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 +0 -0
- package/CHANGELOG.md +13 -0
- package/Editor/Downloader/DownloaderWindow.cs +65 -0
- package/Editor/Downloader/DownloaderWindow.cs.meta +13 -0
- package/Editor/Downloader/DownloaderWindow.uxml +6 -0
- package/Editor/Downloader/DownloaderWindow.uxml.meta +10 -0
- package/Editor/Downloader/FileEntry.cs +80 -0
- package/Editor/Downloader/FileEntry.cs.meta +2 -0
- package/Editor/Downloader/FileEntry.uxml +15 -0
- package/Editor/Downloader/FileEntry.uxml.meta +10 -0
- package/Editor/Downloader/FileState.cs +3 -0
- package/Editor/Downloader/FileState.cs.meta +2 -0
- package/Editor/Downloader/GlobalManifest.cs +22 -0
- package/Editor/Downloader/GlobalManifest.cs.meta +2 -0
- package/Editor/Downloader/Launcher.cs +29 -0
- package/Editor/Downloader/Launcher.cs.meta +11 -0
- package/Editor/Downloader/Manifest.cs +33 -0
- package/Editor/Downloader/Manifest.cs.meta +2 -0
- package/Editor/Downloader.meta +8 -0
- package/README.md +6 -0
- package/package.json +3 -3
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&guid=e5fb5605902c247d8b81f9a365e2b6e4&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,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,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,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,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
|
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.
|
|
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>
|
|
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": "
|
|
19
|
+
"revision": "9afabac843d781841341be05c6421c499ea29a5c"
|
|
20
20
|
}
|
|
21
21
|
}
|