mirror of
https://github.com/ocornut/imgui.git
synced 2026-07-06 01:25:19 +00:00
Compare commits
3439 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8936b58fe2 | ||
|
|
eebaddd340 | ||
|
|
73afb6b6e6 | ||
|
|
b8f6c51af7 | ||
|
|
4ac473b2c7 | ||
|
|
ac1f57ba0c | ||
|
|
821a396556 | ||
|
|
2b31f65167 | ||
|
|
b58836f287 | ||
|
|
bca5a69928 | ||
|
|
eb453f2be6 | ||
|
|
56b37bf93c | ||
|
|
0eae77f783 | ||
|
|
02ccd9f348 | ||
|
|
163b8670c8 | ||
|
|
a70b97ee48 | ||
|
|
6df50a0667 | ||
|
|
976c5c0f3a | ||
|
|
691b89baae | ||
|
|
c0b693b1d4 | ||
|
|
865a6dfa59 | ||
|
|
dee9b15bbe | ||
|
|
d1a8995634 | ||
|
|
ab36fbaf48 | ||
|
|
e3033c3975 | ||
|
|
10c378cdfc | ||
|
|
db23a78c60 | ||
|
|
bda49826cf | ||
|
|
6b05f711fd | ||
|
|
86ebb3bc11 | ||
|
|
7e7f3adb80 | ||
|
|
dfe6f9ebca | ||
|
|
37952fb3b8 | ||
|
|
0a811e8ea1 | ||
|
|
82f46a73f8 | ||
|
|
a6a16cf8a2 | ||
|
|
e887098740 | ||
|
|
f934719fbf | ||
|
|
ce3fe4078a | ||
|
|
f2f843c113 | ||
|
|
adc0027912 | ||
|
|
ac06ad7b48 | ||
|
|
4739af2d51 | ||
|
|
b065713cec | ||
|
|
fb308c14ce | ||
|
|
ac261203a5 | ||
|
|
0453ae96e8 | ||
|
|
a5fd597be3 | ||
|
|
382b99c334 | ||
|
|
2d131ef5b7 | ||
|
|
a1e05521e9 | ||
|
|
d7b40ab9a9 | ||
|
|
ac88294b4a | ||
|
|
ea1c04f7ab | ||
|
|
cdb046ac3f | ||
|
|
97939e6837 | ||
|
|
c91b03060d | ||
|
|
a2eb6d99ed | ||
|
|
a2916923a1 | ||
|
|
2cbdb7a337 | ||
|
|
d4783bd553 | ||
|
|
ce855cada2 | ||
|
|
39e7bf5a08 | ||
|
|
0e318a5182 | ||
|
|
19753a30d8 | ||
|
|
6fb74f38af | ||
|
|
4b80d409e7 | ||
|
|
ed4dd679f1 | ||
|
|
3cd8683061 | ||
|
|
bbd0af7256 | ||
|
|
f83a378d62 | ||
|
|
84b4b35902 | ||
|
|
2dc64f99bc | ||
|
|
5da7eb0a84 | ||
|
|
f678c91617 | ||
|
|
6ce4b44547 | ||
|
|
f08b33fd0c | ||
|
|
b444694b3d | ||
|
|
24677c561e | ||
|
|
01a4ad3a50 | ||
|
|
f4ed421a88 | ||
|
|
11de9df44c | ||
|
|
c2565fe642 | ||
|
|
95bd1577d6 | ||
|
|
dd17495a42 | ||
|
|
1870a779e1 | ||
|
|
a9bd173d89 | ||
|
|
bccec3eabc | ||
|
|
d946c6932b | ||
|
|
4d38508c6b | ||
|
|
c0e6580b62 | ||
|
|
6985925244 | ||
|
|
7cb0baeb77 | ||
|
|
49df3116bc | ||
|
|
03a0b00a34 | ||
|
|
4a61188322 | ||
|
|
dac07199cf | ||
|
|
45866bea47 | ||
|
|
65ebca8157 | ||
|
|
9e9fdc97bb | ||
|
|
fc5e421cb9 | ||
|
|
b7bdea3215 | ||
|
|
bf10275aa7 | ||
|
|
0867f6113a | ||
|
|
836278db6c | ||
|
|
505bc9a312 | ||
|
|
07acc8bc87 | ||
|
|
6603cdef98 | ||
|
|
9df0d38d45 | ||
|
|
2ac782fbed | ||
|
|
9fedea83f0 | ||
|
|
ed4cffece7 | ||
|
|
7be8076e9b | ||
|
|
587c4cb87b | ||
|
|
aab17456a7 | ||
|
|
3c78afbbbb | ||
|
|
b003a85143 | ||
|
|
689f837afa | ||
|
|
97075fae4b | ||
|
|
bd3c925680 | ||
|
|
b62cf3894b | ||
|
|
e9eb04ea95 | ||
|
|
ed2e5dd0f0 | ||
|
|
59183cf782 | ||
|
|
59780020f6 | ||
|
|
0b82487fed | ||
|
|
51f590a2a8 | ||
|
|
6c754ed2cb | ||
|
|
79411a0405 | ||
|
|
6b1776a7d2 | ||
|
|
38f5e5a0b8 | ||
|
|
697b6886e3 | ||
|
|
8314fc3e5a | ||
|
|
50b488765f | ||
|
|
4af77622d9 | ||
|
|
2315b9f33d | ||
|
|
04dfcd838b | ||
|
|
2d957152e4 | ||
|
|
325563a982 | ||
|
|
763db046fa | ||
|
|
3a26b640b2 | ||
|
|
386ce49c58 | ||
|
|
b2c3e37d55 | ||
|
|
9700846bb3 | ||
|
|
0b4967992a | ||
|
|
20d8bcb600 | ||
|
|
358d3912c9 | ||
|
|
4d1ba782ee | ||
|
|
0500e546b5 | ||
|
|
7fc3092870 | ||
|
|
b724f940d6 | ||
|
|
4252275c64 | ||
|
|
6abe65aac6 | ||
|
|
f4c2f50896 | ||
|
|
27cacb0e30 | ||
|
|
709be8c495 | ||
|
|
994ca12b29 | ||
|
|
6464276b62 | ||
|
|
16772365e2 | ||
|
|
8957b3df03 | ||
|
|
4a2e3cce69 | ||
|
|
fd752d8357 | ||
|
|
d02c645e38 | ||
|
|
49ee151ed6 | ||
|
|
b76ab6232d | ||
|
|
6dbda97fee | ||
|
|
90743d3112 | ||
|
|
14a500a476 | ||
|
|
6cc99a6e2b | ||
|
|
a103826154 | ||
|
|
0db591935f | ||
|
|
1fbab15c0a | ||
|
|
7546f1eb16 | ||
|
|
5220c14f4b | ||
|
|
378cb85bf0 | ||
|
|
5aa7d61139 | ||
|
|
03a9946a14 | ||
|
|
decb5cdf10 | ||
|
|
5dd56d4bb5 | ||
|
|
512982d0d2 | ||
|
|
9e6b888626 | ||
|
|
83fa0ae263 | ||
|
|
e92820db2a | ||
|
|
6f8bdb7bf7 | ||
|
|
ca166c0e5f | ||
|
|
41765fbda7 | ||
|
|
ba84d2d372 | ||
|
|
11acd9f5cb | ||
|
|
238651ffa3 | ||
|
|
14e0c70f88 | ||
|
|
ef022c5e0a | ||
|
|
c40226e9de | ||
|
|
650eca386e | ||
|
|
848da73a81 | ||
|
|
8a15a1064d | ||
|
|
dd5c604768 | ||
|
|
2b415e642b | ||
|
|
68a91d3060 | ||
|
|
0666da6a72 | ||
|
|
7dec6b6de8 | ||
|
|
33dfa7f834 | ||
|
|
46f0e2e247 | ||
|
|
f6e0953b38 | ||
|
|
14b4d8a625 | ||
|
|
dbee23e09c | ||
|
|
2000008b47 | ||
|
|
37b7a7a9df | ||
|
|
b5ccee78b6 | ||
|
|
221bac8b06 | ||
|
|
05481194b6 | ||
|
|
e8281fdf1a | ||
|
|
f7fbe5bd91 | ||
|
|
c234426f89 | ||
|
|
3fecb234c8 | ||
|
|
0653a0d42a | ||
|
|
635a5c0a12 | ||
|
|
b8a1f74fd9 | ||
|
|
6ded5230d0 | ||
|
|
e118ea06e0 | ||
|
|
f921abe7e7 | ||
|
|
7609963448 | ||
|
|
ff673d31df | ||
|
|
acdaaef625 | ||
|
|
fbe973a8d0 | ||
|
|
eaa32bb787 | ||
|
|
9f2b3bcf7a | ||
|
|
041cdddf35 | ||
|
|
a8bf659143 | ||
|
|
9c33672e5c | ||
|
|
42f28ba305 | ||
|
|
291787bcac | ||
|
|
d67c66c437 | ||
|
|
7b365fa6b4 | ||
|
|
87262dd07a | ||
|
|
8ed10d538e | ||
|
|
9f30044333 | ||
|
|
fd9873a5c2 | ||
|
|
c71b2a1fe6 | ||
|
|
5fe48b6a0e | ||
|
|
1bcc23ef12 | ||
|
|
524f01d248 | ||
|
|
226f62fa8f | ||
|
|
ea83628438 | ||
|
|
76860017d5 | ||
|
|
4b8e41cffb | ||
|
|
a9ca61a7ce | ||
|
|
5166bec5d8 | ||
|
|
6cc7787c77 | ||
|
|
960aff24fc | ||
|
|
8306e32495 | ||
|
|
814c6a194b | ||
|
|
ab6c9d9b12 | ||
|
|
d12b1a938e | ||
|
|
c91bcea7a8 | ||
|
|
c6e54c7ab5 | ||
|
|
d1cf58e590 | ||
|
|
e1217227b2 | ||
|
|
7250fbde2e | ||
|
|
a117055b6b | ||
|
|
b015acc464 | ||
|
|
3050f653cb | ||
|
|
66bb8add73 | ||
|
|
3aba95060e | ||
|
|
cb3b7ff4fb | ||
|
|
d448045669 | ||
|
|
f21307e5c9 | ||
|
|
42b7704b70 | ||
|
|
3803203d47 | ||
|
|
8c0b410371 | ||
|
|
8b86c939c7 | ||
|
|
b933599f00 | ||
|
|
12223cc3e9 | ||
|
|
ea122de913 | ||
|
|
14dfd5bf6b | ||
|
|
5dde06b327 | ||
|
|
21d3299e58 | ||
|
|
d7598aa84f | ||
|
|
9a6eb0ab25 | ||
|
|
a1dfaf4869 | ||
|
|
7143d711bf | ||
|
|
0d08927dae | ||
|
|
791ad9b82d | ||
|
|
f64c7c37ef | ||
|
|
d1c5a66557 | ||
|
|
f5384544cb | ||
|
|
fedf227ea4 | ||
|
|
7a02f4b545 | ||
|
|
ca9b7b4071 | ||
|
|
1566c96ccd | ||
|
|
3389dfd9dd | ||
|
|
9ce41a92c3 | ||
|
|
43a90adc61 | ||
|
|
7b3ad4a282 | ||
|
|
4ce188def8 | ||
|
|
b467a0466c | ||
|
|
69a501df6e | ||
|
|
1dc1964d5b | ||
|
|
f106ccd5fa | ||
|
|
25158fe33b | ||
|
|
960921f03a | ||
|
|
922a11f084 | ||
|
|
b7b8f52437 | ||
|
|
05581da183 | ||
|
|
f006400f05 | ||
|
|
cde6ad3967 | ||
|
|
73dd0e869d | ||
|
|
55ad3b4abd | ||
|
|
d1de937c31 | ||
|
|
d365417e8b | ||
|
|
0ff810038d | ||
|
|
9055c9ed22 | ||
|
|
d87650dffb | ||
|
|
a5dffbec38 | ||
|
|
22ffa3d6d3 | ||
|
|
683f9160b9 | ||
|
|
4e7c05504a | ||
|
|
99bca397d8 | ||
|
|
dc48a7c88e | ||
|
|
4dac00ca0c | ||
|
|
fc89c61089 | ||
|
|
1e7d2adc29 | ||
|
|
bd6f48fe20 | ||
|
|
0d2dd30ee9 | ||
|
|
9971251574 | ||
|
|
a07b2828ce | ||
|
|
9a4fd69f6d | ||
|
|
cf64b7fa72 | ||
|
|
a726bded11 | ||
|
|
7f78f52243 | ||
|
|
60f8b0733c | ||
|
|
fa4b47c5e2 | ||
|
|
a7ecbcdeba | ||
|
|
ded52c71d9 | ||
|
|
9d4fafa671 | ||
|
|
e2c49530cb | ||
|
|
fee06a92ea | ||
|
|
d71091a957 | ||
|
|
d1e262ad55 | ||
|
|
6e0ee6ff03 | ||
|
|
d27dce58cd | ||
|
|
87b193399e | ||
|
|
bfe137893a | ||
|
|
620a33dd85 | ||
|
|
47766ca403 | ||
|
|
7c6febed66 | ||
|
|
1a62292ac0 | ||
|
|
2026e3db88 | ||
|
|
3ff8c466bf | ||
|
|
1f54665799 | ||
|
|
ae873b1e0d | ||
|
|
9c75ef5a61 | ||
|
|
c36162fc6c | ||
|
|
f0699effed | ||
|
|
75db81cf08 | ||
|
|
fd887f5241 | ||
|
|
285e3042ba | ||
|
|
d981b33dd0 | ||
|
|
e768f91dc2 | ||
|
|
3fef0d553d | ||
|
|
3a45bae9dc | ||
|
|
98636f4a23 | ||
|
|
5f82275ba1 | ||
|
|
136d067eed | ||
|
|
324cea1f41 | ||
|
|
ee48fad09d | ||
|
|
6d910d5487 | ||
|
|
26ff93dadc | ||
|
|
a484fd2b56 | ||
|
|
8ff7f35eec | ||
|
|
e8448d0494 | ||
|
|
4ab86e1d61 | ||
|
|
0faa0dba15 | ||
|
|
db6b8e0fb3 | ||
|
|
1f16ca5e5c | ||
|
|
b4a3d423e0 | ||
|
|
68894d4149 | ||
|
|
23bd697f05 | ||
|
|
37f9153105 | ||
|
|
81e01ddebe | ||
|
|
405c802607 | ||
|
|
91b5256c57 | ||
|
|
6ae32c696a | ||
|
|
9afc62d087 | ||
|
|
c3835de38a | ||
|
|
52caa2f38a | ||
|
|
04af1a3917 | ||
|
|
e1f9b8b3a7 | ||
|
|
cfb48969af | ||
|
|
0cf5b93a0a | ||
|
|
d99baf332c | ||
|
|
7e919a543c | ||
|
|
eb19a77848 | ||
|
|
b885382a63 | ||
|
|
9e15ebb402 | ||
|
|
f145b0cffd | ||
|
|
c254db7637 | ||
|
|
5a0c67c4b8 | ||
|
|
ec6219752d | ||
|
|
d246850787 | ||
|
|
e60e5bff63 | ||
|
|
873fe34b31 | ||
|
|
e3979c2098 | ||
|
|
68a44776bd | ||
|
|
613cfaf0b4 | ||
|
|
de917ebb95 | ||
|
|
501e0adcdb | ||
|
|
a2544f9496 | ||
|
|
b51f6e073c | ||
|
|
52e9d94f93 | ||
|
|
fc262355ca | ||
|
|
7537ba2b44 | ||
|
|
86daa8930e | ||
|
|
635eb1d8e9 | ||
|
|
bd0e2036e0 | ||
|
|
b0d3c3a674 | ||
|
|
dacd080639 | ||
|
|
8e2e87d638 | ||
|
|
e389502ffb | ||
|
|
1c3a60047c | ||
|
|
62162747e7 | ||
|
|
189d8c9d9c | ||
|
|
f45adb995c | ||
|
|
7954d6782e | ||
|
|
59db6ceeb1 | ||
|
|
a0bfbe4d8f | ||
|
|
e674f57bb6 | ||
|
|
1897248bda | ||
|
|
051a31594f | ||
|
|
dc6e0f4b9e | ||
|
|
df3f2fff88 | ||
|
|
8e5e79054e | ||
|
|
3cc8b470a6 | ||
|
|
f1becf7e4b | ||
|
|
a3546b52f8 | ||
|
|
823ccc274e | ||
|
|
ff672b2db3 | ||
|
|
778aed9966 | ||
|
|
c5b2a848fa | ||
|
|
d0e3b1d4e2 | ||
|
|
505ff536f9 | ||
|
|
db577cd445 | ||
|
|
149587b85b | ||
|
|
670a92723a | ||
|
|
130c3e6b75 | ||
|
|
3c578fa87e | ||
|
|
8df962a6ed | ||
|
|
2a194e21a0 | ||
|
|
9753c741b9 | ||
|
|
7c483a0eba | ||
|
|
0ba9fedf1a | ||
|
|
2c54b15a5f | ||
|
|
2a229c8cb8 | ||
|
|
40f9e4e8e2 | ||
|
|
245e12cca7 | ||
|
|
8019d39545 | ||
|
|
a1632c6116 | ||
|
|
c72d0b2cbb | ||
|
|
e6125361f9 | ||
|
|
b7e45b3a48 | ||
|
|
6add99f8d2 | ||
|
|
750c5d2a61 | ||
|
|
e571ccf3f4 | ||
|
|
b8573a7e33 | ||
|
|
bc5da9b367 | ||
|
|
b3dab0a406 | ||
|
|
2a022d997b | ||
|
|
5870b979a8 | ||
|
|
bdb8243602 | ||
|
|
b46f099a3f | ||
|
|
63bfad401f | ||
|
|
e11b7a0414 | ||
|
|
065f9e0269 | ||
|
|
4b1f5aba80 | ||
|
|
71447b94fb | ||
|
|
3dc511c71d | ||
|
|
36de604a5b | ||
|
|
2a5e9a15e4 | ||
|
|
d7fec5e1d3 | ||
|
|
7d8d587bc0 | ||
|
|
9a5d5c45f5 | ||
|
|
25e5baf5f0 | ||
|
|
c8db91b7b4 | ||
|
|
702cc9993a | ||
|
|
bad5ee167b | ||
|
|
b6e277980f | ||
|
|
878c863af4 | ||
|
|
9be4f150ef | ||
|
|
00251c8921 | ||
|
|
5af650fc6d | ||
|
|
2b770a029b | ||
|
|
bee2720faa | ||
|
|
fd0873c61f | ||
|
|
ee3d16f150 | ||
|
|
4b858cf5d1 | ||
|
|
09e15e8c9d | ||
|
|
2128e2f44b | ||
|
|
27a9374ef3 | ||
|
|
1cdec11e24 | ||
|
|
3ac624b795 | ||
|
|
a97b0c32ab | ||
|
|
bcf722e637 | ||
|
|
8c22b8aef6 | ||
|
|
fc4105c8a8 | ||
|
|
ea564a6a5e | ||
|
|
9809b0b061 | ||
|
|
b987970870 | ||
|
|
a3d6e82dbd | ||
|
|
3dafd9e898 | ||
|
|
5cd83e689e | ||
|
|
5ce903af6e | ||
|
|
bab3ebec14 | ||
|
|
3ff195f702 | ||
|
|
e459e5bf0a | ||
|
|
217bc445ff | ||
|
|
1c87024840 | ||
|
|
3470e6112b | ||
|
|
e312b99296 | ||
|
|
cc0a6690bf | ||
|
|
5fe962216a | ||
|
|
01686c6294 | ||
|
|
bf2e0b2c6f | ||
|
|
cee40f8af9 | ||
|
|
940627d008 | ||
|
|
719ea9c228 | ||
|
|
f61a7ef222 | ||
|
|
e06b5dfe12 | ||
|
|
e1aea42e45 | ||
|
|
82e9a5e47d | ||
|
|
5f6eaa5278 | ||
|
|
d701ffb478 | ||
|
|
a00e517a81 | ||
|
|
8868ad67e4 | ||
|
|
301e652376 | ||
|
|
dc0198a7e4 | ||
|
|
ef6fe2ecee | ||
|
|
46e6382b69 | ||
|
|
087fbf08f6 | ||
|
|
d4f722d5b2 | ||
|
|
0e7cd694eb | ||
|
|
bf75bfec48 | ||
|
|
1c544ee941 | ||
|
|
70a43f3088 | ||
|
|
9cf9d2be83 | ||
|
|
7e473d38d3 | ||
|
|
6d834d325e | ||
|
|
f6890ed007 | ||
|
|
431f2c5abd | ||
|
|
6274ca4266 | ||
|
|
d92c8c6aff | ||
|
|
72c00f39c1 | ||
|
|
2675b7ca26 | ||
|
|
10d0162378 | ||
|
|
3c6c5692b8 | ||
|
|
e044d99710 | ||
|
|
22a6a83c54 | ||
|
|
cd476b27f8 | ||
|
|
9f13684d70 | ||
|
|
6d25cb844b | ||
|
|
36133d8ac4 | ||
|
|
b6a33f8ce1 | ||
|
|
78c1d4a92c | ||
|
|
7f1e2bb8dd | ||
|
|
2f3e85bc37 | ||
|
|
8a94422246 | ||
|
|
ae832ce532 | ||
|
|
1e52e7b90c | ||
|
|
67085d732a | ||
|
|
f36c65661c | ||
|
|
e2b7d84e96 | ||
|
|
271f476d08 | ||
|
|
e2f314d613 | ||
|
|
8eb22ea620 | ||
|
|
55f590c1d1 | ||
|
|
5e5658e68f | ||
|
|
013c4ed476 | ||
|
|
2f1d1c8b2f | ||
|
|
1cd08b883c | ||
|
|
4e98fb20e2 | ||
|
|
045645e5f1 | ||
|
|
8e4955bb23 | ||
|
|
e66afbbbe0 | ||
|
|
2841c5135d | ||
|
|
bf52f4a83c | ||
|
|
14e076c5bb | ||
|
|
ea8a5a9e17 | ||
|
|
230418a75d | ||
|
|
16415aa39f | ||
|
|
985723ed94 | ||
|
|
a82f66a9b0 | ||
|
|
e422a38e4c | ||
|
|
11fff1ccf5 | ||
|
|
3cc7d1c81a | ||
|
|
56189cd814 | ||
|
|
a9945899c6 | ||
|
|
bc6478f651 | ||
|
|
34ab6c8a89 | ||
|
|
c63b5bd8fb | ||
|
|
8a35ce0e98 | ||
|
|
f77f68a5ed | ||
|
|
bed08daede | ||
|
|
09ebcf1779 | ||
|
|
02af06ea5f | ||
|
|
026d47cd35 | ||
|
|
c63714822f | ||
|
|
26aa81a8b1 | ||
|
|
1ecc34a0b1 | ||
|
|
ee03cef14f | ||
|
|
e51d93e2f5 | ||
|
|
7d33524042 | ||
|
|
605a751571 | ||
|
|
b7cb3d93a4 | ||
|
|
20160ff1d5 | ||
|
|
3766d40394 | ||
|
|
0dd3c845eb | ||
|
|
8dc457fda2 | ||
|
|
0ef9610e70 | ||
|
|
5c92699f5f | ||
|
|
771fae623d | ||
|
|
6351f00ff1 | ||
|
|
55cbc66508 | ||
|
|
9f969944d5 | ||
|
|
aa2f40c3bb | ||
|
|
a309d2dcac | ||
|
|
87c1ab7988 | ||
|
|
319c481abb | ||
|
|
229d56e37a | ||
|
|
7d230594de | ||
|
|
75a4a48d1f | ||
|
|
9e864012ae | ||
|
|
783f1e62cc | ||
|
|
e728b96600 | ||
|
|
fe03035112 | ||
|
|
515c0b526f | ||
|
|
7c6fa8f8f7 | ||
|
|
42656b3aa1 | ||
|
|
89b7fc906a | ||
|
|
0c4f50090a | ||
|
|
720e94f3da | ||
|
|
321e9eb919 | ||
|
|
655601169b | ||
|
|
361e370fe0 | ||
|
|
86ec5c8342 | ||
|
|
45acd5e0e8 | ||
|
|
774ddb58bd | ||
|
|
4dee11a089 | ||
|
|
43e3ac0dc6 | ||
|
|
02f654cbce | ||
|
|
e1baadba84 | ||
|
|
e2a662eed8 | ||
|
|
e1a93805db | ||
|
|
af920e1e6f | ||
|
|
863e989c25 | ||
|
|
2b24f5fa71 | ||
|
|
e10300ed3c | ||
|
|
5a6fa33b88 | ||
|
|
8239a0e0c4 | ||
|
|
50115596dc | ||
|
|
1c57dc21c2 | ||
|
|
47c41483bd | ||
|
|
ea075ed973 | ||
|
|
b6614f6c7c | ||
|
|
9ee3d731b5 | ||
|
|
e7d0ad092c | ||
|
|
412daf7362 | ||
|
|
c22af8c346 | ||
|
|
1bf41a0762 | ||
|
|
284283615b | ||
|
|
d163e20f63 | ||
|
|
f7eae45ae9 | ||
|
|
ff2dfc8422 | ||
|
|
7e701c18c8 | ||
|
|
90025a62c7 | ||
|
|
902b8cc39a | ||
|
|
70cfc02811 | ||
|
|
250bd66b76 | ||
|
|
c14d83d4e0 | ||
|
|
7d5fef8642 | ||
|
|
22fe9fce4c | ||
|
|
320c94bfaa | ||
|
|
3ef6c8410a | ||
|
|
cc1fbcc9a9 | ||
|
|
78d11cd781 | ||
|
|
7278cda039 | ||
|
|
7bb9db501c | ||
|
|
046a8eae0f | ||
|
|
a0cdac48e0 | ||
|
|
2ab3946ecb | ||
|
|
87d7f7744e | ||
|
|
10dc1882c8 | ||
|
|
c6c0c3be08 | ||
|
|
da6c97203e | ||
|
|
853a46e021 | ||
|
|
075ad676aa | ||
|
|
19d1ad04f4 | ||
|
|
b884533957 | ||
|
|
174f37bdaf | ||
|
|
4f00774006 | ||
|
|
8403c49484 | ||
|
|
06ab541e2f | ||
|
|
7babc24ad4 | ||
|
|
c96e9c8273 | ||
|
|
4a51295c9e | ||
|
|
9c392896b7 | ||
|
|
ea613e181c | ||
|
|
ed5bd1f9ef | ||
|
|
3401dbde92 | ||
|
|
c9e0208de4 | ||
|
|
57a816ae60 | ||
|
|
643f0e3abf | ||
|
|
8744d10235 | ||
|
|
336d9212fc | ||
|
|
79d88e2d0b | ||
|
|
a0d3e405a3 | ||
|
|
0e6e876f23 | ||
|
|
c680f54e6c | ||
|
|
4d745bc602 | ||
|
|
5d4126876b | ||
|
|
0ba02a4ed6 | ||
|
|
f39b138487 | ||
|
|
d9b758661f | ||
|
|
ed7d965818 | ||
|
|
18dca11dd0 | ||
|
|
7c51c0e3de | ||
|
|
c0d02e5ae4 | ||
|
|
032e1397d9 | ||
|
|
c2d9b07533 | ||
|
|
4ef1145241 | ||
|
|
57a93e1a19 | ||
|
|
94c888ebda | ||
|
|
495d6f1e39 | ||
|
|
68971223aa | ||
|
|
4441aa8b60 | ||
|
|
497ebec01d | ||
|
|
be63037654 | ||
|
|
0448428322 | ||
|
|
fd75bdccb0 | ||
|
|
51b3495ad8 | ||
|
|
b7e5d76c79 | ||
|
|
8ccfdf7ba0 | ||
|
|
8c61ee5498 | ||
|
|
d99ab9f903 | ||
|
|
de7625b8c2 | ||
|
|
bc051dcf91 | ||
|
|
0fe5166531 | ||
|
|
9fbe560218 | ||
|
|
fff47f1119 | ||
|
|
8e3aac5744 | ||
|
|
68046106dd | ||
|
|
47570d045d | ||
|
|
ec13fa436b | ||
|
|
22ad62c90c | ||
|
|
f18aea5246 | ||
|
|
5ee9c2ad1f | ||
|
|
4f4bc7cc8f | ||
|
|
85b2fe8486 | ||
|
|
673eb7de96 | ||
|
|
da3c86925a | ||
|
|
2819ab32f8 | ||
|
|
6f21bed66d | ||
|
|
719a3fe98e | ||
|
|
5bc70c68e2 | ||
|
|
dcf14505e2 | ||
|
|
d8c6953710 | ||
|
|
89b5a2c3d5 | ||
|
|
97e0d59619 | ||
|
|
ca72eb0596 | ||
|
|
04a5b9c2cf | ||
|
|
776897d3c9 | ||
|
|
0218ddd575 | ||
|
|
6722d789e9 | ||
|
|
6e846c56b4 | ||
|
|
608dd96de6 | ||
|
|
a49ddaac89 | ||
|
|
613a6a964c | ||
|
|
0dc2885f3e | ||
|
|
afe20dc9b6 | ||
|
|
e97e55adbc | ||
|
|
2f9c518ca8 | ||
|
|
9a50c09172 | ||
|
|
3a964d18e0 | ||
|
|
8d6e66d38c | ||
|
|
f7dabede8b | ||
|
|
725d185a31 | ||
|
|
f633a60581 | ||
|
|
d290e583c5 | ||
|
|
c56e8b4964 | ||
|
|
b2c73596ae | ||
|
|
12626b85c4 | ||
|
|
08bb348142 | ||
|
|
041abe8522 | ||
|
|
39a90ac4d6 | ||
|
|
f2e4e80391 | ||
|
|
fe048efeab | ||
|
|
24f7328e5f | ||
|
|
842837e35b | ||
|
|
6b3cbb10a2 | ||
|
|
cfa43e721a | ||
|
|
d8da97f756 | ||
|
|
ca3169310e | ||
|
|
1ec1510ef7 | ||
|
|
7ac99a4366 | ||
|
|
b7f13df130 | ||
|
|
571dae9664 | ||
|
|
b178fd4286 | ||
|
|
115a8e74c2 | ||
|
|
41f4acfb4f | ||
|
|
1ce75e2bca | ||
|
|
f6fc166584 | ||
|
|
a0b3eceec7 | ||
|
|
7a42233d43 | ||
|
|
895bff6524 | ||
|
|
df068ce11e | ||
|
|
96be957315 | ||
|
|
4acce85656 | ||
|
|
cc3d4cab21 | ||
|
|
e1481a731d | ||
|
|
29fbf3c1ec | ||
|
|
0e769c5418 | ||
|
|
573f08135d | ||
|
|
2e67bd4de7 | ||
|
|
c18301f356 | ||
|
|
02f58b3207 | ||
|
|
bc394410a2 | ||
|
|
b98e92839c | ||
|
|
8269924c33 | ||
|
|
9da3e6696a | ||
|
|
d72e66cdee | ||
|
|
2d2b1cee6b | ||
|
|
3c27c643a9 | ||
|
|
d85e22d205 | ||
|
|
8766efcba6 | ||
|
|
80c08f2286 | ||
|
|
59a11363a5 | ||
|
|
402db2ef32 | ||
|
|
1e118ab891 | ||
|
|
b029be6b6c | ||
|
|
033cdc4133 | ||
|
|
69547bd4bd | ||
|
|
e3860aa6ac | ||
|
|
25f9c318e3 | ||
|
|
5926c877a1 | ||
|
|
9f8b4bdaf1 | ||
|
|
b2343d6247 | ||
|
|
83aad81279 | ||
|
|
f3780c7354 | ||
|
|
92ff153763 | ||
|
|
3d848a886a | ||
|
|
822903e56d | ||
|
|
5ee9845559 | ||
|
|
ea756ede16 | ||
|
|
1b51a88bba | ||
|
|
39f6c793b3 | ||
|
|
91ed6e67b4 | ||
|
|
fad5280d4c | ||
|
|
65e6039979 | ||
|
|
46fa9e8efb | ||
|
|
f6735c223c | ||
|
|
89e880dfd1 | ||
|
|
8523cbdf58 | ||
|
|
4dec946ae6 | ||
|
|
b32ef3c05d | ||
|
|
8140a9d8a6 | ||
|
|
42e7bb80b6 | ||
|
|
6a455e1281 | ||
|
|
5310f5fba3 | ||
|
|
2b0d49a905 | ||
|
|
e7efe94fd2 | ||
|
|
890fff92fd | ||
|
|
c4fa9bb61f | ||
|
|
bcd1a94b89 | ||
|
|
7840e453b5 | ||
|
|
eb650c468a | ||
|
|
c43b138a69 | ||
|
|
cdfa537adf | ||
|
|
ed2bb2cff0 | ||
|
|
0436fba13c | ||
|
|
e8035b94e5 | ||
|
|
d789263e08 | ||
|
|
12599da53d | ||
|
|
fb5c537080 | ||
|
|
526a5d0f8a | ||
|
|
1ea9ff3677 | ||
|
|
074bf39e40 | ||
|
|
23dc46c4f8 | ||
|
|
e9cf3de58f | ||
|
|
69d28f867c | ||
|
|
db30e1b5b6 | ||
|
|
f40274702d | ||
|
|
253dff7656 | ||
|
|
fc87081133 | ||
|
|
9324961cd2 | ||
|
|
44498825cd | ||
|
|
168b97c291 | ||
|
|
2de15dc64b | ||
|
|
5460903f96 | ||
|
|
cb4c03756a | ||
|
|
a548cd9934 | ||
|
|
0fff7ceda4 | ||
|
|
e41bf16ff1 | ||
|
|
8bd1fc4f04 | ||
|
|
cc65015e4e | ||
|
|
41517bca0c | ||
|
|
4048494aa1 | ||
|
|
f816b861fc | ||
|
|
85d0507580 | ||
|
|
b12c42e75d | ||
|
|
e76cfe5aad | ||
|
|
7ac1bff482 | ||
|
|
144f444217 | ||
|
|
52a6863771 | ||
|
|
8ea0ae454f | ||
|
|
735d31e54a | ||
|
|
41a0e991f0 | ||
|
|
40f988ce2a | ||
|
|
c98e3c0eff | ||
|
|
da51485e17 | ||
|
|
93410c47e1 | ||
|
|
dec8d3863a | ||
|
|
131f5c57ab | ||
|
|
0b71339122 | ||
|
|
161e222322 | ||
|
|
e98a314e06 | ||
|
|
2bf6879dae | ||
|
|
ef6beaeff6 | ||
|
|
d8a612f73b | ||
|
|
78a17038c2 | ||
|
|
18c8a93cca | ||
|
|
c06a7585a3 | ||
|
|
1cfc0de31d | ||
|
|
d59f10d7f5 | ||
|
|
76b252f80a | ||
|
|
92993e68c8 | ||
|
|
dc1320df64 | ||
|
|
8a8d8a7b38 | ||
|
|
eb79e3ab3d | ||
|
|
815553c4b4 | ||
|
|
96786a183b | ||
|
|
066b24d741 | ||
|
|
82b81fce68 | ||
|
|
6580590226 | ||
|
|
842c313db2 | ||
|
|
99f6b305c1 | ||
|
|
df694c89b0 | ||
|
|
57d345ff80 | ||
|
|
3ce753c489 | ||
|
|
be151977ca | ||
|
|
daaf0e4ef3 | ||
|
|
80404fae30 | ||
|
|
093d01269a | ||
|
|
7aba8da551 | ||
|
|
a2371ef90b | ||
|
|
fb69a09d6e | ||
|
|
c5653d5f34 | ||
|
|
b203ac1e0d | ||
|
|
722f6013ff | ||
|
|
bd19bc5085 | ||
|
|
2bf6552f2f | ||
|
|
ba62becb7d | ||
|
|
a509790a1c | ||
|
|
953ce90d27 | ||
|
|
288055180e | ||
|
|
8ed4e2dde7 | ||
|
|
2137b3448b | ||
|
|
14614f561b | ||
|
|
b06f3c6d1d | ||
|
|
4ff1631b31 | ||
|
|
a2bc3d81c2 | ||
|
|
cec3e945f0 | ||
|
|
df8450d928 | ||
|
|
4399599de9 | ||
|
|
ef1521b472 | ||
|
|
a51a26e2aa | ||
|
|
553b1c301d | ||
|
|
a6c7801926 | ||
|
|
076a1ab85c | ||
|
|
ac13683c26 | ||
|
|
43cc3fc8b1 | ||
|
|
4f27792ffe | ||
|
|
b670f799d5 | ||
|
|
0f553c57bd | ||
|
|
1269467fa0 | ||
|
|
08e1e7681e | ||
|
|
26c017d5ea | ||
|
|
ee8941e0de | ||
|
|
16fe666e36 | ||
|
|
e538883a20 | ||
|
|
9fa65cd190 | ||
|
|
abe294bfd0 | ||
|
|
0430c55b84 | ||
|
|
dbb91a574f | ||
|
|
eefe5d5aac | ||
|
|
2d2b1bc1cc | ||
|
|
75efba7ec7 | ||
|
|
372fd27e71 | ||
|
|
c20e160e0f | ||
|
|
208705368e | ||
|
|
a21a2e855b | ||
|
|
ee357aaddf | ||
|
|
2cde9125d6 | ||
|
|
0f0473bf1c | ||
|
|
191a728ecc | ||
|
|
b2f39318cb | ||
|
|
201899b611 | ||
|
|
c3d7ada9df | ||
|
|
91f72bbe1c | ||
|
|
9485aeb5c8 | ||
|
|
e877f78b0e | ||
|
|
ef503ab0c8 | ||
|
|
b7ab2b7523 | ||
|
|
69e1fb50ca | ||
|
|
e6913f58b9 | ||
|
|
c3a3a39e92 | ||
|
|
19289d587a | ||
|
|
c53c9a8644 | ||
|
|
87a6443c5b | ||
|
|
77f1d3b317 | ||
|
|
407a0b972e | ||
|
|
5f0acadf7d | ||
|
|
143924bbf3 | ||
|
|
1ffa7a40ac | ||
|
|
415dddf0fa | ||
|
|
10a0eb3e1c | ||
|
|
cdb5cbe6f8 | ||
|
|
d93d918eca | ||
|
|
6d939fcedc | ||
|
|
9361c35176 | ||
|
|
b5a73033ab | ||
|
|
2df9e9b103 | ||
|
|
2fd474132d | ||
|
|
4e487cfa99 | ||
|
|
1387d356aa | ||
|
|
5c3ac93335 | ||
|
|
61242e2e6a | ||
|
|
08689c51a9 | ||
|
|
4a6ba95392 | ||
|
|
b9ac32a0d5 | ||
|
|
f484af34c2 | ||
|
|
ba513ba804 | ||
|
|
bf68040dc5 | ||
|
|
bbc89b6391 | ||
|
|
64a5e27486 | ||
|
|
d1dc2a3298 | ||
|
|
46235e91f6 | ||
|
|
afd3a36f69 | ||
|
|
c5e2bb7cd1 | ||
|
|
e3bfaab3f7 | ||
|
|
c0dfd65d67 | ||
|
|
20066a8964 | ||
|
|
3f8033324f | ||
|
|
75ddd9a6cd | ||
|
|
b3c96bde8c | ||
|
|
cbb8edb0b7 | ||
|
|
75964a9860 | ||
|
|
0fc4967ebc | ||
|
|
aed1bcc12c | ||
|
|
6a42d6b339 | ||
|
|
dcf0d8cab6 | ||
|
|
7c6ce12fa4 | ||
|
|
bf0f586b69 | ||
|
|
af987eb117 | ||
|
|
69d572bb10 | ||
|
|
97d85338e8 | ||
|
|
e4a865177e | ||
|
|
faea193800 | ||
|
|
7ab4728a36 | ||
|
|
b23a216ecd | ||
|
|
d3bb3336f5 | ||
|
|
3ab50c334a | ||
|
|
9943137d1e | ||
|
|
ee0d96ac0d | ||
|
|
8c977bf7b3 | ||
|
|
5311253468 | ||
|
|
ed50bb1676 | ||
|
|
bbb0f0ade4 | ||
|
|
43caca05c2 | ||
|
|
bcbbfdaad4 | ||
|
|
5e7174dec6 | ||
|
|
74e453cf15 | ||
|
|
789de09dda | ||
|
|
39f34e1e58 | ||
|
|
e5b218e6d1 | ||
|
|
faa03031b4 | ||
|
|
974bf58a21 | ||
|
|
91652c317e | ||
|
|
9701810bc3 | ||
|
|
b4bd596a39 | ||
|
|
fcab22f80f | ||
|
|
8098d79ca2 | ||
|
|
4bdb0ac685 | ||
|
|
b6786595a4 | ||
|
|
a26fcf58cc | ||
|
|
8bbdfefe05 | ||
|
|
187acb8609 | ||
|
|
5c9fb8f064 | ||
|
|
7674cbc9b2 | ||
|
|
dbd9ae287a | ||
|
|
702a67807b | ||
|
|
a806d2f9b8 | ||
|
|
ca3ba28768 | ||
|
|
f5003aff69 | ||
|
|
102f3f3a0d | ||
|
|
979c7d76ab | ||
|
|
d467950a5e | ||
|
|
0ecb2bbe74 | ||
|
|
ee48ffe021 | ||
|
|
5679de60c5 | ||
|
|
f5befd2d29 | ||
|
|
cfed7a3a54 | ||
|
|
93b446a962 | ||
|
|
a7dc184772 | ||
|
|
bfaef8ca17 | ||
|
|
2737dbb1e1 | ||
|
|
4d4f1fd364 | ||
|
|
d6493aab02 | ||
|
|
97428e8ac9 | ||
|
|
ea2a12112d | ||
|
|
b758b8223f | ||
|
|
79bba34c5f | ||
|
|
d9dad2f4a1 | ||
|
|
6e30c42101 | ||
|
|
de4f77b0ac | ||
|
|
09654f4e8c | ||
|
|
557c77e455 | ||
|
|
6da230636b | ||
|
|
51e4cba909 | ||
|
|
39585aa90d | ||
|
|
a9e53829d2 | ||
|
|
88d4827b64 | ||
|
|
3c3d943fb1 | ||
|
|
806731e37a | ||
|
|
1ec99f4fd3 | ||
|
|
377a387a42 | ||
|
|
9f49292b35 | ||
|
|
119dfbc627 | ||
|
|
fcec08f7ae | ||
|
|
324172fb1f | ||
|
|
a7657f2ed4 | ||
|
|
df31774327 | ||
|
|
71b160cdbb | ||
|
|
7a919e80c9 | ||
|
|
0758594bd2 | ||
|
|
9b486e47fe | ||
|
|
caf3faa054 | ||
|
|
510a9a77d6 | ||
|
|
4d0c776a80 | ||
|
|
4450d61ac2 | ||
|
|
22baec494b | ||
|
|
94877a137d | ||
|
|
de3f68a233 | ||
|
|
b2c55c9db5 | ||
|
|
eefd2da0f6 | ||
|
|
ce13f6b73e | ||
|
|
4819eae867 | ||
|
|
c5ade6591e | ||
|
|
9c2876b9f8 | ||
|
|
1aab00da85 | ||
|
|
482a1f50b6 | ||
|
|
494ea57b65 | ||
|
|
cdafefd4be | ||
|
|
8bd3e20c86 | ||
|
|
aa83d5d455 | ||
|
|
aaacb01b8d | ||
|
|
9996a2d51b | ||
|
|
6aa0810de5 | ||
|
|
4f4fb1d220 | ||
|
|
242d856ede | ||
|
|
a86fcbd947 | ||
|
|
4c0604ec2e | ||
|
|
6e29450f76 | ||
|
|
030746faff | ||
|
|
dac40d0487 | ||
|
|
ef969a53f5 | ||
|
|
5dce79e941 | ||
|
|
74afea04d6 | ||
|
|
edc66d79c7 | ||
|
|
434b7710f3 | ||
|
|
1e18a6cf60 | ||
|
|
a6bcbb173b | ||
|
|
6dc376f676 | ||
|
|
85c488ee12 | ||
|
|
05742f9b6f | ||
|
|
8b7b3ce03e | ||
|
|
eec097fe35 | ||
|
|
8a35386ba7 | ||
|
|
8f0411ff03 | ||
|
|
c4a32a129d | ||
|
|
78ec1272e9 | ||
|
|
2860d7ba05 | ||
|
|
474305c476 | ||
|
|
ec4cd2cb8c | ||
|
|
98c2f6b0c4 | ||
|
|
e1ae7db4cc | ||
|
|
12963f5231 | ||
|
|
890ead6a71 | ||
|
|
f94a5f0e8c | ||
|
|
b78cc37891 | ||
|
|
a931fb7f51 | ||
|
|
7cd31c3557 | ||
|
|
7221f5e739 | ||
|
|
ef7ffaff74 | ||
|
|
3d900edba7 | ||
|
|
6916f935eb | ||
|
|
3b2f2602b4 | ||
|
|
4dc9df6aae | ||
|
|
88cda0cab6 | ||
|
|
a431e1277e | ||
|
|
a18622c369 | ||
|
|
2206e31e54 | ||
|
|
e8ad60cc4f | ||
|
|
50dbb086f2 | ||
|
|
e368015d79 | ||
|
|
e5668b8c73 | ||
|
|
4982602f6f | ||
|
|
914fbcf2e5 | ||
|
|
4f1d3809c3 | ||
|
|
0625b37760 | ||
|
|
cfed18afc7 | ||
|
|
2d20e13746 | ||
|
|
1a31e31ae9 | ||
|
|
de962e83d0 | ||
|
|
da0ba9e2fe | ||
|
|
5dd84082ab | ||
|
|
204cebc8fc | ||
|
|
6265339995 | ||
|
|
f820bf7cd4 | ||
|
|
e4db4e423d | ||
|
|
e2a99b5760 | ||
|
|
dbb5eeaadf | ||
|
|
e6c5296f30 | ||
|
|
ae6cfd32a0 | ||
|
|
fa178f4235 | ||
|
|
c0308da665 | ||
|
|
dabc990189 | ||
|
|
a71191515a | ||
|
|
dfd1bc3c5b | ||
|
|
4230e98720 | ||
|
|
ea0da0bf47 | ||
|
|
9c4948a4d1 | ||
|
|
a05d547ae8 | ||
|
|
134fbe1245 | ||
|
|
5a28f188ff | ||
|
|
96e3b147f0 | ||
|
|
afb6e9a879 | ||
|
|
8a1613a382 | ||
|
|
4211fdc70b | ||
|
|
9eafb7bbfb | ||
|
|
53244aaac7 | ||
|
|
ed7551c1d4 | ||
|
|
bbf957875b | ||
|
|
9bc5b0406d | ||
|
|
10199341b1 | ||
|
|
71da34c48c | ||
|
|
6906ac979e | ||
|
|
fdca6c08ad | ||
|
|
d17e9fc107 | ||
|
|
3e6bdc2242 | ||
|
|
bf13442c7c | ||
|
|
2af26b75d1 | ||
|
|
7ae7c90790 | ||
|
|
e8779a67b1 | ||
|
|
4c2e7bb035 | ||
|
|
8b0af7fddc | ||
|
|
aa1b4ea861 | ||
|
|
aa23f3801b | ||
|
|
80c9cd1f6e | ||
|
|
d7454de80a | ||
|
|
dd89a3741b | ||
|
|
487d7f9a29 | ||
|
|
f2262eb81a | ||
|
|
b7c27c5333 | ||
|
|
4c64ba16c5 | ||
|
|
007735737a | ||
|
|
b4a5d1dc53 | ||
|
|
0f33d7185f | ||
|
|
8ebf22d3c1 | ||
|
|
6684984c49 | ||
|
|
0e21bde77b | ||
|
|
8a9de84cd0 | ||
|
|
100075f2be | ||
|
|
c59a2267d0 | ||
|
|
5c1d2d1e4c | ||
|
|
9f8481a842 | ||
|
|
21902e2f53 | ||
|
|
c38c18c1a0 | ||
|
|
c5f60942bd | ||
|
|
290e402a02 | ||
|
|
6fb7d44255 | ||
|
|
32cea85331 | ||
|
|
00f12b9a09 | ||
|
|
a604d4f717 | ||
|
|
a28ffa81c4 | ||
|
|
1d962820d8 | ||
|
|
0b8ff4b238 | ||
|
|
e7fb97208a | ||
|
|
596e09770d | ||
|
|
e799849272 | ||
|
|
8bbccf7a97 | ||
|
|
940d9540f3 | ||
|
|
c7983115e9 | ||
|
|
90094a871a | ||
|
|
1c67a3412e | ||
|
|
2b8545684c | ||
|
|
bbbdc70f26 | ||
|
|
e6a7c7689f | ||
|
|
0514332474 | ||
|
|
3115ae0815 | ||
|
|
cec8ff1885 | ||
|
|
f04d3cbdaa | ||
|
|
af271e7330 | ||
|
|
93a93071a2 | ||
|
|
38e606a153 | ||
|
|
a2e21727c0 | ||
|
|
dbf76f62f9 | ||
|
|
e7e898ea17 | ||
|
|
d0021e1621 | ||
|
|
2f1194a296 | ||
|
|
80aafbc81b | ||
|
|
f169102c8e | ||
|
|
a0f907933d | ||
|
|
c147a59bb0 | ||
|
|
2d2c7d3f95 | ||
|
|
87f3109c1a | ||
|
|
6982ce43f5 | ||
|
|
18929bd6d6 | ||
|
|
2a600bddcb | ||
|
|
006721fbd6 | ||
|
|
7219fa65c0 | ||
|
|
61d4bf95dc | ||
|
|
d30e102f3a | ||
|
|
91e8f2b0fe | ||
|
|
eed9502795 | ||
|
|
fd93229770 | ||
|
|
9b0e61aaaa | ||
|
|
ae839620b9 | ||
|
|
457fae24e7 | ||
|
|
cd6c83cdcc | ||
|
|
32f11402f9 | ||
|
|
e900571ac2 | ||
|
|
f31d53093b | ||
|
|
13c4084362 | ||
|
|
f5f11e94be | ||
|
|
324d4bb140 | ||
|
|
8237ab450e | ||
|
|
4ad5496474 | ||
|
|
f9f4e22f6f | ||
|
|
4cc464eadc | ||
|
|
1d069cf435 | ||
|
|
e487eb9da0 | ||
|
|
f25665f360 | ||
|
|
993fa34749 | ||
|
|
2ca83f0bc7 | ||
|
|
c3ffd4c53e | ||
|
|
d78e823449 | ||
|
|
d2645423de | ||
|
|
f3147f446a | ||
|
|
921c22f5ad | ||
|
|
6b348622bb | ||
|
|
fce07bb1cb | ||
|
|
53dd7552dc | ||
|
|
2671f68f7f | ||
|
|
3f3c62a3c9 | ||
|
|
18e5d769fd | ||
|
|
43fbd7ce84 | ||
|
|
566558b17c | ||
|
|
6f6ac84228 | ||
|
|
70b6ba4240 | ||
|
|
923ca4765a | ||
|
|
43c51eb12d | ||
|
|
ee2119d7cb | ||
|
|
19a1f2a5d2 | ||
|
|
9b26743c6b | ||
|
|
dda7672008 | ||
|
|
c1123fd8d0 | ||
|
|
90dd510df1 | ||
|
|
96877eb9c3 | ||
|
|
2d660108b2 | ||
|
|
326dc95f9c | ||
|
|
e6dd8f626a | ||
|
|
61ab94d553 | ||
|
|
9b27329437 | ||
|
|
5b7feebfd8 | ||
|
|
dfbf1b4f6b | ||
|
|
20360e00ce | ||
|
|
551b6c4d66 | ||
|
|
d0e870aad2 | ||
|
|
5ae3dd52a0 | ||
|
|
eb0ad66d88 | ||
|
|
142827f7d8 | ||
|
|
08400f5be7 | ||
|
|
40b2286d16 | ||
|
|
3260ea6954 | ||
|
|
8be0723fb7 | ||
|
|
e97b97467e | ||
|
|
3381ab423b | ||
|
|
f401021d5a | ||
|
|
31b967f098 | ||
|
|
01d27a4acd | ||
|
|
419a9ada16 | ||
|
|
17bd417a3d | ||
|
|
3b683927ee | ||
|
|
3543dfda95 | ||
|
|
d97bbf1904 | ||
|
|
df0776e931 | ||
|
|
738d6db3e6 | ||
|
|
6f287dd16d | ||
|
|
57ab2b4226 | ||
|
|
ec2f1d69c8 | ||
|
|
63234f8dd0 | ||
|
|
be2d006e2e | ||
|
|
88e232739b | ||
|
|
d4791f1bbe | ||
|
|
82d0584e7b | ||
|
|
75f83de52a | ||
|
|
f77d22837c | ||
|
|
71c77c081a | ||
|
|
772ca9e9a9 | ||
|
|
f37a9a27e5 | ||
|
|
a4fcc93f4a | ||
|
|
9a0dff1bc5 | ||
|
|
0bde57c25a | ||
|
|
3b8c7d0326 | ||
|
|
d67e2eea1a | ||
|
|
81b689b969 | ||
|
|
81cfe09657 | ||
|
|
ccb6646bae | ||
|
|
1039b7f543 | ||
|
|
a908d73c16 | ||
|
|
b4033b37ad | ||
|
|
a855bd8df3 | ||
|
|
06092a9756 | ||
|
|
062e580436 | ||
|
|
4994e75852 | ||
|
|
41f02825fc | ||
|
|
99109c0b3b | ||
|
|
83b64b8be2 | ||
|
|
ab9ce2a927 | ||
|
|
3982cb35dc | ||
|
|
1ff9768aa3 | ||
|
|
634a7ed988 | ||
|
|
0bae2db77f | ||
|
|
0536ace2b6 | ||
|
|
23b655f8e3 | ||
|
|
7a56b41124 | ||
|
|
db26fe7ca8 | ||
|
|
604f2fa84a | ||
|
|
38617a5ad3 | ||
|
|
0f6a463fae | ||
|
|
e6b5cafe65 | ||
|
|
706438a43c | ||
|
|
04d9a04557 | ||
|
|
83ecc846dc | ||
|
|
67e5f3505d | ||
|
|
971d243a87 | ||
|
|
49a9eee33f | ||
|
|
50de550ecd | ||
|
|
42f47590f9 | ||
|
|
97da66209c | ||
|
|
462d167456 | ||
|
|
ad37b79bca | ||
|
|
626d358e55 | ||
|
|
b001038901 | ||
|
|
ba5161740e | ||
|
|
d885fe4dd0 | ||
|
|
349af8766c | ||
|
|
20ae8bd4c3 | ||
|
|
c4bc674482 | ||
|
|
98d52b7b26 | ||
|
|
f29e505d94 | ||
|
|
a0b811dd37 | ||
|
|
9fbc313459 | ||
|
|
661bba09ce | ||
|
|
f3d242a90d | ||
|
|
c3629adbeb | ||
|
|
6b8accbfa1 | ||
|
|
92b94980c6 | ||
|
|
19b494df89 | ||
|
|
f890d85381 | ||
|
|
42206b3d51 | ||
|
|
74dd38d27c | ||
|
|
e94f95d82b | ||
|
|
9bd5d8a240 | ||
|
|
1dde20ff4a | ||
|
|
cb16568fca | ||
|
|
8db126188d | ||
|
|
3d399bceca | ||
|
|
b3c87475a5 | ||
|
|
5109a77f69 | ||
|
|
014b722963 | ||
|
|
f0575411c0 | ||
|
|
004f03945f | ||
|
|
655fcf8287 | ||
|
|
03f007d4cd | ||
|
|
29cff2be06 | ||
|
|
ba14c70b02 | ||
|
|
199a44e31e | ||
|
|
30c29d291f | ||
|
|
8776678a46 | ||
|
|
718a594b1e | ||
|
|
2360061520 | ||
|
|
26785fd873 | ||
|
|
797101a882 | ||
|
|
9644c51183 | ||
|
|
d0107f5da2 | ||
|
|
726aad8e08 | ||
|
|
44a73be6ea | ||
|
|
bc77041b57 | ||
|
|
7f81fbc542 | ||
|
|
fb410463e6 | ||
|
|
a727332e77 | ||
|
|
4aeae5d718 | ||
|
|
d0750ee4e7 | ||
|
|
0af2c4ef76 | ||
|
|
faca859043 | ||
|
|
a9f72ab681 | ||
|
|
cfae5ac71b | ||
|
|
f7ba645398 | ||
|
|
e648dbb59d | ||
|
|
6aade6912a | ||
|
|
dad9f45e3e | ||
|
|
71714eab53 | ||
|
|
11fba027e5 | ||
|
|
6ce26ef11d | ||
|
|
08b1496b7e | ||
|
|
1ac162f2b0 | ||
|
|
4925695ae8 | ||
|
|
7ac50bf77d | ||
|
|
aef07aea27 | ||
|
|
b53d91a4c4 | ||
|
|
510b6adc9b | ||
|
|
dab63231d8 | ||
|
|
4d00bf8add | ||
|
|
6dcb7be35f | ||
|
|
ac2ad79812 | ||
|
|
52a6ab44b1 | ||
|
|
dc6346b763 | ||
|
|
8807b01b28 | ||
|
|
19accb14a9 | ||
|
|
3d1e593b5b | ||
|
|
e240bc151a | ||
|
|
1674fe96ff | ||
|
|
d1b7817959 | ||
|
|
abd07f6d30 | ||
|
|
67cd4ead65 | ||
|
|
a8eec24405 | ||
|
|
4236bc088f | ||
|
|
15cb7d61f9 | ||
|
|
ca5701d458 | ||
|
|
21d03edcb0 | ||
|
|
a2366f9022 | ||
|
|
a5cf4fe374 | ||
|
|
d16cb171c6 | ||
|
|
193c1e2366 | ||
|
|
d0b742efde | ||
|
|
4a1a38f7ed | ||
|
|
943fd216ec | ||
|
|
e3cb016328 | ||
|
|
41eebc87a0 | ||
|
|
1dfbb100d6 | ||
|
|
f75cf62d2f | ||
|
|
8dd33839f0 | ||
|
|
722a2a12fb | ||
|
|
776813416b | ||
|
|
afb15e9795 | ||
|
|
f99febfd6f | ||
|
|
a93f7db875 | ||
|
|
30dcdcbe73 | ||
|
|
07be01767a | ||
|
|
4832027eb6 | ||
|
|
6a7319543c | ||
|
|
ee9e3a2ed6 | ||
|
|
4a06fe59b4 | ||
|
|
28caa22356 | ||
|
|
1d88609043 | ||
|
|
864a2bf6b8 | ||
|
|
a131c3e611 | ||
|
|
0b9adc2c79 | ||
|
|
1e939fcc32 | ||
|
|
088e6fc047 | ||
|
|
438f9e1a3e | ||
|
|
ce484301c0 | ||
|
|
d474ed7f78 | ||
|
|
d15da2c47d | ||
|
|
5de7f69cbb | ||
|
|
214977e5fd | ||
|
|
e54f240ea0 | ||
|
|
9ff60ae31d | ||
|
|
ba2f4a2cd5 | ||
|
|
e6460722ea | ||
|
|
8e40104795 | ||
|
|
bf75504d7a | ||
|
|
521f84a3a9 | ||
|
|
8a946b69e9 | ||
|
|
59e69dc6df | ||
|
|
e471206b08 | ||
|
|
eb7201b902 | ||
|
|
ecb1962013 | ||
|
|
092c88dc7b | ||
|
|
fabceaf036 | ||
|
|
61313a7589 | ||
|
|
2d99052d1d | ||
|
|
1b61d55079 | ||
|
|
591a18a9c4 | ||
|
|
29fadad193 | ||
|
|
45e7f7827a | ||
|
|
3232070d3a | ||
|
|
4b654db904 | ||
|
|
8cc6eee295 | ||
|
|
6864a7f839 | ||
|
|
531364d728 | ||
|
|
9f8f5e1145 | ||
|
|
2981a10c53 | ||
|
|
5e7dc72c92 | ||
|
|
fd57b252ac | ||
|
|
71ee2ce367 | ||
|
|
887478793b | ||
|
|
dcf54782d4 | ||
|
|
8199457a7d | ||
|
|
ec9a4ef487 | ||
|
|
1b44e40444 | ||
|
|
1f634f1d94 | ||
|
|
ce3a8d7c79 | ||
|
|
c2a3d5e47b | ||
|
|
df38704926 | ||
|
|
b847c41437 | ||
|
|
249d5caedb | ||
|
|
c7b9256097 | ||
|
|
96460a8a12 | ||
|
|
79e83d6535 | ||
|
|
d42fa46dc6 | ||
|
|
692bee5f22 | ||
|
|
b3ba6b3095 | ||
|
|
3f9a90e2a3 | ||
|
|
b20f62b162 | ||
|
|
4227402b2f | ||
|
|
055b2e80fb | ||
|
|
aad86b8756 | ||
|
|
55f54fa512 | ||
|
|
ed356dc181 | ||
|
|
237165a935 | ||
|
|
a285835ac4 | ||
|
|
79b77d91c9 | ||
|
|
e3da939b86 | ||
|
|
b67b375ae6 | ||
|
|
97c6f4047c | ||
|
|
1230b4410c | ||
|
|
4d8c56c813 | ||
|
|
fe09ebbe0a | ||
|
|
605c8d7110 | ||
|
|
97ff9bd370 | ||
|
|
c3dca77a19 | ||
|
|
fd994943c2 | ||
|
|
da36336321 | ||
|
|
eb72b5a8ee | ||
|
|
f9cda1fa24 | ||
|
|
b6e313bc05 | ||
|
|
168ef39984 | ||
|
|
57eea6746e | ||
|
|
2546d0a0db | ||
|
|
d7e605d430 | ||
|
|
02c31a8dd1 | ||
|
|
2688562fd2 | ||
|
|
7814518049 | ||
|
|
1b63522446 | ||
|
|
2697cfe354 | ||
|
|
7d4de84ee3 | ||
|
|
d411c9054a | ||
|
|
3f34c83bc6 | ||
|
|
529c73ba21 | ||
|
|
a8a1f29512 | ||
|
|
c52346850d | ||
|
|
df664329cb | ||
|
|
3ac367ff41 | ||
|
|
f472f17054 | ||
|
|
c07864f64a | ||
|
|
2af3b2ac81 | ||
|
|
e61612a687 | ||
|
|
e1fd25051e | ||
|
|
c3d7aa252b | ||
|
|
db4898cb91 | ||
|
|
f9caf4447a | ||
|
|
c94cf6f01f | ||
|
|
ab995d3d4f | ||
|
|
443b034895 | ||
|
|
f6b5caf82c | ||
|
|
7bbbbea200 | ||
|
|
2f56df4839 | ||
|
|
1113f13f83 | ||
|
|
81548cb6bf | ||
|
|
dc0a1682e3 | ||
|
|
65ebc0513b | ||
|
|
9435a3185a | ||
|
|
955210ae5b | ||
|
|
0be238ec58 | ||
|
|
e7a734f78d | ||
|
|
a639346fba | ||
|
|
2111e3597b | ||
|
|
dbc67bbf23 | ||
|
|
f36a03c317 | ||
|
|
b13a78e6b2 | ||
|
|
9337151a01 | ||
|
|
3141d87ef8 | ||
|
|
8312c75fef | ||
|
|
d439f590ab | ||
|
|
6c4bf8e56e | ||
|
|
f3d77d8e71 | ||
|
|
907268a430 | ||
|
|
5d9de14493 | ||
|
|
75bac1aac6 | ||
|
|
15391762dd | ||
|
|
1ac469b50f | ||
|
|
7546a2d345 | ||
|
|
750e23998f | ||
|
|
51fe0bfcf6 | ||
|
|
0f633c1d99 | ||
|
|
e0282347db | ||
|
|
0af6fbb51d | ||
|
|
b747d6fe59 | ||
|
|
aa4d64be92 | ||
|
|
f904a6646c | ||
|
|
90305c57e4 | ||
|
|
bf01795483 | ||
|
|
3d41994a63 | ||
|
|
33fc61a091 | ||
|
|
5941edd9f7 | ||
|
|
c527cba470 | ||
|
|
6feff6ff05 | ||
|
|
a6adfb2b49 | ||
|
|
c3998b70cc | ||
|
|
2765fdb43e | ||
|
|
88df590145 | ||
|
|
d18e57e673 | ||
|
|
82de6c470b | ||
|
|
5628dda5a5 | ||
|
|
9da4efed2a | ||
|
|
a6f43dfadd | ||
|
|
dce02f5c4b | ||
|
|
ba698df7bb | ||
|
|
e1d2109208 | ||
|
|
fa516c3d76 | ||
|
|
530155d85a | ||
|
|
8c1f659b3d | ||
|
|
8fe6b31952 | ||
|
|
6ddc5f38af | ||
|
|
c3753809b1 | ||
|
|
ff95fdb668 | ||
|
|
af83a3eea4 | ||
|
|
6821401a3f | ||
|
|
c9eb3714e8 | ||
|
|
e82b49d2d4 | ||
|
|
140a2f0565 | ||
|
|
847b1dde8c | ||
|
|
0cf376348b | ||
|
|
ab9326f4ae | ||
|
|
e3616e151f | ||
|
|
c0035705ca | ||
|
|
df1eeb9a20 | ||
|
|
9223ffc255 | ||
|
|
564dde0ee3 | ||
|
|
387fc13894 | ||
|
|
961b81c362 | ||
|
|
1ea9ca748c | ||
|
|
6ef70a97fd | ||
|
|
ccf43d6a96 | ||
|
|
a83326bc52 | ||
|
|
a39f9e7661 | ||
|
|
c61ada200f | ||
|
|
35b5ebc9b5 | ||
|
|
11bcae1ebd | ||
|
|
5d71314f71 | ||
|
|
85954c845e | ||
|
|
d2f208a30c | ||
|
|
815c61b82e | ||
|
|
78cb1661cb | ||
|
|
a05700e327 | ||
|
|
35bbadcf0c | ||
|
|
b91ae122e1 | ||
|
|
19086c1c48 | ||
|
|
919cac1482 | ||
|
|
ad5d3c9bff | ||
|
|
b9721c1ed7 | ||
|
|
00c4b8f2a3 | ||
|
|
3ba3f0d905 | ||
|
|
0479b188d0 | ||
|
|
9aeebd24f7 | ||
|
|
7abda179af | ||
|
|
9c7183dd04 | ||
|
|
4afbfd5e71 | ||
|
|
17c4c2154a | ||
|
|
57da88093f | ||
|
|
8947c35fa1 | ||
|
|
554db6bc0f | ||
|
|
c2d21ab04f | ||
|
|
070c046cd1 | ||
|
|
7c6d4ff28d | ||
|
|
8bab3eab6a | ||
|
|
74a1854db9 | ||
|
|
669021be4c | ||
|
|
67e9aa4d3d | ||
|
|
4247f190c2 | ||
|
|
9c1f922b02 | ||
|
|
0e4dcfa552 | ||
|
|
3de75138d1 | ||
|
|
0de88a928d | ||
|
|
b4ca869c40 | ||
|
|
7e0800e718 | ||
|
|
46691d172e | ||
|
|
bc9e5b62b6 | ||
|
|
ac7d6fb5ca | ||
|
|
9c2f6003e4 | ||
|
|
df3a74389e | ||
|
|
126569ad5b | ||
|
|
c3c90b49e0 | ||
|
|
a8e96ae21a | ||
|
|
2937339c17 | ||
|
|
6816789a6b | ||
|
|
9504068f66 | ||
|
|
6b6026b133 | ||
|
|
1ec1f7a3de | ||
|
|
2d0baaabe6 | ||
|
|
0a73c6ec3f | ||
|
|
0ebf49b4c1 | ||
|
|
380b3559c6 | ||
|
|
05a4f28059 | ||
|
|
5496050f5f | ||
|
|
0f63d3e916 | ||
|
|
dadf9cd039 | ||
|
|
43925b9fa4 | ||
|
|
ddd4c9d6b9 | ||
|
|
fb799bba7f | ||
|
|
8f36798035 | ||
|
|
0250dc903e | ||
|
|
ae708e3bcd | ||
|
|
7e0b3b9caf | ||
|
|
a62794359a | ||
|
|
a489585f84 | ||
|
|
12f92518bc | ||
|
|
84cc72f372 | ||
|
|
cb16be3a3f | ||
|
|
c554c402d3 | ||
|
|
50a0f18e6a | ||
|
|
dd5c30d2d7 | ||
|
|
67216910fb | ||
|
|
ccf3ee674a | ||
|
|
751bbf38ba | ||
|
|
f2c07ed717 | ||
|
|
c47928ffc0 | ||
|
|
372eebbeb2 | ||
|
|
0403096a9d | ||
|
|
c7df9c7121 | ||
|
|
404af57004 | ||
|
|
0582f7678a | ||
|
|
77d582fa37 | ||
|
|
953d40c929 | ||
|
|
fbb903e158 | ||
|
|
dbffb702f8 | ||
|
|
0c2650e833 | ||
|
|
22b36bef9e | ||
|
|
7c2476986b | ||
|
|
32f9dfc126 | ||
|
|
eb1cc4b8b4 | ||
|
|
a18fb406ac | ||
|
|
aab27130a6 | ||
|
|
48e7e7bfe8 | ||
|
|
755bf2b8c2 | ||
|
|
2c8cc58fd1 | ||
|
|
7f20a4b041 | ||
|
|
e3971079cf | ||
|
|
8067d05f74 | ||
|
|
21581cf70c | ||
|
|
7e7c97ac5f | ||
|
|
77d9f80754 | ||
|
|
8c318dc770 | ||
|
|
50709454b3 | ||
|
|
413c056359 | ||
|
|
37c243bb35 | ||
|
|
8c517fee35 | ||
|
|
32a037c030 | ||
|
|
21bda2ed99 | ||
|
|
1b9593e889 | ||
|
|
b902fa4c44 | ||
|
|
8caf7afbad | ||
|
|
22d65c7949 | ||
|
|
7538ca6f40 | ||
|
|
a47bfb1b5b | ||
|
|
d46a0aa069 | ||
|
|
7260bb51cf | ||
|
|
6f7b5d0ee2 | ||
|
|
67d886fd63 | ||
|
|
2a418f054d | ||
|
|
f1eaf8d7c0 | ||
|
|
47db0698d2 | ||
|
|
3460014e05 | ||
|
|
0561d708ba | ||
|
|
219c6adc58 | ||
|
|
b95b2b4574 | ||
|
|
209edcc247 | ||
|
|
a31aa683ff | ||
|
|
f8de9fec8c | ||
|
|
68a05e3f04 | ||
|
|
6cefd4fd88 | ||
|
|
8ab8965713 | ||
|
|
9aec6d7217 | ||
|
|
0fce21e890 | ||
|
|
854e21d4b4 | ||
|
|
538960bf17 | ||
|
|
f953ebf9ca | ||
|
|
e47015aef4 | ||
|
|
97a1111b94 | ||
|
|
661c388515 | ||
|
|
868f444620 | ||
|
|
109a8632d7 | ||
|
|
51823d117d | ||
|
|
5cbc34a10c | ||
|
|
479c5f62fc | ||
|
|
ed9eb880b5 | ||
|
|
5a1a9a804a | ||
|
|
7f5d5c80b2 | ||
|
|
1f9fc382c3 | ||
|
|
00ad3c65bc | ||
|
|
f814ef816f | ||
|
|
b9084949bd | ||
|
|
86931393a3 | ||
|
|
7832e6a70e | ||
|
|
85d982011e | ||
|
|
ce4e210dcb | ||
|
|
5ce3d29955 | ||
|
|
650cb51bf1 | ||
|
|
ef9d525f02 | ||
|
|
16b72f2d21 | ||
|
|
29439bdd27 | ||
|
|
374b9a7fb4 | ||
|
|
c150ad50c4 | ||
|
|
1002cfa6d2 | ||
|
|
7c71e66370 | ||
|
|
d5a600e9c6 | ||
|
|
0eb025f484 | ||
|
|
a689fa262a | ||
|
|
c06e6340cd | ||
|
|
77e4171894 | ||
|
|
197f8904fe | ||
|
|
dc5caa483c | ||
|
|
fc512a2474 | ||
|
|
85513de247 | ||
|
|
900b29055c | ||
|
|
55748cdbe1 | ||
|
|
ec1d2be96f | ||
|
|
6d1a6f1c74 | ||
|
|
4c3eac2c10 | ||
|
|
a1566c5e1b | ||
|
|
aa725ca79d | ||
|
|
cd48059dc5 | ||
|
|
28a283b460 | ||
|
|
aa5a6098ee | ||
|
|
d39ca33b63 | ||
|
|
ae8218a3ea | ||
|
|
25e279ee73 | ||
|
|
b4f564c1ed | ||
|
|
5107e58b0f | ||
|
|
8bd5d1d42f | ||
|
|
7747106647 | ||
|
|
07dbcf1f70 | ||
|
|
93daf23223 | ||
|
|
e45efa9951 | ||
|
|
5d973a87d4 | ||
|
|
af2fbf043d | ||
|
|
e4576914cb | ||
|
|
d0524df887 | ||
|
|
f806c76e97 | ||
|
|
f0912833ba | ||
|
|
ac90e1bd5b | ||
|
|
0a5d40a016 | ||
|
|
d06b8b58d8 | ||
|
|
5e23680454 | ||
|
|
510eb8f480 | ||
|
|
f48aae600a | ||
|
|
6ccc561a2a | ||
|
|
0d483a1c89 | ||
|
|
92df32d339 | ||
|
|
1ab1af80c7 | ||
|
|
d15574ce2a | ||
|
|
d4495446d5 | ||
|
|
0b309471f2 | ||
|
|
0c9c12c1bb | ||
|
|
6ebbecc6a0 | ||
|
|
fc4d818e17 | ||
|
|
4bb7567141 | ||
|
|
b30df8890d | ||
|
|
558c57a086 | ||
|
|
50b2ff0bf0 | ||
|
|
6ef4f67fa9 | ||
|
|
a60387a3c2 | ||
|
|
913151caa8 | ||
|
|
c895e987ad | ||
|
|
b8a44b198c | ||
|
|
baaaaea9e9 | ||
|
|
da18fcb7ae | ||
|
|
b720c0f541 | ||
|
|
07e8ff9a8d | ||
|
|
fa0120ea5e | ||
|
|
361432a0bb | ||
|
|
eba46cb0d2 | ||
|
|
9ec299ebe3 | ||
|
|
7b8107e7c8 | ||
|
|
648278cd62 | ||
|
|
80a5fdb108 | ||
|
|
f9df6bf662 | ||
|
|
b475309fa1 | ||
|
|
daecfffefb | ||
|
|
fab96a6e59 | ||
|
|
dad1689bf7 | ||
|
|
3caa79c8a5 | ||
|
|
76bc1b825e | ||
|
|
f790d51665 | ||
|
|
231cbee0fc | ||
|
|
4f9ba19e52 | ||
|
|
e7712ff103 | ||
|
|
f959c417fe | ||
|
|
0bf134a8e2 | ||
|
|
9a2b598ec1 | ||
|
|
d3c3514a59 | ||
|
|
25a492f330 | ||
|
|
9638c2839a | ||
|
|
742e53434f | ||
|
|
515b437c08 | ||
|
|
976dc23965 | ||
|
|
37b37fc2a3 | ||
|
|
5c5ae806aa | ||
|
|
cf4c10bef7 | ||
|
|
f0802287db | ||
|
|
29ff159f94 | ||
|
|
38ddfb24f0 | ||
|
|
8be48a44f7 | ||
|
|
868facff9d | ||
|
|
0a1f5b94e3 | ||
|
|
40df3db1a2 | ||
|
|
da29b776ee | ||
|
|
3c435c0297 | ||
|
|
286cd5bd41 | ||
|
|
fc570ac922 | ||
|
|
65dc67f63c | ||
|
|
6b7358e9f3 | ||
|
|
fbf45ad149 | ||
|
|
1ff90c52d5 | ||
|
|
04f40014a6 | ||
|
|
c623669967 | ||
|
|
0573513d6d | ||
|
|
44c7dfca03 | ||
|
|
c3f8f4de25 | ||
|
|
9877941775 | ||
|
|
725f91922d | ||
|
|
e46d1e69ac | ||
|
|
277ae93c41 | ||
|
|
f5be90523d | ||
|
|
13d91ff918 | ||
|
|
34965cf23a | ||
|
|
659fb41d0a | ||
|
|
198c38f0b1 | ||
|
|
3b6d924acd | ||
|
|
d3f1a7165c | ||
|
|
e78ce72eb6 | ||
|
|
014e0ac8c9 | ||
|
|
c16043c1d5 | ||
|
|
405e54ebd5 | ||
|
|
6655ab2e43 | ||
|
|
9159cd7b4a | ||
|
|
ccc5347e45 | ||
|
|
8a14b71f22 | ||
|
|
b19a4c5f2b | ||
|
|
5b6f03213d | ||
|
|
f80e65a406 | ||
|
|
829f45df99 | ||
|
|
3cc37170ca | ||
|
|
891b81fc5d | ||
|
|
262e30e300 | ||
|
|
9dfa2397de | ||
|
|
d15e4100b8 | ||
|
|
f966da1f8f | ||
|
|
bf1c96d4fa | ||
|
|
fd8d6dc5d1 | ||
|
|
e0ba0d0433 | ||
|
|
11d73f03ee | ||
|
|
89019319dd | ||
|
|
1d6f0cea0e | ||
|
|
3af739a2d1 | ||
|
|
2af01baffd | ||
|
|
915c6393ad | ||
|
|
536090303a | ||
|
|
7b5357d817 | ||
|
|
70aa717a8e | ||
|
|
5cdc4a2a41 | ||
|
|
76e09c4b0f | ||
|
|
3a078466a7 | ||
|
|
7d67623d15 | ||
|
|
a5e0e90c16 | ||
|
|
1e8fc01ddd | ||
|
|
a06dd7a27b | ||
|
|
f104967c68 | ||
|
|
06ce312745 | ||
|
|
f50ddc431e | ||
|
|
6172c22c5d | ||
|
|
96839b445e | ||
|
|
7194756370 | ||
|
|
f1960b60c1 | ||
|
|
8491cf36ad | ||
|
|
9176eedf24 | ||
|
|
1509842107 | ||
|
|
1ce41f6218 | ||
|
|
81e0be856a | ||
|
|
a201af7354 | ||
|
|
4c2c09450a | ||
|
|
5b5e9bd0cb | ||
|
|
7c3fa7d049 | ||
|
|
9266c0d2d1 | ||
|
|
595eb86624 | ||
|
|
6850194f60 | ||
|
|
5fc0a361b2 | ||
|
|
831d42c1ab | ||
|
|
e3c7ff944d | ||
|
|
15908502ed | ||
|
|
788747f863 | ||
|
|
763100b385 | ||
|
|
c7edb446ca | ||
|
|
1844f903d5 | ||
|
|
5ddfbb80d8 | ||
|
|
2f48337335 | ||
|
|
d7c2a0e38f | ||
|
|
3b828d3701 | ||
|
|
ff5f3aa38b | ||
|
|
1a48a63446 | ||
|
|
33fabdf392 | ||
|
|
d431d85839 | ||
|
|
f0d1f61fa5 | ||
|
|
095665977f | ||
|
|
d10641b04a | ||
|
|
03417cc77d | ||
|
|
5fdcdf7080 | ||
|
|
80d5cb1ab1 | ||
|
|
1cc0eb4d32 | ||
|
|
46e5f44ec8 | ||
|
|
e0c8c80ada | ||
|
|
4b20a0217e | ||
|
|
2156db7a07 | ||
|
|
dd0efdc637 | ||
|
|
8a3dfda8d0 | ||
|
|
6228c2e1ec | ||
|
|
70bb6d1e79 | ||
|
|
82df7c8bf4 | ||
|
|
29809d7220 | ||
|
|
db049db860 | ||
|
|
d6cb3c923d | ||
|
|
6470e2279e | ||
|
|
fdf8d02be1 | ||
|
|
788bb58b6b | ||
|
|
a5dec42866 | ||
|
|
a3eea8a75a | ||
|
|
69bf3291df | ||
|
|
af00b182e3 | ||
|
|
fc2e532f99 | ||
|
|
8323a06e6d | ||
|
|
58261dbe9a | ||
|
|
f1ae47c4b9 | ||
|
|
7f9533b840 | ||
|
|
27e83c2953 | ||
|
|
278cf1a7bc | ||
|
|
edeb8ee3ab | ||
|
|
c6716f5e9f | ||
|
|
a1b06823fe | ||
|
|
0461ade24b | ||
|
|
c528b688cf | ||
|
|
26eef4df87 | ||
|
|
7938550d52 | ||
|
|
4758f74676 | ||
|
|
6f10cef2a1 | ||
|
|
33d18c580b | ||
|
|
0ea99132c8 | ||
|
|
4778560e66 | ||
|
|
e8dd47effa | ||
|
|
718fa0eec6 | ||
|
|
240ab5890b | ||
|
|
4a2426449a | ||
|
|
f039e69b9c | ||
|
|
8340a30d27 | ||
|
|
1e1013085b | ||
|
|
036a6c875e | ||
|
|
0bd6489721 | ||
|
|
0000739c08 | ||
|
|
33d426842d | ||
|
|
3cb805489b | ||
|
|
22a7d241ff | ||
|
|
b4c5a83cfe | ||
|
|
70f2aaff43 | ||
|
|
55073aa7a3 | ||
|
|
8764a1b7c4 | ||
|
|
089ed30323 | ||
|
|
e265610a0c | ||
|
|
f59b54c6f4 | ||
|
|
0d582dabf3 | ||
|
|
6cfe3ddf52 | ||
|
|
54c1bdeceb | ||
|
|
4afffa36e9 | ||
|
|
f6836ff37f | ||
|
|
07dbd46ddd | ||
|
|
34646627aa | ||
|
|
86512eac06 | ||
|
|
03298fe875 | ||
|
|
69f524ba95 | ||
|
|
9d8de45313 | ||
|
|
5366bd09bf | ||
|
|
c58d2c89c3 | ||
|
|
1fade35159 | ||
|
|
58ca5f6424 | ||
|
|
d72e1563d4 | ||
|
|
9a2985611c | ||
|
|
0b77980cab | ||
|
|
aaf157cfdd | ||
|
|
1fd5ff7152 | ||
|
|
52886872f1 | ||
|
|
5768de79e2 | ||
|
|
b112d73edb | ||
|
|
2ee40d3cf9 | ||
|
|
b4b864e40a | ||
|
|
d2b0167610 | ||
|
|
7965494ff3 | ||
|
|
c1a3c7f445 | ||
|
|
c6ec69c7c1 | ||
|
|
888834c636 | ||
|
|
077e4db772 | ||
|
|
6f171a066d | ||
|
|
1f3090a48d | ||
|
|
86891b0986 | ||
|
|
f37f6f67f6 | ||
|
|
bce4db00bc | ||
|
|
65a10410e3 | ||
|
|
61b8197942 | ||
|
|
3733b5064e | ||
|
|
c5c1c4134b | ||
|
|
7bb0a525c3 | ||
|
|
3d083dbe1a | ||
|
|
b81bd7ed98 | ||
|
|
623bff23ce | ||
|
|
f298491a8a | ||
|
|
5de1312e1c | ||
|
|
afadf74a53 | ||
|
|
46843b683b | ||
|
|
ade4d0e08a | ||
|
|
ed29ff08ba | ||
|
|
abfb9269b5 | ||
|
|
add915bdc4 | ||
|
|
4ad5817aac | ||
|
|
75c46a3930 | ||
|
|
fe6544622b | ||
|
|
454f36d2af | ||
|
|
44dbad64d7 | ||
|
|
79a9e2fdfb | ||
|
|
6e7b43b6c7 | ||
|
|
d0da79c572 | ||
|
|
ab522dd18c | ||
|
|
0f50b52da4 | ||
|
|
5170a9d6dc | ||
|
|
fea52e29aa | ||
|
|
0d3b468cb3 | ||
|
|
44345c2108 | ||
|
|
fa4c49b4a7 | ||
|
|
cdbc21a191 | ||
|
|
ab47efd9a0 | ||
|
|
561af15d67 | ||
|
|
376035fd01 | ||
|
|
cfc71ab7c5 | ||
|
|
1ab63d925f | ||
|
|
c0bc43ccff | ||
|
|
f1d1a8d32b | ||
|
|
9235352400 | ||
|
|
34a0bc456e | ||
|
|
7713c29258 | ||
|
|
88fec09715 | ||
|
|
313676d200 | ||
|
|
8ee85137d8 | ||
|
|
4e4042bc33 | ||
|
|
bc3c6e74e6 | ||
|
|
e2035a514c | ||
|
|
c95fbb4464 | ||
|
|
ade2acfd1d | ||
|
|
1b9cb52d7b | ||
|
|
f8dc03d702 | ||
|
|
56f7e853be | ||
|
|
9a5da23553 | ||
|
|
d6d00b4fcf | ||
|
|
99913b5051 | ||
|
|
a8bdbfddf9 | ||
|
|
8db02ef8df | ||
|
|
947255c3da | ||
|
|
0b8c6b9bce | ||
|
|
12a3c77c2f | ||
|
|
f96c5443b1 | ||
|
|
32228d8add | ||
|
|
9f851ebfe4 | ||
|
|
be1311cfc1 | ||
|
|
08606714a3 | ||
|
|
5053d79a24 | ||
|
|
b9ebb8e06f | ||
|
|
feddcf3030 | ||
|
|
112d8fc41d | ||
|
|
001f102f38 | ||
|
|
7bbd758681 | ||
|
|
b0758c86d8 | ||
|
|
73346e4341 | ||
|
|
0312a29e4c | ||
|
|
1107bffe84 | ||
|
|
2c07d581de | ||
|
|
085ed7bfbe | ||
|
|
0dd756bceb | ||
|
|
a63e2f0a33 | ||
|
|
64b1aeebf5 | ||
|
|
28b237f94d | ||
|
|
330d763477 | ||
|
|
a61438740d | ||
|
|
701a047ac0 | ||
|
|
03e2a7f584 | ||
|
|
c21278eeae | ||
|
|
2f431a948c | ||
|
|
f1519efb16 | ||
|
|
456aa3bc0a | ||
|
|
9ece0bdc02 | ||
|
|
8175a47881 | ||
|
|
204ae8a407 | ||
|
|
94da5842ef | ||
|
|
e5ca5351d5 | ||
|
|
72ae6f5200 | ||
|
|
12ee2dd789 | ||
|
|
d4869207e3 | ||
|
|
f4790f6f66 | ||
|
|
daf49e9d82 | ||
|
|
d6360c1ba9 | ||
|
|
6c022f9bf1 | ||
|
|
ff36fe365e | ||
|
|
ef8ff1b5d8 | ||
|
|
6addf28c4b | ||
|
|
b101cf46b6 | ||
|
|
8a2cd81091 | ||
|
|
223b19f116 | ||
|
|
779568bb38 | ||
|
|
661a70fc79 | ||
|
|
32171a8b0c | ||
|
|
c32db3c72b | ||
|
|
c86ce70968 | ||
|
|
f336e639e9 | ||
|
|
9714594c35 | ||
|
|
6eb2681c09 | ||
|
|
bed492da70 | ||
|
|
556a1397a9 | ||
|
|
3aceb61059 | ||
|
|
da21b74313 | ||
|
|
5a483c2ffb | ||
|
|
a34071876f | ||
|
|
357f752bed | ||
|
|
b9ab6e2019 | ||
|
|
0e1ce76ea8 | ||
|
|
bd63a9f056 | ||
|
|
0962c9fb72 | ||
|
|
7812039402 | ||
|
|
44a6b493ee | ||
|
|
becd75676f | ||
|
|
727c462069 | ||
|
|
c9d3c29aa3 | ||
|
|
e3d9b875c9 | ||
|
|
fa2e5710ac | ||
|
|
56a7b8b724 | ||
|
|
d8ef864b02 | ||
|
|
cf1c4a0cb1 | ||
|
|
fb9b006865 | ||
|
|
f24387fa2b | ||
|
|
c4dc8fd101 | ||
|
|
c6e0284ac5 | ||
|
|
fef3389157 | ||
|
|
7b5fb33296 | ||
|
|
bdc4dfebf5 | ||
|
|
9a93fb5716 | ||
|
|
e8a5c9e1b8 | ||
|
|
3816d478df | ||
|
|
8c497793f9 | ||
|
|
303dc091b4 | ||
|
|
b8f93a8fe0 | ||
|
|
a066074054 | ||
|
|
bdd9b96fa3 | ||
|
|
08b3a1a34a | ||
|
|
f93d0befaf | ||
|
|
d6e9fad60e | ||
|
|
82d177ccbd | ||
|
|
33ea1e8b78 | ||
|
|
f617fe7890 | ||
|
|
200053771a | ||
|
|
4a7810e992 | ||
|
|
981abb4612 | ||
|
|
4a81424492 | ||
|
|
b41811a68c | ||
|
|
040e818d72 | ||
|
|
162f8e01aa | ||
|
|
ba1fa904a9 | ||
|
|
a1a7a1bc03 | ||
|
|
a6857ede03 | ||
|
|
c06c796242 | ||
|
|
1e17d59965 | ||
|
|
983b95bc87 | ||
|
|
d2c7cbcbf9 | ||
|
|
ac64b65634 | ||
|
|
8f5ce73140 | ||
|
|
1362fc0c56 | ||
|
|
bc3c0ce772 | ||
|
|
edebb90a9a | ||
|
|
4d6fbaff11 | ||
|
|
226923fa7e | ||
|
|
2b1fc6f765 | ||
|
|
cf3726bcbc | ||
|
|
52587c28d6 | ||
|
|
f8c768760b | ||
|
|
c00e68102c | ||
|
|
b7a7d673b9 | ||
|
|
d6d94d90bf | ||
|
|
f7eea63872 | ||
|
|
ab490dc7b8 | ||
|
|
2ad8c60abc | ||
|
|
19ae142bdd | ||
|
|
dc2b0a2823 | ||
|
|
88a330ebef | ||
|
|
fa2f1bfbb0 | ||
|
|
7c5b0e8292 | ||
|
|
eefc9035f0 | ||
|
|
c87b9fdb15 | ||
|
|
556ce9f543 | ||
|
|
79d6f4e211 | ||
|
|
f1781c20a3 | ||
|
|
1109de3827 | ||
|
|
db66e33e9e | ||
|
|
2bc5d17ac3 | ||
|
|
e5977f05d8 | ||
|
|
d342ec10cc | ||
|
|
52125a54a5 | ||
|
|
77eba4d0d1 | ||
|
|
3dc3aef8a4 | ||
|
|
0e8eb8c48e | ||
|
|
863ac31f01 | ||
|
|
33e13c85e1 | ||
|
|
6888e6cdff | ||
|
|
dbeeeae593 | ||
|
|
1a9ddd2396 | ||
|
|
c649aca20a | ||
|
|
cc4c37dbac | ||
|
|
b7cdb5a31e | ||
|
|
5ce636b0ba | ||
|
|
140726d23f | ||
|
|
b32ef809c3 | ||
|
|
3349296370 | ||
|
|
6aa408c6af | ||
|
|
9a15730c2a | ||
|
|
3fe4319314 | ||
|
|
d4ddc46e77 | ||
|
|
40aac5875a | ||
|
|
cb9015e254 | ||
|
|
121072cfe6 | ||
|
|
7812e836e4 | ||
|
|
dcdb145713 | ||
|
|
1029f57b8a | ||
|
|
64172685d6 | ||
|
|
655aae5911 | ||
|
|
a02315e1c4 | ||
|
|
6137443d24 | ||
|
|
4dee919bc0 | ||
|
|
10c7709f30 | ||
|
|
8439a73645 | ||
|
|
a9a5cbf431 | ||
|
|
07e24b4058 | ||
|
|
51f564eea6 | ||
|
|
06f5b46133 | ||
|
|
b03a4993b3 | ||
|
|
836aff3467 | ||
|
|
d5d4d709c7 | ||
|
|
a2f6581171 | ||
|
|
3ec128c5fd | ||
|
|
cada78917c | ||
|
|
0a53b45858 | ||
|
|
6b2e03c5b1 | ||
|
|
94c46d7486 | ||
|
|
cb5542bce5 | ||
|
|
959a9c79bd | ||
|
|
e0583975cd | ||
|
|
9214c28aad | ||
|
|
e7a4327eb8 | ||
|
|
b60acfa87d | ||
|
|
0f72652c2d | ||
|
|
b3b8cbd001 | ||
|
|
d4b94bd65b | ||
|
|
f09ef23ae6 | ||
|
|
d96bbf0aae | ||
|
|
194916135a | ||
|
|
15d74bad1d | ||
|
|
89d3dabf2e | ||
|
|
eec344cc1e | ||
|
|
6cabad6e7a | ||
|
|
534340cd88 | ||
|
|
e95d66faa8 | ||
|
|
9c16976749 | ||
|
|
3cc9d2051a | ||
|
|
884e3fd21f | ||
|
|
dec082ff97 | ||
|
|
4fab72b40e | ||
|
|
a134892a3d | ||
|
|
666b93e989 | ||
|
|
956a1a17fb | ||
|
|
31f11cf304 | ||
|
|
61ebb37843 | ||
|
|
f1777f9517 | ||
|
|
5319d1cffa | ||
|
|
075b975fed | ||
|
|
b476184574 | ||
|
|
0b57c07c79 | ||
|
|
b709b02e96 | ||
|
|
88e7d773df | ||
|
|
216ae7db52 | ||
|
|
7e03ae3240 | ||
|
|
7947f327de | ||
|
|
47579f8a40 | ||
|
|
52e19113f3 | ||
|
|
08145bc45c | ||
|
|
45c8c3b611 | ||
|
|
df8667b18b | ||
|
|
2c558d5741 | ||
|
|
c8579abb43 | ||
|
|
7348e99269 | ||
|
|
e489e40a85 | ||
|
|
ecb0aaa7c2 | ||
|
|
a550263d6c | ||
|
|
bcfc1ad8f6 | ||
|
|
430c05991c | ||
|
|
513af1efc9 | ||
|
|
0397321be0 | ||
|
|
6656553fa4 | ||
|
|
39f7248d4a | ||
|
|
dd9db5e889 | ||
|
|
6cdedf5834 | ||
|
|
70cca1eac0 | ||
|
|
5dc6013713 | ||
|
|
7c291ba31b | ||
|
|
085fa42b7d | ||
|
|
031e152d29 | ||
|
|
15da1a9abc | ||
|
|
fd943182bd | ||
|
|
d3ad2f357f | ||
|
|
b47507951e | ||
|
|
eed7b0e9c5 | ||
|
|
da3d7e1587 | ||
|
|
565aa0b763 | ||
|
|
0fbf2888e7 | ||
|
|
4d42450a73 | ||
|
|
01ca196530 | ||
|
|
30eceaf95f | ||
|
|
f0fe1957a8 | ||
|
|
00d3f9295e | ||
|
|
8d9e50c807 | ||
|
|
662ce46971 | ||
|
|
a89590b425 | ||
|
|
9308cfdcfb | ||
|
|
a566ecc58f | ||
|
|
a338b78eb9 | ||
|
|
d0836aa89a | ||
|
|
d6a7aca2f4 | ||
|
|
0948cfc19e | ||
|
|
e49d31a1c9 | ||
|
|
f94a8344f6 | ||
|
|
055e71518e | ||
|
|
f304603e13 | ||
|
|
064153fca4 | ||
|
|
1ebb913827 | ||
|
|
ba98667c65 | ||
|
|
6324280432 | ||
|
|
995f92a456 | ||
|
|
d81f2ae4fb | ||
|
|
e67f2f4791 | ||
|
|
cbdac1e150 | ||
|
|
18d72a9142 | ||
|
|
506f7e0074 | ||
|
|
9203883bbe | ||
|
|
e92b29ad53 | ||
|
|
db4c4e3321 | ||
|
|
a7703fe6f7 | ||
|
|
8738ed88f0 | ||
|
|
47a07d8476 | ||
|
|
c9fe7ebc7b | ||
|
|
f070497cbd | ||
|
|
a16f99c6a2 | ||
|
|
9a1e09eb1f | ||
|
|
13931fd851 | ||
|
|
e8206db829 | ||
|
|
5f301914a0 | ||
|
|
84fd0c7ff4 | ||
|
|
a38e3c222f | ||
|
|
f65bcf481a | ||
|
|
8a6911b894 | ||
|
|
7dcf129b3b | ||
|
|
821814b450 | ||
|
|
89d09070e3 | ||
|
|
c98bad042d | ||
|
|
9ac94ff001 | ||
|
|
d885094be3 | ||
|
|
e55a0ef107 | ||
|
|
7269498ecc | ||
|
|
cac76b2754 | ||
|
|
5a2b1e8482 | ||
|
|
314e6443c9 | ||
|
|
5d4a8978bd | ||
|
|
c501c2d4cd | ||
|
|
91577c7f51 | ||
|
|
301c956039 | ||
|
|
8b6e021f35 | ||
|
|
ae4dad09b5 | ||
|
|
0d606968d8 | ||
|
|
24a44b9abe | ||
|
|
f3f6295d53 | ||
|
|
e39c2552ac | ||
|
|
cc2177de15 | ||
|
|
552969e33e | ||
|
|
c426e32247 | ||
|
|
6ca1556d02 | ||
|
|
bb224c8aa1 | ||
|
|
2bb9e35a48 | ||
|
|
e83fb468c6 | ||
|
|
a322122f74 | ||
|
|
3b2f617652 | ||
|
|
b5f9381036 | ||
|
|
c8ad25caa6 | ||
|
|
10ace228bc | ||
|
|
5a1e6b60a2 | ||
|
|
c9a53aa74d | ||
|
|
b4b79584d1 | ||
|
|
57d0fcd021 | ||
|
|
b6586bb06d | ||
|
|
1c29a8ed18 | ||
|
|
66b762577c | ||
|
|
bfce7750b1 | ||
|
|
2496b973f9 | ||
|
|
e9743d85dd | ||
|
|
2ee77aa6be | ||
|
|
696a533532 | ||
|
|
752603bc70 | ||
|
|
a1b8457cb5 | ||
|
|
5d74891285 | ||
|
|
4f630b0449 | ||
|
|
204cb4d226 | ||
|
|
458a109031 | ||
|
|
b0c1816664 | ||
|
|
fa0852f9e5 | ||
|
|
092b6825ac | ||
|
|
f0ac68ad35 | ||
|
|
082b20e46b | ||
|
|
b2ebd03b16 | ||
|
|
0b865136e3 | ||
|
|
99c0bd65df | ||
|
|
85395b76b0 | ||
|
|
fac19e1883 | ||
|
|
734c6af187 | ||
|
|
13fbd99491 | ||
|
|
d9bf80f655 | ||
|
|
e816bc6723 | ||
|
|
1b27ac982f | ||
|
|
d6ea56dfd9 | ||
|
|
ea39841fcd | ||
|
|
f43c6ea6a4 | ||
|
|
f799a293c8 | ||
|
|
c75410e72c | ||
|
|
a085581057 | ||
|
|
265b88273e | ||
|
|
d0b1aaa076 | ||
|
|
6584de4a78 | ||
|
|
46efed8b70 | ||
|
|
1f1861dae6 | ||
|
|
624c057ae1 | ||
|
|
ce6e6da510 | ||
|
|
96ab68eee0 | ||
|
|
b51919dce1 | ||
|
|
0370856d78 | ||
|
|
f822e07d76 | ||
|
|
3617a96372 | ||
|
|
8d29665ae1 | ||
|
|
2efebe3315 | ||
|
|
5a3f82e2f4 | ||
|
|
867bdbecb3 | ||
|
|
d719776460 | ||
|
|
f142887088 | ||
|
|
259560aa26 | ||
|
|
27f2dd56d6 | ||
|
|
d73e3285de | ||
|
|
fc50532213 | ||
|
|
5741cbae45 | ||
|
|
f4ef420c01 | ||
|
|
07490618ae | ||
|
|
fe0a24f38a | ||
|
|
3d8885cbbd | ||
|
|
739a79b1e9 | ||
|
|
f6db9e2f39 | ||
|
|
e8421de23c | ||
|
|
8f907bc9a2 | ||
|
|
91667430a8 | ||
|
|
14908cba8f | ||
|
|
db55422870 | ||
|
|
3482d4eccf | ||
|
|
0359f6e94f | ||
|
|
51c97a41aa | ||
|
|
82fdd7018d | ||
|
|
ccf94e2e6e | ||
|
|
55b8ce9b23 | ||
|
|
1297a2be52 | ||
|
|
8801f02949 | ||
|
|
482ac70a0b | ||
|
|
46b9c09e41 | ||
|
|
a218d3a824 | ||
|
|
d7c8516a4b | ||
|
|
e06bbe05e1 | ||
|
|
83429abf4a | ||
|
|
03add24acf | ||
|
|
57a5b73a4c | ||
|
|
1f6e62a4ae | ||
|
|
9150c23c04 | ||
|
|
9c1dac3ff0 | ||
|
|
4b39c1f654 | ||
|
|
156e0a8070 | ||
|
|
e5d51866c6 | ||
|
|
c9aef16066 | ||
|
|
328695bd47 | ||
|
|
da832532c0 | ||
|
|
52c61deaf9 | ||
|
|
e57871bb95 | ||
|
|
f1ddf63027 | ||
|
|
91b356cf8e | ||
|
|
59b63defe5 | ||
|
|
317b33d647 | ||
|
|
0949acb6e6 | ||
|
|
1dae7df26f | ||
|
|
48215231f9 | ||
|
|
9d08506dce | ||
|
|
fd0b3734d3 | ||
|
|
16cee3d009 | ||
|
|
820b1e651a | ||
|
|
24b873a740 | ||
|
|
ed54e14f1b | ||
|
|
f83da768b6 | ||
|
|
f9ab2a0e9f | ||
|
|
38a0d7ceb5 | ||
|
|
b5883c1cfb | ||
|
|
713e034d95 | ||
|
|
844e0ae688 | ||
|
|
0e2a167bdb | ||
|
|
9825f7fa87 | ||
|
|
66ad2ad539 | ||
|
|
a5e96ff99e | ||
|
|
45736443be | ||
|
|
87caf27ac4 | ||
|
|
a5f3596e6c | ||
|
|
50aeeff96c | ||
|
|
bf4c2e00c0 | ||
|
|
cc3a2200a9 | ||
|
|
1a497c2499 | ||
|
|
969af7c773 | ||
|
|
bd96f6eac4 | ||
|
|
6af38b1a43 | ||
|
|
a8df192df0 | ||
|
|
27c58c3946 | ||
|
|
233d7ad3f2 | ||
|
|
856c6314ec | ||
|
|
ffe0abbfc2 | ||
|
|
c3d9f8ee7e | ||
|
|
3a685749cb | ||
|
|
16476f99fd | ||
|
|
5bb2874940 | ||
|
|
7bee9a8f96 | ||
|
|
d60985df7f | ||
|
|
83cee9e091 | ||
|
|
81160fee56 | ||
|
|
a582d92c31 | ||
|
|
03d3343e21 | ||
|
|
00b6370848 | ||
|
|
7380b9816e | ||
|
|
cda26635cd | ||
|
|
b8b0f9d02e | ||
|
|
f0ad810553 | ||
|
|
637ddfce09 | ||
|
|
6c9c4879d9 | ||
|
|
d576724bfd | ||
|
|
4d6a9ef93f | ||
|
|
7ff2d3353c | ||
|
|
c59ebb2d71 | ||
|
|
8c95c084cb | ||
|
|
4448d975d1 | ||
|
|
44d98bfd6d | ||
|
|
529cba19b0 | ||
|
|
7109f32f96 | ||
|
|
9f66a3a9ed | ||
|
|
1eac0024c0 | ||
|
|
90e9465fa5 | ||
|
|
6e9dfe1de1 | ||
|
|
86f2af2bc7 | ||
|
|
c2694ef75e | ||
|
|
22bcfca700 | ||
|
|
a241dc7990 | ||
|
|
a61bbdc239 | ||
|
|
9db6b1a0d9 | ||
|
|
baea25e657 | ||
|
|
431fc6a7f6 | ||
|
|
178aee4b1c | ||
|
|
578df14f27 | ||
|
|
f6bd7c8e53 | ||
|
|
bc918404fe | ||
|
|
9a35bfea39 | ||
|
|
de1593d5c0 | ||
|
|
e3fa56ae05 | ||
|
|
5ac94ad898 | ||
|
|
ab6e48b833 | ||
|
|
08752b372e | ||
|
|
81176737f8 | ||
|
|
3920b1c764 | ||
|
|
b15347cb7d | ||
|
|
3e8d198133 | ||
|
|
5196bd15e9 | ||
|
|
c54230d14e | ||
|
|
8a44c31c95 | ||
|
|
dfa1bb0ac7 | ||
|
|
85a368b58d | ||
|
|
c7d3d22ae1 | ||
|
|
80a870a3e5 | ||
|
|
282b2b5afb | ||
|
|
a588f00f7b | ||
|
|
5884219867 | ||
|
|
f2a522d70d | ||
|
|
cc5058e5d7 | ||
|
|
fac8295d6e | ||
|
|
9e7f460c09 | ||
|
|
0749453355 | ||
|
|
9f6aae3bf2 | ||
|
|
bd2355a047 | ||
|
|
3532ed1621 | ||
|
|
d5d705069d | ||
|
|
e74a50f525 | ||
|
|
d17627b9c6 | ||
|
|
0a7054c7e4 | ||
|
|
a229a7f39f | ||
|
|
e0330c1696 | ||
|
|
4d4889bf1b | ||
|
|
5c4426c5b8 | ||
|
|
12c0246890 | ||
|
|
73efcec564 | ||
|
|
a725db17b7 | ||
|
|
325299f942 | ||
|
|
56c3eaed20 | ||
|
|
04316bd223 | ||
|
|
c261dac02f | ||
|
|
51bbc70652 | ||
|
|
7a9045dd77 | ||
|
|
83a0030c0a | ||
|
|
fd408c9790 | ||
|
|
f359dca0dc | ||
|
|
85f327d8d3 | ||
|
|
60ab8a94a7 | ||
|
|
4b522e145c | ||
|
|
5c8041b4d7 | ||
|
|
2736af6b61 | ||
|
|
efe4a3722d | ||
|
|
1dd964f87d | ||
|
|
440f257688 | ||
|
|
472f8013bd | ||
|
|
2b1d8e3eaf | ||
|
|
44e3ba115a | ||
|
|
673df61914 | ||
|
|
1816c5241b | ||
|
|
e8178bf8a4 | ||
|
|
a0e1591ac2 | ||
|
|
6c3c9cea7f | ||
|
|
091445a4a9 | ||
|
|
513c1ba996 | ||
|
|
cb48c81a44 | ||
|
|
52d9ee0dc2 | ||
|
|
3e6f948851 | ||
|
|
b137f31b8c | ||
|
|
2171375f93 | ||
|
|
9e7c0f985f | ||
|
|
b87e58fab3 | ||
|
|
fe62927bd8 | ||
|
|
9e1ccf8fab | ||
|
|
edcd5b113e | ||
|
|
5867a43dc8 | ||
|
|
9445776d61 | ||
|
|
03fc9a0b17 | ||
|
|
b3ea01d86f | ||
|
|
a502ceb075 | ||
|
|
2569c64740 | ||
|
|
7f25143972 | ||
|
|
747c9a7adf | ||
|
|
e13913ed57 | ||
|
|
b3b3a07133 | ||
|
|
2c1262b436 | ||
|
|
72096bf698 | ||
|
|
07b9999de9 | ||
|
|
4eb9066997 | ||
|
|
21b5fac57a | ||
|
|
d357e8504b | ||
|
|
7f4b477d2e | ||
|
|
cdebd70e15 | ||
|
|
5b0510c5b7 | ||
|
|
ef6ba0d846 | ||
|
|
268565079c | ||
|
|
a396233cb6 | ||
|
|
839c31006b | ||
|
|
133bbafa3c | ||
|
|
c911901b5e | ||
|
|
0a4ddd7246 | ||
|
|
4a2ae06ca4 | ||
|
|
0e95cf0dec | ||
|
|
e926a664d5 | ||
|
|
e99c4fc668 | ||
|
|
2d38bc99b3 | ||
|
|
6ab5fd1da9 | ||
|
|
8731cc2914 | ||
|
|
1480bc5d4e | ||
|
|
105bb3ef8a | ||
|
|
8b8a61bdf9 | ||
|
|
a7a25ee19d | ||
|
|
92d0924b82 | ||
|
|
4711b9b05a | ||
|
|
90ef327882 | ||
|
|
f9ccdba352 | ||
|
|
93f02ee0c6 | ||
|
|
82e10f1b61 | ||
|
|
0b2da67912 | ||
|
|
467a1cd4a5 | ||
|
|
67410d53f7 | ||
|
|
609b935a8c | ||
|
|
0afc6cd310 | ||
|
|
873e9d35ac | ||
|
|
24dfe6db8a | ||
|
|
088ddef98a | ||
|
|
9aae45eb4a | ||
|
|
d51e5d2898 | ||
|
|
c4b9101759 | ||
|
|
4b97296148 | ||
|
|
d3fd2630b7 | ||
|
|
f27af1b20a | ||
|
|
90e8404a77 | ||
|
|
37a07858a9 | ||
|
|
07efd7cc20 | ||
|
|
08572189f0 | ||
|
|
27343efb0b | ||
|
|
ddcff10343 | ||
|
|
6cac48df32 | ||
|
|
dd28500835 | ||
|
|
2ed9e21eba | ||
|
|
1d6e34f3f9 | ||
|
|
ec2c805e48 | ||
|
|
076d8fc868 | ||
|
|
0b1bcfcc20 | ||
|
|
a35e876978 | ||
|
|
530332dfbc | ||
|
|
23a785aeb3 | ||
|
|
64d6c30562 | ||
|
|
74f02703e6 | ||
|
|
65c4c0a490 | ||
|
|
17b8c3b6ea | ||
|
|
7354009a73 | ||
|
|
74f7ac04a1 | ||
|
|
f58bd817e2 | ||
|
|
e23c5edd5f | ||
|
|
697ce2d67b | ||
|
|
5139fb7e18 | ||
|
|
ae2fb557f3 | ||
|
|
814ecedd1e | ||
|
|
e5b2286ca8 | ||
|
|
ca222d30c8 | ||
|
|
7bf07d2526 | ||
|
|
cb56b0b238 | ||
|
|
e346059eef | ||
|
|
60bea052a9 | ||
|
|
b7686a88e9 | ||
|
|
507a87354b | ||
|
|
9e0517a134 | ||
|
|
9779cc2fe2 | ||
|
|
4db55f88e8 | ||
|
|
d768b8c812 | ||
|
|
55f8989392 | ||
|
|
6d27fecce1 | ||
|
|
e668890837 | ||
|
|
e66fc22057 | ||
|
|
26f817807c | ||
|
|
d58b8414b9 | ||
|
|
3e5dde9a26 | ||
|
|
709bc03d6f | ||
|
|
314c7bd12f | ||
|
|
e54db4ee70 | ||
|
|
04689979b4 | ||
|
|
b5b704d376 | ||
|
|
5b29d14783 | ||
|
|
eda7792b15 | ||
|
|
28b2089ee4 | ||
|
|
14ca75d4e7 | ||
|
|
088487a3d4 | ||
|
|
fc203c7d76 | ||
|
|
6d15a506fa | ||
|
|
90386780e3 | ||
|
|
937d073328 | ||
|
|
f7f30476d5 | ||
|
|
2c03aac6d3 | ||
|
|
a472e8834b | ||
|
|
c521883be4 | ||
|
|
508c9aaf60 | ||
|
|
f5c5926fb9 | ||
|
|
88fbc31ee0 | ||
|
|
2747a8ca40 | ||
|
|
0dec430707 | ||
|
|
2d76b09d2e | ||
|
|
1ba2905017 | ||
|
|
3587ee492b | ||
|
|
dfbe938e54 | ||
|
|
16ddc1698d | ||
|
|
1ad8ad623e | ||
|
|
7d7bf993bb | ||
|
|
3c07879504 | ||
|
|
c5f67218bf | ||
|
|
7602277c86 | ||
|
|
31e77eacdb | ||
|
|
6fae29679a | ||
|
|
28ba54a32a | ||
|
|
fd06ed833b | ||
|
|
0cff5ac5a1 | ||
|
|
de451d4474 | ||
|
|
279db55840 | ||
|
|
3deb92c2c5 | ||
|
|
0f14933577 | ||
|
|
6315716f23 | ||
|
|
1e18da5c38 | ||
|
|
54fb051e52 | ||
|
|
fa2b318dd6 | ||
|
|
5659db5529 | ||
|
|
a61ca097a7 | ||
|
|
dca527be1b | ||
|
|
29d462ebce | ||
|
|
421e73e6db | ||
|
|
d9e60d29e1 | ||
|
|
5c8f8d0311 | ||
|
|
2dfa71fad5 | ||
|
|
7ff41a78f9 | ||
|
|
8d3906365d | ||
|
|
b6b8f6634e | ||
|
|
5854da10e6 | ||
|
|
71f98dd056 | ||
|
|
955aacfbc5 | ||
|
|
4691fa0ed5 | ||
|
|
aa79d0cd2f | ||
|
|
88de982071 | ||
|
|
97b1abd6dd | ||
|
|
c71a50deb5 | ||
|
|
e52bb147a7 | ||
|
|
732bc2058e | ||
|
|
40fd163a3b | ||
|
|
2554b512c0 | ||
|
|
c6cab1f352 | ||
|
|
c39192ba64 | ||
|
|
43177324c0 | ||
|
|
6f73dbea80 | ||
|
|
35e197f413 | ||
|
|
551ab84c2d | ||
|
|
422902dbda | ||
|
|
64d910ad37 | ||
|
|
49e38a5b32 | ||
|
|
9def2b04d7 | ||
|
|
5429f0f6b5 | ||
|
|
c906c65cac | ||
|
|
718daa153d | ||
|
|
075f4ac661 | ||
|
|
8555335935 | ||
|
|
08f3aa8972 | ||
|
|
4caf1e9b59 | ||
|
|
b17b2fb732 | ||
|
|
cda3db1449 | ||
|
|
dd6a44abb1 | ||
|
|
4fb0c1f963 | ||
|
|
cff0342454 | ||
|
|
c2db4c2462 | ||
|
|
69b697378b | ||
|
|
26e59c8742 | ||
|
|
62d6be3747 | ||
|
|
5ea47d9560 | ||
|
|
39c3412f91 | ||
|
|
3d85433748 | ||
|
|
9f8c599ca7 | ||
|
|
f33bb99821 | ||
|
|
6e63fcaca3 | ||
|
|
ceb26bac48 | ||
|
|
29f104319e | ||
|
|
19471da3fd | ||
|
|
7ad42ff431 | ||
|
|
26d04c948f | ||
|
|
97b1ffcb3b | ||
|
|
91ae56af45 | ||
|
|
673f5e588d | ||
|
|
90a6961638 | ||
|
|
7374b96f5c | ||
|
|
b8e56dce83 | ||
|
|
b6582a471a | ||
|
|
92c4ff1c2f | ||
|
|
0755767440 | ||
|
|
eb823655af | ||
|
|
f84c93d834 | ||
|
|
45c4365ec3 | ||
|
|
6188e94108 | ||
|
|
553b04883e | ||
|
|
9551635684 | ||
|
|
200a8f1ea2 | ||
|
|
98ce013242 | ||
|
|
bf4de2a46b | ||
|
|
7f8a89c25c | ||
|
|
457d4b7b72 | ||
|
|
290c51735e | ||
|
|
0818a42396 | ||
|
|
96186a93b9 | ||
|
|
956e03009a | ||
|
|
e8172fdfbc | ||
|
|
b2e2cc44c2 | ||
|
|
790132a672 | ||
|
|
1797135db5 | ||
|
|
ee436aa803 | ||
|
|
da1864d79e | ||
|
|
1bfe4a75be | ||
|
|
fe646ea591 | ||
|
|
ecd212c01d | ||
|
|
746c9f76e4 | ||
|
|
bf08c13e9b | ||
|
|
3b66929301 | ||
|
|
afffcd5810 | ||
|
|
100ede5764 | ||
|
|
4d023bd7fe | ||
|
|
de36ff043e | ||
|
|
29a8ee0826 | ||
|
|
1cbfe93520 | ||
|
|
2706c9d66e | ||
|
|
3a90dc3893 | ||
|
|
04bc0b0bb8 | ||
|
|
28eabcb099 | ||
|
|
206b9ead8f | ||
|
|
c5a3cae83a | ||
|
|
efa50f72a7 | ||
|
|
b0a6cd6305 | ||
|
|
2402958aec | ||
|
|
92d7869fc7 | ||
|
|
83d22f4e48 | ||
|
|
41e39ea6e1 | ||
|
|
dbeea7220f | ||
|
|
89a28209e8 | ||
|
|
980deb4c9e | ||
|
|
512c54bbc0 | ||
|
|
612b787b0d | ||
|
|
4bad852a78 | ||
|
|
0636f9adac | ||
|
|
d9bc1e44af | ||
|
|
0cdc4a9565 | ||
|
|
4a43dcb940 | ||
|
|
1c4066cd9e | ||
|
|
389982eb5a | ||
|
|
48f263336b | ||
|
|
a528398c77 | ||
|
|
11638fdf7d | ||
|
|
0e8c199e87 | ||
|
|
d7350668d1 | ||
|
|
1b6b8602c1 | ||
|
|
f71ee5203e | ||
|
|
b720f1f03c | ||
|
|
8a9fe26866 | ||
|
|
c801799218 | ||
|
|
a8e1dde357 | ||
|
|
e03383d088 | ||
|
|
bdd2a94315 | ||
|
|
072caa4a90 | ||
|
|
270d4d0855 | ||
|
|
a19815dc6b | ||
|
|
c80e8b964c | ||
|
|
b38af0f522 | ||
|
|
657073a650 | ||
|
|
20e040c858 | ||
|
|
926addbfe2 | ||
|
|
027a7ba3eb | ||
|
|
a76bc52da5 | ||
|
|
6e141a9cae | ||
|
|
eea836135a | ||
|
|
aa41f16589 | ||
|
|
23ef6c149e | ||
|
|
da3a36eefd | ||
|
|
78c6435dbb | ||
|
|
5c388c39f4 | ||
|
|
5b1a70aa2d | ||
|
|
440824d431 | ||
|
|
f087a5b856 | ||
|
|
c5db276521 | ||
|
|
9d704d99d3 | ||
|
|
66f0fb986c | ||
|
|
5ccb66794b | ||
|
|
cb5c73f64a | ||
|
|
65f4be1a10 | ||
|
|
5ac25e7c7a | ||
|
|
4d9a3b19d5 | ||
|
|
764f9e606d | ||
|
|
a3667f462a | ||
|
|
3fde445b91 | ||
|
|
d80a9123b7 | ||
|
|
2c29e391dd | ||
|
|
f8a806ad9f | ||
|
|
7cd3cfa58a | ||
|
|
cad790d43b | ||
|
|
e790fc0e79 | ||
|
|
a9ea1ae854 | ||
|
|
eb02dcf87f | ||
|
|
8ce23b3ccd | ||
|
|
bce1ba400f | ||
|
|
ebac375791 | ||
|
|
1a7526dcd4 | ||
|
|
f01a6d3e8f | ||
|
|
32779c5b64 | ||
|
|
64daeddf6f | ||
|
|
6a7e2c74fb | ||
|
|
93cccd27f6 | ||
|
|
cd1b5f7883 | ||
|
|
b409df34db | ||
|
|
14466a6d19 | ||
|
|
978598b174 | ||
|
|
d1eb7b5757 | ||
|
|
eb654f1bad | ||
|
|
b1a68d899c | ||
|
|
a67f7dce31 | ||
|
|
8d361c47fb | ||
|
|
8361ed1f54 | ||
|
|
19c72cd52a | ||
|
|
c363b6df2b | ||
|
|
0f2898ea88 | ||
|
|
99552420a2 | ||
|
|
126a6f894f | ||
|
|
9c78fc928a | ||
|
|
2318c764cf | ||
|
|
39b99072fb | ||
|
|
ad3f54ff1a | ||
|
|
19c3773cc0 | ||
|
|
bbd5119a26 | ||
|
|
e3bd9434b1 | ||
|
|
13cdf2ff0e | ||
|
|
be03b8ff93 | ||
|
|
55d35d8387 | ||
|
|
75c54e6384 | ||
|
|
ba5c105c01 | ||
|
|
44f801186f | ||
|
|
ec6ca06898 | ||
|
|
dde31030e9 | ||
|
|
30a6873a44 | ||
|
|
31d033c9d8 | ||
|
|
fbe78b1a3a | ||
|
|
25332fa5ac | ||
|
|
2de96c4bd5 | ||
|
|
e443ea139d | ||
|
|
30db674147 | ||
|
|
164a86d3b0 | ||
|
|
677fe33990 | ||
|
|
8f495e5543 | ||
|
|
fc4988ffb0 | ||
|
|
24a77824f2 | ||
|
|
bbb95a5e06 | ||
|
|
fba756176d | ||
|
|
62b17f928e | ||
|
|
d7260104b1 | ||
|
|
15fe7ba31f | ||
|
|
30546bc0e7 | ||
|
|
15132217a3 | ||
|
|
bc3d267c51 | ||
|
|
c6ca327fb2 | ||
|
|
ddddabdccf | ||
|
|
2cffcbdc64 | ||
|
|
3973de7933 | ||
|
|
2d0a6a4969 | ||
|
|
66cd21db88 | ||
|
|
d366694062 | ||
|
|
4f10fe0a27 | ||
|
|
7b8bc864e9 | ||
|
|
82754561e2 | ||
|
|
17a7084b57 | ||
|
|
321b84f01f | ||
|
|
d9b427cce0 | ||
|
|
755bf985d2 | ||
|
|
607ad8c949 | ||
|
|
bd6c9e99fc | ||
|
|
0a154b30ad | ||
|
|
ade4c15eea | ||
|
|
528104a89b | ||
|
|
5ee40c8d34 | ||
|
|
dff15acdb5 | ||
|
|
3d9d3b49ae | ||
|
|
73a5e82e04 | ||
|
|
a735a8c084 | ||
|
|
ee351d3548 | ||
|
|
7b913db1ce | ||
|
|
eb6c16d3dd | ||
|
|
03ce17f0a5 | ||
|
|
7c4ffe490d | ||
|
|
4aea1c5adb | ||
|
|
66102880a3 | ||
|
|
333807b483 | ||
|
|
11103f8253 | ||
|
|
bb6a60b1ff | ||
|
|
ccfb20095e | ||
|
|
4351febe9f | ||
|
|
20a1edef89 | ||
|
|
b08ed61907 | ||
|
|
84890a3074 | ||
|
|
4c31c98d22 | ||
|
|
80ed4eba87 | ||
|
|
780c1ee265 | ||
|
|
2b0bd40b99 | ||
|
|
f8bad7e1e3 | ||
|
|
4a7c21d330 | ||
|
|
e652527313 | ||
|
|
51d841dcf3 | ||
|
|
4c22b3e5d9 | ||
|
|
0608887fb5 | ||
|
|
68f428b449 | ||
|
|
6afe9bbb45 | ||
|
|
e23bee353c | ||
|
|
0649f750b4 | ||
|
|
e3e1fbcf02 | ||
|
|
d79ca9b0b6 | ||
|
|
e6ffc04291 | ||
|
|
32d4f6c5d9 | ||
|
|
f969e68c10 | ||
|
|
d2ffbd9b86 | ||
|
|
fc062e6028 | ||
|
|
df2319a854 | ||
|
|
c543d93af1 | ||
|
|
cb00972b87 | ||
|
|
e3988a84db | ||
|
|
459de65477 | ||
|
|
7bbf8f2ab0 | ||
|
|
f24abbc47d | ||
|
|
161b74e871 | ||
|
|
cd39460925 | ||
|
|
2f40be638f | ||
|
|
86afe966d3 | ||
|
|
7e9e1ff1c2 | ||
|
|
b380d3abe3 | ||
|
|
5f2df2d2cb | ||
|
|
ff428f1d2f | ||
|
|
8fa502ca42 | ||
|
|
c7529c8ea8 | ||
|
|
f99fe72c42 | ||
|
|
2ad912bb85 | ||
|
|
db686ad522 | ||
|
|
044fd0cd2d | ||
|
|
1cdd110eb4 | ||
|
|
c720075c67 | ||
|
|
3d4d1b8553 | ||
|
|
e362c5af48 | ||
|
|
923bd2fd21 | ||
|
|
b846969fe1 | ||
|
|
3e4c89051d | ||
|
|
9c77734447 | ||
|
|
c881667c00 | ||
|
|
90bf996e1a | ||
|
|
6b8a059fc9 | ||
|
|
1ad153056a | ||
|
|
17ec4f1f6f | ||
|
|
fb4bbeb033 | ||
|
|
246ad6c03c | ||
|
|
638e1a721b | ||
|
|
5dd1e38b7a | ||
|
|
cac869b333 | ||
|
|
29525255f3 | ||
|
|
ba1c8464ef | ||
|
|
f6682404e1 | ||
|
|
97638bf977 | ||
|
|
4a100f7f11 | ||
|
|
cc40ae2101 | ||
|
|
03ca38eda1 | ||
|
|
f8fae02270 | ||
|
|
30d164eb26 | ||
|
|
696d3e056e | ||
|
|
3512f2c2c2 | ||
|
|
baa4caf9e3 | ||
|
|
d9b606672a | ||
|
|
327a5d8253 | ||
|
|
4ddb6b46c3 | ||
|
|
cf2daf353e | ||
|
|
6792e1a3e0 | ||
|
|
23a15834fa | ||
|
|
4cec3a0467 | ||
|
|
b5a2bd1a5b | ||
|
|
70c603854e | ||
|
|
88f4c1321a | ||
|
|
0aeb978e61 | ||
|
|
95db098477 | ||
|
|
2ab7f96f21 | ||
|
|
9440974f66 | ||
|
|
38165f420f | ||
|
|
8ced41570e | ||
|
|
30224fdde0 | ||
|
|
e534c56485 | ||
|
|
20d415e939 | ||
|
|
1965f38e9e | ||
|
|
0b8a247074 | ||
|
|
f0c4d609a6 | ||
|
|
a15c42d5bd | ||
|
|
98876b4dc2 | ||
|
|
0905439c31 | ||
|
|
7c44d067e8 | ||
|
|
d5828cd988 | ||
|
|
dc676236f0 | ||
|
|
0cca0d1617 | ||
|
|
98a6292165 | ||
|
|
d0c6dd9baf | ||
|
|
61f4aec868 | ||
|
|
b66529fe3e | ||
|
|
020d1ced1d | ||
|
|
7fc144edde | ||
|
|
6ee398ac2b | ||
|
|
b918751ff4 | ||
|
|
689e387180 | ||
|
|
642426c15b | ||
|
|
2887a6e07d | ||
|
|
1b4323a1b4 | ||
|
|
fe24591411 | ||
|
|
94b680e830 | ||
|
|
c6c82b9f1d | ||
|
|
a640d8a6d2 | ||
|
|
060b6ee7d1 | ||
|
|
5b4bc985ad | ||
|
|
838c16533d | ||
|
|
79e18896fe | ||
|
|
04fd5072fb | ||
|
|
4c420f3cf9 | ||
|
|
c2bf4abfa1 | ||
|
|
3a941f95e9 | ||
|
|
e31d13fa76 | ||
|
|
556689591c |
@@ -1,7 +1,11 @@
|
||||
# See http://editorconfig.org to read about the EditorConfig format.
|
||||
# - In theory automatically supported by VS2017+ and most common IDE or text editors.
|
||||
# - In practice VS2019 stills gets trailing whitespaces wrong :(
|
||||
# - Suggest install to trim whitespaces: https://marketplace.visualstudio.com/items?itemName=MadsKristensen.TrailingWhitespaceVisualizer
|
||||
# - In practice VS2019-VS2022 stills don't trim trailing whitespaces correctly :(
|
||||
# - Suggest installing this to trim whitespaces:
|
||||
# GitHub https://github.com/madskristensen/TrailingWhitespace
|
||||
# VS2019 https://marketplace.visualstudio.com/items?itemName=MadsKristensen.TrailingWhitespaceVisualizer
|
||||
# VS2022 https://marketplace.visualstudio.com/items?itemName=MadsKristensen.TrailingWhitespace64
|
||||
# (in spite of its name doesn't only visualize but also trims)
|
||||
# - Alternative for older VS2010 to VS2015: https://marketplace.visualstudio.com/items?itemName=EditorConfigTeam.EditorConfig
|
||||
|
||||
# top-most EditorConfig file
|
||||
|
||||
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@@ -1 +1 @@
|
||||
custom: ['https://github.com/ocornut/imgui/wiki/Sponsors']
|
||||
custom: ['https://github.com/ocornut/imgui/wiki/Funding']
|
||||
|
||||
1
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
1
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
blank_issues_enabled: false
|
||||
92
.github/ISSUE_TEMPLATE/issue_template.yml
vendored
Normal file
92
.github/ISSUE_TEMPLATE/issue_template.yml
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
name: "Ask a question, report a bug, request a feature, etc."
|
||||
description: "Ask any question, discuss best practices, report a bug, request a feature."
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
FOR FIRST-TIME USERS ISSUES COMPILING/LINKING/RUNNING, please use [GitHub Discussions](https://github.com/ocornut/imgui/discussions)
|
||||
For anything else: **we are happy to use 'GitHub Issues' for many types of open-ended questions**. We are encouraging 'Issues' becoming a large, centralized, tagged, cross-referenced database of Dear ImGui contents.
|
||||
|
||||
Be mindful that messages are being sent to the e-mail box of "Watching" users. Try to proof-read your messages before sending them. Edits are not seen by those users.
|
||||
|
||||
**If you are using Dear ImGui as part of a job that you are being well-paid for** and your company is not a sponsor. Please be mindful that this is a Free Software and you might be about to ask volunteers to help you doing your job. Please put extra effort describing your issue or question properly. If your company is wealthy, please read [Funding](https://github.com/ocornut/imgui/wiki/Funding) and consider getting in touch.
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
**Prerequisites:**
|
||||
- I have read [Frequently Asked Questions](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md).
|
||||
- I have read [Contributing Guidelines -> General Advices](https://github.com/ocornut/imgui/blob/master/docs/CONTRIBUTING.md#getting-started--general-advice).
|
||||
- I have read [Contributing Guidelines -> How to open an Issue](https://github.com/ocornut/imgui/blob/master/docs/CONTRIBUTING.md#how-to-open-an-issue).
|
||||
- I have searched [Github Issues and PR](https://github.com/ocornut/imgui/issues?q=) for discussion of similar topics.
|
||||
|
||||
----
|
||||
- type: input
|
||||
id: specs_version
|
||||
attributes:
|
||||
label: "Version/Branch of Dear ImGui:"
|
||||
description: "(please specify if you have made substantial modifications to your copy)"
|
||||
value: "Version 1.XX, Branch: XXX (master/docking/etc.)"
|
||||
placeholder: "Version 1.XX, Branch: XXX (master/docking/etc.)"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: specs_backend
|
||||
attributes:
|
||||
label: "Back-ends:"
|
||||
description: (or specify when using custom engine/back-ends)
|
||||
value: "imgui_impl_XXX.cpp + imgui_impl_XXX.cpp"
|
||||
placeholder: "imgui_impl_XXX.cpp + imgui_impl_XXX.cpp or n/a"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: specs_compiler_os
|
||||
attributes:
|
||||
label: "Compiler, OS:"
|
||||
placeholder: "e.g. Windows 11 + MSVC 2022, macOS + Clang 12, Linux + GCC etc."
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: specs_full
|
||||
attributes:
|
||||
label: "Full config/build information:"
|
||||
placeholder: |
|
||||
(If you can run, you may go to 'Demo->Tools->About Dear ImGui->Config/Build Info' to obtain detailed information that you can paste here)
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: issue_description
|
||||
attributes:
|
||||
label: "Details:"
|
||||
description: "Try to be explicit with your goals, your expectations and what you have tried. Be mindful of [The XY Problem](https://xyproblem.info). What you have in mind or in your code is not obvious to other people. People frequently discuss problems and suggest incorrect solutions without first clarifying their goals. When requesting a new feature, please describe the usage context (how you intend to use it, why you need it, etc.). If you tried something and it failed, show us what you tried. If you are reporting a bug, explain what's the bug, how does it occur, etc. If you are reporting a crash, please include a debugger callstack."
|
||||
value: |
|
||||
**My Issue/Question:**
|
||||
|
||||
XXX _(please provide as much context as possible)_
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: screenshots
|
||||
attributes:
|
||||
label: "Screenshots/Video:"
|
||||
description: "Attach screenshots or gif/videos to clarify the context. They often convey useful information that is omitted by the description."
|
||||
placeholder: "(You can drag files here)"
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: repro_code
|
||||
attributes:
|
||||
label: "Minimal, Complete and Verifiable Example code:"
|
||||
description: "Provide an [MCVE](https://stackoverflow.com/help/mcve) to demonstrate your problem. An ideal submission includes a small piece of code that anyone can paste into one of the examples applications (examples/*/main.cpp) or the demo (imgui_demo.cpp) to understand and reproduce it. Narrowing your problem to its shortest and purest form is the easiest way to understand it, explain it and fix it. Please test your shortened code to ensure it exhibits the problem. Often while creating the MCVE you will solve the problem! Many questions that are missing a standalone verifiable example are missing the actual cause of their issue in the description, which ends up wasting everyone's time."
|
||||
value: |
|
||||
```cpp
|
||||
// Here's some code anyone can copy and paste to reproduce your issue
|
||||
ImGui::Begin("Example Bug");
|
||||
MoreCodeToExplainMyIssue();
|
||||
ImGui::End();
|
||||
```
|
||||
validations:
|
||||
required: false
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thank you for taking the time to read prerequisites, filling this template and double-checking your message and your code!
|
||||
46
.github/issue_template.md
vendored
46
.github/issue_template.md
vendored
@@ -1,46 +0,0 @@
|
||||
(Click "Preview" above ^ to turn URL into clickable links)
|
||||
|
||||
1. PLEASE CAREFULLY READ: [FAQ](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md)
|
||||
|
||||
2. PLEASE CAREFULLY READ: [Issue Submitting Guidelines](https://github.com/ocornut/imgui/issues/2261)
|
||||
|
||||
3. FOR FIRST-TIME USERS ISSUES COMPILING/LINKING/RUNNING/LOADING FONTS, please use [GitHub Discussions](https://github.com/ocornut/imgui/discussions).
|
||||
|
||||
4. PLEASE MAKE SURE that you have: read the FAQ; explored the contents of `ShowDemoWindow()` including the Examples menu; searched among Issues; used your IDE to search for keywords in all sources and text files; and read the link provided in (1) (2).
|
||||
|
||||
5. Be mindful that messages are being sent to the e-mail box of "Watching" users. Try to proof-read your messages before sending them. Edits are not seen by those users.
|
||||
|
||||
6. Delete points 1-6 and PLEASE FILL THE TEMPLATE BELOW before submitting your issue.
|
||||
|
||||
Thank you!
|
||||
|
||||
----
|
||||
|
||||
_(you may also go to Demo>About Window, and click "Config/Build Information" to obtain a bunch of detailed information that you can paste here)_
|
||||
|
||||
**Version/Branch of Dear ImGui:**
|
||||
|
||||
Version: XXX
|
||||
Branch: XXX _(master/viewport/docking/etc.)_
|
||||
|
||||
**Back-end/Renderer/Compiler/OS**
|
||||
|
||||
Back-ends: imgui_impl_XXX.cpp + imgui_impl_XXX.cpp _(or specify if using a custom engine/back-end)_
|
||||
Compiler: XXX _(if the question is related to building or platform specific features)_
|
||||
Operating System: XXX
|
||||
|
||||
**My Issue/Question:**
|
||||
|
||||
XXX _(please provide as much context as possible)_
|
||||
|
||||
**Screenshots/Video**
|
||||
|
||||
XXX _(you can drag files here)_
|
||||
|
||||
**Standalone, minimal, complete and verifiable example:** _(see https://github.com/ocornut/imgui/issues/2261)_
|
||||
```
|
||||
// Here's some code anyone can copy and paste to reproduce your issue
|
||||
ImGui::Begin("Example Bug");
|
||||
MoreCodeToExplainMyIssue();
|
||||
ImGui::End();
|
||||
```
|
||||
10
.github/pull_request_template.md
vendored
10
.github/pull_request_template.md
vendored
@@ -1,6 +1,10 @@
|
||||
(Click "Preview" to turn any http URL into a clickable link)
|
||||
|
||||
PLEASE CAREFULLY READ:
|
||||
https://github.com/ocornut/imgui/issues/2261
|
||||
1. PLEASE CAREFULLY READ: [Contributing Guidelines](https://github.com/ocornut/imgui/blob/master/docs/CONTRIBUTING.md)
|
||||
|
||||
2. **Make sure you're using a special branch just for this pull request**. (In git, 1 PR = 1 branch. If you update the branch the PR will be updated.)
|
||||
|
||||
3. Consider running the [imgui_test_suite](https://github.com/ocornut/imgui_test_engine) or adding new tests to test for expected behaviors.
|
||||
|
||||
4. Clear this template before submitting your PR.
|
||||
|
||||
(Clear this template before submitting your PR)
|
||||
|
||||
556
.github/workflows/build.yml
vendored
556
.github/workflows/build.yml
vendored
@@ -8,6 +8,7 @@ on:
|
||||
# "scheduled" workflow, while maintaining ability to perform local CI builds.
|
||||
workflows:
|
||||
- scheduled
|
||||
- manual
|
||||
branches:
|
||||
- master
|
||||
- docking
|
||||
@@ -15,42 +16,62 @@ on:
|
||||
- requested
|
||||
|
||||
jobs:
|
||||
Windows:
|
||||
runs-on: windows-2019
|
||||
env:
|
||||
VS_PATH: C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\
|
||||
MSBUILD_PATH: C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
Build-Windows:
|
||||
runs-on: windows-2025
|
||||
name: Build - Windows
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ${{ github.workspace }}/imgui
|
||||
|
||||
env:
|
||||
VS_PATH: C:\Program Files\Microsoft Visual Studio\2022\Enterprise\
|
||||
MSBUILD_PATH: C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
path: ${{ github.workspace }}/imgui
|
||||
|
||||
# The VulkanSDK libs for Windows is manually generated using build_windows_vulkan_libs.ps1 + attached to issue #8925.
|
||||
# (we have a .yml workflow in commit history if it becomes ever useful to create this on CI too)
|
||||
- name: Install Dependencies
|
||||
shell: powershell
|
||||
run: |
|
||||
Invoke-WebRequest -Uri "https://www.libsdl.org/release/SDL2-devel-2.0.10-VC.zip" -OutFile "SDL2-devel-2.0.10-VC.zip"
|
||||
Expand-Archive -Path SDL2-devel-2.0.10-VC.zip
|
||||
echo "SDL2_DIR=$(pwd)\SDL2-devel-2.0.10-VC\SDL2-2.0.10\" >>${env:GITHUB_ENV}
|
||||
Invoke-WebRequest -Uri "https://www.libsdl.org/release/SDL2-devel-2.32.8-VC.zip" -OutFile "SDL2-devel-2.32.8-VC.zip"
|
||||
Expand-Archive -Path SDL2-devel-2.32.8-VC.zip
|
||||
echo "SDL2_DIR=$(pwd)\SDL2-devel-2.32.8-VC\SDL2-2.32.8\" >>${env:GITHUB_ENV}
|
||||
|
||||
Invoke-WebRequest -Uri "https://github.com/ocornut/imgui/files/3789205/vulkan-sdk-1.1.121.2.zip" -OutFile vulkan-sdk-1.1.121.2.zip
|
||||
Expand-Archive -Path vulkan-sdk-1.1.121.2.zip
|
||||
echo "VULKAN_SDK=$(pwd)\vulkan-sdk-1.1.121.2\" >>${env:GITHUB_ENV}
|
||||
Invoke-WebRequest -Uri "https://www.libsdl.org/release/SDL3-devel-3.2.18-VC.zip" -OutFile "SDL3-devel-3.2.18-VC.zip"
|
||||
Expand-Archive -Path SDL3-devel-3.2.18-VC.zip
|
||||
echo "SDL3_DIR=$(pwd)\SDL3-devel-3.2.18-VC\SDL3-3.2.18\" >>${env:GITHUB_ENV}
|
||||
|
||||
Invoke-WebRequest -Uri "https://github.com/user-attachments/files/22464296/vulkan_windows_libs_1.4.326.zip" -OutFile vulkan_windows_libs_1.4.326.zip
|
||||
Expand-Archive -Path vulkan_windows_libs_1.4.326.zip
|
||||
echo "VULKAN_SDK=$(pwd)\vulkan_windows_libs_1.4.326\" >>${env:GITHUB_ENV}
|
||||
|
||||
- name: Fix Projects
|
||||
shell: powershell
|
||||
run: |
|
||||
# WARNING: This will need updating if toolset/sdk change in project files!
|
||||
# CI workers do not supporter older Visual Studio versions. Fix projects to target newer available version.
|
||||
gci -recurse -filter "*.vcxproj" | ForEach-Object {
|
||||
# Fix SDK and toolset for most samples.
|
||||
(Get-Content $_.FullName) -Replace "<PlatformToolset>v110</PlatformToolset>","<PlatformToolset>v142</PlatformToolset>" | Set-Content -Path $_.FullName
|
||||
(Get-Content $_.FullName) -Replace "<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>","<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>" | Set-Content -Path $_.FullName
|
||||
# Fix SDK and toolset for samples that require newer SDK/toolset. At the moment it is only dx12.
|
||||
(Get-Content $_.FullName) -Replace "<PlatformToolset>v140</PlatformToolset>","<PlatformToolset>v142</PlatformToolset>" | Set-Content -Path $_.FullName
|
||||
(Get-Content $_.FullName) -Replace "<WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>","<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>" | Set-Content -Path $_.FullName
|
||||
(Get-Content $_.FullName) -Replace "<PlatformToolset>v\d{3}</PlatformToolset>","<PlatformToolset>v143</PlatformToolset>" | Set-Content -Path $_.FullName
|
||||
(Get-Content $_.FullName) -Replace "<WindowsTargetPlatformVersion>[\d\.]+</WindowsTargetPlatformVersion>",'<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>' | Set-Content -Path $_.FullName
|
||||
}
|
||||
|
||||
# Not using matrix here because it would inflate job count too much. Check out and setup is done for every job and that makes build times way too long.
|
||||
- name: Build example_null (extra warnings, mingw 64-bit)
|
||||
run: mingw32-make -C examples/example_null WITH_EXTRA_WARNINGS=1
|
||||
|
||||
- name: Build example_null (mingw 64-bit, as DLL)
|
||||
shell: bash
|
||||
run: |
|
||||
echo '#define IMGUI_API __declspec(dllexport)' > example_single_file.cpp
|
||||
echo '#define IMGUI_IMPLEMENTATION' >> example_single_file.cpp
|
||||
echo '#include "misc/single_file/imgui_single_file.h"' >> example_single_file.cpp
|
||||
g++ -I. -Wall -Wformat -shared -o libimgui.dll -Wl,--out-implib,libimgui.a example_single_file.cpp -limm32
|
||||
g++ -I. -Wall -Wformat -DIMGUI_API='__declspec(dllimport)' -DIMGUI_IMPL_API= -o example_null.exe examples/example_null/main.cpp -L. -limgui
|
||||
rm -f example_null.exe libimgui.* example_single_file.*
|
||||
|
||||
- name: Build example_null (extra warnings, msvc 64-bit)
|
||||
shell: cmd
|
||||
run: |
|
||||
@@ -88,20 +109,19 @@ jobs:
|
||||
run: |
|
||||
call "%VS_PATH%\VC\Auxiliary\Build\vcvars64.bat"
|
||||
|
||||
echo #ifdef _EXPORT > example_single_file.cpp
|
||||
echo # define IMGUI_API __declspec(dllexport) >> example_single_file.cpp
|
||||
echo #else >> example_single_file.cpp
|
||||
echo # define IMGUI_API __declspec(dllimport) >> example_single_file.cpp
|
||||
echo #endif >> example_single_file.cpp
|
||||
echo #define IMGUI_API __declspec(dllexport) > example_single_file.cpp
|
||||
echo #define IMGUI_IMPLEMENTATION >> example_single_file.cpp
|
||||
echo #include "misc/single_file/imgui_single_file.h" >> example_single_file.cpp
|
||||
|
||||
cl.exe /D_USRDLL /D_WINDLL /D_EXPORT /I. example_single_file.cpp /LD /FeImGui.dll /link
|
||||
cl.exe /I. ImGui.lib /Feexample_null.exe examples/example_null/main.cpp
|
||||
cl.exe /D_USRDLL /D_WINDLL /I. example_single_file.cpp /LD /FeImGui.dll /link
|
||||
cl.exe /DIMGUI_API=__declspec(dllimport) -DIMGUI_IMPL_API= /I. ImGui.lib /Feexample_null.exe examples/example_null/main.cpp
|
||||
|
||||
# Win64 examples are more frequently compilted than the Win32 examples.
|
||||
# More of the Win32 examples requires 'workflow_run' to reduce waste.
|
||||
- name: Build Win32 example_glfw_opengl2
|
||||
shell: cmd
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_opengl2/example_glfw_opengl2.vcxproj /p:Platform=Win32 /p:Configuration=Release'
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build Win32 example_glfw_opengl3
|
||||
shell: cmd
|
||||
@@ -113,98 +133,155 @@ jobs:
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_vulkan/example_glfw_vulkan.vcxproj /p:Platform=Win32 /p:Configuration=Release'
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build Win32 example_sdl_vulkan
|
||||
- name: Build Win32 example_sdl2_sdlrenderer2
|
||||
shell: cmd
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_vulkan/example_sdl_vulkan.vcxproj /p:Platform=Win32 /p:Configuration=Release'
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl2_sdlrenderer2/example_sdl2_sdlrenderer2.vcxproj /p:Platform=Win32 /p:Configuration=Release'
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build Win32 example_sdl_opengl2
|
||||
- name: Build Win32 example_sdl2_vulkan
|
||||
shell: cmd
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_opengl2/example_sdl_opengl2.vcxproj /p:Platform=Win32 /p:Configuration=Release'
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl2_vulkan/example_sdl2_vulkan.vcxproj /p:Platform=Win32 /p:Configuration=Release'
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build Win32 example_sdl_opengl3
|
||||
- name: Build Win32 example_sdl2_opengl2
|
||||
shell: cmd
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_opengl3/example_sdl_opengl3.vcxproj /p:Platform=Win32 /p:Configuration=Release'
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl2_opengl2/example_sdl2_opengl2.vcxproj /p:Platform=Win32 /p:Configuration=Release'
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build Win32 example_sdl_directx11
|
||||
- name: Build Win32 example_sdl2_opengl3
|
||||
shell: cmd
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_directx11/example_sdl_directx11.vcxproj /p:Platform=Win32 /p:Configuration=Release'
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl2_opengl3/example_sdl2_opengl3.vcxproj /p:Platform=Win32 /p:Configuration=Release'
|
||||
|
||||
- name: Build Win32 example_sdl2_directx11
|
||||
shell: cmd
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl2_directx11/example_sdl2_directx11.vcxproj /p:Platform=Win32 /p:Configuration=Release'
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build Win32 example_sdl3_opengl3
|
||||
shell: cmd
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl3_opengl3/example_sdl3_opengl3.vcxproj /p:Platform=Win32 /p:Configuration=Release'
|
||||
|
||||
- name: Build Win32 example_sdl3_sdlgpu3
|
||||
shell: cmd
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl3_sdlgpu3/example_sdl3_sdlgpu3.vcxproj /p:Platform=Win32 /p:Configuration=Release'
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build Win32 example_sdl3_sdlrenderer3
|
||||
shell: cmd
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl3_sdlrenderer3/example_sdl3_sdlrenderer3.vcxproj /p:Platform=Win32 /p:Configuration=Release'
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build Win32 example_sdl3_vulkan
|
||||
shell: cmd
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl3_vulkan/example_sdl3_vulkan.vcxproj /p:Platform=Win32 /p:Configuration=Release'
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build Win32 example_win32_directx9
|
||||
shell: cmd
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx9/example_win32_directx9.vcxproj /p:Platform=Win32 /p:Configuration=Release'
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build Win32 example_win32_directx10
|
||||
shell: cmd
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx10/example_win32_directx10.vcxproj /p:Platform=Win32 /p:Configuration=Release'
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build Win32 example_win32_directx11
|
||||
shell: cmd
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx11/example_win32_directx11.vcxproj /p:Platform=Win32 /p:Configuration=Release'
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build x64 example_glfw_opengl2
|
||||
# Windows 64-bits
|
||||
- name: Build Win64 example_glfw_opengl2
|
||||
shell: cmd
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_opengl2/example_glfw_opengl2.vcxproj /p:Platform=x64 /p:Configuration=Release'
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build x64 example_glfw_opengl3
|
||||
- name: Build Win64 example_glfw_opengl3
|
||||
shell: cmd
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_opengl3/example_glfw_opengl3.vcxproj /p:Platform=x64 /p:Configuration=Release'
|
||||
|
||||
- name: Build x64 example_glfw_vulkan
|
||||
- name: Build Win64 example_glfw_vulkan
|
||||
shell: cmd
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_vulkan/example_glfw_vulkan.vcxproj /p:Platform=x64 /p:Configuration=Release'
|
||||
|
||||
- name: Build x64 example_sdl_vulkan
|
||||
- name: Build Win64 example_sdl2_sdlrenderer2
|
||||
shell: cmd
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_vulkan/example_sdl_vulkan.vcxproj /p:Platform=x64 /p:Configuration=Release'
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl2_sdlrenderer2/example_sdl2_sdlrenderer2.vcxproj /p:Platform=x64 /p:Configuration=Release'
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build x64 example_sdl_opengl2
|
||||
- name: Build Win64 example_sdl2_vulkan
|
||||
shell: cmd
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_opengl2/example_sdl_opengl2.vcxproj /p:Platform=x64 /p:Configuration=Release'
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl2_vulkan/example_sdl2_vulkan.vcxproj /p:Platform=x64 /p:Configuration=Release'
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build x64 example_sdl_opengl3
|
||||
- name: Build Win64 example_sdl2_opengl2
|
||||
shell: cmd
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_opengl3/example_sdl_opengl3.vcxproj /p:Platform=x64 /p:Configuration=Release'
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl2_opengl2/example_sdl2_opengl2.vcxproj /p:Platform=x64 /p:Configuration=Release'
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build x64 example_sdl_directx11
|
||||
- name: Build Win64 example_sdl2_opengl3
|
||||
shell: cmd
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_directx11/example_sdl_directx11.vcxproj /p:Platform=x64 /p:Configuration=Release'
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl2_opengl3/example_sdl2_opengl3.vcxproj /p:Platform=x64 /p:Configuration=Release'
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build x64 example_win32_directx9
|
||||
- name: Build Win64 example_sdl2_directx11
|
||||
shell: cmd
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl2_directx11/example_sdl2_directx11.vcxproj /p:Platform=x64 /p:Configuration=Release'
|
||||
|
||||
- name: Build Win64 example_sdl3_opengl3
|
||||
shell: cmd
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl3_opengl3/example_sdl3_opengl3.vcxproj /p:Platform=x64 /p:Configuration=Release'
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build Win64 example_sdl3_sdlgpu3
|
||||
shell: cmd
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl3_sdlgpu3/example_sdl3_sdlgpu3.vcxproj /p:Platform=x64 /p:Configuration=Release'
|
||||
|
||||
- name: Build Win64 example_sdl3_sdlrenderer3
|
||||
shell: cmd
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl3_sdlrenderer3/example_sdl3_sdlrenderer3.vcxproj /p:Platform=x64 /p:Configuration=Release'
|
||||
|
||||
- name: Build Win64 example_sdl3_vulkan
|
||||
shell: cmd
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl3_vulkan/example_sdl3_vulkan.vcxproj /p:Platform=x64 /p:Configuration=Release'
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build Win64 example_win32_directx9
|
||||
shell: cmd
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx9/example_win32_directx9.vcxproj /p:Platform=x64 /p:Configuration=Release'
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build x64 example_win32_directx10
|
||||
- name: Build Win64 example_win32_directx10
|
||||
shell: cmd
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx10/example_win32_directx10.vcxproj /p:Platform=x64 /p:Configuration=Release'
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build x64 example_win32_directx11
|
||||
- name: Build Win64 example_win32_directx11
|
||||
shell: cmd
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx11/example_win32_directx11.vcxproj /p:Platform=x64 /p:Configuration=Release'
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build x64 example_win32_directx12
|
||||
- name: Build Win64 example_win32_directx12
|
||||
shell: cmd
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx12/example_win32_directx12.vcxproj /p:Platform=x64 /p:Configuration=Release'
|
||||
|
||||
Linux:
|
||||
runs-on: ubuntu-20.04
|
||||
Build-Linux:
|
||||
runs-on: ubuntu-latest
|
||||
name: Build - Linux
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ${{ github.workspace }}/imgui
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
path: ${{ github.workspace }}/imgui
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libglfw3-dev libsdl2-dev gcc-multilib g++-multilib libfreetype6-dev
|
||||
sudo apt-get install -y libglfw3-dev libsdl2-dev gcc-multilib g++-multilib libfreetype6-dev libvulkan-dev
|
||||
|
||||
- name: Build example_null (extra warnings, gcc 32-bit)
|
||||
run: |
|
||||
@@ -226,6 +303,18 @@ jobs:
|
||||
make -C examples/example_null clean
|
||||
CXXFLAGS="$CXXFLAGS -m64 -Werror" CXX=clang++ make -C examples/example_null WITH_EXTRA_WARNINGS=1
|
||||
|
||||
- name: Build example_null (extra warnings, empty IM_ASSERT)
|
||||
run: |
|
||||
cat > example_single_file.cpp <<'EOF'
|
||||
|
||||
#define IM_ASSERT(x)
|
||||
#define IMGUI_IMPLEMENTATION
|
||||
#include "misc/single_file/imgui_single_file.h"
|
||||
#include "examples/example_null/main.cpp"
|
||||
|
||||
EOF
|
||||
g++ -I. -std=c++11 -Wall -Wformat -Wextra -Werror -Wno-zero-as-null-pointer-constant -Wno-double-promotion -Wno-variadic-macros -Wno-empty-body -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_null (freetype)
|
||||
run: |
|
||||
make -C examples/example_null clean
|
||||
@@ -240,7 +329,7 @@ jobs:
|
||||
#include "examples/example_null/main.cpp"
|
||||
|
||||
EOF
|
||||
g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_null (with ImWchar32)
|
||||
run: |
|
||||
@@ -252,9 +341,9 @@ jobs:
|
||||
#include "examples/example_null/main.cpp"
|
||||
|
||||
EOF
|
||||
g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_null (with large ImDrawIdx + pointer ImTextureID)
|
||||
- name: Build example_null (with large ImDrawIdx + custom ImTextureID)
|
||||
run: |
|
||||
cat > example_single_file.cpp <<'EOF'
|
||||
|
||||
@@ -265,7 +354,22 @@ jobs:
|
||||
#include "examples/example_null/main.cpp"
|
||||
|
||||
EOF
|
||||
g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
|
||||
cat > example_single_file.cpp <<'EOF'
|
||||
|
||||
// Test build ImTextureID defined as a struct
|
||||
struct SomeType { int a = 0; int b = 0; };
|
||||
#define ImTextureID SomeType
|
||||
#define ImTextureID_Invalid SomeType()
|
||||
inline bool operator==(const SomeType& lhs, const SomeType& rhs) { return lhs.a == rhs.a && lhs.b == rhs.b; }
|
||||
inline bool operator!=(const SomeType& lhs, const SomeType& rhs) { return lhs.a != rhs.a || lhs.b != rhs.b; }
|
||||
#define IMGUI_IMPLEMENTATION
|
||||
#include "misc/single_file/imgui_single_file.h"
|
||||
#include "examples/example_null/main.cpp"
|
||||
|
||||
EOF
|
||||
g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_null (with IMGUI_DISABLE_OBSOLETE_FUNCTIONS)
|
||||
run: |
|
||||
@@ -277,20 +381,44 @@ jobs:
|
||||
#include "examples/example_null/main.cpp"
|
||||
|
||||
EOF
|
||||
g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_null (with IMGUI_DISABLE_DEMO_WINDOWS and IMGUI_DISABLE_METRICS_WINDOW)
|
||||
- name: Build example_null (with IMGUI_DISABLE_OBSOLETE_KEYIO)
|
||||
run: |
|
||||
cat > example_single_file.cpp <<'EOF'
|
||||
|
||||
#define IMGUI_DISABLE_DEMO_WINDOWS
|
||||
#define IMGUI_DISABLE_METRICS_WINDOW
|
||||
#define IMGUI_DISABLE_OBSOLETE_KEYIO
|
||||
#define IMGUI_IMPLEMENTATION
|
||||
#include "misc/single_file/imgui_single_file.h"
|
||||
#include "examples/example_null/main.cpp"
|
||||
|
||||
EOF
|
||||
g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_null (with C++20)
|
||||
run: |
|
||||
cat > example_single_file.cpp <<'EOF'
|
||||
|
||||
#define IMGUI_DISABLE_OBSOLETE_KEYIO
|
||||
#define IMGUI_IMPLEMENTATION
|
||||
#include "misc/single_file/imgui_single_file.h"
|
||||
#include "examples/example_null/main.cpp"
|
||||
|
||||
EOF
|
||||
g++ -I. -std=c++20 -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_null (with IMGUI_DISABLE_DEMO_WINDOWS and IMGUI_DISABLE_DEBUG_TOOLS)
|
||||
run: |
|
||||
cat > example_single_file.cpp <<'EOF'
|
||||
|
||||
#define IMGUI_DISABLE_DEMO_WINDOWS
|
||||
#define IMGUI_DISABLE_DEBUG_TOOLS
|
||||
#define IMGUI_IMPLEMENTATION
|
||||
#include "misc/single_file/imgui_single_file.h"
|
||||
#include "examples/example_null/main.cpp"
|
||||
|
||||
EOF
|
||||
g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_null (with IMGUI_DISABLE_FILE_FUNCTIONS)
|
||||
run: |
|
||||
@@ -302,7 +430,7 @@ jobs:
|
||||
#include "examples/example_null/main.cpp"
|
||||
|
||||
EOF
|
||||
g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_null (with IMGUI_USE_BGRA_PACKED_COLOR)
|
||||
run: |
|
||||
@@ -314,7 +442,7 @@ jobs:
|
||||
#include "examples/example_null/main.cpp"
|
||||
|
||||
EOF
|
||||
g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_null (with IM_VEC2_CLASS_EXTRA and IM_VEC4_CLASS_EXTRA)
|
||||
run: |
|
||||
@@ -334,7 +462,19 @@ jobs:
|
||||
#include "examples/example_null/main.cpp"
|
||||
|
||||
EOF
|
||||
g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_null (C++26, Clang)
|
||||
run: |
|
||||
cat > example_single_file.cpp <<'EOF'
|
||||
|
||||
#define IMGUI_IMPLEMENTATION
|
||||
#define IMGUI_DISABLE_DEMO_WINDOWS
|
||||
#include "misc/single_file/imgui_single_file.h"
|
||||
#include "examples/example_null/main.cpp"
|
||||
|
||||
EOF
|
||||
clang++ -I. -std=c++26 -Wall -Wformat -fno-exceptions -fno-threadsafe-statics -lc -lm -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_null (without c++ runtime, Clang)
|
||||
run: |
|
||||
@@ -346,7 +486,7 @@ jobs:
|
||||
#include "examples/example_null/main.cpp"
|
||||
|
||||
EOF
|
||||
clang++ -I. -Wall -Wformat -nodefaultlibs -fno-rtti -fno-exceptions -fno-threadsafe-statics -lc -lm -o example_single_file example_single_file.cpp
|
||||
clang++ -I. -std=c++11 -Wall -Wformat -nodefaultlibs -fno-rtti -fno-exceptions -fno-threadsafe-statics -lc -lm -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_glfw_opengl2
|
||||
run: make -C examples/example_glfw_opengl2
|
||||
@@ -355,26 +495,37 @@ jobs:
|
||||
run: make -C examples/example_glfw_opengl3
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build example_sdl_opengl2
|
||||
run: make -C examples/example_sdl_opengl2
|
||||
- name: Build example_sdl2_opengl2
|
||||
run: make -C examples/example_sdl2_opengl2
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build example_sdl_opengl3
|
||||
run: make -C examples/example_sdl_opengl3
|
||||
- name: Build example_sdl2_opengl3
|
||||
run: make -C examples/example_sdl2_opengl3
|
||||
|
||||
MacOS:
|
||||
- name: Build with IMGUI_IMPL_VULKAN_NO_PROTOTYPES
|
||||
run: g++ -c -I. -std=c++11 -DIMGUI_IMPL_VULKAN_NO_PROTOTYPES=1 backends/imgui_impl_vulkan.cpp
|
||||
|
||||
Build-MacOS:
|
||||
runs-on: macos-latest
|
||||
name: Build - MacOS
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ${{ github.workspace }}/imgui
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
path: ${{ github.workspace }}/imgui
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
brew install glfw3 sdl2
|
||||
brew install glfw3 sdl2 sdl3
|
||||
|
||||
- name: Build example_null (extra warnings, clang 64-bit)
|
||||
run: make -C examples/example_null WITH_EXTRA_WARNINGS=1
|
||||
|
||||
- name: Build example_null (single file build)
|
||||
- name: Build macOS example_null (single file build)
|
||||
run: |
|
||||
cat > example_single_file.cpp <<'EOF'
|
||||
|
||||
@@ -383,9 +534,9 @@ jobs:
|
||||
#include "examples/example_null/main.cpp"
|
||||
|
||||
EOF
|
||||
clang++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
clang++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_null (without c++ runtime)
|
||||
- name: Build macOS example_null (single file build, c++20)
|
||||
run: |
|
||||
cat > example_single_file.cpp <<'EOF'
|
||||
|
||||
@@ -394,48 +545,70 @@ jobs:
|
||||
#include "examples/example_null/main.cpp"
|
||||
|
||||
EOF
|
||||
clang++ -I. -Wall -Wformat -nodefaultlibs -fno-rtti -fno-exceptions -fno-threadsafe-statics -lc -lm -o example_single_file example_single_file.cpp
|
||||
clang++ -I. -std=c++20 -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_glfw_opengl2
|
||||
- name: Build macOS example_null (without c++ runtime)
|
||||
run: |
|
||||
cat > example_single_file.cpp <<'EOF'
|
||||
|
||||
#define IMGUI_IMPLEMENTATION
|
||||
#include "misc/single_file/imgui_single_file.h"
|
||||
#include "examples/example_null/main.cpp"
|
||||
|
||||
EOF
|
||||
clang++ -I. -std=c++11 -Wall -Wformat -nodefaultlibs -fno-rtti -fno-exceptions -fno-threadsafe-statics -lc -lm -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build macOS example_glfw_opengl2
|
||||
run: make -C examples/example_glfw_opengl2
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build example_glfw_opengl3
|
||||
- name: Build macOS example_glfw_opengl3
|
||||
run: make -C examples/example_glfw_opengl3
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build example_glfw_metal
|
||||
- name: Build macOS example_glfw_metal
|
||||
run: make -C examples/example_glfw_metal
|
||||
|
||||
- name: Build example_sdl_metal
|
||||
run: make -C examples/example_sdl_metal
|
||||
- name: Build macOS example_sdl2_metal
|
||||
run: make -C examples/example_sdl2_metal
|
||||
|
||||
- name: Build example_sdl_opengl2
|
||||
run: make -C examples/example_sdl_opengl2
|
||||
- name: Build macOS example_sdl2_opengl2
|
||||
run: make -C examples/example_sdl2_opengl2
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build example_sdl_opengl3
|
||||
run: make -C examples/example_sdl_opengl3
|
||||
- name: Build macOS example_sdl2_opengl3
|
||||
run: make -C examples/example_sdl2_opengl3
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build example_apple_metal
|
||||
- name: Build macOS example_sdl3_opengl3
|
||||
run: make -C examples/example_sdl3_opengl3
|
||||
|
||||
- name: Build macOS example_apple_metal
|
||||
run: xcodebuild -project examples/example_apple_metal/example_apple_metal.xcodeproj -target example_apple_metal_macos
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build example_apple_opengl2
|
||||
- name: Build macOS example_apple_opengl2
|
||||
run: xcodebuild -project examples/example_apple_opengl2/example_apple_opengl2.xcodeproj -target example_osx_opengl2
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
Build-iOS:
|
||||
runs-on: macos-14
|
||||
name: Build - iOS
|
||||
|
||||
iOS:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Build example_apple_metal
|
||||
run: |
|
||||
# Code signing is required, but we disable it because it is irrelevant for CI builds.
|
||||
xcodebuild -project examples/example_apple_metal/example_apple_metal.xcodeproj -target example_apple_metal_ios CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO
|
||||
|
||||
Emscripten:
|
||||
runs-on: ubuntu-18.04
|
||||
Build-Emscripten:
|
||||
runs-on: ubuntu-latest
|
||||
name: Build - Emscripten
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
@@ -444,58 +617,177 @@ jobs:
|
||||
emsdk-master/emsdk update
|
||||
emsdk-master/emsdk install latest
|
||||
emsdk-master/emsdk activate latest
|
||||
sudo apt-get install build-essential
|
||||
|
||||
- name: Build example_emscripten_opengl3
|
||||
- name: Build example_sdl2_opengl3 with Emscripten
|
||||
run: |
|
||||
pushd emsdk-master
|
||||
source ./emsdk_env.sh
|
||||
popd
|
||||
make -C examples/example_emscripten_opengl3
|
||||
make -C examples/example_sdl2_opengl3 -f Makefile.emscripten
|
||||
|
||||
- name: Build example_emscripten_wgpu
|
||||
# This build compiles example_glfw_wgpu using Makefile.emscripten and Emscripten GLFW built-in implementation (-sUSE_GLFW=3)
|
||||
# This ensures 2 things: the make build works, and the GLFW built-in implementation is tested
|
||||
- name: Build example_glfw_wgpu with Emscripten/Makefile
|
||||
run: |
|
||||
pushd emsdk-master
|
||||
source ./emsdk_env.sh
|
||||
popd
|
||||
make -C examples/example_emscripten_wgpu
|
||||
make -C examples/example_glfw_wgpu -f Makefile.emscripten
|
||||
|
||||
# This build compiles example_glfw_wgpu using CMakeLists.txt and Emscripten GLFW contrib port (--use-port=contrib.glfw3)
|
||||
# This ensures 2 things: the CMake build works, and the GLFW contrib port is tested
|
||||
- name: Build example_glfw_wgpu with Emscripten/CMake
|
||||
run: |
|
||||
pushd emsdk-master
|
||||
source ./emsdk_env.sh
|
||||
popd
|
||||
emcc -v
|
||||
emcmake cmake -B build -DCMAKE_BUILD_TYPE=Release examples/example_glfw_wgpu
|
||||
cmake --build build
|
||||
|
||||
Build-Android:
|
||||
runs-on: ubuntu-latest
|
||||
name: Build - Android
|
||||
|
||||
Android:
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Build example_android_opengl3
|
||||
run: |
|
||||
cd examples/example_android_opengl3/android
|
||||
gradle assembleDebug
|
||||
gradle assembleDebug --stacktrace
|
||||
|
||||
Test-Windows:
|
||||
runs-on: windows-2025
|
||||
name: Test - Windows
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ${{ github.workspace }}/imgui
|
||||
|
||||
env:
|
||||
MSBUILD_PATH: C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\
|
||||
|
||||
Discord-CI:
|
||||
runs-on: ubuntu-18.04
|
||||
if: always()
|
||||
needs: [Windows, Linux, MacOS, iOS, Emscripten, Android]
|
||||
steps:
|
||||
- uses: dearimgui/github_discord_notifier@latest
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
path: ${{ github.workspace }}/imgui
|
||||
|
||||
- uses: actions/checkout@v6
|
||||
continue-on-error: true
|
||||
with:
|
||||
fetch-depth: 1
|
||||
repository: ocornut/imgui_test_engine
|
||||
path: ${{ github.workspace }}/imgui_test_engine
|
||||
submodules: true
|
||||
|
||||
- name: Fix Tests Projects
|
||||
shell: powershell
|
||||
working-directory: ${{ github.workspace }}/imgui_test_engine
|
||||
run: |
|
||||
# WARNING: This will need updating if toolset/sdk change in project files!
|
||||
gci -recurse -filter "*.vcxproj" | ForEach-Object {
|
||||
# Fix SDK and toolset for most samples.
|
||||
(Get-Content $_.FullName) -Replace "<PlatformToolset>v110</PlatformToolset>","<PlatformToolset>v142</PlatformToolset>" | Set-Content -Path $_.FullName
|
||||
(Get-Content $_.FullName) -Replace "<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>","<WindowsTargetPlatformVersion>10.0.20348.0</WindowsTargetPlatformVersion>" | Set-Content -Path $_.FullName
|
||||
# Fix SDK and toolset for samples that require newer SDK/toolset. At the moment it is only dx12.
|
||||
(Get-Content $_.FullName) -Replace "<PlatformToolset>v140</PlatformToolset>","<PlatformToolset>v142</PlatformToolset>" | Set-Content -Path $_.FullName
|
||||
(Get-Content $_.FullName) -Replace "<WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>","<WindowsTargetPlatformVersion>10.0.20348.0</WindowsTargetPlatformVersion>" | Set-Content -Path $_.FullName
|
||||
}
|
||||
|
||||
- name: Build Tests
|
||||
shell: cmd
|
||||
working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" imgui_test_suite.vcxproj /p:Platform=x64 /p:Configuration=Release /p:ClFlags=/WX -maxcpucount:%NUMBER_OF_PROCESSORS%'
|
||||
|
||||
- name: Run Tests
|
||||
working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
|
||||
run: Release/imgui_test_suite.exe -nogui -nopause -v2 -ve4 tests
|
||||
|
||||
- name: Check for Docking
|
||||
id: check_docking
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}/imgui
|
||||
run: echo "has_dock=$(grep -q "#define IMGUI_HAS_DOCK" imgui.h && echo true || echo false)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Run Viewport Tests
|
||||
if: steps.check_docking.outputs.has_dock == 'true'
|
||||
working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
|
||||
run: Release/imgui_test_suite.exe -nogui -nopause -v2 -ve4 -viewport-mock viewport
|
||||
|
||||
Test-Linux:
|
||||
runs-on: ubuntu-latest
|
||||
name: Test - Linux
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ${{ github.workspace }}/imgui
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
discord-webhook: ${{ secrets.DISCORD_CI_WEBHOOK }}
|
||||
github-token: ${{ github.token }}
|
||||
action-task: discord-jobs
|
||||
discord-filter: "'{{ github.branch }}'.match(/master|docking/g) != null && '{{ run.conclusion }}' != '{{ last_run.conclusion }}'"
|
||||
discord-username: GitHub Actions
|
||||
discord-job-new-failure-message: ''
|
||||
discord-job-fixed-failure-message: ''
|
||||
discord-job-new-failure-embed: |
|
||||
{
|
||||
"title": "`{{ job.name }}` job is failing on `{{ github.branch }}`!",
|
||||
"description": "Commit [{{ github.context.payload.head_commit.title }}]({{ github.context.payload.head_commit.url }}) pushed to [{{ github.branch }}]({{ github.branch_url }}) broke [{{ job.name }}]({{ job.url }}) build job.\nFailing steps: {{ failing_steps }}",
|
||||
"url": "{{ job.url }}",
|
||||
"color": "0xFF0000",
|
||||
"timestamp": "{{ run.updated_at }}"
|
||||
}
|
||||
discord-job-fixed-failure-embed: |
|
||||
{
|
||||
"title": "`{{ github.branch }}` branch is no longer failing!",
|
||||
"description": "Build failures were fixed on [{{ github.branch }}]({{ github.branch_url }}) branch.",
|
||||
"color": "0x00FF00",
|
||||
"url": "{{ github.context.payload.head_commit.url }}",
|
||||
"timestamp": "{{ run.completed_at }}"
|
||||
}
|
||||
path: ${{ github.workspace }}/imgui
|
||||
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 1
|
||||
repository: ocornut/imgui_test_engine
|
||||
path: ${{ github.workspace }}/imgui_test_engine
|
||||
submodules: true
|
||||
|
||||
- name: Build Tests
|
||||
working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
|
||||
run: make -j$(nproc)
|
||||
|
||||
- name: Run Tests
|
||||
working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
|
||||
run: ./imgui_test_suite -nogui -nopause -v2 -ve4 tests
|
||||
|
||||
- name: Check for Docking
|
||||
id: check_docking
|
||||
working-directory: ${{ github.workspace }}/imgui
|
||||
run: echo "has_dock=$(grep -q "#define IMGUI_HAS_DOCK" imgui.h && echo true || echo false)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Run Viewport Tests
|
||||
if: steps.check_docking.outputs.has_dock == 'true'
|
||||
working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
|
||||
run: ./imgui_test_suite -nogui -nopause -v2 -ve4 -viewport-mock viewport
|
||||
|
||||
# Test-MacOS:
|
||||
# runs-on: macos-latest
|
||||
# name: Test - MacOS
|
||||
#
|
||||
# defaults:
|
||||
# run:
|
||||
# working-directory: ${{ github.workspace }}/imgui
|
||||
#
|
||||
# steps:
|
||||
# - uses: actions/checkout@v6
|
||||
# with:
|
||||
# path: ${{ github.workspace }}/imgui
|
||||
#
|
||||
# - uses: actions/checkout@v6
|
||||
# with:
|
||||
# fetch-depth: 1
|
||||
# repository: ocornut/imgui_test_engine
|
||||
# path: ${{ github.workspace }}/imgui_test_engine
|
||||
# submodules: true
|
||||
#
|
||||
# - name: Build Tests
|
||||
# working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
|
||||
# run: make -j$(nproc)
|
||||
#
|
||||
# - name: Run Tests
|
||||
# working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
|
||||
# run: ./imgui_test_suite -nogui -nopause -v2 -ve4 tests
|
||||
#
|
||||
# - name: Check for Docking
|
||||
# id: check_docking
|
||||
# working-directory: ${{ github.workspace }}/imgui
|
||||
# run: echo "has_dock=$(grep -q "#define IMGUI_HAS_DOCK" imgui.h && echo true || echo false)" >> $GITHUB_OUTPUT
|
||||
#
|
||||
# - name: Run Viewport Tests
|
||||
# if: steps.check_docking.outputs.has_dock == 'true'
|
||||
# working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
|
||||
# run: ./imgui_test_suite -nogui -nopause -v2 -ve4 -viewport-mock viewport
|
||||
|
||||
38
.github/workflows/build_windows_vulkan_libs.ps1
vendored
Normal file
38
.github/workflows/build_windows_vulkan_libs.ps1
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
# This is current meant to be run manually, occasionally:
|
||||
# - Run then zip the contents of vulkanArtifact/ into e.g. vulkan_windows_libs_1.4.326
|
||||
# - Upload as an attachment to https://github.com/ocornut/imgui/pull/8925 then change filename in build.yml
|
||||
# - There is a build_windows_vulkan_libs.yml in commit history that we removed thinking this is run so rarely we don't need to pollute CI UI with it.
|
||||
|
||||
# Set default vulkan version if none provided
|
||||
if (-not $env:VULKAN_TAG) { $env:VULKAN_TAG = "1.4.326" }
|
||||
|
||||
# Create output folder
|
||||
mkdir vulkanArtifact
|
||||
|
||||
# Download Vulkan Headers
|
||||
|
||||
Invoke-WebRequest -Uri "https://github.com/KhronosGroup/Vulkan-Headers/archive/refs/tags/v$($env:VULKAN_TAG).zip" -OutFile Vulkan-Headers-$($env:VULKAN_TAG).zip
|
||||
Expand-Archive -Path Vulkan-Headers-$($env:VULKAN_TAG).zip
|
||||
|
||||
# Copy Vulkan Headers to artifact folder
|
||||
|
||||
cp -R Vulkan-Headers-$($env:VULKAN_TAG)\Vulkan-Headers-$($env:VULKAN_TAG)\include vulkanArtifact\Include
|
||||
|
||||
# Download Vulkan Loader
|
||||
|
||||
Invoke-WebRequest -Uri "https://github.com/KhronosGroup/Vulkan-Loader/archive/refs/tags/v$($env:VULKAN_TAG).zip" -OutFile Vulkan-Loader-$($env:VULKAN_TAG).zip
|
||||
Expand-Archive -Path Vulkan-Loader-$($env:VULKAN_TAG).zip
|
||||
|
||||
# Build Vulkan Loader x64
|
||||
|
||||
cmake -S Vulkan-Loader-$($env:VULKAN_TAG)\Vulkan-Loader-$($env:VULKAN_TAG) -B VulkanLoader-build64 -D UPDATE_DEPS=On -A x64
|
||||
cmake --build VulkanLoader-build64
|
||||
mkdir vulkanArtifact\Lib
|
||||
copy VulkanLoader-build64\loader\Debug\vulkan-1.lib vulkanArtifact\Lib
|
||||
|
||||
# Build Vulkan Loader win32
|
||||
|
||||
cmake -S Vulkan-Loader-$($env:VULKAN_TAG)\Vulkan-Loader-$($env:VULKAN_TAG) -B VulkanLoader-build32 -D UPDATE_DEPS=On -A Win32
|
||||
cmake --build VulkanLoader-build32
|
||||
mkdir vulkanArtifact\Lib32
|
||||
copy VulkanLoader-build32\loader\Debug\vulkan-1.lib vulkanArtifact\Lib32
|
||||
12
.github/workflows/manual.yml
vendored
Normal file
12
.github/workflows/manual.yml
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#
|
||||
# This is a dummy workflow used to trigger full builds manually.
|
||||
#
|
||||
name: manual
|
||||
|
||||
on: workflow_dispatch
|
||||
|
||||
jobs:
|
||||
manual:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: exit 0
|
||||
37
.github/workflows/static-analysis.yml
vendored
37
.github/workflows/static-analysis.yml
vendored
@@ -10,9 +10,9 @@ on:
|
||||
|
||||
jobs:
|
||||
PVS-Studio:
|
||||
runs-on: ubuntu-18.04
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
@@ -43,35 +43,4 @@ jobs:
|
||||
cd examples/example_null
|
||||
pvs-studio-analyzer trace -- make WITH_EXTRA_WARNINGS=1
|
||||
pvs-studio-analyzer analyze -e ../../imstb_rectpack.h -e ../../imstb_textedit.h -e ../../imstb_truetype.h -l ../../pvs-studio.lic -o pvs-studio.log
|
||||
plog-converter -a 'GA:1,2;OP:1' -t errorfile -w pvs-studio.log
|
||||
|
||||
Discord-CI:
|
||||
runs-on: ubuntu-18.04
|
||||
needs: [PVS-Studio]
|
||||
if: always()
|
||||
steps:
|
||||
- uses: dearimgui/github_discord_notifier@latest
|
||||
with:
|
||||
discord-webhook: ${{ secrets.DISCORD_CI_WEBHOOK }}
|
||||
github-token: ${{ github.token }}
|
||||
action-task: discord-jobs
|
||||
discord-filter: "'{{ github.branch }}'.match(/master|docking/g) != null && '{{ run.conclusion }}' != '{{ last_run.conclusion }}'"
|
||||
discord-username: GitHub Actions
|
||||
discord-job-new-failure-message: ''
|
||||
discord-job-fixed-failure-message: ''
|
||||
discord-job-new-failure-embed: |
|
||||
{
|
||||
"title": "`{{ job.name }}` job is failing on `{{ github.branch }}`!",
|
||||
"description": "Commit [{{ github.context.payload.head_commit.title }}]({{ github.context.payload.head_commit.url }}) pushed to [{{ github.branch }}]({{ github.branch_url }}) broke static analysis [{{ job.name }}]({{ job.url }}) job.\nFailing steps: {{ failing_steps }}",
|
||||
"url": "{{ job.url }}",
|
||||
"color": "0xFF0000",
|
||||
"timestamp": "{{ run.updated_at }}"
|
||||
}
|
||||
discord-job-fixed-failure-embed: |
|
||||
{
|
||||
"title": "`{{ github.branch }}` branch is no longer failing!",
|
||||
"description": "Static analysis failures were fixed on [{{ github.branch }}]({{ github.branch_url }}) branch.",
|
||||
"color": "0x00FF00",
|
||||
"url": "{{ github.context.payload.head_commit.url }}",
|
||||
"timestamp": "{{ run.completed_at }}"
|
||||
}
|
||||
plog-converter -a 'GA:1,2;OP:1' -d V1071 -t errorfile -w pvs-studio.log
|
||||
|
||||
43
.gitignore
vendored
43
.gitignore
vendored
@@ -1,17 +1,20 @@
|
||||
## OSX artifacts
|
||||
## Misc artifacts
|
||||
.DS_Store
|
||||
.claude
|
||||
.vscode
|
||||
|
||||
## Dear ImGui artifacts
|
||||
imgui.ini
|
||||
imgui*.ini
|
||||
|
||||
## General build artifacts
|
||||
*.o
|
||||
*.obj
|
||||
*.exe
|
||||
examples/build/*
|
||||
examples/*/Debug/*
|
||||
examples/*/Release/*
|
||||
examples/*/x64/*
|
||||
examples/*.tmp
|
||||
|
||||
## Visual Studio artifacts
|
||||
.vs
|
||||
@@ -26,28 +29,50 @@ ipch
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
## Commonly used CMake directories
|
||||
/build*/
|
||||
## Getting files created in JSON/Schemas/Catalog/ from a VS2022 update
|
||||
JSON/
|
||||
|
||||
## Xcode artifacts
|
||||
## Commonly used CMake directories & CMake CPM cache
|
||||
build*/
|
||||
.cache
|
||||
|
||||
## Xcode & macOS artifacts
|
||||
project.xcworkspace
|
||||
xcuserdata
|
||||
examples/*/*.dSYM
|
||||
|
||||
## Emscripten artifacts
|
||||
examples/*.o.tmp
|
||||
examples/*.out.js
|
||||
examples/*.out.wasm
|
||||
examples/example_emscripten_opengl3/web/*
|
||||
examples/example_emscripten_wgpu/web/*
|
||||
examples/example_glfw_opengl3/web/*
|
||||
examples/example_glfw_wgpu/web/*
|
||||
examples/example_glfw_wgpu/external/*
|
||||
examples/example_sdl2_opengl3/web/*
|
||||
examples/example_sdl2_wgpu/web/*
|
||||
examples/example_sdl3_opengl3/web/*
|
||||
examples/example_sdl3_wgpu/web/*
|
||||
|
||||
## JetBrains IDE artifacts
|
||||
.idea
|
||||
cmake-build-*
|
||||
|
||||
## Unix executables from our example Makefiles
|
||||
examples/example_apple_metal/example_apple_metal
|
||||
examples/example_apple_opengl2/example_apple_opengl2
|
||||
examples/example_glfw_metal/example_glfw_metal
|
||||
examples/example_glfw_opengl2/example_glfw_opengl2
|
||||
examples/example_glfw_opengl3/example_glfw_opengl3
|
||||
examples/example_glfw_vulkan/example_glfw_vulkan
|
||||
examples/example_glut_opengl2/example_glut_opengl2
|
||||
examples/example_null/example_null
|
||||
examples/example_sdl_opengl2/example_sdl_opengl2
|
||||
examples/example_sdl_opengl3/example_sdl_opengl3
|
||||
examples/example_sdl2_metal/example_sdl2_metal
|
||||
examples/example_sdl2_opengl2/example_sdl2_opengl2
|
||||
examples/example_sdl2_opengl3/example_sdl2_opengl3
|
||||
examples/example_sdl2_sdlrenderer2/example_sdl2_sdlrenderer2
|
||||
examples/example_sdl2_vulkan/example_sdl2_vulkan
|
||||
examples/example_sdl3_metal/example_sdl3_metal
|
||||
examples/example_sdl3_opengl3/example_sdl3_opengl3
|
||||
examples/example_sdl3_sdlgpu3/example_sdl3_sdlgpu3
|
||||
examples/example_sdl3_sdlrenderer3/example_sdl3_sdlrenderer3
|
||||
examples/example_sdl3_vulkan/example_sdl3_vulkan
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014-2021 Omar Cornut
|
||||
Copyright (c) 2014-2026 Omar Cornut
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -2,19 +2,47 @@
|
||||
// (Info: Allegro 5 is a cross-platform general purpose library for handling windows, inputs, graphics, etc.)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'ALLEGRO_BITMAP*' as ImTextureID. Read the FAQ about ImTextureID!
|
||||
// [X] Platform: Clipboard support (from Allegro 5.1.12)
|
||||
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
// Issues:
|
||||
// [X] Renderer: User texture binding. Use 'ALLEGRO_BITMAP*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy ALLEGRO_KEY_* values are obsolete since 1.87 and not supported since 1.91.5]
|
||||
// [X] Platform: Clipboard support (from Allegro 5.1.12).
|
||||
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
// Missing features or Issues:
|
||||
// [ ] Renderer: The renderer is suboptimal as we need to unindex our buffers and convert vertices manually.
|
||||
// [ ] Renderer: Missing support for DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest callbacks: Allegro5 cannot enable/disable LINEAR bitmap flags after creation.
|
||||
// [ ] Platform: Missing gamepad support.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState (others cannot be supported by Allegro5). (#9378)
|
||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() and platform_io.ClearPlatformHandlers() on shutdown.
|
||||
// 2025-08-12: Inputs: fixed missing support for ImGuiKey_PrintScreen under Windows, as raw Allegro 5 does not receive it.
|
||||
// 2025-08-12: Added ImGui_ImplAllegro5_SetDisplay() function to change current ALLEGRO_DISPLAY, as Allegro applications often need to do that.
|
||||
// 2025-07-07: Fixed texture update broken on some platforms where ALLEGRO_LOCK_WRITEONLY needed all texels to be rewritten.
|
||||
// 2025-06-11: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplSDLGPU3_CreateFontsTexture() and ImGui_ImplSDLGPU3_DestroyFontsTexture().
|
||||
// 2025-02-18: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support.
|
||||
// 2025-01-06: Avoid calling al_set_mouse_cursor() repeatedly since it appears to leak on on X11 (#8256).
|
||||
// 2024-08-22: moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO:
|
||||
// - io.GetClipboardTextFn -> platform_io.Platform_GetClipboardTextFn
|
||||
// - io.SetClipboardTextFn -> platform_io.Platform_SetClipboardTextFn
|
||||
// 2022-11-30: Renderer: Restoring using al_draw_indexed_prim() when Allegro version is >= 5.2.5.
|
||||
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
|
||||
// 2022-09-26: Inputs: Renamed ImGuiKey_ModXXX introduced in 1.87 to ImGuiMod_XXX (old names still supported).
|
||||
// 2022-01-26: Inputs: replaced short-lived io.AddKeyModsEvent() (added two weeks ago) with io.AddKeyEvent() using ImGuiKey_ModXXX flags. Sorry for the confusion.
|
||||
// 2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEvent(), io.AddMouseWheelEvent() API (1.87+).
|
||||
// 2022-01-17: Inputs: always calling io.AddKeyModsEvent() next and before key event (not in NewFrame) to fix input queue with very low framerates.
|
||||
// 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range.
|
||||
// 2021-12-08: Renderer: Fixed mishandling of the ImDrawCmd::IdxOffset field! This is an old bug but it never had an effect until some internal rendering changes in 1.86.
|
||||
// 2021-08-17: Calling io.AddFocusEvent() on ALLEGRO_EVENT_DISPLAY_SWITCH_OUT/ALLEGRO_EVENT_DISPLAY_SWITCH_IN events.
|
||||
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
|
||||
// 2021-05-19: Renderer: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
|
||||
// 2021-02-18: Change blending equation to preserve alpha in output buffer.
|
||||
// 2020-08-10: Inputs: Fixed horizontal mouse wheel direction.
|
||||
@@ -26,6 +54,7 @@
|
||||
// 2018-11-30: Misc: Setting up io.BackendPlatformName/io.BackendRendererName so they can be displayed in the About Window.
|
||||
// 2018-06-13: Platform: Added clipboard support (from Allegro 5.1.12).
|
||||
// 2018-06-13: Renderer: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
|
||||
// 2018-06-13: Renderer: Stopped using al_draw_indexed_prim() as it is buggy in Allegro's DX9 backend.
|
||||
// 2018-06-13: Renderer: Backup/restore transform and clipping rectangle.
|
||||
// 2018-06-11: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoMouseCursorChange flag.
|
||||
// 2018-04-18: Misc: Renamed file from imgui_impl_a5.cpp to imgui_impl_allegro5.cpp.
|
||||
@@ -34,10 +63,11 @@
|
||||
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
|
||||
// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space.
|
||||
|
||||
#include "imgui.h"
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include "imgui_impl_allegro5.h"
|
||||
#include <stdint.h> // uint64_t
|
||||
#include <cstring> // memcpy
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_allegro5.h"
|
||||
|
||||
// Allegro
|
||||
#include <allegro5/allegro.h>
|
||||
@@ -45,28 +75,49 @@
|
||||
#ifdef _WIN32
|
||||
#include <allegro5/allegro_windows.h>
|
||||
#endif
|
||||
#define ALLEGRO_HAS_CLIPBOARD (ALLEGRO_VERSION_INT >= ((5 << 24) | (1 << 16) | (12 << 8))) // Clipboard only supported from Allegro 5.1.12
|
||||
#define ALLEGRO_HAS_CLIPBOARD ((ALLEGRO_VERSION_INT & ~ALLEGRO_UNSTABLE_BIT) >= ((5 << 24) | (1 << 16) | (12 << 8))) // Clipboard only supported from Allegro 5.1.12
|
||||
#define ALLEGRO_HAS_DRAW_INDEXED_PRIM ((ALLEGRO_VERSION_INT & ~ALLEGRO_UNSTABLE_BIT) >= ((5 << 24) | (2 << 16) | ( 5 << 8))) // DX9 implementation of al_draw_indexed_prim() got fixed in Allegro 5.2.5
|
||||
|
||||
// Visual Studio warnings
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (disable: 4127) // condition expression is constant
|
||||
#endif
|
||||
|
||||
// Data
|
||||
static ALLEGRO_DISPLAY* g_Display = NULL;
|
||||
static ALLEGRO_BITMAP* g_Texture = NULL;
|
||||
static double g_Time = 0.0;
|
||||
static ALLEGRO_MOUSE_CURSOR* g_MouseCursorInvisible = NULL;
|
||||
static ALLEGRO_VERTEX_DECL* g_VertexDecl = NULL;
|
||||
static char* g_ClipboardTextData = NULL;
|
||||
|
||||
struct ImDrawVertAllegro
|
||||
{
|
||||
ImVec2 pos;
|
||||
ImVec2 uv;
|
||||
ALLEGRO_COLOR col;
|
||||
ImVec2 pos;
|
||||
ImVec2 uv;
|
||||
ALLEGRO_COLOR col;
|
||||
};
|
||||
|
||||
// FIXME-OPT: Unfortunately Allegro doesn't support 32-bit packed colors so we have to convert them to 4 float as well..
|
||||
// FIXME-OPT: Consider inlining al_map_rgba()?
|
||||
// see https://github.com/liballeg/allegro5/blob/master/src/pixels.c#L554
|
||||
// and https://github.com/liballeg/allegro5/blob/master/include/allegro5/internal/aintern_pixels.h
|
||||
#define DRAW_VERT_IMGUI_TO_ALLEGRO(DST, SRC) { (DST)->pos = (SRC)->pos; (DST)->uv = (SRC)->uv; unsigned char* c = (unsigned char*)&(SRC)->col; (DST)->col = al_map_rgba(c[0], c[1], c[2], c[3]); }
|
||||
|
||||
// Allegro Data
|
||||
struct ImGui_ImplAllegro5_Data
|
||||
{
|
||||
ALLEGRO_DISPLAY* Display;
|
||||
ALLEGRO_BITMAP* Texture;
|
||||
double Time;
|
||||
ALLEGRO_MOUSE_CURSOR* MouseCursorInvisible;
|
||||
ALLEGRO_VERTEX_DECL* VertexDecl;
|
||||
char* ClipboardTextData;
|
||||
ImGuiMouseCursor LastCursor;
|
||||
|
||||
ImVector<ImDrawVertAllegro> BufVertices;
|
||||
ImVector<int> BufIndices;
|
||||
|
||||
ImGui_ImplAllegro5_Data() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
// Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts
|
||||
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
|
||||
// FIXME: multi-context support is not well tested and probably dysfunctional in this backend.
|
||||
static ImGui_ImplAllegro5_Data* ImGui_ImplAllegro5_GetBackendData() { return ImGui::GetCurrentContext() ? (ImGui_ImplAllegro5_Data*)ImGui::GetIO().BackendPlatformUserData : nullptr; }
|
||||
|
||||
static void ImGui_ImplAllegro5_SetupRenderState(ImDrawData* draw_data)
|
||||
{
|
||||
// Setup blending
|
||||
@@ -87,14 +138,26 @@ static void ImGui_ImplAllegro5_SetupRenderState(ImDrawData* draw_data)
|
||||
}
|
||||
}
|
||||
|
||||
// Render function.
|
||||
// Draw callbacks
|
||||
static void ImGui_ImplAllegro5_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
||||
|
||||
// Render function
|
||||
void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data)
|
||||
{
|
||||
// Avoid rendering when minimized
|
||||
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
|
||||
return;
|
||||
|
||||
// Catch up with texture updates. Most of the times, the list will have 1 element with an OK status, aka nothing to do.
|
||||
// (This almost always points to ImGui::GetPlatformIO().Textures[] but is part of ImDrawData to allow overriding or disabling texture updates).
|
||||
if (draw_data->Textures != nullptr)
|
||||
for (ImTextureData* tex : *draw_data->Textures)
|
||||
if (tex->Status != ImTextureStatus_OK)
|
||||
ImGui_ImplAllegro5_UpdateTexture(tex);
|
||||
|
||||
// Backup Allegro state that will be modified
|
||||
ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
ALLEGRO_TRANSFORM last_transform = *al_get_current_transform();
|
||||
ALLEGRO_TRANSFORM last_projection_transform = *al_get_current_projection_transform();
|
||||
int last_clip_x, last_clip_y, last_clip_w, last_clip_h;
|
||||
@@ -106,63 +169,73 @@ void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data)
|
||||
ImGui_ImplAllegro5_SetupRenderState(draw_data);
|
||||
|
||||
// Render command lists
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
for (const ImDrawList* draw_list : draw_data->CmdLists)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
|
||||
// Allegro's implementation of al_draw_indexed_prim() for DX9 is completely broken. Unindex our buffers ourselves.
|
||||
// FIXME-OPT: Unfortunately Allegro doesn't support 32-bit packed colors so we have to convert them to 4 float as well..
|
||||
static ImVector<ImDrawVertAllegro> vertices;
|
||||
vertices.resize(cmd_list->IdxBuffer.Size);
|
||||
for (int i = 0; i < cmd_list->IdxBuffer.Size; i++)
|
||||
ImVector<ImDrawVertAllegro>& vertices = bd->BufVertices;
|
||||
#if ALLEGRO_HAS_DRAW_INDEXED_PRIM
|
||||
vertices.resize(draw_list->VtxBuffer.Size);
|
||||
for (int i = 0; i < draw_list->VtxBuffer.Size; i++)
|
||||
{
|
||||
const ImDrawVert* src_v = &cmd_list->VtxBuffer[cmd_list->IdxBuffer[i]];
|
||||
const ImDrawVert* src_v = &draw_list->VtxBuffer[i];
|
||||
ImDrawVertAllegro* dst_v = &vertices[i];
|
||||
dst_v->pos = src_v->pos;
|
||||
dst_v->uv = src_v->uv;
|
||||
unsigned char* c = (unsigned char*)&src_v->col;
|
||||
dst_v->col = al_map_rgba(c[0], c[1], c[2], c[3]);
|
||||
DRAW_VERT_IMGUI_TO_ALLEGRO(dst_v, src_v);
|
||||
}
|
||||
|
||||
const int* indices = NULL;
|
||||
const int* indices = nullptr;
|
||||
if (sizeof(ImDrawIdx) == 2)
|
||||
{
|
||||
// FIXME-OPT: Unfortunately Allegro doesn't support 16-bit indices.. You can '#define ImDrawIdx int' in imconfig.h to request Dear ImGui to output 32-bit indices.
|
||||
// FIXME-OPT: Allegro doesn't support 16-bit indices.
|
||||
// You can '#define ImDrawIdx int' in imconfig.h to request Dear ImGui to output 32-bit indices.
|
||||
// Otherwise, we convert them from 16-bit to 32-bit at runtime here, which works perfectly but is a little wasteful.
|
||||
static ImVector<int> indices_converted;
|
||||
indices_converted.resize(cmd_list->IdxBuffer.Size);
|
||||
for (int i = 0; i < cmd_list->IdxBuffer.Size; ++i)
|
||||
indices_converted[i] = (int)cmd_list->IdxBuffer.Data[i];
|
||||
indices = indices_converted.Data;
|
||||
bd->BufIndices.resize(draw_list->IdxBuffer.Size);
|
||||
for (int i = 0; i < draw_list->IdxBuffer.Size; ++i)
|
||||
bd->BufIndices[i] = (int)draw_list->IdxBuffer.Data[i];
|
||||
indices = bd->BufIndices.Data;
|
||||
}
|
||||
else if (sizeof(ImDrawIdx) == 4)
|
||||
{
|
||||
indices = (const int*)cmd_list->IdxBuffer.Data;
|
||||
indices = (const int*)draw_list->IdxBuffer.Data;
|
||||
}
|
||||
#else
|
||||
// Allegro's implementation of al_draw_indexed_prim() for DX9 was broken until 5.2.5. Unindex buffers ourselves while converting vertex format.
|
||||
vertices.resize(draw_list->IdxBuffer.Size);
|
||||
for (int i = 0; i < draw_list->IdxBuffer.Size; i++)
|
||||
{
|
||||
const ImDrawVert* src_v = &draw_list->VtxBuffer[draw_list->IdxBuffer[i]];
|
||||
ImDrawVertAllegro* dst_v = &vertices[i];
|
||||
DRAW_VERT_IMGUI_TO_ALLEGRO(dst_v, src_v);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Render command lists
|
||||
int idx_offset = 0;
|
||||
ImVec2 clip_off = draw_data->DisplayPos;
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback)
|
||||
{
|
||||
// User callback, registered via ImDrawList::AddCallback()
|
||||
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
|
||||
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
|
||||
if (pcmd->UserCallback == ImGui_ImplAllegro5_DrawCallback_ResetRenderState)
|
||||
ImGui_ImplAllegro5_SetupRenderState(draw_data);
|
||||
else
|
||||
pcmd->UserCallback(cmd_list, pcmd);
|
||||
pcmd->UserCallback(draw_list, pcmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Draw
|
||||
// Project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y);
|
||||
ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y);
|
||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||
continue;
|
||||
|
||||
// Apply scissor/clipping rectangle, Draw
|
||||
ALLEGRO_BITMAP* texture = (ALLEGRO_BITMAP*)pcmd->GetTexID();
|
||||
al_set_clipping_rectangle(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y, pcmd->ClipRect.z - pcmd->ClipRect.x, pcmd->ClipRect.w - pcmd->ClipRect.y);
|
||||
al_draw_prim(&vertices[0], g_VertexDecl, texture, idx_offset, idx_offset + pcmd->ElemCount, ALLEGRO_PRIM_TRIANGLE_LIST);
|
||||
al_set_clipping_rectangle(clip_min.x, clip_min.y, clip_max.x - clip_min.x, clip_max.y - clip_min.y);
|
||||
#if ALLEGRO_HAS_DRAW_INDEXED_PRIM
|
||||
al_draw_indexed_prim(&vertices[0], bd->VertexDecl, texture, &indices[pcmd->IdxOffset], pcmd->ElemCount, ALLEGRO_PRIM_TRIANGLE_LIST);
|
||||
#else
|
||||
al_draw_prim(&vertices[0], bd->VertexDecl, texture, pcmd->IdxOffset, pcmd->IdxOffset + pcmd->ElemCount, ALLEGRO_PRIM_TRIANGLE_LIST);
|
||||
#endif
|
||||
}
|
||||
idx_offset += pcmd->ElemCount;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,198 +248,384 @@ void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data)
|
||||
|
||||
bool ImGui_ImplAllegro5_CreateDeviceObjects()
|
||||
{
|
||||
// Build texture atlas
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
unsigned char* pixels;
|
||||
int width, height;
|
||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
|
||||
|
||||
// Create texture
|
||||
int flags = al_get_new_bitmap_flags();
|
||||
int fmt = al_get_new_bitmap_format();
|
||||
al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP | ALLEGRO_MIN_LINEAR | ALLEGRO_MAG_LINEAR);
|
||||
al_set_new_bitmap_format(ALLEGRO_PIXEL_FORMAT_ABGR_8888_LE);
|
||||
ALLEGRO_BITMAP* img = al_create_bitmap(width, height);
|
||||
al_set_new_bitmap_flags(flags);
|
||||
al_set_new_bitmap_format(fmt);
|
||||
if (!img)
|
||||
return false;
|
||||
|
||||
ALLEGRO_LOCKED_REGION* locked_img = al_lock_bitmap(img, al_get_bitmap_format(img), ALLEGRO_LOCK_WRITEONLY);
|
||||
if (!locked_img)
|
||||
{
|
||||
al_destroy_bitmap(img);
|
||||
return false;
|
||||
}
|
||||
memcpy(locked_img->data, pixels, sizeof(int) * width * height);
|
||||
al_unlock_bitmap(img);
|
||||
|
||||
// Convert software texture to hardware texture.
|
||||
ALLEGRO_BITMAP* cloned_img = al_clone_bitmap(img);
|
||||
al_destroy_bitmap(img);
|
||||
if (!cloned_img)
|
||||
return false;
|
||||
|
||||
// Store our identifier
|
||||
io.Fonts->SetTexID((void*)cloned_img);
|
||||
g_Texture = cloned_img;
|
||||
ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData();
|
||||
|
||||
// Create an invisible mouse cursor
|
||||
// Because al_hide_mouse_cursor() seems to mess up with the actual inputs..
|
||||
ALLEGRO_BITMAP* mouse_cursor = al_create_bitmap(8, 8);
|
||||
g_MouseCursorInvisible = al_create_mouse_cursor(mouse_cursor, 0, 0);
|
||||
bd->MouseCursorInvisible = al_create_mouse_cursor(mouse_cursor, 0, 0);
|
||||
al_destroy_bitmap(mouse_cursor);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplAllegro5_UpdateTexture(ImTextureData* tex)
|
||||
{
|
||||
if (tex->Status == ImTextureStatus_WantCreate)
|
||||
{
|
||||
// Create and upload new texture to graphics system
|
||||
//IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
|
||||
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == nullptr);
|
||||
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
|
||||
|
||||
// Create texture
|
||||
// (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
|
||||
const int new_bitmap_flags = al_get_new_bitmap_flags();
|
||||
int new_bitmap_format = al_get_new_bitmap_format();
|
||||
al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP | ALLEGRO_MIN_LINEAR | ALLEGRO_MAG_LINEAR);
|
||||
al_set_new_bitmap_format(ALLEGRO_PIXEL_FORMAT_ABGR_8888_LE);
|
||||
ALLEGRO_BITMAP* cpu_bitmap = al_create_bitmap(tex->Width, tex->Height);
|
||||
IM_ASSERT(cpu_bitmap != nullptr && "Backend failed to create texture!");
|
||||
|
||||
// Upload pixels
|
||||
ALLEGRO_LOCKED_REGION* locked_region = al_lock_bitmap(cpu_bitmap, al_get_bitmap_format(cpu_bitmap), ALLEGRO_LOCK_WRITEONLY);
|
||||
IM_ASSERT(locked_region != nullptr && "Backend failed to create texture!");
|
||||
memcpy(locked_region->data, tex->GetPixels(), tex->GetSizeInBytes());
|
||||
al_unlock_bitmap(cpu_bitmap);
|
||||
|
||||
// Convert software texture to hardware texture.
|
||||
al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP);
|
||||
al_set_new_bitmap_format(ALLEGRO_PIXEL_FORMAT_ANY_32_WITH_ALPHA);
|
||||
ALLEGRO_BITMAP* gpu_bitmap = al_clone_bitmap(cpu_bitmap);
|
||||
al_destroy_bitmap(cpu_bitmap);
|
||||
IM_ASSERT(gpu_bitmap != nullptr && "Backend failed to create texture!");
|
||||
|
||||
al_set_new_bitmap_flags(new_bitmap_flags);
|
||||
al_set_new_bitmap_format(new_bitmap_format);
|
||||
|
||||
// Store identifiers
|
||||
tex->SetTexID((ImTextureID)(intptr_t)gpu_bitmap);
|
||||
tex->SetStatus(ImTextureStatus_OK);
|
||||
}
|
||||
else if (tex->Status == ImTextureStatus_WantUpdates)
|
||||
{
|
||||
// Update selected blocks. We only ever write to textures regions which have never been used before!
|
||||
// This backend choose to use tex->Updates[] but you can use tex->UpdateRect to upload a single region.
|
||||
ImTextureRect r = tex->UpdateRect; // Bounding box encompassing all individual updates
|
||||
ALLEGRO_BITMAP* gpu_bitmap = (ALLEGRO_BITMAP*)(intptr_t)tex->TexID;
|
||||
ALLEGRO_LOCKED_REGION* locked_region = al_lock_bitmap_region(gpu_bitmap, r.x, r.y, r.w, r.h, al_get_bitmap_format(gpu_bitmap), ALLEGRO_LOCK_WRITEONLY);
|
||||
IM_ASSERT(locked_region && "Backend failed to update texture!");
|
||||
for (int y = 0; y < r.h; y++)
|
||||
memcpy((unsigned char*)locked_region->data + locked_region->pitch * y, tex->GetPixelsAt(r.x, r.y + y), r.w * tex->BytesPerPixel); // dst, src, block pitch
|
||||
al_unlock_bitmap(gpu_bitmap);
|
||||
tex->SetStatus(ImTextureStatus_OK);
|
||||
}
|
||||
else if (tex->Status == ImTextureStatus_WantDestroy)
|
||||
{
|
||||
ALLEGRO_BITMAP* backend_tex = (ALLEGRO_BITMAP*)(intptr_t)tex->TexID;
|
||||
if (backend_tex)
|
||||
al_destroy_bitmap(backend_tex);
|
||||
|
||||
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
|
||||
tex->SetTexID(ImTextureID_Invalid);
|
||||
tex->SetStatus(ImTextureStatus_Destroyed);
|
||||
}
|
||||
}
|
||||
|
||||
void ImGui_ImplAllegro5_InvalidateDeviceObjects()
|
||||
{
|
||||
if (g_Texture)
|
||||
ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData();
|
||||
|
||||
// Destroy all textures
|
||||
for (ImTextureData* tex : ImGui::GetPlatformIO().Textures)
|
||||
if (tex->RefCount == 1)
|
||||
{
|
||||
tex->SetStatus(ImTextureStatus_WantDestroy);
|
||||
ImGui_ImplAllegro5_UpdateTexture(tex);
|
||||
}
|
||||
|
||||
// Destroy mouse cursor
|
||||
if (bd->MouseCursorInvisible)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.Fonts->SetTexID(NULL);
|
||||
al_destroy_bitmap(g_Texture);
|
||||
g_Texture = NULL;
|
||||
}
|
||||
if (g_MouseCursorInvisible)
|
||||
{
|
||||
al_destroy_mouse_cursor(g_MouseCursorInvisible);
|
||||
g_MouseCursorInvisible = NULL;
|
||||
al_destroy_mouse_cursor(bd->MouseCursorInvisible);
|
||||
bd->MouseCursorInvisible = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
#if ALLEGRO_HAS_CLIPBOARD
|
||||
static const char* ImGui_ImplAllegro5_GetClipboardText(void*)
|
||||
static const char* ImGui_ImplAllegro5_GetClipboardText(ImGuiContext*)
|
||||
{
|
||||
if (g_ClipboardTextData)
|
||||
al_free(g_ClipboardTextData);
|
||||
g_ClipboardTextData = al_get_clipboard_text(g_Display);
|
||||
return g_ClipboardTextData;
|
||||
ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData();
|
||||
if (bd->ClipboardTextData)
|
||||
al_free(bd->ClipboardTextData);
|
||||
bd->ClipboardTextData = al_get_clipboard_text(bd->Display);
|
||||
return bd->ClipboardTextData;
|
||||
}
|
||||
|
||||
static void ImGui_ImplAllegro5_SetClipboardText(void*, const char* text)
|
||||
static void ImGui_ImplAllegro5_SetClipboardText(ImGuiContext*, const char* text)
|
||||
{
|
||||
al_set_clipboard_text(g_Display, text);
|
||||
ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData();
|
||||
al_set_clipboard_text(bd->Display, text);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Not static to allow third-party code to use that if they want to (but undocumented)
|
||||
ImGuiKey ImGui_ImplAllegro5_KeyCodeToImGuiKey(int key_code);
|
||||
ImGuiKey ImGui_ImplAllegro5_KeyCodeToImGuiKey(int key_code)
|
||||
{
|
||||
switch (key_code)
|
||||
{
|
||||
case ALLEGRO_KEY_TAB: return ImGuiKey_Tab;
|
||||
case ALLEGRO_KEY_LEFT: return ImGuiKey_LeftArrow;
|
||||
case ALLEGRO_KEY_RIGHT: return ImGuiKey_RightArrow;
|
||||
case ALLEGRO_KEY_UP: return ImGuiKey_UpArrow;
|
||||
case ALLEGRO_KEY_DOWN: return ImGuiKey_DownArrow;
|
||||
case ALLEGRO_KEY_PGUP: return ImGuiKey_PageUp;
|
||||
case ALLEGRO_KEY_PGDN: return ImGuiKey_PageDown;
|
||||
case ALLEGRO_KEY_HOME: return ImGuiKey_Home;
|
||||
case ALLEGRO_KEY_END: return ImGuiKey_End;
|
||||
case ALLEGRO_KEY_INSERT: return ImGuiKey_Insert;
|
||||
case ALLEGRO_KEY_DELETE: return ImGuiKey_Delete;
|
||||
case ALLEGRO_KEY_BACKSPACE: return ImGuiKey_Backspace;
|
||||
case ALLEGRO_KEY_SPACE: return ImGuiKey_Space;
|
||||
case ALLEGRO_KEY_ENTER: return ImGuiKey_Enter;
|
||||
case ALLEGRO_KEY_ESCAPE: return ImGuiKey_Escape;
|
||||
case ALLEGRO_KEY_QUOTE: return ImGuiKey_Apostrophe;
|
||||
case ALLEGRO_KEY_COMMA: return ImGuiKey_Comma;
|
||||
case ALLEGRO_KEY_MINUS: return ImGuiKey_Minus;
|
||||
case ALLEGRO_KEY_FULLSTOP: return ImGuiKey_Period;
|
||||
case ALLEGRO_KEY_SLASH: return ImGuiKey_Slash;
|
||||
case ALLEGRO_KEY_SEMICOLON: return ImGuiKey_Semicolon;
|
||||
case ALLEGRO_KEY_EQUALS: return ImGuiKey_Equal;
|
||||
case ALLEGRO_KEY_OPENBRACE: return ImGuiKey_LeftBracket;
|
||||
case ALLEGRO_KEY_BACKSLASH: return ImGuiKey_Backslash;
|
||||
case ALLEGRO_KEY_CLOSEBRACE: return ImGuiKey_RightBracket;
|
||||
case ALLEGRO_KEY_TILDE: return ImGuiKey_GraveAccent;
|
||||
case ALLEGRO_KEY_CAPSLOCK: return ImGuiKey_CapsLock;
|
||||
case ALLEGRO_KEY_SCROLLLOCK: return ImGuiKey_ScrollLock;
|
||||
case ALLEGRO_KEY_NUMLOCK: return ImGuiKey_NumLock;
|
||||
case ALLEGRO_KEY_PRINTSCREEN: return ImGuiKey_PrintScreen;
|
||||
case ALLEGRO_KEY_PAUSE: return ImGuiKey_Pause;
|
||||
case ALLEGRO_KEY_PAD_0: return ImGuiKey_Keypad0;
|
||||
case ALLEGRO_KEY_PAD_1: return ImGuiKey_Keypad1;
|
||||
case ALLEGRO_KEY_PAD_2: return ImGuiKey_Keypad2;
|
||||
case ALLEGRO_KEY_PAD_3: return ImGuiKey_Keypad3;
|
||||
case ALLEGRO_KEY_PAD_4: return ImGuiKey_Keypad4;
|
||||
case ALLEGRO_KEY_PAD_5: return ImGuiKey_Keypad5;
|
||||
case ALLEGRO_KEY_PAD_6: return ImGuiKey_Keypad6;
|
||||
case ALLEGRO_KEY_PAD_7: return ImGuiKey_Keypad7;
|
||||
case ALLEGRO_KEY_PAD_8: return ImGuiKey_Keypad8;
|
||||
case ALLEGRO_KEY_PAD_9: return ImGuiKey_Keypad9;
|
||||
case ALLEGRO_KEY_PAD_DELETE: return ImGuiKey_KeypadDecimal;
|
||||
case ALLEGRO_KEY_PAD_SLASH: return ImGuiKey_KeypadDivide;
|
||||
case ALLEGRO_KEY_PAD_ASTERISK: return ImGuiKey_KeypadMultiply;
|
||||
case ALLEGRO_KEY_PAD_MINUS: return ImGuiKey_KeypadSubtract;
|
||||
case ALLEGRO_KEY_PAD_PLUS: return ImGuiKey_KeypadAdd;
|
||||
case ALLEGRO_KEY_PAD_ENTER: return ImGuiKey_KeypadEnter;
|
||||
case ALLEGRO_KEY_PAD_EQUALS: return ImGuiKey_KeypadEqual;
|
||||
case ALLEGRO_KEY_LCTRL: return ImGuiKey_LeftCtrl;
|
||||
case ALLEGRO_KEY_LSHIFT: return ImGuiKey_LeftShift;
|
||||
case ALLEGRO_KEY_ALT: return ImGuiKey_LeftAlt;
|
||||
case ALLEGRO_KEY_LWIN: return ImGuiKey_LeftSuper;
|
||||
case ALLEGRO_KEY_RCTRL: return ImGuiKey_RightCtrl;
|
||||
case ALLEGRO_KEY_RSHIFT: return ImGuiKey_RightShift;
|
||||
case ALLEGRO_KEY_ALTGR: return ImGuiKey_RightAlt;
|
||||
case ALLEGRO_KEY_RWIN: return ImGuiKey_RightSuper;
|
||||
case ALLEGRO_KEY_MENU: return ImGuiKey_Menu;
|
||||
case ALLEGRO_KEY_0: return ImGuiKey_0;
|
||||
case ALLEGRO_KEY_1: return ImGuiKey_1;
|
||||
case ALLEGRO_KEY_2: return ImGuiKey_2;
|
||||
case ALLEGRO_KEY_3: return ImGuiKey_3;
|
||||
case ALLEGRO_KEY_4: return ImGuiKey_4;
|
||||
case ALLEGRO_KEY_5: return ImGuiKey_5;
|
||||
case ALLEGRO_KEY_6: return ImGuiKey_6;
|
||||
case ALLEGRO_KEY_7: return ImGuiKey_7;
|
||||
case ALLEGRO_KEY_8: return ImGuiKey_8;
|
||||
case ALLEGRO_KEY_9: return ImGuiKey_9;
|
||||
case ALLEGRO_KEY_A: return ImGuiKey_A;
|
||||
case ALLEGRO_KEY_B: return ImGuiKey_B;
|
||||
case ALLEGRO_KEY_C: return ImGuiKey_C;
|
||||
case ALLEGRO_KEY_D: return ImGuiKey_D;
|
||||
case ALLEGRO_KEY_E: return ImGuiKey_E;
|
||||
case ALLEGRO_KEY_F: return ImGuiKey_F;
|
||||
case ALLEGRO_KEY_G: return ImGuiKey_G;
|
||||
case ALLEGRO_KEY_H: return ImGuiKey_H;
|
||||
case ALLEGRO_KEY_I: return ImGuiKey_I;
|
||||
case ALLEGRO_KEY_J: return ImGuiKey_J;
|
||||
case ALLEGRO_KEY_K: return ImGuiKey_K;
|
||||
case ALLEGRO_KEY_L: return ImGuiKey_L;
|
||||
case ALLEGRO_KEY_M: return ImGuiKey_M;
|
||||
case ALLEGRO_KEY_N: return ImGuiKey_N;
|
||||
case ALLEGRO_KEY_O: return ImGuiKey_O;
|
||||
case ALLEGRO_KEY_P: return ImGuiKey_P;
|
||||
case ALLEGRO_KEY_Q: return ImGuiKey_Q;
|
||||
case ALLEGRO_KEY_R: return ImGuiKey_R;
|
||||
case ALLEGRO_KEY_S: return ImGuiKey_S;
|
||||
case ALLEGRO_KEY_T: return ImGuiKey_T;
|
||||
case ALLEGRO_KEY_U: return ImGuiKey_U;
|
||||
case ALLEGRO_KEY_V: return ImGuiKey_V;
|
||||
case ALLEGRO_KEY_W: return ImGuiKey_W;
|
||||
case ALLEGRO_KEY_X: return ImGuiKey_X;
|
||||
case ALLEGRO_KEY_Y: return ImGuiKey_Y;
|
||||
case ALLEGRO_KEY_Z: return ImGuiKey_Z;
|
||||
case ALLEGRO_KEY_F1: return ImGuiKey_F1;
|
||||
case ALLEGRO_KEY_F2: return ImGuiKey_F2;
|
||||
case ALLEGRO_KEY_F3: return ImGuiKey_F3;
|
||||
case ALLEGRO_KEY_F4: return ImGuiKey_F4;
|
||||
case ALLEGRO_KEY_F5: return ImGuiKey_F5;
|
||||
case ALLEGRO_KEY_F6: return ImGuiKey_F6;
|
||||
case ALLEGRO_KEY_F7: return ImGuiKey_F7;
|
||||
case ALLEGRO_KEY_F8: return ImGuiKey_F8;
|
||||
case ALLEGRO_KEY_F9: return ImGuiKey_F9;
|
||||
case ALLEGRO_KEY_F10: return ImGuiKey_F10;
|
||||
case ALLEGRO_KEY_F11: return ImGuiKey_F11;
|
||||
case ALLEGRO_KEY_F12: return ImGuiKey_F12;
|
||||
default: return ImGuiKey_None;
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGui_ImplAllegro5_Init(ALLEGRO_DISPLAY* display)
|
||||
{
|
||||
g_Display = display;
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IMGUI_CHECKVERSION();
|
||||
IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!");
|
||||
|
||||
// Setup backend capabilities flags
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
||||
ImGui_ImplAllegro5_Data* bd = IM_NEW(ImGui_ImplAllegro5_Data)();
|
||||
io.BackendPlatformUserData = (void*)bd;
|
||||
io.BackendPlatformName = io.BackendRendererName = "imgui_impl_allegro5";
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
||||
|
||||
// Create custom vertex declaration.
|
||||
// Unfortunately Allegro doesn't support 32-bit packed colors so we have to convert them to 4 floats.
|
||||
// We still use a custom declaration to use 'ALLEGRO_PRIM_TEX_COORD' instead of 'ALLEGRO_PRIM_TEX_COORD_PIXEL' else we can't do a reliable conversion.
|
||||
ALLEGRO_VERTEX_ELEMENT elems[] =
|
||||
{
|
||||
{ ALLEGRO_PRIM_POSITION, ALLEGRO_PRIM_FLOAT_2, IM_OFFSETOF(ImDrawVertAllegro, pos) },
|
||||
{ ALLEGRO_PRIM_TEX_COORD, ALLEGRO_PRIM_FLOAT_2, IM_OFFSETOF(ImDrawVertAllegro, uv) },
|
||||
{ ALLEGRO_PRIM_COLOR_ATTR, 0, IM_OFFSETOF(ImDrawVertAllegro, col) },
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
g_VertexDecl = al_create_vertex_decl(elems, sizeof(ImDrawVertAllegro));
|
||||
bd->LastCursor = ALLEGRO_SYSTEM_MOUSE_CURSOR_NONE;
|
||||
|
||||
io.KeyMap[ImGuiKey_Tab] = ALLEGRO_KEY_TAB;
|
||||
io.KeyMap[ImGuiKey_LeftArrow] = ALLEGRO_KEY_LEFT;
|
||||
io.KeyMap[ImGuiKey_RightArrow] = ALLEGRO_KEY_RIGHT;
|
||||
io.KeyMap[ImGuiKey_UpArrow] = ALLEGRO_KEY_UP;
|
||||
io.KeyMap[ImGuiKey_DownArrow] = ALLEGRO_KEY_DOWN;
|
||||
io.KeyMap[ImGuiKey_PageUp] = ALLEGRO_KEY_PGUP;
|
||||
io.KeyMap[ImGuiKey_PageDown] = ALLEGRO_KEY_PGDN;
|
||||
io.KeyMap[ImGuiKey_Home] = ALLEGRO_KEY_HOME;
|
||||
io.KeyMap[ImGuiKey_End] = ALLEGRO_KEY_END;
|
||||
io.KeyMap[ImGuiKey_Insert] = ALLEGRO_KEY_INSERT;
|
||||
io.KeyMap[ImGuiKey_Delete] = ALLEGRO_KEY_DELETE;
|
||||
io.KeyMap[ImGuiKey_Backspace] = ALLEGRO_KEY_BACKSPACE;
|
||||
io.KeyMap[ImGuiKey_Space] = ALLEGRO_KEY_SPACE;
|
||||
io.KeyMap[ImGuiKey_Enter] = ALLEGRO_KEY_ENTER;
|
||||
io.KeyMap[ImGuiKey_Escape] = ALLEGRO_KEY_ESCAPE;
|
||||
io.KeyMap[ImGuiKey_KeyPadEnter] = ALLEGRO_KEY_PAD_ENTER;
|
||||
io.KeyMap[ImGuiKey_A] = ALLEGRO_KEY_A;
|
||||
io.KeyMap[ImGuiKey_C] = ALLEGRO_KEY_C;
|
||||
io.KeyMap[ImGuiKey_V] = ALLEGRO_KEY_V;
|
||||
io.KeyMap[ImGuiKey_X] = ALLEGRO_KEY_X;
|
||||
io.KeyMap[ImGuiKey_Y] = ALLEGRO_KEY_Y;
|
||||
io.KeyMap[ImGuiKey_Z] = ALLEGRO_KEY_Z;
|
||||
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
|
||||
ImGui_ImplAllegro5_SetDisplay(display);
|
||||
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
#if ALLEGRO_HAS_CLIPBOARD
|
||||
io.SetClipboardTextFn = ImGui_ImplAllegro5_SetClipboardText;
|
||||
io.GetClipboardTextFn = ImGui_ImplAllegro5_GetClipboardText;
|
||||
io.ClipboardUserData = NULL;
|
||||
platform_io.Platform_SetClipboardTextFn = ImGui_ImplAllegro5_SetClipboardText;
|
||||
platform_io.Platform_GetClipboardTextFn = ImGui_ImplAllegro5_GetClipboardText;
|
||||
#endif
|
||||
platform_io.DrawCallback_ResetRenderState = ImGui_ImplAllegro5_DrawCallback_ResetRenderState;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplAllegro5_Shutdown()
|
||||
{
|
||||
ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
ImGui_ImplAllegro5_InvalidateDeviceObjects();
|
||||
if (bd->VertexDecl)
|
||||
al_destroy_vertex_decl(bd->VertexDecl);
|
||||
if (bd->ClipboardTextData)
|
||||
al_free(bd->ClipboardTextData);
|
||||
|
||||
g_Display = NULL;
|
||||
g_Time = 0.0;
|
||||
io.BackendPlatformName = io.BackendRendererName = nullptr;
|
||||
io.BackendPlatformUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_RendererHasTextures);
|
||||
platform_io.ClearRendererHandlers();
|
||||
platform_io.ClearPlatformHandlers();
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
if (g_VertexDecl)
|
||||
al_destroy_vertex_decl(g_VertexDecl);
|
||||
g_VertexDecl = NULL;
|
||||
void ImGui_ImplAllegro5_SetDisplay(ALLEGRO_DISPLAY* display)
|
||||
{
|
||||
ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData();
|
||||
bd->Display = display;
|
||||
|
||||
if (g_ClipboardTextData)
|
||||
al_free(g_ClipboardTextData);
|
||||
g_ClipboardTextData = NULL;
|
||||
if (bd->VertexDecl)
|
||||
{
|
||||
al_destroy_vertex_decl(bd->VertexDecl);
|
||||
bd->VertexDecl = nullptr;
|
||||
}
|
||||
|
||||
if (bd->Display && !bd->VertexDecl)
|
||||
{
|
||||
// Create custom vertex declaration.
|
||||
// Unfortunately Allegro doesn't support 32-bits packed colors so we have to convert them to 4 floats.
|
||||
// We still use a custom declaration to use 'ALLEGRO_PRIM_TEX_COORD' instead of 'ALLEGRO_PRIM_TEX_COORD_PIXEL' else we can't do a reliable conversion.
|
||||
ALLEGRO_VERTEX_ELEMENT elems[] =
|
||||
{
|
||||
{ ALLEGRO_PRIM_POSITION, ALLEGRO_PRIM_FLOAT_2, offsetof(ImDrawVertAllegro, pos) },
|
||||
{ ALLEGRO_PRIM_TEX_COORD, ALLEGRO_PRIM_FLOAT_2, offsetof(ImDrawVertAllegro, uv) },
|
||||
{ ALLEGRO_PRIM_COLOR_ATTR, 0, offsetof(ImDrawVertAllegro, col) },
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
bd->VertexDecl = al_create_vertex_decl(elems, sizeof(ImDrawVertAllegro));
|
||||
}
|
||||
}
|
||||
|
||||
// ev->keyboard.modifiers seems always zero so using that...
|
||||
static void ImGui_ImplAllegro5_UpdateKeyModifiers()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ALLEGRO_KEYBOARD_STATE keys;
|
||||
al_get_keyboard_state(&keys);
|
||||
io.AddKeyEvent(ImGuiMod_Ctrl, al_key_down(&keys, ALLEGRO_KEY_LCTRL) || al_key_down(&keys, ALLEGRO_KEY_RCTRL));
|
||||
io.AddKeyEvent(ImGuiMod_Shift, al_key_down(&keys, ALLEGRO_KEY_LSHIFT) || al_key_down(&keys, ALLEGRO_KEY_RSHIFT));
|
||||
io.AddKeyEvent(ImGuiMod_Alt, al_key_down(&keys, ALLEGRO_KEY_ALT) || al_key_down(&keys, ALLEGRO_KEY_ALTGR));
|
||||
io.AddKeyEvent(ImGuiMod_Super, al_key_down(&keys, ALLEGRO_KEY_LWIN) || al_key_down(&keys, ALLEGRO_KEY_RWIN));
|
||||
}
|
||||
|
||||
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
|
||||
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
|
||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||
bool ImGui_ImplAllegro5_ProcessEvent(ALLEGRO_EVENT* ev)
|
||||
{
|
||||
ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplAllegro5_Init()?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
switch (ev->type)
|
||||
{
|
||||
case ALLEGRO_EVENT_MOUSE_AXES:
|
||||
if (ev->mouse.display == g_Display)
|
||||
if (ev->mouse.display == bd->Display)
|
||||
{
|
||||
io.MouseWheel += ev->mouse.dz;
|
||||
io.MouseWheelH -= ev->mouse.dw;
|
||||
io.MousePos = ImVec2(ev->mouse.x, ev->mouse.y);
|
||||
io.AddMousePosEvent(ev->mouse.x, ev->mouse.y);
|
||||
io.AddMouseWheelEvent(-ev->mouse.dw, ev->mouse.dz);
|
||||
}
|
||||
return true;
|
||||
case ALLEGRO_EVENT_MOUSE_BUTTON_DOWN:
|
||||
case ALLEGRO_EVENT_MOUSE_BUTTON_UP:
|
||||
if (ev->mouse.display == g_Display && ev->mouse.button <= 5)
|
||||
io.MouseDown[ev->mouse.button - 1] = (ev->type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN);
|
||||
if (ev->mouse.display == bd->Display && ev->mouse.button > 0 && ev->mouse.button <= 5)
|
||||
io.AddMouseButtonEvent(ev->mouse.button - 1, ev->type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN);
|
||||
return true;
|
||||
case ALLEGRO_EVENT_TOUCH_MOVE:
|
||||
if (ev->touch.display == g_Display)
|
||||
io.MousePos = ImVec2(ev->touch.x, ev->touch.y);
|
||||
if (ev->touch.display == bd->Display)
|
||||
io.AddMousePosEvent(ev->touch.x, ev->touch.y);
|
||||
return true;
|
||||
case ALLEGRO_EVENT_TOUCH_BEGIN:
|
||||
case ALLEGRO_EVENT_TOUCH_END:
|
||||
case ALLEGRO_EVENT_TOUCH_CANCEL:
|
||||
if (ev->touch.display == g_Display && ev->touch.primary)
|
||||
io.MouseDown[0] = (ev->type == ALLEGRO_EVENT_TOUCH_BEGIN);
|
||||
if (ev->touch.display == bd->Display && ev->touch.primary)
|
||||
io.AddMouseButtonEvent(0, ev->type == ALLEGRO_EVENT_TOUCH_BEGIN);
|
||||
return true;
|
||||
case ALLEGRO_EVENT_MOUSE_LEAVE_DISPLAY:
|
||||
if (ev->mouse.display == g_Display)
|
||||
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
|
||||
if (ev->mouse.display == bd->Display)
|
||||
io.AddMousePosEvent(-FLT_MAX, -FLT_MAX);
|
||||
return true;
|
||||
case ALLEGRO_EVENT_KEY_CHAR:
|
||||
if (ev->keyboard.display == g_Display)
|
||||
if (ev->keyboard.display == bd->Display)
|
||||
if (ev->keyboard.unichar != 0)
|
||||
io.AddInputCharacter((unsigned int)ev->keyboard.unichar);
|
||||
return true;
|
||||
case ALLEGRO_EVENT_KEY_DOWN:
|
||||
case ALLEGRO_EVENT_KEY_UP:
|
||||
if (ev->keyboard.display == g_Display)
|
||||
io.KeysDown[ev->keyboard.keycode] = (ev->type == ALLEGRO_EVENT_KEY_DOWN);
|
||||
if (ev->keyboard.display == bd->Display)
|
||||
{
|
||||
ImGui_ImplAllegro5_UpdateKeyModifiers();
|
||||
ImGuiKey key = ImGui_ImplAllegro5_KeyCodeToImGuiKey(ev->keyboard.keycode);
|
||||
io.AddKeyEvent(key, (ev->type == ALLEGRO_EVENT_KEY_DOWN));
|
||||
io.SetKeyEventNativeData(key, ev->keyboard.keycode, -1); // To support legacy indexing (<1.87 user code)
|
||||
}
|
||||
return true;
|
||||
case ALLEGRO_EVENT_DISPLAY_SWITCH_OUT:
|
||||
if (ev->display.source == bd->Display)
|
||||
io.AddFocusEvent(false);
|
||||
return true;
|
||||
case ALLEGRO_EVENT_DISPLAY_SWITCH_IN:
|
||||
if (ev->display.source == bd->Display)
|
||||
{
|
||||
io.AddFocusEvent(true);
|
||||
#if defined(ALLEGRO_UNSTABLE)
|
||||
al_clear_keyboard_state(bd->Display);
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -378,11 +637,19 @@ static void ImGui_ImplAllegro5_UpdateMouseCursor()
|
||||
if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
|
||||
return;
|
||||
|
||||
ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData();
|
||||
ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
|
||||
if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None)
|
||||
|
||||
// Hide OS mouse cursor if imgui is drawing it
|
||||
if (io.MouseDrawCursor)
|
||||
imgui_cursor = ImGuiMouseCursor_None;
|
||||
|
||||
if (bd->LastCursor == imgui_cursor)
|
||||
return;
|
||||
bd->LastCursor = imgui_cursor;
|
||||
if (imgui_cursor == ImGuiMouseCursor_None)
|
||||
{
|
||||
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
|
||||
al_set_mouse_cursor(g_Display, g_MouseCursorInvisible);
|
||||
al_set_mouse_cursor(bd->Display, bd->MouseCursorInvisible);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -395,37 +662,43 @@ static void ImGui_ImplAllegro5_UpdateMouseCursor()
|
||||
case ImGuiMouseCursor_ResizeEW: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_RESIZE_E; break;
|
||||
case ImGuiMouseCursor_ResizeNESW: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_RESIZE_NE; break;
|
||||
case ImGuiMouseCursor_ResizeNWSE: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_RESIZE_NW; break;
|
||||
case ImGuiMouseCursor_Wait: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_BUSY; break;
|
||||
case ImGuiMouseCursor_Progress: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_PROGRESS; break;
|
||||
case ImGuiMouseCursor_NotAllowed: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_UNAVAILABLE; break;
|
||||
}
|
||||
al_set_system_mouse_cursor(g_Display, cursor_id);
|
||||
al_set_system_mouse_cursor(bd->Display, cursor_id);
|
||||
}
|
||||
}
|
||||
|
||||
void ImGui_ImplAllegro5_NewFrame()
|
||||
{
|
||||
if (!g_Texture)
|
||||
ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplAllegro5_Init()?");
|
||||
|
||||
if (!bd->MouseCursorInvisible)
|
||||
ImGui_ImplAllegro5_CreateDeviceObjects();
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
// Setup display size (every frame to accommodate for window resizing)
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
int w, h;
|
||||
w = al_get_display_width(g_Display);
|
||||
h = al_get_display_height(g_Display);
|
||||
w = al_get_display_width(bd->Display);
|
||||
h = al_get_display_height(bd->Display);
|
||||
io.DisplaySize = ImVec2((float)w, (float)h);
|
||||
|
||||
// Setup time step
|
||||
double current_time = al_get_time();
|
||||
io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f / 60.0f);
|
||||
g_Time = current_time;
|
||||
io.DeltaTime = bd->Time > 0.0 ? (float)(current_time - bd->Time) : (float)(1.0f / 60.0f);
|
||||
bd->Time = current_time;
|
||||
|
||||
// Setup inputs
|
||||
ALLEGRO_KEYBOARD_STATE keys;
|
||||
al_get_keyboard_state(&keys);
|
||||
io.KeyCtrl = al_key_down(&keys, ALLEGRO_KEY_LCTRL) || al_key_down(&keys, ALLEGRO_KEY_RCTRL);
|
||||
io.KeyShift = al_key_down(&keys, ALLEGRO_KEY_LSHIFT) || al_key_down(&keys, ALLEGRO_KEY_RSHIFT);
|
||||
io.KeyAlt = al_key_down(&keys, ALLEGRO_KEY_ALT) || al_key_down(&keys, ALLEGRO_KEY_ALTGR);
|
||||
io.KeySuper = al_key_down(&keys, ALLEGRO_KEY_LWIN) || al_key_down(&keys, ALLEGRO_KEY_RWIN);
|
||||
// Allegro 5 doesn't receive PrintScreen under Windows
|
||||
#ifdef _WIN32
|
||||
io.AddKeyEvent(ImGuiKey_PrintScreen, (::GetAsyncKeyState(VK_SNAPSHOT) & 0x8000) != 0);
|
||||
#endif
|
||||
|
||||
// Setup mouse cursor shape
|
||||
ImGui_ImplAllegro5_UpdateMouseCursor();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
@@ -2,29 +2,44 @@
|
||||
// (Info: Allegro 5 is a cross-platform general purpose library for handling windows, inputs, graphics, etc.)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'ALLEGRO_BITMAP*' as ImTextureID. Read the FAQ about ImTextureID!
|
||||
// [X] Platform: Clipboard support (from Allegro 5.1.12)
|
||||
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
// Issues:
|
||||
// [X] Renderer: User texture binding. Use 'ALLEGRO_BITMAP*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy ALLEGRO_KEY_* values are obsolete since 1.87 and not supported since 1.91.5]
|
||||
// [X] Platform: Clipboard support (from Allegro 5.1.12).
|
||||
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
// Missing features or Issues:
|
||||
// [ ] Renderer: The renderer is suboptimal as we need to unindex our buffers and convert vertices manually.
|
||||
// [ ] Renderer: Missing support for DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest callbacks: Allegro5 cannot enable/disable LINEAR bitmap flags after creation.
|
||||
// [ ] Platform: Missing gamepad support.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
#pragma once
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
struct ALLEGRO_DISPLAY;
|
||||
union ALLEGRO_EVENT;
|
||||
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
IMGUI_IMPL_API bool ImGui_ImplAllegro5_Init(ALLEGRO_DISPLAY* display);
|
||||
IMGUI_IMPL_API void ImGui_ImplAllegro5_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplAllegro5_NewFrame();
|
||||
IMGUI_IMPL_API void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data);
|
||||
IMGUI_IMPL_API bool ImGui_ImplAllegro5_ProcessEvent(ALLEGRO_EVENT* event);
|
||||
IMGUI_IMPL_API void ImGui_ImplAllegro5_SetDisplay(ALLEGRO_DISPLAY* display);
|
||||
|
||||
// Use if you want to reset your rendering device without losing Dear ImGui state.
|
||||
IMGUI_IMPL_API bool ImGui_ImplAllegro5_CreateDeviceObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplAllegro5_InvalidateDeviceObjects();
|
||||
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||
IMGUI_IMPL_API void ImGui_ImplAllegro5_UpdateTexture(ImTextureData* tex);
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
@@ -2,28 +2,37 @@
|
||||
// This needs to be used along with the OpenGL 3 Renderer (imgui_impl_opengl3)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Platform: Keyboard arrays indexed using AKEYCODE_* codes, e.g. ImGui::IsKeyPressed(AKEYCODE_SPACE).
|
||||
// Missing features:
|
||||
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy AKEYCODE_* values are obsolete since 1.87 and not supported since 1.91.5]
|
||||
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen.
|
||||
// Missing features or Issues:
|
||||
// [ ] Platform: Clipboard support.
|
||||
// [ ] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
||||
// [ ] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. FIXME: Check if this is even possible with Android.
|
||||
// [ ] Platform: Gamepad support.
|
||||
// [ ] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. FIXME: Check if this is even possible with Android.
|
||||
// Important:
|
||||
// - Consider using SDL or GLFW backend on Android, which will be more full-featured than this.
|
||||
// - FIXME: On-screen keyboard currently needs to be enabled by the application (see examples/ and issue #3446)
|
||||
// - FIXME: Unicode character inputs needs to be passed by Dear ImGui by the application (see examples/ and issue #3446)
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
|
||||
// https://github.com/ocornut/imgui
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2022-09-26: Inputs: Renamed ImGuiKey_ModXXX introduced in 1.87 to ImGuiMod_XXX (old names still supported).
|
||||
// 2022-01-26: Inputs: replaced short-lived io.AddKeyModsEvent() (added two weeks ago) with io.AddKeyEvent() using ImGuiKey_ModXXX flags. Sorry for the confusion.
|
||||
// 2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEvent(), io.AddMouseWheelEvent() API (1.87+).
|
||||
// 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range.
|
||||
// 2021-03-04: Initial version.
|
||||
|
||||
#include "imgui.h"
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include "imgui_impl_android.h"
|
||||
#include <time.h>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <android/native_window.h>
|
||||
#include <android/input.h>
|
||||
#include <android/keycodes.h>
|
||||
@@ -33,9 +42,121 @@
|
||||
static double g_Time = 0.0;
|
||||
static ANativeWindow* g_Window;
|
||||
static char g_LogTag[] = "ImGuiExample";
|
||||
static std::map<int32_t, std::queue<int32_t>> g_KeyEventQueues; // FIXME: Remove dependency on map and queue once we use upcoming input queue.
|
||||
|
||||
int32_t ImGui_ImplAndroid_HandleInputEvent(AInputEvent* input_event)
|
||||
static ImGuiKey ImGui_ImplAndroid_KeyCodeToImGuiKey(int32_t key_code)
|
||||
{
|
||||
switch (key_code)
|
||||
{
|
||||
case AKEYCODE_TAB: return ImGuiKey_Tab;
|
||||
case AKEYCODE_DPAD_LEFT: return ImGuiKey_LeftArrow;
|
||||
case AKEYCODE_DPAD_RIGHT: return ImGuiKey_RightArrow;
|
||||
case AKEYCODE_DPAD_UP: return ImGuiKey_UpArrow;
|
||||
case AKEYCODE_DPAD_DOWN: return ImGuiKey_DownArrow;
|
||||
case AKEYCODE_PAGE_UP: return ImGuiKey_PageUp;
|
||||
case AKEYCODE_PAGE_DOWN: return ImGuiKey_PageDown;
|
||||
case AKEYCODE_MOVE_HOME: return ImGuiKey_Home;
|
||||
case AKEYCODE_MOVE_END: return ImGuiKey_End;
|
||||
case AKEYCODE_INSERT: return ImGuiKey_Insert;
|
||||
case AKEYCODE_FORWARD_DEL: return ImGuiKey_Delete;
|
||||
case AKEYCODE_DEL: return ImGuiKey_Backspace;
|
||||
case AKEYCODE_SPACE: return ImGuiKey_Space;
|
||||
case AKEYCODE_ENTER: return ImGuiKey_Enter;
|
||||
case AKEYCODE_ESCAPE: return ImGuiKey_Escape;
|
||||
case AKEYCODE_APOSTROPHE: return ImGuiKey_Apostrophe;
|
||||
case AKEYCODE_COMMA: return ImGuiKey_Comma;
|
||||
case AKEYCODE_MINUS: return ImGuiKey_Minus;
|
||||
case AKEYCODE_PERIOD: return ImGuiKey_Period;
|
||||
case AKEYCODE_SLASH: return ImGuiKey_Slash;
|
||||
case AKEYCODE_SEMICOLON: return ImGuiKey_Semicolon;
|
||||
case AKEYCODE_EQUALS: return ImGuiKey_Equal;
|
||||
case AKEYCODE_LEFT_BRACKET: return ImGuiKey_LeftBracket;
|
||||
case AKEYCODE_BACKSLASH: return ImGuiKey_Backslash;
|
||||
case AKEYCODE_RIGHT_BRACKET: return ImGuiKey_RightBracket;
|
||||
case AKEYCODE_GRAVE: return ImGuiKey_GraveAccent;
|
||||
case AKEYCODE_CAPS_LOCK: return ImGuiKey_CapsLock;
|
||||
case AKEYCODE_SCROLL_LOCK: return ImGuiKey_ScrollLock;
|
||||
case AKEYCODE_NUM_LOCK: return ImGuiKey_NumLock;
|
||||
case AKEYCODE_SYSRQ: return ImGuiKey_PrintScreen;
|
||||
case AKEYCODE_BREAK: return ImGuiKey_Pause;
|
||||
case AKEYCODE_NUMPAD_0: return ImGuiKey_Keypad0;
|
||||
case AKEYCODE_NUMPAD_1: return ImGuiKey_Keypad1;
|
||||
case AKEYCODE_NUMPAD_2: return ImGuiKey_Keypad2;
|
||||
case AKEYCODE_NUMPAD_3: return ImGuiKey_Keypad3;
|
||||
case AKEYCODE_NUMPAD_4: return ImGuiKey_Keypad4;
|
||||
case AKEYCODE_NUMPAD_5: return ImGuiKey_Keypad5;
|
||||
case AKEYCODE_NUMPAD_6: return ImGuiKey_Keypad6;
|
||||
case AKEYCODE_NUMPAD_7: return ImGuiKey_Keypad7;
|
||||
case AKEYCODE_NUMPAD_8: return ImGuiKey_Keypad8;
|
||||
case AKEYCODE_NUMPAD_9: return ImGuiKey_Keypad9;
|
||||
case AKEYCODE_NUMPAD_DOT: return ImGuiKey_KeypadDecimal;
|
||||
case AKEYCODE_NUMPAD_DIVIDE: return ImGuiKey_KeypadDivide;
|
||||
case AKEYCODE_NUMPAD_MULTIPLY: return ImGuiKey_KeypadMultiply;
|
||||
case AKEYCODE_NUMPAD_SUBTRACT: return ImGuiKey_KeypadSubtract;
|
||||
case AKEYCODE_NUMPAD_ADD: return ImGuiKey_KeypadAdd;
|
||||
case AKEYCODE_NUMPAD_ENTER: return ImGuiKey_KeypadEnter;
|
||||
case AKEYCODE_NUMPAD_EQUALS: return ImGuiKey_KeypadEqual;
|
||||
case AKEYCODE_CTRL_LEFT: return ImGuiKey_LeftCtrl;
|
||||
case AKEYCODE_SHIFT_LEFT: return ImGuiKey_LeftShift;
|
||||
case AKEYCODE_ALT_LEFT: return ImGuiKey_LeftAlt;
|
||||
case AKEYCODE_META_LEFT: return ImGuiKey_LeftSuper;
|
||||
case AKEYCODE_CTRL_RIGHT: return ImGuiKey_RightCtrl;
|
||||
case AKEYCODE_SHIFT_RIGHT: return ImGuiKey_RightShift;
|
||||
case AKEYCODE_ALT_RIGHT: return ImGuiKey_RightAlt;
|
||||
case AKEYCODE_META_RIGHT: return ImGuiKey_RightSuper;
|
||||
case AKEYCODE_MENU: return ImGuiKey_Menu;
|
||||
case AKEYCODE_0: return ImGuiKey_0;
|
||||
case AKEYCODE_1: return ImGuiKey_1;
|
||||
case AKEYCODE_2: return ImGuiKey_2;
|
||||
case AKEYCODE_3: return ImGuiKey_3;
|
||||
case AKEYCODE_4: return ImGuiKey_4;
|
||||
case AKEYCODE_5: return ImGuiKey_5;
|
||||
case AKEYCODE_6: return ImGuiKey_6;
|
||||
case AKEYCODE_7: return ImGuiKey_7;
|
||||
case AKEYCODE_8: return ImGuiKey_8;
|
||||
case AKEYCODE_9: return ImGuiKey_9;
|
||||
case AKEYCODE_A: return ImGuiKey_A;
|
||||
case AKEYCODE_B: return ImGuiKey_B;
|
||||
case AKEYCODE_C: return ImGuiKey_C;
|
||||
case AKEYCODE_D: return ImGuiKey_D;
|
||||
case AKEYCODE_E: return ImGuiKey_E;
|
||||
case AKEYCODE_F: return ImGuiKey_F;
|
||||
case AKEYCODE_G: return ImGuiKey_G;
|
||||
case AKEYCODE_H: return ImGuiKey_H;
|
||||
case AKEYCODE_I: return ImGuiKey_I;
|
||||
case AKEYCODE_J: return ImGuiKey_J;
|
||||
case AKEYCODE_K: return ImGuiKey_K;
|
||||
case AKEYCODE_L: return ImGuiKey_L;
|
||||
case AKEYCODE_M: return ImGuiKey_M;
|
||||
case AKEYCODE_N: return ImGuiKey_N;
|
||||
case AKEYCODE_O: return ImGuiKey_O;
|
||||
case AKEYCODE_P: return ImGuiKey_P;
|
||||
case AKEYCODE_Q: return ImGuiKey_Q;
|
||||
case AKEYCODE_R: return ImGuiKey_R;
|
||||
case AKEYCODE_S: return ImGuiKey_S;
|
||||
case AKEYCODE_T: return ImGuiKey_T;
|
||||
case AKEYCODE_U: return ImGuiKey_U;
|
||||
case AKEYCODE_V: return ImGuiKey_V;
|
||||
case AKEYCODE_W: return ImGuiKey_W;
|
||||
case AKEYCODE_X: return ImGuiKey_X;
|
||||
case AKEYCODE_Y: return ImGuiKey_Y;
|
||||
case AKEYCODE_Z: return ImGuiKey_Z;
|
||||
case AKEYCODE_F1: return ImGuiKey_F1;
|
||||
case AKEYCODE_F2: return ImGuiKey_F2;
|
||||
case AKEYCODE_F3: return ImGuiKey_F3;
|
||||
case AKEYCODE_F4: return ImGuiKey_F4;
|
||||
case AKEYCODE_F5: return ImGuiKey_F5;
|
||||
case AKEYCODE_F6: return ImGuiKey_F6;
|
||||
case AKEYCODE_F7: return ImGuiKey_F7;
|
||||
case AKEYCODE_F8: return ImGuiKey_F8;
|
||||
case AKEYCODE_F9: return ImGuiKey_F9;
|
||||
case AKEYCODE_F10: return ImGuiKey_F10;
|
||||
case AKEYCODE_F11: return ImGuiKey_F11;
|
||||
case AKEYCODE_F12: return ImGuiKey_F12;
|
||||
default: return ImGuiKey_None;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t ImGui_ImplAndroid_HandleInputEvent(const AInputEvent* input_event)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
int32_t event_type = AInputEvent_getType(input_event);
|
||||
@@ -44,12 +165,14 @@ int32_t ImGui_ImplAndroid_HandleInputEvent(AInputEvent* input_event)
|
||||
case AINPUT_EVENT_TYPE_KEY:
|
||||
{
|
||||
int32_t event_key_code = AKeyEvent_getKeyCode(input_event);
|
||||
int32_t event_scan_code = AKeyEvent_getScanCode(input_event);
|
||||
int32_t event_action = AKeyEvent_getAction(input_event);
|
||||
int32_t event_meta_state = AKeyEvent_getMetaState(input_event);
|
||||
|
||||
io.KeyCtrl = ((event_meta_state & AMETA_CTRL_ON) != 0);
|
||||
io.KeyShift = ((event_meta_state & AMETA_SHIFT_ON) != 0);
|
||||
io.KeyAlt = ((event_meta_state & AMETA_ALT_ON) != 0);
|
||||
io.AddKeyEvent(ImGuiMod_Ctrl, (event_meta_state & AMETA_CTRL_ON) != 0);
|
||||
io.AddKeyEvent(ImGuiMod_Shift, (event_meta_state & AMETA_SHIFT_ON) != 0);
|
||||
io.AddKeyEvent(ImGuiMod_Alt, (event_meta_state & AMETA_ALT_ON) != 0);
|
||||
io.AddKeyEvent(ImGuiMod_Super, (event_meta_state & AMETA_META_ON) != 0);
|
||||
|
||||
switch (event_action)
|
||||
{
|
||||
@@ -58,8 +181,16 @@ int32_t ImGui_ImplAndroid_HandleInputEvent(AInputEvent* input_event)
|
||||
// ImGui_ImplAndroid_NewFrame()...or consider using IO queue, if suitable: https://github.com/ocornut/imgui/issues/2787
|
||||
case AKEY_EVENT_ACTION_DOWN:
|
||||
case AKEY_EVENT_ACTION_UP:
|
||||
g_KeyEventQueues[event_key_code].push(event_action);
|
||||
{
|
||||
ImGuiKey key = ImGui_ImplAndroid_KeyCodeToImGuiKey(event_key_code);
|
||||
if (key != ImGuiKey_None)
|
||||
{
|
||||
io.AddKeyEvent(key, event_action == AKEY_EVENT_ACTION_DOWN);
|
||||
io.SetKeyEventNativeData(key, event_key_code, event_scan_code);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -70,36 +201,53 @@ int32_t ImGui_ImplAndroid_HandleInputEvent(AInputEvent* input_event)
|
||||
int32_t event_action = AMotionEvent_getAction(input_event);
|
||||
int32_t event_pointer_index = (event_action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
|
||||
event_action &= AMOTION_EVENT_ACTION_MASK;
|
||||
|
||||
switch (AMotionEvent_getToolType(input_event, event_pointer_index))
|
||||
{
|
||||
case AMOTION_EVENT_TOOL_TYPE_MOUSE:
|
||||
io.AddMouseSourceEvent(ImGuiMouseSource_Mouse);
|
||||
break;
|
||||
case AMOTION_EVENT_TOOL_TYPE_STYLUS:
|
||||
case AMOTION_EVENT_TOOL_TYPE_ERASER:
|
||||
io.AddMouseSourceEvent(ImGuiMouseSource_Pen);
|
||||
break;
|
||||
case AMOTION_EVENT_TOOL_TYPE_FINGER:
|
||||
default:
|
||||
io.AddMouseSourceEvent(ImGuiMouseSource_TouchScreen);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (event_action)
|
||||
{
|
||||
case AMOTION_EVENT_ACTION_DOWN:
|
||||
case AMOTION_EVENT_ACTION_UP:
|
||||
{
|
||||
// Physical mouse buttons (and probably other physical devices) also invoke the actions AMOTION_EVENT_ACTION_DOWN/_UP,
|
||||
// but we have to process them separately to identify the actual button pressed. This is done below via
|
||||
// AMOTION_EVENT_ACTION_BUTTON_PRESS/_RELEASE. Here, we only process "FINGER" input (and "UNKNOWN", as a fallback).
|
||||
if((AMotionEvent_getToolType(input_event, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_FINGER)
|
||||
|| (AMotionEvent_getToolType(input_event, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_UNKNOWN))
|
||||
int tool_type = AMotionEvent_getToolType(input_event, event_pointer_index);
|
||||
if (tool_type == AMOTION_EVENT_TOOL_TYPE_FINGER || tool_type == AMOTION_EVENT_TOOL_TYPE_UNKNOWN)
|
||||
{
|
||||
io.MouseDown[0] = (event_action == AMOTION_EVENT_ACTION_DOWN);
|
||||
io.MousePos = ImVec2(AMotionEvent_getX(input_event, event_pointer_index), AMotionEvent_getY(input_event, event_pointer_index));
|
||||
io.AddMousePosEvent(AMotionEvent_getX(input_event, event_pointer_index), AMotionEvent_getY(input_event, event_pointer_index));
|
||||
io.AddMouseButtonEvent(0, event_action == AMOTION_EVENT_ACTION_DOWN);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AMOTION_EVENT_ACTION_BUTTON_PRESS:
|
||||
case AMOTION_EVENT_ACTION_BUTTON_RELEASE:
|
||||
{
|
||||
int32_t button_state = AMotionEvent_getButtonState(input_event);
|
||||
io.MouseDown[0] = ((button_state & AMOTION_EVENT_BUTTON_PRIMARY) != 0);
|
||||
io.MouseDown[1] = ((button_state & AMOTION_EVENT_BUTTON_SECONDARY) != 0);
|
||||
io.MouseDown[2] = ((button_state & AMOTION_EVENT_BUTTON_TERTIARY) != 0);
|
||||
}
|
||||
{
|
||||
int32_t button_state = AMotionEvent_getButtonState(input_event);
|
||||
io.AddMouseButtonEvent(0, (button_state & AMOTION_EVENT_BUTTON_PRIMARY) != 0);
|
||||
io.AddMouseButtonEvent(1, (button_state & AMOTION_EVENT_BUTTON_SECONDARY) != 0);
|
||||
io.AddMouseButtonEvent(2, (button_state & AMOTION_EVENT_BUTTON_TERTIARY) != 0);
|
||||
break;
|
||||
}
|
||||
case AMOTION_EVENT_ACTION_HOVER_MOVE: // Hovering: Tool moves while NOT pressed (such as a physical mouse)
|
||||
case AMOTION_EVENT_ACTION_MOVE: // Touch pointer moves while DOWN
|
||||
io.MousePos = ImVec2(AMotionEvent_getX(input_event, event_pointer_index), AMotionEvent_getY(input_event, event_pointer_index));
|
||||
io.AddMousePosEvent(AMotionEvent_getX(input_event, event_pointer_index), AMotionEvent_getY(input_event, event_pointer_index));
|
||||
break;
|
||||
case AMOTION_EVENT_ACTION_SCROLL:
|
||||
io.MouseWheel = AMotionEvent_getAxisValue(input_event, AMOTION_EVENT_AXIS_VSCROLL, event_pointer_index);
|
||||
io.MouseWheelH = AMotionEvent_getAxisValue(input_event, AMOTION_EVENT_AXIS_HSCROLL, event_pointer_index);
|
||||
io.AddMouseWheelEvent(AMotionEvent_getAxisValue(input_event, AMOTION_EVENT_AXIS_HSCROLL, event_pointer_index), AMotionEvent_getAxisValue(input_event, AMOTION_EVENT_AXIS_VSCROLL, event_pointer_index));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -115,6 +263,8 @@ int32_t ImGui_ImplAndroid_HandleInputEvent(AInputEvent* input_event)
|
||||
|
||||
bool ImGui_ImplAndroid_Init(ANativeWindow* window)
|
||||
{
|
||||
IMGUI_CHECKVERSION();
|
||||
|
||||
g_Window = window;
|
||||
g_Time = 0.0;
|
||||
|
||||
@@ -122,51 +272,18 @@ bool ImGui_ImplAndroid_Init(ANativeWindow* window)
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.BackendPlatformName = "imgui_impl_android";
|
||||
|
||||
// Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array.
|
||||
io.KeyMap[ImGuiKey_Tab] = AKEYCODE_TAB;
|
||||
io.KeyMap[ImGuiKey_LeftArrow] = AKEYCODE_DPAD_LEFT; // also covers physical keyboard arrow key
|
||||
io.KeyMap[ImGuiKey_RightArrow] = AKEYCODE_DPAD_RIGHT; // also covers physical keyboard arrow key
|
||||
io.KeyMap[ImGuiKey_UpArrow] = AKEYCODE_DPAD_UP; // also covers physical keyboard arrow key
|
||||
io.KeyMap[ImGuiKey_DownArrow] = AKEYCODE_DPAD_DOWN; // also covers physical keyboard arrow key
|
||||
io.KeyMap[ImGuiKey_PageUp] = AKEYCODE_PAGE_UP;
|
||||
io.KeyMap[ImGuiKey_PageDown] = AKEYCODE_PAGE_DOWN;
|
||||
io.KeyMap[ImGuiKey_Home] = AKEYCODE_MOVE_HOME;
|
||||
io.KeyMap[ImGuiKey_End] = AKEYCODE_MOVE_END;
|
||||
io.KeyMap[ImGuiKey_Insert] = AKEYCODE_INSERT;
|
||||
io.KeyMap[ImGuiKey_Delete] = AKEYCODE_FORWARD_DEL;
|
||||
io.KeyMap[ImGuiKey_Backspace] = AKEYCODE_DEL;
|
||||
io.KeyMap[ImGuiKey_Space] = AKEYCODE_SPACE;
|
||||
io.KeyMap[ImGuiKey_Enter] = AKEYCODE_ENTER;
|
||||
io.KeyMap[ImGuiKey_Escape] = AKEYCODE_ESCAPE;
|
||||
io.KeyMap[ImGuiKey_KeyPadEnter] = AKEYCODE_NUMPAD_ENTER;
|
||||
io.KeyMap[ImGuiKey_A] = AKEYCODE_A;
|
||||
io.KeyMap[ImGuiKey_C] = AKEYCODE_C;
|
||||
io.KeyMap[ImGuiKey_V] = AKEYCODE_V;
|
||||
io.KeyMap[ImGuiKey_X] = AKEYCODE_X;
|
||||
io.KeyMap[ImGuiKey_Y] = AKEYCODE_Y;
|
||||
io.KeyMap[ImGuiKey_Z] = AKEYCODE_Z;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplAndroid_Shutdown()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.BackendPlatformName = nullptr;
|
||||
}
|
||||
|
||||
void ImGui_ImplAndroid_NewFrame()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IM_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built! It is generally built by the renderer backend. Missing call to renderer _NewFrame() function? e.g. ImGui_ImplOpenGL3_NewFrame().");
|
||||
|
||||
// Process queued key events
|
||||
// FIXME: This is a workaround for multiple key event actions occurring at once (see above) and can be removed once we use upcoming input queue.
|
||||
for (auto& key_queue : g_KeyEventQueues)
|
||||
{
|
||||
if (key_queue.second.empty())
|
||||
continue;
|
||||
io.KeysDown[key_queue.first] = (key_queue.second.front() == AKEY_EVENT_ACTION_DOWN);
|
||||
key_queue.second.pop();
|
||||
}
|
||||
|
||||
// Setup display size (every frame to accommodate for window resizing)
|
||||
int32_t window_width = ANativeWindow_getWidth(g_Window);
|
||||
@@ -185,3 +302,7 @@ void ImGui_ImplAndroid_NewFrame()
|
||||
io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f / 60.0f);
|
||||
g_Time = current_time;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
@@ -2,25 +2,36 @@
|
||||
// This needs to be used along with the OpenGL 3 Renderer (imgui_impl_opengl3)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Platform: Keyboard arrays indexed using AKEYCODE_* codes, e.g. ImGui::IsKeyPressed(AKEYCODE_SPACE).
|
||||
// Missing features:
|
||||
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy AKEYCODE_* values are obsolete since 1.87 and not supported since 1.91.5]
|
||||
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen.
|
||||
// Missing features or Issues:
|
||||
// [ ] Platform: Clipboard support.
|
||||
// [ ] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
||||
// [ ] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. FIXME: Check if this is even possible with Android.
|
||||
// [ ] Platform: Gamepad support.
|
||||
// [ ] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. FIXME: Check if this is even possible with Android.
|
||||
// Important:
|
||||
// - Consider using SDL or GLFW backend on Android, which will be more full-featured than this.
|
||||
// - FIXME: On-screen keyboard currently needs to be enabled by the application (see examples/ and issue #3446)
|
||||
// - FIXME: Unicode character inputs needs to be passed by Dear ImGui by the application (see examples/ and issue #3446)
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
|
||||
// https://github.com/ocornut/imgui
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
#pragma once
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
struct ANativeWindow;
|
||||
struct AInputEvent;
|
||||
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
IMGUI_IMPL_API bool ImGui_ImplAndroid_Init(ANativeWindow* window);
|
||||
IMGUI_IMPL_API int32_t ImGui_ImplAndroid_HandleInputEvent(AInputEvent* input_event);
|
||||
IMGUI_IMPL_API int32_t ImGui_ImplAndroid_HandleInputEvent(const AInputEvent* input_event);
|
||||
IMGUI_IMPL_API void ImGui_ImplAndroid_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplAndroid_NewFrame();
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
@@ -2,15 +2,29 @@
|
||||
// This needs to be used along with a Platform Backend (e.g. Win32)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture backend. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
|
||||
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
|
||||
// [X] Renderer: User texture binding. Use 'ID3D10ShaderResourceView*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-04-23: DirectX10: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. Obsoleting samplers from ImGui_ImplDX10_RenderState. (#9378)
|
||||
// 2026-01-19: DirectX10: Added 'SamplerNearest' in ImGui_ImplDX10_RenderState. Renamed 'SamplerDefault' to 'SamplerLinear'.
|
||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||
// 2025-06-11: DirectX10: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas.
|
||||
// 2025-05-07: DirectX10: Honor draw_data->FramebufferScale to allow for custom backends and experiment using it (consistently with other renderer backends, even though in normal condition it is not set under Windows).
|
||||
// 2025-01-06: DirectX10: Expose selected render state in ImGui_ImplDX10_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.
|
||||
// 2024-10-07: DirectX10: Changed default texture sampler to Clamp instead of Repeat/Wrap.
|
||||
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
|
||||
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
|
||||
// 2021-05-19: DirectX10: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
|
||||
// 2021-02-18: DirectX10: Change blending equation to preserve alpha in output buffer.
|
||||
// 2019-07-21: DirectX10: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData().
|
||||
@@ -27,6 +41,7 @@
|
||||
// 2016-05-07: DirectX10: Disabling depth-write.
|
||||
|
||||
#include "imgui.h"
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include "imgui_impl_dx10.h"
|
||||
|
||||
// DirectX
|
||||
@@ -38,121 +53,72 @@
|
||||
#pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below.
|
||||
#endif
|
||||
|
||||
// DirectX data
|
||||
static ID3D10Device* g_pd3dDevice = NULL;
|
||||
static IDXGIFactory* g_pFactory = NULL;
|
||||
static ID3D10Buffer* g_pVB = NULL;
|
||||
static ID3D10Buffer* g_pIB = NULL;
|
||||
static ID3D10VertexShader* g_pVertexShader = NULL;
|
||||
static ID3D10InputLayout* g_pInputLayout = NULL;
|
||||
static ID3D10Buffer* g_pVertexConstantBuffer = NULL;
|
||||
static ID3D10PixelShader* g_pPixelShader = NULL;
|
||||
static ID3D10SamplerState* g_pFontSampler = NULL;
|
||||
static ID3D10ShaderResourceView*g_pFontTextureView = NULL;
|
||||
static ID3D10RasterizerState* g_pRasterizerState = NULL;
|
||||
static ID3D10BlendState* g_pBlendState = NULL;
|
||||
static ID3D10DepthStencilState* g_pDepthStencilState = NULL;
|
||||
static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000;
|
||||
// Clang/GCC warnings with -Weverything
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast // yes, they are more terse.
|
||||
#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
|
||||
#endif
|
||||
|
||||
struct VERTEX_CONSTANT_BUFFER
|
||||
// DirectX10 data
|
||||
struct ImGui_ImplDX10_Texture
|
||||
{
|
||||
ID3D10Texture2D* pTexture;
|
||||
ID3D10ShaderResourceView* pTextureView;
|
||||
};
|
||||
|
||||
struct ImGui_ImplDX10_Data
|
||||
{
|
||||
ID3D10Device* pd3dDevice;
|
||||
IDXGIFactory* pFactory;
|
||||
ID3D10Buffer* pVB;
|
||||
ID3D10Buffer* pIB;
|
||||
ID3D10VertexShader* pVertexShader;
|
||||
ID3D10InputLayout* pInputLayout;
|
||||
ID3D10Buffer* pVertexConstantBuffer;
|
||||
ID3D10PixelShader* pPixelShader;
|
||||
ID3D10SamplerState* pTexSamplerLinear;
|
||||
ID3D10SamplerState* pTexSamplerNearest;
|
||||
ID3D10RasterizerState* pRasterizerState;
|
||||
ID3D10BlendState* pBlendState;
|
||||
ID3D10DepthStencilState* pDepthStencilState;
|
||||
int VertexBufferSize;
|
||||
int IndexBufferSize;
|
||||
|
||||
ImGui_ImplDX10_Data() { memset((void*)this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; }
|
||||
};
|
||||
|
||||
struct VERTEX_CONSTANT_BUFFER_DX10
|
||||
{
|
||||
float mvp[4][4];
|
||||
};
|
||||
|
||||
static void ImGui_ImplDX10_SetupRenderState(ImDrawData* draw_data, ID3D10Device* ctx)
|
||||
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
|
||||
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
|
||||
static ImGui_ImplDX10_Data* ImGui_ImplDX10_GetBackendData()
|
||||
{
|
||||
return ImGui::GetCurrentContext() ? (ImGui_ImplDX10_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
|
||||
}
|
||||
|
||||
// Functions
|
||||
static void ImGui_ImplDX10_SetupRenderState(ImDrawData* draw_data, ID3D10Device* device)
|
||||
{
|
||||
ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData();
|
||||
|
||||
// Setup viewport
|
||||
D3D10_VIEWPORT vp;
|
||||
memset(&vp, 0, sizeof(D3D10_VIEWPORT));
|
||||
vp.Width = (UINT)draw_data->DisplaySize.x;
|
||||
vp.Height = (UINT)draw_data->DisplaySize.y;
|
||||
D3D10_VIEWPORT vp = {};
|
||||
vp.Width = (UINT)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
|
||||
vp.Height = (UINT)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
|
||||
vp.MinDepth = 0.0f;
|
||||
vp.MaxDepth = 1.0f;
|
||||
vp.TopLeftX = vp.TopLeftY = 0;
|
||||
ctx->RSSetViewports(1, &vp);
|
||||
|
||||
// Bind shader and vertex buffers
|
||||
unsigned int stride = sizeof(ImDrawVert);
|
||||
unsigned int offset = 0;
|
||||
ctx->IASetInputLayout(g_pInputLayout);
|
||||
ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset);
|
||||
ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);
|
||||
ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
ctx->VSSetShader(g_pVertexShader);
|
||||
ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer);
|
||||
ctx->PSSetShader(g_pPixelShader);
|
||||
ctx->PSSetSamplers(0, 1, &g_pFontSampler);
|
||||
ctx->GSSetShader(NULL);
|
||||
|
||||
// Setup render state
|
||||
const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
|
||||
ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff);
|
||||
ctx->OMSetDepthStencilState(g_pDepthStencilState, 0);
|
||||
ctx->RSSetState(g_pRasterizerState);
|
||||
}
|
||||
|
||||
// Render function
|
||||
void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
|
||||
{
|
||||
// Avoid rendering when minimized
|
||||
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
|
||||
return;
|
||||
|
||||
ID3D10Device* ctx = g_pd3dDevice;
|
||||
|
||||
// Create and grow vertex/index buffers if needed
|
||||
if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount)
|
||||
{
|
||||
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
|
||||
g_VertexBufferSize = draw_data->TotalVtxCount + 5000;
|
||||
D3D10_BUFFER_DESC desc;
|
||||
memset(&desc, 0, sizeof(D3D10_BUFFER_DESC));
|
||||
desc.Usage = D3D10_USAGE_DYNAMIC;
|
||||
desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert);
|
||||
desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
|
||||
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = 0;
|
||||
if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount)
|
||||
{
|
||||
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
|
||||
g_IndexBufferSize = draw_data->TotalIdxCount + 10000;
|
||||
D3D10_BUFFER_DESC desc;
|
||||
memset(&desc, 0, sizeof(D3D10_BUFFER_DESC));
|
||||
desc.Usage = D3D10_USAGE_DYNAMIC;
|
||||
desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx);
|
||||
desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
|
||||
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
|
||||
if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy and convert all vertices into a single contiguous buffer
|
||||
ImDrawVert* vtx_dst = NULL;
|
||||
ImDrawIdx* idx_dst = NULL;
|
||||
g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst);
|
||||
g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst);
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));
|
||||
memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
|
||||
vtx_dst += cmd_list->VtxBuffer.Size;
|
||||
idx_dst += cmd_list->IdxBuffer.Size;
|
||||
}
|
||||
g_pVB->Unmap();
|
||||
g_pIB->Unmap();
|
||||
device->RSSetViewports(1, &vp);
|
||||
|
||||
// Setup orthographic projection matrix into our constant buffer
|
||||
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
|
||||
void* mapped_resource;
|
||||
if (bd->pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) == S_OK)
|
||||
{
|
||||
void* mapped_resource;
|
||||
if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK)
|
||||
return;
|
||||
VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource;
|
||||
VERTEX_CONSTANT_BUFFER_DX10* constant_buffer = (VERTEX_CONSTANT_BUFFER_DX10*)mapped_resource;
|
||||
float L = draw_data->DisplayPos.x;
|
||||
float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
|
||||
float T = draw_data->DisplayPos.y;
|
||||
@@ -165,9 +131,94 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
|
||||
{ (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f },
|
||||
};
|
||||
memcpy(&constant_buffer->mvp, mvp, sizeof(mvp));
|
||||
g_pVertexConstantBuffer->Unmap();
|
||||
bd->pVertexConstantBuffer->Unmap();
|
||||
}
|
||||
|
||||
// Setup shader and vertex buffers
|
||||
unsigned int stride = sizeof(ImDrawVert);
|
||||
unsigned int offset = 0;
|
||||
device->IASetInputLayout(bd->pInputLayout);
|
||||
device->IASetVertexBuffers(0, 1, &bd->pVB, &stride, &offset);
|
||||
device->IASetIndexBuffer(bd->pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);
|
||||
device->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
device->VSSetShader(bd->pVertexShader);
|
||||
device->VSSetConstantBuffers(0, 1, &bd->pVertexConstantBuffer);
|
||||
device->PSSetShader(bd->pPixelShader);
|
||||
device->PSSetSamplers(0, 1, &bd->pTexSamplerLinear);
|
||||
device->GSSetShader(nullptr);
|
||||
|
||||
// Setup render state
|
||||
const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
|
||||
device->OMSetBlendState(bd->pBlendState, blend_factor, 0xffffffff);
|
||||
device->OMSetDepthStencilState(bd->pDepthStencilState, 0);
|
||||
device->RSSetState(bd->pRasterizerState);
|
||||
}
|
||||
|
||||
// Draw callbacks
|
||||
static void ImGui_ImplDX10_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
||||
static void ImGui_ImplDX10_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData(); bd->pd3dDevice->PSSetSamplers(0, 1, &bd->pTexSamplerLinear); }
|
||||
static void ImGui_ImplDX10_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData(); bd->pd3dDevice->PSSetSamplers(0, 1, &bd->pTexSamplerNearest); }
|
||||
|
||||
// Render function
|
||||
void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
|
||||
{
|
||||
// Avoid rendering when minimized
|
||||
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
|
||||
return;
|
||||
|
||||
ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData();
|
||||
ID3D10Device* device = bd->pd3dDevice;
|
||||
|
||||
// Catch up with texture updates. Most of the times, the list will have 1 element with an OK status, aka nothing to do.
|
||||
// (This almost always points to ImGui::GetPlatformIO().Textures[] but is part of ImDrawData to allow overriding or disabling texture updates).
|
||||
if (draw_data->Textures != nullptr)
|
||||
for (ImTextureData* tex : *draw_data->Textures)
|
||||
if (tex->Status != ImTextureStatus_OK)
|
||||
ImGui_ImplDX10_UpdateTexture(tex);
|
||||
|
||||
// Create and grow vertex/index buffers if needed
|
||||
if (!bd->pVB || bd->VertexBufferSize < draw_data->TotalVtxCount)
|
||||
{
|
||||
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
|
||||
bd->VertexBufferSize = draw_data->TotalVtxCount + 5000;
|
||||
D3D10_BUFFER_DESC desc = {};
|
||||
desc.Usage = D3D10_USAGE_DYNAMIC;
|
||||
desc.ByteWidth = (UINT)bd->VertexBufferSize * sizeof(ImDrawVert);
|
||||
desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
|
||||
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = 0;
|
||||
if (device->CreateBuffer(&desc, nullptr, &bd->pVB) < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!bd->pIB || bd->IndexBufferSize < draw_data->TotalIdxCount)
|
||||
{
|
||||
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
|
||||
bd->IndexBufferSize = draw_data->TotalIdxCount + 10000;
|
||||
D3D10_BUFFER_DESC desc = {};
|
||||
desc.Usage = D3D10_USAGE_DYNAMIC;
|
||||
desc.ByteWidth = (UINT)bd->IndexBufferSize * sizeof(ImDrawIdx);
|
||||
desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
|
||||
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
|
||||
if (device->CreateBuffer(&desc, nullptr, &bd->pIB) < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy and convert all vertices into a single contiguous buffer
|
||||
ImDrawVert* vtx_dst = nullptr;
|
||||
ImDrawIdx* idx_dst = nullptr;
|
||||
bd->pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst);
|
||||
bd->pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst);
|
||||
for (const ImDrawList* draw_list : draw_data->CmdLists)
|
||||
{
|
||||
memcpy(vtx_dst, draw_list->VtxBuffer.Data, draw_list->VtxBuffer.Size * sizeof(ImDrawVert));
|
||||
memcpy(idx_dst, draw_list->IdxBuffer.Data, draw_list->IdxBuffer.Size * sizeof(ImDrawIdx));
|
||||
vtx_dst += draw_list->VtxBuffer.Size;
|
||||
idx_dst += draw_list->IdxBuffer.Size;
|
||||
}
|
||||
bd->pVB->Unmap();
|
||||
bd->pIB->Unmap();
|
||||
|
||||
// Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!)
|
||||
struct BACKUP_DX10_STATE
|
||||
{
|
||||
@@ -193,93 +244,124 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
|
||||
};
|
||||
BACKUP_DX10_STATE old = {};
|
||||
old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
|
||||
ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects);
|
||||
ctx->RSGetViewports(&old.ViewportsCount, old.Viewports);
|
||||
ctx->RSGetState(&old.RS);
|
||||
ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask);
|
||||
ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef);
|
||||
ctx->PSGetShaderResources(0, 1, &old.PSShaderResource);
|
||||
ctx->PSGetSamplers(0, 1, &old.PSSampler);
|
||||
ctx->PSGetShader(&old.PS);
|
||||
ctx->VSGetShader(&old.VS);
|
||||
ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer);
|
||||
ctx->GSGetShader(&old.GS);
|
||||
ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology);
|
||||
ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset);
|
||||
ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset);
|
||||
ctx->IAGetInputLayout(&old.InputLayout);
|
||||
device->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects);
|
||||
device->RSGetViewports(&old.ViewportsCount, old.Viewports);
|
||||
device->RSGetState(&old.RS);
|
||||
device->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask);
|
||||
device->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef);
|
||||
device->PSGetShaderResources(0, 1, &old.PSShaderResource);
|
||||
device->PSGetSamplers(0, 1, &old.PSSampler);
|
||||
device->PSGetShader(&old.PS);
|
||||
device->VSGetShader(&old.VS);
|
||||
device->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer);
|
||||
device->GSGetShader(&old.GS);
|
||||
device->IAGetPrimitiveTopology(&old.PrimitiveTopology);
|
||||
device->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset);
|
||||
device->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset);
|
||||
device->IAGetInputLayout(&old.InputLayout);
|
||||
|
||||
// Setup desired DX state
|
||||
ImGui_ImplDX10_SetupRenderState(draw_data, ctx);
|
||||
ImGui_ImplDX10_SetupRenderState(draw_data, device);
|
||||
// Setup render state structure (for callbacks and custom texture bindings)
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
ImGui_ImplDX10_RenderState render_state;
|
||||
render_state.Device = bd->pd3dDevice;
|
||||
render_state.VertexConstantBuffer = bd->pVertexConstantBuffer;
|
||||
platform_io.Renderer_RenderState = &render_state;
|
||||
|
||||
// Render command lists
|
||||
// (Because we merged all buffers into a single one, we maintain our own offset into them)
|
||||
int global_vtx_offset = 0;
|
||||
int global_idx_offset = 0;
|
||||
ImVec2 clip_off = draw_data->DisplayPos;
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
ImVec2 clip_scale = draw_data->FramebufferScale;
|
||||
for (const ImDrawList* draw_list : draw_data->CmdLists)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback)
|
||||
const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback != nullptr)
|
||||
{
|
||||
// User callback, registered via ImDrawList::AddCallback()
|
||||
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
|
||||
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
|
||||
ImGui_ImplDX10_SetupRenderState(draw_data, ctx);
|
||||
if (pcmd->UserCallback == ImGui_ImplDX10_DrawCallback_ResetRenderState)
|
||||
ImGui_ImplDX10_SetupRenderState(draw_data, device);
|
||||
else
|
||||
pcmd->UserCallback(cmd_list, pcmd);
|
||||
pcmd->UserCallback(draw_list, pcmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
|
||||
ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
|
||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||
continue;
|
||||
|
||||
// Apply scissor/clipping rectangle
|
||||
const D3D10_RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y)};
|
||||
ctx->RSSetScissorRects(1, &r);
|
||||
const D3D10_RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y };
|
||||
device->RSSetScissorRects(1, &r);
|
||||
|
||||
// Bind texture, Draw
|
||||
ID3D10ShaderResourceView* texture_srv = (ID3D10ShaderResourceView*)pcmd->GetTexID();
|
||||
ctx->PSSetShaderResources(0, 1, &texture_srv);
|
||||
ctx->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset);
|
||||
device->PSSetShaderResources(0, 1, &texture_srv);
|
||||
device->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset);
|
||||
}
|
||||
}
|
||||
global_idx_offset += cmd_list->IdxBuffer.Size;
|
||||
global_vtx_offset += cmd_list->VtxBuffer.Size;
|
||||
global_idx_offset += draw_list->IdxBuffer.Size;
|
||||
global_vtx_offset += draw_list->VtxBuffer.Size;
|
||||
}
|
||||
platform_io.Renderer_RenderState = nullptr;
|
||||
|
||||
// Restore modified DX state
|
||||
ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects);
|
||||
ctx->RSSetViewports(old.ViewportsCount, old.Viewports);
|
||||
ctx->RSSetState(old.RS); if (old.RS) old.RS->Release();
|
||||
ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release();
|
||||
ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release();
|
||||
ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release();
|
||||
ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release();
|
||||
ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release();
|
||||
ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release();
|
||||
ctx->GSSetShader(old.GS); if (old.GS) old.GS->Release();
|
||||
ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release();
|
||||
ctx->IASetPrimitiveTopology(old.PrimitiveTopology);
|
||||
ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release();
|
||||
ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release();
|
||||
ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release();
|
||||
device->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects);
|
||||
device->RSSetViewports(old.ViewportsCount, old.Viewports);
|
||||
device->RSSetState(old.RS); if (old.RS) old.RS->Release();
|
||||
device->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release();
|
||||
device->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release();
|
||||
device->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release();
|
||||
device->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release();
|
||||
device->PSSetShader(old.PS); if (old.PS) old.PS->Release();
|
||||
device->VSSetShader(old.VS); if (old.VS) old.VS->Release();
|
||||
device->GSSetShader(old.GS); if (old.GS) old.GS->Release();
|
||||
device->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release();
|
||||
device->IASetPrimitiveTopology(old.PrimitiveTopology);
|
||||
device->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release();
|
||||
device->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release();
|
||||
device->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release();
|
||||
}
|
||||
|
||||
static void ImGui_ImplDX10_CreateFontsTexture()
|
||||
static void ImGui_ImplDX10_DestroyTexture(ImTextureData* tex)
|
||||
{
|
||||
// Build texture atlas
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
unsigned char* pixels;
|
||||
int width, height;
|
||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
|
||||
|
||||
// Upload texture to graphics system
|
||||
if (ImGui_ImplDX10_Texture* backend_tex = (ImGui_ImplDX10_Texture*)tex->BackendUserData)
|
||||
{
|
||||
IM_ASSERT(backend_tex->pTextureView == (ID3D10ShaderResourceView*)(intptr_t)tex->TexID);
|
||||
backend_tex->pTextureView->Release();
|
||||
backend_tex->pTexture->Release();
|
||||
IM_DELETE(backend_tex);
|
||||
|
||||
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
|
||||
tex->SetTexID(ImTextureID_Invalid);
|
||||
tex->BackendUserData = nullptr;
|
||||
}
|
||||
tex->SetStatus(ImTextureStatus_Destroyed);
|
||||
}
|
||||
|
||||
void ImGui_ImplDX10_UpdateTexture(ImTextureData* tex)
|
||||
{
|
||||
ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData();
|
||||
if (tex->Status == ImTextureStatus_WantCreate)
|
||||
{
|
||||
// Create and upload new texture to graphics system
|
||||
//IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
|
||||
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == nullptr);
|
||||
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
|
||||
unsigned int* pixels = (unsigned int*)tex->GetPixels();
|
||||
ImGui_ImplDX10_Texture* backend_tex = IM_NEW(ImGui_ImplDX10_Texture)();
|
||||
|
||||
// Create texture
|
||||
D3D10_TEXTURE2D_DESC desc;
|
||||
ZeroMemory(&desc, sizeof(desc));
|
||||
desc.Width = width;
|
||||
desc.Height = height;
|
||||
desc.Width = (UINT)tex->Width;
|
||||
desc.Height = (UINT)tex->Height;
|
||||
desc.MipLevels = 1;
|
||||
desc.ArraySize = 1;
|
||||
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
@@ -288,13 +370,12 @@ static void ImGui_ImplDX10_CreateFontsTexture()
|
||||
desc.BindFlags = D3D10_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = 0;
|
||||
|
||||
ID3D10Texture2D* pTexture = NULL;
|
||||
D3D10_SUBRESOURCE_DATA subResource;
|
||||
subResource.pSysMem = pixels;
|
||||
subResource.SysMemPitch = desc.Width * 4;
|
||||
subResource.SysMemSlicePitch = 0;
|
||||
g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
|
||||
IM_ASSERT(pTexture != NULL);
|
||||
bd->pd3dDevice->CreateTexture2D(&desc, &subResource, &backend_tex->pTexture);
|
||||
IM_ASSERT(backend_tex->pTexture != nullptr && "Backend failed to create texture!");
|
||||
|
||||
// Create texture view
|
||||
D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc;
|
||||
@@ -303,35 +384,37 @@ static void ImGui_ImplDX10_CreateFontsTexture()
|
||||
srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
|
||||
srv_desc.Texture2D.MipLevels = desc.MipLevels;
|
||||
srv_desc.Texture2D.MostDetailedMip = 0;
|
||||
g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView);
|
||||
pTexture->Release();
|
||||
bd->pd3dDevice->CreateShaderResourceView(backend_tex->pTexture, &srv_desc, &backend_tex->pTextureView);
|
||||
IM_ASSERT(backend_tex->pTextureView != nullptr && "Backend failed to create texture!");
|
||||
|
||||
// Store identifiers
|
||||
tex->SetTexID((ImTextureID)(intptr_t)backend_tex->pTextureView);
|
||||
tex->SetStatus(ImTextureStatus_OK);
|
||||
tex->BackendUserData = backend_tex;
|
||||
}
|
||||
|
||||
// Store our identifier
|
||||
io.Fonts->SetTexID((ImTextureID)g_pFontTextureView);
|
||||
|
||||
// Create texture sampler
|
||||
else if (tex->Status == ImTextureStatus_WantUpdates)
|
||||
{
|
||||
D3D10_SAMPLER_DESC desc;
|
||||
ZeroMemory(&desc, sizeof(desc));
|
||||
desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP;
|
||||
desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP;
|
||||
desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP;
|
||||
desc.MipLODBias = 0.f;
|
||||
desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS;
|
||||
desc.MinLOD = 0.f;
|
||||
desc.MaxLOD = 0.f;
|
||||
g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler);
|
||||
// Update selected blocks. We only ever write to textures regions which have never been used before!
|
||||
// This backend choose to use tex->Updates[] but you can use tex->UpdateRect to upload a single region.
|
||||
ImGui_ImplDX10_Texture* backend_tex = (ImGui_ImplDX10_Texture*)tex->BackendUserData;
|
||||
IM_ASSERT(backend_tex->pTextureView == (ID3D10ShaderResourceView*)(intptr_t)tex->TexID);
|
||||
for (ImTextureRect& r : tex->Updates)
|
||||
{
|
||||
D3D10_BOX box = { (UINT)r.x, (UINT)r.y, (UINT)0, (UINT)(r.x + r.w), (UINT)(r.y + r.h), (UINT)1 };
|
||||
bd->pd3dDevice->UpdateSubresource(backend_tex->pTexture, 0, &box, tex->GetPixelsAt(r.x, r.y), (UINT)tex->GetPitch(), 0);
|
||||
}
|
||||
tex->SetStatus(ImTextureStatus_OK);
|
||||
}
|
||||
if (tex->Status == ImTextureStatus_WantDestroy && tex->UnusedFrames > 0)
|
||||
ImGui_ImplDX10_DestroyTexture(tex);
|
||||
}
|
||||
|
||||
bool ImGui_ImplDX10_CreateDeviceObjects()
|
||||
{
|
||||
if (!g_pd3dDevice)
|
||||
ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData();
|
||||
if (!bd->pd3dDevice)
|
||||
return false;
|
||||
if (g_pFontSampler)
|
||||
ImGui_ImplDX10_InvalidateDeviceObjects();
|
||||
ImGui_ImplDX10_InvalidateDeviceObjects();
|
||||
|
||||
// By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A)
|
||||
// If you would like to use this DX10 sample code but remove this dependency you can:
|
||||
@@ -370,9 +453,9 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
|
||||
}";
|
||||
|
||||
ID3DBlob* vertexShaderBlob;
|
||||
if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &vertexShaderBlob, NULL)))
|
||||
if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), nullptr, nullptr, nullptr, "main", "vs_4_0", 0, 0, &vertexShaderBlob, nullptr)))
|
||||
return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
|
||||
if (g_pd3dDevice->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &g_pVertexShader) != S_OK)
|
||||
if (bd->pd3dDevice->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &bd->pVertexShader) != S_OK)
|
||||
{
|
||||
vertexShaderBlob->Release();
|
||||
return false;
|
||||
@@ -381,11 +464,11 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
|
||||
// Create the input layout
|
||||
D3D10_INPUT_ELEMENT_DESC local_layout[] =
|
||||
{
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, pos), D3D10_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, uv), D3D10_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)IM_OFFSETOF(ImDrawVert, col), D3D10_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)offsetof(ImDrawVert, pos), D3D10_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)offsetof(ImDrawVert, uv), D3D10_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)offsetof(ImDrawVert, col), D3D10_INPUT_PER_VERTEX_DATA, 0 },
|
||||
};
|
||||
if (g_pd3dDevice->CreateInputLayout(local_layout, 3, vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK)
|
||||
if (bd->pd3dDevice->CreateInputLayout(local_layout, 3, vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &bd->pInputLayout) != S_OK)
|
||||
{
|
||||
vertexShaderBlob->Release();
|
||||
return false;
|
||||
@@ -394,13 +477,13 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
|
||||
|
||||
// Create the constant buffer
|
||||
{
|
||||
D3D10_BUFFER_DESC desc;
|
||||
desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER);
|
||||
D3D10_BUFFER_DESC desc = {};
|
||||
desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER_DX10);
|
||||
desc.Usage = D3D10_USAGE_DYNAMIC;
|
||||
desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
|
||||
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = 0;
|
||||
g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer);
|
||||
bd->pd3dDevice->CreateBuffer(&desc, nullptr, &bd->pVertexConstantBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -423,9 +506,9 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
|
||||
}";
|
||||
|
||||
ID3DBlob* pixelShaderBlob;
|
||||
if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &pixelShaderBlob, NULL)))
|
||||
if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), nullptr, nullptr, nullptr, "main", "ps_4_0", 0, 0, &pixelShaderBlob, nullptr)))
|
||||
return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
|
||||
if (g_pd3dDevice->CreatePixelShader(pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize(), &g_pPixelShader) != S_OK)
|
||||
if (bd->pd3dDevice->CreatePixelShader(pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize(), &bd->pPixelShader) != S_OK)
|
||||
{
|
||||
pixelShaderBlob->Release();
|
||||
return false;
|
||||
@@ -446,7 +529,7 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
|
||||
desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
|
||||
desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
|
||||
desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
|
||||
g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState);
|
||||
bd->pd3dDevice->CreateBlendState(&desc, &bd->pBlendState);
|
||||
}
|
||||
|
||||
// Create the rasterizer state
|
||||
@@ -457,7 +540,7 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
|
||||
desc.CullMode = D3D10_CULL_NONE;
|
||||
desc.ScissorEnable = true;
|
||||
desc.DepthClipEnable = true;
|
||||
g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState);
|
||||
bd->pd3dDevice->CreateRasterizerState(&desc, &bd->pRasterizerState);
|
||||
}
|
||||
|
||||
// Create depth-stencil State
|
||||
@@ -471,68 +554,118 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
|
||||
desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D10_STENCIL_OP_KEEP;
|
||||
desc.FrontFace.StencilFunc = D3D10_COMPARISON_ALWAYS;
|
||||
desc.BackFace = desc.FrontFace;
|
||||
g_pd3dDevice->CreateDepthStencilState(&desc, &g_pDepthStencilState);
|
||||
bd->pd3dDevice->CreateDepthStencilState(&desc, &bd->pDepthStencilState);
|
||||
}
|
||||
|
||||
ImGui_ImplDX10_CreateFontsTexture();
|
||||
// Create texture sampler
|
||||
// (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
|
||||
{
|
||||
D3D10_SAMPLER_DESC desc;
|
||||
ZeroMemory(&desc, sizeof(desc));
|
||||
desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
desc.AddressU = D3D10_TEXTURE_ADDRESS_CLAMP;
|
||||
desc.AddressV = D3D10_TEXTURE_ADDRESS_CLAMP;
|
||||
desc.AddressW = D3D10_TEXTURE_ADDRESS_CLAMP;
|
||||
desc.MipLODBias = 0.f;
|
||||
desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS;
|
||||
desc.MinLOD = 0.f;
|
||||
desc.MaxLOD = 0.f;
|
||||
bd->pd3dDevice->CreateSamplerState(&desc, &bd->pTexSamplerLinear);
|
||||
desc.Filter = D3D10_FILTER_MIN_MAG_MIP_POINT;
|
||||
bd->pd3dDevice->CreateSamplerState(&desc, &bd->pTexSamplerNearest);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplDX10_InvalidateDeviceObjects()
|
||||
{
|
||||
if (!g_pd3dDevice)
|
||||
ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData();
|
||||
if (!bd->pd3dDevice)
|
||||
return;
|
||||
|
||||
if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; }
|
||||
if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->SetTexID(NULL); } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
|
||||
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
|
||||
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
|
||||
|
||||
if (g_pBlendState) { g_pBlendState->Release(); g_pBlendState = NULL; }
|
||||
if (g_pDepthStencilState) { g_pDepthStencilState->Release(); g_pDepthStencilState = NULL; }
|
||||
if (g_pRasterizerState) { g_pRasterizerState->Release(); g_pRasterizerState = NULL; }
|
||||
if (g_pPixelShader) { g_pPixelShader->Release(); g_pPixelShader = NULL; }
|
||||
if (g_pVertexConstantBuffer) { g_pVertexConstantBuffer->Release(); g_pVertexConstantBuffer = NULL; }
|
||||
if (g_pInputLayout) { g_pInputLayout->Release(); g_pInputLayout = NULL; }
|
||||
if (g_pVertexShader) { g_pVertexShader->Release(); g_pVertexShader = NULL; }
|
||||
// Destroy all textures
|
||||
for (ImTextureData* tex : ImGui::GetPlatformIO().Textures)
|
||||
if (tex->RefCount == 1)
|
||||
ImGui_ImplDX10_DestroyTexture(tex);
|
||||
if (bd->pTexSamplerLinear) { bd->pTexSamplerLinear->Release(); bd->pTexSamplerLinear = nullptr; }
|
||||
if (bd->pTexSamplerNearest) { bd->pTexSamplerNearest->Release(); bd->pTexSamplerNearest = nullptr; }
|
||||
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
|
||||
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
|
||||
if (bd->pBlendState) { bd->pBlendState->Release(); bd->pBlendState = nullptr; }
|
||||
if (bd->pDepthStencilState) { bd->pDepthStencilState->Release(); bd->pDepthStencilState = nullptr; }
|
||||
if (bd->pRasterizerState) { bd->pRasterizerState->Release(); bd->pRasterizerState = nullptr; }
|
||||
if (bd->pPixelShader) { bd->pPixelShader->Release(); bd->pPixelShader = nullptr; }
|
||||
if (bd->pVertexConstantBuffer) { bd->pVertexConstantBuffer->Release(); bd->pVertexConstantBuffer = nullptr; }
|
||||
if (bd->pInputLayout) { bd->pInputLayout->Release(); bd->pInputLayout = nullptr; }
|
||||
if (bd->pVertexShader) { bd->pVertexShader->Release(); bd->pVertexShader = nullptr; }
|
||||
}
|
||||
|
||||
bool ImGui_ImplDX10_Init(ID3D10Device* device)
|
||||
{
|
||||
// Setup backend capabilities flags
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IMGUI_CHECKVERSION();
|
||||
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
||||
|
||||
// Setup backend capabilities flags
|
||||
ImGui_ImplDX10_Data* bd = IM_NEW(ImGui_ImplDX10_Data)();
|
||||
io.BackendRendererUserData = (void*)bd;
|
||||
io.BackendRendererName = "imgui_impl_dx10";
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
||||
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
platform_io.Renderer_TextureMaxWidth = platform_io.Renderer_TextureMaxHeight = D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;
|
||||
platform_io.DrawCallback_ResetRenderState = ImGui_ImplDX10_DrawCallback_ResetRenderState;
|
||||
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplDX10_DrawCallback_SetSamplerLinear;
|
||||
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplDX10_DrawCallback_SetSamplerNearest;
|
||||
|
||||
// Get factory from device
|
||||
IDXGIDevice* pDXGIDevice = NULL;
|
||||
IDXGIAdapter* pDXGIAdapter = NULL;
|
||||
IDXGIFactory* pFactory = NULL;
|
||||
|
||||
IDXGIDevice* pDXGIDevice = nullptr;
|
||||
IDXGIAdapter* pDXGIAdapter = nullptr;
|
||||
IDXGIFactory* pFactory = nullptr;
|
||||
if (device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice)) == S_OK)
|
||||
if (pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter)) == S_OK)
|
||||
if (pDXGIAdapter->GetParent(IID_PPV_ARGS(&pFactory)) == S_OK)
|
||||
{
|
||||
g_pd3dDevice = device;
|
||||
g_pFactory = pFactory;
|
||||
bd->pd3dDevice = device;
|
||||
bd->pFactory = pFactory;
|
||||
}
|
||||
if (pDXGIDevice) pDXGIDevice->Release();
|
||||
if (pDXGIAdapter) pDXGIAdapter->Release();
|
||||
g_pd3dDevice->AddRef();
|
||||
bd->pd3dDevice->AddRef();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplDX10_Shutdown()
|
||||
{
|
||||
ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
ImGui_ImplDX10_InvalidateDeviceObjects();
|
||||
if (g_pFactory) { g_pFactory->Release(); g_pFactory = NULL; }
|
||||
if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
|
||||
if (bd->pFactory) { bd->pFactory->Release(); }
|
||||
if (bd->pd3dDevice) { bd->pd3dDevice->Release(); }
|
||||
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
|
||||
platform_io.ClearRendererHandlers();
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
void ImGui_ImplDX10_NewFrame()
|
||||
{
|
||||
if (!g_pFontSampler)
|
||||
ImGui_ImplDX10_CreateDeviceObjects();
|
||||
ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplDX10_Init()?");
|
||||
|
||||
if (!bd->pVertexShader)
|
||||
if (!ImGui_ImplDX10_CreateDeviceObjects())
|
||||
IM_ASSERT(0 && "ImGui_ImplDX10_CreateDeviceObjects() failed!");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
@@ -2,23 +2,48 @@
|
||||
// This needs to be used along with a Platform Backend (e.g. Win32)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture backend. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
|
||||
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
|
||||
// [X] Renderer: User texture binding. Use 'ID3D10ShaderResourceView*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
#pragma once
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
struct ID3D10Device;
|
||||
struct ID3D10SamplerState;
|
||||
struct ID3D10Buffer;
|
||||
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
IMGUI_IMPL_API bool ImGui_ImplDX10_Init(ID3D10Device* device);
|
||||
IMGUI_IMPL_API void ImGui_ImplDX10_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplDX10_NewFrame();
|
||||
IMGUI_IMPL_API void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data);
|
||||
|
||||
// Use if you want to reset your rendering device without losing Dear ImGui state.
|
||||
IMGUI_IMPL_API void ImGui_ImplDX10_InvalidateDeviceObjects();
|
||||
IMGUI_IMPL_API bool ImGui_ImplDX10_CreateDeviceObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplDX10_InvalidateDeviceObjects();
|
||||
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||
IMGUI_IMPL_API void ImGui_ImplDX10_UpdateTexture(ImTextureData* tex);
|
||||
|
||||
// [BETA] Selected render state data shared with callbacks.
|
||||
// This is temporarily stored in GetPlatformIO().Renderer_RenderState during the ImGui_ImplDX10_RenderDrawData() call.
|
||||
// (Please open an issue if you feel you need access to more data)
|
||||
struct ImGui_ImplDX10_RenderState
|
||||
{
|
||||
ID3D10Device* Device;
|
||||
ID3D10Buffer* VertexConstantBuffer;
|
||||
//ID3D10SamplerState* SamplerLinear; // Use ImDrawList::AddCallback(ImGui::GetPlatform().DrawCallback_SetSamplerLinear)
|
||||
//ID3D10SamplerState* SamplerNearest; // Use ImDrawList::AddCallback(ImGui::GetPlatform().DrawCallback_SetSamplerNearest)
|
||||
};
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
@@ -2,19 +2,35 @@
|
||||
// This needs to be used along with a Platform Backend (e.g. Win32)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
|
||||
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
|
||||
// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-04-23: DirectX11: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. Obsoleting samplers from ImGui_ImplDX11_RenderState. (#9378)
|
||||
// 2026-01-19: DirectX11: Added 'SamplerNearest' in ImGui_ImplDX11_RenderState. Renamed 'SamplerDefault' to 'SamplerLinear'.
|
||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||
// 2025-06-11: DirectX11: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas.
|
||||
// 2025-05-07: DirectX11: Honor draw_data->FramebufferScale to allow for custom backends and experiment using it (consistently with other renderer backends, even though in normal condition it is not set under Windows).
|
||||
// 2025-01-06: DirectX11: Expose VertexConstantBuffer in ImGui_ImplDX11_RenderState. Reset projection matrix in ImDrawCallback_ResetRenderState handler.
|
||||
// 2024-10-07: DirectX11: Changed default texture sampler to Clamp instead of Repeat/Wrap.
|
||||
// 2024-10-07: DirectX11: Expose selected render state in ImGui_ImplDX11_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.
|
||||
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
|
||||
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
|
||||
// 2021-05-19: DirectX11: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
|
||||
// 2021-02-18: DirectX11: Change blending equation to preserve alpha in output buffer.
|
||||
// 2019-08-01: DirectX11: Fixed code querying the Geometry Shader state (would generally error with Debug layer enabled).
|
||||
// 2019-07-21: DirectX11: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData. Clearing Hull/Domain/Compute shaders without backup/restore.
|
||||
// 2019-07-21: DirectX11: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX11_RenderDrawData. Clearing Hull/Domain/Compute shaders without backup/restore.
|
||||
// 2019-05-29: DirectX11: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
|
||||
// 2019-04-30: DirectX11: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
|
||||
// 2018-12-03: Misc: Added #pragma comment statement to automatically link with d3dcompiler.lib when using D3DCompile().
|
||||
@@ -28,6 +44,7 @@
|
||||
// 2016-05-07: DirectX11: Disabling depth-write.
|
||||
|
||||
#include "imgui.h"
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include "imgui_impl_dx11.h"
|
||||
|
||||
// DirectX
|
||||
@@ -38,127 +55,74 @@
|
||||
#pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below.
|
||||
#endif
|
||||
|
||||
// DirectX data
|
||||
static ID3D11Device* g_pd3dDevice = NULL;
|
||||
static ID3D11DeviceContext* g_pd3dDeviceContext = NULL;
|
||||
static IDXGIFactory* g_pFactory = NULL;
|
||||
static ID3D11Buffer* g_pVB = NULL;
|
||||
static ID3D11Buffer* g_pIB = NULL;
|
||||
static ID3D11VertexShader* g_pVertexShader = NULL;
|
||||
static ID3D11InputLayout* g_pInputLayout = NULL;
|
||||
static ID3D11Buffer* g_pVertexConstantBuffer = NULL;
|
||||
static ID3D11PixelShader* g_pPixelShader = NULL;
|
||||
static ID3D11SamplerState* g_pFontSampler = NULL;
|
||||
static ID3D11ShaderResourceView*g_pFontTextureView = NULL;
|
||||
static ID3D11RasterizerState* g_pRasterizerState = NULL;
|
||||
static ID3D11BlendState* g_pBlendState = NULL;
|
||||
static ID3D11DepthStencilState* g_pDepthStencilState = NULL;
|
||||
static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000;
|
||||
// Clang/GCC warnings with -Weverything
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast // yes, they are more terse.
|
||||
#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
|
||||
#endif
|
||||
|
||||
struct VERTEX_CONSTANT_BUFFER
|
||||
// DirectX11 data
|
||||
struct ImGui_ImplDX11_Texture
|
||||
{
|
||||
ID3D11Texture2D* pTexture;
|
||||
ID3D11ShaderResourceView* pTextureView;
|
||||
};
|
||||
|
||||
struct ImGui_ImplDX11_Data
|
||||
{
|
||||
ID3D11Device* pd3dDevice;
|
||||
ID3D11DeviceContext* pd3dDeviceContext;
|
||||
IDXGIFactory* pFactory;
|
||||
ID3D11Buffer* pVB;
|
||||
ID3D11Buffer* pIB;
|
||||
ID3D11VertexShader* pVertexShader;
|
||||
ID3D11InputLayout* pInputLayout;
|
||||
ID3D11Buffer* pVertexConstantBuffer;
|
||||
ID3D11PixelShader* pPixelShader;
|
||||
ID3D11SamplerState* pTexSamplerLinear;
|
||||
ID3D11SamplerState* pTexSamplerNearest;
|
||||
ID3D11RasterizerState* pRasterizerState;
|
||||
ID3D11BlendState* pBlendState;
|
||||
ID3D11DepthStencilState* pDepthStencilState;
|
||||
int VertexBufferSize;
|
||||
int IndexBufferSize;
|
||||
ImGui_ImplDX11_RenderState* RenderState; // == (ImGui_ImplDX11_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState during rendering.
|
||||
|
||||
ImGui_ImplDX11_Data() { memset((void*)this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; }
|
||||
};
|
||||
|
||||
struct VERTEX_CONSTANT_BUFFER_DX11
|
||||
{
|
||||
float mvp[4][4];
|
||||
};
|
||||
|
||||
static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceContext* ctx)
|
||||
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
|
||||
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
|
||||
static ImGui_ImplDX11_Data* ImGui_ImplDX11_GetBackendData()
|
||||
{
|
||||
return ImGui::GetCurrentContext() ? (ImGui_ImplDX11_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
|
||||
}
|
||||
|
||||
// Functions
|
||||
static void ImGui_ImplDX11_SetupRenderState(const ImDrawData* draw_data, ID3D11DeviceContext* device_ctx)
|
||||
{
|
||||
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
|
||||
|
||||
// Setup viewport
|
||||
D3D11_VIEWPORT vp;
|
||||
memset(&vp, 0, sizeof(D3D11_VIEWPORT));
|
||||
vp.Width = draw_data->DisplaySize.x;
|
||||
vp.Height = draw_data->DisplaySize.y;
|
||||
D3D11_VIEWPORT vp = {};
|
||||
vp.Width = draw_data->DisplaySize.x * draw_data->FramebufferScale.x;
|
||||
vp.Height = draw_data->DisplaySize.y * draw_data->FramebufferScale.y;
|
||||
vp.MinDepth = 0.0f;
|
||||
vp.MaxDepth = 1.0f;
|
||||
vp.TopLeftX = vp.TopLeftY = 0;
|
||||
ctx->RSSetViewports(1, &vp);
|
||||
|
||||
// Setup shader and vertex buffers
|
||||
unsigned int stride = sizeof(ImDrawVert);
|
||||
unsigned int offset = 0;
|
||||
ctx->IASetInputLayout(g_pInputLayout);
|
||||
ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset);
|
||||
ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);
|
||||
ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
ctx->VSSetShader(g_pVertexShader, NULL, 0);
|
||||
ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer);
|
||||
ctx->PSSetShader(g_pPixelShader, NULL, 0);
|
||||
ctx->PSSetSamplers(0, 1, &g_pFontSampler);
|
||||
ctx->GSSetShader(NULL, NULL, 0);
|
||||
ctx->HSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used..
|
||||
ctx->DSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used..
|
||||
ctx->CSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used..
|
||||
|
||||
// Setup blend state
|
||||
const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
|
||||
ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff);
|
||||
ctx->OMSetDepthStencilState(g_pDepthStencilState, 0);
|
||||
ctx->RSSetState(g_pRasterizerState);
|
||||
}
|
||||
|
||||
// Render function
|
||||
void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
|
||||
{
|
||||
// Avoid rendering when minimized
|
||||
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
|
||||
return;
|
||||
|
||||
ID3D11DeviceContext* ctx = g_pd3dDeviceContext;
|
||||
|
||||
// Create and grow vertex/index buffers if needed
|
||||
if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount)
|
||||
{
|
||||
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
|
||||
g_VertexBufferSize = draw_data->TotalVtxCount + 5000;
|
||||
D3D11_BUFFER_DESC desc;
|
||||
memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert);
|
||||
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = 0;
|
||||
if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0)
|
||||
return;
|
||||
}
|
||||
if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount)
|
||||
{
|
||||
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
|
||||
g_IndexBufferSize = draw_data->TotalIdxCount + 10000;
|
||||
D3D11_BUFFER_DESC desc;
|
||||
memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx);
|
||||
desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
// Upload vertex/index data into a single contiguous GPU buffer
|
||||
D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource;
|
||||
if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK)
|
||||
return;
|
||||
if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK)
|
||||
return;
|
||||
ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData;
|
||||
ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData;
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));
|
||||
memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
|
||||
vtx_dst += cmd_list->VtxBuffer.Size;
|
||||
idx_dst += cmd_list->IdxBuffer.Size;
|
||||
}
|
||||
ctx->Unmap(g_pVB, 0);
|
||||
ctx->Unmap(g_pIB, 0);
|
||||
device_ctx->RSSetViewports(1, &vp);
|
||||
|
||||
// Setup orthographic projection matrix into our constant buffer
|
||||
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
|
||||
D3D11_MAPPED_SUBRESOURCE mapped_resource;
|
||||
if (device_ctx->Map(bd->pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) == S_OK)
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE mapped_resource;
|
||||
if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK)
|
||||
return;
|
||||
VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData;
|
||||
VERTEX_CONSTANT_BUFFER_DX11* constant_buffer = (VERTEX_CONSTANT_BUFFER_DX11*)mapped_resource.pData;
|
||||
float L = draw_data->DisplayPos.x;
|
||||
float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
|
||||
float T = draw_data->DisplayPos.y;
|
||||
@@ -171,9 +135,99 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
|
||||
{ (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f },
|
||||
};
|
||||
memcpy(&constant_buffer->mvp, mvp, sizeof(mvp));
|
||||
ctx->Unmap(g_pVertexConstantBuffer, 0);
|
||||
device_ctx->Unmap(bd->pVertexConstantBuffer, 0);
|
||||
}
|
||||
|
||||
// Setup shader and vertex buffers
|
||||
unsigned int stride = sizeof(ImDrawVert);
|
||||
unsigned int offset = 0;
|
||||
device_ctx->IASetInputLayout(bd->pInputLayout);
|
||||
device_ctx->IASetVertexBuffers(0, 1, &bd->pVB, &stride, &offset);
|
||||
device_ctx->IASetIndexBuffer(bd->pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);
|
||||
device_ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
device_ctx->VSSetShader(bd->pVertexShader, nullptr, 0);
|
||||
device_ctx->VSSetConstantBuffers(0, 1, &bd->pVertexConstantBuffer);
|
||||
device_ctx->PSSetShader(bd->pPixelShader, nullptr, 0);
|
||||
device_ctx->PSSetSamplers(0, 1, &bd->pTexSamplerLinear);
|
||||
device_ctx->GSSetShader(nullptr, nullptr, 0);
|
||||
device_ctx->HSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used..
|
||||
device_ctx->DSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used..
|
||||
device_ctx->CSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used..
|
||||
|
||||
// Setup render state
|
||||
const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
|
||||
device_ctx->OMSetBlendState(bd->pBlendState, blend_factor, 0xffffffff);
|
||||
device_ctx->OMSetDepthStencilState(bd->pDepthStencilState, 0);
|
||||
device_ctx->RSSetState(bd->pRasterizerState);
|
||||
}
|
||||
|
||||
// Draw callbacks
|
||||
static void ImGui_ImplDX11_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
||||
static void ImGui_ImplDX11_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); bd->RenderState->DeviceContext->PSSetSamplers(0, 1, &bd->pTexSamplerLinear); }
|
||||
static void ImGui_ImplDX11_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); bd->RenderState->DeviceContext->PSSetSamplers(0, 1, &bd->pTexSamplerNearest); }
|
||||
|
||||
// Render function
|
||||
void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
|
||||
{
|
||||
// Avoid rendering when minimized
|
||||
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
|
||||
return;
|
||||
|
||||
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
|
||||
ID3D11DeviceContext* device = bd->pd3dDeviceContext;
|
||||
|
||||
// Catch up with texture updates. Most of the times, the list will have 1 element with an OK status, aka nothing to do.
|
||||
// (This almost always points to ImGui::GetPlatformIO().Textures[] but is part of ImDrawData to allow overriding or disabling texture updates).
|
||||
if (draw_data->Textures != nullptr)
|
||||
for (ImTextureData* tex : *draw_data->Textures)
|
||||
if (tex->Status != ImTextureStatus_OK)
|
||||
ImGui_ImplDX11_UpdateTexture(tex);
|
||||
|
||||
// Create and grow vertex/index buffers if needed
|
||||
if (!bd->pVB || bd->VertexBufferSize < draw_data->TotalVtxCount)
|
||||
{
|
||||
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
|
||||
bd->VertexBufferSize = draw_data->TotalVtxCount + 5000;
|
||||
D3D11_BUFFER_DESC desc = {};
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
desc.ByteWidth = (UINT)bd->VertexBufferSize * sizeof(ImDrawVert);
|
||||
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = 0;
|
||||
if (bd->pd3dDevice->CreateBuffer(&desc, nullptr, &bd->pVB) < 0)
|
||||
return;
|
||||
}
|
||||
if (!bd->pIB || bd->IndexBufferSize < draw_data->TotalIdxCount)
|
||||
{
|
||||
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
|
||||
bd->IndexBufferSize = draw_data->TotalIdxCount + 10000;
|
||||
D3D11_BUFFER_DESC desc = {};
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
desc.ByteWidth = (UINT)bd->IndexBufferSize * sizeof(ImDrawIdx);
|
||||
desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
if (bd->pd3dDevice->CreateBuffer(&desc, nullptr, &bd->pIB) < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
// Upload vertex/index data into a single contiguous GPU buffer
|
||||
D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource;
|
||||
if (device->Map(bd->pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK)
|
||||
return;
|
||||
if (device->Map(bd->pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK)
|
||||
return;
|
||||
ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData;
|
||||
ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData;
|
||||
for (const ImDrawList* draw_list : draw_data->CmdLists)
|
||||
{
|
||||
memcpy(vtx_dst, draw_list->VtxBuffer.Data, draw_list->VtxBuffer.Size * sizeof(ImDrawVert));
|
||||
memcpy(idx_dst, draw_list->IdxBuffer.Data, draw_list->IdxBuffer.Size * sizeof(ImDrawIdx));
|
||||
vtx_dst += draw_list->VtxBuffer.Size;
|
||||
idx_dst += draw_list->IdxBuffer.Size;
|
||||
}
|
||||
device->Unmap(bd->pVB, 0);
|
||||
device->Unmap(bd->pIB, 0);
|
||||
|
||||
// Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!)
|
||||
struct BACKUP_DX11_STATE
|
||||
{
|
||||
@@ -201,97 +255,130 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
|
||||
};
|
||||
BACKUP_DX11_STATE old = {};
|
||||
old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
|
||||
ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects);
|
||||
ctx->RSGetViewports(&old.ViewportsCount, old.Viewports);
|
||||
ctx->RSGetState(&old.RS);
|
||||
ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask);
|
||||
ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef);
|
||||
ctx->PSGetShaderResources(0, 1, &old.PSShaderResource);
|
||||
ctx->PSGetSamplers(0, 1, &old.PSSampler);
|
||||
device->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects);
|
||||
device->RSGetViewports(&old.ViewportsCount, old.Viewports);
|
||||
device->RSGetState(&old.RS);
|
||||
device->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask);
|
||||
device->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef);
|
||||
device->PSGetShaderResources(0, 1, &old.PSShaderResource);
|
||||
device->PSGetSamplers(0, 1, &old.PSSampler);
|
||||
old.PSInstancesCount = old.VSInstancesCount = old.GSInstancesCount = 256;
|
||||
ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount);
|
||||
ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount);
|
||||
ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer);
|
||||
ctx->GSGetShader(&old.GS, old.GSInstances, &old.GSInstancesCount);
|
||||
device->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount);
|
||||
device->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount);
|
||||
device->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer);
|
||||
device->GSGetShader(&old.GS, old.GSInstances, &old.GSInstancesCount);
|
||||
|
||||
ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology);
|
||||
ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset);
|
||||
ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset);
|
||||
ctx->IAGetInputLayout(&old.InputLayout);
|
||||
device->IAGetPrimitiveTopology(&old.PrimitiveTopology);
|
||||
device->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset);
|
||||
device->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset);
|
||||
device->IAGetInputLayout(&old.InputLayout);
|
||||
|
||||
// Setup desired DX state
|
||||
ImGui_ImplDX11_SetupRenderState(draw_data, ctx);
|
||||
ImGui_ImplDX11_SetupRenderState(draw_data, device);
|
||||
|
||||
// Setup render state structure (for callbacks and custom texture bindings)
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
ImGui_ImplDX11_RenderState render_state;
|
||||
render_state.Device = bd->pd3dDevice;
|
||||
render_state.DeviceContext = bd->pd3dDeviceContext;
|
||||
render_state.VertexConstantBuffer = bd->pVertexConstantBuffer;
|
||||
platform_io.Renderer_RenderState = bd->RenderState = &render_state;
|
||||
|
||||
// Render command lists
|
||||
// (Because we merged all buffers into a single one, we maintain our own offset into them)
|
||||
int global_idx_offset = 0;
|
||||
int global_vtx_offset = 0;
|
||||
ImVec2 clip_off = draw_data->DisplayPos;
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
ImVec2 clip_scale = draw_data->FramebufferScale;
|
||||
for (const ImDrawList* draw_list : draw_data->CmdLists)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback != NULL)
|
||||
const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback != nullptr)
|
||||
{
|
||||
// User callback, registered via ImDrawList::AddCallback()
|
||||
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
|
||||
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
|
||||
ImGui_ImplDX11_SetupRenderState(draw_data, ctx);
|
||||
if (pcmd->UserCallback == ImGui_ImplDX11_DrawCallback_ResetRenderState)
|
||||
ImGui_ImplDX11_SetupRenderState(draw_data, device);
|
||||
else
|
||||
pcmd->UserCallback(cmd_list, pcmd);
|
||||
pcmd->UserCallback(draw_list, pcmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
|
||||
ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
|
||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||
continue;
|
||||
|
||||
// Apply scissor/clipping rectangle
|
||||
const D3D11_RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y) };
|
||||
ctx->RSSetScissorRects(1, &r);
|
||||
const D3D11_RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y };
|
||||
device->RSSetScissorRects(1, &r);
|
||||
|
||||
// Bind texture, Draw
|
||||
ID3D11ShaderResourceView* texture_srv = (ID3D11ShaderResourceView*)pcmd->GetTexID();
|
||||
ctx->PSSetShaderResources(0, 1, &texture_srv);
|
||||
ctx->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset);
|
||||
device->PSSetShaderResources(0, 1, &texture_srv);
|
||||
device->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset);
|
||||
}
|
||||
}
|
||||
global_idx_offset += cmd_list->IdxBuffer.Size;
|
||||
global_vtx_offset += cmd_list->VtxBuffer.Size;
|
||||
global_idx_offset += draw_list->IdxBuffer.Size;
|
||||
global_vtx_offset += draw_list->VtxBuffer.Size;
|
||||
}
|
||||
platform_io.Renderer_RenderState = bd->RenderState = nullptr;
|
||||
|
||||
// Restore modified DX state
|
||||
ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects);
|
||||
ctx->RSSetViewports(old.ViewportsCount, old.Viewports);
|
||||
ctx->RSSetState(old.RS); if (old.RS) old.RS->Release();
|
||||
ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release();
|
||||
ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release();
|
||||
ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release();
|
||||
ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release();
|
||||
ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release();
|
||||
device->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects);
|
||||
device->RSSetViewports(old.ViewportsCount, old.Viewports);
|
||||
device->RSSetState(old.RS); if (old.RS) old.RS->Release();
|
||||
device->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release();
|
||||
device->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release();
|
||||
device->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release();
|
||||
device->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release();
|
||||
device->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release();
|
||||
for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release();
|
||||
ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release();
|
||||
ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release();
|
||||
ctx->GSSetShader(old.GS, old.GSInstances, old.GSInstancesCount); if (old.GS) old.GS->Release();
|
||||
device->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release();
|
||||
device->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release();
|
||||
device->GSSetShader(old.GS, old.GSInstances, old.GSInstancesCount); if (old.GS) old.GS->Release();
|
||||
for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release();
|
||||
ctx->IASetPrimitiveTopology(old.PrimitiveTopology);
|
||||
ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release();
|
||||
ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release();
|
||||
ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release();
|
||||
device->IASetPrimitiveTopology(old.PrimitiveTopology);
|
||||
device->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release();
|
||||
device->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release();
|
||||
device->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release();
|
||||
}
|
||||
|
||||
static void ImGui_ImplDX11_CreateFontsTexture()
|
||||
static void ImGui_ImplDX11_DestroyTexture(ImTextureData* tex)
|
||||
{
|
||||
// Build texture atlas
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
unsigned char* pixels;
|
||||
int width, height;
|
||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
|
||||
|
||||
// Upload texture to graphics system
|
||||
if (ImGui_ImplDX11_Texture* backend_tex = (ImGui_ImplDX11_Texture*)tex->BackendUserData)
|
||||
{
|
||||
IM_ASSERT(backend_tex->pTextureView == (ID3D11ShaderResourceView*)(intptr_t)tex->TexID);
|
||||
backend_tex->pTextureView->Release();
|
||||
backend_tex->pTexture->Release();
|
||||
IM_DELETE(backend_tex);
|
||||
|
||||
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
|
||||
tex->SetTexID(ImTextureID_Invalid);
|
||||
tex->BackendUserData = nullptr;
|
||||
}
|
||||
tex->SetStatus(ImTextureStatus_Destroyed);
|
||||
}
|
||||
|
||||
void ImGui_ImplDX11_UpdateTexture(ImTextureData* tex)
|
||||
{
|
||||
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
|
||||
if (tex->Status == ImTextureStatus_WantCreate)
|
||||
{
|
||||
// Create and upload new texture to graphics system
|
||||
//IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
|
||||
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == nullptr);
|
||||
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
|
||||
unsigned int* pixels = (unsigned int*)tex->GetPixels();
|
||||
ImGui_ImplDX11_Texture* backend_tex = IM_NEW(ImGui_ImplDX11_Texture)();
|
||||
|
||||
// Create texture
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
ZeroMemory(&desc, sizeof(desc));
|
||||
desc.Width = width;
|
||||
desc.Height = height;
|
||||
desc.Width = (UINT)tex->Width;
|
||||
desc.Height = (UINT)tex->Height;
|
||||
desc.MipLevels = 1;
|
||||
desc.ArraySize = 1;
|
||||
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
@@ -299,14 +386,12 @@ static void ImGui_ImplDX11_CreateFontsTexture()
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = 0;
|
||||
|
||||
ID3D11Texture2D* pTexture = NULL;
|
||||
D3D11_SUBRESOURCE_DATA subResource;
|
||||
subResource.pSysMem = pixels;
|
||||
subResource.SysMemPitch = desc.Width * 4;
|
||||
subResource.SysMemSlicePitch = 0;
|
||||
g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
|
||||
IM_ASSERT(pTexture != NULL);
|
||||
bd->pd3dDevice->CreateTexture2D(&desc, &subResource, &backend_tex->pTexture);
|
||||
IM_ASSERT(backend_tex->pTexture != nullptr && "Backend failed to create texture!");
|
||||
|
||||
// Create texture view
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
||||
@@ -315,35 +400,37 @@ static void ImGui_ImplDX11_CreateFontsTexture()
|
||||
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
srvDesc.Texture2D.MipLevels = desc.MipLevels;
|
||||
srvDesc.Texture2D.MostDetailedMip = 0;
|
||||
g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView);
|
||||
pTexture->Release();
|
||||
bd->pd3dDevice->CreateShaderResourceView(backend_tex->pTexture, &srvDesc, &backend_tex->pTextureView);
|
||||
IM_ASSERT(backend_tex->pTextureView != nullptr && "Backend failed to create texture!");
|
||||
|
||||
// Store identifiers
|
||||
tex->SetTexID((ImTextureID)(intptr_t)backend_tex->pTextureView);
|
||||
tex->SetStatus(ImTextureStatus_OK);
|
||||
tex->BackendUserData = backend_tex;
|
||||
}
|
||||
|
||||
// Store our identifier
|
||||
io.Fonts->SetTexID((ImTextureID)g_pFontTextureView);
|
||||
|
||||
// Create texture sampler
|
||||
else if (tex->Status == ImTextureStatus_WantUpdates)
|
||||
{
|
||||
D3D11_SAMPLER_DESC desc;
|
||||
ZeroMemory(&desc, sizeof(desc));
|
||||
desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||
desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||
desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||
desc.MipLODBias = 0.f;
|
||||
desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
|
||||
desc.MinLOD = 0.f;
|
||||
desc.MaxLOD = 0.f;
|
||||
g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler);
|
||||
// Update selected blocks. We only ever write to textures regions which have never been used before!
|
||||
// This backend choose to use tex->Updates[] but you can use tex->UpdateRect to upload a single region.
|
||||
ImGui_ImplDX11_Texture* backend_tex = (ImGui_ImplDX11_Texture*)tex->BackendUserData;
|
||||
IM_ASSERT(backend_tex->pTextureView == (ID3D11ShaderResourceView*)(intptr_t)tex->TexID);
|
||||
for (ImTextureRect& r : tex->Updates)
|
||||
{
|
||||
D3D11_BOX box = { (UINT)r.x, (UINT)r.y, (UINT)0, (UINT)(r.x + r.w), (UINT)(r.y + r .h), (UINT)1 };
|
||||
bd->pd3dDeviceContext->UpdateSubresource(backend_tex->pTexture, 0, &box, tex->GetPixelsAt(r.x, r.y), (UINT)tex->GetPitch(), 0);
|
||||
}
|
||||
tex->SetStatus(ImTextureStatus_OK);
|
||||
}
|
||||
if (tex->Status == ImTextureStatus_WantDestroy && tex->UnusedFrames > 0)
|
||||
ImGui_ImplDX11_DestroyTexture(tex);
|
||||
}
|
||||
|
||||
bool ImGui_ImplDX11_CreateDeviceObjects()
|
||||
{
|
||||
if (!g_pd3dDevice)
|
||||
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
|
||||
if (!bd->pd3dDevice)
|
||||
return false;
|
||||
if (g_pFontSampler)
|
||||
ImGui_ImplDX11_InvalidateDeviceObjects();
|
||||
ImGui_ImplDX11_InvalidateDeviceObjects();
|
||||
|
||||
// By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A)
|
||||
// If you would like to use this DX11 sample code but remove this dependency you can:
|
||||
@@ -382,9 +469,9 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
|
||||
}";
|
||||
|
||||
ID3DBlob* vertexShaderBlob;
|
||||
if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &vertexShaderBlob, NULL)))
|
||||
if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), nullptr, nullptr, nullptr, "main", "vs_4_0", 0, 0, &vertexShaderBlob, nullptr)))
|
||||
return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
|
||||
if (g_pd3dDevice->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), NULL, &g_pVertexShader) != S_OK)
|
||||
if (bd->pd3dDevice->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), nullptr, &bd->pVertexShader) != S_OK)
|
||||
{
|
||||
vertexShaderBlob->Release();
|
||||
return false;
|
||||
@@ -393,11 +480,11 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
|
||||
// Create the input layout
|
||||
D3D11_INPUT_ELEMENT_DESC local_layout[] =
|
||||
{
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, pos), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, uv), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)IM_OFFSETOF(ImDrawVert, col), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)offsetof(ImDrawVert, pos), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)offsetof(ImDrawVert, uv), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)offsetof(ImDrawVert, col), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
};
|
||||
if (g_pd3dDevice->CreateInputLayout(local_layout, 3, vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK)
|
||||
if (bd->pd3dDevice->CreateInputLayout(local_layout, 3, vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &bd->pInputLayout) != S_OK)
|
||||
{
|
||||
vertexShaderBlob->Release();
|
||||
return false;
|
||||
@@ -406,13 +493,13 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
|
||||
|
||||
// Create the constant buffer
|
||||
{
|
||||
D3D11_BUFFER_DESC desc;
|
||||
desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER);
|
||||
D3D11_BUFFER_DESC desc = {};
|
||||
desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER_DX11);
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = 0;
|
||||
g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer);
|
||||
bd->pd3dDevice->CreateBuffer(&desc, nullptr, &bd->pVertexConstantBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -435,9 +522,9 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
|
||||
}";
|
||||
|
||||
ID3DBlob* pixelShaderBlob;
|
||||
if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &pixelShaderBlob, NULL)))
|
||||
if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), nullptr, nullptr, nullptr, "main", "ps_4_0", 0, 0, &pixelShaderBlob, nullptr)))
|
||||
return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
|
||||
if (g_pd3dDevice->CreatePixelShader(pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize(), NULL, &g_pPixelShader) != S_OK)
|
||||
if (bd->pd3dDevice->CreatePixelShader(pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize(), nullptr, &bd->pPixelShader) != S_OK)
|
||||
{
|
||||
pixelShaderBlob->Release();
|
||||
return false;
|
||||
@@ -458,7 +545,7 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
|
||||
desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
|
||||
desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
|
||||
desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
|
||||
g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState);
|
||||
bd->pd3dDevice->CreateBlendState(&desc, &bd->pBlendState);
|
||||
}
|
||||
|
||||
// Create the rasterizer state
|
||||
@@ -469,7 +556,7 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
|
||||
desc.CullMode = D3D11_CULL_NONE;
|
||||
desc.ScissorEnable = true;
|
||||
desc.DepthClipEnable = true;
|
||||
g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState);
|
||||
bd->pd3dDevice->CreateRasterizerState(&desc, &bd->pRasterizerState);
|
||||
}
|
||||
|
||||
// Create depth-stencil State
|
||||
@@ -483,71 +570,123 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
|
||||
desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
|
||||
desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
|
||||
desc.BackFace = desc.FrontFace;
|
||||
g_pd3dDevice->CreateDepthStencilState(&desc, &g_pDepthStencilState);
|
||||
bd->pd3dDevice->CreateDepthStencilState(&desc, &bd->pDepthStencilState);
|
||||
}
|
||||
|
||||
ImGui_ImplDX11_CreateFontsTexture();
|
||||
// Create texture sampler
|
||||
// (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
|
||||
{
|
||||
D3D11_SAMPLER_DESC desc;
|
||||
ZeroMemory(&desc, sizeof(desc));
|
||||
desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
desc.MipLODBias = 0.f;
|
||||
desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
|
||||
desc.MinLOD = 0.f;
|
||||
desc.MaxLOD = 0.f;
|
||||
bd->pd3dDevice->CreateSamplerState(&desc, &bd->pTexSamplerLinear);
|
||||
desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
|
||||
bd->pd3dDevice->CreateSamplerState(&desc, &bd->pTexSamplerNearest);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplDX11_InvalidateDeviceObjects()
|
||||
{
|
||||
if (!g_pd3dDevice)
|
||||
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
|
||||
if (!bd->pd3dDevice)
|
||||
return;
|
||||
|
||||
if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; }
|
||||
if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->SetTexID(NULL); } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
|
||||
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
|
||||
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
|
||||
// Destroy all textures
|
||||
for (ImTextureData* tex : ImGui::GetPlatformIO().Textures)
|
||||
if (tex->RefCount == 1)
|
||||
ImGui_ImplDX11_DestroyTexture(tex);
|
||||
|
||||
if (g_pBlendState) { g_pBlendState->Release(); g_pBlendState = NULL; }
|
||||
if (g_pDepthStencilState) { g_pDepthStencilState->Release(); g_pDepthStencilState = NULL; }
|
||||
if (g_pRasterizerState) { g_pRasterizerState->Release(); g_pRasterizerState = NULL; }
|
||||
if (g_pPixelShader) { g_pPixelShader->Release(); g_pPixelShader = NULL; }
|
||||
if (g_pVertexConstantBuffer) { g_pVertexConstantBuffer->Release(); g_pVertexConstantBuffer = NULL; }
|
||||
if (g_pInputLayout) { g_pInputLayout->Release(); g_pInputLayout = NULL; }
|
||||
if (g_pVertexShader) { g_pVertexShader->Release(); g_pVertexShader = NULL; }
|
||||
if (bd->pTexSamplerLinear) { bd->pTexSamplerLinear->Release(); bd->pTexSamplerLinear = nullptr; }
|
||||
if (bd->pTexSamplerNearest) { bd->pTexSamplerNearest->Release(); bd->pTexSamplerNearest = nullptr; }
|
||||
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
|
||||
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
|
||||
if (bd->pBlendState) { bd->pBlendState->Release(); bd->pBlendState = nullptr; }
|
||||
if (bd->pDepthStencilState) { bd->pDepthStencilState->Release(); bd->pDepthStencilState = nullptr; }
|
||||
if (bd->pRasterizerState) { bd->pRasterizerState->Release(); bd->pRasterizerState = nullptr; }
|
||||
if (bd->pPixelShader) { bd->pPixelShader->Release(); bd->pPixelShader = nullptr; }
|
||||
if (bd->pVertexConstantBuffer) { bd->pVertexConstantBuffer->Release(); bd->pVertexConstantBuffer = nullptr; }
|
||||
if (bd->pInputLayout) { bd->pInputLayout->Release(); bd->pInputLayout = nullptr; }
|
||||
if (bd->pVertexShader) { bd->pVertexShader->Release(); bd->pVertexShader = nullptr; }
|
||||
}
|
||||
|
||||
bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context)
|
||||
{
|
||||
// Setup backend capabilities flags
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IMGUI_CHECKVERSION();
|
||||
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
||||
|
||||
// Setup backend capabilities flags
|
||||
ImGui_ImplDX11_Data* bd = IM_NEW(ImGui_ImplDX11_Data)();
|
||||
io.BackendRendererUserData = (void*)bd;
|
||||
io.BackendRendererName = "imgui_impl_dx11";
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
||||
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
platform_io.Renderer_TextureMaxWidth = platform_io.Renderer_TextureMaxHeight = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
|
||||
platform_io.DrawCallback_ResetRenderState = ImGui_ImplDX11_DrawCallback_ResetRenderState;
|
||||
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplDX11_DrawCallback_SetSamplerLinear;
|
||||
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplDX11_DrawCallback_SetSamplerNearest;
|
||||
|
||||
// Get factory from device
|
||||
IDXGIDevice* pDXGIDevice = NULL;
|
||||
IDXGIAdapter* pDXGIAdapter = NULL;
|
||||
IDXGIFactory* pFactory = NULL;
|
||||
IDXGIDevice* pDXGIDevice = nullptr;
|
||||
IDXGIAdapter* pDXGIAdapter = nullptr;
|
||||
IDXGIFactory* pFactory = nullptr;
|
||||
|
||||
if (device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice)) == S_OK)
|
||||
if (pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter)) == S_OK)
|
||||
if (pDXGIAdapter->GetParent(IID_PPV_ARGS(&pFactory)) == S_OK)
|
||||
{
|
||||
g_pd3dDevice = device;
|
||||
g_pd3dDeviceContext = device_context;
|
||||
g_pFactory = pFactory;
|
||||
bd->pd3dDevice = device;
|
||||
bd->pd3dDeviceContext = device_context;
|
||||
bd->pFactory = pFactory;
|
||||
}
|
||||
if (pDXGIDevice) pDXGIDevice->Release();
|
||||
if (pDXGIAdapter) pDXGIAdapter->Release();
|
||||
g_pd3dDevice->AddRef();
|
||||
g_pd3dDeviceContext->AddRef();
|
||||
bd->pd3dDevice->AddRef();
|
||||
bd->pd3dDeviceContext->AddRef();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplDX11_Shutdown()
|
||||
{
|
||||
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
ImGui_ImplDX11_InvalidateDeviceObjects();
|
||||
if (g_pFactory) { g_pFactory->Release(); g_pFactory = NULL; }
|
||||
if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
|
||||
if (g_pd3dDeviceContext) { g_pd3dDeviceContext->Release(); g_pd3dDeviceContext = NULL; }
|
||||
if (bd->pFactory) { bd->pFactory->Release(); }
|
||||
if (bd->pd3dDevice) { bd->pd3dDevice->Release(); }
|
||||
if (bd->pd3dDeviceContext) { bd->pd3dDeviceContext->Release(); }
|
||||
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
|
||||
platform_io.ClearRendererHandlers();
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
void ImGui_ImplDX11_NewFrame()
|
||||
{
|
||||
if (!g_pFontSampler)
|
||||
ImGui_ImplDX11_CreateDeviceObjects();
|
||||
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplDX11_Init()?");
|
||||
|
||||
if (!bd->pVertexShader)
|
||||
if (!ImGui_ImplDX11_CreateDeviceObjects())
|
||||
IM_ASSERT(0 && "ImGui_ImplDX11_CreateDeviceObjects() failed!");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
@@ -2,24 +2,51 @@
|
||||
// This needs to be used along with a Platform Backend (e.g. Win32)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
|
||||
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
|
||||
// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
#pragma once
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
struct ID3D11Device;
|
||||
struct ID3D11DeviceContext;
|
||||
struct ID3D11SamplerState;
|
||||
struct ID3D11Buffer;
|
||||
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
IMGUI_IMPL_API bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context);
|
||||
IMGUI_IMPL_API void ImGui_ImplDX11_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplDX11_NewFrame();
|
||||
IMGUI_IMPL_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data);
|
||||
|
||||
// Use if you want to reset your rendering device without losing Dear ImGui state.
|
||||
IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects();
|
||||
IMGUI_IMPL_API bool ImGui_ImplDX11_CreateDeviceObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects();
|
||||
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||
IMGUI_IMPL_API void ImGui_ImplDX11_UpdateTexture(ImTextureData* tex);
|
||||
|
||||
// [BETA] Selected render state data shared with callbacks.
|
||||
// This is temporarily stored in GetPlatformIO().Renderer_RenderState during the ImGui_ImplDX11_RenderDrawData() call.
|
||||
// (Please open an issue if you feel you need access to more data)
|
||||
struct ImGui_ImplDX11_RenderState
|
||||
{
|
||||
ID3D11Device* Device;
|
||||
ID3D11DeviceContext* DeviceContext;
|
||||
ID3D11Buffer* VertexConstantBuffer;
|
||||
//ID3D11SamplerState* SamplerLinear; // Use ImDrawList::AddCallback(ImGui::GetPlatform().DrawCallback_SetSamplerLinear)
|
||||
//ID3D11SamplerState* SamplerNearest; // Use ImDrawList::AddCallback(ImGui::GetPlatform().DrawCallback_SetSamplerNearest)
|
||||
};
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,47 +2,88 @@
|
||||
// This needs to be used along with a Platform Backend (e.g. Win32)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID!
|
||||
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
|
||||
// [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
|
||||
|
||||
// Important: to compile on 32-bit systems, this backend requires code to be compiled with '#define ImTextureID ImU64'.
|
||||
// This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*.
|
||||
// This define is set in the example .vcxproj file and need to be replicated in your app or by adding it to your imconfig.h file.
|
||||
// The aim of imgui_impl_dx12.h/.cpp is to be usable in your engine without any modification.
|
||||
// IF YOU FEEL YOU NEED TO MAKE ANY CHANGE TO THIS CODE, please share them and your feedback at https://github.com/ocornut/imgui/
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
#pragma once
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include <dxgiformat.h> // DXGI_FORMAT
|
||||
#include <d3d12.h> // D3D12_CPU_DESCRIPTOR_HANDLE
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4471) // a forward declaration of an unscoped enumeration must have an underlying type
|
||||
// Clang/GCC warnings with -Weverything
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast
|
||||
#endif
|
||||
|
||||
enum DXGI_FORMAT;
|
||||
struct ID3D12Device;
|
||||
struct ID3D12DescriptorHeap;
|
||||
struct ID3D12GraphicsCommandList;
|
||||
struct D3D12_CPU_DESCRIPTOR_HANDLE;
|
||||
struct D3D12_GPU_DESCRIPTOR_HANDLE;
|
||||
// Initialization data, for ImGui_ImplDX12_Init()
|
||||
struct ImGui_ImplDX12_InitInfo
|
||||
{
|
||||
ID3D12Device* Device;
|
||||
ID3D12CommandQueue* CommandQueue; // Command queue used for queuing texture uploads.
|
||||
int NumFramesInFlight;
|
||||
DXGI_FORMAT RTVFormat; // RenderTarget format.
|
||||
DXGI_FORMAT DSVFormat; // DepthStencilView format.
|
||||
void* UserData;
|
||||
|
||||
// cmd_list is the command list that the implementation will use to render imgui draw lists.
|
||||
// Before calling the render function, caller must prepare cmd_list by resetting it and setting the appropriate
|
||||
// render target and descriptor heap that contains font_srv_cpu_desc_handle/font_srv_gpu_desc_handle.
|
||||
// font_srv_cpu_desc_handle and font_srv_gpu_desc_handle are handles to a single SRV descriptor to use for the internal font texture.
|
||||
IMGUI_IMPL_API bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format, ID3D12DescriptorHeap* cbv_srv_heap,
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle);
|
||||
// Allocating SRV descriptors for textures is up to the application, so we provide callbacks.
|
||||
// (current version of the backend will only allocate one descriptor, from 1.92 the backend will need to allocate more)
|
||||
ID3D12DescriptorHeap* SrvDescriptorHeap;
|
||||
void (*SrvDescriptorAllocFn)(ImGui_ImplDX12_InitInfo* info, D3D12_CPU_DESCRIPTOR_HANDLE* out_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE* out_gpu_desc_handle);
|
||||
void (*SrvDescriptorFreeFn)(ImGui_ImplDX12_InitInfo* info, D3D12_CPU_DESCRIPTOR_HANDLE cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE gpu_desc_handle);
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE LegacySingleSrvCpuDescriptor; // To facilitate transition from single descriptor to allocator callback, you may use those.
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE LegacySingleSrvGpuDescriptor;
|
||||
#endif
|
||||
|
||||
ImGui_ImplDX12_InitInfo() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
IMGUI_IMPL_API bool ImGui_ImplDX12_Init(ImGui_ImplDX12_InitInfo* info);
|
||||
IMGUI_IMPL_API void ImGui_ImplDX12_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplDX12_NewFrame();
|
||||
IMGUI_IMPL_API void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandList* graphics_command_list);
|
||||
|
||||
// Use if you want to reset your rendering device without losing Dear ImGui state.
|
||||
IMGUI_IMPL_API void ImGui_ImplDX12_InvalidateDeviceObjects();
|
||||
IMGUI_IMPL_API bool ImGui_ImplDX12_CreateDeviceObjects();
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (pop)
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
// Legacy initialization API Obsoleted in 1.91.5
|
||||
// - font_srv_cpu_desc_handle and font_srv_gpu_desc_handle are handles to a single SRV descriptor to use for the internal font texture, they must be in 'srv_descriptor_heap'
|
||||
// - When we introduced the ImGui_ImplDX12_InitInfo struct we also added a 'ID3D12CommandQueue* CommandQueue' field.
|
||||
IMGUI_IMPL_API bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format, ID3D12DescriptorHeap* srv_descriptor_heap, D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle);
|
||||
#endif
|
||||
|
||||
// Use if you want to reset your rendering device without losing Dear ImGui state.
|
||||
IMGUI_IMPL_API bool ImGui_ImplDX12_CreateDeviceObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplDX12_InvalidateDeviceObjects();
|
||||
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||
IMGUI_IMPL_API void ImGui_ImplDX12_UpdateTexture(ImTextureData* tex);
|
||||
|
||||
// [BETA] Selected render state data shared with callbacks.
|
||||
// This is temporarily stored in GetPlatformIO().Renderer_RenderState during the ImGui_ImplDX12_RenderDrawData() call.
|
||||
// (Please open an issue if you feel you need access to more data)
|
||||
struct ImGui_ImplDX12_RenderState
|
||||
{
|
||||
ID3D12Device* Device;
|
||||
ID3D12GraphicsCommandList* CommandList;
|
||||
};
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
@@ -2,15 +2,30 @@
|
||||
// This needs to be used along with a Platform Backend (e.g. Win32)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID!
|
||||
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
|
||||
// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: IMGUI_USE_BGRA_PACKED_COLOR support, as this is the optimal color encoding for DirectX9.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
|
||||
// 2026-03-19: Fixed issue in ImGui_ImplDX9_UpdateTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295, #9310)
|
||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||
// 2025-06-11: DirectX9: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas.
|
||||
// 2024-10-07: DirectX9: Changed default texture sampler to Clamp instead of Repeat/Wrap.
|
||||
// 2024-02-12: DirectX9: Using RGBA format when supported by the driver to avoid CPU side conversion. (#6575)
|
||||
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
|
||||
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
|
||||
// 2021-06-25: DirectX9: Explicitly disable texture state stages after >= 1.
|
||||
// 2021-05-19: DirectX9: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
|
||||
// 2021-04-23: DirectX9: Explicitly setting up more graphics states to increase compatibility with unusual non-default states.
|
||||
// 2021-03-18: DirectX9: Calling IDirect3DStateBlock9::Capture() after CreateStateBlock() as a workaround for state restoring issues (see #3857).
|
||||
@@ -28,17 +43,30 @@
|
||||
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
|
||||
|
||||
#include "imgui.h"
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include "imgui_impl_dx9.h"
|
||||
|
||||
// DirectX
|
||||
#include <d3d9.h>
|
||||
|
||||
// Clang/GCC warnings with -Weverything
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast // yes, they are more terse.
|
||||
#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
|
||||
#endif
|
||||
|
||||
// DirectX data
|
||||
static LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;
|
||||
static LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL;
|
||||
static LPDIRECT3DINDEXBUFFER9 g_pIB = NULL;
|
||||
static LPDIRECT3DTEXTURE9 g_FontTexture = NULL;
|
||||
static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000;
|
||||
struct ImGui_ImplDX9_Data
|
||||
{
|
||||
LPDIRECT3DDEVICE9 pd3dDevice;
|
||||
LPDIRECT3DVERTEXBUFFER9 pVB;
|
||||
LPDIRECT3DINDEXBUFFER9 pIB;
|
||||
int VertexBufferSize;
|
||||
int IndexBufferSize;
|
||||
bool HasRgbaSupport;
|
||||
|
||||
ImGui_ImplDX9_Data() { memset((void*)this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; }
|
||||
};
|
||||
|
||||
struct CUSTOMVERTEX
|
||||
{
|
||||
@@ -54,8 +82,18 @@ struct CUSTOMVERTEX
|
||||
#define IMGUI_COL_TO_DX9_ARGB(_COL) (((_COL) & 0xFF00FF00) | (((_COL) & 0xFF0000) >> 16) | (((_COL) & 0xFF) << 16))
|
||||
#endif
|
||||
|
||||
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
|
||||
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
|
||||
static ImGui_ImplDX9_Data* ImGui_ImplDX9_GetBackendData()
|
||||
{
|
||||
return ImGui::GetCurrentContext() ? (ImGui_ImplDX9_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
|
||||
}
|
||||
|
||||
// Functions
|
||||
static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data)
|
||||
{
|
||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
||||
|
||||
// Setup viewport
|
||||
D3DVIEWPORT9 vp;
|
||||
vp.X = vp.Y = 0;
|
||||
@@ -63,39 +101,45 @@ static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data)
|
||||
vp.Height = (DWORD)draw_data->DisplaySize.y;
|
||||
vp.MinZ = 0.0f;
|
||||
vp.MaxZ = 1.0f;
|
||||
g_pd3dDevice->SetViewport(&vp);
|
||||
|
||||
// Setup render state: fixed-pipeline, alpha-blending, no face culling, no depth testing, shade mode (for gradient)
|
||||
g_pd3dDevice->SetPixelShader(NULL);
|
||||
g_pd3dDevice->SetVertexShader(NULL);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_INVSRCALPHA);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_FOGENABLE, FALSE);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_RANGEFOGENABLE, FALSE);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_SPECULARENABLE, FALSE);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_CLIPPING, TRUE);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
|
||||
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
||||
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
||||
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
|
||||
g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
|
||||
g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
|
||||
g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
|
||||
g_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
|
||||
g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||
LPDIRECT3DDEVICE9 device = bd->pd3dDevice;
|
||||
device->SetViewport(&vp);
|
||||
|
||||
// Setup render state: fixed-pipeline, alpha-blending, no face culling, no depth testing, shade mode (for gradient), bilinear sampling.
|
||||
device->SetPixelShader(nullptr);
|
||||
device->SetVertexShader(nullptr);
|
||||
device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
|
||||
device->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
|
||||
device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
|
||||
device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
|
||||
device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
||||
device->SetRenderState(D3DRS_ZENABLE, FALSE);
|
||||
device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
|
||||
device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
||||
device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||||
device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
|
||||
device->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE);
|
||||
device->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_INVSRCALPHA);
|
||||
device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
|
||||
device->SetRenderState(D3DRS_FOGENABLE, FALSE);
|
||||
device->SetRenderState(D3DRS_RANGEFOGENABLE, FALSE);
|
||||
device->SetRenderState(D3DRS_SPECULARENABLE, FALSE);
|
||||
device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
|
||||
device->SetRenderState(D3DRS_CLIPPING, TRUE);
|
||||
device->SetRenderState(D3DRS_LIGHTING, FALSE);
|
||||
device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
||||
device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
||||
device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
|
||||
device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
|
||||
device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
|
||||
device->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
|
||||
device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
device->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
|
||||
device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
|
||||
device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||
device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
|
||||
device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
|
||||
|
||||
// Setup orthographic projection matrix
|
||||
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
|
||||
@@ -113,12 +157,17 @@ static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data)
|
||||
0.0f, 0.0f, 0.5f, 0.0f,
|
||||
(L+R)/(L-R), (T+B)/(B-T), 0.5f, 1.0f
|
||||
} } };
|
||||
g_pd3dDevice->SetTransform(D3DTS_WORLD, &mat_identity);
|
||||
g_pd3dDevice->SetTransform(D3DTS_VIEW, &mat_identity);
|
||||
g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat_projection);
|
||||
device->SetTransform(D3DTS_WORLD, &mat_identity);
|
||||
device->SetTransform(D3DTS_VIEW, &mat_identity);
|
||||
device->SetTransform(D3DTS_PROJECTION, &mat_projection);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw callbacks
|
||||
static void ImGui_ImplDX9_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
||||
static void ImGui_ImplDX9_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData(); bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); }
|
||||
static void ImGui_ImplDX9_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData(); bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); }
|
||||
|
||||
// Render function.
|
||||
void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
|
||||
{
|
||||
@@ -126,50 +175,60 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
|
||||
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
|
||||
return;
|
||||
|
||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
||||
LPDIRECT3DDEVICE9 device = bd->pd3dDevice;
|
||||
|
||||
// Catch up with texture updates. Most of the times, the list will have 1 element with an OK status, aka nothing to do.
|
||||
// (This almost always points to ImGui::GetPlatformIO().Textures[] but is part of ImDrawData to allow overriding or disabling texture updates).
|
||||
if (draw_data->Textures != nullptr)
|
||||
for (ImTextureData* tex : *draw_data->Textures)
|
||||
if (tex->Status != ImTextureStatus_OK)
|
||||
ImGui_ImplDX9_UpdateTexture(tex);
|
||||
|
||||
// Create and grow buffers if needed
|
||||
if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount)
|
||||
if (!bd->pVB || bd->VertexBufferSize < draw_data->TotalVtxCount)
|
||||
{
|
||||
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
|
||||
g_VertexBufferSize = draw_data->TotalVtxCount + 5000;
|
||||
if (g_pd3dDevice->CreateVertexBuffer(g_VertexBufferSize * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL) < 0)
|
||||
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
|
||||
bd->VertexBufferSize = draw_data->TotalVtxCount + 5000;
|
||||
if (device->CreateVertexBuffer((UINT)bd->VertexBufferSize * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &bd->pVB, nullptr) < 0)
|
||||
return;
|
||||
}
|
||||
if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount)
|
||||
if (!bd->pIB || bd->IndexBufferSize < draw_data->TotalIdxCount)
|
||||
{
|
||||
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
|
||||
g_IndexBufferSize = draw_data->TotalIdxCount + 10000;
|
||||
if (g_pd3dDevice->CreateIndexBuffer(g_IndexBufferSize * sizeof(ImDrawIdx), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, sizeof(ImDrawIdx) == 2 ? D3DFMT_INDEX16 : D3DFMT_INDEX32, D3DPOOL_DEFAULT, &g_pIB, NULL) < 0)
|
||||
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
|
||||
bd->IndexBufferSize = draw_data->TotalIdxCount + 10000;
|
||||
if (device->CreateIndexBuffer((UINT)bd->IndexBufferSize * sizeof(ImDrawIdx), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, sizeof(ImDrawIdx) == 2 ? D3DFMT_INDEX16 : D3DFMT_INDEX32, D3DPOOL_DEFAULT, &bd->pIB, nullptr) < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
// Backup the DX9 state
|
||||
IDirect3DStateBlock9* d3d9_state_block = NULL;
|
||||
if (g_pd3dDevice->CreateStateBlock(D3DSBT_ALL, &d3d9_state_block) < 0)
|
||||
IDirect3DStateBlock9* state_block = nullptr;
|
||||
if (device->CreateStateBlock(D3DSBT_ALL, &state_block) < 0)
|
||||
return;
|
||||
if (d3d9_state_block->Capture() < 0)
|
||||
if (state_block->Capture() < 0)
|
||||
{
|
||||
d3d9_state_block->Release();
|
||||
state_block->Release();
|
||||
return;
|
||||
}
|
||||
|
||||
// Backup the DX9 transform (DX9 documentation suggests that it is included in the StateBlock but it doesn't appear to)
|
||||
D3DMATRIX last_world, last_view, last_projection;
|
||||
g_pd3dDevice->GetTransform(D3DTS_WORLD, &last_world);
|
||||
g_pd3dDevice->GetTransform(D3DTS_VIEW, &last_view);
|
||||
g_pd3dDevice->GetTransform(D3DTS_PROJECTION, &last_projection);
|
||||
device->GetTransform(D3DTS_WORLD, &last_world);
|
||||
device->GetTransform(D3DTS_VIEW, &last_view);
|
||||
device->GetTransform(D3DTS_PROJECTION, &last_projection);
|
||||
|
||||
// Allocate buffers
|
||||
CUSTOMVERTEX* vtx_dst;
|
||||
ImDrawIdx* idx_dst;
|
||||
if (g_pVB->Lock(0, (UINT)(draw_data->TotalVtxCount * sizeof(CUSTOMVERTEX)), (void**)&vtx_dst, D3DLOCK_DISCARD) < 0)
|
||||
if (bd->pVB->Lock(0, (UINT)(draw_data->TotalVtxCount * sizeof(CUSTOMVERTEX)), (void**)&vtx_dst, D3DLOCK_DISCARD) < 0)
|
||||
{
|
||||
d3d9_state_block->Release();
|
||||
state_block->Release();
|
||||
return;
|
||||
}
|
||||
if (g_pIB->Lock(0, (UINT)(draw_data->TotalIdxCount * sizeof(ImDrawIdx)), (void**)&idx_dst, D3DLOCK_DISCARD) < 0)
|
||||
if (bd->pIB->Lock(0, (UINT)(draw_data->TotalIdxCount * sizeof(ImDrawIdx)), (void**)&idx_dst, D3DLOCK_DISCARD) < 0)
|
||||
{
|
||||
g_pVB->Unlock();
|
||||
d3d9_state_block->Release();
|
||||
bd->pVB->Unlock();
|
||||
state_block->Release();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -177,11 +236,10 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
|
||||
// FIXME-OPT: This is a minor waste of resource, the ideal is to use imconfig.h and
|
||||
// 1) to avoid repacking colors: #define IMGUI_USE_BGRA_PACKED_COLOR
|
||||
// 2) to avoid repacking vertices: #define IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT struct ImDrawVert { ImVec2 pos; float z; ImU32 col; ImVec2 uv; }
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
for (const ImDrawList* draw_list : draw_data->CmdLists)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
const ImDrawVert* vtx_src = cmd_list->VtxBuffer.Data;
|
||||
for (int i = 0; i < cmd_list->VtxBuffer.Size; i++)
|
||||
const ImDrawVert* vtx_src = draw_list->VtxBuffer.Data;
|
||||
for (int i = 0; i < draw_list->VtxBuffer.Size; i++)
|
||||
{
|
||||
vtx_dst->pos[0] = vtx_src->pos.x;
|
||||
vtx_dst->pos[1] = vtx_src->pos.y;
|
||||
@@ -192,14 +250,14 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
|
||||
vtx_dst++;
|
||||
vtx_src++;
|
||||
}
|
||||
memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
|
||||
idx_dst += cmd_list->IdxBuffer.Size;
|
||||
memcpy(idx_dst, draw_list->IdxBuffer.Data, draw_list->IdxBuffer.Size * sizeof(ImDrawIdx));
|
||||
idx_dst += draw_list->IdxBuffer.Size;
|
||||
}
|
||||
g_pVB->Unlock();
|
||||
g_pIB->Unlock();
|
||||
g_pd3dDevice->SetStreamSource(0, g_pVB, 0, sizeof(CUSTOMVERTEX));
|
||||
g_pd3dDevice->SetIndices(g_pIB);
|
||||
g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
|
||||
bd->pVB->Unlock();
|
||||
bd->pIB->Unlock();
|
||||
device->SetStreamSource(0, bd->pVB, 0, sizeof(CUSTOMVERTEX));
|
||||
device->SetIndices(bd->pIB);
|
||||
device->SetFVF(D3DFVF_CUSTOMVERTEX);
|
||||
|
||||
// Setup desired DX state
|
||||
ImGui_ImplDX9_SetupRenderState(draw_data);
|
||||
@@ -209,123 +267,225 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
|
||||
int global_vtx_offset = 0;
|
||||
int global_idx_offset = 0;
|
||||
ImVec2 clip_off = draw_data->DisplayPos;
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
for (const ImDrawList* draw_list : draw_data->CmdLists)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback != NULL)
|
||||
const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback != nullptr)
|
||||
{
|
||||
// User callback, registered via ImDrawList::AddCallback()
|
||||
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
|
||||
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
|
||||
if (pcmd->UserCallback == ImGui_ImplDX9_DrawCallback_ResetRenderState)
|
||||
ImGui_ImplDX9_SetupRenderState(draw_data);
|
||||
else
|
||||
pcmd->UserCallback(cmd_list, pcmd);
|
||||
pcmd->UserCallback(draw_list, pcmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
const RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y) };
|
||||
// Project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y);
|
||||
ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y);
|
||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||
continue;
|
||||
|
||||
// Apply scissor/clipping rectangle
|
||||
const RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y };
|
||||
device->SetScissorRect(&r);
|
||||
|
||||
// Bind texture, Draw
|
||||
const LPDIRECT3DTEXTURE9 texture = (LPDIRECT3DTEXTURE9)pcmd->GetTexID();
|
||||
g_pd3dDevice->SetTexture(0, texture);
|
||||
g_pd3dDevice->SetScissorRect(&r);
|
||||
g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, pcmd->VtxOffset + global_vtx_offset, 0, (UINT)cmd_list->VtxBuffer.Size, pcmd->IdxOffset + global_idx_offset, pcmd->ElemCount / 3);
|
||||
device->SetTexture(0, texture);
|
||||
device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, pcmd->VtxOffset + global_vtx_offset, 0, (UINT)draw_list->VtxBuffer.Size, pcmd->IdxOffset + global_idx_offset, pcmd->ElemCount / 3);
|
||||
}
|
||||
}
|
||||
global_idx_offset += cmd_list->IdxBuffer.Size;
|
||||
global_vtx_offset += cmd_list->VtxBuffer.Size;
|
||||
global_idx_offset += draw_list->IdxBuffer.Size;
|
||||
global_vtx_offset += draw_list->VtxBuffer.Size;
|
||||
}
|
||||
|
||||
// Restore the DX9 transform
|
||||
g_pd3dDevice->SetTransform(D3DTS_WORLD, &last_world);
|
||||
g_pd3dDevice->SetTransform(D3DTS_VIEW, &last_view);
|
||||
g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &last_projection);
|
||||
device->SetTransform(D3DTS_WORLD, &last_world);
|
||||
device->SetTransform(D3DTS_VIEW, &last_view);
|
||||
device->SetTransform(D3DTS_PROJECTION, &last_projection);
|
||||
|
||||
// Restore the DX9 state
|
||||
d3d9_state_block->Apply();
|
||||
d3d9_state_block->Release();
|
||||
state_block->Apply();
|
||||
state_block->Release();
|
||||
}
|
||||
|
||||
bool ImGui_ImplDX9_Init(IDirect3DDevice9* device)
|
||||
static bool ImGui_ImplDX9_CheckFormatSupport(LPDIRECT3DDEVICE9 pDevice, D3DFORMAT format)
|
||||
{
|
||||
// Setup backend capabilities flags
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.BackendRendererName = "imgui_impl_dx9";
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
|
||||
g_pd3dDevice = device;
|
||||
g_pd3dDevice->AddRef();
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplDX9_Shutdown()
|
||||
{
|
||||
ImGui_ImplDX9_InvalidateDeviceObjects();
|
||||
if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
|
||||
}
|
||||
|
||||
static bool ImGui_ImplDX9_CreateFontsTexture()
|
||||
{
|
||||
// Build texture atlas
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
unsigned char* pixels;
|
||||
int width, height, bytes_per_pixel;
|
||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height, &bytes_per_pixel);
|
||||
|
||||
// Convert RGBA32 to BGRA32 (because RGBA32 is not well supported by DX9 devices)
|
||||
#ifndef IMGUI_USE_BGRA_PACKED_COLOR
|
||||
if (io.Fonts->TexPixelsUseColors)
|
||||
LPDIRECT3D9 pd3d = nullptr;
|
||||
if (pDevice->GetDirect3D(&pd3d) != D3D_OK)
|
||||
return false;
|
||||
D3DDEVICE_CREATION_PARAMETERS param = {};
|
||||
D3DDISPLAYMODE mode = {};
|
||||
if (pDevice->GetCreationParameters(¶m) != D3D_OK || pDevice->GetDisplayMode(0, &mode) != D3D_OK)
|
||||
{
|
||||
ImU32* dst_start = (ImU32*)ImGui::MemAlloc(width * height * bytes_per_pixel);
|
||||
for (ImU32* src = (ImU32*)pixels, *dst = dst_start, *dst_end = dst_start + width * height; dst < dst_end; src++, dst++)
|
||||
*dst = IMGUI_COL_TO_DX9_ARGB(*src);
|
||||
pixels = (unsigned char*)dst_start;
|
||||
pd3d->Release();
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Upload texture to graphics system
|
||||
g_FontTexture = NULL;
|
||||
if (g_pd3dDevice->CreateTexture(width, height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &g_FontTexture, NULL) < 0)
|
||||
return false;
|
||||
D3DLOCKED_RECT tex_locked_rect;
|
||||
if (g_FontTexture->LockRect(0, &tex_locked_rect, NULL, 0) != D3D_OK)
|
||||
return false;
|
||||
for (int y = 0; y < height; y++)
|
||||
memcpy((unsigned char*)tex_locked_rect.pBits + tex_locked_rect.Pitch * y, pixels + (width * bytes_per_pixel) * y, (width * bytes_per_pixel));
|
||||
g_FontTexture->UnlockRect(0);
|
||||
|
||||
// Store our identifier
|
||||
io.Fonts->SetTexID((ImTextureID)g_FontTexture);
|
||||
// Font texture should support linear filter, color blend and write to render-target
|
||||
bool support = (pd3d->CheckDeviceFormat(param.AdapterOrdinal, param.DeviceType, mode.Format, D3DUSAGE_DYNAMIC | D3DUSAGE_QUERY_FILTER | D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, D3DRTYPE_TEXTURE, format)) == D3D_OK;
|
||||
pd3d->Release();
|
||||
return support;
|
||||
}
|
||||
|
||||
// Convert RGBA32 to BGRA32 (because RGBA32 is not well supported by DX9 devices)
|
||||
static void ImGui_ImplDX9_CopyTextureRegion(bool tex_use_colors, const ImU32* src, int src_pitch, ImU32* dst, int dst_pitch, int w, int h)
|
||||
{
|
||||
#ifndef IMGUI_USE_BGRA_PACKED_COLOR
|
||||
if (io.Fonts->TexPixelsUseColors)
|
||||
ImGui::MemFree(pixels);
|
||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
||||
const bool convert_rgba_to_bgra = (!bd->HasRgbaSupport && tex_use_colors);
|
||||
#else
|
||||
const bool convert_rgba_to_bgra = false;
|
||||
IM_UNUSED(tex_use_colors);
|
||||
#endif
|
||||
for (int y = 0; y < h; y++)
|
||||
{
|
||||
const ImU32* src_p = (const ImU32*)(const void*)((const unsigned char*)src + src_pitch * y);
|
||||
ImU32* dst_p = (ImU32*)(void*)((unsigned char*)dst + dst_pitch * y);
|
||||
if (convert_rgba_to_bgra)
|
||||
for (int x = w; x > 0; x--, src_p++, dst_p++) // Convert copy
|
||||
*dst_p = IMGUI_COL_TO_DX9_ARGB(*src_p);
|
||||
else
|
||||
memcpy(dst_p, src_p, w * 4); // Raw copy
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
void ImGui_ImplDX9_UpdateTexture(ImTextureData* tex)
|
||||
{
|
||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
||||
|
||||
if (tex->Status == ImTextureStatus_WantCreate)
|
||||
{
|
||||
// Create and upload new texture to graphics system
|
||||
//IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
|
||||
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == nullptr);
|
||||
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
|
||||
LPDIRECT3DTEXTURE9 dx_tex = nullptr;
|
||||
HRESULT hr = bd->pd3dDevice->CreateTexture(tex->Width, tex->Height, 1, D3DUSAGE_DYNAMIC, bd->HasRgbaSupport ? D3DFMT_A8B8G8R8 : D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &dx_tex, nullptr);
|
||||
if (hr < 0)
|
||||
{
|
||||
IM_ASSERT(hr >= 0 && "Backend failed to create texture!");
|
||||
return;
|
||||
}
|
||||
|
||||
D3DLOCKED_RECT locked_rect;
|
||||
if (dx_tex->LockRect(0, &locked_rect, nullptr, 0) == D3D_OK)
|
||||
{
|
||||
ImGui_ImplDX9_CopyTextureRegion(tex->UseColors, (ImU32*)tex->GetPixels(), tex->Width * 4, (ImU32*)locked_rect.pBits, (ImU32)locked_rect.Pitch, tex->Width, tex->Height);
|
||||
dx_tex->UnlockRect(0);
|
||||
}
|
||||
|
||||
// Store identifiers
|
||||
tex->SetTexID((ImTextureID)(intptr_t)dx_tex);
|
||||
tex->SetStatus(ImTextureStatus_OK);
|
||||
}
|
||||
else if (tex->Status == ImTextureStatus_WantUpdates)
|
||||
{
|
||||
// Update selected blocks. We only ever write to textures regions which have never been used before!
|
||||
// This backend choose to use tex->Updates[] but you can use tex->UpdateRect to upload a single region.
|
||||
LPDIRECT3DTEXTURE9 backend_tex = (LPDIRECT3DTEXTURE9)(intptr_t)tex->TexID;
|
||||
RECT update_rect = { (LONG)tex->UpdateRect.x, (LONG)tex->UpdateRect.y, (LONG)(tex->UpdateRect.x + tex->UpdateRect.w), (LONG)(tex->UpdateRect.y + tex->UpdateRect.h) };
|
||||
D3DLOCKED_RECT locked_rect;
|
||||
if (backend_tex->LockRect(0, &locked_rect, &update_rect, 0) == D3D_OK)
|
||||
for (ImTextureRect& r : tex->Updates)
|
||||
ImGui_ImplDX9_CopyTextureRegion(tex->UseColors, (ImU32*)tex->GetPixelsAt(r.x, r.y), tex->Width * 4,
|
||||
(ImU32*)locked_rect.pBits + (r.x - update_rect.left) + (r.y - update_rect.top) * (locked_rect.Pitch / 4), (int)locked_rect.Pitch, r.w, r.h);
|
||||
backend_tex->UnlockRect(0);
|
||||
tex->SetStatus(ImTextureStatus_OK);
|
||||
}
|
||||
else if (tex->Status == ImTextureStatus_WantDestroy)
|
||||
{
|
||||
if (tex->TexID != ImTextureID_Invalid)
|
||||
if (LPDIRECT3DTEXTURE9 backend_tex = (LPDIRECT3DTEXTURE9)tex->TexID)
|
||||
{
|
||||
IM_ASSERT(tex->TexID == (ImTextureID)(intptr_t)backend_tex);
|
||||
backend_tex->Release();
|
||||
|
||||
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
|
||||
tex->SetTexID(ImTextureID_Invalid);
|
||||
}
|
||||
tex->SetStatus(ImTextureStatus_Destroyed);
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGui_ImplDX9_CreateDeviceObjects()
|
||||
{
|
||||
if (!g_pd3dDevice)
|
||||
return false;
|
||||
if (!ImGui_ImplDX9_CreateFontsTexture())
|
||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
||||
if (!bd || !bd->pd3dDevice)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplDX9_InvalidateDeviceObjects()
|
||||
{
|
||||
if (!g_pd3dDevice)
|
||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
||||
if (!bd || !bd->pd3dDevice)
|
||||
return;
|
||||
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
|
||||
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
|
||||
if (g_FontTexture) { g_FontTexture->Release(); g_FontTexture = NULL; ImGui::GetIO().Fonts->SetTexID(NULL); } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
|
||||
|
||||
// Destroy all textures
|
||||
for (ImTextureData* tex : ImGui::GetPlatformIO().Textures)
|
||||
if (tex->RefCount == 1)
|
||||
{
|
||||
tex->SetStatus(ImTextureStatus_WantDestroy);
|
||||
ImGui_ImplDX9_UpdateTexture(tex);
|
||||
}
|
||||
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
|
||||
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
|
||||
}
|
||||
|
||||
void ImGui_ImplDX9_NewFrame()
|
||||
{
|
||||
if (!g_FontTexture)
|
||||
ImGui_ImplDX9_CreateDeviceObjects();
|
||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplDX9_Init()?");
|
||||
IM_UNUSED(bd);
|
||||
}
|
||||
|
||||
|
||||
bool ImGui_ImplDX9_Init(IDirect3DDevice9* device)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IMGUI_CHECKVERSION();
|
||||
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
||||
|
||||
// Setup backend capabilities flags
|
||||
ImGui_ImplDX9_Data* bd = IM_NEW(ImGui_ImplDX9_Data)();
|
||||
io.BackendRendererUserData = (void*)bd;
|
||||
io.BackendRendererName = "imgui_impl_dx9";
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
||||
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
platform_io.Renderer_TextureMaxWidth = platform_io.Renderer_TextureMaxHeight = 4096;
|
||||
platform_io.DrawCallback_ResetRenderState = ImGui_ImplDX9_DrawCallback_ResetRenderState;
|
||||
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplDX9_DrawCallback_SetSamplerLinear;
|
||||
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplDX9_DrawCallback_SetSamplerNearest;
|
||||
|
||||
bd->pd3dDevice = device;
|
||||
bd->pd3dDevice->AddRef();
|
||||
bd->HasRgbaSupport = ImGui_ImplDX9_CheckFormatSupport(bd->pd3dDevice, D3DFMT_A8B8G8R8);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplDX9_Shutdown()
|
||||
{
|
||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
ImGui_ImplDX9_InvalidateDeviceObjects();
|
||||
if (bd->pd3dDevice) { bd->pd3dDevice->Release(); }
|
||||
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
|
||||
platform_io.ClearRendererHandlers();
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
@@ -2,18 +2,26 @@
|
||||
// This needs to be used along with a Platform Backend (e.g. Win32)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID!
|
||||
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
|
||||
// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: IMGUI_USE_BGRA_PACKED_COLOR support, as this is the optimal color encoding for DirectX9.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
#pragma once
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
struct IDirect3DDevice9;
|
||||
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
IMGUI_IMPL_API bool ImGui_ImplDX9_Init(IDirect3DDevice9* device);
|
||||
IMGUI_IMPL_API void ImGui_ImplDX9_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplDX9_NewFrame();
|
||||
@@ -22,3 +30,8 @@ IMGUI_IMPL_API void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data);
|
||||
// Use if you want to reset your rendering device without losing Dear ImGui state.
|
||||
IMGUI_IMPL_API bool ImGui_ImplDX9_CreateDeviceObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplDX9_InvalidateDeviceObjects();
|
||||
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||
IMGUI_IMPL_API void ImGui_ImplDX9_UpdateTexture(ImTextureData* tex);
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,36 +1,71 @@
|
||||
// dear imgui: Platform Backend for GLFW
|
||||
// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan, WebGPU..)
|
||||
// (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
|
||||
// (Requires: GLFW 3.0+. Prefer GLFW 3.3+/3.4+ for full feature support.)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Platform: Clipboard support.
|
||||
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only).
|
||||
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values are obsolete since 1.87 and not supported since 1.91.5]
|
||||
// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
||||
// [x] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. FIXME: 3 cursors types are missing from GLFW.
|
||||
// [X] Platform: Keyboard arrays indexed using GLFW_KEY_* codes, e.g. ImGui::IsKeyPressed(GLFW_KEY_SPACE).
|
||||
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors) with GLFW 3.1+. Resizing cursors requires GLFW 3.4+! Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
// [X] Multiple Dear ImGui contexts support.
|
||||
// Missing features or Issues:
|
||||
// [ ] Platform: Touch events are only correctly identified as Touch on Windows. This create issues with some interactions. GLFW doesn't provide a way to identify touch inputs from mouse inputs, we cannot call io.AddMouseSourceEvent() to identify the source. We provide a Windows-specific workaround.
|
||||
// [ ] Platform: Missing ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress cursors.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
|
||||
// About GLSL version:
|
||||
// The 'glsl_version' initialization parameter defaults to "#version 150" if NULL.
|
||||
// Only override if your GL version doesn't handle this GLSL version. Keep NULL if unsure!
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
#pragma once
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
struct GLFWwindow;
|
||||
struct GLFWmonitor;
|
||||
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks);
|
||||
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks);
|
||||
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool install_callbacks);
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame();
|
||||
|
||||
// GLFW callbacks
|
||||
// - When calling Init with 'install_callbacks=true': GLFW callbacks will be installed for you. They will call user's previously installed callbacks, if any.
|
||||
// - When calling Init with 'install_callbacks=false': GLFW callbacks won't be installed. You will need to call those function yourself from your own GLFW callbacks.
|
||||
// Emscripten related initialization phase methods (call after ImGui_ImplGlfw_InitForOpenGL)
|
||||
#ifdef __EMSCRIPTEN__
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_InstallEmscriptenCallbacks(GLFWwindow* window, const char* canvas_selector);
|
||||
//static inline void ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback(const char* canvas_selector) { ImGui_ImplGlfw_InstallEmscriptenCallbacks(nullptr, canvas_selector); } } // Renamed in 1.91.0
|
||||
#endif
|
||||
|
||||
// GLFW callbacks install
|
||||
// - When calling Init with 'install_callbacks=true': ImGui_ImplGlfw_InstallCallbacks() is called. GLFW callbacks will be installed for you. They will chain-call user's previously installed callbacks, if any.
|
||||
// - When calling Init with 'install_callbacks=false': GLFW callbacks won't be installed. You will need to call individual function yourself from your own GLFW callbacks.
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window);
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_RestoreCallbacks(GLFWwindow* window);
|
||||
|
||||
// GLFW callbacks options:
|
||||
// - Set 'chain_for_all_windows=true' to enable chaining callbacks for all windows (including secondary viewports created by backends or by user)
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_SetCallbacksChainForAllWindows(bool chain_for_all_windows);
|
||||
|
||||
// GLFW callbacks (individual callbacks to call yourself if you didn't install callbacks)
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused); // Since 1.84
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered); // Since 1.84
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y); // Since 1.87
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c);
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor* monitor, int event);
|
||||
|
||||
// GLFW helpers
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_Sleep(int milliseconds);
|
||||
IMGUI_IMPL_API float ImGui_ImplGlfw_GetContentScaleForWindow(GLFWwindow* window);
|
||||
IMGUI_IMPL_API float ImGui_ImplGlfw_GetContentScaleForMonitor(GLFWmonitor* monitor);
|
||||
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
@@ -5,25 +5,39 @@
|
||||
// !!! If someone or something is teaching you GLUT today, you are being abused. Please show some resistance. !!!
|
||||
// !!! Nowadays, prefer using GLFW or SDL instead!
|
||||
|
||||
// Issues:
|
||||
// Implemented features:
|
||||
// [X] Platform: Partial keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLUT values are obsolete since 1.87 and not supported since 1.91.5]
|
||||
// Missing features or Issues:
|
||||
// [ ] Platform: GLUT is unable to distinguish e.g. Backspace from CTRL+H or TAB from CTRL+I
|
||||
// [ ] Platform: Missing horizontal mouse wheel support.
|
||||
// [ ] Platform: Missing mouse cursor shape/visibility support.
|
||||
// [ ] Platform: Missing clipboard support (not supported by Glut).
|
||||
// [ ] Platform: Missing gamepad support.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2023-04-17: BREAKING: Removed call to ImGui::NewFrame() from ImGui_ImplGLUT_NewFrame(). Needs to be called from the main application loop, like with every other backends.
|
||||
// 2022-09-26: Inputs: Renamed ImGuiKey_ModXXX introduced in 1.87 to ImGuiMod_XXX (old names still supported).
|
||||
// 2022-01-26: Inputs: replaced short-lived io.AddKeyModsEvent() (added two weeks ago) with io.AddKeyEvent() using ImGuiKey_ModXXX flags. Sorry for the confusion.
|
||||
// 2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEvent(), io.AddMouseWheelEvent() API (1.87+).
|
||||
// 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range.
|
||||
// 2019-04-03: Misc: Renamed imgui_impl_freeglut.cpp/.h to imgui_impl_glut.cpp/.h.
|
||||
// 2019-03-25: Misc: Made io.DeltaTime always above zero.
|
||||
// 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window.
|
||||
// 2018-03-22: Added GLUT Platform binding.
|
||||
|
||||
#include "imgui.h"
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include "imgui_impl_glut.h"
|
||||
#define GL_SILENCE_DEPRECATION
|
||||
#ifdef __APPLE__
|
||||
#include <GLUT/glut.h>
|
||||
#else
|
||||
@@ -36,42 +50,132 @@
|
||||
|
||||
static int g_Time = 0; // Current time, in milliseconds
|
||||
|
||||
// Glut has one function for characters and one for "special keys". We map the characters in the 0..255 range and the keys above.
|
||||
static ImGuiKey ImGui_ImplGLUT_KeyToImGuiKey(int key)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case '\t': return ImGuiKey_Tab;
|
||||
case 256 + GLUT_KEY_LEFT: return ImGuiKey_LeftArrow;
|
||||
case 256 + GLUT_KEY_RIGHT: return ImGuiKey_RightArrow;
|
||||
case 256 + GLUT_KEY_UP: return ImGuiKey_UpArrow;
|
||||
case 256 + GLUT_KEY_DOWN: return ImGuiKey_DownArrow;
|
||||
case 256 + GLUT_KEY_PAGE_UP: return ImGuiKey_PageUp;
|
||||
case 256 + GLUT_KEY_PAGE_DOWN: return ImGuiKey_PageDown;
|
||||
case 256 + GLUT_KEY_HOME: return ImGuiKey_Home;
|
||||
case 256 + GLUT_KEY_END: return ImGuiKey_End;
|
||||
case 256 + GLUT_KEY_INSERT: return ImGuiKey_Insert;
|
||||
case 127: return ImGuiKey_Delete;
|
||||
case 8: return ImGuiKey_Backspace;
|
||||
case ' ': return ImGuiKey_Space;
|
||||
case 13: return ImGuiKey_Enter;
|
||||
case 27: return ImGuiKey_Escape;
|
||||
case 39: return ImGuiKey_Apostrophe;
|
||||
case 44: return ImGuiKey_Comma;
|
||||
case 45: return ImGuiKey_Minus;
|
||||
case 46: return ImGuiKey_Period;
|
||||
case 47: return ImGuiKey_Slash;
|
||||
case 59: return ImGuiKey_Semicolon;
|
||||
case 61: return ImGuiKey_Equal;
|
||||
case 91: return ImGuiKey_LeftBracket;
|
||||
case 92: return ImGuiKey_Backslash;
|
||||
case 93: return ImGuiKey_RightBracket;
|
||||
case 96: return ImGuiKey_GraveAccent;
|
||||
//case 0: return ImGuiKey_CapsLock;
|
||||
//case 0: return ImGuiKey_ScrollLock;
|
||||
case 256 + 0x006D: return ImGuiKey_NumLock;
|
||||
//case 0: return ImGuiKey_PrintScreen;
|
||||
//case 0: return ImGuiKey_Pause;
|
||||
//case '0': return ImGuiKey_Keypad0;
|
||||
//case '1': return ImGuiKey_Keypad1;
|
||||
//case '2': return ImGuiKey_Keypad2;
|
||||
//case '3': return ImGuiKey_Keypad3;
|
||||
//case '4': return ImGuiKey_Keypad4;
|
||||
//case '5': return ImGuiKey_Keypad5;
|
||||
//case '6': return ImGuiKey_Keypad6;
|
||||
//case '7': return ImGuiKey_Keypad7;
|
||||
//case '8': return ImGuiKey_Keypad8;
|
||||
//case '9': return ImGuiKey_Keypad9;
|
||||
//case 46: return ImGuiKey_KeypadDecimal;
|
||||
//case 47: return ImGuiKey_KeypadDivide;
|
||||
case 42: return ImGuiKey_KeypadMultiply;
|
||||
//case 45: return ImGuiKey_KeypadSubtract;
|
||||
case 43: return ImGuiKey_KeypadAdd;
|
||||
//case 13: return ImGuiKey_KeypadEnter;
|
||||
//case 0: return ImGuiKey_KeypadEqual;
|
||||
case 256 + 0x0072: return ImGuiKey_LeftCtrl;
|
||||
case 256 + 0x0070: return ImGuiKey_LeftShift;
|
||||
case 256 + 0x0074: return ImGuiKey_LeftAlt;
|
||||
//case 0: return ImGuiKey_LeftSuper;
|
||||
case 256 + 0x0073: return ImGuiKey_RightCtrl;
|
||||
case 256 + 0x0071: return ImGuiKey_RightShift;
|
||||
case 256 + 0x0075: return ImGuiKey_RightAlt;
|
||||
//case 0: return ImGuiKey_RightSuper;
|
||||
//case 0: return ImGuiKey_Menu;
|
||||
case '0': return ImGuiKey_0;
|
||||
case '1': return ImGuiKey_1;
|
||||
case '2': return ImGuiKey_2;
|
||||
case '3': return ImGuiKey_3;
|
||||
case '4': return ImGuiKey_4;
|
||||
case '5': return ImGuiKey_5;
|
||||
case '6': return ImGuiKey_6;
|
||||
case '7': return ImGuiKey_7;
|
||||
case '8': return ImGuiKey_8;
|
||||
case '9': return ImGuiKey_9;
|
||||
case 'A': case 'a': return ImGuiKey_A;
|
||||
case 'B': case 'b': return ImGuiKey_B;
|
||||
case 'C': case 'c': return ImGuiKey_C;
|
||||
case 'D': case 'd': return ImGuiKey_D;
|
||||
case 'E': case 'e': return ImGuiKey_E;
|
||||
case 'F': case 'f': return ImGuiKey_F;
|
||||
case 'G': case 'g': return ImGuiKey_G;
|
||||
case 'H': case 'h': return ImGuiKey_H;
|
||||
case 'I': case 'i': return ImGuiKey_I;
|
||||
case 'J': case 'j': return ImGuiKey_J;
|
||||
case 'K': case 'k': return ImGuiKey_K;
|
||||
case 'L': case 'l': return ImGuiKey_L;
|
||||
case 'M': case 'm': return ImGuiKey_M;
|
||||
case 'N': case 'n': return ImGuiKey_N;
|
||||
case 'O': case 'o': return ImGuiKey_O;
|
||||
case 'P': case 'p': return ImGuiKey_P;
|
||||
case 'Q': case 'q': return ImGuiKey_Q;
|
||||
case 'R': case 'r': return ImGuiKey_R;
|
||||
case 'S': case 's': return ImGuiKey_S;
|
||||
case 'T': case 't': return ImGuiKey_T;
|
||||
case 'U': case 'u': return ImGuiKey_U;
|
||||
case 'V': case 'v': return ImGuiKey_V;
|
||||
case 'W': case 'w': return ImGuiKey_W;
|
||||
case 'X': case 'x': return ImGuiKey_X;
|
||||
case 'Y': case 'y': return ImGuiKey_Y;
|
||||
case 'Z': case 'z': return ImGuiKey_Z;
|
||||
case 256 + GLUT_KEY_F1: return ImGuiKey_F1;
|
||||
case 256 + GLUT_KEY_F2: return ImGuiKey_F2;
|
||||
case 256 + GLUT_KEY_F3: return ImGuiKey_F3;
|
||||
case 256 + GLUT_KEY_F4: return ImGuiKey_F4;
|
||||
case 256 + GLUT_KEY_F5: return ImGuiKey_F5;
|
||||
case 256 + GLUT_KEY_F6: return ImGuiKey_F6;
|
||||
case 256 + GLUT_KEY_F7: return ImGuiKey_F7;
|
||||
case 256 + GLUT_KEY_F8: return ImGuiKey_F8;
|
||||
case 256 + GLUT_KEY_F9: return ImGuiKey_F9;
|
||||
case 256 + GLUT_KEY_F10: return ImGuiKey_F10;
|
||||
case 256 + GLUT_KEY_F11: return ImGuiKey_F11;
|
||||
case 256 + GLUT_KEY_F12: return ImGuiKey_F12;
|
||||
default: return ImGuiKey_None;
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGui_ImplGLUT_Init()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IMGUI_CHECKVERSION();
|
||||
|
||||
#ifdef FREEGLUT
|
||||
io.BackendPlatformName = "imgui_impl_glut (freeglut)";
|
||||
#else
|
||||
io.BackendPlatformName = "imgui_impl_glut";
|
||||
#endif
|
||||
|
||||
g_Time = 0;
|
||||
|
||||
// Glut has 1 function for characters and one for "special keys". We map the characters in the 0..255 range and the keys above.
|
||||
io.KeyMap[ImGuiKey_Tab] = '\t'; // == 9 == CTRL+I
|
||||
io.KeyMap[ImGuiKey_LeftArrow] = 256 + GLUT_KEY_LEFT;
|
||||
io.KeyMap[ImGuiKey_RightArrow] = 256 + GLUT_KEY_RIGHT;
|
||||
io.KeyMap[ImGuiKey_UpArrow] = 256 + GLUT_KEY_UP;
|
||||
io.KeyMap[ImGuiKey_DownArrow] = 256 + GLUT_KEY_DOWN;
|
||||
io.KeyMap[ImGuiKey_PageUp] = 256 + GLUT_KEY_PAGE_UP;
|
||||
io.KeyMap[ImGuiKey_PageDown] = 256 + GLUT_KEY_PAGE_DOWN;
|
||||
io.KeyMap[ImGuiKey_Home] = 256 + GLUT_KEY_HOME;
|
||||
io.KeyMap[ImGuiKey_End] = 256 + GLUT_KEY_END;
|
||||
io.KeyMap[ImGuiKey_Insert] = 256 + GLUT_KEY_INSERT;
|
||||
io.KeyMap[ImGuiKey_Delete] = 127;
|
||||
io.KeyMap[ImGuiKey_Backspace] = 8; // == CTRL+H
|
||||
io.KeyMap[ImGuiKey_Space] = ' ';
|
||||
io.KeyMap[ImGuiKey_Enter] = 13; // == CTRL+M
|
||||
io.KeyMap[ImGuiKey_Escape] = 27;
|
||||
io.KeyMap[ImGuiKey_KeyPadEnter] = 13; // == CTRL+M
|
||||
io.KeyMap[ImGuiKey_A] = 'A';
|
||||
io.KeyMap[ImGuiKey_C] = 'C';
|
||||
io.KeyMap[ImGuiKey_V] = 'V';
|
||||
io.KeyMap[ImGuiKey_X] = 'X';
|
||||
io.KeyMap[ImGuiKey_Y] = 'Y';
|
||||
io.KeyMap[ImGuiKey_Z] = 'Z';
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -92,6 +196,8 @@ void ImGui_ImplGLUT_InstallFuncs()
|
||||
|
||||
void ImGui_ImplGLUT_Shutdown()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.BackendPlatformName = nullptr;
|
||||
}
|
||||
|
||||
void ImGui_ImplGLUT_NewFrame()
|
||||
@@ -104,18 +210,22 @@ void ImGui_ImplGLUT_NewFrame()
|
||||
delta_time_ms = 1;
|
||||
io.DeltaTime = delta_time_ms / 1000.0f;
|
||||
g_Time = current_time;
|
||||
|
||||
// Start the frame
|
||||
ImGui::NewFrame();
|
||||
}
|
||||
|
||||
static void ImGui_ImplGLUT_UpdateKeyboardMods()
|
||||
static void ImGui_ImplGLUT_UpdateKeyModifiers()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
int mods = glutGetModifiers();
|
||||
io.KeyCtrl = (mods & GLUT_ACTIVE_CTRL) != 0;
|
||||
io.KeyShift = (mods & GLUT_ACTIVE_SHIFT) != 0;
|
||||
io.KeyAlt = (mods & GLUT_ACTIVE_ALT) != 0;
|
||||
int glut_key_mods = glutGetModifiers();
|
||||
io.AddKeyEvent(ImGuiMod_Ctrl, (glut_key_mods & GLUT_ACTIVE_CTRL) != 0);
|
||||
io.AddKeyEvent(ImGuiMod_Shift, (glut_key_mods & GLUT_ACTIVE_SHIFT) != 0);
|
||||
io.AddKeyEvent(ImGuiMod_Alt, (glut_key_mods & GLUT_ACTIVE_ALT) != 0);
|
||||
}
|
||||
|
||||
static void ImGui_ImplGLUT_AddKeyEvent(ImGuiKey key, bool down, int native_keycode)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.AddKeyEvent(key, down);
|
||||
io.SetKeyEventNativeData(key, native_keycode, -1); // To support legacy indexing (<1.87 user code)
|
||||
}
|
||||
|
||||
void ImGui_ImplGLUT_KeyboardFunc(unsigned char c, int x, int y)
|
||||
@@ -126,79 +236,58 @@ void ImGui_ImplGLUT_KeyboardFunc(unsigned char c, int x, int y)
|
||||
if (c >= 32)
|
||||
io.AddInputCharacter((unsigned int)c);
|
||||
|
||||
// Store letters in KeysDown[] array as both uppercase and lowercase + Handle GLUT translating CTRL+A..CTRL+Z as 1..26.
|
||||
// This is a hacky mess but GLUT is unable to distinguish e.g. a TAB key from CTRL+I so this is probably the best we can do here.
|
||||
if (c >= 1 && c <= 26)
|
||||
io.KeysDown[c] = io.KeysDown[c - 1 + 'a'] = io.KeysDown[c - 1 + 'A'] = true;
|
||||
else if (c >= 'a' && c <= 'z')
|
||||
io.KeysDown[c] = io.KeysDown[c - 'a' + 'A'] = true;
|
||||
else if (c >= 'A' && c <= 'Z')
|
||||
io.KeysDown[c] = io.KeysDown[c - 'A' + 'a'] = true;
|
||||
else
|
||||
io.KeysDown[c] = true;
|
||||
ImGui_ImplGLUT_UpdateKeyboardMods();
|
||||
ImGuiKey key = ImGui_ImplGLUT_KeyToImGuiKey(c);
|
||||
ImGui_ImplGLUT_AddKeyEvent(key, true, c);
|
||||
ImGui_ImplGLUT_UpdateKeyModifiers();
|
||||
(void)x; (void)y; // Unused
|
||||
}
|
||||
|
||||
void ImGui_ImplGLUT_KeyboardUpFunc(unsigned char c, int x, int y)
|
||||
{
|
||||
//printf("char_up_func %d '%c'\n", c, c);
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (c >= 1 && c <= 26)
|
||||
io.KeysDown[c] = io.KeysDown[c - 1 + 'a'] = io.KeysDown[c - 1 + 'A'] = false;
|
||||
else if (c >= 'a' && c <= 'z')
|
||||
io.KeysDown[c] = io.KeysDown[c - 'a' + 'A'] = false;
|
||||
else if (c >= 'A' && c <= 'Z')
|
||||
io.KeysDown[c] = io.KeysDown[c - 'A' + 'a'] = false;
|
||||
else
|
||||
io.KeysDown[c] = false;
|
||||
ImGui_ImplGLUT_UpdateKeyboardMods();
|
||||
ImGuiKey key = ImGui_ImplGLUT_KeyToImGuiKey(c);
|
||||
ImGui_ImplGLUT_AddKeyEvent(key, false, c);
|
||||
ImGui_ImplGLUT_UpdateKeyModifiers();
|
||||
(void)x; (void)y; // Unused
|
||||
}
|
||||
|
||||
void ImGui_ImplGLUT_SpecialFunc(int key, int x, int y)
|
||||
{
|
||||
//printf("key_down_func %d\n", key);
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (key + 256 < IM_ARRAYSIZE(io.KeysDown))
|
||||
io.KeysDown[key + 256] = true;
|
||||
ImGui_ImplGLUT_UpdateKeyboardMods();
|
||||
ImGuiKey imgui_key = ImGui_ImplGLUT_KeyToImGuiKey(key + 256);
|
||||
ImGui_ImplGLUT_AddKeyEvent(imgui_key, true, key + 256);
|
||||
ImGui_ImplGLUT_UpdateKeyModifiers();
|
||||
(void)x; (void)y; // Unused
|
||||
}
|
||||
|
||||
void ImGui_ImplGLUT_SpecialUpFunc(int key, int x, int y)
|
||||
{
|
||||
//printf("key_up_func %d\n", key);
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (key + 256 < IM_ARRAYSIZE(io.KeysDown))
|
||||
io.KeysDown[key + 256] = false;
|
||||
ImGui_ImplGLUT_UpdateKeyboardMods();
|
||||
ImGuiKey imgui_key = ImGui_ImplGLUT_KeyToImGuiKey(key + 256);
|
||||
ImGui_ImplGLUT_AddKeyEvent(imgui_key, false, key + 256);
|
||||
ImGui_ImplGLUT_UpdateKeyModifiers();
|
||||
(void)x; (void)y; // Unused
|
||||
}
|
||||
|
||||
void ImGui_ImplGLUT_MouseFunc(int glut_button, int state, int x, int y)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.MousePos = ImVec2((float)x, (float)y);
|
||||
io.AddMousePosEvent((float)x, (float)y);
|
||||
int button = -1;
|
||||
if (glut_button == GLUT_LEFT_BUTTON) button = 0;
|
||||
if (glut_button == GLUT_RIGHT_BUTTON) button = 1;
|
||||
if (glut_button == GLUT_MIDDLE_BUTTON) button = 2;
|
||||
if (button != -1 && state == GLUT_DOWN)
|
||||
io.MouseDown[button] = true;
|
||||
if (button != -1 && state == GLUT_UP)
|
||||
io.MouseDown[button] = false;
|
||||
if (button != -1 && (state == GLUT_DOWN || state == GLUT_UP))
|
||||
io.AddMouseButtonEvent(button, state == GLUT_DOWN);
|
||||
}
|
||||
|
||||
#ifdef __FREEGLUT_EXT_H__
|
||||
void ImGui_ImplGLUT_MouseWheelFunc(int button, int dir, int x, int y)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.MousePos = ImVec2((float)x, (float)y);
|
||||
if (dir > 0)
|
||||
io.MouseWheel += 1.0;
|
||||
else if (dir < 0)
|
||||
io.MouseWheel -= 1.0;
|
||||
io.AddMousePosEvent((float)x, (float)y);
|
||||
if (dir != 0)
|
||||
io.AddMouseWheelEvent(0.0f, dir > 0 ? 1.0f : -1.0f);
|
||||
(void)button; // Unused
|
||||
}
|
||||
#endif
|
||||
@@ -212,5 +301,9 @@ void ImGui_ImplGLUT_ReshapeFunc(int w, int h)
|
||||
void ImGui_ImplGLUT_MotionFunc(int x, int y)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.MousePos = ImVec2((float)x, (float)y);
|
||||
io.AddMousePosEvent((float)x, (float)y);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
@@ -5,19 +5,28 @@
|
||||
// !!! If someone or something is teaching you GLUT today, you are being abused. Please show some resistance. !!!
|
||||
// !!! Nowadays, prefer using GLFW or SDL instead!
|
||||
|
||||
// Issues:
|
||||
// Implemented features:
|
||||
// [X] Platform: Partial keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLUT values are obsolete since 1.87 and not supported since 1.91.5]
|
||||
// Missing features or Issues:
|
||||
// [ ] Platform: GLUT is unable to distinguish e.g. Backspace from CTRL+H or TAB from CTRL+I
|
||||
// [ ] Platform: Missing horizontal mouse wheel support.
|
||||
// [ ] Platform: Missing mouse cursor shape/visibility support.
|
||||
// [ ] Platform: Missing clipboard support (not supported by Glut).
|
||||
// [ ] Platform: Missing gamepad support.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
#pragma once
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
IMGUI_IMPL_API bool ImGui_ImplGLUT_Init();
|
||||
IMGUI_IMPL_API void ImGui_ImplGLUT_InstallFuncs();
|
||||
IMGUI_IMPL_API void ImGui_ImplGLUT_Shutdown();
|
||||
@@ -25,7 +34,7 @@ IMGUI_IMPL_API void ImGui_ImplGLUT_NewFrame();
|
||||
|
||||
// You can call ImGui_ImplGLUT_InstallFuncs() to get all those functions installed automatically,
|
||||
// or call them yourself from your own GLUT handlers. We are using the same weird names as GLUT for consistency..
|
||||
//---------------------------------------- GLUT name --------------------------------------------- Decent Name ---------
|
||||
//------------------------------------ GLUT name ---------------------------------------------- Decent Name ---------
|
||||
IMGUI_IMPL_API void ImGui_ImplGLUT_ReshapeFunc(int w, int h); // ~ ResizeFunc
|
||||
IMGUI_IMPL_API void ImGui_ImplGLUT_MotionFunc(int x, int y); // ~ MouseMoveFunc
|
||||
IMGUI_IMPL_API void ImGui_ImplGLUT_MouseFunc(int button, int state, int x, int y); // ~ MouseButtonFunc
|
||||
@@ -34,3 +43,5 @@ IMGUI_IMPL_API void ImGui_ImplGLUT_KeyboardFunc(unsigned char c, int x, int
|
||||
IMGUI_IMPL_API void ImGui_ImplGLUT_KeyboardUpFunc(unsigned char c, int x, int y); // ~ CharReleasedFunc
|
||||
IMGUI_IMPL_API void ImGui_ImplGLUT_SpecialFunc(int key, int x, int y); // ~ KeyPressedFunc
|
||||
IMGUI_IMPL_API void ImGui_ImplGLUT_SpecialUpFunc(int key, int x, int y); // ~ KeyReleasedFunc
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
@@ -1,317 +0,0 @@
|
||||
// dear imgui: Renderer + Platform Backend for Marmalade + IwGx
|
||||
// Marmalade code: Copyright (C) 2015 by Giovanni Zito (this file is part of Dear ImGui)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'CIwTexture*' as ImTextureID. Read the FAQ about ImTextureID!
|
||||
// Missing features:
|
||||
// [ ] Renderer: Clipping rectangles are not honored.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2021-05-19: Renderer: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
|
||||
// 2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter.
|
||||
// 2019-05-11: Inputs: Don't filter value from character callback before calling AddInputCharacter().
|
||||
// 2018-11-30: Misc: Setting up io.BackendPlatformName/io.BackendRendererName so they can be displayed in the About Window.
|
||||
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_Marmalade_RenderDrawData() in the .h file so you can call it yourself.
|
||||
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
|
||||
// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space.
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_marmalade.h"
|
||||
|
||||
#include <s3eClipboard.h>
|
||||
#include <s3ePointer.h>
|
||||
#include <s3eKeyboard.h>
|
||||
#include <IwTexture.h>
|
||||
#include <IwGx.h>
|
||||
|
||||
// Data
|
||||
static double g_Time = 0.0f;
|
||||
static bool g_MousePressed[3] = { false, false, false };
|
||||
static CIwTexture* g_FontTexture = NULL;
|
||||
static char* g_ClipboardText = NULL;
|
||||
static bool g_osdKeyboardEnabled = false;
|
||||
|
||||
// use this setting to scale the interface - e.g. on device you could use 2 or 3 scale factor
|
||||
static ImVec2 g_RenderScale = ImVec2(1.0f, 1.0f);
|
||||
|
||||
// Render function.
|
||||
void ImGui_Marmalade_RenderDrawData(ImDrawData* draw_data)
|
||||
{
|
||||
// Avoid rendering when minimized
|
||||
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
|
||||
return;
|
||||
|
||||
// Render command lists
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;
|
||||
const int nVert = cmd_list->VtxBuffer.Size;
|
||||
CIwFVec2* pVertStream = IW_GX_ALLOC(CIwFVec2, nVert);
|
||||
CIwFVec2* pUVStream = IW_GX_ALLOC(CIwFVec2, nVert);
|
||||
CIwColour* pColStream = IW_GX_ALLOC(CIwColour, nVert);
|
||||
|
||||
for (int i = 0; i < nVert; i++)
|
||||
{
|
||||
// FIXME-OPT: optimize multiplication on GPU using vertex shader/projection matrix.
|
||||
pVertStream[i].x = cmd_list->VtxBuffer[i].pos.x * g_RenderScale.x;
|
||||
pVertStream[i].y = cmd_list->VtxBuffer[i].pos.y * g_RenderScale.y;
|
||||
pUVStream[i].x = cmd_list->VtxBuffer[i].uv.x;
|
||||
pUVStream[i].y = cmd_list->VtxBuffer[i].uv.y;
|
||||
pColStream[i] = cmd_list->VtxBuffer[i].col;
|
||||
}
|
||||
|
||||
IwGxSetVertStreamScreenSpace(pVertStream, nVert);
|
||||
IwGxSetUVStream(pUVStream);
|
||||
IwGxSetColStream(pColStream, nVert);
|
||||
IwGxSetNormStream(0);
|
||||
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback)
|
||||
{
|
||||
pcmd->UserCallback(cmd_list, pcmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
// FIXME: Not honoring ClipRect fields.
|
||||
CIwMaterial* pCurrentMaterial = IW_GX_ALLOC_MATERIAL();
|
||||
pCurrentMaterial->SetShadeMode(CIwMaterial::SHADE_FLAT);
|
||||
pCurrentMaterial->SetCullMode(CIwMaterial::CULL_NONE);
|
||||
pCurrentMaterial->SetFiltering(false);
|
||||
pCurrentMaterial->SetAlphaMode(CIwMaterial::ALPHA_BLEND);
|
||||
pCurrentMaterial->SetDepthWriteMode(CIwMaterial::DEPTH_WRITE_NORMAL);
|
||||
pCurrentMaterial->SetAlphaTestMode(CIwMaterial::ALPHATEST_DISABLED);
|
||||
pCurrentMaterial->SetTexture((CIwTexture*)pcmd->GetTexID());
|
||||
IwGxSetMaterial(pCurrentMaterial);
|
||||
IwGxDrawPrims(IW_GX_TRI_LIST, (uint16*)idx_buffer, pcmd->ElemCount);
|
||||
}
|
||||
idx_buffer += pcmd->ElemCount;
|
||||
}
|
||||
IwGxFlush();
|
||||
}
|
||||
|
||||
// TODO: restore modified state (i.e. mvp matrix)
|
||||
}
|
||||
|
||||
static const char* ImGui_Marmalade_GetClipboardText(void* /*user_data*/)
|
||||
{
|
||||
if (!s3eClipboardAvailable())
|
||||
return NULL;
|
||||
|
||||
if (int size = s3eClipboardGetText(NULL, 0))
|
||||
{
|
||||
if (g_ClipboardText)
|
||||
delete[] g_ClipboardText;
|
||||
g_ClipboardText = new char[size];
|
||||
g_ClipboardText[0] = '\0';
|
||||
s3eClipboardGetText(g_ClipboardText, size);
|
||||
}
|
||||
|
||||
return g_ClipboardText;
|
||||
}
|
||||
|
||||
static void ImGui_Marmalade_SetClipboardText(void* /*user_data*/, const char* text)
|
||||
{
|
||||
if (s3eClipboardAvailable())
|
||||
s3eClipboardSetText(text);
|
||||
}
|
||||
|
||||
int32 ImGui_Marmalade_PointerButtonEventCallback(void* system_data, void* user_data)
|
||||
{
|
||||
// pEvent->m_Button is of type s3ePointerButton and indicates which mouse
|
||||
// button was pressed. For touchscreen this should always have the value
|
||||
// S3E_POINTER_BUTTON_SELECT
|
||||
s3ePointerEvent* pEvent = (s3ePointerEvent*)system_data;
|
||||
|
||||
if (pEvent->m_Pressed == 1)
|
||||
{
|
||||
if (pEvent->m_Button == S3E_POINTER_BUTTON_LEFTMOUSE)
|
||||
g_MousePressed[0] = true;
|
||||
if (pEvent->m_Button == S3E_POINTER_BUTTON_RIGHTMOUSE)
|
||||
g_MousePressed[1] = true;
|
||||
if (pEvent->m_Button == S3E_POINTER_BUTTON_MIDDLEMOUSE)
|
||||
g_MousePressed[2] = true;
|
||||
if (pEvent->m_Button == S3E_POINTER_BUTTON_MOUSEWHEELUP)
|
||||
io.MouseWheel += pEvent->m_y;
|
||||
if (pEvent->m_Button == S3E_POINTER_BUTTON_MOUSEWHEELDOWN)
|
||||
io.MouseWheel += pEvent->m_y;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32 ImGui_Marmalade_KeyCallback(void* system_data, void* user_data)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
s3eKeyboardEvent* e = (s3eKeyboardEvent*)system_data;
|
||||
if (e->m_Pressed == 1)
|
||||
io.KeysDown[e->m_Key] = true;
|
||||
if (e->m_Pressed == 0)
|
||||
io.KeysDown[e->m_Key] = false;
|
||||
|
||||
io.KeyCtrl = s3eKeyboardGetState(s3eKeyLeftControl) == S3E_KEY_STATE_DOWN || s3eKeyboardGetState(s3eKeyRightControl) == S3E_KEY_STATE_DOWN;
|
||||
io.KeyShift = s3eKeyboardGetState(s3eKeyLeftShift) == S3E_KEY_STATE_DOWN || s3eKeyboardGetState(s3eKeyRightShift) == S3E_KEY_STATE_DOWN;
|
||||
io.KeyAlt = s3eKeyboardGetState(s3eKeyLeftAlt) == S3E_KEY_STATE_DOWN || s3eKeyboardGetState(s3eKeyRightAlt) == S3E_KEY_STATE_DOWN;
|
||||
io.KeySuper = s3eKeyboardGetState(s3eKeyLeftWindows) == S3E_KEY_STATE_DOWN || s3eKeyboardGetState(s3eKeyRightWindows) == S3E_KEY_STATE_DOWN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32 ImGui_Marmalade_CharCallback(void* system_data, void* user_data)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
s3eKeyboardCharEvent* e = (s3eKeyboardCharEvent*)system_data;
|
||||
io.AddInputCharacter((unsigned int)e->m_Char);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ImGui_Marmalade_CreateDeviceObjects()
|
||||
{
|
||||
// Build texture atlas
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
unsigned char* pixels;
|
||||
int width, height;
|
||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
|
||||
|
||||
// Upload texture to graphics system
|
||||
g_FontTexture = new CIwTexture();
|
||||
g_FontTexture->SetModifiable(true);
|
||||
CIwImage& image = g_FontTexture->GetImage();
|
||||
image.SetFormat(CIwImage::ARGB_8888);
|
||||
image.SetWidth(width);
|
||||
image.SetHeight(height);
|
||||
image.SetBuffers(); // allocates and own buffers
|
||||
image.ReadTexels(pixels);
|
||||
g_FontTexture->SetMipMapping(false);
|
||||
g_FontTexture->SetFiltering(false);
|
||||
g_FontTexture->Upload();
|
||||
|
||||
// Store our identifier
|
||||
io.Fonts->SetTexID((ImTextureID)g_FontTexture);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_Marmalade_InvalidateDeviceObjects()
|
||||
{
|
||||
if (g_ClipboardText)
|
||||
{
|
||||
delete[] g_ClipboardText;
|
||||
g_ClipboardText = NULL;
|
||||
}
|
||||
|
||||
if (g_FontTexture)
|
||||
{
|
||||
ImGui::GetIO().Fonts->SetTexID(0);
|
||||
delete g_FontTexture;
|
||||
g_FontTexture = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGui_Marmalade_Init(bool install_callbacks)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.BackendPlatformName = io.BackendRendererName = "imgui_impl_marmalade";
|
||||
|
||||
// Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array.
|
||||
io.KeyMap[ImGuiKey_Tab] = s3eKeyTab
|
||||
io.KeyMap[ImGuiKey_LeftArrow] = s3eKeyLeft;
|
||||
io.KeyMap[ImGuiKey_RightArrow] = s3eKeyRight;
|
||||
io.KeyMap[ImGuiKey_UpArrow] = s3eKeyUp;
|
||||
io.KeyMap[ImGuiKey_DownArrow] = s3eKeyDown;
|
||||
io.KeyMap[ImGuiKey_PageUp] = s3eKeyPageUp;
|
||||
io.KeyMap[ImGuiKey_PageDown] = s3eKeyPageDown;
|
||||
io.KeyMap[ImGuiKey_Home] = s3eKeyHome;
|
||||
io.KeyMap[ImGuiKey_End] = s3eKeyEnd;
|
||||
io.KeyMap[ImGuiKey_Insert] = s3eKeyInsert;
|
||||
io.KeyMap[ImGuiKey_Delete] = s3eKeyDelete;
|
||||
io.KeyMap[ImGuiKey_Backspace] = s3eKeyBackspace;
|
||||
io.KeyMap[ImGuiKey_Space] = s3eKeySpace;
|
||||
io.KeyMap[ImGuiKey_Enter] = s3eKeyEnter;
|
||||
io.KeyMap[ImGuiKey_Escape] = s3eKeyEsc;
|
||||
io.KeyMap[ImGuiKey_KeyPadEnter] = s3eKeyNumPadEnter;
|
||||
io.KeyMap[ImGuiKey_A] = s3eKeyA;
|
||||
io.KeyMap[ImGuiKey_C] = s3eKeyC;
|
||||
io.KeyMap[ImGuiKey_V] = s3eKeyV;
|
||||
io.KeyMap[ImGuiKey_X] = s3eKeyX;
|
||||
io.KeyMap[ImGuiKey_Y] = s3eKeyY;
|
||||
io.KeyMap[ImGuiKey_Z] = s3eKeyZ;
|
||||
|
||||
io.SetClipboardTextFn = ImGui_Marmalade_SetClipboardText;
|
||||
io.GetClipboardTextFn = ImGui_Marmalade_GetClipboardText;
|
||||
|
||||
if (install_callbacks)
|
||||
{
|
||||
s3ePointerRegister(S3E_POINTER_BUTTON_EVENT, ImGui_Marmalade_PointerButtonEventCallback, 0);
|
||||
s3eKeyboardRegister(S3E_KEYBOARD_KEY_EVENT, ImGui_Marmalade_KeyCallback, 0);
|
||||
s3eKeyboardRegister(S3E_KEYBOARD_CHAR_EVENT, ImGui_Marmalade_CharCallback, 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_Marmalade_Shutdown()
|
||||
{
|
||||
ImGui_Marmalade_InvalidateDeviceObjects();
|
||||
}
|
||||
|
||||
void ImGui_Marmalade_NewFrame()
|
||||
{
|
||||
if (!g_FontTexture)
|
||||
ImGui_Marmalade_CreateDeviceObjects();
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
// Setup display size (every frame to accommodate for window resizing)
|
||||
int w = IwGxGetScreenWidth(), h = IwGxGetScreenHeight();
|
||||
io.DisplaySize = ImVec2((float)w, (float)h);
|
||||
// For retina display or other situations where window coordinates are different from framebuffer coordinates. User storage only, presently not used by ImGui.
|
||||
io.DisplayFramebufferScale = g_scale;
|
||||
|
||||
// Setup time step
|
||||
double current_time = s3eTimerGetUST() / 1000.0f;
|
||||
io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f / 60.0f);
|
||||
g_Time = current_time;
|
||||
|
||||
double mouse_x, mouse_y;
|
||||
mouse_x = s3ePointerGetX();
|
||||
mouse_y = s3ePointerGetY();
|
||||
io.MousePos = ImVec2((float)mouse_x / g_scale.x, (float)mouse_y / g_scale.y); // Mouse position (set to -FLT_MAX,-FLT_MAX if no mouse / on another screen, etc.)
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
io.MouseDown[i] = g_MousePressed[i] || s3ePointerGetState((s3ePointerButton)i) != S3E_POINTER_STATE_UP; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
|
||||
g_MousePressed[i] = false;
|
||||
}
|
||||
|
||||
// TODO: Hide OS mouse cursor if ImGui is drawing it
|
||||
// s3ePointerSetInt(S3E_POINTER_HIDE_CURSOR,(io.MouseDrawCursor ? 0 : 1));
|
||||
|
||||
// Show/hide OSD keyboard
|
||||
if (io.WantTextInput)
|
||||
{
|
||||
// Some text input widget is active?
|
||||
if (!g_osdKeyboardEnabled)
|
||||
{
|
||||
g_osdKeyboardEnabled = true;
|
||||
s3eKeyboardSetInt(S3E_KEYBOARD_GET_CHAR, 1); // show OSD keyboard
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No text input widget is active
|
||||
if (g_osdKeyboardEnabled)
|
||||
{
|
||||
g_osdKeyboardEnabled = false;
|
||||
s3eKeyboardSetInt(S3E_KEYBOARD_GET_CHAR, 0); // hide OSD keyboard
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
// dear imgui: Renderer + Platform Backend for Marmalade + IwGx
|
||||
// Marmalade code: Copyright (C) 2015 by Giovanni Zito (this file is part of Dear ImGui)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'CIwTexture*' as ImTextureID. Read the FAQ about ImTextureID!
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
|
||||
#pragma once
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
|
||||
IMGUI_IMPL_API bool ImGui_Marmalade_Init(bool install_callbacks);
|
||||
IMGUI_IMPL_API void ImGui_Marmalade_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_Marmalade_NewFrame();
|
||||
IMGUI_IMPL_API void ImGui_Marmalade_RenderDrawData(ImDrawData* draw_data);
|
||||
|
||||
// Use if you want to reset your rendering device without losing Dear ImGui state.
|
||||
IMGUI_IMPL_API void ImGui_Marmalade_InvalidateDeviceObjects();
|
||||
IMGUI_IMPL_API bool ImGui_Marmalade_CreateDeviceObjects();
|
||||
|
||||
// Callbacks (installed by default if you enable 'install_callbacks' during initialization)
|
||||
// You can also handle inputs yourself and use those as a reference.
|
||||
IMGUI_IMPL_API int32 ImGui_Marmalade_PointerButtonEventCallback(void* system_data, void* user_data);
|
||||
IMGUI_IMPL_API int32 ImGui_Marmalade_KeyCallback(void* system_data, void* user_data);
|
||||
IMGUI_IMPL_API int32 ImGui_Marmalade_CharCallback(void* system_data, void* user_data);
|
||||
@@ -2,27 +2,77 @@
|
||||
// This needs to be used along with a Platform Backend (e.g. OSX)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'MTLTexture' as ImTextureID. Read the FAQ about ImTextureID!
|
||||
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
|
||||
// [X] Renderer: User texture binding. Use 'MTLTexture' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
#pragma once
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ObjC API
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifdef __OBJC__
|
||||
|
||||
@class MTLRenderPassDescriptor;
|
||||
@protocol MTLDevice, MTLCommandBuffer, MTLRenderCommandEncoder;
|
||||
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
IMGUI_IMPL_API bool ImGui_ImplMetal_Init(id<MTLDevice> device);
|
||||
IMGUI_IMPL_API void ImGui_ImplMetal_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplMetal_NewFrame(MTLRenderPassDescriptor* renderPassDescriptor);
|
||||
IMGUI_IMPL_API void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data,
|
||||
IMGUI_IMPL_API void ImGui_ImplMetal_RenderDrawData(ImDrawData* drawData,
|
||||
id<MTLCommandBuffer> commandBuffer,
|
||||
id<MTLRenderCommandEncoder> commandEncoder);
|
||||
|
||||
// Called by Init/NewFrame/Shutdown
|
||||
IMGUI_IMPL_API bool ImGui_ImplMetal_CreateFontsTexture(id<MTLDevice> device);
|
||||
IMGUI_IMPL_API void ImGui_ImplMetal_DestroyFontsTexture();
|
||||
IMGUI_IMPL_API bool ImGui_ImplMetal_CreateDeviceObjects(id<MTLDevice> device);
|
||||
IMGUI_IMPL_API void ImGui_ImplMetal_DestroyDeviceObjects();
|
||||
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||
IMGUI_IMPL_API void ImGui_ImplMetal_UpdateTexture(ImTextureData* tex);
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// C++ API
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Enable Metal C++ binding support with '#define IMGUI_IMPL_METAL_CPP' in your imconfig.h file
|
||||
// More info about using Metal from C++: https://developer.apple.com/metal/cpp/
|
||||
|
||||
#ifdef IMGUI_IMPL_METAL_CPP
|
||||
#include <Metal/Metal.hpp>
|
||||
#ifndef __OBJC__
|
||||
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
IMGUI_IMPL_API bool ImGui_ImplMetal_Init(MTL::Device* device);
|
||||
IMGUI_IMPL_API void ImGui_ImplMetal_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplMetal_NewFrame(MTL::RenderPassDescriptor* renderPassDescriptor);
|
||||
IMGUI_IMPL_API void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data,
|
||||
MTL::CommandBuffer* commandBuffer,
|
||||
MTL::RenderCommandEncoder* commandEncoder);
|
||||
|
||||
// Called by Init/NewFrame/Shutdown
|
||||
IMGUI_IMPL_API bool ImGui_ImplMetal_CreateDeviceObjects(MTL::Device* device);
|
||||
IMGUI_IMPL_API void ImGui_ImplMetal_DestroyDeviceObjects();
|
||||
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||
IMGUI_IMPL_API void ImGui_ImplMetal_UpdateTexture(ImTextureData* tex);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
@@ -2,15 +2,37 @@
|
||||
// This needs to be used along with a Platform Backend (e.g. OSX)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'MTLTexture' as ImTextureID. Read the FAQ about ImTextureID!
|
||||
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
|
||||
// [X] Renderer: User texture binding. Use 'MTLTexture' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-04-28: Added support for standard draw callbacks (in platform_io): DrawCallback_SetSamplerLinear and DrawCallback_SetSamplerNearest. (#9378, #9381)
|
||||
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState (others are not yet supported). (#9378)
|
||||
// 2026-04-14: Metal: use a dedicated bufferCacheLock to avoid crashing when bufferCache is replaced by a new object while being used for @synchronize(). (#9367)
|
||||
// 2026-04-03: Metal: avoid redundant vertex buffer bind in SetupRenderState. (#9343)
|
||||
// 2026-03-19: Fixed issue in ImGui_ImplMetal_RenderDrawData() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295, #9310)
|
||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||
// 2025-06-11: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplMetal_CreateFontsTexture() and ImGui_ImplMetal_DestroyFontsTexture().
|
||||
// 2025-02-03: Metal: Crash fix. (#8367)
|
||||
// 2025-01-08: Metal: Fixed memory leaks when using metal-cpp (#8276, #8166) or when using multiple contexts (#7419).
|
||||
// 2022-08-23: Metal: Update deprecated property 'sampleCount'->'rasterSampleCount'.
|
||||
// 2022-07-05: Metal: Add dispatch synchronization.
|
||||
// 2022-06-30: Metal: Use __bridge for ARC based systems.
|
||||
// 2022-06-01: Metal: Fixed null dereference on exit inside command buffer completion handler.
|
||||
// 2022-04-27: Misc: Store backend data in a per-context struct, allowing to use this backend with multiple contexts.
|
||||
// 2022-01-03: Metal: Ignore ImDrawCmd where ElemCount == 0 (very rare but can technically be manufactured by user code).
|
||||
// 2021-12-30: Metal: Added Metal C++ support. Enable with '#define IMGUI_IMPL_METAL_CPP' in your imconfig.h file.
|
||||
// 2021-08-24: Metal: Fixed a crash when clipping rect larger than framebuffer is submitted. (#4464)
|
||||
// 2021-05-19: Metal: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
|
||||
// 2021-02-18: Metal: Change blending equation to preserve alpha in output buffer.
|
||||
// 2021-01-25: Metal: Fixed texture storage mode when building on Mac Catalyst.
|
||||
@@ -21,126 +43,421 @@
|
||||
// 2018-07-05: Metal: Added new Metal backend implementation.
|
||||
|
||||
#include "imgui.h"
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include "imgui_impl_metal.h"
|
||||
|
||||
#import <time.h>
|
||||
#import <Metal/Metal.h>
|
||||
// #import <QuartzCore/CAMetalLayer.h> // Not supported in XCode 9.2. Maybe a macro to detect the SDK version can be used (something like #if MACOS_SDK >= 10.13 ...)
|
||||
#import <simd/simd.h>
|
||||
|
||||
#pragma mark - Support classes
|
||||
|
||||
// A wrapper around a MTLBuffer object that knows the last time it was reused
|
||||
@interface MetalBuffer : NSObject
|
||||
@property (nonatomic, strong) id<MTLBuffer> buffer;
|
||||
@property (nonatomic, assign) NSTimeInterval lastReuseTime;
|
||||
@property (nonatomic, assign) double lastReuseTime;
|
||||
- (instancetype)initWithBuffer:(id<MTLBuffer>)buffer;
|
||||
@end
|
||||
|
||||
// An object that encapsulates the data necessary to uniquely identify a
|
||||
// render pipeline state. These are used as cache keys.
|
||||
@interface FramebufferDescriptor : NSObject<NSCopying>
|
||||
@property (nonatomic, assign) unsigned long sampleCount;
|
||||
@property (nonatomic, assign) unsigned long sampleCount;
|
||||
@property (nonatomic, assign) MTLPixelFormat colorPixelFormat;
|
||||
@property (nonatomic, assign) MTLPixelFormat depthPixelFormat;
|
||||
@property (nonatomic, assign) MTLPixelFormat stencilPixelFormat;
|
||||
- (instancetype)initWithRenderPassDescriptor:(MTLRenderPassDescriptor *)renderPassDescriptor;
|
||||
- (instancetype)initWithRenderPassDescriptor:(MTLRenderPassDescriptor*)renderPassDescriptor;
|
||||
@end
|
||||
|
||||
@interface MetalTexture : NSObject
|
||||
@property (nonatomic, strong) id<MTLTexture> metalTexture;
|
||||
- (instancetype)initWithTexture:(id<MTLTexture>)metalTexture;
|
||||
@end
|
||||
|
||||
// A singleton that stores long-lived objects that are needed by the Metal
|
||||
// renderer backend. Stores the render pipeline state cache and the default
|
||||
// font texture, and manages the reusable buffer cache.
|
||||
@interface MetalContext : NSObject
|
||||
@property (nonatomic, strong) id<MTLDepthStencilState> depthStencilState;
|
||||
@property (nonatomic, strong) FramebufferDescriptor *framebufferDescriptor; // framebuffer descriptor for current frame; transient
|
||||
@property (nonatomic, strong) NSMutableDictionary *renderPipelineStateCache; // pipeline cache; keyed on framebuffer descriptors
|
||||
@property (nonatomic, strong, nullable) id<MTLTexture> fontTexture;
|
||||
@property (nonatomic, strong) NSMutableArray<MetalBuffer *> *bufferCache;
|
||||
@property (nonatomic, assign) NSTimeInterval lastBufferCachePurge;
|
||||
- (void)makeDeviceObjectsWithDevice:(id<MTLDevice>)device;
|
||||
- (void)makeFontTextureWithDevice:(id<MTLDevice>)device;
|
||||
- (MetalBuffer *)dequeueReusableBufferOfLength:(NSUInteger)length device:(id<MTLDevice>)device;
|
||||
- (void)enqueueReusableBuffer:(MetalBuffer *)buffer;
|
||||
- (id<MTLRenderPipelineState>)renderPipelineStateForFrameAndDevice:(id<MTLDevice>)device;
|
||||
- (void)emptyRenderPipelineStateCache;
|
||||
- (void)setupRenderState:(ImDrawData *)drawData
|
||||
commandBuffer:(id<MTLCommandBuffer>)commandBuffer
|
||||
commandEncoder:(id<MTLRenderCommandEncoder>)commandEncoder
|
||||
renderPipelineState:(id<MTLRenderPipelineState>)renderPipelineState
|
||||
vertexBuffer:(MetalBuffer *)vertexBuffer
|
||||
vertexBufferOffset:(size_t)vertexBufferOffset;
|
||||
- (void)renderDrawData:(ImDrawData *)drawData
|
||||
commandBuffer:(id<MTLCommandBuffer>)commandBuffer
|
||||
commandEncoder:(id<MTLRenderCommandEncoder>)commandEncoder;
|
||||
@property (nonatomic, strong) id<MTLDevice> device;
|
||||
@property (nonatomic, strong) id<MTLDepthStencilState> depthStencilState;
|
||||
@property (nonatomic, strong) id<MTLSamplerState> samplerStateLinear;
|
||||
@property (nonatomic, strong) id<MTLSamplerState> samplerStateNearest;
|
||||
@property (nonatomic, strong) FramebufferDescriptor* framebufferDescriptor; // framebuffer descriptor for current frame; transient
|
||||
@property (nonatomic, strong) NSMutableDictionary* renderPipelineStateCache; // pipeline cache; keyed on framebuffer descriptors
|
||||
@property (nonatomic, strong) NSMutableArray<MetalBuffer*>* bufferCache;
|
||||
@property (nonatomic, strong) NSObject* bufferCacheLock;
|
||||
@property (nonatomic, assign) double lastBufferCachePurge;
|
||||
- (MetalBuffer*)dequeueReusableBufferOfLength:(NSUInteger)length device:(id<MTLDevice>)device;
|
||||
- (id<MTLRenderPipelineState>)renderPipelineStateForFramebufferDescriptor:(FramebufferDescriptor*)descriptor device:(id<MTLDevice>)device;
|
||||
@end
|
||||
|
||||
static MetalContext *g_sharedMetalContext = nil;
|
||||
|
||||
#pragma mark - ImGui API implementation
|
||||
|
||||
bool ImGui_ImplMetal_Init(id<MTLDevice> device)
|
||||
struct ImGui_ImplMetal_Data
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.BackendRendererName = "imgui_impl_metal";
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
MetalContext* SharedMetalContext;
|
||||
id<MTLRenderCommandEncoder> RenderCommandEncoder;
|
||||
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
g_sharedMetalContext = [[MetalContext alloc] init];
|
||||
});
|
||||
ImGui_ImplMetal_Data() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
ImGui_ImplMetal_CreateDeviceObjects(device);
|
||||
static ImGui_ImplMetal_Data* ImGui_ImplMetal_GetBackendData() { return ImGui::GetCurrentContext() ? (ImGui_ImplMetal_Data*)ImGui::GetIO().BackendRendererUserData : nullptr; }
|
||||
static void ImGui_ImplMetal_DestroyBackendData(){ IM_DELETE(ImGui_ImplMetal_GetBackendData()); }
|
||||
|
||||
return true;
|
||||
static inline CFTimeInterval GetMachAbsoluteTimeInSeconds() { return (CFTimeInterval)(double)(clock_gettime_nsec_np(CLOCK_UPTIME_RAW) / 1e9); }
|
||||
|
||||
#ifdef IMGUI_IMPL_METAL_CPP
|
||||
|
||||
#pragma mark - Dear ImGui Metal C++ Backend API
|
||||
|
||||
bool ImGui_ImplMetal_Init(MTL::Device* device)
|
||||
{
|
||||
return ImGui_ImplMetal_Init((__bridge id<MTLDevice>)(device));
|
||||
}
|
||||
|
||||
void ImGui_ImplMetal_Shutdown()
|
||||
void ImGui_ImplMetal_NewFrame(MTL::RenderPassDescriptor* renderPassDescriptor)
|
||||
{
|
||||
ImGui_ImplMetal_DestroyDeviceObjects();
|
||||
ImGui_ImplMetal_NewFrame((__bridge MTLRenderPassDescriptor*)(renderPassDescriptor));
|
||||
}
|
||||
|
||||
void ImGui_ImplMetal_NewFrame(MTLRenderPassDescriptor *renderPassDescriptor)
|
||||
void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data,
|
||||
MTL::CommandBuffer* commandBuffer,
|
||||
MTL::RenderCommandEncoder* commandEncoder)
|
||||
{
|
||||
IM_ASSERT(g_sharedMetalContext != nil && "No Metal context. Did you call ImGui_ImplMetal_Init() ?");
|
||||
ImGui_ImplMetal_RenderDrawData(draw_data,
|
||||
(__bridge id<MTLCommandBuffer>)(commandBuffer),
|
||||
(__bridge id<MTLRenderCommandEncoder>)(commandEncoder));
|
||||
|
||||
g_sharedMetalContext.framebufferDescriptor = [[FramebufferDescriptor alloc] initWithRenderPassDescriptor:renderPassDescriptor];
|
||||
}
|
||||
|
||||
bool ImGui_ImplMetal_CreateDeviceObjects(MTL::Device* device)
|
||||
{
|
||||
return ImGui_ImplMetal_CreateDeviceObjects((__bridge id<MTLDevice>)(device));
|
||||
}
|
||||
|
||||
#endif // #ifdef IMGUI_IMPL_METAL_CPP
|
||||
|
||||
#pragma mark - Dear ImGui Metal Backend API
|
||||
|
||||
void ImGui_ImplMetal_NewFrame(MTLRenderPassDescriptor* renderPassDescriptor)
|
||||
{
|
||||
ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData();
|
||||
IM_ASSERT(bd != nil && "Context or backend not initialized! Did you call ImGui_ImplMetal_Init()?");
|
||||
#ifdef IMGUI_IMPL_METAL_CPP
|
||||
bd->SharedMetalContext.framebufferDescriptor = [[[FramebufferDescriptor alloc] initWithRenderPassDescriptor:renderPassDescriptor]autorelease];
|
||||
#else
|
||||
bd->SharedMetalContext.framebufferDescriptor = [[FramebufferDescriptor alloc] initWithRenderPassDescriptor:renderPassDescriptor];
|
||||
#endif
|
||||
if (bd->SharedMetalContext.depthStencilState == nil)
|
||||
ImGui_ImplMetal_CreateDeviceObjects(bd->SharedMetalContext.device);
|
||||
}
|
||||
|
||||
static void ImGui_ImplMetal_SetupRenderState(ImDrawData* draw_data, id<MTLCommandBuffer> commandBuffer,
|
||||
id<MTLRenderCommandEncoder> commandEncoder, id<MTLRenderPipelineState> renderPipelineState,
|
||||
MetalBuffer* vertexBuffer, size_t vertexBufferOffset)
|
||||
{
|
||||
IM_UNUSED(commandBuffer);
|
||||
ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData();
|
||||
[commandEncoder setCullMode:MTLCullModeNone];
|
||||
[commandEncoder setDepthStencilState:bd->SharedMetalContext.depthStencilState];
|
||||
|
||||
// Setup viewport, orthographic projection matrix
|
||||
// Our visible imgui space lies from draw_data->DisplayPos (top left) to
|
||||
// draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin is typically (0,0) for single viewport apps.
|
||||
MTLViewport viewport =
|
||||
{
|
||||
.originX = 0.0,
|
||||
.originY = 0.0,
|
||||
.width = (double)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x),
|
||||
.height = (double)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y),
|
||||
.znear = 0.0,
|
||||
.zfar = 1.0
|
||||
};
|
||||
[commandEncoder setViewport:viewport];
|
||||
|
||||
float L = draw_data->DisplayPos.x;
|
||||
float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
|
||||
float T = draw_data->DisplayPos.y;
|
||||
float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
|
||||
float N = (float)viewport.znear;
|
||||
float F = (float)viewport.zfar;
|
||||
const float ortho_projection[4][4] =
|
||||
{
|
||||
{ 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 1/(F-N), 0.0f },
|
||||
{ (R+L)/(L-R), (T+B)/(B-T), N/(F-N), 1.0f },
|
||||
};
|
||||
[commandEncoder setVertexBytes:&ortho_projection length:sizeof(ortho_projection) atIndex:1];
|
||||
|
||||
[commandEncoder setRenderPipelineState:renderPipelineState];
|
||||
[commandEncoder setFragmentSamplerState:bd->SharedMetalContext.samplerStateLinear atIndex:0];
|
||||
|
||||
[commandEncoder setVertexBuffer:vertexBuffer.buffer offset:vertexBufferOffset atIndex:0];
|
||||
}
|
||||
|
||||
// Draw callbacks
|
||||
static void ImGui_ImplMetal_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
||||
static void ImGui_ImplMetal_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData(); [bd->RenderCommandEncoder setFragmentSamplerState:bd->SharedMetalContext.samplerStateLinear atIndex:0]; }
|
||||
static void ImGui_ImplMetal_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData(); [bd->RenderCommandEncoder setFragmentSamplerState:bd->SharedMetalContext.samplerStateNearest atIndex:0]; }
|
||||
|
||||
// Metal Render function.
|
||||
void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, id<MTLCommandBuffer> commandBuffer, id<MTLRenderCommandEncoder> commandEncoder)
|
||||
{
|
||||
[g_sharedMetalContext renderDrawData:draw_data commandBuffer:commandBuffer commandEncoder:commandEncoder];
|
||||
ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData();
|
||||
MetalContext* ctx = bd->SharedMetalContext;
|
||||
|
||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
|
||||
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
|
||||
if (fb_width <= 0 || fb_height <= 0 || draw_data->CmdLists.Size == 0)
|
||||
return;
|
||||
|
||||
// Catch up with texture updates. Most of the times, the list will have 1 element with an OK status, aka nothing to do.
|
||||
// (This almost always points to ImGui::GetPlatformIO().Textures[] but is part of ImDrawData to allow overriding or disabling texture updates).
|
||||
if (draw_data->Textures != nullptr)
|
||||
for (ImTextureData* tex : *draw_data->Textures)
|
||||
if (tex->Status != ImTextureStatus_OK)
|
||||
ImGui_ImplMetal_UpdateTexture(tex);
|
||||
|
||||
// Try to retrieve a render pipeline state that is compatible with the framebuffer config for this frame
|
||||
// The hit rate for this cache should be very near 100%.
|
||||
id<MTLRenderPipelineState> renderPipelineState = ctx.renderPipelineStateCache[ctx.framebufferDescriptor];
|
||||
if (renderPipelineState == nil)
|
||||
{
|
||||
// No luck; make a new render pipeline state
|
||||
renderPipelineState = [ctx renderPipelineStateForFramebufferDescriptor:ctx.framebufferDescriptor device:commandBuffer.device];
|
||||
|
||||
// Cache render pipeline state for later reuse
|
||||
ctx.renderPipelineStateCache[ctx.framebufferDescriptor] = renderPipelineState;
|
||||
}
|
||||
|
||||
size_t vertexBufferLength = (size_t)draw_data->TotalVtxCount * sizeof(ImDrawVert);
|
||||
size_t indexBufferLength = (size_t)draw_data->TotalIdxCount * sizeof(ImDrawIdx);
|
||||
MetalBuffer* vertexBuffer = [ctx dequeueReusableBufferOfLength:vertexBufferLength device:commandBuffer.device];
|
||||
MetalBuffer* indexBuffer = [ctx dequeueReusableBufferOfLength:indexBufferLength device:commandBuffer.device];
|
||||
|
||||
bd->RenderCommandEncoder = commandEncoder;
|
||||
ImGui_ImplMetal_SetupRenderState(draw_data, commandBuffer, commandEncoder, renderPipelineState, vertexBuffer, 0);
|
||||
|
||||
// Will project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
|
||||
ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2)
|
||||
|
||||
// Render command lists
|
||||
size_t vertexBufferOffset = 0;
|
||||
size_t indexBufferOffset = 0;
|
||||
for (const ImDrawList* draw_list : draw_data->CmdLists)
|
||||
{
|
||||
memcpy((char*)vertexBuffer.buffer.contents + vertexBufferOffset, draw_list->VtxBuffer.Data, (size_t)draw_list->VtxBuffer.Size * sizeof(ImDrawVert));
|
||||
memcpy((char*)indexBuffer.buffer.contents + indexBufferOffset, draw_list->IdxBuffer.Data, (size_t)draw_list->IdxBuffer.Size * sizeof(ImDrawIdx));
|
||||
|
||||
for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback)
|
||||
{
|
||||
// User callback, registered via ImDrawList::AddCallback()
|
||||
if (pcmd->UserCallback == ImGui_ImplMetal_DrawCallback_ResetRenderState)
|
||||
ImGui_ImplMetal_SetupRenderState(draw_data, commandBuffer, commandEncoder, renderPipelineState, vertexBuffer, vertexBufferOffset);
|
||||
else
|
||||
pcmd->UserCallback(draw_list, pcmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
|
||||
ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
|
||||
|
||||
// Clamp to viewport as setScissorRect() won't accept values that are off bounds
|
||||
if (clip_min.x < 0.0f) { clip_min.x = 0.0f; }
|
||||
if (clip_min.y < 0.0f) { clip_min.y = 0.0f; }
|
||||
if (clip_max.x > (float)fb_width) { clip_max.x = (float)fb_width; }
|
||||
if (clip_max.y > (float)fb_height) { clip_max.y = (float)fb_height; }
|
||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||
continue;
|
||||
if (pcmd->ElemCount == 0) // drawIndexedPrimitives() validation doesn't accept this
|
||||
continue;
|
||||
|
||||
// Apply scissor/clipping rectangle
|
||||
MTLScissorRect scissorRect =
|
||||
{
|
||||
.x = NSUInteger(clip_min.x),
|
||||
.y = NSUInteger(clip_min.y),
|
||||
.width = NSUInteger(clip_max.x - clip_min.x),
|
||||
.height = NSUInteger(clip_max.y - clip_min.y)
|
||||
};
|
||||
[commandEncoder setScissorRect:scissorRect];
|
||||
|
||||
// Bind texture, Draw
|
||||
ImTextureID tex_id = pcmd->GetTexID();
|
||||
if (tex_id != ImTextureID_Invalid)
|
||||
[commandEncoder setFragmentTexture:(__bridge id<MTLTexture>)(void*)(intptr_t)(tex_id) atIndex:0];
|
||||
|
||||
[commandEncoder setVertexBufferOffset:(vertexBufferOffset + pcmd->VtxOffset * sizeof(ImDrawVert)) atIndex:0];
|
||||
[commandEncoder drawIndexedPrimitives:MTLPrimitiveTypeTriangle
|
||||
indexCount:pcmd->ElemCount
|
||||
indexType:sizeof(ImDrawIdx) == 2 ? MTLIndexTypeUInt16 : MTLIndexTypeUInt32
|
||||
indexBuffer:indexBuffer.buffer
|
||||
indexBufferOffset:indexBufferOffset + pcmd->IdxOffset * sizeof(ImDrawIdx)];
|
||||
}
|
||||
}
|
||||
|
||||
vertexBufferOffset += (size_t)draw_list->VtxBuffer.Size * sizeof(ImDrawVert);
|
||||
indexBufferOffset += (size_t)draw_list->IdxBuffer.Size * sizeof(ImDrawIdx);
|
||||
}
|
||||
|
||||
MetalContext* sharedMetalContext = bd->SharedMetalContext;
|
||||
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer>)
|
||||
{
|
||||
@synchronized(sharedMetalContext.bufferCacheLock)
|
||||
{
|
||||
[sharedMetalContext.bufferCache addObject:vertexBuffer];
|
||||
[sharedMetalContext.bufferCache addObject:indexBuffer];
|
||||
}
|
||||
}];
|
||||
bd->RenderCommandEncoder = nil;
|
||||
}
|
||||
|
||||
bool ImGui_ImplMetal_CreateFontsTexture(id<MTLDevice> device)
|
||||
static void ImGui_ImplMetal_DestroyTexture(ImTextureData* tex)
|
||||
{
|
||||
[g_sharedMetalContext makeFontTextureWithDevice:device];
|
||||
if (MetalTexture* backend_tex = (__bridge_transfer MetalTexture*)(tex->BackendUserData))
|
||||
{
|
||||
IM_ASSERT(backend_tex.metalTexture == (__bridge id<MTLTexture>)(void*)(intptr_t)tex->TexID);
|
||||
backend_tex.metalTexture = nil;
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.Fonts->SetTexID((__bridge void *)g_sharedMetalContext.fontTexture); // ImTextureID == void*
|
||||
|
||||
return (g_sharedMetalContext.fontTexture != nil);
|
||||
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
|
||||
tex->SetTexID(ImTextureID_Invalid);
|
||||
tex->BackendUserData = nullptr;
|
||||
}
|
||||
tex->SetStatus(ImTextureStatus_Destroyed);
|
||||
}
|
||||
|
||||
void ImGui_ImplMetal_DestroyFontsTexture()
|
||||
void ImGui_ImplMetal_UpdateTexture(ImTextureData* tex)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
g_sharedMetalContext.fontTexture = nil;
|
||||
io.Fonts->SetTexID(nullptr);
|
||||
ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData();
|
||||
if (tex->Status == ImTextureStatus_WantCreate)
|
||||
{
|
||||
// Create and upload new texture to graphics system
|
||||
//IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
|
||||
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == nullptr);
|
||||
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
|
||||
|
||||
// We are retrieving and uploading the font atlas as a 4-channels RGBA texture here.
|
||||
// In theory we could call GetTexDataAsAlpha8() and upload a 1-channel texture to save on memory access bandwidth.
|
||||
// However, using a shader designed for 1-channel texture would make it less obvious to use the ImTextureID facility to render users own textures.
|
||||
// You can make that change in your implementation.
|
||||
MTLTextureDescriptor* textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm
|
||||
width:(NSUInteger)tex->Width
|
||||
height:(NSUInteger)tex->Height
|
||||
mipmapped:NO];
|
||||
textureDescriptor.usage = MTLTextureUsageShaderRead;
|
||||
#if TARGET_OS_OSX || TARGET_OS_MACCATALYST
|
||||
textureDescriptor.storageMode = MTLStorageModeManaged;
|
||||
#else
|
||||
textureDescriptor.storageMode = MTLStorageModeShared;
|
||||
#endif
|
||||
id <MTLTexture> texture = [bd->SharedMetalContext.device newTextureWithDescriptor:textureDescriptor];
|
||||
[texture replaceRegion:MTLRegionMake2D(0, 0, (NSUInteger)tex->Width, (NSUInteger)tex->Height) mipmapLevel:0 withBytes:tex->Pixels bytesPerRow:(NSUInteger)tex->Width * 4];
|
||||
MetalTexture* backend_tex = [[MetalTexture alloc] initWithTexture:texture];
|
||||
|
||||
// Store identifiers
|
||||
tex->SetTexID((ImTextureID)(intptr_t)texture);
|
||||
tex->SetStatus(ImTextureStatus_OK);
|
||||
tex->BackendUserData = (__bridge_retained void*)(backend_tex);
|
||||
}
|
||||
else if (tex->Status == ImTextureStatus_WantUpdates)
|
||||
{
|
||||
// Update selected blocks. We only ever write to textures regions which have never been used before!
|
||||
// This backend choose to use tex->Updates[] but you can use tex->UpdateRect to upload a single region.
|
||||
MetalTexture* backend_tex = (__bridge MetalTexture*)(tex->BackendUserData);
|
||||
for (ImTextureRect& r : tex->Updates)
|
||||
{
|
||||
[backend_tex.metalTexture replaceRegion:MTLRegionMake2D((NSUInteger)r.x, (NSUInteger)r.y, (NSUInteger)r.w, (NSUInteger)r.h)
|
||||
mipmapLevel:0
|
||||
withBytes:tex->GetPixelsAt(r.x, r.y)
|
||||
bytesPerRow:(NSUInteger)tex->Width * 4];
|
||||
}
|
||||
tex->SetStatus(ImTextureStatus_OK);
|
||||
}
|
||||
else if (tex->Status == ImTextureStatus_WantDestroy && tex->UnusedFrames > 0)
|
||||
{
|
||||
ImGui_ImplMetal_DestroyTexture(tex);
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGui_ImplMetal_CreateDeviceObjects(id<MTLDevice> device)
|
||||
{
|
||||
[g_sharedMetalContext makeDeviceObjectsWithDevice:device];
|
||||
|
||||
ImGui_ImplMetal_CreateFontsTexture(device);
|
||||
ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData();
|
||||
MTLDepthStencilDescriptor* depthStencilDescriptor = [[MTLDepthStencilDescriptor alloc] init];
|
||||
depthStencilDescriptor.depthWriteEnabled = NO;
|
||||
depthStencilDescriptor.depthCompareFunction = MTLCompareFunctionAlways;
|
||||
bd->SharedMetalContext.depthStencilState = [device newDepthStencilStateWithDescriptor:depthStencilDescriptor];
|
||||
MTLSamplerDescriptor* samplerDescriptor = [[MTLSamplerDescriptor alloc] init];
|
||||
samplerDescriptor.minFilter = MTLSamplerMinMagFilterLinear;
|
||||
samplerDescriptor.magFilter = MTLSamplerMinMagFilterLinear;
|
||||
samplerDescriptor.mipFilter = MTLSamplerMipFilterLinear;
|
||||
bd->SharedMetalContext.samplerStateLinear = [device newSamplerStateWithDescriptor:samplerDescriptor];
|
||||
samplerDescriptor.minFilter = MTLSamplerMinMagFilterNearest;
|
||||
samplerDescriptor.magFilter = MTLSamplerMinMagFilterNearest;
|
||||
samplerDescriptor.mipFilter = MTLSamplerMipFilterNearest;
|
||||
bd->SharedMetalContext.samplerStateNearest = [device newSamplerStateWithDescriptor:samplerDescriptor];
|
||||
#ifdef IMGUI_IMPL_METAL_CPP
|
||||
[samplerDescriptor release];
|
||||
[depthStencilDescriptor release];
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplMetal_DestroyDeviceObjects()
|
||||
{
|
||||
ImGui_ImplMetal_DestroyFontsTexture();
|
||||
[g_sharedMetalContext emptyRenderPipelineStateCache];
|
||||
ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData();
|
||||
|
||||
// Destroy all textures
|
||||
for (ImTextureData* tex : ImGui::GetPlatformIO().Textures)
|
||||
if (tex->RefCount == 1)
|
||||
ImGui_ImplMetal_DestroyTexture(tex);
|
||||
|
||||
[bd->SharedMetalContext.renderPipelineStateCache removeAllObjects];
|
||||
bd->SharedMetalContext.samplerStateLinear = nil;
|
||||
bd->SharedMetalContext.samplerStateNearest = nil;
|
||||
}
|
||||
|
||||
bool ImGui_ImplMetal_Init(id<MTLDevice> device)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IMGUI_CHECKVERSION();
|
||||
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
||||
|
||||
ImGui_ImplMetal_Data* bd = IM_NEW(ImGui_ImplMetal_Data)();
|
||||
io.BackendRendererUserData = (void*)bd;
|
||||
io.BackendRendererName = "imgui_impl_metal";
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
||||
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
platform_io.DrawCallback_ResetRenderState = ImGui_ImplMetal_DrawCallback_ResetRenderState;
|
||||
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplMetal_DrawCallback_SetSamplerLinear;
|
||||
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplMetal_DrawCallback_SetSamplerNearest;
|
||||
|
||||
bd->SharedMetalContext = [[MetalContext alloc] init];
|
||||
bd->SharedMetalContext.device = device;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplMetal_Shutdown()
|
||||
{
|
||||
ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData();
|
||||
IM_UNUSED(bd);
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
ImGui_ImplMetal_DestroyDeviceObjects();
|
||||
ImGui_ImplMetal_DestroyBackendData();
|
||||
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
|
||||
platform_io.ClearRendererHandlers();
|
||||
}
|
||||
|
||||
#pragma mark - MetalBuffer implementation
|
||||
@@ -151,7 +468,7 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
|
||||
if ((self = [super init]))
|
||||
{
|
||||
_buffer = buffer;
|
||||
_lastReuseTime = [NSDate date].timeIntervalSince1970;
|
||||
_lastReuseTime = GetMachAbsoluteTimeInSeconds();
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -160,7 +477,7 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
|
||||
#pragma mark - FramebufferDescriptor implementation
|
||||
|
||||
@implementation FramebufferDescriptor
|
||||
- (instancetype)initWithRenderPassDescriptor:(MTLRenderPassDescriptor *)renderPassDescriptor
|
||||
- (instancetype)initWithRenderPassDescriptor:(MTLRenderPassDescriptor*)renderPassDescriptor
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
@@ -172,9 +489,9 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
|
||||
return self;
|
||||
}
|
||||
|
||||
- (nonnull id)copyWithZone:(nullable NSZone *)zone
|
||||
- (nonnull id)copyWithZone:(nullable NSZone*)zone
|
||||
{
|
||||
FramebufferDescriptor *copy = [[FramebufferDescriptor allocWithZone:zone] init];
|
||||
FramebufferDescriptor* copy = [[FramebufferDescriptor allocWithZone:zone] init];
|
||||
copy.sampleCount = self.sampleCount;
|
||||
copy.colorPixelFormat = self.colorPixelFormat;
|
||||
copy.depthPixelFormat = self.depthPixelFormat;
|
||||
@@ -194,7 +511,7 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
|
||||
|
||||
- (BOOL)isEqual:(id)object
|
||||
{
|
||||
FramebufferDescriptor *other = object;
|
||||
FramebufferDescriptor* other = object;
|
||||
if (![other isKindOfClass:[FramebufferDescriptor class]])
|
||||
return NO;
|
||||
return other.sampleCount == self.sampleCount &&
|
||||
@@ -205,82 +522,62 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - MetalTexture implementation
|
||||
|
||||
@implementation MetalTexture
|
||||
- (instancetype)initWithTexture:(id<MTLTexture>)metalTexture
|
||||
{
|
||||
if ((self = [super init]))
|
||||
self.metalTexture = metalTexture;
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - MetalContext implementation
|
||||
|
||||
@implementation MetalContext
|
||||
- (instancetype)init {
|
||||
- (instancetype)init
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
_renderPipelineStateCache = [NSMutableDictionary dictionary];
|
||||
_bufferCache = [NSMutableArray array];
|
||||
_lastBufferCachePurge = [NSDate date].timeIntervalSince1970;
|
||||
self.renderPipelineStateCache = [NSMutableDictionary dictionary];
|
||||
self.bufferCache = [NSMutableArray array];
|
||||
self.bufferCacheLock = [[NSObject alloc] init];
|
||||
_lastBufferCachePurge = GetMachAbsoluteTimeInSeconds();
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)makeDeviceObjectsWithDevice:(id<MTLDevice>)device
|
||||
- (MetalBuffer*)dequeueReusableBufferOfLength:(NSUInteger)length device:(id<MTLDevice>)device
|
||||
{
|
||||
MTLDepthStencilDescriptor *depthStencilDescriptor = [[MTLDepthStencilDescriptor alloc] init];
|
||||
depthStencilDescriptor.depthWriteEnabled = NO;
|
||||
depthStencilDescriptor.depthCompareFunction = MTLCompareFunctionAlways;
|
||||
self.depthStencilState = [device newDepthStencilStateWithDescriptor:depthStencilDescriptor];
|
||||
}
|
||||
double now = GetMachAbsoluteTimeInSeconds();
|
||||
|
||||
// We are retrieving and uploading the font atlas as a 4-channels RGBA texture here.
|
||||
// In theory we could call GetTexDataAsAlpha8() and upload a 1-channel texture to save on memory access bandwidth.
|
||||
// However, using a shader designed for 1-channel texture would make it less obvious to use the ImTextureID facility to render users own textures.
|
||||
// You can make that change in your implementation.
|
||||
- (void)makeFontTextureWithDevice:(id<MTLDevice>)device
|
||||
{
|
||||
ImGuiIO &io = ImGui::GetIO();
|
||||
unsigned char* pixels;
|
||||
int width, height;
|
||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
|
||||
MTLTextureDescriptor *textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm
|
||||
width:(NSUInteger)width
|
||||
height:(NSUInteger)height
|
||||
mipmapped:NO];
|
||||
textureDescriptor.usage = MTLTextureUsageShaderRead;
|
||||
#if TARGET_OS_OSX || TARGET_OS_MACCATALYST
|
||||
textureDescriptor.storageMode = MTLStorageModeManaged;
|
||||
#else
|
||||
textureDescriptor.storageMode = MTLStorageModeShared;
|
||||
#endif
|
||||
id <MTLTexture> texture = [device newTextureWithDescriptor:textureDescriptor];
|
||||
[texture replaceRegion:MTLRegionMake2D(0, 0, (NSUInteger)width, (NSUInteger)height) mipmapLevel:0 withBytes:pixels bytesPerRow:(NSUInteger)width * 4];
|
||||
self.fontTexture = texture;
|
||||
}
|
||||
|
||||
- (MetalBuffer *)dequeueReusableBufferOfLength:(NSUInteger)length device:(id<MTLDevice>)device
|
||||
{
|
||||
NSTimeInterval now = [NSDate date].timeIntervalSince1970;
|
||||
|
||||
// Purge old buffers that haven't been useful for a while
|
||||
if (now - self.lastBufferCachePurge > 1.0)
|
||||
@synchronized(self.bufferCacheLock)
|
||||
{
|
||||
NSMutableArray *survivors = [NSMutableArray array];
|
||||
for (MetalBuffer *candidate in self.bufferCache)
|
||||
// Purge old buffers that haven't been useful for a while
|
||||
if (now - self.lastBufferCachePurge > 1.0)
|
||||
{
|
||||
if (candidate.lastReuseTime > self.lastBufferCachePurge)
|
||||
{
|
||||
[survivors addObject:candidate];
|
||||
}
|
||||
NSMutableArray* survivors = [NSMutableArray array];
|
||||
for (MetalBuffer* candidate in self.bufferCache)
|
||||
if (candidate.lastReuseTime > self.lastBufferCachePurge)
|
||||
[survivors addObject:candidate];
|
||||
self.bufferCache = [survivors mutableCopy];
|
||||
self.lastBufferCachePurge = now;
|
||||
}
|
||||
self.bufferCache = [survivors mutableCopy];
|
||||
self.lastBufferCachePurge = now;
|
||||
}
|
||||
|
||||
// See if we have a buffer we can reuse
|
||||
MetalBuffer *bestCandidate = nil;
|
||||
for (MetalBuffer *candidate in self.bufferCache)
|
||||
if (candidate.buffer.length >= length && (bestCandidate == nil || bestCandidate.lastReuseTime > candidate.lastReuseTime))
|
||||
bestCandidate = candidate;
|
||||
// See if we have a buffer we can reuse
|
||||
MetalBuffer* bestCandidate = nil;
|
||||
for (MetalBuffer* candidate in self.bufferCache)
|
||||
if (candidate.buffer.length >= length && (bestCandidate == nil || bestCandidate.lastReuseTime > candidate.lastReuseTime))
|
||||
bestCandidate = candidate;
|
||||
|
||||
if (bestCandidate != nil)
|
||||
{
|
||||
[self.bufferCache removeObject:bestCandidate];
|
||||
bestCandidate.lastReuseTime = now;
|
||||
return bestCandidate;
|
||||
if (bestCandidate != nil)
|
||||
{
|
||||
[self.bufferCache removeObject:bestCandidate];
|
||||
bestCandidate.lastReuseTime = now;
|
||||
return bestCandidate;
|
||||
}
|
||||
}
|
||||
|
||||
// No luck; make a new buffer
|
||||
@@ -288,33 +585,12 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
|
||||
return [[MetalBuffer alloc] initWithBuffer:backing];
|
||||
}
|
||||
|
||||
- (void)enqueueReusableBuffer:(MetalBuffer *)buffer
|
||||
// Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling.
|
||||
- (id<MTLRenderPipelineState>)renderPipelineStateForFramebufferDescriptor:(FramebufferDescriptor*)descriptor device:(id<MTLDevice>)device
|
||||
{
|
||||
[self.bufferCache addObject:buffer];
|
||||
}
|
||||
NSError* error = nil;
|
||||
|
||||
- (_Nullable id<MTLRenderPipelineState>)renderPipelineStateForFrameAndDevice:(id<MTLDevice>)device
|
||||
{
|
||||
// Try to retrieve a render pipeline state that is compatible with the framebuffer config for this frame
|
||||
// The hit rate for this cache should be very near 100%.
|
||||
id<MTLRenderPipelineState> renderPipelineState = self.renderPipelineStateCache[self.framebufferDescriptor];
|
||||
|
||||
if (renderPipelineState == nil)
|
||||
{
|
||||
// No luck; make a new render pipeline state
|
||||
renderPipelineState = [self _renderPipelineStateForFramebufferDescriptor:self.framebufferDescriptor device:device];
|
||||
// Cache render pipeline state for later reuse
|
||||
self.renderPipelineStateCache[self.framebufferDescriptor] = renderPipelineState;
|
||||
}
|
||||
|
||||
return renderPipelineState;
|
||||
}
|
||||
|
||||
- (id<MTLRenderPipelineState>)_renderPipelineStateForFramebufferDescriptor:(FramebufferDescriptor *)descriptor device:(id<MTLDevice>)device
|
||||
{
|
||||
NSError *error = nil;
|
||||
|
||||
NSString *shaderSource = @""
|
||||
NSString* shaderSource = @""
|
||||
"#include <metal_stdlib>\n"
|
||||
"using namespace metal;\n"
|
||||
"\n"
|
||||
@@ -344,9 +620,9 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
|
||||
"}\n"
|
||||
"\n"
|
||||
"fragment half4 fragment_main(VertexOut in [[stage_in]],\n"
|
||||
" texture2d<half, access::sample> texture [[texture(0)]]) {\n"
|
||||
" constexpr sampler linearSampler(coord::normalized, min_filter::linear, mag_filter::linear, mip_filter::linear);\n"
|
||||
" half4 texColor = texture.sample(linearSampler, in.texCoords);\n"
|
||||
" texture2d<half, access::sample> texture [[texture(0)]],\n"
|
||||
" sampler textureSampler [[sampler(0)]]) {\n"
|
||||
" half4 texColor = texture.sample(textureSampler, in.texCoords);\n"
|
||||
" return half4(in.color) * texColor;\n"
|
||||
"}\n";
|
||||
|
||||
@@ -366,25 +642,25 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
|
||||
return nil;
|
||||
}
|
||||
|
||||
MTLVertexDescriptor *vertexDescriptor = [MTLVertexDescriptor vertexDescriptor];
|
||||
vertexDescriptor.attributes[0].offset = IM_OFFSETOF(ImDrawVert, pos);
|
||||
MTLVertexDescriptor* vertexDescriptor = [MTLVertexDescriptor vertexDescriptor];
|
||||
vertexDescriptor.attributes[0].offset = offsetof(ImDrawVert, pos);
|
||||
vertexDescriptor.attributes[0].format = MTLVertexFormatFloat2; // position
|
||||
vertexDescriptor.attributes[0].bufferIndex = 0;
|
||||
vertexDescriptor.attributes[1].offset = IM_OFFSETOF(ImDrawVert, uv);
|
||||
vertexDescriptor.attributes[1].offset = offsetof(ImDrawVert, uv);
|
||||
vertexDescriptor.attributes[1].format = MTLVertexFormatFloat2; // texCoords
|
||||
vertexDescriptor.attributes[1].bufferIndex = 0;
|
||||
vertexDescriptor.attributes[2].offset = IM_OFFSETOF(ImDrawVert, col);
|
||||
vertexDescriptor.attributes[2].offset = offsetof(ImDrawVert, col);
|
||||
vertexDescriptor.attributes[2].format = MTLVertexFormatUChar4; // color
|
||||
vertexDescriptor.attributes[2].bufferIndex = 0;
|
||||
vertexDescriptor.layouts[0].stepRate = 1;
|
||||
vertexDescriptor.layouts[0].stepFunction = MTLVertexStepFunctionPerVertex;
|
||||
vertexDescriptor.layouts[0].stride = sizeof(ImDrawVert);
|
||||
|
||||
MTLRenderPipelineDescriptor *pipelineDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
|
||||
MTLRenderPipelineDescriptor* pipelineDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
|
||||
pipelineDescriptor.vertexFunction = vertexFunction;
|
||||
pipelineDescriptor.fragmentFunction = fragmentFunction;
|
||||
pipelineDescriptor.vertexDescriptor = vertexDescriptor;
|
||||
pipelineDescriptor.sampleCount = self.framebufferDescriptor.sampleCount;
|
||||
pipelineDescriptor.rasterSampleCount = self.framebufferDescriptor.sampleCount;
|
||||
pipelineDescriptor.colorAttachments[0].pixelFormat = self.framebufferDescriptor.colorPixelFormat;
|
||||
pipelineDescriptor.colorAttachments[0].blendingEnabled = YES;
|
||||
pipelineDescriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd;
|
||||
@@ -398,156 +674,13 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
|
||||
|
||||
id<MTLRenderPipelineState> renderPipelineState = [device newRenderPipelineStateWithDescriptor:pipelineDescriptor error:&error];
|
||||
if (error != nil)
|
||||
{
|
||||
NSLog(@"Error: failed to create Metal pipeline state: %@", error);
|
||||
}
|
||||
|
||||
return renderPipelineState;
|
||||
}
|
||||
|
||||
- (void)emptyRenderPipelineStateCache
|
||||
{
|
||||
[self.renderPipelineStateCache removeAllObjects];
|
||||
}
|
||||
|
||||
- (void)setupRenderState:(ImDrawData *)drawData
|
||||
commandBuffer:(id<MTLCommandBuffer>)commandBuffer
|
||||
commandEncoder:(id<MTLRenderCommandEncoder>)commandEncoder
|
||||
renderPipelineState:(id<MTLRenderPipelineState>)renderPipelineState
|
||||
vertexBuffer:(MetalBuffer *)vertexBuffer
|
||||
vertexBufferOffset:(size_t)vertexBufferOffset
|
||||
{
|
||||
[commandEncoder setCullMode:MTLCullModeNone];
|
||||
[commandEncoder setDepthStencilState:g_sharedMetalContext.depthStencilState];
|
||||
|
||||
// Setup viewport, orthographic projection matrix
|
||||
// Our visible imgui space lies from draw_data->DisplayPos (top left) to
|
||||
// draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin is typically (0,0) for single viewport apps.
|
||||
MTLViewport viewport =
|
||||
{
|
||||
.originX = 0.0,
|
||||
.originY = 0.0,
|
||||
.width = (double)(drawData->DisplaySize.x * drawData->FramebufferScale.x),
|
||||
.height = (double)(drawData->DisplaySize.y * drawData->FramebufferScale.y),
|
||||
.znear = 0.0,
|
||||
.zfar = 1.0
|
||||
};
|
||||
[commandEncoder setViewport:viewport];
|
||||
|
||||
float L = drawData->DisplayPos.x;
|
||||
float R = drawData->DisplayPos.x + drawData->DisplaySize.x;
|
||||
float T = drawData->DisplayPos.y;
|
||||
float B = drawData->DisplayPos.y + drawData->DisplaySize.y;
|
||||
float N = (float)viewport.znear;
|
||||
float F = (float)viewport.zfar;
|
||||
const float ortho_projection[4][4] =
|
||||
{
|
||||
{ 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 1/(F-N), 0.0f },
|
||||
{ (R+L)/(L-R), (T+B)/(B-T), N/(F-N), 1.0f },
|
||||
};
|
||||
[commandEncoder setVertexBytes:&ortho_projection length:sizeof(ortho_projection) atIndex:1];
|
||||
|
||||
[commandEncoder setRenderPipelineState:renderPipelineState];
|
||||
|
||||
[commandEncoder setVertexBuffer:vertexBuffer.buffer offset:0 atIndex:0];
|
||||
[commandEncoder setVertexBufferOffset:vertexBufferOffset atIndex:0];
|
||||
}
|
||||
|
||||
- (void)renderDrawData:(ImDrawData *)drawData
|
||||
commandBuffer:(id<MTLCommandBuffer>)commandBuffer
|
||||
commandEncoder:(id<MTLRenderCommandEncoder>)commandEncoder
|
||||
{
|
||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||
int fb_width = (int)(drawData->DisplaySize.x * drawData->FramebufferScale.x);
|
||||
int fb_height = (int)(drawData->DisplaySize.y * drawData->FramebufferScale.y);
|
||||
if (fb_width <= 0 || fb_height <= 0 || drawData->CmdListsCount == 0)
|
||||
return;
|
||||
|
||||
id<MTLRenderPipelineState> renderPipelineState = [self renderPipelineStateForFrameAndDevice:commandBuffer.device];
|
||||
|
||||
size_t vertexBufferLength = (size_t)drawData->TotalVtxCount * sizeof(ImDrawVert);
|
||||
size_t indexBufferLength = (size_t)drawData->TotalIdxCount * sizeof(ImDrawIdx);
|
||||
MetalBuffer* vertexBuffer = [self dequeueReusableBufferOfLength:vertexBufferLength device:commandBuffer.device];
|
||||
MetalBuffer* indexBuffer = [self dequeueReusableBufferOfLength:indexBufferLength device:commandBuffer.device];
|
||||
|
||||
[self setupRenderState:drawData commandBuffer:commandBuffer commandEncoder:commandEncoder renderPipelineState:renderPipelineState vertexBuffer:vertexBuffer vertexBufferOffset:0];
|
||||
|
||||
// Will project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_off = drawData->DisplayPos; // (0,0) unless using multi-viewports
|
||||
ImVec2 clip_scale = drawData->FramebufferScale; // (1,1) unless using retina display which are often (2,2)
|
||||
|
||||
// Render command lists
|
||||
size_t vertexBufferOffset = 0;
|
||||
size_t indexBufferOffset = 0;
|
||||
for (int n = 0; n < drawData->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = drawData->CmdLists[n];
|
||||
|
||||
memcpy((char *)vertexBuffer.buffer.contents + vertexBufferOffset, cmd_list->VtxBuffer.Data, (size_t)cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));
|
||||
memcpy((char *)indexBuffer.buffer.contents + indexBufferOffset, cmd_list->IdxBuffer.Data, (size_t)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
|
||||
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback)
|
||||
{
|
||||
// User callback, registered via ImDrawList::AddCallback()
|
||||
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
|
||||
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
|
||||
[self setupRenderState:drawData commandBuffer:commandBuffer commandEncoder:commandEncoder renderPipelineState:renderPipelineState vertexBuffer:vertexBuffer vertexBufferOffset:vertexBufferOffset];
|
||||
else
|
||||
pcmd->UserCallback(cmd_list, pcmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Project scissor/clipping rectangles into framebuffer space
|
||||
ImVec4 clip_rect;
|
||||
clip_rect.x = (pcmd->ClipRect.x - clip_off.x) * clip_scale.x;
|
||||
clip_rect.y = (pcmd->ClipRect.y - clip_off.y) * clip_scale.y;
|
||||
clip_rect.z = (pcmd->ClipRect.z - clip_off.x) * clip_scale.x;
|
||||
clip_rect.w = (pcmd->ClipRect.w - clip_off.y) * clip_scale.y;
|
||||
|
||||
if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f)
|
||||
{
|
||||
// Apply scissor/clipping rectangle
|
||||
MTLScissorRect scissorRect =
|
||||
{
|
||||
.x = NSUInteger(clip_rect.x),
|
||||
.y = NSUInteger(clip_rect.y),
|
||||
.width = NSUInteger(clip_rect.z - clip_rect.x),
|
||||
.height = NSUInteger(clip_rect.w - clip_rect.y)
|
||||
};
|
||||
[commandEncoder setScissorRect:scissorRect];
|
||||
|
||||
|
||||
// Bind texture, Draw
|
||||
if (ImTextureID tex_id = pcmd->GetTexID())
|
||||
[commandEncoder setFragmentTexture:(__bridge id<MTLTexture>)(tex_id) atIndex:0];
|
||||
|
||||
[commandEncoder setVertexBufferOffset:(vertexBufferOffset + pcmd->VtxOffset * sizeof(ImDrawVert)) atIndex:0];
|
||||
[commandEncoder drawIndexedPrimitives:MTLPrimitiveTypeTriangle
|
||||
indexCount:pcmd->ElemCount
|
||||
indexType:sizeof(ImDrawIdx) == 2 ? MTLIndexTypeUInt16 : MTLIndexTypeUInt32
|
||||
indexBuffer:indexBuffer.buffer
|
||||
indexBufferOffset:indexBufferOffset + pcmd->IdxOffset * sizeof(ImDrawIdx)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vertexBufferOffset += (size_t)cmd_list->VtxBuffer.Size * sizeof(ImDrawVert);
|
||||
indexBufferOffset += (size_t)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx);
|
||||
}
|
||||
|
||||
__weak id weakSelf = self;
|
||||
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer>)
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[weakSelf enqueueReusableBuffer:vertexBuffer];
|
||||
[weakSelf enqueueReusableBuffer:indexBuffer];
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
102
backends/imgui_impl_null.cpp
Normal file
102
backends/imgui_impl_null.cpp
Normal file
@@ -0,0 +1,102 @@
|
||||
// dear imgui: Null Platform+Renderer Backends
|
||||
// This is designed if you need to use a blind Dear Imgui context with no input and no output.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2025-11-17: Initial version.
|
||||
|
||||
#include "imgui.h"
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include "imgui_impl_null.h"
|
||||
|
||||
// Clang/GCC warnings with -Weverything
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast // yes, they are more terse.
|
||||
#endif
|
||||
|
||||
IMGUI_IMPL_API bool ImGui_ImplNull_Init()
|
||||
{
|
||||
ImGui_ImplNullPlatform_Init();
|
||||
ImGui_ImplNullRender_Init();
|
||||
return true;
|
||||
}
|
||||
|
||||
IMGUI_IMPL_API void ImGui_ImplNull_Shutdown()
|
||||
{
|
||||
ImGui_ImplNullRender_Shutdown();
|
||||
ImGui_ImplNullPlatform_Shutdown();
|
||||
}
|
||||
|
||||
IMGUI_IMPL_API void ImGui_ImplNull_NewFrame()
|
||||
{
|
||||
ImGui_ImplNullPlatform_NewFrame();
|
||||
ImGui_ImplNullRender_NewFrame();
|
||||
}
|
||||
|
||||
IMGUI_IMPL_API bool ImGui_ImplNullPlatform_Init()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors;
|
||||
return true;
|
||||
}
|
||||
|
||||
IMGUI_IMPL_API void ImGui_ImplNullPlatform_Shutdown()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.BackendFlags &= ~ImGuiBackendFlags_HasMouseCursors;
|
||||
}
|
||||
|
||||
IMGUI_IMPL_API void ImGui_ImplNullPlatform_NewFrame()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.DisplaySize = ImVec2(1920, 1080);
|
||||
io.DeltaTime = 1.0f / 60.0f;
|
||||
}
|
||||
|
||||
IMGUI_IMPL_API bool ImGui_ImplNullRender_Init()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset;
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures;
|
||||
return true;
|
||||
}
|
||||
|
||||
IMGUI_IMPL_API void ImGui_ImplNullRender_Shutdown()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.BackendFlags &= ~ImGuiBackendFlags_RendererHasVtxOffset;
|
||||
io.BackendFlags &= ~ImGuiBackendFlags_RendererHasTextures;
|
||||
}
|
||||
|
||||
IMGUI_IMPL_API void ImGui_ImplNullRender_NewFrame()
|
||||
{
|
||||
}
|
||||
|
||||
static void ImGui_ImplNullRender_UpdateTexture(ImTextureData* tex)
|
||||
{
|
||||
if (tex->Status == ImTextureStatus_WantCreate || tex->Status == ImTextureStatus_WantDestroy)
|
||||
tex->SetStatus(ImTextureStatus_OK);
|
||||
if (tex->Status == ImTextureStatus_WantDestroy)
|
||||
{
|
||||
tex->SetTexID(ImTextureID_Invalid);
|
||||
tex->SetStatus(ImTextureStatus_Destroyed);
|
||||
}
|
||||
}
|
||||
|
||||
IMGUI_IMPL_API void ImGui_ImplNullRender_RenderDrawData(ImDrawData* draw_data)
|
||||
{
|
||||
if (draw_data->Textures != nullptr)
|
||||
for (ImTextureData* tex : *draw_data->Textures)
|
||||
if (tex->Status != ImTextureStatus_OK)
|
||||
ImGui_ImplNullRender_UpdateTexture(tex);
|
||||
}
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
34
backends/imgui_impl_null.h
Normal file
34
backends/imgui_impl_null.h
Normal file
@@ -0,0 +1,34 @@
|
||||
// dear imgui: Null Platform+Renderer Backends
|
||||
// This is designed if you need to use a blind Dear Imgui context with no input and no output.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
#pragma once
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
|
||||
// Null = NullPlatform + NullRender
|
||||
IMGUI_IMPL_API bool ImGui_ImplNull_Init();
|
||||
IMGUI_IMPL_API void ImGui_ImplNull_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplNull_NewFrame();
|
||||
|
||||
// Null platform only (single screen, fixed timestep, no inputs)
|
||||
IMGUI_IMPL_API bool ImGui_ImplNullPlatform_Init();
|
||||
IMGUI_IMPL_API void ImGui_ImplNullPlatform_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplNullPlatform_NewFrame();
|
||||
|
||||
// Null renderer only (no output)
|
||||
IMGUI_IMPL_API bool ImGui_ImplNullRender_Init();
|
||||
IMGUI_IMPL_API void ImGui_ImplNullRender_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplNullRender_NewFrame();
|
||||
IMGUI_IMPL_API void ImGui_ImplNullRender_RenderDrawData(ImDrawData* draw_data);
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
@@ -2,11 +2,19 @@
|
||||
// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
|
||||
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// Missing features or Issues:
|
||||
// [ ] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [ ] Renderer: Use of DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest is emulated by poking to glTexParameter(), as legacy OpenGL doesn't have glBindSampler().
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
// **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)**
|
||||
// **Prefer using the code in imgui_impl_opengl3.cpp**
|
||||
@@ -18,6 +26,16 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-04-23: OpenGL: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
|
||||
// 2026-03-12: OpenGL: Fixed invalid assert in ImGui_ImplOpenGL3_UpdateTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295)
|
||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||
// 2025-07-15: OpenGL: Set GL_UNPACK_ALIGNMENT to 1 before updating textures. (#8802)
|
||||
// 2025-06-11: OpenGL: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplOpenGL2_CreateFontsTexture() and ImGui_ImplOpenGL2_DestroyFontsTexture().
|
||||
// 2024-10-07: OpenGL: Changed default texture sampler to Clamp instead of Repeat/Wrap.
|
||||
// 2024-06-28: OpenGL: ImGui_ImplOpenGL2_NewFrame() recreates font texture if it has been destroyed by ImGui_ImplOpenGL2_DestroyFontsTexture(). (#7748)
|
||||
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
|
||||
// 2021-12-08: OpenGL: Fixed mishandling of the ImDrawCmd::IdxOffset field! This is an old bug but it never had an effect until some internal rendering changes in 1.86.
|
||||
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
|
||||
// 2021-05-19: OpenGL: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
|
||||
// 2021-01-03: OpenGL: Backup, setup and restore GL_SHADE_MODEL state, disable GL_STENCIL_TEST and disable GL_NORMAL_ARRAY client state to increase compatibility with legacy OpenGL applications.
|
||||
// 2020-01-23: OpenGL: Backup, setup and restore GL_TEXTURE_ENV to increase compatibility with legacy OpenGL applications.
|
||||
@@ -33,11 +51,15 @@
|
||||
// 2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle.
|
||||
|
||||
#include "imgui.h"
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include "imgui_impl_opengl2.h"
|
||||
#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
|
||||
#include <stddef.h> // intptr_t
|
||||
#else
|
||||
#include <stdint.h> // intptr_t
|
||||
|
||||
// Clang/GCC warnings with -Weverything
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunused-macros" // warning: macro is not used
|
||||
#pragma clang diagnostic ignored "-Wnonportable-system-include-path"
|
||||
#endif
|
||||
|
||||
// Include OpenGL header (without an OpenGL loader) requires a bit of fiddling
|
||||
@@ -54,32 +76,43 @@
|
||||
#include <GL/gl.h>
|
||||
#endif
|
||||
|
||||
// OpenGL Data
|
||||
static GLuint g_FontTexture = 0;
|
||||
// [Debugging]
|
||||
//#define IMGUI_IMPL_OPENGL_DEBUG
|
||||
#ifdef IMGUI_IMPL_OPENGL_DEBUG
|
||||
#include <stdio.h>
|
||||
#define GL_CALL(_CALL) do { _CALL; GLenum gl_err = glGetError(); if (gl_err != 0) fprintf(stderr, "GL error 0x%x returned from '%s'.\n", gl_err, #_CALL); } while (0) // Call with error check
|
||||
#else
|
||||
#define GL_CALL(_CALL) _CALL // Call without error check
|
||||
#endif
|
||||
|
||||
// OpenGL data
|
||||
struct ImGui_ImplOpenGL2_Data
|
||||
{
|
||||
bool UseTexParameterToSetSampler;
|
||||
GLuint NextSampler;
|
||||
|
||||
ImGui_ImplOpenGL2_Data() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
|
||||
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
|
||||
static ImGui_ImplOpenGL2_Data* ImGui_ImplOpenGL2_GetBackendData()
|
||||
{
|
||||
return ImGui::GetCurrentContext() ? (ImGui_ImplOpenGL2_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
|
||||
}
|
||||
|
||||
// Functions
|
||||
bool ImGui_ImplOpenGL2_Init()
|
||||
{
|
||||
// Setup backend capabilities flags
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.BackendRendererName = "imgui_impl_opengl2";
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplOpenGL2_Shutdown()
|
||||
{
|
||||
ImGui_ImplOpenGL2_DestroyDeviceObjects();
|
||||
}
|
||||
|
||||
void ImGui_ImplOpenGL2_NewFrame()
|
||||
{
|
||||
if (!g_FontTexture)
|
||||
ImGui_ImplOpenGL2_CreateDeviceObjects();
|
||||
ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplOpenGL2_Init()?");
|
||||
IM_UNUSED(bd);
|
||||
}
|
||||
|
||||
static void ImGui_ImplOpenGL2_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height)
|
||||
{
|
||||
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill.
|
||||
ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
//glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // In order to composite our output buffer we need to preserve alpha
|
||||
@@ -97,6 +130,7 @@ static void ImGui_ImplOpenGL2_SetupRenderState(ImDrawData* draw_data, int fb_wid
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
glShadeModel(GL_SMOOTH);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
bd->NextSampler = GL_LINEAR;
|
||||
|
||||
// If you are using this code with non-legacy OpenGL header/contexts (which you should not, prefer using imgui_impl_opengl3.cpp!!),
|
||||
// you may need to backup/reset/restore other state, e.g. for current shader using the commented lines below.
|
||||
@@ -111,7 +145,7 @@ static void ImGui_ImplOpenGL2_SetupRenderState(ImDrawData* draw_data, int fb_wid
|
||||
|
||||
// Setup viewport, orthographic projection matrix
|
||||
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
|
||||
glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
|
||||
GL_CALL(glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height));
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
@@ -121,17 +155,30 @@ static void ImGui_ImplOpenGL2_SetupRenderState(ImDrawData* draw_data, int fb_wid
|
||||
glLoadIdentity();
|
||||
}
|
||||
|
||||
// Draw callbacks
|
||||
static void ImGui_ImplOpenGL2_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
||||
static void ImGui_ImplOpenGL2_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData(); bd->UseTexParameterToSetSampler = true; bd->NextSampler = GL_LINEAR; }
|
||||
static void ImGui_ImplOpenGL2_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData(); bd->UseTexParameterToSetSampler = true; bd->NextSampler = GL_NEAREST; }
|
||||
|
||||
// OpenGL2 Render function.
|
||||
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly.
|
||||
// This is in order to be able to run within an OpenGL engine that doesn't do so.
|
||||
void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
|
||||
{
|
||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||
ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();
|
||||
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
|
||||
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
|
||||
if (fb_width == 0 || fb_height == 0)
|
||||
return;
|
||||
|
||||
// Catch up with texture updates. Most of the times, the list will have 1 element with an OK status, aka nothing to do.
|
||||
// (This almost always points to ImGui::GetPlatformIO().Textures[] but is part of ImDrawData to allow overriding or disabling texture updates).
|
||||
if (draw_data->Textures != nullptr)
|
||||
for (ImTextureData* tex : *draw_data->Textures)
|
||||
if (tex->Status != ImTextureStatus_OK)
|
||||
ImGui_ImplOpenGL2_UpdateTexture(tex);
|
||||
|
||||
// Backup GL state
|
||||
GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||
GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
|
||||
@@ -149,47 +196,50 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
|
||||
ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2)
|
||||
|
||||
// Render command lists
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
for (const ImDrawList* draw_list : draw_data->CmdLists)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data;
|
||||
const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, pos)));
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, uv)));
|
||||
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, col)));
|
||||
const ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data;
|
||||
const ImDrawIdx* idx_buffer = draw_list->IdxBuffer.Data;
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + offsetof(ImDrawVert, pos)));
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + offsetof(ImDrawVert, uv)));
|
||||
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + offsetof(ImDrawVert, col)));
|
||||
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback)
|
||||
{
|
||||
// User callback, registered via ImDrawList::AddCallback()
|
||||
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
|
||||
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
|
||||
if (pcmd->UserCallback == ImGui_ImplOpenGL2_DrawCallback_ResetRenderState)
|
||||
ImGui_ImplOpenGL2_SetupRenderState(draw_data, fb_width, fb_height);
|
||||
else
|
||||
pcmd->UserCallback(cmd_list, pcmd);
|
||||
pcmd->UserCallback(draw_list, pcmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Project scissor/clipping rectangles into framebuffer space
|
||||
ImVec4 clip_rect;
|
||||
clip_rect.x = (pcmd->ClipRect.x - clip_off.x) * clip_scale.x;
|
||||
clip_rect.y = (pcmd->ClipRect.y - clip_off.y) * clip_scale.y;
|
||||
clip_rect.z = (pcmd->ClipRect.z - clip_off.x) * clip_scale.x;
|
||||
clip_rect.w = (pcmd->ClipRect.w - clip_off.y) * clip_scale.y;
|
||||
ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
|
||||
ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
|
||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||
continue;
|
||||
|
||||
if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f)
|
||||
// Apply scissor/clipping rectangle (Y is inverted in OpenGL)
|
||||
glScissor((int)clip_min.x, (int)((float)fb_height - clip_max.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y));
|
||||
|
||||
// Bind texture, Draw
|
||||
GLuint pcmd_texture = (GLuint)(intptr_t)pcmd->GetTexID();
|
||||
glBindTexture(GL_TEXTURE_2D, pcmd_texture);
|
||||
|
||||
// Emulate sampler change (even though it is technically part of texture data)
|
||||
// As a sort of hack/workaround, we only start writing using glTextParameter() if sampler is ever changed explicitly.
|
||||
if (bd->UseTexParameterToSetSampler)
|
||||
{
|
||||
// Apply scissor/clipping rectangle
|
||||
glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y));
|
||||
|
||||
// Bind texture, Draw
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID());
|
||||
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, bd->NextSampler);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, bd->NextSampler);
|
||||
}
|
||||
|
||||
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer + pcmd->IdxOffset);
|
||||
}
|
||||
idx_buffer += pcmd->ElemCount;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,50 +260,121 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, last_tex_env_mode);
|
||||
}
|
||||
|
||||
bool ImGui_ImplOpenGL2_CreateFontsTexture()
|
||||
void ImGui_ImplOpenGL2_UpdateTexture(ImTextureData* tex)
|
||||
{
|
||||
// Build texture atlas
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
unsigned char* pixels;
|
||||
int width, height;
|
||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bit (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
|
||||
|
||||
// Upload texture to graphics system
|
||||
GLint last_texture;
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||
glGenTextures(1, &g_FontTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, g_FontTexture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
// Store our identifier
|
||||
io.Fonts->SetTexID((ImTextureID)(intptr_t)g_FontTexture);
|
||||
|
||||
// Restore state
|
||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplOpenGL2_DestroyFontsTexture()
|
||||
{
|
||||
if (g_FontTexture)
|
||||
if (tex->Status == ImTextureStatus_WantCreate)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
glDeleteTextures(1, &g_FontTexture);
|
||||
io.Fonts->SetTexID(0);
|
||||
g_FontTexture = 0;
|
||||
// Create and upload new texture to graphics system
|
||||
//IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
|
||||
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == nullptr);
|
||||
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
|
||||
const void* pixels = tex->GetPixels();
|
||||
GLuint gl_texture_id = 0;
|
||||
|
||||
// Upload texture to graphics system
|
||||
// (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
|
||||
GLint last_texture;
|
||||
GL_CALL(glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture));
|
||||
GL_CALL(glGenTextures(1, &gl_texture_id));
|
||||
GL_CALL(glBindTexture(GL_TEXTURE_2D, gl_texture_id));
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP));
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP));
|
||||
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
|
||||
GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
|
||||
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex->Width, tex->Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
|
||||
|
||||
// Store identifiers
|
||||
tex->SetTexID((ImTextureID)(intptr_t)gl_texture_id);
|
||||
tex->SetStatus(ImTextureStatus_OK);
|
||||
|
||||
// Restore state
|
||||
GL_CALL(glBindTexture(GL_TEXTURE_2D, last_texture));
|
||||
}
|
||||
else if (tex->Status == ImTextureStatus_WantUpdates)
|
||||
{
|
||||
// Update selected blocks. We only ever write to textures regions which have never been used before!
|
||||
// This backend choose to use tex->Updates[] but you can use tex->UpdateRect to upload a single region.
|
||||
GLint last_texture;
|
||||
GL_CALL(glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture));
|
||||
|
||||
GLuint gl_tex_id = (GLuint)(intptr_t)tex->TexID;
|
||||
GL_CALL(glBindTexture(GL_TEXTURE_2D, gl_tex_id));
|
||||
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, tex->Width));
|
||||
GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
|
||||
for (ImTextureRect& r : tex->Updates)
|
||||
GL_CALL(glTexSubImage2D(GL_TEXTURE_2D, 0, r.x, r.y, r.w, r.h, GL_RGBA, GL_UNSIGNED_BYTE, tex->GetPixelsAt(r.x, r.y)));
|
||||
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
|
||||
GL_CALL(glBindTexture(GL_TEXTURE_2D, last_texture)); // Restore state
|
||||
tex->SetStatus(ImTextureStatus_OK);
|
||||
}
|
||||
else if (tex->Status == ImTextureStatus_WantDestroy)
|
||||
{
|
||||
GLuint gl_tex_id = (GLuint)(intptr_t)tex->TexID;
|
||||
glDeleteTextures(1, &gl_tex_id);
|
||||
|
||||
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
|
||||
tex->SetTexID(ImTextureID_Invalid);
|
||||
tex->SetStatus(ImTextureStatus_Destroyed);
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGui_ImplOpenGL2_CreateDeviceObjects()
|
||||
{
|
||||
return ImGui_ImplOpenGL2_CreateFontsTexture();
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplOpenGL2_DestroyDeviceObjects()
|
||||
{
|
||||
ImGui_ImplOpenGL2_DestroyFontsTexture();
|
||||
for (ImTextureData* tex : ImGui::GetPlatformIO().Textures)
|
||||
if (tex->RefCount == 1)
|
||||
{
|
||||
tex->SetStatus(ImTextureStatus_WantDestroy);
|
||||
ImGui_ImplOpenGL2_UpdateTexture(tex);
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGui_ImplOpenGL2_Init()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IMGUI_CHECKVERSION();
|
||||
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
||||
|
||||
// Setup backend capabilities flags
|
||||
ImGui_ImplOpenGL2_Data* bd = IM_NEW(ImGui_ImplOpenGL2_Data)();
|
||||
io.BackendRendererUserData = (void*)bd;
|
||||
io.BackendRendererName = "imgui_impl_opengl2";
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
||||
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
platform_io.DrawCallback_ResetRenderState = ImGui_ImplOpenGL2_DrawCallback_ResetRenderState;
|
||||
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplOpenGL2_DrawCallback_SetSamplerLinear;
|
||||
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplOpenGL2_DrawCallback_SetSamplerNearest;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplOpenGL2_Shutdown()
|
||||
{
|
||||
ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
ImGui_ImplOpenGL2_DestroyDeviceObjects();
|
||||
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasTextures);
|
||||
platform_io.ClearRendererHandlers();
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
@@ -2,11 +2,19 @@
|
||||
// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
|
||||
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// Missing features or Issues:
|
||||
// [ ] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [ ] Renderer: Use of DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest is emulated by poking to glTexParameter(), as legacy OpenGL doesn't have glBindSampler().
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
// **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)**
|
||||
// **Prefer using the code in imgui_impl_opengl3.cpp**
|
||||
@@ -18,14 +26,19 @@
|
||||
|
||||
#pragma once
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
IMGUI_IMPL_API bool ImGui_ImplOpenGL2_Init();
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL2_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL2_NewFrame();
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data);
|
||||
|
||||
// Called by Init/NewFrame/Shutdown
|
||||
IMGUI_IMPL_API bool ImGui_ImplOpenGL2_CreateFontsTexture();
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL2_DestroyFontsTexture();
|
||||
IMGUI_IMPL_API bool ImGui_ImplOpenGL2_CreateDeviceObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL2_DestroyDeviceObjects();
|
||||
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL2_UpdateTexture(ImTextureData* tex);
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,84 +4,65 @@
|
||||
// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
|
||||
// [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bit indices.
|
||||
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [x] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset) [Desktop OpenGL only!]
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
// About WebGL/ES:
|
||||
// - You need to '#define IMGUI_IMPL_OPENGL_ES2' or '#define IMGUI_IMPL_OPENGL_ES3' to use WebGL or OpenGL ES.
|
||||
// - This is done automatically on iOS, Android and Emscripten targets.
|
||||
// - For other targets, the define needs to be visible from the imgui_impl_opengl3.cpp compilation unit. If unsure, define globally or in imconfig.h.
|
||||
|
||||
// About Desktop OpenGL function loaders:
|
||||
// Modern Desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers.
|
||||
// Helper libraries are often used for this purpose! Here we are supporting a few common ones (gl3w, glew, glad).
|
||||
// You may use another loader/header of your choice (glext, glLoadGen, etc.), or chose to manually implement your own.
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
// About GLSL version:
|
||||
// The 'glsl_version' initialization parameter should be NULL (default) or a "#version XXX" string.
|
||||
// The 'glsl_version' initialization parameter should be nullptr (default) or a "#version XXX" string.
|
||||
// On computer platform the GLSL version default to "#version 130". On OpenGL ES 3 platform it defaults to "#version 300 es"
|
||||
// Only override if your GL version doesn't handle this GLSL version. See GLSL version table at the top of imgui_impl_opengl3.cpp.
|
||||
|
||||
#pragma once
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
// Backend API
|
||||
IMGUI_IMPL_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = NULL);
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
IMGUI_IMPL_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = nullptr);
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL3_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL3_NewFrame();
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data);
|
||||
|
||||
// (Optional) Called by Init/NewFrame/Shutdown
|
||||
IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateFontsTexture();
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyFontsTexture();
|
||||
IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateDeviceObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects();
|
||||
|
||||
// Specific OpenGL ES versions
|
||||
//#define IMGUI_IMPL_OPENGL_ES2 // Auto-detected on Emscripten
|
||||
//#define IMGUI_IMPL_OPENGL_ES3 // Auto-detected on iOS/Android
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL3_UpdateTexture(ImTextureData* tex);
|
||||
|
||||
// Attempt to auto-detect the default Desktop GL loader based on available header files.
|
||||
// If auto-detection fails or doesn't select the same GL loader file as used by your application,
|
||||
// you are likely to get a crash in ImGui_ImplOpenGL3_Init().
|
||||
// You can explicitly select a loader by using one of the '#define IMGUI_IMPL_OPENGL_LOADER_XXX' in imconfig.h or compiler command-line.
|
||||
// Configuration flags to add in your imconfig file:
|
||||
//#define IMGUI_IMPL_OPENGL_ES2 // Enable ES 2 (Auto-detected on Emscripten)
|
||||
//#define IMGUI_IMPL_OPENGL_ES3 // Enable ES 3 (Auto-detected on iOS/Android)
|
||||
|
||||
// You can explicitly select GLES2 or GLES3 API by using one of the '#define IMGUI_IMPL_OPENGL_LOADER_XXX' in imconfig.h or compiler command-line.
|
||||
#if !defined(IMGUI_IMPL_OPENGL_ES2) \
|
||||
&& !defined(IMGUI_IMPL_OPENGL_ES3) \
|
||||
&& !defined(IMGUI_IMPL_OPENGL_LOADER_GL3W) \
|
||||
&& !defined(IMGUI_IMPL_OPENGL_LOADER_GLEW) \
|
||||
&& !defined(IMGUI_IMPL_OPENGL_LOADER_GLAD) \
|
||||
&& !defined(IMGUI_IMPL_OPENGL_LOADER_GLAD2) \
|
||||
&& !defined(IMGUI_IMPL_OPENGL_LOADER_GLBINDING2) \
|
||||
&& !defined(IMGUI_IMPL_OPENGL_LOADER_GLBINDING3) \
|
||||
&& !defined(IMGUI_IMPL_OPENGL_LOADER_CUSTOM)
|
||||
&& !defined(IMGUI_IMPL_OPENGL_ES3)
|
||||
|
||||
// Try to detect GLES on matching platforms
|
||||
#if defined(__APPLE__)
|
||||
#include "TargetConditionals.h"
|
||||
#include <TargetConditionals.h>
|
||||
#endif
|
||||
#if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV)) || (defined(__ANDROID__))
|
||||
#define IMGUI_IMPL_OPENGL_ES3 // iOS, Android -> GL ES 3, "#version 300 es"
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
#elif defined(__EMSCRIPTEN__) || defined(__amigaos4__)
|
||||
#define IMGUI_IMPL_OPENGL_ES2 // Emscripten -> GL ES 2, "#version 100"
|
||||
|
||||
// Otherwise try to detect supported Desktop OpenGL loaders..
|
||||
#elif defined(__has_include)
|
||||
#if __has_include(<GL/glew.h>)
|
||||
#define IMGUI_IMPL_OPENGL_LOADER_GLEW
|
||||
#elif __has_include(<glad/glad.h>)
|
||||
#define IMGUI_IMPL_OPENGL_LOADER_GLAD
|
||||
#elif __has_include(<glad/gl.h>)
|
||||
#define IMGUI_IMPL_OPENGL_LOADER_GLAD2
|
||||
#elif __has_include(<GL/gl3w.h>)
|
||||
#define IMGUI_IMPL_OPENGL_LOADER_GL3W
|
||||
#elif __has_include(<glbinding/glbinding.h>)
|
||||
#define IMGUI_IMPL_OPENGL_LOADER_GLBINDING3
|
||||
#elif __has_include(<glbinding/Binding.h>)
|
||||
#define IMGUI_IMPL_OPENGL_LOADER_GLBINDING2
|
||||
#else
|
||||
#error "Cannot detect OpenGL loader!"
|
||||
#endif
|
||||
#else
|
||||
#define IMGUI_IMPL_OPENGL_LOADER_GL3W // Default to GL3W embedded in our repository
|
||||
// Otherwise imgui_impl_opengl3_loader.h will be used.
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
958
backends/imgui_impl_opengl3_loader.h
Normal file
958
backends/imgui_impl_opengl3_loader.h
Normal file
@@ -0,0 +1,958 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// About imgui_impl_opengl3_loader.h:
|
||||
//
|
||||
// We embed our own OpenGL loader to not require user to provide their own or to have to use ours,
|
||||
// which proved to be endless problems for users.
|
||||
// Our loader is custom-generated, based on gl3w but automatically filtered to only include
|
||||
// enums/functions that we use in our imgui_impl_opengl3.cpp source file in order to be small.
|
||||
//
|
||||
// YOU SHOULD NOT NEED TO INCLUDE/USE THIS DIRECTLY. THIS IS USED BY imgui_impl_opengl3.cpp ONLY.
|
||||
// THE REST OF YOUR APP SHOULD USE A DIFFERENT GL LOADER: ANY GL LOADER OF YOUR CHOICE.
|
||||
//
|
||||
// IF YOU GET BUILD ERRORS IN THIS FILE (commonly macro redefinitions or function redefinitions):
|
||||
// IT LIKELY MEANS THAT YOU ARE BUILDING 'imgui_impl_opengl3.cpp' OR INCLUDING 'imgui_impl_opengl3_loader.h'
|
||||
// IN THE SAME COMPILATION UNIT AS ONE OF YOUR FILE WHICH IS USING A THIRD-PARTY OPENGL LOADER.
|
||||
// (e.g. COULD HAPPEN IF YOU ARE DOING A UNITY/JUMBO BUILD, OR INCLUDING .CPP FILES FROM OTHERS)
|
||||
// YOU SHOULD NOT BUILD BOTH IN THE SAME COMPILATION UNIT.
|
||||
// BUT IF YOU REALLY WANT TO, you can '#define IMGUI_IMPL_OPENGL_LOADER_CUSTOM' and imgui_impl_opengl3.cpp
|
||||
// WILL NOT BE USING OUR LOADER, AND INSTEAD EXPECT ANOTHER/YOUR LOADER TO BE AVAILABLE IN THE COMPILATION UNIT.
|
||||
//
|
||||
// Regenerate with:
|
||||
// python3 gl3w_gen.py --output ../imgui/backends/imgui_impl_opengl3_loader.h --ref ../imgui/backends/imgui_impl_opengl3.cpp ./extra_symbols.txt
|
||||
//
|
||||
// More info:
|
||||
// https://github.com/dearimgui/gl3w_stripped
|
||||
// https://github.com/ocornut/imgui/issues/4445
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* This file was generated with gl3w_gen.py, part of imgl3w
|
||||
* (hosted at https://github.com/dearimgui/gl3w_stripped)
|
||||
*
|
||||
* This is free and unencumbered software released into the public domain.
|
||||
*
|
||||
* Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
* distribute this software, either in source code form or as a compiled
|
||||
* binary, for any purpose, commercial or non-commercial, and by any
|
||||
* means.
|
||||
*
|
||||
* In jurisdictions that recognize copyright laws, the author or authors
|
||||
* of this software dedicate any and all copyright interest in the
|
||||
* software to the public domain. We make this dedication for the benefit
|
||||
* of the public at large and to the detriment of our heirs and
|
||||
* successors. We intend this dedication to be an overt act of
|
||||
* relinquishment in perpetuity of all present and future rights to this
|
||||
* software under copyright law.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __gl3w_h_
|
||||
#define __gl3w_h_
|
||||
|
||||
// Adapted from KHR/khrplatform.h to avoid including entire file.
|
||||
#ifndef __khrplatform_h_
|
||||
typedef float khronos_float_t;
|
||||
typedef signed char khronos_int8_t;
|
||||
typedef unsigned char khronos_uint8_t;
|
||||
typedef signed short int khronos_int16_t;
|
||||
typedef unsigned short int khronos_uint16_t;
|
||||
#ifdef _WIN64
|
||||
typedef signed long long int khronos_intptr_t;
|
||||
typedef signed long long int khronos_ssize_t;
|
||||
#else
|
||||
typedef signed long int khronos_intptr_t;
|
||||
typedef signed long int khronos_ssize_t;
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
typedef signed __int64 khronos_int64_t;
|
||||
typedef unsigned __int64 khronos_uint64_t;
|
||||
#elif (defined(__clang__) || defined(__GNUC__)) && (__cplusplus < 201100)
|
||||
#include <stdint.h>
|
||||
typedef int64_t khronos_int64_t;
|
||||
typedef uint64_t khronos_uint64_t;
|
||||
#else
|
||||
typedef signed long long khronos_int64_t;
|
||||
typedef unsigned long long khronos_uint64_t;
|
||||
#endif
|
||||
#endif // __khrplatform_h_
|
||||
|
||||
#ifndef __gl_glcorearb_h_
|
||||
#define __gl_glcorearb_h_ 1
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/*
|
||||
** Copyright 2013-2020 The Khronos Group Inc.
|
||||
** SPDX-License-Identifier: MIT
|
||||
**
|
||||
** This header is generated from the Khronos OpenGL / OpenGL ES XML
|
||||
** API Registry. The current version of the Registry, generator scripts
|
||||
** used to make the header, and the header can be found at
|
||||
** https://github.com/KhronosGroup/OpenGL-Registry
|
||||
*/
|
||||
#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#ifndef APIENTRY
|
||||
#define APIENTRY
|
||||
#endif
|
||||
#ifndef APIENTRYP
|
||||
#define APIENTRYP APIENTRY *
|
||||
#endif
|
||||
#ifndef GLAPI
|
||||
#define GLAPI extern
|
||||
#endif
|
||||
/* glcorearb.h is for use with OpenGL core profile implementations.
|
||||
** It should should be placed in the same directory as gl.h and
|
||||
** included as <GL/glcorearb.h>.
|
||||
**
|
||||
** glcorearb.h includes only APIs in the latest OpenGL core profile
|
||||
** implementation together with APIs in newer ARB extensions which
|
||||
** can be supported by the core profile. It does not, and never will
|
||||
** include functionality removed from the core profile, such as
|
||||
** fixed-function vertex and fragment processing.
|
||||
**
|
||||
** Do not #include both <GL/glcorearb.h> and either of <GL/gl.h> or
|
||||
** <GL/glext.h> in the same source file.
|
||||
*/
|
||||
/* Generated C header for:
|
||||
* API: gl
|
||||
* Profile: core
|
||||
* Versions considered: .*
|
||||
* Versions emitted: .*
|
||||
* Default extensions included: glcore
|
||||
* Additional extensions included: _nomatch_^
|
||||
* Extensions removed: _nomatch_^
|
||||
*/
|
||||
#ifndef GL_VERSION_1_0
|
||||
typedef void GLvoid;
|
||||
typedef unsigned int GLenum;
|
||||
|
||||
typedef khronos_float_t GLfloat;
|
||||
typedef int GLint;
|
||||
typedef int GLsizei;
|
||||
typedef unsigned int GLbitfield;
|
||||
typedef double GLdouble;
|
||||
typedef unsigned int GLuint;
|
||||
typedef unsigned char GLboolean;
|
||||
typedef khronos_uint8_t GLubyte;
|
||||
#define GL_COLOR_BUFFER_BIT 0x00004000
|
||||
#define GL_FALSE 0
|
||||
#define GL_TRUE 1
|
||||
#define GL_TRIANGLES 0x0004
|
||||
#define GL_ONE 1
|
||||
#define GL_SRC_ALPHA 0x0302
|
||||
#define GL_ONE_MINUS_SRC_ALPHA 0x0303
|
||||
#define GL_FRONT 0x0404
|
||||
#define GL_BACK 0x0405
|
||||
#define GL_FRONT_AND_BACK 0x0408
|
||||
#define GL_POLYGON_MODE 0x0B40
|
||||
#define GL_CULL_FACE 0x0B44
|
||||
#define GL_DEPTH_TEST 0x0B71
|
||||
#define GL_STENCIL_TEST 0x0B90
|
||||
#define GL_VIEWPORT 0x0BA2
|
||||
#define GL_BLEND 0x0BE2
|
||||
#define GL_SCISSOR_BOX 0x0C10
|
||||
#define GL_SCISSOR_TEST 0x0C11
|
||||
#define GL_UNPACK_ROW_LENGTH 0x0CF2
|
||||
#define GL_UNPACK_ALIGNMENT 0x0CF5
|
||||
#define GL_PACK_ALIGNMENT 0x0D05
|
||||
#define GL_MAX_TEXTURE_SIZE 0x0D33
|
||||
#define GL_TEXTURE_2D 0x0DE1
|
||||
#define GL_UNSIGNED_BYTE 0x1401
|
||||
#define GL_UNSIGNED_SHORT 0x1403
|
||||
#define GL_UNSIGNED_INT 0x1405
|
||||
#define GL_FLOAT 0x1406
|
||||
#define GL_RGBA 0x1908
|
||||
#define GL_FILL 0x1B02
|
||||
#define GL_VENDOR 0x1F00
|
||||
#define GL_RENDERER 0x1F01
|
||||
#define GL_VERSION 0x1F02
|
||||
#define GL_EXTENSIONS 0x1F03
|
||||
#define GL_NEAREST 0x2600
|
||||
#define GL_LINEAR 0x2601
|
||||
#define GL_TEXTURE_MAG_FILTER 0x2800
|
||||
#define GL_TEXTURE_MIN_FILTER 0x2801
|
||||
#define GL_TEXTURE_WRAP_S 0x2802
|
||||
#define GL_TEXTURE_WRAP_T 0x2803
|
||||
#define GL_REPEAT 0x2901
|
||||
typedef void (APIENTRYP PFNGLPOLYGONMODEPROC) (GLenum face, GLenum mode);
|
||||
typedef void (APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
typedef void (APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
|
||||
typedef void (APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
|
||||
typedef void (APIENTRYP PFNGLCLEARPROC) (GLbitfield mask);
|
||||
typedef void (APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
|
||||
typedef void (APIENTRYP PFNGLDISABLEPROC) (GLenum cap);
|
||||
typedef void (APIENTRYP PFNGLENABLEPROC) (GLenum cap);
|
||||
typedef void (APIENTRYP PFNGLFLUSHPROC) (void);
|
||||
typedef void (APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param);
|
||||
typedef void (APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
|
||||
typedef GLenum (APIENTRYP PFNGLGETERRORPROC) (void);
|
||||
typedef void (APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *data);
|
||||
typedef const GLubyte *(APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
|
||||
typedef GLboolean (APIENTRYP PFNGLISENABLEDPROC) (GLenum cap);
|
||||
typedef void (APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glPolygonMode (GLenum face, GLenum mode);
|
||||
GLAPI void APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
GLAPI void APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
|
||||
GLAPI void APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
|
||||
GLAPI void APIENTRY glClear (GLbitfield mask);
|
||||
GLAPI void APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
|
||||
GLAPI void APIENTRY glDisable (GLenum cap);
|
||||
GLAPI void APIENTRY glEnable (GLenum cap);
|
||||
GLAPI void APIENTRY glFlush (void);
|
||||
GLAPI void APIENTRY glPixelStorei (GLenum pname, GLint param);
|
||||
GLAPI void APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
|
||||
GLAPI GLenum APIENTRY glGetError (void);
|
||||
GLAPI void APIENTRY glGetIntegerv (GLenum pname, GLint *data);
|
||||
GLAPI const GLubyte *APIENTRY glGetString (GLenum name);
|
||||
GLAPI GLboolean APIENTRY glIsEnabled (GLenum cap);
|
||||
GLAPI void APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
#endif
|
||||
#endif /* GL_VERSION_1_0 */
|
||||
#ifndef GL_VERSION_1_1
|
||||
typedef khronos_float_t GLclampf;
|
||||
typedef double GLclampd;
|
||||
#define GL_TEXTURE_BINDING_2D 0x8069
|
||||
typedef void (APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices);
|
||||
typedef void (APIENTRYP PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
|
||||
typedef void (APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture);
|
||||
typedef void (APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures);
|
||||
typedef void (APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices);
|
||||
GLAPI void APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
|
||||
GLAPI void APIENTRY glBindTexture (GLenum target, GLuint texture);
|
||||
GLAPI void APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures);
|
||||
GLAPI void APIENTRY glGenTextures (GLsizei n, GLuint *textures);
|
||||
#endif
|
||||
#endif /* GL_VERSION_1_1 */
|
||||
#ifndef GL_VERSION_1_2
|
||||
#define GL_CLAMP_TO_EDGE 0x812F
|
||||
#endif /* GL_VERSION_1_2 */
|
||||
#ifndef GL_VERSION_1_3
|
||||
#define GL_TEXTURE0 0x84C0
|
||||
#define GL_ACTIVE_TEXTURE 0x84E0
|
||||
typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glActiveTexture (GLenum texture);
|
||||
#endif
|
||||
#endif /* GL_VERSION_1_3 */
|
||||
#ifndef GL_VERSION_1_4
|
||||
#define GL_BLEND_DST_RGB 0x80C8
|
||||
#define GL_BLEND_SRC_RGB 0x80C9
|
||||
#define GL_BLEND_DST_ALPHA 0x80CA
|
||||
#define GL_BLEND_SRC_ALPHA 0x80CB
|
||||
#define GL_FUNC_ADD 0x8006
|
||||
typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
|
||||
typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
|
||||
GLAPI void APIENTRY glBlendEquation (GLenum mode);
|
||||
#endif
|
||||
#endif /* GL_VERSION_1_4 */
|
||||
#ifndef GL_VERSION_1_5
|
||||
typedef khronos_ssize_t GLsizeiptr;
|
||||
typedef khronos_intptr_t GLintptr;
|
||||
#define GL_ARRAY_BUFFER 0x8892
|
||||
#define GL_ELEMENT_ARRAY_BUFFER 0x8893
|
||||
#define GL_ARRAY_BUFFER_BINDING 0x8894
|
||||
#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
|
||||
#define GL_STREAM_DRAW 0x88E0
|
||||
typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
|
||||
typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
|
||||
typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
|
||||
typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
|
||||
typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glBindBuffer (GLenum target, GLuint buffer);
|
||||
GLAPI void APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers);
|
||||
GLAPI void APIENTRY glGenBuffers (GLsizei n, GLuint *buffers);
|
||||
GLAPI void APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
|
||||
GLAPI void APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
|
||||
#endif
|
||||
#endif /* GL_VERSION_1_5 */
|
||||
#ifndef GL_VERSION_2_0
|
||||
typedef char GLchar;
|
||||
typedef khronos_int16_t GLshort;
|
||||
typedef khronos_int8_t GLbyte;
|
||||
typedef khronos_uint16_t GLushort;
|
||||
#define GL_BLEND_EQUATION_RGB 0x8009
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
|
||||
#define GL_BLEND_EQUATION_ALPHA 0x883D
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
|
||||
#define GL_FRAGMENT_SHADER 0x8B30
|
||||
#define GL_VERTEX_SHADER 0x8B31
|
||||
#define GL_COMPILE_STATUS 0x8B81
|
||||
#define GL_LINK_STATUS 0x8B82
|
||||
#define GL_INFO_LOG_LENGTH 0x8B84
|
||||
#define GL_CURRENT_PROGRAM 0x8B8D
|
||||
#define GL_UPPER_LEFT 0x8CA2
|
||||
typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);
|
||||
typedef void (APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
|
||||
typedef void (APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);
|
||||
typedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
|
||||
typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
|
||||
typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);
|
||||
typedef void (APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
|
||||
typedef void (APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
|
||||
typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
|
||||
typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
|
||||
typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);
|
||||
typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
|
||||
typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
|
||||
typedef void (APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
|
||||
typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
|
||||
typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);
|
||||
typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params);
|
||||
typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, void **pointer);
|
||||
typedef GLboolean (APIENTRYP PFNGLISPROGRAMPROC) (GLuint program);
|
||||
typedef void (APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
|
||||
typedef void (APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
|
||||
typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
|
||||
typedef void (APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
|
||||
typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
|
||||
typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
|
||||
GLAPI void APIENTRY glAttachShader (GLuint program, GLuint shader);
|
||||
GLAPI void APIENTRY glCompileShader (GLuint shader);
|
||||
GLAPI GLuint APIENTRY glCreateProgram (void);
|
||||
GLAPI GLuint APIENTRY glCreateShader (GLenum type);
|
||||
GLAPI void APIENTRY glDeleteProgram (GLuint program);
|
||||
GLAPI void APIENTRY glDeleteShader (GLuint shader);
|
||||
GLAPI void APIENTRY glDetachShader (GLuint program, GLuint shader);
|
||||
GLAPI void APIENTRY glDisableVertexAttribArray (GLuint index);
|
||||
GLAPI void APIENTRY glEnableVertexAttribArray (GLuint index);
|
||||
GLAPI GLint APIENTRY glGetAttribLocation (GLuint program, const GLchar *name);
|
||||
GLAPI void APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params);
|
||||
GLAPI void APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
|
||||
GLAPI void APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params);
|
||||
GLAPI void APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
|
||||
GLAPI GLint APIENTRY glGetUniformLocation (GLuint program, const GLchar *name);
|
||||
GLAPI void APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params);
|
||||
GLAPI void APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer);
|
||||
GLAPI GLboolean APIENTRY glIsProgram (GLuint program);
|
||||
GLAPI void APIENTRY glLinkProgram (GLuint program);
|
||||
GLAPI void APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
|
||||
GLAPI void APIENTRY glUseProgram (GLuint program);
|
||||
GLAPI void APIENTRY glUniform1i (GLint location, GLint v0);
|
||||
GLAPI void APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
|
||||
GLAPI void APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
|
||||
#endif
|
||||
#endif /* GL_VERSION_2_0 */
|
||||
#ifndef GL_VERSION_2_1
|
||||
#define GL_PIXEL_UNPACK_BUFFER 0x88EC
|
||||
#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
|
||||
#endif /* GL_VERSION_2_1 */
|
||||
#ifndef GL_VERSION_3_0
|
||||
typedef khronos_uint16_t GLhalf;
|
||||
#define GL_MAJOR_VERSION 0x821B
|
||||
#define GL_MINOR_VERSION 0x821C
|
||||
#define GL_NUM_EXTENSIONS 0x821D
|
||||
#define GL_FRAMEBUFFER_SRGB 0x8DB9
|
||||
#define GL_VERTEX_ARRAY_BINDING 0x85B5
|
||||
typedef void (APIENTRYP PFNGLGETBOOLEANI_VPROC) (GLenum target, GLuint index, GLboolean *data);
|
||||
typedef void (APIENTRYP PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint *data);
|
||||
typedef const GLubyte *(APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index);
|
||||
typedef void (APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array);
|
||||
typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays);
|
||||
typedef void (APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI const GLubyte *APIENTRY glGetStringi (GLenum name, GLuint index);
|
||||
GLAPI void APIENTRY glBindVertexArray (GLuint array);
|
||||
GLAPI void APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint *arrays);
|
||||
GLAPI void APIENTRY glGenVertexArrays (GLsizei n, GLuint *arrays);
|
||||
#endif
|
||||
#endif /* GL_VERSION_3_0 */
|
||||
#ifndef GL_VERSION_3_1
|
||||
#define GL_VERSION_3_1 1
|
||||
#define GL_PRIMITIVE_RESTART 0x8F9D
|
||||
#endif /* GL_VERSION_3_1 */
|
||||
#ifndef GL_VERSION_3_2
|
||||
#define GL_VERSION_3_2 1
|
||||
typedef struct __GLsync *GLsync;
|
||||
typedef khronos_uint64_t GLuint64;
|
||||
typedef khronos_int64_t GLint64;
|
||||
#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
|
||||
#define GL_CONTEXT_PROFILE_MASK 0x9126
|
||||
typedef void (APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
|
||||
typedef void (APIENTRYP PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
|
||||
#endif
|
||||
#endif /* GL_VERSION_3_2 */
|
||||
#ifndef GL_VERSION_3_3
|
||||
#define GL_VERSION_3_3 1
|
||||
#define GL_SAMPLER_BINDING 0x8919
|
||||
typedef void (APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers);
|
||||
typedef void (APIENTRYP PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint *samplers);
|
||||
typedef void (APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler);
|
||||
typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glGenSamplers (GLsizei count, GLuint *samplers);
|
||||
GLAPI void APIENTRY glDeleteSamplers (GLsizei count, const GLuint *samplers);
|
||||
GLAPI void APIENTRY glBindSampler (GLuint unit, GLuint sampler);
|
||||
GLAPI void APIENTRY glSamplerParameteri (GLuint sampler, GLenum pname, GLint param);
|
||||
#endif
|
||||
#endif /* GL_VERSION_3_3 */
|
||||
#ifndef GL_VERSION_4_1
|
||||
typedef void (APIENTRYP PFNGLGETFLOATI_VPROC) (GLenum target, GLuint index, GLfloat *data);
|
||||
typedef void (APIENTRYP PFNGLGETDOUBLEI_VPROC) (GLenum target, GLuint index, GLdouble *data);
|
||||
#endif /* GL_VERSION_4_1 */
|
||||
#ifndef GL_VERSION_4_3
|
||||
typedef void (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
|
||||
#endif /* GL_VERSION_4_3 */
|
||||
#ifndef GL_VERSION_4_5
|
||||
#define GL_CLIP_ORIGIN 0x935C
|
||||
typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKI_VPROC) (GLuint xfb, GLenum pname, GLuint index, GLint *param);
|
||||
typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKI64_VPROC) (GLuint xfb, GLenum pname, GLuint index, GLint64 *param);
|
||||
#endif /* GL_VERSION_4_5 */
|
||||
#ifndef GL_ARB_bindless_texture
|
||||
typedef khronos_uint64_t GLuint64EXT;
|
||||
#endif /* GL_ARB_bindless_texture */
|
||||
#ifndef GL_ARB_cl_event
|
||||
struct _cl_context;
|
||||
struct _cl_event;
|
||||
#endif /* GL_ARB_cl_event */
|
||||
#ifndef GL_ARB_clip_control
|
||||
#define GL_ARB_clip_control 1
|
||||
#endif /* GL_ARB_clip_control */
|
||||
#ifndef GL_ARB_debug_output
|
||||
typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
|
||||
#endif /* GL_ARB_debug_output */
|
||||
#ifndef GL_EXT_EGL_image_storage
|
||||
typedef void *GLeglImageOES;
|
||||
#endif /* GL_EXT_EGL_image_storage */
|
||||
#ifndef GL_EXT_direct_state_access
|
||||
typedef void (APIENTRYP PFNGLGETFLOATI_VEXTPROC) (GLenum pname, GLuint index, GLfloat *params);
|
||||
typedef void (APIENTRYP PFNGLGETDOUBLEI_VEXTPROC) (GLenum pname, GLuint index, GLdouble *params);
|
||||
typedef void (APIENTRYP PFNGLGETPOINTERI_VEXTPROC) (GLenum pname, GLuint index, void **params);
|
||||
typedef void (APIENTRYP PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, GLint *param);
|
||||
typedef void (APIENTRYP PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, void **param);
|
||||
#endif /* GL_EXT_direct_state_access */
|
||||
#ifndef GL_NV_draw_vulkan_image
|
||||
typedef void (APIENTRY *GLVULKANPROCNV)(void);
|
||||
#endif /* GL_NV_draw_vulkan_image */
|
||||
#ifndef GL_NV_gpu_shader5
|
||||
typedef khronos_int64_t GLint64EXT;
|
||||
#endif /* GL_NV_gpu_shader5 */
|
||||
#ifndef GL_NV_vertex_buffer_unified_memory
|
||||
typedef void (APIENTRYP PFNGLGETINTEGERUI64I_VNVPROC) (GLenum value, GLuint index, GLuint64EXT *result);
|
||||
#endif /* GL_NV_vertex_buffer_unified_memory */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef GL3W_API
|
||||
#define GL3W_API
|
||||
#endif
|
||||
|
||||
#ifndef __gl_h_
|
||||
#define __gl_h_
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define GL3W_OK 0
|
||||
#define GL3W_ERROR_INIT -1
|
||||
#define GL3W_ERROR_LIBRARY_OPEN -2
|
||||
#define GL3W_ERROR_OPENGL_VERSION -3
|
||||
|
||||
typedef void (*GL3WglProc)(void);
|
||||
typedef GL3WglProc (*GL3WGetProcAddressProc)(const char *proc);
|
||||
|
||||
/* gl3w api */
|
||||
GL3W_API int imgl3wInit(void);
|
||||
GL3W_API int imgl3wInit2(GL3WGetProcAddressProc proc);
|
||||
GL3W_API void imgl3wShutdown(void);
|
||||
GL3W_API int imgl3wIsSupported(int major, int minor);
|
||||
GL3W_API GL3WglProc imgl3wGetProcAddress(const char *proc);
|
||||
|
||||
/* gl3w internal state */
|
||||
union ImGL3WProcs {
|
||||
GL3WglProc ptr[63];
|
||||
struct {
|
||||
PFNGLACTIVETEXTUREPROC ActiveTexture;
|
||||
PFNGLATTACHSHADERPROC AttachShader;
|
||||
PFNGLBINDBUFFERPROC BindBuffer;
|
||||
PFNGLBINDSAMPLERPROC BindSampler;
|
||||
PFNGLBINDTEXTUREPROC BindTexture;
|
||||
PFNGLBINDVERTEXARRAYPROC BindVertexArray;
|
||||
PFNGLBLENDEQUATIONPROC BlendEquation;
|
||||
PFNGLBLENDEQUATIONSEPARATEPROC BlendEquationSeparate;
|
||||
PFNGLBLENDFUNCSEPARATEPROC BlendFuncSeparate;
|
||||
PFNGLBUFFERDATAPROC BufferData;
|
||||
PFNGLBUFFERSUBDATAPROC BufferSubData;
|
||||
PFNGLCLEARPROC Clear;
|
||||
PFNGLCLEARCOLORPROC ClearColor;
|
||||
PFNGLCOMPILESHADERPROC CompileShader;
|
||||
PFNGLCREATEPROGRAMPROC CreateProgram;
|
||||
PFNGLCREATESHADERPROC CreateShader;
|
||||
PFNGLDELETEBUFFERSPROC DeleteBuffers;
|
||||
PFNGLDELETEPROGRAMPROC DeleteProgram;
|
||||
PFNGLDELETESAMPLERSPROC DeleteSamplers;
|
||||
PFNGLDELETESHADERPROC DeleteShader;
|
||||
PFNGLDELETETEXTURESPROC DeleteTextures;
|
||||
PFNGLDELETEVERTEXARRAYSPROC DeleteVertexArrays;
|
||||
PFNGLDETACHSHADERPROC DetachShader;
|
||||
PFNGLDISABLEPROC Disable;
|
||||
PFNGLDISABLEVERTEXATTRIBARRAYPROC DisableVertexAttribArray;
|
||||
PFNGLDRAWELEMENTSPROC DrawElements;
|
||||
PFNGLDRAWELEMENTSBASEVERTEXPROC DrawElementsBaseVertex;
|
||||
PFNGLENABLEPROC Enable;
|
||||
PFNGLENABLEVERTEXATTRIBARRAYPROC EnableVertexAttribArray;
|
||||
PFNGLFLUSHPROC Flush;
|
||||
PFNGLGENBUFFERSPROC GenBuffers;
|
||||
PFNGLGENSAMPLERSPROC GenSamplers;
|
||||
PFNGLGENTEXTURESPROC GenTextures;
|
||||
PFNGLGENVERTEXARRAYSPROC GenVertexArrays;
|
||||
PFNGLGETATTRIBLOCATIONPROC GetAttribLocation;
|
||||
PFNGLGETERRORPROC GetError;
|
||||
PFNGLGETINTEGERVPROC GetIntegerv;
|
||||
PFNGLGETPROGRAMINFOLOGPROC GetProgramInfoLog;
|
||||
PFNGLGETPROGRAMIVPROC GetProgramiv;
|
||||
PFNGLGETSHADERINFOLOGPROC GetShaderInfoLog;
|
||||
PFNGLGETSHADERIVPROC GetShaderiv;
|
||||
PFNGLGETSTRINGPROC GetString;
|
||||
PFNGLGETSTRINGIPROC GetStringi;
|
||||
PFNGLGETUNIFORMLOCATIONPROC GetUniformLocation;
|
||||
PFNGLGETVERTEXATTRIBPOINTERVPROC GetVertexAttribPointerv;
|
||||
PFNGLGETVERTEXATTRIBIVPROC GetVertexAttribiv;
|
||||
PFNGLISENABLEDPROC IsEnabled;
|
||||
PFNGLISPROGRAMPROC IsProgram;
|
||||
PFNGLLINKPROGRAMPROC LinkProgram;
|
||||
PFNGLPIXELSTOREIPROC PixelStorei;
|
||||
PFNGLPOLYGONMODEPROC PolygonMode;
|
||||
PFNGLREADPIXELSPROC ReadPixels;
|
||||
PFNGLSAMPLERPARAMETERIPROC SamplerParameteri;
|
||||
PFNGLSCISSORPROC Scissor;
|
||||
PFNGLSHADERSOURCEPROC ShaderSource;
|
||||
PFNGLTEXIMAGE2DPROC TexImage2D;
|
||||
PFNGLTEXPARAMETERIPROC TexParameteri;
|
||||
PFNGLTEXSUBIMAGE2DPROC TexSubImage2D;
|
||||
PFNGLUNIFORM1IPROC Uniform1i;
|
||||
PFNGLUNIFORMMATRIX4FVPROC UniformMatrix4fv;
|
||||
PFNGLUSEPROGRAMPROC UseProgram;
|
||||
PFNGLVERTEXATTRIBPOINTERPROC VertexAttribPointer;
|
||||
PFNGLVIEWPORTPROC Viewport;
|
||||
} gl;
|
||||
};
|
||||
|
||||
GL3W_API extern union ImGL3WProcs imgl3wProcs;
|
||||
|
||||
/* OpenGL functions */
|
||||
#define glActiveTexture imgl3wProcs.gl.ActiveTexture
|
||||
#define glAttachShader imgl3wProcs.gl.AttachShader
|
||||
#define glBindBuffer imgl3wProcs.gl.BindBuffer
|
||||
#define glBindSampler imgl3wProcs.gl.BindSampler
|
||||
#define glBindTexture imgl3wProcs.gl.BindTexture
|
||||
#define glBindVertexArray imgl3wProcs.gl.BindVertexArray
|
||||
#define glBlendEquation imgl3wProcs.gl.BlendEquation
|
||||
#define glBlendEquationSeparate imgl3wProcs.gl.BlendEquationSeparate
|
||||
#define glBlendFuncSeparate imgl3wProcs.gl.BlendFuncSeparate
|
||||
#define glBufferData imgl3wProcs.gl.BufferData
|
||||
#define glBufferSubData imgl3wProcs.gl.BufferSubData
|
||||
#define glClear imgl3wProcs.gl.Clear
|
||||
#define glClearColor imgl3wProcs.gl.ClearColor
|
||||
#define glCompileShader imgl3wProcs.gl.CompileShader
|
||||
#define glCreateProgram imgl3wProcs.gl.CreateProgram
|
||||
#define glCreateShader imgl3wProcs.gl.CreateShader
|
||||
#define glDeleteBuffers imgl3wProcs.gl.DeleteBuffers
|
||||
#define glDeleteProgram imgl3wProcs.gl.DeleteProgram
|
||||
#define glDeleteSamplers imgl3wProcs.gl.DeleteSamplers
|
||||
#define glDeleteShader imgl3wProcs.gl.DeleteShader
|
||||
#define glDeleteTextures imgl3wProcs.gl.DeleteTextures
|
||||
#define glDeleteVertexArrays imgl3wProcs.gl.DeleteVertexArrays
|
||||
#define glDetachShader imgl3wProcs.gl.DetachShader
|
||||
#define glDisable imgl3wProcs.gl.Disable
|
||||
#define glDisableVertexAttribArray imgl3wProcs.gl.DisableVertexAttribArray
|
||||
#define glDrawElements imgl3wProcs.gl.DrawElements
|
||||
#define glDrawElementsBaseVertex imgl3wProcs.gl.DrawElementsBaseVertex
|
||||
#define glEnable imgl3wProcs.gl.Enable
|
||||
#define glEnableVertexAttribArray imgl3wProcs.gl.EnableVertexAttribArray
|
||||
#define glFlush imgl3wProcs.gl.Flush
|
||||
#define glGenBuffers imgl3wProcs.gl.GenBuffers
|
||||
#define glGenSamplers imgl3wProcs.gl.GenSamplers
|
||||
#define glGenTextures imgl3wProcs.gl.GenTextures
|
||||
#define glGenVertexArrays imgl3wProcs.gl.GenVertexArrays
|
||||
#define glGetAttribLocation imgl3wProcs.gl.GetAttribLocation
|
||||
#define glGetError imgl3wProcs.gl.GetError
|
||||
#define glGetIntegerv imgl3wProcs.gl.GetIntegerv
|
||||
#define glGetProgramInfoLog imgl3wProcs.gl.GetProgramInfoLog
|
||||
#define glGetProgramiv imgl3wProcs.gl.GetProgramiv
|
||||
#define glGetShaderInfoLog imgl3wProcs.gl.GetShaderInfoLog
|
||||
#define glGetShaderiv imgl3wProcs.gl.GetShaderiv
|
||||
#define glGetString imgl3wProcs.gl.GetString
|
||||
#define glGetStringi imgl3wProcs.gl.GetStringi
|
||||
#define glGetUniformLocation imgl3wProcs.gl.GetUniformLocation
|
||||
#define glGetVertexAttribPointerv imgl3wProcs.gl.GetVertexAttribPointerv
|
||||
#define glGetVertexAttribiv imgl3wProcs.gl.GetVertexAttribiv
|
||||
#define glIsEnabled imgl3wProcs.gl.IsEnabled
|
||||
#define glIsProgram imgl3wProcs.gl.IsProgram
|
||||
#define glLinkProgram imgl3wProcs.gl.LinkProgram
|
||||
#define glPixelStorei imgl3wProcs.gl.PixelStorei
|
||||
#define glPolygonMode imgl3wProcs.gl.PolygonMode
|
||||
#define glReadPixels imgl3wProcs.gl.ReadPixels
|
||||
#define glSamplerParameteri imgl3wProcs.gl.SamplerParameteri
|
||||
#define glScissor imgl3wProcs.gl.Scissor
|
||||
#define glShaderSource imgl3wProcs.gl.ShaderSource
|
||||
#define glTexImage2D imgl3wProcs.gl.TexImage2D
|
||||
#define glTexParameteri imgl3wProcs.gl.TexParameteri
|
||||
#define glTexSubImage2D imgl3wProcs.gl.TexSubImage2D
|
||||
#define glUniform1i imgl3wProcs.gl.Uniform1i
|
||||
#define glUniformMatrix4fv imgl3wProcs.gl.UniformMatrix4fv
|
||||
#define glUseProgram imgl3wProcs.gl.UseProgram
|
||||
#define glVertexAttribPointer imgl3wProcs.gl.VertexAttribPointer
|
||||
#define glViewport imgl3wProcs.gl.Viewport
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef IMGL3W_IMPL
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define GL3W_ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
|
||||
#if defined(_WIN32)
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#endif
|
||||
#include <windows.h>
|
||||
|
||||
static HMODULE libgl = NULL;
|
||||
typedef PROC(__stdcall* GL3WglGetProcAddr)(LPCSTR);
|
||||
static GL3WglGetProcAddr wgl_get_proc_address;
|
||||
|
||||
static int open_libgl(void)
|
||||
{
|
||||
libgl = LoadLibraryA("opengl32.dll");
|
||||
if (!libgl)
|
||||
return GL3W_ERROR_LIBRARY_OPEN;
|
||||
wgl_get_proc_address = (GL3WglGetProcAddr)GetProcAddress(libgl, "wglGetProcAddress");
|
||||
return GL3W_OK;
|
||||
}
|
||||
|
||||
static void close_libgl(void) { FreeLibrary(libgl); libgl = NULL; }
|
||||
static GL3WglProc get_proc(const char *proc)
|
||||
{
|
||||
GL3WglProc res;
|
||||
res = (GL3WglProc)wgl_get_proc_address(proc);
|
||||
if (!res)
|
||||
res = (GL3WglProc)GetProcAddress(libgl, proc);
|
||||
return res;
|
||||
}
|
||||
#elif defined(__APPLE__)
|
||||
#include <dlfcn.h>
|
||||
|
||||
static void *libgl = NULL;
|
||||
static int open_libgl(void)
|
||||
{
|
||||
libgl = dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY | RTLD_LOCAL);
|
||||
if (!libgl)
|
||||
return GL3W_ERROR_LIBRARY_OPEN;
|
||||
return GL3W_OK;
|
||||
}
|
||||
|
||||
static void close_libgl(void) { dlclose(libgl); libgl = NULL; }
|
||||
|
||||
static GL3WglProc get_proc(const char *proc)
|
||||
{
|
||||
GL3WglProc res;
|
||||
*(void **)(&res) = dlsym(libgl, proc);
|
||||
return res;
|
||||
}
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
|
||||
static void* libgl; // OpenGL library
|
||||
static void* libglx; // GLX library
|
||||
static void* libegl; // EGL library
|
||||
static GL3WGetProcAddressProc gl_get_proc_address;
|
||||
|
||||
static void close_libgl(void)
|
||||
{
|
||||
if (libgl) {
|
||||
dlclose(libgl);
|
||||
libgl = NULL;
|
||||
}
|
||||
if (libegl) {
|
||||
dlclose(libegl);
|
||||
libegl = NULL;
|
||||
}
|
||||
if (libglx) {
|
||||
dlclose(libglx);
|
||||
libglx = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int is_library_loaded(const char* name, void** lib)
|
||||
{
|
||||
#if defined(__HAIKU__)
|
||||
*lib = NULL; // no support for RTLD_NOLOAD on Haiku.
|
||||
#else
|
||||
*lib = dlopen(name, RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
|
||||
#endif
|
||||
return *lib != NULL;
|
||||
}
|
||||
|
||||
static int open_libs(void)
|
||||
{
|
||||
// On Linux we have two APIs to get process addresses: EGL and GLX.
|
||||
// EGL is supported under both X11 and Wayland, whereas GLX is X11-specific.
|
||||
|
||||
libgl = NULL;
|
||||
libegl = NULL;
|
||||
libglx = NULL;
|
||||
|
||||
// First check what's already loaded, the windowing library might have
|
||||
// already loaded either EGL or GLX and we want to use the same one.
|
||||
|
||||
if (is_library_loaded("libEGL.so.1", &libegl) ||
|
||||
is_library_loaded("libGLX.so.0", &libglx)) {
|
||||
libgl = dlopen("libOpenGL.so.0", RTLD_LAZY | RTLD_LOCAL);
|
||||
if (libgl)
|
||||
return GL3W_OK;
|
||||
else
|
||||
close_libgl();
|
||||
}
|
||||
|
||||
if (is_library_loaded("libGL.so", &libgl))
|
||||
return GL3W_OK;
|
||||
if (is_library_loaded("libGL.so.1", &libgl))
|
||||
return GL3W_OK;
|
||||
if (is_library_loaded("libGL.so.3", &libgl))
|
||||
return GL3W_OK;
|
||||
|
||||
// Neither is already loaded, so we have to load one. Try EGL first
|
||||
// because it is supported under both X11 and Wayland.
|
||||
|
||||
// Load OpenGL + EGL
|
||||
libgl = dlopen("libOpenGL.so.0", RTLD_LAZY | RTLD_LOCAL);
|
||||
libegl = dlopen("libEGL.so.1", RTLD_LAZY | RTLD_LOCAL);
|
||||
if (libgl && libegl)
|
||||
return GL3W_OK;
|
||||
else
|
||||
close_libgl();
|
||||
|
||||
// Fall back to legacy libGL, which includes GLX
|
||||
// While most systems use libGL.so.1, NetBSD seems to use that libGL.so.3. See https://github.com/ocornut/imgui/issues/6983
|
||||
libgl = dlopen("libGL.so", RTLD_LAZY | RTLD_LOCAL);
|
||||
if (!libgl)
|
||||
libgl = dlopen("libGL.so.1", RTLD_LAZY | RTLD_LOCAL);
|
||||
if (!libgl)
|
||||
libgl = dlopen("libGL.so.3", RTLD_LAZY | RTLD_LOCAL);
|
||||
|
||||
if (libgl)
|
||||
return GL3W_OK;
|
||||
|
||||
return GL3W_ERROR_LIBRARY_OPEN;
|
||||
}
|
||||
|
||||
static int open_libgl(void)
|
||||
{
|
||||
int res = open_libs();
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
if (libegl)
|
||||
*(void**)(&gl_get_proc_address) = dlsym(libegl, "eglGetProcAddress");
|
||||
else if (libglx)
|
||||
*(void**)(&gl_get_proc_address) = dlsym(libglx, "glXGetProcAddressARB");
|
||||
else
|
||||
*(void**)(&gl_get_proc_address) = dlsym(libgl, "glXGetProcAddressARB");
|
||||
|
||||
if (!gl_get_proc_address) {
|
||||
close_libgl();
|
||||
return GL3W_ERROR_LIBRARY_OPEN;
|
||||
}
|
||||
|
||||
return GL3W_OK;
|
||||
}
|
||||
|
||||
static GL3WglProc get_proc(const char* proc)
|
||||
{
|
||||
GL3WglProc res = NULL;
|
||||
|
||||
// Before EGL version 1.5, eglGetProcAddress doesn't support querying core
|
||||
// functions and may return a dummy function if we try, so try to load the
|
||||
// function from the GL library directly first.
|
||||
if (libegl)
|
||||
*(void**)(&res) = dlsym(libgl, proc);
|
||||
|
||||
if (!res)
|
||||
res = gl_get_proc_address(proc);
|
||||
|
||||
if (!libegl && !res)
|
||||
*(void**)(&res) = dlsym(libgl, proc);
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct { int major, minor; } version;
|
||||
|
||||
static int parse_version(void)
|
||||
{
|
||||
if (!glGetIntegerv)
|
||||
return GL3W_ERROR_INIT;
|
||||
glGetIntegerv(GL_MAJOR_VERSION, &version.major);
|
||||
glGetIntegerv(GL_MINOR_VERSION, &version.minor);
|
||||
if (version.major == 0 && version.minor == 0)
|
||||
{
|
||||
// Query GL_VERSION in desktop GL 2.x, the string will start with "<major>.<minor>"
|
||||
if (const char* gl_version = (const char*)glGetString(GL_VERSION))
|
||||
sscanf(gl_version, "%d.%d", &version.major, &version.minor);
|
||||
}
|
||||
if (version.major < 2)
|
||||
return GL3W_ERROR_OPENGL_VERSION;
|
||||
return GL3W_OK;
|
||||
}
|
||||
|
||||
static void load_procs(GL3WGetProcAddressProc proc);
|
||||
static void clear_procs();
|
||||
|
||||
int imgl3wInit(void)
|
||||
{
|
||||
int res = open_libgl();
|
||||
if (res)
|
||||
return res;
|
||||
atexit(close_libgl);
|
||||
return imgl3wInit2(get_proc);
|
||||
}
|
||||
|
||||
int imgl3wInit2(GL3WGetProcAddressProc proc)
|
||||
{
|
||||
load_procs(proc);
|
||||
return parse_version();
|
||||
}
|
||||
|
||||
void imgl3wShutdown(void)
|
||||
{
|
||||
close_libgl();
|
||||
clear_procs();
|
||||
}
|
||||
|
||||
int imgl3wIsSupported(int major, int minor)
|
||||
{
|
||||
if (major < 2)
|
||||
return 0;
|
||||
if (version.major == major)
|
||||
return version.minor >= minor;
|
||||
return version.major >= major;
|
||||
}
|
||||
|
||||
GL3WglProc imgl3wGetProcAddress(const char *proc) { return get_proc(proc); }
|
||||
|
||||
static const char *proc_names[] = {
|
||||
"glActiveTexture",
|
||||
"glAttachShader",
|
||||
"glBindBuffer",
|
||||
"glBindSampler",
|
||||
"glBindTexture",
|
||||
"glBindVertexArray",
|
||||
"glBlendEquation",
|
||||
"glBlendEquationSeparate",
|
||||
"glBlendFuncSeparate",
|
||||
"glBufferData",
|
||||
"glBufferSubData",
|
||||
"glClear",
|
||||
"glClearColor",
|
||||
"glCompileShader",
|
||||
"glCreateProgram",
|
||||
"glCreateShader",
|
||||
"glDeleteBuffers",
|
||||
"glDeleteProgram",
|
||||
"glDeleteSamplers",
|
||||
"glDeleteShader",
|
||||
"glDeleteTextures",
|
||||
"glDeleteVertexArrays",
|
||||
"glDetachShader",
|
||||
"glDisable",
|
||||
"glDisableVertexAttribArray",
|
||||
"glDrawElements",
|
||||
"glDrawElementsBaseVertex",
|
||||
"glEnable",
|
||||
"glEnableVertexAttribArray",
|
||||
"glFlush",
|
||||
"glGenBuffers",
|
||||
"glGenSamplers",
|
||||
"glGenTextures",
|
||||
"glGenVertexArrays",
|
||||
"glGetAttribLocation",
|
||||
"glGetError",
|
||||
"glGetIntegerv",
|
||||
"glGetProgramInfoLog",
|
||||
"glGetProgramiv",
|
||||
"glGetShaderInfoLog",
|
||||
"glGetShaderiv",
|
||||
"glGetString",
|
||||
"glGetStringi",
|
||||
"glGetUniformLocation",
|
||||
"glGetVertexAttribPointerv",
|
||||
"glGetVertexAttribiv",
|
||||
"glIsEnabled",
|
||||
"glIsProgram",
|
||||
"glLinkProgram",
|
||||
"glPixelStorei",
|
||||
"glPolygonMode",
|
||||
"glReadPixels",
|
||||
"glSamplerParameteri",
|
||||
"glScissor",
|
||||
"glShaderSource",
|
||||
"glTexImage2D",
|
||||
"glTexParameteri",
|
||||
"glTexSubImage2D",
|
||||
"glUniform1i",
|
||||
"glUniformMatrix4fv",
|
||||
"glUseProgram",
|
||||
"glVertexAttribPointer",
|
||||
"glViewport",
|
||||
};
|
||||
|
||||
GL3W_API union ImGL3WProcs imgl3wProcs;
|
||||
|
||||
static void load_procs(GL3WGetProcAddressProc proc)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < GL3W_ARRAY_SIZE(proc_names); i++)
|
||||
imgl3wProcs.ptr[i] = proc(proc_names[i]);
|
||||
}
|
||||
|
||||
static void clear_procs()
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < GL3W_ARRAY_SIZE(proc_names); i++)
|
||||
imgl3wProcs.ptr[i] = nullptr;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,23 +1,54 @@
|
||||
// dear imgui: Platform Backend for OSX / Cocoa
|
||||
// This needs to be used along with a Renderer (e.g. OpenGL2, OpenGL3, Vulkan, Metal..)
|
||||
// [ALPHA] Early backend, not well tested. If you want a portable application, prefer using the GLFW or SDL platform Backends on Mac.
|
||||
// - Not well tested. If you want a portable application, prefer using the GLFW or SDL platform Backends on Mac.
|
||||
// - Requires linking with the GameController framework ("-framework GameController").
|
||||
|
||||
// Implemented features:
|
||||
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
// [X] Platform: OSX clipboard is supported within core Dear ImGui (no specific code in this backend).
|
||||
// Issues:
|
||||
// [ ] Platform: Keys are all generally very broken. Best using [event keycode] and not [event characters]..
|
||||
// [X] Platform: Clipboard support is part of core Dear ImGui (no specific code in this backend).
|
||||
// [X] Platform: Mouse support. Can discriminate Mouse/Pen.
|
||||
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy kVK_* values are obsolete since 1.87 and not supported since 1.91.5]
|
||||
// [X] Platform: Gamepad support.
|
||||
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
// [X] Platform: IME support.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
#pragma once
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
#ifdef __OBJC__
|
||||
|
||||
@class NSEvent;
|
||||
@class NSView;
|
||||
|
||||
IMGUI_IMPL_API bool ImGui_ImplOSX_Init();
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
IMGUI_IMPL_API bool ImGui_ImplOSX_Init(NSView* _Nonnull view);
|
||||
IMGUI_IMPL_API void ImGui_ImplOSX_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplOSX_NewFrame(NSView* _Nullable view);
|
||||
IMGUI_IMPL_API bool ImGui_ImplOSX_HandleEvent(NSEvent* _Nonnull event, NSView* _Nullable view);
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// C++ API
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifdef IMGUI_IMPL_METAL_CPP_EXTENSIONS
|
||||
// #include <AppKit/AppKit.hpp>
|
||||
#ifndef __OBJC__
|
||||
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
IMGUI_IMPL_API bool ImGui_ImplOSX_Init(void* _Nonnull view);
|
||||
IMGUI_IMPL_API void ImGui_ImplOSX_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplOSX_NewFrame(void* _Nullable view);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
@@ -1,23 +1,65 @@
|
||||
// dear imgui: Platform Backend for OSX / Cocoa
|
||||
// This needs to be used along with a Renderer (e.g. OpenGL2, OpenGL3, Vulkan, Metal..)
|
||||
// [ALPHA] Early backend, not well tested. If you want a portable application, prefer using the GLFW or SDL platform Backends on Mac.
|
||||
// - Not well tested. If you want a portable application, prefer using the GLFW or SDL platform Backends on Mac.
|
||||
// - Requires linking with the GameController framework ("-framework GameController").
|
||||
|
||||
// Implemented features:
|
||||
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
// [X] Platform: OSX clipboard is supported within core Dear ImGui (no specific code in this backend).
|
||||
// Issues:
|
||||
// [ ] Platform: Keys are all generally very broken. Best using [event keycode] and not [event characters]..
|
||||
// [X] Platform: Clipboard support is part of core Dear ImGui (no specific code in this backend).
|
||||
// [X] Platform: Mouse support. Can discriminate Mouse/Pen.
|
||||
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy kVK_* values are obsolete since 1.87 and not supported since 1.91.5]
|
||||
// [X] Platform: Gamepad support.
|
||||
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
// [X] Platform: IME support.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_osx.h"
|
||||
#import "imgui.h"
|
||||
#ifndef IMGUI_DISABLE
|
||||
#import "imgui_impl_osx.h"
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <Carbon/Carbon.h>
|
||||
#import <GameController/GameController.h>
|
||||
#import <time.h>
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown.
|
||||
// 2025-06-27: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support.
|
||||
// 2025-06-12: ImGui_ImplOSX_HandleEvent() only process event for window containing our view. (#8644)
|
||||
// 2025-03-21: Fill gamepad inputs and set ImGuiBackendFlags_HasGamepad regardless of ImGuiConfigFlags_NavEnableGamepad being set.
|
||||
// 2025-01-20: Removed notification observer when shutting down. (#8331)
|
||||
// 2024-08-22: moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO:
|
||||
// - io.GetClipboardTextFn -> platform_io.Platform_GetClipboardTextFn
|
||||
// - io.SetClipboardTextFn -> platform_io.Platform_SetClipboardTextFn
|
||||
// - io.PlatformSetImeDataFn -> platform_io.Platform_SetImeDataFn
|
||||
// 2024-07-02: Update for io.SetPlatformImeDataFn() -> io.PlatformSetImeDataFn() renaming in main library.
|
||||
// 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F20 function keys. Stopped mapping F13 into PrintScreen.
|
||||
// 2023-04-09: Inputs: Added support for io.AddMouseSourceEvent() to discriminate ImGuiMouseSource_Mouse/ImGuiMouseSource_Pen.
|
||||
// 2023-02-01: Fixed scroll wheel scaling for devices emitting events with hasPreciseScrollingDeltas==false (e.g. non-Apple mice).
|
||||
// 2022-11-02: Fixed mouse coordinates before clicking the host window.
|
||||
// 2022-10-06: Fixed mouse inputs on flipped views.
|
||||
// 2022-09-26: Inputs: Renamed ImGuiKey_ModXXX introduced in 1.87 to ImGuiMod_XXX (old names still supported).
|
||||
// 2022-05-03: Inputs: Removed ImGui_ImplOSX_HandleEvent() from backend API in favor of backend automatically handling event capture.
|
||||
// 2022-04-27: Misc: Store backend data in a per-context struct, allowing to use this backend with multiple contexts.
|
||||
// 2022-03-22: Inputs: Monitor NSKeyUp events to catch missing keyUp for key when user press Cmd + key
|
||||
// 2022-02-07: Inputs: Forward keyDown/keyUp events to OS when unused by dear imgui.
|
||||
// 2022-01-31: Fixed building with old Xcode versions that are missing gamepad features.
|
||||
// 2022-01-26: Inputs: replaced short-lived io.AddKeyModsEvent() (added two weeks ago) with io.AddKeyEvent() using ImGuiKey_ModXXX flags. Sorry for the confusion.
|
||||
// 2021-01-20: Inputs: calling new io.AddKeyAnalogEvent() for gamepad support, instead of writing directly to io.NavInputs[].
|
||||
// 2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEvent(), io.AddMouseWheelEvent() API (1.87+).
|
||||
// 2022-01-12: Inputs: Added basic Platform IME support, hooking the io.SetPlatformImeDataFn() function.
|
||||
// 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range.
|
||||
// 2021-12-13: *BREAKING CHANGE* Add NSView parameter to ImGui_ImplOSX_Init(). Generally fix keyboard support. Using kVK_* codes for keyboard keys.
|
||||
// 2021-12-13: Add game controller support.
|
||||
// 2021-09-21: Use mach_absolute_time as CFAbsoluteTimeGetCurrent can jump backwards.
|
||||
// 2021-08-17: Calling io.AddFocusEvent() on NSApplicationDidBecomeActiveNotification/NSApplicationDidResignActiveNotification events.
|
||||
// 2021-06-23: Inputs: Added a fix for shortcuts using CTRL key instead of CMD key.
|
||||
// 2021-04-19: Inputs: Added a fix for keys remaining stuck in pressed state when CMD-tabbing into different application.
|
||||
// 2021-01-27: Inputs: Added a fix for mouse position not being reported when mouse buttons other than left one are down.
|
||||
// 2020-10-28: Inputs: Added a fix for handling keypad-enter key.
|
||||
@@ -31,15 +73,36 @@
|
||||
// 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window.
|
||||
// 2018-07-07: Initial version.
|
||||
|
||||
@class ImFocusObserver;
|
||||
#define APPLE_HAS_BUTTON_OPTIONS (__IPHONE_OS_VERSION_MIN_REQUIRED >= 130000 || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500 || __TV_OS_VERSION_MIN_REQUIRED >= 130000)
|
||||
#define APPLE_HAS_CONTROLLER (__IPHONE_OS_VERSION_MIN_REQUIRED >= 140000 || __MAC_OS_X_VERSION_MIN_REQUIRED >= 110000 || __TV_OS_VERSION_MIN_REQUIRED >= 140000)
|
||||
#define APPLE_HAS_THUMBSTICKS (__IPHONE_OS_VERSION_MIN_REQUIRED >= 120100 || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101401 || __TV_OS_VERSION_MIN_REQUIRED >= 120100)
|
||||
|
||||
@class ImGuiObserver;
|
||||
@class KeyEventResponder;
|
||||
|
||||
// Data
|
||||
static CFAbsoluteTime g_Time = 0.0;
|
||||
static NSCursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = {};
|
||||
static bool g_MouseCursorHidden = false;
|
||||
static bool g_MouseJustPressed[ImGuiMouseButton_COUNT] = {};
|
||||
static bool g_MouseDown[ImGuiMouseButton_COUNT] = {};
|
||||
static ImFocusObserver* g_FocusObserver = NULL;
|
||||
struct ImGui_ImplOSX_Data
|
||||
{
|
||||
CFTimeInterval Time;
|
||||
NSCursor* MouseCursors[ImGuiMouseCursor_COUNT];
|
||||
bool MouseCursorHidden;
|
||||
ImGuiObserver* Observer;
|
||||
KeyEventResponder* KeyEventResponder;
|
||||
NSTextInputContext* InputContext;
|
||||
id Monitor;
|
||||
NSWindow* Window;
|
||||
|
||||
ImGui_ImplOSX_Data() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
static ImGui_ImplOSX_Data* ImGui_ImplOSX_GetBackendData() { return (ImGui_ImplOSX_Data*)ImGui::GetIO().BackendPlatformUserData; }
|
||||
static void ImGui_ImplOSX_DestroyBackendData() { IM_DELETE(ImGui_ImplOSX_GetBackendData()); }
|
||||
|
||||
static inline CFTimeInterval GetMachAbsoluteTimeInSeconds() { return (CFTimeInterval)(double)(clock_gettime_nsec_np(CLOCK_UPTIME_RAW) / 1e9); }
|
||||
|
||||
// Forward Declarations
|
||||
static void ImGui_ImplOSX_AddTrackingArea(NSView* _Nonnull view);
|
||||
static bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view);
|
||||
|
||||
// Undocumented methods for creating cursors.
|
||||
@interface NSCursor()
|
||||
@@ -47,102 +110,353 @@ static ImFocusObserver* g_FocusObserver = NULL;
|
||||
+ (id)_windowResizeNorthEastSouthWestCursor;
|
||||
+ (id)_windowResizeNorthSouthCursor;
|
||||
+ (id)_windowResizeEastWestCursor;
|
||||
+ (id)busyButClickableCursor;
|
||||
@end
|
||||
|
||||
static void resetKeys()
|
||||
/**
|
||||
KeyEventResponder implements the NSTextInputClient protocol as is required by the macOS text input manager.
|
||||
|
||||
The macOS text input manager is invoked by calling the interpretKeyEvents method from the keyDown method.
|
||||
Keyboard events are then evaluated by the macOS input manager and valid text input is passed back via the
|
||||
insertText:replacementRange method.
|
||||
|
||||
This is the same approach employed by other cross-platform libraries such as SDL2:
|
||||
https://github.com/spurious/SDL-mirror/blob/e17aacbd09e65a4fd1e166621e011e581fb017a8/src/video/cocoa/SDL_cocoakeyboard.m#L53
|
||||
and GLFW:
|
||||
https://github.com/glfw/glfw/blob/b55a517ae0c7b5127dffa79a64f5406021bf9076/src/cocoa_window.m#L722-L723
|
||||
*/
|
||||
@interface KeyEventResponder: NSView<NSTextInputClient>
|
||||
@end
|
||||
|
||||
@implementation KeyEventResponder
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
memset(io.KeysDown, 0, sizeof(io.KeysDown));
|
||||
io.KeyCtrl = io.KeyShift = io.KeyAlt = io.KeySuper = false;
|
||||
float _posX;
|
||||
float _posY;
|
||||
NSRect _imeRect;
|
||||
}
|
||||
|
||||
@interface ImFocusObserver : NSObject
|
||||
#pragma mark - Public
|
||||
|
||||
- (void)setImePosX:(float)posX imePosY:(float)posY
|
||||
{
|
||||
_posX = posX;
|
||||
_posY = posY;
|
||||
}
|
||||
|
||||
- (void)updateImePosWithView:(NSView *)view
|
||||
{
|
||||
NSWindow* window = view.window;
|
||||
if (!window)
|
||||
return;
|
||||
{
|
||||
NSRect contentRect = [window contentRectForFrameRect:window.frame];
|
||||
NSRect rect = NSMakeRect(_posX, contentRect.size.height - _posY, 0, 0);
|
||||
_imeRect = [window convertRectToScreen:rect];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)viewDidMoveToWindow
|
||||
{
|
||||
// Ensure self is a first responder to receive the input events.
|
||||
[self.window makeFirstResponder:self];
|
||||
}
|
||||
|
||||
- (void)keyDown:(NSEvent*)event
|
||||
{
|
||||
if (!ImGui_ImplOSX_HandleEvent(event, self))
|
||||
[super keyDown:event];
|
||||
|
||||
// Call to the macOS input manager system.
|
||||
[self interpretKeyEvents:@[event]];
|
||||
}
|
||||
|
||||
- (void)keyUp:(NSEvent*)event
|
||||
{
|
||||
if (!ImGui_ImplOSX_HandleEvent(event, self))
|
||||
[super keyUp:event];
|
||||
}
|
||||
|
||||
- (void)insertText:(id)aString replacementRange:(NSRange)replacementRange
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
NSString* characters;
|
||||
if ([aString isKindOfClass:[NSAttributedString class]])
|
||||
characters = [aString string];
|
||||
else
|
||||
characters = (NSString*)aString;
|
||||
|
||||
io.AddInputCharactersUTF8(characters.UTF8String);
|
||||
}
|
||||
|
||||
- (BOOL)acceptsFirstResponder
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)doCommandBySelector:(SEL)myselector
|
||||
{
|
||||
}
|
||||
|
||||
- (nullable NSAttributedString*)attributedSubstringForProposedRange:(NSRange)range actualRange:(nullable NSRangePointer)actualRange
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSUInteger)characterIndexForPoint:(NSPoint)point
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (NSRect)firstRectForCharacterRange:(NSRange)range actualRange:(nullable NSRangePointer)actualRange
|
||||
{
|
||||
return _imeRect;
|
||||
}
|
||||
|
||||
- (BOOL)hasMarkedText
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSRange)markedRange
|
||||
{
|
||||
return NSMakeRange(NSNotFound, 0);
|
||||
}
|
||||
|
||||
- (NSRange)selectedRange
|
||||
{
|
||||
return NSMakeRange(NSNotFound, 0);
|
||||
}
|
||||
|
||||
- (void)setMarkedText:(nonnull id)string selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange
|
||||
{
|
||||
}
|
||||
|
||||
- (void)unmarkText
|
||||
{
|
||||
}
|
||||
|
||||
- (nonnull NSArray<NSAttributedStringKey>*)validAttributesForMarkedText
|
||||
{
|
||||
return @[];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface ImGuiObserver : NSObject
|
||||
|
||||
- (void)onApplicationBecomeActive:(NSNotification*)aNotification;
|
||||
- (void)onApplicationBecomeInactive:(NSNotification*)aNotification;
|
||||
|
||||
@end
|
||||
|
||||
@implementation ImFocusObserver
|
||||
@implementation ImGuiObserver
|
||||
|
||||
- (void)onApplicationBecomeActive:(NSNotification*)aNotification
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.AddFocusEvent(true);
|
||||
}
|
||||
|
||||
- (void)onApplicationBecomeInactive:(NSNotification*)aNotification
|
||||
{
|
||||
// Unfocused applications do not receive input events, therefore we must manually
|
||||
// release any pressed keys when application loses focus, otherwise they would remain
|
||||
// stuck in a pressed state. https://github.com/ocornut/imgui/issues/3832
|
||||
resetKeys();
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.AddFocusEvent(false);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
// Functions
|
||||
bool ImGui_ImplOSX_Init()
|
||||
|
||||
// Not static to allow third-party code to use that if they want to (but undocumented)
|
||||
ImGuiKey ImGui_ImplOSX_KeyCodeToImGuiKey(int key_code);
|
||||
ImGuiKey ImGui_ImplOSX_KeyCodeToImGuiKey(int key_code)
|
||||
{
|
||||
switch (key_code)
|
||||
{
|
||||
case kVK_ANSI_A: return ImGuiKey_A;
|
||||
case kVK_ANSI_S: return ImGuiKey_S;
|
||||
case kVK_ANSI_D: return ImGuiKey_D;
|
||||
case kVK_ANSI_F: return ImGuiKey_F;
|
||||
case kVK_ANSI_H: return ImGuiKey_H;
|
||||
case kVK_ANSI_G: return ImGuiKey_G;
|
||||
case kVK_ANSI_Z: return ImGuiKey_Z;
|
||||
case kVK_ANSI_X: return ImGuiKey_X;
|
||||
case kVK_ANSI_C: return ImGuiKey_C;
|
||||
case kVK_ANSI_V: return ImGuiKey_V;
|
||||
case kVK_ANSI_B: return ImGuiKey_B;
|
||||
case kVK_ANSI_Q: return ImGuiKey_Q;
|
||||
case kVK_ANSI_W: return ImGuiKey_W;
|
||||
case kVK_ANSI_E: return ImGuiKey_E;
|
||||
case kVK_ANSI_R: return ImGuiKey_R;
|
||||
case kVK_ANSI_Y: return ImGuiKey_Y;
|
||||
case kVK_ANSI_T: return ImGuiKey_T;
|
||||
case kVK_ANSI_1: return ImGuiKey_1;
|
||||
case kVK_ANSI_2: return ImGuiKey_2;
|
||||
case kVK_ANSI_3: return ImGuiKey_3;
|
||||
case kVK_ANSI_4: return ImGuiKey_4;
|
||||
case kVK_ANSI_6: return ImGuiKey_6;
|
||||
case kVK_ANSI_5: return ImGuiKey_5;
|
||||
case kVK_ANSI_Equal: return ImGuiKey_Equal;
|
||||
case kVK_ANSI_9: return ImGuiKey_9;
|
||||
case kVK_ANSI_7: return ImGuiKey_7;
|
||||
case kVK_ANSI_Minus: return ImGuiKey_Minus;
|
||||
case kVK_ANSI_8: return ImGuiKey_8;
|
||||
case kVK_ANSI_0: return ImGuiKey_0;
|
||||
case kVK_ANSI_RightBracket: return ImGuiKey_RightBracket;
|
||||
case kVK_ANSI_O: return ImGuiKey_O;
|
||||
case kVK_ANSI_U: return ImGuiKey_U;
|
||||
case kVK_ANSI_LeftBracket: return ImGuiKey_LeftBracket;
|
||||
case kVK_ANSI_I: return ImGuiKey_I;
|
||||
case kVK_ANSI_P: return ImGuiKey_P;
|
||||
case kVK_ANSI_L: return ImGuiKey_L;
|
||||
case kVK_ANSI_J: return ImGuiKey_J;
|
||||
case kVK_ANSI_Quote: return ImGuiKey_Apostrophe;
|
||||
case kVK_ANSI_K: return ImGuiKey_K;
|
||||
case kVK_ANSI_Semicolon: return ImGuiKey_Semicolon;
|
||||
case kVK_ANSI_Backslash: return ImGuiKey_Backslash;
|
||||
case kVK_ANSI_Comma: return ImGuiKey_Comma;
|
||||
case kVK_ANSI_Slash: return ImGuiKey_Slash;
|
||||
case kVK_ANSI_N: return ImGuiKey_N;
|
||||
case kVK_ANSI_M: return ImGuiKey_M;
|
||||
case kVK_ANSI_Period: return ImGuiKey_Period;
|
||||
case kVK_ANSI_Grave: return ImGuiKey_GraveAccent;
|
||||
case kVK_ANSI_KeypadDecimal: return ImGuiKey_KeypadDecimal;
|
||||
case kVK_ANSI_KeypadMultiply: return ImGuiKey_KeypadMultiply;
|
||||
case kVK_ANSI_KeypadPlus: return ImGuiKey_KeypadAdd;
|
||||
case kVK_ANSI_KeypadClear: return ImGuiKey_NumLock;
|
||||
case kVK_ANSI_KeypadDivide: return ImGuiKey_KeypadDivide;
|
||||
case kVK_ANSI_KeypadEnter: return ImGuiKey_KeypadEnter;
|
||||
case kVK_ANSI_KeypadMinus: return ImGuiKey_KeypadSubtract;
|
||||
case kVK_ANSI_KeypadEquals: return ImGuiKey_KeypadEqual;
|
||||
case kVK_ANSI_Keypad0: return ImGuiKey_Keypad0;
|
||||
case kVK_ANSI_Keypad1: return ImGuiKey_Keypad1;
|
||||
case kVK_ANSI_Keypad2: return ImGuiKey_Keypad2;
|
||||
case kVK_ANSI_Keypad3: return ImGuiKey_Keypad3;
|
||||
case kVK_ANSI_Keypad4: return ImGuiKey_Keypad4;
|
||||
case kVK_ANSI_Keypad5: return ImGuiKey_Keypad5;
|
||||
case kVK_ANSI_Keypad6: return ImGuiKey_Keypad6;
|
||||
case kVK_ANSI_Keypad7: return ImGuiKey_Keypad7;
|
||||
case kVK_ANSI_Keypad8: return ImGuiKey_Keypad8;
|
||||
case kVK_ANSI_Keypad9: return ImGuiKey_Keypad9;
|
||||
case kVK_Return: return ImGuiKey_Enter;
|
||||
case kVK_Tab: return ImGuiKey_Tab;
|
||||
case kVK_Space: return ImGuiKey_Space;
|
||||
case kVK_Delete: return ImGuiKey_Backspace;
|
||||
case kVK_Escape: return ImGuiKey_Escape;
|
||||
case kVK_CapsLock: return ImGuiKey_CapsLock;
|
||||
case kVK_Control: return ImGuiKey_LeftCtrl;
|
||||
case kVK_Shift: return ImGuiKey_LeftShift;
|
||||
case kVK_Option: return ImGuiKey_LeftAlt;
|
||||
case kVK_Command: return ImGuiKey_LeftSuper;
|
||||
case kVK_RightControl: return ImGuiKey_RightCtrl;
|
||||
case kVK_RightShift: return ImGuiKey_RightShift;
|
||||
case kVK_RightOption: return ImGuiKey_RightAlt;
|
||||
case kVK_RightCommand: return ImGuiKey_RightSuper;
|
||||
// case kVK_Function: return ImGuiKey_;
|
||||
// case kVK_VolumeUp: return ImGuiKey_;
|
||||
// case kVK_VolumeDown: return ImGuiKey_;
|
||||
// case kVK_Mute: return ImGuiKey_;
|
||||
case kVK_F1: return ImGuiKey_F1;
|
||||
case kVK_F2: return ImGuiKey_F2;
|
||||
case kVK_F3: return ImGuiKey_F3;
|
||||
case kVK_F4: return ImGuiKey_F4;
|
||||
case kVK_F5: return ImGuiKey_F5;
|
||||
case kVK_F6: return ImGuiKey_F6;
|
||||
case kVK_F7: return ImGuiKey_F7;
|
||||
case kVK_F8: return ImGuiKey_F8;
|
||||
case kVK_F9: return ImGuiKey_F9;
|
||||
case kVK_F10: return ImGuiKey_F10;
|
||||
case kVK_F11: return ImGuiKey_F11;
|
||||
case kVK_F12: return ImGuiKey_F12;
|
||||
case kVK_F13: return ImGuiKey_F13;
|
||||
case kVK_F14: return ImGuiKey_F14;
|
||||
case kVK_F15: return ImGuiKey_F15;
|
||||
case kVK_F16: return ImGuiKey_F16;
|
||||
case kVK_F17: return ImGuiKey_F17;
|
||||
case kVK_F18: return ImGuiKey_F18;
|
||||
case kVK_F19: return ImGuiKey_F19;
|
||||
case kVK_F20: return ImGuiKey_F20;
|
||||
case 0x6E: return ImGuiKey_Menu;
|
||||
case kVK_Help: return ImGuiKey_Insert;
|
||||
case kVK_Home: return ImGuiKey_Home;
|
||||
case kVK_PageUp: return ImGuiKey_PageUp;
|
||||
case kVK_ForwardDelete: return ImGuiKey_Delete;
|
||||
case kVK_End: return ImGuiKey_End;
|
||||
case kVK_PageDown: return ImGuiKey_PageDown;
|
||||
case kVK_LeftArrow: return ImGuiKey_LeftArrow;
|
||||
case kVK_RightArrow: return ImGuiKey_RightArrow;
|
||||
case kVK_DownArrow: return ImGuiKey_DownArrow;
|
||||
case kVK_UpArrow: return ImGuiKey_UpArrow;
|
||||
default: return ImGuiKey_None;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef IMGUI_IMPL_METAL_CPP_EXTENSIONS
|
||||
|
||||
IMGUI_IMPL_API bool ImGui_ImplOSX_Init(void* _Nonnull view) {
|
||||
return ImGui_ImplOSX_Init((__bridge NSView*)(view));
|
||||
}
|
||||
|
||||
IMGUI_IMPL_API void ImGui_ImplOSX_NewFrame(void* _Nullable view) {
|
||||
return ImGui_ImplOSX_NewFrame((__bridge NSView*)(view));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
bool ImGui_ImplOSX_Init(NSView* view)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
IMGUI_CHECKVERSION();
|
||||
IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!");
|
||||
|
||||
// Setup backend capabilities flags
|
||||
ImGui_ImplOSX_Data* bd = IM_NEW(ImGui_ImplOSX_Data)();
|
||||
io.BackendPlatformUserData = (void*)bd;
|
||||
io.BackendPlatformName = "imgui_impl_osx";
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
||||
//io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
|
||||
//io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; // We can create multi-viewports on the Platform side (optional)
|
||||
//io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport; // We can set io.MouseHoveredViewport correctly (optional, not easy)
|
||||
io.BackendPlatformName = "imgui_impl_osx";
|
||||
|
||||
// Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeyDown[] array.
|
||||
const int offset_for_function_keys = 256 - 0xF700;
|
||||
io.KeyMap[ImGuiKey_Tab] = '\t';
|
||||
io.KeyMap[ImGuiKey_LeftArrow] = NSLeftArrowFunctionKey + offset_for_function_keys;
|
||||
io.KeyMap[ImGuiKey_RightArrow] = NSRightArrowFunctionKey + offset_for_function_keys;
|
||||
io.KeyMap[ImGuiKey_UpArrow] = NSUpArrowFunctionKey + offset_for_function_keys;
|
||||
io.KeyMap[ImGuiKey_DownArrow] = NSDownArrowFunctionKey + offset_for_function_keys;
|
||||
io.KeyMap[ImGuiKey_PageUp] = NSPageUpFunctionKey + offset_for_function_keys;
|
||||
io.KeyMap[ImGuiKey_PageDown] = NSPageDownFunctionKey + offset_for_function_keys;
|
||||
io.KeyMap[ImGuiKey_Home] = NSHomeFunctionKey + offset_for_function_keys;
|
||||
io.KeyMap[ImGuiKey_End] = NSEndFunctionKey + offset_for_function_keys;
|
||||
io.KeyMap[ImGuiKey_Insert] = NSInsertFunctionKey + offset_for_function_keys;
|
||||
io.KeyMap[ImGuiKey_Delete] = NSDeleteFunctionKey + offset_for_function_keys;
|
||||
io.KeyMap[ImGuiKey_Backspace] = 127;
|
||||
io.KeyMap[ImGuiKey_Space] = 32;
|
||||
io.KeyMap[ImGuiKey_Enter] = 13;
|
||||
io.KeyMap[ImGuiKey_Escape] = 27;
|
||||
io.KeyMap[ImGuiKey_KeyPadEnter] = 3;
|
||||
io.KeyMap[ImGuiKey_A] = 'A';
|
||||
io.KeyMap[ImGuiKey_C] = 'C';
|
||||
io.KeyMap[ImGuiKey_V] = 'V';
|
||||
io.KeyMap[ImGuiKey_X] = 'X';
|
||||
io.KeyMap[ImGuiKey_Y] = 'Y';
|
||||
io.KeyMap[ImGuiKey_Z] = 'Z';
|
||||
bd->Observer = [ImGuiObserver new];
|
||||
bd->Window = view.window ?: NSApp.orderedWindows.firstObject;
|
||||
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
|
||||
main_viewport->PlatformHandle = main_viewport->PlatformHandleRaw = (__bridge_retained void*)bd->Window;
|
||||
|
||||
// Load cursors. Some of them are undocumented.
|
||||
g_MouseCursorHidden = false;
|
||||
g_MouseCursors[ImGuiMouseCursor_Arrow] = [NSCursor arrowCursor];
|
||||
g_MouseCursors[ImGuiMouseCursor_TextInput] = [NSCursor IBeamCursor];
|
||||
g_MouseCursors[ImGuiMouseCursor_ResizeAll] = [NSCursor closedHandCursor];
|
||||
g_MouseCursors[ImGuiMouseCursor_Hand] = [NSCursor pointingHandCursor];
|
||||
g_MouseCursors[ImGuiMouseCursor_NotAllowed] = [NSCursor operationNotAllowedCursor];
|
||||
g_MouseCursors[ImGuiMouseCursor_ResizeNS] = [NSCursor respondsToSelector:@selector(_windowResizeNorthSouthCursor)] ? [NSCursor _windowResizeNorthSouthCursor] : [NSCursor resizeUpDownCursor];
|
||||
g_MouseCursors[ImGuiMouseCursor_ResizeEW] = [NSCursor respondsToSelector:@selector(_windowResizeEastWestCursor)] ? [NSCursor _windowResizeEastWestCursor] : [NSCursor resizeLeftRightCursor];
|
||||
g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = [NSCursor respondsToSelector:@selector(_windowResizeNorthEastSouthWestCursor)] ? [NSCursor _windowResizeNorthEastSouthWestCursor] : [NSCursor closedHandCursor];
|
||||
g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = [NSCursor respondsToSelector:@selector(_windowResizeNorthWestSouthEastCursor)] ? [NSCursor _windowResizeNorthWestSouthEastCursor] : [NSCursor closedHandCursor];
|
||||
bd->MouseCursorHidden = false;
|
||||
bd->MouseCursors[ImGuiMouseCursor_Arrow] = [NSCursor arrowCursor];
|
||||
bd->MouseCursors[ImGuiMouseCursor_TextInput] = [NSCursor IBeamCursor];
|
||||
bd->MouseCursors[ImGuiMouseCursor_ResizeAll] = [NSCursor closedHandCursor];
|
||||
bd->MouseCursors[ImGuiMouseCursor_ResizeNS] = [NSCursor respondsToSelector:@selector(_windowResizeNorthSouthCursor)] ? [NSCursor _windowResizeNorthSouthCursor] : [NSCursor resizeUpDownCursor];
|
||||
bd->MouseCursors[ImGuiMouseCursor_ResizeEW] = [NSCursor respondsToSelector:@selector(_windowResizeEastWestCursor)] ? [NSCursor _windowResizeEastWestCursor] : [NSCursor resizeLeftRightCursor];
|
||||
bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = [NSCursor respondsToSelector:@selector(_windowResizeNorthEastSouthWestCursor)] ? [NSCursor _windowResizeNorthEastSouthWestCursor] : [NSCursor closedHandCursor];
|
||||
bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = [NSCursor respondsToSelector:@selector(_windowResizeNorthWestSouthEastCursor)] ? [NSCursor _windowResizeNorthWestSouthEastCursor] : [NSCursor closedHandCursor];
|
||||
bd->MouseCursors[ImGuiMouseCursor_Hand] = [NSCursor pointingHandCursor];
|
||||
bd->MouseCursors[ImGuiMouseCursor_Wait] = bd->MouseCursors[ImGuiMouseCursor_Progress] = [NSCursor respondsToSelector:@selector(busyButClickableCursor)] ? [NSCursor busyButClickableCursor] : [NSCursor arrowCursor];
|
||||
bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = [NSCursor operationNotAllowedCursor];
|
||||
|
||||
// Note that imgui.cpp also include default OSX clipboard handlers which can be enabled
|
||||
// by adding '#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS' in imconfig.h and adding '-framework ApplicationServices' to your linker command-line.
|
||||
// Since we are already in ObjC land here, it is easy for us to add a clipboard handler using the NSPasteboard api.
|
||||
io.SetClipboardTextFn = [](void*, const char* str) -> void
|
||||
platform_io.Platform_SetClipboardTextFn = [](ImGuiContext*, const char* str) -> void
|
||||
{
|
||||
NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
|
||||
[pasteboard declareTypes:[NSArray arrayWithObject:NSPasteboardTypeString] owner:nil];
|
||||
[pasteboard setString:[NSString stringWithUTF8String:str] forType:NSPasteboardTypeString];
|
||||
};
|
||||
|
||||
io.GetClipboardTextFn = [](void*) -> const char*
|
||||
platform_io.Platform_GetClipboardTextFn = [](ImGuiContext*) -> const char*
|
||||
{
|
||||
NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
|
||||
NSString* available = [pasteboard availableTypeFromArray: [NSArray arrayWithObject:NSPasteboardTypeString]];
|
||||
if (![available isEqualToString:NSPasteboardTypeString])
|
||||
return NULL;
|
||||
return nullptr;
|
||||
|
||||
NSString* string = [pasteboard stringForType:NSPasteboardTypeString];
|
||||
if (string == nil)
|
||||
return NULL;
|
||||
return nullptr;
|
||||
|
||||
const char* string_c = (const char*)[string UTF8String];
|
||||
size_t string_len = strlen(string_c);
|
||||
@@ -152,31 +466,69 @@ bool ImGui_ImplOSX_Init()
|
||||
return s_clipboard.Data;
|
||||
};
|
||||
|
||||
g_FocusObserver = [[ImFocusObserver alloc] init];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:g_FocusObserver
|
||||
[[NSNotificationCenter defaultCenter] addObserver:bd->Observer
|
||||
selector:@selector(onApplicationBecomeActive:)
|
||||
name:NSApplicationDidBecomeActiveNotification
|
||||
object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:bd->Observer
|
||||
selector:@selector(onApplicationBecomeInactive:)
|
||||
name:NSApplicationDidResignActiveNotification
|
||||
object:nil];
|
||||
|
||||
// Add the NSTextInputClient to the view hierarchy,
|
||||
// to receive keyboard events and translate them to input text.
|
||||
bd->KeyEventResponder = [[KeyEventResponder alloc] initWithFrame:NSZeroRect];
|
||||
bd->InputContext = [[NSTextInputContext alloc] initWithClient:bd->KeyEventResponder];
|
||||
[view addSubview:bd->KeyEventResponder];
|
||||
ImGui_ImplOSX_AddTrackingArea(view);
|
||||
|
||||
platform_io.Platform_SetImeDataFn = [](ImGuiContext*, ImGuiViewport*, ImGuiPlatformImeData* data) -> void
|
||||
{
|
||||
ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData();
|
||||
if (data->WantVisible)
|
||||
{
|
||||
[bd->InputContext activate];
|
||||
}
|
||||
else
|
||||
{
|
||||
[bd->InputContext discardMarkedText];
|
||||
[bd->InputContext invalidateCharacterCoordinates];
|
||||
[bd->InputContext deactivate];
|
||||
}
|
||||
[bd->KeyEventResponder setImePosX:data->InputPos.x imePosY:data->InputPos.y + data->InputLineHeight];
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplOSX_Shutdown()
|
||||
{
|
||||
g_FocusObserver = NULL;
|
||||
}
|
||||
ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?");
|
||||
|
||||
static void ImGui_ImplOSX_UpdateMouseCursorAndButtons()
|
||||
{
|
||||
// Update buttons
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++)
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:bd->Observer];
|
||||
bd->Observer = nullptr;
|
||||
if (bd->Monitor != nullptr)
|
||||
{
|
||||
// If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
|
||||
io.MouseDown[i] = g_MouseJustPressed[i] || g_MouseDown[i];
|
||||
g_MouseJustPressed[i] = false;
|
||||
[NSEvent removeMonitor:bd->Monitor];
|
||||
bd->Monitor = nullptr;
|
||||
}
|
||||
|
||||
ImGui_ImplOSX_DestroyBackendData();
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
io.BackendPlatformName = nullptr;
|
||||
io.BackendPlatformUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasGamepad);
|
||||
platform_io.ClearPlatformHandlers();
|
||||
}
|
||||
|
||||
static void ImGui_ImplOSX_UpdateMouseCursor()
|
||||
{
|
||||
ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData();
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
|
||||
return;
|
||||
|
||||
@@ -184,88 +536,200 @@ static void ImGui_ImplOSX_UpdateMouseCursorAndButtons()
|
||||
if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None)
|
||||
{
|
||||
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
|
||||
if (!g_MouseCursorHidden)
|
||||
if (!bd->MouseCursorHidden)
|
||||
{
|
||||
g_MouseCursorHidden = true;
|
||||
bd->MouseCursorHidden = true;
|
||||
[NSCursor hide];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Show OS mouse cursor
|
||||
[g_MouseCursors[g_MouseCursors[imgui_cursor] ? imgui_cursor : ImGuiMouseCursor_Arrow] set];
|
||||
if (g_MouseCursorHidden)
|
||||
NSCursor* desired = bd->MouseCursors[imgui_cursor] ?: bd->MouseCursors[ImGuiMouseCursor_Arrow];
|
||||
// -[NSCursor set] generates measurable overhead if called unconditionally.
|
||||
if (desired != NSCursor.currentCursor)
|
||||
{
|
||||
g_MouseCursorHidden = false;
|
||||
[desired set];
|
||||
}
|
||||
if (bd->MouseCursorHidden)
|
||||
{
|
||||
bd->MouseCursorHidden = false;
|
||||
[NSCursor unhide];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ImGui_ImplOSX_UpdateGamepads()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
#if APPLE_HAS_CONTROLLER
|
||||
GCController* controller = GCController.current;
|
||||
#else
|
||||
GCController* controller = GCController.controllers.firstObject;
|
||||
#endif
|
||||
if (controller == nil || controller.extendedGamepad == nil)
|
||||
{
|
||||
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
|
||||
return;
|
||||
}
|
||||
|
||||
GCExtendedGamepad* gp = controller.extendedGamepad;
|
||||
|
||||
// Update gamepad inputs
|
||||
#define IM_SATURATE(V) (V < 0.0f ? 0.0f : V > 1.0f ? 1.0f : V)
|
||||
#define MAP_BUTTON(KEY_NO, BUTTON_NAME) { io.AddKeyEvent(KEY_NO, gp.BUTTON_NAME.isPressed); }
|
||||
#define MAP_ANALOG(KEY_NO, AXIS_NAME, V0, V1) { float vn = (float)(gp.AXIS_NAME.value - V0) / (float)(V1 - V0); vn = IM_SATURATE(vn); io.AddKeyAnalogEvent(KEY_NO, vn > 0.1f, vn); }
|
||||
const float thumb_dead_zone = 0.0f;
|
||||
|
||||
#if APPLE_HAS_BUTTON_OPTIONS
|
||||
MAP_BUTTON(ImGuiKey_GamepadBack, buttonOptions);
|
||||
#endif
|
||||
MAP_BUTTON(ImGuiKey_GamepadFaceLeft, buttonX); // Xbox X, PS Square
|
||||
MAP_BUTTON(ImGuiKey_GamepadFaceRight, buttonB); // Xbox B, PS Circle
|
||||
MAP_BUTTON(ImGuiKey_GamepadFaceUp, buttonY); // Xbox Y, PS Triangle
|
||||
MAP_BUTTON(ImGuiKey_GamepadFaceDown, buttonA); // Xbox A, PS Cross
|
||||
MAP_BUTTON(ImGuiKey_GamepadDpadLeft, dpad.left);
|
||||
MAP_BUTTON(ImGuiKey_GamepadDpadRight, dpad.right);
|
||||
MAP_BUTTON(ImGuiKey_GamepadDpadUp, dpad.up);
|
||||
MAP_BUTTON(ImGuiKey_GamepadDpadDown, dpad.down);
|
||||
MAP_ANALOG(ImGuiKey_GamepadL1, leftShoulder, 0.0f, 1.0f);
|
||||
MAP_ANALOG(ImGuiKey_GamepadR1, rightShoulder, 0.0f, 1.0f);
|
||||
MAP_ANALOG(ImGuiKey_GamepadL2, leftTrigger, 0.0f, 1.0f);
|
||||
MAP_ANALOG(ImGuiKey_GamepadR2, rightTrigger, 0.0f, 1.0f);
|
||||
#if APPLE_HAS_THUMBSTICKS
|
||||
MAP_BUTTON(ImGuiKey_GamepadL3, leftThumbstickButton);
|
||||
MAP_BUTTON(ImGuiKey_GamepadR3, rightThumbstickButton);
|
||||
#endif
|
||||
MAP_ANALOG(ImGuiKey_GamepadLStickLeft, leftThumbstick.xAxis, -thumb_dead_zone, -1.0f);
|
||||
MAP_ANALOG(ImGuiKey_GamepadLStickRight, leftThumbstick.xAxis, +thumb_dead_zone, +1.0f);
|
||||
MAP_ANALOG(ImGuiKey_GamepadLStickUp, leftThumbstick.yAxis, +thumb_dead_zone, +1.0f);
|
||||
MAP_ANALOG(ImGuiKey_GamepadLStickDown, leftThumbstick.yAxis, -thumb_dead_zone, -1.0f);
|
||||
MAP_ANALOG(ImGuiKey_GamepadRStickLeft, rightThumbstick.xAxis, -thumb_dead_zone, -1.0f);
|
||||
MAP_ANALOG(ImGuiKey_GamepadRStickRight, rightThumbstick.xAxis, +thumb_dead_zone, +1.0f);
|
||||
MAP_ANALOG(ImGuiKey_GamepadRStickUp, rightThumbstick.yAxis, +thumb_dead_zone, +1.0f);
|
||||
MAP_ANALOG(ImGuiKey_GamepadRStickDown, rightThumbstick.yAxis, -thumb_dead_zone, -1.0f);
|
||||
#undef MAP_BUTTON
|
||||
#undef MAP_ANALOG
|
||||
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
|
||||
}
|
||||
|
||||
static void ImGui_ImplOSX_UpdateImePosWithView(NSView* view)
|
||||
{
|
||||
ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData();
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (io.WantTextInput)
|
||||
[bd->KeyEventResponder updateImePosWithView:view];
|
||||
}
|
||||
|
||||
void ImGui_ImplOSX_NewFrame(NSView* view)
|
||||
{
|
||||
// Setup display size
|
||||
ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplOSX_Init()?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
// Setup display size
|
||||
if (view)
|
||||
{
|
||||
const float dpi = (float)[view.window backingScaleFactor];
|
||||
const float fb_scale = (float)[view.window backingScaleFactor];
|
||||
io.DisplaySize = ImVec2((float)view.bounds.size.width, (float)view.bounds.size.height);
|
||||
io.DisplayFramebufferScale = ImVec2(dpi, dpi);
|
||||
io.DisplayFramebufferScale = ImVec2(fb_scale, fb_scale);
|
||||
}
|
||||
|
||||
// Setup time step
|
||||
if (g_Time == 0.0)
|
||||
g_Time = CFAbsoluteTimeGetCurrent();
|
||||
CFAbsoluteTime current_time = CFAbsoluteTimeGetCurrent();
|
||||
io.DeltaTime = (float)(current_time - g_Time);
|
||||
g_Time = current_time;
|
||||
if (bd->Time == 0.0)
|
||||
bd->Time = GetMachAbsoluteTimeInSeconds();
|
||||
|
||||
ImGui_ImplOSX_UpdateMouseCursorAndButtons();
|
||||
double current_time = GetMachAbsoluteTimeInSeconds();
|
||||
io.DeltaTime = (float)(current_time - bd->Time);
|
||||
bd->Time = current_time;
|
||||
|
||||
ImGui_ImplOSX_UpdateMouseCursor();
|
||||
ImGui_ImplOSX_UpdateGamepads();
|
||||
ImGui_ImplOSX_UpdateImePosWithView(view);
|
||||
}
|
||||
|
||||
static int mapCharacterToKey(int c)
|
||||
// Must only be called for a mouse event, otherwise an exception occurs
|
||||
// (Note that NSEventTypeScrollWheel is considered "other input". Oddly enough an exception does not occur with it, but the value will sometimes be wrong!)
|
||||
static ImGuiMouseSource GetMouseSource(NSEvent* event)
|
||||
{
|
||||
if (c >= 'a' && c <= 'z')
|
||||
return c - 'a' + 'A';
|
||||
if (c == 25) // SHIFT+TAB -> TAB
|
||||
return 9;
|
||||
if (c >= 0 && c < 256)
|
||||
return c;
|
||||
if (c >= 0xF700 && c < 0xF700 + 256)
|
||||
return c - 0xF700 + 256;
|
||||
return -1;
|
||||
switch (event.subtype)
|
||||
{
|
||||
case NSEventSubtypeTabletPoint:
|
||||
return ImGuiMouseSource_Pen;
|
||||
// macOS considers input from relative touch devices (like the trackpad or Apple Magic Mouse) to be touch input.
|
||||
// This doesn't really make sense for Dear ImGui, which expects absolute touch devices only.
|
||||
// There does not seem to be a simple way to disambiguate things here so we consider NSEventSubtypeTouch events to always come from mice.
|
||||
// See https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/EventOverview/HandlingTouchEvents/HandlingTouchEvents.html#//apple_ref/doc/uid/10000060i-CH13-SW24
|
||||
//case NSEventSubtypeTouch:
|
||||
// return ImGuiMouseSource_TouchScreen;
|
||||
case NSEventSubtypeMouseEvent:
|
||||
default:
|
||||
return ImGuiMouseSource_Mouse;
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view)
|
||||
static bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view)
|
||||
{
|
||||
// Only process events from the window containing ImGui view
|
||||
if (event.window != view.window)
|
||||
return false;
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
if (event.type == NSEventTypeLeftMouseDown || event.type == NSEventTypeRightMouseDown || event.type == NSEventTypeOtherMouseDown)
|
||||
{
|
||||
int button = (int)[event buttonNumber];
|
||||
if (button >= 0 && button < IM_ARRAYSIZE(g_MouseDown))
|
||||
g_MouseDown[button] = g_MouseJustPressed[button] = true;
|
||||
if (button >= 0 && button < ImGuiMouseButton_COUNT)
|
||||
{
|
||||
io.AddMouseSourceEvent(GetMouseSource(event));
|
||||
io.AddMouseButtonEvent(button, true);
|
||||
}
|
||||
return io.WantCaptureMouse;
|
||||
}
|
||||
|
||||
if (event.type == NSEventTypeLeftMouseUp || event.type == NSEventTypeRightMouseUp || event.type == NSEventTypeOtherMouseUp)
|
||||
{
|
||||
int button = (int)[event buttonNumber];
|
||||
if (button >= 0 && button < IM_ARRAYSIZE(g_MouseDown))
|
||||
g_MouseDown[button] = false;
|
||||
if (button >= 0 && button < ImGuiMouseButton_COUNT)
|
||||
{
|
||||
io.AddMouseSourceEvent(GetMouseSource(event));
|
||||
io.AddMouseButtonEvent(button, false);
|
||||
}
|
||||
return io.WantCaptureMouse;
|
||||
}
|
||||
|
||||
if (event.type == NSEventTypeMouseMoved || event.type == NSEventTypeLeftMouseDragged || event.type == NSEventTypeRightMouseDragged || event.type == NSEventTypeOtherMouseDragged)
|
||||
{
|
||||
NSPoint mousePoint = event.locationInWindow;
|
||||
if (event.window == nil)
|
||||
mousePoint = [[view window] convertPointFromScreen:mousePoint];
|
||||
mousePoint = [view convertPoint:mousePoint fromView:nil];
|
||||
mousePoint = NSMakePoint(mousePoint.x, view.bounds.size.height - mousePoint.y);
|
||||
io.MousePos = ImVec2((float)mousePoint.x, (float)mousePoint.y);
|
||||
if ([view isFlipped])
|
||||
mousePoint = NSMakePoint(mousePoint.x, mousePoint.y);
|
||||
else
|
||||
mousePoint = NSMakePoint(mousePoint.x, view.bounds.size.height - mousePoint.y);
|
||||
io.AddMouseSourceEvent(GetMouseSource(event));
|
||||
io.AddMousePosEvent((float)mousePoint.x, (float)mousePoint.y);
|
||||
return io.WantCaptureMouse;
|
||||
}
|
||||
|
||||
if (event.type == NSEventTypeScrollWheel)
|
||||
{
|
||||
// Ignore canceled events.
|
||||
//
|
||||
// From macOS 12.1, scrolling with two fingers and then decelerating
|
||||
// by tapping two fingers results in two events appearing:
|
||||
//
|
||||
// 1. A scroll wheel NSEvent, with a phase == NSEventPhaseMayBegin, when the user taps
|
||||
// two fingers to decelerate or stop the scroll events.
|
||||
//
|
||||
// 2. A scroll wheel NSEvent, with a phase == NSEventPhaseCancelled, when the user releases the
|
||||
// two-finger tap. It is this event that sometimes contains large values for scrollingDeltaX and
|
||||
// scrollingDeltaY. When these are added to the current x and y positions of the scrolling view,
|
||||
// it appears to jump up or down. It can be observed in Preview, various JetBrains IDEs and here.
|
||||
if (event.phase == NSEventPhaseCancelled)
|
||||
return false;
|
||||
|
||||
double wheel_dx = 0.0;
|
||||
double wheel_dy = 0.0;
|
||||
|
||||
@@ -276,77 +740,99 @@ bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view)
|
||||
wheel_dy = [event scrollingDeltaY];
|
||||
if ([event hasPreciseScrollingDeltas])
|
||||
{
|
||||
wheel_dx *= 0.1;
|
||||
wheel_dy *= 0.1;
|
||||
wheel_dx *= 0.01;
|
||||
wheel_dy *= 0.01;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif // MAC_OS_X_VERSION_MAX_ALLOWED
|
||||
{
|
||||
wheel_dx = [event deltaX];
|
||||
wheel_dy = [event deltaY];
|
||||
wheel_dx = [event deltaX] * 0.1;
|
||||
wheel_dy = [event deltaY] * 0.1;
|
||||
}
|
||||
if (wheel_dx != 0.0 || wheel_dy != 0.0)
|
||||
io.AddMouseWheelEvent((float)wheel_dx, (float)wheel_dy);
|
||||
|
||||
if (fabs(wheel_dx) > 0.0)
|
||||
io.MouseWheelH += (float)wheel_dx * 0.1f;
|
||||
if (fabs(wheel_dy) > 0.0)
|
||||
io.MouseWheel += (float)wheel_dy * 0.1f;
|
||||
return io.WantCaptureMouse;
|
||||
}
|
||||
|
||||
// FIXME: All the key handling is wrong and broken. Refer to GLFW's cocoa_init.mm and cocoa_window.mm.
|
||||
if (event.type == NSEventTypeKeyDown)
|
||||
if (event.type == NSEventTypeKeyDown || event.type == NSEventTypeKeyUp)
|
||||
{
|
||||
NSString* str = [event characters];
|
||||
NSUInteger len = [str length];
|
||||
for (NSUInteger i = 0; i < len; i++)
|
||||
{
|
||||
int c = [str characterAtIndex:i];
|
||||
if (!io.KeyCtrl && !(c >= 0xF700 && c <= 0xFFFF) && c != 127)
|
||||
io.AddInputCharacter((unsigned int)c);
|
||||
if ([event isARepeat])
|
||||
return io.WantCaptureKeyboard;
|
||||
|
||||
// We must reset in case we're pressing a sequence of special keys while keeping the command pressed
|
||||
int key = mapCharacterToKey(c);
|
||||
if (key != -1 && key < 256 && !io.KeyCtrl)
|
||||
resetKeys();
|
||||
if (key != -1)
|
||||
io.KeysDown[key] = true;
|
||||
}
|
||||
return io.WantCaptureKeyboard;
|
||||
}
|
||||
int key_code = (int)[event keyCode];
|
||||
ImGuiKey key = ImGui_ImplOSX_KeyCodeToImGuiKey(key_code);
|
||||
io.AddKeyEvent(key, event.type == NSEventTypeKeyDown);
|
||||
io.SetKeyEventNativeData(key, key_code, -1); // To support legacy indexing (<1.87 user code)
|
||||
|
||||
if (event.type == NSEventTypeKeyUp)
|
||||
{
|
||||
NSString* str = [event characters];
|
||||
NSUInteger len = [str length];
|
||||
for (NSUInteger i = 0; i < len; i++)
|
||||
{
|
||||
int c = [str characterAtIndex:i];
|
||||
int key = mapCharacterToKey(c);
|
||||
if (key != -1)
|
||||
io.KeysDown[key] = false;
|
||||
}
|
||||
return io.WantCaptureKeyboard;
|
||||
}
|
||||
|
||||
if (event.type == NSEventTypeFlagsChanged)
|
||||
{
|
||||
unsigned int flags = [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
|
||||
unsigned short key_code = [event keyCode];
|
||||
NSEventModifierFlags modifier_flags = [event modifierFlags];
|
||||
|
||||
bool oldKeyCtrl = io.KeyCtrl;
|
||||
bool oldKeyShift = io.KeyShift;
|
||||
bool oldKeyAlt = io.KeyAlt;
|
||||
bool oldKeySuper = io.KeySuper;
|
||||
io.KeyCtrl = flags & NSEventModifierFlagControl;
|
||||
io.KeyShift = flags & NSEventModifierFlagShift;
|
||||
io.KeyAlt = flags & NSEventModifierFlagOption;
|
||||
io.KeySuper = flags & NSEventModifierFlagCommand;
|
||||
io.AddKeyEvent(ImGuiMod_Shift, (modifier_flags & NSEventModifierFlagShift) != 0);
|
||||
io.AddKeyEvent(ImGuiMod_Ctrl, (modifier_flags & NSEventModifierFlagControl) != 0);
|
||||
io.AddKeyEvent(ImGuiMod_Alt, (modifier_flags & NSEventModifierFlagOption) != 0);
|
||||
io.AddKeyEvent(ImGuiMod_Super, (modifier_flags & NSEventModifierFlagCommand) != 0);
|
||||
|
||||
ImGuiKey key = ImGui_ImplOSX_KeyCodeToImGuiKey(key_code);
|
||||
if (key != ImGuiKey_None)
|
||||
{
|
||||
// macOS does not generate down/up event for modifiers. We're trying
|
||||
// to use hardware dependent masks to extract that information.
|
||||
// 'imgui_mask' is left as a fallback.
|
||||
NSEventModifierFlags mask = 0;
|
||||
switch (key)
|
||||
{
|
||||
case ImGuiKey_LeftCtrl: mask = 0x0001; break;
|
||||
case ImGuiKey_RightCtrl: mask = 0x2000; break;
|
||||
case ImGuiKey_LeftShift: mask = 0x0002; break;
|
||||
case ImGuiKey_RightShift: mask = 0x0004; break;
|
||||
case ImGuiKey_LeftSuper: mask = 0x0008; break;
|
||||
case ImGuiKey_RightSuper: mask = 0x0010; break;
|
||||
case ImGuiKey_LeftAlt: mask = 0x0020; break;
|
||||
case ImGuiKey_RightAlt: mask = 0x0040; break;
|
||||
default:
|
||||
return io.WantCaptureKeyboard;
|
||||
}
|
||||
io.AddKeyEvent(key, (modifier_flags & mask) != 0);
|
||||
io.SetKeyEventNativeData(key, key_code, -1); // To support legacy indexing (<1.87 user code)
|
||||
}
|
||||
|
||||
// We must reset them as we will not receive any keyUp event if they where pressed with a modifier
|
||||
if ((oldKeyShift && !io.KeyShift) || (oldKeyCtrl && !io.KeyCtrl) || (oldKeyAlt && !io.KeyAlt) || (oldKeySuper && !io.KeySuper))
|
||||
resetKeys();
|
||||
return io.WantCaptureKeyboard;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void ImGui_ImplOSX_AddTrackingArea(NSView* _Nonnull view)
|
||||
{
|
||||
// If we want to receive key events, we either need to be in the responder chain of the key view,
|
||||
// or else we can install a local monitor. The consequence of this heavy-handed approach is that
|
||||
// we receive events for all controls, not just Dear ImGui widgets. If we had native controls in our
|
||||
// window, we'd want to be much more careful than just ingesting the complete event stream.
|
||||
// To match the behavior of other backends, we pass every event down to the OS.
|
||||
ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData();
|
||||
if (bd->Monitor)
|
||||
return;
|
||||
NSEventMask eventMask = 0;
|
||||
eventMask |= NSEventMaskMouseMoved | NSEventMaskScrollWheel;
|
||||
eventMask |= NSEventMaskLeftMouseDown | NSEventMaskLeftMouseUp | NSEventMaskLeftMouseDragged;
|
||||
eventMask |= NSEventMaskRightMouseDown | NSEventMaskRightMouseUp | NSEventMaskRightMouseDragged;
|
||||
eventMask |= NSEventMaskOtherMouseDown | NSEventMaskOtherMouseUp | NSEventMaskOtherMouseDragged;
|
||||
eventMask |= NSEventMaskKeyDown | NSEventMaskKeyUp | NSEventMaskFlagsChanged;
|
||||
bd->Monitor = [NSEvent addLocalMonitorForEventsMatchingMask:eventMask
|
||||
handler:^NSEvent* _Nullable(NSEvent* event)
|
||||
{
|
||||
ImGui_ImplOSX_HandleEvent(event, view);
|
||||
return event;
|
||||
}];
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
@@ -1,377 +0,0 @@
|
||||
// dear imgui: Platform Backend for SDL2
|
||||
// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
|
||||
// (Info: SDL2 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.)
|
||||
// (Requires: SDL 2.0. Prefer SDL 2.0.4+ for full feature support.)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
// [X] Platform: Clipboard support.
|
||||
// [X] Platform: Keyboard arrays indexed using SDL_SCANCODE_* codes, e.g. ImGui::IsKeyPressed(SDL_SCANCODE_SPACE).
|
||||
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
||||
// Missing features:
|
||||
// [ ] Platform: SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2021-03-22: Rework global mouse pos availability check listing supported platforms explicitly, effectively fixing mouse access on Raspberry Pi. (#2837, #3950)
|
||||
// 2020-05-25: Misc: Report a zero display-size when window is minimized, to be consistent with other backends.
|
||||
// 2020-02-20: Inputs: Fixed mapping for ImGuiKey_KeyPadEnter (using SDL_SCANCODE_KP_ENTER instead of SDL_SCANCODE_RETURN2).
|
||||
// 2019-12-17: Inputs: On Wayland, use SDL_GetMouseState (because there is no global mouse state).
|
||||
// 2019-12-05: Inputs: Added support for ImGuiMouseCursor_NotAllowed mouse cursor.
|
||||
// 2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter.
|
||||
// 2019-04-23: Inputs: Added support for SDL_GameController (if ImGuiConfigFlags_NavEnableGamepad is set by user application).
|
||||
// 2019-03-12: Misc: Preserve DisplayFramebufferScale when main window is minimized.
|
||||
// 2018-12-21: Inputs: Workaround for Android/iOS which don't seem to handle focus related calls.
|
||||
// 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window.
|
||||
// 2018-11-14: Changed the signature of ImGui_ImplSDL2_ProcessEvent() to take a 'const SDL_Event*'.
|
||||
// 2018-08-01: Inputs: Workaround for Emscripten which doesn't seem to handle focus related calls.
|
||||
// 2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor.
|
||||
// 2018-06-08: Misc: Extracted imgui_impl_sdl.cpp/.h away from the old combined SDL2+OpenGL/Vulkan examples.
|
||||
// 2018-06-08: Misc: ImGui_ImplSDL2_InitForOpenGL() now takes a SDL_GLContext parameter.
|
||||
// 2018-05-09: Misc: Fixed clipboard paste memory leak (we didn't call SDL_FreeMemory on the data returned by SDL_GetClipboardText).
|
||||
// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoMouseCursorChange flag.
|
||||
// 2018-02-16: Inputs: Added support for mouse cursors, honoring ImGui::GetMouseCursor() value.
|
||||
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
|
||||
// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space.
|
||||
// 2018-02-05: Misc: Using SDL_GetPerformanceCounter() instead of SDL_GetTicks() to be able to handle very high framerate (1000+ FPS).
|
||||
// 2018-02-05: Inputs: Keyboard mapping is using scancodes everywhere instead of a confusing mixture of keycodes and scancodes.
|
||||
// 2018-01-20: Inputs: Added Horizontal Mouse Wheel support.
|
||||
// 2018-01-19: Inputs: When available (SDL 2.0.4+) using SDL_CaptureMouse() to retrieve coordinates outside of client area when dragging. Otherwise (SDL 2.0.3 and before) testing for SDL_WINDOW_INPUT_FOCUS instead of SDL_WINDOW_MOUSE_FOCUS.
|
||||
// 2018-01-18: Inputs: Added mapping for ImGuiKey_Insert.
|
||||
// 2017-08-25: Inputs: MousePos set to -FLT_MAX,-FLT_MAX when mouse is unavailable/missing (instead of -1,-1).
|
||||
// 2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers.
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_sdl.h"
|
||||
|
||||
// SDL
|
||||
#include <SDL.h>
|
||||
#include <SDL_syswm.h>
|
||||
#if defined(__APPLE__)
|
||||
#include "TargetConditionals.h"
|
||||
#endif
|
||||
|
||||
#define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE SDL_VERSION_ATLEAST(2,0,4)
|
||||
#define SDL_HAS_VULKAN SDL_VERSION_ATLEAST(2,0,6)
|
||||
|
||||
// Data
|
||||
static SDL_Window* g_Window = NULL;
|
||||
static Uint64 g_Time = 0;
|
||||
static bool g_MousePressed[3] = { false, false, false };
|
||||
static SDL_Cursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = {};
|
||||
static char* g_ClipboardTextData = NULL;
|
||||
static bool g_MouseCanUseGlobalState = true;
|
||||
|
||||
static const char* ImGui_ImplSDL2_GetClipboardText(void*)
|
||||
{
|
||||
if (g_ClipboardTextData)
|
||||
SDL_free(g_ClipboardTextData);
|
||||
g_ClipboardTextData = SDL_GetClipboardText();
|
||||
return g_ClipboardTextData;
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDL2_SetClipboardText(void*, const char* text)
|
||||
{
|
||||
SDL_SetClipboardText(text);
|
||||
}
|
||||
|
||||
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
|
||||
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||
// If you have multiple SDL events and some of them are not meant to be used by dear imgui, you may need to filter events based on their windowID field.
|
||||
bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
switch (event->type)
|
||||
{
|
||||
case SDL_MOUSEWHEEL:
|
||||
{
|
||||
if (event->wheel.x > 0) io.MouseWheelH += 1;
|
||||
if (event->wheel.x < 0) io.MouseWheelH -= 1;
|
||||
if (event->wheel.y > 0) io.MouseWheel += 1;
|
||||
if (event->wheel.y < 0) io.MouseWheel -= 1;
|
||||
return true;
|
||||
}
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
{
|
||||
if (event->button.button == SDL_BUTTON_LEFT) g_MousePressed[0] = true;
|
||||
if (event->button.button == SDL_BUTTON_RIGHT) g_MousePressed[1] = true;
|
||||
if (event->button.button == SDL_BUTTON_MIDDLE) g_MousePressed[2] = true;
|
||||
return true;
|
||||
}
|
||||
case SDL_TEXTINPUT:
|
||||
{
|
||||
io.AddInputCharactersUTF8(event->text.text);
|
||||
return true;
|
||||
}
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP:
|
||||
{
|
||||
int key = event->key.keysym.scancode;
|
||||
IM_ASSERT(key >= 0 && key < IM_ARRAYSIZE(io.KeysDown));
|
||||
io.KeysDown[key] = (event->type == SDL_KEYDOWN);
|
||||
io.KeyShift = ((SDL_GetModState() & KMOD_SHIFT) != 0);
|
||||
io.KeyCtrl = ((SDL_GetModState() & KMOD_CTRL) != 0);
|
||||
io.KeyAlt = ((SDL_GetModState() & KMOD_ALT) != 0);
|
||||
#ifdef _WIN32
|
||||
io.KeySuper = false;
|
||||
#else
|
||||
io.KeySuper = ((SDL_GetModState() & KMOD_GUI) != 0);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool ImGui_ImplSDL2_Init(SDL_Window* window)
|
||||
{
|
||||
g_Window = window;
|
||||
|
||||
// Setup backend capabilities flags
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
|
||||
io.BackendPlatformName = "imgui_impl_sdl";
|
||||
|
||||
// Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array.
|
||||
io.KeyMap[ImGuiKey_Tab] = SDL_SCANCODE_TAB;
|
||||
io.KeyMap[ImGuiKey_LeftArrow] = SDL_SCANCODE_LEFT;
|
||||
io.KeyMap[ImGuiKey_RightArrow] = SDL_SCANCODE_RIGHT;
|
||||
io.KeyMap[ImGuiKey_UpArrow] = SDL_SCANCODE_UP;
|
||||
io.KeyMap[ImGuiKey_DownArrow] = SDL_SCANCODE_DOWN;
|
||||
io.KeyMap[ImGuiKey_PageUp] = SDL_SCANCODE_PAGEUP;
|
||||
io.KeyMap[ImGuiKey_PageDown] = SDL_SCANCODE_PAGEDOWN;
|
||||
io.KeyMap[ImGuiKey_Home] = SDL_SCANCODE_HOME;
|
||||
io.KeyMap[ImGuiKey_End] = SDL_SCANCODE_END;
|
||||
io.KeyMap[ImGuiKey_Insert] = SDL_SCANCODE_INSERT;
|
||||
io.KeyMap[ImGuiKey_Delete] = SDL_SCANCODE_DELETE;
|
||||
io.KeyMap[ImGuiKey_Backspace] = SDL_SCANCODE_BACKSPACE;
|
||||
io.KeyMap[ImGuiKey_Space] = SDL_SCANCODE_SPACE;
|
||||
io.KeyMap[ImGuiKey_Enter] = SDL_SCANCODE_RETURN;
|
||||
io.KeyMap[ImGuiKey_Escape] = SDL_SCANCODE_ESCAPE;
|
||||
io.KeyMap[ImGuiKey_KeyPadEnter] = SDL_SCANCODE_KP_ENTER;
|
||||
io.KeyMap[ImGuiKey_A] = SDL_SCANCODE_A;
|
||||
io.KeyMap[ImGuiKey_C] = SDL_SCANCODE_C;
|
||||
io.KeyMap[ImGuiKey_V] = SDL_SCANCODE_V;
|
||||
io.KeyMap[ImGuiKey_X] = SDL_SCANCODE_X;
|
||||
io.KeyMap[ImGuiKey_Y] = SDL_SCANCODE_Y;
|
||||
io.KeyMap[ImGuiKey_Z] = SDL_SCANCODE_Z;
|
||||
|
||||
io.SetClipboardTextFn = ImGui_ImplSDL2_SetClipboardText;
|
||||
io.GetClipboardTextFn = ImGui_ImplSDL2_GetClipboardText;
|
||||
io.ClipboardUserData = NULL;
|
||||
|
||||
// Load mouse cursors
|
||||
g_MouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
|
||||
g_MouseCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM);
|
||||
g_MouseCursors[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL);
|
||||
g_MouseCursors[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS);
|
||||
g_MouseCursors[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE);
|
||||
g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW);
|
||||
g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE);
|
||||
g_MouseCursors[ImGuiMouseCursor_Hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND);
|
||||
g_MouseCursors[ImGuiMouseCursor_NotAllowed] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO);
|
||||
|
||||
// Check and store if we are on a SDL backend that supports global mouse position
|
||||
// ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list)
|
||||
const char* sdl_backend = SDL_GetCurrentVideoDriver();
|
||||
const char* global_mouse_whitelist[] = { "windows", "cocoa", "x11", "DIVE", "VMAN" };
|
||||
g_MouseCanUseGlobalState = false;
|
||||
for (int n = 0; n < IM_ARRAYSIZE(global_mouse_whitelist); n++)
|
||||
if (strncmp(sdl_backend, global_mouse_whitelist[n], strlen(global_mouse_whitelist[n])) == 0)
|
||||
g_MouseCanUseGlobalState = true;
|
||||
|
||||
#ifdef _WIN32
|
||||
SDL_SysWMinfo wmInfo;
|
||||
SDL_VERSION(&wmInfo.version);
|
||||
SDL_GetWindowWMInfo(window, &wmInfo);
|
||||
io.ImeWindowHandle = wmInfo.info.win.window;
|
||||
#else
|
||||
(void)window;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context)
|
||||
{
|
||||
(void)sdl_gl_context; // Viewport branch will need this.
|
||||
return ImGui_ImplSDL2_Init(window);
|
||||
}
|
||||
|
||||
bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window)
|
||||
{
|
||||
#if !SDL_HAS_VULKAN
|
||||
IM_ASSERT(0 && "Unsupported");
|
||||
#endif
|
||||
return ImGui_ImplSDL2_Init(window);
|
||||
}
|
||||
|
||||
bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window)
|
||||
{
|
||||
#if !defined(_WIN32)
|
||||
IM_ASSERT(0 && "Unsupported");
|
||||
#endif
|
||||
return ImGui_ImplSDL2_Init(window);
|
||||
}
|
||||
|
||||
bool ImGui_ImplSDL2_InitForMetal(SDL_Window* window)
|
||||
{
|
||||
return ImGui_ImplSDL2_Init(window);
|
||||
}
|
||||
|
||||
void ImGui_ImplSDL2_Shutdown()
|
||||
{
|
||||
g_Window = NULL;
|
||||
|
||||
// Destroy last known clipboard data
|
||||
if (g_ClipboardTextData)
|
||||
SDL_free(g_ClipboardTextData);
|
||||
g_ClipboardTextData = NULL;
|
||||
|
||||
// Destroy SDL mouse cursors
|
||||
for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
|
||||
SDL_FreeCursor(g_MouseCursors[cursor_n]);
|
||||
memset(g_MouseCursors, 0, sizeof(g_MouseCursors));
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDL2_UpdateMousePosAndButtons()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
// Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
|
||||
if (io.WantSetMousePos)
|
||||
SDL_WarpMouseInWindow(g_Window, (int)io.MousePos.x, (int)io.MousePos.y);
|
||||
else
|
||||
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
|
||||
|
||||
int mx, my;
|
||||
Uint32 mouse_buttons = SDL_GetMouseState(&mx, &my);
|
||||
io.MouseDown[0] = g_MousePressed[0] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
|
||||
io.MouseDown[1] = g_MousePressed[1] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0;
|
||||
io.MouseDown[2] = g_MousePressed[2] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0;
|
||||
g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false;
|
||||
|
||||
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IOS)
|
||||
SDL_Window* focused_window = SDL_GetKeyboardFocus();
|
||||
if (g_Window == focused_window)
|
||||
{
|
||||
if (g_MouseCanUseGlobalState)
|
||||
{
|
||||
// SDL_GetMouseState() gives mouse position seemingly based on the last window entered/focused(?)
|
||||
// The creation of a new windows at runtime and SDL_CaptureMouse both seems to severely mess up with that, so we retrieve that position globally.
|
||||
// Won't use this workaround on SDL backends that have no global mouse position, like Wayland or RPI
|
||||
int wx, wy;
|
||||
SDL_GetWindowPosition(focused_window, &wx, &wy);
|
||||
SDL_GetGlobalMouseState(&mx, &my);
|
||||
mx -= wx;
|
||||
my -= wy;
|
||||
}
|
||||
io.MousePos = ImVec2((float)mx, (float)my);
|
||||
}
|
||||
|
||||
// SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger the OS window resize cursor.
|
||||
// The function is only supported from SDL 2.0.4 (released Jan 2016)
|
||||
bool any_mouse_button_down = ImGui::IsAnyMouseDown();
|
||||
SDL_CaptureMouse(any_mouse_button_down ? SDL_TRUE : SDL_FALSE);
|
||||
#else
|
||||
if (SDL_GetWindowFlags(g_Window) & SDL_WINDOW_INPUT_FOCUS)
|
||||
io.MousePos = ImVec2((float)mx, (float)my);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDL2_UpdateMouseCursor()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
|
||||
return;
|
||||
|
||||
ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
|
||||
if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None)
|
||||
{
|
||||
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
|
||||
SDL_ShowCursor(SDL_FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Show OS mouse cursor
|
||||
SDL_SetCursor(g_MouseCursors[imgui_cursor] ? g_MouseCursors[imgui_cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]);
|
||||
SDL_ShowCursor(SDL_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDL2_UpdateGamepads()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
memset(io.NavInputs, 0, sizeof(io.NavInputs));
|
||||
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0)
|
||||
return;
|
||||
|
||||
// Get gamepad
|
||||
SDL_GameController* game_controller = SDL_GameControllerOpen(0);
|
||||
if (!game_controller)
|
||||
{
|
||||
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
|
||||
return;
|
||||
}
|
||||
|
||||
// Update gamepad inputs
|
||||
#define MAP_BUTTON(NAV_NO, BUTTON_NO) { io.NavInputs[NAV_NO] = (SDL_GameControllerGetButton(game_controller, BUTTON_NO) != 0) ? 1.0f : 0.0f; }
|
||||
#define MAP_ANALOG(NAV_NO, AXIS_NO, V0, V1) { float vn = (float)(SDL_GameControllerGetAxis(game_controller, AXIS_NO) - V0) / (float)(V1 - V0); if (vn > 1.0f) vn = 1.0f; if (vn > 0.0f && io.NavInputs[NAV_NO] < vn) io.NavInputs[NAV_NO] = vn; }
|
||||
const int thumb_dead_zone = 8000; // SDL_gamecontroller.h suggests using this value.
|
||||
MAP_BUTTON(ImGuiNavInput_Activate, SDL_CONTROLLER_BUTTON_A); // Cross / A
|
||||
MAP_BUTTON(ImGuiNavInput_Cancel, SDL_CONTROLLER_BUTTON_B); // Circle / B
|
||||
MAP_BUTTON(ImGuiNavInput_Menu, SDL_CONTROLLER_BUTTON_X); // Square / X
|
||||
MAP_BUTTON(ImGuiNavInput_Input, SDL_CONTROLLER_BUTTON_Y); // Triangle / Y
|
||||
MAP_BUTTON(ImGuiNavInput_DpadLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT); // D-Pad Left
|
||||
MAP_BUTTON(ImGuiNavInput_DpadRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT); // D-Pad Right
|
||||
MAP_BUTTON(ImGuiNavInput_DpadUp, SDL_CONTROLLER_BUTTON_DPAD_UP); // D-Pad Up
|
||||
MAP_BUTTON(ImGuiNavInput_DpadDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN); // D-Pad Down
|
||||
MAP_BUTTON(ImGuiNavInput_FocusPrev, SDL_CONTROLLER_BUTTON_LEFTSHOULDER); // L1 / LB
|
||||
MAP_BUTTON(ImGuiNavInput_FocusNext, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); // R1 / RB
|
||||
MAP_BUTTON(ImGuiNavInput_TweakSlow, SDL_CONTROLLER_BUTTON_LEFTSHOULDER); // L1 / LB
|
||||
MAP_BUTTON(ImGuiNavInput_TweakFast, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); // R1 / RB
|
||||
MAP_ANALOG(ImGuiNavInput_LStickLeft, SDL_CONTROLLER_AXIS_LEFTX, -thumb_dead_zone, -32768);
|
||||
MAP_ANALOG(ImGuiNavInput_LStickRight, SDL_CONTROLLER_AXIS_LEFTX, +thumb_dead_zone, +32767);
|
||||
MAP_ANALOG(ImGuiNavInput_LStickUp, SDL_CONTROLLER_AXIS_LEFTY, -thumb_dead_zone, -32767);
|
||||
MAP_ANALOG(ImGuiNavInput_LStickDown, SDL_CONTROLLER_AXIS_LEFTY, +thumb_dead_zone, +32767);
|
||||
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
|
||||
#undef MAP_BUTTON
|
||||
#undef MAP_ANALOG
|
||||
}
|
||||
|
||||
void ImGui_ImplSDL2_NewFrame(SDL_Window* window)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IM_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built! It is generally built by the renderer backend. Missing call to renderer _NewFrame() function? e.g. ImGui_ImplOpenGL3_NewFrame().");
|
||||
|
||||
// Setup display size (every frame to accommodate for window resizing)
|
||||
int w, h;
|
||||
int display_w, display_h;
|
||||
SDL_GetWindowSize(window, &w, &h);
|
||||
if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED)
|
||||
w = h = 0;
|
||||
SDL_GL_GetDrawableSize(window, &display_w, &display_h);
|
||||
io.DisplaySize = ImVec2((float)w, (float)h);
|
||||
if (w > 0 && h > 0)
|
||||
io.DisplayFramebufferScale = ImVec2((float)display_w / w, (float)display_h / h);
|
||||
|
||||
// Setup time step (we don't use SDL_GetTicks() because it is using millisecond resolution)
|
||||
static Uint64 frequency = SDL_GetPerformanceFrequency();
|
||||
Uint64 current_time = SDL_GetPerformanceCounter();
|
||||
io.DeltaTime = g_Time > 0 ? (float)((double)(current_time - g_Time) / frequency) : (float)(1.0f / 60.0f);
|
||||
g_Time = current_time;
|
||||
|
||||
ImGui_ImplSDL2_UpdateMousePosAndButtons();
|
||||
ImGui_ImplSDL2_UpdateMouseCursor();
|
||||
|
||||
// Update game controllers (if enabled and available)
|
||||
ImGui_ImplSDL2_UpdateGamepads();
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
// dear imgui: Platform Backend for SDL2
|
||||
// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
|
||||
// (Info: SDL2 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
// [X] Platform: Clipboard support.
|
||||
// [X] Platform: Keyboard arrays indexed using SDL_SCANCODE_* codes, e.g. ImGui::IsKeyPressed(SDL_SCANCODE_SPACE).
|
||||
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
||||
// Missing features:
|
||||
// [ ] Platform: SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
|
||||
#pragma once
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
|
||||
struct SDL_Window;
|
||||
typedef union SDL_Event SDL_Event;
|
||||
|
||||
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context);
|
||||
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window);
|
||||
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window);
|
||||
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForMetal(SDL_Window* window);
|
||||
IMGUI_IMPL_API void ImGui_ImplSDL2_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplSDL2_NewFrame(SDL_Window* window);
|
||||
IMGUI_IMPL_API bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event);
|
||||
934
backends/imgui_impl_sdl2.cpp
Normal file
934
backends/imgui_impl_sdl2.cpp
Normal file
@@ -0,0 +1,934 @@
|
||||
// dear imgui: Platform Backend for SDL2
|
||||
// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
|
||||
// (Info: SDL2 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.)
|
||||
// (Prefer SDL 2.0.5+ for full feature support.)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Platform: Clipboard support.
|
||||
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen.
|
||||
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values are obsolete since 1.87 and not supported since 1.91.5]
|
||||
// [X] Platform: Gamepad support.
|
||||
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
// [X] Platform: Basic IME support. App needs to call 'SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");' before SDL_CreateWindow()!.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-04-16: Made ImGui_ImplSDL2_GetContentScaleForWindow(), ImGui_ImplSDL2_GetContentScaleForDisplay() helpers return a minimum of 1.0f, as some Linux setup seems to report <1.0f value and this breaks scaling border size. (#9369)
|
||||
// 2026-02-13: Inputs: systems other than X11 are back to starting mouse capture on mouse down (reverts 2025-02-26 change). Only X11 requires waiting for a drag by default (not ideal, but a better default for X11 users). Added ImGui_ImplSDL2_SetMouseCaptureMode() for X11 debugger users. (#3650, #6410, #9235)
|
||||
// 2026-01-15: Changed GetClipboardText() handler to return nullptr on error aka clipboard contents is not text. Consistent with other backends. (#9168)
|
||||
// 2025-09-24: Skip using the SDL_GetGlobalMouseState() state when one of our window is hovered, as the SDL_MOUSEMOTION data is reliable. Fix macOS notch mouse coordinates issue in fullscreen mode + better perf on X11. (#7919, #7786)
|
||||
// 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown.
|
||||
// 2025-09-15: Content Scales are always reported as 1.0 on Wayland. (#8921)
|
||||
// 2025-07-08: Made ImGui_ImplSDL2_GetContentScaleForWindow(), ImGui_ImplSDL2_GetContentScaleForDisplay() helpers return 1.0f on Emscripten and Android platforms, matching macOS logic. (#8742, #8733)
|
||||
// 2025-06-11: Added ImGui_ImplSDL2_GetContentScaleForWindow(SDL_Window* window) and ImGui_ImplSDL2_GetContentScaleForDisplay(int display_index) helper to facilitate making DPI-aware apps.
|
||||
// 2025-04-09: Don't attempt to call SDL_CaptureMouse() on drivers where we don't call SDL_GetGlobalMouseState(). (#8561)
|
||||
// 2025-03-21: Fill gamepad inputs and set ImGuiBackendFlags_HasGamepad regardless of ImGuiConfigFlags_NavEnableGamepad being set.
|
||||
// 2025-03-10: When dealing with OEM keys, use scancodes instead of translated keycodes to choose ImGuiKey values. (#7136, #7201, #7206, #7306, #7670, #7672, #8468)
|
||||
// 2025-02-26: Only start SDL_CaptureMouse() when mouse is being dragged, to mitigate issues with e.g. Linux debuggers not claiming capture back. (#6410, #3650)
|
||||
// 2025-02-24: Avoid calling SDL_GetGlobalMouseState() when mouse is in relative mode.
|
||||
// 2025-02-18: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support.
|
||||
// 2025-02-10: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn handler.
|
||||
// 2025-01-20: Made ImGui_ImplSDL2_SetGamepadMode(ImGui_ImplSDL2_GamepadMode_Manual) accept an empty array.
|
||||
// 2024-10-24: Emscripten: from SDL 2.30.9, SDL_EVENT_MOUSE_WHEEL event doesn't require dividing by 100.0f.
|
||||
// 2024-09-09: use SDL_Vulkan_GetDrawableSize() when available. (#7967, #3190)
|
||||
// 2024-08-22: moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO:
|
||||
// - io.GetClipboardTextFn -> platform_io.Platform_GetClipboardTextFn
|
||||
// - io.SetClipboardTextFn -> platform_io.Platform_SetClipboardTextFn
|
||||
// - io.PlatformOpenInShellFn -> platform_io.Platform_OpenInShellFn
|
||||
// - io.PlatformSetImeDataFn -> platform_io.Platform_SetImeDataFn
|
||||
// 2024-08-19: Storing SDL's Uint32 WindowID inside ImGuiViewport::PlatformHandle instead of SDL_Window*.
|
||||
// 2024-08-19: ImGui_ImplSDL2_ProcessEvent() now ignores events intended for other SDL windows. (#7853)
|
||||
// 2024-07-02: Emscripten: Added io.PlatformOpenInShellFn() handler for Emscripten versions.
|
||||
// 2024-07-02: Update for io.SetPlatformImeDataFn() -> io.PlatformSetImeDataFn() renaming in main library.
|
||||
// 2024-02-14: Inputs: Handle gamepad disconnection. Added ImGui_ImplSDL2_SetGamepadMode().
|
||||
// 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys, app back/forward keys.
|
||||
// 2023-04-06: Inputs: Avoid calling SDL_StartTextInput()/SDL_StopTextInput() as they don't only pertain to IME. It's unclear exactly what their relation is to IME. (#6306)
|
||||
// 2023-04-04: Inputs: Added support for io.AddMouseSourceEvent() to discriminate ImGuiMouseSource_Mouse/ImGuiMouseSource_TouchScreen. (#2702)
|
||||
// 2023-02-23: Accept SDL_GetPerformanceCounter() not returning a monotonically increasing value. (#6189, #6114, #3644)
|
||||
// 2023-02-07: Implement IME handler (io.SetPlatformImeDataFn will call SDL_SetTextInputRect()/SDL_StartTextInput()).
|
||||
// 2023-02-07: *BREAKING CHANGE* Renamed this backend file from imgui_impl_sdl.cpp/.h to imgui_impl_sdl2.cpp/.h in prevision for the future release of SDL3.
|
||||
// 2023-02-02: Avoid calling SDL_SetCursor() when cursor has not changed, as the function is surprisingly costly on Mac with latest SDL (may be fixed in next SDL version).
|
||||
// 2023-02-02: Added support for SDL 2.0.18+ preciseX/preciseY mouse wheel data for smooth scrolling + Scaling X value on Emscripten (bug?). (#4019, #6096)
|
||||
// 2023-02-02: Removed SDL_MOUSEWHEEL value clamping, as values seem correct in latest Emscripten. (#4019)
|
||||
// 2023-02-01: Flipping SDL_MOUSEWHEEL 'wheel.x' value to match other backends and offer consistent horizontal scrolling direction. (#4019, #6096, #1463)
|
||||
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
|
||||
// 2022-09-26: Inputs: Disable SDL 2.0.22 new "auto capture" (SDL_HINT_MOUSE_AUTO_CAPTURE) which prevents drag and drop across windows for multi-viewport support + don't capture when drag and dropping. (#5710)
|
||||
// 2022-09-26: Inputs: Renamed ImGuiKey_ModXXX introduced in 1.87 to ImGuiMod_XXX (old names still supported).
|
||||
// 2022-03-22: Inputs: Fix mouse position issues when dragging outside of boundaries. SDL_CaptureMouse() erroneously still gives out LEAVE events when hovering OS decorations.
|
||||
// 2022-03-22: Inputs: Added support for extra mouse buttons (SDL_BUTTON_X1/SDL_BUTTON_X2).
|
||||
// 2022-02-04: Added SDL_Renderer* parameter to ImGui_ImplSDL2_InitForSDLRenderer(), so we can use SDL_GetRendererOutputSize() instead of SDL_GL_GetDrawableSize() when bound to a SDL_Renderer.
|
||||
// 2022-01-26: Inputs: replaced short-lived io.AddKeyModsEvent() (added two weeks ago) with io.AddKeyEvent() using ImGuiKey_ModXXX flags. Sorry for the confusion.
|
||||
// 2021-01-20: Inputs: calling new io.AddKeyAnalogEvent() for gamepad support, instead of writing directly to io.NavInputs[].
|
||||
// 2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEvent(), io.AddMouseWheelEvent() API (1.87+).
|
||||
// 2022-01-17: Inputs: always update key mods next and before key event (not in NewFrame) to fix input queue with very low framerates.
|
||||
// 2022-01-12: Update mouse inputs using SDL_MOUSEMOTION/SDL_WINDOWEVENT_LEAVE + fallback to provide it when focused but not hovered/captured. More standard and will allow us to pass it to future input queue API.
|
||||
// 2022-01-12: Maintain our own copy of MouseButtonsDown mask instead of using ImGui::IsAnyMouseDown() which will be obsoleted.
|
||||
// 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range.
|
||||
// 2021-08-17: Calling io.AddFocusEvent() on SDL_WINDOWEVENT_FOCUS_GAINED/SDL_WINDOWEVENT_FOCUS_LOST.
|
||||
// 2021-07-29: Inputs: MousePos is correctly reported when the host platform window is hovered but not focused (using SDL_GetMouseFocus() + SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, requires SDL 2.0.5+)
|
||||
// 2021-06-29: *BREAKING CHANGE* Removed 'SDL_Window* window' parameter to ImGui_ImplSDL2_NewFrame() which was unnecessary.
|
||||
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
|
||||
// 2021-03-22: Rework global mouse pos availability check listing supported platforms explicitly, effectively fixing mouse access on Raspberry Pi. (#2837, #3950)
|
||||
// 2020-05-25: Misc: Report a zero display-size when window is minimized, to be consistent with other backends.
|
||||
// 2020-02-20: Inputs: Fixed mapping for ImGuiKey_KeyPadEnter (using SDL_SCANCODE_KP_ENTER instead of SDL_SCANCODE_RETURN2).
|
||||
// 2019-12-17: Inputs: On Wayland, use SDL_GetMouseState (because there is no global mouse state).
|
||||
// 2019-12-05: Inputs: Added support for ImGuiMouseCursor_NotAllowed mouse cursor.
|
||||
// 2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter.
|
||||
// 2019-04-23: Inputs: Added support for SDL_GameController (if ImGuiConfigFlags_NavEnableGamepad is set by user application).
|
||||
// 2019-03-12: Misc: Preserve DisplayFramebufferScale when main window is minimized.
|
||||
// 2018-12-21: Inputs: Workaround for Android/iOS which don't seem to handle focus related calls.
|
||||
// 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window.
|
||||
// 2018-11-14: Changed the signature of ImGui_ImplSDL2_ProcessEvent() to take a 'const SDL_Event*'.
|
||||
// 2018-08-01: Inputs: Workaround for Emscripten which doesn't seem to handle focus related calls.
|
||||
// 2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor.
|
||||
// 2018-06-08: Misc: Extracted imgui_impl_sdl.cpp/.h away from the old combined SDL2+OpenGL/Vulkan examples.
|
||||
// 2018-06-08: Misc: ImGui_ImplSDL2_InitForOpenGL() now takes a SDL_GLContext parameter.
|
||||
// 2018-05-09: Misc: Fixed clipboard paste memory leak (we didn't call SDL_FreeMemory on the data returned by SDL_GetClipboardText).
|
||||
// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoMouseCursorChange flag.
|
||||
// 2018-02-16: Inputs: Added support for mouse cursors, honoring ImGui::GetMouseCursor() value.
|
||||
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
|
||||
// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space.
|
||||
// 2018-02-05: Misc: Using SDL_GetPerformanceCounter() instead of SDL_GetTicks() to be able to handle very high framerate (1000+ FPS).
|
||||
// 2018-02-05: Inputs: Keyboard mapping is using scancodes everywhere instead of a confusing mixture of keycodes and scancodes.
|
||||
// 2018-01-20: Inputs: Added Horizontal Mouse Wheel support.
|
||||
// 2018-01-19: Inputs: When available (SDL 2.0.4+) using SDL_CaptureMouse() to retrieve coordinates outside of client area when dragging. Otherwise (SDL 2.0.3 and before) testing for SDL_WINDOW_INPUT_FOCUS instead of SDL_WINDOW_MOUSE_FOCUS.
|
||||
// 2018-01-18: Inputs: Added mapping for ImGuiKey_Insert.
|
||||
// 2017-08-25: Inputs: MousePos set to -FLT_MAX,-FLT_MAX when mouse is unavailable/missing (instead of -1,-1).
|
||||
// 2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers.
|
||||
|
||||
#include "imgui.h"
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include "imgui_impl_sdl2.h"
|
||||
|
||||
// Clang warnings with -Weverything
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast
|
||||
#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision
|
||||
#endif
|
||||
|
||||
// SDL
|
||||
#include <SDL.h>
|
||||
#include <SDL_syswm.h>
|
||||
#include <stdio.h> // for snprintf()
|
||||
#ifdef __APPLE__
|
||||
#include <TargetConditionals.h>
|
||||
#endif
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include <emscripten/em_js.h>
|
||||
#endif
|
||||
#undef Status // X11 headers are leaking this.
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2,0,4) && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IOS) && !defined(__amigaos4__)
|
||||
#define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE 1
|
||||
#else
|
||||
#define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE 0
|
||||
#endif
|
||||
#define SDL_HAS_PER_MONITOR_DPI SDL_VERSION_ATLEAST(2,0,4)
|
||||
#define SDL_HAS_VULKAN SDL_VERSION_ATLEAST(2,0,6)
|
||||
#define SDL_HAS_OPEN_URL SDL_VERSION_ATLEAST(2,0,14)
|
||||
#if SDL_HAS_VULKAN
|
||||
#include <SDL_vulkan.h>
|
||||
#endif
|
||||
|
||||
// SDL Data
|
||||
struct ImGui_ImplSDL2_Data
|
||||
{
|
||||
SDL_Window* Window;
|
||||
Uint32 WindowID; // Stored in ImGuiViewport::PlatformHandle. Use SDL_GetWindowFromID() to get SDL_Window* from Uint32 WindowID.
|
||||
SDL_Renderer* Renderer;
|
||||
Uint64 Time;
|
||||
char* ClipboardTextData;
|
||||
char BackendPlatformName[48];
|
||||
|
||||
// Mouse handling
|
||||
Uint32 MouseWindowID;
|
||||
int MouseButtonsDown;
|
||||
SDL_Cursor* MouseCursors[ImGuiMouseCursor_COUNT];
|
||||
SDL_Cursor* MouseLastCursor;
|
||||
int MouseLastLeaveFrame;
|
||||
bool MouseCanUseGlobalState;
|
||||
ImGui_ImplSDL2_MouseCaptureMode MouseCaptureMode;
|
||||
|
||||
// Gamepad handling
|
||||
ImVector<SDL_GameController*> Gamepads;
|
||||
ImGui_ImplSDL2_GamepadMode GamepadMode;
|
||||
bool WantUpdateGamepadsList;
|
||||
|
||||
ImGui_ImplSDL2_Data() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
// Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts
|
||||
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
|
||||
// FIXME: multi-context support is not well tested and probably dysfunctional in this backend.
|
||||
// FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context.
|
||||
static ImGui_ImplSDL2_Data* ImGui_ImplSDL2_GetBackendData()
|
||||
{
|
||||
return ImGui::GetCurrentContext() ? (ImGui_ImplSDL2_Data*)ImGui::GetIO().BackendPlatformUserData : nullptr;
|
||||
}
|
||||
|
||||
// Functions
|
||||
static const char* ImGui_ImplSDL2_GetClipboardText(ImGuiContext*)
|
||||
{
|
||||
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
|
||||
if (bd->ClipboardTextData)
|
||||
SDL_free(bd->ClipboardTextData);
|
||||
if (SDL_HasClipboardText())
|
||||
bd->ClipboardTextData = SDL_GetClipboardText();
|
||||
else
|
||||
bd->ClipboardTextData = nullptr;
|
||||
return bd->ClipboardTextData;
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDL2_SetClipboardText(ImGuiContext*, const char* text)
|
||||
{
|
||||
SDL_SetClipboardText(text);
|
||||
}
|
||||
|
||||
// Note: native IME will only display if user calls SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1") _before_ SDL_CreateWindow().
|
||||
static void ImGui_ImplSDL2_PlatformSetImeData(ImGuiContext*, ImGuiViewport*, ImGuiPlatformImeData* data)
|
||||
{
|
||||
if (data->WantVisible)
|
||||
{
|
||||
SDL_Rect r;
|
||||
r.x = (int)data->InputPos.x;
|
||||
r.y = (int)data->InputPos.y;
|
||||
r.w = 1;
|
||||
r.h = (int)data->InputLineHeight;
|
||||
SDL_SetTextInputRect(&r);
|
||||
}
|
||||
}
|
||||
|
||||
// Not static to allow third-party code to use that if they want to (but undocumented)
|
||||
ImGuiKey ImGui_ImplSDL2_KeyEventToImGuiKey(SDL_Keycode keycode, SDL_Scancode scancode);
|
||||
ImGuiKey ImGui_ImplSDL2_KeyEventToImGuiKey(SDL_Keycode keycode, SDL_Scancode scancode)
|
||||
{
|
||||
switch (keycode)
|
||||
{
|
||||
case SDLK_TAB: return ImGuiKey_Tab;
|
||||
case SDLK_LEFT: return ImGuiKey_LeftArrow;
|
||||
case SDLK_RIGHT: return ImGuiKey_RightArrow;
|
||||
case SDLK_UP: return ImGuiKey_UpArrow;
|
||||
case SDLK_DOWN: return ImGuiKey_DownArrow;
|
||||
case SDLK_PAGEUP: return ImGuiKey_PageUp;
|
||||
case SDLK_PAGEDOWN: return ImGuiKey_PageDown;
|
||||
case SDLK_HOME: return ImGuiKey_Home;
|
||||
case SDLK_END: return ImGuiKey_End;
|
||||
case SDLK_INSERT: return ImGuiKey_Insert;
|
||||
case SDLK_DELETE: return ImGuiKey_Delete;
|
||||
case SDLK_BACKSPACE: return ImGuiKey_Backspace;
|
||||
case SDLK_SPACE: return ImGuiKey_Space;
|
||||
case SDLK_RETURN: return ImGuiKey_Enter;
|
||||
case SDLK_ESCAPE: return ImGuiKey_Escape;
|
||||
//case SDLK_QUOTE: return ImGuiKey_Apostrophe;
|
||||
case SDLK_COMMA: return ImGuiKey_Comma;
|
||||
//case SDLK_MINUS: return ImGuiKey_Minus;
|
||||
case SDLK_PERIOD: return ImGuiKey_Period;
|
||||
//case SDLK_SLASH: return ImGuiKey_Slash;
|
||||
case SDLK_SEMICOLON: return ImGuiKey_Semicolon;
|
||||
//case SDLK_EQUALS: return ImGuiKey_Equal;
|
||||
//case SDLK_LEFTBRACKET: return ImGuiKey_LeftBracket;
|
||||
//case SDLK_BACKSLASH: return ImGuiKey_Backslash;
|
||||
//case SDLK_RIGHTBRACKET: return ImGuiKey_RightBracket;
|
||||
//case SDLK_BACKQUOTE: return ImGuiKey_GraveAccent;
|
||||
case SDLK_CAPSLOCK: return ImGuiKey_CapsLock;
|
||||
case SDLK_SCROLLLOCK: return ImGuiKey_ScrollLock;
|
||||
case SDLK_NUMLOCKCLEAR: return ImGuiKey_NumLock;
|
||||
case SDLK_PRINTSCREEN: return ImGuiKey_PrintScreen;
|
||||
case SDLK_PAUSE: return ImGuiKey_Pause;
|
||||
case SDLK_KP_0: return ImGuiKey_Keypad0;
|
||||
case SDLK_KP_1: return ImGuiKey_Keypad1;
|
||||
case SDLK_KP_2: return ImGuiKey_Keypad2;
|
||||
case SDLK_KP_3: return ImGuiKey_Keypad3;
|
||||
case SDLK_KP_4: return ImGuiKey_Keypad4;
|
||||
case SDLK_KP_5: return ImGuiKey_Keypad5;
|
||||
case SDLK_KP_6: return ImGuiKey_Keypad6;
|
||||
case SDLK_KP_7: return ImGuiKey_Keypad7;
|
||||
case SDLK_KP_8: return ImGuiKey_Keypad8;
|
||||
case SDLK_KP_9: return ImGuiKey_Keypad9;
|
||||
case SDLK_KP_PERIOD: return ImGuiKey_KeypadDecimal;
|
||||
case SDLK_KP_DIVIDE: return ImGuiKey_KeypadDivide;
|
||||
case SDLK_KP_MULTIPLY: return ImGuiKey_KeypadMultiply;
|
||||
case SDLK_KP_MINUS: return ImGuiKey_KeypadSubtract;
|
||||
case SDLK_KP_PLUS: return ImGuiKey_KeypadAdd;
|
||||
case SDLK_KP_ENTER: return ImGuiKey_KeypadEnter;
|
||||
case SDLK_KP_EQUALS: return ImGuiKey_KeypadEqual;
|
||||
case SDLK_LCTRL: return ImGuiKey_LeftCtrl;
|
||||
case SDLK_LSHIFT: return ImGuiKey_LeftShift;
|
||||
case SDLK_LALT: return ImGuiKey_LeftAlt;
|
||||
case SDLK_LGUI: return ImGuiKey_LeftSuper;
|
||||
case SDLK_RCTRL: return ImGuiKey_RightCtrl;
|
||||
case SDLK_RSHIFT: return ImGuiKey_RightShift;
|
||||
case SDLK_RALT: return ImGuiKey_RightAlt;
|
||||
case SDLK_RGUI: return ImGuiKey_RightSuper;
|
||||
case SDLK_APPLICATION: return ImGuiKey_Menu;
|
||||
case SDLK_0: return ImGuiKey_0;
|
||||
case SDLK_1: return ImGuiKey_1;
|
||||
case SDLK_2: return ImGuiKey_2;
|
||||
case SDLK_3: return ImGuiKey_3;
|
||||
case SDLK_4: return ImGuiKey_4;
|
||||
case SDLK_5: return ImGuiKey_5;
|
||||
case SDLK_6: return ImGuiKey_6;
|
||||
case SDLK_7: return ImGuiKey_7;
|
||||
case SDLK_8: return ImGuiKey_8;
|
||||
case SDLK_9: return ImGuiKey_9;
|
||||
case SDLK_a: return ImGuiKey_A;
|
||||
case SDLK_b: return ImGuiKey_B;
|
||||
case SDLK_c: return ImGuiKey_C;
|
||||
case SDLK_d: return ImGuiKey_D;
|
||||
case SDLK_e: return ImGuiKey_E;
|
||||
case SDLK_f: return ImGuiKey_F;
|
||||
case SDLK_g: return ImGuiKey_G;
|
||||
case SDLK_h: return ImGuiKey_H;
|
||||
case SDLK_i: return ImGuiKey_I;
|
||||
case SDLK_j: return ImGuiKey_J;
|
||||
case SDLK_k: return ImGuiKey_K;
|
||||
case SDLK_l: return ImGuiKey_L;
|
||||
case SDLK_m: return ImGuiKey_M;
|
||||
case SDLK_n: return ImGuiKey_N;
|
||||
case SDLK_o: return ImGuiKey_O;
|
||||
case SDLK_p: return ImGuiKey_P;
|
||||
case SDLK_q: return ImGuiKey_Q;
|
||||
case SDLK_r: return ImGuiKey_R;
|
||||
case SDLK_s: return ImGuiKey_S;
|
||||
case SDLK_t: return ImGuiKey_T;
|
||||
case SDLK_u: return ImGuiKey_U;
|
||||
case SDLK_v: return ImGuiKey_V;
|
||||
case SDLK_w: return ImGuiKey_W;
|
||||
case SDLK_x: return ImGuiKey_X;
|
||||
case SDLK_y: return ImGuiKey_Y;
|
||||
case SDLK_z: return ImGuiKey_Z;
|
||||
case SDLK_F1: return ImGuiKey_F1;
|
||||
case SDLK_F2: return ImGuiKey_F2;
|
||||
case SDLK_F3: return ImGuiKey_F3;
|
||||
case SDLK_F4: return ImGuiKey_F4;
|
||||
case SDLK_F5: return ImGuiKey_F5;
|
||||
case SDLK_F6: return ImGuiKey_F6;
|
||||
case SDLK_F7: return ImGuiKey_F7;
|
||||
case SDLK_F8: return ImGuiKey_F8;
|
||||
case SDLK_F9: return ImGuiKey_F9;
|
||||
case SDLK_F10: return ImGuiKey_F10;
|
||||
case SDLK_F11: return ImGuiKey_F11;
|
||||
case SDLK_F12: return ImGuiKey_F12;
|
||||
case SDLK_F13: return ImGuiKey_F13;
|
||||
case SDLK_F14: return ImGuiKey_F14;
|
||||
case SDLK_F15: return ImGuiKey_F15;
|
||||
case SDLK_F16: return ImGuiKey_F16;
|
||||
case SDLK_F17: return ImGuiKey_F17;
|
||||
case SDLK_F18: return ImGuiKey_F18;
|
||||
case SDLK_F19: return ImGuiKey_F19;
|
||||
case SDLK_F20: return ImGuiKey_F20;
|
||||
case SDLK_F21: return ImGuiKey_F21;
|
||||
case SDLK_F22: return ImGuiKey_F22;
|
||||
case SDLK_F23: return ImGuiKey_F23;
|
||||
case SDLK_F24: return ImGuiKey_F24;
|
||||
case SDLK_AC_BACK: return ImGuiKey_AppBack;
|
||||
case SDLK_AC_FORWARD: return ImGuiKey_AppForward;
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Fallback to scancode
|
||||
switch (scancode)
|
||||
{
|
||||
case SDL_SCANCODE_GRAVE: return ImGuiKey_GraveAccent;
|
||||
case SDL_SCANCODE_MINUS: return ImGuiKey_Minus;
|
||||
case SDL_SCANCODE_EQUALS: return ImGuiKey_Equal;
|
||||
case SDL_SCANCODE_LEFTBRACKET: return ImGuiKey_LeftBracket;
|
||||
case SDL_SCANCODE_RIGHTBRACKET: return ImGuiKey_RightBracket;
|
||||
case SDL_SCANCODE_NONUSBACKSLASH: return ImGuiKey_Oem102;
|
||||
case SDL_SCANCODE_BACKSLASH: return ImGuiKey_Backslash;
|
||||
case SDL_SCANCODE_SEMICOLON: return ImGuiKey_Semicolon;
|
||||
case SDL_SCANCODE_APOSTROPHE: return ImGuiKey_Apostrophe;
|
||||
case SDL_SCANCODE_COMMA: return ImGuiKey_Comma;
|
||||
case SDL_SCANCODE_PERIOD: return ImGuiKey_Period;
|
||||
case SDL_SCANCODE_SLASH: return ImGuiKey_Slash;
|
||||
default: break;
|
||||
}
|
||||
return ImGuiKey_None;
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDL2_UpdateKeyModifiers(SDL_Keymod sdl_key_mods)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.AddKeyEvent(ImGuiMod_Ctrl, (sdl_key_mods & KMOD_CTRL) != 0);
|
||||
io.AddKeyEvent(ImGuiMod_Shift, (sdl_key_mods & KMOD_SHIFT) != 0);
|
||||
io.AddKeyEvent(ImGuiMod_Alt, (sdl_key_mods & KMOD_ALT) != 0);
|
||||
io.AddKeyEvent(ImGuiMod_Super, (sdl_key_mods & KMOD_GUI) != 0);
|
||||
}
|
||||
|
||||
static ImGuiViewport* ImGui_ImplSDL2_GetViewportForWindowID(Uint32 window_id)
|
||||
{
|
||||
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
|
||||
return (window_id == bd->WindowID) ? ImGui::GetMainViewport() : nullptr;
|
||||
}
|
||||
|
||||
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
|
||||
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
|
||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||
bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
|
||||
{
|
||||
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplSDL2_Init()?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case SDL_MOUSEMOTION:
|
||||
{
|
||||
if (ImGui_ImplSDL2_GetViewportForWindowID(event->motion.windowID) == nullptr)
|
||||
return false;
|
||||
ImVec2 mouse_pos((float)event->motion.x, (float)event->motion.y);
|
||||
io.AddMouseSourceEvent(event->motion.which == SDL_TOUCH_MOUSEID ? ImGuiMouseSource_TouchScreen : ImGuiMouseSource_Mouse);
|
||||
io.AddMousePosEvent(mouse_pos.x, mouse_pos.y);
|
||||
return true;
|
||||
}
|
||||
case SDL_MOUSEWHEEL:
|
||||
{
|
||||
if (ImGui_ImplSDL2_GetViewportForWindowID(event->wheel.windowID) == nullptr)
|
||||
return false;
|
||||
//IMGUI_DEBUG_LOG("wheel %.2f %.2f, precise %.2f %.2f\n", (float)event->wheel.x, (float)event->wheel.y, event->wheel.preciseX, event->wheel.preciseY);
|
||||
#if SDL_VERSION_ATLEAST(2,0,18) // If this fails to compile on Emscripten: update to latest Emscripten!
|
||||
float wheel_x = -event->wheel.preciseX;
|
||||
float wheel_y = event->wheel.preciseY;
|
||||
#else
|
||||
float wheel_x = -(float)event->wheel.x;
|
||||
float wheel_y = (float)event->wheel.y;
|
||||
#endif
|
||||
#if defined(__EMSCRIPTEN__) && !SDL_VERSION_ATLEAST(2,31,0)
|
||||
wheel_x /= 100.0f;
|
||||
#endif
|
||||
io.AddMouseSourceEvent(event->wheel.which == SDL_TOUCH_MOUSEID ? ImGuiMouseSource_TouchScreen : ImGuiMouseSource_Mouse);
|
||||
io.AddMouseWheelEvent(wheel_x, wheel_y);
|
||||
return true;
|
||||
}
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
{
|
||||
if (ImGui_ImplSDL2_GetViewportForWindowID(event->button.windowID) == nullptr)
|
||||
return false;
|
||||
int mouse_button = -1;
|
||||
if (event->button.button == SDL_BUTTON_LEFT) { mouse_button = 0; }
|
||||
if (event->button.button == SDL_BUTTON_RIGHT) { mouse_button = 1; }
|
||||
if (event->button.button == SDL_BUTTON_MIDDLE) { mouse_button = 2; }
|
||||
if (event->button.button == SDL_BUTTON_X1) { mouse_button = 3; }
|
||||
if (event->button.button == SDL_BUTTON_X2) { mouse_button = 4; }
|
||||
if (mouse_button == -1)
|
||||
break;
|
||||
io.AddMouseSourceEvent(event->button.which == SDL_TOUCH_MOUSEID ? ImGuiMouseSource_TouchScreen : ImGuiMouseSource_Mouse);
|
||||
io.AddMouseButtonEvent(mouse_button, (event->type == SDL_MOUSEBUTTONDOWN));
|
||||
bd->MouseButtonsDown = (event->type == SDL_MOUSEBUTTONDOWN) ? (bd->MouseButtonsDown | (1 << mouse_button)) : (bd->MouseButtonsDown & ~(1 << mouse_button));
|
||||
return true;
|
||||
}
|
||||
case SDL_TEXTINPUT:
|
||||
{
|
||||
if (ImGui_ImplSDL2_GetViewportForWindowID(event->text.windowID) == nullptr)
|
||||
return false;
|
||||
io.AddInputCharactersUTF8(event->text.text);
|
||||
return true;
|
||||
}
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP:
|
||||
{
|
||||
if (ImGui_ImplSDL2_GetViewportForWindowID(event->key.windowID) == nullptr)
|
||||
return false;
|
||||
ImGui_ImplSDL2_UpdateKeyModifiers((SDL_Keymod)event->key.keysym.mod);
|
||||
//IMGUI_DEBUG_LOG("SDL_KEY_%s : key=%d ('%s'), scancode=%d ('%s'), mod=%X\n",
|
||||
// (event->type == SDL_KEYDOWN) ? "DOWN" : "UP ", event->key.keysym.sym, SDL_GetKeyName(event->key.keysym.sym), event->key.keysym.scancode, SDL_GetScancodeName(event->key.keysym.scancode), event->key.keysym.mod);
|
||||
ImGuiKey key = ImGui_ImplSDL2_KeyEventToImGuiKey(event->key.keysym.sym, event->key.keysym.scancode);
|
||||
io.AddKeyEvent(key, (event->type == SDL_KEYDOWN));
|
||||
io.SetKeyEventNativeData(key, (int)event->key.keysym.sym, (int)event->key.keysym.scancode, (int)event->key.keysym.scancode); // To support legacy indexing (<1.87 user code). Legacy backend uses SDLK_*** as indices to IsKeyXXX() functions.
|
||||
return true;
|
||||
}
|
||||
case SDL_WINDOWEVENT:
|
||||
{
|
||||
if (ImGui_ImplSDL2_GetViewportForWindowID(event->window.windowID) == nullptr)
|
||||
return false;
|
||||
// - When capturing mouse, SDL will send a bunch of conflicting LEAVE/ENTER event on every mouse move, but the final ENTER tends to be right.
|
||||
// - However we won't get a correct LEAVE event for a captured window.
|
||||
// - In some cases, when detaching a window from main viewport SDL may send SDL_WINDOWEVENT_ENTER one frame too late,
|
||||
// causing SDL_WINDOWEVENT_LEAVE on previous frame to interrupt drag operation by clear mouse position. This is why
|
||||
// we delay process the SDL_WINDOWEVENT_LEAVE events by one frame. See issue #5012 for details.
|
||||
Uint8 window_event = event->window.event;
|
||||
if (window_event == SDL_WINDOWEVENT_ENTER)
|
||||
{
|
||||
bd->MouseWindowID = event->window.windowID;
|
||||
bd->MouseLastLeaveFrame = 0;
|
||||
}
|
||||
if (window_event == SDL_WINDOWEVENT_LEAVE)
|
||||
bd->MouseLastLeaveFrame = ImGui::GetFrameCount() + 1;
|
||||
if (window_event == SDL_WINDOWEVENT_FOCUS_GAINED)
|
||||
io.AddFocusEvent(true);
|
||||
if (window_event == SDL_WINDOWEVENT_FOCUS_LOST)
|
||||
io.AddFocusEvent(false);
|
||||
return true;
|
||||
}
|
||||
case SDL_CONTROLLERDEVICEADDED:
|
||||
case SDL_CONTROLLERDEVICEREMOVED:
|
||||
{
|
||||
bd->WantUpdateGamepadsList = true;
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EM_JS(void, ImGui_ImplSDL2_EmscriptenOpenURL, (char const* url), { url = url ? UTF8ToString(url) : null; if (url) window.open(url, '_blank'); });
|
||||
#endif
|
||||
|
||||
static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer, void* sdl_gl_context)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IMGUI_CHECKVERSION();
|
||||
IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!");
|
||||
//SDL_SetHint(SDL_HINT_EVENT_LOGGING, "2");
|
||||
|
||||
// Obtain compiled and runtime versions
|
||||
SDL_version ver_compiled;
|
||||
SDL_version ver_runtime;
|
||||
SDL_VERSION(&ver_compiled);
|
||||
SDL_GetVersion(&ver_runtime);
|
||||
|
||||
// Setup backend capabilities flags
|
||||
ImGui_ImplSDL2_Data* bd = IM_NEW(ImGui_ImplSDL2_Data)();
|
||||
snprintf(bd->BackendPlatformName, sizeof(bd->BackendPlatformName), "imgui_impl_sdl2 (%u.%u.%u, %u.%u.%u)",
|
||||
ver_compiled.major, ver_compiled.minor, ver_compiled.patch, ver_runtime.major, ver_runtime.minor, ver_runtime.patch);
|
||||
io.BackendPlatformUserData = (void*)bd;
|
||||
io.BackendPlatformName = bd->BackendPlatformName;
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
|
||||
|
||||
bd->Window = window;
|
||||
bd->WindowID = SDL_GetWindowID(window);
|
||||
bd->Renderer = renderer;
|
||||
|
||||
// Check and store if we are on a SDL backend that supports SDL_GetGlobalMouseState() and SDL_CaptureMouse()
|
||||
// ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list)
|
||||
bd->MouseCanUseGlobalState = false;
|
||||
bd->MouseCaptureMode = ImGui_ImplSDL2_MouseCaptureMode_Disabled;
|
||||
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
|
||||
const char* sdl_backend = SDL_GetCurrentVideoDriver();
|
||||
const char* capture_and_global_state_whitelist[] = { "windows", "cocoa", "x11", "DIVE", "VMAN" };
|
||||
for (const char* item : capture_and_global_state_whitelist)
|
||||
if (strncmp(sdl_backend, item, strlen(item)) == 0)
|
||||
{
|
||||
bd->MouseCanUseGlobalState = true;
|
||||
bd->MouseCaptureMode = (strcmp(item, "x11") == 0) ? ImGui_ImplSDL2_MouseCaptureMode_EnabledAfterDrag : ImGui_ImplSDL2_MouseCaptureMode_Enabled;
|
||||
}
|
||||
#endif
|
||||
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
platform_io.Platform_SetClipboardTextFn = ImGui_ImplSDL2_SetClipboardText;
|
||||
platform_io.Platform_GetClipboardTextFn = ImGui_ImplSDL2_GetClipboardText;
|
||||
platform_io.Platform_ClipboardUserData = nullptr;
|
||||
platform_io.Platform_SetImeDataFn = ImGui_ImplSDL2_PlatformSetImeData;
|
||||
#ifdef __EMSCRIPTEN__
|
||||
platform_io.Platform_OpenInShellFn = [](ImGuiContext*, const char* url) { ImGui_ImplSDL2_EmscriptenOpenURL(url); return true; };
|
||||
#elif SDL_HAS_OPEN_URL
|
||||
platform_io.Platform_OpenInShellFn = [](ImGuiContext*, const char* url) { return SDL_OpenURL(url) == 0; };
|
||||
#endif
|
||||
|
||||
// Gamepad handling
|
||||
bd->GamepadMode = ImGui_ImplSDL2_GamepadMode_AutoFirst;
|
||||
bd->WantUpdateGamepadsList = true;
|
||||
|
||||
// Load mouse cursors
|
||||
bd->MouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
|
||||
bd->MouseCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM);
|
||||
bd->MouseCursors[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL);
|
||||
bd->MouseCursors[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS);
|
||||
bd->MouseCursors[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE);
|
||||
bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW);
|
||||
bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE);
|
||||
bd->MouseCursors[ImGuiMouseCursor_Hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND);
|
||||
bd->MouseCursors[ImGuiMouseCursor_Wait] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_WAIT);
|
||||
bd->MouseCursors[ImGuiMouseCursor_Progress] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_WAITARROW);
|
||||
bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO);
|
||||
|
||||
// Set platform dependent data in viewport
|
||||
// Our mouse update function expect PlatformHandle to be filled for the main viewport
|
||||
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
|
||||
main_viewport->PlatformHandle = (void*)(intptr_t)bd->WindowID;
|
||||
main_viewport->PlatformHandleRaw = nullptr;
|
||||
SDL_SysWMinfo info;
|
||||
SDL_VERSION(&info.version);
|
||||
if (SDL_GetWindowWMInfo(window, &info))
|
||||
{
|
||||
#if defined(SDL_VIDEO_DRIVER_WINDOWS)
|
||||
main_viewport->PlatformHandleRaw = (void*)info.info.win.window;
|
||||
#elif defined(__APPLE__) && defined(SDL_VIDEO_DRIVER_COCOA)
|
||||
main_viewport->PlatformHandleRaw = (void*)info.info.cocoa.window;
|
||||
#endif
|
||||
}
|
||||
|
||||
// From 2.0.5: Set SDL hint to receive mouse click events on window focus, otherwise SDL doesn't emit the event.
|
||||
// Without this, when clicking to gain focus, our widgets wouldn't activate even though they showed as hovered.
|
||||
// (This is unfortunately a global SDL setting, so enabling it might have a side-effect on your application.
|
||||
// It is unlikely to make a difference, but if your app absolutely needs to ignore the initial on-focus click:
|
||||
// you can ignore SDL_MOUSEBUTTONDOWN events coming right after a SDL_WINDOWEVENT_FOCUS_GAINED)
|
||||
#ifdef SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH
|
||||
SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
|
||||
#endif
|
||||
|
||||
// From 2.0.18: Enable native IME.
|
||||
// IMPORTANT: This is used at the time of SDL_CreateWindow() so this will only affects secondary windows, if any.
|
||||
// For the main window to be affected, your application needs to call this manually before calling SDL_CreateWindow().
|
||||
#ifdef SDL_HINT_IME_SHOW_UI
|
||||
SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");
|
||||
#endif
|
||||
|
||||
// From 2.0.22: Disable auto-capture, this is preventing drag and drop across multiple windows (see #5710)
|
||||
#ifdef SDL_HINT_MOUSE_AUTO_CAPTURE
|
||||
SDL_SetHint(SDL_HINT_MOUSE_AUTO_CAPTURE, "0");
|
||||
#endif
|
||||
|
||||
(void)sdl_gl_context; // Unused in 'master' branch.
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context)
|
||||
{
|
||||
return ImGui_ImplSDL2_Init(window, nullptr, sdl_gl_context);
|
||||
}
|
||||
|
||||
bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window)
|
||||
{
|
||||
#if !SDL_HAS_VULKAN
|
||||
IM_ASSERT(0 && "Unsupported");
|
||||
#endif
|
||||
return ImGui_ImplSDL2_Init(window, nullptr, nullptr);
|
||||
}
|
||||
|
||||
bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window)
|
||||
{
|
||||
#if !defined(_WIN32)
|
||||
IM_ASSERT(0 && "Unsupported");
|
||||
#endif
|
||||
return ImGui_ImplSDL2_Init(window, nullptr, nullptr);
|
||||
}
|
||||
|
||||
bool ImGui_ImplSDL2_InitForMetal(SDL_Window* window)
|
||||
{
|
||||
return ImGui_ImplSDL2_Init(window, nullptr, nullptr);
|
||||
}
|
||||
|
||||
bool ImGui_ImplSDL2_InitForSDLRenderer(SDL_Window* window, SDL_Renderer* renderer)
|
||||
{
|
||||
return ImGui_ImplSDL2_Init(window, renderer, nullptr);
|
||||
}
|
||||
|
||||
bool ImGui_ImplSDL2_InitForOther(SDL_Window* window)
|
||||
{
|
||||
return ImGui_ImplSDL2_Init(window, nullptr, nullptr);
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDL2_CloseGamepads();
|
||||
|
||||
void ImGui_ImplSDL2_Shutdown()
|
||||
{
|
||||
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
if (bd->ClipboardTextData)
|
||||
SDL_free(bd->ClipboardTextData);
|
||||
for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
|
||||
SDL_FreeCursor(bd->MouseCursors[cursor_n]);
|
||||
ImGui_ImplSDL2_CloseGamepads();
|
||||
|
||||
io.BackendPlatformName = nullptr;
|
||||
io.BackendPlatformUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasSetMousePos | ImGuiBackendFlags_HasGamepad);
|
||||
platform_io.ClearPlatformHandlers();
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
void ImGui_ImplSDL2_SetMouseCaptureMode(ImGui_ImplSDL2_MouseCaptureMode mode)
|
||||
{
|
||||
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
|
||||
if (mode == ImGui_ImplSDL2_MouseCaptureMode_Disabled && bd->MouseCaptureMode != ImGui_ImplSDL2_MouseCaptureMode_Disabled)
|
||||
SDL_CaptureMouse(SDL_FALSE);
|
||||
bd->MouseCaptureMode = mode;
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDL2_UpdateMouseData()
|
||||
{
|
||||
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
// We forward mouse input when hovered or captured (via SDL_MOUSEMOTION) or when focused (below)
|
||||
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
|
||||
// - SDL_CaptureMouse() let the OS know e.g. that our drags can extend outside of parent boundaries (we want updated position) and shouldn't trigger other operations outside.
|
||||
// - Debuggers under Linux tends to leave captured mouse on break, which may be very inconvenient, so to mitigate the issue on X11 we we wait until mouse has moved to begin capture.
|
||||
if (bd->MouseCaptureMode == ImGui_ImplSDL2_MouseCaptureMode_Enabled)
|
||||
{
|
||||
SDL_CaptureMouse((bd->MouseButtonsDown != 0) ? SDL_TRUE : SDL_FALSE);
|
||||
}
|
||||
else if (bd->MouseCaptureMode == ImGui_ImplSDL2_MouseCaptureMode_EnabledAfterDrag)
|
||||
{
|
||||
bool want_capture = false;
|
||||
for (int button_n = 0; button_n < ImGuiMouseButton_COUNT && !want_capture; button_n++)
|
||||
if (ImGui::IsMouseDragging(button_n, 1.0f))
|
||||
want_capture = true;
|
||||
SDL_CaptureMouse(want_capture ? SDL_TRUE : SDL_FALSE);
|
||||
}
|
||||
|
||||
SDL_Window* focused_window = SDL_GetKeyboardFocus();
|
||||
const bool is_app_focused = (bd->Window == focused_window);
|
||||
#else
|
||||
SDL_Window* focused_window = bd->Window;
|
||||
const bool is_app_focused = (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_INPUT_FOCUS) != 0; // SDL 2.0.3 and non-windowed systems: single-viewport only
|
||||
#endif
|
||||
if (is_app_focused)
|
||||
{
|
||||
// (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when io.ConfigNavMoveSetMousePos is enabled by user)
|
||||
if (io.WantSetMousePos)
|
||||
SDL_WarpMouseInWindow(bd->Window, (int)io.MousePos.x, (int)io.MousePos.y);
|
||||
|
||||
// (Optional) Fallback to provide unclamped mouse position when focused but not hovered (SDL_MOUSEMOTION already provides this when hovered or captured)
|
||||
// Note that SDL_GetGlobalMouseState() is in theory slow on X11, but this only runs on rather specific cases. If a problem we may provide a way to opt-out this feature.
|
||||
SDL_Window* hovered_window = SDL_GetMouseFocus();
|
||||
const bool is_relative_mouse_mode = SDL_GetRelativeMouseMode() != 0;
|
||||
if (hovered_window == nullptr && bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0 && !is_relative_mouse_mode)
|
||||
{
|
||||
// Single-viewport mode: mouse position in client window coordinates (io.MousePos is (0,0) when the mouse is on the upper-left corner of the app window)
|
||||
int mouse_x, mouse_y;
|
||||
int window_x, window_y;
|
||||
SDL_GetGlobalMouseState(&mouse_x, &mouse_y);
|
||||
SDL_GetWindowPosition(focused_window, &window_x, &window_y);
|
||||
mouse_x -= window_x;
|
||||
mouse_y -= window_y;
|
||||
io.AddMousePosEvent((float)mouse_x, (float)mouse_y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDL2_UpdateMouseCursor()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
|
||||
return;
|
||||
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
|
||||
|
||||
ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
|
||||
if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None)
|
||||
{
|
||||
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
|
||||
SDL_ShowCursor(SDL_FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Show OS mouse cursor
|
||||
SDL_Cursor* expected_cursor = bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow];
|
||||
if (bd->MouseLastCursor != expected_cursor)
|
||||
{
|
||||
SDL_SetCursor(expected_cursor); // SDL function doesn't have an early out (see #6113)
|
||||
bd->MouseLastCursor = expected_cursor;
|
||||
}
|
||||
SDL_ShowCursor(SDL_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
// - On Windows the process needs to be marked DPI-aware!! SDL2 doesn't do it by default. You can call ::SetProcessDPIAware() or call ImGui_ImplWin32_EnableDpiAwareness() from Win32 backend.
|
||||
// - Apple platforms use FramebufferScale so we always return 1.0f.
|
||||
// - Some accessibility applications are declaring virtual monitors with a DPI of 0.0f, see #7902. We preserve this value for caller to handle.
|
||||
float ImGui_ImplSDL2_GetContentScaleForWindow(SDL_Window* window)
|
||||
{
|
||||
return ImGui_ImplSDL2_GetContentScaleForDisplay(SDL_GetWindowDisplayIndex(window));
|
||||
}
|
||||
|
||||
// SDL_GetDisplayDPI() seems rather unreliable on Linux.
|
||||
float ImGui_ImplSDL2_GetContentScaleForDisplay(int display_index)
|
||||
{
|
||||
const char* sdl_driver = SDL_GetCurrentVideoDriver();
|
||||
if (sdl_driver && strcmp(sdl_driver, "wayland") == 0)
|
||||
return 1.0f;
|
||||
#if SDL_HAS_PER_MONITOR_DPI
|
||||
#if !defined(__APPLE__) && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__)
|
||||
float dpi = 0.0f;
|
||||
if (SDL_GetDisplayDPI(display_index, &dpi, nullptr, nullptr) == 0)
|
||||
{
|
||||
if (dpi < 96.0f)
|
||||
dpi = 96.0f;
|
||||
return dpi / 96.0f;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
IM_UNUSED(display_index);
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDL2_CloseGamepads()
|
||||
{
|
||||
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
|
||||
if (bd->GamepadMode != ImGui_ImplSDL2_GamepadMode_Manual)
|
||||
for (SDL_GameController* gamepad : bd->Gamepads)
|
||||
SDL_GameControllerClose(gamepad);
|
||||
bd->Gamepads.resize(0);
|
||||
}
|
||||
|
||||
void ImGui_ImplSDL2_SetGamepadMode(ImGui_ImplSDL2_GamepadMode mode, struct _SDL_GameController** manual_gamepads_array, int manual_gamepads_count)
|
||||
{
|
||||
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
|
||||
ImGui_ImplSDL2_CloseGamepads();
|
||||
if (mode == ImGui_ImplSDL2_GamepadMode_Manual)
|
||||
{
|
||||
IM_ASSERT(manual_gamepads_array != nullptr || manual_gamepads_count <= 0);
|
||||
for (int n = 0; n < manual_gamepads_count; n++)
|
||||
bd->Gamepads.push_back(manual_gamepads_array[n]);
|
||||
}
|
||||
else
|
||||
{
|
||||
IM_ASSERT(manual_gamepads_array == nullptr && manual_gamepads_count <= 0);
|
||||
bd->WantUpdateGamepadsList = true;
|
||||
}
|
||||
bd->GamepadMode = mode;
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDL2_UpdateGamepadButton(ImGui_ImplSDL2_Data* bd, ImGuiIO& io, ImGuiKey key, SDL_GameControllerButton button_no)
|
||||
{
|
||||
bool merged_value = false;
|
||||
for (SDL_GameController* gamepad : bd->Gamepads)
|
||||
merged_value |= SDL_GameControllerGetButton(gamepad, button_no) != 0;
|
||||
io.AddKeyEvent(key, merged_value);
|
||||
}
|
||||
|
||||
static inline float Saturate(float v) { return v < 0.0f ? 0.0f : v > 1.0f ? 1.0f : v; }
|
||||
static void ImGui_ImplSDL2_UpdateGamepadAnalog(ImGui_ImplSDL2_Data* bd, ImGuiIO& io, ImGuiKey key, SDL_GameControllerAxis axis_no, float v0, float v1)
|
||||
{
|
||||
float merged_value = 0.0f;
|
||||
for (SDL_GameController* gamepad : bd->Gamepads)
|
||||
{
|
||||
float vn = Saturate((float)(SDL_GameControllerGetAxis(gamepad, axis_no) - v0) / (float)(v1 - v0));
|
||||
if (merged_value < vn)
|
||||
merged_value = vn;
|
||||
}
|
||||
io.AddKeyAnalogEvent(key, merged_value > 0.1f, merged_value);
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDL2_UpdateGamepads()
|
||||
{
|
||||
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
// Update list of controller(s) to use
|
||||
if (bd->WantUpdateGamepadsList && bd->GamepadMode != ImGui_ImplSDL2_GamepadMode_Manual)
|
||||
{
|
||||
ImGui_ImplSDL2_CloseGamepads();
|
||||
int joystick_count = SDL_NumJoysticks();
|
||||
for (int n = 0; n < joystick_count; n++)
|
||||
if (SDL_IsGameController(n))
|
||||
if (SDL_GameController* gamepad = SDL_GameControllerOpen(n))
|
||||
{
|
||||
bd->Gamepads.push_back(gamepad);
|
||||
if (bd->GamepadMode == ImGui_ImplSDL2_GamepadMode_AutoFirst)
|
||||
break;
|
||||
}
|
||||
bd->WantUpdateGamepadsList = false;
|
||||
}
|
||||
|
||||
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
|
||||
if (bd->Gamepads.Size == 0)
|
||||
return;
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
|
||||
|
||||
// Update gamepad inputs
|
||||
const int thumb_dead_zone = 8000; // SDL_gamecontroller.h suggests using this value.
|
||||
ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadStart, SDL_CONTROLLER_BUTTON_START);
|
||||
ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadBack, SDL_CONTROLLER_BUTTON_BACK);
|
||||
ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceLeft, SDL_CONTROLLER_BUTTON_X); // Xbox X, PS Square
|
||||
ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceRight, SDL_CONTROLLER_BUTTON_B); // Xbox B, PS Circle
|
||||
ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceUp, SDL_CONTROLLER_BUTTON_Y); // Xbox Y, PS Triangle
|
||||
ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceDown, SDL_CONTROLLER_BUTTON_A); // Xbox A, PS Cross
|
||||
ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT);
|
||||
ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT);
|
||||
ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadUp, SDL_CONTROLLER_BUTTON_DPAD_UP);
|
||||
ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN);
|
||||
ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadL1, SDL_CONTROLLER_BUTTON_LEFTSHOULDER);
|
||||
ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadR1, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER);
|
||||
ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadL2, SDL_CONTROLLER_AXIS_TRIGGERLEFT, 0.0f, 32767);
|
||||
ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadR2, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, 0.0f, 32767);
|
||||
ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadL3, SDL_CONTROLLER_BUTTON_LEFTSTICK);
|
||||
ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadR3, SDL_CONTROLLER_BUTTON_RIGHTSTICK);
|
||||
ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickLeft, SDL_CONTROLLER_AXIS_LEFTX, -thumb_dead_zone, -32768);
|
||||
ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickRight, SDL_CONTROLLER_AXIS_LEFTX, +thumb_dead_zone, +32767);
|
||||
ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickUp, SDL_CONTROLLER_AXIS_LEFTY, -thumb_dead_zone, -32768);
|
||||
ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickDown, SDL_CONTROLLER_AXIS_LEFTY, +thumb_dead_zone, +32767);
|
||||
ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickLeft, SDL_CONTROLLER_AXIS_RIGHTX, -thumb_dead_zone, -32768);
|
||||
ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickRight, SDL_CONTROLLER_AXIS_RIGHTX, +thumb_dead_zone, +32767);
|
||||
ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickUp, SDL_CONTROLLER_AXIS_RIGHTY, -thumb_dead_zone, -32768);
|
||||
ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickDown, SDL_CONTROLLER_AXIS_RIGHTY, +thumb_dead_zone, +32767);
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDL2_GetWindowSizeAndFramebufferScale(SDL_Window* window, SDL_Renderer* renderer, ImVec2* out_size, ImVec2* out_framebuffer_scale)
|
||||
{
|
||||
int w, h;
|
||||
int display_w, display_h;
|
||||
SDL_GetWindowSize(window, &w, &h);
|
||||
if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED)
|
||||
w = h = 0;
|
||||
if (renderer != nullptr)
|
||||
SDL_GetRendererOutputSize(renderer, &display_w, &display_h);
|
||||
#if SDL_HAS_VULKAN
|
||||
else if (SDL_GetWindowFlags(window) & SDL_WINDOW_VULKAN)
|
||||
SDL_Vulkan_GetDrawableSize(window, &display_w, &display_h);
|
||||
#endif
|
||||
else
|
||||
SDL_GL_GetDrawableSize(window, &display_w, &display_h);
|
||||
if (out_size != nullptr)
|
||||
*out_size = ImVec2((float)w, (float)h);
|
||||
if (out_framebuffer_scale != nullptr)
|
||||
*out_framebuffer_scale = (w > 0 && h > 0) ? ImVec2((float)display_w / (float)w, (float)display_h / (float)h) : ImVec2(1.0f, 1.0f);
|
||||
}
|
||||
|
||||
void ImGui_ImplSDL2_NewFrame()
|
||||
{
|
||||
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplSDL2_Init()?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
// Setup main viewport size (every frame to accommodate for window resizing)
|
||||
ImGui_ImplSDL2_GetWindowSizeAndFramebufferScale(bd->Window, bd->Renderer, &io.DisplaySize, &io.DisplayFramebufferScale);
|
||||
|
||||
// Setup time step (we don't use SDL_GetTicks() because it is using millisecond resolution)
|
||||
// (Accept SDL_GetPerformanceCounter() not returning a monotonically increasing value. Happens in VMs and Emscripten, see #6189, #6114, #3644)
|
||||
static Uint64 frequency = SDL_GetPerformanceFrequency();
|
||||
Uint64 current_time = SDL_GetPerformanceCounter();
|
||||
if (current_time <= bd->Time)
|
||||
current_time = bd->Time + 1;
|
||||
io.DeltaTime = bd->Time > 0 ? (float)((double)(current_time - bd->Time) / (double)frequency) : (float)(1.0f / 60.0f);
|
||||
bd->Time = current_time;
|
||||
|
||||
if (bd->MouseLastLeaveFrame && bd->MouseLastLeaveFrame >= ImGui::GetFrameCount() && bd->MouseButtonsDown == 0)
|
||||
{
|
||||
bd->MouseWindowID = 0;
|
||||
bd->MouseLastLeaveFrame = 0;
|
||||
io.AddMousePosEvent(-FLT_MAX, -FLT_MAX);
|
||||
}
|
||||
|
||||
ImGui_ImplSDL2_UpdateMouseData();
|
||||
ImGui_ImplSDL2_UpdateMouseCursor();
|
||||
|
||||
// Update game controllers (if enabled and available)
|
||||
ImGui_ImplSDL2_UpdateGamepads();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
57
backends/imgui_impl_sdl2.h
Normal file
57
backends/imgui_impl_sdl2.h
Normal file
@@ -0,0 +1,57 @@
|
||||
// dear imgui: Platform Backend for SDL2
|
||||
// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
|
||||
// (Info: SDL2 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Platform: Clipboard support.
|
||||
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen.
|
||||
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values are obsolete since 1.87 and not supported since 1.91.5]
|
||||
// [X] Platform: Gamepad support.
|
||||
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
// [X] Platform: Basic IME support. App needs to call 'SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");' before SDL_CreateWindow()!.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
#pragma once
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
struct SDL_Window;
|
||||
struct SDL_Renderer;
|
||||
struct _SDL_GameController;
|
||||
typedef union SDL_Event SDL_Event;
|
||||
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context);
|
||||
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window);
|
||||
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window);
|
||||
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForMetal(SDL_Window* window);
|
||||
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForSDLRenderer(SDL_Window* window, SDL_Renderer* renderer);
|
||||
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForOther(SDL_Window* window);
|
||||
IMGUI_IMPL_API void ImGui_ImplSDL2_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplSDL2_NewFrame();
|
||||
IMGUI_IMPL_API bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event);
|
||||
|
||||
// DPI-related helpers (optional)
|
||||
IMGUI_IMPL_API float ImGui_ImplSDL2_GetContentScaleForWindow(SDL_Window* window);
|
||||
IMGUI_IMPL_API float ImGui_ImplSDL2_GetContentScaleForDisplay(int display_index);
|
||||
|
||||
// Gamepad selection automatically starts in AutoFirst mode, picking first available SDL_Gamepad. You may override this.
|
||||
// When using manual mode, caller is responsible for opening/closing gamepad.
|
||||
enum ImGui_ImplSDL2_GamepadMode { ImGui_ImplSDL2_GamepadMode_AutoFirst, ImGui_ImplSDL2_GamepadMode_AutoAll, ImGui_ImplSDL2_GamepadMode_Manual };
|
||||
IMGUI_IMPL_API void ImGui_ImplSDL2_SetGamepadMode(ImGui_ImplSDL2_GamepadMode mode, struct _SDL_GameController** manual_gamepads_array = nullptr, int manual_gamepads_count = -1);
|
||||
|
||||
// (Advanced, for X11 users) Override Mouse Capture mode. Mouse capture allows receiving updated mouse position after clicking inside our window and dragging outside it.
|
||||
// Having this 'Enabled' is in theory always better. But, on X11 if you crash/break to debugger while capture is active you may temporarily lose access to your mouse.
|
||||
// The best solution is to setup your debugger to automatically release capture, e.g. 'setxkbmap -option grab:break_actions && xdotool key XF86Ungrab' or via a GDB script. See #3650.
|
||||
// But you may independently decide on X11, when a debugger is attached, to set this value to ImGui_ImplSDL2_MouseCaptureMode_Disabled.
|
||||
enum ImGui_ImplSDL2_MouseCaptureMode { ImGui_ImplSDL2_MouseCaptureMode_Enabled, ImGui_ImplSDL2_MouseCaptureMode_EnabledAfterDrag, ImGui_ImplSDL2_MouseCaptureMode_Disabled };
|
||||
IMGUI_IMPL_API void ImGui_ImplSDL2_SetMouseCaptureMode(ImGui_ImplSDL2_MouseCaptureMode mode);
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
887
backends/imgui_impl_sdl3.cpp
Normal file
887
backends/imgui_impl_sdl3.cpp
Normal file
@@ -0,0 +1,887 @@
|
||||
// dear imgui: Platform Backend for SDL3
|
||||
// This needs to be used along with a Renderer (e.g. SDL_GPU, DirectX11, OpenGL3, Vulkan..)
|
||||
// (Info: SDL3 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Platform: Clipboard support.
|
||||
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen.
|
||||
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values are obsolete since 1.87 and not supported since 1.91.5]
|
||||
// [X] Platform: Gamepad support.
|
||||
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
// [X] Platform: IME support.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-02-13: Inputs: systems other than X11 are back to starting mouse capture on mouse down (reverts 2025-02-26 change). Only X11 requires waiting for a drag by default (not ideal, but a better default for X11 users). Added ImGui_ImplSDL3_SetMouseCaptureMode() for X11 debugger users. (#3650, #6410, #9235)
|
||||
// 2026-01-15: Changed GetClipboardText() handler to return nullptr on error aka clipboard contents is not text. Consistent with other backends. (#9168)
|
||||
// 2025-11-05: Fixed an issue with missing characters events when an already active text field changes viewports. (#9054)
|
||||
// 2025-10-22: Fixed Platform_OpenInShellFn() return value (unused in core).
|
||||
// 2025-09-24: Skip using the SDL_GetGlobalMouseState() state when one of our window is hovered, as the SDL_EVENT_MOUSE_MOTION data is reliable. Fix macOS notch mouse coordinates issue in fullscreen mode + better perf on X11. (#7919, #7786)
|
||||
// 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown.
|
||||
// 2025-09-15: Use SDL_GetWindowDisplayScale() on Mac to output DisplayFrameBufferScale. The function is more reliable during resolution changes e.g. going fullscreen. (#8703, #4414)
|
||||
// 2025-06-27: IME: avoid calling SDL_StartTextInput() again if already active. (#8727)
|
||||
// 2025-04-22: IME: honor ImGuiPlatformImeData->WantTextInput as an alternative way to call SDL_StartTextInput(), without IME being necessarily visible.
|
||||
// 2025-04-09: Don't attempt to call SDL_CaptureMouse() on drivers where we don't call SDL_GetGlobalMouseState(). (#8561)
|
||||
// 2025-03-30: Update for SDL3 api changes: Revert SDL_GetClipboardText() memory ownership change. (#8530, #7801)
|
||||
// 2025-03-21: Fill gamepad inputs and set ImGuiBackendFlags_HasGamepad regardless of ImGuiConfigFlags_NavEnableGamepad being set.
|
||||
// 2025-03-10: When dealing with OEM keys, use scancodes instead of translated keycodes to choose ImGuiKey values. (#7136, #7201, #7206, #7306, #7670, #7672, #8468)
|
||||
// 2025-02-26: Only start SDL_CaptureMouse() when mouse is being dragged, to mitigate issues with e.g. Linux debuggers not claiming capture back. (#6410, #3650)
|
||||
// 2025-02-24: Avoid calling SDL_GetGlobalMouseState() when mouse is in relative mode.
|
||||
// 2025-02-18: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support.
|
||||
// 2025-02-10: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn handler.
|
||||
// 2025-01-20: Made ImGui_ImplSDL3_SetGamepadMode(ImGui_ImplSDL3_GamepadMode_Manual) accept an empty array.
|
||||
// 2024-10-24: Emscripten: SDL_EVENT_MOUSE_WHEEL event doesn't require dividing by 100.0f on Emscripten.
|
||||
// 2024-09-03: Update for SDL3 api changes: SDL_GetGamepads() memory ownership revert. (#7918, #7898, #7807)
|
||||
// 2024-08-22: moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO:
|
||||
// - io.GetClipboardTextFn -> platform_io.Platform_GetClipboardTextFn
|
||||
// - io.SetClipboardTextFn -> platform_io.Platform_SetClipboardTextFn
|
||||
// - io.PlatformSetImeDataFn -> platform_io.Platform_SetImeDataFn
|
||||
// 2024-08-19: Storing SDL_WindowID inside ImGuiViewport::PlatformHandle instead of SDL_Window*.
|
||||
// 2024-08-19: ImGui_ImplSDL3_ProcessEvent() now ignores events intended for other SDL windows. (#7853)
|
||||
// 2024-07-22: Update for SDL3 api changes: SDL_GetGamepads() memory ownership change. (#7807)
|
||||
// 2024-07-18: Update for SDL3 api changes: SDL_GetClipboardText() memory ownership change. (#7801)
|
||||
// 2024-07-15: Update for SDL3 api changes: SDL_GetProperty() change to SDL_GetPointerProperty(). (#7794)
|
||||
// 2024-07-02: Update for SDL3 api changes: SDLK_x renames and SDLK_KP_x removals (#7761, #7762).
|
||||
// 2024-07-01: Update for SDL3 api changes: SDL_SetTextInputRect() changed to SDL_SetTextInputArea().
|
||||
// 2024-06-26: Update for SDL3 api changes: SDL_StartTextInput()/SDL_StopTextInput()/SDL_SetTextInputRect() functions signatures.
|
||||
// 2024-06-24: Update for SDL3 api changes: SDL_EVENT_KEY_DOWN/SDL_EVENT_KEY_UP contents.
|
||||
// 2024-06-03; Update for SDL3 api changes: SDL_SYSTEM_CURSOR_ renames.
|
||||
// 2024-05-15: Update for SDL3 api changes: SDLK_ renames.
|
||||
// 2024-04-15: Inputs: Re-enable calling SDL_StartTextInput()/SDL_StopTextInput() as SDL3 no longer enables it by default and should play nicer with IME.
|
||||
// 2024-02-13: Inputs: Fixed gamepad support. Handle gamepad disconnection. Added ImGui_ImplSDL3_SetGamepadMode().
|
||||
// 2023-11-13: Updated for recent SDL3 API changes.
|
||||
// 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys, app back/forward keys.
|
||||
// 2023-05-04: Fixed build on Emscripten/iOS/Android. (#6391)
|
||||
// 2023-04-06: Inputs: Avoid calling SDL_StartTextInput()/SDL_StopTextInput() as they don't only pertain to IME. It's unclear exactly what their relation is to IME. (#6306)
|
||||
// 2023-04-04: Inputs: Added support for io.AddMouseSourceEvent() to discriminate ImGuiMouseSource_Mouse/ImGuiMouseSource_TouchScreen. (#2702)
|
||||
// 2023-02-23: Accept SDL_GetPerformanceCounter() not returning a monotonically increasing value. (#6189, #6114, #3644)
|
||||
// 2023-02-07: Forked "imgui_impl_sdl2" into "imgui_impl_sdl3". Removed version checks for old feature. Refer to imgui_impl_sdl2.cpp for older changelog.
|
||||
|
||||
#include "imgui.h"
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include "imgui_impl_sdl3.h"
|
||||
|
||||
// Clang warnings with -Weverything
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast
|
||||
#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision
|
||||
#endif
|
||||
|
||||
// SDL
|
||||
#include <SDL3/SDL.h>
|
||||
#include <stdio.h> // for snprintf()
|
||||
#if defined(__APPLE__)
|
||||
#include <TargetConditionals.h>
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#if !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IOS) && !defined(__amigaos4__)
|
||||
#define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE 1
|
||||
#else
|
||||
#define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE 0
|
||||
#endif
|
||||
|
||||
// FIXME-LEGACY: remove when SDL 3.1.3 preview is released.
|
||||
#ifndef SDLK_APOSTROPHE
|
||||
#define SDLK_APOSTROPHE SDLK_QUOTE
|
||||
#endif
|
||||
#ifndef SDLK_GRAVE
|
||||
#define SDLK_GRAVE SDLK_BACKQUOTE
|
||||
#endif
|
||||
|
||||
// SDL Data
|
||||
struct ImGui_ImplSDL3_Data
|
||||
{
|
||||
SDL_Window* Window;
|
||||
SDL_WindowID WindowID;
|
||||
SDL_Renderer* Renderer;
|
||||
Uint64 Time;
|
||||
char* ClipboardTextData;
|
||||
char BackendPlatformName[48];
|
||||
|
||||
// IME handling
|
||||
SDL_Window* ImeWindow;
|
||||
ImGuiPlatformImeData ImeData;
|
||||
bool ImeDirty;
|
||||
|
||||
// Mouse handling
|
||||
Uint32 MouseWindowID;
|
||||
int MouseButtonsDown;
|
||||
SDL_Cursor* MouseCursors[ImGuiMouseCursor_COUNT];
|
||||
SDL_Cursor* MouseLastCursor;
|
||||
int MousePendingLeaveFrame;
|
||||
bool MouseCanUseGlobalState;
|
||||
ImGui_ImplSDL3_MouseCaptureMode MouseCaptureMode;
|
||||
|
||||
// Gamepad handling
|
||||
ImVector<SDL_Gamepad*> Gamepads;
|
||||
ImGui_ImplSDL3_GamepadMode GamepadMode;
|
||||
bool WantUpdateGamepadsList;
|
||||
|
||||
ImGui_ImplSDL3_Data() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
// Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts
|
||||
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
|
||||
// FIXME: multi-context support is not well tested and probably dysfunctional in this backend.
|
||||
// FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context.
|
||||
static ImGui_ImplSDL3_Data* ImGui_ImplSDL3_GetBackendData()
|
||||
{
|
||||
return ImGui::GetCurrentContext() ? (ImGui_ImplSDL3_Data*)ImGui::GetIO().BackendPlatformUserData : nullptr;
|
||||
}
|
||||
|
||||
// Forward Declarations
|
||||
static void ImGui_ImplSDL3_UpdateIme();
|
||||
|
||||
// Functions
|
||||
static const char* ImGui_ImplSDL3_GetClipboardText(ImGuiContext*)
|
||||
{
|
||||
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
|
||||
if (bd->ClipboardTextData)
|
||||
SDL_free(bd->ClipboardTextData);
|
||||
if (SDL_HasClipboardText())
|
||||
bd->ClipboardTextData = SDL_GetClipboardText();
|
||||
else
|
||||
bd->ClipboardTextData = nullptr;
|
||||
return bd->ClipboardTextData;
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDL3_SetClipboardText(ImGuiContext*, const char* text)
|
||||
{
|
||||
SDL_SetClipboardText(text);
|
||||
}
|
||||
|
||||
static ImGuiViewport* ImGui_ImplSDL3_GetViewportForWindowID(SDL_WindowID window_id)
|
||||
{
|
||||
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
|
||||
return (window_id == bd->WindowID) ? ImGui::GetMainViewport() : nullptr;
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDL3_PlatformSetImeData(ImGuiContext*, ImGuiViewport*, ImGuiPlatformImeData* data)
|
||||
{
|
||||
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
|
||||
bd->ImeData = *data;
|
||||
bd->ImeDirty = true;
|
||||
ImGui_ImplSDL3_UpdateIme();
|
||||
}
|
||||
|
||||
// We discard viewport passed via ImGuiPlatformImeData and always call SDL_StartTextInput() on SDL_GetKeyboardFocus().
|
||||
static void ImGui_ImplSDL3_UpdateIme()
|
||||
{
|
||||
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
|
||||
ImGuiPlatformImeData* data = &bd->ImeData;
|
||||
SDL_Window* window = SDL_GetKeyboardFocus();
|
||||
|
||||
// Stop previous input
|
||||
if ((!(data->WantVisible || data->WantTextInput) || bd->ImeWindow != window) && bd->ImeWindow != nullptr)
|
||||
{
|
||||
SDL_StopTextInput(bd->ImeWindow);
|
||||
bd->ImeWindow = nullptr;
|
||||
}
|
||||
if ((!bd->ImeDirty && bd->ImeWindow == window) || (window == nullptr))
|
||||
return;
|
||||
|
||||
// Start/update current input
|
||||
bd->ImeDirty = false;
|
||||
if (data->WantVisible)
|
||||
{
|
||||
SDL_Rect r;
|
||||
r.x = (int)data->InputPos.x;
|
||||
r.y = (int)data->InputPos.y;
|
||||
r.w = 1;
|
||||
r.h = (int)data->InputLineHeight;
|
||||
SDL_SetTextInputArea(window, &r, 0);
|
||||
bd->ImeWindow = window;
|
||||
}
|
||||
if (!SDL_TextInputActive(window) && (data->WantVisible || data->WantTextInput))
|
||||
SDL_StartTextInput(window);
|
||||
}
|
||||
|
||||
// Not static to allow third-party code to use that if they want to (but undocumented)
|
||||
ImGuiKey ImGui_ImplSDL3_KeyEventToImGuiKey(SDL_Keycode keycode, SDL_Scancode scancode);
|
||||
ImGuiKey ImGui_ImplSDL3_KeyEventToImGuiKey(SDL_Keycode keycode, SDL_Scancode scancode)
|
||||
{
|
||||
// Keypad doesn't have individual key values in SDL3
|
||||
switch (scancode)
|
||||
{
|
||||
case SDL_SCANCODE_KP_0: return ImGuiKey_Keypad0;
|
||||
case SDL_SCANCODE_KP_1: return ImGuiKey_Keypad1;
|
||||
case SDL_SCANCODE_KP_2: return ImGuiKey_Keypad2;
|
||||
case SDL_SCANCODE_KP_3: return ImGuiKey_Keypad3;
|
||||
case SDL_SCANCODE_KP_4: return ImGuiKey_Keypad4;
|
||||
case SDL_SCANCODE_KP_5: return ImGuiKey_Keypad5;
|
||||
case SDL_SCANCODE_KP_6: return ImGuiKey_Keypad6;
|
||||
case SDL_SCANCODE_KP_7: return ImGuiKey_Keypad7;
|
||||
case SDL_SCANCODE_KP_8: return ImGuiKey_Keypad8;
|
||||
case SDL_SCANCODE_KP_9: return ImGuiKey_Keypad9;
|
||||
case SDL_SCANCODE_KP_PERIOD: return ImGuiKey_KeypadDecimal;
|
||||
case SDL_SCANCODE_KP_DIVIDE: return ImGuiKey_KeypadDivide;
|
||||
case SDL_SCANCODE_KP_MULTIPLY: return ImGuiKey_KeypadMultiply;
|
||||
case SDL_SCANCODE_KP_MINUS: return ImGuiKey_KeypadSubtract;
|
||||
case SDL_SCANCODE_KP_PLUS: return ImGuiKey_KeypadAdd;
|
||||
case SDL_SCANCODE_KP_ENTER: return ImGuiKey_KeypadEnter;
|
||||
case SDL_SCANCODE_KP_EQUALS: return ImGuiKey_KeypadEqual;
|
||||
default: break;
|
||||
}
|
||||
switch (keycode)
|
||||
{
|
||||
case SDLK_TAB: return ImGuiKey_Tab;
|
||||
case SDLK_LEFT: return ImGuiKey_LeftArrow;
|
||||
case SDLK_RIGHT: return ImGuiKey_RightArrow;
|
||||
case SDLK_UP: return ImGuiKey_UpArrow;
|
||||
case SDLK_DOWN: return ImGuiKey_DownArrow;
|
||||
case SDLK_PAGEUP: return ImGuiKey_PageUp;
|
||||
case SDLK_PAGEDOWN: return ImGuiKey_PageDown;
|
||||
case SDLK_HOME: return ImGuiKey_Home;
|
||||
case SDLK_END: return ImGuiKey_End;
|
||||
case SDLK_INSERT: return ImGuiKey_Insert;
|
||||
case SDLK_DELETE: return ImGuiKey_Delete;
|
||||
case SDLK_BACKSPACE: return ImGuiKey_Backspace;
|
||||
case SDLK_SPACE: return ImGuiKey_Space;
|
||||
case SDLK_RETURN: return ImGuiKey_Enter;
|
||||
case SDLK_ESCAPE: return ImGuiKey_Escape;
|
||||
//case SDLK_APOSTROPHE: return ImGuiKey_Apostrophe;
|
||||
case SDLK_COMMA: return ImGuiKey_Comma;
|
||||
//case SDLK_MINUS: return ImGuiKey_Minus;
|
||||
case SDLK_PERIOD: return ImGuiKey_Period;
|
||||
//case SDLK_SLASH: return ImGuiKey_Slash;
|
||||
case SDLK_SEMICOLON: return ImGuiKey_Semicolon;
|
||||
//case SDLK_EQUALS: return ImGuiKey_Equal;
|
||||
//case SDLK_LEFTBRACKET: return ImGuiKey_LeftBracket;
|
||||
//case SDLK_BACKSLASH: return ImGuiKey_Backslash;
|
||||
//case SDLK_RIGHTBRACKET: return ImGuiKey_RightBracket;
|
||||
//case SDLK_GRAVE: return ImGuiKey_GraveAccent;
|
||||
case SDLK_CAPSLOCK: return ImGuiKey_CapsLock;
|
||||
case SDLK_SCROLLLOCK: return ImGuiKey_ScrollLock;
|
||||
case SDLK_NUMLOCKCLEAR: return ImGuiKey_NumLock;
|
||||
case SDLK_PRINTSCREEN: return ImGuiKey_PrintScreen;
|
||||
case SDLK_PAUSE: return ImGuiKey_Pause;
|
||||
case SDLK_LCTRL: return ImGuiKey_LeftCtrl;
|
||||
case SDLK_LSHIFT: return ImGuiKey_LeftShift;
|
||||
case SDLK_LALT: return ImGuiKey_LeftAlt;
|
||||
case SDLK_LGUI: return ImGuiKey_LeftSuper;
|
||||
case SDLK_RCTRL: return ImGuiKey_RightCtrl;
|
||||
case SDLK_RSHIFT: return ImGuiKey_RightShift;
|
||||
case SDLK_RALT: return ImGuiKey_RightAlt;
|
||||
case SDLK_RGUI: return ImGuiKey_RightSuper;
|
||||
case SDLK_APPLICATION: return ImGuiKey_Menu;
|
||||
case SDLK_0: return ImGuiKey_0;
|
||||
case SDLK_1: return ImGuiKey_1;
|
||||
case SDLK_2: return ImGuiKey_2;
|
||||
case SDLK_3: return ImGuiKey_3;
|
||||
case SDLK_4: return ImGuiKey_4;
|
||||
case SDLK_5: return ImGuiKey_5;
|
||||
case SDLK_6: return ImGuiKey_6;
|
||||
case SDLK_7: return ImGuiKey_7;
|
||||
case SDLK_8: return ImGuiKey_8;
|
||||
case SDLK_9: return ImGuiKey_9;
|
||||
case SDLK_A: return ImGuiKey_A;
|
||||
case SDLK_B: return ImGuiKey_B;
|
||||
case SDLK_C: return ImGuiKey_C;
|
||||
case SDLK_D: return ImGuiKey_D;
|
||||
case SDLK_E: return ImGuiKey_E;
|
||||
case SDLK_F: return ImGuiKey_F;
|
||||
case SDLK_G: return ImGuiKey_G;
|
||||
case SDLK_H: return ImGuiKey_H;
|
||||
case SDLK_I: return ImGuiKey_I;
|
||||
case SDLK_J: return ImGuiKey_J;
|
||||
case SDLK_K: return ImGuiKey_K;
|
||||
case SDLK_L: return ImGuiKey_L;
|
||||
case SDLK_M: return ImGuiKey_M;
|
||||
case SDLK_N: return ImGuiKey_N;
|
||||
case SDLK_O: return ImGuiKey_O;
|
||||
case SDLK_P: return ImGuiKey_P;
|
||||
case SDLK_Q: return ImGuiKey_Q;
|
||||
case SDLK_R: return ImGuiKey_R;
|
||||
case SDLK_S: return ImGuiKey_S;
|
||||
case SDLK_T: return ImGuiKey_T;
|
||||
case SDLK_U: return ImGuiKey_U;
|
||||
case SDLK_V: return ImGuiKey_V;
|
||||
case SDLK_W: return ImGuiKey_W;
|
||||
case SDLK_X: return ImGuiKey_X;
|
||||
case SDLK_Y: return ImGuiKey_Y;
|
||||
case SDLK_Z: return ImGuiKey_Z;
|
||||
case SDLK_F1: return ImGuiKey_F1;
|
||||
case SDLK_F2: return ImGuiKey_F2;
|
||||
case SDLK_F3: return ImGuiKey_F3;
|
||||
case SDLK_F4: return ImGuiKey_F4;
|
||||
case SDLK_F5: return ImGuiKey_F5;
|
||||
case SDLK_F6: return ImGuiKey_F6;
|
||||
case SDLK_F7: return ImGuiKey_F7;
|
||||
case SDLK_F8: return ImGuiKey_F8;
|
||||
case SDLK_F9: return ImGuiKey_F9;
|
||||
case SDLK_F10: return ImGuiKey_F10;
|
||||
case SDLK_F11: return ImGuiKey_F11;
|
||||
case SDLK_F12: return ImGuiKey_F12;
|
||||
case SDLK_F13: return ImGuiKey_F13;
|
||||
case SDLK_F14: return ImGuiKey_F14;
|
||||
case SDLK_F15: return ImGuiKey_F15;
|
||||
case SDLK_F16: return ImGuiKey_F16;
|
||||
case SDLK_F17: return ImGuiKey_F17;
|
||||
case SDLK_F18: return ImGuiKey_F18;
|
||||
case SDLK_F19: return ImGuiKey_F19;
|
||||
case SDLK_F20: return ImGuiKey_F20;
|
||||
case SDLK_F21: return ImGuiKey_F21;
|
||||
case SDLK_F22: return ImGuiKey_F22;
|
||||
case SDLK_F23: return ImGuiKey_F23;
|
||||
case SDLK_F24: return ImGuiKey_F24;
|
||||
case SDLK_AC_BACK: return ImGuiKey_AppBack;
|
||||
case SDLK_AC_FORWARD: return ImGuiKey_AppForward;
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Fallback to scancode
|
||||
switch (scancode)
|
||||
{
|
||||
case SDL_SCANCODE_GRAVE: return ImGuiKey_GraveAccent;
|
||||
case SDL_SCANCODE_MINUS: return ImGuiKey_Minus;
|
||||
case SDL_SCANCODE_EQUALS: return ImGuiKey_Equal;
|
||||
case SDL_SCANCODE_LEFTBRACKET: return ImGuiKey_LeftBracket;
|
||||
case SDL_SCANCODE_RIGHTBRACKET: return ImGuiKey_RightBracket;
|
||||
case SDL_SCANCODE_NONUSBACKSLASH: return ImGuiKey_Oem102;
|
||||
case SDL_SCANCODE_BACKSLASH: return ImGuiKey_Backslash;
|
||||
case SDL_SCANCODE_SEMICOLON: return ImGuiKey_Semicolon;
|
||||
case SDL_SCANCODE_APOSTROPHE: return ImGuiKey_Apostrophe;
|
||||
case SDL_SCANCODE_COMMA: return ImGuiKey_Comma;
|
||||
case SDL_SCANCODE_PERIOD: return ImGuiKey_Period;
|
||||
case SDL_SCANCODE_SLASH: return ImGuiKey_Slash;
|
||||
default: break;
|
||||
}
|
||||
return ImGuiKey_None;
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDL3_UpdateKeyModifiers(SDL_Keymod sdl_key_mods)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.AddKeyEvent(ImGuiMod_Ctrl, (sdl_key_mods & SDL_KMOD_CTRL) != 0);
|
||||
io.AddKeyEvent(ImGuiMod_Shift, (sdl_key_mods & SDL_KMOD_SHIFT) != 0);
|
||||
io.AddKeyEvent(ImGuiMod_Alt, (sdl_key_mods & SDL_KMOD_ALT) != 0);
|
||||
io.AddKeyEvent(ImGuiMod_Super, (sdl_key_mods & SDL_KMOD_GUI) != 0);
|
||||
}
|
||||
|
||||
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
|
||||
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
|
||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||
bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event)
|
||||
{
|
||||
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplSDL3_Init()?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case SDL_EVENT_MOUSE_MOTION:
|
||||
{
|
||||
if (ImGui_ImplSDL3_GetViewportForWindowID(event->motion.windowID) == nullptr)
|
||||
return false;
|
||||
ImVec2 mouse_pos((float)event->motion.x, (float)event->motion.y);
|
||||
io.AddMouseSourceEvent(event->motion.which == SDL_TOUCH_MOUSEID ? ImGuiMouseSource_TouchScreen : ImGuiMouseSource_Mouse);
|
||||
io.AddMousePosEvent(mouse_pos.x, mouse_pos.y);
|
||||
return true;
|
||||
}
|
||||
case SDL_EVENT_MOUSE_WHEEL:
|
||||
{
|
||||
if (ImGui_ImplSDL3_GetViewportForWindowID(event->wheel.windowID) == nullptr)
|
||||
return false;
|
||||
//IMGUI_DEBUG_LOG("wheel %.2f %.2f, precise %.2f %.2f\n", (float)event->wheel.x, (float)event->wheel.y, event->wheel.preciseX, event->wheel.preciseY);
|
||||
float wheel_x = -event->wheel.x;
|
||||
float wheel_y = event->wheel.y;
|
||||
io.AddMouseSourceEvent(event->wheel.which == SDL_TOUCH_MOUSEID ? ImGuiMouseSource_TouchScreen : ImGuiMouseSource_Mouse);
|
||||
io.AddMouseWheelEvent(wheel_x, wheel_y);
|
||||
return true;
|
||||
}
|
||||
case SDL_EVENT_MOUSE_BUTTON_DOWN:
|
||||
case SDL_EVENT_MOUSE_BUTTON_UP:
|
||||
{
|
||||
if (ImGui_ImplSDL3_GetViewportForWindowID(event->button.windowID) == nullptr)
|
||||
return false;
|
||||
int mouse_button = -1;
|
||||
if (event->button.button == SDL_BUTTON_LEFT) { mouse_button = 0; }
|
||||
if (event->button.button == SDL_BUTTON_RIGHT) { mouse_button = 1; }
|
||||
if (event->button.button == SDL_BUTTON_MIDDLE) { mouse_button = 2; }
|
||||
if (event->button.button == SDL_BUTTON_X1) { mouse_button = 3; }
|
||||
if (event->button.button == SDL_BUTTON_X2) { mouse_button = 4; }
|
||||
if (mouse_button == -1)
|
||||
break;
|
||||
io.AddMouseSourceEvent(event->button.which == SDL_TOUCH_MOUSEID ? ImGuiMouseSource_TouchScreen : ImGuiMouseSource_Mouse);
|
||||
io.AddMouseButtonEvent(mouse_button, (event->type == SDL_EVENT_MOUSE_BUTTON_DOWN));
|
||||
bd->MouseButtonsDown = (event->type == SDL_EVENT_MOUSE_BUTTON_DOWN) ? (bd->MouseButtonsDown | (1 << mouse_button)) : (bd->MouseButtonsDown & ~(1 << mouse_button));
|
||||
return true;
|
||||
}
|
||||
case SDL_EVENT_TEXT_INPUT:
|
||||
{
|
||||
if (ImGui_ImplSDL3_GetViewportForWindowID(event->text.windowID) == nullptr)
|
||||
return false;
|
||||
io.AddInputCharactersUTF8(event->text.text);
|
||||
return true;
|
||||
}
|
||||
case SDL_EVENT_KEY_DOWN:
|
||||
case SDL_EVENT_KEY_UP:
|
||||
{
|
||||
if (ImGui_ImplSDL3_GetViewportForWindowID(event->key.windowID) == nullptr)
|
||||
return false;
|
||||
ImGui_ImplSDL3_UpdateKeyModifiers((SDL_Keymod)event->key.mod);
|
||||
//IMGUI_DEBUG_LOG("SDL_EVENT_KEY_%s : key=%d ('%s'), scancode=%d ('%s'), mod=%X\n",
|
||||
// (event->type == SDL_EVENT_KEY_DOWN) ? "DOWN" : "UP ", event->key.key, SDL_GetKeyName(event->key.key), event->key.scancode, SDL_GetScancodeName(event->key.scancode), event->key.mod);
|
||||
ImGuiKey key = ImGui_ImplSDL3_KeyEventToImGuiKey(event->key.key, event->key.scancode);
|
||||
io.AddKeyEvent(key, (event->type == SDL_EVENT_KEY_DOWN));
|
||||
io.SetKeyEventNativeData(key, (int)event->key.key, (int)event->key.scancode, (int)event->key.scancode); // To support legacy indexing (<1.87 user code). Legacy backend uses SDLK_*** as indices to IsKeyXXX() functions.
|
||||
return true;
|
||||
}
|
||||
case SDL_EVENT_WINDOW_MOUSE_ENTER:
|
||||
{
|
||||
if (ImGui_ImplSDL3_GetViewportForWindowID(event->window.windowID) == nullptr)
|
||||
return false;
|
||||
bd->MouseWindowID = event->window.windowID;
|
||||
bd->MousePendingLeaveFrame = 0;
|
||||
return true;
|
||||
}
|
||||
// - In some cases, when detaching a window from main viewport SDL may send SDL_WINDOWEVENT_ENTER one frame too late,
|
||||
// causing SDL_WINDOWEVENT_LEAVE on previous frame to interrupt drag operation by clear mouse position. This is why
|
||||
// we delay process the SDL_WINDOWEVENT_LEAVE events by one frame. See issue #5012 for details.
|
||||
// FIXME: Unconfirmed whether this is still needed with SDL3.
|
||||
case SDL_EVENT_WINDOW_MOUSE_LEAVE:
|
||||
{
|
||||
if (ImGui_ImplSDL3_GetViewportForWindowID(event->window.windowID) == nullptr)
|
||||
return false;
|
||||
bd->MousePendingLeaveFrame = ImGui::GetFrameCount() + 1;
|
||||
return true;
|
||||
}
|
||||
case SDL_EVENT_WINDOW_FOCUS_GAINED:
|
||||
case SDL_EVENT_WINDOW_FOCUS_LOST:
|
||||
{
|
||||
if (ImGui_ImplSDL3_GetViewportForWindowID(event->window.windowID) == nullptr)
|
||||
return false;
|
||||
io.AddFocusEvent(event->type == SDL_EVENT_WINDOW_FOCUS_GAINED);
|
||||
return true;
|
||||
}
|
||||
case SDL_EVENT_GAMEPAD_ADDED:
|
||||
case SDL_EVENT_GAMEPAD_REMOVED:
|
||||
{
|
||||
bd->WantUpdateGamepadsList = true;
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDL3_SetupPlatformHandles(ImGuiViewport* viewport, SDL_Window* window)
|
||||
{
|
||||
viewport->PlatformHandle = (void*)(intptr_t)SDL_GetWindowID(window);
|
||||
viewport->PlatformHandleRaw = nullptr;
|
||||
#if defined(_WIN32) && !defined(__WINRT__)
|
||||
viewport->PlatformHandleRaw = (HWND)SDL_GetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_WIN32_HWND_POINTER, nullptr);
|
||||
#elif defined(__APPLE__)
|
||||
viewport->PlatformHandleRaw = SDL_GetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_COCOA_WINDOW_POINTER, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer, void* sdl_gl_context)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IMGUI_CHECKVERSION();
|
||||
IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!");
|
||||
IM_UNUSED(sdl_gl_context); // Unused in this branch
|
||||
//SDL_SetHint(SDL_HINT_EVENT_LOGGING, "2");
|
||||
|
||||
const int ver_linked = SDL_GetVersion();
|
||||
|
||||
// Setup backend capabilities flags
|
||||
ImGui_ImplSDL3_Data* bd = IM_NEW(ImGui_ImplSDL3_Data)();
|
||||
snprintf(bd->BackendPlatformName, sizeof(bd->BackendPlatformName), "imgui_impl_sdl3 (%d.%d.%d; %d.%d.%d)",
|
||||
SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_MICRO_VERSION, SDL_VERSIONNUM_MAJOR(ver_linked), SDL_VERSIONNUM_MINOR(ver_linked), SDL_VERSIONNUM_MICRO(ver_linked));
|
||||
io.BackendPlatformUserData = (void*)bd;
|
||||
io.BackendPlatformName = bd->BackendPlatformName;
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
|
||||
|
||||
bd->Window = window;
|
||||
bd->WindowID = SDL_GetWindowID(window);
|
||||
bd->Renderer = renderer;
|
||||
|
||||
// Check and store if we are on a SDL backend that supports SDL_GetGlobalMouseState() and SDL_CaptureMouse()
|
||||
// ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list)
|
||||
bd->MouseCanUseGlobalState = false;
|
||||
bd->MouseCaptureMode = ImGui_ImplSDL3_MouseCaptureMode_Disabled;
|
||||
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
|
||||
const char* sdl_backend = SDL_GetCurrentVideoDriver();
|
||||
const char* capture_and_global_state_whitelist[] = { "windows", "cocoa", "x11", "DIVE", "VMAN" };
|
||||
for (const char* item : capture_and_global_state_whitelist)
|
||||
if (strncmp(sdl_backend, item, strlen(item)) == 0)
|
||||
{
|
||||
bd->MouseCanUseGlobalState = true;
|
||||
bd->MouseCaptureMode = (strcmp(item, "x11") == 0) ? ImGui_ImplSDL3_MouseCaptureMode_EnabledAfterDrag : ImGui_ImplSDL3_MouseCaptureMode_Enabled;
|
||||
}
|
||||
#endif
|
||||
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
platform_io.Platform_SetClipboardTextFn = ImGui_ImplSDL3_SetClipboardText;
|
||||
platform_io.Platform_GetClipboardTextFn = ImGui_ImplSDL3_GetClipboardText;
|
||||
platform_io.Platform_SetImeDataFn = ImGui_ImplSDL3_PlatformSetImeData;
|
||||
platform_io.Platform_OpenInShellFn = [](ImGuiContext*, const char* url) { return SDL_OpenURL(url); };
|
||||
|
||||
// Gamepad handling
|
||||
bd->GamepadMode = ImGui_ImplSDL3_GamepadMode_AutoFirst;
|
||||
bd->WantUpdateGamepadsList = true;
|
||||
|
||||
// Load mouse cursors
|
||||
bd->MouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_DEFAULT);
|
||||
bd->MouseCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_TEXT);
|
||||
bd->MouseCursors[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_MOVE);
|
||||
bd->MouseCursors[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NS_RESIZE);
|
||||
bd->MouseCursors[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_EW_RESIZE);
|
||||
bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NESW_RESIZE);
|
||||
bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NWSE_RESIZE);
|
||||
bd->MouseCursors[ImGuiMouseCursor_Hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_POINTER);
|
||||
bd->MouseCursors[ImGuiMouseCursor_Wait] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_WAIT);
|
||||
bd->MouseCursors[ImGuiMouseCursor_Progress] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_PROGRESS);
|
||||
bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NOT_ALLOWED);
|
||||
|
||||
// Set platform dependent data in viewport
|
||||
// Our mouse update function expect PlatformHandle to be filled for the main viewport
|
||||
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
|
||||
ImGui_ImplSDL3_SetupPlatformHandles(main_viewport, window);
|
||||
|
||||
// From 2.0.5: Set SDL hint to receive mouse click events on window focus, otherwise SDL doesn't emit the event.
|
||||
// Without this, when clicking to gain focus, our widgets wouldn't activate even though they showed as hovered.
|
||||
// (This is unfortunately a global SDL setting, so enabling it might have a side-effect on your application.
|
||||
// It is unlikely to make a difference, but if your app absolutely needs to ignore the initial on-focus click:
|
||||
// you can ignore SDL_EVENT_MOUSE_BUTTON_DOWN events coming right after a SDL_EVENT_WINDOW_FOCUS_GAINED)
|
||||
SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
|
||||
|
||||
// From 2.0.22: Disable auto-capture, this is preventing drag and drop across multiple windows (see #5710)
|
||||
SDL_SetHint(SDL_HINT_MOUSE_AUTO_CAPTURE, "0");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Should technically be a SDL_GLContext but due to typedef it is sane to keep it void* in public interface.
|
||||
bool ImGui_ImplSDL3_InitForOpenGL(SDL_Window* window, void* sdl_gl_context)
|
||||
{
|
||||
return ImGui_ImplSDL3_Init(window, nullptr, sdl_gl_context);
|
||||
}
|
||||
|
||||
bool ImGui_ImplSDL3_InitForVulkan(SDL_Window* window)
|
||||
{
|
||||
return ImGui_ImplSDL3_Init(window, nullptr, nullptr);
|
||||
}
|
||||
|
||||
bool ImGui_ImplSDL3_InitForD3D(SDL_Window* window)
|
||||
{
|
||||
#if !defined(_WIN32)
|
||||
IM_ASSERT(0 && "Unsupported");
|
||||
#endif
|
||||
return ImGui_ImplSDL3_Init(window, nullptr, nullptr);
|
||||
}
|
||||
|
||||
bool ImGui_ImplSDL3_InitForMetal(SDL_Window* window)
|
||||
{
|
||||
return ImGui_ImplSDL3_Init(window, nullptr, nullptr);
|
||||
}
|
||||
|
||||
bool ImGui_ImplSDL3_InitForSDLRenderer(SDL_Window* window, SDL_Renderer* renderer)
|
||||
{
|
||||
return ImGui_ImplSDL3_Init(window, renderer, nullptr);
|
||||
}
|
||||
|
||||
bool ImGui_ImplSDL3_InitForSDLGPU(SDL_Window* window)
|
||||
{
|
||||
return ImGui_ImplSDL3_Init(window, nullptr, nullptr);
|
||||
}
|
||||
|
||||
bool ImGui_ImplSDL3_InitForOther(SDL_Window* window)
|
||||
{
|
||||
return ImGui_ImplSDL3_Init(window, nullptr, nullptr);
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDL3_CloseGamepads();
|
||||
|
||||
void ImGui_ImplSDL3_Shutdown()
|
||||
{
|
||||
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
if (bd->ClipboardTextData)
|
||||
SDL_free(bd->ClipboardTextData);
|
||||
for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
|
||||
SDL_DestroyCursor(bd->MouseCursors[cursor_n]);
|
||||
ImGui_ImplSDL3_CloseGamepads();
|
||||
|
||||
io.BackendPlatformName = nullptr;
|
||||
io.BackendPlatformUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasSetMousePos | ImGuiBackendFlags_HasGamepad);
|
||||
platform_io.ClearPlatformHandlers();
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
void ImGui_ImplSDL3_SetMouseCaptureMode(ImGui_ImplSDL3_MouseCaptureMode mode)
|
||||
{
|
||||
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
|
||||
if (mode == ImGui_ImplSDL3_MouseCaptureMode_Disabled && bd->MouseCaptureMode != ImGui_ImplSDL3_MouseCaptureMode_Disabled)
|
||||
SDL_CaptureMouse(false);
|
||||
bd->MouseCaptureMode = mode;
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDL3_UpdateMouseData()
|
||||
{
|
||||
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
// We forward mouse input when hovered or captured (via SDL_EVENT_MOUSE_MOTION) or when focused (below)
|
||||
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
|
||||
// - SDL_CaptureMouse() let the OS know e.g. that our drags can extend outside of parent boundaries (we want updated position) and shouldn't trigger other operations outside.
|
||||
// - Debuggers under Linux tends to leave captured mouse on break, which may be very inconvenient, so to mitigate the issue on X11 we we wait until mouse has moved to begin capture.
|
||||
if (bd->MouseCaptureMode == ImGui_ImplSDL3_MouseCaptureMode_Enabled)
|
||||
{
|
||||
SDL_CaptureMouse(bd->MouseButtonsDown != 0);
|
||||
}
|
||||
else if (bd->MouseCaptureMode == ImGui_ImplSDL3_MouseCaptureMode_EnabledAfterDrag)
|
||||
{
|
||||
bool want_capture = false;
|
||||
for (int button_n = 0; button_n < ImGuiMouseButton_COUNT && !want_capture; button_n++)
|
||||
if (ImGui::IsMouseDragging(button_n, 1.0f))
|
||||
want_capture = true;
|
||||
SDL_CaptureMouse(want_capture);
|
||||
}
|
||||
|
||||
SDL_Window* focused_window = SDL_GetKeyboardFocus();
|
||||
const bool is_app_focused = (bd->Window == focused_window);
|
||||
#else
|
||||
SDL_Window* focused_window = bd->Window;
|
||||
const bool is_app_focused = (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_INPUT_FOCUS) != 0; // SDL 2.0.3 and non-windowed systems: single-viewport only
|
||||
#endif
|
||||
if (is_app_focused)
|
||||
{
|
||||
// (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when io.ConfigNavMoveSetMousePos is enabled by user)
|
||||
if (io.WantSetMousePos)
|
||||
SDL_WarpMouseInWindow(bd->Window, io.MousePos.x, io.MousePos.y);
|
||||
|
||||
// (Optional) Fallback to provide unclamped mouse position when focused but not hovered (SDL_EVENT_MOUSE_MOTION already provides this when hovered or captured)
|
||||
// Note that SDL_GetGlobalMouseState() is in theory slow on X11, but this only runs on rather specific cases. If a problem we may provide a way to opt-out this feature.
|
||||
SDL_Window* hovered_window = SDL_GetMouseFocus();
|
||||
const bool is_relative_mouse_mode = SDL_GetWindowRelativeMouseMode(bd->Window);
|
||||
if (hovered_window == nullptr && bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0 && !is_relative_mouse_mode)
|
||||
{
|
||||
// Single-viewport mode: mouse position in client window coordinates (io.MousePos is (0,0) when the mouse is on the upper-left corner of the app window)
|
||||
float mouse_x, mouse_y;
|
||||
int window_x, window_y;
|
||||
SDL_GetGlobalMouseState(&mouse_x, &mouse_y);
|
||||
SDL_GetWindowPosition(focused_window, &window_x, &window_y);
|
||||
mouse_x -= (float)window_x;
|
||||
mouse_y -= (float)window_y;
|
||||
io.AddMousePosEvent(mouse_x, mouse_y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDL3_UpdateMouseCursor()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
|
||||
return;
|
||||
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
|
||||
|
||||
ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
|
||||
if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None)
|
||||
{
|
||||
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
|
||||
SDL_HideCursor();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Show OS mouse cursor
|
||||
SDL_Cursor* expected_cursor = bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow];
|
||||
if (bd->MouseLastCursor != expected_cursor)
|
||||
{
|
||||
SDL_SetCursor(expected_cursor); // SDL function doesn't have an early out (see #6113)
|
||||
bd->MouseLastCursor = expected_cursor;
|
||||
}
|
||||
SDL_ShowCursor();
|
||||
}
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDL3_CloseGamepads()
|
||||
{
|
||||
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
|
||||
if (bd->GamepadMode != ImGui_ImplSDL3_GamepadMode_Manual)
|
||||
for (SDL_Gamepad* gamepad : bd->Gamepads)
|
||||
SDL_CloseGamepad(gamepad);
|
||||
bd->Gamepads.resize(0);
|
||||
}
|
||||
|
||||
void ImGui_ImplSDL3_SetGamepadMode(ImGui_ImplSDL3_GamepadMode mode, SDL_Gamepad** manual_gamepads_array, int manual_gamepads_count)
|
||||
{
|
||||
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
|
||||
ImGui_ImplSDL3_CloseGamepads();
|
||||
if (mode == ImGui_ImplSDL3_GamepadMode_Manual)
|
||||
{
|
||||
IM_ASSERT(manual_gamepads_array != nullptr || manual_gamepads_count <= 0);
|
||||
for (int n = 0; n < manual_gamepads_count; n++)
|
||||
bd->Gamepads.push_back(manual_gamepads_array[n]);
|
||||
}
|
||||
else
|
||||
{
|
||||
IM_ASSERT(manual_gamepads_array == nullptr && manual_gamepads_count <= 0);
|
||||
bd->WantUpdateGamepadsList = true;
|
||||
}
|
||||
bd->GamepadMode = mode;
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDL3_UpdateGamepadButton(ImGui_ImplSDL3_Data* bd, ImGuiIO& io, ImGuiKey key, SDL_GamepadButton button_no)
|
||||
{
|
||||
bool merged_value = false;
|
||||
for (SDL_Gamepad* gamepad : bd->Gamepads)
|
||||
merged_value |= SDL_GetGamepadButton(gamepad, button_no) != 0;
|
||||
io.AddKeyEvent(key, merged_value);
|
||||
}
|
||||
|
||||
static inline float Saturate(float v) { return v < 0.0f ? 0.0f : v > 1.0f ? 1.0f : v; }
|
||||
static void ImGui_ImplSDL3_UpdateGamepadAnalog(ImGui_ImplSDL3_Data* bd, ImGuiIO& io, ImGuiKey key, SDL_GamepadAxis axis_no, float v0, float v1)
|
||||
{
|
||||
float merged_value = 0.0f;
|
||||
for (SDL_Gamepad* gamepad : bd->Gamepads)
|
||||
{
|
||||
float vn = Saturate((float)(SDL_GetGamepadAxis(gamepad, axis_no) - v0) / (float)(v1 - v0));
|
||||
if (merged_value < vn)
|
||||
merged_value = vn;
|
||||
}
|
||||
io.AddKeyAnalogEvent(key, merged_value > 0.1f, merged_value);
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDL3_UpdateGamepads()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
|
||||
|
||||
// Update list of gamepads to use
|
||||
if (bd->WantUpdateGamepadsList && bd->GamepadMode != ImGui_ImplSDL3_GamepadMode_Manual)
|
||||
{
|
||||
ImGui_ImplSDL3_CloseGamepads();
|
||||
int sdl_gamepads_count = 0;
|
||||
SDL_JoystickID* sdl_gamepads = SDL_GetGamepads(&sdl_gamepads_count);
|
||||
for (int n = 0; n < sdl_gamepads_count; n++)
|
||||
if (SDL_Gamepad* gamepad = SDL_OpenGamepad(sdl_gamepads[n]))
|
||||
{
|
||||
bd->Gamepads.push_back(gamepad);
|
||||
if (bd->GamepadMode == ImGui_ImplSDL3_GamepadMode_AutoFirst)
|
||||
break;
|
||||
}
|
||||
bd->WantUpdateGamepadsList = false;
|
||||
SDL_free(sdl_gamepads);
|
||||
}
|
||||
|
||||
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
|
||||
if (bd->Gamepads.Size == 0)
|
||||
return;
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
|
||||
|
||||
// Update gamepad inputs
|
||||
const int thumb_dead_zone = 8000; // SDL_gamepad.h suggests using this value.
|
||||
ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadStart, SDL_GAMEPAD_BUTTON_START);
|
||||
ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadBack, SDL_GAMEPAD_BUTTON_BACK);
|
||||
ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceLeft, SDL_GAMEPAD_BUTTON_WEST); // Xbox X, PS Square
|
||||
ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceRight, SDL_GAMEPAD_BUTTON_EAST); // Xbox B, PS Circle
|
||||
ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceUp, SDL_GAMEPAD_BUTTON_NORTH); // Xbox Y, PS Triangle
|
||||
ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceDown, SDL_GAMEPAD_BUTTON_SOUTH); // Xbox A, PS Cross
|
||||
ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadLeft, SDL_GAMEPAD_BUTTON_DPAD_LEFT);
|
||||
ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadRight, SDL_GAMEPAD_BUTTON_DPAD_RIGHT);
|
||||
ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadUp, SDL_GAMEPAD_BUTTON_DPAD_UP);
|
||||
ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadDown, SDL_GAMEPAD_BUTTON_DPAD_DOWN);
|
||||
ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadL1, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER);
|
||||
ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadR1, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER);
|
||||
ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadL2, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, 0.0f, 32767);
|
||||
ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadR2, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, 0.0f, 32767);
|
||||
ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadL3, SDL_GAMEPAD_BUTTON_LEFT_STICK);
|
||||
ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadR3, SDL_GAMEPAD_BUTTON_RIGHT_STICK);
|
||||
ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickLeft, SDL_GAMEPAD_AXIS_LEFTX, -thumb_dead_zone, -32768);
|
||||
ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickRight, SDL_GAMEPAD_AXIS_LEFTX, +thumb_dead_zone, +32767);
|
||||
ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickUp, SDL_GAMEPAD_AXIS_LEFTY, -thumb_dead_zone, -32768);
|
||||
ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickDown, SDL_GAMEPAD_AXIS_LEFTY, +thumb_dead_zone, +32767);
|
||||
ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickLeft, SDL_GAMEPAD_AXIS_RIGHTX, -thumb_dead_zone, -32768);
|
||||
ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickRight, SDL_GAMEPAD_AXIS_RIGHTX, +thumb_dead_zone, +32767);
|
||||
ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickUp, SDL_GAMEPAD_AXIS_RIGHTY, -thumb_dead_zone, -32768);
|
||||
ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickDown, SDL_GAMEPAD_AXIS_RIGHTY, +thumb_dead_zone, +32767);
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDL3_GetWindowSizeAndFramebufferScale(SDL_Window* window, ImVec2* out_size, ImVec2* out_framebuffer_scale)
|
||||
{
|
||||
int w, h;
|
||||
SDL_GetWindowSize(window, &w, &h);
|
||||
if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED)
|
||||
w = h = 0;
|
||||
|
||||
#if defined(__APPLE__)
|
||||
float fb_scale_x = SDL_GetWindowDisplayScale(window); // Seems more reliable during resolution change (#8703)
|
||||
float fb_scale_y = fb_scale_x;
|
||||
#else
|
||||
int display_w, display_h;
|
||||
SDL_GetWindowSizeInPixels(window, &display_w, &display_h);
|
||||
float fb_scale_x = (w > 0) ? (float)display_w / (float)w : 1.0f;
|
||||
float fb_scale_y = (h > 0) ? (float)display_h / (float)h : 1.0f;
|
||||
#endif
|
||||
|
||||
if (out_size != nullptr)
|
||||
*out_size = ImVec2((float)w, (float)h);
|
||||
if (out_framebuffer_scale != nullptr)
|
||||
*out_framebuffer_scale = ImVec2(fb_scale_x, fb_scale_y);
|
||||
}
|
||||
|
||||
void ImGui_ImplSDL3_NewFrame()
|
||||
{
|
||||
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplSDL3_Init()?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
// Setup main viewport size (every frame to accommodate for window resizing)
|
||||
ImGui_ImplSDL3_GetWindowSizeAndFramebufferScale(bd->Window, &io.DisplaySize, &io.DisplayFramebufferScale);
|
||||
|
||||
// Setup time step (we could also use SDL_GetTicksNS() available since SDL3)
|
||||
// (Accept SDL_GetPerformanceCounter() not returning a monotonically increasing value. Happens in VMs and Emscripten, see #6189, #6114, #3644)
|
||||
static Uint64 frequency = SDL_GetPerformanceFrequency();
|
||||
Uint64 current_time = SDL_GetPerformanceCounter();
|
||||
if (current_time <= bd->Time)
|
||||
current_time = bd->Time + 1;
|
||||
io.DeltaTime = bd->Time > 0 ? (float)((double)(current_time - bd->Time) / (double)frequency) : (float)(1.0f / 60.0f);
|
||||
bd->Time = current_time;
|
||||
|
||||
if (bd->MousePendingLeaveFrame && bd->MousePendingLeaveFrame >= ImGui::GetFrameCount() && bd->MouseButtonsDown == 0)
|
||||
{
|
||||
bd->MouseWindowID = 0;
|
||||
bd->MousePendingLeaveFrame = 0;
|
||||
io.AddMousePosEvent(-FLT_MAX, -FLT_MAX);
|
||||
}
|
||||
|
||||
ImGui_ImplSDL3_UpdateMouseData();
|
||||
ImGui_ImplSDL3_UpdateMouseCursor();
|
||||
ImGui_ImplSDL3_UpdateIme();
|
||||
|
||||
// Update game controllers (if enabled and available)
|
||||
ImGui_ImplSDL3_UpdateGamepads();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
54
backends/imgui_impl_sdl3.h
Normal file
54
backends/imgui_impl_sdl3.h
Normal file
@@ -0,0 +1,54 @@
|
||||
// dear imgui: Platform Backend for SDL3
|
||||
// This needs to be used along with a Renderer (e.g. SDL_GPU, DirectX11, OpenGL3, Vulkan..)
|
||||
// (Info: SDL3 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Platform: Clipboard support.
|
||||
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen.
|
||||
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values are obsolete since 1.87 and not supported since 1.91.5]
|
||||
// [X] Platform: Gamepad support.
|
||||
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
// [X] Platform: IME support.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
#pragma once
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
struct SDL_Window;
|
||||
struct SDL_Renderer;
|
||||
struct SDL_Gamepad;
|
||||
typedef union SDL_Event SDL_Event;
|
||||
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
IMGUI_IMPL_API bool ImGui_ImplSDL3_InitForOpenGL(SDL_Window* window, void* sdl_gl_context);
|
||||
IMGUI_IMPL_API bool ImGui_ImplSDL3_InitForVulkan(SDL_Window* window);
|
||||
IMGUI_IMPL_API bool ImGui_ImplSDL3_InitForD3D(SDL_Window* window);
|
||||
IMGUI_IMPL_API bool ImGui_ImplSDL3_InitForMetal(SDL_Window* window);
|
||||
IMGUI_IMPL_API bool ImGui_ImplSDL3_InitForSDLRenderer(SDL_Window* window, SDL_Renderer* renderer);
|
||||
IMGUI_IMPL_API bool ImGui_ImplSDL3_InitForSDLGPU(SDL_Window* window);
|
||||
IMGUI_IMPL_API bool ImGui_ImplSDL3_InitForOther(SDL_Window* window);
|
||||
IMGUI_IMPL_API void ImGui_ImplSDL3_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplSDL3_NewFrame();
|
||||
IMGUI_IMPL_API bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event);
|
||||
|
||||
// Gamepad selection automatically starts in AutoFirst mode, picking first available SDL_Gamepad. You may override this.
|
||||
// When using manual mode, caller is responsible for opening/closing gamepad.
|
||||
enum ImGui_ImplSDL3_GamepadMode { ImGui_ImplSDL3_GamepadMode_AutoFirst, ImGui_ImplSDL3_GamepadMode_AutoAll, ImGui_ImplSDL3_GamepadMode_Manual };
|
||||
IMGUI_IMPL_API void ImGui_ImplSDL3_SetGamepadMode(ImGui_ImplSDL3_GamepadMode mode, SDL_Gamepad** manual_gamepads_array = nullptr, int manual_gamepads_count = -1);
|
||||
|
||||
// (Advanced, for X11 users) Override Mouse Capture mode. Mouse capture allows receiving updated mouse position after clicking inside our window and dragging outside it.
|
||||
// Having this 'Enabled' is in theory always better. But, on X11 if you crash/break to debugger while capture is active you may temporarily lose access to your mouse.
|
||||
// The best solution is to setup your debugger to automatically release capture, e.g. 'setxkbmap -option grab:break_actions && xdotool key XF86Ungrab' or via a GDB script. See #3650.
|
||||
// But you may independently decide on X11, when a debugger is attached, to set this value to ImGui_ImplSDL3_MouseCaptureMode_Disabled.
|
||||
enum ImGui_ImplSDL3_MouseCaptureMode { ImGui_ImplSDL3_MouseCaptureMode_Enabled, ImGui_ImplSDL3_MouseCaptureMode_EnabledAfterDrag, ImGui_ImplSDL3_MouseCaptureMode_Disabled };
|
||||
IMGUI_IMPL_API void ImGui_ImplSDL3_SetMouseCaptureMode(ImGui_ImplSDL3_MouseCaptureMode mode);
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
706
backends/imgui_impl_sdlgpu3.cpp
Normal file
706
backends/imgui_impl_sdlgpu3.cpp
Normal file
@@ -0,0 +1,706 @@
|
||||
// dear imgui: Renderer Backend for SDL_GPU
|
||||
// This needs to be used along with the SDL3 Platform Backend
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'SDL_GPUTexture*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef! **IMPORTANT** Before 2025/08/08, ImTextureID was a reference to a SDL_GPUTextureSamplerBinding struct.
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
|
||||
// The aim of imgui_impl_sdlgpu3.h/.cpp is to be usable in your engine without any modification.
|
||||
// IF YOU FEEL YOU NEED TO MAKE ANY CHANGE TO THIS CODE, please share them and your feedback at https://github.com/ocornut/imgui/
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
// Important note to the reader who wish to integrate imgui_impl_sdlgpu3.cpp/.h in their own engine/app.
|
||||
// - Unlike other backends, the user must call the function ImGui_ImplSDLGPU3_PrepareDrawData() BEFORE issuing a SDL_GPURenderPass containing ImGui_ImplSDLGPU3_RenderDrawData.
|
||||
// Calling the function is MANDATORY, otherwise the ImGui will not upload neither the vertex nor the index buffer for the GPU. See imgui_impl_sdlgpu3.cpp for more info.
|
||||
|
||||
// CHANGELOG
|
||||
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. Obsoleting samplers from ImGui_ImplSDLGPU3_RenderState. (#9378)
|
||||
// 2026-03-19: Fixed issue in ImGui_ImplSDLGPU3_DestroyTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295, #9310)
|
||||
// 2026-02-25: Removed unnecessary call to SDL_WaitForGPUIdle when releasing vertex/index buffers. (#9262)
|
||||
// 2025-11-26: macOS version can use MSL shaders in order to support macOS 10.14+ (vs Metallib shaders requiring macOS 14+). Requires calling SDL_CreateGPUDevice() with SDL_GPU_SHADERFORMAT_MSL.
|
||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||
// 2025-08-20: Added ImGui_ImplSDLGPU3_InitInfo::SwapchainComposition and ImGui_ImplSDLGPU3_InitInfo::PresentMode to configure how secondary viewports are created.
|
||||
// 2025-08-08: *BREAKING* Changed ImTextureID type from SDL_GPUTextureSamplerBinding* to SDL_GPUTexture*, which is more natural and easier for user to manage. If you need to change the current sampler, you can access the ImGui_ImplSDLGPU3_RenderState struct. (#8866, #8163, #7998, #7988)
|
||||
// 2025-08-08: Expose SamplerDefault and SamplerCurrent in ImGui_ImplSDLGPU3_RenderState. Allow callback to change sampler.
|
||||
// 2025-06-25: Mapping transfer buffer for texture update use cycle=true. Fixes artifacts e.g. on Metal backend.
|
||||
// 2025-06-11: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplSDLGPU3_CreateFontsTexture() and ImGui_ImplSDLGPU3_DestroyFontsTexture().
|
||||
// 2025-04-28: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
|
||||
// 2025-03-30: Made ImGui_ImplSDLGPU3_PrepareDrawData() reuse GPU Transfer Buffers which were unusually slow to recreate every frame. Much faster now.
|
||||
// 2025-03-21: Fixed typo in function name Imgui_ImplSDLGPU3_PrepareDrawData() -> ImGui_ImplSDLGPU3_PrepareDrawData().
|
||||
// 2025-01-16: Renamed ImGui_ImplSDLGPU3_InitInfo::GpuDevice to Device.
|
||||
// 2025-01-09: SDL_GPU: Added the SDL_GPU3 backend.
|
||||
|
||||
#include "imgui.h"
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include "imgui_impl_sdlgpu3.h"
|
||||
#include "imgui_impl_sdlgpu3_shaders.h"
|
||||
|
||||
// SDL_GPU Data
|
||||
|
||||
// Reusable buffers used for rendering 1 current in-flight frame, for ImGui_ImplSDLGPU3_RenderDrawData()
|
||||
struct ImGui_ImplSDLGPU3_FrameData
|
||||
{
|
||||
SDL_GPUBuffer* VertexBuffer = nullptr;
|
||||
SDL_GPUTransferBuffer* VertexTransferBuffer = nullptr;
|
||||
uint32_t VertexBufferSize = 0;
|
||||
SDL_GPUBuffer* IndexBuffer = nullptr;
|
||||
SDL_GPUTransferBuffer* IndexTransferBuffer = nullptr;
|
||||
uint32_t IndexBufferSize = 0;
|
||||
};
|
||||
|
||||
struct ImGui_ImplSDLGPU3_Data
|
||||
{
|
||||
ImGui_ImplSDLGPU3_InitInfo InitInfo;
|
||||
|
||||
// Render state
|
||||
ImGui_ImplSDLGPU3_RenderState* RenderState = nullptr; // == ImGui::GetPlatformIO().Renderer_RenderState during rendering.
|
||||
SDL_GPUSampler* CurrentSampler = nullptr;
|
||||
|
||||
// Graphics pipeline & shaders
|
||||
SDL_GPUShader* VertexShader = nullptr;
|
||||
SDL_GPUShader* FragmentShader = nullptr;
|
||||
SDL_GPUGraphicsPipeline* Pipeline = nullptr;
|
||||
SDL_GPUSampler* TexSamplerLinear = nullptr;
|
||||
SDL_GPUSampler* TexSamplerNearest = nullptr;
|
||||
SDL_GPUTransferBuffer* TexTransferBuffer = nullptr;
|
||||
uint32_t TexTransferBufferSize = 0;
|
||||
|
||||
// Frame data for main window
|
||||
ImGui_ImplSDLGPU3_FrameData MainWindowFrameData;
|
||||
};
|
||||
|
||||
// Forward Declarations
|
||||
static void ImGui_ImplSDLGPU3_DestroyFrameData();
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// FUNCTIONS
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
|
||||
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
|
||||
// FIXME: multi-context support has never been tested.
|
||||
static ImGui_ImplSDLGPU3_Data* ImGui_ImplSDLGPU3_GetBackendData()
|
||||
{
|
||||
return ImGui::GetCurrentContext() ? (ImGui_ImplSDLGPU3_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDLGPU3_SetupRenderState(ImDrawData* draw_data, SDL_GPUGraphicsPipeline* pipeline, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, ImGui_ImplSDLGPU3_FrameData* fd, uint32_t fb_width, uint32_t fb_height)
|
||||
{
|
||||
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
|
||||
bd->CurrentSampler = bd->TexSamplerLinear;
|
||||
|
||||
// Bind graphics pipeline
|
||||
SDL_BindGPUGraphicsPipeline(render_pass, pipeline);
|
||||
|
||||
// Bind Vertex And Index Buffers
|
||||
if (draw_data->TotalVtxCount > 0)
|
||||
{
|
||||
SDL_GPUBufferBinding vertex_buffer_binding = {};
|
||||
vertex_buffer_binding.buffer = fd->VertexBuffer;
|
||||
vertex_buffer_binding.offset = 0;
|
||||
SDL_GPUBufferBinding index_buffer_binding = {};
|
||||
index_buffer_binding.buffer = fd->IndexBuffer;
|
||||
index_buffer_binding.offset = 0;
|
||||
SDL_BindGPUVertexBuffers(render_pass,0, &vertex_buffer_binding, 1);
|
||||
SDL_BindGPUIndexBuffer(render_pass, &index_buffer_binding, sizeof(ImDrawIdx) == 2 ? SDL_GPU_INDEXELEMENTSIZE_16BIT : SDL_GPU_INDEXELEMENTSIZE_32BIT);
|
||||
}
|
||||
|
||||
// Setup viewport
|
||||
SDL_GPUViewport viewport = {};
|
||||
viewport.x = 0;
|
||||
viewport.y = 0;
|
||||
viewport.w = (float)fb_width;
|
||||
viewport.h = (float)fb_height;
|
||||
viewport.min_depth = 0.0f;
|
||||
viewport.max_depth = 1.0f;
|
||||
SDL_SetGPUViewport(render_pass, &viewport);
|
||||
|
||||
// Setup scale and translation
|
||||
// Our visible imgui space lies from draw_data->DisplayPps (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
|
||||
struct UBO { float scale[2]; float translation[2]; } ubo;
|
||||
ubo.scale[0] = 2.0f / draw_data->DisplaySize.x;
|
||||
ubo.scale[1] = 2.0f / draw_data->DisplaySize.y;
|
||||
ubo.translation[0] = -1.0f - draw_data->DisplayPos.x * ubo.scale[0];
|
||||
ubo.translation[1] = -1.0f - draw_data->DisplayPos.y * ubo.scale[1];
|
||||
SDL_PushGPUVertexUniformData(command_buffer, 0, &ubo, sizeof(UBO));
|
||||
}
|
||||
|
||||
static void CreateOrResizeBuffers(SDL_GPUBuffer** buffer, SDL_GPUTransferBuffer** transferbuffer, uint32_t* old_size, uint32_t new_size, SDL_GPUBufferUsageFlags usage)
|
||||
{
|
||||
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
|
||||
ImGui_ImplSDLGPU3_InitInfo* v = &bd->InitInfo;
|
||||
|
||||
// There is no need for calling SDL_WaitForGPUIdle here, as SDL3 will handle deferred buffer deletion automatically.
|
||||
SDL_ReleaseGPUBuffer(v->Device, *buffer);
|
||||
SDL_ReleaseGPUTransferBuffer(v->Device, *transferbuffer);
|
||||
|
||||
SDL_GPUBufferCreateInfo buffer_info = {};
|
||||
buffer_info.usage = usage;
|
||||
buffer_info.size = new_size;
|
||||
buffer_info.props = 0;
|
||||
*buffer = SDL_CreateGPUBuffer(v->Device, &buffer_info);
|
||||
*old_size = new_size;
|
||||
IM_ASSERT(*buffer != nullptr && "Failed to create GPU Buffer, call SDL_GetError() for more information");
|
||||
|
||||
SDL_GPUTransferBufferCreateInfo transferbuffer_info = {};
|
||||
transferbuffer_info.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD;
|
||||
transferbuffer_info.size = new_size;
|
||||
*transferbuffer = SDL_CreateGPUTransferBuffer(v->Device, &transferbuffer_info);
|
||||
IM_ASSERT(*transferbuffer != nullptr && "Failed to create GPU Transfer Buffer, call SDL_GetError() for more information");
|
||||
}
|
||||
|
||||
// SDL_GPU doesn't allow copy passes to occur while a render or compute pass is bound!
|
||||
// The only way to allow a user to supply their own RenderPass (to render to a texture instead of the window for example),
|
||||
// is to split the upload part of ImGui_ImplSDLGPU3_RenderDrawData() to another function that needs to be called by the user before rendering.
|
||||
void ImGui_ImplSDLGPU3_PrepareDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer)
|
||||
{
|
||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
|
||||
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
|
||||
if (fb_width <= 0 || fb_height <= 0 || draw_data->TotalVtxCount <= 0)
|
||||
return;
|
||||
|
||||
// Catch up with texture updates. Most of the times, the list will have 1 element with an OK status, aka nothing to do.
|
||||
// (This almost always points to ImGui::GetPlatformIO().Textures[] but is part of ImDrawData to allow overriding or disabling texture updates).
|
||||
if (draw_data->Textures != nullptr)
|
||||
for (ImTextureData* tex : *draw_data->Textures)
|
||||
if (tex->Status != ImTextureStatus_OK)
|
||||
ImGui_ImplSDLGPU3_UpdateTexture(tex);
|
||||
|
||||
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
|
||||
ImGui_ImplSDLGPU3_InitInfo* v = &bd->InitInfo;
|
||||
ImGui_ImplSDLGPU3_FrameData* fd = &bd->MainWindowFrameData;
|
||||
|
||||
uint32_t vertex_size = (uint32_t)draw_data->TotalVtxCount * sizeof(ImDrawVert);
|
||||
uint32_t index_size = (uint32_t)draw_data->TotalIdxCount * sizeof(ImDrawIdx);
|
||||
if (fd->VertexBuffer == nullptr || fd->VertexBufferSize < vertex_size)
|
||||
CreateOrResizeBuffers(&fd->VertexBuffer, &fd->VertexTransferBuffer, &fd->VertexBufferSize, vertex_size, SDL_GPU_BUFFERUSAGE_VERTEX);
|
||||
if (fd->IndexBuffer == nullptr || fd->IndexBufferSize < index_size)
|
||||
CreateOrResizeBuffers(&fd->IndexBuffer, &fd->IndexTransferBuffer, &fd->IndexBufferSize, index_size, SDL_GPU_BUFFERUSAGE_INDEX);
|
||||
|
||||
ImDrawVert* vtx_dst = (ImDrawVert*)SDL_MapGPUTransferBuffer(v->Device, fd->VertexTransferBuffer, true);
|
||||
ImDrawIdx* idx_dst = (ImDrawIdx*)SDL_MapGPUTransferBuffer(v->Device, fd->IndexTransferBuffer, true);
|
||||
for (const ImDrawList* draw_list : draw_data->CmdLists)
|
||||
{
|
||||
memcpy(vtx_dst, draw_list->VtxBuffer.Data, draw_list->VtxBuffer.Size * sizeof(ImDrawVert));
|
||||
memcpy(idx_dst, draw_list->IdxBuffer.Data, draw_list->IdxBuffer.Size * sizeof(ImDrawIdx));
|
||||
vtx_dst += draw_list->VtxBuffer.Size;
|
||||
idx_dst += draw_list->IdxBuffer.Size;
|
||||
}
|
||||
SDL_UnmapGPUTransferBuffer(v->Device, fd->VertexTransferBuffer);
|
||||
SDL_UnmapGPUTransferBuffer(v->Device, fd->IndexTransferBuffer);
|
||||
|
||||
SDL_GPUTransferBufferLocation vertex_buffer_location = {};
|
||||
vertex_buffer_location.offset = 0;
|
||||
vertex_buffer_location.transfer_buffer = fd->VertexTransferBuffer;
|
||||
SDL_GPUTransferBufferLocation index_buffer_location = {};
|
||||
index_buffer_location.offset = 0;
|
||||
index_buffer_location.transfer_buffer = fd->IndexTransferBuffer;
|
||||
|
||||
SDL_GPUBufferRegion vertex_buffer_region = {};
|
||||
vertex_buffer_region.buffer = fd->VertexBuffer;
|
||||
vertex_buffer_region.offset = 0;
|
||||
vertex_buffer_region.size = vertex_size;
|
||||
|
||||
SDL_GPUBufferRegion index_buffer_region = {};
|
||||
index_buffer_region.buffer = fd->IndexBuffer;
|
||||
index_buffer_region.offset = 0;
|
||||
index_buffer_region.size = index_size;
|
||||
|
||||
SDL_GPUCopyPass* copy_pass = SDL_BeginGPUCopyPass(command_buffer);
|
||||
SDL_UploadToGPUBuffer(copy_pass, &vertex_buffer_location, &vertex_buffer_region, true);
|
||||
SDL_UploadToGPUBuffer(copy_pass, &index_buffer_location, &index_buffer_region, true);
|
||||
SDL_EndGPUCopyPass(copy_pass);
|
||||
}
|
||||
|
||||
// Draw callbacks
|
||||
static void ImGui_ImplSDLGPU3_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
||||
static void ImGui_ImplSDLGPU3_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); bd->CurrentSampler = bd->TexSamplerLinear; }
|
||||
static void ImGui_ImplSDLGPU3_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); bd->CurrentSampler = bd->TexSamplerNearest; }
|
||||
|
||||
void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, SDL_GPUGraphicsPipeline* pipeline)
|
||||
{
|
||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
|
||||
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
|
||||
if (fb_width <= 0 || fb_height <= 0)
|
||||
return;
|
||||
|
||||
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
|
||||
ImGui_ImplSDLGPU3_FrameData* fd = &bd->MainWindowFrameData;
|
||||
|
||||
if (pipeline == nullptr)
|
||||
pipeline = bd->Pipeline;
|
||||
|
||||
// Will project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
|
||||
ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2)
|
||||
|
||||
// Setup render state structure (for callbacks and custom texture bindings)
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
ImGui_ImplSDLGPU3_RenderState render_state;
|
||||
render_state.Device = bd->InitInfo.Device;
|
||||
platform_io.Renderer_RenderState = bd->RenderState = &render_state;
|
||||
|
||||
ImGui_ImplSDLGPU3_SetupRenderState(draw_data, pipeline, command_buffer, render_pass, fd, fb_width, fb_height);
|
||||
|
||||
// Render command lists
|
||||
// (Because we merged all buffers into a single one, we maintain our own offset into them)
|
||||
int global_vtx_offset = 0;
|
||||
int global_idx_offset = 0;
|
||||
for (const ImDrawList* draw_list : draw_data->CmdLists)
|
||||
{
|
||||
for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback != nullptr)
|
||||
{
|
||||
// User callback, registered via ImDrawList::AddCallback()
|
||||
if (pcmd->UserCallback == ImGui_ImplSDLGPU3_DrawCallback_ResetRenderState)
|
||||
ImGui_ImplSDLGPU3_SetupRenderState(draw_data, pipeline, command_buffer, render_pass, fd, fb_width, fb_height);
|
||||
else
|
||||
pcmd->UserCallback(draw_list, pcmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
|
||||
ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
|
||||
|
||||
// Clamp to viewport as SDL_SetGPUScissor() won't accept values that are off bounds
|
||||
if (clip_min.x < 0.0f) { clip_min.x = 0.0f; }
|
||||
if (clip_min.y < 0.0f) { clip_min.y = 0.0f; }
|
||||
if (clip_max.x > (float)fb_width) { clip_max.x = (float)fb_width; }
|
||||
if (clip_max.y > (float)fb_height) { clip_max.y = (float)fb_height; }
|
||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||
continue;
|
||||
|
||||
// Apply scissor/clipping rectangle
|
||||
SDL_Rect scissor_rect = {};
|
||||
scissor_rect.x = (int)clip_min.x;
|
||||
scissor_rect.y = (int)clip_min.y;
|
||||
scissor_rect.w = (int)(clip_max.x - clip_min.x);
|
||||
scissor_rect.h = (int)(clip_max.y - clip_min.y);
|
||||
SDL_SetGPUScissor(render_pass,&scissor_rect);
|
||||
|
||||
// Bind DescriptorSet with font or user texture
|
||||
SDL_GPUTextureSamplerBinding texture_sampler_binding;
|
||||
texture_sampler_binding.texture = (SDL_GPUTexture*)(intptr_t)pcmd->GetTexID();
|
||||
texture_sampler_binding.sampler = bd->CurrentSampler;
|
||||
SDL_BindGPUFragmentSamplers(render_pass, 0, &texture_sampler_binding, 1);
|
||||
|
||||
// Draw
|
||||
// **IF YOU GET A CRASH HERE** In 1.92.2 on 2025/08/08 we have changed ImTextureID to store 'SDL_GPUTexture*' instead of storing 'SDL_GPUTextureSamplerBinding'.
|
||||
// Any code loading custom texture using this backend needs to be updated.
|
||||
SDL_DrawGPUIndexedPrimitives(render_pass, pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0);
|
||||
}
|
||||
}
|
||||
global_idx_offset += draw_list->IdxBuffer.Size;
|
||||
global_vtx_offset += draw_list->VtxBuffer.Size;
|
||||
}
|
||||
|
||||
// Note: at this point both SDL_SetGPUViewport() and SDL_SetGPUScissor() have been called.
|
||||
// Our last values will leak into user/application rendering if you forgot to call SDL_SetGPUViewport() and SDL_SetGPUScissor() yourself to explicitly set that state
|
||||
// In theory we should aim to backup/restore those values but I am not sure this is possible.
|
||||
// We perform a call to SDL_SetGPUScissor() to set back a full viewport which is likely to fix things for 99% users but technically this is not perfect. (See github #4644)
|
||||
SDL_Rect scissor_rect { 0, 0, fb_width, fb_height };
|
||||
SDL_SetGPUScissor(render_pass, &scissor_rect);
|
||||
|
||||
platform_io.Renderer_RenderState = bd->RenderState = nullptr;
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDLGPU3_DestroyTexture(ImTextureData* tex)
|
||||
{
|
||||
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
|
||||
if (tex->GetTexID() != ImTextureID_Invalid)
|
||||
if (SDL_GPUTexture* raw_tex = (SDL_GPUTexture*)(intptr_t)tex->GetTexID())
|
||||
SDL_ReleaseGPUTexture(bd->InitInfo.Device, raw_tex);
|
||||
|
||||
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
|
||||
tex->SetTexID(ImTextureID_Invalid);
|
||||
tex->SetStatus(ImTextureStatus_Destroyed);
|
||||
}
|
||||
|
||||
void ImGui_ImplSDLGPU3_UpdateTexture(ImTextureData* tex)
|
||||
{
|
||||
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
|
||||
ImGui_ImplSDLGPU3_InitInfo* v = &bd->InitInfo;
|
||||
|
||||
if (tex->Status == ImTextureStatus_WantCreate)
|
||||
{
|
||||
// Create and upload new texture to graphics system
|
||||
//IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
|
||||
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == nullptr);
|
||||
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
|
||||
|
||||
// Create texture
|
||||
SDL_GPUTextureCreateInfo texture_info = {};
|
||||
texture_info.type = SDL_GPU_TEXTURETYPE_2D;
|
||||
texture_info.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM;
|
||||
texture_info.usage = SDL_GPU_TEXTUREUSAGE_SAMPLER;
|
||||
texture_info.width = tex->Width;
|
||||
texture_info.height = tex->Height;
|
||||
texture_info.layer_count_or_depth = 1;
|
||||
texture_info.num_levels = 1;
|
||||
texture_info.sample_count = SDL_GPU_SAMPLECOUNT_1;
|
||||
|
||||
SDL_GPUTexture* raw_tex = SDL_CreateGPUTexture(v->Device, &texture_info);
|
||||
IM_ASSERT(raw_tex != nullptr && "Failed to create texture, call SDL_GetError() for more info");
|
||||
|
||||
// Store identifiers
|
||||
tex->SetTexID((ImTextureID)(intptr_t)raw_tex);
|
||||
}
|
||||
|
||||
if (tex->Status == ImTextureStatus_WantCreate || tex->Status == ImTextureStatus_WantUpdates)
|
||||
{
|
||||
SDL_GPUTexture* raw_tex = (SDL_GPUTexture*)(intptr_t)tex->GetTexID();
|
||||
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
|
||||
|
||||
// Update full texture or selected blocks. We only ever write to textures regions which have never been used before!
|
||||
// This backend choose to use tex->UpdateRect but you can use tex->Updates[] to upload individual regions.
|
||||
// We could use the smaller rect on _WantCreate but using the full rect allows us to clear the texture.
|
||||
const int upload_x = (tex->Status == ImTextureStatus_WantCreate) ? 0 : tex->UpdateRect.x;
|
||||
const int upload_y = (tex->Status == ImTextureStatus_WantCreate) ? 0 : tex->UpdateRect.y;
|
||||
const int upload_w = (tex->Status == ImTextureStatus_WantCreate) ? tex->Width : tex->UpdateRect.w;
|
||||
const int upload_h = (tex->Status == ImTextureStatus_WantCreate) ? tex->Height : tex->UpdateRect.h;
|
||||
uint32_t upload_pitch = upload_w * tex->BytesPerPixel;
|
||||
uint32_t upload_size = upload_w * upload_h * tex->BytesPerPixel;
|
||||
|
||||
// Create transfer buffer
|
||||
if (bd->TexTransferBufferSize < upload_size)
|
||||
{
|
||||
SDL_ReleaseGPUTransferBuffer(v->Device, bd->TexTransferBuffer);
|
||||
SDL_GPUTransferBufferCreateInfo transferbuffer_info = {};
|
||||
transferbuffer_info.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD;
|
||||
transferbuffer_info.size = upload_size + 1024;
|
||||
bd->TexTransferBufferSize = upload_size + 1024;
|
||||
bd->TexTransferBuffer = SDL_CreateGPUTransferBuffer(v->Device, &transferbuffer_info);
|
||||
IM_ASSERT(bd->TexTransferBuffer != nullptr && "Failed to create transfer buffer, call SDL_GetError() for more information");
|
||||
}
|
||||
|
||||
// Copy to transfer buffer
|
||||
{
|
||||
void* texture_ptr = SDL_MapGPUTransferBuffer(v->Device, bd->TexTransferBuffer, true);
|
||||
for (int y = 0; y < upload_h; y++)
|
||||
memcpy((void*)((uintptr_t)texture_ptr + y * upload_pitch), tex->GetPixelsAt(upload_x, upload_y + y), upload_pitch);
|
||||
SDL_UnmapGPUTransferBuffer(v->Device, bd->TexTransferBuffer);
|
||||
}
|
||||
|
||||
SDL_GPUTextureTransferInfo transfer_info = {};
|
||||
transfer_info.offset = 0;
|
||||
transfer_info.transfer_buffer = bd->TexTransferBuffer;
|
||||
|
||||
SDL_GPUTextureRegion texture_region = {};
|
||||
texture_region.texture = raw_tex;
|
||||
texture_region.x = (Uint32)upload_x;
|
||||
texture_region.y = (Uint32)upload_y;
|
||||
texture_region.w = (Uint32)upload_w;
|
||||
texture_region.h = (Uint32)upload_h;
|
||||
texture_region.d = 1;
|
||||
|
||||
// Upload
|
||||
{
|
||||
SDL_GPUCommandBuffer* cmd = SDL_AcquireGPUCommandBuffer(v->Device);
|
||||
SDL_GPUCopyPass* copy_pass = SDL_BeginGPUCopyPass(cmd);
|
||||
SDL_UploadToGPUTexture(copy_pass, &transfer_info, &texture_region, false);
|
||||
SDL_EndGPUCopyPass(copy_pass);
|
||||
SDL_SubmitGPUCommandBuffer(cmd);
|
||||
}
|
||||
|
||||
tex->SetStatus(ImTextureStatus_OK);
|
||||
}
|
||||
if (tex->Status == ImTextureStatus_WantDestroy && tex->UnusedFrames > 0)
|
||||
ImGui_ImplSDLGPU3_DestroyTexture(tex);
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDLGPU3_CreateShaders()
|
||||
{
|
||||
// Create the shader modules
|
||||
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
|
||||
ImGui_ImplSDLGPU3_InitInfo* v = &bd->InitInfo;
|
||||
|
||||
const char* driver = SDL_GetGPUDeviceDriver(v->Device);
|
||||
|
||||
SDL_GPUShaderCreateInfo vertex_shader_info = {};
|
||||
vertex_shader_info.entrypoint = "main";
|
||||
vertex_shader_info.stage = SDL_GPU_SHADERSTAGE_VERTEX;
|
||||
vertex_shader_info.num_uniform_buffers = 1;
|
||||
vertex_shader_info.num_storage_buffers = 0;
|
||||
vertex_shader_info.num_storage_textures = 0;
|
||||
vertex_shader_info.num_samplers = 0;
|
||||
|
||||
SDL_GPUShaderCreateInfo fragment_shader_info = {};
|
||||
fragment_shader_info.entrypoint = "main";
|
||||
fragment_shader_info.stage = SDL_GPU_SHADERSTAGE_FRAGMENT;
|
||||
fragment_shader_info.num_samplers = 1;
|
||||
fragment_shader_info.num_storage_buffers = 0;
|
||||
fragment_shader_info.num_storage_textures = 0;
|
||||
fragment_shader_info.num_uniform_buffers = 0;
|
||||
|
||||
if (strcmp(driver, "vulkan") == 0)
|
||||
{
|
||||
vertex_shader_info.format = SDL_GPU_SHADERFORMAT_SPIRV;
|
||||
vertex_shader_info.code = spirv_vertex;
|
||||
vertex_shader_info.code_size = sizeof(spirv_vertex);
|
||||
fragment_shader_info.format = SDL_GPU_SHADERFORMAT_SPIRV;
|
||||
fragment_shader_info.code = spirv_fragment;
|
||||
fragment_shader_info.code_size = sizeof(spirv_fragment);
|
||||
}
|
||||
else if (strcmp(driver, "direct3d12") == 0)
|
||||
{
|
||||
vertex_shader_info.format = SDL_GPU_SHADERFORMAT_DXBC;
|
||||
vertex_shader_info.code = dxbc_vertex;
|
||||
vertex_shader_info.code_size = sizeof(dxbc_vertex);
|
||||
fragment_shader_info.format = SDL_GPU_SHADERFORMAT_DXBC;
|
||||
fragment_shader_info.code = dxbc_fragment;
|
||||
fragment_shader_info.code_size = sizeof(dxbc_fragment);
|
||||
}
|
||||
#ifdef __APPLE__
|
||||
else
|
||||
{
|
||||
SDL_GPUShaderFormat supported_formats = SDL_GetGPUShaderFormats(v->Device);
|
||||
if (supported_formats & SDL_GPU_SHADERFORMAT_METALLIB)
|
||||
{
|
||||
// Using metallib blobs (macOS 14+, iOS)
|
||||
vertex_shader_info.entrypoint = "main0";
|
||||
vertex_shader_info.format = SDL_GPU_SHADERFORMAT_METALLIB;
|
||||
vertex_shader_info.code = metallib_vertex;
|
||||
vertex_shader_info.code_size = sizeof(metallib_vertex);
|
||||
fragment_shader_info.entrypoint = "main0";
|
||||
fragment_shader_info.format = SDL_GPU_SHADERFORMAT_METALLIB;
|
||||
fragment_shader_info.code = metallib_fragment;
|
||||
fragment_shader_info.code_size = sizeof(metallib_fragment);
|
||||
}
|
||||
else if (supported_formats & SDL_GPU_SHADERFORMAT_MSL)
|
||||
{
|
||||
// macOS: using MSL source
|
||||
vertex_shader_info.entrypoint = "main0";
|
||||
vertex_shader_info.format = SDL_GPU_SHADERFORMAT_MSL;
|
||||
vertex_shader_info.code = msl_vertex;
|
||||
vertex_shader_info.code_size = sizeof(msl_vertex);
|
||||
fragment_shader_info.entrypoint = "main0";
|
||||
fragment_shader_info.format = SDL_GPU_SHADERFORMAT_MSL;
|
||||
fragment_shader_info.code = msl_fragment;
|
||||
fragment_shader_info.code_size = sizeof(msl_fragment);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
bd->VertexShader = SDL_CreateGPUShader(v->Device, &vertex_shader_info);
|
||||
bd->FragmentShader = SDL_CreateGPUShader(v->Device, &fragment_shader_info);
|
||||
IM_ASSERT(bd->VertexShader != nullptr && "Failed to create vertex shader, call SDL_GetError() for more information");
|
||||
IM_ASSERT(bd->FragmentShader != nullptr && "Failed to create fragment shader, call SDL_GetError() for more information");
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDLGPU3_CreateGraphicsPipeline()
|
||||
{
|
||||
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
|
||||
ImGui_ImplSDLGPU3_InitInfo* v = &bd->InitInfo;
|
||||
ImGui_ImplSDLGPU3_CreateShaders();
|
||||
|
||||
SDL_GPUVertexBufferDescription vertex_buffer_desc[1];
|
||||
vertex_buffer_desc[0].slot = 0;
|
||||
vertex_buffer_desc[0].input_rate = SDL_GPU_VERTEXINPUTRATE_VERTEX;
|
||||
vertex_buffer_desc[0].instance_step_rate = 0;
|
||||
vertex_buffer_desc[0].pitch = sizeof(ImDrawVert);
|
||||
|
||||
SDL_GPUVertexAttribute vertex_attributes[3];
|
||||
vertex_attributes[0].buffer_slot = 0;
|
||||
vertex_attributes[0].format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2;
|
||||
vertex_attributes[0].location = 0;
|
||||
vertex_attributes[0].offset = offsetof(ImDrawVert,pos);
|
||||
|
||||
vertex_attributes[1].buffer_slot = 0;
|
||||
vertex_attributes[1].format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2;
|
||||
vertex_attributes[1].location = 1;
|
||||
vertex_attributes[1].offset = offsetof(ImDrawVert, uv);
|
||||
|
||||
vertex_attributes[2].buffer_slot = 0;
|
||||
vertex_attributes[2].format = SDL_GPU_VERTEXELEMENTFORMAT_UBYTE4_NORM;
|
||||
vertex_attributes[2].location = 2;
|
||||
vertex_attributes[2].offset = offsetof(ImDrawVert, col);
|
||||
|
||||
SDL_GPUVertexInputState vertex_input_state = {};
|
||||
vertex_input_state.num_vertex_attributes = 3;
|
||||
vertex_input_state.vertex_attributes = vertex_attributes;
|
||||
vertex_input_state.num_vertex_buffers = 1;
|
||||
vertex_input_state.vertex_buffer_descriptions = vertex_buffer_desc;
|
||||
|
||||
SDL_GPURasterizerState rasterizer_state = {};
|
||||
rasterizer_state.fill_mode = SDL_GPU_FILLMODE_FILL;
|
||||
rasterizer_state.cull_mode = SDL_GPU_CULLMODE_NONE;
|
||||
rasterizer_state.front_face = SDL_GPU_FRONTFACE_COUNTER_CLOCKWISE;
|
||||
rasterizer_state.enable_depth_bias = false;
|
||||
rasterizer_state.enable_depth_clip = false;
|
||||
|
||||
SDL_GPUMultisampleState multisample_state = {};
|
||||
multisample_state.sample_count = v->MSAASamples;
|
||||
multisample_state.enable_mask = false;
|
||||
|
||||
SDL_GPUDepthStencilState depth_stencil_state = {};
|
||||
depth_stencil_state.enable_depth_test = false;
|
||||
depth_stencil_state.enable_depth_write = false;
|
||||
depth_stencil_state.enable_stencil_test = false;
|
||||
|
||||
SDL_GPUColorTargetBlendState blend_state = {};
|
||||
blend_state.enable_blend = true;
|
||||
blend_state.src_color_blendfactor = SDL_GPU_BLENDFACTOR_SRC_ALPHA;
|
||||
blend_state.dst_color_blendfactor = SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
blend_state.color_blend_op = SDL_GPU_BLENDOP_ADD;
|
||||
blend_state.src_alpha_blendfactor = SDL_GPU_BLENDFACTOR_ONE;
|
||||
blend_state.dst_alpha_blendfactor = SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
blend_state.alpha_blend_op = SDL_GPU_BLENDOP_ADD;
|
||||
blend_state.color_write_mask = SDL_GPU_COLORCOMPONENT_R | SDL_GPU_COLORCOMPONENT_G | SDL_GPU_COLORCOMPONENT_B | SDL_GPU_COLORCOMPONENT_A;
|
||||
|
||||
SDL_GPUColorTargetDescription color_target_desc[1];
|
||||
color_target_desc[0].format = v->ColorTargetFormat;
|
||||
color_target_desc[0].blend_state = blend_state;
|
||||
|
||||
SDL_GPUGraphicsPipelineTargetInfo target_info = {};
|
||||
target_info.num_color_targets = 1;
|
||||
target_info.color_target_descriptions = color_target_desc;
|
||||
target_info.has_depth_stencil_target = false;
|
||||
|
||||
SDL_GPUGraphicsPipelineCreateInfo pipeline_info = {};
|
||||
pipeline_info.vertex_shader = bd->VertexShader;
|
||||
pipeline_info.fragment_shader = bd->FragmentShader;
|
||||
pipeline_info.vertex_input_state = vertex_input_state;
|
||||
pipeline_info.primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST;
|
||||
pipeline_info.rasterizer_state = rasterizer_state;
|
||||
pipeline_info.multisample_state = multisample_state;
|
||||
pipeline_info.depth_stencil_state = depth_stencil_state;
|
||||
pipeline_info.target_info = target_info;
|
||||
|
||||
bd->Pipeline = SDL_CreateGPUGraphicsPipeline(v->Device, &pipeline_info);
|
||||
IM_ASSERT(bd->Pipeline != nullptr && "Failed to create graphics pipeline, call SDL_GetError() for more information");
|
||||
}
|
||||
|
||||
void ImGui_ImplSDLGPU3_CreateDeviceObjects()
|
||||
{
|
||||
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
|
||||
ImGui_ImplSDLGPU3_InitInfo* v = &bd->InitInfo;
|
||||
|
||||
ImGui_ImplSDLGPU3_DestroyDeviceObjects();
|
||||
|
||||
if (bd->TexSamplerLinear == nullptr)
|
||||
{
|
||||
// Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling.
|
||||
SDL_GPUSamplerCreateInfo sampler_info = {};
|
||||
sampler_info.min_filter = SDL_GPU_FILTER_LINEAR;
|
||||
sampler_info.mag_filter = SDL_GPU_FILTER_LINEAR;
|
||||
sampler_info.mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_LINEAR;
|
||||
sampler_info.address_mode_u = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
|
||||
sampler_info.address_mode_v = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
|
||||
sampler_info.address_mode_w = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
|
||||
sampler_info.mip_lod_bias = 0.0f;
|
||||
sampler_info.min_lod = -1000.0f;
|
||||
sampler_info.max_lod = 1000.0f;
|
||||
sampler_info.enable_anisotropy = false;
|
||||
sampler_info.max_anisotropy = 1.0f;
|
||||
sampler_info.enable_compare = false;
|
||||
bd->TexSamplerLinear = SDL_CreateGPUSampler(v->Device, &sampler_info);
|
||||
IM_ASSERT(bd->TexSamplerLinear != nullptr && "Failed to create sampler, call SDL_GetError() for more information");
|
||||
|
||||
sampler_info.min_filter = SDL_GPU_FILTER_NEAREST;
|
||||
sampler_info.mag_filter = SDL_GPU_FILTER_NEAREST;
|
||||
sampler_info.mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_NEAREST;
|
||||
bd->TexSamplerNearest = SDL_CreateGPUSampler(v->Device, &sampler_info);
|
||||
IM_ASSERT(bd->TexSamplerNearest != nullptr && "Failed to create sampler, call SDL_GetError() for more information");
|
||||
}
|
||||
|
||||
ImGui_ImplSDLGPU3_CreateGraphicsPipeline();
|
||||
}
|
||||
|
||||
void ImGui_ImplSDLGPU3_DestroyFrameData()
|
||||
{
|
||||
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
|
||||
ImGui_ImplSDLGPU3_InitInfo* v = &bd->InitInfo;
|
||||
|
||||
ImGui_ImplSDLGPU3_FrameData* fd = &bd->MainWindowFrameData;
|
||||
SDL_ReleaseGPUBuffer(v->Device, fd->VertexBuffer);
|
||||
SDL_ReleaseGPUBuffer(v->Device, fd->IndexBuffer);
|
||||
SDL_ReleaseGPUTransferBuffer(v->Device, fd->VertexTransferBuffer);
|
||||
SDL_ReleaseGPUTransferBuffer(v->Device, fd->IndexTransferBuffer);
|
||||
fd->VertexBuffer = fd->IndexBuffer = nullptr;
|
||||
fd->VertexTransferBuffer = fd->IndexTransferBuffer = nullptr;
|
||||
fd->VertexBufferSize = fd->IndexBufferSize = 0;
|
||||
}
|
||||
|
||||
void ImGui_ImplSDLGPU3_DestroyDeviceObjects()
|
||||
{
|
||||
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
|
||||
ImGui_ImplSDLGPU3_InitInfo* v = &bd->InitInfo;
|
||||
|
||||
ImGui_ImplSDLGPU3_DestroyFrameData();
|
||||
|
||||
// Destroy all textures
|
||||
for (ImTextureData* tex : ImGui::GetPlatformIO().Textures)
|
||||
if (tex->RefCount == 1)
|
||||
ImGui_ImplSDLGPU3_DestroyTexture(tex);
|
||||
if (bd->TexTransferBuffer) { SDL_ReleaseGPUTransferBuffer(v->Device, bd->TexTransferBuffer); bd->TexTransferBuffer = nullptr; }
|
||||
if (bd->VertexShader) { SDL_ReleaseGPUShader(v->Device, bd->VertexShader); bd->VertexShader = nullptr; }
|
||||
if (bd->FragmentShader) { SDL_ReleaseGPUShader(v->Device, bd->FragmentShader); bd->FragmentShader = nullptr; }
|
||||
if (bd->TexSamplerLinear) { SDL_ReleaseGPUSampler(v->Device, bd->TexSamplerLinear); bd->TexSamplerLinear = nullptr; }
|
||||
if (bd->TexSamplerNearest) { SDL_ReleaseGPUSampler(v->Device, bd->TexSamplerNearest); bd->TexSamplerNearest = nullptr; }
|
||||
if (bd->Pipeline) { SDL_ReleaseGPUGraphicsPipeline(v->Device, bd->Pipeline); bd->Pipeline = nullptr; }
|
||||
}
|
||||
|
||||
bool ImGui_ImplSDLGPU3_Init(ImGui_ImplSDLGPU3_InitInfo* info)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IMGUI_CHECKVERSION();
|
||||
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
||||
|
||||
// Setup backend capabilities flags
|
||||
ImGui_ImplSDLGPU3_Data* bd = IM_NEW(ImGui_ImplSDLGPU3_Data)();
|
||||
io.BackendRendererUserData = (void*)bd;
|
||||
io.BackendRendererName = "imgui_impl_sdlgpu3";
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
||||
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
platform_io.DrawCallback_ResetRenderState = ImGui_ImplSDLGPU3_DrawCallback_ResetRenderState;
|
||||
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplSDLGPU3_DrawCallback_SetSamplerLinear;
|
||||
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplSDLGPU3_DrawCallback_SetSamplerNearest;
|
||||
|
||||
IM_ASSERT(info->Device != nullptr);
|
||||
IM_ASSERT(info->ColorTargetFormat != SDL_GPU_TEXTUREFORMAT_INVALID);
|
||||
|
||||
bd->InitInfo = *info;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplSDLGPU3_Shutdown()
|
||||
{
|
||||
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
ImGui_ImplSDLGPU3_DestroyDeviceObjects();
|
||||
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
|
||||
platform_io.ClearRendererHandlers();
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
void ImGui_ImplSDLGPU3_NewFrame()
|
||||
{
|
||||
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplSDLGPU3_Init()?");
|
||||
|
||||
if (!bd->TexSamplerLinear)
|
||||
ImGui_ImplSDLGPU3_CreateDeviceObjects();
|
||||
}
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
62
backends/imgui_impl_sdlgpu3.h
Normal file
62
backends/imgui_impl_sdlgpu3.h
Normal file
@@ -0,0 +1,62 @@
|
||||
// dear imgui: Renderer Backend for SDL_GPU
|
||||
// This needs to be used along with the SDL3 Platform Backend
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'SDL_GPUTexture*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef! **IMPORTANT** Before 2025/08/08, ImTextureID was a reference to a SDL_GPUTextureSamplerBinding struct.
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
|
||||
// The aim of imgui_impl_sdlgpu3.h/.cpp is to be usable in your engine without any modification.
|
||||
// IF YOU FEEL YOU NEED TO MAKE ANY CHANGE TO THIS CODE, please share them and your feedback at https://github.com/ocornut/imgui/
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
// Important note to the reader who wish to integrate imgui_impl_sdlgpu3.cpp/.h in their own engine/app.
|
||||
// - Unlike other backends, the user must call the function ImGui_ImplSDLGPU_PrepareDrawData BEFORE issuing a SDL_GPURenderPass containing ImGui_ImplSDLGPU_RenderDrawData.
|
||||
// Calling the function is MANDATORY, otherwise the ImGui will not upload neither the vertex nor the index buffer for the GPU. See imgui_impl_sdlgpu3.cpp for more info.
|
||||
|
||||
#pragma once
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include <SDL3/SDL_gpu.h>
|
||||
|
||||
// Initialization data, for ImGui_ImplSDLGPU_Init()
|
||||
// - Remember to set ColorTargetFormat to the correct format. If you're rendering to the swapchain, call SDL_GetGPUSwapchainTextureFormat() to query the right value
|
||||
struct ImGui_ImplSDLGPU3_InitInfo
|
||||
{
|
||||
SDL_GPUDevice* Device = nullptr;
|
||||
SDL_GPUTextureFormat ColorTargetFormat = SDL_GPU_TEXTUREFORMAT_INVALID;
|
||||
SDL_GPUSampleCount MSAASamples = SDL_GPU_SAMPLECOUNT_1;
|
||||
SDL_GPUSwapchainComposition SwapchainComposition = SDL_GPU_SWAPCHAINCOMPOSITION_SDR; // Only used in multi-viewports mode.
|
||||
SDL_GPUPresentMode PresentMode = SDL_GPU_PRESENTMODE_VSYNC; // Only used in multi-viewports mode.
|
||||
};
|
||||
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
IMGUI_IMPL_API bool ImGui_ImplSDLGPU3_Init(ImGui_ImplSDLGPU3_InitInfo* info);
|
||||
IMGUI_IMPL_API void ImGui_ImplSDLGPU3_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplSDLGPU3_NewFrame();
|
||||
IMGUI_IMPL_API void ImGui_ImplSDLGPU3_PrepareDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer);
|
||||
IMGUI_IMPL_API void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, SDL_GPUGraphicsPipeline* pipeline = nullptr);
|
||||
|
||||
// Use if you want to reset your rendering device without losing Dear ImGui state.
|
||||
IMGUI_IMPL_API void ImGui_ImplSDLGPU3_CreateDeviceObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplSDLGPU3_DestroyDeviceObjects();
|
||||
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||
IMGUI_IMPL_API void ImGui_ImplSDLGPU3_UpdateTexture(ImTextureData* tex);
|
||||
|
||||
// [BETA] Selected render state data shared with callbacks.
|
||||
// This is temporarily stored in GetPlatformIO().Renderer_RenderState during the ImGui_ImplSDLGPU3_RenderDrawData() call.
|
||||
// (Please open an issue if you feel you need access to more data)
|
||||
struct ImGui_ImplSDLGPU3_RenderState
|
||||
{
|
||||
SDL_GPUDevice* Device;
|
||||
};
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
406
backends/imgui_impl_sdlgpu3_shaders.h
Normal file
406
backends/imgui_impl_sdlgpu3_shaders.h
Normal file
@@ -0,0 +1,406 @@
|
||||
#pragma once
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include <stdint.h>
|
||||
|
||||
// Data exported using
|
||||
// misc/fonts/binary_to_compressed_c.exe -u8 -nocompress filename symbolname >filename.h
|
||||
// With some manual pasting.
|
||||
|
||||
// Check sdlgpu3/ folder for the shaders' source code and instruction on how to build them
|
||||
const uint8_t spirv_vertex[1732] = {
|
||||
3,2,35,7,0,0,1,0,11,0,13,0,55,0,0,0,0,0,0,0,17,0,2,0,1,0,0,0,11,0,6,0,1,0,0,0,71,76,83,76,46,115,116,100,46,52,53,48,0,0,0,0,14,0,3,0,0,0,0,0,1,0,0,0,15,0,10,0,0,0,0,0,4,0,0,0,109,
|
||||
97,105,110,0,0,0,0,11,0,0,0,15,0,0,0,21,0,0,0,30,0,0,0,31,0,0,0,3,0,3,0,2,0,0,0,194,1,0,0,4,0,10,0,71,76,95,71,79,79,71,76,69,95,99,112,112,95,115,116,121,108,101,95,108,105,110,101,
|
||||
95,100,105,114,101,99,116,105,118,101,0,0,4,0,8,0,71,76,95,71,79,79,71,76,69,95,105,110,99,108,117,100,101,95,100,105,114,101,99,116,105,118,101,0,5,0,4,0,4,0,0,0,109,97,105,110,0,
|
||||
0,0,0,5,0,3,0,9,0,0,0,0,0,0,0,6,0,5,0,9,0,0,0,0,0,0,0,67,111,108,111,114,0,0,0,6,0,4,0,9,0,0,0,1,0,0,0,85,86,0,0,5,0,3,0,11,0,0,0,79,117,116,0,5,0,4,0,15,0,0,0,97,67,111,108,111,114,
|
||||
0,0,5,0,3,0,21,0,0,0,97,85,86,0,5,0,6,0,28,0,0,0,103,108,95,80,101,114,86,101,114,116,101,120,0,0,0,0,6,0,6,0,28,0,0,0,0,0,0,0,103,108,95,80,111,115,105,116,105,111,110,0,6,0,7,0,28,
|
||||
0,0,0,1,0,0,0,103,108,95,80,111,105,110,116,83,105,122,101,0,0,0,0,6,0,7,0,28,0,0,0,2,0,0,0,103,108,95,67,108,105,112,68,105,115,116,97,110,99,101,0,6,0,7,0,28,0,0,0,3,0,0,0,103,108,
|
||||
95,67,117,108,108,68,105,115,116,97,110,99,101,0,5,0,3,0,30,0,0,0,0,0,0,0,5,0,4,0,31,0,0,0,97,80,111,115,0,0,0,0,5,0,6,0,33,0,0,0,117,80,117,115,104,67,111,110,115,116,97,110,116,0,
|
||||
0,0,6,0,5,0,33,0,0,0,0,0,0,0,117,83,99,97,108,101,0,0,6,0,6,0,33,0,0,0,1,0,0,0,117,84,114,97,110,115,108,97,116,101,0,0,5,0,3,0,35,0,0,0,112,99,0,0,71,0,4,0,11,0,0,0,30,0,0,0,0,0,0,
|
||||
0,71,0,4,0,15,0,0,0,30,0,0,0,2,0,0,0,71,0,4,0,21,0,0,0,30,0,0,0,1,0,0,0,71,0,3,0,28,0,0,0,2,0,0,0,72,0,5,0,28,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,72,0,5,0,28,0,0,0,1,0,0,0,11,0,0,0,1,0,
|
||||
0,0,72,0,5,0,28,0,0,0,2,0,0,0,11,0,0,0,3,0,0,0,72,0,5,0,28,0,0,0,3,0,0,0,11,0,0,0,4,0,0,0,71,0,4,0,31,0,0,0,30,0,0,0,0,0,0,0,71,0,3,0,33,0,0,0,2,0,0,0,72,0,5,0,33,0,0,0,0,0,0,0,35,
|
||||
0,0,0,0,0,0,0,72,0,5,0,33,0,0,0,1,0,0,0,35,0,0,0,8,0,0,0,71,0,4,0,35,0,0,0,33,0,0,0,0,0,0,0,71,0,4,0,35,0,0,0,34,0,0,0,1,0,0,0,19,0,2,0,2,0,0,0,33,0,3,0,3,0,0,0,2,0,0,0,22,0,3,0,6,
|
||||
0,0,0,32,0,0,0,23,0,4,0,7,0,0,0,6,0,0,0,4,0,0,0,23,0,4,0,8,0,0,0,6,0,0,0,2,0,0,0,30,0,4,0,9,0,0,0,7,0,0,0,8,0,0,0,32,0,4,0,10,0,0,0,3,0,0,0,9,0,0,0,59,0,4,0,10,0,0,0,11,0,0,0,3,0,0,
|
||||
0,21,0,4,0,12,0,0,0,32,0,0,0,1,0,0,0,43,0,4,0,12,0,0,0,13,0,0,0,0,0,0,0,32,0,4,0,14,0,0,0,1,0,0,0,7,0,0,0,59,0,4,0,14,0,0,0,15,0,0,0,1,0,0,0,32,0,4,0,17,0,0,0,3,0,0,0,7,0,0,0,43,0,
|
||||
4,0,12,0,0,0,19,0,0,0,1,0,0,0,32,0,4,0,20,0,0,0,1,0,0,0,8,0,0,0,59,0,4,0,20,0,0,0,21,0,0,0,1,0,0,0,32,0,4,0,23,0,0,0,3,0,0,0,8,0,0,0,21,0,4,0,25,0,0,0,32,0,0,0,0,0,0,0,43,0,4,0,25,
|
||||
0,0,0,26,0,0,0,1,0,0,0,28,0,4,0,27,0,0,0,6,0,0,0,26,0,0,0,30,0,6,0,28,0,0,0,7,0,0,0,6,0,0,0,27,0,0,0,27,0,0,0,32,0,4,0,29,0,0,0,3,0,0,0,28,0,0,0,59,0,4,0,29,0,0,0,30,0,0,0,3,0,0,0,
|
||||
59,0,4,0,20,0,0,0,31,0,0,0,1,0,0,0,30,0,4,0,33,0,0,0,8,0,0,0,8,0,0,0,32,0,4,0,34,0,0,0,2,0,0,0,33,0,0,0,59,0,4,0,34,0,0,0,35,0,0,0,2,0,0,0,32,0,4,0,36,0,0,0,2,0,0,0,8,0,0,0,43,0,4,
|
||||
0,6,0,0,0,43,0,0,0,0,0,0,0,43,0,4,0,6,0,0,0,44,0,0,0,0,0,128,63,43,0,4,0,6,0,0,0,49,0,0,0,0,0,128,191,32,0,4,0,50,0,0,0,3,0,0,0,6,0,0,0,54,0,5,0,2,0,0,0,4,0,0,0,0,0,0,0,3,0,0,0,248,
|
||||
0,2,0,5,0,0,0,61,0,4,0,7,0,0,0,16,0,0,0,15,0,0,0,65,0,5,0,17,0,0,0,18,0,0,0,11,0,0,0,13,0,0,0,62,0,3,0,18,0,0,0,16,0,0,0,61,0,4,0,8,0,0,0,22,0,0,0,21,0,0,0,65,0,5,0,23,0,0,0,24,0,0,
|
||||
0,11,0,0,0,19,0,0,0,62,0,3,0,24,0,0,0,22,0,0,0,61,0,4,0,8,0,0,0,32,0,0,0,31,0,0,0,65,0,5,0,36,0,0,0,37,0,0,0,35,0,0,0,13,0,0,0,61,0,4,0,8,0,0,0,38,0,0,0,37,0,0,0,133,0,5,0,8,0,0,0,
|
||||
39,0,0,0,32,0,0,0,38,0,0,0,65,0,5,0,36,0,0,0,40,0,0,0,35,0,0,0,19,0,0,0,61,0,4,0,8,0,0,0,41,0,0,0,40,0,0,0,129,0,5,0,8,0,0,0,42,0,0,0,39,0,0,0,41,0,0,0,81,0,5,0,6,0,0,0,45,0,0,0,42,
|
||||
0,0,0,0,0,0,0,81,0,5,0,6,0,0,0,46,0,0,0,42,0,0,0,1,0,0,0,80,0,7,0,7,0,0,0,47,0,0,0,45,0,0,0,46,0,0,0,43,0,0,0,44,0,0,0,65,0,5,0,17,0,0,0,48,0,0,0,30,0,0,0,13,0,0,0,62,0,3,0,48,0,0,
|
||||
0,47,0,0,0,65,0,6,0,50,0,0,0,51,0,0,0,30,0,0,0,13,0,0,0,26,0,0,0,61,0,4,0,6,0,0,0,52,0,0,0,51,0,0,0,133,0,5,0,6,0,0,0,53,0,0,0,52,0,0,0,49,0,0,0,65,0,6,0,50,0,0,0,54,0,0,0,30,0,0,0,
|
||||
13,0,0,0,26,0,0,0,62,0,3,0,54,0,0,0,53,0,0,0,253,0,1,0,56,0,1,0,
|
||||
};
|
||||
const uint8_t spirv_fragment[844] = {
|
||||
3,2,35,7,0,0,1,0,11,0,13,0,30,0,0,0,0,0,0,0,17,0,2,0,1,0,0,0,11,0,6,0,1,0,0,0,71,76,83,76,46,115,116,100,46,52,53,48,0,0,0,0,14,0,3,0,0,0,0,0,1,0,0,0,15,0,7,0,4,0,0,0,4,0,0,0,109,97,
|
||||
105,110,0,0,0,0,9,0,0,0,13,0,0,0,16,0,3,0,4,0,0,0,7,0,0,0,3,0,3,0,2,0,0,0,194,1,0,0,4,0,10,0,71,76,95,71,79,79,71,76,69,95,99,112,112,95,115,116,121,108,101,95,108,105,110,101,95,100,
|
||||
105,114,101,99,116,105,118,101,0,0,4,0,8,0,71,76,95,71,79,79,71,76,69,95,105,110,99,108,117,100,101,95,100,105,114,101,99,116,105,118,101,0,5,0,4,0,4,0,0,0,109,97,105,110,0,0,0,0,5,
|
||||
0,4,0,9,0,0,0,102,67,111,108,111,114,0,0,5,0,3,0,11,0,0,0,0,0,0,0,6,0,5,0,11,0,0,0,0,0,0,0,67,111,108,111,114,0,0,0,6,0,4,0,11,0,0,0,1,0,0,0,85,86,0,0,5,0,3,0,13,0,0,0,73,110,0,0,5,
|
||||
0,5,0,22,0,0,0,115,84,101,120,116,117,114,101,0,0,0,0,71,0,4,0,9,0,0,0,30,0,0,0,0,0,0,0,71,0,4,0,13,0,0,0,30,0,0,0,0,0,0,0,71,0,4,0,22,0,0,0,33,0,0,0,0,0,0,0,71,0,4,0,22,0,0,0,34,0,
|
||||
0,0,2,0,0,0,19,0,2,0,2,0,0,0,33,0,3,0,3,0,0,0,2,0,0,0,22,0,3,0,6,0,0,0,32,0,0,0,23,0,4,0,7,0,0,0,6,0,0,0,4,0,0,0,32,0,4,0,8,0,0,0,3,0,0,0,7,0,0,0,59,0,4,0,8,0,0,0,9,0,0,0,3,0,0,0,23,
|
||||
0,4,0,10,0,0,0,6,0,0,0,2,0,0,0,30,0,4,0,11,0,0,0,7,0,0,0,10,0,0,0,32,0,4,0,12,0,0,0,1,0,0,0,11,0,0,0,59,0,4,0,12,0,0,0,13,0,0,0,1,0,0,0,21,0,4,0,14,0,0,0,32,0,0,0,1,0,0,0,43,0,4,0,
|
||||
14,0,0,0,15,0,0,0,0,0,0,0,32,0,4,0,16,0,0,0,1,0,0,0,7,0,0,0,25,0,9,0,19,0,0,0,6,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,27,0,3,0,20,0,0,0,19,0,0,0,32,0,4,0,21,0,0,0,0,
|
||||
0,0,0,20,0,0,0,59,0,4,0,21,0,0,0,22,0,0,0,0,0,0,0,43,0,4,0,14,0,0,0,24,0,0,0,1,0,0,0,32,0,4,0,25,0,0,0,1,0,0,0,10,0,0,0,54,0,5,0,2,0,0,0,4,0,0,0,0,0,0,0,3,0,0,0,248,0,2,0,5,0,0,0,65,
|
||||
0,5,0,16,0,0,0,17,0,0,0,13,0,0,0,15,0,0,0,61,0,4,0,7,0,0,0,18,0,0,0,17,0,0,0,61,0,4,0,20,0,0,0,23,0,0,0,22,0,0,0,65,0,5,0,25,0,0,0,26,0,0,0,13,0,0,0,24,0,0,0,61,0,4,0,10,0,0,0,27,0,
|
||||
0,0,26,0,0,0,87,0,5,0,7,0,0,0,28,0,0,0,23,0,0,0,27,0,0,0,133,0,5,0,7,0,0,0,29,0,0,0,18,0,0,0,28,0,0,0,62,0,3,0,9,0,0,0,29,0,0,0,253,0,1,0,56,0,1,0,
|
||||
};
|
||||
|
||||
const uint8_t dxbc_vertex[1064] = {
|
||||
68,88,66,67,32,50,127,204,241,196,165,104,216,114,216,116,220,164,29,45,1,0,0,0,40,4,0,0,5,0,0,0,52,0,0,0,136,1,0,0,236,1,0,0,92,2,0,0,140,3,0,0,82,68,69,70,76,1,0,0,1,0,0,0,116,0,
|
||||
0,0,1,0,0,0,60,0,0,0,1,5,254,255,0,5,0,0,34,1,0,0,19,19,68,37,60,0,0,0,24,0,0,0,40,0,0,0,40,0,0,0,36,0,0,0,12,0,0,0,0,0,0,0,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,
|
||||
0,1,0,0,0,1,0,0,0,0,0,0,0,117,80,117,115,104,67,111,110,115,116,97,110,116,0,171,171,100,0,0,0,2,0,0,0,140,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,220,0,0,0,0,0,0,0,8,0,0,0,2,0,0,0,240,0,0,
|
||||
0,0,0,0,0,255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0,20,1,0,0,8,0,0,0,8,0,0,0,2,0,0,0,240,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0,112,99,95,117,83,99,97,
|
||||
108,101,0,102,108,111,97,116,50,0,171,171,171,1,0,3,0,1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,0,0,0,112,99,95,117,84,114,97,110,115,108,97,116,101,0,77,105,99,114,
|
||||
111,115,111,102,116,32,40,82,41,32,72,76,83,76,32,83,104,97,100,101,114,32,67,111,109,112,105,108,101,114,32,49,48,46,49,0,171,171,73,83,71,78,92,0,0,0,3,0,0,0,8,0,0,0,80,0,0,0,0,0,
|
||||
0,0,0,0,0,0,3,0,0,0,0,0,0,0,3,3,0,0,80,0,0,0,1,0,0,0,0,0,0,0,3,0,0,0,1,0,0,0,3,3,0,0,80,0,0,0,2,0,0,0,0,0,0,0,3,0,0,0,2,0,0,0,15,15,0,0,84,69,88,67,79,79,82,68,0,171,171,171,79,83,
|
||||
71,78,104,0,0,0,3,0,0,0,8,0,0,0,80,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,15,0,0,0,80,0,0,0,1,0,0,0,0,0,0,0,3,0,0,0,1,0,0,0,3,12,0,0,89,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,2,0,0,0,15,0,0,
|
||||
0,84,69,88,67,79,79,82,68,0,83,86,95,80,111,115,105,116,105,111,110,0,171,171,171,83,72,69,88,40,1,0,0,81,0,1,0,74,0,0,0,106,8,0,1,89,0,0,7,70,142,48,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,
|
||||
0,0,1,0,0,0,95,0,0,3,50,16,16,0,0,0,0,0,95,0,0,3,50,16,16,0,1,0,0,0,95,0,0,3,242,16,16,0,2,0,0,0,101,0,0,3,242,32,16,0,0,0,0,0,101,0,0,3,50,32,16,0,1,0,0,0,103,0,0,4,242,32,16,0,2,
|
||||
0,0,0,1,0,0,0,104,0,0,2,1,0,0,0,50,0,0,13,50,0,16,0,0,0,0,0,70,16,16,0,0,0,0,0,70,128,48,0,0,0,0,0,0,0,0,0,0,0,0,0,230,138,48,0,0,0,0,0,0,0,0,0,0,0,0,0,54,0,0,6,34,32,16,0,2,0,0,0,
|
||||
26,0,16,128,65,0,0,0,0,0,0,0,54,0,0,5,242,32,16,0,0,0,0,0,70,30,16,0,2,0,0,0,54,0,0,5,18,32,16,0,2,0,0,0,10,0,16,0,0,0,0,0,54,0,0,8,194,32,16,0,2,0,0,0,2,64,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,128,63,54,0,0,5,50,32,16,0,1,0,0,0,70,16,16,0,1,0,0,0,62,0,0,1,83,84,65,84,148,0,0,0,7,0,0,0,1,0,0,0,0,0,0,0,6,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
};
|
||||
const uint8_t dxbc_fragment[744] = {
|
||||
68,88,66,67,235,219,43,109,38,151,39,223,98,41,193,28,215,98,67,110,1,0,0,0,232,2,0,0,5,0,0,0,52,0,0,0,12,1,0,0,88,1,0,0,140,1,0,0,76,2,0,0,82,68,69,70,208,0,0,0,0,0,0,0,0,0,0,0,2,
|
||||
0,0,0,60,0,0,0,1,5,255,255,0,5,0,0,167,0,0,0,19,19,68,37,60,0,0,0,24,0,0,0,40,0,0,0,40,0,0,0,36,0,0,0,12,0,0,0,0,0,0,0,140,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,
|
||||
0,0,2,0,0,0,0,0,0,0,158,0,0,0,2,0,0,0,5,0,0,0,4,0,0,0,255,255,255,255,0,0,0,0,1,0,0,0,12,0,0,0,2,0,0,0,0,0,0,0,95,115,84,101,120,116,117,114,101,95,115,97,109,112,108,101,114,0,115,
|
||||
84,101,120,116,117,114,101,0,77,105,99,114,111,115,111,102,116,32,40,82,41,32,72,76,83,76,32,83,104,97,100,101,114,32,67,111,109,112,105,108,101,114,32,49,48,46,49,0,171,73,83,71,78,
|
||||
68,0,0,0,2,0,0,0,8,0,0,0,56,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,15,15,0,0,56,0,0,0,1,0,0,0,0,0,0,0,3,0,0,0,1,0,0,0,3,3,0,0,84,69,88,67,79,79,82,68,0,171,171,171,79,83,71,78,44,0,
|
||||
0,0,1,0,0,0,8,0,0,0,32,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,15,0,0,0,83,86,95,84,97,114,103,101,116,0,171,171,83,72,69,88,184,0,0,0,81,0,0,0,46,0,0,0,106,8,0,1,90,0,0,6,70,110,48,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,88,24,0,7,70,126,48,0,0,0,0,0,0,0,0,0,0,0,0,0,85,85,0,0,2,0,0,0,98,16,0,3,242,16,16,0,0,0,0,0,98,16,0,3,50,16,16,0,1,0,0,0,101,0,0,3,242,32,16,0,0,
|
||||
0,0,0,104,0,0,2,1,0,0,0,69,0,0,11,242,0,16,0,0,0,0,0,70,16,16,0,1,0,0,0,70,126,32,0,0,0,0,0,0,0,0,0,0,96,32,0,0,0,0,0,0,0,0,0,56,0,0,7,242,32,16,0,0,0,0,0,70,14,16,0,0,0,0,0,70,30,
|
||||
16,0,0,0,0,0,62,0,0,1,83,84,65,84,148,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
};
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <TargetConditionals.h>
|
||||
#if TARGET_OS_MAC
|
||||
const uint8_t metallib_vertex[3892] = {
|
||||
77,84,76,66,1,128,2,0,7,0,0,129,14,0,0,0,52,15,0,0,0,0,0,0,88,0,0,0,0,0,0,0,123,0,0,0,0,0,0,0,219,0,0,0,0,0,0,0,49,0,0,0,0,0,0,0,12,1,0,0,0,0,0,0,8,0,0,0,0,0,0,0,20,1,0,0,0,0,0,0,32,
|
||||
14,0,0,0,0,0,0,1,0,0,0,123,0,0,0,78,65,77,69,6,0,109,97,105,110,48,0,84,89,80,69,1,0,0,72,65,83,72,32,0,62,81,190,157,8,240,236,158,164,213,65,62,170,226,96,136,231,243,238,160,100,
|
||||
26,13,254,254,64,19,129,180,3,149,75,77,68,83,90,8,0,32,14,0,0,0,0,0,0,79,70,70,84,24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,86,69,82,83,8,0,2,0,6,0,3,0,1,0,69,78,68,84,
|
||||
69,78,68,84,45,0,0,0,86,65,84,84,24,0,3,0,97,80,111,115,0,0,128,97,85,86,0,1,128,97,67,111,108,111,114,0,2,128,86,65,84,89,5,0,3,0,4,4,6,69,78,68,84,4,0,0,0,69,78,68,84,222,192,23,
|
||||
11,0,0,0,0,20,0,0,0,8,14,0,0,255,255,255,255,66,67,192,222,53,20,0,0,3,0,0,0,98,12,48,36,128,16,5,200,20,0,0,0,33,12,0,0,74,3,0,0,11,2,33,0,2,0,0,0,22,0,0,0,7,129,35,145,65,200,4,73,
|
||||
6,16,50,57,146,1,132,12,37,5,8,25,30,4,139,98,128,16,69,2,66,146,11,66,132,16,50,20,56,8,24,75,10,50,66,136,72,112,196,33,35,68,18,135,140,16,65,146,2,100,200,8,177,20,32,67,70,136,
|
||||
32,201,1,50,66,132,24,42,40,42,144,49,124,176,92,145,32,196,200,0,0,0,137,32,0,0,24,0,0,0,50,34,8,9,32,98,70,0,33,43,36,152,16,33,37,36,152,16,25,39,12,133,164,144,96,66,100,92,32,
|
||||
36,100,130,224,153,1,24,70,32,128,97,4,1,184,67,72,32,37,77,17,37,76,62,149,82,210,193,57,141,52,1,205,148,4,145,65,4,66,48,197,136,68,145,13,4,204,17,128,129,10,228,28,1,40,12,34,
|
||||
8,194,48,2,145,140,0,0,0,0,0,81,24,0,0,100,0,0,0,27,246,35,248,255,255,255,255,1,48,5,192,15,0,56,0,254,0,144,0,10,232,3,34,28,224,1,30,228,225,29,240,161,13,204,161,30,220,97,28,218,
|
||||
192,28,224,161,13,218,33,28,232,1,29,0,122,144,135,122,40,7,128,48,7,121,8,135,118,40,135,54,128,135,119,72,7,119,160,135,114,144,7,32,28,216,129,29,0,162,29,210,193,29,218,128,29,
|
||||
202,225,28,194,129,29,218,192,30,202,97,28,232,225,29,228,161,13,238,33,29,200,129,30,208,1,136,3,57,192,3,96,112,135,119,104,3,113,168,135,116,96,7,122,72,7,119,152,7,128,112,135,
|
||||
119,104,131,116,112,7,115,152,135,54,48,7,120,104,131,118,8,7,122,64,7,128,30,228,161,30,202,1,32,220,225,29,218,192,29,194,193,29,230,161,13,204,1,30,218,160,29,194,129,30,208,1,160,
|
||||
7,121,168,135,114,0,8,119,120,135,54,152,135,116,56,7,119,40,7,114,104,3,125,40,7,121,120,135,121,104,3,115,128,135,54,104,135,112,160,7,116,0,232,65,30,234,161,28,0,194,29,222,161,
|
||||
13,232,65,30,194,1,30,224,33,29,220,225,28,218,160,29,194,129,30,208,1,160,7,121,168,135,114,0,136,121,160,135,112,24,135,117,104,3,120,144,135,119,160,135,114,24,7,122,120,7,121,104,
|
||||
3,113,168,7,115,48,135,114,144,135,54,152,135,116,208,135,114,0,240,0,32,234,193,29,230,33,28,204,161,28,218,192,28,224,161,13,218,33,28,232,1,29,0,122,144,135,122,40,7,96,195,24,8,
|
||||
4,176,0,164,0,84,65,128,4,105,0,13,225,144,14,242,208,6,226,80,15,230,96,14,229,32,15,109,224,14,239,208,6,225,192,14,233,16,14,243,0,0,0,73,24,0,0,1,0,0,0,19,132,64,0,19,176,112,72,
|
||||
7,121,176,3,58,104,131,112,128,7,120,96,135,114,104,131,118,8,135,113,120,135,121,192,135,56,160,3,55,128,3,55,128,131,13,183,81,14,109,0,15,122,96,7,116,160,7,118,64,7,122,96,7,116,
|
||||
208,6,233,16,7,122,128,7,122,128,7,109,144,14,120,160,7,120,160,7,120,208,6,233,16,7,118,160,7,113,96,7,122,16,7,118,208,6,233,48,7,114,160,7,115,32,7,122,48,7,114,208,6,233,96,7,116,
|
||||
160,7,118,64,7,122,96,7,116,208,6,230,48,7,114,160,7,115,32,7,122,48,7,114,208,6,230,96,7,116,160,7,118,64,7,122,96,7,116,208,6,246,16,7,118,160,7,113,96,7,122,16,7,118,208,6,246,32,
|
||||
7,116,160,7,115,32,7,122,48,7,114,208,6,246,48,7,114,160,7,115,32,7,122,48,7,114,208,6,246,64,7,120,160,7,118,64,7,122,96,7,116,208,6,246,96,7,116,160,7,118,64,7,122,96,7,116,208,6,
|
||||
246,144,7,118,160,7,113,32,7,120,160,7,113,32,7,120,208,6,246,16,7,114,128,7,122,16,7,114,128,7,122,16,7,114,128,7,109,96,15,113,144,7,114,160,7,114,80,7,118,160,7,114,80,7,118,208,
|
||||
6,246,32,7,117,96,7,122,32,7,117,96,7,122,32,7,117,96,7,109,96,15,117,16,7,114,160,7,117,16,7,114,160,7,117,16,7,114,208,6,246,16,7,112,32,7,116,160,7,113,0,7,114,64,7,122,16,7,112,
|
||||
32,7,116,208,6,238,128,7,122,16,7,118,160,7,115,32,7,26,33,12,89,48,0,210,208,67,42,160,48,0,0,8,0,0,0,4,0,0,0,0,0,10,64,98,131,64,81,166,1,0,128,44,16,0,11,0,0,0,50,30,152,16,25,17,
|
||||
76,144,140,9,38,71,198,4,67,202,34,40,129,66,40,135,242,41,64,129,130,40,144,98,24,1,40,3,218,17,0,210,177,132,39,0,0,0,177,24,0,0,165,0,0,0,51,8,128,28,196,225,28,102,20,1,61,136,
|
||||
67,56,132,195,140,66,128,7,121,120,7,115,152,113,12,230,0,15,237,16,14,244,128,14,51,12,66,30,194,193,29,206,161,28,102,48,5,61,136,67,56,132,131,27,204,3,61,200,67,61,140,3,61,204,
|
||||
120,140,116,112,7,123,8,7,121,72,135,112,112,7,122,112,3,118,120,135,112,32,135,25,204,17,14,236,144,14,225,48,15,110,48,15,227,240,14,240,80,14,51,16,196,29,222,33,28,216,33,29,194,
|
||||
97,30,102,48,137,59,188,131,59,208,67,57,180,3,60,188,131,60,132,3,59,204,240,20,118,96,7,123,104,7,55,104,135,114,104,7,55,128,135,112,144,135,112,96,7,118,40,7,118,248,5,118,120,
|
||||
135,119,128,135,95,8,135,113,24,135,114,152,135,121,152,129,44,238,240,14,238,224,14,245,192,14,236,48,3,98,200,161,28,228,161,28,204,161,28,228,161,28,220,97,28,202,33,28,196,129,
|
||||
29,202,97,6,214,144,67,57,200,67,57,152,67,57,200,67,57,184,195,56,148,67,56,136,3,59,148,195,47,188,131,60,252,130,59,212,3,59,176,195,12,199,105,135,112,88,135,114,112,131,116,104,
|
||||
7,120,96,135,116,24,135,116,160,135,25,206,83,15,238,0,15,242,80,14,228,144,14,227,64,15,225,32,14,236,80,14,51,32,40,29,220,193,30,194,65,30,210,33,28,220,129,30,220,224,28,228,225,
|
||||
29,234,1,30,102,24,81,56,176,67,58,156,131,59,204,80,36,118,96,7,123,104,7,55,96,135,119,120,7,120,152,81,76,244,144,15,240,80,14,51,30,106,30,202,97,28,232,33,29,222,193,29,126,1,
|
||||
30,228,161,28,204,33,29,240,97,6,84,133,131,56,204,195,59,176,67,61,208,67,57,252,194,60,228,67,59,136,195,59,176,195,140,197,10,135,121,152,135,119,24,135,116,8,7,122,40,7,114,152,
|
||||
129,92,227,16,14,236,192,14,229,80,14,243,48,35,193,210,65,30,228,225,23,216,225,29,222,1,30,102,72,25,59,176,131,61,180,131,27,132,195,56,140,67,57,204,195,60,184,193,57,200,195,59,
|
||||
212,3,60,204,72,180,113,8,7,118,96,7,113,8,135,113,88,135,25,219,198,14,236,96,15,237,224,6,240,32,15,229,48,15,229,32,15,246,80,14,110,16,14,227,48,14,229,48,15,243,224,6,233,224,
|
||||
14,228,80,14,248,48,35,226,236,97,28,194,129,29,216,225,23,236,33,29,230,33,29,196,33,29,216,33,29,232,33,31,102,32,157,59,188,67,61,184,3,57,148,131,57,204,88,188,112,112,7,119,120,
|
||||
7,122,8,7,122,72,135,119,112,135,25,206,135,14,229,16,14,240,16,14,236,192,14,239,48,14,243,144,14,244,80,14,51,40,48,8,135,116,144,7,55,48,135,122,112,135,113,160,135,116,120,7,119,
|
||||
248,133,115,144,135,119,168,7,120,152,7,0,0,0,0,121,32,0,0,26,1,0,0,114,30,72,32,67,136,12,25,9,114,50,72,32,35,129,140,145,145,209,68,160,16,40,100,60,49,50,66,142,144,33,163,152,
|
||||
6,100,208,82,0,0,0,139,210,88,216,6,109,80,28,20,27,71,6,209,18,25,76,178,24,6,179,64,18,49,24,202,131,68,148,161,68,87,35,0,0,0,0,83,68,75,32,86,101,114,115,105,111,110,119,99,104,
|
||||
97,114,95,115,105,122,101,102,114,97,109,101,45,112,111,105,110,116,101,114,97,105,114,46,109,97,120,95,100,101,118,105,99,101,95,98,117,102,102,101,114,115,97,105,114,46,109,97,120,
|
||||
95,99,111,110,115,116,97,110,116,95,98,117,102,102,101,114,115,97,105,114,46,109,97,120,95,116,104,114,101,97,100,103,114,111,117,112,95,98,117,102,102,101,114,115,97,105,114,46,109,
|
||||
97,120,95,116,101,120,116,117,114,101,115,97,105,114,46,109,97,120,95,114,101,97,100,95,119,114,105,116,101,95,116,101,120,116,117,114,101,115,97,105,114,46,109,97,120,95,115,97,109,
|
||||
112,108,101,114,115,65,112,112,108,101,32,109,101,116,97,108,32,118,101,114,115,105,111,110,32,51,50,48,50,51,46,51,54,56,32,40,109,101,116,97,108,102,101,45,51,50,48,50,51,46,51,54,
|
||||
56,41,77,101,116,97,108,97,105,114,46,99,111,109,112,105,108,101,46,100,101,110,111,114,109,115,95,100,105,115,97,98,108,101,97,105,114,46,99,111,109,112,105,108,101,46,102,97,115,
|
||||
116,95,109,97,116,104,95,101,110,97,98,108,101,97,105,114,46,99,111,109,112,105,108,101,46,102,114,97,109,101,98,117,102,102,101,114,95,102,101,116,99,104,95,101,110,97,98,108,101,
|
||||
97,105,114,46,118,101,114,116,101,120,95,111,117,116,112,117,116,117,115,101,114,40,108,111,99,110,48,41,97,105,114,46,97,114,103,95,116,121,112,101,95,110,97,109,101,102,108,111,97,
|
||||
116,52,97,105,114,46,97,114,103,95,110,97,109,101,79,117,116,95,67,111,108,111,114,117,115,101,114,40,108,111,99,110,49,41,102,108,111,97,116,50,79,117,116,95,85,86,97,105,114,46,112,
|
||||
111,115,105,116,105,111,110,103,108,95,80,111,115,105,116,105,111,110,97,105,114,46,118,101,114,116,101,120,95,105,110,112,117,116,97,105,114,46,108,111,99,97,116,105,111,110,95,105,
|
||||
110,100,101,120,97,80,111,115,97,85,86,97,67,111,108,111,114,97,105,114,46,98,117,102,102,101,114,97,105,114,46,98,117,102,102,101,114,95,115,105,122,101,97,105,114,46,114,101,97,100,
|
||||
97,105,114,46,97,100,100,114,101,115,115,95,115,112,97,99,101,97,105,114,46,115,116,114,117,99,116,95,116,121,112,101,95,105,110,102,111,117,83,99,97,108,101,117,84,114,97,110,115,
|
||||
108,97,116,101,97,105,114,46,97,114,103,95,116,121,112,101,95,115,105,122,101,97,105,114,46,97,114,103,95,116,121,112,101,95,97,108,105,103,110,95,115,105,122,101,117,80,117,115,104,
|
||||
67,111,110,115,116,97,110,116,112,99,0,0,0,166,119,0,0,0,0,0,0,48,130,144,4,35,8,74,51,130,144,8,35,8,201,48,130,144,16,35,8,73,49,130,144,24,35,8,201,49,130,144,32,35,8,73,50,130,
|
||||
144,40,35,8,201,50,130,112,0,51,12,106,16,172,193,12,3,27,8,109,48,195,224,6,131,26,204,48,184,1,241,6,51,12,110,80,188,193,12,131,27,24,111,48,195,224,6,7,28,204,48,184,1,18,7,51,
|
||||
12,110,144,200,193,12,129,50,195,160,6,115,64,7,51,16,75,29,176,1,29,204,16,48,51,4,205,12,129,51,131,241,64,145,52,81,51,24,79,21,89,211,53,67,129,69,210,148,205,48,152,194,41,160,
|
||||
194,12,9,29,104,27,29,176,65,100,77,220,12,9,27,104,27,27,176,65,100,77,221,12,137,26,104,155,26,176,65,36,77,222,12,10,29,196,1,29,88,100,16,7,113,64,7,86,25,204,64,213,193,7,6,114,
|
||||
176,209,1,27,132,129,24,168,193,24,180,130,25,200,193,25,196,65,132,6,83,26,204,64,168,194,42,176,130,43,204,48,216,65,42,188,194,157,1,192,113,28,199,113,28,199,113,28,199,185,129,
|
||||
27,184,129,27,184,129,27,184,129,27,184,129,69,7,122,96,89,22,29,208,129,27,208,1,46,224,2,46,240,3,122,128,130,140,4,38,40,35,54,54,187,54,151,182,55,178,58,182,50,23,51,182,176,179,
|
||||
185,81,18,59,184,3,60,200,3,61,216,3,62,232,3,63,72,133,141,205,174,205,37,141,172,204,141,110,148,224,15,114,9,75,147,115,177,43,147,155,75,123,115,27,37,0,133,164,194,210,228,92,
|
||||
216,194,220,206,234,194,206,202,190,236,202,228,230,210,222,220,70,9,66,33,167,176,52,57,151,177,183,54,184,52,182,178,175,55,56,186,180,55,183,185,81,6,81,24,5,82,72,37,44,77,206,
|
||||
197,174,76,142,174,12,111,148,224,21,0,0,0,169,24,0,0,37,0,0,0,11,10,114,40,135,119,128,7,122,88,112,152,67,61,184,195,56,176,67,57,208,195,130,230,28,198,161,13,232,65,30,194,193,
|
||||
29,230,33,29,232,33,29,222,193,29,22,52,227,96,14,231,80,15,225,32,15,228,64,15,225,32,15,231,80,14,244,176,128,129,7,121,40,135,112,96,7,118,120,135,113,8,7,122,40,7,114,88,112,156,
|
||||
195,56,180,1,59,164,131,61,148,195,2,107,28,216,33,28,220,225,28,220,32,28,228,97,28,220,32,28,232,129,30,194,97,28,208,161,28,200,97,28,194,129,29,216,97,193,1,15,244,32,15,225,80,
|
||||
15,244,128,14,0,0,0,0,209,16,0,0,6,0,0,0,7,204,60,164,131,59,156,3,59,148,3,61,160,131,60,148,67,56,144,195,1,0,0,0,97,32,0,0,68,0,0,0,19,4,65,44,16,0,0,0,11,0,0,0,148,51,0,180,37,
|
||||
64,61,7,161,72,146,52,7,161,72,9,65,48,26,48,2,48,70,0,130,32,136,127,20,115,16,150,117,97,36,163,1,52,51,0,0,0,0,0,241,48,0,0,32,0,0,0,34,71,200,144,81,18,196,43,0,0,0,0,207,115,89,
|
||||
0,111,109,110,105,112,111,116,101,110,116,32,99,104,97,114,83,105,109,112,108,101,32,67,43,43,32,84,66,65,65,97,105,114,45,97,108,105,97,115,45,115,99,111,112,101,115,40,109,97,105,
|
||||
110,48,41,97,105,114,45,97,108,105,97,115,45,115,99,111,112,101,45,97,114,103,40,51,41,0,19,132,133,89,33,216,194,44,172,24,110,193,22,104,97,67,32,11,27,134,88,192,133,90,216,48,228,
|
||||
66,46,212,194,134,224,22,0,0,157,134,5,146,40,16,130,1,36,254,157,6,103,234,40,16,130,67,0,254,131,12,1,226,12,50,4,138,51,134,48,68,22,128,255,28,195,16,76,179,13,204,5,204,54,4,89,
|
||||
48,219,16,12,194,6,1,49,0,4,0,0,0,91,138,32,200,133,67,23,182,20,68,144,11,135,46,0,0,0,0,0,0,113,32,0,0,3,0,0,0,50,14,16,34,132,0,134,6,0,0,0,0,0,0,0,0,101,12,0,0,31,0,0,0,18,3,148,
|
||||
240,0,0,0,0,3,0,0,0,5,0,0,0,9,0,0,0,76,0,0,0,1,0,0,0,88,0,0,0,0,0,0,0,88,0,0,0,1,0,0,0,112,0,0,0,0,0,0,0,14,0,0,0,24,0,0,0,0,0,0,0,5,0,0,0,5,0,0,0,0,0,0,0,112,0,0,0,0,0,0,0,0,0,0,0,
|
||||
1,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,5,0,0,0,255,255,255,255,0,36,0,0,0,0,0,0,93,12,0,0,13,0,0,0,18,3,148,102,0,0,0,0,109,97,105,110,48,51,50,48,50,51,46,51,54,56,97,105,114,54,
|
||||
52,45,97,112,112,108,101,45,109,97,99,111,115,120,49,52,46,48,46,48,0,0,0,0,0,0,0,0,0,0,
|
||||
};
|
||||
const uint8_t metallib_fragment[3787] = {
|
||||
77,84,76,66,1,128,2,0,7,0,0,129,14,0,0,0,203,14,0,0,0,0,0,0,88,0,0,0,0,0,0,0,123,0,0,0,0,0,0,0,219,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,227,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,235,0,0,0,0,0,0,0,
|
||||
224,13,0,0,0,0,0,0,1,0,0,0,123,0,0,0,78,65,77,69,6,0,109,97,105,110,48,0,84,89,80,69,1,0,1,72,65,83,72,32,0,201,103,233,140,10,95,185,107,79,93,85,82,78,218,248,8,95,184,8,139,191,
|
||||
155,174,56,51,95,203,135,255,117,44,62,77,68,83,90,8,0,224,13,0,0,0,0,0,0,79,70,70,84,24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,86,69,82,83,8,0,2,0,6,0,3,0,1,0,69,78,68,
|
||||
84,69,78,68,84,4,0,0,0,69,78,68,84,4,0,0,0,69,78,68,84,222,192,23,11,0,0,0,0,20,0,0,0,196,13,0,0,255,255,255,255,66,67,192,222,53,20,0,0,3,0,0,0,98,12,48,36,128,16,5,200,20,0,0,0,33,
|
||||
12,0,0,44,3,0,0,11,2,33,0,2,0,0,0,22,0,0,0,7,129,35,145,65,200,4,73,6,16,50,57,146,1,132,12,37,5,8,25,30,4,139,98,128,20,69,2,66,146,11,66,164,16,50,20,56,8,24,75,10,50,82,136,72,112,
|
||||
196,33,35,68,18,135,140,16,65,146,2,100,200,8,177,20,32,67,70,136,32,201,1,50,82,132,24,42,40,42,144,49,124,176,92,145,32,197,200,0,0,0,137,32,0,0,31,0,0,0,50,34,72,9,32,98,70,0,33,
|
||||
43,36,152,20,33,37,36,152,20,25,39,12,133,164,144,96,82,100,92,32,36,101,130,128,154,1,24,70,32,128,27,132,97,4,1,64,74,154,34,74,152,252,127,34,174,137,138,136,223,30,254,105,140,
|
||||
0,24,68,32,2,140,164,41,162,132,201,255,37,128,121,22,34,250,167,49,2,96,16,193,16,76,33,194,40,135,208,28,1,114,132,160,230,8,130,57,2,48,24,70,16,26,163,172,114,6,115,12,128,70,111,
|
||||
32,64,5,218,8,0,0,81,24,0,0,105,0,0,0,27,246,35,248,255,255,255,255,1,104,3,96,13,0,83,0,252,0,144,128,10,232,3,34,28,224,1,30,228,225,29,240,161,13,204,161,30,220,97,28,218,192,28,
|
||||
224,161,13,218,33,28,232,1,29,0,122,144,135,122,40,7,128,48,7,121,8,135,118,40,135,54,128,135,119,72,7,119,160,135,114,144,7,32,28,216,129,29,0,162,29,210,193,29,218,128,29,202,225,
|
||||
28,194,129,29,218,192,30,202,97,28,232,225,29,228,161,13,238,33,29,200,129,30,208,1,136,3,57,192,3,96,112,135,119,104,3,113,168,135,116,96,7,122,72,7,119,152,7,128,112,135,119,104,
|
||||
131,116,112,7,115,152,135,54,48,7,120,104,131,118,8,7,122,64,7,128,30,228,161,30,202,1,32,220,225,29,218,192,29,194,193,29,230,161,13,204,1,30,218,160,29,194,129,30,208,1,160,7,121,
|
||||
168,135,114,0,8,119,120,135,54,152,135,116,56,7,119,40,7,114,104,3,125,40,7,121,120,135,121,104,3,115,128,135,54,104,135,112,160,7,116,0,232,65,30,234,161,28,0,194,29,222,161,13,232,
|
||||
65,30,194,1,30,224,33,29,220,225,28,218,160,29,194,129,30,208,1,160,7,121,168,135,114,0,136,121,160,135,112,24,135,117,104,3,120,144,135,119,160,135,114,24,7,122,120,7,121,104,3,113,
|
||||
168,7,115,48,135,114,144,135,54,152,135,116,208,135,114,0,240,0,32,234,193,29,230,33,28,204,161,28,218,192,28,224,161,13,218,33,28,232,1,29,0,122,144,135,122,40,7,96,131,33,12,192,
|
||||
2,84,27,140,129,0,22,160,218,0,17,255,255,255,255,63,0,109,0,172,1,96,10,128,31,0,18,80,1,125,176,193,40,2,96,1,170,13,134,33,0,11,80,109,96,142,255,255,255,255,31,128,54,0,214,0,144,
|
||||
128,10,232,3,0,73,24,0,0,4,0,0,0,19,134,64,24,38,12,68,97,76,24,142,194,0,0,0,0,19,176,112,72,7,121,176,3,58,104,131,112,128,7,120,96,135,114,104,131,118,8,135,113,120,135,121,192,
|
||||
135,56,160,3,55,128,3,55,128,131,13,183,81,14,109,0,15,122,96,7,116,160,7,118,64,7,122,96,7,116,208,6,233,16,7,122,128,7,122,128,7,109,144,14,120,160,7,120,160,7,120,208,6,233,16,7,
|
||||
118,160,7,113,96,7,122,16,7,118,208,6,233,48,7,114,160,7,115,32,7,122,48,7,114,208,6,233,96,7,116,160,7,118,64,7,122,96,7,116,208,6,230,48,7,114,160,7,115,32,7,122,48,7,114,208,6,230,
|
||||
96,7,116,160,7,118,64,7,122,96,7,116,208,6,246,16,7,118,160,7,113,96,7,122,16,7,118,208,6,246,32,7,116,160,7,115,32,7,122,48,7,114,208,6,246,48,7,114,160,7,115,32,7,122,48,7,114,208,
|
||||
6,246,64,7,120,160,7,118,64,7,122,96,7,116,208,6,246,96,7,116,160,7,118,64,7,122,96,7,116,208,6,246,144,7,118,160,7,113,32,7,120,160,7,113,32,7,120,208,6,246,16,7,114,128,7,122,16,
|
||||
7,114,128,7,122,16,7,114,128,7,109,96,15,113,144,7,114,160,7,114,80,7,118,160,7,114,80,7,118,208,6,246,32,7,117,96,7,122,32,7,117,96,7,122,32,7,117,96,7,109,96,15,117,16,7,114,160,
|
||||
7,117,16,7,114,160,7,117,16,7,114,208,6,246,16,7,112,32,7,116,160,7,113,0,7,114,64,7,122,16,7,112,32,7,116,208,6,238,128,7,122,16,7,118,160,7,115,32,7,26,33,12,89,48,0,210,208,67,42,
|
||||
160,64,0,0,8,0,0,0,4,0,0,0,0,0,10,96,72,85,108,15,16,0,2,0,0,128,0,0,0,0,0,64,1,72,108,16,40,234,50,0,0,144,5,2,0,0,0,10,0,0,0,50,30,152,16,25,17,76,144,140,9,38,71,198,4,67,106,69,
|
||||
80,2,133,80,14,229,83,128,2,5,81,32,197,48,2,80,6,36,199,18,158,0,0,177,24,0,0,165,0,0,0,51,8,128,28,196,225,28,102,20,1,61,136,67,56,132,195,140,66,128,7,121,120,7,115,152,113,12,
|
||||
230,0,15,237,16,14,244,128,14,51,12,66,30,194,193,29,206,161,28,102,48,5,61,136,67,56,132,131,27,204,3,61,200,67,61,140,3,61,204,120,140,116,112,7,123,8,7,121,72,135,112,112,7,122,
|
||||
112,3,118,120,135,112,32,135,25,204,17,14,236,144,14,225,48,15,110,48,15,227,240,14,240,80,14,51,16,196,29,222,33,28,216,33,29,194,97,30,102,48,137,59,188,131,59,208,67,57,180,3,60,
|
||||
188,131,60,132,3,59,204,240,20,118,96,7,123,104,7,55,104,135,114,104,7,55,128,135,112,144,135,112,96,7,118,40,7,118,248,5,118,120,135,119,128,135,95,8,135,113,24,135,114,152,135,121,
|
||||
152,129,44,238,240,14,238,224,14,245,192,14,236,48,3,98,200,161,28,228,161,28,204,161,28,228,161,28,220,97,28,202,33,28,196,129,29,202,97,6,214,144,67,57,200,67,57,152,67,57,200,67,
|
||||
57,184,195,56,148,67,56,136,3,59,148,195,47,188,131,60,252,130,59,212,3,59,176,195,12,199,105,135,112,88,135,114,112,131,116,104,7,120,96,135,116,24,135,116,160,135,25,206,83,15,238,
|
||||
0,15,242,80,14,228,144,14,227,64,15,225,32,14,236,80,14,51,32,40,29,220,193,30,194,65,30,210,33,28,220,129,30,220,224,28,228,225,29,234,1,30,102,24,81,56,176,67,58,156,131,59,204,80,
|
||||
36,118,96,7,123,104,7,55,96,135,119,120,7,120,152,81,76,244,144,15,240,80,14,51,30,106,30,202,97,28,232,33,29,222,193,29,126,1,30,228,161,28,204,33,29,240,97,6,84,133,131,56,204,195,
|
||||
59,176,67,61,208,67,57,252,194,60,228,67,59,136,195,59,176,195,140,197,10,135,121,152,135,119,24,135,116,8,7,122,40,7,114,152,129,92,227,16,14,236,192,14,229,80,14,243,48,35,193,210,
|
||||
65,30,228,225,23,216,225,29,222,1,30,102,72,25,59,176,131,61,180,131,27,132,195,56,140,67,57,204,195,60,184,193,57,200,195,59,212,3,60,204,72,180,113,8,7,118,96,7,113,8,135,113,88,
|
||||
135,25,219,198,14,236,96,15,237,224,6,240,32,15,229,48,15,229,32,15,246,80,14,110,16,14,227,48,14,229,48,15,243,224,6,233,224,14,228,80,14,248,48,35,226,236,97,28,194,129,29,216,225,
|
||||
23,236,33,29,230,33,29,196,33,29,216,33,29,232,33,31,102,32,157,59,188,67,61,184,3,57,148,131,57,204,88,188,112,112,7,119,120,7,122,8,7,122,72,135,119,112,135,25,206,135,14,229,16,
|
||||
14,240,16,14,236,192,14,239,48,14,243,144,14,244,80,14,51,40,48,8,135,116,144,7,55,48,135,122,112,135,113,160,135,116,120,7,119,248,133,115,144,135,119,168,7,120,152,7,0,0,0,0,121,
|
||||
32,0,0,252,0,0,0,114,30,72,32,67,136,12,25,9,114,50,72,32,35,129,140,145,145,209,68,160,16,40,100,60,49,50,66,142,144,33,163,56,6,220,41,1,0,0,0,139,210,88,216,6,109,80,28,20,27,71,
|
||||
6,81,100,48,134,180,40,15,178,24,197,34,41,24,178,28,13,83,68,75,32,86,101,114,115,105,111,110,119,99,104,97,114,95,115,105,122,101,102,114,97,109,101,45,112,111,105,110,116,101,114,
|
||||
97,105,114,46,109,97,120,95,100,101,118,105,99,101,95,98,117,102,102,101,114,115,97,105,114,46,109,97,120,95,99,111,110,115,116,97,110,116,95,98,117,102,102,101,114,115,97,105,114,
|
||||
46,109,97,120,95,116,104,114,101,97,100,103,114,111,117,112,95,98,117,102,102,101,114,115,97,105,114,46,109,97,120,95,116,101,120,116,117,114,101,115,97,105,114,46,109,97,120,95,114,
|
||||
101,97,100,95,119,114,105,116,101,95,116,101,120,116,117,114,101,115,97,105,114,46,109,97,120,95,115,97,109,112,108,101,114,115,65,112,112,108,101,32,109,101,116,97,108,32,118,101,
|
||||
114,115,105,111,110,32,51,50,48,50,51,46,51,54,56,32,40,109,101,116,97,108,102,101,45,51,50,48,50,51,46,51,54,56,41,77,101,116,97,108,97,105,114,46,99,111,109,112,105,108,101,46,100,
|
||||
101,110,111,114,109,115,95,100,105,115,97,98,108,101,97,105,114,46,99,111,109,112,105,108,101,46,102,97,115,116,95,109,97,116,104,95,101,110,97,98,108,101,97,105,114,46,99,111,109,
|
||||
112,105,108,101,46,102,114,97,109,101,98,117,102,102,101,114,95,102,101,116,99,104,95,101,110,97,98,108,101,97,105,114,46,114,101,110,100,101,114,95,116,97,114,103,101,116,97,105,114,
|
||||
46,97,114,103,95,116,121,112,101,95,110,97,109,101,102,108,111,97,116,52,97,105,114,46,97,114,103,95,110,97,109,101,102,67,111,108,111,114,97,105,114,46,102,114,97,103,109,101,110,
|
||||
116,95,105,110,112,117,116,117,115,101,114,40,108,111,99,110,48,41,97,105,114,46,99,101,110,116,101,114,97,105,114,46,112,101,114,115,112,101,99,116,105,118,101,73,110,95,67,111,108,
|
||||
111,114,117,115,101,114,40,108,111,99,110,49,41,102,108,111,97,116,50,73,110,95,85,86,97,105,114,46,116,101,120,116,117,114,101,97,105,114,46,108,111,99,97,116,105,111,110,95,105,110,
|
||||
100,101,120,97,105,114,46,115,97,109,112,108,101,116,101,120,116,117,114,101,50,100,60,102,108,111,97,116,44,32,115,97,109,112,108,101,62,115,84,101,120,116,117,114,101,97,105,114,
|
||||
46,115,97,109,112,108,101,114,115,97,109,112,108,101,114,115,84,101,120,116,117,114,101,83,109,112,108,114,0,198,96,0,0,0,0,0,0,48,130,208,8,35,8,82,51,130,208,12,35,8,13,49,130,208,
|
||||
20,35,8,141,49,130,208,28,35,8,13,50,130,208,36,35,8,141,50,130,208,44,35,8,13,51,130,144,0,51,12,100,16,148,193,12,131,25,8,103,48,195,128,6,3,25,204,48,160,1,145,6,51,12,104,80,164,
|
||||
193,12,3,26,24,105,48,195,128,6,135,26,204,48,160,1,178,6,51,12,104,144,176,193,12,129,50,195,64,6,109,224,6,51,16,203,27,152,129,27,204,16,48,51,4,205,12,129,51,195,241,184,129,27,
|
||||
64,145,52,205,16,128,194,12,137,27,80,149,117,65,145,132,205,144,152,1,149,89,23,164,73,219,12,10,25,112,157,27,152,129,7,125,18,24,204,144,188,65,24,116,110,96,6,144,24,72,99,48,3,
|
||||
33,10,163,64,10,165,48,195,0,7,161,96,10,71,6,0,199,113,28,199,113,28,199,113,28,231,6,110,224,6,110,224,6,110,224,6,110,224,6,22,29,232,129,101,89,166,192,177,2,43,144,131,58,128,
|
||||
130,140,4,38,40,35,54,54,187,54,151,182,55,178,58,182,50,23,51,182,176,179,185,81,18,56,136,3,57,152,3,58,168,3,59,184,3,60,72,133,141,205,174,205,37,141,172,204,141,110,148,32,15,
|
||||
114,9,75,147,115,177,43,147,155,75,123,115,27,37,208,131,164,194,210,228,92,216,194,220,206,234,194,206,202,190,236,202,228,230,210,222,220,70,9,246,32,167,176,52,57,151,177,183,54,
|
||||
184,52,182,178,175,55,56,186,180,55,183,185,81,6,62,232,3,63,72,38,44,77,206,197,76,46,236,172,173,204,141,110,148,192,20,0,0,0,0,169,24,0,0,37,0,0,0,11,10,114,40,135,119,128,7,122,
|
||||
88,112,152,67,61,184,195,56,176,67,57,208,195,130,230,28,198,161,13,232,65,30,194,193,29,230,33,29,232,33,29,222,193,29,22,52,227,96,14,231,80,15,225,32,15,228,64,15,225,32,15,231,
|
||||
80,14,244,176,128,129,7,121,40,135,112,96,7,118,120,135,113,8,7,122,40,7,114,88,112,156,195,56,180,1,59,164,131,61,148,195,2,107,28,216,33,28,220,225,28,220,32,28,228,97,28,220,32,
|
||||
28,232,129,30,194,97,28,208,161,28,200,97,28,194,129,29,216,97,193,1,15,244,32,15,225,80,15,244,128,14,0,0,0,0,209,16,0,0,6,0,0,0,7,204,60,164,131,59,156,3,59,148,3,61,160,131,60,148,
|
||||
67,56,144,195,1,0,0,0,97,32,0,0,49,0,0,0,19,4,65,44,16,0,0,0,4,0,0,0,196,106,96,4,128,220,8,0,129,17,0,18,51,0,0,0,241,48,0,0,28,0,0,0,34,71,200,144,81,14,196,42,0,0,0,0,23,134,1,0,
|
||||
97,105,114,45,97,108,105,97,115,45,115,99,111,112,101,115,40,109,97,105,110,48,41,97,105,114,45,97,108,105,97,115,45,115,99,111,112,101,45,115,97,109,112,108,101,114,115,97,105,114,
|
||||
45,97,108,105,97,115,45,115,99,111,112,101,45,116,101,120,116,117,114,101,115,0,43,132,85,64,133,21,3,43,172,66,42,172,24,90,97,21,84,97,131,208,10,172,0,0,35,6,205,16,130,96,240,88,
|
||||
135,129,20,3,33,8,204,104,66,0,96,176,136,255,108,3,17,0,27,4,196,0,0,0,2,0,0,0,91,6,224,104,5,0,0,0,0,0,0,0,113,32,0,0,3,0,0,0,50,14,16,34,132,0,251,5,0,0,0,0,0,0,0,0,101,12,0,0,37,
|
||||
0,0,0,18,3,148,40,1,0,0,0,3,0,0,0,32,0,0,0,9,0,0,0,76,0,0,0,1,0,0,0,88,0,0,0,0,0,0,0,88,0,0,0,2,0,0,0,136,0,0,0,0,0,0,0,41,0,0,0,24,0,0,0,0,0,0,0,5,0,0,0,5,0,0,0,0,0,0,0,136,0,0,0,
|
||||
0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,5,0,0,0,255,255,255,255,0,36,0,0,5,0,0,0,27,0,0,0,5,0,0,0,27,0,0,0,255,255,255,255,8,36,0,0,0,0,0,0,93,12,0,0,20,0,0,0,18,3,
|
||||
148,161,0,0,0,0,109,97,105,110,48,97,105,114,46,115,97,109,112,108,101,95,116,101,120,116,117,114,101,95,50,100,46,118,52,102,51,50,51,50,48,50,51,46,51,54,56,97,105,114,54,52,45,97,
|
||||
112,112,108,101,45,109,97,99,111,115,120,49,52,46,48,46,48,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
};
|
||||
static uint8_t msl_vertex[800] =
|
||||
{
|
||||
35,105,110,99,108,117,100,101,32,60,109,101,116,97,108,95,115,116,100,108,105,98,62,10,35,105,110,99,108,117,100,101,32,60,115,105,109,100,47,115,105,109,100,46,104,62,10,10,117,115,
|
||||
105,110,103,32,110,97,109,101,115,112,97,99,101,32,109,101,116,97,108,59,10,10,115,116,114,117,99,116,32,95,57,10,123,10,32,32,32,32,102,108,111,97,116,52,32,67,111,108,111,114,59,
|
||||
10,32,32,32,32,102,108,111,97,116,50,32,85,86,59,10,125,59,10,10,115,116,114,117,99,116,32,85,66,79,10,123,10,32,32,32,32,102,108,111,97,116,50,32,117,83,99,97,108,101,59,10,32,32,
|
||||
32,32,102,108,111,97,116,50,32,117,84,114,97,110,115,108,97,116,101,59,10,125,59,10,10,115,116,114,117,99,116,32,109,97,105,110,48,95,111,117,116,10,123,10,32,32,32,32,102,108,111,
|
||||
97,116,52,32,79,117,116,95,67,111,108,111,114,32,91,91,117,115,101,114,40,108,111,99,110,48,41,93,93,59,10,32,32,32,32,102,108,111,97,116,50,32,79,117,116,95,85,86,32,91,91,117,115,
|
||||
101,114,40,108,111,99,110,49,41,93,93,59,10,32,32,32,32,102,108,111,97,116,52,32,103,108,95,80,111,115,105,116,105,111,110,32,91,91,112,111,115,105,116,105,111,110,93,93,59,10,125,
|
||||
59,10,10,115,116,114,117,99,116,32,109,97,105,110,48,95,105,110,10,123,10,32,32,32,32,102,108,111,97,116,50,32,97,80,111,115,32,91,91,97,116,116,114,105,98,117,116,101,40,48,41,93,
|
||||
93,59,10,32,32,32,32,102,108,111,97,116,50,32,97,85,86,32,91,91,97,116,116,114,105,98,117,116,101,40,49,41,93,93,59,10,32,32,32,32,102,108,111,97,116,52,32,97,67,111,108,111,114,32,
|
||||
91,91,97,116,116,114,105,98,117,116,101,40,50,41,93,93,59,10,125,59,10,10,118,101,114,116,101,120,32,109,97,105,110,48,95,111,117,116,32,109,97,105,110,48,40,109,97,105,110,48,95,105,
|
||||
110,32,105,110,32,91,91,115,116,97,103,101,95,105,110,93,93,44,32,99,111,110,115,116,97,110,116,32,85,66,79,38,32,117,98,111,32,91,91,98,117,102,102,101,114,40,48,41,93,93,41,10,123,
|
||||
10,32,32,32,32,109,97,105,110,48,95,111,117,116,32,111,117,116,32,61,32,123,125,59,10,32,32,32,32,95,57,32,79,117,116,32,61,32,123,125,59,10,32,32,32,32,79,117,116,46,67,111,108,111,
|
||||
114,32,61,32,105,110,46,97,67,111,108,111,114,59,10,32,32,32,32,79,117,116,46,85,86,32,61,32,105,110,46,97,85,86,59,10,32,32,32,32,111,117,116,46,103,108,95,80,111,115,105,116,105,
|
||||
111,110,32,61,32,102,108,111,97,116,52,40,40,105,110,46,97,80,111,115,32,42,32,117,98,111,46,117,83,99,97,108,101,41,32,43,32,117,98,111,46,117,84,114,97,110,115,108,97,116,101,44,
|
||||
32,48,46,48,44,32,49,46,48,41,59,10,32,32,32,32,111,117,116,46,103,108,95,80,111,115,105,116,105,111,110,46,121,32,42,61,32,40,45,49,46,48,41,59,10,32,32,32,32,111,117,116,46,79,117,
|
||||
116,95,67,111,108,111,114,32,61,32,79,117,116,46,67,111,108,111,114,59,10,32,32,32,32,111,117,116,46,79,117,116,95,85,86,32,61,32,79,117,116,46,85,86,59,10,32,32,32,32,114,101,116,
|
||||
117,114,110,32,111,117,116,59,10,125,10,10,
|
||||
};
|
||||
static uint8_t msl_fragment[580] =
|
||||
{
|
||||
35,105,110,99,108,117,100,101,32,60,109,101,116,97,108,95,115,116,100,108,105,98,62,10,35,105,110,99,108,117,100,101,32,60,115,105,109,100,47,115,105,109,100,46,104,62,10,10,117,115,
|
||||
105,110,103,32,110,97,109,101,115,112,97,99,101,32,109,101,116,97,108,59,10,10,115,116,114,117,99,116,32,95,49,49,10,123,10,32,32,32,32,102,108,111,97,116,52,32,67,111,108,111,114,
|
||||
59,10,32,32,32,32,102,108,111,97,116,50,32,85,86,59,10,125,59,10,10,115,116,114,117,99,116,32,109,97,105,110,48,95,111,117,116,10,123,10,32,32,32,32,102,108,111,97,116,52,32,102,67,
|
||||
111,108,111,114,32,91,91,99,111,108,111,114,40,48,41,93,93,59,10,125,59,10,10,115,116,114,117,99,116,32,109,97,105,110,48,95,105,110,10,123,10,32,32,32,32,102,108,111,97,116,52,32,
|
||||
73,110,95,67,111,108,111,114,32,91,91,117,115,101,114,40,108,111,99,110,48,41,93,93,59,10,32,32,32,32,102,108,111,97,116,50,32,73,110,95,85,86,32,91,91,117,115,101,114,40,108,111,99,
|
||||
110,49,41,93,93,59,10,125,59,10,10,102,114,97,103,109,101,110,116,32,109,97,105,110,48,95,111,117,116,32,109,97,105,110,48,40,109,97,105,110,48,95,105,110,32,105,110,32,91,91,115,116,
|
||||
97,103,101,95,105,110,93,93,44,32,116,101,120,116,117,114,101,50,100,60,102,108,111,97,116,62,32,115,84,101,120,116,117,114,101,32,91,91,116,101,120,116,117,114,101,40,48,41,93,93,
|
||||
44,32,115,97,109,112,108,101,114,32,115,84,101,120,116,117,114,101,83,109,112,108,114,32,91,91,115,97,109,112,108,101,114,40,48,41,93,93,41,10,123,10,32,32,32,32,109,97,105,110,48,
|
||||
95,111,117,116,32,111,117,116,32,61,32,123,125,59,10,32,32,32,32,95,49,49,32,73,110,32,61,32,123,125,59,10,32,32,32,32,73,110,46,67,111,108,111,114,32,61,32,105,110,46,73,110,95,67,
|
||||
111,108,111,114,59,10,32,32,32,32,73,110,46,85,86,32,61,32,105,110,46,73,110,95,85,86,59,10,32,32,32,32,111,117,116,46,102,67,111,108,111,114,32,61,32,73,110,46,67,111,108,111,114,
|
||||
32,42,32,115,84,101,120,116,117,114,101,46,115,97,109,112,108,101,40,115,84,101,120,116,117,114,101,83,109,112,108,114,44,32,73,110,46,85,86,41,59,10,32,32,32,32,114,101,116,117,114,
|
||||
110,32,111,117,116,59,10,125,10,10,
|
||||
};
|
||||
#elif TARGET_OS_IPHONE
|
||||
const uint8_t metallib_vertex[3876] = {
|
||||
77,84,76,66,1,0,2,0,7,0,0,130,18,0,1,0,36,15,0,0,0,0,0,0,88,0,0,0,0,0,0,0,123,0,0,0,0,0,0,0,219,0,0,0,0,0,0,0,49,0,0,0,0,0,0,0,12,1,0,0,0,0,0,0,8,0,0,0,0,0,0,0,20,1,0,0,0,0,0,0,16,
|
||||
14,0,0,0,0,0,0,1,0,0,0,123,0,0,0,78,65,77,69,6,0,109,97,105,110,48,0,84,89,80,69,1,0,0,72,65,83,72,32,0,240,54,230,217,232,66,102,78,35,5,77,235,101,252,229,192,148,96,126,162,111,
|
||||
77,253,247,211,52,17,198,182,137,68,244,77,68,83,90,8,0,16,14,0,0,0,0,0,0,79,70,70,84,24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,86,69,82,83,8,0,2,0,7,0,3,0,2,0,69,78,68,
|
||||
84,69,78,68,84,45,0,0,0,86,65,84,84,24,0,3,0,97,80,111,115,0,0,128,97,85,86,0,1,128,97,67,111,108,111,114,0,2,128,86,65,84,89,5,0,3,0,4,4,6,69,78,68,84,4,0,0,0,69,78,68,84,222,192,
|
||||
23,11,0,0,0,0,20,0,0,0,252,13,0,0,255,255,255,255,66,67,192,222,53,20,0,0,3,0,0,0,98,12,48,36,128,16,5,200,20,0,0,0,33,12,0,0,72,3,0,0,11,2,33,0,2,0,0,0,22,0,0,0,7,129,35,145,65,200,
|
||||
4,73,6,16,50,57,146,1,132,12,37,5,8,25,30,4,139,98,128,16,69,2,66,146,11,66,132,16,50,20,56,8,24,75,10,50,66,136,72,112,196,33,35,68,18,135,140,16,65,146,2,100,200,8,177,20,32,67,70,
|
||||
136,32,201,1,50,66,132,24,42,40,42,144,49,124,176,92,145,32,196,200,0,0,0,137,32,0,0,24,0,0,0,50,34,8,9,32,98,70,0,33,43,36,152,16,33,37,36,152,16,25,39,12,133,164,144,96,66,100,92,
|
||||
32,36,100,130,224,153,1,24,70,32,128,97,4,1,184,67,72,32,37,77,17,37,76,62,149,82,210,193,57,141,52,1,205,148,4,145,65,4,66,48,197,136,68,145,13,4,204,17,128,129,10,228,28,1,40,12,
|
||||
34,8,194,48,2,145,140,0,0,0,0,0,81,24,0,0,100,0,0,0,27,246,35,248,255,255,255,255,1,48,5,192,15,0,56,0,254,0,144,0,10,232,3,34,28,224,1,30,228,225,29,240,161,13,204,161,30,220,97,28,
|
||||
218,192,28,224,161,13,218,33,28,232,1,29,0,122,144,135,122,40,7,128,48,7,121,8,135,118,40,135,54,128,135,119,72,7,119,160,135,114,144,7,32,28,216,129,29,0,162,29,210,193,29,218,128,
|
||||
29,202,225,28,194,129,29,218,192,30,202,97,28,232,225,29,228,161,13,238,33,29,200,129,30,208,1,136,3,57,192,3,96,112,135,119,104,3,113,168,135,116,96,7,122,72,7,119,152,7,128,112,135,
|
||||
119,104,131,116,112,7,115,152,135,54,48,7,120,104,131,118,8,7,122,64,7,128,30,228,161,30,202,1,32,220,225,29,218,192,29,194,193,29,230,161,13,204,1,30,218,160,29,194,129,30,208,1,160,
|
||||
7,121,168,135,114,0,8,119,120,135,54,152,135,116,56,7,119,40,7,114,104,3,125,40,7,121,120,135,121,104,3,115,128,135,54,104,135,112,160,7,116,0,232,65,30,234,161,28,0,194,29,222,161,
|
||||
13,232,65,30,194,1,30,224,33,29,220,225,28,218,160,29,194,129,30,208,1,160,7,121,168,135,114,0,136,121,160,135,112,24,135,117,104,3,120,144,135,119,160,135,114,24,7,122,120,7,121,104,
|
||||
3,113,168,7,115,48,135,114,144,135,54,152,135,116,208,135,114,0,240,0,32,234,193,29,230,33,28,204,161,28,218,192,28,224,161,13,218,33,28,232,1,29,0,122,144,135,122,40,7,96,195,24,8,
|
||||
4,176,0,164,0,84,65,128,4,105,0,13,225,144,14,242,208,6,226,80,15,230,96,14,229,32,15,109,224,14,239,208,6,225,192,14,233,16,14,243,0,0,0,73,24,0,0,1,0,0,0,19,132,64,0,19,170,112,72,
|
||||
7,121,176,3,58,104,131,112,128,7,120,96,135,114,104,131,116,120,135,121,136,3,60,112,131,56,112,3,56,216,112,27,229,208,6,240,160,7,118,64,7,122,96,7,116,160,7,118,64,7,109,144,14,
|
||||
113,160,7,120,160,7,120,208,6,233,128,7,122,128,7,122,128,7,109,144,14,113,96,7,122,16,7,118,160,7,113,96,7,109,144,14,115,32,7,122,48,7,114,160,7,115,32,7,109,144,14,118,64,7,122,
|
||||
96,7,116,160,7,118,64,7,109,96,14,115,32,7,122,48,7,114,160,7,115,32,7,109,96,14,118,64,7,122,96,7,116,160,7,118,64,7,109,96,15,113,96,7,122,16,7,118,160,7,113,96,7,109,96,15,114,64,
|
||||
7,122,48,7,114,160,7,115,32,7,109,96,15,115,32,7,122,48,7,114,160,7,115,32,7,109,96,15,116,128,7,122,96,7,116,160,7,118,64,7,109,96,15,118,64,7,122,96,7,116,160,7,118,64,7,109,96,15,
|
||||
121,96,7,122,16,7,114,128,7,122,16,7,114,128,7,109,96,15,113,32,7,120,160,7,113,32,7,120,160,7,113,32,7,120,208,6,246,16,7,121,32,7,122,32,7,117,96,7,122,32,7,117,96,7,109,96,15,114,
|
||||
80,7,118,160,7,114,80,7,118,160,7,114,80,7,118,208,6,246,80,7,113,32,7,122,80,7,113,32,7,122,80,7,113,32,7,109,96,15,113,0,7,114,64,7,122,16,7,112,32,7,116,160,7,113,0,7,114,64,7,109,
|
||||
224,14,120,160,7,113,96,7,122,48,7,114,160,17,194,144,5,3,32,13,61,164,2,10,3,0,128,0,0,0,64,0,0,0,0,0,160,0,36,54,8,20,85,26,0,0,200,2,1,0,11,0,0,0,50,30,152,16,25,17,76,144,140,9,
|
||||
38,71,198,4,67,202,34,40,129,66,40,135,242,41,64,129,130,40,144,17,128,50,160,29,1,32,29,75,144,2,0,0,0,0,177,24,0,0,165,0,0,0,51,8,128,28,196,225,28,102,20,1,61,136,67,56,132,195,
|
||||
140,66,128,7,121,120,7,115,152,113,12,230,0,15,237,16,14,244,128,14,51,12,66,30,194,193,29,206,161,28,102,48,5,61,136,67,56,132,131,27,204,3,61,200,67,61,140,3,61,204,120,140,116,112,
|
||||
7,123,8,7,121,72,135,112,112,7,122,112,3,118,120,135,112,32,135,25,204,17,14,236,144,14,225,48,15,110,48,15,227,240,14,240,80,14,51,16,196,29,222,33,28,216,33,29,194,97,30,102,48,137,
|
||||
59,188,131,59,208,67,57,180,3,60,188,131,60,132,3,59,204,240,20,118,96,7,123,104,7,55,104,135,114,104,7,55,128,135,112,144,135,112,96,7,118,40,7,118,248,5,118,120,135,119,128,135,95,
|
||||
8,135,113,24,135,114,152,135,121,152,129,44,238,240,14,238,224,14,245,192,14,236,48,3,98,200,161,28,228,161,28,204,161,28,228,161,28,220,97,28,202,33,28,196,129,29,202,97,6,214,144,
|
||||
67,57,200,67,57,152,67,57,200,67,57,184,195,56,148,67,56,136,3,59,148,195,47,188,131,60,252,130,59,212,3,59,176,195,12,199,105,135,112,88,135,114,112,131,116,104,7,120,96,135,116,24,
|
||||
135,116,160,135,25,206,83,15,238,0,15,242,80,14,228,144,14,227,64,15,225,32,14,236,80,14,51,32,40,29,220,193,30,194,65,30,210,33,28,220,129,30,220,224,28,228,225,29,234,1,30,102,24,
|
||||
81,56,176,67,58,156,131,59,204,80,36,118,96,7,123,104,7,55,96,135,119,120,7,120,152,81,76,244,144,15,240,80,14,51,30,106,30,202,97,28,232,33,29,222,193,29,126,1,30,228,161,28,204,33,
|
||||
29,240,97,6,84,133,131,56,204,195,59,176,67,61,208,67,57,252,194,60,228,67,59,136,195,59,176,195,140,197,10,135,121,152,135,119,24,135,116,8,7,122,40,7,114,152,129,92,227,16,14,236,
|
||||
192,14,229,80,14,243,48,35,193,210,65,30,228,225,23,216,225,29,222,1,30,102,72,25,59,176,131,61,180,131,27,132,195,56,140,67,57,204,195,60,184,193,57,200,195,59,212,3,60,204,72,180,
|
||||
113,8,7,118,96,7,113,8,135,113,88,135,25,219,198,14,236,96,15,237,224,6,240,32,15,229,48,15,229,32,15,246,80,14,110,16,14,227,48,14,229,48,15,243,224,6,233,224,14,228,80,14,248,48,
|
||||
35,226,236,97,28,194,129,29,216,225,23,236,33,29,230,33,29,196,33,29,216,33,29,232,33,31,102,32,157,59,188,67,61,184,3,57,148,131,57,204,88,188,112,112,7,119,120,7,122,8,7,122,72,135,
|
||||
119,112,135,25,206,135,14,229,16,14,240,16,14,236,192,14,239,48,14,243,144,14,244,80,14,51,40,48,8,135,116,144,7,55,48,135,122,112,135,113,160,135,116,120,7,119,248,133,115,144,135,
|
||||
119,168,7,120,152,7,0,0,0,0,121,32,0,0,25,1,0,0,114,30,72,32,67,136,12,25,9,114,50,72,32,35,129,140,145,145,209,68,160,16,40,100,60,49,50,66,142,144,33,163,152,6,100,208,82,0,0,0,139,
|
||||
210,88,216,6,109,80,28,20,27,71,6,209,18,25,76,178,24,6,179,64,18,49,24,202,131,68,148,161,68,87,35,0,0,0,0,83,68,75,32,86,101,114,115,105,111,110,119,99,104,97,114,95,115,105,122,
|
||||
101,102,114,97,109,101,45,112,111,105,110,116,101,114,97,105,114,46,109,97,120,95,100,101,118,105,99,101,95,98,117,102,102,101,114,115,97,105,114,46,109,97,120,95,99,111,110,115,116,
|
||||
97,110,116,95,98,117,102,102,101,114,115,97,105,114,46,109,97,120,95,116,104,114,101,97,100,103,114,111,117,112,95,98,117,102,102,101,114,115,97,105,114,46,109,97,120,95,116,101,120,
|
||||
116,117,114,101,115,97,105,114,46,109,97,120,95,114,101,97,100,95,119,114,105,116,101,95,116,101,120,116,117,114,101,115,97,105,114,46,109,97,120,95,115,97,109,112,108,101,114,115,
|
||||
65,112,112,108,101,32,109,101,116,97,108,32,118,101,114,115,105,111,110,32,51,50,48,50,51,46,51,54,56,32,40,109,101,116,97,108,102,101,45,51,50,48,50,51,46,51,54,56,41,77,101,116,97,
|
||||
108,97,105,114,46,99,111,109,112,105,108,101,46,100,101,110,111,114,109,115,95,100,105,115,97,98,108,101,97,105,114,46,99,111,109,112,105,108,101,46,102,97,115,116,95,109,97,116,104,
|
||||
95,101,110,97,98,108,101,97,105,114,46,99,111,109,112,105,108,101,46,102,114,97,109,101,98,117,102,102,101,114,95,102,101,116,99,104,95,101,110,97,98,108,101,97,105,114,46,118,101,
|
||||
114,116,101,120,95,111,117,116,112,117,116,117,115,101,114,40,108,111,99,110,48,41,97,105,114,46,97,114,103,95,116,121,112,101,95,110,97,109,101,102,108,111,97,116,52,97,105,114,46,
|
||||
97,114,103,95,110,97,109,101,79,117,116,95,67,111,108,111,114,117,115,101,114,40,108,111,99,110,49,41,102,108,111,97,116,50,79,117,116,95,85,86,97,105,114,46,112,111,115,105,116,105,
|
||||
111,110,103,108,95,80,111,115,105,116,105,111,110,97,105,114,46,118,101,114,116,101,120,95,105,110,112,117,116,97,105,114,46,108,111,99,97,116,105,111,110,95,105,110,100,101,120,97,
|
||||
80,111,115,97,85,86,97,67,111,108,111,114,97,105,114,46,98,117,102,102,101,114,97,105,114,46,98,117,102,102,101,114,95,115,105,122,101,97,105,114,46,114,101,97,100,97,105,114,46,97,
|
||||
100,100,114,101,115,115,95,115,112,97,99,101,97,105,114,46,115,116,114,117,99,116,95,116,121,112,101,95,105,110,102,111,117,83,99,97,108,101,117,84,114,97,110,115,108,97,116,101,97,
|
||||
105,114,46,97,114,103,95,116,121,112,101,95,115,105,122,101,97,105,114,46,97,114,103,95,116,121,112,101,95,97,108,105,103,110,95,115,105,122,101,117,80,117,115,104,67,111,110,115,116,
|
||||
97,110,116,112,99,0,0,0,230,117,0,0,0,0,0,0,48,130,144,4,35,8,10,51,130,144,8,35,8,201,48,130,144,16,35,8,73,49,130,144,24,35,8,201,49,130,144,32,35,8,73,50,130,144,40,35,8,7,48,195,
|
||||
160,6,193,26,204,48,176,129,208,6,51,12,110,48,168,193,12,131,27,16,111,48,195,224,6,197,27,204,48,184,129,241,6,51,12,110,112,192,193,12,131,27,32,113,48,195,224,6,137,28,204,16,40,
|
||||
51,12,106,224,6,115,48,3,177,208,129,26,204,193,12,1,51,67,208,204,16,56,51,24,15,20,73,19,53,131,241,84,145,53,93,51,20,88,36,77,217,12,67,41,152,194,41,204,144,204,129,182,205,1,
|
||||
27,68,214,196,205,144,176,129,182,177,1,27,68,214,212,205,144,168,129,182,169,1,27,68,210,228,205,160,204,65,28,204,129,69,6,113,16,7,115,96,149,193,12,20,29,124,96,32,7,219,28,176,
|
||||
65,24,136,129,26,140,1,43,152,129,28,156,65,28,68,104,48,165,193,12,68,42,168,194,42,180,194,12,67,29,160,130,43,156,25,0,28,199,113,28,199,113,28,199,113,110,224,6,110,224,6,110,224,
|
||||
6,110,224,6,110,96,209,129,30,88,150,69,7,116,224,6,116,128,11,184,128,11,252,128,30,160,32,35,129,9,202,136,141,205,174,205,165,237,141,172,142,173,204,197,140,45,236,108,110,148,
|
||||
164,14,236,224,14,240,32,15,244,96,15,248,160,15,82,97,99,179,107,115,73,35,43,115,163,27,37,240,131,92,194,210,228,92,236,202,228,230,210,222,220,70,9,254,32,169,176,52,57,23,182,
|
||||
48,183,179,186,176,179,178,47,187,50,185,185,180,55,183,81,2,80,200,41,44,77,206,101,236,173,13,46,141,173,236,235,13,142,46,237,205,109,110,148,33,20,68,97,20,82,9,75,147,115,177,
|
||||
43,147,163,43,195,27,37,112,5,0,0,0,169,24,0,0,37,0,0,0,11,10,114,40,135,119,128,7,122,88,112,152,67,61,184,195,56,176,67,57,208,195,130,230,28,198,161,13,232,65,30,194,193,29,230,
|
||||
33,29,232,33,29,222,193,29,22,52,227,96,14,231,80,15,225,32,15,228,64,15,225,32,15,231,80,14,244,176,128,129,7,121,40,135,112,96,7,118,120,135,113,8,7,122,40,7,114,88,112,156,195,56,
|
||||
180,1,59,164,131,61,148,195,2,107,28,216,33,28,220,225,28,220,32,28,228,97,28,220,32,28,232,129,30,194,97,28,208,161,28,200,97,28,194,129,29,216,97,193,1,15,244,32,15,225,80,15,244,
|
||||
128,14,0,0,0,0,209,16,0,0,6,0,0,0,7,204,60,164,131,59,156,3,59,148,3,61,160,131,60,148,67,56,144,195,1,0,0,0,97,32,0,0,68,0,0,0,19,4,65,44,16,0,0,0,11,0,0,0,148,51,0,197,64,91,2,212,
|
||||
115,16,73,20,69,115,16,73,36,17,4,163,1,35,0,99,4,32,8,130,248,71,49,7,97,89,23,70,50,26,64,51,3,0,0,0,241,48,0,0,32,0,0,0,34,71,200,144,81,18,196,43,0,0,0,0,207,115,89,0,111,109,110,
|
||||
105,112,111,116,101,110,116,32,99,104,97,114,83,105,109,112,108,101,32,67,43,43,32,84,66,65,65,97,105,114,45,97,108,105,97,115,45,115,99,111,112,101,115,40,109,97,105,110,48,41,97,
|
||||
105,114,45,97,108,105,97,115,45,115,99,111,112,101,45,97,114,103,40,51,41,0,19,132,101,89,33,212,130,44,172,24,108,161,22,102,97,67,16,11,27,6,88,184,5,90,216,48,224,2,46,208,194,134,
|
||||
192,22,0,0,157,6,38,154,40,16,130,65,36,254,157,134,135,234,40,16,130,67,0,254,131,12,1,226,12,50,4,138,51,134,48,68,22,128,255,28,195,16,76,179,13,12,6,204,54,4,90,48,219,16,12,194,
|
||||
6,1,49,0,4,0,0,0,91,138,32,192,133,35,23,182,20,68,128,11,71,46,0,0,0,0,0,0,113,32,0,0,3,0,0,0,50,14,16,34,132,0,132,6,0,0,0,0,0,0,0,0,101,12,0,0,31,0,0,0,18,3,148,240,0,0,0,0,3,0,
|
||||
0,0,5,0,0,0,9,0,0,0,76,0,0,0,1,0,0,0,88,0,0,0,0,0,0,0,88,0,0,0,1,0,0,0,112,0,0,0,0,0,0,0,14,0,0,0,21,0,0,0,0,0,0,0,5,0,0,0,5,0,0,0,0,0,0,0,112,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,
|
||||
0,0,0,0,5,0,0,0,0,0,0,0,5,0,0,0,255,255,255,255,0,36,0,0,0,0,0,0,93,12,0,0,12,0,0,0,18,3,148,99,0,0,0,0,109,97,105,110,48,51,50,48,50,51,46,51,54,56,97,105,114,54,52,45,97,112,112,
|
||||
108,101,45,105,111,115,49,56,46,49,46,48,0,0,0,0,0,
|
||||
};
|
||||
const uint8_t metallib_fragment[3771] = {
|
||||
77,84,76,66,1,0,2,0,7,0,0,130,18,0,1,0,187,14,0,0,0,0,0,0,88,0,0,0,0,0,0,0,123,0,0,0,0,0,0,0,219,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,227,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,235,0,0,0,0,0,0,0,208,
|
||||
13,0,0,0,0,0,0,1,0,0,0,123,0,0,0,78,65,77,69,6,0,109,97,105,110,48,0,84,89,80,69,1,0,1,72,65,83,72,32,0,167,26,51,31,140,153,203,226,66,149,243,47,185,58,96,202,28,176,71,121,86,159,
|
||||
244,234,235,69,155,58,121,67,241,212,77,68,83,90,8,0,208,13,0,0,0,0,0,0,79,70,70,84,24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,86,69,82,83,8,0,2,0,7,0,3,0,2,0,69,78,68,84,
|
||||
69,78,68,84,4,0,0,0,69,78,68,84,4,0,0,0,69,78,68,84,222,192,23,11,0,0,0,0,20,0,0,0,180,13,0,0,255,255,255,255,66,67,192,222,53,20,0,0,3,0,0,0,98,12,48,36,128,16,5,200,20,0,0,0,33,12,
|
||||
0,0,41,3,0,0,11,2,33,0,2,0,0,0,22,0,0,0,7,129,35,145,65,200,4,73,6,16,50,57,146,1,132,12,37,5,8,25,30,4,139,98,128,20,69,2,66,146,11,66,164,16,50,20,56,8,24,75,10,50,82,136,72,112,
|
||||
196,33,35,68,18,135,140,16,65,146,2,100,200,8,177,20,32,67,70,136,32,201,1,50,82,132,24,42,40,42,144,49,124,176,92,145,32,197,200,0,0,0,137,32,0,0,31,0,0,0,50,34,72,9,32,98,70,0,33,
|
||||
43,36,152,20,33,37,36,152,20,25,39,12,133,164,144,96,82,100,92,32,36,101,130,128,154,1,24,70,32,128,27,132,97,4,1,64,74,154,34,74,152,252,127,34,174,137,138,136,223,30,254,105,140,
|
||||
0,24,68,32,2,140,164,41,162,132,201,255,37,128,121,22,34,250,167,49,2,96,16,193,16,76,33,194,40,135,208,28,1,114,132,160,230,8,130,57,2,48,24,70,16,26,163,172,114,6,115,12,128,70,111,
|
||||
32,64,5,218,8,0,0,81,24,0,0,105,0,0,0,27,246,35,248,255,255,255,255,1,104,3,96,13,0,83,0,252,0,144,128,10,232,3,34,28,224,1,30,228,225,29,240,161,13,204,161,30,220,97,28,218,192,28,
|
||||
224,161,13,218,33,28,232,1,29,0,122,144,135,122,40,7,128,48,7,121,8,135,118,40,135,54,128,135,119,72,7,119,160,135,114,144,7,32,28,216,129,29,0,162,29,210,193,29,218,128,29,202,225,
|
||||
28,194,129,29,218,192,30,202,97,28,232,225,29,228,161,13,238,33,29,200,129,30,208,1,136,3,57,192,3,96,112,135,119,104,3,113,168,135,116,96,7,122,72,7,119,152,7,128,112,135,119,104,
|
||||
131,116,112,7,115,152,135,54,48,7,120,104,131,118,8,7,122,64,7,128,30,228,161,30,202,1,32,220,225,29,218,192,29,194,193,29,230,161,13,204,1,30,218,160,29,194,129,30,208,1,160,7,121,
|
||||
168,135,114,0,8,119,120,135,54,152,135,116,56,7,119,40,7,114,104,3,125,40,7,121,120,135,121,104,3,115,128,135,54,104,135,112,160,7,116,0,232,65,30,234,161,28,0,194,29,222,161,13,232,
|
||||
65,30,194,1,30,224,33,29,220,225,28,218,160,29,194,129,30,208,1,160,7,121,168,135,114,0,136,121,160,135,112,24,135,117,104,3,120,144,135,119,160,135,114,24,7,122,120,7,121,104,3,113,
|
||||
168,7,115,48,135,114,144,135,54,152,135,116,208,135,114,0,240,0,32,234,193,29,230,33,28,204,161,28,218,192,28,224,161,13,218,33,28,232,1,29,0,122,144,135,122,40,7,96,131,33,12,192,
|
||||
2,84,27,140,129,0,22,160,218,0,17,255,255,255,255,63,0,109,0,172,1,96,10,128,31,0,18,80,1,125,176,193,40,2,96,1,170,13,134,33,0,11,80,109,96,142,255,255,255,255,31,128,54,0,214,0,144,
|
||||
128,10,232,3,0,73,24,0,0,4,0,0,0,19,134,64,24,38,12,68,97,76,24,142,194,0,0,0,0,19,170,112,72,7,121,176,3,58,104,131,112,128,7,120,96,135,114,104,131,116,120,135,121,136,3,60,112,131,
|
||||
56,112,3,56,216,112,27,229,208,6,240,160,7,118,64,7,122,96,7,116,160,7,118,64,7,109,144,14,113,160,7,120,160,7,120,208,6,233,128,7,122,128,7,122,128,7,109,144,14,113,96,7,122,16,7,
|
||||
118,160,7,113,96,7,109,144,14,115,32,7,122,48,7,114,160,7,115,32,7,109,144,14,118,64,7,122,96,7,116,160,7,118,64,7,109,96,14,115,32,7,122,48,7,114,160,7,115,32,7,109,96,14,118,64,7,
|
||||
122,96,7,116,160,7,118,64,7,109,96,15,113,96,7,122,16,7,118,160,7,113,96,7,109,96,15,114,64,7,122,48,7,114,160,7,115,32,7,109,96,15,115,32,7,122,48,7,114,160,7,115,32,7,109,96,15,116,
|
||||
128,7,122,96,7,116,160,7,118,64,7,109,96,15,118,64,7,122,96,7,116,160,7,118,64,7,109,96,15,121,96,7,122,16,7,114,128,7,122,16,7,114,128,7,109,96,15,113,32,7,120,160,7,113,32,7,120,
|
||||
160,7,113,32,7,120,208,6,246,16,7,121,32,7,122,32,7,117,96,7,122,32,7,117,96,7,109,96,15,114,80,7,118,160,7,114,80,7,118,160,7,114,80,7,118,208,6,246,80,7,113,32,7,122,80,7,113,32,
|
||||
7,122,80,7,113,32,7,109,96,15,113,0,7,114,64,7,122,16,7,112,32,7,116,160,7,113,0,7,114,64,7,109,224,14,120,160,7,113,96,7,122,48,7,114,160,17,194,144,5,3,32,13,61,164,2,10,4,0,128,
|
||||
0,0,0,64,0,0,0,0,0,160,0,134,84,197,246,0,1,32,0,0,0,8,0,0,0,0,0,20,128,196,6,129,162,43,3,0,0,89,32,10,0,0,0,50,30,152,16,25,17,76,144,140,9,38,71,198,4,67,106,69,80,2,133,80,14,229,
|
||||
83,128,2,5,81,32,35,0,101,64,114,44,65,10,0,0,0,177,24,0,0,165,0,0,0,51,8,128,28,196,225,28,102,20,1,61,136,67,56,132,195,140,66,128,7,121,120,7,115,152,113,12,230,0,15,237,16,14,244,
|
||||
128,14,51,12,66,30,194,193,29,206,161,28,102,48,5,61,136,67,56,132,131,27,204,3,61,200,67,61,140,3,61,204,120,140,116,112,7,123,8,7,121,72,135,112,112,7,122,112,3,118,120,135,112,32,
|
||||
135,25,204,17,14,236,144,14,225,48,15,110,48,15,227,240,14,240,80,14,51,16,196,29,222,33,28,216,33,29,194,97,30,102,48,137,59,188,131,59,208,67,57,180,3,60,188,131,60,132,3,59,204,
|
||||
240,20,118,96,7,123,104,7,55,104,135,114,104,7,55,128,135,112,144,135,112,96,7,118,40,7,118,248,5,118,120,135,119,128,135,95,8,135,113,24,135,114,152,135,121,152,129,44,238,240,14,
|
||||
238,224,14,245,192,14,236,48,3,98,200,161,28,228,161,28,204,161,28,228,161,28,220,97,28,202,33,28,196,129,29,202,97,6,214,144,67,57,200,67,57,152,67,57,200,67,57,184,195,56,148,67,
|
||||
56,136,3,59,148,195,47,188,131,60,252,130,59,212,3,59,176,195,12,199,105,135,112,88,135,114,112,131,116,104,7,120,96,135,116,24,135,116,160,135,25,206,83,15,238,0,15,242,80,14,228,
|
||||
144,14,227,64,15,225,32,14,236,80,14,51,32,40,29,220,193,30,194,65,30,210,33,28,220,129,30,220,224,28,228,225,29,234,1,30,102,24,81,56,176,67,58,156,131,59,204,80,36,118,96,7,123,104,
|
||||
7,55,96,135,119,120,7,120,152,81,76,244,144,15,240,80,14,51,30,106,30,202,97,28,232,33,29,222,193,29,126,1,30,228,161,28,204,33,29,240,97,6,84,133,131,56,204,195,59,176,67,61,208,67,
|
||||
57,252,194,60,228,67,59,136,195,59,176,195,140,197,10,135,121,152,135,119,24,135,116,8,7,122,40,7,114,152,129,92,227,16,14,236,192,14,229,80,14,243,48,35,193,210,65,30,228,225,23,216,
|
||||
225,29,222,1,30,102,72,25,59,176,131,61,180,131,27,132,195,56,140,67,57,204,195,60,184,193,57,200,195,59,212,3,60,204,72,180,113,8,7,118,96,7,113,8,135,113,88,135,25,219,198,14,236,
|
||||
96,15,237,224,6,240,32,15,229,48,15,229,32,15,246,80,14,110,16,14,227,48,14,229,48,15,243,224,6,233,224,14,228,80,14,248,48,35,226,236,97,28,194,129,29,216,225,23,236,33,29,230,33,
|
||||
29,196,33,29,216,33,29,232,33,31,102,32,157,59,188,67,61,184,3,57,148,131,57,204,88,188,112,112,7,119,120,7,122,8,7,122,72,135,119,112,135,25,206,135,14,229,16,14,240,16,14,236,192,
|
||||
14,239,48,14,243,144,14,244,80,14,51,40,48,8,135,116,144,7,55,48,135,122,112,135,113,160,135,116,120,7,119,248,133,115,144,135,119,168,7,120,152,7,0,0,0,0,121,32,0,0,251,0,0,0,114,
|
||||
30,72,32,67,136,12,25,9,114,50,72,32,35,129,140,145,145,209,68,160,16,40,100,60,49,50,66,142,144,33,163,56,6,220,41,1,0,0,0,139,210,88,216,6,109,80,28,20,27,71,6,81,100,48,134,180,
|
||||
40,15,178,24,197,34,41,24,178,28,13,83,68,75,32,86,101,114,115,105,111,110,119,99,104,97,114,95,115,105,122,101,102,114,97,109,101,45,112,111,105,110,116,101,114,97,105,114,46,109,
|
||||
97,120,95,100,101,118,105,99,101,95,98,117,102,102,101,114,115,97,105,114,46,109,97,120,95,99,111,110,115,116,97,110,116,95,98,117,102,102,101,114,115,97,105,114,46,109,97,120,95,116,
|
||||
104,114,101,97,100,103,114,111,117,112,95,98,117,102,102,101,114,115,97,105,114,46,109,97,120,95,116,101,120,116,117,114,101,115,97,105,114,46,109,97,120,95,114,101,97,100,95,119,114,
|
||||
105,116,101,95,116,101,120,116,117,114,101,115,97,105,114,46,109,97,120,95,115,97,109,112,108,101,114,115,65,112,112,108,101,32,109,101,116,97,108,32,118,101,114,115,105,111,110,32,
|
||||
51,50,48,50,51,46,51,54,56,32,40,109,101,116,97,108,102,101,45,51,50,48,50,51,46,51,54,56,41,77,101,116,97,108,97,105,114,46,99,111,109,112,105,108,101,46,100,101,110,111,114,109,115,
|
||||
95,100,105,115,97,98,108,101,97,105,114,46,99,111,109,112,105,108,101,46,102,97,115,116,95,109,97,116,104,95,101,110,97,98,108,101,97,105,114,46,99,111,109,112,105,108,101,46,102,114,
|
||||
97,109,101,98,117,102,102,101,114,95,102,101,116,99,104,95,101,110,97,98,108,101,97,105,114,46,114,101,110,100,101,114,95,116,97,114,103,101,116,97,105,114,46,97,114,103,95,116,121,
|
||||
112,101,95,110,97,109,101,102,108,111,97,116,52,97,105,114,46,97,114,103,95,110,97,109,101,102,67,111,108,111,114,97,105,114,46,102,114,97,103,109,101,110,116,95,105,110,112,117,116,
|
||||
117,115,101,114,40,108,111,99,110,48,41,97,105,114,46,99,101,110,116,101,114,97,105,114,46,112,101,114,115,112,101,99,116,105,118,101,73,110,95,67,111,108,111,114,117,115,101,114,40,
|
||||
108,111,99,110,49,41,102,108,111,97,116,50,73,110,95,85,86,97,105,114,46,116,101,120,116,117,114,101,97,105,114,46,108,111,99,97,116,105,111,110,95,105,110,100,101,120,97,105,114,46,
|
||||
115,97,109,112,108,101,116,101,120,116,117,114,101,50,100,60,102,108,111,97,116,44,32,115,97,109,112,108,101,62,115,84,101,120,116,117,114,101,97,105,114,46,115,97,109,112,108,101,
|
||||
114,115,97,109,112,108,101,114,115,84,101,120,116,117,114,101,83,109,112,108,114,0,6,95,0,0,0,0,0,0,48,130,208,8,35,8,18,51,130,208,12,35,8,13,49,130,208,20,35,8,141,49,130,208,28,
|
||||
35,8,13,50,130,208,36,35,8,141,50,130,208,44,35,8,9,48,195,64,6,65,25,204,48,152,129,112,6,51,12,104,48,144,193,12,3,26,16,105,48,195,128,6,69,26,204,48,160,129,145,6,51,12,104,112,
|
||||
168,193,12,3,26,32,107,48,195,128,6,9,27,204,16,40,51,12,100,128,6,109,48,3,177,184,1,25,180,193,12,1,51,67,208,204,16,56,51,28,79,27,180,1,20,73,211,12,193,31,204,144,180,1,85,89,
|
||||
23,20,73,216,12,137,25,80,153,117,65,154,180,205,160,144,1,215,181,129,25,120,208,39,129,193,12,137,27,132,65,215,6,102,0,137,129,52,6,51,16,161,32,10,163,64,10,51,12,111,0,10,165,
|
||||
112,99,0,112,28,199,113,28,199,113,28,199,185,129,27,184,129,27,184,129,27,184,129,27,184,129,69,7,122,96,89,150,41,112,172,192,10,228,160,14,160,32,35,129,9,202,136,141,205,174,205,
|
||||
165,237,141,172,142,173,204,197,140,45,236,108,110,148,228,13,224,32,14,228,96,14,232,160,14,236,224,14,82,97,99,179,107,115,73,35,43,115,163,27,37,192,131,92,194,210,228,92,236,202,
|
||||
228,230,210,222,220,70,9,242,32,169,176,52,57,23,182,48,183,179,186,176,179,178,47,187,50,185,185,180,55,183,81,2,61,200,41,44,77,206,101,236,173,13,46,141,173,236,235,13,142,46,237,
|
||||
205,109,110,148,97,15,248,160,15,146,9,75,147,115,49,147,11,59,107,43,115,163,27,37,40,5,0,0,0,0,169,24,0,0,37,0,0,0,11,10,114,40,135,119,128,7,122,88,112,152,67,61,184,195,56,176,
|
||||
67,57,208,195,130,230,28,198,161,13,232,65,30,194,193,29,230,33,29,232,33,29,222,193,29,22,52,227,96,14,231,80,15,225,32,15,228,64,15,225,32,15,231,80,14,244,176,128,129,7,121,40,135,
|
||||
112,96,7,118,120,135,113,8,7,122,40,7,114,88,112,156,195,56,180,1,59,164,131,61,148,195,2,107,28,216,33,28,220,225,28,220,32,28,228,97,28,220,32,28,232,129,30,194,97,28,208,161,28,
|
||||
200,97,28,194,129,29,216,97,193,1,15,244,32,15,225,80,15,244,128,14,0,0,0,0,209,16,0,0,6,0,0,0,7,204,60,164,131,59,156,3,59,148,3,61,160,131,60,148,67,56,144,195,1,0,0,0,97,32,0,0,
|
||||
49,0,0,0,19,4,65,44,16,0,0,0,4,0,0,0,196,106,96,4,128,220,8,0,129,17,0,18,51,0,0,0,241,48,0,0,28,0,0,0,34,71,200,144,81,14,196,42,0,0,0,0,23,134,1,0,97,105,114,45,97,108,105,97,115,
|
||||
45,115,99,111,112,101,115,40,109,97,105,110,48,41,97,105,114,45,97,108,105,97,115,45,115,99,111,112,101,45,115,97,109,112,108,101,114,115,97,105,114,45,97,108,105,97,115,45,115,99,
|
||||
111,112,101,45,116,101,120,116,117,114,101,115,0,43,4,85,56,133,21,195,42,168,2,42,172,24,88,65,21,82,97,131,192,10,171,0,0,35,6,205,16,130,96,240,84,135,129,20,3,33,8,204,104,66,0,
|
||||
96,176,136,255,108,3,17,0,27,4,196,0,0,0,2,0,0,0,91,6,224,96,5,0,0,0,0,0,0,0,113,32,0,0,3,0,0,0,50,14,16,34,132,0,248,5,0,0,0,0,0,0,0,0,101,12,0,0,37,0,0,0,18,3,148,40,1,0,0,0,3,0,
|
||||
0,0,32,0,0,0,9,0,0,0,76,0,0,0,1,0,0,0,88,0,0,0,0,0,0,0,88,0,0,0,2,0,0,0,136,0,0,0,0,0,0,0,41,0,0,0,21,0,0,0,0,0,0,0,5,0,0,0,5,0,0,0,0,0,0,0,136,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,
|
||||
0,0,0,0,0,5,0,0,0,0,0,0,0,5,0,0,0,255,255,255,255,0,36,0,0,5,0,0,0,27,0,0,0,5,0,0,0,27,0,0,0,255,255,255,255,8,36,0,0,0,0,0,0,93,12,0,0,19,0,0,0,18,3,148,126,0,0,0,0,109,97,105,110,
|
||||
48,97,105,114,46,115,97,109,112,108,101,95,116,101,120,116,117,114,101,95,50,100,46,118,52,102,51,50,51,50,48,50,51,46,51,54,56,97,105,114,54,52,45,97,112,112,108,101,45,105,111,115,
|
||||
49,56,46,49,46,48,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
};
|
||||
#elif TARGET_IPHONE_SIMULATOR
|
||||
#error "SDL_GPU does not support the iphone simulator"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
311
backends/imgui_impl_sdlrenderer2.cpp
Normal file
311
backends/imgui_impl_sdlrenderer2.cpp
Normal file
@@ -0,0 +1,311 @@
|
||||
// dear imgui: Renderer Backend for SDL_Renderer for SDL2
|
||||
// (Requires: SDL 2.0.17+)
|
||||
|
||||
// Note that SDL_Renderer is an _optional_ component of SDL2, which IMHO is now largely obsolete.
|
||||
// For a multi-platform app consider using other technologies:
|
||||
// - SDL3+SDL_GPU: SDL_GPU is SDL3 new graphics abstraction API. You will need to update to SDL3.
|
||||
// - SDL2+DirectX, SDL2+OpenGL, SDL2+Vulkan: combine SDL with dedicated renderers.
|
||||
// If your application wants to render any non trivial amount of graphics other than UI,
|
||||
// please be aware that SDL_Renderer currently offers a limited graphic API to the end-user
|
||||
// and it might be difficult to step out of those boundaries.
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'SDL_Texture*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
|
||||
// Missing features or Issues:
|
||||
// [ ] Renderer: Missing support for DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest callbacks: SDLRenderer2 does not support changing SDL_SCALE_MODE while rendering.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState (others cannot be supported). (#9378)
|
||||
// 2026-03-12: Fixed invalid assert in ImGui_ImplSDLRenderer2_UpdateTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295)
|
||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||
// 2025-06-11: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplSDLRenderer2_CreateFontsTexture() and ImGui_ImplSDLRenderer2_DestroyFontsTexture().
|
||||
// 2025-01-18: Use endian-dependent RGBA32 texture format, to match SDL_Color.
|
||||
// 2024-10-09: Expose selected render state in ImGui_ImplSDLRenderer2_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.
|
||||
// 2024-05-14: *BREAKING CHANGE* ImGui_ImplSDLRenderer3_RenderDrawData() requires SDL_Renderer* passed as parameter.
|
||||
// 2023-05-30: Renamed imgui_impl_sdlrenderer.h/.cpp to imgui_impl_sdlrenderer2.h/.cpp to accommodate for upcoming SDL3.
|
||||
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
|
||||
// 2021-12-21: Update SDL_RenderGeometryRaw() format to work with SDL 2.0.19.
|
||||
// 2021-12-03: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
|
||||
// 2021-10-06: Backup and restore modified ClipRect/Viewport.
|
||||
// 2021-09-21: Initial version.
|
||||
|
||||
#include "imgui.h"
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include "imgui_impl_sdlrenderer2.h"
|
||||
#include <stdint.h> // intptr_t
|
||||
|
||||
// Clang warnings with -Weverything
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
|
||||
#elif defined(__GNUC__)
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal" // warning: comparing floating-point with '==' or '!=' is unsafe
|
||||
#endif
|
||||
|
||||
// SDL
|
||||
#include <SDL.h>
|
||||
#if !SDL_VERSION_ATLEAST(2,0,17)
|
||||
#error This backend requires SDL 2.0.17+ because of SDL_RenderGeometry() function
|
||||
#endif
|
||||
|
||||
// SDL_Renderer data
|
||||
struct ImGui_ImplSDLRenderer2_Data
|
||||
{
|
||||
SDL_Renderer* Renderer; // Main viewport's renderer
|
||||
|
||||
ImGui_ImplSDLRenderer2_Data() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
|
||||
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
|
||||
static ImGui_ImplSDLRenderer2_Data* ImGui_ImplSDLRenderer2_GetBackendData()
|
||||
{
|
||||
return ImGui::GetCurrentContext() ? (ImGui_ImplSDLRenderer2_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
|
||||
}
|
||||
|
||||
// Functions
|
||||
static void ImGui_ImplSDLRenderer2_SetupRenderState(SDL_Renderer* renderer)
|
||||
{
|
||||
// Clear out any viewports and cliprect set by the user
|
||||
// FIXME: Technically speaking there are lots of other things we could backup/setup/restore during our render process.
|
||||
SDL_RenderSetViewport(renderer, nullptr);
|
||||
SDL_RenderSetClipRect(renderer, nullptr);
|
||||
}
|
||||
|
||||
void ImGui_ImplSDLRenderer2_NewFrame()
|
||||
{
|
||||
ImGui_ImplSDLRenderer2_Data* bd = ImGui_ImplSDLRenderer2_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplSDLRenderer2_Init()?");
|
||||
IM_UNUSED(bd);
|
||||
}
|
||||
|
||||
// Draw callbacks
|
||||
static void ImGui_ImplSDLRenderer2_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
||||
|
||||
void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data, SDL_Renderer* renderer)
|
||||
{
|
||||
// If there's a scale factor set by the user, use that instead
|
||||
// If the user has specified a scale factor to SDL_Renderer already via SDL_RenderSetScale(), SDL will scale whatever we pass
|
||||
// to SDL_RenderGeometryRaw() by that scale factor. In that case we don't want to be also scaling it ourselves here.
|
||||
float rsx = 1.0f;
|
||||
float rsy = 1.0f;
|
||||
SDL_RenderGetScale(renderer, &rsx, &rsy);
|
||||
ImVec2 render_scale;
|
||||
render_scale.x = (rsx == 1.0f) ? draw_data->FramebufferScale.x : 1.0f;
|
||||
render_scale.y = (rsy == 1.0f) ? draw_data->FramebufferScale.y : 1.0f;
|
||||
|
||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||
int fb_width = (int)(draw_data->DisplaySize.x * render_scale.x);
|
||||
int fb_height = (int)(draw_data->DisplaySize.y * render_scale.y);
|
||||
if (fb_width == 0 || fb_height == 0)
|
||||
return;
|
||||
|
||||
// Catch up with texture updates. Most of the times, the list will have 1 element with an OK status, aka nothing to do.
|
||||
// (This almost always points to ImGui::GetPlatformIO().Textures[] but is part of ImDrawData to allow overriding or disabling texture updates).
|
||||
if (draw_data->Textures != nullptr)
|
||||
for (ImTextureData* tex : *draw_data->Textures)
|
||||
if (tex->Status != ImTextureStatus_OK)
|
||||
ImGui_ImplSDLRenderer2_UpdateTexture(tex);
|
||||
|
||||
// Backup SDL_Renderer state that will be modified to restore it afterwards
|
||||
struct BackupSDLRendererState
|
||||
{
|
||||
SDL_Rect Viewport;
|
||||
bool ClipEnabled;
|
||||
SDL_Rect ClipRect;
|
||||
};
|
||||
BackupSDLRendererState old = {};
|
||||
old.ClipEnabled = SDL_RenderIsClipEnabled(renderer) == SDL_TRUE;
|
||||
SDL_RenderGetViewport(renderer, &old.Viewport);
|
||||
SDL_RenderGetClipRect(renderer, &old.ClipRect);
|
||||
|
||||
// Setup desired state
|
||||
ImGui_ImplSDLRenderer2_SetupRenderState(renderer);
|
||||
|
||||
// Setup render state structure (for callbacks and custom texture bindings)
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
ImGui_ImplSDLRenderer2_RenderState render_state;
|
||||
render_state.Renderer = renderer;
|
||||
platform_io.Renderer_RenderState = &render_state;
|
||||
|
||||
// Will project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
|
||||
ImVec2 clip_scale = render_scale;
|
||||
|
||||
// Render command lists
|
||||
for (const ImDrawList* draw_list : draw_data->CmdLists)
|
||||
{
|
||||
const ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data;
|
||||
const ImDrawIdx* idx_buffer = draw_list->IdxBuffer.Data;
|
||||
|
||||
for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback)
|
||||
{
|
||||
// User callback, registered via ImDrawList::AddCallback()
|
||||
if (pcmd->UserCallback == ImGui_ImplSDLRenderer2_DrawCallback_ResetRenderState)
|
||||
ImGui_ImplSDLRenderer2_SetupRenderState(renderer);
|
||||
else
|
||||
pcmd->UserCallback(draw_list, pcmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
|
||||
ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
|
||||
if (clip_min.x < 0.0f) { clip_min.x = 0.0f; }
|
||||
if (clip_min.y < 0.0f) { clip_min.y = 0.0f; }
|
||||
if (clip_max.x > (float)fb_width) { clip_max.x = (float)fb_width; }
|
||||
if (clip_max.y > (float)fb_height) { clip_max.y = (float)fb_height; }
|
||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||
continue;
|
||||
|
||||
SDL_Rect r = { (int)(clip_min.x), (int)(clip_min.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y) };
|
||||
SDL_RenderSetClipRect(renderer, &r);
|
||||
|
||||
const float* xy = (const float*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, pos));
|
||||
const float* uv = (const float*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, uv));
|
||||
#if SDL_VERSION_ATLEAST(2,0,19)
|
||||
const SDL_Color* color = (const SDL_Color*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, col)); // SDL 2.0.19+
|
||||
#else
|
||||
const int* color = (const int*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, col)); // SDL 2.0.17 and 2.0.18
|
||||
#endif
|
||||
|
||||
// Bind texture, Draw
|
||||
SDL_Texture* tex = (SDL_Texture*)pcmd->GetTexID();
|
||||
SDL_RenderGeometryRaw(renderer, tex,
|
||||
xy, (int)sizeof(ImDrawVert),
|
||||
color, (int)sizeof(ImDrawVert),
|
||||
uv, (int)sizeof(ImDrawVert),
|
||||
draw_list->VtxBuffer.Size - pcmd->VtxOffset,
|
||||
idx_buffer + pcmd->IdxOffset, pcmd->ElemCount, sizeof(ImDrawIdx));
|
||||
}
|
||||
}
|
||||
}
|
||||
platform_io.Renderer_RenderState = nullptr;
|
||||
|
||||
// Restore modified SDL_Renderer state
|
||||
SDL_RenderSetViewport(renderer, &old.Viewport);
|
||||
SDL_RenderSetClipRect(renderer, old.ClipEnabled ? &old.ClipRect : nullptr);
|
||||
}
|
||||
|
||||
void ImGui_ImplSDLRenderer2_UpdateTexture(ImTextureData* tex)
|
||||
{
|
||||
ImGui_ImplSDLRenderer2_Data* bd = ImGui_ImplSDLRenderer2_GetBackendData();
|
||||
|
||||
if (tex->Status == ImTextureStatus_WantCreate)
|
||||
{
|
||||
// Create and upload new texture to graphics system
|
||||
//IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
|
||||
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == nullptr);
|
||||
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
|
||||
|
||||
// Create texture
|
||||
// (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
|
||||
SDL_Texture* sdl_texture = SDL_CreateTexture(bd->Renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STATIC, tex->Width, tex->Height);
|
||||
IM_ASSERT(sdl_texture != nullptr && "Backend failed to create texture!");
|
||||
SDL_UpdateTexture(sdl_texture, nullptr, tex->GetPixels(), tex->GetPitch());
|
||||
SDL_SetTextureBlendMode(sdl_texture, SDL_BLENDMODE_BLEND);
|
||||
SDL_SetTextureScaleMode(sdl_texture, SDL_ScaleModeLinear);
|
||||
|
||||
// Store identifiers
|
||||
tex->SetTexID((ImTextureID)(intptr_t)sdl_texture);
|
||||
tex->SetStatus(ImTextureStatus_OK);
|
||||
}
|
||||
else if (tex->Status == ImTextureStatus_WantUpdates)
|
||||
{
|
||||
// Update selected blocks. We only ever write to textures regions which have never been used before!
|
||||
// This backend choose to use tex->Updates[] but you can use tex->UpdateRect to upload a single region.
|
||||
SDL_Texture* sdl_texture = (SDL_Texture*)(intptr_t)tex->TexID;
|
||||
for (ImTextureRect& r : tex->Updates)
|
||||
{
|
||||
SDL_Rect sdl_r = { r.x, r.y, r.w, r.h };
|
||||
SDL_UpdateTexture(sdl_texture, &sdl_r, tex->GetPixelsAt(r.x, r.y), tex->GetPitch());
|
||||
}
|
||||
tex->SetStatus(ImTextureStatus_OK);
|
||||
}
|
||||
else if (tex->Status == ImTextureStatus_WantDestroy)
|
||||
{
|
||||
if (tex->TexID != ImTextureID_Invalid)
|
||||
if (SDL_Texture* sdl_texture = (SDL_Texture*)(intptr_t)tex->TexID)
|
||||
SDL_DestroyTexture(sdl_texture);
|
||||
|
||||
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
|
||||
tex->SetTexID(ImTextureID_Invalid);
|
||||
tex->SetStatus(ImTextureStatus_Destroyed);
|
||||
}
|
||||
}
|
||||
|
||||
void ImGui_ImplSDLRenderer2_CreateDeviceObjects()
|
||||
{
|
||||
}
|
||||
|
||||
void ImGui_ImplSDLRenderer2_DestroyDeviceObjects()
|
||||
{
|
||||
// Destroy all textures
|
||||
for (ImTextureData* tex : ImGui::GetPlatformIO().Textures)
|
||||
if (tex->RefCount == 1)
|
||||
{
|
||||
tex->SetStatus(ImTextureStatus_WantDestroy);
|
||||
ImGui_ImplSDLRenderer2_UpdateTexture(tex);
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGui_ImplSDLRenderer2_Init(SDL_Renderer* renderer)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IMGUI_CHECKVERSION();
|
||||
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
||||
IM_ASSERT(renderer != nullptr && "SDL_Renderer not initialized!");
|
||||
|
||||
// Setup backend capabilities flags
|
||||
ImGui_ImplSDLRenderer2_Data* bd = IM_NEW(ImGui_ImplSDLRenderer2_Data)();
|
||||
io.BackendRendererUserData = (void*)bd;
|
||||
io.BackendRendererName = "imgui_impl_sdlrenderer2";
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
||||
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
platform_io.DrawCallback_ResetRenderState = ImGui_ImplSDLRenderer2_DrawCallback_ResetRenderState;
|
||||
|
||||
bd->Renderer = renderer;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplSDLRenderer2_Shutdown()
|
||||
{
|
||||
ImGui_ImplSDLRenderer2_Data* bd = ImGui_ImplSDLRenderer2_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
ImGui_ImplSDLRenderer2_DestroyDeviceObjects();
|
||||
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
|
||||
platform_io.ClearRendererHandlers();
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
55
backends/imgui_impl_sdlrenderer2.h
Normal file
55
backends/imgui_impl_sdlrenderer2.h
Normal file
@@ -0,0 +1,55 @@
|
||||
// dear imgui: Renderer Backend for SDL_Renderer for SDL2
|
||||
// (Requires: SDL 2.0.17+)
|
||||
|
||||
// Note that SDL_Renderer is an _optional_ component of SDL2, which IMHO is now largely obsolete.
|
||||
// For a multi-platform app consider using other technologies:
|
||||
// - SDL3+SDL_GPU: SDL_GPU is SDL3 new graphics abstraction API. You will need to update to SDL3.
|
||||
// - SDL2+DirectX, SDL2+OpenGL, SDL2+Vulkan: combine SDL with dedicated renderers.
|
||||
// If your application wants to render any non trivial amount of graphics other than UI,
|
||||
// please be aware that SDL_Renderer currently offers a limited graphic API to the end-user
|
||||
// and it might be difficult to step out of those boundaries.
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'SDL_Texture*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
|
||||
// Missing features or Issues:
|
||||
// [ ] Renderer: Missing support for DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest callbacks: SDLRenderer2 does not support changing SDL_SCALE_MODE while rendering.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
#pragma once
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
|
||||
struct SDL_Renderer;
|
||||
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
IMGUI_IMPL_API bool ImGui_ImplSDLRenderer2_Init(SDL_Renderer* renderer);
|
||||
IMGUI_IMPL_API void ImGui_ImplSDLRenderer2_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplSDLRenderer2_NewFrame();
|
||||
IMGUI_IMPL_API void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data, SDL_Renderer* renderer);
|
||||
|
||||
// Called by Init/NewFrame/Shutdown
|
||||
IMGUI_IMPL_API void ImGui_ImplSDLRenderer2_CreateDeviceObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplSDLRenderer2_DestroyDeviceObjects();
|
||||
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||
IMGUI_IMPL_API void ImGui_ImplSDLRenderer2_UpdateTexture(ImTextureData* tex);
|
||||
|
||||
// [BETA] Selected render state data shared with callbacks.
|
||||
// This is temporarily stored in GetPlatformIO().Renderer_RenderState during the ImGui_ImplSDLRenderer2_RenderDrawData() call.
|
||||
// (Please open an issue if you feel you need access to more data)
|
||||
struct ImGui_ImplSDLRenderer2_RenderState
|
||||
{
|
||||
SDL_Renderer* Renderer;
|
||||
};
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
333
backends/imgui_impl_sdlrenderer3.cpp
Normal file
333
backends/imgui_impl_sdlrenderer3.cpp
Normal file
@@ -0,0 +1,333 @@
|
||||
// dear imgui: Renderer Backend for SDL_Renderer for SDL3
|
||||
// (Requires: SDL 3.1.8+)
|
||||
|
||||
// Note that SDL_Renderer is an _optional_ component of SDL3, which IMHO is now largely obsolete.
|
||||
// For a multi-platform app consider using other technologies:
|
||||
// - SDL3+SDL_GPU: SDL_GPU is SDL3 new graphics abstraction API.
|
||||
// - SDL3+DirectX, SDL3+OpenGL, SDL3+Vulkan: combine SDL with dedicated renderers.
|
||||
// If your application wants to render any non trivial amount of graphics other than UI,
|
||||
// please be aware that SDL_Renderer currently offers a limited graphic API to the end-user
|
||||
// and it might be difficult to step out of those boundaries.
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'SDL_Texture*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
|
||||
// 2026-03-12: Fixed invalid assert in ImGui_ImplSDLRenderer3_UpdateTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295)
|
||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||
// 2025-06-11: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplSDLRenderer3_CreateFontsTexture() and ImGui_ImplSDLRenderer3_DestroyFontsTexture().
|
||||
// 2025-01-18: Use endian-dependent RGBA32 texture format, to match SDL_Color.
|
||||
// 2024-10-09: Expose selected render state in ImGui_ImplSDLRenderer3_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.
|
||||
// 2024-07-01: Update for SDL3 api changes: SDL_RenderGeometryRaw() uint32 version was removed (SDL#9009).
|
||||
// 2024-05-14: *BREAKING CHANGE* ImGui_ImplSDLRenderer3_RenderDrawData() requires SDL_Renderer* passed as parameter.
|
||||
// 2024-02-12: Amend to query SDL_RenderViewportSet() and restore viewport accordingly.
|
||||
// 2023-05-30: Initial version.
|
||||
|
||||
#include "imgui.h"
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include "imgui_impl_sdlrenderer3.h"
|
||||
#include <stdint.h> // intptr_t
|
||||
|
||||
// Clang warnings with -Weverything
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
|
||||
#elif defined(__GNUC__)
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal" // warning: comparing floating-point with '==' or '!=' is unsafe
|
||||
#endif
|
||||
|
||||
// SDL
|
||||
#include <SDL3/SDL.h>
|
||||
#if !SDL_VERSION_ATLEAST(3,0,0)
|
||||
#error This backend requires SDL 3.0.0+
|
||||
#endif
|
||||
|
||||
// SDL_Renderer data
|
||||
struct ImGui_ImplSDLRenderer3_Data
|
||||
{
|
||||
SDL_Renderer* Renderer; // Main viewport's renderer
|
||||
ImVector<SDL_FColor> ColorBuffer;
|
||||
|
||||
// Render State
|
||||
SDL_ScaleMode CurrentScaleMode;
|
||||
|
||||
ImGui_ImplSDLRenderer3_Data() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
|
||||
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
|
||||
static ImGui_ImplSDLRenderer3_Data* ImGui_ImplSDLRenderer3_GetBackendData()
|
||||
{
|
||||
return ImGui::GetCurrentContext() ? (ImGui_ImplSDLRenderer3_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
|
||||
}
|
||||
|
||||
// Functions
|
||||
static void ImGui_ImplSDLRenderer3_SetupRenderState(SDL_Renderer* renderer)
|
||||
{
|
||||
// Clear out any viewports and cliprect set by the user
|
||||
// FIXME: Technically speaking there are lots of other things we could backup/setup/restore during our render process.
|
||||
SDL_SetRenderViewport(renderer, nullptr);
|
||||
SDL_SetRenderClipRect(renderer, nullptr);
|
||||
}
|
||||
|
||||
void ImGui_ImplSDLRenderer3_NewFrame()
|
||||
{
|
||||
ImGui_ImplSDLRenderer3_Data* bd = ImGui_ImplSDLRenderer3_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplSDLRenderer3_Init()?");
|
||||
IM_UNUSED(bd);
|
||||
}
|
||||
|
||||
// https://github.com/libsdl-org/SDL/issues/9009
|
||||
static int SDL_RenderGeometryRaw8BitColor(SDL_Renderer* renderer, ImVector<SDL_FColor>& colors_out, SDL_Texture* texture, const float* xy, int xy_stride, const SDL_Color* color, int color_stride, const float* uv, int uv_stride, int num_vertices, const void* indices, int num_indices, int size_indices)
|
||||
{
|
||||
const Uint8* color2 = (const Uint8*)color;
|
||||
colors_out.resize(num_vertices);
|
||||
SDL_FColor* color3 = colors_out.Data;
|
||||
for (int i = 0; i < num_vertices; i++)
|
||||
{
|
||||
color3[i].r = color->r / 255.0f;
|
||||
color3[i].g = color->g / 255.0f;
|
||||
color3[i].b = color->b / 255.0f;
|
||||
color3[i].a = color->a / 255.0f;
|
||||
color2 += color_stride;
|
||||
color = (const SDL_Color*)color2;
|
||||
}
|
||||
return SDL_RenderGeometryRaw(renderer, texture, xy, xy_stride, color3, sizeof(*color3), uv, uv_stride, num_vertices, indices, num_indices, size_indices);
|
||||
}
|
||||
|
||||
// Draw callbacks
|
||||
static void ImGui_ImplSDLRenderer3_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
||||
static void ImGui_ImplSDLRenderer3_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplSDLRenderer3_Data* bd = ImGui_ImplSDLRenderer3_GetBackendData(); bd->CurrentScaleMode = SDL_SCALEMODE_LINEAR; }
|
||||
static void ImGui_ImplSDLRenderer3_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplSDLRenderer3_Data* bd = ImGui_ImplSDLRenderer3_GetBackendData(); bd->CurrentScaleMode = SDL_SCALEMODE_NEAREST; }
|
||||
|
||||
void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer* renderer)
|
||||
{
|
||||
ImGui_ImplSDLRenderer3_Data* bd = ImGui_ImplSDLRenderer3_GetBackendData();
|
||||
|
||||
// If there's a scale factor set by the user, use that instead
|
||||
// If the user has specified a scale factor to SDL_Renderer already via SDL_RenderSetScale(), SDL will scale whatever we pass
|
||||
// to SDL_RenderGeometryRaw() by that scale factor. In that case we don't want to be also scaling it ourselves here.
|
||||
float rsx = 1.0f;
|
||||
float rsy = 1.0f;
|
||||
SDL_GetRenderScale(renderer, &rsx, &rsy);
|
||||
ImVec2 render_scale;
|
||||
render_scale.x = (rsx == 1.0f) ? draw_data->FramebufferScale.x : 1.0f;
|
||||
render_scale.y = (rsy == 1.0f) ? draw_data->FramebufferScale.y : 1.0f;
|
||||
|
||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||
int fb_width = (int)(draw_data->DisplaySize.x * render_scale.x);
|
||||
int fb_height = (int)(draw_data->DisplaySize.y * render_scale.y);
|
||||
if (fb_width == 0 || fb_height == 0)
|
||||
return;
|
||||
|
||||
// Catch up with texture updates. Most of the times, the list will have 1 element with an OK status, aka nothing to do.
|
||||
// (This almost always points to ImGui::GetPlatformIO().Textures[] but is part of ImDrawData to allow overriding or disabling texture updates).
|
||||
if (draw_data->Textures != nullptr)
|
||||
for (ImTextureData* tex : *draw_data->Textures)
|
||||
if (tex->Status != ImTextureStatus_OK)
|
||||
ImGui_ImplSDLRenderer3_UpdateTexture(tex);
|
||||
|
||||
// Backup SDL_Renderer state that will be modified to restore it afterwards
|
||||
struct BackupSDLRendererState
|
||||
{
|
||||
SDL_Rect Viewport;
|
||||
bool ViewportEnabled;
|
||||
bool ClipEnabled;
|
||||
SDL_Rect ClipRect;
|
||||
};
|
||||
BackupSDLRendererState old = {};
|
||||
old.ViewportEnabled = SDL_RenderViewportSet(renderer);
|
||||
old.ClipEnabled = SDL_RenderClipEnabled(renderer);
|
||||
SDL_GetRenderViewport(renderer, &old.Viewport);
|
||||
SDL_GetRenderClipRect(renderer, &old.ClipRect);
|
||||
|
||||
// Setup desired state
|
||||
ImGui_ImplSDLRenderer3_SetupRenderState(renderer);
|
||||
|
||||
// Setup render state structure (for callbacks and custom texture bindings)
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
ImGui_ImplSDLRenderer3_RenderState render_state;
|
||||
render_state.Renderer = renderer;
|
||||
platform_io.Renderer_RenderState = &render_state;
|
||||
|
||||
// Will project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
|
||||
ImVec2 clip_scale = render_scale;
|
||||
|
||||
// Render command lists
|
||||
for (const ImDrawList* draw_list : draw_data->CmdLists)
|
||||
{
|
||||
const ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data;
|
||||
const ImDrawIdx* idx_buffer = draw_list->IdxBuffer.Data;
|
||||
|
||||
for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback)
|
||||
{
|
||||
// User callback, registered via ImDrawList::AddCallback()
|
||||
if (pcmd->UserCallback == ImGui_ImplSDLRenderer3_DrawCallback_ResetRenderState)
|
||||
ImGui_ImplSDLRenderer3_SetupRenderState(renderer);
|
||||
else
|
||||
pcmd->UserCallback(draw_list, pcmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
|
||||
ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
|
||||
if (clip_min.x < 0.0f) { clip_min.x = 0.0f; }
|
||||
if (clip_min.y < 0.0f) { clip_min.y = 0.0f; }
|
||||
if (clip_max.x > (float)fb_width) { clip_max.x = (float)fb_width; }
|
||||
if (clip_max.y > (float)fb_height) { clip_max.y = (float)fb_height; }
|
||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||
continue;
|
||||
|
||||
SDL_Rect r = { (int)(clip_min.x), (int)(clip_min.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y) };
|
||||
SDL_SetRenderClipRect(renderer, &r);
|
||||
|
||||
const float* xy = (const float*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, pos));
|
||||
const float* uv = (const float*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, uv));
|
||||
const SDL_Color* color = (const SDL_Color*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, col)); // SDL 2.0.19+
|
||||
|
||||
// Bind texture, Draw
|
||||
SDL_Texture* tex = (SDL_Texture*)pcmd->GetTexID();
|
||||
SDL_SetTextureScaleMode(tex, bd->CurrentScaleMode);
|
||||
SDL_RenderGeometryRaw8BitColor(renderer, bd->ColorBuffer, tex,
|
||||
xy, (int)sizeof(ImDrawVert),
|
||||
color, (int)sizeof(ImDrawVert),
|
||||
uv, (int)sizeof(ImDrawVert),
|
||||
draw_list->VtxBuffer.Size - pcmd->VtxOffset,
|
||||
idx_buffer + pcmd->IdxOffset, pcmd->ElemCount, sizeof(ImDrawIdx));
|
||||
}
|
||||
}
|
||||
}
|
||||
platform_io.Renderer_RenderState = nullptr;
|
||||
|
||||
// Restore modified SDL_Renderer state
|
||||
SDL_SetRenderViewport(renderer, old.ViewportEnabled ? &old.Viewport : nullptr);
|
||||
SDL_SetRenderClipRect(renderer, old.ClipEnabled ? &old.ClipRect : nullptr);
|
||||
}
|
||||
|
||||
void ImGui_ImplSDLRenderer3_UpdateTexture(ImTextureData* tex)
|
||||
{
|
||||
ImGui_ImplSDLRenderer3_Data* bd = ImGui_ImplSDLRenderer3_GetBackendData();
|
||||
|
||||
if (tex->Status == ImTextureStatus_WantCreate)
|
||||
{
|
||||
// Create and upload new texture to graphics system
|
||||
//IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
|
||||
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == nullptr);
|
||||
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
|
||||
|
||||
// Create texture
|
||||
// (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
|
||||
SDL_Texture* sdl_texture = SDL_CreateTexture(bd->Renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STATIC, tex->Width, tex->Height);
|
||||
IM_ASSERT(sdl_texture != nullptr && "Backend failed to create texture!");
|
||||
SDL_UpdateTexture(sdl_texture, nullptr, tex->GetPixels(), tex->GetPitch());
|
||||
SDL_SetTextureBlendMode(sdl_texture, SDL_BLENDMODE_BLEND);
|
||||
SDL_SetTextureScaleMode(sdl_texture, SDL_SCALEMODE_LINEAR);
|
||||
|
||||
// Store identifiers
|
||||
tex->SetTexID((ImTextureID)(intptr_t)sdl_texture);
|
||||
tex->SetStatus(ImTextureStatus_OK);
|
||||
}
|
||||
else if (tex->Status == ImTextureStatus_WantUpdates)
|
||||
{
|
||||
// Update selected blocks. We only ever write to textures regions which have never been used before!
|
||||
// This backend choose to use tex->Updates[] but you can use tex->UpdateRect to upload a single region.
|
||||
SDL_Texture* sdl_texture = (SDL_Texture*)(intptr_t)tex->TexID;
|
||||
for (ImTextureRect& r : tex->Updates)
|
||||
{
|
||||
SDL_Rect sdl_r = { r.x, r.y, r.w, r.h };
|
||||
SDL_UpdateTexture(sdl_texture, &sdl_r, tex->GetPixelsAt(r.x, r.y), tex->GetPitch());
|
||||
}
|
||||
tex->SetStatus(ImTextureStatus_OK);
|
||||
}
|
||||
else if (tex->Status == ImTextureStatus_WantDestroy)
|
||||
{
|
||||
if (tex->TexID != ImTextureID_Invalid)
|
||||
if (SDL_Texture* sdl_texture = (SDL_Texture*)(intptr_t)tex->TexID)
|
||||
SDL_DestroyTexture(sdl_texture);
|
||||
|
||||
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
|
||||
tex->SetTexID(ImTextureID_Invalid);
|
||||
tex->SetStatus(ImTextureStatus_Destroyed);
|
||||
}
|
||||
}
|
||||
|
||||
void ImGui_ImplSDLRenderer3_CreateDeviceObjects()
|
||||
{
|
||||
}
|
||||
|
||||
void ImGui_ImplSDLRenderer3_DestroyDeviceObjects()
|
||||
{
|
||||
// Destroy all textures
|
||||
for (ImTextureData* tex : ImGui::GetPlatformIO().Textures)
|
||||
if (tex->RefCount == 1)
|
||||
{
|
||||
tex->SetStatus(ImTextureStatus_WantDestroy);
|
||||
ImGui_ImplSDLRenderer3_UpdateTexture(tex);
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGui_ImplSDLRenderer3_Init(SDL_Renderer* renderer)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IMGUI_CHECKVERSION();
|
||||
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
||||
IM_ASSERT(renderer != nullptr && "SDL_Renderer not initialized!");
|
||||
|
||||
// Setup backend capabilities flags
|
||||
ImGui_ImplSDLRenderer3_Data* bd = IM_NEW(ImGui_ImplSDLRenderer3_Data)();
|
||||
io.BackendRendererUserData = (void*)bd;
|
||||
io.BackendRendererName = "imgui_impl_sdlrenderer3";
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
||||
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
platform_io.DrawCallback_ResetRenderState = ImGui_ImplSDLRenderer3_DrawCallback_ResetRenderState;
|
||||
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplSDLRenderer3_DrawCallback_SetSamplerLinear;
|
||||
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplSDLRenderer3_DrawCallback_SetSamplerNearest;
|
||||
|
||||
bd->Renderer = renderer;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplSDLRenderer3_Shutdown()
|
||||
{
|
||||
ImGui_ImplSDLRenderer3_Data* bd = ImGui_ImplSDLRenderer3_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
ImGui_ImplSDLRenderer3_DestroyDeviceObjects();
|
||||
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
|
||||
platform_io.ClearRendererHandlers();
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
53
backends/imgui_impl_sdlrenderer3.h
Normal file
53
backends/imgui_impl_sdlrenderer3.h
Normal file
@@ -0,0 +1,53 @@
|
||||
// dear imgui: Renderer Backend for SDL_Renderer for SDL3
|
||||
// (Requires: SDL 3.1.8+)
|
||||
|
||||
// Note that SDL_Renderer is an _optional_ component of SDL3, which IMHO is now largely obsolete.
|
||||
// For a multi-platform app consider using other technologies:
|
||||
// - SDL3+SDL_GPU: SDL_GPU is SDL3 new graphics abstraction API.
|
||||
// - SDL3+DirectX, SDL3+OpenGL, SDL3+Vulkan: combine SDL with dedicated renderers.
|
||||
// If your application wants to render any non trivial amount of graphics other than UI,
|
||||
// please be aware that SDL_Renderer currently offers a limited graphic API to the end-user
|
||||
// and it might be difficult to step out of those boundaries.
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'SDL_Texture*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
#pragma once
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
struct SDL_Renderer;
|
||||
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
IMGUI_IMPL_API bool ImGui_ImplSDLRenderer3_Init(SDL_Renderer* renderer);
|
||||
IMGUI_IMPL_API void ImGui_ImplSDLRenderer3_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplSDLRenderer3_NewFrame();
|
||||
IMGUI_IMPL_API void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer* renderer);
|
||||
|
||||
// Called by Init/NewFrame/Shutdown
|
||||
IMGUI_IMPL_API void ImGui_ImplSDLRenderer3_CreateDeviceObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplSDLRenderer3_DestroyDeviceObjects();
|
||||
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||
IMGUI_IMPL_API void ImGui_ImplSDLRenderer3_UpdateTexture(ImTextureData* tex);
|
||||
|
||||
// [BETA] Selected render state data shared with callbacks.
|
||||
// This is temporarily stored in GetPlatformIO().Renderer_RenderState during the ImGui_ImplSDLRenderer3_RenderDrawData() call.
|
||||
// (Please open an issue if you feel you need access to more data)
|
||||
struct ImGui_ImplSDLRenderer3_RenderState
|
||||
{
|
||||
SDL_Renderer* Renderer;
|
||||
};
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,17 +2,22 @@
|
||||
// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
|
||||
// Missing features:
|
||||
// [ ] Renderer: User texture binding. Changes of ImTextureID aren't supported by this backend! See https://github.com/ocornut/imgui/pull/914
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
// [!] Renderer: User texture binding. Use a VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE 'VkDescriptorSet' as texture identifier. Call ImGui_ImplVulkan_AddTexture() to register one. Read the FAQ about ImTextureID/ImTextureRef + https://github.com/ocornut/imgui/pull/914 for discussions.
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
|
||||
|
||||
// The aim of imgui_impl_vulkan.h/.cpp is to be usable in your engine without any modification.
|
||||
// IF YOU FEEL YOU NEED TO MAKE ANY CHANGE TO THIS CODE, please share them and your feedback at https://github.com/ocornut/imgui/
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
// Important note to the reader who wish to integrate imgui_impl_vulkan.cpp/.h in their own engine/app.
|
||||
// - Common ImGui_ImplVulkan_XXX functions and structures are used to interface with imgui_impl_vulkan.cpp/.h.
|
||||
// You will use those if you want to use this rendering backend in your engine/app.
|
||||
@@ -21,6 +26,7 @@
|
||||
// Read comments in imgui_impl_vulkan.h.
|
||||
|
||||
#pragma once
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
|
||||
// [Configuration] in order to use a custom Vulkan function loader:
|
||||
@@ -35,68 +41,171 @@
|
||||
// If you have no idea what this is, leave it alone!
|
||||
//#define IMGUI_IMPL_VULKAN_NO_PROTOTYPES
|
||||
|
||||
// Vulkan includes
|
||||
// [Configuration] Convenience support for Volk
|
||||
// (you can also technically use IMGUI_IMPL_VULKAN_NO_PROTOTYPES + wrap Volk via ImGui_ImplVulkan_LoadFunctions().)
|
||||
// (When using Volk from directory outside your include directories list you can specify full path to the volk.h header,
|
||||
// for example when using Volk from VulkanSDK and using include_directories(${Vulkan_INCLUDE_DIRS})' from 'find_package(Vulkan REQUIRED)')
|
||||
//#define IMGUI_IMPL_VULKAN_USE_VOLK
|
||||
//#define IMGUI_IMPL_VULKAN_VOLK_FILENAME <Volk/volk.h>
|
||||
//#define IMGUI_IMPL_VULKAN_VOLK_FILENAME <volk.h> // Default
|
||||
// Reminder: make those changes in your imconfig.h file, not here!
|
||||
|
||||
// Clang/GCC warnings with -Weverything
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast
|
||||
#endif
|
||||
|
||||
#if defined(IMGUI_IMPL_VULKAN_NO_PROTOTYPES) && !defined(VK_NO_PROTOTYPES)
|
||||
#define VK_NO_PROTOTYPES
|
||||
#endif
|
||||
#if defined(VK_USE_PLATFORM_WIN32_KHR) && !defined(NOMINMAX)
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
// Vulkan includes
|
||||
#ifdef IMGUI_IMPL_VULKAN_USE_VOLK
|
||||
#ifdef IMGUI_IMPL_VULKAN_VOLK_FILENAME
|
||||
#include IMGUI_IMPL_VULKAN_VOLK_FILENAME
|
||||
#else
|
||||
#include <volk.h>
|
||||
#endif
|
||||
#else
|
||||
#include <vulkan/vulkan.h>
|
||||
#endif
|
||||
#if defined(VK_VERSION_1_3) || defined(VK_KHR_dynamic_rendering)
|
||||
#define IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
|
||||
#endif
|
||||
|
||||
// Backend uses a small number of descriptors per font atlas + as many as additional calls done to ImGui_ImplVulkan_AddTexture().
|
||||
#define IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE (8) // Minimum per atlas
|
||||
#define IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE (2) // Minimum for linear + nearest
|
||||
|
||||
// Specify settings to create pipeline and swapchain
|
||||
struct ImGui_ImplVulkan_PipelineInfo
|
||||
{
|
||||
VkRenderPass RenderPass; // Ignored if using dynamic rendering
|
||||
uint32_t Subpass; //
|
||||
VkSampleCountFlagBits MSAASamples = {}; // 0 defaults to VK_SAMPLE_COUNT_1_BIT
|
||||
ImVector<VkDynamicState> ExtraDynamicStates; // Optional, allows to insert more dynamic states into our VkPipeline
|
||||
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
|
||||
VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo; // Optional, valid if .sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR
|
||||
#endif
|
||||
};
|
||||
|
||||
// Initialization data, for ImGui_ImplVulkan_Init()
|
||||
// [Please zero-clear before use!]
|
||||
// - About descriptor pool:
|
||||
// - A VkDescriptorPool should be created with VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
|
||||
// and must contain a pool size large enough to hold a small number of VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptors.
|
||||
// - As an convenience, by setting DescriptorPoolSize > 0 the backend will create one for you.
|
||||
// - About dynamic rendering:
|
||||
// - When using dynamic rendering, set UseDynamicRendering=true + fill PipelineInfoMain.PipelineRenderingCreateInfo structure.
|
||||
struct ImGui_ImplVulkan_InitInfo
|
||||
{
|
||||
uint32_t ApiVersion; // Fill with API version of Instance, e.g. VK_API_VERSION_1_3 or your value of VkApplicationInfo::apiVersion. May be lower than header version (VK_HEADER_VERSION_COMPLETE)
|
||||
VkInstance Instance;
|
||||
VkPhysicalDevice PhysicalDevice;
|
||||
VkDevice Device;
|
||||
uint32_t QueueFamily;
|
||||
VkQueue Queue;
|
||||
VkPipelineCache PipelineCache;
|
||||
VkDescriptorPool DescriptorPool;
|
||||
uint32_t Subpass;
|
||||
uint32_t MinImageCount; // >= 2
|
||||
uint32_t ImageCount; // >= MinImageCount
|
||||
VkSampleCountFlagBits MSAASamples; // >= VK_SAMPLE_COUNT_1_BIT
|
||||
VkDescriptorPool DescriptorPool; // See requirements in note above; ignored if using DescriptorPoolSize > 0
|
||||
uint32_t DescriptorPoolSize; // Optional: set to create internal ImageView descriptor pool automatically instead of using DescriptorPool.
|
||||
uint32_t MinImageCount; // >= 2
|
||||
uint32_t ImageCount; // >= MinImageCount
|
||||
VkPipelineCache PipelineCache; // Optional
|
||||
|
||||
// Pipeline
|
||||
ImGui_ImplVulkan_PipelineInfo PipelineInfoMain; // Infos for Main Viewport (created by app/user)
|
||||
//VkRenderPass RenderPass; // --> Since 2025/09/26: set 'PipelineInfoMain.RenderPass' instead
|
||||
//uint32_t Subpass; // --> Since 2025/09/26: set 'PipelineInfoMain.Subpass' instead
|
||||
//VkSampleCountFlagBits MSAASamples; // --> Since 2025/09/26: set 'PipelineInfoMain.MSAASamples' instead
|
||||
//VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo; // Since 2025/09/26: set 'PipelineInfoMain.PipelineRenderingCreateInfo' instead
|
||||
|
||||
// (Optional) Dynamic Rendering
|
||||
// Need to explicitly enable VK_KHR_dynamic_rendering extension to use this, even for Vulkan 1.3 + setup PipelineInfoMain.PipelineRenderingCreateInfo.
|
||||
bool UseDynamicRendering;
|
||||
|
||||
// (Optional) Allocation, Debugging
|
||||
const VkAllocationCallbacks* Allocator;
|
||||
void (*CheckVkResultFn)(VkResult err);
|
||||
VkDeviceSize MinAllocationSize; // Minimum allocation size. Set to 1024*1024 to satisfy zealous best practices validation layer and waste a little memory.
|
||||
|
||||
// (Optional) Customize default vertex/fragment shaders.
|
||||
// - if .sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO we use specified structs, otherwise we use defaults.
|
||||
// - Shader inputs/outputs need to match ours. Code/data pointed to by the structure needs to survive for whole during of backend usage.
|
||||
VkShaderModuleCreateInfo CustomShaderVertCreateInfo;
|
||||
VkShaderModuleCreateInfo CustomShaderFragCreateInfo;
|
||||
};
|
||||
|
||||
// Called by user code
|
||||
IMGUI_IMPL_API bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass render_pass);
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkan_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkan_NewFrame();
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline = VK_NULL_HANDLE);
|
||||
IMGUI_IMPL_API bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer);
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkan_DestroyFontUploadObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count); // To override MinImageCount after initialization (e.g. if swap chain is recreated)
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
IMGUI_IMPL_API bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info);
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkan_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkan_NewFrame();
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline = VK_NULL_HANDLE);
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count); // To override MinImageCount after initialization (e.g. if swap chain is recreated)
|
||||
|
||||
// (Advanced) Use e.g. if you need to recreate pipeline without reinitializing the backend (see #8110, #8111)
|
||||
// The main window pipeline will be created by ImGui_ImplVulkan_Init() if possible (== RenderPass xor (UseDynamicRendering && PipelineRenderingCreateInfo->sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR))
|
||||
// Else, the pipeline can be created, or re-created, using ImGui_ImplVulkan_CreateMainPipeline() before rendering.
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkan_CreateMainPipeline(const ImGui_ImplVulkan_PipelineInfo* info);
|
||||
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkan_UpdateTexture(ImTextureData* tex);
|
||||
|
||||
// Register a texture (VkDescriptorSet for a VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE == ImTextureID)
|
||||
IMGUI_IMPL_API VkDescriptorSet ImGui_ImplVulkan_AddTexture(VkImageView image_view, VkImageLayout image_layout);
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkan_RemoveTexture(VkDescriptorSet descriptor_set);
|
||||
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
IMGUI_IMPL_API VkDescriptorSet ImGui_ImplVulkan_AddTexture(VkSampler sampler, VkImageView image_view, VkImageLayout image_layout); // Ignore VkSampler
|
||||
#endif
|
||||
|
||||
// Optional: load Vulkan functions with a custom function loader
|
||||
// This is only useful with IMGUI_IMPL_VULKAN_NO_PROTOTYPES / VK_NO_PROTOTYPES
|
||||
IMGUI_IMPL_API bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data = NULL);
|
||||
IMGUI_IMPL_API bool ImGui_ImplVulkan_LoadFunctions(uint32_t api_version, PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data = nullptr);
|
||||
|
||||
// [BETA] Selected render state data shared with callbacks.
|
||||
// This is temporarily stored in GetPlatformIO().Renderer_RenderState during the ImGui_ImplVulkan_RenderDrawData() call.
|
||||
// (Please open an issue if you feel you need access to more data)
|
||||
struct ImGui_ImplVulkan_RenderState
|
||||
{
|
||||
VkCommandBuffer CommandBuffer;
|
||||
VkPipeline Pipeline;
|
||||
VkPipelineLayout PipelineLayout;
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Internal / Miscellaneous Vulkan Helpers
|
||||
// (Used by example's main.cpp. Used by multi-viewport features. PROBABLY NOT used by your own engine/app.)
|
||||
//-------------------------------------------------------------------------
|
||||
// Used by example's main.cpp. Used by multi-viewport features. PROBABLY NOT used by your own engine/app.
|
||||
//
|
||||
// You probably do NOT need to use or care about those functions.
|
||||
// WE DO NOT PROVIDE STRONG GUARANTEES OF BACKWARD/FORWARD COMPATIBILITY.
|
||||
// Those functions only exist because:
|
||||
// 1) they facilitate the readability and maintenance of the multiple main.cpp examples files.
|
||||
// 2) the upcoming multi-viewport feature will need them internally.
|
||||
// 2) the multi-viewport / platform window implementation needs them internally.
|
||||
// Generally we avoid exposing any kind of superfluous high-level helpers in the backends,
|
||||
// but it is too much code to duplicate everywhere so we exceptionally expose them.
|
||||
//
|
||||
// Your engine/app will likely _already_ have code to setup all that stuff (swap chain, render pass, frame buffers, etc.).
|
||||
// You may read this code to learn about Vulkan, but it is recommended you use you own custom tailored code to do equivalent work.
|
||||
// (The ImGui_ImplVulkanH_XXX functions do not interact with any of the state used by the regular ImGui_ImplVulkan_XXX functions)
|
||||
// Your engine/app will likely _already_ have code to setup all that stuff (swap chain,
|
||||
// render pass, frame buffers, etc.). You may read this code if you are curious, but
|
||||
// it is recommended you use your own custom tailored code to do equivalent work.
|
||||
//
|
||||
// The ImGui_ImplVulkanH_XXX functions should NOT interact with any of the state used
|
||||
// by the regular ImGui_ImplVulkan_XXX functions.
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
struct ImGui_ImplVulkanH_Frame;
|
||||
struct ImGui_ImplVulkanH_Window;
|
||||
|
||||
// Helpers
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wnd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count);
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Window* wnd, const VkAllocationCallbacks* allocator);
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count, VkImageUsageFlags image_usage);
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator);
|
||||
IMGUI_IMPL_API VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space);
|
||||
IMGUI_IMPL_API VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count);
|
||||
IMGUI_IMPL_API VkPhysicalDevice ImGui_ImplVulkanH_SelectPhysicalDevice(VkInstance instance);
|
||||
IMGUI_IMPL_API uint32_t ImGui_ImplVulkanH_SelectQueueFamilyIndex(VkPhysicalDevice physical_device);
|
||||
IMGUI_IMPL_API int ImGui_ImplVulkanH_GetMinImageCountFromPresentMode(VkPresentModeKHR present_mode);
|
||||
|
||||
// Helper structure to hold the data needed by one rendering frame
|
||||
@@ -122,27 +231,48 @@ struct ImGui_ImplVulkanH_FrameSemaphores
|
||||
// (Used by example's main.cpp. Used by multi-viewport features. Probably NOT used by your own engine/app.)
|
||||
struct ImGui_ImplVulkanH_Window
|
||||
{
|
||||
int Width;
|
||||
int Height;
|
||||
VkSwapchainKHR Swapchain;
|
||||
VkSurfaceKHR Surface;
|
||||
VkSurfaceFormatKHR SurfaceFormat;
|
||||
VkPresentModeKHR PresentMode;
|
||||
VkRenderPass RenderPass;
|
||||
VkPipeline Pipeline; // The window pipeline may uses a different VkRenderPass than the one passed in ImGui_ImplVulkan_InitInfo
|
||||
bool ClearEnable;
|
||||
VkClearValue ClearValue;
|
||||
uint32_t FrameIndex; // Current frame being rendered to (0 <= FrameIndex < FrameInFlightCount)
|
||||
uint32_t ImageCount; // Number of simultaneous in-flight frames (returned by vkGetSwapchainImagesKHR, usually derived from min_image_count)
|
||||
uint32_t SemaphoreIndex; // Current set of swapchain wait semaphores we're using (needs to be distinct from per frame data)
|
||||
ImGui_ImplVulkanH_Frame* Frames;
|
||||
ImGui_ImplVulkanH_FrameSemaphores* FrameSemaphores;
|
||||
// Input
|
||||
bool UseDynamicRendering;
|
||||
VkSurfaceKHR Surface; // Surface created and destroyed by caller.
|
||||
VkSurfaceFormatKHR SurfaceFormat;
|
||||
VkPresentModeKHR PresentMode;
|
||||
VkAttachmentDescription AttachmentDesc; // RenderPass creation: main attachment description.
|
||||
VkClearValue ClearValue; // RenderPass creation: clear value when using VK_ATTACHMENT_LOAD_OP_CLEAR.
|
||||
|
||||
// Internal
|
||||
int Width; // Generally same as passed to ImGui_ImplVulkanH_CreateOrResizeWindow()
|
||||
int Height;
|
||||
VkSwapchainKHR Swapchain;
|
||||
VkRenderPass RenderPass;
|
||||
VkPipeline Pipeline; // The window pipeline may uses a different VkRenderPass than the one passed in ImGui_ImplVulkan_InitInfo
|
||||
uint32_t FrameIndex; // Current frame being rendered to (0 <= FrameIndex < FrameInFlightCount)
|
||||
uint32_t ImageCount; // Number of simultaneous in-flight frames (returned by vkGetSwapchainImagesKHR, usually derived from min_image_count)
|
||||
uint32_t SemaphoreCount; // Number of simultaneous in-flight frames + 1, to be able to use it in vkAcquireNextImageKHR
|
||||
uint32_t SemaphoreIndex; // Current set of swapchain wait semaphores we're using (needs to be distinct from per frame data)
|
||||
ImVector<ImGui_ImplVulkanH_Frame> Frames;
|
||||
ImVector<ImGui_ImplVulkanH_FrameSemaphores> FrameSemaphores;
|
||||
|
||||
ImGui_ImplVulkanH_Window()
|
||||
{
|
||||
memset(this, 0, sizeof(*this));
|
||||
PresentMode = VK_PRESENT_MODE_MAX_ENUM_KHR;
|
||||
ClearEnable = true;
|
||||
memset((void*)this, 0, sizeof(*this));
|
||||
|
||||
// Parameters to create SwapChain
|
||||
PresentMode = VK_PRESENT_MODE_MAX_ENUM_KHR; // Ensure we get an error if user doesn't set this.
|
||||
|
||||
// Parameters to create RenderPass
|
||||
AttachmentDesc.format = VK_FORMAT_UNDEFINED; // Will automatically use wd->SurfaceFormat.format.
|
||||
AttachmentDesc.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
AttachmentDesc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
AttachmentDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
AttachmentDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
AttachmentDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
AttachmentDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
AttachmentDesc.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,24 +1,119 @@
|
||||
// dear imgui: Renderer for WebGPU
|
||||
// This needs to be used along with a Platform Binding (e.g. GLFW)
|
||||
// (Please note that WebGPU is currently experimental, will not run on non-beta browsers, and may break.)
|
||||
// This needs to be used along with a Platform Binding (e.g. GLFW, SDL2, SDL3)
|
||||
// (Please note that WebGPU is a recent API, may not be supported by all browser, and its ecosystem is generally a mess)
|
||||
|
||||
// When targeting native platforms:
|
||||
// - One of IMGUI_IMPL_WEBGPU_BACKEND_DAWN, IMGUI_IMPL_WEBGPU_BACKEND_WGPU or IMGUI_IMPL_WEBGPU_BACKEND_WGVK *must* be provided.
|
||||
// When targeting Emscripten:
|
||||
// - We now defaults to IMGUI_IMPL_WEBGPU_BACKEND_DAWN and requires Emscripten 4.0.10+, which correspond to using Emscripten '--use-port=emdawnwebgpu'.
|
||||
// - Emscripten < 4.0.10 is not supported anymore (old '-sUSE_WEBGPU=1' option).
|
||||
// - We can still define IMGUI_IMPL_WEBGPU_BACKEND_WGPU to use Emscripten '-s USE_WEBGPU=1' which is marked as obsolete by Emscripten.
|
||||
// Add #define to your imconfig.h file, or as a compilation flag in your build system.
|
||||
// This requirement may be removed once WebGPU stabilizes and backends converge on a unified interface.
|
||||
//#define IMGUI_IMPL_WEBGPU_BACKEND_DAWN
|
||||
//#define IMGUI_IMPL_WEBGPU_BACKEND_WGPU
|
||||
//#define IMGUI_IMPL_WEBGPU_BACKEND_WGVK
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID!
|
||||
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
|
||||
// [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
|
||||
// [X] Renderer: Texture updates support for dynamic font system (ImGuiBackendFlags_RendererHasTextures).
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
#pragma once
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#include <webgpu/webgpu.h>
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
IMGUI_IMPL_API bool ImGui_ImplWGPU_Init(WGPUDevice device, int num_frames_in_flight, WGPUTextureFormat rt_format);
|
||||
// Setup Emscripten default if not specified.
|
||||
#if defined(__EMSCRIPTEN__) && !defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) && !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||
#include <emscripten/version.h>
|
||||
#define IMGUI_IMPL_WEBGPU_BACKEND_DAWN
|
||||
#endif
|
||||
|
||||
#include <webgpu/webgpu.h>
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) && !defined(__EMSCRIPTEN__)
|
||||
#include <webgpu/wgpu.h> // WGPULogLevel
|
||||
#endif
|
||||
|
||||
// Initialization data, for ImGui_ImplWGPU_Init()
|
||||
struct ImGui_ImplWGPU_InitInfo
|
||||
{
|
||||
WGPUDevice Device = nullptr;
|
||||
int NumFramesInFlight = 3;
|
||||
WGPUTextureFormat RenderTargetFormat = WGPUTextureFormat_Undefined;
|
||||
WGPUTextureFormat DepthStencilFormat = WGPUTextureFormat_Undefined;
|
||||
WGPUMultisampleState PipelineMultisampleState = {};
|
||||
|
||||
ImGui_ImplWGPU_InitInfo()
|
||||
{
|
||||
PipelineMultisampleState.count = 1;
|
||||
PipelineMultisampleState.mask = UINT32_MAX;
|
||||
PipelineMultisampleState.alphaToCoverageEnabled = false;
|
||||
}
|
||||
};
|
||||
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
IMGUI_IMPL_API bool ImGui_ImplWGPU_Init(ImGui_ImplWGPU_InitInfo* init_info);
|
||||
IMGUI_IMPL_API void ImGui_ImplWGPU_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplWGPU_NewFrame();
|
||||
IMGUI_IMPL_API void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder pass_encoder);
|
||||
|
||||
// Use if you want to reset your rendering device without losing Dear ImGui state.
|
||||
IMGUI_IMPL_API void ImGui_ImplWGPU_InvalidateDeviceObjects();
|
||||
IMGUI_IMPL_API bool ImGui_ImplWGPU_CreateDeviceObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplWGPU_InvalidateDeviceObjects();
|
||||
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||
IMGUI_IMPL_API void ImGui_ImplWGPU_UpdateTexture(ImTextureData* tex);
|
||||
|
||||
// [BETA] Selected render state data shared with callbacks.
|
||||
// This is temporarily stored in GetPlatformIO().Renderer_RenderState during the ImGui_ImplWGPU_RenderDrawData() call.
|
||||
// (Please open an issue if you feel you need access to more data)
|
||||
struct ImGui_ImplWGPU_RenderState
|
||||
{
|
||||
WGPUDevice Device;
|
||||
WGPURenderPassEncoder RenderPassEncoder;
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Internal Helpers
|
||||
// Those are currently used by our example applications.
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
// (Optional) Helper to wrap some of the Dawn/WGPU/Emscripten quirks
|
||||
bool ImGui_ImplWGPU_IsSurfaceStatusError(WGPUSurfaceGetCurrentTextureStatus status);
|
||||
bool ImGui_ImplWGPU_IsSurfaceStatusSubOptimal(WGPUSurfaceGetCurrentTextureStatus status); // Return whether the texture is suboptimal and may need to be recreated.
|
||||
|
||||
// (Optional) Helper for debugging/logging
|
||||
void ImGui_ImplWGPU_DebugPrintAdapterInfo(const WGPUAdapter& adapter);
|
||||
const char* ImGui_ImplWGPU_GetBackendTypeName(WGPUBackendType type);
|
||||
const char* ImGui_ImplWGPU_GetAdapterTypeName(WGPUAdapterType type);
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
|
||||
const char* ImGui_ImplWGPU_GetDeviceLostReasonName(WGPUDeviceLostReason type);
|
||||
const char* ImGui_ImplWGPU_GetErrorTypeName(WGPUErrorType type);
|
||||
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||
const char* ImGui_ImplWGPU_GetLogLevelName(WGPULogLevel level);
|
||||
#endif
|
||||
|
||||
// (Optional) Helper to create a surface on macOS/Wayland/X11/Window
|
||||
#ifndef __EMSCRIPTEN__
|
||||
struct ImGui_ImplWGPU_CreateSurfaceInfo
|
||||
{
|
||||
WGPUInstance Instance;
|
||||
const char* System; // "cocoa" | "wayland" | "x11" | "win32"
|
||||
void* RawWindow; // NSWindow* | 0 | Window | HWND
|
||||
void* RawDisplay; // 0 | wl_display* | Display* | 0
|
||||
void* RawSurface; // | wl_surface* | 0 | 0
|
||||
void* RawInstance; // 0 | 0 | 0 | HINSTANCE
|
||||
};
|
||||
WGPUSurface ImGui_ImplWGPU_CreateWGPUSurfaceHelper(ImGui_ImplWGPU_CreateSurfaceInfo* info);
|
||||
#endif // #ifndef __EMSCRIPTEN__
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,26 +1,36 @@
|
||||
// dear imgui: Platform Backend for Windows (standard windows API for 32 and 64 bits applications)
|
||||
// dear imgui: Platform Backend for Windows (standard windows API for 32-bits AND 64-bits applications)
|
||||
// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui)
|
||||
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
// [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImGui::IsKeyPressed(VK_SPACE).
|
||||
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
||||
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen.
|
||||
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy VK_* values are obsolete since 1.87 and not supported since 1.91.5]
|
||||
// [X] Platform: Gamepad support.
|
||||
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
#pragma once
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd);
|
||||
IMGUI_IMPL_API bool ImGui_ImplWin32_InitForOpenGL(void* hwnd);
|
||||
IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame();
|
||||
|
||||
// Win32 message handler your application need to call.
|
||||
// Win32 message handler your application needs to call.
|
||||
// - Intentionally commented out in a '#if 0' block to avoid dragging dependencies on <windows.h> from this helper.
|
||||
// - You should COPY the line below into your .cpp code to forward declare the function and then you can call it.
|
||||
// - Call from your application's message handler. Keep calling your message handler unless this function returns TRUE.
|
||||
|
||||
#if 0
|
||||
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
#endif
|
||||
@@ -30,7 +40,7 @@ extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg
|
||||
// - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps.
|
||||
// - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc.
|
||||
// but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime,
|
||||
// neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies.
|
||||
// neither of which we want to require the user to have. So we dynamically select and load those functions to avoid dependencies.
|
||||
IMGUI_IMPL_API void ImGui_ImplWin32_EnableDpiAwareness();
|
||||
IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd); // HWND hwnd
|
||||
IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor); // HMONITOR monitor
|
||||
@@ -39,3 +49,5 @@ IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor); //
|
||||
// - Use to enable alpha compositing transparency with the desktop.
|
||||
// - Use together with e.g. clearing your framebuffer with zero-alpha.
|
||||
IMGUI_IMPL_API void ImGui_ImplWin32_EnableAlphaCompositing(void* hwnd); // HWND hwnd
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
42
backends/sdlgpu3/build_instructions.txt
Normal file
42
backends/sdlgpu3/build_instructions.txt
Normal file
@@ -0,0 +1,42 @@
|
||||
|
||||
Instructions to rebuild imgui_impl_sdlgpu3_shaders.h
|
||||
(You don't need to copy this folder if you are using the backend as-is)
|
||||
|
||||
1) Compile the raw shader files to SPIRV:
|
||||
|
||||
glslc -o vertex.spv -c shader.vert
|
||||
glslc -o fragment.spv -c shader.frag
|
||||
|
||||
|
||||
2) Build SDL_shadercross (https://github.com/libsdl-org/SDL_shadercross)
|
||||
|
||||
|
||||
3-A) Compiling for the Vulkan Driver:
|
||||
|
||||
Nothing to do, you just need the previous vertex.spv/fragment.spv, proceed to step 4
|
||||
|
||||
|
||||
3-B) Compiling for the DirectX 12 Driver:
|
||||
|
||||
./shadercross vertex.spv -s SPIRV -d DXBC -t vertex -e main -o vertex.dxbc
|
||||
./shadercross fragment.spv -s SPIRV -d DXBC -t fragment -e main -o fragment.dxbc
|
||||
|
||||
Proceed to step 4
|
||||
|
||||
|
||||
3-C) Compiling for Metal (On windows you'll need the Metal Developer Tools for Windows, on linux you might use wine, but I never tested it):
|
||||
|
||||
./shadercross vertex.spv -s SPIRV -d MSL -t vertex -e main -o vertex.metal
|
||||
./shadercross fragment.spv -s SPIRV -d MSL -t fragment -e main -o fragment.metal
|
||||
|
||||
xcrun -sdk macosx metal -o vertex.ir -c vertex.metal
|
||||
xcrun -sdk macosx metal -o fragment.ir -c fragment.metal
|
||||
xcrun -sdk macosx metallib -o vertex.metallib -c vertex.ir
|
||||
xcrun -sdk macosx metallib -o fragment.metallib -c fragment.ir
|
||||
|
||||
note: use .metal outputs for updating msl_vertex / msl_fragment variables, and use .metallib outputs for metallib_vertex / metallib_fragment variables
|
||||
|
||||
Proceed to step 4
|
||||
|
||||
|
||||
4) Use a tool like https://notisrac.github.io/FileToCArray/ or misc/fonts/binary_to_compressed_c.cpp in imgui repository to convert the file to a uint8_t array.
|
||||
15
backends/sdlgpu3/shader.frag
Normal file
15
backends/sdlgpu3/shader.frag
Normal file
@@ -0,0 +1,15 @@
|
||||
#version 450 core
|
||||
layout(location = 0) out vec4 fColor;
|
||||
|
||||
layout(set=2, binding=0) uniform sampler2D sTexture;
|
||||
|
||||
layout(location = 0) in struct
|
||||
{
|
||||
vec4 Color;
|
||||
vec2 UV;
|
||||
} In;
|
||||
|
||||
void main()
|
||||
{
|
||||
fColor = In.Color * texture(sTexture, In.UV.st);
|
||||
}
|
||||
24
backends/sdlgpu3/shader.vert
Normal file
24
backends/sdlgpu3/shader.vert
Normal file
@@ -0,0 +1,24 @@
|
||||
#version 450 core
|
||||
layout(location = 0) in vec2 aPos;
|
||||
layout(location = 1) in vec2 aUV;
|
||||
layout(location = 2) in vec4 aColor;
|
||||
|
||||
layout(set=1,binding=0) uniform UBO
|
||||
{
|
||||
vec2 uScale;
|
||||
vec2 uTranslate;
|
||||
} ubo;
|
||||
|
||||
layout(location = 0) out struct
|
||||
{
|
||||
vec4 Color;
|
||||
vec2 UV;
|
||||
} Out;
|
||||
|
||||
void main()
|
||||
{
|
||||
Out.Color = aColor;
|
||||
Out.UV = aUV;
|
||||
gl_Position = vec4(aPos * ubo.uScale + ubo.uTranslate, 0, 1);
|
||||
gl_Position.y *= -1.0f;
|
||||
}
|
||||
4
backends/vulkan/build_instructions.txt
Normal file
4
backends/vulkan/build_instructions.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
Script to rebuild shaders stored inside imgui_impl_vulkan.h
|
||||
(You don't need to copy this folder if you are using the backend as-is)
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#version 450 core
|
||||
layout(location = 0) out vec4 fColor;
|
||||
|
||||
layout(set=0, binding=0) uniform sampler2D sTexture;
|
||||
layout(set=0, binding=0) uniform texture2D _Texture;
|
||||
layout(set=1, binding=0) uniform sampler _Sampler;
|
||||
|
||||
layout(location = 0) in struct {
|
||||
vec4 Color;
|
||||
@@ -10,5 +11,5 @@ layout(location = 0) in struct {
|
||||
|
||||
void main()
|
||||
{
|
||||
fColor = In.Color * texture(sTexture, In.UV.st);
|
||||
fColor = In.Color * texture(sampler2D(_Texture, _Sampler), In.UV.st);
|
||||
}
|
||||
|
||||
341
docs/BACKENDS.md
341
docs/BACKENDS.md
@@ -1,31 +1,33 @@
|
||||
_(You may browse this at https://github.com/ocornut/imgui/blob/master/docs/BACKENDS.md or view this file with any Markdown viewer)_
|
||||
|
||||
## Dear ImGui: Backends
|
||||
# Dear ImGui: Backends
|
||||
|
||||
**The backends/ folder contains backends for popular platforms/graphics API, which you can use in
|
||||
your application or engine to easily integrate Dear ImGui.** Each backend is typically self-contained in a pair of files: imgui_impl_XXXX.cpp + imgui_impl_XXXX.h.
|
||||
## Index
|
||||
|
||||
- The 'Platform' backends are in charge of: mouse/keyboard/gamepad inputs, cursor shape, timing, windowing.<BR>
|
||||
e.g. Windows ([imgui_impl_win32.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_win32.cpp)), GLFW ([imgui_impl_glfw.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_glfw.cpp)), SDL2 ([imgui_impl_sdl.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_sdl.cpp)), etc.
|
||||
- [Introduction](#introduction)
|
||||
- [Getting Started](#getting-started)
|
||||
- [What are Backends?](#what-are-backends)
|
||||
- [Using standard Backends](#using-standard-backends)
|
||||
- [Using third-party Backends](#using-third-party-backends)
|
||||
- [Writing your own Backend](#writing-your-own-backend)
|
||||
- [Using a custom engine?](#using-a-custom-engine)
|
||||
- [Platform: Implementing your Platform Backend](#platform-implementing-your-platform-backend)
|
||||
- [Rendering: Implementing your RenderDrawData function](#rendering-implementing-your-renderdrawdata-function)
|
||||
- [Rendering: Adding support for `ImGuiBackendFlags_RendererHasTextures` (1.92+)](#rendering-adding-support-for-imguibackendflags_rendererhastextures-192)
|
||||
|
||||
- The 'Renderer' backends are in charge of: creating atlas texture, rendering imgui draw data.<BR>
|
||||
e.g. DirectX11 ([imgui_impl_dx11.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_dx11.cpp)), OpenGL/WebGL ([imgui_impl_opengl3.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_opengl3.cpp), Vulkan ([imgui_impl_vulkan.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_vulkan.cpp), etc.
|
||||
## Introduction
|
||||
|
||||
- For some high-level frameworks, a single backend usually handle both 'Platform' and 'Renderer' parts.<BR>
|
||||
e.g. Allegro 5 ([imgui_impl_allegro5.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_allegro5.cpp)), Marmalade ([imgui_impl_marmalade.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_marmalade.cpp)). If you end up creating a custom backend for your engine, you may want to do the same.
|
||||
### Getting Started
|
||||
|
||||
An application usually combines 1 Platform backend + 1 Renderer backend + main Dear ImGui sources.
|
||||
For example, the [example_win32_directx11](https://github.com/ocornut/imgui/tree/master/examples/example_win32_directx11) application combines imgui_impl_win32.cpp + imgui_impl_dx11.cpp. There are 20+ examples in the [examples/](https://github.com/ocornut/imgui/blob/master/examples/) folder. See [EXAMPLES.MD](https://github.com/ocornut/imgui/blob/master/docs/EXAMPLES.md) for details.
|
||||
💡 The **[Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started) wiki guide** has examples of how to integrate Dear ImGui into an existing application.
|
||||
<BR> The [EXAMPLES.MD](https://github.com/ocornut/imgui/blob/master/docs/EXAMPLES.md) documentation may also be worth a read.
|
||||
|
||||
**Once Dear ImGui is setup and running, run and refer to `ImGui::ShowDemoWindow()` in imgui_demo.cpp for usage of the end-user API.**
|
||||
|
||||
|
||||
### What are backends
|
||||
### What are Backends?
|
||||
|
||||
Dear ImGui is highly portable and only requires a few things to run and render, typically:
|
||||
|
||||
- Required: providing mouse/keyboard inputs (fed into the `ImGuiIO` structure).
|
||||
- Required: uploading the font atlas texture into graphics memory.
|
||||
- Required: creating, updating and destroying textures.
|
||||
- Required: rendering indexed textured triangles with a clipping rectangle.
|
||||
|
||||
Extra features are opt-in, our backends try to support as many as possible:
|
||||
@@ -38,57 +40,70 @@ Dear ImGui is highly portable and only requires a few things to run and render,
|
||||
- Optional: multi-viewports support.
|
||||
etc.
|
||||
|
||||
This is essentially what each backends are doing + obligatory portability cruft. Using default backends ensure you can get all those features including the ones that would be harder to implement on your side (e.g. multi-viewports support).
|
||||
This is essentially what each backend is doing + obligatory portability cruft. Using standard backends ensure you can get all those features including the ones that would be harder to implement on your side (e.g. multi-viewports support).
|
||||
|
||||
It is important to understand the difference between the core Dear ImGui library (files in the root folder)
|
||||
and backends which we are describing here (backends/ folder).
|
||||
and the backends which we are describing here (backends/ folder).
|
||||
|
||||
- Some issues may only be backend or platform specific.
|
||||
- You should be able to write backends for pretty much any platform and any 3D graphics API.
|
||||
e.g. you can get creative and use software rendering or render remotely on a different machine.
|
||||
|
||||
## Using standard Backends
|
||||
|
||||
### Integrating a backend
|
||||
**The [backends/](https://github.com/ocornut/imgui/blob/master/backends) folder contains backends for popular platforms/graphics API, which you can use in
|
||||
your application or engine to easily integrate Dear ImGui.** Each backend is typically self-contained in a pair of files: imgui_impl_XXXX.cpp + imgui_impl_XXXX.h.
|
||||
|
||||
See "Getting Started" section of [EXAMPLES.MD](https://github.com/ocornut/imgui/blob/master/docs/EXAMPLES.md) for more details.
|
||||
- The 'Platform' backends are in charge of: mouse/keyboard/gamepad inputs, cursor shape, timing, and windowing.<BR>
|
||||
e.g. Windows ([imgui_impl_win32.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_win32.cpp)), SDL3 ([imgui_impl_sdl3.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_sdl3.cpp)), GLFW ([imgui_impl_glfw.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_glfw.cpp)), etc.
|
||||
|
||||
- The 'Renderer' backends are in charge of: creating atlas texture, and rendering imgui draw data.<BR>
|
||||
e.g. DirectX11 ([imgui_impl_dx11.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_dx11.cpp)), OpenGL/WebGL ([imgui_impl_opengl3.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_opengl3.cpp)), Vulkan ([imgui_impl_vulkan.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_vulkan.cpp)), etc.
|
||||
|
||||
### List of backends
|
||||
- For some high-level frameworks, a single backend usually handles both 'Platform' and 'Renderer' parts.<BR>
|
||||
e.g. Allegro 5 ([imgui_impl_allegro5.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_allegro5.cpp)). If you end up creating a custom backend for your engine, you may want to do the same.
|
||||
|
||||
An application usually combines one Platform backend + one Renderer backend + main Dear ImGui sources.
|
||||
For example, the [example_win32_directx11](https://github.com/ocornut/imgui/tree/master/examples/example_win32_directx11) application combines imgui_impl_win32.cpp + imgui_impl_dx11.cpp. There are 20+ examples in the [examples/](https://github.com/ocornut/imgui/blob/master/examples/) folder. See [EXAMPLES.MD](https://github.com/ocornut/imgui/blob/master/docs/EXAMPLES.md) for details.
|
||||
|
||||
**Once Dear ImGui is setup and running, run and refer to `ImGui::ShowDemoWindow()` in imgui_demo.cpp for usage of the end-user API.**
|
||||
|
||||
### List of standard Backends
|
||||
|
||||
In the [backends/](https://github.com/ocornut/imgui/blob/master/backends) folder:
|
||||
|
||||
List of Platforms Backends:
|
||||
|
||||
imgui_impl_android.cpp ; Android native app API
|
||||
imgui_impl_glfw.cpp ; GLFW (Windows, macOS, Linux, etc.) http://www.glfw.org/
|
||||
imgui_impl_osx.mm ; macOS native API (not as feature complete as glfw/sdl backends)
|
||||
imgui_impl_sdl.cpp ; SDL2 (Windows, macOS, Linux, iOS, Android) https://www.libsdl.org
|
||||
imgui_impl_win32.cpp ; Win32 native API (Windows)
|
||||
imgui_impl_glut.cpp ; GLUT/FreeGLUT (this is prehistoric software and absolutely not recommended today!)
|
||||
imgui_impl_android.cpp ; Android native app API
|
||||
imgui_impl_glfw.cpp ; GLFW (Windows, macOS, Linux, etc.) http://www.glfw.org/
|
||||
imgui_impl_osx.mm ; macOS native API (not as feature complete as glfw/sdl backends)
|
||||
imgui_impl_sdl2.cpp ; SDL2 (Windows, macOS, Linux, iOS, Android) https://www.libsdl.org
|
||||
imgui_impl_sdl3.cpp ; SDL3 (Windows, macOS, Linux, iOS, Android) https://www.libsdl.org
|
||||
imgui_impl_win32.cpp ; Win32 native API (Windows)
|
||||
imgui_impl_glut.cpp ; GLUT/FreeGLUT (this is prehistoric software and absolutely not recommended today!)
|
||||
|
||||
List of Renderer Backends:
|
||||
|
||||
imgui_impl_dx9.cpp ; DirectX9
|
||||
imgui_impl_dx10.cpp ; DirectX10
|
||||
imgui_impl_dx11.cpp ; DirectX11
|
||||
imgui_impl_dx12.cpp ; DirectX12
|
||||
imgui_impl_metal.mm ; Metal (with ObjC)
|
||||
imgui_impl_opengl2.cpp ; OpenGL 2 (legacy, fixed pipeline <- don't use with modern OpenGL context)
|
||||
imgui_impl_opengl3.cpp ; OpenGL 3/4, OpenGL ES 2, OpenGL ES 3 (modern programmable pipeline)
|
||||
imgui_impl_vulkan.cpp ; Vulkan
|
||||
imgui_impl_wgpu.cpp ; WebGPU
|
||||
imgui_impl_dx9.cpp ; DirectX9
|
||||
imgui_impl_dx10.cpp ; DirectX10
|
||||
imgui_impl_dx11.cpp ; DirectX11
|
||||
imgui_impl_dx12.cpp ; DirectX12
|
||||
imgui_impl_metal.mm ; Metal (ObjC or C++)
|
||||
imgui_impl_opengl2.cpp ; OpenGL 2 (legacy fixed pipeline. Don't use with modern OpenGL code!)
|
||||
imgui_impl_opengl3.cpp ; OpenGL 3/4, OpenGL ES 2/3, WebGL
|
||||
imgui_impl_sdlgpu3.cpp ; SDL_GPU (portable 3D graphics API of SDL3)
|
||||
imgui_impl_sdlrenderer2.cpp ; SDL_Renderer (optional component of SDL2 available from SDL 2.0.18+)
|
||||
imgui_impl_sdlrenderer3.cpp ; SDL_Renderer (optional component of SDL3. Prefer using SDL_GPU!).
|
||||
imgui_impl_vulkan.cpp ; Vulkan
|
||||
imgui_impl_wgpu.cpp ; WebGPU (web + desktop)
|
||||
|
||||
List of high-level Frameworks Backends (combining Platform + Renderer):
|
||||
|
||||
imgui_impl_allegro5.cpp
|
||||
imgui_impl_marmalade.cpp
|
||||
imgui_impl_null.cpp
|
||||
|
||||
Emscripten is also supported.
|
||||
The [example_emscripten_opengl3](https://github.com/ocornut/imgui/tree/master/examples/example_emscripten_opengl3) app uses imgui_impl_sdl.cpp + imgui_impl_opengl3.cpp, but other combos are possible.
|
||||
|
||||
### Backends for third-party frameworks, graphics API or other languages
|
||||
|
||||
See https://github.com/ocornut/imgui/wiki/Bindings for the full list.
|
||||
Emscripten is also supported!
|
||||
The SDL2+GL, SDL3+GL, GLFW+GL and GLFW+WebGPU examples are all ready to build and run with Emscripten.
|
||||
|
||||
### Recommended Backends
|
||||
|
||||
@@ -96,46 +111,268 @@ If you are not sure which backend to use, the recommended platform/frameworks fo
|
||||
|
||||
|Library |Website |Backend |Note |
|
||||
|--------|--------|--------|-----|
|
||||
| SDL3 | https://www.libsdl.org | imgui_impl_sdl3.cpp | Recommended |
|
||||
| SDL2 | https://www.libsdl.org | imgui_impl_sdl2.cpp | |
|
||||
| GLFW | https://github.com/glfw/glfw | imgui_impl_glfw.cpp | |
|
||||
| SDL2 | https://www.libsdl.org | imgui_impl_sdl.cpp | |
|
||||
| Sokol | https://github.com/floooh/sokol | [util/sokol_imgui.h](https://github.com/floooh/sokol/blob/master/util/sokol_imgui.h) | Lower-level than GLFW/SDL |
|
||||
|
||||
If your application runs on Windows or if you are using multi-viewport, the win32 backend handles some details a little better than other backends.
|
||||
|
||||
## Using third-party Backends
|
||||
|
||||
See https://github.com/ocornut/imgui/wiki/Bindings for the full list (e.g. Adventure Game Studio, Cinder, Cocos2d-x, Game Maker Studio2, Godot, LÖVE+LUA, Magnum, Monogame, Ogre, openFrameworks, OpenSceneGraph, SFML, Sokol, Unity, Unreal Engine and many others).
|
||||
|
||||
## Writing your own Backend
|
||||
|
||||
### Using a custom engine?
|
||||
|
||||
You will likely be tempted to start by rewrite your own backend using your own custom/high-level facilities...<BR>
|
||||
Think twice!
|
||||
|
||||
If you are new to Dear ImGui, first try using the existing backends as-is.
|
||||
TL;DR;
|
||||
- Writing your own Renderer Backend is easy.
|
||||
- Writing your own Platform Backend is harder and you are more likely to introduce bugs.
|
||||
- **It is unlikely you will add value to your project by creating your own backend.**
|
||||
|
||||
**Consider using the existing backends as-is**.
|
||||
You will save lots of time integrating the library.
|
||||
Standard backends are battle-tested and handle subtleties that you are likely to implement incorrectly.
|
||||
You can LATER decide to rewrite yourself a custom backend if you really need to.
|
||||
In most situations, custom backends have less features and more bugs than the standard backends we provide.
|
||||
In most situations, custom backends have fewer features and more bugs than the standard backends we provide.
|
||||
If you want portability, you can use multiple backends and choose between them either at compile time
|
||||
or at runtime.
|
||||
|
||||
**Example A**: your engine is built over Windows + DirectX11 but you have your own high-level rendering
|
||||
system layered over DirectX11.<BR>
|
||||
Suggestion: try using imgui_impl_win32.cpp + imgui_impl_dx11.cpp first.
|
||||
Once it works, if you really need it you can replace the imgui_impl_dx11.cpp code with a
|
||||
Once it works, if you really need it, you can replace the imgui_impl_dx11.cpp code with a
|
||||
custom renderer using your own rendering functions, and keep using the standard Win32 code etc.
|
||||
|
||||
**Example B**: your engine runs on Windows, Mac, Linux and uses DirectX11, Metal, Vulkan respectively.<BR>
|
||||
**Example B**: your engine runs on Windows, Mac, Linux and uses DirectX11, Metal, and Vulkan respectively.<BR>
|
||||
Suggestion: use multiple generic backends!
|
||||
Once it works, if you really need it you can replace parts of backends with your own abstractions.
|
||||
Once it works, if you really need it, you can replace parts of backends with your own abstractions.
|
||||
|
||||
**Example C**: your engine runs on platforms we can't provide public backends for (e.g. PS4/PS5, Switch),
|
||||
and you have high-level systems everywhere.<BR>
|
||||
Suggestion: try using a non-portable backend first (e.g. win32 + underlying graphics API) to get
|
||||
your desktop builds working first. This will get you running faster and get your acquainted with
|
||||
how Dear ImGui works and is setup. You can then rewrite a custom backend using your own engine API.
|
||||
how Dear ImGui works and is setup. You can then rewrite a custom backend using your own engine API...
|
||||
|
||||
Also:
|
||||
The [multi-viewports feature](https://github.com/ocornut/imgui/issues/1542) of the 'docking' branch allows
|
||||
The [multi-viewports feature](https://github.com/ocornut/imgui/wiki/Multi-Viewports) of the 'docking' branch allows
|
||||
Dear ImGui windows to be seamlessly detached from the main application window. This is achieved using an
|
||||
extra layer to the Platform and Renderer backends, which allows Dear ImGui to communicate platform-specific
|
||||
requests such as: "create an additional OS window", "create a render context", "get the OS position of this
|
||||
window" etc. See 'ImGuiPlatformIO' for details.
|
||||
window", but some things are more difficult "find OS window under mouse position BUT with some windows marked as passthrough". See 'ImGuiPlatformIO' for details.
|
||||
Supporting the multi-viewports feature correctly using 100% of your own abstractions is more difficult
|
||||
than supporting single-viewport.
|
||||
If you decide to use unmodified imgui_impl_XXXX.cpp files, you can automatically benefit from
|
||||
improvements and fixes related to viewports and platform windows without extra work on your side.
|
||||
|
||||
### Platform: Implementing your Platform Backend
|
||||
|
||||
The Platform backends in impl_impl_XXX.cpp files contain many implementations.
|
||||
|
||||
**In your `ImGui_ImplXXX_Init()` function:**
|
||||
- You can allocate your backend data and use `io.BackendPlatformUserData` to store/retrieve it later.
|
||||
- Set `io.BackendPlatformName` to a name `"imgui_impl_xxxx"` which will be available in e.g. About box.
|
||||
- Set `io.BackendPlatformUserData` to your backend data.
|
||||
- Set `io.BackendFlags` with supported optional features:
|
||||
- `ImGuiBackendFlags_HasGamepad`: supports gamepad and currently has one connected.
|
||||
- `ImGuiBackendFlags_HasMouseCursors`: supports honoring GetMouseCursor() value to change the OS cursor shape.
|
||||
- `ImGuiBackendFlags_HasSetMousePos`: supports io.WantSetMousePos requests to reposition the OS mouse position (only used if io.ConfigNavMoveSetMousePos is set).
|
||||
- `ImGuiBackendFlags_PlatformHasViewports` supports multiple viewports. (multi-viewports only)
|
||||
- `ImGuiBackendFlags_HasMouseHoveredViewport` supports calling io.AddMouseViewportEvent() with the viewport under the mouse. IF POSSIBLE, ignore viewports with the ImGuiViewportFlags_NoInputs flag. If this cannot be done, Dear ImGui needs to use a flawed heuristic to find the viewport under mouse position, as it doesn't know about foreign windows. (multi-viewports only)
|
||||
|
||||
**In your `ImGui_ImplXXX_NewFrame()` function:**
|
||||
- Set `io.DeltaTime` to the time elapsed (in seconds) since last frame.
|
||||
- Set `io.DisplaySize` to your window size.
|
||||
- Set `io.DisplayFrameBufferSize` to your window pixel density (macOS/iOS only).
|
||||
- Update mouse cursor shape is supported.
|
||||
|
||||
**In your `ImGui_ImplXXX_NewFrame()` function or event handlers:**
|
||||
- **Mouse Support**
|
||||
- Use `io.AddMousePosEvent()`, `io.AddMouseButtonEvent()`, `io.AddMouseWheelEvent()` to pass mouse events.
|
||||
- Use `io.AddMouseSourceEvent()` if you are able to distinguish Mouse from TouchScreen from Pen inputs. TouchScreen and Pen inputs requires different logic for some Dear ImGui features.
|
||||
- Use `io.AddMouseViewportEvent()` to specify which viewport/OS window is being hovered by the mouse. Read instructions carefully as this is not as simple as it seems! (multi-viewports only)
|
||||
- **Keyboard Support**
|
||||
- Use `io.AddKeyEvent()` to pass key events.
|
||||
- Use `io.AddInputCharacter()` to pass text/character events.
|
||||
- **Gamepad Support**
|
||||
- Use `io.AddKeyEvent()` and `io.AddKeyAnalogEvent()` to pass gamepad events, using `ImGuiKey_GamepadXXX` values.
|
||||
- **Miscellaneous**
|
||||
- Clipboard Support: setup `Platform_GetClipboardTextFn()`, `Platform_SetClipboardTextFn()` handlers in `ImGuiPlatformIO`.
|
||||
- Open in Shell support: setup `Platform_OpenInShellFn()` handler in `ImGuiPlatformIO`.
|
||||
- IME Support: setup `Platform_SetImeDataFn()` handler in `ImGuiPlatformIO`.
|
||||
- Use `io.AddFocusEvent()` to notify when application window gets focused/unfocused.
|
||||
- **Multi-viewport Support**
|
||||
- Update monitor list if supported.
|
||||
- Setup all required handlers in `ImGuiPlatformIO` to create/destroy/move/resize/title/focus/etc. windows.
|
||||
|
||||
### Rendering: Implementing your RenderDrawData function
|
||||
|
||||
Note: set `ImGuiBackendFlags_RendererHasVtxOffset` to signify your backend can handle rendering with a vertex offset (`ImDrawCmd::VtxOffset` field).
|
||||
Otherwise, rendering will be limited to 64K vertices per window, which may be limiting for advanced plot.
|
||||
As an alternative, you may also use `#define ImDrawIdx unsigned int` in your `imconfig.h` file to support 32-bit indices.
|
||||
|
||||
```cpp
|
||||
void MyImGuiBackend_RenderDrawData(ImDrawData* draw_data)
|
||||
{
|
||||
// TODO: Update textures.
|
||||
// - Most of the times, the list will have 1 element with an OK status, aka nothing to do.
|
||||
// - This almost always points to ImGui::GetPlatformIO().Textures[] but is part of ImDrawData to allow overriding or disabling texture updates.
|
||||
if (draw_data->Textures != nullptr)
|
||||
for (ImTextureData* tex : *draw_data->Textures)
|
||||
if (tex->Status != ImTextureStatus_OK)
|
||||
MyImGuiBackend_UpdateTexture(tex);
|
||||
|
||||
// TODO: Setup render state:
|
||||
// - Alpha-blending enabled
|
||||
// - No backface culling
|
||||
// - No depth testing, no depth writing
|
||||
// - Scissor enabled
|
||||
MyEngineSetupenderState();
|
||||
|
||||
// TODO: Setup texture sampling state
|
||||
// - Sample with bilinear filtering (NOT point/nearest filtering).
|
||||
// - Use 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines;' to allow point/nearest filtering.
|
||||
|
||||
// TODO: Setup viewport covering draw_data->DisplayPos to draw_data->DisplayPos + draw_data->DisplaySize
|
||||
|
||||
// TODO: Setup orthographic projection matrix cover draw_data->DisplayPos to draw_data->DisplayPos + draw_data->DisplaySize
|
||||
|
||||
// TODO: Setup shader: vertex { float2 pos, float2 uv, u32 color }, fragment shader sample color from 1 texture, multiply by vertex color.
|
||||
|
||||
// Render command lists
|
||||
ImVec2 clip_off = draw_data->DisplayPos;
|
||||
ImVec2 clip_scale = draw_data->FramebufferScale;
|
||||
for (const ImDrawList* draw_list : draw_data->CmdLists)
|
||||
{
|
||||
const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data; // vertex buffer generated by Dear ImGui
|
||||
const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data; // index buffer generated by Dear ImGui
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback)
|
||||
{
|
||||
if (pcmd->UserCallback == platform_io.DrawCallback_ResetRenderState)
|
||||
MyEngineSetupSenderState();
|
||||
else
|
||||
pcmd->UserCallback(cmd_list, pcmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Project scissor/clipping rectangles into framebuffer space
|
||||
// - Clipping coordinates are provided in imgui coordinates space:
|
||||
// - For a given viewport, draw_data->DisplayPos == viewport->Pos and draw_data->DisplaySize == viewport->Size
|
||||
// - In a single viewport application, draw_data->DisplayPos == (0,0) and draw_data->DisplaySize == io.DisplaySize, but always use GetMainViewport()->Pos/Size instead of hardcoding those values.
|
||||
// - In the interest of supporting multi-viewport applications (see 'docking' branch on github),
|
||||
// always subtract draw_data->DisplayPos from clipping bounds to convert them to your viewport space.
|
||||
// - Note that pcmd->ClipRect contains Min+Max bounds. Some graphics API may use Min+Max, other may use Min+Size (size being Max-Min)
|
||||
ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
|
||||
ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
|
||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||
continue;
|
||||
|
||||
// We are using scissoring to clip some objects. All low-level graphics API should support it.
|
||||
// - If your engine doesn't support scissoring yet, you may ignore this at first. You will get some small glitches
|
||||
// (some elements visible outside their bounds) but you can fix that once everything else works!
|
||||
MyEngineSetScissor(clip_min.x, clip_min.y, clip_max.x, clip_max.y);
|
||||
|
||||
// The texture for the draw call is specified by pcmd->GetTexID().
|
||||
// The vast majority of draw calls will use the Dear ImGui texture atlas, which value you have set yourself during initialization.
|
||||
MyEngineBindTexture((MyTexture*)pcmd->GetTexID());
|
||||
|
||||
// Render 'pcmd->ElemCount/3' indexed triangles.
|
||||
// By default the indices ImDrawIdx are 16-bit, you can change them to 32-bit in imconfig.h if your engine doesn't support 16-bit indices.
|
||||
MyEngineDrawIndexedTriangles(pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer + pcmd->IdxOffset, vtx_buffer, pcmd->VtxOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Rendering: Adding support for `ImGuiBackendFlags_RendererHasTextures` (1.92+)
|
||||
|
||||
Version [1.92.0](https://github.com/ocornut/imgui/releases/tag/v1.92.0) (June 2025), added texture support in Rendering Backends, which is the backbone for supporting dynamic font scaling among other things.
|
||||
|
||||
**In order to move forward and take advantage of all new features, support for `ImGuiBackendFlags_RendererHasTextures` will likely be REQUIRED for all backends before June 2026.**
|
||||
|
||||
`ImFontAtlas` functions such as `Build()`, `GetTexDataAsRGBA32()`, `GetTexDataAsAlpha8()`, `SetTexID()`, `IsBuilt()` were obsoleted in favor if iterating a `Textures[]` array and updating their state when requested by Dear ImGui.
|
||||
|
||||
**TD;DR: List of commits which added support for `ImGuiBackendFlags_RendererHasTextures` in standard backends:**
|
||||
|
||||
- Allegro5: [ee8941e](https://github.com/ocornut/imgui/commit/ee8941e) (+35 lines)
|
||||
- DirectX9: [75efba7](https://github.com/ocornut/imgui/commit/75efba7) (+48 lines)
|
||||
- DirectX10: [2d2b1bc](https://github.com/ocornut/imgui/commit/2d2b1bc) (+40 lines)
|
||||
- DirectX11: [372fd27](https://github.com/ocornut/imgui/commit/372fd27) (+40 lines)
|
||||
- DirectX12: [eefe5d5](https://github.com/ocornut/imgui/commit/eefe5d5) (+87 lines)
|
||||
- Metal: [26c017d](https://github.com/ocornut/imgui/commit/26c017d) (+55 lines)
|
||||
- OpenGL Legacy: [0430c55](https://github.com/ocornut/imgui/commit/0430c55) (+25 lines)
|
||||
- OpenGL3/WebGL/ES: [dbb91a5](https://github.com/ocornut/imgui/commit/dbb91a5) (+47 lines)
|
||||
- SDL_Renderer2: [9fa65cd](https://github.com/ocornut/imgui/commit/9fa65cd) (+20 lines)
|
||||
- SDL_Renderer3: [e538883](https://github.com/ocornut/imgui/commit/e538883) (+19 lines)
|
||||
- SDL_GPU: [16fe666](https://github.com/ocornut/imgui/commit/16fe666) (+41 lines)
|
||||
- Vulkan: [abe294b](https://github.com/ocornut/imgui/commit/abe294b) (+33 lines)
|
||||
- WGPU: [571dae9](https://github.com/ocornut/imgui/commit/571dae9) (+30 lines)
|
||||
|
||||
**Instructions:**
|
||||
|
||||
- Set `ImGuiBackendFlags_RendererHasTextures` to signify your backend can handle the feature.
|
||||
- During rendering, e.g. in your RenderDrawData function, iterate `ImDrawData->Textures` array and process all textures.
|
||||
- During shutdown, iterate the `ImGui::GetPlatformIO().Textures` and destroy all textures.
|
||||
- (Both arrays are `ImVector<ImTextureData*>`. They are only in different location because: to allow advanced users to perform multi-threaded rendering, we store a pointer to the texture list in ImDrawData, with the aim that multi-threaded rendering users replace it with their own pointer.)
|
||||
|
||||
Pseudo-code for processing a texture:
|
||||
```cpp
|
||||
if (draw_data->Textures != nullptr)
|
||||
for (ImTextureData* tex : *draw_data->Textures)
|
||||
if (tex->Status != ImTextureStatus_OK)
|
||||
MyImGuiBackend_UpdateTexture(tex);
|
||||
```
|
||||
```cpp
|
||||
void MyImGuiBackend_UpdateTexture(ImTextureData* tex)
|
||||
{
|
||||
if (tex->Status == ImTextureStatus_WantCreate)
|
||||
{
|
||||
// Create texture based on tex->Width, tex->Height.
|
||||
// - Most backends only support tex->Format == ImTextureFormat_RGBA32.
|
||||
// - Backends for particularly memory constrained platforms may support tex->Format == ImTextureFormat_Alpha8.
|
||||
|
||||
// Upload all texture pixels
|
||||
// - Read from our CPU-side copy of the texture and copy to your graphics API.
|
||||
// - Use tex->Width, tex->Height, tex->GetPixels(), tex->GetPixelsAt(), tex->GetPitch() as needed.
|
||||
|
||||
// Store your data, and acknowledge creation.
|
||||
tex->SetTexID(xxxx); // Specify backend-specific ImTextureID identifier which will be stored in ImDrawCmd.
|
||||
tex->SetStatus(ImTextureStatus_OK);
|
||||
tex->BackendUserData = xxxx; // Store more backend data if needed (most backend allocate a small texture to store data in there)
|
||||
}
|
||||
if (tex->Status == ImTextureStatus_WantUpdates)
|
||||
{
|
||||
// Upload a rectangle of pixels to the existing texture
|
||||
// - We only ever write to textures regions which have never been used before!
|
||||
// - Use tex->TexID or tex->BackendUserData to retrieve your stored data.
|
||||
// - Use tex->UpdateRect.x/y, tex->UpdateRect.w/h to obtain the block position and size.
|
||||
// - Use tex->Updates[] to obtain individual sub-regions within tex->UpdateRect. Not recommended.
|
||||
// - Read from our CPU-side copy of the texture and copy to your graphics API.
|
||||
// - Use tex->Width, tex->Height, tex->GetPixels(), tex->GetPixelsAt(), tex->GetPitch() as needed.
|
||||
|
||||
// Acknowledge update
|
||||
tex->SetStatus(ImTextureStatus_OK);
|
||||
}
|
||||
if (tex->Status == ImTextureStatus_WantDestroy && tex->UnusedFrames > 0)
|
||||
{
|
||||
// If you use staged rendering and have in-flight renders, changed tex->UnusedFrames > 0 check to higher count as needed e.g. > 2
|
||||
|
||||
// Destroy texture
|
||||
// - Use tex->TexID or tex->BackendUserData to retrieve your stored data.
|
||||
// - Destroy texture in your graphics API.
|
||||
|
||||
// Acknowledge destruction
|
||||
tex->SetTexID(ImTextureID_Invalid);
|
||||
tex->SetStatus(ImTextureStatus_Destroyed);
|
||||
}
|
||||
}
|
||||
```
|
||||
Refer to "List of commits which added support for `ImGuiBackendFlags_RendererHasTextures` in standard backends" above for concrete examples of this.
|
||||
|
||||
6183
docs/CHANGELOG.txt
6183
docs/CHANGELOG.txt
File diff suppressed because it is too large
Load Diff
81
docs/CONTRIBUTING.md
Normal file
81
docs/CONTRIBUTING.md
Normal file
@@ -0,0 +1,81 @@
|
||||
# Contributing Guidelines
|
||||
|
||||
## Index
|
||||
|
||||
- [Getting Started & General Advice](#getting-started--general-advice)
|
||||
- [Issues vs Discussions](#issues-vs-discussions)
|
||||
- [How to open an Issue](#how-to-open-an-issue)
|
||||
- [How to open a Pull Request](#how-to-open-a-pull-request)
|
||||
- [Copyright / Contributor License Agreement](#copyright--contributor-license-agreement)
|
||||
|
||||
## Getting Started & General Advice
|
||||
|
||||
- Article: [How To Ask Good Questions](https://bit.ly/3nwRnx1).
|
||||
- Please browse the [Wiki](https://github.com/ocornut/imgui/wiki) to find code snippets, links and other resources (e.g. [Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started), [Useful extensions](https://github.com/ocornut/imgui/wiki/Useful-Extensions)).
|
||||
- Please read [Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started) if your question relates to setting up Dear ImGui.
|
||||
- Please read [docs/FAQ.md](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md).
|
||||
- Please read [docs/FONTS.md](https://github.com/ocornut/imgui/blob/master/docs/FONTS.md) if your question relates to fonts or text.
|
||||
- Please run `ImGui::ShowDemoWindow()` to explore the demo and its sources.
|
||||
- Please use the search function of your IDE to search for symbols and comments related to your situation.
|
||||
- Please use the search function of GitHub to look for similar topics (always include 'Closed' issues/pr in your search).
|
||||
- You may [browse issues by Labels](https://github.com/ocornut/imgui/labels).
|
||||
- Please use a web search engine to look for similar issues.
|
||||
- If you get a crash or assert, use a debugger to locate the line triggering it and read the comments around.
|
||||
- Please don't be a [Help Vampire](https://slash7.com/2006/12/22/vampires/).
|
||||
|
||||
## 'Issues' vs 'Discussions'
|
||||
|
||||
We are happy to use 'Issues' for many type of open-ended questions. We are encouraging 'Issues' becoming an enormous, centralized and cross-referenced database of Dear ImGui contents.
|
||||
|
||||
Only if you:
|
||||
- Cannot BUILD or LINK examples.
|
||||
- Cannot BUILD, or LINK, or RUN Dear ImGui in your application or custom engine.
|
||||
- Cannot LOAD a font.
|
||||
|
||||
Then please [use the Discussions forums](https://github.com/ocornut/imgui/discussions) instead of opening an issue.
|
||||
|
||||
If Dear ImGui is successfully showing in your app and you have used Dear ImGui before, you can open an Issue. Any form of discussions is welcome as a new issue.
|
||||
|
||||
## How to open an issue
|
||||
|
||||
You may use the Issue Tracker to submit bug reports, feature requests or suggestions. You may ask for help or advice as well. But **PLEASE CAREFULLY READ THIS WALL OF TEXT. ISSUES IGNORING THOSE GUIDELINES MAY BE CLOSED. USERS IGNORING THOSE GUIDELINES MIGHT BE BLOCKED.**
|
||||
|
||||
Please do your best to clarify your request. The amount of incomplete or ambiguous requests due to people not following those guidelines is often overwhelming. Issues created without the requested information may be closed prematurely. Exceptionally entitled, impolite, or lazy requests may lead to bans.
|
||||
|
||||
**PLEASE UNDERSTAND THAT OPEN-SOURCE SOFTWARE LIVES OR DIES BY THE AMOUNT OF ENERGY MAINTAINERS CAN SPARE. WE HAVE LOTS OF STUFF TO DO. THIS IS AN ATTENTION ECONOMY AND MANY LAZY OR MINOR ISSUES ARE HOGGING OUR ATTENTION AND DRAINING ENERGY, TAKING US AWAY FROM MORE IMPORTANT WORK.**
|
||||
|
||||
Steps:
|
||||
|
||||
- Article: [How To Ask Good Questions](https://bit.ly/3nwRnx1).
|
||||
- **PLEASE DO FILL THE REQUESTED NEW ISSUE TEMPLATE.** Including Dear ImGui version number, branch name, platform/renderer back-ends (imgui_impl_XXX files), operating system.
|
||||
- **Try to be explicit with your GOALS, your EXPECTATIONS and what you have tried**. Be mindful of [The XY Problem](http://xyproblem.info/). What you have in mind or in your code is not obvious to other people. People frequently discuss problems and suggest incorrect solutions without first clarifying their goals. When requesting a new feature, please describe the usage context (how you intend to use it, why you need it, etc.). If you tried something and it failed, show us what you tried.
|
||||
- **Please INCLUDE CODE. Provide a Minimal, Complete, and Verifiable Example ([MCVE](https://stackoverflow.com/help/mcve)) to demonstrate your problem**. An ideal submission includes a small piece of code that anyone can paste into one of the examples applications (examples/../main.cpp) or demo (imgui_demo.cpp) to understand and reproduce it. **Narrowing your problem to its shortest and purest form is the easiest way to understand it, explain it and fix it**. Please test your shortened code to ensure it exhibits the problem. **Often while creating the MCVE you will solve the problem!** Many questions that are missing a standalone verifiable example are missing the actual cause of their issue in the description, which ends up wasting everyone's time.
|
||||
- **Attach screenshots (or GIF/video) to clarify the context**. They often convey useful information that is omitted by the description. You can drag pictures/files in the message edit box. Avoid using 3rd party image hosting services, prefer the long-term longevity of GitHub attachments (you can drag pictures into your post). On Windows, you can use [ScreenToGif](https://www.screentogif.com/) to easily capture .gif files.
|
||||
- **If you are discussing an assert or a crash, please provide a debugger callstack**. Never state "it crashes" without additional information. If you don't know how to use a debugger and retrieve a callstack, learning about it will be useful.
|
||||
- **Please make sure that your project has asserts enabled.** Calls to IM_ASSERT() are scattered in the code to help catch common issues. When an assert is triggered read the comments around it. By default IM_ASSERT() calls the standard assert() function. To verify that your asserts are enabled, add the line `IM_ASSERT(false);` in your main() function. Your application should display an error message and abort. If your application doesn't report an error, your asserts are disabled.
|
||||
- Please state if you have made substantial modifications to your copy of Dear ImGui or the back-end.
|
||||
- If you are not calling Dear ImGui directly from C++, please provide information about your Language and the wrapper/binding you are using.
|
||||
- Be mindful that messages are being sent to the mailbox of "Watching" users. Try to proofread your messages before sending them. Edits are not seen by those users unless they browse the site.
|
||||
|
||||
**Some unfortunate words of warning**
|
||||
- If you are involved in cheating schemes (e.g. DLL injection) for competitive online multiplayer games, please don't post here. We won't answer and you will be blocked. It doesn't matter if your question relates to said project. We've had too many of you and need to protect our time and sanity.
|
||||
- Due to frequent abuse of this service from the aforementioned users, if your GitHub account is anonymous and was created five minutes ago please understand that your post will receive more scrutiny and incomplete questions will be harshly dismissed.
|
||||
|
||||
If you have been using Dear ImGui for a while or have been using C/C++ for several years or have demonstrated good behavior here, it is ok to not fulfill every item to the letter. Those are guidelines and experienced users or members of the community will know which information is useful in a given context.
|
||||
|
||||
## How to open a Pull Request
|
||||
|
||||
- **Please understand that by submitting a PR you are also submitting a request for the maintainer to review your code and then take over its maintenance.** PR should be crafted both in the interest of the end-users and also to ease the maintainer into understanding and accepting it.
|
||||
- Many PRs are useful to demonstrate a need and a possible solution but aren't adequate for merging (causing other issues, not seeing other aspects of the big picture, etc.). In doubt, don't hesitate to push a PR because that is always the first step toward pointing toward a problem, and finding the mergeable solution! Even if a PR stays unmerged for a long time, its presence can be useful for other users and helps toward finding a general solution.
|
||||
- **When adding a feature,** please describe the usage context (how you intend to use it, why you need it, etc.). Be mindful of [The XY Problem](http://xyproblem.info/).
|
||||
- **When fixing a warning or compilation problem,** please post the compiler log and specify the compiler version and platform you are using.
|
||||
- **Attach screenshots (or GIF/video) to clarify the context and demonstrate the feature at a glance.** You can drag pictures/files in the message edit box. Prefer the long-term longevity of GitHub attachments over 3rd party hosting (you can drag pictures into your post).
|
||||
- **Make sure your code follows the coding style already used in the codebase:** 4 spaces indentations (no tabs), `local_variable`, `FunctionName()`, `MemberName`, `// Text Comment`, `//CodeComment();`, C-style casts, etc.. We don't use modern C++ idioms and tend to use only a minimum of C++11 features. The applications under examples/ are generally less consistent because they sometimes try to mimic the coding style often adopted by a certain ecosystem (e.g. DirectX-related code tend to use the style of their sample).
|
||||
- **Make sure you create a branch dedicated to the pull request**. In Git, 1 PR is associated to 1 branch. If you keep pushing to the same branch after you submitted the PR, your new commits will appear in the PR (we can still cherry-pick individual commits).
|
||||
|
||||
## Copyright / Contributor License Agreement
|
||||
|
||||
Any code you submit will become part of the repository and be distributed under the [Dear ImGui license](https://github.com/ocornut/imgui/blob/master/LICENSE.txt). By submitting code to the project you agree that the code is your work and that you can give it to the project.
|
||||
|
||||
You also agree by submitting your code that you grant all transferable rights to the code to the project maintainer, including for example re-licensing the code, modifying the code, and distributing it in source or binary forms. Specifically, this includes a requirement that you assign copyright to the project maintainer. For this reason, do not modify any copyright statements in files in any PRs.
|
||||
|
||||
223
docs/EXAMPLES.md
223
docs/EXAMPLES.md
@@ -3,76 +3,47 @@ _(You may browse this at https://github.com/ocornut/imgui/blob/master/docs/EXAMP
|
||||
## Dear ImGui: Examples
|
||||
|
||||
**The [examples/](https://github.com/ocornut/imgui/blob/master/examples) folder example applications (standalone, ready-to-build) for variety of
|
||||
platforms and graphics APIs.** They all use standard backends from the [backends/](https://github.com/ocornut/imgui/blob/master/backends) folder (see [BACKENDS.md](https://github.com/ocornut/imgui/blob/master/docs/BACKENDS.md)).
|
||||
platforms and graphics APIs.** They all use standard backends from the [backends/](https://github.com/ocornut/imgui/blob/master/backends) folder (see [docs/BACKENDS.md](https://github.com/ocornut/imgui/blob/master/docs/BACKENDS.md)).
|
||||
|
||||
The purpose of Examples is to showcase integration with backends, let you try Dear ImGui, and guide you toward
|
||||
integrating Dear ImGui in your own application/game/engine.
|
||||
**Once Dear ImGui is setup and running, run and refer to `ImGui::ShowDemoWindow()` in imgui_demo.cpp for usage of the end-user API.**
|
||||
|
||||
You can find Windows binaries for some of those example applications at:
|
||||
http://www.dearimgui.org/binaries
|
||||
https://www.dearimgui.com/binaries
|
||||
|
||||
|
||||
### Getting Started
|
||||
|
||||
Integration in a typical existing application, should take <20 lines when using standard backends.
|
||||
|
||||
At initialization:
|
||||
call ImGui::CreateContext()
|
||||
call ImGui_ImplXXXX_Init() for each backend.
|
||||
```cpp
|
||||
At initialization:
|
||||
call ImGui::CreateContext()
|
||||
call ImGui_ImplXXXX_Init() for each backend.
|
||||
|
||||
At the beginning of your frame:
|
||||
call ImGui_ImplXXXX_NewFrame() for each backend.
|
||||
call ImGui::NewFrame()
|
||||
At the beginning of your frame:
|
||||
call ImGui_ImplXXXX_NewFrame() for each backend.
|
||||
call ImGui::NewFrame()
|
||||
|
||||
At the end of your frame:
|
||||
call ImGui::Render()
|
||||
call ImGui_ImplXXXX_RenderDrawData() for your Renderer backend.
|
||||
At the end of your frame:
|
||||
call ImGui::Render()
|
||||
call ImGui_ImplXXXX_RenderDrawData() for your Renderer backend.
|
||||
|
||||
At shutdown:
|
||||
call ImGui_ImplXXXX_Shutdown() for each backend.
|
||||
call ImGui::DestroyContext()
|
||||
At shutdown:
|
||||
call ImGui_ImplXXXX_Shutdown() for each backend.
|
||||
call ImGui::DestroyContext()
|
||||
```
|
||||
|
||||
Example (using [backends/imgui_impl_win32.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_win32.cpp) + [backends/imgui_impl_dx11.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_dx11.cpp)):
|
||||
Main resource:
|
||||
- Read **[Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started) wiki guide** for detailed examples of how to integrate Dear ImGui in an existing application.
|
||||
|
||||
// Create a Dear ImGui context, setup some options
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable some options
|
||||
Additional resources:
|
||||
- Read FAQ at https://www.dearimgui.com/faq
|
||||
- Read 'PROGRAMMER GUIDE' section in imgui.cpp.
|
||||
- Read the comments and instruction at the top of each file.
|
||||
|
||||
// Initialize Platform + Renderer backends (here: using imgui_impl_win32.cpp + imgui_impl_dx11.cpp)
|
||||
ImGui_ImplWin32_Init(my_hwnd);
|
||||
ImGui_ImplDX11_Init(my_d3d_device, my_d3d_device_context);
|
||||
|
||||
// Application main loop
|
||||
while (true)
|
||||
{
|
||||
// Beginning of frame: update Renderer + Platform backend, start Dear ImGui frame
|
||||
ImGui_ImplDX11_NewFrame();
|
||||
ImGui_ImplWin32_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
// Any application code here
|
||||
ImGui::Text("Hello, world!");
|
||||
|
||||
// End of frame: render Dear ImGui
|
||||
ImGui::Render();
|
||||
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
|
||||
|
||||
// Swap
|
||||
g_pSwapChain->Present(1, 0);
|
||||
}
|
||||
|
||||
// Shutdown
|
||||
ImGui_ImplDX11_Shutdown();
|
||||
ImGui_ImplWin32_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
Please read 'PROGRAMMER GUIDE' in imgui.cpp for notes on how to setup Dear ImGui in your codebase.
|
||||
Please read the comments and instruction at the top of each file.
|
||||
Please read FAQ at http://www.dearimgui.org/faq
|
||||
|
||||
If you are using of the backend provided here, you can add the backends/imgui_impl_xxxx(.cpp,.h)
|
||||
If you are using any of the backends provided here, you can add the backends/imgui_impl_xxxx(.cpp,.h)
|
||||
files to your project and use as-in. Each imgui_impl_xxxx.cpp file comes with its own individual
|
||||
Changelog, so if you want to update them later it will be easier to catch up with what changed.
|
||||
|
||||
@@ -87,7 +58,7 @@ Allegro 5 example. <BR>
|
||||
Android + OpenGL3 (ES) example. <BR>
|
||||
= main.cpp + imgui_impl_android.cpp + imgui_impl_opengl3.cpp
|
||||
|
||||
[example_apple_metal/](https://github.com/ocornut/imgui/blob/master/examples/example_metal/) <BR>
|
||||
[example_apple_metal/](https://github.com/ocornut/imgui/tree/master/examples/example_apple_metal/) <BR>
|
||||
OSX & iOS + Metal example. <BR>
|
||||
= main.m + imgui_impl_osx.mm + imgui_impl_metal.mm <BR>
|
||||
It is based on the "cross-platform" game template provided with Xcode as of Xcode 9.
|
||||
@@ -100,15 +71,10 @@ OSX + OpenGL2 example. <BR>
|
||||
(NB: imgui_impl_osx.mm is currently not as feature complete as other platforms backends.
|
||||
You may prefer to use the GLFW Or SDL backends, which will also support Windows and Linux.)
|
||||
|
||||
[example_emscripten_opengl3/](https://github.com/ocornut/imgui/blob/master/examples/example_emscripten_opengl3/) <BR>
|
||||
Emcripten + SDL2 + OpenGL3+/ES2/ES3 example. <BR>
|
||||
= main.cpp + imgui_impl_sdl.cpp + imgui_impl_opengl3.cpp <BR>
|
||||
Note that other examples based on SDL or GLFW + OpenGL could easily be modified to work with Emscripten.
|
||||
We provide this to make the Emscripten differences obvious, and have them not pollute all other examples.
|
||||
|
||||
[example_emscripten_wgpu/](https://github.com/ocornut/imgui/blob/master/examples/example_emscripten_wgpu/) <BR>
|
||||
Emcripten + GLFW + WebGPU example. <BR>
|
||||
[example_glfw_wgpu/](https://github.com/ocornut/imgui/blob/master/examples/example_glfw_wgpu/) <BR>
|
||||
GLFW + WebGPU example. Supports Emscripten (web), Dawn (native), WGPU (native). <BR>
|
||||
= main.cpp + imgui_impl_glfw.cpp + imgui_impl_wgpu.cpp
|
||||
Note that the 'example_glfw_opengl3' and 'example_sdl2_opengl3' examples also supports Emscripten!
|
||||
|
||||
[example_glfw_metal/](https://github.com/ocornut/imgui/blob/master/examples/example_glfw_metal/) <BR>
|
||||
GLFW (Mac) + Metal example. <BR>
|
||||
@@ -117,21 +83,18 @@ GLFW (Mac) + Metal example. <BR>
|
||||
[example_glfw_opengl2/](https://github.com/ocornut/imgui/blob/master/examples/example_glfw_opengl2/) <BR>
|
||||
GLFW + OpenGL2 example (legacy, fixed pipeline). <BR>
|
||||
= main.cpp + imgui_impl_glfw.cpp + imgui_impl_opengl2.cpp <BR>
|
||||
**DO NOT USE OPENGL2 CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)** <BR>
|
||||
**Prefer using OPENGL3 code (with gl3w/glew/glad/glad2/glbinding, you can replace the OpenGL function loader)** <BR>
|
||||
**DO NOT USE THIS IF YOUR CODE/ENGINE IS USING MODERN GL or WEBGL (SHADERS, VBO, VAO, etc.)** <BR>
|
||||
This code is mostly provided as a reference to learn about Dear ImGui integration, because it is shorter.
|
||||
If your code is using GL3+ context or any semi modern OpenGL calls, using this renderer is likely to
|
||||
make things more complicated, will require your code to reset many OpenGL attributes to their initial
|
||||
If your code is using GL3+ context or any semi modern GL calls, using this renderer is likely to
|
||||
make things more complicated, will require your code to reset many GL attributes to their initial
|
||||
state, and might confuse your GPU driver. One star, not recommended.
|
||||
|
||||
[example_glfw_opengl3/](https://github.com/ocornut/imgui/blob/master/examples/example_glfw_opengl3/) <BR>
|
||||
GLFW (Win32, Mac, Linux) + OpenGL3+/ES2/ES3 example (programmable pipeline). <BR>
|
||||
GLFW (Win32, Mac, Linux) + OpenGL3+/ES2/ES3 example (modern, programmable pipeline). <BR>
|
||||
= main.cpp + imgui_impl_glfw.cpp + imgui_impl_opengl3.cpp <BR>
|
||||
This uses more modern OpenGL calls and custom shaders. <BR>
|
||||
Prefer using that if you are using modern OpenGL in your application (anything with shaders).
|
||||
(Please be mindful that accessing OpenGL3+ functions requires a function loader, which are a frequent
|
||||
source for confusion for new users. We use a loader in imgui_impl_opengl3.cpp which may be different
|
||||
from the one your app normally use. Read imgui_impl_opengl3.h for details and how to change it.)
|
||||
This uses more modern GL calls and custom shaders.<BR>
|
||||
This support building with Emscripten and targeting WebGL.<BR>
|
||||
Prefer using that if you are using modern GL or WebGL in your application.
|
||||
|
||||
[example_glfw_vulkan/](https://github.com/ocornut/imgui/blob/master/examples/example_glfw_vulkan/) <BR>
|
||||
GLFW (Win32, Mac, Linux) + Vulkan example. <BR>
|
||||
@@ -144,50 +107,88 @@ GLUT (e.g., FreeGLUT on Linux/Windows, GLUT framework on OSX) + OpenGL2 example.
|
||||
= main.cpp + imgui_impl_glut.cpp + imgui_impl_opengl2.cpp <BR>
|
||||
Note that GLUT/FreeGLUT is largely obsolete software, prefer using GLFW or SDL.
|
||||
|
||||
[example_marmalade/](https://github.com/ocornut/imgui/blob/master/examples/example_marmalade/) <BR>
|
||||
Marmalade example using IwGx. <BR>
|
||||
= main.cpp + imgui_impl_marmalade.cpp
|
||||
|
||||
[example_null/](https://github.com/ocornut/imgui/blob/master/examples/example_null/) <BR>
|
||||
Null example, compile and link imgui, create context, run headless with no inputs and no graphics output. <BR>
|
||||
= main.cpp <BR>
|
||||
= main.cpp + imgui_impl_null.cpp<BR>
|
||||
This is used to quickly test compilation of core imgui files in as many setups as possible.
|
||||
Because this application doesn't create a window nor a graphic context, there's no graphics output.
|
||||
Please note that imgui_impl_null itself is a rather empty backend. We provide it for consistency but
|
||||
it is similarly easy to create a skeleton application without the null backend.
|
||||
|
||||
[example_sdl_directx11/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl_directx11/) <BR>
|
||||
[example_sdl2_directx11/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl2_directx11/) <BR>
|
||||
SDL2 + DirectX11 example, Windows only. <BR>
|
||||
= main.cpp + imgui_impl_sdl.cpp + imgui_impl_dx11.cpp <BR>
|
||||
This to demonstrate usage of DirectX with SDL.
|
||||
= main.cpp + imgui_impl_sdl2.cpp + imgui_impl_dx11.cpp <BR>
|
||||
This to demonstrate usage of DirectX with SDL2.
|
||||
|
||||
[example_sdl_metal/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl_metal/) <BR>
|
||||
SDL2 (Mac) + Metal example. <BR>
|
||||
= main.mm + imgui_impl_sdl.cpp + imgui_impl_metal.mm
|
||||
[example_sdl2_metal/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl2_metal/) <BR>
|
||||
SDL2 + Metal example, Mac only. <BR>
|
||||
= main.mm + imgui_impl_sdl2.cpp + imgui_impl_metal.mm
|
||||
|
||||
[example_sdl_opengl2/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl_opengl2/) <BR>
|
||||
[example_sdl2_opengl2/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl2_opengl2/) <BR>
|
||||
SDL2 (Win32, Mac, Linux etc.) + OpenGL example (legacy, fixed pipeline). <BR>
|
||||
= main.cpp + imgui_impl_sdl.cpp + imgui_impl_opengl2.cpp <BR>
|
||||
**DO NOT USE OPENGL2 CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)** <BR>
|
||||
**Prefer using OPENGL3 code (with gl3w/glew/glad/glad2/glbinding, you can replace the OpenGL function loader)** <BR>
|
||||
= main.cpp + imgui_impl_sdl2.cpp + imgui_impl_opengl2.cpp <BR>
|
||||
**DO NOT USE OPENGL2 CODE IF YOUR CODE/ENGINE IS USING GL OR WEBGL (SHADERS, VBO, VAO, etc.)** <BR>
|
||||
This code is mostly provided as a reference to learn about Dear ImGui integration, because it is shorter.
|
||||
If your code is using GL3+ context or any semi modern OpenGL calls, using this renderer is likely to
|
||||
make things more complicated, will require your code to reset many OpenGL attributes to their initial
|
||||
If your code is using GL3+ context or any semi modern GL calls, using this renderer is likely to
|
||||
make things more complicated, will require your code to reset many GL attributes to their initial
|
||||
state, and might confuse your GPU driver. One star, not recommended.
|
||||
|
||||
[example_sdl_opengl3/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl_opengl3/) <BR>
|
||||
[example_sdl2_opengl3/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl2_opengl3/) <BR>
|
||||
SDL2 (Win32, Mac, Linux, etc.) + OpenGL3+/ES2/ES3 example. <BR>
|
||||
= main.cpp + imgui_impl_sdl.cpp + imgui_impl_opengl3.cpp <BR>
|
||||
This uses more modern OpenGL calls and custom shaders. <BR>
|
||||
Prefer using that if you are using modern OpenGL in your application (anything with shaders).
|
||||
(Please be mindful that accessing OpenGL3+ functions requires a function loader, which are a frequent
|
||||
source for confusion for new users. We use a loader in imgui_impl_opengl3.cpp which may be different
|
||||
from the one your app normally use. Read imgui_impl_opengl3.h for details and how to change it.)
|
||||
= main.cpp + imgui_impl_sdl2.cpp + imgui_impl_opengl3.cpp <BR>
|
||||
This uses more modern GL calls and custom shaders. <BR>
|
||||
This support building with Emscripten and targeting WebGL.<BR>
|
||||
Prefer using that if you are using modern GL or WebGL in your application.
|
||||
|
||||
[example_sdl_vulkan/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl_vulkan/) <BR>
|
||||
[example_sdl2_sdlrenderer2/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl2_sdlrenderer2/) <BR>
|
||||
SDL2 (Win32, Mac, Linux, etc.) + SDL_Renderer for SDL2 example.<BR>
|
||||
= main.cpp + imgui_impl_sdl2.cpp + imgui_impl_sdlrenderer2.cpp <BR>
|
||||
This requires SDL 2.0.18+ (released November 2021) <BR>
|
||||
|
||||
[example_sdl2_vulkan/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl2_vulkan/) <BR>
|
||||
SDL2 (Win32, Mac, Linux, etc.) + Vulkan example. <BR>
|
||||
= main.cpp + imgui_impl_sdl.cpp + imgui_impl_vulkan.cpp <BR>
|
||||
= main.cpp + imgui_impl_sdl2.cpp + imgui_impl_vulkan.cpp <BR>
|
||||
This is quite long and tedious, because: Vulkan. <BR>
|
||||
For this example, the main.cpp file exceptionally use helpers function from imgui_impl_vulkan.h/cpp.
|
||||
|
||||
[example_sdl2_wgpu/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl2_wgpu/) <BR>
|
||||
SDL2 + WebGPU example. Supports Emscripten (web), Dawn (native), WGPU (native). <BR>
|
||||
= main.cpp + imgui_impl_sdl2.cpp + imgui_impl_wgpu.cpp
|
||||
(note that the 'example_sdl2_opengl3' example also supports Emscripten!)
|
||||
|
||||
[example_sdl3_directx11/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_directx11/) <BR>
|
||||
SDL3 + DirectX11 examples, Windows only. <BR>
|
||||
= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_dx11.cpp <BR>
|
||||
|
||||
[example_sdl3_metal/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_metal/) <BR>
|
||||
SDL3 + Metal example, Mac only. <BR>
|
||||
= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_metal.mm <BR>
|
||||
|
||||
[example_sdl3_opengl3/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_opengl3/) <BR>
|
||||
SDL3 (Win32, Mac, Linux, etc.) + OpenGL3+/ES2/ES3 example. <BR>
|
||||
= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_opengl3.cpp <BR>
|
||||
This uses more modern GL calls and custom shaders. <BR>
|
||||
This support building with Emscripten and targeting WebGL.<BR>
|
||||
|
||||
[example_sdl3_sdlgpu3/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_sdlgpu3/) <BR>
|
||||
SDL3 (Win32, Mac, Linux, etc.) + SDL_GPU for SDL3 example.<BR>
|
||||
= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_sdlrenderer3.cpp <BR>
|
||||
|
||||
[example_sdl3_sdlrenderer3/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_sdlrenderer3/) <BR>
|
||||
SDL3 (Win32, Mac, Linux, etc.) + SDL_Renderer for SDL3 example.<BR>
|
||||
= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_sdlrenderer3.cpp <BR>
|
||||
|
||||
[example_sdl3_vulkan/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_vulkan/) <BR>
|
||||
SDL3 (Win32, Mac, Linux, etc.) + Vulkan example. <BR>
|
||||
= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_vulkan.cpp <BR>
|
||||
This is quite long and tedious, because: Vulkan. <BR>
|
||||
For this example, the main.cpp file exceptionally use helpers function from imgui_impl_vulkan.h/cpp.
|
||||
|
||||
[example_sdl3_wgpu/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_wgpu/) <BR>
|
||||
SDL3 + WebGPU example. Supports Emscripten (web), Dawn (native), WGPU (native). <BR>
|
||||
= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_wgpu.cpp
|
||||
(note that the 'example_sdl3_opengl3' example also supports Emscripten!)
|
||||
|
||||
[example_win32_directx9/](https://github.com/ocornut/imgui/blob/master/examples/example_win32_directx9/) <BR>
|
||||
DirectX9 example, Windows only. <BR>
|
||||
= main.cpp + imgui_impl_win32.cpp + imgui_impl_dx9.cpp
|
||||
@@ -205,12 +206,20 @@ DirectX12 example, Windows only. <BR>
|
||||
= main.cpp + imgui_impl_win32.cpp + imgui_impl_dx12.cpp <BR>
|
||||
This is quite long and tedious, because: DirectX12.
|
||||
|
||||
[example_win32_opengl3/](https://github.com/ocornut/imgui/blob/master/examples/example_win32_opengl3/) <BR>
|
||||
Raw Windows + OpenGL3 example (modern, programmable pipeline) <BR>
|
||||
= main.cpp + imgui_impl_win32.cpp + imgui_impl_opengl3.cpp <BR>
|
||||
|
||||
### Miscallaneous
|
||||
[example_win32_vulkan/](https://github.com/ocornut/imgui/blob/master/examples/example_win32_vulkan/) <BR>
|
||||
Raw Windows + Vulkan example <BR>
|
||||
= main.cpp + imgui_impl_win32.cpp + imgui_impl_vulkan.cpp <BR>
|
||||
|
||||
|
||||
### Miscellaneous
|
||||
|
||||
**Building**
|
||||
|
||||
Unfortunately nowadays it is still tedious to create and maintain portable build files using external
|
||||
Unfortunately, nowadays it is still tedious to create and maintain portable build files using external
|
||||
libraries (the kind we're using here to create a window and render 3D triangles) without relying on
|
||||
third party software and build systems. For most examples here we choose to provide:
|
||||
- Makefiles for Linux/OSX
|
||||
@@ -226,22 +235,22 @@ If you are interested in using Cmake to build and links examples, see:
|
||||
|
||||
**About mouse cursor latency**
|
||||
|
||||
Dear ImGui has no particular extra lag for most behaviors,
|
||||
e.g. the value of 'io.MousePos' provided at the time of NewFrame() will result in windows being moved
|
||||
Dear ImGui does not introduce significant extra lag for most behaviors,
|
||||
e.g. the last value passed to 'io.AddMousePosEvent()' before NewFrame() will result in windows being moved
|
||||
to the right spot at the time of EndFrame()/Render(). At 60 FPS your experience should be pleasant.
|
||||
|
||||
However, consider that OS mouse cursors are typically drawn through a very specific hardware accelerated
|
||||
path and will feel smoother than the majority of contents rendered via regular graphics API (including,
|
||||
However, consider that OS mouse cursors are typically rendered through a very specific hardware-accelerated
|
||||
path, which makes them feel smoother than the majority of content rendered via regular graphics API (including,
|
||||
but not limited to Dear ImGui windows). Because UI rendering and interaction happens on the same plane
|
||||
as the mouse, that disconnect may be jarring to particularly sensitive users.
|
||||
You may experiment with enabling the io.MouseDrawCursor flag to request Dear ImGui to draw a mouse cursor
|
||||
using the regular graphics API, to help you visualize the difference between a "hardware" cursor and a
|
||||
regularly rendered software cursor.
|
||||
However, rendering a mouse cursor at 60 FPS will feel sluggish so you likely won't want to enable that at
|
||||
However, rendering a mouse cursor at 60 FPS will feel sluggish, so you likely won't want to enable that at
|
||||
all times. It might be beneficial for the user experience to switch to a software rendered cursor _only_
|
||||
when an interactive drag is in progress.
|
||||
|
||||
Note that some setup or GPU drivers are likely to be causing extra display lag depending on their settings.
|
||||
If you feel that dragging windows feels laggy and you are not sure what the cause is: try to build a simple
|
||||
drawing a flat 2D shape directly under the mouse cursor!
|
||||
Note that some setup configurations or GPU drivers may introduce additional display lag depending on their settings.
|
||||
If you notice that dragging windows is laggy and you are not sure what the cause is: try drawing a simple
|
||||
2D shape directly under the mouse cursor to help identify the issue!
|
||||
|
||||
|
||||
608
docs/FAQ.md
608
docs/FAQ.md
@@ -1,7 +1,7 @@
|
||||
# FAQ (Frequenty Asked Questions)
|
||||
# FAQ (Frequently Asked Questions)
|
||||
|
||||
You may link to this document using short form:
|
||||
https://www.dearimgui.org/faq
|
||||
https://www.dearimgui.com/faq
|
||||
or its real address:
|
||||
https://github.com/ocornut/imgui/blob/master/docs/FAQ.md
|
||||
or view this file with any Markdown viewer.
|
||||
@@ -13,19 +13,22 @@ or view this file with any Markdown viewer.
|
||||
:---------------------------------------------------------- |
|
||||
| [Where is the documentation?](#q-where-is-the-documentation) |
|
||||
| [What is this library called?](#q-what-is-this-library-called) |
|
||||
| [What is the difference between Dear ImGui and traditional UI toolkits?](#q-what-is-the-difference-between-dear-imgui-and-traditional-ui-toolkits) |
|
||||
| [Which version should I get?](#q-which-version-should-i-get) |
|
||||
| **Q&A: Integration** |
|
||||
| **[How to get started?](#q-how-to-get-started)** |
|
||||
| **[How can I tell whether to dispatch mouse/keyboard to Dear ImGui or my application?](#q-how-can-i-tell-whether-to-dispatch-mousekeyboard-to-dear-imgui-or-my-application)** |
|
||||
| [How can I enable keyboard or gamepad controls?](#q-how-can-i-enable-keyboard-or-gamepad-controls) |
|
||||
| [How can I use this on a machine without mouse, keyboard or screen? (input share, remote display)](#q-how-can-i-use-this-on-a-machine-without-mouse-keyboard-or-screen-input-share-remote-display) |
|
||||
| [How can I create my own backend?](#q-how-can-i-create-my-own-backend)
|
||||
| [I integrated Dear ImGui in my engine and little squares are showing instead of text...](#q-i-integrated-dear-imgui-in-my-engine-and-little-squares-are-showing-instead-of-text) |
|
||||
| [I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around...](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-clipping-or-disappearing-when-i-move-windows-around) |
|
||||
| [I integrated Dear ImGui in my engine and some elements are displaying outside their expected windows boundaries...](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-displaying-outside-their-expected-windows-boundaries) |
|
||||
| **Q&A: Usage** |
|
||||
| **[Why is my widget not reacting when I click on it?<br>How can I have widgets with an empty label?<br>How can I have multiple widgets with the same label?](#q-why-is-my-widget-not-reacting-when-i-click-on-it)** |
|
||||
| [How can I display an image? What is ImTextureID, how does it work?](#q-how-can-i-display-an-image-what-is-imtextureid-how-does-it-work)|
|
||||
| [How can I use my own math types instead of ImVec2/ImVec4?](#q-how-can-i-use-my-own-math-types-instead-of-imvec2imvec4) |
|
||||
| **[About the ID Stack system...](#q-about-the-id-stack-system)**<br>**[How can I have multiple widgets with the same label?](#q-how-can-i-have-multiple-widgets-with-the-same-label) (using `##` or `PushID()`)**<br>**[How can I have widgets with an empty label?](#q-how-can-i-have-widgets-with-an-empty-label) (using `##`)**<br>**[How can I animate the label of an existing widget?](#q-how-can-i-change-the-label-of-an-existing-widget) (using `###`)**<br>**[General description of the label and ID Stack system.](#general-description-of-the-label-and-id-stack-system)** |
|
||||
| [How can I display an image?](#q-how-can-i-display-an-image)<br>[What are ImTextureID/ImTextureRef?](#q-what-are-imtextureidimtextureref)|
|
||||
| [How can I use maths operators with ImVec2?](#q-how-can-i-use-maths-operators-with-imvec2) |
|
||||
| [How can I use my own maths types instead of ImVec2/ImVec4?](#q-how-can-i-use-my-own-maths-types-instead-of-imvec2imvec4) |
|
||||
| [How can I interact with standard C++ types (such as std::string and std::vector)?](#q-how-can-i-interact-with-standard-c-types-such-as-stdstring-and-stdvector) |
|
||||
| [How can I display custom shapes? (using low-level ImDrawList API)](#q-how-can-i-display-custom-shapes-using-low-level-imdrawlist-api) |
|
||||
| **Q&A: Fonts, Text** |
|
||||
@@ -49,14 +52,16 @@ or view this file with any Markdown viewer.
|
||||
|
||||
**This library is poorly documented at the moment and expects the user to be acquainted with C/C++.**
|
||||
- The [Wiki](https://github.com/ocornut/imgui/wiki) is a hub to many resources and links.
|
||||
- Dozens of standalone example applications using e.g. OpenGL/DirectX are provided in the [examples/](https://github.com/ocornut/imgui/blob/master/examples/) folder to explain how to integrate Dear ImGui with your own engine/application. You can run those applications and explore them.
|
||||
- Handy [Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started) guide to integrate Dear ImGui in an existing application.
|
||||
- 20+ standalone example applications using e.g. OpenGL/DirectX are provided in the [examples/](https://github.com/ocornut/imgui/blob/master/examples/) folder to explain how to integrate Dear ImGui with your own engine/application. You can run those applications and explore them.
|
||||
- See demo code in [imgui_demo.cpp](https://github.com/ocornut/imgui/blob/master/imgui_demo.cpp) and particularly the `ImGui::ShowDemoWindow()` function. The demo covers most features of Dear ImGui, so you can read the code and see its output.
|
||||
- See pthom's online [imgui_explorer](https://pthom.github.io/imgui_explorer) which is a web version of the demo with a source code browser.
|
||||
- See documentation: [Backends](https://github.com/ocornut/imgui/blob/master/docs/BACKENDS.md), [Examples](https://github.com/ocornut/imgui/blob/master/docs/EXAMPLES.md), [Fonts](https://github.com/ocornut/imgui/blob/master/docs/FONTS.md).
|
||||
- See documentation and comments at the top of [imgui.cpp](https://github.com/ocornut/imgui/blob/master/imgui.cpp) + general API comments in [imgui.h](https://github.com/ocornut/imgui/blob/master/imgui.h).
|
||||
- The [Glossary](https://github.com/ocornut/imgui/wiki/Glossary) page may be useful.
|
||||
- The [Issues](https://github.com/ocornut/imgui/issues) and [Discussions](https://github.com/ocornut/imgui/discussions) sections can be searched for past questions and issues.
|
||||
- Your programming IDE is your friend, find the type or function declaration to find comments associated with it.
|
||||
- The `ImGui::ShowMetricsWindow()` function exposes lots of internal information and tools. Although it is primary designed as a debugging tool, having access to that information tends to help understands concepts.
|
||||
- The `ImGui::ShowMetricsWindow()` function exposes lots of internal information and tools. Although it is primarily designed as a debugging tool, having access to that information tends to help understands concepts.
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
@@ -66,7 +71,61 @@ or view this file with any Markdown viewer.
|
||||
|
||||
**This library is called Dear ImGui**. Please refer to it as Dear ImGui (not ImGui, not IMGUI).
|
||||
|
||||
(The library misleadingly started its life in 2014 as "ImGui" due to the fact that I didn't give it a proper name when when I released 1.0, and had no particular expectation that it would take off. However, the term IMGUI (immediate-mode graphical user interface) was coined before and is being used in variety of other situations e.g. Unity uses it own implementation of the IMGUI paradigm. To reduce the ambiguity without affecting existing code bases, I have decided in December 2015 a fully qualified name "Dear ImGui" for this library.
|
||||
(The library misleadingly started its life in 2014 as "ImGui" due to the fact that I didn't give it a proper name when I released 1.0, and had no particular expectation that it would take off. However, the term IMGUI (immediate-mode graphical user interface) was coined before and is being used in variety of other situations e.g. Unity uses it own implementation of the IMGUI paradigm. To reduce the ambiguity without affecting existing code bases, I have decided in December 2015 a fully qualified name "Dear ImGui" for this library.
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
---
|
||||
|
||||
### Q: What is the difference between Dear ImGui and traditional UI toolkits?
|
||||
|
||||
Here's a very simplified comparison between the approach taken by Dear ImGui vs traditional toolkits:
|
||||
|
||||
| Dear ImGui | Qt/GTK/WPF... |
|
||||
|--------------------------|--------------------------|
|
||||
| UI fully issued on every update. | UI issued once then later modified. |
|
||||
| UI layout is fully dynamic and can change at any time.<BR>UI is generally emitted programmatically, which empowers reflecting a dynamic set of data. | UI layout is mostly static.<BR>UI may be emitted programmatically or from data created by offline tools. UI need extra code to evolve, which is often tedious and error-prone if it needs to be reflecting dynamic data and systems. |
|
||||
| Application can submit UI based on arbitrary logic and then forget about it. | Application needs more bookkeeping of UI elements. |
|
||||
| UI library stores minimal amounts of data. At one point in time, it typically doesn't know or remember which other widgets are displayed and which widgets are coming next. As a result, certain layout features (alignment, resizing) are not as easy to implement or require ad-hoc code. | UI library stores entire widgets tree and state. UI library can use this retained data to easily layout things. |
|
||||
| UI code may be added anywhere.<BR>You can even create UI to edit a local variable! | UI code needs to be added in dedicated spots. |
|
||||
| UI layout/logic/action/data bindings are all nearby in the code. | UI layout/logic/action/data bindings in distinct functions, files or formats. |
|
||||
| Data is naturally always synchronized. | Use callback/signal/slot for synchronizing data (error-prone). |
|
||||
| API is simple and easy to learn. In particular, doing basic things is very easy. | API is more complex and specialized. |
|
||||
| API is low-level (raw language types). | API are higher-level (more abstractions, advanced language features). |
|
||||
| Less fancy look and feel. | Standard look and feel. |
|
||||
| Compile yourself. Easy to debug, hack, modify, study. | Mostly use precompiled libraries. Compiling, modifying or studying is daunting if not impossible. |
|
||||
| Run on every platform. | Run on limited desktop platforms. |
|
||||
|
||||
Idiomatic Dear ImGui code:
|
||||
```cpp
|
||||
if (ImGui::Button("Save"))
|
||||
MySaveFunction();
|
||||
|
||||
ImGui::SliderFloat("Slider", &m_MyValue, 0.0f, 1.0f);
|
||||
```
|
||||
Idiomatic code with traditional toolkit:
|
||||
```cpp
|
||||
UiButton* button = new UiButton("Save");
|
||||
button->OnClick = &MySaveFunction;
|
||||
parent->Add(button);
|
||||
|
||||
UiSlider* slider = new UiSlider("Slider");
|
||||
slider->SetRange(0.0f, 1.0f);
|
||||
slider->BindData<float>(&m_MyValue);
|
||||
parent->Add(slider);
|
||||
```
|
||||
This is only meant to give you a intuitive feeling of the main differences, but pros & cons go deeper than that.
|
||||
|
||||
Some of those properties are typically associated to the umbrella term "IMGUI", but the term has no simple and well-agreed definition. There are many erroneous statements and misunderstandings with what IMGUI means. It is partly caused by the fact that most popular IMGUI implementations (including Dear ImGui) have originated from game industry needs and have targeted specific use cases, causing people to conflate IMGUI properties with what a specific library does. However, it is perfectly possible to implement an IMGUI library that would have very different properties than e.g. Dear ImGui. My take on defining what an IMGUI is:
|
||||
|
||||
**IMGUI refers to the API: literally the interface between the application and the UI system.**
|
||||
- An IMGUI API favors the application code owning its data and being the single source of truth for it.
|
||||
- An IMGUI API tries to minimize the application having to retain/manage data related to the UI system.
|
||||
- An IMGUI API tries to minimize the UI system having to retain/manage data related to the application.
|
||||
- Synchronization between application data and UI data is natural and less error-prone.
|
||||
|
||||
**IMGUI does NOT refer to the implementation. Whatever happens inside the UI library code doesn't matter.**
|
||||
<BR>Also see: [Links to many articles about the IMGUI paradigm](https://github.com/ocornut/imgui/wiki/#about-the-imgui-paradigm).
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
@@ -75,9 +134,9 @@ or view this file with any Markdown viewer.
|
||||
### Q: Which version should I get?
|
||||
I occasionally tag [Releases](https://github.com/ocornut/imgui/releases) but it is generally safe and recommended to sync to master/latest. The library is fairly stable and regressions tend to be fixed fast when reported.
|
||||
|
||||
You may use the [docking](https://github.com/ocornut/imgui/tree/docking) branch which includes:
|
||||
- [Docking features](https://github.com/ocornut/imgui/issues/2109)
|
||||
- [Multi-viewport features](https://github.com/ocornut/imgui/issues/1542)
|
||||
You may use the ['docking'](https://github.com/ocornut/imgui/tree/docking) branch which includes:
|
||||
- [Docking features](https://github.com/ocornut/imgui/wiki/Docking)
|
||||
- [Multi-viewport features](https://github.com/ocornut/imgui/wiki/Multi-Viewports)
|
||||
|
||||
Many projects are using this branch and it is kept in sync with master regularly.
|
||||
|
||||
@@ -89,11 +148,14 @@ Many projects are using this branch and it is kept in sync with master regularly
|
||||
|
||||
### Q: How to get started?
|
||||
|
||||
Read [EXAMPLES.md](https://github.com/ocornut/imgui/blob/master/docs/EXAMPLES.md). <BR>
|
||||
Read [BACKENDS.md](https://github.com/ocornut/imgui/blob/master/docs/BACKENDS.md). <BR>
|
||||
Read [Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started). <BR>
|
||||
Read [docs/EXAMPLES.md](https://github.com/ocornut/imgui/blob/master/docs/EXAMPLES.md). <BR>
|
||||
Read [docs/BACKENDS.md](https://github.com/ocornut/imgui/blob/master/docs/BACKENDS.md). <BR>
|
||||
Read `PROGRAMMER GUIDE` section of [imgui.cpp](https://github.com/ocornut/imgui/blob/master/imgui.cpp). <BR>
|
||||
The [Wiki](https://github.com/ocornut/imgui/wiki) is a hub to many resources and links.
|
||||
|
||||
For first-time users having issues compiling/linking/running or issues loading fonts, please use [GitHub Discussions](https://github.com/ocornut/imgui/discussions).
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
---
|
||||
@@ -112,7 +174,7 @@ void MyLowLevelMouseButtonHandler(int button, bool down)
|
||||
{
|
||||
// (1) ALWAYS forward mouse data to ImGui! This is automatic with default backends. With your own backend:
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.MouseDown[button] = down;
|
||||
io.AddMouseButtonEvent(button, down);
|
||||
|
||||
// (2) ONLY forward mouse data to your underlying app/game.
|
||||
if (!io.WantCaptureMouse)
|
||||
@@ -120,12 +182,7 @@ void MyLowLevelMouseButtonHandler(int button, bool down)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
**Note:** The `io.WantCaptureMouse` is more correct that any manual attempt to "check if the mouse is hovering a window" (don't do that!). It handle mouse dragging correctly (both dragging that started over your application or over a Dear ImGui window) and handle e.g. popup and modal windows blocking inputs.
|
||||
|
||||
**Note:** Those flags are updated by `ImGui::NewFrame()`. However it is generally more correct and easier that you poll flags from the previous frame, then submit your inputs, then call `NewFrame()`. If you attempt to do the opposite (which is generally harder) you are likely going to submit your inputs after `NewFrame()`, and therefore too late.
|
||||
|
||||
**Note:** If you are using a touch device, you may find use for an early call to `UpdateHoveredWindowAndCaptureFlags()` to correctly dispatch your initial touch. We will work on better out-of-the-box touch support in the future.
|
||||
**Note:** The `io.WantCaptureMouse` is more correct that any manual attempt to "check if the mouse is hovering a window" (don't do that!). It handles mouse dragging correctly (both dragging that started over your application or over a Dear ImGui window) and handle e.g. popup and modal windows blocking inputs.
|
||||
|
||||
**Note:** Text input widget releases focus on the "KeyDown" event of the Return key, so the subsequent "KeyUp" event that your application receive will typically have `io.WantCaptureKeyboard == false`. Depending on your application logic it may or not be inconvenient to receive that KeyUp event. You might want to track which key-downs were targeted for Dear ImGui, e.g. with an array of bool, and filter out the corresponding key-ups.)
|
||||
|
||||
@@ -137,7 +194,7 @@ void MyLowLevelMouseButtonHandler(int button, bool down)
|
||||
- The gamepad/keyboard navigation is fairly functional and keeps being improved. The initial focus was to support game controllers, but keyboard is becoming increasingly and decently usable. Gamepad support is particularly useful to use Dear ImGui on a game console (e.g. PS4, Switch, XB1) without a mouse connected!
|
||||
- Keyboard: set `io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard` to enable.
|
||||
- Gamepad: set `io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad` to enable (with a supporting backend).
|
||||
- See [Control Sheets for Gamepads](http://www.dearimgui.org/controls_sheets) (reference PNG/PSD for for PS4, XB1, Switch gamepads).
|
||||
- See [Control Sheets for Gamepads](https://www.dearimgui.com/controls_sheets) (reference PNG/PSD for PS4, XB1, Switch gamepads).
|
||||
- See `USING GAMEPAD/KEYBOARD NAVIGATION CONTROLS` section of [imgui.cpp](https://github.com/ocornut/imgui/blob/master/imgui.cpp) for more details.
|
||||
|
||||
##### [Return to Index](#index)
|
||||
@@ -159,9 +216,19 @@ Console SDK also sometimes provide equivalent tooling or wrapper for Synergy-lik
|
||||
|
||||
---
|
||||
|
||||
### Q: How can I create my own backend?
|
||||
- See [docs/BACKENDS.md](https://github.com/ocornut/imgui/blob/master/docs/BACKENDS.md).
|
||||
- See Documentation at the top of imgui.cpp.
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
---
|
||||
|
||||
### Q: I integrated Dear ImGui in my engine and little squares are showing instead of text...
|
||||
This usually means that: your font texture wasn't uploaded into GPU, or your shader or other rendering state are not reading from the right texture (e.g. texture wasn't bound).
|
||||
If this happens using the standard backends it is probably that the texture failed to upload, which could happens if for some reason your texture is too big. Also see [docs/FONTS.md](https://github.com/ocornut/imgui/blob/master/docs/FONTS.md).
|
||||
Your renderer backend is not using the font texture correctly or it hasn't been uploaded to the GPU.
|
||||
- If this happens using standard backends (before 1.92): A) have you modified the font atlas after `ImGui_ImplXXX_NewFrame()`? B) maybe the texture failed to upload, which **can if your texture atlas is too big**. Also see [docs/FONTS.md](https://github.com/ocornut/imgui/blob/master/docs/FONTS.md).
|
||||
- If this happens using standard backends (after 1.92): please report.
|
||||
- If this happens with a custom backend: make sure you have uploaded the font texture to the GPU, that all shaders are rendering states are setup properly (e.g. texture is bound). Compare your code to existing backends and use a graphics debugger such as [RenderDoc](https://renderdoc.org) to debug your rendering states.
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
@@ -174,8 +241,21 @@ Each draw command needs the triangle rendered using the clipping rectangle provi
|
||||
Rectangles provided by Dear ImGui are defined as
|
||||
`(x1=left,y1=top,x2=right,y2=bottom)`
|
||||
and **NOT** as
|
||||
`(x1,y1,width,height)`
|
||||
Refer to rendering backends in the [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder for references of how to handle the `ClipRect` field.
|
||||
`(x1,y1,width,height)`.
|
||||
Refer to rendering backends in the [backends/](https://github.com/ocornut/imgui/tree/master/backends) folder for references of how to handle the `ClipRect` field.
|
||||
For example, the [DirectX11 backend](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_dx11.cpp) does this:
|
||||
```cpp
|
||||
// Project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_off = draw_data->DisplayPos;
|
||||
ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y);
|
||||
ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y);
|
||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||
continue;
|
||||
|
||||
// Apply scissor/clipping rectangle
|
||||
const D3D11_RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y };
|
||||
ctx->RSSetScissorRects(1, &r);
|
||||
```
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
@@ -183,17 +263,144 @@ Refer to rendering backends in the [examples/](https://github.com/ocornut/imgui/
|
||||
|
||||
# Q&A: Usage
|
||||
|
||||
### Q: Why is my widget not reacting when I click on it?
|
||||
### Q: How can I have widgets with an empty label?
|
||||
## Q: About the ID Stack system...
|
||||
|
||||
**USING THE SAME LABEL+ID IS THE MOST COMMON USER MISTAKE!**
|
||||
<br>**USING AN EMPTY LABEL IS THE SAME AS USING THE SAME LABEL AS YOUR PARENT WIDGET!**
|
||||
<br>Read the questions in this section for a more general understand of how labels and ID works in Dear ImGui.
|
||||
|
||||
TL;DR;
|
||||
- Widgets labels are also used to compute Widgets unique identifiers.
|
||||
- Unique identifiers are hashes of the label + of the parent scope (e.g. parent window or parent tree node labels).
|
||||
- You can use `PushID()` to append to the identifier without making it visible.
|
||||
- You can use `"##something"` in a label to append to the identifier without making it visible.
|
||||
- You can use `"###something"` in a label to make the identifier ignore the visible part.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td><img src="https://github.com/user-attachments/assets/776a8315-1164-4178-9a8c-df52e0ff28aa"></td>
|
||||
<td>
|
||||
<pre lang="cpp">
|
||||
ImGui::Begin("Incorrect!");
|
||||
ImGui::DragFloat2("My value", &objects[0]->pos.x);
|
||||
ImGui::DragFloat2("My value", &objects[1]->pos.x);
|
||||
ImGui::DragFloat2("My value", &objects[2]->pos.x);
|
||||
ImGui::End();
|
||||
|
||||
ImGui::Begin("Correct!");
|
||||
ImGui::DragFloat2("My value", &objects[0]->pos.x);
|
||||
ImGui::DragFloat2("My value##2", &objects[1]->pos.x);
|
||||
ImGui::DragFloat2("My value##3", &objects[2]->pos.x);
|
||||
ImGui::End();
|
||||
|
||||
ImGui::Begin("Also Correct!");
|
||||
for (int n = 0; n < 3; n++)
|
||||
{
|
||||
ImGui::PushID(n);
|
||||
ImGui::DragFloat2("My value", &objects[n]->pos.x);
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::End();
|
||||
</pre>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
### Q: How can I have multiple widgets with the same label?
|
||||
|
||||
A primer on labels and the ID Stack...
|
||||
A. When widgets are in a same scope and finite, you can use a `"##something"` suffix which will be part of the identifier but not visible as a label.
|
||||
|
||||
Dear ImGui internally need to uniquely identify UI elements.
|
||||
Elements that are typically not clickable (such as calls to the Text functions) don't need an ID.
|
||||
Interactive widgets (such as calls to Button buttons) need a unique ID.
|
||||
Unique ID are used internally to track active widgets and occasionally associate state to widgets.
|
||||
Unique ID are implicitly built from the hash of multiple elements that identify the "path" to the UI element.
|
||||
```cpp
|
||||
Button("Play"); // Label = "Play", ID = hash of ("MyWindow", "Play")
|
||||
Button("Play##foo1"); // Label = "Play", ID = hash of ("MyWindow", "Play##foo1") // Different from other buttons
|
||||
Button("Play##foo2"); // Label = "Play", ID = hash of ("MyWindow", "Play##foo2") // Different from other buttons
|
||||
```
|
||||
|
||||
B. More generally, e.g. in loops, you can use `PushID()/PopID()` to push a prefix which will be part of the identifier.
|
||||
|
||||
```cpp
|
||||
// Using PushID() with a string
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
MyObject* obj = Objects[i];
|
||||
PushID(obj->Name);
|
||||
Button("Click"); // Label = "Click", ID = hash of ("Window", obj->Name, "Click")
|
||||
PopID();
|
||||
}
|
||||
```
|
||||
|
||||
```cpp
|
||||
// Using PushID() with an index
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
PushID(i);
|
||||
Button("Click"); // Label = "Click", ID = hash of ("Window", i, "Click")
|
||||
PopID();
|
||||
}
|
||||
```
|
||||
|
||||
### Q: How can I have widgets with an empty label?
|
||||
|
||||
If you want to completely hide the label, but still need an ID:
|
||||
|
||||
```cpp
|
||||
Checkbox("##On", &b); // Label = "", ID = hash of (..., "##On") // No visible label, just a checkbox!
|
||||
```
|
||||
##### [Return to Index](#index)
|
||||
|
||||
### Q: How can I make a label dynamic?
|
||||
|
||||
Dear ImGui is very dynamic so you can submit different widgets every frame.
|
||||
However, in order to preserve widget state (eg. which tree node is open; which button is focused) the library internaly refers to their unique ID.
|
||||
|
||||
Occasionally you might want to change a label while preserving a constant ID. This allows you to change/animate labels while persisting associated state.
|
||||
For example, you may want to include varying information in a window title bar or button label.
|
||||
|
||||
Using "###" exclude the preceeding part from ID computation:
|
||||
```cpp
|
||||
Button("Hello###ID"); // Label = "Enable", ID = hash of (..., "ID")
|
||||
Button("World###ID"); // Label = "Disable", ID = hash of (..., "ID") // Same ID, different label
|
||||
```
|
||||
Using a same ID ensure that associated related e.g. weither the widget is focused, won't be lost when the label changes.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td><img src="https://github.com/user-attachments/assets/2bf18756-e122-498d-bbd4-5c44bb1018d5"></td>
|
||||
<td>
|
||||
<pre lang="cpp">
|
||||
// Window label has animating FPS counter
|
||||
// Window ID stays the same = hash of "MyGame"
|
||||
char buf[128];
|
||||
sprintf(buf, "My game (%.1f FPS)###MyGame", io.Framerate);
|
||||
ImGui::Begin(buf);
|
||||
|
||||
// Label changes between "Enable" and "Disable"
|
||||
// ID stays the same = hash of ("MyGame", "MyButton")
|
||||
if (ImGui::Button(enabled ? "Disable###MyButton" : "Enable###MyButton", { -FLT_MIN, 0.0f }))
|
||||
enabled = !enabled;
|
||||
|
||||
ImGui::End();
|
||||
</pre>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
(Hint: I'd suggest wrapping sprintf in something more compact to use, e.g. [ocornut/Str](https://github.com/ocornut/Str) for what I personally use).
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
### General description of the label and ID Stack system
|
||||
|
||||
Dear ImGui internally needs to uniquely identify UI elements.
|
||||
Elements that are typically not clickable (such as calls to Text() functions) don't need an ID.
|
||||
Interactive widgets (such as calls to Button() functions) need a unique ID.
|
||||
|
||||
**Unique IDs are used internally to track active widgets and occasionally associate state to widgets.<BR>
|
||||
Unique IDs are implicitly built from the hash of multiple elements that identify the "path" to the UI element.**
|
||||
|
||||
You can use `Demo>Tools>ID Stack Tool` or call `ImGui::ShowIDStackToolWindow()`. The tool display intermediate values leading to the creation of a unique ID, making things easier to debug and understand.
|
||||
|
||||

|
||||
|
||||
- Unique ID are often derived from a string label and at minimum scoped within their host window:
|
||||
```cpp
|
||||
@@ -224,44 +431,35 @@ End();
|
||||
|
||||
- If you have a same ID twice in the same location, you'll have a conflict:
|
||||
```cpp
|
||||
Begin("MyWindow");
|
||||
Button("OK");
|
||||
Button("OK"); // ID collision! Interacting with either button will trigger the first one.
|
||||
Button("OK"); // ERROR: ID collision with the first button! Interacting with either button will trigger the first one.
|
||||
Button(""); // ERROR: ID collision with Begin("MyWindow")!
|
||||
End();
|
||||
```
|
||||
Fear not! this is easy to solve and there are many ways to solve it!
|
||||
Fear not! This is easy to solve and there are many ways to solve it!
|
||||
|
||||
- Solving ID conflict in a simple/local context:
|
||||
When passing a label you can optionally specify extra ID information within string itself.
|
||||
When passing a label you can optionally specify extra ID information within the string itself.
|
||||
Use "##" to pass a complement to the ID that won't be visible to the end-user.
|
||||
This helps solving the simple collision cases when you know e.g. at compilation time which items
|
||||
This helps solve the simple collision cases when you know e.g. at compilation time which items
|
||||
are going to be created:
|
||||
```cpp
|
||||
Begin("MyWindow");
|
||||
Button("Play"); // Label = "Play", ID = hash of ("MyWindow", "Play")
|
||||
Button("Play##foo1"); // Label = "Play", ID = hash of ("MyWindow", "Play##foo1") // Different from above
|
||||
Button("Play##foo2"); // Label = "Play", ID = hash of ("MyWindow", "Play##foo2") // Different from above
|
||||
Button("Play##foo1"); // Label = "Play", ID = hash of ("MyWindow", "Play##foo1") // Different from other buttons
|
||||
Button("Play##foo2"); // Label = "Play", ID = hash of ("MyWindow", "Play##foo2") // Different from other buttons
|
||||
Button("##foo"); // Label = "", ID = hash of ("MyWindow", "##foo") // Different from window
|
||||
End();
|
||||
```
|
||||
- If you want to completely hide the label, but still need an ID:
|
||||
```cpp
|
||||
Checkbox("##On", &b); // Label = "", ID = hash of (..., "##On") // No visible label, just a checkbox!
|
||||
```
|
||||
- Occasionally/rarely you might want change a label while preserving a constant ID. This allows
|
||||
you to animate labels. For example you may want to include varying information in a window title bar,
|
||||
but windows are uniquely identified by their ID. Use "###" to pass a label that isn't part of ID:
|
||||
```cpp
|
||||
Button("Hello###ID"); // Label = "Hello", ID = hash of (..., "###ID")
|
||||
Button("World###ID"); // Label = "World", ID = hash of (..., "###ID") // Same ID, different label
|
||||
|
||||
sprintf(buf, "My game (%f FPS)###MyGame", fps);
|
||||
Begin(buf); // Variable title, ID = hash of "MyGame"
|
||||
```
|
||||
- Solving ID conflict in a more general manner:
|
||||
Use PushID() / PopID() to create scopes and manipulate the ID stack, as to avoid ID conflicts
|
||||
Use `PushID()` / `PopID()` to create scopes and manipulate the ID stack, as to avoid ID conflicts
|
||||
within the same window. This is the most convenient way of distinguishing ID when iterating and
|
||||
creating many UI elements programmatically.
|
||||
You can push a pointer, a string or an integer value into the ID stack.
|
||||
Remember that ID are formed from the concatenation of _everything_ pushed into the ID stack.
|
||||
At each level of the stack we store the seed used for items at this level of the ID stack.
|
||||
You can push a pointer, a string, or an integer value into the ID stack.
|
||||
Remember that IDs are formed from the concatenation of _everything_ pushed into the ID stack.
|
||||
At each level of the stack, we store the seed used for items at this level of the ID stack.
|
||||
```cpp
|
||||
Begin("Window");
|
||||
for (int i = 0; i < 100; i++)
|
||||
@@ -296,7 +494,7 @@ PushID("node");
|
||||
PopID();
|
||||
PopID();
|
||||
```
|
||||
- Tree nodes implicitly creates a scope for you by calling PushID().
|
||||
- Tree nodes implicitly create a scope for you by calling `PushID()`:
|
||||
```cpp
|
||||
Button("Click"); // Label = "Click", ID = hash of (..., "Click")
|
||||
if (TreeNode("node")) // <-- this function call will do a PushID() for you (unless instructed not to, with a special flag)
|
||||
@@ -306,8 +504,8 @@ if (TreeNode("node")) // <-- this function call will do a PushID() for you (unl
|
||||
}
|
||||
```
|
||||
|
||||
When working with trees, ID are used to preserve the open/close state of each tree node.
|
||||
Depending on your use cases you may want to use strings, indices or pointers as ID.
|
||||
When working with trees, IDs are used to preserve the open/close state of each tree node.
|
||||
Depending on your use cases you may want to use strings, indices, or pointers as ID.
|
||||
- e.g. when following a single pointer that may change over time, using a static string as ID
|
||||
will preserve your node open/closed state when the targeted object change.
|
||||
- e.g. when displaying a list of objects, using indices or pointers as ID will preserve the
|
||||
@@ -317,81 +515,132 @@ node open/closed state differently. See what makes more sense in your situation!
|
||||
|
||||
---
|
||||
|
||||
### Q: How can I display an image? What is ImTextureID, how does it work?
|
||||
### Q: How can I display an image?
|
||||
### Q: What are ImTextureID/ImTextureRef?
|
||||
|
||||
Short explanation:
|
||||
- Refer to [Image Loading and Displaying Examples](https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples) on the [Wiki](https://github.com/ocornut/imgui/wiki).
|
||||
**Short explanation:**
|
||||
- You may use functions such as `ImGui::Image()`, `ImGui::ImageButton()` or lower-level `ImDrawList::AddImage()` to emit draw calls that will use your own textures.
|
||||
- Actual textures are identified in a way that is up to the user/engine. Those identifiers are stored and passed as ImTextureID (void*) value.
|
||||
- Loading image files from the disk and turning them into a texture is not within the scope of Dear ImGui (for a good reason).
|
||||
- To load and display your own textures, refer to [Image Loading and Displaying Examples](https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples) on the [Wiki](https://github.com/ocornut/imgui/wiki).
|
||||
- Actual textures are identified in a way that is up to the user/engine. Those identifiers are stored and passed as an opaque ImTextureID value.
|
||||
- By default ImTextureID can store up to 64-bits. You may `#define` it to a custom type/structure if you need.
|
||||
- Loading image files from the disk and turning them into a texture is not within the scope of Dear ImGui (for a good reason), but the examples linked above may be useful references.
|
||||
|
||||
**Details:**
|
||||
|
||||
1.92 introduced `ImTextureRef` in June 2025.
|
||||
- All drawing functions using `ImTextureID` were changed to use `ImTextureRef`.
|
||||
- You can trivially create a `ImTextureRef` from a `ImTextureID`.
|
||||
- **If you use Image functions with textures that you have loaded/created yourself, you will mostly likely only ever store/manipulate `ImTextureID` and then pass them as `ImTextureRef`.**
|
||||
- You only NEED to manipulate `ImTextureRef` when dealing with textures managed by the backend itself, aka mainly the atlas texture for now.
|
||||
- We intentionally do not provide an implicit `ImTextureRef` -> `ImTextureID` cast operator because it is technically lossy to convert ImTextureRef to ImTextureID before rendering.
|
||||
|
||||
**ImTextureID = backend specific, low-level identifier for a texture uploaded in GPU/graphics system.**
|
||||
```cpp
|
||||
#ifndef ImTextureID
|
||||
typedef ImU64 ImTextureID; // Default: store up to 64-bits (any pointer or integer). A majority of backends are ok with that.
|
||||
#endif
|
||||
```
|
||||
- When a Rendered Backend creates a texture, it store its native identifier into a ImTextureID value (e.g. Used by DX11 backend to a `ID3D11ShaderResourceView*`; Used by OpenGL backends to store `GLuint`; Used by SDLGPU backend to store a `SDL_GPUTextureSamplerBinding*`, etc.).
|
||||
- User may submit their own textures to e.g. `ImGui::Image()` function by passing this value.
|
||||
- During the rendering loop, the Renderer Backend retrieve the ImTextureID, which stored inside a ImTextureRef, which is stored inside ImDrawCmd.
|
||||
- Compile-time type configuration:
|
||||
- To use something other than a 64-bit value: add '#define ImTextureID MyTextureType*' in your imconfig.h file.
|
||||
- This can be whatever to you want it to be! read the FAQ entry about textures for details.
|
||||
- You may decide to store a higher-level structure containing texture, sampler, shader etc. with various constructors if you like. You will need to implement ==/!= operators.
|
||||
|
||||
**ImTextureRef = higher-level identifier for a texture.**
|
||||
```cpp
|
||||
// Store a ImTextureID _or_ a ImTextureData*.
|
||||
struct ImTextureRef
|
||||
{
|
||||
ImTextureRef() { _TexData = NULL; _TexID = ImTextureID_Invalid; }
|
||||
ImTextureRef(ImTextureID tex_id) { _TexData = NULL; _TexID = tex_id; }
|
||||
inline ImTextureID GetTexID() const { return _TexData ? _TexData->TexID : _TexID; }
|
||||
|
||||
// Members (either are set, never both!)
|
||||
ImTextureData* _TexData; // A texture, generally owned by a ImFontAtlas. Will convert to ImTextureID during render loop, after texture has been uploaded.
|
||||
ImTextureID _TexID; // _OR_ Low-level backend texture identifier, if already uploaded or created by user/app. Generally provided to e.g. ImGui::Image() calls.
|
||||
};
|
||||
```
|
||||
- The identifier is valid even before the texture has been uploaded to the GPU/graphics system.
|
||||
- This is what gets passed to functions such as `ImGui::Image()`, `ImDrawList::AddImage()`.
|
||||
- This is what gets stored in draw commands (`ImDrawCmd`) to identify a texture during rendering.
|
||||
- When a texture is created by user code (e.g. custom images), we directly store the low-level `ImTextureID`.
|
||||
- Because of this, when displaying your own texture you are likely to ever only manage ImTextureID values on your side.
|
||||
- When a texture is created by the backend, we store a `ImTextureData*` which becomes an indirection to extract the `ImTextureID` value during rendering, after texture upload has happened.
|
||||
- To create a `ImTextureRef` from a `ImTextureData*` you can use `ImTextureData::GetTexRef()`.
|
||||
We intentionally do not provide an `ImTextureRef` constructor for this: we don't expect this to be frequently useful to the end-user, and it would be erroneously called by many legacy code.
|
||||
- There is no constructor to create a `ImTextureRef` from a `ImTextureData*` as we don't expect this to be useful to the end-user, and it would be erroneously called by many legacy code.
|
||||
- If you want to bind the current atlas when using custom rectangles, you can use `io.Fonts->TexRef`.
|
||||
- Binding generators for languages such as C (which don't have constructors), should provide a helper, e.g. `inline ImTextureRef ImTextureRefFromID(ImTextureID tex_id) { ImTextureRef tex_ref = { ._TexData = NULL, .TexID = tex_id }; return tex_ref; }`
|
||||
|
||||
**Please read documentations or tutorials on your graphics API to understand how to display textures on the screen before moving onward.**
|
||||
|
||||
Long explanation:
|
||||
- Dear ImGui's job is to create "meshes", defined in a renderer-agnostic format made of draw commands and vertices. At the end of the frame those meshes (ImDrawList) will be displayed by your rendering function. They are made up of textured polygons and the code to render them is generally fairly short (a few dozen lines). In the examples/ folder we provide functions for popular graphics API (OpenGL, DirectX, etc.).
|
||||
- Dear ImGui's job is to create "meshes", defined in a renderer-agnostic format made of draw commands and vertices. At the end of the frame, those meshes (ImDrawList) will be displayed by your rendering function. They are made up of textured polygons and the code to render them is generally fairly short (a few dozen lines). In the examples/ folder, we provide functions for popular graphics APIs (OpenGL, DirectX, etc.).
|
||||
- Each rendering function decides on a data type to represent "textures". The concept of what is a "texture" is entirely tied to your underlying engine/graphics API.
|
||||
We carry the information to identify a "texture" in the ImTextureID type.
|
||||
ImTextureID is nothing more that a void*, aka 4/8 bytes worth of data: just enough to store 1 pointer or 1 integer of your choice.
|
||||
Dear ImGui doesn't know or understand what you are storing in ImTextureID, it merely pass ImTextureID values until they reach your rendering function.
|
||||
We carry the information to identify a "texture" in the ImTextureID type, which itself tends to be stored inside a ImTextureRef.
|
||||
ImTextureID default to ImU64 aka 8 bytes worth of data: just enough to store one pointer or integer of your choice.
|
||||
Dear ImGui doesn't know or understand what you are storing in ImTextureID, it merely passes values until they reach your rendering function.
|
||||
- In the [examples/](https://github.com/ocornut/imgui/tree/master/examples) backends, for each graphics API we decided on a type that is likely to be a good representation for specifying an image from the end-user perspective. This is what the _examples_ rendering functions are using:
|
||||
```cpp
|
||||
OpenGL:
|
||||
- ImTextureID = GLuint
|
||||
- ImTextureID should contains 'GLuint' (GL texture identifier).
|
||||
- See ImGui_ImplOpenGL3_RenderDrawData() function in imgui_impl_opengl3.cpp
|
||||
```
|
||||
```cpp
|
||||
DirectX9:
|
||||
- ImTextureID = LPDIRECT3DTEXTURE9
|
||||
- ImTextureID should contain a 'LPDIRECT3DTEXTURE9' (pointer).
|
||||
- See ImGui_ImplDX9_RenderDrawData() function in imgui_impl_dx9.cpp
|
||||
```
|
||||
```cpp
|
||||
DirectX11:
|
||||
- ImTextureID = ID3D11ShaderResourceView*
|
||||
- ImTextureID should contain a 'ID3D11ShaderResourceView*' (pointer)
|
||||
- See ImGui_ImplDX11_RenderDrawData() function in imgui_impl_dx11.cpp
|
||||
```
|
||||
```cpp
|
||||
DirectX12:
|
||||
- ImTextureID = D3D12_GPU_DESCRIPTOR_HANDLE
|
||||
- ImTextureID should contain a 'D3D12_GPU_DESCRIPTOR_HANDLE' (always 64-bits)
|
||||
- See ImGui_ImplDX12_RenderDrawData() function in imgui_impl_dx12.cpp
|
||||
```
|
||||
For example, in the OpenGL example backend we store raw OpenGL texture identifier (GLuint) inside ImTextureID.
|
||||
Whereas in the DirectX11 example backend we store a pointer to ID3D11ShaderResourceView inside ImTextureID, which is a higher-level structure tying together both the texture and information about its format and how to read it.
|
||||
|
||||
- If you have a custom engine built over e.g. OpenGL, instead of passing GLuint around you may decide to use a high-level data type to carry information about the texture as well as how to display it (shaders, etc.). The decision of what to use as ImTextureID can always be made better knowing how your codebase is designed. If your engine has high-level data types for "textures" and "material" then you may want to use them.
|
||||
- If you have a custom engine built over e.g. OpenGL, instead of passing GLuint around you may decide to use a high-level data type to carry information about the texture as well as how to display it (shaders, etc.). The decision of what to use as ImTextureID can always be made better by knowing how your codebase is designed. If your engine has high-level data types for "textures" and "material" then you may want to use them.
|
||||
If you are starting with OpenGL or DirectX or Vulkan and haven't built much of a rendering engine over them, keeping the default ImTextureID representation suggested by the example backends is probably the best choice.
|
||||
(Advanced users may also decide to keep a low-level type in ImTextureID, and use ImDrawList callback and pass information to their renderer)
|
||||
(Advanced users may also decide to keep a low-level type in ImTextureID, use ImDrawList callback and pass information to their renderer)
|
||||
|
||||
User code may do:
|
||||
```cpp
|
||||
// Cast our texture type to ImTextureID / void*
|
||||
// Cast our texture type to ImTextureID
|
||||
MyTexture* texture = g_CoffeeTableTexture;
|
||||
ImGui::Image((void*)texture, ImVec2(texture->Width, texture->Height));
|
||||
ImGui::Image((ImTextureID)(intptr_t)texture, ImVec2(texture->Width, texture->Height));
|
||||
```
|
||||
The renderer function called after ImGui::Render() will receive that same value that the user code passed:
|
||||
```cpp
|
||||
// Cast ImTextureID / void* stored in the draw command as our texture type
|
||||
MyTexture* texture = (MyTexture*)pcmd->GetTexID();
|
||||
// Cast ImTextureID stored in the draw command as our texture type
|
||||
MyTexture* texture = (MyTexture*)(intptr_t)pcmd->GetTexID();
|
||||
MyEngineBindTexture2D(texture);
|
||||
```
|
||||
Once you understand this design you will understand that loading image files and turning them into displayable textures is not within the scope of Dear ImGui.
|
||||
This is by design and is actually a good thing, because it means your code has full control over your data types and how you display them.
|
||||
If you want to display an image file (e.g. PNG file) into the screen, please refer to documentation and tutorials for the graphics API you are using.
|
||||
Once you understand this design, you will understand that loading image files and turning them into displayable textures is not within the scope of Dear ImGui.
|
||||
This is by design and is a good thing because it means your code has full control over your data types and how you display them.
|
||||
If you want to display an image file (e.g. PNG file) on the screen, please refer to documentation and tutorials for the graphics API you are using.
|
||||
|
||||
Refer to [Image Loading and Displaying Examples](https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples) on the [Wiki](https://github.com/ocornut/imgui/wiki) to find simplified examples for loading textures with OpenGL, DirectX9 and DirectX11.
|
||||
|
||||
C/C++ tip: a void* is pointer-sized storage. You may safely store any pointer or integer into it by casting your value to ImTextureID / void*, and vice-versa.
|
||||
Because both end-points (user code and rendering function) are under your control, you know exactly what is stored inside the ImTextureID / void*.
|
||||
Examples:
|
||||
C/C++ tip: a u64 is 8 bytes. You may safely store any pointer or integer into it by casting your value to ImTextureID, and vice-versa.
|
||||
Because both end-points (user code and rendering function) are under your control, you know exactly what is stored inside the ImTextureID.
|
||||
Here are some examples:
|
||||
```cpp
|
||||
GLuint my_tex = XXX;
|
||||
void* my_void_ptr;
|
||||
my_void_ptr = (void*)(intptr_t)my_tex; // cast a GLuint into a void* (we don't take its address! we literally store the value inside the pointer)
|
||||
my_tex = (GLuint)(intptr_t)my_void_ptr; // cast a void* into a GLuint
|
||||
ImTextureID my_imtexid;
|
||||
my_imtexid = (ImTextureID)(intptr_t)my_tex; // cast a GLuint into a ImTextureID (we don't take its address! we just copy the address)
|
||||
my_tex = (GLuint)(intptr_t)my_imtexid; // cast a ImTextureID into a GLuint
|
||||
|
||||
ID3D11ShaderResourceView* my_dx11_srv = XXX;
|
||||
void* my_void_ptr;
|
||||
my_void_ptr = (void*)my_dx11_srv; // cast a ID3D11ShaderResourceView* into an opaque void*
|
||||
my_dx11_srv = (ID3D11ShaderResourceView*)my_void_ptr; // cast a void* into a ID3D11ShaderResourceView*
|
||||
ImTextureID my_imtexid;
|
||||
my_imtexid = (ImTextureID)(intptr_t)my_dx11_srv; // cast a ID3D11ShaderResourceView* into an opaque ImTextureID
|
||||
my_dx11_srv = (ID3D11ShaderResourceView*)(intptr_t)_my_imtexid; // cast a ImTextureID into a ID3D11ShaderResourceView*
|
||||
```
|
||||
Finally, you may call `ImGui::ShowMetricsWindow()` to explore/visualize/understand how the ImDrawList are generated.
|
||||
|
||||
@@ -399,17 +648,25 @@ Finally, you may call `ImGui::ShowMetricsWindow()` to explore/visualize/understa
|
||||
|
||||
---
|
||||
|
||||
### Q: How can I use my own math types instead of ImVec2/ImVec4?
|
||||
### Q: How can I use maths operators with ImVec2?
|
||||
|
||||
You can edit [imconfig.h](https://github.com/ocornut/imgui/blob/master/imconfig.h) and setup the `IM_VEC2_CLASS_EXTRA`/`IM_VEC4_CLASS_EXTRA` macros to add implicit type conversions.
|
||||
This way you'll be able to use your own types everywhere, e.g. passing `MyVector2` or `glm::vec2` to ImGui functions instead of `ImVec2`.
|
||||
We do not export maths operators by default in imgui.h in order to not conflict with the use of your own maths types and maths operators. As a convenience, you may use `#define IMGUI_DEFINE_MATH_OPERATORS` + `#include "imgui.h"` to access our basic maths operators.
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
---
|
||||
|
||||
### Q: How can I use my own maths types instead of ImVec2/ImVec4?
|
||||
|
||||
You can setup your [imconfig.h](https://github.com/ocornut/imgui/blob/master/imconfig.h) file with `IM_VEC2_CLASS_EXTRA`/`IM_VEC4_CLASS_EXTRA` macros to add implicit type conversions to our own maths types.
|
||||
This way you will be able to use your own types everywhere, e.g. passing `MyVector2` or `glm::vec2` to ImGui functions instead of `ImVec2`.
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
---
|
||||
|
||||
### Q: How can I interact with standard C++ types (such as std::string and std::vector)?
|
||||
- Being highly portable (backends/bindings for several languages, frameworks, programming style, obscure or older platforms/compilers), and aiming for compatibility & performance suitable for every modern real-time game engines, dear imgui does not use any of std C++ types. We use raw types (e.g. char* instead of std::string) because they adapt to more use cases.
|
||||
- Being highly portable (backends/bindings for several languages, frameworks, programming styles, obscure or older platforms/compilers), and aiming for compatibility & performance suitable for every modern real-time game engine, Dear ImGui does not use any of std C++ types. We use raw types (e.g. char* instead of std::string) because they adapt to more use cases.
|
||||
- To use ImGui::InputText() with a std::string or any resizable string class, see [misc/cpp/imgui_stdlib.h](https://github.com/ocornut/imgui/blob/master/misc/cpp/imgui_stdlib.h).
|
||||
- To use combo boxes and list boxes with `std::vector` or any other data structure: the `BeginCombo()/EndCombo()` API
|
||||
lets you iterate and submit items yourself, so does the `ListBoxHeader()/ListBoxFooter()` API.
|
||||
@@ -418,12 +675,12 @@ Prefer using them over the old and awkward `Combo()/ListBox()` api.
|
||||
You may write your own one-liner wrappers to facilitate user code (tip: add new functions in ImGui:: namespace from your code).
|
||||
- Dear ImGui applications often need to make intensive use of strings. It is expected that many of the strings you will pass
|
||||
to the API are raw literals (free in C/C++) or allocated in a manner that won't incur a large cost on your application.
|
||||
Please bear in mind that using `std::string` on applications with large amount of UI may incur unsatisfactory performances.
|
||||
Please bear in mind that using `std::string` on applications with a large amount of UI may incur unsatisfactory performances.
|
||||
Modern implementations of `std::string` often include small-string optimization (which is often a local buffer) but those
|
||||
are not configurable and not the same across implementations.
|
||||
- If you are finding your UI traversal cost to be too large, make sure your string usage is not leading to excessive amount
|
||||
of heap allocations. Consider using literals, statically sized buffers and your own helper functions. A common pattern
|
||||
is that you will need to build lots of strings on the fly, and their maximum length can be easily be scoped ahead.
|
||||
- If you are finding your UI traversal cost to be too large, make sure your string usage is not leading to an excessive amount
|
||||
of heap allocations. Consider using literals, statically sized buffers, and your own helper functions. A common pattern
|
||||
is that you will need to build lots of strings on the fly, and their maximum length can be easily scoped ahead.
|
||||
One possible implementation of a helper to facilitate printf-style building of strings: https://github.com/ocornut/Str
|
||||
This is a small helper where you can instance strings with configurable local buffers length. Many game engines will
|
||||
provide similar or better string helpers.
|
||||
@@ -444,12 +701,12 @@ ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||||
ImVec2 p = ImGui::GetCursorScreenPos();
|
||||
|
||||
// Draw a red circle
|
||||
draw_list->AddCircleFilled(ImVec2(p.x + 50, p.y + 50), 30.0f, IM_COL32(255, 0, 0, 255), 16);
|
||||
draw_list->AddCircleFilled(ImVec2(p.x + 50, p.y + 50), 30.0f, IM_COL32(255, 0, 0, 255));
|
||||
|
||||
// Draw a 3 pixel thick yellow line
|
||||
draw_list->AddLine(ImVec2(p.x, p.y), ImVec2(p.x + 100.0f, p.y + 100.0f), IM_COL32(255, 255, 0, 255), 3.0f);
|
||||
|
||||
// Advance the ImGui cursor to claim space in the window (otherwise the window will appears small and needs to be resized)
|
||||
// Advance the ImGui cursor to claim space in the window (otherwise the window will appear small and needs to be resized)
|
||||
ImGui::Dummy(ImVec2(200, 200));
|
||||
|
||||
ImGui::End();
|
||||
@@ -458,10 +715,10 @@ ImGui::End();
|
||||
|
||||
- Refer to "Demo > Examples > Custom Rendering" in the demo window and read the code of `ShowExampleAppCustomRendering()` in `imgui_demo.cpp` from more examples.
|
||||
- To generate colors: you can use the macro `IM_COL32(255,255,255,255)` to generate them at compile time, or use `ImGui::GetColorU32(IM_COL32(255,255,255,255))` or `ImGui::GetColorU32(ImVec4(1.0f,1.0f,1.0f,1.0f))` to generate a color that is multiplied by the current value of `style.Alpha`.
|
||||
- Math operators: if you have setup `IM_VEC2_CLASS_EXTRA` in `imconfig.h` to bind your own math types, you can use your own math types and their natural operators instead of ImVec2. ImVec2 by default doesn't export any math operators in the public API. You may use `#define IMGUI_DEFINE_MATH_OPERATORS` `#include "imgui_internal.h"` to use the internally defined math operators, but instead prefer using your own math library and set it up in `imconfig.h`.
|
||||
- You can use `ImGui::GetBackgroundDrawList()` or `ImGui::GetForegroundDrawList()` to access draw lists which will be displayed behind and over every other dear imgui windows (one bg/fg drawlist per viewport). This is very convenient if you need to quickly display something on the screen that is not associated to a dear imgui window.
|
||||
- Math operators: if you have setup `IM_VEC2_CLASS_EXTRA` in `imconfig.h` to bind your own math types, you can use your own math types and their natural operators instead of ImVec2. ImVec2 by default doesn't export any math operators in the public API. You may use `#define IMGUI_DEFINE_MATH_OPERATORS` `#include "imgui.h"` to use our math operators, but instead prefer using your own math library and set it up in `imconfig.h`.
|
||||
- You can use `ImGui::GetBackgroundDrawList()` or `ImGui::GetForegroundDrawList()` to access draw lists which will be displayed behind and over every other Dear ImGui window (one bg/fg drawlist per viewport). This is very convenient if you need to quickly display something on the screen that is not associated with a Dear ImGui window.
|
||||
- You can also create your own empty window and draw inside it. Call Begin() with the NoBackground | NoDecoration | NoSavedSettings | NoInputs flags (The `ImGuiWindowFlags_NoDecoration` flag itself is a shortcut for NoTitleBar | NoResize | NoScrollbar | NoCollapse). Then you can retrieve the ImDrawList* via `GetWindowDrawList()` and draw to it in any way you like.
|
||||
`- You can create your own ImDrawList instance. You'll need to initialize them with `ImGui::GetDrawListSharedData()`, or create your own instancing ImDrawListSharedData`, and then call your renderer function with your own ImDrawList or ImDrawData data.
|
||||
- You can create your own ImDrawList instance. You'll need to initialize them with `ImGui::GetDrawListSharedData()`, or create your own instancing `ImDrawListSharedData`, and then call your renderer function with your own ImDrawList or ImDrawData data.
|
||||
- Looking for fun? The [ImDrawList coding party 2020](https://github.com/ocornut/imgui/issues/3606) thread is full of "don't do this at home" extreme uses of the ImDrawList API.
|
||||
|
||||
##### [Return to Index](#index)
|
||||
@@ -472,26 +729,60 @@ ImGui::End();
|
||||
|
||||
### Q: How should I handle DPI in my application?
|
||||
|
||||
The short answer is: obtain the desired DPI scale, load your fonts resized with that scale (always round down fonts size to nearest integer), and scale your Style structure accordingly using `style.ScaleAllSizes()`.
|
||||
Since 1.92 (June 2025) fonts may be dynamically used at any size.
|
||||
|
||||
Your application may want to detect DPI change and reload the fonts and reset style between frames.
|
||||
**Scaling fonts**
|
||||
|
||||
Your ui code should avoid using hardcoded constants for size and positioning. Prefer to express values as multiple of reference values such as `ImGui::GetFontSize()` or `ImGui::GetFrameHeight()`. So e.g. instead of seeing a hardcoded height of 500 for a given item/window, you may want to use `30*ImGui::GetFontSize()` instead.
|
||||
Select default size:
|
||||
```cpp
|
||||
style.FontSizeBase = 20.0f;
|
||||
```
|
||||
Scale all fonts:
|
||||
```cpp
|
||||
style.FontScaleDpi = 2.0f;
|
||||
```
|
||||
|
||||
Down the line Dear ImGui will provide a variety of standardized reference values to facilitate using this.
|
||||
To change font size:
|
||||
```cpp
|
||||
ImGui::PushFont(NULL, 42.0f); // This will be multiplied by style.FontScaleDpi
|
||||
```
|
||||
To change font and font size:
|
||||
```cpp
|
||||
ImGui::PushFont(new_font, 42.0f);
|
||||
```
|
||||
|
||||
Applications in the `examples/` folder are not DPI aware partly because they are unable to load a custom font from the file-system (may change that in the future).
|
||||
In `docking` branch or with multi-viewports:
|
||||
```cpp
|
||||
io.ConfigDpiScaleFonts = true; // (Docking branch only) Automatically overwrite style.FontScaleDpi in Begin() when Monitor DPI changes. This will scale fonts but _NOT_ scale sizes/padding for now.
|
||||
io.ConfigDpiScaleViewports = true; // (Docking branch only) Scale Dear ImGui and Platform Windows when Monitor DPI changes.
|
||||
```
|
||||
|
||||
The reason DPI is not auto-magically solved in stock examples is that we don't yet have a satisfying solution for the "multi-dpi" problem (using the `docking` branch: when multiple viewport windows are over multiple monitors using different DPI scale). The current way to handle this on the application side is:
|
||||
- Create and maintain one font atlas per active DPI scale (e.g. by iterating `platform_io.Monitors[]` before `NewFrame()`).
|
||||
- Hook `platform_io.OnChangedViewport()` to detect when a `Begin()` call makes a Dear ImGui window change monitor (and therefore DPI).
|
||||
- In the hook: swap atlas, swap style with correctly sized one, remap the current font from one atlas to the other (may need to maintain a remapping table of your fonts at variying DPI scale).
|
||||
**Scaling style** (paddings, spacings, thicknesses)
|
||||
|
||||
This approach is relatively easy and functional but come with two issues:
|
||||
- It's not possibly to reliably size or position a window ahead of `Begin()` without knowing on which monitor it'll land.
|
||||
- Style override may be lost during the `Begin()` call crossing monitor boundaries. You may need to do some custom scaling mumbo-jumbo if you want your `OnChangedViewport()` handler to preserve style overrides.
|
||||
This is still massively work in progress, expect turbulence.
|
||||
Style values are currently not easily scalable dynamically.
|
||||
For single viewport application you can call once:
|
||||
```cpp
|
||||
style.ScaleAllSizes(factor); // call once!
|
||||
```
|
||||
If you need to change the scaling factor, it is currently most practical to reset the style and call this again with a new value.
|
||||
|
||||
Please note that if you are not using multi-viewports with multi-monitors using different DPI scale, you can ignore all of this and use the simpler technique recommended at the top.
|
||||
Your UI code should avoid using hardcoded constants for size and positioning. Prefer to express values as multiple of reference values such as `ImGui::GetFontSize()` or `ImGui::GetFrameHeight()`. So e.g. instead of seeing a hardcoded height of 500 for a given item/window, you may want to use `30*ImGui::GetFontSize()` instead.
|
||||
|
||||
Down the line Dear ImGui will provide a variety of standardized reference values to facilitate using this. This is expected to happen during subsequent 1.92.x releases.
|
||||
|
||||
Applications in the `examples/` folder are partly DPI aware but they are unable to load a custom font from the file-system, so they look ugly (may change that in the future).
|
||||
|
||||
The reason DPI is not auto-magically solved in stock examples is that we don't yet have a satisfying solution for the "multi-dpi" problem (using the `docking` branch: when multiple viewport windows are over multiple monitors using different DPI scales) specifically for the `ImGuiStyle` structure. Fonts are however now perfectly scalable.
|
||||
|
||||
**On Windows, you need to inform Windows that your application is DPI aware!**
|
||||
If this is not done, Windows will scale the application window and the UI text will be blurry. Potential solutions to indicate DPI awareness on Windows are:
|
||||
- For SDL2: the flag `SDL_WINDOW_ALLOW_HIGHDPI` needs to be passed to `SDL_CreateWindow()` + call `::SetProcessDPIAware()`.
|
||||
- For SDL3: the flag `SDL_WINDOW_HIGH_PIXEL_DENSITY` needs to be passed to `SDL_CreateWindow()`.
|
||||
- For GLFW: this is done automatically.
|
||||
- For other Windows projects with other backends, or wrapper projects:
|
||||
- We provide a `ImGui_ImplWin32_EnableDpiAwareness()` helper method in the Win32 backend.
|
||||
- Use an [application manifest file](https://learn.microsoft.com/en-us/windows/win32/hidpi/setting-the-default-dpi-awareness-for-a-process) to set the `<dpiAware>` property.
|
||||
|
||||
### Q: How can I load a different font than the default?
|
||||
Use the font atlas to load the TTF/OTF file you want:
|
||||
@@ -513,7 +804,7 @@ backslash \ within a string literal, you need to write it double backslash "\\":
|
||||
|
||||
```cpp
|
||||
io.Fonts->AddFontFromFileTTF("MyFolder\MyFont.ttf", size); // WRONG (you are escaping the M here!)
|
||||
io.Fonts->AddFontFromFileTTF("MyFolder\\MyFont.ttf", size; // CORRECT (Windows only)
|
||||
io.Fonts->AddFontFromFileTTF("MyFolder\\MyFont.ttf", size); // CORRECT (Windows only)
|
||||
io.Fonts->AddFontFromFileTTF("MyFolder/MyFont.ttf", size); // ALSO CORRECT
|
||||
```
|
||||
|
||||
@@ -522,57 +813,31 @@ io.Fonts->AddFontFromFileTTF("MyFolder/MyFont.ttf", size); // ALSO CORRECT
|
||||
---
|
||||
|
||||
### Q: How can I easily use icons in my application?
|
||||
The most convenient and practical way is to merge an icon font such as FontAwesome inside you
|
||||
The most convenient and practical way is to merge an icon font such as FontAwesome inside your
|
||||
main font. Then you can refer to icons within your strings.
|
||||
You may want to see `ImFontConfig::GlyphMinAdvanceX` to make your icon look monospace to facilitate alignment.
|
||||
(Read the [docs/FONTS.md](https://github.com/ocornut/imgui/blob/master/docs/FONTS.md) file for more details about icons font loading.)
|
||||
With some extra effort, you may use colorful icon by registering custom rectangle space inside the font atlas,
|
||||
and copying your own graphics data into it. See docs/FONTS.md about using the AddCustomRectFontGlyph API.
|
||||
Read the [docs/FONTS.md](https://github.com/ocornut/imgui/blob/master/docs/FONTS.md) file for more details about icons font loading.
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
---
|
||||
|
||||
### Q: How can I load multiple fonts?
|
||||
Use the font atlas to pack them into a single texture:
|
||||
(Read the [docs/FONTS.md](https://github.com/ocornut/imgui/blob/master/docs/FONTS.md) file and the code in ImFontAtlas for more details.)
|
||||
|
||||
```cpp
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImFont* font0 = io.Fonts->AddFontDefault();
|
||||
ImFont* font1 = io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels);
|
||||
ImFont* font2 = io.Fonts->AddFontFromFileTTF("myfontfile2.ttf", size_in_pixels);
|
||||
io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8()
|
||||
// the first loaded font gets used by default
|
||||
// use ImGui::PushFont()/ImGui::PopFont() to change the font at runtime
|
||||
|
||||
// Options
|
||||
ImFontConfig config;
|
||||
config.OversampleH = 2;
|
||||
config.OversampleV = 1;
|
||||
config.GlyphOffset.y -= 1.0f; // Move everything by 1 pixels up
|
||||
config.GlyphExtraSpacing.x = 1.0f; // Increase spacing between characters
|
||||
io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_pixels, &config);
|
||||
|
||||
// Combine multiple fonts into one (e.g. for icon fonts)
|
||||
static ImWchar ranges[] = { 0xf000, 0xf3ff, 0 };
|
||||
ImFontConfig config;
|
||||
config.MergeMode = true;
|
||||
io.Fonts->AddFontDefault();
|
||||
io.Fonts->AddFontFromFileTTF("fontawesome-webfont.ttf", 16.0f, &config, ranges); // Merge icon font
|
||||
io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_pixels, NULL, &config, io.Fonts->GetGlyphRangesJapanese()); // Merge japanese glyphs
|
||||
```
|
||||
Use the font atlas to pack them into a single texture. Read [docs/FONTS.md](https://github.com/ocornut/imgui/blob/master/docs/FONTS.md) for more details.
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
---
|
||||
|
||||
### Q: How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic?
|
||||
When loading a font, pass custom Unicode ranges to specify the glyphs to load.
|
||||
|
||||
Since 1.92 (June 2025) and with an updated backend, it is not necessary to specify glyph ranges at all.
|
||||
|
||||
Before 1.92, when loading a font, pass custom Unicode ranges to specify the glyphs to load.
|
||||
```cpp
|
||||
// [BEFORE 1.92]
|
||||
// Add default Japanese ranges
|
||||
io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, io.Fonts->GetGlyphRangesJapanese());
|
||||
io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, nullptr, io.Fonts->GetGlyphRangesJapanese());
|
||||
|
||||
// Or create your own custom ranges (e.g. for a game you can feed your entire game script and only build the characters the game need)
|
||||
ImVector<ImWchar> ranges;
|
||||
@@ -581,20 +846,21 @@ builder.AddText("Hello world"); // Add a string (here "He
|
||||
builder.AddChar(0x7262); // Add a specific character
|
||||
builder.AddRanges(io.Fonts->GetGlyphRangesJapanese()); // Add one of the default ranges
|
||||
builder.BuildRanges(&ranges); // Build the final result (ordered ranges with all the unique characters submitted)
|
||||
io.Fonts->AddFontFromFileTTF("myfontfile.ttf", 16.0f, NULL, ranges.Data);
|
||||
io.Fonts->AddFontFromFileTTF("myfontfile.ttf", 16.0f, nullptr, ranges.Data);
|
||||
```
|
||||
|
||||
All your strings needs to use UTF-8 encoding. In C++11 you can encode a string literal in UTF-8
|
||||
by using the u8"hello" syntax. Specifying literal in your source code using a local code page
|
||||
(such as CP-923 for Japanese or CP-1251 for Cyrillic) will NOT work!
|
||||
Otherwise you can convert yourself to UTF-8 or load text data from file already saved as UTF-8.
|
||||
All your strings need to use UTF-8 encoding.
|
||||
You need to tell your compiler to use UTF-8, or in C++11 you can encode a string literal in UTF-8 by using the u8"hello" syntax.
|
||||
Specifying literal in your source code using a local code page (such as CP-923 for Japanese or CP-1251 for Cyrillic) will NOT work!
|
||||
See [About UTF-8 Encoding](https://github.com/ocornut/imgui/blob/master/docs/FONTS.md#about-utf-8-encoding) section
|
||||
of [FONTS.md](https://github.com/ocornut/imgui/blob/master/docs/FONTS.md) for details about UTF-8 Encoding.
|
||||
|
||||
Text input: it is up to your application to pass the right character code by calling `io.AddInputCharacter()`.
|
||||
The applications in examples/ are doing that.
|
||||
Windows: you can use the WM_CHAR or WM_UNICHAR or WM_IME_CHAR message (depending if your app is built using Unicode or MultiByte mode).
|
||||
You may also use MultiByteToWideChar() or ToUnicode() to retrieve Unicode codepoints from MultiByte characters or keyboard state.
|
||||
Windows: if your language is relying on an Input Method Editor (IME), you copy the HWND of your window to io.ImeWindowHandle in order for
|
||||
the default implementation of io.ImeSetInputScreenPosFn() to set your Microsoft IME position correctly.
|
||||
You may also use `MultiByteToWideChar()` or `ToUnicode()` to retrieve Unicode codepoints from MultiByte characters or keyboard state.
|
||||
Windows: if your language is relying on an Input Method Editor (IME), you can write your HWND to `ImGui::GetMainViewport()->PlatformHandleRaw`
|
||||
for the default implementation of `GetPlatformIO().Platform_SetImeDataFn()` to set your Microsoft IME position correctly.
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
@@ -608,8 +874,8 @@ You may take a look at:
|
||||
|
||||
- [Quotes](https://github.com/ocornut/imgui/wiki/Quotes)
|
||||
- [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui)
|
||||
- [Sponsors](https://github.com/ocornut/imgui/wiki/Sponsors)
|
||||
- [Gallery](https://github.com/ocornut/imgui/issues/3488)
|
||||
- [Funding & Sponsors](https://github.com/ocornut/imgui/wiki/Funding)
|
||||
- [Gallery](https://github.com/ocornut/imgui/issues?q=label%3Agallery)
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
@@ -617,11 +883,11 @@ You may take a look at:
|
||||
|
||||
### Q: Can you create elaborate/serious tools with Dear ImGui?
|
||||
|
||||
Yes. People have written game editors, data browsers, debuggers, profilers and all sort of non-trivial tools with the library. In my experience the simplicity of the API is very empowering. Your UI runs close to your live data. Make the tools always-on and everybody in the team will be inclined to create new tools (as opposed to more "offline" UI toolkits where only a fraction of your team effectively creates tools). The list of sponsors below is also an indicator that serious game teams have been using the library.
|
||||
Yes. People have written game editors, data browsers, debuggers, profilers, and all sorts of non-trivial tools with the library. In my experience, the simplicity of the API is very empowering. Your UI runs close to your live data. Make the tools always-on and everybody in the team will be inclined to create new tools (as opposed to more "offline" UI toolkits where only a fraction of your team effectively creates tools). The list of sponsors below is also an indicator that serious game teams have been using the library.
|
||||
|
||||
Dear ImGui is very programmer centric and the immediate-mode GUI paradigm might require you to readjust some habits before you can realize its full potential. Dear ImGui is about making things that are simple, efficient and powerful.
|
||||
Dear ImGui is very programmer-centric and the immediate-mode GUI paradigm might require you to readjust some habits before you can realize its full potential. Dear ImGui is about making things that are simple, efficient, and powerful.
|
||||
|
||||
Dear ImGui is built to be efficient and scalable toward the needs for AAA-quality applications running all day. The IMGUI paradigm offers different opportunities for optimization that the more typical RMGUI paradigm.
|
||||
Dear ImGui is built to be efficient and scalable toward the needs for AAA-quality applications running all day. The IMGUI paradigm offers different opportunities for optimization than the more typical RMGUI paradigm.
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
@@ -629,9 +895,9 @@ Dear ImGui is built to be efficient and scalable toward the needs for AAA-qualit
|
||||
|
||||
### Q: Can you reskin the look of Dear ImGui?
|
||||
|
||||
Somehow. You can alter the look of the interface to some degree: changing colors, sizes, padding, rounding, fonts. However, as Dear ImGui is designed and optimized to create debug tools, the amount of skinning you can apply is limited. There is only so much you can stray away from the default look and feel of the interface. Dear ImGui is NOT designed to create user interface for games, although with ingenious use of the low-level API you can do it.
|
||||
Somewhat. You can alter the look of the interface to some degree: changing colors, sizes, padding, rounding, and fonts. However, as Dear ImGui is designed and optimized to create debug tools, the amount of skinning you can apply is limited. There is only so much you can stray away from the default look and feel of the interface. Dear ImGui is NOT designed to create a user interface for games, although with ingenious use of the low-level API you can do it.
|
||||
|
||||
A reasonably skinned application may look like (screenshot from [#2529](https://github.com/ocornut/imgui/issues/2529#issuecomment-524281119))
|
||||
A reasonably skinned application may look like (screenshot from [#2529](https://github.com/ocornut/imgui/issues/2529#issuecomment-524281119)):
|
||||

|
||||
|
||||
##### [Return to Index](#index)
|
||||
@@ -640,7 +906,7 @@ A reasonably skinned application may look like (screenshot from [#2529](https://
|
||||
|
||||
### Q: Why using C++ (as opposed to C)?
|
||||
|
||||
Dear ImGui takes advantage of a few C++ languages features for convenience but nothing anywhere Boost insanity/quagmire. Dear ImGui does NOT require C++11 so it can be used with most old C++ compilers. Dear ImGui doesn't use any C++ header file. Language-wise, function overloading and default parameters are used to make the API easier to use and code more terse. Doing so I believe the API is sitting on a sweet spot and giving up on those features would make the API more cumbersome. Other features such as namespace, constructors and templates (in the case of the ImVector<> class) are also relied on as a convenience.
|
||||
Dear ImGui takes advantage of a few C++ language features for convenience but nothing anywhere Boost insanity/quagmire. Dear ImGui doesn't use any C++ header file. Dear ImGui uses a very small subset of C++11 features. In particular, function overloading and default parameters are used to make the API easier to use and code terser. Doing so I believe the API is sitting on a sweet spot and giving up on those features would make the API more cumbersome. Other features such as namespace, constructors, and templates (in the case of the ImVector<> class) are also relied on as a convenience.
|
||||
|
||||
There is an auto-generated [c-api for Dear ImGui (cimgui)](https://github.com/cimgui/cimgui) by Sonoro1234 and Stephan Dilly. It is designed for creating bindings to other languages. If possible, I would suggest using your target language functionalities to try replicating the function overloading and default parameters used in C++ else the API may be harder to use. Also see [Bindings](https://github.com/ocornut/imgui/wiki/Bindings) for various third-party bindings.
|
||||
|
||||
@@ -651,11 +917,11 @@ There is an auto-generated [c-api for Dear ImGui (cimgui)](https://github.com/ci
|
||||
# Q&A: Community
|
||||
|
||||
### Q: How can I help?
|
||||
- Businesses: please reach out to `contact AT dearimgui.com` if you work in a place using Dear ImGui! We can discuss ways for your company to fund development via invoiced technical support, maintenance or sponsoring contacts. This is among the most useful thing you can do for Dear ImGui. With increased funding, we can hire more people working on this project.
|
||||
- Businesses: please reach out to `omar AT dearimgui.com` if you work in a place using Dear ImGui! We can discuss ways for your company to fund development via invoiced technical support, maintenance, or sponsoring contacts. This is among the most useful thing you can do for Dear ImGui. With increased funding, we can hire more people to work on this project. Please see [Funding](https://github.com/ocornut/imgui/wiki/Funding) page.
|
||||
- Individuals: you can support continued maintenance and development via PayPal donations. See [README](https://github.com/ocornut/imgui/blob/master/docs/README.md).
|
||||
- If you are experienced with Dear ImGui and C++, look at [GitHub Issues](https://github.com/ocornut/imgui/issues), [GitHub Discussions](https://github.com/ocornut/imgui/discussions), the [Wiki](https://github.com/ocornut/imgui/wiki), read [docs/TODO.txt](https://github.com/ocornut/imgui/blob/master/docs/TODO.txt) and see how you want to help and can help!
|
||||
- Disclose your usage of Dear ImGui via a dev blog post, a tweet, a screenshot, a mention somewhere etc.
|
||||
You may post screenshot or links in the [gallery threads](https://github.com/ocornut/imgui/issues/3488). Visuals are ideal as they inspire other programmers. Disclosing your use of Dear ImGui helps the library grow credibility, and help other teams and programmers with taking decisions.
|
||||
- If you are experienced with Dear ImGui and C++, look at [GitHub Issues](https://github.com/ocornut/imgui/issues), [GitHub Discussions](https://github.com/ocornut/imgui/discussions), the [Wiki](https://github.com/ocornut/imgui/wiki), read [docs/TODO.txt](https://github.com/ocornut/imgui/blob/master/docs/TODO.txt), and see how you want to help and can help!
|
||||
- Disclose your usage of Dear ImGui via a dev blog post, a tweet, a screenshot, a mention somewhere, etc.
|
||||
You may post screenshots or links in the [gallery threads](https://github.com/ocornut/imgui/issues?q=label%3Agallery). Visuals are ideal as they inspire other programmers. Disclosing your use of Dear ImGui helps the library grow credibility, and helps other teams and programmers with taking decisions.
|
||||
- If you have issues or if you need to hack into the library, even if you don't expect any support it is useful that you share your issues or sometimes incomplete PR.
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
460
docs/FONTS.md
460
docs/FONTS.md
@@ -2,98 +2,181 @@ _(You may browse this at https://github.com/ocornut/imgui/blob/master/docs/FONTS
|
||||
|
||||
## Dear ImGui: Using Fonts
|
||||
|
||||
The code in imgui.cpp embeds a copy of 'ProggyClean.ttf' (by Tristan Grimmer),
|
||||
a 13 pixels high, pixel-perfect font used by default. We embed it in the source code so you can use Dear ImGui without any file system access. ProggyClean does not scale smoothly, therefore it is recommended that you load your own file when using Dear ImGui in an application aiming to look nice and wanting to support multiple resolutions.
|
||||
The code in Dear ImGui embeds a copy of [ProggyClean.ttf](https://github.com/bluescan/proggyfonts) by Tristan Grimmer,
|
||||
a 13 pixels high, pixel-perfect font used by default. ProggyClean does not scale very nicely.
|
||||
|
||||
You may also load external .TTF/.OTF files.
|
||||
The code in Dear ImGui embeds a partial copy of [ProggyForever.ttf](https://github.com/ocornut/proggyforever) by Disco Hello & Tristan Grimmer,
|
||||
a new font mimicking ProggyClean which does scale nicely.
|
||||
|
||||
We embed fonts in the code so you can use Dear ImGui without any file system access.
|
||||
If you don't use them you can set `IMGUI_DISABLE_DEFAULT_FONT` in your [imconfig.h](https://github.com/ocornut/imgui/blob/master/imconfig.h) file to ship binaries without the fonts and save about ~26 KB.
|
||||
|
||||
Calling io.Fonts->AddFontDefaultVector() loads ProggyForever.
|
||||
Calling io.Fonts->AddFontDefaultBitmap() loads ProggyClean.
|
||||
Calling io.Fonts->AddFontDefault() selects one based on the expected default font size (when `style.FontSizeBase * style.FontScaleMain * style.FontSizeDpi >= 15` we use ProggyForever).
|
||||
|
||||
You may also load external .TTF/.OTF files, see instructions on this page.
|
||||
In the [misc/fonts/](https://github.com/ocornut/imgui/tree/master/misc/fonts) folder you can find a few suggested fonts, provided as a convenience.
|
||||
|
||||
**Also read the FAQ:** https://www.dearimgui.org/faq (there is a Fonts section!)
|
||||
**Also read the FAQ:** https://www.dearimgui.com/faq (there is a Fonts section!)
|
||||
|
||||
## Index
|
||||
- [Readme First](#readme-first)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
- [New! Dynamic Fonts system in 1.92 (June 2025)](#new-dynamic-fonts-system-in-192-june-2025)
|
||||
- [How should I handle DPI in my application?](#how-should-i-handle-dpi-in-my-application)
|
||||
- [Fonts Loading Instructions](#font-loading-instructions)
|
||||
- [Fonts Loading Instructions](#fonts-loading-instructions)
|
||||
- [Loading Font Data from Memory](#loading-font-data-from-memory)
|
||||
- [Loading Font Data Embedded In Source Code](#loading-font-data-embedded-in-source-code)
|
||||
- [Using Icon Fonts](#using-icon-fonts)
|
||||
- [Excluding Overlapping Ranges](#excluding-overlapping-ranges)
|
||||
- [Using FreeType Rasterizer (imgui_freetype)](#using-freetype-rasterizer-imgui_freetype)
|
||||
- [Using Colorful Glyphs/Emojis](#using-colorful-glyphsemojis)
|
||||
- [Using Custom Glyph Ranges](#using-custom-glyph-ranges)
|
||||
- [Using Custom Colorful Icons](#using-custom-colorful-icons)
|
||||
- [Using Font Data Embedded In Source Code](#using-font-data-embedded-in-source-code)
|
||||
- [About filenames](#about-filenames)
|
||||
- [About Filenames](#about-filenames)
|
||||
- [About UTF-8 Encoding](#about-utf-8-encoding)
|
||||
- [Debug Tools](#debug-tools)
|
||||
- [Credits/Licenses For Fonts Included In Repository](#creditslicenses-for-fonts-included-in-repository)
|
||||
- [Font Links](#font-links)
|
||||
|
||||
---------------------------------------
|
||||
## Readme First
|
||||
|
||||
- All loaded fonts glyphs are rendered into a single texture atlas ahead of time. Calling either of `io.Fonts->GetTexDataAsAlpha8()`, `io.Fonts->GetTexDataAsRGBA32()` or `io.Fonts->Build()` will build the atlas.
|
||||
## Troubleshooting
|
||||
|
||||
- You can use the style editor `ImGui::ShowStyleEditor()` in the "Fonts" section to browse your fonts and understand what's going on if you have an issue. You can also reach it in `Demo->Tools->Style Editor->Fonts`:
|
||||
**A vast majority of font and text related issues encountered comes from 4 things:**
|
||||
|
||||

|
||||
### (1) Invalid filename due to use of `\` or unexpected working directory.
|
||||
|
||||
- Make sure your font ranges data are persistent (available during the calls to `GetTexDataAsAlpha8()`/`GetTexDataAsRGBA32()/`Build()`.
|
||||
See [About Filenames](#about-filenames). AddFontXXX() functions should assert if the filename is incorrect.
|
||||
|
||||
- Use C++11 u8"my text" syntax to encode literal strings as UTF-8. e.g.:
|
||||
```cpp
|
||||
u8"hello"
|
||||
u8"こんにちは" // this will be encoded as UTF-8
|
||||
```
|
||||
### (2) Invalid UTF-8 encoding of your non-ASCII strings.
|
||||
|
||||
See [About UTF-8 Encoding](#about-utf-8-encoding). Use the encoding viewer to confirm encoding of string literal in your source code is correct.
|
||||
|
||||
### (3) Missing glyph ranges.
|
||||
|
||||
🆕 **Since 1.92, with an up to date backend: specifying glyph ranges is unnecessary.**
|
||||
|
||||
⏪ Before 1.92: you need to load a font with explicit glyph ranges if you want to use non-ASCII characters. See [Fonts Loading Instructions](#fonts-loading-instructions). Use [Debug Tools](#debug-tools) confirm loaded fonts and loaded glyph ranges.
|
||||
|
||||
This was a previous constraint of Dear ImGui (lifted in 1.92): when loading a font you need to specify which characters glyphs to load.
|
||||
All loaded fonts glyphs are rendered into a single texture atlas ahead of time. Calling either of `io.Fonts->GetTexDataAsAlpha8()`, `io.Fonts->GetTexDataAsRGBA32()` or `io.Fonts->Build()` will build the atlas. This is generally called by the Renderer backend, e.g. `ImGui_ImplDX11_NewFrame()` calls it. **If you use custom glyphs ranges, make sure the array is persistent** and available during the calls to `GetTexDataAsAlpha8()/GetTexDataAsRGBA32()/Build()`.
|
||||
|
||||
### (4) Font atlas texture fails to upload to GPU.
|
||||
|
||||
🆕 **Since 1.92, with an up to date backend: atlas is built incrementally and dynamically resized, this is less likely to happen**
|
||||
|
||||
:rewind: This is often of byproduct of point 3. If you have large number of glyphs or multiple fonts, the texture may become too big for your graphics API. **The typical result of failing to upload a texture is if every glyph or everything appears as empty white rectangles.** Mind the fact that some graphics drivers have texture size limitation. If you are building a PC application, mind the fact that your users may use hardware with lower limitations than yours.
|
||||
|
||||

|
||||
|
||||
Some solutions:
|
||||
- You may reduce oversampling, e.g. `font_config.OversampleH = 1`, this will half your texture size for a quality loss.
|
||||
Note that while OversampleH = 2 looks visibly very close to 3 in most situations, with OversampleH = 1 the quality drop will be noticeable. Read about oversampling [here](https://github.com/nothings/stb/blob/master/tests/oversample).
|
||||
- Reduce glyphs ranges by calculating them from source localization data.
|
||||
You can use the `ImFontGlyphRangesBuilder` for this purpose and rebuilding your atlas between frames when new characters are needed. This will be the biggest win!
|
||||
- Set `io.Fonts.Flags |= ImFontAtlasFlags_NoPowerOfTwoHeight;` to disable rounding the texture height to the next power of two.
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
---------------------------------------
|
||||
|
||||
## New! Dynamic Fonts system in 1.92 (June 2025)
|
||||
|
||||
v1.92 introduces a newer, dynamic font system. It requires backend to support the `ImGuiBackendFlags_HasTextures` feature:
|
||||
- Users of icons, Asian and non-English languages do not need to pre-build all glyphs ahead of time. Saving on loading time, memory, and also reducing issues with missing glyphs. Specifying glyph ranges is not needed anymore.
|
||||
- `PushFont(NULL, new_size)` may be used anytime to change font size.
|
||||
- Packing custom rectangles is more convenient as pixels may be written to immediately.
|
||||
- Any update to fonts previously required backend specific calls to re-upload the texture, and said calls were not portable across backends. It is now possible to scale fonts etc. in a way that doesn't require you to make backend-specific calls.
|
||||
- It is possible to plug a custom loader/backend to any font source.
|
||||
|
||||
See [#8465](https://github.com/ocornut/imgui/issues/8465) for more details.
|
||||
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
---------------------------------------
|
||||
|
||||
## How should I handle DPI in my application?
|
||||
|
||||
See [FAQ entry](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#q-how-should-i-handle-dpi-in-my-application).
|
||||
Since 1.92, with an updated backend, you can set `style.FontScaleDpi = your_content_scale;` to scale all fonts.
|
||||
<BR>You can call `style.ScaleAllSizes(xxx)` at init time or every frame at the beginning of your main loop to scale sizes/paddings.
|
||||
<BR>Since 1.92, with an updated backend, macOS style pixel/backing style scale is automatically handled.
|
||||
<BR>See [FAQ entry](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#q-how-should-i-handle-dpi-in-my-application) for more details.
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
---------------------------------------
|
||||
|
||||
## Font Loading Instructions
|
||||
## Fonts Loading Instructions
|
||||
|
||||
**Select base size**
|
||||
```cpp
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
style.FontSizeBase = 20.0f;
|
||||
```
|
||||
|
||||
**Load default font:**
|
||||
```cpp
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.Fonts->AddFontDefault();
|
||||
io.Fonts->AddFontDefaultVector(); // Load embedded scalable font.
|
||||
```
|
||||
```cpp
|
||||
io.Fonts->AddFontDefaultBitmap(); // Load embedded bitmap font (legacy).
|
||||
```
|
||||
```cpp
|
||||
io.Fonts->AddFontDefault(); // Load embedded font (legacy: auto-selected between the two above).
|
||||
```
|
||||
|
||||
|
||||
**Load .TTF/.OTF file with:**
|
||||
|
||||
🆕 **Since 1.92, with an up to date backend: passing a size is not necessary**
|
||||
```cpp
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.Fonts->AddFontFromFileTTF("font.ttf");
|
||||
```
|
||||
:rewind: **Before 1.92, or without an up to date backend:**
|
||||
```cpp
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels);
|
||||
```
|
||||
If you get an assert stating "Could not load font file!", your font filename is likely incorrect. Read "[About filenames](#about-filenames)" carefully.
|
||||
|
||||
If you get an assert stating "Could not load font file!", your font filename is likely incorrect. Read [About filenames](#about-filenames) carefully.
|
||||
|
||||
**Load multiple fonts:**
|
||||
```cpp
|
||||
// Init
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImFont* font1 = io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels);
|
||||
ImFont* font2 = io.Fonts->AddFontFromFileTTF("anotherfont.otf", size_pixels);
|
||||
ImFont* font1 = io.Fonts->AddFontFromFileTTF("font.ttf",);
|
||||
ImFont* font2 = io.Fonts->AddFontFromFileTTF("anotherfont.otf");
|
||||
```
|
||||
|
||||
In your application loop, select which font to use:
|
||||
```cpp
|
||||
// In application loop: select font at runtime
|
||||
ImGui::Text("Hello"); // use the default font (which is the first loaded font)
|
||||
ImGui::PushFont(font2);
|
||||
ImGui::PushFont(font2, 0.0f); // change font, keep current size
|
||||
ImGui::Text("Hello with another font");
|
||||
ImGui::PopFont();
|
||||
```
|
||||
|
||||
|
||||
**For advanced options create a ImFontConfig structure and pass it to the AddFont() function (it will be copied internally):**
|
||||
```cpp
|
||||
ImFontConfig config;
|
||||
config.OversampleH = 2;
|
||||
config.OversampleV = 1;
|
||||
config.GlyphExtraSpacing.x = 1.0f;
|
||||
config.OversampleH = 1.0f;
|
||||
ImFont* font = io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, &config);
|
||||
```
|
||||
|
||||
|
||||
**Combine multiple fonts into one:**
|
||||
|
||||
🆕 **Since 1.92, with an up to date backend: specifying glyph ranges is unnecessary.**
|
||||
```cpp
|
||||
// Load a first font
|
||||
ImFont* font = io.Fonts->AddFontDefaultVector();
|
||||
ImFontConfig config;
|
||||
config.MergeMode = true;
|
||||
io.Fonts->AddFontFromFileTTF("DroidSans.ttf", 0.0f, &config); // Merge into first font to add e.g. Asian characters
|
||||
io.Fonts->AddFontFromFileTTF("fontawesome-webfont.ttf", 0.0f, &config); // Merge into first font to add Icons
|
||||
```
|
||||
:rewind: **Before 1.92, or without an up to date backend:**
|
||||
```cpp
|
||||
// Load a first font
|
||||
ImFont* font = io.Fonts->AddFontDefault();
|
||||
@@ -111,56 +194,91 @@ io.Fonts->Build();
|
||||
|
||||
**Add a fourth parameter to bake specific font ranges only:**
|
||||
|
||||
🆕 **Since 1.92, with an up to date backend: specifying glyph ranges is unnecessary. All the GetGlyphRangesXXX() functions are marked obsolete.**
|
||||
```cpp
|
||||
// Basic Latin, Extended Latin
|
||||
io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, NULL, io.Fonts->GetGlyphRangesDefault());
|
||||
io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, nullptr, io.Fonts->GetGlyphRangesDefault());
|
||||
|
||||
// Default + Selection of 2500 Ideographs used by Simplified Chinese
|
||||
io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, NULL, io.Fonts->GetGlyphRangesChineseSimplifiedCommon());
|
||||
io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, nullptr, io.Fonts->GetGlyphRangesChineseSimplifiedCommon());
|
||||
|
||||
// Default + Hiragana, Katakana, Half-Width, Selection of 1946 Ideographs
|
||||
io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, NULL, io.Fonts->GetGlyphRangesJapanese());
|
||||
io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, nullptr, io.Fonts->GetGlyphRangesJapanese());
|
||||
```
|
||||
See [Using Custom Glyph Ranges](#using-custom-glyph-ranges) section to create your own ranges.
|
||||
|
||||
|
||||
**Example loading and using a Japanese font:**
|
||||
|
||||
🆕 **Since 1.92, with an up to date backend:**
|
||||
```cpp
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.Fonts->AddFontFromFileTTF("NotoSansCJKjp-Medium.otf", 20.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
|
||||
io.Fonts->AddFontFromFileTTF("NotoSansCJKjp-Medium.otf");
|
||||
```
|
||||
|
||||
:rewind: **Before 1.92, or without an up to date backend:**
|
||||
```cpp
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.Fonts->AddFontFromFileTTF("NotoSansCJKjp-Medium.otf", 20.0f, nullptr, io.Fonts->GetGlyphRangesJapanese());
|
||||
```
|
||||
|
||||
```cpp
|
||||
ImGui::Text(u8"こんにちは!テスト %d", 123);
|
||||
if (ImGui::Button(u8"ロード"))
|
||||
{
|
||||
// do stuff
|
||||
}
|
||||
ImGui::InputText("string", buf, IM_ARRAYSIZE(buf));
|
||||
ImGui::InputText("string", buf, IM_COUNTOF(buf));
|
||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
|
||||
```
|
||||
|
||||

|
||||
<br>_(settings: Dark style (left), Light style (right) / Font: NotoSansCJKjp-Medium, 20px / Rounding: 5)_
|
||||
|
||||
**Font Atlas too large?**
|
||||
##### [Return to Index](#index)
|
||||
|
||||
- If you have very large number of glyphs or multiple fonts, the texture may become too big for your graphics API. The typical result of failing to upload a texture is if every glyphs appears as white rectangles.
|
||||
- Mind the fact that some graphics drivers have texture size limitation. If you are building a PC application, mind the fact that your users may use hardware with lower limitations than yours.
|
||||
---------------------------------------
|
||||
|
||||
Some solutions:
|
||||
## Loading Font Data from Memory
|
||||
|
||||
1. Reduce glyphs ranges by calculating them from source localization data.
|
||||
You can use the `ImFontGlyphRangesBuilder` for this purpose and rebuilding your atlas between frames when new characters are needed. This will be the biggest win!
|
||||
2. You may reduce oversampling, e.g. `font_config.OversampleH = 2`, this will largely reduce your texture size.
|
||||
Note that while OversampleH = 2 looks visibly very close to 3 in most situations, with OversampleH = 1 the quality drop will be noticeable.
|
||||
3. Set `io.Fonts.TexDesiredWidth` to specify a texture width to minimize texture height (see comment in `ImFontAtlas::Build()` function).
|
||||
4. Set `io.Fonts.Flags |= ImFontAtlasFlags_NoPowerOfTwoHeight;` to disable rounding the texture height to the next power of two.
|
||||
5. Read about oversampling [here](https://github.com/nothings/stb/blob/master/tests/oversample).
|
||||
6. To support the extended range of unicode beyond 0xFFFF (e.g. emoticons, dingbats, symbols, shapes, ancient languages, etc...) add `#define IMGUI_USE_WCHAR32`in your `imconfig.h`.
|
||||
```cpp
|
||||
ImFont* font = io.Fonts->AddFontFromMemoryTTF(data, data_size, size_pixels, ...);
|
||||
```
|
||||
|
||||
IMPORTANT: `AddFontFromMemoryTTF()` by default transfer ownership of the data buffer to the font atlas, which will attempt to free it on destruction.
|
||||
This was to avoid an unnecessary copy, and is perhaps not a good API (a future version will redesign it).
|
||||
If you want to keep ownership of the data and free it yourself, you need to clear the `FontDataOwnedByAtlas` field:
|
||||
|
||||
```cpp
|
||||
ImFontConfig font_cfg;
|
||||
font_cfg.FontDataOwnedByAtlas = false;
|
||||
ImFont* font = io.Fonts->AddFontFromMemoryTTF(data, data_size, size_pixels, &font_cfg);
|
||||
```
|
||||
IMPORTANT: Since 1.92, when using `FontDataOwnedByAtlas = false`, font data needs to available until `atlas->RemoveFont()`, or more typically until a shutdown of the owning context or font atlas. It was not immediately noticeable in 1.92.0 due to a bug in handling `FontDataOwnedByAtlas = false`, which was fixed in 1.92.6.
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
---------------------------------------
|
||||
|
||||
## Loading Font Data Embedded In Source Code
|
||||
|
||||
- Compile and use [binary_to_compressed_c.cpp](https://github.com/ocornut/imgui/blob/master/misc/fonts/binary_to_compressed_c.cpp) to create a compressed C style array that you can embed in source code.
|
||||
- See the documentation in [binary_to_compressed_c.cpp](https://github.com/ocornut/imgui/blob/master/misc/fonts/binary_to_compressed_c.cpp) for instructions on how to use the tool.
|
||||
- You may find a precompiled version binary_to_compressed_c.exe for Windows inside the demo binaries package (see [README](https://github.com/ocornut/imgui/blob/master/docs/README.md)).
|
||||
- The tool can optionally output Base85 encoding to reduce the size of _source code_ but the read-only arrays in the actual binary will be about 20% bigger.
|
||||
|
||||
Then load the font with:
|
||||
```cpp
|
||||
ImFont* font = io.Fonts->AddFontFromMemoryCompressedTTF(compressed_data, compressed_data_size, size_pixels, ...);
|
||||
```
|
||||
or
|
||||
```cpp
|
||||
ImFont* font = io.Fonts->AddFontFromMemoryCompressedBase85TTF(compressed_data_base85, size_pixels, ...);
|
||||
```
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
---------------------------------------
|
||||
|
||||
## Using Icon Fonts
|
||||
|
||||
Using an icon font (such as [FontAwesome](http://fontawesome.io) or [OpenFontIcons](https://github.com/traverseda/OpenFontIcons)) is an easy and practical way to use icons in your Dear ImGui application.
|
||||
@@ -170,11 +288,23 @@ To refer to the icon UTF-8 codepoints from your C++ code, you may use those head
|
||||
|
||||
So you can use `ICON_FA_SEARCH` as a string that will render as a "Search" icon.
|
||||
|
||||
🆕 **Since 1.92, with an up to date backend: specifying glyph ranges is unnecessary. You can omit this parameter.**
|
||||
Example Setup:
|
||||
```cpp
|
||||
// Merge icons into default tool font
|
||||
#include "IconsFontAwesome.h"
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.Fonts->AddFontDefaultVector();
|
||||
ImFontConfig config;
|
||||
config.MergeMode = true;
|
||||
config.GlyphMinAdvanceX = 13.0f; // Use if you want to make the icon monospaced
|
||||
io.Fonts->AddFontFromFileTTF("fonts/fontawesome-webfont.ttf", 13.0f, &config);
|
||||
```
|
||||
:rewind: **Before 1.92:**
|
||||
```cpp
|
||||
// Merge icons into default tool font
|
||||
#include "IconsFontAwesome.h"
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.Fonts->AddFontDefault();
|
||||
|
||||
ImFontConfig config;
|
||||
@@ -193,24 +323,73 @@ ImGui::Button(ICON_FA_SEARCH " Search");
|
||||
```
|
||||
See Links below for other icons fonts and related tools.
|
||||
|
||||
**Monospace Icons?**
|
||||
|
||||
To make your icon look more monospace and facilitate alignment, you may want to set the `ImFontConfig::GlyphMinAdvanceX` value when loading an icon font.
|
||||
If you `GlyphMinAdvanceX` you need to pass a `font_size` to `AddFontXXX()` calls, as the MinAdvanceX value will be specified for the given size and scaled otherwise.
|
||||
|
||||
**Screenshot**
|
||||
|
||||
Here's an application using icons ("Avoyd", https://www.avoyd.com):
|
||||

|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
---------------------------------------
|
||||
|
||||
### Excluding Overlapping Ranges
|
||||
|
||||
🆕 **Since 1.92, with an up to date backend: glyphs ranges are ignored**: when loading a glyph, input fonts in the merge list are queried in order. The first font which has the glyph loads it.
|
||||
<BR>‼️ **If you are merging several fonts, you may have undesirable overlapping ranges.** You can use `ImFontConfig::GlyphExcludeRanges[] `to specify ranges to ignore in a given Input.
|
||||
|
||||
```cpp
|
||||
// Add Font Source 1 but ignore ICON_MIN_FA..ICON_MAX_FA range
|
||||
static ImWchar exclude_ranges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 };
|
||||
ImFontConfig cfg1;
|
||||
cfg1.GlyphExcludeRanges = exclude_ranges;
|
||||
io.Fonts->AddFontFromFileTTF("segoeui.ttf", 0.0f, &cfg1);
|
||||
|
||||
// Add Font Source 2, which expects to use the range above
|
||||
ImFontConfig cfg2;
|
||||
cfg2.MergeMode = true;
|
||||
io.Fonts->AddFontFromFileTTF("FontAwesome4.ttf", 0.0f, &cfg2);
|
||||
```
|
||||
Another (silly) example:
|
||||
```cpp
|
||||
// Remove 'A'-'Z' from first font
|
||||
static ImWchar exclude_ranges[] = { 'A', 'Z', 0 };
|
||||
ImFontConfig cfg1;
|
||||
cfg1.GlyphExcludeRanges = exclude_ranges;
|
||||
io.Fonts->AddFontFromFileTTF("segoeui.ttf", 0.0f, &cfg1);
|
||||
|
||||
// Load another font to fill the gaps
|
||||
ImFontConfig cfg2;
|
||||
cfg2.MergeMode = true;
|
||||
io.Fonts->AddFontFromFileTTF("Roboto-Medium.ttf", 0.0f, &cfg2);
|
||||
```
|
||||

|
||||
|
||||
You can use `Metrics/Debugger->Fonts->Font->Input Glyphs Overlap Detection Tool` to see list of glyphs available in multiple font sources. This can facilitate understanding which font input is providing which glyph.
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
---------------------------------------
|
||||
|
||||
## Using FreeType Rasterizer (imgui_freetype)
|
||||
|
||||
- Dear ImGui uses imstb\_truetype.h to rasterize fonts (with optional oversampling). This technique and its implementation are not ideal for fonts rendered at small sizes, which may appear a little blurry or hard to read.
|
||||
- There is an implementation of the ImFontAtlas builder using FreeType that you can use in the [misc/freetype/](https://github.com/ocornut/imgui/tree/master/misc/freetype) folder.
|
||||
- FreeType supports auto-hinting which tends to improve the readability of small fonts.
|
||||
- Dear ImGui uses [stb_truetype.h](https://github.com/nothings/stb/) to rasterize fonts (with optional oversampling). This technique and its implementation are not ideal for fonts rendered at small sizes, which may appear a little blurry or hard to read.
|
||||
- You can however use `imgui_freetype.cpp` from the [misc/freetype/](https://github.com/ocornut/imgui/tree/master/misc/freetype) folder. Compile with this file and add `#define IMGUI_ENABLE_FREETYPE` to your imconfig.h file or build system to automatically activate it.
|
||||
- FreeType supports auto-hinting which tends to improve the readability of small fonts. It makes a big difference especially at smaller resolutions.
|
||||
- Read documentation in the [misc/freetype/](https://github.com/ocornut/imgui/tree/master/misc/freetype) folder.
|
||||
- Correct sRGB space blending will have an important effect on your font rendering quality.
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
---------------------------------------
|
||||
|
||||
## Using Colorful Glyphs/Emojis
|
||||
|
||||
- Rendering of colored emojis is only supported by imgui_freetype with FreeType 2.10+.
|
||||
- Rendering of colored emojis is supported by imgui_freetype with FreeType 2.10+.
|
||||
- You will need to load fonts with the `ImGuiFreeTypeBuilderFlags_LoadColor` flag.
|
||||
- Emojis are frequently encoded in upper Unicode layers (character codes >0x10000) and will need dear imgui compiled with `IMGUI_USE_WCHAR32`.
|
||||
- Not all types of color fonts are supported by FreeType at the moment.
|
||||
@@ -222,17 +401,20 @@ Here's an application using icons ("Avoyd", https://www.avoyd.com):
|
||||
io.Fonts->AddFontFromFileTTF("../../../imgui_dev/data/fonts/NotoSans-Regular.ttf", 16.0f);
|
||||
static ImWchar ranges[] = { 0x1, 0x1FFFF, 0 };
|
||||
static ImFontConfig cfg;
|
||||
cfg.OversampleH = cfg.OversampleV = 1;
|
||||
cfg.MergeMode = true;
|
||||
cfg.FontBuilderFlags |= ImGuiFreeTypeBuilderFlags_LoadColor;
|
||||
io.Fonts->AddFontFromFileTTF("C:\\Windows\\Fonts\\seguiemj.ttf", 16.0f, &cfg, ranges);
|
||||
cfg.FontLoaderFlags |= ImGuiFreeTypeLoaderFlags_LoadColor;
|
||||
io.Fonts->AddFontFromFileTTF("C:\\Windows\\Fonts\\seguiemj.ttf", 16.0f, &cfg);
|
||||
```
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
---------------------------------------
|
||||
|
||||
## Using Custom Glyph Ranges
|
||||
|
||||
You can use the `ImFontGlyphRangesBuilder` helper to create glyph ranges based on text input. For example: for a game where your script is known, if you can feed your entire script to it and only build the characters the game needs.
|
||||
🆕 **Since 1.92, with an up to date backend: specifying glyph ranges is unnecessary. Therefore this is not really useful any more.**
|
||||
|
||||
:rewind: You can use the `ImFontGlyphRangesBuilder` helper to create glyph ranges based on text input. For example: for a game where your script is known, if you can feed your entire script to it and only build the characters the game needs.
|
||||
```cpp
|
||||
ImVector<ImWchar> ranges;
|
||||
ImFontGlyphRangesBuilder builder;
|
||||
@@ -241,24 +423,35 @@ builder.AddChar(0x7262); // Add a specific charact
|
||||
builder.AddRanges(io.Fonts->GetGlyphRangesJapanese()); // Add one of the default ranges
|
||||
builder.BuildRanges(&ranges); // Build the final result (ordered ranges with all the unique characters submitted)
|
||||
|
||||
io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, ranges.Data);
|
||||
io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, nullptr, ranges.Data);
|
||||
io.Fonts->Build(); // Build the atlas while 'ranges' is still in scope and not deleted.
|
||||
```
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
---------------------------------------
|
||||
|
||||
## Using Custom Colorful Icons
|
||||
|
||||
🆕 **Since 1.92, with an up to date backend: this system has been revamped.**
|
||||
|
||||
TL;DR; With the new system, it is recommended that you create a custom `ImFontLoader` and register your fonts with it.
|
||||
`AddCustomRectFontGlyph()` has been obsoleted because its API does not make much sense with resizable fonts.
|
||||
|
||||
You can ask questions in [#8466](https://github.com/ocornut/imgui/issues/8466).
|
||||
|
||||
:rewind: **Before 1.92:**
|
||||
|
||||
As an alternative to rendering colorful glyphs using imgui_freetype with `ImGuiFreeTypeBuilderFlags_LoadColor`, you may allocate your own space in the texture atlas and write yourself into it. **(This is a BETA api, use if you are familiar with dear imgui and with your rendering backend)**
|
||||
|
||||
- You can use the `ImFontAtlas::AddCustomRect()` and `ImFontAtlas::AddCustomRectFontGlyph()` api to register rectangles that will be packed into the font atlas texture. Register them before building the atlas, then call Build()`.
|
||||
- You can then use `ImFontAtlas::GetCustomRectByIndex(int)` to query the position/size of your rectangle within the texture, and blit/copy any graphics data of your choice into those rectangles.
|
||||
- You can then use `ImFontAtlas::GetCustomRect(int)` to query the position/size of your rectangle within the texture, and blit/copy any graphics data of your choice into those rectangles.
|
||||
- This API is beta because it is likely to change in order to support multi-dpi (multiple viewports on multiple monitors with varying DPI scale).
|
||||
|
||||
#### Pseudo-code:
|
||||
```cpp
|
||||
// Add font, then register two custom 13x13 rectangles mapped to glyph 'a' and 'b' of this font
|
||||
ImFont* font = io.Fonts->AddFontDefault();
|
||||
ImFont* font = io.Fonts->AddFontDefaultVector();
|
||||
int rect_ids[2];
|
||||
rect_ids[0] = io.Fonts->AddCustomRectFontGlyph(font, 'a', 13, 13, 13+1);
|
||||
rect_ids[1] = io.Fonts->AddCustomRectFontGlyph(font, 'b', 13, 13, 13+1);
|
||||
@@ -267,14 +460,12 @@ rect_ids[1] = io.Fonts->AddCustomRectFontGlyph(font, 'b', 13, 13, 13+1);
|
||||
io.Fonts->Build();
|
||||
|
||||
// Retrieve texture in RGBA format
|
||||
unsigned char* tex_pixels = NULL;
|
||||
unsigned char* tex_pixels = nullptr;
|
||||
int tex_width, tex_height;
|
||||
io.Fonts->GetTexDataAsRGBA32(&tex_pixels, &tex_width, &tex_height);
|
||||
|
||||
for (int rect_n = 0; rect_n < IM_ARRAYSIZE(rect_ids); rect_n++)
|
||||
{
|
||||
int rect_id = rects_ids[rect_n];
|
||||
if (const ImFontAtlas::CustomRect* rect = io.Fonts->GetCustomRectByIndex(rect_id))
|
||||
for (int rect_n = 0; rect_n < IM_COUNTOF(rect_ids); rect_n++)
|
||||
if (const ImTextureRect* rect = io.Fonts->GetCustomRect(rect_ids[rect_n]))
|
||||
{
|
||||
// Fill the custom rectangle with red pixels (in reality you would draw/copy your bitmap data here!)
|
||||
for (int y = 0; y < rect->Height; y++)
|
||||
@@ -284,54 +475,109 @@ for (int rect_n = 0; rect_n < IM_ARRAYSIZE(rect_ids); rect_n++)
|
||||
*p++ = IM_COL32(255, 0, 0, 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
## Using Font Data Embedded In Source Code
|
||||
---------------------------------------
|
||||
|
||||
- Compile and use [binary_to_compressed_c.cpp](https://github.com/ocornut/imgui/blob/master/misc/fonts/binary_to_compressed_c.cpp) to create a compressed C style array that you can embed in source code.
|
||||
- See the documentation in [binary_to_compressed_c.cpp](https://github.com/ocornut/imgui/blob/master/misc/fonts/binary_to_compressed_c.cpp) for instruction on how to use the tool.
|
||||
- You may find a precompiled version binary_to_compressed_c.exe for Windows instead of demo binaries package (see [README](https://github.com/ocornut/imgui/blob/master/docs/README.md)).
|
||||
- The tool can optionally output Base85 encoding to reduce the size of _source code_ but the read-only arrays in the actual binary will be about 20% bigger.
|
||||
## About Filenames
|
||||
|
||||
Then load the font with:
|
||||
```cpp
|
||||
ImFont* font = io.Fonts->AddFontFromMemoryCompressedTTF(compressed_data, compressed_data_size, size_pixels, ...);
|
||||
```
|
||||
or
|
||||
```cpp
|
||||
ImFont* font = io.Fonts->AddFontFromMemoryCompressedBase85TTF(compressed_data_base85, size_pixels, ...);
|
||||
```
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
## About filenames
|
||||
|
||||
**Please note that many new C/C++ users have issues their files _because the filename they provide is wrong_.**
|
||||
**Please note that many new C/C++ users have issues loading their files _because the filename they provide is wrong_ due to incorrect assumption of what is the current directory.**
|
||||
|
||||
Two things to watch for:
|
||||
- Make sure your IDE/debugger settings starts your executable from the right working directory. In Visual Studio you can change your working directory in project `Properties > General > Debugging > Working Directory`. People assume that their execution will start from the root folder of the project, where by default it oftens start from the folder where object or executable files are stored.
|
||||
```cpp
|
||||
// Relative filename depends on your Working Directory when running your program!
|
||||
io.Fonts->AddFontFromFileTTF("MyImage01.jpg", ...);
|
||||
|
||||
// Load from the parent folder of your Working Directory
|
||||
io.Fonts->AddFontFromFileTTF("../MyImage01.jpg", ...);
|
||||
```
|
||||
- In C/C++ and most programming languages if you want to use a backslash `\` within a string literal, you need to write it double backslash `\\`. At it happens, Windows uses backslashes as a path separator, so be mindful.
|
||||
(1) In C/C++ and most programming languages if you want to use a backslash `\` within a string literal, you need to write it double backslash `\\`. At it happens, Windows uses backslashes as a path separator, so be mindful.
|
||||
```cpp
|
||||
io.Fonts->AddFontFromFileTTF("MyFiles\MyImage01.jpg", ...); // This is INCORRECT!!
|
||||
io.Fonts->AddFontFromFileTTF("MyFiles\\MyImage01.jpg", ...); // This is CORRECT
|
||||
```
|
||||
In some situations, you may also use `/` path separator under Windows.
|
||||
|
||||
(2) Make sure your IDE/debugger settings starts your executable from the right working (current) directory. In Visual Studio you can change your working directory in project `Properties > General > Debugging > Working Directory`. People assume that their execution will start from the root folder of the project, where by default it often starts from the folder where object or executable files are stored.
|
||||
```cpp
|
||||
io.Fonts->AddFontFromFileTTF("MyImage01.jpg", ...); // Relative filename depends on your Working Directory when running your program!
|
||||
io.Fonts->AddFontFromFileTTF("../MyImage01.jpg", ...); // Load from the parent folder of your Working Directory
|
||||
```
|
||||
##### [Return to Index](#index)
|
||||
|
||||
---------------------------------------
|
||||
|
||||
## About UTF-8 Encoding
|
||||
|
||||
**For non-ASCII characters display, a common user issue is not passing correctly UTF-8 encoded strings.**
|
||||
|
||||
(1) We provide a function `ImGui::DebugTextEncoding(const char* text)` which you can call to verify the content of your UTF-8 strings.
|
||||
This is a convenient way to confirm that your encoding is correct.
|
||||
|
||||
```cpp
|
||||
ImGui::SeparatorText("CORRECT");
|
||||
ImGui::DebugTextEncoding(u8"こんにちは");
|
||||
|
||||
ImGui::SeparatorText("INCORRECT");
|
||||
ImGui::DebugTextEncoding("こんにちは");
|
||||
```
|
||||

|
||||
|
||||
You can also find this tool under `Metrics/Debuggers->Tools->UTF-8 Encoding viewer` if you want to paste from clipboard, but this won't validate the UTF-8 encoding done by your compiler.
|
||||
|
||||
(2) To encode in UTF-8:
|
||||
|
||||
There are also compiler-specific ways to enforce UTF-8 encoding by default:
|
||||
|
||||
- Visual Studio compiler: `/utf-8` command-line flag.
|
||||
- Visual Studio compiler: `#pragma execution_character_set("utf-8")` inside your code.
|
||||
- Since May 2023 we have changed the Visual Studio projects of all our examples to use `/utf-8` ([see commit](https://github.com/ocornut/imgui/commit/513af1efc9080857bbd10000d98f98f2a0c96803)).
|
||||
|
||||
Or, since C++11, you can use the `u8"my text"` syntax to encode literal strings as UTF-8. e.g.:
|
||||
```cpp
|
||||
ImGui::Text(u8"hello");
|
||||
ImGui::Text(u8"こんにちは"); // this will always be encoded as UTF-8
|
||||
ImGui::Text("こんにちは"); // the encoding of this is depending on compiler settings/flags and may be incorrect.
|
||||
```
|
||||
|
||||
Since C++20, because the C++ committee hate its users, they decided to change the `u8""` syntax to not return `const char*` but a new type `const char8_t*` which doesn't cast to `const char*`.
|
||||
Because of type usage of `u8""` in C++20 is a little more tedious:
|
||||
```cpp
|
||||
ImGui::Text((const char*)u8"こんにちは");
|
||||
```
|
||||
However, you can disable this behavior completely using the compiler option [`/Zc:char8_t-`](https://learn.microsoft.com/en-us/cpp/build/reference/zc-char8-t?view=msvc-170) for MSVC and [`-fno-char8_t`](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1423r3.html) for Clang and GCC.
|
||||
##### [Return to Index](#index)
|
||||
|
||||
---------------------------------------
|
||||
|
||||
## Debug Tools
|
||||
|
||||
#### Metrics/Debugger->Fonts
|
||||
You can use the `Metrics/Debugger` window (available in `Demo>Tools`) to browse your fonts and understand what's going on if you have an issue. You can also reach it in `Demo->Tools->Style Editor->Fonts`. The same information are also available in the Style Editor under Fonts.
|
||||
|
||||

|
||||
|
||||
#### UTF-8 Encoding Viewer**
|
||||
You can use the `UTF-8 Encoding viewer` in `Metrics/Debugger` to verify the content of your UTF-8 strings. From C/C++ code, you can call `ImGui::DebugTextEncoding("my string");` function to verify that your UTF-8 encoding is correct.
|
||||
|
||||

|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
---------------------------------------
|
||||
|
||||
## Credits/Licenses For Fonts Included In Repository
|
||||
|
||||
Some fonts files are available in the `misc/fonts/` folder:
|
||||
Embedded in source code:
|
||||
|
||||
**ProggyClean.ttf**, by Tristan Grimmer
|
||||
<br>MIT License
|
||||
<br>(recommended loading setting: Size = 13.0, GlyphOffset.y = +1, PixelSnapH = true)
|
||||
<br>https://github.com/bluescan/proggyfonts
|
||||
|
||||
**ProggyForever.ttf**, by Disco Hello, Tristan Grimmer
|
||||
<BR>MIT License
|
||||
<BR>https://github.com/ocornut/proggyforever
|
||||
|
||||
Extra fonts files are available in the `misc/fonts/` folder.
|
||||
Compared to 2014 when they were first introduced, we now have better font support and we embed ProggyForever.
|
||||
I believe all the files here are unnecessary nowadays. You can find font yourself. They might eventually be removed.
|
||||
|
||||
**Roboto-Medium.ttf**, by Christian Robetson
|
||||
<br>Apache License 2.0
|
||||
@@ -346,15 +592,10 @@ Some fonts files are available in the `misc/fonts/` folder:
|
||||
<br>Apache License 2.0
|
||||
<br>https://www.fontsquirrel.com/fonts/droid-sans
|
||||
|
||||
**ProggyClean.ttf**, by Tristan Grimmer
|
||||
<br>MIT License
|
||||
<br>(recommended loading setting: Size = 13.0, GlyphOffset.y = +1)
|
||||
<br>http://www.proggyfonts.net/
|
||||
|
||||
**ProggyTiny.ttf**, by Tristan Grimmer
|
||||
<br>MIT License
|
||||
<br>(recommended loading setting: Size = 10.0, GlyphOffset.y = +1)
|
||||
<br>http://www.proggyfonts.net/
|
||||
<br>https://github.com/bluescan/proggyfonts
|
||||
|
||||
**Karla-Regular.ttf**, by Jonathan Pinhorn
|
||||
<br>SIL OPEN FONT LICENSE Version 1.1
|
||||
@@ -380,15 +621,14 @@ Some fonts files are available in the `misc/fonts/` folder:
|
||||
|
||||
#### MONOSPACE FONTS
|
||||
|
||||
Pixel Perfect:
|
||||
- Proggy Fonts, by Tristan Grimmer http://www.proggyfonts.net or http://upperbounds.net
|
||||
- Sweet16, Sweet16 Mono, by Martin Sedlak (Latin + Supplemental + Extended A) https://github.com/kmar/Sweet16Font (also include an .inl file to use directly in dear imgui.)
|
||||
<img width="1172" height="715" alt="image" src="https://github.com/user-attachments/assets/c9702534-4877-41c9-ae0d-252933c26ced" />
|
||||
|
||||
Regular:
|
||||
- Google Noto Mono Fonts https://www.google.com/get/noto/
|
||||
- Typefaces for source code beautification https://github.com/chrissimpkins/codeface
|
||||
- Programmation fonts http://s9w.github.io/font_compare/
|
||||
- Inconsolata http://www.levien.com/type/myfonts/inconsolata.html
|
||||
- Proggy Fonts, by Tristan Grimmer https://github.com/bluescan/proggyfonts
|
||||
- Sweet16, Sweet16 Mono, by Martin Sedlak (Latin + Supplemental + Extended A) https://github.com/kmar/Sweet16Font
|
||||
- Google Noto Mono Fonts: https://www.google.com/get/noto/
|
||||
- Typefaces for source code beautification: https://github.com/chrissimpkins/codeface
|
||||
- Programmation fonts: http://s9w.github.io/font_compare/
|
||||
- Inconsolata: http://www.levien.com/type/myfonts/inconsolata.html
|
||||
- Adobe Source Code Pro: Monospaced font family for ui & coding environments https://github.com/adobe-fonts/source-code-pro
|
||||
- Monospace/Fixed Width Programmer's Fonts http://www.lowing.org/fonts/
|
||||
|
||||
|
||||
223
docs/README.md
223
docs/README.md
@@ -1,55 +1,63 @@
|
||||
Dear ImGui
|
||||
=====
|
||||
[](https://github.com/ocornut/imgui/actions?workflow=build) [](https://github.com/ocornut/imgui/actions?workflow=static-analysis)
|
||||
|
||||
|
||||
<sub>(This library is available under a free and permissive license, but needs financial support to sustain its continued improvements. In addition to maintenance and stability there are many desirable features yet to be added. If your company is using Dear ImGui, please consider reaching out.)</sub>
|
||||
|
||||
Businesses: support continued development and maintenance via invoiced technical support, maintenance, sponsoring contracts:
|
||||
<br> _E-mail: contact @ dearimgui dot com_
|
||||
|
||||
Individuals: support continued development and maintenance [here](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=WGHNC6MBFLZ2S).
|
||||
|
||||
Also see [Sponsors](https://github.com/ocornut/imgui/wiki/Sponsors) page.
|
||||
<center><b><i>"Give someone state and they'll have a bug one day, but teach them how to represent state in two separate locations that have to be kept in sync and they'll have bugs for a lifetime."</i></b></center> <a href="https://twitter.com/rygorous/status/1507178315886444544">-ryg</a>
|
||||
|
||||
----
|
||||
|
||||
Dear ImGui is a **bloat-free graphical user interface library for C++**. It outputs optimized vertex buffers that you can render anytime in your 3D-pipeline enabled application. It is fast, portable, renderer agnostic and self-contained (no external dependencies).
|
||||
[](https://github.com/ocornut/imgui/actions?workflow=build) [](https://github.com/ocornut/imgui/actions?workflow=static-analysis) [](https://github.com/ocornut/imgui_test_engine/actions?workflow=tests)
|
||||
|
||||
Dear ImGui is designed to **enable fast iterations** and to **empower programmers** to create **content creation tools and visualization / debug tools** (as opposed to UI for the average end-user). It favors simplicity and productivity toward this goal, and lacks certain features normally found in more high-level libraries.
|
||||
<sub>(This library is available under a free and permissive license, but needs financial support to sustain its continued improvements. In addition to maintenance and stability there are many desirable features yet to be added. If your company is using Dear ImGui, please consider reaching out.)</sub>
|
||||
|
||||
Dear ImGui is particularly suited to integration in games engine (for tooling), real-time 3D applications, fullscreen applications, embedded applications, or any applications on consoles platforms where operating system features are non-standard.
|
||||
Businesses: support continued development and maintenance via invoiced sponsoring/support contracts:
|
||||
<br> _E-mail: contact @ dearimgui dot com_
|
||||
<br>Individuals: support continued development and maintenance [here](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=WGHNC6MBFLZ2S). Also see [Funding](https://github.com/ocornut/imgui/wiki/Funding) page.
|
||||
|
||||
| [Usage](#usage) - [How it works](#how-it-works) - [Releases & Changelogs](#releases--changelogs) - [Demo](#demo) - [Integration](#integration) |
|
||||
| [The Pitch](#the-pitch) - [Usage](#usage) - [How it works](#how-it-works) - [Releases & Changelogs](#releases--changelogs) - [Demo](#demo) - [Getting Started & Integration](#getting-started--integration) |
|
||||
:----------------------------------------------------------: |
|
||||
| [Upcoming changes](#upcoming-changes) - [Gallery](#gallery) - [Support, FAQ](#support-frequently-asked-questions-faq) - [How to help](#how-to-help) - [Sponsors](#sponsors) - [Credits](#credits) - [License](#license) |
|
||||
| [Wiki](https://github.com/ocornut/imgui/wiki) - [Languages & frameworks backends/bindings](https://github.com/ocornut/imgui/wiki/Bindings) - [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) - [User quotes](https://github.com/ocornut/imgui/wiki/Quotes) |
|
||||
| [Gallery](#gallery) - [Support, FAQ](#support-frequently-asked-questions-faq) - [How to help](#how-to-help) - **[Funding & Sponsors](https://github.com/ocornut/imgui/wiki/Funding)** - [Credits](#credits) - [License](#license) |
|
||||
| [Wiki](https://github.com/ocornut/imgui/wiki) - [Extensions](https://github.com/ocornut/imgui/wiki/Useful-Extensions) - [Language bindings & framework backends](https://github.com/ocornut/imgui/wiki/Bindings) - [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) - [User quotes](https://github.com/ocornut/imgui/wiki/Quotes) |
|
||||
|
||||
### The Pitch
|
||||
|
||||
Dear ImGui is a **bloat-free graphical user interface library for C++**. It outputs optimized vertex buffers that you can render anytime in your 3D-pipeline-enabled application. It is fast, portable, renderer agnostic, and self-contained (no external dependencies).
|
||||
|
||||
Dear ImGui is designed to **enable fast iterations** and to **empower programmers** to create **content creation tools and visualization / debug tools** (as opposed to UI for the average end-user). It favors simplicity and productivity toward this goal and lacks certain features commonly found in more high-level libraries. Among other things, full internationalization (right-to-left text, bidirectional text, text shaping etc.) and accessibility features are not supported.
|
||||
|
||||
Dear ImGui is particularly suited to integration in game engines (for tooling), real-time 3D applications, fullscreen applications, embedded applications, or any applications on console platforms where operating system features are non-standard.
|
||||
|
||||
- Minimize state synchronization.
|
||||
- Minimize UI-related state storage on user side.
|
||||
- Minimize setup and maintenance.
|
||||
- Easy to use to create dynamic UI which are the reflection of a dynamic data set.
|
||||
- Easy to use to create code-driven and data-driven tools.
|
||||
- Easy to use to create ad hoc short-lived tools and long-lived, more elaborate tools.
|
||||
- Easy to hack and improve.
|
||||
- Portable, minimize dependencies, run on target (consoles, phones, etc.).
|
||||
- Efficient runtime and memory consumption.
|
||||
- Battle-tested, used by [many major actors in the game industry](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui).
|
||||
|
||||
### Usage
|
||||
|
||||
**The core of Dear ImGui is self-contained within a few platform-agnostic files** which you can easily compile in your application/engine. They are all the files in the root folder of the repository (imgui.cpp, imgui.h, imgui_demo.cpp, imgui_draw.cpp etc.).
|
||||
**The core of Dear ImGui is self-contained within a few platform-agnostic files** which you can easily compile in your application/engine. They are all the files in the root folder of the repository (`imgui*.cpp`, `imgui*.h`). **No specific build process is required**: you can add all files into your existing project.
|
||||
|
||||
**No specific build process is required**. You can add the .cpp files to your existing project.
|
||||
**Backends for a variety of graphics API and rendering platforms** are provided in the [backends/](https://github.com/ocornut/imgui/tree/master/backends) folder, along with example applications in the [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder. You may also create your own backend. Anywhere where you can render textured triangles, you can render Dear ImGui.
|
||||
|
||||
You will need a backend to integrate Dear ImGui in your app. The backend passes mouse/keyboard/gamepad inputs and variety of settings to Dear ImGui, and is in charge of rendering the resulting vertices.
|
||||
C++20 users wishing to use a module may the use [stripe2933/imgui-module](https://github.com/stripe2933/imgui-module) third-party extension.
|
||||
|
||||
**Backends for a variety of graphics api and rendering platforms** are provided in the [backends/](https://github.com/ocornut/imgui/tree/master/backends) folder, along with example applications in the [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder. See the [Integration](#integration) section of this document for details. You may also create your own backend. Anywhere where you can render textured triangles, you can render Dear ImGui.
|
||||
See the [Getting Started & Integration](#getting-started--integration) section of this document for more details.
|
||||
|
||||
After Dear ImGui is setup in your application, you can use it from \_anywhere\_ in your program loop:
|
||||
|
||||
Code:
|
||||
After Dear ImGui is set up in your application, you can use it from \_anywhere\_ in your program loop:
|
||||
```cpp
|
||||
ImGui::Text("Hello, world %d", 123);
|
||||
if (ImGui::Button("Save"))
|
||||
MySaveFunction();
|
||||
ImGui::InputText("string", buf, IM_ARRAYSIZE(buf));
|
||||
ImGui::InputText("string", buf, IM_COUNTOF(buf));
|
||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
|
||||
```
|
||||
Result:
|
||||
<br> 
|
||||
<br>_(settings: Dark style (left), Light style (right) / Font: Roboto-Medium, 16px)_
|
||||
<img width="412" height="236" alt="sample code output (dark)" src="https://github.com/user-attachments/assets/32b838df-6378-498b-84a8-9a79ee6264a7" />
|
||||
<img width="412" height="236" alt="sample code output (light)" src="https://github.com/user-attachments/assets/f075e2b0-98de-4be8-acb4-99ba0c9966cd" />
|
||||
|
||||
Code:
|
||||
```cpp
|
||||
// Create a window called "My First Tool", with a menu bar.
|
||||
ImGui::Begin("My First Tool", &my_tool_active, ImGuiWindowFlags_MenuBar);
|
||||
@@ -65,12 +73,14 @@ if (ImGui::BeginMenuBar())
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
|
||||
// Edit a color (stored as ~4 floats)
|
||||
// Edit a color stored as 4 floats
|
||||
ImGui::ColorEdit4("Color", my_color);
|
||||
|
||||
// Plot some values
|
||||
const float my_values[] = { 0.2f, 0.1f, 1.0f, 0.5f, 0.9f, 2.2f };
|
||||
ImGui::PlotLines("Frame Times", my_values, IM_ARRAYSIZE(my_values));
|
||||
// Generate samples and plot them
|
||||
float samples[100];
|
||||
for (int n = 0; n < 100; n++)
|
||||
samples[n] = sinf(n * 0.2f + ImGui::GetTime() * 1.5f);
|
||||
ImGui::PlotLines("Samples", samples, 100);
|
||||
|
||||
// Display contents in a scrolling region
|
||||
ImGui::TextColored(ImVec4(1,1,0,1), "Important Stuff");
|
||||
@@ -80,154 +90,139 @@ for (int n = 0; n < 50; n++)
|
||||
ImGui::EndChild();
|
||||
ImGui::End();
|
||||
```
|
||||
Result:
|
||||
<br>
|
||||

|
||||
|
||||
Dear ImGui allows you to **create elaborate tools** as well as very short-lived ones. On the extreme side of short-livedness: using the Edit&Continue (hot code reload) feature of modern compilers you can add a few widgets to tweaks variables while your application is running, and remove the code a minute later! Dear ImGui is not just for tweaking values. You can use it to trace a running algorithm by just emitting text commands. You can use it along with your own reflection data to browse your dataset live. You can use it to expose the internals of a subsystem in your engine, to create a logger, an inspection tool, a profiler, a debugger, an entire game making editor/framework, etc.
|
||||
Dear ImGui allows you to **create elaborate tools** as well as very short-lived ones. On the extreme side of short-livedness: using the Edit&Continue (hot code reload) feature of modern compilers you can add a few widgets to tweak variables while your application is running, and remove the code a minute later! Dear ImGui is not just for tweaking values. You can use it to trace a running algorithm by just emitting text commands. You can use it along with your own reflection data to browse your dataset live. You can use it to expose the internals of a subsystem in your engine, to create a logger, an inspection tool, a profiler, a debugger, an entire game-making editor/framework, etc.
|
||||
|
||||
### How it works
|
||||
|
||||
Check out the Wiki's [About the IMGUI paradigm](https://github.com/ocornut/imgui/wiki#about-the-imgui-paradigm) section if you want to understand the core principles behind the IMGUI paradigm. An IMGUI tries to minimize superfluous state duplication, state synchronization and state retention from the user's point of view. It is less error prone (less code and less bugs) than traditional retained-mode interfaces, and lends itself to create dynamic user interfaces.
|
||||
The IMGUI paradigm through its API tries to minimize superfluous state duplication, state synchronization, and state retention from the user's point of view. It is less error-prone (less code and fewer bugs) than traditional retained-mode interfaces, and lends itself to creating dynamic user interfaces. Check out the Wiki's [About the IMGUI paradigm](https://github.com/ocornut/imgui/wiki#about-the-imgui-paradigm) section for more details.
|
||||
|
||||
Dear ImGui outputs vertex buffers and command lists that you can easily render in your application. The number of draw calls and state changes required to render them is fairly small. Because Dear ImGui doesn't know or touch graphics state directly, you can call its functions anywhere in your code (e.g. in the middle of a running algorithm, or in the middle of your own rendering process). Refer to the sample applications in the examples/ folder for instructions on how to integrate Dear ImGui with your existing codebase.
|
||||
|
||||
_A common misunderstanding is to mistake immediate mode gui for immediate mode rendering, which usually implies hammering your driver/GPU with a bunch of inefficient draw calls and state changes as the gui functions are called. This is NOT what Dear ImGui does. Dear ImGui outputs vertex buffers and a small list of draw calls batches. It never touches your GPU directly. The draw call batches are decently optimal and you can render them later, in your app or even remotely._
|
||||
_A common misunderstanding is to mistake immediate mode GUI for immediate mode rendering, which usually implies hammering your driver/GPU with a bunch of inefficient draw calls and state changes as the GUI functions are called. This is NOT what Dear ImGui does. Dear ImGui outputs vertex buffers and a small list of draw calls batches. It never touches your GPU directly. The draw call batches are decently optimal and you can render them later, in your app or even remotely._
|
||||
|
||||
### Releases & Changelogs
|
||||
|
||||
See [Releases](https://github.com/ocornut/imgui/releases) page.
|
||||
See [Releases](https://github.com/ocornut/imgui/releases) page for decorated Changelogs.
|
||||
Reading the changelogs is a good way to keep up to date with the things Dear ImGui has to offer, and maybe will give you ideas of some features that you've been ignoring until now!
|
||||
|
||||
### Demo
|
||||
|
||||
Calling the `ImGui::ShowDemoWindow()` function will create a demo window showcasing variety of features and examples. The code is always available for reference in `imgui_demo.cpp`.
|
||||
Calling the `ImGui::ShowDemoWindow()` function will create a demo window showcasing a variety of features and examples. The code is always available for reference in `imgui_demo.cpp`.
|
||||
- [imgui_explorer](https://pthom.github.io/imgui_explorer): Web version of the demo w/ source code browser, courtesy of [@pthom](https://github.com/pthom).
|
||||
|
||||

|
||||
|
||||
You should be able to build the examples from sources (tested on Windows/Mac/Linux). If you don't, let us know! If you want to have a quick look at some Dear ImGui features, you can download Windows binaries of the demo app here:
|
||||
- [imgui-demo-binaries-20210331.zip](https://www.dearimgui.org/binaries/imgui-demo-binaries-20210331.zip) (Windows, 1.83 WIP, built 2021/03/31, master branch) or [older demo binaries](https://www.dearimgui.org/binaries).
|
||||
|
||||
The demo applications are not DPI aware so expect some blurriness on a 4K screen. For DPI awareness in your application, you can load/reload your font at different scale, and scale your style with `style.ScaleAllSizes()` (see [FAQ](https://www.dearimgui.org/faq)).
|
||||
|
||||
### Integration
|
||||
|
||||
On most platforms and when using C++, **you should be able to use a combination of the [imgui_impl_xxxx](https://github.com/ocornut/imgui/tree/master/backends) backends without modification** (e.g. `imgui_impl_win32.cpp` + `imgui_impl_dx11.cpp`). If your engine supports multiple platforms, consider using more of the imgui_impl_xxxx files instead of rewriting them: this will be less work for you and you can get Dear ImGui running immediately. You can _later_ decide to rewrite a custom backend using your custom engine functions if you wish so.
|
||||
|
||||
Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/keyboard/gamepad inputs 2) uploading one texture to your GPU/render engine 3) providing a render function that can bind textures and render textured triangles. The [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder is populated with applications doing just that. If you are an experienced programmer at ease with those concepts, it should take you less than two hours to integrate Dear ImGui in your custom engine. **Make sure to spend time reading the [FAQ](https://www.dearimgui.org/faq), comments, and some of the examples/ application!**
|
||||
|
||||
Officially maintained backends/bindings (in repository):
|
||||
- Renderers: DirectX9, DirectX10, DirectX11, DirectX12, Metal, OpenGL/ES/ES2, Vulkan, WebGPU.
|
||||
- Platforms: GLFW, SDL2, Win32, Glut, OSX, Android.
|
||||
- Frameworks: Emscripten, Allegro5, Marmalade.
|
||||
|
||||
[Third-party backends/bindings](https://github.com/ocornut/imgui/wiki/Bindings) wiki page:
|
||||
- Languages: C, C# and: Beef, ChaiScript, Crystal, D, Go, Haskell, Haxe/hxcpp, Java, JavaScript, Julia, Kotlin, Lobster, Lua, Odin, Pascal, PureBasic, Python, Ruby, Rust, Swift...
|
||||
- Frameworks: AGS/Adventure Game Studio, Amethyst, Blender, bsf, Cinder, Cocos2d-x, Diligent Engine, Flexium, GML/Game Maker Studio2, GLEQ, Godot, GTK3+OpenGL3, Irrlicht Engine, LÖVE+LUA, Magnum, Monogame, NanoRT, nCine, Nim Game Lib, Nintendo 3DS & Switch (homebrew), Ogre, openFrameworks, OSG/OpenSceneGraph, Orx, Photoshop, px_render, Qt/QtDirect3D, SDL_Renderer, SFML, Sokol, Unity, Unreal Engine 4, vtk, VulkanHpp, VulkanSceneGraph, Win32 GDI, WxWidgets.
|
||||
- Note that C bindings ([cimgui](https://github.com/cimgui/cimgui)) are auto-generated, you can use its json/lua output to generate bindings for other languages.
|
||||
|
||||
[Useful Extensions/Widgets](https://github.com/ocornut/imgui/wiki/Useful-Extensions) wiki page:
|
||||
- Text editors, node editors, timeline editors, plotting, software renderers, remote network access, memory editors, gizmos etc.
|
||||
|
||||
Also see [Wiki](https://github.com/ocornut/imgui/wiki) for more links and ideas.
|
||||
|
||||
### Upcoming Changes
|
||||
|
||||
Some of the goals for 2021 are:
|
||||
- Work on Docking (see [#2109](https://github.com/ocornut/imgui/issues/2109), in public [docking](https://github.com/ocornut/imgui/tree/docking) branch)
|
||||
- Work on Multi-Viewport / Multiple OS windows. (see [#1542](https://github.com/ocornut/imgui/issues/1542), in public [docking](https://github.com/ocornut/imgui/tree/docking) branch looking for feedback)
|
||||
- Work on gamepad/keyboard controls. (see [#787](https://github.com/ocornut/imgui/issues/787))
|
||||
- Work on automation and testing system, both to test the library and end-user apps. (see [#435](https://github.com/ocornut/imgui/issues/435))
|
||||
- Make the examples look better, improve styles, improve font support, make the examples hi-DPI and multi-DPI aware.
|
||||
You should be able to build the examples from sources. If you don't, let us know! If you want to have a quick look at some Dear ImGui features, you can download Windows binaries of the demo app here:
|
||||
- [imgui-demo-binaries-20260225.zip](https://www.dearimgui.com/binaries/imgui-demo-binaries-20260225.zip) (Windows, 1.92.6, built 2026/02/25, master) or [older binaries](https://www.dearimgui.com/binaries).
|
||||
|
||||
### Gallery
|
||||
|
||||
For more user-submitted screenshots of projects using Dear ImGui, check out the [Gallery Threads](https://github.com/ocornut/imgui/issues/3488)!
|
||||
Examples projects using Dear ImGui: [Tracy](https://github.com/wolfpld/tracy) (profiler), [ImHex](https://github.com/WerWolv/ImHex) (hex editor/data analysis), [RemedyBG](https://remedybg.itch.io/remedybg) (debugger) and [hundreds of others](https://github.com/ocornut/imgui/wiki/Software-using-Dear-ImGui).
|
||||
|
||||
For more user-submitted screenshots of projects using Dear ImGui, check out the [Gallery Threads](https://github.com/ocornut/imgui/issues?q=label%3Agallery)!
|
||||
|
||||
For a list of third-party widgets and extensions, check out the [Useful Extensions/Widgets](https://github.com/ocornut/imgui/wiki/Useful-Extensions) wiki page.
|
||||
|
||||
Custom engine
|
||||
[](https://cloud.githubusercontent.com/assets/8225057/20628927/33e14cac-b329-11e6-80f6-9524e93b048a.png)
|
||||
| | |
|
||||
|--|--|
|
||||
| Custom engine [erhe](https://github.com/tksuoran/erhe) (docking branch)<BR>[](https://user-images.githubusercontent.com/994606/147875067-a848991e-2ad2-4fd3-bf71-4aeb8a547bcf.png) | Custom engine for [Wonder Boy: The Dragon's Trap](http://www.TheDragonsTrap.com) (2017)<BR>[](https://cloud.githubusercontent.com/assets/8225057/20628927/33e14cac-b329-11e6-80f6-9524e93b048a.png) |
|
||||
| Custom engine (untitled)<BR>[](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/editor_white.png) | Tracy Profiler ([github](https://github.com/wolfpld/tracy))<BR>[](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v176/tracy_profiler.png) |
|
||||
|
||||
Custom engine
|
||||
[](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/editor_white.png)
|
||||
### Getting Started & Integration
|
||||
|
||||
[Tracy Profiler](https://github.com/wolfpld/tracy)
|
||||

|
||||
See the [Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started) guide for details.
|
||||
|
||||
On most platforms and when using C++, **you should be able to use a combination of the [imgui_impl_xxxx](https://github.com/ocornut/imgui/tree/master/backends) backends without modification** (e.g. `imgui_impl_win32.cpp` + `imgui_impl_dx11.cpp`). If your engine supports multiple platforms, consider using more imgui_impl_xxxx files instead of rewriting them: this will be less work for you, and you can get Dear ImGui running immediately. You can _later_ decide to rewrite a custom backend using your custom engine functions if you wish so.
|
||||
|
||||
Integrating Dear ImGui within your custom engine is a matter of mainly 1) wiring mouse/keyboard/gamepad inputs 2) uploading a texture to your GPU/render engine 3) providing a render function that can create/update textures and render textured triangles. This is exactly what backends are doing.
|
||||
- The [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder is populated with applications setting up a window and using standard backends.
|
||||
- The [Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started) guide has instructions to integrate imgui into an existing application using standard backends. It should in theory take you less than an hour to integrate Dear ImGui into your existing codebase where support libraries are linked. Less if you read carefully.
|
||||
- The [Backends](https://github.com/ocornut/imgui/blob/master/docs/BACKENDS.md) guide explains what backends are doing, and has instructions to implement a custom backend. You can also refer to the source code of our ~20 backends to understand how they work.
|
||||
- Generally, **make sure to spend time reading the [FAQ](https://www.dearimgui.com/faq), comments, and the examples applications!**
|
||||
|
||||
Officially maintained backends (in repository):
|
||||
- Renderers: DirectX9, DirectX10, DirectX11, DirectX12, Metal, OpenGL/ES/ES2, SDL_GPU, SDL_Renderer2/3, Vulkan, WebGPU.
|
||||
- Platforms: GLFW, SDL2/SDL3, Win32, Glut, OSX, Android.
|
||||
- Frameworks: Allegro5, Emscripten.
|
||||
|
||||
[Third-party backends/bindings](https://github.com/ocornut/imgui/wiki/Bindings) wiki page:
|
||||
- Languages: C, C# and: Beef, ChaiScript, CovScript, Crystal, D, Go, Haskell, Haxe/hxcpp, Java, JavaScript, Julia, Kotlin, Lobster, Lua, Nim, Odin, Pascal, PureBasic, Python, ReaScript, Ruby, Rust, Swift, Zig...
|
||||
- Frameworks: AGS/Adventure Game Studio, Amethyst, Blender, bsf, Cinder, Cocos2d-x, Defold, Diligent Engine, Ebiten, Flexium, GML/Game Maker Studio, GLEQ, Godot, GTK3, Irrlicht Engine, JUCE, LÖVE+LUA, Mach Engine, Magnum, Marmalade, Monogame, NanoRT, nCine, Nim Game Lib, Nintendo 3DS/Switch/WiiU (homebrew), Ogre, openFrameworks, OSG/OpenSceneGraph, Orx, Photoshop, px_render, Qt/QtDirect3D, raylib, SFML, Sokol, Unity, Unreal Engine 4/5, UWP, vtk, VulkanHpp, VulkanSceneGraph, Win32 GDI, WxWidgets.
|
||||
- Many bindings are auto-generated (by good old [cimgui](https://github.com/cimgui/cimgui) or our newer [dear_bindings](https://github.com/dearimgui/dear_bindings)), you can use their metadata output to generate bindings for other languages.
|
||||
|
||||
[Useful Extensions/Widgets](https://github.com/ocornut/imgui/wiki/Useful-Extensions) wiki page:
|
||||
|
||||
[](https://github.com/ocornut/imgui/wiki/Useful-Extensions)
|
||||
- Automation/testing, Text editors, node editors, timeline editors, plotting, software renderers, remote network access, memory editors, gizmos, etc. Notable and well supported extensions include [ImPlot](https://github.com/epezent/implot), [ImPlot3d](https://github.com/brenocq/implot3d) and [Dear ImGui Test Engine](https://github.com/ocornut/imgui_test_engine).
|
||||
|
||||
Also see [Wiki](https://github.com/ocornut/imgui/wiki) for more links and ideas.
|
||||
|
||||
### Support, Frequently Asked Questions (FAQ)
|
||||
|
||||
See: [Frequently Asked Questions (FAQ)](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md) where common questions are answered.
|
||||
|
||||
See: [Wiki](https://github.com/ocornut/imgui/wiki) for many links, references, articles.
|
||||
See: [Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started) and [Wiki](https://github.com/ocornut/imgui/wiki) for many links, references, articles.
|
||||
|
||||
See: [Articles about the IMGUI paradigm](https://github.com/ocornut/imgui/wiki#about-the-imgui-paradigm) to read/learn about the Immediate Mode GUI paradigm.
|
||||
|
||||
For questions, bug reports, requests, feedback, you may post on [GitHub Issues](https://github.com/ocornut/imgui/issues) or [GitHub Discussions](https://github.com/ocornut/imgui/discussions). Please read and fill the New Issue template carefully.
|
||||
See: [Upcoming Changes](https://github.com/ocornut/imgui/wiki/Upcoming-Changes).
|
||||
|
||||
See: [Dear ImGui Test Engine + Test Suite](https://github.com/ocornut/imgui_test_engine) for Automation & Testing.
|
||||
|
||||
For the purposes of getting search engines to crawl the wiki, here's a link to the [Crawlable Wiki](https://github-wiki-see.page/m/ocornut/imgui/wiki) (not for humans, [here's why](https://github-wiki-see.page/)).
|
||||
|
||||
Getting started? For first-time users having issues compiling/linking/running or issues loading fonts, please use [GitHub Discussions](https://github.com/ocornut/imgui/discussions). For ANY other questions, bug reports, requests, feedback, please post on [GitHub Issues](https://github.com/ocornut/imgui/issues). Please read and fill the New Issue template carefully.
|
||||
|
||||
Private support is available for paying business customers (E-mail: _contact @ dearimgui dot com_).
|
||||
|
||||
**Which version should I get?**
|
||||
|
||||
We occasionally tag [Releases](https://github.com/ocornut/imgui/releases) but it is generally safe and recommended to sync to master/latest. The library is fairly stable and regressions tend to be fixed fast when reported.
|
||||
|
||||
Advanced users may want to use the `docking` branch with [Multi-Viewport](https://github.com/ocornut/imgui/issues/1542) and [Docking](https://github.com/ocornut/imgui/issues/2109) features. This branch is kept in sync with master regularly.
|
||||
We occasionally tag [Releases](https://github.com/ocornut/imgui/releases) (with nice releases notes) but it is generally safe and recommended to sync to latest `master` or `docking` branch. The library is fairly stable and regressions tend to be fixed fast when reported. Advanced users may want to use the `docking` branch with [Multi-Viewport](https://github.com/ocornut/imgui/wiki/Multi-Viewports) and [Docking](https://github.com/ocornut/imgui/wiki/Docking) features. This branch is kept in sync with master regularly.
|
||||
|
||||
**Who uses Dear ImGui?**
|
||||
|
||||
See the [Quotes](https://github.com/ocornut/imgui/wiki/Quotes), [Sponsors](https://github.com/ocornut/imgui/wiki/Sponsors), [Software using dear imgui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) Wiki pages for an idea of who is using Dear ImGui. Please add your game/software if you can! Also see the [Gallery Threads](https://github.com/ocornut/imgui/issues/3488)!
|
||||
See the [Quotes](https://github.com/ocornut/imgui/wiki/Quotes), [Funding & Sponsors](https://github.com/ocornut/imgui/wiki/Funding), and [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) Wiki pages for an idea of who is using Dear ImGui. Please add your game/software if you can! Also, see the [Gallery Threads](https://github.com/ocornut/imgui/issues?q=label%3Agallery)!
|
||||
|
||||
How to help
|
||||
-----------
|
||||
|
||||
**How can I help?**
|
||||
|
||||
- See [GitHub Forum/issues](https://github.com/ocornut/imgui/issues) and [Github Discussions](https://github.com/ocornut/imgui/discussions).
|
||||
- You may help with development and submit pull requests! Please understand that by submitting a PR you are also submitting a request for the maintainer to review your code and then take over its maintenance forever. PR should be crafted both in the interest in the end-users and also to ease the maintainer into understanding and accepting it.
|
||||
- See [GitHub Forum/Issues](https://github.com/ocornut/imgui/issues).
|
||||
- You may help with development and submit pull requests! Please understand that by submitting a PR you are also submitting a request for the maintainer to review your code and then take over its maintenance forever. PR should be crafted both in the interest of the end-users and also to ease the maintainer into understanding and accepting it.
|
||||
- See [Help wanted](https://github.com/ocornut/imgui/wiki/Help-Wanted) on the [Wiki](https://github.com/ocornut/imgui/wiki/) for some more ideas.
|
||||
- Have your company financially support this project (please reach by e-mail)
|
||||
|
||||
**How can I help financing further development of Dear ImGui?**
|
||||
|
||||
See [Sponsors](https://github.com/ocornut/imgui/wiki/Sponsors) page.
|
||||
- Be a [Funding Supporter](https://github.com/ocornut/imgui/wiki/Funding)! Have your company financially support this project via invoiced sponsors/maintenance or by buying a license for [Dear ImGui Test Engine](https://github.com/ocornut/imgui_test_engine) (please reach out: contact AT dearimgui DOT com).
|
||||
|
||||
Sponsors
|
||||
--------
|
||||
|
||||
Ongoing Dear ImGui development is currently financially supported by users and private sponsors:
|
||||
|
||||
*Platinum-chocolate sponsors*
|
||||
- [Blizzard](https://careers.blizzard.com/en-us/openings/engineering/all/all/all/1), [Google](https://github.com/google/filament), [Nvidia](https://developer.nvidia.com/nvidia-omniverse)
|
||||
|
||||
*Double-chocolate and Salty caramel sponsors*
|
||||
- [Activision](https://careers.activision.com/c/programmingsoftware-engineering-jobs), [Aras Pranckevičius](https://aras-p.info), [Arkane Studios](https://www.arkane-studios.com), [Framefield](http://framefield.com), [Grinding Gear Games](https://www.grindinggear.com), [Kylotonn](https://www.kylotonn.com), [Next Level Games](https://www.nextlevelgames.com), [RAD Game Tools](http://www.radgametools.com/), [O-Net Communications (USA)](http://en.o-netcom.com), [Supercell](https://supercell.com), [Ubisoft](https://montreal.ubisoft.com/en/ubisoft-sponsors-user-interface-library-for-c-dear-imgui)
|
||||
|
||||
Please see [detailed list of Dear ImGui supporters](https://github.com/ocornut/imgui/wiki/Sponsors) for past sponsors.
|
||||
From November 2014 to December 2019, ongoing development has also been financially supported by its users on Patreon and through individual donations.
|
||||
Ongoing Dear ImGui development is and has been financially supported by users and private sponsors.
|
||||
<BR>Please see the **[detailed list of current and past Dear ImGui funding supporters and sponsors](https://github.com/ocornut/imgui/wiki/Funding)** for details.
|
||||
<BR>From November 2014 to December 2019, ongoing development has also been financially supported by its users on Patreon and through individual donations.
|
||||
|
||||
**THANK YOU to all past and present supporters for helping to keep this project alive and thriving!**
|
||||
|
||||
Dear ImGui is using software and services provided free of charge for open source projects:
|
||||
- [PVS-Studio](https://www.viva64.com/en/b/0570/) for static analysis.
|
||||
- [PVS-Studio](https://pvs-studio.com/en/pvs-studio/?utm_source=website&utm_medium=github&utm_campaign=open_source) for static analysis (supports C/C++/C#/Java).
|
||||
- [GitHub actions](https://github.com/features/actions) for continuous integration systems.
|
||||
- [OpenCppCoverage](https://github.com/OpenCppCoverage/OpenCppCoverage) for code coverage analysis.
|
||||
|
||||
Credits
|
||||
-------
|
||||
|
||||
Developed by [Omar Cornut](https://www.miracleworld.net) and every direct or indirect [contributors](https://github.com/ocornut/imgui/graphs/contributors) to the GitHub. The early version of this library was developed with the support of [Media Molecule](https://www.mediamolecule.com) and first used internally on the game [Tearaway](https://tearaway.mediamolecule.com) (PS Vita).
|
||||
Developed by [Omar Cornut](https://www.miracleworld.net) and every direct or indirect [contributors](https://github.com/ocornut/imgui/graphs/contributors) to the GitHub. The early version of this library was developed with the support of [Media Molecule](https://www.mediamolecule.com) and first used internally on the game [Tearaway](https://youtu.be/w0oxBviRGlU) (PS Vita).
|
||||
|
||||
Recurring contributors (2020): Omar Cornut [@ocornut](https://github.com/ocornut), Rokas Kupstys [@rokups](https://github.com/rokups), Ben Carter [@ShironekoBen](https://github.com/ShironekoBen).
|
||||
A large portion of work on automation systems, regression tests and other features are currently unpublished.
|
||||
Recurring contributors include Rokas Kupstys [@rokups](https://github.com/rokups) (2020-2022): a good portion of work on automation system and regression tests now available in [Dear ImGui Test Engine](https://github.com/ocornut/imgui_test_engine).
|
||||
|
||||
Sponsoring, support contracts and other B2B transactions are hosted and handled by [Lizardcube](https://www.lizardcube.com).
|
||||
Maintenance/support contracts, sponsoring invoices and other B2B transactions are hosted and handled by [Disco Hello](https://www.discohello.com).
|
||||
|
||||
Omar: "I first discovered the IMGUI paradigm at [Q-Games](https://www.q-games.com) where Atman Binstock had dropped his own simple implementation in the codebase, which I spent quite some time improving and thinking about. It turned out that Atman was exposed to the concept directly by working with Casey. When I moved to Media Molecule I rewrote a new library trying to overcome the flaws and limitations of the first one I've worked with. It became this library and since then I have spent an unreasonable amount of time iterating and improving it."
|
||||
|
||||
Embeds [ProggyClean.ttf](http://upperbounds.net) font by Tristan Grimmer (MIT license).
|
||||
Embeds [ProggyClean](https://www.proggyfonts.net) font by Tristan Grimmer (MIT license).
|
||||
<br>Embeds [ProggyForever](https://github.com/ocornut/proggyforever) fonts by Disco Hello, Tristan Grimmer (MIT license).
|
||||
<br>Embeds [stb_textedit.h, stb_truetype.h, stb_rect_pack.h](https://github.com/nothings/stb/) by Sean Barrett (public domain).
|
||||
|
||||
Embeds [stb_textedit.h, stb_truetype.h, stb_rect_pack.h](https://github.com/nothings/stb/) by Sean Barrett (public domain).
|
||||
|
||||
Inspiration, feedback, and testing for early versions: Casey Muratori, Atman Binstock, Mikko Mononen, Emmanuel Briney, Stefan Kamoda, Anton Mikhailov, Matt Willis. Also thank you to everyone posting feedback, questions and patches on GitHub.
|
||||
Inspiration, feedback, and testing for early versions: Casey Muratori, Atman Binstock, Mikko Mononen, Emmanuel Briney, Stefan Kamoda, Anton Mikhailov, Matt Willis. Special thanks to Alex Evans, Patrick Doane, Marco Koegler for kindly helping. Also thank you to everyone posting feedback, questions and patches on GitHub.
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
17
docs/SECURITY.md
Normal file
17
docs/SECURITY.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# Security Policy
|
||||
|
||||
Dear ImGui is primarily designed for developer tools and technical applications running trusted code and trusted data.
|
||||
|
||||
Given that the library was not designed as a hardened security boundary against hostile or intentionally malformed inputs:
|
||||
consider not using it in a context where a crash (through e.g. intentionally malformed inputs) could lead to privilege elevation.
|
||||
E.g. running in a privileged process and interacting with non-privileged clients feeding code or data to Dear ImGui.
|
||||
|
||||
Dear ImGui development efforts are focused on improving developer experience, usability, correctness, and robustness in real-world applications.
|
||||
We will do our best to reduce e.g. crashes caused by common programmer mistakes.
|
||||
|
||||
However, the project does not specifically focus on adversarial fuzzing scenarios, allocation-failure hardening, or highly artificial edge cases that are unlikely to occur in normal usage.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Considering the above policy, most things may be reported in GitHub Issues.
|
||||
If you have a reason to disclose privately, please reach out to the contact address listed in README.
|
||||
218
docs/TODO.txt
218
docs/TODO.txt
@@ -1,119 +1,91 @@
|
||||
dear imgui
|
||||
ISSUES & TODO LIST
|
||||
|
||||
Issue numbers (#) refer to github issues listed at https://github.com/ocornut/imgui/issues/XXXX
|
||||
Issue numbers (#) refer to GitHub issues listed at https://github.com/ocornut/imgui/issues/XXXX
|
||||
|
||||
THIS LIST IS NOT WELL MAINTAINED. MOST OF THE WORK HAPPENS ON GITHUB NOWADAYS.
|
||||
|
||||
The list below consist mostly of ideas noted down before they are requested/discussed by users (at which point they usually exist on the github issue tracker).
|
||||
It's mostly a bunch of personal notes, probably incomplete. Feel free to query if you have any questions.
|
||||
|
||||
- doc/test: add a proper documentation+regression testing system (#435)
|
||||
- doc/test: checklist app to verify backends/integration of imgui (test inputs, rendering, callback, etc.).
|
||||
- doc: checklist app to verify backends/integration of imgui (test inputs, rendering, callback, etc.).
|
||||
- doc: add a proper documentation system (maybe relying on automation? #435)
|
||||
- doc/tips: tips of the day: website? applet in imgui_club?
|
||||
- doc/wiki: work on the wiki https://github.com/ocornut/imgui/wiki
|
||||
|
||||
- window: preserve/restore relative focus ordering (persistent or not) (#2304) -> also see docking reference to same #.
|
||||
- window: preserve/restore relative focus ordering (persistent or not), and e.g. of multiple reappearing windows (#2304) -> also see docking reference to same #.
|
||||
- window: calling SetNextWindowSize() every frame with <= 0 doesn't do anything, may be useful to allow (particularly when used for a single axis). (#690)
|
||||
- window: add a way for very transient windows (non-saved, temporary overlay over hundreds of objects) to "clean" up from the global window list. perhaps a lightweight explicit cleanup pass.
|
||||
- window: auto-fit feedback loop when user relies on any dynamic layout (window width multiplier, column) appears weird to end-user. clarify.
|
||||
- window: begin with *p_open == false could return false.
|
||||
- window: get size/pos helpers given names (see discussion in #249)
|
||||
- window: a collapsed window can be stuck behind the main menu bar?
|
||||
- window: when window is very small, prioritize resize button over close button.
|
||||
- window: detect extra End() call that pop the "Debug" window out and assert at End() call site instead of at end of frame.
|
||||
- window: increase minimum size of a window with menus or fix the menu rendering so that it doesn't look odd.
|
||||
- window: double-clicking on title bar to minimize isn't consistent, perhaps move to single-click on left-most collapse icon?
|
||||
- window: double-clicking on title bar to minimize isn't consistent interaction, perhaps move to single-click on left-most collapse icon?
|
||||
- window: expose contents size. (#1045)
|
||||
- window: using SetWindowPos() inside Begin() and moving the window with the mouse reacts a very ugly glitch. We should just defer the SetWindowPos() call.
|
||||
- window: GetWindowSize() returns (0,0) when not calculated? (#1045)
|
||||
- window: investigate better auto-positioning for new windows.
|
||||
- window: top most window flag? (#2574)
|
||||
- window: top most window flag? more z-order control? (#2574)
|
||||
- window/size: manually triggered auto-fit (double-click on grip) shouldn't resize window down to viewport size?
|
||||
- window/size: how to allow to e.g. auto-size vertically to fit contents, but be horizontally resizable? Assuming SetNextWindowSize() is modified to treat -1.0f on each axis as "keep as-is" (would be good but might break erroneous code): Problem is UpdateWindowManualResize() and lots of code treat (window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0) together.
|
||||
- window/opt: freeze window flag: if not focused/hovered, return false, render with previous ImDrawList. and/or reduce refresh rate. -> this may require enforcing that it is illegal to submit contents if Begin returns false.
|
||||
- window/child: background options for child windows, border option (disable rounding).
|
||||
- window/child: allow resizing of child windows (possibly given min/max for each axis?.)
|
||||
- window/child: the first draw command of a child window could be moved into the current draw command of the parent window (unless child+tooltip?).
|
||||
- window/child: border could be emitted in parent as well.
|
||||
- window/child: allow SetNextWindowContentSize() to work on child windows.
|
||||
- window/clipping: some form of clipping when DisplaySize (or corresponding viewport) is zero.
|
||||
- window/tabbing: add a way to signify that a window or docked window requires attention (e.g. blinking title bar).
|
||||
- window/id_stack: add e.g. window->GetIDFromPath() with support for leading / and ../ (#1390, #331)
|
||||
! scrolling: exposing horizontal scrolling with Shift+Wheel even when scrollbar is disabled expose lots of issues (#2424, #1463)
|
||||
- window/tabbing: add a way to signify that a window or docked window requires attention (e.g. blinking title bar, trying to click behind a modal).
|
||||
- window/id_stack: add e.g. window->GetIDFromPath() with support for leading / and ../ (#1390, #331) -> model from test engine.
|
||||
|
||||
! scrolling: exposing horizontal scrolling with Shift+Wheel even when scrollbar is disabled expose various issues (#2424, #1463)
|
||||
- scrolling: while holding down a scrollbar, try to keep the same contents visible (at least while not moving mouse)
|
||||
- scrolling: allow immediately effective change of scroll after Begin() if we haven't appended items yet.
|
||||
- scrolling: forward mouse wheel scrolling to parent window when at the edge of scrolling limits? (useful for listbox,tables?)
|
||||
- scrolling/clipping: separator on the initial position of a window is not visible (cursorpos.y <= clippos.y). (2017-08-20: can't repro)
|
||||
- scrolling/style: shadows on scrollable areas to denote that there is more contents (see e.g. DaVinci Resolve ui)
|
||||
|
||||
- drawdata: make it easy to clone (or swap?) a full ImDrawData so user can easily save that data if they use threaded rendering. (e.g. #2646)
|
||||
! drawlist: add calctextsize func to facilitate consistent code from user pov (currently need to use ImGui or ImFont alternatives!)
|
||||
- drawlist: end-user probably can't call Clear() directly because we expect a texture to be pushed in the stack.
|
||||
- drawlist: maintaining bounding box per command would allow to merge draw command when clipping isn't relied on (typical non-scrolling window or non-overflowing column would merge with previous command).
|
||||
- drawlist: primitives/helpers to manipulate vertices post submission, so e.g. a quad/rect can be resized to fit later submitted content, _without_ using the ChannelSplit api
|
||||
- drawdata: make it easy to deep-copy (or swap?) a full ImDrawData so user can easily save that data if they use threaded rendering. (#1860 see ImDrawDataSnapshot)
|
||||
! drawlist: add CalcTextSize() func to facilitate consistent code from user pov (currently need to use ImGui or ImFont alternatives!)
|
||||
- drawlist: maintaining bounding box per command would allow to merge draw command when clipping isn't relied on (typical non-scrolling window or non-overflowing column would merge with previous command). (WIP branch)
|
||||
- drawlist: make it easier to toggle AA per primitive, so we can use e.g. non-AA fill + AA borders more naturally
|
||||
- drawlist: non-AA strokes have gaps between points (#593, #288), glitch especially on RenderCheckmark() and ColorPicker4().
|
||||
- drawlist: would be good to be able to deep copy of ImDrawData (we have a deep copy of ImDrawList now).
|
||||
- drawlist: rendering: provide a way for imgui to output to a single/global vertex buffer, re-order indices only at the end of the frame (ref: https://gist.github.com/floooh/10388a0afbe08fce9e617d8aefa7d302)
|
||||
- drawlist: callback: add an extra void* in ImDrawCallback to allow passing render-local data to the callback (would break API).
|
||||
- drawlist: callback: add an extra void* in ImDrawCallback to expose render state instead of pulling from Renderer_RenderState (would break API).
|
||||
- drawlist: AddRect vs AddLine position confusing (#2441)
|
||||
- drawlist: channel splitter should be external helper and not stored in ImDrawList.
|
||||
- drawlist: Add quadratic bezier curves? (#3127)
|
||||
- drawlist/opt: store rounded corners in texture to use 1 quad per corner (filled and wireframe) to lower the cost of rounding. (#1962)
|
||||
- drawlist/opt: AddRect() axis aligned pixel aligned (no-aa) could use 8 triangles instead of 16 and no normal calculation.
|
||||
- drawlist/opt: thick AA line could be doable in same number of triangles as 1.0 AA line by storing gradient+full color in atlas.
|
||||
|
||||
- main: find a way to preserve relative orders of multiple reappearing windows (so an app toggling between "modes" e.g. fullscreen vs all tools) won't lose relative ordering.
|
||||
- main: IsItemHovered() make it more consistent for various type of widgets, widgets with multiple components, etc. also effectively IsHovered() region sometimes differs from hot region, e.g tree nodes
|
||||
- main: IsItemHovered() info stored in a stack? so that 'if TreeNode() { Text; TreePop; } if IsHovered' return the hover state of the TreeNode?
|
||||
- items: IsItemHovered() info stored in a stack? so that 'if TreeNode() { Text; TreePop; } if IsHovered' return the hover state of the TreeNode?
|
||||
|
||||
- widgets: display mode: widget-label, label-widget (aligned on column or using fixed size), label-newline-tab-widget etc. (#395)
|
||||
- widgets: clean up widgets internal toward exposing everything and stabilizing imgui_internals.h.
|
||||
- widgets: add visuals for Disabled/ReadOnly mode and expose publicly (#211)
|
||||
- widgets: add always-allow-overlap mode. This should perhaps be the default? one problem is that highlight after mouse-wheel scrolling gets deferred, makes scrolling more flickery.
|
||||
- widgets: start exposing PushItemFlag() and ImGuiItemFlags
|
||||
- widgets: alignment options in style (e.g. center Selectable, Right-Align within Button, etc.) #1260
|
||||
- widgets: activate by identifier (trigger button, focus given id)
|
||||
- widgets: a way to represent "mixed" values, so e.g. all values replaced with *, including check-boxes, colors, etc. with support for multi-components widgets (e.g. SliderFloat3, make only "Y" mixed) (#2644)
|
||||
- widgets: checkbox: checkbox with custom glyph inside frame.
|
||||
- widgets: custom glyph/shapes replacements for stock shapes. (also #6090 #2431 #2235 #6517)
|
||||
- widgets: coloredit: keep reporting as active when picker is on?
|
||||
- widgets: group/scalarn functions: expose more per-component information. e.g. store NextItemData.ComponentIdx set by scalarn function, groups can expose them back somehow.
|
||||
- widgets: group/ScalarN functions: expose more per-component information. e.g. store NextItemData.ComponentIdx set by scalarn function, groups can expose them back somehow.
|
||||
- selectable: using (size.x == 0.0f) and (SelectableTextAlign.x > 0.0f) followed by SameLine() is currently not supported.
|
||||
- selectable: generic BeginSelectable()/EndSelectable() mechanism.
|
||||
- selectable: generic BeginSelectable()/EndSelectable() mechanism. (work out alongside range-select branch)
|
||||
- selectable: a way to visualize partial/mixed selection (e.g. parent tree node has children with mixed selection)
|
||||
|
||||
- input text: clean up the mess caused by converting UTF-8 <> wchar. the code is rather inefficient right now and super fragile.
|
||||
- input text: flag to disable live update of the user buffer (also applies to float/int text input) (#701)
|
||||
- input text: preserve scrolling when unfocused?
|
||||
- input text: reorganize event handling, allow CharFilter to modify buffers, allow multiple events? (#541)
|
||||
- input text: expose CursorPos in char filter event (#816)
|
||||
- input text: try usage idiom of using InputText with data only exposed through get/set accessors, without extraneous copy/alloc. (#3009)
|
||||
- input text: access public fields via a non-callback API e.g. InputTextGetState("xxx") that may return NULL if not active.
|
||||
- input text: flag to disable live update of the user buffer (also applies to float/int text input) (#701)
|
||||
- input text: hover tooltip could show unclamped text
|
||||
- input text: support for INSERT key to toggle overwrite mode. currently disabled because stb_textedit behavior is unsatisfactory on multi-line. (#2863)
|
||||
- input text: option to Tab after an Enter validation.
|
||||
- input text: add ImGuiInputTextFlags_EnterToApply? (off #218)
|
||||
- input text: easier ways to update buffer (from source char*) while owned. preserve some sort of cursor position for multi-line text.
|
||||
- input text: add flag (e.g. ImGuiInputTextFlags_EscapeClearsBuffer) to clear instead of revert. what to do with focus? (also see #2890)
|
||||
- input text: add discard flag (e.g. ImGuiInputTextFlags_DiscardActiveBuffer) or make it easier to clear active focus for text replacement during edition (#725)
|
||||
- input text: display bug when clicking a drag/slider after an input text in a different window has all-selected text (order dependent). actually a very old bug but no one appears to have noticed it.
|
||||
- input text: allow centering/positioning text so that ctrl+clicking Drag or Slider keeps the textual value at the same pixel position.
|
||||
- input text: decorrelate layout from inputs - e.g. what's the easiest way to implement a nice IP/Mac address input editor?
|
||||
- input text: global callback system so user can plug in an expression evaluator easily. (#1691)
|
||||
- input text: decorrelate display layout from inputs with custom template - e.g. what's the easiest way to implement a nice IP/Mac address input editor?
|
||||
- input text: callback system (global) so user can plug in an expression evaluator easily. (#1691)
|
||||
- input text: force scroll to end or scroll to a given line/contents (so user can implement a log or a search feature)
|
||||
- input text: a way to preview completion (e.g. disabled text completing from the cursor)
|
||||
- input text: a side bar that could e.g. preview where errors are. probably left to the user to draw but we'd need to give them the info there.
|
||||
- input text: a way for the user to provide syntax coloring.
|
||||
- input text: Shift+TAB with ImGuiInputTextFlags_AllowTabInput could eat preceding blanks, up to tab_count.
|
||||
- input text: facilitate patterns like if (InputText(..., obj.get_string_ref()) { obj.set_string(...); } relying on internally held buffer.
|
||||
- input text multi-line: don't directly call AddText() which does an unnecessary vertex reserve for character count prior to clipping. and/or more line-based clipping to AddText(). and/or reorganize TextUnformatted/RenderText for more efficiency for large text (e.g TextUnformatted could clip and log separately, etc).
|
||||
- input text multi-line: support for cut/paste without selection (cut/paste the current line)
|
||||
- input text multi-line: support for copy/cut without selection (copy/cut current line?)
|
||||
- input text multi-line: line numbers? status bar? (follow up on #200)
|
||||
- input text multi-line: behave better when user changes input buffer while editing is active (even though it is illegal behavior). namely, the change of buffer can create a scrollbar glitch (#725)
|
||||
- input text multi-line: better horizontal scrolling support (#383, #1224)
|
||||
- input text multi-line: single call to AddText() should be coarse clipped on InputTextEx() end.
|
||||
- input number: optional range min/max for Input*() functions
|
||||
- input number: holding [-]/[+] buttons could increase the step speed non-linearly (or user-controlled)
|
||||
- input number: use mouse wheel to step up/down
|
||||
- input number: applying arithmetics ops (+,-,*,/) messes up with text edit undo stack.
|
||||
|
||||
- layout: helper or a way to express ImGui::SameLine(ImGui::GetCursorStartPos().x + ImGui::CalcItemWidth() + ImGui::GetStyle().ItemInnerSpacing.x); in a simpler manner.
|
||||
- layout, font: horizontal tab support, A) text mode: forward only tabs (e.g. every 4 characters/N pixels from pos x1), B) manual mode: explicit tab stops acting as mini columns, no clipping (for menu items, many kind of uses, also vaguely relate to #267, #395)
|
||||
@@ -126,52 +98,34 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
|
||||
- layout: (R&D) local multi-pass layout mode.
|
||||
- layout: (R&D) bind authored layout data (created by an off-line tool), items fetch their pos/size at submission, self-optimize data structures to stable linear access.
|
||||
|
||||
- tables: see https://github.com/ocornut/imgui/issues/2957#issuecomment-569726095
|
||||
|
||||
- group: BeginGroup() needs a border option. (~#1496)
|
||||
- group: IsHovered() after EndGroup() covers whole aabb rather than the intersection of individual items. Is that desirable?
|
||||
- group: IsItemHovered() after EndGroup() covers whole AABB rather than the intersection of individual items. Is that desirable?
|
||||
- group: merge deactivation/activation within same group (fwd WasEdited flag). (#2550)
|
||||
|
||||
!- color: the color conversion helpers/types are a mess and needs sorting out.
|
||||
- color: (api breaking) ImGui::ColorConvertXXX functions should be loose ImColorConvertXX to match imgui_internals.h
|
||||
|
||||
- plot: full featured plot/graph api w/ scrolling, zooming etc. all bell & whistle. why not!
|
||||
- plot: PlotLines() should use the polygon-stroke facilities, less vertices (currently issues with averaging normals)
|
||||
- plot: make it easier for user to draw extra stuff into the graph (e.g: draw basis, highlight certain points, 2d plots, multiple plots)
|
||||
- plot: "smooth" automatic scale over time, user give an input 0.0(full user scale) 1.0(full derived from value)
|
||||
- plot: option/feature: draw the zero line
|
||||
- plot: option/feature: draw grid, vertical markers
|
||||
- plot: option/feature: draw unit
|
||||
- plot: add a helper e.g. Plot(char* label, float value, float time_span=2.0f) that stores values and Plot them for you - probably another function name. and/or automatically allow to plot ANY displayed value (more reliance on stable ID)
|
||||
|
||||
- clipper: ability to force display 1 item in the list would be convenient (for patterns where we need to set active id etc.)
|
||||
- clipper: ability to disable the clipping through a simple flag/bool.
|
||||
- clipper: ability to run without knowing full count in advance.
|
||||
- clipper: horizontal clipping support. (#2580)
|
||||
|
||||
- separator: expose flags (#759)
|
||||
- separator: take indent into consideration (optional)
|
||||
- separator: width, thickness, centering (#1643)
|
||||
- separator: width, thickness, centering (#1643, #2657)
|
||||
- splitter: formalize the splitter idiom into an official api (we want to handle n-way split) (#319)
|
||||
|
||||
- dock: merge docking branch (#2109)
|
||||
- dock: dock out from a collapsing header? would work nicely but need emitting window to keep submitting the code.
|
||||
- docking: merge docking branch (#2109)
|
||||
|
||||
- tabs: "there is currently a problem because TabItem() will try to submit their own tooltip after 0.50 second, and this will have the effect of making your tooltip flicker once." -> tooltip priority work
|
||||
- tabs: close button tends to overlap unsaved-document star
|
||||
- tabs: consider showing the star at the same spot as the close button, like VS Code does.
|
||||
- tabs: "there is currently a problem because TabItem() will try to submit their own tooltip after 0.50 second, and this will have the effect of making your tooltip flicker once." -> tooltip priority work (WIP branch)
|
||||
- tabs: make EndTabBar fail if users doesn't respect BeginTabBar return value, for consistency/future-proofing.
|
||||
- tabs: persistent order/focus in BeginTabBar() api (#261, #351)
|
||||
- tabs: TabItem could honor SetNextItemWidth()?
|
||||
- tabs: explicit api (even if internal) to cleanly manipulate tab order.
|
||||
- tabs: Mouse wheel over tab bar could scroll? (#2702)
|
||||
|
||||
- image/image button: misalignment on padded/bordered button?
|
||||
- image/image button: parameters are confusing, image() has tint_col,border_col whereas imagebutton() has bg_col/tint_col. Even thou they are different parameters ordering could be more consistent. can we fix that?
|
||||
- image button: not taking an explicit id can be problematic. (#2464, #1390)
|
||||
- button: provide a button that looks framed. (?)
|
||||
- slider/drag: ctrl+click when format doesn't include a % character.. disable? display underlying value in default format? (see TempInputTextScalar)
|
||||
- slider: allow using the [-]/[+] buttons used by InputFloat()/InputInt()
|
||||
- slider: initial absolute click is imprecise. change to relative movement slider (same as scrollbar). (#1946)
|
||||
- slider: add dragging-based widgets to edit values with mouse (on 2 axises), saving screen real-estate.
|
||||
- slider: add dragging-based widgets to edit values with mouse (on 2 axes), saving screen real-estate.
|
||||
- slider: tint background based on value (e.g. v_min -> v_max, or use 0.0f either side of the sign)
|
||||
- slider: relative dragging? + precision dragging
|
||||
- slider: step option (#1183)
|
||||
@@ -179,46 +133,36 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
|
||||
- knob: rotating knob widget (#942)
|
||||
- drag float: support for reversed drags (min > max) (removed is_locked, also see fdc526e)
|
||||
- drag float: up/down axis
|
||||
- drag float: power != 0.0f with current value being outside the range keeps the value stuck.
|
||||
- drag float: added leeway on edge (e.g. a few invisible steps past the clamp limits)
|
||||
|
||||
- combo: use clipper: make it easier to disable clipper with a single flag.
|
||||
- combo: flag for BeginCombo to not return true when unchanged (#1182)
|
||||
- combo: a way/helper to customize the combo preview (#1658)
|
||||
- combo: a way/helper to customize the combo preview (#1658) -> experimental BeginComboPreview()
|
||||
- combo/listbox: keyboard control. need InputText-like non-active focus + key handling. considering keyboard for custom listbox (pr #203)
|
||||
- listbox: multiple selection.
|
||||
- listbox: unselect option (#1208)
|
||||
- listbox: make it easier/more natural to implement range-select (need some sort of info/ref about the last clicked/focused item that user can translate to an index?) (wip stash)
|
||||
- listbox: user may want to initial scroll to focus on the one selected value?
|
||||
- listbox: expose hovered item for a simplified ListBox api
|
||||
- listbox: keyboard navigation.
|
||||
- listbox: disable capturing mouse wheel if the listbox has no scrolling. (#1681)
|
||||
- listbox: scrolling should track modified selection.
|
||||
- listbox: future api should allow to enable horizontal scrolling (#2510)
|
||||
|
||||
!- popups/menus: clarify usage of popups id, how MenuItem/Selectable closing parent popups affects the ID, etc. this is quite fishy needs improvement! (#331, #402)
|
||||
- modals: make modal title bar blink when trying to click outside the modal
|
||||
- modals: technically speaking, we could make Begin() with ImGuiWindowFlags_Modal work without involving popup. May help untangle a few things, as modals are more like regular windows than popups.
|
||||
- modals: make modal title bar blink when trying to click outside the modal.
|
||||
- modals: technically speaking, we could make Begin() with ImGuiWindowFlags_Modal work without involving popup. May help untangle a few things, as modals are more like regular windows than popups. (#402)
|
||||
- popups: if the popup functions took explicit ImGuiID it would allow the user to manage the scope of those ID. (#331)
|
||||
- popups: clicking outside (to close popup) and holding shouldn't drag window below.
|
||||
- popups: add variant using global identifier similar to Begin/End (#402)
|
||||
- popups: border options. richer api like BeginChild() perhaps? (#197)
|
||||
- popups: flags could be reworked to allow both mouse buttons as index (0..5 and as flags using higher-bit) allowing to or them.
|
||||
- popups/modals: although it is sometimes convenient that popups/modals lifetime is owned by imgui, we could also a bool-owned-by-user api as long as Begin() return value testing is enforced.
|
||||
|
||||
- tooltip: drag and drop with tooltip near monitor edges lose/changes its last direction instead of locking one. The drag and drop tooltip should always follow without changing direction.
|
||||
- tooltip: allow to set the width of a tooltip to allow TextWrapped() etc. while keeping the height automatic.
|
||||
- tooltip: tooltips with delay timers? or general timer policy? (instantaneous vs timed): IsItemHovered() with timer + implicit aabb-id for items with no ID. (#1485)
|
||||
- tooltip: drag tooltip hovering over source widget with IsItemHovered/SetTooltip flickers.
|
||||
- tooltip: drag tooltip hovering over source widget with IsItemHovered/SetTooltip flickers (WIP branch)
|
||||
- tooltip: tooltip priorities to override a stock tooltip (e.g. shortcut tooltip)
|
||||
|
||||
- menus: menu bars inside modal windows are acting weird.
|
||||
- status-bar: add a per-window status bar helper similar to what menu-bar does.
|
||||
- status-bar: add a per-window status bar helper similar to what menu-bar does. generalize concept of layer0 rect in window (can make _MenuBar window flag obsolete too).
|
||||
- shortcuts: store multiple keychords in ImGuiKeyChord
|
||||
- shortcuts: Hovered route (lower than Focused, higher than Global)
|
||||
- shortcuts: local-style shortcut api, e.g. parse "&Save"
|
||||
- shortcuts,menus: global-style shortcut api e.g. "Save (CTRL+S)" -> explicit flag for recursing into closed menu
|
||||
- shortcuts: programmatically access shortcuts "Focus("&Save"))
|
||||
- menus: menu-bar: main menu-bar could affect clamping of windows position (~ akin to modifying DisplayMin)
|
||||
- menus: hovering from menu to menu on a menu-bar has 1 frame without any menu, which is a little annoying. ideally either 0 either longer.
|
||||
- menus: could merge draw call in most cases (how about storing an optional aabb in ImDrawCmd to move the burden of merging in a single spot).
|
||||
- menus: hovering from menu to menu on a menu-bar has 1 frame without any menu, which is a little annoying. ideally zero.
|
||||
- menus: would be nice if the Selectable() supported horizontal alignment (must be given the equivalent of WorkRect.Max.x matching the position of the shortcut column)
|
||||
|
||||
- tree node: add treenode/treepush int variants? not there because (void*) cast from int warns on some platforms/settings?
|
||||
@@ -226,15 +170,14 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
|
||||
- tree node / selectable render mismatch which is visible if you use them both next to each other (e.g. cf. property viewer)
|
||||
- tree node: tweak color scheme to distinguish headers from selected tree node (#581)
|
||||
- tree node: leaf/non-leaf highlight mismatch.
|
||||
- tree node: flag to disable formatting and/or detect "%s"
|
||||
- tree node/opt: could avoid formatting when clipped (flag assuming we don't care about width/height, assume single line height? format only %s/%c to be able to count height?)
|
||||
|
||||
- settings: write more decent code to allow saving/loading new fields: columns, selected tree nodes?
|
||||
- settings: facilitate extension lazily calling AddSettingsHandler() while running and still getting their data call the ReadXXX handlers immediately.
|
||||
- settings: api for per-tool simple persistent data (bool,int,float,columns sizes,etc.) in .ini file (#437)
|
||||
- settings/persistence: helpers to make TreeNodeBehavior persist (even during dev!) - may need to store some semantic and/or data type in ImGuiStoragePair
|
||||
|
||||
- style: better default styles. (#707)
|
||||
- style: PushStyleVar: allow direct access to individual float X/Y elements.
|
||||
- style: add a highlighted text color (for headers, etc.)
|
||||
- style: border types: out-screen, in-screen, etc. (#447)
|
||||
- style: add window shadow (fading away from the window. Paint-style calculation of vertices alpha after drawlist would be easier)
|
||||
@@ -244,7 +187,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
|
||||
- style: FramePadding could be different for up vs down (#584)
|
||||
- style: WindowPadding needs to be EVEN as the 0.5 multiplier used on this value probably have a subtle effect on clip rectangle
|
||||
- style: have a more global HSV setter (e.g. alter hue on all elements). consider replacing active/hovered by offset in HSV space? (#438, #707, #1223)
|
||||
- style: gradients fill (#1223) ~ 2 bg colors for each fill? tricky with rounded shapes and using textures for corners.
|
||||
- style: gradients fill (#4722, #1223) ~ 2 bg colors for each fill? tricky with rounded shapes and using textures for corners.
|
||||
- style editor: color child window height expressed in multiple of line height.
|
||||
|
||||
- log: improve logging of ArrowButton, ListBox, TabItem
|
||||
@@ -253,20 +196,16 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
|
||||
- log: have more control over the log scope (e.g. stop logging when leaving current tree node scope)
|
||||
- log: be able to log anything (e.g. right-click on a window/tree-node, shows context menu? log into tty/file/clipboard)
|
||||
- log: let user copy any window content to clipboard easily (CTRL+C on windows? while moving it? context menu?). code is commented because it fails with multiple Begin/End pairs.
|
||||
- log: obsolete LogButtons() all together.
|
||||
- log: LogButtons() options for specifying depth and/or hiding depth slider
|
||||
- log: obsolete LogButtons().... (was: LogButtons() options for specifying depth and/or hiding depth slider)
|
||||
|
||||
- filters: set a current filter that tree node can automatically query to hide themselves
|
||||
- filters: set a current filter that certain items (e.g. tree node) can automatically query to hide themselves
|
||||
- filters: handle wild-cards (with implicit leading/trailing *), reg-exprs
|
||||
- filters: fuzzy matches (may use code at blog.forrestthewoods.com/4cffeed33fdb)
|
||||
|
||||
- drag and drop: fix/support/options for overlapping drag sources.
|
||||
- drag and drop: focus drag target window on hold (even without open)
|
||||
- drag and drop: releasing a drop shows the "..." tooltip for one frame - since e13e598 (#1725)
|
||||
- drag and drop: drag source on a group object (would need e.g. an invisible button covering group in EndGroup) https://twitter.com/paniq/status/1121446364909535233
|
||||
- drag and drop: have some way to know when a drag begin from BeginDragDropSource() pov. (see 2018/01/11 post in #143)
|
||||
- drag and drop: allow preview tooltip to be submitted from a different place than the drag source. (#1725)
|
||||
- drag and drop: allow using with other mouse buttons (where activeid won't be set). (#1637)
|
||||
- drag and drop: make it easier and provide a demo to have tooltip both are source and target site, with a more detailed one on target site (tooltip ordering problem)
|
||||
- drag and drop: demo with reordering nodes (in a list, or a tree node). (#143)
|
||||
- drag and drop: test integrating with os drag and drop (make it easy to do a naive WM_DROPFILE integration)
|
||||
@@ -275,13 +214,10 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
|
||||
- drag and drop: (#143) "both an in-process pointer and a promise to generate a serialized version, for whether the drag ends inside or outside the same process"
|
||||
- drag and drop: feedback when hovering a region blocked by modal (mouse cursor "NO"?)
|
||||
|
||||
- node/graph editors (#306) (also see https://github.com/ocornut/imgui/wiki#node-editors)
|
||||
- pie menus patterns (#434)
|
||||
- markup: simple markup language for color change? (#902)
|
||||
- markup: simple markup language for color change? (#902, #3130)
|
||||
|
||||
- text: selectable text (for copy) as a generic feature (ItemFlags?)
|
||||
- text: proper alignment options in imgui_internal.h
|
||||
- text: it's currently impossible to have a window title with "##". perhaps an official workaround would be nice. \ style inhibitor? non-visible ascii code to insert between #?
|
||||
- text: provided a framed text helper, e.g. https://pastebin.com/1Laxy8bT
|
||||
- text: refactor TextUnformatted (or underlying function) to more explicitly request if we need width measurement or not
|
||||
- text/layout/tabs: \t pulling position from base pos + step, or offset array (e.g. could be used in text edit, menus for simple icon+text alignment, etc.)
|
||||
@@ -292,22 +228,13 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
|
||||
|
||||
- font: arbitrary line spacing. (#2945)
|
||||
- font: MergeMode: flags to select overwriting or not (this is now very easy with refactored ImFontAtlasBuildWithStbTruetype)
|
||||
- font: free the Alpha buffer if user only requested RGBA.
|
||||
!- font: better CalcTextSizeA() API, at least for simple use cases. current one is horrible (perhaps have simple vs extended versions).
|
||||
- font: better CalcTextSizeA() API, at least for simple use cases. current one is horrible (perhaps have simple vs extended versions).
|
||||
- font: for the purpose of RenderTextEllipsis(), it might be useful that CalcTextSizeA() can ignore the trailing padding?
|
||||
- font: a CalcTextHeight() helper could run faster than CalcTextSize().y
|
||||
- font: enforce monospace through ImFontConfig (for icons?) + create dual ImFont output from same input, reusing rasterized data but with different glyphs/AdvanceX
|
||||
- font: finish CustomRectRegister() to allow mapping Unicode codepoint to custom texture data
|
||||
- font: remove ID from CustomRect registration, it seems unnecessary!
|
||||
- font: make it easier to submit own bitmap font (same texture, another texture?). (#2127, #2575)
|
||||
- font: PushFontSize API (#1018)
|
||||
- font: MemoryTTF taking ownership confusing/not obvious, maybe default should be opposite?
|
||||
- font: storing MinAdvanceX per font would allow us to skip calculating line width (under a threshold of character count) in loops looking for block width
|
||||
- font/demo: add tools to show glyphs used by a text blob, display U16 value, list missing glyphs.
|
||||
- font/demo: demonstrate use of ImFontGlyphRangesBuilder.
|
||||
- font/atlas: add a missing Glyphs.reserve()
|
||||
- font/atlas: incremental updates
|
||||
- font/atlas: dynamic font atlas to avoid baking huge ranges into bitmap and make scaling easier.
|
||||
- font/draw: vertical and/or rotated text renderer (#705) - vertical is easier clipping wise
|
||||
- font/draw: need to be able to specify wrap start position.
|
||||
- font/draw: better reserve policy for large horizontal block of text (shouldn't reserve for all clipped lines). also see #3349.
|
||||
@@ -316,46 +243,35 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
|
||||
- font: optimization: for monospace font (like the default one) we can trim IndexXAdvance as long as trailing value is == FallbackXAdvance (need to make sure TAB is still correct), would save on cache line.
|
||||
- font: add support for kerning, probably optional. A) perhaps default to (32..128)^2 matrix ~ 9K entries = 36KB, then hash for non-ascii?. B) or sparse lookup into per-char list?
|
||||
- font: add a simpler CalcTextSizeA() api? current one ok but not welcome if user needs to call it directly (without going through ImGui::CalcTextSize)
|
||||
- font: fix AddRemapChar() to work before atlas has been built.
|
||||
- font: support for unicode codepoints higher than 0xFFFF? (pr #2815)
|
||||
- font: (api breaking) remove "TTF" from symbol names. also because it now supports OTF.
|
||||
- font/opt: Considering storing standalone AdvanceX table as 16-bit fixed point integer?
|
||||
- font/opt: Glyph currently 40 bytes (2+9*4). Consider storing UV as 16 bits integer? (->32 bytes). X0/Y0/X1/Y1 as 16 fixed-point integers? Or X0/Y0 as float and X1/Y1 as fixed8_8?
|
||||
- font/opt: Glyph currently 40 bytes (2+9*4). Consider storing UV as 16-bits integer? (->32 bytes). X0/Y0/X1/Y1 as 16 fixed-point integers? Or X0/Y0 as float and X1/Y1 as fixed8_8?
|
||||
|
||||
- nav: some features such as PageUp/Down/Home/End should probably work without ImGuiConfigFlags_NavEnableKeyboard? (where do we draw the line?)
|
||||
- nav: configuration flag to disable global shortcuts (currently only CTRL-Tab) ?
|
||||
! nav: never clear NavId on some setup (e.g. gamepad centric)
|
||||
- nav: there's currently no way to completely clear focus with the keyboard. depending on patterns used by the application to dispatch inputs, it may be desirable.
|
||||
- nav: code to focus child-window on restoring NavId appears to have issue: e.g. when focus change is implicit because of window closure.
|
||||
- nav: some features such as PageUp/Down/Home/End should probably work without ImGuiConfigFlags_NavEnableKeyboard? (where do we draw the line? how about CTRL+Tab)
|
||||
- nav: Home/End behavior when navigable item is not fully visible at the edge of scrolling? should be backtrack to keep item into view?
|
||||
- nav: NavScrollToBringItemIntoView() with item bigger than view should focus top-right? Repro: using Nav in "About Window"
|
||||
- nav: wrap around logic to allow e.g. grid based layout (pressing NavRight on the right-most element would go to the next row, etc.). see internal's NavMoveRequestTryWrapping().
|
||||
- nav: expose wrap around flags/logic to allow e.g. grid based layout (pressing NavRight on the right-most element would go to the next row, etc.). see internal's NavMoveRequestTryWrapping().
|
||||
- nav: patterns to make it possible for arrows key to update selection (see JustMovedTo in range_select branch)
|
||||
- nav: restore/find nearest NavId when current one disappear (e.g. pressed a button that disappear, or perhaps auto restoring when current button change name)
|
||||
- nav: SetItemDefaultFocus() level of priority, so widget like Selectable when inside a popup could claim a low-priority default focus on the first selected iem
|
||||
- nav: SetItemDefaultFocus() level of priority, so widgets like Selectable when inside a popup could claim a low-priority default focus on the first selected item
|
||||
- nav: holding space to repeat a button doesn't show button activated during hold.
|
||||
- nav: NavFlattened: init requests don't work properly on flattened siblings.
|
||||
- nav: NavFlattened: pageup/pagedown/home/end don't work properly on flattened siblings.
|
||||
- nav: NavFlattened: ESC on a flattened child should select something.
|
||||
- nav: NavFlattened: broken: in typical usage scenario, the items of a fully clipped child are currently not considered to enter into a NavFlattened child.
|
||||
- nav: NavFlattened: init request doesn't select items that are part of a NavFlattened child
|
||||
- nav: NavFlattened: cannot access menu-bar of a flattened child window with Alt/menu key (not a very common use case..).
|
||||
- nav: simulate right-click or context activation? (SHIFT+F10)
|
||||
- nav/tabbing: refactor old tabbing system and turn into navigation, should pass through all widgets (in submission order?).
|
||||
- nav/popup: esc/enter default behavior for popups, e.g. be able to mark an "ok" or "cancel" button that would get triggered by those keys, default validation button, etc.
|
||||
- nav/treenode: left within a tree node block as a fallback (ImGuiTreeNodeFlags_NavLeftJumpsBackHere by default?)
|
||||
- nav/menus: pressing left-right on a vertically clipped menu bar tends to jump to the collapse/close buttons.
|
||||
- nav/menus: allow pressing Menu to leave a sub-menu.
|
||||
- nav/menus: a way to access the main menu bar with Alt? (currently needs CTRL+TAB) or last focused window menu bar?
|
||||
! nav/menus: a way to access the main menu bar with Alt? (currently needs CTRL+TAB) or last focused window menu bar?
|
||||
- nav/menus: when using the main menu bar, even though we restore focus after, the underlying window loses its title bar highlight during menu manipulation. could we prevent it?
|
||||
- nav/menus: main menu bar currently cannot restore a NULL focus. Could save NavWindow at the time of being focused, similarly to what popup do?
|
||||
- nav/menus: main menu bar currently cannot restore a nullptr focus. Could save NavWindow at the time of being focused, similarly to what popup do?
|
||||
- nav/menus: Alt,Up could open the first menu (e.g. "File") currently it tends to nav into the window/collapse menu. Do do that we would need custom transition?
|
||||
- nav/windowing: configure fade-in/fade-out delay on Ctrl+Tab?
|
||||
- nav/windowing: when CTRL-Tab/windowing is active, the HoveredWindow detection doesn't take account of the window display re-ordering.
|
||||
- nav/windowing: when CTRL+Tab/windowing is active, the HoveredWindow detection doesn't take account of the window display re-ordering.
|
||||
- nav/windowing: Resizing window will currently fail with certain types of resizing constraints/callback applied
|
||||
- focus: preserve ActiveId/focus stack state, e.g. when opening a menu and close it, previously selected InputText() focus gets restored (#622)
|
||||
- focus: SetKeyboardFocusHere() on with >= 0 offset could be done on same frame (else latch and modulate on beginning of next frame)
|
||||
- focus: unable to use SetKeyboardFocusHere() on clipped widgets. (#787, #343)
|
||||
|
||||
- inputs: we need an explicit flag about whether the imgui window is focused, to be able to distinguish focused key releases vs alt-tabbing all release behaviors.
|
||||
- inputs: rework IO system to be able to pass actual ordered/timestamped events. use an event queue? (~#335, #71)
|
||||
- inputs: support track pad style scrolling & slider edit.
|
||||
- inputs/io: backspace and arrows in the context of a text input could use system repeat rate.
|
||||
- inputs/io: clarify/standardize/expose repeat rate and repeat delays (#1808)
|
||||
@@ -367,13 +283,8 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
|
||||
- misc: no way to run a root-most GetID() with ImGui:: api since there's always a Debug window in the stack. (mentioned in #2960)
|
||||
- misc: make the ImGuiCond values linear (non-power-of-two). internal storage for ImGuiWindow can use integers to combine into flags (Why?)
|
||||
- misc: PushItemFlag(): add a flag to disable keyboard capture when used with mouse? (#1682)
|
||||
- misc: use more size_t in public api?
|
||||
- misc: possible compile-time support for string view/range instead of char* would e.g. facilitate usage with Rust (#683)
|
||||
- misc: possible compile-time support for wchar_t instead of char*?
|
||||
- misc: support for string view/range instead of char* would e.g. facilitate usage with Rust (#683, #3038, WIP string_view branch)
|
||||
|
||||
- remote: make a system like RemoteImGui first-class citizen/project (#75)
|
||||
|
||||
- demo: find a way to demonstrate textures in the examples application, as it such a common issue for new users.
|
||||
- demo: demonstrate using PushStyleVar() in more details.
|
||||
- demo: add vertical separator demo
|
||||
- demo: add virtual scrolling example?
|
||||
@@ -382,25 +293,20 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
|
||||
|
||||
- examples: window minimize, maximize (#583)
|
||||
- examples: provide a zero frame-rate/idle example.
|
||||
- examples: dx11/dx12: try to use new swapchain blit models (#2970)
|
||||
- backends: move to backends/ folder?
|
||||
- examples: dx11/dx12: try to use new swapchain blit models (#2970, #9031)
|
||||
- backends: report it better when not able to create texture?
|
||||
- backends: apple: example_apple should be using modern GL3.
|
||||
- backends: glfw: could go idle when minimized? if (glfwGetWindowAttrib(window, GLFW_ICONIFIED)) { glfwWaitEvents(); continue; } // issue: DeltaTime will be super high on resume, perhaps provide a way to let impl know (#440)
|
||||
- backends: opengl: rename imgui_impl_opengl2 to impl_opengl_legacy and imgui_impl_opengl3 to imgui_impl_opengl? (#1900)
|
||||
- backends: opengl: could use a single vertex buffer and glBufferSubData for uploads?
|
||||
- backends: opengl: explicitly disable GL_STENCIL_TEST in bindings.
|
||||
- backends: opengl: consider gl_lite loader https://github.com/ApoorvaJ/Papaya/blob/3808e39b0f45d4ca4972621c847586e4060c042a/src/libs/gl_lite.h
|
||||
- backends: vulkan: viewport: support for synchronized swapping of multiple swap chains.
|
||||
- backends: bgfx: https://gist.github.com/RichardGale/6e2b74bc42b3005e08397236e4be0fd0
|
||||
- backends: mscriptem: with refactored examples, we could provide a direct imgui_impl_emscripten platform layer (see eg. https://github.com/floooh/sokol-samples/blob/master/html5/imgui-emsc.cc#L42)
|
||||
- backends: emscripten: dedicated backend? (#8178, #9120, eg. https://github.com/floooh/sokol-samples/blob/master/html5/imgui-emsc.cc#L42)
|
||||
|
||||
- bindings: ways to use clang ast dump to generate bindings or helpers for bindings? (e.g. clang++ -Xclang -ast-dump=json imgui.h)
|
||||
- bindings: ways to use clang ast dump to generate bindings or helpers for bindings? (e.g. clang++ -Xclang -ast-dump=json imgui.h) (--> use https://github.com/dearimgui/dear_bindings)
|
||||
|
||||
- optimization: replace vsnprintf with stb_printf? using IMGUI_USE_STB_SPRINTF.(#1038)
|
||||
- optimization: replace vsnprintf with stb_printf? using IMGUI_USE_STB_SPRINTF. (#1038 + needed for string_view)
|
||||
- optimization: add clipping for multi-component widgets (SliderFloatX, ColorEditX, etc.). one problem is that nav branch can't easily clip parent group when there is a move request.
|
||||
- optimization: add a flag to disable most of rendering, for the case where the user expect to skip it (#335)
|
||||
- optimization: fully covered window (covered by another with non-translucent bg + WindowRounding worth of padding) may want to clip rendering.
|
||||
- optimization: use another hash function than crc32, e.g. FNV1a
|
||||
- optimization/render: merge command-lists with same clip-rect into one even if they aren't sequential? (as long as in-between clip rectangle don't overlap)?
|
||||
- optimization: turn some the various stack vectors into statically-sized arrays
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
See BACKENDS and EXAMPLES files in the docs/ folder.
|
||||
New to Dear ImGui?
|
||||
- Check out the Getting Started guide: https://github.com/ocornut/imgui/wiki/Getting-Started
|
||||
- About Backends: docs/BACKENDS.md file, or on the web: https://github.com/ocornut/imgui/blob/master/docs/BACKENDS.md
|
||||
- About Examples: docs/EXAMPLES.md file, or on the web: https://github.com/ocornut/imgui/blob/master/docs/EXAMPLES.md
|
||||
|
||||
Backends = Helper code to facilitate integration with platforms/graphics api (used by Examples + should be used by your app).
|
||||
Examples = Standalone applications showcasing integration with platforms/graphics api.
|
||||
|
||||
A few Examples have extra README files in their respective directory, please check them too!
|
||||
|
||||
Once Dear ImGui is running (in either examples or your own application/game/engine),
|
||||
run and refer to ImGui::ShowDemoWindow() in imgui_demo.cpp for the end-user API.
|
||||
|
||||
@@ -12,7 +12,7 @@ Note that the backend supports _BOTH_ 16-bit and 32-bit indices, but 32-bit indi
|
||||
### On Ubuntu 14.04+ and macOS
|
||||
|
||||
```bash
|
||||
g++ -DIMGUI_USER_CONFIG=\"examples/example_allegro5/imconfig_allegro5.h\" -I .. -I ../.. main.cpp ../../backends/imgui_impl_allegro5.cpp ../../imgui*.cpp -lallegro -lallegro_main -lallegro_primitives -o allegro5_example
|
||||
g++ -DIMGUI_USER_CONFIG=\"examples/example_allegro5/imconfig_allegro5.h\" -I .. -I ../.. -I ../../backends main.cpp ../../backends/imgui_impl_allegro5.cpp ../../imgui*.cpp -lallegro -lallegro_main -lallegro_primitives -o allegro5_example
|
||||
```
|
||||
|
||||
On macOS, install Allegro with homebrew: `brew install allegro`.
|
||||
@@ -23,13 +23,14 @@ You may install Allegro using vcpkg:
|
||||
```
|
||||
git clone https://github.com/Microsoft/vcpkg
|
||||
cd vcpkg
|
||||
.\bootstrap-vcpkg.bat
|
||||
.\vcpkg install allegro5
|
||||
.\vcpkg integrate install ; optional, automatically register include/libs in Visual Studio
|
||||
bootstrap-vcpkg.bat
|
||||
vcpkg install allegro5 --triplet=x86-windows ; for win32
|
||||
vcpkg install allegro5 --triplet=x64-windows ; for win64
|
||||
vcpkg integrate install ; register include / libs in Visual Studio
|
||||
```
|
||||
|
||||
Build:
|
||||
```
|
||||
set ALLEGRODIR=path_to_your_allegro5_folder
|
||||
cl /Zi /MD /I %ALLEGRODIR%\include /DIMGUI_USER_CONFIG=\"examples/example_allegro5/imconfig_allegro5.h\" /I .. /I ..\.. main.cpp ..\..\backends\imgui_impl_allegro5.cpp ..\..\imgui*.cpp /link /LIBPATH:%ALLEGRODIR%\lib allegro-5.0.10-monolith-md.lib user32.lib
|
||||
cl /Zi /MD /utf-8 /I %ALLEGRODIR%\include /DIMGUI_USER_CONFIG=\"examples/example_allegro5/imconfig_allegro5.h\" /I .. /I ..\.. /I ..\..\backends main.cpp ..\..\backends\imgui_impl_allegro5.cpp ..\..\imgui*.cpp /link /LIBPATH:%ALLEGRODIR%\lib allegro-5.0.10-monolith-md.lib user32.lib
|
||||
```
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
@@ -28,27 +28,27 @@
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
@@ -91,6 +91,7 @@
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
@@ -105,6 +106,7 @@
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
@@ -120,8 +122,9 @@
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;$(SolutionDir)\libs\gl3w;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
@@ -140,8 +143,9 @@
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;$(SolutionDir)\libs\gl3w;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
@@ -171,10 +175,11 @@
|
||||
<ClInclude Include="..\..\backends\imgui_impl_allegro5.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\misc\debuggers\imgui.natstepfilter" />
|
||||
<None Include="..\..\misc\debuggers\imgui.natvis" />
|
||||
<None Include="..\README.txt" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -52,7 +52,10 @@
|
||||
<ItemGroup>
|
||||
<None Include="..\README.txt" />
|
||||
<None Include="..\..\misc\debuggers\imgui.natvis">
|
||||
<Filter>sources</Filter>
|
||||
<Filter>imgui</Filter>
|
||||
</None>
|
||||
<None Include="..\..\misc\debuggers\imgui.natstepfilter">
|
||||
<Filter>imgui</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -1,6 +1,18 @@
|
||||
// Dear ImGui: standalone example application for Allegro 5
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
// On Windows, you can install Allegro5 using vcpkg:
|
||||
// git clone https://github.com/Microsoft/vcpkg
|
||||
// cd vcpkg
|
||||
// bootstrap - vcpkg.bat
|
||||
// vcpkg install allegro5 --triplet=x86-windows ; for win32
|
||||
// vcpkg install allegro5 --triplet=x64-windows ; for win64
|
||||
// vcpkg integrate install ; register include and libs in Visual Studio
|
||||
|
||||
#include <stdint.h>
|
||||
#include <allegro5/allegro.h>
|
||||
@@ -16,7 +28,7 @@ int main(int, char**)
|
||||
al_install_mouse();
|
||||
al_init_primitives_addon();
|
||||
al_set_new_display_flags(ALLEGRO_RESIZABLE);
|
||||
ALLEGRO_DISPLAY* display = al_create_display(1280, 720);
|
||||
ALLEGRO_DISPLAY* display = al_create_display(1280, 800);
|
||||
al_set_window_title(display, "Dear ImGui Allegro 5 example");
|
||||
ALLEGRO_EVENT_QUEUE* queue = al_create_event_queue();
|
||||
al_register_event_source(queue, al_get_display_event_source(display));
|
||||
@@ -27,29 +39,32 @@ int main(int, char**)
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||
|
||||
// Setup Dear ImGui style
|
||||
ImGui::StyleColorsDark();
|
||||
//ImGui::StyleColorsClassic();
|
||||
//ImGui::StyleColorsLight();
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
ImGui_ImplAllegro5_Init(display);
|
||||
|
||||
// Load Fonts
|
||||
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
|
||||
// - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
|
||||
// - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
|
||||
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
|
||||
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
|
||||
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
//io.Fonts->AddFontDefault();
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
|
||||
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
|
||||
//IM_ASSERT(font != NULL);
|
||||
//style.FontSizeBase = 20.0f;
|
||||
//io.Fonts->AddFontDefaultVector();
|
||||
//io.Fonts->AddFontDefaultBitmap();
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf");
|
||||
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf");
|
||||
//IM_ASSERT(font != nullptr);
|
||||
|
||||
bool show_demo_window = true;
|
||||
bool show_another_window = false;
|
||||
@@ -61,8 +76,8 @@ int main(int, char**)
|
||||
{
|
||||
// Poll and handle events (inputs, window resize, etc.)
|
||||
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
|
||||
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
|
||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||
ALLEGRO_EVENT ev;
|
||||
while (al_get_next_event(queue, &ev))
|
||||
@@ -86,7 +101,7 @@ int main(int, char**)
|
||||
if (show_demo_window)
|
||||
ImGui::ShowDemoWindow(&show_demo_window);
|
||||
|
||||
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
|
||||
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window.
|
||||
{
|
||||
static float f = 0.0f;
|
||||
static int counter = 0;
|
||||
@@ -105,7 +120,7 @@ int main(int, char**)
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("counter = %d", counter);
|
||||
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
.cxx
|
||||
.externalNativeBuild
|
||||
build/
|
||||
*.iml
|
||||
|
||||
.idea
|
||||
.gradle
|
||||
.idea
|
||||
.DS_Store
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
||||
|
||||
# Android Studio puts a Gradle wrapper here, that we don't want:
|
||||
gradle/
|
||||
!gradle/libs.versions.toml
|
||||
gradlew*
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
plugins {
|
||||
alias(libs.plugins.android.application)
|
||||
alias(libs.plugins.kotlin.android)
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 29
|
||||
buildToolsVersion "30.0.3"
|
||||
ndkVersion "21.4.7075529"
|
||||
namespace 'imgui.example.android'
|
||||
compileSdk 36
|
||||
|
||||
defaultConfig {
|
||||
applicationId "imgui.example.android"
|
||||
minSdkVersion 23
|
||||
targetSdkVersion 29
|
||||
minSdk 24
|
||||
targetSdk 36
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
@@ -19,16 +21,17 @@ android {
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt')
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = '11'
|
||||
}
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
path "../../CMakeLists.txt"
|
||||
path file('../../CMakeLists.txt')
|
||||
version '3.22.1'
|
||||
}
|
||||
}
|
||||
}
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="imgui.example.android">
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<application
|
||||
android:label="ImGuiExample"
|
||||
@@ -11,7 +11,8 @@
|
||||
<activity
|
||||
android:name="imgui.example.android.MainActivity"
|
||||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
|
||||
android:configChanges="orientation|keyboardHidden|screenSize">
|
||||
android:configChanges="orientation|keyboardHidden|screenSize"
|
||||
android:exported="true">
|
||||
<meta-data android:name="android.app.lib_name"
|
||||
android:value="ImGuiExample" />
|
||||
|
||||
|
||||
@@ -1,24 +1,5 @@
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.4.31'
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:4.1.0'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
plugins {
|
||||
alias(libs.plugins.android.application) apply false
|
||||
alias(libs.plugins.kotlin.android) apply false
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
[versions]
|
||||
agp = "8.12.0"
|
||||
kotlin = "2.0.21"
|
||||
|
||||
[plugins]
|
||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
||||
|
||||
@@ -1 +1,22 @@
|
||||
pluginManagement {
|
||||
repositories {
|
||||
google {
|
||||
content {
|
||||
includeGroupByRegex("com\\.android.*")
|
||||
includeGroupByRegex("com\\.google.*")
|
||||
includeGroupByRegex("androidx.*")
|
||||
}
|
||||
}
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
dependencyResolutionManagement {
|
||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
include ':app'
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
// dear imgui: standalone example application for Android + OpenGL ES 3
|
||||
// If you are new to dear imgui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_android.h"
|
||||
@@ -9,21 +14,84 @@
|
||||
#include <android/asset_manager.h>
|
||||
#include <EGL/egl.h>
|
||||
#include <GLES3/gl3.h>
|
||||
#include <string>
|
||||
|
||||
// Data
|
||||
static EGLDisplay g_EglDisplay = EGL_NO_DISPLAY;
|
||||
static EGLSurface g_EglSurface = EGL_NO_SURFACE;
|
||||
static EGLContext g_EglContext = EGL_NO_CONTEXT;
|
||||
static struct android_app* g_App = NULL;
|
||||
static struct android_app* g_App = nullptr;
|
||||
static bool g_Initialized = false;
|
||||
static char g_LogTag[] = "ImGuiExample";
|
||||
static std::string g_IniFilename = "";
|
||||
|
||||
// Forward declarations of helper functions
|
||||
static void Init(struct android_app* app);
|
||||
static void Shutdown();
|
||||
static void MainLoopStep();
|
||||
static int ShowSoftKeyboardInput();
|
||||
static int PollUnicodeChars();
|
||||
static int GetAssetData(const char* filename, void** out_data);
|
||||
|
||||
void init(struct android_app* app)
|
||||
// Main code
|
||||
static void handleAppCmd(struct android_app* app, int32_t appCmd)
|
||||
{
|
||||
switch (appCmd)
|
||||
{
|
||||
case APP_CMD_SAVE_STATE:
|
||||
break;
|
||||
case APP_CMD_INIT_WINDOW:
|
||||
Init(app);
|
||||
break;
|
||||
case APP_CMD_TERM_WINDOW:
|
||||
Shutdown();
|
||||
break;
|
||||
case APP_CMD_GAINED_FOCUS:
|
||||
case APP_CMD_LOST_FOCUS:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t handleInputEvent(struct android_app* app, AInputEvent* inputEvent)
|
||||
{
|
||||
return ImGui_ImplAndroid_HandleInputEvent(inputEvent);
|
||||
}
|
||||
|
||||
void android_main(struct android_app* app)
|
||||
{
|
||||
app->onAppCmd = handleAppCmd;
|
||||
app->onInputEvent = handleInputEvent;
|
||||
|
||||
while (true)
|
||||
{
|
||||
int out_events;
|
||||
struct android_poll_source* out_data;
|
||||
|
||||
// Poll all events. If the app is not visible, this loop blocks until g_Initialized == true.
|
||||
while (ALooper_pollOnce(g_Initialized ? 0 : -1, nullptr, &out_events, (void**)&out_data) >= 0)
|
||||
{
|
||||
// Process one event
|
||||
if (out_data != nullptr)
|
||||
out_data->process(app, out_data);
|
||||
|
||||
// Exit the app by returning from within the infinite loop
|
||||
if (app->destroyRequested != 0)
|
||||
{
|
||||
// shutdown() should have been called already while processing the
|
||||
// app command APP_CMD_TERM_WINDOW. But we play save here
|
||||
if (!g_Initialized)
|
||||
Shutdown();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Initiate a new frame
|
||||
MainLoopStep();
|
||||
}
|
||||
}
|
||||
|
||||
void Init(struct android_app* app)
|
||||
{
|
||||
if (g_Initialized)
|
||||
return;
|
||||
@@ -61,7 +129,7 @@ void init(struct android_app* app)
|
||||
if (g_EglContext == EGL_NO_CONTEXT)
|
||||
__android_log_print(ANDROID_LOG_ERROR, g_LogTag, "%s", "eglCreateContext() returned EGL_NO_CONTEXT");
|
||||
|
||||
g_EglSurface = eglCreateWindowSurface(g_EglDisplay, egl_config, g_App->window, NULL);
|
||||
g_EglSurface = eglCreateWindowSurface(g_EglDisplay, egl_config, g_App->window, nullptr);
|
||||
eglMakeCurrent(g_EglDisplay, g_EglSurface, g_EglSurface, g_EglContext);
|
||||
}
|
||||
|
||||
@@ -70,65 +138,69 @@ void init(struct android_app* app)
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
// Disable loading/saving of .ini file from disk.
|
||||
// FIXME: Consider using LoadIniSettingsFromMemory() / SaveIniSettingsToMemory() to save in appropriate location for Android.
|
||||
io.IniFilename = NULL;
|
||||
// Redirect loading/saving of .ini file to our location.
|
||||
// Make sure 'g_IniFilename' persists while we use Dear ImGui.
|
||||
g_IniFilename = std::string(app->activity->internalDataPath) + "/imgui.ini";
|
||||
io.IniFilename = g_IniFilename.c_str();;
|
||||
|
||||
// Setup Dear ImGui style
|
||||
ImGui::StyleColorsDark();
|
||||
//ImGui::StyleColorsClassic();
|
||||
//ImGui::StyleColorsLight();
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
ImGui_ImplAndroid_Init(g_App->window);
|
||||
ImGui_ImplOpenGL3_Init("#version 300 es");
|
||||
|
||||
// Setup scaling
|
||||
float main_scale = 2.0f;
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
|
||||
style.FontScaleDpi = main_scale; // Set initial font scale.
|
||||
|
||||
// Load Fonts
|
||||
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
|
||||
// - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
|
||||
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
|
||||
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
|
||||
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
// - Android: The TTF files have to be placed into the assets/ directory (android/app/src/main/assets), we use our GetAssetData() helper to retrieve them.
|
||||
//style.FontSizeBase = 20.0f;
|
||||
//io.Fonts->AddFontDefaultVector();
|
||||
//io.Fonts->AddFontDefaultBitmap();
|
||||
|
||||
// We load the default font with increased size to improve readability on many devices with "high" DPI.
|
||||
// FIXME: Put some effort into DPI awareness.
|
||||
// Important: when calling AddFontFromMemoryTTF(), ownership of font_data is transfered by Dear ImGui by default (deleted is handled by Dear ImGui), unless we set FontDataOwnedByAtlas=false in ImFontConfig
|
||||
ImFontConfig font_cfg;
|
||||
font_cfg.SizePixels = 22.0f;
|
||||
io.Fonts->AddFontDefault(&font_cfg);
|
||||
//void* font_data;
|
||||
//int font_data_size;
|
||||
// Important: when calling AddFontFromMemoryTTF(), ownership of font_data is transferred by Dear ImGui by default (deleted is handled by Dear ImGui), unless we set FontDataOwnedByAtlas=false in ImFontConfig
|
||||
//void* font_data;
|
||||
//int font_data_size;
|
||||
//ImFont* font;
|
||||
//font_data_size = GetAssetData("Roboto-Medium.ttf", &font_data);
|
||||
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size, 16.0f);
|
||||
//IM_ASSERT(font != NULL);
|
||||
//font_data_size = GetAssetData("Cousine-Regular.ttf", &font_data);
|
||||
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size, 15.0f);
|
||||
//IM_ASSERT(font != NULL);
|
||||
//font_data_size = GetAssetData("segoeui.ttf", &font_data);
|
||||
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size);
|
||||
//IM_ASSERT(font != nullptr);
|
||||
//font_data_size = GetAssetData("DroidSans.ttf", &font_data);
|
||||
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size, 16.0f);
|
||||
//IM_ASSERT(font != NULL);
|
||||
//font_data_size = GetAssetData("ProggyTiny.ttf", &font_data);
|
||||
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size, 10.0f);
|
||||
//IM_ASSERT(font != NULL);
|
||||
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size);
|
||||
//IM_ASSERT(font != nullptr);
|
||||
//font_data_size = GetAssetData("Roboto-Medium.ttf", &font_data);
|
||||
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size);
|
||||
//IM_ASSERT(font != nullptr);
|
||||
//font_data_size = GetAssetData("Cousine-Regular.ttf", &font_data);
|
||||
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size);
|
||||
//IM_ASSERT(font != nullptr);
|
||||
//font_data_size = GetAssetData("ArialUni.ttf", &font_data);
|
||||
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size, 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
|
||||
//IM_ASSERT(font != NULL);
|
||||
|
||||
// Arbitrary scale-up
|
||||
// FIXME: Put some effort into DPI awareness
|
||||
ImGui::GetStyle().ScaleAllSizes(3.0f);
|
||||
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size);
|
||||
//IM_ASSERT(font != nullptr);
|
||||
|
||||
g_Initialized = true;
|
||||
}
|
||||
|
||||
void tick()
|
||||
void MainLoopStep()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (g_EglDisplay == EGL_NO_DISPLAY)
|
||||
return;
|
||||
|
||||
// Our state
|
||||
// (we use static, which essentially makes the variable globals, as a convenience to keep the example code easy to follow)
|
||||
static bool show_demo_window = true;
|
||||
static bool show_another_window = false;
|
||||
static ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
||||
@@ -152,7 +224,7 @@ void tick()
|
||||
if (show_demo_window)
|
||||
ImGui::ShowDemoWindow(&show_demo_window);
|
||||
|
||||
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
|
||||
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window.
|
||||
{
|
||||
static float f = 0.0f;
|
||||
static int counter = 0;
|
||||
@@ -171,7 +243,7 @@ void tick()
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("counter = %d", counter);
|
||||
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
@@ -194,7 +266,7 @@ void tick()
|
||||
eglSwapBuffers(g_EglDisplay, g_EglSurface);
|
||||
}
|
||||
|
||||
void shutdown()
|
||||
void Shutdown()
|
||||
{
|
||||
if (!g_Initialized)
|
||||
return;
|
||||
@@ -225,85 +297,29 @@ void shutdown()
|
||||
g_Initialized = false;
|
||||
}
|
||||
|
||||
static void handleAppCmd(struct android_app* app, int32_t appCmd)
|
||||
{
|
||||
switch (appCmd)
|
||||
{
|
||||
case APP_CMD_SAVE_STATE:
|
||||
break;
|
||||
case APP_CMD_INIT_WINDOW:
|
||||
init(app);
|
||||
break;
|
||||
case APP_CMD_TERM_WINDOW:
|
||||
shutdown();
|
||||
break;
|
||||
case APP_CMD_GAINED_FOCUS:
|
||||
break;
|
||||
case APP_CMD_LOST_FOCUS:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t handleInputEvent(struct android_app* app, AInputEvent* inputEvent)
|
||||
{
|
||||
return ImGui_ImplAndroid_HandleInputEvent(inputEvent);
|
||||
}
|
||||
|
||||
void android_main(struct android_app* app)
|
||||
{
|
||||
app->onAppCmd = handleAppCmd;
|
||||
app->onInputEvent = handleInputEvent;
|
||||
|
||||
while (true)
|
||||
{
|
||||
int out_events;
|
||||
struct android_poll_source* out_data;
|
||||
|
||||
// Poll all events. If the app is not visible, this loop blocks until g_Initialized == true.
|
||||
while (ALooper_pollAll(g_Initialized ? 0 : -1, NULL, &out_events, (void**)&out_data) >= 0)
|
||||
{
|
||||
// Process one event
|
||||
if (out_data != NULL)
|
||||
out_data->process(app, out_data);
|
||||
|
||||
// Exit the app by returning from within the infinite loop
|
||||
if (app->destroyRequested != 0)
|
||||
{
|
||||
// shutdown() should have been called already while processing the
|
||||
// app command APP_CMD_TERM_WINDOW. But we play save here
|
||||
if (!g_Initialized)
|
||||
shutdown();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Initiate a new frame
|
||||
tick();
|
||||
}
|
||||
}
|
||||
// Helper functions
|
||||
|
||||
// Unfortunately, there is no way to show the on-screen input from native code.
|
||||
// Therefore, we call ShowSoftKeyboardInput() of the main activity implemented in MainActivity.kt via JNI.
|
||||
static int ShowSoftKeyboardInput()
|
||||
{
|
||||
JavaVM* java_vm = g_App->activity->vm;
|
||||
JNIEnv* java_env = NULL;
|
||||
JNIEnv* java_env = nullptr;
|
||||
|
||||
jint jni_return = java_vm->GetEnv((void**)&java_env, JNI_VERSION_1_6);
|
||||
if (jni_return == JNI_ERR)
|
||||
return -1;
|
||||
|
||||
jni_return = java_vm->AttachCurrentThread(&java_env, NULL);
|
||||
jni_return = java_vm->AttachCurrentThread(&java_env, nullptr);
|
||||
if (jni_return != JNI_OK)
|
||||
return -2;
|
||||
|
||||
jclass native_activity_clazz = java_env->GetObjectClass(g_App->activity->clazz);
|
||||
if (native_activity_clazz == NULL)
|
||||
if (native_activity_clazz == nullptr)
|
||||
return -3;
|
||||
|
||||
jmethodID method_id = java_env->GetMethodID(native_activity_clazz, "showSoftInput", "()V");
|
||||
if (method_id == NULL)
|
||||
if (method_id == nullptr)
|
||||
return -4;
|
||||
|
||||
java_env->CallVoidMethod(g_App->activity->clazz, method_id);
|
||||
@@ -321,22 +337,22 @@ static int ShowSoftKeyboardInput()
|
||||
static int PollUnicodeChars()
|
||||
{
|
||||
JavaVM* java_vm = g_App->activity->vm;
|
||||
JNIEnv* java_env = NULL;
|
||||
JNIEnv* java_env = nullptr;
|
||||
|
||||
jint jni_return = java_vm->GetEnv((void**)&java_env, JNI_VERSION_1_6);
|
||||
if (jni_return == JNI_ERR)
|
||||
return -1;
|
||||
|
||||
jni_return = java_vm->AttachCurrentThread(&java_env, NULL);
|
||||
jni_return = java_vm->AttachCurrentThread(&java_env, nullptr);
|
||||
if (jni_return != JNI_OK)
|
||||
return -2;
|
||||
|
||||
jclass native_activity_clazz = java_env->GetObjectClass(g_App->activity->clazz);
|
||||
if (native_activity_clazz == NULL)
|
||||
if (native_activity_clazz == nullptr)
|
||||
return -3;
|
||||
|
||||
jmethodID method_id = java_env->GetMethodID(native_activity_clazz, "pollUnicodeChar", "()I");
|
||||
if (method_id == NULL)
|
||||
if (method_id == nullptr)
|
||||
return -4;
|
||||
|
||||
// Send the actual characters to Dear ImGui
|
||||
|
||||
21
examples/example_apple_metal/Makefile
Normal file
21
examples/example_apple_metal/Makefile
Normal file
@@ -0,0 +1,21 @@
|
||||
# Makefile for example_apple_metal, for macOS only (**not iOS**)
|
||||
CXX = clang++
|
||||
EXE = example_apple_metal
|
||||
IMGUI_DIR = ../../
|
||||
SOURCES = main.mm
|
||||
SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
|
||||
SOURCES += $(IMGUI_DIR)/backends/imgui_impl_osx.mm $(IMGUI_DIR)/backends/imgui_impl_metal.mm
|
||||
|
||||
CXXFLAGS = -std=c++11 -ObjC++ -fobjc-arc -Wall -Wextra -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
|
||||
FRAMEWORKS = -framework AppKit -framework Metal -framework MetalKit -framework QuartzCore -framework GameController
|
||||
|
||||
all: $(EXE)
|
||||
|
||||
$(EXE): $(SOURCES)
|
||||
$(CXX) $(CXXFLAGS) $^ $(FRAMEWORKS) -o $@
|
||||
|
||||
run: all
|
||||
./$(EXE)
|
||||
|
||||
clean:
|
||||
rm -f $(EXE) *.o
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
This example shows how to integrate Dear ImGui with Metal. It is based on the "cross-platform" game template provided with Xcode as of Xcode 9.
|
||||
|
||||
Consider basing your work off the example_glfw_metal/ or example_sdl_metal/ examples. They are better supported and will be portable unlike this one.
|
||||
Consider basing your work off the example_glfw_metal/ or example_sdl2_metal/ examples. They are better supported and will be portable unlike this one.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -3,10 +3,11 @@
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 48;
|
||||
objectVersion = 54;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
05318E0F274C397200A8DE2E /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05318E0E274C397200A8DE2E /* GameController.framework */; };
|
||||
07A82ED82139413D0078D120 /* imgui_widgets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07A82ED72139413C0078D120 /* imgui_widgets.cpp */; };
|
||||
07A82ED92139418F0078D120 /* imgui_widgets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07A82ED72139413C0078D120 /* imgui_widgets.cpp */; };
|
||||
5079822E257677DB0038A28D /* imgui_tables.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5079822D257677DB0038A28D /* imgui_tables.cpp */; };
|
||||
@@ -32,6 +33,7 @@
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
05318E0E274C397200A8DE2E /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = System/Library/Frameworks/GameController.framework; sourceTree = SDKROOT; };
|
||||
07A82ED62139413C0078D120 /* imgui_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui_internal.h; path = ../../imgui_internal.h; sourceTree = "<group>"; };
|
||||
07A82ED72139413C0078D120 /* imgui_widgets.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_widgets.cpp; path = ../../imgui_widgets.cpp; sourceTree = "<group>"; };
|
||||
5079822D257677DB0038A28D /* imgui_tables.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_tables.cpp; path = ../../imgui_tables.cpp; sourceTree = "<group>"; };
|
||||
@@ -76,6 +78,7 @@
|
||||
files = (
|
||||
8309BDC6253CCCFE0045E2A1 /* AppKit.framework in Frameworks */,
|
||||
83BBE9EC20EB471700295997 /* MetalKit.framework in Frameworks */,
|
||||
05318E0F274C397200A8DE2E /* GameController.framework in Frameworks */,
|
||||
83BBE9ED20EB471700295997 /* Metal.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -133,6 +136,7 @@
|
||||
83BBE9E320EB46B800295997 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
05318E0E274C397200A8DE2E /* GameController.framework */,
|
||||
8309BDC5253CCCFE0045E2A1 /* AppKit.framework */,
|
||||
8309BD8E253CCAAA0045E2A1 /* UIKit.framework */,
|
||||
83BBE9EE20EB471C00295997 /* ModelIO.framework */,
|
||||
@@ -205,7 +209,8 @@
|
||||
8307E7B620E9F9C700473790 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 1200;
|
||||
BuildIndependentTargetsInParallel = YES;
|
||||
LastUpgradeCheck = 1530;
|
||||
ORGANIZATIONNAME = "Warren Moore";
|
||||
TargetAttributes = {
|
||||
8307E7C320E9F9C900473790 = {
|
||||
@@ -264,9 +269,9 @@
|
||||
8309BDBB253CCCAD0045E2A1 /* imgui_impl_metal.mm in Sources */,
|
||||
83BBEA0920EB54E700295997 /* imgui.cpp in Sources */,
|
||||
83BBEA0720EB54E700295997 /* imgui_demo.cpp in Sources */,
|
||||
83BBEA0520EB54E700295997 /* imgui_draw.cpp in Sources */,
|
||||
83BBEA0520EB54E700295997 /* imgui_draw.cpp in Sources */,
|
||||
5079822E257677DB0038A28D /* imgui_tables.cpp in Sources */,
|
||||
07A82ED82139413D0078D120 /* imgui_widgets.cpp in Sources */,
|
||||
07A82ED82139413D0078D120 /* imgui_widgets.cpp in Sources */,
|
||||
8309BDA5253CCC070045E2A1 /* main.mm in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -277,10 +282,10 @@
|
||||
files = (
|
||||
8309BDBE253CCCB60045E2A1 /* imgui_impl_metal.mm in Sources */,
|
||||
8309BDBF253CCCB60045E2A1 /* imgui_impl_osx.mm in Sources */,
|
||||
83BBEA0A20EB54E700295997 /* imgui.cpp in Sources */,
|
||||
83BBEA0820EB54E700295997 /* imgui_demo.cpp in Sources */,
|
||||
83BBEA0620EB54E700295997 /* imgui_draw.cpp in Sources */,
|
||||
5079822E257677DB0038A28D /* imgui_tables.cpp in Sources */,
|
||||
83BBEA0A20EB54E700295997 /* imgui.cpp in Sources */,
|
||||
83BBEA0820EB54E700295997 /* imgui_demo.cpp in Sources */,
|
||||
83BBEA0620EB54E700295997 /* imgui_draw.cpp in Sources */,
|
||||
5079822E257677DB0038A28D /* imgui_tables.cpp in Sources */,
|
||||
07A82ED92139418F0078D120 /* imgui_widgets.cpp in Sources */,
|
||||
8309BDA8253CCC080045E2A1 /* main.mm in Sources */,
|
||||
);
|
||||
@@ -323,9 +328,11 @@
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
@@ -379,9 +386,11 @@
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
@@ -401,8 +410,11 @@
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
INFOPLIST_FILE = "$(SRCROOT)/iOS/Info-iOS.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.apple-metal-ios";
|
||||
PRODUCT_NAME = example_apple_metal;
|
||||
SDKROOT = iphoneos;
|
||||
@@ -418,8 +430,11 @@
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
INFOPLIST_FILE = "$(SRCROOT)/iOS/Info-iOS.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.apple-metal-ios";
|
||||
PRODUCT_NAME = example_apple_metal;
|
||||
SDKROOT = iphoneos;
|
||||
@@ -435,10 +450,14 @@
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
INFOPLIST_FILE = "$(SRCROOT)/macOS/Info-macOS.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.12;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.apple-metal-macos";
|
||||
PRODUCT_NAME = example_apple_metal;
|
||||
SDKROOT = macosx;
|
||||
@@ -452,10 +471,14 @@
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
INFOPLIST_FILE = "$(SRCROOT)/macOS/Info-macOS.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.12;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.apple-metal-macos";
|
||||
PRODUCT_NAME = example_apple_metal;
|
||||
SDKROOT = macosx;
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
// Dear ImGui: standalone example application for OSX + Metal.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@@ -15,26 +19,28 @@
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_metal.h"
|
||||
|
||||
#if TARGET_OS_OSX
|
||||
#include "imgui_impl_osx.h"
|
||||
|
||||
@interface ViewController : NSViewController
|
||||
@interface AppViewController : NSViewController<NSWindowDelegate>
|
||||
@end
|
||||
#else
|
||||
@interface ViewController : UIViewController
|
||||
@interface AppViewController : UIViewController
|
||||
@end
|
||||
#endif
|
||||
|
||||
@interface ViewController () <MTKViewDelegate>
|
||||
@interface AppViewController () <MTKViewDelegate>
|
||||
@property (nonatomic, readonly) MTKView *mtkView;
|
||||
@property (nonatomic, strong) id <MTLDevice> device;
|
||||
@property (nonatomic, strong) id <MTLCommandQueue> commandQueue;
|
||||
@end
|
||||
|
||||
@implementation ViewController
|
||||
//-----------------------------------------------------------------------------------
|
||||
// AppViewController
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
- (instancetype)initWithNibName:(nullable NSString *)nibNameOrNil bundle:(nullable NSBundle *)nibBundleOrNil
|
||||
@implementation AppViewController
|
||||
|
||||
-(instancetype)initWithNibName:(nullable NSString *)nibNameOrNil bundle:(nullable NSBundle *)nibBundleOrNil
|
||||
{
|
||||
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
|
||||
|
||||
@@ -52,45 +58,48 @@
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
|
||||
|
||||
// Setup Dear ImGui style
|
||||
ImGui::StyleColorsDark();
|
||||
//ImGui::StyleColorsClassic();
|
||||
//ImGui::StyleColorsLight();
|
||||
|
||||
// Setup Renderer backend
|
||||
ImGui_ImplMetal_Init(_device);
|
||||
|
||||
// Load Fonts
|
||||
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
|
||||
// - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
|
||||
// - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
|
||||
// - Read 'docs/FONTS.txt' for more instructions and details.
|
||||
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
|
||||
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
|
||||
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
//io.Fonts->AddFontDefault();
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
|
||||
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
|
||||
//IM_ASSERT(font != NULL);
|
||||
//style.FontSizeBase = 20.0f;
|
||||
//io.Fonts->AddFontDefaultVector();
|
||||
//io.Fonts->AddFontDefaultBitmap();
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf");
|
||||
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf");
|
||||
//IM_ASSERT(font != nullptr);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (MTKView *)mtkView
|
||||
-(MTKView *)mtkView
|
||||
{
|
||||
return (MTKView *)self.view;
|
||||
}
|
||||
|
||||
- (void)loadView
|
||||
-(void)loadView
|
||||
{
|
||||
self.view = [[MTKView alloc] initWithFrame:CGRectMake(0, 0, 1200, 720)];
|
||||
self.view = [[MTKView alloc] initWithFrame:CGRectMake(0, 0, 1200, 800)];
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
-(void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
|
||||
@@ -98,129 +107,12 @@
|
||||
self.mtkView.delegate = self;
|
||||
|
||||
#if TARGET_OS_OSX
|
||||
// Add a tracking area in order to receive mouse events whenever the mouse is within the bounds of our view
|
||||
NSTrackingArea *trackingArea = [[NSTrackingArea alloc] initWithRect:NSZeroRect
|
||||
options:NSTrackingMouseMoved | NSTrackingInVisibleRect | NSTrackingActiveAlways
|
||||
owner:self
|
||||
userInfo:nil];
|
||||
[self.view addTrackingArea:trackingArea];
|
||||
|
||||
// If we want to receive key events, we either need to be in the responder chain of the key view,
|
||||
// or else we can install a local monitor. The consequence of this heavy-handed approach is that
|
||||
// we receive events for all controls, not just Dear ImGui widgets. If we had native controls in our
|
||||
// window, we'd want to be much more careful than just ingesting the complete event stream.
|
||||
// To match the behavior of other backends, we pass every event down to the OS.
|
||||
NSEventMask eventMask = NSEventMaskKeyDown | NSEventMaskKeyUp | NSEventMaskFlagsChanged | NSEventTypeScrollWheel;
|
||||
[NSEvent addLocalMonitorForEventsMatchingMask:eventMask handler:^NSEvent * _Nullable(NSEvent *event)
|
||||
{
|
||||
ImGui_ImplOSX_HandleEvent(event, self.view);
|
||||
return event;
|
||||
}];
|
||||
|
||||
ImGui_ImplOSX_Init();
|
||||
|
||||
ImGui_ImplOSX_Init(self.view);
|
||||
[NSApp activateIgnoringOtherApps:YES];
|
||||
#endif
|
||||
}
|
||||
|
||||
#pragma mark - Interaction
|
||||
|
||||
#if TARGET_OS_OSX
|
||||
|
||||
- (void)mouseMoved:(NSEvent *)event {
|
||||
ImGui_ImplOSX_HandleEvent(event, self.view);
|
||||
}
|
||||
|
||||
- (void)mouseDown:(NSEvent *)event {
|
||||
ImGui_ImplOSX_HandleEvent(event, self.view);
|
||||
}
|
||||
|
||||
- (void)rightMouseDown:(NSEvent *)event {
|
||||
ImGui_ImplOSX_HandleEvent(event, self.view);
|
||||
}
|
||||
|
||||
- (void)otherMouseDown:(NSEvent *)event {
|
||||
ImGui_ImplOSX_HandleEvent(event, self.view);
|
||||
}
|
||||
|
||||
- (void)mouseUp:(NSEvent *)event {
|
||||
ImGui_ImplOSX_HandleEvent(event, self.view);
|
||||
}
|
||||
|
||||
- (void)rightMouseUp:(NSEvent *)event {
|
||||
ImGui_ImplOSX_HandleEvent(event, self.view);
|
||||
}
|
||||
|
||||
- (void)otherMouseUp:(NSEvent *)event {
|
||||
ImGui_ImplOSX_HandleEvent(event, self.view);
|
||||
}
|
||||
|
||||
- (void)mouseDragged:(NSEvent *)event {
|
||||
ImGui_ImplOSX_HandleEvent(event, self.view);
|
||||
}
|
||||
|
||||
- (void)rightMouseDragged:(NSEvent *)event {
|
||||
ImGui_ImplOSX_HandleEvent(event, self.view);
|
||||
}
|
||||
|
||||
- (void)otherMouseDragged:(NSEvent *)event {
|
||||
ImGui_ImplOSX_HandleEvent(event, self.view);
|
||||
}
|
||||
|
||||
- (void)scrollWheel:(NSEvent *)event {
|
||||
ImGui_ImplOSX_HandleEvent(event, self.view);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// This touch mapping is super cheesy/hacky. We treat any touch on the screen
|
||||
// as if it were a depressed left mouse button, and we don't bother handling
|
||||
// multitouch correctly at all. This causes the "cursor" to behave very erratically
|
||||
// when there are multiple active touches. But for demo purposes, single-touch
|
||||
// interaction actually works surprisingly well.
|
||||
- (void)updateIOWithTouchEvent:(UIEvent *)event
|
||||
{
|
||||
UITouch *anyTouch = event.allTouches.anyObject;
|
||||
CGPoint touchLocation = [anyTouch locationInView:self.view];
|
||||
ImGuiIO &io = ImGui::GetIO();
|
||||
io.MousePos = ImVec2(touchLocation.x, touchLocation.y);
|
||||
|
||||
BOOL hasActiveTouch = NO;
|
||||
for (UITouch *touch in event.allTouches)
|
||||
{
|
||||
if (touch.phase != UITouchPhaseEnded && touch.phase != UITouchPhaseCancelled)
|
||||
{
|
||||
hasActiveTouch = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
io.MouseDown[0] = hasActiveTouch;
|
||||
}
|
||||
|
||||
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
|
||||
{
|
||||
[self updateIOWithTouchEvent:event];
|
||||
}
|
||||
|
||||
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
|
||||
{
|
||||
[self updateIOWithTouchEvent:event];
|
||||
}
|
||||
|
||||
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
|
||||
{
|
||||
[self updateIOWithTouchEvent:event];
|
||||
}
|
||||
|
||||
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
|
||||
{
|
||||
[self updateIOWithTouchEvent:event];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#pragma mark - MTKViewDelegate
|
||||
|
||||
- (void)drawInMTKView:(MTKView*)view
|
||||
-(void)drawInMTKView:(MTKView*)view
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.DisplaySize.x = view.bounds.size.width;
|
||||
@@ -233,90 +125,142 @@
|
||||
#endif
|
||||
io.DisplayFramebufferScale = ImVec2(framebufferScale, framebufferScale);
|
||||
|
||||
io.DeltaTime = 1 / float(view.preferredFramesPerSecond ?: 60);
|
||||
|
||||
id<MTLCommandBuffer> commandBuffer = [self.commandQueue commandBuffer];
|
||||
|
||||
MTLRenderPassDescriptor* renderPassDescriptor = view.currentRenderPassDescriptor;
|
||||
if (renderPassDescriptor == nil)
|
||||
{
|
||||
[commandBuffer commit];
|
||||
return;
|
||||
}
|
||||
|
||||
// Start the Dear ImGui frame
|
||||
ImGui_ImplMetal_NewFrame(renderPassDescriptor);
|
||||
#if TARGET_OS_OSX
|
||||
ImGui_ImplOSX_NewFrame(view);
|
||||
#endif
|
||||
ImGui::NewFrame();
|
||||
|
||||
// Our state (make them static = more or less global) as a convenience to keep the example terse.
|
||||
static bool show_demo_window = true;
|
||||
static bool show_another_window = false;
|
||||
static float clear_color[4] = { 0.28f, 0.36f, 0.5f, 1.0f };
|
||||
static ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
||||
|
||||
MTLRenderPassDescriptor* renderPassDescriptor = view.currentRenderPassDescriptor;
|
||||
if (renderPassDescriptor != nil)
|
||||
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
|
||||
if (show_demo_window)
|
||||
ImGui::ShowDemoWindow(&show_demo_window);
|
||||
|
||||
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window.
|
||||
{
|
||||
renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(clear_color[0] * clear_color[3], clear_color[1] * clear_color[3], clear_color[2] * clear_color[3], clear_color[3]);
|
||||
static float f = 0.0f;
|
||||
static int counter = 0;
|
||||
|
||||
// Here, you could do additional rendering work, including other passes as necessary.
|
||||
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
|
||||
|
||||
id <MTLRenderCommandEncoder> renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
|
||||
[renderEncoder pushDebugGroup:@"ImGui demo"];
|
||||
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
|
||||
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
|
||||
ImGui::Checkbox("Another Window", &show_another_window);
|
||||
|
||||
// Start the Dear ImGui frame
|
||||
ImGui_ImplMetal_NewFrame(renderPassDescriptor);
|
||||
#if TARGET_OS_OSX
|
||||
ImGui_ImplOSX_NewFrame(view);
|
||||
#endif
|
||||
ImGui::NewFrame();
|
||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
|
||||
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
|
||||
|
||||
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
|
||||
if (show_demo_window)
|
||||
ImGui::ShowDemoWindow(&show_demo_window);
|
||||
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
|
||||
counter++;
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("counter = %d", counter);
|
||||
|
||||
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
|
||||
{
|
||||
static float f = 0.0f;
|
||||
static int counter = 0;
|
||||
|
||||
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
|
||||
|
||||
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
|
||||
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
|
||||
ImGui::Checkbox("Another Window", &show_another_window);
|
||||
|
||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
|
||||
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
|
||||
|
||||
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
|
||||
counter++;
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("counter = %d", counter);
|
||||
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// 3. Show another simple window.
|
||||
if (show_another_window)
|
||||
{
|
||||
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
|
||||
ImGui::Text("Hello from another window!");
|
||||
if (ImGui::Button("Close Me"))
|
||||
show_another_window = false;
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// Rendering
|
||||
ImGui::Render();
|
||||
ImDrawData* draw_data = ImGui::GetDrawData();
|
||||
ImGui_ImplMetal_RenderDrawData(draw_data, commandBuffer, renderEncoder);
|
||||
|
||||
[renderEncoder popDebugGroup];
|
||||
[renderEncoder endEncoding];
|
||||
|
||||
[commandBuffer presentDrawable:view.currentDrawable];
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// 3. Show another simple window.
|
||||
if (show_another_window)
|
||||
{
|
||||
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
|
||||
ImGui::Text("Hello from another window!");
|
||||
if (ImGui::Button("Close Me"))
|
||||
show_another_window = false;
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// Rendering
|
||||
ImGui::Render();
|
||||
ImDrawData* draw_data = ImGui::GetDrawData();
|
||||
|
||||
renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
|
||||
id <MTLRenderCommandEncoder> renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
|
||||
[renderEncoder pushDebugGroup:@"Dear ImGui rendering"];
|
||||
ImGui_ImplMetal_RenderDrawData(draw_data, commandBuffer, renderEncoder);
|
||||
[renderEncoder popDebugGroup];
|
||||
[renderEncoder endEncoding];
|
||||
|
||||
// Present
|
||||
[commandBuffer presentDrawable:view.currentDrawable];
|
||||
[commandBuffer commit];
|
||||
}
|
||||
|
||||
- (void)mtkView:(MTKView*)view drawableSizeWillChange:(CGSize)size
|
||||
-(void)mtkView:(MTKView*)view drawableSizeWillChange:(CGSize)size
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
// Input processing
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
#if TARGET_OS_OSX
|
||||
|
||||
- (void)viewWillAppear
|
||||
{
|
||||
[super viewWillAppear];
|
||||
self.view.window.delegate = self;
|
||||
}
|
||||
|
||||
- (void)windowWillClose:(NSNotification *)notification
|
||||
{
|
||||
ImGui_ImplMetal_Shutdown();
|
||||
ImGui_ImplOSX_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// This touch mapping is super cheesy/hacky. We treat any touch on the screen
|
||||
// as if it were a depressed left mouse button, and we don't bother handling
|
||||
// multitouch correctly at all. This causes the "cursor" to behave very erratically
|
||||
// when there are multiple active touches. But for demo purposes, single-touch
|
||||
// interaction actually works surprisingly well.
|
||||
-(void)updateIOWithTouchEvent:(UIEvent *)event
|
||||
{
|
||||
UITouch *anyTouch = event.allTouches.anyObject;
|
||||
CGPoint touchLocation = [anyTouch locationInView:self.view];
|
||||
ImGuiIO &io = ImGui::GetIO();
|
||||
io.AddMouseSourceEvent(ImGuiMouseSource_TouchScreen);
|
||||
io.AddMousePosEvent(touchLocation.x, touchLocation.y);
|
||||
|
||||
BOOL hasActiveTouch = NO;
|
||||
for (UITouch *touch in event.allTouches)
|
||||
{
|
||||
if (touch.phase != UITouchPhaseEnded && touch.phase != UITouchPhaseCancelled)
|
||||
{
|
||||
hasActiveTouch = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
io.AddMouseButtonEvent(0, hasActiveTouch);
|
||||
}
|
||||
|
||||
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [self updateIOWithTouchEvent:event]; }
|
||||
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [self updateIOWithTouchEvent:event]; }
|
||||
-(void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [self updateIOWithTouchEvent:event]; }
|
||||
-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [self updateIOWithTouchEvent:event]; }
|
||||
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - Application Delegate
|
||||
//-----------------------------------------------------------------------------------
|
||||
// AppDelegate
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
#if TARGET_OS_OSX
|
||||
|
||||
@@ -326,28 +270,27 @@
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
- (instancetype)init
|
||||
-(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
-(instancetype)init
|
||||
{
|
||||
if (self = [super init])
|
||||
{
|
||||
NSViewController *rootViewController = [[ViewController alloc] initWithNibName:nil bundle:nil];
|
||||
NSViewController *rootViewController = [[AppViewController alloc] initWithNibName:nil bundle:nil];
|
||||
self.window = [[NSWindow alloc] initWithContentRect:NSZeroRect
|
||||
styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable | NSWindowStyleMaskMiniaturizable
|
||||
backing:NSBackingStoreBuffered
|
||||
defer:NO];
|
||||
self.window.contentViewController = rootViewController;
|
||||
[self.window orderFront:self];
|
||||
[self.window center];
|
||||
[self.window becomeKeyWindow];
|
||||
[self.window makeKeyAndOrderFront:self];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#else
|
||||
@@ -358,10 +301,10 @@
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
- (BOOL)application:(UIApplication *)application
|
||||
-(BOOL)application:(UIApplication *)application
|
||||
didFinishLaunchingWithOptions:(NSDictionary<UIApplicationLaunchOptionsKey,id> *)launchOptions
|
||||
{
|
||||
UIViewController *rootViewController = [[ViewController alloc] init];
|
||||
UIViewController *rootViewController = [[AppViewController alloc] init];
|
||||
self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
|
||||
self.window.rootViewController = rootViewController;
|
||||
[self.window makeKeyAndVisible];
|
||||
@@ -372,13 +315,26 @@
|
||||
|
||||
#endif
|
||||
|
||||
#pragma mark - main()
|
||||
//-----------------------------------------------------------------------------------
|
||||
// Application main() function
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
#if TARGET_OS_OSX
|
||||
|
||||
int main(int argc, const char * argv[])
|
||||
int main(int, const char**)
|
||||
{
|
||||
return NSApplicationMain(argc, argv);
|
||||
@autoreleasepool
|
||||
{
|
||||
[NSApplication sharedApplication];
|
||||
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
|
||||
|
||||
AppDelegate *appDelegate = [[AppDelegate alloc] init]; // creates window
|
||||
[NSApp setDelegate:appDelegate];
|
||||
|
||||
[NSApp activateIgnoringOtherApps:YES];
|
||||
[NSApp run];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
21
examples/example_apple_opengl2/Makefile
Normal file
21
examples/example_apple_opengl2/Makefile
Normal file
@@ -0,0 +1,21 @@
|
||||
# Makefile for example_apple_metal, for macOS only (**not iOS**)
|
||||
CXX = clang++
|
||||
EXE = example_apple_opengl2
|
||||
IMGUI_DIR = ../../
|
||||
SOURCES = main.mm
|
||||
SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
|
||||
SOURCES += $(IMGUI_DIR)/backends/imgui_impl_osx.mm $(IMGUI_DIR)/backends/imgui_impl_opengl2.cpp
|
||||
|
||||
CXXFLAGS = -std=c++11 -ObjC++ -fobjc-arc -Wall -Wextra -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
|
||||
FRAMEWORKS = -framework Cocoa -framework OpenGL -framework GameController
|
||||
|
||||
all: $(EXE)
|
||||
|
||||
$(EXE): $(SOURCES)
|
||||
$(CXX) $(CXXFLAGS) $(SOURCES) -o $(EXE) $(FRAMEWORKS)
|
||||
|
||||
run: all
|
||||
./$(EXE)
|
||||
|
||||
clean:
|
||||
rm -f $(EXE) *.o
|
||||
@@ -7,6 +7,7 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
05E31B59274EF0700083FCB6 /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05E31B57274EF0360083FCB6 /* GameController.framework */; };
|
||||
07A82EDB213941D00078D120 /* imgui_widgets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07A82EDA213941D00078D120 /* imgui_widgets.cpp */; };
|
||||
4080A99820B02D340036BA46 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4080A98A20B02CD90036BA46 /* main.mm */; };
|
||||
4080A9A220B034280036BA46 /* imgui_impl_opengl2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4080A99E20B034280036BA46 /* imgui_impl_opengl2.cpp */; };
|
||||
@@ -32,6 +33,7 @@
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
05E31B57274EF0360083FCB6 /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = System/Library/Frameworks/GameController.framework; sourceTree = SDKROOT; };
|
||||
07A82EDA213941D00078D120 /* imgui_widgets.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_widgets.cpp; path = ../../imgui_widgets.cpp; sourceTree = "<group>"; };
|
||||
4080A96B20B029B00036BA46 /* example_osx_opengl2 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = example_osx_opengl2; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
4080A98A20B02CD90036BA46 /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = SOURCE_ROOT; };
|
||||
@@ -57,6 +59,7 @@
|
||||
files = (
|
||||
4080A9B520B034EA0036BA46 /* OpenGL.framework in Frameworks */,
|
||||
4080A9B320B034E40036BA46 /* Cocoa.framework in Frameworks */,
|
||||
05E31B59274EF0700083FCB6 /* GameController.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -95,6 +98,7 @@
|
||||
4080A9B120B034E40036BA46 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
05E31B57274EF0360083FCB6 /* GameController.framework */,
|
||||
4080A9B420B034EA0036BA46 /* OpenGL.framework */,
|
||||
4080A9B220B034E40036BA46 /* Cocoa.framework */,
|
||||
);
|
||||
@@ -285,9 +289,8 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.12;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SYSTEM_HEADER_SEARCH_PATHS = ../libs/gl3w;
|
||||
USER_HEADER_SEARCH_PATHS = ../..;
|
||||
};
|
||||
name = Debug;
|
||||
@@ -296,9 +299,8 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.12;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SYSTEM_HEADER_SEARCH_PATHS = ../libs/gl3w;
|
||||
USER_HEADER_SEARCH_PATHS = ../..;
|
||||
};
|
||||
name = Release;
|
||||
|
||||
@@ -1,31 +1,30 @@
|
||||
// Dear ImGui: standalone example application for OSX + OpenGL2, using legacy fixed pipeline
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
|
||||
#include "imgui.h"
|
||||
#include "../../backends/imgui_impl_osx.h"
|
||||
#include "../../backends/imgui_impl_opengl2.h"
|
||||
#include <stdio.h>
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <OpenGL/gl.h>
|
||||
#import <OpenGL/glu.h>
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_opengl2.h"
|
||||
#include "imgui_impl_osx.h"
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
// ImGuiExampleView
|
||||
// AppView
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
@interface ImGuiExampleView : NSOpenGLView
|
||||
@interface AppView : NSOpenGLView
|
||||
{
|
||||
NSTimer* animationTimer;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation ImGuiExampleView
|
||||
|
||||
-(void)animationTimerFired:(NSTimer*)timer
|
||||
{
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
@implementation AppView
|
||||
|
||||
-(void)prepareOpenGL
|
||||
{
|
||||
@@ -39,11 +38,49 @@
|
||||
#endif
|
||||
}
|
||||
|
||||
-(void)initialize
|
||||
{
|
||||
// Setup Dear ImGui context
|
||||
// FIXME: This example doesn't have proper cleanup...
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
|
||||
|
||||
// Setup Dear ImGui style
|
||||
ImGui::StyleColorsDark();
|
||||
//ImGui::StyleColorsLight();
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
ImGui_ImplOSX_Init(self);
|
||||
ImGui_ImplOpenGL2_Init();
|
||||
|
||||
// Load Fonts
|
||||
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
|
||||
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
|
||||
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
//style.FontSizeBase = 20.0f;
|
||||
//io.Fonts->AddFontDefaultVector();
|
||||
//io.Fonts->AddFontDefaultBitmap();
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf");
|
||||
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf");
|
||||
//IM_ASSERT(font != nullptr);
|
||||
}
|
||||
|
||||
-(void)updateAndDrawDemoView
|
||||
{
|
||||
// Start the Dear ImGui frame
|
||||
ImGui_ImplOpenGL2_NewFrame();
|
||||
ImGui_ImplOSX_NewFrame(self);
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGui_ImplOpenGL2_NewFrame();
|
||||
ImGui_ImplOSX_NewFrame(self);
|
||||
ImGui::NewFrame();
|
||||
|
||||
// Our state (make them static = more or less global) as a convenience to keep the example terse.
|
||||
@@ -55,7 +92,7 @@
|
||||
if (show_demo_window)
|
||||
ImGui::ShowDemoWindow(&show_demo_window);
|
||||
|
||||
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
|
||||
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window.
|
||||
{
|
||||
static float f = 0.0f;
|
||||
static int counter = 0;
|
||||
@@ -74,7 +111,7 @@
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("counter = %d", counter);
|
||||
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
@@ -88,18 +125,18 @@
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// Rendering
|
||||
ImGui::Render();
|
||||
[[self openGLContext] makeCurrentContext];
|
||||
|
||||
// Rendering
|
||||
ImGui::Render();
|
||||
ImDrawData* draw_data = ImGui::GetDrawData();
|
||||
|
||||
[[self openGLContext] makeCurrentContext];
|
||||
GLsizei width = (GLsizei)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
|
||||
GLsizei height = (GLsizei)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
|
||||
glViewport(0, 0, width, height);
|
||||
glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
ImGui_ImplOpenGL2_RenderDrawData(draw_data);
|
||||
ImGui_ImplOpenGL2_RenderDrawData(draw_data);
|
||||
|
||||
// Present
|
||||
[[self openGLContext] flushBuffer];
|
||||
@@ -108,66 +145,22 @@
|
||||
animationTimer = [NSTimer scheduledTimerWithTimeInterval:0.017 target:self selector:@selector(animationTimerFired:) userInfo:nil repeats:YES];
|
||||
}
|
||||
|
||||
-(void)reshape
|
||||
{
|
||||
[[self openGLContext] update];
|
||||
[self updateAndDrawDemoView];
|
||||
}
|
||||
|
||||
-(void)drawRect:(NSRect)bounds
|
||||
{
|
||||
[self updateAndDrawDemoView];
|
||||
}
|
||||
|
||||
-(BOOL)acceptsFirstResponder
|
||||
{
|
||||
return (YES);
|
||||
}
|
||||
|
||||
-(BOOL)becomeFirstResponder
|
||||
{
|
||||
return (YES);
|
||||
}
|
||||
|
||||
-(BOOL)resignFirstResponder
|
||||
{
|
||||
return (YES);
|
||||
}
|
||||
|
||||
-(void)dealloc
|
||||
{
|
||||
animationTimer = nil;
|
||||
}
|
||||
|
||||
// Forward Mouse/Keyboard events to Dear ImGui OSX backend.
|
||||
-(void)keyUp:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); }
|
||||
-(void)keyDown:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); }
|
||||
-(void)flagsChanged:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); }
|
||||
-(void)mouseDown:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); }
|
||||
-(void)rightMouseDown:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); }
|
||||
-(void)otherMouseDown:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); }
|
||||
-(void)mouseUp:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); }
|
||||
-(void)rightMouseUp:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); }
|
||||
-(void)otherMouseUp:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); }
|
||||
-(void)mouseMoved:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); }
|
||||
-(void)rightMouseMoved:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); }
|
||||
-(void)otherMouseMoved:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); }
|
||||
-(void)mouseDragged:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); }
|
||||
-(void)rightMouseDragged:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); }
|
||||
-(void)otherMouseDragged:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); }
|
||||
-(void)scrollWheel:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); }
|
||||
-(void)reshape { [super reshape]; [[self openGLContext] update]; [self updateAndDrawDemoView]; }
|
||||
-(void)drawRect:(NSRect)bounds { [self updateAndDrawDemoView]; }
|
||||
-(void)animationTimerFired:(NSTimer*)timer { [self setNeedsDisplay:YES]; }
|
||||
-(void)dealloc { animationTimer = nil; }
|
||||
|
||||
@end
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
// ImGuiExampleAppDelegate
|
||||
// AppDelegate
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
@interface ImGuiExampleAppDelegate : NSObject <NSApplicationDelegate>
|
||||
@interface AppDelegate : NSObject <NSApplicationDelegate>
|
||||
@property (nonatomic, readonly) NSWindow* window;
|
||||
@end
|
||||
|
||||
@implementation ImGuiExampleAppDelegate
|
||||
@implementation AppDelegate
|
||||
@synthesize window = _window;
|
||||
|
||||
-(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication
|
||||
@@ -178,9 +171,9 @@
|
||||
-(NSWindow*)window
|
||||
{
|
||||
if (_window != nil)
|
||||
return (_window);
|
||||
return _window;
|
||||
|
||||
NSRect viewRect = NSMakeRect(100.0, 100.0, 100.0 + 1280.0, 100 + 720.0);
|
||||
NSRect viewRect = NSMakeRect(100.0, 100.0, 100.0 + 1280.0, 100 + 800.0);
|
||||
|
||||
_window = [[NSWindow alloc] initWithContentRect:viewRect styleMask:NSWindowStyleMaskTitled|NSWindowStyleMaskMiniaturizable|NSWindowStyleMaskResizable|NSWindowStyleMaskClosable backing:NSBackingStoreBuffered defer:YES];
|
||||
[_window setTitle:@"Dear ImGui OSX+OpenGL2 Example"];
|
||||
@@ -188,12 +181,12 @@
|
||||
[_window setOpaque:YES];
|
||||
[_window makeKeyAndOrderFront:NSApp];
|
||||
|
||||
return (_window);
|
||||
return _window;
|
||||
}
|
||||
|
||||
-(void)setupMenu
|
||||
{
|
||||
NSMenu* mainMenuBar = [[NSMenu alloc] init];
|
||||
NSMenu* mainMenuBar = [[NSMenu alloc] init];
|
||||
NSMenu* appMenu;
|
||||
NSMenuItem* menuItem;
|
||||
|
||||
@@ -217,11 +210,11 @@
|
||||
|
||||
-(void)applicationDidFinishLaunching:(NSNotification *)aNotification
|
||||
{
|
||||
// Make the application a foreground application (else it won't receive keyboard events)
|
||||
ProcessSerialNumber psn = {0, kCurrentProcess};
|
||||
TransformProcessType(&psn, kProcessTransformToForegroundApplication);
|
||||
// Make the application a foreground application (else it won't receive keyboard events)
|
||||
ProcessSerialNumber psn = {0, kCurrentProcess};
|
||||
TransformProcessType(&psn, kProcessTransformToForegroundApplication);
|
||||
|
||||
// Menu
|
||||
// Menu
|
||||
[self setupMenu];
|
||||
|
||||
NSOpenGLPixelFormatAttribute attrs[] =
|
||||
@@ -232,7 +225,7 @@
|
||||
};
|
||||
|
||||
NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
|
||||
ImGuiExampleView* view = [[ImGuiExampleView alloc] initWithFrame:self.window.frame pixelFormat:format];
|
||||
AppView* view = [[AppView alloc] initWithFrame:self.window.frame pixelFormat:format];
|
||||
format = nil;
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
|
||||
if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6)
|
||||
@@ -243,48 +236,23 @@
|
||||
if ([view openGLContext] == nil)
|
||||
NSLog(@"No OpenGL Context!");
|
||||
|
||||
// Setup Dear ImGui context
|
||||
// FIXME: This example doesn't have proper cleanup...
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
|
||||
|
||||
// Setup Dear ImGui style
|
||||
ImGui::StyleColorsDark();
|
||||
//ImGui::StyleColorsClassic();
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
ImGui_ImplOSX_Init();
|
||||
ImGui_ImplOpenGL2_Init();
|
||||
|
||||
// Load Fonts
|
||||
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
|
||||
// - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
|
||||
// - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
|
||||
// - Read 'docs/FONTS.txt' for more instructions and details.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
//io.Fonts->AddFontDefault();
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
|
||||
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
|
||||
//IM_ASSERT(font != NULL);
|
||||
[view initialize];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
// Application main() function
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
NSApp = [NSApplication sharedApplication];
|
||||
ImGuiExampleAppDelegate* delegate = [[ImGuiExampleAppDelegate alloc] init];
|
||||
[[NSApplication sharedApplication] setDelegate:delegate];
|
||||
[NSApp run];
|
||||
}
|
||||
return NSApplicationMain(argc, argv);
|
||||
@autoreleasepool
|
||||
{
|
||||
NSApp = [NSApplication sharedApplication];
|
||||
AppDelegate* delegate = [[AppDelegate alloc] init];
|
||||
[[NSApplication sharedApplication] setDelegate:delegate];
|
||||
[NSApp run];
|
||||
}
|
||||
return NSApplicationMain(argc, argv);
|
||||
}
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
## How to Build
|
||||
|
||||
- You need to install Emscripten from https://emscripten.org/docs/getting_started/downloads.html, and have the environment variables set, as described in https://emscripten.org/docs/getting_started/downloads.html#installation-instructions
|
||||
- You may also refer to our [Continuous Integration setup](https://github.com/ocornut/imgui/tree/master/.github/workflows) for Emscripten setup.
|
||||
- Depending on your configuration, in Windows you may need to run `emsdk/emsdk_env.bat` in your console to access the Emscripten command-line tools.
|
||||
- Then build using `make` while in the `example_emscripten_opengl3/` directory.
|
||||
|
||||
## How to Run
|
||||
|
||||
To run on a local machine:
|
||||
- `make serve` will use Python3 to spawn a local webserver, you can then browse http://localhost:8000 to access your build.
|
||||
- Otherwise, generally you will need a local webserver:
|
||||
- Quoting [https://emscripten.org/docs/getting_started](https://emscripten.org/docs/getting_started/Tutorial.html#generating-html):<br>
|
||||
_"Unfortunately several browsers (including Chrome, Safari, and Internet Explorer) do not support file:// [XHR](https://emscripten.org/docs/site/glossary.html#term-xhr) requests, and can’t load extra files needed by the HTML (like a .wasm file, or packaged file data as mentioned lower down). For these browsers you’ll need to serve the files using a [local webserver](https://emscripten.org/docs/getting_started/FAQ.html#faq-local-webserver) and then open http://localhost:8000/hello.html."_
|
||||
- Emscripten SDK has a handy `emrun` command: `emrun web/example_emscripten_opengl3.html --browser firefox` which will spawn a temporary local webserver (in Firefox). See https://emscripten.org/docs/compiling/Running-html-files-with-emrun.html for details.
|
||||
- You may use Python 3 builtin webserver: `python -m http.server -d web` (this is what `make serve` uses).
|
||||
- You may use Python 2 builtin webserver: `cd web && python -m SimpleHTTPServer`.
|
||||
|
||||
## Obsolete features:
|
||||
|
||||
- Emscripten 2.0 (August 2020) obsoleted the fastcomp backend, only llvm is supported.
|
||||
- Emscripten 1.39.0 (October 2019) obsoleted the `BINARYEN_TRAP_MODE=clamp` compilation flag which was required with version older than 1.39.0 to avoid rendering artefacts. See [#2877](https://github.com/ocornut/imgui/issues/2877) for details. If you use an older version, uncomment this line in the Makefile: `#EMS += -s BINARYEN_TRAP_MODE=clamp`
|
||||
@@ -1,174 +0,0 @@
|
||||
// Dear ImGui: standalone example application for Emscripten, using SDL2 + OpenGL3
|
||||
// (Emscripten is a C++-to-javascript compiler, used to publish executables for the web. See https://emscripten.org/)
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
|
||||
// This is mostly the same code as the SDL2 + OpenGL3 example, simply with the modifications needed to run on Emscripten.
|
||||
// It is possible to combine both code into a single source file that will compile properly on Desktop and using Emscripten.
|
||||
// See https://github.com/ocornut/imgui/pull/2492 as an example on how to do just that.
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_sdl.h"
|
||||
#include "imgui_impl_opengl3.h"
|
||||
#include <stdio.h>
|
||||
#include <emscripten.h>
|
||||
#include <SDL.h>
|
||||
#include <SDL_opengles2.h>
|
||||
|
||||
// Emscripten requires to have full control over the main loop. We're going to store our SDL book-keeping variables globally.
|
||||
// Having a single function that acts as a loop prevents us to store state in the stack of said function. So we need some location for this.
|
||||
SDL_Window* g_Window = NULL;
|
||||
SDL_GLContext g_GLContext = NULL;
|
||||
|
||||
// For clarity, our main loop code is declared at the end.
|
||||
static void main_loop(void*);
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
// Setup SDL
|
||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
|
||||
{
|
||||
printf("Error: %s\n", SDL_GetError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
// For the browser using Emscripten, we are going to use WebGL1 with GL ES2. See the Makefile. for requirement details.
|
||||
// It is very likely the generated file won't work in many browsers. Firefox is the only sure bet, but I have successfully
|
||||
// run this code on Chrome for Android for example.
|
||||
const char* glsl_version = "#version 100";
|
||||
//const char* glsl_version = "#version 300 es";
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||
|
||||
// Create window with graphics context
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
|
||||
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
|
||||
SDL_DisplayMode current;
|
||||
SDL_GetCurrentDisplayMode(0, ¤t);
|
||||
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
|
||||
g_Window = SDL_CreateWindow("Dear ImGui Emscripten example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
|
||||
g_GLContext = SDL_GL_CreateContext(g_Window);
|
||||
if (!g_GLContext)
|
||||
{
|
||||
fprintf(stderr, "Failed to initialize WebGL context!\n");
|
||||
return 1;
|
||||
}
|
||||
SDL_GL_SetSwapInterval(1); // Enable vsync
|
||||
|
||||
// Setup Dear ImGui context
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
|
||||
|
||||
// For an Emscripten build we are disabling file-system access, so let's not attempt to do a fopen() of the imgui.ini file.
|
||||
// You may manually call LoadIniSettingsFromMemory() to load settings from your own storage.
|
||||
io.IniFilename = NULL;
|
||||
|
||||
// Setup Dear ImGui style
|
||||
ImGui::StyleColorsDark();
|
||||
//ImGui::StyleColorsClassic();
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
ImGui_ImplSDL2_InitForOpenGL(g_Window, g_GLContext);
|
||||
ImGui_ImplOpenGL3_Init(glsl_version);
|
||||
|
||||
// Load Fonts
|
||||
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
|
||||
// - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
|
||||
// - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
// - Emscripten allows preloading a file or folder to be accessible at runtime. See Makefile for details.
|
||||
//io.Fonts->AddFontDefault();
|
||||
#ifndef IMGUI_DISABLE_FILE_FUNCTIONS
|
||||
io.Fonts->AddFontFromFileTTF("fonts/Roboto-Medium.ttf", 16.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("fonts/Cousine-Regular.ttf", 15.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("fonts/DroidSans.ttf", 16.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("fonts/ProggyTiny.ttf", 10.0f);
|
||||
//ImFont* font = io.Fonts->AddFontFromFileTTF("fonts/ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
|
||||
//IM_ASSERT(font != NULL);
|
||||
#endif
|
||||
|
||||
// This function call won't return, and will engage in an infinite loop, processing events from the browser, and dispatching them.
|
||||
emscripten_set_main_loop_arg(main_loop, NULL, 0, true);
|
||||
}
|
||||
|
||||
static void main_loop(void* arg)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IM_UNUSED(arg); // We can pass this argument as the second parameter of emscripten_set_main_loop_arg(), but we don't use that.
|
||||
|
||||
// Our state (make them static = more or less global) as a convenience to keep the example terse.
|
||||
static bool show_demo_window = true;
|
||||
static bool show_another_window = false;
|
||||
static ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
||||
|
||||
// Poll and handle events (inputs, window resize, etc.)
|
||||
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
|
||||
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event))
|
||||
{
|
||||
ImGui_ImplSDL2_ProcessEvent(&event);
|
||||
// Capture events here, based on io.WantCaptureMouse and io.WantCaptureKeyboard
|
||||
}
|
||||
|
||||
// Start the Dear ImGui frame
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplSDL2_NewFrame(g_Window);
|
||||
ImGui::NewFrame();
|
||||
|
||||
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
|
||||
if (show_demo_window)
|
||||
ImGui::ShowDemoWindow(&show_demo_window);
|
||||
|
||||
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
|
||||
{
|
||||
static float f = 0.0f;
|
||||
static int counter = 0;
|
||||
|
||||
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
|
||||
|
||||
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
|
||||
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
|
||||
ImGui::Checkbox("Another Window", &show_another_window);
|
||||
|
||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
|
||||
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
|
||||
|
||||
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
|
||||
counter++;
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("counter = %d", counter);
|
||||
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// 3. Show another simple window.
|
||||
if (show_another_window)
|
||||
{
|
||||
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
|
||||
ImGui::Text("Hello from another window!");
|
||||
if (ImGui::Button("Close Me"))
|
||||
show_another_window = false;
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// Rendering
|
||||
ImGui::Render();
|
||||
SDL_GL_MakeCurrent(g_Window, g_GLContext);
|
||||
glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
|
||||
glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
SDL_GL_SwapWindow(g_Window);
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
|
||||
# How to Build
|
||||
|
||||
- You need to install Emscripten from https://emscripten.org/docs/getting_started/downloads.html, and have the environment variables set, as described in https://emscripten.org/docs/getting_started/downloads.html#installation-instructions
|
||||
|
||||
- Depending on your configuration, in Windows you may need to run `emsdk/emsdk_env.bat` in your console to access the Emscripten command-line tools.
|
||||
|
||||
- Then build using `make` while in the `example_emscripten_wgpu/` directory.
|
||||
|
||||
- Requires Emscripten 2.0.10 (December 2020) due to GLFW adaptations
|
||||
@@ -1,245 +0,0 @@
|
||||
// Dear ImGui: standalone example application for Emscripten, using GLFW + WebGPU
|
||||
// (Emscripten is a C++-to-javascript compiler, used to publish executables for the web. See https://emscripten.org/)
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_glfw.h"
|
||||
#include "imgui_impl_wgpu.h"
|
||||
#include <stdio.h>
|
||||
#include <emscripten.h>
|
||||
#include <emscripten/html5.h>
|
||||
#include <emscripten/html5_webgpu.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <webgpu/webgpu.h>
|
||||
#include <webgpu/webgpu_cpp.h>
|
||||
|
||||
// Global WebGPU required states
|
||||
static WGPUDevice wgpu_device = NULL;
|
||||
static WGPUSurface wgpu_surface = NULL;
|
||||
static WGPUSwapChain wgpu_swap_chain = NULL;
|
||||
static int wgpu_swap_chain_width = 0;
|
||||
static int wgpu_swap_chain_height = 0;
|
||||
|
||||
// States tracked across render frames
|
||||
static bool show_demo_window = true;
|
||||
static bool show_another_window = false;
|
||||
static ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
||||
|
||||
// Forward declarations
|
||||
static bool init_wgpu();
|
||||
static void main_loop(void* window);
|
||||
static void print_glfw_error(int error, const char* description);
|
||||
static void print_wgpu_error(WGPUErrorType error_type, const char* message, void*);
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
glfwSetErrorCallback(print_glfw_error);
|
||||
if (!glfwInit())
|
||||
return 1;
|
||||
|
||||
// Make sure GLFW does not initialize any graphics context.
|
||||
// This needs to be done explicitly later
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
|
||||
GLFWwindow* window = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+WebGPU example", NULL, NULL);
|
||||
if (!window)
|
||||
{
|
||||
glfwTerminate();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Initialize the WebGPU environment
|
||||
if (!init_wgpu())
|
||||
{
|
||||
if (window)
|
||||
glfwDestroyWindow(window);
|
||||
glfwTerminate();
|
||||
return 1;
|
||||
}
|
||||
glfwShowWindow(window);
|
||||
|
||||
// Setup Dear ImGui context
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
|
||||
|
||||
// For an Emscripten build we are disabling file-system access, so let's not attempt to do a fopen() of the imgui.ini file.
|
||||
// You may manually call LoadIniSettingsFromMemory() to load settings from your own storage.
|
||||
io.IniFilename = NULL;
|
||||
|
||||
// Setup Dear ImGui style
|
||||
ImGui::StyleColorsDark();
|
||||
//ImGui::StyleColorsClassic();
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
ImGui_ImplGlfw_InitForOther(window, true);
|
||||
ImGui_ImplWGPU_Init(wgpu_device, 3, WGPUTextureFormat_RGBA8Unorm);
|
||||
|
||||
// Load Fonts
|
||||
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
|
||||
// - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
|
||||
// - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
// - Emscripten allows preloading a file or folder to be accessible at runtime. See Makefile for details.
|
||||
//io.Fonts->AddFontDefault();
|
||||
#ifndef IMGUI_DISABLE_FILE_FUNCTIONS
|
||||
io.Fonts->AddFontFromFileTTF("fonts/Roboto-Medium.ttf", 16.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("fonts/Cousine-Regular.ttf", 15.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("fonts/DroidSans.ttf", 16.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("fonts/ProggyTiny.ttf", 10.0f);
|
||||
//ImFont* font = io.Fonts->AddFontFromFileTTF("fonts/ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
|
||||
//IM_ASSERT(font != NULL);
|
||||
#endif
|
||||
|
||||
// This function will directly return and exit the main function.
|
||||
// Make sure that no required objects get cleaned up.
|
||||
// This way we can use the browsers 'requestAnimationFrame' to control the rendering.
|
||||
emscripten_set_main_loop_arg(main_loop, window, 0, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool init_wgpu()
|
||||
{
|
||||
wgpu_device = emscripten_webgpu_get_device();
|
||||
if (!wgpu_device)
|
||||
return false;
|
||||
|
||||
wgpuDeviceSetUncapturedErrorCallback(wgpu_device, print_wgpu_error, NULL);
|
||||
|
||||
// Use C++ wrapper due to misbehavior in Emscripten.
|
||||
// Some offset computation for wgpuInstanceCreateSurface in JavaScript
|
||||
// seem to be inline with struct alignments in the C++ structure
|
||||
wgpu::SurfaceDescriptorFromCanvasHTMLSelector html_surface_desc = {};
|
||||
html_surface_desc.selector = "#canvas";
|
||||
|
||||
wgpu::SurfaceDescriptor surface_desc = {};
|
||||
surface_desc.nextInChain = &html_surface_desc;
|
||||
|
||||
// Use 'null' instance
|
||||
wgpu::Instance instance = {};
|
||||
wgpu_surface = instance.CreateSurface(&surface_desc).Release();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void main_loop(void* window)
|
||||
{
|
||||
glfwPollEvents();
|
||||
|
||||
int width, height;
|
||||
glfwGetFramebufferSize((GLFWwindow*) window, &width, &height);
|
||||
|
||||
// React to changes in screen size
|
||||
if (width != wgpu_swap_chain_width && height != wgpu_swap_chain_height)
|
||||
{
|
||||
ImGui_ImplWGPU_InvalidateDeviceObjects();
|
||||
|
||||
if (wgpu_swap_chain)
|
||||
wgpuSwapChainRelease(wgpu_swap_chain);
|
||||
|
||||
wgpu_swap_chain_width = width;
|
||||
wgpu_swap_chain_height = height;
|
||||
|
||||
WGPUSwapChainDescriptor swap_chain_desc = {};
|
||||
swap_chain_desc.usage = WGPUTextureUsage_RenderAttachment;
|
||||
swap_chain_desc.format = WGPUTextureFormat_RGBA8Unorm;
|
||||
swap_chain_desc.width = width;
|
||||
swap_chain_desc.height = height;
|
||||
swap_chain_desc.presentMode = WGPUPresentMode_Fifo;
|
||||
wgpu_swap_chain = wgpuDeviceCreateSwapChain(wgpu_device, wgpu_surface, &swap_chain_desc);
|
||||
|
||||
ImGui_ImplWGPU_CreateDeviceObjects();
|
||||
}
|
||||
|
||||
// Start the Dear ImGui frame
|
||||
ImGui_ImplWGPU_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
|
||||
if (show_demo_window)
|
||||
ImGui::ShowDemoWindow(&show_demo_window);
|
||||
|
||||
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
|
||||
{
|
||||
static float f = 0.0f;
|
||||
static int counter = 0;
|
||||
|
||||
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
|
||||
|
||||
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
|
||||
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
|
||||
ImGui::Checkbox("Another Window", &show_another_window);
|
||||
|
||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
|
||||
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
|
||||
|
||||
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
|
||||
counter++;
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("counter = %d", counter);
|
||||
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// 3. Show another simple window.
|
||||
if (show_another_window)
|
||||
{
|
||||
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
|
||||
ImGui::Text("Hello from another window!");
|
||||
if (ImGui::Button("Close Me"))
|
||||
show_another_window = false;
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// Rendering
|
||||
ImGui::Render();
|
||||
|
||||
WGPURenderPassColorAttachment color_attachments = {};
|
||||
color_attachments.loadOp = WGPULoadOp_Clear;
|
||||
color_attachments.storeOp = WGPUStoreOp_Store;
|
||||
color_attachments.clearColor = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w };
|
||||
color_attachments.view = wgpuSwapChainGetCurrentTextureView(wgpu_swap_chain);
|
||||
WGPURenderPassDescriptor render_pass_desc = {};
|
||||
render_pass_desc.colorAttachmentCount = 1;
|
||||
render_pass_desc.colorAttachments = &color_attachments;
|
||||
render_pass_desc.depthStencilAttachment = NULL;
|
||||
|
||||
WGPUCommandEncoderDescriptor enc_desc = {};
|
||||
WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(wgpu_device, &enc_desc);
|
||||
|
||||
WGPURenderPassEncoder pass = wgpuCommandEncoderBeginRenderPass(encoder, &render_pass_desc);
|
||||
ImGui_ImplWGPU_RenderDrawData(ImGui::GetDrawData(), pass);
|
||||
wgpuRenderPassEncoderEndPass(pass);
|
||||
|
||||
WGPUCommandBufferDescriptor cmd_buffer_desc = {};
|
||||
WGPUCommandBuffer cmd_buffer = wgpuCommandEncoderFinish(encoder, &cmd_buffer_desc);
|
||||
WGPUQueue queue = wgpuDeviceGetQueue(wgpu_device);
|
||||
wgpuQueueSubmit(queue, 1, &cmd_buffer);
|
||||
}
|
||||
|
||||
static void print_glfw_error(int error, const char* description)
|
||||
{
|
||||
printf("Glfw Error %d: %s\n", error, description);
|
||||
}
|
||||
|
||||
static void print_wgpu_error(WGPUErrorType error_type, const char* message, void*)
|
||||
{
|
||||
const char* error_type_lbl = "";
|
||||
switch (error_type)
|
||||
{
|
||||
case WGPUErrorType_Validation: error_type_lbl = "Validation"; break;
|
||||
case WGPUErrorType_OutOfMemory: error_type_lbl = "Out of memory"; break;
|
||||
case WGPUErrorType_Unknown: error_type_lbl = "Unknown"; break;
|
||||
case WGPUErrorType_DeviceLost: error_type_lbl = "Device lost"; break;
|
||||
default: error_type_lbl = "Unknown";
|
||||
}
|
||||
printf("%s error: %s\n", error_type_lbl, message);
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en-us">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"/>
|
||||
<title>Dear ImGui Emscripten+WebGPU example</title>
|
||||
<style>
|
||||
body { margin: 0; background-color: black }
|
||||
.emscripten {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
margin: 0px;
|
||||
border: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
display: block;
|
||||
image-rendering: optimizeSpeed;
|
||||
image-rendering: -moz-crisp-edges;
|
||||
image-rendering: -o-crisp-edges;
|
||||
image-rendering: -webkit-optimize-contrast;
|
||||
image-rendering: optimize-contrast;
|
||||
image-rendering: crisp-edges;
|
||||
image-rendering: pixelated;
|
||||
-ms-interpolation-mode: nearest-neighbor;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
|
||||
<script type='text/javascript'>
|
||||
var Module;
|
||||
(async () => {
|
||||
Module = {
|
||||
preRun: [],
|
||||
postRun: [],
|
||||
print: (function() {
|
||||
return function(text) {
|
||||
text = Array.prototype.slice.call(arguments).join(' ');
|
||||
console.log(text);
|
||||
};
|
||||
})(),
|
||||
printErr: function(text) {
|
||||
text = Array.prototype.slice.call(arguments).join(' ');
|
||||
console.error(text);
|
||||
},
|
||||
canvas: (function() {
|
||||
var canvas = document.getElementById('canvas');
|
||||
//canvas.addEventListener("webglcontextlost", function(e) { alert('FIXME: WebGL context lost, please reload the page'); e.preventDefault(); }, false);
|
||||
return canvas;
|
||||
})(),
|
||||
setStatus: function(text) {
|
||||
console.log("status: " + text);
|
||||
},
|
||||
monitorRunDependencies: function(left) {
|
||||
// no run dependencies to log
|
||||
}
|
||||
};
|
||||
window.onerror = function() {
|
||||
console.log("onerror: " + event);
|
||||
};
|
||||
|
||||
// Initialize the graphics adapter
|
||||
{
|
||||
const adapter = await navigator.gpu.requestAdapter();
|
||||
const device = await adapter.requestDevice();
|
||||
Module.preinitializedWebGPUDevice = device;
|
||||
}
|
||||
|
||||
{
|
||||
const js = document.createElement('script');
|
||||
js.async = true;
|
||||
js.src = "index.js";
|
||||
document.body.appendChild(js);
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -14,10 +14,10 @@ SOURCES += $(IMGUI_DIR)/backends/imgui_impl_glfw.cpp $(IMGUI_DIR)/backends/imgui
|
||||
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
|
||||
|
||||
LIBS = -framework Metal -framework MetalKit -framework Cocoa -framework IOKit -framework CoreVideo -framework QuartzCore
|
||||
LIBS += -L/usr/local/lib -L/opt/homebrew/lib
|
||||
LIBS += -L/usr/local/lib -L/opt/homebrew/lib -L/opt/local/lib
|
||||
LIBS += -lglfw
|
||||
|
||||
CXXFLAGS = -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends -I/usr/local/include -I/opt/homebrew/include
|
||||
CXXFLAGS = -std=c++11 -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends -I/usr/local/include -I/opt/homebrew/include -I/opt/local/include
|
||||
CXXFLAGS += -Wall -Wformat
|
||||
CFLAGS = $(CXXFLAGS)
|
||||
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
// Dear ImGui: standalone example application for GLFW + Metal, using programmable pipeline
|
||||
// (GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan/Metal graphics context creation, etc.)
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_glfw.h"
|
||||
@@ -23,50 +27,58 @@ static void glfw_error_callback(int error, const char* description)
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
// Setup Dear ImGui context
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
|
||||
|
||||
// Setup style
|
||||
ImGui::StyleColorsDark();
|
||||
//ImGui::StyleColorsClassic();
|
||||
|
||||
// Load Fonts
|
||||
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
|
||||
// - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
|
||||
// - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
|
||||
// - Read 'docs/FONTS.txt' for more instructions and details.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
//io.Fonts->AddFontDefault();
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
|
||||
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
|
||||
//IM_ASSERT(font != NULL);
|
||||
|
||||
// Setup window
|
||||
glfwSetErrorCallback(glfw_error_callback);
|
||||
if (!glfwInit())
|
||||
return 1;
|
||||
|
||||
// Create window with graphics context
|
||||
float main_scale = ImGui_ImplGlfw_GetContentScaleForMonitor(glfwGetPrimaryMonitor()); // Valid on GLFW 3.3+ only
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
GLFWwindow* window = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+Metal example", NULL, NULL);
|
||||
if (window == NULL)
|
||||
GLFWwindow* window = glfwCreateWindow((int)(1280 * main_scale), (int)(800 * main_scale), "Dear ImGui GLFW+Metal example", nullptr, nullptr);
|
||||
if (window == nullptr)
|
||||
return 1;
|
||||
|
||||
id <MTLDevice> device = MTLCreateSystemDefaultDevice();;
|
||||
// Setup Dear ImGui context
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
|
||||
|
||||
// Setup Dear ImGui style
|
||||
ImGui::StyleColorsDark();
|
||||
//ImGui::StyleColorsLight();
|
||||
|
||||
// Setup scaling
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
|
||||
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
|
||||
|
||||
id <MTLDevice> device = MTLCreateSystemDefaultDevice();
|
||||
id <MTLCommandQueue> commandQueue = [device newCommandQueue];
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
ImGui_ImplGlfw_InitForOpenGL(window, true);
|
||||
ImGui_ImplMetal_Init(device);
|
||||
|
||||
// Load Fonts
|
||||
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
|
||||
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
|
||||
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
//style.FontSizeBase = 20.0f;
|
||||
//io.Fonts->AddFontDefaultVector();
|
||||
//io.Fonts->AddFontDefaultBitmap();
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf");
|
||||
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf");
|
||||
//IM_ASSERT(font != nullptr);
|
||||
|
||||
NSWindow *nswin = glfwGetCocoaWindow(window);
|
||||
CAMetalLayer *layer = [CAMetalLayer layer];
|
||||
layer.device = device;
|
||||
@@ -88,8 +100,8 @@ int main(int, char**)
|
||||
{
|
||||
// Poll and handle events (inputs, window resize, etc.)
|
||||
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
|
||||
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
|
||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||
glfwPollEvents();
|
||||
|
||||
@@ -115,7 +127,7 @@ int main(int, char**)
|
||||
if (show_demo_window)
|
||||
ImGui::ShowDemoWindow(&show_demo_window);
|
||||
|
||||
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
|
||||
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window.
|
||||
{
|
||||
static float f = 0.0f;
|
||||
static int counter = 0;
|
||||
@@ -134,7 +146,7 @@ int main(int, char**)
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("counter = %d", counter);
|
||||
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user