Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhanced brush mode #17

Open
wants to merge 75 commits into
base: master
Choose a base branch
from

Conversation

zacharied
Copy link
Contributor

@zacharied zacharied commented Oct 20, 2024

TODO

[x] Refactor selection area code
[x] Enable click selection with FilterSubmode
[x] Fix missing Brush button text
[x] Fix crash when clicking on LaneBlock in batch mode
[ ] Add menu bar buttons so users can discover keybinds
[ ] Allow dragging when starting drag on non-filter object (out of scope?)

Brush mode improvements

Brush mode has been changed. When in Brush Mode, an overlay is shown in the bottom left. It shows the input object.

OngekiFumenEditor_vEkEa1HRjO

By default, the input object is "Clipboard", which is the same as the old brush mode behavior.

Changing input object

The user can press keys to change the input object. See CommandDefinitions for the full list.

OngekiFumenEditor_xtONGUNjXN

Insert input object

Left Click inserts the input object. If Alt or Ctrl is held, modifiers are applied to some inputs. If Shift is held, the previous selection will be kept; otherwise the selection will be cleared.

OngekiFumenEditor_RF3MrJ9cxg

Deleting input object

If the input object is not "Clipboard", Right Click deletes instances of the input object.

OngekiFumenEditor_Hphen1ggba

Change selection

If Alt is held while clicking and dragging, normal box selection will be used. This is so that the user does not have to exit Brush Mode to change selection.

OngekiFumenEditor_9bxDUu186U

Questions

@MikiraSora, before I finish localizing and bugfixing, I want to make sure you like this.

  • Are you okay with implementing brush mode as a Behavior?
  • Any other keybinds I should add to brush mode?
  • I wanted to add a "preview" of the input object below the mouse cursor. What would be the best way to do that?

- I'm not sure how I feel about this. There's a lot of friction involving entering brush mode and leaving it to gain access to the left mouse button. This feels especially bad when we have nothing in the clipboard and left mouse button doesn't do anything at all.

- Solution: Brush Mode should contain a field that tracks a creation command. The user can press the keys we have set up now to change that field.

- Should probably turn Brush Mode into a behavior.

- For later consideration, we could have a "diret insertion" mode that replicates the behavior seen as of this commit.
@zacharied zacharied marked this pull request as draft October 20, 2024 18:42
@MikiraSora
Copy link
Collaborator

MikiraSora commented Oct 21, 2024

It shouldn't continue to be called BrushMode, because there are too many operations to memorize.
Maybe we can just combine all these functions, including BrushMode, into a new name, BatchMode.
Then the original mode could be called NormalMode, so that new users can quickly get started in this mode, and users who need more operations can use BatchMode.

Are you okay with implementing brush mode as a Behavior?

I haven't delved much into the full functionality of WPF, so this implementation requires me to understand it before I can draw conclusions

Any other keybinds I should add to brush mode?

None at the moment, but I would suggest that this needs to be compatible with the Keybinding feature, as users may need to modify the shortcuts to make it easier for them to use them.

I wanted to add a "preview" of the input object below the mouse cursor. What would be the best way to do that?

I do have an idea, is that the user's current pointer operation can be displayed near the pointer, for example, in your demonstration of the function #Deleting input object, when the user presses and holds the pointer and drags it, the words “Deletion of objects within the range” will be displayed near the pointer to indicate that
I'll try to make a prototype of this feature when I get around to it.

Anyway, it's not recommended to merge this PR yet, need to wait for me to finish the keybinding feature first, sorry, but it's coming soon!

[Key.D4] = new BrushModeInputWallRight(),
[Key.D5] = new BrushModeInputLaneColorful(),
[Key.T] = new BrushModeInputTap(),
[Key.D] = new BrushModeInputHold(),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The H key should be assigned here

@zacharied
Copy link
Contributor Author

I will rename "Brush Mode" to "Batch Mode" and add new keybindings called KBD_Batch_AddTap, KBD_Batch_AddHold, etc.

