Skip to content

Commit 72a2808

Browse files
authored
Fixes for duplicate and saving assets, resize listener (microsoft#7536)
* Save before opening assets editor, build assets before exiting * Resize listener for image/tilemap/animation editors * Clean up duplication code * Use asset ID to get selected asset * Add create animation button to dialog
1 parent 4e2321b commit 72a2808

8 files changed

Lines changed: 51 additions & 33 deletions

File tree

pxtlib/tilemap.ts

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ namespace pxt {
373373
return this.state.animations.add(newAnimation);
374374
}
375375

376-
public createNewAnimationFromData(frames: pxt.sprite.BitmapData[], interval = 500) {
376+
public createNewAnimationFromData(frames: pxt.sprite.BitmapData[], interval = 500, displayName?: string) {
377377
const id = this.generateNewID(AssetType.Animation, pxt.sprite.ANIMATION_PREFIX, pxt.sprite.ANIMATION_NAMESPACE);
378378

379379
const newAnimation: Animation = {
@@ -382,7 +382,7 @@ namespace pxt {
382382
type: AssetType.Animation,
383383
frames,
384384
interval,
385-
meta: {},
385+
meta: { displayName },
386386
};
387387
return this.state.animations.add(newAnimation);
388388
}
@@ -891,27 +891,21 @@ namespace pxt {
891891
public duplicateAsset(asset: Asset): Asset;
892892
public duplicateAsset(asset: Asset) {
893893
this.onChange();
894-
const newAsset = cloneAsset(asset);
895-
newAsset.internalID = this.getNewInternalId();
896-
const id = newAsset.id.substr(newAsset.id.lastIndexOf(".") + 1).replace(/\d*$/, "");
897-
if (!newAsset.meta?.displayName) {
898-
if (!newAsset.meta) newAsset.meta = {};
899-
newAsset.meta.displayName = id;
900-
}
894+
const clone = cloneAsset(asset);
895+
const displayName = clone.meta?.displayName;
901896

902-
switch (newAsset.type) {
897+
let newAsset: pxt.Asset;
898+
switch (asset.type) {
903899
case AssetType.Image:
904-
newAsset.id = this.generateNewID(AssetType.Image, id, pxt.sprite.IMAGES_NAMESPACE);
905-
this.state.images.add(newAsset); break;
900+
newAsset = this.createNewProjectImage((clone as pxt.ProjectImage).bitmap, displayName); break;
906901
case AssetType.Tile:
907-
newAsset.id = this.generateNewID(AssetType.Tile, id, pxt.sprite.TILE_NAMESPACE);
908-
this.state.tiles.add(newAsset); break;
902+
newAsset = this.createNewTile((clone as pxt.Tile).bitmap, null, displayName); break;
909903
case AssetType.Tilemap:
910-
newAsset.id = this.generateNewID(AssetType.Tilemap, id);
911-
this.state.tilemaps.add(newAsset); break;
904+
const [id, tilemap] = this.createNewTilemapFromData((clone as pxt.ProjectTilemap).data, displayName);
905+
newAsset = this.getTilemap(id);
906+
break;
912907
case AssetType.Animation:
913-
newAsset.id = this.generateNewID(AssetType.Animation, id);
914-
this.state.animations.add(newAsset); break;
908+
newAsset = this.createNewAnimationFromData((clone as pxt.Animation).frames, (clone as pxt.Animation).interval, displayName)
915909
}
916910
return newAsset;
917911
}

webapp/src/app.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ export class ProjectView
518518
if (!mainEditorPkg.lookupFile("this/" + pxt.ASSETS_FILE)) {
519519
mainEditorPkg.setFile(pxt.ASSETS_FILE, "\n", true);
520520
}
521-
this.setFile(pkg.mainEditorPkg().lookupFile(`this/${pxt.ASSETS_FILE}`));
521+
this.saveFileAsync().then(() => this.setFile(pkg.mainEditorPkg().lookupFile(`this/${pxt.ASSETS_FILE}`)));
522522
}
523523

524524
openSettings() {
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as actions from './types'
22
import { GalleryView } from '../store/assetEditorReducer';
33

4-
export const dispatchChangeSelectedAsset = (asset: pxt.Asset) => ({ type: actions.CHANGE_SELECTED_ASSET, asset });
4+
export const dispatchChangeSelectedAsset = (assetType?: pxt.AssetType, assetId?: string) => ({ type: actions.CHANGE_SELECTED_ASSET, assetType, assetId });
55
export const dispatchChangeGalleryView = (view: GalleryView) => ({ type: actions.CHANGE_GALLERY_VIEW, view });
66
export const dispatchUpdateUserAssets = () => ({ type: actions.UPDATE_USER_ASSETS });

webapp/src/components/assetEditor/assetCard.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { AssetPreview } from "./assetPreview";
1010
interface AssetCardProps {
1111
asset: pxt.Asset;
1212
selected?: boolean;
13-
dispatchChangeSelectedAsset: (asset: pxt.Asset) => void;
13+
dispatchChangeSelectedAsset: (assetType?: pxt.AssetType, assetId?: string) => void;
1414
}
1515

1616
class AssetCardImpl extends React.Component<AssetCardProps> {
@@ -29,7 +29,8 @@ class AssetCardImpl extends React.Component<AssetCardProps> {
2929
}
3030

3131
clickHandler = () => {
32-
this.props.dispatchChangeSelectedAsset(this.props.asset);
32+
const { type, id } = this.props.asset;
33+
this.props.dispatchChangeSelectedAsset(type, id);
3334
}
3435

3536
render() {

webapp/src/components/assetEditor/assetGallery.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ class AssetGalleryImpl extends React.Component<AssetGalleryProps, AssetGallerySt
5252
case pxt.AssetType.Tilemap:
5353
project.createNewTilemapFromData(result.data, name); break;
5454
case pxt.AssetType.Animation:
55-
project.createNewAnimationFromData(result.data, name); break;
55+
project.createNewAnimationFromData(result.frames, result.interval, name); break;
5656
}
5757
pkg.mainEditorPkg().buildAssetsAsync()
5858
.then(() => this.props.dispatchUpdateUserAssets());
@@ -101,7 +101,8 @@ class AssetGalleryImpl extends React.Component<AssetGalleryProps, AssetGallerySt
101101
const actions: sui.ModalButton[] = [
102102
{ label: lf("Image"), onclick: this.getCreateAssetHandler(pxt.AssetType.Image) },
103103
{ label: lf("Tile"), onclick: this.getCreateAssetHandler(pxt.AssetType.Tile) },
104-
{ label: lf("Tilemap"), onclick: this.getCreateAssetHandler(pxt.AssetType.Tilemap) }
104+
{ label: lf("Tilemap"), onclick: this.getCreateAssetHandler(pxt.AssetType.Tilemap) },
105+
{ label: lf("Animation"), onclick: this.getCreateAssetHandler(pxt.AssetType.Animation) }
105106
]
106107

107108
return <div className="asset-editor-gallery">

webapp/src/components/assetEditor/assetSidebar.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ interface AssetSidebarProps {
1818
isGalleryAsset?: boolean;
1919
showAssetFieldView?: (asset: pxt.Asset, cb: (result: any) => void) => void;
2020
dispatchChangeGalleryView: (view: GalleryView) => void;
21-
dispatchChangeSelectedAsset: (asset: pxt.Asset) => void;
21+
dispatchChangeSelectedAsset: (assetType?: pxt.AssetType, assetId?: string) => void;
2222
dispatchUpdateUserAssets: () => void;
2323
}
2424

@@ -73,9 +73,10 @@ class AssetSidebarImpl extends React.Component<AssetSidebarProps, AssetSidebarSt
7373
return details;
7474
}
7575

76-
protected updateAssets(): void {
76+
protected updateAssets(select?: pxt.Asset): void {
7777
pkg.mainEditorPkg().buildAssetsAsync()
78-
.then(() => this.props.dispatchUpdateUserAssets());
78+
.then(() => this.props.dispatchUpdateUserAssets())
79+
.then(() => select && this.props.dispatchChangeSelectedAsset(select.type, select.id));
7980
}
8081

8182
protected editAssetHandler = () => {
@@ -93,10 +94,9 @@ class AssetSidebarImpl extends React.Component<AssetSidebarProps, AssetSidebarSt
9394
protected duplicateAssetHandler = () => {
9495
const project = pxt.react.getTilemapProject();
9596
project.pushUndo();
96-
const newAsset = project.duplicateAsset(this.props.asset);
97-
this.props.dispatchChangeSelectedAsset(newAsset);
97+
const asset = project.duplicateAsset(this.props.asset);
9898
this.props.dispatchChangeGalleryView(GalleryView.User);
99-
this.updateAssets();
99+
this.updateAssets(asset);
100100
}
101101

102102
protected copyAssetHandler = () => {
@@ -132,7 +132,7 @@ class AssetSidebarImpl extends React.Component<AssetSidebarProps, AssetSidebarSt
132132
const project = pxt.react.getTilemapProject();
133133
project.pushUndo();
134134
project.removeAsset(this.props.asset);
135-
this.props.dispatchChangeSelectedAsset(null);
135+
this.props.dispatchChangeSelectedAsset();
136136
this.props.dispatchChangeGalleryView(GalleryView.User);
137137
this.updateAssets();
138138
}

webapp/src/components/assetEditor/editor.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import * as React from "react";
44
import * as pkg from "../../package";
55
import * as compiler from "../../compiler";
6+
import * as blocklyFieldView from "../../blocklyFieldView";
67

78
import { Provider } from 'react-redux';
89
import store from './store/assetEditorStore'
@@ -27,6 +28,7 @@ export class AssetEditor extends Editor {
2728

2829
loadFileAsync(file: pkg.File, hc?: boolean): Promise<void> {
2930
// force refresh to ensure we have a view
31+
3032
return super.loadFileAsync(file, hc)
3133
.then(() => compiler.getBlocksAsync()) // make sure to load block definitions
3234
.then(info => {
@@ -37,6 +39,10 @@ export class AssetEditor extends Editor {
3739
.then(() => this.parent.forceUpdate());
3840
}
3941

42+
unloadFileAsync(): Promise<void> {
43+
return pkg.mainEditorPkg().buildAssetsAsync();
44+
}
45+
4046
undo() {
4147
pxt.react.getTilemapProject().undo();
4248
store.dispatch(dispatchUpdateUserAssets());
@@ -47,6 +53,16 @@ export class AssetEditor extends Editor {
4753
store.dispatch(dispatchUpdateUserAssets());
4854
}
4955

56+
57+
resize(e?: Event) {
58+
blocklyFieldView.setEditorBounds({
59+
top: 0,
60+
left: 0,
61+
width: window.innerWidth,
62+
height: window.innerHeight
63+
});
64+
}
65+
5066
display(): JSX.Element {
5167
return <Provider store={store}>
5268
<div className="asset-editor-outer">

webapp/src/components/assetEditor/store/assetEditorReducer.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ const topReducer = (state: AssetEditorState = initialState, action: any): AssetE
2121
case actions.CHANGE_SELECTED_ASSET:
2222
return {
2323
...state,
24-
selectedAsset: action.asset
24+
selectedAsset: getSelectedAsset(state.assets, action.assetType, action.assetId)
2525
};
2626
case actions.CHANGE_GALLERY_VIEW:
2727
return {
2828
...state,
2929
view: action.view
3030
};
3131
case actions.UPDATE_USER_ASSETS:
32-
const assets = getUserAssets()
32+
const assets = getUserAssets();
3333
return {
3434
...state,
3535
selectedAsset: state.selectedAsset ? assets.find(el => el.id == state.selectedAsset.id) : undefined,
@@ -44,6 +44,12 @@ function compareInternalId(a: pxt.Asset, b: pxt.Asset) {
4444
return a.internalID - b.internalID;
4545
}
4646

47+
function getSelectedAsset(assets: pxt.Asset[], type: pxt.AssetType, id: string) {
48+
if (!type || !id) return undefined;
49+
50+
return assets.find(el => el.type == type && el.id == id);
51+
}
52+
4753
function getUserAssets() {
4854
const project = pxt.react.getTilemapProject();
4955
const imgConv = new pxt.ImageConverter();

0 commit comments

Comments
 (0)