Skip to content

Commit

Permalink
Base emscripten port
Browse files Browse the repository at this point in the history
  • Loading branch information
RicoRodriges committed Jan 6, 2020
1 parent 083aa19 commit 7753439
Show file tree
Hide file tree
Showing 15 changed files with 295 additions and 39 deletions.
43 changes: 43 additions & 0 deletions Build_Release/openclaw.html
@@ -0,0 +1,43 @@
<!DOCTYPE HTML>
<html>
<head></head>
<body>
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()" tabindex=-1></canvas>


<script type='text/javascript'>
var Module = {
preRun: [],
postRun: [],
canvas: (function () {
var canvas = document.getElementById('canvas');

// As a default initial behavior, pop up an alert when webgl context is lost. To make your
// application robust, you may want to override this behavior before shipping!
// See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
canvas.addEventListener("webglcontextlost", function (e) {
alert('WebGL context lost. You will need to reload the page.');
e.preventDefault();
}, false);

return canvas;
})(),
};
</script>
<script>
!function (e, t) {
console.info("Loading client...");
var o = t.createElement("script");
o.async = !0;
o.type = "text/javascript";
o.src = "openclaw.js";
o.onerror = function (t) {
console.error("Script Error");
console.error(t);
};
var r = t.getElementsByTagName("script")[0];
r.parentNode.insertBefore(o, r)
}(window, document);
</script>
</body>
</html>
71 changes: 51 additions & 20 deletions CMakeLists.txt
@@ -1,37 +1,53 @@
cmake_minimum_required(VERSION 3.2)

# Build options
option(Android "Android" OFF)

option(Emscripten "Build as WASM" OFF)
set(EMSCRIPTEN_PATH "CHANGE ME PLEASE!!!/emsdk")

project(OpenClaw)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -g")

# CMake compiled directories with dependencies
add_subdirectory(Box2D)
add_subdirectory(libwap)
add_subdirectory(./ThirdParty/Tinyxml)
if (WIN32)
add_subdirectory(MidiProc)
endif (WIN32)

#if(Android)
# add_subdirectory(./ThirdParty/Tinyxml)
# add_subdirectory(./ThirdParty/SDL2-2.0.5)
# include_directories(./ThirdParty/SDL2-2.0.5/include/)
# link_directories(./ThirdParty/SDL2-2.0.5/libs/armeabi/)
# add_subdirectory(./ThirdParty/SDL2_gfx-1.0.1)
#endif(Android)

# Directories with headers
include_directories(./Box2D/)
include_directories(./libwap/)
include_directories(./ThirdParty/)
include_directories(./ThirdParty/Tinyxml/)
if (Emscripten)
include_directories("${EMSCRIPTEN_PATH}/upstream/emscripten/system/include/emscripten/")
endif (Emscripten)

# for android
#include_directories(./ThirdParty/Tinyxml/)

# Directories with libs
link_directories(./libwap)
link_directories(./Box2D)
if (WIN32)
link_directories(./ThirdParty/SDL2/lib/x86)
link_directories(./Build_Release)
endif (WIN32)

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ../Build_Release)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ../android/libs/armeabi-v7a)

# Cmake target definitions
if(Android)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DANDROID")
add_library(openclaw SHARED "")
Expand All @@ -41,27 +57,42 @@ endif(Android)

add_subdirectory(OpenClaw)

# Linker settings
list(APPEND TARGET_LIBS
libwap
tinyxml
Box2D
SDL2
SDL2_mixer
SDL2_ttf
SDL2_image
SDL2_gfx
stdc++
m
)

if(Android)
if (Emscripten)
set_target_properties(openclaw PROPERTIES LINK_FLAGS "-s WASM=1 -s BINARYEN_METHOD='native-wasm' -s EXPORTED_FUNCTIONS='[_main]' -s USE_SDL=2 -s USE_SDL_IMAGE=2 -s SDL2_IMAGE_FORMATS='[\"pcx\",\"png\",\"tga\"]' -s USE_SDL_TTF=2 -s USE_SDL_GFX=2 -s ASYNCIFY=1 -s TOTAL_MEMORY=268435456 --preload-file config.xml --preload-file CLAW.REZ --preload-file ASSETS.ZIP --preload-file SAVES.XML --preload-file console02.tga --preload-file clacon.ttf")
else (Emscripten)
list(APPEND TARGET_LIBS
GLESv2
GLESv1_CM
dl
log
android
)
endif(Android)
SDL2
SDL2_mixer
SDL2_ttf
SDL2_image
SDL2_gfx
)
if (WIN32)
list(APPEND TARGET_LIBS
Rpcrt4
)
else (WIN32)
# TODO: Is it really important???
list(APPEND TARGET_LIBS
stdc++
m
)
endif (WIN32)
if (Android)
list(APPEND TARGET_LIBS
GLESv2
GLESv1_CM
dl
log
android
)
endif (Android)
endif (Emscripten)

