Add Chromium-only Blender WebEngine parity work
This commit is contained in:
@@ -0,0 +1,239 @@
|
||||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup wm
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "CLG_log.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BLI_ghash.h"
|
||||
|
||||
#include "WM_types.hh"
|
||||
|
||||
#include "message_bus/intern/wm_message_bus_intern.hh"
|
||||
#include "message_bus/wm_message_bus.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/** \name Public API
|
||||
* \{ */
|
||||
|
||||
static wmMsgTypeInfo wm_msg_types[WM_MSG_TYPE_NUM] = {{{nullptr}}};
|
||||
|
||||
using wmMsgTypeInitFn = void (*)(wmMsgTypeInfo *);
|
||||
|
||||
static wmMsgTypeInitFn wm_msg_init_fn[WM_MSG_TYPE_NUM] = {
|
||||
WM_msgtypeinfo_init_rna,
|
||||
WM_msgtypeinfo_init_static,
|
||||
WM_msgtypeinfo_init_remote_io,
|
||||
};
|
||||
|
||||
void WM_msgbus_types_init()
|
||||
{
|
||||
for (uint i = 0; i < WM_MSG_TYPE_NUM; i++) {
|
||||
wm_msg_init_fn[i](&wm_msg_types[i]);
|
||||
}
|
||||
}
|
||||
|
||||
wmMsgBus *WM_msgbus_create()
|
||||
{
|
||||
wmMsgBus *mbus = MEM_new_zeroed<wmMsgBus>(__func__);
|
||||
const uint gset_reserve = 512;
|
||||
for (uint i = 0; i < WM_MSG_TYPE_NUM; i++) {
|
||||
wmMsgTypeInfo *info = &wm_msg_types[i];
|
||||
mbus->messages_gset[i] = BLI_gset_new_ex(
|
||||
info->gset.hash_fn, info->gset.cmp_fn, __func__, gset_reserve);
|
||||
}
|
||||
return mbus;
|
||||
}
|
||||
|
||||
void WM_msgbus_destroy(wmMsgBus *mbus)
|
||||
{
|
||||
for (uint i = 0; i < WM_MSG_TYPE_NUM; i++) {
|
||||
wmMsgTypeInfo *info = &wm_msg_types[i];
|
||||
BLI_gset_free(mbus->messages_gset[i], info->gset.key_free_fn);
|
||||
}
|
||||
MEM_delete(mbus);
|
||||
}
|
||||
|
||||
void WM_msgbus_clear_by_owner(wmMsgBus *mbus, void *owner)
|
||||
{
|
||||
wmMsgSubscribeKey *msg_key, *msg_key_next;
|
||||
for (msg_key = static_cast<wmMsgSubscribeKey *>(mbus->messages.first); msg_key;
|
||||
msg_key = msg_key_next)
|
||||
{
|
||||
msg_key_next = msg_key->next;
|
||||
|
||||
wmMsgSubscribeValueLink *msg_lnk_next;
|
||||
for (wmMsgSubscribeValueLink *msg_lnk =
|
||||
static_cast<wmMsgSubscribeValueLink *>(msg_key->values.first);
|
||||
msg_lnk;
|
||||
msg_lnk = msg_lnk_next)
|
||||
{
|
||||
msg_lnk_next = msg_lnk->next;
|
||||
if (msg_lnk->params.owner == owner) {
|
||||
if (msg_lnk->params.tag) {
|
||||
mbus->messages_tag_count -= 1;
|
||||
}
|
||||
if (msg_lnk->params.free_data) {
|
||||
msg_lnk->params.free_data(msg_key, &msg_lnk->params);
|
||||
}
|
||||
BLI_remlink(&msg_key->values, msg_lnk);
|
||||
MEM_delete(msg_lnk);
|
||||
}
|
||||
}
|
||||
|
||||
if (msg_key->values.is_empty()) {
|
||||
const wmMsg *msg = wm_msg_subscribe_value_msg_cast(msg_key);
|
||||
wmMsgTypeInfo *info = &wm_msg_types[msg->type];
|
||||
BLI_remlink(&mbus->messages, msg_key);
|
||||
bool ok = BLI_gset_remove(mbus->messages_gset[msg->type], msg_key, info->gset.key_free_fn);
|
||||
BLI_assert(ok);
|
||||
UNUSED_VARS_NDEBUG(ok);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WM_msg_dump(wmMsgBus *mbus, const char *info_str)
|
||||
{
|
||||
printf(">>>> %s\n", info_str);
|
||||
for (wmMsgSubscribeKey &key : mbus->messages) {
|
||||
const wmMsg *msg = wm_msg_subscribe_value_msg_cast(&key);
|
||||
const wmMsgTypeInfo *info = &wm_msg_types[msg->type];
|
||||
info->repr(stdout, &key);
|
||||
}
|
||||
printf("<<<< %s\n", info_str);
|
||||
}
|
||||
|
||||
void WM_msgbus_handle(wmMsgBus *mbus, bContext *C)
|
||||
{
|
||||
if (mbus->messages_tag_count == 0) {
|
||||
// printf("msgbus: skipping\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (false) {
|
||||
WM_msg_dump(mbus, __func__);
|
||||
}
|
||||
|
||||
// uint a = 0, b = 0;
|
||||
for (wmMsgSubscribeKey &key : mbus->messages) {
|
||||
for (wmMsgSubscribeValueLink &msg_lnk : key.values) {
|
||||
if (msg_lnk.params.tag) {
|
||||
msg_lnk.params.notify(C, &key, &msg_lnk.params);
|
||||
msg_lnk.params.tag = false;
|
||||
mbus->messages_tag_count -= 1;
|
||||
}
|
||||
// b++;
|
||||
}
|
||||
// a++;
|
||||
}
|
||||
BLI_assert(mbus->messages_tag_count == 0);
|
||||
mbus->messages_tag_count = 0;
|
||||
// printf("msgbus: keys=%u values=%u\n", a, b);
|
||||
}
|
||||
|
||||
wmMsgSubscribeKey *WM_msg_subscribe_with_key(wmMsgBus *mbus,
|
||||
const wmMsgSubscribeKey *msg_key_test,
|
||||
const wmMsgSubscribeValue *msg_val_params)
|
||||
{
|
||||
const uint type = wm_msg_subscribe_value_msg_cast(msg_key_test)->type;
|
||||
const wmMsgTypeInfo *info = &wm_msg_types[type];
|
||||
wmMsgSubscribeKey *key;
|
||||
|
||||
BLI_assert(wm_msg_subscribe_value_msg_cast(msg_key_test)->id != nullptr);
|
||||
|
||||
void **r_key;
|
||||
if (!BLI_gset_ensure_p_ex(mbus->messages_gset[type], msg_key_test, &r_key)) {
|
||||
*r_key = info->gset.key_duplicate_fn(msg_key_test);
|
||||
key = static_cast<wmMsgSubscribeKey *>(*r_key);
|
||||
BLI_addtail(&mbus->messages, key);
|
||||
}
|
||||
else {
|
||||
key = static_cast<wmMsgSubscribeKey *>(*r_key);
|
||||
for (wmMsgSubscribeValueLink &msg_lnk : key->values) {
|
||||
if ((msg_lnk.params.notify == msg_val_params->notify) &&
|
||||
(msg_lnk.params.owner == msg_val_params->owner) &&
|
||||
(msg_lnk.params.user_data == msg_val_params->user_data))
|
||||
{
|
||||
return key;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wmMsgSubscribeValueLink *msg_lnk = MEM_new_uninitialized<wmMsgSubscribeValueLink>(__func__);
|
||||
msg_lnk->params = *msg_val_params;
|
||||
BLI_addtail(&key->values, msg_lnk);
|
||||
return key;
|
||||
}
|
||||
|
||||
void WM_msg_publish_with_key(wmMsgBus *mbus, wmMsgSubscribeKey *msg_key)
|
||||
{
|
||||
CLOG_DEBUG(WM_LOG_MSGBUS_SUB,
|
||||
"tagging subscribers: (ptr=%p, len=%d)",
|
||||
msg_key,
|
||||
msg_key->values.count());
|
||||
|
||||
for (wmMsgSubscribeValueLink &msg_lnk : msg_key->values) {
|
||||
if (false) { /* Make an option? */
|
||||
msg_lnk.params.notify(nullptr, msg_key, &msg_lnk.params);
|
||||
}
|
||||
else {
|
||||
if (msg_lnk.params.tag == false) {
|
||||
msg_lnk.params.tag = true;
|
||||
mbus->messages_tag_count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WM_msg_id_update(wmMsgBus *mbus, ID *id_src, ID *id_dst)
|
||||
{
|
||||
for (uint i = 0; i < WM_MSG_TYPE_NUM; i++) {
|
||||
wmMsgTypeInfo *info = &wm_msg_types[i];
|
||||
if (info->update_by_id != nullptr) {
|
||||
info->update_by_id(mbus, id_src, id_dst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WM_msg_id_remove(wmMsgBus *mbus, const ID *id)
|
||||
{
|
||||
for (uint i = 0; i < WM_MSG_TYPE_NUM; i++) {
|
||||
wmMsgTypeInfo *info = &wm_msg_types[i];
|
||||
if (info->remove_by_id != nullptr) {
|
||||
info->remove_by_id(mbus, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/** \name Internal API
|
||||
*
|
||||
* \note While we could have a separate type for ID's, use RNA since there is enough overlap.
|
||||
* \{ */
|
||||
|
||||
void wm_msg_subscribe_value_free(wmMsgSubscribeKey *msg_key, wmMsgSubscribeValueLink *msg_lnk)
|
||||
{
|
||||
if (msg_lnk->params.free_data) {
|
||||
msg_lnk->params.free_data(msg_key, &msg_lnk->params);
|
||||
}
|
||||
BLI_remlink(&msg_key->values, msg_lnk);
|
||||
MEM_delete(msg_lnk);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,45 @@
|
||||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup wm
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../wm_message_bus.hh"
|
||||
|
||||
struct GSet;
|
||||
|
||||
namespace blender {
|
||||
|
||||
struct wmMsgBus {
|
||||
GSet *messages_gset[WM_MSG_TYPE_NUM];
|
||||
/** Messages in order of being added. */
|
||||
ListBaseT<wmMsgSubscribeKey> messages;
|
||||
/** Avoid checking messages when no tags exist. */
|
||||
uint messages_tag_count;
|
||||
};
|
||||
|
||||
/**
|
||||
* \note #wmMsgBus.messages_tag_count isn't updated, caller must handle.
|
||||
*/
|
||||
void wm_msg_subscribe_value_free(wmMsgSubscribeKey *msg_key, wmMsgSubscribeValueLink *msg_lnk);
|
||||
|
||||
struct wmMsgSubscribeKey_Generic {
|
||||
wmMsgSubscribeKey head;
|
||||
wmMsg msg;
|
||||
};
|
||||
|
||||
BLI_INLINE const wmMsg *wm_msg_subscribe_value_msg_cast(const wmMsgSubscribeKey *key)
|
||||
{
|
||||
return &(reinterpret_cast<wmMsgSubscribeKey_Generic *>(const_cast<wmMsgSubscribeKey *>(key)))
|
||||
->msg;
|
||||
}
|
||||
BLI_INLINE wmMsg *wm_msg_subscribe_value_msg_cast_mut(wmMsgSubscribeKey *key)
|
||||
{
|
||||
return &(reinterpret_cast<wmMsgSubscribeKey_Generic *>(key))->msg;
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,149 @@
|
||||
/* SPDX-FileCopyrightText: 2025 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup wm
|
||||
*/
|
||||
|
||||
#include "CLG_log.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_hash.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_string_ref.hh"
|
||||
|
||||
#include "WM_types.hh"
|
||||
#include "message_bus/intern/wm_message_bus_intern.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static uint wm_msg_remote_io_gset_hash(const void *key_p)
|
||||
{
|
||||
const wmMsgSubscribeKey_RemoteIO *key = static_cast<const wmMsgSubscribeKey_RemoteIO *>(key_p);
|
||||
const wmMsgParams_RemoteIO *params = &key->msg.params;
|
||||
uint k = BLI_hash_string(params->remote_url);
|
||||
return k;
|
||||
}
|
||||
static bool wm_msg_remote_io_gset_cmp(const void *key_a_p, const void *key_b_p)
|
||||
{
|
||||
const wmMsgParams_RemoteIO *params_a =
|
||||
&(static_cast<const wmMsgSubscribeKey_RemoteIO *>(key_a_p))->msg.params;
|
||||
const wmMsgParams_RemoteIO *params_b =
|
||||
&(static_cast<const wmMsgSubscribeKey_RemoteIO *>(key_b_p))->msg.params;
|
||||
return !STREQ(params_a->remote_url, params_b->remote_url);
|
||||
}
|
||||
|
||||
static void *wm_msg_remote_io_gset_key_duplicate(const void *key_p)
|
||||
{
|
||||
const wmMsgSubscribeKey_RemoteIO *key_src = static_cast<const wmMsgSubscribeKey_RemoteIO *>(
|
||||
key_p);
|
||||
wmMsgSubscribeKey_RemoteIO *key = MEM_new<wmMsgSubscribeKey_RemoteIO>(__func__, *key_src);
|
||||
key->msg.params.remote_url = BLI_strdup(key_src->msg.params.remote_url);
|
||||
return key;
|
||||
}
|
||||
static void wm_msg_remote_io_gset_key_free(void *key_p)
|
||||
{
|
||||
wmMsgSubscribeKey_RemoteIO *key = static_cast<wmMsgSubscribeKey_RemoteIO *>(key_p);
|
||||
MEM_delete(key->msg.params.remote_url);
|
||||
wmMsgSubscribeValueLink *msg_lnk_next;
|
||||
for (wmMsgSubscribeValueLink *msg_lnk =
|
||||
static_cast<wmMsgSubscribeValueLink *>(key->head.values.first);
|
||||
msg_lnk;
|
||||
msg_lnk = msg_lnk_next)
|
||||
{
|
||||
msg_lnk_next = msg_lnk->next;
|
||||
BLI_remlink(&key->head.values, msg_lnk);
|
||||
MEM_delete(msg_lnk);
|
||||
}
|
||||
MEM_delete(key);
|
||||
}
|
||||
|
||||
static void wm_msg_remote_io_repr(FILE *stream, const wmMsgSubscribeKey *msg_key)
|
||||
{
|
||||
const wmMsgSubscribeKey_RemoteIO *m = reinterpret_cast<wmMsgSubscribeKey_RemoteIO *>(
|
||||
const_cast<wmMsgSubscribeKey *>(msg_key));
|
||||
fprintf(stream,
|
||||
"<wmMsg_RemoteIO %p, "
|
||||
"id='%s', "
|
||||
"values_len=%d\n",
|
||||
m,
|
||||
m->msg.head.id,
|
||||
m->head.values.count());
|
||||
}
|
||||
|
||||
void WM_msgtypeinfo_init_remote_io(wmMsgTypeInfo *msgtype_info)
|
||||
{
|
||||
msgtype_info->gset.hash_fn = wm_msg_remote_io_gset_hash;
|
||||
msgtype_info->gset.cmp_fn = wm_msg_remote_io_gset_cmp;
|
||||
msgtype_info->gset.key_duplicate_fn = wm_msg_remote_io_gset_key_duplicate;
|
||||
msgtype_info->gset.key_free_fn = wm_msg_remote_io_gset_key_free;
|
||||
msgtype_info->repr = wm_msg_remote_io_repr;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
wmMsgSubscribeKey_RemoteIO *WM_msg_lookup_remote_io(wmMsgBus *mbus,
|
||||
const wmMsgParams_RemoteIO *msg_key_params)
|
||||
{
|
||||
wmMsgSubscribeKey_RemoteIO key_test;
|
||||
key_test.msg.params = *msg_key_params;
|
||||
return static_cast<wmMsgSubscribeKey_RemoteIO *>(
|
||||
BLI_gset_lookup(mbus->messages_gset[WM_MSG_TYPE_REMOTE_IO], &key_test));
|
||||
}
|
||||
|
||||
void WM_msg_publish_remote_io_params(wmMsgBus *mbus, const wmMsgParams_RemoteIO *msg_key_params)
|
||||
{
|
||||
CLOG_DEBUG(WM_LOG_MSGBUS_PUB, "remote_io(remote_url=%s)", msg_key_params->remote_url);
|
||||
|
||||
wmMsgSubscribeKey_RemoteIO *key = WM_msg_lookup_remote_io(mbus, msg_key_params);
|
||||
if (key) {
|
||||
WM_msg_publish_with_key(mbus, &key->head);
|
||||
}
|
||||
}
|
||||
|
||||
void WM_msg_publish_remote_io(wmMsgBus *mbus, const StringRef remote_url)
|
||||
{
|
||||
wmMsgParams_RemoteIO params{};
|
||||
params.remote_url = BLI_strdupn(remote_url.data(), remote_url.size());
|
||||
WM_msg_publish_remote_io_params(mbus, ¶ms);
|
||||
|
||||
/* Value was copied into the publish key. */
|
||||
MEM_delete(params.remote_url);
|
||||
}
|
||||
|
||||
void WM_msg_subscribe_remote_io_params(wmMsgBus *mbus,
|
||||
const wmMsgParams_RemoteIO *msg_key_params,
|
||||
const wmMsgSubscribeValue *msg_val_params,
|
||||
const char *id_repr)
|
||||
{
|
||||
wmMsgSubscribeKey_RemoteIO msg_key_test{};
|
||||
|
||||
/* Use when added. */
|
||||
msg_key_test.msg.head.id = id_repr;
|
||||
msg_key_test.msg.head.type = WM_MSG_TYPE_REMOTE_IO;
|
||||
/* For lookup. */
|
||||
msg_key_test.msg.params = *msg_key_params;
|
||||
|
||||
WM_msg_subscribe_with_key(mbus, &msg_key_test.head, msg_val_params);
|
||||
}
|
||||
|
||||
void WM_msg_subscribe_remote_io(wmMsgBus *mbus,
|
||||
const StringRef remote_url,
|
||||
const wmMsgSubscribeValue *msg_val_params,
|
||||
const char *id_repr)
|
||||
{
|
||||
wmMsgParams_RemoteIO params{};
|
||||
params.remote_url = BLI_strdupn(remote_url.data(), remote_url.size());
|
||||
WM_msg_subscribe_remote_io_params(mbus, ¶ms, msg_val_params, id_repr);
|
||||
|
||||
/* Value was copied into the subscribe key. */
|
||||
MEM_delete(params.remote_url);
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,376 @@
|
||||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup wm
|
||||
*/
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#include "CLG_log.h"
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_ID.h"
|
||||
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_string.h"
|
||||
|
||||
#include "WM_message.hh"
|
||||
#include "WM_types.hh"
|
||||
#include "message_bus/intern/wm_message_bus_intern.hh"
|
||||
|
||||
#include "RNA_access.hh"
|
||||
#include "RNA_path.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Internal Utilities
|
||||
* \{ */
|
||||
|
||||
BLI_INLINE uint void_hash_uint(const void *key)
|
||||
{
|
||||
size_t y = size_t(key) >> sizeof(void *);
|
||||
return uint(y);
|
||||
}
|
||||
|
||||
static uint wm_msg_rna_gset_hash(const void *key_p)
|
||||
{
|
||||
const wmMsgSubscribeKey_RNA *key = static_cast<const wmMsgSubscribeKey_RNA *>(key_p);
|
||||
const wmMsgParams_RNA *params = &key->msg.params;
|
||||
// printf("%s\n", RNA_struct_identifier(params->ptr.type));
|
||||
uint k = void_hash_uint(params->ptr.type);
|
||||
k ^= void_hash_uint(params->ptr.data);
|
||||
k ^= void_hash_uint(params->ptr.owner_id);
|
||||
k ^= void_hash_uint(params->prop);
|
||||
return k;
|
||||
}
|
||||
static bool wm_msg_rna_gset_cmp(const void *key_a_p, const void *key_b_p)
|
||||
{
|
||||
const wmMsgParams_RNA *params_a =
|
||||
&(static_cast<const wmMsgSubscribeKey_RNA *>(key_a_p))->msg.params;
|
||||
const wmMsgParams_RNA *params_b =
|
||||
&(static_cast<const wmMsgSubscribeKey_RNA *>(key_b_p))->msg.params;
|
||||
return !((params_a->ptr.type == params_b->ptr.type) &&
|
||||
(params_a->ptr.owner_id == params_b->ptr.owner_id) &&
|
||||
(params_a->ptr.data == params_b->ptr.data) && (params_a->prop == params_b->prop));
|
||||
}
|
||||
|
||||
static void *wm_msg_rna_gset_key_duplicate(const void *key_p)
|
||||
{
|
||||
const wmMsgSubscribeKey_RNA *key_src = static_cast<const wmMsgSubscribeKey_RNA *>(key_p);
|
||||
return MEM_new<wmMsgSubscribeKey_RNA>(__func__, *key_src);
|
||||
}
|
||||
static void wm_msg_rna_gset_key_free(void *key_p)
|
||||
{
|
||||
wmMsgSubscribeKey_RNA *key = static_cast<wmMsgSubscribeKey_RNA *>(key_p);
|
||||
wmMsgSubscribeValueLink *msg_lnk_next;
|
||||
for (wmMsgSubscribeValueLink *msg_lnk =
|
||||
static_cast<wmMsgSubscribeValueLink *>(key->head.values.first);
|
||||
msg_lnk;
|
||||
msg_lnk = msg_lnk_next)
|
||||
{
|
||||
msg_lnk_next = msg_lnk->next;
|
||||
wm_msg_subscribe_value_free(&key->head, msg_lnk);
|
||||
}
|
||||
if (key->msg.params.data_path != nullptr) {
|
||||
MEM_delete(key->msg.params.data_path);
|
||||
}
|
||||
MEM_delete(key);
|
||||
}
|
||||
|
||||
static void wm_msg_rna_repr(FILE *stream, const wmMsgSubscribeKey *msg_key)
|
||||
{
|
||||
const wmMsgSubscribeKey_RNA *m = reinterpret_cast<wmMsgSubscribeKey_RNA *>(
|
||||
const_cast<wmMsgSubscribeKey *>(msg_key));
|
||||
const char *none = "<none>";
|
||||
fprintf(stream,
|
||||
"<wmMsg_RNA %p, "
|
||||
"id='%s', "
|
||||
"%s.%s values_len=%d\n",
|
||||
m,
|
||||
m->msg.head.id,
|
||||
m->msg.params.ptr.type ? RNA_struct_identifier(m->msg.params.ptr.type) : none,
|
||||
m->msg.params.prop ?
|
||||
RNA_property_identifier(const_cast<PropertyRNA *>(m->msg.params.prop)) :
|
||||
none,
|
||||
m->head.values.count());
|
||||
}
|
||||
|
||||
static void wm_msg_rna_update_by_id(wmMsgBus *mbus, ID *id_src, ID *id_dst)
|
||||
{
|
||||
GSet *gs = mbus->messages_gset[WM_MSG_TYPE_RNA];
|
||||
GSetIterator gs_iter;
|
||||
BLI_gsetIterator_init(&gs_iter, gs);
|
||||
while (BLI_gsetIterator_done(&gs_iter) == false) {
|
||||
wmMsgSubscribeKey_RNA *key = static_cast<wmMsgSubscribeKey_RNA *>(
|
||||
BLI_gsetIterator_getKey(&gs_iter));
|
||||
BLI_gsetIterator_step(&gs_iter);
|
||||
if (key->msg.params.ptr.owner_id == id_src) {
|
||||
|
||||
/* GSet always needs updating since the key changes. */
|
||||
BLI_gset_remove(gs, key, nullptr);
|
||||
|
||||
/* Remove any non-persistent values, so a single persistent
|
||||
* value doesn't modify behavior for the rest. */
|
||||
for (wmMsgSubscribeValueLink *
|
||||
msg_lnk = static_cast<wmMsgSubscribeValueLink *>(key->head.values.first),
|
||||
*msg_lnk_next;
|
||||
msg_lnk;
|
||||
msg_lnk = msg_lnk_next)
|
||||
{
|
||||
msg_lnk_next = msg_lnk->next;
|
||||
if (msg_lnk->params.is_persistent == false) {
|
||||
if (msg_lnk->params.tag) {
|
||||
mbus->messages_tag_count -= 1;
|
||||
}
|
||||
wm_msg_subscribe_value_free(&key->head, msg_lnk);
|
||||
}
|
||||
}
|
||||
|
||||
bool remove = true;
|
||||
|
||||
if (key->head.values.is_empty()) {
|
||||
/* Remove, no reason to keep. */
|
||||
}
|
||||
else if (key->msg.params.ptr.data == key->msg.params.ptr.owner_id) {
|
||||
/* Simple, just update the ID. */
|
||||
key->msg.params.ptr.data = id_dst;
|
||||
key->msg.params.ptr.owner_id = id_dst;
|
||||
remove = false;
|
||||
}
|
||||
else {
|
||||
/* We need to resolve this from the new ID pointer. */
|
||||
PointerRNA idptr = RNA_id_pointer_create(id_dst);
|
||||
PointerRNA ptr;
|
||||
PropertyRNA *prop = nullptr;
|
||||
if (RNA_path_resolve(&idptr, key->msg.params.data_path, &ptr, &prop) &&
|
||||
(prop == nullptr) == (key->msg.params.prop == nullptr))
|
||||
{
|
||||
key->msg.params.ptr = ptr;
|
||||
key->msg.params.prop = prop;
|
||||
remove = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (remove) {
|
||||
for (wmMsgSubscribeValueLink *
|
||||
msg_lnk = static_cast<wmMsgSubscribeValueLink *>(key->head.values.first),
|
||||
*msg_lnk_next;
|
||||
msg_lnk;
|
||||
msg_lnk = msg_lnk_next)
|
||||
{
|
||||
msg_lnk_next = msg_lnk->next;
|
||||
if (msg_lnk->params.is_persistent == false) {
|
||||
if (msg_lnk->params.tag) {
|
||||
mbus->messages_tag_count -= 1;
|
||||
}
|
||||
wm_msg_subscribe_value_free(&key->head, msg_lnk);
|
||||
}
|
||||
}
|
||||
/* Failed to persist, remove the key. */
|
||||
BLI_remlink(&mbus->messages, key);
|
||||
wm_msg_rna_gset_key_free(key);
|
||||
}
|
||||
else {
|
||||
/* Note that it's not impossible this key exists, however it is very unlikely
|
||||
* since a subscriber would need to register in the middle of an undo for eg.
|
||||
* so assert for now. */
|
||||
BLI_assert(!BLI_gset_haskey(gs, key));
|
||||
BLI_gset_add(gs, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void wm_msg_rna_remove_by_id(wmMsgBus *mbus, const ID *id)
|
||||
{
|
||||
GSet *gs = mbus->messages_gset[WM_MSG_TYPE_RNA];
|
||||
GSetIterator gs_iter;
|
||||
BLI_gsetIterator_init(&gs_iter, gs);
|
||||
while (BLI_gsetIterator_done(&gs_iter) == false) {
|
||||
wmMsgSubscribeKey_RNA *key = static_cast<wmMsgSubscribeKey_RNA *>(
|
||||
BLI_gsetIterator_getKey(&gs_iter));
|
||||
BLI_gsetIterator_step(&gs_iter);
|
||||
if (key->msg.params.ptr.owner_id == id) {
|
||||
/* Clear here so we can decrement 'messages_tag_count'. */
|
||||
for (wmMsgSubscribeValueLink *
|
||||
msg_lnk = static_cast<wmMsgSubscribeValueLink *>(key->head.values.first),
|
||||
*msg_lnk_next;
|
||||
msg_lnk;
|
||||
msg_lnk = msg_lnk_next)
|
||||
{
|
||||
msg_lnk_next = msg_lnk->next;
|
||||
if (msg_lnk->params.tag) {
|
||||
mbus->messages_tag_count -= 1;
|
||||
}
|
||||
wm_msg_subscribe_value_free(&key->head, msg_lnk);
|
||||
}
|
||||
|
||||
BLI_remlink(&mbus->messages, key);
|
||||
BLI_gset_remove(gs, key, nullptr);
|
||||
wm_msg_rna_gset_key_free(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WM_msgtypeinfo_init_rna(wmMsgTypeInfo *msgtype_info)
|
||||
{
|
||||
msgtype_info->gset.hash_fn = wm_msg_rna_gset_hash;
|
||||
msgtype_info->gset.cmp_fn = wm_msg_rna_gset_cmp;
|
||||
msgtype_info->gset.key_duplicate_fn = wm_msg_rna_gset_key_duplicate;
|
||||
msgtype_info->gset.key_free_fn = wm_msg_rna_gset_key_free;
|
||||
|
||||
msgtype_info->repr = wm_msg_rna_repr;
|
||||
msgtype_info->update_by_id = wm_msg_rna_update_by_id;
|
||||
msgtype_info->remove_by_id = wm_msg_rna_remove_by_id;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name RNA API
|
||||
* \{ */
|
||||
|
||||
wmMsgSubscribeKey_RNA *WM_msg_lookup_rna(wmMsgBus *mbus, const wmMsgParams_RNA *msg_key_params)
|
||||
{
|
||||
wmMsgSubscribeKey_RNA key_test;
|
||||
key_test.msg.params = *msg_key_params;
|
||||
return static_cast<wmMsgSubscribeKey_RNA *>(
|
||||
BLI_gset_lookup(mbus->messages_gset[WM_MSG_TYPE_RNA], &key_test));
|
||||
}
|
||||
|
||||
void WM_msg_publish_rna_params(wmMsgBus *mbus, const wmMsgParams_RNA *msg_key_params)
|
||||
{
|
||||
wmMsgSubscribeKey_RNA *key;
|
||||
|
||||
const char *none = "<none>";
|
||||
CLOG_DEBUG(WM_LOG_MSGBUS_PUB,
|
||||
"rna(id='%s', %s.%s)",
|
||||
msg_key_params->ptr.owner_id ? ((ID *)msg_key_params->ptr.owner_id)->name : none,
|
||||
msg_key_params->ptr.type ? RNA_struct_identifier(msg_key_params->ptr.type) : none,
|
||||
msg_key_params->prop ? RNA_property_identifier((PropertyRNA *)msg_key_params->prop) :
|
||||
none);
|
||||
|
||||
if ((key = WM_msg_lookup_rna(mbus, msg_key_params))) {
|
||||
WM_msg_publish_with_key(mbus, &key->head);
|
||||
}
|
||||
|
||||
/* Support anonymous subscribers, this may be some extra overhead
|
||||
* but we want to be able to be more ambiguous. */
|
||||
if (msg_key_params->ptr.owner_id || msg_key_params->ptr.data) {
|
||||
wmMsgParams_RNA msg_key_params_anon = *msg_key_params;
|
||||
|
||||
/* We might want to enable this later? */
|
||||
if (msg_key_params_anon.prop != nullptr) {
|
||||
/* All properties for this type. */
|
||||
msg_key_params_anon.prop = nullptr;
|
||||
if ((key = WM_msg_lookup_rna(mbus, &msg_key_params_anon))) {
|
||||
WM_msg_publish_with_key(mbus, &key->head);
|
||||
}
|
||||
msg_key_params_anon.prop = msg_key_params->prop;
|
||||
}
|
||||
|
||||
msg_key_params_anon.ptr.owner_id = nullptr;
|
||||
msg_key_params_anon.ptr.data = nullptr;
|
||||
if ((key = WM_msg_lookup_rna(mbus, &msg_key_params_anon))) {
|
||||
WM_msg_publish_with_key(mbus, &key->head);
|
||||
}
|
||||
|
||||
/* Support subscribers to a type. */
|
||||
if (msg_key_params->prop) {
|
||||
msg_key_params_anon.prop = nullptr;
|
||||
if ((key = WM_msg_lookup_rna(mbus, &msg_key_params_anon))) {
|
||||
WM_msg_publish_with_key(mbus, &key->head);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WM_msg_publish_rna(wmMsgBus *mbus, PointerRNA *ptr, PropertyRNA *prop)
|
||||
{
|
||||
wmMsgParams_RNA params{};
|
||||
params.ptr = *ptr;
|
||||
params.prop = prop;
|
||||
WM_msg_publish_rna_params(mbus, ¶ms);
|
||||
}
|
||||
|
||||
void WM_msg_subscribe_rna_params(wmMsgBus *mbus,
|
||||
const wmMsgParams_RNA *msg_key_params,
|
||||
const wmMsgSubscribeValue *msg_val_params,
|
||||
const char *id_repr)
|
||||
{
|
||||
wmMsgSubscribeKey_RNA msg_key_test{};
|
||||
|
||||
/* Use when added. */
|
||||
msg_key_test.msg.head.id = id_repr;
|
||||
msg_key_test.msg.head.type = WM_MSG_TYPE_RNA;
|
||||
/* For lookup. */
|
||||
msg_key_test.msg.params = *msg_key_params;
|
||||
|
||||
const char *none = "<none>";
|
||||
CLOG_TRACE(WM_LOG_MSGBUS_SUB,
|
||||
"rna(id='%s', %s.%s, info='%s')",
|
||||
msg_key_params->ptr.owner_id ? ((ID *)msg_key_params->ptr.owner_id)->name : none,
|
||||
msg_key_params->ptr.type ? RNA_struct_identifier(msg_key_params->ptr.type) : none,
|
||||
msg_key_params->prop ? RNA_property_identifier((PropertyRNA *)msg_key_params->prop) :
|
||||
none,
|
||||
id_repr);
|
||||
|
||||
wmMsgSubscribeKey_RNA *msg_key = reinterpret_cast<wmMsgSubscribeKey_RNA *>(
|
||||
WM_msg_subscribe_with_key(mbus, &msg_key_test.head, msg_val_params));
|
||||
|
||||
if (msg_val_params->is_persistent) {
|
||||
if (msg_key->msg.params.data_path == nullptr) {
|
||||
if (msg_key->msg.params.ptr.data != msg_key->msg.params.ptr.owner_id) {
|
||||
/* We assume prop type can't change. */
|
||||
const std::optional<std::string> str = RNA_path_from_ID_to_struct(
|
||||
&msg_key->msg.params.ptr);
|
||||
msg_key->msg.params.data_path = str ? BLI_strdupn(str->c_str(), str->size()) : nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WM_msg_subscribe_rna(wmMsgBus *mbus,
|
||||
PointerRNA *ptr,
|
||||
const PropertyRNA *prop,
|
||||
const wmMsgSubscribeValue *msg_val_params,
|
||||
const char *id_repr)
|
||||
{
|
||||
wmMsgParams_RNA params{};
|
||||
params.ptr = *ptr;
|
||||
params.prop = prop;
|
||||
WM_msg_subscribe_rna_params(mbus, ¶ms, msg_val_params, id_repr);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/** \name ID variants of RNA API
|
||||
*
|
||||
* \note While we could have a separate type for ID's, use RNA since there is enough overlap.
|
||||
* \{ */
|
||||
|
||||
void WM_msg_subscribe_ID(wmMsgBus *mbus,
|
||||
ID *id,
|
||||
const wmMsgSubscribeValue *msg_val_params,
|
||||
const char *id_repr)
|
||||
{
|
||||
wmMsgParams_RNA msg_key_params = {{}};
|
||||
msg_key_params.ptr = RNA_id_pointer_create(id);
|
||||
WM_msg_subscribe_rna_params(mbus, &msg_key_params, msg_val_params, id_repr);
|
||||
}
|
||||
|
||||
void WM_msg_publish_ID(wmMsgBus *mbus, ID *id)
|
||||
{
|
||||
wmMsgParams_RNA msg_key_params = {{}};
|
||||
msg_key_params.ptr = RNA_id_pointer_create(id);
|
||||
WM_msg_publish_rna_params(mbus, &msg_key_params);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,139 @@
|
||||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup wm
|
||||
*/
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#include "CLG_log.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_listbase.h"
|
||||
|
||||
#include "WM_message.hh"
|
||||
#include "WM_types.hh"
|
||||
#include "message_bus/intern/wm_message_bus_intern.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static uint wm_msg_static_gset_hash(const void *key_p)
|
||||
{
|
||||
const wmMsgSubscribeKey_Static *key = static_cast<const wmMsgSubscribeKey_Static *>(key_p);
|
||||
const wmMsgParams_Static *params = &key->msg.params;
|
||||
uint k = params->event;
|
||||
return k;
|
||||
}
|
||||
static bool wm_msg_static_gset_cmp(const void *key_a_p, const void *key_b_p)
|
||||
{
|
||||
const wmMsgParams_Static *params_a =
|
||||
&(static_cast<const wmMsgSubscribeKey_Static *>(key_a_p))->msg.params;
|
||||
const wmMsgParams_Static *params_b =
|
||||
&(static_cast<const wmMsgSubscribeKey_Static *>(key_b_p))->msg.params;
|
||||
return !(params_a->event == params_b->event);
|
||||
}
|
||||
|
||||
static void *wm_msg_static_gset_key_duplicate(const void *key_p)
|
||||
{
|
||||
const wmMsgSubscribeKey *key_src = static_cast<const wmMsgSubscribeKey *>(key_p);
|
||||
return MEM_new<wmMsgSubscribeKey>(__func__, *key_src);
|
||||
}
|
||||
static void wm_msg_static_gset_key_free(void *key_p)
|
||||
{
|
||||
wmMsgSubscribeKey *key = static_cast<wmMsgSubscribeKey *>(key_p);
|
||||
wmMsgSubscribeValueLink *msg_lnk_next;
|
||||
for (wmMsgSubscribeValueLink *msg_lnk =
|
||||
static_cast<wmMsgSubscribeValueLink *>(key->values.first);
|
||||
msg_lnk;
|
||||
msg_lnk = msg_lnk_next)
|
||||
{
|
||||
msg_lnk_next = msg_lnk->next;
|
||||
BLI_remlink(&key->values, msg_lnk);
|
||||
MEM_delete(msg_lnk);
|
||||
}
|
||||
MEM_delete(key);
|
||||
}
|
||||
|
||||
static void wm_msg_static_repr(FILE *stream, const wmMsgSubscribeKey *msg_key)
|
||||
{
|
||||
const wmMsgSubscribeKey_Static *m = reinterpret_cast<wmMsgSubscribeKey_Static *>(
|
||||
const_cast<wmMsgSubscribeKey *>(msg_key));
|
||||
fprintf(stream,
|
||||
"<wmMsg_Static %p, "
|
||||
"id='%s', "
|
||||
"values_len=%d\n",
|
||||
m,
|
||||
m->msg.head.id,
|
||||
m->head.values.count());
|
||||
}
|
||||
|
||||
void WM_msgtypeinfo_init_static(wmMsgTypeInfo *msgtype_info)
|
||||
{
|
||||
msgtype_info->gset.hash_fn = wm_msg_static_gset_hash;
|
||||
msgtype_info->gset.cmp_fn = wm_msg_static_gset_cmp;
|
||||
msgtype_info->gset.key_duplicate_fn = wm_msg_static_gset_key_duplicate;
|
||||
msgtype_info->gset.key_free_fn = wm_msg_static_gset_key_free;
|
||||
msgtype_info->repr = wm_msg_static_repr;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
wmMsgSubscribeKey_Static *WM_msg_lookup_static(wmMsgBus *mbus,
|
||||
const wmMsgParams_Static *msg_key_params)
|
||||
{
|
||||
wmMsgSubscribeKey_Static key_test;
|
||||
key_test.msg.params = *msg_key_params;
|
||||
return static_cast<wmMsgSubscribeKey_Static *>(
|
||||
BLI_gset_lookup(mbus->messages_gset[WM_MSG_TYPE_STATIC], &key_test));
|
||||
}
|
||||
|
||||
void WM_msg_publish_static_params(wmMsgBus *mbus, const wmMsgParams_Static *msg_key_params)
|
||||
{
|
||||
CLOG_DEBUG(WM_LOG_MSGBUS_PUB, "static(event=%d)", msg_key_params->event);
|
||||
|
||||
wmMsgSubscribeKey_Static *key = WM_msg_lookup_static(mbus, msg_key_params);
|
||||
if (key) {
|
||||
WM_msg_publish_with_key(mbus, &key->head);
|
||||
}
|
||||
}
|
||||
|
||||
void WM_msg_publish_static(wmMsgBus *mbus, int event)
|
||||
{
|
||||
wmMsgParams_Static params{};
|
||||
params.event = event;
|
||||
WM_msg_publish_static_params(mbus, ¶ms);
|
||||
}
|
||||
|
||||
void WM_msg_subscribe_static_params(wmMsgBus *mbus,
|
||||
const wmMsgParams_Static *msg_key_params,
|
||||
const wmMsgSubscribeValue *msg_val_params,
|
||||
const char *id_repr)
|
||||
{
|
||||
wmMsgSubscribeKey_Static msg_key_test{};
|
||||
|
||||
/* Use when added. */
|
||||
msg_key_test.msg.head.id = id_repr;
|
||||
msg_key_test.msg.head.type = WM_MSG_TYPE_STATIC;
|
||||
/* For lookup. */
|
||||
msg_key_test.msg.params = *msg_key_params;
|
||||
|
||||
WM_msg_subscribe_with_key(mbus, &msg_key_test.head, msg_val_params);
|
||||
}
|
||||
|
||||
void WM_msg_subscribe_static(wmMsgBus *mbus,
|
||||
int event,
|
||||
const wmMsgSubscribeValue *msg_val_params,
|
||||
const char *id_repr)
|
||||
{
|
||||
wmMsgParams_Static params{};
|
||||
params.event = event;
|
||||
WM_msg_subscribe_static_params(mbus, ¶ms, msg_val_params, id_repr);
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,299 @@
|
||||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup wm
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_string_ref.hh"
|
||||
|
||||
#include "DNA_listBase.h"
|
||||
|
||||
#include "RNA_prototypes.hh"
|
||||
#include "RNA_types.hh"
|
||||
#include <cstdio>
|
||||
|
||||
namespace blender {
|
||||
|
||||
struct ID;
|
||||
struct bContext;
|
||||
struct wmMsg;
|
||||
/* Opaque (don't expose outside `wm_message_bus.cc`). */
|
||||
struct wmMsgBus;
|
||||
struct wmMsgSubscribeKey;
|
||||
struct wmMsgSubscribeValue;
|
||||
struct wmMsgSubscribeValueLink;
|
||||
|
||||
using wmMsgNotifyFn = void (*)(bContext *C,
|
||||
wmMsgSubscribeKey *msg_key,
|
||||
wmMsgSubscribeValue *msg_val);
|
||||
using wmMsgSubscribeValueFreeDataFn = void (*)(wmMsgSubscribeKey *msg_key,
|
||||
wmMsgSubscribeValue *msg_val);
|
||||
|
||||
/* Exactly what arguments here is not obvious. */
|
||||
using wmMsgSubscribeValueUpdateIdFn =
|
||||
void (*)(bContext *C, wmMsgBus *mbus, ID *id_src, ID *id_dst, wmMsgSubscribeValue *msg_val);
|
||||
enum {
|
||||
WM_MSG_TYPE_RNA = 0,
|
||||
WM_MSG_TYPE_STATIC = 1,
|
||||
/** Messages relating to some remote resources, like progress reporting for online asset
|
||||
* downloads. */
|
||||
WM_MSG_TYPE_REMOTE_IO = 2,
|
||||
};
|
||||
#define WM_MSG_TYPE_NUM 3
|
||||
|
||||
struct wmMsgTypeInfo {
|
||||
struct {
|
||||
unsigned int (*hash_fn)(const void *msg);
|
||||
bool (*cmp_fn)(const void *a, const void *b);
|
||||
|
||||
/* Creation, duplication and deletion callbacks. */
|
||||
/* Not needed currently, key are always allocated by duplicating from stack data. */
|
||||
/* void *(*key_alloc_fn)(); */
|
||||
void *(*key_duplicate_fn)(const void *key);
|
||||
void (*key_free_fn)(void *key);
|
||||
} gset;
|
||||
|
||||
void (*update_by_id)(wmMsgBus *mbus, ID *id_src, ID *id_dst);
|
||||
void (*remove_by_id)(wmMsgBus *mbus, const ID *id);
|
||||
void (*repr)(FILE *stream, const wmMsgSubscribeKey *msg_key);
|
||||
};
|
||||
|
||||
struct wmMsg {
|
||||
unsigned int type;
|
||||
// #ifndef NDEBUG
|
||||
/* For debugging: '__func__:__LINE__'. */
|
||||
const char *id;
|
||||
// #endif
|
||||
};
|
||||
|
||||
struct wmMsgSubscribeKey {
|
||||
/** Linked list for predictable ordering, otherwise we would depend on #GHash bucketing. */
|
||||
wmMsgSubscribeKey *next, *prev;
|
||||
ListBaseT<wmMsgSubscribeValueLink> values;
|
||||
/* Over-allocate, eg: #wmMsgSubscribeKey_RNA. */
|
||||
/* Last member will be `wmMsg_*`. */
|
||||
};
|
||||
|
||||
/** One of many in #wmMsgSubscribeKey.values. */
|
||||
struct wmMsgSubscribeValue {
|
||||
wmMsgSubscribeValue *next, *prev;
|
||||
|
||||
/** Handle, used to iterate and clear. */
|
||||
void *owner;
|
||||
/** User data, can be whatever we like, free using the 'free_data' callback if it's owned. */
|
||||
void *user_data;
|
||||
|
||||
/** Callbacks. */
|
||||
wmMsgNotifyFn notify;
|
||||
wmMsgSubscribeValueUpdateIdFn update_id;
|
||||
wmMsgSubscribeValueFreeDataFn free_data;
|
||||
|
||||
/** Keep this subscriber if possible. */
|
||||
uint is_persistent : 1;
|
||||
/* Tag to run when handling events,
|
||||
* we may want option for immediate execution. */
|
||||
uint tag : 1;
|
||||
};
|
||||
|
||||
/** One of many in #wmMsgSubscribeKey.values. */
|
||||
struct wmMsgSubscribeValueLink {
|
||||
wmMsgSubscribeValueLink *next, *prev;
|
||||
wmMsgSubscribeValue params;
|
||||
};
|
||||
|
||||
void WM_msgbus_types_init();
|
||||
|
||||
wmMsgBus *WM_msgbus_create();
|
||||
void WM_msgbus_destroy(wmMsgBus *mbus);
|
||||
|
||||
void WM_msgbus_clear_by_owner(wmMsgBus *mbus, void *owner);
|
||||
|
||||
void WM_msg_dump(wmMsgBus *mbus, const char *info_str);
|
||||
void WM_msgbus_handle(wmMsgBus *mbus, bContext *C);
|
||||
|
||||
void WM_msg_publish_with_key(wmMsgBus *mbus, wmMsgSubscribeKey *msg_key);
|
||||
/**
|
||||
* \param msg_key_test: Needs following #wmMsgSubscribeKey fields filled in:
|
||||
* - `msg.params`
|
||||
* - `msg.head.type`
|
||||
* - `msg.head.id`
|
||||
* .. other values should be zeroed.
|
||||
*
|
||||
* \return The key for this subscription.
|
||||
* note that this is only needed in rare cases when the key needs further manipulation.
|
||||
*/
|
||||
wmMsgSubscribeKey *WM_msg_subscribe_with_key(wmMsgBus *mbus,
|
||||
const wmMsgSubscribeKey *msg_key_test,
|
||||
const wmMsgSubscribeValue *msg_val_params);
|
||||
|
||||
void WM_msg_id_update(wmMsgBus *mbus, ID *id_src, ID *id_dst);
|
||||
void WM_msg_id_remove(wmMsgBus *mbus, const ID *id);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* `wm_message_bus_static.cc` */
|
||||
|
||||
enum {
|
||||
/* Generic window redraw. */
|
||||
WM_MSG_STATICTYPE_WINDOW_DRAW = 0,
|
||||
WM_MSG_STATICTYPE_SCREEN_EDIT = 1,
|
||||
WM_MSG_STATICTYPE_FILE_READ = 2,
|
||||
};
|
||||
|
||||
struct wmMsgParams_Static {
|
||||
int event;
|
||||
};
|
||||
|
||||
struct wmMsg_Static {
|
||||
wmMsg head; /* Keep first. */
|
||||
wmMsgParams_Static params;
|
||||
};
|
||||
|
||||
struct wmMsgSubscribeKey_Static {
|
||||
wmMsgSubscribeKey head;
|
||||
wmMsg_Static msg;
|
||||
};
|
||||
|
||||
void WM_msgtypeinfo_init_static(wmMsgTypeInfo *msgtype_info);
|
||||
|
||||
wmMsgSubscribeKey_Static *WM_msg_lookup_static(wmMsgBus *mbus,
|
||||
const wmMsgParams_Static *msg_key_params);
|
||||
void WM_msg_publish_static_params(wmMsgBus *mbus, const wmMsgParams_Static *msg_key_params);
|
||||
void WM_msg_publish_static(wmMsgBus *mbus,
|
||||
/* #wmMsgParams_Static (expanded). */
|
||||
int event);
|
||||
void WM_msg_subscribe_static_params(wmMsgBus *mbus,
|
||||
const wmMsgParams_Static *msg_key_params,
|
||||
const wmMsgSubscribeValue *msg_val_params,
|
||||
const char *id_repr);
|
||||
void WM_msg_subscribe_static(wmMsgBus *mbus,
|
||||
int event,
|
||||
const wmMsgSubscribeValue *msg_val_params,
|
||||
const char *id_repr);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* `wm_message_bus_remote_io.cc` */
|
||||
|
||||
struct wmMsgParams_RemoteIO {
|
||||
/* Owned, needs freeing with `MEM_delete_void()`. */
|
||||
const char *remote_url;
|
||||
};
|
||||
|
||||
struct wmMsg_RemoteIO {
|
||||
wmMsg head; /* Keep first. */
|
||||
wmMsgParams_RemoteIO params;
|
||||
};
|
||||
|
||||
struct wmMsgSubscribeKey_RemoteIO {
|
||||
wmMsgSubscribeKey head;
|
||||
wmMsg_RemoteIO msg;
|
||||
};
|
||||
|
||||
void WM_msgtypeinfo_init_remote_io(wmMsgTypeInfo *msgtype_info);
|
||||
|
||||
wmMsgSubscribeKey_RemoteIO *WM_msg_lookup_remote_io(wmMsgBus *mbus,
|
||||
const wmMsgParams_RemoteIO *msg_key_params);
|
||||
void WM_msg_publish_remote_io_params(wmMsgBus *mbus, const wmMsgParams_RemoteIO *msg_key_params);
|
||||
void WM_msg_publish_remote_io(wmMsgBus *mbus, StringRef remote_url);
|
||||
void WM_msg_subscribe_remote_io_params(wmMsgBus *mbus,
|
||||
const wmMsgParams_RemoteIO *msg_key_params,
|
||||
const wmMsgSubscribeValue *msg_val_params,
|
||||
const char *id_repr);
|
||||
void WM_msg_subscribe_remote_io(wmMsgBus *mbus,
|
||||
StringRef remote_url,
|
||||
const wmMsgSubscribeValue *msg_val_params,
|
||||
const char *id_repr);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* `wm_message_bus_rna.cc` */
|
||||
|
||||
struct wmMsgParams_RNA {
|
||||
/** When #PointerRNA.data & owner_id are NULL. match against all. */
|
||||
PointerRNA ptr;
|
||||
/** When NULL, match against any property. */
|
||||
const PropertyRNA *prop;
|
||||
|
||||
/**
|
||||
* Optional RNA data path for persistent RNA properties, ignore if NULL.
|
||||
* otherwise it's allocated.
|
||||
*/
|
||||
char *data_path;
|
||||
};
|
||||
|
||||
struct wmMsg_RNA {
|
||||
wmMsg head; /* Keep first. */
|
||||
wmMsgParams_RNA params;
|
||||
};
|
||||
|
||||
struct wmMsgSubscribeKey_RNA {
|
||||
wmMsgSubscribeKey head;
|
||||
wmMsg_RNA msg;
|
||||
};
|
||||
|
||||
void WM_msgtypeinfo_init_rna(wmMsgTypeInfo *msgtype_info);
|
||||
|
||||
wmMsgSubscribeKey_RNA *WM_msg_lookup_rna(wmMsgBus *mbus, const wmMsgParams_RNA *msg_key_params);
|
||||
void WM_msg_publish_rna_params(wmMsgBus *mbus, const wmMsgParams_RNA *msg_key_params);
|
||||
void WM_msg_publish_rna(wmMsgBus *mbus,
|
||||
/* #wmMsgParams_RNA (expanded). */
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *prop);
|
||||
void WM_msg_subscribe_rna_params(wmMsgBus *mbus,
|
||||
const wmMsgParams_RNA *msg_key_params,
|
||||
const wmMsgSubscribeValue *msg_val_params,
|
||||
const char *id_repr);
|
||||
void WM_msg_subscribe_rna(wmMsgBus *mbus,
|
||||
PointerRNA *ptr,
|
||||
const PropertyRNA *prop,
|
||||
const wmMsgSubscribeValue *msg_val_params,
|
||||
const char *id_repr);
|
||||
|
||||
/* ID variants. */
|
||||
void WM_msg_subscribe_ID(wmMsgBus *mbus,
|
||||
ID *id,
|
||||
const wmMsgSubscribeValue *msg_val_params,
|
||||
const char *id_repr);
|
||||
void WM_msg_publish_ID(wmMsgBus *mbus, ID *id);
|
||||
|
||||
#define WM_msg_publish_rna_prop(mbus, id_, data_, type_, prop_) \
|
||||
{ \
|
||||
wmMsgParams_RNA msg_key_params_ = {{}}; \
|
||||
msg_key_params_.ptr = RNA_pointer_create_discrete(id_, RNA_##type_, data_); \
|
||||
msg_key_params_.prop = &rna_##type_##_##prop_; \
|
||||
WM_msg_publish_rna_params(mbus, &msg_key_params_); \
|
||||
} \
|
||||
((void)0)
|
||||
#define WM_msg_subscribe_rna_prop(mbus, id_, data_, type_, prop_, value) \
|
||||
{ \
|
||||
wmMsgParams_RNA msg_key_params_ = {{}}; \
|
||||
msg_key_params_.ptr = RNA_pointer_create_discrete(id_, RNA_##type_, data_); \
|
||||
msg_key_params_.prop = &rna_##type_##_##prop_; \
|
||||
WM_msg_subscribe_rna_params(mbus, &msg_key_params_, value, __func__); \
|
||||
} \
|
||||
((void)0)
|
||||
|
||||
/* Anonymous variants (for convenience). */
|
||||
#define WM_msg_subscribe_rna_anon_type(mbus, type_, value) \
|
||||
{ \
|
||||
PointerRNA msg_ptr_ = {nullptr, RNA_##type_, nullptr}; \
|
||||
wmMsgParams_RNA msg_key_params_ = {{}}; \
|
||||
msg_key_params_.ptr = msg_ptr_; \
|
||||
\
|
||||
WM_msg_subscribe_rna_params(mbus, &msg_key_params_, value, __func__); \
|
||||
} \
|
||||
((void)0)
|
||||
#define WM_msg_subscribe_rna_anon_prop(mbus, type_, prop_, value) \
|
||||
{ \
|
||||
PointerRNA msg_ptr_ = {nullptr, RNA_##type_, nullptr}; \
|
||||
wmMsgParams_RNA msg_key_params_ = {{}}; \
|
||||
msg_key_params_.ptr = msg_ptr_; \
|
||||
msg_key_params_.prop = &rna_##type_##_##prop_; \
|
||||
\
|
||||
WM_msg_subscribe_rna_params(mbus, &msg_key_params_, value, __func__); \
|
||||
} \
|
||||
((void)0)
|
||||
|
||||
} // namespace blender
|
||||
Reference in New Issue
Block a user