diff --git a/engine/build.cpp b/engine/build.cpp index 3e2f095..8a89c0e 100644 --- a/engine/build.cpp +++ b/engine/build.cpp @@ -33,6 +33,10 @@ DECLARE_BUILD_STAGE(engine) "openxr.cpp", }; + if (ldProject.m_target.kernel == TARGET_KERNEL_ANDROID) + { + compileProject.files.AppendTail("filesystem_android.cpp"); + } if ( GET_PROJECT_VALUE(config, "steam") == "true" ) { diff --git a/engine/cl_dll.cpp b/engine/cl_dll.cpp index 7072e6e..7ca843e 100644 --- a/engine/cl_dll.cpp +++ b/engine/cl_dll.cpp @@ -11,7 +11,7 @@ void CClientGameDLL::Init() CreateInterfaceFn pfnServerFactory = Sys_GetFactory("client"); - IEngineBridge *pEngineBridge = (IEngineBridge*)pfnServerFactory(ENGINE_BRIDGE_INTERFACE_VERSION, NULL); + IEngineBridge *pEngineBridge = (IEngineBridge*)pfnServerFactory(CLIENT_ENGINE_BRIDGE_INTERFACE_VERSION, NULL); pEngineBridge->ConnectInterface(FILESYSTEM_INTERFACE_VERSION, filesystem); pEngineBridge->ConnectInterface(RENDER_CONTEXT_INTERFACE_VERSION, m_pRenderContext); diff --git a/engine/engine.cpp b/engine/engine.cpp index dedf7b1..d2eb098 100644 --- a/engine/engine.cpp +++ b/engine/engine.cpp @@ -151,8 +151,6 @@ extern "C" void FunnyMain( int argc, char **argv ) g_pWindowManager->Frame(fDelta); g_pClientGame->m_pBridge->Frame(fDelta); g_pRenderContext->Frame(fDelta); - - fCurrent = Plat_GetTime(); } Console()->Execute(); diff --git a/engine/filesystem_android.cpp b/engine/filesystem_android.cpp new file mode 100644 index 0000000..d17b6ef --- /dev/null +++ b/engine/filesystem_android.cpp @@ -0,0 +1,139 @@ +#include "tier2/ifilesystem.h" +#include "tier1/interface.h" +#include "android/asset_manager.h" +#include "android/android_native_app_glue.h" + +class CAndroidFileHandle : public IFileHandle +{ +public: + AAsset *m_pFile; + size_t m_nSize; + +}; + +class CAndroidDirectoryHandle: public IDirectoryHandle +{ +public: +}; + +#include "android/log.h" +#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, "funnygame", __VA_ARGS__) +extern struct android_app *g_android_app; +class CAndroidFileSystem : public IFileSystem +{ +public: + virtual void Init() override { + + }; + virtual void Shutdown() override {}; + + virtual IFileHandle *Open( const char *szFileName, int eOpCode ) override + { + LOGI("Opening file: %s", szFileName); + FILE *pFile; + CAndroidFileHandle *pHandle = NULL; + + switch (eOpCode) + { + case FILEMODE_READ: + break; + default: + return 0; + } + + pHandle = new CAndroidFileHandle; + pHandle->m_pFileSystem = this; + pHandle->m_pFile = AAssetManager_open(g_android_app->activity->assetManager, szFileName, AASSET_MODE_RANDOM); + LOGI("Opened file: %p", pHandle->m_pFile); + pHandle->m_nSize = AAsset_getLength64(pHandle->m_pFile); + return pHandle; + } + virtual size_t Write( IFileHandle *pFile, const void *pData, size_t nDataSize ) override + { + } + virtual size_t Read( IFileHandle *pFile, void *pData, size_t nDataSize ) override + { + CAndroidFileHandle *pHandle = (CAndroidFileHandle*)pFile; + if (!pHandle) + return 0; + return AAsset_read(pHandle->m_pFile, pData, nDataSize); + } + + virtual size_t Seek( IFileHandle *pFile, ESeekMode eSeekMode, size_t nOffset ) override + { + CAndroidFileHandle *pHandle = (CAndroidFileHandle*)pFile; + int eLibcSeekMode = 0; + + if (!pHandle) + return 0; + + switch (eSeekMode) { + case SEEKMODE_RELATIVE_CURRENT: + eLibcSeekMode = SEEK_CUR; + break; + case SEEKMODE_RELATIVE_END: + eLibcSeekMode = SEEK_END; + break; + case SEEKMODE_RELATIVE_START: + eLibcSeekMode = SEEK_SET; + break; + } + return AAsset_seek64(pHandle->m_pFile, nOffset, eLibcSeekMode); + } + + virtual size_t Tell( IFileHandle *pFile ) override + { + CAndroidFileHandle *pHandle = (CAndroidFileHandle*)pFile; + if (!pHandle) + return 0; + return AAsset_seek64(pHandle->m_pFile, 0, SEEK_CUR); + } + + virtual size_t Size( IFileHandle *pFile ) override + { + CAndroidFileHandle *pHandle = (CAndroidFileHandle*)pFile; + if (!pHandle) + return 0; + return pHandle->m_nSize; + } + + + + virtual void Close( IFileHandle *pFile ) override + { + CAndroidFileHandle *pHandle = (CAndroidFileHandle*)pFile; + if (!pHandle) + return; + AAsset_close(pHandle->m_pFile); + delete pHandle; + } + + virtual CUtlBuffer Read( IFileHandle *pFile ) override { return {}; }; + virtual const char *ReadString( IFileHandle *pFile ) override { + char *szData = NULL; + size_t uSize = Size(pFile); + + szData = (char*)V_malloc(uSize+1); + Read(pFile, szData,uSize); + szData[uSize] = 0; + + return szData; + }; + + virtual size_t PrintF( IFileHandle *pFile, const char *szFormat, ... ) override + { + return 0; + } + + virtual IDirectoryHandle *OpenDir( const char *szDirName ) override + { + return NULL; + + }; + + virtual void CloseDir( IDirectoryHandle *pDir ) override + { + }; +}; + +EXPOSE_INTERFACE(CAndroidFileSystem, IFileSystem, FILESYSTEM_INTERFACE_VERSION) diff --git a/engine/sv_dll.cpp b/engine/sv_dll.cpp index cf5dc37..fd5a154 100644 --- a/engine/sv_dll.cpp +++ b/engine/sv_dll.cpp @@ -7,10 +7,9 @@ void CServerGameDLL::Init() { CreateInterfaceFn pfnServerFactory = Sys_GetFactory("server"); - IEngineBridge *pEngineBridge = (IEngineBridge*)pfnServerFactory(ENGINE_BRIDGE_INTERFACE_VERSION, NULL); + IEngineBridge *pEngineBridge = (IEngineBridge*)pfnServerFactory(SERVER_ENGINE_BRIDGE_INTERFACE_VERSION, NULL); pEngineBridge->ConnectInterface(FILESYSTEM_INTERFACE_VERSION, filesystem); pEngineBridge->ConnectInterface("EngineConstants", m_pEngineConsts); - pEngineBridge->ConnectInterface(FILESYSTEM_INTERFACE_VERSION, filesystem); pEngineBridge->Init(); m_pBridge = pEngineBridge; } diff --git a/external/android/aarch64/libVkLayer_khronos_validation.so b/external/android/aarch64/libVkLayer_khronos_validation.so new file mode 100644 index 0000000..6c6f62e Binary files /dev/null and b/external/android/aarch64/libVkLayer_khronos_validation.so differ diff --git a/external/android/aarch64/libc++_shared.so b/external/android/aarch64/libc++_shared.so new file mode 100755 index 0000000..e978645 Binary files /dev/null and b/external/android/aarch64/libc++_shared.so differ diff --git a/external/android/aarch64/libopenxr_loader.so b/external/android/aarch64/libopenxr_loader.so new file mode 100644 index 0000000..ef4dea6 Binary files /dev/null and b/external/android/aarch64/libopenxr_loader.so differ diff --git a/external/android/android_native_app_glue.c b/external/android/android_native_app_glue.c new file mode 100644 index 0000000..1e63c5e --- /dev/null +++ b/external/android/android_native_app_glue.c @@ -0,0 +1,457 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * 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. + */ + +#include "android_native_app_glue.h" + +#include + +#include +#include +#include +#include + +#include + +#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "threaded_app", __VA_ARGS__)) +#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "threaded_app", __VA_ARGS__)) + +/* For debug builds, always enable the debug traces in this library */ +#ifndef NDEBUG +# define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, "threaded_app", __VA_ARGS__)) +#else +# define LOGV(...) ((void)0) +#endif + +static void free_saved_state(struct android_app* android_app) { + pthread_mutex_lock(&android_app->mutex); + if (android_app->savedState != NULL) { + free(android_app->savedState); + android_app->savedState = NULL; + android_app->savedStateSize = 0; + } + pthread_mutex_unlock(&android_app->mutex); +} + +int8_t android_app_read_cmd(struct android_app* android_app) { + int8_t cmd; + if (read(android_app->msgread, &cmd, sizeof(cmd)) != sizeof(cmd)) { + LOGE("No data on command pipe!"); + return -1; + } + if (cmd == APP_CMD_SAVE_STATE) free_saved_state(android_app); + return cmd; +} + +static void print_cur_config(struct android_app* android_app) { + char lang[2], country[2]; + AConfiguration_getLanguage(android_app->config, lang); + AConfiguration_getCountry(android_app->config, country); + + LOGV("Config: mcc=%d mnc=%d lang=%c%c cnt=%c%c orien=%d touch=%d dens=%d " + "keys=%d nav=%d keysHid=%d navHid=%d sdk=%d size=%d long=%d " + "modetype=%d modenight=%d", + AConfiguration_getMcc(android_app->config), + AConfiguration_getMnc(android_app->config), + lang[0], lang[1], country[0], country[1], + AConfiguration_getOrientation(android_app->config), + AConfiguration_getTouchscreen(android_app->config), + AConfiguration_getDensity(android_app->config), + AConfiguration_getKeyboard(android_app->config), + AConfiguration_getNavigation(android_app->config), + AConfiguration_getKeysHidden(android_app->config), + AConfiguration_getNavHidden(android_app->config), + AConfiguration_getSdkVersion(android_app->config), + AConfiguration_getScreenSize(android_app->config), + AConfiguration_getScreenLong(android_app->config), + AConfiguration_getUiModeType(android_app->config), + AConfiguration_getUiModeNight(android_app->config)); +} + +void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd) { + switch (cmd) { + case APP_CMD_INPUT_CHANGED: + LOGV("APP_CMD_INPUT_CHANGED"); + pthread_mutex_lock(&android_app->mutex); + if (android_app->inputQueue != NULL) { + AInputQueue_detachLooper(android_app->inputQueue); + } + android_app->inputQueue = android_app->pendingInputQueue; + if (android_app->inputQueue != NULL) { + LOGV("Attaching input queue to looper"); + AInputQueue_attachLooper(android_app->inputQueue, + android_app->looper, LOOPER_ID_INPUT, NULL, + &android_app->inputPollSource); + } + pthread_cond_broadcast(&android_app->cond); + pthread_mutex_unlock(&android_app->mutex); + break; + + case APP_CMD_INIT_WINDOW: + LOGV("APP_CMD_INIT_WINDOW"); + pthread_mutex_lock(&android_app->mutex); + android_app->window = android_app->pendingWindow; + pthread_cond_broadcast(&android_app->cond); + pthread_mutex_unlock(&android_app->mutex); + break; + + case APP_CMD_TERM_WINDOW: + LOGV("APP_CMD_TERM_WINDOW"); + pthread_cond_broadcast(&android_app->cond); + break; + + case APP_CMD_RESUME: + case APP_CMD_START: + case APP_CMD_PAUSE: + case APP_CMD_STOP: + LOGV("activityState=%d", cmd); + pthread_mutex_lock(&android_app->mutex); + android_app->activityState = cmd; + pthread_cond_broadcast(&android_app->cond); + pthread_mutex_unlock(&android_app->mutex); + break; + + case APP_CMD_CONFIG_CHANGED: + LOGV("APP_CMD_CONFIG_CHANGED"); + AConfiguration_fromAssetManager(android_app->config, + android_app->activity->assetManager); + print_cur_config(android_app); + break; + + case APP_CMD_DESTROY: + LOGV("APP_CMD_DESTROY"); + android_app->destroyRequested = 1; + break; + } +} + +void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd) { + switch (cmd) { + case APP_CMD_TERM_WINDOW: + LOGV("APP_CMD_TERM_WINDOW"); + pthread_mutex_lock(&android_app->mutex); + android_app->window = NULL; + pthread_cond_broadcast(&android_app->cond); + pthread_mutex_unlock(&android_app->mutex); + break; + + case APP_CMD_SAVE_STATE: + LOGV("APP_CMD_SAVE_STATE"); + pthread_mutex_lock(&android_app->mutex); + android_app->stateSaved = 1; + pthread_cond_broadcast(&android_app->cond); + pthread_mutex_unlock(&android_app->mutex); + break; + + case APP_CMD_RESUME: + free_saved_state(android_app); + break; + } +} + +void app_dummy() { +} + +static void android_app_destroy(struct android_app* android_app) { + LOGV("android_app_destroy!"); + free_saved_state(android_app); + pthread_mutex_lock(&android_app->mutex); + if (android_app->inputQueue != NULL) { + AInputQueue_detachLooper(android_app->inputQueue); + } + AConfiguration_delete(android_app->config); + android_app->destroyed = 1; + pthread_cond_broadcast(&android_app->cond); + pthread_mutex_unlock(&android_app->mutex); + // Can't touch android_app object after this. +} + +static void process_input(struct android_app* app, struct android_poll_source* source) { + AInputEvent* event = NULL; + while (AInputQueue_getEvent(app->inputQueue, &event) >= 0) { + LOGV("New input event: type=%d", AInputEvent_getType(event)); + if (AInputQueue_preDispatchEvent(app->inputQueue, event)) { + continue; + } + int32_t handled = 0; + if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event); + AInputQueue_finishEvent(app->inputQueue, event, handled); + } +} + +static void process_cmd(struct android_app* app, struct android_poll_source* source) { + int8_t cmd = android_app_read_cmd(app); + android_app_pre_exec_cmd(app, cmd); + if (app->onAppCmd != NULL) app->onAppCmd(app, cmd); + android_app_post_exec_cmd(app, cmd); +} + +static void* android_app_entry(void* param) { + struct android_app* android_app = (struct android_app*)param; + + android_app->config = AConfiguration_new(); + AConfiguration_fromAssetManager(android_app->config, android_app->activity->assetManager); + + print_cur_config(android_app); + + android_app->cmdPollSource.id = LOOPER_ID_MAIN; + android_app->cmdPollSource.app = android_app; + android_app->cmdPollSource.process = process_cmd; + android_app->inputPollSource.id = LOOPER_ID_INPUT; + android_app->inputPollSource.app = android_app; + android_app->inputPollSource.process = process_input; + + ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); + ALooper_addFd(looper, android_app->msgread, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL, + &android_app->cmdPollSource); + android_app->looper = looper; + + pthread_mutex_lock(&android_app->mutex); + android_app->running = 1; + pthread_cond_broadcast(&android_app->cond); + pthread_mutex_unlock(&android_app->mutex); + + android_main(android_app); + + android_app_destroy(android_app); + return NULL; +} + +// -------------------------------------------------------------------- +// Native activity interaction (called from main thread) +// -------------------------------------------------------------------- + +static struct android_app* android_app_create(ANativeActivity* activity, + void* savedState, size_t savedStateSize) { + struct android_app* android_app = calloc(1, sizeof(struct android_app)); + android_app->activity = activity; + + pthread_mutex_init(&android_app->mutex, NULL); + pthread_cond_init(&android_app->cond, NULL); + + if (savedState != NULL) { + android_app->savedState = malloc(savedStateSize); + android_app->savedStateSize = savedStateSize; + memcpy(android_app->savedState, savedState, savedStateSize); + } + + int msgpipe[2]; + if (pipe(msgpipe)) { + LOGE("could not create pipe: %s", strerror(errno)); + return NULL; + } + android_app->msgread = msgpipe[0]; + android_app->msgwrite = msgpipe[1]; + + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pthread_create(&android_app->thread, &attr, android_app_entry, android_app); + + // Wait for thread to start. + pthread_mutex_lock(&android_app->mutex); + while (!android_app->running) { + pthread_cond_wait(&android_app->cond, &android_app->mutex); + } + pthread_mutex_unlock(&android_app->mutex); + + return android_app; +} + +static void android_app_write_cmd(struct android_app* android_app, int8_t cmd) { + if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd)) { + LOGE("Failure writing android_app cmd: %s", strerror(errno)); + } +} + +static void android_app_set_input(struct android_app* android_app, AInputQueue* inputQueue) { + pthread_mutex_lock(&android_app->mutex); + android_app->pendingInputQueue = inputQueue; + android_app_write_cmd(android_app, APP_CMD_INPUT_CHANGED); + while (android_app->inputQueue != android_app->pendingInputQueue) { + pthread_cond_wait(&android_app->cond, &android_app->mutex); + } + pthread_mutex_unlock(&android_app->mutex); +} + +static void android_app_set_window(struct android_app* android_app, ANativeWindow* window) { + pthread_mutex_lock(&android_app->mutex); + if (android_app->pendingWindow != NULL) { + android_app_write_cmd(android_app, APP_CMD_TERM_WINDOW); + } + android_app->pendingWindow = window; + if (window != NULL) { + android_app_write_cmd(android_app, APP_CMD_INIT_WINDOW); + } + while (android_app->window != android_app->pendingWindow) { + pthread_cond_wait(&android_app->cond, &android_app->mutex); + } + pthread_mutex_unlock(&android_app->mutex); +} + +static void android_app_set_activity_state(struct android_app* android_app, int8_t cmd) { + pthread_mutex_lock(&android_app->mutex); + android_app_write_cmd(android_app, cmd); + while (android_app->activityState != cmd) { + pthread_cond_wait(&android_app->cond, &android_app->mutex); + } + pthread_mutex_unlock(&android_app->mutex); +} + +static void android_app_free(struct android_app* android_app) { + pthread_mutex_lock(&android_app->mutex); + android_app_write_cmd(android_app, APP_CMD_DESTROY); + while (!android_app->destroyed) { + pthread_cond_wait(&android_app->cond, &android_app->mutex); + } + pthread_mutex_unlock(&android_app->mutex); + + close(android_app->msgread); + close(android_app->msgwrite); + pthread_cond_destroy(&android_app->cond); + pthread_mutex_destroy(&android_app->mutex); + free(android_app); +} + +static struct android_app* ToApp(ANativeActivity* activity) { + return (struct android_app*) activity->instance; +} + +static void onDestroy(ANativeActivity* activity) { + LOGV("Destroy: %p", activity); + android_app_free(ToApp(activity)); +} + +static void onStart(ANativeActivity* activity) { + LOGV("Start: %p", activity); + android_app_set_activity_state(ToApp(activity), APP_CMD_START); +} + +static void onResume(ANativeActivity* activity) { + LOGV("Resume: %p", activity); + android_app_set_activity_state(ToApp(activity), APP_CMD_RESUME); +} + +static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) { + LOGV("SaveInstanceState: %p", activity); + + struct android_app* android_app = ToApp(activity); + void* savedState = NULL; + pthread_mutex_lock(&android_app->mutex); + android_app->stateSaved = 0; + android_app_write_cmd(android_app, APP_CMD_SAVE_STATE); + while (!android_app->stateSaved) { + pthread_cond_wait(&android_app->cond, &android_app->mutex); + } + + if (android_app->savedState != NULL) { + savedState = android_app->savedState; + *outLen = android_app->savedStateSize; + android_app->savedState = NULL; + android_app->savedStateSize = 0; + } + + pthread_mutex_unlock(&android_app->mutex); + + return savedState; +} + +static void onPause(ANativeActivity* activity) { + LOGV("Pause: %p", activity); + android_app_set_activity_state(ToApp(activity), APP_CMD_PAUSE); +} + +static void onStop(ANativeActivity* activity) { + LOGV("Stop: %p", activity); + android_app_set_activity_state(ToApp(activity), APP_CMD_STOP); +} + +static void onConfigurationChanged(ANativeActivity* activity) { + LOGV("ConfigurationChanged: %p", activity); + android_app_write_cmd(ToApp(activity), APP_CMD_CONFIG_CHANGED); +} + +static void onContentRectChanged(ANativeActivity* activity, const ARect* r) { + LOGV("ContentRectChanged: l=%d,t=%d,r=%d,b=%d", r->left, r->top, r->right, r->bottom); + struct android_app* android_app = ToApp(activity); + pthread_mutex_lock(&android_app->mutex); + android_app->contentRect = *r; + pthread_mutex_unlock(&android_app->mutex); + android_app_write_cmd(ToApp(activity), APP_CMD_CONTENT_RECT_CHANGED); +} + +static void onLowMemory(ANativeActivity* activity) { + LOGV("LowMemory: %p", activity); + android_app_write_cmd(ToApp(activity), APP_CMD_LOW_MEMORY); +} + +static void onWindowFocusChanged(ANativeActivity* activity, int focused) { + LOGV("WindowFocusChanged: %p -- %d", activity, focused); + android_app_write_cmd(ToApp(activity), focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS); +} + +static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) { + LOGV("NativeWindowCreated: %p -- %p", activity, window); + android_app_set_window(ToApp(activity), window); +} + +static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) { + LOGV("NativeWindowDestroyed: %p -- %p", activity, window); + android_app_set_window(ToApp(activity), NULL); +} + +static void onNativeWindowRedrawNeeded(ANativeActivity* activity, ANativeWindow* window) { + LOGV("NativeWindowRedrawNeeded: %p -- %p", activity, window); + android_app_write_cmd(ToApp(activity), APP_CMD_WINDOW_REDRAW_NEEDED); +} + +static void onNativeWindowResized(ANativeActivity* activity, ANativeWindow* window) { + LOGV("NativeWindowResized: %p -- %p", activity, window); + android_app_write_cmd(ToApp(activity), APP_CMD_WINDOW_RESIZED); +} + +static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) { + LOGV("InputQueueCreated: %p -- %p", activity, queue); + android_app_set_input(ToApp(activity), queue); +} + +static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) { + LOGV("InputQueueDestroyed: %p -- %p", activity, queue); + android_app_set_input(ToApp(activity), NULL); +} + +JNIEXPORT +void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_t savedStateSize) { + LOGV("Creating: %p", activity); + + activity->callbacks->onConfigurationChanged = onConfigurationChanged; + activity->callbacks->onContentRectChanged = onContentRectChanged; + activity->callbacks->onDestroy = onDestroy; + activity->callbacks->onInputQueueCreated = onInputQueueCreated; + activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed; + activity->callbacks->onLowMemory = onLowMemory; + activity->callbacks->onNativeWindowCreated = onNativeWindowCreated; + activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed; + activity->callbacks->onNativeWindowRedrawNeeded = onNativeWindowRedrawNeeded; + activity->callbacks->onNativeWindowResized = onNativeWindowResized; + activity->callbacks->onPause = onPause; + activity->callbacks->onResume = onResume; + activity->callbacks->onSaveInstanceState = onSaveInstanceState; + activity->callbacks->onStart = onStart; + activity->callbacks->onStop = onStop; + activity->callbacks->onWindowFocusChanged = onWindowFocusChanged; + + activity->instance = android_app_create(activity, savedState, savedStateSize); +} diff --git a/external/android/android_native_app_glue.h b/external/android/android_native_app_glue.h new file mode 100644 index 0000000..f9d517f --- /dev/null +++ b/external/android/android_native_app_glue.h @@ -0,0 +1,354 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * 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. + */ + +#pragma once + +#include +#include +#include + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * The native activity interface provided by + * is based on a set of application-provided callbacks that will be called + * by the Activity's main thread when certain events occur. + * + * This means that each one of this callbacks _should_ _not_ block, or they + * risk having the system force-close the application. This programming + * model is direct, lightweight, but constraining. + * + * The 'android_native_app_glue' static library is used to provide a different + * execution model where the application can implement its own main event + * loop in a different thread instead. Here's how it works: + * + * 1/ The application must provide a function named "android_main()" that + * will be called when the activity is created (and again every time the + * activity is recreated), in a new thread that is distinct from the + * activity's main thread. + * + * 2/ android_main() receives a pointer to a valid "android_app" structure + * that contains references to other important objects, e.g. the + * ANativeActivity object instance the application is running in. + * + * 3/ the "android_app" object holds an ALooper instance that already + * listens to two important things: + * + * - activity lifecycle events (e.g. "pause", "resume"). See APP_CMD_XXX + * declarations below. + * + * - input events coming from the AInputQueue attached to the activity. + * + * Each of these correspond to an ALooper identifier returned by + * ALooper_pollOnce with values of LOOPER_ID_MAIN and LOOPER_ID_INPUT, + * respectively. + * + * Your application can use the same ALooper to listen to additional + * file-descriptors. They can either be callback based, or with return + * identifiers starting with LOOPER_ID_USER. + * + * 4/ Whenever you receive a LOOPER_ID_MAIN or LOOPER_ID_INPUT event, + * the returned data will point to an android_poll_source structure. You + * can call the process() function on it, and fill in android_app->onAppCmd + * and android_app->onInputEvent to be called for your own processing + * of the event. + * + * Alternatively, you can call the low-level functions to read and process + * the data directly... look at the process_cmd() and process_input() + * implementations in the glue to see how to do this. + * + * See the sample named "native-activity" that comes with the NDK with a + * full usage example. Also look at the JavaDoc of NativeActivity. + */ + +struct android_app; + +/** + * Data associated with an ALooper fd that will be returned as the "outData" + * when that source has data ready. + */ +struct android_poll_source { + // The identifier of this source. May be LOOPER_ID_MAIN or + // LOOPER_ID_INPUT. + int32_t id; + + // The android_app this ident is associated with. + struct android_app* app; + + // Function to call to perform the standard processing of data from + // this source. + void (*process)(struct android_app* app, struct android_poll_source* source); +}; + +/** + * This is the interface for the standard glue code of a threaded + * application. In this model, the application's code is running + * in its own thread separate from the main thread of the process. + * It is not required that this thread be associated with the Java + * VM, although it will need to be in order to make JNI calls any + * Java objects. + */ +struct android_app { + // The application can place a pointer to its own state object + // here if it likes. + void* userData; + + // Fill this in with the function to process main app commands (APP_CMD_*) + void (*onAppCmd)(struct android_app* app, int32_t cmd); + + // Fill this in with the function to process input events. At this point + // the event has already been pre-dispatched, and it will be finished upon + // return. Return 1 if you have handled the event, 0 for any default + // dispatching. + int32_t (*onInputEvent)(struct android_app* app, AInputEvent* event); + + // The ANativeActivity object instance that this app is running in. + ANativeActivity* activity; + + // The current configuration the app is running in. + AConfiguration* config; + + // This is the last instance's saved state, as provided at creation time. + // It is NULL if there was no state. You can use this as you need; the + // memory will remain around until you call android_app_exec_cmd() for + // APP_CMD_RESUME, at which point it will be freed and savedState set to NULL. + // These variables should only be changed when processing a APP_CMD_SAVE_STATE, + // at which point they will be initialized to NULL and you can malloc your + // state and place the information here. In that case the memory will be + // freed for you later. + void* savedState; + size_t savedStateSize; + + // The ALooper associated with the app's thread. + ALooper* looper; + + // When non-NULL, this is the input queue from which the app will + // receive user input events. + AInputQueue* inputQueue; + + // When non-NULL, this is the window surface that the app can draw in. + ANativeWindow* window; + + // Current content rectangle of the window; this is the area where the + // window's content should be placed to be seen by the user. + ARect contentRect; + + // Current state of the app's activity. May be either APP_CMD_START, + // APP_CMD_RESUME, APP_CMD_PAUSE, or APP_CMD_STOP; see below. + int activityState; + + // This is non-zero when the application's NativeActivity is being + // destroyed and waiting for the app thread to complete. + // Your android_main() must return to its caller when this is non-zero. + int destroyRequested; + + // ------------------------------------------------- + // Below are "private" implementation of the glue code. + + pthread_mutex_t mutex; + pthread_cond_t cond; + + int msgread; + int msgwrite; + + pthread_t thread; + + struct android_poll_source cmdPollSource; + struct android_poll_source inputPollSource; + + int running; + int stateSaved; + int destroyed; + int redrawNeeded; + AInputQueue* pendingInputQueue; + ANativeWindow* pendingWindow; + ARect pendingContentRect; +}; + +enum { + /** + * Looper data ID of commands coming from the app's main thread, which + * is returned as an identifier from ALooper_pollOnce(). The data for this + * identifier is a pointer to an android_poll_source structure. + * These can be retrieved and processed with android_app_read_cmd() + * and android_app_exec_cmd(). + */ + LOOPER_ID_MAIN = 1, + + /** + * Looper data ID of events coming from the AInputQueue of the + * application's window, which is returned as an identifier from + * ALooper_pollOnce(). The data for this identifier is a pointer to an + * android_poll_source structure. These can be read via the inputQueue + * object of android_app. + */ + LOOPER_ID_INPUT = 2, + + /** + * Start of user-defined ALooper identifiers. + */ + LOOPER_ID_USER = 3, +}; + +enum { + /** + * Command from main thread: the AInputQueue has changed. Upon processing + * this command, android_app->inputQueue will be updated to the new queue + * (or NULL). + */ + APP_CMD_INPUT_CHANGED, + + /** + * Command from main thread: a new ANativeWindow is ready for use. Upon + * receiving this command, android_app->window will contain the new window + * surface. + */ + APP_CMD_INIT_WINDOW, + + /** + * Command from main thread: the existing ANativeWindow needs to be + * terminated. Upon receiving this command, android_app->window still + * contains the existing window; after calling android_app_exec_cmd + * it will be set to NULL. + */ + APP_CMD_TERM_WINDOW, + + /** + * Command from main thread: the current ANativeWindow has been resized. + * Please redraw with its new size. + */ + APP_CMD_WINDOW_RESIZED, + + /** + * Command from main thread: the system needs that the current ANativeWindow + * be redrawn. You should redraw the window before handing this to + * android_app_exec_cmd() in order to avoid transient drawing glitches. + */ + APP_CMD_WINDOW_REDRAW_NEEDED, + + /** + * Command from main thread: the content area of the window has changed, + * such as from the soft input window being shown or hidden. You can + * find the new content rect in android_app::contentRect. + */ + APP_CMD_CONTENT_RECT_CHANGED, + + /** + * Command from main thread: the app's activity window has gained + * input focus. + */ + APP_CMD_GAINED_FOCUS, + + /** + * Command from main thread: the app's activity window has lost + * input focus. + */ + APP_CMD_LOST_FOCUS, + + /** + * Command from main thread: the current device configuration has changed. + */ + APP_CMD_CONFIG_CHANGED, + + /** + * Command from main thread: the system is running low on memory. + * Try to reduce your memory use. + */ + APP_CMD_LOW_MEMORY, + + /** + * Command from main thread: the app's activity has been started. + */ + APP_CMD_START, + + /** + * Command from main thread: the app's activity has been resumed. + */ + APP_CMD_RESUME, + + /** + * Command from main thread: the app should generate a new saved state + * for itself, to restore from later if needed. If you have saved state, + * allocate it with malloc and place it in android_app.savedState with + * the size in android_app.savedStateSize. The will be freed for you + * later. + */ + APP_CMD_SAVE_STATE, + + /** + * Command from main thread: the app's activity has been paused. + */ + APP_CMD_PAUSE, + + /** + * Command from main thread: the app's activity has been stopped. + */ + APP_CMD_STOP, + + /** + * Command from main thread: the app's activity is being destroyed, + * and waiting for the app thread to clean up and exit before proceeding. + */ + APP_CMD_DESTROY, +}; + +/** + * Call when ALooper_pollAll() returns LOOPER_ID_MAIN, reading the next + * app command message. + */ +int8_t android_app_read_cmd(struct android_app* android_app); + +/** + * Call with the command returned by android_app_read_cmd() to do the + * initial pre-processing of the given command. You can perform your own + * actions for the command after calling this function. + */ +void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd); + +/** + * Call with the command returned by android_app_read_cmd() to do the + * final post-processing of the given command. You must have done your own + * actions for the command before calling this function. + */ +void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd); + +/** + * No-op function that used to be used to prevent the linker from stripping app + * glue code. No longer necessary, since __attribute__((visibility("default"))) + * does this for us. + */ +__attribute__(( + deprecated("Calls to app_dummy are no longer necessary. See " + "https://github.com/android-ndk/ndk/issues/381."))) void +app_dummy(); + +/** + * This is the function that application code must implement, representing + * the main entry to the app. + * + * This is called every time the activity is recreated. + */ +extern void android_main(struct android_app* app); + +#ifdef __cplusplus +} +#endif diff --git a/game/client/assetmgr.cpp b/game/client/assetmgr.cpp index 06dc357..724c2fd 100644 --- a/game/client/assetmgr.cpp +++ b/game/client/assetmgr.cpp @@ -13,7 +13,7 @@ #define MAX_FONT_COUNT 128 template -class CAssetArc +class C_AssetArc { struct ObjectHandle_t { @@ -76,7 +76,7 @@ public: } }; -class CAssetManager: public IAssetManager +class C_AssetManager: public IAssetManager { public: virtual HFunnyModel LoadModel( const char *szName ) override; @@ -105,37 +105,37 @@ public: void LoadMaterialData( CBaseMaterial *pMaterial, IJSONObject *pObj ); - CAssetArc m_models = {}; - CAssetArc m_meshes = {}; - CAssetArc m_materials = {}; - CAssetArc m_textures = {}; - CAssetArc m_shaders = {}; - CAssetArc m_physics = {}; + C_AssetArc m_models = {}; + C_AssetArc m_meshes = {}; + C_AssetArc m_materials = {}; + C_AssetArc m_textures = {}; + C_AssetArc m_shaders = {}; + C_AssetArc m_physics = {}; }; -FunnyModel_t *CAssetManager::GetModelByIndex( uint32_t uIndex ) +FunnyModel_t *C_AssetManager::GetModelByIndex( uint32_t uIndex ) { return m_models.GetObjectPtr(uIndex); } -FunnyMaterial_t *CAssetManager::GetMaterialByIndex( uint32_t uIndex ) +FunnyMaterial_t *C_AssetManager::GetMaterialByIndex( uint32_t uIndex ) { return m_materials.GetObjectPtr(uIndex); } -IShader **CAssetManager::GetShaderByIndex( uint32_t uIndex ) +IShader **C_AssetManager::GetShaderByIndex( uint32_t uIndex ) { return m_shaders.GetObjectPtr(uIndex); } -FunnyMesh_t *CAssetManager::GetMeshByIndex( uint32_t uIndex ) +FunnyMesh_t *C_AssetManager::GetMeshByIndex( uint32_t uIndex ) { return m_meshes.GetObjectPtr(uIndex); } -uint32_t CAssetManager::LoadModel( const char *szName ) +uint32_t C_AssetManager::LoadModel( const char *szName ) { bool bHasBeenCreated = false; HFunnyModel hModel = m_models.GetOrCreateObject(szName, &bHasBeenCreated); @@ -189,12 +189,12 @@ uint32_t CAssetManager::LoadModel( const char *szName ) } } -void CAssetManager::UnrefModel( uint32_t uIndex ) +void C_AssetManager::UnrefModel( uint32_t uIndex ) { } -void CAssetManager::LoadMaterialData( CBaseMaterial *pMaterial, IJSONObject *pObj ) +void C_AssetManager::LoadMaterialData( CBaseMaterial *pMaterial, IJSONObject *pObj ) { for ( int i = 0; i < pMaterial->GetDataMap()->m_iNumFields; i++ ) { @@ -236,7 +236,7 @@ void CAssetManager::LoadMaterialData( CBaseMaterial *pMaterial, IJSONObject *pOb } -uint32_t CAssetManager::LoadMaterial( const char *szName ) +uint32_t C_AssetManager::LoadMaterial( const char *szName ) { bool bHasBeenCreated = false; HFunnyMaterial hMaterial = m_materials.GetOrCreateObject(szName, &bHasBeenCreated); @@ -288,12 +288,12 @@ uint32_t CAssetManager::LoadMaterial( const char *szName ) return hMaterial; } -void CAssetManager::UnrefMaterial( uint32_t uIndex ) +void C_AssetManager::UnrefMaterial( uint32_t uIndex ) { } -HFunnyMesh CAssetManager::LoadMesh( const char *szName ) +HFunnyMesh C_AssetManager::LoadMesh( const char *szName ) { bool bHasBeenCreated = false; HFunnyMesh hAsset = m_meshes.GetOrCreateObject(szName, &bHasBeenCreated); @@ -322,12 +322,12 @@ HFunnyMesh CAssetManager::LoadMesh( const char *szName ) return hAsset; } -void CAssetManager::UnrefMesh( uint32_t uIndex ) +void C_AssetManager::UnrefMesh( uint32_t uIndex ) { m_meshes.UnrefObject(uIndex); } -uint32_t CAssetManager::LoadShader( const char *szName ) +uint32_t C_AssetManager::LoadShader( const char *szName ) { bool bHasBeenCreated = false; uint32_t hShader = m_shaders.GetOrCreateObject(szName, &bHasBeenCreated); @@ -347,12 +347,12 @@ uint32_t CAssetManager::LoadShader( const char *szName ) return hShader; } -void CAssetManager::UnrefShader( uint32_t uIndex ) +void C_AssetManager::UnrefShader( uint32_t uIndex ) { m_shaders.UnrefObject(uIndex); } -HFunnyTexture CAssetManager::LoadTexture( const char *szName ) +HFunnyTexture C_AssetManager::LoadTexture( const char *szName ) { bool bHasBeenCreated = false; uint32_t hTexture = m_textures.GetOrCreateObject(szName, &bHasBeenCreated); @@ -372,18 +372,18 @@ HFunnyTexture CAssetManager::LoadTexture( const char *szName ) return hTexture; } -FunnyTexture_t *CAssetManager::GetTextureByIndex( HFunnyTexture hTexture ) +FunnyTexture_t *C_AssetManager::GetTextureByIndex( HFunnyTexture hTexture ) { return m_textures.GetObjectPtr(hTexture); } -void CAssetManager::UnrefTexture( uint32_t hTexture ) +void C_AssetManager::UnrefTexture( uint32_t hTexture ) { } -HFunnyPhysics CAssetManager::LoadPhysics( const char *szName ) +HFunnyPhysics C_AssetManager::LoadPhysics( const char *szName ) { bool bHasBeenCreated = false; HFunnyPhysics hPhysics = m_physics.GetOrCreateObject(szName, &bHasBeenCreated); @@ -436,12 +436,12 @@ HFunnyPhysics CAssetManager::LoadPhysics( const char *szName ) } -FunnyPhysics_t *CAssetManager::GetPhysicsByIndex( HFunnyPhysics hPhysics ) +FunnyPhysics_t *C_AssetManager::GetPhysicsByIndex( HFunnyPhysics hPhysics ) { return m_physics.GetObjectPtr(hPhysics); } -void CAssetManager::UnrefPhysics( HFunnyPhysics hPhysics ) +void C_AssetManager::UnrefPhysics( HFunnyPhysics hPhysics ) { m_physics.UnrefObject(hPhysics); } @@ -449,5 +449,5 @@ void CAssetManager::UnrefPhysics( HFunnyPhysics hPhysics ) -static CAssetManager s_assetmgr; +static C_AssetManager s_assetmgr; IAssetManager *g_pAssetManager = &s_assetmgr; diff --git a/game/client/baseentity.h b/game/client/baseentity.h index efe7e31..5eb08eb 100644 --- a/game/client/baseentity.h +++ b/game/client/baseentity.h @@ -20,7 +20,7 @@ typedef className ThisClass; #define LINK_ENTITY_TO_CLASS( mapClassName, DLLClassName) \ - static CEntityFactory g_EntityFactory_##mapClassName( #mapClassName ); \ + static C_EntityFactory g_EntityFactory_##mapClassName( #mapClassName ); \ class C_BaseEntity; @@ -32,12 +32,12 @@ public: template -class CEntityFactory : public IEntityFactory +class C_EntityFactory : public IEntityFactory { public: - CEntityFactory( const char *szClassName ) + C_EntityFactory( const char *szClassName ) { - EntitySystem()->RegisterEntityClass(this, szClassName); + ClientEntitySystem()->RegisterEntityClass(this, szClassName); }; virtual C_BaseEntity *Create() { return new T; diff --git a/game/client/basemodelentity.cpp b/game/client/basemodelentity.cpp index ba702b0..7390436 100644 --- a/game/client/basemodelentity.cpp +++ b/game/client/basemodelentity.cpp @@ -25,7 +25,7 @@ void C_BaseModelEntity::Think( float fDelta ) void C_BaseModelEntity::SetModel( const char *szName ) { V_memset(m_szModel, 0, 256); - V_strncpy(m_szModel, szName, 255); + V_memcpy(m_szModel, szName, 256); } void C_BaseModelEntity::UpdateModel() @@ -33,8 +33,7 @@ void C_BaseModelEntity::UpdateModel() if (!V_strncmp(m_szModel, m_szCurrentModel, 256)) return; - V_memset(m_szCurrentModel, 0, 256); - V_strncpy(m_szCurrentModel, m_szModel, 255); + V_memcpy(m_szCurrentModel, m_szModel, 256); if (m_hModelHandle) { diff --git a/game/client/entitysystem.cpp b/game/client/entitysystem.cpp index d13477b..a00e8fb 100644 --- a/game/client/entitysystem.cpp +++ b/game/client/entitysystem.cpp @@ -14,7 +14,7 @@ static C_BaseEntity *s_pLocalEntity; -C_EntitySystem *EntitySystem() +C_EntitySystem *ClientEntitySystem() { static C_EntitySystem s_entitySystem; return &s_entitySystem; @@ -25,7 +25,7 @@ static struct EntityRegistry_t IEntityFactory *m_pFactory; const char *m_szClassName; struct EntityRegistry_t *m_pNext; -} *s_pEntitiesRegistry = NULL; +} *s_pClientEntitiesRegistry = NULL; C_EntitySystem::C_EntitySystem() { @@ -52,9 +52,9 @@ void C_EntitySystem::RegisterEntityClass( IEntityFactory *pEntityFactory, const pRegistry = new EntityRegistry_t; pRegistry->m_pFactory = pEntityFactory; - pRegistry->m_pNext = s_pEntitiesRegistry; + pRegistry->m_pNext = s_pClientEntitiesRegistry; pRegistry->m_szClassName = szClassName; - s_pEntitiesRegistry = pRegistry; + s_pClientEntitiesRegistry = pRegistry; } C_BaseEntity *C_EntitySystem::CreateByClassname( const char *szName ) @@ -113,7 +113,7 @@ IEntityFactory *C_EntitySystem::GetFactoryByClassname( const char *szName ) { EntityRegistry_t *pEntity; - for ( pEntity = s_pEntitiesRegistry; pEntity; pEntity = pEntity->m_pNext ) + for ( pEntity = s_pClientEntitiesRegistry; pEntity; pEntity = pEntity->m_pNext ) { if (!strcmp(szName, pEntity->m_szClassName)) { diff --git a/game/client/entitysystem.h b/game/client/entitysystem.h index d778362..e4308d5 100644 --- a/game/client/entitysystem.h +++ b/game/client/entitysystem.h @@ -43,7 +43,7 @@ private: int m_nEntityCount; }; -C_EntitySystem *EntitySystem(); +C_EntitySystem *ClientEntitySystem(); C_BaseEntity *UTIL_GetLocalPlayer(); diff --git a/game/client/game.cpp b/game/client/game.cpp index d3b0378..c5e31db 100644 --- a/game/client/game.cpp +++ b/game/client/game.cpp @@ -15,7 +15,7 @@ #include "steam/steam_gameserver.h" #endif -class CFunnyGameBridge: public IEngineBridge +class CClientGameBridge: public IEngineBridge { virtual void Init() override; virtual void Tick( float fDelta ) override; @@ -33,18 +33,18 @@ class CFunnyGameBridge: public IEngineBridge }; -IEngineBridge *EngineBridge() +IEngineBridge *ClientEngineBridge() { - static CFunnyGameBridge s_bridge; + static CClientGameBridge s_bridge; return &s_bridge; } void XRInputCallback( IXRController *pController, EXRInputType_t eType, const char *szType, EXRInputActionType_t action, EXRInputValue_t value ); -EXPOSE_INTERFACE_FN(EngineBridge, IEngineBridge, ENGINE_BRIDGE_INTERFACE_VERSION) +EXPOSE_INTERFACE_FN(ClientEngineBridge, IClientEngineBridge, CLIENT_ENGINE_BRIDGE_INTERFACE_VERSION) -void CFunnyGameBridge::Init() +void CClientGameBridge::Init() { Console()->AddCommand("exec game/core/default.cfg\n"); Console()->Execute(); @@ -121,12 +121,12 @@ void CFunnyGameBridge::Init() */ } -void CFunnyGameBridge::Tick( float fDelta ) +void CClientGameBridge::Tick( float fDelta ) { } -void CFunnyGameBridge::TryToConnectToServer() +void CClientGameBridge::TryToConnectToServer() { #ifdef STEAM if (g_pEngineConstants->m_bIsSteam) @@ -145,10 +145,10 @@ void CFunnyGameBridge::TryToConnectToServer() if (g_pServerConnection) { m_bIsConnectedToServer = true; - C_BaseEntity **ppEntities = EntitySystem()->GetEntities(); + C_BaseEntity **ppEntities = ClientEntitySystem()->GetEntities(); for ( int i = 0; i < MAX_EDICTS; i++ ) { - EntitySystem()->DestroyEntityByIndex(i); + ClientEntitySystem()->DestroyEntityByIndex(i); } } return; @@ -156,9 +156,8 @@ void CFunnyGameBridge::TryToConnectToServer() #endif } -void CFunnyGameBridge::Frame( float fDelta ) +void CClientGameBridge::Frame( float fDelta ) { - if (g_pMainWindow->GetRenderWidth() != m_pMainViewport->GetWidth()) if (g_pMainWindow->GetRenderHeight() != m_pMainViewport->GetHeight()) m_pMainViewport->UpdateResolution(g_pMainWindow->GetRenderWidth(), g_pMainWindow->GetRenderHeight()); @@ -198,7 +197,7 @@ void CFunnyGameBridge::Frame( float fDelta ) case MESSAGE_ENTITY_CLASS_SYNC: case MESSAGE_ENTITY_DATA_SYNC: case k_EMessage_PlayerSetLocalEntity: - EntitySystem()->NetRecvPacket(&packet); + ClientEntitySystem()->NetRecvPacket(&packet); pCurrentServer->RecievePacket(); break; default: @@ -209,7 +208,7 @@ void CFunnyGameBridge::Frame( float fDelta ) } } - EntitySystem()->Think(); + ClientEntitySystem()->Think(); float fTickRate = 1.0/60.0; m_fNetUpdateTimer += fDelta; @@ -220,19 +219,19 @@ void CFunnyGameBridge::Frame( float fDelta ) m_fNetUpdateTimer-=fTickRate; m_fNetUpdateTimer = fmod(m_fNetUpdateTimer, fTickRate); if (pCurrentServer) - EntitySystem()->NetSendThink(pCurrentServer); + ClientEntitySystem()->NetSendThink(pCurrentServer); } g_pWorldRenderer->Frame(fDelta); g_pMainWindow->SetOutputImage(m_pMainViewport->GetRenderImage()); } -void CFunnyGameBridge::Shutdown() +void CClientGameBridge::Shutdown() { } #define CONNECT_INTERFACE(szName, pGlobal) if (!V_strcmp(psz, szName)) { pGlobal = (typeof(pGlobal))pInterface; return; } -void CFunnyGameBridge::ConnectInterface( const char *psz, void *pInterface ) +void CClientGameBridge::ConnectInterface( const char *psz, void *pInterface ) { CONNECT_INTERFACE(FILESYSTEM_INTERFACE_VERSION, filesystem); CONNECT_INTERFACE(RENDER_CONTEXT_INTERFACE_VERSION, g_pRenderContext); diff --git a/game/client/milmoba/player.cpp b/game/client/milmoba/player.cpp index 8d653e9..b91cd5f 100644 --- a/game/client/milmoba/player.cpp +++ b/game/client/milmoba/player.cpp @@ -26,8 +26,8 @@ void C_MOBAPlayer::Think( float fDelta ) if (pPlayerEntity == this) { } - m_pLeftHand = (C_MOBAPlayerHandController*)EntitySystem()->GetEntityByIndex(m_leftHandId); - m_pRightHand = (C_MOBAPlayerHandController*)EntitySystem()->GetEntityByIndex(m_rightHandId); + m_pLeftHand = (C_MOBAPlayerHandController*)ClientEntitySystem()->GetEntityByIndex(m_leftHandId); + m_pRightHand = (C_MOBAPlayerHandController*)ClientEntitySystem()->GetEntityByIndex(m_rightHandId); BaseClass::Think(fDelta); }; @@ -157,10 +157,8 @@ void Game_OnGameAxisDiff( EInputDeviceType eDevice, EInputAxis eAxis, float fVal } } - void C_MOBAPlayerHandController::Precache() { - m_hNormal = g_pAssetManager->LoadModel("game/core/models/hand.fmdl"); m_pNormalModel = g_pAssetManager->GetModelByIndex(m_hNormal); m_hSqueezed = g_pAssetManager->LoadModel("game/core/models/sphere.fmdl"); diff --git a/game/client/worldrender.cpp b/game/client/worldrender.cpp index 3b1ac60..0e358d9 100644 --- a/game/client/worldrender.cpp +++ b/game/client/worldrender.cpp @@ -367,7 +367,7 @@ void CFunnyWorldRenderer::Frame( float fDelta ) v->m_pDepth, LOAD_MODE_CLEAR, STORE_MODE_STORE, - {.depth = 0}, + {.depth = 1}, }; BeginInfo begin = {}; begin.uWidth = uWidth; diff --git a/game/server/assetmgr.cpp b/game/server/assetmgr.cpp index a7a4612..f0d410d 100644 --- a/game/server/assetmgr.cpp +++ b/game/server/assetmgr.cpp @@ -295,5 +295,5 @@ void CAssetManager::UnrefPhysics( HFunnyPhysics hPhysics ) -static CAssetManager s_assetmgr; -IAssetManager *g_pAssetManager = &s_assetmgr; +static CAssetManager s_server_assetmgr; +IAssetManager *g_pServerAssetManager = &s_server_assetmgr; diff --git a/game/server/assetmgr.h b/game/server/assetmgr.h index cff5ac4..18f02f1 100644 --- a/game/server/assetmgr.h +++ b/game/server/assetmgr.h @@ -58,6 +58,6 @@ public: virtual void UnrefPhysics( HFunnyPhysics hPhysics ) = 0; }; -extern IAssetManager *g_pAssetManager; +extern IAssetManager *g_pServerAssetManager; #endif diff --git a/game/server/basemodelentity.cpp b/game/server/basemodelentity.cpp index 16b52db..14540ed 100644 --- a/game/server/basemodelentity.cpp +++ b/game/server/basemodelentity.cpp @@ -21,8 +21,7 @@ void CBaseModelEntity::Think( float fDelta ) { if (V_strncmp(m_szModel, m_szCurrentModel, 256)) { - V_memset(m_szCurrentModel, 0, 256); - V_strncpy(m_szCurrentModel, m_szModel, 255); + V_memcpy(m_szCurrentModel, m_szModel, 256); OnModelChanged(m_szCurrentModel); } } diff --git a/game/server/basemodelentity.h b/game/server/basemodelentity.h index 4bf488f..1ce0dbc 100644 --- a/game/server/basemodelentity.h +++ b/game/server/basemodelentity.h @@ -17,7 +17,6 @@ public: virtual void OnModelChanged( const char *szName ); void Think( float fDelta ); char m_szModel[256] = {}; -private: char m_szCurrentModel[256] = {}; }; diff --git a/game/server/entitysystem.cpp b/game/server/entitysystem.cpp index d608bf5..9322bcb 100644 --- a/game/server/entitysystem.cpp +++ b/game/server/entitysystem.cpp @@ -63,14 +63,14 @@ CBaseEntity *CEntitySystem::CreateByClassname( const char *szName, int *pOutputI int i; int iSelectedSlot; - pFactory = GetFactoryByClassname(szName); - if ( !pFactory ) - return NULL; - // We do not want to have more than MAX_EDICT entities if ( m_nEntityCount >= MAX_EDICTS-1 ) return NULL; + pFactory = GetFactoryByClassname(szName); + if ( !pFactory ) + return NULL; + // Search for space // Could be more efficient but nobody cares for ( i = 0; i < MAX_EDICTS; i++ ) @@ -112,7 +112,6 @@ IEntityFactory *CEntitySystem::GetFactoryByClassname( const char *szName ) } return NULL; } - void CEntitySystem::Think( float fDelta ) { CBaseEntity *pEntity; @@ -120,7 +119,6 @@ void CEntitySystem::Think( float fDelta ) for ( i = 0; i < MAX_EDICTS; i++ ) { - pEntity = m_pEntities[i]; if ( pEntity == NULL ) continue; @@ -150,6 +148,23 @@ searchIndex: return NULL; } +static netfield_t *UTIL_GetNetMapField( CBaseEntity *pEntity, netmap_t *pMap, uint32_t uIndex ) +{ + netmap_t *pCurrentMap = pMap; + uint32_t uCurrentIndex = uIndex; +searchIndex: + if ( pCurrentMap ) + { + if (uCurrentIndex >= pCurrentMap->m_uFieldCount) + { + uCurrentIndex -= pCurrentMap->m_uFieldCount; + pCurrentMap = pCurrentMap->m_pBase; + goto searchIndex; + } + return &pCurrentMap->m_pFields[uCurrentIndex]; + } + return NULL; +} void CEntitySystem::NetRecvPacket( NetPacket_t *pPacket ) { @@ -182,9 +197,13 @@ void CEntitySystem::NetRecvPacket( NetPacket_t *pPacket ) // this shall be reworked for ( uint32_t u = 0; u < pPlayerPacket->m_entityData.m_uCount; u++ ) { + netfield_t *pnf = UTIL_GetNetMapField( + pEntity, + pEntity->GetRecvMap(), + pcSyncValue->m_uVariableIndex); uint32_t uVariableSize = pcSyncValue->m_uVariableSize; - void *pValueData = (float*)UTIL_GetNetMapData( + void *pValueData = UTIL_GetNetMapData( pEntity, pEntity->GetRecvMap(), pcSyncValue->m_uVariableIndex); diff --git a/game/server/entitysystem.h b/game/server/entitysystem.h index a5f1634..d890d40 100644 --- a/game/server/entitysystem.h +++ b/game/server/entitysystem.h @@ -34,8 +34,8 @@ public: virtual void NetSendThink( INetworkBase *pBase ); virtual void SetAllowedEntityForPlayer( uint64_t ullPlayer, CBaseEntity *pEntity ); private: - CBaseEntity *m_pEntities[MAX_EDICTS]; - int m_nEntityCount; + CBaseEntity *m_pEntities[MAX_EDICTS] = {}; + int m_nEntityCount = 0; }; CEntitySystem *EntitySystem(); diff --git a/game/server/game.cpp b/game/server/game.cpp index 0c95157..e52812e 100644 --- a/game/server/game.cpp +++ b/game/server/game.cpp @@ -11,7 +11,7 @@ #include "steam/steam_gameserver.h" #endif -class CFunnyGameBridge: public IEngineBridge +class CServerGameBridge: public IEngineBridge { virtual void Init() override; virtual void Tick( float fDelta ) override; @@ -24,13 +24,13 @@ class CFunnyGameBridge: public IEngineBridge }; -IEngineBridge *EngineBridge() +IEngineBridge *ServerEngineBridge() { - static CFunnyGameBridge s_bridge; + static CServerGameBridge s_bridge; return &s_bridge; } -EXPOSE_INTERFACE_FN(EngineBridge, IEngineBridge, ENGINE_BRIDGE_INTERFACE_VERSION) +EXPOSE_INTERFACE_FN(ServerEngineBridge, IServerEngineBridge, SERVER_ENGINE_BRIDGE_INTERFACE_VERSION) uint32_t NET_ServerCallback( NetCallback_t *pCallback ) { @@ -97,7 +97,7 @@ uint32_t NET_ServerCallback( NetCallback_t *pCallback ) return 0; } -void CFunnyGameBridge::Init() +void CServerGameBridge::Init() { if (g_pEngineConstants->m_bIsDedicated == false) g_pClientBridge = g_pEngineConstants->LaunchLocalBridge(0); @@ -145,7 +145,7 @@ void CFunnyGameBridge::Init() } -void CFunnyGameBridge::Tick( float fDelta ) +void CServerGameBridge::Tick( float fDelta ) { } @@ -196,7 +196,7 @@ void NET_ProcessPacket( INetworkBase *pBase ) pBase->RecievePacket(); } -void CFunnyGameBridge::Frame( float fDelta ) +void CServerGameBridge::Frame( float fDelta ) { g_pEngineVars->m_fTime += fDelta; g_pEngineVars->m_fDeltaTime = fDelta; @@ -242,13 +242,13 @@ void CFunnyGameBridge::Frame( float fDelta ) } -void CFunnyGameBridge::Shutdown() +void CServerGameBridge::Shutdown() { } #define CONNECT_INTERFACE(szName, pGlobal) if (!V_strcmp(psz, szName)) { pGlobal = (typeof(pGlobal))pInterface; return; } -void CFunnyGameBridge::ConnectInterface( const char *psz, void *pInterface ) +void CServerGameBridge::ConnectInterface( const char *psz, void *pInterface ) { CONNECT_INTERFACE(FILESYSTEM_INTERFACE_VERSION, filesystem); CONNECT_INTERFACE("EngineConstants", g_pEngineConstants) diff --git a/game/server/milmoba/player.cpp b/game/server/milmoba/player.cpp index 749d83c..db3c077 100644 --- a/game/server/milmoba/player.cpp +++ b/game/server/milmoba/player.cpp @@ -5,7 +5,6 @@ CMOBAPlayer::CMOBAPlayer() { - m_hCuboid = g_pPhysics->CreateCube({1,1,1}); } CMOBAPlayer::~CMOBAPlayer() @@ -19,6 +18,8 @@ void CMOBAPlayer::Spawn() SetModel("game/core/models/sphere.fmdl"); SetAbsOrigin({0,-11.5, 0}); SetThink(Think); + + m_hCuboid = g_pPhysics->CreateCube({1,1,1}); m_pLeftHand = EntitySystem()->CreateByClassname("player_hand_controller", &m_leftHandId); m_pRightHand = EntitySystem()->CreateByClassname("player_hand_controller", &m_rightHandId); diff --git a/game/server/physicsprop.cpp b/game/server/physicsprop.cpp index 4b8a9c0..8de6e8a 100644 --- a/game/server/physicsprop.cpp +++ b/game/server/physicsprop.cpp @@ -61,11 +61,11 @@ void CPhysicsProp::OnModelChanged( const char *szName ) { if (m_hModel) { - g_pAssetManager->UnrefModel(m_hModel); + g_pServerAssetManager->UnrefModel(m_hModel); } - m_hModel = g_pAssetManager->LoadModel(szName); - m_pModel = g_pAssetManager->GetModelByIndex(m_hModel); - m_pPhysics = g_pAssetManager->GetPhysicsByIndex(m_pModel->m_hPhysics); + m_hModel = g_pServerAssetManager->LoadModel(szName); + m_pModel = g_pServerAssetManager->GetModelByIndex(m_hModel); + m_pPhysics = g_pServerAssetManager->GetPhysicsByIndex(m_pModel->m_hPhysics); m_hCollider = g_pPhysics->CreateCollider(m_pPhysics->m_hShape); m_pBody = g_pPhysicsWorld->CreateRigidBody(m_hCollider, m_eCurrentPhysicsType); m_pBody->SetPosition(GetAbsOrigin()); diff --git a/launcher/build.cpp b/launcher/build.cpp index 8db06d9..5a546dc 100644 --- a/launcher/build.cpp +++ b/launcher/build.cpp @@ -11,8 +11,12 @@ ADD_DEPENDENCY_BUILD_FILE(ms, "../materialsystem/build.cpp"); ADD_DEPENDENCY_BUILD_FILE(fs, "../external/funnystdlib/stdfilesystems/build.cpp"); ADD_DEPENDENCY_BUILD_FILE(tier0, "../external/funnystdlib/tier0/build.cpp"); ADD_DEPENDENCY_BUILD_FILE(tier1, "../external/funnystdlib/tier1/build.cpp"); +ADD_DEPENDENCY_BUILD_FILE(tier2, "../external/funnystdlib/tier2/build.cpp"); ADD_DEPENDENCY_BUILD_FILE(server, "../game/server/build.cpp"); ADD_DEPENDENCY_BUILD_FILE(client, "../game/client/build.cpp"); +ADD_DEPENDENCY_BUILD_FILE(rapier, "../rapier/build.cpp"); + +#define EXTERNAL "../external/" DECLARE_BUILD_STAGE(launcher) { @@ -22,13 +26,30 @@ DECLARE_BUILD_STAGE(launcher) compileProject.files = {"launcher.cpp"}; compileProject.includeDirectories = {"../external/SDL/include"}; compileProject.m_target = Target_t::DefaultTarget(); + if (compileProject.m_target.kernel == TARGET_KERNEL_ANDROID) + { + compileProject.files.AppendTail(EXTERNAL "android/android_native_app_glue.c"); + compileProject.includeDirectories.AppendTail(EXTERNAL "android"); + compileProject.bFPIC = true; + } ldProject = ccompiler->Compile(&compileProject); - ldProject.linkType = ELINK_EXECUTABLE; + if (compileProject.m_target.kernel == TARGET_KERNEL_ANDROID) + ldProject.linkType = ELINK_DYNAMIC_LIBRARY; + else + ldProject.linkType = ELINK_EXECUTABLE; if (compileProject.m_target.kernel == TARGET_KERNEL_IOS) { ldProject.frameworkDirectories = {"../external/ios"}; ldProject.frameworks = {"SDL3"}; } + if (compileProject.m_target.kernel == TARGET_KERNEL_ANDROID) + { + ldProject.libraries.AppendTail("android"); + ldProject.libraries.AppendTail("log"); + if (compileProject.m_target.cpu == TARGET_CPU_AARCH64) + ldProject.libraryDirectories.AppendTail(EXTERNAL "android/aarch64"); + + } if ( GET_PROJECT_VALUE(config, "static") == "true" ) { ldProject.objects.AppendTail({GET_PROJECT_OBJECT(engine, "engine")}); @@ -36,10 +57,15 @@ DECLARE_BUILD_STAGE(launcher) ldProject.objects.AppendTail({GET_PROJECT_OBJECT(RenderSystemVulkan, "RenderSystemVulkan")}); ldProject.objects.AppendTail({GET_PROJECT_OBJECT(tier0, "libtier0")}); ldProject.objects.AppendTail({GET_PROJECT_OBJECT(tier1, "tier1")}); - ldProject.objects.AppendTail({GET_PROJECT_OBJECT(filesystem_std, "libfs")}); + ldProject.objects.AppendTail({GET_PROJECT_OBJECT(tier2, "tier2")}); + if (ldProject.m_target.kernel != TARGET_KERNEL_ANDROID) + ldProject.objects.AppendTail({GET_PROJECT_OBJECT(filesystem_std, "libfs")}); ldProject.objects.AppendTail({GET_PROJECT_OBJECT(shadercompiler, "fs")}); ldProject.objects.AppendTail({GET_PROJECT_OBJECT(Server, "server")}); ldProject.objects.AppendTail({GET_PROJECT_OBJECT(Client, "client")}); + ldProject.objects.AppendTail({GET_PROJECT_OBJECT(rapier, "physics")}); + ldProject.objects.AppendTail({GET_PROJECT_OBJECT(rapier, "rapier_static")}); + ldProject.libraries.AppendTail("openxr_loader"); } CUtlString outputProject = linker->Link(&ldProject); @@ -52,16 +78,16 @@ DECLARE_BUILD_STAGE(launcher) CUtlString szOutputDir = manifest.BuildManifest(); - filesystem2->CopyDirectory(CUtlString("%s/core/",szOutputDir.GetString()), "../funnyassets/maps"); - filesystem2->CopyDirectory(CUtlString("%s/core/",szOutputDir.GetString()), "../funnyassets/models"); - filesystem2->CopyDirectory(CUtlString("%s/core/",szOutputDir.GetString()), "../funnyassets/meshes"); - filesystem2->CopyDirectory(CUtlString("%s/core/",szOutputDir.GetString()), "../funnyassets/materials"); - filesystem2->CopyDirectory(CUtlString("%s/core/",szOutputDir.GetString()), "../funnyassets/textures"); - filesystem2->CopyDirectory(CUtlString("%s/core/",szOutputDir.GetString()), "../funnyassets/physics"); - filesystem2->CopyFile(CUtlString("%s/core/",szOutputDir.GetString()), "../funnyassets/default.cfg"); + filesystem2->CopyDirectory(CUtlString("%s/core/",szOutputDir.GetString()), "../funnyassets/game/maps"); + filesystem2->CopyDirectory(CUtlString("%s/core/",szOutputDir.GetString()), "../funnyassets/game/models"); + filesystem2->CopyDirectory(CUtlString("%s/core/",szOutputDir.GetString()), "../funnyassets/game/meshes"); + filesystem2->CopyDirectory(CUtlString("%s/core/",szOutputDir.GetString()), "../funnyassets/game/materials"); + filesystem2->CopyDirectory(CUtlString("%s/core/",szOutputDir.GetString()), "../funnyassets/game/textures"); + filesystem2->CopyDirectory(CUtlString("%s/core/",szOutputDir.GetString()), "../funnyassets/game/physics"); + filesystem2->CopyFile(CUtlString("%s/core/",szOutputDir.GetString()), "../funnyassets/game/default.cfg"); filesystem2->CopyDirectory(szOutputDir, "../external/ios/SDL3.framework"); - filesystem2->CopyDirectory(CUtlString("%s/core/",szOutputDir.GetString()), "../build/funnygame/assets/shaders"); + filesystem2->CopyDirectory(CUtlString("%s/core/",szOutputDir.GetString()), "../build/funnygame/assets/game/shaders"); CUtlString szIpa = AppleTool()->BuildPackage( manifest, szOutputDir ); } if (compileProject.m_target.kernel == TARGET_KERNEL_ANDROID) @@ -74,20 +100,37 @@ DECLARE_BUILD_STAGE(launcher) CUtlString szOutputDir = manifest.BuildManifest(); - CUtlString szLibDir = CUtlString("%s/lib/%s",szOutputDir.GetString(), Target_t::StringFromCPU(compileProject.m_target.cpu)); - filesystem2->MakeDirectory(szLibDir); - filesystem2->CopyFile(CUtlString("%s/libnative-app.so",szLibDir.GetString()), outputProject); + CUtlVector libdirs = {}; + CUtlString nativelibs; + if (compileProject.m_target.cpu == TARGET_CPU_AARCH64) + { + libdirs.AppendTail(CUtlString("%s/lib/aarch64",szOutputDir.GetString())); + libdirs.AppendTail(CUtlString("%s/lib/arm64-v8a",szOutputDir.GetString())); + nativelibs.AppendTail(EXTERNAL "android/aarch64"); + } + for (auto lib: libdirs) + { + filesystem2->MakeDirectory(lib); + filesystem2->CopyFile(CUtlString("%s/libnative-app.so",lib.GetString()), outputProject); + filesystem2->CopyFile(lib, CUtlString("%s/libc++_shared.so",nativelibs.GetString())); + filesystem2->CopyFile(lib, CUtlString("%s/libopenxr_loader.so",nativelibs.GetString())); + filesystem2->CopyFile(lib, CUtlString("%s/libVkLayer_khronos_validation.so",nativelibs.GetString())); + } - filesystem2->MakeDirectory(CUtlString("%s/assets/core/",szOutputDir.GetString())); - filesystem2->CopyDirectory(CUtlString("%s/assets/core/",szOutputDir.GetString()), "../funnyassets/maps"); - filesystem2->CopyDirectory(CUtlString("%s/assets/core/",szOutputDir.GetString()), "../funnyassets/models"); - filesystem2->CopyDirectory(CUtlString("%s/assets/core/",szOutputDir.GetString()), "../funnyassets/meshes"); - filesystem2->CopyDirectory(CUtlString("%s/assets/core/",szOutputDir.GetString()), "../funnyassets/materials"); - filesystem2->CopyDirectory(CUtlString("%s/assets/core/",szOutputDir.GetString()), "../funnyassets/textures"); - filesystem2->CopyDirectory(CUtlString("%s/assets/core/",szOutputDir.GetString()), "../funnyassets/physics"); - filesystem2->CopyFile(CUtlString("%s/assets/core/",szOutputDir.GetString()), "../funnyassets/default.cfg"); + manifest.AddObject("lib"); + manifest.AddObject("assets"); - filesystem2->CopyDirectory(CUtlString("%s/assets/core/",szOutputDir.GetString()), "../build/funnygame/assets/shaders"); + + filesystem2->MakeDirectory(CUtlString("%s/assets/game/core/",szOutputDir.GetString())); + filesystem2->CopyDirectory(CUtlString("%s/assets/game/core/",szOutputDir.GetString()), "../funnyassets/maps"); + filesystem2->CopyDirectory(CUtlString("%s/assets/game/core/",szOutputDir.GetString()), "../funnyassets/models"); + filesystem2->CopyDirectory(CUtlString("%s/assets/game/core/",szOutputDir.GetString()), "../funnyassets/meshes"); + filesystem2->CopyDirectory(CUtlString("%s/assets/game/core/",szOutputDir.GetString()), "../funnyassets/materials"); + filesystem2->CopyDirectory(CUtlString("%s/assets/game/core/",szOutputDir.GetString()), "../funnyassets/textures"); + filesystem2->CopyDirectory(CUtlString("%s/assets/game/core/",szOutputDir.GetString()), "../funnyassets/physics"); + filesystem2->CopyFile(CUtlString("%s/assets/game/core/",szOutputDir.GetString()), "../funnyassets/default.cfg"); + + filesystem2->CopyDirectory(CUtlString("%s/assets/game/core/",szOutputDir.GetString()), "../build/funnygame/assets/shaders"); CUtlString szApkPackage = APKTool()->BuildPackage( manifest, szOutputDir ); APKTool()->SignPackage(szApkPackage, NULL, "kotofyt", "password1", "password1"); } diff --git a/launcher/launcher.cpp b/launcher/launcher.cpp index 3ca1bd5..7c42892 100644 --- a/launcher/launcher.cpp +++ b/launcher/launcher.cpp @@ -37,9 +37,12 @@ void *pEngineLib = NULL; void *pTier0Lib = NULL; typedef void (*EngineMainFn)(int argc, char** argv); EngineMainFn pEngineMain; -extern void FunnyMain(int argc, char** argv); +extern "C" void FunnyMain(int argc, char** argv); int main( int argc, char **argv ) { +#ifdef __ANDROID__ + FunnyMain(argc, argv); +#endif #ifdef __linux__ readlink("/proc/self/exe",szLauncherPath, MAX_PATH); dirname(szLauncherPath); @@ -100,14 +103,19 @@ int main( int argc, char **argv ) { SetCurrentDirectoryA(szLauncherPath); pEngineMain(argc, argv); #endif - FunnyMain(argc, argv); return 0; }; #ifdef __ANDROID__ +#include +#include + +struct android_app *g_android_app; void android_main(struct android_app* app) { - + g_android_app = app; + const char *arg = "funnygame"; + FunnyMain(1, (char**)&arg); } #endif diff --git a/materialsystem/build.cpp b/materialsystem/build.cpp index d4be6b4..bb48756 100644 --- a/materialsystem/build.cpp +++ b/materialsystem/build.cpp @@ -33,7 +33,6 @@ CUtlVector RenderContextVulkan_CompiledFiles = { "vulkan/commands/base.cpp", "vulkan/libraries/raster.cpp", EXTERNAL"volk/volk.c", - "gamewindow_sdl.cpp", "stb.c", }; @@ -89,6 +88,16 @@ DECLARE_BUILD_STAGE(RenderSystemVulkan) compileProject.m_szName = "RenderSystemVulkan"; compileProject.files = RenderContextVulkan_CompiledFiles; + if (Target_t::DefaultTarget().kernel == TARGET_KERNEL_ANDROID) + { + + compileProject.files.AppendTail("gamewindow_android.cpp"); + compileProject.macros = { + (C_Macro_t){"VK_USE_PLATFORM_ANDROID_KHR"} + }; + } + else + compileProject.files.AppendTail("gamewindow_sdl.cpp"); compileProject.includeDirectories = { "../public", FUNNYSTDLIB"public", diff --git a/materialsystem/gamewindow_android.cpp b/materialsystem/gamewindow_android.cpp new file mode 100644 index 0000000..e17e247 --- /dev/null +++ b/materialsystem/gamewindow_android.cpp @@ -0,0 +1,224 @@ +#include "android/android_native_app_glue.h" +#include "materialsystem/igamewindow.h" +#include "tier0/lib.h" +#include "tier0/platform.h" +#include "tier1/interface.h" +#include "tier1/utlvector.h" + +#include "volk.h" + +extern struct android_app *g_android_app; +class CAndroidGameWindow: public IGameWindow +{ +public: + virtual void Init() override; + virtual void Shutdown() override; + virtual void Frame( float fDelta ) override; + + virtual uint32_t GetRenderWidth() override; + virtual uint32_t GetRenderHeight() override; + virtual bool BRenderSizeUpdated() override; + + virtual void SetOutputImage( IImage *pImage ) override; + virtual IImage *GetOutputImage() override; + + virtual void SetKeyCallback( KeyCallbackFn fn ) override; + virtual void SetAxisCallback( AxisCallbackFn fn ) override; + + virtual void *CreateVulkanSurface( void *pInstance ) override; + virtual void DestroyVulkanSurface( void *pInstance ) override; + + virtual bool IsValid() override; + + KeyCallbackFn m_fnKeyCallback = NULL; + AxisCallbackFn m_fnAxisCallback = NULL; + + bool m_bWindowSizeUpdated; + uint32_t m_uRenderWidth; + uint32_t m_uRenderHeight; + + bool m_bIsValid = false; + +private: + + VkSurfaceKHR m_hSurface = NULL; + IImage *m_pOutputImage = NULL; +}; +void CAndroidGameWindow::Init() +{ + m_uRenderWidth = 1280; + m_uRenderHeight = 720; +} + +void CAndroidGameWindow::Shutdown() +{ +} + +void CAndroidGameWindow::Frame( float fDelta ) +{ +} + +uint32_t CAndroidGameWindow::GetRenderWidth() +{ + return m_uRenderWidth; +} + +uint32_t CAndroidGameWindow::GetRenderHeight() +{ + return m_uRenderHeight; +} + +bool CAndroidGameWindow::BRenderSizeUpdated() +{ + return m_bWindowSizeUpdated; +} + +void CAndroidGameWindow::SetOutputImage( IImage *pImage ) +{ + m_pOutputImage = pImage; +} + +IImage *CAndroidGameWindow::GetOutputImage() +{ + return m_pOutputImage; + +} + + +void CAndroidGameWindow::SetKeyCallback( KeyCallbackFn fn ) +{ + m_fnKeyCallback = fn; +} + +void CAndroidGameWindow::SetAxisCallback( AxisCallbackFn fn ) +{ + m_fnAxisCallback = fn; +} + +void *CAndroidGameWindow::CreateVulkanSurface( void *pInstance ) +{ + VkAndroidSurfaceCreateInfoKHR ci = {}; + ci.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR; + ci.window = g_android_app->window; + vkCreateAndroidSurfaceKHR((VkInstance)pInstance, &ci, NULL, &m_hSurface); + return m_hSurface; +} + +void CAndroidGameWindow::DestroyVulkanSurface( void *pInstance ) +{ + vkDestroySurfaceKHR((VkInstance)pInstance, m_hSurface, NULL); +} + +bool CAndroidGameWindow::IsValid() +{ + return m_bIsValid; +} + +class CAndroidGameWindowManager: public IGameWindowManager +{ +public: + virtual void Init() override; + virtual void Frame( float fDelta ) override; + virtual void Shutdown() override; + + virtual IGameWindow *CreateWindow() override; + virtual void DestroyWindow( IGameWindow* pWindow ) override; + + virtual int GetVulkanInstanceExtensionCount() override; + virtual const char **GetVulkanInstanceExtensions() override; + CAndroidGameWindow m_window; +private: +}; + +IGameWindowManager *GameWindowManager() +{ + static CAndroidGameWindowManager mgr; + return &mgr; +} +EXPOSE_INTERFACE_FN(GameWindowManager, IGameWindowManager, GAME_WINDOW_MANAGER_INTERFACE_VERSION) + +#include "android/log.h" +#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, "funnygame", __VA_ARGS__) +static void HandleAndroidEvent(android_app* app, int32_t cmd) { + CAndroidGameWindowManager *pMgr = (CAndroidGameWindowManager*)GameWindowManager(); + switch (cmd) { + case APP_CMD_INIT_WINDOW: + pMgr->m_window.m_bIsValid = true; + break; + default: + break; + } +} + +void CAndroidGameWindowManager::Init() +{ + g_android_app->onAppCmd = HandleAndroidEvent; + while (true) + { + int events; + android_poll_source* source; + while (ALooper_pollOnce(0, nullptr, &events, (void**)&source) >= 0) { + if (source) source->process(g_android_app, source); + } + if (m_window.IsValid()) + break; + } +} +/* +static EInputButton GetKeyButton( Android_Keycode eCode ) +{ + +} +*/ + +void CAndroidGameWindowManager::Frame( float fDelta ) +{ + m_window.m_bWindowSizeUpdated = false; + int events; + android_poll_source* source; + while (ALooper_pollOnce(0, nullptr, &events, (void**)&source) >= 0) { + if (source) source->process(g_android_app, source); + } + LOGI("%u %u", m_window.m_uRenderWidth, m_window.m_uRenderHeight); + uint32_t uNewWidth = ANativeWindow_getWidth(g_android_app->window); + uint32_t uNewHeight = ANativeWindow_getHeight(g_android_app->window); + if (m_window.m_uRenderWidth != uNewWidth || m_window.m_uRenderHeight != uNewHeight) + { + m_window.m_bWindowSizeUpdated = true; + } + m_window.m_uRenderWidth = uNewWidth; + m_window.m_uRenderHeight = uNewHeight; +} + +void CAndroidGameWindowManager::Shutdown() +{ + +} + + +IGameWindow *CAndroidGameWindowManager::CreateWindow() +{ + return &m_window; +} + +void CAndroidGameWindowManager::DestroyWindow( IGameWindow* pWindow ) +{ + pWindow->Shutdown(); +} + + +int CAndroidGameWindowManager::GetVulkanInstanceExtensionCount() +{ + + return 2; +} + +static const char *extensions[] = { + VK_KHR_ANDROID_SURFACE_EXTENSION_NAME, + VK_KHR_SURFACE_EXTENSION_NAME, +}; +const char **CAndroidGameWindowManager::GetVulkanInstanceExtensions() +{ + + return extensions; +} diff --git a/materialsystem/vulkan/commands/draw.cpp b/materialsystem/vulkan/commands/draw.cpp index 1faf209..2beb207 100644 --- a/materialsystem/vulkan/commands/draw.cpp +++ b/materialsystem/vulkan/commands/draw.cpp @@ -23,6 +23,9 @@ DECLARE_VULKAN_COMMAND(Begin) { if (vkCmdBeginRendering || vkCmdBeginRenderingKHR) { + V_printf("USING DYNAMIC RENDERING\n"); + V_printf("%p\n", vkCmdBeginRendering); + V_printf("%p\n", vkCmdBeginRenderingKHR); VkRenderingInfo stRenderingInfo = {}; CUtlVector attachments = {}; VkRenderingAttachmentInfo depthAttachment = {}; @@ -75,6 +78,7 @@ DECLARE_VULKAN_COMMAND(Begin) } else { + V_printf("USING RENDERPASS"); CUtlVector attachments = {}; CUtlVector input_refs = {}; CUtlVector image_views = {}; @@ -184,7 +188,10 @@ DECLARE_VULKAN_COMMAND(End) else if (vkCmdEndRenderingKHR) vkCmdEndRenderingKHR(hCommandBuffer); else + { vkCmdEndRenderPass(hCommandBuffer); + + } } DECLARE_VULKAN_COMMAND(SetShader) diff --git a/materialsystem/vulkan/csshader.cpp b/materialsystem/vulkan/csshader.cpp index 0e75f0a..76403e6 100644 --- a/materialsystem/vulkan/csshader.cpp +++ b/materialsystem/vulkan/csshader.cpp @@ -8,6 +8,7 @@ void CVkComputeShader::Build() VulkanInputMetaData_t *pMetaData = (VulkanInputMetaData_t*)m_shader.GetLumpPtr(s->m_nMetadataLump); VkPipelineLayoutCreateInfo stPipelineLayout = {}; CUtlVector> bindings = {}; + VkShaderModule sm; for ( int u = 0; u < pMetaData->nDescriptorsCount; u++ ) { @@ -45,8 +46,14 @@ void CVkComputeShader::Build() mod.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; mod.pCode = (uint32_t*)m_shader.GetLumpPtr(s->m_nDataLump); mod.codeSize = m_shader.GetLumpSize(s->m_nDataLump); + if (g_vkAvailableExtensions.bIsSupported_VK_KHR_MAINTENANCE_5) + stage.pNext = &mod; + else + { + vkCreateShaderModule(m_hDevice, &mod, NULL, &sm); + stage.module = sm; + } stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - stage.pNext = &mod; stage.pName = "main"; stage.stage = VK_SHADER_STAGE_COMPUTE_BIT; diff --git a/materialsystem/vulkan/device_extensions.h b/materialsystem/vulkan/device_extensions.h index d3320f2..b00042d 100644 --- a/materialsystem/vulkan/device_extensions.h +++ b/materialsystem/vulkan/device_extensions.h @@ -6,6 +6,7 @@ REQUIRED_EXTENSION(VK_EXT_DESCRIPTOR_INDEXING) REQUIRED_EXTENSION(VK_KHR_TIMELINE_SEMAPHORE ) REQUIRED_EXTENSION(VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS) OPTIONAL_EXTENSION(VK_KHR_RAY_TRACING_PIPELINE) +OPTIONAL_EXTENSION(VK_KHR_CREATE_RENDERPASS_2) OPTIONAL_EXTENSION(VK_KHR_ACCELERATION_STRUCTURE) OPTIONAL_EXTENSION(VK_KHR_DEFERRED_HOST_OPERATIONS) OPTIONAL_EXTENSION(VK_KHR_BUFFER_DEVICE_ADDRESS) @@ -14,4 +15,3 @@ OPTIONAL_EXTENSION(VK_KHR_MAINTENANCE_5) //OPTIONAL_EXTENSION(VK_KHR_DYNAMIC_RENDERING) //OPTIONAL_EXTENSION(VK_KHR_SYNCHRONIZATION2) //OPTIONAL_EXTENSION(VK_KHR_COPY_COMMANDS2) -//OPTIONAL_EXTENSION(VK_KHR_DYNAMIC_RENDERING) diff --git a/materialsystem/vulkan/rendercommandlist.cpp b/materialsystem/vulkan/rendercommandlist.cpp index 40d554f..26346a3 100644 --- a/materialsystem/vulkan/rendercommandlist.cpp +++ b/materialsystem/vulkan/rendercommandlist.cpp @@ -42,6 +42,7 @@ void CVkRenderCommandList::Begin( BeginInfo *pBegin ) output.m_eLoadMode = pBegin->pDepth->eLoadMode; output.m_eStoreMode = pBegin->pDepth->eStoreMode; pBeginCommand->stDepthImage = output; + pBeginCommand->bDepthEnabled = true; } m_pCurrentBegin = pBeginCommand; m_pCommandBuffer->AddCommand(pBeginCommand); diff --git a/materialsystem/vulkan/rendercontext.cpp b/materialsystem/vulkan/rendercontext.cpp index 7c24d85..875ad2b 100644 --- a/materialsystem/vulkan/rendercontext.cpp +++ b/materialsystem/vulkan/rendercontext.cpp @@ -228,7 +228,7 @@ void CVkImage::SetDebugName( const char *szName ) nameInfo.objectHandle = (uint64_t)m_image; nameInfo.pObjectName = szName; - vkSetDebugUtilsObjectNameEXT(s_vkDevice, &nameInfo); + //vkSetDebugUtilsObjectNameEXT(s_vkDevice, &nameInfo); } @@ -807,7 +807,7 @@ void CVkRenderContext::Init() stInstanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; stInstanceCreateInfo.pApplicationInfo = &stApplicationInfo; enabledInstanceExtensions.AppendTail(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - enabledInstanceExtensions.AppendTail(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + //enabledInstanceExtensions.AppendTail(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); stInstanceCreateInfo.enabledExtensionCount = enabledInstanceExtensions.GetSize(); stInstanceCreateInfo.ppEnabledExtensionNames = enabledInstanceExtensions.GetData(); @@ -898,12 +898,14 @@ void CVkRenderContext::Init() vkGetDeviceQueue(s_vkDevice, g_iDrawFamily, 0, &s_vkDrawQueue); vkGetDeviceQueue(s_vkDevice, g_iPresentFamily, 0, &s_vkPresentQueue); volkLoadDevice(s_vkDevice); + vkCmdBeginRendering = NULL; + vkCmdEndRendering = NULL; VmaAllocatorCreateInfo stAllocatorInfo = {}; - stAllocatorInfo.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT - | VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT - ; - stAllocatorInfo.vulkanApiVersion = VK_API_VERSION_1_4; + stAllocatorInfo.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT; + if (g_vkAvailableExtensions.bIsSupported_VK_KHR_MAINTENANCE_5) + stAllocatorInfo.flags |= VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT; + stAllocatorInfo.vulkanApiVersion = VK_API_VERSION_1_1; stAllocatorInfo.physicalDevice = s_vkPhysicalDevice; stAllocatorInfo.device = s_vkDevice; stAllocatorInfo.instance = s_vkInstance; @@ -946,7 +948,6 @@ void CVkRenderContext::Frame( float fDeltaTime ) { uint32_t i; CUtlVector swapchains = {}; - CUtlVector uImageIndexes = {}; CUtlVector uSwapchainImageIndexes = {}; CUtlVector recreatedWindows = {}; @@ -975,7 +976,6 @@ void CVkRenderContext::Frame( float fDeltaTime ) for ( auto &s: m_renderWindows) { swapchains.AppendTail(s.m_swapchain); - uImageIndexes.AppendTail(s.m_uCurrentFrame); } uSwapchainImageIndexes.Resize(m_renderWindows.GetSize()); @@ -1092,7 +1092,7 @@ void CVkRenderContext::Frame( float fDeltaTime ) stPresentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; stPresentInfo.swapchainCount = swapchains.GetSize(); stPresentInfo.pSwapchains = swapchains.GetData(); - stPresentInfo.pImageIndices = uImageIndexes.GetData(); + stPresentInfo.pImageIndices = uSwapchainImageIndexes.GetData(); vkQueuePresentKHR(s_vkPresentQueue, &stPresentInfo); vkDeviceWaitIdle(s_vkDevice); diff --git a/materialsystem/vulkan/rtlinker.cpp b/materialsystem/vulkan/rtlinker.cpp index 065f6af..78aeda9 100644 --- a/materialsystem/vulkan/rtlinker.cpp +++ b/materialsystem/vulkan/rtlinker.cpp @@ -298,9 +298,9 @@ void CVkShaderLinker::Build() m_out.m_data = spv.data; m_out.m_size = spv.count; - IFileHandle *ph = filesystem->Open("a.txt", FILEMODE_WRITE); - filesystem->Write(ph, spv.data, spv.count*4); - filesystem->Close(ph); + //IFileHandle *ph = filesystem->Open("a.txt", FILEMODE_WRITE); + //filesystem->Write(ph, spv.data, spv.count*4); + //filesystem->Close(ph); mspv_array_destroy(spv); diff --git a/materialsystem/vulkan/shader.cpp b/materialsystem/vulkan/shader.cpp index cc6d7ff..341cf54 100644 --- a/materialsystem/vulkan/shader.cpp +++ b/materialsystem/vulkan/shader.cpp @@ -70,6 +70,7 @@ void CVkShader::Build() VkGraphicsPipelineCreateInfo createInfo = {}; CUtlVector stages = {}; CUtlVector modules = {}; + CUtlVector sms = {}; VkPipelineVertexInputStateCreateInfo vertexInput = {}; VkPipelineInputAssemblyStateCreateInfo inputAssembly = {}; VkPipelineDynamicStateCreateInfo dynamicState = {}; @@ -91,6 +92,7 @@ void CVkShader::Build() // TODO: Filter by vulkan shaders at some points stages.Resize(m_shader.m_objects.GetSize()); modules.Resize(m_shader.m_objects.GetSize()); + sms.Resize(m_shader.m_objects.GetSize()); for ( int i = 0; i < m_shader.m_objects.GetSize(); i++ ) { VulkanInputMetaData_t *pMetaData = (VulkanInputMetaData_t*)m_shader.GetLumpPtr(m_shader.m_objects[i].m_nMetadataLump); @@ -127,11 +129,21 @@ void CVkShader::Build() bindings[stDescriptor.uSet].AppendTail(bind); m_bindings.AppendTail(stDescriptor); } + modules[i] = {}; modules[i].sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; modules[i].pCode = (uint32_t*)m_shader.GetLumpPtr(m_shader.m_objects[i].m_nDataLump); modules[i].codeSize = m_shader.GetLumpSize(m_shader.m_objects[i].m_nDataLump); + if (!g_vkAvailableExtensions.bIsSupported_VK_KHR_MAINTENANCE_5) + { + VkResult r = vkCreateShaderModule(m_hDevice, &modules[i], NULL, &sms[i]); + VULKAN_RESULT_PRINT(r, vkCreateShaderModule); + } + stages[i] = {}; stages[i].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - stages[i].pNext = &modules[i]; + if (g_vkAvailableExtensions.bIsSupported_VK_KHR_MAINTENANCE_5) + stages[i].pNext = &modules[i]; + else + stages[i].module = sms[i]; stages[i].pName = "main"; stages[i].stage = VulkanGetShaderStage(m_shader.m_objects[i].m_eStage); } diff --git a/public/enginebridge.h b/public/enginebridge.h index c1bbdea..4c975c8 100644 --- a/public/enginebridge.h +++ b/public/enginebridge.h @@ -22,5 +22,7 @@ public: }; #define ENGINE_BRIDGE_INTERFACE_VERSION "EngineBridge001" +#define CLIENT_ENGINE_BRIDGE_INTERFACE_VERSION "ClientEngineBridge001" +#define SERVER_ENGINE_BRIDGE_INTERFACE_VERSION "ServerEngineBridge001" #endif diff --git a/rapier/build.cpp b/rapier/build.cpp index 915bd50..35afe3c 100644 --- a/rapier/build.cpp +++ b/rapier/build.cpp @@ -48,10 +48,18 @@ DECLARE_BUILD_STAGE(rapier) }; cProject.bFPIC = true; LinkProject_t linkProject = ccompiler->Compile(&cProject); - linkProject.linkType = ELINK_DYNAMIC_LIBRARY; - linkProject.objects.AppendTail({rapier_lib}); - linkProject.objects.AppendTail({GET_PROJECT_OBJECT(tier1, "tier1")}); - linkProject.libraryObjects.AppendTail(GET_PROJECT_OBJECT(tier0, "tier0")); + + if ( GET_PROJECT_VALUE(config, "static") == "true" ) + { + linkProject.linkType = ELINK_STATIC_LIBRARY; + } + else + { + linkProject.linkType = ELINK_DYNAMIC_LIBRARY; + linkProject.objects.AppendTail({rapier_lib}); + linkProject.objects.AppendTail({GET_PROJECT_OBJECT(tier1, "tier1")}); + linkProject.libraryObjects.AppendTail(GET_PROJECT_OBJECT(tier0, "tier0")); + } if (linkProject.m_target.kernel & TARGET_KERNEL_WINDOWS_DEVICES) { @@ -73,6 +81,7 @@ DECLARE_BUILD_STAGE(rapier) CUtlString sz_libRapierPhysics = linker->Link(&linkProject); ADD_OUTPUT_OBJECT("physics", sz_libRapierPhysics); + ADD_OUTPUT_OBJECT("rapier_static", rapier_lib); return 0; diff --git a/rapier/physics.cpp b/rapier/physics.cpp index cc4a089..0d4cb7e 100644 --- a/rapier/physics.cpp +++ b/rapier/physics.cpp @@ -94,7 +94,6 @@ public: virtual CastResult_t ShapeCast( HShape hShape, Quat vOrientation, Vector vBegin, Vector vEnd, fnCheckCast check ) override { return CRapierPhysicsWorld_ShapeCast(m_pWorld, (RapierShape_t*)hShape, vOrientation, vBegin, vEnd, (Option_checkCastFn){check} ); - }