target_link_libraries(openclaw ${TARGET_LIBS})
21 changes: 21 additions & 0 deletions MidiProc/CMakeLists.txt
@@ -0,0 +1,21 @@
cmake_minimum_required(VERSION 3.2)

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../Build_Release")

project(MidiProc)

add_executable(MidiProc WIN32 "")
target_sources(MidiProc
PRIVATE
main.cpp
midiproc_s.c)

target_include_directories(MidiProc PRIVATE ../ThirdParty/)
target_link_directories(MidiProc PRIVATE ../Build_Release)
target_link_directories(MidiProc PRIVATE ../ThirdParty/SDL2/lib/x86)

target_link_libraries(MidiProc
PRIVATE
SDL2
SDL2_mixer
rpcrt4)
2 changes: 2 additions & 0 deletions OpenClaw/CMakeLists.txt
@@ -1,5 +1,7 @@
cmake_minimum_required(VERSION 3.2)

target_compile_definitions(openclaw PRIVATE SDL_MAIN_HANDLED)

target_sources(openclaw
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/ActorController.h
Expand Down
15 changes: 14 additions & 1 deletion OpenClaw/Engine/Actor/Components/LocalAmbientSoundComponent.cpp
Expand Up @@ -92,18 +92,27 @@ void LocalAmbientSoundComponent::PlayAmbientSound()
assert(m_SoundChannel == -1);
assert(m_pActorInArea != NULL);

#ifndef __EMSCRIPTEN__
m_SoundChannel = Mix_GroupAvailable(1);
assert(m_SoundChannel != -1 && "Could not get a channel from channel group");
#else
// TODO: [EMSCRIPTEN] Try to implement Mix_Group* functions
m_SoundChannel = -1;
#endif

shared_ptr<Mix_Chunk> pSound = WavResourceLoader::LoadAndReturnSound(m_Properties.sound.c_str());
assert(pSound != nullptr);

#ifndef __EMSCRIPTEN__
int globalVolume = (int)((((float)g_pApp->GetAudio()->GetSoundVolume()) / 100.0f) * (float)MIX_MAX_VOLUME);
int chunkVolume = (int)((((float)m_Properties.volume) / 100.0f) * (float)globalVolume);

Mix_VolumeChunk(pSound.get(), chunkVolume);
#else
// TODO: [EMSCRIPTEN] Try to implement Mix_VolumeChunk
#endif

Mix_PlayChannel(m_SoundChannel, pSound.get(), -1);
m_SoundChannel = Mix_PlayChannel(m_SoundChannel, pSound.get(), -1);

// Set positional properties
UpdateAmbientSound();
Expand All @@ -119,6 +128,10 @@ void LocalAmbientSoundComponent::StopAmbientSound()

void LocalAmbientSoundComponent::UpdateAmbientSound()
{
#ifdef __EMSCRIPTEN__
// TODO: [EMSCRIPTEN] Try to implement Mix_SetDistance
return;
#endif
assert(m_SoundChannel != -1);
assert(m_pActorInArea != NULL);

Expand Down
28 changes: 27 additions & 1 deletion OpenClaw/Engine/Audio/Audio.cpp
Expand Up @@ -63,13 +63,23 @@ bool Audio::Initialize(const GameOptions& config)
Mix_AllocateChannels(config.mixingChannels);

int reservedChannels = Mix_ReserveChannels(16);
#ifndef __EMSCRIPTEN__
if (reservedChannels != 16)
{
LOG_ERROR(std::string(Mix_GetError()));
return false;
}

Mix_GroupChannels(0, 15, 1);
#else
// Mix_ReserveChannels returns nothing.
if (reservedChannels != 0)
{
LOG_ERROR(std::string(Mix_GetError()));
return false;
}
// TODO: [EMSCRIPTEN] Try to implement Mix_Group* functions
#endif

m_SoundVolume = config.soundVolume;
m_MusicVolume = config.musicVolume;
Expand Down Expand Up @@ -268,21 +278,37 @@ bool Audio::PlaySound(const char* soundData, size_t soundSize, const SoundProper

bool Audio::PlaySound(Mix_Chunk* sound, const SoundProperties& soundProperties)
{
#ifndef __EMSCRIPTEN__
int chunkVolume = (int)((((float)soundProperties.volume) / 100.0f) * (float)m_SoundVolume);

Mix_VolumeChunk(sound, chunkVolume);
int channel = Mix_PlayChannel(-1, sound, soundProperties.loops);

int loops = soundProperties.loops;
#else
// TODO: [EMSCRIPTEN] Try to implement Mix_VolumeChunk

int loops = soundProperties.loops;
// Emscripten SDL port supports infinite loops only
if (loops != -1) {
loops = 0;
}
#endif
int channel = Mix_PlayChannel(-1, sound, loops);
if (channel == -1)
{
LOG_ERROR("Failed to play chunk: " + std::string(Mix_GetError()));
return false;
}

#ifndef __EMSCRIPTEN__
if (!Mix_SetPosition(channel, soundProperties.angle, soundProperties.distance))
{
LOG_ERROR("Mix_SetPosition: " + std::string(Mix_GetError()));
return false;
}
#else
// TODO: [EMSCRIPTEN] Try to implement Mix_SetPosition
#endif

if (!m_bSoundOn)
{
Expand Down
4 changes: 4 additions & 0 deletions OpenClaw/Engine/Audio/CMakeLists.txt
Expand Up @@ -5,3 +5,7 @@ target_sources(openclaw
${CMAKE_CURRENT_SOURCE_DIR}/Audio.h
${CMAKE_CURRENT_SOURCE_DIR}/Audio.cpp
)

if (WIN32)
target_sources(openclaw PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/midiproc_c.c)
endif (WIN32)
49 changes: 37 additions & 12 deletions OpenClaw/Engine/GameApp/BaseGameApp.cpp
Expand Up @@ -24,6 +24,10 @@

#include <cctype>

#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif

TiXmlElement* CreateDefaultDisplayConfig();
TiXmlElement* CreateDefaultAudioConfig();
TiXmlElement* CreateDefaultFontConfig();
Expand Down Expand Up @@ -171,19 +175,12 @@ bool BaseGameApp::VPerformStartupTests()
return bTestsOk;
}

//=====================================================================================================================
// BaseGameApp::Run - Main game loop
//
// Handle events -> update game -> render views
//=====================================================================================================================

int32 BaseGameApp::Run()
{
void BaseGameApp::StepLoop() {
static uint32 lastTime = SDL_GetTicks();
SDL_Event event;
int consecutiveLagSpikes = 0;
static int consecutiveLagSpikes = 0;

while (m_IsRunning)
if (m_IsRunning)
{
//PROFILE_CPU("MAINLOOP");

Expand All @@ -200,7 +197,7 @@ int32 BaseGameApp::Run()
{
LOG_ERROR("Experiencing lag spikes, " + ToStr(consecutiveLagSpikes) + "high latency frames in a row");
}
continue;
return;
}
consecutiveLagSpikes = 0;

Expand Down Expand Up @@ -231,10 +228,38 @@ int32 BaseGameApp::Run()

// Artificially decrease fps. Configurable from console
SDL_Delay(m_DebugOptions.cpuDelayMs);
} else {
Terminate();
#ifdef __EMSCRIPTEN__
emscripten_cancel_main_loop();
#else
exit(0);
#endif
}
}

Terminate();
void loop(void *param) {
BaseGameApp *self = (BaseGameApp *) param;
self->StepLoop();
}

//=====================================================================================================================
// BaseGameApp::Run - Main game loop
//
// Handle events -> update game -> render views
//=====================================================================================================================

int32 BaseGameApp::Run()
{
// Some systems (like web browsers) does not support infinite loops.
// We need to return control after each loop steps.
#ifdef __EMSCRIPTEN__
emscripten_set_main_loop_arg(loop, this, 0, 0);
#else
while (true) {
loop(this);
}
#endif
return 0;
}

Expand Down
1 change: 1 addition & 0 deletions OpenClaw/Engine/GameApp/BaseGameApp.h
Expand Up @@ -237,6 +237,7 @@ class BaseGameApp

// Main loop
int32 Run();
void StepLoop();

// This is provided to be used the engine
bool LoadStrings(std::string language);
Expand Down

0 comments on commit 7753439

Please sign in to comment.