The Omega Update(TM) Part 3 (Rendering)

This commit is contained in:
2025-08-10 01:27:06 -04:00
parent b9c9105621
commit a48c72357a
26 changed files with 1250 additions and 1004 deletions

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 B

View File

@@ -1,256 +0,0 @@
unsigned char atlas_png[] = {
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x68,
0x04, 0x03, 0x00, 0x00, 0x01, 0x8b, 0xe2, 0xd8, 0xf0, 0x00, 0x00, 0x00,
0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x12, 0x00, 0x00, 0x0b,
0x12, 0x01, 0xd2, 0xdd, 0x7e, 0xfc, 0x00, 0x00, 0x00, 0x0f, 0x50, 0x4c,
0x54, 0x45, 0x00, 0x00, 0x00, 0x60, 0x60, 0x60, 0xff, 0xff, 0xff, 0x60,
0x60, 0x60, 0xff, 0xff, 0xff, 0xb1, 0x03, 0xf0, 0x56, 0x00, 0x00, 0x00,
0x03, 0x74, 0x52, 0x4e, 0x53, 0x00, 0x00, 0x00, 0xfa, 0x76, 0xc4, 0xde,
0x00, 0x00, 0x04, 0x90, 0x49, 0x44, 0x41, 0x54, 0x58, 0xc3, 0xdd, 0x97,
0x6b, 0x6e, 0x24, 0x39, 0x0e, 0x84, 0x3f, 0x2c, 0xe3, 0x40, 0x1a, 0x48,
0x07, 0x88, 0x86, 0xe2, 0xfe, 0x67, 0x9a, 0x1f, 0x7a, 0x54, 0x96, 0xdb,
0x9e, 0x71, 0xf7, 0x0c, 0xb0, 0x8b, 0x15, 0x0a, 0x56, 0xca, 0x4c, 0x8a,
0xef, 0x20, 0x13, 0xd6, 0x92, 0x4a, 0xd2, 0x7e, 0x24, 0x03, 0x25, 0x5c,
0x1a, 0xa0, 0x7b, 0x2a, 0x24, 0xe8, 0xad, 0x01, 0x8c, 0xc6, 0x87, 0x4d,
0xf7, 0x74, 0x56, 0xe8, 0x8c, 0x7b, 0x6a, 0xe0, 0xe7, 0xd5, 0x96, 0xd7,
0xb3, 0xf1, 0xc4, 0x86, 0x0e, 0x18, 0x72, 0x37, 0xbd, 0x9d, 0x30, 0x20,
0xfd, 0x20, 0x0a, 0x26, 0x48, 0xb2, 0xa8, 0xbe, 0xf4, 0x77, 0x0d, 0x28,
0x61, 0x4c, 0x59, 0x83, 0x68, 0x00, 0x46, 0x22, 0xa0, 0xa9, 0x60, 0x14,
0x81, 0x88, 0x2c, 0x60, 0x30, 0x0a, 0x0d, 0x2c, 0x1d, 0x43, 0x1b, 0x48,
0x8c, 0x2c, 0x53, 0x04, 0xdc, 0x43, 0x5e, 0x87, 0x24, 0x09, 0xef, 0xaf,
0x95, 0x1b, 0xed, 0xe9, 0xb1, 0xbb, 0xec, 0x84, 0x24, 0x45, 0x20, 0x4a,
0x26, 0xbd, 0xab, 0x4d, 0x83, 0xd3, 0x44, 0xb5, 0xeb, 0x8c, 0xbb, 0xd4,
0xa6, 0x8d, 0xad, 0x06, 0xb4, 0x64, 0x98, 0xc8, 0x4a, 0x90, 0xcb, 0xae,
0x36, 0x7f, 0x12, 0xc3, 0x34, 0x41, 0xb1, 0x82, 0xf1, 0x72, 0x8b, 0xbc,
0x7e, 0x11, 0xc1, 0xc1, 0x3f, 0x29, 0x87, 0x83, 0x86, 0x20, 0xd0, 0x70,
0x43, 0x4d, 0x06, 0x44, 0x68, 0xc8, 0x22, 0xa1, 0xf7, 0xf3, 0x36, 0x70,
0x52, 0xe4, 0xeb, 0x43, 0xde, 0x28, 0xbe, 0x87, 0xed, 0xb7, 0x4d, 0xd1,
0xdf, 0xdc, 0xf6, 0xca, 0x90, 0x27, 0x09, 0x40, 0x2b, 0x3b, 0x34, 0x96,
0x9e, 0x52, 0x92, 0x95, 0x27, 0xf1, 0x8a, 0x79, 0x8c, 0x82, 0x95, 0x44,
0x82, 0xea, 0xbd, 0xcb, 0x9a, 0xe2, 0x79, 0xf1, 0x89, 0xf8, 0x7b, 0xda,
0x86, 0x4a, 0x5c, 0x49, 0x5b, 0x72, 0x02, 0xcc, 0x6e, 0xf5, 0x0c, 0x1d,
0x79, 0x2e, 0xa9, 0x2c, 0x90, 0xad, 0xf4, 0x29, 0x64, 0xa5, 0xa6, 0xba,
0xd0, 0x75, 0xb2, 0xe6, 0x8e, 0xc0, 0x6c, 0xc8, 0x5b, 0xee, 0xd3, 0x0e,
0xdf, 0xbf, 0x1d, 0x35, 0x8e, 0x6b, 0xa4, 0xc4, 0x4a, 0x82, 0x62, 0xe4,
0x4c, 0x05, 0xdd, 0x12, 0x78, 0xfa, 0x4e, 0xb1, 0x25, 0x1b, 0xd2, 0x88,
0xa9, 0x75, 0x71, 0x01, 0xdd, 0x30, 0x0d, 0x0c, 0x98, 0x60, 0x0c, 0x95,
0x86, 0x68, 0x35, 0xa7, 0x35, 0x66, 0x23, 0x6d, 0x11, 0x14, 0x50, 0x2d,
0x76, 0xcd, 0x55, 0x6d, 0x8a, 0x02, 0xd5, 0x3f, 0x3a, 0x08, 0x45, 0x66,
0x24, 0x69, 0x0f, 0xf7, 0x5d, 0x9f, 0x1e, 0x02, 0xbf, 0x4b, 0x58, 0xe6,
0x7c, 0x24, 0xe4, 0xae, 0x9f, 0x39, 0xbc, 0xca, 0xf9, 0x13, 0x19, 0xd7,
0xd9, 0x5f, 0x0a, 0xaf, 0xc4, 0x9f, 0x12, 0x28, 0xf3, 0xa9, 0x81, 0x5f,
0xaf, 0x67, 0x68, 0xb3, 0xe2, 0xad, 0x4e, 0x43, 0xc8, 0xc9, 0x0f, 0x6f,
0x2b, 0x8c, 0x1a, 0x4a, 0x37, 0xc6, 0x5e, 0xff, 0x60, 0x21, 0xef, 0xda,
0x8d, 0x85, 0x93, 0x78, 0x0a, 0xfa, 0xe8, 0x8d, 0x61, 0xe4, 0x95, 0xf5,
0x4e, 0xe6, 0xaa, 0xee, 0xde, 0x18, 0xc7, 0x76, 0x59, 0x8c, 0xfc, 0xb8,
0x6a, 0x86, 0xe3, 0x94, 0x6f, 0x28, 0xce, 0x85, 0x31, 0x3d, 0x6c, 0x51,
0xd2, 0x2a, 0x2b, 0xaf, 0x88, 0x81, 0x61, 0xd4, 0x87, 0x01, 0x0b, 0x99,
0xe1, 0xcd, 0xd5, 0x07, 0xb3, 0x4f, 0xaf, 0x6a, 0xb7, 0xdd, 0x64, 0xab,
0x19, 0x87, 0xe1, 0xd1, 0x27, 0xd0, 0x2c, 0x6c, 0x69, 0xc5, 0x50, 0x32,
0x63, 0x76, 0x83, 0x3c, 0x5c, 0xc6, 0xdd, 0xab, 0x72, 0x32, 0xd1, 0x1c,
0x14, 0x43, 0xf2, 0xe8, 0x2f, 0x80, 0x65, 0x29, 0x00, 0x32, 0xe3, 0x59,
0x51, 0x7f, 0x15, 0x0f, 0x9f, 0xaa, 0xb9, 0xf7, 0x54, 0x43, 0x1e, 0xbb,
0xa7, 0x40, 0x76, 0xbd, 0xc3, 0x68, 0x04, 0x6c, 0x16, 0x57, 0x56, 0x0d,
0x9a, 0x9a, 0x2c, 0x82, 0xee, 0x55, 0xf6, 0xe9, 0x77, 0x83, 0x38, 0xbe,
0x3a, 0xda, 0xaf, 0xb2, 0x0f, 0x0b, 0x8c, 0xe2, 0x0d, 0xca, 0x47, 0xdb,
0x38, 0xce, 0x0e, 0x67, 0xa8, 0xfc, 0x8c, 0x41, 0x6f, 0x21, 0x39, 0x5d,
0xa9, 0xed, 0x72, 0x5e, 0xc5, 0xb9, 0x6c, 0x09, 0x10, 0x6b, 0x42, 0xcd,
0xa5, 0x94, 0x88, 0x77, 0x67, 0x12, 0x35, 0xa7, 0xc7, 0x98, 0x30, 0x59,
0x1c, 0x95, 0x79, 0x10, 0xa7, 0x39, 0x41, 0x99, 0xa7, 0x3e, 0x8e, 0x0e,
0xad, 0x65, 0x0e, 0x90, 0x97, 0x65, 0xba, 0x39, 0xdd, 0x56, 0x22, 0x0c,
0xb6, 0xc9, 0xfd, 0x13, 0x87, 0x5b, 0xa6, 0xf7, 0xde, 0x3f, 0xb1, 0x01,
0x92, 0xcc, 0xff, 0x19, 0x42, 0xfc, 0x39, 0x21, 0xba, 0x15, 0xf4, 0x4e,
0xf0, 0xc5, 0xf5, 0x27, 0xe1, 0xa2, 0x92, 0xbf, 0x4b, 0xf8, 0xf2, 0xaa,
0xbf, 0x12, 0xfe, 0xa5, 0xba, 0xff, 0xc4, 0x25, 0x7a, 0x87, 0xc4, 0xc7,
0xe4, 0xf2, 0xce, 0xf0, 0x20, 0xa8, 0x7d, 0x41, 0x78, 0x07, 0x3f, 0x3e,
0x01, 0xd4, 0x31, 0xef, 0x64, 0x70, 0x5a, 0x78, 0x4c, 0x25, 0xc9, 0x1f,
0x2f, 0x8c, 0x46, 0xc7, 0x67, 0xfb, 0xc2, 0xae, 0x05, 0x8b, 0x64, 0x41,
0xa4, 0x92, 0x64, 0xc6, 0x0b, 0xa0, 0x59, 0xe7, 0xc5, 0xb1, 0x7b, 0xa2,
0x56, 0x93, 0x90, 0x51, 0x90, 0xcf, 0x0b, 0x6b, 0x12, 0x82, 0xea, 0x23,
0x99, 0xbd, 0xbd, 0x33, 0x4c, 0xd0, 0xae, 0xd1, 0xc3, 0x50, 0xd9, 0xda,
0x56, 0xef, 0xbd, 0x37, 0x60, 0x58, 0x73, 0x69, 0xb2, 0x8d, 0xc9, 0x02,
0xda, 0x24, 0xf9, 0x21, 0x33, 0x96, 0xdf, 0xaa, 0xaa, 0x7a, 0x15, 0x8a,
0x41, 0xf1, 0xcb, 0x68, 0x76, 0xff, 0x7a, 0xcc, 0xc8, 0xbb, 0xd7, 0x54,
0xb1, 0xba, 0x33, 0x95, 0x46, 0xf8, 0xc7, 0xab, 0x3e, 0x04, 0xf7, 0x9e,
0xef, 0x8c, 0x96, 0x0f, 0x4d, 0x7d, 0x25, 0xd9, 0x64, 0x4d, 0x0c, 0x23,
0x1f, 0xd3, 0x60, 0x07, 0xb2, 0x92, 0xa4, 0x51, 0xe9, 0x7d, 0x24, 0x6d,
0x8f, 0x6a, 0x54, 0x76, 0x42, 0x79, 0xb4, 0x9a, 0x82, 0x35, 0x78, 0x42,
0xcd, 0x31, 0xe6, 0x1c, 0x4d, 0xb3, 0x8f, 0xf4, 0xe1, 0xc3, 0x70, 0xe2,
0x13, 0x5b, 0xa7, 0x2d, 0x24, 0x09, 0x65, 0xb5, 0xb2, 0x9a, 0xa6, 0x02,
0x87, 0xe1, 0x11, 0x1f, 0x4f, 0x18, 0xb2, 0xcc, 0x98, 0xc8, 0x50, 0x73,
0x81, 0x71, 0xd2, 0x7b, 0x5f, 0x83, 0xa0, 0xc6, 0x34, 0x09, 0xd5, 0x97,
0x4f, 0xcf, 0xa4, 0xee, 0x8f, 0x1d, 0x62, 0xcf, 0x13, 0x4d, 0xad, 0x4c,
0x4f, 0x12, 0xda, 0x6e, 0xc2, 0xbc, 0xf6, 0x6f, 0x34, 0x4f, 0xbf, 0xef,
0x5b, 0xa4, 0x9c, 0xdd, 0xb7, 0xd7, 0xfe, 0x1c, 0xc0, 0x6f, 0xf5, 0xf4,
0xc6, 0xc9, 0xfb, 0x3d, 0x00, 0x9c, 0x79, 0xc6, 0x3c, 0xe5, 0x6f, 0x2c,
0x56, 0xeb, 0xed, 0x26, 0x97, 0x80, 0xb1, 0x18, 0x9f, 0xb8, 0xf3, 0x78,
0x40, 0xab, 0x1b, 0xe4, 0xe2, 0x88, 0x32, 0xce, 0x88, 0x75, 0x24, 0xec,
0xd4, 0xd6, 0x7e, 0x7f, 0x00, 0x4a, 0x23, 0xda, 0x83, 0x28, 0x9c, 0x31,
0xc3, 0xbb, 0x0b, 0x5a, 0x7e, 0x7d, 0x21, 0x8d, 0x2d, 0xdb, 0xbb, 0x84,
0x6f, 0x47, 0x7c, 0x39, 0x70, 0x4b, 0x58, 0x4a, 0x8c, 0xfb, 0xf4, 0x60,
0xf0, 0xc3, 0x81, 0x3a, 0x36, 0x18, 0xa8, 0x61, 0xfe, 0xc5, 0x55, 0x79,
0x9b, 0xfd, 0xeb, 0x60, 0xc7, 0x09, 0x5d, 0xdf, 0x65, 0x3f, 0x97, 0xf7,
0xe6, 0xca, 0x9d, 0xca, 0x3c, 0xde, 0x3b, 0x1f, 0x56, 0xdb, 0xb6, 0xbe,
0x01, 0x56, 0x64, 0xc2, 0x29, 0xbb, 0xd1, 0xe7, 0xe8, 0x2f, 0xc7, 0x3f,
0x6c, 0x6b, 0xc9, 0xdc, 0x5f, 0x8a, 0x35, 0xa1, 0xa7, 0xa7, 0x6f, 0x14,
0x19, 0xde, 0x05, 0xf6, 0x3e, 0x1f, 0xfb, 0xbc, 0x2f, 0x80, 0xde, 0x7b,
0xef, 0x1d, 0x91, 0xcc, 0x6c, 0x8d, 0xbd, 0x5d, 0xbd, 0x20, 0x69, 0xa7,
0xfb, 0xc9, 0x8a, 0x06, 0x45, 0x21, 0xab, 0x4f, 0xf3, 0x48, 0x83, 0x3d,
0xe1, 0x40, 0x66, 0x2f, 0x1a, 0x63, 0xab, 0xba, 0x25, 0x40, 0x65, 0xb9,
0x7e, 0xe1, 0xfe, 0x83, 0xe1, 0x17, 0x57, 0xdf, 0xab, 0x7d, 0xf1, 0xd1,
0xc5, 0xc7, 0x4b, 0xc7, 0xca, 0xde, 0xf9, 0xdb, 0x0c, 0xfc, 0xff, 0x31,
0xdc, 0x46, 0xf7, 0x4d, 0x06, 0x99, 0xf8, 0x3f, 0xf9, 0x3e, 0xc3, 0x6a,
0x01, 0x6f, 0x18, 0xf9, 0x15, 0x43, 0x7e, 0x5e, 0xfe, 0x77, 0x25, 0xfc,
0xa6, 0x0d, 0xbf, 0xec, 0xa5, 0xff, 0x4a, 0xa4, 0x6b, 0x31, 0xb4, 0x6f,
0x33, 0x9c, 0xb6, 0xfb, 0xed, 0x7a, 0x38, 0x1d, 0xe8, 0x17, 0x18, 0xa8,
0xe7, 0xf7, 0x6e, 0xfb, 0x9b, 0x92, 0xfe, 0x13, 0xdc, 0x2c, 0x81, 0x38,
0xc8, 0xfa, 0xf8, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44,
0xae, 0x42, 0x60, 0x82
};
unsigned int atlas_png_len = 1288;
unsigned char atlas_png[] = {
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x68,
0x08, 0x06, 0x00, 0x00, 0x00, 0x0e, 0xcb, 0xf5, 0x55, 0x00, 0x00, 0x00,
0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x12, 0x00, 0x00, 0x0b,
0x12, 0x01, 0xd2, 0xdd, 0x7e, 0xfc, 0x00, 0x00, 0x06, 0x52, 0x49, 0x44,
0x41, 0x54, 0x78, 0xda, 0xed, 0x5d, 0x8b, 0x4e, 0xeb, 0x30, 0x0c, 0x65,
0xd5, 0x3e, 0x14, 0xbe, 0x0c, 0xfe, 0x74, 0x97, 0x4a, 0x04, 0x05, 0x5f,
0x3f, 0x8e, 0x1d, 0xa7, 0xe9, 0x56, 0x5b, 0x42, 0x6c, 0xb4, 0x69, 0x52,
0x1f, 0xbf, 0xf3, 0xe0, 0xed, 0xad, 0xe8, 0x9c, 0xf4, 0x20, 0xf4, 0xcc,
0xef, 0x10, 0x69, 0xfb, 0xfe, 0xfe, 0xfe, 0xfb, 0xee, 0xfb, 0xe7, 0x99,
0x7d, 0xa9, 0x8c, 0x7f, 0x46, 0x20, 0x32, 0xc6, 0xee, 0x6d, 0xdb, 0x83,
0xd5, 0xc0, 0x93, 0x80, 0x13, 0x01, 0xd5, 0x3a, 0xd4, 0xae, 0xf5, 0xd2,
0x22, 0xd1, 0xcf, 0xc0, 0x86, 0x24, 0xd1, 0x62, 0xea, 0x03, 0xa4, 0x19,
0x00, 0x34, 0xc6, 0x5b, 0xbc, 0x6a, 0xd7, 0xdd, 0x2a, 0x94, 0xf1, 0xe2,
0x3b, 0x00, 0xfb, 0xcf, 0x08, 0x23, 0xb8, 0x71, 0x3c, 0x82, 0x34, 0xcb,
0x04, 0x71, 0xc2, 0x47, 0x9f, 0xe9, 0x02, 0x20, 0x4b, 0xf2, 0xa8, 0x34,
0xa3, 0xd2, 0x3f, 0x0a, 0x52, 0x54, 0x13, 0x22, 0x82, 0x82, 0x8e, 0xa7,
0xb5, 0xbb, 0xf5, 0x2a, 0x71, 0xfb, 0x26, 0x4d, 0x5d, 0xda, 0x75, 0x7a,
0x7f, 0xd4, 0x37, 0x70, 0xfd, 0x71, 0x7d, 0x5b, 0xf7, 0xa9, 0xaa, 0x1d,
0xe8, 0x37, 0xd2, 0x7f, 0x7f, 0x2f, 0x32, 0x8e, 0xf6, 0x4c, 0x15, 0x00,
0x8e, 0xf9, 0x33, 0x00, 0xb0, 0xfa, 0xb7, 0x18, 0x40, 0x4d, 0xc4, 0xe7,
0xe7, 0x27, 0x7b, 0xdf, 0xc7, 0xc7, 0xc7, 0x9f, 0xef, 0x5f, 0x5f, 0x5f,
0xb7, 0x15, 0x00, 0xec, 0xe3, 0x68, 0x7d, 0x6f, 0x88, 0x34, 0xa1, 0x12,
0x33, 0x4a, 0x3d, 0x23, 0xdb, 0x67, 0xca, 0x34, 0x84, 0xf6, 0x36, 0x7d,
0x3b, 0xfa, 0xdd, 0x6b, 0xfa, 0x50, 0x3f, 0x40, 0xc7, 0x2d, 0xf1, 0xad,
0x07, 0xde, 0x34, 0x29, 0x9a, 0x59, 0xca, 0xd2, 0x80, 0x7d, 0xd0, 0x4d,
0x6a, 0x2d, 0xad, 0xf0, 0x68, 0x82, 0x44, 0x9a, 0xe4, 0x6b, 0x63, 0xe9,
0x25, 0x17, 0xd5, 0x96, 0xfe, 0x79, 0x5c, 0xfb, 0x8d, 0x76, 0xe4, 0x65,
0xbe, 0x57, 0x32, 0xbd, 0x0c, 0xf1, 0x30, 0xdf, 0x7a, 0x4e, 0x7f, 0x9d,
0x6a, 0x5b, 0x23, 0xca, 0xfc, 0xfe, 0xf3, 0x7e, 0xcd, 0x13, 0x19, 0xb5,
0x3e, 0x1b, 0xa9, 0xe3, 0x43, 0x23, 0x84, 0xd1, 0x30, 0x54, 0x7a, 0x06,
0x17, 0xef, 0x7b, 0xd5, 0x9e, 0xfb, 0xdd, 0xc7, 0xe7, 0xf4, 0x77, 0xf4,
0xdd, 0x35, 0x1e, 0xa4, 0x65, 0x90, 0x2b, 0x12, 0xb1, 0x8c, 0xac, 0x5b,
0x03, 0x43, 0x32, 0x53, 0xa7, 0x01, 0xe0, 0x0c, 0xa5, 0x88, 0x8c, 0x7e,
0x10, 0xa6, 0x47, 0x92, 0x2e, 0xed, 0xbe, 0x74, 0xfe, 0xbc, 0x42, 0x31,
0xce, 0xe3, 0x98, 0x8b, 0x8a, 0x8a, 0xb2, 0xcd, 0x21, 0xd2, 0x7e, 0x9b,
0xa5, 0xf6, 0xd1, 0x88, 0xe6, 0x2c, 0xfd, 0xd3, 0x44, 0x2c, 0xc2, 0xfc,
0x91, 0xf6, 0x87, 0x3b, 0x71, 0x24, 0x92, 0xd2, 0x98, 0xd9, 0xd7, 0xe1,
0x81, 0x68, 0xec, 0x11, 0x79, 0x87, 0x51, 0x1e, 0x1c, 0xca, 0x7c, 0xcf,
0x35, 0x4f, 0xba, 0x2f, 0x55, 0x48, 0xad, 0x4a, 0xeb, 0x0a, 0x6d, 0x0c,
0x33, 0x3e, 0xa2, 0xc2, 0x54, 0xc2, 0xe8, 0x8f, 0x25, 0x0d, 0x5e, 0x09,
0xd3, 0xfa, 0x1f, 0x8d, 0xea, 0xb2, 0x4c, 0xa8, 0x1b, 0x00, 0x54, 0x85,
0xad, 0xf8, 0xd8, 0x62, 0xbe, 0x14, 0x47, 0x47, 0x01, 0x50, 0x27, 0x3a,
0x04, 0x93, 0x20, 0xf5, 0xcf, 0x4d, 0x27, 0xd2, 0xbf, 0xa1, 0x02, 0x84,
0x08, 0x1b, 0x5b, 0xfe, 0x95, 0x6a, 0x36, 0x5c, 0x9d, 0xc4, 0x6a, 0xd7,
0x97, 0x86, 0xdb, 0x75, 0xee, 0x39, 0xfb, 0x33, 0x3c, 0x75, 0x7a, 0xad,
0x3c, 0x6e, 0x55, 0x75, 0xa5, 0x62, 0x62, 0x2b, 0x25, 0x73, 0x45, 0xb3,
0x56, 0x54, 0xeb, 0xcb, 0xcd, 0x5a, 0xe1, 0x50, 0x2b, 0xc2, 0xfd, 0x77,
0x7f, 0x8f, 0x70, 0xff, 0x99, 0xce, 0x64, 0x49, 0x13, 0xce, 0x92, 0xf4,
0x73, 0xce, 0x4f, 0x92, 0xd6, 0x11, 0x0d, 0xf0, 0xfa, 0x1d, 0x69, 0xf6,
0x8a, 0x8b, 0x5e, 0xb8, 0x68, 0xe6, 0x91, 0x48, 0xac, 0xed, 0xa4, 0x1d,
0xd1, 0x81, 0x71, 0xe0, 0xf4, 0x2a, 0xac, 0x31, 0x5f, 0xb2, 0xd7, 0x1e,
0x00, 0x90, 0x32, 0x00, 0xe2, 0x90, 0x4f, 0x01, 0x00, 0x32, 0x01, 0x61,
0x5d, 0xa7, 0x0c, 0x45, 0x0b, 0x77, 0x51, 0x0d, 0xb0, 0x6c, 0x2d, 0x12,
0x71, 0x49, 0x8c, 0xb6, 0xfc, 0x9c, 0xd5, 0x7e, 0xa8, 0x6e, 0x24, 0xbd,
0x84, 0x95, 0x54, 0x68, 0x8e, 0x56, 0x32, 0x4b, 0x5e, 0x27, 0xac, 0x45,
0x31, 0x52, 0xff, 0x5a, 0x9e, 0x70, 0x16, 0x27, 0xbc, 0xd1, 0x09, 0x93,
0xd6, 0xd1, 0x8d, 0x50, 0x1b, 0x04, 0xe7, 0x68, 0xb9, 0x89, 0x06, 0x6b,
0x0a, 0xd0, 0x33, 0x09, 0x43, 0xfb, 0x6d, 0xe3, 0xd4, 0x9e, 0x45, 0x1d,
0xa2, 0xd5, 0x47, 0xbb, 0x7f, 0x7f, 0xd6, 0xfe, 0xfc, 0x7e, 0xf2, 0x65,
0xff, 0xdc, 0x3b, 0x52, 0xce, 0xd9, 0x7b, 0x26, 0xa8, 0xd4, 0x7b, 0xb5,
0x50, 0xd4, 0x93, 0x41, 0x6a, 0x0e, 0xd9, 0x93, 0x88, 0x71, 0xa6, 0x8d,
0x33, 0x8b, 0x52, 0x1f, 0x88, 0x4f, 0x3a, 0x73, 0x69, 0x7d, 0x59, 0x29,
0x82, 0xfa, 0x18, 0xcd, 0x27, 0x79, 0x4a, 0x11, 0x88, 0x56, 0x3c, 0x6d,
0x29, 0x62, 0x66, 0x31, 0x2e, 0x23, 0x93, 0xf5, 0x48, 0xfe, 0x28, 0xf3,
0x5e, 0x65, 0x3e, 0xe5, 0xe5, 0xcb, 0xd1, 0x45, 0x67, 0xa4, 0xa8, 0x09,
0xe1, 0x12, 0x1c, 0xed, 0x73, 0x76, 0xfb, 0xd9, 0xb5, 0xf7, 0x8c, 0x67,
0x53, 0x33, 0x78, 0xf3, 0x76, 0x22, 0xd5, 0x5b, 0x46, 0x56, 0xcf, 0x8d,
0xb6, 0x47, 0x6a, 0x42, 0x99, 0x00, 0x44, 0x9f, 0x4f, 0x85, 0x78, 0x0f,
0x6b, 0x37, 0x2f, 0xc2, 0x59, 0xd1, 0xc0, 0xa8, 0x34, 0x65, 0x66, 0xd2,
0xb3, 0x35, 0xa1, 0x59, 0x10, 0xd7, 0xc2, 0x2c, 0x69, 0xe5, 0x58, 0x46,
0x48, 0x96, 0x0d, 0x80, 0xa7, 0xf6, 0x82, 0x2e, 0x3b, 0xc9, 0xdc, 0xe8,
0xc1, 0xd5, 0xcb, 0x42, 0x21, 0x93, 0xa7, 0x3c, 0xe1, 0x01, 0x2f, 0x23,
0xd2, 0x18, 0xdd, 0x1b, 0x30, 0x63, 0x8f, 0x01, 0xb7, 0x27, 0x82, 0x15,
0x80, 0x68, 0xb6, 0x8b, 0x30, 0x10, 0xd1, 0x80, 0x8c, 0x49, 0xef, 0x15,
0x00, 0x44, 0x98, 0xaf, 0xee, 0x8e, 0xf1, 0xee, 0x46, 0xf1, 0xdc, 0x4b,
0xd5, 0x70, 0x86, 0x0f, 0xf0, 0x26, 0x69, 0x52, 0x35, 0x77, 0xf4, 0xdd,
0x5d, 0xcc, 0x47, 0x6a, 0xe7, 0x11, 0x0d, 0xd0, 0x26, 0x43, 0x66, 0x85,
0x8e, 0xd1, 0xad, 0x47, 0x99, 0x5b, 0x96, 0xdc, 0xcc, 0xb7, 0x4c, 0x90,
0xb6, 0xf7, 0x09, 0x51, 0x5f, 0xd4, 0x84, 0x78, 0x19, 0xec, 0xda, 0x81,
0x98, 0x08, 0x80, 0x37, 0x87, 0x82, 0xf6, 0xb9, 0x69, 0xd5, 0x4a, 0x24,
0x9a, 0x88, 0xda, 0xc8, 0x55, 0xa9, 0x7d, 0x14, 0x00, 0x14, 0x20, 0x17,
0xf3, 0x11, 0x67, 0x19, 0xdd, 0x25, 0x99, 0x15, 0x57, 0x67, 0x56, 0x17,
0x47, 0x7c, 0x80, 0xc7, 0x3f, 0xa0, 0xcc, 0xbf, 0x69, 0x8c, 0x90, 0x36,
0x9c, 0x69, 0x9b, 0xf9, 0xd0, 0x89, 0x87, 0x3e, 0xfb, 0xb5, 0x32, 0xe1,
0xc8, 0xf3, 0x2d, 0x60, 0xd1, 0x77, 0x40, 0x33, 0x5f, 0x8e, 0x77, 0x08,
0x70, 0x5b, 0xa4, 0x51, 0x76, 0xd6, 0x69, 0xf5, 0xdb, 0x66, 0xe5, 0xa4,
0xef, 0x67, 0xa8, 0x9d, 0xf5, 0x33, 0x76, 0x9e, 0xb1, 0x6d, 0xd2, 0xcb,
0x8e, 0x48, 0x17, 0x52, 0x60, 0xe3, 0x24, 0x30, 0x52, 0x7c, 0xf3, 0x92,
0xb4, 0x7b, 0x71, 0xff, 0x5b, 0x64, 0x47, 0xa6, 0x26, 0x28, 0x45, 0x45,
0xd7, 0xa2, 0x88, 0xb6, 0x6e, 0xcf, 0xf4, 0x82, 0xd6, 0x1a, 0xd0, 0x91,
0xd2, 0x30, 0xd2, 0xef, 0x0a, 0x80, 0x7e, 0x07, 0x10, 0x5d, 0x1d, 0xcc,
0x9d, 0x14, 0xe2, 0x79, 0x16, 0x77, 0x0e, 0xcf, 0x08, 0x33, 0xb4, 0xb5,
0x3d, 0x56, 0xff, 0xa3, 0x0c, 0x0e, 0x8d, 0x7d, 0xe4, 0xc5, 0xb9, 0x75,
0xa6, 0x68, 0x92, 0xc6, 0xad, 0x4f, 0x8d, 0x68, 0x8a, 0x96, 0x34, 0x66,
0xd6, 0xbd, 0x34, 0x06, 0x87, 0xf3, 0x18, 0x74, 0x6d, 0xbf, 0x87, 0x19,
0xd6, 0x20, 0xa3, 0x4c, 0x97, 0x18, 0xcf, 0xad, 0x6a, 0xf3, 0x08, 0x41,
0x64, 0xee, 0xc3, 0x03, 0xc0, 0xdd, 0x52, 0x55, 0xee, 0xe4, 0x11, 0xe4,
0x58, 0x80, 0x3e, 0xc1, 0xfa, 0xbe, 0xf7, 0x8f, 0xca, 0x5b, 0xe1, 0x5e,
0x24, 0x94, 0x6b, 0xcb, 0xc1, 0xe9, 0x12, 0x78, 0xc9, 0xee, 0x6b, 0x63,
0x88, 0x1e, 0x54, 0x22, 0xdd, 0xeb, 0x3e, 0xff, 0xc2, 0xda, 0x58, 0x81,
0xda, 0x43, 0xcd, 0x27, 0x58, 0x7d, 0x5a, 0xdf, 0x25, 0xc9, 0x97, 0xc6,
0x8e, 0xae, 0x09, 0x8a, 0xbc, 0x6b, 0xaa, 0x0f, 0xe0, 0x54, 0x35, 0x83,
0xf9, 0xd4, 0x27, 0x64, 0x02, 0xe0, 0x3d, 0xad, 0xcb, 0x6b, 0x2e, 0xbd,
0x66, 0x2b, 0x2d, 0xcc, 0xcb, 0x60, 0x3e, 0x8d, 0x3a, 0xb4, 0x4d, 0x76,
0xd1, 0x10, 0x12, 0x29, 0x8d, 0x23, 0xa1, 0xe4, 0xc8, 0x7c, 0x72, 0x38,
0x7b, 0xa6, 0x36, 0x94, 0x2b, 0xc6, 0x35, 0x7b, 0x89, 0x9c, 0x30, 0x15,
0x5d, 0xb6, 0xe2, 0x7d, 0x39, 0xba, 0xe5, 0x47, 0x3b, 0xbb, 0xa8, 0xad,
0x76, 0xf6, 0xd8, 0x74, 0xce, 0x07, 0x4a, 0x6d, 0x91, 0x62, 0xa1, 0x5a,
0xac, 0xd3, 0x54, 0x0f, 0x65, 0x8e, 0x25, 0xf9, 0x23, 0x89, 0x11, 0xbd,
0x66, 0x1d, 0x37, 0xa3, 0x6d, 0xb7, 0x1a, 0x29, 0x31, 0x7b, 0x35, 0x07,
0xb9, 0xbe, 0x59, 0x92, 0x8d, 0x46, 0x3c, 0x9c, 0x84, 0x66, 0x2d, 0xb8,
0xca, 0x2a, 0x86, 0x79, 0xc6, 0x72, 0xd4, 0x91, 0x6d, 0x77, 0x6a, 0x6e,
0x34, 0x55, 0xf7, 0x4a, 0xcf, 0x51, 0xcc, 0xe7, 0xfa, 0xe9, 0x77, 0x28,
0x4a, 0x87, 0xf8, 0x21, 0x1a, 0x37, 0xfb, 0x1d, 0xee, 0x9c, 0xcd, 0xef,
0x6d, 0x67, 0x1b, 0xcc, 0x0e, 0x44, 0xaf, 0x0d, 0x54, 0x33, 0xe8, 0xae,
0x95, 0x68, 0x2c, 0x9f, 0xe1, 0x23, 0x22, 0x4c, 0xa7, 0xe0, 0x69, 0xe7,
0xc3, 0x4d, 0x71, 0xc2, 0xda, 0xcb, 0xf6, 0xcc, 0x8f, 0x9a, 0xa4, 0x57,
0xaf, 0x82, 0x0e, 0x39, 0xe1, 0xa2, 0x75, 0x74, 0xcb, 0x88, 0x6d, 0x47,
0x34, 0xe2, 0x2c, 0x1a, 0xb5, 0xe2, 0x9c, 0xd4, 0xdf, 0x28, 0xa8, 0x68,
0x1d, 0xdd, 0xa5, 0xc2, 0x15, 0xea, 0xec, 0x8a, 0x4a, 0x03, 0x0a, 0x80,
0x55, 0xfe, 0xa3, 0x00, 0x28, 0x2a, 0x00, 0x0a, 0x80, 0xa2, 0x02, 0xa0,
0x00, 0x28, 0x2a, 0x00, 0x0a, 0x80, 0xa2, 0x78, 0x26, 0x7c, 0x65, 0xd2,
0xf6, 0xac, 0x1d, 0x51, 0x13, 0xba, 0x17, 0xe3, 0xed, 0x7b, 0x66, 0x02,
0xb1, 0x5d, 0x9d, 0xf9, 0xdc, 0x34, 0x26, 0xfd, 0xdb, 0xcc, 0x63, 0x10,
0x2e, 0xed, 0x03, 0x00, 0xc9, 0x9e, 0x6e, 0x82, 0xb6, 0xab, 0x4a, 0x3f,
0x62, 0x56, 0xf6, 0x5b, 0x46, 0xff, 0x55, 0x57, 0x01, 0x50, 0x51, 0xd0,
0x7a, 0x67, 0xea, 0x6d, 0x37, 0xb2, 0x09, 0xdc, 0x69, 0xe2, 0x4a, 0x03,
0x2a, 0x11, 0x2b, 0x13, 0xf4, 0xf2, 0x91, 0x0c, 0xe4, 0x84, 0xb5, 0x49,
0xf9, 0x99, 0xf9, 0x40, 0x69, 0x40, 0x99, 0xa0, 0x35, 0x1a, 0x03, 0x66,
0xc2, 0xd3, 0xb3, 0xe1, 0x4b, 0x6b, 0x00, 0x00, 0xc2, 0xf4, 0x83, 0x00,
0x2f, 0x59, 0x0b, 0xea, 0xd7, 0xc0, 0x22, 0x07, 0x48, 0x1d, 0xb2, 0x3a,
0xba, 0x4c, 0xd1, 0xb8, 0x83, 0x2f, 0x00, 0x92, 0x80, 0xa8, 0xa5, 0x89,
0x15, 0x05, 0x15, 0x15, 0x00, 0x05, 0x40, 0x51, 0x01, 0x70, 0x15, 0xf2,
0x1e, 0x5a, 0x4d, 0x8f, 0xa1, 0x79, 0x95, 0xa4, 0x6c, 0xe9, 0x7f, 0xbc,
0x88, 0xfe, 0x3f, 0xdf, 0x02, 0xe0, 0x60, 0x10, 0xac, 0x4d, 0xd3, 0x91,
0x3e, 0xaf, 0x0c, 0xc0, 0x1f, 0x1f, 0xd0, 0xfe, 0x89, 0x99, 0x44, 0x47,
0x6d, 0xdd, 0xbc, 0xb4, 0x13, 0x96, 0x40, 0x28, 0xe6, 0x1f, 0x18, 0x05,
0x51, 0x10, 0x8a, 0xf9, 0xf3, 0x48, 0xac, 0x05, 0xfd, 0x30, 0xfc, 0xd1,
0x7d, 0x7e, 0x69, 0x5a, 0xb5, 0x71, 0xfa, 0x1f, 0xcc, 0xd3, 0x69, 0xcc,
0x40, 0x9f, 0x7b, 0x52, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44,
0xae, 0x42, 0x60, 0x82
};
unsigned int atlas_png_len = 1696;

