Updated sokol to latest git commit 1d48f3a.

RefactorUnifiedBlendTreeStateMachineHandling
Martin Felis 2023-04-15 00:06:12 +02:00
parent 2e631b4fc3
commit eb70c06c57
18 changed files with 11117 additions and 6874 deletions

View File

@ -57,35 +57,6 @@ OZZ_OPTIONS_DECLARE_STRING(skeleton, "Path to the runtime skeleton file.",
OZZ_OPTIONS_DECLARE_STRING(animation, "Path to the raw animation file.",
"media/animation_raw.ozz", false)
namespace {
// Loads a raw animation from a file.
bool LoadAnimation(const char* _filename,
ozz::animation::offline::RawAnimation* _animation) {
assert(_filename && _animation);
ozz::log::Out() << "Loading raw animation archive: " << _filename << "."
<< std::endl;
ozz::io::File file(_filename, "rb");
if (!file.opened()) {
ozz::log::Err() << "Failed to open animation file " << _filename << "."
<< std::endl;
return false;
}
ozz::io::IArchive archive(&file);
if (!archive.TestTag<ozz::animation::offline::RawAnimation>()) {
ozz::log::Err() << "Failed to load raw animation instance from file "
<< _filename << "." << std::endl;
return false;
}
// Once the tag is validated, reading cannot fail.
archive >> *_animation;
// Ensure animation is valid.
return _animation->Validate();
}
} // namespace
class OptimizeSampleApplication : public ozz::sample::Application {
public:
OptimizeSampleApplication()
@ -285,7 +256,7 @@ class OptimizeSampleApplication : public ozz::sample::Application {
// Imports offline animation from a binary file.
// Invalid animations are rejected by the load function.
if (!LoadAnimation(OPTIONS_animation, &raw_animation_)) {
if (!ozz::sample::LoadRawAnimation(OPTIONS_animation, &raw_animation_)) {
return false;
}

View File

@ -1,12 +1,13 @@
# Sokol
[![Build Status](https://github.com/floooh/sokol/workflows/build_and_test/badge.svg)](https://github.com/floooh/sokol/actions)
Simple
[STB-style](https://github.com/nothings/stb/blob/master/docs/stb_howto.txt)
cross-platform libraries for C and C++, written in C.
[**See what's new**](https://github.com/floooh/sokol/blob/master/CHANGELOG.md) (**08-Oct-2021** revisited and cleaned up texture compression support in sokol_gfx.h)
[**See what's new**](https://github.com/floooh/sokol/blob/master/CHANGELOG.md) (**20-Feb-2023** a new set of functions in sokol_gfx.h
to get a pre-filled 'desc struct' for a resource)
[![Build](/../../actions/workflows/main.yml/badge.svg)](/../../actions/workflows/main.yml) [![Bindings](/../../actions/workflows/gen_bindings.yml/badge.svg)](/../../actions/workflows/gen_bindings.yml) [![build](https://github.com/floooh/sokol-zig/actions/workflows/main.yml/badge.svg)](https://github.com/floooh/sokol-zig/actions/workflows/main.yml) [![build](https://github.com/floooh/sokol-nim/actions/workflows/main.yml/badge.svg)](https://github.com/floooh/sokol-nim/actions/workflows/main.yml) [![Odin](https://github.com/floooh/sokol-odin/actions/workflows/main.yml/badge.svg)](https://github.com/floooh/sokol-odin/actions/workflows/main.yml)[![Rust](https://github.com/floooh/sokol-rust/actions/workflows/main.yml/badge.svg)](https://github.com/floooh/sokol-rust/actions/workflows/main.yml)
## Examples and Related Projects
@ -14,10 +15,14 @@ cross-platform libraries for C and C++, written in C.
- [Doom Shareware](https://floooh.github.io/doom-sokol/) ported to the Sokol headers ([source](https://github.com/floooh/doom-sokol))
- [sokol_gp.h](https://github.com/edubart/sokol_gp) a 2D shape drawing library on top of sokol_gfx.h
- [LearnOpenGL examples ported to sokol-gfx](https://www.geertarien.com/learnopengl-examples-html5/) by @geertarien (cool stuff!)
- [Dear ImGui starterkit](https://github.com/floooh/cimgui-sokol-starterkit) a self-contained starterkit for writing Dear ImGui apps in C.
- [qoiview](https://github.com/floooh/qoiview) a basic viewer for the new QOI image file format
- [Tiny 8-bit emulators](https://floooh.github.io/tiny8bit/)
- A 'single-file' [Pacman clone in C99](https://github.com/floooh/pacman.c/), also available in [Zig](https://github.com/floooh/pacman.zig/)
@ -40,6 +45,7 @@ useful details for integrating the Sokol headers into your own project with your
- [**sokol\_audio.h**](https://github.com/floooh/sokol/blob/master/sokol_audio.h): minimal buffer-streaming audio playback
- [**sokol\_fetch.h**](https://github.com/floooh/sokol/blob/master/sokol_fetch.h): asynchronous data streaming from HTTP and local filesystem
- [**sokol\_args.h**](https://github.com/floooh/sokol/blob/master/sokol_args.h): unified cmdline/URL arg parser for web and native apps
- [**sokol\_log.h**](https://github.com/floooh/sokol/blob/master/sokol_log.h): provides a standard logging callback for the other sokol headers
## Utility libraries
@ -52,6 +58,16 @@ useful details for integrating the Sokol headers into your own project with your
- [**sokol\_memtrack.h**](https://github.com/floooh/sokol/blob/master/util/sokol_memtrack.h): easily track memory allocations in sokol headers
- [**sokol\_shape.h**](https://github.com/floooh/sokol/blob/master/util/sokol_shape.h): generate simple shapes and plug them into sokol-gfx resource creation structs
- [**sokol\_color.h**](https://github.com/floooh/sokol/blob/master/util/sokol_color.h): X11 style color constants and functions for creating sg_color objects
- [**sokol\_spine.h**](https://github.com/floooh/sokol/blob/master/util/sokol_spine.h): a sokol-style wrapper around the Spine C runtime (http://en.esotericsoftware.com/spine-in-depth)
## 'Official' Language Bindings
These are automatically updated on changes to the C headers:
- [sokol-zig](https://github.com/floooh/sokol-zig)
- [sokol-odin](https://github.com/floooh/sokol-odin)
- [sokol-nim](https://github.com/floooh/sokol-nim)
- [sokol-rust](https://github.com/floooh/sokol-rust)
## Notes
@ -83,6 +99,7 @@ A triangle in C99 with GLFW:
#define SOKOL_IMPL
#define SOKOL_GLCORE33
#include "sokol_gfx.h"
#include "sokol_log.h"
#define GLFW_INCLUDE_NONE
#include "GLFW/glfw3.h"
@ -99,7 +116,9 @@ int main() {
glfwSwapInterval(1);
/* setup sokol_gfx */
sg_setup(&(sg_desc){0});
sg_setup(&(sg_desc){
.logger.func = slog_func,
});
/* a vertex buffer */
const float vertices[] = {
@ -190,13 +209,15 @@ to split the Objective-C code from the C code of the sample):
```c
#include "sokol_gfx.h"
#include "sokol_app.h"
#include "sokol_log.h"
#include "sokol_glue.h"
sg_pass_action pass_action;
void init(void) {
sg_setup(&(sg_desc){
.context = sapp_sgcontext()
.context = sapp_sgcontext(),
.logger.func = slog_func,
});
pass_action = (sg_pass_action) {
.colors[0] = { .action=SG_ACTION_CLEAR, .value={1.0f, 0.0f, 0.0f, 1.0f} }
@ -223,6 +244,7 @@ sapp_desc sokol_main(int argc, char* argv[]) {
.width = 400,
.height = 300,
.window_title = "Clear Sample",
.logger.func = slog_func,
};
}
```
@ -257,7 +279,8 @@ static void stream_cb(float* buffer, int num_frames, int num_channels) {
int main() {
// init sokol-audio with default params
saudio_setup(&(saudio_desc){
.stream_cb = stream_cb
.stream_cb = stream_cb,
.logger.func = slog_func,
});
// run main loop
@ -274,7 +297,9 @@ The same code using the push-model
#define BUF_SIZE (32)
int main() {
// init sokol-audio with default params, no callback
saudio_setup(&(saudio_desc){0});
saudio_setup(&(saudio_desc){
.logger.func = slog_func,
});
assert(saudio_channels() == 1);
// a small intermediate buffer so we don't need to push
@ -315,6 +340,7 @@ Simple C99 example loading a file into a static buffer:
```c
#include "sokol_fetch.h"
#include "sokol_log.h"
static void response_callback(const sfetch_response*);
@ -325,7 +351,7 @@ static uint8_t buffer[MAX_FILE_SIZE];
static void init(void) {
...
// setup sokol-fetch with default config:
sfetch_setup(&(sfetch_desc_t){0});
sfetch_setup(&(sfetch_desc_t){ .logger.func = slog_func });
// start loading a file into a statically allocated buffer:
sfetch_send(&(sfetch_request_t){

View File

@ -22,6 +22,7 @@ To update the Zig bindings:
> cd sokol/bindgen
> git clone https://github.com/floooh/sokol-zig
> git clone https://github.com/floooh/sokol-nim
> git clone https://github.com/floooh/sokol-odin
> python3 gen_all.py
```

File diff suppressed because it is too large Load Diff

View File

@ -16,9 +16,6 @@
Optionally provide the following defines with your own implementations:
SOKOL_ASSERT(c) - your own assert macro (default: assert(c))
SOKOL_LOG(msg) - your own logging functions (default: puts(msg))
SOKOL_CALLOC(n,s) - your own calloc() implementation (default: calloc(n,s))
SOKOL_FREE(p) - your own free() implementation (default: free(p))
SOKOL_ARGS_API_DECL - public function declaration prefix (default: extern)
SOKOL_API_DECL - same as SOKOL_ARGS_API_DECL
SOKOL_API_IMPL - public function implementation prefix (default: -)
@ -218,6 +215,36 @@
Return the value of argument at index. Returns empty string
if index is outside range.
MEMORY ALLOCATION OVERRIDE
==========================
You can override the memory allocation functions at initialization time
like this:
void* my_alloc(size_t size, void* user_data) {
return malloc(size);
}
void my_free(void* ptr, void* user_data) {
free(ptr);
}
...
sargs_setup(&(sargs_desc){
// ...
.allocator = {
.alloc = my_alloc,
.free = my_free,
.user_data = ...,
}
});
...
If no overrides are provided, malloc and free will be used.
This only affects memory allocation calls done by sokol_args.h
itself though, not any allocations in OS libraries.
TODO
====
- parsing errors?
@ -251,6 +278,7 @@
#define SOKOL_ARGS_INCLUDED (1)
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h> // size_t
#if defined(SOKOL_API_DECL) && !defined(SOKOL_ARGS_API_DECL)
#define SOKOL_ARGS_API_DECL SOKOL_API_DECL
@ -269,11 +297,26 @@
extern "C" {
#endif
/*
sargs_allocator
Used in sargs_desc to provide custom memory-alloc and -free functions
to sokol_args.h. If memory management should be overridden, both the
alloc and free function must be provided (e.g. it's not valid to
override one function but not the other).
*/
typedef struct sargs_allocator {
void* (*alloc)(size_t size, void* user_data);
void (*free)(void* ptr, void* user_data);
void* user_data;
} sargs_allocator;
typedef struct sargs_desc {
int argc;
char** argv;
int max_args;
int buf_size;
sargs_allocator allocator;
} sargs_desc;
/* setup sokol-args */
@ -313,7 +356,13 @@ inline void sargs_setup(const sargs_desc& desc) { return sargs_setup(&desc); }
/*--- IMPLEMENTATION ---------------------------------------------------------*/
#ifdef SOKOL_ARGS_IMPL
#define SOKOL_ARGS_IMPL_INCLUDED (1)
#include <string.h> /* memset, strcmp */
#if defined(SOKOL_MALLOC) || defined(SOKOL_CALLOC) || defined(SOKOL_FREE)
#error "SOKOL_MALLOC/CALLOC/FREE macros are no longer supported, please use sargs_desc.allocator to override memory allocation functions"
#endif
#include <string.h> // memset, strcmp
#include <stdlib.h> // malloc, free
#if defined(__EMSCRIPTEN__)
#include <emscripten/emscripten.h>
@ -324,30 +373,13 @@ inline void sargs_setup(const sargs_desc& desc) { return sargs_setup(&desc); }
#endif
#ifndef SOKOL_DEBUG
#ifndef NDEBUG
#define SOKOL_DEBUG (1)
#define SOKOL_DEBUG
#endif
#endif
#ifndef SOKOL_ASSERT
#include <assert.h>
#define SOKOL_ASSERT(c) assert(c)
#endif
#if !defined(SOKOL_CALLOC) && !defined(SOKOL_FREE)
#include <stdlib.h>
#endif
#if !defined(SOKOL_CALLOC)
#define SOKOL_CALLOC(n,s) calloc(n,s)
#endif
#if !defined(SOKOL_FREE)
#define SOKOL_FREE(p) free(p)
#endif
#ifndef SOKOL_LOG
#ifdef SOKOL_DEBUG
#include <stdio.h>
#define SOKOL_LOG(s) { SOKOL_ASSERT(s); puts(s); }
#else
#define SOKOL_LOG(s)
#endif
#endif
#ifndef _SOKOL_PRIVATE
#if defined(__GNUC__) || defined(__clang__)
@ -388,10 +420,43 @@ typedef struct {
uint32_t parse_state;
char quote; /* current quote char, 0 if not in a quote */
bool in_escape; /* currently in an escape sequence */
sargs_allocator allocator;
} _sargs_state_t;
static _sargs_state_t _sargs;
/*== PRIVATE IMPLEMENTATION FUNCTIONS ========================================*/
_SOKOL_PRIVATE void _sargs_clear(void* ptr, size_t size) {
SOKOL_ASSERT(ptr && (size > 0));
memset(ptr, 0, size);
}
_SOKOL_PRIVATE void* _sargs_malloc(size_t size) {
SOKOL_ASSERT(size > 0);
void* ptr;
if (_sargs.allocator.alloc) {
ptr = _sargs.allocator.alloc(size, _sargs.allocator.user_data);
}
else {
ptr = malloc(size);
}
SOKOL_ASSERT(ptr);
return ptr;
}
_SOKOL_PRIVATE void* _sargs_malloc_clear(size_t size) {
void* ptr = _sargs_malloc(size);
_sargs_clear(ptr, size);
return ptr;
}
_SOKOL_PRIVATE void _sargs_free(void* ptr) {
if (_sargs.allocator.free) {
_sargs.allocator.free(ptr, _sargs.allocator.user_data);
}
else {
free(ptr);
}
}
_SOKOL_PRIVATE void _sargs_putc(char c) {
if ((_sargs.buf_pos+2) < _sargs.buf_size) {
@ -617,6 +682,11 @@ _SOKOL_PRIVATE bool _sargs_parse_cargs(int argc, const char** argv) {
#ifdef __cplusplus
extern "C" {
#endif
#if defined(EM_JS_DEPS)
EM_JS_DEPS(sokol_audio, "$withStackSave,$allocateUTF8OnStack");
#endif
EMSCRIPTEN_KEEPALIVE void _sargs_add_kvp(const char* key, const char* val) {
SOKOL_ASSERT(_sargs.valid && key && val);
if (_sargs.num_args >= _sargs.max_args) {
@ -648,11 +718,15 @@ EMSCRIPTEN_KEEPALIVE void _sargs_add_kvp(const char* key, const char* val) {
/* JS function to extract arguments from the page URL */
EM_JS(void, sargs_js_parse_url, (void), {
var params = new URLSearchParams(window.location.search).entries();
for (var p = params.next(); !p.done; p = params.next()) {
var key = p.value[0];
var val = p.value[1];
var res = ccall('_sargs_add_kvp', 'void', ['string','string'], [key,val]);
const params = new URLSearchParams(window.location.search).entries();
for (let p = params.next(); !p.done; p = params.next()) {
const key = p.value[0];
const val = p.value[1];
withStackSave(() => {
const key_cstr = allocateUTF8OnStack(key);
const val_cstr = allocateUTF8OnStack(val);
__sargs_add_kvp(key_cstr, val_cstr)
});
}
});
@ -661,14 +735,15 @@ EM_JS(void, sargs_js_parse_url, (void), {
/*== PUBLIC IMPLEMENTATION FUNCTIONS =========================================*/
SOKOL_API_IMPL void sargs_setup(const sargs_desc* desc) {
SOKOL_ASSERT(desc);
memset(&_sargs, 0, sizeof(_sargs));
_sargs_clear(&_sargs, sizeof(_sargs));
_sargs.max_args = _sargs_def(desc->max_args, _SARGS_MAX_ARGS_DEF);
_sargs.buf_size = _sargs_def(desc->buf_size, _SARGS_BUF_SIZE_DEF);
SOKOL_ASSERT(_sargs.buf_size > 8);
_sargs.args = (_sargs_kvp_t*) SOKOL_CALLOC((size_t)_sargs.max_args, sizeof(_sargs_kvp_t));
_sargs.buf = (char*) SOKOL_CALLOC((size_t)_sargs.buf_size, sizeof(char));
_sargs.args = (_sargs_kvp_t*) _sargs_malloc_clear((size_t)_sargs.max_args * sizeof(_sargs_kvp_t));
_sargs.buf = (char*) _sargs_malloc_clear((size_t)_sargs.buf_size * sizeof(char));
/* the first character in buf is reserved and always zero, this is the 'empty string' */
_sargs.buf_pos = 1;
_sargs.allocator = desc->allocator;
_sargs.valid = true;
/* parse argc/argv */
@ -683,11 +758,11 @@ SOKOL_API_IMPL void sargs_setup(const sargs_desc* desc) {
SOKOL_API_IMPL void sargs_shutdown(void) {
SOKOL_ASSERT(_sargs.valid);
if (_sargs.args) {
SOKOL_FREE(_sargs.args);
_sargs_free(_sargs.args);
_sargs.args = 0;
}
if (_sargs.buf) {
SOKOL_FREE(_sargs.buf);
_sargs_free(_sargs.buf);
_sargs.buf = 0;
}
_sargs.valid = false;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

343
3rdparty/sokol/sokol_log.h vendored Normal file
View File

@ -0,0 +1,343 @@
#if defined(SOKOL_IMPL) && !defined(SOKOL_LOG_IMPL)
#define SOKOL_LOG_IMPL
#endif
#ifndef SOKOL_LOG_INCLUDED
/*
sokol_log.h -- common logging callback for sokol headers
Project URL: https://github.com/floooh/sokol
Example code: https://github.com/floooh/sokol-samples
Do this:
#define SOKOL_IMPL or
#define SOKOL_LOG_IMPL
before you include this file in *one* C or C++ file to create the
implementation.
Optionally provide the following defines when building the implementation:
SOKOL_ASSERT(c) - your own assert macro (default: assert(c))
SOKOL_UNREACHABLE() - a guard macro for unreachable code (default: assert(false))
SOKOL_LOG_API_DECL - public function declaration prefix (default: extern)
SOKOL_API_DECL - same as SOKOL_GFX_API_DECL
SOKOL_API_IMPL - public function implementation prefix (default: -)
Optionally define the following for verbose output:
SOKOL_DEBUG - by default this is defined if _DEBUG is defined
OVERVIEW
========
sokol_log.h provides a default logging callback for other sokol headers.
To use the default log callback, just include sokol_log.h and provide
a function pointer to the 'slog_func' function when setting up the
sokol library:
For instance with sokol_audio.h:
#include "sokol_log.h"
...
saudio_setup(&(saudio_desc){ .logger.func = slog_func });
Logging output goes to stderr and/or a platform specific logging subsystem
(which means that in some scenarios you might see logging messages duplicated):
- Windows: stderr + OutputDebugStringA()
- macOS/iOS/Linux: stderr + syslog()
- Emscripten: console.info()/warn()/error()
- Android: __android_log_write()
On Windows with sokol_app.h also note the runtime config items to make
stdout/stderr output visible on the console for WinMain() applications
via sapp_desc.win32_console_attach or sapp_desc.win32_console_create,
however when running in a debugger on Windows, the logging output should
show up on the debug output UI panel.
In debug mode, a log message might look like this:
[sspine][error][id:12] /Users/floh/projects/sokol/util/sokol_spine.h:3472:0:
SKELETON_DESC_NO_ATLAS: no atlas object provided in sspine_skeleton_desc.atlas
The source path and line number is formatted like compiler errors, in some IDEs (like VSCode)
such error messages are clickable.
In release mode, logging is less verbose as to not bloat the executable with string data, but you still get
enough information to identify the type and location of an error:
[sspine][error][id:12][line:3472]
RULES FOR WRITING YOUR OWN LOGGING FUNCTION
===========================================
- must be re-entrant because it might be called from different threads
- must treat **all** provided string pointers as optional (can be null)
- don't store the string pointers, copy the string data instead
- must not return for log level panic
LICENSE
=======
zlib/libpng license
Copyright (c) 2023 Andre Weissflog
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the
use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software in a
product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not
be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#define SOKOL_LOG_INCLUDED (1)
#include <stdint.h>
#if defined(SOKOL_API_DECL) && !defined(SOKOL_LOG_API_DECL)
#define SOKOL_LOG_API_DECL SOKOL_API_DECL
#endif
#ifndef SOKOL_LOG_API_DECL
#if defined(_WIN32) && defined(SOKOL_DLL) && defined(SOKOL_LOG_IMPL)
#define SOKOL_LOG_API_DECL __declspec(dllexport)
#elif defined(_WIN32) && defined(SOKOL_DLL)
#define SOKOL_LOG_API_DECL __declspec(dllimport)
#else
#define SOKOL_LOG_API_DECL extern
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*
Plug this function into the 'logger.func' struct item when initializating any of the sokol
headers. For instance for sokol_audio.h it would loom like this:
saudio_setup(&(saudio_desc){
.logger = {
.func = slog_func
}
});
*/
SOKOL_LOG_API_DECL void slog_func(const char* tag, uint32_t log_level, uint32_t log_item, const char* message, uint32_t line_nr, const char* filename, void* user_data);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // SOKOL_LOG_INCLUDED
// ██ ███ ███ ██████ ██ ███████ ███ ███ ███████ ███ ██ ████████ █████ ████████ ██ ██████ ███ ██
// ██ ████ ████ ██ ██ ██ ██ ████ ████ ██ ████ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██
// ██ ██ ████ ██ ██████ ██ █████ ██ ████ ██ █████ ██ ██ ██ ██ ███████ ██ ██ ██ ██ ██ ██ ██
// ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
// ██ ██ ██ ██ ███████ ███████ ██ ██ ███████ ██ ████ ██ ██ ██ ██ ██ ██████ ██ ████
//
// >>implementation
#ifdef SOKOL_LOG_IMPL
#define SOKOL_LOG_IMPL_INCLUDED (1)
#ifndef SOKOL_API_IMPL
#define SOKOL_API_IMPL
#endif
#ifndef SOKOL_DEBUG
#ifndef NDEBUG
#define SOKOL_DEBUG
#endif
#endif
#ifndef SOKOL_ASSERT
#include <assert.h>
#define SOKOL_ASSERT(c) assert(c)
#endif
#ifndef _SOKOL_PRIVATE
#if defined(__GNUC__) || defined(__clang__)
#define _SOKOL_PRIVATE __attribute__((unused)) static
#else
#define _SOKOL_PRIVATE static
#endif
#endif
#ifndef _SOKOL_UNUSED
#define _SOKOL_UNUSED(x) (void)(x)
#endif
// platform detection
#if defined(__APPLE__)
#define _SLOG_APPLE (1)
#elif defined(__EMSCRIPTEN__)
#define _SLOG_EMSCRIPTEN (1)
#elif defined(_WIN32)
#define _SLOG_WINDOWS (1)
#elif defined(__ANDROID__)
#define _SLOG_ANDROID (1)
#elif defined(__linux__) || defined(__unix__)
#define _SLOG_LINUX (1)
#else
#error "sokol_log.h: unknown platform"
#endif
#include <stdlib.h> // abort
#include <stdio.h> // fputs
#include <stddef.h> // size_t
#if defined(_SLOG_EMSCRIPTEN)
#include <emscripten/emscripten.h>
#elif defined(_SLOG_WINDOWS)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
#elif defined(_SLOG_ANDROID)
#include <android/log.h>
#elif defined(_SLOG_LINUX) || defined(_SLOG_APPLE)
#include <syslog.h>
#endif
// size of line buffer (on stack!) in bytes including terminating zero
#define _SLOG_LINE_LENGTH (512)
_SOKOL_PRIVATE char* _slog_append(const char* str, char* dst, char* end) {
if (str) {
char c;
while (((c = *str++) != 0) && (dst < (end - 1))) {
*dst++ = c;
}
}
*dst = 0;
return dst;
}
_SOKOL_PRIVATE char* _slog_itoa(uint32_t x, char* buf, size_t buf_size) {
const size_t max_digits_and_null = 11;
if (buf_size < max_digits_and_null) {
return 0;
}
char* p = buf + max_digits_and_null;
*--p = 0;
do {
*--p = '0' + (x % 10);
x /= 10;
} while (x != 0);
return p;
}
#if defined(_SLOG_EMSCRIPTEN)
EM_JS(void, slog_js_log, (uint32_t level, const char* c_str), {
const str = UTF8ToString(c_str);
switch (level) {
case 0: console.error(str); break;
case 1: console.error(str); break;
case 2: console.warn(str); break;
default: console.info(str); break;
}
});
#endif
SOKOL_API_IMPL void slog_func(const char* tag, uint32_t log_level, uint32_t log_item, const char* message, uint32_t line_nr, const char* filename, void* user_data) {
_SOKOL_UNUSED(user_data);
const char* log_level_str;
switch (log_level) {
case 0: log_level_str = "panic"; break;
case 1: log_level_str = "error"; break;
case 2: log_level_str = "warning"; break;
default: log_level_str = "info"; break;
}
// build log output line
char line_buf[_SLOG_LINE_LENGTH];
char* str = line_buf;
char* end = line_buf + sizeof(line_buf);
char num_buf[32];
if (tag) {
str = _slog_append("[", str, end);
str = _slog_append(tag, str, end);
str = _slog_append("]", str, end);
}
str = _slog_append("[", str, end);
str = _slog_append(log_level_str, str, end);
str = _slog_append("]", str, end);
str = _slog_append("[id:", str, end);
str = _slog_append(_slog_itoa(log_item, num_buf, sizeof(num_buf)), str, end);
str = _slog_append("]", str, end);
// if a filename is provided, build a clickable log message that's compatible with compiler error messages
if (filename) {
str = _slog_append(" ", str, end);
#if defined(_MSC_VER)
// MSVC compiler error format
str = _slog_append(filename, str, end);
str = _slog_append("(", str, end);
str = _slog_append(_slog_itoa(line_nr, num_buf, sizeof(num_buf)), str, end);
str = _slog_append("): ", str, end);
#else
// gcc/clang compiler error format
str = _slog_append(filename, str, end);
str = _slog_append(":", str, end);
str = _slog_append(_slog_itoa(line_nr, num_buf, sizeof(num_buf)), str, end);
str = _slog_append(":0: ", str, end);
#endif
}
else {
str = _slog_append("[line:", str, end);
str = _slog_append(_slog_itoa(line_nr, num_buf, sizeof(num_buf)), str, end);
str = _slog_append("] ", str, end);
}
if (message) {
str = _slog_append("\n\t", str, end);
str = _slog_append(message, str, end);
}
str = _slog_append("\n\n", str, end);
if (0 == log_level) {
str = _slog_append("ABORTING because of [panic]\n", str, end);
(void)str;
}
// print to stderr?
#if defined(_SLOG_LINUX) || defined(_SLOG_WINDOWS) || defined(_SLOG_APPLE)
fputs(line_buf, stderr);
#endif
// platform specific logging calls
#if defined(_SLOG_WINDOWS)
OutputDebugStringA(line_buf);
#elif defined(_SLOG_ANDROID)
int prio;
switch (log_level) {
case 0: prio = ANDROID_LOG_FATAL; break;
case 1: prio = ANDROID_LOG_ERROR; break;
case 2: prio = ANDROID_LOG_WARN; break;
default: prio = ANDROID_LOG_INFO; break;
}
__android_log_write(prio, "SOKOL", line_buf);
#elif defined(_SLOG_EMSCRIPTEN)
slog_js_log(log_level, line_buf);
#elif defined(_SLOG_LINUX) || defined(_SLOG_APPLE)
int prio;
switch (log_level) {
case 0: prio = LOG_CRIT; break;
case 1: prio = LOG_ERR; break;
case 2: prio = LOG_WARNING; break;
default: prio = LOG_INFO; break;
}
syslog(prio, "%s", line_buf);
#endif
if (0 == log_level) {
abort();
}
}
#endif // SOKOL_LOG_IMPL

View File

@ -61,6 +61,8 @@
The main purpose of this function is to remove jitter/inaccuracies from
measured frame times, and instead use the display refresh rate as
frame duration.
NOTE: for more robust frame timing, consider using the
sokol_app.h function sapp_frame_duration()
Use the following functions to convert a duration in ticks into
useful time units:
@ -77,7 +79,7 @@
Windows: QueryPerformanceFrequency() / QueryPerformanceCounter()
MacOS/iOS: mach_absolute_time()
emscripten: performance.now()
emscripten: emscripten_get_now()
Linux+others: clock_gettime(CLOCK_MONOTONIC)
zlib/libpng license
@ -199,19 +201,13 @@ static _stm_state_t _stm;
see https://gist.github.com/jspohr/3dc4f00033d79ec5bdaf67bc46c813e3
*/
#if defined(_WIN32) || (defined(__APPLE__) && defined(__MACH__))
_SOKOL_PRIVATE int64_t int64_muldiv(int64_t value, int64_t numer, int64_t denom) {
_SOKOL_PRIVATE int64_t _stm_int64_muldiv(int64_t value, int64_t numer, int64_t denom) {
int64_t q = value / denom;
int64_t r = value % denom;
return q * numer + r * numer / denom;
}
#endif
#if defined(__EMSCRIPTEN__)
EM_JS(double, stm_js_perfnow, (void), {
return performance.now();
});
#endif
SOKOL_API_IMPL void stm_setup(void) {
memset(&_stm, 0, sizeof(_stm));
_stm.initialized = 0xABCDABCD;
@ -222,7 +218,7 @@ SOKOL_API_IMPL void stm_setup(void) {
mach_timebase_info(&_stm.timebase);
_stm.start = mach_absolute_time();
#elif defined(__EMSCRIPTEN__)
_stm.start = stm_js_perfnow();
_stm.start = emscripten_get_now();
#else
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
@ -236,13 +232,12 @@ SOKOL_API_IMPL uint64_t stm_now(void) {
#if defined(_WIN32)
LARGE_INTEGER qpc_t;
QueryPerformanceCounter(&qpc_t);
now = (uint64_t) int64_muldiv(qpc_t.QuadPart - _stm.start.QuadPart, 1000000000, _stm.freq.QuadPart);
now = (uint64_t) _stm_int64_muldiv(qpc_t.QuadPart - _stm.start.QuadPart, 1000000000, _stm.freq.QuadPart);
#elif defined(__APPLE__) && defined(__MACH__)
const uint64_t mach_now = mach_absolute_time() - _stm.start;
now = (uint64_t) int64_muldiv((int64_t)mach_now, (int64_t)_stm.timebase.numer, (int64_t)_stm.timebase.denom);
now = (uint64_t) _stm_int64_muldiv((int64_t)mach_now, (int64_t)_stm.timebase.numer, (int64_t)_stm.timebase.denom);
#elif defined(__EMSCRIPTEN__)
double js_now = stm_js_perfnow() - _stm.start;
SOKOL_ASSERT(js_now >= 0.0);
double js_now = emscripten_get_now() - _stm.start;
now = (uint64_t) (js_now * 1000000.0);
#else
struct timespec ts;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -45,8 +45,6 @@
SOKOL_ASSERT(c) -- your own assert macro, default: assert(c)
SOKOL_UNREACHABLE -- your own macro to annotate unreachable code,
default: SOKOL_ASSERT(false)
SOKOL_MALLOC(s) -- your own memory allocation function, default: malloc(s)
SOKOL_FREE(p) -- your own memory free function, default: free(p)
SOKOL_GFX_IMGUI_API_DECL - public function declaration prefix (default: extern)
SOKOL_API_DECL - same as SOKOL_GFX_IMGUI_API_DECL
SOKOL_API_IMPL - public function implementation prefix (default: -)
@ -64,7 +62,21 @@
--- create an sg_imgui_t struct (which must be preserved between frames)
and initialize it with:
sg_imgui_init(&sg_imgui);
sg_imgui_init(&sg_imgui, &(sg_imgui_desc_t){ 0 });
Note that from C++ you can't inline the desc structure initialization:
const sg_imgui_desc_t desc = { };
sg_imgui_init(&sg_imgui, &desc);
Provide optional memory allocator override functions (compatible with malloc/free) like this:
sg_imgui_init(&sg_imgui, &(sg_imgui_desc_t){
.allocator = {
.alloc = my_malloc,
.free = my_free,
}
});
--- somewhere in the per-frame code call:
@ -136,6 +148,34 @@
Finer-grained drawing functions may be moved to the public API
in the future as needed.
MEMORY ALLOCATION OVERRIDE
==========================
You can override the memory allocation functions at initialization time
like this:
void* my_alloc(size_t size, void* user_data) {
return malloc(size);
}
void my_free(void* ptr, void* user_data) {
free(ptr);
}
...
sg_imgui_init(&(&ctx, &(sg_imgui_desc_t){
// ...
.allocator = {
.alloc = my_alloc,
.free = my_free,
.user_data = ...;
}
});
...
This only affects memory allocation calls done by sokol_gfx_imgui.h
itself though, not any allocations in OS libraries.
LICENSE
=======
zlib/libpng license
@ -164,6 +204,7 @@
#define SOKOL_GFX_IMGUI_INCLUDED (1)
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h> // size_t
#if !defined(SOKOL_GFX_INCLUDED)
#error "Please include sokol_gfx.h before sokol_gfx_imgui.h"
@ -616,8 +657,32 @@ typedef struct sg_imgui_caps_t {
bool open;
} sg_imgui_caps_t;
/*
sg_imgui_allocator_t
Used in sg_imgui_desc_t to provide custom memory-alloc and -free functions
to sokol_gfx_imgui.h. If memory management should be overridden, both the
alloc and free function must be provided (e.g. it's not valid to
override one function but not the other).
*/
typedef struct sg_imgui_allocator_t {
void* (*alloc)(size_t size, void* user_data);
void (*free)(void* ptr, void* user_data);
void* user_data;
} sg_imgui_allocator_t;
/*
sg_imgui_desc_t
Initialization options for sg_imgui_init().
*/
typedef struct sg_imgui_desc_t {
sg_imgui_allocator_t allocator; // optional memory allocation overrides (default: malloc/free)
} sg_imgui_desc_t;
typedef struct sg_imgui_t {
uint32_t init_tag;
sg_imgui_desc_t desc;
sg_imgui_buffers_t buffers;
sg_imgui_images_t images;
sg_imgui_shaders_t shaders;
@ -629,7 +694,7 @@ typedef struct sg_imgui_t {
sg_trace_hooks hooks;
} sg_imgui_t;
SOKOL_GFX_IMGUI_API_DECL void sg_imgui_init(sg_imgui_t* ctx);
SOKOL_GFX_IMGUI_API_DECL void sg_imgui_init(sg_imgui_t* ctx, const sg_imgui_desc_t* desc);
SOKOL_GFX_IMGUI_API_DECL void sg_imgui_discard(sg_imgui_t* ctx);
SOKOL_GFX_IMGUI_API_DECL void sg_imgui_draw(sg_imgui_t* ctx);
@ -657,6 +722,11 @@ SOKOL_GFX_IMGUI_API_DECL void sg_imgui_draw_capabilities_window(sg_imgui_t* ctx)
/*=== IMPLEMENTATION =========================================================*/
#ifdef SOKOL_GFX_IMGUI_IMPL
#define SOKOL_GFX_IMGUI_IMPL_INCLUDED (1)
#if defined(SOKOL_MALLOC) || defined(SOKOL_CALLOC) || defined(SOKOL_FREE)
#error "SOKOL_MALLOC/CALLOC/FREE macros are no longer supported, please use sg_imgui_desc_t.allocator to override memory allocation functions"
#endif
#if defined(__cplusplus)
#if !defined(IMGUI_VERSION)
#error "Please include imgui.h before the sokol_imgui.h implementation"
@ -673,11 +743,6 @@ SOKOL_GFX_IMGUI_API_DECL void sg_imgui_draw_capabilities_window(sg_imgui_t* ctx)
#ifndef SOKOL_UNREACHABLE
#define SOKOL_UNREACHABLE SOKOL_ASSERT(false)
#endif
#ifndef SOKOL_MALLOC
#include <stdlib.h>
#define SOKOL_MALLOC(s) malloc(s)
#define SOKOL_FREE(p) free(p)
#endif
#ifndef _SOKOL_PRIVATE
#if defined(__GNUC__) || defined(__clang__)
#define _SOKOL_PRIVATE __attribute__((unused)) static
@ -693,7 +758,8 @@ SOKOL_GFX_IMGUI_API_DECL void sg_imgui_draw_capabilities_window(sg_imgui_t* ctx)
#endif
#include <string.h>
#include <stdio.h> /* snprintf */
#include <stdio.h> // snprintf
#include <stdlib.h> // malloc, free
#define _SG_IMGUI_SLOT_MASK (0xFFFF)
#define _SG_IMGUI_LIST_WIDTH (192)
@ -718,38 +784,38 @@ _SOKOL_PRIVATE void igSeparator() {
_SOKOL_PRIVATE void igSameLine(float offset_from_start_x, float spacing) {
return ImGui::SameLine(offset_from_start_x,spacing);
}
_SOKOL_PRIVATE void igPushIDInt(int int_id) {
_SOKOL_PRIVATE void igPushID_Int(int int_id) {
return ImGui::PushID(int_id);
}
_SOKOL_PRIVATE void igPopID() {
return ImGui::PopID();
}
_SOKOL_PRIVATE bool igSelectableBool(const char* label,bool selected,ImGuiSelectableFlags flags,const ImVec2 size) {
_SOKOL_PRIVATE bool igSelectable_Bool(const char* label,bool selected,ImGuiSelectableFlags flags,const ImVec2 size) {
return ImGui::Selectable(label,selected,flags,size);
}
_SOKOL_PRIVATE bool igSmallButton(const char* label) {
return ImGui::SmallButton(label);
}
_SOKOL_PRIVATE bool igBeginChildStr(const char* str_id,const ImVec2 size,bool border,ImGuiWindowFlags flags) {
_SOKOL_PRIVATE bool igBeginChild_Str(const char* str_id,const ImVec2 size,bool border,ImGuiWindowFlags flags) {
return ImGui::BeginChild(str_id,size,border,flags);
}
_SOKOL_PRIVATE void igEndChild() {
return ImGui::EndChild();
}
_SOKOL_PRIVATE void igPushStyleColorU32(ImGuiCol idx, ImU32 col) {
_SOKOL_PRIVATE void igPushStyleColor_U32(ImGuiCol idx, ImU32 col) {
return ImGui::PushStyleColor(idx,col);
}
_SOKOL_PRIVATE void igPopStyleColor(int count) {
return ImGui::PopStyleColor(count);
}
_SOKOL_PRIVATE bool igTreeNodeStrStr(const char* str_id,const char* fmt,...) {
_SOKOL_PRIVATE bool igTreeNode_StrStr(const char* str_id,const char* fmt,...) {
va_list args;
va_start(args, fmt);
bool ret = ImGui::TreeNodeV(str_id,fmt,args);
va_end(args);
return ret;
}
_SOKOL_PRIVATE bool igTreeNodeStr(const char* label) {
_SOKOL_PRIVATE bool igTreeNode_Str(const char* label) {
return ImGui::TreeNode(label);
}
_SOKOL_PRIVATE void igTreePop() {
@ -785,48 +851,131 @@ _SOKOL_PRIVATE void igEnd() {
#endif
/*--- UTILS ------------------------------------------------------------------*/
_SOKOL_PRIVATE void _sg_imgui_clear(void* ptr, size_t size) {
SOKOL_ASSERT(ptr && (size > 0));
memset(ptr, 0, size);
}
_SOKOL_PRIVATE void* _sg_imgui_malloc(const sg_imgui_allocator_t* allocator, size_t size) {
SOKOL_ASSERT(allocator && (size > 0));
void* ptr;
if (allocator->alloc) {
ptr = allocator->alloc(size, allocator->user_data);
}
else {
ptr = malloc(size);
}
SOKOL_ASSERT(ptr);
return ptr;
}
_SOKOL_PRIVATE void* _sg_imgui_malloc_clear(const sg_imgui_allocator_t* allocator, size_t size) {
void* ptr = _sg_imgui_malloc(allocator, size);
_sg_imgui_clear(ptr, size);
return ptr;
}
_SOKOL_PRIVATE void _sg_imgui_free(const sg_imgui_allocator_t* allocator, void* ptr) {
SOKOL_ASSERT(allocator);
if (allocator->free) {
allocator->free(ptr, allocator->user_data);
}
else {
free(ptr);
}
}
_SOKOL_PRIVATE void* _sg_imgui_realloc(const sg_imgui_allocator_t* allocator, void* old_ptr, size_t old_size, size_t new_size) {
SOKOL_ASSERT(allocator && (new_size > 0) && (new_size > old_size));
void* new_ptr = _sg_imgui_malloc(allocator, new_size);
if (old_ptr) {
if (old_size > 0) {
memcpy(new_ptr, old_ptr, old_size);
}
_sg_imgui_free(allocator, old_ptr);
}
return new_ptr;
}
_SOKOL_PRIVATE int _sg_imgui_slot_index(uint32_t id) {
int slot_index = (int) (id & _SG_IMGUI_SLOT_MASK);
SOKOL_ASSERT(0 != slot_index);
return slot_index;
}
_SOKOL_PRIVATE int _sg_imgui_uniform_size(sg_uniform_type type, int count) {
_SOKOL_PRIVATE uint32_t _sg_imgui_align_u32(uint32_t val, uint32_t align) {
SOKOL_ASSERT((align > 0) && ((align & (align - 1)) == 0));
return (val + (align - 1)) & ~(align - 1);
}
_SOKOL_PRIVATE uint32_t _sg_imgui_std140_uniform_alignment(sg_uniform_type type, int array_count) {
SOKOL_ASSERT(array_count > 0);
if (array_count == 1) {
switch (type) {
case SG_UNIFORMTYPE_INVALID: return 0;
case SG_UNIFORMTYPE_FLOAT: return 4 * count;
case SG_UNIFORMTYPE_FLOAT2: return 8 * count;
case SG_UNIFORMTYPE_FLOAT3: return 12 * count; /* FIXME: std140??? */
case SG_UNIFORMTYPE_FLOAT4: return 16 * count;
case SG_UNIFORMTYPE_MAT4: return 64 * count;
case SG_UNIFORMTYPE_FLOAT:
case SG_UNIFORMTYPE_INT:
return 4;
case SG_UNIFORMTYPE_FLOAT2:
case SG_UNIFORMTYPE_INT2:
return 8;
case SG_UNIFORMTYPE_FLOAT3:
case SG_UNIFORMTYPE_FLOAT4:
case SG_UNIFORMTYPE_INT3:
case SG_UNIFORMTYPE_INT4:
return 16;
case SG_UNIFORMTYPE_MAT4:
return 16;
default:
SOKOL_UNREACHABLE;
return -1;
return 1;
}
}
else {
return 16;
}
}
_SOKOL_PRIVATE void* _sg_imgui_alloc(size_t size) {
SOKOL_ASSERT(size > 0);
return SOKOL_MALLOC(size);
}
_SOKOL_PRIVATE void _sg_imgui_free(void* ptr) {
if (ptr) {
SOKOL_FREE(ptr);
_SOKOL_PRIVATE uint32_t _sg_imgui_std140_uniform_size(sg_uniform_type type, int array_count) {
SOKOL_ASSERT(array_count > 0);
if (array_count == 1) {
switch (type) {
case SG_UNIFORMTYPE_FLOAT:
case SG_UNIFORMTYPE_INT:
return 4;
case SG_UNIFORMTYPE_FLOAT2:
case SG_UNIFORMTYPE_INT2:
return 8;
case SG_UNIFORMTYPE_FLOAT3:
case SG_UNIFORMTYPE_INT3:
return 12;
case SG_UNIFORMTYPE_FLOAT4:
case SG_UNIFORMTYPE_INT4:
return 16;
case SG_UNIFORMTYPE_MAT4:
return 64;
default:
SOKOL_UNREACHABLE;
return 0;
}
}
_SOKOL_PRIVATE void* _sg_imgui_realloc(void* old_ptr, size_t old_size, size_t new_size) {
SOKOL_ASSERT((new_size > 0) && (new_size > old_size));
void* new_ptr = SOKOL_MALLOC(new_size);
SOKOL_ASSERT(new_ptr);
if (old_ptr) {
if (old_size > 0) {
memcpy(new_ptr, old_ptr, old_size);
}
_sg_imgui_free(old_ptr);
else {
switch (type) {
case SG_UNIFORMTYPE_FLOAT:
case SG_UNIFORMTYPE_FLOAT2:
case SG_UNIFORMTYPE_FLOAT3:
case SG_UNIFORMTYPE_FLOAT4:
case SG_UNIFORMTYPE_INT:
case SG_UNIFORMTYPE_INT2:
case SG_UNIFORMTYPE_INT3:
case SG_UNIFORMTYPE_INT4:
return 16 * (uint32_t)array_count;
case SG_UNIFORMTYPE_MAT4:
return 64 * (uint32_t)array_count;
default:
SOKOL_UNREACHABLE;
return 0;
}
}
return new_ptr;
}
_SOKOL_PRIVATE void _sg_imgui_strcpy(sg_imgui_str_t* dst, const char* src) {
@ -840,7 +989,7 @@ _SOKOL_PRIVATE void _sg_imgui_strcpy(sg_imgui_str_t* dst, const char* src) {
dst->buf[SG_IMGUI_STRBUF_LEN-1] = 0;
}
else {
memset(dst->buf, 0, SG_IMGUI_STRBUF_LEN);
_sg_imgui_clear(dst->buf, SG_IMGUI_STRBUF_LEN);
}
}
@ -850,17 +999,17 @@ _SOKOL_PRIVATE sg_imgui_str_t _sg_imgui_make_str(const char* str) {
return res;
}
_SOKOL_PRIVATE const char* _sg_imgui_str_dup(const char* src) {
SOKOL_ASSERT(src);
_SOKOL_PRIVATE const char* _sg_imgui_str_dup(const sg_imgui_allocator_t* allocator, const char* src) {
SOKOL_ASSERT(allocator && src);
size_t len = strlen(src) + 1;
char* dst = (char*) _sg_imgui_alloc(len);
char* dst = (char*) _sg_imgui_malloc(allocator, len);
memcpy(dst, src, len);
return (const char*) dst;
}
_SOKOL_PRIVATE const void* _sg_imgui_bin_dup(const void* src, size_t num_bytes) {
SOKOL_ASSERT(src && (num_bytes > 0));
void* dst = _sg_imgui_alloc(num_bytes);
_SOKOL_PRIVATE const void* _sg_imgui_bin_dup(const sg_imgui_allocator_t* allocator, const void* src, size_t num_bytes) {
SOKOL_ASSERT(allocator && src && (num_bytes > 0));
void* dst = _sg_imgui_malloc(allocator, num_bytes);
memcpy(dst, src, num_bytes);
return (const void*) dst;
}
@ -966,6 +1115,7 @@ _SOKOL_PRIVATE const char* _sg_imgui_pixelformat_string(sg_pixel_format fmt) {
case SG_PIXELFORMAT_RG16SI: return "SG_PIXELFORMAT_RG16SI";
case SG_PIXELFORMAT_RG16F: return "SG_PIXELFORMAT_RG16F";
case SG_PIXELFORMAT_RGBA8: return "SG_PIXELFORMAT_RGBA8";
case SG_PIXELFORMAT_SRGB8A8: return "SG_PIXELFORMAT_SRGB8A8";
case SG_PIXELFORMAT_RGBA8SN: return "SG_PIXELFORMAT_RGBA8SN";
case SG_PIXELFORMAT_RGBA8UI: return "SG_PIXELFORMAT_RGBA8UI";
case SG_PIXELFORMAT_RGBA8SI: return "SG_PIXELFORMAT_RGBA8SI";
@ -1004,6 +1154,7 @@ _SOKOL_PRIVATE const char* _sg_imgui_pixelformat_string(sg_pixel_format fmt) {
case SG_PIXELFORMAT_ETC2_RGBA8: return "SG_PIXELFORMAT_ETC2_RGBA8";
case SG_PIXELFORMAT_ETC2_RG11: return "SG_PIXELFORMAT_ETC2_RG11";
case SG_PIXELFORMAT_ETC2_RG11SN: return "SG_PIXELFORMAT_ETC2_RG11SN";
case SG_PIXELFORMAT_RGB9E5: return "SG_PIXELFORMAT_RGB9E5";
default: return "???";
}
}
@ -1045,6 +1196,10 @@ _SOKOL_PRIVATE const char* _sg_imgui_uniformtype_string(sg_uniform_type t) {
case SG_UNIFORMTYPE_FLOAT2: return "SG_UNIFORMTYPE_FLOAT2";
case SG_UNIFORMTYPE_FLOAT3: return "SG_UNIFORMTYPE_FLOAT3";
case SG_UNIFORMTYPE_FLOAT4: return "SG_UNIFORMTYPE_FLOAT4";
case SG_UNIFORMTYPE_INT: return "SG_UNIFORMTYPE_INT";
case SG_UNIFORMTYPE_INT2: return "SG_UNIFORMTYPE_INT2";
case SG_UNIFORMTYPE_INT3: return "SG_UNIFORMTYPE_INT3";
case SG_UNIFORMTYPE_INT4: return "SG_UNIFORMTYPE_INT4";
case SG_UNIFORMTYPE_MAT4: return "SG_UNIFORMTYPE_MAT4";
default: return "???";
}
@ -1358,16 +1513,16 @@ _SOKOL_PRIVATE void _sg_imgui_shader_created(sg_imgui_t* ctx, sg_shader res_id,
}
}
if (shd->desc.vs.source) {
shd->desc.vs.source = _sg_imgui_str_dup(shd->desc.vs.source);
shd->desc.vs.source = _sg_imgui_str_dup(&ctx->desc.allocator, shd->desc.vs.source);
}
if (shd->desc.vs.bytecode.ptr) {
shd->desc.vs.bytecode.ptr = _sg_imgui_bin_dup(shd->desc.vs.bytecode.ptr, shd->desc.vs.bytecode.size);
shd->desc.vs.bytecode.ptr = _sg_imgui_bin_dup(&ctx->desc.allocator, shd->desc.vs.bytecode.ptr, shd->desc.vs.bytecode.size);
}
if (shd->desc.fs.source) {
shd->desc.fs.source = _sg_imgui_str_dup(shd->desc.fs.source);
shd->desc.fs.source = _sg_imgui_str_dup(&ctx->desc.allocator, shd->desc.fs.source);
}
if (shd->desc.fs.bytecode.ptr) {
shd->desc.fs.bytecode.ptr = _sg_imgui_bin_dup(shd->desc.fs.bytecode.ptr, shd->desc.fs.bytecode.size);
shd->desc.fs.bytecode.ptr = _sg_imgui_bin_dup(&ctx->desc.allocator, shd->desc.fs.bytecode.ptr, shd->desc.fs.bytecode.size);
}
for (int i = 0; i < SG_MAX_VERTEX_ATTRIBUTES; i++) {
sg_shader_attr_desc* ad = &shd->desc.attrs[i];
@ -1387,19 +1542,19 @@ _SOKOL_PRIVATE void _sg_imgui_shader_destroyed(sg_imgui_t* ctx, int slot_index)
sg_imgui_shader_t* shd = &ctx->shaders.slots[slot_index];
shd->res_id.id = SG_INVALID_ID;
if (shd->desc.vs.source) {
_sg_imgui_free((void*)shd->desc.vs.source);
_sg_imgui_free(&ctx->desc.allocator, (void*)shd->desc.vs.source);
shd->desc.vs.source = 0;
}
if (shd->desc.vs.bytecode.ptr) {
_sg_imgui_free((void*)shd->desc.vs.bytecode.ptr);
_sg_imgui_free(&ctx->desc.allocator, (void*)shd->desc.vs.bytecode.ptr);
shd->desc.vs.bytecode.ptr = 0;
}
if (shd->desc.fs.source) {
_sg_imgui_free((void*)shd->desc.fs.source);
_sg_imgui_free(&ctx->desc.allocator, (void*)shd->desc.fs.source);
shd->desc.fs.source = 0;
}
if (shd->desc.fs.bytecode.ptr) {
_sg_imgui_free((void*)shd->desc.fs.bytecode.ptr);
_sg_imgui_free(&ctx->desc.allocator, (void*)shd->desc.fs.bytecode.ptr);
shd->desc.fs.bytecode.ptr = 0;
}
}
@ -1443,8 +1598,7 @@ _SOKOL_PRIVATE void _sg_imgui_capture_init(sg_imgui_t* ctx) {
for (int i = 0; i < 2; i++) {
sg_imgui_capture_bucket_t* bucket = &ctx->capture.bucket[i];
bucket->ubuf_size = ubuf_initial_size;
bucket->ubuf = (uint8_t*) _sg_imgui_alloc(bucket->ubuf_size);
SOKOL_ASSERT(bucket->ubuf);
bucket->ubuf = (uint8_t*) _sg_imgui_malloc(&ctx->desc.allocator, bucket->ubuf_size);
}
}
@ -1452,7 +1606,7 @@ _SOKOL_PRIVATE void _sg_imgui_capture_discard(sg_imgui_t* ctx) {
for (int i = 0; i < 2; i++) {
sg_imgui_capture_bucket_t* bucket = &ctx->capture.bucket[i];
SOKOL_ASSERT(bucket->ubuf);
_sg_imgui_free(bucket->ubuf);
_sg_imgui_free(&ctx->desc.allocator, bucket->ubuf);
bucket->ubuf = 0;
}
}
@ -1478,7 +1632,7 @@ _SOKOL_PRIVATE void _sg_imgui_capture_grow_ubuf(sg_imgui_t* ctx, size_t required
size_t old_size = bucket->ubuf_size;
size_t new_size = required_size + (required_size>>1); /* allocate a bit ahead */
bucket->ubuf_size = new_size;
bucket->ubuf = (uint8_t*) _sg_imgui_realloc(bucket->ubuf, old_size, new_size);
bucket->ubuf = (uint8_t*) _sg_imgui_realloc(&ctx->desc.allocator, bucket->ubuf, old_size, new_size);
}
_SOKOL_PRIVATE sg_imgui_capture_item_t* _sg_imgui_capture_next_write_item(sg_imgui_t* ctx) {
@ -2834,15 +2988,15 @@ _SOKOL_PRIVATE void _sg_imgui_err_bindings_invalid(void* user_data) {
/*--- IMGUI HELPERS ----------------------------------------------------------*/
_SOKOL_PRIVATE bool _sg_imgui_draw_resid_list_item(uint32_t res_id, const char* label, bool selected) {
igPushIDInt((int)res_id);
igPushID_Int((int)res_id);
bool res;
if (label[0]) {
res = igSelectableBool(label, selected, 0, IMVEC2(0,0));
res = igSelectable_Bool(label, selected, 0, IMVEC2(0,0));
}
else {
sg_imgui_str_t str;
_sg_imgui_snprintf(&str, "0x%08X", res_id);
res = igSelectableBool(str.buf, selected, 0, IMVEC2(0,0));
res = igSelectable_Bool(str.buf, selected, 0, IMVEC2(0,0));
}
igPopID();
return res;
@ -2859,7 +3013,7 @@ _SOKOL_PRIVATE bool _sg_imgui_draw_resid_link(uint32_t res_type, uint32_t res_id
_sg_imgui_snprintf(&str_buf, "0x%08X", res_id);
str = str_buf.buf;
}
igPushIDInt((int)((res_type<<24)|res_id));
igPushID_Int((int)((res_type<<24)|res_id));
bool res = igSmallButton(str);
igPopID();
return res;
@ -2908,7 +3062,7 @@ _SOKOL_PRIVATE void _sg_imgui_show_shader(sg_imgui_t* ctx, sg_shader shd) {
}
_SOKOL_PRIVATE void _sg_imgui_draw_buffer_list(sg_imgui_t* ctx) {
igBeginChildStr("buffer_list", IMVEC2(_SG_IMGUI_LIST_WIDTH,0), true, 0);
igBeginChild_Str("buffer_list", IMVEC2(_SG_IMGUI_LIST_WIDTH,0), true, 0);
for (int i = 0; i < ctx->buffers.num_slots; i++) {
sg_buffer buf = ctx->buffers.slots[i].res_id;
sg_resource_state state = sg_query_buffer_state(buf);
@ -2923,7 +3077,7 @@ _SOKOL_PRIVATE void _sg_imgui_draw_buffer_list(sg_imgui_t* ctx) {
}
_SOKOL_PRIVATE void _sg_imgui_draw_image_list(sg_imgui_t* ctx) {
igBeginChildStr("image_list", IMVEC2(_SG_IMGUI_LIST_WIDTH,0), true, 0);
igBeginChild_Str("image_list", IMVEC2(_SG_IMGUI_LIST_WIDTH,0), true, 0);
for (int i = 0; i < ctx->images.num_slots; i++) {
sg_image img = ctx->images.slots[i].res_id;
sg_resource_state state = sg_query_image_state(img);
@ -2938,7 +3092,7 @@ _SOKOL_PRIVATE void _sg_imgui_draw_image_list(sg_imgui_t* ctx) {
}
_SOKOL_PRIVATE void _sg_imgui_draw_shader_list(sg_imgui_t* ctx) {
igBeginChildStr("shader_list", IMVEC2(_SG_IMGUI_LIST_WIDTH,0), true, 0);
igBeginChild_Str("shader_list", IMVEC2(_SG_IMGUI_LIST_WIDTH,0), true, 0);
for (int i = 0; i < ctx->shaders.num_slots; i++) {
sg_shader shd = ctx->shaders.slots[i].res_id;
sg_resource_state state = sg_query_shader_state(shd);
@ -2953,7 +3107,7 @@ _SOKOL_PRIVATE void _sg_imgui_draw_shader_list(sg_imgui_t* ctx) {
}
_SOKOL_PRIVATE void _sg_imgui_draw_pipeline_list(sg_imgui_t* ctx) {
igBeginChildStr("pipeline_list", IMVEC2(_SG_IMGUI_LIST_WIDTH,0), true, 0);
igBeginChild_Str("pipeline_list", IMVEC2(_SG_IMGUI_LIST_WIDTH,0), true, 0);
for (int i = 1; i < ctx->pipelines.num_slots; i++) {
sg_pipeline pip = ctx->pipelines.slots[i].res_id;
sg_resource_state state = sg_query_pipeline_state(pip);
@ -2968,7 +3122,7 @@ _SOKOL_PRIVATE void _sg_imgui_draw_pipeline_list(sg_imgui_t* ctx) {
}
_SOKOL_PRIVATE void _sg_imgui_draw_pass_list(sg_imgui_t* ctx) {
igBeginChildStr("pass_list", IMVEC2(_SG_IMGUI_LIST_WIDTH,0), true, 0);
igBeginChild_Str("pass_list", IMVEC2(_SG_IMGUI_LIST_WIDTH,0), true, 0);
for (int i = 1; i < ctx->passes.num_slots; i++) {
sg_pass pass = ctx->passes.slots[i].res_id;
sg_resource_state state = sg_query_pass_state(pass);
@ -2983,19 +3137,19 @@ _SOKOL_PRIVATE void _sg_imgui_draw_pass_list(sg_imgui_t* ctx) {
}
_SOKOL_PRIVATE void _sg_imgui_draw_capture_list(sg_imgui_t* ctx) {
igBeginChildStr("capture_list", IMVEC2(_SG_IMGUI_LIST_WIDTH,0), true, 0);
igBeginChild_Str("capture_list", IMVEC2(_SG_IMGUI_LIST_WIDTH,0), true, 0);
const int num_items = _sg_imgui_capture_num_read_items(ctx);
uint64_t group_stack = 1; /* bit set: group unfolded, cleared: folded */
for (int i = 0; i < num_items; i++) {
const sg_imgui_capture_item_t* item = _sg_imgui_capture_read_item_at(ctx, i);
sg_imgui_str_t item_string = _sg_imgui_capture_item_string(ctx, i, item);
igPushStyleColorU32(ImGuiCol_Text, item->color);
igPushIDInt(i);
igPushStyleColor_U32(ImGuiCol_Text, item->color);
igPushID_Int(i);
if (item->cmd == SG_IMGUI_CMD_PUSH_DEBUG_GROUP) {
if (group_stack & 1) {
group_stack <<= 1;
const char* group_name = item->args.push_debug_group.name.buf;
if (igTreeNodeStrStr(group_name, "Group: %s", group_name)) {
if (igTreeNode_StrStr(group_name, "Group: %s", group_name)) {
group_stack |= 1;
}
}
@ -3010,7 +3164,7 @@ _SOKOL_PRIVATE void _sg_imgui_draw_capture_list(sg_imgui_t* ctx) {
group_stack >>= 1;
}
else if (group_stack & 1) {
if (igSelectableBool(item_string.buf, ctx->capture.sel_item == i, 0, IMVEC2(0,0))) {
if (igSelectable_Bool(item_string.buf, ctx->capture.sel_item == i, 0, IMVEC2(0,0))) {
ctx->capture.sel_item = i;
}
if (igIsItemHovered(0)) {
@ -3025,7 +3179,7 @@ _SOKOL_PRIVATE void _sg_imgui_draw_capture_list(sg_imgui_t* ctx) {
_SOKOL_PRIVATE void _sg_imgui_draw_buffer_panel(sg_imgui_t* ctx, sg_buffer buf) {
if (buf.id != SG_INVALID_ID) {
igBeginChildStr("buffer", IMVEC2(0,0), false, 0);
igBeginChild_Str("buffer", IMVEC2(0,0), false, 0);
sg_buffer_info info = sg_query_buffer_info(buf);
if (info.slot.state == SG_RESOURCESTATE_VALID) {
const sg_imgui_buffer_t* buf_ui = &ctx->buffers.slots[_sg_imgui_slot_index(buf.id)];
@ -3060,7 +3214,7 @@ _SOKOL_PRIVATE void _sg_imgui_draw_embedded_image(sg_imgui_t* ctx, sg_image img,
if (sg_query_image_state(img) == SG_RESOURCESTATE_VALID) {
sg_imgui_image_t* img_ui = &ctx->images.slots[_sg_imgui_slot_index(img.id)];
if (_sg_imgui_image_renderable(img_ui->desc.type, img_ui->desc.pixel_format)) {
igPushIDInt((int)img.id);
igPushID_Int((int)img.id);
igSliderFloat("Scale", scale, 0.125f, 8.0f, "%.3f", ImGuiSliderFlags_Logarithmic);
float w = (float)img_ui->desc.width * (*scale);
float h = (float)img_ui->desc.height * (*scale);
@ -3075,7 +3229,7 @@ _SOKOL_PRIVATE void _sg_imgui_draw_embedded_image(sg_imgui_t* ctx, sg_image img,
_SOKOL_PRIVATE void _sg_imgui_draw_image_panel(sg_imgui_t* ctx, sg_image img) {
if (img.id != SG_INVALID_ID) {
igBeginChildStr("image", IMVEC2(0,0), false, 0);
igBeginChild_Str("image", IMVEC2(0,0), false, 0);
sg_image_info info = sg_query_image_info(img);
if (info.slot.state == SG_RESOURCESTATE_VALID) {
sg_imgui_image_t* img_ui = &ctx->images.slots[_sg_imgui_slot_index(img.id)];
@ -3139,14 +3293,14 @@ _SOKOL_PRIVATE void _sg_imgui_draw_shader_stage(const sg_shader_stage_desc* stag
}
}
if (num_valid_ubs > 0) {
if (igTreeNodeStr("Uniform Blocks")) {
if (igTreeNode_Str("Uniform Blocks")) {
for (int i = 0; i < num_valid_ubs; i++) {
igText("#%d:", i);
const sg_shader_uniform_block_desc* ub = &stage->uniform_blocks[i];
for (int j = 0; j < SG_MAX_UB_MEMBERS; j++) {
const sg_shader_uniform_desc* u = &ub->uniforms[j];
if (SG_UNIFORMTYPE_INVALID != u->type) {
if (u->array_count == 0) {
if (u->array_count <= 1) {
igText(" %s %s", _sg_imgui_uniformtype_string(u->type), u->name ? u->name : "");
}
else {
@ -3159,7 +3313,7 @@ _SOKOL_PRIVATE void _sg_imgui_draw_shader_stage(const sg_shader_stage_desc* stag
}
}
if (num_valid_images > 0) {
if (igTreeNodeStr("Images")) {
if (igTreeNode_Str("Images")) {
for (int i = 0; i < SG_MAX_SHADERSTAGE_IMAGES; i++) {
const sg_shader_image_desc* sid = &stage->images[i];
if (sid->image_type != _SG_IMAGETYPE_DEFAULT) {
@ -3182,13 +3336,13 @@ _SOKOL_PRIVATE void _sg_imgui_draw_shader_stage(const sg_shader_stage_desc* stag
igText("D3D11 Target: %s", stage->d3d11_target);
}
if (stage->source) {
if (igTreeNodeStr("Source")) {
if (igTreeNode_Str("Source")) {
igText("%s", stage->source);
igTreePop();
}
}
else if (stage->bytecode.ptr) {
if (igTreeNodeStr("Byte Code")) {
if (igTreeNode_Str("Byte Code")) {
igText("Byte-code display currently not supported.");
igTreePop();
}
@ -3197,14 +3351,14 @@ _SOKOL_PRIVATE void _sg_imgui_draw_shader_stage(const sg_shader_stage_desc* stag
_SOKOL_PRIVATE void _sg_imgui_draw_shader_panel(sg_imgui_t* ctx, sg_shader shd) {
if (shd.id != SG_INVALID_ID) {
igBeginChildStr("shader", IMVEC2(0,0), false, ImGuiWindowFlags_HorizontalScrollbar);
igBeginChild_Str("shader", IMVEC2(0,0), false, ImGuiWindowFlags_HorizontalScrollbar);
sg_shader_info info = sg_query_shader_info(shd);
if (info.slot.state == SG_RESOURCESTATE_VALID) {
const sg_imgui_shader_t* shd_ui = &ctx->shaders.slots[_sg_imgui_slot_index(shd.id)];
igText("Label: %s", shd_ui->label.buf[0] ? shd_ui->label.buf : "---");
_sg_imgui_draw_resource_slot(&info.slot);
igSeparator();
if (igTreeNodeStr("Attrs")) {
if (igTreeNode_Str("Attrs")) {
for (int i = 0; i < SG_MAX_VERTEX_ATTRIBUTES; i++) {
const sg_shader_attr_desc* a_desc = &shd_ui->desc.attrs[i];
if (a_desc->name || a_desc->sem_index) {
@ -3216,11 +3370,11 @@ _SOKOL_PRIVATE void _sg_imgui_draw_shader_panel(sg_imgui_t* ctx, sg_shader shd)
}
igTreePop();
}
if (igTreeNodeStr("Vertex Shader Stage")) {
if (igTreeNode_Str("Vertex Shader Stage")) {
_sg_imgui_draw_shader_stage(&shd_ui->desc.vs);
igTreePop();
}
if (igTreeNodeStr("Fragment Shader Stage")) {
if (igTreeNode_Str("Fragment Shader Stage")) {
_sg_imgui_draw_shader_stage(&shd_ui->desc.fs);
igTreePop();
}
@ -3233,7 +3387,7 @@ _SOKOL_PRIVATE void _sg_imgui_draw_shader_panel(sg_imgui_t* ctx, sg_shader shd)
}
_SOKOL_PRIVATE void _sg_imgui_draw_vertex_layout(const sg_layout_desc* layout) {
if (igTreeNodeStr("Buffers")) {
if (igTreeNode_Str("Buffers")) {
for (int i = 0; i < SG_MAX_SHADERSTAGE_BUFFERS; i++) {
const sg_buffer_layout_desc* l_desc = &layout->buffers[i];
if (l_desc->stride > 0) {
@ -3245,7 +3399,7 @@ _SOKOL_PRIVATE void _sg_imgui_draw_vertex_layout(const sg_layout_desc* layout) {
}
igTreePop();
}
if (igTreeNodeStr("Attrs")) {
if (igTreeNode_Str("Attrs")) {
for (int i = 0; i < SG_MAX_VERTEX_ATTRIBUTES; i++) {
const sg_vertex_attr_desc* a_desc = &layout->attrs[i];
if (a_desc->format != SG_VERTEXFORMAT_INVALID) {
@ -3271,11 +3425,11 @@ _SOKOL_PRIVATE void _sg_imgui_draw_stencil_state(const sg_stencil_state* ss) {
igText("Read Mask: 0x%02X", ss->read_mask);
igText("Write Mask: 0x%02X", ss->write_mask);
igText("Ref: 0x%02X", ss->ref);
if (igTreeNodeStr("Front")) {
if (igTreeNode_Str("Front")) {
_sg_imgui_draw_stencil_face_state(&ss->front);
igTreePop();
}
if (igTreeNodeStr("Back")) {
if (igTreeNode_Str("Back")) {
_sg_imgui_draw_stencil_face_state(&ss->back);
igTreePop();
}
@ -3303,7 +3457,7 @@ _SOKOL_PRIVATE void _sg_imgui_draw_blend_state(const sg_blend_state* bs) {
_SOKOL_PRIVATE void _sg_imgui_draw_color_state(const sg_color_state* cs) {
igText("Pixel Format: %s", _sg_imgui_pixelformat_string(cs->pixel_format));
igText("Write Mask: %s", _sg_imgui_colormask_string(cs->write_mask));
if (igTreeNodeStr("Blend State:")) {
if (igTreeNode_Str("Blend State:")) {
_sg_imgui_draw_blend_state(&cs->blend);
igTreePop();
}
@ -3311,7 +3465,7 @@ _SOKOL_PRIVATE void _sg_imgui_draw_color_state(const sg_color_state* cs) {
_SOKOL_PRIVATE void _sg_imgui_draw_pipeline_panel(sg_imgui_t* ctx, sg_pipeline pip) {
if (pip.id != SG_INVALID_ID) {
igBeginChildStr("pipeline", IMVEC2(0,0), false, 0);
igBeginChild_Str("pipeline", IMVEC2(0,0), false, 0);
sg_pipeline_info info = sg_query_pipeline_info(pip);
if (info.slot.state == SG_RESOURCESTATE_VALID) {
const sg_imgui_pipeline_t* pip_ui = &ctx->pipelines.slots[_sg_imgui_slot_index(pip.id)];
@ -3322,15 +3476,15 @@ _SOKOL_PRIVATE void _sg_imgui_draw_pipeline_panel(sg_imgui_t* ctx, sg_pipeline p
if (_sg_imgui_draw_shader_link(ctx, pip_ui->desc.shader)) {
_sg_imgui_show_shader(ctx, pip_ui->desc.shader);
}
if (igTreeNodeStr("Vertex Layout")) {
if (igTreeNode_Str("Vertex Layout")) {
_sg_imgui_draw_vertex_layout(&pip_ui->desc.layout);
igTreePop();
}
if (igTreeNodeStr("Depth State")) {
if (igTreeNode_Str("Depth State")) {
_sg_imgui_draw_depth_state(&pip_ui->desc.depth);
igTreePop();
}
if (igTreeNodeStr("Stencil State")) {
if (igTreeNode_Str("Stencil State")) {
_sg_imgui_draw_stencil_state(&pip_ui->desc.stencil);
igTreePop();
}
@ -3338,7 +3492,7 @@ _SOKOL_PRIVATE void _sg_imgui_draw_pipeline_panel(sg_imgui_t* ctx, sg_pipeline p
for (int i = 0; i < pip_ui->desc.color_count; i++) {
sg_imgui_str_t str;
_sg_imgui_snprintf(&str, "Color %d", i);
if (igTreeNodeStr(str.buf)) {
if (igTreeNode_Str(str.buf)) {
_sg_imgui_draw_color_state(&pip_ui->desc.colors[i]);
igTreePop();
}
@ -3371,7 +3525,7 @@ _SOKOL_PRIVATE void _sg_imgui_draw_pass_attachment(sg_imgui_t* ctx, const sg_pas
_SOKOL_PRIVATE void _sg_imgui_draw_pass_panel(sg_imgui_t* ctx, sg_pass pass) {
if (pass.id != SG_INVALID_ID) {
igBeginChildStr("pass", IMVEC2(0,0), false, 0);
igBeginChild_Str("pass", IMVEC2(0,0), false, 0);
sg_pass_info info = sg_query_pass_info(pass);
if (info.slot.state == SG_RESOURCESTATE_VALID) {
sg_imgui_pass_t* pass_ui = &ctx->passes.slots[_sg_imgui_slot_index(pass.id)];
@ -3482,7 +3636,9 @@ _SOKOL_PRIVATE void _sg_imgui_draw_uniforms_panel(sg_imgui_t* ctx, const sg_imgu
sg_imgui_capture_bucket_t* bucket = _sg_imgui_capture_get_read_bucket(ctx);
SOKOL_ASSERT((args->ubuf_pos + args->data_size) <= bucket->ubuf_size);
const float* uptrf = (const float*) (bucket->ubuf + args->ubuf_pos);
const int32_t* uptri32 = (const int32_t*) uptrf;
if (!draw_dump) {
uint32_t u_off = 0;
for (int i = 0; i < SG_MAX_UB_MEMBERS; i++) {
const sg_shader_uniform_desc* ud = &ub_desc->uniforms[i];
if (ud->type == SG_UNIFORMTYPE_INVALID) {
@ -3496,38 +3652,54 @@ _SOKOL_PRIVATE void _sg_imgui_draw_uniforms_panel(sg_imgui_t* ctx, const sg_imgu
igText("%d: %s %s =", i, _sg_imgui_uniformtype_string(ud->type), ud->name?ud->name:"");
}
for (int item_index = 0; item_index < num_items; item_index++) {
const uint32_t u_size = _sg_imgui_std140_uniform_size(ud->type, ud->array_count) / 4;
const uint32_t u_align = _sg_imgui_std140_uniform_alignment(ud->type, ud->array_count) / 4;
u_off = _sg_imgui_align_u32(u_off, u_align);
switch (ud->type) {
case SG_UNIFORMTYPE_FLOAT:
igText(" %.3f", *uptrf);
igText(" %.3f", uptrf[u_off]);
break;
case SG_UNIFORMTYPE_INT:
igText(" %d", uptri32[u_off]);
break;
case SG_UNIFORMTYPE_FLOAT2:
igText(" %.3f, %.3f", uptrf[0], uptrf[1]);
igText(" %.3f, %.3f", uptrf[u_off], uptrf[u_off+1]);
break;
case SG_UNIFORMTYPE_INT2:
igText(" %d, %d", uptri32[u_off], uptri32[u_off+1]);
break;
case SG_UNIFORMTYPE_FLOAT3:
igText(" %.3f, %.3f, %.3f", uptrf[0], uptrf[1], uptrf[2]);
igText(" %.3f, %.3f, %.3f", uptrf[u_off], uptrf[u_off+1], uptrf[u_off+2]);
break;
case SG_UNIFORMTYPE_INT3:
igText(" %d, %d, %d", uptri32[u_off], uptri32[u_off+1], uptri32[u_off+2]);
break;
case SG_UNIFORMTYPE_FLOAT4:
igText(" %.3f, %.3f, %.3f, %.3f", uptrf[0], uptrf[1], uptrf[2], uptrf[3]);
igText(" %.3f, %.3f, %.3f, %.3f", uptrf[u_off], uptrf[u_off+1], uptrf[u_off+2], uptrf[u_off+3]);
break;
case SG_UNIFORMTYPE_INT4:
igText(" %d, %d, %d, %d", uptri32[u_off], uptri32[u_off+1], uptri32[u_off+2], uptri32[u_off+3]);
break;
case SG_UNIFORMTYPE_MAT4:
igText(" %.3f, %.3f, %.3f, %.3f\n"
" %.3f, %.3f, %.3f, %.3f\n"
" %.3f, %.3f, %.3f, %.3f\n"
" %.3f, %.3f, %.3f, %.3f",
uptrf[0], uptrf[1], uptrf[2], uptrf[3],
uptrf[4], uptrf[5], uptrf[6], uptrf[7],
uptrf[8], uptrf[9], uptrf[10], uptrf[11],
uptrf[12], uptrf[13], uptrf[14], uptrf[15]);
uptrf[u_off+0], uptrf[u_off+1], uptrf[u_off+2], uptrf[u_off+3],
uptrf[u_off+4], uptrf[u_off+5], uptrf[u_off+6], uptrf[u_off+7],
uptrf[u_off+8], uptrf[u_off+9], uptrf[u_off+10], uptrf[u_off+11],
uptrf[u_off+12], uptrf[u_off+13], uptrf[u_off+14], uptrf[u_off+15]);
break;
default:
igText("???");
break;
}
uptrf += _sg_imgui_uniform_size(ud->type, 1) / (int)sizeof(float);
u_off += u_size;
}
}
}
else {
// FIXME: float vs int
const size_t num_floats = ub_desc->size / sizeof(float);
for (uint32_t i = 0; i < num_floats; i++) {
igText("%.3f, ", uptrf[i]);
@ -3589,8 +3761,8 @@ _SOKOL_PRIVATE void _sg_imgui_draw_capture_panel(sg_imgui_t* ctx) {
return;
}
sg_imgui_capture_item_t* item = _sg_imgui_capture_read_item_at(ctx, sel_item_index);
igBeginChildStr("capture_item", IMVEC2(0, 0), false, 0);
igPushStyleColorU32(ImGuiCol_Text, item->color);
igBeginChild_Str("capture_item", IMVEC2(0, 0), false, 0);
igPushStyleColor_U32(ImGuiCol_Text, item->color);
igText("%s", _sg_imgui_capture_item_string(ctx, sel_item_index, item).buf);
igPopStyleColor(1);
igSeparator();
@ -3736,6 +3908,7 @@ _SOKOL_PRIVATE void _sg_imgui_draw_caps_panel(void) {
igText(" max_image_array_layers: %d", l.max_image_array_layers);
igText(" max_vertex_attrs: %d", l.max_vertex_attrs);
igText(" gl_max_vertex_uniform_vectors: %d", l.gl_max_vertex_uniform_vectors);
igText(" gl_max_combined_texture_image_units: %d", l.gl_max_combined_texture_image_units);
igText("\nUsable Pixelformats:");
for (int i = (int)(SG_PIXELFORMAT_NONE+1); i < (int)_SG_PIXELFORMAT_NUM; i++) {
sg_pixel_format fmt = (sg_pixel_format)i;
@ -3753,16 +3926,26 @@ _SOKOL_PRIVATE void _sg_imgui_draw_caps_panel(void) {
}
}
#define _sg_imgui_def(val, def) (((val) == 0) ? (def) : (val))
_SOKOL_PRIVATE sg_imgui_desc_t _sg_imgui_desc_defaults(const sg_imgui_desc_t* desc) {
SOKOL_ASSERT((desc->allocator.alloc && desc->allocator.free) || (!desc->allocator.alloc && !desc->allocator.free));
sg_imgui_desc_t res = *desc;
// FIXME: any additional default overrides would go here
return res;
}
/*--- PUBLIC FUNCTIONS -------------------------------------------------------*/
SOKOL_API_IMPL void sg_imgui_init(sg_imgui_t* ctx) {
SOKOL_ASSERT(ctx);
memset(ctx, 0, sizeof(sg_imgui_t));
SOKOL_API_IMPL void sg_imgui_init(sg_imgui_t* ctx, const sg_imgui_desc_t* desc) {
SOKOL_ASSERT(ctx && desc);
_sg_imgui_clear(ctx, sizeof(sg_imgui_t));
ctx->init_tag = 0xABCDABCD;
ctx->desc = _sg_imgui_desc_defaults(desc);
_sg_imgui_capture_init(ctx);
/* hook into sokol_gfx functions */
sg_trace_hooks hooks;
memset(&hooks, 0, sizeof(hooks));
_sg_imgui_clear(&hooks, sizeof(hooks));
hooks.user_data = (void*) ctx;
hooks.reset_state_cache = _sg_imgui_reset_state_cache;
hooks.make_buffer = _sg_imgui_make_buffer;
@ -3827,37 +4010,27 @@ SOKOL_API_IMPL void sg_imgui_init(sg_imgui_t* ctx) {
ctx->hooks = sg_install_trace_hooks(&hooks);
/* allocate resource debug-info slots */
sg_desc desc = sg_query_desc();
ctx->buffers.num_slots = desc.buffer_pool_size;
ctx->images.num_slots = desc.image_pool_size;
ctx->shaders.num_slots = desc.shader_pool_size;
ctx->pipelines.num_slots = desc.pipeline_pool_size;
ctx->passes.num_slots = desc.pass_pool_size;
const sg_desc sgdesc = sg_query_desc();
ctx->buffers.num_slots = sgdesc.buffer_pool_size;
ctx->images.num_slots = sgdesc.image_pool_size;
ctx->shaders.num_slots = sgdesc.shader_pool_size;
ctx->pipelines.num_slots = sgdesc.pipeline_pool_size;
ctx->passes.num_slots = sgdesc.pass_pool_size;
const size_t buffer_pool_size = (size_t)ctx->buffers.num_slots * sizeof(sg_imgui_buffer_t);
ctx->buffers.slots = (sg_imgui_buffer_t*) _sg_imgui_alloc(buffer_pool_size);
SOKOL_ASSERT(ctx->buffers.slots);
memset(ctx->buffers.slots, 0, buffer_pool_size);
ctx->buffers.slots = (sg_imgui_buffer_t*) _sg_imgui_malloc_clear(&ctx->desc.allocator, buffer_pool_size);
const size_t image_pool_size = (size_t)ctx->images.num_slots * sizeof(sg_imgui_image_t);
ctx->images.slots = (sg_imgui_image_t*) _sg_imgui_alloc(image_pool_size);
SOKOL_ASSERT(ctx->images.slots);
memset(ctx->images.slots, 0, image_pool_size);
ctx->images.slots = (sg_imgui_image_t*) _sg_imgui_malloc_clear(&ctx->desc.allocator, image_pool_size);
const size_t shader_pool_size = (size_t)ctx->shaders.num_slots * sizeof(sg_imgui_shader_t);
ctx->shaders.slots = (sg_imgui_shader_t*) _sg_imgui_alloc(shader_pool_size);
SOKOL_ASSERT(ctx->shaders.slots);
memset(ctx->shaders.slots, 0, shader_pool_size);
ctx->shaders.slots = (sg_imgui_shader_t*) _sg_imgui_malloc_clear(&ctx->desc.allocator, shader_pool_size);
const size_t pipeline_pool_size = (size_t)ctx->pipelines.num_slots * sizeof(sg_imgui_pipeline_t);
ctx->pipelines.slots = (sg_imgui_pipeline_t*) _sg_imgui_alloc(pipeline_pool_size);
SOKOL_ASSERT(ctx->pipelines.slots);
memset(ctx->pipelines.slots, 0, pipeline_pool_size);
ctx->pipelines.slots = (sg_imgui_pipeline_t*) _sg_imgui_malloc_clear(&ctx->desc.allocator, pipeline_pool_size);
const size_t pass_pool_size = (size_t)ctx->passes.num_slots * sizeof(sg_imgui_pass_t);
ctx->passes.slots = (sg_imgui_pass_t*) _sg_imgui_alloc(pass_pool_size);
SOKOL_ASSERT(ctx->passes.slots);
memset(ctx->passes.slots, 0, pass_pool_size);
ctx->passes.slots = (sg_imgui_pass_t*) _sg_imgui_malloc_clear(&ctx->desc.allocator, pass_pool_size);
}
SOKOL_API_IMPL void sg_imgui_discard(sg_imgui_t* ctx) {
@ -3872,7 +4045,7 @@ SOKOL_API_IMPL void sg_imgui_discard(sg_imgui_t* ctx) {
_sg_imgui_buffer_destroyed(ctx, i);
}
}
_sg_imgui_free((void*)ctx->buffers.slots);
_sg_imgui_free(&ctx->desc.allocator, (void*)ctx->buffers.slots);
ctx->buffers.slots = 0;
}
if (ctx->images.slots) {
@ -3881,7 +4054,7 @@ SOKOL_API_IMPL void sg_imgui_discard(sg_imgui_t* ctx) {
_sg_imgui_image_destroyed(ctx, i);
}
}
_sg_imgui_free((void*)ctx->images.slots);
_sg_imgui_free(&ctx->desc.allocator, (void*)ctx->images.slots);
ctx->images.slots = 0;
}
if (ctx->shaders.slots) {
@ -3890,7 +4063,7 @@ SOKOL_API_IMPL void sg_imgui_discard(sg_imgui_t* ctx) {
_sg_imgui_shader_destroyed(ctx, i);
}
}
_sg_imgui_free((void*)ctx->shaders.slots);
_sg_imgui_free(&ctx->desc.allocator, (void*)ctx->shaders.slots);
ctx->shaders.slots = 0;
}
if (ctx->pipelines.slots) {
@ -3899,7 +4072,7 @@ SOKOL_API_IMPL void sg_imgui_discard(sg_imgui_t* ctx) {
_sg_imgui_pipeline_destroyed(ctx, i);
}
}
_sg_imgui_free((void*)ctx->pipelines.slots);
_sg_imgui_free(&ctx->desc.allocator, (void*)ctx->pipelines.slots);
ctx->pipelines.slots = 0;
}
if (ctx->passes.slots) {
@ -3908,7 +4081,7 @@ SOKOL_API_IMPL void sg_imgui_discard(sg_imgui_t* ctx) {
_sg_imgui_pass_destroyed(ctx, i);
}
}
_sg_imgui_free((void*)ctx->passes.slots);
_sg_imgui_free(&ctx->desc.allocator, (void*)ctx->passes.slots);
ctx->passes.slots = 0;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -42,8 +42,6 @@
to override defaults:
SOKOL_ASSERT(c) - your own assert macro (default: assert(c))
SOKOL_MALLOC(s) - your own malloc function (default: malloc(s))
SOKOL_FREE(p) - your own free function (default: free(p))
SOKOL_IMGUI_API_DECL- public function declaration prefix (default: extern)
SOKOL_API_DECL - same as SOKOL_IMGUI_API_DECL
SOKOL_API_IMPL - public function implementation prefix (default: -)
@ -107,20 +105,18 @@
sg_pixel_format color_format
The color pixel format of the render pass where the UI
will be rendered. The default is SG_PIXELFORMAT_RGBA8
will be rendered. The default (0) matches sokoL_gfx.h's
default pass.
sg_pixel_format depth_format
The depth-buffer pixel format of the render pass where
the UI will be rendered. The default is SG_PIXELFORMAT_DEPTHSTENCIL.
the UI will be rendered. The default (0) matches
sokol_gfx.h's default pass depth format.
int sample_count
The MSAA sample-count of the render pass where the UI
will be rendered. The default is 1.
float dpi_scale
DPI scaling factor. Set this to the result of sapp_dpi_scale().
To render in high resolution on a Retina Mac this would
typically be 2.0. The default value is 1.0
will be rendered. The default (0) matches sokol_gfx.h's
default pass sample count.
const char* ini_filename
Sets this path as ImGui::GetIO().IniFilename where ImGui will store
@ -138,19 +134,51 @@
font. In this case you need to initialize the font
yourself after simgui_setup() is called.
bool disable_paste_override
If set to true, sokol_imgui.h will not 'emulate' a Dear Imgui
clipboard paste action on SAPP_EVENTTYPE_CLIPBOARD_PASTED event.
This is mainly a hack/workaround to allow external workarounds
for making copy/paste work on the web platform. In general,
copy/paste support isn't properly fleshed out in sokol_imgui.h yet.
bool disable_set_mouse_cursor
If true, sokol_imgui.h will not control the mouse cursor type
by calling sapp_set_mouse_cursor().
bool disable_windows_resize_from_edges
If true, windows can only be resized from the bottom right corner.
The default is false, meaning windows can be resized from edges.
bool write_alpha_channel
Set this to true if you want alpha values written to the
framebuffer. By default this behavior is disabled to prevent
undesired behavior on platforms like the web where the canvas is
always alpha-blended with the background.
simgui_allocator_t allocator
Used to override memory allocation functions. See further below
for details.
--- At the start of a frame, call:
simgui_new_frame(int width, int height, double delta_time)
simgui_new_frame(&(simgui_frame_desc_t){.width = ..., .height = ..., .delta_time = ..., .dpi_scale = ...});
'width' and 'height' are the dimensions of the rendering surface,
passed to ImGui::GetIO().DisplaySize.
'delta_time' is the frame duration passed to ImGui::GetIO().DeltaTime.
For example, if you're using sokol_app.h and render to the
default framebuffer:
'dpi_scale' is the current DPI scale factor, if this is left zero-initialized,
1.0f will be used instead. Typical values for dpi_scale are >= 1.0f.
simgui_new_frame(sapp_width(), sapp_height(), delta_time);
For example, if you're using sokol_app.h and render to the default framebuffer:
simgui_new_frame(&(simgui_frame_desc_t){
.width = sapp_width(),
.height = sapp_height(),
.delta_time = sapp_frame_duration(),
.dpi_scale = sapp_dpi_scale()
});
--- at the end of the frame, before the sg_end_pass() where you
want to render the UI, call:
@ -169,10 +197,49 @@
if this is true, you might want to skip keyboard input handling
in your own event handler.
If you want to use the ImGui functions for checking if a key is pressed
(e.g. ImGui::IsKeyPressed()) the following helper function to map
an sapp_keycode to an ImGuiKey value may be useful:
int simgui_map_keycode(sapp_keycode c);
Note that simgui_map_keycode() can be called outside simgui_setup()/simgui_shutdown().
--- finally, on application shutdown, call
simgui_shutdown()
MEMORY ALLOCATION OVERRIDE
==========================
You can override the memory allocation functions at initialization time
like this:
void* my_alloc(size_t size, void* user_data) {
return malloc(size);
}
void my_free(void* ptr, void* user_data) {
free(ptr);
}
...
simgui_setup(&(simgui_desc_t){
// ...
.allocator = {
.alloc = my_alloc,
.free = my_free,
.user_data = ...;
}
});
...
If no overrides are provided, malloc and free will be used.
This only affects memory allocation calls done by sokol_imgui.h
itself though, not any allocations in Dear ImGui.
LICENSE
=======
@ -202,6 +269,7 @@
#define SOKOL_IMGUI_INCLUDED (1)
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h> // size_t
#if !defined(SOKOL_GFX_INCLUDED)
#error "Please include sokol_gfx.h before sokol_imgui.h"
@ -227,22 +295,47 @@
extern "C" {
#endif
/*
simgui_allocator_t
Used in simgui_desc_t to provide custom memory-alloc and -free functions
to sokol_imgui.h. If memory management should be overridden, both the
alloc and free function must be provided (e.g. it's not valid to
override one function but not the other).
*/
typedef struct simgui_allocator_t {
void* (*alloc)(size_t size, void* user_data);
void (*free)(void* ptr, void* user_data);
void* user_data;
} simgui_allocator_t;
typedef struct simgui_desc_t {
int max_vertices;
sg_pixel_format color_format;
sg_pixel_format depth_format;
int sample_count;
float dpi_scale;
const char* ini_filename;
bool no_default_font;
bool disable_hotkeys; /* don't let ImGui handle Ctrl-A,C,V,X,Y,Z */
bool disable_paste_override; // if true, don't send Ctrl-V on EVENTTYPE_CLIPBOARD_PASTED
bool disable_set_mouse_cursor; // if true, don't control the mouse cursor type via sapp_set_mouse_cursor()
bool disable_windows_resize_from_edges; // if true, only resize edges from the bottom right corner
bool write_alpha_channel; // if true, alpha values get written into the framebuffer
simgui_allocator_t allocator; // optional memory allocation overrides (default: malloc/free)
} simgui_desc_t;
typedef struct simgui_frame_desc_t {
int width;
int height;
double delta_time;
float dpi_scale;
} simgui_frame_desc_t;
SOKOL_IMGUI_API_DECL void simgui_setup(const simgui_desc_t* desc);
SOKOL_IMGUI_API_DECL void simgui_new_frame(int width, int height, double delta_time);
SOKOL_IMGUI_API_DECL void simgui_new_frame(const simgui_frame_desc_t* desc);
SOKOL_IMGUI_API_DECL void simgui_render(void);
#if !defined(SOKOL_IMGUI_NO_SOKOL_APP)
SOKOL_IMGUI_API_DECL bool simgui_handle_event(const sapp_event* ev);
SOKOL_IMGUI_API_DECL int simgui_map_keycode(sapp_keycode keycode); // returns ImGuiKey_*
#endif
SOKOL_IMGUI_API_DECL void simgui_shutdown(void);
@ -251,14 +344,21 @@ SOKOL_IMGUI_API_DECL void simgui_shutdown(void);
/* reference-based equivalents for C++ */
inline void simgui_setup(const simgui_desc_t& desc) { return simgui_setup(&desc); }
inline void simgui_new_frame(const simgui_frame_desc_t& desc) { return simgui_new_frame(&desc); }
#endif
#endif /* SOKOL_IMGUI_INCLUDED */
/*-- IMPLEMENTATION ----------------------------------------------------------*/
#define SOKOL_IMGUI_IMPL
#ifdef SOKOL_IMGUI_IMPL
#define SOKOL_IMGUI_IMPL_INCLUDED (1)
#if defined(SOKOL_MALLOC) || defined(SOKOL_CALLOC) || defined(SOKOL_FREE)
#error "SOKOL_MALLOC/CALLOC/FREE macros are no longer supported, please use simgui_desc_t.allocator to override memory allocation functions"
#endif
#if defined(__cplusplus)
#if !defined(IMGUI_VERSION)
#error "Please include imgui.h before the sokol_imgui.h implementation"
@ -269,8 +369,8 @@ inline void simgui_setup(const simgui_desc_t& desc) { return simgui_setup(&desc)
#endif
#endif
#include <stddef.h> /* offsetof */
#include <string.h> /* memset */
#include <string.h> // memset
#include <stdlib.h> // malloc/free
#if defined(__EMSCRIPTEN__) && !defined(SOKOL_DUMMY_BACKEND)
#include <emscripten.h>
@ -281,18 +381,13 @@ inline void simgui_setup(const simgui_desc_t& desc) { return simgui_setup(&desc)
#endif
#ifndef SOKOL_DEBUG
#ifndef NDEBUG
#define SOKOL_DEBUG (1)
#define SOKOL_DEBUG
#endif
#endif
#ifndef SOKOL_ASSERT
#include <assert.h>
#define SOKOL_ASSERT(c) assert(c)
#endif
#ifndef SOKOL_MALLOC
#include <stdlib.h>
#define SOKOL_MALLOC(s) malloc(s)
#define SOKOL_FREE(p) free(p)
#endif
#ifndef _SOKOL_PRIVATE
#if defined(__GNUC__) || defined(__clang__)
#define _SOKOL_PRIVATE __attribute__((unused)) static
@ -301,7 +396,7 @@ inline void simgui_setup(const simgui_desc_t& desc) { return simgui_setup(&desc)
#endif
#endif
/* helper macros */
/* helper macros and constants */
#define _simgui_def(val, def) (((val) == 0) ? (def) : (val))
typedef struct {
@ -309,26 +404,17 @@ typedef struct {
uint8_t _pad_8[8];
} _simgui_vs_params_t;
#define SIMGUI_MAX_KEY_VALUE (512) // same as ImGuis IO.KeysDown array
typedef struct {
simgui_desc_t desc;
float cur_dpi_scale;
sg_buffer vbuf;
sg_buffer ibuf;
sg_image img;
sg_shader shd;
sg_pipeline pip;
bool is_osx; // return true if running on OSX (or HTML5 OSX), needed for copy/paste
sg_range vertices;
sg_range indices;
#if !defined(SOKOL_IMGUI_NO_SOKOL_APP)
bool btn_down[SAPP_MAX_MOUSEBUTTONS];
bool btn_up[SAPP_MAX_MOUSEBUTTONS];
uint8_t keys_down[SIMGUI_MAX_KEY_VALUE]; // bits 0..3 or modifiers, != 0 is key-down
uint8_t keys_up[SIMGUI_MAX_KEY_VALUE]; // same is keys_down
#endif
bool is_osx; // return true if running on OSX (or HTML5 OSX), needed for copy/paste
} _simgui_state_t;
static _simgui_state_t _simgui;
@ -1605,6 +1691,33 @@ EM_JS(int, simgui_js_is_osx, (void), {
});
#endif
static void _simgui_clear(void* ptr, size_t size) {
SOKOL_ASSERT(ptr && (size > 0));
memset(ptr, 0, size);
}
static void* _simgui_malloc(size_t size) {
SOKOL_ASSERT(size > 0);
void* ptr;
if (_simgui.desc.allocator.alloc) {
ptr = _simgui.desc.allocator.alloc(size, _simgui.desc.allocator.user_data);
}
else {
ptr = malloc(size);
}
SOKOL_ASSERT(ptr);
return ptr;
}
static void _simgui_free(void* ptr) {
if (_simgui.desc.allocator.free) {
_simgui.desc.allocator.free(ptr, _simgui.desc.allocator.user_data);
}
else {
free(ptr);
}
}
static bool _simgui_is_osx(void) {
#if defined(SOKOL_DUMMY_BACKEND)
return false;
@ -1617,12 +1730,18 @@ static bool _simgui_is_osx(void) {
#endif
}
static simgui_desc_t _simgui_desc_defaults(const simgui_desc_t* desc) {
SOKOL_ASSERT((desc->allocator.alloc && desc->allocator.free) || (!desc->allocator.alloc && !desc->allocator.free));
simgui_desc_t res = *desc;
res.max_vertices = _simgui_def(res.max_vertices, 65536);
return res;
}
SOKOL_API_IMPL void simgui_setup(const simgui_desc_t* desc) {
SOKOL_ASSERT(desc);
memset(&_simgui, 0, sizeof(_simgui));
_simgui.desc = *desc;
_simgui.desc.max_vertices = _simgui_def(_simgui.desc.max_vertices, 65536);
_simgui.desc.dpi_scale = _simgui_def(_simgui.desc.dpi_scale, 1.0f);
_simgui_clear(&_simgui, sizeof(_simgui));
_simgui.desc = _simgui_desc_defaults(desc);
_simgui.cur_dpi_scale = 1.0f;
#if !defined(SOKOL_IMGUI_NO_SOKOL_APP)
_simgui.is_osx = _simgui_is_osx();
#endif
@ -1633,11 +1752,9 @@ SOKOL_API_IMPL void simgui_setup(const simgui_desc_t* desc) {
/* allocate an intermediate vertex- and index-buffer */
SOKOL_ASSERT(_simgui.desc.max_vertices > 0);
_simgui.vertices.size = (size_t)_simgui.desc.max_vertices * sizeof(ImDrawVert);
_simgui.vertices.ptr = SOKOL_MALLOC(_simgui.vertices.size);
SOKOL_ASSERT(_simgui.vertices.ptr);
_simgui.vertices.ptr = _simgui_malloc(_simgui.vertices.size);
_simgui.indices.size = (size_t)_simgui.desc.max_vertices * 3 * sizeof(ImDrawIdx);
_simgui.indices.ptr = SOKOL_MALLOC(_simgui.indices.size);
SOKOL_ASSERT(_simgui.indices.ptr);
_simgui.indices.ptr = _simgui_malloc(_simgui.indices.size);
/* initialize Dear ImGui */
#if defined(__cplusplus)
@ -1659,47 +1776,27 @@ SOKOL_API_IMPL void simgui_setup(const simgui_desc_t* desc) {
io->ConfigMacOSXBehaviors = _simgui_is_osx();
io->BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset;
#if !defined(SOKOL_IMGUI_NO_SOKOL_APP)
io->KeyMap[ImGuiKey_Tab] = SAPP_KEYCODE_TAB;
io->KeyMap[ImGuiKey_LeftArrow] = SAPP_KEYCODE_LEFT;
io->KeyMap[ImGuiKey_RightArrow] = SAPP_KEYCODE_RIGHT;
io->KeyMap[ImGuiKey_UpArrow] = SAPP_KEYCODE_UP;
io->KeyMap[ImGuiKey_DownArrow] = SAPP_KEYCODE_DOWN;
io->KeyMap[ImGuiKey_PageUp] = SAPP_KEYCODE_PAGE_UP;
io->KeyMap[ImGuiKey_PageDown] = SAPP_KEYCODE_PAGE_DOWN;
io->KeyMap[ImGuiKey_Home] = SAPP_KEYCODE_HOME;
io->KeyMap[ImGuiKey_End] = SAPP_KEYCODE_END;
io->KeyMap[ImGuiKey_Delete] = SAPP_KEYCODE_DELETE;
io->KeyMap[ImGuiKey_Backspace] = SAPP_KEYCODE_BACKSPACE;
io->KeyMap[ImGuiKey_Space] = SAPP_KEYCODE_SPACE;
io->KeyMap[ImGuiKey_Enter] = SAPP_KEYCODE_ENTER;
io->KeyMap[ImGuiKey_Escape] = SAPP_KEYCODE_ESCAPE;
if (!_simgui.desc.disable_hotkeys) {
io->KeyMap[ImGuiKey_A] = SAPP_KEYCODE_A;
io->KeyMap[ImGuiKey_C] = SAPP_KEYCODE_C;
io->KeyMap[ImGuiKey_V] = SAPP_KEYCODE_V;
io->KeyMap[ImGuiKey_X] = SAPP_KEYCODE_X;
io->KeyMap[ImGuiKey_Y] = SAPP_KEYCODE_Y;
io->KeyMap[ImGuiKey_Z] = SAPP_KEYCODE_Z;
if (!_simgui.desc.disable_set_mouse_cursor) {
io->BackendFlags |= ImGuiBackendFlags_HasMouseCursors;
}
#if !defined(SOKOL_IMGUI_NO_SOKOL_APP)
io->SetClipboardTextFn = _simgui_set_clipboard;
io->GetClipboardTextFn = _simgui_get_clipboard;
#endif
#endif
io->ConfigWindowsResizeFromEdges = !_simgui.desc.disable_windows_resize_from_edges;
/* create sokol-gfx resources */
sg_push_debug_group("sokol-imgui");
/* NOTE: since we're in C++ mode here we can't use C99 designated init */
sg_buffer_desc vb_desc;
memset(&vb_desc, 0, sizeof(vb_desc));
_simgui_clear(&vb_desc, sizeof(vb_desc));
vb_desc.usage = SG_USAGE_STREAM;
vb_desc.size = _simgui.vertices.size;
vb_desc.label = "sokol-imgui-vertices";
_simgui.vbuf = sg_make_buffer(&vb_desc);
sg_buffer_desc ib_desc;
memset(&ib_desc, 0, sizeof(ib_desc));
_simgui_clear(&ib_desc, sizeof(ib_desc));
ib_desc.type = SG_BUFFERTYPE_INDEXBUFFER;
ib_desc.usage = SG_USAGE_STREAM;
ib_desc.size = _simgui.indices.size;
@ -1717,7 +1814,7 @@ SOKOL_API_IMPL void simgui_setup(const simgui_desc_t* desc) {
ImFontAtlas_GetTexDataAsRGBA32(io->Fonts, &font_pixels, &font_width, &font_height, &bytes_per_pixel);
#endif
sg_image_desc img_desc;
memset(&img_desc, 0, sizeof(img_desc));
_simgui_clear(&img_desc, sizeof(img_desc));
img_desc.width = font_width;
img_desc.height = font_height;
img_desc.pixel_format = SG_PIXELFORMAT_RGBA8;
@ -1734,7 +1831,7 @@ SOKOL_API_IMPL void simgui_setup(const simgui_desc_t* desc) {
/* shader object for using the embedded shader source (or bytecode) */
sg_shader_desc shd_desc;
memset(&shd_desc, 0, sizeof(shd_desc));
_simgui_clear(&shd_desc, sizeof(shd_desc));
shd_desc.attrs[0].name = "position";
shd_desc.attrs[1].name = "texcoord0";
shd_desc.attrs[2].name = "color0";
@ -1790,7 +1887,7 @@ SOKOL_API_IMPL void simgui_setup(const simgui_desc_t* desc) {
/* pipeline object for imgui rendering */
sg_pipeline_desc pip_desc;
memset(&pip_desc, 0, sizeof(pip_desc));
_simgui_clear(&pip_desc, sizeof(pip_desc));
pip_desc.layout.buffers[0].stride = sizeof(ImDrawVert);
{
sg_vertex_attr_desc* attr = &pip_desc.layout.attrs[0];
@ -1812,10 +1909,14 @@ SOKOL_API_IMPL void simgui_setup(const simgui_desc_t* desc) {
pip_desc.sample_count = _simgui.desc.sample_count;
pip_desc.depth.pixel_format = _simgui.desc.depth_format;
pip_desc.colors[0].pixel_format = _simgui.desc.color_format;
pip_desc.colors[0].write_mask = SG_COLORMASK_RGB;
pip_desc.colors[0].write_mask = _simgui.desc.write_alpha_channel ? SG_COLORMASK_RGBA : SG_COLORMASK_RGB;
pip_desc.colors[0].blend.enabled = true;
pip_desc.colors[0].blend.src_factor_rgb = SG_BLENDFACTOR_SRC_ALPHA;
pip_desc.colors[0].blend.dst_factor_rgb = SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA;
if (_simgui.desc.write_alpha_channel) {
pip_desc.colors[0].blend.src_factor_alpha = SG_BLENDFACTOR_ONE;
pip_desc.colors[0].blend.dst_factor_alpha = SG_BLENDFACTOR_ONE;
}
pip_desc.label = "sokol-imgui-pipeline";
_simgui.pip = sg_make_pipeline(&pip_desc);
@ -1837,58 +1938,52 @@ SOKOL_API_IMPL void simgui_shutdown(void) {
sg_destroy_buffer(_simgui.vbuf);
sg_pop_debug_group();
SOKOL_ASSERT(_simgui.vertices.ptr);
SOKOL_FREE((void*)_simgui.vertices.ptr);
_simgui_free((void*)_simgui.vertices.ptr);
SOKOL_ASSERT(_simgui.indices.ptr);
SOKOL_FREE((void*)_simgui.indices.ptr);
_simgui_free((void*)_simgui.indices.ptr);
}
#if !defined(SOKOL_IMGUI_NO_SOKOL_APP)
_SOKOL_PRIVATE void _simgui_set_imgui_modifiers(ImGuiIO* io, uint32_t mods) {
io->KeyAlt = (mods & SAPP_MODIFIER_ALT) != 0;
io->KeyCtrl = (mods & SAPP_MODIFIER_CTRL) != 0;
io->KeyShift = (mods & SAPP_MODIFIER_SHIFT) != 0;
io->KeySuper = (mods & SAPP_MODIFIER_SUPER) != 0;
}
#endif
SOKOL_API_IMPL void simgui_new_frame(int width, int height, double delta_time) {
SOKOL_API_IMPL void simgui_new_frame(const simgui_frame_desc_t* desc) {
SOKOL_ASSERT(desc);
SOKOL_ASSERT(desc->width > 0);
SOKOL_ASSERT(desc->height > 0);
_simgui.cur_dpi_scale = _simgui_def(desc->dpi_scale, 1.0f);
#if defined(__cplusplus)
ImGuiIO* io = &ImGui::GetIO();
#else
ImGuiIO* io = igGetIO();
#endif
io->DisplaySize.x = ((float) width) / _simgui.desc.dpi_scale;
io->DisplaySize.y = ((float) height) / _simgui.desc.dpi_scale;
io->DeltaTime = (float) delta_time;
io->DisplaySize.x = ((float)desc->width) / _simgui.cur_dpi_scale;
io->DisplaySize.y = ((float)desc->height) / _simgui.cur_dpi_scale;
io->DeltaTime = (float)desc->delta_time;
#if !defined(SOKOL_IMGUI_NO_SOKOL_APP)
for (int i = 0; i < SAPP_MAX_MOUSEBUTTONS; i++) {
if (_simgui.btn_down[i]) {
_simgui.btn_down[i] = false;
io->MouseDown[i] = true;
}
else if (_simgui.btn_up[i]) {
_simgui.btn_up[i] = false;
io->MouseDown[i] = false;
}
}
for (int i = 0; i < SIMGUI_MAX_KEY_VALUE; i++) {
if (_simgui.keys_down[i]) {
io->KeysDown[i] = true;
_simgui_set_imgui_modifiers(io, _simgui.keys_down[i]);
_simgui.keys_down[i] = 0;
}
else if (_simgui.keys_up[i]) {
io->KeysDown[i] = false;
_simgui_set_imgui_modifiers(io, _simgui.keys_up[i]);
_simgui.keys_up[i] = 0;
}
}
if (io->WantTextInput && !sapp_keyboard_shown()) {
sapp_show_keyboard(true);
}
if (!io->WantTextInput && sapp_keyboard_shown()) {
sapp_show_keyboard(false);
}
if (!_simgui.desc.disable_set_mouse_cursor) {
#if defined(__cplusplus)
ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
#else
ImGuiMouseCursor imgui_cursor = igGetMouseCursor();
#endif
sapp_mouse_cursor cursor = sapp_get_mouse_cursor();
switch (imgui_cursor) {
case ImGuiMouseCursor_Arrow: cursor = SAPP_MOUSECURSOR_ARROW; break;
case ImGuiMouseCursor_TextInput: cursor = SAPP_MOUSECURSOR_IBEAM; break;
case ImGuiMouseCursor_ResizeAll: cursor = SAPP_MOUSECURSOR_RESIZE_ALL; break;
case ImGuiMouseCursor_ResizeNS: cursor = SAPP_MOUSECURSOR_RESIZE_NS; break;
case ImGuiMouseCursor_ResizeEW: cursor = SAPP_MOUSECURSOR_RESIZE_EW; break;
case ImGuiMouseCursor_ResizeNESW: cursor = SAPP_MOUSECURSOR_RESIZE_NESW; break;
case ImGuiMouseCursor_ResizeNWSE: cursor = SAPP_MOUSECURSOR_RESIZE_NWSE; break;
case ImGuiMouseCursor_Hand: cursor = SAPP_MOUSECURSOR_POINTING_HAND; break;
case ImGuiMouseCursor_NotAllowed: cursor = SAPP_MOUSECURSOR_NOT_ALLOWED; break;
default: break;
}
sapp_set_mouse_cursor(cursor);
}
#endif
#if defined(__cplusplus)
ImGui::NewFrame();
@ -1966,7 +2061,7 @@ SOKOL_API_IMPL void simgui_render(void) {
}
/* render the ImGui command list */
const float dpi_scale = _simgui.desc.dpi_scale;
const float dpi_scale = _simgui.cur_dpi_scale;
const int fb_width = (int) (io->DisplaySize.x * dpi_scale);
const int fb_height = (int) (io->DisplaySize.y * dpi_scale);
sg_apply_viewport(0, 0, fb_width, fb_height, true);
@ -1974,12 +2069,12 @@ SOKOL_API_IMPL void simgui_render(void) {
sg_apply_pipeline(_simgui.pip);
_simgui_vs_params_t vs_params;
memset((void*)&vs_params, 0, sizeof(vs_params));
_simgui_clear((void*)&vs_params, sizeof(vs_params));
vs_params.disp_size.x = io->DisplaySize.x;
vs_params.disp_size.y = io->DisplaySize.y;
sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(vs_params));
sg_bindings bind;
memset((void*)&bind, 0, sizeof(bind));
_simgui_clear((void*)&bind, sizeof(bind));
bind.vertex_buffers[0] = _simgui.vbuf;
bind.index_buffer = _simgui.ibuf;
ImTextureID tex_id = io->Fonts->TexID;
@ -1993,7 +2088,6 @@ SOKOL_API_IMPL void simgui_render(void) {
bind.index_buffer_offset = ib_offset;
sg_apply_bindings(&bind);
int base_element = 0;
#if defined(__cplusplus)
const int num_cmds = cl->CmdBuffer.size();
#else
@ -2023,13 +2117,12 @@ SOKOL_API_IMPL void simgui_render(void) {
const int scissor_w = (int) ((pcmd->ClipRect.z - pcmd->ClipRect.x) * dpi_scale);
const int scissor_h = (int) ((pcmd->ClipRect.w - pcmd->ClipRect.y) * dpi_scale);
sg_apply_scissor_rect(scissor_x, scissor_y, scissor_w, scissor_h, true);
sg_draw(base_element, (int)pcmd->ElemCount, 1);
sg_draw((int)pcmd->IdxOffset, (int)pcmd->ElemCount, 1);
}
base_element += (int)pcmd->ElemCount;
}
#if defined(__cplusplus)
const size_t vtx_size = cl->VtxBuffer.size() * sizeof(ImDrawVert);
const size_t idx_size = cl->IdxBuffer.size() * sizeof(ImDrawIdx);
const size_t vtx_size = (size_t)cl->VtxBuffer.size() * sizeof(ImDrawVert);
const size_t idx_size = (size_t)cl->IdxBuffer.size() * sizeof(ImDrawIdx);
#else
const size_t vtx_size = (size_t)cl->VtxBuffer.Size * sizeof(ImDrawVert);
const size_t idx_size = (size_t)cl->IdxBuffer.Size * sizeof(ImDrawIdx);
@ -2052,67 +2145,257 @@ _SOKOL_PRIVATE bool _simgui_is_ctrl(uint32_t modifiers) {
}
}
_SOKOL_PRIVATE ImGuiKey _simgui_map_keycode(sapp_keycode key) {
switch (key) {
case SAPP_KEYCODE_SPACE: return ImGuiKey_Space;
case SAPP_KEYCODE_APOSTROPHE: return ImGuiKey_Apostrophe;
case SAPP_KEYCODE_COMMA: return ImGuiKey_Comma;
case SAPP_KEYCODE_MINUS: return ImGuiKey_Minus;
case SAPP_KEYCODE_PERIOD: return ImGuiKey_Apostrophe;
case SAPP_KEYCODE_SLASH: return ImGuiKey_Slash;
case SAPP_KEYCODE_0: return ImGuiKey_0;
case SAPP_KEYCODE_1: return ImGuiKey_1;
case SAPP_KEYCODE_2: return ImGuiKey_2;
case SAPP_KEYCODE_3: return ImGuiKey_3;
case SAPP_KEYCODE_4: return ImGuiKey_4;
case SAPP_KEYCODE_5: return ImGuiKey_5;
case SAPP_KEYCODE_6: return ImGuiKey_6;
case SAPP_KEYCODE_7: return ImGuiKey_7;
case SAPP_KEYCODE_8: return ImGuiKey_8;
case SAPP_KEYCODE_9: return ImGuiKey_9;
case SAPP_KEYCODE_SEMICOLON: return ImGuiKey_Semicolon;
case SAPP_KEYCODE_EQUAL: return ImGuiKey_Equal;
case SAPP_KEYCODE_A: return ImGuiKey_A;
case SAPP_KEYCODE_B: return ImGuiKey_B;
case SAPP_KEYCODE_C: return ImGuiKey_C;
case SAPP_KEYCODE_D: return ImGuiKey_D;
case SAPP_KEYCODE_E: return ImGuiKey_E;
case SAPP_KEYCODE_F: return ImGuiKey_F;
case SAPP_KEYCODE_G: return ImGuiKey_G;
case SAPP_KEYCODE_H: return ImGuiKey_H;
case SAPP_KEYCODE_I: return ImGuiKey_I;
case SAPP_KEYCODE_J: return ImGuiKey_J;
case SAPP_KEYCODE_K: return ImGuiKey_K;
case SAPP_KEYCODE_L: return ImGuiKey_L;
case SAPP_KEYCODE_M: return ImGuiKey_M;
case SAPP_KEYCODE_N: return ImGuiKey_N;
case SAPP_KEYCODE_O: return ImGuiKey_O;
case SAPP_KEYCODE_P: return ImGuiKey_P;
case SAPP_KEYCODE_Q: return ImGuiKey_Q;
case SAPP_KEYCODE_R: return ImGuiKey_R;
case SAPP_KEYCODE_S: return ImGuiKey_S;
case SAPP_KEYCODE_T: return ImGuiKey_T;
case SAPP_KEYCODE_U: return ImGuiKey_U;
case SAPP_KEYCODE_V: return ImGuiKey_V;
case SAPP_KEYCODE_W: return ImGuiKey_W;
case SAPP_KEYCODE_X: return ImGuiKey_X;
case SAPP_KEYCODE_Y: return ImGuiKey_Y;
case SAPP_KEYCODE_Z: return ImGuiKey_Z;
case SAPP_KEYCODE_LEFT_BRACKET: return ImGuiKey_LeftBracket;
case SAPP_KEYCODE_BACKSLASH: return ImGuiKey_Backslash;
case SAPP_KEYCODE_RIGHT_BRACKET:return ImGuiKey_RightBracket;
case SAPP_KEYCODE_GRAVE_ACCENT: return ImGuiKey_GraveAccent;
case SAPP_KEYCODE_ESCAPE: return ImGuiKey_Escape;
case SAPP_KEYCODE_ENTER: return ImGuiKey_Enter;
case SAPP_KEYCODE_TAB: return ImGuiKey_Tab;
case SAPP_KEYCODE_BACKSPACE: return ImGuiKey_Backspace;
case SAPP_KEYCODE_INSERT: return ImGuiKey_Insert;
case SAPP_KEYCODE_DELETE: return ImGuiKey_Delete;
case SAPP_KEYCODE_RIGHT: return ImGuiKey_RightArrow;
case SAPP_KEYCODE_LEFT: return ImGuiKey_LeftArrow;
case SAPP_KEYCODE_DOWN: return ImGuiKey_DownArrow;
case SAPP_KEYCODE_UP: return ImGuiKey_UpArrow;
case SAPP_KEYCODE_PAGE_UP: return ImGuiKey_PageUp;
case SAPP_KEYCODE_PAGE_DOWN: return ImGuiKey_PageDown;
case SAPP_KEYCODE_HOME: return ImGuiKey_Home;
case SAPP_KEYCODE_END: return ImGuiKey_End;
case SAPP_KEYCODE_CAPS_LOCK: return ImGuiKey_CapsLock;
case SAPP_KEYCODE_SCROLL_LOCK: return ImGuiKey_ScrollLock;
case SAPP_KEYCODE_NUM_LOCK: return ImGuiKey_NumLock;
case SAPP_KEYCODE_PRINT_SCREEN: return ImGuiKey_PrintScreen;
case SAPP_KEYCODE_PAUSE: return ImGuiKey_Pause;
case SAPP_KEYCODE_F1: return ImGuiKey_F1;
case SAPP_KEYCODE_F2: return ImGuiKey_F2;
case SAPP_KEYCODE_F3: return ImGuiKey_F3;
case SAPP_KEYCODE_F4: return ImGuiKey_F4;
case SAPP_KEYCODE_F5: return ImGuiKey_F5;
case SAPP_KEYCODE_F6: return ImGuiKey_F6;
case SAPP_KEYCODE_F7: return ImGuiKey_F7;
case SAPP_KEYCODE_F8: return ImGuiKey_F8;
case SAPP_KEYCODE_F9: return ImGuiKey_F9;
case SAPP_KEYCODE_F10: return ImGuiKey_F10;
case SAPP_KEYCODE_F11: return ImGuiKey_F11;
case SAPP_KEYCODE_F12: return ImGuiKey_F12;
case SAPP_KEYCODE_KP_0: return ImGuiKey_Keypad0;
case SAPP_KEYCODE_KP_1: return ImGuiKey_Keypad1;
case SAPP_KEYCODE_KP_2: return ImGuiKey_Keypad2;
case SAPP_KEYCODE_KP_3: return ImGuiKey_Keypad3;
case SAPP_KEYCODE_KP_4: return ImGuiKey_Keypad4;
case SAPP_KEYCODE_KP_5: return ImGuiKey_Keypad5;
case SAPP_KEYCODE_KP_6: return ImGuiKey_Keypad6;
case SAPP_KEYCODE_KP_7: return ImGuiKey_Keypad7;
case SAPP_KEYCODE_KP_8: return ImGuiKey_Keypad8;
case SAPP_KEYCODE_KP_9: return ImGuiKey_Keypad9;
case SAPP_KEYCODE_KP_DECIMAL: return ImGuiKey_KeypadDecimal;
case SAPP_KEYCODE_KP_DIVIDE: return ImGuiKey_KeypadDivide;
case SAPP_KEYCODE_KP_MULTIPLY: return ImGuiKey_KeypadMultiply;
case SAPP_KEYCODE_KP_SUBTRACT: return ImGuiKey_KeypadSubtract;
case SAPP_KEYCODE_KP_ADD: return ImGuiKey_KeypadAdd;
case SAPP_KEYCODE_KP_ENTER: return ImGuiKey_KeypadEnter;
case SAPP_KEYCODE_KP_EQUAL: return ImGuiKey_KeypadEqual;
case SAPP_KEYCODE_LEFT_SHIFT: return ImGuiKey_LeftShift;
case SAPP_KEYCODE_LEFT_CONTROL: return ImGuiKey_LeftCtrl;
case SAPP_KEYCODE_LEFT_ALT: return ImGuiKey_LeftAlt;
case SAPP_KEYCODE_LEFT_SUPER: return ImGuiKey_LeftSuper;
case SAPP_KEYCODE_RIGHT_SHIFT: return ImGuiKey_RightShift;
case SAPP_KEYCODE_RIGHT_CONTROL:return ImGuiKey_RightCtrl;
case SAPP_KEYCODE_RIGHT_ALT: return ImGuiKey_RightAlt;
case SAPP_KEYCODE_RIGHT_SUPER: return ImGuiKey_RightSuper;
case SAPP_KEYCODE_MENU: return ImGuiKey_Menu;
default: return ImGuiKey_None;
}
}
_SOKOL_PRIVATE void _simgui_add_focus_event(ImGuiIO* io, bool focus) {
#if defined(__cplusplus)
io->AddFocusEvent(focus);
#else
ImGuiIO_AddFocusEvent(io, focus);
#endif
}
_SOKOL_PRIVATE void _simgui_add_mouse_pos_event(ImGuiIO* io, float x, float y) {
#if defined(__cplusplus)
io->AddMousePosEvent(x, y);
#else
ImGuiIO_AddMousePosEvent(io, x, y);
#endif
}
_SOKOL_PRIVATE void _simgui_add_mouse_button_event(ImGuiIO* io, int mouse_button, bool down) {
#if defined(__cplusplus)
io->AddMouseButtonEvent(mouse_button, down);
#else
ImGuiIO_AddMouseButtonEvent(io, mouse_button, down);
#endif
}
_SOKOL_PRIVATE void _simgui_add_mouse_wheel_event(ImGuiIO* io, float wheel_x, float wheel_y) {
#if defined(__cplusplus)
io->AddMouseWheelEvent(wheel_x, wheel_y);
#else
ImGuiIO_AddMouseWheelEvent(io, wheel_x, wheel_y);
#endif
}
_SOKOL_PRIVATE void _simgui_add_sapp_key_event(ImGuiIO* io, sapp_keycode sapp_key, bool down) {
const ImGuiKey imgui_key = _simgui_map_keycode(sapp_key);
#if defined(__cplusplus)
io->AddKeyEvent(imgui_key, down);
io->SetKeyEventNativeData(imgui_key, (int)sapp_key, 0, -1);
#else
ImGuiIO_AddKeyEvent(io, imgui_key, down);
ImGuiIO_SetKeyEventNativeData(io, imgui_key, (int)sapp_key, 0, -1);
#endif
}
_SOKOL_PRIVATE void _simgui_add_imgui_key_event(ImGuiIO* io, ImGuiKey imgui_key, bool down) {
#if defined(__cplusplus)
io->AddKeyEvent(imgui_key, down);
#else
ImGuiIO_AddKeyEvent(io, imgui_key, down);
#endif
}
_SOKOL_PRIVATE void _simgui_add_input_character(ImGuiIO* io, uint32_t c) {
#if defined(__cplusplus)
io->AddInputCharacter(c);
#else
ImGuiIO_AddInputCharacter(io, c);
#endif
}
_SOKOL_PRIVATE void _simgui_update_modifiers(ImGuiIO* io, uint32_t mods) {
_simgui_add_imgui_key_event(io, ImGuiMod_Ctrl, (mods & SAPP_MODIFIER_CTRL) != 0);
_simgui_add_imgui_key_event(io, ImGuiMod_Shift, (mods & SAPP_MODIFIER_SHIFT) != 0);
_simgui_add_imgui_key_event(io, ImGuiMod_Alt, (mods & SAPP_MODIFIER_ALT) != 0);
_simgui_add_imgui_key_event(io, ImGuiMod_Super, (mods & SAPP_MODIFIER_SUPER) != 0);
}
// returns Ctrl or Super, depending on platform
_SOKOL_PRIVATE ImGuiKey _simgui_copypaste_modifier(void) {
return _simgui.is_osx ? ImGuiMod_Super : ImGuiMod_Ctrl;
}
SOKOL_API_IMPL int simgui_map_keycode(sapp_keycode keycode) {
return (int)_simgui_map_keycode(keycode);
}
SOKOL_API_IMPL bool simgui_handle_event(const sapp_event* ev) {
const float dpi_scale = _simgui.desc.dpi_scale;
const float dpi_scale = _simgui.cur_dpi_scale;
#if defined(__cplusplus)
ImGuiIO* io = &ImGui::GetIO();
#else
ImGuiIO* io = igGetIO();
#endif
_simgui_set_imgui_modifiers(io, ev->modifiers);
switch (ev->type) {
case SAPP_EVENTTYPE_FOCUSED:
_simgui_add_focus_event(io, true);
break;
case SAPP_EVENTTYPE_UNFOCUSED:
_simgui_add_focus_event(io, false);
break;
case SAPP_EVENTTYPE_MOUSE_DOWN:
io->MousePos.x = ev->mouse_x / dpi_scale;
io->MousePos.y = ev->mouse_y / dpi_scale;
if (ev->mouse_button < 3) {
_simgui.btn_down[ev->mouse_button] = true;
}
_simgui_add_mouse_pos_event(io, ev->mouse_x / dpi_scale, ev->mouse_y / dpi_scale);
_simgui_add_mouse_button_event(io, (int)ev->mouse_button, true);
_simgui_update_modifiers(io, ev->modifiers);
break;
case SAPP_EVENTTYPE_MOUSE_UP:
io->MousePos.x = ev->mouse_x / dpi_scale;
io->MousePos.y = ev->mouse_y / dpi_scale;
if (ev->mouse_button < 3) {
_simgui.btn_up[ev->mouse_button] = true;
}
_simgui_add_mouse_pos_event(io, ev->mouse_x / dpi_scale, ev->mouse_y / dpi_scale);
_simgui_add_mouse_button_event(io, (int)ev->mouse_button, false);
_simgui_update_modifiers(io, ev->modifiers);
break;
case SAPP_EVENTTYPE_MOUSE_MOVE:
io->MousePos.x = ev->mouse_x / dpi_scale;
io->MousePos.y = ev->mouse_y / dpi_scale;
_simgui_add_mouse_pos_event(io, ev->mouse_x / dpi_scale, ev->mouse_y / dpi_scale);
break;
case SAPP_EVENTTYPE_MOUSE_ENTER:
case SAPP_EVENTTYPE_MOUSE_LEAVE:
for (int i = 0; i < 3; i++) {
_simgui.btn_down[i] = false;
_simgui.btn_up[i] = false;
io->MouseDown[i] = false;
// FIXME: since the sokol_app.h emscripten backend doesn't support
// mouse capture, mouse buttons must be released when the mouse leaves the
// browser window, so that they don't "stick" when released outside the window.
// A cleaner solution would be a new sokol_app.h function to query
// "platform behaviour flags".
#if defined(__EMSCRIPTEN__)
for (int i = 0; i < SAPP_MAX_MOUSEBUTTONS; i++) {
_simgui_add_mouse_button_event(io, i, false);
}
#endif
break;
case SAPP_EVENTTYPE_MOUSE_SCROLL:
io->MouseWheelH = ev->scroll_x;
io->MouseWheel = ev->scroll_y;
_simgui_add_mouse_wheel_event(io, ev->scroll_x, ev->scroll_y);
break;
case SAPP_EVENTTYPE_TOUCHES_BEGAN:
_simgui.btn_down[0] = true;
io->MousePos.x = ev->touches[0].pos_x / dpi_scale;
io->MousePos.y = ev->touches[0].pos_y / dpi_scale;
_simgui_add_mouse_pos_event(io, ev->touches[0].pos_x / dpi_scale, ev->touches[0].pos_y / dpi_scale);
_simgui_add_mouse_button_event(io, 0, true);
break;
case SAPP_EVENTTYPE_TOUCHES_MOVED:
io->MousePos.x = ev->touches[0].pos_x / dpi_scale;
io->MousePos.y = ev->touches[0].pos_y / dpi_scale;
_simgui_add_mouse_pos_event(io, ev->touches[0].pos_x / dpi_scale, ev->touches[0].pos_y / dpi_scale);
break;
case SAPP_EVENTTYPE_TOUCHES_ENDED:
_simgui.btn_up[0] = true;
io->MousePos.x = ev->touches[0].pos_x / dpi_scale;
io->MousePos.y = ev->touches[0].pos_y / dpi_scale;
_simgui_add_mouse_pos_event(io, ev->touches[0].pos_x / dpi_scale, ev->touches[0].pos_y / dpi_scale);
_simgui_add_mouse_button_event(io, 0, false);
break;
case SAPP_EVENTTYPE_TOUCHES_CANCELLED:
_simgui.btn_up[0] = _simgui.btn_down[0] = false;
_simgui_add_mouse_button_event(io, 0, false);
break;
case SAPP_EVENTTYPE_KEY_DOWN:
_simgui_update_modifiers(io, ev->modifiers);
/* intercept Ctrl-V, this is handled via EVENTTYPE_CLIPBOARD_PASTED */
if (!_simgui.desc.disable_paste_override) {
if (_simgui_is_ctrl(ev->modifiers) && (ev->key_code == SAPP_KEYCODE_V)) {
break;
}
}
/* on web platform, don't forward Ctrl-X, Ctrl-V to the browser */
if (_simgui_is_ctrl(ev->modifiers) && (ev->key_code == SAPP_KEYCODE_X)) {
sapp_consume_event();
@ -2120,9 +2403,11 @@ SOKOL_API_IMPL bool simgui_handle_event(const sapp_event* ev) {
if (_simgui_is_ctrl(ev->modifiers) && (ev->key_code == SAPP_KEYCODE_C)) {
sapp_consume_event();
}
_simgui.keys_down[ev->key_code] = 0x80 | (uint8_t)ev->modifiers;
// it's ok to add ImGuiKey_None key events
_simgui_add_sapp_key_event(io, ev->key_code, true);
break;
case SAPP_EVENTTYPE_KEY_UP:
_simgui_update_modifiers(io, ev->modifiers);
/* intercept Ctrl-V, this is handled via EVENTTYPE_CLIPBOARD_PASTED */
if (_simgui_is_ctrl(ev->modifiers) && (ev->key_code == SAPP_KEYCODE_V)) {
break;
@ -2134,7 +2419,8 @@ SOKOL_API_IMPL bool simgui_handle_event(const sapp_event* ev) {
if (_simgui_is_ctrl(ev->modifiers) && (ev->key_code == SAPP_KEYCODE_C)) {
sapp_consume_event();
}
_simgui.keys_up[ev->key_code] = 0x80 | (uint8_t)ev->modifiers;
// it's ok to add ImGuiKey_None key events
_simgui_add_sapp_key_event(io, ev->key_code, false);
break;
case SAPP_EVENTTYPE_CHAR:
/* on some platforms, special keys may be reported as
@ -2142,27 +2428,28 @@ SOKOL_API_IMPL bool simgui_handle_event(const sapp_event* ev) {
drop those, also don't forward characters if some
modifiers have been pressed
*/
_simgui_update_modifiers(io, ev->modifiers);
if ((ev->char_code >= 32) &&
(ev->char_code != 127) &&
(0 == (ev->modifiers & (SAPP_MODIFIER_ALT|SAPP_MODIFIER_CTRL|SAPP_MODIFIER_SUPER))))
{
#if defined(__cplusplus)
io->AddInputCharacter((ImWchar)ev->char_code);
#else
ImGuiIO_AddInputCharacter(io, (ImWchar)ev->char_code);
#endif
_simgui_add_input_character(io, ev->char_code);
}
break;
case SAPP_EVENTTYPE_CLIPBOARD_PASTED:
/* simulate a Ctrl-V key down/up */
_simgui.keys_down[SAPP_KEYCODE_V] = _simgui.keys_up[SAPP_KEYCODE_V] =
(uint8_t) (0x80 | (_simgui.is_osx ? SAPP_MODIFIER_SUPER:SAPP_MODIFIER_CTRL));
if (!_simgui.desc.disable_paste_override) {
_simgui_add_imgui_key_event(io, _simgui_copypaste_modifier(), true);
_simgui_add_imgui_key_event(io, ImGuiKey_V, true);
_simgui_add_imgui_key_event(io, ImGuiKey_V, false);
_simgui_add_imgui_key_event(io, _simgui_copypaste_modifier(), false);
}
break;
default:
break;
}
return io->WantCaptureKeyboard || io->WantCaptureMouse;
}
#endif
#endif // SOKOL_IMGUI_NO_SOKOL_APP
#endif /* SOKOL_IMPL */
#endif // SOKOL_IMPL

View File

@ -8,15 +8,6 @@
Project URL: https://github.com/floooh/sokol
Simply include this file before the sokol header implementation includes
and after the SOKOL_IMPL macro:
#define SOKOL_IMPL
#include "sokol_memtrack.h"
#include "sokol_app.h"
#include "sokol_gfx.h"
...
Optionally provide the following defines with your own implementations:
SOKOL_MEMTRACK_API_DECL - public function declaration prefix (default: extern)
@ -28,24 +19,29 @@
SOKOL_DLL
The sokol_memtrack.h header will redirect the macros SOKOL_MALLOC,
SOKOL_FREE and SOKOL_CALLOC to use its own function wrappers which
keep track of number and size of allocations. The wrapper functions
then call the CRT functions malloc(), calloc() or free().
USAGE
=====
Just plug the malloc/free wrapper functions into the desc.allocator
struct provided by most sokol header setup functions:
Naturally, only the memory management calls in sokol header code are tracked,
not in underlying APIs such as D3D11 or OpenGL.
sg_setup(&(sg_desc){
//...
.allocator = {
.alloc = smemtrack_alloc,
.free = smemtrack_free,
}
});
To get the current number and overall size of allocations, call:
Then call smemtrack_info() to get information about current number
of allocations and overall allocation size:
smemtrack_info_t alloc_info = smemtrack_info();
const smemtrack_info_t info = smemtrack_info();
const int num_allocs = info.num_allocs;
const int num_bytes = info.num_bytes;
int num_allocations = info.num_alloc;
int allocation_size = info.num_bytes;
The allocation wrapper functions are *not* thread-safe (which shouldn't
be a problem because the sokol headers don't allocate or deallocate
in threads).
Note the sokol_memtrack.h can only track allocations issued by
the sokol headers, not allocations that happen under the hood
in system libraries.
LICENSE
=======
@ -75,6 +71,7 @@
*/
#define SOKOL_MEMTRACK_INCLUDED (1)
#include <stdint.h>
#include <stddef.h> // size_t
#if defined(SOKOL_API_DECL) && !defined(SOKOL_MEMTRACK_API_DECL)
#define SOKOL_MEMTRACK_API_DECL SOKOL_API_DECL
@ -99,6 +96,8 @@ typedef struct smemtrack_info_t {
} smemtrack_info_t;
SOKOL_MEMTRACK_API_DECL smemtrack_info_t smemtrack_info(void);
SOKOL_MEMTRACK_API_DECL void* smemtrack_alloc(size_t size, void* user_data);
SOKOL_MEMTRACK_API_DECL void smemtrack_free(void* ptr, void* user_data);
#ifdef __cplusplus
} /* extern "C" */
@ -108,16 +107,15 @@ SOKOL_MEMTRACK_API_DECL smemtrack_info_t smemtrack_info(void);
/*=== IMPLEMENTATION =========================================================*/
#ifdef SOKOL_MEMTRACK_IMPL
#define SOKOL_MEMTRACK_IMPL_INCLUDED (1)
#include <stdlib.h> /* malloc, free, calloc */
#include <string.h> /* memset */
#include <stddef.h> /* size_t */
#include <stdlib.h> // malloc, free
#include <string.h> // memset
#ifndef SOKOL_API_IMPL
#define SOKOL_API_IMPL
#endif
#ifndef SOKOL_DEBUG
#ifndef NDEBUG
#define SOKOL_DEBUG (1)
#define SOKOL_DEBUG
#endif
#endif
#ifndef _SOKOL_PRIVATE
@ -128,40 +126,38 @@ SOKOL_MEMTRACK_API_DECL smemtrack_info_t smemtrack_info(void);
#endif
#endif
#define SOKOL_MALLOC(s) _smemtrack_malloc(s)
#define SOKOL_FREE(p) _smemtrack_free(p)
#define SOKOL_CALLOC(n,s) _smemtrack_calloc(n,s)
// per-allocation header used to keep track of the allocation size
#define _SMEMTRACK_HEADER_SIZE (16)
static struct {
smemtrack_info_t state;
} _smemtrack;
_SOKOL_PRIVATE void* _smemtrack_malloc(size_t size) {
SOKOL_API_IMPL void* smemtrack_alloc(size_t size, void* user_data) {
(void)user_data;
uint8_t* ptr = (uint8_t*) malloc(size + _SMEMTRACK_HEADER_SIZE);
if (ptr) {
// store allocation size (for allocation size tracking)
*(size_t*)ptr = size;
_smemtrack.state.num_allocs++;
_smemtrack.state.num_bytes += (int) size;
uint8_t* ptr = (uint8_t*) malloc(size + _SMEMTRACK_HEADER_SIZE);
*(size_t*)ptr = size;
return ptr + _SMEMTRACK_HEADER_SIZE;
}
else {
// allocation failed, return null pointer
return ptr;
}
}
_SOKOL_PRIVATE void _smemtrack_free(void* ptr) {
SOKOL_API_IMPL void smemtrack_free(void* ptr, void* user_data) {
(void)user_data;
if (ptr) {
uint8_t* alloc_ptr = ((uint8_t*)ptr) - _SMEMTRACK_HEADER_SIZE;
size_t size = *(size_t*)alloc_ptr;
_smemtrack.state.num_allocs--;
_smemtrack.state.num_bytes -= (int) size;
free(alloc_ptr);
}
_SOKOL_PRIVATE void* _smemtrack_calloc(size_t num, size_t size) {
size_t mem_size = num * size;
_smemtrack.state.num_allocs++;
_smemtrack.state.num_bytes += (int) mem_size;
uint8_t* ptr = (uint8_t*) malloc(mem_size + _SMEMTRACK_HEADER_SIZE);
memset(ptr + _SMEMTRACK_HEADER_SIZE, 0, mem_size);
*(size_t*)ptr = size;
return ptr + _SMEMTRACK_HEADER_SIZE;
}
}
SOKOL_API_IMPL smemtrack_info_t smemtrack_info(void) {

View File

@ -267,7 +267,7 @@ inline void snk_setup(const snk_desc_t& desc) { return snk_setup(&desc); }
#endif
#ifndef SOKOL_DEBUG
#ifndef NDEBUG
#define SOKOL_DEBUG (1)
#define SOKOL_DEBUG
#endif
#endif
#ifndef SOKOL_ASSERT
@ -1941,8 +1941,15 @@ SOKOL_API_IMPL void snk_render(int width, int height) {
int idx_offset = 0;
nk_draw_foreach(cmd, &_snuklear.ctx, &cmds) {
if (cmd->elem_count > 0) {
sg_image img;
if (cmd->texture.id != 0) {
img = (sg_image){ .id = (uint32_t) cmd->texture.id };
}
else {
img = _snuklear.img;
}
sg_apply_bindings(&(sg_bindings){
.fs_images[0] = _snuklear.img,
.fs_images[0] = img,
.vertex_buffers[0] = _snuklear.vbuf,
.index_buffer = _snuklear.ibuf,
.vertex_buffer_offsets[0] = 0,

View File

@ -556,7 +556,6 @@ SOKOL_SHAPE_API_DECL sshape_mat4_t sshape_mat4_transpose(const float m[16]);
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
#pragma clang diagnostic ignored "-Wmissing-braces"
#endif
#ifndef SOKOL_API_IMPL
@ -857,7 +856,7 @@ SOKOL_API_IMPL sshape_mat4_t sshape_mat4_transpose(const float m[16]) {
SOKOL_API_IMPL sshape_sizes_t sshape_plane_sizes(uint32_t tiles) {
SOKOL_ASSERT(tiles >= 1);
sshape_sizes_t res = { 0 };
sshape_sizes_t res = { {0} };
res.vertices.num = _sshape_plane_num_vertices(tiles);
res.indices.num = _sshape_plane_num_indices(tiles);
res.vertices.size = res.vertices.num * sizeof(sshape_vertex_t);
@ -867,7 +866,7 @@ SOKOL_API_IMPL sshape_sizes_t sshape_plane_sizes(uint32_t tiles) {
SOKOL_API_IMPL sshape_sizes_t sshape_box_sizes(uint32_t tiles) {
SOKOL_ASSERT(tiles >= 1);
sshape_sizes_t res = { 0 };
sshape_sizes_t res = { {0} };
res.vertices.num = _sshape_box_num_vertices(tiles);
res.indices.num = _sshape_box_num_indices(tiles);
res.vertices.size = res.vertices.num * sizeof(sshape_vertex_t);
@ -877,7 +876,7 @@ SOKOL_API_IMPL sshape_sizes_t sshape_box_sizes(uint32_t tiles) {
SOKOL_API_IMPL sshape_sizes_t sshape_sphere_sizes(uint32_t slices, uint32_t stacks) {
SOKOL_ASSERT((slices >= 3) && (stacks >= 2));
sshape_sizes_t res = { 0 };
sshape_sizes_t res = { {0} };
res.vertices.num = _sshape_sphere_num_vertices(slices, stacks);
res.indices.num = _sshape_sphere_num_indices(slices, stacks);
res.vertices.size = res.vertices.num * sizeof(sshape_vertex_t);
@ -887,7 +886,7 @@ SOKOL_API_IMPL sshape_sizes_t sshape_sphere_sizes(uint32_t slices, uint32_t stac
SOKOL_API_IMPL sshape_sizes_t sshape_cylinder_sizes(uint32_t slices, uint32_t stacks) {
SOKOL_ASSERT((slices >= 3) && (stacks >= 1));
sshape_sizes_t res = { 0 };
sshape_sizes_t res = { {0} };
res.vertices.num = _sshape_cylinder_num_vertices(slices, stacks);
res.indices.num = _sshape_cylinder_num_indices(slices, stacks);
res.vertices.size = res.vertices.num * sizeof(sshape_vertex_t);
@ -897,7 +896,7 @@ SOKOL_API_IMPL sshape_sizes_t sshape_cylinder_sizes(uint32_t slices, uint32_t st
SOKOL_API_IMPL sshape_sizes_t sshape_torus_sizes(uint32_t sides, uint32_t rings) {
SOKOL_ASSERT((sides >= 3) && (rings >= 3));
sshape_sizes_t res = { 0 };
sshape_sizes_t res = { {0} };
res.vertices.num = _sshape_torus_num_vertices(sides, rings);
res.indices.num = _sshape_torus_num_indices(sides, rings);
res.vertices.size = res.vertices.num * sizeof(sshape_vertex_t);