diff --git a/Core/GDCore/IDE/Dialogs/LayoutEditorCanvas/EditorSettings.cpp b/Core/GDCore/IDE/Dialogs/LayoutEditorCanvas/EditorSettings.cpp new file mode 100644 index 0000000000..eecc4697eb --- /dev/null +++ b/Core/GDCore/IDE/Dialogs/LayoutEditorCanvas/EditorSettings.cpp @@ -0,0 +1,25 @@ +/* + * GDevelop Core + * Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). 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 diff --git a/Core/GDCore/IDE/Dialogs/LayoutEditorCanvas/EditorSettings.h b/Core/GDCore/IDE/Dialogs/LayoutEditorCanvas/EditorSettings.h new file mode 100644 index 0000000000..76268f06d7 --- /dev/null +++ b/Core/GDCore/IDE/Dialogs/LayoutEditorCanvas/EditorSettings.h @@ -0,0 +1,46 @@ +/* + * GDevelop Core + * Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). 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 diff --git a/Core/GDCore/IDE/Dialogs/LayoutEditorCanvas/LayoutEditorCanvasOptions.cpp b/Core/GDCore/IDE/Dialogs/LayoutEditorCanvas/LayoutEditorCanvasOptions.cpp deleted file mode 100644 index 4462452669..0000000000 --- a/Core/GDCore/IDE/Dialogs/LayoutEditorCanvas/LayoutEditorCanvasOptions.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - * GDevelop Core - * Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). 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 diff --git a/Core/GDCore/IDE/Dialogs/LayoutEditorCanvas/LayoutEditorCanvasOptions.h b/Core/GDCore/IDE/Dialogs/LayoutEditorCanvas/LayoutEditorCanvasOptions.h deleted file mode 100644 index 6b633b7320..0000000000 --- a/Core/GDCore/IDE/Dialogs/LayoutEditorCanvas/LayoutEditorCanvasOptions.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * GDevelop Core - * Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). 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 diff --git a/Core/GDCore/Project/ExternalLayout.cpp b/Core/GDCore/Project/ExternalLayout.cpp index d429db657e..99d82a427a 100644 --- a/Core/GDCore/Project/ExternalLayout.cpp +++ b/Core/GDCore/Project/ExternalLayout.cpp @@ -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 diff --git a/Core/GDCore/Project/ExternalLayout.h b/Core/GDCore/Project/ExternalLayout.h index 4112965136..b0e77e427c 100644 --- a/Core/GDCore/Project/ExternalLayout.h +++ b/Core/GDCore/Project/ExternalLayout.h @@ -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; }; diff --git a/Core/GDCore/Project/Layout.cpp b/Core/GDCore/Project/Layout.cpp index 28f12c67e7..e6ed7fc8e6 100644 --- a/Core/GDCore/Project/Layout.cpp +++ b/Core/GDCore/Project/Layout.cpp @@ -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; diff --git a/Core/GDCore/Project/Layout.h b/Core/GDCore/Project/Layout.h index e311949123..4e2c7571c8 100644 --- a/Core/GDCore/Project/Layout.h +++ b/Core/GDCore/Project/Layout.h @@ -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 diff --git a/GDevelop.js/Bindings/Bindings.idl b/GDevelop.js/Bindings/Bindings.idl index 90354a9b59..282613c80f 100644 --- a/GDevelop.js/Bindings/Bindings.idl +++ b/GDevelop.js/Bindings/Bindings.idl @@ -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); diff --git a/GDevelop.js/Bindings/Wrapper.cpp b/GDevelop.js/Bindings/Wrapper.cpp index c5ef027027..bd29bb5409 100644 --- a/GDevelop.js/Bindings/Wrapper.cpp +++ b/GDevelop.js/Bindings/Wrapper.cpp @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/GDevelop.js/__tests__/Core.js b/GDevelop.js/__tests__/Core.js index f7c00b9030..6f10291809 100644 --- a/GDevelop.js/__tests__/Core.js +++ b/GDevelop.js/__tests__/Core.js @@ -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); + }); + }); }); diff --git a/GDevelop.js/types/gdlayouteditorcanvasoptions.js b/GDevelop.js/types/gdeditorsettings.js similarity index 84% rename from GDevelop.js/types/gdlayouteditorcanvasoptions.js rename to GDevelop.js/types/gdeditorsettings.js index 9e7cf6cfb8..bca55d5235 100644 --- a/GDevelop.js/types/gdlayouteditorcanvasoptions.js +++ b/GDevelop.js/types/gdeditorsettings.js @@ -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; diff --git a/GDevelop.js/types/gdexternallayout.js b/GDevelop.js/types/gdexternallayout.js index 8c50fb0ae0..dde8d681a0 100644 --- a/GDevelop.js/types/gdexternallayout.js +++ b/GDevelop.js/types/gdexternallayout.js @@ -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; diff --git a/GDevelop.js/types/gdlayout.js b/GDevelop.js/types/gdlayout.js index bf499a0e67..ff2a800bf1 100644 --- a/GDevelop.js/types/gdlayout.js +++ b/GDevelop.js/types/gdlayout.js @@ -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; diff --git a/GDevelop.js/types/libgdevelop.js b/GDevelop.js/types/libgdevelop.js index 9d88d5d691..034f479a20 100644 --- a/GDevelop.js/types/libgdevelop.js +++ b/GDevelop.js/types/libgdevelop.js @@ -176,7 +176,7 @@ declare class libGDevelop { ResourcesRenamer: Class; ProjectResourcesCopier: Class; ResourcesInUseHelper: Class; - LayoutEditorCanvasOptions: Class; + EditorSettings: Class; Point: Class; VectorPoint: Class; Polygon2d: Class; diff --git a/newIDE/app/src/InstancesEditor/Grid.js b/newIDE/app/src/InstancesEditor/Grid.js index e7a3fe031b..137eb0b5bd 100644 --- a/newIDE/app/src/InstancesEditor/Grid.js +++ b/newIDE/app/src/InstancesEditor/Grid.js @@ -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); diff --git a/newIDE/app/src/InstancesEditor/InstancesAdder.js b/newIDE/app/src/InstancesEditor/InstancesAdder.js index d95b10173e..a89482ad1f 100644 --- a/newIDE/app/src/InstancesEditor/InstancesAdder.js +++ b/newIDE/app/src/InstancesEditor/InstancesAdder.js @@ -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; - _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 => { - const newPos = roundPositionsToGrid(pos, this._options); + const newPos = roundPositionsToGrid(pos, this._instancesEditorSettings); this._temporaryInstances.forEach(instance => { instance.setX(newPos[0]); instance.setY(newPos[1]); diff --git a/newIDE/app/src/InstancesEditor/InstancesEditorSettings.js b/newIDE/app/src/InstancesEditor/InstancesEditorSettings.js new file mode 100644 index 0000000000..fff9b233a4 --- /dev/null +++ b/newIDE/app/src/InstancesEditor/InstancesEditorSettings.js @@ -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 }; +}; diff --git a/newIDE/app/src/InstancesEditor/InstancesMover.js b/newIDE/app/src/InstancesEditor/InstancesMover.js index 28977318df..c8bf3439b4 100644 --- a/newIDE/app/src/InstancesEditor/InstancesMover.js +++ b/newIDE/app/src/InstancesEditor/InstancesMover.js @@ -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. diff --git a/newIDE/app/src/InstancesEditor/InstancesResizer.js b/newIDE/app/src/InstancesEditor/InstancesResizer.js index 20442520f5..0cad260eaa 100644 --- a/newIDE/app/src/InstancesEditor/InstancesResizer.js +++ b/newIDE/app/src/InstancesEditor/InstancesResizer.js @@ -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. diff --git a/newIDE/app/src/InstancesEditor/ViewPosition.js b/newIDE/app/src/InstancesEditor/ViewPosition.js index 6082a671e7..55be364cee 100644 --- a/newIDE/app/src/InstancesEditor/ViewPosition.js +++ b/newIDE/app/src/InstancesEditor/ViewPosition.js @@ -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; } } diff --git a/newIDE/app/src/InstancesEditor/WindowBorder.js b/newIDE/app/src/InstancesEditor/WindowBorder.js index e4c739a052..5af8fd6a4f 100644 --- a/newIDE/app/src/InstancesEditor/WindowBorder.js +++ b/newIDE/app/src/InstancesEditor/WindowBorder.js @@ -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, diff --git a/newIDE/app/src/InstancesEditor/WindowMask.js b/newIDE/app/src/InstancesEditor/WindowMask.js index 18daca44eb..8bd0436ac5 100644 --- a/newIDE/app/src/InstancesEditor/WindowMask.js +++ b/newIDE/app/src/InstancesEditor/WindowMask.js @@ -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; } diff --git a/newIDE/app/src/InstancesEditor/index.js b/newIDE/app/src/InstancesEditor/index.js index 7426189eab..6a38addd7c 100644 --- a/newIDE/app/src/InstancesEditor/index.js +++ b/newIDE/app/src/InstancesEditor/index.js @@ -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) => void, @@ -229,13 +232,13 @@ export default class InstancesEditor extends Component { 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 { 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 { }); 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 { 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 { 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 { } 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), }); }; diff --git a/newIDE/app/src/MainFrame/EditorContainers/ExternalLayoutEditorContainer.js b/newIDE/app/src/MainFrame/EditorContainers/ExternalLayoutEditorContainer.js index 006ed1753f..1915f57b40 100644 --- a/newIDE/app/src/MainFrame/EditorContainers/ExternalLayoutEditorContainer.js +++ b/newIDE/app/src/MainFrame/EditorContainers/ExternalLayoutEditorContainer.js @@ -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} /> diff --git a/newIDE/app/src/MainFrame/EditorContainers/SceneEditorContainer.js b/newIDE/app/src/MainFrame/EditorContainers/SceneEditorContainer.js index 7494bbc430..5778477c99 100644 --- a/newIDE/app/src/MainFrame/EditorContainers/SceneEditorContainer.js +++ b/newIDE/app/src/MainFrame/EditorContainers/SceneEditorContainer.js @@ -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 + prepareInstancesEditorSettings( + serializeToJSObject(layout.getAssociatedEditorSettings()) + ) + } isActive={isActive} hotReloadPreviewButtonProps={this.props.hotReloadPreviewButtonProps} /> diff --git a/newIDE/app/src/SceneEditor/SetupGridDialog.js b/newIDE/app/src/SceneEditor/SetupGridDialog.js index 3331c07017..484e43f40a 100644 --- a/newIDE/app/src/SceneEditor/SetupGridDialog.js +++ b/newIDE/app/src/SceneEditor/SetupGridDialog.js @@ -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 = [ - Cancel} - primary={false} - onClick={this.props.onCancel} - />, - Apply} - primary={true} - keyboardFocused={true} - onClick={this.onApply} - />, - ]; - - return ( - Edit Grid Options} - actions={actions} - cannotBeDismissed={true} - open={this.props.open} - onRequestClose={this.props.onCancel} - maxWidth="sm" - noMargin - > - - - Line color} - fullWidth - color={this.state.gridColor} - onChangeComplete={color => { - this.setState({ gridColor: color.rgb }); - }} - /> - - - Cell width (in pixels)} - fullWidth - type="number" - value={this.state.gridWidth} - onChange={(e, value) => - this.setState({ gridWidth: parseFloat(value) }) - } - /> - Cell height (in pixels)} - fullWidth - type="number" - value={this.state.gridHeight} - onChange={(e, value) => - this.setState({ gridHeight: parseFloat(value) }) - } - /> - - - X offset (in pixels)} - fullWidth - type="number" - value={this.state.gridOffsetX} - onChange={(e, value) => - this.setState({ gridOffsetX: parseFloat(value) }) - } - /> - Y offset (in pixels)} - fullWidth - type="number" - value={this.state.gridOffsetY} - onChange={(e, value) => - this.setState({ gridOffsetY: parseFloat(value) }) - } - /> - - - Isometric} - onCheck={(e, check) => - this.setState({ - gridType: check ? 'isometric' : 'rectangular', - }) - } - /> - - - - ); - } + return ( + Edit Grid Options} + actions={[ + Cancel} + primary={false} + onClick={onCancel} + />, + Apply} + primary={true} + keyboardFocused={true} + onClick={props.onApply} + />, + ]} + cannotBeDismissed={true} + open + onRequestClose={onCancel} + maxWidth="sm" + noMargin + > + + + Line color} + fullWidth + color={hexNumberToRGBColor(props.instancesEditorSettings.gridColor)} + disableAlpha + onChangeComplete={color => { + props.onChangeInstancesEditorSettings({ + ...props.instancesEditorSettings, + gridColor: rgbToHexNumber( + color.rgb.r, + color.rgb.g, + color.rgb.b + ), + }); + }} + /> + + + Cell width (in pixels)} + fullWidth + type="number" + value={props.instancesEditorSettings.gridWidth} + onChange={(e, value) => + props.onChangeInstancesEditorSettings({ + ...props.instancesEditorSettings, + gridWidth: Math.max(parseFloat(value), GRID_MIN_VALUE), + }) + } + /> + Cell height (in pixels)} + fullWidth + type="number" + value={props.instancesEditorSettings.gridHeight} + onChange={(e, value) => + props.onChangeInstancesEditorSettings({ + ...props.instancesEditorSettings, + gridHeight: Math.max(parseFloat(value), GRID_MIN_VALUE), + }) + } + /> + + + X offset (in pixels)} + fullWidth + type="number" + value={props.instancesEditorSettings.gridOffsetX} + onChange={(e, value) => + props.onChangeInstancesEditorSettings({ + ...props.instancesEditorSettings, + gridOffsetX: parseFloat(value), + }) + } + /> + Y offset (in pixels)} + fullWidth + type="number" + value={props.instancesEditorSettings.gridOffsetY} + onChange={(e, value) => + props.onChangeInstancesEditorSettings({ + ...props.instancesEditorSettings, + gridOffsetY: parseFloat(value), + }) + } + /> + + + Isometric} + onCheck={(e, check) => + props.onChangeInstancesEditorSettings({ + ...props.instancesEditorSettings, + gridType: check ? 'isometric' : 'rectangular', + }) + } + /> + + + + ); } diff --git a/newIDE/app/src/SceneEditor/index.js b/newIDE/app/src/SceneEditor/index.js index 7a084084fe..1706fc43b6 100644 --- a/newIDE/app/src/SceneEditor/index.js +++ b/newIDE/app/src/SceneEditor/index.js @@ -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 { 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 { 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 { 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 { 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 { 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 { 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 { /> {this.state.setupGridOpen && ( this.openSetupGrid(false)} - onApply={gridOptions => { - this.setUiSettings(gridOptions); - this.openSetupGrid(false); - }} + onApply={() => this.openSetupGrid(false)} /> )} {!!this.state.variablesEditedInstance && (