mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
Compare commits
1 Commits
ai-ux-impr
...
cursor/ext
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c0ab3ccc50 |
117
newIDE/app/src/MainFrame/EditorsPane.js
Normal file
117
newIDE/app/src/MainFrame/EditorsPane.js
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
// @flow
|
||||||
|
import * as React from 'react';
|
||||||
|
import TabsTitlebar from './TabsTitlebar';
|
||||||
|
import Toolbar, { type ToolbarInterface } from './Toolbar';
|
||||||
|
import { DraggableEditorTabs } from './EditorTabs/DraggableEditorTabs';
|
||||||
|
import {
|
||||||
|
getEditors,
|
||||||
|
getCurrentTab,
|
||||||
|
getCurrentTabIndex,
|
||||||
|
type EditorTabsState,
|
||||||
|
type EditorTab,
|
||||||
|
} from './EditorTabs/EditorTabsHandler';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EditorsPane is a thin wrapper that gathers together:
|
||||||
|
* - the TabsTitlebar (and the draggable tabs inside it)
|
||||||
|
* - the main Toolbar
|
||||||
|
* - the rendering of the editors contained in the current pane.
|
||||||
|
*
|
||||||
|
* It is intentionally kept “dumb”: all the real logic still sits in
|
||||||
|
* MainFrame, and is passed down through props. This allows MainFrame to
|
||||||
|
* continue owning the business logic while giving us the flexibility to
|
||||||
|
* later instantiate several panes or move tabs between them.
|
||||||
|
*/
|
||||||
|
|
||||||
|
type Props = {|
|
||||||
|
// State of the tabs for this pane
|
||||||
|
editorTabs: EditorTabsState,
|
||||||
|
// Visibility/hide logic shared with MainFrame
|
||||||
|
tabsTitleBarAndEditorToolbarHidden: boolean,
|
||||||
|
// Title-bar props
|
||||||
|
toggleProjectManager: () => void,
|
||||||
|
hasAskAiOpened: boolean,
|
||||||
|
onOpenAskAi: () => void,
|
||||||
|
// Tab actions
|
||||||
|
onChangeEditorTab: (id: number) => void,
|
||||||
|
onCloseEditorTab: (editorTab: EditorTab) => void,
|
||||||
|
onCloseOtherEditorTabs: (editorTab: EditorTab) => void,
|
||||||
|
onCloseAllEditorTabs: () => void,
|
||||||
|
onEditorTabActivated: (editorTab: EditorTab) => void,
|
||||||
|
onDropEditorTab: (sourceEditorTab: EditorTab, destinationEditorTab: EditorTab) => void,
|
||||||
|
// Toolbar props
|
||||||
|
toolbarRef: { current: ?ToolbarInterface },
|
||||||
|
toolbarProps: Object,
|
||||||
|
// Renderer for a single editor tab content (kept in MainFrame)
|
||||||
|
renderEditorTab: (editorTab: EditorTab, isCurrentTab: boolean) => React.Node,
|
||||||
|
|};
|
||||||
|
|
||||||
|
const EditorsPane = ({
|
||||||
|
editorTabs,
|
||||||
|
tabsTitleBarAndEditorToolbarHidden,
|
||||||
|
toggleProjectManager,
|
||||||
|
hasAskAiOpened,
|
||||||
|
onOpenAskAi,
|
||||||
|
onChangeEditorTab,
|
||||||
|
onCloseEditorTab,
|
||||||
|
onCloseOtherEditorTabs,
|
||||||
|
onCloseAllEditorTabs,
|
||||||
|
onEditorTabActivated,
|
||||||
|
onDropEditorTab,
|
||||||
|
toolbarRef,
|
||||||
|
toolbarProps,
|
||||||
|
renderEditorTab,
|
||||||
|
}: Props): React.Node => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<TabsTitlebar
|
||||||
|
hidden={tabsTitleBarAndEditorToolbarHidden}
|
||||||
|
toggleProjectManager={toggleProjectManager}
|
||||||
|
renderTabs={(onEditorTabHovered, onEditorTabClosing) => (
|
||||||
|
<DraggableEditorTabs
|
||||||
|
hideLabels={false}
|
||||||
|
editorTabs={editorTabs}
|
||||||
|
onClickTab={(id: number) => onChangeEditorTab(id)}
|
||||||
|
onCloseTab={(editorTab: EditorTab) => {
|
||||||
|
onEditorTabClosing();
|
||||||
|
onCloseEditorTab(editorTab);
|
||||||
|
}}
|
||||||
|
onCloseOtherTabs={(editorTab: EditorTab) => {
|
||||||
|
onEditorTabClosing();
|
||||||
|
onCloseOtherEditorTabs(editorTab);
|
||||||
|
}}
|
||||||
|
onCloseAll={() => {
|
||||||
|
onEditorTabClosing();
|
||||||
|
onCloseAllEditorTabs();
|
||||||
|
}}
|
||||||
|
onTabActivated={(editorTab: EditorTab) =>
|
||||||
|
onEditorTabActivated(editorTab)
|
||||||
|
}
|
||||||
|
onDropTab={onDropEditorTab}
|
||||||
|
onHoverTab={(
|
||||||
|
editorTab: ?EditorTab,
|
||||||
|
options: {| isLabelTruncated: boolean |}
|
||||||
|
) => onEditorTabHovered(editorTab, options)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
hasAskAiOpened={hasAskAiOpened}
|
||||||
|
onOpenAskAi={onOpenAskAi}
|
||||||
|
/>
|
||||||
|
<Toolbar
|
||||||
|
ref={toolbarRef}
|
||||||
|
hidden={tabsTitleBarAndEditorToolbarHidden}
|
||||||
|
showProjectButtons={
|
||||||
|
!['start page', 'debugger', 'ask-ai', null].includes(
|
||||||
|
getCurrentTab(editorTabs) ? getCurrentTab(editorTabs).key : null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
{...toolbarProps}
|
||||||
|
/>
|
||||||
|
{getEditors(editorTabs).map((editorTab, id) =>
|
||||||
|
renderEditorTab(editorTab, getCurrentTabIndex(editorTabs) === id)
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EditorsPane;
|
@@ -208,6 +208,7 @@ import RobotIcon from '../ProjectCreation/RobotIcon';
|
|||||||
import PublicProfileContext from '../Profile/PublicProfileContext';
|
import PublicProfileContext from '../Profile/PublicProfileContext';
|
||||||
import { useGamesPlatformFrame } from './EditorContainers/HomePage/PlaySection/UseGamesPlatformFrame';
|
import { useGamesPlatformFrame } from './EditorContainers/HomePage/PlaySection/UseGamesPlatformFrame';
|
||||||
import { useExtensionLoadErrorDialog } from '../Utils/UseExtensionLoadErrorDialog';
|
import { useExtensionLoadErrorDialog } from '../Utils/UseExtensionLoadErrorDialog';
|
||||||
|
import EditorsPane from './EditorsPane';
|
||||||
|
|
||||||
const GD_STARTUP_TIMES = global.GD_STARTUP_TIMES || [];
|
const GD_STARTUP_TIMES = global.GD_STARTUP_TIMES || [];
|
||||||
|
|
||||||
@@ -3835,6 +3836,150 @@ const MainFrame = (props: Props) => {
|
|||||||
(!currentFileMetadata || !isProjectOwnedBySomeoneElse);
|
(!currentFileMetadata || !isProjectOwnedBySomeoneElse);
|
||||||
const hasAskAiOpened = hasEditorTabOpenedWithKey(state.editorTabs, 'ask-ai');
|
const hasAskAiOpened = hasEditorTabOpenedWithKey(state.editorTabs, 'ask-ai');
|
||||||
|
|
||||||
|
// Render a single editor tab content. This used to be inline in the JSX but
|
||||||
|
// has been extracted so that the EditorsPane component can be kept generic.
|
||||||
|
const renderEditorTab = (
|
||||||
|
editorTab: EditorTab,
|
||||||
|
isCurrentTab: boolean
|
||||||
|
): React.Node => {
|
||||||
|
const errorBoundaryProps = getEditorErrorBoundaryProps(editorTab.key);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TabContentContainer
|
||||||
|
key={editorTab.key}
|
||||||
|
active={isCurrentTab}
|
||||||
|
removePointerEvents={gamesPlatformFrameTools.iframeVisible}
|
||||||
|
>
|
||||||
|
<CommandsContextScopedProvider active={isCurrentTab}>
|
||||||
|
<ErrorBoundary
|
||||||
|
componentTitle={errorBoundaryProps.componentTitle}
|
||||||
|
scope={errorBoundaryProps.scope}
|
||||||
|
>
|
||||||
|
{editorTab.renderEditorContainer({
|
||||||
|
isActive: isCurrentTab,
|
||||||
|
extraEditorProps: editorTab.extraEditorProps,
|
||||||
|
project: currentProject,
|
||||||
|
fileMetadata: currentFileMetadata,
|
||||||
|
storageProvider: getStorageProvider(),
|
||||||
|
ref: editorRef => (editorTab.editorRef = editorRef),
|
||||||
|
setToolbar: editorToolbar =>
|
||||||
|
setEditorToolbar(editorToolbar, isCurrentTab),
|
||||||
|
hideTabsTitleBarAndEditorToolbar: setTabsTitleBarAndEditorToolbarHidden,
|
||||||
|
projectItemName: editorTab.projectItemName,
|
||||||
|
setPreviewedLayout,
|
||||||
|
onOpenExternalEvents: openExternalEvents,
|
||||||
|
onOpenEvents: (sceneName: string) => {
|
||||||
|
openLayout(sceneName, {
|
||||||
|
openEventsEditor: true,
|
||||||
|
openSceneEditor: false,
|
||||||
|
focusWhenOpened: 'events',
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onOpenLayout: openLayout,
|
||||||
|
onOpenTemplateFromTutorial: openTemplateFromTutorial,
|
||||||
|
onOpenTemplateFromCourseChapter: openTemplateFromCourseChapter,
|
||||||
|
previewDebuggerServer,
|
||||||
|
hotReloadPreviewButtonProps,
|
||||||
|
resourceManagementProps,
|
||||||
|
onSave: saveProject,
|
||||||
|
canSave,
|
||||||
|
onCreateEventsFunction,
|
||||||
|
openInstructionOrExpression,
|
||||||
|
onOpenCustomObjectEditor: openCustomObjectEditor,
|
||||||
|
onRenamedEventsBasedObject: onRenamedEventsBasedObject,
|
||||||
|
onDeletedEventsBasedObject: onDeletedEventsBasedObject,
|
||||||
|
openObjectEvents,
|
||||||
|
unsavedChanges: unsavedChanges,
|
||||||
|
canOpen: !!props.storageProviders.filter(
|
||||||
|
({ hiddenInOpenDialog }) => !hiddenInOpenDialog
|
||||||
|
).length,
|
||||||
|
onChooseProject: () => openOpenFromStorageProviderDialog(),
|
||||||
|
onOpenRecentFile: openFromFileMetadataWithStorageProvider,
|
||||||
|
onOpenNewProjectSetupDialog: openNewProjectDialog,
|
||||||
|
onOpenProjectManager: () => openProjectManager(true),
|
||||||
|
onOpenVersionHistory: openVersionHistoryPanel,
|
||||||
|
askToCloseProject,
|
||||||
|
closeProject,
|
||||||
|
onSelectExampleShortHeader: exampleShortHeader => {
|
||||||
|
onSelectExampleShortHeader({
|
||||||
|
exampleShortHeader,
|
||||||
|
preventBackHome: true,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onSelectPrivateGameTemplateListingData: privateGameTemplateListingData => {
|
||||||
|
onSelectPrivateGameTemplateListingData({
|
||||||
|
privateGameTemplateListingData,
|
||||||
|
preventBackHome: true,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onOpenPrivateGameTemplateListingData: privateGameTemplateListingData => {
|
||||||
|
onSelectPrivateGameTemplateListingData({
|
||||||
|
privateGameTemplateListingData,
|
||||||
|
preventBackHome: true,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onCreateEmptyProject: createEmptyProject,
|
||||||
|
onCreateProjectFromExample: createProjectFromExample,
|
||||||
|
onOpenProfile: onOpenProfileDialog,
|
||||||
|
onOpenLanguageDialog: () => openLanguageDialog(true),
|
||||||
|
onOpenPreferences: () => openPreferencesDialog(true),
|
||||||
|
onOpenAbout: () => openAboutDialog(true),
|
||||||
|
selectInAppTutorial: selectInAppTutorial,
|
||||||
|
onLoadEventsFunctionsExtensions: async () => {
|
||||||
|
if (isProjectClosedSoAvoidReloadingExtensions) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return eventsFunctionsExtensionsState.loadProjectEventsFunctionsExtensions(
|
||||||
|
currentProject
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onReloadEventsFunctionsExtensionMetadata: extension => {
|
||||||
|
if (isProjectClosedSoAvoidReloadingExtensions) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
eventsFunctionsExtensionsState.reloadProjectEventsFunctionsExtensionMetadata(
|
||||||
|
currentProject,
|
||||||
|
extension
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onDeleteResource: (
|
||||||
|
resource: gdResource,
|
||||||
|
cb: boolean => void
|
||||||
|
) => {
|
||||||
|
cb(true);
|
||||||
|
},
|
||||||
|
onRenameResource: (
|
||||||
|
resource: gdResource,
|
||||||
|
newName: string,
|
||||||
|
cb: boolean => void
|
||||||
|
) => {
|
||||||
|
if (currentProject)
|
||||||
|
renameResourcesInProject(currentProject, {
|
||||||
|
[resource.getName()]: newName,
|
||||||
|
});
|
||||||
|
|
||||||
|
cb(true);
|
||||||
|
},
|
||||||
|
openBehaviorEvents: openBehaviorEvents,
|
||||||
|
onExtractAsExternalLayout: onExtractAsExternalLayout,
|
||||||
|
onExtractAsEventBasedObject: onOpenEventBasedObjectEditor,
|
||||||
|
onOpenEventBasedObjectEditor: onOpenEventBasedObjectEditor,
|
||||||
|
onOpenEventBasedObjectVariantEditor: onOpenEventBasedObjectVariantEditor,
|
||||||
|
onDeleteEventsBasedObjectVariant: deleteEventsBasedObjectVariant,
|
||||||
|
onEventsBasedObjectChildrenEdited: onEventsBasedObjectChildrenEdited,
|
||||||
|
onSceneObjectEdited: onSceneObjectEdited,
|
||||||
|
onSceneObjectsDeleted: onSceneObjectsDeleted,
|
||||||
|
onSceneEventsModifiedOutsideEditor: onSceneEventsModifiedOutsideEditor,
|
||||||
|
onExtensionInstalled: onExtensionInstalled,
|
||||||
|
gamesList,
|
||||||
|
gamesPlatformFrameTools,
|
||||||
|
})}
|
||||||
|
</ErrorBoundary>
|
||||||
|
</CommandsContextScopedProvider>
|
||||||
|
</TabContentContainer>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={
|
className={
|
||||||
@@ -3905,230 +4050,49 @@ const MainFrame = (props: Props) => {
|
|||||||
buildMainMenuProps={buildMainMenuProps}
|
buildMainMenuProps={buildMainMenuProps}
|
||||||
/>
|
/>
|
||||||
</ProjectManagerDrawer>
|
</ProjectManagerDrawer>
|
||||||
<TabsTitlebar
|
|
||||||
hidden={tabsTitleBarAndEditorToolbarHidden}
|
|
||||||
toggleProjectManager={toggleProjectManager}
|
|
||||||
renderTabs={(onEditorTabHovered, onEditorTabClosing) => (
|
|
||||||
<DraggableEditorTabs
|
|
||||||
hideLabels={false}
|
|
||||||
editorTabs={state.editorTabs}
|
|
||||||
onClickTab={(id: number) => _onChangeEditorTab(id)}
|
|
||||||
onCloseTab={(editorTab: EditorTab) => {
|
|
||||||
// Call onEditorTabClosing before to ensure any tooltip is removed before the tab is closed.
|
|
||||||
onEditorTabClosing();
|
|
||||||
_onCloseEditorTab(editorTab);
|
|
||||||
}}
|
|
||||||
onCloseOtherTabs={(editorTab: EditorTab) => {
|
|
||||||
// Call onEditorTabClosing before to ensure any tooltip is removed before the tab is closed.
|
|
||||||
onEditorTabClosing();
|
|
||||||
_onCloseOtherEditorTabs(editorTab);
|
|
||||||
}}
|
|
||||||
onCloseAll={() => {
|
|
||||||
// Call onEditorTabClosing before to ensure any tooltip is removed before the tab is closed.
|
|
||||||
onEditorTabClosing();
|
|
||||||
_onCloseAllEditorTabs();
|
|
||||||
}}
|
|
||||||
onTabActivated={(editorTab: EditorTab) =>
|
|
||||||
_onEditorTabActivated(editorTab)
|
|
||||||
}
|
|
||||||
onDropTab={onDropEditorTab}
|
|
||||||
onHoverTab={(
|
|
||||||
editorTab: ?EditorTab,
|
|
||||||
options: {| isLabelTruncated: boolean |}
|
|
||||||
) => onEditorTabHovered(editorTab, options)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
hasAskAiOpened={hasAskAiOpened}
|
|
||||||
onOpenAskAi={openAskAi}
|
|
||||||
/>
|
|
||||||
<Toolbar
|
|
||||||
ref={toolbar}
|
|
||||||
hidden={tabsTitleBarAndEditorToolbarHidden}
|
|
||||||
showProjectButtons={
|
|
||||||
!['start page', 'debugger', 'ask-ai', null].includes(
|
|
||||||
getCurrentTab(state.editorTabs)
|
|
||||||
? getCurrentTab(state.editorTabs).key
|
|
||||||
: null
|
|
||||||
)
|
|
||||||
}
|
|
||||||
canSave={canSave}
|
|
||||||
onSave={saveProject}
|
|
||||||
openShareDialog={() =>
|
|
||||||
openShareDialog(/* leave the dialog decide which tab to open */)
|
|
||||||
}
|
|
||||||
isSharingEnabled={
|
|
||||||
!checkedOutVersionStatus && !cloudProjectRecoveryOpenedVersionId
|
|
||||||
}
|
|
||||||
onOpenDebugger={launchDebuggerAndPreview}
|
|
||||||
hasPreviewsRunning={hasPreviewsRunning}
|
|
||||||
onPreviewWithoutHotReload={launchNewPreview}
|
|
||||||
onNetworkPreview={launchNetworkPreview}
|
|
||||||
onHotReloadPreview={launchHotReloadPreview}
|
|
||||||
onLaunchPreviewWithDiagnosticReport={launchPreviewWithDiagnosticReport}
|
|
||||||
canDoNetworkPreview={
|
|
||||||
!!_previewLauncher.current &&
|
|
||||||
_previewLauncher.current.canDoNetworkPreview()
|
|
||||||
}
|
|
||||||
setPreviewOverride={setPreviewOverride}
|
|
||||||
isPreviewEnabled={
|
|
||||||
!!currentProject && currentProject.getLayoutsCount() > 0
|
|
||||||
}
|
|
||||||
previewState={previewState}
|
|
||||||
onOpenVersionHistory={openVersionHistoryPanel}
|
|
||||||
checkedOutVersionStatus={checkedOutVersionStatus}
|
|
||||||
onQuitVersionHistory={onQuitVersionHistory}
|
|
||||||
canQuitVersionHistory={!isSavingProject}
|
|
||||||
/>
|
|
||||||
{// Render games platform frame before the editors, so the editor have priority
|
{// Render games platform frame before the editors, so the editor have priority
|
||||||
// in what to display (ex: Loader of play section)
|
// in what to display (ex: Loader of play section)
|
||||||
gamesPlatformFrameTools.renderGamesPlatformFrame()}
|
gamesPlatformFrameTools.renderGamesPlatformFrame()}
|
||||||
<LeaderboardProvider
|
<LeaderboardProvider
|
||||||
gameId={
|
gameId={state.currentProject ? state.currentProject.getProjectUuid() : ''}
|
||||||
state.currentProject ? state.currentProject.getProjectUuid() : ''
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
{getEditors(state.editorTabs).map((editorTab, id) => {
|
<EditorsPane
|
||||||
const isCurrentTab = getCurrentTabIndex(state.editorTabs) === id;
|
editorTabs={state.editorTabs}
|
||||||
const errorBoundaryProps = getEditorErrorBoundaryProps(editorTab.key);
|
tabsTitleBarAndEditorToolbarHidden={tabsTitleBarAndEditorToolbarHidden}
|
||||||
|
toggleProjectManager={toggleProjectManager}
|
||||||
return (
|
hasAskAiOpened={hasAskAiOpened}
|
||||||
<TabContentContainer
|
onOpenAskAi={openAskAi}
|
||||||
key={editorTab.key}
|
onChangeEditorTab={_onChangeEditorTab}
|
||||||
active={isCurrentTab}
|
onCloseEditorTab={_onCloseEditorTab}
|
||||||
// Deactivate pointer events when the play tab is active, so the iframe
|
onCloseOtherEditorTabs={_onCloseOtherEditorTabs}
|
||||||
// can be interacted with.
|
onCloseAllEditorTabs={_onCloseAllEditorTabs}
|
||||||
removePointerEvents={gamesPlatformFrameTools.iframeVisible}
|
onEditorTabActivated={_onEditorTabActivated}
|
||||||
>
|
onDropEditorTab={onDropEditorTab}
|
||||||
<CommandsContextScopedProvider active={isCurrentTab}>
|
toolbarRef={toolbar}
|
||||||
<ErrorBoundary
|
toolbarProps={{
|
||||||
componentTitle={errorBoundaryProps.componentTitle}
|
canSave,
|
||||||
scope={errorBoundaryProps.scope}
|
onSave: saveProject,
|
||||||
>
|
openShareDialog: () =>
|
||||||
{editorTab.renderEditorContainer({
|
openShareDialog(/* leave the dialog decide which tab to open */),
|
||||||
isActive: isCurrentTab,
|
isSharingEnabled: !checkedOutVersionStatus && !cloudProjectRecoveryOpenedVersionId,
|
||||||
extraEditorProps: editorTab.extraEditorProps,
|
onOpenDebugger: launchDebuggerAndPreview,
|
||||||
project: currentProject,
|
hasPreviewsRunning,
|
||||||
fileMetadata: currentFileMetadata,
|
onPreviewWithoutHotReload: launchNewPreview,
|
||||||
storageProvider: getStorageProvider(),
|
onNetworkPreview: launchNetworkPreview,
|
||||||
ref: editorRef => (editorTab.editorRef = editorRef),
|
onHotReloadPreview: launchHotReloadPreview,
|
||||||
setToolbar: editorToolbar =>
|
onLaunchPreviewWithDiagnosticReport: launchPreviewWithDiagnosticReport,
|
||||||
setEditorToolbar(editorToolbar, isCurrentTab),
|
canDoNetworkPreview:
|
||||||
hideTabsTitleBarAndEditorToolbar: setTabsTitleBarAndEditorToolbarHidden,
|
!!_previewLauncher.current && _previewLauncher.current.canDoNetworkPreview(),
|
||||||
projectItemName: editorTab.projectItemName,
|
setPreviewOverride,
|
||||||
setPreviewedLayout,
|
isPreviewEnabled: !!currentProject && currentProject.getLayoutsCount() > 0,
|
||||||
onOpenExternalEvents: openExternalEvents,
|
previewState,
|
||||||
onOpenEvents: (sceneName: string) => {
|
onOpenVersionHistory: openVersionHistoryPanel,
|
||||||
openLayout(sceneName, {
|
checkedOutVersionStatus,
|
||||||
openEventsEditor: true,
|
onQuitVersionHistory,
|
||||||
openSceneEditor: false,
|
canQuitVersionHistory: !isSavingProject,
|
||||||
focusWhenOpened: 'events',
|
}}
|
||||||
});
|
renderEditorTab={renderEditorTab}
|
||||||
},
|
/>
|
||||||
onOpenLayout: openLayout,
|
|
||||||
onOpenTemplateFromTutorial: openTemplateFromTutorial,
|
|
||||||
onOpenTemplateFromCourseChapter: openTemplateFromCourseChapter,
|
|
||||||
previewDebuggerServer,
|
|
||||||
hotReloadPreviewButtonProps,
|
|
||||||
resourceManagementProps,
|
|
||||||
onSave: saveProject,
|
|
||||||
canSave,
|
|
||||||
onCreateEventsFunction,
|
|
||||||
openInstructionOrExpression,
|
|
||||||
onOpenCustomObjectEditor: openCustomObjectEditor,
|
|
||||||
onRenamedEventsBasedObject: onRenamedEventsBasedObject,
|
|
||||||
onDeletedEventsBasedObject: onDeletedEventsBasedObject,
|
|
||||||
openObjectEvents,
|
|
||||||
unsavedChanges: unsavedChanges,
|
|
||||||
canOpen: !!props.storageProviders.filter(
|
|
||||||
({ hiddenInOpenDialog }) => !hiddenInOpenDialog
|
|
||||||
).length,
|
|
||||||
onChooseProject: () => openOpenFromStorageProviderDialog(),
|
|
||||||
onOpenRecentFile: openFromFileMetadataWithStorageProvider,
|
|
||||||
onOpenNewProjectSetupDialog: openNewProjectDialog,
|
|
||||||
onOpenProjectManager: () => openProjectManager(true),
|
|
||||||
onOpenVersionHistory: openVersionHistoryPanel,
|
|
||||||
askToCloseProject,
|
|
||||||
closeProject,
|
|
||||||
onSelectExampleShortHeader: exampleShortHeader => {
|
|
||||||
onSelectExampleShortHeader({
|
|
||||||
exampleShortHeader,
|
|
||||||
preventBackHome: true,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onSelectPrivateGameTemplateListingData: privateGameTemplateListingData => {
|
|
||||||
onSelectPrivateGameTemplateListingData({
|
|
||||||
privateGameTemplateListingData,
|
|
||||||
preventBackHome: true,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onOpenPrivateGameTemplateListingData: privateGameTemplateListingData => {
|
|
||||||
onSelectPrivateGameTemplateListingData({
|
|
||||||
privateGameTemplateListingData,
|
|
||||||
preventBackHome: true,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onCreateEmptyProject: createEmptyProject,
|
|
||||||
onCreateProjectFromExample: createProjectFromExample,
|
|
||||||
onOpenProfile: onOpenProfileDialog,
|
|
||||||
onOpenLanguageDialog: () => openLanguageDialog(true),
|
|
||||||
onOpenPreferences: () => openPreferencesDialog(true),
|
|
||||||
onOpenAbout: () => openAboutDialog(true),
|
|
||||||
selectInAppTutorial: selectInAppTutorial,
|
|
||||||
onLoadEventsFunctionsExtensions: async () => {
|
|
||||||
if (isProjectClosedSoAvoidReloadingExtensions) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return eventsFunctionsExtensionsState.loadProjectEventsFunctionsExtensions(
|
|
||||||
currentProject
|
|
||||||
);
|
|
||||||
},
|
|
||||||
onReloadEventsFunctionsExtensionMetadata: extension => {
|
|
||||||
if (isProjectClosedSoAvoidReloadingExtensions) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
eventsFunctionsExtensionsState.reloadProjectEventsFunctionsExtensionMetadata(
|
|
||||||
currentProject,
|
|
||||||
extension
|
|
||||||
);
|
|
||||||
},
|
|
||||||
onDeleteResource: (
|
|
||||||
resource: gdResource,
|
|
||||||
cb: boolean => void
|
|
||||||
) => {
|
|
||||||
// TODO: Project wide refactoring of objects/events using the resource
|
|
||||||
cb(true);
|
|
||||||
},
|
|
||||||
onRenameResource: (
|
|
||||||
resource: gdResource,
|
|
||||||
newName: string,
|
|
||||||
cb: boolean => void
|
|
||||||
) => {
|
|
||||||
if (currentProject)
|
|
||||||
renameResourcesInProject(currentProject, {
|
|
||||||
[resource.getName()]: newName,
|
|
||||||
});
|
|
||||||
|
|
||||||
cb(true);
|
|
||||||
},
|
|
||||||
openBehaviorEvents: openBehaviorEvents,
|
|
||||||
onExtractAsExternalLayout: onExtractAsExternalLayout,
|
|
||||||
onExtractAsEventBasedObject: onOpenEventBasedObjectEditor,
|
|
||||||
onOpenEventBasedObjectEditor: onOpenEventBasedObjectEditor,
|
|
||||||
onOpenEventBasedObjectVariantEditor: onOpenEventBasedObjectVariantEditor,
|
|
||||||
onDeleteEventsBasedObjectVariant: deleteEventsBasedObjectVariant,
|
|
||||||
onEventsBasedObjectChildrenEdited: onEventsBasedObjectChildrenEdited,
|
|
||||||
onSceneObjectEdited: onSceneObjectEdited,
|
|
||||||
onSceneObjectsDeleted: onSceneObjectsDeleted,
|
|
||||||
onSceneEventsModifiedOutsideEditor: onSceneEventsModifiedOutsideEditor,
|
|
||||||
onExtensionInstalled: onExtensionInstalled,
|
|
||||||
gamesList,
|
|
||||||
gamesPlatformFrameTools,
|
|
||||||
})}
|
|
||||||
</ErrorBoundary>
|
|
||||||
</CommandsContextScopedProvider>
|
|
||||||
</TabContentContainer>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</LeaderboardProvider>
|
</LeaderboardProvider>
|
||||||
<CommandPaletteWithAlgoliaSearch ref={commandPaletteRef} />
|
<CommandPaletteWithAlgoliaSearch ref={commandPaletteRef} />
|
||||||
<LoaderModal
|
<LoaderModal
|
||||||
|
Reference in New Issue
Block a user