com.beamable 5.1.0-PREVIEW.RC7 → 5.1.0-PREVIEW.RC8
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 +1 -0
- package/Editor/ContentService/CliContentService.cs +28 -27
- package/Editor/ContentService/DefaultContentImporter.cs +248 -0
- package/Editor/ContentService/DefaultContentImporter.cs.meta +2 -0
- package/Editor/Modules/Content/DefaultAssets~/currency/coins.png +0 -0
- package/Editor/Modules/Content/DefaultAssets~/currency/coins.png.meta +135 -0
- package/Editor/Modules/Content/DefaultAssets~/currency/gems.png +0 -0
- package/Editor/Modules/Content/DefaultAssets~/currency/gems.png.meta +135 -0
- package/Editor/Modules/Content/DefaultContent/currency/coins.asset +1 -1
- package/Editor/Modules/Content/DefaultContent/currency/gems.asset +1 -1
- package/Editor/UI/ContentWindow/ContentWindow.cs +100 -2
- package/Runtime/Environment/Resources/env-default.json +1 -1
- package/Runtime/UI/Sprites/icon_gem.png.meta +1 -1
- package/package.json +1 -1
package/.attestation.p7m
CHANGED
|
Binary file
|
package/CHANGELOG.md
CHANGED
|
@@ -28,6 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
28
28
|
- "Beam Library" Window is now "Beam Samples" Window and was updated with latest docs and samples
|
|
29
29
|
- AdminFlow prefab (ConsoleFlow) was removed from the Beam Samples Window and is now considered Deprecated
|
|
30
30
|
- Now Renamed content entries will be shown as Modified Renamed in the Content Manager Window rather than a New and Deleted entries.
|
|
31
|
+
- Default assets and content are imported manually on first visit to Content Manager
|
|
31
32
|
|
|
32
33
|
## [5.0.1] - 2026-04-02
|
|
33
34
|
### Fixed
|
|
@@ -83,6 +83,23 @@ namespace Beamable.Editor.ContentService
|
|
|
83
83
|
public bool isReloading;
|
|
84
84
|
public List<string> availableManifestIds;
|
|
85
85
|
|
|
86
|
+
/// <summary>
|
|
87
|
+
/// True once the most recent <see cref="Reload"/> has finished fetching the realm's remote
|
|
88
|
+
/// manifest list. Until this is true the realm's emptiness is unknown (still loading).
|
|
89
|
+
/// </summary>
|
|
90
|
+
public bool RemoteManifestsLoaded { get; private set; }
|
|
91
|
+
/// <summary>
|
|
92
|
+
/// True when the last remote-manifest fetch errored. Used so the Content Manager does not
|
|
93
|
+
/// misread a transient failure as "this realm is empty".
|
|
94
|
+
/// </summary>
|
|
95
|
+
public bool RemoteManifestsErrored { get; private set; }
|
|
96
|
+
/// <summary>
|
|
97
|
+
/// Number of remote manifests on the realm as of the last successful fetch. Zero means the
|
|
98
|
+
/// realm has never had content published — the signal used to offer the opt-in default
|
|
99
|
+
/// content import (see DefaultContentImporter).
|
|
100
|
+
/// </summary>
|
|
101
|
+
public int RemoteManifestCount { get; private set; }
|
|
102
|
+
|
|
86
103
|
public Dictionary<string, LocalContentManifestEntry> EntriesCache { get; }
|
|
87
104
|
|
|
88
105
|
private readonly Dictionary<string, ContentObject> _contentScriptableCache;
|
|
@@ -735,10 +752,10 @@ namespace Beamable.Editor.ContentService
|
|
|
735
752
|
_contentWatcher.OnProgressStreamContentPsProgressMessage(dp => { LatestProgressUpdate = dp.data; });
|
|
736
753
|
_ = _contentWatcher.Command.Run();
|
|
737
754
|
|
|
738
|
-
|
|
755
|
+
RemoteManifestsLoaded = false;
|
|
756
|
+
RemoteManifestsErrored = false;
|
|
739
757
|
var getAvailableManifestsPromise = _cli.ContentListManifests(new ContentListManifestsArgs()).OnStreamContentListManifestsCommandResults(dp =>
|
|
740
758
|
{
|
|
741
|
-
|
|
742
759
|
var manifestIds = new HashSet<string>();
|
|
743
760
|
foreach (var id in dp.data.localManifests)
|
|
744
761
|
{
|
|
@@ -749,41 +766,25 @@ namespace Beamable.Editor.ContentService
|
|
|
749
766
|
{
|
|
750
767
|
manifestIds.Add(id);
|
|
751
768
|
}
|
|
752
|
-
|
|
753
|
-
if (dp.data.remoteManifests.Count == 0)
|
|
754
|
-
{
|
|
755
|
-
// If no remote manifest on remote, it means that it is the first time that the customer is using this realm
|
|
756
|
-
// If so, we need to create the default contents
|
|
757
|
-
string[] guids = BeamableAssetDatabase.FindAssets<ContentObject>(new[] {Constants.Directories.DEFAULT_DATA_DIR});
|
|
758
|
-
foreach (string guid in guids)
|
|
759
|
-
{
|
|
760
|
-
string path = AssetDatabase.GUIDToAssetPath(guid);
|
|
761
|
-
ContentObject obj = AssetDatabase.LoadAssetAtPath<ContentObject>(path);
|
|
762
769
|
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
}
|
|
771
|
-
}
|
|
770
|
+
// A realm with zero remote manifests has never had content published to it.
|
|
771
|
+
// Seeding default content is deferred to an explicit, user-initiated action
|
|
772
|
+
// (see DefaultContentImporter) so we never mutate the AssetDatabase / Addressables
|
|
773
|
+
// at init time. Here we only record the signal the Content Manager uses to offer
|
|
774
|
+
// the opt-in import prompt.
|
|
775
|
+
RemoteManifestCount = dp.data.remoteManifests.Count;
|
|
776
|
+
RemoteManifestsLoaded = true;
|
|
772
777
|
|
|
773
778
|
availableManifestIds = manifestIds.ToList();
|
|
774
779
|
}).OnError(dp =>
|
|
775
780
|
{
|
|
781
|
+
RemoteManifestsErrored = true;
|
|
776
782
|
Debug.LogError(dp.data.message);
|
|
777
783
|
}).Run();
|
|
778
|
-
|
|
784
|
+
|
|
779
785
|
await manifestIsFetchedTaskCompletion.Task;
|
|
780
786
|
await getAvailableManifestsPromise;
|
|
781
787
|
|
|
782
|
-
if (addedAnyDefault)
|
|
783
|
-
{
|
|
784
|
-
await PublishContents();
|
|
785
|
-
}
|
|
786
|
-
|
|
787
788
|
ManifestChangedCount++;
|
|
788
789
|
}
|
|
789
790
|
finally
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
using Beamable.Common;
|
|
2
|
+
using Beamable.Common.Content;
|
|
3
|
+
using System.Collections.Generic;
|
|
4
|
+
using System.IO;
|
|
5
|
+
using System.Threading.Tasks;
|
|
6
|
+
using UnityEditor;
|
|
7
|
+
using UnityEditor.AddressableAssets;
|
|
8
|
+
using UnityEditor.AddressableAssets.Settings;
|
|
9
|
+
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
|
|
10
|
+
using UnityEngine;
|
|
11
|
+
|
|
12
|
+
namespace Beamable.Editor.ContentService
|
|
13
|
+
{
|
|
14
|
+
/// <summary>
|
|
15
|
+
/// Opt-in, user-initiated seeding of Beamable's default content (currency gems/coins) into a
|
|
16
|
+
/// realm that has never had content published.
|
|
17
|
+
///
|
|
18
|
+
/// This replaces the old behaviour where <see cref="CliContentService.Reload"/> silently seeded
|
|
19
|
+
/// and published default content at editor init time. That ran AssetDatabase / Addressables
|
|
20
|
+
/// mutation during initialization, which was risky (potential refresh loops). Seeding now only
|
|
21
|
+
/// happens when the user explicitly asks for it — via the Content Manager empty-state prompt or
|
|
22
|
+
/// the "Import Default Content" menu item.
|
|
23
|
+
///
|
|
24
|
+
/// The currency icons are Addressable sprite references. The seed sprites ship in the
|
|
25
|
+
/// Unity-ignored <c>DefaultAssets~</c> folder with pinned-GUID meta files; importing copies them
|
|
26
|
+
/// into the project (where the pinned GUID registers for the first time, avoiding a collision),
|
|
27
|
+
/// marks them addressable, and only then seeds the content — whose serialized references already
|
|
28
|
+
/// point at the pinned GUIDs.
|
|
29
|
+
/// </summary>
|
|
30
|
+
public static class DefaultContentImporter
|
|
31
|
+
{
|
|
32
|
+
private const string DISMISS_PREF_PREFIX = "beamable.contentmanager.defaultcontent.dismissed";
|
|
33
|
+
|
|
34
|
+
/// <summary>Per-realm EditorPrefs key controlling whether the in-window prompt is shown.</summary>
|
|
35
|
+
public static string DismissKey(string cid, string pid) => $"{DISMISS_PREF_PREFIX}.{cid}.{pid}";
|
|
36
|
+
|
|
37
|
+
public static bool IsDismissed(string cid, string pid)
|
|
38
|
+
{
|
|
39
|
+
if (string.IsNullOrEmpty(cid) || string.IsNullOrEmpty(pid))
|
|
40
|
+
return false;
|
|
41
|
+
return EditorPrefs.GetBool(DismissKey(cid, pid), false);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public static void SetDismissed(string cid, string pid, bool dismissed = true)
|
|
45
|
+
{
|
|
46
|
+
if (string.IsNullOrEmpty(cid) || string.IsNullOrEmpty(pid))
|
|
47
|
+
return;
|
|
48
|
+
EditorPrefs.SetBool(DismissKey(cid, pid), dismissed);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
[MenuItem(Constants.MenuItems.Windows.Paths.MENU_ITEM_PATH_WINDOW_BEAMABLE_UTILITIES + "/Import Default Content")]
|
|
52
|
+
public static async void ImportDefaultContent_MenuItem()
|
|
53
|
+
{
|
|
54
|
+
bool confirmed = EditorUtility.DisplayDialog(
|
|
55
|
+
"Import Default Content",
|
|
56
|
+
"This will create Beamable's default content (gems & coins currencies) as local content, " +
|
|
57
|
+
"copying their icon sprites into Assets/Beamable/DefaultAssets and registering them as " +
|
|
58
|
+
"Addressables.",
|
|
59
|
+
"Import",
|
|
60
|
+
"Cancel");
|
|
61
|
+
|
|
62
|
+
if (confirmed)
|
|
63
|
+
{
|
|
64
|
+
await ImportDefaultContent();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/// <summary>
|
|
69
|
+
/// Shared import routine used by both the menu item and the Content Manager prompt. Seeds the
|
|
70
|
+
/// default content as local content; the user can review and publish it themselves.
|
|
71
|
+
/// </summary>
|
|
72
|
+
public static async Task ImportDefaultContent()
|
|
73
|
+
{
|
|
74
|
+
var api = BeamEditorContext.Default;
|
|
75
|
+
await api.InitializePromise;
|
|
76
|
+
var contentService = api.ServiceScope.GetService<CliContentService>();
|
|
77
|
+
|
|
78
|
+
// 1. Ensure Addressables settings exist (GetSettings(true) creates them if missing).
|
|
79
|
+
var settings = AddressableAssetSettingsDefaultObject.GetSettings(true);
|
|
80
|
+
if (settings == null)
|
|
81
|
+
{
|
|
82
|
+
EditorUtility.DisplayDialog(
|
|
83
|
+
"Addressables Required",
|
|
84
|
+
"Beamable's default content uses Unity Addressables for its currency icons, but the " +
|
|
85
|
+
"Addressables settings could not be created. Please configure the Addressables package " +
|
|
86
|
+
"and try again.",
|
|
87
|
+
"OK");
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// 2. Copy seed sprites into the project and register them as addressables (idempotent).
|
|
92
|
+
if (!EnsureDefaultAssetsImported(settings))
|
|
93
|
+
{
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// 3. Seed the content locally. The default content's serialized icon references already
|
|
98
|
+
// point at the pinned GUIDs, so no per-asset remap is needed.
|
|
99
|
+
SeedDefaultContent(contentService);
|
|
100
|
+
|
|
101
|
+
// 4. Refresh the Content Manager view. The seeded content is left local for the user to
|
|
102
|
+
// review and publish on their own terms.
|
|
103
|
+
await contentService.Reload();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/// <summary>
|
|
107
|
+
/// Copies the seed sprites out of the Unity-ignored source folder into the project and
|
|
108
|
+
/// ensures each is an entry in the "Beamable Assets" Addressables group. Idempotent: sprites
|
|
109
|
+
/// already present (by pinned GUID) are reused rather than re-copied.
|
|
110
|
+
/// </summary>
|
|
111
|
+
private static bool EnsureDefaultAssetsImported(AddressableAssetSettings settings)
|
|
112
|
+
{
|
|
113
|
+
var sourceRoot = ResolveSourceRoot();
|
|
114
|
+
if (string.IsNullOrEmpty(sourceRoot) || !Directory.Exists(sourceRoot))
|
|
115
|
+
{
|
|
116
|
+
EditorUtility.DisplayDialog(
|
|
117
|
+
"Default Content Unavailable",
|
|
118
|
+
$"Could not locate the default content seed assets at '{Constants.Directories.DEFAULT_ASSET_SOURCE_DIR}'.",
|
|
119
|
+
"OK");
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
var knownGuids = new List<string>();
|
|
124
|
+
var copiedAnything = false;
|
|
125
|
+
|
|
126
|
+
foreach (var typeDir in Directory.GetDirectories(sourceRoot))
|
|
127
|
+
{
|
|
128
|
+
var typeName = Path.GetFileName(typeDir); // e.g. "currency"
|
|
129
|
+
var destDir = $"{Constants.Directories.ASSET_DIR}/{typeName}";
|
|
130
|
+
|
|
131
|
+
foreach (var src in Directory.GetFiles(typeDir))
|
|
132
|
+
{
|
|
133
|
+
if (src.EndsWith(".meta"))
|
|
134
|
+
continue;
|
|
135
|
+
|
|
136
|
+
var metaSrc = src + ".meta";
|
|
137
|
+
if (!File.Exists(metaSrc))
|
|
138
|
+
continue; // a pinned-GUID meta is required
|
|
139
|
+
|
|
140
|
+
var knownGuid = ReadGuidFromMeta(metaSrc);
|
|
141
|
+
if (string.IsNullOrEmpty(knownGuid))
|
|
142
|
+
continue;
|
|
143
|
+
|
|
144
|
+
knownGuids.Add(knownGuid);
|
|
145
|
+
|
|
146
|
+
// Short-circuit: already imported (by pinned GUID) -> reuse, don't duplicate.
|
|
147
|
+
var existingPath = AssetDatabase.GUIDToAssetPath(knownGuid);
|
|
148
|
+
if (!string.IsNullOrEmpty(existingPath) && File.Exists(existingPath))
|
|
149
|
+
continue;
|
|
150
|
+
|
|
151
|
+
Directory.CreateDirectory(destDir);
|
|
152
|
+
var fileName = Path.GetFileName(src);
|
|
153
|
+
var dest = Path.Combine(destDir, fileName);
|
|
154
|
+
File.Copy(src, dest, true);
|
|
155
|
+
// Copy the pinned-GUID meta so the imported asset keeps the known GUID.
|
|
156
|
+
File.Copy(metaSrc, dest + ".meta", true);
|
|
157
|
+
copiedAnything = true;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (copiedAnything)
|
|
162
|
+
{
|
|
163
|
+
AssetDatabase.Refresh();
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Ensure the addressables group exists, then ensure each seed sprite is an entry in it.
|
|
167
|
+
var group = settings.FindGroup(Constants.BEAMABLE_ASSET_GROUP);
|
|
168
|
+
if (group == null)
|
|
169
|
+
{
|
|
170
|
+
group = settings.CreateGroup(
|
|
171
|
+
Constants.BEAMABLE_ASSET_GROUP,
|
|
172
|
+
setAsDefaultGroup: false,
|
|
173
|
+
readOnly: false,
|
|
174
|
+
postEvent: true,
|
|
175
|
+
schemasToCopy: new List<AddressableAssetGroupSchema>(),
|
|
176
|
+
typeof(ContentUpdateGroupSchema), typeof(BundledAssetGroupSchema));
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
var entries = new List<AddressableAssetEntry>();
|
|
180
|
+
foreach (var knownGuid in knownGuids)
|
|
181
|
+
{
|
|
182
|
+
var path = AssetDatabase.GUIDToAssetPath(knownGuid);
|
|
183
|
+
if (string.IsNullOrEmpty(path))
|
|
184
|
+
{
|
|
185
|
+
Debug.LogWarning($"[Default Content] Seed sprite with GUID {knownGuid} did not import; its currency icon may not resolve.");
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
var entry = settings.CreateOrMoveEntry(knownGuid, group);
|
|
190
|
+
if (entry != null)
|
|
191
|
+
entries.Add(entry);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (entries.Count > 0)
|
|
195
|
+
{
|
|
196
|
+
settings.SetDirty(AddressableAssetSettings.ModificationEvent.EntryMoved, entries, true);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/// <summary>
|
|
203
|
+
/// Loads the default content objects shipped in the package and saves them as local content.
|
|
204
|
+
/// </summary>
|
|
205
|
+
private static void SeedDefaultContent(CliContentService contentService)
|
|
206
|
+
{
|
|
207
|
+
string[] guids = BeamableAssetDatabase.FindAssets<ContentObject>(new[] { Constants.Directories.DEFAULT_DATA_DIR });
|
|
208
|
+
foreach (string guid in guids)
|
|
209
|
+
{
|
|
210
|
+
string path = AssetDatabase.GUIDToAssetPath(guid);
|
|
211
|
+
ContentObject obj = AssetDatabase.LoadAssetAtPath<ContentObject>(path);
|
|
212
|
+
if (obj == null)
|
|
213
|
+
continue;
|
|
214
|
+
|
|
215
|
+
string fileName = Path.GetFileNameWithoutExtension(path);
|
|
216
|
+
obj.SetContentName(fileName);
|
|
217
|
+
contentService.SaveContent(obj);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/// <summary>
|
|
222
|
+
/// Resolves the seed-asset source folder to an absolute path. The folder is "~"-suffixed so
|
|
223
|
+
/// Unity ignores it; we read it with System.IO. <see cref="Path.GetFullPath"/> resolves the
|
|
224
|
+
/// "Packages/com.beamable/..." virtual path for embedded/local packages.
|
|
225
|
+
/// </summary>
|
|
226
|
+
private static string ResolveSourceRoot()
|
|
227
|
+
{
|
|
228
|
+
var relative = Constants.Directories.DEFAULT_ASSET_SOURCE_DIR;
|
|
229
|
+
if (Directory.Exists(relative))
|
|
230
|
+
return relative;
|
|
231
|
+
|
|
232
|
+
var full = Path.GetFullPath(relative);
|
|
233
|
+
return Directory.Exists(full) ? full : null;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
private static string ReadGuidFromMeta(string metaPath)
|
|
237
|
+
{
|
|
238
|
+
foreach (var line in File.ReadLines(metaPath))
|
|
239
|
+
{
|
|
240
|
+
var trimmed = line.Trim();
|
|
241
|
+
if (trimmed.StartsWith("guid:"))
|
|
242
|
+
return trimmed.Substring("guid:".Length).Trim();
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
fileFormatVersion: 2
|
|
2
|
+
guid: a7796303ede2490ea179355045c77b7e
|
|
3
|
+
TextureImporter:
|
|
4
|
+
internalIDToNameTable: []
|
|
5
|
+
externalObjects: {}
|
|
6
|
+
serializedVersion: 12
|
|
7
|
+
mipmaps:
|
|
8
|
+
mipMapMode: 0
|
|
9
|
+
enableMipMap: 1
|
|
10
|
+
sRGBTexture: 1
|
|
11
|
+
linearTexture: 0
|
|
12
|
+
fadeOut: 0
|
|
13
|
+
borderMipMap: 0
|
|
14
|
+
mipMapsPreserveCoverage: 0
|
|
15
|
+
alphaTestReferenceValue: 0.5
|
|
16
|
+
mipMapFadeDistanceStart: 1
|
|
17
|
+
mipMapFadeDistanceEnd: 3
|
|
18
|
+
bumpmap:
|
|
19
|
+
convertToNormalMap: 0
|
|
20
|
+
externalNormalMap: 0
|
|
21
|
+
heightScale: 0.25
|
|
22
|
+
normalMapFilter: 0
|
|
23
|
+
isReadable: 0
|
|
24
|
+
streamingMipmaps: 0
|
|
25
|
+
streamingMipmapsPriority: 0
|
|
26
|
+
vTOnly: 0
|
|
27
|
+
ignoreMasterTextureLimit: 0
|
|
28
|
+
grayScaleToAlpha: 0
|
|
29
|
+
generateCubemap: 6
|
|
30
|
+
cubemapConvolution: 0
|
|
31
|
+
seamlessCubemap: 0
|
|
32
|
+
textureFormat: 1
|
|
33
|
+
maxTextureSize: 2048
|
|
34
|
+
textureSettings:
|
|
35
|
+
serializedVersion: 2
|
|
36
|
+
filterMode: 1
|
|
37
|
+
aniso: 1
|
|
38
|
+
mipBias: 0
|
|
39
|
+
wrapU: 1
|
|
40
|
+
wrapV: 1
|
|
41
|
+
wrapW: 1
|
|
42
|
+
nPOTScale: 0
|
|
43
|
+
lightmap: 0
|
|
44
|
+
compressionQuality: 50
|
|
45
|
+
spriteMode: 1
|
|
46
|
+
spriteExtrude: 1
|
|
47
|
+
spriteMeshType: 1
|
|
48
|
+
alignment: 0
|
|
49
|
+
spritePivot: {x: 0.5, y: 0.5}
|
|
50
|
+
spritePixelsToUnits: 100
|
|
51
|
+
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
|
52
|
+
spriteGenerateFallbackPhysicsShape: 1
|
|
53
|
+
alphaUsage: 1
|
|
54
|
+
alphaIsTransparency: 1
|
|
55
|
+
spriteTessellationDetail: -1
|
|
56
|
+
textureType: 8
|
|
57
|
+
textureShape: 1
|
|
58
|
+
singleChannelComponent: 0
|
|
59
|
+
flipbookRows: 1
|
|
60
|
+
flipbookColumns: 1
|
|
61
|
+
maxTextureSizeSet: 0
|
|
62
|
+
compressionQualitySet: 0
|
|
63
|
+
textureFormatSet: 0
|
|
64
|
+
ignorePngGamma: 0
|
|
65
|
+
applyGammaDecoding: 0
|
|
66
|
+
cookieLightType: 0
|
|
67
|
+
platformSettings:
|
|
68
|
+
- serializedVersion: 3
|
|
69
|
+
buildTarget: DefaultTexturePlatform
|
|
70
|
+
maxTextureSize: 2048
|
|
71
|
+
resizeAlgorithm: 0
|
|
72
|
+
textureFormat: -1
|
|
73
|
+
textureCompression: 1
|
|
74
|
+
compressionQuality: 50
|
|
75
|
+
crunchedCompression: 0
|
|
76
|
+
allowsAlphaSplitting: 0
|
|
77
|
+
overridden: 0
|
|
78
|
+
androidETC2FallbackOverride: 0
|
|
79
|
+
forceMaximumCompressionQuality_BC6H_BC7: 0
|
|
80
|
+
- serializedVersion: 3
|
|
81
|
+
buildTarget: Standalone
|
|
82
|
+
maxTextureSize: 2048
|
|
83
|
+
resizeAlgorithm: 0
|
|
84
|
+
textureFormat: -1
|
|
85
|
+
textureCompression: 1
|
|
86
|
+
compressionQuality: 50
|
|
87
|
+
crunchedCompression: 0
|
|
88
|
+
allowsAlphaSplitting: 0
|
|
89
|
+
overridden: 0
|
|
90
|
+
androidETC2FallbackOverride: 0
|
|
91
|
+
forceMaximumCompressionQuality_BC6H_BC7: 0
|
|
92
|
+
- serializedVersion: 3
|
|
93
|
+
buildTarget: Server
|
|
94
|
+
maxTextureSize: 2048
|
|
95
|
+
resizeAlgorithm: 0
|
|
96
|
+
textureFormat: -1
|
|
97
|
+
textureCompression: 1
|
|
98
|
+
compressionQuality: 50
|
|
99
|
+
crunchedCompression: 0
|
|
100
|
+
allowsAlphaSplitting: 0
|
|
101
|
+
overridden: 0
|
|
102
|
+
androidETC2FallbackOverride: 0
|
|
103
|
+
forceMaximumCompressionQuality_BC6H_BC7: 0
|
|
104
|
+
- serializedVersion: 3
|
|
105
|
+
buildTarget: Android
|
|
106
|
+
maxTextureSize: 2048
|
|
107
|
+
resizeAlgorithm: 0
|
|
108
|
+
textureFormat: -1
|
|
109
|
+
textureCompression: 1
|
|
110
|
+
compressionQuality: 50
|
|
111
|
+
crunchedCompression: 0
|
|
112
|
+
allowsAlphaSplitting: 0
|
|
113
|
+
overridden: 0
|
|
114
|
+
androidETC2FallbackOverride: 0
|
|
115
|
+
forceMaximumCompressionQuality_BC6H_BC7: 0
|
|
116
|
+
spriteSheet:
|
|
117
|
+
serializedVersion: 2
|
|
118
|
+
sprites: []
|
|
119
|
+
outline: []
|
|
120
|
+
physicsShape: []
|
|
121
|
+
bones: []
|
|
122
|
+
spriteID: 0b1370abfc5b4c3b81bf007ca6b9664a
|
|
123
|
+
internalID: 0
|
|
124
|
+
vertices: []
|
|
125
|
+
indices:
|
|
126
|
+
edges: []
|
|
127
|
+
weights: []
|
|
128
|
+
secondaryTextures: []
|
|
129
|
+
nameFileIdTable: {}
|
|
130
|
+
spritePackingTag:
|
|
131
|
+
pSDRemoveMatte: 0
|
|
132
|
+
pSDShowRemoveMatteOption: 0
|
|
133
|
+
userData:
|
|
134
|
+
assetBundleName:
|
|
135
|
+
assetBundleVariant:
|
|
Binary file
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
fileFormatVersion: 2
|
|
2
|
+
guid: 5a08d920469e4ee0a87a745623583807
|
|
3
|
+
TextureImporter:
|
|
4
|
+
internalIDToNameTable: []
|
|
5
|
+
externalObjects: {}
|
|
6
|
+
serializedVersion: 12
|
|
7
|
+
mipmaps:
|
|
8
|
+
mipMapMode: 0
|
|
9
|
+
enableMipMap: 1
|
|
10
|
+
sRGBTexture: 1
|
|
11
|
+
linearTexture: 0
|
|
12
|
+
fadeOut: 0
|
|
13
|
+
borderMipMap: 0
|
|
14
|
+
mipMapsPreserveCoverage: 0
|
|
15
|
+
alphaTestReferenceValue: 0.5
|
|
16
|
+
mipMapFadeDistanceStart: 1
|
|
17
|
+
mipMapFadeDistanceEnd: 3
|
|
18
|
+
bumpmap:
|
|
19
|
+
convertToNormalMap: 0
|
|
20
|
+
externalNormalMap: 0
|
|
21
|
+
heightScale: 0.25
|
|
22
|
+
normalMapFilter: 0
|
|
23
|
+
isReadable: 0
|
|
24
|
+
streamingMipmaps: 0
|
|
25
|
+
streamingMipmapsPriority: 0
|
|
26
|
+
vTOnly: 0
|
|
27
|
+
ignoreMasterTextureLimit: 0
|
|
28
|
+
grayScaleToAlpha: 0
|
|
29
|
+
generateCubemap: 6
|
|
30
|
+
cubemapConvolution: 0
|
|
31
|
+
seamlessCubemap: 0
|
|
32
|
+
textureFormat: 1
|
|
33
|
+
maxTextureSize: 2048
|
|
34
|
+
textureSettings:
|
|
35
|
+
serializedVersion: 2
|
|
36
|
+
filterMode: 1
|
|
37
|
+
aniso: 1
|
|
38
|
+
mipBias: 0
|
|
39
|
+
wrapU: 1
|
|
40
|
+
wrapV: 1
|
|
41
|
+
wrapW: 0
|
|
42
|
+
nPOTScale: 0
|
|
43
|
+
lightmap: 0
|
|
44
|
+
compressionQuality: 50
|
|
45
|
+
spriteMode: 1
|
|
46
|
+
spriteExtrude: 1
|
|
47
|
+
spriteMeshType: 1
|
|
48
|
+
alignment: 0
|
|
49
|
+
spritePivot: {x: 0.5, y: 0.5}
|
|
50
|
+
spritePixelsToUnits: 100
|
|
51
|
+
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
|
52
|
+
spriteGenerateFallbackPhysicsShape: 1
|
|
53
|
+
alphaUsage: 1
|
|
54
|
+
alphaIsTransparency: 1
|
|
55
|
+
spriteTessellationDetail: -1
|
|
56
|
+
textureType: 8
|
|
57
|
+
textureShape: 1
|
|
58
|
+
singleChannelComponent: 0
|
|
59
|
+
flipbookRows: 1
|
|
60
|
+
flipbookColumns: 1
|
|
61
|
+
maxTextureSizeSet: 0
|
|
62
|
+
compressionQualitySet: 0
|
|
63
|
+
textureFormatSet: 0
|
|
64
|
+
ignorePngGamma: 0
|
|
65
|
+
applyGammaDecoding: 1
|
|
66
|
+
cookieLightType: 1
|
|
67
|
+
platformSettings:
|
|
68
|
+
- serializedVersion: 3
|
|
69
|
+
buildTarget: DefaultTexturePlatform
|
|
70
|
+
maxTextureSize: 2048
|
|
71
|
+
resizeAlgorithm: 0
|
|
72
|
+
textureFormat: -1
|
|
73
|
+
textureCompression: 1
|
|
74
|
+
compressionQuality: 50
|
|
75
|
+
crunchedCompression: 0
|
|
76
|
+
allowsAlphaSplitting: 0
|
|
77
|
+
overridden: 0
|
|
78
|
+
androidETC2FallbackOverride: 0
|
|
79
|
+
forceMaximumCompressionQuality_BC6H_BC7: 0
|
|
80
|
+
- serializedVersion: 3
|
|
81
|
+
buildTarget: Standalone
|
|
82
|
+
maxTextureSize: 2048
|
|
83
|
+
resizeAlgorithm: 0
|
|
84
|
+
textureFormat: -1
|
|
85
|
+
textureCompression: 1
|
|
86
|
+
compressionQuality: 50
|
|
87
|
+
crunchedCompression: 0
|
|
88
|
+
allowsAlphaSplitting: 0
|
|
89
|
+
overridden: 0
|
|
90
|
+
androidETC2FallbackOverride: 0
|
|
91
|
+
forceMaximumCompressionQuality_BC6H_BC7: 0
|
|
92
|
+
- serializedVersion: 3
|
|
93
|
+
buildTarget: Server
|
|
94
|
+
maxTextureSize: 2048
|
|
95
|
+
resizeAlgorithm: 0
|
|
96
|
+
textureFormat: -1
|
|
97
|
+
textureCompression: 1
|
|
98
|
+
compressionQuality: 50
|
|
99
|
+
crunchedCompression: 0
|
|
100
|
+
allowsAlphaSplitting: 0
|
|
101
|
+
overridden: 0
|
|
102
|
+
androidETC2FallbackOverride: 0
|
|
103
|
+
forceMaximumCompressionQuality_BC6H_BC7: 0
|
|
104
|
+
- serializedVersion: 3
|
|
105
|
+
buildTarget: Android
|
|
106
|
+
maxTextureSize: 2048
|
|
107
|
+
resizeAlgorithm: 0
|
|
108
|
+
textureFormat: -1
|
|
109
|
+
textureCompression: 1
|
|
110
|
+
compressionQuality: 50
|
|
111
|
+
crunchedCompression: 0
|
|
112
|
+
allowsAlphaSplitting: 0
|
|
113
|
+
overridden: 0
|
|
114
|
+
androidETC2FallbackOverride: 0
|
|
115
|
+
forceMaximumCompressionQuality_BC6H_BC7: 0
|
|
116
|
+
spriteSheet:
|
|
117
|
+
serializedVersion: 2
|
|
118
|
+
sprites: []
|
|
119
|
+
outline: []
|
|
120
|
+
physicsShape: []
|
|
121
|
+
bones: []
|
|
122
|
+
spriteID: dda64ca25ea5446da563ba3807929558
|
|
123
|
+
internalID: 0
|
|
124
|
+
vertices: []
|
|
125
|
+
indices:
|
|
126
|
+
edges: []
|
|
127
|
+
weights: []
|
|
128
|
+
secondaryTextures: []
|
|
129
|
+
nameFileIdTable: {}
|
|
130
|
+
spritePackingTag:
|
|
131
|
+
pSDRemoveMatte: 0
|
|
132
|
+
pSDShowRemoveMatteOption: 0
|
|
133
|
+
userData:
|
|
134
|
+
assetBundleName:
|
|
135
|
+
assetBundleVariant:
|
|
@@ -16,7 +16,7 @@ MonoBehaviour:
|
|
|
16
16
|
- base
|
|
17
17
|
_serializedValidationGUID: 00000000-0000-0000-0000-000000000008
|
|
18
18
|
icon:
|
|
19
|
-
m_AssetGUID:
|
|
19
|
+
m_AssetGUID: a7796303ede2490ea179355045c77b7e
|
|
20
20
|
m_SubObjectName:
|
|
21
21
|
m_SubObjectType:
|
|
22
22
|
m_EditorAssetChanged: 0
|
|
@@ -16,7 +16,7 @@ MonoBehaviour:
|
|
|
16
16
|
- base
|
|
17
17
|
_serializedValidationGUID: 00000000-0000-0000-0000-000000000009
|
|
18
18
|
icon:
|
|
19
|
-
m_AssetGUID:
|
|
19
|
+
m_AssetGUID: 5a08d920469e4ee0a87a745623583807
|
|
20
20
|
m_SubObjectName:
|
|
21
21
|
m_SubObjectType:
|
|
22
22
|
m_EditorAssetChanged: 0
|
|
@@ -33,6 +33,7 @@ namespace Beamable.Editor.UI.ContentWindow
|
|
|
33
33
|
private int _lastManifestChangedCount;
|
|
34
34
|
private int _lastProgressUpdateVersion;
|
|
35
35
|
private EditorGUISplitView _mainSplitter;
|
|
36
|
+
private bool _importingDefaultContent;
|
|
36
37
|
|
|
37
38
|
static ContentWindow()
|
|
38
39
|
{
|
|
@@ -215,8 +216,20 @@ namespace Beamable.Editor.UI.ContentWindow
|
|
|
215
216
|
return;
|
|
216
217
|
}
|
|
217
218
|
|
|
218
|
-
|
|
219
|
-
|
|
219
|
+
if (_importingDefaultContent)
|
|
220
|
+
{
|
|
221
|
+
DrawBlockLoading("Importing default content...");
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (ShouldShowDefaultContentPrompt())
|
|
226
|
+
{
|
|
227
|
+
DrawDefaultContentPrompt();
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
|
|
220
233
|
EditorGUILayout.BeginVertical();
|
|
221
234
|
_horizontalScrollPosition = EditorGUILayout.BeginScrollView(_horizontalScrollPosition);
|
|
222
235
|
|
|
@@ -356,6 +369,91 @@ namespace Beamable.Editor.UI.ContentWindow
|
|
|
356
369
|
}
|
|
357
370
|
}
|
|
358
371
|
|
|
372
|
+
/// <summary>
|
|
373
|
+
/// Whether to offer the opt-in default-content import. Only shown when the realm's remote
|
|
374
|
+
/// manifest is confirmed empty (not merely still loading or errored), there is no content
|
|
375
|
+
/// at all yet, and the user hasn't dismissed the prompt for this realm.
|
|
376
|
+
/// </summary>
|
|
377
|
+
private bool ShouldShowDefaultContentPrompt()
|
|
378
|
+
{
|
|
379
|
+
if (_contentService == null)
|
|
380
|
+
return false;
|
|
381
|
+
if (!_contentService.RemoteManifestsLoaded || _contentService.RemoteManifestsErrored)
|
|
382
|
+
return false;
|
|
383
|
+
if (_contentService.RemoteManifestCount > 0)
|
|
384
|
+
return false;
|
|
385
|
+
if (_contentService.EntriesCache.Count > 0)
|
|
386
|
+
return false;
|
|
387
|
+
|
|
388
|
+
var cid = _cli?.CurrentRealm?.Cid;
|
|
389
|
+
var pid = _cli?.CurrentRealm?.Pid;
|
|
390
|
+
if (string.IsNullOrEmpty(cid) || string.IsNullOrEmpty(pid))
|
|
391
|
+
return false;
|
|
392
|
+
|
|
393
|
+
return !DefaultContentImporter.IsDismissed(cid, pid);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
private void DrawDefaultContentPrompt()
|
|
397
|
+
{
|
|
398
|
+
EditorGUILayout.BeginVertical(new GUIStyle(EditorStyles.helpBox)
|
|
399
|
+
{
|
|
400
|
+
padding = new RectOffset(12, 12, 12, 12),
|
|
401
|
+
margin = new RectOffset(10, 10, 10, 10)
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
EditorGUILayout.TextArea(
|
|
405
|
+
"This realm doesn't have any content yet. " +
|
|
406
|
+
"\n\n" +
|
|
407
|
+
"Would you like to import Beamable's default content? This creates the gems and coins " +
|
|
408
|
+
"currencies and copies their icon sprites into Assets/Beamable/DefaultAssets, " +
|
|
409
|
+
"registering them as Addressables. The content is added locally so you can review and " +
|
|
410
|
+
"publish it yourself.",
|
|
411
|
+
new GUIStyle(EditorStyles.label) { wordWrap = true });
|
|
412
|
+
|
|
413
|
+
EditorGUILayout.BeginHorizontal(new GUIStyle
|
|
414
|
+
{
|
|
415
|
+
margin = new RectOffset(0, 0, 12, 12)
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
EditorGUILayout.Space(5, true);
|
|
419
|
+
EditorGUILayout.Space(5, true);
|
|
420
|
+
|
|
421
|
+
var clickedNotNow = BeamGUI.CancelButton("Not now");
|
|
422
|
+
var clickedImport = BeamGUI.PrimaryButton(new GUIContent("Import"));
|
|
423
|
+
|
|
424
|
+
EditorGUILayout.EndHorizontal();
|
|
425
|
+
EditorGUILayout.EndVertical();
|
|
426
|
+
|
|
427
|
+
if (clickedNotNow)
|
|
428
|
+
{
|
|
429
|
+
DefaultContentImporter.SetDismissed(_cli?.CurrentRealm?.Cid, _cli?.CurrentRealm?.Pid);
|
|
430
|
+
Repaint();
|
|
431
|
+
}
|
|
432
|
+
else if (clickedImport)
|
|
433
|
+
{
|
|
434
|
+
StartDefaultContentImport();
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
private async void StartDefaultContentImport()
|
|
439
|
+
{
|
|
440
|
+
if (_importingDefaultContent)
|
|
441
|
+
return;
|
|
442
|
+
|
|
443
|
+
_importingDefaultContent = true;
|
|
444
|
+
Repaint();
|
|
445
|
+
try
|
|
446
|
+
{
|
|
447
|
+
// Awaited continuations resume on Unity's main-thread synchronization context.
|
|
448
|
+
await DefaultContentImporter.ImportDefaultContent();
|
|
449
|
+
}
|
|
450
|
+
finally
|
|
451
|
+
{
|
|
452
|
+
_importingDefaultContent = false;
|
|
453
|
+
Repaint();
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
359
457
|
private List<LocalContentManifestEntry> GetCachedManifestEntries()
|
|
360
458
|
{
|
|
361
459
|
var localContentManifestEntries = new List<LocalContentManifestEntry>();
|