Also implement a "layer" system for keybindings.
Keybindings are allowed to conflict with each other if they are on different layers, unless one of them is on Global.
@zacharied
Copy link
Contributor Author

Batch Mode requires its own set of keybindings, separate from the normal ones. So I have started to make a "layer" system.

There are three layers, Global, Normal, and Batch. Keybindings in Normal are allowed to conflict with keybindings from Batch mode.

Global keybinds are always active.
Normal keybinds are detached when Batch mode is enabled.
Batch keybinds are attached when Batch mode is enabled.

For keybindings such as FastAddConnectableChild, I want to be accessible in Batch mode. So, I will make the Layers into a Flag, and each KeyBindingDefinition can have multiple layers.

The only object that takes two modifiers is Flick, and we don't care about the selection when adding flicks.
@zacharied
Copy link
Contributor Author

zacharied commented Oct 24, 2024

I used the feature a lot and made some changes.

InputObjects are now referred to as "Submodes". There are two types of submodes. They determine what is done when clicking.

  • InputObjectSubmode: Clicking creates new objects
  • FilterObjectSubmode: Clicking selects objects like in Normal Mode, but only certain types are selected

A new icon is displayed when in a FilterObjectSubmode.

OngekiFumenEditor_djIHN0ZZdH

The filters are:

  • FloatingObject: selects bells, bullets, & flicks
  • DockableObject: selects taps & holds
  • Lane: selects lanes & walls

Documentation

Default keybinds

✏️: InputSubmode
🔎: FilterSubmode

Key Action
Tilde ✏️WallLeft
1 ✏️LaneLeft
2 ✏️LaneCenter
3 ✏️LaneRight
4 ✏️WallRight
5 ✏️LaneColorful
6 🔎Lanes
E ✏️Bell
T ✏️ Tap
H ✏️Hold
F ✏️Flick
Z ✏️LaneBlock
V ✏️Clipboard
Y 🔎Dockable Objects
U 🔎Floating Objects

These tables describe the behavior when clicking with different modifiers in Batch Mode.

Left click operations

Modifier InputObject FilterObject
None Lane, hold, LaneBlock: Place object and select
Tap, flick, bell, bullet: Place object
Drag to select filtered object
Alt Normal mode selection Normal mode selection
Shift Lanes & holds: Place object (keep current selection)
Flick & Lane block: Place object (change direction)
Others: same as None
Drag to select filtered object (keep current selection)
Ctrl Taps, holds, & flicks: Place object (critical) Same as None
Ctrl+Alt Drag to select only input object Same as None

Right click operations

Modifier InputObject FilterObject
None Clipboard: Nothing
Others: Drag to delete input object
Drag to delete filtered object
Alt Drag to delete all objects Drag to delete all objects
Shift Same as None Same as None
Ctrl Same as None Same as None
Ctrl+Alt Same as None Same as None

TODO

  • Some right click behavior is buggy
  • Finish renaming classes BrushModeBatchMode
  • Test

@zacharied zacharied marked this pull request as ready for review October 24, 2024 23:21
@MikiraSora
Copy link
Collaborator

at fad1143 KeyboardAction_DeleteSelectingObjects()
Here I used a new implementation to fix the problem

QQ20241028-15741-HD.mp4

But I see that you're deleting objects elsewhere as well, so I'd suggest that you need to follow up on that as well

@zacharied
Copy link
Contributor Author

Thanks, I will follow your code for the other deletion functions

@zacharied
Copy link
Contributor Author

zacharied commented Oct 28, 2024

Could you merge fad1143 into this PR? So i don't have to duplicate your deletion code.

@MikiraSora
Copy link
Collaborator

Could you merge fad1143 into this PR? So i don't have to duplicate your deletion code.

how , I merged your current work and push to batch_mode in my repo

@zacharied
Copy link
Contributor Author

Oh, i can do it myself, sorry

@zacharied
Copy link
Contributor Author

