skyfloogle / red-viper

A Virtual Boy emulator for the 3DS
764 stars 17 forks source link

Add backlight toggle #48

Closed vaguerant closed 3 months ago

vaguerant commented 3 months ago

Adds an on-screen toggle to disable the backlight on the bottom screen, to reduce battery consumption when the user doesn't need it. Also handles the user doing "unexpected" things like pressing Home while the touch screen is turned off or sleeping and waking the console.

The feature is disabled entirely on the original 2DS; that model actually has one single LCD panel on which both "screens" are shown; attempting to turn off the "bottom screen" just turns off the entire single screen, rendering this feature unusable.

If the touch screen is turned off, touching it again wakes it.

I tried to make the button fit with the rest of the app's aesthetic, not sure if it came out too abstract? It kind of looks like a floppy disk if you're not primed to see it as a 3DS. The top screen on the button will adjust its tint with the rest of the UI.

![image](https://github.com/skyfloogle/red-viper/assets/5259025/81e9ba6e-4fe9-4ae8-a915-d4170fdcae16)

I really just did this as a learning exercise, so if it's not desired or poorly written, just junk it. :+1:

EDIT: Pushed an additional commit that restores the backlight if the emulator errors out while it's turned off, build 2 below has that commit included.

Test build

  1. red-viper_backlight-pr.zip
  2. red-viper_backlight-pr_light-on-error.zip
profi200 commented 3 months ago

You forgot the old 2DS exists. If you toggle the bottom screen backlight you toggle the backlight on the entire LCD (o2DS has one big LCD).

vaguerant commented 3 months ago

It's not actually tested on a 2DS because I don't own one, but I definitely didn't forget 2DS. I'm on mobile so I can't easily point to the exact lines, but I'm setting up a bool old_2ds which the button is hidden behind. I also mentioned this problem exactly in the original PR text. :D

skyfloogle commented 3 months ago

This is cute, didn't even know this sort of thing was possible! I'm not sure if it makes UX sense to bind it to a touchscreen button though. I certainly think it makes sense to set the brightness level on the touch screen to minimum in-game (possibly with an option to leave it alone).

vaguerant commented 3 months ago

I'm not sure if it makes UX sense to bind it to a touchscreen button though.

The reason I did it this way is so that users still have easy access to the Switch, Fast-Forward and other virtual buttons without having to navigate back through the menus to get to them. e.g. If you boot up Red Alarm, you probably want the touch screen available so you can at least hit Switch, then you can turn the screen off after that.

Option 1

I certainly think it makes sense to set the brightness level on the touch screen to minimum in-game (possibly with an option to leave it alone).

This does give me an idea, which is for the backlight to automatically toggle off whenever you press a physical input, then back on if you touch the screen. i.e. I'm trying out this (these are two separate snippets):

        if (hidKeysDown() && ~KEY_TOUCH && tVBOpt.BACKLIGHT == 0 && !old_2ds) {
            backlightEnabled = toggleBacklight(false);
            return 0;
        }
    } else if (hidKeysUp() & KEY_TOUCH) {
        backlightEnabled = toggleBacklight(true);
    }

Along with a new button in video settings to toggle tVBOpt.BACKLIGHT.

![image](https://github.com/skyfloogle/red-viper/assets/5259025/ac580c1d-1b6b-42c1-b05f-0e2a849b5f00)

The button toggle in video settings currently uses "Backlight: On / Auto", with the current behavior ("On") as the default. On 2DS, the button is always set to "On". Unlike the in-game menu, I'm not sure how to hide the button entirely since it's managed through handle_buttons(), but that would probably be preferable to a non-functional button for 2DS users.

With this setup, all of the touch buttons are accessible immediately after booting a ROM, because you haven't touched any physical buttons yet. Users can hit e.g. "Switch" on the touch screen then start playing and the screen will turn off. Of course, you can wake it again with a touch as needed.

I'm not sure how intuitive this is, whether people will grasp easily what's turning the screen off and on? That is one advantage to the on-screen button, requiring a user action to make it occur, but the automated setup is more convenient, as long as you understand why it's doing what it's doing.

I'll attach a build, but this change is uncommitted currently. Also, this is from my testing branch with the 4-way slider toggle, so slider behavior may not match other builds.

Option 2

Another possibility is a timeout. I just threw together a build that keeps the touch screen lit for ~5 seconds since the last touch interaction. The GUI remains the same, with the button in video settings. The timeout could obviously be adjusted in either direction, but so far I like this better than option 1. Build attached, see number 2.

Test build

  1. red-viper_backlight-pr_in-video-settings.zip
  2. red-viper_backlight-pr_timeout.zip
vaguerant commented 3 months ago

Pushed Option 2 as mentioned above with some extra tweaks. There's a 5-second timeout on "normal" touch screen input like the Switch and Fast Forward buttons, and a longer 30-second timeout if your last input was one of the virtual buttons (A/B or the D-pad). I made these timeouts #defines up the top so they can more easily be adjusted/to avoid all the magic numbers.

The other big change is the fadeout; when the screen hits the timeout, instead of just shutting off immediately, it fades to black then shuts off the screen, which looks a lot less abrupt. This is just done with a C2D_DrawRectSolid() over the touch screen with incrementing opacity. It's not ideal but it's probably the best I can manage currently. The test build is back to the proper backlight branch, no more slider shenanigans, this is the exact code in the PR.

Test build

cheatfreak47 commented 3 months ago

This is cute, didn't even know this sort of thing was possible! I'm not sure if it makes UX sense to bind it to a touchscreen button though. I certainly think it makes sense to set the brightness level on the touch screen to minimum in-game (possibly with an option to leave it alone).

It's also worth noting that some other emulators on 3DS also have a bottom screen light off button on the top left or right. It's a little weird at first but I think a lot of people are used to it working like this already.

skyfloogle commented 3 months ago

You're gonna kill me but I'm starting to prefer the idea of it being a touchscreen button again. It's more predictable, and according to @cheatfreak47 it has precedent. The touchscreen button commits are still there, so I can put them together. As far as the icon goes, I feel like the most intuitive thing would be a lightbulb. I'll see if I can put that together.