Skip to content

Commit

Permalink
⚡ Create missing properties and variables when copying Catnip blocks …
Browse files Browse the repository at this point in the history
…from one asset to another (and in other similar cases)
  • Loading branch information
CosmoMyzrailGorynych committed Sep 19, 2024
1 parent 680799b commit f013b1d
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 9 deletions.
74 changes: 71 additions & 3 deletions src/node_requires/catnip/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {getModulePathByName, loadModuleByName} from '../resources/modules';
import {convertFromDtsToBlocks} from './blockUtils';
import {parseFile} from './declarationExtractor';
import {getByPath} from '../i18n';
import {getBehaviorFields} from '../events';

import propsVarsBlocks from './stdLib/propsVars';
import logicBlocks from './stdLib/logic';
Expand Down Expand Up @@ -592,22 +593,89 @@ export const canPaste = (target: blockArgumentType | 'script'): boolean => {
export const paste = (
target: IBlock | BlockScript,
index: number | string,
owningAsset: IScriptable,
owningEvent: IScriptableEvent,
customOptions?: boolean
): void => {
if (Array.isArray(target)) {
if (!canPaste('script')) {
throw new Error('[catnip] Attempt to paste into a script with an invalid clipboard.');
}
target.splice(index as number, 0, ...structuredClone(clipboard!));
}
// Fist step: Find all the used variables and props and match them
// with variables and behaviors' and regular props of the current asset.
// Use behavior props when possible, and add missing props and variables.
const vars = new Set<string>(),
props = new Set<string>();
const behaviorFields = getBehaviorFields(owningAsset);
const convertToBh = new Set<string>();
walkOverScript(clipboard!, block => {
// Filter out visible blocks as props and vars are in a hidden group
if (block.lib !== 'core.hidden') {
return;
}
// Handle behaviors' and regular props
if (block.code === 'property' || block.code === 'behavior property') {
const propName = block.values.variableName as string;
if (behaviorFields.includes(propName)) {
convertToBh.add(propName);
} else {
props.add(propName);
}
} else if (block.code === 'variable') {
// Handle variables
vars.add(block.values.variableName as string);
}
});
// Add missing variables
for (const varName of vars) {
if (!('variables' in owningEvent)) {
owningEvent.variables = [];
}
if (!owningEvent.variables!.includes(varName)) {
owningEvent.variables!.push(varName);
}
}
// Add missing props
for (const propName of props) {
if (!('properties' in owningAsset)) {
owningAsset.properties = [];
}
if (!owningAsset.properties!.includes(propName)) {
owningAsset.properties!.push(propName);
}
}

/**
* @returns A copy with regular properties replaced with behavior properties where possible.
*/
const patchProps = (contents: IBlock | IBlock[]) => {
const copy = structuredClone(contents);
walkOverScript(Array.isArray(copy) ? copy : [copy], block => {
if (block.lib === 'core.hidden' && block.code === 'property') {
if (convertToBh.has(block.values.variableName as string)) {
block.code = 'behavior property';
}
}
});
return copy;
};

// Actually paste stuff
if (Array.isArray(target)) {
target.splice(index as number, 0, ...(patchProps(clipboard!) as IBlock[]));
window.signals.trigger('rerenderCatnipLibrary');
return;
}
const block = target as IBlock;
if (customOptions) {
// eslint-disable-next-line prefer-destructuring
block.customOptions![index as string] = structuredClone(clipboard![0]);
block.customOptions![index as string] = patchProps(clipboard![0]) as IBlock;
} else {
// eslint-disable-next-line prefer-destructuring
block.values[index as string] = structuredClone(clipboard![0]);
block.values[index as string] = patchProps(clipboard![0]) as IBlock;
}
window.signals.trigger('rerenderCatnipLibrary');
};

/*
Expand Down
2 changes: 1 addition & 1 deletion src/node_requires/resources/IScriptable.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@ interface IScriptable extends IAsset {
*/
extendTypes: string;
/** Used for Catnip only */
properties?: [];
properties?: string[];
}
15 changes: 14 additions & 1 deletion src/riotTags/catnip/catnip-block-list.tag
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
//-
@attribute blocks (BlockScript)
Catnip blocks to display in the list
@attribute asset (IScriptable)
The asset that owns these blocks
@attribute scriptableevent (IScriptableEvent)
The catnip event that owns this block
@attribute [placeholder] (Array<IBlockPieceLabel | IBlockPieceIcon>)
Shown when there are no blocks in this list (when opts.blocks is an empty array)
@attribute [showplaceholder] (atomic)
@attribute [readonly] (atomic)
catnip-block-list(
Expand Down Expand Up @@ -32,6 +38,8 @@ catnip-block-list(
oncontextmenu="{parent.onContextMenu}"
ref="blocks"
onclick="{parent.manageSelection}"
asset="{opts.asset}"
scriptableevent="{opts.scriptableevent}"
)
catnip-insert-mark(
if="{!opts.readonly}"
Expand Down Expand Up @@ -259,7 +267,12 @@ catnip-block-list(
label: this.vocGlob.paste,
icon: 'clipboard',
click: () => {
paste(this.opts.blocks, pastePosition);
paste(
this.opts.blocks,
pastePosition,
this.opts.asset,
this.opts.scriptableevent
);
this.update();
}
}]
Expand Down
42 changes: 38 additions & 4 deletions src/riotTags/catnip/catnip-block.tag
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
//-
@attribute block (IBlock)
The block from the block script that is rendered
@attribute asset (IScriptable)
The asset that owns this block
@attribute scriptableevent (IScriptableEvent)
The catnip event that owns this block
@atribute [nodrag] (atomic)
Prohibits dragging this block
@attribute [readonly] (atomic)
Expand Down Expand Up @@ -72,6 +76,8 @@ catnip-block(
showplaceholder="showplaceholder"
placeholder="{piece.placeholder}"
readonly="{parent.opts.readonly}"
asset="{opts.asset}"
scriptableevent="{opts.scriptableevent}"
)
// Options
.catnip-block-Options(if="{piece.type === 'options'}")
Expand All @@ -96,6 +102,8 @@ catnip-block(
ondragend="{parent.onDragEnd}"
oncontextmenu="{parent.onContextMenu}"
onclick="{parent.tryMutate}"
asset="{opts.asset}"
scriptableevent="{opts.scriptableevent}"
)
input.catnip-block-aConstantInput(
ondrop="{parent.onDrop}"
Expand Down Expand Up @@ -157,6 +165,8 @@ catnip-block(
ondragend="{parent.onOptionDragEnd}"
oncontextmenu="{parent.onContextMenu}"
onclick="{parent.tryMutateCustomOption}"
asset="{opts.asset}"
scriptableevent="{opts.scriptableevent}"
)
input.catnip-block-aConstantInput.wildcard(
ondrop="{parent.onOptionDrop}"
Expand Down Expand Up @@ -185,6 +195,8 @@ catnip-block(
ondragend="{parent.onDragEnd}"
oncontextmenu="{parent.onContextMenu}"
onclick="{parent.tryMutate}"
asset="{opts.asset}"
scriptableevent="{opts.scriptableevent}"
)
input.catnip-block-aConstantInput(
ondrop="{parent.onDrop}"
Expand Down Expand Up @@ -513,10 +525,21 @@ catnip-block(
},
click: () => {
if (this.contextOption) {
paste(this.opts.block, this.contextOption, true);
paste(
this.opts.block,
this.contextOption,
this.opts.asset,
this.opts.scriptableevent,
true
);
this.contextOption = false;
} else {
paste(this.opts.block, this.contextPiece.key);
paste(
this.opts.block,
this.contextPiece.key,
this.opts.asset,
this.opts.scriptableevent
);
this.contextPiece = false;
}
this.update();
Expand Down Expand Up @@ -590,10 +613,21 @@ catnip-block(
icon: 'clipboard',
click: () => {
if (this.contextOption) {
paste(this.opts.block, this.contextOption, true);
paste(
this.opts.block,
this.contextOption,
this.opts.asset,
this.opts.scriptableevent,
true
);
this.contextOption = false;
} else {
paste(this.opts.block, this.contextPiece.key);
paste(
this.opts.block,
this.contextPiece.key,
this.opts.asset,
this.opts.scriptableevent
);
this.contextPiece = false;
}
this.update();
Expand Down
2 changes: 2 additions & 0 deletions src/riotTags/catnip/catnip-editor.tag
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ catnip-editor(class="flexrow {opts.class}" onpointermove="{repositionGhost}" ond
showplaceholder="showplaceholder"
if="{opts.event || opts.scriptmode}"
onclick="{tryDeselect}"
asset="{opts.asset}"
scriptableevent="{opts.event}"
)
.flexfix(ondragenter="{handlePreDrop}" ondragover="{handlePreDrop}" if="{opts.event || opts.scriptmode}")
catnip-library.flexfix-body(
Expand Down
3 changes: 3 additions & 0 deletions src/riotTags/catnip/catnip-library.tag
Original file line number Diff line number Diff line change
Expand Up @@ -267,13 +267,16 @@ catnip-library(class="{opts.class}").flexrow
this.enums = getOfType('enum');
this.update();
};
const update = () => this.update();
window.signals.on('enumCreated', updateEnums);
window.signals.on('enumRemoved', updateEnums);
window.signals.on('enumChanged', updateEnums);
window.signals.on('rerenderCatnipLibrary', update);
this.on('unmount', () => {
window.signals.off('enumCreated', updateEnums);
window.signals.off('enumRemoved', updateEnums);
window.signals.off('enumChanged', updateEnums);
window.signals.off('rerenderCatnipLibrary', update);
});

this.onDragStart = e => {
Expand Down

0 comments on commit f013b1d

Please sign in to comment.