duality icon indicating copy to clipboard operation
duality copied to clipboard

Introduce a Way to Selectively Keep Changes When Exiting Sandbox Mode

Open ChristianGreiner opened this issue 9 years ago • 7 comments

It would be helpful if you could save modified values of an component when the the game is in the sandbox mode.

The problem is that the changes don't get saved when you exit the sandbox mode.

My suggestion:

  • A new entry in the menustrip called e.g. "Save changes". It's visible when the sandbox mode is active.

dualityeditor_2016-08-14_13-19-41

ChristianGreiner avatar Aug 14 '16 11:08 ChristianGreiner

Although the details of this still need to be fleshed out, the overall idea of allowing to keep a selected subset of changes when exiting sandbox mode definitely isn't too bad. Open for discussion and concept work!

ilexp avatar Aug 14 '16 19:08 ilexp

Hey there. Have there been any developments on this since? Happy to assist with implementing this feature :+1:

heraldofgargos avatar Jul 07 '19 12:07 heraldofgargos

Hey @alexfonseka. There haven't been any developments since, but I'm pretty sure the feature would still be very much appreciated 🙂 Let's first discuss how we could approach this issue with regard to implementations, behavior and features.

Potential Use Cases?

Saving...

  • Single property or multiple select property changes to a Component
  • All changes to a Component
  • All changes to a GameObject
  • Newly created GameObjects or Components
  • Deletion of a previously existing GameObject or Component
  • Changes to Scene properties, such as gravity
  • Potentially crazy, but maybe not: All of the above to multiple scenes that may all have been active during play mode and been switched between in the mean time. Example would be changes to a level even if the user started play mode in the level select screen.

General Approaches

Component "Save changes" menu

See original posting and screenshot.

  • Limited to a single use case, somewhat clunky
  • Probably still the most straightforward to implement of the potential solutions

Capturing the Undo / Redo stack

Undo / Redo can already express all the changes that a user can do in the editor and will continue to do so by design. Capturing the stack and applying the operations after exiting play mode could be an "easy" way to do the right thing. When exiting sandbox mode, or changing scenes while in sandbox mode, a pop-up dialog could list all captured changes and let the user tick which ones to keep.

  • Can probably work for most of the above use cases.
  • Does not work well with repeated changes to the same properties, or operations that depend on each other.
  • Right now, Undo / Redo is inactive during play mode, because constant updates potentially kill actions that depend on each others states. Might revisit this decision though.
  • Undo / Redo uses direct object references to operate on, so it can't work on the reloaded scene after the active scene of the play mode has been disposed.
  • It's not great for cross-scene operations either, for the same reasons.

Keeping a list of changed properties

There is a global editor event for every property change made by the user, including all Components and GameObjects. It should be possible to hook into that and build a list of all changes to re-apply later on. When exiting sandbox mode, or changing scenes while in sandbox mode, a pop-up dialog could list all captured changes and let the user tick which ones to keep.

  • Can probably work for most of the above use cases.
  • Can be made to work across scenes and scene disposal, as change storage could work with GameObject ID + Component type, but would require some additional logic to resolve scene-internal object references.
  • Cannot deal with changes that are not exposed as object properties (but most relevant changes should be)

Thoughts?

ilexp avatar Jul 10 '19 18:07 ilexp

@ilexp I vouch for approach 3 - Keeping a list of changed properties. It's probably the least straightforward of them all to implement but I think it is the best option as it covers pretty much all the user scenarios.

Here is a mockup I have designed for a potential popup UI that will appear after exiting sandbox mode with changes. https://wireframe.cc/QnPhxO We could use icons associated with each field to indicate the type of change (e.g. property changed, component removed/added etc.).

Any potential holes with the design?

heraldofgargos avatar Jul 11 '19 05:07 heraldofgargos

Approach 3 would be my favorite as well - sounds like a good tradeoff between implementation complexity and gain.

Here is a mockup I have designed for a potential popup UI that will appear after exiting sandbox mode with changes. https://wireframe.cc/QnPhxO

Looks good 👍 Some thoughts:

  • The terminology I'd propose for those changes would be "apply", as "save" is associated with kind of a different operation. The two buttons in the lower right could then be "Apply" and "Cancel".
  • I'd remove the "Select All" button and instead make any changes to the tree view apply recursively, with all changes being selected by default. All that matters are selection states of the property nodes, with parent nodes only reflecting child states as "all / checked", "none / unchecked" or "some / indeterminate"
  • For the tree view, we should use a TreeViewAdv instance, which is a lot more versatile than the regular WinForms tree view. It can also combine trees with multi-column display and sorting, which could be used at some later point in time to improve overview in cases with lots of changes. Maybe not in the first iteration though.

We could use icons associated with each field to indicate the type of change (e.g. property changed, component removed/added etc.).

With a TreeViewAdv, we could actually use two icons - one for the object type (Scene, GameObject, Component type, retrieved via reflection), and one for the item type (Add, Remove, Change). Not sure if that's too much visual input, but it would be an option.

That said, I'm not sure we can easily deal with additions and removals in the property change approach, since there is no global event for object creation and deletion. It's possible to gather them via Undo / Redo listener for specific events, but it will likely be a special case.

Overall, since the UI part is probably the easier half of the work, my suggestion would be to start with the change gathering and applying first. For testing purposes, a default behavior of applying all gathered changes should do the trick, and as soon as that works, we know for sure that we've only got the UI part left to do.

ilexp avatar Jul 11 '19 18:07 ilexp

Recursively selecting/deselecting would certainly be the expected behavior. I've updated the mockup to reflect your suggestions. Using two icons (for object type and change) would be pretty good. It's what I had in mind anyway.

On implementing the change tracking - which areas of the source do I need to look at?

heraldofgargos avatar Jul 12 '19 03:07 heraldofgargos

Looks good 👍

On implementing the change tracking - which areas of the source do I need to look at?

DualityEditorApp.ObjectPropertyChanged is the global event you're probably going to use for detecting user-made changes, and the Sandbox class is where the management code for tracking changes and spawning the UI is probably going to live. The UI itself will of course be a new class, usually goes to the Forms folder.

Most of the change storage, management and applying code itself should probably be in its own class, something like a SceneDiff that has API for adding, removing, querying and applying changes. The class itself should be passive and not subscribe to any events, or editor infrastructure in general - all of the integration code could live in Sandbox, which would then use one or more SceneDiff objects. Dependency-wise, I'd almost see it in the core, but since it's obviously editor functionality, Utility might be a good place to put it. I'd imagine this class to also be very testable, so we can add unit tests for it here.

ilexp avatar Jul 13 '19 10:07 ilexp