mirror of
https://github.com/Heretek-AI/GDevelop-Heretek.git
synced 2026-10-12 02:02:42 +00:00
When browsing search results in event sheet, start from currently selected event
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
#include "GDCore/IDE/Events/EventsPositionFinder.h"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/Events/Event.h"
|
||||
#include "GDCore/Events/EventsList.h"
|
||||
#include "GDCore/String.h"
|
||||
|
||||
namespace gd {
|
||||
class BaseEvent;
|
||||
class EventsList;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
bool EventsPositionFinder::DoVisitEvent(gd::BaseEvent& event) {
|
||||
auto it = std::find(searchedEvents.begin(), searchedEvents.end(), &event);
|
||||
if (it != searchedEvents.end()) {
|
||||
positions[it - searchedEvents.begin()] = index;
|
||||
}
|
||||
index++;
|
||||
return false;
|
||||
}
|
||||
EventsPositionFinder::~EventsPositionFinder() {}
|
||||
|
||||
} // namespace gd
|
||||
@@ -0,0 +1,48 @@
|
||||
#ifndef EventsPositionFinder_H
|
||||
#define EventsPositionFinder_H
|
||||
#include "GDCore/Events/EventsList.h"
|
||||
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
|
||||
#include "GDCore/String.h"
|
||||
|
||||
namespace gd {
|
||||
class BaseEvent;
|
||||
class EventsList;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief Scans an event list to retrieve the position of a list of searched
|
||||
* events when the events list is flattened.
|
||||
*
|
||||
* \ingroup IDE
|
||||
*/
|
||||
class GD_CORE_API EventsPositionFinder : public ArbitraryEventsWorker {
|
||||
public:
|
||||
EventsPositionFinder() : index(0){};
|
||||
virtual ~EventsPositionFinder();
|
||||
|
||||
/**
|
||||
* Return the positions of all searched events
|
||||
*/
|
||||
const std::vector<std::size_t>& GetPositions() const { return positions; }
|
||||
|
||||
/**
|
||||
* Add an event for which the position must be reported in `GetPositions`.
|
||||
*/
|
||||
void AddEventToSearch(gd::BaseEvent* event) {
|
||||
searchedEvents.push_back(event);
|
||||
positions.push_back(gd::String::npos);
|
||||
}
|
||||
|
||||
private:
|
||||
bool DoVisitEvent(gd::BaseEvent& event) override;
|
||||
|
||||
std::vector<gd::BaseEvent*> searchedEvents;
|
||||
std::vector<std::size_t> positions;
|
||||
std::size_t index;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // EventsPositionFinder_H
|
||||
@@ -39,6 +39,11 @@ interface VectorDependencyMetadata {
|
||||
[Const, Ref] DependencyMetadata at(unsigned long index);
|
||||
};
|
||||
|
||||
interface VectorInt {
|
||||
unsigned long size();
|
||||
long at(unsigned long index);
|
||||
};
|
||||
|
||||
interface VectorVariable {
|
||||
unsigned long size();
|
||||
[Const] Variable WRAPPED_at(unsigned long index);
|
||||
@@ -2289,6 +2294,15 @@ interface EventsParametersLister {
|
||||
void Launch([Ref] EventsList events);
|
||||
};
|
||||
|
||||
interface EventsPositionFinder {
|
||||
void EventsPositionFinder();
|
||||
[Value] VectorInt GetPositions();
|
||||
void AddEventToSearch(BaseEvent event);
|
||||
|
||||
//Inherited from ArbitraryEventsWorker
|
||||
void Launch([Ref] EventsList events);
|
||||
};
|
||||
|
||||
interface EventsTypesLister {
|
||||
void EventsTypesLister([Const, Ref] Project project);
|
||||
[Const, Ref] VectorString GetAllEventsTypes();
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <GDCore/IDE/Events/EventsContextAnalyzer.h>
|
||||
#include <GDCore/IDE/Events/EventsListUnfolder.h>
|
||||
#include <GDCore/IDE/Events/EventsParametersLister.h>
|
||||
#include <GDCore/IDE/Events/EventsPositionFinder.h>
|
||||
#include <GDCore/IDE/Events/EventsRefactorer.h>
|
||||
#include <GDCore/IDE/Events/EventsRemover.h>
|
||||
#include <GDCore/IDE/Events/EventsTypesLister.h>
|
||||
@@ -383,6 +384,7 @@ typedef std::vector<std::shared_ptr<gd::Variable>> VectorVariable;
|
||||
typedef std::map<gd::String, gd::PropertyDescriptor>
|
||||
MapStringPropertyDescriptor;
|
||||
typedef std::set<gd::String> SetString;
|
||||
typedef std::vector<std::size_t> VectorInt;
|
||||
typedef std::vector<Point> VectorPoint;
|
||||
typedef std::vector<Polygon2d> VectorPolygon2d;
|
||||
typedef std::vector<sf::Vector2f> VectorVector2f;
|
||||
|
||||
@@ -159,6 +159,15 @@ var adaptNamingConventions = function (gd) {
|
||||
return arr;
|
||||
};
|
||||
|
||||
gd.VectorInt.prototype.toJSArray = function () {
|
||||
var arr = [];
|
||||
var size = this.size();
|
||||
for (var i = 0; i < size; ++i) {
|
||||
arr.push(this.at(i));
|
||||
}
|
||||
return arr;
|
||||
};
|
||||
|
||||
// Add gd.Serializer.fromJSObject which is much faster than manually parsing
|
||||
// JSON with gd.Serializer.fromJSON.
|
||||
const elementFromJSObject = function (object, element) {
|
||||
|
||||
+251
-185
File diff suppressed because it is too large
Load Diff
@@ -199,6 +199,12 @@ type ParticleEmitterObject_RendererType = 0 | 1 | 2`
|
||||
'declare class gdVectorString {\n toJSArray(): Array<string>;',
|
||||
'types/gdvectorstring.js'
|
||||
);
|
||||
shell.sed(
|
||||
'-i',
|
||||
'declare class gdVectorInt {',
|
||||
'declare class gdVectorInt {\n toJSArray(): Array<number>;',
|
||||
'types/gdvectorint.js'
|
||||
);
|
||||
shell.sed(
|
||||
'-i',
|
||||
'declare class gdSerializer {',
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
// Automatically generated by GDevelop.js/scripts/generate-types.js
|
||||
declare class gdEventsPositionFinder {
|
||||
constructor(): void;
|
||||
getPositions(): gdVectorInt;
|
||||
addEventToSearch(event: gdBaseEvent): void;
|
||||
launch(events: gdEventsList): void;
|
||||
delete(): void;
|
||||
ptr: number;
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
// Automatically generated by GDevelop.js/scripts/generate-types.js
|
||||
declare class gdVectorInt {
|
||||
toJSArray(): Array<number>;
|
||||
size(): number;
|
||||
at(index: number): number;
|
||||
delete(): void;
|
||||
ptr: number;
|
||||
};
|
||||
@@ -37,6 +37,7 @@ declare class libGDevelop {
|
||||
VectorString: Class<gdVectorString>;
|
||||
VectorPlatformExtension: Class<gdVectorPlatformExtension>;
|
||||
VectorDependencyMetadata: Class<gdVectorDependencyMetadata>;
|
||||
VectorInt: Class<gdVectorInt>;
|
||||
VectorVariable: Class<gdVectorVariable>;
|
||||
MapStringString: Class<gdMapStringString>;
|
||||
MapStringBoolean: Class<gdMapStringBoolean>;
|
||||
@@ -169,6 +170,7 @@ declare class libGDevelop {
|
||||
ProjectResourcesAdder: Class<gdProjectResourcesAdder>;
|
||||
ArbitraryEventsWorker: Class<gdArbitraryEventsWorker>;
|
||||
EventsParametersLister: Class<gdEventsParametersLister>;
|
||||
EventsPositionFinder: Class<gdEventsPositionFinder>;
|
||||
EventsTypesLister: Class<gdEventsTypesLister>;
|
||||
InstructionsTypeRenamer: Class<gdInstructionsTypeRenamer>;
|
||||
EventsContext: Class<gdEventsContext>;
|
||||
|
||||
@@ -24,4 +24,4 @@
|
||||
|
||||
[options]
|
||||
module.ignore_non_literal_requires=true
|
||||
sharedmemory.hash_table_pow=21
|
||||
sharedmemory.hash_table_pow=22
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// @flow
|
||||
import * as React from 'react';
|
||||
import { type SelectionState } from './SelectionHandler';
|
||||
import { type SelectionState, getSelectedEvents } from './SelectionHandler';
|
||||
import { mapFor } from '../Utils/MapFor';
|
||||
import uniqBy from 'lodash/uniqBy';
|
||||
const gd: libGDevelop = global.gd;
|
||||
@@ -47,6 +47,43 @@ type Props = {|
|
||||
|}) => React.Node,
|
||||
|};
|
||||
|
||||
/**
|
||||
* Computes the positions of the first selected event and the search results
|
||||
* in the flatten event tree and looks for the search result just after the
|
||||
* first selected event.
|
||||
*/
|
||||
const getSearchInitialOffset = (
|
||||
events: gdEventsList,
|
||||
resultEvents: Array<gdBaseEvent>,
|
||||
selection: SelectionState
|
||||
): number => {
|
||||
const selectedEvents = getSelectedEvents(selection);
|
||||
if (!selectedEvents.length) return 0;
|
||||
|
||||
const eventsToSearch = [selectedEvents[0], ...resultEvents];
|
||||
|
||||
const positionFinder = new gd.EventsPositionFinder();
|
||||
eventsToSearch.forEach(event => positionFinder.addEventToSearch(event));
|
||||
positionFinder.launch(events);
|
||||
const [
|
||||
selectedEventPosition,
|
||||
...searchResultsPositions
|
||||
] = positionFinder.getPositions().toJSArray();
|
||||
|
||||
// Search results are considered to be sorted by position
|
||||
// (top to bottom in the flatten event tree)
|
||||
for (
|
||||
let searchResultIndex = 0;
|
||||
searchResultIndex < searchResultsPositions.length;
|
||||
searchResultIndex++
|
||||
) {
|
||||
if (searchResultsPositions[searchResultIndex] >= selectedEventPosition) {
|
||||
return searchResultIndex;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Component allowing to do search in events and pass the results
|
||||
* to its children components, as well as methods to browse the results.
|
||||
@@ -185,11 +222,16 @@ export default class EventsSearcher extends React.Component<Props, State> {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { searchFocusOffset } = this.state;
|
||||
|
||||
let newSearchFocusOffset =
|
||||
this.state.searchFocusOffset === null
|
||||
? 0
|
||||
: ((this.state.searchFocusOffset || 0) + step) %
|
||||
this._resultEvents.length;
|
||||
searchFocusOffset === null || searchFocusOffset === undefined
|
||||
? getSearchInitialOffset(
|
||||
this.props.events,
|
||||
this._resultEvents,
|
||||
this.props.selection
|
||||
)
|
||||
: (searchFocusOffset + step) % this._resultEvents.length;
|
||||
if (newSearchFocusOffset < 0)
|
||||
newSearchFocusOffset += this._resultEvents.length;
|
||||
|
||||
|
||||
@@ -332,6 +332,7 @@ export class EventsSheetComponentWithoutHandle extends React.Component<
|
||||
};
|
||||
|
||||
_closeSearchPanel = () => {
|
||||
if (this._eventSearcher) this._eventSearcher.reset();
|
||||
this.setState({ showSearchPanel: false });
|
||||
};
|
||||
|
||||
@@ -1309,7 +1310,6 @@ export class EventsSheetComponentWithoutHandle extends React.Component<
|
||||
replaceInEvents,
|
||||
goToPreviousSearchResult,
|
||||
goToNextSearchResult,
|
||||
clearSearchResults,
|
||||
}) => (
|
||||
<div
|
||||
className="gd-events-sheet"
|
||||
@@ -1390,7 +1390,6 @@ export class EventsSheetComponentWithoutHandle extends React.Component<
|
||||
this._ensureEventUnfolded(goToPreviousSearchResult)
|
||||
}
|
||||
onCloseSearchPanel={() => {
|
||||
clearSearchResults();
|
||||
this._closeSearchPanel();
|
||||
}}
|
||||
onGoToNextSearchResult={() =>
|
||||
|
||||
@@ -115,28 +115,37 @@ export default class KeyboardShortcuts {
|
||||
|
||||
if (onMove) {
|
||||
if (evt.which === UP_KEY) {
|
||||
evt.preventDefault();
|
||||
this._shiftPressed ? onMove(0, -5) : onMove(0, -1);
|
||||
} else if (evt.which === DOWN_KEY) {
|
||||
evt.preventDefault();
|
||||
this._shiftPressed ? onMove(0, 5) : onMove(0, 1);
|
||||
} else if (evt.which === LEFT_KEY) {
|
||||
evt.preventDefault();
|
||||
this._shiftPressed ? onMove(-5, 0) : onMove(-1, 0);
|
||||
} else if (evt.which === RIGHT_KEY) {
|
||||
evt.preventDefault();
|
||||
this._shiftPressed ? onMove(5, 0) : onMove(1, 0);
|
||||
}
|
||||
}
|
||||
if (onDelete && (evt.which === BACKSPACE_KEY || evt.which === DELETE_KEY)) {
|
||||
evt.preventDefault();
|
||||
onDelete();
|
||||
}
|
||||
if (onCopy && this._isControlOrCmdPressed() && evt.which === C_KEY) {
|
||||
evt.preventDefault();
|
||||
onCopy();
|
||||
}
|
||||
if (onCut && this._isControlOrCmdPressed() && evt.which === X_KEY) {
|
||||
evt.preventDefault();
|
||||
onCut();
|
||||
}
|
||||
if (onPaste && this._isControlOrCmdPressed() && evt.which === V_KEY) {
|
||||
evt.preventDefault();
|
||||
onPaste();
|
||||
}
|
||||
if (onUndo && this._isControlOrCmdPressed() && evt.which === Z_KEY) {
|
||||
evt.preventDefault();
|
||||
onUndo();
|
||||
}
|
||||
if (
|
||||
@@ -145,29 +154,37 @@ export default class KeyboardShortcuts {
|
||||
evt.shiftKey &&
|
||||
evt.which === Z_KEY
|
||||
) {
|
||||
evt.preventDefault();
|
||||
onRedo();
|
||||
}
|
||||
if (onRedo && this._isControlOrCmdPressed() && evt.which === Y_KEY) {
|
||||
evt.preventDefault();
|
||||
onRedo();
|
||||
}
|
||||
if (onSearch && this._isControlOrCmdPressed() && evt.which === F_KEY) {
|
||||
evt.preventDefault();
|
||||
onSearch();
|
||||
}
|
||||
if (onEscape && evt.which === ESC_KEY) {
|
||||
evt.preventDefault();
|
||||
onEscape();
|
||||
}
|
||||
|
||||
if (onZoomOut && this._isControlOrCmdPressed() && evt.which === MINUS_KEY) {
|
||||
evt.preventDefault();
|
||||
onZoomOut(evt);
|
||||
}
|
||||
if (onZoomOut && evt.which === NUMPAD_SUBTRACT) {
|
||||
evt.preventDefault();
|
||||
onZoomOut(evt);
|
||||
}
|
||||
|
||||
if (onZoomIn && this._isControlOrCmdPressed() && evt.which === EQUAL_KEY) {
|
||||
evt.preventDefault();
|
||||
onZoomIn(evt);
|
||||
}
|
||||
if (onZoomIn && evt.which === NUMPAD_ADD) {
|
||||
evt.preventDefault();
|
||||
onZoomIn(evt);
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user