View File

@@ -55,6 +55,16 @@ using namespace glm;
#define INDEX_NONE -1
#define TIME_NONE -1.0f
#if defined(_WIN32)
#define POPEN _popen
#define PCLOSE _pclose
#define PWRITE_MODE "wb"
#else
#define POPEN popen
#define PCLOSE pclose
#define PWRITE_MODE "w"
#endif
#define UV_VERTICES(uvMin, uvMax) \
{ \
0, 0, uvMin.x, uvMin.y, \
@@ -120,6 +130,41 @@ static inline void working_directory_from_file_set(const std::string& path)
std::filesystem::current_path(parentPath);
};
static inline std::string path_extension_change(const std::string& path, const std::string& extension)
{
std::filesystem::path filePath(path);
filePath.replace_extension(extension);
return filePath.string();
}
static inline bool path_exists(const std::filesystem::path& pathCheck)
{
std::error_code errorCode;
return std::filesystem::exists(pathCheck, errorCode) && ((void)std::filesystem::status(pathCheck, errorCode), !errorCode);
}
static inline bool path_valid(const std::filesystem::path& pathCheck)
{
namespace fs = std::filesystem;
std::error_code ec;
if (fs::is_directory(pathCheck, ec)) return false;
if (fs::exists(pathCheck, ec) && !fs::is_regular_file(pathCheck, ec)) return false;
fs::path parentDir = pathCheck.has_parent_path() ? pathCheck.parent_path() : fs::path(".");
if (!fs::is_directory(parentDir, ec)) return false;
bool existedBefore = fs::exists(pathCheck, ec);
std::ofstream testStream(pathCheck, std::ios::app | std::ios::binary);
bool isValid = testStream.is_open();
testStream.close();
if (!existedBefore && isValid)
fs::remove(pathCheck, ec); // cleanup if we created it
return isValid;
}
static inline const char* enum_to_string(const char* array[], s32 count, s32 index)
{
return (index >= 0 && index < count) ? array[index] : "";

View File

@@ -4,271 +4,209 @@
#include "COMMON.h"
const u32 TEXTURE_ATLAS_LENGTH = 1698;
const u8 TEXTURE_ATLAS[] =
{
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x68,
0x08, 0x06, 0x00, 0x00, 0x00, 0x0e, 0xcb, 0xf5, 0x55, 0x00, 0x00, 0x00,
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x78,
0x04, 0x03, 0x00, 0x00, 0x00, 0xff, 0x33, 0xea, 0xfd, 0x00, 0x00, 0x00,
0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x12, 0x00, 0x00, 0x0b,
0x12, 0x01, 0xd2, 0xdd, 0x7e, 0xfc, 0x00, 0x00, 0x06, 0x54, 0x49, 0x44,
0x41, 0x54, 0x78, 0xda, 0xed, 0x5d, 0x8b, 0x4e, 0xeb, 0x30, 0x0c, 0x65,
0xd5, 0x3e, 0x14, 0xbe, 0x0c, 0xfe, 0x74, 0x97, 0x48, 0x04, 0x05, 0x5f,
0x3f, 0x8e, 0x1d, 0xa7, 0xed, 0x56, 0x5b, 0x42, 0x6c, 0xb4, 0x69, 0x52,
0x1f, 0xbf, 0xf3, 0xe0, 0xed, 0xad, 0xe8, 0x9c, 0xf4, 0x20, 0xf4, 0xcc,
0xef, 0x10, 0x69, 0xfb, 0xfe, 0xfe, 0xfe, 0xfb, 0xee, 0xed, 0xf3, 0xca,
0xbe, 0x54, 0xc6, 0x3f, 0x23, 0x10, 0x19, 0x63, 0xf7, 0xb6, 0x1d, 0xc1,
0xea, 0xe0, 0x49, 0xc0, 0x89, 0x80, 0x6a, 0x1d, 0x6a, 0xd7, 0x46, 0x69,
0x91, 0xe8, 0x67, 0x60, 0x53, 0x92, 0x68, 0x31, 0xf5, 0x01, 0xd2, 0x0a,
0x00, 0x3a, 0xe3, 0x2d, 0x5e, 0xf5, 0xeb, 0x6e, 0x15, 0xca, 0x78, 0xf1,
0x06, 0x40, 0xfb, 0x99, 0x61, 0x04, 0x37, 0x8e, 0x47, 0x90, 0x56, 0x99,
0x20, 0x4e, 0xf8, 0xe8, 0x33, 0x5d, 0x00, 0x64, 0x49, 0x1e, 0x95, 0x66,
0x54, 0xfa, 0x67, 0x41, 0x8a, 0x6a, 0x42, 0x44, 0x50, 0xd0, 0xf1, 0xf4,
0x76, 0xb7, 0x51, 0x25, 0x6e, 0xdf, 0xa4, 0xa9, 0x4b, 0xbf, 0x4e, 0xef,
0x8f, 0xfa, 0x06, 0xae, 0x3f, 0xae, 0x6f, 0xeb, 0x3e, 0x55, 0xb5, 0x03,
0xfd, 0x46, 0xfa, 0x1f, 0xef, 0x45, 0xc6, 0xd1, 0x9f, 0xa9, 0x02, 0xc0,
0x31, 0x7f, 0x05, 0x00, 0x56, 0xff, 0x16, 0x03, 0xa8, 0x89, 0xf8, 0xfc,
0xfc, 0x64, 0xef, 0xfb, 0xf8, 0xf8, 0xf8, 0xf3, 0xfd, 0xeb, 0xeb, 0xeb,
0x76, 0x04, 0x00, 0x6d, 0x1c, 0xbd, 0xef, 0x0d, 0x91, 0x26, 0x54, 0x62,
0x66, 0x69, 0x64, 0x64, 0xff, 0x4c, 0x99, 0x86, 0x50, 0x6b, 0x33, 0xb6,
0xa3, 0xdf, 0xbd, 0xa6, 0x0f, 0xf5, 0x03, 0x74, 0xdc, 0x12, 0xdf, 0x46,
0xe0, 0x4d, 0x93, 0xa2, 0x99, 0xa5, 0x2c, 0x0d, 0x68, 0x83, 0xee, 0x52,
0x6b, 0x69, 0x85, 0x47, 0x13, 0x24, 0xd2, 0x24, 0x5f, 0x1b, 0xcb, 0x28,
0xb9, 0xa8, 0xb6, 0x8c, 0xcf, 0xe3, 0xda, 0x6f, 0xb4, 0x23, 0x2f, 0xf3,
0xbd, 0x92, 0xe9, 0x65, 0x88, 0x87, 0xf9, 0xd6, 0x73, 0xc6, 0xeb, 0x54,
0xdb, 0x3a, 0x51, 0xe6, 0x8f, 0x9f, 0xdb, 0x35, 0x4f, 0x64, 0xd4, 0xfb,
0xec, 0xa4, 0x8e, 0x0f, 0x8d, 0x10, 0x66, 0xc3, 0x50, 0xe9, 0x19, 0x5c,
0xbc, 0xef, 0x55, 0x7b, 0xee, 0xf7, 0x18, 0x9f, 0xd3, 0xdf, 0xd1, 0x77,
0xd7, 0x78, 0x90, 0x96, 0x41, 0x1e, 0x91, 0x88, 0x65, 0x64, 0xdd, 0x1a,
0x18, 0x92, 0x99, 0x3a, 0x0d, 0x00, 0x67, 0x28, 0x45, 0x64, 0xf4, 0x83,
0x30, 0x3d, 0x92, 0x74, 0x69, 0xf7, 0xa5, 0xf3, 0xe7, 0x15, 0x8a, 0x71,
0x1e, 0xc7, 0x5c, 0x54, 0x54, 0x94, 0x6d, 0x0e, 0x91, 0xf6, 0xdb, 0x2a,
0xb5, 0x8f, 0x46, 0x34, 0x67, 0xe9, 0x9f, 0x26, 0x62, 0x11, 0xe6, 0xcf,
0xb4, 0xdf, 0xdd, 0x89, 0x23, 0x91, 0x94, 0xc6, 0xcc, 0xb1, 0x0e, 0x0f,
0x44, 0x63, 0x8f, 0xc8, 0x3b, 0xcc, 0xf2, 0x60, 0x57, 0xe6, 0x7b, 0xae,
0x79, 0xd2, 0x7d, 0xa9, 0x42, 0x6a, 0x55, 0x5a, 0x8f, 0xd0, 0xc6, 0x30,
0xe3, 0x23, 0x2a, 0x4c, 0x25, 0x8c, 0xfe, 0x58, 0xd2, 0xe0, 0x95, 0x30,
0xad, 0xff, 0xd9, 0xa8, 0x2e, 0xcb, 0x84, 0xba, 0x01, 0x40, 0x55, 0xd8,
0x8a, 0x8f, 0x2d, 0xe6, 0x4b, 0x71, 0x74, 0x14, 0x00, 0x75, 0xa2, 0x43,
0x30, 0x09, 0x52, 0xff, 0xdc, 0x74, 0x22, 0xfd, 0x1b, 0x2a, 0x40, 0x88,
0xb0, 0xb1, 0xe5, 0x5f, 0xa9, 0x66, 0xc3, 0xd5, 0x49, 0xac, 0x76, 0x63,
0x69, 0xb8, 0x5f, 0xe7, 0x9e, 0xd3, 0x9e, 0xe1, 0xa9, 0xd3, 0x6b, 0xe5,
0x71, 0xab, 0xaa, 0x2b, 0x15, 0x13, 0x7b, 0x29, 0x99, 0x2b, 0x9a, 0xf5,
0xa2, 0xda, 0x58, 0x6e, 0xd6, 0x0a, 0x87, 0x5a, 0x11, 0xee, 0xbf, 0xfb,
0x47, 0x84, 0xc7, 0xcf, 0x74, 0x26, 0x4b, 0x9a, 0x70, 0x96, 0xa4, 0x9f,
0x73, 0x7e, 0x92, 0xb4, 0xce, 0x68, 0x80, 0xd7, 0xef, 0x48, 0xb3, 0x57,
0x5c, 0xf4, 0xc2, 0x45, 0x33, 0x8f, 0x44, 0x62, 0x6d, 0x27, 0xed, 0x88,
0x0e, 0x8c, 0x03, 0x67, 0x54, 0x61, 0x8d, 0xf9, 0x92, 0xbd, 0xf6, 0x00,
0x80, 0x94, 0x01, 0x10, 0x87, 0x7c, 0x0a, 0x00, 0x90, 0x09, 0x08, 0xeb,
0x3a, 0x65, 0x28, 0x5a, 0xb8, 0x8b, 0x6a, 0x80, 0x65, 0x6b, 0x91, 0x88,
0x4b, 0x62, 0xb4, 0xe5, 0xe7, 0xac, 0xf6, 0x53, 0x75, 0x23, 0xe9, 0x25,
0xac, 0xa4, 0x42, 0x73, 0xb4, 0x92, 0x59, 0xf2, 0x3a, 0x61, 0x2d, 0x8a,
0x91, 0xfa, 0xd7, 0xf2, 0x84, 0xb3, 0x38, 0xe1, 0x8d, 0x4e, 0x98, 0xf4,
0x8e, 0x6e, 0x84, 0xfa, 0x20, 0x38, 0x47, 0xcb, 0x4d, 0x34, 0x58, 0x53,
0x80, 0x9e, 0x49, 0x18, 0xda, 0x6f, 0x1f, 0xa7, 0xf6, 0x2c, 0xea, 0x10,
0xad, 0x3e, 0xfa, 0xfd, 0xed, 0x59, 0xed, 0xf9, 0xe3, 0xe4, 0x4b, 0xfb,
0x3c, 0x3a, 0x52, 0xce, 0xd9, 0x7b, 0x26, 0xa8, 0xd4, 0x7b, 0xb5, 0x50,
0xd4, 0x93, 0x41, 0x6a, 0x0e, 0xd9, 0x93, 0x88, 0x71, 0xa6, 0x8d, 0x33,
0x8b, 0x52, 0x1f, 0x88, 0x4f, 0x3a, 0x73, 0x69, 0xfd, 0xb0, 0x52, 0x04,
0xf5, 0x31, 0x9a, 0x4f, 0xf2, 0x94, 0x22, 0x10, 0xad, 0x78, 0xda, 0x52,
0xc4, 0xca, 0x62, 0x5c, 0x46, 0x26, 0xeb, 0x91, 0xfc, 0x59, 0xe6, 0xbd,
0xca, 0x7c, 0xca, 0xcb, 0x97, 0xa3, 0x8b, 0xce, 0x48, 0x51, 0x13, 0xc2,
0x25, 0x38, 0xda, 0xe7, 0xec, 0xf6, 0xab, 0x6b, 0xef, 0x19, 0xcf, 0xa6,
0x66, 0xf0, 0xe6, 0xed, 0x44, 0xaa, 0xb7, 0xcc, 0xac, 0x9e, 0x9b, 0x6d,
0x8f, 0xd4, 0x84, 0x32, 0x01, 0x88, 0x3e, 0x9f, 0x0a, 0x71, 0x0b, 0x6b,
0x37, 0x2f, 0xc2, 0x59, 0xd1, 0xc0, 0xac, 0x34, 0x65, 0x66, 0xd2, 0xab,
0x35, 0xa1, 0x5b, 0x10, 0xd7, 0xc2, 0x2c, 0x69, 0xe5, 0x58, 0x46, 0x48,
0x96, 0x0d, 0x80, 0xa7, 0xf6, 0x82, 0x2e, 0x3b, 0xc9, 0xdc, 0xe8, 0xc1,
0xd5, 0xcb, 0x42, 0x21, 0x93, 0xa7, 0x3c, 0xe1, 0x01, 0x2f, 0x23, 0xd2,
0x98, 0xdd, 0x1b, 0xb0, 0x62, 0x8f, 0x01, 0xb7, 0x27, 0x82, 0x15, 0x80,
0x68, 0xb6, 0x8b, 0x30, 0x10, 0xd1, 0x80, 0x8c, 0x49, 0xef, 0x23, 0x00,
0x88, 0x30, 0x5f, 0xdd, 0x1d, 0xe3, 0xdd, 0x8d, 0xe2, 0xb9, 0x97, 0xaa,
0xe1, 0x0a, 0x1f, 0xe0, 0x4d, 0xd2, 0xa4, 0x6a, 0xee, 0xec, 0xbb, 0xbb,
0x98, 0x8f, 0xd4, 0xce, 0x23, 0x1a, 0xa0, 0x4d, 0x86, 0xac, 0x0a, 0x1d,
0xa3, 0x5b, 0x8f, 0x32, 0xb7, 0x2c, 0xb9, 0x99, 0x6f, 0x99, 0x20, 0x6d,
0xef, 0x13, 0xa2, 0xbe, 0xa8, 0x09, 0xf1, 0x32, 0xd8, 0xb5, 0x03, 0x31,
0x11, 0x00, 0x6f, 0x0e, 0x05, 0xed, 0x73, 0xd3, 0xaa, 0x95, 0x48, 0x34,
0x11, 0xb5, 0x91, 0x47, 0xa5, 0xf6, 0x51, 0x00, 0x50, 0x80, 0x5c, 0xcc,
0x47, 0x9c, 0x65, 0x74, 0x97, 0x64, 0x56, 0x5c, 0x9d, 0x59, 0x5d, 0x9c,
0xf1, 0x01, 0x1e, 0xff, 0x80, 0x32, 0xff, 0xa6, 0x31, 0x42, 0xda, 0x70,
0xa6, 0x6d, 0xe6, 0x43, 0x27, 0x1e, 0xc6, 0xec, 0xd7, 0xca, 0x84, 0x23,
0xcf, 0xb7, 0x80, 0x45, 0xdf, 0x01, 0xcd, 0x7c, 0x39, 0xde, 0x21, 0xc0,
0x6d, 0x91, 0x46, 0xd9, 0x59, 0xa7, 0xd5, 0x6f, 0x9f, 0x95, 0x93, 0xbe,
0x9f, 0xa1, 0x76, 0x36, 0xce, 0xd8, 0x79, 0xc6, 0xb6, 0x49, 0x2f, 0x3b,
0x23, 0x5d, 0x48, 0x81, 0x8d, 0x93, 0xc0, 0x48, 0xf1, 0xcd, 0x4b, 0xd2,
0xee, 0xc5, 0xf6, 0xb7, 0xc8, 0x8e, 0x4c, 0x4d, 0x50, 0x8a, 0x8a, 0xae,
0x45, 0x11, 0x6d, 0xdd, 0x9e, 0xe9, 0x05, 0xad, 0x35, 0xa0, 0x33, 0xa5,
0x61, 0xa4, 0xdf, 0x23, 0x00, 0xfa, 0x1d, 0x40, 0x74, 0x75, 0x30, 0x77,
0x52, 0x88, 0xe7, 0x59, 0xdc, 0x39, 0x3c, 0x33, 0xcc, 0xd0, 0xd6, 0xf6,
0x58, 0xfd, 0xcf, 0x32, 0x38, 0x34, 0xf6, 0x99, 0x17, 0xe7, 0xd6, 0x99,
0xa2, 0x49, 0x1a, 0xb7, 0x3e, 0x35, 0xa2, 0x29, 0x5a, 0xd2, 0x98, 0x59,
0xf7, 0xd2, 0x18, 0x1c, 0xce, 0x63, 0xd0, 0xb5, 0xfd, 0x1e, 0x66, 0x58,
0x83, 0x8c, 0x32, 0x5d, 0x62, 0x3c, 0xb7, 0xaa, 0xcd, 0x23, 0x04, 0x91,
0xb9, 0x0f, 0x0f, 0x00, 0x77, 0x4b, 0x55, 0xb9, 0x93, 0x47, 0x90, 0x63,
0x01, 0xc6, 0x04, 0xeb, 0xfb, 0xde, 0x3f, 0x2a, 0x6f, 0x85, 0x7b, 0x91,
0x50, 0xae, 0x2f, 0x07, 0xa7, 0x4b, 0xe0, 0x25, 0xbb, 0xaf, 0x8d, 0x21,
0x7a, 0x50, 0x89, 0x74, 0xaf, 0xfb, 0xfc, 0x0b, 0x6b, 0x63, 0x05, 0x6a,
0x0f, 0x35, 0x9f, 0x60, 0xf5, 0x69, 0x7d, 0x97, 0x24, 0x5f, 0x1a, 0x3b,
0xba, 0x26, 0x28, 0xf2, 0xae, 0xa9, 0x3e, 0x80, 0x53, 0xd5, 0x0c, 0xe6,
0x53, 0x9f, 0x90, 0x09, 0x80, 0xf7, 0xb4, 0x2e, 0xaf, 0xb9, 0xf4, 0x9a,
0xad, 0xb4, 0x30, 0x2f, 0x83, 0xf9, 0x34, 0xea, 0xd0, 0x36, 0xd9, 0x45,
0x43, 0x48, 0xa4, 0x34, 0x8e, 0x84, 0x92, 0x33, 0xf3, 0xc9, 0xe1, 0xec,
0x99, 0xda, 0x50, 0xae, 0x18, 0xd7, 0xed, 0x25, 0x72, 0xc2, 0x54, 0x74,
0xd9, 0x8a, 0xf7, 0xe5, 0xe8, 0x96, 0x1f, 0xed, 0xec, 0xa2, 0xbe, 0xda,
0xd9, 0x63, 0xd3, 0x39, 0x1f, 0x28, 0xb5, 0x45, 0x8a, 0x85, 0x6a, 0xb1,
0x4e, 0x53, 0x3d, 0x94, 0x39, 0x96, 0xe4, 0xcf, 0x24, 0x46, 0xf4, 0x9a,
0x75, 0xdc, 0x8c, 0xb6, 0xdd, 0x6a, 0xa6, 0xc4, 0xec, 0xd5, 0x1c, 0xe4,
0xfa, 0x66, 0x49, 0x36, 0x1a, 0xf1, 0x70, 0x12, 0x9a, 0xb5, 0xe0, 0x2a,
0xab, 0x18, 0xe6, 0x19, 0xcb, 0x5e, 0x47, 0xb6, 0xdd, 0xa9, 0xb9, 0xd1,
0x54, 0xdd, 0x2b, 0x3d, 0x7b, 0x31, 0x9f, 0xeb, 0x67, 0xdc, 0xa1, 0x28,
0x1d, 0xe2, 0x87, 0x68, 0xdc, 0xea, 0x77, 0xb8, 0x73, 0x36, 0x7f, 0xb4,
0x9d, 0x7d, 0x30, 0x0d, 0x88, 0x51, 0x1b, 0xa8, 0x66, 0xd0, 0x5d, 0x2b,
0xd1, 0x58, 0x3e, 0xc3, 0x47, 0x44, 0x98, 0x4e, 0xc1, 0xd3, 0xce, 0x87,
0x5b, 0xe2, 0x84, 0xb5, 0x97, 0x1d, 0x99, 0x1f, 0x35, 0x49, 0xaf, 0x5e,
0x05, 0x9d, 0x72, 0xc2, 0x45, 0xc7, 0xd1, 0xed, 0x0c, 0x27, 0x4a, 0x9d,
0x41, 0xa3, 0x8e, 0x38, 0x27, 0x55, 0xad, 0x05, 0xed, 0xc1, 0xc0, 0x3a,
0x4e, 0xec, 0x07, 0x80, 0xa8, 0xc3, 0x9a, 0x9d, 0x43, 0x2d, 0x7a, 0xb2,
0x19, 0xb1, 0x02, 0xe0, 0x45, 0xed, 0x7f, 0x69, 0x40, 0x01, 0x50, 0x54,
0x00, 0x14, 0x00, 0x45, 0x05, 0x40, 0x01, 0x50, 0x54, 0x00, 0x5c, 0x31,
0x13, 0xbe, 0x32, 0x69, 0x7b, 0xd6, 0xf6, 0xa8, 0x09, 0xdd, 0x8b, 0xf1,
0xf6, 0x3d, 0x2b, 0x81, 0xd8, 0xae, 0xce, 0x7c, 0x6e, 0x1a, 0x93, 0xfe,
0x6d, 0xe5, 0x31, 0x08, 0x97, 0xf6, 0x01, 0x80, 0x64, 0x2f, 0x37, 0x41,
0xdb, 0x55, 0xa5, 0x1f, 0x31, 0x2b, 0xed, 0x96, 0xd9, 0x7f, 0xd5, 0x55,
0x00, 0x54, 0x14, 0x74, 0xbc, 0x33, 0xf5, 0xb6, 0x9b, 0xd9, 0x04, 0xee,
0x34, 0x71, 0xa5, 0x01, 0x95, 0x88, 0x95, 0x09, 0x7a, 0xf9, 0x48, 0x06,
0x72, 0xc2, 0xda, 0xa4, 0xfc, 0xca, 0x7c, 0xa0, 0x34, 0xa0, 0x4c, 0xd0,
0x31, 0x1a, 0x03, 0x66, 0xc2, 0xcb, 0xb3, 0xe1, 0x4b, 0x6b, 0x00, 0x00,
0xc2, 0xf2, 0x65, 0x33, 0x97, 0xac, 0x05, 0x8d, 0x6b, 0x60, 0x91, 0x03,
0xa4, 0x76, 0x59, 0x1d, 0x5d, 0xa6, 0x68, 0xde, 0xc1, 0x17, 0x00, 0x49,
0x40, 0xec, 0xb9, 0x34, 0xb1, 0xa2, 0xa0, 0x8a, 0x82, 0x0a, 0x80, 0xa2,
0x02, 0xa0, 0x00, 0x28, 0x3a, 0x0a, 0x80, 0xfe, 0x5f, 0x83, 0xbc, 0xb4,
0xd7, 0x1e, 0xaa, 0x4b, 0x68, 0x80, 0x17, 0x84, 0x62, 0xfe, 0x02, 0x13,
0x84, 0x82, 0x90, 0xcd, 0xfc, 0xab, 0xef, 0x92, 0xf9, 0xe3, 0x03, 0x2c,
0x10, 0x4a, 0xf2, 0x77, 0x70, 0xc2, 0x12, 0x08, 0xc5, 0xfc, 0x1d, 0xa3,
0x20, 0x0a, 0x42, 0x31, 0x7f, 0x1d, 0x89, 0xb5, 0xa0, 0x1f, 0x86, 0x3f,
0x86, 0xcf, 0x2f, 0x6d, 0xc7, 0x8f, 0xda, 0x38, 0xfd, 0x0f, 0xc3, 0x64,
0xcf, 0x81, 0x94, 0xa2, 0x56, 0xa7, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45,
0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
0x12, 0x01, 0xd2, 0xdd, 0x7e, 0xfc, 0x00, 0x00, 0x00, 0x0f, 0x50, 0x4c,
0x54, 0x45, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x60, 0x60, 0x60, 0xff,
0xff, 0xff, 0x60, 0x60, 0x60, 0x15, 0x68, 0x14, 0xc2, 0x00, 0x00, 0x00,
0x03, 0x74, 0x52, 0x4e, 0x53, 0x00, 0x00, 0x00, 0xfa, 0x76, 0xc4, 0xde,
0x00, 0x00, 0x03, 0xf4, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xed, 0x98,
0x6d, 0x6e, 0xde, 0x38, 0x0c, 0x84, 0x27, 0x20, 0x0f, 0xb0, 0xc1, 0x5e,
0x60, 0x81, 0x5c, 0x80, 0x9b, 0xe1, 0x01, 0x08, 0x88, 0xf7, 0x3f, 0xd3,
0x42, 0x94, 0x04, 0xa9, 0xad, 0x83, 0xd8, 0x0b, 0x34, 0xed, 0x8f, 0x4e,
0x90, 0xc8, 0xb4, 0xf9, 0x84, 0x5f, 0xd2, 0xeb, 0x20, 0xf8, 0x3f, 0x22,
0x71, 0x29, 0x31, 0x94, 0x9a, 0x97, 0xd7, 0xe1, 0x4f, 0xd6, 0x12, 0x42,
0xc6, 0xe1, 0x4f, 0xda, 0xf1, 0x0b, 0x99, 0x0e, 0x68, 0xdd, 0x07, 0x68,
0x90, 0x22, 0x87, 0x4b, 0x23, 0x09, 0x29, 0x73, 0x03, 0x29, 0x04, 0x64,
0x86, 0x22, 0xeb, 0x72, 0x7b, 0x90, 0xc2, 0x92, 0xed, 0x94, 0x84, 0xae,
0x1c, 0x80, 0x90, 0x38, 0x1c, 0xd4, 0x80, 0xd3, 0x16, 0x9b, 0x00, 0xc9,
0x61, 0xd1, 0xc4, 0xa4, 0xb2, 0xd7, 0xed, 0x30, 0x53, 0xba, 0x02, 0x84,
0x10, 0x13, 0x94, 0xac, 0xdb, 0x15, 0x26, 0x1b, 0xe9, 0x19, 0xdf, 0x02,
0x5e, 0x16, 0xed, 0x04, 0x1c, 0x2d, 0x0a, 0xc8, 0xe6, 0xd9, 0x01, 0x1d,
0xbd, 0x63, 0x0b, 0xd2, 0x3a, 0x20, 0xc4, 0x01, 0x28, 0x41, 0x60, 0x10,
0xe5, 0x8f, 0x66, 0xe2, 0x1d, 0x58, 0xd5, 0x17, 0x46, 0x2c, 0x00, 0x0b,
0x88, 0xee, 0x1f, 0xa1, 0x64, 0xcd, 0x08, 0x3c, 0xe7, 0x7c, 0x02, 0x8d,
0x5e, 0x01, 0x54, 0x35, 0x55, 0x21, 0x95, 0x06, 0x6d, 0x02, 0x7b, 0x70,
0xab, 0x4b, 0xf5, 0xb0, 0x14, 0x5d, 0x17, 0xc0, 0xdc, 0x1a, 0xca, 0x52,
0xa0, 0x9e, 0xcc, 0x18, 0x00, 0x94, 0x31, 0x7e, 0xf0, 0xf3, 0xcd, 0x87,
0xc0, 0x2f, 0x96, 0x92, 0x71, 0x65, 0x8b, 0x61, 0xd9, 0xd8, 0xda, 0xe7,
0xa2, 0x71, 0x6c, 0x81, 0xec, 0x6b, 0x1e, 0x00, 0xb9, 0x89, 0xa3, 0xbd,
0x70, 0x74, 0xaa, 0x83, 0x40, 0x07, 0x85, 0x7c, 0x07, 0x80, 0x37, 0x66,
0xd0, 0x8e, 0xd0, 0xcc, 0x4c, 0x12, 0xb0, 0xa2, 0x01, 0xc6, 0xe8, 0x9f,
0x8b, 0xb5, 0x0a, 0xa0, 0x91, 0xe4, 0xf0, 0xef, 0x84, 0x32, 0xb3, 0x91,
0xb1, 0x00, 0x25, 0x20, 0x65, 0x8b, 0xc9, 0x04, 0xa4, 0x00, 0xf1, 0xcc,
0x66, 0xb5, 0xd0, 0x9b, 0x2d, 0x60, 0x9d, 0x13, 0x96, 0x80, 0x56, 0xcf,
0xc5, 0xa0, 0xde, 0x9a, 0x7b, 0x0b, 0xf1, 0x6c, 0xcc, 0x13, 0x80, 0x10,
0x07, 0x50, 0xcf, 0xc5, 0xc0, 0x10, 0x31, 0x53, 0x36, 0x4b, 0x7a, 0x8a,
0x0f, 0x40, 0xb1, 0xce, 0xc9, 0x4a, 0x49, 0x4c, 0xe9, 0xdd, 0x56, 0x93,
0xe8, 0xdf, 0xe2, 0x42, 0x60, 0x45, 0xd8, 0xe7, 0x64, 0x15, 0xdd, 0x9f,
0x67, 0xb7, 0x21, 0x20, 0x61, 0x50, 0xd2, 0x33, 0x67, 0xd1, 0x64, 0xb7,
0x0d, 0xc9, 0xa8, 0xb6, 0x92, 0x00, 0xe9, 0x91, 0xd5, 0x25, 0x47, 0x1d,
0x4a, 0x56, 0x5f, 0xd1, 0x01, 0x69, 0x6e, 0x05, 0x75, 0x00, 0x62, 0xd3,
0x8e, 0xb2, 0x6b, 0xb4, 0x5e, 0x83, 0xcb, 0x9c, 0x83, 0xab, 0x2c, 0x1a,
0x91, 0xf4, 0xec, 0x40, 0xd9, 0xc2, 0x08, 0xba, 0x5e, 0x6d, 0x8d, 0xe8,
0x55, 0x21, 0xcb, 0x0e, 0xe0, 0xf5, 0x9f, 0xb2, 0x31, 0xec, 0xeb, 0xcd,
0xb7, 0x26, 0x9a, 0x79, 0xd8, 0x58, 0xf6, 0x73, 0x89, 0xed, 0xf5, 0x96,
0xc8, 0xbd, 0xee, 0xd4, 0xc4, 0x28, 0xc6, 0xbd, 0x96, 0x32, 0xf6, 0x7b,
0xa0, 0xd6, 0x5d, 0xbc, 0xac, 0xf0, 0x38, 0xa4, 0x05, 0x9c, 0xa9, 0xfd,
0x05, 0xfc, 0x4d, 0x76, 0x52, 0xc6, 0x6f, 0xb0, 0x09, 0x18, 0x5e, 0x01,
0x89, 0x8c, 0xb3, 0x3b, 0x52, 0x77, 0xc9, 0x58, 0x87, 0xb1, 0x03, 0x98,
0xc0, 0xcb, 0x2b, 0xe0, 0x54, 0x00, 0xd6, 0x42, 0x5d, 0x00, 0xeb, 0x80,
0x60, 0x7d, 0x70, 0x49, 0x8d, 0xc4, 0xce, 0x94, 0xa4, 0x8d, 0xc1, 0x3b,
0xd0, 0xc4, 0xc4, 0xd0, 0x1c, 0x62, 0x52, 0xe1, 0x06, 0x50, 0x29, 0xed,
0x08, 0x4e, 0x37, 0xa0, 0xdf, 0x33, 0x11, 0x2e, 0x09, 0x51, 0x40, 0x75,
0xa1, 0xed, 0x94, 0xf0, 0x2a, 0x8d, 0x0d, 0xd7, 0x80, 0x81, 0x26, 0x45,
0x9d, 0x29, 0x55, 0x80, 0xeb, 0x94, 0x28, 0x34, 0x61, 0x55, 0x6e, 0x05,
0x88, 0x19, 0x50, 0x01, 0x7e, 0x2c, 0x5a, 0x69, 0x20, 0x19, 0x73, 0x2a,
0xb6, 0xfa, 0x07, 0x91, 0x0a, 0x70, 0xd5, 0x56, 0x23, 0xb9, 0xc7, 0xb9,
0x46, 0x4a, 0xab, 0x00, 0x57, 0x83, 0x33, 0xd2, 0x16, 0x60, 0x1b, 0x20,
0x4a, 0x17, 0x5b, 0x63, 0x47, 0x38, 0x52, 0xd2, 0x66, 0x57, 0x9b, 0x6f,
0x5d, 0xd0, 0x3a, 0x40, 0x31, 0x80, 0x52, 0xab, 0xc6, 0xe5, 0xf6, 0xfe,
0x1a, 0xd9, 0x11, 0x1b, 0x43, 0x4a, 0x4c, 0xc5, 0xb0, 0xc7, 0x22, 0xd1,
0x7c, 0x27, 0x76, 0x24, 0xc9, 0x5c, 0x40, 0x58, 0x2d, 0xd3, 0x56, 0x27,
0x01, 0x9e, 0x00, 0x01, 0x88, 0x33, 0x46, 0x18, 0x9f, 0x0f, 0xb5, 0x4d,
0xa7, 0x56, 0xed, 0xec, 0x8a, 0xf5, 0x1e, 0x36, 0xb0, 0xf9, 0x4c, 0xeb,
0xfd, 0x2d, 0x86, 0x63, 0x92, 0x3e, 0x32, 0xa6, 0x83, 0x43, 0xc0, 0xba,
0x60, 0xa0, 0xd4, 0xf2, 0xfd, 0x2d, 0x19, 0x23, 0x00, 0x73, 0x54, 0x2b,
0x01, 0xf9, 0x16, 0x30, 0x24, 0xfb, 0x17, 0x94, 0x49, 0x66, 0xc1, 0x41,
0x7a, 0x54, 0x00, 0xa8, 0x03, 0xb4, 0xfd, 0x17, 0x8c, 0x10, 0x03, 0x98,
0xa9, 0xd6, 0xb4, 0x95, 0xb2, 0x02, 0x84, 0xb5, 0xd9, 0x19, 0xb1, 0xb9,
0xcc, 0x46, 0x2a, 0x04, 0x1d, 0x18, 0x95, 0xda, 0x0a, 0x20, 0xe8, 0x3a,
0x01, 0x00, 0x59, 0x2a, 0xc0, 0xd7, 0x3b, 0x51, 0x57, 0x00, 0x94, 0x26,
0xb0, 0x47, 0xa5, 0x50, 0x08, 0x99, 0x05, 0x60, 0x34, 0x11, 0xc7, 0x69,
0xdc, 0x35, 0x9c, 0x80, 0x49, 0xfa, 0xda, 0xd5, 0x18, 0x80, 0x61, 0x48,
0x56, 0x97, 0x6c, 0x03, 0x75, 0xbb, 0x0d, 0x0f, 0x7a, 0x2a, 0x02, 0x8d,
0xb8, 0x04, 0xb2, 0x04, 0x40, 0x17, 0xa0, 0x19, 0x11, 0x38, 0x24, 0x6b,
0xd2, 0x86, 0x2f, 0x95, 0x1c, 0xf1, 0xd4, 0x6e, 0x01, 0x1b, 0x62, 0x00,
0x2f, 0x9c, 0x86, 0x30, 0x84, 0x31, 0xba, 0xf1, 0x01, 0x20, 0x44, 0x07,
0x68, 0x9f, 0x01, 0xfb, 0x73, 0x65, 0x00, 0xb4, 0x7b, 0x80, 0x10, 0x13,
0xa0, 0x5d, 0x03, 0x27, 0x54, 0xf7, 0x63, 0x01, 0xb4, 0x0d, 0x94, 0xed,
0x6b, 0x3d, 0x6a, 0x50, 0x92, 0x5c, 0x00, 0xe3, 0x63, 0xe0, 0xdc, 0x39,
0xbe, 0x00, 0xff, 0x10, 0x38, 0x95, 0xb4, 0x09, 0x78, 0xec, 0x94, 0x32,
0xe9, 0x99, 0x40, 0x96, 0xf6, 0x07, 0xf2, 0x6e, 0x6b, 0xf9, 0x7f, 0x54,
0x74, 0x01, 0x67, 0x5b, 0x81, 0xf2, 0xbf, 0x05, 0x28, 0xb1, 0x9a, 0x75,
0x0f, 0x90, 0xe1, 0x98, 0x81, 0xb5, 0xdb, 0x75, 0x5c, 0x67, 0x5e, 0x01,
0x37, 0xb5, 0x8b, 0x7e, 0xac, 0xfc, 0x4e, 0x81, 0xef, 0x44, 0xbb, 0x06,
0x56, 0x05, 0x9f, 0x02, 0x8d, 0x25, 0xff, 0x3a, 0x00, 0x7f, 0x80, 0xdf,
0x12, 0x20, 0x69, 0x4f, 0x00, 0x76, 0xd9, 0x7d, 0x40, 0x08, 0x9a, 0xf0,
0x01, 0x60, 0xa0, 0xbd, 0x3c, 0x00, 0x58, 0x45, 0x8b, 0xfd, 0x0c, 0x80,
0x3f, 0xea, 0xdf, 0x2f, 0x05, 0xbe, 0xbe, 0xe8, 0xe7, 0x73, 0x78, 0x3e,
0xe9, 0xe7, 0x7b, 0x69, 0x13, 0xf6, 0xe7, 0x4c, 0x3f, 0x06, 0x94, 0xa5,
0xb8, 0x05, 0xec, 0x10, 0x8e, 0xfb, 0x80, 0x56, 0x00, 0xdc, 0x7e, 0x3f,
0x54, 0x08, 0xc7, 0x13, 0x40, 0xc9, 0x78, 0x04, 0xa0, 0x39, 0x9e, 0x01,
0xe5, 0x94, 0x53, 0x9f, 0xfd, 0x33, 0xf0, 0x3f, 0x53, 0x26, 0x87, 0x23,
0x59, 0xac, 0x2b, 0x06, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44,
0xae, 0x42, 0x60, 0x82
};
enum TextureType
const u32 TEXTURE_ATLAS_LENGTH = (u32)std::size(TEXTURE_ATLAS);
const vec2 TEXTURE_ATLAS_SIZE = {96, 120};
enum AtlasType
{
TEXTURE_NONE,
TEXTURE_RECORD,
TEXTURE_ROOT,
TEXTURE_LAYER,
TEXTURE_NULL,
TEXTURE_TRIGGERS,
TEXTURE_VISIBLE,
TEXTURE_INVISIBLE,
TEXTURE_SHOW_RECT,
TEXTURE_HIDE_RECT,
TEXTURE_PAN,
TEXTURE_MOVE,
TEXTURE_ROTATE,
TEXTURE_SCALE,
TEXTURE_CROP,
TEXTURE_UNDO,
TEXTURE_REDO,
TEXTURE_DRAW,
TEXTURE_ERASE,
TEXTURE_COLOR_PICKER,
TEXTURE_ANIMATION,
TEXTURE_SPRITESHEET,
TEXTURE_EVENT,
TEXTURE_TRIGGER,
TEXTURE_PIVOT,
TEXTURE_SQUARE,
TEXTURE_CIRCLE,
TEXTURE_PICKER,
TEXTURE_FRAME_ALT,
TEXTURE_FRAME,
TEXTURE_TARGET,
TEXTURE_COUNT
ATLAS_NONE,
ATLAS_FOLDER,
ATLAS_ROOT,
ATLAS_LAYER,
ATLAS_NULL,
ATLAS_TRIGGERS,
ATLAS_VISIBLE,
ATLAS_INVISIBLE,
ATLAS_SHOW_RECT,
ATLAS_HIDE_RECT,
ATLAS_SHOW_TARGETS,
ATLAS_HIDE_TARGETS,
ATLAS_PAN,
ATLAS_MOVE,
ATLAS_ROTATE,
ATLAS_SCALE,
ATLAS_CROP,
ATLAS_DRAW,
ATLAS_ERASE,
ATLAS_COLOR_PICKER,
ATLAS_UNDO,
ATLAS_REDO,
ATLAS_ANIMATION,
ATLAS_SPRITESHEET,
ATLAS_EVENT,
ATLAS_PLAY,
ATLAS_PAUSE,
ATLAS_ADD,
ATLAS_REMOVE,
ATLAS_TRIGGER,
ATLAS_PIVOT,
ATLAS_SQUARE,
ATLAS_CIRCLE,
ATLAS_PICKER,
ATLAS_FRAME,
ATLAS_FRAME_ALT,
ATLAS_TARGET,
ATLAS_COUNT
};
const vec2 ATLAS_SIZE = {96, 104};
const vec2 TEXTURE_SIZE_SMALL = {8, 8};
const vec2 TEXTURE_SIZE = {16, 16};
const vec2 TEXTURE_SIZE_OBLONG = {16, 40};
const vec2 TEXTURE_SIZE_BIG = {40, 40};
#define ATLAS_UV(x,y){(f32)x / ATLAS_SIZE[0], (f32) y / ATLAS_SIZE[1]}
const vec2 ATLAS_UVS[TEXTURE_COUNT][2] =
struct AtlasEntry
{
{ ATLAS_UV( 0, 0), ATLAS_UV( 16, 16) }, /* 16 x 16 v */
{ ATLAS_UV( 16, 0), ATLAS_UV( 32, 16) },
{ ATLAS_UV( 32, 0), ATLAS_UV( 48, 16) },
{ ATLAS_UV( 48, 0), ATLAS_UV( 64, 16) },
{ ATLAS_UV( 64, 0), ATLAS_UV( 80, 16) },
{ ATLAS_UV( 80, 0), ATLAS_UV( 96, 16) },
{ ATLAS_UV( 0, 16), ATLAS_UV( 16, 32) },
{ ATLAS_UV( 16, 16), ATLAS_UV( 32, 32) },
{ ATLAS_UV( 32, 16), ATLAS_UV( 48, 32) },
{ ATLAS_UV( 48, 16), ATLAS_UV( 64, 32) },
{ ATLAS_UV( 64, 16), ATLAS_UV( 80, 32) },
{ ATLAS_UV( 80, 16), ATLAS_UV( 96, 32) },
{ ATLAS_UV( 0, 32), ATLAS_UV( 16, 48) },
{ ATLAS_UV( 16, 32), ATLAS_UV( 32, 48) },
{ ATLAS_UV( 32, 32), ATLAS_UV( 48, 48) },
{ ATLAS_UV( 48, 32), ATLAS_UV( 64, 48) },
{ ATLAS_UV( 64, 32), ATLAS_UV( 80, 48) },
{ ATLAS_UV( 80, 32), ATLAS_UV( 96, 48) },
{ ATLAS_UV( 0, 48), ATLAS_UV( 16, 64) },
{ ATLAS_UV( 16, 48), ATLAS_UV( 32, 64) },
{ ATLAS_UV( 32, 48), ATLAS_UV( 48, 64) },
{ ATLAS_UV( 48, 48), ATLAS_UV( 64, 64) },
{ ATLAS_UV( 64, 48), ATLAS_UV( 80, 64) },
{ ATLAS_UV( 80, 48), ATLAS_UV( 88, 56) }, /* 8 x 8 v */
{ ATLAS_UV( 88, 48), ATLAS_UV( 96, 56) },
{ ATLAS_UV( 80, 56), ATLAS_UV( 88, 64) },
{ ATLAS_UV( 88, 56), ATLAS_UV( 96, 64) },
{ ATLAS_UV( 0, 64), ATLAS_UV( 16,104) }, /* 16 x 40 */
{ ATLAS_UV( 16, 64), ATLAS_UV( 32,104) },
{ ATLAS_UV( 32, 64), ATLAS_UV( 48,104) },
{ ATLAS_UV( 48, 64), ATLAS_UV( 88,104) } /* 40 x 40 */
vec2 position;
vec2 size;
};
#define ATLAS_UV_ARGS(type) ATLAS_UVS[type][0], ATLAS_UVS[type][1]
const vec2 ATLAS_SIZE_SMALL = {8, 8};
const vec2 ATLAS_SIZE_NORMAL = {16, 16};
const vec2 ATLAS_SIZE_OBLONG = {16, 40};
const vec2 ATLAS_SIZE_BIG = {40, 40};
const vec2 ATLAS_SIZES[TEXTURE_COUNT] =
const inline AtlasEntry ATLAS_ENTRIES[ATLAS_COUNT] =
{
TEXTURE_SIZE,
TEXTURE_SIZE,
TEXTURE_SIZE,
TEXTURE_SIZE,
TEXTURE_SIZE,
TEXTURE_SIZE,
TEXTURE_SIZE,
TEXTURE_SIZE,
TEXTURE_SIZE,
TEXTURE_SIZE,
TEXTURE_SIZE,
TEXTURE_SIZE,
TEXTURE_SIZE,
TEXTURE_SIZE,
TEXTURE_SIZE,
TEXTURE_SIZE,
TEXTURE_SIZE,
TEXTURE_SIZE,
TEXTURE_SIZE,
TEXTURE_SIZE,
TEXTURE_SIZE,
TEXTURE_SIZE,
TEXTURE_SIZE,
TEXTURE_SIZE_SMALL,
TEXTURE_SIZE_SMALL,
TEXTURE_SIZE_SMALL,
TEXTURE_SIZE_SMALL,
TEXTURE_SIZE_OBLONG,
TEXTURE_SIZE_OBLONG,
TEXTURE_SIZE_OBLONG,
TEXTURE_SIZE_BIG
{{ 0, 0}, ATLAS_SIZE_NORMAL},
{{ 16, 0}, ATLAS_SIZE_NORMAL},
{{ 32, 0}, ATLAS_SIZE_NORMAL},
{{ 48, 0}, ATLAS_SIZE_NORMAL},
{{ 64, 0}, ATLAS_SIZE_NORMAL},
{{ 80, 0}, ATLAS_SIZE_NORMAL},
{{ 0, 16}, ATLAS_SIZE_NORMAL},
{{ 16, 16}, ATLAS_SIZE_NORMAL},
{{ 32, 16}, ATLAS_SIZE_NORMAL},
{{ 48, 16}, ATLAS_SIZE_NORMAL},
{{ 64, 16}, ATLAS_SIZE_NORMAL},
{{ 80, 16}, ATLAS_SIZE_NORMAL},
{{ 0, 32}, ATLAS_SIZE_NORMAL},
{{ 16, 32}, ATLAS_SIZE_NORMAL},
{{ 32, 32}, ATLAS_SIZE_NORMAL},
{{ 48, 32}, ATLAS_SIZE_NORMAL},
{{ 64, 32}, ATLAS_SIZE_NORMAL},
{{ 80, 32}, ATLAS_SIZE_NORMAL},
{{ 0, 48}, ATLAS_SIZE_NORMAL},
{{ 16, 48}, ATLAS_SIZE_NORMAL},
{{ 32, 48}, ATLAS_SIZE_NORMAL},
{{ 48, 48}, ATLAS_SIZE_NORMAL},
{{ 64, 48}, ATLAS_SIZE_NORMAL},
{{ 80, 48}, ATLAS_SIZE_NORMAL},
{{ 0, 64}, ATLAS_SIZE_NORMAL},
{{ 16, 64}, ATLAS_SIZE_NORMAL},
{{ 32, 64}, ATLAS_SIZE_NORMAL},
{{ 48, 64}, ATLAS_SIZE_NORMAL},
{{ 64, 64}, ATLAS_SIZE_NORMAL},
{{ 80, 64}, ATLAS_SIZE_SMALL },
{{ 88, 64}, ATLAS_SIZE_SMALL },
{{ 80, 72}, ATLAS_SIZE_SMALL },
{{ 88, 72}, ATLAS_SIZE_SMALL },
{{ 0, 80}, ATLAS_SIZE_OBLONG},
{{16, 80}, ATLAS_SIZE_OBLONG},
{{32, 80}, ATLAS_SIZE_OBLONG},
{{48, 80}, ATLAS_SIZE_BIG}
};
#define ATLAS_UV_VERTICES(type) UV_VERTICES(ATLAS_UVS[type][0], ATLAS_UVS[type][1])
#define ATLAS_POSITION(type) ATLAS_ENTRIES[type].position
#define ATLAS_SIZE(type) ATLAS_ENTRIES[type].size
#define ATLAS_UV_MIN(type) (ATLAS_POSITION(type) / TEXTURE_ATLAS_SIZE)
#define ATLAS_UV_MAX(type) ((ATLAS_POSITION(type) + ATLAS_SIZE(type)) / TEXTURE_ATLAS_SIZE)
#define ATLAS_UV_ARGS(type) ATLAS_UV_MIN(type), ATLAS_UV_MAX(type)
#define ATLAS_UV_VERTICES(type) UV_VERTICES(ATLAS_UV_MIN(type), ATLAS_UV_MAX(type))
/* Shaders */
struct ShaderData
{
std::string vertex;
@@ -331,4 +269,4 @@ const ShaderData SHADER_DATA[SHADER_COUNT] =
{
{SHADER_VERTEX, SHADER_FRAGMENT},
{SHADER_VERTEX, SHADER_TEXTURE_FRAGMENT}
};
};

View File

@@ -228,21 +228,6 @@ void canvas_rect_draw(Canvas* self, const GLuint& shader, const mat4& transform,
glUseProgram(0);
}
void canvas_rect_dotted_draw(Canvas* self, const GLuint& shader, const mat4& transform, const vec4& color)
{
glUseProgram(shader);
glBindVertexArray(self->rectVAO);
glUniformMatrix4fv(glGetUniformLocation(shader, SHADER_UNIFORM_TRANSFORM), 1, GL_FALSE, value_ptr(transform));
glUniform4fv(glGetUniformLocation(shader, SHADER_UNIFORM_COLOR), 1, value_ptr(color));
glDrawArrays(GL_LINE_LOOP, 0, 4);
glBindVertexArray(0);
glUseProgram(0);
}
void canvas_axes_draw(Canvas* self, GLuint& shader, mat4& transform, vec4& color)
{
glUseProgram(shader);

View File

@@ -2,8 +2,6 @@
#include "dialog.h"
static void _dialog_callback(void* userdata, const char* const* filelist, s32 filter);
static void _dialog_callback(void* userdata, const char* const* filelist, s32 filter)
{
Dialog* self;
@@ -23,91 +21,59 @@ static void _dialog_callback(void* userdata, const char* const* filelist, s32 fi
}
}
void dialog_init(Dialog* self, Anm2* anm2, Anm2Reference* reference, Resources* resources, SDL_Window* window)
void dialog_init(Dialog* self, SDL_Window* window)
{
self->anm2 = anm2;
self->reference = reference;
self->resources = resources;
self->window = window;
}
void dialog_anm2_open(Dialog* self)
{
SDL_ShowOpenFileDialog(_dialog_callback, self, nullptr, DIALOG_FILE_FILTER_ANM2, 1, nullptr, false);
SDL_ShowOpenFileDialog(_dialog_callback, self, self->window, DIALOG_FILE_FILTER_ANM2, 1, nullptr, false);
self->type = DIALOG_ANM2_OPEN;
}
void dialog_anm2_save(Dialog* self)
{
SDL_ShowSaveFileDialog(_dialog_callback, self, nullptr, DIALOG_FILE_FILTER_ANM2, 1, nullptr);
SDL_ShowSaveFileDialog(_dialog_callback, self, self->window, DIALOG_FILE_FILTER_ANM2, 1, nullptr);
self->type = DIALOG_ANM2_SAVE;
}
void dialog_png_open(Dialog* self)
void dialog_spritesheet_add(Dialog* self)
{
SDL_ShowOpenFileDialog(_dialog_callback, self, nullptr, DIALOG_FILE_FILTER_PNG, 1, nullptr, false);
self->type = DIALOG_PNG_OPEN;
SDL_ShowOpenFileDialog(_dialog_callback, self, self->window, DIALOG_FILE_FILTER_PNG, 1, nullptr, false);
self->type = DIALOG_SPRITESHEET_ADD;
}
void dialog_png_replace(Dialog* self)
void dialog_spritesheet_replace(Dialog* self, s32 id)
{
SDL_ShowOpenFileDialog(_dialog_callback, self, nullptr, DIALOG_FILE_FILTER_PNG, 1, nullptr, false);
self->type = DIALOG_PNG_REPLACE;
SDL_ShowOpenFileDialog(_dialog_callback, self, self->window, DIALOG_FILE_FILTER_PNG, 1, nullptr, false);
self->replaceID = id;
self->type = DIALOG_SPRITESHEET_REPLACE;
}
void dialog_update(Dialog* self)
void dialog_render_path_set(Dialog* self)
{
self->isJustSelected = false;
SDL_ShowSaveFileDialog(_dialog_callback, self, self->window, DIALOG_FILE_FILTER_RENDER, 2, nullptr);
self->type = DIALOG_RENDER_PATH_SET;
}
if (self->isSelected)
{
Texture texture;
s32 id;
switch (self->type)
{
case DIALOG_ANM2_OPEN:
*self->reference = Anm2Reference{};
resources_textures_free(self->resources);
anm2_deserialize(self->anm2, self->resources, self->path);
window_title_from_path_set(self->window, self->path);
break;
case DIALOG_ANM2_SAVE:
anm2_serialize(self->anm2, self->path);
window_title_from_path_set(self->window, self->path);
break;
case DIALOG_PNG_OPEN:
id = map_next_id_get(self->resources->textures);
self->anm2->spritesheets[id] = Anm2Spritesheet{};
self->anm2->spritesheets[id].path = self->path;
resources_texture_init(self->resources, self->path, id);
break;
case DIALOG_PNG_REPLACE:
self->anm2->spritesheets[self->replaceID].path = self->path;
resources_texture_init(self->resources, self->path, self->replaceID);
self->replaceID = -1;
break;
default:
break;
}
void dialog_render_directory_set(Dialog* self)
{
SDL_ShowOpenFolderDialog(_dialog_callback, self, self->window, nullptr, false);
self->type = DIALOG_RENDER_DIRECTORY_SET;
}
self->lastType = self->type;
self->lastPath = self->path;
self->type = DIALOG_NONE;
self->path.clear();
self->isJustSelected = true;
self->isSelected = false;
}
void dialog_ffmpeg_path_set(Dialog* self)
{
SDL_ShowOpenFileDialog(_dialog_callback, self, self->window, DIALOG_FILE_FILTER_FFMPEG, 1, nullptr, false);
self->type = DIALOG_FFMPEG_PATH_SET;
}
void
dialog_reset(Dialog* self)
{
self->lastType = DIALOG_NONE;
self->replaceID = ID_NONE;
self->type = DIALOG_NONE;
self->lastPath.clear();
self->path.clear();
self->isJustSelected = false;
self->isSelected = false;
}

View File

@@ -1,17 +1,26 @@
#pragma once
#include "anm2.h"
#include "resources.h"
#include "window.h"
const SDL_DialogFileFilter DIALOG_FILE_FILTER_ANM2[] =
{
{"Anm2", "anm2;xml"}
{"Anm2 file", "anm2;xml"}
};
const SDL_DialogFileFilter DIALOG_FILE_FILTER_PNG[] =
{
{"png", "png"}
{"PNG image", "png"}
};
const SDL_DialogFileFilter DIALOG_FILE_FILTER_RENDER[] =
{
{"GIF image", "gif"},
{"WebM video", "webm"}
};
const SDL_DialogFileFilter DIALOG_FILE_FILTER_FFMPEG[] =
{
{"Executable", ""}
};
enum DialogType
@@ -19,32 +28,29 @@ enum DialogType
DIALOG_NONE,
DIALOG_ANM2_OPEN,
DIALOG_ANM2_SAVE,
DIALOG_PNG_OPEN,
DIALOG_PNG_REPLACE,
DIALOG_FRAME_DIRECTORY_OPEN,
DIALOG_SPRITESHEET_ADD,
DIALOG_SPRITESHEET_REPLACE,
DIALOG_RENDER_PATH_SET,
DIALOG_RENDER_DIRECTORY_SET,
DIALOG_FFMPEG_PATH_SET
};
struct Dialog
{
Anm2* anm2 = nullptr;
Anm2Reference* reference = nullptr;
Resources* resources = nullptr;
SDL_Window* window = nullptr;
s32 selectedFilter = ID_NONE;
std::string path{};
std::string lastPath{};
s32 replaceID = ID_NONE;
s32 selectedFilter{};
DialogType type = DIALOG_NONE;
DialogType lastType = DIALOG_NONE;
bool isSelected = false;
bool isJustSelected = false;
};
void dialog_init(Dialog* self, Anm2* anm2, Anm2Reference* reference, Resources* resources, SDL_Window* window);
void dialog_init(Dialog* self, SDL_Window* window);
void dialog_anm2_open(Dialog* self);
void dialog_png_open(Dialog* self);
void dialog_png_replace(Dialog* self);
void dialog_spritesheet_add(Dialog* self);
void dialog_spritesheet_replace(Dialog* self, s32 id);
void dialog_anm2_save(Dialog* self);
void dialog_frame_directory_open(Dialog* self);
void dialog_update(Dialog* self);
void dialog_render_path_set(Dialog* self);
void dialog_render_directory_set(Dialog* self);
void dialog_ffmpeg_path_set(Dialog* self);
void dialog_reset(Dialog* self);

View File

@@ -44,7 +44,7 @@ void editor_draw(Editor* self)
canvas_rect_draw(&self->canvas, shaderLine, mvp, EDITOR_FRAME_COLOR);
mvp = canvas_mvp_get(transform, CANVAS_PIVOT_SIZE, frame->crop + frame->pivot, CANVAS_PIVOT_SIZE * 0.5f);
f32 vertices[] = ATLAS_UV_VERTICES(TEXTURE_PIVOT);
f32 vertices[] = ATLAS_UV_VERTICES(ATLAS_PIVOT);
canvas_texture_draw(&self->canvas, shaderTexture, self->resources->atlas.id, mvp, vertices, EDITOR_PIVOT_COLOR);
}
}

