Internally we use the name "context (path)" instead of "breadcrumb". This was missing from a rename in the original patch.
307 lines
9.5 KiB
C++
307 lines
9.5 KiB
C++
/*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
#include "BLI_hash.h"
|
|
#include "BLI_hash.hh"
|
|
#include "BLI_hash_mm2a.h"
|
|
#include "BLI_listbase.h"
|
|
#include "BLI_string.h"
|
|
#include "BLI_utildefines.h"
|
|
#include "BLI_vector.hh"
|
|
|
|
#include "ED_spreadsheet.h"
|
|
|
|
#include "DEG_depsgraph.h"
|
|
|
|
#include "BKE_main.h"
|
|
#include "BKE_modifier.h"
|
|
#include "BKE_object.h"
|
|
|
|
#include "spreadsheet_context.hh"
|
|
|
|
namespace blender::ed::spreadsheet {
|
|
|
|
static SpreadsheetContextObject *spreadsheet_context_object_new()
|
|
{
|
|
SpreadsheetContextObject *context = (SpreadsheetContextObject *)MEM_callocN(
|
|
sizeof(SpreadsheetContextObject), __func__);
|
|
context->base.type = SPREADSHEET_CONTEXT_OBJECT;
|
|
return context;
|
|
}
|
|
|
|
static SpreadsheetContextObject *spreadsheet_context_object_copy(
|
|
const SpreadsheetContextObject *src_context)
|
|
{
|
|
SpreadsheetContextObject *new_context = spreadsheet_context_object_new();
|
|
new_context->object = src_context->object;
|
|
return new_context;
|
|
}
|
|
|
|
static void spreadsheet_context_object_hash(const SpreadsheetContextObject *context,
|
|
BLI_HashMurmur2A *mm2)
|
|
{
|
|
BLI_hash_mm2a_add(mm2, (const uchar *)&context->object, sizeof(Object *));
|
|
}
|
|
|
|
static void spreadsheet_context_object_free(SpreadsheetContextObject *context)
|
|
{
|
|
MEM_freeN(context);
|
|
}
|
|
|
|
static SpreadsheetContextModifier *spreadsheet_context_modifier_new()
|
|
{
|
|
SpreadsheetContextModifier *context = (SpreadsheetContextModifier *)MEM_callocN(
|
|
sizeof(SpreadsheetContextModifier), __func__);
|
|
context->base.type = SPREADSHEET_CONTEXT_MODIFIER;
|
|
return context;
|
|
}
|
|
|
|
static SpreadsheetContextModifier *spreadsheet_context_modifier_copy(
|
|
const SpreadsheetContextModifier *src_context)
|
|
{
|
|
SpreadsheetContextModifier *new_context = spreadsheet_context_modifier_new();
|
|
if (src_context->modifier_name) {
|
|
new_context->modifier_name = BLI_strdup(src_context->modifier_name);
|
|
}
|
|
return new_context;
|
|
}
|
|
|
|
static void spreadsheet_context_modifier_hash(const SpreadsheetContextModifier *context,
|
|
BLI_HashMurmur2A *mm2)
|
|
{
|
|
if (context->modifier_name) {
|
|
BLI_hash_mm2a_add(mm2, (const uchar *)context->modifier_name, strlen(context->modifier_name));
|
|
}
|
|
}
|
|
|
|
static void spreadsheet_context_modifier_free(SpreadsheetContextModifier *context)
|
|
{
|
|
if (context->modifier_name) {
|
|
MEM_freeN(context->modifier_name);
|
|
}
|
|
MEM_freeN(context);
|
|
}
|
|
|
|
static SpreadsheetContextNode *spreadsheet_context_node_new()
|
|
{
|
|
SpreadsheetContextNode *context = (SpreadsheetContextNode *)MEM_callocN(
|
|
sizeof(SpreadsheetContextNode), __func__);
|
|
context->base.type = SPREADSHEET_CONTEXT_NODE;
|
|
return context;
|
|
}
|
|
|
|
static SpreadsheetContextNode *spreadsheet_context_node_copy(
|
|
const SpreadsheetContextNode *src_context)
|
|
{
|
|
SpreadsheetContextNode *new_context = spreadsheet_context_node_new();
|
|
if (src_context->node_name) {
|
|
new_context->node_name = BLI_strdup(src_context->node_name);
|
|
}
|
|
return new_context;
|
|
}
|
|
|
|
static void spreadsheet_context_node_hash(const SpreadsheetContextNode *context,
|
|
BLI_HashMurmur2A *mm2)
|
|
{
|
|
if (context->node_name) {
|
|
BLI_hash_mm2a_add(mm2, (const uchar *)context->node_name, strlen(context->node_name));
|
|
}
|
|
}
|
|
|
|
static void spreadsheet_context_node_free(SpreadsheetContextNode *context)
|
|
{
|
|
if (context->node_name) {
|
|
MEM_freeN(context->node_name);
|
|
}
|
|
MEM_freeN(context);
|
|
}
|
|
|
|
SpreadsheetContext *spreadsheet_context_new(eSpaceSpreadsheet_ContextType type)
|
|
{
|
|
switch (type) {
|
|
case SPREADSHEET_CONTEXT_OBJECT: {
|
|
return (SpreadsheetContext *)spreadsheet_context_object_new();
|
|
}
|
|
case SPREADSHEET_CONTEXT_MODIFIER: {
|
|
return (SpreadsheetContext *)spreadsheet_context_modifier_new();
|
|
}
|
|
case SPREADSHEET_CONTEXT_NODE: {
|
|
return (SpreadsheetContext *)spreadsheet_context_node_new();
|
|
}
|
|
}
|
|
BLI_assert_unreachable();
|
|
return nullptr;
|
|
}
|
|
|
|
SpreadsheetContext *spreadsheet_context_copy(const SpreadsheetContext *old_context)
|
|
{
|
|
switch (old_context->type) {
|
|
case SPREADSHEET_CONTEXT_OBJECT: {
|
|
return (SpreadsheetContext *)spreadsheet_context_object_copy(
|
|
(const SpreadsheetContextObject *)old_context);
|
|
}
|
|
case SPREADSHEET_CONTEXT_MODIFIER: {
|
|
return (SpreadsheetContext *)spreadsheet_context_modifier_copy(
|
|
(const SpreadsheetContextModifier *)old_context);
|
|
}
|
|
case SPREADSHEET_CONTEXT_NODE: {
|
|
return (SpreadsheetContext *)spreadsheet_context_node_copy(
|
|
(const SpreadsheetContextNode *)old_context);
|
|
}
|
|
}
|
|
BLI_assert_unreachable();
|
|
return nullptr;
|
|
}
|
|
|
|
static void spreadsheet_context_hash(const SpreadsheetContext *context, BLI_HashMurmur2A *mm2)
|
|
{
|
|
BLI_hash_mm2a_add_int(mm2, context->type);
|
|
switch (context->type) {
|
|
case SPREADSHEET_CONTEXT_OBJECT: {
|
|
spreadsheet_context_object_hash((const SpreadsheetContextObject *)context, mm2);
|
|
break;
|
|
}
|
|
case SPREADSHEET_CONTEXT_MODIFIER: {
|
|
spreadsheet_context_modifier_hash((const SpreadsheetContextModifier *)context, mm2);
|
|
break;
|
|
}
|
|
case SPREADSHEET_CONTEXT_NODE: {
|
|
spreadsheet_context_node_hash((const SpreadsheetContextNode *)context, mm2);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void spreadsheet_context_free(SpreadsheetContext *context)
|
|
{
|
|
switch (context->type) {
|
|
case SPREADSHEET_CONTEXT_OBJECT: {
|
|
return spreadsheet_context_object_free((SpreadsheetContextObject *)context);
|
|
}
|
|
case SPREADSHEET_CONTEXT_MODIFIER: {
|
|
return spreadsheet_context_modifier_free((SpreadsheetContextModifier *)context);
|
|
}
|
|
case SPREADSHEET_CONTEXT_NODE: {
|
|
return spreadsheet_context_node_free((SpreadsheetContextNode *)context);
|
|
}
|
|
}
|
|
BLI_assert_unreachable();
|
|
}
|
|
|
|
/**
|
|
* Tag any data relevant to the spreadsheet's context for recalculation in order to collect
|
|
* information to display in the editor, which may be cached during evaluation.
|
|
*/
|
|
static void spreadsheet_context_update_tag(SpaceSpreadsheet *sspreadsheet)
|
|
{
|
|
using namespace blender;
|
|
Vector<const SpreadsheetContext *> context_path = sspreadsheet->context_path;
|
|
if (context_path.is_empty()) {
|
|
return;
|
|
}
|
|
if (context_path[0]->type != SPREADSHEET_CONTEXT_OBJECT) {
|
|
return;
|
|
}
|
|
SpreadsheetContextObject *object_context = (SpreadsheetContextObject *)context_path[0];
|
|
Object *object = object_context->object;
|
|
if (object == nullptr) {
|
|
return;
|
|
}
|
|
if (context_path.size() == 1) {
|
|
/* No need to reevaluate, when the final or original object is viewed. */
|
|
return;
|
|
}
|
|
|
|
DEG_id_tag_update(&object->id, ID_RECALC_GEOMETRY);
|
|
}
|
|
|
|
} // namespace blender::ed::spreadsheet
|
|
|
|
SpreadsheetContext *ED_spreadsheet_context_new(int type)
|
|
{
|
|
return blender::ed::spreadsheet::spreadsheet_context_new((eSpaceSpreadsheet_ContextType)type);
|
|
}
|
|
|
|
void ED_spreadsheet_context_free(struct SpreadsheetContext *context)
|
|
{
|
|
blender::ed::spreadsheet::spreadsheet_context_free(context);
|
|
}
|
|
|
|
void ED_spreadsheet_context_path_clear(struct SpaceSpreadsheet *sspreadsheet)
|
|
{
|
|
LISTBASE_FOREACH_MUTABLE (SpreadsheetContext *, context, &sspreadsheet->context_path) {
|
|
ED_spreadsheet_context_free(context);
|
|
}
|
|
BLI_listbase_clear(&sspreadsheet->context_path);
|
|
}
|
|
|
|
void ED_spreadsheet_context_path_update_tag(SpaceSpreadsheet *sspreadsheet)
|
|
{
|
|
blender::ed::spreadsheet::spreadsheet_context_update_tag(sspreadsheet);
|
|
}
|
|
|
|
uint64_t ED_spreadsheet_context_path_hash(SpaceSpreadsheet *sspreadsheet)
|
|
{
|
|
BLI_HashMurmur2A mm2;
|
|
BLI_hash_mm2a_init(&mm2, 1234);
|
|
LISTBASE_FOREACH (SpreadsheetContext *, context, &sspreadsheet->context_path) {
|
|
blender::ed::spreadsheet::spreadsheet_context_hash(context, &mm2);
|
|
}
|
|
return BLI_hash_mm2a_end(&mm2);
|
|
}
|
|
|
|
void ED_spreadsheet_set_geometry_node_context(struct SpaceSpreadsheet *sspreadsheet,
|
|
struct SpaceNode *snode,
|
|
struct bNode *node)
|
|
{
|
|
using namespace blender::ed::spreadsheet;
|
|
ED_spreadsheet_context_path_clear(sspreadsheet);
|
|
|
|
Object *object = (Object *)snode->id;
|
|
ModifierData *modifier = BKE_object_active_modifier(object);
|
|
|
|
{
|
|
SpreadsheetContextObject *context = spreadsheet_context_object_new();
|
|
context->object = object;
|
|
BLI_addtail(&sspreadsheet->context_path, context);
|
|
}
|
|
{
|
|
SpreadsheetContextModifier *context = spreadsheet_context_modifier_new();
|
|
context->modifier_name = BLI_strdup(modifier->name);
|
|
BLI_addtail(&sspreadsheet->context_path, context);
|
|
}
|
|
{
|
|
int i;
|
|
LISTBASE_FOREACH_INDEX (bNodeTreePath *, path, &snode->treepath, i) {
|
|
if (i == 0) {
|
|
continue;
|
|
}
|
|
SpreadsheetContextNode *context = spreadsheet_context_node_new();
|
|
context->node_name = BLI_strdup(path->node_name);
|
|
BLI_addtail(&sspreadsheet->context_path, context);
|
|
}
|
|
}
|
|
{
|
|
SpreadsheetContextNode *context = spreadsheet_context_node_new();
|
|
context->node_name = BLI_strdup(node->name);
|
|
BLI_addtail(&sspreadsheet->context_path, context);
|
|
}
|
|
|
|
sspreadsheet->object_eval_state = SPREADSHEET_OBJECT_EVAL_STATE_EVALUATED;
|
|
}
|