Brush assets project #106303
@ -6739,6 +6739,21 @@ def km_node_link_modal_map(_params):
|
|||||||
return keymap
|
return keymap
|
||||||
|
|
||||||
|
|
||||||
|
def km_asset_shelf_brushes(_params):
|
||||||
|
items = []
|
||||||
|
keymap = (
|
||||||
|
"Asset Shelf",
|
||||||
|
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||||
|
{"items": items},
|
||||||
|
)
|
||||||
|
|
||||||
|
items.extend([
|
||||||
|
("sculpt_curves.brush_asset_select", {"type": 'LEFTMOUSE', "value": 'CLICK'}, None),
|
||||||
|
])
|
||||||
|
|
||||||
|
return keymap
|
||||||
|
|
||||||
|
|
||||||
# Fallback for gizmos that don't have custom a custom key-map.
|
# Fallback for gizmos that don't have custom a custom key-map.
|
||||||
def km_generic_gizmo(_params):
|
def km_generic_gizmo(_params):
|
||||||
keymap = (
|
keymap = (
|
||||||
@ -8561,6 +8576,9 @@ def generate_keymaps(params=None):
|
|||||||
km_curve_pen_modal_map(params),
|
km_curve_pen_modal_map(params),
|
||||||
km_node_link_modal_map(params),
|
km_node_link_modal_map(params),
|
||||||
|
|
||||||
|
# Asset Shelf Keymaps.
|
||||||
|
km_asset_shelf_brushes(params),
|
||||||
|
|
||||||
# Gizmos.
|
# Gizmos.
|
||||||
km_generic_gizmo(params),
|
km_generic_gizmo(params),
|
||||||
km_generic_gizmo_drag(params),
|
km_generic_gizmo_drag(params),
|
||||||
|
@ -1075,6 +1075,19 @@ class VIEW3D_HT_header(Header):
|
|||||||
sub.popover(panel="VIEW3D_PT_shading", text="")
|
sub.popover(panel="VIEW3D_PT_shading", text="")
|
||||||
|
|
||||||
|
|
||||||
|
class VIEW3D_AST_brush_asset_shelf(bpy.types.AssetShelf):
|
||||||
|
bl_space_type = "VIEW_3D"
|
||||||
|
bl_options = {'NO_ASSET_DRAG'}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
return context.object and context.object.mode == 'SCULPT_CURVES'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def asset_poll(cls, asset):
|
||||||
|
return asset.id_type == 'BRUSH'
|
||||||
|
|
||||||
|
|
||||||
class VIEW3D_MT_editor_menus(Menu):
|
class VIEW3D_MT_editor_menus(Menu):
|
||||||
bl_label = ""
|
bl_label = ""
|
||||||
|
|
||||||
@ -8656,6 +8669,7 @@ class VIEW3D_AST_sculpt_brushes(bpy.types.AssetShelf):
|
|||||||
|
|
||||||
|
|
||||||
classes = (
|
classes = (
|
||||||
|
VIEW3D_AST_brush_asset_shelf,
|
||||||
VIEW3D_HT_header,
|
VIEW3D_HT_header,
|
||||||
VIEW3D_HT_tool_header,
|
VIEW3D_HT_tool_header,
|
||||||
VIEW3D_MT_editor_menus,
|
VIEW3D_MT_editor_menus,
|
||||||
|
@ -31,6 +31,9 @@ struct UnifiedPaintSettings;
|
|||||||
void BKE_brush_system_init();
|
void BKE_brush_system_init();
|
||||||
void BKE_brush_system_exit();
|
void BKE_brush_system_exit();
|
||||||
|
|
||||||
|
Brush *BKE_brush_asset_runtime_ensure(Main *bmain,
|
||||||
|
const AssetWeakReference *brush_asset_reference);
|
||||||
|
|
||||||
/* Data-block functions. */
|
/* Data-block functions. */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -82,6 +82,17 @@ bool BKE_lib_override_library_is_user_edited(const ID *id);
|
|||||||
*/
|
*/
|
||||||
bool BKE_lib_override_library_is_system_defined(const Main *bmain, const ID *id);
|
bool BKE_lib_override_library_is_system_defined(const Main *bmain, const ID *id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count the amount of liboverride IDs of given `id_type`, using a refererence linked ID from given
|
||||||
|
* `library`, that are user-edited.
|
||||||
|
*
|
||||||
|
* \param r_reports If not NULL, add one report for each relevant ID.
|
||||||
|
*/
|
||||||
|
int BKE_lib_override_user_edited_from_library_count(struct Main *bmain,
|
||||||
|
const short id_type,
|
||||||
|
struct Library *library,
|
||||||
|
struct ReportList *r_reports);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if given Override Property for given ID is animated (through a F-Curve in an Action, or
|
* Check if given Override Property for given ID is animated (through a F-Curve in an Action, or
|
||||||
* from a driver).
|
* from a driver).
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include "bmesh.h"
|
#include "bmesh.h"
|
||||||
|
|
||||||
|
struct AssetWeakReference;
|
||||||
struct BMFace;
|
struct BMFace;
|
||||||
struct BMesh;
|
struct BMesh;
|
||||||
struct BlendDataReader;
|
struct BlendDataReader;
|
||||||
@ -166,7 +167,7 @@ PaintCurve *BKE_paint_curve_add(Main *bmain, const char *name);
|
|||||||
/**
|
/**
|
||||||
* Call when entering each respective paint mode.
|
* Call when entering each respective paint mode.
|
||||||
*/
|
*/
|
||||||
bool BKE_paint_ensure(ToolSettings *ts, Paint **r_paint);
|
bool BKE_paint_ensure(Main *bmain, ToolSettings *ts, Paint **r_paint);
|
||||||
void BKE_paint_init(Main *bmain, Scene *sce, ePaintMode mode, const uchar col[3]);
|
void BKE_paint_init(Main *bmain, Scene *sce, ePaintMode mode, const uchar col[3]);
|
||||||
void BKE_paint_free(Paint *p);
|
void BKE_paint_free(Paint *p);
|
||||||
/**
|
/**
|
||||||
@ -181,7 +182,7 @@ void BKE_paint_runtime_init(const ToolSettings *ts, Paint *paint);
|
|||||||
void BKE_paint_cavity_curve_preset(Paint *p, int preset);
|
void BKE_paint_cavity_curve_preset(Paint *p, int preset);
|
||||||
|
|
||||||
eObjectMode BKE_paint_object_mode_from_paintmode(ePaintMode mode);
|
eObjectMode BKE_paint_object_mode_from_paintmode(ePaintMode mode);
|
||||||
bool BKE_paint_ensure_from_paintmode(Scene *sce, ePaintMode mode);
|
bool BKE_paint_ensure_from_paintmode(Main *bmain, Scene *sce, ePaintMode mode);
|
||||||
Paint *BKE_paint_get_active_from_paintmode(Scene *sce, ePaintMode mode);
|
Paint *BKE_paint_get_active_from_paintmode(Scene *sce, ePaintMode mode);
|
||||||
const EnumPropertyItem *BKE_paint_get_tool_enum_from_paintmode(ePaintMode mode);
|
const EnumPropertyItem *BKE_paint_get_tool_enum_from_paintmode(ePaintMode mode);
|
||||||
const char *BKE_paint_get_tool_enum_translation_context_from_paintmode(ePaintMode mode);
|
const char *BKE_paint_get_tool_enum_translation_context_from_paintmode(ePaintMode mode);
|
||||||
@ -194,6 +195,14 @@ ePaintMode BKE_paintmode_get_from_tool(const bToolRef *tref);
|
|||||||
Brush *BKE_paint_brush(Paint *paint);
|
Brush *BKE_paint_brush(Paint *paint);
|
||||||
const Brush *BKE_paint_brush_for_read(const Paint *p);
|
const Brush *BKE_paint_brush_for_read(const Paint *p);
|
||||||
void BKE_paint_brush_set(Paint *paint, Brush *br);
|
void BKE_paint_brush_set(Paint *paint, Brush *br);
|
||||||
|
|
||||||
|
/** Set the active brush of given paint struct, and store the weak asset reference to it.
|
||||||
|
* NOTE: Takes ownership of the given `weak_asset_reference`. */
|
||||||
|
void BKE_paint_brush_asset_set(Paint *p, Brush *br, AssetWeakReference *weak_asset_reference);
|
||||||
|
|
||||||
|
/** Attempt to restore a valid active brush in `p` from brush asset informations stored in `p`. */
|
||||||
|
void BKE_paint_brush_asset_restore(Main *bmain, Paint *p);
|
||||||
|
|
||||||
Palette *BKE_paint_palette(Paint *paint);
|
Palette *BKE_paint_palette(Paint *paint);
|
||||||
void BKE_paint_palette_set(Paint *p, Palette *palette);
|
void BKE_paint_palette_set(Paint *p, Palette *palette);
|
||||||
void BKE_paint_curve_set(Brush *br, PaintCurve *pc);
|
void BKE_paint_curve_set(Brush *br, PaintCurve *pc);
|
||||||
@ -869,7 +878,7 @@ void BKE_sculpt_mask_layers_ensure(Depsgraph *depsgraph,
|
|||||||
Main *bmain,
|
Main *bmain,
|
||||||
Object *ob,
|
Object *ob,
|
||||||
MultiresModifierData *mmd);
|
MultiresModifierData *mmd);
|
||||||
void BKE_sculpt_toolsettings_data_ensure(Scene *scene);
|
void BKE_sculpt_toolsettings_data_ensure(Main *bmain, Scene *scene);
|
||||||
|
|
||||||
PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob);
|
PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob);
|
||||||
|
|
||||||
|
@ -306,14 +306,195 @@ static bool reuse_bmain_data_remapper_is_id_remapped(IDRemapper *remapper, ID *i
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Library *reuse_bmain_data_dependencies_new_library_get(ReuseOldBMainData *reuse_data,
|
||||||
|
Library *old_lib)
|
||||||
|
{
|
||||||
|
if (old_lib == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
IDRemapper *remapper = reuse_data->remapper;
|
||||||
|
Library *new_lib = old_lib;
|
||||||
|
IDRemapperApplyResult result = BKE_id_remapper_apply(
|
||||||
|
remapper, reinterpret_cast<ID **>(&new_lib), ID_REMAP_APPLY_DEFAULT);
|
||||||
|
if (result == ID_REMAP_RESULT_SOURCE_UNAVAILABLE) {
|
||||||
|
/* No matching new library found. Avoid nullptr case when original data was linked, which would
|
||||||
|
* match against all local IDs. */
|
||||||
|
}
|
||||||
|
BLI_assert_msg(result == ID_REMAP_RESULT_SOURCE_UNASSIGNED || new_lib != nullptr,
|
||||||
|
"`new_lib` should only ever be NULL here in case the library of the old linked "
|
||||||
|
"ID is the newly opened .blend file.");
|
||||||
|
return new_lib;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int reuse_bmain_data_dependencies_process_cb(LibraryIDLinkCallbackData *cb_data)
|
||||||
|
{
|
||||||
|
ID *id = *cb_data->id_pointer;
|
||||||
|
|
||||||
|
if (id == nullptr) {
|
||||||
|
return IDWALK_RET_NOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReuseOldBMainData *reuse_data = static_cast<ReuseOldBMainData *>(cb_data->user_data);
|
||||||
|
Main *new_bmain = reuse_data->new_bmain;
|
||||||
|
Main *old_bmain = reuse_data->old_bmain;
|
||||||
|
|
||||||
|
/* First check if it has already been remapped. */
|
||||||
|
IDRemapper *remapper = reuse_bmain_data_remapper_ensure(reuse_data);
|
||||||
|
if (reuse_bmain_data_remapper_is_id_remapped(remapper, id)) {
|
||||||
|
return IDWALK_RET_STOP_RECURSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
ListBase *new_lb = which_libbase(new_bmain, GS(id->name));
|
||||||
|
ListBase *old_lb = which_libbase(old_bmain, GS(id->name));
|
||||||
|
|
||||||
|
/* if ID is already in the new_bmain, this should have been detected by the check on `remapper`
|
||||||
|
* above. */
|
||||||
|
BLI_assert(BLI_findindex(new_lb, id) < 0);
|
||||||
|
BLI_assert(BLI_findindex(old_lb, id) >= 0);
|
||||||
|
|
||||||
|
/* There may be a new library pointer in new_bmain, matching a library in old_bmain, even
|
||||||
|
* though pointer values are not the same. So we need to check new linked IDs in new_bmain
|
||||||
|
* against both potential library pointers. */
|
||||||
|
Library *old_id_new_lib = reuse_bmain_data_dependencies_new_library_get(reuse_data, id->lib);
|
||||||
|
|
||||||
|
if (ID_IS_LINKED(id)) {
|
||||||
|
/* In case of linked ID, a 'new' version of the same data may already exist in new_bmain. In
|
||||||
|
* such case, do not move the old linked ID, but remap its usages to the new one instead. */
|
||||||
|
for (ID *id_iter = static_cast<ID *>(new_lb->last); id_iter != nullptr;
|
||||||
|
id_iter = static_cast<ID *>(id_iter->prev))
|
||||||
|
{
|
||||||
|
if (!ELEM(id_iter->lib, id->lib, old_id_new_lib)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!STREQ(id_iter->name + 2, id->name + 2)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NOTE: In case the old ID was from a library that is the newly opened .blend file (i.e.
|
||||||
|
* `old_id_new_lib` is NULL), this will remap to a local new ID in new_bmain.
|
||||||
|
*
|
||||||
|
* This has a potential impact on other ported over linked IDs (which are not allowed to
|
||||||
|
* use local data), and liboverrides (which are not allowed to have a local reference).
|
||||||
|
*
|
||||||
|
* Such cases are checked and 'fixed' later by the call to
|
||||||
|
* #reuse_bmain_data_invalid_local_usages_fix. */
|
||||||
|
BKE_id_remapper_add(remapper, id, id_iter);
|
||||||
|
return IDWALK_RET_STOP_RECURSION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BLI_remlink_safe(old_lb, id);
|
||||||
|
BKE_main_namemap_remove_name(old_bmain, id, id->name + 2);
|
||||||
|
|
||||||
|
id->lib = old_id_new_lib;
|
||||||
|
BLI_addtail(new_lb, id);
|
||||||
|
BKE_id_new_name_validate(new_bmain, new_lb, id, nullptr, true);
|
||||||
|
/* Remap to itself, to avoid re-processing this ID again. */
|
||||||
|
BKE_id_remapper_add(remapper, id, id);
|
||||||
|
|
||||||
|
return IDWALK_RET_NOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Selectively 'import' data from old BMain into new BMain, provided it does not conflict with data
|
||||||
|
* already present in the new BMain (name-wise and library-wise).
|
||||||
|
*
|
||||||
|
* Dependencies from moved over old data are also imported into the new BMain, (unless, in case of
|
||||||
|
* linked data, a matching linked ID is already available in new BMain).
|
||||||
|
*
|
||||||
|
* When a conflict is found, usages of the conflicted ID by the old data are stored in the
|
||||||
|
* `remapper` of `ReuseOldBMainData` to be remapped to the matching data in the new BMain later.
|
||||||
|
*
|
||||||
|
* NOTE: This function will never remove any original new data from the new BMain, it only moves
|
||||||
|
* (some of) the old data to the new BMain.
|
||||||
|
*/
|
||||||
|
static void reuse_old_bmain_data_for_blendfile(ReuseOldBMainData *reuse_data, const short id_code)
|
||||||
|
{
|
||||||
|
Main *new_bmain = reuse_data->new_bmain;
|
||||||
|
Main *old_bmain = reuse_data->old_bmain;
|
||||||
|
|
||||||
|
ListBase *new_lb = which_libbase(new_bmain, id_code);
|
||||||
|
ListBase *old_lb = which_libbase(old_bmain, id_code);
|
||||||
|
|
||||||
|
IDRemapper *remapper = reuse_bmain_data_remapper_ensure(reuse_data);
|
||||||
|
|
||||||
|
/* Bring back local existing IDs from old_lb into new_lb, if there are no name/library
|
||||||
|
* conflicts. */
|
||||||
|
for (ID *old_id_iter_next, *old_id_iter = static_cast<ID *>(old_lb->first);
|
||||||
|
old_id_iter != nullptr;
|
||||||
|
old_id_iter = old_id_iter_next)
|
||||||
|
{
|
||||||
|
old_id_iter_next = static_cast<ID *>(old_id_iter->next);
|
||||||
|
|
||||||
|
/* Fully local assets are never re-used, since in this case the old file can be considered as
|
||||||
|
* an asset repository, and its assets should be accessed through the asset system by other
|
||||||
|
* files. */
|
||||||
|
if (!ID_IS_LINKED(old_id_iter) && !ID_IS_OVERRIDE_LIBRARY(old_id_iter) &&
|
||||||
|
ID_IS_ASSET(old_id_iter)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* All other IDs can be re-used, provided there is no name/library conflict (i.e. the new bmain
|
||||||
|
* does not already have the 'same' data). */
|
||||||
|
bool can_use_old_id = true;
|
||||||
|
Library *old_id_new_lib = reuse_bmain_data_dependencies_new_library_get(reuse_data,
|
||||||
|
old_id_iter->lib);
|
||||||
|
for (ID *new_id_iter = static_cast<ID *>(new_lb->first); new_id_iter != nullptr;
|
||||||
|
new_id_iter = static_cast<ID *>(new_id_iter->next))
|
||||||
|
{
|
||||||
|
if (!ELEM(new_id_iter->lib, old_id_iter->lib, old_id_new_lib)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!STREQ(old_id_iter->name + 2, new_id_iter->name + 2)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* In case we found a matching ID in new_bmain, it can be considered as 'the same'
|
||||||
|
* as the old ID, so usages of old ID ported over to new main can be remapped.
|
||||||
|
*
|
||||||
|
* This is only valid if the old ID was linked though. */
|
||||||
|
if (ID_IS_LINKED(old_id_iter)) {
|
||||||
|
BKE_id_remapper_add(remapper, old_id_iter, new_id_iter);
|
||||||
|
}
|
||||||
|
can_use_old_id = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (can_use_old_id) {
|
||||||
|
BLI_remlink_safe(old_lb, old_id_iter);
|
||||||
|
BKE_main_namemap_remove_name(old_bmain, old_id_iter, old_id_iter->name + 2);
|
||||||
|
|
||||||
|
BLI_addtail(new_lb, old_id_iter);
|
||||||
|
old_id_iter->lib = old_id_new_lib;
|
||||||
|
BKE_id_new_name_validate(new_bmain, new_lb, old_id_iter, nullptr, true);
|
||||||
|
BKE_lib_libblock_session_uuid_renew(old_id_iter);
|
||||||
|
|
||||||
|
/* Remap to itself, to avoid re-processing this ID again. */
|
||||||
|
BKE_id_remapper_add(remapper, old_id_iter, old_id_iter);
|
||||||
|
|
||||||
|
/* Port over dependencies of re-used ID, unless matching already existing ones in
|
||||||
|
* new_bmain can be found.
|
||||||
|
*
|
||||||
|
* NOTE : No pointers are remapped here, this code only moves dependencies from old_bmain
|
||||||
|
* to new_bmain if needed, and add necessary remapping rules to the reuse_data.remapper. */
|
||||||
|
BKE_library_foreach_ID_link(new_bmain,
|
||||||
|
old_id_iter,
|
||||||
|
reuse_bmain_data_dependencies_process_cb,
|
||||||
|
reuse_data,
|
||||||
|
IDWALK_RECURSE | IDWALK_DO_LIBRARY_POINTER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Does a complete replacement of data in `new_bmain` by data from `old_bmain. Original new data
|
/** Does a complete replacement of data in `new_bmain` by data from `old_bmain. Original new data
|
||||||
* are moved to the `old_bmain`, and will be freed together with it.
|
* are moved to the `old_bmain`, and will be freed together with it.
|
||||||
*
|
*
|
||||||
* WARNING: Currently only expects to work on local data, won't work properly if some of the IDs of
|
* WARNING: Currently only expects to work on local data, won't work properly if some of the IDs of
|
||||||
* given type are linked.
|
* given type are linked.
|
||||||
*
|
*
|
||||||
* NOTE: There is no support at all for potential dependencies of the IDs moved around. This is not
|
* NOTE: Unlike with #reuse_old_bmain_data_for_blendfile, there is no support at all for potential
|
||||||
* expected to be necessary for the current use cases (UI-related IDs). */
|
* dependencies of the IDs moved around. This is not expected to be necessary for the current use
|
||||||
|
* cases (UI-related IDs). */
|
||||||
static void swap_old_bmain_data_for_blendfile(ReuseOldBMainData *reuse_data, const short id_code)
|
static void swap_old_bmain_data_for_blendfile(ReuseOldBMainData *reuse_data, const short id_code)
|
||||||
{
|
{
|
||||||
Main *new_bmain = reuse_data->new_bmain;
|
Main *new_bmain = reuse_data->new_bmain;
|
||||||
@ -720,6 +901,12 @@ static void setup_app_data(bContext *C,
|
|||||||
}
|
}
|
||||||
|
|
||||||
BKE_main_idmap_destroy(reuse_data.id_map);
|
BKE_main_idmap_destroy(reuse_data.id_map);
|
||||||
|
|
||||||
|
if (!is_startup) {
|
||||||
|
/* Keeping old brushes has different conditions, and different behavior, than UI-like ID
|
||||||
|
* types when actually reading a blendfile. */
|
||||||
|
reuse_old_bmain_data_for_blendfile(&reuse_data, ID_BR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Logic for 'track_undo_scene' is to keep using the scene which the active screen has, as long
|
/* Logic for 'track_undo_scene' is to keep using the scene which the active screen has, as long
|
||||||
|
@ -14,13 +14,17 @@
|
|||||||
#include "DNA_material_types.h"
|
#include "DNA_material_types.h"
|
||||||
#include "DNA_object_types.h"
|
#include "DNA_object_types.h"
|
||||||
#include "DNA_scene_types.h"
|
#include "DNA_scene_types.h"
|
||||||
|
#include "DNA_space_types.h"
|
||||||
|
|
||||||
#include "BLI_listbase.h"
|
#include "BLI_listbase.h"
|
||||||
#include "BLI_math_rotation.h"
|
#include "BLI_math_rotation.h"
|
||||||
#include "BLI_rand.h"
|
#include "BLI_rand.h"
|
||||||
|
|
||||||
|
#include "BLO_readfile.h"
|
||||||
|
|
||||||
#include "BLT_translation.h"
|
#include "BLT_translation.h"
|
||||||
|
|
||||||
|
#include "BKE_blendfile_link_append.h"
|
||||||
#include "BKE_bpath.h"
|
#include "BKE_bpath.h"
|
||||||
#include "BKE_brush.hh"
|
#include "BKE_brush.hh"
|
||||||
#include "BKE_colortools.h"
|
#include "BKE_colortools.h"
|
||||||
@ -36,6 +40,8 @@
|
|||||||
#include "BKE_preview_image.hh"
|
#include "BKE_preview_image.hh"
|
||||||
#include "BKE_texture.h"
|
#include "BKE_texture.h"
|
||||||
|
|
||||||
|
#include "AS_asset_library.h"
|
||||||
|
|
||||||
#include "IMB_colormanagement.h"
|
#include "IMB_colormanagement.h"
|
||||||
#include "IMB_imbuf.h"
|
#include "IMB_imbuf.h"
|
||||||
#include "IMB_imbuf_types.h"
|
#include "IMB_imbuf_types.h"
|
||||||
@ -376,39 +382,6 @@ static void brush_blend_read_after_liblink(BlendLibReader * /*reader*/, ID *id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int brush_undo_preserve_cb(LibraryIDLinkCallbackData *cb_data)
|
|
||||||
{
|
|
||||||
BlendLibReader *reader = (BlendLibReader *)cb_data->user_data;
|
|
||||||
ID *self_id = cb_data->self_id;
|
|
||||||
ID *id_old = *cb_data->id_pointer;
|
|
||||||
/* Old data has not been remapped to new values of the pointers, if we want to keep the old
|
|
||||||
* pointer here we need its new address. */
|
|
||||||
ID *id_old_new = id_old != nullptr ? BLO_read_get_new_id_address(
|
|
||||||
reader, self_id, ID_IS_LINKED(self_id), id_old) :
|
|
||||||
nullptr;
|
|
||||||
BLI_assert(id_old_new == nullptr || ELEM(id_old, id_old_new, id_old_new->orig_id));
|
|
||||||
if (cb_data->cb_flag & IDWALK_CB_USER) {
|
|
||||||
id_us_plus_no_lib(id_old_new);
|
|
||||||
id_us_min(id_old);
|
|
||||||
}
|
|
||||||
*cb_data->id_pointer = id_old_new;
|
|
||||||
return IDWALK_RET_NOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void brush_undo_preserve(BlendLibReader *reader, ID *id_new, ID *id_old)
|
|
||||||
{
|
|
||||||
/* Whole Brush is preserved across undo-steps. */
|
|
||||||
BKE_lib_id_swap(nullptr, id_new, id_old, false, 0);
|
|
||||||
|
|
||||||
/* `id_new` now has content from `id_old`, we need to ensure those old ID pointers are valid.
|
|
||||||
* NOTE: Since we want to re-use all old pointers here, code is much simpler than for Scene. */
|
|
||||||
BKE_library_foreach_ID_link(nullptr, id_new, brush_undo_preserve_cb, reader, IDWALK_NOP);
|
|
||||||
|
|
||||||
/* NOTE: We do not swap IDProperties, as dealing with potential ID pointers in those would be
|
|
||||||
* fairly delicate. */
|
|
||||||
std::swap(id_new->properties, id_old->properties);
|
|
||||||
}
|
|
||||||
|
|
||||||
IDTypeInfo IDType_ID_BR = {
|
IDTypeInfo IDType_ID_BR = {
|
||||||
/*id_code*/ ID_BR,
|
/*id_code*/ ID_BR,
|
||||||
/*id_filter*/ FILTER_ID_BR,
|
/*id_filter*/ FILTER_ID_BR,
|
||||||
@ -417,7 +390,7 @@ IDTypeInfo IDType_ID_BR = {
|
|||||||
/*name*/ "Brush",
|
/*name*/ "Brush",
|
||||||
/*name_plural*/ N_("brushes"),
|
/*name_plural*/ N_("brushes"),
|
||||||
/*translation_context*/ BLT_I18NCONTEXT_ID_BRUSH,
|
/*translation_context*/ BLT_I18NCONTEXT_ID_BRUSH,
|
||||||
/*flags*/ IDTYPE_FLAGS_NO_ANIMDATA,
|
/*flags*/ IDTYPE_FLAGS_NO_ANIMDATA | IDTYPE_FLAGS_NO_MEMFILE_UNDO,
|
||||||
/*asset_type_info*/ nullptr,
|
/*asset_type_info*/ nullptr,
|
||||||
|
|
||||||
/*init_data*/ brush_init_data,
|
/*init_data*/ brush_init_data,
|
||||||
@ -433,7 +406,7 @@ IDTypeInfo IDType_ID_BR = {
|
|||||||
/*blend_read_data*/ brush_blend_read_data,
|
/*blend_read_data*/ brush_blend_read_data,
|
||||||
/*blend_read_after_liblink*/ brush_blend_read_after_liblink,
|
/*blend_read_after_liblink*/ brush_blend_read_after_liblink,
|
||||||
|
|
||||||
/*blend_read_undo_preserve*/ brush_undo_preserve,
|
/*blend_read_undo_preserve*/ nullptr,
|
||||||
|
|
||||||
/*lib_override_apply_post*/ nullptr,
|
/*lib_override_apply_post*/ nullptr,
|
||||||
};
|
};
|
||||||
@ -510,6 +483,63 @@ static void brush_defaults(Brush *brush)
|
|||||||
#undef FROM_DEFAULT_PTR
|
#undef FROM_DEFAULT_PTR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Brush *BKE_brush_asset_runtime_ensure(Main *bmain, const AssetWeakReference *brush_asset_reference)
|
||||||
|
{
|
||||||
|
BLI_assert(brush_asset_reference != nullptr);
|
||||||
|
|
||||||
|
char asset_full_path_buffer[FILE_MAX_LIBEXTRA];
|
||||||
|
char *asset_lib_path, *asset_group, *asset_name;
|
||||||
|
|
||||||
|
AS_asset_full_path_explode_from_weak_ref(
|
||||||
|
brush_asset_reference, asset_full_path_buffer, &asset_lib_path, &asset_group, &asset_name);
|
||||||
|
|
||||||
|
if (asset_lib_path == nullptr && asset_group == nullptr && asset_name == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
BLI_assert(STREQ(asset_group, IDType_ID_BR.name));
|
||||||
|
BLI_assert(asset_name != nullptr);
|
||||||
|
|
||||||
|
/* If the weakreference resolves to a null library path, assume that we are in local asset case.
|
||||||
|
*/
|
||||||
|
if (asset_lib_path == nullptr) {
|
||||||
|
Brush *local_brush_asset = reinterpret_cast<Brush *>(
|
||||||
|
BLI_findstring(&bmain->brushes, asset_name, offsetof(ID, name) + 2));
|
||||||
|
|
||||||
|
if (local_brush_asset == nullptr || !ID_IS_ASSET(local_brush_asset)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return local_brush_asset;
|
||||||
|
}
|
||||||
|
|
||||||
|
LibraryLink_Params lapp_parameters = {nullptr};
|
||||||
|
lapp_parameters.bmain = bmain;
|
||||||
|
BlendfileLinkAppendContext *lapp_context = BKE_blendfile_link_append_context_new(
|
||||||
|
&lapp_parameters);
|
||||||
|
BKE_blendfile_link_append_context_flag_set(lapp_context, BLO_LIBLINK_FORCE_INDIRECT, true);
|
||||||
|
BKE_blendfile_link_append_context_flag_set(lapp_context, FILE_LINK, true);
|
||||||
|
|
||||||
|
BKE_blendfile_link_append_context_library_add(lapp_context, asset_lib_path, nullptr);
|
||||||
|
|
||||||
|
BlendfileLinkAppendContextItem *lapp_item = BKE_blendfile_link_append_context_item_add(
|
||||||
|
lapp_context, asset_name, ID_BR, nullptr);
|
||||||
|
BKE_blendfile_link_append_context_item_library_index_enable(lapp_context, lapp_item, 0);
|
||||||
|
|
||||||
|
BKE_blendfile_link(lapp_context, nullptr);
|
||||||
|
BKE_blendfile_override(
|
||||||
|
lapp_context,
|
||||||
|
static_cast<eBKELibLinkOverride>(BKE_LIBLINK_OVERRIDE_USE_EXISTING_LIBOVERRIDES |
|
||||||
|
BKE_LIBLINK_OVERRIDE_CREATE_RUNTIME),
|
||||||
|
nullptr);
|
||||||
|
|
||||||
|
Brush *liboverride_brush = reinterpret_cast<Brush *>(
|
||||||
|
BKE_blendfile_link_append_context_item_liboverrideid_get(lapp_context, lapp_item));
|
||||||
|
|
||||||
|
BKE_blendfile_link_append_context_free(lapp_context);
|
||||||
|
|
||||||
|
return liboverride_brush;
|
||||||
|
}
|
||||||
|
|
||||||
/* Datablock add/copy/free/make_local */
|
/* Datablock add/copy/free/make_local */
|
||||||
|
|
||||||
Brush *BKE_brush_add(Main *bmain, const char *name, const eObjectMode ob_mode)
|
Brush *BKE_brush_add(Main *bmain, const char *name, const eObjectMode ob_mode)
|
||||||
|
@ -362,6 +362,41 @@ bool BKE_lib_override_library_is_system_defined(const Main *bmain, const ID *id)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int BKE_lib_override_user_edited_from_library_count(Main *bmain,
|
||||||
|
const short id_type,
|
||||||
|
Library *library,
|
||||||
|
ReportList *r_reports)
|
||||||
|
{
|
||||||
|
ListBase *lb = which_libbase(bmain, id_type);
|
||||||
|
int num_user_edited = 0;
|
||||||
|
|
||||||
|
for (ID *id_iter = static_cast<ID *>(lb->first); id_iter != nullptr;
|
||||||
|
id_iter = static_cast<ID *>(id_iter->next))
|
||||||
|
{
|
||||||
|
if (ID_IS_LINKED(id_iter)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!ID_IS_OVERRIDE_LIBRARY(id_iter)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (id_iter->override_library->reference->lib != library) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BKE_lib_override_library_is_user_edited(id_iter)) {
|
||||||
|
/* NOTE: If changes have been saved in a draft, then the local override is based on said
|
||||||
|
* draft (using the linked ID from the draft file as reference), so there should be no user
|
||||||
|
* edited changes anymore. */
|
||||||
|
num_user_edited++;
|
||||||
|
if (r_reports) {
|
||||||
|
BKE_report(r_reports, RPT_INFO, id_iter->name + 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return num_user_edited;
|
||||||
|
}
|
||||||
|
|
||||||
bool BKE_lib_override_library_property_is_animated(
|
bool BKE_lib_override_library_property_is_animated(
|
||||||
const ID *id,
|
const ID *id,
|
||||||
const IDOverrideLibraryProperty *liboverride_prop,
|
const IDOverrideLibraryProperty *liboverride_prop,
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include "MEM_guardedalloc.h"
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
|
#include "DNA_asset_types.h"
|
||||||
#include "DNA_brush_types.h"
|
#include "DNA_brush_types.h"
|
||||||
#include "DNA_defaults.h"
|
#include "DNA_defaults.h"
|
||||||
#include "DNA_gpencil_legacy_types.h"
|
#include "DNA_gpencil_legacy_types.h"
|
||||||
@ -37,6 +38,7 @@
|
|||||||
|
|
||||||
#include "BLT_translation.h"
|
#include "BLT_translation.h"
|
||||||
|
|
||||||
|
#include "BKE_asset.hh"
|
||||||
#include "BKE_attribute.h"
|
#include "BKE_attribute.h"
|
||||||
#include "BKE_attribute.hh"
|
#include "BKE_attribute.hh"
|
||||||
#include "BKE_brush.hh"
|
#include "BKE_brush.hh"
|
||||||
@ -312,7 +314,7 @@ void BKE_paint_reset_overlay_invalid(ePaintOverlayControlFlags flag)
|
|||||||
overlay_flags &= ~(flag);
|
overlay_flags &= ~(flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BKE_paint_ensure_from_paintmode(Scene *sce, ePaintMode mode)
|
bool BKE_paint_ensure_from_paintmode(Main *bmain, Scene *sce, ePaintMode mode)
|
||||||
{
|
{
|
||||||
ToolSettings *ts = sce->toolsettings;
|
ToolSettings *ts = sce->toolsettings;
|
||||||
Paint **paint_ptr = nullptr;
|
Paint **paint_ptr = nullptr;
|
||||||
@ -357,7 +359,7 @@ bool BKE_paint_ensure_from_paintmode(Scene *sce, ePaintMode mode)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (paint_ptr) {
|
if (paint_ptr) {
|
||||||
BKE_paint_ensure(ts, paint_ptr);
|
BKE_paint_ensure(bmain, ts, paint_ptr);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -671,6 +673,50 @@ void BKE_paint_brush_set(Paint *p, Brush *br)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void paint_brush_asset_update(Paint *p,
|
||||||
|
Brush *br,
|
||||||
|
AssetWeakReference *brush_asset_reference)
|
||||||
|
{
|
||||||
|
if (p->brush_asset_reference != nullptr) {
|
||||||
|
BKE_asset_weak_reference_free(&p->brush_asset_reference);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (br == nullptr || br != p->brush || !ID_IS_OVERRIDE_LIBRARY_REAL(p->brush) ||
|
||||||
|
!(ID_IS_ASSET(p->brush) || ID_IS_ASSET(p->brush->id.override_library->reference)))
|
||||||
|
{
|
||||||
|
BKE_asset_weak_reference_free(&brush_asset_reference);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
p->brush_asset_reference = brush_asset_reference;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BKE_paint_brush_asset_set(Paint *p, Brush *br, AssetWeakReference *weak_asset_reference)
|
||||||
|
{
|
||||||
|
BKE_paint_brush_set(p, br);
|
||||||
|
paint_brush_asset_update(p, br, weak_asset_reference);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BKE_paint_brush_asset_restore(Main *bmain, Paint *p)
|
||||||
|
{
|
||||||
|
if (p->brush != nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p->brush_asset_reference == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetWeakReference *brush_asset_reference = p->brush_asset_reference;
|
||||||
|
p->brush_asset_reference = nullptr;
|
||||||
|
|
||||||
|
Brush *brush_asset = BKE_brush_asset_runtime_ensure(bmain, brush_asset_reference);
|
||||||
|
|
||||||
|
/* Will either re-assign the brush_asset_reference to `p`, or free it if loading a brush ID from
|
||||||
|
* it failed. */
|
||||||
|
BKE_paint_brush_asset_set(p, brush_asset, brush_asset_reference);
|
||||||
|
}
|
||||||
|
|
||||||
void BKE_paint_runtime_init(const ToolSettings *ts, Paint *paint)
|
void BKE_paint_runtime_init(const ToolSettings *ts, Paint *paint)
|
||||||
{
|
{
|
||||||
if (paint == &ts->imapaint.paint) {
|
if (paint == &ts->imapaint.paint) {
|
||||||
@ -1096,7 +1142,7 @@ eObjectMode BKE_paint_object_mode_from_paintmode(ePaintMode mode)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BKE_paint_ensure(ToolSettings *ts, Paint **r_paint)
|
bool BKE_paint_ensure(Main *bmain, ToolSettings *ts, Paint **r_paint)
|
||||||
{
|
{
|
||||||
Paint *paint = nullptr;
|
Paint *paint = nullptr;
|
||||||
if (*r_paint) {
|
if (*r_paint) {
|
||||||
@ -1130,6 +1176,7 @@ bool BKE_paint_ensure(ToolSettings *ts, Paint **r_paint)
|
|||||||
BLI_assert(paint_test.runtime.tool_offset == (*r_paint)->runtime.tool_offset);
|
BLI_assert(paint_test.runtime.tool_offset == (*r_paint)->runtime.tool_offset);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
BKE_paint_brush_asset_restore(bmain, *r_paint);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1177,6 +1224,7 @@ bool BKE_paint_ensure(ToolSettings *ts, Paint **r_paint)
|
|||||||
*r_paint = paint;
|
*r_paint = paint;
|
||||||
|
|
||||||
BKE_paint_runtime_init(ts, paint);
|
BKE_paint_runtime_init(ts, paint);
|
||||||
|
BKE_paint_brush_asset_restore(bmain, paint);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1186,7 +1234,7 @@ void BKE_paint_init(Main *bmain, Scene *sce, ePaintMode mode, const uchar col[3]
|
|||||||
UnifiedPaintSettings *ups = &sce->toolsettings->unified_paint_settings;
|
UnifiedPaintSettings *ups = &sce->toolsettings->unified_paint_settings;
|
||||||
Paint *paint = BKE_paint_get_active_from_paintmode(sce, mode);
|
Paint *paint = BKE_paint_get_active_from_paintmode(sce, mode);
|
||||||
|
|
||||||
BKE_paint_ensure_from_paintmode(sce, mode);
|
BKE_paint_ensure_from_paintmode(bmain, sce, mode);
|
||||||
|
|
||||||
/* If there's no brush, create one */
|
/* If there's no brush, create one */
|
||||||
if (PAINT_MODE_HAS_BRUSH(mode)) {
|
if (PAINT_MODE_HAS_BRUSH(mode)) {
|
||||||
@ -1216,6 +1264,9 @@ void BKE_paint_free(Paint *paint)
|
|||||||
{
|
{
|
||||||
BKE_curvemapping_free(paint->cavity_curve);
|
BKE_curvemapping_free(paint->cavity_curve);
|
||||||
MEM_SAFE_FREE(paint->tool_slots);
|
MEM_SAFE_FREE(paint->tool_slots);
|
||||||
|
if (paint->brush_asset_reference != nullptr) {
|
||||||
|
BKE_asset_weak_reference_free(&paint->brush_asset_reference);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BKE_paint_copy(Paint *src, Paint *tar, const int flag)
|
void BKE_paint_copy(Paint *src, Paint *tar, const int flag)
|
||||||
@ -1224,6 +1275,8 @@ void BKE_paint_copy(Paint *src, Paint *tar, const int flag)
|
|||||||
tar->cavity_curve = BKE_curvemapping_copy(src->cavity_curve);
|
tar->cavity_curve = BKE_curvemapping_copy(src->cavity_curve);
|
||||||
tar->tool_slots = static_cast<PaintToolSlot *>(MEM_dupallocN(src->tool_slots));
|
tar->tool_slots = static_cast<PaintToolSlot *>(MEM_dupallocN(src->tool_slots));
|
||||||
|
|
||||||
|
tar->brush_asset_reference = BKE_asset_weak_reference_copy(src->brush_asset_reference);
|
||||||
|
|
||||||
if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
|
if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
|
||||||
id_us_plus((ID *)tar->brush);
|
id_us_plus((ID *)tar->brush);
|
||||||
id_us_plus((ID *)tar->palette);
|
id_us_plus((ID *)tar->palette);
|
||||||
@ -1252,6 +1305,9 @@ void BKE_paint_blend_write(BlendWriter *writer, Paint *p)
|
|||||||
if (p->cavity_curve) {
|
if (p->cavity_curve) {
|
||||||
BKE_curvemapping_blend_write(writer, p->cavity_curve);
|
BKE_curvemapping_blend_write(writer, p->cavity_curve);
|
||||||
}
|
}
|
||||||
|
if (p->brush_asset_reference) {
|
||||||
|
BKE_asset_weak_reference_write(writer, p->brush_asset_reference);
|
||||||
|
}
|
||||||
BLO_write_struct_array(writer, PaintToolSlot, p->tool_slots_len, p->tool_slots);
|
BLO_write_struct_array(writer, PaintToolSlot, p->tool_slots_len, p->tool_slots);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1269,6 +1325,11 @@ void BKE_paint_blend_read_data(BlendDataReader *reader, const Scene *scene, Pain
|
|||||||
BKE_paint_cavity_curve_preset(p, CURVE_PRESET_LINE);
|
BKE_paint_cavity_curve_preset(p, CURVE_PRESET_LINE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BLO_read_data_address(reader, &p->brush_asset_reference);
|
||||||
|
if (p->brush_asset_reference) {
|
||||||
|
BKE_asset_weak_reference_read(reader, p->brush_asset_reference);
|
||||||
|
}
|
||||||
|
|
||||||
BLO_read_data_address(reader, &p->tool_slots);
|
BLO_read_data_address(reader, &p->tool_slots);
|
||||||
|
|
||||||
/* Workaround for invalid data written in older versions. */
|
/* Workaround for invalid data written in older versions. */
|
||||||
@ -2069,9 +2130,9 @@ void BKE_sculpt_mask_layers_ensure(Depsgraph *depsgraph,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BKE_sculpt_toolsettings_data_ensure(Scene *scene)
|
void BKE_sculpt_toolsettings_data_ensure(Main *bmain, Scene *scene)
|
||||||
{
|
{
|
||||||
BKE_paint_ensure(scene->toolsettings, (Paint **)&scene->toolsettings->sculpt);
|
BKE_paint_ensure(bmain, scene->toolsettings, (Paint **)&scene->toolsettings->sculpt);
|
||||||
|
|
||||||
Sculpt *sd = scene->toolsettings->sculpt;
|
Sculpt *sd = scene->toolsettings->sculpt;
|
||||||
|
|
||||||
|
@ -1017,6 +1017,9 @@ static void scene_foreach_path(ID *id, BPathForeachPathData *bpath_data)
|
|||||||
if (scene->ed != nullptr) {
|
if (scene->ed != nullptr) {
|
||||||
SEQ_for_each_callback(&scene->ed->seqbase, seq_foreach_path_callback, bpath_data);
|
SEQ_for_each_callback(&scene->ed->seqbase, seq_foreach_path_callback, bpath_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO: Also handle `asset_weak_reference` here? Probably not, conceptually this is not a file
|
||||||
|
* path. */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scene_blend_write(BlendWriter *writer, ID *id, const void *id_address)
|
static void scene_blend_write(BlendWriter *writer, ID *id, const void *id_address)
|
||||||
|
@ -2881,10 +2881,10 @@ void do_versions_after_linking_280(FileData *fd, Main *bmain)
|
|||||||
ToolSettings *ts = scene->toolsettings;
|
ToolSettings *ts = scene->toolsettings;
|
||||||
|
|
||||||
/* Ensure new Paint modes. */
|
/* Ensure new Paint modes. */
|
||||||
BKE_paint_ensure_from_paintmode(scene, PAINT_MODE_GPENCIL);
|
BKE_paint_ensure_from_paintmode(bmain, scene, PAINT_MODE_GPENCIL);
|
||||||
BKE_paint_ensure_from_paintmode(scene, PAINT_MODE_VERTEX_GPENCIL);
|
BKE_paint_ensure_from_paintmode(bmain, scene, PAINT_MODE_VERTEX_GPENCIL);
|
||||||
BKE_paint_ensure_from_paintmode(scene, PAINT_MODE_SCULPT_GPENCIL);
|
BKE_paint_ensure_from_paintmode(bmain, scene, PAINT_MODE_SCULPT_GPENCIL);
|
||||||
BKE_paint_ensure_from_paintmode(scene, PAINT_MODE_WEIGHT_GPENCIL);
|
BKE_paint_ensure_from_paintmode(bmain, scene, PAINT_MODE_WEIGHT_GPENCIL);
|
||||||
|
|
||||||
/* Set default Draw brush. */
|
/* Set default Draw brush. */
|
||||||
if (brush != nullptr) {
|
if (brush != nullptr) {
|
||||||
@ -2925,9 +2925,9 @@ void do_versions_after_linking_280(FileData *fd, Main *bmain)
|
|||||||
/* Reset all grease pencil brushes. */
|
/* Reset all grease pencil brushes. */
|
||||||
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
||||||
/* Ensure new Paint modes. */
|
/* Ensure new Paint modes. */
|
||||||
BKE_paint_ensure_from_paintmode(scene, PAINT_MODE_VERTEX_GPENCIL);
|
BKE_paint_ensure_from_paintmode(bmain, scene, PAINT_MODE_VERTEX_GPENCIL);
|
||||||
BKE_paint_ensure_from_paintmode(scene, PAINT_MODE_SCULPT_GPENCIL);
|
BKE_paint_ensure_from_paintmode(bmain, scene, PAINT_MODE_SCULPT_GPENCIL);
|
||||||
BKE_paint_ensure_from_paintmode(scene, PAINT_MODE_WEIGHT_GPENCIL);
|
BKE_paint_ensure_from_paintmode(bmain, scene, PAINT_MODE_WEIGHT_GPENCIL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -494,9 +494,9 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Ensure new Paint modes. */
|
/* Ensure new Paint modes. */
|
||||||
BKE_paint_ensure_from_paintmode(scene, PAINT_MODE_VERTEX_GPENCIL);
|
BKE_paint_ensure_from_paintmode(bmain, scene, PAINT_MODE_VERTEX_GPENCIL);
|
||||||
BKE_paint_ensure_from_paintmode(scene, PAINT_MODE_SCULPT_GPENCIL);
|
BKE_paint_ensure_from_paintmode(bmain, scene, PAINT_MODE_SCULPT_GPENCIL);
|
||||||
BKE_paint_ensure_from_paintmode(scene, PAINT_MODE_WEIGHT_GPENCIL);
|
BKE_paint_ensure_from_paintmode(bmain, scene, PAINT_MODE_WEIGHT_GPENCIL);
|
||||||
|
|
||||||
/* Enable cursor. */
|
/* Enable cursor. */
|
||||||
if (ts->gp_paint) {
|
if (ts->gp_paint) {
|
||||||
|
@ -43,6 +43,10 @@ void ED_asset_handle_get_full_library_path(
|
|||||||
/* `1024` for #FILE_MAX,
|
/* `1024` for #FILE_MAX,
|
||||||
* rely on warnings to let us know if this gets out of sync. */
|
* rely on warnings to let us know if this gets out of sync. */
|
||||||
char r_full_lib_path[1024]);
|
char r_full_lib_path[1024]);
|
||||||
|
void ED_asset_handle_get_full_path(const AssetHandle *asset_handle,
|
||||||
|
/* `1024 + 66` for #FILE_MAX_LIBEXTRA,
|
||||||
|
* rely on warnings to let us know if this gets out of sync. */
|
||||||
|
char r_full_lib_path[1024 + 66]);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -57,3 +57,16 @@ void ED_asset_handle_get_full_library_path(const AssetHandle *asset_handle,
|
|||||||
|
|
||||||
BLI_strncpy(r_full_lib_path, library_path.c_str(), FILE_MAX);
|
BLI_strncpy(r_full_lib_path, library_path.c_str(), FILE_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ED_asset_handle_get_full_path(const AssetHandle *asset_handle,
|
||||||
|
char r_full_lib_path[FILE_MAX_LIBEXTRA])
|
||||||
|
{
|
||||||
|
*r_full_lib_path = '\0';
|
||||||
|
|
||||||
|
std::string library_path = asset_handle->file_data->asset->get_identifier().full_path();
|
||||||
|
if (library_path.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BLI_strncpy(r_full_lib_path, library_path.c_str(), FILE_MAX);
|
||||||
|
}
|
||||||
|
@ -396,8 +396,8 @@ static int gpencil_paintmode_toggle_exec(bContext *C, wmOperator *op)
|
|||||||
if (mode == OB_MODE_PAINT_GPENCIL_LEGACY) {
|
if (mode == OB_MODE_PAINT_GPENCIL_LEGACY) {
|
||||||
/* Be sure we have brushes and Paint settings.
|
/* Be sure we have brushes and Paint settings.
|
||||||
* Need Draw and Vertex (used for Tint). */
|
* Need Draw and Vertex (used for Tint). */
|
||||||
BKE_paint_ensure(ts, (Paint **)&ts->gp_paint);
|
BKE_paint_ensure(bmain, ts, (Paint **)&ts->gp_paint);
|
||||||
BKE_paint_ensure(ts, (Paint **)&ts->gp_vertexpaint);
|
BKE_paint_ensure(bmain, ts, (Paint **)&ts->gp_vertexpaint);
|
||||||
|
|
||||||
BKE_brush_gpencil_paint_presets(bmain, ts, false);
|
BKE_brush_gpencil_paint_presets(bmain, ts, false);
|
||||||
|
|
||||||
@ -511,7 +511,7 @@ static int gpencil_sculptmode_toggle_exec(bContext *C, wmOperator *op)
|
|||||||
|
|
||||||
if (mode == OB_MODE_SCULPT_GPENCIL_LEGACY) {
|
if (mode == OB_MODE_SCULPT_GPENCIL_LEGACY) {
|
||||||
/* Be sure we have brushes. */
|
/* Be sure we have brushes. */
|
||||||
BKE_paint_ensure(ts, (Paint **)&ts->gp_sculptpaint);
|
BKE_paint_ensure(bmain, ts, (Paint **)&ts->gp_sculptpaint);
|
||||||
|
|
||||||
const bool reset_mode = (ts->gp_sculptpaint->paint.brush == nullptr);
|
const bool reset_mode = (ts->gp_sculptpaint->paint.brush == nullptr);
|
||||||
BKE_brush_gpencil_sculpt_presets(bmain, ts, reset_mode);
|
BKE_brush_gpencil_sculpt_presets(bmain, ts, reset_mode);
|
||||||
@ -625,7 +625,7 @@ static int gpencil_weightmode_toggle_exec(bContext *C, wmOperator *op)
|
|||||||
|
|
||||||
if (mode == OB_MODE_WEIGHT_GPENCIL_LEGACY) {
|
if (mode == OB_MODE_WEIGHT_GPENCIL_LEGACY) {
|
||||||
/* Be sure we have brushes. */
|
/* Be sure we have brushes. */
|
||||||
BKE_paint_ensure(ts, (Paint **)&ts->gp_weightpaint);
|
BKE_paint_ensure(bmain, ts, (Paint **)&ts->gp_weightpaint);
|
||||||
|
|
||||||
const bool reset_mode = (ts->gp_weightpaint->paint.brush == nullptr);
|
const bool reset_mode = (ts->gp_weightpaint->paint.brush == nullptr);
|
||||||
BKE_brush_gpencil_weight_presets(bmain, ts, reset_mode);
|
BKE_brush_gpencil_weight_presets(bmain, ts, reset_mode);
|
||||||
@ -732,8 +732,8 @@ static int gpencil_vertexmode_toggle_exec(bContext *C, wmOperator *op)
|
|||||||
if (mode == OB_MODE_VERTEX_GPENCIL_LEGACY) {
|
if (mode == OB_MODE_VERTEX_GPENCIL_LEGACY) {
|
||||||
/* Be sure we have brushes.
|
/* Be sure we have brushes.
|
||||||
* Need Draw as well (used for Palettes). */
|
* Need Draw as well (used for Palettes). */
|
||||||
BKE_paint_ensure(ts, (Paint **)&ts->gp_paint);
|
BKE_paint_ensure(bmain, ts, (Paint **)&ts->gp_paint);
|
||||||
BKE_paint_ensure(ts, (Paint **)&ts->gp_vertexpaint);
|
BKE_paint_ensure(bmain, ts, (Paint **)&ts->gp_vertexpaint);
|
||||||
|
|
||||||
const bool reset_mode = (ts->gp_vertexpaint->paint.brush == nullptr);
|
const bool reset_mode = (ts->gp_vertexpaint->paint.brush == nullptr);
|
||||||
BKE_brush_gpencil_vertex_presets(bmain, ts, reset_mode);
|
BKE_brush_gpencil_vertex_presets(bmain, ts, reset_mode);
|
||||||
|
@ -1428,7 +1428,7 @@ void ED_gpencil_add_defaults(bContext *C, Object *ob)
|
|||||||
Main *bmain = CTX_data_main(C);
|
Main *bmain = CTX_data_main(C);
|
||||||
ToolSettings *ts = CTX_data_tool_settings(C);
|
ToolSettings *ts = CTX_data_tool_settings(C);
|
||||||
|
|
||||||
BKE_paint_ensure(ts, (Paint **)&ts->gp_paint);
|
BKE_paint_ensure(bmain, ts, (Paint **)&ts->gp_paint);
|
||||||
Paint *paint = &ts->gp_paint->paint;
|
Paint *paint = &ts->gp_paint->paint;
|
||||||
/* if not exist, create a new one */
|
/* if not exist, create a new one */
|
||||||
if ((paint->brush == nullptr) || (paint->brush->gpencil_settings == nullptr)) {
|
if ((paint->brush == nullptr) || (paint->brush->gpencil_settings == nullptr)) {
|
||||||
|
@ -4,8 +4,12 @@
|
|||||||
|
|
||||||
set(INC
|
set(INC
|
||||||
../include
|
../include
|
||||||
|
../asset
|
||||||
../uvedit
|
../uvedit
|
||||||
|
../../asset_system
|
||||||
../../blenkernel
|
../../blenkernel
|
||||||
|
../../blenlib
|
||||||
|
../../blenloader
|
||||||
../../blentranslation
|
../../blentranslation
|
||||||
../../bmesh
|
../../bmesh
|
||||||
../../depsgraph
|
../../depsgraph
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
#include "BLI_utildefines.h"
|
#include "BLI_utildefines.h"
|
||||||
#include "BLI_vector_set.hh"
|
#include "BLI_vector_set.hh"
|
||||||
|
|
||||||
|
#include "BKE_asset.hh"
|
||||||
|
#include "BKE_blendfile.h"
|
||||||
#include "BKE_brush.hh"
|
#include "BKE_brush.hh"
|
||||||
#include "BKE_bvhutils.hh"
|
#include "BKE_bvhutils.hh"
|
||||||
#include "BKE_context.hh"
|
#include "BKE_context.hh"
|
||||||
@ -20,6 +22,7 @@
|
|||||||
#include "WM_message.hh"
|
#include "WM_message.hh"
|
||||||
#include "WM_toolsystem.h"
|
#include "WM_toolsystem.h"
|
||||||
|
|
||||||
|
#include "ED_asset_handle.h"
|
||||||
#include "ED_curves.hh"
|
#include "ED_curves.hh"
|
||||||
#include "ED_curves_sculpt.hh"
|
#include "ED_curves_sculpt.hh"
|
||||||
#include "ED_image.hh"
|
#include "ED_image.hh"
|
||||||
@ -28,6 +31,8 @@
|
|||||||
#include "ED_space_api.hh"
|
#include "ED_space_api.hh"
|
||||||
#include "ED_view3d.hh"
|
#include "ED_view3d.hh"
|
||||||
|
|
||||||
|
#include "AS_asset_representation.hh"
|
||||||
|
|
||||||
#include "DEG_depsgraph.hh"
|
#include "DEG_depsgraph.hh"
|
||||||
#include "DEG_depsgraph_query.hh"
|
#include "DEG_depsgraph_query.hh"
|
||||||
|
|
||||||
@ -283,7 +288,8 @@ static void curves_sculptmode_enter(bContext *C)
|
|||||||
wmMsgBus *mbus = CTX_wm_message_bus(C);
|
wmMsgBus *mbus = CTX_wm_message_bus(C);
|
||||||
|
|
||||||
Object *ob = CTX_data_active_object(C);
|
Object *ob = CTX_data_active_object(C);
|
||||||
BKE_paint_ensure(scene->toolsettings, (Paint **)&scene->toolsettings->curves_sculpt);
|
BKE_paint_ensure(
|
||||||
|
CTX_data_main(C), scene->toolsettings, (Paint **)&scene->toolsettings->curves_sculpt);
|
||||||
CurvesSculpt *curves_sculpt = scene->toolsettings->curves_sculpt;
|
CurvesSculpt *curves_sculpt = scene->toolsettings->curves_sculpt;
|
||||||
|
|
||||||
ob->mode = OB_MODE_SCULPT_CURVES;
|
ob->mode = OB_MODE_SCULPT_CURVES;
|
||||||
@ -1167,6 +1173,45 @@ static void SCULPT_CURVES_OT_min_distance_edit(wmOperatorType *ot)
|
|||||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_DEPENDS_ON_CURSOR;
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_DEPENDS_ON_CURSOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static int brush_asset_select_exec(bContext *C, wmOperator * /*op*/)
|
||||||
|
{
|
||||||
|
blender::asset_system::AssetRepresentation *asset = CTX_wm_asset(C);
|
||||||
|
if (!asset) {
|
||||||
|
return OPERATOR_CANCELLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetWeakReference *brush_asset_reference = asset->make_weak_reference();
|
||||||
|
Brush *brush = BKE_brush_asset_runtime_ensure(CTX_data_main(C), brush_asset_reference);
|
||||||
|
|
||||||
|
ToolSettings *tool_settings = CTX_data_tool_settings(C);
|
||||||
|
/* Either takes ownership of the brush_asset_reference, or frees it. */
|
||||||
|
BKE_paint_brush_asset_set(&tool_settings->curves_sculpt->paint, brush, brush_asset_reference);
|
||||||
|
|
||||||
|
return OPERATOR_FINISHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This operator currently covers both cases, the File/Asset Browser file list and the asset list
|
||||||
|
* used for the asset-view template. Once the asset list design is used by the Asset Browser, this
|
||||||
|
* can be simplified to just that case.
|
||||||
|
*/
|
||||||
|
static void SCULPT_CURVES_OT_brush_asset_select(struct wmOperatorType *ot)
|
||||||
|
{
|
||||||
|
/* identifiers */
|
||||||
|
ot->name = "Select Brush Asset";
|
||||||
|
ot->description = "Select a brush asset as currently sculpt/paint tool - TESTING PURPOSE ONLY";
|
||||||
|
ot->idname = "SCULPT_CURVES_OT_brush_asset_select";
|
||||||
|
|
||||||
|
/* api callbacks */
|
||||||
|
ot->exec = brush_asset_select_exec;
|
||||||
|
ot->poll = CURVES_SCULPT_mode_poll;
|
||||||
|
|
||||||
|
ot->prop = RNA_def_string(
|
||||||
|
ot->srna, "name", nullptr, MAX_NAME, "Brush Name", "name of the brush asset to select");
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace blender::ed::sculpt_paint
|
} // namespace blender::ed::sculpt_paint
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
@ -1181,6 +1226,8 @@ void ED_operatortypes_sculpt_curves()
|
|||||||
WM_operatortype_append(SCULPT_CURVES_OT_select_random);
|
WM_operatortype_append(SCULPT_CURVES_OT_select_random);
|
||||||
WM_operatortype_append(SCULPT_CURVES_OT_select_grow);
|
WM_operatortype_append(SCULPT_CURVES_OT_select_grow);
|
||||||
WM_operatortype_append(SCULPT_CURVES_OT_min_distance_edit);
|
WM_operatortype_append(SCULPT_CURVES_OT_min_distance_edit);
|
||||||
|
|
||||||
|
WM_operatortype_append(SCULPT_CURVES_OT_brush_asset_select);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
@ -228,7 +228,7 @@ static void grease_pencil_draw_mode_enter(bContext *C)
|
|||||||
|
|
||||||
Object *ob = CTX_data_active_object(C);
|
Object *ob = CTX_data_active_object(C);
|
||||||
GpPaint *grease_pencil_paint = scene->toolsettings->gp_paint;
|
GpPaint *grease_pencil_paint = scene->toolsettings->gp_paint;
|
||||||
BKE_paint_ensure(scene->toolsettings, (Paint **)&grease_pencil_paint);
|
BKE_paint_ensure(CTX_data_main(C), scene->toolsettings, (Paint **)&grease_pencil_paint);
|
||||||
|
|
||||||
ob->mode = OB_MODE_PAINT_GREASE_PENCIL;
|
ob->mode = OB_MODE_PAINT_GREASE_PENCIL;
|
||||||
|
|
||||||
|
@ -553,7 +553,8 @@ void get_brush_alpha_data(const Scene *scene,
|
|||||||
|
|
||||||
void init_stroke(Depsgraph *depsgraph, Object *ob);
|
void init_stroke(Depsgraph *depsgraph, Object *ob);
|
||||||
void init_session_data(const ToolSettings *ts, Object *ob);
|
void init_session_data(const ToolSettings *ts, Object *ob);
|
||||||
void init_session(Depsgraph *depsgraph, Scene *scene, Object *ob, eObjectMode object_mode);
|
void init_session(
|
||||||
|
Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob, eObjectMode object_mode);
|
||||||
|
|
||||||
Vector<PBVHNode *> pbvh_gather_generic(Object *ob, VPaint *wp, Sculpt *sd, Brush *brush);
|
Vector<PBVHNode *> pbvh_gather_generic(Object *ob, VPaint *wp, Sculpt *sd, Brush *brush);
|
||||||
|
|
||||||
|
@ -209,10 +209,11 @@ void init_stroke(Depsgraph *depsgraph, Object *ob)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Toggle operator for turning vertex paint mode on or off (copied from sculpt.cc) */
|
/* Toggle operator for turning vertex paint mode on or off (copied from sculpt.cc) */
|
||||||
void init_session(Depsgraph *depsgraph, Scene *scene, Object *ob, eObjectMode object_mode)
|
void init_session(
|
||||||
|
Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob, eObjectMode object_mode)
|
||||||
{
|
{
|
||||||
/* Create persistent sculpt mode data */
|
/* Create persistent sculpt mode data */
|
||||||
BKE_sculpt_toolsettings_data_ensure(scene);
|
BKE_sculpt_toolsettings_data_ensure(bmain, scene);
|
||||||
|
|
||||||
BLI_assert(ob->sculpt == nullptr);
|
BLI_assert(ob->sculpt == nullptr);
|
||||||
ob->sculpt = MEM_new<SculptSession>(__func__);
|
ob->sculpt = MEM_new<SculptSession>(__func__);
|
||||||
@ -336,7 +337,7 @@ void mode_enter_generic(
|
|||||||
const ePaintMode paint_mode = PAINT_MODE_VERTEX;
|
const ePaintMode paint_mode = PAINT_MODE_VERTEX;
|
||||||
ED_mesh_color_ensure(me, nullptr);
|
ED_mesh_color_ensure(me, nullptr);
|
||||||
|
|
||||||
BKE_paint_ensure(scene->toolsettings, (Paint **)&scene->toolsettings->vpaint);
|
BKE_paint_ensure(bmain, scene->toolsettings, (Paint **)&scene->toolsettings->vpaint);
|
||||||
Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode);
|
Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode);
|
||||||
ED_paint_cursor_start(paint, vertex_paint_poll);
|
ED_paint_cursor_start(paint, vertex_paint_poll);
|
||||||
BKE_paint_init(bmain, scene, paint_mode, PAINT_CURSOR_VERTEX_PAINT);
|
BKE_paint_init(bmain, scene, paint_mode, PAINT_CURSOR_VERTEX_PAINT);
|
||||||
@ -344,7 +345,7 @@ void mode_enter_generic(
|
|||||||
else if (mode_flag == OB_MODE_WEIGHT_PAINT) {
|
else if (mode_flag == OB_MODE_WEIGHT_PAINT) {
|
||||||
const ePaintMode paint_mode = PAINT_MODE_WEIGHT;
|
const ePaintMode paint_mode = PAINT_MODE_WEIGHT;
|
||||||
|
|
||||||
BKE_paint_ensure(scene->toolsettings, (Paint **)&scene->toolsettings->wpaint);
|
BKE_paint_ensure(bmain, scene->toolsettings, (Paint **)&scene->toolsettings->wpaint);
|
||||||
Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode);
|
Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode);
|
||||||
ED_paint_cursor_start(paint, weight_paint_poll);
|
ED_paint_cursor_start(paint, weight_paint_poll);
|
||||||
BKE_paint_init(bmain, scene, paint_mode, PAINT_CURSOR_WEIGHT_PAINT);
|
BKE_paint_init(bmain, scene, paint_mode, PAINT_CURSOR_WEIGHT_PAINT);
|
||||||
@ -366,7 +367,7 @@ void mode_enter_generic(
|
|||||||
BKE_sculptsession_free(ob);
|
BKE_sculptsession_free(ob);
|
||||||
}
|
}
|
||||||
|
|
||||||
vwpaint::init_session(depsgraph, scene, ob, mode_flag);
|
vwpaint::init_session(bmain, depsgraph, scene, ob, mode_flag);
|
||||||
|
|
||||||
/* Flush object mode. */
|
/* Flush object mode. */
|
||||||
DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
|
DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
|
||||||
|
@ -267,7 +267,7 @@ static void SCULPT_OT_symmetrize(wmOperatorType *ot)
|
|||||||
static void sculpt_init_session(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob)
|
static void sculpt_init_session(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob)
|
||||||
{
|
{
|
||||||
/* Create persistent sculpt mode data. */
|
/* Create persistent sculpt mode data. */
|
||||||
BKE_sculpt_toolsettings_data_ensure(scene);
|
BKE_sculpt_toolsettings_data_ensure(bmain, scene);
|
||||||
|
|
||||||
/* Create sculpt mode session data. */
|
/* Create sculpt mode session data. */
|
||||||
if (ob->sculpt != nullptr) {
|
if (ob->sculpt != nullptr) {
|
||||||
|
@ -948,6 +948,13 @@ typedef struct PaintToolSlot {
|
|||||||
typedef struct Paint {
|
typedef struct Paint {
|
||||||
struct Brush *brush;
|
struct Brush *brush;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A weak asset reference to the #brush, if not NULL.
|
||||||
|
* Used to attempt restoring the active brush from the AssetLibrary system, typically on
|
||||||
|
* file load.
|
||||||
|
*/
|
||||||
|
struct AssetWeakReference *brush_asset_reference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Each tool has its own active brush,
|
* Each tool has its own active brush,
|
||||||
* The currently active tool is defined by the current 'brush'.
|
* The currently active tool is defined by the current 'brush'.
|
||||||
|
@ -770,7 +770,12 @@ static void rna_Brush_reset_icon(Brush *br)
|
|||||||
|
|
||||||
static void rna_Brush_update(Main * /*bmain*/, Scene * /*scene*/, PointerRNA *ptr)
|
static void rna_Brush_update(Main * /*bmain*/, Scene * /*scene*/, PointerRNA *ptr)
|
||||||
{
|
{
|
||||||
Brush *br = (Brush *)ptr->data;
|
Brush *br = (Brush *)ptr->owner_id;
|
||||||
|
|
||||||
|
if (ID_IS_OVERRIDE_LIBRARY_REAL(&br->id)) {
|
||||||
|
br->id.tag |= LIB_TAG_LIBOVERRIDE_AUTOREFRESH;
|
||||||
|
}
|
||||||
|
|
||||||
WM_main_add_notifier(NC_BRUSH | NA_EDITED, br);
|
WM_main_add_notifier(NC_BRUSH | NA_EDITED, br);
|
||||||
// WM_main_add_notifier(NC_SPACE | ND_SPACE_VIEW3D, nullptr);
|
// WM_main_add_notifier(NC_SPACE | ND_SPACE_VIEW3D, nullptr);
|
||||||
}
|
}
|
||||||
@ -2146,14 +2151,18 @@ static void rna_def_curves_sculpt_options(BlenderRNA *brna)
|
|||||||
RNA_def_struct_sdna(srna, "BrushCurvesSculptSettings");
|
RNA_def_struct_sdna(srna, "BrushCurvesSculptSettings");
|
||||||
RNA_def_struct_ui_text(srna, "Curves Sculpt Brush Settings", "");
|
RNA_def_struct_ui_text(srna, "Curves Sculpt Brush Settings", "");
|
||||||
|
|
||||||
|
RNA_define_lib_overridable(true);
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "add_amount", PROP_INT, PROP_NONE);
|
prop = RNA_def_property(srna, "add_amount", PROP_INT, PROP_NONE);
|
||||||
RNA_def_property_range(prop, 1, INT32_MAX);
|
RNA_def_property_range(prop, 1, INT32_MAX);
|
||||||
RNA_def_property_ui_text(prop, "Count", "Number of curves added by the Add brush");
|
RNA_def_property_ui_text(prop, "Count", "Number of curves added by the Add brush");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "points_per_curve", PROP_INT, PROP_NONE);
|
prop = RNA_def_property(srna, "points_per_curve", PROP_INT, PROP_NONE);
|
||||||
RNA_def_property_range(prop, 2, INT32_MAX);
|
RNA_def_property_range(prop, 2, INT32_MAX);
|
||||||
RNA_def_property_ui_text(
|
RNA_def_property_ui_text(
|
||||||
prop, "Points per Curve", "Number of control points in a newly added curve");
|
prop, "Points per Curve", "Number of control points in a newly added curve");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "scale_uniform", PROP_BOOLEAN, PROP_NONE);
|
prop = RNA_def_property(srna, "scale_uniform", PROP_BOOLEAN, PROP_NONE);
|
||||||
RNA_def_property_boolean_sdna(prop, nullptr, "flag", BRUSH_CURVES_SCULPT_FLAG_SCALE_UNIFORM);
|
RNA_def_property_boolean_sdna(prop, nullptr, "flag", BRUSH_CURVES_SCULPT_FLAG_SCALE_UNIFORM);
|
||||||
@ -2161,17 +2170,20 @@ static void rna_def_curves_sculpt_options(BlenderRNA *brna)
|
|||||||
"Scale Uniform",
|
"Scale Uniform",
|
||||||
"Grow or shrink curves by changing their size uniformly instead of "
|
"Grow or shrink curves by changing their size uniformly instead of "
|
||||||
"using trimming or extrapolation");
|
"using trimming or extrapolation");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "minimum_length", PROP_FLOAT, PROP_DISTANCE);
|
prop = RNA_def_property(srna, "minimum_length", PROP_FLOAT, PROP_DISTANCE);
|
||||||
RNA_def_property_range(prop, 0.0f, FLT_MAX);
|
RNA_def_property_range(prop, 0.0f, FLT_MAX);
|
||||||
RNA_def_property_ui_text(
|
RNA_def_property_ui_text(
|
||||||
prop, "Minimum Length", "Avoid shrinking curves shorter than this length");
|
prop, "Minimum Length", "Avoid shrinking curves shorter than this length");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "interpolate_length", PROP_BOOLEAN, PROP_NONE);
|
prop = RNA_def_property(srna, "interpolate_length", PROP_BOOLEAN, PROP_NONE);
|
||||||
RNA_def_property_boolean_sdna(
|
RNA_def_property_boolean_sdna(
|
||||||
prop, nullptr, "flag", BRUSH_CURVES_SCULPT_FLAG_INTERPOLATE_LENGTH);
|
prop, nullptr, "flag", BRUSH_CURVES_SCULPT_FLAG_INTERPOLATE_LENGTH);
|
||||||
RNA_def_property_ui_text(
|
RNA_def_property_ui_text(
|
||||||
prop, "Interpolate Length", "Use length of the curves in close proximity");
|
prop, "Interpolate Length", "Use length of the curves in close proximity");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "interpolate_point_count", PROP_BOOLEAN, PROP_NONE);
|
prop = RNA_def_property(srna, "interpolate_point_count", PROP_BOOLEAN, PROP_NONE);
|
||||||
RNA_def_property_boolean_sdna(
|
RNA_def_property_boolean_sdna(
|
||||||
@ -2179,11 +2191,13 @@ static void rna_def_curves_sculpt_options(BlenderRNA *brna)
|
|||||||
RNA_def_property_ui_text(prop,
|
RNA_def_property_ui_text(prop,
|
||||||
"Interpolate Point Count",
|
"Interpolate Point Count",
|
||||||
"Use the number of points from the curves in close proximity");
|
"Use the number of points from the curves in close proximity");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "interpolate_shape", PROP_BOOLEAN, PROP_NONE);
|
prop = RNA_def_property(srna, "interpolate_shape", PROP_BOOLEAN, PROP_NONE);
|
||||||
RNA_def_property_boolean_sdna(prop, nullptr, "flag", BRUSH_CURVES_SCULPT_FLAG_INTERPOLATE_SHAPE);
|
RNA_def_property_boolean_sdna(prop, nullptr, "flag", BRUSH_CURVES_SCULPT_FLAG_INTERPOLATE_SHAPE);
|
||||||
RNA_def_property_ui_text(
|
RNA_def_property_ui_text(
|
||||||
prop, "Interpolate Shape", "Use shape of the curves in close proximity");
|
prop, "Interpolate Shape", "Use shape of the curves in close proximity");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "curve_length", PROP_FLOAT, PROP_DISTANCE);
|
prop = RNA_def_property(srna, "curve_length", PROP_FLOAT, PROP_DISTANCE);
|
||||||
RNA_def_property_range(prop, 0.0, FLT_MAX);
|
RNA_def_property_range(prop, 0.0, FLT_MAX);
|
||||||
@ -2191,28 +2205,35 @@ static void rna_def_curves_sculpt_options(BlenderRNA *brna)
|
|||||||
prop,
|
prop,
|
||||||
"Curve Length",
|
"Curve Length",
|
||||||
"Length of newly added curves when it is not interpolated from other curves");
|
"Length of newly added curves when it is not interpolated from other curves");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "minimum_distance", PROP_FLOAT, PROP_DISTANCE);
|
prop = RNA_def_property(srna, "minimum_distance", PROP_FLOAT, PROP_DISTANCE);
|
||||||
RNA_def_property_range(prop, 0.0f, FLT_MAX);
|
RNA_def_property_range(prop, 0.0f, FLT_MAX);
|
||||||
RNA_def_property_ui_range(prop, 0.0, 1000.0f, 0.001, 2);
|
RNA_def_property_ui_range(prop, 0.0, 1000.0f, 0.001, 2);
|
||||||
RNA_def_property_ui_text(
|
RNA_def_property_ui_text(
|
||||||
prop, "Minimum Distance", "Goal distance between curve roots for the Density brush");
|
prop, "Minimum Distance", "Goal distance between curve roots for the Density brush");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "density_add_attempts", PROP_INT, PROP_NONE);
|
prop = RNA_def_property(srna, "density_add_attempts", PROP_INT, PROP_NONE);
|
||||||
RNA_def_property_range(prop, 0, INT32_MAX);
|
RNA_def_property_range(prop, 0, INT32_MAX);
|
||||||
RNA_def_property_ui_text(
|
RNA_def_property_ui_text(
|
||||||
prop, "Density Add Attempts", "How many times the Density brush tries to add a new curve");
|
prop, "Density Add Attempts", "How many times the Density brush tries to add a new curve");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "density_mode", PROP_ENUM, PROP_NONE);
|
prop = RNA_def_property(srna, "density_mode", PROP_ENUM, PROP_NONE);
|
||||||
RNA_def_property_enum_items(prop, density_mode_items);
|
RNA_def_property_enum_items(prop, density_mode_items);
|
||||||
RNA_def_property_ui_text(
|
RNA_def_property_ui_text(
|
||||||
prop, "Density Mode", "Determines whether the brush adds or removes curves");
|
prop, "Density Mode", "Determines whether the brush adds or removes curves");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "curve_parameter_falloff", PROP_POINTER, PROP_NONE);
|
prop = RNA_def_property(srna, "curve_parameter_falloff", PROP_POINTER, PROP_NONE);
|
||||||
RNA_def_property_struct_type(prop, "CurveMapping");
|
RNA_def_property_struct_type(prop, "CurveMapping");
|
||||||
RNA_def_property_ui_text(prop,
|
RNA_def_property_ui_text(prop,
|
||||||
"Curve Parameter Falloff",
|
"Curve Parameter Falloff",
|
||||||
"Falloff that is applied from the tip to the root of each curve");
|
"Falloff that is applied from the tip to the root of each curve");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||||
|
|
||||||
|
RNA_define_lib_overridable(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rna_def_brush(BlenderRNA *brna)
|
static void rna_def_brush(BlenderRNA *brna)
|
||||||
@ -2560,6 +2581,8 @@ static void rna_def_brush(BlenderRNA *brna)
|
|||||||
srna, "Brush", "Brush data-block for storing brush settings for painting and sculpting");
|
srna, "Brush", "Brush data-block for storing brush settings for painting and sculpting");
|
||||||
RNA_def_struct_ui_icon(srna, ICON_BRUSH_DATA);
|
RNA_def_struct_ui_icon(srna, ICON_BRUSH_DATA);
|
||||||
|
|
||||||
|
RNA_define_lib_overridable(true);
|
||||||
|
|
||||||
/* enums */
|
/* enums */
|
||||||
prop = RNA_def_property(srna, "blend", PROP_ENUM, PROP_NONE);
|
prop = RNA_def_property(srna, "blend", PROP_ENUM, PROP_NONE);
|
||||||
RNA_def_property_enum_items(prop, prop_blend_items);
|
RNA_def_property_enum_items(prop, prop_blend_items);
|
||||||
@ -3867,6 +3890,8 @@ static void rna_def_brush(BlenderRNA *brna)
|
|||||||
RNA_def_property_struct_type(prop, "BrushCurvesSculptSettings");
|
RNA_def_property_struct_type(prop, "BrushCurvesSculptSettings");
|
||||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||||
RNA_def_property_ui_text(prop, "Curves Sculpt Settings", "");
|
RNA_def_property_ui_text(prop, "Curves Sculpt Settings", "");
|
||||||
|
|
||||||
|
RNA_define_lib_overridable(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -627,6 +627,13 @@ static void rna_def_paint(BlenderRNA *brna)
|
|||||||
RNA_def_property_ui_text(prop, "Brush", "Active Brush");
|
RNA_def_property_ui_text(prop, "Brush", "Active Brush");
|
||||||
RNA_def_property_update(prop, 0, "rna_Paint_brush_update");
|
RNA_def_property_update(prop, 0, "rna_Paint_brush_update");
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "brush_asset_reference", PROP_POINTER, PROP_NONE);
|
||||||
|
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||||
|
RNA_def_property_ui_text(prop,
|
||||||
|
"Brush Asset Reference",
|
||||||
|
"A weak reference to the matching brush asset, used e.g. to restore "
|
||||||
|
"the last used brush on file load");
|
||||||
|
|
||||||
/* paint_tool_slots */
|
/* paint_tool_slots */
|
||||||
prop = RNA_def_property(srna, "tool_slots", PROP_COLLECTION, PROP_NONE);
|
prop = RNA_def_property(srna, "tool_slots", PROP_COLLECTION, PROP_NONE);
|
||||||
RNA_def_property_collection_sdna(prop, nullptr, "tool_slots", "tool_slots_len");
|
RNA_def_property_collection_sdna(prop, nullptr, "tool_slots", "tool_slots_len");
|
||||||
|
@ -145,6 +145,11 @@ static void wm_history_file_write();
|
|||||||
|
|
||||||
static void wm_test_autorun_revert_action_exec(bContext *C);
|
static void wm_test_autorun_revert_action_exec(bContext *C);
|
||||||
|
|
||||||
|
static bool wm_operator_open_file_draft_check_dialog(bContext *C,
|
||||||
|
wmOperator *op,
|
||||||
|
const int num_user_edited_lost,
|
||||||
|
ReportList *user_edited_lost_reports);
|
||||||
|
|
||||||
static CLG_LogRef LOG = {"wm.files"};
|
static CLG_LogRef LOG = {"wm.files"};
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
@ -2791,6 +2796,7 @@ static int operator_state_dispatch(bContext *C, wmOperator *op, OperatorDispatch
|
|||||||
enum {
|
enum {
|
||||||
OPEN_MAINFILE_STATE_DISCARD_CHANGES,
|
OPEN_MAINFILE_STATE_DISCARD_CHANGES,
|
||||||
OPEN_MAINFILE_STATE_SELECT_FILE_PATH,
|
OPEN_MAINFILE_STATE_SELECT_FILE_PATH,
|
||||||
|
OPEN_MAINFILE_STATE_DISCARD_ASSET_DRAFTS,
|
||||||
OPEN_MAINFILE_STATE_OPEN,
|
OPEN_MAINFILE_STATE_OPEN,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2808,7 +2814,7 @@ static int wm_open_mainfile__discard_changes(bContext *C, wmOperator *op)
|
|||||||
set_next_operator_state(op, OPEN_MAINFILE_STATE_SELECT_FILE_PATH);
|
set_next_operator_state(op, OPEN_MAINFILE_STATE_SELECT_FILE_PATH);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
set_next_operator_state(op, OPEN_MAINFILE_STATE_OPEN);
|
set_next_operator_state(op, OPEN_MAINFILE_STATE_DISCARD_ASSET_DRAFTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wm_operator_close_file_dialog_if_needed(C, op, wm_open_mainfile_after_dialog_callback)) {
|
if (wm_operator_close_file_dialog_if_needed(C, op, wm_open_mainfile_after_dialog_callback)) {
|
||||||
@ -2848,6 +2854,44 @@ static int wm_open_mainfile__select_file_path(bContext *C, wmOperator *op)
|
|||||||
return OPERATOR_RUNNING_MODAL;
|
return OPERATOR_RUNNING_MODAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int wm_open_mainfile__discard_asset_drafts(bContext *C, wmOperator *op)
|
||||||
|
{
|
||||||
|
Main *bmain = CTX_data_main(C);
|
||||||
|
|
||||||
|
char filepath[FILE_MAX];
|
||||||
|
RNA_string_get(op->ptr, "filepath", filepath);
|
||||||
|
|
||||||
|
set_next_operator_state(op, OPEN_MAINFILE_STATE_OPEN);
|
||||||
|
|
||||||
|
Library *lib = static_cast<Library *>(
|
||||||
|
BLI_findstring(&bmain->libraries, filepath, offsetof(Library, filepath_abs)));
|
||||||
|
|
||||||
|
if (lib == nullptr) {
|
||||||
|
return wm_open_mainfile_dispatch(C, op);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If new to-be-opened blendfile was a library of the currently opened one, check for potential
|
||||||
|
* persistent edited assets that would be reset to their library status (only Brushes IDs
|
||||||
|
* currently). */
|
||||||
|
ReportList *reports = MEM_cnew<ReportList>(__func__);
|
||||||
|
BKE_reports_init(reports, RPT_STORE);
|
||||||
|
const int num_user_edited_brushes = BKE_lib_override_user_edited_from_library_count(
|
||||||
|
bmain, ID_BR, lib, reports);
|
||||||
|
if (num_user_edited_brushes > 0) {
|
||||||
|
/* NOTE: steals ownership of `user_edited_lost_reports` regardless of its result. */
|
||||||
|
if (wm_operator_open_file_draft_check_dialog(C, op, num_user_edited_brushes, reports)) {
|
||||||
|
return OPERATOR_INTERFACE;
|
||||||
|
}
|
||||||
|
reports = nullptr;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
BKE_reports_clear(reports);
|
||||||
|
MEM_delete(reports);
|
||||||
|
}
|
||||||
|
|
||||||
|
return wm_open_mainfile_dispatch(C, op);
|
||||||
|
}
|
||||||
|
|
||||||
static int wm_open_mainfile__open(bContext *C, wmOperator *op)
|
static int wm_open_mainfile__open(bContext *C, wmOperator *op)
|
||||||
{
|
{
|
||||||
char filepath[FILE_MAX];
|
char filepath[FILE_MAX];
|
||||||
@ -2880,6 +2924,7 @@ static int wm_open_mainfile__open(bContext *C, wmOperator *op)
|
|||||||
static OperatorDispatchTarget wm_open_mainfile_dispatch_targets[] = {
|
static OperatorDispatchTarget wm_open_mainfile_dispatch_targets[] = {
|
||||||
{OPEN_MAINFILE_STATE_DISCARD_CHANGES, wm_open_mainfile__discard_changes},
|
{OPEN_MAINFILE_STATE_DISCARD_CHANGES, wm_open_mainfile__discard_changes},
|
||||||
{OPEN_MAINFILE_STATE_SELECT_FILE_PATH, wm_open_mainfile__select_file_path},
|
{OPEN_MAINFILE_STATE_SELECT_FILE_PATH, wm_open_mainfile__select_file_path},
|
||||||
|
{OPEN_MAINFILE_STATE_DISCARD_ASSET_DRAFTS, wm_open_mainfile__discard_asset_drafts},
|
||||||
{OPEN_MAINFILE_STATE_OPEN, wm_open_mainfile__open},
|
{OPEN_MAINFILE_STATE_OPEN, wm_open_mainfile__open},
|
||||||
{0, nullptr},
|
{0, nullptr},
|
||||||
};
|
};
|
||||||
@ -4359,3 +4404,217 @@ bool wm_operator_close_file_dialog_if_needed(bContext *C,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \name Open Asset Library File Dialog.
|
||||||
|
*
|
||||||
|
* This handles cases where user is opening a file that is an asset library, which assets are used
|
||||||
|
* in the 'user preference' way (i.e. assets are linked, and have runtime-only, session-persistant,
|
||||||
|
* user-editable overrides of these.
|
||||||
|
*
|
||||||
|
* Special warning is necessary because when opening the library file, all non-drafted user edits
|
||||||
|
* of the relevant assets will be lost. */
|
||||||
|
/** \{ */
|
||||||
|
|
||||||
|
static const char *open_file_draft_check_dialog_name = "open_file_draft_check_popup";
|
||||||
|
|
||||||
|
typedef struct wmOpenDraftCheckCallback {
|
||||||
|
IDProperty *op_properties;
|
||||||
|
|
||||||
|
ReportList *user_edited_lost_reports;
|
||||||
|
int num_user_edited_lost;
|
||||||
|
|
||||||
|
char new_filepath[FILE_MAX];
|
||||||
|
} wmOpenDraftCheckCallback;
|
||||||
|
|
||||||
|
static void wm_block_open_file_draft_cancel(bContext *C, void *arg_block, void * /*arg_data*/)
|
||||||
|
{
|
||||||
|
wmWindow *win = CTX_wm_window(C);
|
||||||
|
UI_popup_block_close(C, win, static_cast<uiBlock *>(arg_block));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wm_block_open_file_draft_discard(bContext *C, void *arg_block, void *arg_data)
|
||||||
|
{
|
||||||
|
wmGenericCallback *callback = WM_generic_callback_steal((wmGenericCallback *)arg_data);
|
||||||
|
|
||||||
|
/* Close the popup before executing the callback. Otherwise
|
||||||
|
* the popup might be closed by the callback, which will lead
|
||||||
|
* to a crash. */
|
||||||
|
wmWindow *win = CTX_wm_window(C);
|
||||||
|
UI_popup_block_close(C, win, static_cast<uiBlock *>(arg_block));
|
||||||
|
|
||||||
|
callback->exec(C, callback->user_data);
|
||||||
|
WM_generic_callback_free(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wm_block_open_file_draft_save(bContext *C, void *arg_block, void *arg_data)
|
||||||
|
{
|
||||||
|
wmGenericCallback *callback = WM_generic_callback_steal((wmGenericCallback *)arg_data);
|
||||||
|
bool execute_callback = true;
|
||||||
|
|
||||||
|
wmWindow *win = CTX_wm_window(C);
|
||||||
|
UI_popup_block_close(C, win, static_cast<uiBlock *>(arg_block));
|
||||||
|
|
||||||
|
/* TODO: Actually save the edited lost local runtime assets overrides into drafts. */
|
||||||
|
|
||||||
|
if (execute_callback) {
|
||||||
|
callback->exec(C, callback->user_data);
|
||||||
|
}
|
||||||
|
WM_generic_callback_free(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wm_block_open_file_draft_cancel_button(uiBlock *block, wmGenericCallback *post_action)
|
||||||
|
{
|
||||||
|
uiBut *but = uiDefIconTextBut(
|
||||||
|
block, UI_BTYPE_BUT, 0, 0, IFACE_("Cancel"), 0, 0, 0, UI_UNIT_Y, 0, 0, 0, 0, 0, "");
|
||||||
|
UI_but_func_set(but, wm_block_open_file_draft_cancel, block, post_action);
|
||||||
|
UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wm_block_open_file_draft_discard_button(uiBlock *block, wmGenericCallback *post_action)
|
||||||
|
{
|
||||||
|
uiBut *but = uiDefIconTextBut(
|
||||||
|
block, UI_BTYPE_BUT, 0, 0, IFACE_("Ignore"), 0, 0, 0, UI_UNIT_Y, 0, 0, 0, 0, 0, "");
|
||||||
|
UI_but_func_set(but, wm_block_open_file_draft_discard, block, post_action);
|
||||||
|
UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wm_block_open_file_draft_save_button(uiBlock *block, wmGenericCallback *post_action)
|
||||||
|
{
|
||||||
|
uiBut *but = uiDefIconTextBut(
|
||||||
|
block, UI_BTYPE_BUT, 0, 0, IFACE_("Save To Draft"), 0, 0, 0, UI_UNIT_Y, 0, 0, 0, 0, 0, "");
|
||||||
|
UI_but_func_set(but, wm_block_open_file_draft_save, block, post_action);
|
||||||
|
UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT);
|
||||||
|
UI_but_flag_enable(but, UI_BUT_ACTIVE_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wm_open_file_after_draft_check_dialog_callback(bContext *C, void *user_data)
|
||||||
|
{
|
||||||
|
wmOpenDraftCheckCallback *callback_data = static_cast<wmOpenDraftCheckCallback *>(user_data);
|
||||||
|
|
||||||
|
WM_operator_name_call_with_properties(
|
||||||
|
C, "WM_OT_open_mainfile", WM_OP_INVOKE_DEFAULT, callback_data->op_properties, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uiBlock *block_create__open_draft_check_file_dialog(struct bContext *C,
|
||||||
|
struct ARegion *region,
|
||||||
|
void *arg1)
|
||||||
|
{
|
||||||
|
wmGenericCallback *post_action = static_cast<wmGenericCallback *>(arg1);
|
||||||
|
wmOpenDraftCheckCallback *callback_data = static_cast<wmOpenDraftCheckCallback *>(
|
||||||
|
post_action->user_data);
|
||||||
|
|
||||||
|
uiBlock *block = UI_block_begin(C, region, open_file_draft_check_dialog_name, UI_EMBOSS);
|
||||||
|
UI_block_flag_enable(
|
||||||
|
block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_LOOP | UI_BLOCK_NO_WIN_CLIP | UI_BLOCK_NUMSELECT);
|
||||||
|
UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
|
||||||
|
|
||||||
|
uiLayout *layout = uiItemsAlertBox(block, 34, ALERT_ICON_QUESTION);
|
||||||
|
|
||||||
|
/* Title. */
|
||||||
|
uiItemL_ex(layout, TIP_("Save User-Edited Assets to Draft?"), ICON_NONE, true, false);
|
||||||
|
|
||||||
|
char message[2048];
|
||||||
|
SNPRINTF(message,
|
||||||
|
TIP_("The following %d assets have local edits that will be lost"),
|
||||||
|
callback_data->num_user_edited_lost);
|
||||||
|
uiItemL(layout, message, ICON_NONE);
|
||||||
|
uiItemL(layout, "by opening the chosen Blender Asset Library file", ICON_NONE);
|
||||||
|
uiItemL(layout, callback_data->new_filepath, ICON_NONE);
|
||||||
|
|
||||||
|
/* Draw available report messages. */
|
||||||
|
LISTBASE_FOREACH (Report *, report, &callback_data->user_edited_lost_reports->list) {
|
||||||
|
uiLayout *row = uiLayoutColumn(layout, false);
|
||||||
|
uiLayoutSetScaleY(row, 0.6f);
|
||||||
|
uiItemS(row);
|
||||||
|
|
||||||
|
uiItemL_ex(row, report->message, ICON_NONE, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
uiItemS_ex(layout, 4.0f);
|
||||||
|
|
||||||
|
/* Buttons. */
|
||||||
|
#ifdef _WIN32
|
||||||
|
const bool windows_layout = true;
|
||||||
|
#else
|
||||||
|
const bool windows_layout = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (windows_layout) {
|
||||||
|
/* Windows standard layout. */
|
||||||
|
|
||||||
|
uiLayout *split = uiLayoutSplit(layout, 0.0f, true);
|
||||||
|
uiLayoutSetScaleY(split, 1.2f);
|
||||||
|
|
||||||
|
uiLayoutColumn(split, false);
|
||||||
|
wm_block_open_file_draft_save_button(block, post_action);
|
||||||
|
|
||||||
|
uiLayoutColumn(split, false);
|
||||||
|
wm_block_open_file_draft_discard_button(block, post_action);
|
||||||
|
|
||||||
|
uiLayoutColumn(split, false);
|
||||||
|
wm_block_open_file_draft_cancel_button(block, post_action);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Non-Windows layout (macOS and Linux). */
|
||||||
|
|
||||||
|
uiLayout *split = uiLayoutSplit(layout, 0.3f, true);
|
||||||
|
uiLayoutSetScaleY(split, 1.2f);
|
||||||
|
|
||||||
|
uiLayoutColumn(split, false);
|
||||||
|
wm_block_open_file_draft_discard_button(block, post_action);
|
||||||
|
|
||||||
|
uiLayout *split_right = uiLayoutSplit(split, 0.1f, true);
|
||||||
|
|
||||||
|
uiLayoutColumn(split_right, false);
|
||||||
|
/* Empty space. */
|
||||||
|
|
||||||
|
uiLayoutColumn(split_right, false);
|
||||||
|
wm_block_open_file_draft_cancel_button(block, post_action);
|
||||||
|
|
||||||
|
uiLayoutColumn(split_right, false);
|
||||||
|
wm_block_open_file_draft_save_button(block, post_action);
|
||||||
|
}
|
||||||
|
|
||||||
|
UI_block_bounds_set_centered(block, int(14 * U.scale_factor));
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wm_free_open_file_draft_check_callback(void *user_data)
|
||||||
|
{
|
||||||
|
wmOpenDraftCheckCallback *callback_data = static_cast<wmOpenDraftCheckCallback *>(user_data);
|
||||||
|
|
||||||
|
IDP_FreeProperty(callback_data->op_properties);
|
||||||
|
BKE_reports_clear(callback_data->user_edited_lost_reports);
|
||||||
|
MEM_delete(callback_data->user_edited_lost_reports);
|
||||||
|
|
||||||
|
MEM_delete(callback_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NOTE: steals ownership of `user_edited_lost_reports`. */
|
||||||
|
static bool wm_operator_open_file_draft_check_dialog(bContext *C,
|
||||||
|
wmOperator *op,
|
||||||
|
const int num_user_edited_lost,
|
||||||
|
ReportList *user_edited_lost_reports)
|
||||||
|
{
|
||||||
|
wmOpenDraftCheckCallback *callback_data = MEM_cnew<wmOpenDraftCheckCallback>(__func__);
|
||||||
|
callback_data->op_properties = IDP_CopyProperty(op->properties);
|
||||||
|
RNA_string_get(op->ptr, "filepath", callback_data->new_filepath);
|
||||||
|
callback_data->num_user_edited_lost = num_user_edited_lost;
|
||||||
|
callback_data->user_edited_lost_reports = user_edited_lost_reports;
|
||||||
|
|
||||||
|
wmGenericCallback *callback = MEM_cnew<wmGenericCallback>(__func__);
|
||||||
|
callback->exec = wm_open_file_after_draft_check_dialog_callback;
|
||||||
|
callback->user_data = callback_data;
|
||||||
|
callback->free_user_data = wm_free_open_file_draft_check_callback;
|
||||||
|
|
||||||
|
if (!UI_popup_block_name_exists(CTX_wm_screen(C), open_file_draft_check_dialog_name)) {
|
||||||
|
UI_popup_block_invoke(
|
||||||
|
C, block_create__open_draft_check_file_dialog, callback, free_post_file_close_action);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
WM_generic_callback_free(callback);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/** \} */
|
||||||
|
@ -187,7 +187,7 @@ static void toolsystem_ref_link(bContext *C, WorkSpace *workspace, bToolRef *tre
|
|||||||
LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
|
LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
|
||||||
if (workspace == WM_window_get_active_workspace(win)) {
|
if (workspace == WM_window_get_active_workspace(win)) {
|
||||||
Scene *scene = WM_window_get_active_scene(win);
|
Scene *scene = WM_window_get_active_scene(win);
|
||||||
BKE_paint_ensure_from_paintmode(scene, paint_mode);
|
BKE_paint_ensure_from_paintmode(bmain, scene, paint_mode);
|
||||||
Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode);
|
Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode);
|
||||||
Brush *brush = BKE_paint_toolslots_brush_get(paint, slot_index);
|
Brush *brush = BKE_paint_toolslots_brush_get(paint, slot_index);
|
||||||
if (brush == nullptr) {
|
if (brush == nullptr) {
|
||||||
|
Loading…
Reference in New Issue
Block a user