60
src/ffmpeg.cpp Normal file
View File

@@ -0,0 +1,60 @@
#include "ffmpeg.h"
bool
ffmpeg_render
(
const std::string& ffmpegPath,
const std::string& outputPath,
const std::vector<Texture>& frames,
ivec2 size,
s32 fps,
enum RenderType type
)
{
if (frames.empty() || size.x <= 0 || size.y <= 0 || fps <= 0 || ffmpegPath.empty() || outputPath.empty()) return false;
std::string command{};
switch (type)
{
case RENDER_GIF:
command = std::format(FFMPEG_GIF_FORMAT, ffmpegPath, size.x, size.y, fps, outputPath);
break;
case RENDER_WEBM:
command = std::format(FFMPEG_WEBM_FORMAT, ffmpegPath, size.x, size.y, fps, outputPath);
break;
default:
return false;
}
FILE* fp = POPEN(command.c_str(), PWRITE_MODE);
if (!fp)
{
log_info(std::format(FFMPEG_POPEN_ERROR, strerror(errno)));
return false;
}
size_t frameBytes = size.x * size.y * TEXTURE_CHANNELS;
for (const auto& frame : frames)
{
std::vector<u8> rgba = texture_download(&frame);
if (rgba.size() != frameBytes)
{
PCLOSE(fp);
return false;
}
if (fwrite(rgba.data(), 1, frameBytes, fp) != frameBytes)
{
PCLOSE(fp);
return false;
}
}
const int code = PCLOSE(fp);
return (code == 0);
}