Crash when clicking on LaneBlock in batch mode:

----------Exception Catcher----------
Program notice a (unhandled) exception from object: System.Windows.Threading.Dispatcher(System.Windows.Threading.Dispatcher)

Exception lv.0 : Unable to cast object of type 'OngekiFumenEditor.Base.OngekiObjects.LaneBlockArea' to type 'OngekiFumenEditor.Base.OngekiMovableObjectBase'.
Stack :    at OngekiFumenEditor.Modules.FumenVisualEditor.ViewModels.FumenVisualEditorViewModel.<>c__DisplayClass292_0.<GetConflictingObject>b__0(IDisplayableObject x)
   at System.Linq.Enumerable.TryGetFirst[TSource](IEnumerable`1 source, Func`2 predicate, Boolean& found)
   at OngekiFumenEditor.Modules.FumenVisualEditor.Behaviors.BatchMode.BatchModeBehavior.PerformBrush(BatchModeInputSubmode submode)
   at OngekiFumenEditor.Modules.FumenVisualEditor.Behaviors.BatchMode.BatchModeBehavior.MouseUp(MouseButtonEventArgs args)
   at Microsoft.Xaml.Behaviors.TriggerBase.InvokeActions(Object parameter) in D:\a\_work\1\s\src\Microsoft.Xaml.Behaviors\TriggerBase.cs:line 153
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
   at System.Windows.Input.InputManager.ProcessStagingArea()
   at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
   at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
----------------------------

@zacharied
Copy link
Contributor Author

zacharied commented Oct 29, 2024

I'm noticing this bug starting today, was it one of the recent commits?

Bottom green object is a TAP and top green object is a HOLD.

OngekiFumenEditor_XaJFbZp3ZQ.mp4

@MikiraSora
Copy link
Collaborator

I'm noticing this bug starting today, was it one of the recent commits?

Bottom green object is a TAP and top green object is a HOLD.

OngekiFumenEditor_XaJFbZp3ZQ.mp4

fixed and plz pull

@MikiraSora
Copy link
Collaborator

Crash when clicking on LaneBlock in batch mode:

----------Exception Catcher----------
Program notice a (unhandled) exception from object: System.Windows.Threading.Dispatcher(System.Windows.Threading.Dispatcher)

Exception lv.0 : Unable to cast object of type 'OngekiFumenEditor.Base.OngekiObjects.LaneBlockArea' to type 'OngekiFumenEditor.Base.OngekiMovableObjectBase'.
Stack :    at OngekiFumenEditor.Modules.FumenVisualEditor.ViewModels.FumenVisualEditorViewModel.<>c__DisplayClass292_0.<GetConflictingObject>b__0(IDisplayableObject x)
   at System.Linq.Enumerable.TryGetFirst[TSource](IEnumerable`1 source, Func`2 predicate, Boolean& found)
   at OngekiFumenEditor.Modules.FumenVisualEditor.Behaviors.BatchMode.BatchModeBehavior.PerformBrush(BatchModeInputSubmode submode)
   at OngekiFumenEditor.Modules.FumenVisualEditor.Behaviors.BatchMode.BatchModeBehavior.MouseUp(MouseButtonEventArgs args)
   at Microsoft.Xaml.Behaviors.TriggerBase.InvokeActions(Object parameter) in D:\a\_work\1\s\src\Microsoft.Xaml.Behaviors\TriggerBase.cs:line 153
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
   at System.Windows.Input.InputManager.ProcessStagingArea()
   at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
   at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
----------------------------

LaneBlockArea no X axis to move so it's actual not a OngekiMovableObjectBase
OngekiMovableObjectBase means its has X/Y axis to move.

@zacharied
Copy link
Contributor Author

LaneBlockArea no X axis to move so it's actual not a OngekiMovableObjectBase OngekiMovableObjectBase means its has X/Y axis to move.

Thank you, i should have mentioned i fixed it with db8b813

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants