WIP: Brush assets project #106303

Draft
Julian Eisel wants to merge 358 commits from brush-assets-project into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
2 changed files with 106 additions and 1 deletions
Showing only changes of commit d9f2fce614 - Show all commits

View File

@ -6,6 +6,8 @@
* \ingroup bke
*/
#include <memory>
#include "MEM_guardedalloc.h"
#include "DNA_brush_types.h"
@ -24,12 +26,14 @@
#include "BLT_translation.h"
#include "BKE_asset.hh"
#include "BKE_blendfile_link_append.hh"
#include "BKE_bpath.h"
#include "BKE_brush.hh"
#include "BKE_colortools.hh"
#include "BKE_context.hh"
#include "BKE_gpencil_legacy.h"
#include "BKE_idprop.hh"
#include "BKE_idtype.h"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.h"
@ -382,6 +386,39 @@ static void brush_blend_read_after_liblink(BlendLibReader * /*reader*/, ID *id)
}
}
static void brush_asset_metadata_ensure(void *asset_ptr, AssetMetaData *asset_data)
{
using namespace blender;
using namespace blender::bke;
Brush *brush = reinterpret_cast<Brush *>(asset_ptr);
BLI_assert(GS(brush->id.name) == ID_BR);
static const Array<std::pair<const char *, int>> mode_map = {
{"use_paint_sculpt", OB_MODE_SCULPT},
{"use_paint_uv_sculpt", OB_MODE_EDIT},
{"use_paint_vertex", OB_MODE_VERTEX_PAINT},
{"use_paint_weight", OB_MODE_WEIGHT_PAINT},
{"use_paint_image", OB_MODE_TEXTURE_PAINT},
{"use_paint_grease_pencil", OB_MODE_PAINT_GPENCIL_LEGACY},
{"use_vertex_grease_pencil", OB_MODE_VERTEX_GPENCIL_LEGACY},
{"use_paint_sculpt_curves", OB_MODE_SCULPT_CURVES}};
for (const auto &mode_mapping : mode_map) {
/* Only add bools for supported modes. */
if (!(brush->ob_mode & mode_mapping.second)) {
continue;
}
auto mode_property = idprop::create_bool(mode_mapping.first, true);
BKE_asset_metadata_idprop_ensure(asset_data, mode_property.release());
}
}
static AssetTypeInfo AssetType_BR = {
/*pre_save_fn*/ brush_asset_metadata_ensure,
/*on_mark_asset_fn*/ brush_asset_metadata_ensure,
};
IDTypeInfo IDType_ID_BR = {
/*id_code*/ ID_BR,
/*id_filter*/ FILTER_ID_BR,
@ -391,7 +428,7 @@ IDTypeInfo IDType_ID_BR = {
/*name_plural*/ N_("brushes"),
/*translation_context*/ BLT_I18NCONTEXT_ID_BRUSH,
/*flags*/ IDTYPE_FLAGS_NO_ANIMDATA | IDTYPE_FLAGS_NO_MEMFILE_UNDO,
/*asset_type_info*/ nullptr,
/*asset_type_info*/ &AssetType_BR,
/*init_data*/ brush_init_data,
/*copy_data*/ brush_copy_data,

View File

@ -31,6 +31,7 @@ static constexpr StringRef IDP_KEY_SUBTYPE("subtype");
static constexpr StringRef IDP_KEY_VALUE("value");
static constexpr StringRef IDP_PROPERTY_TYPENAME_STRING("IDP_STRING");
static constexpr StringRef IDP_PROPERTY_TYPENAME_BOOL("IDP_BOOL");
static constexpr StringRef IDP_PROPERTY_TYPENAME_INT("IDP_INT");
static constexpr StringRef IDP_PROPERTY_TYPENAME_FLOAT("IDP_FLOAT");
static constexpr StringRef IDP_PROPERTY_TYPENAME_DOUBLE("IDP_DOUBLE");
@ -125,6 +126,11 @@ struct DictionaryEntryParser {
return get_string(IDP_KEY_VALUE);
}
std::optional<bool> get_bool_value() const
{
return get_bool(IDP_KEY_VALUE);
}
std::optional<int32_t> get_int_value() const
{
return get_int(IDP_KEY_VALUE);
@ -196,6 +202,21 @@ struct DictionaryEntryParser {
return value->as_array_value();
}
std::optional<bool> get_bool(StringRef key) const
{
const DictionaryValue::LookupValue *value_ptr = lookup.lookup_ptr(key);
if (value_ptr == nullptr) {
return std::nullopt;
}
const DictionaryValue::LookupValue &value = *value_ptr;
if (value->type() != eValueType::Boolean) {
return std::nullopt;
}
return value->as_boolean_value()->value();
}
std::optional<int32_t> get_int(StringRef key) const
{
const DictionaryValue::LookupValue *value_ptr = lookup.lookup_ptr(key);
@ -321,6 +342,46 @@ class IDPStringSerializer : public IDPropertySerializer {
}
};
/** \brief IDPSerializer for IDP_INT. */
class IDPBoolSerializer : public IDPropertySerializer {
public:
constexpr IDPBoolSerializer() = default;
std::string type_name() const override
{
return IDP_PROPERTY_TYPENAME_BOOL;
}
std::optional<eIDPropertyType> property_type() const override
{
return IDP_BOOLEAN;
}
std::shared_ptr<DictionaryValue> idprop_to_dictionary(
const IDProperty *id_property) const override
{
std::shared_ptr<DictionaryValue> result = create_dictionary(id_property);
DictionaryValue::Items &attributes = result->elements();
attributes.append_as(std::pair(IDP_KEY_VALUE, new BooleanValue(IDP_Bool(id_property) != 0)));
return result;
}
std::unique_ptr<IDProperty, IDPropertyDeleter> entry_to_idprop(
DictionaryEntryParser &entry_reader) const override
{
BLI_assert(*(entry_reader.get_type()) == IDP_BOOLEAN);
std::optional<std::string> name = entry_reader.get_name();
if (!name.has_value()) {
return nullptr;
}
std::optional<bool> extracted_value = entry_reader.get_bool_value();
if (!extracted_value.has_value()) {
return nullptr;
}
return create_bool(name->c_str(), *extracted_value);
}
};
/** \brief IDPSerializer for IDP_INT. */
class IDPIntSerializer : public IDPropertySerializer {
public:
@ -704,6 +765,7 @@ class IDPUnknownSerializer : public IDPropertySerializer {
/* Serializers are constructed statically to remove construction/destruction. */
static constexpr IDPStringSerializer IDP_SERIALIZER_STRING;
static constexpr IDPIntSerializer IDP_SERIALIZER_BOOL;
static constexpr IDPIntSerializer IDP_SERIALIZER_INT;
static constexpr IDPFloatSerializer IDP_SERIALIZER_FLOAT;
static constexpr IDPDoubleSerializer IDP_SERIALIZER_DOUBLE;
@ -718,6 +780,9 @@ static const IDPropertySerializer &serializer_for(eIDPropertyType property_type)
case IDP_STRING:
return IDP_SERIALIZER_STRING;
case IDP_BOOLEAN:
return IDP_SERIALIZER_BOOL;
case IDP_INT:
return IDP_SERIALIZER_INT;
@ -745,6 +810,9 @@ static const IDPropertySerializer &serializer_for(StringRef idprop_typename)
if (idprop_typename == IDP_PROPERTY_TYPENAME_STRING) {
return IDP_SERIALIZER_STRING;
}
if (idprop_typename == IDP_PROPERTY_TYPENAME_BOOL) {
return IDP_SERIALIZER_BOOL;
}
if (idprop_typename == IDP_PROPERTY_TYPENAME_INT) {
return IDP_SERIALIZER_INT;
}