Geometry Nodes: make evaluation and logging system aware of zones #109029
|
@ -2166,7 +2166,7 @@ static bool ui_but_drag_init(bContext *C,
|
|||
else if (but->type == UI_BTYPE_VIEW_ITEM) {
|
||||
const uiButViewItem *view_item_but = (uiButViewItem *)but;
|
||||
if (view_item_but->view_item) {
|
||||
UI_view_item_drag_start(C, view_item_but->view_item);
|
||||
return UI_view_item_drag_start(C, view_item_but->view_item);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -11347,6 +11347,10 @@ static int ui_handle_menus_recursive(bContext *C,
|
|||
}
|
||||
}
|
||||
|
||||
if (!menu->retvalue) {
|
||||
ui_handle_viewlist_items_hover(event, menu->region);
|
||||
}
|
||||
|
||||
if (do_towards_reinit) {
|
||||
ui_mouse_motion_towards_reinit(menu, event->xy);
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ AbstractTreeViewItem *AbstractTreeView::find_matching_child(
|
|||
const AbstractTreeViewItem &lookup_item, const TreeViewOrItem &items)
|
||||
{
|
||||
for (const auto &iter_item : items.children_) {
|
||||
if (lookup_item.matches_single(*iter_item)) {
|
||||
if (lookup_item.matches(*iter_item)) {
|
||||
/* We have a matching item! */
|
||||
return iter_item.get();
|
||||
}
|
||||
|
@ -176,7 +176,7 @@ void AbstractTreeViewItem::collapse_chevron_click_fn(bContext *C,
|
|||
* lookup the hovered item via context here. */
|
||||
|
||||
const wmWindow *win = CTX_wm_window(C);
|
||||
const ARegion *region = CTX_wm_region(C);
|
||||
const ARegion *region = CTX_wm_menu(C) ? CTX_wm_menu(C) : CTX_wm_region(C);
|
||||
uiViewItemHandle *hovered_item_handle = UI_region_views_find_item_at(region,
|
||||
win->eventstate->xy);
|
||||
|
||||
|
@ -474,14 +474,16 @@ void TreeViewLayoutBuilder::build_row(AbstractTreeViewItem &item) const
|
|||
uiLayoutSetActive(overlap, false);
|
||||
}
|
||||
|
||||
uiLayoutRow(overlap, false);
|
||||
uiLayout *row = uiLayoutRow(overlap, false);
|
||||
/* Enable emboss for mouse hover highlight. */
|
||||
uiLayoutSetEmboss(row, UI_EMBOSS);
|
||||
/* Every item gets one! Other buttons can be overlapped on top. */
|
||||
item.add_treerow_button(block_);
|
||||
|
||||
/* After adding tree-row button (would disable hover highlighting). */
|
||||
UI_block_emboss_set(&block_, UI_EMBOSS_NONE);
|
||||
|
||||
uiLayout *row = uiLayoutRow(overlap, true);
|
||||
row = uiLayoutRow(overlap, true);
|
||||
item.add_indent(*row);
|
||||
item.add_collapse_chevron(block_);
|
||||
|
||||
|
|
|
@ -51,6 +51,10 @@
|
|||
|
||||
#include "object_intern.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
|
||||
namespace blender::ed::object::bake_simulation {
|
||||
|
||||
static bool calculate_to_frame_poll(bContext *C)
|
||||
|
@ -252,10 +256,6 @@ static void bake_simulation_job_startjob(void *customdata,
|
|||
if (md->type == eModifierType_Nodes) {
|
||||
NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md);
|
||||
nmd->simulation_cache->ptr->reset();
|
||||
if (StringRef(nmd->simulation_bake_directory).is_empty()) {
|
||||
nmd->simulation_bake_directory = BLI_strdup(
|
||||
bke::sim::get_default_modifier_bake_directory(*job.bmain, *object, *md).c_str());
|
||||
}
|
||||
char absolute_bake_dir[FILE_MAX];
|
||||
STRNCPY(absolute_bake_dir, nmd->simulation_bake_directory);
|
||||
BLI_path_abs(absolute_bake_dir, base_path);
|
||||
|
@ -362,7 +362,7 @@ static void bake_simulation_job_endjob(void *customdata)
|
|||
WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, nullptr);
|
||||
}
|
||||
|
||||
static int bake_simulation_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
|
||||
static int bake_simulation_execute(bContext *C, wmOperator *op)
|
||||
{
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
|
@ -405,6 +405,160 @@ static int bake_simulation_invoke(bContext *C, wmOperator *op, const wmEvent * /
|
|||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
struct PathStringHash {
|
||||
uint64_t operator()(const StringRef s) const
|
||||
{
|
||||
/* Normalize the paths so we can compare them. */
|
||||
DynamicStackBuffer<256> norm_buf(s.size() + 1, 8);
|
||||
memcpy(norm_buf.buffer(), s.data(), s.size() + 1);
|
||||
char *norm = static_cast<char *>(norm_buf.buffer());
|
||||
|
||||
BLI_path_slash_native(norm);
|
||||
|
||||
/* Strip ending slash. */
|
||||
BLI_path_slash_rstrip(norm);
|
||||
|
||||
BLI_path_normalize(norm);
|
||||
return get_default_hash(norm);
|
||||
}
|
||||
};
|
||||
|
||||
struct PathStringEquality {
|
||||
bool operator()(const StringRef a, const StringRef b) const
|
||||
{
|
||||
return BLI_path_cmp_normalized(a.data(), b.data()) == 0;
|
||||
}
|
||||
};
|
||||
|
||||
static bool bake_directory_has_data(const StringRefNull absolute_bake_dir)
|
||||
{
|
||||
char meta_dir[FILE_MAX];
|
||||
BLI_path_join(meta_dir, sizeof(meta_dir), absolute_bake_dir.c_str(), "meta");
|
||||
char bdata_dir[FILE_MAX];
|
||||
BLI_path_join(bdata_dir, sizeof(bdata_dir), absolute_bake_dir.c_str(), "bdata");
|
||||
|
||||
if (!BLI_is_dir(meta_dir) || !BLI_is_dir(bdata_dir)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void bake_simulation_validate_paths(bContext *C,
|
||||
wmOperator *op,
|
||||
const Span<Object *> objects)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
|
||||
for (Object *object : objects) {
|
||||
if (!BKE_id_is_editable(bmain, &object->id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
|
||||
if (md->type != eModifierType_Nodes) {
|
||||
continue;
|
||||
}
|
||||
|
||||
NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md);
|
||||
if (StringRef(nmd->simulation_bake_directory).is_empty()) {
|
||||
BKE_reportf(op->reports,
|
||||
RPT_INFO,
|
||||
"Bake directory of object %s, modifier %s is empty, setting default path",
|
||||
object->id.name + 2,
|
||||
md->name);
|
||||
|
||||
nmd->simulation_bake_directory = BLI_strdup(
|
||||
bke::sim::get_default_modifier_bake_directory(*bmain, *object, *md).c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Map for counting path references. */
|
||||
using PathUsersMap = Map<std::string,
|
||||
int,
|
||||
default_inline_buffer_capacity(sizeof(std::string)),
|
||||
DefaultProbingStrategy,
|
||||
PathStringHash,
|
||||
PathStringEquality>;
|
||||
|
||||
static PathUsersMap bake_simulation_get_path_users(bContext *C, const Span<Object *> objects)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
|
||||
PathUsersMap path_users;
|
||||
for (const Object *object : objects) {
|
||||
const char *base_path = ID_BLEND_PATH(bmain, &object->id);
|
||||
|
||||
LISTBASE_FOREACH (const ModifierData *, md, &object->modifiers) {
|
||||
if (md->type != eModifierType_Nodes) {
|
||||
continue;
|
||||
}
|
||||
const NodesModifierData *nmd = reinterpret_cast<const NodesModifierData *>(md);
|
||||
if (StringRef(nmd->simulation_bake_directory).is_empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
char absolute_bake_dir[FILE_MAX];
|
||||
STRNCPY(absolute_bake_dir, nmd->simulation_bake_directory);
|
||||
BLI_path_abs(absolute_bake_dir, base_path);
|
||||
path_users.add_or_modify(
|
||||
absolute_bake_dir, [](int *value) { *value = 1; }, [](int *value) { ++(*value); });
|
||||
}
|
||||
}
|
||||
|
||||
return path_users;
|
||||
}
|
||||
|
||||
static int bake_simulation_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
|
||||
{
|
||||
Vector<Object *> objects;
|
||||
if (RNA_boolean_get(op->ptr, "selected")) {
|
||||
CTX_DATA_BEGIN (C, Object *, object, selected_objects) {
|
||||
objects.append(object);
|
||||
}
|
||||
CTX_DATA_END;
|
||||
}
|
||||
else {
|
||||
if (Object *object = CTX_data_active_object(C)) {
|
||||
objects.append(object);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set empty paths to default. */
|
||||
bake_simulation_validate_paths(C, op, objects);
|
||||
|
||||
PathUsersMap path_users = bake_simulation_get_path_users(C, objects);
|
||||
bool has_path_conflict = false;
|
||||
bool has_existing_bake_data = false;
|
||||
for (const auto &item : path_users.items()) {
|
||||
/* Check if multiple caches are writing to the same bake directory. */
|
||||
if (item.value > 1) {
|
||||
BKE_reportf(op->reports,
|
||||
RPT_ERROR,
|
||||
"Path conflict: %d caches set to path %s",
|
||||
item.value,
|
||||
item.key.data());
|
||||
has_path_conflict = true;
|
||||
}
|
||||
|
||||
/* Check if path exists and contains bake data already. */
|
||||
if (bake_directory_has_data(item.key.data())) {
|
||||
has_existing_bake_data = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_path_conflict) {
|
||||
UI_popup_menu_reports(C, op->reports);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
if (has_existing_bake_data) {
|
||||
return WM_operator_confirm_message(C, op, "Overwrite existing bake data");
|
||||
}
|
||||
return bake_simulation_execute(C, op);
|
||||
}
|
||||
|
||||
static int bake_simulation_modal(bContext *C, wmOperator * /*op*/, const wmEvent * /*event*/)
|
||||
{
|
||||
if (!WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C), WM_JOB_TYPE_BAKE_SIMULATION_NODES)) {
|
||||
|
@ -493,6 +647,7 @@ void OBJECT_OT_simulation_nodes_cache_bake(wmOperatorType *ot)
|
|||
ot->description = "Bake simulations in geometry nodes modifiers";
|
||||
ot->idname = __func__;
|
||||
|
||||
ot->exec = bake_simulation_execute;
|
||||
ot->invoke = bake_simulation_invoke;
|
||||
ot->modal = bake_simulation_modal;
|
||||
ot->poll = bake_simulation_poll;
|
||||
|
|
|
@ -412,7 +412,7 @@ static void nla_main_region_message_subscribe(const wmRegionMessageSubscribePara
|
|||
PointerRNA ptr;
|
||||
RNA_pointer_create(&screen->id, &RNA_SpaceNLA, area->spacedata.first, &ptr);
|
||||
|
||||
wmMsgSubscribeValue msg_sub_value_region_tag_redraw;
|
||||
wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {};
|
||||
msg_sub_value_region_tag_redraw.owner = region;
|
||||
msg_sub_value_region_tag_redraw.user_data = region;
|
||||
msg_sub_value_region_tag_redraw.notify = ED_region_do_msg_notify_tag_redraw;
|
||||
|
@ -488,7 +488,7 @@ static void nla_channel_region_message_subscribe(const wmRegionMessageSubscribeP
|
|||
PointerRNA ptr;
|
||||
RNA_pointer_create(&screen->id, &RNA_SpaceNLA, area->spacedata.first, &ptr);
|
||||
|
||||
wmMsgSubscribeValue msg_sub_value_region_tag_redraw;
|
||||
wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {};
|
||||
msg_sub_value_region_tag_redraw.owner = region;
|
||||
msg_sub_value_region_tag_redraw.user_data = region;
|
||||
msg_sub_value_region_tag_redraw.notify = ED_region_do_msg_notify_tag_redraw;
|
||||
|
|
Loading…
Reference in New Issue