32
src/ffmpeg.h Normal file
View File

@@ -0,0 +1,32 @@
#pragma once
#include "render.h"
#include "texture.h"
#define FFMPEG_POPEN_ERROR "popen() (for FFmpeg) failed!\n{}"
static constexpr const char* FFMPEG_GIF_FORMAT =
"\"{0}\" -y "
"-f rawvideo -pix_fmt rgba -s {1}x{2} -r {3} -i pipe:0 "
"-lavfi \"split[s0][s1];"
"[s0]palettegen=stats_mode=full[p];"
"[s1][p]paletteuse=dither=floyd_steinberg\" "
"-loop 0 \"{4}\"";
static constexpr const char* FFMPEG_WEBM_FORMAT =
"\"{0}\" -y "
"-f rawvideo -pix_fmt rgba -s {1}x{2} -r {3} -i pipe:0 "
"-c:v libvpx-vp9 -crf 30 -b:v 0 -pix_fmt yuva420p -row-mt 1 -threads 0 -speed 2 "
"-auto-alt-ref 0 -an \"{4}\"";
bool
ffmpeg_render
(
const std::string& ffmpegPath,
const std::string& outputPath,
const std::vector<Texture>& frames,
ivec2 size,
s32 fps,
enum RenderType type
);

View File

@@ -35,9 +35,9 @@ static void _imgui_clipboard_hovered_item_set(Imgui* self, const T& data)
self->clipboard->hoveredItem = ClipboardItem(data);
}
static void _imgui_atlas_image(Imgui* self, TextureType type)
static void _imgui_atlas_image(Imgui* self, AtlasType type)
{
ImGui::Image(self->resources->atlas.id, ATLAS_SIZES[type], ATLAS_UV_ARGS(type));
ImGui::Image(self->resources->atlas.id, ATLAS_SIZE(type), ATLAS_UV_ARGS(type));
}
static void _imgui_item_text(const ImguiItem& item)
@@ -83,7 +83,7 @@ static void _imgui_item(Imgui* self, const ImguiItem& item, bool* isActivated)
}
}
if (isActivated && self->isHotkeysEnabled && (item.is_chord() && ImGui::IsKeyChordPressed(item.chord)))
if (isActivated && self->isContextualActionsEnabled && (item.is_chord() && ImGui::IsKeyChordPressed(item.chord)))
if (item.is_focus_window() && (imgui_nav_window_root_get() == item.focusWindow))
*isActivated = true;
@@ -97,25 +97,43 @@ static void _imgui_item(Imgui* self, const ImguiItem& item, bool* isActivated)
if (item.is_popup())
{
ImGui::OpenPopup(item.popup.c_str());
switch (item.popupType)
{
case IMGUI_POPUP_CENTER_SCREEN:
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
break;
case IMGUI_POPUP_BY_ITEM:
default:
ImGui::SetNextWindowPos(ImVec2(ImGui::GetItemRectMin().x, ImGui::GetItemRectMin().y + ImGui::GetItemRectSize().y));
break;
}
self->pendingPopup = item.popup;
self->pendingPopupType = item.popupType;
self->pendingPopupPosition = ImVec2(ImGui::GetItemRectMin().x, ImGui::GetItemRectMin().y + ImGui::GetItemRectSize().y);
}
}
}
static bool _imgui_item_combo(Imgui* self, const ImguiItem& item, s32* current, const char* const items[], s32 count)
static void _imgui_pending_popup_process(Imgui* self)
{
bool isActivated = ImGui::Combo(item.label.c_str(), current, items, count);
if (self->pendingPopup.empty()) return;
switch (self->pendingPopupType)
{
case IMGUI_POPUP_CENTER_SCREEN:
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
break;
case IMGUI_POPUP_BY_ITEM:
default:
ImGui::SetNextWindowPos(self->pendingPopupPosition);
break;
}
ImGui::OpenPopup(self->pendingPopup.c_str());
self->pendingPopup.clear();
self->pendingPopupType = IMGUI_POPUP_NONE;
self->pendingPopupPosition = ImVec2();
}
static bool _imgui_item_combo(Imgui* self, const ImguiItem& item, s32* current)
{
std::vector<const char*> cStrings;
cStrings.reserve(item.items.size());
for (auto& string : item.items)
cStrings.push_back(string.c_str());
bool isActivated = ImGui::Combo(item.label.c_str(), current, cStrings.data(), (s32)item.items.size());
_imgui_item(self, item, &isActivated);
return isActivated;
}
@@ -125,14 +143,15 @@ static bool _imgui_item_selectable(Imgui* self, const ImguiItem& item)
const char* label = item.label.c_str();
s32 flags = item.flags;
if (item.isInactive || item.color.is_normal())
if (item.isInactive)
{
vec4 color = item.isInactive ? IMGUI_INACTIVE_COLOR : item.color.normal;
ImGui::PushStyleColor(ImGuiCol_Text, color);
flags |= ImGuiSelectableFlags_Disabled;
}
ImGui::PushStyleColor(ImGuiCol_Text, IMGUI_INACTIVE_COLOR);
flags |= ImGuiSelectableFlags_Disabled;
}
else if (item.color.is_normal())
ImGui::PushStyleColor(ImGuiCol_Text, item.color.normal);
ImVec2 size = item.is_size() ? item.size : item.isSizeToText ? ImGui::CalcTextSize(label) :ImVec2(0, 0);
ImVec2 size = item.is_size() ? item.size : item.isSizeToText ? ImGui::CalcTextSize(label) : ImVec2();
bool isActivated = ImGui::Selectable(label, item.isSelected, flags, size);
_imgui_item(self, item, &isActivated);
@@ -173,14 +192,19 @@ static bool _imgui_item_inputint2(Imgui* self, const ImguiItem& item, ivec2& val
static bool _imgui_item_inputtext(Imgui* self, const ImguiItem& item, std::string& buffer)
{
if ((s32)buffer.size() < item.max) buffer.resize(item.max);
if ((s32)buffer.size() < (s32)item.max) buffer.resize(item.max);
ImVec2 size = item.is_size() ? item.size : ImVec2(-FLT_MIN, 0);
if (item.isSizeToChild)
{
size.x = (ImGui::GetWindowSize().x - ImGui::GetStyle().ItemSpacing.x * (item.childRowItemCount + 1)) / item.childRowItemCount;
size.x -= ImGui::CalcTextSize(item.label.c_str()).x * 2;
}
ImGui::SetNextItemWidth(size.x);
ImGui::InputText(item.label.c_str(), &buffer[0], item.max, item.flags);
bool isActivated = ImGui::IsItemActivated();
bool isActivated = ImGui::InputText(item.label.c_str(), &buffer[0], item.max, item.flags);
_imgui_item(self, item, &isActivated);
return isActivated;
@@ -292,7 +316,7 @@ static bool _imgui_item_selectable_inputtext(Imgui* self, const ImguiItem& item,
renameID = ID_NONE;
itemID = ID_NONE;
self->isRename = false;
self->isContextualActionsEnabled = true;
}
ImGui::PopID();
@@ -307,6 +331,7 @@ static bool _imgui_item_selectable_inputtext(Imgui* self, const ImguiItem& item,
renameID = id;
itemID = item.id;
ImGui::SetKeyboardFocusHere(-1);
self->isContextualActionsEnabled = false;
}
}
@@ -340,6 +365,7 @@ static bool _imgui_item_selectable_inputint(Imgui* self, const ImguiItem& item,
itemID = ID_NONE;
changeID = ID_NONE;
self->isChangeValue = false;
self->isContextualActionsEnabled = true;
}
ImGui::PopID();
@@ -353,6 +379,7 @@ static bool _imgui_item_selectable_inputint(Imgui* self, const ImguiItem& item,
itemID = item.id;
changeID = id;
ImGui::SetKeyboardFocusHere(-1);
self->isContextualActionsEnabled = false;
}
}
@@ -361,16 +388,9 @@ static bool _imgui_item_selectable_inputint(Imgui* self, const ImguiItem& item,
return isActivated;
}
static void _imgui_item_atlas_image_text(Imgui* self, const ImguiItem& item)
{
_imgui_atlas_image(self, item.texture);
ImGui::SameLine();
ImGui::Text(item.label.c_str());
}
static bool _imgui_item_atlas_image_selectable(Imgui* self, const ImguiItem& item)
{
_imgui_atlas_image(self, item.texture);
_imgui_atlas_image(self, item.atlas);
ImGui::SameLine();
return _imgui_item_selectable(self, item);
}
@@ -388,14 +408,14 @@ static bool _imgui_item_text_inputtext(Imgui* self, const ImguiItem& item, std::
static bool _imgui_item_atlas_image_selectable_inputtext(Imgui* self, ImguiItem& item, std::string& string, s32 id)
{
_imgui_atlas_image(self, item.texture);
_imgui_atlas_image(self, item.atlas);
ImGui::SameLine();
return _imgui_item_selectable_inputtext(self, item, string, id);
}
static bool _imgui_item_atlas_image_selectable_inputint(Imgui* self, ImguiItem& item, s32& value, s32 id)
{
_imgui_atlas_image(self, item.texture);
_imgui_atlas_image(self, item.atlas);
ImGui::SameLine();
return _imgui_item_selectable_inputint(self, item, value, id);
}
@@ -407,7 +427,7 @@ static bool _imgui_item_atlas_image_checkbox_selectable(Imgui* self, const Imgui
_imgui_item_checkbox(self, checkboxItem, value);
ImGui::SameLine();
_imgui_atlas_image(self, item.texture);
_imgui_atlas_image(self, item.atlas);
ImGui::SameLine();
return _imgui_item_selectable(self, item);
}
@@ -415,7 +435,7 @@ static bool _imgui_item_atlas_image_checkbox_selectable(Imgui* self, const Imgui
static bool _imgui_item_atlas_image_button(Imgui* self, const ImguiItem& item)
{
bool isActivated = false;
ImVec2 imageSize = (ATLAS_SIZES[item.texture]);
ImVec2 imageSize = (ATLAS_SIZE(item.atlas));
ImVec2 buttonSize = item.is_size() ? item.size : imageSize;
if (item.color.is_normal()) ImGui::PushStyleColor(ImGuiCol_Button, item.color.normal);
@@ -432,10 +452,10 @@ static bool _imgui_item_atlas_image_button(Imgui* self, const ImguiItem& item)
ImVec2 imageMin = pos + item.contentOffset;
ImVec2 imageMax = imageMin + imageSize;
ImGui::GetWindowDrawList()->AddImage(self->resources->atlas.id, imageMin, imageMax, ATLAS_UV_ARGS(item.texture));
ImGui::GetWindowDrawList()->AddImage(self->resources->atlas.id, imageMin, imageMax, ATLAS_UV_ARGS(item.atlas));
}
else
isActivated = ImGui::ImageButton(item.label.c_str(), self->resources->atlas.id, buttonSize, ATLAS_UV_ARGS(item.texture));
isActivated = ImGui::ImageButton(item.label.c_str(), self->resources->atlas.id, buttonSize, ATLAS_UV_ARGS(item.atlas));
_imgui_item(self, item, &isActivated);
if (item.color.is_normal()) ImGui::PopStyleColor();
@@ -481,26 +501,32 @@ static void _imgui_keyboard_navigation_set(bool value)
if (!value) ImGui::GetIO().ConfigFlags &= ~ImGuiConfigFlags_NavEnableKeyboard;
}
static bool _imgui_item_yes_no_popup(Imgui* self, const ImguiItem& item)
static bool _imgui_item_option_popup(Imgui* self, const ImguiItem& item)
{
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
if (ImGui::BeginPopupModal(item.popup.c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize))
{
self->isContextualActionsEnabled = false;
ImGui::Text(item.label.c_str());
ImGui::Separator();
if (_imgui_item_button(self, IMGUI_POPUP_YES_BUTTON))
if (_imgui_item_button(self, IMGUI_POPUP_CONFIRM_BUTTON))
{
ImGui::CloseCurrentPopup();
ImGui::EndPopup();
self->isContextualActionsEnabled = true;
return true;
}
ImGui::SameLine();
if (_imgui_item_button(self, IMGUI_POPUP_NO_BUTTON))
if (_imgui_item_button(self, IMGUI_POPUP_CANCEL_BUTTON))
{
ImGui::CloseCurrentPopup();
self->isContextualActionsEnabled = true;
}
ImGui::EndPopup();
}
@@ -639,7 +665,7 @@ static void _imgui_timeline(Imgui* self)
drawList->AddText(textPosition, textColor, buffer.c_str());
}
drawList->AddImage(self->resources->atlas.id, positionStart, positionEnd, ATLAS_UV_ARGS(TEXTURE_FRAME));
drawList->AddImage(self->resources->atlas.id, positionStart, positionEnd, ATLAS_UV_ARGS(ATLAS_FRAME_ALT));
}
_imgui_item_end_child(); // IMGUI_TIMELINE_HEADER
@@ -656,7 +682,7 @@ static void _imgui_timeline(Imgui* self)
drawList = ImGui::GetWindowDrawList();
drawList->PushClipRect(clipRectMin, clipRectMax, true);
drawList->AddImage(self->resources->atlas.id, pos, ImVec2(pos.x + frameSize.x, pos.y + frameSize.y), ATLAS_UV_ARGS(TEXTURE_PICKER));
drawList->AddImage(self->resources->atlas.id, pos, ImVec2(pos.x + frameSize.x, pos.y + frameSize.y), ATLAS_UV_ARGS(ATLAS_PICKER));
drawList->AddRectFilled(lineStart, lineEnd, IMGUI_PICKER_LINE_COLOR);
drawList->PopClipRect();
@@ -669,7 +695,7 @@ static void _imgui_timeline(Imgui* self)
if (!item) return;
ImVec2 buttonSize = ImVec2(TEXTURE_SIZE) + (defaultFramePadding * ImVec2(2, 2));
ImVec2 buttonSize = ImVec2(ATLAS_SIZE_NORMAL) + (defaultFramePadding * ImVec2(2, 2));
Anm2Type& type = reference.itemType;
Anm2Layer* layer = nullptr;
@@ -749,14 +775,14 @@ static void _imgui_timeline(Imgui* self)
if (type == ANM2_NULL)
{
ImguiItem rectItem = null->isShowRect ? IMGUI_TIMELINE_ITEM_SHOW_RECT : IMGUI_TIMELINE_ITEM_HIDE_RECT;
const ImguiItem& rectItem = null->isShowRect ? IMGUI_TIMELINE_ITEM_SHOW_RECT : IMGUI_TIMELINE_ITEM_HIDE_RECT;
if (_imgui_item_atlas_image_button(self, rectItem))
null->isShowRect = !null->isShowRect;
ImGui::SameLine(0.0f, defaultItemSpacing.x);
}
ImguiItem visibleItem = item->isVisible ? IMGUI_TIMELINE_ITEM_VISIBLE : IMGUI_TIMELINE_ITEM_INVISIBLE;
const ImguiItem& visibleItem = item->isVisible ? IMGUI_TIMELINE_ITEM_VISIBLE : IMGUI_TIMELINE_ITEM_INVISIBLE;
if (_imgui_item_atlas_image_button(self, visibleItem))
item->isVisible = !item->isVisible;
@@ -875,7 +901,7 @@ static void _imgui_timeline(Imgui* self)
ImVec2 endPosition(endX, cursorPos.y + frameSize.y);
drawList->AddRectFilled(startPosition, endPosition, bgColor);
drawList->AddImage(self->resources->atlas.id, startPosition, endPosition, ATLAS_UV_ARGS(TEXTURE_FRAME_ALT));
drawList->AddImage(self->resources->atlas.id, startPosition, endPosition, ATLAS_UV_ARGS(ATLAS_FRAME));
}
ImGui::SetCursorPos(startPos);
@@ -886,14 +912,14 @@ static void _imgui_timeline(Imgui* self)
reference.frameIndex = i;
ImguiItem frameButton = *IMGUI_TIMELINE_FRAMES[type];
ImVec2 framePos = ImGui::GetCursorPos();
frameButton.texture = frame.isInterpolated ? TEXTURE_CIRCLE : TEXTURE_SQUARE;
frameButton.atlas = frame.isInterpolated ? ATLAS_CIRCLE : ATLAS_SQUARE;
frameButton.size = {frameSize.x * frame.delay, frameSize.y};
frameButton.isSelected = reference == *self->reference;
if (type == ANM2_TRIGGERS)
{
framePos.x = startPos.x + (frameSize.x * frame.atFrame);
frameButton.texture = TEXTURE_TRIGGER;
frameButton.atlas = ATLAS_TRIGGER;
}
ImGui::SetCursorPos(framePos);
@@ -1017,21 +1043,7 @@ static void _imgui_timeline(Imgui* self)
Anm2Frame* frame = anm2_frame_from_reference(self->anm2, self->reference);
_imgui_item_begin_child(IMGUI_TIMELINE_FOOTER_ITEM_CHILD);
if(_imgui_item_button(self, IMGUI_TIMELINE_ADD_ITEM))
ImGui::OpenPopup(IMGUI_TIMELINE_ADD_ITEM.popup.c_str());
if (ImGui::BeginPopup(IMGUI_TIMELINE_ADD_ITEM.popup.c_str()))
{
if (_imgui_item_selectable(self, IMGUI_TIMELINE_ADD_ITEM_LAYER))
anm2_layer_add(self->anm2);
if (_imgui_item_selectable(self, IMGUI_TIMELINE_ADD_ITEM_NULL))
anm2_null_add(self->anm2);
ImGui::EndPopup();
}
_imgui_item_button(self, IMGUI_TIMELINE_ADD_ITEM);
ImGui::SameLine();
if (_imgui_item_button(self, IMGUI_TIMELINE_REMOVE_ITEM))
@@ -1059,7 +1071,7 @@ static void _imgui_timeline(Imgui* self)
_imgui_item_begin_child(IMGUI_TIMELINE_FOOTER_OPTIONS_CHILD);
ImguiItem playPauseItem = self->preview->isPlaying ? IMGUI_TIMELINE_PAUSE : IMGUI_TIMELINE_PLAY;
const ImguiItem& playPauseItem = self->preview->isPlaying ? IMGUI_TIMELINE_PAUSE : IMGUI_TIMELINE_PLAY;
if (_imgui_item_button(self, playPauseItem))
self->preview->isPlaying = !self->preview->isPlaying;
@@ -1082,12 +1094,35 @@ static void _imgui_timeline(Imgui* self)
ImGui::SameLine();
if (_imgui_item_button(self, IMGUI_TIMELINE_BAKE))
_imgui_item_button(self, IMGUI_TIMELINE_BAKE);
ImGui::SameLine();
if (_imgui_item_button(self, IMGUI_TIMELINE_FIT_ANIMATION_LENGTH))
anm2_animation_length_set(animation);
ImGui::SameLine();
_imgui_item_inputint(self, IMGUI_TIMELINE_ANIMATION_LENGTH, animation->frameNum);
ImGui::SameLine();
_imgui_item_inputint(self, IMGUI_TIMELINE_FPS, self->anm2->fps);
ImGui::SameLine();
_imgui_item_checkbox(self, IMGUI_TIMELINE_LOOP, animation->isLoop);
ImGui::SameLine();
_imgui_item_text_inputtext(self, IMGUI_TIMELINE_CREATED_BY, self->anm2->createdBy);
_imgui_item_end_child(); //IMGUI_TIMELINE_FOOTER_OPTIONS_CHILD
_imgui_pending_popup_process(self);
if (ImGui::BeginPopup(IMGUI_TIMELINE_ADD_ITEM.popup.c_str()))
{
if (frame)
ImGui::OpenPopup(IMGUI_TIMELINE_BAKE.popup.c_str());
else
ImGui::CloseCurrentPopup();
if (_imgui_item_selectable(self, IMGUI_TIMELINE_ADD_ITEM_LAYER))
anm2_layer_add(self->anm2);
if (_imgui_item_selectable(self, IMGUI_TIMELINE_ADD_ITEM_NULL))
anm2_null_add(self->anm2);
ImGui::EndPopup();
}
if (ImGui::BeginPopupModal(IMGUI_TIMELINE_BAKE.popup.c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize))
@@ -1129,22 +1164,6 @@ static void _imgui_timeline(Imgui* self)
ImGui::EndPopup();
}
}
ImGui::SameLine();
if (_imgui_item_button(self, IMGUI_TIMELINE_FIT_ANIMATION_LENGTH))
anm2_animation_length_set(animation);
ImGui::SameLine();
_imgui_item_inputint(self, IMGUI_TIMELINE_ANIMATION_LENGTH, animation->frameNum);
ImGui::SameLine();
_imgui_item_inputint(self, IMGUI_TIMELINE_FPS, self->anm2->fps);
ImGui::SameLine();
_imgui_item_checkbox(self, IMGUI_TIMELINE_LOOP, animation->isLoop);
ImGui::SameLine();
_imgui_item_text_inputtext(self, IMGUI_TIMELINE_CREATED_BY, self->anm2->createdBy);
_imgui_item_end_child(); //IMGUI_TIMELINE_FOOTER_OPTIONS_CHILD
_imgui_item_end(); // IMGUI_TIMELINE
@@ -1159,37 +1178,237 @@ static void _imgui_taskbar(Imgui* self)
ImGui::SetNextWindowPos(viewport->Pos);
_imgui_item_begin(taskbarItem);
Anm2Animation* animation = anm2_animation_from_reference(self->anm2, self->reference);
_imgui_item_selectable(self, IMGUI_TASKBAR_FILE);
ImGui::SameLine();
_imgui_item_selectable(self, IMGUI_TASKBAR_WIZARD);
ImGui::SameLine();
_imgui_item_selectable(self, IMGUI_TASKBAR_PLAYBACK);
_imgui_pending_popup_process(self);
if (ImGui::BeginPopup(IMGUI_TASKBAR_FILE.popup.c_str()))
{
_imgui_item_selectable(self, IMGUI_FILE_NEW);
_imgui_item_selectable(self, IMGUI_FILE_OPEN);
_imgui_item_selectable(self, IMGUI_FILE_SAVE);
_imgui_item_selectable(self, IMGUI_FILE_SAVE_AS);
_imgui_item_selectable(self, IMGUI_FILE_NEW); // imgui_file_new
_imgui_item_selectable(self, IMGUI_FILE_OPEN); // imgui_file_open
_imgui_item_selectable(self, IMGUI_FILE_SAVE); // imgui_file_save
_imgui_item_selectable(self, IMGUI_FILE_SAVE_AS); // imgui_file_save_as
ImGui::EndPopup();
}
ImGui::SameLine();
_imgui_item_selectable(self, IMGUI_TASKBAR_WIZARD);
if (ImGui::BeginPopup(IMGUI_TASKBAR_WIZARD.popup.c_str()))
{
_imgui_item_selectable(self, IMGUI_TASKBAR_WIZARD_GENERATE_ANIMATION_FROM_GRID);
_imgui_item_selectable(self, IMGUI_TASKBAR_WIZARD_RECORD_GIF_ANIMATION);
ImGui::Separator();
_imgui_item_selectable(self, IMGUI_TASKBAR_WIZARD_RENDER_ANIMATION);
ImGui::EndPopup();
}
_imgui_pending_popup_process(self);
if (ImGui::BeginPopupModal(IMGUI_TASKBAR_WIZARD_RENDER_ANIMATION.popup.c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize))
{
if (animation)
{
RenderType& type = self->settings->renderType;
std::string& path = self->settings->renderPath;
std::string& format = self->settings->renderFormat;
std::string& ffmpegPath = self->settings->ffmpegPath;
self->isContextualActionsEnabled = false;
_imgui_item_begin_child(IMGUI_RENDER_ANIMATION_CHILD);
if (_imgui_item_atlas_image_button(self, IMGUI_RENDER_ANIMATION_BROWSE))
{
switch (self->settings->renderType)
{
case RENDER_PNG:
dialog_render_directory_set(self->dialog);
break;
default:
dialog_render_path_set(self->dialog);
break;
}
}
if (self->dialog->isSelected && self->dialog->type == DIALOG_RENDER_PATH_SET)
{
path = self->dialog->path;
dialog_reset(self->dialog);
}
ImGui::SameLine();
_imgui_item_inputtext(self, IMGUI_RENDER_ANIMATION_LOCATION, path);
if (_imgui_item_atlas_image_button(self, IMGUI_RENDER_ANIMATION_FFMPEG_BROWSE))
dialog_ffmpeg_path_set(self->dialog);
if (self->dialog->isSelected && self->dialog->type == DIALOG_FFMPEG_PATH_SET)
{
ffmpegPath = self->dialog->path;
dialog_reset(self->dialog);
}
ImGui::SameLine();
_imgui_item_inputtext(self, IMGUI_RENDER_ANIMATION_FFMPEG_PATH, ffmpegPath);
_imgui_item_combo(self, IMGUI_RENDER_ANIMATION_OUTPUT, (s32*)&type);
_imgui_item_inputtext(self, IMGUI_RENDER_ANIMATION_FORMAT, format);
ImGui::Separator();
if (_imgui_item_button(self, IMGUI_RENDER_ANIMATION_CONFIRM))
{
bool isRenderStart = true;
switch (type)
{
case RENDER_PNG:
if (!std::filesystem::is_directory(path))
{
imgui_message_queue_push(self, IMGUI_MESSAGE_RENDER_ANIMATION_DIRECTORY_ERROR);
isRenderStart = false;
}
break;
case RENDER_GIF:
case RENDER_WEBM:
if (!path_valid(path))
{
imgui_message_queue_push(self, IMGUI_MESSAGE_RENDER_ANIMATION_PATH_ERROR);
isRenderStart = false;
}
default:
break;
}
if (isRenderStart)
preview_render_start(self->preview);
else
self->preview->isRenderCancelled = true;
ImGui::CloseCurrentPopup();
}
ImGui::SameLine();
if (_imgui_item_button(self, IMGUI_RENDER_ANIMATION_CANCEL))
ImGui::CloseCurrentPopup();
_imgui_item_end_child(); // IMGUI_RENDER_ANIMATION_CHILD
ImGui::EndPopup();
}
else
{
ImGui::CloseCurrentPopup();
ImGui::EndPopup();
imgui_message_queue_push(self, IMGUI_MESSAGE_RENDER_ANIMATION_NO_SELECTED_ANIMATION_ERROR);
}
}
_imgui_pending_popup_process(self);
if (ImGui::BeginPopupModal(IMGUI_RENDER_ANIMATION_CONFIRM.popup.c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize))
{
auto rendering_end = [&]()
{
preview_render_end(self->preview);
self->isContextualActionsEnabled = true;
ImGui::CloseCurrentPopup();
};
RenderType& type = self->settings->renderType;
std::string& format = self->settings->renderFormat;
std::vector<Texture>& frames = self->preview->renderFrames;
std::string path = std::string(self->settings->renderPath.c_str());
if (self->preview->isRenderCancelled)
{
rendering_end();
self->preview->isRenderCancelled = false;
}
if (!animation)
{
imgui_message_queue_push(self, IMGUI_MESSAGE_RENDER_ANIMATION_NO_ANIMATION_ERROR);
rendering_end();
}
_imgui_item_begin_child(IMGUI_RENDERING_ANIMATION_CHILD);
f32 progress = self->preview->time / (animation->frameNum - 1);
ImGui::ProgressBar(progress);
if (_imgui_item_button(self, IMGUI_RENDERING_ANIMATION_CANCEL))
self->preview->isRenderCancelled = true;
_imgui_item_end_child(); // IMGUI_RENDERING_ANIMATION_CHILD
if (self->preview->isRenderFinished && frames.empty())
{
imgui_message_queue_push(self, IMGUI_MESSAGE_RENDER_ANIMATION_NO_FRAMES_ERROR);
rendering_end();
}
if (self->preview->isRenderFinished)
{
switch (type)
{
case RENDER_PNG:
{
std::filesystem::path workingPath = std::filesystem::current_path();
std::filesystem::current_path(path);
for (auto [i, frame] : std::views::enumerate(frames))
{
std::string framePath = std::vformat(format, std::make_format_args(i));
framePath = path_extension_change(framePath, RENDER_EXTENSIONS[type]);
if (!frame.isInvalid)
texture_from_gl_write(&frame, framePath);
}
std::filesystem::current_path(workingPath);
imgui_message_queue_push(self, std::format(IMGUI_MESSAGE_RENDER_ANIMATION_FRAMES_SAVE_FORMAT, path));
break;
}
case RENDER_GIF:
case RENDER_WEBM:
{
std::string ffmpegPath = std::string(self->settings->ffmpegPath.c_str());
path = path_extension_change(path, RENDER_EXTENSIONS[type]);
if (ffmpeg_render(ffmpegPath, path, frames, self->preview->canvas.size, self->anm2->fps, type))
{
std::string message = std::format(IMGUI_MESSAGE_RENDER_ANIMATION_SAVE_FORMAT, path);
imgui_message_queue_push(self, message);
log_info(message);
}
else
{
std::string message = std::format(IMGUI_MESSAGE_RENDER_ANIMATION_FFMPEG_ERROR, path);
imgui_message_queue_push(self, message);
log_error(message);
}
break;
}
default:
break;
}
rendering_end();
}
ImGui::EndPopup();
}
if (ImGui::BeginPopupModal(IMGUI_TASKBAR_WIZARD_GENERATE_ANIMATION_FROM_GRID.popup.c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize))
{
ImGui::EndPopup();
}
ImGui::SameLine();
_imgui_item_selectable(self, IMGUI_TASKBAR_PLAYBACK);
if (ImGui::BeginPopup(IMGUI_TASKBAR_PLAYBACK.popup.c_str()))
{
_imgui_item_checkbox(self, IMGUI_PLAYBACK_ALWAYS_LOOP, self->settings->playbackIsLoop);
@@ -1197,6 +1416,30 @@ static void _imgui_taskbar(Imgui* self)
}
_imgui_item_end();
if (self->dialog->isSelected)
{
switch (self->dialog->type)
{
case DIALOG_ANM2_OPEN:
*self->reference = Anm2Reference{};
resources_textures_free(self->resources);
anm2_deserialize(self->anm2, self->resources, self->dialog->path);
window_title_from_path_set(self->window, self->dialog->path);
snapshots_reset(self->snapshots);
imgui_message_queue_push(self, std::format(IMGUI_MESSAGE_FILE_OPEN_FORMAT, self->dialog->path));
break;
case DIALOG_ANM2_SAVE:
anm2_serialize(self->anm2, self->dialog->path);
window_title_from_path_set(self->window, self->dialog->path);
imgui_message_queue_push(self, std::format(IMGUI_MESSAGE_FILE_SAVE_FORMAT, self->dialog->path));
break;
default:
break;
}
dialog_reset(self->dialog);
}
}
static void _imgui_tools(Imgui* self)
@@ -1345,8 +1588,21 @@ static void _imgui_animations(Imgui* self)
}
ImGui::SameLine();
_imgui_item_button(self, IMGUI_ANIMATIONS_MERGE);
ImGui::SameLine();
if (_imgui_item_button(self, IMGUI_ANIMATION_REMOVE) && animation)
{
anm2_animation_remove(self->anm2, self->reference->animationID);
anm2_reference_clear(self->reference);
}
ImGui::SameLine();
if (_imgui_item_button(self, IMGUI_ANIMATION_DEFAULT) && animation)
self->anm2->defaultAnimationID = self->reference->animationID;
_imgui_pending_popup_process(self);
if (ImGui::BeginPopupModal(IMGUI_ANIMATIONS_MERGE.popup.c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize))
{
@@ -1462,18 +1718,9 @@ static void _imgui_animations(Imgui* self)
ImGui::EndPopup();
}
ImGui::SameLine();
if (_imgui_item_button(self, IMGUI_ANIMATION_REMOVE) && animation)
{
anm2_animation_remove(self->anm2, self->reference->animationID);
anm2_reference_clear(self->reference);
}
ImGui::SameLine();
if (_imgui_item_button(self, IMGUI_ANIMATION_DEFAULT) && animation)
self->anm2->defaultAnimationID = self->reference->animationID;
_imgui_item_end_child(); // IMGUI_ANIMATIONS_OPTIONS_CHILD)
_imgui_item_end();
@@ -1598,7 +1845,7 @@ static void _imgui_spritesheets(Imgui* self)
spritesheetPreviewSize.y = IMGUI_SPRITESHEET_PREVIEW_SIZE.x / spritesheetAspect;
if (texture->isInvalid)
_imgui_atlas_image(self, TEXTURE_NONE);
_imgui_atlas_image(self, ATLAS_NONE);
else
ImGui::Image(texture->id, spritesheetPreviewSize);
@@ -1614,8 +1861,9 @@ static void _imgui_spritesheets(Imgui* self)
_imgui_item_begin_child(IMGUI_SPRITESHEETS_OPTIONS_CHILD);
_imgui_item_button(self, IMGUI_SPRITESHEETS_ADD);
if (_imgui_item_button(self, IMGUI_SPRITESHEETS_ADD))
dialog_spritesheet_add(self->dialog);
ImGui::SameLine();
if (_imgui_item_button(self, IMGUI_SPRITESHEETS_RELOAD))
@@ -1634,13 +1882,30 @@ static void _imgui_spritesheets(Imgui* self)
ImGui::SameLine();
if (_imgui_item_button(self, IMGUI_SPRITESHEETS_REPLACE))
if (_imgui_item_button(self, IMGUI_SPRITESHEETS_REPLACE) && highlightedID != ID_NONE)
dialog_spritesheet_replace(self->dialog, highlightedID);
if (self->dialog->isSelected)
{
if (highlightedID != ID_NONE)
switch (self->dialog->type)
{
self->dialog->replaceID = highlightedID;
dialog_png_replace(self->dialog);
case DIALOG_SPRITESHEET_ADD:
{
s32 id = map_next_id_get(self->resources->textures);
self->anm2->spritesheets[id] = Anm2Spritesheet{};
self->anm2->spritesheets[id].path = self->dialog->path;
resources_texture_init(self->resources, self->dialog->path, id);
break;
}
case DIALOG_SPRITESHEET_REPLACE:
self->anm2->spritesheets[self->dialog->replaceID].path = self->dialog->path;
resources_texture_init(self->resources, self->dialog->path, self->dialog->replaceID);
break;
default:
break;
}
dialog_reset(self->dialog);
}
ImGui::SameLine();
@@ -1688,7 +1953,7 @@ static void _imgui_spritesheets(Imgui* self)
Anm2Spritesheet* spritesheet = &self->anm2->spritesheets[id];
Texture* texture = &self->resources->textures[id];
texture_from_gl_write(texture, spritesheet->path);
imgui_message_queue_push(self, std::format(IMGUI_ACTION_SPRITESHEET_SAVE_FORMAT, id, spritesheet->path));
imgui_message_queue_push(self, std::format(IMGUI_MESSAGE_SPRITESHEET_SAVE_FORMAT, id, spritesheet->path));
std::filesystem::current_path(workingPath);
}
}
@@ -1736,29 +2001,25 @@ static void _imgui_animation_preview(Imgui* self)
_imgui_item_begin_child(IMGUI_ANIMATION_PREVIEW_BACKGROUND_SETTINGS);
_imgui_item_coloredit4(self, IMGUI_ANIMATION_PREVIEW_BACKGROUND_COLOR, self->settings->previewBackgroundColor);
std::vector<std::string> animationStrings;
std::vector<const char*> animationLabels;
std::vector<s32> animationIDs;
ImguiItem animationOverlayItem = IMGUI_ANIMATION_PREVIEW_OVERLAY;
s32 animationOverlayCount = self->anm2->animations.size() + 1;
animationStrings.reserve(self->anm2->animations.size() + 1);
animationIDs.reserve(self->anm2->animations.size() + 1);
animationLabels.reserve(self->anm2->animations.size() + 1);
animationIDs.reserve(animationOverlayCount);
animationOverlayItem.items.reserve(animationOverlayCount);
animationIDs.push_back(ID_NONE);
animationStrings.push_back(IMGUI_EVENT_NONE);
animationLabels.push_back(animationStrings.back().c_str());
animationOverlayItem.items.push_back(IMGUI_ANIMATION_NONE);
for (auto & [id, animation] : self->anm2->animations)
{
animationIDs.push_back(id);
animationStrings.push_back(animation.name);
animationLabels.push_back(animationStrings.back().c_str());
animationOverlayItem.items.push_back(animation.name);
}
s32 selectedAnimationID = std::find(animationIDs.begin(), animationIDs.end(), self->preview->animationOverlayID) - animationIDs.begin();
s32 animationIndex = std::find(animationIDs.begin(), animationIDs.end(), self->preview->animationOverlayID) - animationIDs.begin();
if (_imgui_item_combo(self, IMGUI_ANIMATION_PREVIEW_OVERLAY, &selectedAnimationID, animationLabels.data(), (s32)animationLabels.size()))
self->preview->animationOverlayID = animationIDs[selectedAnimationID];
if (_imgui_item_combo(self, animationOverlayItem, &animationIndex))
self->preview->animationOverlayID = animationIDs[animationIndex];
_imgui_item_dragfloat(self, IMGUI_ANIMATION_PREVIEW_OVERLAY_TRANSPARENCY, self->settings->previewOverlayTransparency);
_imgui_item_end_child();
@@ -1770,7 +2031,9 @@ static void _imgui_animation_preview(Imgui* self)
ImGui::SameLine();
_imgui_item_coloredit4(self, IMGUI_ANIMATION_PREVIEW_AXIS_COLOR, self->settings->previewAxisColor);
_imgui_item_checkbox(self, IMGUI_ANIMATION_PREVIEW_ROOT_TRANSFORM, self->settings->previewIsRootTransform);
_imgui_item_checkbox(self, IMGUI_ANIMATION_PREVIEW_SHOW_PIVOT, self->settings->previewIsShowPivot);
_imgui_item_checkbox(self, IMGUI_ANIMATION_PREVIEW_PIVOTS, self->settings->previewIsPivots);
ImGui::SameLine();
_imgui_item_checkbox(self, IMGUI_ANIMATION_PREVIEW_TARGETS, self->settings->previewIsTargets);
ImGui::SameLine();
_imgui_item_checkbox(self, IMGUI_ANIMATION_PREVIEW_BORDER, self->settings->previewIsBorder);
_imgui_item_end_child();
@@ -1995,6 +2258,8 @@ static void _imgui_spritesheet_editor(Imgui* self)
}
_imgui_item_end();
}
static void _imgui_frame_properties(Imgui* self)
@@ -2045,29 +2310,25 @@ static void _imgui_frame_properties(Imgui* self)
}
else if (type == ANM2_TRIGGERS)
{
std::vector<std::string> eventStrings;
std::vector<const char*> eventLabels;
std::vector<s32> eventIDs;
ImguiItem framePropertiesEventItem = IMGUI_FRAME_PROPERTIES_EVENT;
s32 eventComboCount = self->anm2->events.size() + 1;
eventStrings.reserve(self->anm2->events.size() + 1);
eventIDs.reserve(self->anm2->events.size() + 1);
eventLabels.reserve(self->anm2->events.size() + 1);
framePropertiesEventItem.items.reserve(eventComboCount);
eventIDs.reserve(eventComboCount);
framePropertiesEventItem.items.push_back(IMGUI_EVENT_NONE);
eventIDs.push_back(ID_NONE);
eventStrings.push_back(IMGUI_EVENT_NONE);
eventLabels.push_back(eventStrings.back().c_str());
for (auto & [id, event] : self->anm2->events)
{
eventIDs.push_back(id);
eventStrings.push_back(event.name);
eventLabels.push_back(eventStrings.back().c_str());
framePropertiesEventItem.items.push_back(event.name);
}
s32 selectedEventIndex = std::find(eventIDs.begin(), eventIDs.end(), frame->eventID) - eventIDs.begin();
if (_imgui_item_combo(self, IMGUI_FRAME_PROPERTIES_EVENT, &selectedEventIndex, eventLabels.data(), (s32)eventLabels.size()))
frame->eventID = eventIDs[selectedEventIndex];
s32 eventIndex = std::find(eventIDs.begin(), eventIDs.end(), frame->eventID) - eventIDs.begin();
if (_imgui_item_combo(self, framePropertiesEventItem, &eventIndex))
frame->eventID = eventIDs[eventIndex];
_imgui_item_inputint(self, IMGUI_FRAME_PROPERTIES_AT_FRAME, frame->atFrame);
frame->atFrame = std::clamp(frame->atFrame, 0, animation->frameNum - 1);
@@ -2109,7 +2370,7 @@ static void _imgui_messages(Imgui* self)
self->messageQueue.erase(self->messageQueue.begin() + i);
continue;
}
ImGui::SetNextWindowPos(position, ImGuiCond_Always, {1.0f, 1.0f});
ImGui::PushStyleColor(ImGuiCol_Border, borderColor);
ImGui::PushStyleColor(ImGuiCol_Text, textColor);
@@ -2124,36 +2385,11 @@ static void _imgui_messages(Imgui* self)
position.y -= windowSize.y + IMGUI_MESSAGE_PADDING;
}
if (self->dialog->isJustSelected)
{
switch (self->dialog->lastType)
{
case DIALOG_ANM2_OPEN:
imgui_message_queue_push(self, std::format(IMGUI_ACTION_FILE_OPEN_FORMAT, self->dialog->lastPath));
break;
case DIALOG_ANM2_SAVE:
imgui_message_queue_push(self, std::format(IMGUI_ACTION_FILE_SAVE_FORMAT, self->dialog->lastPath));
break;
default:
break;
}
dialog_reset(self->dialog);
}
}
static void _imgui_persistent(Imgui* self)
{
if (self->preview->isRecording)
{
ImVec2 mousePos = ImGui::GetMousePos();
ImGui::SetNextWindowPos(ImVec2(mousePos.x + IMGUI_TOOLTIP_OFFSET.x, mousePos.y + IMGUI_TOOLTIP_OFFSET.y));
ImGui::BeginTooltip();
_imgui_item_atlas_image_text(self, IMGUI_RECORDING);
ImGui::EndTooltip();
}
if (!self->isContextualActionsEnabled) return;
if (ImGui::IsMouseClicked(ImGuiMouseButton_Right))
ImGui::OpenPopup(IMGUI_CONTEXT_MENU.popup.c_str());
@@ -2251,9 +2487,7 @@ void imgui_update(Imgui* self)
_imgui_messages(self);
_imgui_persistent(self);
self->isHotkeysEnabled = !self->isRename && !self->isChangeValue;
if (self->isHotkeysEnabled)
if (self->isContextualActionsEnabled)
{
for (const auto& hotkey : imgui_hotkey_registry())
{
@@ -2286,7 +2520,7 @@ void imgui_update(Imgui* self)
}
}
if (_imgui_item_yes_no_popup(self, IMGUI_EXIT_CONFIRMATION))
if (_imgui_item_option_popup(self, IMGUI_EXIT_CONFIRMATION))
self->isQuit = true;
}

