added asset workspace working with packer
This commit is contained in:
parent
1506858b25
commit
1f6df50f09
@ -145,6 +145,7 @@ public enum I18n {
|
||||
ASSETS_INPUTS_EMPTY("assets.inputs.empty"),
|
||||
ASSETS_DIAGNOSTICS_EMPTY("assets.diagnostics.empty"),
|
||||
ASSETS_PREVIEW_EMPTY("assets.preview.empty"),
|
||||
ASSETS_PREVIEW_ZOOM("assets.preview.zoom"),
|
||||
ASSETS_PREVIEW_TEXT_ERROR("assets.preview.textError"),
|
||||
ASSETS_PREVIEW_IMAGE_ERROR("assets.preview.imageError"),
|
||||
ASSETS_PREVIEW_AUDIO_PLACEHOLDER("assets.preview.audioPlaceholder"),
|
||||
|
||||
@ -9,11 +9,11 @@ public final class AssetNavigatorProjectionBuilder {
|
||||
|
||||
public static AssetNavigatorProjection build(
|
||||
List<AssetWorkspaceAssetSummary> assets,
|
||||
Path assetsRoot,
|
||||
Path projectRoot,
|
||||
String searchQuery,
|
||||
Set<AssetNavigatorFilter> filters) {
|
||||
Objects.requireNonNull(assets, "assets");
|
||||
final Path normalizedAssetsRoot = Objects.requireNonNull(assetsRoot, "assetsRoot").toAbsolutePath().normalize();
|
||||
final Path normalizedProjectRoot = Objects.requireNonNull(projectRoot, "projectRoot").toAbsolutePath().normalize();
|
||||
final String normalizedQuery = normalizeQuery(searchQuery);
|
||||
final Set<AssetNavigatorFilter> normalizedFilters = filters == null || filters.isEmpty()
|
||||
? EnumSet.noneOf(AssetNavigatorFilter.class)
|
||||
@ -21,10 +21,10 @@ public final class AssetNavigatorProjectionBuilder {
|
||||
|
||||
final Map<String, List<AssetWorkspaceAssetSummary>> grouped = new LinkedHashMap<>();
|
||||
for (AssetWorkspaceAssetSummary asset : assets) {
|
||||
if (!matchesFilters(asset, normalizedFilters) || !matchesQuery(asset, normalizedAssetsRoot, normalizedQuery)) {
|
||||
if (!matchesFilters(asset, normalizedFilters) || !matchesQuery(asset, normalizedProjectRoot, normalizedQuery)) {
|
||||
continue;
|
||||
}
|
||||
grouped.computeIfAbsent(groupLabel(asset, normalizedAssetsRoot), ignored -> new ArrayList<>())
|
||||
grouped.computeIfAbsent(groupLabel(asset, normalizedProjectRoot), ignored -> new ArrayList<>())
|
||||
.add(asset);
|
||||
}
|
||||
|
||||
@ -35,8 +35,8 @@ public final class AssetNavigatorProjectionBuilder {
|
||||
return new AssetNavigatorProjection(groups, visibleAssetCount);
|
||||
}
|
||||
|
||||
static String relativeRoot(AssetWorkspaceAssetSummary asset, Path assetsRoot) {
|
||||
return relativize(asset.assetRoot(), assetsRoot).toString().replace('\\', '/');
|
||||
static String relativeRoot(AssetWorkspaceAssetSummary asset, Path projectRoot) {
|
||||
return relativize(asset.assetRoot(), projectRoot).toString().replace('\\', '/');
|
||||
}
|
||||
|
||||
private static boolean matchesFilters(AssetWorkspaceAssetSummary asset, Set<AssetNavigatorFilter> filters) {
|
||||
@ -65,29 +65,29 @@ public final class AssetNavigatorProjectionBuilder {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean matchesQuery(AssetWorkspaceAssetSummary asset, Path assetsRoot, String normalizedQuery) {
|
||||
private static boolean matchesQuery(AssetWorkspaceAssetSummary asset, Path projectRoot, String normalizedQuery) {
|
||||
if (normalizedQuery.isBlank()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final String relativeRoot = relativeRoot(asset, assetsRoot);
|
||||
final String relativeRoot = relativeRoot(asset, projectRoot);
|
||||
return asset.assetName().toLowerCase(Locale.ROOT).contains(normalizedQuery)
|
||||
|| asset.assetFamily().toLowerCase(Locale.ROOT).contains(normalizedQuery)
|
||||
|| relativeRoot.toLowerCase(Locale.ROOT).contains(normalizedQuery);
|
||||
}
|
||||
|
||||
private static String groupLabel(AssetWorkspaceAssetSummary asset, Path assetsRoot) {
|
||||
final Path relativeRoot = relativize(asset.assetRoot(), assetsRoot);
|
||||
private static String groupLabel(AssetWorkspaceAssetSummary asset, Path projectRoot) {
|
||||
final Path relativeRoot = relativize(asset.assetRoot(), projectRoot);
|
||||
final Path parent = relativeRoot.getParent();
|
||||
if (parent == null) {
|
||||
return "assets";
|
||||
return relativeRoot.toString().replace('\\', '/');
|
||||
}
|
||||
return parent.toString().replace('\\', '/');
|
||||
}
|
||||
|
||||
private static Path relativize(Path assetRoot, Path assetsRoot) {
|
||||
private static Path relativize(Path assetRoot, Path projectRoot) {
|
||||
try {
|
||||
return assetsRoot.relativize(assetRoot.toAbsolutePath().normalize());
|
||||
return projectRoot.relativize(assetRoot.toAbsolutePath().normalize());
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
return assetRoot.getFileName();
|
||||
}
|
||||
|
||||
@ -9,24 +9,20 @@ import javafx.scene.control.*;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.layout.*;
|
||||
import p.packer.declarations.PackerAssetDeclarationParser;
|
||||
import p.packer.foundation.PackerWorkspaceFoundation;
|
||||
import p.packer.workspace.FileSystemPackerWorkspaceService;
|
||||
import p.studio.Container;
|
||||
import p.studio.events.*;
|
||||
import p.studio.projects.ProjectReference;
|
||||
import p.studio.utilities.i18n.I18n;
|
||||
import p.studio.workspaces.Workspace;
|
||||
import p.studio.workspaces.WorkspaceId;
|
||||
import p.packer.declarations.PackerAssetDeclarationParser;
|
||||
import p.packer.foundation.PackerWorkspaceFoundation;
|
||||
import p.packer.workspace.FileSystemPackerWorkspaceService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.EnumMap;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public final class AssetWorkspace implements Workspace {
|
||||
@ -46,6 +42,7 @@ public final class AssetWorkspace implements Workspace {
|
||||
private final VBox detailsContent = new VBox(12);
|
||||
private final Label workspaceSummaryLabel = new Label();
|
||||
private final TextArea logsArea = new TextArea();
|
||||
private final ScrollPane detailsScroll = new ScrollPane();
|
||||
|
||||
private final Map<AssetNavigatorFilter, ToggleButton> filterButtons = new EnumMap<>(AssetNavigatorFilter.class);
|
||||
private final EnumSet<AssetNavigatorFilter> activeFilters = EnumSet.noneOf(AssetNavigatorFilter.class);
|
||||
@ -56,6 +53,7 @@ public final class AssetWorkspace implements Workspace {
|
||||
private volatile String detailsErrorMessage;
|
||||
private volatile AssetWorkspaceMutationPreview stagedMutationPreview;
|
||||
private volatile Path selectedPreviewInput;
|
||||
private volatile int selectedPreviewZoom = 1;
|
||||
private String searchQuery = "";
|
||||
|
||||
public AssetWorkspace(ProjectReference projectReference) {
|
||||
@ -167,7 +165,7 @@ public final class AssetWorkspace implements Workspace {
|
||||
detailsTitle.getStyleClass().add("assets-workspace-pane-title");
|
||||
workspaceSummaryLabel.getStyleClass().add("assets-workspace-summary");
|
||||
detailsContent.getStyleClass().add("assets-workspace-details-content");
|
||||
final ScrollPane detailsScroll = new ScrollPane(detailsContent);
|
||||
detailsScroll.setContent(detailsContent);
|
||||
detailsScroll.setFitToWidth(true);
|
||||
detailsScroll.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
|
||||
detailsScroll.getStyleClass().add("assets-workspace-details-scroll");
|
||||
@ -231,6 +229,7 @@ public final class AssetWorkspace implements Workspace {
|
||||
detailsErrorMessage = null;
|
||||
stagedMutationPreview = null;
|
||||
selectedPreviewInput = null;
|
||||
selectedPreviewZoom = 1;
|
||||
setInlineProgress(Container.i18n().text(I18n.ASSETS_PROGRESS_REFRESHING), ProgressBar.INDETERMINATE_PROGRESS, true);
|
||||
appendLog("Assets refresh started.");
|
||||
renderState();
|
||||
@ -268,6 +267,7 @@ public final class AssetWorkspace implements Workspace {
|
||||
detailsErrorMessage = null;
|
||||
stagedMutationPreview = null;
|
||||
selectedPreviewInput = null;
|
||||
selectedPreviewZoom = 1;
|
||||
setInlineProgress(Container.i18n().text(I18n.ASSETS_PROGRESS_LOADING_DETAILS), ProgressBar.INDETERMINATE_PROGRESS, true);
|
||||
appendLog("Loading details for " + selectionKey.stableKey() + ".");
|
||||
renderState();
|
||||
@ -291,6 +291,7 @@ public final class AssetWorkspace implements Workspace {
|
||||
selectedAssetDetails = details;
|
||||
detailsStatus = AssetWorkspaceDetailsStatus.READY;
|
||||
selectedPreviewInput = firstPreviewInput(details);
|
||||
selectedPreviewZoom = 1;
|
||||
setInlineProgress(Container.i18n().text(I18n.ASSETS_PROGRESS_IDLE), 0, false);
|
||||
appendLog("Asset details ready for " + details.summary().assetName() + ".");
|
||||
renderState();
|
||||
@ -319,7 +320,7 @@ public final class AssetWorkspace implements Workspace {
|
||||
case READY -> {
|
||||
final AssetNavigatorProjection projection = AssetNavigatorProjectionBuilder.build(
|
||||
state.assets(),
|
||||
assetsRoot(),
|
||||
projectRoot(),
|
||||
searchQuery,
|
||||
activeFilters);
|
||||
if (projection.isEmpty()) {
|
||||
@ -406,7 +407,7 @@ public final class AssetWorkspace implements Workspace {
|
||||
createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_STATE), summary.state().name().toLowerCase()),
|
||||
createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_ASSET_ID), summary.assetId() == null ? "—" : String.valueOf(summary.assetId())),
|
||||
createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_TYPE), summary.assetFamily()),
|
||||
createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_LOCATION), summary.assetRoot().toString()));
|
||||
createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_LOCATION), projectRelativePath(summary.assetRoot())));
|
||||
return createSection(Container.i18n().text(I18n.ASSETS_SECTION_SUMMARY), content);
|
||||
}
|
||||
|
||||
@ -428,6 +429,7 @@ public final class AssetWorkspace implements Workspace {
|
||||
|
||||
if (selectedPreviewInput == null || !containsInput(details, selectedPreviewInput)) {
|
||||
selectedPreviewInput = firstPreviewInput(details);
|
||||
selectedPreviewZoom = 1;
|
||||
}
|
||||
|
||||
final VBox inputsList = new VBox(8);
|
||||
@ -445,6 +447,7 @@ public final class AssetWorkspace implements Workspace {
|
||||
inputButton.setMaxWidth(Double.MAX_VALUE);
|
||||
inputButton.setOnAction(event -> {
|
||||
selectedPreviewInput = input;
|
||||
selectedPreviewZoom = 1;
|
||||
renderState();
|
||||
});
|
||||
roleBox.getChildren().add(inputButton);
|
||||
@ -565,15 +568,18 @@ public final class AssetWorkspace implements Workspace {
|
||||
final String extension = extensionOf(input);
|
||||
if (isImage(extension)) {
|
||||
try {
|
||||
final Image image = new Image(input.toUri().toString(), true);
|
||||
final Image image = new Image(input.toUri().toString(), false);
|
||||
final ImageView imageView = new ImageView(image);
|
||||
imageView.setPreserveRatio(true);
|
||||
imageView.setFitWidth(420);
|
||||
imageView.setSmooth(false);
|
||||
imageView.getStyleClass().add("assets-details-preview-image");
|
||||
previewBox.getChildren().add(createPreviewZoomBar(image));
|
||||
applyPreviewScale(image, imageView, selectedPreviewZoom);
|
||||
previewBox.getChildren().add(imageView);
|
||||
} catch (RuntimeException runtimeException) {
|
||||
previewBox.getChildren().add(createSectionMessage(Container.i18n().text(I18n.ASSETS_PREVIEW_IMAGE_ERROR)));
|
||||
}
|
||||
previewBox.getChildren().add(createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_LOCATION), input.toString()));
|
||||
previewBox.getChildren().add(createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_LOCATION), projectRelativePath(input)));
|
||||
return previewBox;
|
||||
}
|
||||
|
||||
@ -588,15 +594,78 @@ public final class AssetWorkspace implements Workspace {
|
||||
|
||||
if (isAudio(extension)) {
|
||||
previewBox.getChildren().add(createSectionMessage(Container.i18n().format(I18n.ASSETS_PREVIEW_AUDIO_PLACEHOLDER, input.getFileName().toString())));
|
||||
previewBox.getChildren().add(createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_LOCATION), input.toString()));
|
||||
previewBox.getChildren().add(createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_LOCATION), projectRelativePath(input)));
|
||||
return previewBox;
|
||||
}
|
||||
|
||||
previewBox.getChildren().add(createSectionMessage(Container.i18n().format(I18n.ASSETS_PREVIEW_GENERIC_PLACEHOLDER, input.getFileName().toString())));
|
||||
previewBox.getChildren().add(createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_LOCATION), input.toString()));
|
||||
previewBox.getChildren().add(createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_LOCATION), projectRelativePath(input)));
|
||||
return previewBox;
|
||||
}
|
||||
|
||||
private Node createPreviewZoomBar(Image image) {
|
||||
final HBox zoomBar = new HBox(8);
|
||||
zoomBar.setAlignment(Pos.CENTER_LEFT);
|
||||
zoomBar.getStyleClass().add("assets-details-preview-zoom-bar");
|
||||
|
||||
final Label zoomLabel = new Label(Container.i18n().text(I18n.ASSETS_PREVIEW_ZOOM));
|
||||
zoomLabel.getStyleClass().add("assets-details-preview-zoom-label");
|
||||
zoomBar.getChildren().add(zoomLabel);
|
||||
|
||||
final ToggleGroup zoomGroup = new ToggleGroup();
|
||||
final int maxZoom = maxPreviewZoom(image);
|
||||
for (int zoom : List.of(1, 2, 4, 8)) {
|
||||
final ToggleButton button = new ToggleButton("x" + zoom);
|
||||
button.getStyleClass().add("assets-details-preview-zoom-button");
|
||||
button.setToggleGroup(zoomGroup);
|
||||
button.setSelected(selectedPreviewZoom == zoom);
|
||||
button.setDisable(zoom > maxZoom);
|
||||
button.setOnAction(event -> {
|
||||
selectedPreviewZoom = zoom;
|
||||
renderState();
|
||||
});
|
||||
zoomBar.getChildren().add(button);
|
||||
}
|
||||
return zoomBar;
|
||||
}
|
||||
|
||||
private void applyPreviewScale(Image image, ImageView imageView, int requestedZoom) {
|
||||
final double width = image.getWidth();
|
||||
final double height = image.getHeight();
|
||||
if (width <= 0.0d || height <= 0.0d) {
|
||||
imageView.setFitWidth(420);
|
||||
return;
|
||||
}
|
||||
|
||||
final double scale = previewScale(width, height, requestedZoom);
|
||||
imageView.setFitWidth(Math.max(1.0d, width * scale));
|
||||
imageView.setFitHeight(Math.max(1.0d, height * scale));
|
||||
imageView.setSmooth(false);
|
||||
}
|
||||
|
||||
static double previewScale(double width, double height, int requestedZoom) {
|
||||
final double longestEdge = Math.max(width, height);
|
||||
if (longestEdge <= 0.0d) {
|
||||
return 1.0d;
|
||||
}
|
||||
if (longestEdge > 420.0d) {
|
||||
return 420.0d / longestEdge;
|
||||
}
|
||||
return Math.max(1, Math.min(Math.max(1, requestedZoom), maxPreviewZoom(width, height)));
|
||||
}
|
||||
|
||||
static int maxPreviewZoom(Image image) {
|
||||
return maxPreviewZoom(image.getWidth(), image.getHeight());
|
||||
}
|
||||
|
||||
static int maxPreviewZoom(double width, double height) {
|
||||
final double longestEdge = Math.max(width, height);
|
||||
if (longestEdge <= 0.0d || longestEdge > 420.0d) {
|
||||
return 1;
|
||||
}
|
||||
return Math.max(1, (int) Math.floor(420.0d / longestEdge));
|
||||
}
|
||||
|
||||
private Node createSection(String title, Node content) {
|
||||
final VBox section = new VBox(10);
|
||||
section.getStyleClass().add("assets-details-section");
|
||||
@ -678,7 +747,7 @@ public final class AssetWorkspace implements Workspace {
|
||||
}
|
||||
topLine.getChildren().addAll(icon, name, spacer, badges);
|
||||
|
||||
final Label path = new Label(AssetNavigatorProjectionBuilder.relativeRoot(asset, assetsRoot()));
|
||||
final Label path = new Label(AssetNavigatorProjectionBuilder.relativeRoot(asset, projectRoot()));
|
||||
path.getStyleClass().add("assets-workspace-asset-path");
|
||||
row.getChildren().addAll(topLine, path);
|
||||
row.setOnMouseClicked(event -> selectAsset(asset.selectionKey()));
|
||||
@ -722,10 +791,18 @@ public final class AssetWorkspace implements Workspace {
|
||||
if (selectedAsset == null) {
|
||||
return;
|
||||
}
|
||||
final AssetWorkspaceMutationPreview preview = mutationService.preview(projectReference, selectedAsset, action);
|
||||
stagedMutationPreview = preview;
|
||||
appendLog("Preview ready for " + actionLabel(action) + ".");
|
||||
renderState();
|
||||
try {
|
||||
stagedMutationPreview = mutationService.preview(projectReference, selectedAsset, action);
|
||||
appendLog("Preview ready for " + actionLabel(action) + ".");
|
||||
renderState();
|
||||
Platform.runLater(() -> detailsScroll.setVvalue(1.0d));
|
||||
} catch (RuntimeException runtimeException) {
|
||||
final String message = rootCauseMessage(runtimeException);
|
||||
appendLog("Preview failed: " + message);
|
||||
workspaceBus.publish(new StudioAssetsMutationFailedEvent(projectReference, action, message));
|
||||
stagedMutationPreview = null;
|
||||
renderState();
|
||||
}
|
||||
}
|
||||
|
||||
private Node createStagedMutationPanel(AssetWorkspaceMutationPreview preview) {
|
||||
@ -786,7 +863,7 @@ public final class AssetWorkspace implements Workspace {
|
||||
box.getChildren().add(createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_NAME), preview.asset().assetName()));
|
||||
box.getChildren().add(createKeyValueRow(
|
||||
Container.i18n().text(I18n.ASSETS_LABEL_LOCATION),
|
||||
AssetNavigatorProjectionBuilder.relativeRoot(preview.asset(), assetsRoot())));
|
||||
projectRelativePath(preview.asset().assetRoot())));
|
||||
return box;
|
||||
}
|
||||
|
||||
@ -921,6 +998,19 @@ public final class AssetWorkspace implements Workspace {
|
||||
return projectReference.rootPath().resolve("assets").toAbsolutePath().normalize();
|
||||
}
|
||||
|
||||
private Path projectRoot() {
|
||||
return projectReference.rootPath().toAbsolutePath().normalize();
|
||||
}
|
||||
|
||||
private String projectRelativePath(Path path) {
|
||||
final Path normalizedPath = path.toAbsolutePath().normalize();
|
||||
try {
|
||||
return projectRoot().relativize(normalizedPath).toString().replace('\\', '/');
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
return normalizedPath.toString().replace('\\', '/');
|
||||
}
|
||||
}
|
||||
|
||||
private void setInlineProgress(String message, double progress, boolean visible) {
|
||||
inlineProgressLabel.setText(message);
|
||||
inlineProgressBar.setVisible(visible);
|
||||
|
||||
@ -135,6 +135,7 @@ assets.logs.title=Logs
|
||||
assets.inputs.empty=No previewable inputs are currently declared for this asset.
|
||||
assets.diagnostics.empty=No diagnostics are currently attached to this asset.
|
||||
assets.preview.empty=Select an input to preview it here.
|
||||
assets.preview.zoom=Zoom
|
||||
assets.preview.textError=Unable to read this text-like input for preview.
|
||||
assets.preview.imageError=Unable to decode this image for preview.
|
||||
assets.preview.audioPlaceholder=Audio preview placeholder: {0}
|
||||
|
||||
@ -422,6 +422,29 @@
|
||||
-fx-font-weight: bold;
|
||||
}
|
||||
|
||||
.assets-details-preview-zoom-bar {
|
||||
-fx-alignment: center-left;
|
||||
}
|
||||
|
||||
.assets-details-preview-zoom-label {
|
||||
-fx-text-fill: #9fc3e7;
|
||||
-fx-font-size: 11px;
|
||||
-fx-font-weight: bold;
|
||||
}
|
||||
|
||||
.assets-details-preview-zoom-button {
|
||||
-fx-background-color: #17202a;
|
||||
-fx-text-fill: #e6eff8;
|
||||
-fx-background-radius: 999;
|
||||
-fx-border-radius: 999;
|
||||
-fx-border-color: #2f4053;
|
||||
}
|
||||
|
||||
.assets-details-preview-zoom-button:selected {
|
||||
-fx-background-color: #224160;
|
||||
-fx-border-color: #4f8dc3;
|
||||
}
|
||||
|
||||
.assets-details-preview-text {
|
||||
-fx-control-inner-background: #10161d;
|
||||
-fx-text-fill: #e4edf6;
|
||||
|
||||
@ -11,27 +11,29 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
final class AssetNavigatorProjectionBuilderTest {
|
||||
@Test
|
||||
void groupsAssetsByParentPath() {
|
||||
final Path assetsRoot = Path.of("/tmp/project/assets");
|
||||
final Path projectRoot = Path.of("/tmp/project");
|
||||
final Path assetsRoot = projectRoot.resolve("assets");
|
||||
final AssetNavigatorProjection projection = AssetNavigatorProjectionBuilder.build(
|
||||
List.of(
|
||||
managedAsset(1, "ui_atlas", "image_bank", assetsRoot.resolve("ui/atlas"), true, false),
|
||||
orphanAsset("menu_sounds", "sound_bank", assetsRoot.resolve("audio/menu"), false, false)),
|
||||
assetsRoot,
|
||||
projectRoot,
|
||||
"",
|
||||
EnumSet.noneOf(AssetNavigatorFilter.class));
|
||||
|
||||
assertEquals(2, projection.visibleAssetCount());
|
||||
assertEquals(List.of("audio", "ui"), projection.groups().stream().map(AssetNavigatorGroup::label).sorted().toList());
|
||||
assertEquals(List.of("assets/audio", "assets/ui"), projection.groups().stream().map(AssetNavigatorGroup::label).sorted().toList());
|
||||
}
|
||||
|
||||
@Test
|
||||
void managedAndOrphanFiltersBehaveAsStateFilterSet() {
|
||||
final Path assetsRoot = Path.of("/tmp/project/assets");
|
||||
final Path projectRoot = Path.of("/tmp/project");
|
||||
final Path assetsRoot = projectRoot.resolve("assets");
|
||||
final AssetNavigatorProjection projection = AssetNavigatorProjectionBuilder.build(
|
||||
List.of(
|
||||
managedAsset(1, "ui_atlas", "image_bank", assetsRoot.resolve("ui/atlas"), true, false),
|
||||
orphanAsset("menu_sounds", "sound_bank", assetsRoot.resolve("audio/menu"), false, false)),
|
||||
assetsRoot,
|
||||
projectRoot,
|
||||
"",
|
||||
EnumSet.of(AssetNavigatorFilter.MANAGED));
|
||||
|
||||
@ -41,13 +43,14 @@ final class AssetNavigatorProjectionBuilderTest {
|
||||
|
||||
@Test
|
||||
void diagnosticsAndPreloadActAsAdditionalConstraints() {
|
||||
final Path assetsRoot = Path.of("/tmp/project/assets");
|
||||
final Path projectRoot = Path.of("/tmp/project");
|
||||
final Path assetsRoot = projectRoot.resolve("assets");
|
||||
final AssetNavigatorProjection projection = AssetNavigatorProjectionBuilder.build(
|
||||
List.of(
|
||||
managedAsset(1, "ui_atlas", "image_bank", assetsRoot.resolve("ui/atlas"), true, true),
|
||||
managedAsset(2, "bg_tiles", "image_bank", assetsRoot.resolve("bg/tiles"), true, false),
|
||||
managedAsset(3, "voice_bank", "sound_bank", assetsRoot.resolve("audio/voice"), false, true)),
|
||||
assetsRoot,
|
||||
projectRoot,
|
||||
"",
|
||||
EnumSet.of(AssetNavigatorFilter.MANAGED, AssetNavigatorFilter.PRELOAD, AssetNavigatorFilter.DIAGNOSTICS));
|
||||
|
||||
@ -57,19 +60,20 @@ final class AssetNavigatorProjectionBuilderTest {
|
||||
|
||||
@Test
|
||||
void searchMatchesAssetNameAndPathContext() {
|
||||
final Path assetsRoot = Path.of("/tmp/project/assets");
|
||||
final Path projectRoot = Path.of("/tmp/project");
|
||||
final Path assetsRoot = projectRoot.resolve("assets");
|
||||
final List<AssetWorkspaceAssetSummary> assets = List.of(
|
||||
managedAsset(1, "ui_atlas", "image_bank", assetsRoot.resolve("ui/atlas"), true, false),
|
||||
orphanAsset("menu_sounds", "sound_bank", assetsRoot.resolve("audio/menu"), false, false));
|
||||
|
||||
final AssetNavigatorProjection byName = AssetNavigatorProjectionBuilder.build(
|
||||
assets,
|
||||
assetsRoot,
|
||||
projectRoot,
|
||||
"atlas",
|
||||
EnumSet.noneOf(AssetNavigatorFilter.class));
|
||||
final AssetNavigatorProjection byPath = AssetNavigatorProjectionBuilder.build(
|
||||
assets,
|
||||
assetsRoot,
|
||||
projectRoot,
|
||||
"audio",
|
||||
EnumSet.noneOf(AssetNavigatorFilter.class));
|
||||
|
||||
|
||||
@ -0,0 +1,28 @@
|
||||
package p.studio.workspaces.assets;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
final class AssetWorkspacePreviewScaleTest {
|
||||
@Test
|
||||
void keepsSmallImageAtOriginalScaleByDefault() {
|
||||
assertEquals(1.0d, AssetWorkspace.previewScale(16.0d, 16.0d, 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void appliesIntegerZoomForSmallImages() {
|
||||
assertEquals(8.0d, AssetWorkspace.previewScale(16.0d, 16.0d, 8));
|
||||
}
|
||||
|
||||
@Test
|
||||
void capsZoomOptionsByMaximumPreviewSize() {
|
||||
assertEquals(6, AssetWorkspace.maxPreviewZoom(64.0d, 64.0d));
|
||||
assertEquals(1.0d, AssetWorkspace.previewScale(300.0d, 200.0d, 8));
|
||||
}
|
||||
|
||||
@Test
|
||||
void scalesLargeImagesDownToPreviewLimit() {
|
||||
assertEquals(420.0d / 512.0d, AssetWorkspace.previewScale(512.0d, 128.0d, 1));
|
||||
}
|
||||
}
|
||||
9
test-projects/main/assets/.prometeu/index.json
Normal file
9
test-projects/main/assets/.prometeu/index.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"schema_version" : 1,
|
||||
"next_asset_id" : 2,
|
||||
"assets" : [ {
|
||||
"asset_id" : 1,
|
||||
"asset_uuid" : "67cd978d-cd61-4641-ba9e-98fe4bc039bd",
|
||||
"root" : "ui/atlas-relocated"
|
||||
} ]
|
||||
}
|
||||
8
test-projects/main/assets/ui/atlas-relocated/asset.json
Normal file
8
test-projects/main/assets/ui/atlas-relocated/asset.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"name": "ui_atlas",
|
||||
"type": "image_bank",
|
||||
"inputs": { "sprites": ["sprites/confirm.png"] },
|
||||
"output": { "format": "TILES/indexed_v1", "codec": "RAW" },
|
||||
"preload": { "enabled": true }
|
||||
}
|
||||
BIN
test-projects/main/assets/ui/atlas-relocated/sprites/confirm.png
Normal file
BIN
test-projects/main/assets/ui/atlas-relocated/sprites/confirm.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 137 B |
Loading…
x
Reference in New Issue
Block a user