Fix color of grids in scene editor not properly persisted

* Also make the update real time (any change in the settings are shown directly in the editor)

Don't show the rest in the changelog:

* Add various Flow typings where missing (SetupGridDialog and various InstancesEditor files)
* Serialize the settings into a generic "EditorSetting" (so that the Project is agnostic of any editor related stuff)
* Rename uiSettings/options/LayoutEditorCanvasOptions to InstancesEditorSettings
  * Handle everything inside the IDE (so that the Project remains agnostic of any editor related stuff)

Note that in the future, this kind of EditorSetting that is stored inside the project could be moved to its own structure (living outside of the project file).
This commit is contained in:
Florian Rival
2021-08-12 17:05:32 +02:00
committed by Florian Rival
parent a1b840a4fa
commit d1f4d26e49
28 changed files with 579 additions and 430 deletions
@@ -0,0 +1,25 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival ([email protected]). All rights
* reserved. This project is released under the MIT License.
*/
#if defined(GD_IDE_ONLY)
#include "GDCore/CommonTools.h"
#include "GDCore/Serialization/SerializerElement.h"
#include "EditorSettings.h"
namespace gd {
EditorSettings::EditorSettings() {}
void EditorSettings::SerializeTo(SerializerElement& element) const {
element = content;
}
void EditorSettings::UnserializeFrom(
const SerializerElement& element) {
content = element;
}
} // namespace gd
#endif
@@ -0,0 +1,46 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival ([email protected]). All rights
* reserved. This project is released under the MIT License.
*/
#if defined(GD_IDE_ONLY)
#ifndef SCENECANVASSETTINGS_H
#define SCENECANVASSETTINGS_H
#include "GDCore/String.h"
#include "GDCore/Serialization/SerializerElement.h"
namespace gd {
/**
* \brief Container for arbitrary serialized data to be used by the editor
* to store settings.
*
* \see Scene
*/
class GD_CORE_API EditorSettings {
public:
EditorSettings();
virtual ~EditorSettings(){};
/** \name Serialization
*/
///@{
/**
* \brief Serialize the settings.
*/
void SerializeTo(SerializerElement& element) const;
/**
* \brief Unserialize the settings.
*/
void UnserializeFrom(const SerializerElement& element);
///@}
private:
gd::SerializerElement content; ///< Arbitrary content, depending on the editor.
};
} // namespace gd
#endif // SCENECANVASSETTINGS_H
#endif
@@ -1,59 +0,0 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival ([email protected]). All rights
* reserved. This project is released under the MIT License.
*/
#if defined(GD_IDE_ONLY)
#include "LayoutEditorCanvasOptions.h"
#include "GDCore/CommonTools.h"
#include "GDCore/Serialization/SerializerElement.h"
namespace gd {
LayoutEditorCanvasOptions::LayoutEditorCanvasOptions()
: grid(false),
snap(true),
gridWidth(32),
gridHeight(32),
gridOffsetX(0),
gridOffsetY(0),
gridType("rectangular"),
gridR(158),
gridG(180),
gridB(255),
zoomFactor(1),
windowMask(false) {}
void LayoutEditorCanvasOptions::SerializeTo(SerializerElement& element) const {
element.SetAttribute("grid", grid);
element.SetAttribute("snap", snap);
element.SetAttribute("gridWidth", gridWidth);
element.SetAttribute("gridHeight", gridHeight);
element.SetAttribute("gridOffsetX", gridOffsetX);
element.SetAttribute("gridOffsetY", gridOffsetY);
element.SetAttribute("gridType", gridType);
element.SetAttribute("gridR", gridR);
element.SetAttribute("gridG", gridG);
element.SetAttribute("gridB", gridB);
element.SetAttribute("zoomFactor", zoomFactor);
element.SetAttribute("windowMask", windowMask);
}
void LayoutEditorCanvasOptions::UnserializeFrom(
const SerializerElement& element) {
grid = element.GetBoolAttribute("grid");
snap = element.GetBoolAttribute("snap");
windowMask = element.GetBoolAttribute("windowMask");
gridWidth = element.GetDoubleAttribute("gridWidth", 32);
gridHeight = element.GetDoubleAttribute("gridHeight", 32);
gridOffsetX = element.GetDoubleAttribute("gridOffsetX", 0);
gridOffsetY = element.GetDoubleAttribute("gridOffsetY", 0);
gridType = element.GetStringAttribute("gridType", "rectangular");
gridR = element.GetIntAttribute("gridR", 158);
gridG = element.GetIntAttribute("gridG", 180);
gridB = element.GetIntAttribute("gridB", 255);
zoomFactor = element.GetDoubleAttribute("zoomFactor", 1.0);
}
} // namespace gd
#endif
@@ -1,58 +0,0 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival ([email protected]). All rights
* reserved. This project is released under the MIT License.
*/
#if defined(GD_IDE_ONLY)
#ifndef SCENECANVASSETTINGS_H
#define SCENECANVASSETTINGS_H
#include "GDCore/String.h"
namespace gd {
class SerializerElement;
}
namespace gd {
/**
* \brief Tool class used to store settings of a LayoutEditorCanvas.
*
* \see Scene
*/
class GD_CORE_API LayoutEditorCanvasOptions {
public:
LayoutEditorCanvasOptions();
virtual ~LayoutEditorCanvasOptions(){};
/** \name Serialization
*/
///@{
/**
* \brief Serialize instances container.
*/
void SerializeTo(SerializerElement& element) const;
/**
* \brief Unserialize the instances container.
*/
void UnserializeFrom(const SerializerElement& element);
///@}
bool grid; ///< True if grid activated in editor
bool snap; ///< True if snap to grid activated in editor
double gridWidth; ///< Grid width in editor
double gridHeight; ///< Grid height in editor
double gridOffsetX; ///< Grid X offset
double gridOffsetY; ///< Grid Y offset
gd::String gridType; ///< Grid type: rectangular or isometric
int gridR; ///< Grid red color in editor
int gridG; ///< Grid green color in editor
int gridB; ///< Grid blue color in editor
double zoomFactor; ///< Stores the zoom factor
bool windowMask; ///< True if window mask displayed in editor
};
} // namespace gd
#endif // SCENECANVASSETTINGS_H
#endif
+3 -3
View File
@@ -5,7 +5,7 @@
*/
#include "GDCore/Project/ExternalLayout.h"
#include "GDCore/IDE/Dialogs/LayoutEditorCanvas/LayoutEditorCanvasOptions.h"
#include "GDCore/IDE/Dialogs/LayoutEditorCanvas/EditorSettings.h"
#include "GDCore/Project/InitialInstancesContainer.h"
#include "GDCore/Serialization/SerializerElement.h"
#include "GDCore/TinyXml/tinyxml.h"
@@ -16,7 +16,7 @@ void ExternalLayout::UnserializeFrom(const SerializerElement& element) {
name = element.GetStringAttribute("name", "", "Name");
instances.UnserializeFrom(element.GetChild("instances", 0, "Instances"));
#if defined(GD_IDE_ONLY)
editionSettings.UnserializeFrom(element.GetChild("editionSettings"));
editorSettings.UnserializeFrom(element.GetChild("editionSettings"));
#endif
associatedLayout = element.GetStringAttribute("associatedLayout");
}
@@ -25,7 +25,7 @@ void ExternalLayout::UnserializeFrom(const SerializerElement& element) {
void ExternalLayout::SerializeTo(SerializerElement& element) const {
element.SetAttribute("name", name);
instances.SerializeTo(element.AddChild("instances"));
editionSettings.SerializeTo(element.AddChild("editionSettings"));
editorSettings.SerializeTo(element.AddChild("editionSettings"));
element.SetAttribute("associatedLayout", associatedLayout);
}
#endif
+6 -6
View File
@@ -13,7 +13,7 @@ namespace gd {
class SerializerElement;
}
#if defined(GD_IDE_ONLY)
#include "GDCore/IDE/Dialogs/LayoutEditorCanvas/LayoutEditorCanvasOptions.h"
#include "GDCore/IDE/Dialogs/LayoutEditorCanvas/EditorSettings.h"
#endif
namespace gd {
@@ -58,15 +58,15 @@ class GD_CORE_API ExternalLayout {
/**
* \brief Get the user settings for the IDE.
*/
const gd::LayoutEditorCanvasOptions& GetAssociatedSettings() const {
return editionSettings;
const gd::EditorSettings& GetAssociatedEditorSettings() const {
return editorSettings;
}
/**
* \brief Get the user settings for the IDE.
*/
gd::LayoutEditorCanvasOptions& GetAssociatedSettings() {
return editionSettings;
gd::EditorSettings& GetAssociatedEditorSettings() {
return editorSettings;
}
#endif
@@ -100,7 +100,7 @@ class GD_CORE_API ExternalLayout {
gd::String name;
gd::InitialInstancesContainer instances;
#if defined(GD_IDE_ONLY)
gd::LayoutEditorCanvasOptions editionSettings;
gd::EditorSettings editorSettings;
#endif
gd::String associatedLayout;
};
+3 -3
View File
@@ -272,7 +272,7 @@ void Layout::SerializeTo(SerializerElement& element) const {
disableInputWhenNotFocused);
#if defined(GD_IDE_ONLY)
GetAssociatedSettings().SerializeTo(element.AddChild("uiSettings"));
editorSettings.SerializeTo(element.AddChild("uiSettings"));
#endif
GetObjectGroups().SerializeTo(element.AddChild("objectsGroups"));
@@ -333,7 +333,7 @@ void Layout::UnserializeFrom(gd::Project& project,
element.GetBoolAttribute("disableInputWhenNotFocused");
#if defined(GD_IDE_ONLY)
associatedSettings.UnserializeFrom(
editorSettings.UnserializeFrom(
element.GetChild("uiSettings", 0, "UISettings"));
GetObjectGroups().UnserializeFrom(
@@ -412,7 +412,7 @@ void Layout::Init(const Layout& other) {
#if defined(GD_IDE_ONLY)
events = other.events;
associatedSettings = other.associatedSettings;
editorSettings = other.editorSettings;
objectGroups = other.objectGroups;
profiler = other.profiler;
+8 -8
View File
@@ -18,7 +18,7 @@
#include "GDCore/Project/VariablesContainer.h"
#include "GDCore/String.h"
#if defined(GD_IDE_ONLY)
#include "GDCore/IDE/Dialogs/LayoutEditorCanvas/LayoutEditorCanvasOptions.h"
#include "GDCore/IDE/Dialogs/LayoutEditorCanvas/EditorSettings.h"
#endif
namespace gd {
class BaseEvent;
@@ -291,18 +291,18 @@ class GD_CORE_API Layout : public ObjectsContainer {
#if defined(GD_IDE_ONLY)
/**
* Return the settings associated to the layout.
* \see gd::LayoutEditorCanvasOptions
* \see gd::EditorSettings
*/
const gd::LayoutEditorCanvasOptions& GetAssociatedSettings() const {
return associatedSettings;
const gd::EditorSettings& GetAssociatedEditorSettings() const {
return editorSettings;
}
/**
* Return the settings associated to the layout.
* \see gd::LayoutEditorCanvasOptions
* \see gd::EditorSettings
*/
gd::LayoutEditorCanvasOptions& GetAssociatedSettings() {
return associatedSettings;
gd::EditorSettings& GetAssociatedEditorSettings() {
return editorSettings;
}
#endif
@@ -436,7 +436,7 @@ class GD_CORE_API Layout : public ObjectsContainer {
///< specified behavior shared data.
#if defined(GD_IDE_ONLY)
EventsList events; ///< Scene events
gd::LayoutEditorCanvasOptions associatedSettings;
gd::EditorSettings editorSettings;
#endif
// TODO: GD C++ Platform specific code below
+4 -4
View File
@@ -607,7 +607,7 @@ interface Layout {
void SerializeLayersTo([Ref] SerializerElement element);
void UnserializeLayersFrom([Const, Ref] SerializerElement element);
[Ref] LayoutEditorCanvasOptions GetAssociatedSettings();
[Ref] EditorSettings GetAssociatedEditorSettings();
void SerializeTo([Ref] SerializerElement element);
void UnserializeFrom([Ref] Project project, [Const, Ref] SerializerElement element);
@@ -656,7 +656,7 @@ interface ExternalLayout {
[Const, Ref] DOMString GetAssociatedLayout();
[Ref] InitialInstancesContainer GetInitialInstances();
[Ref] LayoutEditorCanvasOptions GetAssociatedSettings();
[Ref] EditorSettings GetAssociatedEditorSettings();
void SerializeTo([Ref] SerializerElement element);
void UnserializeFrom([Const, Ref] SerializerElement element);
@@ -2314,8 +2314,8 @@ interface ResourcesInUseHelper {
};
ResourcesInUseHelper implements ArbitraryResourceWorker;
interface LayoutEditorCanvasOptions {
void LayoutEditorCanvasOptions();
interface EditorSettings {
void EditorSettings();
void SerializeTo([Ref] SerializerElement element);
void UnserializeFrom([Const, Ref] SerializerElement element);
+1 -1
View File
@@ -20,7 +20,7 @@
#include <GDCore/Extensions/Metadata/ParameterMetadataTools.h>
#include <GDCore/Extensions/Platform.h>
#include <GDCore/IDE/AbstractFileSystem.h>
#include <GDCore/IDE/Dialogs/LayoutEditorCanvas/LayoutEditorCanvasOptions.h>
#include <GDCore/IDE/Dialogs/LayoutEditorCanvas/EditorSettings.h>
#include <GDCore/IDE/Events/ArbitraryEventsWorker.h>
#include <GDCore/IDE/Events/EventsContextAnalyzer.h>
#include <GDCore/IDE/Events/EventsListUnfolder.h>
+22
View File
@@ -3612,4 +3612,26 @@ describe('libGD.js', function () {
);
});
});
describe('gd.EditorSettings', () => {
it('can store anything', () => {
const element = gd.Serializer.fromJSObject({
test: 1,
anything: {
canBeStored: true,
},
});
const editorSettings = new gd.EditorSettings();
editorSettings.unserializeFrom(element);
const element2 = new gd.SerializerElement();
editorSettings.serializeTo(element2);
expect(element2.getChild('test').getIntValue()).toBe(1);
expect(
element2.getChild('anything').getChild('canBeStored').getBoolValue()
).toBe(true);
});
});
});
@@ -1,5 +1,5 @@
// Automatically generated by GDevelop.js/scripts/generate-types.js
declare class gdLayoutEditorCanvasOptions {
declare class gdEditorSettings {
constructor(): void;
serializeTo(element: gdSerializerElement): void;
unserializeFrom(element: gdSerializerElement): void;
+1 -1
View File
@@ -6,7 +6,7 @@ declare class gdExternalLayout {
setAssociatedLayout(name: string): void;
getAssociatedLayout(): string;
getInitialInstances(): gdInitialInstancesContainer;
getAssociatedSettings(): gdLayoutEditorCanvasOptions;
getAssociatedEditorSettings(): gdEditorSettings;
serializeTo(element: gdSerializerElement): void;
unserializeFrom(element: gdSerializerElement): void;
delete(): void;
+1 -1
View File
@@ -27,7 +27,7 @@ declare class gdLayout extends gdObjectsContainer {
moveLayer(oldIndex: number, newIndex: number): void;
serializeLayersTo(element: gdSerializerElement): void;
unserializeLayersFrom(element: gdSerializerElement): void;
getAssociatedSettings(): gdLayoutEditorCanvasOptions;
getAssociatedEditorSettings(): gdEditorSettings;
serializeTo(element: gdSerializerElement): void;
unserializeFrom(project: gdProject, element: gdSerializerElement): void;
setStopSoundsOnStartup(enable: boolean): void;
+1 -1
View File
@@ -176,7 +176,7 @@ declare class libGDevelop {
ResourcesRenamer: Class<gdResourcesRenamer>;
ProjectResourcesCopier: Class<gdProjectResourcesCopier>;
ResourcesInUseHelper: Class<gdResourcesInUseHelper>;
LayoutEditorCanvasOptions: Class<gdLayoutEditorCanvasOptions>;
EditorSettings: Class<gdEditorSettings>;
Point: Class<gdPoint>;
VectorPoint: Class<gdVectorPoint>;
Polygon2d: Class<gdPolygon2d>;
+80 -51
View File
@@ -1,28 +1,27 @@
// @flow
import * as PIXI from 'pixi.js-legacy';
import {
rgbColorToHexNumber,
// TODO: Add Flow typing in this file.
// , type RGBColor
} from '../Utils/ColorTransformer';
import ViewPosition from './ViewPosition';
import { type InstancesEditorSettings } from './InstancesEditorSettings';
// Equal to #6868E8
const DEFAULT_COLOR /*: RGBColor */ = {
r: 104,
g: 104,
b: 232,
};
type Props = {|
viewPosition: ViewPosition,
instancesEditorSettings: InstancesEditorSettings,
|};
export default class SelectionRectangle {
constructor({ viewPosition, options }) {
export default class Grid {
pixiGrid = new PIXI.Graphics();
instancesEditorSettings: InstancesEditorSettings;
viewPosition: ViewPosition;
constructor({ viewPosition, instancesEditorSettings }: Props) {
this.viewPosition = viewPosition;
this.options = options;
this.instancesEditorSettings = instancesEditorSettings;
this.pixiGrid = new PIXI.Graphics();
this.pixiGrid.hitArea = new PIXI.Rectangle(0, 0, 0, 0);
}
setOptions(options) {
this.options = options;
setInstancesEditorSettings(instancesEditorSettings: InstancesEditorSettings) {
this.instancesEditorSettings = instancesEditorSettings;
}
getPixiObject() {
@@ -30,21 +29,20 @@ export default class SelectionRectangle {
}
render() {
const options = this.options;
const instancesEditorSettings = this.instancesEditorSettings;
if (!options.grid) {
if (!instancesEditorSettings.grid) {
this.pixiGrid.visible = false;
return;
}
const gridColor = options.gridColor || DEFAULT_COLOR;
const gridHex = rgbColorToHexNumber(gridColor);
const gridAlpha = gridColor.a || 1;
const gridColor = instancesEditorSettings.gridColor;
const gridAlpha = 1;
this.pixiGrid.visible = true;
this.pixiGrid.clear();
this.pixiGrid.beginFill(gridHex);
this.pixiGrid.lineStyle(1, gridHex, gridAlpha);
this.pixiGrid.beginFill(gridColor);
this.pixiGrid.lineStyle(1, gridColor, gridAlpha);
this.pixiGrid.fill.alpha = 0.1;
this.pixiGrid.alpha = 0.8;
@@ -55,57 +53,83 @@ export default class SelectionRectangle {
);
const offsetX =
((options.gridOffsetX % options.gridWidth) + options.gridWidth) %
options.gridWidth;
((instancesEditorSettings.gridOffsetX %
instancesEditorSettings.gridWidth) +
instancesEditorSettings.gridWidth) %
instancesEditorSettings.gridWidth;
const offsetY =
((options.gridOffsetY % options.gridHeight) + options.gridHeight) %
options.gridHeight;
((instancesEditorSettings.gridOffsetY %
instancesEditorSettings.gridHeight) +
instancesEditorSettings.gridHeight) %
instancesEditorSettings.gridHeight;
const startX =
Math.floor((sceneStartPoint[0] - offsetX) / options.gridWidth) *
options.gridWidth +
Math.floor(
(sceneStartPoint[0] - offsetX) / instancesEditorSettings.gridWidth
) *
instancesEditorSettings.gridWidth +
offsetX;
const startY =
Math.floor((sceneStartPoint[1] - offsetY) / options.gridHeight) *
options.gridHeight +
Math.floor(
(sceneStartPoint[1] - offsetY) / instancesEditorSettings.gridHeight
) *
instancesEditorSettings.gridHeight +
offsetY;
const endX =
Math.ceil((sceneEndPoint[0] - offsetX) / options.gridWidth) *
options.gridWidth +
Math.ceil(
(sceneEndPoint[0] - offsetX) / instancesEditorSettings.gridWidth
) *
instancesEditorSettings.gridWidth +
offsetX;
const endY =
Math.ceil((sceneEndPoint[1] - offsetY) / options.gridHeight) *
options.gridHeight +
Math.ceil(
(sceneEndPoint[1] - offsetY) / instancesEditorSettings.gridHeight
) *
instancesEditorSettings.gridHeight +
offsetY;
if (options.gridType === 'isometric') {
const countX = Math.round((endX - startX) / options.gridWidth);
const countY = Math.round((endY - startY) / options.gridHeight);
if (instancesEditorSettings.gridType === 'isometric') {
const countX = Math.round(
(endX - startX) / instancesEditorSettings.gridWidth
);
const countY = Math.round(
(endY - startY) / instancesEditorSettings.gridHeight
);
const lineCount = countX + countY;
for (let i = 0; i < lineCount; ++i) {
let lineStartX;
let lineStartY;
if (i < countX) {
// top
lineStartX = startX + options.gridWidth / 2 + i * options.gridWidth;
lineStartX =
startX +
instancesEditorSettings.gridWidth / 2 +
i * instancesEditorSettings.gridWidth;
lineStartY = startY;
} else {
// right
lineStartX = endX;
lineStartY =
startY + options.gridHeight / 2 + (i - countX) * options.gridHeight;
startY +
instancesEditorSettings.gridHeight / 2 +
(i - countX) * instancesEditorSettings.gridHeight;
}
let lineEndX;
let lineEndY;
if (i < countY) {
// left
lineEndX = startX;
lineEndY = startY + options.gridHeight / 2 + i * options.gridHeight;
lineEndY =
startY +
instancesEditorSettings.gridHeight / 2 +
i * instancesEditorSettings.gridHeight;
} else {
// bottom
lineEndX =
startX + options.gridWidth / 2 + (i - countY) * options.gridWidth;
startX +
instancesEditorSettings.gridWidth / 2 +
(i - countY) * instancesEditorSettings.gridWidth;
lineEndY = endY;
}
const start = this.viewPosition.toCanvasCoordinates(
@@ -124,27 +148,32 @@ export default class SelectionRectangle {
lineStartX = startX;
lineStartY =
startY +
options.gridHeight / 2 +
(countY - 1 - i) * options.gridHeight;
instancesEditorSettings.gridHeight / 2 +
(countY - 1 - i) * instancesEditorSettings.gridHeight;
} else {
// top
lineStartX =
startX + options.gridWidth / 2 + (i - countY) * options.gridWidth;
startX +
instancesEditorSettings.gridWidth / 2 +
(i - countY) * instancesEditorSettings.gridWidth;
lineStartY = startY;
}
let lineEndX;
let lineEndY;
if (i < countX) {
// bottom
lineEndX = startX + options.gridWidth / 2 + i * options.gridWidth;
lineEndX =
startX +
instancesEditorSettings.gridWidth / 2 +
i * instancesEditorSettings.gridWidth;
lineEndY = endY;
} else {
// reverse right
lineEndX = endX;
lineEndY =
startY +
options.gridHeight / 2 +
(lineCount - 1 - i) * options.gridHeight;
instancesEditorSettings.gridHeight / 2 +
(lineCount - 1 - i) * instancesEditorSettings.gridHeight;
}
const start = this.viewPosition.toCanvasCoordinates(
lineStartX,
@@ -155,7 +184,7 @@ export default class SelectionRectangle {
this.pixiGrid.lineTo(end[0], end[1]);
}
} else {
for (let x = startX; x < endX; x += options.gridWidth) {
for (let x = startX; x < endX; x += instancesEditorSettings.gridWidth) {
const start = this.viewPosition.toCanvasCoordinates(x, startY);
const end = this.viewPosition.toCanvasCoordinates(x, endY);
@@ -163,7 +192,7 @@ export default class SelectionRectangle {
this.pixiGrid.lineTo(end[0], end[1]);
}
for (let y = startY; y < endY; y += options.gridHeight) {
for (let y = startY; y < endY; y += instancesEditorSettings.gridHeight) {
const start = this.viewPosition.toCanvasCoordinates(startX, y);
const end = this.viewPosition.toCanvasCoordinates(endX, y);
@@ -1,26 +1,27 @@
// @flow
import { roundPosition } from '../Utils/GridHelpers';
import { type InstancesEditorSettings } from './InstancesEditorSettings';
const gd: libGDevelop = global.gd;
type Props = {|
instances: gdInitialInstancesContainer,
options: Object,
instancesEditorSettings: InstancesEditorSettings,
|};
const roundPositionsToGrid = (
pos: [number, number],
options: Object
instancesEditorSettings: InstancesEditorSettings
): [number, number] => {
const newPos = pos;
if (options.grid && options.snap) {
if (instancesEditorSettings.grid && instancesEditorSettings.snap) {
roundPosition(
newPos,
options.gridWidth,
options.gridHeight,
options.gridOffsetX,
options.gridOffsetY,
options.gridType
instancesEditorSettings.gridWidth,
instancesEditorSettings.gridHeight,
instancesEditorSettings.gridOffsetX,
instancesEditorSettings.gridOffsetY,
instancesEditorSettings.gridType
);
} else {
newPos[0] = Math.round(newPos[0]);
@@ -37,17 +38,17 @@ const roundPositionsToGrid = (
export default class InstancesAdder {
_instances: gdInitialInstancesContainer;
_temporaryInstances: Array<gdInitialInstance>;
_options: Object;
_instancesEditorSettings: InstancesEditorSettings;
_zOrderFinder = new gd.HighestZOrderFinder();
constructor({ instances, options }: Props) {
constructor({ instances, instancesEditorSettings }: Props) {
this._instances = instances;
this._options = options;
this._instancesEditorSettings = instancesEditorSettings;
this._temporaryInstances = [];
}
setOptions(options: Object) {
this._options = options;
setInstancesEditorSettings(instancesEditorSettings: InstancesEditorSettings) {
this._instancesEditorSettings = instancesEditorSettings;
}
/**
@@ -61,7 +62,7 @@ export default class InstancesAdder {
this._instances.iterateOverInstances(this._zOrderFinder);
const zOrder = this._zOrderFinder.getHighestZOrder() + 1;
const newPos = roundPositionsToGrid(pos, this._options);
const newPos = roundPositionsToGrid(pos, this._instancesEditorSettings);
const addedInstances = objectNames.map(objectName => {
const instance: gdInitialInstance = this._instances.insertNewInitialInstance();
instance.setObjectName(objectName);
@@ -101,7 +102,7 @@ export default class InstancesAdder {
this._instances.iterateOverInstances(this._zOrderFinder);
const zOrder = this._zOrderFinder.getHighestZOrder() + 1;
const newPos = roundPositionsToGrid(pos, this._options);
const newPos = roundPositionsToGrid(pos, this._instancesEditorSettings);
this._temporaryInstances = objectNames.map(objectName => {
const instance: gdInitialInstance = this._instances.insertNewInitialInstance();
instance.setObjectName(objectName);
@@ -120,7 +121,7 @@ export default class InstancesAdder {
updateTemporaryInstancePositions = (
pos: [number, number]
): Array<gdInitialInstance> => {
const newPos = roundPositionsToGrid(pos, this._options);
const newPos = roundPositionsToGrid(pos, this._instancesEditorSettings);
this._temporaryInstances.forEach(instance => {
instance.setX(newPos[0]);
instance.setY(newPos[1]);
@@ -0,0 +1,45 @@
// @flow
import { rgbToHexNumber } from '../Utils/ColorTransformer';
export type InstancesEditorSettings = {|
/** Is grid shown? */
grid: boolean,
gridType: 'isometric' | 'rectangular',
gridWidth: number,
gridHeight: number,
gridOffsetX: number,
gridOffsetY: number,
gridColor: number,
/** Is snap to grid activated? */
snap: boolean,
/** The zoom of the editor, 1 by default. */
zoomFactor: number,
/** Is the window mask shown? */
windowMask: boolean,
|};
export const prepareInstancesEditorSettings = (
object: any
): InstancesEditorSettings => {
return {
grid: object.grid || false,
gridType: object.gridType || 'rectangular',
gridWidth: object.gridWidth || 32,
gridHeight: object.gridHeight || 32,
gridOffsetX: object.gridOffsetX || 0,
gridOffsetY: object.gridOffsetY || 0,
gridColor: object.gridColor || rgbToHexNumber(158, 180, 255),
snap: object.snap || false,
zoomFactor: Math.max(object.zoomFactor || 1, 0.0001),
windowMask: object.windowMask || false,
};
};
export const cloneInstancesEditorSettings = (
instancesEditorSettings: InstancesEditorSettings
) => {
return { ...instancesEditorSettings };
};
@@ -1,10 +1,11 @@
// @flow
import { roundPosition } from '../Utils/GridHelpers';
import Rectangle from '../Utils/Rectangle';
import { type InstancesEditorSettings } from './InstancesEditorSettings';
export default class InstancesMover {
instanceMeasurer: any;
options: Object;
instancesEditorSettings: InstancesEditorSettings;
instancePositions: { [number]: { x: number, y: number } };
totalDeltaX: number;
totalDeltaY: number;
@@ -15,21 +16,21 @@ export default class InstancesMover {
constructor({
instanceMeasurer,
options,
instancesEditorSettings,
}: {
instanceMeasurer: any,
options: Object,
instancesEditorSettings: InstancesEditorSettings,
}) {
this.instanceMeasurer = instanceMeasurer;
this.options = options;
this.instancesEditorSettings = instancesEditorSettings;
this.instancePositions = {};
this.totalDeltaX = 0;
this.totalDeltaY = 0;
this._temporaryPoint = [0, 0];
}
setOptions(options: Object) {
this.options = options;
setInstancesEditorSettings(instancesEditorSettings: InstancesEditorSettings) {
this.instancesEditorSettings = instancesEditorSettings;
}
_getMoveDeltaX(
@@ -96,14 +97,18 @@ export default class InstancesMover {
const magnetPosition = this._temporaryPoint;
magnetPosition[0] = initialMagnetX + this.totalDeltaX;
magnetPosition[1] = initialMagnetY + this.totalDeltaY;
if (this.options.snap && this.options.grid && !noGridSnap) {
if (
this.instancesEditorSettings.snap &&
this.instancesEditorSettings.grid &&
!noGridSnap
) {
roundPosition(
magnetPosition,
this.options.gridWidth,
this.options.gridHeight,
this.options.gridOffsetX,
this.options.gridOffsetY,
this.options.gridType
this.instancesEditorSettings.gridWidth,
this.instancesEditorSettings.gridHeight,
this.instancesEditorSettings.gridOffsetX,
this.instancesEditorSettings.gridOffsetY,
this.instancesEditorSettings.gridType
);
} else {
// Without a grid, the position is still rounded to the nearest pixel.
@@ -1,6 +1,7 @@
// @flow
import Rectangle from '../Utils/Rectangle';
import { roundPositionForResizing } from '../Utils/GridHelpers';
import { type InstancesEditorSettings } from './InstancesEditorSettings';
export type ResizeGrabbingLocation =
| 'TopLeft'
@@ -49,7 +50,7 @@ const areAnyInstancesNotStraight = (instances: gdInitialInstance[]) => {
export default class InstancesResizer {
instanceMeasurer: any;
options: Object;
instancesEditorSettings: InstancesEditorSettings;
// The initial state of instances before a resize:
_initialSelectionAABB: ?Rectangle = null;
@@ -68,17 +69,17 @@ export default class InstancesResizer {
constructor({
instanceMeasurer,
options,
instancesEditorSettings,
}: {
instanceMeasurer: any,
options: Object,
instancesEditorSettings: InstancesEditorSettings,
}) {
this.instanceMeasurer = instanceMeasurer;
this.options = options;
this.instancesEditorSettings = instancesEditorSettings;
}
setOptions(options: Object) {
this.options = options;
setInstancesEditorSettings(instancesEditorSettings: InstancesEditorSettings) {
this.instancesEditorSettings = instancesEditorSettings;
}
_getOrCreateInstanceAABB(instance: gdInitialInstance) {
@@ -154,14 +155,17 @@ export default class InstancesResizer {
const grabbingPosition = this._temporaryGrabbingPosition;
grabbingPosition[0] = initialGrabbingX + this.totalDeltaX;
grabbingPosition[1] = initialGrabbingY + this.totalDeltaY;
if (this.options.snap && this.options.grid) {
if (
this.instancesEditorSettings.snap &&
this.instancesEditorSettings.grid
) {
roundPositionForResizing(
grabbingPosition,
this.options.gridWidth,
this.options.gridHeight,
this.options.gridOffsetX,
this.options.gridOffsetY,
this.options.gridType
this.instancesEditorSettings.gridWidth,
this.instancesEditorSettings.gridHeight,
this.instancesEditorSettings.gridOffsetX,
this.instancesEditorSettings.gridOffsetY,
this.instancesEditorSettings.gridType
);
} else {
// Without a grid, the position is still rounded to the nearest pixel.
+23 -14
View File
@@ -1,12 +1,13 @@
// @flow
import * as PIXI from 'pixi.js-legacy';
import { type InstancesEditorSettings } from './InstancesEditorSettings';
type Props = {|
initialViewX: number,
initialViewY: number,
width: number,
height: number,
options: any,
instancesEditorSettings: InstancesEditorSettings,
|};
export default class ViewPosition {
@@ -14,18 +15,24 @@ export default class ViewPosition {
viewY: number = 0;
_width: number;
_height: number;
options: any;
instancesEditorSettings: InstancesEditorSettings;
_pixiContainer = new PIXI.Container();
constructor({ initialViewX, initialViewY, width, height, options }: Props) {
constructor({
initialViewX,
initialViewY,
width,
height,
instancesEditorSettings,
}: Props) {
this.viewX = initialViewX;
this.viewY = initialViewY;
this.options = options;
this.instancesEditorSettings = instancesEditorSettings;
this.resize(width, height);
}
setOptions(options: any) {
this.options = options;
setInstancesEditorSettings(instancesEditorSettings: InstancesEditorSettings) {
this.instancesEditorSettings = instancesEditorSettings;
}
resize(width: number, height: number) {
@@ -48,8 +55,8 @@ export default class ViewPosition {
toSceneCoordinates = (x: number, y: number): [number, number] => {
x -= this._width / 2;
y -= this._height / 2;
x /= Math.abs(this.options.zoomFactor);
y /= Math.abs(this.options.zoomFactor);
x /= Math.abs(this.instancesEditorSettings.zoomFactor);
y /= Math.abs(this.instancesEditorSettings.zoomFactor);
var viewRotation = 0;
var tmp = x;
@@ -80,8 +87,8 @@ export default class ViewPosition {
Math.sin((viewRotation / 180) * Math.PI) * tmp +
Math.cos((viewRotation / 180) * Math.PI) * y;
x *= Math.abs(this.options.zoomFactor);
y *= Math.abs(this.options.zoomFactor);
x *= Math.abs(this.instancesEditorSettings.zoomFactor);
y *= Math.abs(this.instancesEditorSettings.zoomFactor);
return [x + this._width / 2, y + this._height / 2];
};
@@ -114,11 +121,13 @@ export default class ViewPosition {
}
render() {
this._pixiContainer.position.x = -this.viewX * this.options.zoomFactor;
this._pixiContainer.position.y = -this.viewY * this.options.zoomFactor;
this._pixiContainer.position.x =
-this.viewX * this.instancesEditorSettings.zoomFactor;
this._pixiContainer.position.y =
-this.viewY * this.instancesEditorSettings.zoomFactor;
this._pixiContainer.position.x += this._width / 2;
this._pixiContainer.position.y += this._height / 2;
this._pixiContainer.scale.x = this.options.zoomFactor;
this._pixiContainer.scale.y = this.options.zoomFactor;
this._pixiContainer.scale.x = this.instancesEditorSettings.zoomFactor;
this._pixiContainer.scale.y = this.instancesEditorSettings.zoomFactor;
}
}
+14 -2
View File
@@ -1,14 +1,26 @@
// @flow
import * as PIXI from 'pixi.js-legacy';
import transformRect from '../Utils/TransformRect';
import { rgbToHexNumber } from '../Utils/ColorTransformer';
type Props = {|
project: gdProject,
layout: gdLayout,
toCanvasCoordinates: (x: number, y: number) => [number, number],
|};
export default class WindowBorder {
constructor({ project, layout, toCanvasCoordinates }) {
project: gdProject;
layout: gdLayout;
toCanvasCoordinates: (x: number, y: number) => [number, number];
pixiRectangle = new PIXI.Graphics();
windowRectangle: { x: number, y: number, width: number, height: number };
constructor({ project, layout, toCanvasCoordinates }: Props) {
this.project = project;
this.layout = layout;
this.toCanvasCoordinates = toCanvasCoordinates;
this.pixiRectangle = new PIXI.Graphics();
this.pixiRectangle.hitArea = new PIXI.Rectangle(0, 0, 0, 0);
this.windowRectangle = {
x: 0,
+26 -15
View File
@@ -1,24 +1,37 @@
// @flow
import * as PIXI from 'pixi.js-legacy';
import transformRect from '../Utils/TransformRect';
import ViewPosition from './ViewPosition';
import { type InstancesEditorSettings } from './InstancesEditorSettings';
export default class WindowBorder {
constructor({ project, viewPosition, options }) {
type Props = {|
project: gdProject,
instancesEditorSettings: InstancesEditorSettings,
viewPosition: ViewPosition,
|};
export default class WindowMask {
project: gdProject;
instancesEditorSettings: InstancesEditorSettings;
viewPosition: ViewPosition;
pixiRectangle = new PIXI.Graphics();
windowRectangle = {
x: 0,
y: 0,
width: 0,
height: 0,
};
constructor({ project, viewPosition, instancesEditorSettings }: Props) {
this.project = project;
this.viewPosition = viewPosition;
this.options = options;
this.instancesEditorSettings = instancesEditorSettings;
this.pixiRectangle = new PIXI.Graphics();
this.pixiRectangle.hitArea = new PIXI.Rectangle(0, 0, 0, 0);
this.windowRectangle = {
x: 0,
y: 0,
width: 0,
height: 0,
};
}
setOptions(options) {
this.options = options;
setInstancesEditorSettings(instancesEditorSettings: InstancesEditorSettings) {
this.instancesEditorSettings = instancesEditorSettings;
}
getPixiObject() {
@@ -26,9 +39,7 @@ export default class WindowBorder {
}
render() {
const options = this.options;
if (!options.windowMask) {
if (!this.instancesEditorSettings.windowMask) {
this.pixiRectangle.visible = false;
return;
}
+33 -17
View File
@@ -30,6 +30,7 @@ import PinchHandler, { shouldBeHandledByPinch } from './PinchHandler';
import { type ScreenType } from '../UI/Reponsive/ScreenTypeMeasurer';
import InstancesSelection from './InstancesSelection';
import LongTouchHandler from './LongTouchHandler';
import { type InstancesEditorSettings } from './InstancesEditorSettings';
const styles = {
canvasArea: { flex: 1, position: 'absolute', overflow: 'hidden' },
@@ -42,8 +43,10 @@ export type InstancesEditorPropsWithoutSizeAndScroll = {|
project: gdProject,
layout: gdLayout,
initialInstances: gdInitialInstancesContainer,
options: Object,
onChangeOptions: (uiSettings: Object) => void,
instancesEditorSettings: InstancesEditorSettings,
onChangeInstancesEditorSettings: (
instancesEditorSettings: InstancesEditorSettings
) => void,
instancesSelection: InstancesSelection,
onDeleteSelection: () => void,
onInstancesAdded: (instances: Array<gdInitialInstance>) => void,
@@ -229,13 +232,13 @@ export default class InstancesEditor extends Component<Props> {
initialViewY: project ? project.getGameResolutionHeight() / 2 : 0,
width: this.props.width,
height: this.props.height,
options: this.props.options,
instancesEditorSettings: this.props.instancesEditorSettings,
});
this.pixiContainer.addChild(this.viewPosition.getPixiContainer());
this.grid = new Grid({
viewPosition: this.viewPosition,
options: this.props.options,
instancesEditorSettings: this.props.instancesEditorSettings,
});
this.pixiContainer.addChild(this.grid.getPixiObject());
@@ -265,7 +268,7 @@ export default class InstancesEditor extends Component<Props> {
this._instancesAdder = new InstancesAdder({
instances: this.props.initialInstances,
options: this.props.options,
instancesEditorSettings: this.props.instancesEditorSettings,
});
this._mountEditorComponents(this.props);
@@ -348,14 +351,14 @@ export default class InstancesEditor extends Component<Props> {
});
this.instancesResizer = new InstancesResizer({
instanceMeasurer: this.instancesRenderer.getInstanceMeasurer(),
options: this.props.options,
instancesEditorSettings: this.props.instancesEditorSettings,
});
this.instancesRotator = new InstancesRotator(
this.instancesRenderer.getInstanceMeasurer()
);
this.instancesMover = new InstancesMover({
instanceMeasurer: this.instancesRenderer.getInstanceMeasurer(),
options: this.props.options,
instancesEditorSettings: this.props.instancesEditorSettings,
});
this.windowBorder = new WindowBorder({
project: props.project,
@@ -365,7 +368,7 @@ export default class InstancesEditor extends Component<Props> {
this.windowMask = new WindowMask({
project: props.project,
viewPosition: this.viewPosition,
options: this.props.options,
instancesEditorSettings: this.props.instancesEditorSettings,
});
this.statusBar = new StatusBar({
width: this.props.width,
@@ -420,13 +423,25 @@ export default class InstancesEditor extends Component<Props> {
this._renderScene();
}
if (nextProps.options !== this.props.options) {
this.grid.setOptions(nextProps.options);
this.instancesMover.setOptions(nextProps.options);
this.instancesResizer.setOptions(nextProps.options);
this.windowMask.setOptions(nextProps.options);
this.viewPosition.setOptions(nextProps.options);
this._instancesAdder.setOptions(nextProps.options);
if (
nextProps.instancesEditorSettings !== this.props.instancesEditorSettings
) {
this.grid.setInstancesEditorSettings(nextProps.instancesEditorSettings);
this.instancesMover.setInstancesEditorSettings(
nextProps.instancesEditorSettings
);
this.instancesResizer.setInstancesEditorSettings(
nextProps.instancesEditorSettings
);
this.windowMask.setInstancesEditorSettings(
nextProps.instancesEditorSettings
);
this.viewPosition.setInstancesEditorSettings(
nextProps.instancesEditorSettings
);
this._instancesAdder.setInstancesEditorSettings(
nextProps.instancesEditorSettings
);
}
if (nextProps.screenType !== this.props.screenType) {
@@ -484,11 +499,12 @@ export default class InstancesEditor extends Component<Props> {
}
getZoomFactor = () => {
return this.props.options.zoomFactor;
return this.props.instancesEditorSettings.zoomFactor;
};
setZoomFactor = (zoomFactor: number) => {
this.props.onChangeOptions({
this.props.onChangeInstancesEditorSettings({
...this.props.instancesEditorSettings,
zoomFactor: Math.max(Math.min(zoomFactor, 10), 0.01),
});
};
@@ -16,6 +16,7 @@ import {
import LayoutChooserDialog from './LayoutChooserDialog';
import { Line } from '../../UI/Grid';
import Text from '../../UI/Text';
import { prepareInstancesEditorSettings } from '../../InstancesEditor/InstancesEditorSettings';
const styles = {
container: {
@@ -132,8 +133,8 @@ export class ExternalLayoutEditorContainer extends React.Component<
if (editor && layout) {
unserializeFromJSObject(
layout.getAssociatedSettings(),
editor.getUiSettings()
layout.getAssociatedEditorSettings(),
editor.getInstancesEditorSettings()
);
}
};
@@ -162,9 +163,13 @@ export class ExternalLayoutEditorContainer extends React.Component<
project={project}
layout={layout}
initialInstances={externalLayout.getInitialInstances()}
initialUiSettings={serializeToJSObject(
externalLayout.getAssociatedSettings()
)}
getInitialInstancesEditorSettings={() =>
prepareInstancesEditorSettings(
serializeToJSObject(
externalLayout.getAssociatedEditorSettings()
)
)
}
onOpenMoreSettings={this.openLayoutChooser}
isActive={isActive}
/>
@@ -1,5 +1,6 @@
// @flow
import * as React from 'react';
import { prepareInstancesEditorSettings } from '../../InstancesEditor/InstancesEditorSettings';
import SceneEditor from '../../SceneEditor';
import {
serializeToJSObject,
@@ -69,8 +70,8 @@ export class SceneEditorContainer extends React.Component<RenderEditorContainerP
if (editor && layout) {
unserializeFromJSObject(
layout.getAssociatedSettings(),
editor.getUiSettings()
layout.getAssociatedEditorSettings(),
editor.getInstancesEditorSettings()
);
}
};
@@ -94,7 +95,11 @@ export class SceneEditorContainer extends React.Component<RenderEditorContainerP
project={project}
layout={layout}
initialInstances={layout.getInitialInstances()}
initialUiSettings={serializeToJSObject(layout.getAssociatedSettings())}
getInitialInstancesEditorSettings={() =>
prepareInstancesEditorSettings(
serializeToJSObject(layout.getAssociatedEditorSettings())
)
}
isActive={isActive}
hotReloadPreviewButtonProps={this.props.hotReloadPreviewButtonProps}
/>
+142 -110
View File
@@ -1,123 +1,155 @@
// @flow
import { Trans } from '@lingui/macro';
import React, { Component } from 'react';
import * as React from 'react';
import FlatButton from '../UI/FlatButton';
import TextField from '../UI/TextField';
import Checkbox from '../UI/Checkbox';
import { ColumnStackLayout, ResponsiveLineStackLayout } from '../UI/Layout';
import Dialog from '../UI/Dialog';
import ColorField from '../UI/ColorField';
import {
type InstancesEditorSettings,
cloneInstancesEditorSettings,
} from '../InstancesEditor/InstancesEditorSettings';
import { hexNumberToRGBColor, rgbToHexNumber } from '../Utils/ColorTransformer';
export default class SetupGridDialog extends Component {
constructor(props) {
super(props);
this.state = {
...props.gridOptions,
};
}
type Props = {|
instancesEditorSettings: InstancesEditorSettings,
onChangeInstancesEditorSettings: InstancesEditorSettings => void,
onApply: () => void,
onCancel: () => void,
|};
onApply = () => {
this.props.onApply({
gridWidth: this.state.gridWidth,
gridHeight: this.state.gridHeight,
gridOffsetX: this.state.gridOffsetX,
gridOffsetY: this.state.gridOffsetY,
gridColor: this.state.gridColor,
gridType: this.state.gridType,
/** Below this value, rendering the grid is too costly (risk of infinite loop/memory saturation). */
const GRID_MIN_VALUE = 0.01;
export default function SetupGridDialog(props: Props) {
const [previousOptions] = React.useState(() =>
cloneInstancesEditorSettings(props.instancesEditorSettings)
);
const onCancel = () => {
props.onChangeInstancesEditorSettings({
...props.instancesEditorSettings,
gridWidth: previousOptions.gridWidth,
gridHeight: previousOptions.gridHeight,
gridOffsetX: previousOptions.gridOffsetX,
gridOffsetY: previousOptions.gridOffsetY,
gridColor: previousOptions.gridColor,
gridType: previousOptions.gridType,
});
props.onCancel();
};
render() {
const actions = [
<FlatButton
key="cancel"
label={<Trans>Cancel</Trans>}
primary={false}
onClick={this.props.onCancel}
/>,
<FlatButton
key="apply"
label={<Trans>Apply</Trans>}
primary={true}
keyboardFocused={true}
onClick={this.onApply}
/>,
];
return (
<Dialog
onApply={this.onApply}
title={<Trans>Edit Grid Options</Trans>}
actions={actions}
cannotBeDismissed={true}
open={this.props.open}
onRequestClose={this.props.onCancel}
maxWidth="sm"
noMargin
>
<ColumnStackLayout>
<ResponsiveLineStackLayout noMargin expand>
<ColorField
floatingLabelText={<Trans>Line color</Trans>}
fullWidth
color={this.state.gridColor}
onChangeComplete={color => {
this.setState({ gridColor: color.rgb });
}}
/>
</ResponsiveLineStackLayout>
<ResponsiveLineStackLayout noMargin expand>
<TextField
floatingLabelText={<Trans>Cell width (in pixels)</Trans>}
fullWidth
type="number"
value={this.state.gridWidth}
onChange={(e, value) =>
this.setState({ gridWidth: parseFloat(value) })
}
/>
<TextField
floatingLabelText={<Trans>Cell height (in pixels)</Trans>}
fullWidth
type="number"
value={this.state.gridHeight}
onChange={(e, value) =>
this.setState({ gridHeight: parseFloat(value) })
}
/>
</ResponsiveLineStackLayout>
<ResponsiveLineStackLayout noMargin expand>
<TextField
floatingLabelText={<Trans>X offset (in pixels)</Trans>}
fullWidth
type="number"
value={this.state.gridOffsetX}
onChange={(e, value) =>
this.setState({ gridOffsetX: parseFloat(value) })
}
/>
<TextField
floatingLabelText={<Trans>Y offset (in pixels)</Trans>}
fullWidth
type="number"
value={this.state.gridOffsetY}
onChange={(e, value) =>
this.setState({ gridOffsetY: parseFloat(value) })
}
/>
</ResponsiveLineStackLayout>
<ResponsiveLineStackLayout noMargin expand>
<Checkbox
checked={this.state.gridType === 'isometric'}
label={<Trans>Isometric</Trans>}
onCheck={(e, check) =>
this.setState({
gridType: check ? 'isometric' : 'rectangular',
})
}
/>
</ResponsiveLineStackLayout>
</ColumnStackLayout>
</Dialog>
);
}
return (
<Dialog
onApply={props.onApply}
title={<Trans>Edit Grid Options</Trans>}
actions={[
<FlatButton
key="cancel"
label={<Trans>Cancel</Trans>}
primary={false}
onClick={onCancel}
/>,
<FlatButton
key="apply"
label={<Trans>Apply</Trans>}
primary={true}
keyboardFocused={true}
onClick={props.onApply}
/>,
]}
cannotBeDismissed={true}
open
onRequestClose={onCancel}
maxWidth="sm"
noMargin
>
<ColumnStackLayout>
<ResponsiveLineStackLayout noMargin expand>
<ColorField
floatingLabelText={<Trans>Line color</Trans>}
fullWidth
color={hexNumberToRGBColor(props.instancesEditorSettings.gridColor)}
disableAlpha
onChangeComplete={color => {
props.onChangeInstancesEditorSettings({
...props.instancesEditorSettings,
gridColor: rgbToHexNumber(
color.rgb.r,
color.rgb.g,
color.rgb.b
),
});
}}
/>
</ResponsiveLineStackLayout>
<ResponsiveLineStackLayout noMargin expand>
<TextField
floatingLabelText={<Trans>Cell width (in pixels)</Trans>}
fullWidth
type="number"
value={props.instancesEditorSettings.gridWidth}
onChange={(e, value) =>
props.onChangeInstancesEditorSettings({
...props.instancesEditorSettings,
gridWidth: Math.max(parseFloat(value), GRID_MIN_VALUE),
})
}
/>
<TextField
floatingLabelText={<Trans>Cell height (in pixels)</Trans>}
fullWidth
type="number"
value={props.instancesEditorSettings.gridHeight}
onChange={(e, value) =>
props.onChangeInstancesEditorSettings({
...props.instancesEditorSettings,
gridHeight: Math.max(parseFloat(value), GRID_MIN_VALUE),
})
}
/>
</ResponsiveLineStackLayout>
<ResponsiveLineStackLayout noMargin expand>
<TextField
floatingLabelText={<Trans>X offset (in pixels)</Trans>}
fullWidth
type="number"
value={props.instancesEditorSettings.gridOffsetX}
onChange={(e, value) =>
props.onChangeInstancesEditorSettings({
...props.instancesEditorSettings,
gridOffsetX: parseFloat(value),
})
}
/>
<TextField
floatingLabelText={<Trans>Y offset (in pixels)</Trans>}
fullWidth
type="number"
value={props.instancesEditorSettings.gridOffsetY}
onChange={(e, value) =>
props.onChangeInstancesEditorSettings({
...props.instancesEditorSettings,
gridOffsetY: parseFloat(value),
})
}
/>
</ResponsiveLineStackLayout>
<ResponsiveLineStackLayout noMargin expand>
<Checkbox
checked={props.instancesEditorSettings.gridType === 'isometric'}
label={<Trans>Isometric</Trans>}
onCheck={(e, check) =>
props.onChangeInstancesEditorSettings({
...props.instancesEditorSettings,
gridType: check ? 'isometric' : 'rectangular',
})
}
/>
</ResponsiveLineStackLayout>
</ColumnStackLayout>
</Dialog>
);
}
+26 -27
View File
@@ -36,6 +36,7 @@ import { showWarningBox } from '../UI/Messages/MessageBox';
import { shortenString } from '../Utils/StringHelpers';
import getObjectByName from '../Utils/GetObjectByName';
import UseSceneEditorCommands from './UseSceneEditorCommands';
import { type InstancesEditorSettings } from '../InstancesEditor/InstancesEditorSettings';
import {
type ResourceSource,
@@ -107,7 +108,7 @@ const initialMosaicEditorNodesSmallWindow = {
type Props = {|
initialInstances: gdInitialInstancesContainer,
initialUiSettings: Object,
getInitialInstancesEditorSettings: () => InstancesEditorSettings,
layout: gdLayout,
onEditObject?: ?(object: gdObject) => void,
onOpenMoreSettings?: ?() => void,
@@ -140,7 +141,7 @@ type State = {|
editedGroup: ?gdObjectGroup,
uiSettings: Object,
instancesEditorSettings: Object,
history: HistoryState,
showObjectsListInfoBar: boolean,
@@ -190,7 +191,7 @@ export default class SceneEditor extends React.Component<Props, State> {
newObjectInstanceSceneCoordinates: null,
editedGroup: null,
uiSettings: props.initialUiSettings,
instancesEditorSettings: props.getInitialInstancesEditorSettings(),
history: getHistoryInitialState(props.initialInstances, {
historyMaxSize: 50,
}),
@@ -218,8 +219,8 @@ export default class SceneEditor extends React.Component<Props, State> {
this.props.unsavedChanges.triggerUnsavedChanges();
}
getUiSettings() {
return this.state.uiSettings;
getInstancesEditorSettings() {
return this.state.instancesEditorSettings;
}
updateToolbar() {
@@ -234,8 +235,10 @@ export default class SceneEditor extends React.Component<Props, State> {
toggleLayersList={this.toggleLayersList}
toggleWindowMask={this.toggleWindowMask}
toggleGrid={this.toggleGrid}
isGridShown={() => !!this.state.uiSettings.grid}
isWindowMaskShown={() => !!this.state.uiSettings.windowMask}
isGridShown={() => !!this.state.instancesEditorSettings.grid}
isWindowMaskShown={() =>
!!this.state.instancesEditorSettings.windowMask
}
openSetupGrid={this.openSetupGrid}
setZoomFactor={this.setZoomFactor}
centerView={this.centerView}
@@ -306,19 +309,19 @@ export default class SceneEditor extends React.Component<Props, State> {
toggleWindowMask = () => {
this.setState({
uiSettings: {
...this.state.uiSettings,
windowMask: !this.state.uiSettings.windowMask,
instancesEditorSettings: {
...this.state.instancesEditorSettings,
windowMask: !this.state.instancesEditorSettings.windowMask,
},
});
};
toggleGrid = () => {
this.setState({
uiSettings: {
...this.state.uiSettings,
grid: !this.state.uiSettings.grid,
snap: !this.state.uiSettings.grid,
instancesEditorSettings: {
...this.state.instancesEditorSettings,
grid: !this.state.instancesEditorSettings.grid,
snap: !this.state.instancesEditorSettings.grid,
},
});
};
@@ -389,12 +392,11 @@ export default class SceneEditor extends React.Component<Props, State> {
this.setState({ editedGroup: group });
};
setUiSettings = (uiSettings: Object) => {
setInstancesEditorSettings = (
instancesEditorSettings: InstancesEditorSettings
) => {
this.setState({
uiSettings: {
...this.state.uiSettings,
...uiSettings,
},
instancesEditorSettings,
});
};
@@ -1033,8 +1035,8 @@ export default class SceneEditor extends React.Component<Props, State> {
project={project}
layout={layout}
initialInstances={initialInstances}
options={this.state.uiSettings}
onChangeOptions={this.setUiSettings}
instancesEditorSettings={this.state.instancesEditorSettings}
onChangeInstancesEditorSettings={this.setInstancesEditorSettings}
instancesSelection={this.instancesSelection}
onDeleteSelection={this.deleteSelection}
onInstancesAdded={this._onInstancesAdded}
@@ -1268,13 +1270,10 @@ export default class SceneEditor extends React.Component<Props, State> {
/>
{this.state.setupGridOpen && (
<SetupGridDialog
open
gridOptions={this.state.uiSettings}
instancesEditorSettings={this.state.instancesEditorSettings}
onChangeInstancesEditorSettings={this.setInstancesEditorSettings}
onCancel={() => this.openSetupGrid(false)}
onApply={gridOptions => {
this.setUiSettings(gridOptions);
this.openSetupGrid(false);
}}
onApply={() => this.openSetupGrid(false)}
/>
)}
{!!this.state.variablesEditedInstance && (