View File

@@ -10,6 +10,8 @@
#include "tool.h"
#include "window.h"
#include "ffmpeg.h"
#define IMGUI_IMPL_OPENGL_LOADER_CUSTOM
#define IMGUI_ENABLE_DOCKING
#define IM_VEC2_CLASS_EXTRA \
@@ -35,56 +37,69 @@
#include <imgui/backends/imgui_impl_sdl3.h>
#include <imgui/backends/imgui_impl_opengl3.h>
#define IMGUI_ANIMATION_DEFAULT_FORMAT "(*) {}"
#define IMGUI_CHORD_NONE (ImGuiMod_None)
#define IMGUI_EVENT_NONE "None"
#define IMGUI_FRAME_BORDER 2.0f
#define IMGUI_FRAME_PROPERTIES_NO_FRAME "Select a frame to show properties..."
#define IMGUI_ITEM_SELECTABLE_EDITABLE_LABEL "## Editing"
#define IMGUI_OPENGL_VERSION "#version 330"
#define IMGUI_PICKER_LINE_COLOR IM_COL32(255, 255, 255, 255)
#define IMGUI_POSITION_FORMAT "Position: {{{:6}, {:6}}}"
#define IMGUI_SPRITESHEET_FORMAT "#{} {}"
#define IMGUI_TIMELINE_CHILD_ID_LABEL "#{} {}"
#define IMGUI_TIMELINE_FOOTER_HEIGHT 40
#define IMGUI_ANIMATIONS_FOOTER_HEIGHT 40
#define IMGUI_EVENTS_FOOTER_HEIGHT 40
#define IMGUI_SPRITESHEETS_FOOTER_HEIGHT 65
#define IMGUI_TIMELINE_FRAME_BORDER 2
#define IMGUI_TIMELINE_FRAME_LABEL_FORMAT "## {}"
#define IMGUI_TIMELINE_FRAME_MULTIPLE 5
#define IMGUI_TIMELINE_MERGE
#define IMGUI_TIMELINE_NO_ANIMATION "Select an animation to show timeline..."
#define IMGUI_TIMELINE_PICKER_LINE_WIDTH 2.0f
#define IMGUI_TIMELINE_SPRITESHEET_ID_FORMAT "#{}"
#define IMGUI_INVISIBLE_LABEL_MARKER "##"
#define IMGUI_ANIMATIONS_OPTIONS_ROW_ITEM_COUNT 5
#define IMGUI_CHORD_NONE (ImGuiMod_None)
#define IMGUI_EVENTS_FOOTER_HEIGHT 40
#define IMGUI_EVENTS_OPTIONS_ROW_ITEM_COUNT 2
#define IMGUI_SPRITESHEETS_OPTIONS_FIRST_ROW_ITEM_COUNT 4
#define IMGUI_SPRITESHEETS_OPTIONS_SECOND_ROW_ITEM_COUNT 3
#define IMGUI_TIMELINE_FOOTER_ITEM_CHILD_ITEM_COUNT 2
#define IMGUI_TIMELINE_BAKE_OPTIONS_CHILD_ROW_ITEM_COUNT 2
#define IMGUI_TIMELINE_MERGE_OPTIONS_ROW_ITEM_COUNT 2
#define IMGUI_FRAME_BORDER 2.0f
#define IMGUI_MESSAGE_DURATION 3.0f
#define IMGUI_MESSAGE_PADDING 10.0f
#define IMGUI_MESSAGE_FORMAT "## Message {}"
#define IMGUI_MESSAGE_UNDO_FORMAT "Undo: {}"
#define IMGUI_MESSAGE_REDO_FORMAT "Redo: {}"
#define IMGUI_PICKER_LINE_COLOR IM_COL32(255, 255, 255, 255)
#define IMGUI_POPUP_OPTION_CHILD_ROW_ITEM_COUNT 2
#define IMGUI_RENDER_ANIMATION_OPTIONS_ROW_ITEM_COUNT 2
#define IMGUI_SPRITESHEETS_FOOTER_HEIGHT 65
#define IMGUI_SPRITESHEETS_OPTIONS_FIRST_ROW_ITEM_COUNT 4
#define IMGUI_SPRITESHEETS_OPTIONS_SECOND_ROW_ITEM_COUNT 3
#define IMGUI_TIMELINE_BAKE_OPTIONS_CHILD_ROW_ITEM_COUNT 2
#define IMGUI_TIMELINE_FOOTER_HEIGHT 40
#define IMGUI_TIMELINE_FOOTER_ITEM_CHILD_ITEM_COUNT 2
#define IMGUI_TIMELINE_FRAME_BORDER 2
#define IMGUI_TIMELINE_FRAME_MULTIPLE 5
#define IMGUI_TIMELINE_MERGE
#define IMGUI_TIMELINE_MERGE_OPTIONS_ROW_ITEM_COUNT 2
#define IMGUI_TIMELINE_PICKER_LINE_WIDTH 2.0f
#define IMGUI_ACTION_FILE_SAVE_FORMAT "Saved anm2 to: {}"
#define IMGUI_ACTION_FILE_OPEN_FORMAT "Opened anm2: {}"
#define IMGUI_ACTION_SPRITESHEET_SAVE_FORMAT "Saved spritesheet #{} to: {}"
#define IMGUI_ACTION_TRIGGER_MOVE "Trigger AtFrame"
#define IMGUI_ACTION_FRAME_SWAP "Frame Swap"
#define IMGUI_ACTION_ANIMATION_SWAP "Animation Swap"
#define IMGUI_ACTION_FRAME_TRANSFORM "Frame Transform"
#define IMGUI_ACTION_FRAME_CROP "Frame Crop"
#define IMGUI_ACTION_FRAME_SWAP "Frame Swap"
#define IMGUI_ACTION_FRAME_TRANSFORM "Frame Transform"
#define IMGUI_ACTION_ANIMATION_SWAP "Animation Swap"
#define IMGUI_ACTION_TRIGGER_MOVE "Trigger AtFrame"
#define IMGUI_MESSAGE_FILE_OPEN_FORMAT "Opened anm2: {}"
#define IMGUI_MESSAGE_FILE_SAVE_FORMAT "Saved anm2 to: {}"
#define IMGUI_MESSAGE_RENDER_ANIMATION_FRAMES_SAVE_FORMAT "Saved rendered frames to: {}"
#define IMGUI_MESSAGE_RENDER_ANIMATION_SAVE_FORMAT "Saved rendered animation to: {}"
#define IMGUI_MESSAGE_RENDER_ANIMATION_NO_SELECTED_ANIMATION_ERROR "Select an animation first to render!"
#define IMGUI_MESSAGE_RENDER_ANIMATION_NO_ANIMATION_ERROR "No animation selected; rendering cancelled."
#define IMGUI_MESSAGE_RENDER_ANIMATION_NO_FRAMES_ERROR "No frames to render; rendering cancelled."
#define IMGUI_MESSAGE_RENDER_ANIMATION_DIRECTORY_ERROR "Invalid directory! Make sure it's valid and you have write permissions."
#define IMGUI_MESSAGE_RENDER_ANIMATION_PATH_ERROR "Invalid path! Make sure it's valid and you have write permissions."
#define IMGUI_MESSAGE_RENDER_ANIMATION_FFMPEG_PATH_ERROR "Invalid FFmpeg path! Make sure you have it installed and the path is correct."
#define IMGUI_MESSAGE_RENDER_ANIMATION_FFMPEG_ERROR "FFmpeg could not render animation! Check paths or your FFmpeg installation."
#define IMGUI_MESSAGE_SPRITESHEET_SAVE_FORMAT "Saved spritesheet #{} to: {}"
#define IMGUI_ANIMATION_DEFAULT_FORMAT "(*) {}"
#define IMGUI_ANIMATION_NONE "None"
#define IMGUI_BUFFER_MAX 255
#define IMGUI_EVENT_NONE "None"
#define IMGUI_FRAME_PROPERTIES_NO_FRAME "Select a frame to show properties..."
#define IMGUI_INVISIBLE_LABEL_MARKER "##"
#define IMGUI_ITEM_SELECTABLE_EDITABLE_LABEL "## Editing"
#define IMGUI_MESSAGE_FORMAT "## Message {}"
#define IMGUI_MESSAGE_REDO_FORMAT "Redo: {}"
#define IMGUI_MESSAGE_UNDO_FORMAT "Undo: {}"
#define IMGUI_OPENGL_VERSION "#version 330"
#define IMGUI_POSITION_FORMAT "Position: ({:8}, {:8})"
#define IMGUI_SPRITESHEET_FORMAT "#{} {}"
#define IMGUI_TIMELINE_CHILD_ID_LABEL "#{} {}"
#define IMGUI_TIMELINE_FRAME_LABEL_FORMAT "## {}"
#define IMGUI_TIMELINE_NO_ANIMATION "Select an animation to show timeline..."
#define IMGUI_TIMELINE_SPRITESHEET_ID_FORMAT "#{}"
#define IMGUI_SPACING 4
const ImVec2 IMGUI_TIMELINE_FRAME_SIZE = {16, 40};
const ImVec2 IMGUI_TIMELINE_FRAME_CONTENT_OFFSET = {TEXTURE_SIZE_SMALL.x * 0.25f, (IMGUI_TIMELINE_FRAME_SIZE.y * 0.5f) - (TEXTURE_SIZE_SMALL.y * 0.5f)};
const ImVec2 IMGUI_TIMELINE_FRAME_CONTENT_OFFSET = {ATLAS_SIZE_SMALL.x * 0.25f, (IMGUI_TIMELINE_FRAME_SIZE.y * 0.5f) - (ATLAS_SIZE_SMALL.y * 0.5f)};
const ImVec2 IMGUI_TIMELINE_ITEM_SELECTABLE_SIZE = {150, 0};
const ImVec2 IMGUI_TIMELINE_ITEM_SIZE = {300, 40};
@@ -102,7 +117,7 @@ const ImVec2 IMGUI_FRAME_PROPERTIES_FLIP_BUTTON_SIZE = {100, 0};
const ImVec2 IMGUI_SPRITESHEET_PREVIEW_SIZE = {125.0, 125.0};
const ImVec2 IMGUI_TOOLTIP_OFFSET = {16, 8};
const vec2 IMGUI_SPRITESHEET_EDITOR_CROP_FORGIVENESS = {1, 1};
const ImVec2 IMGUI_CANVAS_CHILD_SIZE = {200, 85};
const ImVec2 IMGUI_CANVAS_CHILD_SIZE = {230, 85};
const ImGuiKey IMGUI_INPUT_DELETE = ImGuiKey_Delete;
const ImGuiKey IMGUI_INPUT_LEFT = ImGuiKey_LeftArrow;
@@ -136,6 +151,13 @@ struct ImguiMessage
f32 timeRemaining;
};
enum ImguiPopupType
{
IMGUI_POPUP_NONE,
IMGUI_POPUP_BY_ITEM,
IMGUI_POPUP_CENTER_SCREEN
};
struct Imgui
{
Dialog* dialog = nullptr;
@@ -149,8 +171,11 @@ struct Imgui
Clipboard* clipboard = nullptr;
SDL_Window* window = nullptr;
SDL_GLContext* glContext = nullptr;
std::string pendingPopup{};
ImguiPopupType pendingPopupType = IMGUI_POPUP_NONE;
ImVec2 pendingPopupPosition{};
std::vector<ImguiMessage> messageQueue;
bool isHotkeysEnabled = true;
bool isContextualActionsEnabled = true;
bool isRename = false;
bool isChangeValue = false;
bool isQuit = false;
@@ -173,12 +198,6 @@ static std::vector<ImguiHotkey>& imgui_hotkey_registry()
return registry;
}
enum PopupType
{
IMGUI_POPUP_BY_ITEM,
IMGUI_POPUP_CENTER_SCREEN
};
struct ImguiColorSet
{
ImVec4 normal{};
@@ -199,20 +218,21 @@ struct ImguiItemBuilder
std::string dragDrop{};
std::string format = "%.1f";
std::string focusWindow{};
std::vector<std::string> items{};
ImguiFunction function = nullptr;
ImGuiKeyChord chord = IMGUI_CHORD_NONE;
TextureType texture = TEXTURE_NONE;
PopupType popupType = IMGUI_POPUP_BY_ITEM;
AtlasType atlas = ATLAS_NONE;
ImguiPopupType popupType = IMGUI_POPUP_BY_ITEM;
bool isUndoable = false;
bool isSizeToText = true;
bool isSizeToChild = false;
ImguiColorSet color{};
ImVec2 size{};
ImVec2 contentOffset{};
s32 childRowItemCount{};
s32 childRowItemCount = 1;
f64 speed{};
f64 min{};
f64 max{};
f64 max = IMGUI_BUFFER_MAX;
s32 border{};
s32 step = 1;
s32 stepFast = 1;
@@ -231,10 +251,11 @@ struct ImguiItem
std::string dragDrop{};
std::string format = "%.1f";
std::string focusWindow{};
std::vector<std::string> items{};
ImguiFunction function = nullptr;
ImGuiKeyChord chord = IMGUI_CHORD_NONE;
TextureType texture = TEXTURE_NONE;
PopupType popupType = IMGUI_POPUP_BY_ITEM;
AtlasType atlas = ATLAS_NONE;
ImguiPopupType popupType = IMGUI_POPUP_BY_ITEM;
bool isUndoable = false;
bool isInactive = false;
bool isSizeToText = true;
@@ -242,7 +263,7 @@ struct ImguiItem
bool isSelected = false;
f64 speed{};
f64 min{};
f64 max{};
f64 max = IMGUI_BUFFER_MAX;
s32 border{};
s32 childRowItemCount = 1;
s32 step = 1;
@@ -276,10 +297,11 @@ struct ImguiItem
dragDrop = builder.dragDrop;
format = builder.format;
focusWindow = builder.focusWindow;
items = builder.items;
function = builder.function;
chord = builder.chord;
popupType = builder.popupType;
texture = builder.texture;
atlas = builder.atlas;
isUndoable = builder.isUndoable;
isSizeToText = builder.isSizeToText;
isSizeToChild = builder.isSizeToChild;
@@ -363,7 +385,7 @@ static inline void imgui_file_save(Imgui* self)
else
{
anm2_serialize(self->anm2, self->anm2->path);
imgui_message_queue_push(self, std::format(IMGUI_ACTION_FILE_SAVE_FORMAT, self->anm2->path));
imgui_message_queue_push(self, std::format(IMGUI_MESSAGE_FILE_SAVE_FORMAT, self->anm2->path));
}
}
@@ -372,20 +394,6 @@ static inline void imgui_file_save_as(Imgui* self)
dialog_anm2_save(self->dialog);
}
static inline void imgui_png_open(Imgui* self)
{
dialog_png_open(self->dialog);
}
static inline void imgui_generate_gif_animation(Imgui* self)
{
if (anm2_animation_from_reference(self->anm2, self->reference))
{
self->preview->isRecording = true;
self->preview->time = 0;
}
}
static inline void imgui_undo_stack_push(Imgui* self, const std::string& action = SNAPSHOT_ACTION)
{
Snapshot snapshot = {*self->anm2, *self->reference, self->preview->time, action};
@@ -549,11 +557,90 @@ const inline ImguiItem IMGUI_TASKBAR_WIZARD_GENERATE_ANIMATION_FROM_GRID = Imgui
.popupType = IMGUI_POPUP_CENTER_SCREEN
});
const inline ImguiItem IMGUI_TASKBAR_WIZARD_RECORD_GIF_ANIMATION = ImguiItem
const inline ImguiItem IMGUI_TASKBAR_WIZARD_RENDER_ANIMATION = ImguiItem
({
.label = "G&enerate GIF Animation",
.tooltip = "Generates a GIF animation from the current animation.",
.function = imgui_generate_gif_animation
.label = "&Render Animation",
.tooltip = "Renders the current animation preview; output options can be customized.",
.popup = "Render Animation",
.popupType = IMGUI_POPUP_CENTER_SCREEN
});
const inline ImguiItem IMGUI_RENDER_ANIMATION_CHILD = ImguiItem
({
.label = "## Render Animation Child",
.size = {600, 125}
});
const inline ImguiItem IMGUI_RENDER_ANIMATION_LOCATION = ImguiItem
({
.label = "Location",
.tooltip = "Set the rendered animation's output location.",
.isSizeToChild = true
});
const inline ImguiItem IMGUI_RENDER_ANIMATION_BROWSE = ImguiItem
({
.label = "## Location Browse",
.atlas = ATLAS_FOLDER
});
const inline ImguiItem IMGUI_RENDER_ANIMATION_OUTPUT = ImguiItem
({
.label = "Output",
.tooltip = "Select the rendered animation output.\nIt can either be one animated image or a sequence of frames.",
.items = {std::begin(RENDER_TYPE_STRINGS), std::end(RENDER_TYPE_STRINGS)},
.isSizeToChild = true
});
const inline ImguiItem IMGUI_RENDER_ANIMATION_FORMAT = ImguiItem
({
.label = "Format",
.tooltip = "(PNG images only).\nSet the format of each output frame; i.e., its filename.\nThe format will only take one argument; that being the frame's index.\nFor example, a format like \"{}.png\" will export a frame of index 0 as \"0.png\".",
.isSizeToChild = true
});
const inline ImguiItem IMGUI_RENDER_ANIMATION_FFMPEG_PATH = ImguiItem
({
.label = "FFmpeg Path",
.tooltip = "Sets the path FFmpeg currently resides in.\nFFmpeg is required for rendering animations.\nDownload it from https://ffmpeg.org/, your package manager, or wherever else.",
.isSizeToChild = true
});
const inline ImguiItem IMGUI_RENDER_ANIMATION_FFMPEG_BROWSE = ImguiItem
({
.label = "## FFMpeg Browse",
.atlas = ATLAS_FOLDER
});
const inline ImguiItem IMGUI_RENDER_ANIMATION_CONFIRM = ImguiItem
({
.label = "Render",
.tooltip = "Render the animation with the chosen options.",
.popup = "Rendering Animation...",
.popupType = IMGUI_POPUP_CENTER_SCREEN,
.isSizeToChild = true,
.childRowItemCount = IMGUI_RENDER_ANIMATION_OPTIONS_ROW_ITEM_COUNT
});
const inline ImguiItem IMGUI_RENDER_ANIMATION_CANCEL = ImguiItem
({
.label = "Cancel",
.tooltip = "Cancel rendering animation.",
.isSizeToChild = true,
.childRowItemCount = IMGUI_RENDER_ANIMATION_OPTIONS_ROW_ITEM_COUNT
});
const inline ImguiItem IMGUI_RENDERING_ANIMATION_CHILD = ImguiItem
({
.label = "## Render Animation Child",
.size = {300, 60},
.flags = true
});
const inline ImguiItem IMGUI_RENDERING_ANIMATION_CANCEL = ImguiItem
({
.label = "Cancel",
.isSizeToChild = true
});
const inline ImguiItem IMGUI_TASKBAR_PLAYBACK = ImguiItem
@@ -583,7 +670,7 @@ const inline ImguiItem IMGUI_ANIMATION = ImguiItem
.label = "## Animation Item",
.action = "Select Animation",
.dragDrop = "## Animation Drag Drop",
.texture = TEXTURE_ANIMATION,
.atlas = ATLAS_ANIMATION,
.isUndoable = true,
.isSizeToText = false
});
@@ -731,7 +818,7 @@ const inline ImguiItem IMGUI_EVENTS_CHILD = ImguiItem
const inline ImguiItem IMGUI_EVENT = ImguiItem
({
.label = "## Event Item",
.texture = TEXTURE_EVENT,
.atlas = ATLAS_EVENT,
.isUndoable = true,
.isSizeToText = false
});
@@ -781,7 +868,7 @@ const inline ImguiItem IMGUI_SPRITESHEET = ImguiItem
({
.label = "## Spritesheet",
.dragDrop = "## Spritesheet Drag Drop",
.texture = TEXTURE_SPRITESHEET,
.atlas = ATLAS_SPRITESHEET,
.flags = true
});
@@ -795,7 +882,6 @@ const inline ImguiItem IMGUI_SPRITESHEETS_ADD = ImguiItem
({
.label = "Add",
.tooltip = "Select an image to add as a spritesheet.",
.function = imgui_png_open,
.isSizeToChild = true,
.childRowItemCount = IMGUI_SPRITESHEETS_OPTIONS_FIRST_ROW_ITEM_COUNT
});
@@ -967,10 +1053,16 @@ const inline ImguiItem IMGUI_ANIMATION_PREVIEW_ROOT_TRANSFORM = ImguiItem
.tooltip = "Toggles the root frames's attributes transforming the other items in an animation."
});
const inline ImguiItem IMGUI_ANIMATION_PREVIEW_SHOW_PIVOT = ImguiItem
const inline ImguiItem IMGUI_ANIMATION_PREVIEW_PIVOTS = ImguiItem
({
.label = "Show Pivot",
.tooltip = "Toggles the appearance of an icon for each animation item's pivot."
.label = "Pivots",
.tooltip = "Toggles drawing each layer's pivot."
});
const inline ImguiItem IMGUI_ANIMATION_PREVIEW_TARGETS = ImguiItem
({
.label = "Targets",
.tooltip = "Toggles drawing the targets (i.e., the colored root/null icons)."
});
const inline ImguiItem IMGUI_ANIMATION_PREVIEW_BORDER = ImguiItem
@@ -1078,6 +1170,8 @@ const inline ImguiItem IMGUI_FRAME_PROPERTIES_POSITION = ImguiItem
.format = "%.0f",
.isUndoable = true,
.speed = 0.25f,
.min = 0,
.max = 0
});
const inline ImguiItem IMGUI_FRAME_PROPERTIES_CROP = ImguiItem
@@ -1088,6 +1182,8 @@ const inline ImguiItem IMGUI_FRAME_PROPERTIES_CROP = ImguiItem
.format = "%.0f",
.isUndoable = true,
.speed = 0.25f,
.min = 0,
.max = 0
});
const inline ImguiItem IMGUI_FRAME_PROPERTIES_SIZE = ImguiItem
@@ -1097,7 +1193,9 @@ const inline ImguiItem IMGUI_FRAME_PROPERTIES_SIZE = ImguiItem
.action = "Frame Size",
.format = "%.0f",
.isUndoable = true,
.speed = 0.25f
.speed = 0.25f,
.min = 0,
.max = 0
});
const inline ImguiItem IMGUI_FRAME_PROPERTIES_PIVOT = ImguiItem
@@ -1107,7 +1205,9 @@ const inline ImguiItem IMGUI_FRAME_PROPERTIES_PIVOT = ImguiItem
.action = "Frame Pivot",
.format = "%.0f",
.isUndoable = true,
.speed = 0.25f
.speed = 0.25f,
.min = 0,
.max = 0
});
const inline ImguiItem IMGUI_FRAME_PROPERTIES_SCALE = ImguiItem
@@ -1116,7 +1216,9 @@ const inline ImguiItem IMGUI_FRAME_PROPERTIES_SCALE = ImguiItem
.tooltip = "Change the scale of the selected frame.",
.action = "Frame Scale",
.isUndoable = true,
.speed = 0.25f
.speed = 0.25f,
.min = 0,
.max = 0
});
const inline ImguiItem IMGUI_FRAME_PROPERTIES_ROTATION = ImguiItem
@@ -1125,7 +1227,9 @@ const inline ImguiItem IMGUI_FRAME_PROPERTIES_ROTATION = ImguiItem
.tooltip = "Change the rotation of the selected frame.",
.action = "Frame Rotation",
.isUndoable = true,
.speed = 0.25f
.speed = 0.25f,
.min = 0,
.max = 0
});
const inline ImguiItem IMGUI_FRAME_PROPERTIES_DURATION = ImguiItem
@@ -1191,7 +1295,7 @@ const inline ImguiItem IMGUI_FRAME_PROPERTIES_FLIP_Y = ImguiItem
const inline ImguiItem IMGUI_FRAME_PROPERTIES_EVENT = ImguiItem
({
.label = "Event",
.tooltip = "Change the event the trigger uses.\nNOTE: This sets the event ID, not the event. If the events change IDs, then this will need to be changed.",
.tooltip = "Change the event the trigger uses.\n",
.action = "Trigger Event",
.isUndoable = true
});
@@ -1212,7 +1316,7 @@ const inline ImguiItem IMGUI_TOOL_PAN = ImguiItem
.tooltip = "Use the pan tool.\nWill shift the view as the cursor is dragged.\nYou can also use the middle mouse button to pan at any time.",
.function = imgui_tool_pan_set,
.chord = ImGuiKey_P,
.texture = TEXTURE_PAN,
.atlas = ATLAS_PAN,
});
const inline ImguiItem IMGUI_TOOL_MOVE = ImguiItem
@@ -1221,7 +1325,7 @@ const inline ImguiItem IMGUI_TOOL_MOVE = ImguiItem
.tooltip = "Use the move tool.\nWill move the selected item as the cursor is dragged, or directional keys are pressed.\n(Animation Preview only.)",
.function = imgui_tool_move_set,
.chord = ImGuiKey_M,
.texture = TEXTURE_MOVE,
.atlas = ATLAS_MOVE,
});
const inline ImguiItem IMGUI_TOOL_ROTATE = ImguiItem
@@ -1230,7 +1334,7 @@ const inline ImguiItem IMGUI_TOOL_ROTATE = ImguiItem
.tooltip = "Use the rotate tool.\nWill rotate the selected item as the cursor is dragged, or directional keys are pressed.\n(Animation Preview only.)",
.function = imgui_tool_rotate_set,
.chord = ImGuiKey_R,
.texture = TEXTURE_ROTATE,
.atlas = ATLAS_ROTATE,
});
const inline ImguiItem IMGUI_TOOL_SCALE = ImguiItem
@@ -1239,7 +1343,7 @@ const inline ImguiItem IMGUI_TOOL_SCALE = ImguiItem
.tooltip = "Use the scale tool.\nWill scale the selected item as the cursor is dragged, or directional keys are pressed.\n(Animation Preview only.)",
.function = imgui_tool_scale_set,
.chord = ImGuiKey_S,
.texture = TEXTURE_SCALE,
.atlas = ATLAS_SCALE,
});
const inline ImguiItem IMGUI_TOOL_CROP = ImguiItem
@@ -1248,7 +1352,7 @@ const inline ImguiItem IMGUI_TOOL_CROP = ImguiItem
.tooltip = "Use the crop tool.\nWill produce a crop rectangle based on how the cursor is dragged.\n(Spritesheet Editor only.)",
.function = imgui_tool_crop_set,
.chord = ImGuiKey_C,
.texture = TEXTURE_CROP,
.atlas = ATLAS_CROP,
});
const inline ImguiItem IMGUI_TOOL_DRAW = ImguiItem
@@ -1257,7 +1361,7 @@ const inline ImguiItem IMGUI_TOOL_DRAW = ImguiItem
.tooltip = "Draws pixels onto the selected spritesheet, with the current color.\n(Spritesheet Editor only.)",
.function = imgui_tool_draw_set,
.chord = ImGuiKey_B,
.texture = TEXTURE_DRAW,
.atlas = ATLAS_DRAW,
});
const inline ImguiItem IMGUI_TOOL_ERASE = ImguiItem
@@ -1266,7 +1370,7 @@ const inline ImguiItem IMGUI_TOOL_ERASE = ImguiItem
.tooltip = "Erases pixels from the selected spritesheet.\n(Spritesheet Editor only.)",
.function = imgui_tool_erase_set,
.chord = ImGuiKey_E,
.texture = TEXTURE_ERASE,
.atlas = ATLAS_ERASE,
});
const inline ImguiItem IMGUI_TOOL_COLOR_PICKER = ImguiItem
@@ -1275,7 +1379,7 @@ const inline ImguiItem IMGUI_TOOL_COLOR_PICKER = ImguiItem
.tooltip = "Selects a color from anywhere on the screen, to be used for drawing.",
.function = imgui_tool_color_picker_set,
.chord = ImGuiKey_W,
.texture = TEXTURE_COLOR_PICKER,
.atlas = ATLAS_COLOR_PICKER,
});
const inline ImguiItem IMGUI_TOOL_UNDO = ImguiItem
@@ -1284,7 +1388,7 @@ const inline ImguiItem IMGUI_TOOL_UNDO = ImguiItem
.tooltip = "Undoes the last action.",
.function = imgui_undo,
.chord = ImGuiKey_Z,
.texture = TEXTURE_UNDO
.atlas = ATLAS_UNDO
});
const inline ImguiItem IMGUI_TOOL_REDO = ImguiItem
@@ -1293,7 +1397,7 @@ const inline ImguiItem IMGUI_TOOL_REDO = ImguiItem
.tooltip = "Redoes the last action.",
.function = imgui_redo,
.chord = ImGuiMod_Shift + ImGuiKey_Z,
.texture = TEXTURE_REDO
.atlas = ATLAS_REDO
});
const inline ImguiItem IMGUI_TOOL_COLOR = ImguiItem
@@ -1423,7 +1527,7 @@ const inline ImguiItem IMGUI_TIMELINE_ITEM_ROOT_SELECTABLE = ImguiItem
.label = "Root",
.tooltip = "The root item of an animation.\nChanging its properties will transform the rest of the animation.",
.action = "Root Item Select",
.texture = TEXTURE_ROOT,
.atlas = ATLAS_ROOT,
.isUndoable = true,
.size = IMGUI_TIMELINE_ITEM_SELECTABLE_SIZE
});
@@ -1434,7 +1538,7 @@ const inline ImguiItem IMGUI_TIMELINE_ITEM_LAYER_SELECTABLE = ImguiItem
.tooltip = "A layer item.\nA graphical item within the animation.",
.action = "Layer Item Select",
.dragDrop = "## Layer Drag Drop",
.texture = TEXTURE_LAYER,
.atlas = ATLAS_LAYER,
.isUndoable = true,
.size = IMGUI_TIMELINE_ITEM_SELECTABLE_SIZE
});
@@ -1445,7 +1549,7 @@ const inline ImguiItem IMGUI_TIMELINE_ITEM_NULL_SELECTABLE = ImguiItem
.tooltip = "A null item.\nAn invisible item within the animation that is accessible via a game engine.",
.action = "Null Item Select",
.dragDrop = "## Null Drag Drop",
.texture = TEXTURE_NULL,
.atlas = ATLAS_NULL,
.isUndoable = true,
.size = IMGUI_TIMELINE_ITEM_SELECTABLE_SIZE
});
@@ -1455,7 +1559,7 @@ const inline ImguiItem IMGUI_TIMELINE_ITEM_TRIGGERS_SELECTABLE = ImguiItem
.label = "Triggers",
.tooltip = "The animation's triggers.\nWill fire based on an event.",
.action = "Triggers Item Select",
.texture = TEXTURE_TRIGGERS,
.atlas = ATLAS_TRIGGERS,
.isUndoable = true,
.size = IMGUI_TIMELINE_ITEM_SELECTABLE_SIZE
});
@@ -1473,7 +1577,7 @@ const inline ImguiItem IMGUI_TIMELINE_ITEM_VISIBLE = ImguiItem
({
.label = "## Visible",
.tooltip = "The item is visible.\nPress to set to invisible.",
.texture = TEXTURE_VISIBLE,
.atlas = ATLAS_VISIBLE,
.isUndoable = true
});
@@ -1481,7 +1585,7 @@ const inline ImguiItem IMGUI_TIMELINE_ITEM_INVISIBLE = ImguiItem
({
.label = "## Invisible",
.tooltip = "The item is invisible.\nPress to set to visible.",
.texture = TEXTURE_INVISIBLE,
.atlas = ATLAS_INVISIBLE,
.isUndoable = true
});
@@ -1489,7 +1593,7 @@ const inline ImguiItem IMGUI_TIMELINE_ITEM_SHOW_RECT = ImguiItem
({
.label = "## Show Rect",
.tooltip = "The rect is shown.\nPress to hide rect.",
.texture = TEXTURE_SHOW_RECT,
.atlas = ATLAS_SHOW_RECT,
.isUndoable = true
});
@@ -1497,7 +1601,7 @@ const inline ImguiItem IMGUI_TIMELINE_ITEM_HIDE_RECT = ImguiItem
({
.label = "## Hide Rect",
.tooltip = "The rect is hidden.\nPress to show rect.",
.texture = TEXTURE_HIDE_RECT,
.atlas = ATLAS_HIDE_RECT,
.isUndoable = true
});
@@ -1505,7 +1609,7 @@ const inline ImguiItem IMGUI_TIMELINE_SPRITESHEET_ID = ImguiItem
({
.label = "## Spritesheet ID",
.tooltip = "Change the spritesheet ID this item uses.",
.texture = TEXTURE_SPRITESHEET,
.atlas = ATLAS_SPRITESHEET,
.isUndoable = true,
.size = {32, 0},
});
@@ -1631,6 +1735,7 @@ const inline ImguiItem IMGUI_TIMELINE_PLAY = ImguiItem
({
.label = "|> Play",
.tooltip = "Play the current animation, if paused.",
.focusWindow = IMGUI_TIMELINE.label,
.chord = ImGuiKey_Space
});
@@ -1638,6 +1743,7 @@ const inline ImguiItem IMGUI_TIMELINE_PAUSE = ImguiItem
({
.label = "|| Pause",
.tooltip = "Pause the current animation, if playing.",
.focusWindow = IMGUI_TIMELINE.label,
.chord = ImGuiKey_Space
});
@@ -1760,12 +1866,6 @@ const inline ImguiItem IMGUI_TIMELINE_CREATED_BY = ImguiItem
const inline ImguiItem IMGUI_TIMELINE_CREATED_ON = ImguiItem({"Created on: "});
const inline ImguiItem IMGUI_TIMELINE_VERSION = ImguiItem({"Version: "});
const inline ImguiItem IMGUI_RECORDING = ImguiItem
({
.label = "Recording...",
.texture = TEXTURE_RECORD
});
const inline ImguiItem IMGUI_CONTEXT_MENU = ImguiItem
({
.label = "## Context Menu",
@@ -1794,8 +1894,8 @@ const inline ImguiItem IMGUI_COPY = ImguiItem
const inline ImguiItem IMGUI_PASTE = ImguiItem
({
.label = "Paste",
.tooltip = "Pastes the currently selection contextual element from the clipboard.",
.label = "Paste",
.tooltip = "Pastes the currently selection contextual element from the clipboard.",
.action = "Paste",
.function = imgui_paste,
.chord = ImGuiMod_Ctrl | ImGuiKey_V,
@@ -1808,7 +1908,7 @@ const inline ImguiItem IMGUI_RENAMABLE = ImguiItem
.tooltip = "Rename the selected item.",
.action = "Rename",
.isUndoable = true,
.max = 255,
.max = IMGUI_BUFFER_MAX,
.flags = ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue
});
@@ -1827,16 +1927,24 @@ const inline ImguiItem IMGUI_EXIT_CONFIRMATION = ImguiItem
.popup = "Exit Confirmation"
});
const inline ImguiItem IMGUI_POPUP_YES_BUTTON = ImguiItem
const inline ImguiItem IMGUI_POPUP_OK_BUTTON = ImguiItem
({
.label = "Yes",
.size = {120, 0}
.label = "OK",
.isSizeToChild = true
});
const inline ImguiItem IMGUI_POPUP_NO_BUTTON = ImguiItem
const inline ImguiItem IMGUI_POPUP_CONFIRM_BUTTON = ImguiItem
({
.label = "No",
.size = {120, 0}
.label = "OK",
.isSizeToChild = true,
.childRowItemCount = IMGUI_POPUP_OPTION_CHILD_ROW_ITEM_COUNT
});
const inline ImguiItem IMGUI_POPUP_CANCEL_BUTTON = ImguiItem
({
.label = "Cancel",
.isSizeToChild = true,
.childRowItemCount = IMGUI_POPUP_OPTION_CHILD_ROW_ITEM_COUNT
});
void imgui_init

