jp.keijiro.klutter-tools 2.4.4 → 2.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.attestation.p7m CHANGED
Binary file
package/CHANGELOG.md CHANGED
@@ -5,6 +5,19 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
6
6
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [2.5.1] - 2026-01-21
9
+
10
+ ### Fixed
11
+
12
+ - Adjusted Downloader launch delay to be applied when constructing the launcher.
13
+ - Avoided setting the Downloader visible flag when the window is not shown.
14
+
15
+ ## [2.5.0] - 2026-01-17
16
+
17
+ ### Added
18
+
19
+ - Added the Downloader tool for fetching large external assets.
20
+
8
21
  ## [2.4.4] - 2025-11-25
9
22
 
10
23
  ### Added
@@ -0,0 +1,65 @@
1
+ using System;
2
+ using UnityEditor;
3
+ using UnityEngine;
4
+ using UnityEngine.UIElements;
5
+
6
+ namespace KlutterTools.Downloader {
7
+
8
+ sealed class DownloaderWindow : EditorWindow
9
+ {
10
+ static readonly string UxmlPath =
11
+ "Packages/jp.keijiro.klutter-tools/Editor/Downloader/DownloaderWindow.uxml";
12
+
13
+ public static void ShowWindow()
14
+ {
15
+ var window = GetWindow<DownloaderWindow>(true, "Downloader");
16
+ window.minSize = new Vector2(400, 200);
17
+ window.Show();
18
+ }
19
+
20
+ public void CreateGUI()
21
+ {
22
+ // New UI document from UXML
23
+ var uxml = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(UxmlPath);
24
+ var doc = uxml.CloneTree();
25
+
26
+ // Caption text
27
+ var caption = doc.Q<Label>("caption-label");
28
+ caption.text = GlobalManifest.Instance.Caption;
29
+
30
+ // List view setup
31
+ var list = doc.Q<ListView>("entry-list");
32
+ list.bindItem = BindItem;
33
+ list.itemsSource = GlobalManifest.Instance.FileEntries;
34
+
35
+ rootVisualElement.Add(doc);
36
+ }
37
+
38
+ // List view item binding
39
+ void BindItem(VisualElement element, int index)
40
+ {
41
+ var button = element.Q<Button>("download-button");
42
+ var entry = GlobalManifest.Instance.FileEntries[index];
43
+
44
+ // Enable button only for missing files.
45
+ button.enabledSelf = (entry.CurrentState == FileState.Missing);
46
+
47
+ // Remove previous handler if exists.
48
+ if (button.userData is Action prev) button.clicked -= prev;
49
+
50
+ // Register new handler.
51
+ Action action = async () =>
52
+ {
53
+ button.enabledSelf = false;
54
+ if (await entry.DownloadAsync())
55
+ AssetDatabase.Refresh();
56
+ else
57
+ button.enabledSelf = true;
58
+ Repaint();
59
+ };
60
+ button.clicked += action;
61
+ button.userData = action;
62
+ }
63
+ }
64
+
65
+ } // namespace KlutterTools.Downloader
@@ -0,0 +1,13 @@
1
+ fileFormatVersion: 2
2
+ guid: 125c9a9d918e49768edc34c7ffa1dbcd
3
+ MonoImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ defaultReferences:
7
+ - m_ViewDataDictionary: {instanceID: 0}
8
+ - _uxml: {fileID: 9197481963319205126, guid: 6c823161c766e470388d0ce278f2a86f, type: 3}
9
+ executionOrder: 0
10
+ icon: {instanceID: 0}
11
+ userData:
12
+ assetBundleName:
13
+ assetBundleVariant:
@@ -0,0 +1,6 @@
1
+ <ui:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="True">
2
+ <ui:VisualElement name="root-container" style="margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px;">
3
+ <ui:Label text="Some files are missing:" name="caption-label" style="margin-bottom: 8px; white-space: normal;"/>
4
+ <ui:ListView item-template="project://database/Packages/jp.keijiro.klutter-tools/Editor/Downloader/FileEntry.uxml?fileID=9197481963319205126&amp;guid=e5fb5605902c247d8b81f9a365e2b6e4&amp;type=3#FileEntry" binding-source-selection-mode="AutoAssign" name="entry-list"/>
5
+ </ui:VisualElement>
6
+ </ui:UXML>
@@ -0,0 +1,10 @@
1
+ fileFormatVersion: 2
2
+ guid: 6c823161c766e470388d0ce278f2a86f
3
+ ScriptedImporter:
4
+ internalIDToNameTable: []
5
+ externalObjects: {}
6
+ serializedVersion: 2
7
+ userData:
8
+ assetBundleName:
9
+ assetBundleVariant:
10
+ script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
@@ -0,0 +1,80 @@
1
+ using System;
2
+ using System.IO;
3
+ using System.Threading.Tasks;
4
+ using Unity.Properties;
5
+ using UnityEngine;
6
+ using UnityEngine.Networking;
7
+
8
+ namespace KlutterTools.Downloader {
9
+
10
+ [Serializable]
11
+ public sealed class FileEntry
12
+ {
13
+ //// Editable attributes
14
+
15
+ [field:SerializeField]
16
+ public string SourceUrl { get; private set; }
17
+
18
+ [field:SerializeField]
19
+ public string Destination { get; private set; } = "Assets/StreamingAssets";
20
+
21
+ //// Exposed UI properties
22
+
23
+ [CreateProperty]
24
+ public string Filename { get; private set; }
25
+
26
+ [CreateProperty]
27
+ public FileState CurrentState { get; private set; }
28
+
29
+ //// Dynamic properties
30
+
31
+ public string DestinationPath
32
+ => Path.Combine(Destination, Filename);
33
+
34
+ public string TemporaryPath
35
+ => Path.Combine(Application.temporaryCachePath, Filename);
36
+
37
+ //// Public methods
38
+
39
+ // Validation method
40
+ public void OnValidate()
41
+ {
42
+ if (Uri.TryCreate(SourceUrl, UriKind.Absolute, out var uri))
43
+ {
44
+ Filename = Path.GetFileName(uri.LocalPath);
45
+ CurrentState = File.Exists(DestinationPath)
46
+ ? FileState.Downloaded : FileState.Missing;
47
+ }
48
+ else
49
+ {
50
+ Filename = null;
51
+ CurrentState = FileState.Missing;
52
+ }
53
+ }
54
+
55
+ // Asynchronous file download method
56
+ public async Task<bool> DownloadAsync()
57
+ {
58
+ var destPath = DestinationPath;
59
+ var tempPath = TemporaryPath;
60
+ var success = false;
61
+
62
+ using (var request = UnityWebRequest.Get(SourceUrl))
63
+ {
64
+ CurrentState = FileState.Downloading;
65
+ request.downloadHandler = new DownloadHandlerFile(tempPath);
66
+ await Awaitable.FromAsyncOperation(request.SendWebRequest());
67
+ success = (request.result == UnityWebRequest.Result.Success);
68
+ CurrentState = success ? FileState.Downloaded : FileState.Missing;
69
+ }
70
+
71
+ if (success)
72
+ File.Move(tempPath, destPath);
73
+ else
74
+ Debug.LogError($"Failed to download test data file: {Filename}");
75
+
76
+ return success;
77
+ }
78
+ }
79
+
80
+ } // namespace KlutterTools.Downloader
@@ -0,0 +1,2 @@
1
+ fileFormatVersion: 2
2
+ guid: 270945ec9f9a749a1bd38f4a91503d59
@@ -0,0 +1,15 @@
1
+ <ui:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="True">
2
+ <ui:VisualElement name="file-entry" data-source-type="KlutterTools.Downloader.FileEntry, KlutterTools.Editor" style="flex-direction: row; align-items: center;">
3
+ <ui:Label text="TestFile.dat" name="filename-label" style="flex-grow: 1;">
4
+ <Bindings>
5
+ <ui:DataBinding property="text" data-source-path="Filename" binding-mode="ToTarget"/>
6
+ </Bindings>
7
+ </ui:Label>
8
+ <ui:Label name="state-label" text="Missing" style="color: rgb(147, 147, 147); -unity-font-style: italic;">
9
+ <Bindings>
10
+ <ui:DataBinding property="text" data-source-path="CurrentState" binding-mode="ToTarget"/>
11
+ </Bindings>
12
+ </ui:Label>
13
+ <ui:Button text="Download" name="download-button"/>
14
+ </ui:VisualElement>
15
+ </ui:UXML>
@@ -0,0 +1,10 @@
1
+ fileFormatVersion: 2
2
+ guid: e5fb5605902c247d8b81f9a365e2b6e4
3
+ ScriptedImporter:
4
+ internalIDToNameTable: []
5
+ externalObjects: {}
6
+ serializedVersion: 2
7
+ userData:
8
+ assetBundleName:
9
+ assetBundleVariant:
10
+ script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
@@ -0,0 +1,3 @@
1
+ namespace KlutterTools.Downloader {
2
+ public enum FileState { Missing, Downloading, Downloaded }
3
+ }
@@ -0,0 +1,2 @@
1
+ fileFormatVersion: 2
2
+ guid: 9243bbc63cbb149b7bec57f3e379c01d
@@ -0,0 +1,22 @@
1
+ using UnityEditor;
2
+
3
+ namespace KlutterTools.Downloader {
4
+
5
+ public static class GlobalManifest
6
+ {
7
+ public static Manifest Instance { get; private set; }
8
+
9
+ static GlobalManifest()
10
+ {
11
+ // Search
12
+ var guids = AssetDatabase.FindAssets("t:KlutterTools.Downloader.Manifest");
13
+ if (guids.Length == 0) return;
14
+
15
+ // Load
16
+ var path = AssetDatabase.GUIDToAssetPath(guids[0]);
17
+ Instance = AssetDatabase.LoadAssetAtPath<Manifest>(path);
18
+ Instance.Validate();
19
+ }
20
+ }
21
+
22
+ } // namespace KlutterTools.Downloader
@@ -0,0 +1,2 @@
1
+ fileFormatVersion: 2
2
+ guid: 2709c757046bf4a5ca615b877b57f204
@@ -0,0 +1,29 @@
1
+ using UnityEditor;
2
+
3
+ namespace KlutterTools.Downloader {
4
+
5
+ [InitializeOnLoad]
6
+ static class Launcher
7
+ {
8
+ static Launcher()
9
+ => EditorApplication.delayCall += CheckAndShow;
10
+
11
+ static void CheckAndShow()
12
+ {
13
+ // Session state check
14
+ const string sessionKey = "KlutterTools.Downloader.Shown";
15
+ if (SessionState.GetBool(sessionKey, false)) return;
16
+
17
+ // Manifest existence check
18
+ if (GlobalManifest.Instance == null) return;
19
+
20
+ // All files downloaded check
21
+ if (GlobalManifest.Instance.CheckAllDownloaded()) return;
22
+
23
+ // Downloader window open
24
+ DownloaderWindow.ShowWindow();
25
+ SessionState.SetBool(sessionKey, true);
26
+ }
27
+ }
28
+
29
+ } // namespace KlutterTools.Downloader
@@ -0,0 +1,11 @@
1
+ fileFormatVersion: 2
2
+ guid: 102ec9e67620463f9254f5fdd9b699c1
3
+ MonoImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ defaultReferences: []
7
+ executionOrder: 0
8
+ icon: {instanceID: 0}
9
+ userData:
10
+ assetBundleName:
11
+ assetBundleVariant:
@@ -0,0 +1,33 @@
1
+ using System.Linq;
2
+ using UnityEngine;
3
+
4
+ namespace KlutterTools.Downloader {
5
+
6
+ [CreateAssetMenu(fileName = "Manifest", menuName = "Klutter Tools/Downloader/Manifest")]
7
+ public sealed class Manifest : ScriptableObject
8
+ {
9
+ // Editable attributes
10
+
11
+ [field:SerializeField]
12
+ public string Caption { get; private set; } = "Some files are missing:";
13
+
14
+ [field:SerializeField]
15
+ public FileEntry[] FileEntries { get; private set; }
16
+
17
+ // Public methods
18
+
19
+ public bool CheckAllDownloaded()
20
+ => FileEntries.All(e => e.CurrentState == FileState.Downloaded);
21
+
22
+ public void Validate() => OnValidate();
23
+
24
+ // ScriptableObject implementation
25
+
26
+ void OnValidate()
27
+ {
28
+ if (FileEntries == null) return;
29
+ foreach (var entry in FileEntries) entry.OnValidate();
30
+ }
31
+ }
32
+
33
+ } // namespace KlutterTools.Downloader
@@ -0,0 +1,2 @@
1
+ fileFormatVersion: 2
2
+ guid: 5acc6266be6eb4130afc5134ec35fcec
@@ -0,0 +1,8 @@
1
+ fileFormatVersion: 2
2
+ guid: 5b3e6ae533eef420c830e5e3b00bbbbd
3
+ folderAsset: yes
4
+ DefaultImporter:
5
+ externalObjects: {}
6
+ userData:
7
+ assetBundleName:
8
+ assetBundleVariant:
package/README.md CHANGED
@@ -41,6 +41,12 @@ or notes directly to GameObjects in the Inspector. This can be useful for
41
41
  leaving reminders, instructions, or context for other developers -- or just
