diff --git a/src/editor/editor.ts b/src/editor/editor.ts index a3938082..48358810 100644 --- a/src/editor/editor.ts +++ b/src/editor/editor.ts @@ -24,15 +24,11 @@ import * as Blockly from 'blockly/core'; import { extendedPythonGenerator } from './extended_python_generator'; import { GeneratorContext } from './generator_context'; import * as commonStorage from '../storage/common_storage'; -import * as toolboxOpmode from '../toolbox/toolbox_opmode'; -import * as toolboxMechanism from '../toolbox/toolbox_mechanism'; -import * as toolboxRobot from '../toolbox/toolbox_robot'; //import { testAllBlocksInToolbox } from '../toolbox/toolbox_tests'; import { MethodsCategory} from '../toolbox/methods_category'; import { EventsCategory} from '../toolbox/event_category'; -import { ComponentsCategory } from '../toolbox/components_category'; - +import { getToolboxJSON } from '../toolbox/toolbox'; const EMPTY_TOOLBOX: Blockly.utils.toolbox.ToolboxDefinition = { kind: 'categoryToolbox', @@ -47,7 +43,6 @@ export class Editor { private storage: commonStorage.Storage; private methodsCategory: MethodsCategory; private eventsCategory: EventsCategory; - private componentsCategory: ComponentsCategory; private currentModule: commonStorage.Module | null = null; private modulePath: string = ''; private projectPath: string = ''; @@ -63,7 +58,6 @@ export class Editor { this.storage = storage; this.methodsCategory = new MethodsCategory(blocklyWorkspace); this.eventsCategory = new EventsCategory(blocklyWorkspace); - this.componentsCategory = new ComponentsCategory(blocklyWorkspace); } private onChangeWhileLoading(event: Blockly.Events.Abstract) { @@ -127,7 +121,6 @@ export class Editor { this.currentModule = currentModule; this.methodsCategory.setCurrentModule(currentModule); this.eventsCategory.setCurrentModule(currentModule); - this.componentsCategory.setCurrentModule(currentModule); if (currentModule) { this.modulePath = currentModule.modulePath; @@ -201,23 +194,9 @@ export class Editor { }, 50); return; } - switch(this.currentModule.moduleType){ - case commonStorage.MODULE_TYPE_PROJECT: - this.setToolbox(toolboxRobot.getToolboxJSON(shownPythonToolboxCategories)); - break; - case commonStorage.MODULE_TYPE_MECHANISM: - this.setToolbox(toolboxMechanism.getToolboxJSON(shownPythonToolboxCategories)); - break; - case commonStorage.MODULE_TYPE_OPMODE: -/* - * TODO: When editing an opmode, we'll need to have blocks for all the methods that a robot has. - * Not sure what this will be replaced with, but it will need something. - * const robotBlocks = commonStorage.extractExportedBlocks( - * this.currentModule.projectName, this.projectContent); -*/ - this.setToolbox(toolboxOpmode.getToolboxJSON(shownPythonToolboxCategories)); - break; - } + this.setToolbox( + getToolboxJSON( + shownPythonToolboxCategories, this.currentModule)); } } diff --git a/src/toolbox/add_hardware_component_category.ts b/src/toolbox/add_hardware_component_category.ts deleted file mode 100644 index b7c580d4..00000000 --- a/src/toolbox/add_hardware_component_category.ts +++ /dev/null @@ -1,50 +0,0 @@ -export const category = -{ - kind: 'category', - name: 'Hardware', - contents: [ - { - kind: 'label', - text: 'Components', - }, - { - kind: 'block', - type: 'mrc_component', - fields: { - NAME: 'my_motor', - TYPE: 'SmartMotor' - }, - extraState: { - importModule: 'smart_motor', - params: [{ name: 'motor_port', type: 'int' }], - hideParams: true - }, - }, - { - kind: 'block', - type: 'mrc_component', - fields: { - NAME: 'my_color_range_sensor', - TYPE: 'ColorRangeSensor' - }, - extraState: { - importModule: 'color_range_sensor', - params: [{ name: 'i2c_port', type: 'int' }], - hideParams: true - }, - }, - { - kind: 'block', - type: 'mrc_component', - fields: { - NAME: 'my_touch_sensor', - TYPE: 'RevTouchSensor' - }, - extraState: { - importModule: 'rev_touch_sensor', - params: [{ name: 'smartIO_port', type: 'int' }], - hideParams: true - }, - }, - ], -} \ No newline at end of file diff --git a/src/toolbox/blocks_components.ts b/src/toolbox/blocks_components.ts new file mode 100644 index 00000000..84372a5a --- /dev/null +++ b/src/toolbox/blocks_components.ts @@ -0,0 +1,34 @@ +/** + * @license + * Copyright 2025 Porpoiseful LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @author alan@porpoiseful.com (Alan Smith) + */ +import * as ToolboxItems from './items'; +import * as ColorSensor from './hardware_components/color_sensor'; +import * as SmartMotor from './hardware_components/smart_motor'; +import * as TouchSensor from './hardware_components/touch_sensor'; +import * as Servo from './hardware_components/servo'; + +export function getAllPossibleComponents(hideParams : boolean): ToolboxItems.ContentsType[] { + return [ + SmartMotor.getDefinitionBlock(hideParams), + TouchSensor.getDefinitionBlock(hideParams), + ColorSensor.getDefinitionBlock(hideParams), + Servo.getDefinitionBlock(hideParams), + ]; +} diff --git a/src/toolbox/blocks_mechanisms.ts b/src/toolbox/blocks_mechanisms.ts new file mode 100644 index 00000000..249dc454 --- /dev/null +++ b/src/toolbox/blocks_mechanisms.ts @@ -0,0 +1,121 @@ +/** + * @license + * Copyright 2025 Porpoiseful LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @author alan@porpoiseful.com (Alan Smith) + */ +import * as ToolboxItems from './items'; + +/** + * TODO: This is all fake right now, it will be generated dynamically + * based on reading things from mechanisms. + */ + +export function getAllPossibleMechanisms(): ToolboxItems.ContentsType[] { + return [ + + { + kind: 'block', + type: 'mrc_mechanism', + fields: { + NAME: 'claw', + TYPE: 'Claw' + }, + extraState: { + importModule: 'claw', + params: [{ name: 'gripper_port', type: 'int' }, + { name: 'piece_sensor_port', type: 'int' }, + ] + }, + inputs: { + ARG0: { + shadow: { + type: 'mrc_port', + fields: { + TYPE: 'SmartMotor', + PORT_NUM: 1 + }, + }, + }, + ARG1: { + shadow: { + type: 'mrc_port', + fields: { + TYPE: 'SmartIO', + PORT_NUM: 1 + }, + }, + }, + } + }, + { + kind: 'block', + type: 'mrc_mechanism', + fields: { + NAME: 'drive', + TYPE: 'DriveMecanum' + }, + extraState: { + importModule: 'DriveMecanum', + params: [{ name: 'front_left_drive_port', type: 'int' }, + { name: 'front_right_drive_port', type: 'int' }, + { name: 'back_left_drive_port', type: 'int' }, + { name: 'back_right_drive_port', type: 'int' }, + ] + }, + inputs: { + ARG0: { + shadow: { + type: 'mrc_port', + fields: { + TYPE: 'SmartMotor', + PORT_NUM: 1 + }, + }, + }, + ARG1: { + shadow: { + type: 'mrc_port', + fields: { + TYPE: 'SmartMotor', + PORT_NUM: 2 + }, + }, + }, + ARG2: { + shadow: { + type: 'mrc_port', + fields: { + TYPE: 'SmartMotor', + PORT_NUM: 3 + }, + }, + }, + ARG3: { + shadow: { + type: 'mrc_port', + fields: { + TYPE: 'SmartMotor', + PORT_NUM: 4 + }, + }, + }, + } + }, + ]; +} + diff --git a/src/toolbox/component_samples_category.ts b/src/toolbox/component_samples_category.ts deleted file mode 100644 index 68008610..00000000 --- a/src/toolbox/component_samples_category.ts +++ /dev/null @@ -1,526 +0,0 @@ -export const category = -{ - kind: 'category', - name: 'Components', - contents: [ - { - kind: 'category', - name: 'REV Color Range Sensor', - contents: [ - // def get_color_rgb(self) -> tuple[int, int, int]: - { - kind: 'block', - type: 'mrc_call_python_function', - extraState: { - functionKind: 'instance_component', - returnType: 'tuple[int, int, int]', - args: [], - tooltip: 'Get the color in rgb (red, green, blue).', - importModule: '', - componentClassName: 'rev.ColorRangeSensor', - componentName: 'colorSensor', - }, - fields: { - COMPONENT_NAME: 'colorSensor', - FUNC: 'get_color_rgb', - }, - inputs: {}, - }, - // def get_color_hsv(self) -> tuple[int, int, int]: - { - kind: 'block', - type: 'mrc_call_python_function', - extraState: { - functionKind: 'instance_component', - returnType: 'tuple[int, int, int]', - args: [], - tooltip: 'Get the color in hsv (hue, saturation, value).', - importModule: '', - componentClassName: 'rev.ColorRangeSensor', - componentName: 'colorSensor', - }, - fields: { - COMPONENT_NAME: 'colorSensor', - FUNC: 'get_color_hsv', - }, - inputs: {}, - }, - // def get_distance_mm(self) -> float: - { - kind: 'block', - type: 'mrc_call_python_function', - extraState: { - functionKind: 'instance_component', - returnType: 'float', - args: [], - tooltip: 'Get the distance of the object seen.', - importModule: '', - componentClassName: 'rev.ColorRangeSensor', - componentName: 'colorSensor', - }, - fields: { - COMPONENT_NAME: 'colorSensor', - FUNC: 'get_distance_mm', - }, - inputs: {}, - }, - ], - }, - { - kind: 'category', - name: 'REV Servo', - contents: [ - // def set_position(self, pos: float) -> None: - { - kind: 'block', - type: 'mrc_call_python_function', - extraState: { - functionKind: 'instance_component', - returnType: 'None', - args: [ - { - name: 'pos', - type: 'float', - }, - ], - tooltip: 'Set the servo to a position between 0 and 1.', - importModule: '', - componentClassName: 'rev.Servo', - componentName: 'clawServo', - }, - fields: { - COMPONENT_NAME: 'clawServo', - FUNC: 'set_position', - }, - inputs: { - ARG0: { - block: { - type: 'math_number', - fields: { - NUM: 0.5, - }, - }, - }, - }, - }, - // def set_angle_degrees(self, angle: float) -> None: - { - kind: 'block', - type: 'mrc_call_python_function', - extraState: { - functionKind: 'instance_component', - returnType: 'None', - args: [ - { - name: 'angle', - type: 'float', - }, - ], - tooltip: 'Set the servo to an angle between 0 and 270.', - importModule: '', - componentClassName: 'rev.Servo', - componentName: 'clawServo', - }, - fields: { - COMPONENT_NAME: 'clawServo', - FUNC: 'set_angle_degrees', - }, - inputs: { - ARG0: { - block: { - type: 'math_number', - fields: { - NUM: 180, - }, - }, - }, - }, - }, - ], - }, - { - kind: 'category', - name: 'REV Smart Motor', - contents: [ - // def set_speed(self, speed: float) -> None: - { - kind: 'block', - type: 'mrc_call_python_function', - extraState: { - functionKind: 'instance_component', - returnType: 'None', - args: [ - { - name: 'speed', - type: 'float', - }, - ], - tooltip: 'Set the motor to a speed between -1 and 1.', - importModule: '', - componentClassName: 'rev.SmartMotor', - componentName: 'leftMotor', - }, - fields: { - COMPONENT_NAME: 'leftMotor', - FUNC: 'set_speed', - }, - inputs: { - ARG0: { - block: { - type: 'math_number', - fields: { - NUM: 0.8, - }, - }, - }, - }, - }, - // def set_angle_degrees(self, angle: float) -> None: - { - kind: 'block', - type: 'mrc_call_python_function', - extraState: { - functionKind: 'instance_component', - returnType: 'None', - args: [ - { - name: 'angle', - type: 'float', - }, - ], - tooltip: 'Set the motor to an angle between 0 and 360.', - importModule: '', - componentClassName: 'rev.SmartMotor', - componentName: 'leftMotor', - }, - fields: { - COMPONENT_NAME: 'leftMotor', - FUNC: 'set_angle_degrees', - }, - inputs: { - ARG0: { - block: { - type: 'math_number', - fields: { - NUM: 180, - }, - }, - }, - }, - }, - // def get_num_relative_encoder_ticks(self) -> int: - { - kind: 'block', - type: 'mrc_call_python_function', - extraState: { - functionKind: 'instance_component', - returnType: 'int', - args: [], - tooltip: 'Get the number of relative motor ticks since reset of encoder.', - importModule: '', - componentClassName: 'rev.SmartMotor', - componentName: 'leftMotor', - }, - fields: { - COMPONENT_NAME: 'leftMotor', - FUNC: 'get_num_relative_encoder_ticks', - }, - inputs: {}, - }, - // def get_angle_degrees(self) -> float: - { - kind: 'block', - type: 'mrc_call_python_function', - extraState: { - functionKind: 'instance_component', - returnType: 'float', - args: [], - tooltip: 'Get the angle position of the motor.', - importModule: '', - componentClassName: 'rev.SmartMotor', - componentName: 'leftMotor', - }, - fields: { - COMPONENT_NAME: 'leftMotor', - FUNC: 'get_angle_degrees', - }, - inputs: {}, - }, - // def reset_relative_encoder(self) -> None: - { - kind: 'block', - type: 'mrc_call_python_function', - extraState: { - functionKind: 'instance_component', - returnType: 'None', - args: [], - tooltip: 'Reset the relative encoder value to 0.', - importModule: '', - componentClassName: 'rev.SmartMotor', - componentName: 'leftMotor', - }, - fields: { - COMPONENT_NAME: 'leftMotor', - FUNC: 'reset_relative_encoder', - }, - inputs: {}, - }, - ] - }, - { - kind: 'category', - name: 'REV Touch Sensor', - contents: [ - // def is_pressed(self) -> bool: - { - kind: 'block', - type: 'mrc_call_python_function', - extraState: { - functionKind: 'instance_component', - returnType: 'bool', - args: [], - tooltip: 'Return whether the touch sensor is pressed.', - importModule: '', - componentClassName: 'rev.TouchSensor', - componentName: 'frontTouch', - }, - fields: { - COMPONENT_NAME: 'frontTouch', - FUNC: 'is_pressed', - }, - inputs: {}, - }, - ], - }, - { - kind: 'category', - name: 'SparkFun LED Stick', - contents: [ - // def set_color(self, position: int, color: wpilib.Color) -> None: - { - kind: 'block', - type: 'mrc_call_python_function', - extraState: { - functionKind: 'instance_component', - returnType: 'None', - args: [ - { - name: 'position', - type: 'int', - }, - { - name: 'color', - type: 'wpilib.Color', - }, - ], - tooltip: 'Change the color of an individual LED.', - importModule: '', - componentClassName: 'sparkfun.LEDStick', - componentName: 'ledStick', - }, - fields: { - COMPONENT_NAME: 'ledStick', - FUNC: 'set_color', - }, - inputs: { - ARG0: { - block: { - type: 'math_number', - fields: { - NUM: 1, - }, - }, - }, - ARG1: { - block: { - type: 'mrc_get_python_variable', - extraState: { - varKind: 'class', - moduleOrClassName: 'wpilib.Color', - varType: 'wpilib.Color', - importModule: 'wpilib', - }, - fields: { - MODULE_OR_CLASS: 'wpilib.Color', - VAR: 'kWhite', - }, - }, - }, - }, - }, - // def set_color(self, color: wpilib.Color) -> None: - { - kind: 'block', - type: 'mrc_call_python_function', - extraState: { - functionKind: 'instance_component', - returnType: 'None', - args: [ - { - name: 'color', - type: 'wpilib.Color', - }, - ], - tooltip: 'Change the color of all LEDs to a single color.', - importModule: '', - componentClassName: 'sparkfun.LEDStick', - componentName: 'ledStick', - }, - fields: { - COMPONENT_NAME: 'ledStick', - FUNC: 'set_color', - }, - inputs: { - ARG0: { - block: { - type: 'mrc_get_python_variable', - extraState: { - varKind: 'class', - moduleOrClassName: 'wpilib.Color', - varType: 'wpilib.Color', - importModule: 'wpilib', - }, - fields: { - MODULE_OR_CLASS: 'wpilib.Color', - VAR: 'kWhite', - }, - }, - }, - }, - }, - // def set_colors(self, colors: list[int]) -> None: - { - kind: 'block', - type: 'mrc_call_python_function', - extraState: { - functionKind: 'instance_component', - returnType: 'None', - args: [ - { - name: 'colors', - type: 'list[int]', - }, - ], - tooltip: 'Change the color of all LEDs using a list.', - importModule: '', - componentClassName: 'sparkfun.LEDStick', - componentName: 'ledStick', - }, - fields: { - COMPONENT_NAME: 'ledStick', - FUNC: 'set_colors', - }, - inputs: { - ARG0: { - block: { - type: 'variables_get', - fields: { - VAR: { - name: 'myListOfColors', - }, - }, - }, - }, - }, - }, - // def set_brightness(self, position: int, brightness: int) -> None: - { - kind: 'block', - type: 'mrc_call_python_function', - extraState: { - functionKind: 'instance_component', - returnType: 'None', - args: [ - { - name: 'position', - type: 'int', - }, - { - name: 'brightness', - type: 'int', - }, - ], - tooltip: 'Set the brightness of an individual LED.', - importModule: '', - componentClassName: 'sparkfun.LEDStick', - componentName: 'ledStick', - }, - fields: { - COMPONENT_NAME: 'ledStick', - FUNC: 'set_brightness', - }, - inputs: { - ARG0: { - block: { - type: 'math_number', - fields: { - NUM: 1, - }, - }, - }, - ARG1: { - block: { - type: 'math_number', - fields: { - NUM: 16, - }, - }, - }, - }, - }, - // def set_brightness(self, brightness: int) -> None: - { - kind: 'block', - type: 'mrc_call_python_function', - extraState: { - functionKind: 'instance_component', - returnType: 'None', - args: [ - { - name: 'brightness', - type: 'int', - } - ], - tooltip: 'Set the brightness of all LEDs.', - importModule: '', - componentClassName: 'sparkfun.LEDStick', - componentName: 'ledStick', - }, - fields: { - COMPONENT_NAME: 'ledStick', - FUNC: 'set_brightness', - }, - inputs: { - ARG0: { - block: { - type: 'math_number', - fields: { - NUM: 16, - }, - }, - }, - }, - }, - // def turn_all_off(self) -> None: - { - kind: 'block', - type: 'mrc_call_python_function', - extraState: { - functionKind: 'instance_component', - returnType: 'None', - args: [], - tooltip: 'Turn all LEDs off.', - importModule: '', - componentClassName: 'sparkfun.LEDStick', - componentName: 'ledStick', - }, - fields: { - COMPONENT_NAME: 'ledStick', - FUNC: 'turn_all_off', - }, - inputs: {}, - }, - ], - } - ], -} \ No newline at end of file diff --git a/src/toolbox/components_category.ts b/src/toolbox/components_category.ts deleted file mode 100644 index b312cadc..00000000 --- a/src/toolbox/components_category.ts +++ /dev/null @@ -1,246 +0,0 @@ -/** - * @license - * Copyright 2025 Porpoiseful LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @author alan@porpoiseful.com (Alan Smith) - */ - -/** - * TODO: This is all fake right now, it will be generated dynamically - * based on the components that are available in the current module. - */ - -import * as Blockly from 'blockly/core'; - -import * as toolboxItems from './items'; -import * as commonStorage from '../storage/common_storage'; -import { MRC_CATEGORY_STYLE_COMPONENTS } from '../themes/styles'; - -const CUSTOM_CATEGORY_COMPONENTS = 'COMPONENTS'; - -export const category = { - kind: 'category', - categorystyle: MRC_CATEGORY_STYLE_COMPONENTS, - name: 'Hardware', - contents: [ - { - kind: 'category', - name: 'my_motor', - custom: CUSTOM_CATEGORY_COMPONENTS, - componentConfig: { - name: 'my_motor', - type: 'rev.SmartMotor', - } - }, - { - kind: 'category', - name: 'my_touch_sensor', - custom: CUSTOM_CATEGORY_COMPONENTS, - componentConfig: { - name: 'my_touch_sensor', - type: 'rev.TouchSensor', - } - }, - { - kind: 'category', - name: 'New', - contents: [ - { - kind: 'label', - text: 'Components', - }, - { - kind: 'block', - type: 'mrc_component', - fields: { - NAME: 'my_motor', - TYPE: 'SmartMotor' - }, - extraState: { - importModule: 'smart_motor', - params: [{ name: 'motor_port', type: 'int' }], - hideParams: true - }, - }, - { - kind: 'block', - type: 'mrc_component', - fields: { - NAME: 'my_color_range_sensor', - TYPE: 'ColorRangeSensor' - }, - extraState: { - importModule: 'color_range_sensor', - params: [{ name: 'i2c_port', type: 'int' }], - hideParams: true - }, - }, - { - kind: 'block', - type: 'mrc_component', - fields: { - NAME: 'my_touch_sensor', - TYPE: 'RevTouchSensor' - }, - extraState: { - importModule: 'rev_touch_sensor', - params: [{ name: 'smartIO_port', type: 'int' }], - hideParams: true - }, - }, - ] - },] -}; - - -export class ComponentsCategory { - private currentModule: commonStorage.Module | null = null; - - - constructor(blocklyWorkspace: Blockly.WorkspaceSvg) { - blocklyWorkspace.registerToolboxCategoryCallback(CUSTOM_CATEGORY_COMPONENTS, this.componentsFlyout.bind(this)); - } - - public setCurrentModule(currentModule: commonStorage.Module | null) { - this.currentModule = currentModule; - } - - public componentsFlyout(workspace: Blockly.WorkspaceSvg) { - const contents: toolboxItems.ContentsType[] = []; - - contents.push( - { - kind: 'block', - type: 'mrc_event_handler', - extraState: { - tooltip: '', - pathOfSender: '', - typeOfSender: 'component', - params: [], - }, - fields: { - SENDER: 'my_motor', - EVENT_NAME: 'on_stall', - }, - }, - { - kind: 'block', - type: 'mrc_event_handler', - extraState: { - tooltip: '', - pathOfSender: '', - typeOfSender: 'component', - params: [ - { - name: 'new_state', - type: 'boolean', - }, - ], - }, - fields: { - SENDER: 'my_touch_sensor', - EVENT_NAME: 'on_change', - }, - }, - { - kind: 'block', - type: 'mrc_event_handler', - extraState: { - tooltip: '', - pathOfSender: '', - typeOfSender: 'component', - params: [], - }, - fields: { - SENDER: 'my_touch_sensor', - EVENT_NAME: 'on_pressed', - }, - }, - { - kind: 'block', - type: 'mrc_event_handler', - extraState: { - tooltip: '', - pathOfSender: '', - typeOfSender: 'component', - params: [], - }, - fields: { - SENDER: 'my_touch_sensor', - EVENT_NAME: 'on_released', - }, - }, - // def set_speed(self, speed: float) -> None: - { - kind: 'block', - type: 'mrc_call_python_function', - extraState: { - functionKind: 'instance_component', - returnType: 'None', - args: [ - { - name: 'speed', - type: 'float', - }, - ], - tooltip: 'Set the motor to a speed between -1 and 1.', - importModule: '', - componentClassName: 'rev.SmartMotor', - componentName: 'my_motor', - }, - fields: { - COMPONENT_NAME: 'my_motor', - FUNC: 'set_speed', - }, - inputs: { - ARG0: { - block: { - type: 'math_number', - fields: { - NUM: 0.8, - }, - }, - }, - }, - }, - { - kind: 'block', - type: 'mrc_call_python_function', - extraState: { - functionKind: 'instance_component', - returnType: 'None', - args: [ - ], - tooltip: 'Stop the motor', - importModule: '', - componentClassName: 'rev.SmartMotor', - componentName: 'my_motor', - }, - fields: { - COMPONENT_NAME: 'my_motor', - FUNC: 'stop', - }, - }, - ); - - const toolboxInfo = { - contents: contents, - }; - - return toolboxInfo; - } -} \ No newline at end of file diff --git a/src/toolbox/hardware_category.ts b/src/toolbox/hardware_category.ts index cffc7ef5..f5b9d8c2 100644 --- a/src/toolbox/hardware_category.ts +++ b/src/toolbox/hardware_category.ts @@ -1,172 +1,267 @@ -export const category = -{ - kind: 'category', - name: 'Hardware', - contents: [ +/** + * @license + * Copyright 2025 Porpoiseful LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @author alan@porpoiseful.com (Alan Smith) + */ + +/** + * TODO: This is all fake right now, it will be generated dynamically + * based on the components that are available in the current module. + */ + +import * as Blockly from 'blockly/core'; + +import * as toolboxItems from './items'; +import * as commonStorage from '../storage/common_storage'; +import { getAllPossibleMechanisms } from './blocks_mechanisms'; +import { getAllPossibleComponents } from './blocks_components'; +import * as SmartMotor from './hardware_components/smart_motor'; +import * as TouchSensor from './hardware_components/touch_sensor'; + +export function getHardwareCategory(currentModule: commonStorage.Module) { + if (currentModule.moduleType === commonStorage.MODULE_TYPE_OPMODE) { + return { + kind: 'category', + name: 'Robot', + contents: [ + getRobotMechanismsBlocks(currentModule), + getRobotComponentsBlocks(currentModule), + getRobotMethodsBlocks(currentModule), + ] + }; + } + if (currentModule.moduleType === commonStorage.MODULE_TYPE_PROJECT) { + return { + kind: 'category', + name: 'Hardware', + contents: [ + getRobotMechanismsBlocks(currentModule), + getRobotComponentsBlocks(currentModule), + ] + }; + } + if (currentModule.moduleType === commonStorage.MODULE_TYPE_MECHANISM) { + return getComponentsBlocks(currentModule); + } + // Return default empty category if module type doesn't match + return { + kind: 'category', + name: 'Hardware', + contents: [] + }; +} + +// TODO: This needs to load the robot file and get the list of mechanisms +function getRobotMechanismsBlocks(currentModule: commonStorage.Module) { + const includeAdd = currentModule.moduleType !== commonStorage.MODULE_TYPE_OPMODE; + + const contents = []; + + // Only include the "+ Mechanism" category if includeAdd is true + if (includeAdd) { + contents.push({ + kind: 'category', + name: '+ Mechanism', + contents: getAllPossibleMechanisms(), + }); + } + + // Add the existing mechanisms + contents.push( { - kind: 'label', - text: 'Mechanisms', - }, - { - kind: 'block', - type: 'mrc_mechanism', - fields: { - NAME: 'claw', - TYPE: 'Claw' - }, - extraState: { - importModule: 'claw', - params: [{ name: 'gripper_port', type: 'int' }, - { name: 'piece_sensor_port', type: 'int' }, - ] - }, - inputs: { - ARG0: { - shadow: { - type: 'mrc_port', - fields: { - TYPE: 'SmartMotor', - PORT_NUM: 1 - }, + kind: 'category', + name: 'drive', + contents: [ + { + kind: 'block', + type: 'mrc_call_python_function', + extraState: { + functionKind: 'instance_component', + returnType: '', + args: [ + { + name: 'forward_speed', + type: 'float', + }, + { + name: 'strafe_right_speed', + type: 'float', + }, + { + name: 'rotate_cw_speed', + type: 'float', + }, + ], + tooltip: 'Drive (robot relative)', + importModule: '', + componentClassName: 'rev.ColorRangeSensor', + componentName: 'robot.drive', }, - }, - ARG1: { - shadow: { - type: 'mrc_port', - fields: { - TYPE: 'SmartIO', - PORT_NUM: 1 - }, + fields: { + COMPONENT_NAME: 'robot.drive', + FUNC: 'drive_field_relative', }, + inputs: {}, }, - } + ] }, { - kind: 'block', - type: 'mrc_mechanism', - fields: { - NAME: 'drive', - TYPE: 'DriveMecanum' - }, - extraState: { - importModule: 'DriveMecanum', - params: [{ name: 'front_left_drive_port', type: 'int' }, - { name: 'front_right_drive_port', type: 'int' }, - { name: 'back_left_drive_port', type: 'int' }, - { name: 'back_right_drive_port', type: 'int' }, - ] - }, - inputs: { - ARG0: { - shadow: { - type: 'mrc_port', - fields: { - TYPE: 'SmartMotor', - PORT_NUM: 1 - }, - }, + kind: 'category', + name: 'claw', + contents: [ + { + kind: 'category', + name: 'gripper', + contents: [], }, - ARG1: { - shadow: { - type: 'mrc_port', - fields: { - TYPE: 'SmartMotor', - PORT_NUM: 2 + { + kind: 'category', + name: 'piece_sensor', + contents: [ + // def get_color_rgb(self) -> tuple[int, int, int]: + { + kind: 'block', + type: 'mrc_call_python_function', + extraState: { + functionKind: 'instance_component', + returnType: 'tuple[int, int, int]', + args: [], + tooltip: 'Get the color in rgb (red, green, blue).', + importModule: '', + componentClassName: 'rev.ColorRangeSensor', + componentName: 'colorSensor', + }, + fields: { + COMPONENT_NAME: 'robot.claw.piece_sensor', + FUNC: 'get_color_rgb', + }, + inputs: {}, }, - }, - }, - ARG2: { - shadow: { - type: 'mrc_port', - fields: { - TYPE: 'SmartMotor', - PORT_NUM: 3 + // def get_color_hsv(self) -> tuple[int, int, int]: + { + kind: 'block', + type: 'mrc_call_python_function', + extraState: { + functionKind: 'instance_component', + returnType: 'tuple[int, int, int]', + args: [], + tooltip: 'Get the color in hsv (hue, saturation, value).', + importModule: '', + componentClassName: 'rev.ColorRangeSensor', + componentName: 'colorSensor', + }, + fields: { + COMPONENT_NAME: 'robot.claw.piece_sensor', + FUNC: 'get_color_hsv', + }, + inputs: {}, }, - }, - }, - ARG3: { - shadow: { - type: 'mrc_port', - fields: { - TYPE: 'SmartMotor', - PORT_NUM: 4 + // def get_distance_mm(self) -> float: + { + kind: 'block', + type: 'mrc_call_python_function', + extraState: { + functionKind: 'instance_component', + returnType: 'float', + args: [], + tooltip: 'Get the distance of the object seen.', + importModule: '', + componentClassName: 'rev.ColorRangeSensor', + componentName: 'colorSensor', + }, + fields: { + COMPONENT_NAME: 'robot.claw.piece_sensor', + FUNC: 'get_distance_mm', + }, + inputs: {}, }, - }, + ], }, - } + ] }, { - kind: 'label', - text: 'Components', + kind: 'category', + name: 'flywheel', + contents: [], }, { - kind: 'block', - type: 'mrc_component', - fields: { - NAME: 'my_motor', - TYPE: 'SmartMotor' - }, - extraState: { - importModule: 'smart_motor', - params: [{ name: 'motor_port', type: 'int' }] - }, - inputs: { - ARG0: { - shadow: { - type: 'mrc_port', - fields: { - TYPE: 'SmartMotor', - PORT_NUM: 1 - }, - }, - }, - } + kind: 'category', + name: 'shooter', + contents: [], + } + ); + + return { + kind: 'category', + name: 'Mechanisms', + contents, + }; +} + +// TODO: This needs to load the robot file and get the list of components +function getRobotComponentsBlocks(currentModule: commonStorage.Module) { + const includeAdd = currentModule.moduleType !== commonStorage.MODULE_TYPE_OPMODE; + const contents = []; + + if (includeAdd) { + contents.push({ + kind: 'category', + name: '+ Component', + contents: getAllPossibleComponents(false) + }); + } + + return { + kind: 'category', + name: 'Components', + contents, + }; +} + +function getRobotMethodsBlocks(currentModule: commonStorage.Module) { + return { + kind: 'category', + name: 'Methods', + contents: [] + }; +} + +function getComponentsBlocks(currentModule: commonStorage.Module) { + const contents = []; + contents.push({ + kind: 'category', + name: '+ Component', + contents: getAllPossibleComponents(true) + }); + contents.push({ + kind: 'category', + name: 'my_motor', + contents: SmartMotor.getBlocks('my_motor') }, { - kind: 'block', - type: 'mrc_component', - fields: { - NAME: 'my_color_range_sensor', - TYPE: 'ColorRangeSensor' - }, - extraState: { - importModule: 'color_range_sensor', - params: [{ name: 'i2c_port', type: 'int' }] - }, - inputs: { - ARG0: { - shadow: { - type: 'mrc_port', - fields: { - TYPE: 'I2C', - PORT_NUM: 1 - }, - }, - }, - } - }, - { - kind: 'block', - type: 'mrc_component', - fields: { - NAME: 'my_touch_sensor', - TYPE: 'RevTouchSensor' - }, - extraState: { - importModule: 'rev_touch_sensor', - params: [{ name: 'smartIO_port', type: 'int' }] - }, - inputs: { - ARG0: { - shadow: { - type: 'mrc_port', - fields: { - TYPE: 'SmartIO', - PORT_NUM: 1 - }, - }, - }, - } + kind: 'category', + name: 'my_touch_sensor', + contents: TouchSensor.getBlocks('my_touch_sensor') }, - ], + ); + return { + kind: 'category', + name: 'Components', + contents, + }; } \ No newline at end of file diff --git a/src/toolbox/hardware_components/color_sensor.ts b/src/toolbox/hardware_components/color_sensor.ts new file mode 100644 index 00000000..6cd689fb --- /dev/null +++ b/src/toolbox/hardware_components/color_sensor.ts @@ -0,0 +1,122 @@ +/** + * @license + * Copyright 2025 Porpoiseful LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @fileoverview Color range sensor hardware component definitions. + * @author alan@porpoiseful.com (Alan Smith) + */ + +import * as ToolboxItems from '../items'; + +export const TYPE_NAME = 'ColorRangeSensor'; + +/** + * Returns a component definition block for a color range sensor. + */ +export function getDefinitionBlock(hideParams: boolean): ToolboxItems.ContentsType { + return { + kind: 'block', + type: 'mrc_component', + fields: { + NAME: 'my_color_range_sensor', + TYPE: TYPE_NAME, + }, + extraState: { + importModule: 'rev_color_range_sensor', + params: [{name: 'smartIO_port', type: 'int'}], + hideParams, + }, + ...(hideParams ? {} : { + inputs: { + ARG0: { + shadow: { + type: 'mrc_port', + fields: { + TYPE: 'SmartIO', + PORT_NUM: 1, + }, + }, + }, + }, + }), + }; +} + +/** + * Returns the blocks available for a color range sensor component. + */ +export function getBlocks(componentName: string): ToolboxItems.ContentsType[] { + return [ + // Method: get_color_rgb() -> tuple[int, int, int] + { + kind: 'block', + type: 'mrc_call_python_function', + extraState: { + functionKind: 'instance_component', + returnType: 'tuple[int, int, int]', + args: [], + tooltip: 'Get the color in rgb (red, green, blue).', + importModule: '', + componentClassName: 'rev.ColorRangeSensor', + componentName, + }, + fields: { + COMPONENT_NAME: componentName, + FUNC: 'get_color_rgb', + }, + inputs: {}, + }, + // Method: get_color_hsv() -> tuple[int, int, int] + { + kind: 'block', + type: 'mrc_call_python_function', + extraState: { + functionKind: 'instance_component', + returnType: 'tuple[int, int, int]', + args: [], + tooltip: 'Get the color in hsv (hue, saturation, value).', + importModule: '', + componentClassName: 'rev.ColorRangeSensor', + componentName, + }, + fields: { + COMPONENT_NAME: componentName, + FUNC: 'get_color_hsv', + }, + inputs: {}, + }, + // Method: get_distance_mm() -> float + { + kind: 'block', + type: 'mrc_call_python_function', + extraState: { + functionKind: 'instance_component', + returnType: 'float', + args: [], + tooltip: 'Get the distance of the object seen.', + importModule: '', + componentClassName: 'rev.ColorRangeSensor', + componentName, + }, + fields: { + COMPONENT_NAME: componentName, + FUNC: 'get_distance_mm', + }, + inputs: {}, + }, + ]; +} \ No newline at end of file diff --git a/src/toolbox/hardware_components/servo.ts b/src/toolbox/hardware_components/servo.ts new file mode 100644 index 00000000..4274c4b5 --- /dev/null +++ b/src/toolbox/hardware_components/servo.ts @@ -0,0 +1,130 @@ +/** + * @license + * Copyright 2025 Porpoiseful LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @fileoverview Servo hardware component definitions. + * @author alan@porpoiseful.com (Alan Smith) + */ +import * as ToolboxItems from '../items'; + +export const TYPE_NAME = 'Servo'; + +/** + * Returns a component definition block for a servo. + */ +export function getDefinitionBlock(hideParams: boolean): ToolboxItems.ContentsType { + return { + kind: 'block', + type: 'mrc_component', + fields: { + NAME: 'my_servo', + TYPE: TYPE_NAME, + }, + extraState: { + importModule: 'rev_servo', + params: [{name: 'servo_port', type: 'int'}], + hideParams, + }, + ...(hideParams ? {} : { + inputs: { + ARG0: { + shadow: { + type: 'mrc_port', + fields: { + TYPE: 'SmartIO', + PORT_NUM: 1, + }, + }, + }, + }, + }), + }; +} + +/** + * Returns the blocks available for a servo component. + */ +export function getBlocks(componentName: string): ToolboxItems.ContentsType[] { + return [ + // Method: set_position(pos: float) -> None + { + kind: 'block', + type: 'mrc_call_python_function', + extraState: { + functionKind: 'instance_component', + returnType: 'None', + args: [ + { + name: 'pos', + type: 'float', + }, + ], + tooltip: 'Set the servo to a position between 0 and 1.', + importModule: '', + componentClassName: 'rev.Servo', + componentName, + }, + fields: { + COMPONENT_NAME: componentName, + FUNC: 'set_position', + }, + inputs: { + ARG0: { + block: { + type: 'math_number', + fields: { + NUM: 0.5, + }, + }, + }, + }, + }, + // Method: set_angle_degrees(angle: float) -> None + { + kind: 'block', + type: 'mrc_call_python_function', + extraState: { + functionKind: 'instance_component', + returnType: 'None', + args: [ + { + name: 'angle', + type: 'float', + }, + ], + tooltip: 'Set the servo to an angle between 0 and 270.', + importModule: '', + componentClassName: 'rev.Servo', + componentName, + }, + fields: { + COMPONENT_NAME: componentName, + FUNC: 'set_angle_degrees', + }, + inputs: { + ARG0: { + block: { + type: 'math_number', + fields: { + NUM: 180, + }, + }, + }, + }, + }, + ]; +} diff --git a/src/toolbox/hardware_components/smart_motor.ts b/src/toolbox/hardware_components/smart_motor.ts new file mode 100644 index 00000000..abbe1deb --- /dev/null +++ b/src/toolbox/hardware_components/smart_motor.ts @@ -0,0 +1,203 @@ +/** + * @license + * Copyright 2025 Porpoiseful LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @fileoverview SmartMotor hardware component definitions. + * @author alan@porpoiseful.com (Alan Smith) + */ + +import * as ToolboxItems from '../items'; + +export const TYPE_NAME = 'SmartMotor'; + +/** + * Returns a component definition block for a smart motor. + */ +export function getDefinitionBlock(hideParams: boolean): ToolboxItems.ContentsType { + return { + kind: 'block', + type: 'mrc_component', + fields: { + NAME: 'my_motor', + TYPE: TYPE_NAME, + }, + extraState: { + importModule: 'smart_motor', + params: [{name: 'motor_port', type: 'int'}], + hideParams, + }, + ...(hideParams ? {} : { + inputs: { + ARG0: { + shadow: { + type: 'mrc_port', + fields: { + TYPE: 'SmartMotor', + PORT_NUM: 1, + }, + }, + }, + }, + }), + }; +} + +/** + * Returns the blocks available for a smart motor component. + */ +export function getBlocks(componentName: string): ToolboxItems.ContentsType[] { + return [ + // Event: on_stall + { + kind: 'block', + type: 'mrc_event_handler', + extraState: { + tooltip: '', + pathOfSender: '', + typeOfSender: 'component', + params: [], + }, + fields: { + SENDER: componentName, + EVENT_NAME: 'on_stall', + }, + }, + // Method: set_speed(speed: float) -> None + { + kind: 'block', + type: 'mrc_call_python_function', + extraState: { + functionKind: 'instance_component', + returnType: 'None', + args: [ + { + name: 'speed', + type: 'float', + }, + ], + tooltip: 'Set the motor to a speed between -1 and 1.', + importModule: '', + componentClassName: 'rev.SmartMotor', + componentName, + }, + fields: { + COMPONENT_NAME: componentName, + FUNC: 'set_speed', + }, + inputs: { + ARG0: { + block: { + type: 'math_number', + fields: { + NUM: 0.8, + }, + }, + }, + }, + }, + // Method: set_angle_degrees(angle: float) -> None + { + kind: 'block', + type: 'mrc_call_python_function', + extraState: { + functionKind: 'instance_component', + returnType: 'None', + args: [ + { + name: 'angle', + type: 'float', + }, + ], + tooltip: 'Set the motor to an angle between 0 and 360.', + importModule: '', + componentClassName: 'rev.SmartMotor', + componentName, + }, + fields: { + COMPONENT_NAME: componentName, + FUNC: 'set_angle_degrees', + }, + inputs: { + ARG0: { + block: { + type: 'math_number', + fields: { + NUM: 180, + }, + }, + }, + }, + }, + // Method: get_num_relative_encoder_ticks() -> int + { + kind: 'block', + type: 'mrc_call_python_function', + extraState: { + functionKind: 'instance_component', + returnType: 'int', + args: [], + tooltip: 'Get the number of relative motor ticks since reset of encoder.', + importModule: '', + componentClassName: 'rev.SmartMotor', + componentName, + }, + fields: { + COMPONENT_NAME: componentName, + FUNC: 'get_num_relative_encoder_ticks', + }, + inputs: {}, + }, + // Method: get_angle_degrees() -> float + { + kind: 'block', + type: 'mrc_call_python_function', + extraState: { + functionKind: 'instance_component', + returnType: 'float', + args: [], + tooltip: 'Get the angle position of the motor.', + importModule: '', + componentClassName: 'rev.SmartMotor', + componentName, + }, + fields: { + COMPONENT_NAME: componentName, + FUNC: 'get_angle_degrees', + }, + inputs: {}, + }, + // Method: reset_relative_encoder() -> None + { + kind: 'block', + type: 'mrc_call_python_function', + extraState: { + functionKind: 'instance_component', + returnType: 'None', + args: [], + tooltip: 'Reset the relative encoder value to 0.', + importModule: '', + componentClassName: 'rev.SmartMotor', + componentName, + }, + fields: { + COMPONENT_NAME: componentName, + FUNC: 'reset_relative_encoder', + }, + inputs: {}, + }, + ]; +} \ No newline at end of file diff --git a/src/toolbox/hardware_components/touch_sensor.ts b/src/toolbox/hardware_components/touch_sensor.ts new file mode 100644 index 00000000..5b95a8f5 --- /dev/null +++ b/src/toolbox/hardware_components/touch_sensor.ts @@ -0,0 +1,134 @@ +/** + * @license + * Copyright 2025 Porpoiseful LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @fileoverview Touch Sensor hardware component definitions. + * @author alan@porpoiseful.com (Alan Smith) + */ + +import * as ToolboxItems from '../items'; + +export const TYPE_NAME = 'TouchSensor'; + +/** + * Returns a component definition block for a touch sensor. + */ +export function getDefinitionBlock(hideParams: boolean): ToolboxItems.ContentsType { + return { + kind: 'block', + type: 'mrc_component', + fields: { + NAME: 'my_touch_sensor', + TYPE: TYPE_NAME, + }, + extraState: { + importModule: 'rev_touch_sensor', + params: [{name: 'smartIO_port', type: 'int'}], + hideParams, + }, + ...(hideParams ? {} : { + inputs: { + ARG0: { + shadow: { + type: 'mrc_port', + fields: { + TYPE: 'SmartIO', + PORT_NUM: 1, + }, + }, + }, + }, + }), + }; +} + +/** + * Returns the blocks available for a touch sensor component. + */ +export function getBlocks(componentName: string): ToolboxItems.ContentsType[] { + return [ + // Event: pressed + { + kind: 'block', + type: 'mrc_event_handler', + extraState: { + tooltip: '', + pathOfSender: '', + typeOfSender: 'component', + params: [], + }, + fields: { + SENDER: 'my_touch_sensor', + EVENT_NAME: 'pressed', + }, + }, + // Event: released + { + kind: 'block', + type: 'mrc_event_handler', + extraState: { + tooltip: '', + pathOfSender: '', + typeOfSender: 'component', + params: [], + }, + fields: { + SENDER: 'my_touch_sensor', + EVENT_NAME: 'released', + }, + }, + // Event: changed with new_state parameter + { + kind: 'block', + type: 'mrc_event_handler', + extraState: { + tooltip: '', + pathOfSender: '', + typeOfSender: 'component', + params: [ + { + name: 'new_state', + type: 'boolean', + }, + ], + }, + fields: { + SENDER: 'my_touch_sensor', + EVENT_NAME: 'changed', + }, + }, + // Method: is_pressed() -> bool + { + kind: 'block', + type: 'mrc_call_python_function', + extraState: { + functionKind: 'instance_component', + returnType: 'bool', + args: [], + tooltip: 'Return whether the touch sensor is pressed.', + importModule: '', + componentClassName: 'rev.TouchSensor', + componentName, + }, + fields: { + COMPONENT_NAME: componentName, + FUNC: 'is_pressed', + }, + inputs: {}, + }, + ]; +} diff --git a/src/toolbox/robot_category.ts b/src/toolbox/robot_category.ts deleted file mode 100644 index e7bd2768..00000000 --- a/src/toolbox/robot_category.ts +++ /dev/null @@ -1,134 +0,0 @@ -export const category = -{ - kind: 'category', - name: 'Robot', - contents: [ - { - kind: 'category', - name: 'drive', - contents: [ - { - kind: 'block', - type: 'mrc_call_python_function', - extraState: { - functionKind: 'instance_component', - returnType: '', - args: [ - { - name: 'forward_speed', - type: 'float', - }, - { - name: 'strafe_right_speed', - type: 'float', - }, - { - name: 'rotate_cw_speed', - type: 'float', - }, - ], - tooltip: 'Drive (robot relative)', - importModule: '', - componentClassName: 'rev.ColorRangeSensor', - componentName: 'robot.drive', - }, - fields: { - COMPONENT_NAME: 'robot.drive', - FUNC: 'drive_field_relative', - }, - inputs: {}, - }, - ] - }, - { - kind: 'category', - name: 'claw', - contents: [ - { - kind: 'category', - name: 'gripper', - contents: [ - - ], - }, - { - kind: 'category', - name: 'piece_sensor', - contents: [ - // def get_color_rgb(self) -> tuple[int, int, int]: - { - kind: 'block', - type: 'mrc_call_python_function', - extraState: { - functionKind: 'instance_component', - returnType: 'tuple[int, int, int]', - args: [], - tooltip: 'Get the color in rgb (red, green, blue).', - importModule: '', - componentClassName: 'rev.ColorRangeSensor', - componentName: 'colorSensor', - }, - fields: { - COMPONENT_NAME: 'robot.claw.piece_sensor', - FUNC: 'get_color_rgb', - }, - inputs: {}, - }, - // def get_color_hsv(self) -> tuple[int, int, int]: - { - kind: 'block', - type: 'mrc_call_python_function', - extraState: { - functionKind: 'instance_component', - returnType: 'tuple[int, int, int]', - args: [], - tooltip: 'Get the color in hsv (hue, saturation, value).', - importModule: '', - componentClassName: 'rev.ColorRangeSensor', - componentName: 'colorSensor', - }, - fields: { - COMPONENT_NAME: 'robot.claw.piece_sensor', - FUNC: 'get_color_hsv', - }, - inputs: {}, - }, - // def get_distance_mm(self) -> float: - { - kind: 'block', - type: 'mrc_call_python_function', - extraState: { - functionKind: 'instance_component', - returnType: 'float', - args: [], - tooltip: 'Get the distance of the object seen.', - importModule: '', - componentClassName: 'rev.ColorRangeSensor', - componentName: 'colorSensor', - }, - fields: { - COMPONENT_NAME: 'robot.claw.piece_sensor', - FUNC: 'get_distance_mm', - }, - inputs: {}, - }, - ], - }, - ] - }, - { - kind: 'category', - name: 'flywheel', - contents: [ - - ], - }, - { - kind: 'category', - name: 'shooter', - contents: [ - - ], - }, - ], -} \ No newline at end of file diff --git a/src/toolbox/toolbox.ts b/src/toolbox/toolbox.ts new file mode 100644 index 00000000..1509966a --- /dev/null +++ b/src/toolbox/toolbox.ts @@ -0,0 +1,37 @@ +import * as Blockly from 'blockly/core'; +import * as commonStorage from '../storage/common_storage'; +import * as common from './toolbox_common' +import { getHardwareCategory } from './hardware_category'; +import { category as eventCategory } from './event_category'; + +export function getToolboxJSON( + shownPythonToolboxCategories: Set | null, + currentModule: commonStorage.Module): Blockly.utils.toolbox.ToolboxDefinition { + switch (currentModule.moduleType) { + case commonStorage.MODULE_TYPE_PROJECT: + case commonStorage.MODULE_TYPE_MECHANISM: + return { + kind: 'categoryToolbox', + contents: [ + getHardwareCategory(currentModule), + { kind: 'sep' }, + ...common.getToolboxItems(shownPythonToolboxCategories), + eventCategory, + ] + }; + case commonStorage.MODULE_TYPE_OPMODE: + return { + kind: 'categoryToolbox', + contents: [ + getHardwareCategory(currentModule), + { kind: 'sep' }, + ...common.getToolboxItems(shownPythonToolboxCategories) + ] + }; + default: + return { + kind: 'categoryToolbox', + contents: [] + }; + } +} \ No newline at end of file diff --git a/src/toolbox/toolbox_mechanism.ts b/src/toolbox/toolbox_mechanism.ts deleted file mode 100644 index ce841212..00000000 --- a/src/toolbox/toolbox_mechanism.ts +++ /dev/null @@ -1,19 +0,0 @@ -import * as common from './toolbox_common' -import { category as hardwareComponentCategory } from './add_hardware_component_category'; -import { category as eventCategory } from './event_category'; -import { category as componentsCategory } from './components_category'; - -export function getToolboxJSON( - shownPythonToolboxCategories: Set | null) { - - return { - kind: 'categoryToolbox', - contents: [ - hardwareComponentCategory, - componentsCategory, - eventCategory, - { kind: 'sep' }, - ...common.getToolboxItems(shownPythonToolboxCategories) - ] - }; -} diff --git a/src/toolbox/toolbox_opmode.ts b/src/toolbox/toolbox_opmode.ts deleted file mode 100644 index 2b2e3139..00000000 --- a/src/toolbox/toolbox_opmode.ts +++ /dev/null @@ -1,34 +0,0 @@ - import * as common from './toolbox_common' - import {category as robotCategory} from './/robot_category'; - - export function getToolboxJSON( - shownPythonToolboxCategories: Set | null) { - - return { - kind: 'categoryToolbox', - contents: [ - robotCategory, - { kind: 'sep' }, - ...common.getToolboxItems(shownPythonToolboxCategories) - ] - }; - } - /** TODO: - * The opmode will need to have blocks for all the methods that are in the - * robot. This commented out code will have to be reworked in the future to - * do this. - */ - /*if (opt_robotBlocks.length) { - contents.push.apply( - contents, - [ - { - kind: 'sep', - }, - { - kind: 'category', - name: 'Project', - contents: opt_robotBlocks, - }, - ]); - }*/ \ No newline at end of file diff --git a/src/toolbox/toolbox_robot.ts b/src/toolbox/toolbox_robot.ts deleted file mode 100644 index c61acc72..00000000 --- a/src/toolbox/toolbox_robot.ts +++ /dev/null @@ -1,18 +0,0 @@ - import * as common from './toolbox_common' - import {category as hardwareCategory} from './hardware_category'; - import {category as eventCategory} from './event_category'; - - export function getToolboxJSON( - shownPythonToolboxCategories: Set | null) { - - return { - kind: 'categoryToolbox', - contents: [ - hardwareCategory, - eventCategory, - { kind: 'sep' }, - ...common.getToolboxItems(shownPythonToolboxCategories) - ] - }; - } - \ No newline at end of file