View File

@@ -1,7 +1,15 @@
// Handles the rendering of the animation preview
// Handles the render of the animation preview
#include "preview.h"
static void _preview_render_textures_free(Preview* self)
{
for (auto& texture : self->renderFrames)
texture_free(&texture);
self->renderFrames.clear();
}
void preview_init(Preview* self, Anm2* anm2, Anm2Reference* reference, Resources* resources, Settings* settings)
{
self->anm2 = anm2;
@@ -20,19 +28,45 @@ void preview_tick(Preview* self)
{
if (self->isPlaying)
{
if (self->isRender)
{
vec2& size = self->canvas.size;
u32 framebufferPixelCount = size.x * size.y * TEXTURE_CHANNELS;
std::vector<u8> framebufferPixels(framebufferPixelCount);
Texture frameTexture;
glBindFramebuffer(GL_READ_FRAMEBUFFER, self->canvas.fbo);
glReadBuffer(GL_COLOR_ATTACHMENT0);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0, 0, size.x, size.y, GL_RGBA, GL_UNSIGNED_BYTE, framebufferPixels.data());
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
texture_from_rgba_init(&frameTexture, size, TEXTURE_CHANNELS, framebufferPixels.data());
self->renderFrames.push_back(frameTexture);
}
self->time += (f32)self->anm2->fps / TICK_RATE;
if (self->time >= (f32)animation->frameNum - 1)
{
if (self->settings->playbackIsLoop && !self->isRecording)
if (self->isRender)
{
self->isRender = false;
self->isRenderFinished = true;
self->time = 0.0f;
else
self->isPlaying = false;
}
else
{
if (self->settings->playbackIsLoop)
self->time = 0.0f;
else
self->isPlaying = false;
}
}
}
if (!self->isPlaying)
self->time = std::clamp(self->time, 0.0f, (f32)animation->frameNum - 1);
self->time = std::clamp(self->time, 0.0f, (f32)animation->frameNum - 1);
}
}
@@ -72,11 +106,11 @@ void preview_draw(Preview* self)
rootModel = quad_parent_model_get(root.position, vec2(0.0f), root.rotation, PERCENT_TO_UNIT(root.scale));
// Root
if (animation->rootAnimation.isVisible && root.isVisible)
if (self->settings->previewIsTargets && animation->rootAnimation.isVisible && root.isVisible)
{
mat4 model = quad_model_get(PREVIEW_TARGET_SIZE, root.position, PREVIEW_TARGET_SIZE * 0.5f, root.rotation, PERCENT_TO_UNIT(root.scale));
mat4 rootTransform = transform * model;
f32 vertices[] = ATLAS_UV_VERTICES(TEXTURE_TARGET);
f32 vertices[] = ATLAS_UV_VERTICES(ATLAS_TARGET);
canvas_texture_draw(&self->canvas, shaderTexture, self->resources->atlas.id, rootTransform, vertices, PREVIEW_ROOT_COLOR);
}
@@ -94,26 +128,26 @@ void preview_draw(Preview* self)
if (!frame.isVisible)
continue;
Texture texture = self->resources->textures[self->anm2->layers[id].spritesheetID];
Texture* texture = map_find(self->resources->textures, self->anm2->layers[id].spritesheetID);
if (texture.isInvalid)
if (!texture || texture->isInvalid)
continue;
vec2 uvMin = frame.crop / vec2(texture.size);
vec2 uvMax = (frame.crop + frame.size) / vec2(texture.size);
vec2 uvMin = frame.crop / vec2(texture->size);
vec2 uvMax = (frame.crop + frame.size) / vec2(texture->size);
f32 vertices[] = UV_VERTICES(uvMin, uvMax);
mat4 model = quad_model_get(frame.size, frame.position, frame.pivot, frame.rotation, PERCENT_TO_UNIT(frame.scale));
mat4 layerTransform = transform * (rootModel * model);
canvas_texture_draw(&self->canvas, shaderTexture, texture.id, layerTransform, vertices, frame.tintRGBA, frame.offsetRGB);
canvas_texture_draw(&self->canvas, shaderTexture, texture->id, layerTransform, vertices, frame.tintRGBA, frame.offsetRGB);
if (self->settings->previewIsBorder)
canvas_rect_draw(&self->canvas, shaderLine, layerTransform, PREVIEW_BORDER_COLOR);
if (self->settings->previewIsShowPivot)
if (self->settings->previewIsPivots)
{
f32 vertices[] = ATLAS_UV_VERTICES(TEXTURE_PIVOT);
f32 vertices[] = ATLAS_UV_VERTICES(ATLAS_PIVOT);
mat4 pivotModel = quad_model_get(CANVAS_PIVOT_SIZE, frame.position, CANVAS_PIVOT_SIZE * 0.5f, frame.rotation, PERCENT_TO_UNIT(frame.scale));
mat4 pivotTransform = transform * (rootModel * pivotModel);
canvas_texture_draw(&self->canvas, shaderTexture, self->resources->atlas.id, pivotTransform, vertices, PREVIEW_PIVOT_COLOR);
@@ -121,38 +155,41 @@ void preview_draw(Preview* self)
}
// Nulls
for (auto& [id, nullAnimation] : animation->nullAnimations)
if (self->settings->previewIsTargets)
{
if (!nullAnimation.isVisible || nullAnimation.frames.size() <= 0)
continue;
Anm2Frame frame;
anm2_frame_from_time(self->anm2, &frame, Anm2Reference{animationID, ANM2_NULL, id}, self->time);
if (!frame.isVisible)
continue;
Anm2Null null = self->anm2->nulls[id];
vec4 color = (self->reference->itemType == ANM2_NULL && self->reference->itemID == id) ?
PREVIEW_NULL_SELECTED_COLOR :
PREVIEW_NULL_COLOR;
vec2 size = null.isShowRect ? CANVAS_PIVOT_SIZE : PREVIEW_TARGET_SIZE;
TextureType texture = null.isShowRect ? TEXTURE_SQUARE : TEXTURE_TARGET;
mat4 model = quad_model_get(size, frame.position, size * 0.5f, frame.rotation, PERCENT_TO_UNIT(frame.scale));
mat4 nullTransform = transform * (rootModel * model);
f32 vertices[] = ATLAS_UV_VERTICES(texture);
canvas_texture_draw(&self->canvas, shaderTexture, self->resources->atlas.id, nullTransform, vertices, color);
if (null.isShowRect)
for (auto& [id, nullAnimation] : animation->nullAnimations)
{
mat4 rectModel = quad_model_get(PREVIEW_NULL_RECT_SIZE, frame.position, PREVIEW_NULL_RECT_SIZE * 0.5f, frame.rotation, PERCENT_TO_UNIT(frame.scale));
mat4 rectTransform = transform * (rootModel * rectModel);
canvas_rect_draw(&self->canvas, shaderLine, rectTransform, color);
if (!nullAnimation.isVisible || nullAnimation.frames.size() <= 0)
continue;
Anm2Frame frame;
anm2_frame_from_time(self->anm2, &frame, Anm2Reference{animationID, ANM2_NULL, id}, self->time);
if (!frame.isVisible)
continue;
Anm2Null null = self->anm2->nulls[id];
vec4 color = (self->reference->itemType == ANM2_NULL && self->reference->itemID == id) ?
PREVIEW_NULL_SELECTED_COLOR :
PREVIEW_NULL_COLOR;
vec2 size = null.isShowRect ? CANVAS_PIVOT_SIZE : PREVIEW_TARGET_SIZE;
AtlasType atlas = null.isShowRect ? ATLAS_SQUARE : ATLAS_TARGET;
mat4 model = quad_model_get(size, frame.position, size * 0.5f, frame.rotation, PERCENT_TO_UNIT(frame.scale));
mat4 nullTransform = transform * (rootModel * model);
f32 vertices[] = ATLAS_UV_VERTICES(atlas);
canvas_texture_draw(&self->canvas, shaderTexture, self->resources->atlas.id, nullTransform, vertices, color);
if (null.isShowRect)
{
mat4 rectModel = quad_model_get(PREVIEW_NULL_RECT_SIZE, frame.position, PREVIEW_NULL_RECT_SIZE * 0.5f, frame.rotation, PERCENT_TO_UNIT(frame.scale));
mat4 rectTransform = transform * (rootModel * rectModel);
canvas_rect_draw(&self->canvas, shaderLine, rectTransform, color);
}
}
}
}
@@ -173,7 +210,7 @@ void preview_draw(Preview* self)
for (auto [i, id] : self->anm2->layerMap)
{
Anm2Frame frame;
Anm2Item& layerAnimation = animation->layerAnimations[id];
Anm2Item& layerAnimation = animationOverlay->layerAnimations[id];
if (!layerAnimation.isVisible || layerAnimation.frames.size() <= 0)
continue;
@@ -183,13 +220,13 @@ void preview_draw(Preview* self)
if (!frame.isVisible)
continue;
Texture texture = self->resources->textures[self->anm2->layers[id].spritesheetID];
if (texture.isInvalid)
Texture* texture = map_find(self->resources->textures, self->anm2->layers[id].spritesheetID);
if (!texture || texture->isInvalid)
continue;
vec2 uvMin = frame.crop / vec2(texture.size);
vec2 uvMax = (frame.crop + frame.size) / vec2(texture.size);
vec2 uvMin = frame.crop / vec2(texture->size);
vec2 uvMax = (frame.crop + frame.size) / vec2(texture->size);
f32 vertices[] = UV_VERTICES(uvMin, uvMax);
mat4 model = quad_model_get(frame.size, frame.position, frame.pivot, frame.rotation, PERCENT_TO_UNIT(frame.scale));
@@ -198,13 +235,29 @@ void preview_draw(Preview* self)
vec4 tint = frame.tintRGBA;
tint.a *= U8_TO_FLOAT(self->settings->previewOverlayTransparency);
canvas_texture_draw(&self->canvas, shaderTexture, texture.id, layerTransform, vertices, tint, frame.offsetRGB);
canvas_texture_draw(&self->canvas, shaderTexture, texture->id, layerTransform, vertices, tint, frame.offsetRGB);
}
}
canvas_unbind();
}
void preview_render_start(Preview* self)
{
self->isRender = true;
self->isPlaying = true;
self->time = 0.0f;
_preview_render_textures_free(self);
}
void preview_render_end(Preview* self)
{
self->isRender = false;
self->isPlaying = false;
self->isRenderFinished = false;
_preview_render_textures_free(self);
}
void preview_free(Preview* self)
{
canvas_free(&self->canvas);

View File

@@ -35,7 +35,10 @@ struct Preview
s32 animationOverlayID = ID_NONE;
Canvas canvas;
bool isPlaying = false;
bool isRecording = false;
bool isRender = false;
bool isRenderFinished = false;
bool isRenderCancelled = false;
std::vector<Texture> renderFrames;
f32 time{};
};
@@ -43,4 +46,5 @@ void preview_init(Preview* self, Anm2* anm2, Anm2Reference* reference, Resources
void preview_draw(Preview* self);
void preview_tick(Preview* self);
void preview_free(Preview* self);
void preview_record_set(Preview* self);
void preview_render_start(Preview* self);
void preview_render_end(Preview* self);

25
src/render.h Normal file
View File

@@ -0,0 +1,25 @@
#pragma once
#include "COMMON.h"
enum RenderType
{
RENDER_PNG,
RENDER_GIF,
RENDER_WEBM,
RENDER_COUNT
};
const inline std::string RENDER_TYPE_STRINGS[] =
{
"PNG Images",
"GIF image",
"WebM video",
};
const inline std::string RENDER_EXTENSIONS[RENDER_COUNT] =
{
".png",
".gif",
".webm"
};

View File

@@ -1,21 +1,20 @@
#include "resources.h"
void resources_texture_init(Resources* resources, const std::string& path, s32 id)
void resources_texture_init(Resources* self, const std::string& path, s32 id)
{
Texture texture;
if (resources->textures.find(id) != resources->textures.end() && resources->textures[id].id != resources->textures[TEXTURE_NONE].id)
texture_free(&resources->textures[id]);
if (map_find(self->textures, id))
texture_free(&self->textures[id]);
if (!texture_from_path_init(&texture, path))
texture.isInvalid = true;
texture_from_path_init(&texture, path);
resources->textures[id] = texture;
self->textures[id] = texture;
}
void resources_init(Resources* self)
{
texture_from_data_init(&self->atlas, (u8*)TEXTURE_ATLAS, TEXTURE_ATLAS_LENGTH);
texture_from_encoded_data_init(&self->atlas, TEXTURE_ATLAS_SIZE, TEXTURE_CHANNELS, (u8*)TEXTURE_ATLAS, TEXTURE_ATLAS_LENGTH);
for (s32 i = 0; i < SHADER_COUNT; i++)
shader_init(&self->shaders[i], SHADER_DATA[i].vertex, SHADER_DATA[i].fragment);
@@ -25,14 +24,15 @@ void resources_free(Resources* self)
{
resources_textures_free(self);
for (s32 i = 0; i < SHADER_COUNT; i++)
shader_free(&self->shaders[i]);
for (auto& shader : self->shaders)
shader_free(&shader);
texture_free(&self->atlas);
}
void resources_textures_free(Resources* self)
{
for (auto & [id, texture] : self->textures)
for (auto& [id, texture] : self->textures)
texture_free(&self->textures[id]);
log_info(RESOURCES_TEXTURES_FREE_INFO);

View File

@@ -14,6 +14,6 @@ struct Resources
};
void resources_init(Resources* self);
void resources_texture_init(Resources* resources, const std::string& path, s32 id);
void resources_texture_init(Resources* self, const std::string& path, s32 id);
void resources_free(Resources* self);
void resources_textures_free(Resources* self);

View File

@@ -6,11 +6,17 @@ static void _settings_setting_load(Settings* self, const std::string& line)
{
const auto& entry = SETTINGS_ENTRIES[i];
const std::string& key = entry.key;
void* target = (u8*)self + entry.offset;
auto match_key = [&](const std::string& full) -> const char*
{
return (line.starts_with(full) && line[full.size()] == '=') ? line.c_str() + full.size() + 1 : nullptr;
if (!line.starts_with(full))
return nullptr;
size_t p = full.size();
while (p < line.size() && std::isspace((u8)line[p])) ++p;
if (p < line.size() && line[p] == '=') return line.c_str() + p + 1;
return nullptr;
};
auto* value = match_key(key);
@@ -79,9 +85,12 @@ static void _settings_setting_write(Settings* self, std::ostream& out, SettingsE
out << entry.key << "=" << value << "\n";
break;
case TYPE_STRING:
value = *(std::string*)(selfPointer + entry.offset);
out << entry.key << "=" << value << "\n";
{
const std::string data = *reinterpret_cast<const std::string*>(selfPointer + entry.offset);
if (!data.empty())
out << entry.key << "=" << data.c_str() << "\n";
break;
}
case TYPE_IVEC2:
{
ivec2* data = (ivec2*)(selfPointer + entry.offset);

View File

@@ -1,5 +1,6 @@
#pragma once
#include "render.h"
#include "tool.h"
#define SETTINGS_BUFFER 0xFFFF
@@ -24,7 +25,8 @@ struct Settings
bool previewIsAxis = true;
bool previewIsGrid = true;
bool previewIsRootTransform = false;
bool previewIsShowPivot = false;
bool previewIsPivots = false;
bool previewIsTargets = true;
bool previewIsBorder = false;
f32 previewOverlayTransparency = 255.0f;
f32 previewZoom = 200.0;
@@ -45,6 +47,10 @@ struct Settings
vec4 editorBackgroundColor = {0.113, 0.184, 0.286, 1.0};
ToolType tool = TOOL_PAN;
vec4 toolColor = {1.0, 1.0, 1.0, 1.0};
RenderType renderType = RENDER_PNG;
std::string renderPath = ".";
std::string renderFormat = "{}.png";
std::string ffmpegPath = "/usr/bin/ffmpeg";
};
const SettingsEntry SETTINGS_ENTRIES[] =
@@ -54,7 +60,8 @@ const SettingsEntry SETTINGS_ENTRIES[] =
{"previewIsAxis", TYPE_BOOL, offsetof(Settings, previewIsAxis)},
{"previewIsGrid", TYPE_BOOL, offsetof(Settings, previewIsGrid)},
{"previewIsRootTransform", TYPE_BOOL, offsetof(Settings, previewIsRootTransform)},
{"previewIsShowPivot", TYPE_BOOL, offsetof(Settings, previewIsShowPivot)},
{"previewIsPivots", TYPE_BOOL, offsetof(Settings, previewIsPivots)},
{"previewIsTargets", TYPE_BOOL, offsetof(Settings, previewIsTargets)},
{"previewIsBorder", TYPE_BOOL, offsetof(Settings, previewIsBorder)},
{"previewOverlayTransparency", TYPE_FLOAT, offsetof(Settings, previewOverlayTransparency)},
{"previewZoom", TYPE_FLOAT, offsetof(Settings, previewZoom)},
@@ -75,6 +82,10 @@ const SettingsEntry SETTINGS_ENTRIES[] =
{"editorBackgroundColor", TYPE_VEC4, offsetof(Settings, editorBackgroundColor)},
{"tool", TYPE_INT, offsetof(Settings, tool)},
{"toolColor", TYPE_VEC4, offsetof(Settings, toolColor)},
{"renderType", TYPE_INT, offsetof(Settings, renderType)},
{"renderPath", TYPE_STRING, offsetof(Settings, renderPath)},
{"renderFormat", TYPE_STRING, offsetof(Settings, renderFormat)},
{"ffmpegPath", TYPE_STRING, offsetof(Settings, ffmpegPath)}
};
constexpr s32 SETTINGS_COUNT = (s32)std::size(SETTINGS_ENTRIES);

View File

@@ -34,6 +34,13 @@ void snapshots_init(Snapshots* self, Anm2* anm2, Anm2Reference* reference, Previ
self->preview = preview;
}
void snapshots_reset(Snapshots* self)
{
self->undoStack = SnapshotStack{};
self->redoStack = SnapshotStack{};
self->action.clear();
}
void snapshots_undo_stack_push(Snapshots* self, const Snapshot* snapshot)
{
_snapshot_stack_push(&self->undoStack, snapshot);

View File

@@ -33,4 +33,5 @@ struct Snapshots
void snapshots_undo_stack_push(Snapshots* self, const Snapshot* snapshot);
void snapshots_init(Snapshots* self, Anm2* anm2, Anm2Reference* reference, Preview* preview);
void snapshots_undo(Snapshots* self);
void snapshots_redo(Snapshots* self);
void snapshots_redo(Snapshots* self);
void snapshots_reset(Snapshots* self);

View File

@@ -10,7 +10,6 @@ static void _update(State* self)
SDL_GetWindowSize(self->window, &self->settings.windowSize.x, &self->settings.windowSize.y);
imgui_update(&self->imgui);
dialog_update(&self->dialog);
if (self->imgui.isQuit)
self->isRunning = false;
@@ -99,8 +98,8 @@ void init(State* self)
glDisable(GL_LINE_SMOOTH);
resources_init(&self->resources);
dialog_init(&self->dialog, self->window);
clipboard_init(&self->clipboard, &self->anm2);
dialog_init(&self->dialog, &self->anm2, &self->reference, &self->resources, self->window);
snapshots_init(&self->snapshots, &self->anm2, &self->reference, &self->preview);
preview_init(&self->preview, &self->anm2, &self->reference, &self->resources, &self->settings);
editor_init(&self->editor, &self->anm2, &self->reference, &self->resources, &self->settings);
@@ -130,7 +129,6 @@ void init(State* self)
anm2_new(&self->anm2);
}
void loop(State* self)
{
self->tick = SDL_GetTicks();

View File

@@ -8,19 +8,7 @@
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include <stb_image_write.h>
static std::vector<u8> _texture_download(Texture* self)
{
std::vector<u8> pixels(self->size.x * self->size.y * TEXTURE_CHANNELS);
glBindTexture(GL_TEXTURE_2D, self->id);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
return pixels;
}
void texture_gl_set(Texture* self, void* data)
static void _texture_gl_set(Texture* self, const u8* data)
{
glGenTextures(1, &self->id);
glBindTexture(GL_TEXTURE_2D, self->id);
@@ -32,35 +20,67 @@ void texture_gl_set(Texture* self, void* data)
glBindTexture(GL_TEXTURE_2D, 0);
}
std::vector<u8> texture_download(const Texture* self)
{
std::vector<u8> pixels(self->size.x * self->size.y * TEXTURE_CHANNELS);
glBindTexture(GL_TEXTURE_2D, self->id);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
return pixels;
}
bool texture_from_path_init(Texture* self, const std::string& path)
{
void* data = stbi_load(path.c_str(), &self->size.x, &self->size.y, &self->channels, TEXTURE_CHANNELS);
*self = Texture{};
u8* data = stbi_load(path.c_str(), &self->size.x, &self->size.y, &self->channels, TEXTURE_CHANNELS);
if (!data)
{
log_error(std::format(TEXTURE_INIT_ERROR, path));
self->isInvalid = true;
return false;
}
log_info(std::format(TEXTURE_INIT_INFO, path));
texture_gl_set(self, data);
_texture_gl_set(self, data);
return true;
}
bool texture_from_data_init(Texture* self, const u8* data, u32 length)
bool texture_from_encoded_data_init(Texture* self, ivec2 size, s32 channels, const u8* data, u32 length)
{
void* textureData = stbi_load_from_memory(data, length, &self->size.x, &self->size.y, &self->channels, TEXTURE_CHANNELS);
*self = Texture{};
self->size = size;
self->channels = channels;
if (!textureData) return false;
u8* textureData = stbi_load_from_memory(data, length, &self->size.x, &self->size.y, &self->channels, TEXTURE_CHANNELS);
texture_gl_set(self, textureData);
if (!textureData)
{
self->isInvalid = true;
return false;
}
_texture_gl_set(self, textureData);
return true;
}
bool texture_from_data_write(const std::string& path, const u8* data, ivec2 size)
bool texture_from_rgba_init(Texture* self, ivec2 size, s32 channels, const u8* data)
{
*self = Texture{};
self->size = size;
self->channels = channels;
_texture_gl_set(self, data);
return true;
}
bool texture_from_rgba_write(const std::string& path, const u8* data, ivec2 size)
{
log_info(std::format(TEXTURE_SAVE_INFO, path));
return (bool)stbi_write_png(path.c_str(), size.x, size.y, TEXTURE_CHANNELS, data, size.x * TEXTURE_CHANNELS);
@@ -68,7 +88,7 @@ bool texture_from_data_write(const std::string& path, const u8* data, ivec2 size
bool texture_from_gl_write(Texture* self, const std::string& path)
{
return texture_from_data_write(path, _texture_download(self).data(), self->size);
return texture_from_rgba_write(path, texture_download(self).data(), self->size);
}
void texture_free(Texture* self)

View File

@@ -15,11 +15,11 @@ struct Texture
bool isInvalid = false;
};
void texture_gl_set(Texture* self, void* data);
bool texture_from_encoded_data_init(Texture* self, ivec2 size, s32 channels, const u8* data, u32 length);
bool texture_from_gl_write(Texture* self, const std::string& path);
bool texture_from_path_init(Texture* self, const std::string& path);
bool texture_from_data_init(Texture* self, const u8* data, u32 length);
void texture_free(Texture* self);
std::vector<u8> texture_download(Texture* self);
bool texture_from_data_write(const std::string& path, const u8* data, ivec2 size);
bool texture_from_rgba_init(Texture* self, ivec2 size, s32 channels, const u8* data);
bool texture_from_rgba_write(const std::string& path, const u8* data, ivec2 size);
bool texture_pixel_set(Texture* self, ivec2 position, vec4 color);
bool texture_from_gl_write(Texture* self, const std::string& path);
void texture_free(Texture* self);
std::vector<u8> texture_download(const Texture* self);