42
42
  jotting down your own thoughts.
43
43
 
44
+ ### Downloader
45
+
46
+ **Downloader** is a tool for fetching additional data from the web. It's
47
+ useful when a project needs large assets, such as uncompressed video files or
48
+ large machine learning models.
49
+
44
50
  ## System Requirements
45
51
 
46
52
  - Unity 6 or later
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jp.keijiro.klutter-tools",
3
- "version": "2.4.4",
3
+ "version": "2.5.1",
4
4
  "displayName": "Klutter Tools",
5
5
  "description": "Miscellaneous editor tools.",
6
6
  "unity": "6000.0",
@@ -11,11 +11,11 @@
11
11
  "licensesUrl": "https://github.com/keijiro/KlutterTools/blob/main/LICENSE",
12
12
  "license": "Unlicense",
13
13
  "_upm": {
14
- "changelog": "<b>Added</b><br>- Added signing for Unity 6.3."
14
+ "changelog": "<b>Fixed</b><br>- Adjusted Downloader launch delay to be applied when constructing the launcher.<br>- Avoided setting the Downloader visible flag when the window is not shown."
15
15
  },
16
16
  "repository": {
17
17
  "url": "git@github.com:keijiro/KlutterTools.git",
18
18
  "type": "git",
19
- "revision": "e681f462862b2948acac6125f0e640030e1434e4"
19
+ "revision": "9afabac843d781841341be05c6421c499ea29a5c"
20
20
  }
21
21
  }