1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-10 20:42:21 +02:00

wasm improvements

This commit is contained in:
Brian Fiete 2022-03-24 11:59:00 -07:00
parent 17b29c7227
commit 474454382f
6 changed files with 257 additions and 22 deletions

View file

@ -9,12 +9,15 @@ StartupObject = "Program"
LibPaths = ["$(ProjectDir)/dist/SDL2.lib", "$(ProjectDir)/dist/SDL2_ttf.lib", "$(ProjectDir)/dist/SDL2_image.lib", "$(ProjectDir)/dist/SDL2_mixer.lib"]
PostBuildCmds = ["CopyToDependents(\"$(ProjectDir)/dist/*.dll\")"]
[Configs.Debug.Linux64]
OtherLinkFlags = "$(LinkFlags) -lSDL2 -lSDL2_ttf -lSDL2_image -lSDL2_mixer"
[Configs.Debug.wasm32]
PreprocessorMacros = ["DEBUG", "NOTTF"]
[Configs.Release.Win64]
LibPaths = ["$(ProjectDir)/dist/SDL2.lib", "$(ProjectDir)/dist/SDL2_ttf.lib", "$(ProjectDir)/dist/SDL2_image.lib", "$(ProjectDir)/dist/SDL2_mixer.lib"]
PostBuildCmds = ["CopyToDependents(\"$(ProjectDir)/dist/*.dll\")"]
[Configs.Debug.Linux64]
OtherLinkFlags = "$(LinkFlags) -lSDL2 -lSDL2_ttf -lSDL2_image -lSDL2_mixer"
[Configs.Release.Linux64]
OtherLinkFlags = "$(LinkFlags) -lSDL2 -lSDL2_ttf -lSDL2_image -lSDL2_mixer"

View file

@ -0,0 +1,32 @@
using System.Collections;
namespace SDL2
{
class BitmapFont
{
public class Page
{
public Image mImage ~ delete _;
}
public struct CharData
{
public int32 mX;
public int32 mY;
public int32 mWidth;
public int32 mHeight;
public int32 mXOfs;
public int32 mYOfs;
public int32 mXAdvance;
public int32 mPage;
}
public List<Page> mPages = new .() ~ DeleteContainerAndItems!(_);
public List<CharData> mCharData = new .() ~ delete _;
public this()
{
}
}
}

View file

@ -79,7 +79,7 @@ namespace SDL2
);
[LinkName("IMG_LoadTexture")]
private static extern SDL.Texture* LoadTexture(
public static extern SDL.Texture* LoadTexture(
SDL.Renderer* renderer,
char8* file
);

View file

@ -10,6 +10,8 @@ namespace SDL2
{
public SDL.Surface* mSurface;
public SDL.Texture* mTexture;
public int32 mWidth;
public int32 mHeight;
public ~this()
{
@ -26,7 +28,25 @@ namespace SDL2
return .Err;
mSurface = origSurface;
mTexture = SDL.CreateTextureFromSurface(gApp.mRenderer, mSurface);
SDL.Rect rect = .(0, 0, mSurface.w, mSurface.h);
mTexture = SDL.CreateTexture(gApp.mRenderer, SDL.PIXELFORMAT_ABGR8888, (.)SDL.TextureAccess.Static, mSurface.w, mSurface.h);
uint32* data = new uint32[mSurface.w*mSurface.h]*;
defer delete data;
int res = SDL.ConvertPixels(mSurface.w, mSurface.h, mSurface.format.format, mSurface.pixels, mSurface.pitch, SDL.PIXELFORMAT_ABGR8888, data, mSurface.w * 4);
if (res == -1)
{
for (int y = 0; y < mSurface.h; y++)
Internal.MemCpy(data + y*mSurface.w, (uint8*)mSurface.pixels + y*mSurface.pitch, mSurface.w*4);
}
SDL.UpdateTexture(mTexture, &rect, data, mSurface.w * 4);
SDL.SetTextureBlendMode(mTexture, .Blend);
mWidth = mSurface.w;
mHeight = mSurface.h;
return .Ok;
}
@ -54,6 +74,7 @@ namespace SDL2
class Font
{
public SDLTTF.Font* mFont;
public BitmapFont mBMFont;
public this()
{
@ -64,10 +85,90 @@ namespace SDL2
{
if (mFont != null)
SDLTTF.CloseFont(mFont);
delete mBMFont;
}
public Result<void> Load(StringView fileName, int32 pointSize)
{
if (fileName.EndsWith(".fnt"))
{
mBMFont = new BitmapFont();
var contents = File.ReadAllText(fileName, .. scope .());
contents.Replace("\r", "");
for (var line in contents.Split('\n', .RemoveEmptyEntries))
{
bool CheckVal(StringView text, StringView key, ref int32 val)
{
if (!text.StartsWith(key))
return false;
if (text[key.Length] != '=')
return false;
val = int32.Parse(text.Substring(key.Length + 1));
return true;
}
bool CheckVal(StringView text, String key, String val)
{
if (!text.StartsWith(key))
return false;
if (text[key.Length] != '=')
return false;
StringView sv = text.Substring(key.Length + 1);
if (sv.StartsWith('"'))
sv.RemoveFromStart(1);
if (sv.EndsWith('"'))
sv.RemoveFromEnd(1);
val.Append(sv);
return true;
}
if (line.StartsWith("page"))
{
String imageFileName = scope .();
for (var text in line.Split(' ', .RemoveEmptyEntries))
CheckVal(text, "file", imageFileName);
var dir = Path.GetDirectoryPath(fileName, .. scope .());
var imagePath = scope $"{dir}/{imageFileName}";
BitmapFont.Page page = new BitmapFont.Page();
page.mImage = new Image()..Load(imagePath);
mBMFont.mPages.Add(page);
}
if (line.StartsWith("char"))
{
BitmapFont.CharData* charData = null;
for (var text in line.Split(' ', .RemoveEmptyEntries))
{
int32 id = 0;
if (CheckVal(text, "id", ref id))
{
while (id >= mBMFont.mCharData.Count)
mBMFont.mCharData.Add(default);
charData = &mBMFont.mCharData[id];
}
if (charData != null)
{
CheckVal(text, "x", ref charData.mX);
CheckVal(text, "y", ref charData.mY);
CheckVal(text, "width", ref charData.mWidth);
CheckVal(text, "height", ref charData.mHeight);
CheckVal(text, "xoffset", ref charData.mXOfs);
CheckVal(text, "yoffset", ref charData.mYOfs);
CheckVal(text, "xadvance", ref charData.mXAdvance);
CheckVal(text, "page", ref charData.mPage);
}
}
}
}
return .Ok;
}
mFont = SDLTTF.OpenFont(fileName.ToScopeCStr!(), pointSize);
if (mFont == null)
return .Err;
@ -86,7 +187,10 @@ namespace SDL2
public int32 mHeight = 768;
public bool* mKeyboardState;
public bool mHasAudio;
public bool mDidInit;
private Stopwatch mFPSStopwatch = new .() ~ delete _;
private int32 mFPSCount;
private Stopwatch mStopwatch = new .() ~ delete _;
private int mCurPhysTickCount = 0;
@ -103,8 +207,17 @@ namespace SDL2
SDL.DestroyWindow(mWindow);
}
public void Init()
public void PreInit()
{
#if BF_PLATFORM_WASM
emscripten_set_main_loop(=> EmscriptenMainLoop, 0, 1);
#endif
}
public virtual void Init()
{
mDidInit = true;
String exePath = scope .();
Environment.GetExecutableFilePath(exePath);
String exeDir = scope .();
@ -120,12 +233,16 @@ namespace SDL2
SDL.EventState(.JoyDeviceAdded, .Disable);
SDL.EventState(.JoyDeviceRemoved, .Disable);
mWindow = SDL.CreateWindow(mTitle, .Undefined, .Undefined, mWidth, mHeight, .Hidden); // Initially hide window
//mWindow = SDL.CreateWindow(mTitle, .Undefined, .Undefined, mWidth, mHeight, .Hidden); // Initially hide window
mWindow = SDL.CreateWindow(mTitle, .Undefined, .Undefined, mWidth, mHeight, .Shown); // Initially hide window
mRenderer = SDL.CreateRenderer(mWindow, -1, .Accelerated);
mScreen = SDL.GetWindowSurface(mWindow);
SDLImage.Init(.PNG | .JPG);
SDLImage.Init(.PNG);
mHasAudio = SDLMixer.OpenAudio(44100, SDLMixer.MIX_DEFAULT_FORMAT, 2, 4096) >= 0;
SDL.SetRenderDrawBlendMode(mRenderer, .Blend);
SDLTTF.Init();
}
@ -176,19 +293,77 @@ namespace SDL2
public void Draw(Image image, float x, float y)
{
SDL.Rect srcRect = .(0, 0, image.mSurface.w, image.mSurface.h);
SDL.Rect destRect = .((int32)x, (int32)y, image.mSurface.w, image.mSurface.h);
SDL.Rect srcRect = .(0, 0, image.mWidth, image.mHeight);
SDL.Rect destRect = .((int32)x, (int32)y, image.mWidth, image.mHeight);
SDL.RenderCopy(mRenderer, image.mTexture, &srcRect, &destRect);
}
public void Draw(Image image, float x, float y, float rot, float centerX, float centerY)
{
SDL.Rect srcRect = .(0, 0, image.mSurface.w, image.mSurface.h);
SDL.Rect destRect = .((int32)x, (int32)y, image.mSurface.w, image.mSurface.h);
SDL.Rect srcRect = .(0, 0, image.mWidth, image.mHeight);
SDL.Rect destRect = .((int32)x, (int32)y, image.mWidth, image.mHeight);
SDL.Point centerPoint = .((.)centerX, (.)centerY);
SDL.RenderCopyEx(mRenderer, image.mTexture, &srcRect, &destRect, rot, &centerPoint, .None);
}
public void DrawString(Font font, float x, float y, String str, SDL.Color color, bool centerX = false)
{
var x;
if (font.mBMFont != null)
{
for (var page in font.mBMFont.mPages)
SDL.SetTextureColorMod(page.mImage.mTexture, color.r, color.g, color.b);
var drawX = x;
var drawY = y;
if (centerX)
{
float width = 0;
for (var c in str.RawChars)
{
if ((int32)c >= font.mBMFont.mCharData.Count)
continue;
var charData = ref font.mBMFont.mCharData[(int32)c];
width += charData.mXAdvance;
}
drawX -= width / 2;
}
for (var c in str.RawChars)
{
if ((int32)c >= font.mBMFont.mCharData.Count)
continue;
var charData = ref font.mBMFont.mCharData[(int32)c];
SDL.Rect srcRect = .(charData.mX, charData.mY, charData.mWidth, charData.mHeight);
SDL.Rect destRect = .((int32)drawX + charData.mXOfs, (int32)drawY + charData.mYOfs, charData.mWidth, charData.mHeight);
SDL.RenderCopy(mRenderer, font.mBMFont.mPages[charData.mPage].mImage.mTexture, &srcRect, &destRect);
drawX += charData.mXAdvance;
}
}
else
{
#if !NOTTF
SDL.SetRenderDrawColor(mRenderer, 255, 255, 255, 255);
let surface = SDLTTF.RenderUTF8_Blended(font.mFont, str, color);
let texture = SDL.CreateTextureFromSurface(mRenderer, surface);
SDL.Rect srcRect = .(0, 0, surface.w, surface.h);
if (centerX)
x -= surface.w / 2;
SDL.Rect destRect = .((int32)x, (int32)y, surface.w, surface.h);
SDL.RenderCopy(mRenderer, texture, &srcRect, &destRect);
SDL.FreeSurface(surface);
SDL.DestroyTexture(texture);
#endif
}
}
public void PlaySound(Sound sound, float volume = 1.0f, float pan = 0.5f)
{
if (sound == null)
@ -214,8 +389,19 @@ namespace SDL2
[CLink, CallingConvention(.Stdcall)]
private static extern void emscripten_set_main_loop(em_callback_func func, int32 fps, int32 simulateInfinteLoop);
[CLink, CallingConvention(.Stdcall)]
private static extern int32 emscripten_set_main_loop_timing(int32 mode, int32 value);
[CLink, CallingConvention(.Stdcall)]
private static extern double emscripten_get_now();
private static void EmscriptenMainLoop()
{
if (!gApp.mDidInit)
{
gApp.Init();
gApp.mStopwatch.Start();
}
gApp.RunOneFrame();
}
#endif
@ -225,15 +411,25 @@ namespace SDL2
mStopwatch.Start();
#if BF_PLATFORM_WASM
emscripten_set_main_loop(=> EmscriptenMainLoop, -1, 1);
emscripten_set_main_loop(=> EmscriptenMainLoop, 0, 1);
#else
while (true)
RunOneFrame();
while (RunOneFrame()) {}
#endif
}
private void RunOneFrame()
private bool RunOneFrame()
{
if (!mFPSStopwatch.IsRunning)
mFPSStopwatch.Start();
mFPSCount++;
if (mFPSStopwatch.ElapsedMilliseconds > 1000)
{
//Debug.WriteLine($"FPS: {mFPSCount} @ {mStopwatch.Elapsed} now: {emscripten_get_now()}");
mFPSCount = 0;
mFPSStopwatch.Restart();
}
int32 waitTime = 1;
SDL.Event event;
@ -242,7 +438,7 @@ namespace SDL2
switch (event.type)
{
case .Quit:
return;
return false;
case .KeyDown:
KeyDown(event.key);
case .KeyUp:
@ -292,6 +488,7 @@ namespace SDL2
}
mCurPhysTickCount = newPhysTickCount;
return true;
}
}

View file

@ -589,9 +589,11 @@ namespace IDE
if (isExe || isDynLib)
{
var actualTargetPath = Path.GetActualPathName(targetPath, .. scope .());
String linkLine = scope String();
linkLine.Append("-o ");
IDEUtils.AppendWithOptionalQuotes(linkLine, targetPath);
IDEUtils.AppendWithOptionalQuotes(linkLine, actualTargetPath);
linkLine.Append(" ");
linkLine.Append(objectsArg);
@ -667,7 +669,8 @@ namespace IDE
linkLine.Replace('\\', '/');
var runCmd = gApp.QueueRun(compilerExePath, linkLine, project.mProjectDir, .UTF8);
var targetDir = Path.GetDirectoryPath(actualTargetPath, .. scope .());
var runCmd = gApp.QueueRun(compilerExePath, linkLine, targetDir, .UTF8);
runCmd.mReference = new .(project.mProjectName);
runCmd.mOnlyIfNotFailed = true;
var tagetCompletedCmd = new IDEApp.TargetCompletedCmd(project);

View file

@ -1061,16 +1061,16 @@ namespace IDE
public class WasmOptions
{
[Reflect]
public bool mEnableThreads = true;
public bool mEnableThreads = false;
public void Deserialize(StructuredData data)
{
mEnableThreads = data.GetBool("EnableThreads", true);
mEnableThreads = data.GetBool("EnableThreads", false);
}
public void Serialize(StructuredData data)
{
data.ConditionalAdd("EnableThreads", mEnableThreads, true);
data.ConditionalAdd("EnableThreads", mEnableThreads, false);
}
}