diff --git a/VisualPinball.Unity/Assets/Presets/Asset Thumbcam/Mid Distance (less).preset b/VisualPinball.Unity/Assets/Presets/Asset Thumbcam/Mid Distance (less).preset new file mode 100644 index 000000000..a8ec4424c --- /dev/null +++ b/VisualPinball.Unity/Assets/Presets/Asset Thumbcam/Mid Distance (less).preset @@ -0,0 +1,76 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!181963792 &2655988077585873504 +Preset: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Mid Distance (less) + m_TargetType: + m_NativeTypeID: 4 + m_ManagedTypePPtr: {fileID: 0} + m_ManagedTypeFallback: + m_Properties: + - target: {fileID: 0} + propertyPath: m_LocalRotation.x + value: 0.27781588 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_LocalRotation.y + value: 0.36497167 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_LocalRotation.z + value: -0.1150751 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_LocalRotation.w + value: 0.8811196 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_LocalPosition.x + value: -0.0819 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_LocalPosition.y + value: 0.1051 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_LocalPosition.z + value: -0.0819 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_LocalScale.x + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_LocalScale.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_LocalScale.z + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_ConstrainProportionsScale + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_LocalEulerAnglesHint.x + value: 35 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_LocalEulerAnglesHint.y + value: 45 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + m_ExcludedProperties: [] + m_CoupledType: + m_NativeTypeID: 0 + m_ManagedTypePPtr: {fileID: 0} + m_ManagedTypeFallback: + m_CoupledProperties: [] diff --git a/VisualPinball.Unity/Assets/Presets/Asset Thumbcam/Mid Distance (less).preset.meta b/VisualPinball.Unity/Assets/Presets/Asset Thumbcam/Mid Distance (less).preset.meta new file mode 100644 index 000000000..15a921cd0 --- /dev/null +++ b/VisualPinball.Unity/Assets/Presets/Asset Thumbcam/Mid Distance (less).preset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b0032d5f974510d47a3825e7cf7b4ed7 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2655988077585873504 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/Assets/Resources/Materials/Dot Matrix Display (SRP).mat b/VisualPinball.Unity/Assets/Resources/Materials/Dot Matrix Display (SRP).mat index efb2476c7..cb87fca25 100644 --- a/VisualPinball.Unity/Assets/Resources/Materials/Dot Matrix Display (SRP).mat +++ b/VisualPinball.Unity/Assets/Resources/Materials/Dot Matrix Display (SRP).mat @@ -24,8 +24,7 @@ Material: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_Name: Dot Matrix Display (SRP) - m_Shader: {fileID: -6465566751694194690, guid: 3dfbd2115636a284d89d71fdefd9b4d2, - type: 3} + m_Shader: {fileID: -6465566751694194690, guid: 3dfbd2115636a284d89d71fdefd9b4d2, type: 3} m_Parent: {fileID: 0} m_ModifiedSerializedProperties: 0 m_ValidKeywords: @@ -197,6 +196,7 @@ Material: - _DoubleSidedGIMode: 0 - _DoubleSidedNormalMode: 1 - _DstBlend: 0 + - _DstBlend2: 0 - _EmissiveColorMode: 1 - _EmissiveExposureWeight: 1 - _EmissiveIntensity: 1 @@ -205,6 +205,7 @@ Material: - _EnableFogOnTransparent: 1 - _EnableGeometricSpecularAA: 0 - _EnergyConservingSpecularColor: 1 + - _ExcludeFromTUAndAA: 0 - _HeightAmplitude: 0.02 - _HeightCenter: 0.5 - _HeightMapParametrization: 0 @@ -220,6 +221,7 @@ Material: - _IridescenceThickness: 1 - _LinkDetailsWithBase: 1 - _MaterialID: 1 + - _MaterialTypeMask: 2 - _Metallic: 0 - _MetallicRemapMax: 1 - _MetallicRemapMin: 0 @@ -231,6 +233,9 @@ Material: - _PPDMinSamples: 5 - _PPDPrimitiveLength: 1 - _PPDPrimitiveWidth: 1 + - _PerPixelSorting: 0 + - _QueueControl: -1 + - _QueueOffset: 0 - _RayTracing: 0 - _ReceivesSSR: 1 - _ReceivesSSRTransparent: 0 @@ -250,10 +255,10 @@ Material: - _StencilRefGBuffer: 10 - _StencilRefMV: 40 - _StencilWriteMask: 6 - - _StencilWriteMaskDepth: 8 + - _StencilWriteMaskDepth: 9 - _StencilWriteMaskDistortionVec: 4 - - _StencilWriteMaskGBuffer: 14 - - _StencilWriteMaskMV: 40 + - _StencilWriteMaskGBuffer: 15 + - _StencilWriteMaskMV: 41 - _SubsurfaceMask: 1 - _SupportDecals: 1 - _SurfaceType: 0 @@ -287,8 +292,7 @@ Material: - __SkewAngle: 0 m_Colors: - Color_754dade2513142578632eb55adb8f59b: {r: 1, g: 0.36865607, b: 0, a: 0} - - Color_a1cf9b5e0df34a8c907984367d220f54: {r: 0.25471696, g: 0.25471696, b: 0.25471696, - a: 0} + - Color_a1cf9b5e0df34a8c907984367d220f54: {r: 0.25471696, g: 0.25471696, b: 0.25471696, a: 0} - Vector2_59fda9737b9e42259b122fbd66ccd94d: {r: 0.7, g: 0.28, b: 0, a: 0} - _BaseColor: {r: 1, g: 1, b: 1, a: 1} - _BaseColorMap_MipInfo: {r: 0, g: 0, b: 0, a: 0} @@ -311,6 +315,7 @@ Material: - __Padding: {r: 0.3, g: 0.5, b: 0, a: 0} - __UnlitColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} m_BuildTextureStacks: [] + m_AllowLocking: 1 --- !u!114 &3792289215621747627 MonoBehaviour: m_ObjectHideFlags: 11 @@ -323,4 +328,4 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} m_Name: m_EditorClassIdentifier: - version: 5 + version: 9 diff --git a/VisualPinball.Unity/Assets/Resources/Materials/Segment Display (SRP).mat b/VisualPinball.Unity/Assets/Resources/Materials/Segment Display (SRP).mat index 923011b22..f53e3bc1c 100644 --- a/VisualPinball.Unity/Assets/Resources/Materials/Segment Display (SRP).mat +++ b/VisualPinball.Unity/Assets/Resources/Materials/Segment Display (SRP).mat @@ -24,8 +24,7 @@ Material: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_Name: Segment Display (SRP) - m_Shader: {fileID: -6465566751694194690, guid: d54eb986991300e419411008eb1f597d, - type: 3} + m_Shader: {fileID: -6465566751694194690, guid: d54eb986991300e419411008eb1f597d, type: 3} m_Parent: {fileID: 0} m_ModifiedSerializedProperties: 0 m_ValidKeywords: @@ -115,6 +114,10 @@ Material: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} + - _SegmentDisplayCustomFunction_a94cb738cee9426e8bf076adaa3b6811_SegmentData_2_Texture2D: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} - _SpecularColorMap: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} @@ -196,6 +199,7 @@ Material: - _DoubleSidedGIMode: 0 - _DoubleSidedNormalMode: 1 - _DstBlend: 0 + - _DstBlend2: 0 - _EmissiveColorMode: 1 - _EmissiveExposureWeight: 1 - _EmissiveIntensity: 1 @@ -204,6 +208,7 @@ Material: - _EnableFogOnTransparent: 1 - _EnableGeometricSpecularAA: 0 - _EnergyConservingSpecularColor: 1 + - _ExcludeFromTUAndAA: 0 - _HeightAmplitude: 0.02 - _HeightCenter: 0.5 - _HeightMapParametrization: 0 @@ -219,6 +224,7 @@ Material: - _IridescenceThickness: 1 - _LinkDetailsWithBase: 1 - _MaterialID: 1 + - _MaterialTypeMask: 2 - _Metallic: 0 - _MetallicRemapMax: 1 - _MetallicRemapMin: 0 @@ -230,6 +236,9 @@ Material: - _PPDMinSamples: 5 - _PPDPrimitiveLength: 1 - _PPDPrimitiveWidth: 1 + - _PerPixelSorting: 0 + - _QueueControl: -1 + - _QueueOffset: 0 - _RayTracing: 0 - _ReceivesSSR: 1 - _ReceivesSSRTransparent: 0 @@ -249,10 +258,10 @@ Material: - _StencilRefGBuffer: 10 - _StencilRefMV: 40 - _StencilWriteMask: 6 - - _StencilWriteMaskDepth: 8 + - _StencilWriteMaskDepth: 9 - _StencilWriteMaskDistortionVec: 4 - - _StencilWriteMaskGBuffer: 14 - - _StencilWriteMaskMV: 40 + - _StencilWriteMaskGBuffer: 15 + - _StencilWriteMaskMV: 41 - _SubsurfaceMask: 1 - _SupportDecals: 1 - _SurfaceType: 0 @@ -276,6 +285,7 @@ Material: - _ZTestGBuffer: 4 - _ZTestTransparent: 4 - _ZWrite: 1 + - __Emission: 1 - __HorizontalMiddle: 0 - __NumChars: 2 - __NumSegments: 14 @@ -285,8 +295,7 @@ Material: - __SkewAngle: 0 m_Colors: - Color_754dade2513142578632eb55adb8f59b: {r: 1, g: 0.36865607, b: 0, a: 0} - - Color_a1cf9b5e0df34a8c907984367d220f54: {r: 0.25471696, g: 0.25471696, b: 0.25471696, - a: 0} + - Color_a1cf9b5e0df34a8c907984367d220f54: {r: 0.25471696, g: 0.25471696, b: 0.25471696, a: 0} - Vector2_59fda9737b9e42259b122fbd66ccd94d: {r: 0.7, g: 0.28, b: 0, a: 0} - _BaseColor: {r: 1, g: 1, b: 1, a: 1} - _BaseColorMap_MipInfo: {r: 0, g: 0, b: 0, a: 0} @@ -309,6 +318,7 @@ Material: - __SeparatorPos: {r: 1.4, g: 0, b: 0, a: 0} - __UnlitColor: {r: 0.25471696, g: 0.25471696, b: 0.25471696, a: 0} m_BuildTextureStacks: [] + m_AllowLocking: 1 --- !u!114 &6529312484818753363 MonoBehaviour: m_ObjectHideFlags: 11 @@ -321,4 +331,4 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} m_Name: m_EditorClassIdentifier: - version: 5 + version: 9 diff --git a/VisualPinball.Unity/Documentation~/creators-guide/editor/asset-library-styleguide.md b/VisualPinball.Unity/Documentation~/creators-guide/editor/asset-library-styleguide.md index 45ca3a137..c4428ccd7 100644 --- a/VisualPinball.Unity/Documentation~/creators-guide/editor/asset-library-styleguide.md +++ b/VisualPinball.Unity/Documentation~/creators-guide/editor/asset-library-styleguide.md @@ -204,7 +204,6 @@ The smoothness map (the inverse of a roughness map) defines how regularly light All texture maps must use power-of-two dimensions for width and height (e.g., 256, 512, 1024). They don't have to be square.
-Metallicness set to 1 with smoothness going from 0 to 1. We're aiming for a resolution of about 6 pixels per millimeter (approximately 150 DPI). For a playfield texture, this means roughly 4096×8192 pixels. Use this resolution when possible, but don't upscale images — the highest resolution should be from your source. This applies to both color and normal maps. For metallic/smoothness maps, half the resolution of the color map is a good balance between performance and visual fidelity. @@ -224,15 +223,14 @@ We're aiming for a resolution of about 6 pixels per millimeter (approximately 15 > > So, a texture map at 296×296 would correspond to 6px / mm. Since we're at power of twos, we could go for either 512×512 or 256×256. +### Compression -### File Format - -Export your texture maps in **PNG format**. Use 32-bit if they include an alpha channel; otherwise, 24-bit is sufficient. +Export your texture maps in **PNG format**. Use 32-bit if they include an alpha channel; otherwise, 24-bit is sufficient. Use halved resolution for the mask map. Don't quantize / TinyPNG your maps, since together with the GPU's block compression they will result in artifacts. > [!note] > Many artists prefer to export their textures as TGA due to faster read/write speeds, but TGA files consume significantly more space. PNG uses lossless compression, and once imported, Unity stores textures in a GPU-friendly format anyway. Additionally, when exporting to the `.vpe` format, image textures are converted into a runtime-optimized format. -In terms of *packaging*, Unity's HDRP stores metallic, ambient occlusion and smoothness in what they call a [mask map](https://docs.unity3d.com/Packages/com.unity.render-pipelines.high-definition@17.2/manual/Mask-Map-and-Detail-Map.html). Substance Painter exports this out of the box, but it should be pretty easy to do with Blender as well. +In terms of *packaging*, Unity's HDRP stores metallic, ambient occlusion and smoothness in what they call a [mask map](https://docs.unity3d.com/Packages/com.unity.render-pipelines.high-definition@17.2/manual/Mask-Map-and-Detail-Map.html). Substance Painter exports this out of the box, but it should be pretty easy to do with Blender as well. ### Wear diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser.cs index 74c85f262..b2eb65d7a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser.cs @@ -50,8 +50,6 @@ public partial class AssetBrowser : EditorWindow, IDragHandler [NonSerialized] public AssetQuery Query; - public const int ThumbSize = 256; - private AssetResult LastSelectedResult { set => _detailsElement.Asset = value?.Asset; } @@ -98,7 +96,7 @@ private void RefreshLibraries() Libraries = AssetDatabase.FindAssets($"t:{typeof(AssetLibrary)}") .Select(AssetDatabase.GUIDToAssetPath) .Select(AssetDatabase.LoadAssetAtPath) - .Where(asset => asset != null).ToList(); + .Where(lib => lib != null).ToList(); // toggle label if (Libraries.Count == 0) { @@ -198,115 +196,123 @@ private void UpdateQueryResults(List results, long duration) _statusLabel.text = $"Found {results.Count} asset" + (results.Count == 1 ? "" : "s") + $" in {duration}ms."; } - private void AddAssetContextMenu(ContextualMenuPopulateEvent evt) - { - if (evt.target is not VisualElement ve || !_resultByElement.ContainsKey(ve)) { - return; - } - - var clickedAsset = _resultByElement[ve]; - var lib = _resultByElement[ve].Asset.Library; - if (lib.IsLocked) { - return; - } - - // lib is not locked, and asset is known. - evt.menu.AppendAction("Remove from Library", _ => { - if (!_selectedResults.Contains(clickedAsset)) { - _selectedResults.Add(clickedAsset); - ToggleSelectionClass(_elementByAsset[clickedAsset.Asset]); + private void AddAssetContextMenu(ContextualMenuPopulateEvent evt) + { + if (evt.target is not VisualElement target) { + Debug.Log("Early out in AddAssetContextMenu, target is no VisualElement."); + return; } - var numRemovedAssets = 0; - foreach (var assetResult in _selectedResults.Where(a => !a.Asset.Library.IsLocked).ToList()) { - _selectedResults.Remove(assetResult); - assetResult.Asset.Library.RemoveAsset(assetResult.Asset); - if (_thumbCache.ContainsKey(assetResult.Asset.GUID)) { - DestroyImmediate(_thumbCache[assetResult.Asset.GUID]); - _thumbCache.Remove(assetResult.Asset.GUID); - } - numRemovedAssets++; + + if (!_resultByElement.ContainsKey(target.parent.parent)) { + Debug.Log($"Early out in AddAssetContextMenu, {target.parent.parent} not in resultByElement."); + return; } - RefreshCategories(); - RefreshAssets(); - _statusLabel.text = $"Removed {numRemovedAssets} assets from library."; - }); + var clickedAsset = _resultByElement[target.parent.parent]; + var libs = clickedAsset.Asset.Libraries; + if (libs.All(l => l.IsLocked)) { + Debug.Log("Early out in AddAssetContextMenu, all libraries are locked."); + return; + } - if (_selectedResults.Count > 1) { - var srcAsset = clickedAsset.Asset; - evt.menu.AppendSeparator(); - evt.menu.AppendAction("Add Attributes to Selected", _ => { - var destAssets = OtherSelected(clickedAsset).ToList(); - foreach (var destAsset in destAssets) { - foreach (var attr in srcAsset.Attributes) { - destAsset.AddAttribute(attr.Key, attr.Value); - } - destAsset.Save(); - } - EditorUtility.DisplayDialog("Add Attributes to Selected", $"Added {srcAsset.Attributes.Count} attributes to {destAssets.Count} other assets.", "OK"); - - }); - evt.menu.AppendAction("Replace Attributes in Selected", _ => { - var destAssets = OtherSelected(clickedAsset).ToList(); - foreach (var destAsset in destAssets) { - foreach (var attr in srcAsset.Attributes) { - destAsset.ReplaceAttribute(attr.Key, attr.Value); + // lib is not locked, and asset is known. + foreach (var lib in libs.Where(l => !l.IsLocked)) { + evt.menu.AppendAction($"Remove from {lib.Name}", _ => { + if (_selectedResults.Add(clickedAsset)) { + ToggleSelectionClass(_elementByAsset[clickedAsset.Asset]); } - destAsset.Save(); - } - EditorUtility.DisplayDialog("Replace Attributes to Selected", $"Replaced {srcAsset.Attributes.Count} attributes in {destAssets.Count} other assets.", "OK"); - }); - - evt.menu.AppendSeparator(); - evt.menu.AppendAction("Add Tags to Selected", _ => { - var destAssets = OtherSelected(clickedAsset).ToList(); - foreach (var destAsset in destAssets) { - foreach (var tag in srcAsset.Tags) { - destAsset.AddTag(tag.TagName); + var numRemovedAssets = 0; + foreach (var assetResult in _selectedResults.Where(a => lib.HasAsset(a.Asset.GUID)).ToList()) { + _selectedResults.Remove(assetResult); + lib.DeleteAsset(assetResult.Asset); + if (libs.Length == 1 && _thumbCache.ContainsKey(assetResult.Asset.GUID)) { + DestroyImmediate(_thumbCache[assetResult.Asset.GUID]); + _thumbCache.Remove(assetResult.Asset.GUID); + } + numRemovedAssets++; } - destAsset.Save(); - } - EditorUtility.DisplayDialog("Add Tags to Selected", $"Added {srcAsset.Tags.Count} tags to {destAssets.Count} other assets.", "OK"); - }); - - evt.menu.AppendAction("Replace Tags in Selected", _ => { - var destAssets = OtherSelected(clickedAsset).ToList(); - foreach (var destAsset in destAssets) { - destAsset.Tags.Clear(); - foreach (var tag in srcAsset.Tags) { - destAsset.AddTag(tag.TagName); + + RefreshCategories(); + RefreshAssets(); + _statusLabel.text = $"Removed {numRemovedAssets} asset(s) from library {lib.Name}."; + }); + } + + if (_selectedResults.Count > 1) { + var srcAsset = clickedAsset.Asset; + evt.menu.AppendSeparator(); + evt.menu.AppendAction("Add Attributes to Selected", _ => { + var destAssets = OtherSelected(clickedAsset).ToList(); + foreach (var destAsset in destAssets) { + foreach (var attr in srcAsset.Attributes) { + destAsset.AddAttribute(attr.Key, attr.Value); + } + destAsset.Save(); } - destAsset.Save(); - } - EditorUtility.DisplayDialog("Replace Tags in Selected", $"Replaced {srcAsset.Tags.Count} tags in {destAssets.Count} other assets.", "OK"); - }); - - evt.menu.AppendSeparator(); - evt.menu.AppendAction("Copy All to Selected", _ => { - var destAssets = OtherSelected(clickedAsset).ToList(); - foreach (var destAsset in destAssets) { - if (string.IsNullOrEmpty(destAsset.Description)) { - destAsset.Description = srcAsset.Description; + EditorUtility.DisplayDialog("Add Attributes to Selected", $"Added {srcAsset.Attributes.Count} attributes to {destAssets.Count} other assets.", "OK"); + + }); + evt.menu.AppendAction("Replace Attributes in Selected", _ => { + var destAssets = OtherSelected(clickedAsset).ToList(); + foreach (var destAsset in destAssets) { + foreach (var attr in srcAsset.Attributes) { + destAsset.ReplaceAttribute(attr.Key, attr.Value); + } + destAsset.Save(); } - foreach (var tag in srcAsset.Tags) { - destAsset.AddTag(tag.TagName); + EditorUtility.DisplayDialog("Replace Attributes to Selected", $"Replaced {srcAsset.Attributes.Count} attributes in {destAssets.Count} other assets.", "OK"); + }); + + evt.menu.AppendSeparator(); + evt.menu.AppendAction("Add Tags to Selected", _ => { + var destAssets = OtherSelected(clickedAsset).ToList(); + foreach (var destAsset in destAssets) { + foreach (var tag in srcAsset.Tags) { + destAsset.AddTag(tag.TagName); + } + destAsset.Save(); } - foreach (var attr in srcAsset.Attributes) { - destAsset.AddAttribute(attr.Key, attr.Value); + EditorUtility.DisplayDialog("Add Tags to Selected", $"Added {srcAsset.Tags.Count} tags to {destAssets.Count} other assets.", "OK"); + }); + + evt.menu.AppendAction("Replace Tags in Selected", _ => { + var destAssets = OtherSelected(clickedAsset).ToList(); + foreach (var destAsset in destAssets) { + destAsset.Tags.Clear(); + foreach (var tag in srcAsset.Tags) { + destAsset.AddTag(tag.TagName); + } + destAsset.Save(); } - foreach (var link in srcAsset.Links.Where(link => destAsset.Links.FirstOrDefault(l => l.Name == link.Name) != null)) { - destAsset.Links.Add(new AssetLink(link.Name, link.Url)); + EditorUtility.DisplayDialog("Replace Tags in Selected", $"Replaced {srcAsset.Tags.Count} tags in {destAssets.Count} other assets.", "OK"); + }); + + evt.menu.AppendSeparator(); + evt.menu.AppendAction("Copy All to Selected", _ => { + var destAssets = OtherSelected(clickedAsset).ToList(); + foreach (var destAsset in destAssets) { + if (string.IsNullOrEmpty(destAsset.Description)) { + destAsset.Description = srcAsset.Description; + } + foreach (var tag in srcAsset.Tags) { + destAsset.AddTag(tag.TagName); + } + foreach (var attr in srcAsset.Attributes) { + destAsset.AddAttribute(attr.Key, attr.Value); + } + foreach (var link in srcAsset.Links.Where(link => destAsset.Links.FirstOrDefault(l => l.Name == link.Name) != null)) { + destAsset.Links.Add(new AssetLink(link.Name, link.Url)); + } + + destAsset.Quality = srcAsset.Quality; + destAsset.ThumbCameraPreset = srcAsset.ThumbCameraPreset; + + destAsset.Save(); } - - destAsset.Quality = srcAsset.Quality; - destAsset.ThumbCameraPreset = srcAsset.ThumbCameraPreset; - - destAsset.Save(); - } - EditorUtility.DisplayDialog("Copy All to Selected", $"Copied data of to {destAssets.Count} other assets.", "OK"); - }); + EditorUtility.DisplayDialog("Copy All to Selected", $"Copied data of to {destAssets.Count} other assets.", "OK"); + }); + } } - } private IEnumerable OtherSelected(AssetResult src) { @@ -574,16 +580,13 @@ private void OnThumbSizeChanged(ChangeEvent evt) { _thumbnailSize = (int)evt.newValue; foreach (var e in _elementByAsset.Values) { - e.style.width = _thumbnailSize; - e.style.height = _thumbnailSize; + e.Q().SetSize(_thumbnailSize); } } public void AttachData(AssetResult clickedResult) { - if (!_selectedResults.Contains(clickedResult)) { - _selectedResults.Add(clickedResult); - } + _selectedResults.Add(clickedResult); DragAndDrop.objectReferences = _selectedResults.Select(result => result.Asset.Object).ToArray(); StartDraggingAssets(_selectedResults); } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser.uss b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser.uss index d33227f88..129c05d00 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser.uss +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser.uss @@ -24,6 +24,10 @@ -unity-text-align: middle-center; } +.library-element--dragover { + background-color: #515151 !important; +} + /*AssetDetails > TemplateContainer { flex-grow: 1; }*/ @@ -60,7 +64,6 @@ LibraryCategoryView { #gridContent .unity-image { width: 150px; height: 150px; - margin: 10px 10px 5px 10px; } #dragErrorContainer, #dragErrorContainerLeft { diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser_Init.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser_Init.cs index c6acdb4a9..a109b2434 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser_Init.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser_Init.cs @@ -15,7 +15,6 @@ // along with this program. If not, see . using System.Collections.Generic; -using System.IO; using UnityEditor; using UnityEditor.UIElements; using UnityEngine; @@ -42,9 +41,12 @@ public partial class AssetBrowser private Slider _sizeSlider; private VisualTreeAsset _assetTree; + private StyleSheet _assetStyle; private readonly Dictionary _thumbCache = new(); + private const string ClassDrag = "library-element--dragover"; + public string DragErrorLeft { get => _dragErrorContainerLeft.ClassListContains("hidden") ? null : _dragErrorLabelLeft.text; set { @@ -84,6 +86,7 @@ public void CreateGUI() var visualTree = AssetDatabase.LoadAssetAtPath("Packages/org.visualpinball.engine.unity/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/AssetBrowser.uxml"); visualTree.CloneTree(rootVisualElement); _assetTree = AssetDatabase.LoadAssetAtPath("Packages/org.visualpinball.engine.unity/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/LibraryAssetElement.uxml"); + _assetStyle = AssetDatabase.LoadAssetAtPath("Packages/org.visualpinball.engine.unity/VisualPinball.Unity/VisualPinball.Unity.Editor/AssetBrowser/LibraryAssetElement.uss"); var ui = rootVisualElement; @@ -148,33 +151,33 @@ private VisualElement NewItem(AssetResult result) { var item = new VisualElement(); _assetTree.CloneTree(item); - item.Q().Result = result; + item.styleSheets.Add(_assetStyle); + var assetElement = item.Q(); + assetElement.Result = result; LoadThumb(item, result.Asset); - item.style.width = _thumbnailSize; - item.style.height = _thumbnailSize; + var img = item.Q("thumbnail-mask"); + assetElement.SetSize(_thumbnailSize); + var label = item.Q