Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Object detection updates #375

Open
wants to merge 26 commits into
base: scratch-package-refactor
Choose a base branch
from
Open
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
19 changes: 18 additions & 1 deletion extensions/src/common/extension/decorators/blocks.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type BlockUtility from "$scratch-vm/engine/block-utility";
import { TypedClassDecorator, TypedGetterDecorator, TypedMethodDecorator, TypedSetterDecorator } from ".";
import { BlockType } from "$common/types/enums";
import { BlockMetadata, ScratchArgument, Argument, NoArgsBlock } from "$common/types";
import { BlockMetadata, ScratchArgument, Argument, NoArgsBlock, VersionedOptions } from "$common/types";
import { getImplementationName } from "../mixins/base/scratchInfo/index";
import { ExtensionInstance } from "..";
import { isFunction, isString, tryCreateBundleTimeEvent } from "$common/utils";
Expand Down Expand Up @@ -87,6 +87,23 @@ export function block<
};
}

export function versions<
const This extends ExtensionInstance,
const Args extends any[],
const Return,
const Fn extends (...args: Args) => Return,
>
(
...config: VersionedOptions[]
): TypedMethodDecorator<This, Args, Return, (...args: Args) => Return> {

return function (this: This, target: (this: This, ...args: Args) => Return, context: ClassMethodDecoratorContext<This, Fn>) {
context.addInitializer(function () { this.pushVersions(target.name, config); });
//
return target;
};
}

/**
* This is a short-hand for invoking the block decorator when your `blockType` is button
* @param text
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,5 +82,6 @@ interface TemplateEngine<TBlockType extends ScratchBlockType> {
export const scratch = {
reporter: makeDecorator("reporter"),
command: makeDecorator("command"),
hat: makeDecorator("hat"),
button: makeDecorator("button"),
}
3 changes: 2 additions & 1 deletion extensions/src/common/extension/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ExtensionWithFunctionality, MixinName, optionalMixins } from "./mixins/index";
import { ExtensionBase } from "./ExtensionBase";
import scratchInfo from "./mixins/base/scratchInfo";
import scratchVersions from "./mixins/base/scratchVersioning";
import supported from "./mixins/base/supported";
import { ExtensionMenuDisplayDetails, Writeable } from "$common/types";
import { tryCaptureDependencies } from "./mixins/dependencies";
Expand Down Expand Up @@ -49,7 +50,7 @@ export const extension = <const TSupported extends readonly MixinName[]>(

if (details) extensionBundleEvent?.fire({ details, addOns });

const Base = scratchInfo(supported(ExtensionBase, addOns)) as ExtensionWithFunctionality<[...TSupported]>;
const Base = scratchVersions(scratchInfo(supported(ExtensionBase, addOns))) as ExtensionWithFunctionality<[...TSupported]>;

if (!addOns) return Base;

Expand Down
8 changes: 6 additions & 2 deletions extensions/src/common/extension/mixins/base/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import scratchInfo from "./scratchInfo/index";
import scratchVersioning from "./scratchVersioning/index";
import supported from "./supported";

export type CustomizableExtensionConstructor = ReturnType<typeof supported>;
export type CustomizableExtensionInstance = InstanceType<CustomizableExtensionConstructor>

export type MinimalExtensionConstructor = ReturnType<typeof scratchInfo>;
export type MinimalExtensionInstance = InstanceType<ReturnType<typeof scratchInfo>>;
export type BaseScratchExtensionConstuctor = ReturnType<typeof scratchInfo>;
export type BaseScratchExtensionInstance = InstanceType<BaseScratchExtensionConstuctor>;

export type MinimalExtensionConstructor = ReturnType<typeof scratchVersioning>;
export type MinimalExtensionInstance = InstanceType<ReturnType<typeof scratchVersioning>>;
23 changes: 19 additions & 4 deletions extensions/src/common/extension/mixins/base/scratchInfo/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { castToType } from "$common/cast";
import CustomArgumentManager from "$common/extension/mixins/configurable/customArguments/CustomArgumentManager";
import { ArgumentType, BlockType } from "$common/types/enums";
import { BlockOperation, ValueOf, Menu, ExtensionMetadata, ExtensionBlockMetadata, ExtensionMenuMetadata, DynamicMenu, BlockMetadata, BlockUtilityWithID, } from "$common/types";
import { BlockOperation, ValueOf, Menu, ExtensionMetadata, ExtensionBlockMetadata, ExtensionMenuMetadata, DynamicMenu, BlockMetadata, BlockUtilityWithID, VersionedOptions } from "$common/types";
import { registerButtonCallback } from "$common/ui";
import { isString, typesafeCall, } from "$common/utils";
import { menuProbe, asStaticMenu, getMenuName, convertMenuItemsToString } from "./menus";
import { Handler } from "./handlers";
import { BlockDefinition, getButtonID, isBlockGetter } from "./util";
import { convertToArgumentInfo, extractArgs, zipArgs } from "./args";
import { convertToDisplayText } from "./text";
import { CustomizableExtensionConstructor, MinimalExtensionInstance, } from "..";
import { CustomizableExtensionConstructor, BaseScratchExtensionInstance, } from "..";
import { ExtensionInstanceWithFunctionality } from "../..";
import { blockIDKey } from "$common/globals";

Expand All @@ -29,7 +29,7 @@ const checkForBlockContext = (blockUtility: BlockUtilityWithID) => isBlockUtilit
* @param args The args that must be parsed before being passed to the underlying operation
* @returns
*/
export const wrapOperation = <T extends MinimalExtensionInstance>(
export const wrapOperation = <T extends BaseScratchExtensionInstance>(
_this: T,
operation: BlockOperation,
args: { name: string, type: ValueOf<typeof ArgumentType>, handler: Handler }[]
Expand Down Expand Up @@ -71,8 +71,10 @@ export const wrapOperation = <T extends MinimalExtensionInstance>(
export default function (Ctor: CustomizableExtensionConstructor) {
type BlockEntry = { definition: BlockDefinition<ScratchExtension, BlockOperation>, operation: BlockOperation };
type BlockMap = Map<string, BlockEntry>;
type VersionMap = Map<string, VersionedOptions[]>;
abstract class ScratchExtension extends Ctor {
private readonly blockMap: BlockMap = new Map();
private readonly versionMap: VersionMap = new Map();

private readonly menus: Menu<any>[] = [];
private info: ExtensionMetadata;
Expand All @@ -88,6 +90,19 @@ export default function (Ctor: CustomizableExtensionConstructor) {
this.blockMap.set(opcode, { definition, operation } as BlockEntry);
}

pushVersions(opcode: string, versions: any) {
if (this.versionMap.has(opcode)) throw new Error(`Attempt to push block with opcode ${opcode}, but it was already set. This is assumed to be a mistake.`)
this.versionMap.set(opcode, versions);
}

getVersion(opcode: string) {
return this.versionMap.get(opcode);
}

getVersionMap() {
return this.versionMap;
}

protected getInfo(): ExtensionMetadata {
if (!this.info) {
const { id, name, blockIconURI } = this;
Expand Down Expand Up @@ -126,7 +141,7 @@ export default function (Ctor: CustomizableExtensionConstructor) {
info.func = buttonID;
} else {
const implementationName = getImplementationName(opcode);
this[implementationName] = wrapOperation(this as MinimalExtensionInstance, operation, zipArgs(args));
this[implementationName] = wrapOperation(this as BaseScratchExtensionInstance, operation, zipArgs(args));
}

return info;
Expand Down
Loading
Loading