Controller Support Update (#511)

* Update issue template to include .riq/.zip info (#483)

Co-authored-by: patata <patataofcourse@gmail.com>

* Pull release 1 (#484)

* Squashed commit of the following:

commit a6ce193ce5
Merge: 6105bb4f 9b24ac48
Author: minenice55 <star.elementa@gmail.com>
Date:   Wed Jun 14 01:23:31 2023 +0000

    Merge pull request #473 from minenice55/easings-fix

    Enum Parsing Fix

commit 9b24ac4838
Author: minenice55 <star.elementa@gmail.com>
Date:   Tue Jun 13 21:21:13 2023 -0400

    fix all parsing of enums, removed the "special case" for eases

    update to latest Jukebox

commit 6105bb4f64
Merge: 576b4a00 8df235a8
Author: minenice55 <star.elementa@gmail.com>
Date:   Tue Jun 13 21:39:15 2023 +0000

    Merge pull request #469 from minenice55/jukebox-update

    Jukebox Package Update

commit 576b4a0017
Merge: 99804457 10f8fa7f
Author: minenice55 <star.elementa@gmail.com>
Date:   Tue Jun 13 21:39:08 2023 +0000

    Merge pull request #458 from AstrlJelly/MiscAdditions_4

    Bug Fixes + Feature Additions

commit 10f8fa7f5a
Author: minenice55 <star.elementa@gmail.com>
Date:   Tue Jun 13 17:38:24 2023 -0400

    add "updater" for the old marching entity

commit 118cd4993d
Merge: 1c1c731d 99804457
Author: minenice55 <star.elementa@gmail.com>
Date:   Tue Jun 13 17:22:01 2023 -0400

    Merge branch 'release_1' into pr/458

commit 8df235a85b
Author: minenice55 <star.elementa@gmail.com>
Date:   Tue Jun 13 16:55:02 2023 -0400

    let play mode start if no song file is loaded

    fix issue with loading large audio files

commit 9980445723
Merge: aff1e3d8 2f595824
Author: minenice55 <star.elementa@gmail.com>
Date:   Tue Jun 13 18:32:40 2023 +0000

    Merge pull request #471 from Rapandrasmus/FixWorkingDoughCurve

    Fixed weird curve stuff on game switch in working dough

commit 2f59582460
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Tue Jun 13 19:24:13 2023 +0200

    Fixed weird curve stuff on game switch in working dough

commit aff1e3d889
Merge: b40ec128 c9accfa5
Author: minenice55 <star.elementa@gmail.com>
Date:   Tue Jun 13 16:09:21 2023 +0000

    Merge pull request #470 from Rapandrasmus/WorkingDoughFixes

    Fixed small balls not working in working dough

commit c9accfa52d
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Tue Jun 13 18:07:13 2023 +0200

    Fixed small balls not working in working dough

commit b40ec128a5
Merge: 9f953d50 95c9b346
Author: minenice55 <star.elementa@gmail.com>
Date:   Tue Jun 13 14:56:58 2023 +0000

    Merge pull request #467 from Rapandrasmus/WorkingDoughRework

    Working Dough rework

commit 95c9b34695
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Tue Jun 13 16:13:08 2023 +0200

    modernised rockers pass turn

commit 0debf55391
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Tue Jun 13 16:03:08 2023 +0200

    Rhythm tweezers pass turn now works like working dough

commit 6eac745eae
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Tue Jun 13 15:51:35 2023 +0200

    gandw on balls has been added

commit 349867d983
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Tue Jun 13 14:59:56 2023 +0200

    Proper inactive handling now

commit d469c6c3fa
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Tue Jun 13 13:52:15 2023 +0200

    OnSpawnBall reimplemented

commit dd290b3331
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Tue Jun 13 13:37:09 2023 +0200

    new sounds

commit 757e1c2c5e
Author: minenice55 <star.elementa@gmail.com>
Date:   Mon Jun 12 17:18:37 2023 -0400

    update Jukebox to latest version

    fixes for inferred entity loading

commit 8ce1d8276b
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Mon Jun 12 21:36:57 2023 +0200

    ball transporter anims for pass turn

commit af0d9bae19
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Mon Jun 12 20:38:48 2023 +0200

    working dough converted, need to fix eveerything though

commit db21d51673
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Mon Jun 12 18:36:41 2023 +0200

    Converted everything to new curves and made playerballs handle themselves input-wise

commit 41157a038c
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Mon Jun 12 14:04:32 2023 +0200

    Some new curves

commit 7d754f5706
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Mon Jun 12 12:03:21 2023 +0200

    Rockers can do it too now

commit c196947251
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Mon Jun 12 11:58:31 2023 +0200

    You can now place inputs on top of pass turn for rhythm tweezers

commit 9f953d505f
Merge: 2a8d8d6f df120f08
Author: minenice55 <star.elementa@gmail.com>
Date:   Sun Jun 11 15:55:40 2023 -0400

    Merge branch 'master' into release_1

commit 2a8d8d6fd2
Merge: 9e3e5942 13adf5b0
Author: minenice55 <star.elementa@gmail.com>
Date:   Sun Jun 11 19:53:47 2023 +0000

    Merge pull request #465 from minenice55/dont_infer_track

    Don't infer the track field when importing converted v0 riq coming from unknown origin

commit 13adf5b07b
Author: minenice55 <star.elementa@gmail.com>
Date:   Sun Jun 11 15:52:14 2023 -0400

    don't infer track when importing a v0 riq from another program

commit 9e3e594209
Author: minenice55 <star.elementa@gmail.com>
Date:   Sun Jun 11 12:12:25 2023 -0400

    make base datamodels for special entity reading (#463)

    * make base datamodels for special entity reading

    * fix crop stomp breaking when no game switch or remix end is set

    * fix save shortcut

    fix loading charts with no music

commit 1c1c731dd1
Author: minenice55 <star.elementa@gmail.com>
Date:   Sat Jun 10 23:00:30 2023 -0400

    add updater for marching orders turn

commit 210be54ba3
Merge: 67b6658c af8395fb
Author: minenice55 <star.elementa@gmail.com>
Date:   Sat Jun 10 22:36:10 2023 -0400

    Merge branch 'release_1' into pr/458

commit af8395fb6a
Merge: 81eafec9 b1fab52a
Author: minenice55 <star.elementa@gmail.com>
Date:   Sat Jun 10 22:30:32 2023 -0400

    Merge branch 'master' into release_1

commit 81eafec986
Author: minenice55 <star.elementa@gmail.com>
Date:   Sat Jun 10 22:27:58 2023 -0400

    editor fixes (#459)

    * ditch loading dialog

    doesn't show up when it's supposed to

    * format song offset in editor

    * remove VorbisPlugin

    * Update Editor.cs

commit 67b6658cd3
Author: AstrlJelly <bdlawson115@gmail.com>
Date:   Sat Jun 10 16:55:10 2023 -0400

    convert float to double and all that

commit a4b66367fd
Merge: 08a664ba b1fab52a
Author: AstrlJelly <bdlawson115@gmail.com>
Date:   Sat Jun 10 16:01:44 2023 -0400

    Merge remote-tracking branch 'upstream/master' into MiscAdditions_4

commit 08a664ba2a
Merge: faf3fbf9 b7afd697
Author: AstrlJelly <bdlawson115@gmail.com>
Date:   Sat Jun 10 15:21:22 2023 -0400

    Merge remote-tracking branch 'upstream/master' into MiscAdditions_4

commit faf3fbf97c
Author: AstrlJelly <bdlawson115@gmail.com>
Date:   Sat Jun 10 15:18:45 2023 -0400

    a lot

    * munchy monk input + mustache fixes
    * fork lifter and pajama party bopping
    * meat grinder miss bop fix
    * cloud monkey Real
    * marching orders Go! was broken
    * force march doesn't break when it's too early from a game switch
    * you can use the March! block without the marching now

commit bb2ae74339
Author: minenice55 <star.elementa@gmail.com>
Date:   Sat Jun 10 15:13:29 2023 -0400

    Integration of Jukebox Library (#451)

    * add Jukebox library

    todo:
    - saving / loading of new format
    - inferrence of unknown data like past versions
    - move the temporary float casts to proper use of double
    - make sound related functions take double for timing
    - inform people that the Jukebox sound player was renamed to SoundByte lol

    * make sound, input scheduling, and super curve use double precision

    * successfully load charts

    * editor works again

    v1 riqs can be saved and loaded

    * first tempo and volume markers are unmovable

    fix loading of charts' easing values

    * use gsync / freesync

    * update Jukebox refs to SoundByte

    * game events use double part 1

    Air Rally - Glee Club converted

    * don't load song if chart load fails

    * finish conversion of all minigames

    * remove editor waveform toggle

    * timeline now respects added song offset length

    clear cache files on app close
    prepped notes for dsp sync

    * update timeline length when offset changed

    * update to latest Jukebox

    * make error panel object in global game manager

    * improve conductor music scheduling

    * added error message box

    fix first game events sometimes not playing

* Squashed commit of the following:

commit e782e3a5b4
Merge: 5b8cfef1 ce74719c
Author: minenice55 <star.elementa@gmail.com>
Date:   Sat Jun 17 16:40:52 2023 +0000

    Merge pull request #478 from evdial/working-dough

    Working Dough Tweaks

commit ce74719c1a
Merge: 9c61b760 5b8cfef1
Author: minenice55 <star.elementa@gmail.com>
Date:   Sat Jun 17 12:40:06 2023 -0400

    Merge branch 'release_1' into pr/478

commit 5b8cfef1b0
Author: patata <patataofcourse@gmail.com>
Date:   Sat Jun 17 17:20:15 2023 +0200

    Update issue template to include .riq/.zip info

commit 9c61b760bb
Author: ev <85412919+evdial@users.noreply.github.com>
Date:   Thu Jun 15 15:05:07 2023 -0400

    assbuns

commit ae7451e9d3
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Thu Jun 15 20:56:40 2023 +0200

    made small idle not crazy

commit 4c5c95237c
Author: ev <85412919+evdial@users.noreply.github.com>
Date:   Thu Jun 15 14:33:57 2023 -0400

    fsd

commit 083d916238
Author: ev <85412919+evdial@users.noreply.github.com>
Date:   Thu Jun 15 14:16:38 2023 -0400

    anim

commit b3664e01b3
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Thu Jun 15 20:13:11 2023 +0200

    Fixed stuff also scaled now yippee

commit 71e3a0ce6b
Author: ev <85412919+evdial@users.noreply.github.com>
Date:   Thu Jun 15 13:50:10 2023 -0400

    many

commit 534b06301d
Author: minenice55 <star.elementa@gmail.com>
Date:   Tue Jun 13 21:28:21 2023 -0400

    Squashed commit of the following: (#474)

    commit a6ce193ce5
    Merge: 6105bb4f 9b24ac48
    Author: minenice55 <star.elementa@gmail.com>
    Date:   Wed Jun 14 01:23:31 2023 +0000

        Merge pull request #473 from minenice55/easings-fix

        Enum Parsing Fix

    commit 9b24ac4838
    Author: minenice55 <star.elementa@gmail.com>
    Date:   Tue Jun 13 21:21:13 2023 -0400

        fix all parsing of enums, removed the "special case" for eases

        update to latest Jukebox

    commit 6105bb4f64
    Merge: 576b4a00 8df235a8
    Author: minenice55 <star.elementa@gmail.com>
    Date:   Tue Jun 13 21:39:15 2023 +0000

        Merge pull request #469 from minenice55/jukebox-update

        Jukebox Package Update

    commit 576b4a0017
    Merge: 99804457 10f8fa7f
    Author: minenice55 <star.elementa@gmail.com>
    Date:   Tue Jun 13 21:39:08 2023 +0000

        Merge pull request #458 from AstrlJelly/MiscAdditions_4

        Bug Fixes + Feature Additions

    commit 10f8fa7f5a
    Author: minenice55 <star.elementa@gmail.com>
    Date:   Tue Jun 13 17:38:24 2023 -0400

        add "updater" for the old marching entity

    commit 118cd4993d
    Merge: 1c1c731d 99804457
    Author: minenice55 <star.elementa@gmail.com>
    Date:   Tue Jun 13 17:22:01 2023 -0400

        Merge branch 'release_1' into pr/458

    commit 8df235a85b
    Author: minenice55 <star.elementa@gmail.com>
    Date:   Tue Jun 13 16:55:02 2023 -0400

        let play mode start if no song file is loaded

        fix issue with loading large audio files

    commit 9980445723
    Merge: aff1e3d8 2f595824
    Author: minenice55 <star.elementa@gmail.com>
    Date:   Tue Jun 13 18:32:40 2023 +0000

        Merge pull request #471 from Rapandrasmus/FixWorkingDoughCurve

        Fixed weird curve stuff on game switch in working dough

    commit 2f59582460
    Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
    Date:   Tue Jun 13 19:24:13 2023 +0200

        Fixed weird curve stuff on game switch in working dough

    commit aff1e3d889
    Merge: b40ec128 c9accfa5
    Author: minenice55 <star.elementa@gmail.com>
    Date:   Tue Jun 13 16:09:21 2023 +0000

        Merge pull request #470 from Rapandrasmus/WorkingDoughFixes

        Fixed small balls not working in working dough

    commit c9accfa52d
    Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
    Date:   Tue Jun 13 18:07:13 2023 +0200

        Fixed small balls not working in working dough

    commit b40ec128a5
    Merge: 9f953d50 95c9b346
    Author: minenice55 <star.elementa@gmail.com>
    Date:   Tue Jun 13 14:56:58 2023 +0000

        Merge pull request #467 from Rapandrasmus/WorkingDoughRework

        Working Dough rework

    commit 95c9b34695
    Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
    Date:   Tue Jun 13 16:13:08 2023 +0200

        modernised rockers pass turn

    commit 0debf55391
    Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
    Date:   Tue Jun 13 16:03:08 2023 +0200

        Rhythm tweezers pass turn now works like working dough

    commit 6eac745eae
    Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
    Date:   Tue Jun 13 15:51:35 2023 +0200

        gandw on balls has been added

    commit 349867d983
    Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
    Date:   Tue Jun 13 14:59:56 2023 +0200

        Proper inactive handling now

    commit d469c6c3fa
    Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
    Date:   Tue Jun 13 13:52:15 2023 +0200

        OnSpawnBall reimplemented

    commit dd290b3331
    Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
    Date:   Tue Jun 13 13:37:09 2023 +0200

        new sounds

    commit 757e1c2c5e
    Author: minenice55 <star.elementa@gmail.com>
    Date:   Mon Jun 12 17:18:37 2023 -0400

        update Jukebox to latest version

        fixes for inferred entity loading

    commit 8ce1d8276b
    Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
    Date:   Mon Jun 12 21:36:57 2023 +0200

        ball transporter anims for pass turn

    commit af0d9bae19
    Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
    Date:   Mon Jun 12 20:38:48 2023 +0200

        working dough converted, need to fix eveerything though

    commit db21d51673
    Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
    Date:   Mon Jun 12 18:36:41 2023 +0200

        Converted everything to new curves and made playerballs handle themselves input-wise

    commit 41157a038c
    Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
    Date:   Mon Jun 12 14:04:32 2023 +0200

        Some new curves

    commit 7d754f5706
    Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
    Date:   Mon Jun 12 12:03:21 2023 +0200

        Rockers can do it too now

    commit c196947251
    Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
    Date:   Mon Jun 12 11:58:31 2023 +0200

        You can now place inputs on top of pass turn for rhythm tweezers

    commit 9f953d505f
    Merge: 2a8d8d6f df120f08
    Author: minenice55 <star.elementa@gmail.com>
    Date:   Sun Jun 11 15:55:40 2023 -0400

        Merge branch 'master' into release_1

    commit 2a8d8d6fd2
    Merge: 9e3e5942 13adf5b0
    Author: minenice55 <star.elementa@gmail.com>
    Date:   Sun Jun 11 19:53:47 2023 +0000

        Merge pull request #465 from minenice55/dont_infer_track

        Don't infer the track field when importing converted v0 riq coming from unknown origin

    commit 13adf5b07b
    Author: minenice55 <star.elementa@gmail.com>
    Date:   Sun Jun 11 15:52:14 2023 -0400

        don't infer track when importing a v0 riq from another program

    commit 9e3e594209
    Author: minenice55 <star.elementa@gmail.com>
    Date:   Sun Jun 11 12:12:25 2023 -0400

        make base datamodels for special entity reading (#463)

        * make base datamodels for special entity reading

        * fix crop stomp breaking when no game switch or remix end is set

        * fix save shortcut

        fix loading charts with no music

    commit 1c1c731dd1
    Author: minenice55 <star.elementa@gmail.com>
    Date:   Sat Jun 10 23:00:30 2023 -0400

        add updater for marching orders turn

    commit 210be54ba3
    Merge: 67b6658c af8395fb
    Author: minenice55 <star.elementa@gmail.com>
    Date:   Sat Jun 10 22:36:10 2023 -0400

        Merge branch 'release_1' into pr/458

    commit af8395fb6a
    Merge: 81eafec9 b1fab52a
    Author: minenice55 <star.elementa@gmail.com>
    Date:   Sat Jun 10 22:30:32 2023 -0400

        Merge branch 'master' into release_1

    commit 81eafec986
    Author: minenice55 <star.elementa@gmail.com>
    Date:   Sat Jun 10 22:27:58 2023 -0400

        editor fixes (#459)

        * ditch loading dialog

        doesn't show up when it's supposed to

        * format song offset in editor

        * remove VorbisPlugin

        * Update Editor.cs

    commit 67b6658cd3
    Author: AstrlJelly <bdlawson115@gmail.com>
    Date:   Sat Jun 10 16:55:10 2023 -0400

        convert float to double and all that

    commit a4b66367fd
    Merge: 08a664ba b1fab52a
    Author: AstrlJelly <bdlawson115@gmail.com>
    Date:   Sat Jun 10 16:01:44 2023 -0400

        Merge remote-tracking branch 'upstream/master' into MiscAdditions_4

    commit 08a664ba2a
    Merge: faf3fbf9 b7afd697
    Author: AstrlJelly <bdlawson115@gmail.com>
    Date:   Sat Jun 10 15:21:22 2023 -0400

        Merge remote-tracking branch 'upstream/master' into MiscAdditions_4

    commit faf3fbf97c
    Author: AstrlJelly <bdlawson115@gmail.com>
    Date:   Sat Jun 10 15:18:45 2023 -0400

        a lot

        * munchy monk input + mustache fixes
        * fork lifter and pajama party bopping
        * meat grinder miss bop fix
        * cloud monkey Real
        * marching orders Go! was broken
        * force march doesn't break when it's too early from a game switch
        * you can use the March! block without the marching now

    commit bb2ae74339
    Author: minenice55 <star.elementa@gmail.com>
    Date:   Sat Jun 10 15:13:29 2023 -0400

        Integration of Jukebox Library (#451)

        * add Jukebox library

        todo:
        - saving / loading of new format
        - inferrence of unknown data like past versions
        - move the temporary float casts to proper use of double
        - make sound related functions take double for timing
        - inform people that the Jukebox sound player was renamed to SoundByte lol

        * make sound, input scheduling, and super curve use double precision

        * successfully load charts

        * editor works again

        v1 riqs can be saved and loaded

        * first tempo and volume markers are unmovable

        fix loading of charts' easing values

        * use gsync / freesync

        * update Jukebox refs to SoundByte

        * game events use double part 1

        Air Rally - Glee Club converted

        * don't load song if chart load fails

        * finish conversion of all minigames

        * remove editor waveform toggle

        * timeline now respects added song offset length

        clear cache files on app close
        prepped notes for dsp sync

        * update timeline length when offset changed

        * update to latest Jukebox

        * make error panel object in global game manager

        * improve conductor music scheduling

        * added error message box

        fix first game events sometimes not playing

commit a6ce193ce5
Merge: 6105bb4f 9b24ac48
Author: minenice55 <star.elementa@gmail.com>
Date:   Wed Jun 14 01:23:31 2023 +0000

    Merge pull request #473 from minenice55/easings-fix

    Enum Parsing Fix

commit 9b24ac4838
Author: minenice55 <star.elementa@gmail.com>
Date:   Tue Jun 13 21:21:13 2023 -0400

    fix all parsing of enums, removed the "special case" for eases

    update to latest Jukebox

commit 6105bb4f64
Merge: 576b4a00 8df235a8
Author: minenice55 <star.elementa@gmail.com>
Date:   Tue Jun 13 21:39:15 2023 +0000

    Merge pull request #469 from minenice55/jukebox-update

    Jukebox Package Update

commit 576b4a0017
Merge: 99804457 10f8fa7f
Author: minenice55 <star.elementa@gmail.com>
Date:   Tue Jun 13 21:39:08 2023 +0000

    Merge pull request #458 from AstrlJelly/MiscAdditions_4

    Bug Fixes + Feature Additions

commit 10f8fa7f5a
Author: minenice55 <star.elementa@gmail.com>
Date:   Tue Jun 13 17:38:24 2023 -0400

    add "updater" for the old marching entity

commit 118cd4993d
Merge: 1c1c731d 99804457
Author: minenice55 <star.elementa@gmail.com>
Date:   Tue Jun 13 17:22:01 2023 -0400

    Merge branch 'release_1' into pr/458

commit 8df235a85b
Author: minenice55 <star.elementa@gmail.com>
Date:   Tue Jun 13 16:55:02 2023 -0400

    let play mode start if no song file is loaded

    fix issue with loading large audio files

commit 9980445723
Merge: aff1e3d8 2f595824
Author: minenice55 <star.elementa@gmail.com>
Date:   Tue Jun 13 18:32:40 2023 +0000

    Merge pull request #471 from Rapandrasmus/FixWorkingDoughCurve

    Fixed weird curve stuff on game switch in working dough

commit 2f59582460
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Tue Jun 13 19:24:13 2023 +0200

    Fixed weird curve stuff on game switch in working dough

commit aff1e3d889
Merge: b40ec128 c9accfa5
Author: minenice55 <star.elementa@gmail.com>
Date:   Tue Jun 13 16:09:21 2023 +0000

    Merge pull request #470 from Rapandrasmus/WorkingDoughFixes

    Fixed small balls not working in working dough

commit c9accfa52d
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Tue Jun 13 18:07:13 2023 +0200

    Fixed small balls not working in working dough

commit b40ec128a5
Merge: 9f953d50 95c9b346
Author: minenice55 <star.elementa@gmail.com>
Date:   Tue Jun 13 14:56:58 2023 +0000

    Merge pull request #467 from Rapandrasmus/WorkingDoughRework

    Working Dough rework

commit 95c9b34695
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Tue Jun 13 16:13:08 2023 +0200

    modernised rockers pass turn

commit 0debf55391
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Tue Jun 13 16:03:08 2023 +0200

    Rhythm tweezers pass turn now works like working dough

commit 6eac745eae
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Tue Jun 13 15:51:35 2023 +0200

    gandw on balls has been added

commit 349867d983
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Tue Jun 13 14:59:56 2023 +0200

    Proper inactive handling now

commit d469c6c3fa
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Tue Jun 13 13:52:15 2023 +0200

    OnSpawnBall reimplemented

commit dd290b3331
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Tue Jun 13 13:37:09 2023 +0200

    new sounds

commit 757e1c2c5e
Author: minenice55 <star.elementa@gmail.com>
Date:   Mon Jun 12 17:18:37 2023 -0400

    update Jukebox to latest version

    fixes for inferred entity loading

commit 8ce1d8276b
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Mon Jun 12 21:36:57 2023 +0200

    ball transporter anims for pass turn

commit af0d9bae19
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Mon Jun 12 20:38:48 2023 +0200

    working dough converted, need to fix eveerything though

commit db21d51673
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Mon Jun 12 18:36:41 2023 +0200

    Converted everything to new curves and made playerballs handle themselves input-wise

commit 41157a038c
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Mon Jun 12 14:04:32 2023 +0200

    Some new curves

commit 7d754f5706
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Mon Jun 12 12:03:21 2023 +0200

    Rockers can do it too now

commit c196947251
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Mon Jun 12 11:58:31 2023 +0200

    You can now place inputs on top of pass turn for rhythm tweezers

commit 9f953d505f
Merge: 2a8d8d6f df120f08
Author: minenice55 <star.elementa@gmail.com>
Date:   Sun Jun 11 15:55:40 2023 -0400

    Merge branch 'master' into release_1

commit 2a8d8d6fd2
Merge: 9e3e5942 13adf5b0
Author: minenice55 <star.elementa@gmail.com>
Date:   Sun Jun 11 19:53:47 2023 +0000

    Merge pull request #465 from minenice55/dont_infer_track

    Don't infer the track field when importing converted v0 riq coming from unknown origin

commit 13adf5b07b
Author: minenice55 <star.elementa@gmail.com>
Date:   Sun Jun 11 15:52:14 2023 -0400

    don't infer track when importing a v0 riq from another program

commit 9e3e594209
Author: minenice55 <star.elementa@gmail.com>
Date:   Sun Jun 11 12:12:25 2023 -0400

    make base datamodels for special entity reading (#463)

    * make base datamodels for special entity reading

    * fix crop stomp breaking when no game switch or remix end is set

    * fix save shortcut

    fix loading charts with no music

commit 1c1c731dd1
Author: minenice55 <star.elementa@gmail.com>
Date:   Sat Jun 10 23:00:30 2023 -0400

    add updater for marching orders turn

commit 210be54ba3
Merge: 67b6658c af8395fb
Author: minenice55 <star.elementa@gmail.com>
Date:   Sat Jun 10 22:36:10 2023 -0400

    Merge branch 'release_1' into pr/458

commit af8395fb6a
Merge: 81eafec9 b1fab52a
Author: minenice55 <star.elementa@gmail.com>
Date:   Sat Jun 10 22:30:32 2023 -0400

    Merge branch 'master' into release_1

commit 81eafec986
Author: minenice55 <star.elementa@gmail.com>
Date:   Sat Jun 10 22:27:58 2023 -0400

    editor fixes (#459)

    * ditch loading dialog

    doesn't show up when it's supposed to

    * format song offset in editor

    * remove VorbisPlugin

    * Update Editor.cs

commit 67b6658cd3
Author: AstrlJelly <bdlawson115@gmail.com>
Date:   Sat Jun 10 16:55:10 2023 -0400

    convert float to double and all that

commit a4b66367fd
Merge: 08a664ba b1fab52a
Author: AstrlJelly <bdlawson115@gmail.com>
Date:   Sat Jun 10 16:01:44 2023 -0400

    Merge remote-tracking branch 'upstream/master' into MiscAdditions_4

commit 08a664ba2a
Merge: faf3fbf9 b7afd697
Author: AstrlJelly <bdlawson115@gmail.com>
Date:   Sat Jun 10 15:21:22 2023 -0400

    Merge remote-tracking branch 'upstream/master' into MiscAdditions_4

commit faf3fbf97c
Author: AstrlJelly <bdlawson115@gmail.com>
Date:   Sat Jun 10 15:18:45 2023 -0400

    a lot

    * munchy monk input + mustache fixes
    * fork lifter and pajama party bopping
    * meat grinder miss bop fix
    * cloud monkey Real
    * marching orders Go! was broken
    * force march doesn't break when it's too early from a game switch
    * you can use the March! block without the marching now

commit bb2ae74339
Author: minenice55 <star.elementa@gmail.com>
Date:   Sat Jun 10 15:13:29 2023 -0400

    Integration of Jukebox Library (#451)

    * add Jukebox library

    todo:
    - saving / loading of new format
    - inferrence of unknown data like past versions
    - move the temporary float casts to proper use of double
    - make sound related functions take double for timing
    - inform people that the Jukebox sound player was renamed to SoundByte lol

    * make sound, input scheduling, and super curve use double precision

    * successfully load charts

    * editor works again

    v1 riqs can be saved and loaded

    * first tempo and volume markers are unmovable

    fix loading of charts' easing values

    * use gsync / freesync

    * update Jukebox refs to SoundByte

    * game events use double part 1

    Air Rally - Glee Club converted

    * don't load song if chart load fails

    * finish conversion of all minigames

    * remove editor waveform toggle

    * timeline now respects added song offset length

    clear cache files on app close
    prepped notes for dsp sync

    * update timeline length when offset changed

    * update to latest Jukebox

    * make error panel object in global game manager

    * improve conductor music scheduling

    * added error message box

    fix first game events sometimes not playing

* Editor Additions (#479)

* favoriting and pick block

favoriting needs to not break after previewing (maybe make it persistent in the settings file?)
pick block needs to pick the icon, too. and preferably scroll to it as well

* final star anim + automatic icon game switching

before i make any more changes im making a checkpoint here cuz i know it works
* i want to add a way to specify which event SwitchGame() will switch to (because that's a cool feature for pick block)
* i'll have to figure out how to auto scroll to the game when the icon is selected
* the star now fully works, even between preview switches 👍

* fix the rest of the stuff

the event name gets colored correctly and hidden games are skipped over, but still loaded.
also i built mm ass buns

* tweaks + zoom and sorting

this stuff will be in the pr desc so it doesn't matter

* oop one more thing

* icons look better now :D

mipmaps to the rescue

* double date fix

* Merge pull request #486 from RHeavenStudio/actions_rework

Rework GitHub Actions and build script

* add ab meta to gitignore (#489)

* Sound Scheduling Improvements (#491)

* port conductor adjustments

* scheduled sounds prebake

* allow aiff files to be imported

add vbr mp3 warning to readme

* improve wording

* separate controller initializers

update JSL

* set initial player on joyshocks

* loaders have their own namespace

* port PlayerActionEvent IsHittable

rename timing margin values
simplify some player action event logic

* CNR API Internal Rework (#488)

* Prep stuff

* Tweezers now spawn in

* Started converting tweezers

* I hate <1 beat intervals

* Actually nvm

* fixed a bug

* You can chain intervals now, stack them if you really wanted

* Pass turn checks if crhandlerinstance exists

* Fixed hairs being deleted by onion switch

* Rockers rerewritten

* working dough rerewritten

* Revert "Merge branch 'master' into new-controller-support"

This reverts commit 2bf4c14f68a6f4f512504feb21d0ea5242e4a0fc, reversing
changes made to b9c5fd4581750de0e4aefffa9b4a2ab9564971d1.

* Squashed commit of the following:

commit d68e71775a
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Wed Jun 28 06:51:53 2023 +0200

    CNR API Internal Rework (#488)

    * Prep stuff

    * Tweezers now spawn in

    * Started converting tweezers

    * I hate <1 beat intervals

    * Actually nvm

    * fixed a bug

    * You can chain intervals now, stack them if you really wanted

    * Pass turn checks if crhandlerinstance exists

    * Fixed hairs being deleted by onion switch

    * Rockers rerewritten

    * working dough rerewritten

* update packages for mac

* assign plugin platforms

* JSL polling via event

* JSL timestamped input

* initial prep for rebinding controls

rename some bindings
properly expose newer JSL stuff

* update JSL plugin

support for DualSense Edge (treated as DualSense)

* methods for working on controller binds

doc parts of the InputController class

* show bindings in settings menu

* CNR API Internal Rework (#488)

* Prep stuff

* Tweezers now spawn in

* Started converting tweezers

* I hate <1 beat intervals

* Actually nvm

* fixed a bug

* You can chain intervals now, stack them if you really wanted

* Pass turn checks if crhandlerinstance exists

* Fixed hairs being deleted by onion switch

* Rockers rerewritten

* working dough rerewritten

* Games fixes/reworks patch (#501)

* ghosts are scaled now

* Lockstep fully reworked

* mr. bach has been implemented

* Space dance fixes

* oops

* Tap trial rework part 1

* tap trial rework part 2

* oopsie

* Gramps Talk Update

* Space Dance Voice Offsets

* Giraffe done! (Except miss anim)

* bg is not showing up for some reason

* bg not rendering fixed + giraffe fixed

* scrolling done

* fixed space dance and space soccer bg scrolls

* fixed rockers bugs

* adjustment

* fixed el inaccuracies

* particle fix

* changed pitch and volume of monkey tap

* miss anim

* megamix face for girl

* Proper miss anim implementation

* Added force stepping event

* miss anim fix

---------

Co-authored-by: saladplainzone <chocolate2890mail@gmail.com>
Co-authored-by: ev <85412919+evdial@users.noreply.github.com>

* Revert "Merge branch 'master' into new-controller-support"

This reverts commit 3f0edd8657074fea4ff93a91b3822ba10f9e98c1, reversing
changes made to 804d7fad3b6498bc80da9646115a1d1e30254961.

* Squashed commit of the following:

commit dfe144cf4b
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Thu Jul 13 02:35:47 2023 +0200

    Games fixes/reworks patch (#501)

    * ghosts are scaled now

    * Lockstep fully reworked

    * mr. bach has been implemented

    * Space dance fixes

    * oops

    * Tap trial rework part 1

    * tap trial rework part 2

    * oopsie

    * Gramps Talk Update

    * Space Dance Voice Offsets

    * Giraffe done! (Except miss anim)

    * bg is not showing up for some reason

    * bg not rendering fixed + giraffe fixed

    * scrolling done

    * fixed space dance and space soccer bg scrolls

    * fixed rockers bugs

    * adjustment

    * fixed el inaccuracies

    * particle fix

    * changed pitch and volume of monkey tap

    * miss anim

    * megamix face for girl

    * Proper miss anim implementation

    * Added force stepping event

    * miss anim fix

    ---------

    Co-authored-by: saladplainzone <chocolate2890mail@gmail.com>
    Co-authored-by: ev <85412919+evdial@users.noreply.github.com>

commit 8a968b0a38
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Wed Jul 12 18:49:32 2023 +0200

    Second Contact Rework + Small CNR API changes (#500)

    * Just need to rewrite how player text works

    * text almost fixed

    * text is now fixed

    * ellipses added

    * Removed cnr api from rockers and working dough

    * oops

commit d68e71775a
Author: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Date:   Wed Jun 28 06:51:53 2023 +0200

    CNR API Internal Rework (#488)

    * Prep stuff

    * Tweezers now spawn in

    * Started converting tweezers

    * I hate <1 beat intervals

    * Actually nvm

    * fixed a bug

    * You can chain intervals now, stack them if you really wanted

    * Pass turn checks if crhandlerinstance exists

    * Fixed hairs being deleted by onion switch

    * Rockers rerewritten

    * working dough rerewritten

* working controller remapping

* better differentiate between physical buttons and virtual actions

fix bugs with single joy-con

* add 90hz input debouncing

* fix display issue in joycon pairing UI

* start fixing issues with split pair

todo: make the con read the paired controller as well

* saving/loading custom binds

* fix issues with joy-con pairs

fix binding reset issue with joyshocks

* apply same fix to kb

swap kb east and south action binds

* implement IsHittable in places that need it as examples

* pj party needed IsHittable as well

---------

Co-authored-by: patata <patataofcourse@gmail.com>
Co-authored-by: AstrlJelly <bdlawson115@gmail.com>
Co-authored-by: Rapandrasmus <78219215+Rapandrasmus@users.noreply.github.com>
Co-authored-by: saladplainzone <chocolate2890mail@gmail.com>
Co-authored-by: ev <85412919+evdial@users.noreply.github.com>
This commit is contained in:
minenice55 2023-07-30 22:32:11 -04:00 committed by GitHub
parent fc5614dae2
commit 3d8f43668f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
47 changed files with 7280 additions and 1323 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,63 @@
fileFormatVersion: 2
guid: ba4f73ad56fdd254c9406111c6702f84
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Editor: 0
Exclude Linux64: 0
Exclude OSXUniversal: 0
Exclude Win: 0
Exclude Win64: 0
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 1
settings:
CPU: x86_64
DefaultValueInitialized: true
OS: AnyOS
- first:
Standalone: Linux64
second:
enabled: 1
settings:
CPU: AnyCPU
- first:
Standalone: OSXUniversal
second:
enabled: 1
settings:
CPU: AnyCPU
- first:
Standalone: Win
second:
enabled: 1
settings:
CPU: None
- first:
Standalone: Win64
second:
enabled: 1
settings:
CPU: x86_64
userData:
assetBundleName:
assetBundleVariant:

View file

@ -53,7 +53,7 @@ PluginImporter:
second: second:
enabled: 1 enabled: 1
settings: settings:
CPU: AnyCPU CPU: x86_64
- first: - first:
Standalone: Win Standalone: Win
second: second:

View file

@ -11,6 +11,16 @@ PluginImporter:
isExplicitlyReferenced: 0 isExplicitlyReferenced: 0
validateReferences: 1 validateReferences: 1
platformData: platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Editor: 0
Exclude Linux64: 0
Exclude OSXUniversal: 1
Exclude Win: 0
Exclude Win64: 0
- first: - first:
Any: Any:
second: second:
@ -19,10 +29,11 @@ PluginImporter:
- first: - first:
Editor: Editor Editor: Editor
second: second:
enabled: 0 enabled: 1
settings: settings:
CPU: x86_64 CPU: x86_64
DefaultValueInitialized: true DefaultValueInitialized: true
OS: AnyOS
- first: - first:
Standalone: Linux64 Standalone: Linux64
second: second:
@ -34,11 +45,11 @@ PluginImporter:
second: second:
enabled: 0 enabled: 0
settings: settings:
CPU: x86_64 CPU: None
- first: - first:
Standalone: Win Standalone: Win
second: second:
enabled: 0 enabled: 1
settings: settings:
CPU: None CPU: None
- first: - first:

View file

@ -76,28 +76,50 @@ public static class JSL
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct MOTION_STATE { public struct MOTION_STATE {
float quatW; public float quatW;
float quatX; public float quatX;
float quatY; public float quatY;
float quatZ; public float quatZ;
float accelX; public float accelX;
float accelY; public float accelY;
float accelZ; public float accelZ;
float gravX; public float gravX;
float gravY; public float gravY;
float gravZ; public float gravZ;
} }
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct TOUCH_STATE { public struct TOUCH_STATE {
int t0Id; public int t0Id;
int t1Id; public int t1Id;
bool t0Down; public bool t0Down;
bool t1Down; public bool t1Down;
float t0X; public float t0X;
float t0Y; public float t0Y;
float t1X; public float t1X;
float t1Y; public float t1Y;
}
[StructLayout(LayoutKind.Sequential)]
public struct JSL_AUTO_CALIBRATION {
public float confidence;
public bool autoCalibrationEnabled;
public bool isSteady;
}
[StructLayout(LayoutKind.Sequential)]
public struct JSL_SETTINGS {
public int gyroSpace;
public int bodyColour;
public int lGripColour;
public int rGripColour;
public int buttonColour;
public int playerNumber;
public int controllerType;
public int splitType;
public bool isCalibrating;
public bool autoCalibrationEnabled;
public bool isConnected;
} }
public delegate void EventCallback(int handle, JOY_SHOCK_STATE state, JOY_SHOCK_STATE lastState, public delegate void EventCallback(int handle, JOY_SHOCK_STATE state, JOY_SHOCK_STATE lastState,
@ -105,12 +127,17 @@ public static class JSL
public delegate void TouchCallback(int handle, TOUCH_STATE state, TOUCH_STATE lastState, float deltaTime); public delegate void TouchCallback(int handle, TOUCH_STATE state, TOUCH_STATE lastState, float deltaTime);
public delegate void ConnectionCallback(int handle);
public delegate void DeconnectionCallback(int handle, bool isConnected);
[DllImport("JoyShockLibrary")] [DllImport("JoyShockLibrary")]
public static extern int JslConnectDevices(); public static extern int JslConnectDevices();
[DllImport("JoyShockLibrary")] [DllImport("JoyShockLibrary")]
public static extern int JslGetConnectedDeviceHandles(int[] deviceHandleArray, int size); public static extern int JslGetConnectedDeviceHandles(int[] deviceHandleArray, int size);
[DllImport("JoyShockLibrary")] [DllImport("JoyShockLibrary")]
public static extern void JslDisconnectAndDisposeAll(); public static extern void JslDisconnectAndDisposeAll();
[DllImport("JoyShockLibrary")]
public static extern bool JslStillConnected(int deviceId);
[DllImport("JoyShockLibrary", CallingConvention = CallingConvention.Cdecl)] [DllImport("JoyShockLibrary", CallingConvention = CallingConvention.Cdecl)]
public static extern JOY_SHOCK_STATE JslGetSimpleState(int deviceId); public static extern JOY_SHOCK_STATE JslGetSimpleState(int deviceId);
@ -121,12 +148,17 @@ public static class JSL
[DllImport("JoyShockLibrary", CallingConvention = CallingConvention.Cdecl)] [DllImport("JoyShockLibrary", CallingConvention = CallingConvention.Cdecl)]
public static extern TOUCH_STATE JslGetTouchState(int deviceId); public static extern TOUCH_STATE JslGetTouchState(int deviceId);
[DllImport("JoyShockLibrary")]
public static extern void JslSetGyroSpace(int deviceId, int gyroSpace);
[DllImport("JoyShockLibrary")] [DllImport("JoyShockLibrary")]
public static extern float JslGetStickStep(int deviceId); public static extern float JslGetStickStep(int deviceId);
[DllImport("JoyShockLibrary")] [DllImport("JoyShockLibrary")]
public static extern float JslGetTriggerStep(int deviceId); public static extern float JslGetTriggerStep(int deviceId);
[DllImport("JoyShockLibrary")] [DllImport("JoyShockLibrary")]
public static extern float JslGetPollRate(int deviceId); public static extern float JslGetPollRate(int deviceId);
[DllImport("JoyShockLibrary")]
public static extern float JslGetTimeSinceLastUpdate(int deviceId);
[DllImport("JoyShockLibrary")] [DllImport("JoyShockLibrary")]
public static extern float JslGetTouchId(int deviceId, bool secondTouch = false); public static extern float JslGetTouchId(int deviceId, bool secondTouch = false);
@ -147,12 +179,23 @@ public static class JSL
public static extern void JslGetCalibrationOffset(int deviceId, ref float xOffset, ref float yOffset, ref float zOffset); public static extern void JslGetCalibrationOffset(int deviceId, ref float xOffset, ref float yOffset, ref float zOffset);
[DllImport("JoyShockLibrary")] [DllImport("JoyShockLibrary")]
public static extern void JslGetCalibrationOffset(int deviceId, float xOffset, float yOffset, float zOffset); public static extern void JslGetCalibrationOffset(int deviceId, float xOffset, float yOffset, float zOffset);
[DllImport("JoyShockLibrary")]
public static extern JSL_AUTO_CALIBRATION JslGetAutoCalibrationStatus(int deviceId);
[DllImport("JoyShockLibrary")] [DllImport("JoyShockLibrary")]
public static extern void JslSetCallback(EventCallback callback); public static extern void JslSetCallback(EventCallback callback);
[DllImport("JoyShockLibrary")] [DllImport("JoyShockLibrary")]
public static extern void JslSetTouchCallback(TouchCallback callback); public static extern void JslSetTouchCallback(TouchCallback callback);
// this function will get called for each device when it is newly connected
[DllImport("JoyShockLibrary")]
public static extern void JslSetConnectCallback(ConnectionCallback callback);
// this function will get called for each device when it is disconnected
[DllImport("JoyShockLibrary")]
public static extern void JslSetDisconnectCallback(DeconnectionCallback callback);
// super-getter for reading a whole lot of state at once
[DllImport("JoyShockLibrary")]
public static extern JSL_SETTINGS JslGetControllerInfoAndSettings(int deviceId);
[DllImport("JoyShockLibrary")] [DllImport("JoyShockLibrary")]
public static extern int JslGetControllerType(int deviceId); public static extern int JslGetControllerType(int deviceId);
[DllImport("JoyShockLibrary")] [DllImport("JoyShockLibrary")]

View file

@ -70,58 +70,79 @@
#define JSOFFSET_SR 19 #define JSOFFSET_SR 19
// PS5 Player maps for the DS Player Lightbar // PS5 Player maps for the DS Player Lightbar
#define DS5_PLAYER_1 = 4 #define DS5_PLAYER_1 4
#define DS5_PLAYER_2 = 10 #define DS5_PLAYER_2 10
#define DS5_PLAYER_3 = 21 #define DS5_PLAYER_3 21
#define DS5_PLAYER_4 = 27 #define DS5_PLAYER_4 27
#define DS5_PLAYER_5 = 31 #define DS5_PLAYER_5 31
typedef struct JOY_SHOCK_STATE { typedef struct JOY_SHOCK_STATE {
int buttons; int buttons = 0;
float lTrigger; float lTrigger = 0.f;
float rTrigger; float rTrigger = 0.f;
float stickLX; float stickLX = 0.f;
float stickLY; float stickLY = 0.f;
float stickRX; float stickRX = 0.f;
float stickRY; float stickRY = 0.f;
} JOY_SHOCK_STATE; } JOY_SHOCK_STATE;
typedef struct IMU_STATE { typedef struct IMU_STATE {
float accelX; float accelX = 0.f;
float accelY; float accelY = 0.f;
float accelZ; float accelZ = 0.f;
float gyroX; float gyroX = 0.f;
float gyroY; float gyroY = 0.f;
float gyroZ; float gyroZ = 0.f;
} IMU_STATE; } IMU_STATE;
typedef struct MOTION_STATE { typedef struct MOTION_STATE {
float quatW; float quatW = 0.f;
float quatX; float quatX = 0.f;
float quatY; float quatY = 0.f;
float quatZ; float quatZ = 0.f;
float accelX; float accelX = 0.f;
float accelY; float accelY = 0.f;
float accelZ; float accelZ = 0.f;
float gravX; float gravX = 0.f;
float gravY; float gravY = 0.f;
float gravZ; float gravZ = 0.f;
} MOTION_STATE; } MOTION_STATE;
typedef struct TOUCH_STATE { typedef struct TOUCH_STATE {
int t0Id; int t0Id = 0;
int t1Id; int t1Id = 0;
bool t0Down; bool t0Down = false;
bool t1Down; bool t1Down = false;
float t0X; float t0X = 0.f;
float t0Y; float t0Y = 0.f;
float t1X; float t1X = 0.f;
float t1Y; float t1Y = 0.f;
} TOUCH_STATE; } TOUCH_STATE;
typedef struct JSL_AUTO_CALIBRATION {
float confidence = 0.f;
bool autoCalibrationEnabled = false;
bool isSteady = false;
} JSL_AUTO_CALIBRATION;
typedef struct JSL_SETTINGS {
int gyroSpace = 0;
int bodyColour = 0;
int lGripColour = 0;
int rGripColour = 0;
int buttonColour = 0;
int playerNumber = 0;
int controllerType = 0;
int splitType = 0;
bool isCalibrating = false;
bool autoCalibrationEnabled = false;
bool isConnected = false;
} JSL_SETTINGS;
extern "C" JOY_SHOCK_API int JslConnectDevices(); extern "C" JOY_SHOCK_API int JslConnectDevices();
extern "C" JOY_SHOCK_API int JslGetConnectedDeviceHandles(int* deviceHandleArray, int size); extern "C" JOY_SHOCK_API int JslGetConnectedDeviceHandles(int* deviceHandleArray, int size);
extern "C" JOY_SHOCK_API void JslDisconnectAndDisposeAll(); extern "C" JOY_SHOCK_API void JslDisconnectAndDisposeAll();
extern "C" JOY_SHOCK_API bool JslStillConnected(int deviceId);
// get buttons as bits in the following order, using North South East West to name face buttons to avoid ambiguity between Xbox and Nintendo layouts: // get buttons as bits in the following order, using North South East West to name face buttons to avoid ambiguity between Xbox and Nintendo layouts:
// 0x00001: up // 0x00001: up
@ -169,6 +190,15 @@ extern "C" JOY_SHOCK_API float JslGetGyroX(int deviceId);
extern "C" JOY_SHOCK_API float JslGetGyroY(int deviceId); extern "C" JOY_SHOCK_API float JslGetGyroY(int deviceId);
extern "C" JOY_SHOCK_API float JslGetGyroZ(int deviceId); extern "C" JOY_SHOCK_API float JslGetGyroZ(int deviceId);
// get accumulated average gyro since this function was last called or last flushed values
extern "C" JOY_SHOCK_API void JslGetAndFlushAccumulatedGyro(int deviceId, float& gyroX, float& gyroY, float& gyroZ);
// set gyro space. JslGetGyro*, JslGetAndFlushAccumulatedGyro, JslGetIMUState, and the IMU_STATEs reported in the callback functions will use one of 3 transformations:
// 0 = local space -> no transformation is done on gyro input
// 1 = world space -> gyro input is transformed based on the calculated gravity direction to account for the player's preferred controller orientation
// 2 = player space -> a simple combination of local and world space that is as adaptive as world space but is as robust as local space
extern "C" JOY_SHOCK_API void JslSetGyroSpace(int deviceId, int gyroSpace);
// get accelerometor // get accelerometor
extern "C" JOY_SHOCK_API float JslGetAccelX(int deviceId); extern "C" JOY_SHOCK_API float JslGetAccelX(int deviceId);
extern "C" JOY_SHOCK_API float JslGetAccelY(int deviceId); extern "C" JOY_SHOCK_API float JslGetAccelY(int deviceId);
@ -185,6 +215,7 @@ extern "C" JOY_SHOCK_API float JslGetTouchY(int deviceId, bool secondTouch = fal
extern "C" JOY_SHOCK_API float JslGetStickStep(int deviceId); extern "C" JOY_SHOCK_API float JslGetStickStep(int deviceId);
extern "C" JOY_SHOCK_API float JslGetTriggerStep(int deviceId); extern "C" JOY_SHOCK_API float JslGetTriggerStep(int deviceId);
extern "C" JOY_SHOCK_API float JslGetPollRate(int deviceId); extern "C" JOY_SHOCK_API float JslGetPollRate(int deviceId);
extern "C" JOY_SHOCK_API float JslGetTimeSinceLastUpdate(int deviceId);
// calibration // calibration
extern "C" JOY_SHOCK_API void JslResetContinuousCalibration(int deviceId); extern "C" JOY_SHOCK_API void JslResetContinuousCalibration(int deviceId);
@ -193,12 +224,19 @@ extern "C" JOY_SHOCK_API void JslPauseContinuousCalibration(int deviceId);
extern "C" JOY_SHOCK_API void JslSetAutomaticCalibration(int deviceId, bool enabled); extern "C" JOY_SHOCK_API void JslSetAutomaticCalibration(int deviceId, bool enabled);
extern "C" JOY_SHOCK_API void JslGetCalibrationOffset(int deviceId, float& xOffset, float& yOffset, float& zOffset); extern "C" JOY_SHOCK_API void JslGetCalibrationOffset(int deviceId, float& xOffset, float& yOffset, float& zOffset);
extern "C" JOY_SHOCK_API void JslSetCalibrationOffset(int deviceId, float xOffset, float yOffset, float zOffset); extern "C" JOY_SHOCK_API void JslSetCalibrationOffset(int deviceId, float xOffset, float yOffset, float zOffset);
extern "C" JOY_SHOCK_API JSL_AUTO_CALIBRATION JslGetAutoCalibrationStatus(int deviceId);
// this function will get called for each input event from each controller // this function will get called for each input event from each controller
extern "C" JOY_SHOCK_API void JslSetCallback(void(*callback)(int, JOY_SHOCK_STATE, JOY_SHOCK_STATE, IMU_STATE, IMU_STATE, float)); extern "C" JOY_SHOCK_API void JslSetCallback(void(*callback)(int, JOY_SHOCK_STATE, JOY_SHOCK_STATE, IMU_STATE, IMU_STATE, float));
// this function will get called for each input event, even if touch data didn't update // this function will get called for each input event, even if touch data didn't update
extern "C" JOY_SHOCK_API void JslSetTouchCallback(void(*callback)(int, TOUCH_STATE, TOUCH_STATE, float)); extern "C" JOY_SHOCK_API void JslSetTouchCallback(void(*callback)(int, TOUCH_STATE, TOUCH_STATE, float));
// this function will get called for each device when it is newly connected
extern "C" JOY_SHOCK_API void JslSetConnectCallback(void(*callback)(int));
// this function will get called for each device when it is disconnected
extern "C" JOY_SHOCK_API void JslSetDisconnectCallback(void(*callback)(int, bool));
// super-getter for reading a whole lot of state at once
extern "C" JOY_SHOCK_API JSL_SETTINGS JslGetControllerInfoAndSettings(int deviceId);
// what kind of controller is this? // what kind of controller is this?
extern "C" JOY_SHOCK_API int JslGetControllerType(int deviceId); extern "C" JOY_SHOCK_API int JslGetControllerType(int deviceId);
// is this a left, right, or full controller? // is this a left, right, or full controller?

View file

@ -1,17 +1,18 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: b8c465928f1784a3fac8dc3766f7201c guid: b8c465928f1784a3fac8dc3766f7201c
timeCreated: 1538230728
licenseType: Free
PluginImporter: PluginImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2
iconMap: {} iconMap: {}
executionOrder: {} executionOrder: {}
defineConstraints: []
isPreloaded: 0 isPreloaded: 0
isOverridable: 0 isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData: platformData:
- first: - first:
'': Any : Any
second: second:
enabled: 0 enabled: 0
settings: settings:
@ -77,7 +78,7 @@ PluginImporter:
second: second:
enabled: 1 enabled: 1
settings: settings:
CPU: x86_64 CPU: AnyCPU
- first: - first:
Standalone: LinuxUniversal Standalone: LinuxUniversal
second: second:

View file

@ -3,7 +3,7 @@
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>BuildMachineOSBuild</key> <key>BuildMachineOSBuild</key>
<string>18A391</string> <string>22D68</string>
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>English</string> <string>English</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
@ -31,16 +31,20 @@
<key>DTCompiler</key> <key>DTCompiler</key>
<string>com.apple.compilers.llvm.clang.1_0</string> <string>com.apple.compilers.llvm.clang.1_0</string>
<key>DTPlatformBuild</key> <key>DTPlatformBuild</key>
<string>10A255</string> <string>14C18</string>
<key>DTPlatformName</key>
<string>macosx</string>
<key>DTPlatformVersion</key> <key>DTPlatformVersion</key>
<string>GM</string> <string>13.1</string>
<key>DTSDKBuild</key> <key>DTSDKBuild</key>
<string>18A384</string> <string>22C55</string>
<key>DTSDKName</key> <key>DTSDKName</key>
<string>macosx10.14</string> <string>macosx13.1</string>
<key>DTXcode</key> <key>DTXcode</key>
<string>1000</string> <string>1420</string>
<key>DTXcodeBuild</key> <key>DTXcodeBuild</key>
<string>10A255</string> <string>14C18</string>
<key>LSMinimumSystemVersion</key>
<string>13.1</string>
</dict> </dict>
</plist> </plist>

View file

@ -0,0 +1,14 @@
fileFormatVersion: 2
<<<<<<<< HEAD:Assets/Plugins/StandaloneFileBrowser/Plugins/StandaloneFileBrowser.bundle/Contents/_CodeSignature.meta
guid: 7c3db81ca6b7837489ddd39d07d8a941
folderAsset: yes
DefaultImporter:
========
guid: e329403cfc5867042884e77dd4796d34
NativeFormatImporter:
>>>>>>>> release_1:Assets/Resources/Sprites/Games/Lockstep/Animations/Bach.controller.meta
externalObjects: {}
mainObjectFileID: 9100000
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,115 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>files</key>
<dict/>
<key>files2</key>
<dict/>
<key>rules</key>
<dict>
<key>^Resources/</key>
<true/>
<key>^Resources/.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^Resources/.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Resources/Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^version.plist$</key>
<true/>
</dict>
<key>rules2</key>
<dict>
<key>.*\.dSYM($|/)</key>
<dict>
<key>weight</key>
<real>11</real>
</dict>
<key>^(.*/)?\.DS_Store$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>2000</real>
</dict>
<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>
<dict>
<key>nested</key>
<true/>
<key>weight</key>
<real>10</real>
</dict>
<key>^.*</key>
<true/>
<key>^Info\.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^PkgInfo$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^Resources/</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
<key>^Resources/.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^Resources/.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Resources/Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^[^/]+$</key>
<dict>
<key>nested</key>
<true/>
<key>weight</key>
<real>10</real>
</dict>
<key>^embedded\.provisionprofile$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
<key>^version\.plist$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
</dict>
</dict>
</plist>

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 5905078a1ef7dab4fa302ee6555826c0
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -5,11 +5,14 @@ PluginImporter:
serializedVersion: 2 serializedVersion: 2
iconMap: {} iconMap: {}
executionOrder: {} executionOrder: {}
defineConstraints: []
isPreloaded: 0 isPreloaded: 0
isOverridable: 0 isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData: platformData:
- first: - first:
'': Any : Any
second: second:
enabled: 0 enabled: 0
settings: settings:
@ -61,7 +64,7 @@ PluginImporter:
second: second:
enabled: 0 enabled: 0
settings: settings:
CPU: x86_64 CPU: AnyCPU
- first: - first:
Standalone: LinuxUniversal Standalone: LinuxUniversal
second: second:

View file

@ -1,145 +1,130 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 7d459a96865cc4aaab657012c6dc4833 guid: 7d459a96865cc4aaab657012c6dc4833
timeCreated: 1491979494
licenseType: Pro
PluginImporter: PluginImporter:
externalObjects: {}
serializedVersion: 2 serializedVersion: 2
iconMap: {} iconMap: {}
executionOrder: {} executionOrder: {}
defineConstraints: []
isPreloaded: 0 isPreloaded: 0
isOverridable: 0 isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData: platformData:
data: - first:
first: : Any
'': Any second:
second: enabled: 0
enabled: 0 settings:
settings: Exclude Android: 1
Exclude Android: 1 Exclude Editor: 0
Exclude Editor: 0 Exclude Linux: 1
Exclude Linux: 1 Exclude Linux64: 1
Exclude Linux64: 1 Exclude LinuxUniversal: 1
Exclude LinuxUniversal: 1 Exclude OSXIntel: 1
Exclude OSXIntel: 1 Exclude OSXIntel64: 1
Exclude OSXIntel64: 1 Exclude OSXUniversal: 1
Exclude OSXUniversal: 1 Exclude WebGL: 1
Exclude WebGL: 1 Exclude Win: 0
Exclude Win: 0 Exclude Win64: 0
Exclude Win64: 0 Exclude iOS: 1
Exclude iOS: 1 - first:
data: : Editor
first: second:
'': Editor enabled: 0
second: settings:
enabled: 0 CPU: AnyCPU
settings: OS: AnyOS
CPU: AnyCPU - first:
OS: AnyOS Android: Android
data: second:
first: enabled: 0
Android: Android settings:
second: CPU: ARMv7
enabled: 0 - first:
settings: Any:
CPU: ARMv7 second:
data: enabled: 0
first: settings: {}
Any: - first:
second: Editor: Editor
enabled: 0 second:
settings: {} enabled: 1
data: settings:
first: DefaultValueInitialized: true
Editor: Editor - first:
second: Facebook: Win
enabled: 1 second:
settings: enabled: 0
DefaultValueInitialized: true settings:
data: CPU: AnyCPU
first: - first:
Facebook: Win Facebook: Win64
second: second:
enabled: 0 enabled: 0
settings: settings:
CPU: AnyCPU CPU: AnyCPU
data: - first:
first: Standalone: Linux
Facebook: Win64 second:
second: enabled: 0
enabled: 0 settings:
settings: CPU: None
CPU: AnyCPU - first:
data: Standalone: Linux64
first: second:
Standalone: Linux enabled: 0
second: settings:
enabled: 0 CPU: None
settings: - first:
CPU: None Standalone: LinuxUniversal
data: second:
first: enabled: 0
Standalone: Linux64 settings:
second: CPU: None
enabled: 0 - first:
settings: Standalone: OSXIntel
CPU: None second:
data: enabled: 0
first: settings:
Standalone: LinuxUniversal CPU: None
second: - first:
enabled: 0 Standalone: OSXIntel64
settings: second:
CPU: None enabled: 0
data: settings:
first: CPU: None
Standalone: OSXIntel - first:
second: Standalone: OSXUniversal
enabled: 0 second:
settings: enabled: 0
CPU: None settings:
data: CPU: None
first: - first:
Standalone: OSXIntel64 Standalone: Win
second: second:
enabled: 0 enabled: 1
settings: settings:
CPU: None CPU: AnyCPU
data: - first:
first: Standalone: Win64
Standalone: OSXUniversal second:
second: enabled: 1
enabled: 0 settings:
settings: CPU: AnyCPU
CPU: None - first:
data: Windows Store Apps: WindowsStoreApps
first: second:
Standalone: Win enabled: 0
second: settings:
enabled: 1 CPU: AnyCPU
settings: - first:
CPU: AnyCPU iPhone: iOS
data: second:
first: enabled: 0
Standalone: Win64 settings:
second: CompileFlags:
enabled: 1 FrameworkDependencies:
settings:
CPU: AnyCPU
data:
first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
data:
first:
iPhone: iOS
second:
enabled: 0
settings:
CompileFlags:
FrameworkDependencies:
userData: userData:
assetBundleName: assetBundleName:
assetBundleVariant: assetBundleVariant:

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -2,14 +2,15 @@
%TAG !u! tag:unity3d.com,2011: %TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000 --- !u!21 &2100000
Material: Material:
serializedVersion: 6 serializedVersion: 8
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0} m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0} m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0} m_PrefabAsset: {fileID: 0}
m_Name: ButtonSDFMaterial m_Name: ButtonSDFMaterial
m_Shader: {fileID: 4800000, guid: 574134bcfa99f7140a2cd7986bf57c25, type: 3} m_Shader: {fileID: 4800000, guid: 574134bcfa99f7140a2cd7986bf57c25, type: 3}
m_ShaderKeywords: m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4 m_LightmapFlags: 4
m_EnableInstancingVariants: 0 m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0 m_DoubleSidedGI: 0
@ -67,6 +68,7 @@ Material:
m_Texture: {fileID: 0} m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1} m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0} m_Offset: {x: 0, y: 0}
m_Ints: []
m_Floats: m_Floats:
- _Ambient: 0.5 - _Ambient: 0.5
- _Bevel: 0.5 - _Bevel: 0.5
@ -101,7 +103,7 @@ Material:
- _Mode: 0 - _Mode: 0
- _OcclusionStrength: 1 - _OcclusionStrength: 1
- _OffBright: 0.25 - _OffBright: 0.25
- _OutSmoothness: 0.075 - _OutSmoothness: 0.025
- _OutThickness: 0.6 - _OutThickness: 0.6
- _OutlineSoftness: 0 - _OutlineSoftness: 0
- _OutlineUVSpeedX: 0 - _OutlineUVSpeedX: 0
@ -118,7 +120,7 @@ Material:
- _ScaleY: 1 - _ScaleY: 1
- _ShaderFlags: 0 - _ShaderFlags: 0
- _Sharpness: 0 - _Sharpness: 0
- _Smoothness: 0.075 - _Smoothness: 0.025
- _SmoothnessTextureChannel: 0 - _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1 - _SpecularHighlights: 1
- _SpecularPower: 2 - _SpecularPower: 2

View file

@ -2,14 +2,15 @@
%TAG !u! tag:unity3d.com,2011: %TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000 --- !u!21 &2100000
Material: Material:
serializedVersion: 6 serializedVersion: 8
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0} m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0} m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0} m_PrefabAsset: {fileID: 0}
m_Name: UIControllerMaterial m_Name: UIControllerMaterial
m_Shader: {fileID: 4800000, guid: cfe42e963af2b934bb427536d4d29068, type: 3} m_Shader: {fileID: 4800000, guid: cfe42e963af2b934bb427536d4d29068, type: 3}
m_ShaderKeywords: m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4 m_LightmapFlags: 4
m_EnableInstancingVariants: 0 m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0 m_DoubleSidedGI: 0
@ -55,6 +56,7 @@ Material:
m_Texture: {fileID: 0} m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1} m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0} m_Offset: {x: 0, y: 0}
m_Ints: []
m_Floats: m_Floats:
- _BumpScale: 1 - _BumpScale: 1
- _ColorMask: 15 - _ColorMask: 15
@ -81,11 +83,11 @@ Material:
- _ZWrite: 1 - _ZWrite: 1
m_Colors: m_Colors:
- _BodyColor: {r: 0.95686275, g: 0.95686275, b: 0.95686275, a: 1} - _BodyColor: {r: 0.95686275, g: 0.95686275, b: 0.95686275, a: 1}
- _BtnColor: {r: 1, g: 1, b: 1, a: 1} - _BtnColor: {r: 0.11764706, g: 0.039215688, b: 0.039215688, a: 1}
- _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767} - _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767}
- _Color: {r: 1, g: 1, b: 1, a: 1} - _Color: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1} - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _LGripColor: {r: 1, g: 1, b: 1, a: 1} - _LGripColor: {r: 0.18431373, g: 0.20784314, b: 0.22745098, a: 1}
- _RGripColor: {r: 1, g: 1, b: 1, a: 1} - _RGripColor: {r: 0.18431373, g: 0.20784314, b: 0.22745098, a: 1}
- _Rect: {r: 0, g: 0, b: 1, a: 1} - _Rect: {r: 0, g: 0, b: 1, a: 1}
m_BuildTextureStacks: [] m_BuildTextureStacks: []

View file

@ -235,7 +235,7 @@ namespace HeavenStudio.Games.Scripts_CropStomp
stompedBeat = cond.songPositionInBeatsAsDouble; stompedBeat = cond.songPositionInBeatsAsDouble;
landBeat = targetBeat + (float)cond.SecsToBeats(Minigame.EndTime()-1, cond.GetBpmAtBeat(targetBeat)); landBeat = targetBeat + (float)cond.SecsToBeats(Minigame.NgLateTime()-1, cond.GetBpmAtBeat(targetBeat));
if (autoTriggered) if (autoTriggered)
{ {

View file

@ -201,7 +201,7 @@ namespace HeavenStudio.Games.Scripts_KarateMan
switch (forceHand) switch (forceHand)
{ {
case 0: case 0:
if (cond.songPositionInBeatsAsDouble - lastPunchTime < 0.25f + (Minigame.LateTime() - 1f)) if (cond.songPositionInBeatsAsDouble - lastPunchTime < 0.25f + (Minigame.JustLateTime() - 1f))
{ {
lastPunchTime = double.MinValue; lastPunchTime = double.MinValue;
anim.DoScaledAnimationAsync("Straight", 0.5f); anim.DoScaledAnimationAsync("Straight", 0.5f);

View file

@ -180,8 +180,8 @@ namespace HeavenStudio.Games.Scripts_KarateMan
switch (type) switch (type)
{ {
case ItemType.ComboPot1: case ItemType.ComboPot1:
OnHit = KarateMan.instance.ScheduleInput(startBeat, 1f, InputType.STANDARD_ALT_DOWN, ComboStartJustOrNg, ComboStartThrough, ComboStartOut); OnHit = KarateMan.instance.ScheduleInput(startBeat, 1f, InputType.STANDARD_ALT_DOWN, ComboStartJustOrNg, ComboStartThrough, ComboStartOut, CanCombo);
OnHitWrongAction = KarateMan.instance.ScheduleUserInput(startBeat, 1f, InputType.STANDARD_DOWN | InputType.DIRECTION_DOWN, ComboStartWrongAction, ComboStartOut, ComboStartOut); OnHitWrongAction = KarateMan.instance.ScheduleUserInput(startBeat, 1f, InputType.STANDARD_DOWN | InputType.DIRECTION_DOWN, ComboStartWrongAction, ComboStartOut, ComboStartOut, CanHit);
path = 1; path = 1;
break; break;
case ItemType.ComboPot2: case ItemType.ComboPot2:
@ -202,28 +202,24 @@ namespace HeavenStudio.Games.Scripts_KarateMan
BeatAction.New(gameObject, new List<BeatAction.Action>() { new BeatAction.Action(startBeat + 1f, delegate { JoeComboSequence(); }) }); BeatAction.New(gameObject, new List<BeatAction.Action>() { new BeatAction.Action(startBeat + 1f, delegate { JoeComboSequence(); }) });
break; break;
case ItemType.ComboBarrel: case ItemType.ComboBarrel:
//check for button release OnHit = KarateMan.instance.ScheduleInput(startBeat, 1f, InputType.STANDARD_ALT_UP, ComboEndJustOrNg, ComboEndThrough, ComboEndOut, CanComboEnd);
OnHit = KarateMan.instance.ScheduleInput(startBeat, 1f, InputType.STANDARD_ALT_UP, ComboEndJustOrNg, ComboEndThrough, ComboEndOut);
//button presses
KarateMan.instance.ScheduleUserInput(startBeat, 1f, InputType.STANDARD_DOWN | InputType.DIRECTION_DOWN, ComboEndWrongAction, ItemOut, ItemOut);
KarateMan.instance.ScheduleUserInput(startBeat, 1f, InputType.STANDARD_ALT_DOWN, ComboEndWrongActionAlt, ItemOut, ItemOut);
path = 5; path = 5;
break; break;
case ItemType.KickBarrel: case ItemType.KickBarrel:
OnHit = KarateMan.instance.ScheduleInput(startBeat, 1f, InputType.STANDARD_DOWN | InputType.DIRECTION_DOWN, KickChargeJustOrNg, ItemThrough, ItemOut); OnHit = KarateMan.instance.ScheduleInput(startBeat, 1f, InputType.STANDARD_DOWN | InputType.DIRECTION_DOWN, KickChargeJustOrNg, ItemThrough, ItemOut, CanCombo);
OnHitWrongAction = KarateMan.instance.ScheduleUserInput(startBeat, 1f, InputType.STANDARD_ALT_DOWN, ItemWrongAction, ItemOut, ItemOut); OnHitWrongAction = KarateMan.instance.ScheduleUserInput(startBeat, 1f, InputType.STANDARD_ALT_DOWN, ItemWrongAction, ItemOut, ItemOut, CanCombo);
path = 1; path = 1;
comboId = -1; comboId = -1;
break; break;
case ItemType.KickBomb: case ItemType.KickBomb:
OnHit = KarateMan.instance.ScheduleInput(startBeat, 0.75f, InputType.STANDARD_UP | InputType.DIRECTION_UP, KickJustOrNg, KickThrough, KickOut); OnHit = KarateMan.instance.ScheduleInput(startBeat, 0.75f, InputType.STANDARD_UP | InputType.DIRECTION_UP, KickJustOrNg, KickThrough, KickOut, CanKick);
CurrentCurve = ItemCurves[6]; CurrentCurve = ItemCurves[6];
curveTargetBeat = 2 * 0.75f; curveTargetBeat = 2 * 0.75f;
path = 1; path = 1;
comboId = -1; comboId = -1;
break; break;
case ItemType.KickBall: case ItemType.KickBall:
OnHit = KarateMan.instance.ScheduleInput(startBeat, 0.75f, InputType.STANDARD_UP | InputType.DIRECTION_UP, KickJustOrNg, KickThrough, KickOut); OnHit = KarateMan.instance.ScheduleInput(startBeat, 0.75f, InputType.STANDARD_UP | InputType.DIRECTION_UP, KickJustOrNg, KickThrough, KickOut, CanKick);
CurrentCurve = ItemCurves[6]; CurrentCurve = ItemCurves[6];
curveTargetBeat = 2 * 0.75f; curveTargetBeat = 2 * 0.75f;
path = 1; path = 1;
@ -237,14 +233,14 @@ namespace HeavenStudio.Games.Scripts_KarateMan
comboId = -1; comboId = -1;
break; break;
case ItemType.Bomb: case ItemType.Bomb:
OnHit = KarateMan.instance.ScheduleInput(startBeat, 1f, InputType.STANDARD_DOWN | InputType.DIRECTION_DOWN, ItemJustOrNg, ItemThrough, ItemOut); OnHit = KarateMan.instance.ScheduleInput(startBeat, 1f, InputType.STANDARD_DOWN | InputType.DIRECTION_DOWN, ItemJustOrNg, ItemThrough, ItemOut, CanHit);
OnHitWrongAction = KarateMan.instance.ScheduleUserInput(startBeat, 1f, InputType.STANDARD_ALT_DOWN, ItemWrongAction, ItemOut, ItemOut); OnHitWrongAction = KarateMan.instance.ScheduleUserInput(startBeat, 1f, InputType.STANDARD_ALT_DOWN, ItemWrongAction, ItemOut, ItemOut, CanHit);
path = 1; path = 1;
comboId = -1; comboId = -1;
break; break;
default: default:
OnHit = KarateMan.instance.ScheduleInput(startBeat, 1f, InputType.STANDARD_DOWN | InputType.DIRECTION_DOWN, ItemJustOrNg, ItemThrough, ItemOut); OnHit = KarateMan.instance.ScheduleInput(startBeat, 1f, InputType.STANDARD_DOWN | InputType.DIRECTION_DOWN, ItemJustOrNg, ItemThrough, ItemOut, CanHit);
OnHitWrongAction = KarateMan.instance.ScheduleUserInput(startBeat, 1f, InputType.STANDARD_ALT_DOWN, ItemWrongAction, ItemOut, ItemOut); OnHitWrongAction = KarateMan.instance.ScheduleUserInput(startBeat, 1f, InputType.STANDARD_ALT_DOWN, ItemWrongAction, ItemOut, ItemOut, CanHit);
path = 1; path = 1;
comboId = -1; comboId = -1;
break; break;
@ -726,53 +722,55 @@ namespace HeavenStudio.Games.Scripts_KarateMan
}); });
} }
public bool CanHit()
{
var joe = KarateMan.instance.Joe;
return status == FlyStatus.Fly && !(joe.inCombo || joe.inNuriLock);
}
public void ItemJustOrNg(PlayerActionEvent caller, float state) public void ItemJustOrNg(PlayerActionEvent caller, float state)
{ {
if (GameManager.instance.currentGame != "karateman") return; if (GameManager.instance.currentGame != "karateman") return;
var joe = KarateMan.instance.Joe; var joe = KarateMan.instance.Joe;
if (status == FlyStatus.Fly && !(joe.inCombo || joe.inNuriLock)) { if (state <= -1f || state >= 1f) {
if (state <= -1f || state >= 1f) { bool straight = joe.Punch(ItemPunchHand());
bool straight = joe.Punch(ItemPunchHand()); startBeat = Conductor.instance.songPositionInBeatsAsDouble;
startBeat = Conductor.instance.songPositionInBeatsAsDouble; CurrentCurve = ItemCurves[6];
CurrentCurve = ItemCurves[6]; curveTargetBeat = 1f;
curveTargetBeat = 1f; SoundByte.PlayOneShot("miss");
SoundByte.PlayOneShot("miss"); status = FlyStatus.NG;
status = FlyStatus.NG;
joe.SetFaceExpression((int) KarateMan.KarateManFaces.Sad); joe.SetFaceExpression((int) KarateMan.KarateManFaces.Sad);
BeatAction.New(joe.gameObject, new List<BeatAction.Action>() BeatAction.New(joe.gameObject, new List<BeatAction.Action>()
{ {
new BeatAction.Action(startBeat + 2f, delegate { new BeatAction.Action(startBeat + 2f, delegate {
joe.SetFaceExpression((int) KarateMan.KarateManFaces.Normal); joe.SetFaceExpression((int) KarateMan.KarateManFaces.Normal);
}), }),
}); });
KarateMan.instance.Nori.DoNG(); KarateMan.instance.Nori.DoNG();
} }
else { else {
if (KarateMan.instance.IsNoriActive) if (KarateMan.instance.IsNoriActive)
{ {
if (ItemNeedNori() && KarateMan.instance.NoriPerformance < 0.6f) if (ItemNeedNori() && KarateMan.instance.NoriPerformance < 0.6f)
{ {
CreateHitMark(false); CreateHitMark(false);
startBeat = Conductor.instance.songPositionInBeatsAsDouble; startBeat = Conductor.instance.songPositionInBeatsAsDouble;
status = FlyStatus.HitWeak; status = FlyStatus.HitWeak;
SoundByte.PlayOneShotGame("karateman/hitNoNori", forcePlay: true); SoundByte.PlayOneShotGame("karateman/hitNoNori", forcePlay: true);
joe.Punch(3); joe.Punch(3);
transform.rotation = Quaternion.Euler(0, 0, transform.rotation.eulerAngles.z - 30f); transform.rotation = Quaternion.Euler(0, 0, transform.rotation.eulerAngles.z - 30f);
KarateMan.instance.Nori.DoNG(); KarateMan.instance.Nori.DoNG();
return; return;
} }
} }
bool straight = joe.Punch(ItemPunchHand()); bool straight = joe.Punch(ItemPunchHand());
DoHitExpression(startBeat + 1f); DoHitExpression(startBeat + 1f);
ItemHitEffect(straight); ItemHitEffect(straight);
status = FlyStatus.Hit; status = FlyStatus.Hit;
KarateMan.instance.Nori.DoHit(); KarateMan.instance.Nori.DoHit();
}
} }
OnHit.CanHit(false);
OnHitWrongAction.CanHit(false);
} }
public void ItemWrongAction(PlayerActionEvent caller, float state) public void ItemWrongAction(PlayerActionEvent caller, float state)
@ -782,32 +780,28 @@ namespace HeavenStudio.Games.Scripts_KarateMan
//hitting a normal object with the alt input //hitting a normal object with the alt input
//WHEN SCORING THIS IS A MISS //WHEN SCORING THIS IS A MISS
var joe = KarateMan.instance.Joe; var joe = KarateMan.instance.Joe;
if (status == FlyStatus.Fly && !(joe.inCombo || joe.inNuriLock)) { joe.ForceFailCombo(Conductor.instance.songPositionInBeatsAsDouble);
joe.ForceFailCombo(Conductor.instance.songPositionInBeatsAsDouble); if (state <= -1f || state >= 1f) {
if (state <= -1f || state >= 1f) { startBeat = Conductor.instance.songPositionInBeatsAsDouble;
startBeat = Conductor.instance.songPositionInBeatsAsDouble; CurrentCurve = ItemCurves[6];
CurrentCurve = ItemCurves[6]; curveTargetBeat = 1f;
curveTargetBeat = 1f; SoundByte.PlayOneShot("miss");
SoundByte.PlayOneShot("miss"); status = FlyStatus.NG;
status = FlyStatus.NG;
}
else {
ItemHitEffect();
}
BeatAction.New(joe.gameObject, new List<BeatAction.Action>()
{
new BeatAction.Action(startBeat + 4f, delegate {
joe.SetFaceExpression((int) KarateMan.KarateManFaces.Sad);
}),
new BeatAction.Action(startBeat + 6f, delegate {
joe.SetFaceExpression((int) KarateMan.KarateManFaces.Normal);
}),
});
KarateMan.instance.Nori.DoThrough();
} }
OnHit.CanHit(false); else {
OnHitWrongAction.CanHit(false); ItemHitEffect();
}
BeatAction.New(joe.gameObject, new List<BeatAction.Action>()
{
new BeatAction.Action(startBeat + 4f, delegate {
joe.SetFaceExpression((int) KarateMan.KarateManFaces.Sad);
}),
new BeatAction.Action(startBeat + 6f, delegate {
joe.SetFaceExpression((int) KarateMan.KarateManFaces.Normal);
}),
});
KarateMan.instance.Nori.DoThrough();
} }
public void ItemOut(PlayerActionEvent caller) {} public void ItemOut(PlayerActionEvent caller) {}
@ -833,31 +827,33 @@ namespace HeavenStudio.Games.Scripts_KarateMan
OnHitWrongAction.CanHit(false); OnHitWrongAction.CanHit(false);
} }
public bool CanCombo()
{
var joe = KarateMan.instance.Joe;
return status == FlyStatus.Fly && !(joe.inKick || joe.wantKick || joe.inCombo || joe.inNuriLock);
}
public void ComboStartJustOrNg(PlayerActionEvent caller, float state) public void ComboStartJustOrNg(PlayerActionEvent caller, float state)
{ {
if (GameManager.instance.currentGame != "karateman") return; if (GameManager.instance.currentGame != "karateman") return;
var joe = KarateMan.instance.Joe; var joe = KarateMan.instance.Joe;
if (status == FlyStatus.Fly && !(joe.inKick || joe.wantKick || joe.inCombo || joe.inNuriLock)) { joe.inCombo = true;
joe.inCombo = true; joe.Punch(1);
joe.Punch(1); joe.SetComboId(comboId);
joe.SetComboId(comboId); joe.SetShouldComboId(comboId);
joe.SetShouldComboId(comboId); if (state <= -1f || state >= 1f) {
if (state <= -1f || state >= 1f) { startBeat = Conductor.instance.songPositionInBeatsAsDouble;
startBeat = Conductor.instance.songPositionInBeatsAsDouble; CurrentCurve = ItemCurves[6];
CurrentCurve = ItemCurves[6]; curveTargetBeat = 1f;
curveTargetBeat = 1f; SoundByte.PlayOneShot("miss");
SoundByte.PlayOneShot("miss"); status = FlyStatus.NG;
status = FlyStatus.NG;
KarateMan.instance.Nori.DoNG(); KarateMan.instance.Nori.DoNG();
}
else {
ItemHitEffect();
KarateMan.instance.Nori.DoHit();
}
} }
OnHit.CanHit(false); else {
OnHitWrongAction.CanHit(false); ItemHitEffect();
KarateMan.instance.Nori.DoHit();
}
} }
public void ComboStartOut(PlayerActionEvent caller) {} public void ComboStartOut(PlayerActionEvent caller) {}
@ -888,59 +884,58 @@ namespace HeavenStudio.Games.Scripts_KarateMan
//hitting a combo start with the normal input //hitting a combo start with the normal input
//WHEN SCORING THIS IS A MISS //WHEN SCORING THIS IS A MISS
var joe = KarateMan.instance.Joe; var joe = KarateMan.instance.Joe;
if (status == FlyStatus.Fly && !(joe.inCombo || joe.inNuriLock)) { bool straight = joe.Punch(ItemPunchHand());
bool straight = joe.Punch(ItemPunchHand()); if (state <= -1f || state >= 1f) {
if (state <= -1f || state >= 1f) { startBeat = Conductor.instance.songPositionInBeatsAsDouble;
startBeat = Conductor.instance.songPositionInBeatsAsDouble; CurrentCurve = ItemCurves[6];
CurrentCurve = ItemCurves[6]; curveTargetBeat = 1f;
curveTargetBeat = 1f; SoundByte.PlayOneShot("miss");
SoundByte.PlayOneShot("miss"); status = FlyStatus.NG;
status = FlyStatus.NG;
}
else {
ItemHitEffect(straight);
}
KarateMan.instance.Nori.DoThrough();
} }
OnHit.CanHit(false); else {
OnHitWrongAction.CanHit(false); ItemHitEffect(straight);
}
KarateMan.instance.Nori.DoThrough();
}
public bool CanComboEnd()
{
var joe = KarateMan.instance.Joe;
return status == FlyStatus.Fly && joe.inCombo && joe.GetComboId() == comboId;
} }
public void ComboEndJustOrNg(PlayerActionEvent caller, float state) public void ComboEndJustOrNg(PlayerActionEvent caller, float state)
{ {
if (GameManager.instance.currentGame != "karateman") return; if (GameManager.instance.currentGame != "karateman") return;
var joe = KarateMan.instance.Joe; var joe = KarateMan.instance.Joe;
if (status == FlyStatus.Fly && joe.inCombo && joe.GetComboId() == comboId) { joe.inCombo = false;
joe.inCombo = false; joe.SetComboId(-1);
joe.SetComboId(-1); joe.SetShouldComboId(-1);
joe.SetShouldComboId(-1); joe.ComboSequence(3);
joe.ComboSequence(3); if (state <= -1f || state >= 1f) {
if (state <= -1f || state >= 1f) { startBeat = Conductor.instance.songPositionInBeatsAsDouble;
startBeat = Conductor.instance.songPositionInBeatsAsDouble; CurrentCurve = ItemCurves[5];
CurrentCurve = ItemCurves[5]; curveTargetBeat = 1f;
curveTargetBeat = 1f; SoundByte.PlayOneShot("miss");
SoundByte.PlayOneShot("miss"); status = FlyStatus.NG;
status = FlyStatus.NG;
BeatAction.New(joe.gameObject, new List<BeatAction.Action>() BeatAction.New(joe.gameObject, new List<BeatAction.Action>()
{ {
new BeatAction.Action(startBeat + 2f, delegate { new BeatAction.Action(startBeat + 2f, delegate {
joe.SetFaceExpression((int) KarateMan.KarateManFaces.Sad); joe.SetFaceExpression((int) KarateMan.KarateManFaces.Sad);
}), }),
new BeatAction.Action(startBeat + 6f, delegate { new BeatAction.Action(startBeat + 6f, delegate {
joe.SetFaceExpression((int) KarateMan.KarateManFaces.Normal); joe.SetFaceExpression((int) KarateMan.KarateManFaces.Normal);
}), }),
}); });
KarateMan.instance.Nori.DoNG(); KarateMan.instance.Nori.DoNG();
} }
else { else {
DoHitExpression(startBeat + 1.5f); DoHitExpression(startBeat + 1.5f);
ItemHitEffect(); ItemHitEffect();
KarateMan.instance.Nori.DoHit(); KarateMan.instance.Nori.DoHit();
}
} }
OnHit.CanHit(false);
} }
public void ComboEndOut(PlayerActionEvent caller) { public void ComboEndOut(PlayerActionEvent caller) {
@ -998,51 +993,34 @@ namespace HeavenStudio.Games.Scripts_KarateMan
OnHit.CanHit(false); OnHit.CanHit(false);
} }
public void ComboEndWrongAction(PlayerActionEvent caller, float state)
{
if (GameManager.instance.currentGame != "karateman") return;
if (!(KarateMan.instance.Joe.inCombo || KarateMan.instance.Joe.inNuriLock))
KarateMan.instance.Joe.Punch(1);
}
public void ComboEndWrongActionAlt(PlayerActionEvent caller, float state)
{
if (GameManager.instance.currentGame != "karateman") return;
if (KarateMan.IsComboEnable && !(KarateMan.instance.Joe.inCombo || KarateMan.instance.Joe.inNuriLock))
KarateMan.instance.Joe.ForceFailCombo(Conductor.instance.songPositionInBeatsAsDouble);
}
public void KickChargeJustOrNg(PlayerActionEvent caller, float state) public void KickChargeJustOrNg(PlayerActionEvent caller, float state)
{ {
if (GameManager.instance.currentGame != "karateman") return; if (GameManager.instance.currentGame != "karateman") return;
var joe = KarateMan.instance.Joe; var joe = KarateMan.instance.Joe;
if (status == FlyStatus.Fly && !(joe.inKick || joe.wantKick || joe.inCombo || joe.inNuriLock)) {
joe.Punch(ItemPunchHand());
if (state <= -1f || state >= 1f) {
startBeat = Conductor.instance.songPositionInBeatsAsDouble;
CurrentCurve = ItemCurves[6];
curveTargetBeat = 1f;
SoundByte.PlayOneShot("miss");
status = FlyStatus.NG;
joe.SetFaceExpression((int) KarateMan.KarateManFaces.Sad); joe.Punch(ItemPunchHand());
BeatAction.New(joe.gameObject, new List<BeatAction.Action>() if (state <= -1f || state >= 1f) {
{ startBeat = Conductor.instance.songPositionInBeatsAsDouble;
new BeatAction.Action(startBeat + 2f, delegate { CurrentCurve = ItemCurves[6];
joe.SetFaceExpression((int) KarateMan.KarateManFaces.Normal); curveTargetBeat = 1f;
}), SoundByte.PlayOneShot("miss");
}); status = FlyStatus.NG;
KarateMan.instance.Nori.DoNG();
} joe.SetFaceExpression((int) KarateMan.KarateManFaces.Sad);
else { BeatAction.New(joe.gameObject, new List<BeatAction.Action>()
joe.StartKickCharge(startBeat + 1.25f); {
ItemHitEffect(); new BeatAction.Action(startBeat + 2f, delegate {
status = FlyStatus.Hit; joe.SetFaceExpression((int) KarateMan.KarateManFaces.Normal);
KarateMan.instance.Nori.DoHit(); }),
} });
KarateMan.instance.Nori.DoNG();
}
else {
joe.StartKickCharge(startBeat + 1.25f);
ItemHitEffect();
status = FlyStatus.Hit;
KarateMan.instance.Nori.DoHit();
} }
OnHit.CanHit(false);
OnHitWrongAction.CanHit(false);
} }
public void KickChargeOut(PlayerActionEvent caller) {} public void KickChargeOut(PlayerActionEvent caller) {}
@ -1068,44 +1046,48 @@ namespace HeavenStudio.Games.Scripts_KarateMan
OnHitWrongAction.CanHit(false); OnHitWrongAction.CanHit(false);
} }
public bool CanKick()
{
var joe = KarateMan.instance.Joe;
return status == FlyStatus.Fly && joe.inKick;
}
public void KickJustOrNg(PlayerActionEvent caller, float state) public void KickJustOrNg(PlayerActionEvent caller, float state)
{ {
if (GameManager.instance.currentGame != "karateman") return; if (GameManager.instance.currentGame != "karateman") return;
var joe = KarateMan.instance.Joe; var joe = KarateMan.instance.Joe;
if (status == FlyStatus.Fly && joe.inKick) {
joe.Kick(Conductor.instance.songPositionInBeatsAsDouble);
if (state <= -1f || state >= 1f) {
startBeat = Conductor.instance.songPositionInBeatsAsDouble;
CurrentCurve = ItemCurves[8];
curveTargetBeat = 1f;
SoundByte.PlayOneShot("miss");
status = FlyStatus.NG;
BeatAction.New(joe.gameObject, new List<BeatAction.Action>() joe.Kick(Conductor.instance.songPositionInBeatsAsDouble);
{ if (state <= -1f || state >= 1f) {
new BeatAction.Action(startBeat + 1.25f, delegate { startBeat = Conductor.instance.songPositionInBeatsAsDouble;
joe.SetFaceExpression((int) KarateMan.KarateManFaces.Sad); CurrentCurve = ItemCurves[8];
}), curveTargetBeat = 1f;
new BeatAction.Action(startBeat + 4.25f, delegate { SoundByte.PlayOneShot("miss");
joe.SetFaceExpression((int) KarateMan.KarateManFaces.Normal); status = FlyStatus.NG;
}),
});
KarateMan.instance.Nori.DoNG(); BeatAction.New(joe.gameObject, new List<BeatAction.Action>()
if (type == ItemType.KickBomb) {
joe.RemoveBombGlow(startBeat + 0.75f); new BeatAction.Action(startBeat + 1.25f, delegate {
} joe.SetFaceExpression((int) KarateMan.KarateManFaces.Sad);
else { }),
DoHitExpression(startBeat + 2f); new BeatAction.Action(startBeat + 4.25f, delegate {
ItemHitEffect(); joe.SetFaceExpression((int) KarateMan.KarateManFaces.Normal);
status = FlyStatus.Hit; }),
CurrentCurve = ItemCurves[7]; });
startBeat = Conductor.instance.songPositionInBeatsAsDouble;
curveTargetBeat = 3f; KarateMan.instance.Nori.DoNG();
KarateMan.instance.Nori.DoHit(); if (type == ItemType.KickBomb)
} joe.RemoveBombGlow(startBeat + 0.75f);
}
else {
DoHitExpression(startBeat + 2f);
ItemHitEffect();
status = FlyStatus.Hit;
CurrentCurve = ItemCurves[7];
startBeat = Conductor.instance.songPositionInBeatsAsDouble;
curveTargetBeat = 3f;
KarateMan.instance.Nori.DoHit();
} }
OnHit.CanHit(false);
} }
public void KickOut(PlayerActionEvent caller) {} public void KickOut(PlayerActionEvent caller) {}

View file

@ -9,7 +9,7 @@ namespace HeavenStudio.Games
{ {
public class Minigame : MonoBehaviour public class Minigame : MonoBehaviour
{ {
public static double earlyTime = 0.075f, perfectTime = 0.06f, aceEarlyTime = 0.01f, aceLateTime = 0.01f, lateTime = 0.06f, endTime = 0.075f; public static double ngEarlyTime = 0.075f, justEarlyTime = 0.06f, aceEarlyTime = 0.01f, aceLateTime = 0.01f, justLateTime = 0.06f, ngLateTime = 0.075f;
public static float rankHiThreshold = 0.8f, rankOkThreshold = 0.6f; public static float rankHiThreshold = 0.8f, rankOkThreshold = 0.6f;
[SerializeField] public SoundSequence.SequenceKeyValue[] SoundSequences; [SerializeField] public SoundSequence.SequenceKeyValue[] SoundSequences;
@ -45,7 +45,9 @@ namespace HeavenStudio.Games
InputType inputType, InputType inputType,
PlayerActionEvent.ActionEventCallbackState OnHit, PlayerActionEvent.ActionEventCallbackState OnHit,
PlayerActionEvent.ActionEventCallback OnMiss, PlayerActionEvent.ActionEventCallback OnMiss,
PlayerActionEvent.ActionEventCallback OnBlank) PlayerActionEvent.ActionEventCallback OnBlank,
PlayerActionEvent.ActionEventHittableQuery HittableQuery = null
)
{ {
GameObject evtObj = new GameObject("ActionEvent" + (startBeat+timer)); GameObject evtObj = new GameObject("ActionEvent" + (startBeat+timer));
@ -59,6 +61,7 @@ namespace HeavenStudio.Games
evt.OnHit = OnHit; evt.OnHit = OnHit;
evt.OnMiss = OnMiss; evt.OnMiss = OnMiss;
evt.OnBlank = OnBlank; evt.OnBlank = OnBlank;
evt.IsHittable = HittableQuery;
evt.OnDestroy = RemoveScheduledInput; evt.OnDestroy = RemoveScheduledInput;
@ -91,15 +94,14 @@ namespace HeavenStudio.Games
InputType inputType, InputType inputType,
PlayerActionEvent.ActionEventCallbackState OnHit, PlayerActionEvent.ActionEventCallbackState OnHit,
PlayerActionEvent.ActionEventCallback OnMiss, PlayerActionEvent.ActionEventCallback OnMiss,
PlayerActionEvent.ActionEventCallback OnBlank) PlayerActionEvent.ActionEventCallback OnBlank,
PlayerActionEvent.ActionEventHittableQuery HittableQuery = null)
{ {
PlayerActionEvent evt = ScheduleInput(startBeat, timer, inputType, OnHit, OnMiss, OnBlank); PlayerActionEvent evt = ScheduleInput(startBeat, timer, inputType, OnHit, OnMiss, OnBlank, HittableQuery);
evt.noAutoplay = true; evt.noAutoplay = true;
return evt; return evt;
} }
//Clean up method used whenever a PlayerActionEvent has finished //Clean up method used whenever a PlayerActionEvent has finished
public void RemoveScheduledInput(PlayerActionEvent evt) public void RemoveScheduledInput(PlayerActionEvent evt)
{ {
@ -151,49 +153,36 @@ namespace HeavenStudio.Games
} }
// now should fix the fast bpm problem // now should fix the fast bpm problem
public static double EarlyTime() public static double NgEarlyTime()
{ {
return 1f - earlyTime; return 1f - ngEarlyTime;
} }
public static double PerfectTime() public static double JustEarlyTime()
{ {
return 1f - perfectTime; return 1f - justEarlyTime;
} }
public static double LateTime() public static double JustLateTime()
{ {
return 1f + lateTime; return 1f + justLateTime;
} }
public static double EndTime() public static double NgLateTime()
{ {
return 1f + endTime; return 1f + ngLateTime;
} }
public static double AceStartTime() public static double AceEarlyTime()
{ {
return 1f - aceEarlyTime; return 1f - aceEarlyTime;
} }
public static double AceEndTime() public static double AceLateTime()
{ {
return 1f + aceLateTime; return 1f + aceLateTime;
} }
// DEPRECATED: scales timing windows to the BPM in an ""intelligent"" manner
// only left for historical reasons
static float ScaleTimingMargin(float f)
{
float bpm = Conductor.instance.songBpm * Conductor.instance.musicSource.pitch;
float a = bpm / 120f;
float b = (Mathf.Log(a) + 2f) * 0.5f;
float r = Mathf.Lerp(a, b, 0.25f);
return r * f;
}
public int firstEnable = 0;
public virtual void OnGameSwitch(double beat) public virtual void OnGameSwitch(double beat)
{ {
//Below is a template that can be used for handling previous entities. //Below is a template that can be used for handling previous entities.
@ -263,7 +252,7 @@ namespace HeavenStudio.Games
public void ScoreMiss(double weight = 1f) public void ScoreMiss(double weight = 1f)
{ {
GameManager.instance.ScoreInputAccuracy(0, true, EndTime(), weight, false); GameManager.instance.ScoreInputAccuracy(0, true, NgLateTime(), weight, false);
if (weight > 0) if (weight > 0)
{ {
GoForAPerfect.instance.Miss(); GoForAPerfect.instance.Miss();

View file

@ -244,9 +244,14 @@ namespace HeavenStudio.Games.Scripts_PajamaParty
} }
// jumping cues (timings for both are the same) // jumping cues (timings for both are the same)
public bool CanJump()
{
return canJump;
}
public void ScheduleJump(double beat) public void ScheduleJump(double beat)
{ {
PajamaParty.instance.ScheduleInput(beat, 2f, InputType.STANDARD_DOWN, JumpJustOrNg, JumpThrough, JumpOut); PajamaParty.instance.ScheduleInput(beat, 2f, InputType.STANDARD_DOWN, JumpJustOrNg, JumpThrough, JumpOut, CanJump);
} }
public void JumpJustOrNg(PlayerActionEvent caller, float state) public void JumpJustOrNg(PlayerActionEvent caller, float state)
@ -284,7 +289,7 @@ namespace HeavenStudio.Games.Scripts_PajamaParty
public void ScheduleThrow(double beat) public void ScheduleThrow(double beat)
{ {
PajamaParty.instance.ScheduleInput(beat, 2f, InputType.STANDARD_ALT_DOWN, ChargeJustOrNg, ThrowThrough, JumpOut); PajamaParty.instance.ScheduleInput(beat, 2f, InputType.STANDARD_ALT_DOWN, ChargeJustOrNg, ThrowThrough, JumpOut);
PajamaParty.instance.ScheduleInput(beat, 3f, InputType.STANDARD_ALT_UP, ThrowJustOrNg, ThrowThrough, JumpOut); PajamaParty.instance.ScheduleInput(beat, 3f, InputType.STANDARD_ALT_UP, ThrowJustOrNg, ThrowThrough, JumpOut, CanThrow);
} }
public void ChargeJustOrNg(PlayerActionEvent caller, float state) { public void ChargeJustOrNg(PlayerActionEvent caller, float state) {
@ -293,23 +298,25 @@ namespace HeavenStudio.Games.Scripts_PajamaParty
SoundByte.PlayOneShotGame("pajamaParty/throw4"); SoundByte.PlayOneShotGame("pajamaParty/throw4");
} }
public bool CanThrow()
{
return charging;
}
public void ThrowJustOrNg(PlayerActionEvent caller, float state) public void ThrowJustOrNg(PlayerActionEvent caller, float state)
{ {
if (charging) var cond = Conductor.instance;
{ if (state <= -1f || state >= 1f)
var cond = Conductor.instance; {
if (state <= -1f || state >= 1f) SoundByte.PlayOneShot("miss");
{ EndCharge(cond.songPositionInBeatsAsDouble, true, true);
SoundByte.PlayOneShot("miss");
EndCharge(cond.songPositionInBeatsAsDouble, true, true);
}
else
{
SoundByte.PlayOneShotGame("pajamaParty/throw5");
EndCharge(cond.songPositionInBeatsAsDouble, true, (throwNg || false));
}
caller.CanHit(false);
} }
else
{
SoundByte.PlayOneShotGame("pajamaParty/throw5");
EndCharge(cond.songPositionInBeatsAsDouble, true, (throwNg || false));
}
caller.CanHit(false);
} }
public void ThrowThrough(PlayerActionEvent caller) public void ThrowThrough(PlayerActionEvent caller)
@ -325,28 +332,7 @@ namespace HeavenStudio.Games.Scripts_PajamaParty
// sleep cue // sleep cue
public void StartSleepSequence(double beat, bool alt, int action) public void StartSleepSequence(double beat, bool alt, int action)
{ {
startedSleeping = true; PajamaParty.instance.ScheduleInput(beat, 4f, InputType.STANDARD_DOWN, SleepJustOrNg, SleepThrough, SleepOut, CanSleep);
if (hasJumped)
{
hasJumped = false;
PajamaParty.instance.DoBedImpact();
jumpNg = false;
}
startJumpTime = double.MinValue;
Player.transform.localPosition = new Vector3(0, 0);
Shadow.transform.localScale = new Vector3(1.65f, 1f, 1f);
Projectile.GetComponent<Animator>().Play("NoPose", -1, 0);
startThrowTime = double.MinValue;
Projectile_Root.transform.localPosition = new Vector3(0, 0);
Projectile.transform.rotation = Quaternion.Euler(0, 0, 0);
if (hasThrown)
{
Projectile.SetActive(false);
hasThrown = false;
}
PajamaParty.instance.ScheduleInput(beat, 4f, InputType.STANDARD_DOWN, SleepJustOrNg, SleepThrough, SleepOut);
var cond = Conductor.instance; var cond = Conductor.instance;
charging = false; charging = false;
@ -365,6 +351,16 @@ namespace HeavenStudio.Games.Scripts_PajamaParty
Player.transform.localPosition = new Vector3(0, 0); Player.transform.localPosition = new Vector3(0, 0);
Shadow.transform.localScale = new Vector3(1.65f, 1f, 1f); Shadow.transform.localScale = new Vector3(1.65f, 1f, 1f);
Projectile.GetComponent<Animator>().Play("NoPose", -1, 0);
startThrowTime = double.MinValue;
Projectile_Root.transform.localPosition = new Vector3(0, 0);
Projectile.transform.rotation = Quaternion.Euler(0, 0, 0);
if (hasThrown)
{
Projectile.SetActive(false);
hasThrown = false;
}
if (action == (int) PajamaParty.SleepType.NoAwake) if (action == (int) PajamaParty.SleepType.NoAwake)
{ {
longSleep = true; longSleep = true;
@ -403,35 +399,37 @@ namespace HeavenStudio.Games.Scripts_PajamaParty
}); });
} }
public bool CanSleep()
{
return canSleep;
}
public void SleepJustOrNg(PlayerActionEvent caller, float state) public void SleepJustOrNg(PlayerActionEvent caller, float state)
{ {
var cond = Conductor.instance; var cond = Conductor.instance;
if (canSleep) caller.CanHit(false);
{ canSleep = false;
caller.CanHit(false); if (state <= -1f || state >= 1f)
canSleep = false; anim.DoUnscaledAnimation("MakoSleepNg");
if (state <= -1f || state >= 1f) else
anim.DoUnscaledAnimation("MakoSleepNg"); {
else SoundByte.PlayOneShotGame("pajamaParty/siesta4");
{ anim.DoScaledAnimationAsync("MakoSleepJust");
SoundByte.PlayOneShotGame("pajamaParty/siesta4");
anim.DoScaledAnimationAsync("MakoSleepJust");
if (!longSleep) if (!longSleep)
{
BeatAction.New(Player, new List<BeatAction.Action>()
{ {
BeatAction.New(Player, new List<BeatAction.Action>() new BeatAction.Action(
{ caller.startBeat + 7f,
new BeatAction.Action( delegate {
caller.startBeat + 7f, anim.DoScaledAnimationAsync("MakoAwake");
delegate { SoundByte.PlayOneShotGame("pajamaParty/siestaDone");
anim.DoScaledAnimationAsync("MakoAwake"); }
SoundByte.PlayOneShotGame("pajamaParty/siestaDone"); ),
} });
),
});
}
longSleep = false;
} }
longSleep = false;
} }
} }

View file

@ -18,10 +18,12 @@ namespace HeavenStudio.Games
public static bool EnableAutoplayCheat = true; public static bool EnableAutoplayCheat = true;
public delegate void ActionEventCallback(PlayerActionEvent caller); public delegate void ActionEventCallback(PlayerActionEvent caller);
public delegate void ActionEventCallbackState(PlayerActionEvent caller, float state); public delegate void ActionEventCallbackState(PlayerActionEvent caller, float state);
public delegate bool ActionEventHittableQuery();
public ActionEventCallbackState OnHit; //Function to trigger when an input has been done perfectly public ActionEventCallbackState OnHit; //Function to trigger when an input has been done perfectly
public ActionEventCallback OnMiss; //Function to trigger when an input has been missed public ActionEventCallback OnMiss; //Function to trigger when an input has been missed
public ActionEventCallback OnBlank; //Function to trigger when an input has been recorded while this is pending public ActionEventCallback OnBlank; //Function to trigger when an input has been recorded while this is pending
public ActionEventHittableQuery IsHittable; //Checks if an input can be hit. Returning false will skip button checks.
public ActionEventCallback OnDestroy; //Function to trigger whenever this event gets destroyed. /!\ Shouldn't be used for a minigame! Use OnMiss instead /!\ public ActionEventCallback OnDestroy; //Function to trigger whenever this event gets destroyed. /!\ Shouldn't be used for a minigame! Use OnMiss instead /!\
@ -55,28 +57,38 @@ namespace HeavenStudio.Games
this.OnMiss = OnMiss; this.OnMiss = OnMiss;
} }
public void setHittableQuery(ActionEventHittableQuery IsHittable)
{
this.IsHittable = IsHittable;
}
public void Enable() { enabled = true; } public void Enable() { enabled = true; }
public void Disable() { enabled = false; } public void Disable() { enabled = false; }
public void QueueDeletion() { markForDeletion = true; } public void QueueDeletion() { markForDeletion = true; }
public bool IsCorrectInput() => public bool IsCorrectInput(out double dt)
//General inputs, both down and up {
(PlayerInput.Pressed() && inputType.HasFlag(InputType.STANDARD_DOWN)) || dt = 0;
(PlayerInput.AltPressed() && inputType.HasFlag(InputType.STANDARD_ALT_DOWN)) || return (
(PlayerInput.GetAnyDirectionDown() && inputType.HasFlag(InputType.DIRECTION_DOWN)) || //General inputs, both down and up
(PlayerInput.PressedUp() && inputType.HasFlag(InputType.STANDARD_UP)) || (PlayerInput.Pressed(out dt) && inputType.HasFlag(InputType.STANDARD_DOWN)) ||
(PlayerInput.AltPressedUp() && inputType.HasFlag(InputType.STANDARD_ALT_UP)) || (PlayerInput.AltPressed(out dt) && inputType.HasFlag(InputType.STANDARD_ALT_DOWN)) ||
(PlayerInput.GetAnyDirectionUp() && inputType.HasFlag(InputType.DIRECTION_UP)) || (PlayerInput.GetAnyDirectionDown(out dt) && inputType.HasFlag(InputType.DIRECTION_DOWN)) ||
//Specific directional inputs (PlayerInput.PressedUp(out dt) && inputType.HasFlag(InputType.STANDARD_UP)) ||
(PlayerInput.GetSpecificDirectionDown(PlayerInput.DOWN) && inputType.HasFlag(InputType.DIRECTION_DOWN_DOWN)) || (PlayerInput.AltPressedUp(out dt) && inputType.HasFlag(InputType.STANDARD_ALT_UP)) ||
(PlayerInput.GetSpecificDirectionDown(PlayerInput.UP) && inputType.HasFlag(InputType.DIRECTION_UP_DOWN)) || (PlayerInput.GetAnyDirectionUp(out dt) && inputType.HasFlag(InputType.DIRECTION_UP)) ||
(PlayerInput.GetSpecificDirectionDown(PlayerInput.LEFT) && inputType.HasFlag(InputType.DIRECTION_LEFT_DOWN)) || //Specific directional inputs
(PlayerInput.GetSpecificDirectionDown(PlayerInput.RIGHT) && inputType.HasFlag(InputType.DIRECTION_RIGHT_DOWN)) || (PlayerInput.GetSpecificDirectionDown(PlayerInput.DOWN, out dt) && inputType.HasFlag(InputType.DIRECTION_DOWN_DOWN)) ||
(PlayerInput.GetSpecificDirectionDown(PlayerInput.UP, out dt) && inputType.HasFlag(InputType.DIRECTION_UP_DOWN)) ||
(PlayerInput.GetSpecificDirectionDown(PlayerInput.LEFT, out dt) && inputType.HasFlag(InputType.DIRECTION_LEFT_DOWN)) ||
(PlayerInput.GetSpecificDirectionDown(PlayerInput.RIGHT, out dt) && inputType.HasFlag(InputType.DIRECTION_RIGHT_DOWN)) ||
(PlayerInput.GetSpecificDirectionUp(PlayerInput.DOWN) && inputType.HasFlag(InputType.DIRECTION_DOWN_UP)) || (PlayerInput.GetSpecificDirectionUp(PlayerInput.DOWN, out dt) && inputType.HasFlag(InputType.DIRECTION_DOWN_UP)) ||
(PlayerInput.GetSpecificDirectionUp(PlayerInput.UP) && inputType.HasFlag(InputType.DIRECTION_UP_UP)) || (PlayerInput.GetSpecificDirectionUp(PlayerInput.UP, out dt) && inputType.HasFlag(InputType.DIRECTION_UP_UP)) ||
(PlayerInput.GetSpecificDirectionUp(PlayerInput.LEFT) && inputType.HasFlag(InputType.DIRECTION_LEFT_UP)) || (PlayerInput.GetSpecificDirectionUp(PlayerInput.LEFT, out dt) && inputType.HasFlag(InputType.DIRECTION_LEFT_UP)) ||
(PlayerInput.GetSpecificDirectionUp(PlayerInput.RIGHT) && inputType.HasFlag(InputType.DIRECTION_RIGHT_UP)); (PlayerInput.GetSpecificDirectionUp(PlayerInput.RIGHT, out dt) && inputType.HasFlag(InputType.DIRECTION_RIGHT_UP))
);
}
public void CanHit(bool canHit) public void CanHit(bool canHit)
{ {
@ -105,7 +117,7 @@ namespace HeavenStudio.Games
} }
//BUGFIX: ActionEvents destroyed too early //BUGFIX: ActionEvents destroyed too early
if (normalizedTime > Minigame.EndTime()) Miss(); if (normalizedTime > Minigame.NgLateTime()) Miss();
if (lockedByEvent) if (lockedByEvent)
{ {
@ -116,11 +128,12 @@ namespace HeavenStudio.Games
return; return;
} }
if (!autoplayOnly && IsCorrectInput()) if (!autoplayOnly && (IsHittable == null || IsHittable != null && IsHittable()) && IsCorrectInput(out double dt))
{ {
normalizedTime -= dt;
if (IsExpectingInputNow()) if (IsExpectingInputNow())
{ {
double stateProg = ((normalizedTime - Minigame.PerfectTime()) / (Minigame.LateTime() - Minigame.PerfectTime()) - 0.5f) * 2; double stateProg = ((normalizedTime - Minigame.JustEarlyTime()) / (Minigame.JustLateTime() - Minigame.JustEarlyTime()) - 0.5f) * 2;
Hit(stateProg, normalizedTime); Hit(stateProg, normalizedTime);
} }
else else
@ -186,8 +199,16 @@ namespace HeavenStudio.Games
public bool IsExpectingInputNow() public bool IsExpectingInputNow()
{ {
if (IsHittable != null)
{
if (!IsHittable()) return false;
}
if (!enabled) return false;
if (!isEligible) return false;
if (markForDeletion) return false;
double normalizedBeat = GetNormalizedTime(); double normalizedBeat = GetNormalizedTime();
return normalizedBeat > Minigame.EarlyTime() && normalizedBeat < Minigame.EndTime(); return normalizedBeat > Minigame.NgEarlyTime() && normalizedBeat < Minigame.NgLateTime();
} }
double GetNormalizedTime() double GetNormalizedTime()
@ -195,9 +216,9 @@ namespace HeavenStudio.Games
var cond = Conductor.instance; var cond = Conductor.instance;
double currTime = cond.songPositionAsDouble; double currTime = cond.songPositionAsDouble;
double targetTime = cond.GetSongPosFromBeat(startBeat + timer); double targetTime = cond.GetSongPosFromBeat(startBeat + timer);
double min = targetTime - 1f;
double max = targetTime + 1f; // HS timing window uses 1 as the middle point instead of 0
return 1f + (((currTime - min) / (max - min))-0.5f)*2; return 1 + (currTime - targetTime);
} }
//For the Autoplay //For the Autoplay
@ -210,7 +231,7 @@ namespace HeavenStudio.Games
else else
{ {
double normalizedBeat = GetNormalizedTime(); double normalizedBeat = GetNormalizedTime();
double stateProg = ((normalizedBeat - Minigame.PerfectTime()) / (Minigame.LateTime() - Minigame.PerfectTime()) - 0.5f) * 2; double stateProg = ((normalizedBeat - Minigame.JustEarlyTime()) / (Minigame.JustLateTime() - Minigame.JustEarlyTime()) - 0.5f) * 2;
Hit(stateProg, normalizedBeat); Hit(stateProg, normalizedBeat);
} }
} }
@ -220,7 +241,7 @@ namespace HeavenStudio.Games
{ {
if (OnHit != null && enabled) if (OnHit != null && enabled)
{ {
if(canHit) if (canHit)
{ {
double normalized = time - 1f; double normalized = time - 1f;
int offset = Mathf.CeilToInt((float)normalized * 1000); int offset = Mathf.CeilToInt((float)normalized * 1000);
@ -251,27 +272,27 @@ namespace HeavenStudio.Games
double TimeToAccuracy(double time) double TimeToAccuracy(double time)
{ {
if (time >= Minigame.AceStartTime() && time <= Minigame.AceEndTime()) if (time >= Minigame.AceEarlyTime() && time <= Minigame.AceLateTime())
{ {
// Ace // Ace
return 1.0; return 1.0;
} }
double state = 0; double state = 0;
if (time >= Minigame.PerfectTime() && time <= Minigame.LateTime()) if (time >= Minigame.JustEarlyTime() && time <= Minigame.JustLateTime())
{ {
// Good Hit // Good Hit
if (time > 1.0) if (time > 1.0)
{ {
// late half of timing window // late half of timing window
state = 1.0 - ((time - Minigame.AceEndTime()) / (Minigame.LateTime() - Minigame.AceEndTime())); state = 1.0 - ((time - Minigame.AceLateTime()) / (Minigame.JustLateTime() - Minigame.AceLateTime()));
state *= 1.0 - Minigame.rankHiThreshold; state *= 1.0 - Minigame.rankHiThreshold;
state += Minigame.rankHiThreshold; state += Minigame.rankHiThreshold;
} }
else else
{ {
//early half of timing window //early half of timing window
state = ((time - Minigame.PerfectTime()) / (Minigame.AceStartTime() - Minigame.PerfectTime())); state = ((time - Minigame.JustEarlyTime()) / (Minigame.AceEarlyTime() - Minigame.JustEarlyTime()));
state *= 1.0 - Minigame.rankHiThreshold; state *= 1.0 - Minigame.rankHiThreshold;
state += Minigame.rankHiThreshold; state += Minigame.rankHiThreshold;
} }
@ -281,13 +302,13 @@ namespace HeavenStudio.Games
if (time > 1.0) if (time > 1.0)
{ {
// late half of timing window // late half of timing window
state = 1.0 - ((time - Minigame.LateTime()) / (Minigame.EndTime() - Minigame.LateTime())); state = 1.0 - ((time - Minigame.JustLateTime()) / (Minigame.NgLateTime() - Minigame.JustLateTime()));
state *= Minigame.rankOkThreshold; state *= Minigame.rankOkThreshold;
} }
else else
{ {
//early half of timing window //early half of timing window
state = ((time - Minigame.PerfectTime()) / (Minigame.AceStartTime() - Minigame.PerfectTime())); state = ((time - Minigame.JustEarlyTime()) / (Minigame.AceEarlyTime() - Minigame.JustEarlyTime()));
state *= Minigame.rankOkThreshold; state *= Minigame.rankOkThreshold;
} }
} }

View file

@ -1067,4 +1067,3 @@ namespace HeavenStudio.Games
} }
} }
} }

View file

@ -343,7 +343,7 @@ namespace HeavenStudio.Games.Scripts_SpaceSoccer
var cond = Conductor.instance; var cond = Conductor.instance;
ball = null; ball = null;
// queue the miss sound // queue the miss sound
MultiSound.Play(new MultiSound.Sound[] { new MultiSound.Sound("spaceSoccer/missNeutral", targetBeat + (float)cond.SecsToBeats(Minigame.EndTime()-1, MultiSound.Play(new MultiSound.Sound[] { new MultiSound.Sound("spaceSoccer/missNeutral", targetBeat + (float)cond.SecsToBeats(Minigame.NgLateTime()-1,
cond.GetBpmAtBeat(targetBeat)), SoundByte.GetPitchFromCents(UnityEngine.Random.Range(-75, 75), false)) }); cond.GetBpmAtBeat(targetBeat)), SoundByte.GetPitchFromCents(UnityEngine.Random.Range(-75, 75), false)) });
} }

View file

@ -33,7 +33,7 @@ namespace HeavenStudio.Games.Scripts_TrickClass
float flyPos = cond.GetPositionFromBeat(startBeat, flyBeats); float flyPos = cond.GetPositionFromBeat(startBeat, flyBeats);
transform.position = curve.GetPoint(flyPos); transform.position = curve.GetPoint(flyPos);
hitProg = game.ScheduleInput(startBeat, dodgeBeats, InputType.STANDARD_DOWN, DodgeJustOrNg, DodgeMiss, DodgeThrough); hitProg = game.ScheduleInput(startBeat, dodgeBeats, InputType.STANDARD_DOWN, DodgeJustOrNg, DodgeMiss, DodgeThrough, CanDodge);
} }
// Update is called once per frame // Update is called once per frame
@ -113,38 +113,32 @@ namespace HeavenStudio.Games.Scripts_TrickClass
startBeat += dodgeBeats; startBeat += dodgeBeats;
} }
public bool CanDodge()
{
return game.playerCanDodge <= Conductor.instance.songPositionInBeatsAsDouble;
}
public void DodgeJustOrNg(PlayerActionEvent caller, float state) public void DodgeJustOrNg(PlayerActionEvent caller, float state)
{ {
if (game.playerCanDodge <= Conductor.instance.songPositionInBeatsAsDouble) if (state <= -1f || state >= 1f)
{ {
if (state <= -1f || state >= 1f) //NG
{ game.PlayerDodgeNg();
//NG MultiSound.Play(new MultiSound.Sound[] {
game.PlayerDodgeNg(); new MultiSound.Sound(GetDodgeSound(), startBeat + flyBeats, volume: 0.4f),
MultiSound.Play(new MultiSound.Sound[] { });
new MultiSound.Sound(GetDodgeSound(), startBeat + flyBeats, volume: 0.4f), SoundByte.PlayOneShotGame(GetDodgeSound(), volume: 0.6f);
}); SoundByte.PlayOneShot("miss");
SoundByte.PlayOneShotGame(GetDodgeSound(), volume: 0.6f); DoObjMiss();
SoundByte.PlayOneShot("miss");
DoObjMiss();
}
else
{
//just
game.PlayerDodge();
SoundByte.PlayOneShotGame("trickClass/player_dodge_success", volume: 0.8f, pitch: UnityEngine.Random.Range(0.85f, 1.15f));
MultiSound.Play(new MultiSound.Sound[] {
new MultiSound.Sound(GetDodgeSound(), startBeat + flyBeats, volume: 0.4f),
});
}
} }
else else
{ {
SoundByte.PlayOneShotGame(GetDodgeSound()); //just
DoObjMiss(); game.PlayerDodge();
game.PlayerThrough(); SoundByte.PlayOneShotGame("trickClass/player_dodge_success", volume: 0.8f, pitch: UnityEngine.Random.Range(0.85f, 1.15f));
caller.isEligible = false; MultiSound.Play(new MultiSound.Sound[] {
game.ScoreMiss(); new MultiSound.Sound(GetDodgeSound(), startBeat + flyBeats, volume: 0.4f),
});
} }
} }

View file

@ -371,7 +371,7 @@ namespace HeavenStudio
void OnApplicationQuit() void OnApplicationQuit()
{ {
Debug.Log("Disconnecting JoyShocks..."); Debug.Log("Disconnecting JoyShocks...");
PlayerInput.DisconnectJoyshocks(); PlayerInput.CleanUp();
Debug.Log("Clearing RIQ Cache..."); Debug.Log("Clearing RIQ Cache...");
Jukebox.RiqFileHandler.ClearCache(); Jukebox.RiqFileHandler.ClearCache();
} }

View file

@ -1,4 +1,5 @@
using System; using System;
using System.Threading.Tasks;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
@ -6,11 +7,99 @@ using HeavenStudio.Util;
using static JSL; using static JSL;
namespace HeavenStudio.InputSystem.Loaders
{
public static class InputJoyshockInitializer
{
[LoadOrder(1)]
public static InputController[] Initialize()
{
InputJoyshock.joyshocks = new();
PlayerInput.PlayerInputCleanUp += DisposeJoyshocks;
PlayerInput.PlayerInputRefresh.Add(Refresh);
InputJoyshock.JslEventInit();
InputController[] controllers;
int jslDevicesFound = 0;
int jslDevicesConnected = 0;
int[] jslDeviceHandles;
jslDevicesFound = JslConnectDevices();
if (jslDevicesFound > 0)
{
jslDeviceHandles = new int[jslDevicesFound];
jslDevicesConnected = JslGetConnectedDeviceHandles(jslDeviceHandles, jslDevicesFound);
if (jslDevicesConnected < jslDevicesFound)
{
Debug.Log("Found " + jslDevicesFound + " JoyShocks, but only " + jslDevicesConnected + " are connected.");
}
else
{
Debug.Log("Found " + jslDevicesFound + " JoyShocks.");
Debug.Log("Connected " + jslDevicesConnected + " JoyShocks.");
}
controllers = new InputController[jslDevicesConnected];
foreach (int i in jslDeviceHandles)
{
Debug.Log("Setting up JoyShock: ( Handle " + i + ", type " + JslGetControllerType(i) + " )");
InputJoyshock joyshock = new InputJoyshock(i);
joyshock.SetPlayer(null);
joyshock.InitializeController();
controllers[i] = joyshock;
}
return controllers;
}
Debug.Log("No JoyShocks found.");
return null;
}
public static void DisposeJoyshocks()
{
foreach (InputJoyshock joyshock in InputJoyshock.joyshocks.Values)
{
joyshock.CleanUp();
}
JslDisconnectAndDisposeAll();
}
public static InputController[] Refresh()
{
InputJoyshock.joyshocks.Clear();
InputController[] controllers;
int jslDevicesFound = 0;
int jslDevicesConnected = 0;
int[] jslDeviceHandles;
jslDevicesFound = JslConnectDevices();
if (jslDevicesFound > 0)
{
jslDeviceHandles = new int[jslDevicesFound];
jslDevicesConnected = JslGetConnectedDeviceHandles(jslDeviceHandles, jslDevicesFound);
controllers = new InputController[jslDevicesConnected];
foreach (int i in jslDeviceHandles)
{
Debug.Log("Setting up JoyShock: ( Handle " + i + ", type " + JslGetControllerType(i) + " )");
InputJoyshock joyshock = new InputJoyshock(i);
joyshock.SetPlayer(null);
joyshock.InitializeController();
controllers[i] = joyshock;
}
return controllers;
}
Debug.Log("No JoyShocks found.");
return null;
}
}
}
namespace HeavenStudio.InputSystem namespace HeavenStudio.InputSystem
{ {
public class InputJoyshock : InputController public class InputJoyshock : InputController
{ {
static string[] joyShockNames = static readonly string[] joyShockNames =
{ {
"Unknown", "Unknown",
"Joy-Con (L)", "Joy-Con (L)",
@ -20,7 +109,7 @@ namespace HeavenStudio.InputSystem
"DualSense" "DualSense"
}; };
static int[] dsPlayerColours = new[] static readonly int[] dsPlayerColours = new[]
{ {
0xd41817, 0xd41817,
0x04d4fa, 0x04d4fa,
@ -31,50 +120,167 @@ namespace HeavenStudio.InputSystem
0x888888 0x888888
}; };
//TODO: see if single joy-con mappings differ from a normal pad (they don't!) static int[] defaultMappings {
int[] mappings = new[] get
{
return new[]
{
ButtonMaskUp,
ButtonMaskDown,
ButtonMaskLeft,
ButtonMaskRight,
ButtonMaskS,
ButtonMaskE,
ButtonMaskW,
ButtonMaskN,
ButtonMaskL,
ButtonMaskR,
ButtonMaskPlus,
-1
};
}
}
static int[] defaultMappingsL {
get
{
return new[]
{
20,
21,
22,
23,
ButtonMaskLeft,
ButtonMaskDown,
ButtonMaskUp,
ButtonMaskRight,
ButtonMaskSL,
ButtonMaskSR,
ButtonMaskMinus,
-1
};
}
}
static int[] defaultMappingsR {
get
{
return new[]
{
20,
21,
22,
23,
ButtonMaskE,
ButtonMaskN,
ButtonMaskS,
ButtonMaskW,
ButtonMaskSL,
ButtonMaskSR,
ButtonMaskPlus,
-1
};
}
}
static readonly string[] nsProButtonNames = new[]
{ {
ButtonMaskUp, "Up",
ButtonMaskDown, "Down",
ButtonMaskLeft, "Left",
ButtonMaskRight, "Right",
ButtonMaskS, "Plus",
ButtonMaskE, "Minus",
ButtonMaskW, "Left Stick Click",
ButtonMaskN, "Right Stick Click",
ButtonMaskL, "L",
ButtonMaskR, "R",
ButtonMaskPlus, "ZL",
"ZR",
"B",
"A",
"Y",
"X",
"Home",
"Capture",
}; };
int[] mappingsSplitLeft = new[]
static readonly string[] nsConButtonNames = new[]
{ {
-1, "Up",
-1, "Down",
-1, "Left",
-1, "Right",
ButtonMaskLeft, "Plus",
ButtonMaskDown, "Minus",
ButtonMaskUp, "Left Stick Click",
ButtonMaskRight, "Right Stick Click",
ButtonMaskSL, "L",
ButtonMaskSR, "R",
ButtonMaskMinus, "ZL",
"ZR",
"B",
"A",
"Y",
"X",
"Home",
"Capture",
"SL",
"SR",
"Stick Up",
"Stick Down",
"Stick Left",
"Stick Right",
}; };
int[] mappingsSplitRight = new[]
static readonly string[] ps4ButtonNames = new[]
{ {
-1, "Up",
-1, "Down",
-1, "Left",
-1, "Right",
ButtonMaskE, "Options",
ButtonMaskN, "Share",
ButtonMaskS, "L3",
ButtonMaskW, "R3",
ButtonMaskSL, "L",
ButtonMaskSR, "R",
ButtonMaskPlus, "L2",
"R2",
"X",
"Circle",
"Square",
"Triangle",
"PS",
"Touchpad Click",
}; };
static readonly string[] ps5ButtonNames = new[]
{
"Up",
"Down",
"Left",
"Right",
"Options",
"Share",
"L3",
"R3",
"L",
"R",
"L2",
"R2",
"X",
"Circle",
"Square",
"Triangle",
"PS",
"Create",
"Mic",
};
static readonly float debounceTime = 1f/90f;
public static Dictionary<int, InputJoyshock> joyshocks;
float stickDeadzone = 0.5f; float stickDeadzone = 0.5f;
int joyshockHandle; int joyshockHandle;
@ -82,53 +288,171 @@ namespace HeavenStudio.InputSystem
int splitType; int splitType;
int lightbarColour; int lightbarColour;
string joyshockName; string joyshockName;
DateTime startTime;
//buttons, sticks, triggers //buttons, sticks, triggers
JOY_SHOCK_STATE joyBtStateCurrent, joyBtStateLast; JoyshockButtonState[] actionStates = new JoyshockButtonState[BINDS_MAX];
JoyshockButtonState[] buttonStates = new JoyshockButtonState[ButtonMaskSR + 1];
JOY_SHOCK_STATE joyBtStateCurrent;
//gyro and accelerometer //gyro and accelerometer
IMU_STATE joyImuStateCurrent, joyImuStateLast; IMU_STATE joyImuStateCurrent, joyImuStateLast;
//touchpad //touchpad
TOUCH_STATE joyTouchStateCurrent, joyTouchStateLast; TOUCH_STATE joyTouchStateCurrent, joyTouchStateLast;
// controller settings
JSL_SETTINGS joySettings;
InputJoyshock otherHalf; InputJoyshock otherHalf;
bool isPair;
public struct JoyshockButtonState
{
public double dt; // time passed since state
public bool pressed; // true if button is down
public float debounce; // timer to ignore button updates
public bool isDelta; // true if the button changed state since last frame
}
public struct TimestampedState
{
public double timestamp;
public JOY_SHOCK_STATE input;
}
protected List<TimestampedState> inputStack; // asynnc input events / polling should feed into this dict
protected List<TimestampedState> lastInputStack; // when processing input copy the inputStack to this dict
protected bool wantClearInputStack = false; // strobe from main thread to clear the input stack
protected double reportTime = 0;
public InputJoyshock(int handle) public InputJoyshock(int handle)
{ {
joyshockHandle = handle; joyshockHandle = handle;
} }
int GetButtonForSplitType(int action)
{
if (currentBindings.Pad == null) return -1;
if (action < 0 || action >= BINDS_MAX) return -1;
ControlBindings actionMap = currentBindings;
if (actionMap.Pad[action] > ButtonMaskSR) return -1;
return actionMap.Pad[action];
}
public static void JslEventInit()
{
JslSetCallback(JslEventCallback);
}
static void JslEventCallback(int handle, JOY_SHOCK_STATE state, JOY_SHOCK_STATE lastState,
IMU_STATE imuState, IMU_STATE lastImuState, float deltaTime)
{
if (joyshocks == null || !joyshocks.ContainsKey(handle)) return;
InputJoyshock js = joyshocks[handle];
if (js == null) return;
if (js.inputStack == null) return;
if (js.wantClearInputStack)
{
js.inputStack.Clear();
js.wantClearInputStack = false;
}
js.inputStack.Add(new TimestampedState
{
timestamp = (DateTime.Now - js.startTime).TotalSeconds,
input = state
});
}
public override void InitializeController() public override void InitializeController()
{ {
startTime = DateTime.Now;
inputStack = new();
lastInputStack = new();
actionStates = new JoyshockButtonState[BINDS_MAX];
buttonStates = new JoyshockButtonState[ButtonMaskSR + 1];
joyBtStateCurrent = new JOY_SHOCK_STATE(); joyBtStateCurrent = new JOY_SHOCK_STATE();
joyBtStateLast = new JOY_SHOCK_STATE();
joyImuStateCurrent = new IMU_STATE(); joyImuStateCurrent = new IMU_STATE();
joyImuStateLast = new IMU_STATE(); joyImuStateLast = new IMU_STATE();
joyTouchStateCurrent = new TOUCH_STATE(); joyTouchStateCurrent = new TOUCH_STATE();
joyTouchStateLast = new TOUCH_STATE(); joyTouchStateLast = new TOUCH_STATE();
//FUTURE: remappable controls
type = JslGetControllerType(joyshockHandle); joySettings = JslGetControllerInfoAndSettings(joyshockHandle);
type = joySettings.controllerType;
joyshockName = joyShockNames[type]; joyshockName = joyShockNames[type];
splitType = JslGetControllerSplitType(joyshockHandle); splitType = joySettings.splitType;
joyshocks.Add(joyshockHandle, this);
LoadBindings();
}
public void CleanUp()
{
JslSetPlayerNumber(joyshockHandle, 0);
JslSetLightColour(joyshockHandle, 0);
} }
public override void UpdateState() public override void UpdateState()
{ {
//buttons reportTime = (DateTime.Now - startTime).TotalSeconds;
joyBtStateLast = joyBtStateCurrent; lastInputStack.Capacity = inputStack.Count;
joyBtStateCurrent = JslGetSimpleState(joyshockHandle); lastInputStack = new(inputStack);
wantClearInputStack = true;
//gyro and accelerometer for (int i = 0; i < actionStates.Length; i++)
joyImuStateLast = joyImuStateCurrent; {
joyImuStateCurrent = JslGetIMUState(joyshockHandle); actionStates[i].isDelta = false;
actionStates[i].debounce -= Time.deltaTime;
if (actionStates[i].debounce < 0)
actionStates[i].debounce = 0;
}
for (int i = 0; i < buttonStates.Length; i++)
{
buttonStates[i].isDelta = false;
}
//touchpad foreach(TimestampedState state in lastInputStack)
joyTouchStateLast = joyTouchStateCurrent; {
joyTouchStateCurrent = JslGetTouchState(joyshockHandle); joyBtStateCurrent = state.input;
//stick direction state for (int i = 0; i < actionStates.Length; i++)
{
int bt = GetButtonForSplitType(i);
if (bt != -1)
{
bool pressed = BitwiseUtils.WantCurrent(state.input.buttons, 1 << bt);
if (pressed != actionStates[i].pressed && !actionStates[i].isDelta)
{
if (actionStates[i].debounce <= 0)
{
actionStates[i].pressed = pressed;
actionStates[i].isDelta = true;
actionStates[i].dt = reportTime - state.timestamp;
}
actionStates[i].debounce = debounceTime;
}
}
}
for (int i = 0; i < buttonStates.Length; i++)
{
bool pressed = BitwiseUtils.WantCurrent(state.input.buttons, 1 << i);
if (pressed != buttonStates[i].pressed && !buttonStates[i].isDelta)
{
buttonStates[i].pressed = pressed;
buttonStates[i].isDelta = true;
buttonStates[i].dt = reportTime - state.timestamp;
}
}
}
//stick direction state, only handled on update
//split controllers will need to be rotated to compensate //split controllers will need to be rotated to compensate
//left rotates counterclockwise, right rotates clockwise, all by 90 degrees //left rotates counterclockwise, right rotates clockwise, all by 90 degrees
float xAxis = 0f; float xAxis = 0f;
@ -164,6 +488,22 @@ namespace HeavenStudio.InputSystem
directionStateCurrent |= ((xAxis >= stickDeadzone) ? (1 << ((int) InputDirection.Right)) : 0); directionStateCurrent |= ((xAxis >= stickDeadzone) ? (1 << ((int) InputDirection.Right)) : 0);
directionStateCurrent |= ((xAxis <= -stickDeadzone) ? (1 << ((int) InputDirection.Left)) : 0); directionStateCurrent |= ((xAxis <= -stickDeadzone) ? (1 << ((int) InputDirection.Left)) : 0);
//Debug.Log("stick direction: " + directionStateCurrent + "| x axis: " + xAxis + " y axis: " + yAxis); //Debug.Log("stick direction: " + directionStateCurrent + "| x axis: " + xAxis + " y axis: " + yAxis);
lastInputStack.Clear();
}
public override void OnSelected()
{
Task.Run(() => SelectionVibrate());
}
async void SelectionVibrate()
{
JslSetRumbleFrequency(GetHandle(), 0.5f, 0.5f, 80f, 160f);
await Task.Delay(50);
JslSetRumbleFrequency(GetHandle(), 0.75f, 0.75f, 160f, 320f);
await Task.Delay(50);
JslSetRumbleFrequency(GetHandle(), 0f, 0f, 0f, 0f);
} }
public override string GetDeviceName() public override string GetDeviceName()
@ -173,6 +513,24 @@ namespace HeavenStudio.InputSystem
return joyshockName; return joyshockName;
} }
public override string[] GetButtonNames()
{
switch (type)
{
case TypeProController:
return nsProButtonNames;
case TypeDualShock4:
return ps4ButtonNames;
case TypeDualSense:
return ps5ButtonNames;
default:
if (otherHalf == null)
return nsConButtonNames;
else
return nsProButtonNames;
}
}
public override InputFeatures GetFeatures() public override InputFeatures GetFeatures()
{ {
InputFeatures features = InputFeatures.Readable_MotionSensor | InputFeatures.Extra_Rumble | InputFeatures.Style_Pad | InputFeatures.Style_Baton; InputFeatures features = InputFeatures.Readable_MotionSensor | InputFeatures.Extra_Rumble | InputFeatures.Style_Pad | InputFeatures.Style_Baton;
@ -197,83 +555,138 @@ namespace HeavenStudio.InputSystem
return features; return features;
} }
public override bool GetIsConnected()
{
return JslStillConnected(joyshockHandle);
}
public override bool GetIsPoorConnection()
{
return false;
}
public override ControlBindings GetDefaultBindings()
{
ControlBindings binds = new ControlBindings();
switch (type)
{
case TypeJoyConLeft:
if (otherHalf == null)
binds.Pad = defaultMappingsL;
else
binds.Pad = defaultMappings;
break;
case TypeJoyConRight:
if (otherHalf == null)
binds.Pad = defaultMappingsR;
else
binds.Pad = defaultMappings;
break;
case TypeProController:
binds.Pad = defaultMappings;
break;
case TypeDualShock4:
binds.Pad = defaultMappings;
break;
case TypeDualSense:
binds.Pad = defaultMappings;
break;
}
return binds;
}
public override void ResetBindings()
{
currentBindings = GetDefaultBindings();
}
public override ControlBindings GetCurrentBindings()
{
return currentBindings;
}
public override void SetCurrentBindings(ControlBindings newBinds)
{
currentBindings = newBinds;
}
public override bool GetIsActionUnbindable(int action, ControlStyles style)
{
if (otherHalf == null)
{
switch (splitType)
{
case SplitLeft:
case SplitRight:
switch (style)
{
case ControlStyles.Pad:
return action is 0 or 1 or 2 or 3;
}
break;
}
}
return false;
}
public override int GetLastButtonDown() public override int GetLastButtonDown()
{ {
return BitwiseUtils.FirstSetBit(joyBtStateCurrent.buttons & joyBtStateLast.buttons); for (int i = 0; i < buttonStates.Length; i++)
}
public override KeyCode GetLastKeyDown()
{
return KeyCode.None;
}
public override bool GetButton(int button)
{
int bt = 0;
if (otherHalf == null)
{ {
if (splitType == SplitLeft) if (buttonStates[i].pressed && buttonStates[i].isDelta)
{ {
bt = mappingsSplitLeft[button]; return i;
} }
else if (splitType == SplitRight)
{
bt = mappingsSplitRight[button];
}
else
{
bt = mappings[button];
}
return BitwiseUtils.WantCurrent(joyBtStateCurrent.buttons, 1 << bt);
} }
bt = mappings[button]; return -1;
return BitwiseUtils.WantCurrent(joyBtStateCurrent.buttons, 1 << bt) || BitwiseUtils.WantCurrent(otherHalf.joyBtStateCurrent.buttons, 1 << bt);
} }
public override bool GetButtonDown(int button) public override int GetLastActionDown()
{ {
int bt = 0; for (int i = 0; i < actionStates.Length; i++)
if (otherHalf == null)
{ {
if (splitType == SplitLeft) if (actionStates[i].pressed && actionStates[i].isDelta)
{ {
bt = mappingsSplitLeft[button]; return i;
} }
else if (splitType == SplitRight)
{
bt = mappingsSplitRight[button];
}
else
{
bt = mappings[button];
}
return BitwiseUtils.WantCurrentAndNotLast(joyBtStateCurrent.buttons, joyBtStateLast.buttons, 1 << bt);
} }
bt = mappings[button]; if (otherHalf != null)
return BitwiseUtils.WantCurrentAndNotLast(joyBtStateCurrent.buttons, joyBtStateLast.buttons, 1 << bt) || BitwiseUtils.WantCurrentAndNotLast(otherHalf.joyBtStateCurrent.buttons, otherHalf.joyBtStateLast.buttons, 1 << bt); {
return otherHalf.GetLastActionDown();
}
return -1;
} }
public override bool GetButtonUp(int button) public override bool GetAction(int button)
{ {
int bt = 0; if (button == -1) {return false;}
if (otherHalf == null) if (otherHalf != null)
{ {
if (splitType == SplitLeft) return actionStates[button].pressed || otherHalf.actionStates[button].pressed;
{
bt = mappingsSplitLeft[button];
}
else if (splitType == SplitRight)
{
bt = mappingsSplitRight[button];
}
else
{
bt = mappings[button];
}
return BitwiseUtils.WantNotCurrentAndLast(joyBtStateCurrent.buttons, joyBtStateLast.buttons, 1 << bt);
} }
bt = mappings[button]; return actionStates[button].pressed;
return BitwiseUtils.WantNotCurrentAndLast(joyBtStateCurrent.buttons, joyBtStateLast.buttons, 1 << bt) || BitwiseUtils.WantNotCurrentAndLast(otherHalf.joyBtStateCurrent.buttons, otherHalf.joyBtStateLast.buttons, 1 << bt); }
public override bool GetActionDown(int button, out double dt)
{
if (button == -1) {dt = 0; return false;}
if (otherHalf != null && otherHalf.GetActionDown(button, out dt))
{
return true;
}
dt = actionStates[button].dt;
return actionStates[button].pressed && actionStates[button].isDelta;
}
public override bool GetActionUp(int button, out double dt)
{
if (button == -1) {dt = 0; return false;}
if (otherHalf != null && otherHalf.GetActionUp(button, out dt))
{
return true;
}
dt = actionStates[button].dt;
return !actionStates[button].pressed && actionStates[button].isDelta;
} }
public override float GetAxis(InputAxis axis) public override float GetAxis(InputAxis axis)
@ -303,74 +716,89 @@ namespace HeavenStudio.InputSystem
public override bool GetHatDirection(InputDirection direction) public override bool GetHatDirection(InputDirection direction)
{ {
//todo: check analogue stick hat direction too
int bt; int bt;
switch (direction) switch (direction)
{ {
case InputDirection.Up: case InputDirection.Up:
bt = mappings[0]; bt = 0;
break; break;
case InputDirection.Down: case InputDirection.Down:
bt = mappings[1]; bt = 1;
break; break;
case InputDirection.Left: case InputDirection.Left:
bt = mappings[2]; bt = 2;
break; break;
case InputDirection.Right: case InputDirection.Right:
bt = mappings[3]; bt = 3;
break; break;
default: default:
return false; return false;
} }
return GetButton(bt) || BitwiseUtils.WantCurrent(directionStateCurrent, 1 << (int) direction); if (otherHalf != null)
{
return GetAction(bt) || BitwiseUtils.WantCurrent(otherHalf.directionStateCurrent, 1 << (int) direction) || BitwiseUtils.WantCurrent(directionStateCurrent, 1 << (int) direction);
}
return GetAction(bt) || BitwiseUtils.WantCurrent(directionStateCurrent, 1 << (int) direction);
} }
public override bool GetHatDirectionDown(InputDirection direction) public override bool GetHatDirectionDown(InputDirection direction, out double dt)
{ {
//todo: check analogue stick hat direction too
int bt; int bt;
switch (direction) switch (direction)
{ {
case InputDirection.Up: case InputDirection.Up:
bt = mappings[0]; bt = 0;
break; break;
case InputDirection.Down: case InputDirection.Down:
bt = mappings[1]; bt = 1;
break; break;
case InputDirection.Left: case InputDirection.Left:
bt = mappings[2]; bt = 2;
break; break;
case InputDirection.Right: case InputDirection.Right:
bt = mappings[3]; bt = 3;
break; break;
default: default:
dt = 0;
return false; return false;
} }
return GetButtonDown(bt) || BitwiseUtils.WantCurrentAndNotLast(directionStateCurrent, directionStateLast, 1 << (int) direction); bool btbool = GetActionDown(bt, out dt);
if (!btbool) dt = 0;
if (otherHalf != null)
{
return btbool || BitwiseUtils.WantCurrentAndNotLast(otherHalf.directionStateCurrent, otherHalf.directionStateLast, 1 << (int)direction) || BitwiseUtils.WantCurrentAndNotLast(directionStateCurrent, directionStateLast, 1 << (int)direction);
}
return btbool || BitwiseUtils.WantCurrentAndNotLast(directionStateCurrent, directionStateLast, 1 << (int) direction);
} }
public override bool GetHatDirectionUp(InputDirection direction) public override bool GetHatDirectionUp(InputDirection direction, out double dt)
{ {
//todo: check analogue stick hat direction too
int bt; int bt;
switch (direction) switch (direction)
{ {
case InputDirection.Up: case InputDirection.Up:
bt = mappings[0]; bt = 0;
break; break;
case InputDirection.Down: case InputDirection.Down:
bt = mappings[1]; bt = 1;
break; break;
case InputDirection.Left: case InputDirection.Left:
bt = mappings[2]; bt = 2;
break; break;
case InputDirection.Right: case InputDirection.Right:
bt = mappings[3]; bt = 3;
break; break;
default: default:
dt = 0;
return false; return false;
} }
return GetButtonUp(bt) || BitwiseUtils.WantNotCurrentAndLast(directionStateCurrent, directionStateLast, 1 << (int) direction); bool btbool = GetActionUp(bt, out dt);
if (!btbool) dt = 0;
if (otherHalf != null)
{
return btbool || BitwiseUtils.WantNotCurrentAndLast(otherHalf.directionStateCurrent, otherHalf.directionStateLast, 1 << (int) direction) || BitwiseUtils.WantNotCurrentAndLast(directionStateCurrent, directionStateLast, 1 << (int) direction);
}
return btbool || BitwiseUtils.WantNotCurrentAndLast(directionStateCurrent, directionStateLast, 1 << (int) direction);
} }
public override void SetPlayer(int? playerNum) public override void SetPlayer(int? playerNum)
@ -387,9 +815,9 @@ namespace HeavenStudio.InputSystem
int ledMask = (int) this.playerNum; int ledMask = (int) this.playerNum;
if (type == TypeDualSense) if (type == TypeDualSense)
{ {
if (playerNum <= 4) if (playerNum <= 5)
{ {
ledMask = DualSensePlayerMask[(int) this.playerNum]; ledMask = DualSensePlayerMask[Math.Max((int) this.playerNum + 1, 1)];
} }
} }
JslSetPlayerNumber(joyshockHandle, ledMask); JslSetPlayerNumber(joyshockHandle, ledMask);
@ -407,32 +835,38 @@ namespace HeavenStudio.InputSystem
if (otherHalf != null) if (otherHalf != null)
{ {
// gets the colour of the right controller if is split // gets the colour of the right controller if is split
return BitwiseUtils.IntToRgb(splitType == SplitRight ? JslGetControllerColour(joyshockHandle) : JslGetControllerColour(GetOtherHalf().GetHandle())); return BitwiseUtils.IntToRgb(splitType == SplitRight ? joySettings.bodyColour : GetOtherHalf().joySettings.bodyColour);
} }
return BitwiseUtils.IntToRgb(JslGetControllerColour(joyshockHandle)); return BitwiseUtils.IntToRgb(joySettings.bodyColour);
} }
public Color GetButtonColor() public Color GetButtonColor()
{ {
return BitwiseUtils.IntToRgb(JslGetControllerButtonColour(joyshockHandle)); if (joySettings.buttonColour == 0xFFFFFF)
return GetBodyColor();
return BitwiseUtils.IntToRgb(joySettings.buttonColour);
} }
public Color GetLeftGripColor() public Color GetLeftGripColor()
{ {
if (otherHalf != null) if (otherHalf != null)
{ {
return BitwiseUtils.IntToRgb(splitType == SplitLeft ? JslGetControllerColour(joyshockHandle) : JslGetControllerColour(GetOtherHalf().GetHandle())); return BitwiseUtils.IntToRgb(splitType == SplitLeft ? joySettings.lGripColour : GetOtherHalf().joySettings.lGripColour);
} }
return BitwiseUtils.IntToRgb(JslGetControllerLeftGripColour(joyshockHandle)); if (joySettings.lGripColour == 0xFFFFFF)
return GetBodyColor();
return BitwiseUtils.IntToRgb(joySettings.lGripColour);
} }
public Color GetRightGripColor() public Color GetRightGripColor()
{ {
if (otherHalf != null) if (otherHalf != null)
{ {
return BitwiseUtils.IntToRgb(splitType == SplitRight ? JslGetControllerColour(joyshockHandle) : JslGetControllerColour(GetOtherHalf().GetHandle())); return BitwiseUtils.IntToRgb(splitType == SplitRight ? joySettings.rGripColour : GetOtherHalf().joySettings.rGripColour);
} }
return BitwiseUtils.IntToRgb(JslGetControllerRightGripColour(joyshockHandle)); if (joySettings.rGripColour == 0xFFFFFF)
return GetBodyColor();
return BitwiseUtils.IntToRgb(joySettings.rGripColour);
} }
public Color GetLightbarColour() public Color GetLightbarColour()

View file

@ -1,82 +1,179 @@
using System;
using System.Linq;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
using static JSL; using static JSL;
namespace HeavenStudio.InputSystem.Loaders
{
public static class InputKeyboardInitializer
{
[LoadOrder(0)]
public static InputController[] Initialize()
{
PlayerInput.PlayerInputRefresh.Add(Refresh);
InputKeyboard keyboard = new InputKeyboard();
keyboard.SetPlayer(1);
keyboard.InitializeController();
return new InputController[] { keyboard };
}
public static InputController[] Refresh()
{
InputKeyboard keyboard = new InputKeyboard();
keyboard.SetPlayer(1);
keyboard.InitializeController();
return new InputController[] { keyboard };
}
}
}
namespace HeavenStudio.InputSystem namespace HeavenStudio.InputSystem
{ {
public class InputKeyboard : InputController public class InputKeyboard : InputController
{ {
static KeyCode[] keyCodes = (KeyCode[]) System.Enum.GetValues(typeof(UnityEngine.KeyCode)); private static readonly KeyCode[] keyCodes = Enum.GetValues(typeof(KeyCode))
.Cast<KeyCode>()
.Where(k => ((int)k < (int)KeyCode.Mouse0))
.ToArray();
//FUTURE: remappable controls static ControlBindings defaultBindings {
//KeyCode[] mappings = new KeyCode[Enum.GetNames(typeof(ButtonsPad)).Length]; get
KeyCode[] mappings = new KeyCode[] {
{ return new ControlBindings()
KeyCode.W, // dpad up {
KeyCode.S, // dpad down Pad = new int[]
KeyCode.A, // dpad left {
KeyCode.D, // dpad right (int)KeyCode.W,
KeyCode.K, // south face button (int)KeyCode.S,
KeyCode.J, // east face button (int)KeyCode.A,
KeyCode.I, // west face button (int)KeyCode.D,
KeyCode.U, // north face button (int)KeyCode.J,
KeyCode.C, // left shoulder button (int)KeyCode.K,
KeyCode.N, // right shoulder button (int)KeyCode.I,
KeyCode.Escape, // start button (int)KeyCode.U,
}; (int)KeyCode.E,
(int)KeyCode.U,
(int)KeyCode.Escape,
},
};
}
}
InputDirection hatDirectionCurrent; InputDirection hatDirectionCurrent;
InputDirection hatDirectionLast; InputDirection hatDirectionLast;
public override void InitializeController() public override void InitializeController()
{ {
//FUTURE: remappable controls LoadBindings();
} }
public override void UpdateState() public override void UpdateState()
{ {
// Update the state of the controller // Update the state of the controller
} }
public override void OnSelected()
{
}
public override string GetDeviceName() public override string GetDeviceName()
{ {
return "Keyboard"; return "Keyboard";
} }
public override string[] GetButtonNames()
{
string[] names = new string[(int)KeyCode.Mouse0];
for (int i = 0; i < keyCodes.Length; i++)
{
names[(int)keyCodes[i]] = keyCodes[i].ToString();
}
return names;
}
public override InputFeatures GetFeatures() public override InputFeatures GetFeatures()
{ {
return InputFeatures.Readable_StringInput | InputFeatures.Style_Pad | InputFeatures.Style_Baton; return InputFeatures.Readable_StringInput | InputFeatures.Style_Pad | InputFeatures.Style_Baton;
} }
public override bool GetIsConnected()
{
return true;
}
public override bool GetIsPoorConnection()
{
return false;
}
public override ControlBindings GetDefaultBindings()
{
return defaultBindings;
}
public override void ResetBindings()
{
currentBindings = GetDefaultBindings();
}
public override ControlBindings GetCurrentBindings()
{
return currentBindings;
}
public override void SetCurrentBindings(ControlBindings newBinds)
{
currentBindings = newBinds;
}
public override bool GetIsActionUnbindable(int action, ControlStyles style)
{
return false;
}
public override int GetLastButtonDown() public override int GetLastButtonDown()
{ {
return 0; if (Input.anyKeyDown)
{
for (KeyCode i = keyCodes[1]; i <= KeyCode.Menu; i++)
{
if (Input.GetKeyDown(i))
return (int)i;
}
}
return (int)KeyCode.None;
} }
public override KeyCode GetLastKeyDown() public override int GetLastActionDown()
{ {
for(KeyCode i = keyCodes[1]; i <= KeyCode.Menu; i++) { for (int i = 0; i < BINDS_MAX; i++)
if (Input.GetKeyDown(i)) {
if (Input.GetKeyDown((KeyCode)currentBindings.Pad[i]))
return i; return i;
} }
return KeyCode.None; return -1;
} }
public override bool GetButton(int button) public override bool GetAction(int button)
{ {
return Input.GetKey(mappings[button]); return Input.GetKey((KeyCode)currentBindings.Pad[button]);
} }
public override bool GetButtonDown(int button) public override bool GetActionDown(int button, out double dt)
{ {
return Input.GetKeyDown(mappings[button]); dt = 0;
return Input.GetKeyDown((KeyCode)currentBindings.Pad[button]);
} }
public override bool GetButtonUp(int button) public override bool GetActionUp(int button, out double dt)
{ {
return Input.GetKeyUp(mappings[button]); dt = 0;
return Input.GetKeyUp((KeyCode)currentBindings.Pad[button]);
} }
public override float GetAxis(InputAxis axis) public override float GetAxis(InputAxis axis)
@ -90,47 +187,49 @@ namespace HeavenStudio.InputSystem
switch (direction) switch (direction)
{ {
case InputDirection.Up: case InputDirection.Up:
return Input.GetKey(mappings[0]); return Input.GetKey((KeyCode)currentBindings.Pad[0]);
case InputDirection.Down: case InputDirection.Down:
return Input.GetKey(mappings[1]); return Input.GetKey((KeyCode)currentBindings.Pad[1]);
case InputDirection.Left: case InputDirection.Left:
return Input.GetKey(mappings[2]); return Input.GetKey((KeyCode)currentBindings.Pad[2]);
case InputDirection.Right: case InputDirection.Right:
return Input.GetKey(mappings[3]); return Input.GetKey((KeyCode)currentBindings.Pad[3]);
default: default:
return false; return false;
} }
} }
public override bool GetHatDirectionDown(InputDirection direction) public override bool GetHatDirectionDown(InputDirection direction, out double dt)
{ {
dt = 0;
switch (direction) switch (direction)
{ {
case InputDirection.Up: case InputDirection.Up:
return Input.GetKeyDown(mappings[0]); return Input.GetKeyDown((KeyCode)currentBindings.Pad[0]);
case InputDirection.Down: case InputDirection.Down:
return Input.GetKeyDown(mappings[1]); return Input.GetKeyDown((KeyCode)currentBindings.Pad[1]);
case InputDirection.Left: case InputDirection.Left:
return Input.GetKeyDown(mappings[2]); return Input.GetKeyDown((KeyCode)currentBindings.Pad[2]);
case InputDirection.Right: case InputDirection.Right:
return Input.GetKeyDown(mappings[3]); return Input.GetKeyDown((KeyCode)currentBindings.Pad[3]);
default: default:
return false; return false;
} }
} }
public override bool GetHatDirectionUp(InputDirection direction) public override bool GetHatDirectionUp(InputDirection direction, out double dt)
{ {
dt = 0;
switch (direction) switch (direction)
{ {
case InputDirection.Up: case InputDirection.Up:
return Input.GetKeyUp(mappings[0]); return Input.GetKeyUp((KeyCode)currentBindings.Pad[0]);
case InputDirection.Down: case InputDirection.Down:
return Input.GetKeyUp(mappings[1]); return Input.GetKeyUp((KeyCode)currentBindings.Pad[1]);
case InputDirection.Left: case InputDirection.Left:
return Input.GetKeyUp(mappings[2]); return Input.GetKeyUp((KeyCode)currentBindings.Pad[2]);
case InputDirection.Right: case InputDirection.Right:
return Input.GetKeyUp(mappings[3]); return Input.GetKeyUp((KeyCode)currentBindings.Pad[3]);
default: default:
return false; return false;
} }

View file

@ -1,6 +1,7 @@
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
using System.IO;
namespace HeavenStudio.InputSystem namespace HeavenStudio.InputSystem
{ {
@ -10,34 +11,6 @@ namespace HeavenStudio.InputSystem
/// </summary> /// </summary>
public abstract class InputController public abstract class InputController
{ {
//Buttons and Axis used by most controllers
public enum InputButtons : int
{
ButtonPadUp = 0,
ButtonPadDown = 1,
ButtonPadLeft = 2,
ButtonPadRight = 3,
ButtonPlus = 4,
ButtonOptions = 4,
ButtonMinus = 5,
ButtonShare = 5,
ButtonLClick = 6,
ButtonRClick = 7,
ButtonL = 8,
ButtonR = 9,
ButtonZL = 10,
ButtonZR = 11,
ButtonFaceS = 12,
ButtonFaceE = 13,
ButtonFaceW = 14,
ButtonFaceN = 15,
ButtonHome = 16,
ButtonPS = 16,
ButtonCapture = 17,
ButtonTouchpadClick = 17,
ButtonSL = 18,
ButtonSR = 19,
}
public enum InputAxis : int public enum InputAxis : int
{ {
AxisLTrigger = 4, AxisLTrigger = 4,
@ -97,50 +70,65 @@ namespace HeavenStudio.InputSystem
{ {
Pad, Pad,
Baton, Baton,
Touch Touch,
Move
} }
public const int BINDS_MAX = 12; //maximum number of binds per controller
//buttons used in Heaven Studio gameplay (Pad Style) //buttons used in Heaven Studio gameplay (Pad Style)
public enum ButtonsPad : int public enum ActionsPad : int
{ {
PadUp = 0, Up = 0,
PadDown = 1, Down = 1,
PadLeft = 2, Left = 2,
PadRight = 3, Right = 3,
PadS = 4, South = 4,
PadE = 5, East = 5,
PadW = 6, West = 6,
PadN = 7, North = 7,
PadL = 8, L = 8,
PadR = 9, R = 9,
PadPause = 10, Pause = 10,
} }
//FUTURE: buttons used in Heaven Studio gameplay ("Form Baton" / WiiMote Style) //FUTURE: buttons used in Heaven Studio gameplay ("Form Baton" / WiiMote Style)
public enum ButtonsBaton : int public enum ActionsBaton : int
{ {
BatonS = 0, //-- all these... South = 0, //-- all these...
BatonE = 1, // | East = 1, // |
BatonW = 2, // | West = 2, // |
BatonN = 3, //-- North = 3, //--
BatonA = 4, // < ...map to this, but are directional Face = 4, // < ...are also equivalent to this, but with added directionality
BatonB = 5, // should never be used alone Trigger = 5, // should never be used alone, but still bindable separately (controller logic should handle confirming & timestamping face + trigger input)
Baton1 = 6, Up = 6, // Wiimote 1
Baton2 = 7, Down = 7, // Wiimote 2
BatonPause = 8, Pause = 8,
} }
//FUTURE: buttons used in Heaven Studio gameplay (Touch Style) //FUTURE: buttons used in Heaven Studio gameplay (Touch Style)
public enum ButtonsTouch : int public enum ActionsTouch : int
{ {
TouchL = 0, Tap = 0, // flicks are handled like a motion, don't have a binding
TouchR = 1, Left = 1, // also maps to tap, but with directionality (tap the left side of the panel)
TouchTap = 2, Right = 2, // also maps to tap, but with directionality (tap the right side of the panel)
TouchFlick = 3, ButtonL = 3,
TouchButtonL = 4, ButtonR = 4,
TouchButtonR = 4, Pause = 5,
} }
[System.Serializable]
public struct ControlBindings
{
public int[] Pad;
public int[] Baton;
public int[] Touch;
}
// FUTURE: Move Style needs to be implemented per-game (maybe implement checks for common actions?)
protected ControlBindings currentBindings;
protected int? playerNum; protected int? playerNum;
protected int directionStateCurrent = 0; protected int directionStateCurrent = 0;
protected int directionStateLast = 0; protected int directionStateLast = 0;
@ -148,21 +136,144 @@ namespace HeavenStudio.InputSystem
public abstract void InitializeController(); public abstract void InitializeController();
public abstract void UpdateState(); // Update the state of the controller public abstract void UpdateState(); // Update the state of the controller
public abstract void OnSelected();
public abstract string GetDeviceName(); // Get the name of the controller public abstract string GetDeviceName(); // Get the name of the controller
public abstract string[] GetButtonNames(); // Get the names of the buttons on the controller
public abstract InputFeatures GetFeatures(); // Get the features of the controller public abstract InputFeatures GetFeatures(); // Get the features of the controller
public abstract bool GetIsConnected();
public abstract bool GetIsPoorConnection();
public abstract int GetLastButtonDown(); // Get the last button down public void SaveBindings()
public abstract KeyCode GetLastKeyDown(); // Get the last key down (used for keyboards and other devices that use Keycode) {
public abstract bool GetButton(int button); // is button currently pressed? if (!Directory.Exists($"{Application.persistentDataPath}/controls"))
public abstract bool GetButtonDown(int button); // is button just pressed? Directory.CreateDirectory($"{Application.persistentDataPath}/controls");
public abstract bool GetButtonUp(int button); // is button just released? string path = $"{Application.persistentDataPath}/controls/{GetDeviceName()}.json";
public abstract float GetAxis(InputAxis axis); // Get the value of an axis string json = JsonUtility.ToJson(currentBindings);
public abstract bool GetHatDirection(InputDirection direction); // is direction active? File.WriteAllText(path, json);
public abstract bool GetHatDirectionDown(InputDirection direction); // direction just became active? }
public abstract bool GetHatDirectionUp(InputDirection direction); // direction just became inactive?
public abstract void SetPlayer(int? playerNum); // Set the player number (starts at 1, set to -1 or null for no player) public void LoadBindings()
public abstract int? GetPlayer(); // Get the player number (null if no player) {
string path = $"{Application.persistentDataPath}/controls/{GetDeviceName()}.json";
if (File.Exists(path))
{
string json = File.ReadAllText(path);
currentBindings = JsonUtility.FromJson<ControlBindings>(json);
}
else
{
ResetBindings();
}
}
/// <summary>
/// Gets the controller's default mappings
/// </summary>
/// <returns></returns>
public abstract ControlBindings GetDefaultBindings();
/// <summary>
/// Resets the controller's mappings to default
/// </summary>
public abstract void ResetBindings();
/// <summary>
/// Gets the controller's current mappings
/// </summary>
/// <returns></returns>
public abstract ControlBindings GetCurrentBindings();
/// <summary>
/// Sets the controller's current mappings
/// </summary>
/// <param name="newBinds"></param>
public abstract void SetCurrentBindings(ControlBindings newBinds);
/// <summary>
/// Whether a given action can have be rebount
/// </summary>
/// <param name="action">action to check</param>
/// <param name="style">control style to check</param>
/// <returns></returns>
public abstract bool GetIsActionUnbindable(int action, ControlStyles style);
/// <summary>
/// Gets the last pressed physical button
/// </summary>
/// <returns></returns>
public abstract int GetLastButtonDown();
/// <summary>
/// Gets the last pressed virtual action
/// </summary>
/// <returns></returns>
public abstract int GetLastActionDown();
/// <summary>
/// True if the given action is being held
/// </summary>
/// <param name="action"></param>
/// <returns></returns>
public abstract bool GetAction(int action);
/// <summary>
/// True if the action was just pressed this Update
/// </summary>
/// <param name="action"></param>
/// <param name="dt">time since the reported event, use to compensate for controller delays</param>
/// <returns></returns>
public abstract bool GetActionDown(int action, out double dt);
/// <summary>
/// True if the action was just released this Update
/// </summary>
/// <param name="action"></param>
/// <param name="dt">time since the reported event, use to compensate for controller delays</param>
/// <returns></returns>
public abstract bool GetActionUp(int action, out double dt);
/// <summary>
/// Get the value of an analogue axis
/// </summary>
/// <param name="axis"></param>
/// <returns></returns>
public abstract float GetAxis(InputAxis axis);
/// <summary>
/// True if the current direction is active
/// </summary>
/// <param name="direction"></param>
/// <returns></returns>
public abstract bool GetHatDirection(InputDirection direction);
/// <summary>
/// True if the current direction just became active this Update
/// </summary>
/// <param name="direction"></param>
/// <param name="dt">time since the reported event, use to compensate for controller delays</param>
/// <returns></returns>
public abstract bool GetHatDirectionDown(InputDirection direction, out double dt);
/// <summary>
/// True if the current direction just became inactive this Update
/// </summary>
/// <param name="direction"></param>
/// <param name="dt">time since the reported event, use to compensate for controller delays</param>
/// <returns></returns>
public abstract bool GetHatDirectionUp(InputDirection direction, out double dt);
/// <summary>
/// Sets the player number (starts at 1, set to -1 or null for no player)
/// </summary>
/// <param name="playerNum"></param>
public abstract void SetPlayer(int? playerNum);
/// <summary>
/// Gets the player number (starts at 1, -1 or null for no player)
/// </summary>
/// <returns></returns>
public abstract int? GetPlayer();
//public abstract Sprite GetDisplayIcon(); //"big icon" for the controller in the settings menu //public abstract Sprite GetDisplayIcon(); //"big icon" for the controller in the settings menu
//public abstract Sprite GetPlaybackIcon(); //"small icon" for the controller during playback //public abstract Sprite GetPlaybackIcon(); //"small icon" for the controller during playback

View file

@ -1,3 +1,7 @@
using System;
using System.Linq;
using System.Reflection;
using System.IO;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
@ -5,6 +9,16 @@ using HeavenStudio.InputSystem;
using static JSL; using static JSL;
namespace HeavenStudio.InputSystem
{
public class LoadOrder : Attribute {
public int Order { get; set; }
public LoadOrder(int order) {
Order = order;
}
}
}
namespace HeavenStudio namespace HeavenStudio
{ {
public class PlayerInput public class PlayerInput
@ -15,63 +29,60 @@ namespace HeavenStudio
public const int DOWN = 2; public const int DOWN = 2;
public const int LEFT = 3; public const int LEFT = 3;
///////////////////////////////
////TEMPORARY JSL FUNCTIONS////
///////////////////////////////
static int jslDevicesFound = 0;
static int jslDevicesConnected = 0;
static int[] jslDeviceHandles;
static List<InputController> inputDevices; static List<InputController> inputDevices;
static InputController.ControlStyles currentControlStyle = InputController.ControlStyles.Pad;
public delegate InputController[] InputControllerInitializer();
public delegate void InputControllerDispose();
public static event InputControllerDispose PlayerInputCleanUp;
public delegate InputController[] InputControllerRefresh();
public static List<InputControllerRefresh> PlayerInputRefresh;
static List<InputControllerInitializer> loadRunners;
static void BuildLoadRunnerList() {
PlayerInputRefresh = new();
loadRunners = System.Reflection.Assembly.GetExecutingAssembly()
.GetTypes()
.Where(x => x.Namespace == "HeavenStudio.InputSystem.Loaders" && x.GetMethod("Initialize", BindingFlags.Public | BindingFlags.Static) != null)
.Select(t => (InputControllerInitializer) Delegate.CreateDelegate(
typeof(InputControllerInitializer),
null,
t.GetMethod("Initialize", BindingFlags.Public | BindingFlags.Static),
false
))
.ToList();
loadRunners.Sort((x, y) => x.Method.GetCustomAttribute<LoadOrder>().Order.CompareTo(y.Method.GetCustomAttribute<LoadOrder>().Order));
}
public static int InitInputControllers() public static int InitInputControllers()
{ {
inputDevices = new List<InputController>(); inputDevices = new List<InputController>();
//Keyboard setup
InputKeyboard keyboard = new InputKeyboard(); BuildLoadRunnerList();
keyboard.SetPlayer(1); foreach (InputControllerInitializer runner in loadRunners) {
keyboard.InitializeController(); InputController[] controllers = runner();
inputDevices.Add(keyboard); if (controllers != null) {
//end Keyboard setup inputDevices.AddRange(controllers);
//JoyShock setup
Debug.Log("Flushing possible JoyShocks...");
DisconnectJoyshocks();
jslDevicesFound = JslConnectDevices();
if (jslDevicesFound > 0)
{
jslDeviceHandles = new int[jslDevicesFound];
jslDevicesConnected = JslGetConnectedDeviceHandles(jslDeviceHandles, jslDevicesFound);
if (jslDevicesConnected < jslDevicesFound)
{
Debug.Log("Found " + jslDevicesFound + " JoyShocks, but only " + jslDevicesConnected + " are connected.");
}
else
{
Debug.Log("Found " + jslDevicesFound + " JoyShocks.");
Debug.Log("Connected " + jslDevicesConnected + " JoyShocks.");
}
foreach (int i in jslDeviceHandles)
{
Debug.Log("Setting up JoyShock: ( Handle " + i + ", type " + JslGetControllerType(i) + " )");
InputJoyshock joyshock = new InputJoyshock(i);
joyshock.InitializeController();
joyshock.SetPlayer(inputDevices.Count + 1);
inputDevices.Add(joyshock);
} }
} }
else
{ return inputDevices.Count;
Debug.Log("No JoyShocks found."); }
public static int RefreshInputControllers()
{
inputDevices = new List<InputController>();
if (PlayerInputRefresh != null) {
foreach (InputControllerRefresh runner in PlayerInputRefresh) {
InputController[] controllers = runner();
if (controllers != null) {
inputDevices.AddRange(controllers);
}
}
} }
//end JoyShock setup
//TODO: XInput setup (boo)
//end XInput setup
return inputDevices.Count; return inputDevices.Count;
} }
@ -159,28 +170,15 @@ namespace HeavenStudio
} }
} }
public static void DisconnectJoyshocks() public static void CleanUp()
{ {
if (jslDeviceHandles != null && jslDevicesConnected > 0 && jslDeviceHandles.Length > 0) PlayerInputCleanUp?.Invoke();
{
foreach (InputController i in inputDevices)
{
if (typeof(InputJoyshock) == i.GetType())
{
InputJoyshock joy = (InputJoyshock)i;
joy.DisconnectJoyshock();
}
}
}
JslDisconnectAndDisposeAll();
jslDevicesFound = 0;
jslDevicesConnected = 0;
} }
// The autoplay isn't activated AND // The autoplay isn't activated AND
// The song is actually playing AND // The song is actually playing AND
// The GameManager allows you to Input // The GameManager allows you to Input
public static bool playerHasControl() public static bool PlayerHasControl()
{ {
return !GameManager.instance.autoplay && Conductor.instance.isPlaying && GameManager.instance.canInput; return !GameManager.instance.autoplay && Conductor.instance.isPlaying && GameManager.instance.canInput;
} }
@ -194,39 +192,63 @@ namespace HeavenStudio
public static bool Pressed(bool includeDPad = false) public static bool Pressed(bool includeDPad = false)
{ {
bool keyDown = GetInputController(1).GetButtonDown((int) InputController.ButtonsPad.PadE) || (includeDPad && GetAnyDirectionDown()); bool keyDown = GetInputController(1).GetActionDown((int) InputController.ActionsPad.East, out _) || (includeDPad && GetAnyDirectionDown());
return keyDown && !GameManager.instance.autoplay && Conductor.instance.isPlaying && GameManager.instance.canInput ; return keyDown && !GameManager.instance.autoplay && Conductor.instance.isPlaying && GameManager.instance.canInput;
}
public static bool Pressed(out double dt, bool includeDPad = false)
{
bool keyDown = GetInputController(1).GetActionDown((int) InputController.ActionsPad.East, out dt) || (includeDPad && GetAnyDirectionDown());
return keyDown && !GameManager.instance.autoplay && Conductor.instance.isPlaying && GameManager.instance.canInput;
} }
public static bool PressedUp(bool includeDPad = false) public static bool PressedUp(bool includeDPad = false)
{ {
bool keyUp = GetInputController(1).GetButtonUp((int) InputController.ButtonsPad.PadE) || (includeDPad && GetAnyDirectionUp()); bool keyUp = GetInputController(1).GetActionUp((int) InputController.ActionsPad.East, out _) || (includeDPad && GetAnyDirectionUp());
return keyUp && !GameManager.instance.autoplay && Conductor.instance.isPlaying && GameManager.instance.canInput;
}
public static bool PressedUp(out double dt, bool includeDPad = false)
{
bool keyUp = GetInputController(1).GetActionUp((int) InputController.ActionsPad.East, out dt) || (includeDPad && GetAnyDirectionUp());
return keyUp && !GameManager.instance.autoplay && Conductor.instance.isPlaying && GameManager.instance.canInput; return keyUp && !GameManager.instance.autoplay && Conductor.instance.isPlaying && GameManager.instance.canInput;
} }
public static bool Pressing(bool includeDPad = false) public static bool Pressing(bool includeDPad = false)
{ {
bool pressing = GetInputController(1).GetButton((int) InputController.ButtonsPad.PadE) || (includeDPad && GetAnyDirection()); bool pressing = GetInputController(1).GetAction((int) InputController.ActionsPad.East) || (includeDPad && GetAnyDirection());
return pressing && !GameManager.instance.autoplay && Conductor.instance.isPlaying && GameManager.instance.canInput; return pressing && !GameManager.instance.autoplay && Conductor.instance.isPlaying && GameManager.instance.canInput;
} }
public static bool AltPressed() public static bool AltPressed()
{ {
bool down = GetInputController(1).GetButtonDown((int) InputController.ButtonsPad.PadS); bool down = GetInputController(1).GetActionDown((int) InputController.ActionsPad.South, out _);
return down && playerHasControl(); return down && PlayerHasControl();
}
public static bool AltPressed(out double dt)
{
bool down = GetInputController(1).GetActionDown((int) InputController.ActionsPad.South, out dt);
return down && PlayerHasControl();
} }
public static bool AltPressedUp() public static bool AltPressedUp()
{ {
bool up = GetInputController(1).GetButtonUp((int) InputController.ButtonsPad.PadS); bool up = GetInputController(1).GetActionUp((int) InputController.ActionsPad.South, out _);
return up && playerHasControl(); return up && PlayerHasControl();
}
public static bool AltPressedUp(out double dt)
{
bool up = GetInputController(1).GetActionUp((int) InputController.ActionsPad.South, out dt);
return up && PlayerHasControl();
} }
public static bool AltPressing() public static bool AltPressing()
{ {
bool pressing = GetInputController(1).GetButton((int) InputController.ButtonsPad.PadS); bool pressing = GetInputController(1).GetAction((int) InputController.ActionsPad.South);
return pressing && playerHasControl(); return pressing && PlayerHasControl();
} }
//Directions //Directions
@ -234,23 +256,45 @@ namespace HeavenStudio
public static bool GetAnyDirectionDown() public static bool GetAnyDirectionDown()
{ {
InputController c = GetInputController(1); InputController c = GetInputController(1);
return (c.GetHatDirectionDown((InputController.InputDirection) UP) return (c.GetHatDirectionDown((InputController.InputDirection) UP, out _)
|| c.GetHatDirectionDown((InputController.InputDirection) DOWN) || c.GetHatDirectionDown((InputController.InputDirection) DOWN, out _)
|| c.GetHatDirectionDown((InputController.InputDirection) LEFT) || c.GetHatDirectionDown((InputController.InputDirection) LEFT, out _)
|| c.GetHatDirectionDown((InputController.InputDirection) RIGHT) || c.GetHatDirectionDown((InputController.InputDirection) RIGHT, out _)
) && playerHasControl(); ) && PlayerHasControl();
}
public static bool GetAnyDirectionDown(out double dt)
{
InputController c = GetInputController(1);
bool r1 = c.GetHatDirectionDown((InputController.InputDirection)UP, out double d1);
bool r2 = c.GetHatDirectionDown((InputController.InputDirection)DOWN, out double d2);
bool r3 = c.GetHatDirectionDown((InputController.InputDirection)LEFT, out double d3);
bool r4 = c.GetHatDirectionDown((InputController.InputDirection)RIGHT, out double d4);
bool r = (r1 || r2 || r3 || r4) && PlayerHasControl();
dt = Math.Max(Math.Max(Math.Max(d1, d2), d3), d4);
return r;
} }
public static bool GetAnyDirectionUp() public static bool GetAnyDirectionUp()
{ {
InputController c = GetInputController(1); InputController c = GetInputController(1);
return (c.GetHatDirectionUp((InputController.InputDirection) UP) return (c.GetHatDirectionUp((InputController.InputDirection) UP, out _)
|| c.GetHatDirectionUp((InputController.InputDirection) DOWN) || c.GetHatDirectionUp((InputController.InputDirection) DOWN, out _)
|| c.GetHatDirectionUp((InputController.InputDirection) LEFT) || c.GetHatDirectionUp((InputController.InputDirection) LEFT, out _)
|| c.GetHatDirectionUp((InputController.InputDirection) RIGHT) || c.GetHatDirectionUp((InputController.InputDirection) RIGHT, out _)
) && playerHasControl(); ) && PlayerHasControl();
}
public static bool GetAnyDirectionUp(out double dt)
{
InputController c = GetInputController(1);
bool r1 = c.GetHatDirectionUp((InputController.InputDirection)UP, out double d1);
bool r2 = c.GetHatDirectionUp((InputController.InputDirection)DOWN, out double d2);
bool r3 = c.GetHatDirectionUp((InputController.InputDirection)LEFT, out double d3);
bool r4 = c.GetHatDirectionUp((InputController.InputDirection)RIGHT, out double d4);
bool r = (r1 || r2 || r3 || r4) && PlayerHasControl();
dt = Math.Max(Math.Max(Math.Max(d1, d2), d3), d4);
return r;
} }
public static bool GetAnyDirection() public static bool GetAnyDirection()
@ -260,23 +304,32 @@ namespace HeavenStudio
|| c.GetHatDirection((InputController.InputDirection) DOWN) || c.GetHatDirection((InputController.InputDirection) DOWN)
|| c.GetHatDirection((InputController.InputDirection) LEFT) || c.GetHatDirection((InputController.InputDirection) LEFT)
|| c.GetHatDirection((InputController.InputDirection) RIGHT) || c.GetHatDirection((InputController.InputDirection) RIGHT)
) && playerHasControl(); ) && PlayerHasControl();
} }
public static bool GetSpecificDirection(int direction) public static bool GetSpecificDirection(int direction)
{ {
return GetInputController(1).GetHatDirection((InputController.InputDirection) direction) && playerHasControl(); return GetInputController(1).GetHatDirection((InputController.InputDirection) direction) && PlayerHasControl();
} }
public static bool GetSpecificDirectionDown(int direction) public static bool GetSpecificDirectionDown(int direction)
{ {
return GetInputController(1).GetHatDirectionDown((InputController.InputDirection) direction) && playerHasControl(); return GetInputController(1).GetHatDirectionDown((InputController.InputDirection) direction, out _) && PlayerHasControl();
} }
public static bool GetSpecificDirectionUp(int direction) public static bool GetSpecificDirectionUp(int direction)
{ {
return GetInputController(1).GetHatDirectionUp((InputController.InputDirection) direction) && playerHasControl(); return GetInputController(1).GetHatDirectionUp((InputController.InputDirection) direction, out _) && PlayerHasControl();
}
public static bool GetSpecificDirectionDown(int direction, out double dt)
{
return GetInputController(1).GetHatDirectionDown((InputController.InputDirection) direction, out dt) && PlayerHasControl();
}
public static bool GetSpecificDirectionUp(int direction, out double dt)
{
return GetInputController(1).GetHatDirectionUp((InputController.InputDirection) direction, out dt) && PlayerHasControl();
} }
} }
} }

