blob: 534b1586cb155c4ae5bfeb113385414cbe95d21e [file]
#ifndef _RIVE_WRITE_ATTRIBUTION_HPP_
#define _RIVE_WRITE_ATTRIBUTION_HPP_
#ifdef WITH_RIVE_TOOLS
#include <cstddef>
#include <cstdint>
#include <vector>
struct lua_State;
namespace rive
{
class DataBind;
class StateMachineInstance;
class StateMachineLayer;
class StateMachineListener;
class WasmScriptingVM;
// What is writing view model values right now, innermost last, so a debugger
// stopped on a change can say where it came from. Tools only, and recorded
// only while a debugger has enabled it.
struct WriteSource
{
enum class Kind : uint8_t
{
luau,
wasm,
layer,
listener,
dataBind,
};
Kind kind;
// lua_State, WasmScriptingVM, StateMachineLayer,
// StateMachineListener or DataBind, by kind.
const void* object;
const StateMachineInstance* machine;
};
class WriteAttribution
{
public:
static bool enabled() { return s_enabled; }
static void enable(bool enabled) { s_enabled = enabled; }
static const std::vector<WriteSource>& sources() { return s_sources; }
// At a frame boundary, where no scope is open.
static void reset() { s_sources.clear(); }
private:
friend class WriteAttributionScope;
static bool s_enabled;
static thread_local std::vector<WriteSource> s_sources;
};
class WriteAttributionScope
{
public:
WriteAttributionScope(
WriteSource::Kind kind,
const void* object,
const StateMachineInstance* machine = nullptr)
: m_pushed(WriteAttribution::s_enabled)
, m_depth(WriteAttribution::s_sources.size())
{
if (m_pushed)
{
WriteAttribution::s_sources.push_back({kind, object, machine});
}
}
// Back to this scope's depth rather than one pop: a Luau error longjmps
// past the destructors of the scopes inside it.
~WriteAttributionScope()
{
if (m_pushed)
{
WriteAttribution::s_sources.resize(m_depth);
}
}
WriteAttributionScope(const WriteAttributionScope&) = delete;
WriteAttributionScope& operator=(const WriteAttributionScope&) = delete;
private:
bool m_pushed;
size_t m_depth;
};
} // namespace rive
#define RIVE_WRITE_SOURCE_CAT2(a, b) a##b
#define RIVE_WRITE_SOURCE_CAT(a, b) RIVE_WRITE_SOURCE_CAT2(a, b)
#define RIVE_WRITE_SOURCE(kind, ...) \
rive::WriteAttributionScope RIVE_WRITE_SOURCE_CAT( \
riveWriteSource, \
__LINE__)(rive::WriteSource::Kind::kind, __VA_ARGS__)
#else
#define RIVE_WRITE_SOURCE(kind, ...)
#endif
#endif