@@ -125,9 +125,10 @@ inline constinit struct ExEdit092 {
125
125
uint8_t * easing_specs_script; // 0x231d90
126
126
127
127
uintptr_t cmp_shift_state_easing; // 0x02ca90
128
+ byte* call_easing_popup_menu; // 0x02d4b5
128
129
129
130
// index: index of the script; zero1, zero2: zero, unknown otherwise.
130
- void (*load_easing_spec)(int32_t index, int32_t zero1, int32_t zero2); // 0x087940;
131
+ void (*load_easing_spec)(int32_t index, int32_t zero1, int32_t zero2); // 0x087940
131
132
132
133
private:
133
134
void init_pointers ()
@@ -160,6 +161,7 @@ inline constinit struct ExEdit092 {
160
161
pick_addr (easing_specs_script, 0x231d90 );
161
162
162
163
pick_addr (cmp_shift_state_easing, 0x02ca90 );
164
+ pick_addr (call_easing_popup_menu, 0x02d4b5 );
163
165
pick_addr (load_easing_spec, 0x087940 );
164
166
}
165
167
} exedit;
@@ -205,7 +207,7 @@ bool check_window_class(HWND hwnd, const wchar_t(&classname)[N])
205
207
{
206
208
wchar_t buf[N + 1 ];
207
209
return ::GetClassNameW (hwnd, buf, N + 1 ) == N - 1
208
- && std::memcmp (buf, classname, sizeof ( wchar_t ) * ( N - 1 ) ) == 0 ;
210
+ && std::wmemcmp (buf, classname, N - 1 ) == 0 ;
209
211
}
210
212
211
213
inline auto get_edit_selection (HWND edit_box)
@@ -227,6 +229,15 @@ inline bool key_pressed_any(auto... vkeys) {
227
229
return ((::GetKeyState (vkeys) < 0 ) || ...);
228
230
}
229
231
232
+ inline byte set_key_state (byte vkey, byte state)
233
+ {
234
+ byte states[0x100 ];
235
+ std::ignore = ::GetKeyboardState (states);
236
+ std::swap (state, states[vkey]);
237
+ ::SetKeyboardState (states);
238
+ return state;
239
+ }
240
+
230
241
inline void discard_message (HWND hwnd, UINT message) {
231
242
MSG msg;
232
243
while (::PeekMessageW (&msg, hwnd, message, message, PM_REMOVE));
@@ -369,18 +380,31 @@ struct TextBox : SettingDlg {
369
380
struct TrackLabel : SettingDlg {
370
381
private:
371
382
// finding edit boxes for trackbars.
372
- constexpr static int id_label_left_base = 4100 , id_label_right_base = 4200 ;
383
+ constexpr static uint32_t id_button_base = 4000 ,
384
+ id_label_left_base = 4100 , id_label_right_base = 4200 ;
373
385
374
386
public:
375
387
static uintptr_t hook_uid () { return SettingDlg::hook_uid () + 2 ; }
376
388
377
- static std::pair<bool , int8_t > check_edit_box_id (uint32_t id)
389
+ static constexpr int8_t check_button_id (uint32_t id)
390
+ {
391
+ auto idx = id - id_button_base;
392
+ if (idx >= Object::MAX_TRACK) return -1 ;
393
+ return static_cast <int8_t >(idx);
394
+ }
395
+ static constexpr uint32_t button_id (size_t idx) {
396
+ return idx + id_button_base;
397
+ }
398
+ static constexpr std::pair<bool , int8_t > check_edit_box_id (uint32_t id)
378
399
{
379
400
bool left = id < id_label_right_base;
380
401
id -= left ? id_label_left_base : id_label_right_base;
381
402
if (id >= Object::MAX_TRACK) return { false , -1 };
382
403
return { left , static_cast <int8_t >(id) };
383
404
}
405
+ static constexpr uint32_t label_id (bool left, size_t idx) {
406
+ return idx + (left ? id_label_left_base : id_label_right_base);
407
+ }
384
408
static bool check_edit_box_style (HWND edit)
385
409
{
386
410
// check whether ...
@@ -479,17 +503,30 @@ struct TrackLabel : SettingDlg {
479
503
480
504
private:
481
505
// manipulation of the currently selected trackbar.
482
- static inline constinit const TrackInfo* info = nullptr ;
483
- static inline constinit wchar_t last_text[15 ] = L" " ;
506
+ static inline constinit TrackInfo const * info = nullptr ;
507
+ static inline constinit wchar_t last_text[16 ] = L" " ;
484
508
485
509
public:
486
510
static inline POINT mouse_pos_on_focused{};
487
- static const TrackInfo& curr_info () { return *info; }
488
- static void on_setfocus (const TrackInfo* track_info)
511
+ static inline struct {
512
+ uint16_t idx = ~0 ;
513
+ byte alt_state = 0 ;
514
+ constexpr bool is_active () const { return idx < Object::MAX_TRACK; }
515
+ constexpr void activate (size_t idx) { this ->idx = static_cast <decltype (this ->idx )>(idx); }
516
+ constexpr void deactivate () { idx = ~0 ; alt_state = 0 ; }
517
+ } easing_menu;
518
+ static TrackInfo const & curr_info () { return *info; }
519
+ constexpr static size_t max_num_len = std::size(last_text);
520
+ static size_t find_info_index (TrackInfo const * ptr_info) {
521
+ return std::min<size_t >(ptr_info - exedit.trackinfo_left , ptr_info - exedit.trackinfo_right );
522
+ }
523
+ static void on_setfocus (TrackInfo const * track_info)
489
524
{
490
- ::GetCursorPos (&mouse_pos_on_focused);
491
525
info = track_info;
492
- ::GetWindowTextW (track_info->hwnd_label, last_text, std::size(last_text));
526
+ if (!easing_menu.is_active ()) {
527
+ ::GetCursorPos (&mouse_pos_on_focused);
528
+ ::GetWindowTextW (track_info->hwnd_label, last_text, std::size(last_text));
529
+ }
493
530
}
494
531
static void on_killfocus () { info = nullptr ; }
495
532
static bool is_focused () { return info != nullptr ; }
@@ -1178,15 +1215,17 @@ inline constinit struct Settings {
1178
1215
return (boost (keys) ? rate_boost : 1 ) * (decimal (keys) ? 1 : info.precision ());
1179
1216
}
1180
1217
};
1218
+ struct shortcut_key {
1219
+ byte vkey;
1220
+ modkeys mkeys;
1221
+ constexpr bool match (byte code, modkeys keys) const {
1222
+ return is_enabled () && code == vkey && mkeys == keys;
1223
+ }
1224
+ constexpr bool is_enabled () const { return vkey != 0 ; }
1225
+ };
1181
1226
1182
1227
struct {
1183
- struct {
1184
- byte vkey;
1185
- modkeys mkeys;
1186
- constexpr bool match (byte code, modkeys keys) const {
1187
- return vkey != 0 && code == vkey && mkeys == keys;
1188
- }
1189
- } forward{ VK_TAB, modkeys::none }, backward{ VK_TAB, modkeys::shift };
1228
+ shortcut_key forward{ VK_TAB, modkeys::none }, backward{ VK_TAB, modkeys::shift };
1190
1229
constexpr bool is_enabled () const { return forward.vkey != 0 || backward.vkey != 0 ; }
1191
1230
constexpr bool match (bool & is_forward, auto ... args)
1192
1231
{
@@ -1214,14 +1253,15 @@ inline constinit struct Settings {
1214
1253
1215
1254
struct : modkey_set {
1216
1255
bool updown, updown_clamp, escape;
1217
- constexpr bool is_enabled () const { return updown || escape; }
1256
+ shortcut_key easing_menu;
1257
+ constexpr bool is_enabled () const { return updown || escape || easing_menu.is_enabled (); }
1218
1258
constexpr bool no_wrong_keys (modkeys keys) const
1219
1259
{
1220
1260
return keys <= (keys_decimal | keys_boost);
1221
1261
}
1222
1262
} trackKbd{
1223
1263
{ modkeys::shift, modkeys::alt, false , 10 , },
1224
- true , false , true ,
1264
+ true , false , true , { 0 , modkeys::none },
1225
1265
};
1226
1266
1227
1267
struct : modkey_set {
@@ -1335,6 +1375,8 @@ inline constinit struct Settings {
1335
1375
load_bool (trackKbd., def_decimal, " Track.Keyboard" );
1336
1376
load_gen (trackKbd., rate_boost, " Track.Keyboard" ,
1337
1377
[](auto x) { return std::clamp (x, modkey_set::min_rate_boost, modkey_set::max_rate_boost); }, /* id */ );
1378
+ load_int (trackKbd., easing_menu.vkey , " Track.Keyboard" );
1379
+ load_key (trackKbd., easing_menu.mkeys , " Track.Keyboard" );
1338
1380
1339
1381
load_bool (trackMouse., wheel, " Track.Mouse" );
1340
1382
load_bool (trackMouse., reverse_wheel, " Track.Mouse" );
@@ -1534,7 +1576,7 @@ inline bool delta_move_on_label(byte vkey)
1534
1576
}
1535
1577
1536
1578
// ESC キーで編集前に戻す / フォーカスを外す機能.
1537
- inline bool escape_from_label (HWND edit_box )
1579
+ inline bool escape_from_label ()
1538
1580
{
1539
1581
if (!TrackLabel::is_focused ()) [[unlikely]] return false ;
1540
1582
@@ -1545,6 +1587,62 @@ inline bool escape_from_label(HWND edit_box)
1545
1587
return ::SetFocus (exedit.fp ->hwnd ) != nullptr ; // no need to revert, the focus moves away.
1546
1588
}
1547
1589
1590
+ // トラックバー変化方法の選択メニューを表示する機能.
1591
+ inline bool popup_easing_menu (byte vkey)
1592
+ {
1593
+ if (!settings.trackKbd .easing_menu .match (vkey, curr_modkeys ()) ||
1594
+ key_pressed_any (VK_LWIN, VK_RWIN)) return false ;
1595
+
1596
+ if (!TrackLabel::is_focused ()) [[unlikely]] return false ;
1597
+
1598
+ auto & info = TrackLabel::curr_info ();
1599
+ auto const idx = TrackLabel::find_info_index (&info);
1600
+ if (idx >= Object::MAX_TRACK) return false ;
1601
+
1602
+ // suppress notification sound by discarding certain messages.
1603
+ discard_message (info.hwnd_label , settings.trackKbd .easing_menu .mkeys
1604
+ .has_flags (modkeys::alt) ? WM_SYSCHAR : WM_CHAR);
1605
+
1606
+ // save the index so it the hook is enabled.
1607
+ TrackLabel::easing_menu.activate (idx);
1608
+
1609
+ // move off the focus form this edit box,
1610
+ // otherwise it would swallow the input of Enter key.
1611
+ auto [l_pos, r_pos] = get_edit_selection (info.hwnd_label );
1612
+ wchar_t last_text[TrackLabel::max_num_len];
1613
+ ::GetWindowTextW (info.hwnd_label, last_text, std::size(last_text));
1614
+ ::SetFocus (*exedit.hwnd_setting_dlg);
1615
+
1616
+ if (settings.trackKbd .easing_menu .mkeys .has_flags (modkeys::alt))
1617
+ // as alt+clicking the button has a different functionality,
1618
+ // make the key recognized as released.
1619
+ TrackLabel::easing_menu.alt_state = set_key_state (VK_MENU, 0 );
1620
+ // send the button-click notification.
1621
+ ::SendMessageW (*exedit.hwnd_setting_dlg, WM_COMMAND,
1622
+ (BN_CLICKED << 16 ) | TrackLabel::button_id(idx),
1623
+ reinterpret_cast<LPARAM>(exedit.hwnd_track_buttons[idx]));
1624
+
1625
+ // rewind the focus and other states.
1626
+ if ((::GetWindowLongW (info.hwnd_label , GWL_STYLE) & WS_DISABLED) == 0 ) {
1627
+ ::SetFocus (info.hwnd_label);
1628
+ ::SetWindowTextW (info.hwnd_label, last_text);
1629
+ set_edit_selection (info.hwnd_label , l_pos, r_pos);
1630
+
1631
+ // turn out of the hooking state.
1632
+ TrackLabel::easing_menu.deactivate ();
1633
+ }
1634
+ else {
1635
+ // if it's right side and disabled now, focus on left instead.
1636
+ auto left_one = exedit.trackinfo_left [idx].hwnd_label ;
1637
+
1638
+ TrackLabel::easing_menu.deactivate (); // no more hooks.
1639
+ ::SetFocus (left_one);
1640
+ set_edit_selection_all (left_one);
1641
+ }
1642
+
1643
+ return true ;
1644
+ }
1645
+
1548
1646
// ホイールでトラックバーの数値をテキストラベル上で増減する機能.
1549
1647
inline bool wheel_on_track (const TrackInfo& info, short wheel, modkeys keys)
1550
1648
{
@@ -1690,16 +1788,17 @@ LRESULT CALLBACK track_label_hook(HWND hwnd, UINT message, WPARAM wparam, LPARAM
1690
1788
case WM_KEYDOWN:
1691
1789
case WM_SYSKEYDOWN:
1692
1790
if (byte vkey = static_cast <byte>(wparam);
1693
- settings.trackKbd .updown &&
1694
- delta_move_on_label (vkey)) {
1791
+ settings.trackKbd .updown && delta_move_on_label (vkey)) {
1695
1792
// prevent calling the default window procedure.
1696
1793
return 0 ;
1697
1794
}
1698
- else if (settings.trackKbd .escape && vkey == VK_ESCAPE && escape_from_label (hwnd )) {
1795
+ else if (settings.trackKbd .escape && vkey == VK_ESCAPE && escape_from_label ()) {
1699
1796
// needs to remove WM_CHAR messages to avoid the notification sound.
1700
1797
discard_message (hwnd, message == WM_KEYDOWN ? WM_CHAR : WM_SYSCHAR);
1701
1798
return 0 ;
1702
1799
}
1800
+ else if (settings.trackKbd .easing_menu .is_enabled () && popup_easing_menu (vkey))
1801
+ return 0 ;
1703
1802
break ;
1704
1803
case WM_MOUSEMOVE:
1705
1804
if (settings.trackMouse .fixed_drag &&
@@ -1725,6 +1824,28 @@ LRESULT CALLBACK track_label_hook(HWND hwnd, UINT message, WPARAM wparam, LPARAM
1725
1824
return ::DefSubclassProc (hwnd, message, wparam, lparam);
1726
1825
}
1727
1826
1827
+ // トラックバー変化方法のメニューをショートカットキーで表示させたときの座標調整.
1828
+ BOOL WINAPI popup_easing_menu_hook (HMENU menu, UINT flags, int x, int y, int , HWND hwnd, RECT const *)
1829
+ {
1830
+ if (TrackLabel::easing_menu.is_active ()) {
1831
+ auto const btn = exedit.hwnd_track_buttons [TrackLabel::easing_menu.idx ];
1832
+
1833
+ // Alt の状態を差し戻す.
1834
+ set_key_state (VK_MENU, TrackLabel::easing_menu.alt_state );
1835
+
1836
+ // メニューの位置をボタンの矩形に合わせて調整.
1837
+ TPMPARAMS p{ .cbSize = sizeof (p) };
1838
+ ::GetWindowRect (btn, &p.rcExclude);
1839
+
1840
+ // メニュー表示.
1841
+ return ::TrackPopupMenuEx (menu, flags | TPM_VERTICAL,
1842
+ p.rcExclude .left , p.rcExclude .top , hwnd, &p);
1843
+ }
1844
+
1845
+ // 条件を満たさない場合は未介入のデフォルト処理.
1846
+ return ::TrackPopupMenuEx (menu, flags, x, y, hwnd, nullptr );
1847
+ }
1848
+
1728
1849
LRESULT CALLBACK setting_dlg_hook (HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam, auto id, auto data)
1729
1850
{
1730
1851
switch (message) {
@@ -2049,6 +2170,14 @@ BOOL func_init(FilterPlugin* fp)
2049
2170
conflict_warning (" filter_name.auf" , " [FilterName]\n anim_eff_fmt=\"\" " );
2050
2171
}
2051
2172
2173
+ // トラックバー変化方法のメニューをショートカットキーで表示させたときの座標調整.
2174
+ if (settings.trackKbd .easing_menu .is_enabled ())
2175
+ // ff 15 48 a3 ff 2f call dword ptr ds:[TrackPopupMenu]
2176
+ // V
2177
+ // e8 yy yy yy yy call yyyyyyyy
2178
+ // 90 nop
2179
+ memory::hook_api_call (exedit.call_easing_popup_menu , popup_easing_menu_hook);
2180
+
2052
2181
// トラックバーの変化方法の調整.
2053
2182
if (settings.easings .linked_track_invert_shift )
2054
2183
// 0f 8c 87 00 00 00 jl
@@ -2151,7 +2280,7 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD fdwReason, LPVOID lpvReserved)
2151
2280
// 看板.
2152
2281
// //////////////////////////////
2153
2282
#define PLUGIN_NAME " Reactive Dialog"
2154
- #define PLUGIN_VERSION " v1.63-beta1 "
2283
+ #define PLUGIN_VERSION " v1.70-beta2 "
2155
2284
#define PLUGIN_AUTHOR " sigma-axis"
2156
2285
#define PLUGIN_INFO_FMT (name, ver, author ) (name##" " ##ver##" by " ##author)
2157
2286
#define PLUGIN_INFO PLUGIN_INFO_FMT (PLUGIN_NAME, PLUGIN_VERSION, PLUGIN_AUTHOR)
0 commit comments