mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-10 20:42:21 +02:00
wasm improvements
This commit is contained in:
parent
17b29c7227
commit
474454382f
6 changed files with 257 additions and 22 deletions
|
@ -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"
|
||||
|
|
32
BeefLibs/SDL2/src/BitmapFont.bf
Normal file
32
BeefLibs/SDL2/src/BitmapFont.bf
Normal 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()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
);
|
||||
|
|
|
@ -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, ¢erPoint, .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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue