Compare commits
328 Commits
cd6930c56b
...
e2002e
Author | SHA1 | Date | |
---|---|---|---|
316441b954 | |||
9d7613be8f | |||
c989f3254f | |||
f8d76929ae | |||
a51c28b607 | |||
9142371f88 | |||
35f92341fa | |||
a8d1eebdaf | |||
87922c9389 | |||
38287f56b0 | |||
42ad5b01c1 | |||
2b46d6ebca | |||
953ad8391c | |||
1458ecd84f | |||
288b085d0c | |||
aa0b2b1b7e | |||
acede01167 | |||
92a2b0305e | |||
4886953722 | |||
601860b242 | |||
f00cef2e21 | |||
e733dca053 | |||
387be05826 | |||
c5b21a9bb3 | |||
5b2c7bfc84 | |||
47d913ab64 | |||
878ce14254 | |||
9075931c51 | |||
39ab42f2da | |||
30cab4d79b | |||
8ee2aaa70a | |||
2f9694632d | |||
7b8d73cd84 | |||
3d8bd77c59 | |||
290289f413 | |||
2732210fc9 | |||
68900fb992 | |||
ef724ae323 | |||
6d4c1a680b | |||
8aeaa0368e | |||
7969286fdc | |||
cde2bead97 | |||
c42e4c09a8 | |||
b8c8ccad9d | |||
335f3541f1 | |||
808dcef817 | |||
6ac06cc504 | |||
86de9617f3 | |||
29761ec9e6 | |||
ea7cf849b8 | |||
5d559734b9 | |||
939346c896 | |||
f2dcfc0ffa | |||
e78bd17d93 | |||
f9a02f03cb | |||
21a4ee0af7 | |||
9bf83bc49f | |||
d88e1f0f42 | |||
96f4e29778 | |||
1d705d2ca2 | |||
0979cd976f | |||
db6d786ee4 | |||
06319131fd | |||
c08e1d3835 | |||
27bd360317 | |||
82a53a868a | |||
94eaba7319 | |||
8d1c2c51bd | |||
07d98639f2 | |||
1944fc97b8 | |||
d69e3438ff | |||
62e52a7316 | |||
c4b48c2d87 | |||
96f69a7cfe | |||
90950970f0 | |||
106e36e30d | |||
e71b0849b3 | |||
e079c94832 | |||
5572494f3d | |||
8f03927391 | |||
6586d90177 | |||
952cee36a3 | |||
35bfdf3715 | |||
135aaa0669 | |||
c6b776a329 | |||
67c7443985 | |||
42273470c3 | |||
4dfc6be702 | |||
92e1abcfdc | |||
764eefeb06 | |||
979dfc605d | |||
55fb300901 | |||
c59e6a66d4 | |||
659802b888 | |||
33f6fcaaaf | |||
d37b41b181 | |||
70742b823f | |||
da8f9d23e4 | |||
ff886e6d46 | |||
70a603cf7a | |||
bfc4c2644f | |||
f101124d24 | |||
c6f672bd61 | |||
7f38b15fe7 | |||
2bb296028f | |||
5628493493 | |||
f8a08a41b1 | |||
2cd91f598c | |||
a20d6b581c | |||
e34ed0794f | |||
bdcf4c980b | |||
25d7ba3e72 | |||
30e5acf9bf | |||
c3435b9533 | |||
8765e894f5 | |||
2c5c8d0e4f | |||
4805dd06a7 | |||
2bc2ab43a1 | |||
bf7b4416ec | |||
a2d03cfe6e | |||
95f0ecfc54 | |||
07f59224fc | |||
02259985be | |||
6b8585c81a | |||
5d78eabf94 | |||
41c1459c4e | |||
304a497565 | |||
9fa399371a | |||
4625fdb6b2 | |||
79553927aa | |||
86661c1012 | |||
03967c7a2b | |||
61fd48a12f | |||
519039b8b6 | |||
5244b1b3e8 | |||
7ae3bbe496 | |||
001be2f8da | |||
6a25b3c5d7 | |||
8d4ac7251a | |||
ae63b252c6 | |||
ee73823206 | |||
af2850e20c | |||
bc4a31d415 | |||
5303ad3ac6 | |||
5153cff790 | |||
abe17870ce | |||
c798f122d0 | |||
d1edb1464e | |||
ee8d3314b5 | |||
c6139282ed | |||
559a3b8b39 | |||
8d072ae481 | |||
293a612e9c | |||
8020599513 | |||
4fbc1aba7f | |||
1380585297 | |||
beee036a3d | |||
76b2ba8f80 | |||
e7143cc740 | |||
bd0886b1d7 | |||
8eb8c0bd98 | |||
dd06e490a7 | |||
5e4ac6dd0b | |||
be0a9149ad | |||
7ab3398941 | |||
c10e988d2d | |||
caafeea2f1 | |||
2edee3fe68 | |||
af147c9c63 | |||
8e4c20647b | |||
594cbeffbe | |||
e1d48e4289 | |||
7960ca94a6 | |||
72f14f59bf | |||
d994d040ef | |||
1e18795d29 | |||
9557b82970 | |||
88949c63c5 | |||
7cab325397 | |||
8792ef5cee | |||
761b1832ad | |||
074a51866f | |||
c382460355 | |||
4a3544b5d8 | |||
7cebe8340f | |||
ecaea8ad9d | |||
cae7963b21 | |||
7a2976ced1 | |||
aae64aa8f8 | |||
ef25d15aed | |||
01bcf029f9 | |||
2b9baef712 | |||
489057018e | |||
501a064d25 | |||
9478e4e957 | |||
32c6535f8a | |||
21c2abe67c | |||
2b1b56bc0a | |||
9e47c1db6d | |||
6be977da7e | |||
693fa36ee1 | |||
6ec480930a | |||
a627a52d46 | |||
be63323c09 | |||
38595db46b | |||
48d28f6873 | |||
eb033149a0 | |||
db1c3bdf4c | |||
2b16b565a8 | |||
8c758bf51f | |||
1764081740 | |||
c90bde8719 | |||
bfb11275df | |||
3185f61f39 | |||
fb00ca88ff | |||
78109cfee2 | |||
fa65c02e8a | |||
cb93ede7d7 | |||
2a3f8db0bc | |||
3ab9123000 | |||
d6b4b6eeea | |||
2f1e6783a4 | |||
603a976adf | |||
1e0d32a88d | |||
82a7075308 | |||
de8f7d08ed | |||
caf95e2611 | |||
b639f06aba | |||
de41800e1c | |||
d2746fb087 | |||
62d3e65796 | |||
74473087b5 | |||
392da64d1f | |||
30748390ca | |||
f9d463ca1d | |||
b8771e9d81 | |||
1f52eed66c | |||
e562b626cb | |||
ccb554ba16 | |||
972775b432 | |||
ee984c332e | |||
038e5123c9 | |||
b5575e5a48 | |||
76d79e6e18 | |||
ca8fd0b357 | |||
87fa82e3d3 | |||
9fa58d9d7c | |||
864568d66b | |||
f3e96546ae | |||
fcc114aed3 | |||
df33848bee | |||
c17516a4e2 | |||
9b9acd5e15 | |||
3b0eb0e075 | |||
f5b3da3a15 | |||
b71275d0d5 | |||
6aeb9b0f22 | |||
609477737e | |||
a747f89438 | |||
0bd0c57a00 | |||
f3ab801928 | |||
9b821d4b8e | |||
f2a0dbe36c | |||
12e66d8cf1 | |||
4b6424b702 | |||
e66e082cc7 | |||
42eff22cbb | |||
448898a634 | |||
15ec41b1f0 | |||
c5a7746c84 | |||
51aa8ea1d4 | |||
ccdfc4246f | |||
aead4c4903 | |||
d2f4c0e221 | |||
887eeebe27 | |||
83077e3f15 | |||
f5c20c5a13 | |||
4bd4995b6e | |||
381744e678 | |||
34c15c29cd | |||
0346e27657 | |||
9087b9c98c | |||
f2cbcc88a7 | |||
b8d9ea2aff | |||
37a09d0a21 | |||
ed932e3fa4 | |||
f00edd882f | |||
f403955fcd | |||
a562af9b60 | |||
bdd9b0197f | |||
f200933375 | |||
829ef5f269 | |||
0d73133f36 | |||
181b860360 | |||
20db9cc24d | |||
c67b38ea1e | |||
adb95eab1e | |||
93addd1200 | |||
7f9a7c9b4a | |||
7433409cda | |||
2a6e05aff1 | |||
348d7bf343 | |||
4c6df16aa7 | |||
8a7f5ee519 | |||
1958342a74 | |||
16e8e00783 | |||
bcdcbfb106 | |||
28afefbbf7 | |||
3d2130e26a | |||
9761719dd5 | |||
b2a781c7c2 | |||
7121737297 | |||
b0991a8928 | |||
b84fc93899 | |||
06c0c430a8 | |||
0f0c67dc07 | |||
3bb2d65faa | |||
20e33afeac | |||
9c5fc5d1d3 | |||
6bed0cbc6d | |||
0eb4effeb3 | |||
238acaad0a | |||
f4f5665835 | |||
eb15dddd38 | |||
8c238c320d | |||
ef27ce45ae | |||
61a4bf0ff8 | |||
b985c5949b |
@ -1,268 +1,268 @@
|
||||
/*
|
||||
* Platform-specific and custom entropy polling functions
|
||||
*
|
||||
* Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_ENTROPY_C)
|
||||
|
||||
#include "mbedtls/entropy.h"
|
||||
#include "mbedtls/entropy_poll.h"
|
||||
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
#include <string.h>
|
||||
#include "mbedtls/timing.h"
|
||||
#endif
|
||||
#if defined(MBEDTLS_HAVEGE_C)
|
||||
#include "mbedtls/havege.h"
|
||||
#endif
|
||||
#if defined(MBEDTLS_ENTROPY_NV_SEED)
|
||||
#include "mbedtls/platform.h"
|
||||
#endif
|
||||
|
||||
#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
|
||||
|
||||
#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
|
||||
!defined(__APPLE__) && !defined(_WIN32)
|
||||
#error "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in config.h"
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
|
||||
|
||||
#if !defined(_WIN32_WINNT)
|
||||
#define _WIN32_WINNT 0x0400
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
|
||||
int mbedtls_platform_entropy_poll( void *data, unsigned char *output, size_t len,
|
||||
size_t *olen )
|
||||
{
|
||||
HCRYPTPROV provider;
|
||||
((void) data);
|
||||
*olen = 0;
|
||||
|
||||
if( CryptAcquireContext( &provider, NULL, NULL,
|
||||
PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE )
|
||||
{
|
||||
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
|
||||
}
|
||||
|
||||
if( CryptGenRandom( provider, (DWORD) len, output ) == FALSE )
|
||||
{
|
||||
CryptReleaseContext( provider, 0 );
|
||||
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
|
||||
}
|
||||
|
||||
CryptReleaseContext( provider, 0 );
|
||||
*olen = len;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
#else /* _WIN32 && !EFIX64 && !EFI32 */
|
||||
|
||||
/*
|
||||
* Test for Linux getrandom() support.
|
||||
* Since there is no wrapper in the libc yet, use the generic syscall wrapper
|
||||
* available in GNU libc and compatible libc's (eg uClibc).
|
||||
*/
|
||||
#if defined(__linux__) && defined(__GLIBC__)
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
#if defined(SYS_getrandom)
|
||||
#define HAVE_GETRANDOM
|
||||
|
||||
static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags )
|
||||
{
|
||||
/* MemSan cannot understand that the syscall writes to the buffer */
|
||||
#if defined(__has_feature)
|
||||
#if __has_feature(memory_sanitizer)
|
||||
memset( buf, 0, buflen );
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return( syscall( SYS_getrandom, buf, buflen, flags ) );
|
||||
}
|
||||
|
||||
#include <sys/utsname.h>
|
||||
/* Check if version is at least 3.17.0 */
|
||||
static int check_version_3_17_plus( void )
|
||||
{
|
||||
int minor;
|
||||
struct utsname un;
|
||||
const char *ver;
|
||||
|
||||
/* Get version information */
|
||||
uname(&un);
|
||||
ver = un.release;
|
||||
|
||||
/* Check major version; assume a single digit */
|
||||
if( ver[0] < '3' || ver[0] > '9' || ver [1] != '.' )
|
||||
return( -1 );
|
||||
|
||||
if( ver[0] - '0' > 3 )
|
||||
return( 0 );
|
||||
|
||||
/* Ok, so now we know major == 3, check minor.
|
||||
* Assume 1 or 2 digits. */
|
||||
if( ver[2] < '0' || ver[2] > '9' )
|
||||
return( -1 );
|
||||
|
||||
minor = ver[2] - '0';
|
||||
|
||||
if( ver[3] >= '0' && ver[3] <= '9' )
|
||||
minor = 10 * minor + ver[3] - '0';
|
||||
else if( ver [3] != '.' )
|
||||
return( -1 );
|
||||
|
||||
if( minor < 17 )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
static int has_getrandom = -1;
|
||||
#endif /* SYS_getrandom */
|
||||
#endif /* __linux__ */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int mbedtls_platform_entropy_poll( void *data,
|
||||
unsigned char *output, size_t len, size_t *olen )
|
||||
{
|
||||
FILE *file;
|
||||
size_t read_len;
|
||||
((void) data);
|
||||
|
||||
#if defined(HAVE_GETRANDOM)
|
||||
if( has_getrandom == -1 )
|
||||
has_getrandom = ( check_version_3_17_plus() == 0 );
|
||||
|
||||
if( has_getrandom )
|
||||
{
|
||||
int ret;
|
||||
|
||||
if( ( ret = getrandom_wrapper( output, len, 0 ) ) < 0 )
|
||||
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
|
||||
|
||||
*olen = ret;
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* HAVE_GETRANDOM */
|
||||
|
||||
*olen = 0;
|
||||
|
||||
file = fopen( "/dev/urandom", "rb" );
|
||||
if( file == NULL )
|
||||
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
|
||||
|
||||
read_len = fread( output, 1, len, file );
|
||||
if( read_len != len )
|
||||
{
|
||||
fclose( file );
|
||||
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
|
||||
}
|
||||
|
||||
fclose( file );
|
||||
*olen = len;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* _WIN32 && !EFIX64 && !EFI32 */
|
||||
#endif /* !MBEDTLS_NO_PLATFORM_ENTROPY */
|
||||
|
||||
#if defined(MBEDTLS_TEST_NULL_ENTROPY)
|
||||
int mbedtls_null_entropy_poll( void *data,
|
||||
unsigned char *output, size_t len, size_t *olen )
|
||||
{
|
||||
((void) data);
|
||||
((void) output);
|
||||
*olen = 0;
|
||||
|
||||
if( len < sizeof(unsigned char) )
|
||||
return( 0 );
|
||||
|
||||
*olen = sizeof(unsigned char);
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
int mbedtls_hardclock_poll( void *data,
|
||||
unsigned char *output, size_t len, size_t *olen )
|
||||
{
|
||||
unsigned long timer = mbedtls_timing_hardclock();
|
||||
((void) data);
|
||||
*olen = 0;
|
||||
|
||||
if( len < sizeof(unsigned long) )
|
||||
return( 0 );
|
||||
|
||||
memcpy( output, &timer, sizeof(unsigned long) );
|
||||
*olen = sizeof(unsigned long);
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* MBEDTLS_TIMING_C */
|
||||
|
||||
#if defined(MBEDTLS_HAVEGE_C)
|
||||
int mbedtls_havege_poll( void *data,
|
||||
unsigned char *output, size_t len, size_t *olen )
|
||||
{
|
||||
mbedtls_havege_state *hs = (mbedtls_havege_state *) data;
|
||||
*olen = 0;
|
||||
|
||||
if( mbedtls_havege_random( hs, output, len ) != 0 )
|
||||
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
|
||||
|
||||
*olen = len;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* MBEDTLS_HAVEGE_C */
|
||||
|
||||
#if defined(MBEDTLS_ENTROPY_NV_SEED)
|
||||
int mbedtls_nv_seed_poll( void *data,
|
||||
unsigned char *output, size_t len, size_t *olen )
|
||||
{
|
||||
unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
|
||||
size_t use_len = MBEDTLS_ENTROPY_BLOCK_SIZE;
|
||||
((void) data);
|
||||
|
||||
memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
|
||||
|
||||
if( mbedtls_nv_seed_read( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 )
|
||||
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
|
||||
|
||||
if( len < use_len )
|
||||
use_len = len;
|
||||
|
||||
memcpy( output, buf, use_len );
|
||||
*olen = use_len;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* MBEDTLS_ENTROPY_NV_SEED */
|
||||
|
||||
#endif /* MBEDTLS_ENTROPY_C */
|
||||
/*
|
||||
* Platform-specific and custom entropy polling functions
|
||||
*
|
||||
* Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
#define _GNU_SOURCE
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_ENTROPY_C)
|
||||
|
||||
#include "mbedtls/entropy.h"
|
||||
#include "mbedtls/entropy_poll.h"
|
||||
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
#include <string.h>
|
||||
#include "mbedtls/timing.h"
|
||||
#endif
|
||||
#if defined(MBEDTLS_HAVEGE_C)
|
||||
#include "mbedtls/havege.h"
|
||||
#endif
|
||||
#if defined(MBEDTLS_ENTROPY_NV_SEED)
|
||||
#include "mbedtls/platform.h"
|
||||
#endif
|
||||
|
||||
#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
|
||||
|
||||
#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
|
||||
!defined(__APPLE__) && !defined(_WIN32)
|
||||
#error "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in config.h"
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
|
||||
|
||||
#if !defined(_WIN32_WINNT)
|
||||
#define _WIN32_WINNT 0x0400
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
|
||||
int mbedtls_platform_entropy_poll( void *data, unsigned char *output, size_t len,
|
||||
size_t *olen )
|
||||
{
|
||||
HCRYPTPROV provider;
|
||||
((void) data);
|
||||
*olen = 0;
|
||||
|
||||
if( CryptAcquireContext( &provider, NULL, NULL,
|
||||
PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE )
|
||||
{
|
||||
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
|
||||
}
|
||||
|
||||
if( CryptGenRandom( provider, (DWORD) len, output ) == FALSE )
|
||||
{
|
||||
CryptReleaseContext( provider, 0 );
|
||||
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
|
||||
}
|
||||
|
||||
CryptReleaseContext( provider, 0 );
|
||||
*olen = len;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
#else /* _WIN32 && !EFIX64 && !EFI32 */
|
||||
|
||||
/*
|
||||
* Test for Linux getrandom() support.
|
||||
* Since there is no wrapper in the libc yet, use the generic syscall wrapper
|
||||
* available in GNU libc and compatible libc's (eg uClibc).
|
||||
*/
|
||||
#if defined(__linux__) && defined(__GLIBC__)
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
#if defined(SYS_getrandom)
|
||||
#define HAVE_GETRANDOM
|
||||
|
||||
static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags )
|
||||
{
|
||||
/* MemSan cannot understand that the syscall writes to the buffer */
|
||||
#if defined(__has_feature)
|
||||
#if __has_feature(memory_sanitizer)
|
||||
memset( buf, 0, buflen );
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return( syscall( SYS_getrandom, buf, buflen, flags ) );
|
||||
}
|
||||
|
||||
#include <sys/utsname.h>
|
||||
/* Check if version is at least 3.17.0 */
|
||||
static int check_version_3_17_plus( void )
|
||||
{
|
||||
int minor;
|
||||
struct utsname un;
|
||||
const char *ver;
|
||||
|
||||
/* Get version information */
|
||||
uname(&un);
|
||||
ver = un.release;
|
||||
|
||||
/* Check major version; assume a single digit */
|
||||
if( ver[0] < '3' || ver[0] > '9' || ver [1] != '.' )
|
||||
return( -1 );
|
||||
|
||||
if( ver[0] - '0' > 3 )
|
||||
return( 0 );
|
||||
|
||||
/* Ok, so now we know major == 3, check minor.
|
||||
* Assume 1 or 2 digits. */
|
||||
if( ver[2] < '0' || ver[2] > '9' )
|
||||
return( -1 );
|
||||
|
||||
minor = ver[2] - '0';
|
||||
|
||||
if( ver[3] >= '0' && ver[3] <= '9' )
|
||||
minor = 10 * minor + ver[3] - '0';
|
||||
else if( ver [3] != '.' )
|
||||
return( -1 );
|
||||
|
||||
if( minor < 17 )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
static int has_getrandom = -1;
|
||||
#endif /* SYS_getrandom */
|
||||
#endif /* __linux__ */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int mbedtls_platform_entropy_poll( void *data,
|
||||
unsigned char *output, size_t len, size_t *olen )
|
||||
{
|
||||
FILE *file;
|
||||
size_t read_len;
|
||||
((void) data);
|
||||
|
||||
#if defined(HAVE_GETRANDOM)
|
||||
if( has_getrandom == -1 )
|
||||
has_getrandom = ( check_version_3_17_plus() == 0 );
|
||||
|
||||
if( has_getrandom )
|
||||
{
|
||||
int ret;
|
||||
|
||||
if( ( ret = getrandom_wrapper( output, len, 0 ) ) < 0 )
|
||||
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
|
||||
|
||||
*olen = ret;
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* HAVE_GETRANDOM */
|
||||
|
||||
*olen = 0;
|
||||
|
||||
file = fopen( "/dev/urandom", "rb" );
|
||||
if( file == NULL )
|
||||
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
|
||||
|
||||
read_len = fread( output, 1, len, file );
|
||||
if( read_len != len )
|
||||
{
|
||||
fclose( file );
|
||||
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
|
||||
}
|
||||
|
||||
fclose( file );
|
||||
*olen = len;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* _WIN32 && !EFIX64 && !EFI32 */
|
||||
#endif /* !MBEDTLS_NO_PLATFORM_ENTROPY */
|
||||
|
||||
#if defined(MBEDTLS_TEST_NULL_ENTROPY)
|
||||
int mbedtls_null_entropy_poll( void *data,
|
||||
unsigned char *output, size_t len, size_t *olen )
|
||||
{
|
||||
((void) data);
|
||||
((void) output);
|
||||
*olen = 0;
|
||||
|
||||
if( len < sizeof(unsigned char) )
|
||||
return( 0 );
|
||||
|
||||
*olen = sizeof(unsigned char);
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
int mbedtls_hardclock_poll( void *data,
|
||||
unsigned char *output, size_t len, size_t *olen )
|
||||
{
|
||||
unsigned long timer = mbedtls_timing_hardclock();
|
||||
((void) data);
|
||||
*olen = 0;
|
||||
|
||||
if( len < sizeof(unsigned long) )
|
||||
return( 0 );
|
||||
|
||||
memcpy( output, &timer, sizeof(unsigned long) );
|
||||
*olen = sizeof(unsigned long);
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* MBEDTLS_TIMING_C */
|
||||
|
||||
#if defined(MBEDTLS_HAVEGE_C)
|
||||
int mbedtls_havege_poll( void *data,
|
||||
unsigned char *output, size_t len, size_t *olen )
|
||||
{
|
||||
mbedtls_havege_state *hs = (mbedtls_havege_state *) data;
|
||||
*olen = 0;
|
||||
|
||||
if( mbedtls_havege_random( hs, output, len ) != 0 )
|
||||
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
|
||||
|
||||
*olen = len;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* MBEDTLS_HAVEGE_C */
|
||||
|
||||
#if defined(MBEDTLS_ENTROPY_NV_SEED)
|
||||
int mbedtls_nv_seed_poll( void *data,
|
||||
unsigned char *output, size_t len, size_t *olen )
|
||||
{
|
||||
unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
|
||||
size_t use_len = MBEDTLS_ENTROPY_BLOCK_SIZE;
|
||||
((void) data);
|
||||
|
||||
memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
|
||||
|
||||
if( mbedtls_nv_seed_read( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 )
|
||||
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
|
||||
|
||||
if( len < use_len )
|
||||
use_len = len;
|
||||
|
||||
memcpy( output, buf, use_len );
|
||||
*olen = use_len;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* MBEDTLS_ENTROPY_NV_SEED */
|
||||
|
||||
#endif /* MBEDTLS_ENTROPY_C */
|
||||
|
@ -9,6 +9,7 @@ if (platform == Platform.OSX) project.addDefine('KORE_DEBUGDIR="osx-hl"');
|
||||
if (platform == Platform.iOS) project.addDefine('KORE_DEBUGDIR="ios-hl"');
|
||||
if (platform !== Platform.Windows || audio !== AudioApi.DirectSound) {
|
||||
project.addDefine('KORE_MULTITHREADED_AUDIO');
|
||||
project.addDefine('KINC_MULTITHREADED_AUDIO');
|
||||
}
|
||||
|
||||
project.addDefine('KORE');
|
||||
|
@ -1,31 +1,70 @@
|
||||
package kha.graphics4;
|
||||
|
||||
import kha.Blob;
|
||||
|
||||
class FragmentShader {
|
||||
public var _shader: Pointer;
|
||||
|
||||
public function new(sources: Array<Blob>, files: Array<String>) {
|
||||
initShader(sources[0]);
|
||||
}
|
||||
|
||||
function initShader(source: Blob): Void {
|
||||
_shader = kinc_create_fragmentshader(source.bytes.getData(), source.bytes.getData().length);
|
||||
}
|
||||
|
||||
public static function fromSource(source: String): FragmentShader {
|
||||
var sh = new FragmentShader(null, null);
|
||||
sh._shader = kinc_fragmentshader_from_source(StringHelper.convert(source));
|
||||
return sh;
|
||||
}
|
||||
|
||||
public function delete(): Void {}
|
||||
|
||||
@:hlNative("std", "kinc_create_fragmentshader") static function kinc_create_fragmentshader(data: hl.Bytes, length: Int): Pointer {
|
||||
return null;
|
||||
}
|
||||
|
||||
@:hlNative("std", "kinc_fragmentshader_from_source") static function kinc_fragmentshader_from_source(source: hl.Bytes): Pointer {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
package kha.graphics4;
|
||||
using StringTools;
|
||||
import kha.Blob;
|
||||
|
||||
class FragmentShader {
|
||||
public var _shader: Pointer;
|
||||
|
||||
public function new(sources: Array<Blob>, files: Array<String>) {
|
||||
//initShader(sources[0]);
|
||||
var shaderBlob: Blob = null;
|
||||
var shaderFile: String = null;
|
||||
|
||||
#if kha_opengl
|
||||
final expectedExtension = ".glsl";
|
||||
#elseif kha_direct3d11
|
||||
final expectedExtension = ".d3d11";
|
||||
#elseif kha_direct3d12
|
||||
final expectedExtension = ".d3d12";
|
||||
#elseif kha_metal
|
||||
final expectedExtension = ".metal";
|
||||
#elseif kha_vulkan
|
||||
final expectedExtension = ".spirv";
|
||||
#else
|
||||
final expectedExtension = ".glsl";
|
||||
#end
|
||||
|
||||
if (sources != null && files != null) {
|
||||
for (i in 0...files.length) {
|
||||
if (files[i].endsWith(expectedExtension)) {
|
||||
shaderBlob = sources[i];
|
||||
shaderFile = files[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (shaderBlob == null && sources != null && sources.length > 0) {
|
||||
trace('Warning: Could not find shader with extension ${expectedExtension}. Falling back to sources[0]: ${files != null && files.length > 0 ? files[0] : "Unknown"}');
|
||||
shaderBlob = sources[0];
|
||||
}
|
||||
|
||||
if (shaderBlob != null) {
|
||||
initShader(shaderBlob);
|
||||
} else {
|
||||
trace('Error: No suitable fragment shader source found!');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function initShader(source: Blob): Void {
|
||||
//_shader = kinc_create_fragmentshader(source.bytes.getData(), source.bytes.getData().length);
|
||||
_shader = kinc_create_fragmentshader(source.bytes.getData(), source.length); // Use source.length here
|
||||
}
|
||||
|
||||
public static function fromSource(source: String): FragmentShader {
|
||||
var sh = new FragmentShader(null, null);
|
||||
sh._shader = kinc_fragmentshader_from_source(StringHelper.convert(source));
|
||||
return sh;
|
||||
}
|
||||
|
||||
public function delete(): Void {}
|
||||
|
||||
@:hlNative("std", "kinc_create_fragmentshader") static function kinc_create_fragmentshader(data: hl.Bytes, length: Int): Pointer {
|
||||
return null;
|
||||
}
|
||||
|
||||
@:hlNative("std", "kinc_fragmentshader_from_source") static function kinc_fragmentshader_from_source(source: hl.Bytes): Pointer {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -1,179 +1,38 @@
|
||||
#include <kinc/compute/compute.h>
|
||||
#include <kinc/graphics4/compute.h>
|
||||
#include <kinc/graphics4/texture.h>
|
||||
|
||||
#include <hl.h>
|
||||
|
||||
vbyte *hl_kinc_compute_create_shader(vbyte *data, int length) {
|
||||
kinc_compute_shader_t *shader = (kinc_compute_shader_t *)malloc(sizeof(kinc_compute_shader_t));
|
||||
kinc_compute_shader_init(shader, data, length);
|
||||
kinc_g4_compute_shader *shader = (kinc_g4_compute_shader *)malloc(sizeof(kinc_g4_compute_shader));
|
||||
kinc_g4_compute_shader_init(shader, data, length);
|
||||
return (vbyte *)shader;
|
||||
}
|
||||
|
||||
void hl_kinc_compute_delete_shader(vbyte *shader) {
|
||||
kinc_compute_shader_t *sh = (kinc_compute_shader_t *)shader;
|
||||
kinc_compute_shader_destroy(sh);
|
||||
kinc_g4_compute_shader *sh = (kinc_g4_compute_shader *)shader;
|
||||
kinc_g4_compute_shader_destroy(sh);
|
||||
free(sh);
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_compute_get_constantlocation(vbyte *shader, vbyte *name) {
|
||||
kinc_compute_shader_t *sh = (kinc_compute_shader_t *)shader;
|
||||
kinc_compute_constant_location_t *location = (kinc_compute_constant_location_t *)malloc(sizeof(kinc_compute_constant_location_t));
|
||||
*location = kinc_compute_shader_get_constant_location(sh, (char *)name), sizeof(kinc_compute_constant_location_t);
|
||||
kinc_g4_compute_shader *sh = (kinc_g4_compute_shader *)shader;
|
||||
kinc_g4_constant_location_t *location = (kinc_g4_constant_location_t *)malloc(sizeof(kinc_g4_constant_location_t));
|
||||
*location = kinc_g4_compute_shader_get_constant_location(sh, (char *)name);
|
||||
return (vbyte *)location;
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_compute_get_textureunit(vbyte *shader, vbyte *name) {
|
||||
kinc_compute_shader_t *sh = (kinc_compute_shader_t *)shader;
|
||||
kinc_compute_texture_unit_t *unit = (kinc_compute_texture_unit_t *)malloc(sizeof(kinc_compute_texture_unit_t));
|
||||
*unit = kinc_compute_shader_get_texture_unit(sh, (char *)name), sizeof(kinc_compute_texture_unit_t);
|
||||
kinc_g4_compute_shader *sh = (kinc_g4_compute_shader *)shader;
|
||||
kinc_g4_texture_unit_t *unit = (kinc_g4_texture_unit_t *)malloc(sizeof(kinc_g4_texture_unit_t));
|
||||
*unit = kinc_g4_compute_shader_get_texture_unit(sh, (char *)name);
|
||||
return (vbyte *)unit;
|
||||
}
|
||||
|
||||
void hl_kinc_compute_set_bool(vbyte *location, bool value) {
|
||||
kinc_compute_constant_location_t *loc = (kinc_compute_constant_location_t *)location;
|
||||
kinc_compute_set_bool(*loc, value);
|
||||
void hl_kinc_set_compute_shader(vbyte *shader) {
|
||||
kinc_g4_set_compute_shader((kinc_g4_compute_shader *)shader);
|
||||
}
|
||||
|
||||
void hl_kinc_compute_set_int(vbyte *location, int value) {
|
||||
kinc_compute_constant_location_t *loc = (kinc_compute_constant_location_t *)location;
|
||||
kinc_compute_set_int(*loc, value);
|
||||
}
|
||||
|
||||
void hl_kinc_compute_set_float(vbyte *location, float value) {
|
||||
kinc_compute_constant_location_t *loc = (kinc_compute_constant_location_t *)location;
|
||||
kinc_compute_set_float(*loc, value);
|
||||
}
|
||||
|
||||
void hl_kinc_compute_set_float2(vbyte *location, float value1, float value2) {
|
||||
kinc_compute_constant_location_t *loc = (kinc_compute_constant_location_t *)location;
|
||||
kinc_compute_set_float2(*loc, value1, value2);
|
||||
}
|
||||
|
||||
void hl_kinc_compute_set_float3(vbyte *location, float value1, float value2, float value3) {
|
||||
kinc_compute_constant_location_t *loc = (kinc_compute_constant_location_t *)location;
|
||||
kinc_compute_set_float3(*loc, value1, value2, value3);
|
||||
}
|
||||
|
||||
void hl_kinc_compute_set_float4(vbyte *location, float value1, float value2, float value3, float value4) {
|
||||
kinc_compute_constant_location_t *loc = (kinc_compute_constant_location_t *)location;
|
||||
kinc_compute_set_float4(*loc, value1, value2, value3, value4);
|
||||
}
|
||||
|
||||
void hl_kinc_compute_set_floats(vbyte *location, vbyte *values, int count) {
|
||||
kinc_compute_constant_location_t *loc = (kinc_compute_constant_location_t *)location;
|
||||
kinc_compute_set_floats(*loc, (float *)values, count);
|
||||
}
|
||||
|
||||
void hl_kinc_compute_set_matrix(vbyte *location, float _00, float _10, float _20, float _30, float _01, float _11, float _21, float _31, float _02, float _12,
|
||||
float _22, float _32, float _03, float _13, float _23, float _33) {
|
||||
kinc_compute_constant_location_t *loc = (kinc_compute_constant_location_t *)location;
|
||||
kinc_matrix4x4_t value;
|
||||
kinc_matrix4x4_set(&value, 0, 0, _00);
|
||||
kinc_matrix4x4_set(&value, 0, 1, _01);
|
||||
kinc_matrix4x4_set(&value, 0, 2, _02);
|
||||
kinc_matrix4x4_set(&value, 0, 3, _03);
|
||||
kinc_matrix4x4_set(&value, 1, 0, _10);
|
||||
kinc_matrix4x4_set(&value, 1, 1, _11);
|
||||
kinc_matrix4x4_set(&value, 1, 2, _12);
|
||||
kinc_matrix4x4_set(&value, 1, 3, _13);
|
||||
kinc_matrix4x4_set(&value, 2, 0, _20);
|
||||
kinc_matrix4x4_set(&value, 2, 1, _21);
|
||||
kinc_matrix4x4_set(&value, 2, 2, _22);
|
||||
kinc_matrix4x4_set(&value, 2, 3, _23);
|
||||
kinc_matrix4x4_set(&value, 3, 0, _30);
|
||||
kinc_matrix4x4_set(&value, 3, 1, _31);
|
||||
kinc_matrix4x4_set(&value, 3, 2, _32);
|
||||
kinc_matrix4x4_set(&value, 3, 3, _33);
|
||||
kinc_compute_set_matrix4(*loc, &value);
|
||||
}
|
||||
|
||||
void hl_kinc_compute_set_matrix3(vbyte *location, float _00, float _10, float _20, float _01, float _11, float _21, float _02, float _12, float _22) {
|
||||
kinc_compute_constant_location_t *loc = (kinc_compute_constant_location_t *)location;
|
||||
kinc_matrix3x3_t value;
|
||||
kinc_matrix3x3_set(&value, 0, 0, _00);
|
||||
kinc_matrix3x3_set(&value, 0, 1, _01);
|
||||
kinc_matrix3x3_set(&value, 0, 2, _02);
|
||||
kinc_matrix3x3_set(&value, 1, 0, _10);
|
||||
kinc_matrix3x3_set(&value, 1, 1, _11);
|
||||
kinc_matrix3x3_set(&value, 1, 2, _12);
|
||||
kinc_matrix3x3_set(&value, 2, 0, _20);
|
||||
kinc_matrix3x3_set(&value, 2, 1, _21);
|
||||
kinc_matrix3x3_set(&value, 2, 2, _22);
|
||||
kinc_compute_set_matrix3(*loc, &value);
|
||||
}
|
||||
|
||||
void hl_kinc_compute_set_texture(vbyte *unit, vbyte *texture, int access) {
|
||||
kinc_compute_texture_unit_t *u = (kinc_compute_texture_unit_t *)unit;
|
||||
kinc_g4_texture_t *tex = (kinc_g4_texture_t *)texture;
|
||||
kinc_compute_set_texture(*u, tex, (kinc_compute_access_t)access);
|
||||
}
|
||||
|
||||
void hl_kinc_compute_set_target(vbyte *unit, vbyte *renderTarget, int access) {
|
||||
kinc_compute_texture_unit_t *u = (kinc_compute_texture_unit_t *)unit;
|
||||
kinc_g4_render_target_t *rt = (kinc_g4_render_target_t *)renderTarget;
|
||||
kinc_compute_set_render_target(*u, rt, (kinc_compute_access_t)access);
|
||||
}
|
||||
|
||||
void hl_kinc_compute_set_sampled_texture(vbyte *unit, vbyte *texture) {
|
||||
kinc_compute_texture_unit_t *u = (kinc_compute_texture_unit_t *)unit;
|
||||
kinc_g4_texture_t *tex = (kinc_g4_texture_t *)texture;
|
||||
kinc_compute_set_sampled_texture(*u, tex);
|
||||
}
|
||||
|
||||
void hl_kinc_compute_set_sampled_target(vbyte *unit, vbyte *renderTarget) {
|
||||
kinc_compute_texture_unit_t *u = (kinc_compute_texture_unit_t *)unit;
|
||||
kinc_g4_render_target_t *rt = (kinc_g4_render_target_t *)renderTarget;
|
||||
kinc_compute_set_sampled_render_target(*u, rt);
|
||||
}
|
||||
|
||||
void hl_kinc_compute_set_sampled_depth_target(vbyte *unit, vbyte *renderTarget) {
|
||||
kinc_compute_texture_unit_t *u = (kinc_compute_texture_unit_t *)unit;
|
||||
kinc_g4_render_target_t *rt = (kinc_g4_render_target_t *)renderTarget;
|
||||
kinc_compute_set_sampled_depth_from_render_target(*u, rt);
|
||||
}
|
||||
|
||||
void hl_kinc_compute_set_sampled_cubemap_texture(vbyte *unit, vbyte *texture) {
|
||||
kinc_compute_texture_unit_t *u = (kinc_compute_texture_unit_t *)unit;
|
||||
kinc_g4_texture_t *tex = (kinc_g4_texture_t *)texture;
|
||||
kinc_compute_set_sampled_texture(*u, tex);
|
||||
}
|
||||
|
||||
void hl_kinc_compute_set_sampled_cubemap_target(vbyte *unit, vbyte *renderTarget) {
|
||||
kinc_compute_texture_unit_t *u = (kinc_compute_texture_unit_t *)unit;
|
||||
kinc_g4_render_target_t *rt = (kinc_g4_render_target_t *)renderTarget;
|
||||
kinc_compute_set_sampled_render_target(*u, rt);
|
||||
}
|
||||
|
||||
void hl_kinc_compute_set_sampled_cubemap_depth_target(vbyte *unit, vbyte *renderTarget) {
|
||||
kinc_compute_texture_unit_t *u = (kinc_compute_texture_unit_t *)unit;
|
||||
kinc_g4_render_target_t *rt = (kinc_g4_render_target_t *)renderTarget;
|
||||
kinc_compute_set_sampled_depth_from_render_target(*u, rt);
|
||||
}
|
||||
|
||||
void hl_kinc_compute_set_texture_parameters(vbyte *unit, int uAddressing, int vAddressing, int minificationFilter, int magnificationFilter, int mipmapFilter) {
|
||||
kinc_compute_texture_unit_t *u = (kinc_compute_texture_unit_t *)unit;
|
||||
kinc_compute_set_texture_addressing(*u, KINC_G4_TEXTURE_DIRECTION_U, (kinc_g4_texture_addressing_t)uAddressing);
|
||||
kinc_compute_set_texture_addressing(*u, KINC_G4_TEXTURE_DIRECTION_V, (kinc_g4_texture_addressing_t)vAddressing);
|
||||
kinc_compute_set_texture_minification_filter(*u, (kinc_g4_texture_filter_t)minificationFilter);
|
||||
kinc_compute_set_texture_magnification_filter(*u, (kinc_g4_texture_filter_t)magnificationFilter);
|
||||
kinc_compute_set_texture_mipmap_filter(*u, (kinc_g4_mipmap_filter_t)mipmapFilter);
|
||||
}
|
||||
|
||||
void hl_kinc_compute_set_texture3d_parameters(vbyte *unit, int uAddressing, int vAddressing, int wAddressing, int minificationFilter, int magnificationFilter,
|
||||
int mipmapFilter) {
|
||||
kinc_compute_texture_unit_t *u = (kinc_compute_texture_unit_t *)unit;
|
||||
kinc_compute_set_texture3d_addressing(*u, KINC_G4_TEXTURE_DIRECTION_U, (kinc_g4_texture_addressing_t)uAddressing);
|
||||
kinc_compute_set_texture3d_addressing(*u, KINC_G4_TEXTURE_DIRECTION_V, (kinc_g4_texture_addressing_t)vAddressing);
|
||||
kinc_compute_set_texture3d_addressing(*u, KINC_G4_TEXTURE_DIRECTION_W, (kinc_g4_texture_addressing_t)wAddressing);
|
||||
kinc_compute_set_texture3d_minification_filter(*u, (kinc_g4_texture_filter_t)minificationFilter);
|
||||
kinc_compute_set_texture3d_magnification_filter(*u, (kinc_g4_texture_filter_t)magnificationFilter);
|
||||
kinc_compute_set_texture3d_mipmap_filter(*u, (kinc_g4_mipmap_filter_t)mipmapFilter);
|
||||
}
|
||||
|
||||
void hl_kinc_compute_set_shader(vbyte *shader) {
|
||||
kinc_compute_set_shader((kinc_compute_shader_t *)shader);
|
||||
}
|
||||
|
||||
void hl_kinc_compute_compute(int x, int y, int z) {
|
||||
kinc_compute(x, y, z);
|
||||
void hl_kinc_compute(int x, int y, int z) {
|
||||
kinc_g4_compute(x, y, z);
|
||||
}
|
||||
|
@ -1,127 +1,129 @@
|
||||
#include <kinc/audio2/audio.h>
|
||||
#include <kinc/graphics4/graphics.h>
|
||||
#include <kinc/io/filereader.h>
|
||||
#include <kinc/log.h>
|
||||
#include <kinc/system.h>
|
||||
#include <kinc/window.h>
|
||||
|
||||
#include <hl.h>
|
||||
|
||||
void frame();
|
||||
|
||||
static bool visible = true;
|
||||
static bool paused = false;
|
||||
|
||||
typedef void (*FN_AUDIO_CALL_CALLBACK)(int);
|
||||
typedef float (*FN_AUDIO_READ_SAMPLE)(void);
|
||||
|
||||
void (*audioCallCallback)(int);
|
||||
float (*audioReadSample)(void);
|
||||
|
||||
static void update(void *data) {
|
||||
if (paused) {
|
||||
return;
|
||||
}
|
||||
|
||||
kinc_a2_update();
|
||||
|
||||
int windowCount = kinc_count_windows();
|
||||
|
||||
for (int windowIndex = 0; windowIndex < windowCount; ++windowIndex) {
|
||||
if (visible) {
|
||||
kinc_g4_begin(windowIndex);
|
||||
frame();
|
||||
kinc_g4_end(windowIndex);
|
||||
}
|
||||
}
|
||||
|
||||
if (!kinc_g4_swap_buffers()) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Graphics context lost.");
|
||||
}
|
||||
}
|
||||
|
||||
static bool mixThreadregistered = false;
|
||||
|
||||
static void mix(kinc_a2_buffer_t *buffer, int samples) {
|
||||
#ifdef KORE_MULTITHREADED_AUDIO
|
||||
if (!mixThreadregistered) {
|
||||
vdynamic *ret;
|
||||
hl_register_thread(&ret);
|
||||
mixThreadregistered = true;
|
||||
}
|
||||
hl_blocking(true);
|
||||
#endif
|
||||
|
||||
audioCallCallback(samples);
|
||||
|
||||
for (int i = 0; i < samples; ++i) {
|
||||
float value = audioReadSample();
|
||||
*(float *)&buffer->data[buffer->write_location] = value;
|
||||
buffer->write_location += 4;
|
||||
if (buffer->write_location >= buffer->data_size) {
|
||||
buffer->write_location = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef KORE_MULTITHREADED_AUDIO
|
||||
hl_blocking(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
void hl_init_kore(vbyte *title, int width, int height, int samplesPerPixel, bool vSync, int windowMode, int windowFeatures) {
|
||||
kinc_log(KINC_LOG_LEVEL_INFO, "Starting KincHL");
|
||||
|
||||
kinc_window_options_t win;
|
||||
kinc_window_options_set_defaults(&win);
|
||||
win.title = (char *)title;
|
||||
win.width = width;
|
||||
win.height = height;
|
||||
win.x = -1;
|
||||
win.y = -1;
|
||||
win.mode = (kinc_window_mode_t)windowMode;
|
||||
win.window_features = windowFeatures;
|
||||
kinc_framebuffer_options_t frame;
|
||||
kinc_framebuffer_options_set_defaults(&frame);
|
||||
frame.vertical_sync = vSync;
|
||||
frame.samples_per_pixel = samplesPerPixel;
|
||||
kinc_init((char *)title, width, height, &win, &frame);
|
||||
|
||||
kinc_set_update_callback(update, NULL);
|
||||
}
|
||||
|
||||
void hl_kinc_init_audio(vclosure *callCallback, vclosure *readSample, int *outSamplesPerSecond) {
|
||||
audioCallCallback = *((FN_AUDIO_CALL_CALLBACK *)(&callCallback->fun));
|
||||
audioReadSample = *((FN_AUDIO_READ_SAMPLE *)(&readSample->fun));
|
||||
kinc_a2_set_callback(mix);
|
||||
kinc_a2_init();
|
||||
*outSamplesPerSecond = kinc_a2_samples_per_second;
|
||||
}
|
||||
|
||||
void hl_run_kore(void) {
|
||||
kinc_start();
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_file_contents(vbyte *name, int *size) {
|
||||
int len;
|
||||
int p = 0;
|
||||
vbyte *content;
|
||||
kinc_file_reader_t file;
|
||||
if (!kinc_file_reader_open(&file, (char *)name, KINC_FILE_TYPE_ASSET)) {
|
||||
return NULL;
|
||||
}
|
||||
hl_blocking(true);
|
||||
len = (int)kinc_file_reader_size(&file);
|
||||
if (size) {
|
||||
*size = len;
|
||||
}
|
||||
hl_blocking(false);
|
||||
content = (vbyte *)hl_gc_alloc_noptr(size ? len : len + 1);
|
||||
hl_blocking(true);
|
||||
if (!size) {
|
||||
content[len] = 0; // final 0 for UTF8
|
||||
}
|
||||
kinc_file_reader_read(&file, content, len);
|
||||
kinc_file_reader_close(&file);
|
||||
hl_blocking(false);
|
||||
return content;
|
||||
}
|
||||
#include <kinc/audio2/audio.h>
|
||||
#include <kinc/graphics4/graphics.h>
|
||||
#include <kinc/io/filereader.h>
|
||||
#include <kinc/log.h>
|
||||
#include <kinc/system.h>
|
||||
#include <kinc/window.h>
|
||||
|
||||
#include <hl.h>
|
||||
|
||||
void frame();
|
||||
|
||||
static bool visible = true;
|
||||
static bool paused = false;
|
||||
|
||||
typedef void (*FN_AUDIO_CALL_CALLBACK)(int);
|
||||
typedef float (*FN_AUDIO_READ_SAMPLE)(void);
|
||||
|
||||
void (*audioCallCallback)(int);
|
||||
float (*audioReadSample)(void);
|
||||
|
||||
static void update(void *data) {
|
||||
if (paused) {
|
||||
return;
|
||||
}
|
||||
|
||||
kinc_a2_update();
|
||||
|
||||
int windowCount = kinc_count_windows();
|
||||
|
||||
for (int windowIndex = 0; windowIndex < windowCount; ++windowIndex) {
|
||||
if (visible) {
|
||||
kinc_g4_begin(windowIndex);
|
||||
frame();
|
||||
kinc_g4_end(windowIndex);
|
||||
}
|
||||
}
|
||||
|
||||
if (!kinc_g4_swap_buffers()) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Graphics context lost.");
|
||||
}
|
||||
}
|
||||
|
||||
static bool mixThreadregistered = false;
|
||||
|
||||
static void mix(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata) {
|
||||
#ifdef KINC_MULTITHREADED_AUDIO
|
||||
if (!mixThreadregistered) {
|
||||
vdynamic *ret;
|
||||
hl_register_thread(&ret);
|
||||
mixThreadregistered = true;
|
||||
}
|
||||
hl_blocking(true);
|
||||
#endif
|
||||
|
||||
audioCallCallback(samples);
|
||||
|
||||
for (uint32_t i = 0; i < samples; i += 2) {
|
||||
float left_value = audioReadSample();
|
||||
float right_value = audioReadSample();
|
||||
*(float *)&buffer->channels[0][buffer->write_location] = left_value;
|
||||
*(float *)&buffer->channels[1][buffer->write_location] = right_value;
|
||||
buffer->write_location += 1;
|
||||
if (buffer->write_location >= buffer->data_size) {
|
||||
buffer->write_location = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef KINC_MULTITHREADED_AUDIO
|
||||
hl_blocking(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
void hl_init_kore(vbyte *title, int width, int height, int samplesPerPixel, bool vSync, int windowMode, int windowFeatures) {
|
||||
kinc_log(KINC_LOG_LEVEL_INFO, "Starting KincHL");
|
||||
|
||||
kinc_window_options_t win;
|
||||
kinc_window_options_set_defaults(&win);
|
||||
win.title = (char *)title;
|
||||
win.width = width;
|
||||
win.height = height;
|
||||
win.x = -1;
|
||||
win.y = -1;
|
||||
win.mode = (kinc_window_mode_t)windowMode;
|
||||
win.window_features = windowFeatures;
|
||||
kinc_framebuffer_options_t frame;
|
||||
kinc_framebuffer_options_set_defaults(&frame);
|
||||
frame.vertical_sync = vSync;
|
||||
frame.samples_per_pixel = samplesPerPixel;
|
||||
kinc_init((char *)title, width, height, &win, &frame);
|
||||
|
||||
kinc_set_update_callback(update, NULL);
|
||||
}
|
||||
|
||||
void hl_kinc_init_audio(vclosure *callCallback, vclosure *readSample, int *outSamplesPerSecond) {
|
||||
audioCallCallback = *((FN_AUDIO_CALL_CALLBACK *)(&callCallback->fun));
|
||||
audioReadSample = *((FN_AUDIO_READ_SAMPLE *)(&readSample->fun));
|
||||
kinc_a2_init();
|
||||
kinc_a2_set_callback(mix, NULL);
|
||||
*outSamplesPerSecond = kinc_a2_samples_per_second();
|
||||
}
|
||||
|
||||
void hl_run_kore(void) {
|
||||
kinc_start();
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_file_contents(vbyte *name, int *size) {
|
||||
int len;
|
||||
int p = 0;
|
||||
vbyte *content;
|
||||
kinc_file_reader_t file;
|
||||
if (!kinc_file_reader_open(&file, (char *)name, KINC_FILE_TYPE_ASSET)) {
|
||||
return NULL;
|
||||
}
|
||||
hl_blocking(true);
|
||||
len = (int)kinc_file_reader_size(&file);
|
||||
if (size) {
|
||||
*size = len;
|
||||
}
|
||||
hl_blocking(false);
|
||||
content = (vbyte *)hl_gc_alloc_noptr(size ? len : len + 1);
|
||||
hl_blocking(true);
|
||||
if (!size) {
|
||||
content[len] = 0; // final 0 for UTF8
|
||||
}
|
||||
kinc_file_reader_read(&file, content, len);
|
||||
kinc_file_reader_close(&file);
|
||||
hl_blocking(false);
|
||||
return content;
|
||||
}
|
||||
|
@ -1,265 +1,265 @@
|
||||
#include <kinc/graphics4/graphics.h>
|
||||
#include <kinc/graphics4/pipeline.h>
|
||||
#include <kinc/graphics4/shader.h>
|
||||
#include <kinc/graphics4/vertexstructure.h>
|
||||
|
||||
#include <hl.h>
|
||||
|
||||
static kinc_g4_compare_mode_t convertCompareMode(int mode) {
|
||||
switch (mode) {
|
||||
case 0:
|
||||
return KINC_G4_COMPARE_ALWAYS;
|
||||
case 1:
|
||||
return KINC_G4_COMPARE_NEVER;
|
||||
case 2:
|
||||
return KINC_G4_COMPARE_EQUAL;
|
||||
case 3:
|
||||
return KINC_G4_COMPARE_NOT_EQUAL;
|
||||
case 4:
|
||||
return KINC_G4_COMPARE_LESS;
|
||||
case 5:
|
||||
return KINC_G4_COMPARE_LESS_EQUAL;
|
||||
case 6:
|
||||
return KINC_G4_COMPARE_GREATER;
|
||||
case 7:
|
||||
default:
|
||||
return KINC_G4_COMPARE_GREATER_EQUAL;
|
||||
}
|
||||
}
|
||||
|
||||
static kinc_g4_stencil_action_t convertStencilAction(int action) {
|
||||
switch (action) {
|
||||
case 0:
|
||||
return KINC_G4_STENCIL_KEEP;
|
||||
case 1:
|
||||
return KINC_G4_STENCIL_ZERO;
|
||||
case 2:
|
||||
return KINC_G4_STENCIL_REPLACE;
|
||||
case 3:
|
||||
return KINC_G4_STENCIL_INCREMENT;
|
||||
case 4:
|
||||
return KINC_G4_STENCIL_INCREMENT_WRAP;
|
||||
case 5:
|
||||
return KINC_G4_STENCIL_DECREMENT;
|
||||
case 6:
|
||||
return KINC_G4_STENCIL_DECREMENT_WRAP;
|
||||
case 7:
|
||||
default:
|
||||
return KINC_G4_STENCIL_INVERT;
|
||||
}
|
||||
}
|
||||
|
||||
static kinc_g4_render_target_format_t convertColorAttachment(int format) {
|
||||
switch (format) {
|
||||
case 0:
|
||||
return KINC_G4_RENDER_TARGET_FORMAT_32BIT;
|
||||
case 1:
|
||||
return KINC_G4_RENDER_TARGET_FORMAT_8BIT_RED;
|
||||
case 2:
|
||||
return KINC_G4_RENDER_TARGET_FORMAT_128BIT_FLOAT;
|
||||
case 3:
|
||||
return KINC_G4_RENDER_TARGET_FORMAT_16BIT_DEPTH;
|
||||
case 4:
|
||||
return KINC_G4_RENDER_TARGET_FORMAT_64BIT_FLOAT;
|
||||
case 5:
|
||||
return KINC_G4_RENDER_TARGET_FORMAT_32BIT_RED_FLOAT;
|
||||
case 6:
|
||||
default:
|
||||
return KINC_G4_RENDER_TARGET_FORMAT_16BIT_RED_FLOAT;
|
||||
}
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_create_vertexshader(vbyte *data, int length) {
|
||||
kinc_g4_shader_t *shader = (kinc_g4_shader_t *)malloc(sizeof(kinc_g4_shader_t));
|
||||
kinc_g4_shader_init(shader, data, length, KINC_G4_SHADER_TYPE_VERTEX);
|
||||
return (vbyte *)shader;
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_create_fragmentshader(vbyte *data, int length) {
|
||||
kinc_g4_shader_t *shader = (kinc_g4_shader_t *)malloc(sizeof(kinc_g4_shader_t));
|
||||
kinc_g4_shader_init(shader, data, length, KINC_G4_SHADER_TYPE_FRAGMENT);
|
||||
return (vbyte *)shader;
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_create_geometryshader(vbyte *data, int length) {
|
||||
kinc_g4_shader_t *shader = (kinc_g4_shader_t *)malloc(sizeof(kinc_g4_shader_t));
|
||||
kinc_g4_shader_init(shader, data, length, KINC_G4_SHADER_TYPE_GEOMETRY);
|
||||
return (vbyte *)shader;
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_create_tesscontrolshader(vbyte *data, int length) {
|
||||
kinc_g4_shader_t *shader = (kinc_g4_shader_t *)malloc(sizeof(kinc_g4_shader_t));
|
||||
kinc_g4_shader_init(shader, data, length, KINC_G4_SHADER_TYPE_TESSELLATION_CONTROL);
|
||||
return (vbyte *)shader;
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_create_tessevalshader(vbyte *data, int length) {
|
||||
kinc_g4_shader_t *shader = (kinc_g4_shader_t *)malloc(sizeof(kinc_g4_shader_t));
|
||||
kinc_g4_shader_init(shader, data, length, KINC_G4_SHADER_TYPE_TESSELLATION_EVALUATION);
|
||||
return (vbyte *)shader;
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_vertexshader_from_source(vbyte *source) {
|
||||
kinc_g4_shader_t *shader = (kinc_g4_shader_t *)malloc(sizeof(kinc_g4_shader_t));
|
||||
kinc_g4_shader_init_from_source(shader, (char *)source, KINC_G4_SHADER_TYPE_VERTEX);
|
||||
return (vbyte *)shader;
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_fragmentshader_from_source(vbyte *source) {
|
||||
kinc_g4_shader_t *shader = (kinc_g4_shader_t *)malloc(sizeof(kinc_g4_shader_t));
|
||||
kinc_g4_shader_init_from_source(shader, (char *)source, KINC_G4_SHADER_TYPE_FRAGMENT);
|
||||
return (vbyte *)shader;
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_geometryshader_from_source(vbyte *source) {
|
||||
kinc_g4_shader_t *shader = (kinc_g4_shader_t *)malloc(sizeof(kinc_g4_shader_t));
|
||||
kinc_g4_shader_init_from_source(shader, (char *)source, KINC_G4_SHADER_TYPE_GEOMETRY);
|
||||
return (vbyte *)shader;
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_tesscontrolshader_from_source(vbyte *source) {
|
||||
kinc_g4_shader_t *shader = (kinc_g4_shader_t *)malloc(sizeof(kinc_g4_shader_t));
|
||||
kinc_g4_shader_init_from_source(shader, (char *)source, KINC_G4_SHADER_TYPE_TESSELLATION_CONTROL);
|
||||
return (vbyte *)shader;
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_tessevalshader_from_source(vbyte *source) {
|
||||
kinc_g4_shader_t *shader = (kinc_g4_shader_t *)malloc(sizeof(kinc_g4_shader_t));
|
||||
kinc_g4_shader_init_from_source(shader, (char *)source, KINC_G4_SHADER_TYPE_TESSELLATION_EVALUATION);
|
||||
return (vbyte *)shader;
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_create_pipeline() {
|
||||
kinc_g4_pipeline_t *pipeline = (kinc_g4_pipeline_t *)malloc(sizeof(kinc_g4_pipeline_t));
|
||||
kinc_g4_pipeline_init(pipeline);
|
||||
return (vbyte *)pipeline;
|
||||
}
|
||||
|
||||
void hl_kinc_delete_pipeline(vbyte *pipeline) {
|
||||
kinc_g4_pipeline_t *pipe = (kinc_g4_pipeline_t *)pipeline;
|
||||
kinc_g4_pipeline_destroy(pipe);
|
||||
free(pipe);
|
||||
}
|
||||
|
||||
void hl_kinc_pipeline_set_vertex_shader(vbyte *pipeline, vbyte *shader) {
|
||||
kinc_g4_pipeline_t *pipe = (kinc_g4_pipeline_t *)pipeline;
|
||||
kinc_g4_shader_t *sh = (kinc_g4_shader_t *)shader;
|
||||
pipe->vertex_shader = sh;
|
||||
}
|
||||
|
||||
void hl_kinc_pipeline_set_fragment_shader(vbyte *pipeline, vbyte *shader) {
|
||||
kinc_g4_pipeline_t *pipe = (kinc_g4_pipeline_t *)pipeline;
|
||||
kinc_g4_shader_t *sh = (kinc_g4_shader_t *)shader;
|
||||
pipe->fragment_shader = sh;
|
||||
}
|
||||
|
||||
void hl_kinc_pipeline_set_geometry_shader(vbyte *pipeline, vbyte *shader) {
|
||||
kinc_g4_pipeline_t *pipe = (kinc_g4_pipeline_t *)pipeline;
|
||||
kinc_g4_shader_t *sh = (kinc_g4_shader_t *)shader;
|
||||
pipe->geometry_shader = sh;
|
||||
}
|
||||
|
||||
void hl_kinc_pipeline_set_tesscontrol_shader(vbyte *pipeline, vbyte *shader) {
|
||||
kinc_g4_pipeline_t *pipe = (kinc_g4_pipeline_t *)pipeline;
|
||||
kinc_g4_shader_t *sh = (kinc_g4_shader_t *)shader;
|
||||
pipe->tessellation_control_shader = sh;
|
||||
}
|
||||
|
||||
void hl_kinc_pipeline_set_tesseval_shader(vbyte *pipeline, vbyte *shader) {
|
||||
kinc_g4_pipeline_t *pipe = (kinc_g4_pipeline_t *)pipeline;
|
||||
kinc_g4_shader_t *sh = (kinc_g4_shader_t *)shader;
|
||||
pipe->tessellation_evaluation_shader = sh;
|
||||
}
|
||||
|
||||
void hl_kinc_pipeline_compile(vbyte *pipeline, vbyte *structure0, vbyte *structure1, vbyte *structure2, vbyte *structure3) {
|
||||
kinc_g4_pipeline_t *pipe = (kinc_g4_pipeline_t *)pipeline;
|
||||
pipe->input_layout[0] = (kinc_g4_vertex_structure_t *)structure0;
|
||||
pipe->input_layout[1] = (kinc_g4_vertex_structure_t *)structure1;
|
||||
pipe->input_layout[2] = (kinc_g4_vertex_structure_t *)structure2;
|
||||
pipe->input_layout[3] = (kinc_g4_vertex_structure_t *)structure3;
|
||||
pipe->input_layout[4] = NULL;
|
||||
kinc_g4_pipeline_compile(pipe);
|
||||
}
|
||||
|
||||
void hl_kinc_pipeline_set_states(vbyte *pipeline, int cullMode, int depthMode, int stencilFrontMode, int stencilFrontBothPass, int stencilFrontDepthFail,
|
||||
int stencilFrontFail, int stencilBackMode, int stencilBackBothPass, int stencilBackDepthFail, int stencilBackFail,
|
||||
int blendSource, int blendDestination, int alphaBlendSource, int alphaBlendDestination, bool depthWrite,
|
||||
int stencilReferenceValue, int stencilReadMask, int stencilWriteMask, bool colorWriteMaskRed, bool colorWriteMaskGreen,
|
||||
bool colorWriteMaskBlue, bool colorWriteMaskAlpha, int colorAttachmentCount, int colorAttachment0, int colorAttachment1,
|
||||
int colorAttachment2, int colorAttachment3, int colorAttachment4, int colorAttachment5, int colorAttachment6,
|
||||
int colorAttachment7, int depthAttachmentBits, int stencilAttachmentBits, bool conservativeRasterization) {
|
||||
kinc_g4_pipeline_t *pipe = (kinc_g4_pipeline_t *)pipeline;
|
||||
|
||||
switch (cullMode) {
|
||||
case 0:
|
||||
pipe->cull_mode = KINC_G4_CULL_CLOCKWISE;
|
||||
break;
|
||||
case 1:
|
||||
pipe->cull_mode = KINC_G4_CULL_COUNTER_CLOCKWISE;
|
||||
break;
|
||||
case 2:
|
||||
pipe->cull_mode = KINC_G4_CULL_NOTHING;
|
||||
break;
|
||||
}
|
||||
|
||||
pipe->depth_mode = convertCompareMode(depthMode);
|
||||
pipe->depth_write = depthWrite;
|
||||
|
||||
pipe->stencil_front_mode = convertCompareMode(stencilFrontMode);
|
||||
pipe->stencil_front_both_pass = convertStencilAction(stencilFrontBothPass);
|
||||
pipe->stencil_front_depth_fail = convertStencilAction(stencilFrontDepthFail);
|
||||
pipe->stencil_front_fail = convertStencilAction(stencilFrontFail);
|
||||
|
||||
pipe->stencil_back_mode = convertCompareMode(stencilBackMode);
|
||||
pipe->stencil_back_both_pass = convertStencilAction(stencilBackBothPass);
|
||||
pipe->stencil_back_depth_fail = convertStencilAction(stencilBackDepthFail);
|
||||
pipe->stencil_back_fail = convertStencilAction(stencilBackFail);
|
||||
|
||||
pipe->stencil_reference_value = stencilReferenceValue;
|
||||
pipe->stencil_read_mask = stencilReadMask;
|
||||
pipe->stencil_write_mask = stencilWriteMask;
|
||||
|
||||
pipe->blend_source = (kinc_g4_blending_factor_t)blendSource;
|
||||
pipe->blend_destination = (kinc_g4_blending_factor_t)blendDestination;
|
||||
pipe->alpha_blend_source = (kinc_g4_blending_factor_t)alphaBlendSource;
|
||||
pipe->alpha_blend_destination = (kinc_g4_blending_factor_t)alphaBlendDestination;
|
||||
|
||||
pipe->color_write_mask_red[0] = colorWriteMaskRed;
|
||||
pipe->color_write_mask_green[0] = colorWriteMaskGreen;
|
||||
pipe->color_write_mask_blue[0] = colorWriteMaskBlue;
|
||||
pipe->color_write_mask_alpha[0] = colorWriteMaskAlpha;
|
||||
|
||||
pipe->color_attachment_count = colorAttachmentCount;
|
||||
pipe->color_attachment[0] = convertColorAttachment(colorAttachment0);
|
||||
pipe->color_attachment[1] = convertColorAttachment(colorAttachment1);
|
||||
pipe->color_attachment[2] = convertColorAttachment(colorAttachment2);
|
||||
pipe->color_attachment[3] = convertColorAttachment(colorAttachment3);
|
||||
pipe->color_attachment[4] = convertColorAttachment(colorAttachment4);
|
||||
pipe->color_attachment[5] = convertColorAttachment(colorAttachment5);
|
||||
pipe->color_attachment[6] = convertColorAttachment(colorAttachment6);
|
||||
pipe->color_attachment[7] = convertColorAttachment(colorAttachment7);
|
||||
|
||||
pipe->depth_attachment_bits = depthAttachmentBits;
|
||||
pipe->stencil_attachment_bits = stencilAttachmentBits;
|
||||
|
||||
pipe->conservative_rasterization = conservativeRasterization;
|
||||
}
|
||||
|
||||
void hl_kinc_pipeline_set(vbyte *pipeline) {
|
||||
kinc_g4_pipeline_t *pipe = (kinc_g4_pipeline_t *)pipeline;
|
||||
kinc_g4_set_pipeline(pipe);
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_pipeline_get_constantlocation(vbyte *pipeline, vbyte *name) {
|
||||
kinc_g4_pipeline_t *pipe = (kinc_g4_pipeline_t *)pipeline;
|
||||
kinc_g4_constant_location_t *location = (kinc_g4_constant_location_t *)malloc(sizeof(kinc_g4_constant_location_t));
|
||||
*location = kinc_g4_pipeline_get_constant_location(pipe, (char *)name);
|
||||
return (vbyte *)location;
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_pipeline_get_textureunit(vbyte *pipeline, vbyte *name) {
|
||||
kinc_g4_pipeline_t *pipe = (kinc_g4_pipeline_t *)pipeline;
|
||||
kinc_g4_texture_unit_t *unit = (kinc_g4_texture_unit_t *)malloc(sizeof(kinc_g4_texture_unit_t));
|
||||
*unit = kinc_g4_pipeline_get_texture_unit(pipe, (char *)name);
|
||||
return (vbyte *)unit;
|
||||
}
|
||||
#include <kinc/graphics4/graphics.h>
|
||||
#include <kinc/graphics4/pipeline.h>
|
||||
#include <kinc/graphics4/shader.h>
|
||||
#include <kinc/graphics4/vertexstructure.h>
|
||||
|
||||
#include <hl.h>
|
||||
|
||||
static kinc_g4_compare_mode_t convertCompareMode(int mode) {
|
||||
switch (mode) {
|
||||
case 0:
|
||||
return KINC_G4_COMPARE_ALWAYS;
|
||||
case 1:
|
||||
return KINC_G4_COMPARE_NEVER;
|
||||
case 2:
|
||||
return KINC_G4_COMPARE_EQUAL;
|
||||
case 3:
|
||||
return KINC_G4_COMPARE_NOT_EQUAL;
|
||||
case 4:
|
||||
return KINC_G4_COMPARE_LESS;
|
||||
case 5:
|
||||
return KINC_G4_COMPARE_LESS_EQUAL;
|
||||
case 6:
|
||||
return KINC_G4_COMPARE_GREATER;
|
||||
case 7:
|
||||
default:
|
||||
return KINC_G4_COMPARE_GREATER_EQUAL;
|
||||
}
|
||||
}
|
||||
|
||||
static kinc_g4_stencil_action_t convertStencilAction(int action) {
|
||||
switch (action) {
|
||||
case 0:
|
||||
return KINC_G4_STENCIL_KEEP;
|
||||
case 1:
|
||||
return KINC_G4_STENCIL_ZERO;
|
||||
case 2:
|
||||
return KINC_G4_STENCIL_REPLACE;
|
||||
case 3:
|
||||
return KINC_G4_STENCIL_INCREMENT;
|
||||
case 4:
|
||||
return KINC_G4_STENCIL_INCREMENT_WRAP;
|
||||
case 5:
|
||||
return KINC_G4_STENCIL_DECREMENT;
|
||||
case 6:
|
||||
return KINC_G4_STENCIL_DECREMENT_WRAP;
|
||||
case 7:
|
||||
default:
|
||||
return KINC_G4_STENCIL_INVERT;
|
||||
}
|
||||
}
|
||||
|
||||
static kinc_g4_render_target_format_t convertColorAttachment(int format) {
|
||||
switch (format) {
|
||||
case 0:
|
||||
return KINC_G4_RENDER_TARGET_FORMAT_32BIT;
|
||||
case 1:
|
||||
return KINC_G4_RENDER_TARGET_FORMAT_8BIT_RED;
|
||||
case 2:
|
||||
return KINC_G4_RENDER_TARGET_FORMAT_128BIT_FLOAT;
|
||||
case 3:
|
||||
return KINC_G4_RENDER_TARGET_FORMAT_16BIT_DEPTH;
|
||||
case 4:
|
||||
return KINC_G4_RENDER_TARGET_FORMAT_64BIT_FLOAT;
|
||||
case 5:
|
||||
return KINC_G4_RENDER_TARGET_FORMAT_32BIT_RED_FLOAT;
|
||||
case 6:
|
||||
default:
|
||||
return KINC_G4_RENDER_TARGET_FORMAT_16BIT_RED_FLOAT;
|
||||
}
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_create_vertexshader(vbyte *data, int length) {
|
||||
kinc_g4_shader_t *shader = (kinc_g4_shader_t *)malloc(sizeof(kinc_g4_shader_t));
|
||||
kinc_g4_shader_init(shader, data, length, KINC_G4_SHADER_TYPE_VERTEX);
|
||||
return (vbyte *)shader;
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_create_fragmentshader(vbyte *data, int length) {
|
||||
kinc_g4_shader_t *shader = (kinc_g4_shader_t *)malloc(sizeof(kinc_g4_shader_t));
|
||||
kinc_g4_shader_init(shader, data, length, KINC_G4_SHADER_TYPE_FRAGMENT);
|
||||
return (vbyte *)shader;
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_create_geometryshader(vbyte *data, int length) {
|
||||
kinc_g4_shader_t *shader = (kinc_g4_shader_t *)malloc(sizeof(kinc_g4_shader_t));
|
||||
kinc_g4_shader_init(shader, data, length, KINC_G4_SHADER_TYPE_GEOMETRY);
|
||||
return (vbyte *)shader;
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_create_tesscontrolshader(vbyte *data, int length) {
|
||||
kinc_g4_shader_t *shader = (kinc_g4_shader_t *)malloc(sizeof(kinc_g4_shader_t));
|
||||
kinc_g4_shader_init(shader, data, length, KINC_G4_SHADER_TYPE_TESSELLATION_CONTROL);
|
||||
return (vbyte *)shader;
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_create_tessevalshader(vbyte *data, int length) {
|
||||
kinc_g4_shader_t *shader = (kinc_g4_shader_t *)malloc(sizeof(kinc_g4_shader_t));
|
||||
kinc_g4_shader_init(shader, data, length, KINC_G4_SHADER_TYPE_TESSELLATION_EVALUATION);
|
||||
return (vbyte *)shader;
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_vertexshader_from_source(vbyte *source) {
|
||||
kinc_g4_shader_t *shader = (kinc_g4_shader_t *)malloc(sizeof(kinc_g4_shader_t));
|
||||
kinc_g4_shader_init_from_source(shader, (char *)source, KINC_G4_SHADER_TYPE_VERTEX);
|
||||
return (vbyte *)shader;
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_fragmentshader_from_source(vbyte *source) {
|
||||
kinc_g4_shader_t *shader = (kinc_g4_shader_t *)malloc(sizeof(kinc_g4_shader_t));
|
||||
kinc_g4_shader_init_from_source(shader, (char *)source, KINC_G4_SHADER_TYPE_FRAGMENT);
|
||||
return (vbyte *)shader;
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_geometryshader_from_source(vbyte *source) {
|
||||
kinc_g4_shader_t *shader = (kinc_g4_shader_t *)malloc(sizeof(kinc_g4_shader_t));
|
||||
kinc_g4_shader_init_from_source(shader, (char *)source, KINC_G4_SHADER_TYPE_GEOMETRY);
|
||||
return (vbyte *)shader;
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_tesscontrolshader_from_source(vbyte *source) {
|
||||
kinc_g4_shader_t *shader = (kinc_g4_shader_t *)malloc(sizeof(kinc_g4_shader_t));
|
||||
kinc_g4_shader_init_from_source(shader, (char *)source, KINC_G4_SHADER_TYPE_TESSELLATION_CONTROL);
|
||||
return (vbyte *)shader;
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_tessevalshader_from_source(vbyte *source) {
|
||||
kinc_g4_shader_t *shader = (kinc_g4_shader_t *)malloc(sizeof(kinc_g4_shader_t));
|
||||
kinc_g4_shader_init_from_source(shader, (char *)source, KINC_G4_SHADER_TYPE_TESSELLATION_EVALUATION);
|
||||
return (vbyte *)shader;
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_create_pipeline() {
|
||||
kinc_g4_pipeline_t *pipeline = (kinc_g4_pipeline_t *)malloc(sizeof(kinc_g4_pipeline_t));
|
||||
kinc_g4_pipeline_init(pipeline);
|
||||
return (vbyte *)pipeline;
|
||||
}
|
||||
|
||||
void hl_kinc_delete_pipeline(vbyte *pipeline) {
|
||||
kinc_g4_pipeline_t *pipe = (kinc_g4_pipeline_t *)pipeline;
|
||||
kinc_g4_pipeline_destroy(pipe);
|
||||
free(pipe);
|
||||
}
|
||||
|
||||
void hl_kinc_pipeline_set_vertex_shader(vbyte *pipeline, vbyte *shader) {
|
||||
kinc_g4_pipeline_t *pipe = (kinc_g4_pipeline_t *)pipeline;
|
||||
kinc_g4_shader_t *sh = (kinc_g4_shader_t *)shader;
|
||||
pipe->vertex_shader = sh;
|
||||
}
|
||||
|
||||
void hl_kinc_pipeline_set_fragment_shader(vbyte *pipeline, vbyte *shader) {
|
||||
kinc_g4_pipeline_t *pipe = (kinc_g4_pipeline_t *)pipeline;
|
||||
kinc_g4_shader_t *sh = (kinc_g4_shader_t *)shader;
|
||||
pipe->fragment_shader = sh;
|
||||
}
|
||||
|
||||
void hl_kinc_pipeline_set_geometry_shader(vbyte *pipeline, vbyte *shader) {
|
||||
kinc_g4_pipeline_t *pipe = (kinc_g4_pipeline_t *)pipeline;
|
||||
kinc_g4_shader_t *sh = (kinc_g4_shader_t *)shader;
|
||||
pipe->geometry_shader = sh;
|
||||
}
|
||||
|
||||
void hl_kinc_pipeline_set_tesscontrol_shader(vbyte *pipeline, vbyte *shader) {
|
||||
kinc_g4_pipeline_t *pipe = (kinc_g4_pipeline_t *)pipeline;
|
||||
kinc_g4_shader_t *sh = (kinc_g4_shader_t *)shader;
|
||||
pipe->tessellation_control_shader = sh;
|
||||
}
|
||||
|
||||
void hl_kinc_pipeline_set_tesseval_shader(vbyte *pipeline, vbyte *shader) {
|
||||
kinc_g4_pipeline_t *pipe = (kinc_g4_pipeline_t *)pipeline;
|
||||
kinc_g4_shader_t *sh = (kinc_g4_shader_t *)shader;
|
||||
pipe->tessellation_evaluation_shader = sh;
|
||||
}
|
||||
|
||||
void hl_kinc_pipeline_compile(vbyte *pipeline, vbyte *structure0, vbyte *structure1, vbyte *structure2, vbyte *structure3) {
|
||||
kinc_g4_pipeline_t *pipe = (kinc_g4_pipeline_t *)pipeline;
|
||||
pipe->input_layout[0] = (kinc_g4_vertex_structure_t *)structure0;
|
||||
pipe->input_layout[1] = (kinc_g4_vertex_structure_t *)structure1;
|
||||
pipe->input_layout[2] = (kinc_g4_vertex_structure_t *)structure2;
|
||||
pipe->input_layout[3] = (kinc_g4_vertex_structure_t *)structure3;
|
||||
pipe->input_layout[4] = NULL;
|
||||
kinc_g4_pipeline_compile(pipe);
|
||||
}
|
||||
|
||||
void hl_kinc_pipeline_set_states(vbyte *pipeline, int cullMode, int depthMode, int stencilFrontMode, int stencilFrontBothPass, int stencilFrontDepthFail,
|
||||
int stencilFrontFail, int stencilBackMode, int stencilBackBothPass, int stencilBackDepthFail, int stencilBackFail,
|
||||
int blendSource, int blendDestination, int alphaBlendSource, int alphaBlendDestination, bool depthWrite,
|
||||
int stencilReferenceValue, int stencilReadMask, int stencilWriteMask, bool colorWriteMaskRed, bool colorWriteMaskGreen,
|
||||
bool colorWriteMaskBlue, bool colorWriteMaskAlpha, int colorAttachmentCount, int colorAttachment0, int colorAttachment1,
|
||||
int colorAttachment2, int colorAttachment3, int colorAttachment4, int colorAttachment5, int colorAttachment6,
|
||||
int colorAttachment7, int depthAttachmentBits, int stencilAttachmentBits, bool conservativeRasterization) {
|
||||
kinc_g4_pipeline_t *pipe = (kinc_g4_pipeline_t *)pipeline;
|
||||
|
||||
switch (cullMode) {
|
||||
case 0:
|
||||
pipe->cull_mode = KINC_G4_CULL_CLOCKWISE;
|
||||
break;
|
||||
case 1:
|
||||
pipe->cull_mode = KINC_G4_CULL_COUNTER_CLOCKWISE;
|
||||
break;
|
||||
case 2:
|
||||
pipe->cull_mode = KINC_G4_CULL_NOTHING;
|
||||
break;
|
||||
}
|
||||
|
||||
pipe->depth_mode = convertCompareMode(depthMode);
|
||||
pipe->depth_write = depthWrite;
|
||||
|
||||
pipe->stencil_front_mode = convertCompareMode(stencilFrontMode);
|
||||
pipe->stencil_front_both_pass = convertStencilAction(stencilFrontBothPass);
|
||||
pipe->stencil_front_depth_fail = convertStencilAction(stencilFrontDepthFail);
|
||||
pipe->stencil_front_fail = convertStencilAction(stencilFrontFail);
|
||||
|
||||
pipe->stencil_back_mode = convertCompareMode(stencilBackMode);
|
||||
pipe->stencil_back_both_pass = convertStencilAction(stencilBackBothPass);
|
||||
pipe->stencil_back_depth_fail = convertStencilAction(stencilBackDepthFail);
|
||||
pipe->stencil_back_fail = convertStencilAction(stencilBackFail);
|
||||
|
||||
pipe->stencil_reference_value = stencilReferenceValue;
|
||||
pipe->stencil_read_mask = stencilReadMask;
|
||||
pipe->stencil_write_mask = stencilWriteMask;
|
||||
|
||||
pipe->blend_source = (kinc_g4_blending_factor_t)blendSource;
|
||||
pipe->blend_destination = (kinc_g4_blending_factor_t)blendDestination;
|
||||
pipe->alpha_blend_source = (kinc_g4_blending_factor_t)alphaBlendSource;
|
||||
pipe->alpha_blend_destination = (kinc_g4_blending_factor_t)alphaBlendDestination;
|
||||
|
||||
pipe->color_write_mask_red[0] = colorWriteMaskRed;
|
||||
pipe->color_write_mask_green[0] = colorWriteMaskGreen;
|
||||
pipe->color_write_mask_blue[0] = colorWriteMaskBlue;
|
||||
pipe->color_write_mask_alpha[0] = colorWriteMaskAlpha;
|
||||
|
||||
pipe->color_attachment_count = colorAttachmentCount;
|
||||
pipe->color_attachment[0] = convertColorAttachment(colorAttachment0);
|
||||
pipe->color_attachment[1] = convertColorAttachment(colorAttachment1);
|
||||
pipe->color_attachment[2] = convertColorAttachment(colorAttachment2);
|
||||
pipe->color_attachment[3] = convertColorAttachment(colorAttachment3);
|
||||
pipe->color_attachment[4] = convertColorAttachment(colorAttachment4);
|
||||
pipe->color_attachment[5] = convertColorAttachment(colorAttachment5);
|
||||
pipe->color_attachment[6] = convertColorAttachment(colorAttachment6);
|
||||
pipe->color_attachment[7] = convertColorAttachment(colorAttachment7);
|
||||
|
||||
pipe->depth_attachment_bits = depthAttachmentBits;
|
||||
pipe->stencil_attachment_bits = stencilAttachmentBits;
|
||||
|
||||
pipe->conservative_rasterization = conservativeRasterization;
|
||||
}
|
||||
|
||||
void hl_kinc_pipeline_set(vbyte *pipeline) {
|
||||
kinc_g4_pipeline_t *pipe = (kinc_g4_pipeline_t *)pipeline;
|
||||
kinc_g4_set_pipeline(pipe);
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_pipeline_get_constantlocation(vbyte *pipeline, vbyte *name) {
|
||||
kinc_g4_pipeline_t *pipe = (kinc_g4_pipeline_t *)pipeline;
|
||||
kinc_g4_constant_location_t *location = (kinc_g4_constant_location_t *)malloc(sizeof(kinc_g4_constant_location_t));
|
||||
*location = kinc_g4_pipeline_get_constant_location(pipe, (char *)name);
|
||||
return (vbyte *)location;
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_pipeline_get_textureunit(vbyte *pipeline, vbyte *name) {
|
||||
kinc_g4_pipeline_t *pipe = (kinc_g4_pipeline_t *)pipeline;
|
||||
kinc_g4_texture_unit_t *unit = (kinc_g4_texture_unit_t *)malloc(sizeof(kinc_g4_texture_unit_t));
|
||||
*unit = kinc_g4_pipeline_get_texture_unit(pipe, (char *)name);
|
||||
return (vbyte *)unit;
|
||||
}
|
@ -1,201 +1,201 @@
|
||||
#include <kinc/input/acceleration.h>
|
||||
#include <kinc/input/gamepad.h>
|
||||
#include <kinc/input/keyboard.h>
|
||||
#include <kinc/input/mouse.h>
|
||||
#include <kinc/input/pen.h>
|
||||
#include <kinc/input/rotation.h>
|
||||
#include <kinc/input/surface.h>
|
||||
#include <kinc/log.h>
|
||||
#include <kinc/system.h>
|
||||
#include <kinc/video.h>
|
||||
#include <kinc/window.h>
|
||||
|
||||
#include <hl.h>
|
||||
|
||||
void hl_kinc_log(vbyte *v) {
|
||||
kinc_log(KINC_LOG_LEVEL_INFO, (char *)v);
|
||||
}
|
||||
|
||||
double hl_kinc_get_time(void) {
|
||||
return kinc_time();
|
||||
}
|
||||
|
||||
int hl_kinc_get_window_width(int window) {
|
||||
return kinc_window_width(window);
|
||||
}
|
||||
|
||||
int hl_kinc_get_window_height(int window) {
|
||||
return kinc_window_height(window);
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_get_system_id(void) {
|
||||
return (vbyte *)kinc_system_id();
|
||||
}
|
||||
|
||||
void hl_kinc_vibrate(int ms) {
|
||||
kinc_vibrate(ms);
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_get_language(void) {
|
||||
return (vbyte *)kinc_language();
|
||||
}
|
||||
|
||||
void hl_kinc_request_shutdown(void) {
|
||||
kinc_stop();
|
||||
}
|
||||
|
||||
void hl_kinc_mouse_lock(int windowId) {
|
||||
kinc_mouse_lock(windowId);
|
||||
}
|
||||
|
||||
void hl_kinc_mouse_unlock(void) {
|
||||
kinc_mouse_unlock();
|
||||
}
|
||||
|
||||
bool hl_kinc_can_lock_mouse(void) {
|
||||
return kinc_mouse_can_lock();
|
||||
}
|
||||
|
||||
bool hl_kinc_is_mouse_locked(void) {
|
||||
return kinc_mouse_is_locked();
|
||||
}
|
||||
|
||||
void hl_kinc_show_mouse(bool show) {
|
||||
if (show) {
|
||||
kinc_mouse_show();
|
||||
}
|
||||
else {
|
||||
kinc_mouse_hide();
|
||||
}
|
||||
}
|
||||
|
||||
bool hl_kinc_system_is_fullscreen(void) {
|
||||
return false; // kinc_is_fullscreen();
|
||||
}
|
||||
|
||||
void hl_kinc_system_request_fullscreen(void) {
|
||||
// kinc_change_resolution(display_width(), display_height(), true);
|
||||
}
|
||||
|
||||
void hl_kinc_system_exit_fullscreen(int previousWidth, int previousHeight) {
|
||||
// kinc_change_resolution(previousWidth, previousHeight, false);
|
||||
}
|
||||
|
||||
void hl_kinc_system_change_resolution(int width, int height) {
|
||||
// kinc_change_resolution(width, height, false);
|
||||
}
|
||||
|
||||
void hl_kinc_system_set_keepscreenon(bool on) {
|
||||
kinc_set_keep_screen_on(on);
|
||||
}
|
||||
|
||||
void hl_kinc_system_load_url(vbyte *url) {
|
||||
kinc_load_url((char *)url);
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_get_gamepad_id(int index) {
|
||||
return (vbyte*)kinc_gamepad_product_name(index);
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_get_gamepad_vendor(int index) {
|
||||
return (vbyte*)kinc_gamepad_vendor(index);
|
||||
}
|
||||
|
||||
bool hl_kinc_gamepad_connected(int index) {
|
||||
return kinc_gamepad_connected(index);
|
||||
}
|
||||
|
||||
typedef void (*FN_KEY_DOWN)(int, void *);
|
||||
typedef void (*FN_KEY_UP)(int, void *);
|
||||
typedef void (*FN_KEY_PRESS)(unsigned int, void *);
|
||||
|
||||
void hl_kinc_register_keyboard(vclosure *keyDown, vclosure *keyUp, vclosure *keyPress) {
|
||||
kinc_keyboard_set_key_down_callback(*((FN_KEY_DOWN *)(&keyDown->fun)), NULL);
|
||||
kinc_keyboard_set_key_up_callback(*((FN_KEY_UP *)(&keyUp->fun)), NULL);
|
||||
kinc_keyboard_set_key_press_callback(*((FN_KEY_PRESS *)(&keyPress->fun)), NULL);
|
||||
}
|
||||
|
||||
typedef void (*FN_MOUSE_DOWN)(int, int, int, int, void *);
|
||||
typedef void (*FN_MOUSE_UP)(int, int, int, int, void *);
|
||||
typedef void (*FN_MOUSE_MOVE)(int, int, int, int, int, void *);
|
||||
typedef void (*FN_MOUSE_WHEEL)(int, int, void *);
|
||||
|
||||
void hl_kinc_register_mouse(vclosure *mouseDown, vclosure *mouseUp, vclosure *mouseMove, vclosure *mouseWheel) {
|
||||
kinc_mouse_set_press_callback(*((FN_MOUSE_DOWN *)(&mouseDown->fun)), NULL);
|
||||
kinc_mouse_set_release_callback(*((FN_MOUSE_UP *)(&mouseUp->fun)), NULL);
|
||||
kinc_mouse_set_move_callback(*((FN_MOUSE_MOVE *)(&mouseMove->fun)), NULL);
|
||||
kinc_mouse_set_scroll_callback(*((FN_MOUSE_WHEEL *)(&mouseWheel->fun)), NULL);
|
||||
}
|
||||
|
||||
typedef void (*FN_PEN_DOWN)(int, int, int, float);
|
||||
typedef void (*FN_PEN_UP)(int, int, int, float);
|
||||
typedef void (*FN_PEN_MOVE)(int, int, int, float);
|
||||
|
||||
void hl_kinc_register_pen(vclosure *penDown, vclosure *penUp, vclosure *penMove) {
|
||||
kinc_pen_set_press_callback(*((FN_PEN_DOWN *)(&penDown->fun)));
|
||||
kinc_pen_set_release_callback(*((FN_PEN_UP *)(&penUp->fun)));
|
||||
kinc_pen_set_move_callback(*((FN_PEN_MOVE *)(&penMove->fun)));
|
||||
}
|
||||
|
||||
typedef void (*FN_GAMEPAD_AXIS)(int, int, float);
|
||||
typedef void (*FN_GAMEPAD_BUTTON)(int, int, float);
|
||||
|
||||
void hl_kinc_register_gamepad(vclosure *gamepadAxis, vclosure *gamepadButton) {
|
||||
kinc_gamepad_set_axis_callback(*((FN_GAMEPAD_AXIS *)(&gamepadAxis->fun)));
|
||||
kinc_gamepad_set_button_callback(*((FN_GAMEPAD_BUTTON *)(&gamepadButton->fun)));
|
||||
}
|
||||
|
||||
typedef void (*FN_TOUCH_START)(int, int, int);
|
||||
typedef void (*FN_TOUCH_END)(int, int, int);
|
||||
typedef void (*FN_TOUCH_MOVE)(int, int, int);
|
||||
|
||||
void hl_kinc_register_surface(vclosure *touchStart, vclosure *touchEnd, vclosure *touchMove) {
|
||||
kinc_surface_set_touch_start_callback(*((FN_TOUCH_START *)(&touchStart->fun)));
|
||||
kinc_surface_set_touch_end_callback(*((FN_TOUCH_END *)(&touchEnd->fun)));
|
||||
kinc_surface_set_move_callback(*((FN_TOUCH_MOVE *)(&touchMove->fun)));
|
||||
}
|
||||
|
||||
typedef void (*FN_SENSOR_ACCELEROMETER)(float, float, float);
|
||||
typedef void (*FN_SENSOR_GYROSCOPE)(float, float, float);
|
||||
|
||||
void hl_kinc_register_sensor(vclosure *accelerometerChanged, vclosure *gyroscopeChanged) {
|
||||
kinc_acceleration_set_callback(*((FN_SENSOR_ACCELEROMETER *)(&accelerometerChanged->fun)));
|
||||
kinc_rotation_set_callback(*((FN_SENSOR_GYROSCOPE *)(&gyroscopeChanged->fun)));
|
||||
}
|
||||
|
||||
// typedef void(*FN_CB_ORIENTATION)(int);
|
||||
typedef void (*FN_CB_FOREGROUND)(void *);
|
||||
typedef void (*FN_CB_RESUME)(void *);
|
||||
typedef void (*FN_CB_PAUSE)(void *);
|
||||
typedef void (*FN_CB_BACKGROUND)(void *);
|
||||
typedef void (*FN_CB_SHUTDOWN)(void *);
|
||||
|
||||
void hl_kinc_register_callbacks(vclosure *foreground, vclosure *resume, vclosure *pause, vclosure *background, vclosure *shutdown) {
|
||||
// kinc_set_orientation_callback(orientation);
|
||||
kinc_set_foreground_callback(*((FN_CB_FOREGROUND *)(&foreground->fun)), NULL);
|
||||
kinc_set_resume_callback(*((FN_CB_RESUME *)(&resume->fun)), NULL);
|
||||
kinc_set_pause_callback(*((FN_CB_PAUSE *)(&pause->fun)), NULL);
|
||||
kinc_set_background_callback(*((FN_CB_BACKGROUND *)(&background->fun)), NULL);
|
||||
kinc_set_shutdown_callback(*((FN_CB_SHUTDOWN *)(&shutdown->fun)), NULL);
|
||||
}
|
||||
|
||||
typedef void (*FN_CB_DROPFILES)(wchar_t *);
|
||||
|
||||
void hl_kinc_register_dropfiles(vclosure *dropFiles) {
|
||||
// todo: string convert
|
||||
// kinc_set_drop_files_callback(*((FN_CB_DROPFILES*)(&dropFiles->fun)));
|
||||
}
|
||||
|
||||
typedef char *(*FN_CB_COPY)(void *);
|
||||
typedef char *(*FN_CB_CUT)(void *);
|
||||
typedef void (*FN_CB_PASTE)(char *, void *);
|
||||
|
||||
void hl_kinc_register_copycutpaste(vclosure *copy, vclosure *cut, vclosure *paste) {
|
||||
kinc_set_copy_callback(*((FN_CB_COPY *)(©->fun)), NULL);
|
||||
kinc_set_cut_callback(*((FN_CB_CUT *)(&cut->fun)), NULL);
|
||||
kinc_set_paste_callback(*((FN_CB_PASTE *)(&paste->fun)), NULL);
|
||||
}
|
||||
|
||||
const char *hl_kinc_video_format(void) {
|
||||
return kinc_video_formats()[0];
|
||||
}
|
||||
#include <kinc/input/acceleration.h>
|
||||
#include <kinc/input/gamepad.h>
|
||||
#include <kinc/input/keyboard.h>
|
||||
#include <kinc/input/mouse.h>
|
||||
#include <kinc/input/pen.h>
|
||||
#include <kinc/input/rotation.h>
|
||||
#include <kinc/input/surface.h>
|
||||
#include <kinc/log.h>
|
||||
#include <kinc/system.h>
|
||||
#include <kinc/video.h>
|
||||
#include <kinc/window.h>
|
||||
|
||||
#include <hl.h>
|
||||
|
||||
void hl_kinc_log(vbyte *v) {
|
||||
kinc_log(KINC_LOG_LEVEL_INFO, (char *)v);
|
||||
}
|
||||
|
||||
double hl_kinc_get_time(void) {
|
||||
return kinc_time();
|
||||
}
|
||||
|
||||
int hl_kinc_get_window_width(int window) {
|
||||
return kinc_window_width(window);
|
||||
}
|
||||
|
||||
int hl_kinc_get_window_height(int window) {
|
||||
return kinc_window_height(window);
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_get_system_id(void) {
|
||||
return (vbyte *)kinc_system_id();
|
||||
}
|
||||
|
||||
void hl_kinc_vibrate(int ms) {
|
||||
kinc_vibrate(ms);
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_get_language(void) {
|
||||
return (vbyte *)kinc_language();
|
||||
}
|
||||
|
||||
void hl_kinc_request_shutdown(void) {
|
||||
kinc_stop();
|
||||
}
|
||||
|
||||
void hl_kinc_mouse_lock(int windowId) {
|
||||
kinc_mouse_lock(windowId);
|
||||
}
|
||||
|
||||
void hl_kinc_mouse_unlock(void) {
|
||||
kinc_mouse_unlock();
|
||||
}
|
||||
|
||||
bool hl_kinc_can_lock_mouse(void) {
|
||||
return kinc_mouse_can_lock();
|
||||
}
|
||||
|
||||
bool hl_kinc_is_mouse_locked(void) {
|
||||
return kinc_mouse_is_locked();
|
||||
}
|
||||
|
||||
void hl_kinc_show_mouse(bool show) {
|
||||
if (show) {
|
||||
kinc_mouse_show();
|
||||
}
|
||||
else {
|
||||
kinc_mouse_hide();
|
||||
}
|
||||
}
|
||||
|
||||
bool hl_kinc_system_is_fullscreen(void) {
|
||||
return false; // kinc_is_fullscreen();
|
||||
}
|
||||
|
||||
void hl_kinc_system_request_fullscreen(void) {
|
||||
// kinc_change_resolution(display_width(), display_height(), true);
|
||||
}
|
||||
|
||||
void hl_kinc_system_exit_fullscreen(int previousWidth, int previousHeight) {
|
||||
// kinc_change_resolution(previousWidth, previousHeight, false);
|
||||
}
|
||||
|
||||
void hl_kinc_system_change_resolution(int width, int height) {
|
||||
// kinc_change_resolution(width, height, false);
|
||||
}
|
||||
|
||||
void hl_kinc_system_set_keepscreenon(bool on) {
|
||||
kinc_set_keep_screen_on(on);
|
||||
}
|
||||
|
||||
void hl_kinc_system_load_url(vbyte *url) {
|
||||
kinc_load_url((char *)url);
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_get_gamepad_id(int index) {
|
||||
return (vbyte *)kinc_gamepad_product_name(index);
|
||||
}
|
||||
|
||||
vbyte *hl_kinc_get_gamepad_vendor(int index) {
|
||||
return (vbyte *)kinc_gamepad_vendor(index);
|
||||
}
|
||||
|
||||
bool hl_kinc_gamepad_connected(int index) {
|
||||
return kinc_gamepad_connected(index);
|
||||
}
|
||||
|
||||
typedef void (*FN_KEY_DOWN)(int, void *);
|
||||
typedef void (*FN_KEY_UP)(int, void *);
|
||||
typedef void (*FN_KEY_PRESS)(unsigned int, void *);
|
||||
|
||||
void hl_kinc_register_keyboard(vclosure *keyDown, vclosure *keyUp, vclosure *keyPress) {
|
||||
kinc_keyboard_set_key_down_callback(*((FN_KEY_DOWN *)(&keyDown->fun)), NULL);
|
||||
kinc_keyboard_set_key_up_callback(*((FN_KEY_UP *)(&keyUp->fun)), NULL);
|
||||
kinc_keyboard_set_key_press_callback(*((FN_KEY_PRESS *)(&keyPress->fun)), NULL);
|
||||
}
|
||||
|
||||
typedef void (*FN_MOUSE_DOWN)(int, int, int, int, void *);
|
||||
typedef void (*FN_MOUSE_UP)(int, int, int, int, void *);
|
||||
typedef void (*FN_MOUSE_MOVE)(int, int, int, int, int, void *);
|
||||
typedef void (*FN_MOUSE_WHEEL)(int, int, void *);
|
||||
|
||||
void hl_kinc_register_mouse(vclosure *mouseDown, vclosure *mouseUp, vclosure *mouseMove, vclosure *mouseWheel) {
|
||||
kinc_mouse_set_press_callback(*((FN_MOUSE_DOWN *)(&mouseDown->fun)), NULL);
|
||||
kinc_mouse_set_release_callback(*((FN_MOUSE_UP *)(&mouseUp->fun)), NULL);
|
||||
kinc_mouse_set_move_callback(*((FN_MOUSE_MOVE *)(&mouseMove->fun)), NULL);
|
||||
kinc_mouse_set_scroll_callback(*((FN_MOUSE_WHEEL *)(&mouseWheel->fun)), NULL);
|
||||
}
|
||||
|
||||
typedef void (*FN_PEN_DOWN)(int, int, int, float);
|
||||
typedef void (*FN_PEN_UP)(int, int, int, float);
|
||||
typedef void (*FN_PEN_MOVE)(int, int, int, float);
|
||||
|
||||
void hl_kinc_register_pen(vclosure *penDown, vclosure *penUp, vclosure *penMove) {
|
||||
kinc_pen_set_press_callback(*((FN_PEN_DOWN *)(&penDown->fun)));
|
||||
kinc_pen_set_release_callback(*((FN_PEN_UP *)(&penUp->fun)));
|
||||
kinc_pen_set_move_callback(*((FN_PEN_MOVE *)(&penMove->fun)));
|
||||
}
|
||||
|
||||
typedef void (*FN_GAMEPAD_AXIS)(int, int, float, void *);
|
||||
typedef void (*FN_GAMEPAD_BUTTON)(int, int, float, void *);
|
||||
|
||||
void hl_kinc_register_gamepad(vclosure *gamepadAxis, vclosure *gamepadButton) {
|
||||
kinc_gamepad_set_axis_callback(*((FN_GAMEPAD_AXIS *)(&gamepadAxis->fun)), NULL);
|
||||
kinc_gamepad_set_button_callback(*((FN_GAMEPAD_BUTTON *)(&gamepadButton->fun)), NULL);
|
||||
}
|
||||
|
||||
typedef void (*FN_TOUCH_START)(int, int, int);
|
||||
typedef void (*FN_TOUCH_END)(int, int, int);
|
||||
typedef void (*FN_TOUCH_MOVE)(int, int, int);
|
||||
|
||||
void hl_kinc_register_surface(vclosure *touchStart, vclosure *touchEnd, vclosure *touchMove) {
|
||||
kinc_surface_set_touch_start_callback(*((FN_TOUCH_START *)(&touchStart->fun)));
|
||||
kinc_surface_set_touch_end_callback(*((FN_TOUCH_END *)(&touchEnd->fun)));
|
||||
kinc_surface_set_move_callback(*((FN_TOUCH_MOVE *)(&touchMove->fun)));
|
||||
}
|
||||
|
||||
typedef void (*FN_SENSOR_ACCELEROMETER)(float, float, float);
|
||||
typedef void (*FN_SENSOR_GYROSCOPE)(float, float, float);
|
||||
|
||||
void hl_kinc_register_sensor(vclosure *accelerometerChanged, vclosure *gyroscopeChanged) {
|
||||
kinc_acceleration_set_callback(*((FN_SENSOR_ACCELEROMETER *)(&accelerometerChanged->fun)));
|
||||
kinc_rotation_set_callback(*((FN_SENSOR_GYROSCOPE *)(&gyroscopeChanged->fun)));
|
||||
}
|
||||
|
||||
// typedef void(*FN_CB_ORIENTATION)(int);
|
||||
typedef void (*FN_CB_FOREGROUND)(void *);
|
||||
typedef void (*FN_CB_RESUME)(void *);
|
||||
typedef void (*FN_CB_PAUSE)(void *);
|
||||
typedef void (*FN_CB_BACKGROUND)(void *);
|
||||
typedef void (*FN_CB_SHUTDOWN)(void *);
|
||||
|
||||
void hl_kinc_register_callbacks(vclosure *foreground, vclosure *resume, vclosure *pause, vclosure *background, vclosure *shutdown) {
|
||||
// kinc_set_orientation_callback(orientation);
|
||||
kinc_set_foreground_callback(*((FN_CB_FOREGROUND *)(&foreground->fun)), NULL);
|
||||
kinc_set_resume_callback(*((FN_CB_RESUME *)(&resume->fun)), NULL);
|
||||
kinc_set_pause_callback(*((FN_CB_PAUSE *)(&pause->fun)), NULL);
|
||||
kinc_set_background_callback(*((FN_CB_BACKGROUND *)(&background->fun)), NULL);
|
||||
kinc_set_shutdown_callback(*((FN_CB_SHUTDOWN *)(&shutdown->fun)), NULL);
|
||||
}
|
||||
|
||||
typedef void (*FN_CB_DROPFILES)(wchar_t *);
|
||||
|
||||
void hl_kinc_register_dropfiles(vclosure *dropFiles) {
|
||||
// todo: string convert
|
||||
// kinc_set_drop_files_callback(*((FN_CB_DROPFILES*)(&dropFiles->fun)));
|
||||
}
|
||||
|
||||
typedef char *(*FN_CB_COPY)(void *);
|
||||
typedef char *(*FN_CB_CUT)(void *);
|
||||
typedef void (*FN_CB_PASTE)(char *, void *);
|
||||
|
||||
void hl_kinc_register_copycutpaste(vclosure *copy, vclosure *cut, vclosure *paste) {
|
||||
kinc_set_copy_callback(*((FN_CB_COPY *)(©->fun)), NULL);
|
||||
kinc_set_cut_callback(*((FN_CB_CUT *)(&cut->fun)), NULL);
|
||||
kinc_set_paste_callback(*((FN_CB_PASTE *)(&paste->fun)), NULL);
|
||||
}
|
||||
|
||||
const char *hl_kinc_video_format(void) {
|
||||
return kinc_video_formats()[0];
|
||||
}
|
||||
|
@ -80,6 +80,7 @@ extern class Krom {
|
||||
static function unloadImage(image: kha.Image): Void;
|
||||
static function loadSound(file: String): Dynamic;
|
||||
static function writeAudioBuffer(buffer: js.lib.ArrayBuffer, samples: Int): Void;
|
||||
static function getSamplesPerSecond(): Int;
|
||||
static function loadBlob(file: String): js.lib.ArrayBuffer;
|
||||
|
||||
static function init(title: String, width: Int, height: Int, samplesPerPixel: Int, vSync: Bool, windowMode: Int, windowFeatures: Int, kromApi: Int): Void;
|
||||
@ -115,6 +116,7 @@ extern class Krom {
|
||||
static function screenDpi(): Int;
|
||||
static function systemId(): String;
|
||||
static function requestShutdown(): Void;
|
||||
static function displayFrequency(): Int;
|
||||
static function displayCount(): Int;
|
||||
static function displayWidth(index: Int): Int;
|
||||
static function displayHeight(index: Int): Int;
|
||||
|
@ -79,7 +79,7 @@ class Display {
|
||||
public var frequency(get, never): Int;
|
||||
|
||||
function get_frequency(): Int {
|
||||
return 60;
|
||||
return Krom.displayFrequency();
|
||||
}
|
||||
|
||||
public var pixelsPerInch(get, never): Int;
|
||||
|
@ -1,343 +1,344 @@
|
||||
package kha;
|
||||
|
||||
import kha.graphics4.TextureFormat;
|
||||
import kha.input.Gamepad;
|
||||
import kha.input.Keyboard;
|
||||
import kha.input.Mouse;
|
||||
import kha.input.MouseImpl;
|
||||
import kha.input.Pen;
|
||||
import kha.input.Surface;
|
||||
import kha.System;
|
||||
import haxe.ds.Vector;
|
||||
|
||||
class SystemImpl {
|
||||
static var start: Float;
|
||||
static var framebuffer: Framebuffer;
|
||||
static var keyboard: Keyboard;
|
||||
static var mouse: Mouse;
|
||||
static var pen: Pen;
|
||||
static var maxGamepads: Int = 4;
|
||||
static var gamepads: Array<Gamepad>;
|
||||
static var mouseLockListeners: Array<Void->Void> = [];
|
||||
|
||||
static function renderCallback(): Void {
|
||||
Scheduler.executeFrame();
|
||||
System.render([framebuffer]);
|
||||
}
|
||||
|
||||
static function dropFilesCallback(filePath: String): Void {
|
||||
System.dropFiles(filePath);
|
||||
}
|
||||
|
||||
static function copyCallback(): String {
|
||||
if (System.copyListener != null) {
|
||||
return System.copyListener();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static function cutCallback(): String {
|
||||
if (System.cutListener != null) {
|
||||
return System.cutListener();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static function pasteCallback(data: String): Void {
|
||||
if (System.pasteListener != null) {
|
||||
System.pasteListener(data);
|
||||
}
|
||||
}
|
||||
|
||||
static function foregroundCallback(): Void {
|
||||
System.foreground();
|
||||
}
|
||||
|
||||
static function resumeCallback(): Void {
|
||||
System.resume();
|
||||
}
|
||||
|
||||
static function pauseCallback(): Void {
|
||||
System.pause();
|
||||
}
|
||||
|
||||
static function backgroundCallback(): Void {
|
||||
System.background();
|
||||
}
|
||||
|
||||
static function shutdownCallback(): Void {
|
||||
System.shutdown();
|
||||
}
|
||||
|
||||
static function keyboardDownCallback(code: Int): Void {
|
||||
keyboard.sendDownEvent(cast code);
|
||||
}
|
||||
|
||||
static function keyboardUpCallback(code: Int): Void {
|
||||
keyboard.sendUpEvent(cast code);
|
||||
}
|
||||
|
||||
static function keyboardPressCallback(charCode: Int): Void {
|
||||
keyboard.sendPressEvent(String.fromCharCode(charCode));
|
||||
}
|
||||
|
||||
static function mouseDownCallback(button: Int, x: Int, y: Int): Void {
|
||||
mouse.sendDownEvent(0, button, x, y);
|
||||
}
|
||||
|
||||
static function mouseUpCallback(button: Int, x: Int, y: Int): Void {
|
||||
mouse.sendUpEvent(0, button, x, y);
|
||||
}
|
||||
|
||||
static function mouseMoveCallback(x: Int, y: Int, mx: Int, my: Int): Void {
|
||||
mouse.sendMoveEvent(0, x, y, mx, my);
|
||||
}
|
||||
|
||||
static function mouseWheelCallback(delta: Int): Void {
|
||||
mouse.sendWheelEvent(0, delta);
|
||||
}
|
||||
|
||||
static function penDownCallback(x: Int, y: Int, pressure: Float): Void {
|
||||
pen.sendDownEvent(0, x, y, pressure);
|
||||
}
|
||||
|
||||
static function penUpCallback(x: Int, y: Int, pressure: Float): Void {
|
||||
pen.sendUpEvent(0, x, y, pressure);
|
||||
}
|
||||
|
||||
static function penMoveCallback(x: Int, y: Int, pressure: Float): Void {
|
||||
pen.sendMoveEvent(0, x, y, pressure);
|
||||
}
|
||||
|
||||
static function gamepadAxisCallback(gamepad: Int, axis: Int, value: Float): Void {
|
||||
gamepads[gamepad].sendAxisEvent(axis, value);
|
||||
}
|
||||
|
||||
static function gamepadButtonCallback(gamepad: Int, button: Int, value: Float): Void {
|
||||
gamepads[gamepad].sendButtonEvent(button, value);
|
||||
}
|
||||
|
||||
static function audioCallback(samples: Int): Void {
|
||||
kha.audio2.Audio._callCallback(samples);
|
||||
var buffer = @:privateAccess kha.audio2.Audio.buffer;
|
||||
Krom.writeAudioBuffer(buffer.data.buffer, samples);
|
||||
}
|
||||
|
||||
public static function init(options: SystemOptions, callback: Window->Void): Void {
|
||||
Krom.init(options.title, options.width, options.height, options.framebuffer.samplesPerPixel, options.framebuffer.verticalSync,
|
||||
cast options.window.mode, options.window.windowFeatures, Krom.KROM_API);
|
||||
|
||||
start = Krom.getTime();
|
||||
|
||||
haxe.Log.trace = function(v: Dynamic, ?infos: haxe.PosInfos) {
|
||||
var message = haxe.Log.formatOutput(v, infos);
|
||||
Krom.log(message);
|
||||
};
|
||||
|
||||
new Window(0);
|
||||
Scheduler.init();
|
||||
Shaders.init();
|
||||
|
||||
var g4 = new kha.krom.Graphics();
|
||||
framebuffer = new Framebuffer(0, null, null, g4);
|
||||
framebuffer.init(new kha.graphics2.Graphics1(framebuffer), new kha.graphics4.Graphics2(framebuffer), g4);
|
||||
Krom.setCallback(renderCallback);
|
||||
Krom.setDropFilesCallback(dropFilesCallback);
|
||||
Krom.setCutCopyPasteCallback(cutCallback, copyCallback, pasteCallback);
|
||||
Krom.setApplicationStateCallback(foregroundCallback, resumeCallback, pauseCallback, backgroundCallback, shutdownCallback);
|
||||
|
||||
keyboard = new Keyboard();
|
||||
mouse = new MouseImpl();
|
||||
pen = new Pen();
|
||||
gamepads = new Array<Gamepad>();
|
||||
for (i in 0...maxGamepads) {
|
||||
gamepads[i] = new Gamepad(i);
|
||||
}
|
||||
|
||||
Krom.setKeyboardDownCallback(keyboardDownCallback);
|
||||
Krom.setKeyboardUpCallback(keyboardUpCallback);
|
||||
Krom.setKeyboardPressCallback(keyboardPressCallback);
|
||||
Krom.setMouseDownCallback(mouseDownCallback);
|
||||
Krom.setMouseUpCallback(mouseUpCallback);
|
||||
Krom.setMouseMoveCallback(mouseMoveCallback);
|
||||
Krom.setMouseWheelCallback(mouseWheelCallback);
|
||||
Krom.setPenDownCallback(penDownCallback);
|
||||
Krom.setPenUpCallback(penUpCallback);
|
||||
Krom.setPenMoveCallback(penMoveCallback);
|
||||
Krom.setGamepadAxisCallback(gamepadAxisCallback);
|
||||
Krom.setGamepadButtonCallback(gamepadButtonCallback);
|
||||
|
||||
kha.audio2.Audio._init();
|
||||
kha.audio1.Audio._init();
|
||||
Krom.setAudioCallback(audioCallback);
|
||||
|
||||
Scheduler.start();
|
||||
|
||||
callback(Window.get(0));
|
||||
}
|
||||
|
||||
public static function initEx(title: String, options: Array<WindowOptions>, windowCallback: Int->Void, callback: Void->Void): Void {}
|
||||
|
||||
static function translateWindowMode(value: Null<WindowMode>): Int {
|
||||
if (value == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return switch (value) {
|
||||
case Windowed: 0;
|
||||
case Fullscreen: 1;
|
||||
case ExclusiveFullscreen: 2;
|
||||
}
|
||||
}
|
||||
|
||||
public static function getScreenRotation(): ScreenRotation {
|
||||
return ScreenRotation.RotationNone;
|
||||
}
|
||||
|
||||
public static function getTime(): Float {
|
||||
return Krom.getTime() - start;
|
||||
}
|
||||
|
||||
public static function getVsync(): Bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function getRefreshRate(): Int {
|
||||
return 60;
|
||||
}
|
||||
|
||||
public static function getSystemId(): String {
|
||||
return Krom.systemId();
|
||||
}
|
||||
|
||||
public static function vibrate(ms: Int): Void {
|
||||
// TODO: Implement
|
||||
}
|
||||
|
||||
public static function getLanguage(): String {
|
||||
return "en"; // TODO: Implement
|
||||
}
|
||||
|
||||
public static function requestShutdown(): Bool {
|
||||
Krom.requestShutdown();
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function getMouse(num: Int): Mouse {
|
||||
return mouse;
|
||||
}
|
||||
|
||||
public static function getPen(num: Int): Pen {
|
||||
return pen;
|
||||
}
|
||||
|
||||
public static function getKeyboard(num: Int): Keyboard {
|
||||
return keyboard;
|
||||
}
|
||||
|
||||
public static function lockMouse(): Void {
|
||||
if (!isMouseLocked()) {
|
||||
Krom.lockMouse();
|
||||
for (listener in mouseLockListeners) {
|
||||
listener();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function unlockMouse(): Void {
|
||||
if (isMouseLocked()) {
|
||||
Krom.unlockMouse();
|
||||
for (listener in mouseLockListeners) {
|
||||
listener();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function canLockMouse(): Bool {
|
||||
return Krom.canLockMouse();
|
||||
}
|
||||
|
||||
public static function isMouseLocked(): Bool {
|
||||
return Krom.isMouseLocked();
|
||||
}
|
||||
|
||||
public static function notifyOfMouseLockChange(func: Void->Void, error: Void->Void): Void {
|
||||
if (canLockMouse() && func != null) {
|
||||
mouseLockListeners.push(func);
|
||||
}
|
||||
}
|
||||
|
||||
public static function removeFromMouseLockChange(func: Void->Void, error: Void->Void): Void {
|
||||
if (canLockMouse() && func != null) {
|
||||
mouseLockListeners.remove(func);
|
||||
}
|
||||
}
|
||||
|
||||
public static function hideSystemCursor(): Void {
|
||||
Krom.showMouse(false);
|
||||
}
|
||||
|
||||
public static function showSystemCursor(): Void {
|
||||
Krom.showMouse(true);
|
||||
}
|
||||
|
||||
static function unload(): Void {}
|
||||
|
||||
public static function canSwitchFullscreen(): Bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function isFullscreen(): Bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function requestFullscreen(): Void {}
|
||||
|
||||
public static function exitFullscreen(): Void {}
|
||||
|
||||
public static function notifyOfFullscreenChange(func: Void->Void, error: Void->Void): Void {}
|
||||
|
||||
public static function removeFromFullscreenChange(func: Void->Void, error: Void->Void): Void {}
|
||||
|
||||
public static function changeResolution(width: Int, height: Int): Void {}
|
||||
|
||||
public static function setKeepScreenOn(on: Bool): Void {}
|
||||
|
||||
public static function loadUrl(url: String): Void {}
|
||||
|
||||
public static function getGamepadId(index: Int): String {
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
public static function getGamepadVendor(index: Int): String {
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
public static function setGamepadRumble(index: Int, leftAmount: Float, rightAmount: Float): Void {}
|
||||
|
||||
public static function safeZone(): Float {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
public static function login(): Void {}
|
||||
|
||||
public static function automaticSafeZone(): Bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function setSafeZone(value: Float): Void {}
|
||||
|
||||
public static function unlockAchievement(id: Int): Void {}
|
||||
|
||||
public static function waitingForLogin(): Bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function disallowUserChange(): Void {}
|
||||
|
||||
public static function allowUserChange(): Void {}
|
||||
}
|
||||
package kha;
|
||||
|
||||
import kha.graphics4.TextureFormat;
|
||||
import kha.input.Gamepad;
|
||||
import kha.input.Keyboard;
|
||||
import kha.input.Mouse;
|
||||
import kha.input.MouseImpl;
|
||||
import kha.input.Pen;
|
||||
import kha.input.Surface;
|
||||
import kha.System;
|
||||
import haxe.ds.Vector;
|
||||
|
||||
class SystemImpl {
|
||||
static var start: Float;
|
||||
static var framebuffer: Framebuffer;
|
||||
static var keyboard: Keyboard;
|
||||
static var mouse: Mouse;
|
||||
static var pen: Pen;
|
||||
static var maxGamepads: Int = 4;
|
||||
static var gamepads: Array<Gamepad>;
|
||||
static var mouseLockListeners: Array<Void->Void> = [];
|
||||
|
||||
static function renderCallback(): Void {
|
||||
Scheduler.executeFrame();
|
||||
System.render([framebuffer]);
|
||||
}
|
||||
|
||||
static function dropFilesCallback(filePath: String): Void {
|
||||
System.dropFiles(filePath);
|
||||
}
|
||||
|
||||
static function copyCallback(): String {
|
||||
if (System.copyListener != null) {
|
||||
return System.copyListener();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static function cutCallback(): String {
|
||||
if (System.cutListener != null) {
|
||||
return System.cutListener();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static function pasteCallback(data: String): Void {
|
||||
if (System.pasteListener != null) {
|
||||
System.pasteListener(data);
|
||||
}
|
||||
}
|
||||
|
||||
static function foregroundCallback(): Void {
|
||||
System.foreground();
|
||||
}
|
||||
|
||||
static function resumeCallback(): Void {
|
||||
System.resume();
|
||||
}
|
||||
|
||||
static function pauseCallback(): Void {
|
||||
System.pause();
|
||||
}
|
||||
|
||||
static function backgroundCallback(): Void {
|
||||
System.background();
|
||||
}
|
||||
|
||||
static function shutdownCallback(): Void {
|
||||
System.shutdown();
|
||||
}
|
||||
|
||||
static function keyboardDownCallback(code: Int): Void {
|
||||
keyboard.sendDownEvent(cast code);
|
||||
}
|
||||
|
||||
static function keyboardUpCallback(code: Int): Void {
|
||||
keyboard.sendUpEvent(cast code);
|
||||
}
|
||||
|
||||
static function keyboardPressCallback(charCode: Int): Void {
|
||||
keyboard.sendPressEvent(String.fromCharCode(charCode));
|
||||
}
|
||||
|
||||
static function mouseDownCallback(button: Int, x: Int, y: Int): Void {
|
||||
mouse.sendDownEvent(0, button, x, y);
|
||||
}
|
||||
|
||||
static function mouseUpCallback(button: Int, x: Int, y: Int): Void {
|
||||
mouse.sendUpEvent(0, button, x, y);
|
||||
}
|
||||
|
||||
static function mouseMoveCallback(x: Int, y: Int, mx: Int, my: Int): Void {
|
||||
mouse.sendMoveEvent(0, x, y, mx, my);
|
||||
}
|
||||
|
||||
static function mouseWheelCallback(delta: Int): Void {
|
||||
mouse.sendWheelEvent(0, delta);
|
||||
}
|
||||
|
||||
static function penDownCallback(x: Int, y: Int, pressure: Float): Void {
|
||||
pen.sendDownEvent(0, x, y, pressure);
|
||||
}
|
||||
|
||||
static function penUpCallback(x: Int, y: Int, pressure: Float): Void {
|
||||
pen.sendUpEvent(0, x, y, pressure);
|
||||
}
|
||||
|
||||
static function penMoveCallback(x: Int, y: Int, pressure: Float): Void {
|
||||
pen.sendMoveEvent(0, x, y, pressure);
|
||||
}
|
||||
|
||||
static function gamepadAxisCallback(gamepad: Int, axis: Int, value: Float): Void {
|
||||
gamepads[gamepad].sendAxisEvent(axis, value);
|
||||
}
|
||||
|
||||
static function gamepadButtonCallback(gamepad: Int, button: Int, value: Float): Void {
|
||||
gamepads[gamepad].sendButtonEvent(button, value);
|
||||
}
|
||||
|
||||
static function audioCallback(samples: Int): Void {
|
||||
kha.audio2.Audio._callCallback(samples);
|
||||
var buffer = @:privateAccess kha.audio2.Audio.buffer;
|
||||
Krom.writeAudioBuffer(buffer.data.buffer, samples);
|
||||
}
|
||||
|
||||
public static function init(options: SystemOptions, callback: Window->Void): Void {
|
||||
Krom.init(options.title, options.width, options.height, options.framebuffer.samplesPerPixel, options.framebuffer.verticalSync,
|
||||
cast options.window.mode, options.window.windowFeatures, Krom.KROM_API);
|
||||
|
||||
start = Krom.getTime();
|
||||
|
||||
haxe.Log.trace = function(v: Dynamic, ?infos: haxe.PosInfos) {
|
||||
var message = haxe.Log.formatOutput(v, infos);
|
||||
Krom.log(message);
|
||||
};
|
||||
|
||||
new Window(0);
|
||||
Scheduler.init();
|
||||
Shaders.init();
|
||||
|
||||
var g4 = new kha.krom.Graphics();
|
||||
framebuffer = new Framebuffer(0, null, null, g4);
|
||||
framebuffer.init(new kha.graphics2.Graphics1(framebuffer), new kha.graphics4.Graphics2(framebuffer), g4);
|
||||
Krom.setCallback(renderCallback);
|
||||
Krom.setDropFilesCallback(dropFilesCallback);
|
||||
Krom.setCutCopyPasteCallback(cutCallback, copyCallback, pasteCallback);
|
||||
Krom.setApplicationStateCallback(foregroundCallback, resumeCallback, pauseCallback, backgroundCallback, shutdownCallback);
|
||||
|
||||
keyboard = new Keyboard();
|
||||
mouse = new MouseImpl();
|
||||
pen = new Pen();
|
||||
gamepads = new Array<Gamepad>();
|
||||
for (i in 0...maxGamepads) {
|
||||
gamepads[i] = new Gamepad(i);
|
||||
}
|
||||
|
||||
Krom.setKeyboardDownCallback(keyboardDownCallback);
|
||||
Krom.setKeyboardUpCallback(keyboardUpCallback);
|
||||
Krom.setKeyboardPressCallback(keyboardPressCallback);
|
||||
Krom.setMouseDownCallback(mouseDownCallback);
|
||||
Krom.setMouseUpCallback(mouseUpCallback);
|
||||
Krom.setMouseMoveCallback(mouseMoveCallback);
|
||||
Krom.setMouseWheelCallback(mouseWheelCallback);
|
||||
Krom.setPenDownCallback(penDownCallback);
|
||||
Krom.setPenUpCallback(penUpCallback);
|
||||
Krom.setPenMoveCallback(penMoveCallback);
|
||||
Krom.setGamepadAxisCallback(gamepadAxisCallback);
|
||||
Krom.setGamepadButtonCallback(gamepadButtonCallback);
|
||||
|
||||
kha.audio2.Audio.samplesPerSecond = Krom.getSamplesPerSecond();
|
||||
kha.audio1.Audio._init();
|
||||
kha.audio2.Audio._init();
|
||||
Krom.setAudioCallback(audioCallback);
|
||||
|
||||
Scheduler.start();
|
||||
|
||||
callback(Window.get(0));
|
||||
}
|
||||
|
||||
public static function initEx(title: String, options: Array<WindowOptions>, windowCallback: Int->Void, callback: Void->Void): Void {}
|
||||
|
||||
static function translateWindowMode(value: Null<WindowMode>): Int {
|
||||
if (value == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return switch (value) {
|
||||
case Windowed: 0;
|
||||
case Fullscreen: 1;
|
||||
case ExclusiveFullscreen: 2;
|
||||
}
|
||||
}
|
||||
|
||||
public static function getScreenRotation(): ScreenRotation {
|
||||
return ScreenRotation.RotationNone;
|
||||
}
|
||||
|
||||
public static function getTime(): Float {
|
||||
return Krom.getTime() - start;
|
||||
}
|
||||
|
||||
public static function getVsync(): Bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function getRefreshRate(): Int {
|
||||
return Krom.displayFrequency();
|
||||
}
|
||||
|
||||
public static function getSystemId(): String {
|
||||
return Krom.systemId();
|
||||
}
|
||||
|
||||
public static function vibrate(ms: Int): Void {
|
||||
// TODO: Implement
|
||||
}
|
||||
|
||||
public static function getLanguage(): String {
|
||||
return "en"; // TODO: Implement
|
||||
}
|
||||
|
||||
public static function requestShutdown(): Bool {
|
||||
Krom.requestShutdown();
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function getMouse(num: Int): Mouse {
|
||||
return mouse;
|
||||
}
|
||||
|
||||
public static function getPen(num: Int): Pen {
|
||||
return pen;
|
||||
}
|
||||
|
||||
public static function getKeyboard(num: Int): Keyboard {
|
||||
return keyboard;
|
||||
}
|
||||
|
||||
public static function lockMouse(): Void {
|
||||
if (!isMouseLocked()) {
|
||||
Krom.lockMouse();
|
||||
for (listener in mouseLockListeners) {
|
||||
listener();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function unlockMouse(): Void {
|
||||
if (isMouseLocked()) {
|
||||
Krom.unlockMouse();
|
||||
for (listener in mouseLockListeners) {
|
||||
listener();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function canLockMouse(): Bool {
|
||||
return Krom.canLockMouse();
|
||||
}
|
||||
|
||||
public static function isMouseLocked(): Bool {
|
||||
return Krom.isMouseLocked();
|
||||
}
|
||||
|
||||
public static function notifyOfMouseLockChange(func: Void->Void, error: Void->Void): Void {
|
||||
if (canLockMouse() && func != null) {
|
||||
mouseLockListeners.push(func);
|
||||
}
|
||||
}
|
||||
|
||||
public static function removeFromMouseLockChange(func: Void->Void, error: Void->Void): Void {
|
||||
if (canLockMouse() && func != null) {
|
||||
mouseLockListeners.remove(func);
|
||||
}
|
||||
}
|
||||
|
||||
public static function hideSystemCursor(): Void {
|
||||
Krom.showMouse(false);
|
||||
}
|
||||
|
||||
public static function showSystemCursor(): Void {
|
||||
Krom.showMouse(true);
|
||||
}
|
||||
|
||||
static function unload(): Void {}
|
||||
|
||||
public static function canSwitchFullscreen(): Bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function isFullscreen(): Bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function requestFullscreen(): Void {}
|
||||
|
||||
public static function exitFullscreen(): Void {}
|
||||
|
||||
public static function notifyOfFullscreenChange(func: Void->Void, error: Void->Void): Void {}
|
||||
|
||||
public static function removeFromFullscreenChange(func: Void->Void, error: Void->Void): Void {}
|
||||
|
||||
public static function changeResolution(width: Int, height: Int): Void {}
|
||||
|
||||
public static function setKeepScreenOn(on: Bool): Void {}
|
||||
|
||||
public static function loadUrl(url: String): Void {}
|
||||
|
||||
public static function getGamepadId(index: Int): String {
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
public static function getGamepadVendor(index: Int): String {
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
public static function setGamepadRumble(index: Int, leftAmount: Float, rightAmount: Float): Void {}
|
||||
|
||||
public static function safeZone(): Float {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
public static function login(): Void {}
|
||||
|
||||
public static function automaticSafeZone(): Bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function setSafeZone(value: Float): Void {}
|
||||
|
||||
public static function unlockAchievement(id: Int): Void {}
|
||||
|
||||
public static function waitingForLogin(): Bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function disallowUserChange(): Void {}
|
||||
|
||||
public static function allowUserChange(): Void {}
|
||||
}
|
||||
|
@ -1,57 +1,56 @@
|
||||
package kha.audio2;
|
||||
|
||||
import kha.Sound;
|
||||
import kha.internal.IntBox;
|
||||
|
||||
class Audio {
|
||||
public static var disableGcInteractions = false;
|
||||
static var intBox: IntBox = new IntBox(0);
|
||||
static var buffer: Buffer;
|
||||
|
||||
public static function _init() {
|
||||
var bufferSize = 1024 * 2;
|
||||
buffer = new Buffer(bufferSize * 4, 2, 44100);
|
||||
Audio.samplesPerSecond = 44100;
|
||||
}
|
||||
|
||||
public static function _callCallback(samples: Int): Void {
|
||||
if (buffer == null)
|
||||
return;
|
||||
if (audioCallback != null) {
|
||||
intBox.value = samples;
|
||||
audioCallback(intBox, buffer);
|
||||
}
|
||||
else {
|
||||
for (i in 0...samples) {
|
||||
buffer.data.set(buffer.writeLocation, 0);
|
||||
buffer.writeLocation += 1;
|
||||
if (buffer.writeLocation >= buffer.size) {
|
||||
buffer.writeLocation = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function _readSample(): Float {
|
||||
if (buffer == null)
|
||||
return 0;
|
||||
var value = buffer.data.get(buffer.readLocation);
|
||||
buffer.readLocation += 1;
|
||||
if (buffer.readLocation >= buffer.size) {
|
||||
buffer.readLocation = 0;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public static var samplesPerSecond: Int;
|
||||
|
||||
public static var audioCallback: IntBox->Buffer->Void;
|
||||
|
||||
public static function play(sound: Sound, loop: Bool = false): kha.audio1.AudioChannel {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function stream(sound: Sound, loop: Bool = false): kha.audio1.AudioChannel {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
package kha.audio2;
|
||||
|
||||
import kha.Sound;
|
||||
import kha.internal.IntBox;
|
||||
|
||||
class Audio {
|
||||
public static var disableGcInteractions = false;
|
||||
static var intBox: IntBox = new IntBox(0);
|
||||
static var buffer: Buffer;
|
||||
|
||||
public static function _init() {
|
||||
var bufferSize = 1024 * 2;
|
||||
buffer = new Buffer(bufferSize * 4, 2, samplesPerSecond);
|
||||
}
|
||||
|
||||
public static function _callCallback(samples: Int): Void {
|
||||
if (buffer == null)
|
||||
return;
|
||||
if (audioCallback != null) {
|
||||
intBox.value = samples;
|
||||
audioCallback(intBox, buffer);
|
||||
}
|
||||
else {
|
||||
for (i in 0...samples) {
|
||||
buffer.data.set(buffer.writeLocation, 0);
|
||||
buffer.writeLocation += 1;
|
||||
if (buffer.writeLocation >= buffer.size) {
|
||||
buffer.writeLocation = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function _readSample(): FastFloat {
|
||||
if (buffer == null)
|
||||
return 0;
|
||||
var value = buffer.data.get(buffer.readLocation);
|
||||
++buffer.readLocation;
|
||||
if (buffer.readLocation >= buffer.size) {
|
||||
buffer.readLocation = 0;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public static var samplesPerSecond: Int;
|
||||
|
||||
public static var audioCallback: IntBox->Buffer->Void;
|
||||
|
||||
public static function play(sound: Sound, loop: Bool = false): kha.audio1.AudioChannel {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function stream(sound: Sound, loop: Bool = false): kha.audio1.AudioChannel {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ class Graphics implements kha.graphics4.Graphics {
|
||||
}
|
||||
|
||||
public function refreshRate(): Int {
|
||||
return 60;
|
||||
return Krom.displayFrequency();
|
||||
}
|
||||
|
||||
public function clear(?color: Color, ?depth: Float, ?stencil: Int): Void {
|
||||
|
@ -34,22 +34,46 @@ void copySample(void *buffer) {
|
||||
}
|
||||
|
||||
int playback_callback(snd_pcm_sframes_t nframes) {
|
||||
int err = 0;
|
||||
if (kinc_a2_internal_callback(&a2_buffer, nframes)) {
|
||||
int ni = 0;
|
||||
while (ni < nframes) {
|
||||
int i = 0;
|
||||
for (; ni < nframes && i < 4096 * 2; ++i, ++ni) {
|
||||
copySample(&buf[i * 2]);
|
||||
}
|
||||
int err2;
|
||||
if ((err2 = snd_pcm_writei(playback_handle, buf, i)) < 0) {
|
||||
fprintf(stderr, "write failed (%s)\n", snd_strerror(err2));
|
||||
}
|
||||
err += err2;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
int err = 0;
|
||||
if (kinc_a2_internal_callback(&a2_buffer, nframes)) {
|
||||
int ni = 0;
|
||||
while (ni < nframes) {
|
||||
int i = 0;
|
||||
for (; ni < nframes && i < 4096; ++i, ++ni) {
|
||||
copySample(&buf[i * 2]);
|
||||
}
|
||||
int err2 = snd_pcm_writei(playback_handle, buf, i);
|
||||
if (err2 < 0) {
|
||||
fprintf(stderr, "ALSA write failed in playback_callback: %s\n", snd_strerror(err2));
|
||||
return err2;
|
||||
}
|
||||
if (err2 < i) {
|
||||
fprintf(stderr, "ALSA short write in playback_callback: wrote %d of %d frames\n", err2, i);
|
||||
}
|
||||
}
|
||||
err = nframes;
|
||||
}
|
||||
else {
|
||||
// Write silence data to prevent recovery
|
||||
if (nframes > 4096) {
|
||||
fprintf(stderr, "Warning: ALSA requested %ld frames for silence, exceeding local buffer size %d. Clamping.\n", nframes, 4096);
|
||||
nframes = 4096;
|
||||
}
|
||||
memset(buf, 0, nframes * 4);
|
||||
|
||||
int err2 = snd_pcm_writei(playback_handle, buf, nframes);
|
||||
|
||||
if (err2 < 0) {
|
||||
fprintf(stderr, "ALSA silence write failed in playback_callback: %s\n", snd_strerror(err2));
|
||||
err = err2;
|
||||
} else {
|
||||
if (err2 < nframes) {
|
||||
fprintf(stderr, "ALSA short silence write in playback_callback: wrote %d of %d frames\n", err2, (int)nframes);
|
||||
}
|
||||
err = err2;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
bool tryToRecover(snd_pcm_t *handle, int errorCode) {
|
||||
|
@ -140,4 +140,4 @@ void kinc_internal_gamepad_trigger_button(int gamepad, int button, float value)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
Before Width: | Height: | Size: 417 KiB After Width: | Height: | Size: 281 KiB |
Before Width: | Height: | Size: 417 KiB After Width: | Height: | Size: 281 KiB |
Before Width: | Height: | Size: 417 KiB After Width: | Height: | Size: 281 KiB |
Before Width: | Height: | Size: 417 KiB After Width: | Height: | Size: 281 KiB |
Before Width: | Height: | Size: 417 KiB After Width: | Height: | Size: 281 KiB |
Before Width: | Height: | Size: 417 KiB After Width: | Height: | Size: 281 KiB |
BIN
Krom/Krom.exe
BIN
Krom/Krom_opengl.exe
Normal file
@ -1 +0,0 @@
|
||||
# armorcore_bin
|
14
README.md
@ -6,22 +6,12 @@ Welcome to Leenkx!
|
||||
|
||||
|
||||
<br>
|
||||
- <a style="color:#2AE0E0;" class="text primary primary-text" href="https://leenkx.com/files/LeenkxSDK3_RC.zip">LeenkxSDKV3.6 lts</a>
|
||||
<br>
|
||||
- <a style="color:#2AE0E0;" class="text primary primary-text" href="https://leenkx.com/files/lx/Leenkx.js">Leenkx.js</a>
|
||||
<br>
|
||||
- Run your own private p2p torrent socket changing Leenkx javascript file directly in /lnxsdk/lib/leenkx_tools/lxjs/Leenkx.js or by configuring the OPTS map in the create Leenkx node.
|
||||
- Run your own private p2p torrent socket changing Leenkx javascript file directly in /lnxsdk/lib/leenkx_tools/lnxjs/Leenkx.js or by configuring the OPTS map in the create Leenkx node.
|
||||
<br>
|
||||
- All works are open source ZLIB / MIT and any compatible licence that guarantee the softwares freedom from my additions to the previous maintainers
|
||||
<br>
|
||||
- LxJS Works as a standalone library
|
||||
- LNXJS Works as a standalone library
|
||||
<br>
|
||||
- The SDK is not ready for production, use for educational purposes. Help the team by reaching out at Leenkx.com!
|
||||
<br>
|
||||
- This build is based on QuantumCoder's whole new core animation system packed with new features! Timmodrians Aura library is also built into this build when audio is enabled!
|
||||
<br>
|
||||
- The SDK is still undergoing many changes so working on large projects is not recommended.
|
||||
<br>
|
||||
- Special thanks to all contributors from the following projects!
|
||||
<br>
|
||||
* https://github.com/armory3d/armory/graphs/contributors<br>
|
||||
|
23
leenkx.py
@ -182,7 +182,7 @@ class LeenkxAddonPreferences(AddonPreferences):
|
||||
description=(
|
||||
"Whether to use OpenCL processing to generate radiance maps with CMFT."
|
||||
" If you experience extremely long build times caused by CMFT, try disabling this option."
|
||||
" For more information see https://github.com/leenkx3d/leenkx/issues/2760"
|
||||
" For more information see https://dev.leenkx.com/LeenkxTeam/LNXSDK/issues/2760"
|
||||
))
|
||||
legacy_shaders: BoolProperty(name="Legacy Shaders", description="Attempt to compile shaders runnable on older hardware, use this for WebGL1 or GLES2 support in mobile render path", default=False)
|
||||
relative_paths: BoolProperty(name="Generate Relative Paths", description="Write relative paths in khafile", default=False)
|
||||
@ -310,9 +310,9 @@ class LeenkxAddonPreferences(AddonPreferences):
|
||||
layout.label(text="Welcome to Leenkx!")
|
||||
|
||||
# Compare version Blender and Leenkx (major, minor)
|
||||
if bpy.app.version[0] != 3 or bpy.app.version[1] != 6:
|
||||
if bpy.app.version[:2] not in [(4, 4), (4, 2), (3, 6), (3, 3)]:
|
||||
box = layout.box().column()
|
||||
box.label(text="Warning: For Leenkx to work correctly, you need Blender 3.6 LTS.")
|
||||
box.label(text="Warning: For Leenkx to work correctly, use a Blender LTS version")
|
||||
|
||||
layout.prop(self, "sdk_path")
|
||||
sdk_path = get_sdk_path(context)
|
||||
@ -617,8 +617,6 @@ def try_os_call(func: Callable, *args, **kwargs) -> bool:
|
||||
|
||||
|
||||
def git_clone(done: Callable[[bool], None], rootdir: str, gitn: str, subdir: str, recursive=False):
|
||||
print('Download SDK manually from https://leenkx.com...')
|
||||
return False
|
||||
rootdir = os.path.normpath(rootdir)
|
||||
path = rootdir + '/' + subdir if subdir != '' else rootdir
|
||||
|
||||
@ -629,14 +627,12 @@ def git_clone(done: Callable[[bool], None], rootdir: str, gitn: str, subdir: str
|
||||
shutil.rmtree(path, onerror=remove_readonly)
|
||||
|
||||
if recursive:
|
||||
run_proc(['git', 'clone', '--recursive', 'https://github.com/' + gitn, path, '--depth', '1', '--shallow-submodules', '--jobs', '4'], done)
|
||||
run_proc(['git', 'clone', '--recursive', 'https://dev.leenkx.com/' + gitn, path, '--depth', '1', '--shallow-submodules', '--jobs', '4'], done)
|
||||
else:
|
||||
run_proc(['git', 'clone', 'https://github.com/' + gitn, path, '--depth', '1'], done)
|
||||
run_proc(['git', 'clone', 'https://dev.leenkx.com/' + gitn, path, '--depth', '1'], done)
|
||||
|
||||
|
||||
def git_test(self: bpy.types.Operator, required_version=None):
|
||||
print('Download SDK manually from https://leenkx.com...')
|
||||
return False
|
||||
try:
|
||||
p = subprocess.Popen(['git', '--version'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
output, _ = p.communicate()
|
||||
@ -789,7 +785,7 @@ def download_sdk(self: bpy.types.Operator, context):
|
||||
else:
|
||||
done(False)
|
||||
|
||||
git_clone(done_clone, sdk_path, 'leenkx3d/lnxsdk', '', recursive=True)
|
||||
git_clone(done_clone, sdk_path, 'LeenkxTeam/LNXSDK', '', recursive=True)
|
||||
|
||||
|
||||
class LnxAddonRestoreButton(bpy.types.Operator):
|
||||
@ -812,7 +808,7 @@ class LnxAddonHelpButton(bpy.types.Operator):
|
||||
"""Updater help"""
|
||||
bl_idname = "lnx_addon.help"
|
||||
bl_label = "Help"
|
||||
bl_description = "Leenkx Updater is currently disabled. Download SDK manually from https://leenkx.com"
|
||||
bl_description = "Leenkx Updater to get the latest SDK from https://dev.leenkx.com/LeenkxTeam/LNXSDK"
|
||||
|
||||
def execute(self, context):
|
||||
webbrowser.open('https://leenkx.com/support')
|
||||
@ -918,7 +914,10 @@ def restart_leenkx(context):
|
||||
|
||||
@persistent
|
||||
def on_load_post(context):
|
||||
restart_leenkx(bpy.context) # context is None, use bpy.context instead
|
||||
if bpy.context is not None:
|
||||
restart_leenkx(bpy.context) # context is None, use bpy.context instead
|
||||
else:
|
||||
bpy.app.timers.register(lambda: restart_leenkx(bpy.context), first_interval=0.1)
|
||||
|
||||
|
||||
def on_register_post():
|
||||
|
@ -475,7 +475,11 @@ fragColor.rgb = min(fragColor.rgb, 65504 * 0.5);
|
||||
} else {
|
||||
fragColor.rgb = mix(midLumColor, maxLumColor, luminance);
|
||||
}
|
||||
|
||||
} else if (PPComp4.x == 9){
|
||||
fragColor.rgb = tonemapAgXSimple(fragColor.rgb);
|
||||
fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2)); // To gamma
|
||||
} else if (PPComp4.x == 10){
|
||||
fragColor.rgb = tonemapAgXFull(fragColor.rgb);
|
||||
} else {
|
||||
fragColor.rgb = vec3(0,1,0); //ERROR
|
||||
}
|
||||
@ -498,6 +502,13 @@ fragColor.rgb = min(fragColor.rgb, 65504 * 0.5);
|
||||
fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2)); // To gamma
|
||||
fragColor.rgb = clamp(fragColor.rgb, 0.0, 2.2);
|
||||
#endif
|
||||
#ifdef _CToneAgXSimple
|
||||
fragColor.rgb = tonemapAgXSimple(fragColor.rgb);
|
||||
fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2)); // To gamma
|
||||
#endif
|
||||
#ifdef _CToneAgXFull
|
||||
fragColor.rgb = tonemapAgXFull(fragColor.rgb);
|
||||
#endif
|
||||
#ifdef _CToneNone
|
||||
fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2)); // To gamma
|
||||
#endif
|
||||
@ -614,4 +625,37 @@ fragColor.rgb = min(fragColor.rgb, 65504 * 0.5);
|
||||
#ifdef _CLUT
|
||||
fragColor = LUTlookup(fragColor, lutTexture);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _CDitheringBlueNoise
|
||||
const float ditherStrength = ditherStrengthValue / 255.0;
|
||||
float noise = ditherBlueNoiseStyle(gl_FragCoord.xy);
|
||||
float noiseOffset = (noise - 0.5) * ditherStrength;
|
||||
fragColor.rgb += noiseOffset;
|
||||
#endif
|
||||
|
||||
#ifdef _CDitheringWhiteNoise
|
||||
const float ditherStrength = ditherStrengthValue / 255.0;
|
||||
float noise = ditherWhiteNoise(gl_FragCoord.xy);
|
||||
float noiseOffset = (noise - 0.5) * ditherStrength;
|
||||
fragColor.rgb += noiseOffset;
|
||||
#endif
|
||||
|
||||
#ifdef _CDitheringOrderedBayer4x4
|
||||
const float ditherStrength = ditherStrengthValue / 255.0;
|
||||
float noise = ditherOrderedBayer4x4(ivec2(gl_FragCoord.xy));
|
||||
float noiseOffset = (noise - 0.5) * ditherStrength;
|
||||
fragColor.rgb += noiseOffset;
|
||||
#endif
|
||||
|
||||
#ifdef _CDitheringOrderedBayer8x8
|
||||
const float ditherStrength = ditherStrengthValue / 255.0;
|
||||
float noise = ditherOrderedBayer8x8(ivec2(gl_FragCoord.xy));
|
||||
float noiseOffset = (noise - 0.5) * ditherStrength;
|
||||
fragColor.rgb += noiseOffset;
|
||||
#endif
|
||||
|
||||
//fragColor.rgb = clamp(fragColor.rgb, 0.0, 1.0);
|
||||
|
||||
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ uniform sampler2D gbuffer0;
|
||||
uniform sampler2D gbuffer1;
|
||||
|
||||
#ifdef _gbuffer2
|
||||
uniform sampler2D gbuffer2;
|
||||
//!uniform sampler2D gbuffer2;
|
||||
#endif
|
||||
#ifdef _EmissionShaded
|
||||
uniform sampler2D gbufferEmission;
|
||||
@ -286,7 +286,7 @@ void main() {
|
||||
|
||||
#ifdef _VoxelGI
|
||||
vec4 indirect_diffuse = textureLod(voxels_diffuse, texCoord, 0.0);
|
||||
fragColor.rgb = (indirect_diffuse.rgb * albedo + envl.rgb * (1.0 - indirect_diffuse.a)) * voxelgiDiff;
|
||||
fragColor.rgb = (indirect_diffuse.rgb + envl.rgb * (1.0 - indirect_diffuse.a)) * albedo * voxelgiDiff;
|
||||
if(roughness < 1.0 && occspec.y > 0.0)
|
||||
fragColor.rgb += textureLod(voxels_specular, texCoord, 0.0).rgb * occspec.y * voxelgiRefl;
|
||||
#endif
|
||||
@ -380,7 +380,7 @@ void main() {
|
||||
#endif
|
||||
|
||||
#ifdef _VoxelShadow
|
||||
svisibility *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, sunDir, clipmaps, gl_FragCoord.xy).r) * voxelgiShad;
|
||||
svisibility *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, sunDir, clipmaps, gl_FragCoord.xy, g2.rg).r) * voxelgiShad;
|
||||
#endif
|
||||
|
||||
#ifdef _SSRS
|
||||
|
@ -92,7 +92,7 @@ void main() {
|
||||
|
||||
vec3 viewNormal = V3 * n;
|
||||
vec3 viewPos = getPosView(viewRay, d, cameraProj);
|
||||
vec3 reflected = reflect(viewPos, viewNormal);
|
||||
vec3 reflected = reflect(normalize(viewPos), viewNormal);
|
||||
hitCoord = viewPos;
|
||||
|
||||
#ifdef _CPostprocess
|
||||
|
@ -57,14 +57,17 @@ vec4 binarySearch(vec3 dir) {
|
||||
}
|
||||
|
||||
vec4 rayCast(vec3 dir) {
|
||||
float ddepth;
|
||||
dir *= ss_refractionRayStep;
|
||||
for (int i = 0; i < maxSteps; i++) {
|
||||
hitCoord += dir;
|
||||
ddepth = getDeltaDepth(hitCoord);
|
||||
if (ddepth > 0.0) return binarySearch(dir);
|
||||
}
|
||||
return vec4(texCoord, 0.0, 1.0);
|
||||
float ddepth;
|
||||
dir *= ss_refractionRayStep;
|
||||
for (int i = 0; i < maxSteps; i++) {
|
||||
hitCoord += dir;
|
||||
ddepth = getDeltaDepth(hitCoord);
|
||||
if (ddepth > 0.0)
|
||||
return binarySearch(dir);
|
||||
}
|
||||
// No hit — fallback to projecting the ray to UV space
|
||||
vec2 fallbackUV = getProjectedCoord(hitCoord);
|
||||
return vec4(fallbackUV, 0.0, 0.5); // We set .w lower to indicate fallback
|
||||
}
|
||||
|
||||
void main() {
|
||||
@ -74,7 +77,7 @@ void main() {
|
||||
float ior = gr.x;
|
||||
float opac = gr.y;
|
||||
float d = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0;
|
||||
if (d == 0.0 || d == 1.0 || opac == 1.0 || ior == 1.0) {
|
||||
if (d == 0.0 || opac == 1.0 || ior == 1.0) {
|
||||
fragColor.rgb = textureLod(tex1, texCoord, 0.0).rgb;
|
||||
return;
|
||||
}
|
||||
@ -86,7 +89,7 @@ void main() {
|
||||
|
||||
vec3 viewNormal = V3 * n;
|
||||
vec3 viewPos = getPosView(viewRay, d, cameraProj);
|
||||
vec3 refracted = refract(viewPos, viewNormal, 1.0 / ior);
|
||||
vec3 refracted = refract(normalize(viewPos), viewNormal, 1.0 / ior);
|
||||
hitCoord = viewPos;
|
||||
|
||||
vec3 dir = refracted * (1.0 - rand(texCoord) * ss_refractionJitter * roughness) * 2.0;
|
||||
|
@ -166,7 +166,7 @@ vec4 traceDiffuse(const vec3 origin, const vec3 normal, const sampler3D voxels,
|
||||
}
|
||||
|
||||
vec4 traceSpecular(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 viewDir, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) {
|
||||
vec3 specularDir = reflect(-viewDir, normal);
|
||||
vec3 specularDir = reflect(normalize(-viewDir), normal);
|
||||
vec3 P = origin + specularDir * ((BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5)) * voxelgiStep;
|
||||
vec4 amount = traceCone(voxels, voxelsSDF, P, normal, specularDir, 0, true, roughness, voxelgiStep, clipmaps);
|
||||
|
||||
@ -176,9 +176,9 @@ vec4 traceSpecular(const vec3 origin, const vec3 normal, const sampler3D voxels,
|
||||
return amount * voxelgiOcc;
|
||||
}
|
||||
|
||||
vec4 traceRefraction(const vec3 origin, const vec3 normal, sampler3D voxels, sampler3D voxelsSDF, const vec3 viewDir, const float ior, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) {
|
||||
const float transmittance = 1.0;
|
||||
vec3 refractionDir = refract(-viewDir, normal, 1.0 / ior);
|
||||
vec4 traceRefraction(const vec3 origin, const vec3 normal, sampler3D voxels, sampler3D voxelsSDF, const vec3 viewDir, const float ior, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity, const float opacity) {
|
||||
const float transmittance = 1.0 - opacity;
|
||||
vec3 refractionDir = refract(normalize(-viewDir), normal, 1.0 / ior);
|
||||
vec3 P = origin + refractionDir * (BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5) * voxelgiStep;
|
||||
vec4 amount = transmittance * traceCone(voxels, voxelsSDF, P, normal, refractionDir, 0, true, roughness, voxelgiStep, clipmaps);
|
||||
|
||||
@ -328,8 +328,8 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v
|
||||
}
|
||||
|
||||
|
||||
float traceShadow(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 dir, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel) {
|
||||
vec3 P = origin + dir * (BayerMatrix8[int(pixel.x) % 8][int(pixel.y) % 8] - 0.5) * voxelgiStep;
|
||||
float traceShadow(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 dir, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) {
|
||||
vec3 P = origin + dir * (BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5) * voxelgiStep;
|
||||
float amount = traceConeShadow(voxels, voxelsSDF, P, normal, dir, DIFFUSE_CONE_APERTURE, voxelgiStep, clipmaps);
|
||||
amount = clamp(amount, 0.0, 1.0);
|
||||
return amount * voxelgiOcc;
|
||||
|
@ -1,239 +1,242 @@
|
||||
#ifndef _LIGHT_GLSL_
|
||||
#define _LIGHT_GLSL_
|
||||
|
||||
#include "compiled.inc"
|
||||
#include "std/brdf.glsl"
|
||||
#include "std/math.glsl"
|
||||
#ifdef _ShadowMap
|
||||
#include "std/shadows.glsl"
|
||||
#endif
|
||||
#ifdef _VoxelShadow
|
||||
#include "std/conetrace.glsl"
|
||||
//!uniform sampler2D voxels_shadows;
|
||||
#endif
|
||||
#ifdef _LTC
|
||||
#include "std/ltc.glsl"
|
||||
#endif
|
||||
#ifdef _LightIES
|
||||
#include "std/ies.glsl"
|
||||
#endif
|
||||
#ifdef _SSRS
|
||||
#include "std/ssrs.glsl"
|
||||
#endif
|
||||
#ifdef _Spot
|
||||
#include "std/light_common.glsl"
|
||||
#endif
|
||||
|
||||
#ifdef _ShadowMap
|
||||
#ifdef _SinglePoint
|
||||
#ifdef _Spot
|
||||
#ifndef _LTC
|
||||
uniform sampler2DShadow shadowMapSpot[1];
|
||||
uniform sampler2D shadowMapSpotTransparent[1];
|
||||
uniform mat4 LWVPSpot[1];
|
||||
#endif
|
||||
#else
|
||||
uniform samplerCubeShadow shadowMapPoint[1];
|
||||
uniform samplerCube shadowMapPointTransparent[1];
|
||||
uniform vec2 lightProj;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
#ifdef _SingleAtlas
|
||||
//!uniform sampler2DShadow shadowMapAtlas;
|
||||
//!uniform sampler2D shadowMapAtlasTransparent;
|
||||
#endif
|
||||
uniform vec2 lightProj;
|
||||
#ifdef _ShadowMapAtlas
|
||||
#ifndef _SingleAtlas
|
||||
uniform sampler2DShadow shadowMapAtlasPoint;
|
||||
uniform sampler2D shadowMapAtlasPointTransparent;
|
||||
#endif
|
||||
#else
|
||||
uniform samplerCubeShadow shadowMapPoint[4];
|
||||
uniform samplerCube shadowMapPointTransparent[4];
|
||||
#endif
|
||||
#ifdef _Spot
|
||||
#ifdef _ShadowMapAtlas
|
||||
#ifndef _SingleAtlas
|
||||
uniform sampler2DShadow shadowMapAtlasSpot;
|
||||
uniform sampler2D shadowMapAtlasSpotTransparent;
|
||||
#endif
|
||||
#else
|
||||
uniform sampler2DShadow shadowMapSpot[4];
|
||||
uniform sampler2D shadowMapSpotTransparent[4];
|
||||
#endif
|
||||
uniform mat4 LWVPSpotArray[maxLightsCluster];
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _LTC
|
||||
uniform vec3 lightArea0;
|
||||
uniform vec3 lightArea1;
|
||||
uniform vec3 lightArea2;
|
||||
uniform vec3 lightArea3;
|
||||
uniform sampler2D sltcMat;
|
||||
uniform sampler2D sltcMag;
|
||||
#ifdef _ShadowMap
|
||||
#ifndef _Spot
|
||||
#ifdef _SinglePoint
|
||||
uniform sampler2DShadow shadowMapSpot[1];
|
||||
uniform sampler2D shadowMapSpotTransparent[1];
|
||||
uniform mat4 LWVPSpot[1];
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
uniform sampler2DShadow shadowMapSpot[maxLightsCluster];
|
||||
uniform sampler2D shadowMapSpotTransparent[maxLightsCluster];
|
||||
uniform mat4 LWVPSpotArray[maxLightsCluster];
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol,
|
||||
const vec3 albedo, const float rough, const float spec, const vec3 f0
|
||||
#ifdef _ShadowMap
|
||||
, int index, float bias, bool receiveShadow, bool transparent
|
||||
#endif
|
||||
#ifdef _Spot
|
||||
, const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right
|
||||
#endif
|
||||
#ifdef _VoxelShadow
|
||||
, sampler3D voxels, sampler3D voxelsSDF, float clipmaps[10 * voxelgiClipmapCount]
|
||||
#endif
|
||||
#ifdef _MicroShadowing
|
||||
, float occ
|
||||
#endif
|
||||
#ifdef _SSRS
|
||||
, sampler2D gbufferD, mat4 invVP, vec3 eye
|
||||
#endif
|
||||
) {
|
||||
vec3 ld = lp - p;
|
||||
vec3 l = normalize(ld);
|
||||
vec3 h = normalize(v + l);
|
||||
float dotNH = max(0.0, dot(n, h));
|
||||
float dotVH = max(0.0, dot(v, h));
|
||||
float dotNL = max(0.0, dot(n, l));
|
||||
|
||||
#ifdef _LTC
|
||||
float theta = acos(dotNV);
|
||||
vec2 tuv = vec2(rough, theta / (0.5 * PI));
|
||||
tuv = tuv * LUT_SCALE + LUT_BIAS;
|
||||
vec4 t = textureLod(sltcMat, tuv, 0.0);
|
||||
mat3 invM = mat3(
|
||||
vec3(1.0, 0.0, t.y),
|
||||
vec3(0.0, t.z, 0.0),
|
||||
vec3(t.w, 0.0, t.x));
|
||||
float ltcspec = ltcEvaluate(n, v, dotNV, p, invM, lightArea0, lightArea1, lightArea2, lightArea3);
|
||||
ltcspec *= textureLod(sltcMag, tuv, 0.0).a;
|
||||
float ltcdiff = ltcEvaluate(n, v, dotNV, p, mat3(1.0), lightArea0, lightArea1, lightArea2, lightArea3);
|
||||
vec3 direct = albedo * ltcdiff + ltcspec * spec * 0.05;
|
||||
#else
|
||||
vec3 direct = lambertDiffuseBRDF(albedo, dotNL) +
|
||||
specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec;
|
||||
#endif
|
||||
|
||||
direct *= attenuate(distance(p, lp));
|
||||
direct *= lightCol;
|
||||
|
||||
#ifdef _MicroShadowing
|
||||
direct *= clamp(dotNL + 2.0 * occ * occ - 1.0, 0.0, 1.0);
|
||||
#endif
|
||||
|
||||
#ifdef _SSRS
|
||||
direct *= traceShadowSS(l, p, gbufferD, invVP, eye);
|
||||
#endif
|
||||
|
||||
#ifdef _VoxelShadow
|
||||
direct *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, l, clipmaps, gl_FragCoord.xy).r) * voxelgiShad;
|
||||
#endif
|
||||
|
||||
#ifdef _LTC
|
||||
#ifdef _ShadowMap
|
||||
if (receiveShadow) {
|
||||
#ifdef _SinglePoint
|
||||
vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0);
|
||||
direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent);
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0);
|
||||
if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent);
|
||||
else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent);
|
||||
else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent);
|
||||
else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
return direct;
|
||||
#endif
|
||||
|
||||
#ifdef _Spot
|
||||
if (isSpot) {
|
||||
direct *= spotlightMask(l, spotDir, right, scale, spotSize, spotBlend);
|
||||
|
||||
#ifdef _ShadowMap
|
||||
if (receiveShadow) {
|
||||
#ifdef _SinglePoint
|
||||
vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0);
|
||||
direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent);
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0);
|
||||
#ifdef _ShadowMapAtlas
|
||||
direct *= shadowTest(
|
||||
#ifndef _SingleAtlas
|
||||
shadowMapAtlasSpot, shadowMapAtlasSpotTransparent
|
||||
#else
|
||||
shadowMapAtlas, shadowMapAtlasTransparent
|
||||
#endif
|
||||
, lPos.xyz / lPos.w, bias, transparent
|
||||
);
|
||||
#else
|
||||
if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent);
|
||||
else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent);
|
||||
else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent);
|
||||
else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
return direct;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _LightIES
|
||||
direct *= iesAttenuation(-l);
|
||||
#endif
|
||||
|
||||
#ifdef _ShadowMap
|
||||
if (receiveShadow) {
|
||||
#ifdef _SinglePoint
|
||||
#ifndef _Spot
|
||||
direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
#ifdef _ShadowMapAtlas
|
||||
direct *= PCFFakeCube(
|
||||
#ifndef _SingleAtlas
|
||||
shadowMapAtlasPoint, shadowMapAtlasPointTransparent
|
||||
#else
|
||||
shadowMapAtlas, shadowMapAtlasTransparent
|
||||
#endif
|
||||
, ld, -l, bias, lightProj, n, index, transparent
|
||||
);
|
||||
#else
|
||||
if (index == 0) direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent);
|
||||
else if (index == 1) direct *= PCFCube(shadowMapPoint[1], shadowMapPointTransparent[1], ld, -l, bias, lightProj, n, transparent);
|
||||
else if (index == 2) direct *= PCFCube(shadowMapPoint[2], shadowMapPointTransparent[2], ld, -l, bias, lightProj, n, transparent);
|
||||
else if (index == 3) direct *= PCFCube(shadowMapPoint[3], shadowMapPointTransparent[3], ld, -l, bias, lightProj, n, transparent);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
return direct;
|
||||
}
|
||||
|
||||
#endif
|
||||
#ifndef _LIGHT_GLSL_
|
||||
#define _LIGHT_GLSL_
|
||||
|
||||
#include "compiled.inc"
|
||||
#include "std/brdf.glsl"
|
||||
#include "std/math.glsl"
|
||||
#ifdef _ShadowMap
|
||||
#include "std/shadows.glsl"
|
||||
#endif
|
||||
#ifdef _VoxelShadow
|
||||
#include "std/conetrace.glsl"
|
||||
#endif
|
||||
#ifdef _gbuffer2
|
||||
uniform sampler2D gbuffer2;
|
||||
#endif
|
||||
#ifdef _LTC
|
||||
#include "std/ltc.glsl"
|
||||
#endif
|
||||
#ifdef _LightIES
|
||||
#include "std/ies.glsl"
|
||||
#endif
|
||||
#ifdef _SSRS
|
||||
#include "std/ssrs.glsl"
|
||||
#endif
|
||||
#ifdef _Spot
|
||||
#include "std/light_common.glsl"
|
||||
#endif
|
||||
|
||||
#ifdef _ShadowMap
|
||||
#ifdef _SinglePoint
|
||||
#ifdef _Spot
|
||||
#ifndef _LTC
|
||||
uniform sampler2DShadow shadowMapSpot[1];
|
||||
uniform sampler2D shadowMapSpotTransparent[1];
|
||||
uniform mat4 LWVPSpot[1];
|
||||
#endif
|
||||
#else
|
||||
uniform samplerCubeShadow shadowMapPoint[1];
|
||||
uniform samplerCube shadowMapPointTransparent[1];
|
||||
uniform vec2 lightProj;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
#ifdef _SingleAtlas
|
||||
//!uniform sampler2DShadow shadowMapAtlas;
|
||||
//!uniform sampler2D shadowMapAtlasTransparent;
|
||||
#endif
|
||||
uniform vec2 lightProj;
|
||||
#ifdef _ShadowMapAtlas
|
||||
#ifndef _SingleAtlas
|
||||
uniform sampler2DShadow shadowMapAtlasPoint;
|
||||
uniform sampler2D shadowMapAtlasPointTransparent;
|
||||
#endif
|
||||
#else
|
||||
uniform samplerCubeShadow shadowMapPoint[4];
|
||||
uniform samplerCube shadowMapPointTransparent[4];
|
||||
#endif
|
||||
#ifdef _Spot
|
||||
#ifdef _ShadowMapAtlas
|
||||
#ifndef _SingleAtlas
|
||||
uniform sampler2DShadow shadowMapAtlasSpot;
|
||||
uniform sampler2D shadowMapAtlasSpotTransparent;
|
||||
#endif
|
||||
#else
|
||||
uniform sampler2DShadow shadowMapSpot[4];
|
||||
uniform sampler2D shadowMapSpotTransparent[4];
|
||||
#endif
|
||||
uniform mat4 LWVPSpotArray[maxLightsCluster];
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _LTC
|
||||
uniform vec3 lightArea0;
|
||||
uniform vec3 lightArea1;
|
||||
uniform vec3 lightArea2;
|
||||
uniform vec3 lightArea3;
|
||||
uniform sampler2D sltcMat;
|
||||
uniform sampler2D sltcMag;
|
||||
#ifdef _ShadowMap
|
||||
#ifndef _Spot
|
||||
#ifdef _SinglePoint
|
||||
uniform sampler2DShadow shadowMapSpot[1];
|
||||
uniform sampler2D shadowMapSpotTransparent[1];
|
||||
uniform mat4 LWVPSpot[1];
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
uniform sampler2DShadow shadowMapSpot[maxLightsCluster];
|
||||
uniform sampler2D shadowMapSpotTransparent[maxLightsCluster];
|
||||
uniform mat4 LWVPSpotArray[maxLightsCluster];
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol,
|
||||
const vec3 albedo, const float rough, const float spec, const vec3 f0
|
||||
#ifdef _ShadowMap
|
||||
, int index, float bias, bool receiveShadow, bool transparent
|
||||
#endif
|
||||
#ifdef _Spot
|
||||
, const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right
|
||||
#endif
|
||||
#ifdef _VoxelShadow
|
||||
, sampler3D voxels, sampler3D voxelsSDF, float clipmaps[10 * voxelgiClipmapCount]
|
||||
#endif
|
||||
#ifdef _MicroShadowing
|
||||
, float occ
|
||||
#endif
|
||||
#ifdef _SSRS
|
||||
, sampler2D gbufferD, mat4 invVP, vec3 eye
|
||||
#endif
|
||||
) {
|
||||
vec3 ld = lp - p;
|
||||
vec3 l = normalize(ld);
|
||||
vec3 h = normalize(v + l);
|
||||
float dotNH = max(0.0, dot(n, h));
|
||||
float dotVH = max(0.0, dot(v, h));
|
||||
float dotNL = max(0.0, dot(n, l));
|
||||
|
||||
#ifdef _LTC
|
||||
float theta = acos(dotNV);
|
||||
vec2 tuv = vec2(rough, theta / (0.5 * PI));
|
||||
tuv = tuv * LUT_SCALE + LUT_BIAS;
|
||||
vec4 t = textureLod(sltcMat, tuv, 0.0);
|
||||
mat3 invM = mat3(
|
||||
vec3(1.0, 0.0, t.y),
|
||||
vec3(0.0, t.z, 0.0),
|
||||
vec3(t.w, 0.0, t.x));
|
||||
float ltcspec = ltcEvaluate(n, v, dotNV, p, invM, lightArea0, lightArea1, lightArea2, lightArea3);
|
||||
ltcspec *= textureLod(sltcMag, tuv, 0.0).a;
|
||||
float ltcdiff = ltcEvaluate(n, v, dotNV, p, mat3(1.0), lightArea0, lightArea1, lightArea2, lightArea3);
|
||||
vec3 direct = albedo * ltcdiff + ltcspec * spec * 0.05;
|
||||
#else
|
||||
vec3 direct = lambertDiffuseBRDF(albedo, dotNL) +
|
||||
specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec;
|
||||
#endif
|
||||
|
||||
direct *= attenuate(distance(p, lp));
|
||||
direct *= lightCol;
|
||||
|
||||
#ifdef _MicroShadowing
|
||||
direct *= clamp(dotNL + 2.0 * occ * occ - 1.0, 0.0, 1.0);
|
||||
#endif
|
||||
|
||||
#ifdef _SSRS
|
||||
direct *= traceShadowSS(l, p, gbufferD, invVP, eye);
|
||||
#endif
|
||||
|
||||
#ifdef _VoxelShadow
|
||||
vec4 g2 = textureLod(gbuffer2, gl_FragCoord.xy, 0.0);
|
||||
direct *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, l, clipmaps, gl_FragCoord.xy, g2.rg).r) * voxelgiShad;
|
||||
#endif
|
||||
|
||||
#ifdef _LTC
|
||||
#ifdef _ShadowMap
|
||||
if (receiveShadow) {
|
||||
#ifdef _SinglePoint
|
||||
vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0);
|
||||
direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent);
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0);
|
||||
if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent);
|
||||
else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent);
|
||||
else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent);
|
||||
else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
return direct;
|
||||
#endif
|
||||
|
||||
#ifdef _Spot
|
||||
if (isSpot) {
|
||||
direct *= spotlightMask(l, spotDir, right, scale, spotSize, spotBlend);
|
||||
|
||||
#ifdef _ShadowMap
|
||||
if (receiveShadow) {
|
||||
#ifdef _SinglePoint
|
||||
vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0);
|
||||
direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent);
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0);
|
||||
#ifdef _ShadowMapAtlas
|
||||
direct *= shadowTest(
|
||||
#ifndef _SingleAtlas
|
||||
shadowMapAtlasSpot, shadowMapAtlasSpotTransparent
|
||||
#else
|
||||
shadowMapAtlas, shadowMapAtlasTransparent
|
||||
#endif
|
||||
, lPos.xyz / lPos.w, bias, transparent
|
||||
);
|
||||
#else
|
||||
if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent);
|
||||
else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent);
|
||||
else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent);
|
||||
else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
return direct;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _LightIES
|
||||
direct *= iesAttenuation(-l);
|
||||
#endif
|
||||
|
||||
#ifdef _ShadowMap
|
||||
if (receiveShadow) {
|
||||
#ifdef _SinglePoint
|
||||
#ifndef _Spot
|
||||
direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
#ifdef _ShadowMapAtlas
|
||||
direct *= PCFFakeCube(
|
||||
#ifndef _SingleAtlas
|
||||
shadowMapAtlasPoint, shadowMapAtlasPointTransparent
|
||||
#else
|
||||
shadowMapAtlas, shadowMapAtlasTransparent
|
||||
#endif
|
||||
, ld, -l, bias, lightProj, n, index, transparent
|
||||
);
|
||||
#else
|
||||
if (index == 0) direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent);
|
||||
else if (index == 1) direct *= PCFCube(shadowMapPoint[1], shadowMapPointTransparent[1], ld, -l, bias, lightProj, n, transparent);
|
||||
else if (index == 2) direct *= PCFCube(shadowMapPoint[2], shadowMapPointTransparent[2], ld, -l, bias, lightProj, n, transparent);
|
||||
else if (index == 3) direct *= PCFCube(shadowMapPoint[3], shadowMapPointTransparent[3], ld, -l, bias, lightProj, n, transparent);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
return direct;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
vec3 uncharted2Tonemap(const vec3 x) {
|
||||
const float A = 0.15;
|
||||
const float B = 0.50;
|
||||
@ -36,3 +35,106 @@ vec3 acesFilm(const vec3 x) {
|
||||
vec3 tonemapReinhard(const vec3 color) {
|
||||
return color / (color + vec3(1.0));
|
||||
}
|
||||
|
||||
// Blender AgX Implementation
|
||||
// Troy Sobotka https://github.com/sobotka/AgX
|
||||
|
||||
// AGX Simple
|
||||
vec3 tonemapAgXSimple(vec3 x) {
|
||||
// TODO CORRECT AND OPTIMIZE
|
||||
x = max(x, vec3(0.0));
|
||||
float exposure = 0.6;
|
||||
x *= exposure;
|
||||
const vec3 AgX_A = vec3(0.92, 0.92, 0.72);
|
||||
const vec3 AgX_B = vec3(0.24, 0.24, 0.36);
|
||||
const vec3 AgX_C = vec3(0.92, 0.92, 0.72);
|
||||
const vec3 AgX_D = vec3(0.24, 0.24, 0.36);
|
||||
const vec3 AgX_E = vec3(0.08, 0.08, 0.12);
|
||||
const vec3 AgX_F = vec3(0.0);
|
||||
vec3 result = (x * (AgX_A * x + AgX_B)) / (x * (AgX_C * x + AgX_D) + AgX_E) + AgX_F;
|
||||
float luma = dot(result, vec3(0.2126, 0.7152, 0.0722));
|
||||
result = mix(vec3(luma), result, 0.6);
|
||||
return clamp(result, vec3(0.0), vec3(1.0));
|
||||
}
|
||||
|
||||
// AGX Full Contrast Approx
|
||||
vec3 agxDefaultContrastApprox(vec3 x) {
|
||||
vec3 x2 = x * x;
|
||||
vec3 x4 = x2 * x2;
|
||||
return + 15.5 * x4 * x2
|
||||
- 40.14 * x4 * x
|
||||
+ 31.96 * x4
|
||||
- 6.868 * x2 * x
|
||||
+ 0.4298 * x2
|
||||
+ 0.1191 * x
|
||||
- 0.00232;
|
||||
}
|
||||
// AGX Full Look
|
||||
vec3 agxLook(vec3 x, float strength) {
|
||||
const vec3 slope = vec3(1.0);
|
||||
const vec3 power = vec3(1.35);
|
||||
const vec3 sat = vec3(1.4);
|
||||
vec3 lw = vec3(0.2126, 0.7152, 0.0722);
|
||||
float luma = dot(x, lw);
|
||||
return pow(x * slope, power) * sat - (pow(luma * slope, power) * (sat - 1.0));
|
||||
}
|
||||
|
||||
// AGX Full
|
||||
vec3 tonemapAgXFull(vec3 x) {
|
||||
// x *= 2.0 * (1.0/0.8); // Brightness scale to match Blender's default
|
||||
x = clamp(x, 0.0, 65504.0);
|
||||
x = log2(x + 1.0);
|
||||
x = agxDefaultContrastApprox(clamp(x * 0.5 - 10.5, -12.0, 12.0));
|
||||
x = mix(x, agxLook(x, 0.5), 0.5);
|
||||
x = clamp(x, 0.0, 1.0);
|
||||
return pow(x, vec3(1.0/2.2));
|
||||
}
|
||||
|
||||
|
||||
// Interleaved Gradient Noise (Pseudo-random, AKA Blue Noise style)
|
||||
// Based on http://momentsingraphics.de/BlueNoise.html
|
||||
float ditherBlueNoiseStyle(vec2 p) {
|
||||
return fract(sin(dot(p.xy, vec2(12.9898, 78.233))) * 43758.5453123);
|
||||
}
|
||||
|
||||
// White Noise Dithering
|
||||
float ditherWhiteNoise(vec2 p) {
|
||||
return fract(sin(dot(p, vec2(12.9898, 4.1414))) * 43758.5453);
|
||||
}
|
||||
|
||||
// Ordered Dithering (4x4 Bayer Matrix)
|
||||
float ditherOrderedBayer4x4(ivec2 p) {
|
||||
const float bayer[16] = float[16](
|
||||
0.0, 8.0, 2.0, 10.0,
|
||||
12.0, 4.0, 14.0, 6.0,
|
||||
3.0, 11.0, 1.0, 9.0,
|
||||
15.0, 7.0, 13.0, 5.0
|
||||
);
|
||||
int index = (p.x % 4) * 4 + (p.y % 4);
|
||||
return bayer[index] / 16.0;
|
||||
}
|
||||
|
||||
// Ordered Dithering (8x8 Bayer Matrix)
|
||||
float ditherOrderedBayer8x8(ivec2 p) {
|
||||
const float bayer8x8[64] = float[64](
|
||||
0.0, 32.0, 8.0, 40.0, 2.0, 34.0, 10.0, 42.0,
|
||||
48.0, 16.0, 56.0, 24.0, 50.0, 18.0, 58.0, 26.0,
|
||||
12.0, 44.0, 4.0, 36.0, 14.0, 46.0, 6.0, 38.0,
|
||||
60.0, 28.0, 52.0, 20.0, 62.0, 30.0, 54.0, 22.0,
|
||||
3.0, 35.0, 11.0, 43.0, 1.0, 33.0, 9.0, 41.0,
|
||||
51.0, 19.0, 59.0, 27.0, 49.0, 17.0, 57.0, 25.0,
|
||||
15.0, 47.0, 7.0, 39.0, 13.0, 45.0, 5.0, 37.0,
|
||||
63.0, 31.0, 55.0, 23.0, 61.0, 29.0, 53.0, 21.0
|
||||
);
|
||||
int index = (p.x % 8) * 8 + (p.y % 8);
|
||||
return bayer8x8[index] / 64.0;
|
||||
}
|
||||
|
||||
|
||||
//vec3 applyDither(vec3 color, vec2 screenCoord) {
|
||||
// float quantizationLevels = 255.0;
|
||||
// float noise = randomDither(screenCoord);
|
||||
// float noiseOffset = (noise - 0.5) / quantizationLevels;
|
||||
// vec3 ditheredColor = color + noiseOffset;
|
||||
// return clamp(ditheredColor, 0.0, 1.0);
|
||||
//}
|
||||
|
@ -33,6 +33,7 @@ uniform layout(r32ui) uimage3D voxelsLight;
|
||||
|
||||
#ifdef _ShadowMap
|
||||
uniform sampler2DShadow shadowMap;
|
||||
uniform sampler2D shadowMapTransparent;
|
||||
uniform sampler2DShadow shadowMapSpot;
|
||||
#ifdef _ShadowMapAtlas
|
||||
uniform sampler2DShadow shadowMapPoint;
|
||||
@ -86,53 +87,51 @@ float lpToDepth(vec3 lp, const vec2 lightProj) {
|
||||
|
||||
void main() {
|
||||
int res = voxelgiResolution.x;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
ivec3 dst = ivec3(gl_GlobalInvocationID.xyz);
|
||||
vec3 P = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution;
|
||||
P = P * 2.0 - 1.0;
|
||||
|
||||
ivec3 dst = ivec3(gl_GlobalInvocationID.xyz);
|
||||
dst.y += clipmapLevel * res;
|
||||
|
||||
vec3 P = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution;
|
||||
P = P * 2.0 - 1.0;
|
||||
P *= clipmaps[int(clipmapLevel * 10)];
|
||||
P *= voxelgiResolution;
|
||||
P += vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)]);
|
||||
|
||||
vec3 visibility;
|
||||
vec3 lp = lightPos - P;
|
||||
vec3 l;
|
||||
if (lightType == 0) { l = lightDir; visibility = vec3(1.0); }
|
||||
else { l = normalize(lp); visibility = vec3(attenuate(distance(P, lightPos))); }
|
||||
float visibility;
|
||||
vec3 lp = lightPos - P;
|
||||
vec3 l;
|
||||
if (lightType == 0) { l = lightDir; visibility = 1.0; }
|
||||
else { l = normalize(lp); visibility = attenuate(distance(P, lightPos)); }
|
||||
|
||||
#ifdef _ShadowMap
|
||||
if (lightShadow == 1) {
|
||||
vec4 lightPosition = LVP * vec4(P, 1.0);
|
||||
vec3 lPos = lightPosition.xyz / lightPosition.w;
|
||||
visibility = texture(shadowMap, vec3(lPos.xy, lPos.z - shadowsBias)).rrr;
|
||||
}
|
||||
else if (lightShadow == 2) {
|
||||
vec4 lightPosition = LVP * vec4(P, 1.0);
|
||||
vec3 lPos = lightPosition.xyz / lightPosition.w;
|
||||
visibility *= texture(shadowMapSpot, vec3(lPos.xy, lPos.z - shadowsBias)).r;
|
||||
}
|
||||
else if (lightShadow == 3) {
|
||||
#ifdef _ShadowMapAtlas
|
||||
int faceIndex = 0;
|
||||
const int lightIndex = index * 6;
|
||||
const vec2 uv = sampleCube(-l, faceIndex);
|
||||
vec4 pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas
|
||||
vec2 uvtiled = pointLightTile.z * uv + pointLightTile.xy;
|
||||
#ifdef _FlipY
|
||||
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
|
||||
#endif
|
||||
visibility *= texture(shadowMapPoint, vec3(uvtiled, lpToDepth(lp, lightProj) - shadowsBias)).r;
|
||||
#else
|
||||
visibility *= texture(shadowMapPoint, vec4(-l, lpToDepth(lp, lightProj) - shadowsBias)).r;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
if (lightShadow == 1) {
|
||||
vec4 lightPosition = LVP * vec4(P, 1.0);
|
||||
vec3 lPos = lightPosition.xyz / lightPosition.w;
|
||||
visibility = texture(shadowMap, vec3(lPos.xy, lPos.z - shadowsBias)).r;
|
||||
}
|
||||
else if (lightShadow == 2) {
|
||||
vec4 lightPosition = LVP * vec4(P, 1.0);
|
||||
vec3 lPos = lightPosition.xyz / lightPosition.w;
|
||||
visibility *= texture(shadowMapSpot, vec3(lPos.xy, lPos.z - shadowsBias)).r;
|
||||
}
|
||||
else if (lightShadow == 3) {
|
||||
#ifdef _ShadowMapAtlas
|
||||
int faceIndex = 0;
|
||||
const int lightIndex = index * 6;
|
||||
const vec2 uv = sampleCube(-l, faceIndex);
|
||||
vec4 pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas
|
||||
vec2 uvtiled = pointLightTile.z * uv + pointLightTile.xy;
|
||||
#ifdef _FlipY
|
||||
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
|
||||
#endif
|
||||
visibility *= texture(shadowMapPoint, vec3(uvtiled, lpToDepth(lp, lightProj) - shadowsBias)).r;
|
||||
#else
|
||||
visibility *= texture(shadowMapPoint, vec4(-l, lpToDepth(lp, lightProj) - shadowsBias)).r;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
vec3 uvw_light = (P - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]) * voxelgiResolution);
|
||||
uvw_light = (uvw_light * 0.5 + 0.5);
|
||||
if (any(notEqual(uvw_light, clamp(uvw_light, 0.0, 1.0)))) return;
|
||||
vec3 writecoords_light = floor(uvw_light * voxelgiResolution);
|
||||
|
||||
vec3 light = visibility * lightColor;
|
||||
|
||||
imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, 0), uint(light.r * 255));
|
||||
imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, voxelgiResolution.x), uint(light.g * 255));
|
||||
imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, voxelgiResolution.x * 2), uint(light.b * 255));
|
||||
imageAtomicMax(voxelsLight, ivec3(writecoords_light), uint(visibility * lightColor.r * 255));
|
||||
imageAtomicMax(voxelsLight, ivec3(writecoords_light) + ivec3(0, 0, voxelgiResolution.x), uint(visibility * lightColor.g * 255));
|
||||
imageAtomicMax(voxelsLight, ivec3(writecoords_light) + ivec3(0, 0, voxelgiResolution.x * 2), uint(visibility * lightColor.b * 255));
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
|
||||
uniform sampler3D voxels;
|
||||
uniform sampler2D gbufferD;
|
||||
uniform sampler2D gbuffer0;
|
||||
uniform layout(r8) image2D voxels_ao;
|
||||
uniform layout(r16) image2D voxels_ao;
|
||||
|
||||
uniform float clipmaps[voxelgiClipmapCount * 10];
|
||||
uniform mat4 InvVP;
|
||||
|
@ -33,7 +33,7 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
|
||||
uniform sampler3D voxels;
|
||||
uniform sampler2D gbufferD;
|
||||
uniform sampler2D gbuffer0;
|
||||
uniform layout(rgba8) image2D voxels_diffuse;
|
||||
uniform layout(rgba16) image2D voxels_diffuse;
|
||||
|
||||
uniform float clipmaps[voxelgiClipmapCount * 10];
|
||||
uniform mat4 InvVP;
|
||||
@ -46,7 +46,7 @@ void main() {
|
||||
const vec2 pixel = gl_GlobalInvocationID.xy;
|
||||
vec2 uv = (pixel + 0.5) / postprocess_resolution;
|
||||
#ifdef _InvY
|
||||
uv.y = 1.0 - uv.y
|
||||
uv.y = 1.0 - uv.y;
|
||||
#endif
|
||||
|
||||
float depth = textureLod(gbufferD, uv, 0.0).r * 2.0 - 1.0;
|
||||
|
@ -34,7 +34,7 @@ uniform sampler2D gbufferD;
|
||||
uniform sampler2D gbuffer0;
|
||||
uniform sampler3D voxels;
|
||||
uniform sampler3D voxelsSDF;
|
||||
uniform layout(rgba8) image2D voxels_specular;
|
||||
uniform layout(rgba16) image2D voxels_specular;
|
||||
|
||||
uniform float clipmaps[voxelgiClipmapCount * 10];
|
||||
uniform mat4 InvVP;
|
||||
@ -48,7 +48,7 @@ void main() {
|
||||
const vec2 pixel = gl_GlobalInvocationID.xy;
|
||||
vec2 uv = (pixel + 0.5) / postprocess_resolution;
|
||||
#ifdef _InvY
|
||||
uv.y = 1.0 - uv.y
|
||||
uv.y = 1.0 - uv.y;
|
||||
#endif
|
||||
|
||||
float depth = textureLod(gbufferD, uv, 0.0).r * 2.0 - 1.0;
|
||||
@ -71,7 +71,7 @@ void main() {
|
||||
|
||||
vec2 velocity = -textureLod(sveloc, uv, 0.0).rg;
|
||||
|
||||
vec3 color = traceSpecular(P, n, voxels, voxelsSDF, normalize(eye - P), g0.z, clipmaps, pixel, velocity).rgb;
|
||||
vec3 color = traceSpecular(P, n, voxels, voxelsSDF, normalize(eye - P), g0.z * g0.z, clipmaps, pixel, velocity).rgb;
|
||||
|
||||
imageStore(voxels_specular, ivec2(pixel), vec4(color, 1.0));
|
||||
}
|
||||
|
@ -23,8 +23,8 @@ THE SOFTWARE.
|
||||
|
||||
#include "compiled.inc"
|
||||
|
||||
uniform layout(r16) image3D input_sdf;
|
||||
uniform layout(r16) image3D output_sdf;
|
||||
uniform layout(r8) image3D input_sdf;
|
||||
uniform layout(r8) image3D output_sdf;
|
||||
|
||||
uniform float jump_size;
|
||||
uniform int clipmapLevel;
|
||||
|
@ -46,15 +46,15 @@ uniform layout(r32ui) uimage3D voxels;
|
||||
uniform layout(r32ui) uimage3D voxelsLight;
|
||||
uniform layout(rgba8) image3D voxelsB;
|
||||
uniform layout(rgba8) image3D voxelsOut;
|
||||
uniform layout(r16) image3D SDF;
|
||||
uniform layout(r8) image3D SDF;
|
||||
#else
|
||||
#ifdef _VoxelAOvar
|
||||
#ifdef _VoxelShadow
|
||||
uniform layout(r16) image3D SDF;
|
||||
uniform layout(r8) image3D SDF;
|
||||
#endif
|
||||
uniform layout(r32ui) uimage3D voxels;
|
||||
uniform layout(r16) image3D voxelsB;
|
||||
uniform layout(r16) image3D voxelsOut;
|
||||
uniform layout(r8) image3D voxelsB;
|
||||
uniform layout(r8) image3D voxelsOut;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -80,7 +80,6 @@ void main() {
|
||||
light.r = float(imageLoad(voxelsLight, src)) / 255;
|
||||
light.g = float(imageLoad(voxelsLight, src + ivec3(0, 0, voxelgiResolution.x))) / 255;
|
||||
light.b = float(imageLoad(voxelsLight, src + ivec3(0, 0, voxelgiResolution.x * 2))) / 255;
|
||||
light /= 3;
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < 6 + DIFFUSE_CONE_COUNT; i++)
|
||||
@ -125,7 +124,7 @@ void main() {
|
||||
envl.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 10))) / 255;
|
||||
envl.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 11))) / 255;
|
||||
envl /= 3;
|
||||
envl *= 100;
|
||||
|
||||
|
||||
//clipmap to world
|
||||
vec3 wposition = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution.x;
|
||||
@ -137,7 +136,7 @@ void main() {
|
||||
radiance = basecol;
|
||||
vec4 trace = traceDiffuse(wposition, wnormal, voxelsSampler, clipmaps);
|
||||
vec3 indirect = trace.rgb + envl.rgb * (1.0 - trace.a);
|
||||
radiance.rgb *= light + indirect;
|
||||
radiance.rgb *= light / PI + indirect;
|
||||
radiance.rgb += emission.rgb;
|
||||
|
||||
#else
|
||||
|
@ -75,16 +75,17 @@ vec4 binarySearch(vec3 dir) {
|
||||
}
|
||||
|
||||
vec4 rayCast(vec3 dir) {
|
||||
#ifdef _CPostprocess
|
||||
dir *= PPComp9.x;
|
||||
#else
|
||||
dir *= ssrRayStep;
|
||||
#endif
|
||||
for (int i = 0; i < maxSteps; i++) {
|
||||
hitCoord += dir;
|
||||
if (getDeltaDepth(hitCoord) > 0.0) return binarySearch(dir);
|
||||
}
|
||||
return vec4(0.0);
|
||||
float ddepth;
|
||||
dir *= ss_refractionRayStep;
|
||||
for (int i = 0; i < maxSteps; i++) {
|
||||
hitCoord += dir;
|
||||
ddepth = getDeltaDepth(hitCoord);
|
||||
if (ddepth > 0.0)
|
||||
return binarySearch(dir);
|
||||
}
|
||||
// No hit — fallback to projecting the ray to UV space
|
||||
vec2 fallbackUV = getProjectedCoord(hitCoord);
|
||||
return vec4(fallbackUV, 0.0, 0.5); // We set .w lower to indicate fallback
|
||||
}
|
||||
#endif //SSR
|
||||
|
||||
|
@ -66,12 +66,32 @@ class Quat {
|
||||
}
|
||||
|
||||
public inline function fromAxisAngle(axis: Vec4, angle: FastFloat): Quat {
|
||||
var s: FastFloat = Math.sin(angle * 0.5);
|
||||
x = axis.x * s;
|
||||
y = axis.y * s;
|
||||
z = axis.z * s;
|
||||
w = Math.cos(angle * 0.5);
|
||||
return normalize();
|
||||
//var s: FastFloat = Math.sin(angle * 0.5);
|
||||
//x = axis.x * s;
|
||||
//y = axis.y * s;
|
||||
//z = axis.z * s;
|
||||
//w = Math.cos(angle * 0.5);
|
||||
//return normalize();
|
||||
// Normalize the axis vector first
|
||||
var axisLen = Math.sqrt(axis.x * axis.x + axis.y * axis.y + axis.z * axis.z);
|
||||
if (axisLen > 0.00001) {
|
||||
var aL = 1.0 / axisLen;
|
||||
var nX = axis.x * aL;
|
||||
var nY = axis.y * aL;
|
||||
var nZ = axis.z * aL;
|
||||
var halfAngle = angle * 0.5;
|
||||
var s: FastFloat = Math.sin(halfAngle);
|
||||
x = nX * s;
|
||||
y = nY * s;
|
||||
z = nZ * s;
|
||||
w = Math.cos(halfAngle);
|
||||
} else {
|
||||
x = 0.0;
|
||||
y = 0.0;
|
||||
z = 0.0;
|
||||
w = 1.0;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function toAxisAngle(axis: Vec4): FastFloat {
|
||||
@ -379,17 +399,33 @@ class Quat {
|
||||
@return This quaternion.
|
||||
**/
|
||||
public inline function fromEulerOrdered(e: Vec4, order: String): Quat {
|
||||
var c1 = Math.cos(e.x / 2);
|
||||
var c2 = Math.cos(e.y / 2);
|
||||
var c3 = Math.cos(e.z / 2);
|
||||
var s1 = Math.sin(e.x / 2);
|
||||
var s2 = Math.sin(e.y / 2);
|
||||
var s3 = Math.sin(e.z / 2);
|
||||
|
||||
|
||||
var mappedAngles = new Vec4();
|
||||
switch (order) {
|
||||
case "XYZ":
|
||||
mappedAngles.set(e.x, e.y, e.z);
|
||||
case "XZY":
|
||||
mappedAngles.set(e.x, e.z, e.y);
|
||||
case "YXZ":
|
||||
mappedAngles.set(e.y, e.x, e.z);
|
||||
case "YZX":
|
||||
mappedAngles.set(e.y, e.z, e.x);
|
||||
case "ZXY":
|
||||
mappedAngles.set(e.z, e.x, e.y);
|
||||
case "ZYX":
|
||||
mappedAngles.set(e.z, e.y, e.x);
|
||||
}
|
||||
var c1 = Math.cos(mappedAngles.x / 2);
|
||||
var c2 = Math.cos(mappedAngles.y / 2);
|
||||
var c3 = Math.cos(mappedAngles.z / 2);
|
||||
var s1 = Math.sin(mappedAngles.x / 2);
|
||||
var s2 = Math.sin(mappedAngles.y / 2);
|
||||
var s3 = Math.sin(mappedAngles.z / 2);
|
||||
var qx = new Quat(s1, 0, 0, c1);
|
||||
var qy = new Quat(0, s2, 0, c2);
|
||||
var qz = new Quat(0, 0, s3, c3);
|
||||
|
||||
// Original multiplication sequence (implements reverse of 'order')
|
||||
if (order.charAt(2) == 'X')
|
||||
this.setFrom(qx);
|
||||
else if (order.charAt(2) == 'Y')
|
||||
@ -409,6 +445,12 @@ class Quat {
|
||||
else
|
||||
this.mult(qz);
|
||||
|
||||
// TO DO quick fix somethings wrong..
|
||||
this.x = -this.x;
|
||||
this.y = -this.y;
|
||||
this.z = -this.z;
|
||||
this.w = -this.w;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -411,12 +411,23 @@ class ActionSampler {
|
||||
*/
|
||||
public inline function setBoneAction(actionData: Array<TObj>) {
|
||||
this.actionData = actionData;
|
||||
this.totalFrames = actionData[0].anim.tracks[0].frames.length;
|
||||
if(actionData[0].anim.root_motion_pos) this.rootMotionPos = true;
|
||||
if(actionData[0].anim.root_motion_rot) this.rootMotionRot = true;
|
||||
if (actionData != null && actionData.length > 0 && actionData[0] != null && actionData[0].anim != null) {
|
||||
if (actionData[0].anim.tracks != null && actionData[0].anim.tracks.length > 0) {
|
||||
this.totalFrames = actionData[0].anim.tracks[0].frames.length;
|
||||
}
|
||||
else {
|
||||
this.totalFrames = 0;
|
||||
}
|
||||
if(actionData[0].anim.root_motion_pos) this.rootMotionPos = true;
|
||||
if(actionData[0].anim.root_motion_rot) this.rootMotionRot = true;
|
||||
}
|
||||
else {
|
||||
this.totalFrames = 0;
|
||||
}
|
||||
actionDataInit = true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Cache raw object data for object animation.
|
||||
* @param actionData Raw object data.
|
||||
|
@ -51,6 +51,7 @@ class ParticleSystem {
|
||||
seed = pref.seed;
|
||||
particles = [];
|
||||
ready = false;
|
||||
|
||||
Data.getParticle(sceneName, pref.particle, function(b: ParticleData) {
|
||||
data = b;
|
||||
r = data.raw;
|
||||
@ -70,7 +71,13 @@ class ParticleSystem {
|
||||
lifetime = r.lifetime / frameRate;
|
||||
animtime = (r.frame_end - r.frame_start) / frameRate;
|
||||
spawnRate = ((r.frame_end - r.frame_start) / r.count) / frameRate;
|
||||
for (i in 0...r.count) particles.push(new Particle(i));
|
||||
|
||||
for (i in 0...r.count) {
|
||||
var particle = new Particle(i);
|
||||
particle.sr = 1 - Math.random() * r.size_random;
|
||||
particles.push(particle);
|
||||
}
|
||||
|
||||
ready = true;
|
||||
});
|
||||
}
|
||||
@ -108,7 +115,7 @@ class ParticleSystem {
|
||||
}
|
||||
|
||||
// Animate
|
||||
time += Time.realDelta * speed;
|
||||
time += Time.delta * speed;
|
||||
lap = Std.int(time / animtime);
|
||||
lapTime = time - lap * animtime;
|
||||
count = Std.int(lapTime / spawnRate);
|
||||
@ -143,7 +150,7 @@ class ParticleSystem {
|
||||
}
|
||||
|
||||
function setupGeomGpu(object: MeshObject, owner: MeshObject) {
|
||||
var instancedData = new Float32Array(particles.length * 3);
|
||||
var instancedData = new Float32Array(particles.length * 6);
|
||||
var i = 0;
|
||||
|
||||
var normFactor = 1 / 32767; // pa.values are not normalized
|
||||
@ -162,6 +169,10 @@ class ParticleSystem {
|
||||
instancedData.set(i, pa.values[j * pa.size ] * normFactor * scaleFactor.x); i++;
|
||||
instancedData.set(i, pa.values[j * pa.size + 1] * normFactor * scaleFactor.y); i++;
|
||||
instancedData.set(i, pa.values[j * pa.size + 2] * normFactor * scaleFactor.z); i++;
|
||||
|
||||
instancedData.set(i, p.sr); i++;
|
||||
instancedData.set(i, p.sr); i++;
|
||||
instancedData.set(i, p.sr); i++;
|
||||
}
|
||||
|
||||
case 1: // Face
|
||||
@ -185,6 +196,10 @@ class ParticleSystem {
|
||||
instancedData.set(i, pos.x * normFactor * scaleFactor.x); i++;
|
||||
instancedData.set(i, pos.y * normFactor * scaleFactor.y); i++;
|
||||
instancedData.set(i, pos.z * normFactor * scaleFactor.z); i++;
|
||||
|
||||
instancedData.set(i, p.sr); i++;
|
||||
instancedData.set(i, p.sr); i++;
|
||||
instancedData.set(i, p.sr); i++;
|
||||
}
|
||||
|
||||
case 2: // Volume
|
||||
@ -195,9 +210,13 @@ class ParticleSystem {
|
||||
instancedData.set(i, (Math.random() * 2.0 - 1.0) * scaleFactorVolume.x); i++;
|
||||
instancedData.set(i, (Math.random() * 2.0 - 1.0) * scaleFactorVolume.y); i++;
|
||||
instancedData.set(i, (Math.random() * 2.0 - 1.0) * scaleFactorVolume.z); i++;
|
||||
|
||||
instancedData.set(i, p.sr); i++;
|
||||
instancedData.set(i, p.sr); i++;
|
||||
instancedData.set(i, p.sr); i++;
|
||||
}
|
||||
}
|
||||
object.data.geom.setupInstanced(instancedData, 1, Usage.StaticUsage);
|
||||
object.data.geom.setupInstanced(instancedData, 3, Usage.StaticUsage);
|
||||
}
|
||||
|
||||
function fhash(n: Int): Float {
|
||||
@ -236,9 +255,10 @@ class ParticleSystem {
|
||||
|
||||
class Particle {
|
||||
public var i: Int;
|
||||
public var x = 0.0;
|
||||
public var y = 0.0;
|
||||
public var z = 0.0;
|
||||
public var px = 0.0;
|
||||
public var py = 0.0;
|
||||
public var pz = 0.0;
|
||||
public var sr = 1.0; // Size random
|
||||
public var cameraDistance: Float;
|
||||
|
||||
public function new(i: Int) {
|
||||
|
@ -160,6 +160,7 @@ class LnxPack {
|
||||
case "anim": TAnimation;
|
||||
case "tracks": TTrack;
|
||||
case "morph_target": TMorphTarget;
|
||||
case "vertex_groups": TVertex_groups;
|
||||
case _: TSceneFormat;
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +0,0 @@
|
||||
# The zlib/libpng License
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
This notice may not be removed or altered from any source distribution.
|
@ -1,8 +0,0 @@
|
||||

|
||||
|
||||
iron
|
||||
==============
|
||||
|
||||
[Wiki](https://github.com/leenkx3d/iron/wiki) - [Examples](https://github.com/leenkx3d/iron_examples)
|
||||
|
||||
Iron is a 3D engine core library built with [Kha](https://github.com/Kode/Kha) and [Haxe](https://github.com/HaxeFoundation/haxe). Powering [Leenkx](https://leenkx.com).
|
@ -1,7 +0,0 @@
|
||||
|
||||
* 2019-11-04: `comma` key is now `,`, `period` key is now `.`
|
||||
* 2018-08-28: `LampObject` and `LampData` is now `LightObject` and `LightData`
|
||||
* 2018-08-28: Use `new Vec4(0,0,1)` (or `Vec4.zAxis()`) instead of `Vec4.up()`
|
||||
* 2018-08-28: `Vec4.lerp` is no longer static, use `var v = new Vec4(); v.lerp(from, to, s)`
|
||||
* 2018-08-21: `Vec4.lerp(to, from, s)` is now `Vec4.lerp(from, to, s)`
|
||||
* 2017-12-10: Use `iron.math.Vec4.distance()` instead of `iron.math.Vec4.distance3d()`.
|
@ -1,253 +0,0 @@
|
||||
{
|
||||
"defaultSeverity": "INFO",
|
||||
"checks": [
|
||||
{
|
||||
"type": "CodeSimilarity"
|
||||
},
|
||||
{
|
||||
"type": "DefaultComesLast"
|
||||
},
|
||||
{
|
||||
"type": "DocCommentStyle"
|
||||
},
|
||||
{
|
||||
"type": "ERegLiteral"
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"tokens": [
|
||||
"CLASS_DEF",
|
||||
"ENUM_DEF",
|
||||
"ABSTRACT_DEF",
|
||||
"TYPEDEF_DEF",
|
||||
"INTERFACE_DEF",
|
||||
"OBJECT_DECL",
|
||||
"FUNCTION",
|
||||
"FOR",
|
||||
"IF",
|
||||
"WHILE",
|
||||
"SWITCH",
|
||||
"TRY",
|
||||
"CATCH"
|
||||
],
|
||||
"option": "empty"
|
||||
},
|
||||
"type": "EmptyBlock"
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"max": 1
|
||||
},
|
||||
"type": "EmptyLines"
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"option": "lowerCase"
|
||||
},
|
||||
"type": "HexadecimalLiteral"
|
||||
},
|
||||
{
|
||||
"type": "InnerAssignment"
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"modifiers": [
|
||||
"MACRO",
|
||||
"OVERRIDE",
|
||||
"PUBLIC_PRIVATE",
|
||||
"STATIC",
|
||||
"INLINE",
|
||||
"DYNAMIC"
|
||||
]
|
||||
},
|
||||
"type": "ModifierOrder"
|
||||
},
|
||||
{
|
||||
"type": "MultipleVariableDeclarations"
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"allowSingleLineStatement": true,
|
||||
"tokens": [
|
||||
"FOR",
|
||||
"IF",
|
||||
"ELSE_IF",
|
||||
"WHILE",
|
||||
"DO_WHILE"
|
||||
]
|
||||
},
|
||||
"type": "NeedBraces"
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"assignOpPolicy": "around",
|
||||
"unaryOpPolicy": "none",
|
||||
"ternaryOpPolicy": "around",
|
||||
"arithmeticOpPolicy": "around",
|
||||
"compareOpPolicy": "around",
|
||||
"bitwiseOpPolicy": "around",
|
||||
"boolOpPolicy": "around",
|
||||
"intervalOpPolicy": "none",
|
||||
"arrowPolicy": "none",
|
||||
"oldFunctionTypePolicy": "none",
|
||||
"newFunctionTypePolicy": "none",
|
||||
"arrowFunctionPolicy": "around"
|
||||
},
|
||||
"type": "OperatorWhitespace"
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"tokens": [
|
||||
"=",
|
||||
"*",
|
||||
"/",
|
||||
"%",
|
||||
">",
|
||||
"<",
|
||||
">=",
|
||||
"<=",
|
||||
"==",
|
||||
"!=",
|
||||
"&",
|
||||
"|",
|
||||
"^",
|
||||
"<<",
|
||||
">>",
|
||||
">>>",
|
||||
"+=",
|
||||
"-=",
|
||||
"*=",
|
||||
"/=",
|
||||
"%=",
|
||||
"<<=",
|
||||
">>=",
|
||||
">>>=",
|
||||
"|=",
|
||||
"&=",
|
||||
"^=",
|
||||
"...",
|
||||
"=>",
|
||||
"++",
|
||||
"--",
|
||||
"+",
|
||||
"-",
|
||||
"&&",
|
||||
"||"
|
||||
],
|
||||
"option": "eol"
|
||||
},
|
||||
"type": "OperatorWrap"
|
||||
},
|
||||
{
|
||||
"type": "RedundantModifier"
|
||||
},
|
||||
{
|
||||
"type": "RedundantAllowMeta"
|
||||
},
|
||||
{
|
||||
"type": "RedundantAccessMeta"
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"allowEmptyReturn": true,
|
||||
"enforceReturnType": false
|
||||
},
|
||||
"type": "Return"
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"dotPolicy": "none",
|
||||
"commaPolicy": "after",
|
||||
"semicolonPolicy": "after"
|
||||
},
|
||||
"type": "SeparatorWhitespace"
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"tokens": [
|
||||
","
|
||||
],
|
||||
"option": "eol"
|
||||
},
|
||||
"type": "SeparatorWrap"
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"spaceIfCondition": "should",
|
||||
"spaceAroundBinop": true,
|
||||
"spaceForLoop": "should",
|
||||
"ignoreRangeOperator": true,
|
||||
"spaceWhileLoop": "should",
|
||||
"spaceCatch": "should",
|
||||
"spaceSwitchCase": "should",
|
||||
"noSpaceAroundUnop": true
|
||||
},
|
||||
"type": "Spacing"
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"allowException": true,
|
||||
"policy": "doubleAndInterpolation"
|
||||
},
|
||||
"type": "StringLiteral"
|
||||
},
|
||||
{
|
||||
"type": "TrailingWhitespace"
|
||||
},
|
||||
{
|
||||
"type": "UnusedImport"
|
||||
},
|
||||
{
|
||||
"type": "UnusedLocalVar"
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"tokens": [
|
||||
",",
|
||||
";",
|
||||
":"
|
||||
]
|
||||
},
|
||||
"type": "WhitespaceAfter"
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"tokens": [
|
||||
"=",
|
||||
"+",
|
||||
"-",
|
||||
"*",
|
||||
"/",
|
||||
"%",
|
||||
">",
|
||||
"<",
|
||||
">=",
|
||||
"<=",
|
||||
"==",
|
||||
"!=",
|
||||
"&",
|
||||
"|",
|
||||
"^",
|
||||
"&&",
|
||||
"||",
|
||||
"<<",
|
||||
">>",
|
||||
">>>",
|
||||
"+=",
|
||||
"-=",
|
||||
"*=",
|
||||
"/=",
|
||||
"%=",
|
||||
"<<=",
|
||||
">>=",
|
||||
">>>=",
|
||||
"|=",
|
||||
"&=",
|
||||
"^=",
|
||||
"=>"
|
||||
]
|
||||
},
|
||||
"type": "WhitespaceAround"
|
||||
}
|
||||
]
|
||||
}
|
@ -1,861 +0,0 @@
|
||||
"""Leenkx Mesh Exporter"""
|
||||
#
|
||||
# https://leenkx.com/
|
||||
#
|
||||
# Based on Open Game Engine Exchange
|
||||
# https://opengex.org/
|
||||
# Export plugin for Blender by Eric Lengyel
|
||||
# Copyright 2015, Terathon Software LLC
|
||||
#
|
||||
# This software is licensed under the Creative Commons
|
||||
# Attribution-ShareAlike 3.0 Unported License:
|
||||
# http://creativecommons.org/licenses/by-sa/3.0/deed.en_US
|
||||
|
||||
import io
|
||||
import os
|
||||
import struct
|
||||
import time
|
||||
import bpy
|
||||
from bpy_extras.io_utils import ExportHelper
|
||||
from mathutils import Vector
|
||||
import numpy as np
|
||||
|
||||
bl_info = {
|
||||
"name": "Leenkx Mesh Exporter",
|
||||
"category": "Import-Export",
|
||||
"location": "File -> Export",
|
||||
"description": "Leenkx mesh data",
|
||||
"author": "Leenkx3D.org",
|
||||
"version": (2022, 12, 0),
|
||||
"blender": (3, 3, 0),
|
||||
"doc_url": "https://github.com/leenkx3d/iron/wiki",
|
||||
"tracker_url": "https://github.com/leenkx3d/iron/issues",
|
||||
}
|
||||
|
||||
NodeTypeBone = 1
|
||||
NodeTypeMesh = 2
|
||||
structIdentifier = ["object", "bone_object", "mesh_object"]
|
||||
|
||||
|
||||
class LeenkxExporter(bpy.types.Operator, ExportHelper):
|
||||
"""Export to Leenkx format"""
|
||||
|
||||
bl_idname = "export_scene.lnx"
|
||||
bl_label = "Export Leenkx"
|
||||
filename_ext = ".lnx"
|
||||
|
||||
def execute(self, context):
|
||||
profile_time = time.time()
|
||||
current_frame = context.scene.frame_current
|
||||
current_subframe = context.scene.frame_subframe
|
||||
self.scene = context.scene
|
||||
self.output = {}
|
||||
self.bobjectArray = {}
|
||||
self.bobjectBoneArray = {}
|
||||
self.meshArray = {}
|
||||
self.boneParentArray = {}
|
||||
self.bone_tracks = []
|
||||
self.depsgraph = context.evaluated_depsgraph_get()
|
||||
scene_objects = self.scene.collection.all_objects
|
||||
|
||||
for bobject in scene_objects:
|
||||
if not bobject.parent:
|
||||
self.process_bobject(bobject)
|
||||
|
||||
self.process_skinned_meshes()
|
||||
|
||||
self.output["name"] = self.scene.name
|
||||
self.output["objects"] = []
|
||||
for bo in scene_objects:
|
||||
if not bo.parent:
|
||||
self.export_object(bo, self.scene)
|
||||
|
||||
self.output["mesh_datas"] = []
|
||||
for o in self.meshArray.items():
|
||||
self.export_mesh(o)
|
||||
|
||||
self.write_lnx(self.filepath, self.output)
|
||||
self.scene.frame_set(current_frame, subframe=current_subframe)
|
||||
|
||||
print(f"Scene exported in {str(time.time() - profile_time)}")
|
||||
|
||||
return {"FINISHED"}
|
||||
|
||||
def write_lnx(self, filepath, output):
|
||||
with open(filepath, "wb") as f:
|
||||
f.write(packb(output))
|
||||
|
||||
def write_matrix(self, matrix):
|
||||
return [
|
||||
matrix[0][0],
|
||||
matrix[0][1],
|
||||
matrix[0][2],
|
||||
matrix[0][3],
|
||||
matrix[1][0],
|
||||
matrix[1][1],
|
||||
matrix[1][2],
|
||||
matrix[1][3],
|
||||
matrix[2][0],
|
||||
matrix[2][1],
|
||||
matrix[2][2],
|
||||
matrix[2][3],
|
||||
matrix[3][0],
|
||||
matrix[3][1],
|
||||
matrix[3][2],
|
||||
matrix[3][3],
|
||||
]
|
||||
|
||||
def find_bone(self, name):
|
||||
return next(
|
||||
(
|
||||
bobject_ref
|
||||
for bobject_ref in self.bobjectBoneArray.items()
|
||||
if bobject_ref[0].name == name
|
||||
),
|
||||
None,
|
||||
)
|
||||
|
||||
def collect_bone_animation(self, armature, name):
|
||||
path = 'pose.bones["' + name + '"].'
|
||||
curve_array = []
|
||||
if armature.animation_data:
|
||||
if action := armature.animation_data.action:
|
||||
curve_array.extend(
|
||||
fcurve
|
||||
for fcurve in action.fcurves
|
||||
if fcurve.data_path.startswith(path)
|
||||
)
|
||||
return curve_array
|
||||
|
||||
def export_bone(self, armature, bone, scene, o, action):
|
||||
if bobjectRef := self.bobjectBoneArray.get(bone):
|
||||
o["type"] = structIdentifier[bobjectRef["objectType"]]
|
||||
o["name"] = bobjectRef["structName"]
|
||||
self.export_bone_transform(armature, bone, o, action)
|
||||
o["children"] = []
|
||||
for subbobject in bone.children:
|
||||
so = {}
|
||||
self.export_bone(armature, subbobject, scene, so, action)
|
||||
o["children"].append(so)
|
||||
|
||||
def export_pose_markers(self, oanim, action):
|
||||
if action.pose_markers is None or len(action.pose_markers) == 0:
|
||||
return
|
||||
oanim["marker_frames"] = []
|
||||
oanim["marker_names"] = []
|
||||
for m in action.pose_markers:
|
||||
oanim["marker_frames"].append(int(m.frame))
|
||||
oanim["marker_names"].append(m.name)
|
||||
|
||||
def process_bone(self, bone):
|
||||
self.bobjectBoneArray[bone] = {
|
||||
"objectType": NodeTypeBone,
|
||||
"structName": bone.name,
|
||||
}
|
||||
for subbobject in bone.children:
|
||||
self.process_bone(subbobject)
|
||||
|
||||
def process_bobject(self, bobject):
|
||||
if bobject.type not in ["MESH", "ARMATURE"]:
|
||||
return
|
||||
|
||||
btype = NodeTypeMesh if bobject.type == "MESH" else 0
|
||||
self.bobjectArray[bobject] = {"objectType": btype, "structName": bobject.name}
|
||||
|
||||
if bobject.type == "ARMATURE":
|
||||
if skeleton := bobject.data:
|
||||
for bone in skeleton.bones:
|
||||
if not bone.parent:
|
||||
self.process_bone(bone)
|
||||
|
||||
for subbobject in bobject.children:
|
||||
self.process_bobject(subbobject)
|
||||
|
||||
def process_skinned_meshes(self):
|
||||
for bobjectRef in self.bobjectArray.items():
|
||||
if bobjectRef[1]["objectType"] == NodeTypeMesh:
|
||||
if armature := bobjectRef[0].find_armature():
|
||||
for bone in armature.data.bones:
|
||||
boneRef = self.find_bone(bone.name)
|
||||
if boneRef:
|
||||
boneRef[1]["objectType"] = NodeTypeBone
|
||||
|
||||
def export_bone_transform(self, armature, bone, o, action):
|
||||
pose_bone = armature.pose.bones.get(bone.name)
|
||||
transform = bone.matrix_local.copy()
|
||||
if bone.parent is not None:
|
||||
transform = bone.parent.matrix_local.inverted_safe() @ transform
|
||||
|
||||
o["transform"] = {}
|
||||
o["transform"]["values"] = self.write_matrix(transform)
|
||||
|
||||
curve_array = self.collect_bone_animation(armature, bone.name)
|
||||
animation = len(curve_array) != 0
|
||||
|
||||
if animation and pose_bone:
|
||||
begin_frame = int(action.frame_range[0])
|
||||
end_frame = int(action.frame_range[1])
|
||||
tracko = {}
|
||||
o["anim"] = {"tracks": [tracko]}
|
||||
tracko["target"] = "transform"
|
||||
tracko["frames"] = [
|
||||
i - begin_frame for i in range(begin_frame, end_frame + 1)
|
||||
]
|
||||
tracko["values"] = []
|
||||
self.bone_tracks.append((tracko["values"], pose_bone))
|
||||
|
||||
def write_bone_matrices(self, scene, action):
|
||||
if len(self.bone_tracks) > 0:
|
||||
begin_frame = int(action.frame_range[0])
|
||||
end_frame = int(action.frame_range[1])
|
||||
for i in range(begin_frame, end_frame + 1):
|
||||
scene.frame_set(i)
|
||||
for track in self.bone_tracks:
|
||||
values, pose_bone = track[0], track[1]
|
||||
if parent := pose_bone.parent:
|
||||
values += self.write_matrix(
|
||||
(parent.matrix.inverted_safe() @ pose_bone.matrix)
|
||||
)
|
||||
else:
|
||||
values += self.write_matrix(pose_bone.matrix)
|
||||
|
||||
def export_object(self, bobject, scene, parento=None):
|
||||
if bobjectRef := self.bobjectArray.get(bobject):
|
||||
o = {
|
||||
"type": structIdentifier[bobjectRef["objectType"]],
|
||||
"name": bobjectRef["structName"],
|
||||
}
|
||||
if bobject.parent_type == "BONE":
|
||||
o["parent_bone"] = bobject.parent_bone
|
||||
|
||||
if bobjectRef["objectType"] == NodeTypeMesh:
|
||||
objref = bobject.data
|
||||
if objref not in self.meshArray:
|
||||
self.meshArray[objref] = {
|
||||
"structName": objref.name,
|
||||
"objectTable": [bobject],
|
||||
}
|
||||
else:
|
||||
self.meshArray[objref]["objectTable"].append(bobject)
|
||||
oid = self.meshArray[objref]["structName"]
|
||||
o["data_ref"] = oid
|
||||
o["dimensions"] = self.calc_aabb(bobject)
|
||||
|
||||
o["transform"] = {}
|
||||
o["transform"]["values"] = self.write_matrix(bobject.matrix_local)
|
||||
|
||||
# If the object is parented to a bone and is not relative, undo the
|
||||
# bone's transform
|
||||
if bobject.parent_type == "BONE":
|
||||
armature = bobject.parent.data
|
||||
bone = armature.bones[bobject.parent_bone]
|
||||
o["parent_bone_connected"] = bone.use_connect
|
||||
if bone.use_connect:
|
||||
bone_translation = Vector((0, bone.length, 0)) + bone.head
|
||||
o["parent_bone_tail"] = [
|
||||
bone_translation[0],
|
||||
bone_translation[1],
|
||||
bone_translation[2],
|
||||
]
|
||||
else:
|
||||
bone_translation = bone.tail - bone.head
|
||||
o["parent_bone_tail"] = [
|
||||
bone_translation[0],
|
||||
bone_translation[1],
|
||||
bone_translation[2],
|
||||
]
|
||||
pose_bone = bobject.parent.pose.bones[bobject.parent_bone]
|
||||
bone_translation_pose = pose_bone.tail - pose_bone.head
|
||||
o["parent_bone_tail_pose"] = [
|
||||
bone_translation_pose[0],
|
||||
bone_translation_pose[1],
|
||||
bone_translation_pose[2],
|
||||
]
|
||||
|
||||
if bobject.type == "ARMATURE" and bobject.data is not None:
|
||||
bdata = bobject.data
|
||||
action = None
|
||||
adata = bobject.animation_data
|
||||
|
||||
# Active action
|
||||
if adata is not None:
|
||||
action = adata.action
|
||||
if action is None:
|
||||
bobject.animation_data_create()
|
||||
actions = bpy.data.actions
|
||||
action = actions.get("leenkx_pose")
|
||||
if action is None:
|
||||
action = actions.new(name="leenkx_pose")
|
||||
|
||||
# Collect export actions
|
||||
export_actions = [action]
|
||||
if hasattr(adata, "nla_tracks") and adata.nla_tracks is not None:
|
||||
for track in adata.nla_tracks:
|
||||
if track.strips is None:
|
||||
continue
|
||||
for strip in track.strips:
|
||||
if strip.action is None:
|
||||
continue
|
||||
if strip.action.name == action.name:
|
||||
continue
|
||||
export_actions.append(strip.action)
|
||||
|
||||
basename = os.path.basename(self.filepath)[:-4]
|
||||
o["bone_actions"] = []
|
||||
for action in export_actions:
|
||||
o["bone_actions"].append(basename + "_" + action.name)
|
||||
|
||||
orig_action = bobject.animation_data.action
|
||||
for action in export_actions:
|
||||
bobject.animation_data.action = action
|
||||
bones = []
|
||||
self.bone_tracks = []
|
||||
for bone in bdata.bones:
|
||||
if not bone.parent:
|
||||
boneo = {}
|
||||
self.export_bone(bobject, bone, scene, boneo, action)
|
||||
bones.append(boneo)
|
||||
self.write_bone_matrices(scene, action)
|
||||
if len(bones) > 0 and "anim" in bones[0]:
|
||||
self.export_pose_markers(bones[0]["anim"], action)
|
||||
# Save action separately
|
||||
action_obj = {}
|
||||
action_obj["name"] = action.name
|
||||
action_obj["objects"] = bones
|
||||
self.write_lnx(
|
||||
self.filepath[:-4] + "_" + action.name + ".lnx", action_obj
|
||||
)
|
||||
|
||||
bobject.animation_data.action = orig_action
|
||||
|
||||
if parento is None:
|
||||
self.output["objects"].append(o)
|
||||
else:
|
||||
parento["children"].append(o)
|
||||
|
||||
if not hasattr(o, "children") and len(bobject.children) > 0:
|
||||
o["children"] = []
|
||||
|
||||
for subbobject in bobject.children:
|
||||
self.export_object(subbobject, scene, o)
|
||||
|
||||
def export_skin(self, bobject, armature, exportMesh, o):
|
||||
# This function exports all skinning data, which includes the skeleton
|
||||
# and per-vertex bone influence data
|
||||
oskin = {}
|
||||
o["skin"] = oskin
|
||||
|
||||
# Write the skin bind pose transform
|
||||
otrans = {}
|
||||
oskin["transform"] = otrans
|
||||
otrans["values"] = self.write_matrix(bobject.matrix_world)
|
||||
|
||||
bone_array = armature.data.bones
|
||||
bone_count = len(bone_array)
|
||||
max_bones = 128
|
||||
bone_count = min(bone_count, max_bones)
|
||||
|
||||
# Write the bone object reference array
|
||||
oskin["bone_ref_array"] = np.empty(bone_count, dtype=object)
|
||||
oskin["bone_len_array"] = np.empty(bone_count, dtype="<f4")
|
||||
|
||||
for i in range(bone_count):
|
||||
if boneRef := self.find_bone(bone_array[i].name):
|
||||
oskin["bone_ref_array"][i] = boneRef[1]["structName"]
|
||||
oskin["bone_len_array"][i] = bone_array[i].length
|
||||
else:
|
||||
oskin["bone_ref_array"][i] = ""
|
||||
oskin["bone_len_array"][i] = 0.0
|
||||
|
||||
# Write the bind pose transform array
|
||||
oskin["transformsI"] = []
|
||||
for i in range(bone_count):
|
||||
skeletonI = (
|
||||
armature.matrix_world @ bone_array[i].matrix_local
|
||||
).inverted_safe()
|
||||
skeletonI = skeletonI @ bobject.matrix_world
|
||||
oskin["transformsI"].append(self.write_matrix(skeletonI))
|
||||
|
||||
# Export the per-vertex bone influence data
|
||||
group_remap = []
|
||||
for group in bobject.vertex_groups:
|
||||
for i in range(bone_count):
|
||||
if bone_array[i].name == group.name:
|
||||
group_remap.append(i)
|
||||
break
|
||||
else:
|
||||
group_remap.append(-1)
|
||||
|
||||
bone_count_array = np.empty(len(exportMesh.loops), dtype="<i2")
|
||||
bone_index_array = np.empty(len(exportMesh.loops) * 4, dtype="<i2")
|
||||
bone_weight_array = np.empty(len(exportMesh.loops) * 4, dtype="<f4")
|
||||
|
||||
vertices = bobject.data.vertices
|
||||
count = 0
|
||||
for index, l in enumerate(exportMesh.loops):
|
||||
bone_count = 0
|
||||
total_weight = 0.0
|
||||
bone_values = []
|
||||
for g in vertices[l.vertex_index].groups:
|
||||
bone_index = group_remap[g.group]
|
||||
bone_weight = g.weight
|
||||
if bone_index >= 0: # and bone_weight != 0.0:
|
||||
bone_values.append((bone_weight, bone_index))
|
||||
total_weight += bone_weight
|
||||
bone_count += 1
|
||||
|
||||
if bone_count > 4:
|
||||
bone_count = 4
|
||||
bone_values.sort(reverse=True)
|
||||
bone_values = bone_values[:4]
|
||||
|
||||
bone_count_array[index] = bone_count
|
||||
for bv in bone_values:
|
||||
bone_weight_array[count] = bv[0]
|
||||
bone_index_array[count] = bv[1]
|
||||
count += 1
|
||||
|
||||
if total_weight not in (0.0, 1.0):
|
||||
normalizer = 1.0 / total_weight
|
||||
for i in range(bone_count):
|
||||
bone_weight_array[count - i - 1] *= normalizer
|
||||
|
||||
bone_index_array = bone_index_array[:count]
|
||||
bone_weight_array = bone_weight_array[:count]
|
||||
bone_weight_array *= 32767
|
||||
bone_weight_array = np.array(bone_weight_array, dtype="<i2")
|
||||
|
||||
oskin["bone_count_array"] = bone_count_array
|
||||
oskin["bone_index_array"] = bone_index_array
|
||||
oskin["bone_weight_array"] = bone_weight_array
|
||||
|
||||
def calc_aabb(self, bobject):
|
||||
aabb_center = 0.125 * sum((Vector(b) for b in bobject.bound_box), Vector())
|
||||
return [
|
||||
abs(
|
||||
(bobject.bound_box[6][0] - bobject.bound_box[0][0]) / 2
|
||||
+ abs(aabb_center[0])
|
||||
)
|
||||
* 2,
|
||||
abs(
|
||||
(bobject.bound_box[6][1] - bobject.bound_box[0][1]) / 2
|
||||
+ abs(aabb_center[1])
|
||||
)
|
||||
* 2,
|
||||
abs(
|
||||
(bobject.bound_box[6][2] - bobject.bound_box[0][2]) / 2
|
||||
+ abs(aabb_center[2])
|
||||
)
|
||||
* 2,
|
||||
]
|
||||
|
||||
def export_mesh_data(self, exportMesh, bobject, o, has_armature=False):
|
||||
exportMesh.calc_normals_split()
|
||||
exportMesh.calc_loop_triangles()
|
||||
|
||||
loops = exportMesh.loops
|
||||
num_verts = len(loops)
|
||||
num_uv_layers = len(exportMesh.uv_layers)
|
||||
num_colors = len(exportMesh.vertex_colors)
|
||||
has_tex = num_uv_layers > 0
|
||||
has_tex1 = num_uv_layers > 1
|
||||
has_col = num_colors > 0
|
||||
has_tang = False
|
||||
|
||||
pdata = np.empty(num_verts * 4, dtype="<f4") # p.xyz, n.z
|
||||
ndata = np.empty(num_verts * 2, dtype="<f4") # n.xy
|
||||
if has_tex:
|
||||
t0map = 0 # Get active uvmap
|
||||
t0data = np.empty(num_verts * 2, dtype="<f4")
|
||||
uv_layers = exportMesh.uv_layers
|
||||
if uv_layers is not None:
|
||||
for i in range(0, len(uv_layers)):
|
||||
if uv_layers[i].active_render:
|
||||
t0map = i
|
||||
break
|
||||
if has_tex1:
|
||||
t1map = 1 if t0map == 0 else 0
|
||||
t1data = np.empty(num_verts * 2, dtype="<f4")
|
||||
# Scale for packed coords
|
||||
maxdim = 1.0
|
||||
lay0 = uv_layers[t0map]
|
||||
for v in lay0.data:
|
||||
if abs(v.uv[0]) > maxdim:
|
||||
maxdim = abs(v.uv[0])
|
||||
if abs(v.uv[1]) > maxdim:
|
||||
maxdim = abs(v.uv[1])
|
||||
if has_tex1:
|
||||
lay1 = uv_layers[t1map]
|
||||
for v in lay1.data:
|
||||
if abs(v.uv[0]) > maxdim:
|
||||
maxdim = abs(v.uv[0])
|
||||
if abs(v.uv[1]) > maxdim:
|
||||
maxdim = abs(v.uv[1])
|
||||
if maxdim > 1:
|
||||
o["scale_tex"] = maxdim
|
||||
invscale_tex = (1 / o["scale_tex"]) * 32767
|
||||
else:
|
||||
invscale_tex = 1 * 32767
|
||||
if has_tang:
|
||||
exportMesh.calc_tangents(uvmap=lay0.name)
|
||||
tangdata = np.empty(num_verts * 3, dtype="<f4")
|
||||
if has_col:
|
||||
cdata = np.empty(num_verts * 3, dtype="<f4")
|
||||
|
||||
# Scale for packed coords
|
||||
aabb = self.calc_aabb(bobject)
|
||||
maxdim = max(aabb[0], max(aabb[1], aabb[2]))
|
||||
if maxdim > 2:
|
||||
o["scale_pos"] = maxdim / 2
|
||||
else:
|
||||
o["scale_pos"] = 1.0
|
||||
if has_armature: # Allow up to 2x bigger bounds for skinned mesh
|
||||
o["scale_pos"] *= 2.0
|
||||
|
||||
scale_pos = o["scale_pos"]
|
||||
invscale_pos = (1 / scale_pos) * 32767
|
||||
|
||||
verts = exportMesh.vertices
|
||||
if has_tex:
|
||||
lay0 = exportMesh.uv_layers[t0map]
|
||||
if has_tex1:
|
||||
lay1 = exportMesh.uv_layers[t1map]
|
||||
if has_col:
|
||||
vcol0 = exportMesh.vertex_colors[0].data
|
||||
|
||||
for i, loop in enumerate(loops):
|
||||
v = verts[loop.vertex_index]
|
||||
co = v.co
|
||||
normal = loop.normal
|
||||
tang = loop.tangent
|
||||
|
||||
i4 = i * 4
|
||||
i2 = i * 2
|
||||
pdata[i4] = co[0]
|
||||
pdata[i4 + 1] = co[1]
|
||||
pdata[i4 + 2] = co[2]
|
||||
pdata[i4 + 3] = normal[2] * scale_pos # Cancel scale
|
||||
ndata[i2] = normal[0]
|
||||
ndata[i2 + 1] = normal[1]
|
||||
if has_tex:
|
||||
uv = lay0.data[loop.index].uv
|
||||
t0data[i2] = uv[0]
|
||||
t0data[i2 + 1] = 1.0 - uv[1] # Reverse Y
|
||||
if has_tex1:
|
||||
uv = lay1.data[loop.index].uv
|
||||
t1data[i2] = uv[0]
|
||||
t1data[i2 + 1] = 1.0 - uv[1]
|
||||
if has_tang:
|
||||
i3 = i * 3
|
||||
tangdata[i3] = tang[0]
|
||||
tangdata[i3 + 1] = tang[1]
|
||||
tangdata[i3 + 2] = tang[2]
|
||||
if has_col:
|
||||
col = vcol0[loop.index].color
|
||||
i3 = i * 3
|
||||
cdata[i3] = col[0]
|
||||
cdata[i3 + 1] = col[1]
|
||||
cdata[i3 + 2] = col[2]
|
||||
|
||||
mats = exportMesh.materials
|
||||
poly_map = []
|
||||
for i in range(max(len(mats), 1)):
|
||||
poly_map.append([])
|
||||
for poly in exportMesh.polygons:
|
||||
poly_map[poly.material_index].append(poly)
|
||||
|
||||
o["index_arrays"] = []
|
||||
|
||||
# map polygon indices to triangle loops
|
||||
tri_loops = {}
|
||||
for loop in exportMesh.loop_triangles:
|
||||
if loop.polygon_index not in tri_loops:
|
||||
tri_loops[loop.polygon_index] = []
|
||||
tri_loops[loop.polygon_index].append(loop)
|
||||
|
||||
for index, polys in enumerate(poly_map):
|
||||
tris = 0
|
||||
for poly in polys:
|
||||
tris += poly.loop_total - 2
|
||||
if tris == 0: # No face assigned
|
||||
continue
|
||||
prim = np.empty(tris * 3, dtype="<i4")
|
||||
|
||||
i = 0
|
||||
for poly in polys:
|
||||
for loop in tri_loops[poly.index]:
|
||||
prim[i] = loops[loop.loops[0]].index
|
||||
prim[i + 1] = loops[loop.loops[1]].index
|
||||
prim[i + 2] = loops[loop.loops[2]].index
|
||||
i += 3
|
||||
|
||||
ia = {}
|
||||
ia["values"] = prim
|
||||
ia["material"] = 0
|
||||
if len(mats) > 1:
|
||||
for i in range(len(mats)): # Multi-mat mesh
|
||||
if mats[i] == mats[index]: # Default material for empty slots
|
||||
ia["material"] = i
|
||||
break
|
||||
o["index_arrays"].append(ia)
|
||||
|
||||
# Pack
|
||||
pdata *= invscale_pos
|
||||
ndata *= 32767
|
||||
pdata = np.array(pdata, dtype="<i2")
|
||||
ndata = np.array(ndata, dtype="<i2")
|
||||
if has_tex:
|
||||
t0data *= invscale_tex
|
||||
t0data = np.array(t0data, dtype="<i2")
|
||||
if has_tex1:
|
||||
t1data *= invscale_tex
|
||||
t1data = np.array(t1data, dtype="<i2")
|
||||
if has_col:
|
||||
cdata *= 32767
|
||||
cdata = np.array(cdata, dtype="<i2")
|
||||
if has_tang:
|
||||
tangdata *= 32767
|
||||
tangdata = np.array(tangdata, dtype="<i2")
|
||||
|
||||
# Output
|
||||
o["vertex_arrays"] = []
|
||||
o["vertex_arrays"].append(
|
||||
{"attrib": "pos", "values": pdata, "data": "short4norm"}
|
||||
)
|
||||
o["vertex_arrays"].append(
|
||||
{"attrib": "nor", "values": ndata, "data": "short2norm"}
|
||||
)
|
||||
if has_tex:
|
||||
o["vertex_arrays"].append(
|
||||
{"attrib": "tex", "values": t0data, "data": "short2norm"}
|
||||
)
|
||||
if has_tex1:
|
||||
o["vertex_arrays"].append(
|
||||
{"attrib": "tex1", "values": t1data, "data": "short2norm"}
|
||||
)
|
||||
if has_col:
|
||||
o["vertex_arrays"].append(
|
||||
{"attrib": "col", "values": cdata, "data": "short4norm", "padding": 1}
|
||||
)
|
||||
if has_tang:
|
||||
o["vertex_arrays"].append(
|
||||
{
|
||||
"attrib": "tang",
|
||||
"values": tangdata,
|
||||
"data": "short4norm",
|
||||
"padding": 1,
|
||||
}
|
||||
)
|
||||
|
||||
def export_mesh(self, objectRef):
|
||||
# This function exports a single mesh object
|
||||
table = objectRef[1]["objectTable"]
|
||||
bobject = table[0]
|
||||
oid = objectRef[1]["structName"]
|
||||
o = {}
|
||||
o["name"] = oid
|
||||
|
||||
armature = bobject.find_armature()
|
||||
apply_modifiers = not armature
|
||||
|
||||
bobject_eval = (
|
||||
bobject.evaluated_get(self.depsgraph) if apply_modifiers else bobject
|
||||
)
|
||||
exportMesh = bobject_eval.to_mesh()
|
||||
|
||||
self.export_mesh_data(exportMesh, bobject, o, has_armature=armature is not None)
|
||||
if armature:
|
||||
self.export_skin(bobject, armature, exportMesh, o)
|
||||
|
||||
self.output["mesh_datas"].append(o)
|
||||
bobject_eval.to_mesh_clear()
|
||||
|
||||
|
||||
def menu_func(self, context):
|
||||
self.layout.operator(LeenkxExporter.bl_idname, text="Leenkx (.lnx)")
|
||||
|
||||
|
||||
def register():
|
||||
bpy.utils.register_class(LeenkxExporter)
|
||||
bpy.types.TOPBAR_MT_file_export.append(menu_func)
|
||||
|
||||
|
||||
def unregister():
|
||||
bpy.types.TOPBAR_MT_file_export.remove(menu_func)
|
||||
bpy.utils.unregister_class(LeenkxExporter)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
register()
|
||||
|
||||
# Msgpack parser with typed arrays
|
||||
# Based on u-msgpack-python v2.4.1 - v at sergeev.io
|
||||
# https://github.com/vsergeev/u-msgpack-python
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
#
|
||||
|
||||
|
||||
def _pack_integer(obj, fp):
|
||||
if obj < 0:
|
||||
if obj >= -32:
|
||||
fp.write(struct.pack("b", obj))
|
||||
elif obj >= -(2 ** (8 - 1)):
|
||||
fp.write(b"\xd0" + struct.pack("b", obj))
|
||||
elif obj >= -(2 ** (16 - 1)):
|
||||
fp.write(b"\xd1" + struct.pack("<h", obj))
|
||||
elif obj >= -(2 ** (32 - 1)):
|
||||
fp.write(b"\xd2" + struct.pack("<i", obj))
|
||||
elif obj >= -(2 ** (64 - 1)):
|
||||
fp.write(b"\xd3" + struct.pack("<q", obj))
|
||||
else:
|
||||
raise Exception("huge signed int")
|
||||
else:
|
||||
if obj <= 127:
|
||||
fp.write(struct.pack("B", obj))
|
||||
elif obj <= 2**8 - 1:
|
||||
fp.write(b"\xcc" + struct.pack("B", obj))
|
||||
elif obj <= 2**16 - 1:
|
||||
fp.write(b"\xcd" + struct.pack("<H", obj))
|
||||
elif obj <= 2**32 - 1:
|
||||
fp.write(b"\xce" + struct.pack("<I", obj))
|
||||
elif obj <= 2**64 - 1:
|
||||
fp.write(b"\xcf" + struct.pack("<Q", obj))
|
||||
else:
|
||||
raise Exception("huge unsigned int")
|
||||
|
||||
|
||||
def _pack_nil(fp):
|
||||
fp.write(b"\xc0")
|
||||
|
||||
|
||||
def _pack_boolean(obj, fp):
|
||||
fp.write(b"\xc3" if obj else b"\xc2")
|
||||
|
||||
|
||||
def _pack_float(obj, fp):
|
||||
# NOTE: forced 32-bit floats for Leenkx
|
||||
# fp.write(b"\xcb" + struct.pack("<d", obj)) # Double
|
||||
fp.write(b"\xca" + struct.pack("<f", obj))
|
||||
|
||||
|
||||
def _pack_string(obj, fp):
|
||||
obj = obj.encode("utf-8")
|
||||
if len(obj) <= 31:
|
||||
fp.write(struct.pack("B", 0xA0 | len(obj)) + obj)
|
||||
elif len(obj) <= 2**8 - 1:
|
||||
fp.write(b"\xd9" + struct.pack("B", len(obj)) + obj)
|
||||
elif len(obj) <= 2**16 - 1:
|
||||
fp.write(b"\xda" + struct.pack("<H", len(obj)) + obj)
|
||||
elif len(obj) <= 2**32 - 1:
|
||||
fp.write(b"\xdb" + struct.pack("<I", len(obj)) + obj)
|
||||
else:
|
||||
raise Exception("huge string")
|
||||
|
||||
|
||||
def _pack_binary(obj, fp):
|
||||
if len(obj) <= 2**8 - 1:
|
||||
fp.write(b"\xc4" + struct.pack("B", len(obj)) + obj)
|
||||
elif len(obj) <= 2**16 - 1:
|
||||
fp.write(b"\xc5" + struct.pack("<H", len(obj)) + obj)
|
||||
elif len(obj) <= 2**32 - 1:
|
||||
fp.write(b"\xc6" + struct.pack("<I", len(obj)) + obj)
|
||||
else:
|
||||
raise Exception("huge binary string")
|
||||
|
||||
|
||||
def _pack_array(obj, fp):
|
||||
if len(obj) <= 15:
|
||||
fp.write(struct.pack("B", 0x90 | len(obj)))
|
||||
elif len(obj) <= 2**16 - 1:
|
||||
fp.write(b"\xdc" + struct.pack("<H", len(obj)))
|
||||
elif len(obj) <= 2**32 - 1:
|
||||
fp.write(b"\xdd" + struct.pack("<I", len(obj)))
|
||||
else:
|
||||
raise Exception("huge array")
|
||||
|
||||
if len(obj) > 0 and isinstance(obj[0], float):
|
||||
fp.write(b"\xca")
|
||||
for e in obj:
|
||||
fp.write(struct.pack("<f", e))
|
||||
elif len(obj) > 0 and isinstance(obj[0], bool):
|
||||
for e in obj:
|
||||
pack(e, fp)
|
||||
elif len(obj) > 0 and isinstance(obj[0], int):
|
||||
fp.write(b"\xd2")
|
||||
for e in obj:
|
||||
fp.write(struct.pack("<i", e))
|
||||
# Float32
|
||||
elif len(obj) > 0 and isinstance(obj[0], np.float32):
|
||||
fp.write(b"\xca")
|
||||
fp.write(obj.tobytes())
|
||||
# Int32
|
||||
elif len(obj) > 0 and isinstance(obj[0], np.int32):
|
||||
fp.write(b"\xd2")
|
||||
fp.write(obj.tobytes())
|
||||
# Int16
|
||||
elif len(obj) > 0 and isinstance(obj[0], np.int16):
|
||||
fp.write(b"\xd1")
|
||||
fp.write(obj.tobytes())
|
||||
# Regular
|
||||
else:
|
||||
for e in obj:
|
||||
pack(e, fp)
|
||||
|
||||
|
||||
def _pack_map(obj, fp):
|
||||
if len(obj) <= 15:
|
||||
fp.write(struct.pack("B", 0x80 | len(obj)))
|
||||
elif len(obj) <= 2**16 - 1:
|
||||
fp.write(b"\xde" + struct.pack("<H", len(obj)))
|
||||
elif len(obj) <= 2**32 - 1:
|
||||
fp.write(b"\xdf" + struct.pack("<I", len(obj)))
|
||||
else:
|
||||
raise Exception("huge array")
|
||||
|
||||
for k, v in obj.items():
|
||||
pack(k, fp)
|
||||
pack(v, fp)
|
||||
|
||||
|
||||
def pack(obj, fp):
|
||||
if obj is None:
|
||||
_pack_nil(fp)
|
||||
elif isinstance(obj, bool):
|
||||
_pack_boolean(obj, fp)
|
||||
elif isinstance(obj, int):
|
||||
_pack_integer(obj, fp)
|
||||
elif isinstance(obj, float):
|
||||
_pack_float(obj, fp)
|
||||
elif isinstance(obj, str):
|
||||
_pack_string(obj, fp)
|
||||
elif isinstance(obj, bytes):
|
||||
_pack_binary(obj, fp)
|
||||
elif isinstance(obj, (list, np.ndarray, tuple)):
|
||||
_pack_array(obj, fp)
|
||||
elif isinstance(obj, dict):
|
||||
_pack_map(obj, fp)
|
||||
else:
|
||||
raise Exception(f"unsupported type: {str(type(obj))}")
|
||||
|
||||
|
||||
def packb(obj):
|
||||
fp = io.BytesIO()
|
||||
pack(obj, fp)
|
||||
return fp.getvalue()
|
@ -2,9 +2,11 @@ package leenkx.logicnode;
|
||||
|
||||
import iron.object.Object;
|
||||
|
||||
#if lnx_physics
|
||||
#if lnx_bullet
|
||||
import leenkx.trait.physics.PhysicsConstraint;
|
||||
import leenkx.trait.physics.bullet.PhysicsConstraint.ConstraintType;
|
||||
#elseif lnx_oimo
|
||||
// TODO
|
||||
#end
|
||||
|
||||
class AddPhysicsConstraintNode extends LogicNode {
|
||||
@ -25,7 +27,7 @@ class AddPhysicsConstraintNode extends LogicNode {
|
||||
|
||||
if (pivotObject == null || rb1 == null || rb2 == null) return;
|
||||
|
||||
#if lnx_physics
|
||||
#if lnx_bullet
|
||||
|
||||
var disableCollisions: Bool = inputs[4].get();
|
||||
var breakable: Bool = inputs[5].get();
|
||||
@ -108,6 +110,8 @@ class AddPhysicsConstraintNode extends LogicNode {
|
||||
}
|
||||
pivotObject.addTrait(con);
|
||||
}
|
||||
#elseif lnx_oimo
|
||||
// TODO
|
||||
#end
|
||||
runOutput(0);
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import iron.object.Object;
|
||||
|
||||
#if lnx_physics
|
||||
import leenkx.trait.physics.RigidBody;
|
||||
import leenkx.trait.physics.bullet.RigidBody.Shape;
|
||||
import leenkx.trait.physics.RigidBody.Shape;
|
||||
#end
|
||||
|
||||
|
||||
|
@ -21,7 +21,7 @@ class ApplyForceNode extends LogicNode {
|
||||
|
||||
#if lnx_physics
|
||||
var rb: RigidBody = object.getTrait(RigidBody);
|
||||
|
||||
if (rb == null) return;
|
||||
!local ? rb.applyForce(force) : rb.applyForce(object.transform.worldVecToOrientation(force));
|
||||
#end
|
||||
|
||||
|
26
leenkx/Sources/leenkx/logicnode/ArrayIndexListNode.hx
Normal file
@ -0,0 +1,26 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
class ArrayIndexListNode extends LogicNode {
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function get(from: Int): Dynamic {
|
||||
var array: Array<Dynamic> = inputs[0].get();
|
||||
array = array.map(item -> Std.string(item));
|
||||
var value: Dynamic = inputs[1].get();
|
||||
var from: Int = 0;
|
||||
|
||||
var arrayList: Array<Int> = [];
|
||||
|
||||
var index: Int = array.indexOf(Std.string(value), from);
|
||||
|
||||
while(index != -1){
|
||||
arrayList.push(index);
|
||||
index = array.indexOf(Std.string(value), index+1);
|
||||
}
|
||||
|
||||
return arrayList;
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
package leenkx.logicnode;
|
||||
import aura.Aura;
|
||||
import aura.Types;
|
||||
import aura.types.HRTFData;
|
||||
import aura.types.HRTF;
|
||||
import aura.dsp.panner.HRTFPanner;
|
||||
|
||||
class AudioHRTFPannerNode extends LogicNode {
|
||||
|
@ -1,7 +1,6 @@
|
||||
package leenkx.logicnode;
|
||||
import iron.data.Data;
|
||||
import aura.Aura;
|
||||
import aura.Assets;
|
||||
|
||||
class AudioLoadNode extends LogicNode {
|
||||
public var property1: String;
|
||||
@ -25,53 +24,18 @@ class AudioLoadNode extends LogicNode {
|
||||
return null;
|
||||
}
|
||||
|
||||
//var sound = aura.Assets.Sound(name, Uncompress);
|
||||
//var anotherSound = aura.Assets.Sound("AnotherSoundFile", KeepCompressed);
|
||||
//var hrtf = aura.Assets.HRTF("myHRTF_mhr");
|
||||
|
||||
//var loadConfig: AuraLoadConfig = {
|
||||
// uncompressed: [name],
|
||||
// compressed: [name],
|
||||
// hrtf: ["myHRTF_mhr"],
|
||||
//};
|
||||
|
||||
|
||||
Data.getSound(name, function (data) {
|
||||
//audio = Aura.createUncompBufferChannel(data,inputs[2].get(),Aura.mixChannels[inputs[0].get()]);
|
||||
var assetList = [
|
||||
data,
|
||||
//anotherSound,
|
||||
//hrtf,
|
||||
];
|
||||
|
||||
aura.Assets.startLoading(assetList,
|
||||
|
||||
(asset: aura.Assets.Asset, numLoaded: Int, numTotalAssets: Int) -> {
|
||||
trace('Loaded $numLoadedAssets of $totalNumAssets: ${asset.name}');
|
||||
audio = Aura.createUncompBufferChannel(asset,inputs[2].get(),Aura.mixChannels[inputs[0].get()]);
|
||||
if (numLoaded == totalNumAssets) {
|
||||
trace("Loaded all assets");
|
||||
}
|
||||
},
|
||||
|
||||
(asset: aura.Assets.Asset, error: kha.AssetError) -> {
|
||||
trace('Failed to load asset ${asset.name}. Reason: $error');
|
||||
return AbortLoading;
|
||||
}
|
||||
);
|
||||
|
||||
audio = Aura.createUncompBufferChannel(data,inputs[2].get(),Aura.mixChannels[inputs[0].get()]);
|
||||
});
|
||||
|
||||
|
||||
|
||||
//Data.getSound(name, function (data) {
|
||||
// audio = Aura.createUncompBufferChannel(data,inputs[2].get(),Aura.mixChannels[inputs[0].get()]);
|
||||
//});
|
||||
|
||||
return audio;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
In addition to the above change:
|
||||
- `aura.types.HRTF` was renamed to `aura.types.HRTFData`
|
||||
- `aura.dsp.panner.HRTFPanner.new()` now expects an `aura.Assets.HRTF` object instead of an `aura.types.HRTFData` object as its second parameter
|
||||
- `Aura.getSound()` now returns `Null<aura.Assets.Sound>` instead of `Null<kha.Sound>`
|
||||
- `Aura.getHRTF()` now returns `Null<aura.Assets.HRTF>` instead of `Null<aura.types.HRTFData>`
|
||||
- `Aura.createUncompBufferChannel()` and `Aura.createCompBufferChannel()` now take an `aura.Assets.Sound` as their first parameter instead of a `kha.Sound`
|
@ -26,10 +26,9 @@ class GetBoneTransformNode extends LogicNode {
|
||||
// Get bone in armature
|
||||
var bone = anim.getBone(boneName);
|
||||
|
||||
//return anim.getAbsWorldMat(bone);
|
||||
return anim.getAbsMat(bone).clone().multmat(object.transform.world);
|
||||
//return anim.getAbsWorldMat(bone);
|
||||
|
||||
return anim.getAbsWorldMat(anim.skeletonMats, bone);
|
||||
//return anim.getAbsMat(bone).clone().multmat(object.transform.world);
|
||||
|
||||
#else
|
||||
return null;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
#if lnx_physics
|
||||
import leenkx.trait.physics.bullet.PhysicsWorld;
|
||||
import leenkx.trait.physics.PhysicsWorld;
|
||||
#end
|
||||
import leenkx.trait.navigation.Navigation;
|
||||
import iron.object.Object;
|
||||
|
@ -1,7 +1,7 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
#if lnx_audio
|
||||
import iron.object.SpeakerObject;
|
||||
|
||||
#end
|
||||
class PauseSoundNode extends LogicNode {
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
@ -9,9 +9,11 @@ class PauseSoundNode extends LogicNode {
|
||||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
#if lnx_audio
|
||||
var object: SpeakerObject = cast(inputs[1].get(), SpeakerObject);
|
||||
if (object == null) return;
|
||||
object.pause();
|
||||
#end
|
||||
runOutput(0);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
#if lnx_physics
|
||||
import leenkx.trait.physics.bullet.PhysicsConstraint.ConstraintAxis;
|
||||
import leenkx.trait.physics.PhysicsConstraint.ConstraintAxis;
|
||||
#end
|
||||
|
||||
class PhysicsConstraintNode extends LogicNode {
|
||||
|
@ -1,7 +1,7 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
#if lnx_audio
|
||||
import iron.object.SpeakerObject;
|
||||
|
||||
#end
|
||||
class PlaySoundNode extends LogicNode {
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
@ -9,9 +9,11 @@ class PlaySoundNode extends LogicNode {
|
||||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
#if lnx_audio
|
||||
var object: SpeakerObject = cast(inputs[1].get(), SpeakerObject);
|
||||
if (object == null) return;
|
||||
object.play();
|
||||
#end
|
||||
runOutput(0);
|
||||
}
|
||||
}
|
||||
|
@ -16,15 +16,16 @@ class PlaySoundRawNode extends LogicNode {
|
||||
public var property5: Bool;
|
||||
|
||||
public var property6: String;
|
||||
|
||||
#if lnx_audio
|
||||
var sound: kha.Sound = null;
|
||||
var channel: kha.audio1.AudioChannel = null;
|
||||
|
||||
#end
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
#if lnx_audio
|
||||
switch (from) {
|
||||
case Play:
|
||||
if (property6 == 'Sound' ? sound == null : true) {
|
||||
@ -63,6 +64,10 @@ class PlaySoundRawNode extends LogicNode {
|
||||
case UpdateVolume:
|
||||
if (channel != null) channel.volume = inputs[4].get();
|
||||
}
|
||||
#end
|
||||
#if !lnx_audio
|
||||
runOutput(0);
|
||||
#end
|
||||
}
|
||||
|
||||
function onUpdate() {
|
||||
|
@ -37,6 +37,7 @@ class RotationNode extends LogicNode {
|
||||
value.y = vect.y;
|
||||
value.z = vect.z;
|
||||
value.w = inputs[1].get();
|
||||
value.normalize();
|
||||
|
||||
case "AxisAngle":
|
||||
var vec: Vec4 = inputs[0].get();
|
||||
|
37
leenkx/Sources/leenkx/logicnode/SetBoneTransformNode.hx
Normal file
@ -0,0 +1,37 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
import iron.object.Object;
|
||||
#if lnx_skin
|
||||
import iron.object.BoneAnimation;
|
||||
#end
|
||||
import iron.math.Mat4;
|
||||
|
||||
class SetBoneTransformNode extends LogicNode {
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
|
||||
override function run(from: Int) {
|
||||
#if lnx_skin
|
||||
|
||||
var object: Object = inputs[1].get();
|
||||
if (object == null) return;
|
||||
var transform = inputs[3].get();
|
||||
if (transform == null) return;
|
||||
var boneName: String = inputs[2].get();
|
||||
|
||||
var anim = object.animation != null ? cast(object.animation, BoneAnimation) : null;
|
||||
if (anim == null) anim = object.getBoneAnimation(object.uid);
|
||||
|
||||
// Get bone in armature
|
||||
var bone = anim.getBone(boneName);
|
||||
|
||||
anim.setBoneMatFromWorldMat(anim.skeletonMats, transform, bone);
|
||||
|
||||
runOutput(0);
|
||||
|
||||
#end
|
||||
}
|
||||
}
|
@ -17,7 +17,7 @@ class SetParentBoneNode extends LogicNode {
|
||||
|
||||
if (object == null || parent == null) return;
|
||||
|
||||
object.setParent(parent, false, false);
|
||||
object.setParent(parent, inputs[4].get(), inputs[5].get());
|
||||
|
||||
var banim = object.getBoneAnimation(object.parent.uid);
|
||||
banim.addBoneChild(bone, object);
|
||||
|
@ -1,7 +1,7 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
#if lnx_audio
|
||||
import iron.object.SpeakerObject;
|
||||
|
||||
#end
|
||||
class SetSoundNode extends LogicNode {
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
@ -9,10 +9,12 @@ class SetSoundNode extends LogicNode {
|
||||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
#if lnx_audio
|
||||
var object: SpeakerObject = cast(inputs[1].get(), SpeakerObject);
|
||||
var sound: String = inputs[2].get();
|
||||
if (object == null || sound == null) return;
|
||||
object.setSound(sound);
|
||||
#end
|
||||
runOutput(0);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
#if lnx_audio
|
||||
import iron.object.SpeakerObject;
|
||||
|
||||
#end
|
||||
class SetVolumeSoundNode extends LogicNode {
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
@ -9,9 +9,11 @@ class SetVolumeSoundNode extends LogicNode {
|
||||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
#if lnx_audio
|
||||
var object: SpeakerObject = cast(inputs[1].get(), SpeakerObject);
|
||||
if (object == null) return;
|
||||
object.setVolume(inputs[2].get());
|
||||
#end
|
||||
runOutput(0);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
#if lnx_audio
|
||||
import iron.object.SpeakerObject;
|
||||
|
||||
#end
|
||||
class StopSoundNode extends LogicNode {
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
@ -9,9 +9,11 @@ class StopSoundNode extends LogicNode {
|
||||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
#if lnx_audio
|
||||
var object: SpeakerObject = cast(inputs[1].get(), SpeakerObject);
|
||||
if (object == null) return;
|
||||
object.stop();
|
||||
#end
|
||||
runOutput(0);
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ class TransformNode extends LogicNode {
|
||||
override function get(from: Int): Dynamic {
|
||||
var loc: Vec4 = inputs[0].get();
|
||||
var rot: Quat = new Quat().setFrom(inputs[1].get());
|
||||
rot.normalize();
|
||||
//rot.normalize();
|
||||
var scale: Vec4 = inputs[2].get();
|
||||
if (loc == null && rot == null && scale == null) return this.value;
|
||||
if (loc == null || rot == null || scale == null) return null;
|
||||
|
@ -77,6 +77,9 @@ class Inc {
|
||||
#if (rp_voxels == "Voxel GI")
|
||||
static var voxel_sh5:kha.compute.Shader = null;
|
||||
static var voxel_ta5:kha.compute.TextureUnit;
|
||||
static var voxel_te5:kha.compute.TextureUnit;
|
||||
static var voxel_tf5:kha.compute.TextureUnit;
|
||||
static var voxel_tg5:kha.compute.TextureUnit;
|
||||
static var voxel_ca5:kha.compute.ConstantLocation;
|
||||
static var voxel_cb5:kha.compute.ConstantLocation;
|
||||
static var voxel_cc5:kha.compute.ConstantLocation;
|
||||
@ -677,7 +680,7 @@ class Inc {
|
||||
}
|
||||
else {
|
||||
if (t.name == "voxelsSDF" || t.name == "voxelsSDFtmp") {
|
||||
t.format = "R16";
|
||||
t.format = "R8";
|
||||
t.width = res;
|
||||
t.height = res * Main.voxelgiClipmapCount;
|
||||
t.depth = res;
|
||||
@ -686,7 +689,7 @@ class Inc {
|
||||
#if (rp_voxels == "Voxel AO")
|
||||
{
|
||||
if (t.name == "voxelsOut" || t.name == "voxelsOutB") {
|
||||
t.format = "R16";
|
||||
t.format = "R8";
|
||||
t.width = res * (6 + 16);
|
||||
t.height = res * Main.voxelgiClipmapCount;
|
||||
t.depth = res;
|
||||
@ -892,7 +895,9 @@ class Inc {
|
||||
{
|
||||
voxel_sh5 = path.getComputeShader("voxel_light");
|
||||
voxel_ta5 = voxel_sh5.getTextureUnit("voxelsLight");
|
||||
|
||||
voxel_te5 = voxel_sh5.getTextureUnit("voxels");
|
||||
voxel_tf5 = voxel_sh5.getTextureUnit("voxelsSampler");
|
||||
voxel_tg5 = voxel_sh5.getTextureUnit("voxelsSDFSampler");
|
||||
voxel_ca5 = voxel_sh5.getConstantLocation("clipmaps");
|
||||
voxel_cb5 = voxel_sh5.getConstantLocation("clipmapLevel");
|
||||
|
||||
@ -1288,7 +1293,9 @@ class Inc {
|
||||
kha.compute.Compute.setShader(voxel_sh5);
|
||||
|
||||
kha.compute.Compute.setTexture(voxel_ta5, rts.get("voxelsLight").image, kha.compute.Access.Write);
|
||||
|
||||
kha.compute.Compute.setTexture(voxel_te5, rts.get("voxels").image, kha.compute.Access.Read);
|
||||
kha.compute.Compute.setSampledTexture(voxel_tf5, rts.get("voxelsOut").image);
|
||||
kha.compute.Compute.setSampledTexture(voxel_tg5, rts.get("voxelsSDF").image);
|
||||
var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10);
|
||||
for (i in 0...Main.voxelgiClipmapCount) {
|
||||
fa[i * 10] = clipmaps[i].voxelSize;
|
||||
|
@ -368,7 +368,7 @@ class RenderPathDeferred {
|
||||
t.scale = Inc.getSuperSampling();
|
||||
path.createRenderTarget(t);
|
||||
|
||||
// holds background depth
|
||||
// holds background color
|
||||
var t = new RenderTargetRaw();
|
||||
t.name = "refr";
|
||||
t.width = 0;
|
||||
@ -473,6 +473,13 @@ class RenderPathDeferred {
|
||||
}
|
||||
#end
|
||||
|
||||
#if rp_ssrefr
|
||||
{
|
||||
path.setTarget("gbuffer_refraction");
|
||||
path.clearTarget(0xffffff00);
|
||||
}
|
||||
#end
|
||||
|
||||
RenderPathCreator.setTargetMeshes();
|
||||
|
||||
#if rp_dynres
|
||||
@ -837,7 +844,7 @@ class RenderPathDeferred {
|
||||
{
|
||||
path.bindTarget("voxelsOut", "voxels");
|
||||
path.bindTarget("voxelsSDF", "voxelsSDF");
|
||||
path.bindTarget("gbuffer2", "sveloc");
|
||||
path.bindTarget("gbuffer2", "gbuffer2");
|
||||
}
|
||||
#end
|
||||
|
||||
|
@ -522,6 +522,17 @@ class RenderPathForward {
|
||||
|
||||
path.setTarget("lbuffer0", ["lbuffer1", "gbuffer_refraction"]);
|
||||
|
||||
#if rp_shadowmap
|
||||
{
|
||||
#if lnx_shadowmap_atlas
|
||||
Inc.bindShadowMapAtlas();
|
||||
#else
|
||||
Inc.bindShadowMap();
|
||||
#end
|
||||
}
|
||||
#end
|
||||
|
||||
|
||||
#if (rp_voxels != "Off")
|
||||
path.bindTarget("voxelsOut", "voxels");
|
||||
path.bindTarget("voxelsSDF", "voxelsSDF");
|
||||
|
@ -41,7 +41,11 @@ class Starter {
|
||||
try {
|
||||
#end
|
||||
|
||||
kha.System.start({title: Main.projectName, width: c.window_w, height: c.window_h, window: {mode: windowMode, windowFeatures: windowFeatures}, framebuffer: {samplesPerPixel: c.window_msaa, verticalSync: c.window_vsync}}, function(window: kha.Window) {
|
||||
kha.System.start({title: Main.projectName, width: c.window_w, height: c.window_h, window: {
|
||||
#if lnx_render_viewport
|
||||
visible: false,
|
||||
#end
|
||||
mode: windowMode, windowFeatures: windowFeatures}, framebuffer: {samplesPerPixel: c.window_msaa, verticalSync: c.window_vsync}}, function(window: kha.Window) {
|
||||
|
||||
iron.App.init(function() {
|
||||
#if lnx_loadscreen
|
||||
|
@ -10,6 +10,10 @@ class KinematicCharacterController extends iron.Trait { public function new() {
|
||||
|
||||
typedef KinematicCharacterController = leenkx.trait.physics.bullet.KinematicCharacterController;
|
||||
|
||||
#else
|
||||
|
||||
typedef KinematicCharacterController = leenkx.trait.physics.oimo.KinematicCharacterController;
|
||||
|
||||
#end
|
||||
|
||||
#end
|
||||
|
@ -3,17 +3,16 @@ package leenkx.trait.physics;
|
||||
#if (!lnx_physics)
|
||||
|
||||
class PhysicsConstraint extends iron.Trait { public function new() { super(); } }
|
||||
@:enum abstract ConstraintAxis(Int) from Int to Int { }
|
||||
|
||||
#else
|
||||
|
||||
#if lnx_bullet
|
||||
|
||||
typedef PhysicsConstraint = leenkx.trait.physics.bullet.PhysicsConstraint;
|
||||
|
||||
typedef ConstraintAxis = leenkx.trait.physics.bullet.PhysicsConstraint.ConstraintAxis;
|
||||
#else
|
||||
|
||||
typedef PhysicsConstraint = leenkx.trait.physics.oimo.PhysicsConstraint;
|
||||
|
||||
typedef ConstraintAxis = leenkx.trait.physics.oimo.PhysicsConstraint.ConstraintAxis;
|
||||
#end
|
||||
|
||||
#end
|
||||
|
@ -2,6 +2,7 @@ package leenkx.trait.physics;
|
||||
|
||||
#if (!lnx_physics)
|
||||
|
||||
class Hit { }
|
||||
class PhysicsWorld extends iron.Trait { public function new() { super(); } }
|
||||
|
||||
#else
|
||||
@ -9,11 +10,11 @@ class PhysicsWorld extends iron.Trait { public function new() { super(); } }
|
||||
#if lnx_bullet
|
||||
|
||||
typedef PhysicsWorld = leenkx.trait.physics.bullet.PhysicsWorld;
|
||||
|
||||
typedef Hit = leenkx.trait.physics.bullet.PhysicsWorld.Hit;
|
||||
#else
|
||||
|
||||
typedef PhysicsWorld = leenkx.trait.physics.oimo.PhysicsWorld;
|
||||
|
||||
typedef Hit = leenkx.trait.physics.oimo.PhysicsWorld.Hit;
|
||||
#end
|
||||
|
||||
#end
|
||||
|
@ -3,17 +3,20 @@ package leenkx.trait.physics;
|
||||
#if (!lnx_physics)
|
||||
|
||||
class RigidBody extends iron.Trait { public function new() { super(); } }
|
||||
@:enum abstract Shape(Int) from Int to Int { }
|
||||
|
||||
#else
|
||||
|
||||
#if lnx_bullet
|
||||
|
||||
typedef RigidBody = leenkx.trait.physics.bullet.RigidBody;
|
||||
|
||||
typedef Shape = leenkx.trait.physics.bullet.RigidBody.Shape;
|
||||
|
||||
#else
|
||||
|
||||
typedef RigidBody = leenkx.trait.physics.oimo.RigidBody;
|
||||
|
||||
typedef Shape = leenkx.trait.physics.oimo.RigidBody.Shape;
|
||||
|
||||
#end
|
||||
|
||||
#end
|
||||
|
@ -1,5 +1,8 @@
|
||||
package leenkx.trait.physics.bullet;
|
||||
|
||||
#if lnx_bullet
|
||||
import leenkx.trait.physics.bullet.PhysicsWorld.DebugDrawMode;
|
||||
|
||||
import bullet.Bt.Vector3;
|
||||
|
||||
import kha.FastFloat;
|
||||
@ -18,15 +21,21 @@ class DebugDrawHelper {
|
||||
static inline var contactPointNormalColor = 0xffffffff;
|
||||
static inline var contactPointDrawLifetime = true;
|
||||
|
||||
final rayCastColor: Vec4 = new Vec4(0.0, 1.0, 0.0);
|
||||
final rayCastHitColor: Vec4 = new Vec4(1.0, 0.0, 0.0);
|
||||
final rayCastHitPointColor: Vec4 = new Vec4(1.0, 1.0, 0.0);
|
||||
|
||||
final physicsWorld: PhysicsWorld;
|
||||
final lines: Array<LineData> = [];
|
||||
final texts: Array<TextData> = [];
|
||||
var font: kha.Font = null;
|
||||
|
||||
var debugMode: PhysicsWorld.DebugDrawMode = NoDebug;
|
||||
var rayCasts:Array<TRayCastData> = [];
|
||||
var debugDrawMode: DebugDrawMode = NoDebug;
|
||||
|
||||
public function new(physicsWorld: PhysicsWorld) {
|
||||
public function new(physicsWorld: PhysicsWorld, debugDrawMode: DebugDrawMode) {
|
||||
this.physicsWorld = physicsWorld;
|
||||
this.debugDrawMode = debugDrawMode;
|
||||
|
||||
#if lnx_ui
|
||||
iron.data.Data.getFont(Canvas.defaultFontName, function(defaultFont: kha.Font) {
|
||||
@ -35,6 +44,11 @@ class DebugDrawHelper {
|
||||
#end
|
||||
|
||||
iron.App.notifyOnRender2D(onRender);
|
||||
if (debugDrawMode & DrawRayCast != 0) {
|
||||
iron.App.notifyOnUpdate(function () {
|
||||
rayCasts.resize(0);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public function drawLine(from: bullet.Bt.Vector3, to: bullet.Bt.Vector3, color: bullet.Bt.Vector3) {
|
||||
@ -49,9 +63,10 @@ class DebugDrawHelper {
|
||||
final fromScreenSpace = worldToScreenFast(new Vec4(from.x(), from.y(), from.z(), 1.0));
|
||||
final toScreenSpace = worldToScreenFast(new Vec4(to.x(), to.y(), to.z(), 1.0));
|
||||
|
||||
// For now don't draw lines if any point is outside of clip space z,
|
||||
// investigate how to clamp lines to clip space borders
|
||||
if (fromScreenSpace.w == 1 && toScreenSpace.w == 1) {
|
||||
// If at least one point is within the Z clip space (w==1), attempt to draw.
|
||||
// Note: This is not full clipping, line may still go off screen sides.
|
||||
if (fromScreenSpace.w == 1 || toScreenSpace.w == 1) {
|
||||
lines.push({
|
||||
fromX: fromScreenSpace.x,
|
||||
fromY: fromScreenSpace.y,
|
||||
@ -112,6 +127,61 @@ class DebugDrawHelper {
|
||||
}
|
||||
}
|
||||
|
||||
public function rayCast(rayCastData:TRayCastData) {
|
||||
rayCasts.push(rayCastData);
|
||||
}
|
||||
|
||||
function drawRayCast(f: Vec4, t: Vec4, hit: Bool) {
|
||||
final from = worldToScreenFast(f.clone());
|
||||
final to = worldToScreenFast(t.clone());
|
||||
var c: kha.Color;
|
||||
|
||||
if (from.w == 1 && to.w == 1) {
|
||||
if (hit) c = kha.Color.fromFloats(rayCastHitColor.x, rayCastHitColor.y, rayCastHitColor.z);
|
||||
else c = kha.Color.fromFloats(rayCastColor.x, rayCastColor.y, rayCastColor.z);
|
||||
|
||||
lines.push({
|
||||
fromX: from.x,
|
||||
fromY: from.y,
|
||||
toX: to.x,
|
||||
toY: to.y,
|
||||
color: c
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function drawHitPoint(hp: Vec4) {
|
||||
final hitPoint = worldToScreenFast(hp.clone());
|
||||
final c = kha.Color.fromFloats(rayCastHitPointColor.x, rayCastHitPointColor.y, rayCastHitPointColor.z);
|
||||
|
||||
if (hitPoint.w == 1) {
|
||||
lines.push({
|
||||
fromX: hitPoint.x - contactPointSizePx,
|
||||
fromY: hitPoint.y - contactPointSizePx,
|
||||
toX: hitPoint.x + contactPointSizePx,
|
||||
toY: hitPoint.y + contactPointSizePx,
|
||||
color: c
|
||||
});
|
||||
|
||||
lines.push({
|
||||
fromX: hitPoint.x - contactPointSizePx,
|
||||
fromY: hitPoint.y + contactPointSizePx,
|
||||
toX: hitPoint.x + contactPointSizePx,
|
||||
toY: hitPoint.y - contactPointSizePx,
|
||||
color: c
|
||||
});
|
||||
|
||||
if (font != null) {
|
||||
texts.push({
|
||||
x: hitPoint.x,
|
||||
y: hitPoint.y,
|
||||
color: c,
|
||||
text: 'RAYCAST HIT'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function reportErrorWarning(warningString: bullet.Bt.BulletString) {
|
||||
trace(warningString.toHaxeString().trim());
|
||||
}
|
||||
@ -135,13 +205,13 @@ class DebugDrawHelper {
|
||||
});
|
||||
}
|
||||
|
||||
public function setDebugMode(debugMode: PhysicsWorld.DebugDrawMode) {
|
||||
this.debugMode = debugMode;
|
||||
public function setDebugMode(debugDrawMode: DebugDrawMode) {
|
||||
this.debugDrawMode = debugDrawMode;
|
||||
}
|
||||
|
||||
public function getDebugMode(): PhysicsWorld.DebugDrawMode {
|
||||
public function getDebugMode(): DebugDrawMode {
|
||||
#if js
|
||||
return debugMode;
|
||||
return debugDrawMode;
|
||||
#elseif hl
|
||||
return physicsWorld.getDebugDrawMode();
|
||||
#else
|
||||
@ -161,6 +231,7 @@ class DebugDrawHelper {
|
||||
// before some user-specific physics update, which would result in a
|
||||
// one-frame drawing delay... Ideally we would ensure that debugDrawWorld()
|
||||
// is called when all other (late) update callbacks are already executed...
|
||||
|
||||
physicsWorld.world.debugDrawWorld();
|
||||
|
||||
g.opacity = 1.0;
|
||||
@ -180,6 +251,17 @@ class DebugDrawHelper {
|
||||
}
|
||||
texts.resize(0);
|
||||
}
|
||||
|
||||
if (debugDrawMode & DrawRayCast != 0) {
|
||||
for (rayCastData in rayCasts) {
|
||||
if (rayCastData.hasHit) {
|
||||
drawRayCast(rayCastData.from, rayCastData.hitPoint, true);
|
||||
drawHitPoint(rayCastData.hitPoint);
|
||||
} else {
|
||||
drawRayCast(rayCastData.from, rayCastData.to, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -222,3 +304,14 @@ class TextData {
|
||||
public var color: kha.Color;
|
||||
public var text: String;
|
||||
}
|
||||
|
||||
@:structInit
|
||||
typedef TRayCastData = {
|
||||
var from: Vec4;
|
||||
var to: Vec4;
|
||||
var hasHit: Bool;
|
||||
@:optional var hitPoint: Vec4;
|
||||
@:optional var hitNormal: Vec4;
|
||||
}
|
||||
|
||||
#end
|
@ -85,6 +85,22 @@ class PhysicsWorld extends Trait {
|
||||
public static var physTime = 0.0;
|
||||
#end
|
||||
|
||||
public static function getSolverInfo(world:bullet.Bt.DynamicsWorld):Dynamic {
|
||||
return Reflect.callMethod(world, Reflect.field(world, "getSolverInfo"), []);
|
||||
}
|
||||
|
||||
public static function setSolverIterations(world:bullet.Bt.DynamicsWorld, iterations:Int):Void {
|
||||
var solverInfo = getSolverInfo(world);
|
||||
if (solverInfo != null) {
|
||||
Reflect.setField(solverInfo, "m_numIterations", iterations);
|
||||
} else {
|
||||
trace("Warning: Could not access solver info. Solver iterations not applied.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public function new(timeScale = 1.0, maxSteps = 10, solverIterations = 10, debugDrawMode: DebugDrawMode = NoDebug) {
|
||||
super();
|
||||
|
||||
@ -164,7 +180,8 @@ class PhysicsWorld extends Trait {
|
||||
#else
|
||||
world = new bullet.Bt.DiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration);
|
||||
#end
|
||||
|
||||
// TO DO: Set the solver iterations from Blender's rigid body world
|
||||
// setSolverIterations(world, solverIterations);
|
||||
setGravity(gravity);
|
||||
}
|
||||
|
||||
@ -378,6 +395,7 @@ class PhysicsWorld extends Trait {
|
||||
rayTo.setValue(to.x, to.y, to.z);
|
||||
|
||||
var rayCallback = new bullet.Bt.ClosestRayResultCallback(rayFrom, rayTo);
|
||||
|
||||
#if js
|
||||
rayCallback.set_m_collisionFilterGroup(group);
|
||||
rayCallback.set_m_collisionFilterMask(mask);
|
||||
@ -387,6 +405,7 @@ class PhysicsWorld extends Trait {
|
||||
#end
|
||||
var worldDyn: bullet.Bt.DynamicsWorld = world;
|
||||
var worldCol: bullet.Bt.CollisionWorld = worldDyn;
|
||||
|
||||
worldCol.rayTest(rayFrom, rayTo, rayCallback);
|
||||
var rb: RigidBody = null;
|
||||
var hitInfo: Hit = null;
|
||||
@ -412,6 +431,16 @@ class PhysicsWorld extends Trait {
|
||||
#end
|
||||
}
|
||||
|
||||
if (getDebugDrawMode() & DrawRayCast != 0) {
|
||||
debugDrawHelper.rayCast({
|
||||
from: from,
|
||||
to: to,
|
||||
hasHit: rc.hasHit(),
|
||||
hitPoint: hitPointWorld,
|
||||
hitNormal: hitNormalWorld
|
||||
});
|
||||
}
|
||||
|
||||
#if js
|
||||
bullet.Bt.Ammo.destroy(rayCallback);
|
||||
#else
|
||||
@ -493,7 +522,7 @@ class PhysicsWorld extends Trait {
|
||||
if (debugDrawMode == NoDebug) {
|
||||
return;
|
||||
}
|
||||
initDebugDrawing();
|
||||
initDebugDrawing(debugDrawMode);
|
||||
}
|
||||
|
||||
#if js
|
||||
@ -517,8 +546,8 @@ class PhysicsWorld extends Trait {
|
||||
#end
|
||||
}
|
||||
|
||||
function initDebugDrawing() {
|
||||
debugDrawHelper = new DebugDrawHelper(this);
|
||||
function initDebugDrawing(debugDrawMode: DebugDrawMode) {
|
||||
debugDrawHelper = new DebugDrawHelper(this, debugDrawMode);
|
||||
|
||||
#if js
|
||||
final drawer = new bullet.Bt.DebugDrawer();
|
||||
@ -644,10 +673,7 @@ enum abstract DebugDrawMode(Int) from Int to Int {
|
||||
// We could use it in the future to toggle depth testing for lines, i.e. draw actual 3D lines if not set and Kha's g2 lines if set.
|
||||
var FastWireframe = 1 << 13;
|
||||
|
||||
/**
|
||||
Draw the normal vectors of the triangles of the physics collider meshes.
|
||||
This only works for `Mesh` collision shapes.
|
||||
**/
|
||||
/** Draw the normal vectors of the triangles of the physics collider meshes. **/
|
||||
// Outside of Leenkx this works for a few more collision shapes
|
||||
var DrawNormals = 1 << 14;
|
||||
|
||||
@ -657,6 +683,8 @@ enum abstract DebugDrawMode(Int) from Int to Int {
|
||||
**/
|
||||
var DrawFrames = 1 << 15;
|
||||
|
||||
var DrawRayCast = 1 << 16;
|
||||
|
||||
@:op(~A) public inline function bitwiseNegate(): DebugDrawMode {
|
||||
return ~this;
|
||||
}
|
||||
|
@ -1,8 +1,5 @@
|
||||
package zui;
|
||||
|
||||
// Immediate Mode UI Library
|
||||
// https://github.com/leenkx3d/zui
|
||||
|
||||
import kha.input.Mouse;
|
||||
import kha.input.Pen;
|
||||
import kha.input.Surface;
|
||||
@ -255,7 +252,7 @@ class Zui {
|
||||
Mouse.get().notifyWindowed(ops.khaWindowId, onMouseDown, onMouseUp, onMouseMove, onMouseWheel);
|
||||
if (Pen.get() != null) Pen.get().notify(onPenDown, onPenUp, onPenMove);
|
||||
Keyboard.get().notify(onKeyDown, onKeyUp, onKeyPress);
|
||||
#if (kha_android || kha_ios)
|
||||
#if (kha_android || kha_ios || kha_html5 || kha_debug_html5)
|
||||
if (Surface.get() != null) Surface.get().notify(onTouchDown, onTouchUp, onTouchMove);
|
||||
#end
|
||||
// Reset mouse delta on foreground
|
||||
@ -268,7 +265,7 @@ class Zui {
|
||||
Mouse.get().removeWindowed(ops.khaWindowId, onMouseDown, onMouseUp, onMouseMove, onMouseWheel);
|
||||
if (Pen.get() != null) Pen.get().remove(onPenDown, onPenUp, onPenMove);
|
||||
Keyboard.get().remove(onKeyDown, onKeyUp, onKeyPress);
|
||||
#if (kha_android || kha_ios)
|
||||
#if (kha_android || kha_ios || kha_html5 || kha_debug_html5)
|
||||
if (Surface.get() != null) Surface.get().remove(onTouchDown, onTouchUp, onTouchMove);
|
||||
#end
|
||||
endInput();
|
||||
@ -1760,7 +1757,7 @@ class Zui {
|
||||
button == 0 ? inputStarted = true : inputStartedR = true;
|
||||
button == 0 ? inputDown = true : inputDownR = true;
|
||||
inputStartedTime = kha.Scheduler.time();
|
||||
#if (kha_android || kha_ios)
|
||||
#if (kha_android || kha_ios || kha_html5 || kha_debug_html5)
|
||||
setInputPosition(x, y);
|
||||
#end
|
||||
inputStartedX = x;
|
||||
@ -1787,7 +1784,7 @@ class Zui {
|
||||
button == 0 ? inputReleased = true : inputReleasedR = true;
|
||||
}
|
||||
button == 0 ? inputDown = false : inputDownR = false;
|
||||
#if (kha_android || kha_ios)
|
||||
#if (kha_android || kha_ios || kha_html5 || kha_debug_html5)
|
||||
setInputPosition(x, y);
|
||||
#end
|
||||
deselectText();
|
||||
@ -1811,7 +1808,7 @@ class Zui {
|
||||
}
|
||||
|
||||
public function onPenDown(x: Int, y: Int, pressure: Float) {
|
||||
#if (kha_android || kha_ios)
|
||||
#if (kha_android || kha_ios || kha_html5 || kha_debug_html5)
|
||||
return;
|
||||
#end
|
||||
|
||||
@ -1819,7 +1816,7 @@ class Zui {
|
||||
}
|
||||
|
||||
public function onPenUp(x: Int, y: Int, pressure: Float) {
|
||||
#if (kha_android || kha_ios)
|
||||
#if (kha_android || kha_ios || kha_html5 || kha_debug_html5)
|
||||
return;
|
||||
#end
|
||||
|
||||
@ -1829,7 +1826,7 @@ class Zui {
|
||||
}
|
||||
|
||||
public function onPenMove(x: Int, y: Int, pressure: Float) {
|
||||
#if (kha_android || kha_ios)
|
||||
#if (kha_android || kha_ios || kha_html5 || kha_debug_html5)
|
||||
return;
|
||||
#end
|
||||
|
||||
@ -1889,7 +1886,7 @@ class Zui {
|
||||
isKeyPressed = true;
|
||||
}
|
||||
|
||||
#if (kha_android || kha_ios)
|
||||
#if (kha_android || kha_ios || kha_html5 || kha_debug_html5)
|
||||
public function onTouchDown(index: Int, x: Int, y: Int) {
|
||||
// Reset movement delta on touch start
|
||||
if (index == 0) {
|
||||
|
@ -324,6 +324,20 @@ class LeenkxExporter:
|
||||
def export_object_transform(self, bobject: bpy.types.Object, o):
|
||||
wrd = bpy.data.worlds['Lnx']
|
||||
|
||||
# HACK: In Blender 4.2.x, each camera must be selected to ensure its matrix is correctly assigned
|
||||
if bpy.app.version >= (4, 2, 0) and bobject.type == 'CAMERA' and bobject.users_scene:
|
||||
current_scene = bpy.context.window.scene
|
||||
|
||||
bpy.context.window.scene = bobject.users_scene[0]
|
||||
bpy.context.view_layer.update()
|
||||
|
||||
bobject.select_set(True)
|
||||
bpy.context.view_layer.update()
|
||||
bobject.select_set(False)
|
||||
|
||||
bpy.context.window.scene = current_scene
|
||||
bpy.context.view_layer.update()
|
||||
|
||||
# Static transform
|
||||
o['transform'] = {'values': LeenkxExporter.write_matrix(bobject.matrix_local)}
|
||||
|
||||
@ -1001,7 +1015,8 @@ class LeenkxExporter:
|
||||
action = actions.get('leenkxpose')
|
||||
if action is None:
|
||||
action = actions.new(name='leenkxpose')
|
||||
|
||||
adata.action = action
|
||||
|
||||
# Export actions
|
||||
export_actions = [action]
|
||||
# hasattr - armature modifier may reference non-parent
|
||||
@ -1551,8 +1566,7 @@ class LeenkxExporter:
|
||||
log.error(e.message)
|
||||
else:
|
||||
# Assume it was caused because of encountering n-gons
|
||||
log.error(f"""object {bobject.name} contains n-gons in its mesh, so it's impossible to compute tanget space for normal mapping.
|
||||
Make sure the mesh only has tris/quads.""")
|
||||
log.error(f"""object {bobject.name} contains n-gons in its mesh, so it's impossible to compute tanget space for normal mapping. Make sure the mesh only has tris/quads.""")
|
||||
|
||||
tangdata = np.empty(num_verts * 3, dtype='<f4')
|
||||
if has_col:
|
||||
@ -3025,14 +3039,15 @@ Make sure the mesh only has tris/quads.""")
|
||||
if rbw is not None and rbw.enabled:
|
||||
out_trait['parameters'] = [str(rbw.time_scale), str(rbw.substeps_per_frame), str(rbw.solver_iterations)]
|
||||
|
||||
if phys_pkg == 'bullet':
|
||||
debug_draw_mode = 1 if wrd.lnx_bullet_dbg_draw_wireframe else 0
|
||||
debug_draw_mode |= 2 if wrd.lnx_bullet_dbg_draw_aabb else 0
|
||||
debug_draw_mode |= 8 if wrd.lnx_bullet_dbg_draw_contact_points else 0
|
||||
debug_draw_mode |= 2048 if wrd.lnx_bullet_dbg_draw_constraints else 0
|
||||
debug_draw_mode |= 4096 if wrd.lnx_bullet_dbg_draw_constraint_limits else 0
|
||||
debug_draw_mode |= 16384 if wrd.lnx_bullet_dbg_draw_normals else 0
|
||||
debug_draw_mode |= 32768 if wrd.lnx_bullet_dbg_draw_axis_gizmo else 0
|
||||
if phys_pkg == 'bullet' or phys_pkg == 'oimo':
|
||||
debug_draw_mode = 1 if wrd.lnx_physics_dbg_draw_wireframe else 0
|
||||
debug_draw_mode |= 2 if wrd.lnx_physics_dbg_draw_aabb else 0
|
||||
debug_draw_mode |= 8 if wrd.lnx_physics_dbg_draw_contact_points else 0
|
||||
debug_draw_mode |= 2048 if wrd.lnx_physics_dbg_draw_constraints else 0
|
||||
debug_draw_mode |= 4096 if wrd.lnx_physics_dbg_draw_constraint_limits else 0
|
||||
debug_draw_mode |= 16384 if wrd.lnx_physics_dbg_draw_normals else 0
|
||||
debug_draw_mode |= 32768 if wrd.lnx_physics_dbg_draw_axis_gizmo else 0
|
||||
debug_draw_mode |= 65536 if wrd.lnx_physics_dbg_draw_raycast else 0
|
||||
out_trait['parameters'].append(str(debug_draw_mode))
|
||||
|
||||
self.output['traits'].append(out_trait)
|
||||
|
@ -132,6 +132,7 @@ def always() -> float:
|
||||
return 0.5
|
||||
|
||||
|
||||
|
||||
def poll_threads() -> float:
|
||||
"""Polls the thread callback queue and if a thread has finished, it
|
||||
is joined with the main thread and the corresponding callback is
|
||||
@ -141,21 +142,27 @@ def poll_threads() -> float:
|
||||
thread, callback = make.thread_callback_queue.get(block=False)
|
||||
except queue.Empty:
|
||||
return 0.25
|
||||
|
||||
thread.join()
|
||||
|
||||
try:
|
||||
callback()
|
||||
except Exception as e:
|
||||
# If there is an exception, we can no longer return the time to
|
||||
# the next call to this polling function, so to keep it running
|
||||
# we re-register it and then raise the original exception.
|
||||
bpy.app.timers.unregister(poll_threads)
|
||||
bpy.app.timers.register(poll_threads, first_interval=0.01, persistent=True)
|
||||
raise e
|
||||
|
||||
# Quickly check if another thread has finished
|
||||
return 0.01
|
||||
if thread.is_alive():
|
||||
try:
|
||||
make.thread_callback_queue.put((thread, callback), block=False)
|
||||
except queue.Full:
|
||||
return 0.5
|
||||
return 0.1
|
||||
else:
|
||||
try:
|
||||
thread.join()
|
||||
callback()
|
||||
except Exception as e:
|
||||
# If there is an exception, we can no longer return the time to
|
||||
# the next call to this polling function, so to keep it running
|
||||
# we re-register it and then raise the original exception.
|
||||
try:
|
||||
bpy.app.timers.unregister(poll_threads)
|
||||
except ValueError:
|
||||
pass
|
||||
bpy.app.timers.register(poll_threads, first_interval=0.01, persistent=True)
|
||||
# Quickly check if another thread has finished
|
||||
return 0.01
|
||||
|
||||
|
||||
loaded_py_libraries: dict[str, types.ModuleType] = {}
|
||||
|
@ -7,48 +7,46 @@ if lnx.is_reload(__name__):
|
||||
else:
|
||||
lnx.enable_reload(__name__)
|
||||
|
||||
lnx.keymaps = []
|
||||
#lnx.keymaps = []
|
||||
|
||||
|
||||
def register():
|
||||
wm = bpy.context.window_manager
|
||||
addon_keyconfig = wm.keyconfigs.addon
|
||||
|
||||
keyconfig = wm.keyconfigs.user
|
||||
|
||||
# Keyconfigs are not available in background mode. If the keyconfig
|
||||
# was not found despite running _not_ in background mode, a warning
|
||||
# is printed
|
||||
if addon_keyconfig is None:
|
||||
if keyconfig is None:
|
||||
if not bpy.app.background:
|
||||
log.warn("No keyconfig path found")
|
||||
return
|
||||
|
||||
km = addon_keyconfig.keymaps.new(name='Window', space_type='EMPTY', region_type="WINDOW")
|
||||
km.keymap_items.new(props_ui.LeenkxPlayButton.bl_idname, type='F5', value='PRESS')
|
||||
km.keymap_items.new("tlm.build_lightmaps", type='F6', value='PRESS')
|
||||
km.keymap_items.new("tlm.clean_lightmaps", type='F7', value='PRESS')
|
||||
lnx.keymaps.append(km)
|
||||
|
||||
km = addon_keyconfig.keymaps.new(name='Node Editor', space_type='NODE_EDITOR')
|
||||
|
||||
# shift+G: Create a new node call group node
|
||||
km.keymap_items.new('lnx.add_call_group_node', 'G', 'PRESS', shift=True)
|
||||
|
||||
# ctrl+G: make node group from selected
|
||||
km.keymap_items.new('lnx.add_group_tree_from_selected', 'G', 'PRESS', ctrl=True)
|
||||
|
||||
# TAB: enter node groups depending on selection
|
||||
km.keymap_items.new('lnx.edit_group_tree', 'TAB', 'PRESS')
|
||||
|
||||
# ctrl+TAB: exit node groups depending on selectio
|
||||
km.keymap_items.new('node.tree_path_parent', 'TAB', 'PRESS', ctrl=True)
|
||||
|
||||
# alt+G: ungroup node tree
|
||||
km.keymap_items.new('lnx.ungroup_group_tree', 'G', 'PRESS', alt=True)
|
||||
lnx.keymaps.append(km)
|
||||
|
||||
km = keyconfig.keymaps.get('Window')
|
||||
if km is None:
|
||||
log.warn("Window keymaps not available")
|
||||
return
|
||||
lnx_start = any(kmi.idname == props_ui.LeenkxPlayButton.bl_idname for kmi in km.keymap_items)
|
||||
if not lnx_start:
|
||||
kmw = keyconfig.keymaps.new(name='Window', space_type='EMPTY', region_type="WINDOW")
|
||||
kmw.keymap_items.new(props_ui.LeenkxPlayButton.bl_idname, type='F5', value='PRESS')
|
||||
kmw.keymap_items.new('tlm.build_lightmaps', type='F6', value='PRESS')
|
||||
kmw.keymap_items.new('tlm.clean_lightmaps', type='F7', value='PRESS')
|
||||
kmn = keyconfig.keymaps.new(name='Node Editor', space_type='NODE_EDITOR')
|
||||
kmn.keymap_items.new('lnx.add_call_group_node', 'G', 'PRESS', shift=True)
|
||||
kmn.keymap_items.new('lnx.add_group_tree_from_selected', 'G', 'PRESS', ctrl=True)
|
||||
kmn.keymap_items.new('lnx.edit_group_tree', 'TAB', 'PRESS')
|
||||
kmn.keymap_items.new('node.tree_path_parent', 'TAB', 'PRESS', ctrl=True)
|
||||
kmn.keymap_items.new('lnx.ungroup_group_tree', 'G', 'PRESS', alt=True)
|
||||
|
||||
|
||||
def unregister():
|
||||
wm = bpy.context.window_manager
|
||||
for km in lnx.keymaps:
|
||||
wm.keyconfigs.addon.keymaps.remove(km)
|
||||
del lnx.keymaps[:]
|
||||
kmw = bpy.context.window_manager.keyconfigs.user.keymaps.get('Window')
|
||||
kmw.keymap_items.remove(kmw.keymap_items[props_ui.LeenkxPlayButton.bl_idname])
|
||||
kmw.keymap_items.remove(kmw.keymap_items['tlm.build_lightmaps'])
|
||||
kmw.keymap_items.remove(kmw.keymap_items['tlm.clean_lightmaps'])
|
||||
kmn = bpy.context.window_manager.keyconfigs.user.keymaps.get('Node Editor')
|
||||
kmn.keymap_items.remove(kmn.keymap_items['lnx.add_call_group_node'])
|
||||
kmn.keymap_items.remove(kmn.keymap_items['lnx.add_group_tree_from_selected'])
|
||||
kmn.keymap_items.remove(kmn.keymap_items['lnx.edit_group_tree'])
|
||||
kmn.keymap_items.remove(kmn.keymap_items['node.tree_path_parent'])
|
||||
kmn.keymap_items.remove(kmn.keymap_items['lnx.ungroup_group_tree'])
|
||||
|
@ -5,7 +5,8 @@ class TLM_Logman:
|
||||
|
||||
_log = []
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(TLM_Logman, self).__init__(*args, **kwargs)
|
||||
print("Logger started Init")
|
||||
self.append("Logger started.")
|
||||
|
||||
|
@ -1,25 +1,25 @@
|
||||
from lnx.logicnode.lnx_nodes import *
|
||||
|
||||
class BlendActionNode(LnxLogicTreeNode):
|
||||
"""Interpolates between the two given actions."""
|
||||
bl_idname = 'LNBlendActionNode'
|
||||
bl_label = 'Blend Action'
|
||||
lnx_version = 2
|
||||
|
||||
def lnx_init(self, context):
|
||||
self.add_input('LnxNodeSocketObject', 'Object')
|
||||
self.add_input('LnxNodeSocketAnimTree', 'Action 1')
|
||||
self.add_input('LnxNodeSocketAnimTree', 'Action 2')
|
||||
self.add_input('ArmFactorSocket', 'Factor', default_value = 0.5)
|
||||
self.add_input('LnxIntSocket', 'Bone Group', default_value = -1)
|
||||
|
||||
self.add_output('LnxNodeSocketAnimTree', 'Result')
|
||||
|
||||
def get_replacement_node(self, node_tree: bpy.types.NodeTree):
|
||||
if self.lnx_version not in (0, 1):
|
||||
raise LookupError()
|
||||
|
||||
return NodeReplacement(
|
||||
'LNBlendActionNode', self.lnx_version, 'LNBlendActionNode', 2,
|
||||
in_socket_mapping={}, out_socket_mapping={}
|
||||
)
|
||||
from lnx.logicnode.lnx_nodes import *
|
||||
|
||||
class BlendActionNode(LnxLogicTreeNode):
|
||||
"""Interpolates between the two given actions."""
|
||||
bl_idname = 'LNBlendActionNode'
|
||||
bl_label = 'Blend Action'
|
||||
lnx_version = 2
|
||||
|
||||
def lnx_init(self, context):
|
||||
self.add_input('LnxNodeSocketObject', 'Object')
|
||||
self.add_input('LnxNodeSocketAnimTree', 'Action 1')
|
||||
self.add_input('LnxNodeSocketAnimTree', 'Action 2')
|
||||
self.add_input('LnxFactorSocket', 'Factor', default_value = 0.5)
|
||||
self.add_input('LnxIntSocket', 'Bone Group', default_value = -1)
|
||||
|
||||
self.add_output('LnxNodeSocketAnimTree', 'Result')
|
||||
|
||||
def get_replacement_node(self, node_tree: bpy.types.NodeTree):
|
||||
if self.lnx_version not in (0, 1):
|
||||
raise LookupError()
|
||||
|
||||
return NodeReplacement(
|
||||
'LNBlendActionNode', self.lnx_version, 'LNBlendActionNode', 2,
|
||||
in_socket_mapping={}, out_socket_mapping={}
|
||||
)
|
||||
|
@ -90,7 +90,8 @@ class BlendSpaceNode(LnxLogicTreeNode):
|
||||
draw_handler_dict = {}
|
||||
modal_handler_dict = {}
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(BlendSpaceNode, self).__init__(*args, **kwargs)
|
||||
array_nodes[str(id(self))] = self
|
||||
if self.advanced_draw_run:
|
||||
self.add_advanced_draw()
|
||||
@ -112,8 +113,8 @@ class BlendSpaceNode(LnxLogicTreeNode):
|
||||
def lnx_init(self, context):
|
||||
self.add_input('LnxNodeSocketObject', 'Object')
|
||||
self.add_input('LnxNodeSocketArray', 'Actions')
|
||||
self.add_input('ArmBlendSpaceSocket', 'Cursor X')
|
||||
self.add_input('ArmBlendSpaceSocket', 'Cursor Y')
|
||||
self.add_input('LnxBlendSpaceSocket', 'Cursor X')
|
||||
self.add_input('LnxBlendSpaceSocket', 'Cursor Y')
|
||||
self.add_output('LnxNodeSocketAnimTree', 'Out')
|
||||
|
||||
def add_advanced_draw(self):
|
||||
|
@ -45,7 +45,7 @@ class BoneIKNode(LnxLogicTreeNode):
|
||||
self.add_input('LnxBoolSocket', 'Enable Pole')
|
||||
self.add_input('LnxVectorSocket', 'Pole Position')
|
||||
self.add_input('LnxFloatSocket', 'Roll Angle')
|
||||
self.add_input('ArmFactorSocket', 'Influence', default_value = 1.0)
|
||||
self.add_input('LnxFactorSocket', 'Influence', default_value = 1.0)
|
||||
self.add_input('LnxIntSocket', 'Bone Group', default_value = 0)
|
||||
|
||||
self.add_output('LnxNodeSocketAnimTree', 'Result')
|
||||
|
@ -8,8 +8,8 @@ class OneShotActionMultiNode(LnxLogicTreeNode):
|
||||
lnx_version = 1
|
||||
min_inputs = 10
|
||||
|
||||
def __init__(self):
|
||||
super(OneShotActionMultiNode, self).__init__()
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(OneShotActionMultiNode, self).__init__(*args, **kwargs)
|
||||
array_nodes[self.get_id_str()] = self
|
||||
|
||||
property0: HaxeStringProperty('property0', name = 'Action ID', default = '')
|
||||
|
@ -0,0 +1,16 @@
|
||||
from lnx.logicnode.lnx_nodes import *
|
||||
|
||||
class SetBoneTransformNode(LnxLogicTreeNode):
|
||||
"""Sets the bones transform in world space."""
|
||||
bl_idname = 'LNSetBoneTransformNode'
|
||||
bl_label = 'Set Bone Transform'
|
||||
lnx_version = 1
|
||||
lnx_section = 'armature'
|
||||
|
||||
def lnx_init(self, context):
|
||||
self.add_input('LnxNodeSocketAction', 'In')
|
||||
self.add_input('LnxNodeSocketObject', 'Object')
|
||||
self.add_input('LnxStringSocket', 'Bone')
|
||||
self.add_input('LnxDynamicSocket', 'Transform')
|
||||
|
||||
self.add_output('LnxNodeSocketAction', 'Out')
|
@ -12,5 +12,7 @@ class SetParentBoneNode(LnxLogicTreeNode):
|
||||
self.add_input('LnxNodeSocketObject', 'Object')
|
||||
self.add_input('LnxNodeSocketObject', 'Parent')
|
||||
self.add_input('LnxStringSocket', 'Bone', default_value='Bone')
|
||||
|
||||
self.add_input('LnxBoolSocket', 'Set Inverse')
|
||||
self.add_input('LnxBoolSocket', 'Keep Transform')
|
||||
|
||||
self.add_output('LnxNodeSocketAction', 'Out')
|
||||
|
@ -7,8 +7,8 @@ class SwitchActionMultiNode(LnxLogicTreeNode):
|
||||
lnx_version = 1
|
||||
min_inputs = 8
|
||||
|
||||
def __init__(self):
|
||||
super(SwitchActionMultiNode, self).__init__()
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(SwitchActionMultiNode, self).__init__(*args, **kwargs)
|
||||
array_nodes[self.get_id_str()] = self
|
||||
|
||||
def lnx_init(self, context):
|
||||
|
@ -9,7 +9,8 @@ class ArrayNode(LnxLogicVariableNodeMixin, LnxLogicTreeNode):
|
||||
lnx_section = 'variable'
|
||||
min_inputs = 0
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ArrayNode, self).__init__(*args, **kwargs)
|
||||
self.register_id()
|
||||
|
||||
def lnx_init(self, context):
|
||||
|
@ -12,8 +12,8 @@ class ArrayAddNode(LnxLogicTreeNode):
|
||||
lnx_version = 5
|
||||
min_inputs = 6
|
||||
|
||||
def __init__(self):
|
||||
super(ArrayAddNode, self).__init__()
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ArrayAddNode, self).__init__(*args, **kwargs)
|
||||
array_nodes[self.get_id_str()] = self
|
||||
|
||||
def lnx_init(self, context):
|
||||
|
@ -9,8 +9,8 @@ class BooleanArrayNode(LnxLogicVariableNodeMixin, LnxLogicTreeNode):
|
||||
lnx_section = 'variable'
|
||||
min_inputs = 0
|
||||
|
||||
def __init__(self):
|
||||
super(BooleanArrayNode, self).__init__()
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(BooleanArrayNode, self).__init__(*args, **kwargs)
|
||||
self.register_id()
|
||||
|
||||
def lnx_init(self, context):
|
||||
|
@ -9,8 +9,8 @@ class ColorArrayNode(LnxLogicVariableNodeMixin, LnxLogicTreeNode):
|
||||
lnx_section = 'variable'
|
||||
min_inputs = 0
|
||||
|
||||
def __init__(self):
|
||||
super(ColorArrayNode, self).__init__()
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ColorArrayNode, self).__init__(*args, **kwargs)
|
||||
self.register_id()
|
||||
|
||||
def lnx_init(self, context):
|
||||
|
@ -9,8 +9,8 @@ class FloatArrayNode(LnxLogicVariableNodeMixin, LnxLogicTreeNode):
|
||||
lnx_section = 'variable'
|
||||
min_inputs = 0
|
||||
|
||||
def __init__(self):
|
||||
super(FloatArrayNode, self).__init__()
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(FloatArrayNode, self).__init__(*args, **kwargs)
|
||||
self.register_id()
|
||||
|
||||
def lnx_init(self, context):
|
||||
|
13
leenkx/blender/lnx/logicnode/array/LN_array_index_list.py
Normal file
@ -0,0 +1,13 @@
|
||||
from lnx.logicnode.lnx_nodes import *
|
||||
|
||||
class ArrayIndexNode(LnxLogicTreeNode):
|
||||
"""Returns the array index list of the given value as an array."""
|
||||
bl_idname = 'LNArrayIndexListNode'
|
||||
bl_label = 'Array Index List'
|
||||
lnx_version = 1
|
||||
|
||||
def lnx_init(self, context):
|
||||
self.add_input('LnxNodeSocketArray', 'Array')
|
||||
self.add_input('LnxDynamicSocket', 'Value')
|
||||
|
||||
self.add_output('LnxNodeSocketArray', 'Array')
|