diff --git a/newIDE/app/src/EventsFunctionsExtensionEditor/EventsBasedBehaviorOrObjectEditor/EventsBasedBehaviorOrObjectEditorDialog.js b/newIDE/app/src/EventsFunctionsExtensionEditor/EventsBasedBehaviorOrObjectEditor/EventsBasedBehaviorOrObjectEditorDialog.js new file mode 100644 index 000000000000..35f6021c1780 --- /dev/null +++ b/newIDE/app/src/EventsFunctionsExtensionEditor/EventsBasedBehaviorOrObjectEditor/EventsBasedBehaviorOrObjectEditorDialog.js @@ -0,0 +1,386 @@ +// @flow +import { Trans } from '@lingui/macro'; +import * as React from 'react'; +import { t } from '@lingui/macro'; + +import { type UnsavedChanges } from '../../MainFrame/UnsavedChangesContext'; +import { type ExtensionItemConfigurationAttribute } from '../../EventsFunctionsExtensionEditor'; +import { ProjectScopedContainersAccessor } from '../../InstructionOrExpression/EventsScope'; +import { LineStackLayout } from '../../UI/Layout'; +import { + EventsBasedBehaviorOrObjectEditor, + type EventsBasedBehaviorOrObjectEditorInterface, +} from '.'; +import PropertyListEditor, { + type PropertyListEditorInterface, +} from '../PropertyListEditor'; +import FlatButton from '../../UI/FlatButton'; +import HelpButton from '../../UI/HelpButton'; +import Dialog from '../../UI/Dialog'; +import { type VariableDialogOpeningProps } from '../../VariablesList/VariablesEditorDialog'; +import EditorNavigator from '../../UI/EditorMosaic/EditorNavigator'; +import { type Editor } from '../../UI/EditorMosaic'; +import TuneIcon from '../../UI/CustomSvgIcons/Tune'; +import { useResponsiveWindowSize } from '../../UI/Responsive/ResponsiveWindowMeasurer'; +import AddIcon from '../../UI/CustomSvgIcons/Add'; +import newNameGenerator from '../../Utils/NewNameGenerator'; +import { Divider } from '@material-ui/core'; + +const styles = { + simpleSizeContainer: { + display: 'flex', + flex: 1, + }, + doubleSizeContainer: { + display: 'flex', + flex: 2, + }, +}; + +const noop = () => {}; + +type Props = {| + project: gdProject, + projectScopedContainersAccessor: ProjectScopedContainersAccessor, + eventsFunctionsExtension: gdEventsFunctionsExtension, + eventsBasedBehavior?: ?gdEventsBasedBehavior, + eventsBasedObject?: ?gdEventsBasedObject, + onRenameProperty: (oldName: string, newName: string) => void, + onRenameSharedProperty: (oldName: string, newName: string) => void, + onPropertyTypeChanged: (propertyName: string) => void, + onPropertiesUpdated: () => void, + onEventsFunctionsAdded: () => void, + unsavedChanges?: ?UnsavedChanges, + onConfigurationUpdated?: (?ExtensionItemConfigurationAttribute) => void, + onOpenCustomObjectEditor: () => void, + onEventsBasedObjectChildrenEdited: ( + eventsBasedObject: gdEventsBasedObject + ) => void, + onWillInstallExtension: (extensionNames: Array) => void, + onExtensionInstalled: (extensionNames: Array) => void, + onClose: () => void, + initiallySelectedProperty: VariableDialogOpeningProps | null, +|}; + +export default function EventsBasedBehaviorOrObjectEditorDialog({ + eventsBasedBehavior, + eventsBasedObject, + eventsFunctionsExtension, + project, + projectScopedContainersAccessor, + onRenameProperty, + onRenameSharedProperty, + onPropertyTypeChanged, + unsavedChanges, + onEventsFunctionsAdded, + onConfigurationUpdated, + onPropertiesUpdated, + onOpenCustomObjectEditor, + onEventsBasedObjectChildrenEdited, + onWillInstallExtension, + onExtensionInstalled, + onClose, + initiallySelectedProperty, +}: Props): React.Node { + const propertyEditor = React.useRef( + null + ); + const propertyList = React.useRef(null); + + const lastFocusedProperty = React.useRef<{ + propertyName: string, + isSharedProperties: boolean, + } | null>(null); + + const eventsBasedEntity = eventsBasedBehavior || eventsBasedObject; + + const addProperty = React.useCallback( + (name?: string, type?: string | null) => { + if (!eventsBasedEntity) { + return; + } + const properties = eventsBasedEntity.getPropertyDescriptors(); + const newName = newNameGenerator(name || 'Property', name => + properties.has(name) + ); + const property = properties.insertNew(newName, properties.getCount()); + property.setType(type || 'Number'); + + if (propertyEditor.current) { + propertyEditor.current.forceUpdateProperties(); + } + if (propertyList.current) { + propertyList.current.forceUpdateList(); + } + // Scroll to the selected property. + // Ideally, we'd wait for the list to be updated to scroll, but + // to simplify the code, we just wait a few ms for a new render + // to be done. + setTimeout(() => { + if (propertyList.current) { + propertyList.current.setSelectedProperty(newName, false); + } + if (propertyEditor.current) { + propertyEditor.current.scrollToProperty(newName, false); + } + if (propertyEditor.current) { + propertyEditor.current.focusOnProperty(newName, false); + } + }, 100); // A few ms is enough for a new render to be done. + onPropertiesUpdated(); + }, + [eventsBasedEntity, onPropertiesUpdated] + ); + + React.useEffect( + () => { + if (!eventsBasedEntity) { + return; + } + const properties = eventsBasedEntity.getPropertyDescriptors(); + if (!initiallySelectedProperty || !properties) { + return; + } + if (initiallySelectedProperty.shouldCreate) { + const propertyType = + initiallySelectedProperty.variableType === 'number' + ? 'Number' + : initiallySelectedProperty.variableType === 'string' + ? 'String' + : initiallySelectedProperty.variableType === 'boolean' + ? 'Boolean' + : initiallySelectedProperty.variableType; + addProperty(initiallySelectedProperty.variableName, propertyType); + } else { + // Scroll to the selected property. + // Ideally, we'd wait for the list to be updated to scroll, but + // to simplify the code, we just wait a few ms for a new render + // to be done. + setTimeout(() => { + const currentPropertyEditor = propertyEditor.current; + if (currentPropertyEditor) { + currentPropertyEditor.scrollToProperty( + initiallySelectedProperty.variableName, + false + ); + } + const currentPropertyList = propertyList.current; + if (currentPropertyList) { + currentPropertyList.setSelectedProperty( + initiallySelectedProperty.variableName, + false + ); + } + }, 100); // A few ms is enough for a new render to be done. + } + }, + // eslint-disable-next-line react-hooks/exhaustive-deps + [] + ); + + const editors: { + [string]: Editor, + } = { + propertyList: { + type: 'primary', + noTitleBar: true, + title: t`Properties`, + toolbarControls: [], + renderEditor: () => ( + { + if (propertyEditor.current) { + propertyEditor.current.forceUpdateProperties(); + } + onPropertiesUpdated(); + }} + onOpenConfiguration={propertyName => { + if (propertyEditor.current) { + propertyEditor.current.scrollToConfiguration(); + } + }} + onOpenProperty={(propertyName, isSharedProperties) => { + if (propertyEditor.current) { + propertyEditor.current.scrollToProperty( + propertyName, + isSharedProperties + ); + } + }} + onEventsFunctionsAdded={onEventsFunctionsAdded} + /> + ), + }, + propertyEditor: { + type: 'primary', + noTitleBar: true, + noSoftKeyboardAvoidance: true, + title: eventsBasedBehavior + ? t`Behavior Configuration` + : eventsBasedObject + ? t`Object Configuration` + : null, + toolbarControls: [], + renderEditor: () => ( + { + if (propertyList.current) { + propertyList.current.forceUpdateList(); + } + onPropertiesUpdated(); + }} + onFocusProperty={(propertyName, isSharedProperties) => { + lastFocusedProperty.current = { propertyName, isSharedProperties }; + if (propertyList.current) { + propertyList.current.setSelectedProperty( + propertyName, + isSharedProperties + ); + } + }} + shouldHideAddPropertyButton={true} + /> + ), + }, + }; + + const { isMobile } = useResponsiveWindowSize(); + + return ( + Properties} + secondaryActions={[ + , + Add a property} + onClick={() => addProperty()} + leftIcon={} + />, + ]} + actions={[ + Close} + primary={false} + onClick={onClose} + id="close-button" + />, + ]} + onRequestClose={onClose} + onApply={onClose} + open + flexBody + fullHeight + id="properties-editor-dialog" + > + + {isMobile ? ( + , + nextLabel: Property list, + previousEditor: null, + nextEditor: () => { + const selection = lastFocusedProperty.current; + if (selection) { + const { propertyName, isSharedProperties } = selection; + // Scroll to the selected property. + // Ideally, we'd wait for the list to be updated to scroll, but + // to simplify the code, we just wait a few ms for a new render + // to be done. + setTimeout(() => { + if (propertyList.current) { + propertyList.current.setSelectedProperty( + propertyName, + isSharedProperties + ); + } + }, 100); // A few ms is enough for a new render to be done. + } + return 'propertyList'; + }, + }, + propertyList: { + nextIcon: null, + nextLabel: null, + nextEditor: null, + previousEditor: () => { + if (propertyList.current) { + const selection = propertyList.current.getSelectedProperty(); + if (selection) { + const { propertyName, isSharedProperties } = selection; + // Scroll to the selected property. + // Ideally, we'd wait for the list to be updated to scroll, but + // to simplify the code, we just wait a few ms for a new render + // to be done. + setTimeout(() => { + if (propertyEditor.current) { + propertyEditor.current.scrollToProperty( + propertyName, + isSharedProperties + ); + } + }, 100); // A few ms is enough for a new render to be done. + } + } + return 'propertyEditor'; + }, + }, + }} + onEditorChanged={ + // It's important that this callback is the same across renders, + // to avoid confusing EditorNavigator into thinking it's changed + // and immediately calling it, which would trigger an infinite loop. + // Search for "callback-prevent-infinite-rerendering" in the codebase. + noop + } + /> + ) : ( + <> +
+ {editors.propertyEditor.renderEditor()} +
+ +
+ {editors.propertyList.renderEditor()} +
+ + )} +
+
+ ); +} diff --git a/newIDE/app/src/EventsFunctionsExtensionEditor/EventsBasedBehaviorOrObjectEditor/EventsBasedBehaviorOrObjectPropertiesEditor.js b/newIDE/app/src/EventsFunctionsExtensionEditor/EventsBasedBehaviorOrObjectEditor/EventsBasedBehaviorOrObjectPropertiesEditor.js index 93afcbd4dd63..6127bdea0ae2 100644 --- a/newIDE/app/src/EventsFunctionsExtensionEditor/EventsBasedBehaviorOrObjectEditor/EventsBasedBehaviorOrObjectPropertiesEditor.js +++ b/newIDE/app/src/EventsFunctionsExtensionEditor/EventsBasedBehaviorOrObjectEditor/EventsBasedBehaviorOrObjectPropertiesEditor.js @@ -41,6 +41,7 @@ import VariableStringIcon from '../../VariablesList/Icons/VariableStringIcon'; import VariableNumberIcon from '../../VariablesList/Icons/VariableNumberIcon'; import VariableBooleanIcon from '../../VariablesList/Icons/VariableBooleanIcon'; import NewBehaviorDialog from '../../BehaviorsEditor/NewBehaviorDialog'; +import { type CompactTextFieldInterface } from '../../UI/CompactTextField'; const gd: libGDevelop = global.gd; @@ -179,6 +180,7 @@ const getChoicesArray = ( export type EventsBasedBehaviorOrObjectPropertiesEditorInterface = {| forceUpdate: () => void, getPropertyEditorRef: (propertyName: string) => React.ElementRef, + focusOnProperty: (propertyName: string) => void, |}; export const EventsBasedBehaviorOrObjectPropertiesEditor: React.ComponentType<{ @@ -210,10 +212,22 @@ export const EventsBasedBehaviorOrObjectPropertiesEditor: React.ComponentType<{ ) => { const forceUpdate = useForceUpdate(); const propertyRefs = React.useRef(new Map>()); + const propertyNameFieldRefs = React.useRef( + new Map() + ); React.useImperativeHandle(ref, () => ({ forceUpdate, getPropertyEditorRef: (propertyName: string) => propertyRefs ? propertyRefs.current.get(propertyName) : null, + focusOnProperty: (propertyName: string) => { + const propertyNameField = propertyNameFieldRefs.current.get( + propertyName + ); + if (propertyNameField) { + propertyNameField.focus(); + propertyNameField.select(); + } + }, })); const [newBehaviorDialogOpen, setNewBehaviorDialogOpen] = React.useState<{ @@ -233,7 +247,6 @@ export const EventsBasedBehaviorOrObjectPropertiesEditor: React.ComponentType<{ property.setType('Number'); forceUpdate(); onPropertiesUpdated(); - //setJustAddedPropertyName(newName); }, [forceUpdate, onPropertiesUpdated, properties] ); @@ -309,6 +322,7 @@ export const EventsBasedBehaviorOrObjectPropertiesEditor: React.ComponentType<{ ); propertyRefs.current.clear(); + propertyNameFieldRefs.current.clear(); return ( @@ -349,6 +363,12 @@ export const EventsBasedBehaviorOrObjectPropertiesEditor: React.ComponentType<{ { + propertyNameFieldRefs.current.set( + property.getName(), + ref + ); + }} commitOnBlur placeholder={i18n._( t`Enter the property name` diff --git a/newIDE/app/src/EventsFunctionsExtensionEditor/EventsBasedBehaviorOrObjectEditor/index.js b/newIDE/app/src/EventsFunctionsExtensionEditor/EventsBasedBehaviorOrObjectEditor/index.js index 3fbcdab2cd2a..199105e96169 100644 --- a/newIDE/app/src/EventsFunctionsExtensionEditor/EventsBasedBehaviorOrObjectEditor/index.js +++ b/newIDE/app/src/EventsFunctionsExtensionEditor/EventsBasedBehaviorOrObjectEditor/index.js @@ -42,12 +42,14 @@ type Props = {| ) => void, onWillInstallExtension: (extensionNames: Array) => void, onExtensionInstalled: (extensionNames: Array) => void, + shouldHideAddPropertyButton?: boolean, |}; export type EventsBasedBehaviorOrObjectEditorInterface = {| forceUpdateProperties: () => void, scrollToConfiguration: () => void, scrollToProperty: (propertyName: string, isSharedProperties: boolean) => void, + focusOnProperty: (propertyName: string, isSharedProperties: boolean) => void, |}; export const EventsBasedBehaviorOrObjectEditor: React.ComponentType<{ @@ -73,6 +75,7 @@ export const EventsBasedBehaviorOrObjectEditor: React.ComponentType<{ onEventsBasedObjectChildrenEdited, onWillInstallExtension, onExtensionInstalled, + shouldHideAddPropertyButton, }: Props, ref ) => { @@ -127,6 +130,17 @@ export const EventsBasedBehaviorOrObjectEditor: React.ComponentType<{ scenePropertiesEditor.current.forceUpdate(); } }, + focusOnProperty: (propertyName: string, isSharedProperties: boolean) => { + if (isSharedProperties) { + if (scenePropertiesEditor.current) { + scenePropertiesEditor.current.focusOnProperty(propertyName); + } + } else { + if (propertiesEditor.current) { + propertiesEditor.current.focusOnProperty(propertyName); + } + } + }, scrollToConfiguration: () => { if (scrollView.current) { scrollView.current.scrollToPosition(0); @@ -271,7 +285,7 @@ export const EventsBasedBehaviorOrObjectEditor: React.ComponentType<{ - {windowSize === 'small' && ( + {windowSize === 'small' && !shouldHideAddPropertyButton && ( void, @@ -129,7 +133,7 @@ const extensionEditIconReactNode = ; // The event based object editor is hidden in releases // because it's not handled by GDJS. -const getInitialMosaicEditorNodes = () => ({ +const getInitialMosaicEditorNodes = (): EditorMosaicNode => ({ direction: 'row', first: 'functions-list', second: { @@ -158,6 +162,7 @@ export default class EventsFunctionsExtensionEditor extends React.Component< extensionFunctionSelectorDialogOpen: false, eventsBasedObjectSelectorDialogOpen: false, variablesEditorOpen: null, + eventsBasedEntityPropertiesDialogOpen: null, onAddEventsFunctionCb: null, onAddEventsBasedObjectCb: null, }; @@ -1189,7 +1194,7 @@ export default class EventsFunctionsExtensionEditor extends React.Component< }); }; - _editVariables = ( + _openVariableEditorDialog = ( options: { isGlobalTabInitiallyOpen: boolean } | null = { isGlobalTabInitiallyOpen: false, } @@ -1342,6 +1347,14 @@ export default class EventsFunctionsExtensionEditor extends React.Component< this.eventsFunctionConfigurationEditor.editEventsFunctionParameter(props); }; + _openEventsBasedEntityPropertyEditorDialog = ( + props: VariableDialogOpeningProps + ) => { + this.setState({ + eventsBasedEntityPropertiesDialogOpen: props, + }); + }; + render(): any { const { project, eventsFunctionsExtension } = this.props; @@ -1355,6 +1368,7 @@ export default class EventsFunctionsExtensionEditor extends React.Component< extensionFunctionSelectorDialogOpen, eventsBasedObjectSelectorDialogOpen, variablesEditorOpen, + eventsBasedEntityPropertiesDialogOpen, } = this.state; const scope = { @@ -1370,7 +1384,9 @@ export default class EventsFunctionsExtensionEditor extends React.Component< const selectedEventsBasedEntity = selectedEventsBasedBehavior || selectedEventsBasedObject; - const editors = { + const editors: { + [string]: Editor, + } = { parameters: { type: 'primary', title: selectedEventsFunction @@ -1563,6 +1579,9 @@ export default class EventsFunctionsExtensionEditor extends React.Component< onWillInstallExtension={this.props.onWillInstallExtension} onExtensionInstalled={this.props.onExtensionInstalled} editEventsFunctionParameter={this._editEventsFunctionParameter} + openEventsBasedEntityPropertyEditorDialog={ + this._openEventsBasedEntityPropertyEditorDialog + } /> ) : selectedEventsBasedBehavior && @@ -1732,9 +1751,13 @@ export default class EventsFunctionsExtensionEditor extends React.Component< onAddEventsBasedObject={this._onAddEventsBasedObject} onSelectExtensionProperties={() => this._editOptions(true)} onSelectExtensionGlobalVariables={() => - this._editVariables({ isGlobalTabInitiallyOpen: true }) + this._openVariableEditorDialog({ + isGlobalTabInitiallyOpen: true, + }) + } + onSelectExtensionSceneVariables={() => + this._openVariableEditorDialog() } - onSelectExtensionSceneVariables={() => this._editVariables()} onOpenCustomObjectEditor={this.props.onOpenCustomObjectEditor} onEventBasedObjectTypeChanged={ this.props.onEventBasedObjectTypeChanged @@ -1755,7 +1778,6 @@ export default class EventsFunctionsExtensionEditor extends React.Component< ref={editorNavigator => (this._editorNavigator = editorNavigator) } - // $FlowFixMe[incompatible-type] editors={editors} initialEditorName={'functions-list'} transitions={{ @@ -1840,16 +1862,13 @@ export default class EventsFunctionsExtensionEditor extends React.Component< mosaicContainsNode( getDefaultEditorMosaicNode( 'events-functions-extension-editor' - // $FlowFixMe[incompatible-type] ) || getInitialMosaicEditorNodes(), 'functions-list' ) ? getDefaultEditorMosaicNode( 'events-functions-extension-editor' - // $FlowFixMe[incompatible-type] ) || getInitialMosaicEditorNodes() : // Force the mosaic to reset to default. - // $FlowFixMe[incompatible-type] getInitialMosaicEditorNodes() } /> @@ -1879,13 +1898,115 @@ export default class EventsFunctionsExtensionEditor extends React.Component< }) } open - onCancel={() => this._editVariables(null)} - onApply={() => this._editVariables(null)} + onCancel={() => this._openVariableEditorDialog(null)} + onApply={() => this._openVariableEditorDialog(null)} hotReloadPreviewButtonProps={this.props.hotReloadPreviewButtonProps} isListLocked={false} initiallySelectedVariable={null} /> )} + {eventsBasedEntityPropertiesDialogOpen && + this._projectScopedContainersAccessor && + (selectedEventsBasedBehavior ? ( + { + this.setState({ + eventsBasedEntityPropertiesDialogOpen: null, + }); + }} + project={project} + projectScopedContainersAccessor={ + this._projectScopedContainersAccessor + } + eventsFunctionsExtension={eventsFunctionsExtension} + eventsBasedBehavior={selectedEventsBasedBehavior} + unsavedChanges={this.props.unsavedChanges} + onRenameProperty={(oldName, newName) => + this._onBehaviorPropertyRenamed( + selectedEventsBasedBehavior, + oldName, + newName + ) + } + onRenameSharedProperty={(oldName, newName) => + this._onBehaviorSharedPropertyRenamed( + selectedEventsBasedBehavior, + oldName, + newName + ) + } + onPropertyTypeChanged={propertyName => { + gd.WholeProjectRefactorer.changeEventsBasedBehaviorPropertyType( + project, + eventsFunctionsExtension, + selectedEventsBasedBehavior, + propertyName + ); + }} + onPropertiesUpdated={() => { + this.forceUpdate(); + }} + onEventsFunctionsAdded={() => { + if (this.eventsFunctionList) { + this.eventsFunctionList.forceUpdateList(); + } + }} + onConfigurationUpdated={this._onConfigurationUpdated} + onOpenCustomObjectEditor={() => {}} + onEventsBasedObjectChildrenEdited={() => {}} + onWillInstallExtension={this.props.onWillInstallExtension} + onExtensionInstalled={this.props.onExtensionInstalled} + /> + ) : selectedEventsBasedObject ? ( + { + this.setState({ + eventsBasedEntityPropertiesDialogOpen: null, + }); + }} + project={project} + projectScopedContainersAccessor={ + this._projectScopedContainersAccessor + } + eventsFunctionsExtension={eventsFunctionsExtension} + eventsBasedObject={selectedEventsBasedObject} + unsavedChanges={this.props.unsavedChanges} + onRenameProperty={(oldName, newName) => + this._onObjectPropertyRenamed( + selectedEventsBasedObject, + oldName, + newName + ) + } + onRenameSharedProperty={() => {}} + onPropertyTypeChanged={propertyName => { + gd.WholeProjectRefactorer.changeEventsBasedObjectPropertyType( + project, + eventsFunctionsExtension, + selectedEventsBasedObject, + propertyName + ); + }} + onPropertiesUpdated={() => { + this.forceUpdate(); + }} + onEventsFunctionsAdded={() => { + if (this.eventsFunctionList) { + this.eventsFunctionList.forceUpdateList(); + } + }} + onOpenCustomObjectEditor={() => + this.props.onOpenCustomObjectEditor(selectedEventsBasedObject) + } + onEventsBasedObjectChildrenEdited={ + this.props.onEventsBasedObjectChildrenEdited + } + onWillInstallExtension={this.props.onWillInstallExtension} + onExtensionInstalled={this.props.onExtensionInstalled} + /> + ) : null)} {objectMethodSelectorDialogOpen && selectedEventsBasedObject && ( void, + openEventsBasedEntityPropertyEditorDialog: VariableDialogOpeningProps => void, |}; const InlineParameterEditor = ({ @@ -60,6 +61,7 @@ const InlineParameterEditor = ({ anchorEl, resourceManagementProps, editEventsFunctionParameter, + openEventsBasedEntityPropertyEditorDialog, }: Props): null | React.Node => { const portalContainer = React.useContext(PortalContainerContext); const [ @@ -191,6 +193,9 @@ const InlineParameterEditor = ({ isInline resourceManagementProps={resourceManagementProps} editEventsFunctionParameter={editEventsFunctionParameter} + openEventsBasedEntityPropertyEditorDialog={ + openEventsBasedEntityPropertyEditorDialog + } /> ); diff --git a/newIDE/app/src/EventsSheet/InstructionEditor/InstructionEditorDialog.js b/newIDE/app/src/EventsSheet/InstructionEditor/InstructionEditorDialog.js index 13092e982abf..630940aa4d50 100644 --- a/newIDE/app/src/EventsSheet/InstructionEditor/InstructionEditorDialog.js +++ b/newIDE/app/src/EventsSheet/InstructionEditor/InstructionEditorDialog.js @@ -81,6 +81,7 @@ type Props = {| onWillInstallExtension: (extensionNames: Array) => void, onExtensionInstalled: (extensionNames: Array) => void, editEventsFunctionParameter: VariableDialogOpeningProps => void, + openEventsBasedEntityPropertyEditorDialog: VariableDialogOpeningProps => void, |}; const getInitialStepName = (isNewInstruction: boolean): StepName => { @@ -118,6 +119,7 @@ const InstructionEditorDialog = ({ onExtensionInstalled, i18n, editEventsFunctionParameter, + openEventsBasedEntityPropertyEditorDialog, }: Props) => { const forceUpdate = useForceUpdate(); const [ @@ -393,6 +395,9 @@ const InstructionEditorDialog = ({ focusOnMount={shouldAutofocusInput && !!instructionType} noHelpButton id="object-instruction-parameters" + openEventsBasedEntityPropertyEditorDialog={ + openEventsBasedEntityPropertyEditorDialog + } /> ); diff --git a/newIDE/app/src/EventsSheet/InstructionEditor/InstructionEditorMenu.js b/newIDE/app/src/EventsSheet/InstructionEditor/InstructionEditorMenu.js index dd3b723f74b5..f714017f4ca2 100644 --- a/newIDE/app/src/EventsSheet/InstructionEditor/InstructionEditorMenu.js +++ b/newIDE/app/src/EventsSheet/InstructionEditor/InstructionEditorMenu.js @@ -64,6 +64,7 @@ type Props = {| onWillInstallExtension: (extensionNames: Array) => void, onExtensionInstalled: (extensionNames: Array) => void, editEventsFunctionParameter: VariableDialogOpeningProps => void, + openEventsBasedEntityPropertyEditorDialog: VariableDialogOpeningProps => void, |}; /** diff --git a/newIDE/app/src/EventsSheet/InstructionEditor/InstructionParametersEditor.js b/newIDE/app/src/EventsSheet/InstructionEditor/InstructionParametersEditor.js index 842361ae0c81..a27077d0e816 100644 --- a/newIDE/app/src/EventsSheet/InstructionEditor/InstructionParametersEditor.js +++ b/newIDE/app/src/EventsSheet/InstructionEditor/InstructionParametersEditor.js @@ -40,6 +40,7 @@ import { } from '../ParameterFields/ParameterFieldCommons'; import Edit from '../../UI/CustomSvgIcons/Edit'; import { ProjectScopedContainersAccessor } from '../../InstructionOrExpression/EventsScope'; +import { type VariableDialogOpeningProps } from '../../VariablesList/VariablesEditorDialog'; const gd: libGDevelop = global.gd; @@ -90,6 +91,7 @@ type Props = {| ) => void, noHelpButton?: boolean, id?: string, + openEventsBasedEntityPropertyEditorDialog: VariableDialogOpeningProps => void, |}; const isParameterVisible = ( @@ -136,6 +138,7 @@ const InstructionParametersEditor: React.ComponentType<{ openInstructionOrExpression, resourceManagementProps, id, + openEventsBasedEntityPropertyEditorDialog, }, ref ) => { @@ -434,6 +437,9 @@ const InstructionParametersEditor: React.ComponentType<{ firstVisibleField.current = field; } }} + openEventsBasedEntityPropertyEditorDialog={ + openEventsBasedEntityPropertyEditorDialog + } /> ); })} diff --git a/newIDE/app/src/EventsSheet/ParameterFields/AnyVariableField.js b/newIDE/app/src/EventsSheet/ParameterFields/AnyVariableField.js index 56b756d6659f..c8f31e03e27c 100644 --- a/newIDE/app/src/EventsSheet/ParameterFields/AnyVariableField.js +++ b/newIDE/app/src/EventsSheet/ParameterFields/AnyVariableField.js @@ -23,8 +23,8 @@ export default (React.forwardRef( function AnyVariableField(props: ParameterFieldProps, ref) { const field = React.useRef(null); const [ - editorOpen, - setEditorOpen, + variableEditorOpen, + setVariableEditorOpen, ] = React.useState(null); const focus: FieldFocusFunction = options => { if (field.current) field.current.focus(options); @@ -78,7 +78,7 @@ export default (React.forwardRef( if (selectedVariableName && selectedVariableName.startsWith(value)) { onChange(selectedVariableName); } - setEditorOpen(null); + setVariableEditorOpen(null); // The variable editor may have refactor the events for a variable type // change which may have change the currently edited instruction type. if (onInstructionTypeChanged) onInstructionTypeChanged(); @@ -116,7 +116,7 @@ export default (React.forwardRef( onRequestClose={props.onRequestClose} onApply={props.onApply} ref={field} - onOpenDialog={setEditorOpen} + openVariableEditorDialog={setVariableEditorOpen} globalObjectsContainer={props.globalObjectsContainer} objectsContainer={props.objectsContainer} projectScopedContainersAccessor={projectScopedContainersAccessor} @@ -129,8 +129,9 @@ export default (React.forwardRef( onInstructionTypeChanged={onInstructionTypeChanged} getVariableSourceFromIdentifier={getVariableSourceFromIdentifier} editEventsFunctionParameter={null} + openEventsBasedEntityPropertyEditorDialog={null} /> - {editorOpen && + {variableEditorOpen && (variableSourceType === gd.VariablesContainer.Local ? ( project && ( ( } variablesContainer={variablesContainer} open - onCancel={() => setEditorOpen(null)} + onCancel={() => setVariableEditorOpen(null)} onApply={onVariableEditorApply} - initiallySelectedVariable={editorOpen} + initiallySelectedVariable={variableEditorOpen} isListLocked={false} /> ) @@ -150,12 +151,12 @@ export default (React.forwardRef( setEditorOpen(null)} + onCancel={() => setVariableEditorOpen(null)} onApply={onVariableEditorApply} isGlobalTabInitiallyOpen={ variableSourceType === gd.VariablesContainer.Global } - initiallySelectedVariable={editorOpen} + initiallySelectedVariable={variableEditorOpen} hotReloadPreviewButtonProps={null} isListLocked={false} /> diff --git a/newIDE/app/src/EventsSheet/ParameterFields/AnyVariableOrPropertyField.js b/newIDE/app/src/EventsSheet/ParameterFields/AnyVariableOrPropertyField.js index 2310bde7a9fe..4a3ce6103aab 100644 --- a/newIDE/app/src/EventsSheet/ParameterFields/AnyVariableOrPropertyField.js +++ b/newIDE/app/src/EventsSheet/ParameterFields/AnyVariableOrPropertyField.js @@ -23,8 +23,8 @@ export default (React.forwardRef( function AnyVariableField(props: ParameterFieldProps, ref) { const field = React.useRef(null); const [ - editorOpen, - setEditorOpen, + variableEditorOpen, + setVariableEditorOpen, ] = React.useState(null); const focus: FieldFocusFunction = options => { if (field.current) field.current.focus(options); @@ -41,6 +41,7 @@ export default (React.forwardRef( projectScopedContainersAccessor, onChange, value, + openEventsBasedEntityPropertyEditorDialog, } = props; const enumerateGlobalAndSceneVariables = React.useCallback( @@ -76,7 +77,7 @@ export default (React.forwardRef( if (selectedVariableName && selectedVariableName.startsWith(value)) { onChange(selectedVariableName); } - setEditorOpen(null); + setVariableEditorOpen(null); // The variable editor may have refactor the events for a variable type // change which may have change the currently edited instruction type. if (onInstructionTypeChanged) onInstructionTypeChanged(); @@ -114,7 +115,7 @@ export default (React.forwardRef( onRequestClose={props.onRequestClose} onApply={props.onApply} ref={field} - onOpenDialog={setEditorOpen} + openVariableEditorDialog={setVariableEditorOpen} globalObjectsContainer={props.globalObjectsContainer} objectsContainer={props.objectsContainer} projectScopedContainersAccessor={projectScopedContainersAccessor} @@ -127,8 +128,11 @@ export default (React.forwardRef( onInstructionTypeChanged={onInstructionTypeChanged} getVariableSourceFromIdentifier={getVariableSourceFromIdentifier} editEventsFunctionParameter={null} + openEventsBasedEntityPropertyEditorDialog={ + openEventsBasedEntityPropertyEditorDialog || null + } /> - {editorOpen && + {variableEditorOpen && (variableSourceType === gd.VariablesContainer.Local ? ( project && ( ( } variablesContainer={variablesContainer} open - onCancel={() => setEditorOpen(null)} + onCancel={() => setVariableEditorOpen(null)} onApply={onVariableEditorApply} - initiallySelectedVariable={editorOpen} + initiallySelectedVariable={variableEditorOpen} isListLocked={false} /> ) @@ -148,13 +152,13 @@ export default (React.forwardRef( setEditorOpen(null)} + onCancel={() => setVariableEditorOpen(null)} onApply={onVariableEditorApply} isGlobalTabInitiallyOpen={ variableSourceType === gd.VariablesContainer.Global || variableSourceType === gd.VariablesContainer.ExtensionGlobal } - initiallySelectedVariable={editorOpen} + initiallySelectedVariable={variableEditorOpen} hotReloadPreviewButtonProps={null} isListLocked={false} /> diff --git a/newIDE/app/src/EventsSheet/ParameterFields/AnyVariableOrPropertyOrParameterField.js b/newIDE/app/src/EventsSheet/ParameterFields/AnyVariableOrPropertyOrParameterField.js index 149a44cc8691..39573d8a670e 100644 --- a/newIDE/app/src/EventsSheet/ParameterFields/AnyVariableOrPropertyOrParameterField.js +++ b/newIDE/app/src/EventsSheet/ParameterFields/AnyVariableOrPropertyOrParameterField.js @@ -23,8 +23,8 @@ export default (React.forwardRef( function AnyVariableField(props: ParameterFieldProps, ref) { const field = React.useRef(null); const [ - editorOpen, - setEditorOpen, + variableEditorOpen, + setVariableEditorOpen, ] = React.useState(null); const focus: FieldFocusFunction = options => { if (field.current) field.current.focus(options); @@ -42,6 +42,7 @@ export default (React.forwardRef( onChange, value, editEventsFunctionParameter, + openEventsBasedEntityPropertyEditorDialog, } = props; const enumerateGlobalAndSceneVariables = React.useCallback( @@ -73,7 +74,7 @@ export default (React.forwardRef( if (selectedVariableName && selectedVariableName.startsWith(value)) { onChange(selectedVariableName); } - setEditorOpen(null); + setVariableEditorOpen(null); // The variable editor may have refactor the events for a variable type // change which may have change the currently edited instruction type. if (onInstructionTypeChanged) onInstructionTypeChanged(); @@ -95,13 +96,6 @@ export default (React.forwardRef( ); const variableSourceType = variablesContainer.getSourceType(); - const onOpenDialog = React.useCallback( - (props: VariableDialogOpeningProps) => { - setEditorOpen(props); - }, - [] - ); - return ( ( onRequestClose={props.onRequestClose} onApply={props.onApply} ref={field} - onOpenDialog={onOpenDialog} + openVariableEditorDialog={setVariableEditorOpen} globalObjectsContainer={props.globalObjectsContainer} objectsContainer={props.objectsContainer} projectScopedContainersAccessor={projectScopedContainersAccessor} @@ -131,8 +125,11 @@ export default (React.forwardRef( onInstructionTypeChanged={onInstructionTypeChanged} getVariableSourceFromIdentifier={getVariableSourceFromIdentifier} editEventsFunctionParameter={editEventsFunctionParameter || null} + openEventsBasedEntityPropertyEditorDialog={ + openEventsBasedEntityPropertyEditorDialog || null + } /> - {editorOpen && + {variableEditorOpen && (variableSourceType === gd.VariablesContainer.Local ? ( project && ( ( } variablesContainer={variablesContainer} open - onCancel={() => setEditorOpen(null)} + onCancel={() => setVariableEditorOpen(null)} onApply={onVariableEditorApply} - initiallySelectedVariable={editorOpen} + initiallySelectedVariable={variableEditorOpen} isListLocked={false} /> ) @@ -152,13 +149,13 @@ export default (React.forwardRef( setEditorOpen(null)} + onCancel={() => setVariableEditorOpen(null)} onApply={onVariableEditorApply} isGlobalTabInitiallyOpen={ variableSourceType === gd.VariablesContainer.Global || variableSourceType === gd.VariablesContainer.ExtensionGlobal } - initiallySelectedVariable={editorOpen} + initiallySelectedVariable={variableEditorOpen} hotReloadPreviewButtonProps={null} isListLocked={false} /> diff --git a/newIDE/app/src/EventsSheet/ParameterFields/GlobalVariableField.js b/newIDE/app/src/EventsSheet/ParameterFields/GlobalVariableField.js index e17603f5daa1..7409b6a98dd5 100644 --- a/newIDE/app/src/EventsSheet/ParameterFields/GlobalVariableField.js +++ b/newIDE/app/src/EventsSheet/ParameterFields/GlobalVariableField.js @@ -20,8 +20,8 @@ export default (React.forwardRef( function GlobalVariableField(props: ParameterFieldProps, ref) { const field = React.useRef(null); const [ - editorOpen, - setEditorOpen, + variableEditorOpen, + setVariableEditorOpen, ] = React.useState(null); const focus: FieldFocusFunction = options => { if (field.current) field.current.focus(options); @@ -59,19 +59,20 @@ export default (React.forwardRef( onRequestClose={props.onRequestClose} onApply={props.onApply} ref={field} - onOpenDialog={setEditorOpen} + openVariableEditorDialog={setVariableEditorOpen} globalObjectsContainer={props.globalObjectsContainer} objectsContainer={props.objectsContainer} projectScopedContainersAccessor={projectScopedContainersAccessor} scope={scope} getVariableSourceFromIdentifier={getVariableSourceFromIdentifier} editEventsFunctionParameter={null} + openEventsBasedEntityPropertyEditorDialog={null} /> - {editorOpen && project && ( + {variableEditorOpen && project && ( setEditorOpen(null)} + onCancel={() => setVariableEditorOpen(null)} onApply={(selectedVariableName: string | null) => { if ( selectedVariableName && @@ -79,10 +80,10 @@ export default (React.forwardRef( ) { props.onChange(selectedVariableName); } - setEditorOpen(null); + setVariableEditorOpen(null); if (field.current) field.current.updateAutocompletions(); }} - initiallySelectedVariable={editorOpen} + initiallySelectedVariable={variableEditorOpen} hotReloadPreviewButtonProps={null} isListLocked={false} /> diff --git a/newIDE/app/src/EventsSheet/ParameterFields/ObjectVariableField.js b/newIDE/app/src/EventsSheet/ParameterFields/ObjectVariableField.js index e54fddd77908..548d62398fa9 100644 --- a/newIDE/app/src/EventsSheet/ParameterFields/ObjectVariableField.js +++ b/newIDE/app/src/EventsSheet/ParameterFields/ObjectVariableField.js @@ -197,7 +197,9 @@ export default (React.forwardRef( onRequestClose={props.onRequestClose} onApply={props.onApply} ref={field} - onOpenDialog={canObjectDeclareVariable ? setEditorOpen : null} + openVariableEditorDialog={ + canObjectDeclareVariable ? setEditorOpen : null + } globalObjectsContainer={props.globalObjectsContainer} objectsContainer={props.objectsContainer} projectScopedContainersAccessor={projectScopedContainersAccessor} @@ -210,6 +212,7 @@ export default (React.forwardRef( onInstructionTypeChanged={onInstructionTypeChanged} getVariableSourceFromIdentifier={getVariableSourceFromIdentifier} editEventsFunctionParameter={null} + openEventsBasedEntityPropertyEditorDialog={null} /> {editorOpen && project && diff --git a/newIDE/app/src/EventsSheet/ParameterFields/ParameterFieldCommons.js b/newIDE/app/src/EventsSheet/ParameterFields/ParameterFieldCommons.js index d814f598a7c9..40e266d9bb4d 100644 --- a/newIDE/app/src/EventsSheet/ParameterFields/ParameterFieldCommons.js +++ b/newIDE/app/src/EventsSheet/ParameterFields/ParameterFieldCommons.js @@ -58,6 +58,7 @@ export type ParameterFieldProps = {| parameterIndex?: number, onInstructionTypeChanged?: () => void, editEventsFunctionParameter?: VariableDialogOpeningProps => void, + openEventsBasedEntityPropertyEditorDialog?: VariableDialogOpeningProps => void, |}; export type FieldFocusFunction = ( diff --git a/newIDE/app/src/EventsSheet/ParameterFields/SceneVariableField.js b/newIDE/app/src/EventsSheet/ParameterFields/SceneVariableField.js index 6ef3a899933b..421e9855a468 100644 --- a/newIDE/app/src/EventsSheet/ParameterFields/SceneVariableField.js +++ b/newIDE/app/src/EventsSheet/ParameterFields/SceneVariableField.js @@ -21,8 +21,8 @@ export default (React.forwardRef( function SceneVariableField(props: ParameterFieldProps, ref) { const field = React.useRef(null); const [ - editorOpen, - setEditorOpen, + variableEditorOpen, + setVariableEditorOpen, ] = React.useState(null); const focus: FieldFocusFunction = options => { if (field.current) field.current.focus(options); @@ -67,7 +67,7 @@ export default (React.forwardRef( if (selectedVariableName && selectedVariableName.startsWith(value)) { onChange(selectedVariableName); } - setEditorOpen(null); + setVariableEditorOpen(null); if (field.current) field.current.updateAutocompletions(); }, [onChange, value] @@ -86,7 +86,7 @@ export default (React.forwardRef( onRequestClose={props.onRequestClose} onApply={props.onApply} ref={field} - onOpenDialog={setEditorOpen} + openVariableEditorDialog={setVariableEditorOpen} globalObjectsContainer={props.globalObjectsContainer} objectsContainer={props.objectsContainer} projectScopedContainersAccessor={projectScopedContainersAccessor} @@ -98,27 +98,28 @@ export default (React.forwardRef( } getVariableSourceFromIdentifier={getVariableSourceFromIdentifier} editEventsFunctionParameter={null} + openEventsBasedEntityPropertyEditorDialog={null} /> - {editorOpen && layout && project && ( + {variableEditorOpen && layout && project && ( setEditorOpen(null)} + onCancel={() => setVariableEditorOpen(null)} onApply={onVariableEditorApply} - initiallySelectedVariable={editorOpen} + initiallySelectedVariable={variableEditorOpen} hotReloadPreviewButtonProps={null} isListLocked={false} /> )} - {editorOpen && eventsFunctionsExtension && !layout && ( + {variableEditorOpen && eventsFunctionsExtension && !layout && ( setEditorOpen(null)} + onCancel={() => setVariableEditorOpen(null)} onApply={onVariableEditorApply} isGlobalTabInitiallyOpen={false} - initiallySelectedVariable={editorOpen} + initiallySelectedVariable={variableEditorOpen} hotReloadPreviewButtonProps={null} isListLocked={false} /> diff --git a/newIDE/app/src/EventsSheet/ParameterFields/VariableField.js b/newIDE/app/src/EventsSheet/ParameterFields/VariableField.js index 3547cfe27d4d..dbe583808cd2 100644 --- a/newIDE/app/src/EventsSheet/ParameterFields/VariableField.js +++ b/newIDE/app/src/EventsSheet/ParameterFields/VariableField.js @@ -77,8 +77,11 @@ type Props = { ) => VariablesContainer_SourceType, enumerateVariables: () => Array, forceDeclaration?: boolean, - onOpenDialog: (VariableDialogOpeningProps => void) | null, + openVariableEditorDialog: (VariableDialogOpeningProps => void) | null, editEventsFunctionParameter: (VariableDialogOpeningProps => void) | null, + openEventsBasedEntityPropertyEditorDialog: + | (VariableDialogOpeningProps => void) + | null, }; type VariableNameQuickAnalyzeResult = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7; @@ -88,7 +91,9 @@ export type VariableFieldInterface = {| updateAutocompletions: () => void, |}; -export const VariableNameQuickAnalyzeResults = { +export const VariableNameQuickAnalyzeResults: { + [string]: VariableNameQuickAnalyzeResult, +} = { OK: 0, WRONG_QUOTE: 1, WRONG_SPACE: 2, @@ -139,7 +144,6 @@ export const quicklyAnalyzeVariableName = ( projectScopedContainersAccessor?: ProjectScopedContainersAccessor, isObjectVariable: boolean = false ): VariableNameQuickAnalyzeResult => { - // $FlowFixMe[incompatible-type] if (!name) return VariableNameQuickAnalyzeResults.OK; for (let i = 0; i < name.length; ++i) { @@ -149,10 +153,8 @@ export const quicklyAnalyzeVariableName = ( // This probably starts an expression, so stop the analysis. break; } else if (character === ' ') { - // $FlowFixMe[incompatible-type] return VariableNameQuickAnalyzeResults.WRONG_SPACE; } else if (character === '"') { - // $FlowFixMe[incompatible-type] return VariableNameQuickAnalyzeResults.WRONG_QUOTE; } else if ( character === '(' || @@ -161,7 +163,6 @@ export const quicklyAnalyzeVariableName = ( character === '/' || character === '*' ) { - // $FlowFixMe[incompatible-type] return VariableNameQuickAnalyzeResults.WRONG_EXPRESSION; } } @@ -169,12 +170,10 @@ export const quicklyAnalyzeVariableName = ( const rootVariableName = getRootVariableName(name); // Check at least the name of the root variable, it's the best we can do. if (!isRootVariableDeclared(rootVariableName, variablesContainers)) { - // $FlowFixMe[incompatible-type] return VariableNameQuickAnalyzeResults.UNDECLARED_VARIABLE; } if (!projectScopedContainersAccessor) { - // $FlowFixMe[incompatible-type] return VariableNameQuickAnalyzeResults.OK; } const projectScopedContainers = projectScopedContainersAccessor.get(); @@ -185,7 +184,6 @@ export const quicklyAnalyzeVariableName = ( .getObjectsContainersList() .hasObjectOrGroupNamed(rootVariableName) ) { - // $FlowFixMe[incompatible-type] return VariableNameQuickAnalyzeResults.NAME_COLLISION_WITH_OBJECT; } @@ -199,16 +197,13 @@ export const quicklyAnalyzeVariableName = ( ); if (variableSource === gd.VariablesContainer.Parameters) { - // $FlowFixMe[incompatible-type] return VariableNameQuickAnalyzeResults.PARAMETER_WITH_CHILD; } if (variableSource === gd.VariablesContainer.Properties) { - // $FlowFixMe[incompatible-type] return VariableNameQuickAnalyzeResults.PROPERTY_WITH_CHILD; } } - // $FlowFixMe[incompatible-type] return VariableNameQuickAnalyzeResults.OK; }; @@ -271,8 +266,9 @@ export default (React.forwardRef( onInstructionTypeChanged, isObjectVariable, getVariableSourceFromIdentifier, - onOpenDialog, + openVariableEditorDialog, editEventsFunctionParameter, + openEventsBasedEntityPropertyEditorDialog, } = props; const field = React.useRef(null); @@ -333,7 +329,7 @@ export default (React.forwardRef( const openVariableEditor = React.useCallback( () => { - if (!onOpenDialog) { + if (!openVariableEditorDialog) { return; } // Access to the input directly because the value @@ -343,7 +339,7 @@ export default (React.forwardRef( : value; onChange(fieldCurrentValue); - onOpenDialog({ + openVariableEditorDialog({ variableName: fieldCurrentValue, shouldCreate: !!fieldCurrentValue && @@ -357,7 +353,13 @@ export default (React.forwardRef( : 'number', }); }, - [instruction, onChange, onOpenDialog, value, variablesContainers] + [ + instruction, + onChange, + openVariableEditorDialog, + value, + variablesContainers, + ] ); const openParameterEditor = React.useCallback( @@ -374,10 +376,9 @@ export default (React.forwardRef( onChange(fieldCurrentValue); editEventsFunctionParameter({ variableName: fieldCurrentValue, - shouldCreate: !isRootVariableDeclared( - fieldCurrentValue, - variablesContainers - ), + shouldCreate: + !!fieldCurrentValue && + !isRootVariableDeclared(fieldCurrentValue, variablesContainers), variableType: instruction ? getVariableTypeName( gd.VariableInstructionSwitcher.getSwitchableInstructionVariableType( @@ -396,6 +397,41 @@ export default (React.forwardRef( ] ); + const openPropertyEditor = React.useCallback( + () => { + if (!openEventsBasedEntityPropertyEditorDialog) { + return; + } + // Access to the input directly because the value + // may not have been sent to onChange yet. + const fieldCurrentValue = field.current + ? field.current.getInputValue() + : value; + + onChange(fieldCurrentValue); + openEventsBasedEntityPropertyEditorDialog({ + variableName: fieldCurrentValue, + shouldCreate: + !!fieldCurrentValue && + !isRootVariableDeclared(fieldCurrentValue, variablesContainers), + variableType: instruction + ? getVariableTypeName( + gd.VariableInstructionSwitcher.getSwitchableInstructionVariableType( + instruction.getType() + ) + ) + : 'number', + }); + }, + [ + openEventsBasedEntityPropertyEditorDialog, + value, + onChange, + instruction, + variablesContainers, + ] + ); + const description = parameterMetadata ? parameterMetadata.getDescription() : undefined; @@ -504,12 +540,11 @@ export default (React.forwardRef( ? variableSourceType === gd.VariablesContainer.Parameters ? ['edit-parameters'] : variableSourceType === gd.VariablesContainer.Properties - ? // TODO Allow to edit properties from the event sheet. - [] + ? ['edit-properties'] : ['edit-variables'] : fieldCurrentValue - ? ['add-variable', 'add-parameter'] - : ['edit-or-add-variables']; + ? ['add-parameter', 'add-property', 'add-variable'] + : ['edit-or-add-properties', 'edit-or-add-variables']; return optionIds.includes(id); }, @@ -539,54 +574,81 @@ export default (React.forwardRef( onRequestClose={onRequestClose} onApply={onApply} filterOptionById={filterOptionById} - // $FlowFixMe[incompatible-type] dataSource={[ ...autocompletionVariableNames, - ...(onOpenDialog + ...(editEventsFunctionParameter ? [ { - id: 'edit-variables', - translatableValue: t`Edit variables...`, + id: 'edit-parameters', + translatableValue: t`Edit parameters...`, text: '', value: '', renderIcon: () => , - onClick: openVariableEditor, + onClick: openParameterEditor, }, { - id: 'add-variable', - translatableValue: t`Add variable...`, + id: 'add-parameter', + translatableValue: t`Add parameter...`, text: '', value: '', renderIcon: () => , - onClick: openVariableEditor, + onClick: openParameterEditor, }, + ] + : []), + ...(openEventsBasedEntityPropertyEditorDialog + ? [ { - id: 'edit-or-add-variables', - translatableValue: t`Edit or add variables...`, + id: 'edit-properties', + translatableValue: t`Edit properties...`, text: '', value: '', renderIcon: () => , - onClick: openVariableEditor, + onClick: openPropertyEditor, + }, + { + id: 'add-property', + translatableValue: t`Add property...`, + text: '', + value: '', + renderIcon: () => , + onClick: openPropertyEditor, + }, + { + id: 'edit-or-add-properties', + translatableValue: t`Edit or add properties...`, + text: '', + value: '', + renderIcon: () => , + onClick: openPropertyEditor, }, ] : []), - ...(editEventsFunctionParameter + ...(openVariableEditorDialog ? [ { - id: 'edit-parameters', - translatableValue: t`Edit parameters...`, + id: 'edit-variables', + translatableValue: t`Edit variables...`, text: '', value: '', renderIcon: () => , - onClick: openParameterEditor, + onClick: openVariableEditor, }, { - id: 'add-parameter', - translatableValue: t`Add parameter...`, + id: 'add-variable', + translatableValue: t`Add variable...`, text: '', value: '', renderIcon: () => , - onClick: openParameterEditor, + onClick: openVariableEditor, + }, + { + id: 'edit-or-add-variables', + translatableValue: t`Edit or add variables...`, + text: '', + value: '', + renderIcon: () => , + onClick: openVariableEditor, }, ] : []), @@ -600,12 +662,12 @@ export default (React.forwardRef( !isInline ? ( } - disabled={!onOpenDialog} + disabled={!openVariableEditorDialog} primary style={style} onClick={() => { - if (onOpenDialog) { - onOpenDialog({ + if (openVariableEditorDialog) { + openVariableEditorDialog({ variableName: value, shouldCreate: false, variableType: getVariableTypeName(variableType), diff --git a/newIDE/app/src/EventsSheet/index.js b/newIDE/app/src/EventsSheet/index.js index 750a5f60423e..b695abcfab64 100644 --- a/newIDE/app/src/EventsSheet/index.js +++ b/newIDE/app/src/EventsSheet/index.js @@ -195,6 +195,7 @@ type Props = {| onWillInstallExtension: (extensionNames: Array) => void, onExtensionInstalled: (extensionNames: Array) => void, editEventsFunctionParameter: VariableDialogOpeningProps => void, + openEventsBasedEntityPropertyEditorDialog: VariableDialogOpeningProps => void, |}; type ComponentProps = {| @@ -2520,6 +2521,9 @@ export class EventsSheetComponentWithoutHandle extends React.Component< onWillInstallExtension={this.props.onWillInstallExtension} onExtensionInstalled={this.props.onExtensionInstalled} editEventsFunctionParameter={this.props.editEventsFunctionParameter} + openEventsBasedEntityPropertyEditorDialog={ + this.props.openEventsBasedEntityPropertyEditorDialog + } /> )} @@ -2603,6 +2607,7 @@ export class EventsSheetComponentWithoutHandle extends React.Component< screenType, highlightedAiGeneratedEventIds, editEventsFunctionParameter, + openEventsBasedEntityPropertyEditorDialog, } = this.props; if (!project) return null; @@ -2937,6 +2942,9 @@ export class EventsSheetComponentWithoutHandle extends React.Component< }} resourceManagementProps={resourceManagementProps} editEventsFunctionParameter={editEventsFunctionParameter} + openEventsBasedEntityPropertyEditorDialog={ + openEventsBasedEntityPropertyEditorDialog + } /> diff --git a/newIDE/app/src/MainFrame/EditorContainers/EventsEditorContainer.js b/newIDE/app/src/MainFrame/EditorContainers/EventsEditorContainer.js index 450c6228c30a..2f28ffd41f08 100644 --- a/newIDE/app/src/MainFrame/EditorContainers/EventsEditorContainer.js +++ b/newIDE/app/src/MainFrame/EditorContainers/EventsEditorContainer.js @@ -18,6 +18,7 @@ import { type HotReloadSteps, } from '../../EmbeddedGame/EmbeddedGameFrame'; import type { SearchFilterParams } from '../../Utils/Search'; +import { type EventsScope } from '../../InstructionOrExpression/EventsScope'; export class EventsEditorContainer extends React.Component { editor: ?EventsSheetInterface; @@ -184,7 +185,7 @@ export class EventsEditorContainer extends React.ComponentNo layout called {projectItemName} found!; } - const scope = { + const scope: EventsScope = { project, layout, }; @@ -204,7 +205,6 @@ export class EventsEditorContainer extends React.Component {}} + openEventsBasedEntityPropertyEditorDialog={() => {}} /> ); } diff --git a/newIDE/app/src/MainFrame/EditorContainers/ExternalEventsEditorContainer.js b/newIDE/app/src/MainFrame/EditorContainers/ExternalEventsEditorContainer.js index f55816da5870..7ea454e775e5 100644 --- a/newIDE/app/src/MainFrame/EditorContainers/ExternalEventsEditorContainer.js +++ b/newIDE/app/src/MainFrame/EditorContainers/ExternalEventsEditorContainer.js @@ -288,8 +288,9 @@ export class ExternalEventsEditorContainer extends React.Component< hotReloadPreviewButtonProps={this.props.hotReloadPreviewButtonProps} onWillInstallExtension={this.props.onWillInstallExtension} onExtensionInstalled={this.props.onExtensionInstalled} - // Scene events don't have parameters + // Scene events don't have parameters nor properties editEventsFunctionParameter={() => {}} + openEventsBasedEntityPropertyEditorDialog={() => {}} /> )} {!layout && ( diff --git a/newIDE/app/src/Version/index.js b/newIDE/app/src/Version/index.js index d7e6a03d868e..96b485262307 100644 --- a/newIDE/app/src/Version/index.js +++ b/newIDE/app/src/Version/index.js @@ -20,14 +20,6 @@ export const shouldHideExtension = ( extension: gdPlatformExtension ): boolean => { const initialGDVersion = project.getInitialGDVersion(); - if (initialGDVersion && extension.isDeprecated()) { - console.log( - 'shouldHideExtension', - extension.getDeprecationGDVersion(), - initialGDVersion, - !semverGreaterThan(extension.getDeprecationGDVersion(), initialGDVersion) - ); - } return ( !!initialGDVersion && extension.isDeprecated() && diff --git a/newIDE/app/src/stories/componentStories/EventsSheet/EventsSheet.stories.js b/newIDE/app/src/stories/componentStories/EventsSheet/EventsSheet.stories.js index fbef3d87e232..61a693fabebf 100644 --- a/newIDE/app/src/stories/componentStories/EventsSheet/EventsSheet.stories.js +++ b/newIDE/app/src/stories/componentStories/EventsSheet/EventsSheet.stories.js @@ -40,6 +40,9 @@ export const DefaultNoScope = (): React.Node => ( onWillInstallExtension={action('extension will be installed')} onExtensionInstalled={action('extension installed')} editEventsFunctionParameter={action('edit function parameter')} + openEventsBasedEntityPropertyEditorDialog={action( + 'openEventsBasedEntityPropertyEditorDialog' + )} /> @@ -73,6 +76,9 @@ export const EmptyNoScope = (): React.Node => ( onWillInstallExtension={action('extension will be installed')} onExtensionInstalled={action('extension installed')} editEventsFunctionParameter={action('edit function parameter')} + openEventsBasedEntityPropertyEditorDialog={action( + 'openEventsBasedEntityPropertyEditorDialog' + )} /> diff --git a/newIDE/app/src/stories/everything-else.stories.js b/newIDE/app/src/stories/everything-else.stories.js index 6f7289b933ab..e2068464cda7 100644 --- a/newIDE/app/src/stories/everything-else.stories.js +++ b/newIDE/app/src/stories/everything-else.stories.js @@ -2058,6 +2058,9 @@ storiesOf('InstructionEditorDialog', module) onWillInstallExtension={action('extension will be installed')} onExtensionInstalled={action('extension installed')} editEventsFunctionParameter={action('editEventsFunctionParameter')} + openEventsBasedEntityPropertyEditorDialog={action( + 'openEventsBasedEntityPropertyEditorDialog' + )} /> )} @@ -2087,6 +2090,9 @@ storiesOf('InstructionEditorDialog', module) onWillInstallExtension={action('extension will be installed')} onExtensionInstalled={action('extension installed')} editEventsFunctionParameter={action('editEventsFunctionParameter')} + openEventsBasedEntityPropertyEditorDialog={action( + 'openEventsBasedEntityPropertyEditorDialog' + )} /> )} @@ -2125,6 +2131,9 @@ storiesOf('InstructionEditorDialog', module) onWillInstallExtension={action('extension will be installed')} onExtensionInstalled={action('extension installed')} editEventsFunctionParameter={action('editEventsFunctionParameter')} + openEventsBasedEntityPropertyEditorDialog={action( + 'openEventsBasedEntityPropertyEditorDialog' + )} /> )} @@ -2176,6 +2185,9 @@ storiesOf('InstructionEditorMenu', module) editEventsFunctionParameter={action( 'editEventsFunctionParameter' )} + openEventsBasedEntityPropertyEditorDialog={action( + 'openEventsBasedEntityPropertyEditorDialog' + )} /> )}