Compare commits

...

2 Commits

Author SHA1 Message Date
Florian Rival
869a050d24 Fix broken JavaScript event autocompletions in the IDE
This was broken because the GDJS source files were missing, only the built files were considered.

The disadvantage of this change is having to copy more files everytime a change is made. The impact should be limited though as the copy time is in the same magnitude as before, and the alternative would be to emit .d.ts files which would force to run TypeScript compiler as part of the GDJS build process, and would make the TypeScript compiler time to complete at least 2x slower.
To keep iterations fast when working on GDJS, this approach is preferable.

Don't show in changelog
2021-01-12 19:20:08 +01:00
Florian Rival
1064570727 Improve the search bar when adding an action/condition to search in all the existing actions and conditions.
* This includes the object actions and conditions. If one is selected, the object can be chosen as a parameter.
* This should reduce confusions for users searching for an action/condition and not finding it because they have not chosen an object first.

TODO: slice the size of the list to reduce the lag when searching
2021-01-10 13:50:11 +01:00
4 changed files with 105 additions and 90 deletions

View File

@@ -5,14 +5,8 @@ const args = require('minimist')(process.argv.slice(2));
const gdevelopRootPath = path.join(__dirname, '..', '..', '..');
const destinationPaths = [
path.join(__dirname, '..', 'resources', 'GDJS', 'Runtime'),
path.join(
__dirname,
'..',
'node_modules',
'GDJS-for-web-app-only',
'Runtime'
),
path.join(__dirname, '..', 'resources', 'GDJS'),
path.join(__dirname, '..', 'node_modules', 'GDJS-for-web-app-only'),
];
// Build GDJS
@@ -32,7 +26,7 @@ const copyOptions = {
};
shell.echo(
` Copying GDJS and extensions runtime files (*.js) to ${destinationPaths.join(
` Copying GDJS and extensions runtime built files and sources to ${destinationPaths.join(
', '
)}...`
);
@@ -44,13 +38,30 @@ destinationPaths.forEach(destinationPath => {
shell.mkdir('-p', destinationPath);
const startTime = Date.now();
return copy(
path.join(gdevelopRootPath, 'GDJS', 'Runtime-bundled'),
destinationPath,
copyOptions
)
.then(function(results) {
const totalFilesCount = results.length;
// TODO: Investigate the use of a smart & faster sync
// that only copy files with changed content.
return Promise.all([
// Copy the built files
copy(
path.join(gdevelopRootPath, 'GDJS', 'Runtime-bundled'),
path.join(destinationPath, 'Runtime'),
copyOptions
),
// Copy the GDJS runtime and extension sources (useful for autocompletions
// in the IDE).
copy(
path.join(gdevelopRootPath, 'GDJS', 'Runtime'),
path.join(destinationPath, 'Runtime-sources'),
copyOptions
),
copy(
path.join(gdevelopRootPath, 'Extensions'),
path.join(destinationPath, 'Runtime-sources', 'Extensions'),
{ ...copyOptions, filter: ['**/*.js', '**/*.ts'] }
),
])
.then(function([bundledResults, unbundledResults, unbundledExtensionsResults]) {
const totalFilesCount = bundledResults.length + unbundledResults.length + unbundledExtensionsResults.length;
const duration = Date.now() - startTime;
console.info(
`✅ Runtime files copy done (${totalFilesCount} file(s) copied in ${duration}ms).`

View File

@@ -4,9 +4,6 @@ import optionalRequire from '../Utils/OptionalRequire';
const fs = optionalRequire('fs');
const path = optionalRequire('path');
// TODO: Replace the reading into files by an automatic generation of a .d.ts
// using TypeScript from the game engine sources, and have a script integrate the .d.ts
// into newIDE sources
export const setupAutocompletions = (monaco: any) => {
const importAllJsFilesFromFolder = (folderPath: string) =>
fs.readdir(folderPath, (error: ?Error, filenames: Array<string>) => {
@@ -19,7 +16,7 @@ export const setupAutocompletions = (monaco: any) => {
}
filenames.forEach(filename => {
if (filename.endsWith('.js') || filename.endsWith('.ts')) {
if (filename.endsWith('.ts') || filename.endsWith('.js')) {
const fullPath = path.join(folderPath, filename);
fs.readFile(fullPath, 'utf8', (fileError, content) => {
if (fileError) {
@@ -30,42 +27,36 @@ export const setupAutocompletions = (monaco: any) => {
return;
}
monaco.languages.typescript.javascriptDefaults.addExtraLib(
content,
fullPath
);
monaco.languages.typescript.javascriptDefaults.addExtraLib(content, fullPath);
});
}
});
});
findGDJS().then(({ gdjsRoot }) => {
const runtimePath = path.join(gdjsRoot, 'Runtime');
const runtimeTypesPath = path.join(gdjsRoot, 'Runtime', 'types');
const runtimeLibsPath = path.join(gdjsRoot, 'Runtime', 'libs');
const runtimePixiRenderersPath = path.join(
gdjsRoot,
'Runtime',
'pixi-renderers'
);
const runtimeCocosRenderersPath = path.join(
gdjsRoot,
'Runtime',
'cocos-renderers'
);
// Autocompletions are generated by reading the sources of the game engine
// (much like how autocompletions work in Visual Studio Code) - *not* the built files.
// The built files are stripped of their types and documentation, so it would
// not work.
//
// We could also use the TypeScript compiler to emit .d.ts files when building GDJS,
// but this would make TypeScript slower (at least 2x slower) and we would still need
// to copy and read an equivalent number of files.
const runtimePath = path.join(gdjsRoot, 'Runtime-sources');
const runtimeTypesPath = path.join(runtimePath, 'types');
const runtimeLibsPath = path.join(runtimePath, 'libs');
const runtimePixiRenderersPath = path.join(runtimePath, 'pixi-renderers');
const runtimeCocosRenderersPath = path.join(runtimePath, 'cocos-renderers');
const runtimeHowlerSoundManagerPath = path.join(
gdjsRoot,
'Runtime',
runtimePath,
'howler-sound-manager'
);
const runtimeCocosSoundManagerPath = path.join(
gdjsRoot,
'Runtime',
runtimePath,
'cocos-sound-manager'
);
const runtimeFontfaceobserverFontManagerPath = path.join(
gdjsRoot,
'Runtime',
runtimePath,
'fontfaceobserver-font-manager'
);
const extensionsPath = path.join(runtimePath, 'Extensions');

View File

@@ -11,6 +11,7 @@ import {
findInTree,
} from '../../InstructionOrExpression/CreateTree';
import {
enumerateAllInstructions,
enumerateFreeInstructions,
filterInstructionsList,
} from '../../InstructionOrExpression/EnumerateInstructions';
@@ -85,17 +86,24 @@ export default class InstructionOrObjectSelector extends React.PureComponent<
_scrollView = React.createRef<ScrollViewInterface>();
_selectedItem = React.createRef<ListItemRefType>();
instructionsInfo: Array<EnumeratedInstructionMetadata> = enumerateFreeInstructions(
// Free instructions, to be displayed in a tab next to the objects.
freeInstructionsInfo: Array<EnumeratedInstructionMetadata> = enumerateFreeInstructions(
this.props.isCondition
);
instructionsInfoTree: InstructionOrExpressionTreeNode = createTree(
this.instructionsInfo
freeInstructionsInfoTree: InstructionOrExpressionTreeNode = createTree(
this.freeInstructionsInfo
);
initialInstructionTypePath = findInTree(
this.instructionsInfoTree,
this.freeInstructionsInfoTree,
this.props.chosenInstructionType
);
// All the instructions, to be used when searching, so that the search is done
// across all the instructions (including object and behaviors instructions).
allInstructionsInfo: Array<EnumeratedInstructionMetadata> = enumerateAllInstructions(
this.props.isCondition
);
componentDidMount() {
if (
this.props.focusOnMount &&
@@ -168,11 +176,12 @@ export default class InstructionOrObjectSelector extends React.PureComponent<
const displayedObjectGroupsList = selectedObjectTags.length
? []
: filterGroupsList(allGroupsList, searchText);
const isSearching = !!searchText;
const displayedInstructionsList = filterInstructionsList(
this.instructionsInfo,
// When searching, search among all the instructions
isSearching ? this.allInstructionsInfo : this.freeInstructionsInfo,
{ searchText }
);
const isSearching = !!searchText;
const hasResults =
!isSearching ||
!!displayedObjectsList.length ||
@@ -265,49 +274,53 @@ export default class InstructionOrObjectSelector extends React.PureComponent<
)}
{hasResults && (
<List>
{(isSearching || currentTab === 'objects') &&
displayedObjectsList.map(objectWithContext =>
renderObjectListItem({
project: project,
objectWithContext: objectWithContext,
iconSize: iconSize,
onClick: () =>
onChooseObject(
objectWithContext.object.getName()
),
selectedValue: chosenObjectName
? getObjectOrObjectGroupListItemValue(
chosenObjectName
)
: undefined,
})
)}
{(isSearching || currentTab === 'objects') &&
displayedObjectGroupsList.length > 0 && (
<Subheader>
<Trans>Object groups</Trans>
</Subheader>
)}
{(isSearching || currentTab === 'objects') &&
displayedObjectGroupsList.map(groupWithContext =>
renderGroupObjectsListItem({
groupWithContext: groupWithContext,
iconSize: iconSize,
onClick: () =>
onChooseObject(groupWithContext.group.getName()),
selectedValue: chosenObjectName
? getObjectOrObjectGroupListItemValue(
chosenObjectName
)
: undefined,
})
)}
{(isSearching || currentTab === 'objects') && (
<React.Fragment>
{displayedObjectsList.map(objectWithContext =>
renderObjectListItem({
project: project,
objectWithContext: objectWithContext,
iconSize: iconSize,
onClick: () =>
onChooseObject(
objectWithContext.object.getName()
),
selectedValue: chosenObjectName
? getObjectOrObjectGroupListItemValue(
chosenObjectName
)
: undefined,
})
)}
{displayedObjectGroupsList.length > 0 && (
<Subheader>
<Trans>Object groups</Trans>
</Subheader>
)}
{displayedObjectGroupsList.map(groupWithContext =>
renderGroupObjectsListItem({
groupWithContext: groupWithContext,
iconSize: iconSize,
onClick: () =>
onChooseObject(
groupWithContext.group.getName()
),
selectedValue: chosenObjectName
? getObjectOrObjectGroupListItemValue(
chosenObjectName
)
: undefined,
})
)}
</React.Fragment>
)}
{isSearching && displayedInstructionsList.length > 0 && (
<Subheader>
{isCondition ? (
<Trans>Non-objects and other conditions</Trans>
<Trans>Conditions</Trans>
) : (
<Trans>Non-objects and other actions</Trans>
<Trans>Actions</Trans>
)}
</Subheader>
)}
@@ -331,7 +344,7 @@ export default class InstructionOrObjectSelector extends React.PureComponent<
{!isSearching &&
currentTab === 'free-instructions' &&
renderInstructionOrExpressionTree({
instructionTreeNode: this.instructionsInfoTree,
instructionTreeNode: this.freeInstructionsInfoTree,
onChoose: onChooseInstruction,
iconSize,
selectedValue: chosenInstructionType

View File

@@ -43,7 +43,7 @@ export const findGDJS = (
filesContent: Array<TextFileDescriptor>,
|}> => {
// Get GDJS for this version. If you updated the version,
// run `newIDE/web0app/scripts/deploy-GDJS-Runtime` script.
// run `newIDE/web-app/scripts/deploy-GDJS-Runtime` script.
const gdjsRoot = `https://resources.gdevelop-app.com/GDJS-${getIDEVersion()}`;
return Promise.all(