Compare commits
842 Commits
Author | SHA1 | Date | |
---|---|---|---|
e8cb874afe | |||
55ab515551 | |||
1266e4a181 | |||
f7f71043ca | |||
98047b1b65 | |||
f53d5da0f8 | |||
d6117e33d0 | |||
bc4ede656b | |||
b7d1b91e4b | |||
be8fb858cc | |||
b4ac413868 | |||
02a0967243 | |||
3ff04c95d5 | |||
52dd99915b | |||
0f25885b3d | |||
9d4d7f3381 | |||
298118fccc | |||
d19d8f40ba | |||
d170620816 | |||
4842ac3bc6 | |||
5e846612d3 | |||
80276ef07b | |||
6c3ab6fc9b | |||
a56768463a | |||
d750df9189 | |||
baa2328b99 | |||
d7a2a23457 | |||
8081e81e55 | |||
1a3ef63132 | |||
368d2c3568 | |||
0224d29a35 | |||
035ff302d2 | |||
95f489ac1f | |||
3e3d9f9a69 | |||
7ad4843f57 | |||
99a92ee7c5 | |||
8952b93b2f | |||
fcec337061 | |||
815168c7ef | |||
6ae8062ca0 | |||
c02f9b58ef | |||
fc6545830b | |||
faec745438 | |||
8cfd963fda | |||
355cbf6326 | |||
52c820e7b0 | |||
ba9317b924 | |||
5b053dd350 | |||
7eca4e2a7f | |||
fbb9113118 | |||
4565bf9813 | |||
6520b6c458 | |||
7a0004eb86 | |||
d10d0343b2 | |||
e681937f66 | |||
fd44b9440b | |||
b67593a4b1 | |||
8094aa78d2 | |||
827ff970cd | |||
d2701727b9 | |||
f2bed00d80 | |||
5ab23ab1c0 | |||
398ef1a212 | |||
245cf36522 | |||
890585cde8 | |||
08b1dd1035 | |||
fec09e37ab | |||
7d45c84f21 | |||
f4aae6b9ec | |||
09e8c4ec11 | |||
d81ba432ec | |||
e5bea65582 | |||
2f574ef952 | |||
60dd221737 | |||
bbaaab7537 | |||
4d2d0ce5cd | |||
8db229b96f | |||
c58d61dfd1 | |||
489e28ec11 | |||
1845ff4690 | |||
19e3c1506f | |||
e49977a913 | |||
d041ebc6d4 | |||
b7e63c163c | |||
b36ff2fec3 | |||
12aba576fb | |||
a14f6696a3 | |||
22e099366f | |||
4167528001 | |||
81cebb9c85 | |||
b7a2a6b23f | |||
44c23e0eed | |||
b3ae2976c5 | |||
046dbf502c | |||
e3b9a61883 | |||
ca042134ae | |||
1cd391146d | |||
67d93156df | |||
5f039e7098 | |||
7d144eb899 | |||
fb27360ea8 | |||
eee6dab226 | |||
54c2665032 | |||
439040bb25 | |||
d03b046ef4 | |||
d35c1a9e66 | |||
ac56e4e209 | |||
af7f35d7c2 | |||
87ebe95fd6 | |||
3e4841765d | |||
f4fc008a2a | |||
acf58c6223 | |||
bfa7d86070 | |||
c3ced1bd71 | |||
3869e10574 | |||
25882c47a3 | |||
502e360ee5 | |||
aeae03f4ac | |||
02dbcf5405 | |||
4d42760c0b | |||
de6dfe8c5d | |||
92b61d2ee4 | |||
b92396b46a | |||
6a22835f63 | |||
e7e2fcdd19 | |||
a17e47fe14 | |||
5782c69c2a | |||
9db4b35168 | |||
0ff2a6ff64 | |||
d6987d1586 | |||
c52cefa2c2 | |||
0d5e6e125c | |||
0676efd37f | |||
b2b616be00 | |||
f3303fa84f | |||
2633325b9f | |||
562aecdaa5 | |||
3fa4451936 | |||
1c160adbba | |||
c9676554b9 | |||
8b4a470e1d | |||
56553f33b8 | |||
19e59421e5 | |||
46c440d186 | |||
c09af38804 | |||
a74ca9025f | |||
a8b5f77591 | |||
0292c82b9c | |||
2f21347803 | |||
7959fbe992 | |||
f04c2002d6 | |||
0d7ca3da24 | |||
18fa8e1c7e | |||
61e551e0ee | |||
3b94c37efc | |||
f435e42561 | |||
d76bc3434e | |||
a33810d652 | |||
e9b81dd5ab | |||
fd3c6067bf | |||
7437b43b2d | |||
b69d7d9df3 | |||
2f03511062 | |||
6826ab3ffd | |||
0f9e2f8173 | |||
42efc29def | |||
4eba6cd470 | |||
b54cb1c24c | |||
b37a326163 | |||
5d59e965f6 | |||
7bd28d17ca | |||
531d0ce7ce | |||
0201fe6ed1 | |||
9bedcb5304 | |||
1b01137c90 | |||
bbc22ac8ca | |||
90ec28f6de | |||
e0da1e0658 | |||
77fad80e9f | |||
eaaab0120a | |||
fc7b562635 | |||
57f70a29b2 | |||
0e5b64ecd2 | |||
824cf5ae85 | |||
3d7b596a40 | |||
49b7a8e61f | |||
b74d8e4c87 | |||
067b7d909a | |||
d3c0bfefb3 | |||
b30d08d63a | |||
c39372e7d5 | |||
47826830af | |||
c71b183965 | |||
1318e1b74c | |||
4bb94a9e4d | |||
a8f0eb5ec6 | |||
bbdf36cd3a | |||
c3040dee35 | |||
077285ae57 | |||
aaefe458df | |||
ebfe4637d4 | |||
d57ee2458c | |||
5bf30bd6c4 | |||
71e9f2a3dd | |||
43dcd6ef47 | |||
0bf90770b0 | |||
0e3198edc2 | |||
af0de5f357 | |||
882c7a8cef | |||
039ebb79f4 | |||
8b392feba1 | |||
0783697f87 | |||
4ac21aaa12 | |||
14f189b2f6 | |||
5cd1a01514 | |||
f66be0e7b2 | |||
ea2c824192 | |||
8224ca16b6 | |||
4976bf97a6 | |||
af5890b276 | |||
975ef00682 | |||
d171e48b20 | |||
5436266963 | |||
bcbf53857c | |||
06ed9257ef | |||
2a041cfbe1 | |||
0f38a53d28 | |||
f0311b643a | |||
a4cd585f54 | |||
fe17f6e735 | |||
8c790a3234 | |||
bce495c581 | |||
f10bbbb851 | |||
0b98d3eb26 | |||
01cb0dc7f7 | |||
0884cb51cd | |||
68534c2319 | |||
eec047c9f7 | |||
9e8da4dba0 | |||
747999bbaf | |||
e7b43b014b | |||
1b28f11acb | |||
73db855c77 | |||
84987ac3e0 | |||
324b1c2a28 | |||
c4720ec90f | |||
cd27f8a8e6 | |||
b524c59c70 | |||
2b68a5c0cf | |||
86666489df | |||
c6d77f3bf5 | |||
10b4fa44c1 | |||
26d2b361d1 | |||
5f362cabe9 | |||
60079988bd | |||
846cfc74a2 | |||
d30e8f38b7 | |||
8fbb4a566a | |||
9180126db6 | |||
c06373de93 | |||
d0ea5942a9 | |||
9c399ee3be | |||
b0e8643523 | |||
490e9e42ff | |||
5e323561be | |||
3df91b52ea | |||
7dc5228235 | |||
f75b8c72cf | |||
417a7bc29b | |||
f1dfc4d7c4 | |||
917a1fdbf7 | |||
73491e5adc | |||
0795a60c6b | |||
ec7c1834b3 | |||
6d31c498c0 | |||
d06ad43dca | |||
748837acfd | |||
a248575dea | |||
9765559a28 | |||
34986771b4 | |||
0df7b472c2 | |||
b360c83e92 | |||
7d860a0181 | |||
6eb1fec7a9 | |||
b503e5ee5b | |||
4f0fa58ff2 | |||
c82e72eecb | |||
cf481e1a7b | |||
2bcafc861e | |||
96496ced5f | |||
039418f393 | |||
6bb06fdb81 | |||
3fd4441f70 | |||
3ca54ad369 | |||
e8422f7aa0 | |||
8c86322068 | |||
6f1dd7a688 | |||
6807546caf | |||
4536668482 | |||
20088303e9 | |||
d31cf1af5d | |||
eb75ffdc5d | |||
e57d460e31 | |||
0e04dfbad7 | |||
9928d19af1 | |||
82d4180f39 | |||
931b8dcdaf | |||
c603534d38 | |||
a76eea85c8 | |||
ade7661b3f | |||
8738147aee | |||
b148f70f83 | |||
1c2dac2a90 | |||
b5b165b989 | |||
04e91500c5 | |||
374d160234 | |||
bda0269133 | |||
eb4ffd5dbd | |||
446d8abfb0 | |||
df37df821e | |||
0539be7067 | |||
475498f2eb | |||
03ff2faacb | |||
c4cb768432 | |||
01f74781b0 | |||
9417df2a26 | |||
abd0e85fc6 | |||
5ea23977f7 | |||
f1f3424cdd | |||
73d1126bf4 | |||
448b262b37 | |||
83770e5e40 | |||
0db6bac590 | |||
9ace617e7e | |||
616a7e6c61 | |||
d86785ac98 | |||
4144c59ce4 | |||
15a26a479b | |||
f0781d3a24 | |||
aaefe462bb | |||
78dc54ab3d | |||
7847100ad8 | |||
733e079081 | |||
95e2afcad6 | |||
46a27cdb6b | |||
123fd73c8c | |||
cd9244ab15 | |||
dcc7df2b21 | |||
235cca4f97 | |||
1cb6a294b0 | |||
b0a9bbf6f6 | |||
f8b7d5c76d | |||
938528e5ee | |||
5b0861768e | |||
8c4c421f74 | |||
70f2ff0e5a | |||
99ff45ad2e | |||
90db64d4e3 | |||
487500d291 | |||
7d28fe5915 | |||
d05c1d58c3 | |||
405785ea62 | |||
0a7024c198 | |||
3d36c81241 | |||
d69f2f57ee | |||
904e187f70 | |||
3c264827fd | |||
f841097e99 | |||
f26de46350 | |||
e6ac9e88aa | |||
b8ee48a74b | |||
843219daec | |||
7b8b5754bc | |||
6f32684f15 | |||
15113f682e | |||
3a6e6645e6 | |||
90cf77b191 | |||
6b3ccd3edf | |||
0db122bc3b | |||
fdce095101 | |||
d009a85de4 | |||
63a39dd08e | |||
cdb5e16f70 | |||
4eeba016f6 | |||
83b10f77a9 | |||
fd0108dbef | |||
98540370a0 | |||
bb8cdcb916 | |||
83cb040d20 | |||
2acdafe4f2 | |||
44ed5640d3 | |||
0836f69d9b | |||
6c749934ec | |||
9abcbf73cb | |||
63aa035f59 | |||
8c1d7daef8 | |||
1ab1712849 | |||
48ede93a58 | |||
3498617a3c | |||
53892ab893 | |||
292f08b11e | |||
14bcfef041 | |||
8cfae35042 | |||
89d1340225 | |||
485832fe06 | |||
e6b1e39847 | |||
e7097d6176 | |||
e3f2ad728a | |||
cc3ed515ca | |||
882b4a5eb4 | |||
7fbe6574c6 | |||
8a6d543bc9 | |||
6a1eba2d0a | |||
14ab9708be | |||
df276b82da | |||
30a0193d73 | |||
e43c5cd3d3 | |||
92ded00fd9 | |||
6ee65fc5af | |||
da53caf310 | |||
b6f3c97e3b | |||
0cdd050cd7 | |||
6da8a77fa3 | |||
9bdacaf08d | |||
75ec4841df | |||
e674df8101 | |||
097fe51f97 | |||
060f879816 | |||
7184de24b8 | |||
0e8c2f9d41 | |||
a17c930d1f | |||
09abf11e56 | |||
4bd43bdb35 | |||
7f3f3891c0 | |||
88d7b3de23 | |||
f2b738648f | |||
e0594340ff | |||
6251d37987 | |||
f44526cc45 | |||
e912bcb36d | |||
ecda785cbc | |||
4250357ed2 | |||
79a95256e8 | |||
3115e546aa | |||
c1b55991c0 | |||
70f83a3a65 | |||
e9b6e437eb | |||
1eafe86627 | |||
81937d34a8 | |||
fa0f0f4507 | |||
1fe2906923 | |||
900394a612 | |||
222a9231bb | |||
d9ca8f3145 | |||
d9b2a90773 | |||
748072c045 | |||
e57ee2852a | |||
1e4c22c206 | |||
5df542c3c0 | |||
4b088ec7e8 | |||
9d9cf31972 | |||
ad79db32c7 | |||
30552ecfd6 | |||
356a37edcf | |||
03720acaff | |||
9be3319653 | |||
9e307d60e3 | |||
515e0c6122 | |||
317744489f | |||
5082182790 | |||
ba7a4fc034 | |||
7fb704d308 | |||
79198fd6a5 | |||
34aad73fd8 | |||
141ac8beab | |||
33a2fd368a | |||
b3faed610d | |||
fcd08ed8d4 | |||
94b7c9e307 | |||
cd2ec7868c | |||
99a1a85f1f | |||
4a41ce9414 | |||
c2c43928a9 | |||
8ac9036db3 | |||
4913668ea4 | |||
bb2d3a8b41 | |||
6c1084eaa1 | |||
f293bec97c | |||
d23709ce35 | |||
9fe654c6e4 | |||
debe6522bb | |||
33e8fb85cf | |||
dd2a578012 | |||
f46557d2d6 | |||
c36172ebef | |||
85b8967291 | |||
13c3f11c66 | |||
fbbe7fee53 | |||
25d8c1af91 | |||
e7ffcea33d | |||
b1b23d6ca9 | |||
0ca7926b94 | |||
a3a10d4a3c | |||
47e875314b | |||
f00662a5ad | |||
08fd6a7e7d | |||
d84b5737a6 | |||
99e315d2b2 | |||
221f36e116 | |||
a3560b274e | |||
6ca4b31bf8 | |||
a906738ba7 | |||
1b5795c96d | |||
81bf614821 | |||
7fac4013a4 | |||
4e292bf67d | |||
376a6a5af0 | |||
46f55fe6f6 | |||
3f7f256752 | |||
19f7bf90f8 | |||
07ebb14ce2 | |||
ad7f600e0d | |||
68ccdc4fb8 | |||
8fbb42cc6f | |||
2440a30444 | |||
bd23c11a93 | |||
1d90f099bd | |||
6844952d56 | |||
18a00c7060 | |||
c93a562b06 | |||
9119f58ce5 | |||
0123fc8c0f | |||
37d8d78fc2 | |||
064b94721e | |||
94c4e9564d | |||
86d1abf3f6 | |||
05ee36baab | |||
85e18c72d2 | |||
731b003c9d | |||
acbd58627f | |||
c46d5634d4 | |||
c82f909be1 | |||
26e469af22 | |||
04a4433706 | |||
02de9bd859 | |||
4f1acf0d4a | |||
1847270a5f | |||
6408ac482c | |||
6920e70e2e | |||
7fde17e15a | |||
0d4f29a317 | |||
508d05414a | |||
b7b3df3c81 | |||
d24474ea82 | |||
64db50ba46 | |||
aca85dbea4 | |||
f400ea4ec8 | |||
17b63d846f | |||
ac518a1d3e | |||
de3a154f38 | |||
43cb4038c6 | |||
0bb89ccee2 | |||
71429d306e | |||
c735d3066b | |||
fe15756129 | |||
88bc8efab0 | |||
b28ec1f3b1 | |||
dd36e8bf2b | |||
d11b4160aa | |||
16ddd796f3 | |||
9918ec31d6 | |||
a143e2e772 | |||
750b6c9224 | |||
6ed06a8dc8 | |||
f5ad362912 | |||
0dc3d07e7f | |||
62abde5b37 | |||
b308d2728b | |||
adae98664e | |||
88725be381 | |||
7ca21a1bc2 | |||
ac740170b9 | |||
bff9a6b6e3 | |||
d809abbe1c | |||
c3a71f5472 | |||
dbc9b2ec9b | |||
6bdb8719e2 | |||
a48130b682 | |||
e0cd947904 | |||
1e69175403 | |||
431e391ccd | |||
dd893ac4f5 | |||
14ddb81f7a | |||
39445cf23a | |||
7ab49f80ca | |||
4f51b77937 | |||
90766141b3 | |||
37f1715bfa | |||
1746b04065 | |||
500a8a0e02 | |||
4fa3eee84e | |||
aa1a96f907 | |||
334fba2f56 | |||
707df6c7b7 | |||
742808d835 | |||
15f82e0deb | |||
aa2935968e | |||
f38cca09cf | |||
0fc1f5b17f | |||
ae1166a783 | |||
2bb6e31520 | |||
200d3482dc | |||
71cfa264d7 | |||
5ba77928ba | |||
13fab08cdb | |||
b9dd7c65ab | |||
241ccb46d5 | |||
3c6257b8b9 | |||
6e99688fa7 | |||
323ae8326e | |||
d692286862 | |||
8211081c54 | |||
33ef3992f7 | |||
d9ff617ff8 | |||
7c9739c67f | |||
e09e2cbd28 | |||
6e4d3dac1a | |||
a8a5ba9d1e | |||
46769406dc | |||
c38c54af52 | |||
fe64da6197 | |||
73e2d56acc | |||
f5310a2f2d | |||
28a45877aa | |||
c93f34238e | |||
962aa4c396 | |||
916a8955ec | |||
61d886e14b | |||
4b7be31197 | |||
aac99819d6 | |||
f3967f1183 | |||
dc52938627 | |||
f7e35ce120 | |||
1247ce251f | |||
d25578efd8 | |||
6aed651f77 | |||
2d157d3af0 | |||
e6792f84d4 | |||
153db91917 | |||
74f2e53b3b | |||
31fd72bde1 | |||
503b8c20de | |||
b61b311772 | |||
e03d2b2900 | |||
fc1b0b090c | |||
a4cf50affe | |||
c0699958ce | |||
eb3e640fa6 | |||
468fcd7b30 | |||
6ba7a74191 | |||
bb385fabd4 | |||
0a31531f44 | |||
9d16b85ed2 | |||
e16f2e898a | |||
3abfb85613 | |||
ff35d24bcc | |||
4ee5a792ff | |||
26991bb2ec | |||
2e26196aba | |||
a1582874d3 | |||
729e524955 | |||
bcd85e7cd6 | |||
e1de4908f6 | |||
4b7818dfc2 | |||
c6112550eb | |||
f5ba64d8cd | |||
93c9777165 | |||
a3086f40fe | |||
fc25d71f84 | |||
a4dc775339 | |||
5fe4ae62cb | |||
ac2da570f5 | |||
de7552047b | |||
91f8eb7b92 | |||
d3e8e15e41 | |||
7e334013a0 | |||
325e292427 | |||
3268646180 | |||
743c815821 | |||
8b7668d24f | |||
b04ee7e040 | |||
9d4ba2e27d | |||
c9430bb807 | |||
e176a8b93f | |||
b578e86971 | |||
5737a79c8d | |||
7e8f1f1062 | |||
ed94edfd8e | |||
136dbdfd95 | |||
c1766c95ed | |||
efd927e300 | |||
fde991fbbb | |||
dec73a8a8a | |||
99314dad73 | |||
072c57b0ca | |||
85f432dc8d | |||
7c8946b9b7 | |||
b024ff85f7 | |||
dee2790133 | |||
9363e6c154 | |||
810fcd8bcb | |||
ff1040a38d | |||
7f49ac0407 | |||
bae32567c3 | |||
8f90238e53 | |||
d77082af00 | |||
92a22ab35f | |||
c0eab2a164 | |||
c18a409a97 | |||
f32d92f842 | |||
6699ccfd1f | |||
5600ef9701 | |||
5f914c9cbe | |||
60f3cfbe98 | |||
2142181c51 | |||
efeeba99ca | |||
876a755bac | |||
4cd438f663 | |||
c070314621 | |||
2d81a73f85 | |||
2d29907611 | |||
a71fc8e6a5 | |||
3b3a32cbd6 | |||
8a553cdcbe | |||
282532a92a | |||
138e292c4b | |||
ff5378bd66 | |||
d1aca79f4e | |||
693bd56db2 | |||
6e5130ddf4 | |||
129339adb0 | |||
11025b3160 | |||
d953f8d99a | |||
2f0fb2bc34 | |||
314b87dfaf | |||
c151f35751 | |||
6425b8c1cf | |||
2a04c2a7bb | |||
13caf21018 | |||
7a2da7cd02 | |||
62e8661a37 | |||
9a6aebeb96 | |||
2f4271a2b3 | |||
d45d1d1bca | |||
ed0f0dbe87 | |||
4e245f0bfb | |||
bc88ed0cb9 | |||
e14c7e5510 | |||
dcaafffe0e | |||
9f1b407def | |||
7d26e85b05 | |||
6f150d8800 | |||
1de735ba7c | |||
e10d648a28 | |||
215b0065e3 | |||
7665b8e5e7 | |||
d8026e4d84 | |||
2a9a2918f8 | |||
9c489a081c | |||
be83c07957 | |||
7e6112bf26 | |||
302316c6cf | |||
7e297945c3 | |||
da4bfe3289 | |||
2e63bf1d16 | |||
30bc952ac3 | |||
fd7f50d269 | |||
3bd5597cee | |||
bbaf7e2eee | |||
fe2809fecc | |||
7e00a41f1b | |||
cb285c4d35 | |||
04358c301e | |||
d4c0ecea0e | |||
f2ff88b03a | |||
ea720963cf | |||
d3e444dfd9 | |||
f4970d0e00 | |||
733eedc477 | |||
d08ce58876 | |||
0fc9168439 | |||
9c6c8a1ab9 | |||
44826972c0 | |||
edde703f8f | |||
304d19a0d8 | |||
b443c7ebe9 | |||
1ac4f33736 | |||
7019cb10f7 | |||
c1547dd79e | |||
ce8150ce69 | |||
6da83cd5b7 | |||
98eeeab025 | |||
1ef789bb68 | |||
ce87c69c38 | |||
93befadc0b | |||
06fbeed41a | |||
55edd522c2 | |||
e97d02a294 | |||
7c9bd71512 | |||
2b0acc128c | |||
60591dd7c6 | |||
8e0f04638d | |||
e2c4ba21bc | |||
ef957b7878 | |||
834085c90c | |||
72855becab | |||
eff466d77d | |||
110d96034b | |||
aaca73de15 | |||
4d78c5c9ab | |||
ceb4da2038 | |||
55093ea8fe | |||
153454a0fb | |||
1c1a55f6b1 | |||
e2734d23ef | |||
0911526424 | |||
58dc3f97c5 | |||
5d1c381509 | |||
4b1a18c2c9 | |||
dac9266f6f | |||
378eee490b | |||
8dd3f854fe | |||
470a8499fe | |||
af1f41dc6a | |||
f5c2f8c60d | |||
cf1554ebb5 | |||
2b032004a9 | |||
d69df3065f | |||
8ca3dc8e41 | |||
fdc8c0722f | |||
91684a428b | |||
d9757bb583 |
2
LICENSE
@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Omar Cornut
|
||||
Copyright (c) 2014-2015 Omar Cornut and ImGui contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
66
README.md
@ -1,14 +1,15 @@
|
||||
ImGui
|
||||
=====
|
||||
[](https://travis-ci.org/ocornut/imgui)
|
||||
[](https://scan.coverity.com/projects/4720)
|
||||
|
||||
[](http://www.patreon.com/imgui) [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5Q73FPZ9C526U)
|
||||
|
||||
ImGui is a bloat-free graphical user interface library for C++. It outputs vertex buffers that you can render in your 3D-pipeline enabled application. It is portable, renderer agnostic and carries minimal amount of dependencies. It is based on an "immediate" graphical user interface paradigm which allows you to build user interfaces with ease.
|
||||
ImGui is a bloat-free graphical user interface library for C++. It outputs vertex buffers that you can render in your 3D-pipeline enabled application. It is portable, renderer agnostic and carries minimal amount of dependencies. It is based on an "immediate" graphical user interface paradigm which enables you to build user interfaces with ease.
|
||||
|
||||
ImGui is designed to enable fast iteration and allow programmers to create "content creation" or "debug" tools (as opposed to UI for the average end-user). It favors simplicity and productivity toward this goal, and thus lacks certain features normally found in more high-level libraries.
|
||||
|
||||
ImGui is particularly suited to integration in 3D applications, fullscreen applications, embedded applications, games, or any applications on consoles platforms where operating system features are non-standard.
|
||||
ImGui is particularly suited to integration in realtime 3D applications, fullscreen applications, embedded applications, games, or any applications on consoles platforms where operating system features are non-standard. pa
|
||||
|
||||
ImGui is self-contained within 6 files that you can easily copy and compile into your application/engine:
|
||||
|
||||
@ -21,20 +22,29 @@ ImGui is self-contained within 6 files that you can easily copy and compile into
|
||||
|
||||
Your code passes mouse/keyboard inputs and settings to ImGui (see example applications for more details). After ImGui is setup, you can use it like in this example:
|
||||
|
||||

|
||||

|
||||
|
||||
ImGui outputs vertex buffers and simple command-lists that you can render in your application. Because it doesn't know or touch graphics state directly, you can call ImGui commands 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 ImGui with your existing codebase.
|
||||
|
||||
ImGui allows you create elaborate tools as well as very short-lived ones. On the extreme side of short-liveness: using the Edit&Continue feature of compilers you can add a few widgets to tweaks variables while your application is running, and remove the code a minute later! 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, etc.
|
||||
|
||||
Demo
|
||||
----
|
||||
|
||||
You should be able to build the examples from sources (tested on Windows/Mac/Linux). If you don't, let me know! If you want to have a quick look at the features of ImGui, you can download binaries of the demo app here.
|
||||
- [imgui-demo-binaries-20150716.zip](http://www.miracleworld.net/imgui/binaries/imgui-demo-binaries-20150716.zip) (Windows binaries, ImGui 1.43 WIP 2015/07/16, 4 executables, 475 KB)
|
||||
|
||||
|
||||
Gallery
|
||||
-------
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
ImGui can load TTF fonts. UTF-8 is supported for text display and input. Here using Arial Unicode font to display Japanese. Initialize custom font with:
|
||||
```
|
||||
@ -45,7 +55,7 @@ For Microsoft IME, pass your HWND to enable IME positioning:
|
||||
```
|
||||
io.ImeWindowHandle = my_hwnd;
|
||||
```
|
||||

|
||||

|
||||
|
||||
References
|
||||
----------
|
||||
@ -59,13 +69,15 @@ The Immediate Mode GUI paradigm may at first appear unusual to some users. This
|
||||
Frequently Asked Question
|
||||
-------------------------
|
||||
|
||||
<b>Where are samples?</b>
|
||||
<b>Where is the documentation?</b>
|
||||
|
||||
The bulk of example user code is contained within the ImGui::ShowTestWindow() function. It covers most features of ImGui so you can read the code and call the function itself to see its output. Ready-to-go example applications covering different versions of OpenGL/DirectX are provided in the examples/ folder.
|
||||
- The documentation is at the top of imgui.cpp + effectively imgui.h.
|
||||
- Example code is in the ImGui::ShowTestWindow() function. It covers most features of ImGui so you can read the code and call the function itself to see its output.
|
||||
- Standalone example applications using OpenGL/DirectX are provided in the examples/ folder.
|
||||
|
||||
<b>How do you use ImGui on a platform that may not have a mouse or keyboard?</b>
|
||||
|
||||
I recommend using [Synergy](http://synergy-project.org). With the uSynergy.c micro client running on your platform and connecting to your PC, you can seamlessly use your PC input devices from a video game console or a tablet. ImGui allows to increase the hit box of widgets (via the _TouchPadding_ setting) to accomodate a little for the lack of precision of touch inputs, but it is recommended you use a mouse to allow optimising for screen real-estate.
|
||||
I recommend using [Synergy](http://synergy-project.org) ([sources](https://github.com/synergy/synergy)). In particular, the _src/micro/uSynergy.c_ file contains a small client that you can use on any platform to connect to your host PC. You can seamlessly use your PC input devices from a video game console or a tablet. ImGui allows to increase the hit box of widgets (via the _TouchPadding_ setting) to accomodate a little for the lack of precision of touch inputs, but it is recommended you use a mouse to allow optimising for screen real-estate.
|
||||
|
||||
<b>I integrated ImGui in my engine and the text or lines are blurry..</b>
|
||||
|
||||
@ -73,20 +85,21 @@ In your Render function, try translating your projection matrix by (0.5f,0.5f) o
|
||||
|
||||
<b>Can you create elaborate/serious tools with ImGui?</b>
|
||||
|
||||
Yes. I have written data browsers, debuggers, profilers and all sort of non-trivial tools with the library. There's no reason you cannot, and in my experience the simplicity of the API is very empowering. However note that ImGui is programmer centric and the immediate-mode GUI paradigm might requires a bit of adaptation before you can realize its full potential.
|
||||
Yes. I have written 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).
|
||||
|
||||
However note that ImGui is programmer centric and the immediate-mode GUI paradigm might requires a bit of adaptation before you can realize its full potential. Many programmers have unfortunately been taught by their environment to make complicated unproductive things. Strip yourself out of all those heavy layers and start making lots of useful tools!
|
||||
|
||||
<b>Is ImGui fast?</b>
|
||||
|
||||
Down the fundation of its visual design, ImGui is engineered to be fairly performant both in term of CPU and GPU usage. Running elaborate code and creating elaborate UI will of course have a cost but ImGui aims to minimize it.
|
||||
Down to the fundation of its visual design, ImGui is engineered to be fairly performant both in term of CPU and GPU usage. Running elaborate code and creating elaborate UI will of course have a cost but ImGui aims to minimize it.
|
||||
|
||||
Mileage may vary but the following screenshot may give you a rough idea of the cost of running and rendering UI code (In the case of a trivial demo application like this one, your driver/os setup may be a bottleneck and cause higher variation or throttled framerate. Testing performance as part of a real application is recommended).
|
||||
Mileage may vary but the following screenshot can give you a rough idea of the cost of running and rendering UI code (In the case of a trivial demo application like this one, your driver/os setup are likely to be the bottleneck. Testing performance as part of a real application is recommended).
|
||||
|
||||

|
||||

|
||||
|
||||
This is showing framerate for the full application loop on my 2011 iMac running Windows 7, OpenGL, AMD Radeon HD 6700M with an optimized executable. ([click here for the full-size picture](/web/performance_01.png)).
|
||||
In contrast, librairies featuring higher-quality rendering and layouting techniques may have a higher resources footprint.
|
||||
This is showing framerate for the full application loop on my 2011 iMac running Windows 7, OpenGL, AMD Radeon HD 6700M with an optimized executable. In contrast, librairies featuring higher-quality rendering and layouting techniques may have a higher resources footprint.
|
||||
|
||||
If you intend to display large lists of items (say, 1000+) it can be beneficial for your code to perform clipping manually - using helpers such as CalcListClipping() - in order to avoid submitting them to ImGui in the first place. Even though ImGui will discard your clipped items it still needs to calculate their size and that overhead will add up if you have thousands of items.
|
||||
If you intend to display large lists of items (say, 1000+) it can be beneficial for your code to perform clipping manually - using helpers such as ImGuiListClipper - in order to avoid submitting them to ImGui in the first place. Even though ImGui will discard your clipped items it still needs to calculate their size and that overhead will add up if you have thousands of items. If you can handle clipping and height positionning yourself then browsing a list with millions of items isn't a problem.
|
||||
|
||||
<b>Can you reskin the look of ImGui?</b>
|
||||
|
||||
@ -96,7 +109,7 @@ You can alter the look of the interface to some degree: changing colors, sizes,
|
||||
|
||||
ImGui takes advantage of a few C++ features for convenience but nothing anywhere Boost-insanity/quagmire. In particular, 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 but could be removed.
|
||||
|
||||
Shall someone wants to use ImGui from another language, it should be possible to wrap ImGui to be used from a raw C API in the future.
|
||||
Shall someone really need to use ImGui from another language, there is an unofficial but reasonably maintained [c-api for ImGui](https://github.com/Extrawurst/cimgui) by Stephan Dilly. I would suggest using your target language functionality to try replicating the function overloading and default parameters used in C++ else the API may be harder to use. It was really designed with C++ in mind and may not make the same amount of sense with another language.
|
||||
|
||||
Donate
|
||||
------
|
||||
@ -118,16 +131,13 @@ Embeds [stb_textedit.h, stb_truetype.h, stb_rectpack.h](https://github.com/nothi
|
||||
|
||||
Inspiration, feedback, and testing for early versions: Casey Muratori, Atman Binstock, Mikko Mononen, Emmanuel Briney, Stefan Kamoda, Anton Mikhailov, Matt Willis. And everybody posting feedback, questions and patches on the GitHub.
|
||||
|
||||
ImGui is financially supported on [**Patreon**](http://www.patreon.com/imgui).
|
||||
ImGui development is financially supported on [**Patreon**](http://www.patreon.com/imgui).
|
||||
|
||||
Special supporters
|
||||
- Jetha Chan
|
||||
- Pastagames
|
||||
- Wild Sheep Studio
|
||||
Special supporters:
|
||||
- Jetha Chan, Wild Sheep Studio, Pastagames, Mārtiņš Možeiko, Daniel Collin, Stefano Cristiano.
|
||||
|
||||
And
|
||||
- Dale Kim
|
||||
- Michel Courtine
|
||||
And:
|
||||
- Michel Courtine, César Leblic, Dale Kim, Alex Evans, Rui Figueira, Paul Patrashcu, Jerome Lanquetot, Ctrl Alt Ninja, Paul Fleming, Neil Henning, Stephan Dilly, Neil Blakey-Milner, Aleksei.
|
||||
|
||||
And other supporters; thanks!
|
||||
|
||||
|
@ -1,12 +1,35 @@
|
||||
Those are standalone ready-to-build applications to demonstrate ImGui.
|
||||
Binaries of those demos are available from the main GitHub page.
|
||||
|
||||
TL;DR;
|
||||
Refer to 'opengl_example' (not 'opengl3_example') to understand how the library is setup.
|
||||
Copy the imgui_impl_xxx.cpp/.h file you need if you are using one of the rendering backend used in an example.
|
||||
If you are using a different or your own backend, copy opengl_example/imgui_impl_opengl.cpp/.h to get started.
|
||||
|
||||
|
||||
ImGui is highly portable and only requires a few things to run:
|
||||
- Providing mouse/keyboard inputs
|
||||
- Load the font atlas texture into GPU memory
|
||||
- Providing a render function to process the drawing commands (we rendere indexed textured triangles)
|
||||
- Extra just as clipboard support, mouse cursor supports, Windows IME support.
|
||||
So this is essentially what those examples are doing + the obligatory cruft for portability.
|
||||
|
||||
Unfortunately in 2015 it is still a massive pain to create and maintain portable build files using
|
||||
external library like the ones we're using here.
|
||||
For most example here I choose to provide Visual Studio 10 .sln files and Makefile for Linux/OSX.
|
||||
Please let me know if they don't work with your setup!
|
||||
You can probably just import the imgui_impl_xxx.cpp/.h files into your own codebase or compile those
|
||||
directly with a command-line compiler.
|
||||
|
||||
opengl_example/
|
||||
OpenGL example, using GLFW + fixed pipeline.
|
||||
This is simple and should work for all OpenGL enabled applications.
|
||||
Prefer following this example since it is the shortest one!
|
||||
Prefer following this example to learn how ImGui works!
|
||||
|
||||
opengl3_example/
|
||||
OpenGL exemple, using GLFW/GL3W + programmable pipeline.
|
||||
This uses more modern calls and custom shaders.
|
||||
OpenGL example, using GLFW/GL3W + programmable pipeline.
|
||||
This uses more modern OpenGL calls and custom shaders.
|
||||
Even if your application is using modern OpenGL you are better off copying the code from the fixed pipeline version!
|
||||
I don't think there is an advantage using this over the simpler example, but it is provided for reference.
|
||||
|
||||
directx9_example/
|
||||
@ -16,3 +39,12 @@ directx11_example/
|
||||
DirectX11 example, Windows only.
|
||||
This is quite long and tedious, because: DirectX11.
|
||||
|
||||
ios_example/
|
||||
iOS example.
|
||||
Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky.
|
||||
|
||||
sdl_opengl_example/
|
||||
SDL2 + OpenGL example.
|
||||
|
||||
allegro5_example/
|
||||
Allegro 5 example.
|
||||
|
16
examples/allegro5_example/README.md
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
# How to Build
|
||||
|
||||
- On Ubuntu 14.04+
|
||||
|
||||
```bash
|
||||
g++ -I ../imgui main.cpp imgui_impl_a5.cpp ../imgui/imgui.cpp -lallegro -lallegro_primitives
|
||||
```
|
||||
|
||||
- On Windows with Visual Studio's CLI
|
||||
|
||||
\<a5path\> is your allegro5 folder.
|
||||
|
||||
```
|
||||
cl /MD /I <a5path\include> /I ..\imgui main.cpp imgui_impl_a5.cpp ..\imgui\imgui.cpp /link /LIBPATH:<a5path\lib> allegro-5.0.10-monolith-md.lib user32.lib
|
||||
```
|
290
examples/allegro5_example/imgui_impl_a5.cpp
Normal file
@ -0,0 +1,290 @@
|
||||
// ImGui Allegro 5 bindings
|
||||
// https://github.com/ocornut/imgui
|
||||
// by @birthggd
|
||||
|
||||
#include <stdint.h> // uint64_t
|
||||
#include <cstring> // memcpy
|
||||
#include <imgui.h>
|
||||
#include "imgui_impl_a5.h"
|
||||
#include <allegro5/allegro.h>
|
||||
#include <allegro5/allegro_primitives.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <allegro5/allegro_windows.h>
|
||||
#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;
|
||||
|
||||
#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT))
|
||||
|
||||
struct ImDrawVertAllegro
|
||||
{
|
||||
ImVec2 pos;
|
||||
ImVec2 uv;
|
||||
ALLEGRO_COLOR col;
|
||||
};
|
||||
|
||||
static void ImGui_ImplA5_RenderDrawLists(ImDrawData* draw_data)
|
||||
{
|
||||
int op, src, dst;
|
||||
al_get_blender(&op, &src, &dst);
|
||||
al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
|
||||
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
|
||||
// FIXME-OPT: Unfortunately Allegro doesn't support 32-bits packed colors so we have to convert them to 4 floats
|
||||
static ImVector<ImDrawVertAllegro> vertices;
|
||||
vertices.resize(cmd_list->VtxBuffer.size());
|
||||
for (int i = 0; i < cmd_list->VtxBuffer.size(); ++i)
|
||||
{
|
||||
const ImDrawVert &dv = cmd_list->VtxBuffer[i];
|
||||
ImDrawVertAllegro v;
|
||||
v.pos = dv.pos;
|
||||
v.uv = dv.uv;
|
||||
unsigned char *c = (unsigned char*)&dv.col;
|
||||
v.col = al_map_rgba(c[0], c[1], c[2], c[3]);
|
||||
vertices[i] = v;
|
||||
}
|
||||
|
||||
// FIXME-OPT: Unfortunately Allegro doesn't support 16-bit vertices
|
||||
static ImVector<int> indices;
|
||||
indices.resize(cmd_list->IdxBuffer.size());
|
||||
for (int i = 0; i < cmd_list->IdxBuffer.size(); ++i)
|
||||
indices[i] = (int)cmd_list->IdxBuffer.Data[i];
|
||||
|
||||
int idx_offset = 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
|
||||
{
|
||||
ALLEGRO_BITMAP* texture = (ALLEGRO_BITMAP*)pcmd->TextureId;
|
||||
al_set_clipping_rectangle(pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z-pcmd->ClipRect.x, pcmd->ClipRect.w-pcmd->ClipRect.y);
|
||||
al_draw_indexed_prim(&vertices[0], g_VertexDecl, texture, &indices[idx_offset], pcmd->ElemCount, ALLEGRO_PRIM_TRIANGLE_LIST);
|
||||
}
|
||||
idx_offset += pcmd->ElemCount;
|
||||
}
|
||||
}
|
||||
|
||||
// Restore modified state
|
||||
al_set_blender(op, src, dst);
|
||||
al_set_clipping_rectangle(0, 0, al_get_display_width(g_Display), al_get_display_height(g_Display));
|
||||
}
|
||||
|
||||
bool Imgui_ImplA5_CreateDeviceObjects()
|
||||
{
|
||||
ImGuiIO &io = ImGui::GetIO();
|
||||
|
||||
// Build texture
|
||||
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->TexID = (void*)cloned_img;
|
||||
g_Texture = cloned_img;
|
||||
|
||||
// Cleanup (don't clear the input data if you want to append new fonts later)
|
||||
io.Fonts->ClearInputData();
|
||||
io.Fonts->ClearTexData();
|
||||
|
||||
// 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);
|
||||
al_destroy_bitmap(mouse_cursor);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplA5_InvalidateDeviceObjects()
|
||||
{
|
||||
if (g_Texture)
|
||||
{
|
||||
al_destroy_bitmap(g_Texture);
|
||||
ImGui::GetIO().Fonts->TexID = NULL;
|
||||
g_Texture = NULL;
|
||||
}
|
||||
if (g_MouseCursorInvisible)
|
||||
{
|
||||
al_destroy_mouse_cursor(g_MouseCursorInvisible);
|
||||
g_MouseCursorInvisible = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGui_ImplA5_Init(ALLEGRO_DISPLAY* display)
|
||||
{
|
||||
g_Display = display;
|
||||
|
||||
// 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 }
|
||||
};
|
||||
g_VertexDecl = al_create_vertex_decl(elems, sizeof(ImDrawVertAllegro));
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
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_Delete] = ALLEGRO_KEY_DELETE;
|
||||
io.KeyMap[ImGuiKey_Backspace] = ALLEGRO_KEY_BACKSPACE;
|
||||
io.KeyMap[ImGuiKey_Enter] = ALLEGRO_KEY_ENTER;
|
||||
io.KeyMap[ImGuiKey_Escape] = ALLEGRO_KEY_ESCAPE;
|
||||
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.RenderDrawListsFn = ImGui_ImplA5_RenderDrawLists;
|
||||
#ifdef _WIN32
|
||||
io.ImeWindowHandle = al_get_win_window_handle(g_Display);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplA5_Shutdown()
|
||||
{
|
||||
ImGui_ImplA5_InvalidateDeviceObjects();
|
||||
ImGui::Shutdown();
|
||||
}
|
||||
|
||||
bool ImGui_ImplA5_ProcessEvent(ALLEGRO_EVENT *ev)
|
||||
{
|
||||
ImGuiIO &io = ImGui::GetIO();
|
||||
|
||||
switch (ev->type)
|
||||
{
|
||||
case ALLEGRO_EVENT_MOUSE_AXES:
|
||||
io.MouseWheel += ev->mouse.dz;
|
||||
return true;
|
||||
case ALLEGRO_EVENT_KEY_CHAR:
|
||||
if (ev->keyboard.display == g_Display)
|
||||
if (ev->keyboard.unichar > 0 && ev->keyboard.unichar < 0x10000)
|
||||
io.AddInputCharacter((unsigned short)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);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void ImGui_ImplA5_NewFrame()
|
||||
{
|
||||
if (!g_Texture)
|
||||
Imgui_ImplA5_CreateDeviceObjects();
|
||||
|
||||
ImGuiIO &io = ImGui::GetIO();
|
||||
|
||||
// Setup display size (every frame to accommodate for window resizing)
|
||||
int w, h;
|
||||
w = al_get_display_width(g_Display);
|
||||
h = al_get_display_height(g_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;
|
||||
|
||||
// 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);
|
||||
|
||||
ALLEGRO_MOUSE_STATE mouse;
|
||||
if (keys.display == g_Display)
|
||||
{
|
||||
al_get_mouse_state(&mouse);
|
||||
io.MousePos = ImVec2((float)mouse.x, (float)mouse.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
io.MousePos = ImVec2(-1, -1);
|
||||
}
|
||||
|
||||
al_get_mouse_state(&mouse);
|
||||
io.MouseDown[0] = mouse.buttons & (1 << 0);
|
||||
io.MouseDown[1] = mouse.buttons & (1 << 1);
|
||||
io.MouseDown[2] = mouse.buttons & (1 << 2);
|
||||
|
||||
// Hide OS mouse cursor if ImGui is drawing it
|
||||
if (io.MouseDrawCursor)
|
||||
{
|
||||
al_set_mouse_cursor(g_Display, g_MouseCursorInvisible);
|
||||
}
|
||||
else
|
||||
{
|
||||
ALLEGRO_SYSTEM_MOUSE_CURSOR cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_DEFAULT;
|
||||
switch (ImGui::GetMouseCursor())
|
||||
{
|
||||
case ImGuiMouseCursor_TextInput: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_EDIT; break;
|
||||
case ImGuiMouseCursor_Move: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_MOVE; break;
|
||||
case ImGuiMouseCursor_ResizeNS: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_RESIZE_N; break;
|
||||
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;
|
||||
}
|
||||
al_set_system_mouse_cursor(g_Display, cursor_id);
|
||||
}
|
||||
|
||||
// Start the frame
|
||||
ImGui::NewFrame();
|
||||
}
|
18
examples/allegro5_example/imgui_impl_a5.h
Normal file
@ -0,0 +1,18 @@
|
||||
// ImGui Allegro 5 bindings
|
||||
// https://github.com/ocornut/imgui
|
||||
// by @birthggd
|
||||
|
||||
#pragma once
|
||||
|
||||
struct ALLEGRO_DISPLAY;
|
||||
union ALLEGRO_EVENT;
|
||||
|
||||
bool ImGui_ImplA5_Init(ALLEGRO_DISPLAY* display);
|
||||
void ImGui_ImplA5_Shutdown();
|
||||
void ImGui_ImplA5_NewFrame();
|
||||
|
||||
bool ImGui_ImplA5_ProcessEvent(ALLEGRO_EVENT* event);
|
||||
|
||||
// Use if you want to reset your rendering device without losing ImGui state.
|
||||
bool Imgui_ImplA5_CreateDeviceObjects();
|
||||
void ImGui_ImplA5_InvalidateDeviceObjects();
|
105
examples/allegro5_example/main.cpp
Normal file
@ -0,0 +1,105 @@
|
||||
// ImGui - standalone example application for Allegro 5
|
||||
|
||||
#include <stdint.h>
|
||||
#include <allegro5/allegro.h>
|
||||
#include <allegro5/allegro_primitives.h>
|
||||
#include <imgui.h>
|
||||
#include "imgui_impl_a5.h"
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
// Setup Allegro
|
||||
al_init();
|
||||
al_install_keyboard();
|
||||
al_install_mouse();
|
||||
al_init_primitives_addon();
|
||||
al_set_new_display_flags(ALLEGRO_RESIZABLE);
|
||||
ALLEGRO_DISPLAY* display = al_create_display(1280, 720);
|
||||
al_set_window_title(display, "ImGui Allegro 5 example");
|
||||
ALLEGRO_EVENT_QUEUE* queue = al_create_event_queue();
|
||||
al_register_event_source(queue, al_get_display_event_source(display));
|
||||
al_register_event_source(queue, al_get_keyboard_event_source());
|
||||
al_register_event_source(queue, al_get_mouse_event_source());
|
||||
|
||||
// Setup ImGui binding
|
||||
ImGui_ImplA5_Init(display);
|
||||
|
||||
// Load Fonts
|
||||
// (see extra_fonts/README.txt for more details)
|
||||
//ImGuiIO& io = ImGui::GetIO();
|
||||
//io.Fonts->AddFontDefault();
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
|
||||
|
||||
// Merge glyphs from multiple fonts into one (e.g. combine default font with another with Chinese glyphs, or add icons)
|
||||
//ImWchar icons_ranges[] = { 0xf000, 0xf3ff, 0 };
|
||||
//ImFontConfig icons_config; icons_config.MergeMode = true; icons_config.PixelSnapH = true;
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 18.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/fontawesome-webfont.ttf", 18.0f, &icons_config, icons_ranges);
|
||||
|
||||
bool show_test_window = true;
|
||||
bool show_another_window = false;
|
||||
ImVec4 clear_color = ImColor(114, 144, 154);
|
||||
|
||||
// Main loop
|
||||
bool running = true;
|
||||
while (running)
|
||||
{
|
||||
ALLEGRO_EVENT ev;
|
||||
while (al_get_next_event(queue, &ev))
|
||||
{
|
||||
ImGui_ImplA5_ProcessEvent(&ev);
|
||||
if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) running = false;
|
||||
if (ev.type == ALLEGRO_EVENT_DISPLAY_RESIZE)
|
||||
{
|
||||
ImGui_ImplA5_InvalidateDeviceObjects();
|
||||
al_acknowledge_resize(display);
|
||||
Imgui_ImplA5_CreateDeviceObjects();
|
||||
}
|
||||
}
|
||||
ImGui_ImplA5_NewFrame();
|
||||
|
||||
// 1. Show a simple window
|
||||
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug"
|
||||
{
|
||||
static float f;
|
||||
ImGui::Text("Hello, world!");
|
||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
|
||||
ImGui::ColorEdit3("clear color", (float*)&clear_color);
|
||||
if (ImGui::Button("Test Window")) show_test_window ^= 1;
|
||||
if (ImGui::Button("Another Window")) show_another_window ^= 1;
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f/ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
|
||||
}
|
||||
|
||||
// 2. Show another simple window, this time using an explicit Begin/End pair
|
||||
if (show_another_window)
|
||||
{
|
||||
ImGui::SetNextWindowSize(ImVec2(200, 100), ImGuiSetCond_FirstUseEver);
|
||||
ImGui::Begin("Another Window", &show_another_window);
|
||||
ImGui::Text("Hello");
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow()
|
||||
if (show_test_window)
|
||||
{
|
||||
ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver);
|
||||
ImGui::ShowTestWindow(&show_test_window);
|
||||
}
|
||||
|
||||
// Rendering
|
||||
al_clear_to_color(al_map_rgba_f(clear_color.x, clear_color.y, clear_color.z, clear_color.w));
|
||||
ImGui::Render();
|
||||
al_flip_display();
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
ImGui_ImplA5_Shutdown();
|
||||
al_destroy_event_queue(queue);
|
||||
al_destroy_display(display);
|
||||
|
||||
return 0;
|
||||
}
|
@ -5,10 +5,18 @@
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{9F316E83-5AE5-4939-A723-305A94F48005}</ProjectGuid>
|
||||
@ -20,35 +28,60 @@
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..;$(DXSDK_DIR)/Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
@ -57,13 +90,26 @@
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\..;$(DXSDK_DIR)/Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
@ -74,6 +120,23 @@
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>d3d11.lib;d3dcompiler.lib;dxgi.lib;imm32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\imconfig.h" />
|
||||
<ClInclude Include="..\..\imgui.h" />
|
||||
|
@ -18,6 +18,7 @@ static HWND g_hWnd = 0;
|
||||
static ID3D11Device* g_pd3dDevice = NULL;
|
||||
static ID3D11DeviceContext* g_pd3dDeviceContext = NULL;
|
||||
static ID3D11Buffer* g_pVB = NULL;
|
||||
static ID3D11Buffer* g_pIB = NULL;
|
||||
static ID3D10Blob * g_pVertexShaderBlob = NULL;
|
||||
static ID3D11VertexShader* g_pVertexShader = NULL;
|
||||
static ID3D11InputLayout* g_pInputLayout = NULL;
|
||||
@ -26,14 +27,10 @@ static ID3D10Blob * g_pPixelShaderBlob = NULL;
|
||||
static ID3D11PixelShader* g_pPixelShader = NULL;
|
||||
static ID3D11SamplerState* g_pFontSampler = NULL;
|
||||
static ID3D11ShaderResourceView*g_pFontTextureView = NULL;
|
||||
static ID3D11BlendState* g_blendState = NULL;
|
||||
|
||||
struct CUSTOMVERTEX
|
||||
{
|
||||
float pos[2];
|
||||
float uv[2];
|
||||
unsigned int col;
|
||||
};
|
||||
static ID3D11RasterizerState* g_pRasterizerState = NULL;
|
||||
static ID3D11BlendState* g_pBlendState = NULL;
|
||||
static int VERTEX_BUFFER_SIZE = 20000; // TODO: Make buffers smaller and grow dynamically as needed.
|
||||
static int INDEX_BUFFER_SIZE = 40000; // TODO: Make buffers smaller and grow dynamically as needed.
|
||||
|
||||
struct VERTEX_CONSTANT_BUFFER
|
||||
{
|
||||
@ -43,29 +40,26 @@ struct VERTEX_CONSTANT_BUFFER
|
||||
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure)
|
||||
// If text or lines are blurry when integrating ImGui in your engine:
|
||||
// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
|
||||
static void ImGui_ImplDX11_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count)
|
||||
static void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data)
|
||||
{
|
||||
// Copy and convert all vertices into a single contiguous buffer
|
||||
D3D11_MAPPED_SUBRESOURCE mappedResource;
|
||||
if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK)
|
||||
D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource;
|
||||
if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK)
|
||||
return;
|
||||
CUSTOMVERTEX* vtx_dst = (CUSTOMVERTEX*)mappedResource.pData;
|
||||
for (int n = 0; n < cmd_lists_count; n++)
|
||||
if (g_pd3dDeviceContext->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 = cmd_lists[n];
|
||||
const ImDrawVert* vtx_src = &cmd_list->vtx_buffer[0];
|
||||
for (size_t i = 0; i < cmd_list->vtx_buffer.size(); i++)
|
||||
{
|
||||
vtx_dst->pos[0] = vtx_src->pos.x;
|
||||
vtx_dst->pos[1] = vtx_src->pos.y;
|
||||
vtx_dst->uv[0] = vtx_src->uv.x;
|
||||
vtx_dst->uv[1] = vtx_src->uv.y;
|
||||
vtx_dst->col = vtx_src->col;
|
||||
vtx_dst++;
|
||||
vtx_src++;
|
||||
}
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
memcpy(vtx_dst, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert));
|
||||
memcpy(idx_dst, &cmd_list->IdxBuffer[0], cmd_list->IdxBuffer.size() * sizeof(ImDrawIdx));
|
||||
vtx_dst += cmd_list->VtxBuffer.size();
|
||||
idx_dst += cmd_list->IdxBuffer.size();
|
||||
}
|
||||
g_pd3dDeviceContext->Unmap(g_pVB, 0);
|
||||
g_pd3dDeviceContext->Unmap(g_pIB, 0);
|
||||
|
||||
// Setup orthographic projection matrix into our constant buffer
|
||||
{
|
||||
@ -103,10 +97,11 @@ static void ImGui_ImplDX11_RenderDrawLists(ImDrawList** const cmd_lists, int cmd
|
||||
}
|
||||
|
||||
// Bind shader and vertex buffers
|
||||
unsigned int stride = sizeof(CUSTOMVERTEX);
|
||||
unsigned int stride = sizeof(ImDrawVert);
|
||||
unsigned int offset = 0;
|
||||
g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout);
|
||||
g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset);
|
||||
g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, DXGI_FORMAT_R16_UINT, 0);
|
||||
g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0);
|
||||
g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer);
|
||||
@ -115,29 +110,32 @@ static void ImGui_ImplDX11_RenderDrawLists(ImDrawList** const cmd_lists, int cmd
|
||||
|
||||
// Setup render state
|
||||
const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f };
|
||||
g_pd3dDeviceContext->OMSetBlendState(g_blendState, blendFactor, 0xffffffff);
|
||||
g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff);
|
||||
g_pd3dDeviceContext->RSSetState(g_pRasterizerState);
|
||||
|
||||
// Render command lists
|
||||
int vtx_offset = 0;
|
||||
for (int n = 0; n < cmd_lists_count; n++)
|
||||
int idx_offset = 0;
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = cmd_lists[n];
|
||||
for (size_t cmd_i = 0; cmd_i < cmd_list->commands.size(); cmd_i++)
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.size(); cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &cmd_list->commands[cmd_i];
|
||||
if (pcmd->user_callback)
|
||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback)
|
||||
{
|
||||
pcmd->user_callback(cmd_list, pcmd);
|
||||
pcmd->UserCallback(cmd_list, pcmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
const D3D11_RECT r = { (LONG)pcmd->clip_rect.x, (LONG)pcmd->clip_rect.y, (LONG)pcmd->clip_rect.z, (LONG)pcmd->clip_rect.w };
|
||||
g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->texture_id);
|
||||
const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w };
|
||||
g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId);
|
||||
g_pd3dDeviceContext->RSSetScissorRects(1, &r);
|
||||
g_pd3dDeviceContext->Draw(pcmd->vtx_count, vtx_offset);
|
||||
g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset);
|
||||
}
|
||||
vtx_offset += pcmd->vtx_count;
|
||||
idx_offset += pcmd->ElemCount;
|
||||
}
|
||||
vtx_offset += cmd_list->VtxBuffer.size();
|
||||
}
|
||||
|
||||
// Restore modified state
|
||||
@ -146,7 +144,7 @@ static void ImGui_ImplDX11_RenderDrawLists(ImDrawList** const cmd_lists, int cmd
|
||||
g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0);
|
||||
}
|
||||
|
||||
LRESULT ImGui_ImplDX11_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
switch (msg)
|
||||
@ -171,11 +169,11 @@ LRESULT ImGui_ImplDX11_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM
|
||||
io.MousePos.y = (signed short)(lParam >> 16);
|
||||
return true;
|
||||
case WM_KEYDOWN:
|
||||
if (wParam >= 0 && wParam < 256)
|
||||
if (wParam < 256)
|
||||
io.KeysDown[wParam] = 1;
|
||||
return true;
|
||||
case WM_KEYUP:
|
||||
if (wParam >= 0 && wParam < 256)
|
||||
if (wParam < 256)
|
||||
io.KeysDown[wParam] = 0;
|
||||
return true;
|
||||
case WM_CHAR:
|
||||
@ -245,6 +243,10 @@ static void ImGui_ImplDX11_CreateFontsTexture()
|
||||
samplerDesc.MaxLOD = 0.f;
|
||||
g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler);
|
||||
}
|
||||
|
||||
// Cleanup (don't clear the input data if you want to append new fonts later)
|
||||
io.Fonts->ClearInputData();
|
||||
io.Fonts->ClearTexData();
|
||||
}
|
||||
|
||||
bool ImGui_ImplDX11_CreateDeviceObjects()
|
||||
@ -292,9 +294,9 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
|
||||
|
||||
// Create the input layout
|
||||
D3D11_INPUT_ELEMENT_DESC localLayout[] = {
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, (size_t)(&((CUSTOMVERTEX*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((CUSTOMVERTEX*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((CUSTOMVERTEX*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
};
|
||||
|
||||
if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK)
|
||||
@ -350,19 +352,42 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
|
||||
desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
|
||||
desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
|
||||
desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
|
||||
g_pd3dDevice->CreateBlendState(&desc, &g_blendState);
|
||||
g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState);
|
||||
}
|
||||
|
||||
// Create the rasterizer state
|
||||
{
|
||||
D3D11_RASTERIZER_DESC desc;
|
||||
ZeroMemory(&desc, sizeof(desc));
|
||||
desc.FillMode = D3D11_FILL_SOLID;
|
||||
desc.CullMode = D3D11_CULL_NONE;
|
||||
desc.ScissorEnable = true;
|
||||
desc.DepthClipEnable = true;
|
||||
g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState);
|
||||
}
|
||||
|
||||
// Create the vertex buffer
|
||||
{
|
||||
D3D11_BUFFER_DESC desc;
|
||||
memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
desc.ByteWidth = VERTEX_BUFFER_SIZE * 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 false;
|
||||
}
|
||||
|
||||
// Create the index buffer
|
||||
{
|
||||
D3D11_BUFFER_DESC bufferDesc;
|
||||
memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC));
|
||||
bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
bufferDesc.ByteWidth = 100000 * sizeof(CUSTOMVERTEX); // Maybe we should handle that more dynamically?
|
||||
bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
bufferDesc.ByteWidth = INDEX_BUFFER_SIZE * sizeof(ImDrawIdx);
|
||||
bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
|
||||
bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
bufferDesc.MiscFlags = 0;
|
||||
if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pVB) < 0)
|
||||
if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -378,9 +403,11 @@ void ImGui_ImplDX11_InvalidateDeviceObjects()
|
||||
|
||||
if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; }
|
||||
if (g_pFontTextureView) { g_pFontTextureView->Release(); ImGui::GetIO().Fonts->TexID = 0; }
|
||||
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
|
||||
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
|
||||
|
||||
if (g_blendState) { g_blendState->Release(); g_blendState = NULL; }
|
||||
if (g_pBlendState) { g_pBlendState->Release(); g_pBlendState = NULL; }
|
||||
if (g_pRasterizerState) { g_pRasterizerState->Release(); g_pRasterizerState = NULL; }
|
||||
if (g_pPixelShader) { g_pPixelShader->Release(); g_pPixelShader = NULL; }
|
||||
if (g_pPixelShaderBlob) { g_pPixelShaderBlob->Release(); g_pPixelShaderBlob = NULL; }
|
||||
if (g_pVertexConstantBuffer) { g_pVertexConstantBuffer->Release(); g_pVertexConstantBuffer = NULL; }
|
||||
@ -405,7 +432,9 @@ bool ImGui_ImplDX11_Init(void* hwnd, ID3D11Device* device, ID3D11DeviceContex
|
||||
io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT;
|
||||
io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT;
|
||||
io.KeyMap[ImGuiKey_UpArrow] = VK_UP;
|
||||
io.KeyMap[ImGuiKey_DownArrow] = VK_UP;
|
||||
io.KeyMap[ImGuiKey_DownArrow] = VK_DOWN;
|
||||
io.KeyMap[ImGuiKey_PageUp] = VK_PRIOR;
|
||||
io.KeyMap[ImGuiKey_PageDown] = VK_NEXT;
|
||||
io.KeyMap[ImGuiKey_Home] = VK_HOME;
|
||||
io.KeyMap[ImGuiKey_End] = VK_END;
|
||||
io.KeyMap[ImGuiKey_Delete] = VK_DELETE;
|
||||
@ -455,11 +484,15 @@ void ImGui_ImplDX11_NewFrame()
|
||||
// Read keyboard modifiers inputs
|
||||
io.KeyCtrl = (GetKeyState(VK_CONTROL) & 0x8000) != 0;
|
||||
io.KeyShift = (GetKeyState(VK_SHIFT) & 0x8000) != 0;
|
||||
io.KeyAlt = (GetKeyState(VK_MENU) & 0x8000) != 0;
|
||||
// io.KeysDown : filled by WM_KEYDOWN/WM_KEYUP events
|
||||
// io.MousePos : filled by WM_MOUSEMOVE events
|
||||
// io.MouseDown : filled by WM_*BUTTON* events
|
||||
// io.MouseWheel : filled by WM_MOUSEWHEEL events
|
||||
|
||||
// Hide OS mouse cursor if ImGui is drawing it
|
||||
SetCursor(io.MouseDrawCursor ? NULL : LoadCursor(NULL, IDC_ARROW));
|
||||
|
||||
// Start the frame
|
||||
ImGui::NewFrame();
|
||||
}
|
||||
|
@ -117,6 +117,10 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
ImGui_ImplDX11_CreateDeviceObjects();
|
||||
}
|
||||
return 0;
|
||||
case WM_SYSCOMMAND:
|
||||
if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu
|
||||
return 0;
|
||||
break;
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage(0);
|
||||
return 0;
|
||||
@ -124,7 +128,7 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
return DefWindowProc(hWnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
int main(int, char**)
|
||||
{
|
||||
// Create application window
|
||||
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, LoadCursor(NULL, IDC_ARROW), NULL, NULL, L"ImGui Example", NULL };
|
||||
@ -145,12 +149,22 @@ int main(int argc, char** argv)
|
||||
|
||||
// Setup ImGui binding
|
||||
ImGui_ImplDX11_Init(hwnd, g_pd3dDevice, g_pd3dDeviceContext);
|
||||
|
||||
// Load Fonts
|
||||
// (see extra_fonts/README.txt for more details)
|
||||
//ImGuiIO& io = ImGui::GetIO();
|
||||
//ImFont* my_font1 = io.Fonts->AddFontDefault();
|
||||
//ImFont* my_font2 = io.Fonts->AddFontFromFileTTF("extra_fonts/Karla-Regular.ttf", 15.0f);
|
||||
//ImFont* my_font3 = io.Fonts->AddFontFromFileTTF("extra_fonts/ProggyClean.ttf", 13.0f); my_font3->DisplayOffset.y += 1;
|
||||
//ImFont* my_font4 = io.Fonts->AddFontFromFileTTF("extra_fonts/ProggyTiny.ttf", 10.0f); my_font4->DisplayOffset.y += 1;
|
||||
//ImFont* my_font5 = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, io.Fonts->GetGlyphRangesJapanese());
|
||||
//io.Fonts->AddFontDefault();
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
|
||||
|
||||
// Merge glyphs from multiple fonts into one (e.g. combine default font with another with Chinese glyphs, or add icons)
|
||||
//ImWchar icons_ranges[] = { 0xf000, 0xf3ff, 0 };
|
||||
//ImFontConfig icons_config; icons_config.MergeMode = true; icons_config.PixelSnapH = true;
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 18.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/fontawesome-webfont.ttf", 18.0f, &icons_config, icons_ranges);
|
||||
|
||||
bool show_test_window = true;
|
||||
bool show_another_window = false;
|
||||
@ -172,7 +186,7 @@ int main(int argc, char** argv)
|
||||
// 1. Show a simple window
|
||||
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug"
|
||||
{
|
||||
static float f;
|
||||
static float f = 0.0f;
|
||||
ImGui::Text("Hello, world!");
|
||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
|
||||
ImGui::ColorEdit3("clear color", (float*)&clear_col);
|
||||
@ -184,7 +198,8 @@ int main(int argc, char** argv)
|
||||
// 2. Show another simple window, this time using an explicit Begin/End pair
|
||||
if (show_another_window)
|
||||
{
|
||||
ImGui::Begin("Another Window", &show_another_window, ImVec2(200,100));
|
||||
ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiSetCond_FirstUseEver);
|
||||
ImGui::Begin("Another Window", &show_another_window);
|
||||
ImGui::Text("Hello");
|
||||
ImGui::End();
|
||||
}
|
||||
|
@ -5,10 +5,18 @@
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{4165A294-21F2-44CA-9B38-E3F935ABADF5}</ProjectGuid>
|
||||
@ -20,35 +28,60 @@
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..;$(DXSDK_DIR)Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
@ -57,13 +90,26 @@
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(DXSDK_DIR)Lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>d3d9.lib;d3dx9d.lib;dxerr.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\..;$(DXSDK_DIR)Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
@ -74,6 +120,23 @@
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalLibraryDirectories>$(DXSDK_DIR)Lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>d3d9.lib;d3dx9d.lib;dxerr.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\imgui.cpp" />
|
||||
<ClCompile Include="imgui_impl_dx9.cpp" />
|
||||
|
@ -15,6 +15,9 @@ static INT64 g_Time = 0;
|
||||
static INT64 g_TicksPerSecond = 0;
|
||||
static LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;
|
||||
static LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL;
|
||||
static LPDIRECT3DINDEXBUFFER9 g_pIB = NULL;
|
||||
static int VERTEX_BUFFER_SIZE = 20000; // TODO: Make buffers smaller and grow dynamically as needed.
|
||||
static int INDEX_BUFFER_SIZE = 40000; // TODO: Make buffers smaller and grow dynamically as needed.
|
||||
|
||||
struct CUSTOMVERTEX
|
||||
{
|
||||
@ -27,23 +30,20 @@ struct CUSTOMVERTEX
|
||||
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure)
|
||||
// If text or lines are blurry when integrating ImGui in your engine:
|
||||
// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
|
||||
static void ImGui_ImplDX9_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count)
|
||||
static void ImGui_ImplDX9_RenderDrawLists(ImDrawData* draw_data)
|
||||
{
|
||||
size_t total_vtx_count = 0;
|
||||
for (int n = 0; n < cmd_lists_count; n++)
|
||||
total_vtx_count += cmd_lists[n]->vtx_buffer.size();
|
||||
if (total_vtx_count == 0)
|
||||
return;
|
||||
|
||||
// Copy and convert all vertices into a single contiguous buffer
|
||||
CUSTOMVERTEX* vtx_dst;
|
||||
if (g_pVB->Lock(0, (UINT)total_vtx_count, (void**)&vtx_dst, D3DLOCK_DISCARD) < 0)
|
||||
ImDrawIdx* idx_dst;
|
||||
if (g_pVB->Lock(0, (UINT)(draw_data->TotalVtxCount * sizeof(CUSTOMVERTEX)), (void**)&vtx_dst, D3DLOCK_DISCARD) < 0)
|
||||
return;
|
||||
for (int n = 0; n < cmd_lists_count; n++)
|
||||
if (g_pIB->Lock(0, (UINT)(draw_data->TotalIdxCount * sizeof(ImDrawIdx)), (void**)&idx_dst, D3DLOCK_DISCARD) < 0)
|
||||
return;
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = cmd_lists[n];
|
||||
const ImDrawVert* vtx_src = &cmd_list->vtx_buffer[0];
|
||||
for (size_t i = 0; i < cmd_list->vtx_buffer.size(); i++)
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
const ImDrawVert* vtx_src = &cmd_list->VtxBuffer[0];
|
||||
for (int i = 0; i < cmd_list->VtxBuffer.size(); i++)
|
||||
{
|
||||
vtx_dst->pos.x = vtx_src->pos.x;
|
||||
vtx_dst->pos.y = vtx_src->pos.y;
|
||||
@ -54,13 +54,18 @@ static void ImGui_ImplDX9_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_
|
||||
vtx_dst++;
|
||||
vtx_src++;
|
||||
}
|
||||
memcpy(idx_dst, &cmd_list->IdxBuffer[0], cmd_list->IdxBuffer.size() * sizeof(ImDrawIdx));
|
||||
idx_dst += cmd_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 );
|
||||
|
||||
// Setup render state: alpha-blending, no face culling, no depth testing
|
||||
// Setup render state: fixed-pipeline, alpha-blending, no face culling, no depth testing
|
||||
g_pd3dDevice->SetPixelShader( NULL );
|
||||
g_pd3dDevice->SetVertexShader( NULL );
|
||||
g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
|
||||
g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, false );
|
||||
g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, false );
|
||||
@ -88,29 +93,31 @@ static void ImGui_ImplDX9_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_
|
||||
|
||||
// Render command lists
|
||||
int vtx_offset = 0;
|
||||
for (int n = 0; n < cmd_lists_count; n++)
|
||||
int idx_offset = 0;
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = cmd_lists[n];
|
||||
for (size_t cmd_i = 0; cmd_i < cmd_list->commands.size(); cmd_i++)
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.size(); cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &cmd_list->commands[cmd_i];
|
||||
if (pcmd->user_callback)
|
||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback)
|
||||
{
|
||||
pcmd->user_callback(cmd_list, pcmd);
|
||||
pcmd->UserCallback(cmd_list, pcmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
const RECT r = { (LONG)pcmd->clip_rect.x, (LONG)pcmd->clip_rect.y, (LONG)pcmd->clip_rect.z, (LONG)pcmd->clip_rect.w };
|
||||
g_pd3dDevice->SetTexture( 0, (LPDIRECT3DTEXTURE9)pcmd->texture_id );
|
||||
const RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w };
|
||||
g_pd3dDevice->SetTexture( 0, (LPDIRECT3DTEXTURE9)pcmd->TextureId );
|
||||
g_pd3dDevice->SetScissorRect(&r);
|
||||
g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, vtx_offset, pcmd->vtx_count/3);
|
||||
g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, vtx_offset, 0, (UINT)cmd_list->VtxBuffer.size(), idx_offset, pcmd->ElemCount/3);
|
||||
}
|
||||
vtx_offset += pcmd->vtx_count;
|
||||
idx_offset += pcmd->ElemCount;
|
||||
}
|
||||
vtx_offset += cmd_list->VtxBuffer.size();
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT ImGui_ImplDX9_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
LRESULT ImGui_ImplDX9_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
switch (msg)
|
||||
@ -135,11 +142,11 @@ LRESULT ImGui_ImplDX9_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM
|
||||
io.MousePos.y = (signed short)(lParam >> 16);
|
||||
return true;
|
||||
case WM_KEYDOWN:
|
||||
if (wParam >= 0 && wParam < 256)
|
||||
if (wParam < 256)
|
||||
io.KeysDown[wParam] = 1;
|
||||
return true;
|
||||
case WM_KEYUP:
|
||||
if (wParam >= 0 && wParam < 256)
|
||||
if (wParam < 256)
|
||||
io.KeysDown[wParam] = 0;
|
||||
return true;
|
||||
case WM_CHAR:
|
||||
@ -166,7 +173,9 @@ bool ImGui_ImplDX9_Init(void* hwnd, IDirect3DDevice9* device)
|
||||
io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT;
|
||||
io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT;
|
||||
io.KeyMap[ImGuiKey_UpArrow] = VK_UP;
|
||||
io.KeyMap[ImGuiKey_DownArrow] = VK_UP;
|
||||
io.KeyMap[ImGuiKey_DownArrow] = VK_DOWN;
|
||||
io.KeyMap[ImGuiKey_PageUp] = VK_PRIOR;
|
||||
io.KeyMap[ImGuiKey_PageDown] = VK_NEXT;
|
||||
io.KeyMap[ImGuiKey_Home] = VK_HOME;
|
||||
io.KeyMap[ImGuiKey_End] = VK_END;
|
||||
io.KeyMap[ImGuiKey_Delete] = VK_DELETE;
|
||||
@ -183,9 +192,6 @@ bool ImGui_ImplDX9_Init(void* hwnd, IDirect3DDevice9* device)
|
||||
io.RenderDrawListsFn = ImGui_ImplDX9_RenderDrawLists;
|
||||
io.ImeWindowHandle = g_hWnd;
|
||||
|
||||
if (g_pd3dDevice->CreateVertexBuffer(10000 * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL) < 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -225,6 +231,10 @@ static void ImGui_ImplDX9_CreateFontsTexture()
|
||||
|
||||
// Store our identifier
|
||||
io.Fonts->TexID = (void *)pTexture;
|
||||
|
||||
// Cleanup (don't clear the input data if you want to append new fonts later)
|
||||
io.Fonts->ClearInputData();
|
||||
io.Fonts->ClearTexData();
|
||||
}
|
||||
|
||||
bool ImGui_ImplDX9_CreateDeviceObjects()
|
||||
@ -232,7 +242,10 @@ bool ImGui_ImplDX9_CreateDeviceObjects()
|
||||
if (!g_pd3dDevice)
|
||||
return false;
|
||||
|
||||
if (g_pd3dDevice->CreateVertexBuffer(10000 * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL) < 0)
|
||||
if (g_pd3dDevice->CreateVertexBuffer(VERTEX_BUFFER_SIZE * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL) < 0)
|
||||
return false;
|
||||
|
||||
if (g_pd3dDevice->CreateIndexBuffer(INDEX_BUFFER_SIZE * sizeof(ImDrawIdx), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &g_pIB, NULL) < 0)
|
||||
return false;
|
||||
|
||||
ImGui_ImplDX9_CreateFontsTexture();
|
||||
@ -248,6 +261,11 @@ void ImGui_ImplDX9_InvalidateDeviceObjects()
|
||||
g_pVB->Release();
|
||||
g_pVB = NULL;
|
||||
}
|
||||
if (g_pIB)
|
||||
{
|
||||
g_pIB->Release();
|
||||
g_pIB = NULL;
|
||||
}
|
||||
if (LPDIRECT3DTEXTURE9 tex = (LPDIRECT3DTEXTURE9)ImGui::GetIO().Fonts->TexID)
|
||||
{
|
||||
tex->Release();
|
||||
@ -276,11 +294,15 @@ void ImGui_ImplDX9_NewFrame()
|
||||
// Read keyboard modifiers inputs
|
||||
io.KeyCtrl = (GetKeyState(VK_CONTROL) & 0x8000) != 0;
|
||||
io.KeyShift = (GetKeyState(VK_SHIFT) & 0x8000) != 0;
|
||||
io.KeyAlt = (GetKeyState(VK_MENU) & 0x8000) != 0;
|
||||
// io.KeysDown : filled by WM_KEYDOWN/WM_KEYUP events
|
||||
// io.MousePos : filled by WM_MOUSEMOVE events
|
||||
// io.MouseDown : filled by WM_*BUTTON* events
|
||||
// io.MouseWheel : filled by WM_MOUSEWHEEL events
|
||||
|
||||
// Hide OS mouse cursor if ImGui is drawing it
|
||||
SetCursor(io.MouseDrawCursor ? NULL : LoadCursor(NULL, IDC_ARROW));
|
||||
|
||||
// Start the frame
|
||||
ImGui::NewFrame();
|
||||
}
|
||||
|
@ -30,6 +30,10 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
ImGui_ImplDX9_CreateDeviceObjects();
|
||||
}
|
||||
return 0;
|
||||
case WM_SYSCOMMAND:
|
||||
if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu
|
||||
return 0;
|
||||
break;
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage(0);
|
||||
return 0;
|
||||
@ -37,7 +41,7 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
return DefWindowProc(hWnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
int main(int, char**)
|
||||
{
|
||||
// Create application window
|
||||
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, LoadCursor(NULL, IDC_ARROW), NULL, NULL, L"ImGui Example", NULL };
|
||||
@ -69,15 +73,22 @@ int main(int argc, char** argv)
|
||||
|
||||
// Setup ImGui binding
|
||||
ImGui_ImplDX9_Init(hwnd, g_pd3dDevice);
|
||||
//ImGuiIO& io = ImGui::GetIO();
|
||||
//ImFont* my_font1 = io.Fonts->AddFontDefault();
|
||||
//ImFont* my_font2 = io.Fonts->AddFontFromFileTTF("extra_fonts/Karla-Regular.ttf", 15.0f);
|
||||
//ImFont* my_font3 = io.Fonts->AddFontFromFileTTF("extra_fonts/ProggyClean.ttf", 13.0f); my_font3->DisplayOffset.y += 1;
|
||||
//ImFont* my_font4 = io.Fonts->AddFontFromFileTTF("extra_fonts/ProggyTiny.ttf", 10.0f); my_font4->DisplayOffset.y += 1;
|
||||
//ImFont* my_font5 = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, io.Fonts->GetGlyphRangesJapanese());
|
||||
|
||||
ShowWindow(hwnd, SW_SHOWDEFAULT);
|
||||
UpdateWindow(hwnd);
|
||||
// Load Fonts
|
||||
// (see extra_fonts/README.txt for more details)
|
||||
//ImGuiIO& io = ImGui::GetIO();
|
||||
//io.Fonts->AddFontDefault();
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
|
||||
|
||||
// Merge glyphs from multiple fonts into one (e.g. combine default font with another with Chinese glyphs, or add icons)
|
||||
//ImWchar icons_ranges[] = { 0xf000, 0xf3ff, 0 };
|
||||
//ImFontConfig icons_config; icons_config.MergeMode = true; icons_config.PixelSnapH = true;
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 18.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/fontawesome-webfont.ttf", 18.0f, &icons_config, icons_ranges);
|
||||
|
||||
bool show_test_window = true;
|
||||
bool show_another_window = false;
|
||||
@ -86,6 +97,8 @@ int main(int argc, char** argv)
|
||||
// Main loop
|
||||
MSG msg;
|
||||
ZeroMemory(&msg, sizeof(msg));
|
||||
ShowWindow(hwnd, SW_SHOWDEFAULT);
|
||||
UpdateWindow(hwnd);
|
||||
while (msg.message != WM_QUIT)
|
||||
{
|
||||
if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
|
||||
@ -99,7 +112,7 @@ int main(int argc, char** argv)
|
||||
// 1. Show a simple window
|
||||
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug"
|
||||
{
|
||||
static float f;
|
||||
static float f = 0.0f;
|
||||
ImGui::Text("Hello, world!");
|
||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
|
||||
ImGui::ColorEdit3("clear color", (float*)&clear_col);
|
||||
@ -111,7 +124,8 @@ int main(int argc, char** argv)
|
||||
// 2. Show another simple window, this time using an explicit Begin/End pair
|
||||
if (show_another_window)
|
||||
{
|
||||
ImGui::Begin("Another Window", &show_another_window, ImVec2(200,100));
|
||||
ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiSetCond_FirstUseEver);
|
||||
ImGui::Begin("Another Window", &show_another_window);
|
||||
ImGui::Text("Hello");
|
||||
ImGui::End();
|
||||
}
|
||||
|
@ -12,25 +12,43 @@ EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Debug|x64 = Debug|x64
|
||||
Release|Win32 = Release|Win32
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{9CDA7840-B7A5-496D-A527-E95571496D18}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{9CDA7840-B7A5-496D-A527-E95571496D18}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{9CDA7840-B7A5-496D-A527-E95571496D18}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{9CDA7840-B7A5-496D-A527-E95571496D18}.Debug|x64.Build.0 = Debug|x64
|
||||
{9CDA7840-B7A5-496D-A527-E95571496D18}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{9CDA7840-B7A5-496D-A527-E95571496D18}.Release|Win32.Build.0 = Release|Win32
|
||||
{9CDA7840-B7A5-496D-A527-E95571496D18}.Release|x64.ActiveCfg = Release|x64
|
||||
{9CDA7840-B7A5-496D-A527-E95571496D18}.Release|x64.Build.0 = Release|x64
|
||||
{4165A294-21F2-44CA-9B38-E3F935ABADF5}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{4165A294-21F2-44CA-9B38-E3F935ABADF5}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{4165A294-21F2-44CA-9B38-E3F935ABADF5}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{4165A294-21F2-44CA-9B38-E3F935ABADF5}.Debug|x64.Build.0 = Debug|x64
|
||||
{4165A294-21F2-44CA-9B38-E3F935ABADF5}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{4165A294-21F2-44CA-9B38-E3F935ABADF5}.Release|Win32.Build.0 = Release|Win32
|
||||
{4165A294-21F2-44CA-9B38-E3F935ABADF5}.Release|x64.ActiveCfg = Release|x64
|
||||
{4165A294-21F2-44CA-9B38-E3F935ABADF5}.Release|x64.Build.0 = Release|x64
|
||||
{9F316E83-5AE5-4939-A723-305A94F48005}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{9F316E83-5AE5-4939-A723-305A94F48005}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{9F316E83-5AE5-4939-A723-305A94F48005}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{9F316E83-5AE5-4939-A723-305A94F48005}.Debug|x64.Build.0 = Debug|x64
|
||||
{9F316E83-5AE5-4939-A723-305A94F48005}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{9F316E83-5AE5-4939-A723-305A94F48005}.Release|Win32.Build.0 = Release|Win32
|
||||
{9F316E83-5AE5-4939-A723-305A94F48005}.Release|x64.ActiveCfg = Release|x64
|
||||
{9F316E83-5AE5-4939-A723-305A94F48005}.Release|x64.Build.0 = Release|x64
|
||||
{4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Debug|x64.Build.0 = Debug|x64
|
||||
{4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Release|Win32.Build.0 = Release|Win32
|
||||
{4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Release|x64.ActiveCfg = Release|x64
|
||||
{4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
3
examples/ios_example/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
.DS_Store
|
||||
imguiex.xcodeproj/project.xcworkspace/
|
||||
imguiex.xcodeproj/xcuserdata/
|
35
examples/ios_example/README.md
Normal file
@ -0,0 +1,35 @@
|
||||
# iOS example
|
||||
|
||||
----
|
||||
## Introduction
|
||||
|
||||
This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/).
|
||||
|
||||
Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active.
|
||||
|
||||
## How to Use
|
||||
----
|
||||
|
||||
0. In Synergy, go to Preferences, and uncheck "Use SSL encryption"
|
||||
0. Run the example app.
|
||||
0. Tap the "servername" button in the corner
|
||||
0. Enter the name or the IP of your synergy host
|
||||
0. If you had previously connected to a server, you may need to kill and re-start the app.
|
||||
|
||||
----
|
||||
## Notes and TODOs
|
||||
|
||||
Things that would be nice but I didn't get around to doing:
|
||||
|
||||
* iOS software keyboard not supported for text inputs
|
||||
* iOS hardware (bluetooth) keyboards not supported
|
||||
* Graceful disconnect/reconnect from uSynergy.
|
||||
* Copy/Paste not well-supported
|
||||
|
||||
----
|
||||
## C++ on iOS
|
||||
ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension.
|
||||
|
||||
Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer.
|
||||
|
||||
In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly.
|
365
examples/ios_example/imguiex.xcodeproj/project.pbxproj
Normal file
@ -0,0 +1,365 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; };
|
||||
6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; };
|
||||
6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; };
|
||||
6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; };
|
||||
6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; };
|
||||
6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; };
|
||||
6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; };
|
||||
6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; };
|
||||
6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; };
|
||||
6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; };
|
||||
6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; };
|
||||
6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; };
|
||||
6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; };
|
||||
6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = "<group>"; };
|
||||
6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = "<group>"; };
|
||||
6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
||||
6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
||||
6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = "<group>"; };
|
||||
6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = "<group>"; };
|
||||
6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = "<group>"; };
|
||||
6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = "<group>"; };
|
||||
6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||
6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
|
||||
6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
|
||||
6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = "<group>"; };
|
||||
6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = "<group>"; };
|
||||
6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = "<group>"; };
|
||||
6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = "<group>"; };
|
||||
6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = "<group>"; };
|
||||
6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = "<group>"; };
|
||||
6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = "<group>"; };
|
||||
6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; };
|
||||
6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
6D2FC5511B2E632000C130BA /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */,
|
||||
6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
6D1E39141B35EEF10017B40F /* usynergy */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6D1E39151B35EEF10017B40F /* uSynergy.c */,
|
||||
6D1E39161B35EEF10017B40F /* uSynergy.h */,
|
||||
);
|
||||
name = usynergy;
|
||||
path = ../libs/usynergy;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6D2FC54B1B2E632000C130BA = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6D1E39141B35EEF10017B40F /* usynergy */,
|
||||
6D2FC5841B2E648D00C130BA /* imgui */,
|
||||
6D2FC5561B2E632000C130BA /* imguiex */,
|
||||
6D2FC5551B2E632000C130BA /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6D2FC5551B2E632000C130BA /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6D2FC5541B2E632000C130BA /* imguiex.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6D2FC5561B2E632000C130BA /* imguiex */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */,
|
||||
6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */,
|
||||
6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */,
|
||||
6D2FC58A1B2E6A5500C130BA /* debug_hud.h */,
|
||||
6D2FC55B1B2E632000C130BA /* AppDelegate.h */,
|
||||
6D2FC55C1B2E632000C130BA /* AppDelegate.m */,
|
||||
6D2FC55E1B2E632000C130BA /* Shader.fsh */,
|
||||
6D2FC5601B2E632000C130BA /* Shader.vsh */,
|
||||
6D2FC5621B2E632000C130BA /* GameViewController.h */,
|
||||
6D2FC5631B2E632000C130BA /* GameViewController.m */,
|
||||
6D2FC5651B2E632000C130BA /* Main.storyboard */,
|
||||
6D2FC5681B2E632000C130BA /* Images.xcassets */,
|
||||
6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */,
|
||||
6D2FC5571B2E632000C130BA /* Supporting Files */,
|
||||
);
|
||||
path = imguiex;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6D2FC5571B2E632000C130BA /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6D2FC5921B30774900C130BA /* SystemConfiguration.framework */,
|
||||
6D2FC5901B30773F00C130BA /* CFNetwork.framework */,
|
||||
6D2FC5581B2E632000C130BA /* Info.plist */,
|
||||
6D2FC5591B2E632000C130BA /* main.m */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6D2FC5841B2E648D00C130BA /* imgui */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6D2FC5851B2E64AB00C130BA /* imconfig.h */,
|
||||
6D2FC5861B2E64AB00C130BA /* imgui.cpp */,
|
||||
6D2FC5871B2E64AB00C130BA /* imgui.h */,
|
||||
);
|
||||
name = imgui;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
6D2FC5531B2E632000C130BA /* imguiex */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */;
|
||||
buildPhases = (
|
||||
6D2FC5501B2E632000C130BA /* Sources */,
|
||||
6D2FC5511B2E632000C130BA /* Frameworks */,
|
||||
6D2FC5521B2E632000C130BA /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = imguiex;
|
||||
productName = imguiex;
|
||||
productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
6D2FC54C1B2E632000C130BA /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0630;
|
||||
ORGANIZATIONNAME = "Joel Davis";
|
||||
TargetAttributes = {
|
||||
6D2FC5531B2E632000C130BA = {
|
||||
CreatedOnToolsVersion = 6.3.2;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 6D2FC54B1B2E632000C130BA;
|
||||
productRefGroup = 6D2FC5551B2E632000C130BA /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
6D2FC5531B2E632000C130BA /* imguiex */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
6D2FC5521B2E632000C130BA /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */,
|
||||
6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */,
|
||||
6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */,
|
||||
6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */,
|
||||
6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
6D2FC5501B2E632000C130BA /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */,
|
||||
6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */,
|
||||
6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */,
|
||||
6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */,
|
||||
6D2FC55A1B2E632000C130BA /* main.m in Sources */,
|
||||
6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */,
|
||||
6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
6D2FC5651B2E632000C130BA /* Main.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
6D2FC5661B2E632000C130BA /* Base */,
|
||||
);
|
||||
name = Main.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
6D2FC56B1B2E632000C130BA /* Base */,
|
||||
);
|
||||
name = LaunchScreen.xib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
6D2FC5791B2E632000C130BA /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
6D2FC57A1B2E632000C130BA /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
6D2FC57C1B2E632000C130BA /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
INFOPLIST_FILE = imguiex/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
6D2FC57D1B2E632000C130BA /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
INFOPLIST_FILE = imguiex/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
6D2FC5791B2E632000C130BA /* Debug */,
|
||||
6D2FC57A1B2E632000C130BA /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
6D2FC57C1B2E632000C130BA /* Debug */,
|
||||
6D2FC57D1B2E632000C130BA /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 6D2FC54C1B2E632000C130BA /* Project object */;
|
||||
}
|
13
examples/ios_example/imguiex/AppDelegate.h
Normal file
@ -0,0 +1,13 @@
|
||||
//
|
||||
// AppDelegate.h
|
||||
// imguiex
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||
|
||||
@property (strong, nonatomic) UIWindow *window;
|
||||
|
||||
|
||||
@end
|
||||
|
41
examples/ios_example/imguiex/AppDelegate.m
Normal file
@ -0,0 +1,41 @@
|
||||
//
|
||||
// AppDelegate.m
|
||||
// imguiex
|
||||
|
||||
#import "AppDelegate.h"
|
||||
|
||||
@interface AppDelegate ()
|
||||
|
||||
@end
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
// Override point for customization after application launch.
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)applicationWillResignActive:(UIApplication *)application {
|
||||
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
|
||||
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
|
||||
}
|
||||
|
||||
- (void)applicationDidEnterBackground:(UIApplication *)application {
|
||||
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
|
||||
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
|
||||
}
|
||||
|
||||
- (void)applicationWillEnterForeground:(UIApplication *)application {
|
||||
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
|
||||
}
|
||||
|
||||
- (void)applicationDidBecomeActive:(UIApplication *)application {
|
||||
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
|
||||
}
|
||||
|
||||
- (void)applicationWillTerminate:(UIApplication *)application {
|
||||
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
|
||||
}
|
||||
|
||||
@end
|
32
examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib
Normal file
@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7706" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
|
||||
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view contentMode="scaleToFill" id="iN0-l3-epB">
|
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="imguiex" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
|
||||
<rect key="frame" x="20" y="140" width="441" height="43"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="5cJ-9S-tgC"/>
|
||||
<constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk"/>
|
||||
<constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g"/>
|
||||
</constraints>
|
||||
<nil key="simulatedStatusBarMetrics"/>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<point key="canvasLocation" x="548" y="455"/>
|
||||
</view>
|
||||
</objects>
|
||||
</document>
|
44
examples/ios_example/imguiex/Base.lproj/Main.storyboard
Normal file
@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="7706" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BV1-FR-VrT">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
|
||||
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--Game View Controller-->
|
||||
<scene sceneID="tXr-a1-R10">
|
||||
<objects>
|
||||
<viewController id="BV1-FR-VrT" customClass="GameViewController" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="8aa-yV-Osq"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="qHh-Mt-9TT"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="3se-qz-xqx" customClass="GLKView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="piS-r7-VWh">
|
||||
<rect key="frame" x="16" y="550" width="136" height="30"/>
|
||||
<state key="normal" title="servername">
|
||||
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="onServernameTapped:" destination="BV1-FR-VrT" eventType="touchUpInside" id="9sO-yv-0be"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstItem="qHh-Mt-9TT" firstAttribute="top" secondItem="piS-r7-VWh" secondAttribute="bottom" constant="20" id="JxW-fj-qni"/>
|
||||
<constraint firstItem="piS-r7-VWh" firstAttribute="leading" secondItem="3se-qz-xqx" secondAttribute="leadingMargin" constant="20" id="w5q-gx-tJj"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="btnServername" destination="piS-r7-VWh" id="9iV-ef-l6M"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="SZV-WD-TEh" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
12
examples/ios_example/imguiex/GameViewController.h
Normal file
@ -0,0 +1,12 @@
|
||||
//
|
||||
// GameViewController.h
|
||||
// imguiex
|
||||
|
||||
// This is the OpenGL Example template from XCode, modified to support ImGui
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <GLKit/GLKit.h>
|
||||
|
||||
@interface GameViewController : GLKViewController
|
||||
|
||||
@end
|
481
examples/ios_example/imguiex/GameViewController.m
Normal file
@ -0,0 +1,481 @@
|
||||
//
|
||||
// GameViewController.m
|
||||
// imguiex
|
||||
//
|
||||
#import "GameViewController.h"
|
||||
#import <OpenGLES/ES2/glext.h>
|
||||
|
||||
#import "imgui_impl_ios.h"
|
||||
#import "debug_hud.h"
|
||||
|
||||
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
|
||||
|
||||
#define SERVERNAME_KEY @"ServerName"
|
||||
|
||||
#define SERVERNAME_ALERT_TAG (10)
|
||||
|
||||
// Uniform index.
|
||||
enum
|
||||
{
|
||||
UNIFORM_MODELVIEWPROJECTION_MATRIX,
|
||||
UNIFORM_NORMAL_MATRIX,
|
||||
UNIFORM_DIFFUSE_COLOR,
|
||||
|
||||
NUM_UNIFORMS
|
||||
};
|
||||
GLint uniforms[NUM_UNIFORMS];
|
||||
|
||||
// Attribute index.
|
||||
enum
|
||||
{
|
||||
ATTRIB_VERTEX,
|
||||
ATTRIB_NORMAL,
|
||||
NUM_ATTRIBUTES
|
||||
};
|
||||
|
||||
GLfloat gCubeVertexData[216] =
|
||||
{
|
||||
// Data layout for each line below is:
|
||||
// positionX, positionY, positionZ, normalX, normalY, normalZ,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
|
||||
|
||||
0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
|
||||
|
||||
-0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
|
||||
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
|
||||
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
|
||||
0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f
|
||||
};
|
||||
|
||||
@interface GameViewController () <UIAlertViewDelegate>
|
||||
{
|
||||
GLuint _program;
|
||||
|
||||
GLKMatrix4 _modelViewProjectionMatrix;
|
||||
GLKMatrix3 _normalMatrix;
|
||||
float _rotation;
|
||||
|
||||
GLuint _vertexArray;
|
||||
GLuint _vertexBuffer;
|
||||
|
||||
DebugHUD _hud;
|
||||
}
|
||||
@property (strong, nonatomic) EAGLContext *context;
|
||||
@property (strong, nonatomic) GLKBaseEffect *effect;
|
||||
@property (strong, nonatomic) ImGuiHelper *imgui;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *btnServername;
|
||||
|
||||
@property (strong, nonatomic) NSString *serverName;
|
||||
|
||||
- (IBAction)onServernameTapped:(id)sender;
|
||||
|
||||
- (void)setupGL;
|
||||
- (void)tearDownGL;
|
||||
|
||||
- (BOOL)loadShaders;
|
||||
- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file;
|
||||
- (BOOL)linkProgram:(GLuint)prog;
|
||||
- (BOOL)validateProgram:(GLuint)prog;
|
||||
@end
|
||||
|
||||
@implementation GameViewController
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
|
||||
self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
|
||||
|
||||
if (!self.context) {
|
||||
NSLog(@"Failed to create ES context");
|
||||
}
|
||||
|
||||
GLKView *view = (GLKView *)self.view;
|
||||
view.context = self.context;
|
||||
view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
|
||||
|
||||
[self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
|
||||
|
||||
[self setupGL];
|
||||
|
||||
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
|
||||
self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ];
|
||||
self.imgui = [[ImGuiHelper alloc] initWithView:self.view ];
|
||||
if (self.serverName)
|
||||
{
|
||||
[self.btnServername setTitle:self.serverName forState:UIControlStateNormal];
|
||||
[self.imgui connectServer: self.serverName ];
|
||||
}
|
||||
|
||||
DebugHUD_InitDefaults( &_hud );
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[self tearDownGL];
|
||||
|
||||
if ([EAGLContext currentContext] == self.context) {
|
||||
[EAGLContext setCurrentContext:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning
|
||||
{
|
||||
[super didReceiveMemoryWarning];
|
||||
|
||||
if ([self isViewLoaded] && ([[self view] window] == nil)) {
|
||||
self.view = nil;
|
||||
|
||||
[self tearDownGL];
|
||||
|
||||
if ([EAGLContext currentContext] == self.context) {
|
||||
[EAGLContext setCurrentContext:nil];
|
||||
}
|
||||
self.context = nil;
|
||||
}
|
||||
|
||||
// Dispose of any resources that can be recreated.
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)prefersStatusBarHidden {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (IBAction)onServernameTapped:(id)sender
|
||||
{
|
||||
UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ];
|
||||
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
|
||||
alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to
|
||||
[alert show];
|
||||
}
|
||||
|
||||
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
|
||||
{
|
||||
if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG))
|
||||
{
|
||||
// This is really janky. I usually just hardcode the servername since I'm building it anyway.
|
||||
// If you want to properly handle updating the server, you'll want to tear down and recreate
|
||||
// the usynergy stuff in connectServer
|
||||
BOOL serverNameWasSet = self.serverName.length > 0;
|
||||
NSString *serverName = [[alertView textFieldAtIndex:0] text];
|
||||
|
||||
if ([serverName length] > 0) {
|
||||
self.serverName = serverName;
|
||||
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
|
||||
[userDefaults setObject:serverName forKey:SERVERNAME_KEY ];
|
||||
[userDefaults synchronize];
|
||||
|
||||
[self.btnServername setTitle:self.serverName forState:UIControlStateNormal];
|
||||
|
||||
// If we hadn't previously connected, try now
|
||||
if (!serverNameWasSet) {
|
||||
[self.imgui connectServer:self.serverName];
|
||||
}
|
||||
else
|
||||
{
|
||||
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated"
|
||||
message:@"Restart the app to connect the server"
|
||||
delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
|
||||
[alert show];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setupGL
|
||||
{
|
||||
[EAGLContext setCurrentContext:self.context];
|
||||
|
||||
[self loadShaders];
|
||||
|
||||
self.effect = [[GLKBaseEffect alloc] init];
|
||||
self.effect.light0.enabled = GL_TRUE;
|
||||
self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
glGenVertexArraysOES(1, &_vertexArray);
|
||||
glBindVertexArrayOES(_vertexArray);
|
||||
|
||||
glGenBuffers(1, &_vertexBuffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW);
|
||||
|
||||
glEnableVertexAttribArray(GLKVertexAttribPosition);
|
||||
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0));
|
||||
glEnableVertexAttribArray(GLKVertexAttribNormal);
|
||||
glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12));
|
||||
|
||||
glBindVertexArrayOES(0);
|
||||
|
||||
|
||||
}
|
||||
|
||||
- (void)tearDownGL
|
||||
{
|
||||
[EAGLContext setCurrentContext:self.context];
|
||||
|
||||
glDeleteBuffers(1, &_vertexBuffer);
|
||||
glDeleteVertexArraysOES(1, &_vertexArray);
|
||||
|
||||
self.effect = nil;
|
||||
|
||||
if (_program) {
|
||||
glDeleteProgram(_program);
|
||||
_program = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - GLKView and GLKViewController delegate methods
|
||||
|
||||
- (void)update
|
||||
{
|
||||
float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height);
|
||||
GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f);
|
||||
|
||||
self.effect.transform.projectionMatrix = projectionMatrix;
|
||||
|
||||
GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f);
|
||||
baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f);
|
||||
|
||||
// Compute the model view matrix for the object rendered with GLKit
|
||||
GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f);
|
||||
modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f);
|
||||
modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix);
|
||||
|
||||
self.effect.transform.modelviewMatrix = modelViewMatrix;
|
||||
|
||||
// Compute the model view matrix for the object rendered with ES2
|
||||
modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f);
|
||||
modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f);
|
||||
modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix);
|
||||
|
||||
_normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL);
|
||||
|
||||
_modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix);
|
||||
|
||||
_rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0));
|
||||
}
|
||||
|
||||
|
||||
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
|
||||
{
|
||||
glClearColor(0.65f, 0.65f, 0.65f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glBindVertexArrayOES(_vertexArray);
|
||||
|
||||
// Render the object with GLKit
|
||||
[self.effect prepareToDraw];
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
|
||||
// Render the object again with ES2
|
||||
glUseProgram(_program);
|
||||
|
||||
glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m);
|
||||
glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m);
|
||||
glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] );
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
|
||||
[self.imgui newFrame];
|
||||
|
||||
// Now do our ImGUI UI
|
||||
DebugHUD_DoInterface( &_hud );
|
||||
|
||||
self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f);
|
||||
|
||||
// Now render Imgui
|
||||
[self.imgui render];
|
||||
|
||||
}
|
||||
|
||||
#pragma mark - OpenGL ES 2 shader compilation
|
||||
|
||||
- (BOOL)loadShaders
|
||||
{
|
||||
GLuint vertShader, fragShader;
|
||||
NSString *vertShaderPathname, *fragShaderPathname;
|
||||
|
||||
// Create shader program.
|
||||
_program = glCreateProgram();
|
||||
|
||||
// Create and compile vertex shader.
|
||||
vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"];
|
||||
if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) {
|
||||
NSLog(@"Failed to compile vertex shader");
|
||||
return NO;
|
||||
}
|
||||
|
||||
// Create and compile fragment shader.
|
||||
fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"];
|
||||
if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) {
|
||||
NSLog(@"Failed to compile fragment shader");
|
||||
return NO;
|
||||
}
|
||||
|
||||
// Attach vertex shader to program.
|
||||
glAttachShader(_program, vertShader);
|
||||
|
||||
// Attach fragment shader to program.
|
||||
glAttachShader(_program, fragShader);
|
||||
|
||||
// Bind attribute locations.
|
||||
// This needs to be done prior to linking.
|
||||
glBindAttribLocation(_program, GLKVertexAttribPosition, "position");
|
||||
glBindAttribLocation(_program, GLKVertexAttribNormal, "normal");
|
||||
|
||||
// Link program.
|
||||
if (![self linkProgram:_program]) {
|
||||
NSLog(@"Failed to link program: %d", _program);
|
||||
|
||||
if (vertShader) {
|
||||
glDeleteShader(vertShader);
|
||||
vertShader = 0;
|
||||
}
|
||||
if (fragShader) {
|
||||
glDeleteShader(fragShader);
|
||||
fragShader = 0;
|
||||
}
|
||||
if (_program) {
|
||||
glDeleteProgram(_program);
|
||||
_program = 0;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
// Get uniform locations.
|
||||
uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix");
|
||||
uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix");
|
||||
uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor");
|
||||
|
||||
// Release vertex and fragment shaders.
|
||||
if (vertShader) {
|
||||
glDetachShader(_program, vertShader);
|
||||
glDeleteShader(vertShader);
|
||||
}
|
||||
if (fragShader) {
|
||||
glDetachShader(_program, fragShader);
|
||||
glDeleteShader(fragShader);
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file
|
||||
{
|
||||
GLint status;
|
||||
const GLchar *source;
|
||||
|
||||
source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String];
|
||||
if (!source) {
|
||||
NSLog(@"Failed to load vertex shader");
|
||||
return NO;
|
||||
}
|
||||
|
||||
*shader = glCreateShader(type);
|
||||
glShaderSource(*shader, 1, &source, NULL);
|
||||
glCompileShader(*shader);
|
||||
|
||||
#if defined(DEBUG)
|
||||
GLint logLength;
|
||||
glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength);
|
||||
if (logLength > 0) {
|
||||
GLchar *log = (GLchar *)malloc(logLength);
|
||||
glGetShaderInfoLog(*shader, logLength, &logLength, log);
|
||||
NSLog(@"Shader compile log:\n%s", log);
|
||||
free(log);
|
||||
}
|
||||
#endif
|
||||
|
||||
glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
|
||||
if (status == 0) {
|
||||
glDeleteShader(*shader);
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)linkProgram:(GLuint)prog
|
||||
{
|
||||
GLint status;
|
||||
glLinkProgram(prog);
|
||||
|
||||
#if defined(DEBUG)
|
||||
GLint logLength;
|
||||
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength);
|
||||
if (logLength > 0) {
|
||||
GLchar *log = (GLchar *)malloc(logLength);
|
||||
glGetProgramInfoLog(prog, logLength, &logLength, log);
|
||||
NSLog(@"Program link log:\n%s", log);
|
||||
free(log);
|
||||
}
|
||||
#endif
|
||||
|
||||
glGetProgramiv(prog, GL_LINK_STATUS, &status);
|
||||
if (status == 0) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)validateProgram:(GLuint)prog
|
||||
{
|
||||
GLint logLength, status;
|
||||
|
||||
glValidateProgram(prog);
|
||||
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength);
|
||||
if (logLength > 0) {
|
||||
GLchar *log = (GLchar *)malloc(logLength);
|
||||
glGetProgramInfoLog(prog, logLength, &logLength, log);
|
||||
NSLog(@"Program validate log:\n%s", log);
|
||||
free(log);
|
||||
}
|
||||
|
||||
glGetProgramiv(prog, GL_VALIDATE_STATUS, &status);
|
||||
if (status == 0) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
@ -0,0 +1,72 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "icon_imgui_60@2x~iphone.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "icon_imgui_60@3x~iphone.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "29x29",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "29x29",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "40x40",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "40x40",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon_imgui_76~ipad.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon_imgui_76@2x~ipad.png",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 2.5 KiB |
49
examples/ios_example/imguiex/Info.plist
Normal file
@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.imgui.example.$(PRODUCT_NAME:rfc1034identifier)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UIStatusBarHidden</key>
|
||||
<true/>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
10
examples/ios_example/imguiex/Shaders/Shader.fsh
Normal file
@ -0,0 +1,10 @@
|
||||
//
|
||||
// Shader.fsh
|
||||
// imguiex
|
||||
|
||||
varying lowp vec4 colorVarying;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = colorVarying;
|
||||
}
|
25
examples/ios_example/imguiex/Shaders/Shader.vsh
Normal file
@ -0,0 +1,25 @@
|
||||
//
|
||||
// Shader.vsh
|
||||
// imguiex
|
||||
|
||||
attribute vec4 position;
|
||||
attribute vec3 normal;
|
||||
|
||||
varying lowp vec4 colorVarying;
|
||||
|
||||
uniform vec3 diffuseColor;
|
||||
uniform mat4 modelViewProjectionMatrix;
|
||||
uniform mat3 normalMatrix;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 eyeNormal = normalize(normalMatrix * normal);
|
||||
vec3 lightPosition = vec3(0.0, 0.0, 1.0);
|
||||
|
||||
float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition)));
|
||||
|
||||
vec3 colorLit = diffuseColor * nDotVP;
|
||||
colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 );
|
||||
|
||||
gl_Position = modelViewProjectionMatrix * position;
|
||||
}
|
45
examples/ios_example/imguiex/debug_hud.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
//
|
||||
// debug_hud.cpp
|
||||
// imguiex
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "debug_hud.h"
|
||||
#include "imgui.h"
|
||||
|
||||
void DebugHUD_InitDefaults( DebugHUD *hud )
|
||||
{
|
||||
hud->show_test_window = true;
|
||||
hud->show_example_window = true;
|
||||
hud->rotation_speed = 15.0f;
|
||||
|
||||
hud->cubeColor1[0] = 0.4f;
|
||||
hud->cubeColor1[1] = 0.4f;
|
||||
hud->cubeColor1[2] = 1.0f;
|
||||
hud->cubeColor1[3] = 1.0f;
|
||||
|
||||
hud->cubeColor2[0] = 1.0f;
|
||||
hud->cubeColor2[1] = 0.4f;
|
||||
hud->cubeColor2[2] = 0.4f;
|
||||
hud->cubeColor2[3] = 1.0f;
|
||||
}
|
||||
|
||||
void DebugHUD_DoInterface( DebugHUD *hud )
|
||||
{
|
||||
if (hud->show_test_window)
|
||||
{
|
||||
ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver );
|
||||
ImGui::ShowTestWindow( &hud->show_test_window );
|
||||
}
|
||||
|
||||
if (hud->show_example_window)
|
||||
{
|
||||
ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver );
|
||||
ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver );
|
||||
ImGui::Begin("Another Window", &hud->show_example_window);
|
||||
ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1);
|
||||
ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2);
|
||||
ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f);
|
||||
ImGui::End();
|
||||
}
|
||||
}
|
25
examples/ios_example/imguiex/debug_hud.h
Normal file
@ -0,0 +1,25 @@
|
||||
//
|
||||
// debug_hud.h
|
||||
// imguiex
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef struct DebugHUD
|
||||
{
|
||||
bool show_test_window;
|
||||
bool show_example_window;
|
||||
float rotation_speed;
|
||||
float cubeColor1[4];
|
||||
float cubeColor2[4];
|
||||
} DebugHUD;
|
||||
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void DebugHUD_InitDefaults( DebugHUD *hud );
|
||||
void DebugHUD_DoInterface( DebugHUD *hud );
|
||||
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
BIN
examples/ios_example/imguiex/imgui_ex_icon.png
Normal file
After Width: | Height: | Size: 12 KiB |
22
examples/ios_example/imguiex/imgui_impl_ios.h
Normal file
@ -0,0 +1,22 @@
|
||||
//
|
||||
// imgui_impl_ios.h
|
||||
// imguiex
|
||||
//
|
||||
// Joel Davis (joeld42@gmail.com)
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Foundation/Foundation.h>
|
||||
#include <UIKit/UIKit.h>
|
||||
|
||||
@interface ImGuiHelper : NSObject
|
||||
|
||||
- (id) initWithView: (UIView *)view;
|
||||
|
||||
- (void)connectServer: (NSString*)serverName;
|
||||
|
||||
- (void)render;
|
||||
- (void)newFrame;
|
||||
|
||||
@end
|
801
examples/ios_example/imguiex/imgui_impl_ios.mm
Normal file
@ -0,0 +1,801 @@
|
||||
//
|
||||
// imgui_impl_ios.cpp
|
||||
// imguiex
|
||||
|
||||
#import <OpenGLES/ES3/gl.h>
|
||||
#import <OpenGLES/ES3/glext.h>
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include "imgui_impl_ios.h"
|
||||
#include "imgui.h"
|
||||
|
||||
#include "uSynergy.h"
|
||||
|
||||
// From Carbon HIToolbox/Events.h
|
||||
// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247
|
||||
enum {
|
||||
kVK_ANSI_A = 0x00,
|
||||
kVK_ANSI_S = 0x01,
|
||||
kVK_ANSI_D = 0x02,
|
||||
kVK_ANSI_F = 0x03,
|
||||
kVK_ANSI_H = 0x04,
|
||||
kVK_ANSI_G = 0x05,
|
||||
kVK_ANSI_Z = 0x06,
|
||||
kVK_ANSI_X = 0x07,
|
||||
kVK_ANSI_C = 0x08,
|
||||
kVK_ANSI_V = 0x09,
|
||||
kVK_ANSI_B = 0x0B,
|
||||
kVK_ANSI_Q = 0x0C,
|
||||
kVK_ANSI_W = 0x0D,
|
||||
kVK_ANSI_E = 0x0E,
|
||||
kVK_ANSI_R = 0x0F,
|
||||
kVK_ANSI_Y = 0x10,
|
||||
kVK_ANSI_T = 0x11,
|
||||
kVK_ANSI_1 = 0x12,
|
||||
kVK_ANSI_2 = 0x13,
|
||||
kVK_ANSI_3 = 0x14,
|
||||
kVK_ANSI_4 = 0x15,
|
||||
kVK_ANSI_6 = 0x16,
|
||||
kVK_ANSI_5 = 0x17,
|
||||
kVK_ANSI_Equal = 0x18,
|
||||
kVK_ANSI_9 = 0x19,
|
||||
kVK_ANSI_7 = 0x1A,
|
||||
kVK_ANSI_Minus = 0x1B,
|
||||
kVK_ANSI_8 = 0x1C,
|
||||
kVK_ANSI_0 = 0x1D,
|
||||
kVK_ANSI_RightBracket = 0x1E,
|
||||
kVK_ANSI_O = 0x1F,
|
||||
kVK_ANSI_U = 0x20,
|
||||
kVK_ANSI_LeftBracket = 0x21,
|
||||
kVK_ANSI_I = 0x22,
|
||||
kVK_ANSI_P = 0x23,
|
||||
kVK_ANSI_L = 0x25,
|
||||
kVK_ANSI_J = 0x26,
|
||||
kVK_ANSI_Quote = 0x27,
|
||||
kVK_ANSI_K = 0x28,
|
||||
kVK_ANSI_Semicolon = 0x29,
|
||||
kVK_ANSI_Backslash = 0x2A,
|
||||
kVK_ANSI_Comma = 0x2B,
|
||||
kVK_ANSI_Slash = 0x2C,
|
||||
kVK_ANSI_N = 0x2D,
|
||||
kVK_ANSI_M = 0x2E,
|
||||
kVK_ANSI_Period = 0x2F,
|
||||
kVK_ANSI_Grave = 0x32,
|
||||
kVK_ANSI_KeypadDecimal = 0x41,
|
||||
kVK_ANSI_KeypadMultiply = 0x43,
|
||||
kVK_ANSI_KeypadPlus = 0x45,
|
||||
kVK_ANSI_KeypadClear = 0x47,
|
||||
kVK_ANSI_KeypadDivide = 0x4B,
|
||||
kVK_ANSI_KeypadEnter = 0x4C,
|
||||
kVK_ANSI_KeypadMinus = 0x4E,
|
||||
kVK_ANSI_KeypadEquals = 0x51,
|
||||
kVK_ANSI_Keypad0 = 0x52,
|
||||
kVK_ANSI_Keypad1 = 0x53,
|
||||
kVK_ANSI_Keypad2 = 0x54,
|
||||
kVK_ANSI_Keypad3 = 0x55,
|
||||
kVK_ANSI_Keypad4 = 0x56,
|
||||
kVK_ANSI_Keypad5 = 0x57,
|
||||
kVK_ANSI_Keypad6 = 0x58,
|
||||
kVK_ANSI_Keypad7 = 0x59,
|
||||
kVK_ANSI_Keypad8 = 0x5B,
|
||||
kVK_ANSI_Keypad9 = 0x5C
|
||||
};
|
||||
|
||||
/* keycodes for keys that are independent of keyboard layout*/
|
||||
enum {
|
||||
kVK_Return = 0x24,
|
||||
kVK_Tab = 0x30,
|
||||
kVK_Space = 0x31,
|
||||
kVK_Delete = 0x33,
|
||||
kVK_Escape = 0x35,
|
||||
kVK_Command = 0x37,
|
||||
kVK_Shift = 0x38,
|
||||
kVK_CapsLock = 0x39,
|
||||
kVK_Option = 0x3A,
|
||||
kVK_Control = 0x3B,
|
||||
kVK_RightShift = 0x3C,
|
||||
kVK_RightOption = 0x3D,
|
||||
kVK_RightControl = 0x3E,
|
||||
kVK_Function = 0x3F,
|
||||
kVK_F17 = 0x40,
|
||||
kVK_VolumeUp = 0x48,
|
||||
kVK_VolumeDown = 0x49,
|
||||
kVK_Mute = 0x4A,
|
||||
kVK_F18 = 0x4F,
|
||||
kVK_F19 = 0x50,
|
||||
kVK_F20 = 0x5A,
|
||||
kVK_F5 = 0x60,
|
||||
kVK_F6 = 0x61,
|
||||
kVK_F7 = 0x62,
|
||||
kVK_F3 = 0x63,
|
||||
kVK_F8 = 0x64,
|
||||
kVK_F9 = 0x65,
|
||||
kVK_F11 = 0x67,
|
||||
kVK_F13 = 0x69,
|
||||
kVK_F16 = 0x6A,
|
||||
kVK_F14 = 0x6B,
|
||||
kVK_F10 = 0x6D,
|
||||
kVK_F12 = 0x6F,
|
||||
kVK_F15 = 0x71,
|
||||
kVK_Help = 0x72,
|
||||
kVK_Home = 0x73,
|
||||
kVK_PageUp = 0x74,
|
||||
kVK_ForwardDelete = 0x75,
|
||||
kVK_F4 = 0x76,
|
||||
kVK_End = 0x77,
|
||||
kVK_F2 = 0x78,
|
||||
kVK_PageDown = 0x79,
|
||||
kVK_F1 = 0x7A,
|
||||
kVK_LeftArrow = 0x7B,
|
||||
kVK_RightArrow = 0x7C,
|
||||
kVK_DownArrow = 0x7D,
|
||||
kVK_UpArrow = 0x7E
|
||||
};
|
||||
|
||||
static char g_keycodeCharUnshifted[256] = {};
|
||||
static char g_keycodeCharShifted[256] = {};
|
||||
|
||||
//static double g_Time = 0.0f;
|
||||
static bool g_MousePressed[3] = { false, false, false };
|
||||
static float g_mouseWheelX = 0.0f;
|
||||
static float g_mouseWheelY = 0.0f;
|
||||
|
||||
static GLuint g_FontTexture = 0;
|
||||
static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0;
|
||||
static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0;
|
||||
static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0;
|
||||
static size_t g_VboSize = 0;
|
||||
static unsigned int g_VboHandle = 0, g_VaoHandle = 0;
|
||||
static float g_displayScale;
|
||||
|
||||
static int usynergy_sockfd;
|
||||
static bool g_synergyPtrActive = false;
|
||||
static uint16_t g_mousePosX = 0;
|
||||
static uint16_t g_mousePosY = 0;
|
||||
|
||||
static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data);
|
||||
bool ImGui_ImplIOS_CreateDeviceObjects();
|
||||
|
||||
static NSString *g_serverName;
|
||||
|
||||
uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie)
|
||||
{
|
||||
// NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since
|
||||
// uSynergy does not support SSL.
|
||||
|
||||
NSLog( @"Connect Func!");
|
||||
struct addrinfo hints, *res;
|
||||
|
||||
// first, load up address structs with getaddrinfo():
|
||||
memset(&hints, 0, sizeof hints);
|
||||
hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
// get server address
|
||||
getaddrinfo([g_serverName UTF8String], "24800", &hints, &res);
|
||||
|
||||
if (!res)
|
||||
{
|
||||
NSLog( @"Could not find server: %@", g_serverName );
|
||||
return USYNERGY_FALSE;
|
||||
}
|
||||
|
||||
// make a socket:
|
||||
usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
||||
|
||||
// connect it to the address and port we passed in to getaddrinfo():
|
||||
int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen);
|
||||
if (!ret) {
|
||||
NSLog( @"Connect suceeded...");
|
||||
} else {
|
||||
NSLog( @"Connect failed, %d", ret );
|
||||
}
|
||||
|
||||
|
||||
return USYNERGY_TRUE;
|
||||
}
|
||||
|
||||
uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length)
|
||||
{
|
||||
// NSLog( @"Send Func" );
|
||||
send( usynergy_sockfd, buffer, length, 0 );
|
||||
|
||||
return USYNERGY_TRUE;
|
||||
}
|
||||
|
||||
uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength)
|
||||
{
|
||||
*outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 );
|
||||
|
||||
return USYNERGY_TRUE;
|
||||
}
|
||||
|
||||
void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs)
|
||||
{
|
||||
usleep( timeMs * 1000 );
|
||||
}
|
||||
|
||||
uint32_t ImGui_GetTimeFunc()
|
||||
{
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000);
|
||||
}
|
||||
|
||||
void ImGui_TraceFunc(uSynergyCookie cookie, const char *text)
|
||||
{
|
||||
puts(text);
|
||||
}
|
||||
|
||||
void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active)
|
||||
{
|
||||
g_synergyPtrActive = active;
|
||||
// printf( "Synergy: screen activate %s\n", active?"YES":"NO" );
|
||||
}
|
||||
|
||||
void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY,
|
||||
uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle)
|
||||
{
|
||||
// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY );
|
||||
uSynergyContext *ctx = (uSynergyContext*)cookie;
|
||||
g_mousePosX = x;
|
||||
g_mousePosY = y;
|
||||
g_mouseWheelX = wheelX;
|
||||
g_mouseWheelY = wheelY;
|
||||
g_MousePressed[0] = buttonLeft;
|
||||
g_MousePressed[1] = buttonMiddle;
|
||||
g_MousePressed[2] = buttonRight;
|
||||
|
||||
ctx->m_mouseWheelX = 0;
|
||||
ctx->m_mouseWheelY = 0;
|
||||
}
|
||||
|
||||
void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key,
|
||||
uint16_t modifiers, uSynergyBool down, uSynergyBool repeat)
|
||||
{
|
||||
int scanCode = key-1;
|
||||
// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.KeysDown[key] = down;
|
||||
io.KeyShift = modifiers & USYNERGY_MODIFIER_SHIFT;
|
||||
io.KeyCtrl = modifiers & USYNERGY_MODIFIER_CTRL;
|
||||
io.KeyAlt = modifiers & USYNERGY_MODIFIER_ALT;
|
||||
|
||||
|
||||
// Add this as keyboard input
|
||||
if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL))
|
||||
{
|
||||
// If this key maps to a character input, apply it
|
||||
int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode];
|
||||
io.AddInputCharacter((unsigned short)charForKeycode);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY)
|
||||
{
|
||||
printf("Synergy: joystick callback TODO\n");
|
||||
}
|
||||
|
||||
void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size)
|
||||
{
|
||||
printf("Synergy: clipboard callback TODO\n" );
|
||||
}
|
||||
|
||||
|
||||
@interface ImGuiHelper ()
|
||||
{
|
||||
BOOL _mouseDown;
|
||||
BOOL _mouseTapped;
|
||||
CGPoint _touchPos;
|
||||
|
||||
uSynergyContext _synergyCtx;
|
||||
dispatch_queue_t _synergyQueue;
|
||||
}
|
||||
@property (nonatomic, weak) UIView *view;
|
||||
@property (nonatomic, strong) NSString *serverName;
|
||||
|
||||
@end
|
||||
|
||||
@implementation ImGuiHelper
|
||||
|
||||
- (id) initWithView: (UIView *)view
|
||||
{
|
||||
self = [super init];
|
||||
if (self)
|
||||
{
|
||||
self.view = view;
|
||||
|
||||
[self setupImGuiHooks];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setupKeymaps
|
||||
{
|
||||
// The keyboard mapping is a big headache. I tried for a while to find a better way to do this,
|
||||
// but this was the best I could come up with. There are some device independent API's available
|
||||
// to convert scan codes to unicode characters, but these are only available on mac and not
|
||||
// on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do
|
||||
// this or any way to get the character codes out of usynergy.
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_A ]='a';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_S ]='s';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_D ]='d';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_F ]='f';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_H ]='h';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_G ]='g';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_X ]='x';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_C ]='c';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_V ]='v';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_B ]='b';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_W ]='w';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_E ]='e';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_R ]='r';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_T ]='t';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='=';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_O ]='o';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_U ]='u';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='[';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_I ]='i';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_P ]='p';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_L ]='l';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_J ]='j';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\'';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_K ]='k';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=',';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_N ]='n';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_M ]='m';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='=';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8';
|
||||
g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9';
|
||||
g_keycodeCharUnshifted[ kVK_Space ]=' ';
|
||||
|
||||
g_keycodeCharShifted[ kVK_ANSI_A ]='A';
|
||||
g_keycodeCharShifted[ kVK_ANSI_S ]='S';
|
||||
g_keycodeCharShifted[ kVK_ANSI_D ]='D';
|
||||
g_keycodeCharShifted[ kVK_ANSI_F ]='F';
|
||||
g_keycodeCharShifted[ kVK_ANSI_H ]='H';
|
||||
g_keycodeCharShifted[ kVK_ANSI_G ]='G';
|
||||
g_keycodeCharShifted[ kVK_ANSI_Z ]='Z';
|
||||
g_keycodeCharShifted[ kVK_ANSI_X ]='X';
|
||||
g_keycodeCharShifted[ kVK_ANSI_C ]='C';
|
||||
g_keycodeCharShifted[ kVK_ANSI_V ]='V';
|
||||
g_keycodeCharShifted[ kVK_ANSI_B ]='B';
|
||||
g_keycodeCharShifted[ kVK_ANSI_Q ]='Q';
|
||||
g_keycodeCharShifted[ kVK_ANSI_W ]='W';
|
||||
g_keycodeCharShifted[ kVK_ANSI_E ]='E';
|
||||
g_keycodeCharShifted[ kVK_ANSI_R ]='R';
|
||||
g_keycodeCharShifted[ kVK_ANSI_Y ]='Y';
|
||||
g_keycodeCharShifted[ kVK_ANSI_T ]='T';
|
||||
g_keycodeCharShifted[ kVK_ANSI_1 ]='!';
|
||||
g_keycodeCharShifted[ kVK_ANSI_2 ]='@';
|
||||
g_keycodeCharShifted[ kVK_ANSI_3 ]='#';
|
||||
g_keycodeCharShifted[ kVK_ANSI_4 ]='$';
|
||||
g_keycodeCharShifted[ kVK_ANSI_6 ]='^';
|
||||
g_keycodeCharShifted[ kVK_ANSI_5 ]='%';
|
||||
g_keycodeCharShifted[ kVK_ANSI_Equal ]='+';
|
||||
g_keycodeCharShifted[ kVK_ANSI_9 ]='(';
|
||||
g_keycodeCharShifted[ kVK_ANSI_7 ]='&';
|
||||
g_keycodeCharShifted[ kVK_ANSI_Minus ]='_';
|
||||
g_keycodeCharShifted[ kVK_ANSI_8 ]='*';
|
||||
g_keycodeCharShifted[ kVK_ANSI_0 ]=')';
|
||||
g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}';
|
||||
g_keycodeCharShifted[ kVK_ANSI_O ]='O';
|
||||
g_keycodeCharShifted[ kVK_ANSI_U ]='U';
|
||||
g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{';
|
||||
g_keycodeCharShifted[ kVK_ANSI_I ]='I';
|
||||
g_keycodeCharShifted[ kVK_ANSI_P ]='P';
|
||||
g_keycodeCharShifted[ kVK_ANSI_L ]='L';
|
||||
g_keycodeCharShifted[ kVK_ANSI_J ]='J';
|
||||
g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"';
|
||||
g_keycodeCharShifted[ kVK_ANSI_K ]='K';
|
||||
g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':';
|
||||
g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|';
|
||||
g_keycodeCharShifted[ kVK_ANSI_Comma ]='<';
|
||||
g_keycodeCharShifted[ kVK_ANSI_Slash ]='?';
|
||||
g_keycodeCharShifted[ kVK_ANSI_N ]='N';
|
||||
g_keycodeCharShifted[ kVK_ANSI_M ]='M';
|
||||
g_keycodeCharShifted[ kVK_ANSI_Period ]='>';
|
||||
g_keycodeCharShifted[ kVK_ANSI_Grave ]='~';
|
||||
g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.';
|
||||
g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*';
|
||||
g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+';
|
||||
g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/';
|
||||
g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n';
|
||||
g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-';
|
||||
g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='=';
|
||||
g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0';
|
||||
g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1';
|
||||
g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2';
|
||||
g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3';
|
||||
g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4';
|
||||
g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5';
|
||||
g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6';
|
||||
g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7';
|
||||
g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8';
|
||||
g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9';
|
||||
g_keycodeCharShifted[ kVK_Space ]=' ';
|
||||
}
|
||||
|
||||
- (void)setupImGuiHooks
|
||||
{
|
||||
ImGuiIO &io = ImGui::GetIO();
|
||||
|
||||
[self setupKeymaps];
|
||||
|
||||
// Account for retina display for glScissor
|
||||
g_displayScale = [[UIScreen mainScreen] scale];
|
||||
|
||||
ImGuiStyle &style = ImGui::GetStyle();
|
||||
style.TouchExtraPadding = ImVec2( 4.0, 4.0 );
|
||||
|
||||
io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists;
|
||||
|
||||
UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ];
|
||||
[self.view addGestureRecognizer:panRecognizer];
|
||||
|
||||
UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)];
|
||||
[self.view addGestureRecognizer:tapRecoginzer];
|
||||
|
||||
// Fill out the Synergy key map
|
||||
// (for some reason synergy scan codes are off by 1)
|
||||
io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1;
|
||||
io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1;
|
||||
io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1;
|
||||
io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1;
|
||||
io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1;
|
||||
io.KeyMap[ImGuiKey_Home] = kVK_Home+1;
|
||||
io.KeyMap[ImGuiKey_End] = kVK_End+1;
|
||||
io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1;
|
||||
io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1;
|
||||
io.KeyMap[ImGuiKey_Enter] = kVK_Return+1;
|
||||
io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1;
|
||||
io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1;
|
||||
io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1;
|
||||
io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1;
|
||||
io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1;
|
||||
io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1;
|
||||
io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1;
|
||||
}
|
||||
|
||||
- (void)connectServer: (NSString*)serverName
|
||||
{
|
||||
self.serverName = serverName;
|
||||
g_serverName = serverName;
|
||||
|
||||
// Init synergy
|
||||
NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey];
|
||||
|
||||
uSynergyInit( &_synergyCtx );
|
||||
_synergyCtx.m_clientName = strdup( [bundleName UTF8String] );
|
||||
_synergyCtx.m_clientWidth = self.view.bounds.size.width;
|
||||
_synergyCtx.m_clientHeight = self.view.bounds.size.height;
|
||||
|
||||
_synergyCtx.m_connectFunc = ImGui_ConnectFunc;
|
||||
_synergyCtx.m_sendFunc = ImGui_SendFunc;
|
||||
_synergyCtx.m_receiveFunc = ImGui_RecvFunc;
|
||||
_synergyCtx.m_sleepFunc = ImGui_SleepFunc;
|
||||
_synergyCtx.m_traceFunc = ImGui_TraceFunc;
|
||||
_synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc;
|
||||
|
||||
_synergyCtx.m_traceFunc = ImGui_TraceFunc;
|
||||
_synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback;
|
||||
_synergyCtx.m_mouseCallback = ImGui_MouseCallback;
|
||||
_synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback;
|
||||
|
||||
_synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx;
|
||||
|
||||
// Create a background thread for synergy
|
||||
_synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL );
|
||||
dispatch_async( _synergyQueue, ^{
|
||||
while (1) {
|
||||
uSynergyUpdate( &_synergyCtx );
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer
|
||||
{
|
||||
|
||||
if ((recognizer.state == UIGestureRecognizerStateBegan) ||
|
||||
(recognizer.state == UIGestureRecognizerStateChanged))
|
||||
{
|
||||
_mouseDown = YES;
|
||||
_touchPos = [recognizer locationInView:self.view];
|
||||
}
|
||||
else
|
||||
{
|
||||
_mouseDown = NO;
|
||||
_touchPos = CGPointMake( -1, -1 );
|
||||
}
|
||||
}
|
||||
|
||||
- (void)viewDidTap: (UITapGestureRecognizer*)recognizer
|
||||
{
|
||||
_touchPos = [recognizer locationInView:self.view];
|
||||
_mouseTapped = YES;
|
||||
}
|
||||
|
||||
- (void)render
|
||||
{
|
||||
ImGui::Render();
|
||||
}
|
||||
|
||||
- (void)newFrame
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiStyle &style = ImGui::GetStyle();
|
||||
|
||||
if (!g_FontTexture)
|
||||
{
|
||||
ImGui_ImplIOS_CreateDeviceObjects();
|
||||
}
|
||||
|
||||
io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height );
|
||||
|
||||
io.MouseDrawCursor = g_synergyPtrActive;
|
||||
if (g_synergyPtrActive)
|
||||
{
|
||||
style.TouchExtraPadding = ImVec2( 0.0, 0.0 );
|
||||
io.MousePos = ImVec2( g_mousePosX, g_mousePosY );
|
||||
for (int i=0; i < 3; i++)
|
||||
{
|
||||
io.MouseDown[i] = g_MousePressed[i];
|
||||
}
|
||||
|
||||
// This is an arbitrary scaling factor that works for me. Not sure what units these
|
||||
// mousewheel values from synergy are supposed to be in
|
||||
io.MouseWheel = g_mouseWheelY / 500.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Synergy not active, use touch events
|
||||
style.TouchExtraPadding = ImVec2( 4.0, 4.0 );
|
||||
io.MousePos = ImVec2(_touchPos.x, _touchPos.y );
|
||||
if ((_mouseDown) || (_mouseTapped))
|
||||
{
|
||||
io.MouseDown[0] = true;
|
||||
_mouseTapped = NO;
|
||||
}
|
||||
else
|
||||
{
|
||||
io.MouseDown[0] = false;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::NewFrame();
|
||||
}
|
||||
@end
|
||||
|
||||
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure)
|
||||
// If text or lines are blurry when integrating ImGui in your engine:
|
||||
// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
|
||||
// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES
|
||||
static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data)
|
||||
{
|
||||
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled
|
||||
GLint last_program, last_texture;
|
||||
glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
// Setup orthographic projection matrix
|
||||
const float width = ImGui::GetIO().DisplaySize.x;
|
||||
const float height = ImGui::GetIO().DisplaySize.y;
|
||||
const float ortho_projection[4][4] =
|
||||
{
|
||||
{ 2.0f/width, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 2.0f/-height, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, -1.0f, 0.0f },
|
||||
{ -1.0f, 1.0f, 0.0f, 1.0f },
|
||||
};
|
||||
glUseProgram(g_ShaderHandle);
|
||||
glUniform1i(g_AttribLocationTex, 0);
|
||||
glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
|
||||
glBindVertexArray(g_VaoHandle);
|
||||
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front();
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
|
||||
int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert);
|
||||
if (g_VboSize < needed_vtx_size)
|
||||
{
|
||||
// Grow our buffer if needed
|
||||
g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert);
|
||||
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW);
|
||||
}
|
||||
|
||||
unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
|
||||
if (!vtx_data)
|
||||
continue;
|
||||
memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert));
|
||||
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||
|
||||
for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++)
|
||||
{
|
||||
if (pcmd->UserCallback)
|
||||
{
|
||||
pcmd->UserCallback(cmd_list, pcmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
|
||||
glScissor((int)(pcmd->ClipRect.x * g_displayScale),
|
||||
(int)((height - pcmd->ClipRect.w) * g_displayScale),
|
||||
(int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale),
|
||||
(int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale));
|
||||
glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer );
|
||||
}
|
||||
idx_buffer += pcmd->ElemCount;
|
||||
}
|
||||
}
|
||||
|
||||
// Restore modified state
|
||||
glBindVertexArray(0);
|
||||
glBindBuffer( GL_ARRAY_BUFFER, 0);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glUseProgram(last_program);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||
}
|
||||
|
||||
void ImGui_ImplIOS_CreateFontsTexture()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
unsigned char* pixels;
|
||||
int width, height;
|
||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader.
|
||||
|
||||
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);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
// Store our identifier
|
||||
io.Fonts->TexID = (void *)(intptr_t)g_FontTexture;
|
||||
|
||||
// Cleanup (don't clear the input data if you want to append new fonts later)
|
||||
io.Fonts->ClearInputData();
|
||||
io.Fonts->ClearTexData();
|
||||
}
|
||||
|
||||
bool ImGui_ImplIOS_CreateDeviceObjects()
|
||||
{
|
||||
const GLchar *vertex_shader =
|
||||
"uniform mat4 ProjMtx;\n"
|
||||
"attribute highp vec2 Position;\n"
|
||||
"attribute highp vec2 UV;\n"
|
||||
"attribute highp vec4 Color;\n"
|
||||
"varying vec2 Frag_UV;\n"
|
||||
"varying vec4 Frag_Color;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" Frag_UV = UV;\n"
|
||||
" Frag_Color = Color;\n"
|
||||
" gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
|
||||
"}\n";
|
||||
|
||||
const GLchar* fragment_shader =
|
||||
"uniform sampler2D Texture;\n"
|
||||
"varying highp vec2 Frag_UV;\n"
|
||||
"varying highp vec4 Frag_Color;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n"
|
||||
"}\n";
|
||||
|
||||
g_ShaderHandle = glCreateProgram();
|
||||
g_VertHandle = glCreateShader(GL_VERTEX_SHADER);
|
||||
g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(g_VertHandle, 1, &vertex_shader, 0);
|
||||
glShaderSource(g_FragHandle, 1, &fragment_shader, 0);
|
||||
glCompileShader(g_VertHandle);
|
||||
|
||||
#if defined(DEBUG)
|
||||
GLint logLength;
|
||||
glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength);
|
||||
if (logLength > 0) {
|
||||
GLchar *log = (GLchar *)malloc(logLength);
|
||||
glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log);
|
||||
NSLog(@"VERTEX Shader compile log:\n%s", log);
|
||||
free(log);
|
||||
}
|
||||
#endif
|
||||
|
||||
glCompileShader(g_FragHandle);
|
||||
|
||||
#if defined(DEBUG)
|
||||
glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength);
|
||||
if (logLength > 0) {
|
||||
GLchar *log = (GLchar *)malloc(logLength);
|
||||
glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log);
|
||||
NSLog(@"FRAGMENT Shader compile log:\n%s", log);
|
||||
free(log);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
glAttachShader(g_ShaderHandle, g_VertHandle);
|
||||
glAttachShader(g_ShaderHandle, g_FragHandle);
|
||||
glLinkProgram(g_ShaderHandle);
|
||||
|
||||
g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture");
|
||||
g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx");
|
||||
g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position");
|
||||
g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV");
|
||||
g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color");
|
||||
|
||||
glGenBuffers(1, &g_VboHandle);
|
||||
|
||||
glGenVertexArrays(1, &g_VaoHandle);
|
||||
glBindVertexArray(g_VaoHandle);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
|
||||
glEnableVertexAttribArray(g_AttribLocationPosition);
|
||||
glEnableVertexAttribArray(g_AttribLocationUV);
|
||||
glEnableVertexAttribArray(g_AttribLocationColor);
|
||||
|
||||
#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT))
|
||||
glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos));
|
||||
glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv));
|
||||
glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col));
|
||||
#undef OFFSETOF
|
||||
glBindVertexArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
ImGui_ImplIOS_CreateFontsTexture();
|
||||
|
||||
return true;
|
||||
}
|
13
examples/ios_example/imguiex/main.m
Normal file
@ -0,0 +1,13 @@
|
||||
//
|
||||
// main.m
|
||||
// imguiex
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "AppDelegate.h"
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
@autoreleasepool {
|
||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
|
||||
}
|
||||
}
|
@ -1,5 +1,10 @@
|
||||
#include <GL/gl3w.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (disable: 4055) // warning C4055: 'type cast' : from data pointer 'void *' to function pointer
|
||||
#pragma warning (disable: 4152) // warning C4152: nonstandard extension, function/data pointer conversion in expression
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#include <windows.h>
|
356
examples/libs/glfw/include/GLFW/glfw3native.h
Normal file
@ -0,0 +1,356 @@
|
||||
/*************************************************************************
|
||||
* GLFW 3.1 - www.glfw.org
|
||||
* A library for OpenGL, window and input
|
||||
*------------------------------------------------------------------------
|
||||
* Copyright (c) 2002-2006 Marcus Geelnard
|
||||
* Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would
|
||||
* be appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef _glfw3_native_h_
|
||||
#define _glfw3_native_h_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* Doxygen documentation
|
||||
*************************************************************************/
|
||||
|
||||
/*! @defgroup native Native access
|
||||
*
|
||||
* **By using the native access functions you assert that you know what you're
|
||||
* doing and how to fix problems caused by using them. If you don't, you
|
||||
* shouldn't be using them.**
|
||||
*
|
||||
* Before the inclusion of @ref glfw3native.h, you must define exactly one
|
||||
* window system API macro and exactly one context creation API macro. Failure
|
||||
* to do this will cause a compile-time error.
|
||||
*
|
||||
* The available window API macros are:
|
||||
* * `GLFW_EXPOSE_NATIVE_WIN32`
|
||||
* * `GLFW_EXPOSE_NATIVE_COCOA`
|
||||
* * `GLFW_EXPOSE_NATIVE_X11`
|
||||
*
|
||||
* The available context API macros are:
|
||||
* * `GLFW_EXPOSE_NATIVE_WGL`
|
||||
* * `GLFW_EXPOSE_NATIVE_NSGL`
|
||||
* * `GLFW_EXPOSE_NATIVE_GLX`
|
||||
* * `GLFW_EXPOSE_NATIVE_EGL`
|
||||
*
|
||||
* These macros select which of the native access functions that are declared
|
||||
* and which platform-specific headers to include. It is then up your (by
|
||||
* definition platform-specific) code to handle which of these should be
|
||||
* defined.
|
||||
*/
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* System headers and types
|
||||
*************************************************************************/
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_WIN32)
|
||||
// This is a workaround for the fact that glfw3.h needs to export APIENTRY (for
|
||||
// example to allow applications to correctly declare a GL_ARB_debug_output
|
||||
// callback) but windows.h assumes no one will define APIENTRY before it does
|
||||
#undef APIENTRY
|
||||
#include <windows.h>
|
||||
#elif defined(GLFW_EXPOSE_NATIVE_COCOA)
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#if defined(__OBJC__)
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#else
|
||||
typedef void* id;
|
||||
#endif
|
||||
#elif defined(GLFW_EXPOSE_NATIVE_X11)
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
#else
|
||||
#error "No window API selected"
|
||||
#endif
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_WGL)
|
||||
/* WGL is declared by windows.h */
|
||||
#elif defined(GLFW_EXPOSE_NATIVE_NSGL)
|
||||
/* NSGL is declared by Cocoa.h */
|
||||
#elif defined(GLFW_EXPOSE_NATIVE_GLX)
|
||||
#include <GL/glx.h>
|
||||
#elif defined(GLFW_EXPOSE_NATIVE_EGL)
|
||||
#include <EGL/egl.h>
|
||||
#else
|
||||
#error "No context API selected"
|
||||
#endif
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* Functions
|
||||
*************************************************************************/
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_WIN32)
|
||||
/*! @brief Returns the adapter device name of the specified monitor.
|
||||
*
|
||||
* @return The UTF-8 encoded adapter device name (for example `\\.\DISPLAY1`)
|
||||
* of the specified monitor, or `NULL` if an [error](@ref error_handling)
|
||||
* occurred.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* This function may be called from any thread. Access is not synchronized.
|
||||
*
|
||||
* @par History
|
||||
* Added in GLFW 3.1.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI const char* glfwGetWin32Adapter(GLFWmonitor* monitor);
|
||||
|
||||
/*! @brief Returns the display device name of the specified monitor.
|
||||
*
|
||||
* @return The UTF-8 encoded display device name (for example
|
||||
* `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* This function may be called from any thread. Access is not synchronized.
|
||||
*
|
||||
* @par History
|
||||
* Added in GLFW 3.1.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* monitor);
|
||||
|
||||
/*! @brief Returns the `HWND` of the specified window.
|
||||
*
|
||||
* @return The `HWND` of the specified window, or `NULL` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* This function may be called from any thread. Access is not synchronized.
|
||||
*
|
||||
* @par History
|
||||
* Added in GLFW 3.0.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI HWND glfwGetWin32Window(GLFWwindow* window);
|
||||
#endif
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_WGL)
|
||||
/*! @brief Returns the `HGLRC` of the specified window.
|
||||
*
|
||||
* @return The `HGLRC` of the specified window, or `NULL` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* This function may be called from any thread. Access is not synchronized.
|
||||
*
|
||||
* @par History
|
||||
* Added in GLFW 3.0.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* window);
|
||||
#endif
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_COCOA)
|
||||
/*! @brief Returns the `CGDirectDisplayID` of the specified monitor.
|
||||
*
|
||||
* @return The `CGDirectDisplayID` of the specified monitor, or
|
||||
* `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* This function may be called from any thread. Access is not synchronized.
|
||||
*
|
||||
* @par History
|
||||
* Added in GLFW 3.1.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* monitor);
|
||||
|
||||
/*! @brief Returns the `NSWindow` of the specified window.
|
||||
*
|
||||
* @return The `NSWindow` of the specified window, or `nil` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* This function may be called from any thread. Access is not synchronized.
|
||||
*
|
||||
* @par History
|
||||
* Added in GLFW 3.0.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI id glfwGetCocoaWindow(GLFWwindow* window);
|
||||
#endif
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_NSGL)
|
||||
/*! @brief Returns the `NSOpenGLContext` of the specified window.
|
||||
*
|
||||
* @return The `NSOpenGLContext` of the specified window, or `nil` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* This function may be called from any thread. Access is not synchronized.
|
||||
*
|
||||
* @par History
|
||||
* Added in GLFW 3.0.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI id glfwGetNSGLContext(GLFWwindow* window);
|
||||
#endif
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_X11)
|
||||
/*! @brief Returns the `Display` used by GLFW.
|
||||
*
|
||||
* @return The `Display` used by GLFW, or `NULL` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* This function may be called from any thread. Access is not synchronized.
|
||||
*
|
||||
* @par History
|
||||
* Added in GLFW 3.0.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI Display* glfwGetX11Display(void);
|
||||
|
||||
/*! @brief Returns the `RRCrtc` of the specified monitor.
|
||||
*
|
||||
* @return The `RRCrtc` of the specified monitor, or `None` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* This function may be called from any thread. Access is not synchronized.
|
||||
*
|
||||
* @par History
|
||||
* Added in GLFW 3.1.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI RRCrtc glfwGetX11Adapter(GLFWmonitor* monitor);
|
||||
|
||||
/*! @brief Returns the `RROutput` of the specified monitor.
|
||||
*
|
||||
* @return The `RROutput` of the specified monitor, or `None` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* This function may be called from any thread. Access is not synchronized.
|
||||
*
|
||||
* @par History
|
||||
* Added in GLFW 3.1.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* monitor);
|
||||
|
||||
/*! @brief Returns the `Window` of the specified window.
|
||||
*
|
||||
* @return The `Window` of the specified window, or `None` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* This function may be called from any thread. Access is not synchronized.
|
||||
*
|
||||
* @par History
|
||||
* Added in GLFW 3.0.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI Window glfwGetX11Window(GLFWwindow* window);
|
||||
#endif
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_GLX)
|
||||
/*! @brief Returns the `GLXContext` of the specified window.
|
||||
*
|
||||
* @return The `GLXContext` of the specified window, or `NULL` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* This function may be called from any thread. Access is not synchronized.
|
||||
*
|
||||
* @par History
|
||||
* Added in GLFW 3.0.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window);
|
||||
#endif
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_EGL)
|
||||
/*! @brief Returns the `EGLDisplay` used by GLFW.
|
||||
*
|
||||
* @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* This function may be called from any thread. Access is not synchronized.
|
||||
*
|
||||
* @par History
|
||||
* Added in GLFW 3.0.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI EGLDisplay glfwGetEGLDisplay(void);
|
||||
|
||||
/*! @brief Returns the `EGLContext` of the specified window.
|
||||
*
|
||||
* @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* This function may be called from any thread. Access is not synchronized.
|
||||
*
|
||||
* @par History
|
||||
* Added in GLFW 3.0.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* window);
|
||||
|
||||
/*! @brief Returns the `EGLSurface` of the specified window.
|
||||
*
|
||||
* @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @par Thread Safety
|
||||
* This function may be called from any thread. Access is not synchronized.
|
||||
*
|
||||
* @par History
|
||||
* Added in GLFW 3.0.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* window);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _glfw3_native_h_ */
|
||||
|
BIN
examples/libs/glfw/lib-vc2010-32/glfw3.lib
Normal file
BIN
examples/libs/glfw/lib-vc2010-64/glfw3.lib
Normal file
636
examples/libs/usynergy/uSynergy.c
Normal file
@ -0,0 +1,636 @@
|
||||
/*
|
||||
uSynergy client -- Implementation for the embedded Synergy client library
|
||||
version 1.0.0, July 7th, 2012
|
||||
|
||||
Copyright (c) 2012 Alex Evans
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*/
|
||||
#include "uSynergy.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// Internal helpers
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Read 16 bit integer in network byte order and convert to native byte order
|
||||
**/
|
||||
static int16_t sNetToNative16(const unsigned char *value)
|
||||
{
|
||||
#ifdef USYNERGY_LITTLE_ENDIAN
|
||||
return value[1] | (value[0] << 8);
|
||||
#else
|
||||
return value[0] | (value[1] << 8);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Read 32 bit integer in network byte order and convert to native byte order
|
||||
**/
|
||||
static int32_t sNetToNative32(const unsigned char *value)
|
||||
{
|
||||
#ifdef USYNERGY_LITTLE_ENDIAN
|
||||
return value[3] | (value[2] << 8) | (value[1] << 16) | (value[0] << 24);
|
||||
#else
|
||||
return value[0] | (value[1] << 8) | (value[2] << 16) | (value[3] << 24);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Trace text to client
|
||||
**/
|
||||
static void sTrace(uSynergyContext *context, const char* text)
|
||||
{
|
||||
// Don't trace if we don't have a trace function
|
||||
if (context->m_traceFunc != 0L)
|
||||
context->m_traceFunc(context->m_cookie, text);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Add string to reply packet
|
||||
**/
|
||||
static void sAddString(uSynergyContext *context, const char *string)
|
||||
{
|
||||
size_t len = strlen(string);
|
||||
memcpy(context->m_replyCur, string, len);
|
||||
context->m_replyCur += len;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Add uint8 to reply packet
|
||||
**/
|
||||
static void sAddUInt8(uSynergyContext *context, uint8_t value)
|
||||
{
|
||||
*context->m_replyCur++ = value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Add uint16 to reply packet
|
||||
**/
|
||||
static void sAddUInt16(uSynergyContext *context, uint16_t value)
|
||||
{
|
||||
uint8_t *reply = context->m_replyCur;
|
||||
*reply++ = (uint8_t)(value >> 8);
|
||||
*reply++ = (uint8_t)value;
|
||||
context->m_replyCur = reply;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Add uint32 to reply packet
|
||||
**/
|
||||
static void sAddUInt32(uSynergyContext *context, uint32_t value)
|
||||
{
|
||||
uint8_t *reply = context->m_replyCur;
|
||||
*reply++ = (uint8_t)(value >> 24);
|
||||
*reply++ = (uint8_t)(value >> 16);
|
||||
*reply++ = (uint8_t)(value >> 8);
|
||||
*reply++ = (uint8_t)value;
|
||||
context->m_replyCur = reply;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Send reply packet
|
||||
**/
|
||||
static uSynergyBool sSendReply(uSynergyContext *context)
|
||||
{
|
||||
// Set header size
|
||||
uint8_t *reply_buf = context->m_replyBuffer;
|
||||
uint32_t reply_len = (uint32_t)(context->m_replyCur - reply_buf); /* Total size of reply */
|
||||
uint32_t body_len = reply_len - 4; /* Size of body */
|
||||
uSynergyBool ret;
|
||||
reply_buf[0] = (uint8_t)(body_len >> 24);
|
||||
reply_buf[1] = (uint8_t)(body_len >> 16);
|
||||
reply_buf[2] = (uint8_t)(body_len >> 8);
|
||||
reply_buf[3] = (uint8_t)body_len;
|
||||
|
||||
// Send reply
|
||||
ret = context->m_sendFunc(context->m_cookie, context->m_replyBuffer, reply_len);
|
||||
|
||||
// Reset reply buffer write pointer
|
||||
context->m_replyCur = context->m_replyBuffer+4;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Call mouse callback after a mouse event
|
||||
**/
|
||||
static void sSendMouseCallback(uSynergyContext *context)
|
||||
{
|
||||
// Skip if no callback is installed
|
||||
if (context->m_mouseCallback == 0L)
|
||||
return;
|
||||
|
||||
// Send callback
|
||||
context->m_mouseCallback(context->m_cookie, context->m_mouseX, context->m_mouseY, context->m_mouseWheelX,
|
||||
context->m_mouseWheelY, context->m_mouseButtonLeft, context->m_mouseButtonRight, context->m_mouseButtonMiddle);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Send keyboard callback when a key has been pressed or released
|
||||
**/
|
||||
static void sSendKeyboardCallback(uSynergyContext *context, uint16_t key, uint16_t modifiers, uSynergyBool down, uSynergyBool repeat)
|
||||
{
|
||||
// Skip if no callback is installed
|
||||
if (context->m_keyboardCallback == 0L)
|
||||
return;
|
||||
|
||||
// Send callback
|
||||
context->m_keyboardCallback(context->m_cookie, key, modifiers, down, repeat);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Send joystick callback
|
||||
**/
|
||||
static void sSendJoystickCallback(uSynergyContext *context, uint8_t joyNum)
|
||||
{
|
||||
int8_t *sticks;
|
||||
|
||||
// Skip if no callback is installed
|
||||
if (context->m_joystickCallback == 0L)
|
||||
return;
|
||||
|
||||
// Send callback
|
||||
sticks = context->m_joystickSticks[joyNum];
|
||||
context->m_joystickCallback(context->m_cookie, joyNum, context->m_joystickButtons[joyNum], sticks[0], sticks[1], sticks[2], sticks[3]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Parse a single client message, update state, send callbacks and send replies
|
||||
**/
|
||||
#define USYNERGY_IS_PACKET(pkt_id) memcmp(message+4, pkt_id, 4)==0
|
||||
static void sProcessMessage(uSynergyContext *context, const uint8_t *message)
|
||||
{
|
||||
// We have a packet!
|
||||
if (memcmp(message+4, "Synergy", 7)==0)
|
||||
{
|
||||
// Welcome message
|
||||
// kMsgHello = "Synergy%2i%2i"
|
||||
// kMsgHelloBack = "Synergy%2i%2i%s"
|
||||
sAddString(context, "Synergy");
|
||||
sAddUInt16(context, USYNERGY_PROTOCOL_MAJOR);
|
||||
sAddUInt16(context, USYNERGY_PROTOCOL_MINOR);
|
||||
sAddUInt32(context, (uint32_t)strlen(context->m_clientName));
|
||||
sAddString(context, context->m_clientName);
|
||||
if (!sSendReply(context))
|
||||
{
|
||||
// Send reply failed, let's try to reconnect
|
||||
sTrace(context, "SendReply failed, trying to reconnect in a second");
|
||||
context->m_connected = USYNERGY_FALSE;
|
||||
context->m_sleepFunc(context->m_cookie, 1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Let's assume we're connected
|
||||
char buffer[256+1];
|
||||
sprintf(buffer, "Connected as client \"%s\"", context->m_clientName);
|
||||
sTrace(context, buffer);
|
||||
context->m_hasReceivedHello = USYNERGY_TRUE;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (USYNERGY_IS_PACKET("QINF"))
|
||||
{
|
||||
// Screen info. Reply with DINF
|
||||
// kMsgQInfo = "QINF"
|
||||
// kMsgDInfo = "DINF%2i%2i%2i%2i%2i%2i%2i"
|
||||
uint16_t x = 0, y = 0, warp = 0;
|
||||
sAddString(context, "DINF");
|
||||
sAddUInt16(context, x);
|
||||
sAddUInt16(context, y);
|
||||
sAddUInt16(context, context->m_clientWidth);
|
||||
sAddUInt16(context, context->m_clientHeight);
|
||||
sAddUInt16(context, warp);
|
||||
sAddUInt16(context, 0); // mx?
|
||||
sAddUInt16(context, 0); // my?
|
||||
sSendReply(context);
|
||||
return;
|
||||
}
|
||||
else if (USYNERGY_IS_PACKET("CIAK"))
|
||||
{
|
||||
// Do nothing?
|
||||
// kMsgCInfoAck = "CIAK"
|
||||
return;
|
||||
}
|
||||
else if (USYNERGY_IS_PACKET("CROP"))
|
||||
{
|
||||
// Do nothing?
|
||||
// kMsgCResetOptions = "CROP"
|
||||
return;
|
||||
}
|
||||
else if (USYNERGY_IS_PACKET("CINN"))
|
||||
{
|
||||
// Screen enter. Reply with CNOP
|
||||
// kMsgCEnter = "CINN%2i%2i%4i%2i"
|
||||
|
||||
// Obtain the Synergy sequence number
|
||||
context->m_sequenceNumber = sNetToNative32(message + 12);
|
||||
context->m_isCaptured = USYNERGY_TRUE;
|
||||
|
||||
// Call callback
|
||||
if (context->m_screenActiveCallback != 0L)
|
||||
context->m_screenActiveCallback(context->m_cookie, USYNERGY_TRUE);
|
||||
}
|
||||
else if (USYNERGY_IS_PACKET("COUT"))
|
||||
{
|
||||
// Screen leave
|
||||
// kMsgCLeave = "COUT"
|
||||
context->m_isCaptured = USYNERGY_FALSE;
|
||||
|
||||
// Call callback
|
||||
if (context->m_screenActiveCallback != 0L)
|
||||
context->m_screenActiveCallback(context->m_cookie, USYNERGY_FALSE);
|
||||
}
|
||||
else if (USYNERGY_IS_PACKET("DMDN"))
|
||||
{
|
||||
// Mouse down
|
||||
// kMsgDMouseDown = "DMDN%1i"
|
||||
char btn = message[8]-1;
|
||||
if (btn==2)
|
||||
context->m_mouseButtonRight = USYNERGY_TRUE;
|
||||
else if (btn==1)
|
||||
context->m_mouseButtonMiddle = USYNERGY_TRUE;
|
||||
else
|
||||
context->m_mouseButtonLeft = USYNERGY_TRUE;
|
||||
sSendMouseCallback(context);
|
||||
}
|
||||
else if (USYNERGY_IS_PACKET("DMUP"))
|
||||
{
|
||||
// Mouse up
|
||||
// kMsgDMouseUp = "DMUP%1i"
|
||||
char btn = message[8]-1;
|
||||
if (btn==2)
|
||||
context->m_mouseButtonRight = USYNERGY_FALSE;
|
||||
else if (btn==1)
|
||||
context->m_mouseButtonMiddle = USYNERGY_FALSE;
|
||||
else
|
||||
context->m_mouseButtonLeft = USYNERGY_FALSE;
|
||||
sSendMouseCallback(context);
|
||||
}
|
||||
else if (USYNERGY_IS_PACKET("DMMV"))
|
||||
{
|
||||
// Mouse move. Reply with CNOP
|
||||
// kMsgDMouseMove = "DMMV%2i%2i"
|
||||
context->m_mouseX = sNetToNative16(message+8);
|
||||
context->m_mouseY = sNetToNative16(message+10);
|
||||
sSendMouseCallback(context);
|
||||
}
|
||||
else if (USYNERGY_IS_PACKET("DMWM"))
|
||||
{
|
||||
// Mouse wheel
|
||||
// kMsgDMouseWheel = "DMWM%2i%2i"
|
||||
// kMsgDMouseWheel1_0 = "DMWM%2i"
|
||||
context->m_mouseWheelX += sNetToNative16(message+8);
|
||||
context->m_mouseWheelY += sNetToNative16(message+10);
|
||||
sSendMouseCallback(context);
|
||||
}
|
||||
else if (USYNERGY_IS_PACKET("DKDN"))
|
||||
{
|
||||
// Key down
|
||||
// kMsgDKeyDown = "DKDN%2i%2i%2i"
|
||||
// kMsgDKeyDown1_0 = "DKDN%2i%2i"
|
||||
//uint16_t id = sNetToNative16(message+8);
|
||||
uint16_t mod = sNetToNative16(message+10);
|
||||
uint16_t key = sNetToNative16(message+12);
|
||||
sSendKeyboardCallback(context, key, mod, USYNERGY_TRUE, USYNERGY_FALSE);
|
||||
}
|
||||
else if (USYNERGY_IS_PACKET("DKRP"))
|
||||
{
|
||||
// Key repeat
|
||||
// kMsgDKeyRepeat = "DKRP%2i%2i%2i%2i"
|
||||
// kMsgDKeyRepeat1_0 = "DKRP%2i%2i%2i"
|
||||
uint16_t mod = sNetToNative16(message+10);
|
||||
// uint16_t count = sNetToNative16(message+12);
|
||||
uint16_t key = sNetToNative16(message+14);
|
||||
sSendKeyboardCallback(context, key, mod, USYNERGY_TRUE, USYNERGY_TRUE);
|
||||
}
|
||||
else if (USYNERGY_IS_PACKET("DKUP"))
|
||||
{
|
||||
// Key up
|
||||
// kMsgDKeyUp = "DKUP%2i%2i%2i"
|
||||
// kMsgDKeyUp1_0 = "DKUP%2i%2i"
|
||||
//uint16 id=Endian::sNetToNative(sbuf[4]);
|
||||
uint16_t mod = sNetToNative16(message+10);
|
||||
uint16_t key = sNetToNative16(message+12);
|
||||
sSendKeyboardCallback(context, key, mod, USYNERGY_FALSE, USYNERGY_FALSE);
|
||||
}
|
||||
else if (USYNERGY_IS_PACKET("DGBT"))
|
||||
{
|
||||
// Joystick buttons
|
||||
// kMsgDGameButtons = "DGBT%1i%2i";
|
||||
uint8_t joy_num = message[8];
|
||||
if (joy_num<USYNERGY_NUM_JOYSTICKS)
|
||||
{
|
||||
// Copy button state, then send callback
|
||||
context->m_joystickButtons[joy_num] = (message[9] << 8) | message[10];
|
||||
sSendJoystickCallback(context, joy_num);
|
||||
}
|
||||
}
|
||||
else if (USYNERGY_IS_PACKET("DGST"))
|
||||
{
|
||||
// Joystick sticks
|
||||
// kMsgDGameSticks = "DGST%1i%1i%1i%1i%1i";
|
||||
uint8_t joy_num = message[8];
|
||||
if (joy_num<USYNERGY_NUM_JOYSTICKS)
|
||||
{
|
||||
// Copy stick state, then send callback
|
||||
memcpy(context->m_joystickSticks[joy_num], message+9, 4);
|
||||
sSendJoystickCallback(context, joy_num);
|
||||
}
|
||||
}
|
||||
else if (USYNERGY_IS_PACKET("DSOP"))
|
||||
{
|
||||
// Set options
|
||||
// kMsgDSetOptions = "DSOP%4I"
|
||||
}
|
||||
else if (USYNERGY_IS_PACKET("CALV"))
|
||||
{
|
||||
// Keepalive, reply with CALV and then CNOP
|
||||
// kMsgCKeepAlive = "CALV"
|
||||
sAddString(context, "CALV");
|
||||
sSendReply(context);
|
||||
// now reply with CNOP
|
||||
}
|
||||
else if (USYNERGY_IS_PACKET("DCLP"))
|
||||
{
|
||||
// Clipboard message
|
||||
// kMsgDClipboard = "DCLP%1i%4i%s"
|
||||
//
|
||||
// The clipboard message contains:
|
||||
// 1 uint32: The size of the message
|
||||
// 4 chars: The identifier ("DCLP")
|
||||
// 1 uint8: The clipboard index
|
||||
// 1 uint32: The sequence number. It's zero, because this message is always coming from the server?
|
||||
// 1 uint32: The total size of the remaining 'string' (as per the Synergy %s string format (which is 1 uint32 for size followed by a char buffer (not necessarily null terminated)).
|
||||
// 1 uint32: The number of formats present in the message
|
||||
// And then 'number of formats' times the following:
|
||||
// 1 uint32: The format of the clipboard data
|
||||
// 1 uint32: The size n of the clipboard data
|
||||
// n uint8: The clipboard data
|
||||
const uint8_t * parse_msg = message+17;
|
||||
uint32_t num_formats = sNetToNative32(parse_msg);
|
||||
parse_msg += 4;
|
||||
for (; num_formats; num_formats--)
|
||||
{
|
||||
// Parse clipboard format header
|
||||
uint32_t format = sNetToNative32(parse_msg);
|
||||
uint32_t size = sNetToNative32(parse_msg+4);
|
||||
parse_msg += 8;
|
||||
|
||||
// Call callback
|
||||
if (context->m_clipboardCallback)
|
||||
context->m_clipboardCallback(context->m_cookie, format, parse_msg, size);
|
||||
|
||||
parse_msg += size;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unknown packet, could be any of these
|
||||
// kMsgCNoop = "CNOP"
|
||||
// kMsgCClose = "CBYE"
|
||||
// kMsgCClipboard = "CCLP%1i%4i"
|
||||
// kMsgCScreenSaver = "CSEC%1i"
|
||||
// kMsgDKeyRepeat = "DKRP%2i%2i%2i%2i"
|
||||
// kMsgDKeyRepeat1_0 = "DKRP%2i%2i%2i"
|
||||
// kMsgDMouseRelMove = "DMRM%2i%2i"
|
||||
// kMsgEIncompatible = "EICV%2i%2i"
|
||||
// kMsgEBusy = "EBSY"
|
||||
// kMsgEUnknown = "EUNK"
|
||||
// kMsgEBad = "EBAD"
|
||||
char buffer[64];
|
||||
sprintf(buffer, "Unknown packet '%c%c%c%c'", message[4], message[5], message[6], message[7]);
|
||||
sTrace(context, buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
// Reply with CNOP maybe?
|
||||
sAddString(context, "CNOP");
|
||||
sSendReply(context);
|
||||
}
|
||||
#undef USYNERGY_IS_PACKET
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Mark context as being disconnected
|
||||
**/
|
||||
static void sSetDisconnected(uSynergyContext *context)
|
||||
{
|
||||
context->m_connected = USYNERGY_FALSE;
|
||||
context->m_hasReceivedHello = USYNERGY_FALSE;
|
||||
context->m_isCaptured = USYNERGY_FALSE;
|
||||
context->m_replyCur = context->m_replyBuffer + 4;
|
||||
context->m_sequenceNumber = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Update a connected context
|
||||
**/
|
||||
static void sUpdateContext(uSynergyContext *context)
|
||||
{
|
||||
/* Receive data (blocking) */
|
||||
int receive_size = USYNERGY_RECEIVE_BUFFER_SIZE - context->m_receiveOfs;
|
||||
int num_received = 0;
|
||||
int packlen = 0;
|
||||
if (context->m_receiveFunc(context->m_cookie, context->m_receiveBuffer + context->m_receiveOfs, receive_size, &num_received) == USYNERGY_FALSE)
|
||||
{
|
||||
/* Receive failed, let's try to reconnect */
|
||||
char buffer[128];
|
||||
sprintf(buffer, "Receive failed (%d bytes asked, %d bytes received), trying to reconnect in a second", receive_size, num_received);
|
||||
sTrace(context, buffer);
|
||||
sSetDisconnected(context);
|
||||
context->m_sleepFunc(context->m_cookie, 1000);
|
||||
return;
|
||||
}
|
||||
context->m_receiveOfs += num_received;
|
||||
|
||||
/* If we didn't receive any data then we're probably still polling to get connected and
|
||||
therefore not getting any data back. To avoid overloading the system with a Synergy
|
||||
thread that would hammer on polling, we let it rest for a bit if there's no data. */
|
||||
if (num_received == 0)
|
||||
context->m_sleepFunc(context->m_cookie, 500);
|
||||
|
||||
/* Check for timeouts */
|
||||
if (context->m_hasReceivedHello)
|
||||
{
|
||||
uint32_t cur_time = context->m_getTimeFunc();
|
||||
if (num_received == 0)
|
||||
{
|
||||
/* Timeout after 2 secs of inactivity (we received no CALV) */
|
||||
if ((cur_time - context->m_lastMessageTime) > USYNERGY_IDLE_TIMEOUT)
|
||||
sSetDisconnected(context);
|
||||
}
|
||||
else
|
||||
context->m_lastMessageTime = cur_time;
|
||||
}
|
||||
|
||||
/* Eat packets */
|
||||
for (;;)
|
||||
{
|
||||
/* Grab packet length and bail out if the packet goes beyond the end of the buffer */
|
||||
packlen = sNetToNative32(context->m_receiveBuffer);
|
||||
if (packlen+4 > context->m_receiveOfs)
|
||||
break;
|
||||
|
||||
/* Process message */
|
||||
sProcessMessage(context, context->m_receiveBuffer);
|
||||
|
||||
/* Move packet to front of buffer */
|
||||
memmove(context->m_receiveBuffer, context->m_receiveBuffer+packlen+4, context->m_receiveOfs-packlen-4);
|
||||
context->m_receiveOfs -= packlen+4;
|
||||
}
|
||||
|
||||
/* Throw away over-sized packets */
|
||||
if (packlen > USYNERGY_RECEIVE_BUFFER_SIZE)
|
||||
{
|
||||
/* Oversized packet, ditch tail end */
|
||||
char buffer[128];
|
||||
sprintf(buffer, "Oversized packet: '%c%c%c%c' (length %d)", context->m_receiveBuffer[4], context->m_receiveBuffer[5], context->m_receiveBuffer[6], context->m_receiveBuffer[7], packlen);
|
||||
sTrace(context, buffer);
|
||||
num_received = context->m_receiveOfs-4; // 4 bytes for the size field
|
||||
while (num_received != packlen)
|
||||
{
|
||||
int buffer_left = packlen - num_received;
|
||||
int to_receive = buffer_left < USYNERGY_RECEIVE_BUFFER_SIZE ? buffer_left : USYNERGY_RECEIVE_BUFFER_SIZE;
|
||||
int ditch_received = 0;
|
||||
if (context->m_receiveFunc(context->m_cookie, context->m_receiveBuffer, to_receive, &ditch_received) == USYNERGY_FALSE)
|
||||
{
|
||||
/* Receive failed, let's try to reconnect */
|
||||
sTrace(context, "Receive failed, trying to reconnect in a second");
|
||||
sSetDisconnected(context);
|
||||
context->m_sleepFunc(context->m_cookie, 1000);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
num_received += ditch_received;
|
||||
}
|
||||
}
|
||||
context->m_receiveOfs = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// Public interface
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Initialize uSynergy context
|
||||
**/
|
||||
void uSynergyInit(uSynergyContext *context)
|
||||
{
|
||||
/* Zero memory */
|
||||
memset(context, 0, sizeof(uSynergyContext));
|
||||
|
||||
/* Initialize to default state */
|
||||
sSetDisconnected(context);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@brief Update uSynergy
|
||||
**/
|
||||
void uSynergyUpdate(uSynergyContext *context)
|
||||
{
|
||||
if (context->m_connected)
|
||||
{
|
||||
/* Update context, receive data, call callbacks */
|
||||
sUpdateContext(context);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Try to connect */
|
||||
if (context->m_connectFunc(context->m_cookie))
|
||||
context->m_connected = USYNERGY_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Send clipboard data
|
||||
**/
|
||||
void uSynergySendClipboard(uSynergyContext *context, const char *text)
|
||||
{
|
||||
// Calculate maximum size that will fit in a reply packet
|
||||
uint32_t overhead_size = 4 + /* Message size */
|
||||
4 + /* Message ID */
|
||||
1 + /* Clipboard index */
|
||||
4 + /* Sequence number */
|
||||
4 + /* Rest of message size (because it's a Synergy string from here on) */
|
||||
4 + /* Number of clipboard formats */
|
||||
4 + /* Clipboard format */
|
||||
4; /* Clipboard data length */
|
||||
uint32_t max_length = USYNERGY_REPLY_BUFFER_SIZE - overhead_size;
|
||||
|
||||
// Clip text to max length
|
||||
uint32_t text_length = (uint32_t)strlen(text);
|
||||
if (text_length > max_length)
|
||||
{
|
||||
char buffer[128];
|
||||
sprintf(buffer, "Clipboard buffer too small, clipboard truncated at %d characters", max_length);
|
||||
sTrace(context, buffer);
|
||||
text_length = max_length;
|
||||
}
|
||||
|
||||
// Assemble packet
|
||||
sAddString(context, "DCLP");
|
||||
sAddUInt8(context, 0); /* Clipboard index */
|
||||
sAddUInt32(context, context->m_sequenceNumber);
|
||||
sAddUInt32(context, 4+4+4+text_length); /* Rest of message size: numFormats, format, length, data */
|
||||
sAddUInt32(context, 1); /* Number of formats (only text for now) */
|
||||
sAddUInt32(context, USYNERGY_CLIPBOARD_FORMAT_TEXT);
|
||||
sAddUInt32(context, text_length);
|
||||
sAddString(context, text);
|
||||
sSendReply(context);
|
||||
}
|
420
examples/libs/usynergy/uSynergy.h
Normal file
@ -0,0 +1,420 @@
|
||||
/*
|
||||
uSynergy client -- Interface for the embedded Synergy client library
|
||||
version 1.0.0, July 7th, 2012
|
||||
|
||||
Copyright (C) 2012 Synergy Si Ltd.
|
||||
Copyright (c) 2012 Alex Evans
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// Configuration
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Determine endianness
|
||||
**/
|
||||
#if defined(USYNERGY_LITTLE_ENDIAN) && defined(USYNERGY_BIG_ENDIAN)
|
||||
/* Ambiguous: both endians specified */
|
||||
#error "Can't define both USYNERGY_LITTLE_ENDIAN and USYNERGY_BIG_ENDIAN"
|
||||
#elif !defined(USYNERGY_LITTLE_ENDIAN) && !defined(USYNERGY_BIG_ENDIAN)
|
||||
/* Attempt to auto detect */
|
||||
#if defined(__LITTLE_ENDIAN__) || defined(LITTLE_ENDIAN) || (_BYTE_ORDER == _LITTLE_ENDIAN)
|
||||
#define USYNERGY_LITTLE_ENDIAN
|
||||
#elif defined(__BIG_ENDIAN__) || defined(BIG_ENDIAN) || (_BYTE_ORDER == _BIG_ENDIAN)
|
||||
#define USYNERGY_BIG_ENDIAN
|
||||
#else
|
||||
#error "Can't detect endian-nes, please defined either USYNERGY_LITTLE_ENDIAN or USYNERGY_BIG_ENDIAN";
|
||||
#endif
|
||||
#else
|
||||
/* User-specified endian-nes, nothing to do for us */
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// Types and Constants
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Boolean type
|
||||
**/
|
||||
typedef int uSynergyBool;
|
||||
#define USYNERGY_FALSE 0 /* False value */
|
||||
#define USYNERGY_TRUE 1 /* True value */
|
||||
|
||||
|
||||
/**
|
||||
@brief User context type
|
||||
|
||||
The uSynergyCookie type is an opaque type that is used by uSynergy to communicate to the client. It is passed along to
|
||||
callback functions as context.
|
||||
**/
|
||||
typedef struct { int ignored; } * uSynergyCookie;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Clipboard types
|
||||
**/
|
||||
enum uSynergyClipboardFormat
|
||||
{
|
||||
USYNERGY_CLIPBOARD_FORMAT_TEXT = 0, /* Text format, UTF-8, newline is LF */
|
||||
USYNERGY_CLIPBOARD_FORMAT_BITMAP = 1, /* Bitmap format, BMP 24/32bpp, BI_RGB */
|
||||
USYNERGY_CLIPBOARD_FORMAT_HTML = 2, /* HTML format, HTML fragment, UTF-8, newline is LF */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Constants and limits
|
||||
**/
|
||||
#define USYNERGY_NUM_JOYSTICKS 4 /* Maximum number of supported joysticks */
|
||||
|
||||
#define USYNERGY_PROTOCOL_MAJOR 1 /* Major protocol version */
|
||||
#define USYNERGY_PROTOCOL_MINOR 4 /* Minor protocol version */
|
||||
|
||||
#define USYNERGY_IDLE_TIMEOUT 2000 /* Timeout in milliseconds before reconnecting */
|
||||
|
||||
#define USYNERGY_TRACE_BUFFER_SIZE 1024 /* Maximum length of traced message */
|
||||
#define USYNERGY_REPLY_BUFFER_SIZE 1024 /* Maximum size of a reply packet */
|
||||
#define USYNERGY_RECEIVE_BUFFER_SIZE 4096 /* Maximum size of an incoming packet */
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Keyboard constants
|
||||
**/
|
||||
#define USYNERGY_MODIFIER_SHIFT 0x0001 /* Shift key modifier */
|
||||
#define USYNERGY_MODIFIER_CTRL 0x0002 /* Ctrl key modifier */
|
||||
#define USYNERGY_MODIFIER_ALT 0x0004 /* Alt key modifier */
|
||||
#define USYNERGY_MODIFIER_META 0x0008 /* Meta key modifier */
|
||||
#define USYNERGY_MODIFIER_WIN 0x0010 /* Windows key modifier */
|
||||
#define USYNERGY_MODIFIER_ALT_GR 0x0020 /* AltGr key modifier */
|
||||
#define USYNERGY_MODIFIER_LEVEL5LOCK 0x0040 /* Level5Lock key modifier */
|
||||
#define USYNERGY_MODIFIER_CAPSLOCK 0x1000 /* CapsLock key modifier */
|
||||
#define USYNERGY_MODIFIER_NUMLOCK 0x2000 /* NumLock key modifier */
|
||||
#define USYNERGY_MODIFIER_SCROLLOCK 0x4000 /* ScrollLock key modifier */
|
||||
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// Functions and Callbacks
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Connect function
|
||||
|
||||
This function is called when uSynergy needs to connect to the host. It doesn't imply a network implementation or
|
||||
destination address, that must all be handled on the user side. The function should return USYNERGY_TRUE if a
|
||||
connection was established or USYNERGY_FALSE if it could not connect.
|
||||
|
||||
When network errors occur (e.g. uSynergySend or uSynergyReceive fail) then the connect call will be called again
|
||||
so the implementation of the function must close any old connections and clean up resources before retrying.
|
||||
|
||||
@param cookie Cookie supplied in the Synergy context
|
||||
**/
|
||||
typedef uSynergyBool (*uSynergyConnectFunc)(uSynergyCookie cookie);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Send function
|
||||
|
||||
This function is called when uSynergy needs to send something over the default connection. It should return
|
||||
USYNERGY_TRUE if sending succeeded and USYNERGY_FALSE otherwise. This function should block until the send
|
||||
operation is completed.
|
||||
|
||||
@param cookie Cookie supplied in the Synergy context
|
||||
@param buffer Address of buffer to send
|
||||
@param length Length of buffer to send
|
||||
**/
|
||||
typedef uSynergyBool (*uSynergySendFunc)(uSynergyCookie cookie, const uint8_t *buffer, int length);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Receive function
|
||||
|
||||
This function is called when uSynergy needs to receive data from the default connection. It should return
|
||||
USYNERGY_TRUE if receiving data succeeded and USYNERGY_FALSE otherwise. This function should block until data
|
||||
has been received and wait for data to become available. If @a outLength is set to 0 upon completion it is
|
||||
assumed that the connection is alive, but still in a connecting state and needs time to settle.
|
||||
|
||||
@param cookie Cookie supplied in the Synergy context
|
||||
@param buffer Address of buffer to receive data into
|
||||
@param maxLength Maximum amount of bytes to write into the receive buffer
|
||||
@param outLength Address of integer that receives the actual amount of bytes written into @a buffer
|
||||
**/
|
||||
typedef uSynergyBool (*uSynergyReceiveFunc)(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Thread sleep function
|
||||
|
||||
This function is called when uSynergy wants to suspend operation for a while before retrying an operation. It
|
||||
is mostly used when a socket times out or disconnect occurs to prevent uSynergy from continuously hammering a
|
||||
network connection in case the network is down.
|
||||
|
||||
@param cookie Cookie supplied in the Synergy context
|
||||
@param timeMs Time to sleep the current thread (in milliseconds)
|
||||
**/
|
||||
typedef void (*uSynergySleepFunc)(uSynergyCookie cookie, int timeMs);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Get time function
|
||||
|
||||
This function is called when uSynergy needs to know the current time. This is used to determine when timeouts
|
||||
have occured. The time base should be a cyclic millisecond time value.
|
||||
|
||||
@returns Time value in milliseconds
|
||||
**/
|
||||
typedef uint32_t (*uSynergyGetTimeFunc)();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Trace function
|
||||
|
||||
This function is called when uSynergy wants to trace something. It is optional to show these messages, but they
|
||||
are often useful when debugging. uSynergy only traces major events like connecting and disconnecting. Usually
|
||||
only a single trace is shown when the connection is established and no more trace are called.
|
||||
|
||||
@param cookie Cookie supplied in the Synergy context
|
||||
@param text Text to be traced
|
||||
**/
|
||||
typedef void (*uSynergyTraceFunc)(uSynergyCookie cookie, const char *text);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Screen active callback
|
||||
|
||||
This callback is called when Synergy makes the screen active or inactive. This
|
||||
callback is usually sent when the mouse enters or leaves the screen.
|
||||
|
||||
@param cookie Cookie supplied in the Synergy context
|
||||
@param active Activation flag, 1 if the screen has become active, 0 if the screen has become inactive
|
||||
**/
|
||||
typedef void (*uSynergyScreenActiveCallback)(uSynergyCookie cookie, uSynergyBool active);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Mouse callback
|
||||
|
||||
This callback is called when a mouse events happens. The mouse X and Y position,
|
||||
wheel and button state is communicated in the message. It's up to the user to
|
||||
interpret if this is a mouse up, down, double-click or other message.
|
||||
|
||||
@param cookie Cookie supplied in the Synergy context
|
||||
@param x Mouse X position
|
||||
@param y Mouse Y position
|
||||
@param wheelX Mouse wheel X position
|
||||
@param wheelY Mouse wheel Y position
|
||||
@param buttonLeft Left button pressed status, 0 for released, 1 for pressed
|
||||
@param buttonMiddle Middle button pressed status, 0 for released, 1 for pressed
|
||||
@param buttonRight Right button pressed status, 0 for released, 1 for pressed
|
||||
**/
|
||||
typedef void (*uSynergyMouseCallback)(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Key event callback
|
||||
|
||||
This callback is called when a key is pressed or released.
|
||||
|
||||
@param cookie Cookie supplied in the Synergy context
|
||||
@param key Key code of key that was pressed or released
|
||||
@param modifiers Status of modifier keys (alt, shift, etc.)
|
||||
@param down Down or up status, 1 is key is pressed down, 0 if key is released (up)
|
||||
@param repeat Repeat flag, 1 if the key is down because the key is repeating, 0 if the key is initially pressed by the user
|
||||
**/
|
||||
typedef void (*uSynergyKeyboardCallback)(uSynergyCookie cookie, uint16_t key, uint16_t modifiers, uSynergyBool down, uSynergyBool repeat);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Joystick event callback
|
||||
|
||||
This callback is called when a joystick stick or button changes. It is possible that multiple callbacks are
|
||||
fired when different sticks or buttons change as these are individual messages in the packet stream. Each
|
||||
callback will contain all the valid state for the different axes and buttons. The last callback received will
|
||||
represent the most current joystick state.
|
||||
|
||||
@param cookie Cookie supplied in the Synergy context
|
||||
@param joyNum Joystick number, always in the range [0 ... USYNERGY_NUM_JOYSTICKS>
|
||||
@param buttons Button pressed mask
|
||||
@param leftStickX Left stick X position, in range [-127 ... 127]
|
||||
@param leftStickY Left stick Y position, in range [-127 ... 127]
|
||||
@param rightStickX Right stick X position, in range [-127 ... 127]
|
||||
@param rightStickY Right stick Y position, in range [-127 ... 127]
|
||||
**/
|
||||
typedef void (*uSynergyJoystickCallback)(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Clipboard event callback
|
||||
|
||||
This callback is called when something is placed on the clipboard. Multiple callbacks may be fired for
|
||||
multiple clipboard formats if they are supported. The data provided is read-only and may not be modified
|
||||
by the application.
|
||||
|
||||
@param cookie Cookie supplied in the Synergy context
|
||||
@param format Clipboard format
|
||||
@param data Memory area containing the clipboard raw data
|
||||
@param size Size of clipboard data
|
||||
**/
|
||||
typedef void (*uSynergyClipboardCallback)(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size);
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// Context
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief uSynergy context
|
||||
**/
|
||||
typedef struct
|
||||
{
|
||||
/* Mandatory configuration data, filled in by client */
|
||||
uSynergyConnectFunc m_connectFunc; /* Connect function */
|
||||
uSynergySendFunc m_sendFunc; /* Send data function */
|
||||
uSynergyReceiveFunc m_receiveFunc; /* Receive data function */
|
||||
uSynergySleepFunc m_sleepFunc; /* Thread sleep function */
|
||||
uSynergyGetTimeFunc m_getTimeFunc; /* Get current time function */
|
||||
const char* m_clientName; /* Name of Synergy Screen / Client */
|
||||
uint16_t m_clientWidth; /* Width of screen */
|
||||
uint16_t m_clientHeight; /* Height of screen */
|
||||
|
||||
/* Optional configuration data, filled in by client */
|
||||
uSynergyCookie m_cookie; /* Cookie pointer passed to callback functions (can be NULL) */
|
||||
uSynergyTraceFunc m_traceFunc; /* Function for tracing status (can be NULL) */
|
||||
uSynergyScreenActiveCallback m_screenActiveCallback; /* Callback for entering and leaving screen */
|
||||
uSynergyMouseCallback m_mouseCallback; /* Callback for mouse events */
|
||||
uSynergyKeyboardCallback m_keyboardCallback; /* Callback for keyboard events */
|
||||
uSynergyJoystickCallback m_joystickCallback; /* Callback for joystick events */
|
||||
uSynergyClipboardCallback m_clipboardCallback; /* Callback for clipboard events */
|
||||
|
||||
/* State data, used internall by client, initialized by uSynergyInit() */
|
||||
uSynergyBool m_connected; /* Is our socket connected? */
|
||||
uSynergyBool m_hasReceivedHello; /* Have we received a 'Hello' from the server? */
|
||||
uSynergyBool m_isCaptured; /* Is Synergy active (i.e. this client is receiving input messages?) */
|
||||
uint32_t m_lastMessageTime; /* Time at which last message was received */
|
||||
uint32_t m_sequenceNumber; /* Packet sequence number */
|
||||
uint8_t m_receiveBuffer[USYNERGY_RECEIVE_BUFFER_SIZE]; /* Receive buffer */
|
||||
int m_receiveOfs; /* Receive buffer offset */
|
||||
uint8_t m_replyBuffer[USYNERGY_REPLY_BUFFER_SIZE]; /* Reply buffer */
|
||||
uint8_t* m_replyCur; /* Write offset into reply buffer */
|
||||
uint16_t m_mouseX; /* Mouse X position */
|
||||
uint16_t m_mouseY; /* Mouse Y position */
|
||||
int16_t m_mouseWheelX; /* Mouse wheel X position */
|
||||
int16_t m_mouseWheelY; /* Mouse wheel Y position */
|
||||
uSynergyBool m_mouseButtonLeft; /* Mouse left button */
|
||||
uSynergyBool m_mouseButtonRight; /* Mouse right button */
|
||||
uSynergyBool m_mouseButtonMiddle; /* Mouse middle button */
|
||||
int8_t m_joystickSticks[USYNERGY_NUM_JOYSTICKS][4]; /* Joystick stick position in 2 axes for 2 sticks */
|
||||
uint16_t m_joystickButtons[USYNERGY_NUM_JOYSTICKS]; /* Joystick button state */
|
||||
} uSynergyContext;
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// Interface
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Initialize uSynergy context
|
||||
|
||||
This function initializes @a context for use. Call this function directly after
|
||||
creating the context, before filling in any configuration data in it. Not calling
|
||||
this function will cause undefined behavior.
|
||||
|
||||
@param context Context to be initialized
|
||||
**/
|
||||
extern void uSynergyInit(uSynergyContext *context);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Update uSynergy
|
||||
|
||||
This function updates uSynergy and does the bulk of the work. It does connection management,
|
||||
receiving data, reconnecting after errors or timeouts and so on. It assumes that networking
|
||||
operations are blocking and it can suspend the current thread if it needs to wait. It is
|
||||
best practice to call uSynergyUpdate from a background thread so it is responsive.
|
||||
|
||||
Because uSynergy relies mostly on blocking calls it will mostly stay in thread sleep state
|
||||
waiting for system mutexes and won't eat much memory.
|
||||
|
||||
uSynergyUpdate doesn't do any memory allocations or have any side effects beyond those of
|
||||
the callbacks it calls.
|
||||
|
||||
@param context Context to be updated
|
||||
**/
|
||||
extern void uSynergyUpdate(uSynergyContext *context);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Send clipboard data
|
||||
|
||||
This function sets new clipboard data and sends it to the server. Use this function if
|
||||
your client cuts or copies data onto the clipboard that it needs to share with the
|
||||
server.
|
||||
|
||||
Currently there is only support for plaintext, but HTML and image data could be
|
||||
supported with some effort.
|
||||
|
||||
@param context Context to send clipboard data to
|
||||
@param text Text to set to the clipboard
|
||||
**/
|
||||
extern void uSynergySendClipboard(uSynergyContext *context, const char *text);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
@ -10,8 +10,9 @@
|
||||
|
||||
#CXX = g++
|
||||
|
||||
OBJS = main.o imgui_impl_glfw_gl3.o gl3w/GL/gl3w.o
|
||||
OBJS = main.o imgui_impl_glfw_gl3.o
|
||||
OBJS += ../../imgui.o
|
||||
OBJS += ../libs/gl3w/GL/gl3w.o
|
||||
|
||||
UNAME_S := $(shell uname -s)
|
||||
|
||||
@ -20,7 +21,7 @@ ifeq ($(UNAME_S), Linux) #LINUX
|
||||
ECHO_MESSAGE = "Linux"
|
||||
LIBS = `pkg-config --static --libs glfw3`
|
||||
|
||||
CXXFLAGS = -I../../ -Igl3w `pkg-config --cflags glfw3`
|
||||
CXXFLAGS = -I../../ -I../libs/gl3w `pkg-config --cflags glfw3`
|
||||
CXXFLAGS += -Wall
|
||||
CFLAGS = $(CXXFLAGS)
|
||||
endif
|
||||
@ -31,7 +32,7 @@ ifeq ($(UNAME_S), Darwin) #APPLE
|
||||
LIBS += -L/usr/local/lib
|
||||
LIBS += -lglfw3
|
||||
|
||||
CXXFLAGS = -I../../ -Igl3w -I/usr/local/Cellar/glew/1.10.0/include -I/usr/local/include
|
||||
CXXFLAGS = -I../../ -I../libs/gl3w -I/usr/local/Cellar/glew/1.10.0/include -I/usr/local/include
|
||||
CXXFLAGS += -Wall
|
||||
# CXXFLAGS += -D__APPLE__
|
||||
CFLAGS = $(CXXFLAGS)
|
||||
|
@ -23,18 +23,18 @@ static GLuint g_FontTexture = 0;
|
||||
static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0;
|
||||
static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0;
|
||||
static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0;
|
||||
static size_t g_VboMaxSize = 20000;
|
||||
static int g_VboSize = 0;
|
||||
static unsigned int g_VboHandle = 0, g_VaoHandle = 0;
|
||||
|
||||
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure)
|
||||
// If text or lines are blurry when integrating ImGui in your engine:
|
||||
// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
|
||||
static void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count)
|
||||
static void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawData* draw_data)
|
||||
{
|
||||
if (cmd_lists_count == 0)
|
||||
return;
|
||||
|
||||
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled
|
||||
GLint last_program, last_texture;
|
||||
glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
@ -56,61 +56,50 @@ static void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawList** const cmd_lists, int
|
||||
glUseProgram(g_ShaderHandle);
|
||||
glUniform1i(g_AttribLocationTex, 0);
|
||||
glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
|
||||
|
||||
// Grow our buffer according to what we need
|
||||
size_t total_vtx_count = 0;
|
||||
for (int n = 0; n < cmd_lists_count; n++)
|
||||
total_vtx_count += cmd_lists[n]->vtx_buffer.size();
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
|
||||
size_t neededBufferSize = total_vtx_count * sizeof(ImDrawVert);
|
||||
if (neededBufferSize > g_VboMaxSize)
|
||||
{
|
||||
g_VboMaxSize = neededBufferSize + 5000; // Grow buffer
|
||||
glBufferData(GL_ARRAY_BUFFER, g_VboMaxSize, NULL, GL_STREAM_DRAW);
|
||||
}
|
||||
|
||||
// Copy and convert all vertices into a single contiguous buffer
|
||||
unsigned char* buffer_data = (unsigned char*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
|
||||
if (!buffer_data)
|
||||
return;
|
||||
for (int n = 0; n < cmd_lists_count; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = cmd_lists[n];
|
||||
memcpy(buffer_data, &cmd_list->vtx_buffer[0], cmd_list->vtx_buffer.size() * sizeof(ImDrawVert));
|
||||
buffer_data += cmd_list->vtx_buffer.size() * sizeof(ImDrawVert);
|
||||
}
|
||||
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(g_VaoHandle);
|
||||
|
||||
int cmd_offset = 0;
|
||||
for (int n = 0; n < cmd_lists_count; n++)
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = cmd_lists[n];
|
||||
int vtx_offset = cmd_offset;
|
||||
const ImDrawCmd* pcmd_end = cmd_list->commands.end();
|
||||
for (const ImDrawCmd* pcmd = cmd_list->commands.begin(); pcmd != pcmd_end; pcmd++)
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
const ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front();
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
|
||||
int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert);
|
||||
if (g_VboSize < needed_vtx_size)
|
||||
{
|
||||
if (pcmd->user_callback)
|
||||
// Grow our buffer if needed
|
||||
g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert);
|
||||
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW);
|
||||
}
|
||||
|
||||
unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
|
||||
if (!vtx_data)
|
||||
continue;
|
||||
memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert));
|
||||
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||
|
||||
for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++)
|
||||
{
|
||||
if (pcmd->UserCallback)
|
||||
{
|
||||
pcmd->user_callback(cmd_list, pcmd);
|
||||
pcmd->UserCallback(cmd_list, pcmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->texture_id);
|
||||
glScissor((int)pcmd->clip_rect.x, (int)(height - pcmd->clip_rect.w), (int)(pcmd->clip_rect.z - pcmd->clip_rect.x), (int)(pcmd->clip_rect.w - pcmd->clip_rect.y));
|
||||
glDrawArrays(GL_TRIANGLES, vtx_offset, pcmd->vtx_count);
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
|
||||
glScissor((int)pcmd->ClipRect.x, (int)(height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y));
|
||||
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer);
|
||||
}
|
||||
vtx_offset += pcmd->vtx_count;
|
||||
idx_buffer += pcmd->ElemCount;
|
||||
}
|
||||
cmd_offset = vtx_offset;
|
||||
}
|
||||
|
||||
// Restore modified state
|
||||
glBindVertexArray(0);
|
||||
glUseProgram(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glUseProgram(last_program);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||
}
|
||||
|
||||
static const char* ImGui_ImplGlfwGL3_GetClipboardText()
|
||||
@ -123,29 +112,32 @@ static void ImGui_ImplGlfwGL3_SetClipboardText(const char* text)
|
||||
glfwSetClipboardString(g_Window, text);
|
||||
}
|
||||
|
||||
void ImGui_ImplGlfwGL3_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods)
|
||||
void ImGui_ImplGlfwGL3_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/)
|
||||
{
|
||||
if (action == GLFW_PRESS && button >= 0 && button < 3)
|
||||
g_MousePressed[button] = true;
|
||||
}
|
||||
|
||||
void ImGui_ImplGlfwGL3_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
void ImGui_ImplGlfwGL3_ScrollCallback(GLFWwindow*, double /*xoffset*/, double yoffset)
|
||||
{
|
||||
g_MouseWheel += (float)yoffset; // Use fractional mouse wheel, 1.0 unit 5 lines.
|
||||
}
|
||||
|
||||
void ImGui_ImplGlfwGL3_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
|
||||
void ImGui_ImplGlfwGL3_KeyCallback(GLFWwindow*, int key, int, int action, int mods)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (action == GLFW_PRESS)
|
||||
io.KeysDown[key] = true;
|
||||
if (action == GLFW_RELEASE)
|
||||
io.KeysDown[key] = false;
|
||||
io.KeyCtrl = (mods & GLFW_MOD_CONTROL) != 0;
|
||||
io.KeyShift = (mods & GLFW_MOD_SHIFT) != 0;
|
||||
|
||||
(void)mods; // Modifiers are not reliable across systems
|
||||
io.KeyCtrl = io.KeysDown[GLFW_KEY_LEFT_CONTROL] || io.KeysDown[GLFW_KEY_RIGHT_CONTROL];
|
||||
io.KeyShift = io.KeysDown[GLFW_KEY_LEFT_SHIFT] || io.KeysDown[GLFW_KEY_RIGHT_SHIFT];
|
||||
io.KeyAlt = io.KeysDown[GLFW_KEY_LEFT_ALT] || io.KeysDown[GLFW_KEY_RIGHT_ALT];
|
||||
}
|
||||
|
||||
void ImGui_ImplGlfwGL3_CharCallback(GLFWwindow* window, unsigned int c)
|
||||
void ImGui_ImplGlfwGL3_CharCallback(GLFWwindow*, unsigned int c)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (c > 0 && c < 0x10000)
|
||||
@ -168,6 +160,10 @@ void ImGui_ImplGlfwGL3_CreateFontsTexture()
|
||||
|
||||
// Store our identifier
|
||||
io.Fonts->TexID = (void *)(intptr_t)g_FontTexture;
|
||||
|
||||
// Cleanup (don't clear the input data if you want to append new fonts later)
|
||||
io.Fonts->ClearInputData();
|
||||
io.Fonts->ClearTexData();
|
||||
}
|
||||
|
||||
bool ImGui_ImplGlfwGL3_CreateDeviceObjects()
|
||||
@ -216,8 +212,6 @@ bool ImGui_ImplGlfwGL3_CreateDeviceObjects()
|
||||
g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color");
|
||||
|
||||
glGenBuffers(1, &g_VboHandle);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
|
||||
glBufferData(GL_ARRAY_BUFFER, g_VboMaxSize, NULL, GL_DYNAMIC_DRAW);
|
||||
|
||||
glGenVertexArrays(1, &g_VaoHandle);
|
||||
glBindVertexArray(g_VaoHandle);
|
||||
@ -249,6 +243,8 @@ bool ImGui_ImplGlfwGL3_Init(GLFWwindow* window, bool install_callbacks)
|
||||
io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT;
|
||||
io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP;
|
||||
io.KeyMap[ImGuiKey_DownArrow] = GLFW_KEY_DOWN;
|
||||
io.KeyMap[ImGuiKey_PageUp] = GLFW_KEY_PAGE_UP;
|
||||
io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN;
|
||||
io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME;
|
||||
io.KeyMap[ImGuiKey_End] = GLFW_KEY_END;
|
||||
io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE;
|
||||
@ -328,11 +324,18 @@ void ImGui_ImplGlfwGL3_NewFrame()
|
||||
|
||||
// Setup inputs
|
||||
// (we already got mouse wheel, keyboard keys & characters from glfw callbacks polled in glfwPollEvents())
|
||||
double mouse_x, mouse_y;
|
||||
glfwGetCursorPos(g_Window, &mouse_x, &mouse_y);
|
||||
mouse_x *= (float)display_w / w; // Convert mouse coordinates to pixels
|
||||
mouse_y *= (float)display_h / h;
|
||||
io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.)
|
||||
if (glfwGetWindowAttrib(g_Window, GLFW_FOCUSED))
|
||||
{
|
||||
double mouse_x, mouse_y;
|
||||
glfwGetCursorPos(g_Window, &mouse_x, &mouse_y);
|
||||
mouse_x *= (float)display_w / w; // Convert mouse coordinates to pixels
|
||||
mouse_y *= (float)display_h / h;
|
||||
io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.)
|
||||
}
|
||||
else
|
||||
{
|
||||
io.MousePos = ImVec2(-1,-1);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
@ -343,6 +346,9 @@ void ImGui_ImplGlfwGL3_NewFrame()
|
||||
io.MouseWheel = g_MouseWheel;
|
||||
g_MouseWheel = 0.0f;
|
||||
|
||||
// Hide OS mouse cursor if ImGui is drawing it
|
||||
glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL);
|
||||
|
||||
// Start the frame
|
||||
ImGui::NewFrame();
|
||||
}
|
||||
|
@ -16,5 +16,5 @@ bool ImGui_ImplGlfwGL3_CreateDeviceObjects();
|
||||
// You can also handle inputs yourself and use those as a reference.
|
||||
void ImGui_ImplGlfwGL3_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
|
||||
void ImGui_ImplGlfwGL3_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
void ImGui_ImplGlFwGL3_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
|
||||
void ImGui_ImplGlfwGL3_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
|
||||
void ImGui_ImplGlfwGL3_CharCallback(GLFWwindow* window, unsigned int c);
|
||||
|
@ -8,10 +8,10 @@
|
||||
|
||||
static void error_callback(int error, const char* description)
|
||||
{
|
||||
fprintf(stderr, "Error: %s\n", description);
|
||||
fprintf(stderr, "Error %d: %s\n", error, description);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
int main(int, char**)
|
||||
{
|
||||
// Setup window
|
||||
glfwSetErrorCallback(error_callback);
|
||||
@ -20,18 +20,31 @@ int main(int argc, char** argv)
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
#if __APPLE__
|
||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
||||
#endif
|
||||
GLFWwindow* window = glfwCreateWindow(1280, 720, "ImGui OpenGL3 example", NULL, NULL);
|
||||
glfwMakeContextCurrent(window);
|
||||
gl3wInit();
|
||||
|
||||
// Setup ImGui binding
|
||||
ImGui_ImplGlfwGL3_Init(window, true);
|
||||
|
||||
// Load Fonts
|
||||
// (see extra_fonts/README.txt for more details)
|
||||
//ImGuiIO& io = ImGui::GetIO();
|
||||
//ImFont* my_font1 = io.Fonts->AddFontDefault();
|
||||
//ImFont* my_font2 = io.Fonts->AddFontFromFileTTF("extra_fonts/Karla-Regular.ttf", 15.0f);
|
||||
//ImFont* my_font3 = io.Fonts->AddFontFromFileTTF("extra_fonts/ProggyClean.ttf", 13.0f); my_font3->DisplayOffset.y += 1;
|
||||
//ImFont* my_font4 = io.Fonts->AddFontFromFileTTF("extra_fonts/ProggyTiny.ttf", 10.0f); my_font4->DisplayOffset.y += 1;
|
||||
//ImFont* my_font5 = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, io.Fonts->GetGlyphRangesJapanese());
|
||||
//io.Fonts->AddFontDefault();
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
|
||||
|
||||
// Merge glyphs from multiple fonts into one (e.g. combine default font with another with Chinese glyphs, or add icons)
|
||||
//ImWchar icons_ranges[] = { 0xf000, 0xf3ff, 0 };
|
||||
//ImFontConfig icons_config; icons_config.MergeMode = true; icons_config.PixelSnapH = true;
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 18.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/fontawesome-webfont.ttf", 18.0f, &icons_config, icons_ranges);
|
||||
|
||||
bool show_test_window = true;
|
||||
bool show_another_window = false;
|
||||
@ -47,7 +60,7 @@ int main(int argc, char** argv)
|
||||
// 1. Show a simple window
|
||||
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug"
|
||||
{
|
||||
static float f;
|
||||
static float f = 0.0f;
|
||||
ImGui::Text("Hello, world!");
|
||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
|
||||
ImGui::ColorEdit3("clear color", (float*)&clear_color);
|
||||
@ -59,7 +72,8 @@ int main(int argc, char** argv)
|
||||
// 2. Show another simple window, this time using an explicit Begin/End pair
|
||||
if (show_another_window)
|
||||
{
|
||||
ImGui::Begin("Another Window", &show_another_window, ImVec2(200,100));
|
||||
ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiSetCond_FirstUseEver);
|
||||
ImGui::Begin("Another Window", &show_another_window);
|
||||
ImGui::Text("Hello");
|
||||
ImGui::End();
|
||||
}
|
||||
@ -70,7 +84,7 @@ int main(int argc, char** argv)
|
||||
ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver);
|
||||
ImGui::ShowTestWindow(&show_test_window);
|
||||
}
|
||||
|
||||
|
||||
// Rendering
|
||||
glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
|
||||
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
|
||||
|
@ -5,10 +5,18 @@
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{4a1fb5ea-22f5-42a8-ab92-1d2df5d47fb9}</ProjectGuid>
|
||||
@ -20,41 +28,82 @@
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
|
||||
<IncludePath>$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
|
||||
<IncludePath>$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
|
||||
<IncludePath>$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
|
||||
<IncludePath>$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\opengl_example\glfw\include;gl3w;..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)\libs\glfw\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)..\opengl_example\glfw\lib-msvc100;$(ProjectDir)..\opengl_example\glew\lib\Release\Win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)\libs\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>opengl32.lib;glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)\libs\glfw\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)\libs\glfw\lib-vc2010-64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>opengl32.lib;glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
|
||||
@ -62,17 +111,36 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\opengl_example\glfw\include;gl3w;..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)\libs\glfw\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)..\opengl_example\glfw\lib-msvc100;$(ProjectDir)..\opengl_example\glew\lib\Release\Win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)\libs\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>opengl32.lib;glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreSpecificDefaultLibraries>
|
||||
</IgnoreSpecificDefaultLibraries>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)\libs\glfw\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)\libs\glfw\lib-vc2010-64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>opengl32.lib;glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreSpecificDefaultLibraries>
|
||||
@ -81,15 +149,15 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\imgui.cpp" />
|
||||
<ClCompile Include="gl3w\GL\gl3w.c" />
|
||||
<ClCompile Include="..\libs\gl3w\GL\gl3w.c" />
|
||||
<ClCompile Include="imgui_impl_glfw_gl3.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\imconfig.h" />
|
||||
<ClInclude Include="..\..\imgui.h" />
|
||||
<ClInclude Include="gl3w\GL\gl3w.h" />
|
||||
<ClInclude Include="gl3w\GL\glcorearb.h" />
|
||||
<ClInclude Include="..\libs\gl3w\GL\gl3w.h" />
|
||||
<ClInclude Include="..\libs\gl3w\GL\glcorearb.h" />
|
||||
<ClInclude Include="imgui_impl_glfw_gl3.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
|
@ -22,7 +22,7 @@
|
||||
<ClCompile Include="imgui_impl_glfw_gl3.cpp">
|
||||
<Filter>sources</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gl3w\GL\gl3w.c">
|
||||
<ClCompile Include="..\libs\gl3w\GL\gl3w.c">
|
||||
<Filter>gl3w</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
@ -36,10 +36,10 @@
|
||||
<ClInclude Include="imgui_impl_glfw_gl3.h">
|
||||
<Filter>sources</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gl3w\GL\gl3w.h">
|
||||
<ClInclude Include="..\libs\gl3w\GL\gl3w.h">
|
||||
<Filter>gl3w</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gl3w\GL\glcorearb.h">
|
||||
<ClInclude Include="..\libs\gl3w\GL\glcorearb.h">
|
||||
<Filter>gl3w</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
|
@ -1,180 +0,0 @@
|
||||
/*************************************************************************
|
||||
* GLFW 3.0 - www.glfw.org
|
||||
* A library for OpenGL, window and input
|
||||
*------------------------------------------------------------------------
|
||||
* Copyright (c) 2002-2006 Marcus Geelnard
|
||||
* Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would
|
||||
* be appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef _glfw3_native_h_
|
||||
#define _glfw3_native_h_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* Doxygen documentation
|
||||
*************************************************************************/
|
||||
|
||||
/*! @defgroup native Native access
|
||||
*
|
||||
* **By using the native API, you assert that you know what you're doing and
|
||||
* how to fix problems caused by using it. If you don't, you shouldn't be
|
||||
* using it.**
|
||||
*
|
||||
* Before the inclusion of @ref glfw3native.h, you must define exactly one
|
||||
* window API macro and exactly one context API macro. Failure to do this
|
||||
* will cause a compile-time error.
|
||||
*
|
||||
* The available window API macros are:
|
||||
* * `GLFW_EXPOSE_NATIVE_WIN32`
|
||||
* * `GLFW_EXPOSE_NATIVE_COCOA`
|
||||
* * `GLFW_EXPOSE_NATIVE_X11`
|
||||
*
|
||||
* The available context API macros are:
|
||||
* * `GLFW_EXPOSE_NATIVE_WGL`
|
||||
* * `GLFW_EXPOSE_NATIVE_NSGL`
|
||||
* * `GLFW_EXPOSE_NATIVE_GLX`
|
||||
* * `GLFW_EXPOSE_NATIVE_EGL`
|
||||
*
|
||||
* These macros select which of the native access functions that are declared
|
||||
* and which platform-specific headers to include. It is then up your (by
|
||||
* definition platform-specific) code to handle which of these should be
|
||||
* defined.
|
||||
*/
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* System headers and types
|
||||
*************************************************************************/
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_WIN32)
|
||||
#include <windows.h>
|
||||
#elif defined(GLFW_EXPOSE_NATIVE_COCOA)
|
||||
#if defined(__OBJC__)
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#else
|
||||
typedef void* id;
|
||||
#endif
|
||||
#elif defined(GLFW_EXPOSE_NATIVE_X11)
|
||||
#include <X11/Xlib.h>
|
||||
#else
|
||||
#error "No window API specified"
|
||||
#endif
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_WGL)
|
||||
/* WGL is declared by windows.h */
|
||||
#elif defined(GLFW_EXPOSE_NATIVE_NSGL)
|
||||
/* NSGL is declared by Cocoa.h */
|
||||
#elif defined(GLFW_EXPOSE_NATIVE_GLX)
|
||||
#include <GL/glx.h>
|
||||
#elif defined(GLFW_EXPOSE_NATIVE_EGL)
|
||||
#include <EGL/egl.h>
|
||||
#else
|
||||
#error "No context API specified"
|
||||
#endif
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* Functions
|
||||
*************************************************************************/
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_WIN32)
|
||||
/*! @brief Returns the `HWND` of the specified window.
|
||||
* @return The `HWND` of the specified window.
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI HWND glfwGetWin32Window(GLFWwindow* window);
|
||||
#endif
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_WGL)
|
||||
/*! @brief Returns the `HGLRC` of the specified window.
|
||||
* @return The `HGLRC` of the specified window.
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* window);
|
||||
#endif
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_COCOA)
|
||||
/*! @brief Returns the `NSWindow` of the specified window.
|
||||
* @return The `NSWindow` of the specified window.
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI id glfwGetCocoaWindow(GLFWwindow* window);
|
||||
#endif
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_NSGL)
|
||||
/*! @brief Returns the `NSOpenGLContext` of the specified window.
|
||||
* @return The `NSOpenGLContext` of the specified window.
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI id glfwGetNSGLContext(GLFWwindow* window);
|
||||
#endif
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_X11)
|
||||
/*! @brief Returns the `Display` used by GLFW.
|
||||
* @return The `Display` used by GLFW.
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI Display* glfwGetX11Display(void);
|
||||
/*! @brief Returns the `Window` of the specified window.
|
||||
* @return The `Window` of the specified window.
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI Window glfwGetX11Window(GLFWwindow* window);
|
||||
#endif
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_GLX)
|
||||
/*! @brief Returns the `GLXContext` of the specified window.
|
||||
* @return The `GLXContext` of the specified window.
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window);
|
||||
#endif
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_EGL)
|
||||
/*! @brief Returns the `EGLDisplay` used by GLFW.
|
||||
* @return The `EGLDisplay` used by GLFW.
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI EGLDisplay glfwGetEGLDisplay(void);
|
||||
/*! @brief Returns the `EGLContext` of the specified window.
|
||||
* @return The `EGLContext` of the specified window.
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* window);
|
||||
/*! @brief Returns the `EGLSurface` of the specified window.
|
||||
* @return The `EGLSurface` of the specified window.
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* window);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _glfw3_native_h_ */
|
||||
|
@ -23,11 +23,8 @@ static GLuint g_FontTexture = 0;
|
||||
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure)
|
||||
// If text or lines are blurry when integrating ImGui in your engine:
|
||||
// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
|
||||
static void ImGui_ImplGlfw_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count)
|
||||
static void ImGui_ImplGlfw_RenderDrawLists(ImDrawData* draw_data)
|
||||
{
|
||||
if (cmd_lists_count == 0)
|
||||
return;
|
||||
|
||||
// We are using the OpenGL fixed pipeline to make the example code simpler to read!
|
||||
// A probable faster way to render would be to collate all vertices from all cmd_lists into a single vertex buffer.
|
||||
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers.
|
||||
@ -41,6 +38,7 @@ static void ImGui_ImplGlfw_RenderDrawLists(ImDrawList** const cmd_lists, int cmd
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
//glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context
|
||||
|
||||
// Setup orthographic projection matrix
|
||||
const float width = ImGui::GetIO().DisplaySize.x;
|
||||
@ -55,29 +53,29 @@ static void ImGui_ImplGlfw_RenderDrawLists(ImDrawList** const cmd_lists, int cmd
|
||||
|
||||
// Render command lists
|
||||
#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT))
|
||||
for (int n = 0; n < cmd_lists_count; n++)
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = cmd_lists[n];
|
||||
const unsigned char* vtx_buffer = (const unsigned char*)&cmd_list->vtx_buffer.front();
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
const unsigned char* vtx_buffer = (const unsigned char*)&cmd_list->VtxBuffer.front();
|
||||
const ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front();
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (void*)(vtx_buffer + OFFSETOF(ImDrawVert, pos)));
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (void*)(vtx_buffer + OFFSETOF(ImDrawVert, uv)));
|
||||
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (void*)(vtx_buffer + OFFSETOF(ImDrawVert, col)));
|
||||
|
||||
int vtx_offset = 0;
|
||||
for (size_t cmd_i = 0; cmd_i < cmd_list->commands.size(); cmd_i++)
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.size(); cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &cmd_list->commands[cmd_i];
|
||||
if (pcmd->user_callback)
|
||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback)
|
||||
{
|
||||
pcmd->user_callback(cmd_list, pcmd);
|
||||
pcmd->UserCallback(cmd_list, pcmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->texture_id);
|
||||
glScissor((int)pcmd->clip_rect.x, (int)(height - pcmd->clip_rect.w), (int)(pcmd->clip_rect.z - pcmd->clip_rect.x), (int)(pcmd->clip_rect.w - pcmd->clip_rect.y));
|
||||
glDrawArrays(GL_TRIANGLES, vtx_offset, pcmd->vtx_count);
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
|
||||
glScissor((int)pcmd->ClipRect.x, (int)(height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y));
|
||||
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer);
|
||||
}
|
||||
vtx_offset += pcmd->vtx_count;
|
||||
idx_buffer += pcmd->ElemCount;
|
||||
}
|
||||
}
|
||||
#undef OFFSETOF
|
||||
@ -86,6 +84,7 @@ static void ImGui_ImplGlfw_RenderDrawLists(ImDrawList** const cmd_lists, int cmd
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
@ -103,29 +102,32 @@ static void ImGui_ImplGlfw_SetClipboardText(const char* text)
|
||||
glfwSetClipboardString(g_Window, text);
|
||||
}
|
||||
|
||||
void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods)
|
||||
void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/)
|
||||
{
|
||||
if (action == GLFW_PRESS && button >= 0 && button < 3)
|
||||
g_MousePressed[button] = true;
|
||||
}
|
||||
|
||||
void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
void ImGui_ImplGlfw_ScrollCallback(GLFWwindow*, double /*xoffset*/, double yoffset)
|
||||
{
|
||||
g_MouseWheel += (float)yoffset; // Use fractional mouse wheel, 1.0 unit 5 lines.
|
||||
}
|
||||
|
||||
void ImGui_ImplGlFw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
|
||||
void ImGui_ImplGlFw_KeyCallback(GLFWwindow*, int key, int, int action, int mods)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (action == GLFW_PRESS)
|
||||
io.KeysDown[key] = true;
|
||||
if (action == GLFW_RELEASE)
|
||||
io.KeysDown[key] = false;
|
||||
io.KeyCtrl = (mods & GLFW_MOD_CONTROL) != 0;
|
||||
io.KeyShift = (mods & GLFW_MOD_SHIFT) != 0;
|
||||
|
||||
(void)mods; // Modifiers are not reliable across systems
|
||||
io.KeyCtrl = io.KeysDown[GLFW_KEY_LEFT_CONTROL] || io.KeysDown[GLFW_KEY_RIGHT_CONTROL];
|
||||
io.KeyShift = io.KeysDown[GLFW_KEY_LEFT_SHIFT] || io.KeysDown[GLFW_KEY_RIGHT_SHIFT];
|
||||
io.KeyAlt = io.KeysDown[GLFW_KEY_LEFT_ALT] || io.KeysDown[GLFW_KEY_RIGHT_ALT];
|
||||
}
|
||||
|
||||
void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c)
|
||||
void ImGui_ImplGlfw_CharCallback(GLFWwindow*, unsigned int c)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (c > 0 && c < 0x10000)
|
||||
@ -151,6 +153,10 @@ bool ImGui_ImplGlfw_CreateDeviceObjects()
|
||||
// Store our identifier
|
||||
io.Fonts->TexID = (void *)(intptr_t)g_FontTexture;
|
||||
|
||||
// Cleanup (don't clear the input data if you want to append new fonts later)
|
||||
io.Fonts->ClearInputData();
|
||||
io.Fonts->ClearTexData();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -174,6 +180,8 @@ bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks)
|
||||
io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT;
|
||||
io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP;
|
||||
io.KeyMap[ImGuiKey_DownArrow] = GLFW_KEY_DOWN;
|
||||
io.KeyMap[ImGuiKey_PageUp] = GLFW_KEY_PAGE_UP;
|
||||
io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN;
|
||||
io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME;
|
||||
io.KeyMap[ImGuiKey_End] = GLFW_KEY_END;
|
||||
io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE;
|
||||
@ -232,11 +240,18 @@ void ImGui_ImplGlfw_NewFrame()
|
||||
|
||||
// Setup inputs
|
||||
// (we already got mouse wheel, keyboard keys & characters from glfw callbacks polled in glfwPollEvents())
|
||||
double mouse_x, mouse_y;
|
||||
glfwGetCursorPos(g_Window, &mouse_x, &mouse_y);
|
||||
mouse_x *= (float)display_w / w; // Convert mouse coordinates to pixels
|
||||
mouse_y *= (float)display_h / h;
|
||||
io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.)
|
||||
if (glfwGetWindowAttrib(g_Window, GLFW_FOCUSED))
|
||||
{
|
||||
double mouse_x, mouse_y;
|
||||
glfwGetCursorPos(g_Window, &mouse_x, &mouse_y);
|
||||
mouse_x *= (float)display_w / w; // Convert mouse coordinates to pixels
|
||||
mouse_y *= (float)display_h / h;
|
||||
io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.)
|
||||
}
|
||||
else
|
||||
{
|
||||
io.MousePos = ImVec2(-1,-1);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
@ -247,6 +262,9 @@ void ImGui_ImplGlfw_NewFrame()
|
||||
io.MouseWheel = g_MouseWheel;
|
||||
g_MouseWheel = 0.0f;
|
||||
|
||||
// Hide OS mouse cursor if ImGui is drawing it
|
||||
glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL);
|
||||
|
||||
// Start the frame
|
||||
ImGui::NewFrame();
|
||||
}
|
||||
|
@ -7,10 +7,10 @@
|
||||
|
||||
static void error_callback(int error, const char* description)
|
||||
{
|
||||
fprintf(stderr, "Error: %s\n", description);
|
||||
fprintf(stderr, "Error %d: %s\n", error, description);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
int main(int, char**)
|
||||
{
|
||||
// Setup window
|
||||
glfwSetErrorCallback(error_callback);
|
||||
@ -21,12 +21,22 @@ int main(int argc, char** argv)
|
||||
|
||||
// Setup ImGui binding
|
||||
ImGui_ImplGlfw_Init(window, true);
|
||||
|
||||
// Load Fonts
|
||||
// (see extra_fonts/README.txt for more details)
|
||||
//ImGuiIO& io = ImGui::GetIO();
|
||||
//ImFont* my_font1 = io.Fonts->AddFontDefault();
|
||||
//ImFont* my_font2 = io.Fonts->AddFontFromFileTTF("extra_fonts/Karla-Regular.ttf", 15.0f);
|
||||
//ImFont* my_font3 = io.Fonts->AddFontFromFileTTF("extra_fonts/ProggyClean.ttf", 13.0f); my_font3->DisplayOffset.y += 1;
|
||||
//ImFont* my_font4 = io.Fonts->AddFontFromFileTTF("extra_fonts/ProggyTiny.ttf", 10.0f); my_font4->DisplayOffset.y += 1;
|
||||
//ImFont* my_font5 = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, io.Fonts->GetGlyphRangesJapanese());
|
||||
//io.Fonts->AddFontDefault();
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
|
||||
|
||||
// Merge glyphs from multiple fonts into one (e.g. combine default font with another with Chinese glyphs, or add icons)
|
||||
//ImWchar icons_ranges[] = { 0xf000, 0xf3ff, 0 };
|
||||
//ImFontConfig icons_config; icons_config.MergeMode = true; icons_config.PixelSnapH = true;
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 18.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/fontawesome-webfont.ttf", 18.0f, &icons_config, icons_ranges);
|
||||
|
||||
bool show_test_window = true;
|
||||
bool show_another_window = false;
|
||||
@ -41,7 +51,7 @@ int main(int argc, char** argv)
|
||||
// 1. Show a simple window
|
||||
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug"
|
||||
{
|
||||
static float f;
|
||||
static float f = 0.0f;
|
||||
ImGui::Text("Hello, world!");
|
||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
|
||||
ImGui::ColorEdit3("clear color", (float*)&clear_color);
|
||||
@ -53,7 +63,8 @@ int main(int argc, char** argv)
|
||||
// 2. Show another simple window, this time using an explicit Begin/End pair
|
||||
if (show_another_window)
|
||||
{
|
||||
ImGui::Begin("Another Window", &show_another_window, ImVec2(200,100));
|
||||
ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiSetCond_FirstUseEver);
|
||||
ImGui::Begin("Another Window", &show_another_window);
|
||||
ImGui::Text("Hello");
|
||||
ImGui::End();
|
||||
}
|
||||
|
@ -5,10 +5,18 @@
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{9CDA7840-B7A5-496D-A527-E95571496D18}</ProjectGuid>
|
||||
@ -20,41 +28,82 @@
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
|
||||
<IncludePath>$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
|
||||
<IncludePath>$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
|
||||
<IncludePath>$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
|
||||
<IncludePath>$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)\glfw\include;..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)\libs\glfw\include;..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)\glfw\lib-msvc100;$(ProjectDir)\glew\lib\Release\Win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)\libs\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>opengl32.lib;glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)\libs\glfw\include;..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)\libs\glfw\lib-vc2010-64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>opengl32.lib;glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
|
||||
@ -62,17 +111,36 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)\glfw\include;..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)\libs\glfw\include;..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)\glfw\lib-msvc100;$(ProjectDir)\glew\lib\Release\Win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)\libs\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>opengl32.lib;glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreSpecificDefaultLibraries>
|
||||
</IgnoreSpecificDefaultLibraries>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)\libs\glfw\include;..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)\libs\glfw\lib-vc2010-64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>opengl32.lib;glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreSpecificDefaultLibraries>
|
||||
|
16
examples/sdl_opengl_example/README.md
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
# How to Build
|
||||
|
||||
- On Windows with Visual Studio's CLI
|
||||
|
||||
\<sdl2path\> is your SDL2 folder.
|
||||
|
||||
```
|
||||
cl /MD /I <sdl2path\include> /I ..\.. main.cpp imgui_impl_sdl.cpp ..\..\imgui.cpp /link /LIBPATH:<sdl2path\lib> SDL2.lib SDL2main.lib
|
||||
```
|
||||
|
||||
- On Linux and similar Unices
|
||||
|
||||
```
|
||||
c++ `sdl2-config --cflags` -I ../.. main.cpp imgui_impl_sdl.cpp ../../imgui.cpp `sdl2-config --libs` -lGL -o sdl2example
|
||||
```
|
257
examples/sdl_opengl_example/imgui_impl_sdl.cpp
Normal file
@ -0,0 +1,257 @@
|
||||
// ImGui SDL2 binding with OpenGL
|
||||
// https://github.com/ocornut/imgui
|
||||
|
||||
#include <SDL.h>
|
||||
#include <SDL_syswm.h>
|
||||
#include <SDL_opengl.h>
|
||||
#include <imgui.h>
|
||||
#include "imgui_impl_sdl.h"
|
||||
|
||||
// Data
|
||||
static double g_Time = 0.0f;
|
||||
static bool g_MousePressed[3] = { false, false, false };
|
||||
static float g_MouseWheel = 0.0f;
|
||||
static GLuint g_FontTexture = 0;
|
||||
|
||||
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure)
|
||||
// If text or lines are blurry when integrating ImGui in your engine:
|
||||
// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
|
||||
static void ImGui_ImplSdl_RenderDrawLists(ImDrawData* draw_data)
|
||||
{
|
||||
// We are using the OpenGL fixed pipeline to make the example code simpler to read!
|
||||
// A probable faster way to render would be to collate all vertices from all cmd_lists into a single vertex buffer.
|
||||
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers.
|
||||
glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
//glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context
|
||||
|
||||
// Setup orthographic projection matrix
|
||||
const float width = ImGui::GetIO().DisplaySize.x;
|
||||
const float height = ImGui::GetIO().DisplaySize.y;
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glOrtho(0.0f, width, height, 0.0f, -1.0f, +1.0f);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
// Render command lists
|
||||
#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT))
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
const unsigned char* vtx_buffer = (const unsigned char*)&cmd_list->VtxBuffer.front();
|
||||
const ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front();
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (void*)(vtx_buffer + OFFSETOF(ImDrawVert, pos)));
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (void*)(vtx_buffer + OFFSETOF(ImDrawVert, uv)));
|
||||
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (void*)(vtx_buffer + OFFSETOF(ImDrawVert, col)));
|
||||
|
||||
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
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
|
||||
glScissor((int)pcmd->ClipRect.x, (int)(height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y));
|
||||
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer);
|
||||
}
|
||||
idx_buffer += pcmd->ElemCount;
|
||||
}
|
||||
}
|
||||
#undef OFFSETOF
|
||||
|
||||
// Restore modified state
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
static const char* ImGui_ImplSdl_GetClipboardText()
|
||||
{
|
||||
return SDL_GetClipboardText();
|
||||
}
|
||||
|
||||
static void ImGui_ImplSdl_SetClipboardText(const char* text)
|
||||
{
|
||||
SDL_SetClipboardText(text);
|
||||
}
|
||||
|
||||
bool ImGui_ImplSdl_ProcessEvent(SDL_Event* event)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
switch (event->type)
|
||||
{
|
||||
case SDL_MOUSEWHEEL:
|
||||
{
|
||||
if (event->wheel.y > 0)
|
||||
g_MouseWheel = 1;
|
||||
if (event->wheel.y < 0)
|
||||
g_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:
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.AddInputCharactersUTF8(event->text.text);
|
||||
return true;
|
||||
}
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP:
|
||||
{
|
||||
int key = event->key.keysym.sym & ~SDLK_SCANCODE_MASK;
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ImGui_ImplSdl_CreateDeviceObjects()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
// Build texture
|
||||
unsigned char* pixels;
|
||||
int width, height;
|
||||
io.Fonts->GetTexDataAsAlpha8(&pixels, &width, &height);
|
||||
|
||||
// Create 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);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
// Store our identifier
|
||||
io.Fonts->TexID = (void *)(intptr_t)g_FontTexture;
|
||||
|
||||
// Cleanup (don't clear the input data if you want to append new fonts later)
|
||||
io.Fonts->ClearInputData();
|
||||
io.Fonts->ClearTexData();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplSdl_InvalidateDeviceObjects()
|
||||
{
|
||||
if (g_FontTexture)
|
||||
{
|
||||
glDeleteTextures(1, &g_FontTexture);
|
||||
ImGui::GetIO().Fonts->TexID = 0;
|
||||
g_FontTexture = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGui_ImplSdl_Init(SDL_Window *window)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.KeyMap[ImGuiKey_Tab] = SDLK_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array.
|
||||
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_Delete] = SDLK_DELETE;
|
||||
io.KeyMap[ImGuiKey_Backspace] = SDLK_BACKSPACE;
|
||||
io.KeyMap[ImGuiKey_Enter] = SDLK_RETURN;
|
||||
io.KeyMap[ImGuiKey_Escape] = SDLK_ESCAPE;
|
||||
io.KeyMap[ImGuiKey_A] = SDLK_a;
|
||||
io.KeyMap[ImGuiKey_C] = SDLK_c;
|
||||
io.KeyMap[ImGuiKey_V] = SDLK_v;
|
||||
io.KeyMap[ImGuiKey_X] = SDLK_x;
|
||||
io.KeyMap[ImGuiKey_Y] = SDLK_y;
|
||||
io.KeyMap[ImGuiKey_Z] = SDLK_z;
|
||||
|
||||
io.RenderDrawListsFn = ImGui_ImplSdl_RenderDrawLists;
|
||||
io.SetClipboardTextFn = ImGui_ImplSdl_SetClipboardText;
|
||||
io.GetClipboardTextFn = ImGui_ImplSdl_GetClipboardText;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
SDL_SysWMinfo wmInfo;
|
||||
SDL_VERSION(&wmInfo.version);
|
||||
SDL_GetWindowWMInfo(window, &wmInfo);
|
||||
io.ImeWindowHandle = wmInfo.info.win.window;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplSdl_Shutdown()
|
||||
{
|
||||
ImGui_ImplSdl_InvalidateDeviceObjects();
|
||||
ImGui::Shutdown();
|
||||
}
|
||||
|
||||
void ImGui_ImplSdl_NewFrame(SDL_Window *window)
|
||||
{
|
||||
if (!g_FontTexture)
|
||||
ImGui_ImplSdl_CreateDeviceObjects();
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
// Setup display size (every frame to accommodate for window resizing)
|
||||
int w, h;
|
||||
SDL_GetWindowSize(window, &w, &h);
|
||||
io.DisplaySize = ImVec2((float)w, (float)h);
|
||||
|
||||
// Setup time step
|
||||
Uint32 time = SDL_GetTicks();
|
||||
double current_time = time / 1000.0;
|
||||
io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f/60.0f);
|
||||
g_Time = current_time;
|
||||
|
||||
// Setup inputs
|
||||
// (we already got mouse wheel, keyboard keys & characters from glfw callbacks polled in glfwPollEvents())
|
||||
int mx, my;
|
||||
Uint32 mouseMask = SDL_GetMouseState(&mx, &my);
|
||||
if (SDL_GetWindowFlags(window) & SDL_WINDOW_MOUSE_FOCUS)
|
||||
io.MousePos = ImVec2((float)mx, (float)my); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.)
|
||||
else
|
||||
io.MousePos = ImVec2(-1,-1);
|
||||
|
||||
io.MouseDown[0] = g_MousePressed[0] || (mouseMask & 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] || (mouseMask & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0;
|
||||
io.MouseDown[2] = g_MousePressed[2] || (mouseMask & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0;
|
||||
g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false;
|
||||
|
||||
io.MouseWheel = g_MouseWheel;
|
||||
g_MouseWheel = 0.0f;
|
||||
|
||||
// Hide OS mouse cursor if ImGui is drawing it
|
||||
SDL_ShowCursor(io.MouseDrawCursor ? 0 : 1);
|
||||
|
||||
// Start the frame
|
||||
ImGui::NewFrame();
|
||||
}
|
14
examples/sdl_opengl_example/imgui_impl_sdl.h
Normal file
@ -0,0 +1,14 @@
|
||||
// ImGui SDL2 binding with OpenGL
|
||||
// https://github.com/ocornut/imgui
|
||||
|
||||
struct SDL_Window;
|
||||
typedef union SDL_Event SDL_Event;
|
||||
|
||||
bool ImGui_ImplSdl_Init(SDL_Window *window);
|
||||
void ImGui_ImplSdl_Shutdown();
|
||||
void ImGui_ImplSdl_NewFrame(SDL_Window *window);
|
||||
bool ImGui_ImplSdl_ProcessEvent(SDL_Event* event);
|
||||
|
||||
// Use if you want to reset your rendering device without losing ImGui state.
|
||||
void ImGui_ImplSdl_InvalidateDeviceObjects();
|
||||
bool ImGui_ImplSdl_CreateDeviceObjects();
|
105
examples/sdl_opengl_example/main.cpp
Normal file
@ -0,0 +1,105 @@
|
||||
// ImGui - standalone example application for SDL2 + OpenGL
|
||||
|
||||
#include <imgui.h>
|
||||
#include "imgui_impl_sdl.h"
|
||||
#include <stdio.h>
|
||||
#include <SDL.h>
|
||||
#include <SDL_opengl.h>
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
// Setup SDL
|
||||
if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
|
||||
return -1;
|
||||
|
||||
// Setup window
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
|
||||
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
|
||||
SDL_DisplayMode current;
|
||||
SDL_GetCurrentDisplayMode(0, ¤t);
|
||||
SDL_Window *window = SDL_CreateWindow("ImGui SDL2+OpenGL example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE);
|
||||
SDL_GLContext glcontext = SDL_GL_CreateContext(window);
|
||||
|
||||
// Setup ImGui binding
|
||||
ImGui_ImplSdl_Init(window);
|
||||
|
||||
// Load Fonts
|
||||
// (see extra_fonts/README.txt for more details)
|
||||
//ImGuiIO& io = ImGui::GetIO();
|
||||
//io.Fonts->AddFontDefault();
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
|
||||
|
||||
// Merge glyphs from multiple fonts into one (e.g. combine default font with another with Chinese glyphs, or add icons)
|
||||
//ImWchar icons_ranges[] = { 0xf000, 0xf3ff, 0 };
|
||||
//ImFontConfig icons_config; icons_config.MergeMode = true; icons_config.PixelSnapH = true;
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 18.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../extra_fonts/fontawesome-webfont.ttf", 18.0f, &icons_config, icons_ranges);
|
||||
|
||||
bool show_test_window = true;
|
||||
bool show_another_window = false;
|
||||
ImVec4 clear_color = ImColor(114, 144, 154);
|
||||
|
||||
// Main loop
|
||||
bool done = false;
|
||||
while (!done)
|
||||
{
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event))
|
||||
{
|
||||
ImGui_ImplSdl_ProcessEvent(&event);
|
||||
if (event.type == SDL_QUIT)
|
||||
done = true;
|
||||
}
|
||||
ImGui_ImplSdl_NewFrame(window);
|
||||
|
||||
// 1. Show a simple window
|
||||
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug"
|
||||
{
|
||||
static float f = 0.0f;
|
||||
ImGui::Text("Hello, world!");
|
||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
|
||||
ImGui::ColorEdit3("clear color", (float*)&clear_color);
|
||||
if (ImGui::Button("Test Window")) show_test_window ^= 1;
|
||||
if (ImGui::Button("Another Window")) show_another_window ^= 1;
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
|
||||
}
|
||||
|
||||
// 2. Show another simple window, this time using an explicit Begin/End pair
|
||||
if (show_another_window)
|
||||
{
|
||||
ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiSetCond_FirstUseEver);
|
||||
ImGui::Begin("Another Window", &show_another_window);
|
||||
ImGui::Text("Hello");
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow()
|
||||
if (show_test_window)
|
||||
{
|
||||
ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver);
|
||||
ImGui::ShowTestWindow(&show_test_window);
|
||||
}
|
||||
|
||||
// Rendering
|
||||
glViewport(0, 0, (int)ImGui::GetIO().DisplaySize.x, (int)ImGui::GetIO().DisplaySize.y);
|
||||
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
ImGui::Render();
|
||||
SDL_GL_SwapWindow(window);
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
ImGui_ImplSdl_Shutdown();
|
||||
SDL_GL_DeleteContext(glcontext);
|
||||
SDL_DestroyWindow(window);
|
||||
SDL_Quit();
|
||||
|
||||
return 0;
|
||||
}
|
BIN
extra_fonts/Cousine-Regular.ttf
Normal file
@ -1,10 +1,39 @@
|
||||
|
||||
The code in imgui.cpp embeds a copy of 'ProggyClean.ttf' that you can use without any external files.
|
||||
Those are only provided as a convenience, you can load your own .TTF files.
|
||||
|
||||
---------------------------------
|
||||
EXTRA FONTS FOR IMGUI
|
||||
LINKS
|
||||
---------------------------------
|
||||
|
||||
Typefaces for source code beautification
|
||||
https://github.com/chrissimpkins/codeface
|
||||
|
||||
Proggy Programming Fonts
|
||||
http://upperbounds.net
|
||||
|
||||
Inconsolata
|
||||
http://www.levien.com/type/myfonts/inconsolata.html
|
||||
|
||||
Adobe Source Code Pro: Monospaced font family for user interface and coding environments
|
||||
https://github.com/adobe-fonts/source-code-pro
|
||||
|
||||
Monospace/Fixed Width Programmer's Fonts
|
||||
http://www.lowing.org/fonts/
|
||||
|
||||
(Japanese) M+ fonts by Coji Morishita are free and include most useful Kanjis you would need.
|
||||
http://mplus-fonts.sourceforge.jp/mplus-outline-fonts/index-en.html
|
||||
|
||||
Or use Arial Unicode or other Unicode fonts provided with Windows for full characters coverage (not sure of their licensing).
|
||||
|
||||
---------------------------------
|
||||
INCLUDED FONTS
|
||||
---------------------------------
|
||||
|
||||
Cousine-Regular.ttf
|
||||
Digitized data copyright (c) 2010 Google Corporation.
|
||||
Licensed under the SIL Open Font License, Version 1.1
|
||||
|
||||
DroidSans.ttf
|
||||
Copyright (c) Steve Matteson
|
||||
Apache License, version 2.0
|
||||
@ -24,37 +53,53 @@
|
||||
Copyright (c) 2012, Jonathan Pinhorn
|
||||
SIL OPEN FONT LICENSE Version 1.1
|
||||
|
||||
---------------------------------
|
||||
OTHER FONTS
|
||||
---------------------------------
|
||||
|
||||
For Japanese:
|
||||
|
||||
M+ fonts by Coji Morishita are free and include most useful Kanjis you would need.
|
||||
mplus-fonts.sourceforge.jp/mplus-outline-fonts/index-en.html
|
||||
|
||||
For Japanese, Chinese, Korean:
|
||||
|
||||
You can use Arial Unicode or other Unicode fonts provided with Windows (not sure of their license).
|
||||
Other suggestions?
|
||||
|
||||
---------------------------------
|
||||
LOADING INSTRUCTIONS
|
||||
---------------------------------
|
||||
|
||||
Load default font with:
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.Fonts->AddFontDefault();
|
||||
|
||||
Load .TTF file with:
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_pixels);
|
||||
|
||||
Add a third parameter to bake specific font ranges:
|
||||
Detailed options:
|
||||
|
||||
io.Fonts->LoadFromFileTTF("myfontfile.ttf", size_pixels, io.Fonts->GetGlyphRangesDefault()); // Basic Latin, Extended Latin
|
||||
io.Fonts->LoadFromFileTTF("myfontfile.ttf", size_pixels, io.Fonts->GetGlyphRangesJapanese()); // Default + Hiragana, Katakana, Half-Width, Selection of 1946 Ideographs
|
||||
io.Fonts->LoadFromFileTTF("myfontfile.ttf", size_pixels, io.Fonts->GetGlyphRangesChinese()); // Include full set of about 21000 CJK Unified Ideographs
|
||||
ImFontConfig config;
|
||||
config.OversampleH = 3;
|
||||
config.OversampleV = 3;
|
||||
config.GlyphExtraSpacing.x = 1.0f;
|
||||
io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_pixels, &config);
|
||||
|
||||
Offset font by altering the io.Font->DisplayOffset value:
|
||||
Merge two fonts:
|
||||
|
||||
// Load main font
|
||||
io.Fonts->AddFontDefault();
|
||||
|
||||
// Add character ranges and merge into main font
|
||||
ImWchar ranges[] = { 0xf000, 0xf3ff, 0 };
|
||||
ImFontConfig config;
|
||||
config.MergeMode = true;
|
||||
io.Fonts->AddFontFromFileTTF("fontawesome-webfont.ttf", 16.0f, &config, ranges);
|
||||
io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_pixels, &config, io.Fonts->GetGlyphRangesJapanese());
|
||||
|
||||
Add a fourth parameter to bake specific font ranges only:
|
||||
|
||||
io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_pixels, NULL, io.Fonts->GetGlyphRangesDefault()); // Basic Latin, Extended Latin
|
||||
io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_pixels, NULL, io.Fonts->GetGlyphRangesJapanese()); // Default + Hiragana, Katakana, Half-Width, Selection of 1946 Ideographs
|
||||
io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_pixels, NULL, io.Fonts->GetGlyphRangesChinese()); // Include full set of about 21000 CJK Unified Ideographs
|
||||
|
||||
Offset font vertically by altering the io.Font->DisplayOffset value:
|
||||
|
||||
ImFont* font = io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_pixels);
|
||||
font->DisplayOffset.y += 1; // Render 1 pixel down
|
||||
|
||||
If you want to embed the font in source code (e.g. in your engine, so it doesn't have file-system dependencies);
|
||||
Compile and use 'binary_to_compressed_c.cpp' to create a compressed C style array. Then load the font with:
|
||||
|
||||
ImFont* font = io.Fonts->AddFontFromMemoryCompressedTTF(compressed_data, compressed_data_size, size_pixels, ...);
|
||||
|
||||
|
330
extra_fonts/binary_to_compressed_c.cpp
Normal file
@ -0,0 +1,330 @@
|
||||
// ImGui - binary_to_compressed_c.cpp
|
||||
// Helper tool to turn a file into a C array.
|
||||
// The data is first compressed with stb_compress() to reduce source code size a little.
|
||||
// Useful if you want to embed fonts into your code.
|
||||
// Note that the output array is likely to be bigger than the binary file..
|
||||
// Load compressed TTF fonts with ImGui::GetIO().Fonts->AddFontFromMemoryCompressedTTF()
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
const int COLUMNS = 12;
|
||||
|
||||
// stb_compress* from stb.h - declaration
|
||||
typedef unsigned int stb_uint;
|
||||
typedef unsigned char stb_uchar;
|
||||
stb_uint stb_compress(stb_uchar *out,stb_uchar *in,stb_uint len);
|
||||
|
||||
static bool binary_to_compressed_c(const char* filename, const char* symbol);
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (argc < 3)
|
||||
{
|
||||
printf("Syntax: %s <inputfile> <symbolname>\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
binary_to_compressed_c(argv[1], argv[2]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool binary_to_compressed_c(const char* filename, const char* symbol)
|
||||
{
|
||||
// Read file
|
||||
FILE* f = fopen(filename, "rb");
|
||||
if (!f) return false;
|
||||
int data_sz;
|
||||
if (fseek(f, 0, SEEK_END) || (data_sz = (int)ftell(f)) == -1 || fseek(f, 0, SEEK_SET)) { fclose(f); return false; }
|
||||
char* data = new char[data_sz+4];
|
||||
if (fread(data, 1, data_sz, f) != (size_t)data_sz) { fclose(f); delete[] data; return false; }
|
||||
memset((void *)(((char*)data) + data_sz), 0, 4);
|
||||
fclose(f);
|
||||
|
||||
// Compress
|
||||
int maxlen = data_sz + 512 + (data_sz >> 2) + sizeof(int); // total guess
|
||||
char* compressed = new char[maxlen];
|
||||
int compressed_sz = stb_compress((stb_uchar*)compressed, (stb_uchar*)data, data_sz);
|
||||
memset(compressed + compressed_sz, 0, maxlen - compressed_sz);
|
||||
|
||||
// Output
|
||||
FILE* out = stdout;
|
||||
fprintf(out, "// File: '%s' (%d bytes)\n", filename, (int)data_sz);
|
||||
fprintf(out, "// Exported using binary_to_compressed_c\n");
|
||||
fprintf(out, "static const unsigned int %s_compressed_size = %d;\n", symbol, (int)compressed_sz);
|
||||
fprintf(out, "static const unsigned int %s_compressed_data[%d/4] =\n{", symbol, (int)((compressed_sz+3)/4)*4);
|
||||
int column = 0;
|
||||
for (int i = 0; i < compressed_sz; i += 4)
|
||||
{
|
||||
unsigned int d = *(unsigned int*)(compressed + i);
|
||||
if ((column++ % COLUMNS) == 0)
|
||||
fprintf(out, "\n 0x%08x, ", d);
|
||||
else
|
||||
fprintf(out, "0x%08x, ", d);
|
||||
}
|
||||
fprintf(out, "\n};\n\n");
|
||||
|
||||
// Cleanup
|
||||
delete[] data;
|
||||
delete[] compressed;
|
||||
return true;
|
||||
}
|
||||
|
||||
// stb_compress* from stb.h - definition
|
||||
|
||||
//////////////////// compressor ///////////////////////
|
||||
|
||||
static stb_uint stb_adler32(stb_uint adler32, stb_uchar *buffer, stb_uint buflen)
|
||||
{
|
||||
const unsigned long ADLER_MOD = 65521;
|
||||
unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16;
|
||||
unsigned long blocklen, i;
|
||||
|
||||
blocklen = buflen % 5552;
|
||||
while (buflen) {
|
||||
for (i=0; i + 7 < blocklen; i += 8) {
|
||||
s1 += buffer[0], s2 += s1;
|
||||
s1 += buffer[1], s2 += s1;
|
||||
s1 += buffer[2], s2 += s1;
|
||||
s1 += buffer[3], s2 += s1;
|
||||
s1 += buffer[4], s2 += s1;
|
||||
s1 += buffer[5], s2 += s1;
|
||||
s1 += buffer[6], s2 += s1;
|
||||
s1 += buffer[7], s2 += s1;
|
||||
|
||||
buffer += 8;
|
||||
}
|
||||
|
||||
for (; i < blocklen; ++i)
|
||||
s1 += *buffer++, s2 += s1;
|
||||
|
||||
s1 %= ADLER_MOD, s2 %= ADLER_MOD;
|
||||
buflen -= blocklen;
|
||||
blocklen = 5552;
|
||||
}
|
||||
return (s2 << 16) + s1;
|
||||
}
|
||||
|
||||
static unsigned int stb_matchlen(stb_uchar *m1, stb_uchar *m2, stb_uint maxlen)
|
||||
{
|
||||
stb_uint i;
|
||||
for (i=0; i < maxlen; ++i)
|
||||
if (m1[i] != m2[i]) return i;
|
||||
return i;
|
||||
}
|
||||
|
||||
// simple implementation that just takes the source data in a big block
|
||||
|
||||
static stb_uchar *stb__out;
|
||||
static FILE *stb__outfile;
|
||||
static stb_uint stb__outbytes;
|
||||
|
||||
static void stb__write(unsigned char v)
|
||||
{
|
||||
fputc(v, stb__outfile);
|
||||
++stb__outbytes;
|
||||
}
|
||||
|
||||
#define stb_out(v) (stb__out ? *stb__out++ = (stb_uchar) (v) : stb__write((stb_uchar) (v)))
|
||||
|
||||
static void stb_out2(stb_uint v)
|
||||
{
|
||||
stb_out(v >> 8);
|
||||
stb_out(v);
|
||||
}
|
||||
|
||||
static void stb_out3(stb_uint v) { stb_out(v >> 16); stb_out(v >> 8); stb_out(v); }
|
||||
static void stb_out4(stb_uint v) { stb_out(v >> 24); stb_out(v >> 16);
|
||||
stb_out(v >> 8 ); stb_out(v); }
|
||||
|
||||
static void outliterals(stb_uchar *in, int numlit)
|
||||
{
|
||||
while (numlit > 65536) {
|
||||
outliterals(in,65536);
|
||||
in += 65536;
|
||||
numlit -= 65536;
|
||||
}
|
||||
|
||||
if (numlit == 0) ;
|
||||
else if (numlit <= 32) stb_out (0x000020 + numlit-1);
|
||||
else if (numlit <= 2048) stb_out2(0x000800 + numlit-1);
|
||||
else /* numlit <= 65536) */ stb_out3(0x070000 + numlit-1);
|
||||
|
||||
if (stb__out) {
|
||||
memcpy(stb__out,in,numlit);
|
||||
stb__out += numlit;
|
||||
} else
|
||||
fwrite(in, 1, numlit, stb__outfile);
|
||||
}
|
||||
|
||||
static int stb__window = 0x40000; // 256K
|
||||
|
||||
static int stb_not_crap(int best, int dist)
|
||||
{
|
||||
return ((best > 2 && dist <= 0x00100)
|
||||
|| (best > 5 && dist <= 0x04000)
|
||||
|| (best > 7 && dist <= 0x80000));
|
||||
}
|
||||
|
||||
static stb_uint stb__hashsize = 32768;
|
||||
|
||||
// note that you can play with the hashing functions all you
|
||||
// want without needing to change the decompressor
|
||||
#define stb__hc(q,h,c) (((h) << 7) + ((h) >> 25) + q[c])
|
||||
#define stb__hc2(q,h,c,d) (((h) << 14) + ((h) >> 18) + (q[c] << 7) + q[d])
|
||||
#define stb__hc3(q,c,d,e) ((q[c] << 14) + (q[d] << 7) + q[e])
|
||||
|
||||
static unsigned int stb__running_adler;
|
||||
|
||||
static int stb_compress_chunk(stb_uchar *history,
|
||||
stb_uchar *start,
|
||||
stb_uchar *end,
|
||||
int length,
|
||||
int *pending_literals,
|
||||
stb_uchar **chash,
|
||||
stb_uint mask)
|
||||
{
|
||||
(void)history;
|
||||
int window = stb__window;
|
||||
stb_uint match_max;
|
||||
stb_uchar *lit_start = start - *pending_literals;
|
||||
stb_uchar *q = start;
|
||||
|
||||
#define STB__SCRAMBLE(h) (((h) + ((h) >> 16)) & mask)
|
||||
|
||||
// stop short of the end so we don't scan off the end doing
|
||||
// the hashing; this means we won't compress the last few bytes
|
||||
// unless they were part of something longer
|
||||
while (q < start+length && q+12 < end) {
|
||||
int m;
|
||||
stb_uint h1,h2,h3,h4, h;
|
||||
stb_uchar *t;
|
||||
int best = 2, dist=0;
|
||||
|
||||
if (q+65536 > end)
|
||||
match_max = end-q;
|
||||
else
|
||||
match_max = 65536;
|
||||
|
||||
#define stb__nc(b,d) ((d) <= window && ((b) > 9 || stb_not_crap(b,d)))
|
||||
|
||||
#define STB__TRY(t,p) /* avoid retrying a match we already tried */ \
|
||||
if (p ? dist != q-t : 1) \
|
||||
if ((m = stb_matchlen(t, q, match_max)) > best) \
|
||||
if (stb__nc(m,q-(t))) \
|
||||
best = m, dist = q - (t)
|
||||
|
||||
// rather than search for all matches, only try 4 candidate locations,
|
||||
// chosen based on 4 different hash functions of different lengths.
|
||||
// this strategy is inspired by LZO; hashing is unrolled here using the
|
||||
// 'hc' macro
|
||||
h = stb__hc3(q,0, 1, 2); h1 = STB__SCRAMBLE(h);
|
||||
t = chash[h1]; if (t) STB__TRY(t,0);
|
||||
h = stb__hc2(q,h, 3, 4); h2 = STB__SCRAMBLE(h);
|
||||
h = stb__hc2(q,h, 5, 6); t = chash[h2]; if (t) STB__TRY(t,1);
|
||||
h = stb__hc2(q,h, 7, 8); h3 = STB__SCRAMBLE(h);
|
||||
h = stb__hc2(q,h, 9,10); t = chash[h3]; if (t) STB__TRY(t,1);
|
||||
h = stb__hc2(q,h,11,12); h4 = STB__SCRAMBLE(h);
|
||||
t = chash[h4]; if (t) STB__TRY(t,1);
|
||||
|
||||
// because we use a shared hash table, can only update it
|
||||
// _after_ we've probed all of them
|
||||
chash[h1] = chash[h2] = chash[h3] = chash[h4] = q;
|
||||
|
||||
if (best > 2)
|
||||
assert(dist > 0);
|
||||
|
||||
// see if our best match qualifies
|
||||
if (best < 3) { // fast path literals
|
||||
++q;
|
||||
} else if (best > 2 && best <= 0x80 && dist <= 0x100) {
|
||||
outliterals(lit_start, q-lit_start); lit_start = (q += best);
|
||||
stb_out(0x80 + best-1);
|
||||
stb_out(dist-1);
|
||||
} else if (best > 5 && best <= 0x100 && dist <= 0x4000) {
|
||||
outliterals(lit_start, q-lit_start); lit_start = (q += best);
|
||||
stb_out2(0x4000 + dist-1);
|
||||
stb_out(best-1);
|
||||
} else if (best > 7 && best <= 0x100 && dist <= 0x80000) {
|
||||
outliterals(lit_start, q-lit_start); lit_start = (q += best);
|
||||
stb_out3(0x180000 + dist-1);
|
||||
stb_out(best-1);
|
||||
} else if (best > 8 && best <= 0x10000 && dist <= 0x80000) {
|
||||
outliterals(lit_start, q-lit_start); lit_start = (q += best);
|
||||
stb_out3(0x100000 + dist-1);
|
||||
stb_out2(best-1);
|
||||
} else if (best > 9 && dist <= 0x1000000) {
|
||||
if (best > 65536) best = 65536;
|
||||
outliterals(lit_start, q-lit_start); lit_start = (q += best);
|
||||
if (best <= 0x100) {
|
||||
stb_out(0x06);
|
||||
stb_out3(dist-1);
|
||||
stb_out(best-1);
|
||||
} else {
|
||||
stb_out(0x04);
|
||||
stb_out3(dist-1);
|
||||
stb_out2(best-1);
|
||||
}
|
||||
} else { // fallback literals if no match was a balanced tradeoff
|
||||
++q;
|
||||
}
|
||||
}
|
||||
|
||||
// if we didn't get all the way, add the rest to literals
|
||||
if (q-start < length)
|
||||
q = start+length;
|
||||
|
||||
// the literals are everything from lit_start to q
|
||||
*pending_literals = (q - lit_start);
|
||||
|
||||
stb__running_adler = stb_adler32(stb__running_adler, start, q - start);
|
||||
return q - start;
|
||||
}
|
||||
|
||||
static int stb_compress_inner(stb_uchar *input, stb_uint length)
|
||||
{
|
||||
int literals = 0;
|
||||
stb_uint len,i;
|
||||
|
||||
stb_uchar **chash;
|
||||
chash = (stb_uchar**) malloc(stb__hashsize * sizeof(stb_uchar*));
|
||||
if (chash == NULL) return 0; // failure
|
||||
for (i=0; i < stb__hashsize; ++i)
|
||||
chash[i] = NULL;
|
||||
|
||||
// stream signature
|
||||
stb_out(0x57); stb_out(0xbc);
|
||||
stb_out2(0);
|
||||
|
||||
stb_out4(0); // 64-bit length requires 32-bit leading 0
|
||||
stb_out4(length);
|
||||
stb_out4(stb__window);
|
||||
|
||||
stb__running_adler = 1;
|
||||
|
||||
len = stb_compress_chunk(input, input, input+length, length, &literals, chash, stb__hashsize-1);
|
||||
assert(len == length);
|
||||
|
||||
outliterals(input+length - literals, literals);
|
||||
|
||||
free(chash);
|
||||
|
||||
stb_out2(0x05fa); // end opcode
|
||||
|
||||
stb_out4(stb__running_adler);
|
||||
|
||||
return 1; // success
|
||||
}
|
||||
|
||||
stb_uint stb_compress(stb_uchar *out, stb_uchar *input, stb_uint length)
|
||||
{
|
||||
stb__out = out;
|
||||
stb__outfile = NULL;
|
||||
|
||||
stb_compress_inner(input, length);
|
||||
|
||||
return stb__out - out;
|
||||
}
|
24
imconfig.h
@ -6,11 +6,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
//---- Define your own ImVector<> type if you don't want to use the provided implementation defined in imgui.h
|
||||
//#include <vector>
|
||||
//#define ImVector std::vector
|
||||
//#define ImVector MyVector
|
||||
|
||||
//---- Define assertion handler. Defaults to calling assert().
|
||||
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
|
||||
|
||||
@ -18,17 +13,26 @@
|
||||
//#define IMGUI_API __declspec( dllexport )
|
||||
//#define IMGUI_API __declspec( dllimport )
|
||||
|
||||
//---- Don't implement default handlers for Windows (so as not to link with OpenClipboard() and others Win32 functions)
|
||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS
|
||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS
|
||||
|
||||
//---- Include imgui_user.inl at the end of imgui.cpp so you can include code that extends ImGui using its private data/functions.
|
||||
//#define IMGUI_INCLUDE_IMGUI_USER_INL
|
||||
|
||||
//---- Include imgui_user.h at the end of imgui.h
|
||||
//#define IMGUI_INCLUDE_IMGUI_USER_H
|
||||
|
||||
//---- Define implicit cast operators to convert back<>forth from your math types and ImVec2/ImVec4.
|
||||
//---- Don't implement default handlers for Windows (so as not to link with OpenClipboard() and others Win32 functions)
|
||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS
|
||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS
|
||||
|
||||
//---- Don't implement help and test window functionality (ShowUserGuide()/ShowStyleEditor()/ShowTestWindow() methods will be empty)
|
||||
//#define IMGUI_DISABLE_TEST_WINDOWS
|
||||
|
||||
//---- Don't define obsolete functions names
|
||||
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
|
||||
//---- Implement STB libraries in a namespace to avoid conflicts
|
||||
//#define IMGUI_STB_NAMESPACE ImStb
|
||||
|
||||
//---- Define constructor and implicit cast operators to convert back<>forth from your math types and ImVec2/ImVec4.
|
||||
/*
|
||||
#define IM_VEC2_CLASS_EXTRA \
|
||||
ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \
|
||||
|
@ -1,3 +1,6 @@
|
||||
// [ImGui] this is a slightly modified version of stb_truetype.h 1.4
|
||||
// [ImGui] we made a fix for using the END key on multi-line text edit, see https://github.com/ocornut/imgui/issues/275
|
||||
|
||||
// stb_textedit.h - v1.4 - public domain - Sean Barrett
|
||||
// Development of this library was sponsored by RAD Game Tools
|
||||
//
|
||||
@ -957,6 +960,8 @@ retry:
|
||||
stb_textedit_move_to_first(state);
|
||||
stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
|
||||
state->cursor = find.first_char + find.length;
|
||||
if (find.length > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) == STB_TEXTEDIT_NEWLINE)
|
||||
state->cursor--;
|
||||
state->has_preferred_x = 0;
|
||||
break;
|
||||
}
|
||||
@ -977,6 +982,8 @@ retry:
|
||||
stb_textedit_prep_selection_at_cursor(state);
|
||||
stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
|
||||
state->cursor = state->select_end = find.first_char + find.length;
|
||||
if (find.length > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) == STB_TEXTEDIT_NEWLINE)
|
||||
state->cursor = state->select_end = state->cursor - 1;
|
||||
state->has_preferred_x = 0;
|
||||
break;
|
||||
}
|
||||
|
651
stb_truetype.h
@ -1,7 +1,7 @@
|
||||
// [ImGui] this is a slightly modified version of stb_truetype.h 1.02
|
||||
// [ImGui] this is a slightly modified version of stb_truetype.h 1.06
|
||||
// [ImGui] we added stbtt_PackFontRangesGatherRects() and stbtt_PackFontRangesRenderIntoRects() and modified stbtt_PackBegin()
|
||||
|
||||
// stb_truetype.h - v1.02 - public domain
|
||||
// stb_truetype.h - v1.06 - public domain
|
||||
// authored from 2009-2014 by Sean Barrett / RAD Game Tools
|
||||
//
|
||||
// This library processes TrueType files:
|
||||
@ -37,12 +37,23 @@
|
||||
// Johan Duparc
|
||||
// Hou Qiming
|
||||
// Fabian "ryg" Giesen
|
||||
// Martins Mozeiko
|
||||
// Cap Petschulat
|
||||
// Omar Cornut
|
||||
// github:aloucks
|
||||
// Peter LaValle
|
||||
//
|
||||
// Misc other:
|
||||
// Ryan Gordon
|
||||
//
|
||||
// VERSION HISTORY
|
||||
//
|
||||
// 1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine)
|
||||
// also more precise AA rasterizer, except if shapes overlap
|
||||
// remove need for STBTT_sort
|
||||
// 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC
|
||||
// 1.04 (2015-04-15) typo in example
|
||||
// 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes
|
||||
// 1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++
|
||||
// 1.01 (2014-12-08) fix subpixel position when oversampling to exactly match
|
||||
// non-oversampled; STBTT_POINT_SIZE for packed case only
|
||||
@ -86,6 +97,9 @@
|
||||
// before the #include of this file. This expands out the actual
|
||||
// implementation into that C/C++ file.
|
||||
//
|
||||
// To make the implementation private to the file that generates the implementation,
|
||||
// #define STBTT_STATIC
|
||||
//
|
||||
// Simple 3D API (don't ship this, but it's fine for tools and quick start)
|
||||
// stbtt_BakeFontBitmap() -- bake a font to a bitmap for use as texture
|
||||
// stbtt_GetBakedQuad() -- compute quad to draw for a given char
|
||||
@ -112,6 +126,15 @@
|
||||
// stbtt_GetFontVMetrics()
|
||||
// stbtt_GetCodepointKernAdvance()
|
||||
//
|
||||
// Starting with version 1.06, the rasterizer was replaced with a new,
|
||||
// faster and generally-more-precise rasterizer. The new rasterizer more
|
||||
// accurately measures pixel coverage for anti-aliasing, except in the case
|
||||
// where multiple shapes overlap, in which case it overestimates the AA pixel
|
||||
// coverage. Thus, anti-aliasing of intersecting shapes may look wrong. If
|
||||
// this turns out to be a problem, you can re-enable the old rasterizer with
|
||||
// #define STBTT_RASTERIZER_VERSION 1
|
||||
// which will incur about a 15% speed hit.
|
||||
//
|
||||
// ADDITIONAL DOCUMENTATION
|
||||
//
|
||||
// Immediately after this block comment are a series of sample programs.
|
||||
@ -211,7 +234,15 @@
|
||||
// Baked bitmap interface 70 LOC /
|
||||
// Font name matching & access 150 LOC ---- 150
|
||||
// C runtime library abstraction 60 LOC ---- 60
|
||||
|
||||
//
|
||||
//
|
||||
// PERFORMANCE MEASUREMENTS FOR 1.06:
|
||||
//
|
||||
// 32-bit 64-bit
|
||||
// Previous release: 8.83 s 7.68 s
|
||||
// Pool allocations: 7.72 s 6.34 s
|
||||
// Inline sort : 6.54 s 5.65 s
|
||||
// New rasterizer : 5.63 s 5.00 s
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@ -225,16 +256,16 @@
|
||||
#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
|
||||
#include "stb_truetype.h"
|
||||
|
||||
char ttf_buffer[1<<20];
|
||||
unsigned char ttf_buffer[1<<20];
|
||||
unsigned char temp_bitmap[512*512];
|
||||
|
||||
stbtt_bakedchar cdata[96]; // ASCII 32..126 is 95 glyphs
|
||||
GLstbtt_uint ftex;
|
||||
GLuint ftex;
|
||||
|
||||
void my_stbtt_initfont(void)
|
||||
{
|
||||
fread(ttf_buffer, 1, 1<<20, fopen("c:/windows/fonts/times.ttf", "rb"));
|
||||
stbtt_BakeFontBitmap(data,0, 32.0, temp_bitmap,512,512, 32,96, cdata); // no guarantee this fits!
|
||||
stbtt_BakeFontBitmap(ttf_buffer,0, 32.0, temp_bitmap,512,512, 32,96, cdata); // no guarantee this fits!
|
||||
// can free ttf_buffer at this point
|
||||
glGenTextures(1, &ftex);
|
||||
glBindTexture(GL_TEXTURE_2D, ftex);
|
||||
@ -246,6 +277,7 @@ void my_stbtt_initfont(void)
|
||||
void my_stbtt_print(float x, float y, char *text)
|
||||
{
|
||||
// assume orthographic projection with units = screen pixels, origin at top left
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, ftex);
|
||||
glBegin(GL_QUADS);
|
||||
while (*text) {
|
||||
@ -321,7 +353,7 @@ int main(int arg, char **argv)
|
||||
stbtt_fontinfo font;
|
||||
int i,j,ascent,baseline,ch=0;
|
||||
float scale, xpos=2; // leave a little padding in case the character extends left
|
||||
char *text = "Heljo World!";
|
||||
char *text = "Heljo World!"; // intentionally misspelled to show 'lj' brokenness
|
||||
|
||||
fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb"));
|
||||
stbtt_InitFont(&font, buffer, 0);
|
||||
@ -379,18 +411,6 @@ int main(int arg, char **argv)
|
||||
typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1];
|
||||
typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1];
|
||||
|
||||
#ifdef STBTT_STATIC
|
||||
#define STBTT_DEF static
|
||||
#else
|
||||
#define STBTT_DEF extern
|
||||
#endif
|
||||
|
||||
// #define your own STBTT_sort() to override this to avoid qsort
|
||||
#ifndef STBTT_sort
|
||||
#include <stdlib.h>
|
||||
#define STBTT_sort(data,num_items,item_size,compare_func) qsort(data,num_items,item_size,compare_func)
|
||||
#endif
|
||||
|
||||
// #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h
|
||||
#ifndef STBTT_ifloor
|
||||
#include <math.h>
|
||||
@ -437,6 +457,12 @@ int main(int arg, char **argv)
|
||||
#ifndef __STB_INCLUDE_STB_TRUETYPE_H__
|
||||
#define __STB_INCLUDE_STB_TRUETYPE_H__
|
||||
|
||||
#ifdef STBTT_STATIC
|
||||
#define STBTT_DEF static
|
||||
#else
|
||||
#define STBTT_DEF extern
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -903,6 +929,10 @@ enum { // languageID for STBTT_PLATFORM_ID_MAC
|
||||
|
||||
typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1];
|
||||
|
||||
#ifndef STBTT_RASTERIZER_VERSION
|
||||
#define STBTT_RASTERIZER_VERSION 2
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// accessors to parse data from file
|
||||
@ -1059,7 +1089,6 @@ STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codep
|
||||
stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1;
|
||||
stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10);
|
||||
stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1;
|
||||
stbtt_uint16 item, offset, start, end;
|
||||
|
||||
// do a binary search of the segments
|
||||
stbtt_uint32 endCount = index_map + 14;
|
||||
@ -1076,8 +1105,8 @@ STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codep
|
||||
// now decrement to bias correctly to find smallest
|
||||
search -= 2;
|
||||
while (entrySelector) {
|
||||
stbtt_uint16 end;
|
||||
searchRange >>= 1;
|
||||
start = ttUSHORT(data + search + searchRange*2 + segcount*2 + 2);
|
||||
end = ttUSHORT(data + search + searchRange*2);
|
||||
if (unicode_codepoint > end)
|
||||
search += searchRange*2;
|
||||
@ -1085,19 +1114,21 @@ STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codep
|
||||
}
|
||||
search += 2;
|
||||
|
||||
item = (stbtt_uint16) ((search - endCount) >> 1);
|
||||
{
|
||||
stbtt_uint16 offset, start;
|
||||
stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1);
|
||||
|
||||
STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item));
|
||||
start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
|
||||
end = ttUSHORT(data + index_map + 14 + 2 + 2*item);
|
||||
if (unicode_codepoint < start)
|
||||
return 0;
|
||||
STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item));
|
||||
start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
|
||||
if (unicode_codepoint < start)
|
||||
return 0;
|
||||
|
||||
offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
|
||||
if (offset == 0)
|
||||
return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item));
|
||||
offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
|
||||
if (offset == 0)
|
||||
return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item));
|
||||
|
||||
return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);
|
||||
return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);
|
||||
}
|
||||
} else if (format == 12 || format == 13) {
|
||||
stbtt_uint32 ngroups = ttULONG(data+index_map+12);
|
||||
stbtt_int32 low,high;
|
||||
@ -1550,42 +1581,129 @@ STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codep
|
||||
stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Rasterizer
|
||||
|
||||
typedef struct stbtt__hheap_chunk
|
||||
{
|
||||
struct stbtt__hheap_chunk *next;
|
||||
} stbtt__hheap_chunk;
|
||||
|
||||
typedef struct stbtt__hheap
|
||||
{
|
||||
struct stbtt__hheap_chunk *head;
|
||||
void *first_free;
|
||||
int num_remaining_in_head_chunk;
|
||||
} stbtt__hheap;
|
||||
|
||||
static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata)
|
||||
{
|
||||
if (hh->first_free) {
|
||||
void *p = hh->first_free;
|
||||
hh->first_free = * (void **) p;
|
||||
return p;
|
||||
} else {
|
||||
if (hh->num_remaining_in_head_chunk == 0) {
|
||||
int count = (size < 32 ? 2000 : size < 128 ? 800 : 100);
|
||||
stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata);
|
||||
if (c == NULL)
|
||||
return NULL;
|
||||
c->next = hh->head;
|
||||
hh->head = c;
|
||||
hh->num_remaining_in_head_chunk = count;
|
||||
}
|
||||
--hh->num_remaining_in_head_chunk;
|
||||
return (char *) (hh->head) + size * hh->num_remaining_in_head_chunk;
|
||||
}
|
||||
}
|
||||
|
||||
static void stbtt__hheap_free(stbtt__hheap *hh, void *p)
|
||||
{
|
||||
*(void **) p = hh->first_free;
|
||||
hh->first_free = p;
|
||||
}
|
||||
|
||||
static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata)
|
||||
{
|
||||
stbtt__hheap_chunk *c = hh->head;
|
||||
while (c) {
|
||||
stbtt__hheap_chunk *n = c->next;
|
||||
STBTT_free(c, userdata);
|
||||
c = n;
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct stbtt__edge {
|
||||
float x0,y0, x1,y1;
|
||||
int invert;
|
||||
} stbtt__edge;
|
||||
|
||||
|
||||
typedef struct stbtt__active_edge
|
||||
{
|
||||
struct stbtt__active_edge *next;
|
||||
#if STBTT_RASTERIZER_VERSION==1
|
||||
int x,dx;
|
||||
float ey;
|
||||
struct stbtt__active_edge *next;
|
||||
int valid;
|
||||
int direction;
|
||||
#elif STBTT_RASTERIZER_VERSION==2
|
||||
float fx,fdx,fdy;
|
||||
float direction;
|
||||
float sy;
|
||||
float ey;
|
||||
#else
|
||||
#error "Unrecognized value of STBTT_RASTERIZER_VERSION"
|
||||
#endif
|
||||
} stbtt__active_edge;
|
||||
|
||||
#define FIXSHIFT 10
|
||||
#define FIX (1 << FIXSHIFT)
|
||||
#define FIXMASK (FIX-1)
|
||||
#if STBTT_RASTERIZER_VERSION == 1
|
||||
#define STBTT_FIXSHIFT 10
|
||||
#define STBTT_FIX (1 << STBTT_FIXSHIFT)
|
||||
#define STBTT_FIXMASK (STBTT_FIX-1)
|
||||
|
||||
static stbtt__active_edge *new_active(stbtt__edge *e, int off_x, float start_point, void *userdata)
|
||||
static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata)
|
||||
{
|
||||
stbtt__active_edge *z = (stbtt__active_edge *) STBTT_malloc(sizeof(*z), userdata); // @TODO: make a pool of these!!!
|
||||
stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
|
||||
float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
|
||||
STBTT_assert(e->y0 <= start_point);
|
||||
if (!z) return z;
|
||||
// round dx down to avoid going too far
|
||||
|
||||
// round dx down to avoid overshooting
|
||||
if (dxdy < 0)
|
||||
z->dx = -STBTT_ifloor(FIX * -dxdy);
|
||||
z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy);
|
||||
else
|
||||
z->dx = STBTT_ifloor(FIX * dxdy);
|
||||
z->x = STBTT_ifloor(FIX * (e->x0 + dxdy * (start_point - e->y0)));
|
||||
z->x -= off_x * FIX;
|
||||
z->dx = STBTT_ifloor(STBTT_FIX * dxdy);
|
||||
|
||||
z->x = STBTT_ifloor(STBTT_FIX * e->x0 + z->dx * (start_point - e->y0)); // use z->dx so when we offset later it's by the same amount
|
||||
z->x -= off_x * STBTT_FIX;
|
||||
|
||||
z->ey = e->y1;
|
||||
z->next = 0;
|
||||
z->valid = e->invert ? 1 : -1;
|
||||
z->direction = e->invert ? 1 : -1;
|
||||
return z;
|
||||
}
|
||||
#elif STBTT_RASTERIZER_VERSION == 2
|
||||
static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata)
|
||||
{
|
||||
stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
|
||||
float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
|
||||
//STBTT_assert(e->y0 <= start_point);
|
||||
if (!z) return z;
|
||||
z->fdx = dxdy;
|
||||
z->fdy = (1/dxdy);
|
||||
z->fx = e->x0 + dxdy * (start_point - e->y0);
|
||||
z->fx -= off_x;
|
||||
z->direction = e->invert ? 1.0f : -1.0f;
|
||||
z->sy = e->y0;
|
||||
z->ey = e->y1;
|
||||
z->next = 0;
|
||||
return z;
|
||||
}
|
||||
#else
|
||||
#error "Unrecognized value of STBTT_RASTERIZER_VERSION"
|
||||
#endif
|
||||
|
||||
#if STBTT_RASTERIZER_VERSION == 1
|
||||
// note: this routine clips fills that extend off the edges... ideally this
|
||||
// wouldn't happen, but it could happen if the truetype glyph bounding boxes
|
||||
// are wrong, or if the user supplies a too-small bitmap
|
||||
@ -1597,26 +1715,26 @@ static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__ac
|
||||
while (e) {
|
||||
if (w == 0) {
|
||||
// if we're currently at zero, we need to record the edge start point
|
||||
x0 = e->x; w += e->valid;
|
||||
x0 = e->x; w += e->direction;
|
||||
} else {
|
||||
int x1 = e->x; w += e->valid;
|
||||
int x1 = e->x; w += e->direction;
|
||||
// if we went to zero, we need to draw
|
||||
if (w == 0) {
|
||||
int i = x0 >> FIXSHIFT;
|
||||
int j = x1 >> FIXSHIFT;
|
||||
int i = x0 >> STBTT_FIXSHIFT;
|
||||
int j = x1 >> STBTT_FIXSHIFT;
|
||||
|
||||
if (i < len && j >= 0) {
|
||||
if (i == j) {
|
||||
// x0,x1 are the same pixel, so compute combined coverage
|
||||
scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> FIXSHIFT);
|
||||
scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT);
|
||||
} else {
|
||||
if (i >= 0) // add antialiasing for x0
|
||||
scanline[i] = scanline[i] + (stbtt_uint8) (((FIX - (x0 & FIXMASK)) * max_weight) >> FIXSHIFT);
|
||||
scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT);
|
||||
else
|
||||
i = -1; // clip
|
||||
|
||||
if (j < len) // add antialiasing for x1
|
||||
scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & FIXMASK) * max_weight) >> FIXSHIFT);
|
||||
scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT);
|
||||
else
|
||||
j = len; // clip
|
||||
|
||||
@ -1633,6 +1751,7 @@ static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__ac
|
||||
|
||||
static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
|
||||
{
|
||||
stbtt__hheap hh = { 0 };
|
||||
stbtt__active_edge *active = NULL;
|
||||
int y,j=0;
|
||||
int max_weight = (255 / vsubsample); // weight per vertical scanline
|
||||
@ -1660,9 +1779,9 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e,
|
||||
stbtt__active_edge * z = *step;
|
||||
if (z->ey <= scan_y) {
|
||||
*step = z->next; // delete from list
|
||||
STBTT_assert(z->valid);
|
||||
z->valid = 0;
|
||||
STBTT_free(z, userdata);
|
||||
STBTT_assert(z->direction);
|
||||
z->direction = 0;
|
||||
stbtt__hheap_free(&hh, z);
|
||||
} else {
|
||||
z->x += z->dx; // advance to position for current scanline
|
||||
step = &((*step)->next); // advance through list
|
||||
@ -1691,7 +1810,7 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e,
|
||||
// insert all edges that start before the center of this scanline -- omit ones that also end on this scanline
|
||||
while (e->y0 <= scan_y) {
|
||||
if (e->y1 > scan_y) {
|
||||
stbtt__active_edge *z = new_active(e, off_x, scan_y, userdata);
|
||||
stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata);
|
||||
// find insertion point
|
||||
if (active == NULL)
|
||||
active = z;
|
||||
@ -1722,24 +1841,378 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e,
|
||||
++j;
|
||||
}
|
||||
|
||||
while (active) {
|
||||
stbtt__active_edge *z = active;
|
||||
active = active->next;
|
||||
STBTT_free(z, userdata);
|
||||
}
|
||||
stbtt__hheap_cleanup(&hh, userdata);
|
||||
|
||||
if (scanline != scanline_data)
|
||||
STBTT_free(scanline, userdata);
|
||||
}
|
||||
|
||||
static int stbtt__edge_compare(const void *p, const void *q)
|
||||
{
|
||||
stbtt__edge *a = (stbtt__edge *) p;
|
||||
stbtt__edge *b = (stbtt__edge *) q;
|
||||
#elif STBTT_RASTERIZER_VERSION == 2
|
||||
|
||||
if (a->y0 < b->y0) return -1;
|
||||
if (a->y0 > b->y0) return 1;
|
||||
return 0;
|
||||
// the edge passed in here does not cross the vertical line at x or the vertical line at x+1
|
||||
// (i.e. it has already been clipped to those)
|
||||
static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edge *e, float x0, float y0, float x1, float y1)
|
||||
{
|
||||
if (y0 == y1) return;
|
||||
assert(y0 < y1);
|
||||
assert(e->sy <= e->ey);
|
||||
if (y0 > e->ey) return;
|
||||
if (y1 < e->sy) return;
|
||||
if (y0 < e->sy) {
|
||||
x0 += (x1-x0) * (e->sy - y0) / (y1-y0);
|
||||
y0 = e->sy;
|
||||
}
|
||||
if (y1 > e->ey) {
|
||||
x1 += (x1-x0) * (e->ey - y1) / (y1-y0);
|
||||
y1 = e->ey;
|
||||
}
|
||||
|
||||
if (x0 == x)
|
||||
assert(x1 <= x+1);
|
||||
else if (x0 == x+1)
|
||||
assert(x1 >= x);
|
||||
else if (x0 <= x)
|
||||
assert(x1 <= x);
|
||||
else if (x0 >= x+1)
|
||||
assert(x1 >= x+1);
|
||||
else
|
||||
assert(x1 >= x && x1 <= x+1);
|
||||
|
||||
if (x0 <= x && x1 <= x)
|
||||
scanline[x] += e->direction * (y1-y0);
|
||||
else if (x0 >= x+1 && x1 >= x+1)
|
||||
;
|
||||
else {
|
||||
assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1);
|
||||
scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2); // coverage = 1 - average x position
|
||||
}
|
||||
}
|
||||
|
||||
static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top)
|
||||
{
|
||||
float y_bottom = y_top+1;
|
||||
|
||||
while (e) {
|
||||
// brute force every pixel
|
||||
|
||||
// compute intersection points with top & bottom
|
||||
assert(e->ey >= y_top);
|
||||
|
||||
if (e->fdx == 0) {
|
||||
float x0 = e->fx;
|
||||
if (x0 < len) {
|
||||
if (x0 >= 0) {
|
||||
stbtt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom);
|
||||
stbtt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom);
|
||||
} else {
|
||||
stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
float x0 = e->fx;
|
||||
float dx = e->fdx;
|
||||
float xb = x0 + dx;
|
||||
float x_top, x_bottom;
|
||||
float y0,y1;
|
||||
float dy = e->fdy;
|
||||
assert(e->sy <= y_bottom && e->ey >= y_top);
|
||||
|
||||
// compute endpoints of line segment clipped to this scanline (if the
|
||||
// line segment starts on this scanline. x0 is the intersection of the
|
||||
// line with y_top, but that may be off the line segment.
|
||||
if (e->sy > y_top) {
|
||||
x_top = x0 + dx * (e->sy - y_top);
|
||||
y0 = e->sy;
|
||||
} else {
|
||||
x_top = x0;
|
||||
y0 = y_top;
|
||||
}
|
||||
if (e->ey < y_bottom) {
|
||||
x_bottom = x0 + dx * (e->ey - y_top);
|
||||
y1 = e->ey;
|
||||
} else {
|
||||
x_bottom = xb;
|
||||
y1 = y_bottom;
|
||||
}
|
||||
|
||||
if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) {
|
||||
// from here on, we don't have to range check x values
|
||||
|
||||
if ((int) x_top == (int) x_bottom) {
|
||||
float height;
|
||||
// simple case, only spans one pixel
|
||||
int x = (int) x_top;
|
||||
height = y1 - y0;
|
||||
assert(x >= 0 && x < len);
|
||||
scanline[x] += e->direction * (1-((x_top - x) + (x_bottom-x))/2) * height;
|
||||
scanline_fill[x] += e->direction * height; // everything right of this pixel is filled
|
||||
} else {
|
||||
int x,x1,x2;
|
||||
float y_crossing, step, sign, area;
|
||||
// covers 2+ pixels
|
||||
if (x_top > x_bottom) {
|
||||
// flip scanline vertically; signed area is the same
|
||||
float t;
|
||||
y0 = y_bottom - (y0 - y_top);
|
||||
y1 = y_bottom - (y1 - y_top);
|
||||
t = y0, y0 = y1, y1 = t;
|
||||
t = x_bottom, x_bottom = x_top, x_top = t;
|
||||
dx = -dx;
|
||||
dy = -dy;
|
||||
t = x0, x0 = xb, xb = t;
|
||||
}
|
||||
|
||||
x1 = (int) x_top;
|
||||
x2 = (int) x_bottom;
|
||||
// compute intersection with y axis at x1+1
|
||||
y_crossing = (x1+1 - x0) * dy + y_top;
|
||||
|
||||
sign = e->direction;
|
||||
// area of the rectangle covered from y0..y_crossing
|
||||
area = sign * (y_crossing-y0);
|
||||
// area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing)
|
||||
scanline[x1] += area * (1-((x_top - x1)+(x1+1-x1))/2);
|
||||
|
||||
step = sign * dy;
|
||||
for (x = x1+1; x < x2; ++x) {
|
||||
scanline[x] += area + step/2;
|
||||
area += step;
|
||||
}
|
||||
y_crossing += dy * (x2 - (x1+1));
|
||||
|
||||
assert(fabs(area) <= 1.01f);
|
||||
|
||||
scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (y1-y_crossing);
|
||||
|
||||
scanline_fill[x2] += sign * (y1-y0);
|
||||
}
|
||||
} else {
|
||||
// if edge goes outside of box we're drawing, we require
|
||||
// clipping logic. since this does not match the intended use
|
||||
// of this library, we use a different, very slow brute
|
||||
// force implementation
|
||||
int x;
|
||||
for (x=0; x < len; ++x) {
|
||||
// cases:
|
||||
//
|
||||
// there can be up to two intersections with the pixel. any intersection
|
||||
// with left or right edges can be handled by splitting into two (or three)
|
||||
// regions. intersections with top & bottom do not necessitate case-wise logic.
|
||||
float y0,y1;
|
||||
float y_cur = y_top, x_cur = x0;
|
||||
// x = e->x + e->dx * (y-y_top)
|
||||
// (y-y_top) = (x - e->x) / e->dx
|
||||
// y = (x - e->x) / e->dx + y_top
|
||||
y0 = (x - x0) / dx + y_top;
|
||||
y1 = (x+1 - x0) / dx + y_top;
|
||||
|
||||
if (y0 < y1) {
|
||||
if (y0 > y_top && y0 < y_bottom) {
|
||||
stbtt__handle_clipped_edge(scanline,x,e, x_cur,y_cur, (float) x,y0);
|
||||
y_cur = y0;
|
||||
x_cur = (float) x;
|
||||
}
|
||||
if (y1 >= y_cur && y1 < y_bottom) {
|
||||
stbtt__handle_clipped_edge(scanline,x,e, x_cur,y_cur, (float) x+1,y1);
|
||||
y_cur = y1;
|
||||
x_cur = (float) x+1;
|
||||
}
|
||||
} else {
|
||||
if (y1 >= y_cur && y1 < y_bottom) {
|
||||
stbtt__handle_clipped_edge(scanline,x,e, x_cur,y_cur, (float) x+1,y1);
|
||||
y_cur = y1;
|
||||
x_cur = (float) x+1;
|
||||
}
|
||||
if (y0 > y_top && y0 < y_bottom) {
|
||||
stbtt__handle_clipped_edge(scanline,x,e, x_cur,y_cur, (float) x,y0);
|
||||
y_cur = y0;
|
||||
x_cur = (float) x;
|
||||
}
|
||||
}
|
||||
stbtt__handle_clipped_edge(scanline,x,e, x_cur,y_cur, xb,y_bottom);
|
||||
}
|
||||
}
|
||||
}
|
||||
e = e->next;
|
||||
}
|
||||
}
|
||||
|
||||
// directly AA rasterize edges w/o supersampling
|
||||
static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
|
||||
{
|
||||
(void)vsubsample;
|
||||
stbtt__hheap hh = { 0 };
|
||||
stbtt__active_edge *active = NULL;
|
||||
int y,j=0, i;
|
||||
float scanline_data[129], *scanline, *scanline2;
|
||||
|
||||
if (result->w > 64)
|
||||
scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata);
|
||||
else
|
||||
scanline = scanline_data;
|
||||
|
||||
scanline2 = scanline + result->w;
|
||||
|
||||
y = off_y;
|
||||
e[n].y0 = (float) (off_y + result->h) + 1;
|
||||
|
||||
while (j < result->h) {
|
||||
// find center of pixel for this scanline
|
||||
float scan_y_top = y + 0.0f;
|
||||
float scan_y_bottom = y + 1.0f;
|
||||
stbtt__active_edge **step = &active;
|
||||
|
||||
STBTT_memset(scanline , 0, result->w*sizeof(scanline[0]));
|
||||
STBTT_memset(scanline2, 0, (result->w+1)*sizeof(scanline[0]));
|
||||
|
||||
// update all active edges;
|
||||
// remove all active edges that terminate before the top of this scanline
|
||||
while (*step) {
|
||||
stbtt__active_edge * z = *step;
|
||||
if (z->ey <= scan_y_top) {
|
||||
*step = z->next; // delete from list
|
||||
STBTT_assert(z->direction);
|
||||
z->direction = 0;
|
||||
stbtt__hheap_free(&hh, z);
|
||||
} else {
|
||||
step = &((*step)->next); // advance through list
|
||||
}
|
||||
}
|
||||
|
||||
// insert all edges that start before the bottom of this scanline
|
||||
while (e->y0 <= scan_y_bottom) {
|
||||
stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata);
|
||||
assert(z->ey >= scan_y_top);
|
||||
// insert at front
|
||||
z->next = active;
|
||||
active = z;
|
||||
++e;
|
||||
}
|
||||
|
||||
// now process all active edges
|
||||
if (active)
|
||||
stbtt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top);
|
||||
|
||||
{
|
||||
float sum = 0;
|
||||
for (i=0; i < result->w; ++i) {
|
||||
float k;
|
||||
int m;
|
||||
sum += scanline2[i];
|
||||
k = scanline[i] + sum;
|
||||
k = (float) fabs(k)*255 + 0.5f;
|
||||
m = (int) k;
|
||||
if (m > 255) m = 255;
|
||||
result->pixels[j*result->stride + i] = (unsigned char) m;
|
||||
}
|
||||
}
|
||||
// advance all the edges
|
||||
step = &active;
|
||||
while (*step) {
|
||||
stbtt__active_edge *z = *step;
|
||||
z->fx += z->fdx; // advance to position for current scanline
|
||||
step = &((*step)->next); // advance through list
|
||||
}
|
||||
|
||||
++y;
|
||||
++j;
|
||||
}
|
||||
|
||||
stbtt__hheap_cleanup(&hh, userdata);
|
||||
|
||||
if (scanline != scanline_data)
|
||||
STBTT_free(scanline, userdata);
|
||||
}
|
||||
#else
|
||||
#error "Unrecognized value of STBTT_RASTERIZER_VERSION"
|
||||
#endif
|
||||
|
||||
#define STBTT__COMPARE(a,b) ((a)->y0 < (b)->y0)
|
||||
|
||||
static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n)
|
||||
{
|
||||
int i,j;
|
||||
for (i=1; i < n; ++i) {
|
||||
stbtt__edge t = p[i], *a = &t;
|
||||
j = i;
|
||||
while (j > 0) {
|
||||
stbtt__edge *b = &p[j-1];
|
||||
int c = STBTT__COMPARE(a,b);
|
||||
if (!c) break;
|
||||
p[j] = p[j-1];
|
||||
--j;
|
||||
}
|
||||
if (i != j)
|
||||
p[j] = t;
|
||||
}
|
||||
}
|
||||
|
||||
static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n)
|
||||
{
|
||||
/* threshhold for transitioning to insertion sort */
|
||||
while (n > 12) {
|
||||
stbtt__edge t;
|
||||
int c01,c12,c,m,i,j;
|
||||
|
||||
/* compute median of three */
|
||||
m = n >> 1;
|
||||
c01 = STBTT__COMPARE(&p[0],&p[m]);
|
||||
c12 = STBTT__COMPARE(&p[m],&p[n-1]);
|
||||
/* if 0 >= mid >= end, or 0 < mid < end, then use mid */
|
||||
if (c01 != c12) {
|
||||
/* otherwise, we'll need to swap something else to middle */
|
||||
int z;
|
||||
c = STBTT__COMPARE(&p[0],&p[n-1]);
|
||||
/* 0>mid && mid<n: 0>n => n; 0<n => 0 */
|
||||
/* 0<mid && mid>n: 0>n => 0; 0<n => n */
|
||||
z = (c == c12) ? 0 : n-1;
|
||||
t = p[z];
|
||||
p[z] = p[m];
|
||||
p[m] = t;
|
||||
}
|
||||
/* now p[m] is the median-of-three */
|
||||
/* swap it to the beginning so it won't move around */
|
||||
t = p[0];
|
||||
p[0] = p[m];
|
||||
p[m] = t;
|
||||
|
||||
/* partition loop */
|
||||
i=1;
|
||||
j=n-1;
|
||||
for(;;) {
|
||||
/* handling of equality is crucial here */
|
||||
/* for sentinels & efficiency with duplicates */
|
||||
for (;;++i) {
|
||||
if (!STBTT__COMPARE(&p[i], &p[0])) break;
|
||||
}
|
||||
for (;;--j) {
|
||||
if (!STBTT__COMPARE(&p[0], &p[j])) break;
|
||||
}
|
||||
/* make sure we haven't crossed */
|
||||
if (i >= j) break;
|
||||
t = p[i];
|
||||
p[i] = p[j];
|
||||
p[j] = t;
|
||||
|
||||
++i;
|
||||
--j;
|
||||
}
|
||||
/* recurse on smaller side, iterate on larger */
|
||||
if (j < (n-i)) {
|
||||
stbtt__sort_edges_quicksort(p,j);
|
||||
p = p+i;
|
||||
n = n-i;
|
||||
} else {
|
||||
stbtt__sort_edges_quicksort(p+i, n-i);
|
||||
n = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void stbtt__sort_edges(stbtt__edge *p, int n)
|
||||
{
|
||||
stbtt__sort_edges_quicksort(p, n);
|
||||
stbtt__sort_edges_ins_sort(p, n);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
@ -1752,7 +2225,13 @@ static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcou
|
||||
float y_scale_inv = invert ? -scale_y : scale_y;
|
||||
stbtt__edge *e;
|
||||
int n,i,j,k,m;
|
||||
#if STBTT_RASTERIZER_VERSION == 1
|
||||
int vsubsample = result->h < 8 ? 15 : 5;
|
||||
#elif STBTT_RASTERIZER_VERSION == 2
|
||||
int vsubsample = 1;
|
||||
#else
|
||||
#error "Unrecognized value of STBTT_RASTERIZER_VERSION"
|
||||
#endif
|
||||
// vsubsample should divide 255 evenly; otherwise we won't reach full opacity
|
||||
|
||||
// now we have to blow out the windings into explicit edge lists
|
||||
@ -1789,7 +2268,8 @@ static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcou
|
||||
}
|
||||
|
||||
// now sort the edges by their highest point (should snap to integer, and then by x)
|
||||
STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare);
|
||||
//STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare);
|
||||
stbtt__sort_edges(e, n);
|
||||
|
||||
// now, traverse the scanlines and find the intersections on each scanline, use xor winding rule
|
||||
stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata);
|
||||
@ -2054,8 +2534,8 @@ STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int
|
||||
float d3d_bias = opengl_fillrule ? 0 : -0.5f;
|
||||
float ipw = 1.0f / pw, iph = 1.0f / ph;
|
||||
stbtt_bakedchar *b = chardata + char_index;
|
||||
int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5);
|
||||
int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5);
|
||||
int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f);
|
||||
int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f);
|
||||
|
||||
q->x0 = round_x + d3d_bias;
|
||||
q->y0 = round_y + d3d_bias;
|
||||
@ -2209,7 +2689,7 @@ static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_i
|
||||
for (j=0; j < h; ++j) {
|
||||
int i;
|
||||
unsigned int total;
|
||||
memset(buffer, 0, kernel_width);
|
||||
STBTT_memset(buffer, 0, kernel_width);
|
||||
|
||||
total = 0;
|
||||
|
||||
@ -2263,7 +2743,7 @@ static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_i
|
||||
for (j=0; j < w; ++j) {
|
||||
int i;
|
||||
unsigned int total;
|
||||
memset(buffer, 0, kernel_width);
|
||||
STBTT_memset(buffer, 0, kernel_width);
|
||||
|
||||
total = 0;
|
||||
|
||||
@ -2333,18 +2813,14 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, stbtt_fon
|
||||
for (j=0; j < ranges[i].num_chars_in_range; ++j) {
|
||||
int x0,y0,x1,y1;
|
||||
int glyph = stbtt_FindGlyphIndex(info,ranges[i].first_unicode_char_in_range + j);
|
||||
if (glyph) {
|
||||
stbtt_GetGlyphBitmapBoxSubpixel(info,glyph,
|
||||
scale * spc->h_oversample,
|
||||
scale * spc->v_oversample,
|
||||
0,0,
|
||||
&x0,&y0,&x1,&y1);
|
||||
rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1);
|
||||
rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1);
|
||||
} else {
|
||||
rects[k].w = rects[k].h = 1;
|
||||
}
|
||||
++k;
|
||||
stbtt_GetGlyphBitmapBoxSubpixel(info,glyph,
|
||||
scale * spc->h_oversample,
|
||||
scale * spc->v_oversample,
|
||||
0,0,
|
||||
&x0,&y0,&x1,&y1);
|
||||
rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1);
|
||||
rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1);
|
||||
++k;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2453,6 +2929,7 @@ STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontd
|
||||
|
||||
return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects);
|
||||
|
||||
STBTT_free(rects, spc->user_allocator_context);
|
||||
return return_value;
|
||||
}
|
||||
|
||||
@ -2473,8 +2950,8 @@ STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, i
|
||||
stbtt_packedchar *b = chardata + char_index;
|
||||
|
||||
if (align_to_integer) {
|
||||
float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5);
|
||||
float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5);
|
||||
float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f);
|
||||
float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5f);
|
||||
q->x0 = x;
|
||||
q->y0 = y;
|
||||
q->x1 = x + b->xoff2 - b->xoff;
|
||||
|
Before Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 9.5 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 7.8 KiB |
Before Width: | Height: | Size: 7.1 KiB |
Before Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 5.9 KiB |
Before Width: | Height: | Size: 16 KiB |