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

Implement legacy combo splash #17616

Draft
wants to merge 19 commits into
base: master
Choose a base branch
from
Draft

Conversation

Feodor0090
Copy link
Contributor

@Feodor0090 Feodor0090 commented Apr 2, 2022

This is a MVP implementation of combo splashes from osu!stable. Supports multiple (comboburst-N.png) sprites.

Demo (BMS's skin, default skin, custom legacy skin):

2022-04-02.20-30-42.mp4

Closes #4629

@bdach
Copy link
Collaborator

bdach commented Apr 2, 2022

Aside from the above, there are unresolved code inspections (please run inspectcode locally to check) and this component should come with a test scene to be able to preview it without launching the game.

The component is also missing several features and quirks from stable (among others: ruleset-specific burst sprites and burst combo thresholds, being able to toggle on/off the order randomisation, being able to display the burst from both sides of the screen). But I suppose this was signposted as an MVP, just not sure how viable it is given all of the aforementioned omissions.

Also the Z-order is weird - as is the burst can display on top of the combo counter and other HUD elements which seems undesirable.

@Feodor0090
Copy link
Contributor Author

ruleset-specific

Where is the correct place to place these 2 settings (threshold check and sprite name)? I think, inside Ruleset?

being able to display the burst from both sides of the screen

To have the burst from both sides player is supposed to add a second component, flip it and anchor to the opposite side, but in this case both bursts will appear every time. Stable shows the splash from the random side each time. I'm not sure how to implement this. Something like "share an bindable between all ComboSplashes that will somehow block ValueChangedEvent for everything except the first ComboSplash; it will choose random ComboSplash from available and trigger animation on it" may work, but feels weird.

Z-order

The latest added component to the skin is always on top. If this to be fixed locally by rearranging skin components somehow, it will become a problem again when sprite placing will be implemented. Maybe, it's better to handle this on skin editor level by adding "bring to back/front" options?

@peppy
Copy link
Member

peppy commented Apr 3, 2022

Where is the correct place to place these 2 settings (threshold check and sprite name)? I think, inside Ruleset?

You would make a specific return of the component in each ruleset's LegacyTransformer. And potentially falback to a default at LegacySkin for rulesets that don't have support.

To have the burst from both sides player is supposed to add a second component, flip it and anchor to the opposite side, but in this case both bursts will appear every time. Stable shows the splash from the random side each time. I'm not sure how to implement this. Something like "share an bindable between all ComboSplashes that will somehow block ValueChangedEvent for everything except the first ComboSplash; it will choose random ComboSplash from available and trigger animation on it" may work, but feels weird.

You'd make the component handle both sides, rather than having two separate components.

The latest added component to the skin is always on top. If this to be fixed locally by rearranging skin components somehow, it will become a problem again when sprite placing will be implemented. Maybe, it's better to handle this on skin editor level by adding "bring to back/front" options?

This is out of scope. Handle the default case, not the skin editor case.

@pull-request-size pull-request-size bot added size/L and removed size/M labels Apr 3, 2022
@Feodor0090
Copy link
Contributor Author

I'm still not sure how to properly override sprites. Does GetDrawableComponent in legacy transformer fire before component's BDL?

@peppy
Copy link
Member

peppy commented Apr 4, 2022

I'm still not sure how to properly override sprites. Does GetDrawableComponent in legacy transformer fire before component's BDL?

If you don't want to derive the LegacyComboSplash component, you can nest a skin component inside your component and make an OsuSkinComponents lookup for it. Then you can implement the logic in each ruleset's transformer mapping that lookup to the correct sprite name. Something like this:

diff --git a/osu.Game.Rulesets.Osu/OsuSkinComponents.cs b/osu.Game.Rulesets.Osu/OsuSkinComponents.cs
index 71657ed532..c5f4e5d351 100644
--- a/osu.Game.Rulesets.Osu/OsuSkinComponents.cs
+++ b/osu.Game.Rulesets.Osu/OsuSkinComponents.cs
@@ -20,5 +20,6 @@ public enum OsuSkinComponents
         SliderBody,
         SpinnerBody,
         ApproachCircle,
+        ComboSplash
     }
 }
diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs
index 900ad6f6d3..dbf2480021 100644
--- a/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs
+++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs
@@ -32,8 +32,8 @@ public override Drawable GetDrawableComponent(ISkinComponent component)
             {
                 switch (osuComponent.Component)
                 {
-                    case OsuSkinComponents.FollowPoint:
-                        return this.GetAnimation(component.LookupName, true, true, true, startAtCurrentTime: false);
+                    case OsuSkinComponents.ComboSplash:
+                        return this.GetAnimation("osu-combo-splash", false, false);
 
                     case OsuSkinComponents.SliderFollowCircle:
                         var followCircle = this.GetAnimation("sliderfollowcircle", true, true, true);

Let me know if this doesn't make sense (I haven't tested so I may be missing something).

@Feodor0090
Copy link
Contributor Author

Feodor0090 commented Apr 5, 2022

This didn't allow to abstract from rulesets due to deriving from gameplay skin elements, if i understood correctly.
I created local ISkinComponent subclass, and used it to get a container for sprites with specific names via GetDrawableComponent. Not sure that i done everything properly.
Also, seems that only pippi's sprite is presented in game resources. Sprites for catch and mania are missed.

Comment on lines +21 to +22
[SettingSource("Side, where bursts will appear")]
public Bindable<Side> BurstsSide { get; } = new Bindable<Side>(Side.Random);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Not sure about making this the new sort of setting rather than hooking it up to the old setting flow that reads from skin.ini. This is kind of uncharted territory still.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Afaik there was no way to change this in stable (for osu! and osu!taiko) and there is no setting for this in skin.ini. I want to implement this here to make the component more flexible, so decided to use "modern" setting.

A mania-specific option for this exists, but it doesn't suit the behaviour implemented here (anchors are screen's sides, not playfield's ones):
image
Should i use it instead of "modern" setting anyway?

[SettingSource("Side, where bursts will appear")]
public Bindable<Side> BurstsSide { get; } = new Bindable<Side>(Side.Random);

public Bindable<int> Current { get; } = new BindableInt { MinValue = 0 };
Copy link
Collaborator

Choose a reason for hiding this comment

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

This bindable shouldn't be public (or if you really want it to be, it should be externally immutable by exposing as IBindable<int>).


private void OnNewCombo(int combo)
{
if (BurstCondition(combo))
Copy link
Collaborator

Choose a reason for hiding this comment

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

Would invert and early-return to reduce nesting.


namespace osu.Game.Screens.Play.HUD
{
public class LegacyComboSplash : Container<Container<Sprite>>, ISkinnableDrawable
Copy link
Collaborator

Choose a reason for hiding this comment

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

This generic type (Container<Container<Sprite>>) is a bit much. Is this just for the test? If so, I'd recommend switching over to .ChildrenOfType<>() there.

Comment on lines 153 to 154
Both,
Random
Copy link
Collaborator

Choose a reason for hiding this comment

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

In stable both is random, for what it's worth. Not sure a new option needs to be invented here.

Comment on lines +80 to +94
case SkinnableTargetComponent targetComponent:
if (targetComponent.Target == SkinnableTarget.MainHUDComponents)
{
var components = base.GetDrawableComponent(component) as SkinnableTargetComponentsContainer;
if (components == null) return null;

foreach (var comboSplash in components.OfType<LegacyComboSplash>())
{
comboSplash.BurstCondition = combo => combo > 0 && combo % 100 == 0;
}

return components;
}

break;
Copy link
Member

@peppy peppy Apr 21, 2022

Choose a reason for hiding this comment

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

Rather than doing this, it will be cleaner if you make a ManiaLegacyComboSplashSide and return it below, and then include the conditional logic within the subclass (you can likely make it a virutal / override pair if you do this).

@peppy peppy self-requested a review September 9, 2022 09:12
@peppy
Copy link
Member

peppy commented Sep 9, 2022

I've brought this up-to-date, but still needs some work to get it in a good state.

@peppy peppy marked this pull request as draft June 16, 2023 06:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add back comboburst
4 participants