View file

@ -41,13 +41,13 @@ namespace HeavenStudio.Common
{ {
if (cond.songPositionInBeatsAsDouble > starStart && state == StarState.In) if (cond.songPositionInBeatsAsDouble > starStart && state == StarState.In)
{ {
double offset = cond.SecsToBeats(Minigame.AceStartTime()-1, cond.GetBpmAtBeat(StarTargetTime)); double offset = cond.SecsToBeats(Minigame.AceEarlyTime()-1, cond.GetBpmAtBeat(StarTargetTime));
if (cond.songPositionInBeatsAsDouble <= starStart + starLength + offset) if (cond.songPositionInBeatsAsDouble <= starStart + starLength + offset)
starAnim.DoScaledAnimation("StarIn", starStart, starLength + (float)offset); starAnim.DoScaledAnimation("StarIn", starStart, starLength + (float)offset);
else else
starAnim.Play("StarIn", -1, 1f); starAnim.Play("StarIn", -1, 1f);
offset = cond.SecsToBeats(Minigame.AceEndTime()-1, cond.GetBpmAtBeat(StarTargetTime)); offset = cond.SecsToBeats(Minigame.AceLateTime()-1, cond.GetBpmAtBeat(StarTargetTime));
if (cond.songPositionInBeatsAsDouble > starStart + starLength + offset) if (cond.songPositionInBeatsAsDouble > starStart + starLength + offset)
KillStar(); KillStar();
} }
@ -94,8 +94,8 @@ namespace HeavenStudio.Common
public bool DoStarJust() public bool DoStarJust()
{ {
if (state == StarState.In && if (state == StarState.In &&
cond.songPositionInBeatsAsDouble >= StarTargetTime + cond.SecsToBeats(Minigame.AceStartTime()-1, cond.GetBpmAtBeat(StarTargetTime)) && cond.songPositionInBeatsAsDouble >= StarTargetTime + cond.SecsToBeats(Minigame.AceEarlyTime()-1, cond.GetBpmAtBeat(StarTargetTime)) &&
cond.songPositionInBeatsAsDouble <= StarTargetTime + cond.SecsToBeats(Minigame.AceEndTime()-1, cond.GetBpmAtBeat(StarTargetTime)) cond.songPositionInBeatsAsDouble <= StarTargetTime + cond.SecsToBeats(Minigame.AceLateTime()-1, cond.GetBpmAtBeat(StarTargetTime))
) )
{ {
state = StarState.Collected; state = StarState.Collected;

View file

@ -87,12 +87,12 @@ namespace HeavenStudio.Common
// SetArrowPos(time); // SetArrowPos(time);
// no Clamp() because double // no Clamp() because double
time = System.Math.Max(Minigame.EarlyTime(), System.Math.Min(Minigame.EndTime(), time)); time = System.Math.Max(Minigame.NgEarlyTime(), System.Math.Min(Minigame.NgLateTime(), time));
if (time >= Minigame.AceStartTime() && time <= Minigame.AceEndTime()) if (time >= Minigame.AceEarlyTime() && time <= Minigame.AceLateTime())
{ {
type = Rating.Just; type = Rating.Just;
frac = (float)((time - Minigame.AceStartTime()) / (Minigame.AceEndTime() - Minigame.AceStartTime())); frac = (float)((time - Minigame.AceEarlyTime()) / (Minigame.AceLateTime() - Minigame.AceEarlyTime()));
y = barJustTransform.localScale.y * frac - (barJustTransform.localScale.y * 0.5f); y = barJustTransform.localScale.y * frac - (barJustTransform.localScale.y * 0.5f);
} }
else else
@ -100,32 +100,32 @@ namespace HeavenStudio.Common
if (time > 1.0) if (time > 1.0)
{ {
// goes "down" // goes "down"
if (time <= Minigame.LateTime()) if (time <= Minigame.JustLateTime())
{ {
type = Rating.OK; type = Rating.OK;
frac = (float)((time - Minigame.AceEndTime()) / (Minigame.LateTime() - Minigame.AceEndTime())); frac = (float)((time - Minigame.AceLateTime()) / (Minigame.JustLateTime() - Minigame.AceLateTime()));
y = ((barOKTransform.localScale.y - barJustTransform.localScale.y) * frac) + barJustTransform.localScale.y; y = ((barOKTransform.localScale.y - barJustTransform.localScale.y) * frac) + barJustTransform.localScale.y;
} }
else else
{ {
type = Rating.NG; type = Rating.NG;
frac = (float)((time - Minigame.LateTime()) / (Minigame.EndTime() - Minigame.LateTime())); frac = (float)((time - Minigame.JustLateTime()) / (Minigame.NgLateTime() - Minigame.JustLateTime()));
y = ((barNGTransform.localScale.y - barOKTransform.localScale.y) * frac) + barOKTransform.localScale.y; y = ((barNGTransform.localScale.y - barOKTransform.localScale.y) * frac) + barOKTransform.localScale.y;
} }
} }
else else
{ {
// goes "up" // goes "up"
if (time >= Minigame.PerfectTime()) if (time >= Minigame.JustEarlyTime())
{ {
type = Rating.OK; type = Rating.OK;
frac = (float)((time - Minigame.PerfectTime()) / (Minigame.AceStartTime() - Minigame.PerfectTime())); frac = (float)((time - Minigame.JustEarlyTime()) / (Minigame.AceEarlyTime() - Minigame.JustEarlyTime()));
y = ((barOKTransform.localScale.y - barJustTransform.localScale.y) * -frac) - barJustTransform.localScale.y; y = ((barOKTransform.localScale.y - barJustTransform.localScale.y) * -frac) - barJustTransform.localScale.y;
} }
else else
{ {
type = Rating.NG; type = Rating.NG;
frac = (float)((time - Minigame.EarlyTime()) / (Minigame.PerfectTime() - Minigame.EarlyTime())); frac = (float)((time - Minigame.NgEarlyTime()) / (Minigame.JustEarlyTime() - Minigame.NgEarlyTime()));
y = ((barNGTransform.localScale.y - barOKTransform.localScale.y) * -frac) - barOKTransform.localScale.y; y = ((barNGTransform.localScale.y - barOKTransform.localScale.y) * -frac) - barOKTransform.localScale.y;
} }
} }

View file

@ -85,7 +85,7 @@ namespace HeavenStudio.Common
void Update() void Update()
{ {
if (isQuitting) return; if (isQuitting) return;
if (PlayerInput.GetInputController(1).GetButtonDown((int) InputController.ButtonsPad.PadPause)) if (PlayerInput.GetInputController(1).GetActionDown((int) InputController.ActionsPad.Pause, out _))
{ {
if (isPaused) if (isPaused)
{ {
@ -98,7 +98,7 @@ namespace HeavenStudio.Common
} }
else if (isPaused && canPick && !settingsDialog.IsOpen) else if (isPaused && canPick && !settingsDialog.IsOpen)
{ {
if (Input.GetKeyDown(KeyCode.UpArrow) || PlayerInput.GetInputController(1).GetButtonDown((int)InputController.ButtonsPad.PadUp)) if (Input.GetKeyDown(KeyCode.UpArrow) || PlayerInput.GetInputController(1).GetActionDown((int)InputController.ActionsPad.Up, out _))
{ {
optionSelected--; optionSelected--;
if (optionSelected < 0) if (optionSelected < 0)
@ -107,7 +107,7 @@ namespace HeavenStudio.Common
} }
ChooseOption((Options) optionSelected); ChooseOption((Options) optionSelected);
} }
else if (Input.GetKeyDown(KeyCode.DownArrow) || PlayerInput.GetInputController(1).GetButtonDown((int)InputController.ButtonsPad.PadDown)) else if (Input.GetKeyDown(KeyCode.DownArrow) || PlayerInput.GetInputController(1).GetActionDown((int)InputController.ActionsPad.Down, out _))
{ {
optionSelected++; optionSelected++;
if (optionSelected > optionHolder.transform.childCount - 1) if (optionSelected > optionHolder.transform.childCount - 1)
@ -116,7 +116,7 @@ namespace HeavenStudio.Common
} }
ChooseOption((Options) optionSelected); ChooseOption((Options) optionSelected);
} }
else if (Input.GetKeyDown(KeyCode.Return) || PlayerInput.GetInputController(1).GetButtonDown((int)InputController.ButtonsPad.PadE)) else if (Input.GetKeyDown(KeyCode.Return) || PlayerInput.GetInputController(1).GetActionDown((int)InputController.ActionsPad.East, out _))
{ {
UseOption((Options) optionSelected); UseOption((Options) optionSelected);
} }

View file

@ -4,6 +4,7 @@ using System.Collections.Generic;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using TMPro; using TMPro;
using System.Threading.Tasks;
using HeavenStudio; using HeavenStudio;
using HeavenStudio.Util; using HeavenStudio.Util;
@ -20,97 +21,155 @@ namespace HeavenStudio.Editor
[SerializeField] private GameObject pairSearchItem; [SerializeField] private GameObject pairSearchItem;
[SerializeField] private GameObject autoSearchLabel; [SerializeField] private GameObject autoSearchLabel;
[SerializeField] private GameObject pairSearchLabel; [SerializeField] private GameObject pairSearchLabel;
[SerializeField] private GameObject pairSearchCancelBt;
[SerializeField] private TMP_Text pairingLabel; [SerializeField] private TMP_Text pairingLabel;
[SerializeField] private List<GameObject> controllerIcons; [SerializeField] private List<GameObject> controllerIcons;
[SerializeField] private Material controllerMat; [SerializeField] private Material controllerMat;
[SerializeField] private List<GameObject> PadBindingsMenus;
[SerializeField] private List<GameObject> BatonBindingsMenus;
[SerializeField] private List<GameObject> TouchBindingsMenus;
[SerializeField] private List<TMP_Text> PadBindingsTxt;
[SerializeField] private List<TMP_Text> BatonBindingsTxt;
[SerializeField] private List<TMP_Text> TouchBindingsTxt;
private bool isAutoSearching = false; private bool isAutoSearching = false;
private bool isPairSearching = false; private bool isPairSearching = false;
private bool pairSelectLR = false; //true = left, false = right private bool pairSelectLR = false; //true = left, false = right
private bool bindAllMode;
private int currentBindingBt;
private void Start() { private void Start() {
numConnectedLabel.text = "Connected: " + PlayerInput.GetNumControllersConnected(); numConnectedLabel.text = "Connected: " + PlayerInput.GetNumControllersConnected();
currentControllerLabel.text = "Current Controller: " + PlayerInput.GetInputController(1).GetDeviceName(); currentControllerLabel.text = "Current Controller: " + PlayerInput.GetInputController(1).GetDeviceName();
PopulateControllersDropdown(); PopulateControllersDropdown();
pairSearchItem.SetActive(false);
ShowControllerBinds(PlayerInput.GetInputController(1));
ShowControllerIcon(PlayerInput.GetInputController(1)); ShowControllerIcon(PlayerInput.GetInputController(1));
controllersDropdown.onValueChanged.AddListener(delegate
{
InputController lastController = PlayerInput.GetInputController(1);
InputController newController = PlayerInput.GetInputControllers()[controllersDropdown.value];
AssignController(newController, lastController);
});
} }
private void Update() { private void Update() {
if (isAutoSearching) { InputController currentController = PlayerInput.GetInputController(1);
var controllers = PlayerInput.GetInputControllers(); if (currentBindingBt >= 0)
foreach (var controller in controllers) { {
if (controller.GetLastButtonDown() > 0 || controller.GetLastKeyDown() > 0) { int bt = currentController.GetLastButtonDown();
InputController lastController = PlayerInput.GetInputController(1); if (bt > 0)
isAutoSearching = false; {
autoSearchLabel.SetActive(false); InputController.ControlBindings binds = currentController.GetCurrentBindings();
AssignController(controller, lastController); binds.Pad[currentBindingBt] = bt;
currentController.SetCurrentBindings(binds);
currentControllerLabel.text = "Current Controller: " + currentController.GetDeviceName();
ShowControllerBinds(currentController);
AdvanceAutoBind(currentController);
}
return;
}
else
{
if (isAutoSearching) {
var controllers = PlayerInput.GetInputControllers();
foreach (var newController in controllers) {
if (newController.GetLastButtonDown() > 0)
{
isAutoSearching = false;
autoSearchLabel.SetActive(false);
AssignController(newController, currentController);
controllersDropdown.value = PlayerInput.GetInputControllerId(1); controllersDropdown.value = PlayerInput.GetInputControllerId(1);
}
}
}
else if (isPairSearching) {
var controllers = PlayerInput.GetInputControllers();
InputController.InputFeatures lrFlag = pairSelectLR ? InputController.InputFeatures.Extra_SplitControllerLeft : InputController.InputFeatures.Extra_SplitControllerRight;
foreach (var pairController in controllers) {
if (pairController == currentController) continue;
InputController.InputFeatures features = pairController.GetFeatures();
if (!features.HasFlag(lrFlag)) continue;
if (pairController.GetLastButtonDown() > 0)
{
(PlayerInput.GetInputController(1) as InputJoyshock)?.AssignOtherHalf((InputJoyshock) pairController);
isPairSearching = false;
pairSearchLabel.SetActive(false);
currentControllerLabel.text = "Current Controller: " + pairController.GetDeviceName();
pairingLabel.text = "Joy-Con Pair Selected\nPairing Successful!";
ShowControllerIcon(pairController);
currentController.OnSelected();
pairController.OnSelected();
}
} }
} }
} }
else if (isPairSearching) { }
var controllers = PlayerInput.GetInputControllers();
InputController.InputFeatures lrFlag = pairSelectLR ? InputController.InputFeatures.Extra_SplitControllerLeft : InputController.InputFeatures.Extra_SplitControllerRight;
foreach (var controller in controllers) {
if (controller == PlayerInput.GetInputController(1)) continue;
InputController.InputFeatures features = controller.GetFeatures();
if (!features.HasFlag(lrFlag)) continue;
if (controller.GetLastButtonDown() > 0 || controller.GetLastKeyDown() > 0) {
InputJoyshock con = (InputJoyshock) PlayerInput.GetInputController(1);
con.AssignOtherHalf((InputJoyshock) controller);
isPairSearching = false;
pairSearchLabel.SetActive(false);
currentControllerLabel.text = "Current Controller: " + controller.GetDeviceName();
pairingLabel.text = "Joy-Con Pair Selected\nPairing Successful!";
ShowControllerIcon(controller);
StartCoroutine(SelectionVibrate(con)); void AdvanceAutoBind(InputController currentController)
StartCoroutine(SelectionVibrate((InputJoyshock) controller)); {
} if (bindAllMode)
{
currentBindingBt++;
Debug.Log("Binding: " + currentBindingBt);
while (currentController.GetIsActionUnbindable(currentBindingBt, InputController.ControlStyles.Pad) && currentBindingBt < (int)InputController.ActionsPad.Pause)
{
currentBindingBt++;
Debug.Log("Unbindable, binding: " + currentBindingBt);
} }
if (currentBindingBt > (int)InputController.ActionsPad.Pause)
{
currentController.SaveBindings();
CancelBind();
return;
}
currentControllerLabel.text = $"Now Binding: {(InputController.ActionsPad) currentBindingBt}";
}
else
{
currentController.SaveBindings();
CancelBind();
} }
} }
void AssignController(InputController newController, InputController lastController) void AssignController(InputController newController, InputController lastController)
{ {
Debug.Log("Assigning controller: " + newController.GetDeviceName());
lastController.SetPlayer(-1); lastController.SetPlayer(-1);
newController.SetPlayer(1); newController.SetPlayer(1);
if (typeof(InputJoyshock) == lastController.GetType()) { if ((lastController as InputJoyshock) != null)
InputJoyshock con = (InputJoyshock) lastController; {
con.UnAssignOtherHalf(); (lastController as InputJoyshock)?.UnAssignOtherHalf();
} }
if (typeof(InputJoyshock) == newController.GetType()) { if ((newController as InputJoyshock) != null)
InputJoyshock con = (InputJoyshock) newController; {
StartCoroutine(SelectionVibrate(con)); newController.OnSelected();
con.UnAssignOtherHalf(); (newController as InputJoyshock)?.UnAssignOtherHalf();
} }
currentControllerLabel.text = "Current Controller: " + newController.GetDeviceName(); currentControllerLabel.text = "Current Controller: " + newController.GetDeviceName();
ShowControllerBinds(newController);
ShowControllerIcon(newController); ShowControllerIcon(newController);
InputController.InputFeatures features = newController.GetFeatures(); InputController.InputFeatures features = newController.GetFeatures();
if (features.HasFlag(InputController.InputFeatures.Extra_SplitControllerLeft)) { if (features.HasFlag(InputController.InputFeatures.Extra_SplitControllerLeft)) {
pairingLabel.text = "Joy-Con (L) Selected\nPress A to pair with Joy-Con (R)"; pairingLabel.text = "Joy-Con (L) Selected\nPress any button on Joy-Con (R) to pair.";
pairSelectLR = !features.HasFlag(InputController.InputFeatures.Extra_SplitControllerLeft); pairSelectLR = !features.HasFlag(InputController.InputFeatures.Extra_SplitControllerLeft);
pairSearchItem.SetActive(true); pairSearchItem.SetActive(true);
StartPairSearch(); StartPairSearch();
} }
else if (features.HasFlag(InputController.InputFeatures.Extra_SplitControllerRight)) { else if (features.HasFlag(InputController.InputFeatures.Extra_SplitControllerRight)) {
pairingLabel.text = "Joy-Con (R) Selected\nPress A to pair with Joy-Con (L)"; pairingLabel.text = "Joy-Con (R) Selected\nPress any button on Joy-Con (L) to pair.";
pairSelectLR = !features.HasFlag(InputController.InputFeatures.Extra_SplitControllerLeft); pairSelectLR = !features.HasFlag(InputController.InputFeatures.Extra_SplitControllerLeft);
pairSearchItem.SetActive(true); pairSearchItem.SetActive(true);
@ -122,7 +181,53 @@ namespace HeavenStudio.Editor
} }
} }
public void ControllerDropdownChange()
{
CancelBind();
InputController lastController = PlayerInput.GetInputController(1);
lastController.SaveBindings();
InputController newController = PlayerInput.GetInputControllers()[controllersDropdown.value];
AssignController(newController, lastController);
}
public void StartBindSingle(int bt)
{
CancelBind();
if (PlayerInput.GetInputController(1).GetIsActionUnbindable(bt, InputController.ControlStyles.Pad))
{
return;
}
currentBindingBt = bt;
currentControllerLabel.text = $"Now Binding: {(InputController.ActionsPad) bt}";
}
public void StartBindAll()
{
CancelBind();
bindAllMode = true;
currentBindingBt = -1;
AdvanceAutoBind(PlayerInput.GetInputController(1));
}
public void CancelBind()
{
bindAllMode = false;
currentBindingBt = -1;
currentControllerLabel.text = "Current Controller: " + PlayerInput.GetInputController(1).GetDeviceName();
}
public void ResetBindings()
{
CancelBind();
InputController controller = PlayerInput.GetInputController(1);
controller.ResetBindings();
ShowControllerBinds(controller);
controller.SaveBindings();
}
public void StartAutoSearch() { public void StartAutoSearch() {
CancelBind();
if (!isPairSearching) if (!isPairSearching)
{ {
autoSearchLabel.SetActive(true); autoSearchLabel.SetActive(true);
@ -131,15 +236,19 @@ namespace HeavenStudio.Editor
} }
public void StartPairSearch() { public void StartPairSearch() {
CancelBind();
if (!isAutoSearching) { if (!isAutoSearching) {
pairSearchLabel.SetActive(true); pairSearchLabel.SetActive(true);
pairSearchCancelBt.SetActive(true);
isPairSearching = true; isPairSearching = true;
} }
} }
public void CancelPairSearch() { public void CancelPairSearch() {
CancelBind();
if (isPairSearching) { if (isPairSearching) {
pairSearchLabel.SetActive(false); pairSearchLabel.SetActive(false);
pairSearchCancelBt.SetActive(false);
isPairSearching = false; isPairSearching = false;
pairingLabel.text = "Joy-Con Selected\nPairing was cancelled."; pairingLabel.text = "Joy-Con Selected\nPairing was cancelled.";
} }
@ -147,7 +256,7 @@ namespace HeavenStudio.Editor
public void SearchAndConnectControllers() public void SearchAndConnectControllers()
{ {
int connected = PlayerInput.InitInputControllers(); int connected = PlayerInput.RefreshInputControllers();
numConnectedLabel.text = "Connected: " + connected; numConnectedLabel.text = "Connected: " + connected;
currentControllerLabel.text = "Current Controller: " + PlayerInput.GetInputController(1).GetDeviceName(); currentControllerLabel.text = "Current Controller: " + PlayerInput.GetInputController(1).GetDeviceName();
PopulateControllersDropdown(); PopulateControllersDropdown();
@ -165,12 +274,40 @@ namespace HeavenStudio.Editor
} }
controllersDropdown.ClearOptions(); controllersDropdown.ClearOptions();
controllersDropdown.AddOptions(dropDownData); controllersDropdown.AddOptions(dropDownData);
controllersDropdown.value = 0; controllersDropdown.value = PlayerInput.GetInputControllerId(1);
}
public void ShowControllerBinds(InputController controller)
{
string[] buttons = controller.GetButtonNames();
//show binds
int ac = 0;
foreach (int i in controller.GetCurrentBindings().Pad)
{
if (ac >= PadBindingsTxt.Count) break;
if (i == -1)
{
PadBindingsTxt[ac].text = "NOT BOUND";
}
else if (buttons[i] == null)
{
PadBindingsTxt[ac].text = "UNKNOWN";
}
else
{
PadBindingsTxt[ac].text = buttons[i];
}
ac++;
}
} }
public void ShowControllerIcon(InputController controller) public void ShowControllerIcon(InputController controller)
{ {
string name = controller.GetDeviceName(); string name = controller.GetDeviceName();
//show icon
foreach (var icon in controllerIcons) foreach (var icon in controllerIcons)
{ {
if (icon.name == name) if (icon.name == name)
@ -182,6 +319,7 @@ namespace HeavenStudio.Editor
icon.SetActive(false); icon.SetActive(false);
} }
} }
//setup material //setup material
Color colour; Color colour;
switch (name) switch (name)
@ -235,23 +373,14 @@ namespace HeavenStudio.Editor
} }
} }
IEnumerator SelectionVibrate(InputJoyshock controller)
{
JslSetRumbleFrequency(controller.GetHandle(), 0.4f, 0.4f, 80f, 160f);
yield return new WaitForSeconds(0.15f);
JslSetRumbleFrequency(controller.GetHandle(), 0f, 0f, 0f, 0f);
yield return new WaitForSeconds(0.05f);
JslSetRumbleFrequency(controller.GetHandle(), 0.5f, 0.5f, 160f, 320f);
yield return new WaitForSeconds(0.25f);
JslSetRumbleFrequency(controller.GetHandle(), 0f, 0f, 0f, 0f);
}
public override void OnOpenTab() public override void OnOpenTab()
{ {
CancelBind();
} }
public override void OnCloseTab() public override void OnCloseTab()
{ {
CancelBind();
} }
} }
} }