Updated sokol to latest git commit 1d48f3a.
parent
2e631b4fc3
commit
eb70c06c57
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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){
|
||||
|
|
|
@ -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
|
@ -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
|
@ -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
|
|
@ -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
|
@ -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) {
|
||||
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;
|
||||
default:
|
||||
SOKOL_UNREACHABLE;
|
||||
return -1;
|
||||
}
|
||||
_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 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 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);
|
||||
_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_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;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return 16;
|
||||
}
|
||||
}
|
||||
|
||||
_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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
_sg_imgui_free(old_ptr);
|
||||
}
|
||||
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
|
@ -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;
|
||||
if (io->WantTextInput && !sapp_keyboard_shown()) {
|
||||
sapp_show_keyboard(true);
|
||||
}
|
||||
else if (_simgui.btn_up[i]) {
|
||||
_simgui.btn_up[i] = false;
|
||||
io->MouseDown[i] = false;
|
||||
if (!io->WantTextInput && sapp_keyboard_shown()) {
|
||||
sapp_show_keyboard(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;
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
#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,66 +2145,256 @@ _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_is_ctrl(ev->modifiers) && (ev->key_code == SAPP_KEYCODE_V)) {
|
||||
break;
|
||||
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)) {
|
||||
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
_smemtrack.state.num_allocs++;
|
||||
_smemtrack.state.num_bytes += (int) 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);
|
||||
*(size_t*)ptr = size;
|
||||
return ptr + _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;
|
||||
return ptr + _SMEMTRACK_HEADER_SIZE;
|
||||
}
|
||||
else {
|
||||
// allocation failed, return null pointer
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _smemtrack_free(void* 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 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_API_IMPL smemtrack_info_t smemtrack_info(void) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue