/// <inheritdoc /> public override void Initialize(LayoutElementsContainer layout) { _scripts.Clear(); // Area for drag&drop scripts var dragArea = layout.Custom <DragAreaControl>(); dragArea.CustomControl.ScriptsEditor = this; // No support to show scripts for more than one actor selected if (Values.Count != 1) { return; } // Scripts var scripts = (Script[])Values[0]; _scripts.AddRange(scripts); var elementType = typeof(Script); for (int i = 0; i < scripts.Length; i++) { var script = scripts[i]; if (script == null) { layout.Group("Missing script"); continue; } var values = new ListValueContainer(elementType, i, Values); var type = script.GetType(); var editor = CustomEditorsUtil.CreateEditor(type, false); // Create group var title = CustomEditorsUtil.GetPropertyNameUI(type.Name); var group = layout.Group(title); group.Panel.Open(false); // Add settings button to the group const float settingsButtonSize = 14; var settingsButton = new Image(group.Panel.Width - settingsButtonSize, 0, settingsButtonSize, settingsButtonSize) { CanFocus = true, AnchorStyle = AnchorStyle.UpperRight, IsScrollable = false, Color = new Color(0.7f), Margin = new Margin(1), ImageSource = new SpriteImageSource(FlaxEngine.GUI.Style.Current.Settings), Tag = script, Parent = group.Panel }; settingsButton.Clicked += SettingsButtonOnClicked; group.Object(values, editor); } base.Initialize(layout); }
public override void Initialize(LayoutElementsContainer layout) { var window = ((PropertiesProxy)Values[0])._window; if (window == null) { layout.Label("Loading...", TextAlignment.Center); return; } // Audio properties { var audio = window.Asset; AudioClip.AudioDataInfo info; audio.GetInfo(out info); int originalSize, importedSize; Editor.Internal_GetAudioClipMetadata(audio.unmanagedPtr, out originalSize, out importedSize); var group = layout.Group("General"); group.Label("Format: " + audio.Format); group.Label("Length: " + (Mathf.CeilToInt(audio.Length * 100.0f) / 100.0f) + "s"); group.Label(string.Format("{0}kHz, channels: {1}, bit depth: {2}", info.SampleRate / 1000, info.NumChannels, info.BitDepth)); group.Label("Original size: " + Utilities.Utils.FormatBytesCount((ulong)originalSize)); group.Label("Imported size: " + Utilities.Utils.FormatBytesCount((ulong)importedSize)); group.Label("Compression ratio: " + Mathf.CeilToInt((float)importedSize / originalSize * 100.0f) + "%"); } base.Initialize(layout); layout.Space(10); var reimportButton = layout.Button("Reimport"); reimportButton.Button.Clicked += () => ((PropertiesProxy)Values[0]).Reimport(); }
/// <inheritdoc /> public override void Initialize(LayoutElementsContainer layout) { var window = Values[0] as IVisjectSurfaceWindow; var asset = window?.VisjectAsset; if (asset == null || !asset.IsLoaded) { return; } var group = layout.Group("Functions"); var nodes = window.VisjectSurface.Nodes; // List of functions in the graph for (int i = 0; i < nodes.Count; i++) { var node = nodes[i]; if (node is Surface.Archetypes.Function.VisualScriptFunctionNode functionNode && !string.IsNullOrEmpty(functionNode._signature.Name)) { var label = group.ClickableLabel(functionNode._signature.Name ?? string.Empty).CustomControl; label.TextColorHighlighted = Color.FromBgra(0xFFA0A0A0); label.TooltipText = functionNode.TooltipText; label.DoubleClick += () => ((VisualScriptWindow)Values[0]).Surface.FocusNode(functionNode); label.RightClick += () => ShowContextMenu(functionNode, label); }
/// <inheritdoc /> public override void Initialize(LayoutElementsContainer layout) { base.Initialize(layout); _isValid = IsValid; if (!_isValid) { return; } // Show all effect parameters grouped by the emitter track name var effect = (ParticleEffect)Values[0]; var groups = layout.Group("Parameters"); groups.Panel.Open(false); var parameters = effect.Parameters; var parametersGroups = parameters.GroupBy(x => x.EmitterIndex); foreach (var parametersGroup in parametersGroups) { var trackName = parametersGroup.First().TrackName; var group = groups.Group(trackName); group.Panel.Open(false); var data = SurfaceUtils.InitGraphParameters(parametersGroup); SurfaceUtils.DisplayGraphParameters(group, data, (instance, parameter, tag) => ((ParticleEffect)instance).GetParameterValue(trackName, parameter.Name), (instance, value, parameter, tag) => ((ParticleEffect)instance).SetParameterValue(trackName, parameter.Name, value), Values, (instance, parameter, tag) => ((ParticleEffectParameter)tag).DefaultValue); } }
/// <inheritdoc /> public override void Initialize(LayoutElementsContainer layout) { base.Initialize(layout); // Show instanced parameters to view/edit at runtime if (Values.IsSingleObject && Editor.Instance.StateMachine.IsPlayMode) { var group = layout.Group("Parameters"); group.Panel.Open(false); group.Panel.IndexInParent -= 2; var animatedModel = (AnimatedModel)Values[0]; var parameters = animatedModel.Parameters; for (int i = 0; i < parameters.Length; i++) { var param = parameters[i]; if (!param.IsPublic) { continue; } var id = param.Identifier; var value = param.Value; var valueType = Utilities.Utils.GetGraphParameterValueType(param.Type); var valueContainer = new CustomValueContainer( valueType, value, (instance, index) => animatedModel.GetParameterValue(id), (instance, index, o) => animatedModel.SetParameterValue(id, o) ); group.Property(param.Name, valueContainer); } } }
public override void Initialize(LayoutElementsContainer layout) { var window = ((PropertiesProxy)Values[0])._window; if (window == null) { layout.Label("Loading...", TextAlignment.Center); return; } // Texture properties { var texture = window.Asset; var group = layout.Group("General"); group.Label("Format: " + texture.Format); group.Label(string.Format("Size: {0}x{1}", texture.Width, texture.Height)); group.Label("Mip levels: " + texture.MipLevels); group.Label("Memory usage: " + Utilities.Utils.FormatBytesCount(texture.TotalMemoryUsage)); } base.Initialize(layout); layout.Space(10); var reimportButton = layout.Button("Reimport"); reimportButton.Button.Clicked += () => ((PropertiesProxy)Values[0]).Reimport(); }
public override void Initialize(LayoutElementsContainer layout) { var proxy = (BuildTabProxy)Values[0]; _platform = proxy.Selector.Selected; var platformObj = proxy.PerPlatformOptions[_platform]; if (!platformObj.IsSupported) { layout.Label("This platform is not supported on this system.", TextAlignment.Center); } else if (platformObj.IsAvailable) { string name; switch (_platform) { case PlatformType.Windows: name = "Windows"; break; case PlatformType.XboxOne: name = "Xbox One"; break; case PlatformType.UWP: name = "Windows Store"; break; case PlatformType.Linux: name = "Linux"; break; case PlatformType.PS4: name = "PlayStation 4"; break; case PlatformType.XboxScarlett: name = "Xbox Scarlett"; break; case PlatformType.Android: name = "Android"; break; default: name = CustomEditorsUtil.GetPropertyNameUI(_platform.ToString()); break; } var group = layout.Group(name); group.Object(new ReadOnlyValueContainer(platformObj)); _buildButton = layout.Button("Build").Button; _buildButton.Clicked += OnBuildClicked; } else { platformObj.OnNotAvailableLayout(layout); } }
/// <inheritdoc /> public override void Initialize(LayoutElementsContainer layout) { _updateName = true; var group = layout.Group("Entry"); _group = group; base.Initialize(group); }
/// <inheritdoc /> public override void Initialize(LayoutElementsContainer layout) { var proxy = (PropertiesProxy)Values[0]; if (proxy.Asset == null || !proxy.Asset.IsLoaded) { layout.Label("Loading..."); return; } base.Initialize(layout); // General properties { var group = layout.Group("General"); Animation.Info info; proxy.Asset.GetInfo(out info); group.Label("Length: " + info.Length + "s"); group.Label("Frames: " + info.FramesCount); group.Label("Chanels: " + info.ChannelsCount); group.Label("Keyframes: " + info.KeyframesCount); } // Import Settings { var group = layout.Group("Import Settings"); var importSettingsField = typeof(PropertiesProxy).GetField("ImportSettings", BindingFlags.NonPublic | BindingFlags.Instance); var importSettingsValues = new ValueContainer(importSettingsField) { proxy.ImportSettings }; group.Object(importSettingsValues); layout.Space(5); var reimportButton = group.Button("Reimport"); reimportButton.Button.Clicked += () => ((PropertiesProxy)Values[0]).Reimport(); } }
public override void Initialize(LayoutElementsContainer layout) { var window = ((PropertiesProxy)Values[0])._window; var texture = window?.Asset; if (texture == null || !texture.IsLoaded) { layout.Label("Loading...", TextAlignment.Center); return; } // Texture info var general = layout.Group("General"); general.Label("Format: " + texture.Format); general.Label(string.Format("Size: {0}x{1}", texture.Width, texture.Height)); general.Label("Mip levels: " + texture.MipLevels); general.Label("Memory usage: " + Utilities.Utils.FormatBytesCount(texture.TotalMemoryUsage)); // Texture properties var properties = layout.Group("Properties"); var textureGroup = new CustomValueContainer(new ScriptType(typeof(int)), texture.TextureGroup, (instance, index) => texture.TextureGroup, (instance, index, value) => { texture.TextureGroup = (int)value; window.MarkAsEdited(); }); properties.Property("Texture Group", textureGroup, new TextureGroupEditor(), "The texture group used by this texture."); // Import settings base.Initialize(layout); // Reimport layout.Space(10); var reimportButton = layout.Button("Reimport"); reimportButton.Button.Clicked += () => ((PropertiesProxy)Values[0]).Reimport(); }
public override void Initialize(LayoutElementsContainer layout) { var sprites = (SpriteEntry[])Values[0]; if (sprites != null) { var elementType = typeof(SpriteEntry); for (int i = 0; i < sprites.Length; i++) { var group = layout.Group(sprites[i].Name); group.Object(new ListValueContainer(elementType, i, Values)); } } }
public override void Initialize(LayoutElementsContainer layout) { var proxy = (BuildTabProxy)Values[0]; _platform = proxy.Selector.Selected; var platformObj = proxy.PerPlatformOptions[_platform]; var group = layout.Group(CustomEditorsUtil.GetPropertyNameUI(_platform.ToString())); group.Object(new ReadOnlyValueContainer(platformObj)); _buildButton = layout.Button("Build").Button; _buildButton.Clicked += OnBuildClicked; }
/// <inheritdoc /> public override void Initialize(LayoutElementsContainer layout) { base.Initialize(layout); var ragdoll = Values.Count == 1 ? Values[0] as Ragdoll : null; if (ragdoll == null) { return; } var editorGroup = layout.Group("Ragdoll Editor"); editorGroup.Panel.Open(false); // Info var text = $"Total mass: {Utils.RoundTo1DecimalPlace(ragdoll.TotalMass)}kg"; var label = editorGroup.Label(text); label.Label.AutoHeight = true; if (ragdoll.Parent is AnimatedModel animatedModel && animatedModel.SkinnedModel) { // Builder var grid = editorGroup.CustomContainer <UniformGridPanel>(); var gridControl = grid.CustomControl; gridControl.ClipChildren = false; gridControl.Height = Button.DefaultHeight; gridControl.SlotsHorizontally = 3; gridControl.SlotsVertically = 1; grid.Button("Rebuild").Button.ButtonClicked += OnRebuild; grid.Button("Rebuild/Add bone").Button.ButtonClicked += OnRebuildBone; grid.Button("Remove bone").Button.ButtonClicked += OnRemoveBone; } if (Presenter.Owner is Windows.PropertiesWindow || Presenter.Owner is Windows.Assets.PrefabWindow) { // Selection var grid = editorGroup.CustomContainer <UniformGridPanel>(); var gridControl = grid.CustomControl; gridControl.ClipChildren = false; gridControl.Height = Button.DefaultHeight; gridControl.SlotsHorizontally = 3; gridControl.SlotsVertically = 1; grid.Button("Select all joints").Button.Clicked += OnSelectAllJoints; grid.Button("Select all colliders").Button.Clicked += OnSelectAllColliders; grid.Button("Select all bodies").Button.Clicked += OnSelectAllBodies; } }
public override void Initialize(LayoutElementsContainer layout) { var sprites = (SpriteEntry[])Values[0]; if (sprites != null) { var elementType = new ScriptType(typeof(SpriteEntry)); for (int i = 0; i < sprites.Length; i++) { var group = layout.Group(sprites[i].Name); group.Panel.Tag = i; group.Panel.MouseButtonRightClicked += OnGroupPanelMouseButtonRightClicked; group.Object(new ListValueContainer(elementType, i, Values)); } } }
public override void Initialize(LayoutElementsContainer layout) { var proxy = (BuildTabProxy)Values[0]; _platform = proxy.Selector.Selected; var platformObj = proxy.PerPlatformOptions[_platform]; if (platformObj.IsAvailable) { string name; switch (_platform) { case PlatformType.Windows: name = "Windows"; break; case PlatformType.XboxOne: name = "Xbox One"; break; case PlatformType.WindowsStore: name = "Windows Store"; break; case PlatformType.Linux: name = "Linux"; break; default: name = CustomEditorsUtil.GetPropertyNameUI(_platform.ToString()); break; } var group = layout.Group(name); group.Object(new ReadOnlyValueContainer(platformObj)); _buildButton = layout.Button("Build").Button; _buildButton.Clicked += OnBuildClicked; } else { platformObj.OnNotAvailableLayout(layout); } }
/// <inheritdoc /> public override void Initialize(LayoutElementsContainer layout) { var window = Values[0] as IVisjectSurfaceWindow; var asset = window?.VisjectAsset; if (asset == null || !asset.IsLoaded) { return; } var group = layout.Group("Functions"); var nodes = window.VisjectSurface.Nodes; var grid = group.CustomContainer <UniformGridPanel>(); var gridControl = grid.CustomControl; gridControl.ClipChildren = false; gridControl.Height = Button.DefaultHeight; gridControl.SlotsHorizontally = 2; gridControl.SlotsVertically = 1; var addOverride = grid.Button("Add Override"); addOverride.Button.Clicked += OnOverrideMethodClicked; // TODO: Add sender arg to button clicked action? _overrideButton = addOverride.Control; var addFuncction = grid.Button("Add Function"); addFuncction.Button.Clicked += OnAddNewFunctionClicked; // List of functions in the graph for (int i = 0; i < nodes.Count; i++) { var node = nodes[i]; if (node is Surface.Archetypes.Function.VisualScriptFunctionNode functionNode && !string.IsNullOrEmpty(functionNode._signature.Name)) { var label = group.ClickableLabel(functionNode._signature.Name ?? string.Empty).CustomControl; label.TextColorHighlighted = Color.FromBgra(0xFFA0A0A0); label.TooltipText = functionNode.TooltipText; label.DoubleClick += () => ((VisualScriptWindow)Values[0]).Surface.FocusNode(functionNode); label.RightClick += () => ShowContextMenu(functionNode, label); }
/// <inheritdoc /> public override void Initialize(LayoutElementsContainer layout) { base.Initialize(layout); // Show instanced parameters to view/edit at runtime if (Values.IsSingleObject && Editor.Instance.StateMachine.IsPlayMode) { var group = layout.Group("Parameters"); group.Panel.Open(false); group.Panel.IndexInParent -= 2; var animatedModel = (AnimatedModel)Values[0]; var parameters = animatedModel.Parameters; var data = SurfaceUtils.InitGraphParameters(parameters); SurfaceUtils.DisplayGraphParameters(group, data, (instance, parameter, tag) => ((AnimatedModel)instance).GetParameterValue(parameter.Identifier), (instance, value, parameter, tag) => ((AnimatedModel)instance).SetParameterValue(parameter.Identifier, value), Values); } }
private void AddMissingScript(int index, LayoutElementsContainer layout) { var group = layout.Group("Missing script"); // Add settings button to the group const float settingsButtonSize = 14; var settingsButton = new Image(group.Panel.Width - settingsButtonSize, 0, settingsButtonSize, settingsButtonSize) { TooltipText = "Settings", CanFocus = true, AnchorStyle = AnchorStyle.UpperRight, IsScrollable = false, Color = new Color(0.7f), Margin = new Margin(1), ImageSource = new SpriteImageSource(FlaxEngine.GUI.Style.Current.Settings), Tag = index, Parent = group.Panel }; settingsButton.Clicked += MissingSettingsButtonOnClicked; }
private void AddMissingScript(int index, LayoutElementsContainer layout) { var group = layout.Group("Missing script"); // Add settings button to the group const float settingsButtonSize = 14; var settingsButton = new Image { TooltipText = "Settings", AutoFocus = true, AnchorPreset = AnchorPresets.TopRight, Parent = group.Panel, Bounds = new Rectangle(group.Panel.Width - settingsButtonSize, 0, settingsButtonSize, settingsButtonSize), IsScrollable = false, Color = FlaxEngine.GUI.Style.Current.ForegroundGrey, Margin = new Margin(1), Brush = new SpriteBrush(FlaxEngine.GUI.Style.Current.Settings), Tag = index, }; settingsButton.Clicked += MissingSettingsButtonOnClicked; }
public override void Initialize(LayoutElementsContainer layout) { var proxy = (PropertiesProxy)Values[0]; proxy._materialSlotComboBoxes.Clear(); proxy._isolateCheckBoxes.Clear(); proxy._highlightCheckBoxes.Clear(); var meshes = proxy.Asset.Meshes; var nodes = proxy.Asset.Nodes; var bones = proxy.Asset.Bones; // General properties { var group = layout.Group("General"); var minScreenSize = group.FloatValue("Min Screen Size", "The minimum screen size to draw model (the bottom limit). Used to cull small models. Set to 0 to disable this feature."); minScreenSize.FloatValue.MinValue = 0.0f; minScreenSize.FloatValue.MaxValue = 1.0f; minScreenSize.FloatValue.Value = proxy.Asset.MinScreenSize; minScreenSize.FloatValue.ValueChanged += () => { proxy.Asset.MinScreenSize = minScreenSize.FloatValue.Value; proxy.Window.MarkAsEdited(); }; int triangleCount = 0, vertexCount = 0; for (int meshIndex = 0; meshIndex < meshes.Length; meshIndex++) { var mesh = meshes[meshIndex]; triangleCount += mesh.Triangles; vertexCount += mesh.Vertices; } group.Label(string.Format("Triangles: {0:N0} Vertices: {1:N0}", triangleCount, vertexCount)); group.Label("Nodes: " + nodes.Length); group.Label("Bones: " + bones.Length); } // Group per mesh var meshesGroup = layout.Group("Meshes"); meshesGroup.Panel.Close(false); for (int meshIndex = 0; meshIndex < meshes.Length; meshIndex++) { var mesh = meshes[meshIndex]; var group = meshesGroup.Group("Mesh " + meshIndex); group.Label(string.Format("Triangles: {0:N0} Vertices: {1:N0}", mesh.Triangles, mesh.Vertices)); // Material Slot var materialSlot = group.ComboBox("Material Slot", "Material slot used by this mesh during rendering"); materialSlot.ComboBox.Tag = mesh; materialSlot.ComboBox.SelectedIndexChanged += comboBox => proxy.SetMaterialSlot((SkinnedMesh)comboBox.Tag, comboBox.SelectedIndex); proxy._materialSlotComboBoxes.Add(materialSlot.ComboBox); // Isolate var isolate = group.Checkbox("Isolate", "Shows only this mesh (and meshes using the same material slot)"); isolate.CheckBox.Tag = mesh; isolate.CheckBox.StateChanged += (box) => proxy.SetIsolate(box.Checked ? (SkinnedMesh)box.Tag : null); proxy._isolateCheckBoxes.Add(isolate.CheckBox); // Highlight var highlight = group.Checkbox("Highlight", "Highlights this mesh with a tint color (and meshes using the same material slot)"); highlight.CheckBox.Tag = mesh; highlight.CheckBox.StateChanged += (box) => proxy.SetHighlight(box.Checked ? (SkinnedMesh)box.Tag : null); proxy._highlightCheckBoxes.Add(highlight.CheckBox); } // Skeleton Bones { var group = layout.Group("Skeleton Bones"); group.Panel.Close(false); var tree = group.Tree(); for (int i = 0; i < bones.Length; i++) { if (bones[i].ParentIndex == -1) { var node = tree.Node(nodes[bones[i].NodeIndex].Name); BuildSkeletonBonesTree(nodes, bones, node, i); node.TreeNode.ExpandAll(true); } } } // Skeleton Nodes { var group = layout.Group("Skeleton Nodes"); group.Panel.Close(false); var tree = group.Tree(); for (int i = 0; i < nodes.Length; i++) { if (nodes[i].ParentIndex == -1) { var node = tree.Node(nodes[i].Name); BuildSkeletonNodesTree(nodes, node, i); node.TreeNode.ExpandAll(true); } } } // Import Settings { var group = layout.Group("Import Settings"); var importSettingsField = typeof(PropertiesProxy).GetField("ImportSettings", BindingFlags.NonPublic | BindingFlags.Instance); var importSettingsValues = new ValueContainer(importSettingsField) { proxy.ImportSettings }; group.Object(importSettingsValues); layout.Space(5); var reimportButton = group.Button("Reimport"); reimportButton.Button.Clicked += () => ((PropertiesProxy)Values[0]).Reimport(); } // Refresh UI proxy.UpdateMaterialSlotsUI(); }
/// <inheritdoc /> public override void Initialize(LayoutElementsContainer layout) { _visibleIfCaches = null; // Collect items to edit List <ItemInfo> items; if (!HasDifferentTypes) { var value = Values[0]; if (value == null) { // Check if it's an object type that can be created in editor var type = Values.Type; if (type != null && type.GetConstructor(Type.EmptyTypes) != null) { layout = layout.Space(20); const float ButtonSize = 14.0f; var button = new Button { Text = "+", TooltipText = "Create a new instance of the object", Height = ButtonSize, Width = ButtonSize, X = layout.ContainerControl.Width - ButtonSize - 4, AnchorStyle = AnchorStyle.CenterRight, Parent = layout.ContainerControl }; button.Clicked += () => { var newType = Values.Type; SetValue(Activator.CreateInstance(newType)); RebuildLayoutOnRefresh(); }; } layout.Label("<null>"); return; } items = GetItemsForType(value.GetType()); } else { var types = ValuesTypes; items = new List <ItemInfo>(GetItemsForType(types[0])); for (int i = 1; i < types.Length && items.Count > 0; i++) { var otherItems = GetItemsForType(types[i]); // Merge items for (int j = 0; j < items.Count && items.Count > 0; j++) { bool isInvalid = true; for (int k = 0; k < otherItems.Count; k++) { var a = items[j]; var b = otherItems[k]; if (ItemInfo.CanMerge(a, b)) { isInvalid = false; break; } } if (isInvalid) { items.RemoveAt(j--); } } } } // Sort items items.Sort(); // Add items GroupElement lastGroup = null; for (int i = 0; i < items.Count; i++) { var item = items[i]; // Check if use group LayoutElementsContainer itemLayout; if (item.UseGroup) { if (lastGroup == null || lastGroup.Panel.HeaderText != item.Display.Group) { lastGroup = layout.Group(item.Display.Group); } itemLayout = lastGroup; } else { lastGroup = null; itemLayout = layout; } // Space if (item.Space != null) { itemLayout.Space(item.Space.Height); } // Header if (item.Header != null) { itemLayout.Header(item.Header.Text); } // Peek values ValueContainer itemValues; try { itemValues = item.GetValues(Values); } catch (Exception ex) { Editor.LogWarning("Failed to get object values for item " + item); Editor.LogWarning(ex.Message); Editor.LogWarning(ex.StackTrace); return; } // Spawn property editor SpawnProperty(itemLayout, itemValues, item); // Expand all parent groups if need to if (item.ExpandGroups) { var c = itemLayout.ContainerControl; do { if (c is DropPanel dropPanel) { dropPanel.Open(false); } else if (c is CustomEditorPresenter.PresenterPanel) { break; } c = c.Parent; } while (c != null); } } }
public override void Initialize(LayoutElementsContainer layout) { var proxy = (PropertiesProxy)Values[0]; proxy._materialSlotComboBoxes.Clear(); proxy._isolateCheckBoxes.Clear(); proxy._highlightCheckBoxes.Clear(); var lods = proxy.Asset.LODs; // General properties { var group = layout.Group("General"); var minScreenSize = group.FloatValue("Min Screen Size", "The minimum screen size to draw model (the bottom limit). Used to cull small models. Set to 0 to disable this feature."); minScreenSize.FloatValue.MinValue = 0.0f; minScreenSize.FloatValue.MaxValue = 1.0f; minScreenSize.FloatValue.Value = proxy.Asset.MinScreenSize; minScreenSize.FloatValue.ValueChanged += () => { proxy.Asset.MinScreenSize = minScreenSize.FloatValue.Value; proxy.Window.MarkAsEdited(); }; } // Group per LOD for (int lodIndex = 0; lodIndex < lods.Length; lodIndex++) { var lod = lods[lodIndex]; int triangleCount = 0, vertexCount = 0; for (int meshIndex = 0; meshIndex < lod.Meshes.Length; meshIndex++) { var mesh = lod.Meshes[meshIndex]; triangleCount += mesh.Triangles; vertexCount += mesh.Vertices; } var group = layout.Group("LOD " + lodIndex); group.Label(string.Format("Triangles: {0:N0} Vertices: {1:N0}", triangleCount, vertexCount)); group.Label("Size: " + lod.Bounds.Size); var screenSize = group.FloatValue("Screen Size", "The screen size to switch LODs. Bottom limit of the model screen size to render this LOD."); screenSize.FloatValue.MinValue = 0.0f; screenSize.FloatValue.MaxValue = 10.0f; screenSize.FloatValue.Value = lod.ScreenSize; screenSize.FloatValue.ValueChanged += () => { lod.ScreenSize = screenSize.FloatValue.Value; proxy.Window.MarkAsEdited(); }; // Every mesh properties for (int meshIndex = 0; meshIndex < lod.Meshes.Length; meshIndex++) { var mesh = lod.Meshes[meshIndex]; group.Label("Mesh " + meshIndex); // Material Slot var materialSlot = group.ComboBox("Material Slot", "Material slot used by this mesh during rendering"); materialSlot.ComboBox.Tag = mesh; materialSlot.ComboBox.SelectedIndexChanged += comboBox => proxy.SetMaterialSlot((Mesh)comboBox.Tag, comboBox.SelectedIndex); proxy._materialSlotComboBoxes.Add(materialSlot.ComboBox); // Isolate var isolate = group.Checkbox("Isolate", "Shows only this mesh (and meshes using the same material slot)"); isolate.CheckBox.Tag = mesh; isolate.CheckBox.StateChanged += (box) => proxy.SetIsolate(box.Checked ? (Mesh)box.Tag : null); proxy._isolateCheckBoxes.Add(isolate.CheckBox); // Highlight var highlight = group.Checkbox("Highlight", "Highlights this mesh with a tint color (and meshes using the same material slot)"); highlight.CheckBox.Tag = mesh; highlight.CheckBox.StateChanged += (box) => proxy.SetHighlight(box.Checked ? (Mesh)box.Tag : null); proxy._highlightCheckBoxes.Add(highlight.CheckBox); } } // Import Settings { var group = layout.Group("Import Settings"); var importSettingsField = typeof(PropertiesProxy).GetField("ImportSettings", BindingFlags.NonPublic | BindingFlags.Instance); var importSettingsValues = new ValueContainer(importSettingsField) { proxy.ImportSettings }; group.Object(importSettingsValues); layout.Space(5); var reimportButton = group.Button("Reimport"); reimportButton.Button.Clicked += () => ((PropertiesProxy)Values[0]).Reimport(); } // Refresh UI proxy.UpdateMaterialSlotsUI(); }
/// <inheritdoc /> public override void Initialize(LayoutElementsContainer layout) { var window = Values[0] as IVisjectSurfaceWindow; var asset = window?.VisjectAsset; if (asset == null) { layout.Label("No parameters"); return; } if (asset.LastLoadFailed) { layout.Label("Failed to load asset"); return; } if (!asset.IsLoaded) { layout.Label("Loading..."); return; } var parameters = window.VisjectSurface.Parameters; GroupElement lastGroup = null; for (int i = 0; i < parameters.Count; i++) { var p = parameters[i]; if (!p.IsPublic) { continue; } var pIndex = i; var pValue = p.Value; var attributes = p.Meta.GetAttributes(); if (attributes == null || attributes.Length == 0) { attributes = DefaultAttributes; } var itemLayout = layout; var name = p.Name; // Editor Display var editorDisplay = (EditorDisplayAttribute)attributes.FirstOrDefault(x => x is EditorDisplayAttribute); if (editorDisplay?.Group != null) { if (lastGroup == null || lastGroup.Panel.HeaderText != editorDisplay.Group) { lastGroup = layout.Group(editorDisplay.Group); lastGroup.Panel.Open(false); } itemLayout = lastGroup; } else { lastGroup = null; itemLayout = layout; } if (editorDisplay?.Name != null) { name = editorDisplay.Name; } // Space var space = (SpaceAttribute)attributes.FirstOrDefault(x => x is SpaceAttribute); if (space != null) { itemLayout.Space(space.Height); } // Header var header = (HeaderAttribute)attributes.FirstOrDefault(x => x is HeaderAttribute); if (header != null) { itemLayout.Header(header.Text); } var propertyValue = new CustomValueContainer ( p.Type, pValue, (instance, index) => ((IVisjectSurfaceWindow)instance).GetParameter(pIndex), (instance, index, value) => ((IVisjectSurfaceWindow)instance).SetParameter(pIndex, value), attributes ); var propertyLabel = new DraggablePropertyNameLabel(name) { Tag = pIndex, Drag = OnDragParameter }; var tooltip = (TooltipAttribute)attributes.FirstOrDefault(x => x is TooltipAttribute); propertyLabel.MouseLeftDoubleClick += (label, location) => StartParameterRenaming(pIndex, label); propertyLabel.SetupContextMenu += OnPropertyLabelSetupContextMenu; var property = itemLayout.AddPropertyItem(propertyLabel, tooltip?.Text); property.Object(propertyValue); } // Parameters creating var newParameterTypes = window.NewParameterTypes; if (newParameterTypes != null) { layout.Space(parameters.Count > 0 ? 10 : 4); var newParam = layout.Button("Add parameter..."); newParam.Button.ButtonClicked += OnAddParameterButtonClicked; layout.Space(10); } }
/// <inheritdoc /> public override void Initialize(LayoutElementsContainer layout) { _scripts.Clear(); // Area for drag&drop scripts var dragArea = layout.CustomContainer <DragAreaControl>(); dragArea.CustomControl.ScriptsEditor = this; // No support to show scripts for more than one actor selected // TODO: support showing scripts from objects that has the same scripts layout if (Values.Count != 1) { return; } // Scripts arrange bar var dragBar = layout.Custom <ScriptArrangeBar>(); dragBar.CustomControl.Init(0, this); // Scripts var scripts = (Script[])Values[0]; _scripts.AddRange(scripts); var elementType = typeof(Script); for (int i = 0; i < scripts.Length; i++) { var script = scripts[i]; if (script == null) { AddMissingScript(i, layout); continue; } var values = new ListValueContainer(elementType, i, Values); var type = script.GetType(); var editor = CustomEditorsUtil.CreateEditor(type, false); // Create group var title = CustomEditorsUtil.GetPropertyNameUI(type.Name); var group = layout.Group(title); group.Panel.Open(false); // Customize var typeAttributes = type.GetCustomAttributes(true); var tooltip = (TooltipAttribute)typeAttributes.FirstOrDefault(x => x is TooltipAttribute); if (tooltip != null) { group.Panel.TooltipText = tooltip.Text; } // Add toggle button to the group var scriptToggle = new CheckBox(2, 0, script.Enabled) { TooltipText = "If checked, script will be enabled", IsScrollable = false, Size = new Vector2(14, 14), BoxSize = 12.0f, Tag = script, Parent = group.Panel }; scriptToggle.StateChanged += ScriptToggleOnCheckChanged; // Add drag button to the group const float dragIconSize = 14; var scriptDrag = new ScriptDragIcon(this, script, scriptToggle.Right, 0.5f, dragIconSize) { TooltipText = "Script reference", CanFocus = true, IsScrollable = false, Color = new Color(0.7f), Margin = new Margin(1), ImageSource = new SpriteImageSource(Editor.Instance.UI.DragBar12), Tag = script, Parent = group.Panel }; // Add settings button to the group const float settingsButtonSize = 14; var settingsButton = new Image(group.Panel.Width - settingsButtonSize, 0, settingsButtonSize, settingsButtonSize) { TooltipText = "Settings", CanFocus = true, AnchorStyle = AnchorStyle.UpperRight, IsScrollable = false, Color = new Color(0.7f), Margin = new Margin(1), ImageSource = new SpriteImageSource(FlaxEngine.GUI.Style.Current.Settings), Tag = script, Parent = group.Panel }; settingsButton.Clicked += SettingsButtonOnClicked; group.Panel.HeaderTextMargin = new Margin(scriptDrag.Right, 15, 2, 2); group.Object(values, editor); // Scripts arrange bar dragBar = layout.Custom <ScriptArrangeBar>(); dragBar.CustomControl.Init(i + 1, this); } base.Initialize(layout); }
internal static void DisplayGraphParameters(LayoutElementsContainer layout, GraphParameterData[] data, GetGraphParameterDelegate getter, SetGraphParameterDelegate setter, ValueContainer values, GetGraphParameterDelegate defaultValueGetter = null, CustomPropertySpawnDelegate propertySpawn = null) { GroupElement lastGroup = null; for (int i = 0; i < data.Length; i++) { ref var e = ref data[i]; if (!e.IsPublic) { continue; } var tag = e.Tag; var parameter = e.Parameter; LayoutElementsContainer itemLayout; // Editor Display if (e.Display?.Group != null) { if (lastGroup == null || lastGroup.Panel.HeaderText != e.Display.Group) { lastGroup = layout.Group(e.Display.Group); lastGroup.Panel.Open(false); } itemLayout = lastGroup; } else { lastGroup = null; itemLayout = layout; } // Space if (e.Space != null) { itemLayout.Space(e.Space.Height); } // Header if (e.Header != null) { itemLayout.Header(e.Header); } // Values container var valueType = new ScriptType(e.Type); var valueContainer = new CustomValueContainer(valueType, (instance, index) => getter(values[index], parameter, tag), (instance, index, value) => setter(values[index], value, parameter, tag), e.Attributes); for (int j = 0; j < values.Count; j++) { valueContainer.Add(getter(values[j], parameter, tag)); } // Default value if (defaultValueGetter != null) { valueContainer.SetDefaultValue(defaultValueGetter(values[0], parameter, tag)); } // Prefab value if (values.HasReferenceValue) { var referenceValue = getter(values.ReferenceValue, parameter, tag); if (referenceValue != null) { valueContainer.SetReferenceValue(referenceValue); } } if (propertySpawn == null) { itemLayout.Property(e.DisplayName, valueContainer, null, e.Tooltip?.Text); } else { propertySpawn(itemLayout, valueContainer, ref e); } }
/// <inheritdoc /> public override void Initialize(LayoutElementsContainer layout) { // Get the target options _options = Options; if (_options == null) { throw new ArgumentNullException(); } int selectedIndex = -1; bool hasDifferentTypes = Values.HasDifferentTypes; var type = Type; _type = type; // Type var typeEditor = layout.ComboBox(TypeComboBoxName, "Type of the object value. Use it to change the object."); for (int i = 0; i < _options.Length; i++) { typeEditor.ComboBox.AddItem(_options[i].Name); selectedIndex = _options[i].Type == type.Type ? i : selectedIndex; } typeEditor.ComboBox.SupportMultiSelect = false; typeEditor.ComboBox.SelectedIndex = hasDifferentTypes ? -1 : selectedIndex; typeEditor.ComboBox.SelectedIndexChanged += OnSelectedIndexChanged; // Editing different types is not supported if (Values.HasDifferentTypes) { var property = layout.AddPropertyItem("Value"); property.Label("Different Values"); return; } // Nothing to edit if (Values.HasNull) { var property = layout.AddPropertyItem("Value"); property.Label("<null>"); return; } // Value var values = new CustomValueContainer(type, (instance, index) => instance, (instance, index, value) => { }); values.AddRange(Values); var editor = CustomEditorsUtil.CreateEditor(type); var style = editor.Style; if (style == DisplayStyle.InlineIntoParent) { layout.Object(values, editor); } else if (style == DisplayStyle.Group) { var group = layout.Group("Value", true); group.Panel.Open(false); group.Object(values, editor); // Remove empty group if (group.ContainerControl.ChildrenCount == 0) { layout.Children.Remove(group); group.Panel.Dispose(); } } else { layout.AddPropertyItem("Value").Object(values, editor); } }
public override void Initialize(LayoutElementsContainer layout) { var proxy = (SkeletonPropertiesProxy)Values[0]; if (proxy.Asset == null || !proxy.Asset.IsLoaded) { layout.Label("Loading..."); return; } var lods = proxy.Asset.LODs; var loadedLODs = proxy.Asset.LoadedLODs; var nodes = proxy.Asset.Nodes; var bones = proxy.Asset.Bones; // Skeleton Bones { var group = layout.Group("Skeleton Bones"); var tree = group.Tree(); for (int i = 0; i < bones.Length; i++) { if (bones[i].ParentIndex == -1) { var node = tree.Node(nodes[bones[i].NodeIndex].Name); BuildSkeletonBonesTree(nodes, bones, node, i); node.TreeNode.ExpandAll(true); } } } // Skeleton Nodes { var group = layout.Group("Skeleton Nodes"); var tree = group.Tree(); for (int i = 0; i < nodes.Length; i++) { if (nodes[i].ParentIndex == -1) { var node = tree.Node(nodes[i].Name); BuildSkeletonNodesTree(nodes, node, i); node.TreeNode.ExpandAll(true); } } } // Blend Shapes var blendShapes = proxy.Asset.BlendShapes; if (blendShapes.Length != 0) { var group = layout.Group("Blend Shapes"); proxy.Window._preview.PreviewActor.ClearBlendShapeWeights(); for (int i = 0; i < blendShapes.Length; i++) { var blendShape = blendShapes[i]; var label = new PropertyNameLabel(blendShape); label.SetupContextMenu += (nameLabel, menu, linkedEditor) => { menu.AddButton("Copy name", () => Clipboard.Text = blendShape); }; var property = group.AddPropertyItem(label); var editor = property.FloatValue(); editor.FloatValue.Value = 0.0f; editor.FloatValue.MinValue = -1; editor.FloatValue.MaxValue = 1; editor.FloatValue.SlideSpeed = 0.01f; editor.FloatValue.ValueChanged += () => { proxy.Window._preview.PreviewActor.SetBlendShapeWeight(blendShape, editor.FloatValue.Value); }; } } }
public override void Initialize(LayoutElementsContainer layout) { var proxy = (MeshesPropertiesProxy)Values[0]; if (proxy.Asset == null || !proxy.Asset.IsLoaded) { layout.Label("Loading..."); return; } proxy._materialSlotComboBoxes.Clear(); proxy._isolateCheckBoxes.Clear(); proxy._highlightCheckBoxes.Clear(); var lods = proxy.Asset.LODs; var loadedLODs = proxy.Asset.LoadedLODs; var nodes = proxy.Asset.Nodes; var bones = proxy.Asset.Bones; // General properties { var group = layout.Group("General"); var minScreenSize = group.FloatValue("Min Screen Size", "The minimum screen size to draw model (the bottom limit). Used to cull small models. Set to 0 to disable this feature."); minScreenSize.FloatValue.MinValue = 0.0f; minScreenSize.FloatValue.MaxValue = 1.0f; minScreenSize.FloatValue.Value = proxy.Asset.MinScreenSize; minScreenSize.FloatValue.ValueChanged += () => { proxy.Asset.MinScreenSize = minScreenSize.FloatValue.Value; proxy.Window.MarkAsEdited(); }; } // Group per LOD for (int lodIndex = 0; lodIndex < lods.Length; lodIndex++) { var group = layout.Group("LOD " + lodIndex); if (lodIndex < lods.Length - loadedLODs) { group.Label("Loading LOD..."); continue; } var lod = lods[lodIndex]; var meshes = lod.Meshes; int triangleCount = 0, vertexCount = 0; for (int meshIndex = 0; meshIndex < meshes.Length; meshIndex++) { var mesh = meshes[meshIndex]; triangleCount += mesh.TriangleCount; vertexCount += mesh.VertexCount; } group.Label(string.Format("Triangles: {0:N0} Vertices: {1:N0}", triangleCount, vertexCount)); group.Label("Size: " + lod.Box.Size); var screenSize = group.FloatValue("Screen Size", "The screen size to switch LODs. Bottom limit of the model screen size to render this LOD."); screenSize.FloatValue.MinValue = 0.0f; screenSize.FloatValue.MaxValue = 10.0f; screenSize.FloatValue.Value = lod.ScreenSize; screenSize.FloatValue.ValueChanged += () => { lod.ScreenSize = screenSize.FloatValue.Value; proxy.Window.MarkAsEdited(); }; // Every mesh properties for (int meshIndex = 0; meshIndex < meshes.Length; meshIndex++) { var mesh = meshes[meshIndex]; group.Label($"Mesh {meshIndex} (tris: {mesh.TriangleCount:N0}, verts: {mesh.VertexCount:N0})"); // Material Slot var materialSlot = group.ComboBox("Material Slot", "Material slot used by this mesh during rendering"); materialSlot.ComboBox.Tag = mesh; materialSlot.ComboBox.SelectedIndexChanged += comboBox => proxy.SetMaterialSlot((SkinnedMesh)comboBox.Tag, comboBox.SelectedIndex); proxy._materialSlotComboBoxes.Add(materialSlot.ComboBox); // Isolate var isolate = group.Checkbox("Isolate", "Shows only this mesh (and meshes using the same material slot)"); isolate.CheckBox.Tag = mesh; isolate.CheckBox.StateChanged += (box) => proxy.SetIsolate(box.Checked ? (SkinnedMesh)box.Tag : null); proxy._isolateCheckBoxes.Add(isolate.CheckBox); // Highlight var highlight = group.Checkbox("Highlight", "Highlights this mesh with a tint color (and meshes using the same material slot)"); highlight.CheckBox.Tag = mesh; highlight.CheckBox.StateChanged += (box) => proxy.SetHighlight(box.Checked ? (SkinnedMesh)box.Tag : null); proxy._highlightCheckBoxes.Add(highlight.CheckBox); } } // Refresh UI proxy.UpdateMaterialSlotsUI(); }
/// <inheritdoc /> public override void Initialize(LayoutElementsContainer layout) { // Area for drag&drop scripts var dragArea = layout.CustomContainer <DragAreaControl>(); dragArea.CustomControl.ScriptsEditor = this; // No support for showing scripts from multiple actors that have different set of scripts var scripts = (Script[])Values[0]; _scripts.Clear(); _scripts.AddRange(scripts); for (int i = 1; i < Values.Count; i++) { var e = (Script[])Values[i]; if (scripts.Length != e.Length) { return; } for (int j = 0; j < e.Length; j++) { var t1 = scripts[j]?.TypeName; var t2 = e[j]?.TypeName; if (t1 != t2) { return; } } } // Scripts arrange bar var dragBar = layout.Custom <ScriptArrangeBar>(); dragBar.CustomControl.Init(0, this); // Scripts var elementType = new ScriptType(typeof(Script)); _scriptToggles = new CheckBox[scripts.Length]; for (int i = 0; i < scripts.Length; i++) { var script = scripts[i]; if (script == null) { AddMissingScript(i, layout); continue; } var values = new ScriptsContainer(elementType, i, Values); var scriptType = TypeUtils.GetObjectType(script); var editor = CustomEditorsUtil.CreateEditor(scriptType, false); // Create group var title = Utilities.Utils.GetPropertyNameUI(scriptType.Name); var group = layout.Group(title, editor); if ((Presenter.Features & FeatureFlags.CacheExpandedGroups) != 0) { if (Editor.Instance.ProjectCache.IsCollapsedGroup(title)) { group.Panel.Close(false); } else { group.Panel.Open(false); } group.Panel.IsClosedChanged += panel => Editor.Instance.ProjectCache.SetCollapsedGroup(panel.HeaderText, panel.IsClosed); } else { group.Panel.Open(false); } // Customize group.Panel.TooltipText = Editor.Instance.CodeDocs.GetTooltip(scriptType); if (script.HasPrefabLink) { group.Panel.HeaderTextColor = FlaxEngine.GUI.Style.Current.ProgressNormal; } // Add toggle button to the group var scriptToggle = new CheckBox { TooltipText = "If checked, script will be enabled.", IsScrollable = false, Checked = script.Enabled, Parent = group.Panel, Size = new Float2(14, 14), Bounds = new Rectangle(2, 0, 14, 14), BoxSize = 12.0f, Tag = script, }; scriptToggle.StateChanged += OnScriptToggleCheckChanged; _scriptToggles[i] = scriptToggle; // Add drag button to the group const float dragIconSize = 14; var scriptDrag = new ScriptDragIcon(this, script) { TooltipText = "Script reference", AutoFocus = true, IsScrollable = false, Color = FlaxEngine.GUI.Style.Current.ForegroundGrey, Parent = group.Panel, Bounds = new Rectangle(scriptToggle.Right, 0.5f, dragIconSize, dragIconSize), Margin = new Margin(1), Brush = new SpriteBrush(Editor.Instance.Icons.DragBar12), Tag = script, }; // Add settings button to the group const float settingsButtonSize = 14; var settingsButton = new Image { TooltipText = "Settings", AutoFocus = true, AnchorPreset = AnchorPresets.TopRight, Parent = group.Panel, Bounds = new Rectangle(group.Panel.Width - settingsButtonSize, 0, settingsButtonSize, settingsButtonSize), IsScrollable = false, Color = FlaxEngine.GUI.Style.Current.ForegroundGrey, Margin = new Margin(1), Brush = new SpriteBrush(FlaxEngine.GUI.Style.Current.Settings), Tag = script, }; settingsButton.Clicked += OnSettingsButtonClicked; group.Panel.HeaderTextMargin = new Margin(scriptDrag.Right, 15, 2, 2); group.Object(values, editor); // Scripts arrange bar dragBar = layout.Custom <ScriptArrangeBar>(); dragBar.CustomControl.Init(i + 1, this); } base.Initialize(layout); }
/// <inheritdoc /> public override void Initialize(LayoutElementsContainer layout) { Profiler.BeginEvent("LocalizationSettingsEditor.Initialize"); var settings = (LocalizationSettings)Values[0]; var tablesLength = settings.LocalizedStringTables?.Length ?? 0; var tables = new List <LocalizedStringTable>(tablesLength); for (int i = 0; i < tablesLength; i++) { var table = settings.LocalizedStringTables[i]; if (table && !table.WaitForLoaded()) { tables.Add(table); } } var locales = tables.GroupBy(x => x.Locale); var tableEntries = new Dictionary <LocalizedStringTable, Dictionary <string, string[]> >(); var allKeys = new HashSet <string>(); foreach (var e in locales) { foreach (var table in e) { var entries = table.Entries; tableEntries[table] = entries; allKeys.AddRange(entries.Keys); } } { var group = layout.Group("Preview"); // Current language and culture preview management group.Object("Current Language", new CustomValueContainer(new ScriptType(typeof(CultureInfo)), Localization.CurrentLanguage, (instance, index) => Localization.CurrentLanguage, (instance, index, value) => Localization.CurrentLanguage = value as CultureInfo), null, "Current UI display language for the game preview."); group.Object("Current Culture", new CustomValueContainer(new ScriptType(typeof(CultureInfo)), Localization.CurrentCulture, (instance, index) => Localization.CurrentCulture, (instance, index, value) => Localization.CurrentCulture = value as CultureInfo), null, "Current values formatting culture for the game preview."); } { var group = layout.Group("Locales"); // Show all existing locales _theMostTranslatedCulture = null; _theMostTranslatedCultureCount = -1; foreach (var e in locales) { var culture = new CultureInfo(e.Key); var prop = group.AddPropertyItem(CultureInfoEditor.GetName(culture), culture.NativeName); int count = e.Sum(x => tableEntries[x].Count); int validCount = e.Sum(x => tableEntries[x].Values.Count(y => y != null && y.Length != 0 && !string.IsNullOrEmpty(y[0]))); if (count > _theMostTranslatedCultureCount) { _theMostTranslatedCulture = culture; _theMostTranslatedCultureCount = count; } prop.Label(string.Format("Progress: {0}% ({1}/{2})", allKeys.Count > 0 ? (int)(((float)validCount / allKeys.Count * 100.0f)) : 0, validCount, allKeys.Count)); prop.Label("Tables:"); foreach (var table in e) { var namePath = table.Path; if (namePath.StartsWith(Globals.ProjectFolder)) { namePath = namePath.Substring(Globals.ProjectFolder.Length + 1); } var tableLabel = prop.ClickableLabel(namePath).CustomControl; tableLabel.TextColorHighlighted = Color.Wheat; tableLabel.DoubleClick += delegate { Editor.Instance.Windows.ContentWin.Select(table); }; } group.Space(10); } // Update add button var update = group.Button("Update").Button; update.TooltipText = "Refreshes the dashboard statistics"; update.Height = 16.0f; update.Clicked += RebuildLayout; // New locale add button var addLocale = group.Button("Add Locale...").Button; addLocale.TooltipText = "Shows a locale picker and creates new localization for it with not translated string tables"; addLocale.Height = 16.0f; addLocale.ButtonClicked += delegate(Button button) { var menu = CultureInfoEditor.CreatePicker(null, culture => { var displayName = CultureInfoEditor.GetName(culture); if (locales.Any(x => x.Key == culture.Name)) { MessageBox.Show($"Culture '{displayName}' is already added."); return; } Profiler.BeginEvent("LocalizationSettingsEditor.AddLocale"); Editor.Log($"Adding culture '{displayName}' to localization settings"); var newTables = settings.LocalizedStringTables?.ToList() ?? new List <LocalizedStringTable>(); if (_theMostTranslatedCulture != null) { // Duplicate localization for culture with the highest amount of keys var g = locales.First(x => x.Key == _theMostTranslatedCulture.Name); foreach (var e in g) { var path = e.Path; var filename = Path.GetFileNameWithoutExtension(path); if (filename.EndsWith(_theMostTranslatedCulture.Name)) { filename = filename.Substring(0, filename.Length - _theMostTranslatedCulture.Name.Length); } path = Path.Combine(Path.GetDirectoryName(path), filename + culture.Name + ".json"); var table = FlaxEngine.Content.CreateVirtualAsset <LocalizedStringTable>(); table.Locale = culture.Name; var entries = new Dictionary <string, string[]>(); foreach (var ee in tableEntries[e]) { var vv = (string[])ee.Value.Clone(); for (var i = 0; i < vv.Length; i++) { vv[i] = string.Empty; } entries.Add(ee.Key, vv); } table.Entries = entries; if (!table.Save(path)) { Object.Destroy(table); newTables.Add(FlaxEngine.Content.LoadAsync <LocalizedStringTable>(path)); } } } else { // No localization so initialize with empty table var path = Path.Combine(Path.Combine(Path.GetDirectoryName(GameSettings.Load().Localization.Path), "Localization", culture.Name + ".json")); var table = FlaxEngine.Content.CreateVirtualAsset <LocalizedStringTable>(); table.Locale = culture.Name; if (!table.Save(path)) { Object.Destroy(table); newTables.Add(FlaxEngine.Content.LoadAsync <LocalizedStringTable>(path)); } } settings.LocalizedStringTables = newTables.ToArray(); Presenter.OnModified(); RebuildLayout(); Profiler.EndEvent(); }); menu.Show(button, new Vector2(0, button.Height)); }; // Export button var exportLocalization = group.Button("Export...").Button; exportLocalization.TooltipText = "Exports the localization strings into .pot file for translation"; exportLocalization.Height = 16.0f; exportLocalization.Clicked += () => Export(tableEntries, allKeys); // Find localized strings in code button var findStringsCode = group.Button("Find localized strings in code").Button; findStringsCode.TooltipText = "Searches for localized string usage in inside a project source files"; findStringsCode.Height = 16.0f; findStringsCode.Clicked += delegate { var newKeys = new Dictionary <string, string>(); Profiler.BeginEvent("LocalizationSettingsEditor.FindLocalizedStringsInSource"); // C# var files = Directory.GetFiles(Globals.ProjectSourceFolder, "*.cs", SearchOption.AllDirectories); var filesCount = files.Length; foreach (var file in files) { FindNewKeysCSharp(file, newKeys, allKeys); } // C++ files = Directory.GetFiles(Globals.ProjectSourceFolder, "*.cpp", SearchOption.AllDirectories); filesCount += files.Length; foreach (var file in files) { FindNewKeysCpp(file, newKeys, allKeys); } files = Directory.GetFiles(Globals.ProjectSourceFolder, "*.h", SearchOption.AllDirectories); filesCount += files.Length; foreach (var file in files) { FindNewKeysCpp(file, newKeys, allKeys); } AddNewKeys(newKeys, filesCount, locales, tableEntries); Profiler.EndEvent(); }; // Find localized strings in content button var findStringsContent = group.Button("Find localized strings in content").Button; findStringsContent.TooltipText = "Searches for localized string usage in inside a project content files (scenes, prefabs)"; findStringsContent.Height = 16.0f; findStringsContent.Clicked += delegate { var newKeys = new Dictionary <string, string>(); Profiler.BeginEvent("LocalizationSettingsEditor.FindLocalizedStringsInContent"); // Scenes var files = Directory.GetFiles(Globals.ProjectContentFolder, "*.scene", SearchOption.AllDirectories); var filesCount = files.Length; foreach (var file in files) { FindNewKeysJson(file, newKeys, allKeys); } // Prefabs files = Directory.GetFiles(Globals.ProjectContentFolder, "*.prefab", SearchOption.AllDirectories); filesCount += files.Length; foreach (var file in files) { FindNewKeysJson(file, newKeys, allKeys); } AddNewKeys(newKeys, filesCount, locales, tableEntries); Profiler.EndEvent(); }; } { // Raw asset data editing var group = layout.Group("Data"); base.Initialize(group); } Profiler.EndEvent(); }