Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pxteditor/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export * from "./monaco-fields/field_tilemap";
export * from "./monaco-fields/field_musiceditor";
export * from "./monaco-fields/field_soundEffect";
export * from "./monaco-fields/field_sprite";
export * from "./monaco-fields/field_pianoroll";
export * from "./monaco-fields/field_animation";
export * from "./monaco-fields/field_react";

Expand Down
16 changes: 10 additions & 6 deletions pxteditor/monaco-fields/field_musiceditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,7 @@ export class MonacoSongEditor extends MonacoReactFieldEditor<pxt.Song> {
}
let out = pxt.getTSReferenceForAsset(result, this.isPython);
if (!this.isAsset) {
if (this.isPython) {
out = `music.create_song(${out})`;
}
else {
out = `music.createSong(${out})`;
}
out = this.wrapCreateSong(out);
}
return out;
}
Expand All @@ -100,6 +95,15 @@ export class MonacoSongEditor extends MonacoReactFieldEditor<pxt.Song> {
blocksInfo: this.host.blocksInfo()
};
}

protected wrapCreateSong(text: string): string {
if (this.isPython) {
return `music.create_song(${text})`;
}
else {
return `music.createSong(${text})`;
}
}
}

function createFakeAsset(song: pxt.assets.music.Song): pxt.Song {
Expand Down
53 changes: 53 additions & 0 deletions pxteditor/monaco-fields/field_pianoroll.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { MonacoSongEditor } from "./field_musiceditor";
import { registerMonacoFieldEditor } from "./monacoFieldEditor";

const fieldEditorId = "piano-roll-editor";

export class MonacoPianoRollEditor extends MonacoSongEditor {
protected wrapCreateSong(text: string): string {
if (this.isPython) {
return `pianoRoll.create_song(${text})`;
}
else {
return `pianoRoll.createSong(${text})`;
}
}

protected getOptions(): any {
const opts = super.getOptions();
opts.showTimeSignature = true;
opts.showSnapControls = true;
return opts;
}

protected getFieldEditorId() {
return fieldEditorId;
}
}

const regexes = [
// typescript
"pianoRoll\\s*\\.\\s*createSong\\s*\\(\\s*hex`[a-fA-F0-9\\s\\n]*`\\s*\\)",

// python
'pianoRoll\\s*\\.\\s*create_song\\s*\\(\\s*hex\\s*\\(\\s*"""[a-fA-F0-9\\s\\n]*"""\\s*\\)\\s*\\)',
'pianoRoll\\s*\\.\\s*createSong\\s*\\(\\s*hex\\s*\\(\\s*"""[a-fA-F0-9\\s\\n]*"""\\s*\\)\\s*\\)',
];

const searchString = regexes.map(r => `(?:${r})`).join("|");

export const pianoRollEditorDefinition: pxt.editor.MonacoFieldEditorDefinition = {
id: fieldEditorId,
foldMatches: true,
glyphCssClass: "fas fa-music sprite-focus-hover",
heightInPixels: 510,
matcher: {
searchString: searchString,
isRegex: true,
matchCase: true,
matchWholeWord: false
},
proto: MonacoPianoRollEditor
};

registerMonacoFieldEditor(fieldEditorId, pianoRollEditorDefinition);
2 changes: 1 addition & 1 deletion pxtlib/music.ts
Original file line number Diff line number Diff line change
Expand Up @@ -799,7 +799,7 @@ namespace pxt.assets.music {
},

{
name: lf("booming kick"),
name: lf("boom kick"),
startFrequency: 100,
startVolume: 1024,
steps: [{
Expand Down
114 changes: 65 additions & 49 deletions pxtlib/tilemap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -843,8 +843,10 @@ namespace pxt {
* @param skipIDs string[] a list of string ids (block id, asset id, or file name) to ignore
**/
public isAssetUsed(asset: Asset, files?: pxt.Map<{content: string}>, skipIDs?: string[]): boolean {
let blockIds = asset.meta?.blockIDs?.filter(id => !skipIDs || skipIDs?.indexOf(id) < 0) || [];
if (blockIds.length > 0) return true;
if (!asset.meta?.displayName || !files) {
let blockIds = asset.meta?.blockIDs?.filter(id => !skipIDs || skipIDs?.indexOf(id) < 0) || [];
if (blockIds.length > 0) return true;
}

if (asset.type == pxt.AssetType.Tile) {
for (const tm of this.getAssets(AssetType.Tilemap)) {
Expand All @@ -857,74 +859,88 @@ namespace pxt {
}

if (files) {
const config = U.jsonTryParse(files["pxt.json"]?.content) as pxt.PackageConfig;

const filesToCheck: string[] = [];

if (config?.files) {
for (const file of config.files) {
if (file.endsWith(".g.ts")) continue;
if (skipIDs && (skipIDs.indexOf(file) !== -1)) continue;

if (file.endsWith(".ts") && file !== pxt.MAIN_TS || file.endsWith(".py") && file !== pxt.MAIN_PY) {
filesToCheck.push(file);
}
}
}

if (config?.preferredEditor === pxt.BLOCKS_PROJECT_NAME) {
filesToCheck.push(pxt.MAIN_BLOCKS);
}
else if (config?.preferredEditor === pxt.JAVASCRIPT_PROJECT_NAME) {
filesToCheck.push(pxt.MAIN_TS);
}
else if (config?.preferredEditor === pxt.PYTHON_PROJECT_NAME) {
filesToCheck.push(pxt.MAIN_PY);
}

const references: string[] = [];

const shortId = Util.escapeForRegex(getShortIDForAsset(asset));
const displayName = Util.escapeForRegex(asset.meta?.displayName) || "";

let assetTsRefs: string;
switch (asset.type) {
case pxt.AssetType.Tile:
assetTsRefs = `myTiles.${shortId}|assets.tile\`${shortId}\``;
if (displayName) assetTsRefs += `|assets.tile\`${displayName}\``;
break;
case pxt.AssetType.Tilemap:
assetTsRefs = `tilemap\`${shortId}\``;
break;
case pxt.AssetType.Animation:
assetTsRefs = `assets.animation\`${shortId}\``;
if (displayName) assetTsRefs += `|assets.animation\`${displayName}\``;
break;
case pxt.AssetType.Song:
assetTsRefs = `assets.song\`${shortId}\``;
if (displayName) assetTsRefs += `|assets.song\`${displayName}\``;
break;
case pxt.AssetType.Json:
assetTsRefs = `assets.json\`${shortId}\``;
if (displayName) assetTsRefs += `|assets.json\`${displayName}\``;
break;
default:
assetTsRefs = `assets.image\`${shortId}\``;
if (displayName) assetTsRefs += `|assets.image\`${displayName}\``;
break;
const addNamespaceReference = (namespace: string, fun: string, id: string) => {
references.push(`${namespace}\\s*\\.\\s*${fun}\`\\s*${id}\\s*\``);
}
const assetTsRegex = new RegExp(assetTsRefs, "gm");

let assetPyRefs: string;
switch (asset.type) {
case pxt.AssetType.Tile:
assetPyRefs = `myTiles.${shortId}|assets.tile\("""${shortId}"""\)`;
if (displayName) assetPyRefs += `|assets.tile\("""${displayName}"""\)`;
references.push(`myTiles\\s*\\.\\s*${shortId}\\s*`);

addNamespaceReference("assets", "tile", shortId);
if (displayName) addNamespaceReference("assets", "tile", displayName);
break;
case pxt.AssetType.Tilemap:
assetPyRefs = `assets.tilemap\("""${shortId}"""\)`;
references.push(`tilemap\`\\s*${shortId}\\s*\``);
addNamespaceReference("assets", "tilemap", shortId);
if (displayName) {
references.push(`tilemap\`\\s*${displayName}\\s*\``);
addNamespaceReference("assets", "tilemap", displayName);
}
break;
case pxt.AssetType.Animation:
assetPyRefs = `assets.animation\("""${shortId}"""\)`;
if (displayName) assetPyRefs += `|assets.animation\("""${displayName}"""\)`;
addNamespaceReference("assets", "animation", shortId);
if (displayName) addNamespaceReference("assets", "animation", displayName);
break;
case pxt.AssetType.Song:
assetPyRefs = `assets.song\("""${shortId}"""\)`;
if (displayName) assetPyRefs += `|assets.song\("""${displayName}"""\)`;
addNamespaceReference("assets", "song", shortId);
if (displayName) addNamespaceReference("assets", "song", displayName);
break;
case pxt.AssetType.Json:
assetPyRefs = `assets.json\("""${shortId}"""\)`;
if (displayName) assetPyRefs += `|assets.json\("""${displayName}"""\)`;
addNamespaceReference("assets", "json", shortId);
if (displayName) addNamespaceReference("assets", "json", displayName);
break;
default:
assetPyRefs = `assets.image\("""${shortId}"""\)`;
if (displayName) assetPyRefs += `|assets.image\("""${displayName}"""\)`;
addNamespaceReference("assets", "image", shortId);
if (displayName) addNamespaceReference("assets", "image", displayName);
break;
}
const assetPyRegex = new RegExp(assetPyRefs, "gm");

for (let filename of Object.keys(files)) {
if (skipIDs?.indexOf(filename) >= 0) continue;
const regex = new RegExp(references.map(r => `(?:${r})`).join("|"));
const pyRegex = new RegExp(references.map(r => `(?:${r})`).join("|").replace(/`/g, '"""'));

for (const file of filesToCheck) {
const content = files[file].content;

const f = files[filename];
// Match .ts files that are not generated (.g.ts)
if (filename.match(/((?!\.g).{2}|^.{0,1})\.ts$/i)) {
if (f.content.match(assetTsRegex)) return true;
} else if (filename.endsWith(".py")) {
if (f.content.match(assetPyRegex)) return true;
if (file.endsWith(".py")) {
if (pyRegex.test(content)) {
return true;
}
}
else {
if (regex.test(content)) {
return true;
}
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions theme/monaco.less
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

.monacoToolboxDiv {
height: 100%;
/* Prevent large category lists from expanding the page scroll bounds. */
contain: paint;
}

.monacoEditorRightArea {
Expand Down
11 changes: 10 additions & 1 deletion theme/music-editor/gallery.less
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
.image-editor-gallery.song {
display: flex;
flex-direction: column;
flex-wrap: balance;
align-items: center;
align-content: center;
justify-content: unset;
padding: 0.5rem;
Expand All @@ -15,11 +17,12 @@
padding: 0.5rem;
width: 100%;
height: 4rem;
flex-shrink: 0;

background-color: var(--pxt-neutral-background1);
color: var(--pxt-neutral-foreground1);
border-radius: 0.25rem;
max-width: 500px;
max-width: 440px;
gap: 1rem;

.song-gallery-item-name {
Expand Down Expand Up @@ -94,4 +97,10 @@
outline-offset: 5px;
}
}
}

@media @tabletAndBelow {
.image-editor-gallery.song {
flex-wrap: nowrap;
}
}
3 changes: 3 additions & 0 deletions theme/piano-roll/piano-roll.less
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,9 @@
padding-right: 0.25rem;
background-color: var(--white-key-color);
color: var(--key-text-color);
white-space: nowrap;
text-overflow: ellipsis;
overflow-x: hidden;

&.active,
&.playing {
Expand Down
Loading