WIP: Vulkan: Workbench #107886

Closed
Jeroen Bakker wants to merge 88 commits from Jeroen-Bakker:vulkan-draw-manager-workbench into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
100 changed files with 754 additions and 2143 deletions
Showing only changes of commit 912189f9e7 - Show all commits

View File

@ -215,6 +215,7 @@ class GHOST_DeviceVK {
device_features.geometryShader = VK_TRUE;
device_features.dualSrcBlend = VK_TRUE;
device_features.logicOp = VK_TRUE;
device_features.imageCubeArray = VK_TRUE;
#endif
VkDeviceCreateInfo device_create_info = {};
@ -309,7 +310,7 @@ static GHOST_TSuccess ensure_vulkan_device(VkInstance vk_instance,
#if STRICT_REQUIREMENTS
if (!device_vk.features.geometryShader || !device_vk.features.dualSrcBlend ||
!device_vk.features.logicOp)
!device_vk.features.logicOp || !device_vk.features.imageCubeArray)
{
continue;
}

View File

@ -571,8 +571,6 @@ class KeyframesCo:
keyframe_points.foreach_set("co", co_buffer)
keyframe_points.foreach_set("interpolation", ipo_buffer)
# TODO: in Blender 4.0 the next lines can be replaced with one call to `fcurve.update()`.
# See https://projects.blender.org/blender/blender/issues/107126 for more info.
keyframe_points.sort()
keyframe_points.deduplicate()
keyframe_points.handles_recalc()
# This also deduplicates keys where baked keys were inserted on the
# same frame as existing ones.
fcurve.update()

View File

@ -44,8 +44,8 @@ def geometry_modifier_poll(context):
def get_context_modifier(context):
area = context.area
if (area is not None) and (area.type == 'PROPERTIES'):
# Context only has a 'modifier' attribute in the modifier extra operators dropdown.
if hasattr(context, 'modifier'):
modifier = context.modifier
else:
ob = context.object

View File

@ -109,17 +109,6 @@ class MESH_UL_vgroups(UIList):
layout.label(text="", icon_value=icon)
class MESH_UL_fmaps(UIList):
def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname, _index):
# assert(isinstance(item, bpy.types.FaceMap))
fmap = item
if self.layout_type in {'DEFAULT', 'COMPACT'}:
layout.prop(fmap, "name", text="", emboss=False, icon='FACE_MAPS')
elif self.layout_type == 'GRID':
layout.alignment = 'CENTER'
layout.label(text="", icon_value=icon)
class MESH_UL_shape_keys(UIList):
def draw_item(self, _context, layout, _data, item, icon, active_data, _active_propname, index):
# assert(isinstance(item, bpy.types.ShapeKey))
@ -285,50 +274,6 @@ class DATA_PT_vertex_groups(MeshButtonsPanel, Panel):
layout.prop(context.tool_settings, "vertex_group_weight", text="Weight")
class DATA_PT_face_maps(MeshButtonsPanel, Panel):
bl_label = "Face Maps"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH', 'BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
obj = context.object
return (obj and obj.type == 'MESH')
def draw(self, context):
layout = self.layout
ob = context.object
facemap = ob.face_maps.active
rows = 2
if facemap:
rows = 4
row = layout.row()
row.template_list("MESH_UL_fmaps", "", ob, "face_maps", ob.face_maps, "active_index", rows=rows)
col = row.column(align=True)
col.operator("object.face_map_add", icon='ADD', text="")
col.operator("object.face_map_remove", icon='REMOVE', text="")
if facemap:
col.separator()
col.operator("object.face_map_move", icon='TRIA_UP', text="").direction = 'UP'
col.operator("object.face_map_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
if ob.face_maps and (ob.mode == 'EDIT' and ob.type == 'MESH'):
row = layout.row()
sub = row.row(align=True)
sub.operator("object.face_map_assign", text="Assign")
sub.operator("object.face_map_remove_from", text="Remove")
sub = row.row(align=True)
sub.operator("object.face_map_select", text="Select")
sub.operator("object.face_map_deselect", text="Deselect")
class DATA_PT_shape_keys(MeshButtonsPanel, Panel):
bl_label = "Shape Keys"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH', 'BLENDER_WORKBENCH_NEXT'}
@ -717,7 +662,6 @@ classes = (
MESH_MT_color_attribute_context_menu,
MESH_MT_attribute_context_menu,
MESH_UL_vgroups,
MESH_UL_fmaps,
MESH_UL_shape_keys,
MESH_UL_uvmaps,
MESH_UL_attributes,
@ -726,7 +670,6 @@ classes = (
DATA_PT_shape_keys,
DATA_PT_uv_texture,
DATA_PT_vertex_colors,
DATA_PT_face_maps,
DATA_PT_mesh_attributes,
DATA_PT_normals,
DATA_PT_texture_space,

View File

@ -2103,7 +2103,7 @@ class VIEW3D_MT_select_edit_curves(Menu):
layout.separator()
layout.operator("curves.select_random", text="Random")
layout.operator("curves.select_end", text="Endpoints")
layout.operator("curves.select_ends", text="Endpoints")
layout.operator("curves.select_linked", text="Linked")
layout.separator()
@ -2121,7 +2121,7 @@ class VIEW3D_MT_select_sculpt_curves(Menu):
layout.operator("curves.select_all", text="None").action = 'DESELECT'
layout.operator("curves.select_all", text="Invert").action = 'INVERT'
layout.operator("sculpt_curves.select_random", text="Random")
layout.operator("curves.select_end", text="Endpoints")
layout.operator("curves.select_ends", text="Endpoints")
layout.operator("sculpt_curves.select_grow", text="Grow")

View File

@ -10,6 +10,8 @@
#include "BLI_compiler_attrs.h"
#include "DNA_ID_enums.h"
#ifdef __cplusplus
extern "C" {
#endif
@ -22,7 +24,8 @@ typedef struct AssetRepresentation AssetRepresentation;
const char *AS_asset_representation_name_get(const AssetRepresentation *asset)
ATTR_WARN_UNUSED_RESULT;
int AS_asset_representation_id_type_get(const AssetRepresentation *asset) ATTR_WARN_UNUSED_RESULT;
ID_Type AS_asset_representation_id_type_get(const AssetRepresentation *asset)
ATTR_WARN_UNUSED_RESULT;
AssetMetaData *AS_asset_representation_metadata_get(const AssetRepresentation *asset)
ATTR_WARN_UNUSED_RESULT;
struct ID *AS_asset_representation_local_id_get(const AssetRepresentation *asset)
@ -31,6 +34,9 @@ bool AS_asset_representation_is_local_id(const AssetRepresentation *asset) ATTR_
bool AS_asset_representation_is_never_link(const AssetRepresentation *asset)
ATTR_WARN_UNUSED_RESULT;
bool AS_asset_representation_may_override_import_method(const AssetRepresentation *asset);
bool AS_asset_representation_use_relative_path_get(const AssetRepresentation *asset);
/**
* C version of #AssetRepresentation::make_weak_reference. Returned pointer needs freeing with
* #MEM_delete() or #BKE_asset_weak_reference_free().

View File

@ -19,6 +19,7 @@
#include "BLI_string_ref.hh"
#include "DNA_ID_enums.h"
#include "DNA_asset_types.h"
#include "AS_asset_identifier.hh"
@ -87,7 +88,7 @@ class AssetRepresentation {
std::unique_ptr<AssetWeakReference> make_weak_reference() const;
StringRefNull get_name() const;
int get_id_type() const;
ID_Type get_id_type() const;
AssetMetaData &get_metadata() const;
/**
* Get the import method to use for this asset. A different one may be used if
@ -129,5 +130,3 @@ std::string AS_asset_representation_full_path_get(const ::AssetRepresentation *a
std::string AS_asset_representation_full_library_path_get(const ::AssetRepresentation *asset);
std::optional<eAssetImportMethod> AS_asset_representation_import_method_get(
const ::AssetRepresentation *asset_handle);
bool AS_asset_representation_may_override_import_method(const ::AssetRepresentation *asset_handle);
bool AS_asset_representation_use_relative_path_get(const ::AssetRepresentation *asset_handle);

View File

@ -89,13 +89,13 @@ StringRefNull AssetRepresentation::get_name() const
return external_asset_.name;
}
int AssetRepresentation::get_id_type() const
ID_Type AssetRepresentation::get_id_type() const
{
if (is_local_id_) {
return GS(local_asset_id_->name);
}
return external_asset_.id_type;
return ID_Type(external_asset_.id_type);
}
AssetMetaData &AssetRepresentation::get_metadata() const
@ -203,7 +203,7 @@ const char *AS_asset_representation_name_get(const AssetRepresentation *asset_ha
return asset->get_name().c_str();
}
int AS_asset_representation_id_type_get(const AssetRepresentation *asset_handle)
ID_Type AS_asset_representation_id_type_get(const AssetRepresentation *asset_handle)
{
const asset_system::AssetRepresentation *asset =
reinterpret_cast<const asset_system::AssetRepresentation *>(asset_handle);

View File

@ -27,13 +27,13 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 5
#define BLENDER_FILE_SUBVERSION 6
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file
* was written with too new a version. */
#define BLENDER_FILE_MIN_VERSION 400
#define BLENDER_FILE_MIN_SUBVERSION 2
#define BLENDER_FILE_MIN_SUBVERSION 3
/** User readable version string. */
const char *BKE_blender_version_string(void);

View File

@ -180,9 +180,6 @@ struct Mesh *BKE_mesh_new_nomain_from_curve_displist(const struct Object *ob,
bool BKE_mesh_attribute_required(const char *name);
bool BKE_mesh_ensure_facemap_customdata(struct Mesh *me);
bool BKE_mesh_clear_facemap_customdata(struct Mesh *me);
float (*BKE_mesh_orco_verts_get(struct Object *ob))[3];
void BKE_mesh_orco_verts_transform(struct Mesh *me, float (*orco)[3], int totvert, int invert);

View File

@ -84,6 +84,8 @@ void BKE_mesh_legacy_convert_polys_to_offsets(Mesh *mesh);
void BKE_mesh_legacy_convert_loops_to_corners(struct Mesh *mesh);
void BKE_mesh_legacy_face_map_to_generic(struct Mesh *mesh);
#endif
#ifdef __cplusplus

View File

@ -1,37 +0,0 @@
/* SPDX-FileCopyrightText: 2023 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/** \file
* \ingroup bke
* \brief Functions for dealing with object face-maps.
*/
#ifdef __cplusplus
extern "C" {
#endif
struct ListBase;
struct Object;
struct bFaceMap;
struct bFaceMap *BKE_object_facemap_add(struct Object *ob);
struct bFaceMap *BKE_object_facemap_add_name(struct Object *ob, const char *name);
void BKE_object_facemap_remove(struct Object *ob, struct bFaceMap *fmap);
void BKE_object_facemap_clear(struct Object *ob);
int BKE_object_facemap_name_index(struct Object *ob, const char *name);
void BKE_object_facemap_unique_name(struct Object *ob, struct bFaceMap *fmap);
struct bFaceMap *BKE_object_facemap_find_name(struct Object *ob, const char *name);
void BKE_object_facemap_copy_list(struct ListBase *outbase, const struct ListBase *inbase);
int *BKE_object_facemap_index_map_create(struct Object *ob_src,
struct Object *ob_dst,
int *r_map_len);
void BKE_object_facemap_index_map_apply(int *fmap, int fmap_len, const int *map, int map_len);
#ifdef __cplusplus
}
#endif

View File

@ -241,7 +241,6 @@ set(SRC
intern/object.cc
intern/object_deform.c
intern/object_dupli.cc
intern/object_facemap.c
intern/object_update.cc
intern/ocean.c
intern/ocean_spectrum.c
@ -457,7 +456,6 @@ set(SRC
BKE_node_tree_zones.hh
BKE_object.h
BKE_object_deform.h
BKE_object_facemap.h
BKE_ocean.h
BKE_outliner_treehash.hh
BKE_packedFile.h

View File

@ -1257,20 +1257,6 @@ static void layerSwap_flnor(void *data, const int *corner_indices)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Callbacks for (`int`, #CD_FACEMAP)
* \{ */
static void layerDefault_fmap(void *data, const int count)
{
int *fmap_num = (int *)data;
for (int i = 0; i < count; i++) {
fmap_num[i] = -1;
}
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Callbacks for (#MPropCol, #CD_PROP_COLOR)
* \{ */
@ -1628,8 +1614,8 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
nullptr,
nullptr,
layerCopyValue_normal},
/* 9: CD_FACEMAP */
{sizeof(int), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, layerDefault_fmap, nullptr},
/* 9: CD_FACEMAP */ /* DEPRECATED */
{sizeof(int), ""},
/* 10: CD_PROP_FLOAT */
{sizeof(MFloatProperty),
"MFloatProperty",
@ -1865,7 +1851,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
/* 41: CD_CUSTOMLOOPNORMAL */
{sizeof(short[2]), "vec2s", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 42: CD_SCULPT_FACE_SETS */ /* DEPRECATED */
{sizeof(int), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
{sizeof(int), ""},
/* 43: CD_LOCATION */
{sizeof(float[3]), "vec3f", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 44: CD_RADIUS */
@ -2010,14 +1996,14 @@ const CustomData_MeshMasks CD_MASK_BAREMESH = {
/*vmask*/ CD_MASK_PROP_FLOAT3,
/*emask*/ CD_MASK_PROP_INT32_2D,
/*fmask*/ 0,
/*pmask*/ CD_MASK_FACEMAP,
/*pmask*/ 0,
/*lmask*/ CD_MASK_PROP_INT32,
};
const CustomData_MeshMasks CD_MASK_BAREMESH_ORIGINDEX = {
/*vmask*/ CD_MASK_PROP_FLOAT3 | CD_MASK_ORIGINDEX,
/*emask*/ CD_MASK_PROP_INT32_2D | CD_MASK_ORIGINDEX,
/*fmask*/ 0,
/*pmask*/ CD_MASK_FACEMAP | CD_MASK_ORIGINDEX,
/*pmask*/ CD_MASK_ORIGINDEX,
/*lmask*/ CD_MASK_PROP_INT32,
};
const CustomData_MeshMasks CD_MASK_MESH = {
@ -2027,7 +2013,7 @@ const CustomData_MeshMasks CD_MASK_MESH = {
(CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL | CD_MASK_CREASE),
/*fmask*/ 0,
/*pmask*/
(CD_MASK_FACEMAP | CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL),
(CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL),
/*lmask*/
(CD_MASK_MDISPS | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
};
@ -2039,7 +2025,7 @@ const CustomData_MeshMasks CD_MASK_DERIVEDMESH = {
(CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL | CD_MASK_CREASE),
/*fmask*/ (CD_MASK_ORIGINDEX | CD_MASK_ORIGSPACE | CD_MASK_PREVIEW_MCOL | CD_MASK_TANGENT),
/*pmask*/
(CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_FACE | CD_MASK_FACEMAP | CD_MASK_PROP_ALL),
(CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL),
/*lmask*/
(CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_PREVIEW_MLOOPCOL | CD_MASK_ORIGSPACE_MLOOP |
CD_MASK_PROP_ALL), /* XXX: MISSING #CD_MASK_MLOOPTANGENT ? */
@ -2050,7 +2036,7 @@ const CustomData_MeshMasks CD_MASK_BMESH = {
/*emask*/ (CD_MASK_CREASE | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL),
/*fmask*/ 0,
/*pmask*/
(CD_MASK_FREESTYLE_FACE | CD_MASK_FACEMAP | CD_MASK_PROP_ALL),
(CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL),
/*lmask*/
(CD_MASK_MDISPS | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
};
@ -2066,8 +2052,7 @@ const CustomData_MeshMasks CD_MASK_EVERYTHING = {
CD_MASK_ORIGSPACE | CD_MASK_TANGENT | CD_MASK_TESSLOOPNORMAL | CD_MASK_PREVIEW_MCOL |
CD_MASK_PROP_ALL),
/*pmask*/
(CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_FACEMAP | CD_MASK_FREESTYLE_FACE |
CD_MASK_PROP_ALL),
(CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL),
/*lmask*/
(CD_MASK_BM_ELEM_PYPTR | CD_MASK_MDISPS | CD_MASK_NORMAL | CD_MASK_CUSTOMLOOPNORMAL |
CD_MASK_MLOOPTANGENT | CD_MASK_PREVIEW_MLOOPCOL | CD_MASK_ORIGSPACE_MLOOP |
@ -5169,9 +5154,6 @@ void CustomData_blend_write(BlendWriter *writer,
case CD_GRID_PAINT_MASK:
write_grid_paint_mask(writer, count, static_cast<const GridPaintMask *>(layer.data));
break;
case CD_FACEMAP:
BLO_write_raw(writer, sizeof(int) * count, static_cast<const int *>(layer.data));
break;
case CD_PROP_BOOL:
BLO_write_raw(writer, sizeof(bool) * count, static_cast<const bool *>(layer.data));
break;

View File

@ -808,44 +808,6 @@ void BKE_mesh_ensure_skin_customdata(Mesh *me)
}
}
bool BKE_mesh_ensure_facemap_customdata(Mesh *me)
{
BMesh *bm = me->edit_mesh ? me->edit_mesh->bm : nullptr;
bool changed = false;
if (bm) {
if (!CustomData_has_layer(&bm->pdata, CD_FACEMAP)) {
BM_data_layer_add(bm, &bm->pdata, CD_FACEMAP);
changed = true;
}
}
else {
if (!CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
CustomData_add_layer(&me->pdata, CD_FACEMAP, CD_SET_DEFAULT, me->totpoly);
changed = true;
}
}
return changed;
}
bool BKE_mesh_clear_facemap_customdata(Mesh *me)
{
BMesh *bm = me->edit_mesh ? me->edit_mesh->bm : nullptr;
bool changed = false;
if (bm) {
if (CustomData_has_layer(&bm->pdata, CD_FACEMAP)) {
BM_data_layer_free(bm, &bm->pdata, CD_FACEMAP);
changed = true;
}
}
else {
if (CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
CustomData_free_layers(&me->pdata, CD_FACEMAP, me->totpoly);
changed = true;
}
}
return changed;
}
bool BKE_mesh_has_custom_loop_normals(Mesh *me)
{
if (me->edit_mesh) {

View File

@ -1305,6 +1305,40 @@ void BKE_mesh_legacy_face_set_to_generic(Mesh *mesh)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Face Map Conversion
* \{ */
void BKE_mesh_legacy_face_map_to_generic(Mesh *mesh)
{
using namespace blender;
if (mesh->attributes().contains("face_maps")) {
return;
}
void *data = nullptr;
const ImplicitSharingInfo *sharing_info = nullptr;
for (const int i : IndexRange(mesh->pdata.totlayer)) {
CustomDataLayer &layer = mesh->pdata.layers[i];
if (layer.type == CD_FACEMAP) {
data = layer.data;
sharing_info = layer.sharing_info;
layer.data = nullptr;
layer.sharing_info = nullptr;
CustomData_free_layer(&mesh->pdata, CD_FACEMAP, mesh->totpoly, i);
break;
}
}
if (data != nullptr) {
CustomData_add_layer_named_with_data(
&mesh->pdata, CD_PROP_INT32, data, mesh->totpoly, "face_maps", sharing_info);
}
if (sharing_info != nullptr) {
sharing_info->remove_user_and_delete_if_last();
}
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Bevel Weight Conversion
* \{ */

View File

@ -759,6 +759,10 @@ class NodeTreeMainUpdater {
LISTBASE_FOREACH (bNodeLink *, link, &ntree.links) {
link->flag |= NODE_LINK_VALID;
if (!link->fromsock->is_available() || !link->tosock->is_available()) {
link->flag &= ~NODE_LINK_VALID;
continue;
}
const bNode &from_node = *link->fromnode;
const bNode &to_node = *link->tonode;
if (toposort_indices[from_node.index()] > toposort_indices[to_node.index()]) {

View File

@ -114,7 +114,6 @@
#include "BKE_multires.h"
#include "BKE_node.hh"
#include "BKE_object.h"
#include "BKE_object_facemap.h"
#include "BKE_paint.h"
#include "BKE_particle.h"
#include "BKE_pbvh.h"
@ -233,7 +232,6 @@ static void object_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const in
}
}
BKE_object_facemap_copy_list(&ob_dst->fmaps, &ob_src->fmaps);
BKE_constraints_copy_ex(&ob_dst->constraints, &ob_src->constraints, flag_subdata, true);
ob_dst->mode = ob_dst->type != OB_GPENCIL_LEGACY ? OB_MODE_OBJECT : ob_dst->mode;
@ -302,7 +300,6 @@ static void object_free_data(ID *id)
MEM_SAFE_FREE(ob->iuser);
MEM_SAFE_FREE(ob->runtime.bb);
BLI_freelistN(&ob->fmaps);
if (ob->pose) {
BKE_pose_free_ex(ob->pose, false);
ob->pose = nullptr;
@ -546,13 +543,6 @@ static void object_foreach_path(ID *id, BPathForeachPathData *bpath_data)
}
}
static void write_fmaps(BlendWriter *writer, ListBase *fbase)
{
LISTBASE_FOREACH (bFaceMap *, fmap, fbase) {
BLO_write_struct(writer, bFaceMap, fmap);
}
}
static void object_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
Object *ob = (Object *)id;
@ -586,7 +576,6 @@ static void object_blend_write(BlendWriter *writer, ID *id, const void *id_addre
}
BKE_pose_blend_write(writer, ob->pose, arm);
write_fmaps(writer, &ob->fmaps);
BKE_constraint_blend_write(writer, &ob->constraints);
animviz_motionpath_blend_write(writer, ob->mpath);
@ -682,7 +671,6 @@ static void object_blend_read_data(BlendDataReader *reader, ID *id)
/* Only for versioning, vertex group names are now stored on object data. */
BLO_read_list(reader, &ob->defbase);
BLO_read_list(reader, &ob->fmaps);
/* XXX deprecated - old animation system <<< */
direct_link_nlastrips(reader, &ob->nlastrips);
BLO_read_list(reader, &ob->constraintChannels);

View File

@ -1,286 +0,0 @@
/* SPDX-FileCopyrightText: 2008 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup bke
*/
#include <string.h>
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLI_string_utils.h"
#include "BLI_utildefines.h"
#include "BKE_customdata.h"
#include "BKE_editmesh.h"
#include "BKE_object.h"
#include "BKE_object_deform.h"
#include "BKE_object_facemap.h" /* own include */
#include "BLT_translation.h"
#include "MEM_guardedalloc.h"
#include "RNA_access.h"
#include "RNA_define.h"
static bool fmap_unique_check(void *arg, const char *name)
{
struct {
Object *ob;
void *fm;
} *data = arg;
bFaceMap *fmap;
for (fmap = data->ob->fmaps.first; fmap; fmap = fmap->next) {
if (data->fm != fmap) {
if (STREQ(fmap->name, name)) {
return true;
}
}
}
return false;
}
static bFaceMap *fmap_duplicate(bFaceMap *infmap)
{
bFaceMap *outfmap;
if (!infmap) {
return NULL;
}
outfmap = MEM_callocN(sizeof(bFaceMap), "copy facemap");
/* For now, just copy everything over. */
memcpy(outfmap, infmap, sizeof(bFaceMap));
outfmap->next = outfmap->prev = NULL;
return outfmap;
}
void BKE_object_facemap_copy_list(ListBase *outbase, const ListBase *inbase)
{
bFaceMap *fmap, *fmapn;
BLI_listbase_clear(outbase);
for (fmap = inbase->first; fmap; fmap = fmap->next) {
fmapn = fmap_duplicate(fmap);
BLI_addtail(outbase, fmapn);
}
}
void BKE_object_facemap_unique_name(Object *ob, bFaceMap *fmap)
{
struct {
Object *ob;
void *fmap;
} data;
data.ob = ob;
data.fmap = fmap;
BLI_uniquename_cb(fmap_unique_check, &data, DATA_("Group"), '.', fmap->name, sizeof(fmap->name));
}
bFaceMap *BKE_object_facemap_add_name(Object *ob, const char *name)
{
bFaceMap *fmap;
if (!ob || ob->type != OB_MESH) {
return NULL;
}
fmap = MEM_callocN(sizeof(bFaceMap), __func__);
STRNCPY(fmap->name, name);
BLI_addtail(&ob->fmaps, fmap);
ob->actfmap = BLI_listbase_count(&ob->fmaps);
BKE_object_facemap_unique_name(ob, fmap);
return fmap;
}
bFaceMap *BKE_object_facemap_add(Object *ob)
{
return BKE_object_facemap_add_name(ob, DATA_("FaceMap"));
}
static void object_fmap_remove_edit_mode(Object *ob, bFaceMap *fmap, bool do_selected, bool purge)
{
const int fmap_nr = BLI_findindex(&ob->fmaps, fmap);
if (ob->type == OB_MESH) {
Mesh *me = ob->data;
if (me->edit_mesh) {
BMEditMesh *em = me->edit_mesh;
const int cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
if (cd_fmap_offset != -1) {
BMFace *efa;
BMIter iter;
int *map;
if (purge) {
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
if (map) {
if (*map == fmap_nr) {
*map = -1;
}
else if (*map > fmap_nr) {
*map -= 1;
}
}
}
}
else {
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
if (map && *map == fmap_nr && (!do_selected || BM_elem_flag_test(efa, BM_ELEM_SELECT)))
{
*map = -1;
}
}
}
}
if (ob->actfmap == BLI_listbase_count(&ob->fmaps)) {
ob->actfmap--;
}
BLI_remlink(&ob->fmaps, fmap);
MEM_freeN(fmap);
}
}
}
static void object_fmap_remove_object_mode(Object *ob, bFaceMap *fmap, bool purge)
{
const int fmap_nr = BLI_findindex(&ob->fmaps, fmap);
if (ob->type == OB_MESH) {
Mesh *me = ob->data;
if (CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
int *map = CustomData_get_layer_for_write(&me->pdata, CD_FACEMAP, me->totpoly);
int i;
if (map) {
for (i = 0; i < me->totpoly; i++) {
if (map[i] == fmap_nr) {
map[i] = -1;
}
else if (purge && map[i] > fmap_nr) {
map[i]--;
}
}
}
}
if (ob->actfmap == BLI_listbase_count(&ob->fmaps)) {
ob->actfmap--;
}
BLI_remlink(&ob->fmaps, fmap);
MEM_freeN(fmap);
}
}
static void fmap_remove_exec(Object *ob, bFaceMap *fmap, const bool is_edit_mode, const bool purge)
{
if (is_edit_mode) {
object_fmap_remove_edit_mode(ob, fmap, false, purge);
}
else {
object_fmap_remove_object_mode(ob, fmap, purge);
}
}
void BKE_object_facemap_remove(Object *ob, bFaceMap *fmap)
{
fmap_remove_exec(ob, fmap, BKE_object_is_in_editmode(ob), true);
}
void BKE_object_facemap_clear(Object *ob)
{
bFaceMap *fmap = (bFaceMap *)ob->fmaps.first;
if (fmap) {
const bool edit_mode = BKE_object_is_in_editmode_vgroup(ob);
while (fmap) {
bFaceMap *next_fmap = fmap->next;
fmap_remove_exec(ob, fmap, edit_mode, false);
fmap = next_fmap;
}
}
/* remove all face-maps */
if (ob->type == OB_MESH) {
Mesh *me = ob->data;
CustomData_free_layer(&me->pdata, CD_FACEMAP, me->totpoly, 0);
}
ob->actfmap = 0;
}
int BKE_object_facemap_name_index(Object *ob, const char *name)
{
return (name) ? BLI_findstringindex(&ob->fmaps, name, offsetof(bFaceMap, name)) : -1;
}
bFaceMap *BKE_object_facemap_find_name(Object *ob, const char *name)
{
return BLI_findstring(&ob->fmaps, name, offsetof(bFaceMap, name));
}
int *BKE_object_facemap_index_map_create(Object *ob_src, Object *ob_dst, int *r_map_len)
{
/* Build src to merged mapping of facemap indices. */
if (BLI_listbase_is_empty(&ob_src->fmaps) || BLI_listbase_is_empty(&ob_dst->fmaps)) {
*r_map_len = 0;
return NULL;
}
*r_map_len = BLI_listbase_count(&ob_src->fmaps);
int *fmap_index_map = MEM_malloc_arrayN(
*r_map_len, sizeof(*fmap_index_map), "defgroup index map create");
bool is_fmap_remap_needed = false;
int i = 0;
for (bFaceMap *fmap_src = ob_src->fmaps.first; fmap_src; fmap_src = fmap_src->next, i++) {
fmap_index_map[i] = BKE_object_facemap_name_index(ob_dst, fmap_src->name);
is_fmap_remap_needed = is_fmap_remap_needed || (fmap_index_map[i] != i);
}
if (!is_fmap_remap_needed) {
MEM_freeN(fmap_index_map);
fmap_index_map = NULL;
*r_map_len = 0;
}
return fmap_index_map;
}
void BKE_object_facemap_index_map_apply(int *fmap, int fmap_len, const int *map, int map_len)
{
if (map == NULL || map_len == 0) {
return;
}
for (int i = 0; i < fmap_len; i++, fmap++) {
*fmap = (*fmap < map_len && *fmap != -1) ? map[*fmap] : -1;
}
}

View File

@ -1569,7 +1569,6 @@ static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm,
loopindex2);
loopindex2++;
/* Copy over poly data, e.g. #CD_FACEMAP. */
CustomData_copy_data(&dm->polyData, &ccgdm->dm.polyData, origIndex, faceNum, 1);
if (polyOrigIndex) {

View File

@ -182,14 +182,30 @@ void blo_do_versions_400(FileData * /*fd*/, Library * /*lib*/, Main *bmain)
if (!MAIN_VERSION_ATLEAST(bmain, 400, 5)) {
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
ToolSettings *ts = scene->toolsettings;
if (ts->snap_mode_tools != SCE_SNAP_MODE_NONE) {
ts->snap_mode_tools = SCE_SNAP_MODE_GEOM;
}
#define SCE_SNAP_PROJECT (1 << 3)
if (scene->toolsettings->snap_flag & SCE_SNAP_PROJECT) {
scene->toolsettings->snap_mode |= SCE_SNAP_MODE_FACE_RAYCAST;
if (ts->snap_flag & SCE_SNAP_PROJECT) {
ts->snap_mode |= SCE_SNAP_MODE_FACE_RAYCAST;
}
#undef SCE_SNAP_PROJECT
}
}
if (!MAIN_VERSION_ATLEAST(bmain, 400, 6)) {
LISTBASE_FOREACH (Mesh *, mesh, &bmain->meshes) {
BKE_mesh_legacy_face_map_to_generic(mesh);
}
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
versioning_replace_legacy_glossy_node(ntree);
versioning_remove_microfacet_sharp_distribution(ntree);
}
FOREACH_NODETREE_END;
}
/**
* Versioning code until next subversion bump goes here.
*
@ -204,11 +220,6 @@ void blo_do_versions_400(FileData * /*fd*/, Library * /*lib*/, Main *bmain)
*/
{
/* Convert anisotropic BSDF node to glossy BSDF. */
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
versioning_replace_legacy_glossy_node(ntree);
versioning_remove_microfacet_sharp_distribution(ntree);
}
FOREACH_NODETREE_END;
/* Keep this block, even when empty. */
}

View File

@ -62,7 +62,6 @@ enum {
SIMFACE_NORMAL,
SIMFACE_COPLANAR,
SIMFACE_SMOOTH,
SIMFACE_FACEMAP,
SIMFACE_FREESTYLE,
};

View File

@ -4,6 +4,7 @@
#include "COM_KuwaharaNode.h"
#include "COM_ConvolutionFilterOperation.h"
#include "COM_FastGaussianBlurOperation.h"
#include "COM_KuwaharaAnisotropicOperation.h"
#include "COM_KuwaharaClassicOperation.h"

View File

@ -101,6 +101,11 @@ void KuwaharaClassicOperation::execute_pixel_sampled(float output[4],
}
output[ch] = mean[min_index];
}
/* No changes for alpha channel. */
float tmp[4];
image_reader_->read_sampled(tmp, x, y, sampler);
output[3] = tmp[3];
}
void KuwaharaClassicOperation::set_kernel_size(int kernel_size)

View File

@ -45,9 +45,14 @@ class Context {
/* Get the node tree used for compositing. */
virtual const bNodeTree &get_node_tree() const = 0;
/* True if compositor should do write file outputs, false if only running for viewing. */
/* True if the compositor should write file outputs, false otherwise. */
virtual bool use_file_output() const = 0;
/* True if the compositor should write the composite output, otherwise, the compositor is assumed
* to not support the composite output and just displays its viewer output. In that case, the
* composite output will be used as a fallback viewer if no other viewer exists */
virtual bool use_composite_output() const = 0;
/* True if color management should be used for texture evaluation. */
virtual bool use_texture_color_management() const = 0;
@ -66,10 +71,14 @@ class Context {
* region. */
virtual rcti get_compositing_region() const = 0;
/* Get the texture representing the output where the result of the compositor should be
* written. This should be called by output nodes to get their target texture. */
/* Get the texture where the result of the compositor should be written. This should be called by
* the composite output node to get its target texture. */
virtual GPUTexture *get_output_texture() = 0;
/* Get the texture where the result of the compositor viewer should be written. This should be
* called by viewer output nodes to get their target texture. */
virtual GPUTexture *get_viewer_output_texture() = 0;
/* Get the texture where the given render pass is stored. This should be called by the Render
* Layer node to populate its outputs. */
virtual GPUTexture *get_input_texture(int view_layer, const char *pass_name) = 0;

View File

@ -8,6 +8,8 @@
#include "NOD_derived_node_tree.hh"
#include "COM_context.hh"
namespace blender::realtime_compositor {
using namespace nodes::derived_node_tree_types;
@ -18,6 +20,6 @@ using Schedule = VectorSet<DNode>;
/* Computes the execution schedule of the node tree. This is essentially a post-order depth first
* traversal of the node tree from the output node to the leaf input nodes, with informed order of
* traversal of dependencies based on a heuristic estimation of the number of needed buffers. */
Schedule compute_schedule(const DerivedNodeTree &tree);
Schedule compute_schedule(const Context &context, const DerivedNodeTree &tree);
} // namespace blender::realtime_compositor

View File

@ -72,7 +72,7 @@ void Evaluator::compile_and_evaluate()
return;
}
const Schedule schedule = compute_schedule(*derived_node_tree_);
const Schedule schedule = compute_schedule(context_, *derived_node_tree_);
CompileState compile_state(schedule);

View File

@ -13,6 +13,7 @@
#include "BKE_node.hh"
#include "BKE_node_runtime.hh"
#include "COM_context.hh"
#include "COM_scheduler.hh"
#include "COM_utilities.hh"
@ -72,55 +73,88 @@ static const DTreeContext *find_active_context(const DerivedNodeTree &tree)
return find_active_context_recursive(&tree.root_context(), NODE_INSTANCE_KEY_BASE);
}
/* Return the output node which is marked as NODE_DO_OUTPUT. If multiple types of output nodes are
* marked, then the preference will be CMP_NODE_VIEWER > CMP_NODE_SPLITVIEWER > CMP_NODE_COMPOSITE.
* If no output node exists, a null node will be returned. */
static DNode find_output_in_context(const DTreeContext *context)
/* Add the viewer node which is marked as NODE_DO_OUTPUT in the given context to the given stack.
* If multiple types of viewer nodes are marked, then the preference will be CMP_NODE_VIEWER >
* CMP_NODE_SPLITVIEWER. If no viewer nodes were found, composite nodes can be added as a fallback
* viewer node. */
static bool add_viewer_nodes_in_context(const DTreeContext *context, Stack<DNode> &node_stack)
{
const bNodeTree &tree = context->btree();
for (const bNode *node : tree.nodes_by_type("CompositorNodeViewer")) {
for (const bNode *node : context->btree().nodes_by_type("CompositorNodeViewer")) {
if (node->flag & NODE_DO_OUTPUT) {
return DNode(context, node);
node_stack.push(DNode(context, node));
return true;
}
}
for (const bNode *node : tree.nodes_by_type("CompositorNodeSplitViewer")) {
for (const bNode *node : context->btree().nodes_by_type("CompositorNodeSplitViewer")) {
if (node->flag & NODE_DO_OUTPUT) {
return DNode(context, node);
node_stack.push(DNode(context, node));
return true;
}
}
for (const bNode *node : tree.nodes_by_type("CompositorNodeComposite")) {
/* The active Composite node was already added, no need to add it again, see the next block. */
if (!node_stack.is_empty() && node_stack.peek()->type == CMP_NODE_COMPOSITE) {
return false;
}
/* No active viewers exist in this context, try to add the Composite node as a fallback viewer if
* it was not already added. */
for (const bNode *node : context->btree().nodes_by_type("CompositorNodeComposite")) {
if (node->flag & NODE_DO_OUTPUT) {
return DNode(context, node);
node_stack.push(DNode(context, node));
return true;
}
}
return DNode();
return false;
}
/* Compute the output node whose result should be computed. This node is the output node that
* satisfies the requirements in the find_output_in_context function. First, the active context is
* searched for an output node, if non was found, the root context is search. For more information
* on what contexts mean here, see the find_active_context function. */
static DNode compute_output_node(const DerivedNodeTree &tree)
/* Add the output nodes whose result should be computed to the given stack. This includes File
* Output, Composite, and Viewer nodes. Viewer nodes are a special case, as only the nodes that
* satisfies the requirements in the add_viewer_nodes_in_context function are added. First, the
* active context is searched for viewer nodes, if non were found, the root context is searched.
* For more information on what contexts mean here, see the find_active_context function. */
static void add_output_nodes(const Context &context,
const DerivedNodeTree &tree,
Stack<DNode> &node_stack)
{
const DTreeContext &root_context = tree.root_context();
/* Only add File Output nodes if the context supports them. */
if (context.use_file_output()) {
for (const bNode *node : root_context.btree().nodes_by_type("CompositorNodeOutputFile")) {
node_stack.push(DNode(&root_context, node));
}
}
/* Only add the Composite output node if the context supports composite outputs. The active
* Composite node may still be added as a fallback viewer output below. */
if (context.use_composite_output()) {
for (const bNode *node : root_context.btree().nodes_by_type("CompositorNodeComposite")) {
if (node->flag & NODE_DO_OUTPUT) {
node_stack.push(DNode(&root_context, node));
break;
}
}
}
const DTreeContext *active_context = find_active_context(tree);
const bool viewer_was_added = add_viewer_nodes_in_context(active_context, node_stack);
const DNode node = find_output_in_context(active_context);
if (node) {
return node;
/* An active viewer was added, no need to search further. */
if (viewer_was_added) {
return;
}
/* If the active context is the root one and no output node was found, we consider this node tree
* to have no output node, even if one of the non-active descendants have an output node. */
/* If the active context is the root one and no viewer nodes were found, we consider this node
* tree to have no viewer nodes, even if one of the non-active descendants have viewer nodes. */
if (active_context->is_root()) {
return DNode();
return;
}
/* The active context doesn't have an output node, search in the root context as a fallback. */
return find_output_in_context(&tree.root_context());
/* The active context doesn't have a viewer node, search in the root context as a fallback. */
add_viewer_nodes_in_context(&tree.root_context(), node_stack);
}
/* A type representing a mapping that associates each node with a heuristic estimation of the
@ -177,12 +211,12 @@ using NeededBuffers = Map<DNode, int>;
* implementation because it rarely affects the output and is done by very few nodes.
* - The compiler may decide to compiler the schedule differently depending on runtime information
* which we can merely speculate at scheduling-time as described above. */
static NeededBuffers compute_number_of_needed_buffers(DNode output_node)
static NeededBuffers compute_number_of_needed_buffers(Stack<DNode> &output_nodes)
{
NeededBuffers needed_buffers;
/* A stack of nodes used to traverse the node tree starting from the output node. */
Stack<DNode> node_stack = {output_node};
/* A stack of nodes used to traverse the node tree starting from the output nodes. */
Stack<DNode> node_stack = output_nodes;
/* Traverse the node tree in a post order depth first manner and compute the number of needed
* buffers for each node. Post order traversal guarantee that all the node dependencies of each
@ -301,23 +335,23 @@ static NeededBuffers compute_number_of_needed_buffers(DNode output_node)
* doesn't always guarantee an optimal evaluation order, as the optimal evaluation order is very
* difficult to compute, however, this method works well in most cases. Moreover it assumes that
* all buffers will have roughly the same size, which may not always be the case. */
Schedule compute_schedule(const DerivedNodeTree &tree)
Schedule compute_schedule(const Context &context, const DerivedNodeTree &tree)
{
Schedule schedule;
/* Compute the output node whose result should be computed. */
const DNode output_node = compute_output_node(tree);
/* A stack of nodes used to traverse the node tree starting from the output nodes. */
Stack<DNode> node_stack;
/* No output node, the node tree has no effect, return an empty schedule. */
if (!output_node) {
/* Add the output nodes whose result should be computed to the stack. */
add_output_nodes(context, tree, node_stack);
/* No output nodes, the node tree has no effect, return an empty schedule. */
if (node_stack.is_empty()) {
return schedule;
}
/* Compute the number of buffers needed by each node connected to the output. */
const NeededBuffers needed_buffers = compute_number_of_needed_buffers(output_node);
/* A stack of nodes used to traverse the node tree starting from the output node. */
Stack<DNode> node_stack = {output_node};
/* Compute the number of buffers needed by each node connected to the outputs. */
const NeededBuffers needed_buffers = compute_number_of_needed_buffers(node_stack);
/* Traverse the node tree in a post order depth first manner, scheduling the nodes in an order
* informed by the number of buffers needed by each node. Post order traversal guarantee that all

View File

@ -10,7 +10,19 @@ GPU_SHADER_CREATE_INFO(compositor_read_pass_shared)
.sampler(0, ImageType::FLOAT_2D, "input_tx")
.compute_source("compositor_read_pass.glsl");
GPU_SHADER_CREATE_INFO(compositor_read_pass)
GPU_SHADER_CREATE_INFO(compositor_read_pass_float)
.additional_info("compositor_read_pass_shared")
.image(0, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
.define("READ_EXPRESSION(pass_color)", "vec4(pass_color.r, vec3(0.0))")
.do_static_compilation(true);
GPU_SHADER_CREATE_INFO(compositor_read_pass_vector)
.additional_info("compositor_read_pass_shared")
.image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
.define("READ_EXPRESSION(pass_color)", "pass_color")
.do_static_compilation(true);
GPU_SHADER_CREATE_INFO(compositor_read_pass_color)
.additional_info("compositor_read_pass_shared")
.image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
.define("READ_EXPRESSION(pass_color)", "pass_color")

View File

@ -68,6 +68,14 @@ class Context : public realtime_compositor::Context {
return false;
}
/* The viewport compositor doesn't really support the composite output, it only displays the
* viewer output in the viewport. Settings this to false will make the compositor use the
* composite output as fallback viewer if no other viewer exists. */
bool use_composite_output() const override
{
return false;
}
bool use_texture_color_management() const override
{
return BKE_scene_check_color_management_enabled(DRW_context_state_get()->scene);
@ -145,6 +153,11 @@ class Context : public realtime_compositor::Context {
return DRW_viewport_texture_list_get()->color;
}
GPUTexture *get_viewer_output_texture() override
{
return DRW_viewport_texture_list_get()->color;
}
GPUTexture *get_input_texture(int view_layer, const char *pass_name) override
{
if (view_layer == 0 && STREQ(pass_name, RE_PASSNAME_COMBINED)) {

View File

@ -184,7 +184,7 @@ static void drw_shgroup_uniform_create_ex(DRWShadingGroup *shgroup,
/* Happens on first uniform or if chunk is full. */
if (!unichunk || unichunk->uniform_used == unichunk->uniform_len) {
unichunk = static_cast<DRWUniformChunk *>(BLI_memblock_alloc(DST.vmempool->uniforms));
unichunk->uniform_len = ARRAY_SIZE(shgroup->uniforms->uniforms);
unichunk->uniform_len = BOUNDED_ARRAY_TYPE_SIZE<decltype(shgroup->uniforms->uniforms)>();
unichunk->uniform_used = 0;
BLI_LINKS_PREPEND(shgroup->uniforms, unichunk);
}

View File

@ -265,6 +265,10 @@ static bool need_extra_redraw_after_scrubbing_ends(bContext *C)
* scrubbing, the actual result should be shown again. */
return true;
}
Scene *scene = CTX_data_scene(C);
if (scene->eevee.flag & SCE_EEVEE_TAA_REPROJECTION) {
return true;
}
wmWindowManager *wm = CTX_wm_manager(C);
Object *object = CTX_data_active_object(C);
if (object && object->type == OB_GPENCIL_LEGACY) {

View File

@ -38,9 +38,9 @@ set(SRC
ED_asset_catalog.h
ED_asset_catalog.hh
ED_asset_filter.h
ED_asset_filter.hh
ED_asset_handle.h
ED_asset_import.h
ED_asset_import.hh
ED_asset_indexer.h
ED_asset_library.h
ED_asset_list.h

View File

@ -10,12 +10,11 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
struct AssetFilterSettings;
struct AssetHandle;
namespace blender::asset_system {
class AssetRepresentation;
}
/**
* Compare \a asset against the settings of \a filter.
@ -29,9 +28,5 @@ struct AssetHandle;
* \returns True if the asset should be visible with these filter settings (parameters match).
* Otherwise returns false (mismatch).
*/
bool ED_asset_filter_matches_asset(const struct AssetFilterSettings *filter,
const struct AssetHandle *asset);
#ifdef __cplusplus
}
#endif
bool ED_asset_filter_matches_asset(const AssetFilterSettings *filter,
const blender::asset_system::AssetRepresentation &asset);

View File

@ -34,23 +34,7 @@ void ED_asset_handle_get_full_library_path(
/* `1024` for #FILE_MAX,
* rely on warnings to let us know if this gets out of sync. */
char r_full_lib_path[1024]);
bool ED_asset_handle_get_use_relative_path(const struct AssetHandle *asset);
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
# include <optional>
# include "BLI_string_ref.hh"
/** The asset library may have an import method (e.g. append vs. link) defined to use. If so, this
* returns it. Otherwise a reasonable method should be used, usually "Append (Reuse Data)". */
std::optional<eAssetImportMethod> ED_asset_handle_get_import_method(
const struct AssetHandle *asset);
blender::StringRefNull ED_asset_handle_get_library_relative_identifier(const AssetHandle &asset);
#endif

View File

@ -10,16 +10,11 @@
#include "DNA_ID_enums.h"
struct AssetRepresentation;
struct Main;
#ifdef __cplusplus
extern "C" {
#endif
namespace blender::asset_system {
class AssetRepresentation;
}
struct ID *ED_asset_get_local_id_from_asset_or_append_and_reuse(
struct Main *bmain, const struct AssetRepresentation *asset_c_ptr, ID_Type idtype);
#ifdef __cplusplus
}
#endif
Main *bmain, const blender::asset_system::AssetRepresentation &asset, ID_Type idtype);

View File

@ -10,6 +10,12 @@
#include "DNA_asset_types.h"
#ifdef __cplusplus
namespace blender::asset_system {
class AssetRepresentation;
}
#endif
#ifdef __cplusplus
extern "C" {
#endif
@ -52,8 +58,12 @@ void ED_assetlist_storage_id_remap(struct ID *id_old, struct ID *id_new);
*/
void ED_assetlist_storage_exit(void);
AssetHandle ED_assetlist_asset_get_by_index(const AssetLibraryReference *library_reference,
int asset_index);
AssetHandle ED_assetlist_asset_handle_get_by_index(const AssetLibraryReference *library_reference,
int asset_index);
#ifdef __cplusplus
blender::asset_system::AssetRepresentation *ED_assetlist_asset_get_by_index(
const AssetLibraryReference &library_reference, int asset_index);
#endif
struct ImBuf *ED_assetlist_asset_image_get(const AssetHandle *asset_handle);

View File

@ -17,7 +17,8 @@ struct AssetLibraryReference;
namespace blender::asset_system {
class AssetLibrary;
}
class AssetRepresentation;
} // namespace blender::asset_system
/**
* Get the asset library being read into an asset-list and identified using \a library_reference.
@ -31,9 +32,13 @@ blender::asset_system::AssetLibrary *ED_assetlist_library_get_once_available(
const AssetLibraryReference &library_reference);
/* Can return false to stop iterating. */
using AssetListIterFn = blender::FunctionRef<bool(AssetHandle)>;
using AssetListHandleIterFn = blender::FunctionRef<bool(AssetHandle)>;
using AssetListIterFn = blender::FunctionRef<bool(blender::asset_system::AssetRepresentation &)>;
/**
* \warning Never keep the asset handle passed to \a fn outside of \a fn's scope. While iterating,
* the file data wrapped by the asset handle can be freed, since the file cache has a maximum size.
*/
void ED_assetlist_iterate(const AssetLibraryReference &library_reference,
AssetListHandleIterFn fn);
void ED_assetlist_iterate(const AssetLibraryReference &library_reference, AssetListIterFn fn);

View File

@ -6,18 +6,22 @@
* \ingroup edasset
*/
#include "AS_asset_representation.hh"
#include "BKE_idtype.h"
#include "BLI_listbase.h"
#include "DNA_asset_types.h"
#include "ED_asset_filter.h"
#include "ED_asset_handle.h"
#include "ED_asset_filter.hh"
bool ED_asset_filter_matches_asset(const AssetFilterSettings *filter, const AssetHandle *asset)
using namespace blender;
bool ED_asset_filter_matches_asset(const AssetFilterSettings *filter,
const asset_system::AssetRepresentation &asset)
{
ID_Type asset_type = ED_asset_handle_get_id_type(asset);
ID_Type asset_type = asset.get_id_type();
uint64_t asset_id_filter = BKE_idtype_idcode_to_idfilter(asset_type);
if ((filter->id_types & asset_id_filter) == 0) {
@ -25,10 +29,10 @@ bool ED_asset_filter_matches_asset(const AssetFilterSettings *filter, const Asse
}
/* Not very efficient (O(n^2)), could be improved quite a bit. */
LISTBASE_FOREACH (const AssetTag *, filter_tag, &filter->tags) {
AssetMetaData *asset_data = ED_asset_handle_get_metadata(asset);
AssetMetaData &asset_data = asset.get_metadata();
AssetTag *matched_tag = (AssetTag *)BLI_findstring(
&asset_data->tags, filter_tag->name, offsetof(AssetTag, name));
&asset_data.tags, filter_tag->name, offsetof(AssetTag, name));
if (matched_tag == nullptr) {
return false;
}

View File

@ -43,7 +43,7 @@ ID *ED_asset_handle_get_local_id(const AssetHandle *asset_handle)
ID_Type ED_asset_handle_get_id_type(const AssetHandle *asset_handle)
{
return static_cast<ID_Type>(AS_asset_representation_id_type_get(asset_handle->file_data->asset));
return AS_asset_representation_id_type_get(asset_handle->file_data->asset);
}
int ED_asset_handle_get_preview_icon_id(const AssetHandle *asset)
@ -51,17 +51,6 @@ int ED_asset_handle_get_preview_icon_id(const AssetHandle *asset)
return asset->file_data->preview_icon_id;
}
std::optional<eAssetImportMethod> ED_asset_handle_get_import_method(
const AssetHandle *asset_handle)
{
return AS_asset_representation_import_method_get(asset_handle->file_data->asset);
}
blender::StringRefNull ED_asset_handle_get_library_relative_identifier(const AssetHandle &asset)
{
return AS_asset_representation_library_relative_identifier_get(asset.file_data->asset);
}
void ED_asset_handle_get_full_library_path(const AssetHandle *asset_handle,
char r_full_lib_path[FILE_MAX])
{
@ -75,8 +64,3 @@ void ED_asset_handle_get_full_library_path(const AssetHandle *asset_handle,
BLI_strncpy(r_full_lib_path, library_path.c_str(), FILE_MAX);
}
bool ED_asset_handle_get_use_relative_path(const AssetHandle *asset)
{
return AS_asset_representation_use_relative_path_get(asset->file_data->asset);
}

View File

@ -6,24 +6,19 @@
* \ingroup edasset
*/
#include "AS_asset_representation.h"
#include "AS_asset_representation.hh"
#include "BLO_readfile.h"
#include "WM_api.h"
#include "ED_asset_import.h"
#include "ED_asset_import.hh"
using namespace blender;
ID *ED_asset_get_local_id_from_asset_or_append_and_reuse(Main *bmain,
const AssetRepresentation *asset_c_ptr,
ID_Type idtype)
ID *ED_asset_get_local_id_from_asset_or_append_and_reuse(
Main *bmain, const asset_system::AssetRepresentation &asset, ID_Type idtype)
{
const asset_system::AssetRepresentation &asset =
*reinterpret_cast<const asset_system::AssetRepresentation *>(asset_c_ptr);
if (ID *local_id = asset.local_id()) {
return local_id;
}

View File

@ -31,7 +31,6 @@
#include "../space_file/file_indexer.h"
#include "../space_file/filelist.h"
#include "ED_asset_handle.h"
#include "ED_asset_indexer.h"
#include "ED_asset_list.h"
#include "ED_asset_list.hh"
@ -121,6 +120,7 @@ class AssetList : NonCopyable {
bool needsRefetch() const;
bool isLoaded() const;
asset_system::AssetLibrary *asset_library() const;
void iterate(AssetListHandleIterFn fn) const;
void iterate(AssetListIterFn fn) const;
int size() const;
void tagMainDataDirty() const;
@ -196,7 +196,7 @@ asset_system::AssetLibrary *AssetList::asset_library() const
return reinterpret_cast<asset_system::AssetLibrary *>(filelist_asset_library(filelist_));
}
void AssetList::iterate(AssetListIterFn fn) const
void AssetList::iterate(AssetListHandleIterFn fn) const
{
FileList *files = filelist_;
int numfiles = filelist_files_ensure(files);
@ -215,6 +215,16 @@ void AssetList::iterate(AssetListIterFn fn) const
}
}
void AssetList::iterate(AssetListIterFn fn) const
{
iterate([&fn](AssetHandle handle) {
asset_system::AssetRepresentation &asset =
reinterpret_cast<blender::asset_system::AssetRepresentation &>(*handle.file_data->asset);
return fn(asset);
});
}
void AssetList::ensurePreviewsJob(const bContext *C)
{
FileList *files = filelist_;
@ -465,6 +475,14 @@ bool ED_assetlist_storage_has_list_for_library(const AssetLibraryReference *libr
return AssetListStorage::lookup_list(*library_reference) != nullptr;
}
void ED_assetlist_iterate(const AssetLibraryReference &library_reference, AssetListHandleIterFn fn)
{
AssetList *list = AssetListStorage::lookup_list(library_reference);
if (list) {
list->iterate(fn);
}
}
void ED_assetlist_iterate(const AssetLibraryReference &library_reference, AssetListIterFn fn)
{
AssetList *list = AssetListStorage::lookup_list(library_reference);
@ -483,13 +501,21 @@ asset_system::AssetLibrary *ED_assetlist_library_get_once_available(
return list->asset_library();
}
AssetHandle ED_assetlist_asset_get_by_index(const AssetLibraryReference *library_reference,
int asset_index)
AssetHandle ED_assetlist_asset_handle_get_by_index(const AssetLibraryReference *library_reference,
int asset_index)
{
const AssetList *list = AssetListStorage::lookup_list(*library_reference);
return list->asset_get_by_index(asset_index);
}
asset_system::AssetRepresentation *ED_assetlist_asset_get_by_index(
const AssetLibraryReference &library_reference, int asset_index)
{
AssetHandle asset_handle = ED_assetlist_asset_handle_get_by_index(&library_reference,
asset_index);
return reinterpret_cast<asset_system::AssetRepresentation *>(asset_handle.file_data->asset);
}
ImBuf *ED_assetlist_asset_image_get(const AssetHandle *asset_handle)
{
ImBuf *imbuf = filelist_file_getimage(asset_handle->file_data);

View File

@ -16,6 +16,8 @@
#include "BLI_utildefines.h"
#include "BLI_vector_set.hh"
#include "BLT_translation.h"
#include "ED_curves.h"
#include "ED_object.h"
#include "ED_screen.h"
@ -938,15 +940,15 @@ static void CURVES_OT_select_random(wmOperatorType *ot)
1.0f);
}
static int select_end_exec(bContext *C, wmOperator *op)
static int select_ends_exec(bContext *C, wmOperator *op)
{
VectorSet<Curves *> unique_curves = curves::get_unique_editable_curves(*C);
const bool end_points = RNA_boolean_get(op->ptr, "end_points");
const int amount = RNA_int_get(op->ptr, "amount");
const int amount_start = RNA_int_get(op->ptr, "amount_start");
const int amount_end = RNA_int_get(op->ptr, "amount_end");
for (Curves *curves_id : unique_curves) {
CurvesGeometry &curves = curves_id->geometry.wrap();
select_ends(curves, amount, end_points);
select_ends(curves, amount_start, amount_end);
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic
* attribute for now. */
@ -957,24 +959,48 @@ static int select_end_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
static void CURVES_OT_select_end(wmOperatorType *ot)
static void select_ends_ui(bContext * /*C*/, wmOperator *op)
{
ot->name = "Select End";
uiLayout *layout = op->layout;
uiLayoutSetPropSep(layout, true);
uiLayout *col = uiLayoutColumn(layout, true);
uiLayoutSetPropDecorate(col, false);
uiItemR(col, op->ptr, "amount_start", 0, IFACE_("Amount Start"), ICON_NONE);
uiItemR(col, op->ptr, "amount_end", 0, IFACE_("End"), ICON_NONE);
}
static void CURVES_OT_select_ends(wmOperatorType *ot)
{
ot->name = "Select Ends";
ot->idname = __func__;
ot->description = "Select end points of curves";
ot->exec = select_end_exec;
ot->exec = select_ends_exec;
ot->ui = select_ends_ui;
ot->poll = editable_curves_point_domain_poll;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_boolean(ot->srna,
"end_points",
true,
"End Points",
"Select points at the end of the curve as opposed to the beginning");
RNA_def_int(
ot->srna, "amount", 1, 0, INT32_MAX, "Amount", "Number of points to select", 0, INT32_MAX);
RNA_def_int(ot->srna,
"amount_start",
0,
0,
INT32_MAX,
"Amount Front",
"Number of points to select from the front",
0,
INT32_MAX);
RNA_def_int(ot->srna,
"amount_end",
1,
0,
INT32_MAX,
"Amount Back",
"Number of points to select from the back",
0,
INT32_MAX);
}
static int select_linked_exec(bContext *C, wmOperator * /*op*/)
@ -1181,7 +1207,7 @@ void ED_operatortypes_curves()
WM_operatortype_append(CURVES_OT_set_selection_domain);
WM_operatortype_append(CURVES_OT_select_all);
WM_operatortype_append(CURVES_OT_select_random);
WM_operatortype_append(CURVES_OT_select_end);
WM_operatortype_append(CURVES_OT_select_ends);
WM_operatortype_append(CURVES_OT_select_linked);
WM_operatortype_append(CURVES_OT_select_more);
WM_operatortype_append(CURVES_OT_select_less);

View File

@ -222,7 +222,7 @@ void select_all(bke::CurvesGeometry &curves, const eAttrDomain selection_domain,
}
}
void select_ends(bke::CurvesGeometry &curves, int amount, bool end_points)
void select_ends(bke::CurvesGeometry &curves, int amount_start, int amount_end)
{
const bool was_anything_selected = has_anything_selected(curves);
const OffsetIndices points_by_curve = curves.points_by_curve();
@ -240,12 +240,9 @@ void select_ends(bke::CurvesGeometry &curves, int amount, bool end_points)
MutableSpan<T> selection_typed = selection.span.typed<T>();
threading::parallel_for(curves.curves_range(), 256, [&](const IndexRange range) {
for (const int curve_i : range) {
if (end_points) {
selection_typed.slice(points_by_curve[curve_i].drop_back(amount)).fill(T(0));
}
else {
selection_typed.slice(points_by_curve[curve_i].drop_front(amount)).fill(T(0));
}
selection_typed
.slice(points_by_curve[curve_i].drop_front(amount_start).drop_back(amount_end))
.fill(T(0));
}
});
}

View File

@ -99,28 +99,3 @@ void ED_gizmo_draw_preset_circle(const struct wmGizmo *gz,
single_axis_convert(OB_POSZ, mat, axis, mat_rotate);
ed_gizmo_draw_preset_geometry(gz, mat_rotate, select_id, &wm_gizmo_geom_data_dial);
}
void ED_gizmo_draw_preset_facemap(
const bContext *C, const struct wmGizmo *gz, Object *ob, const int facemap, int select_id)
{
/* Dependency graph is supposed to be evaluated prior to draw. */
Depsgraph *depsgraph = CTX_data_expect_evaluated_depsgraph(C);
const bool is_select = (select_id != -1);
const bool is_highlight = is_select && (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
float color[4];
gizmo_color_get(gz, is_highlight, color);
if (is_select) {
GPU_select_load_id(select_id);
}
GPU_matrix_push();
GPU_matrix_mul(ob->object_to_world);
ED_draw_object_facemap(depsgraph, ob, color, facemap);
GPU_matrix_pop();
if (is_select) {
GPU_select_load_id(-1);
}
}

View File

@ -25,9 +25,7 @@ void ED_operatortypes_asset(void);
#endif
#include "../asset/ED_asset_catalog.h"
#include "../asset/ED_asset_filter.h"
#include "../asset/ED_asset_handle.h"
#include "../asset/ED_asset_import.h"
#include "../asset/ED_asset_library.h"
#include "../asset/ED_asset_list.h"
#include "../asset/ED_asset_mark_clear.h"
@ -37,5 +35,7 @@ void ED_operatortypes_asset(void);
/* C++ only headers. */
#ifdef __cplusplus
# include "../asset/ED_asset_catalog.hh"
# include "../asset/ED_asset_filter.hh"
# include "../asset/ED_asset_import.hh"
# include "../asset/ED_asset_list.hh"
#endif

View File

@ -150,10 +150,10 @@ void select_all(bke::CurvesGeometry &curves, eAttrDomain selection_domain, int a
/**
* Select the ends (front or back) of all the curves.
*
* \param amount: The amount of points to select from the front or back.
* \param end_points: If true, select the last point(s), if false, select the first point(s).
* \param amount_start: The amount of points to select from the front.
* \param amount_end: The amount of points to select from the back.
*/
void select_ends(bke::CurvesGeometry &curves, int amount, bool end_points);
void select_ends(bke::CurvesGeometry &curves, int amount_start, int amount_end);
/**
* Select the points of all curves that have at least one point selected.

View File

@ -52,11 +52,6 @@ void ED_gizmo_draw_preset_circle(const struct wmGizmo *gz,
float mat[4][4],
int axis,
int select_id);
void ED_gizmo_draw_preset_facemap(const struct bContext *C,
const struct wmGizmo *gz,
struct Object *ob,
int facemap,
int select_id);
/* -------------------------------------------------------------------- */
/* 3D Arrow Gizmo */

View File

@ -34,7 +34,6 @@ struct ViewLayer;
struct XFormObjectData;
struct bConstraint;
struct bContext;
struct bFaceMap;
struct bPoseChannel;
struct uiLayout;
struct wmKeyConfig;
@ -729,17 +728,6 @@ bool ED_object_jump_to_bone(struct bContext *C,
const char *bone_name,
bool reveal_hidden);
/* object_facemap_ops.c */
/**
* Called while not in edit-mode.
*/
void ED_object_facemap_face_add(struct Object *ob, struct bFaceMap *fmap, int facenum);
/**
* Called while not in edit-mode.
*/
void ED_object_facemap_face_remove(struct Object *ob, struct bFaceMap *fmap, int facenum);
/* object_data_transform.cc */
struct XFormObjectData *ED_object_data_xform_create_ex(struct ID *id, bool is_edit_mode);

View File

@ -1056,11 +1056,6 @@ void ED_view3d_check_mats_rv3d(struct RegionView3D *rv3d);
struct RV3DMatrixStore *ED_view3d_mats_rv3d_backup(struct RegionView3D *rv3d);
void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, struct RV3DMatrixStore *rv3dmat);
void ED_draw_object_facemap(struct Depsgraph *depsgraph,
struct Object *ob,
const float col[4],
int facemap);
struct RenderEngineType *ED_view3d_engine_type(const struct Scene *scene, int drawtype);
bool ED_view3d_context_activate(struct bContext *C);

View File

@ -22,7 +22,7 @@ extern "C" {
struct ARegion;
struct AssetFilterSettings;
struct AssetHandle;
struct AssetRepresentation;
struct AutoComplete;
struct EnumPropertyItem;
struct FileSelectParams;
@ -1813,8 +1813,7 @@ void UI_but_drag_attach_image(uiBut *but, struct ImBuf *imb, float scale);
* \param asset: May be passed from a temporary variable, drag data only stores a copy of this.
*/
void UI_but_drag_set_asset(uiBut *but,
const struct AssetHandle *asset,
const char *path,
const struct AssetRepresentation *asset,
int import_type, /* eAssetImportType */
int icon,
struct ImBuf *imb,

View File

@ -30,14 +30,13 @@ void UI_but_drag_attach_image(uiBut *but, ImBuf *imb, const float scale)
}
void UI_but_drag_set_asset(uiBut *but,
const AssetHandle *asset_handle,
const char *path,
const AssetRepresentation *asset,
int import_type,
int icon,
ImBuf *imb,
float scale)
{
wmDragAsset *asset_drag = WM_drag_create_asset_data(asset_handle, path, import_type);
wmDragAsset *asset_drag = WM_drag_create_asset_data(asset, import_type);
/* FIXME: This is temporary evil solution to get scene/view-layer/etc in the copy callback of the
* #wmDropBox.

View File

@ -6,6 +6,9 @@
* \ingroup edinterface
*/
#include "AS_asset_representation.h"
#include "AS_asset_representation.hh"
#include "DNA_space_types.h"
#include "DNA_userdef_types.h"
@ -33,6 +36,8 @@
#include "interface_intern.hh"
using namespace blender;
struct AssetViewListData {
AssetLibraryReference asset_library_ref;
AssetFilterSettings filter_settings;
@ -42,28 +47,20 @@ struct AssetViewListData {
static void asset_view_item_but_drag_set(uiBut *but, AssetHandle *asset_handle)
{
ID *id = ED_asset_handle_get_local_id(asset_handle);
AssetRepresentation *asset = ED_asset_handle_get_representation(asset_handle);
ID *id = AS_asset_representation_local_id_get(asset);
if (id != nullptr) {
UI_but_drag_set_id(but, id);
return;
}
char blend_path[FILE_MAX_LIBEXTRA];
ED_asset_handle_get_full_library_path(asset_handle, blend_path);
const eAssetImportMethod import_method =
ED_asset_handle_get_import_method(asset_handle).value_or(ASSET_IMPORT_APPEND_REUSE);
AS_asset_representation_import_method_get(asset).value_or(ASSET_IMPORT_APPEND_REUSE);
if (blend_path[0]) {
ImBuf *imbuf = ED_assetlist_asset_image_get(asset_handle);
UI_but_drag_set_asset(but,
asset_handle,
BLI_strdup(blend_path),
import_method,
ED_asset_handle_get_preview_icon_id(asset_handle),
imbuf,
1.0f);
}
ImBuf *imbuf = ED_assetlist_asset_image_get(asset_handle);
UI_but_drag_set_asset(
but, asset, import_method, ED_asset_handle_get_preview_icon_id(asset_handle), imbuf, 1.0f);
}
static void asset_view_draw_item(uiList *ui_list,
@ -79,7 +76,8 @@ static void asset_view_draw_item(uiList *ui_list,
{
AssetViewListData *list_data = (AssetViewListData *)ui_list->dyn_data->customdata;
AssetHandle asset_handle = ED_assetlist_asset_get_by_index(&list_data->asset_library_ref, index);
AssetHandle asset_handle = ED_assetlist_asset_handle_get_by_index(&list_data->asset_library_ref,
index);
PointerRNA file_ptr;
RNA_pointer_create(&list_data->screen->id,
@ -132,8 +130,10 @@ static void asset_view_filter_items(uiList *ui_list,
C,
[&name_filter, list_data, &filter_settings](
const PointerRNA &itemptr, blender::StringRefNull name, int index) {
AssetHandle asset = ED_assetlist_asset_get_by_index(&list_data->asset_library_ref, index);
if (!ED_asset_filter_matches_asset(&filter_settings, &asset)) {
asset_system::AssetRepresentation *asset = ED_assetlist_asset_get_by_index(
list_data->asset_library_ref, index);
if (!ED_asset_filter_matches_asset(&filter_settings, *asset)) {
return UI_LIST_ITEM_NEVER_SHOW;
}
return name_filter(itemptr, name, index);
@ -141,8 +141,10 @@ static void asset_view_filter_items(uiList *ui_list,
dataptr,
propname,
[list_data](const PointerRNA & /*itemptr*/, int index) -> std::string {
AssetHandle asset = ED_assetlist_asset_get_by_index(&list_data->asset_library_ref, index);
return ED_asset_handle_get_name(&asset);
asset_system::AssetRepresentation *asset = ED_assetlist_asset_get_by_index(
list_data->asset_library_ref, index);
return asset->get_name();
});
}

View File

@ -2221,23 +2221,6 @@ bool EDBM_select_pick(bContext *C, const int mval[2], const SelectPick_Params *p
vc.em->mat_nr = efa->mat_nr;
WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, nullptr);
}
/* Change active face-map on object. */
if (!BLI_listbase_is_empty(&vc.obedit->fmaps)) {
const int cd_fmap_offset = CustomData_get_offset(&vc.em->bm->pdata, CD_FACEMAP);
if (cd_fmap_offset != -1) {
int map = *((int *)BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset));
if ((map < -1) || (map > BLI_listbase_count_at_most(&vc.obedit->fmaps, map))) {
map = -1;
}
map += 1;
if (map != vc.obedit->actfmap) {
/* We may want to add notifiers later,
* currently select update handles redraw. */
vc.obedit->actfmap = map;
}
}
}
}
/* Changing active object is handy since it allows us to

View File

@ -76,7 +76,6 @@ static const EnumPropertyItem prop_similar_types[] = {
{SIMFACE_NORMAL, "NORMAL", 0, "Normal", ""},
{SIMFACE_COPLANAR, "COPLANAR", 0, "Coplanar", ""},
{SIMFACE_SMOOTH, "SMOOTH", 0, "Flat/Smooth", ""},
{SIMFACE_FACEMAP, "FACE_MAP", 0, "Face Map", ""},
#ifdef WITH_FREESTYLE
{SIMFACE_FREESTYLE, "FREESTYLE_FACE", 0, "Freestyle Face Marks", ""},
#endif
@ -177,7 +176,6 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
KDTree_3d *tree_3d = NULL;
KDTree_4d *tree_4d = NULL;
GSet *gset = NULL;
GSet **gset_array = NULL;
int face_data_value = SIMFACE_DATA_NONE;
switch (type) {
@ -195,10 +193,6 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
case SIMFACE_MATERIAL:
gset = BLI_gset_ptr_new("Select similar face");
break;
case SIMFACE_FACEMAP:
gset_array = MEM_callocN(sizeof(GSet *) * objects_len,
"Select similar face: facemap gset array");
break;
}
int tree_index = 0;
@ -208,7 +202,6 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
BMesh *bm = em->bm;
Material ***material_array = NULL;
invert_m4_m4(ob->world_to_object, ob->object_to_world);
int custom_data_offset = 0;
if (bm->totfacesel == 0) {
continue;
@ -232,13 +225,6 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
}
break;
}
case SIMFACE_FACEMAP: {
custom_data_offset = CustomData_get_offset(&bm->pdata, CD_FACEMAP);
if (custom_data_offset == -1) {
continue;
}
gset_array[ob_index] = BLI_gset_ptr_new("Select similar face: facemap gset");
}
}
BMFace *face; /* Mesh face. */
@ -301,12 +287,6 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
}
break;
}
case SIMFACE_FACEMAP: {
BLI_assert(custom_data_offset != -1);
int *face_map = BM_ELEM_CD_GET_VOID_P(face, custom_data_offset);
BLI_gset_add(gset_array[ob_index], face_map);
break;
}
}
}
}
@ -333,7 +313,6 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
BMesh *bm = em->bm;
bool changed = false;
Material ***material_array = NULL;
int custom_data_offset;
float ob_m3[3][3];
copy_m3_m4(ob_m3, ob->object_to_world);
@ -354,12 +333,6 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
}
break;
}
case SIMFACE_FACEMAP: {
custom_data_offset = CustomData_get_offset(&bm->pdata, CD_FACEMAP);
if (custom_data_offset == -1) {
continue;
}
}
}
BMFace *face; /* Mesh face. */
@ -467,18 +440,6 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
}
break;
}
case SIMFACE_FACEMAP: {
const int *face_map = BM_ELEM_CD_GET_VOID_P(face, custom_data_offset);
GSetIterator gs_iter;
GSET_ITER (gs_iter, gset_array[ob_index]) {
const int *face_map_iter = BLI_gsetIterator_getKey(&gs_iter);
if (*face_map == *face_map_iter) {
select = true;
break;
}
}
break;
}
}
if (select) {
@ -533,14 +494,6 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
if (gset != NULL) {
BLI_gset_free(gset, NULL);
}
if (gset_array != NULL) {
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
if (gset_array[ob_index] != NULL) {
BLI_gset_free(gset_array[ob_index], NULL);
}
}
MEM_freeN(gset_array);
}
return OPERATOR_FINISHED;
}
@ -1376,7 +1329,7 @@ static const EnumPropertyItem *select_similar_type_itemf(bContext *C,
#ifdef WITH_FREESTYLE
const int a_end = SIMFACE_FREESTYLE;
#else
const int a_end = SIMFACE_FACEMAP;
const int a_end = SIMFACE_MATERIAL;
#endif
for (a = SIMFACE_MATERIAL; a <= a_end; a++) {
RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a);

View File

@ -40,7 +40,6 @@
#include "BKE_multires.h"
#include "BKE_object.h"
#include "BKE_object_deform.h"
#include "BKE_object_facemap.h"
#include "BKE_report.h"
#include "DEG_depsgraph.h"
@ -273,23 +272,6 @@ static void join_mesh_single(Depsgraph *depsgraph,
for (const int i : blender::IndexRange(me->totpoly)) {
poly_offsets[i] = src_poly_offsets[i] + *loopofs;
}
/* Face maps. */
int *fmap = (int *)CustomData_get_for_write(pdata, *polyofs, CD_FACEMAP, totpoly);
const int *fmap_src = (const int *)CustomData_get_for_write(
&me->pdata, 0, CD_FACEMAP, me->totpoly);
/* Remap to correct new face-map indices, if needed. */
if (fmap_src) {
BLI_assert(fmap != nullptr);
int *fmap_index_map;
int fmap_index_map_len;
fmap_index_map = BKE_object_facemap_index_map_create(ob_src, ob_dst, &fmap_index_map_len);
BKE_object_facemap_index_map_apply(fmap, me->totpoly, fmap_index_map, fmap_index_map_len);
if (fmap_index_map != nullptr) {
MEM_freeN(fmap_index_map);
}
}
}
/* these are used for relinking (cannot be set earlier, or else reattaching goes wrong) */
@ -483,19 +465,6 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op)
me->vertex_group_active_index = 1;
}
/* Join this object's face maps to the base one's. */
LISTBASE_FOREACH (bFaceMap *, fmap, &ob_iter->fmaps) {
/* See if this group exists in the object (if it doesn't, add it to the end) */
if (BKE_object_facemap_find_name(ob, fmap->name) == nullptr) {
bFaceMap *fmap_new = static_cast<bFaceMap *>(MEM_mallocN(sizeof(bFaceMap), __func__));
memcpy(fmap_new, fmap, sizeof(bFaceMap));
BLI_addtail(&ob->fmaps, fmap_new);
}
}
if (ob->fmaps.first && ob->actfmap == 0) {
ob->actfmap = 1;
}
mesh_join_offset_face_sets_ID(me, &face_set_id_offset);
if (me->totvert) {

View File

@ -44,7 +44,6 @@ set(SRC
object_data_transfer.c
object_data_transform.cc
object_edit.cc
object_facemap_ops.c
object_gpencil_modifier.c
object_hook.c
object_light_linking_ops.cc

View File

@ -1,493 +0,0 @@
/* SPDX-FileCopyrightText: 2008 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edobj
*/
#include <string.h>
#include "MEM_guardedalloc.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
#include "DNA_workspace_types.h"
#include "BKE_context.h"
#include "BKE_customdata.h"
#include "BKE_editmesh.h"
#include "BKE_object.h"
#include "BKE_object_deform.h"
#include "BKE_object_facemap.h"
#include "DEG_depsgraph.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "WM_api.h"
#include "WM_types.h"
#include "ED_mesh.h"
#include "ED_object.h"
#include "object_intern.h"
void ED_object_facemap_face_add(Object *ob, bFaceMap *fmap, int facenum)
{
int fmap_nr;
if (GS(((ID *)ob->data)->name) != ID_ME) {
return;
}
/* get the face map number, exit if it can't be found */
fmap_nr = BLI_findindex(&ob->fmaps, fmap);
if (fmap_nr != -1) {
int *facemap;
Mesh *me = ob->data;
/* if there's is no facemap layer then create one */
if ((facemap = CustomData_get_layer_for_write(&me->pdata, CD_FACEMAP, me->totpoly)) == NULL) {
facemap = CustomData_add_layer(&me->pdata, CD_FACEMAP, CD_SET_DEFAULT, me->totpoly);
}
facemap[facenum] = fmap_nr;
}
}
void ED_object_facemap_face_remove(Object *ob, bFaceMap *fmap, int facenum)
{
int fmap_nr;
if (GS(((ID *)ob->data)->name) != ID_ME) {
return;
}
/* get the face map number, exit if it can't be found */
fmap_nr = BLI_findindex(&ob->fmaps, fmap);
if (fmap_nr != -1) {
int *facemap;
Mesh *me = ob->data;
if ((facemap = CustomData_get_layer_for_write(&me->pdata, CD_FACEMAP, me->totpoly)) == NULL) {
return;
}
facemap[facenum] = -1;
}
}
static void object_fmap_remap_edit_mode(Object *ob, const int *remap)
{
if (ob->type != OB_MESH) {
return;
}
Mesh *me = ob->data;
if (me->edit_mesh) {
BMEditMesh *em = me->edit_mesh;
const int cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
if (cd_fmap_offset != -1) {
BMFace *efa;
BMIter iter;
int *map;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
if (map && *map != -1) {
*map = remap[*map];
}
}
}
}
}
static void object_fmap_remap_object_mode(Object *ob, const int *remap)
{
if (ob->type != OB_MESH) {
return;
}
Mesh *me = ob->data;
if (CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
int *map = CustomData_get_layer_for_write(&me->pdata, CD_FACEMAP, me->totpoly);
if (map) {
for (int i = 0; i < me->totpoly; i++) {
if (map[i] != -1) {
map[i] = remap[map[i]];
}
}
}
}
}
static void object_facemap_remap(Object *ob, const int *remap)
{
if (BKE_object_is_in_editmode(ob)) {
object_fmap_remap_edit_mode(ob, remap);
}
else {
object_fmap_remap_object_mode(ob, remap);
}
}
static bool face_map_supported_poll(bContext *C)
{
Object *ob = ED_object_context(C);
ID *data = (ob) ? ob->data : NULL;
return (ob && !ID_IS_LINKED(ob) && !ID_IS_OVERRIDE_LIBRARY(ob) && ob->type == OB_MESH && data &&
!ID_IS_LINKED(data) && !ID_IS_OVERRIDE_LIBRARY(data));
}
static bool face_map_supported_edit_mode_poll(bContext *C)
{
Object *ob = ED_object_context(C);
if (face_map_supported_poll(C)) {
if (ob->mode == OB_MODE_EDIT) {
return true;
}
}
return false;
}
static bool face_map_supported_remove_poll(bContext *C)
{
if (!face_map_supported_poll(C)) {
return false;
}
Object *ob = ED_object_context(C);
bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
if (fmap) {
return true;
}
return false;
}
static int face_map_add_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = ED_object_context(C);
BKE_object_facemap_add(ob);
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
return OPERATOR_FINISHED;
}
void OBJECT_OT_face_map_add(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Add Face Map";
ot->idname = "OBJECT_OT_face_map_add";
ot->description = "Add a new face map to the active object";
/* api callbacks */
ot->poll = face_map_supported_poll;
ot->exec = face_map_add_exec;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int face_map_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = ED_object_context(C);
bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
if (fmap) {
BKE_object_facemap_remove(ob, fmap);
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
}
return OPERATOR_FINISHED;
}
void OBJECT_OT_face_map_remove(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Remove Face Map";
ot->idname = "OBJECT_OT_face_map_remove";
ot->description = "Remove a face map from the active object";
/* api callbacks */
ot->poll = face_map_supported_remove_poll;
ot->exec = face_map_remove_exec;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int face_map_assign_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = ED_object_context(C);
bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
if (fmap) {
Mesh *me = ob->data;
BMEditMesh *em = me->edit_mesh;
BMFace *efa;
BMIter iter;
int *map;
int cd_fmap_offset;
if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP)) {
BM_data_layer_add(em->bm, &em->bm->pdata, CD_FACEMAP);
}
cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
*map = ob->actfmap - 1;
}
}
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
}
return OPERATOR_FINISHED;
}
void OBJECT_OT_face_map_assign(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Assign Face Map";
ot->idname = "OBJECT_OT_face_map_assign";
ot->description = "Assign faces to a face map";
/* api callbacks */
ot->poll = face_map_supported_edit_mode_poll;
ot->exec = face_map_assign_exec;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int face_map_remove_from_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = ED_object_context(C);
bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
if (fmap) {
Mesh *me = ob->data;
BMEditMesh *em = me->edit_mesh;
BMFace *efa;
BMIter iter;
int *map;
int cd_fmap_offset;
int mapindex = ob->actfmap - 1;
if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP)) {
return OPERATOR_CANCELLED;
}
cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
if (BM_elem_flag_test(efa, BM_ELEM_SELECT) && *map == mapindex) {
*map = -1;
}
}
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
}
return OPERATOR_FINISHED;
}
void OBJECT_OT_face_map_remove_from(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Remove from Face Map";
ot->idname = "OBJECT_OT_face_map_remove_from";
ot->description = "Remove faces from a face map";
/* api callbacks */
ot->poll = face_map_supported_edit_mode_poll;
ot->exec = face_map_remove_from_exec;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static void fmap_select(Object *ob, bool select)
{
Mesh *me = ob->data;
BMEditMesh *em = me->edit_mesh;
BMFace *efa;
BMIter iter;
int *map;
int cd_fmap_offset;
int mapindex = ob->actfmap - 1;
if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP)) {
BM_data_layer_add(em->bm, &em->bm->pdata, CD_FACEMAP);
}
cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
if (*map == mapindex) {
BM_face_select_set(em->bm, efa, select);
}
}
}
static int face_map_select_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = ED_object_context(C);
bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
if (fmap) {
fmap_select(ob, true);
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
}
return OPERATOR_FINISHED;
}
void OBJECT_OT_face_map_select(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Select Face Map Faces";
ot->idname = "OBJECT_OT_face_map_select";
ot->description = "Select faces belonging to a face map";
/* api callbacks */
ot->poll = face_map_supported_edit_mode_poll;
ot->exec = face_map_select_exec;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int face_map_deselect_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = ED_object_context(C);
bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
if (fmap) {
fmap_select(ob, false);
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
}
return OPERATOR_FINISHED;
}
void OBJECT_OT_face_map_deselect(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Deselect Face Map Faces";
ot->idname = "OBJECT_OT_face_map_deselect";
ot->description = "Deselect faces belonging to a face map";
/* api callbacks */
ot->poll = face_map_supported_edit_mode_poll;
ot->exec = face_map_deselect_exec;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int face_map_move_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
bFaceMap *fmap;
int dir = RNA_enum_get(op->ptr, "direction");
fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
if (!fmap) {
return OPERATOR_CANCELLED;
}
if (!fmap->prev && !fmap->next) {
return OPERATOR_CANCELLED;
}
int pos1 = BLI_findindex(&ob->fmaps, fmap);
int pos2 = pos1 - dir;
int len = BLI_listbase_count(&ob->fmaps);
int *map = MEM_mallocN(len * sizeof(*map), __func__);
if (!IN_RANGE(pos2, -1, len)) {
const int offset = len - dir;
for (int i = 0; i < len; i++) {
map[i] = (i + offset) % len;
}
pos2 = map[pos1];
}
else {
range_vn_i(map, len, 0);
SWAP(int, map[pos1], map[pos2]);
}
void *prev = fmap->prev;
void *next = fmap->next;
BLI_remlink(&ob->fmaps, fmap);
if (dir == 1) { /*up*/
BLI_insertlinkbefore(&ob->fmaps, prev, fmap);
}
else { /*down*/
BLI_insertlinkafter(&ob->fmaps, next, fmap);
}
/* Iterate through mesh and substitute the indices as necessary. */
object_facemap_remap(ob, map);
MEM_freeN(map);
ob->actfmap = pos2 + 1;
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob);
return OPERATOR_FINISHED;
}
void OBJECT_OT_face_map_move(wmOperatorType *ot)
{
static EnumPropertyItem fmap_slot_move[] = {
{1, "UP", 0, "Up", ""},
{-1, "DOWN", 0, "Down", ""},
{0, NULL, 0, NULL, NULL},
};
/* identifiers */
ot->name = "Move Face Map";
ot->idname = "OBJECT_OT_face_map_move";
ot->description = "Move the active face map up/down in the list";
/* api callbacks */
ot->poll = face_map_supported_poll;
ot->exec = face_map_move_exec;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_enum(
ot->srna, "direction", fmap_slot_move, 0, "Direction", "Direction to move, up or down");
}

View File

@ -316,16 +316,6 @@ void OBJECT_OT_vertex_weight_set_active(struct wmOperatorType *ot);
void OBJECT_OT_vertex_weight_normalize_active_vertex(struct wmOperatorType *ot);
void OBJECT_OT_vertex_weight_copy(struct wmOperatorType *ot);
/* object_facemap_ops.c */
void OBJECT_OT_face_map_add(struct wmOperatorType *ot);
void OBJECT_OT_face_map_remove(struct wmOperatorType *ot);
void OBJECT_OT_face_map_assign(struct wmOperatorType *ot);
void OBJECT_OT_face_map_remove_from(struct wmOperatorType *ot);
void OBJECT_OT_face_map_select(struct wmOperatorType *ot);
void OBJECT_OT_face_map_deselect(struct wmOperatorType *ot);
void OBJECT_OT_face_map_move(struct wmOperatorType *ot);
/* object_warp.c */
void TRANSFORM_OT_vertex_warp(struct wmOperatorType *ot);

View File

@ -226,14 +226,6 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_vertex_weight_normalize_active_vertex);
WM_operatortype_append(OBJECT_OT_vertex_weight_copy);
WM_operatortype_append(OBJECT_OT_face_map_add);
WM_operatortype_append(OBJECT_OT_face_map_remove);
WM_operatortype_append(OBJECT_OT_face_map_assign);
WM_operatortype_append(OBJECT_OT_face_map_remove_from);
WM_operatortype_append(OBJECT_OT_face_map_select);
WM_operatortype_append(OBJECT_OT_face_map_deselect);
WM_operatortype_append(OBJECT_OT_face_map_move);
WM_operatortype_append(TRANSFORM_OT_vertex_warp);
WM_operatortype_append(OBJECT_OT_move_to_collection);

View File

@ -464,7 +464,6 @@ enum eSculptFaceSetsInitMode {
SCULPT_FACE_SETS_FROM_CREASES = 4,
SCULPT_FACE_SETS_FROM_SHARP_EDGES = 5,
SCULPT_FACE_SETS_FROM_BEVEL_WEIGHT = 6,
SCULPT_FACE_SETS_FROM_FACE_MAPS = 7,
SCULPT_FACE_SETS_FROM_FACE_SET_BOUNDARIES = 8,
};
@ -518,13 +517,7 @@ static EnumPropertyItem prop_sculpt_face_sets_init_types[] = {
"Face Sets from Sharp Edges",
"Create Face Sets using Sharp Edges as boundaries",
},
{
SCULPT_FACE_SETS_FROM_FACE_MAPS,
"FACE_MAPS",
0,
"Face Sets from Face Maps",
"Create a Face Set per Face Map",
},
{
SCULPT_FACE_SETS_FROM_FACE_SET_BOUNDARIES,
"FACE_SET_BOUNDARIES",
@ -610,13 +603,6 @@ static void sculpt_face_sets_init_loop(Object *ob, const int mode)
ss->face_sets[i] = material_indices[i] + 1;
}
}
else if (mode == SCULPT_FACE_SETS_FROM_FACE_MAPS) {
const int *face_maps = static_cast<const int *>(
CustomData_get_layer(&mesh->pdata, CD_FACEMAP));
for (const int i : IndexRange(mesh->totpoly)) {
ss->face_sets[i] = face_maps ? face_maps[i] : 1;
}
}
}
static int sculpt_face_set_init_exec(bContext *C, wmOperator *op)
@ -719,10 +705,6 @@ static int sculpt_face_set_init_exec(bContext *C, wmOperator *op)
});
break;
}
case SCULPT_FACE_SETS_FROM_FACE_MAPS: {
sculpt_face_sets_init_loop(ob, SCULPT_FACE_SETS_FROM_FACE_MAPS);
break;
}
}
SCULPT_undo_push_end(ob);

View File

@ -39,7 +39,6 @@
#include "RNA_access.h"
#include "RNA_prototypes.h"
#include "ED_asset_handle.h"
#include "ED_fileselect.h"
#include "ED_screen.h"
@ -156,17 +155,10 @@ static void file_but_enable_drag(uiBut *but,
}
else if (sfile->browse_mode == FILE_BROWSE_MODE_ASSETS &&
(file->typeflag & FILE_TYPE_ASSET) != 0) {
char blend_path[FILE_MAX_LIBEXTRA];
if (BKE_blendfile_library_path_explode(path, blend_path, nullptr, nullptr)) {
const int import_method = ED_fileselect_asset_import_method_get(sfile, file);
BLI_assert(import_method > -1);
const int import_method = ED_fileselect_asset_import_method_get(sfile, file);
BLI_assert(import_method > -1);
AssetHandle asset{};
asset.file_data = file;
UI_but_drag_set_asset(
but, &asset, BLI_strdup(blend_path), import_method, icon, preview_image, scale);
}
UI_but_drag_set_asset(but, file->asset, import_method, icon, preview_image, scale);
}
else if (preview_image) {
UI_but_drag_set_image(but, path, icon, preview_image, scale);

View File

@ -5,7 +5,7 @@
#include "AS_asset_catalog.hh"
#include "AS_asset_catalog_tree.hh"
#include "AS_asset_library.hh"
#include "AS_asset_representation.h"
#include "AS_asset_representation.hh"
#include "BLI_multi_value_map.hh"
@ -49,7 +49,7 @@ static void node_add_menu_assets_listen_fn(const wmRegionListenerParams *params)
struct LibraryAsset {
AssetLibraryReference library_ref;
AssetRepresentation &asset;
asset_system::AssetRepresentation &asset;
};
struct AssetItemTree {
@ -121,11 +121,11 @@ static AssetItemTree build_catalog_tree(const bContext &C, const bNodeTree *node
return {};
}
ED_assetlist_iterate(all_library_ref, [&](AssetHandle asset_handle) {
if (!ED_asset_filter_matches_asset(&type_filter, &asset_handle)) {
ED_assetlist_iterate(all_library_ref, [&](asset_system::AssetRepresentation &asset) {
if (!ED_asset_filter_matches_asset(&type_filter, asset)) {
return true;
}
const AssetMetaData &meta_data = *ED_asset_handle_get_metadata(&asset_handle);
const AssetMetaData &meta_data = asset.get_metadata();
const IDProperty *tree_type = BKE_asset_metadata_idprop_find(&meta_data, "type");
if (tree_type == nullptr || IDP_Int(tree_type) != node_tree->type) {
return true;
@ -139,8 +139,7 @@ static AssetItemTree build_catalog_tree(const bContext &C, const bNodeTree *node
if (catalog == nullptr) {
return true;
}
AssetRepresentation *asset = ED_asset_handle_get_representation(&asset_handle);
assets_per_path.add(catalog->path, LibraryAsset{all_library_ref, *asset});
assets_per_path.add(catalog->path, LibraryAsset{all_library_ref, asset});
return true;
});
@ -205,10 +204,7 @@ static void node_add_catalog_assets_draw(const bContext *C, Menu *menu)
const_cast<AssetLibraryReference *>(&item.library_ref)};
uiLayoutSetContextPointer(col, "asset_library_ref", &library_ptr);
uiItemO(col,
IFACE_(AS_asset_representation_name_get(&item.asset)),
ICON_NONE,
"NODE_OT_add_group_asset");
uiItemO(col, IFACE_(item.asset.get_name().c_str()), ICON_NONE, "NODE_OT_add_group_asset");
}
asset_system::AssetLibrary *all_library = get_all_library_once_available();

View File

@ -6,6 +6,7 @@
#include "AS_asset_catalog.hh"
#include "AS_asset_library.hh"
#include "AS_asset_representation.hh"
#include "BLI_listbase.h"
#include "BLI_string_search.h"
@ -62,20 +63,19 @@ static void add_node_search_listen_fn(const wmRegionListenerParams *params, void
}
static void search_items_for_asset_metadata(const bNodeTree &node_tree,
const AssetHandle asset_handle,
const asset_system::AssetRepresentation &asset,
nodes::GatherAddNodeSearchParams &params)
{
const AssetMetaData &asset_data = *ED_asset_handle_get_metadata(&asset_handle);
const AssetMetaData &asset_data = asset.get_metadata();
const IDProperty *tree_type = BKE_asset_metadata_idprop_find(&asset_data, "type");
if (tree_type == nullptr || IDP_Int(tree_type) != node_tree.type) {
return;
}
const AssetRepresentation *asset = ED_asset_handle_get_representation(&asset_handle);
params.add_single_node_item(
IFACE_(ED_asset_handle_get_name(&asset_handle)),
IFACE_(asset.get_name().c_str()),
asset_data.description == nullptr ? "" : IFACE_(asset_data.description),
[asset](const bContext &C, bNodeTree &node_tree, bNode &node) {
[&asset](const bContext &C, bNodeTree &node_tree, bNode &node) {
Main &bmain = *CTX_data_main(&C);
node.flag &= ~NODE_OPTIONS;
node.id = ED_asset_get_local_id_from_asset_or_append_and_reuse(&bmain, asset, ID_NT);
@ -102,11 +102,11 @@ static void gather_search_items_for_all_assets(const bContext &C,
ED_assetlist_storage_fetch(&library_ref, &C);
ED_assetlist_ensure_previews_job(&library_ref, &C);
ED_assetlist_iterate(library_ref, [&](AssetHandle asset) {
if (!ED_asset_filter_matches_asset(&filter_settings, &asset)) {
ED_assetlist_iterate(library_ref, [&](asset_system::AssetRepresentation &asset) {
if (!ED_asset_filter_matches_asset(&filter_settings, asset)) {
return true;
}
if (!r_added_assets.add(ED_asset_handle_get_name(&asset))) {
if (!r_added_assets.add(asset.get_name())) {
/* If an asset with the same name has already been added, skip this. */
return true;
}

View File

@ -2,6 +2,8 @@
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "AS_asset_representation.hh"
#include "BLI_listbase.h"
#include "BLI_string_search.h"
@ -148,10 +150,10 @@ static void add_existing_group_input_fn(nodes::LinkSearchOpParams &params,
*/
static void search_link_ops_for_asset_metadata(const bNodeTree &node_tree,
const bNodeSocket &socket,
const AssetHandle asset_handle,
const asset_system::AssetRepresentation &asset,
Vector<SocketLinkOperation> &search_link_ops)
{
const AssetMetaData &asset_data = *ED_asset_handle_get_metadata(&asset_handle);
const AssetMetaData &asset_data = asset.get_metadata();
const IDProperty *tree_type = BKE_asset_metadata_idprop_find(&asset_data, "type");
if (tree_type == nullptr || IDP_Int(tree_type) != node_tree.type) {
return;
@ -187,13 +189,12 @@ static void search_link_ops_for_asset_metadata(const bNodeTree &node_tree,
continue;
}
AssetRepresentation *asset = ED_asset_handle_get_representation(&asset_handle);
const StringRef asset_name = ED_asset_handle_get_name(&asset_handle);
const StringRef asset_name = asset.get_name();
const StringRef socket_name = socket_property->name;
search_link_ops.append(
{asset_name + " " + UI_MENU_ARROW_SEP + socket_name,
[asset, socket_property, in_out](nodes::LinkSearchOpParams &params) {
[&asset, socket_property, in_out](nodes::LinkSearchOpParams &params) {
Main &bmain = *CTX_data_main(&params.C);
bNode &node = params.add_node(params.node_tree.typeinfo->group_idname);
@ -232,11 +233,11 @@ static void gather_search_link_ops_for_asset_library(const bContext &C,
ED_assetlist_storage_fetch(&library_ref, &C);
ED_assetlist_ensure_previews_job(&library_ref, &C);
ED_assetlist_iterate(library_ref, [&](AssetHandle asset) {
if (!ED_asset_filter_matches_asset(&filter_settings, &asset)) {
ED_assetlist_iterate(library_ref, [&](asset_system::AssetRepresentation &asset) {
if (!ED_asset_filter_matches_asset(&filter_settings, asset)) {
return true;
}
if (skip_local && ED_asset_handle_get_local_id(&asset) != nullptr) {
if (skip_local && asset.is_local_id()) {
return true;
}
search_link_ops_for_asset_metadata(node_tree, socket, asset, search_link_ops);

View File

@ -9,6 +9,7 @@
#include <numeric>
#include "AS_asset_representation.h"
#include "AS_asset_representation.hh"
#include "MEM_guardedalloc.h"
@ -379,13 +380,14 @@ void NODE_OT_add_group(wmOperatorType *ot)
* \{ */
static bool add_node_group_asset(const bContext &C,
const AssetRepresentation *asset,
const AssetRepresentation &asset_c_handle,
ReportList &reports)
{
Main &bmain = *CTX_data_main(&C);
SpaceNode &snode = *CTX_wm_space_node(&C);
bNodeTree &edit_tree = *snode.edittree;
auto &asset = reinterpret_cast<const asset_system::AssetRepresentation &>(asset_c_handle);
bNodeTree *node_group = reinterpret_cast<bNodeTree *>(
ED_asset_get_local_id_from_asset_or_append_and_reuse(&bmain, asset, ID_NT));
if (!node_group) {
@ -443,7 +445,7 @@ static int node_add_group_asset_invoke(bContext *C, wmOperator *op, const wmEven
snode.runtime->cursor /= UI_SCALE_FAC;
if (!add_node_group_asset(*C, asset, *op->reports)) {
if (!add_node_group_asset(*C, *asset, *op->reports)) {
return OPERATOR_CANCELLED;
}

View File

@ -4,6 +4,7 @@
set(INC
../include
../../asset_system
../../blenfont
../../blenkernel
../../blenlib

View File

@ -41,87 +41,3 @@
uchar view3d_camera_border_hack_col[3];
bool view3d_camera_border_hack_test = false;
#endif
/* ***************** BACKBUF SEL (BBS) ********* */
void ED_draw_object_facemap(Depsgraph *depsgraph,
Object *ob,
const float col[4],
const int facemap)
{
/* happens on undo */
if (ob->type != OB_MESH || !ob->data) {
return;
}
const Mesh *me = static_cast<const Mesh *>(ob->data);
{
Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval);
if (me_eval != nullptr) {
me = me_eval;
}
}
GPU_front_facing(ob->transflag & OB_NEG_SCALE);
/* Just to create the data to pass to immediate mode! (sigh) */
const int *facemap_data = static_cast<const int *>(CustomData_get_layer(&me->pdata, CD_FACEMAP));
if (facemap_data) {
GPU_blend(GPU_BLEND_ALPHA);
const float(*positions)[3] = BKE_mesh_vert_positions(me);
const blender::OffsetIndices polys = me->polys();
const blender::Span<int> corner_verts = me->corner_verts();
const blender::Span<MLoopTri> looptris = me->looptris();
facemap_data = static_cast<const int *>(CustomData_get_layer(&me->pdata, CD_FACEMAP));
/* Make a batch and free it each time for now. */
const int looptris_len = poly_to_tri_count(polys.size(), corner_verts.size());
const int vbo_len_capacity = looptris_len * 3;
int vbo_len_used = 0;
GPUVertFormat format_pos = {0};
const uint pos_id = GPU_vertformat_attr_add(
&format_pos, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
GPUVertBuf *vbo_pos = GPU_vertbuf_create_with_format(&format_pos);
GPU_vertbuf_data_alloc(vbo_pos, vbo_len_capacity);
GPUVertBufRaw pos_step;
GPU_vertbuf_attr_get_raw_data(vbo_pos, pos_id, &pos_step);
int tri_index = 0;
for (const int i : polys.index_range()) {
if (facemap_data[i] == facemap) {
for (int j = 2; j < polys[i].size(); j++) {
copy_v3_v3(static_cast<float *>(GPU_vertbuf_raw_step(&pos_step)),
positions[corner_verts[looptris[tri_index].tri[0]]]);
copy_v3_v3(static_cast<float *>(GPU_vertbuf_raw_step(&pos_step)),
positions[corner_verts[looptris[tri_index].tri[1]]]);
copy_v3_v3(static_cast<float *>(GPU_vertbuf_raw_step(&pos_step)),
positions[corner_verts[looptris[tri_index].tri[2]]]);
vbo_len_used += 3;
tri_index++;
}
}
else {
tri_index += polys[i].size() - 2;
}
}
if (vbo_len_capacity != vbo_len_used) {
GPU_vertbuf_data_resize(vbo_pos, vbo_len_used);
}
GPUBatch *draw_batch = GPU_batch_create(GPU_PRIM_TRIS, vbo_pos, nullptr);
GPU_batch_program_set_builtin(draw_batch, GPU_SHADER_3D_UNIFORM_COLOR);
GPU_batch_uniform_4fv(draw_batch, "color", col);
GPU_batch_draw(draw_batch);
GPU_batch_discard(draw_batch);
GPU_vertbuf_discard(vbo_pos);
GPU_blend(GPU_BLEND_NONE);
}
}

View File

@ -12,6 +12,8 @@
#include <cstdio>
#include <cstring>
#include "AS_asset_representation.h"
#include "DNA_collection_types.h"
#include "DNA_defaults.h"
#include "DNA_gpencil_legacy_types.h"
@ -496,7 +498,7 @@ static ID_Type view3d_drop_id_in_main_region_poll_get_id_type(bContext *C,
wmDragAsset *asset_drag = WM_drag_get_asset_data(drag, 0);
if (asset_drag) {
return ID_Type(asset_drag->id_type);
return AS_asset_representation_id_type_get(asset_drag->asset);
}
return ID_Type(0);
@ -731,7 +733,8 @@ static bool view3d_geometry_nodes_drop_poll(bContext *C, wmDrag *drag, const wmE
if (!asset_data) {
return false;
}
const IDProperty *tree_type = BKE_asset_metadata_idprop_find(asset_data->metadata, "type");
const AssetMetaData *metadata = AS_asset_representation_metadata_get(asset_data->asset);
const IDProperty *tree_type = BKE_asset_metadata_idprop_find(metadata, "type");
if (!tree_type || IDP_Int(tree_type) != NTREE_GEOMETRY) {
return false;
}

View File

@ -581,7 +581,7 @@ static bool transform_modal_item_poll(const wmOperator *op, int value)
return false;
}
if (value == TFM_MODAL_ADD_SNAP) {
if (!validSnap(t)) {
if (!(t->tsnap.status & SNAP_TARGET_FOUND)) {
return false;
}
}

View File

@ -143,6 +143,8 @@ typedef enum {
/** Do not display Xform gizmo even though it is available. */
T_NO_GIZMO = 1 << 24,
T_DRAW_SNAP_SOURCE = 1 << 25,
} eTFlag;
ENUM_OPERATORS(eTFlag, T_NO_GIZMO);

View File

@ -61,12 +61,9 @@ static void snapsource_end(TransInfo *t)
t->mouse.post = customdata->mouse_prev.post;
t->mouse.use_virtual_mval = customdata->mouse_prev.use_virtual_mval;
transform_gizmo_3d_model_from_constraint_and_mode_set(t);
MEM_freeN(customdata);
t->tsnap.snap_source_fn = NULL;
transform_gizmo_3d_model_from_constraint_and_mode_set(t);
tranform_snap_source_restore_context(t);
}
@ -74,6 +71,9 @@ static void snapsource_confirm(TransInfo *t)
{
BLI_assert(t->modifiers & MOD_EDIT_SNAP_SOURCE);
getSnapPoint(t, t->tsnap.snap_source);
t->tsnap.snap_source_fn = NULL;
t->tsnap.status |= SNAP_SOURCE_FOUND;
t->flag |= T_DRAW_SNAP_SOURCE;
int mval[2];
#ifndef RESET_TRANSFORMATION
@ -180,23 +180,12 @@ void transform_mode_snap_source_init(TransInfo *t, wmOperator *UNUSED(op))
t->mode_info = &TransMode_snapsource;
t->tsnap.target_operation = SCE_SNAP_TARGET_ALL;
if ((t->tsnap.status & SNAP_SOURCE_FOUND) == 0) {
if (t->tsnap.snap_source_fn) {
/* Calculate the current snap source for perpendicular snap. */
t->tsnap.snap_source_fn(t);
}
if ((t->tsnap.status & SNAP_SOURCE_FOUND) == 0) {
/* Fallback. */
copy_v3_v3(t->tsnap.snap_source, t->center_global);
t->tsnap.status |= SNAP_SOURCE_FOUND;
}
}
t->tsnap.status &= ~SNAP_SOURCE_FOUND;
if ((t->tsnap.mode & ~(SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)) == 0) {
/* Initialize snap modes for geometry. */
t->tsnap.mode &= ~(SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID);
t->tsnap.mode |= SCE_SNAP_MODE_GEOM & ~SCE_SNAP_MODE_FACE_NEAREST;
t->tsnap.mode |= SCE_SNAP_MODE_GEOM;
}
if (t->data_type == &TransConvertType_Mesh) {

View File

@ -174,12 +174,10 @@ void drawSnapping(const bContext *C, TransInfo *t)
return;
}
const bool draw_source = (t->spacetype == SPACE_VIEW3D) &&
(t->tsnap.status & SNAP_SOURCE_FOUND) &&
((t->tsnap.mode & SCE_SNAP_MODE_EDGE_PERPENDICULAR) ||
t->tsnap.snap_source_fn == nullptr);
const bool draw_source = (t->tsnap.status & SNAP_SOURCE_FOUND) && (t->flag & T_DRAW_SNAP_SOURCE);
const bool draw_target = (t->tsnap.status & (SNAP_TARGET_FOUND | SNAP_MULTI_POINTS));
if (!(draw_source || validSnap(t))) {
if (!(draw_source || draw_target)) {
return;
}
@ -767,6 +765,10 @@ static void initSnappingMode(TransInfo *t)
t->tsnap.mode &= ~(SCE_SNAP_MODE_FACE_RAYCAST | SCE_SNAP_MODE_FACE_NEAREST);
}
if (t->tsnap.mode & SCE_SNAP_MODE_EDGE_PERPENDICULAR) {
t->flag |= T_DRAW_SNAP_SOURCE;
}
setSnappingCallback(t);
if (t->spacetype == SPACE_VIEW3D) {
@ -1388,7 +1390,7 @@ eSnapMode snapObjectsTransform(
snap_object_params.use_occlusion_test = true;
snap_object_params.use_backface_culling = (t->tsnap.flag & SCE_SNAP_BACKFACE_CULLING) != 0;
float *target = (t->tsnap.status & SNAP_SOURCE_FOUND) ? t->tsnap.snap_source : t->center_global;
float *prev_co = (t->tsnap.status & SNAP_SOURCE_FOUND) ? t->tsnap.snap_source : nullptr;
return ED_transform_snap_object_project_view3d(t->tsnap.object_context,
t->depsgraph,
t->region,
@ -1397,7 +1399,7 @@ eSnapMode snapObjectsTransform(
&snap_object_params,
nullptr,
mval,
target,
prev_co,
dist_px,
r_loc,
r_no);

View File

@ -3294,8 +3294,10 @@ static eSnapMode transform_snap_context_project_view3d_mixed_impl(SnapObjectCont
}
}
if ((snap_to_flag & SCE_SNAP_MODE_FACE_NEAREST) && ELEM(nullptr, prev_co, init_co)) {
/* No location to work with #SCE_SNAP_MODE_FACE_NEAREST. */
if (prev_co == nullptr) {
snap_to_flag &= ~(SCE_SNAP_MODE_EDGE_PERPENDICULAR | SCE_SNAP_MODE_FACE_NEAREST);
}
else if (init_co == nullptr) {
snap_to_flag &= ~SCE_SNAP_MODE_FACE_NEAREST;
}

View File

@ -4,6 +4,7 @@
#include "testing/testing.h"
#include "GPU_context.h"
#include "GPU_framebuffer.h"
#include "gpu_testing.hh"
@ -199,4 +200,52 @@ static void test_framebuffer_scissor_test()
}
GPU_TEST(framebuffer_scissor_test);
/* Color each side of a cubemap with a different color. */
static void test_framebuffer_cube()
{
const int SIZE = 32;
GPU_render_begin();
eGPUTextureUsage usage = GPU_TEXTURE_USAGE_ATTACHMENT | GPU_TEXTURE_USAGE_HOST_READ;
GPUTexture *tex = GPU_texture_create_cube("tex", SIZE, 1, GPU_RGBA32F, usage, nullptr);
const float4 clear_colors[6] = {
{0.5f, 0.0f, 0.0f, 1.0f},
{1.0f, 0.0f, 0.0f, 1.0f},
{0.0f, 0.5f, 0.0f, 1.0f},
{0.0f, 1.0f, 0.0f, 1.0f},
{0.0f, 0.0f, 0.5f, 1.0f},
{0.0f, 0.0f, 1.0f, 1.0f},
};
GPUFrameBuffer *framebuffers[6] = {nullptr};
for (int i : IndexRange(6)) {
GPU_framebuffer_ensure_config(&framebuffers[i],
{
GPU_ATTACHMENT_NONE,
GPU_ATTACHMENT_TEXTURE_CUBEFACE(tex, i),
});
GPU_framebuffer_bind(framebuffers[i]);
GPU_framebuffer_clear_color(framebuffers[i], clear_colors[i]);
};
float4 *data = (float4 *)GPU_texture_read(tex, GPU_DATA_FLOAT, 0);
for (int side : IndexRange(6)) {
for (int pixel_index : IndexRange(SIZE * SIZE)) {
int index = pixel_index + (SIZE * SIZE) * side;
EXPECT_EQ(clear_colors[side], data[index]);
}
}
MEM_freeN(data);
GPU_texture_free(tex);
for (int i : IndexRange(6)) {
GPU_FRAMEBUFFER_FREE_SAFE(framebuffers[i]);
}
GPU_render_end();
}
GPU_TEST(framebuffer_cube)
} // namespace blender::gpu::tests

View File

@ -63,6 +63,52 @@ static void test_texture_read()
}
GPU_TEST(texture_read)
static void test_texture_cube()
{
const int SIZE = 32;
GPU_render_begin();
eGPUTextureUsage usage = GPU_TEXTURE_USAGE_ATTACHMENT | GPU_TEXTURE_USAGE_HOST_READ;
GPUTexture *tex = GPU_texture_create_cube("tex", SIZE, 1, GPU_RGBA32F, usage, nullptr);
float4 clear_color(1.0f, 0.5f, 0.2f, 1.0f);
GPU_texture_clear(tex, GPU_DATA_FLOAT, clear_color);
float4 *data = (float4 *)GPU_texture_read(tex, GPU_DATA_FLOAT, 0);
for (int index : IndexRange(SIZE * SIZE * 6)) {
EXPECT_EQ(clear_color, data[index]);
}
MEM_freeN(data);
GPU_texture_free(tex);
GPU_render_end();
}
GPU_TEST(texture_cube)
static void test_texture_cube_array()
{
const int SIZE = 32;
const int ARRAY = 2;
GPU_render_begin();
eGPUTextureUsage usage = GPU_TEXTURE_USAGE_ATTACHMENT | GPU_TEXTURE_USAGE_HOST_READ;
GPUTexture *tex = GPU_texture_create_cube_array(
"tex", SIZE, ARRAY, 1, GPU_RGBA32F, usage, nullptr);
float4 clear_color(1.0f, 0.5f, 0.2f, 1.0f);
GPU_texture_clear(tex, GPU_DATA_FLOAT, clear_color);
float4 *data = (float4 *)GPU_texture_read(tex, GPU_DATA_FLOAT, 0);
for (int index : IndexRange(SIZE * SIZE * 6 * ARRAY)) {
EXPECT_EQ(clear_color, data[index]);
}
MEM_freeN(data);
GPU_texture_free(tex);
GPU_render_end();
}
GPU_TEST(texture_cube_array)
static void test_texture_copy()
{
const int SIZE = 128;

View File

@ -108,7 +108,10 @@ void VKBackend::compute_dispatch(int groups_x_len, int groups_y_len, int groups_
command_buffer.dispatch(groups_x_len, groups_y_len, groups_z_len);
}
void VKBackend::compute_dispatch_indirect(StorageBuf * /*indirect_buf*/) {}
void VKBackend::compute_dispatch_indirect(StorageBuf * /*indirect_buf*/)
{
NOT_YET_IMPLEMENTED;
}
Context *VKBackend::context_alloc(void *ghost_window, void *ghost_context)
{

View File

@ -588,17 +588,22 @@ VkFormat to_vk_format(const GPUVertCompType type, const uint32_t size, GPUVertFe
VkImageType to_vk_image_type(const eGPUTextureType type)
{
/* See
* https://vulkan.lunarg.com/doc/view/1.3.243.0/linux/1.3-extensions/vkspec.html#resources-image-views-compatibility
* for reference */
switch (type) {
case GPU_TEXTURE_1D:
case GPU_TEXTURE_BUFFER:
case GPU_TEXTURE_1D_ARRAY:
return VK_IMAGE_TYPE_1D;
case GPU_TEXTURE_2D:
case GPU_TEXTURE_2D_ARRAY:
return VK_IMAGE_TYPE_2D;
case GPU_TEXTURE_3D:
case GPU_TEXTURE_CUBE:
case GPU_TEXTURE_CUBE_ARRAY:
return VK_IMAGE_TYPE_2D;
case GPU_TEXTURE_3D:
return VK_IMAGE_TYPE_3D;
case GPU_TEXTURE_ARRAY:
@ -610,7 +615,7 @@ VkImageType to_vk_image_type(const eGPUTextureType type)
return VK_IMAGE_TYPE_1D;
}
VkImageViewType to_vk_image_view_type(const eGPUTextureType type)
VkImageViewType to_vk_image_view_type(const eGPUTextureType type, const eImageViewUsage view_type)
{
switch (type) {
case GPU_TEXTURE_1D:
@ -621,13 +626,15 @@ VkImageViewType to_vk_image_view_type(const eGPUTextureType type)
case GPU_TEXTURE_3D:
return VK_IMAGE_VIEW_TYPE_3D;
case GPU_TEXTURE_CUBE:
return VK_IMAGE_VIEW_TYPE_CUBE;
return view_type == eImageViewUsage::Attachment ? VK_IMAGE_VIEW_TYPE_2D_ARRAY :
VK_IMAGE_VIEW_TYPE_CUBE;
case GPU_TEXTURE_1D_ARRAY:
return VK_IMAGE_VIEW_TYPE_1D_ARRAY;
case GPU_TEXTURE_2D_ARRAY:
return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
case GPU_TEXTURE_CUBE_ARRAY:
return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
return view_type == eImageViewUsage::Attachment ? VK_IMAGE_VIEW_TYPE_2D_ARRAY :
VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
case GPU_TEXTURE_ARRAY:
/* GPU_TEXTURE_ARRAY should always be used together with 1D, 2D, or CUBE*/

View File

@ -23,13 +23,27 @@
namespace blender::gpu {
/**
* Based on the usage of an Image View a different image view type should be created.
*
* When using a GPU_TEXTURE_CUBE as an frame buffer attachment it will be used as a
* GPU_TEXTURE_2D_ARRAY. eg only a single side of the cube map will be attached. But when bound as
* a shader resource the cubemap will be used.
*/
enum class eImageViewUsage {
/** Image View will be used as a bindable shader resource. */
ShaderBinding,
/** Image View will be used as an framebuffer attachment. */
Attachment,
};
VkImageAspectFlagBits to_vk_image_aspect_flag_bits(const eGPUTextureFormat format);
VkFormat to_vk_format(const eGPUTextureFormat format);
VkFormat to_vk_format(const GPUVertCompType type,
const uint32_t size,
const GPUVertFetchMode fetch_mode);
VkComponentMapping to_vk_component_mapping(const eGPUTextureFormat format);
VkImageViewType to_vk_image_view_type(const eGPUTextureType type);
VkImageViewType to_vk_image_view_type(const eGPUTextureType type, eImageViewUsage view_type);
VkImageType to_vk_image_type(const eGPUTextureType type);
VkClearColorValue to_vk_clear_color_value(const eGPUDataFormat format, const void *data);
VkIndexType to_vk_index_type(const GPUIndexBufType index_type);

View File

@ -404,7 +404,7 @@ void VKFrameBuffer::render_pass_create()
/* Ensure texture is allocated to ensure the image view. */
VKTexture &texture = *static_cast<VKTexture *>(unwrap(attachment.tex));
texture.ensure_allocated();
image_views_.append(VKImageView(texture, attachment.mip, name_));
image_views_.append(VKImageView(texture, attachment.layer, attachment.mip, name_));
image_views[attachment_location] = image_views_.last().vk_handle();
VkAttachmentDescription &attachment_description =

View File

@ -15,8 +15,8 @@
namespace blender::gpu {
VKImageView::VKImageView(VKTexture &texture, int mip_level, StringRefNull name)
: vk_image_view_(create_vk_image_view(texture, mip_level, name))
VKImageView::VKImageView(VKTexture &texture, int layer, int mip_level, StringRefNull name)
: vk_image_view_(create_vk_image_view(texture, layer, mip_level, name))
{
BLI_assert(vk_image_view_ != VK_NULL_HANDLE);
}
@ -41,6 +41,7 @@ VKImageView::~VKImageView()
}
}
VkImageView VKImageView::create_vk_image_view(VKTexture &texture,
int layer,
int mip_level,
StringRefNull name)
{
@ -49,14 +50,15 @@ VkImageView VKImageView::create_vk_image_view(VKTexture &texture,
VkImageViewCreateInfo image_view_info = {};
image_view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
image_view_info.image = texture.vk_image_handle();
image_view_info.viewType = to_vk_image_view_type(texture.type_get());
image_view_info.viewType = to_vk_image_view_type(texture.type_get(),
eImageViewUsage::Attachment);
image_view_info.format = to_vk_format(texture.format_get());
image_view_info.components = to_vk_component_mapping(texture.format_get());
image_view_info.subresourceRange.aspectMask = to_vk_image_aspect_flag_bits(texture.format_get());
image_view_info.subresourceRange.baseMipLevel = mip_level;
image_view_info.subresourceRange.levelCount = 1;
image_view_info.subresourceRange.baseArrayLayer = 0;
image_view_info.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
image_view_info.subresourceRange.baseArrayLayer = layer == -1 ? 0 : layer;
image_view_info.subresourceRange.layerCount = 1;
const VKDevice &device = VKBackend::get().device_get();
VkImageView image_view = VK_NULL_HANDLE;

View File

@ -20,7 +20,7 @@ class VKImageView : NonCopyable {
VkImageView vk_image_view_ = VK_NULL_HANDLE;
public:
VKImageView(VKTexture &texture, int mip_level, StringRefNull name);
VKImageView(VKTexture &texture, int layer, int mip_level, StringRefNull name);
/**
* Wrap the given vk_image_view handle. Note that the vk_image_view handle ownership is
@ -38,7 +38,10 @@ class VKImageView : NonCopyable {
}
private:
static VkImageView create_vk_image_view(VKTexture &texture, int mip_level, StringRefNull name);
static VkImageView create_vk_image_view(VKTexture &texture,
int layer,
int mip_level,
StringRefNull name);
};
} // namespace blender::gpu

View File

@ -157,6 +157,15 @@ void VKTexture::mip_range_set(int min, int max)
flags_ |= IMAGE_VIEW_DIRTY;
}
int VKTexture::layer_count()
{
int layers = 1;
if (ELEM(type_, GPU_TEXTURE_CUBE, GPU_TEXTURE_CUBE_ARRAY)) {
layers = d_;
}
return layers;
}
void VKTexture::read_sub(int mip, eGPUDataFormat format, const int area[4], void *r_data)
{
VKContext &context = *VKContext::get();
@ -165,7 +174,7 @@ void VKTexture::read_sub(int mip, eGPUDataFormat format, const int area[4], void
/* Vulkan images cannot be directly mapped to host memory and requires a staging buffer. */
VKBuffer staging_buffer;
size_t sample_len = area[2] * area[3];
size_t sample_len = area[2] * area[3] * layer_count();
size_t device_memory_size = sample_len * to_bytesize(format_);
staging_buffer.create(
@ -179,7 +188,7 @@ void VKTexture::read_sub(int mip, eGPUDataFormat format, const int area[4], void
region.imageExtent.depth = 1;
region.imageSubresource.aspectMask = to_vk_image_aspect_flag_bits(format_);
region.imageSubresource.mipLevel = mip;
region.imageSubresource.layerCount = 1;
region.imageSubresource.layerCount = layer_count();
VKCommandBuffer &command_buffer = context.command_buffer_get();
command_buffer.copy(staging_buffer, *this, Span<VkBufferImageCopy>(&region, 1));
@ -192,7 +201,7 @@ void *VKTexture::read(int mip, eGPUDataFormat format)
{
int mip_size[3] = {1, 1, 1};
mip_size_get(mip, mip_size);
size_t sample_len = mip_size[0] * mip_size[1];
size_t sample_len = mip_size[0] * mip_size[1] * layer_count();
size_t host_memory_size = sample_len * to_bytesize(format_, format);
void *data = MEM_mallocN(host_memory_size, __func__);
@ -372,6 +381,17 @@ static VkImageUsageFlagBits to_vk_image_usage(const eGPUTextureUsage usage,
return result;
}
static VkImageCreateFlagBits to_vk_image_create(const eGPUTextureType texture_type)
{
VkImageCreateFlagBits result = static_cast<VkImageCreateFlagBits>(0);
if (ELEM(texture_type, GPU_TEXTURE_CUBE, GPU_TEXTURE_CUBE_ARRAY)) {
result = static_cast<VkImageCreateFlagBits>(result | VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT);
}
return result;
}
bool VKTexture::allocate()
{
BLI_assert(vk_image_ == VK_NULL_HANDLE);
@ -379,17 +399,23 @@ bool VKTexture::allocate()
int extent[3] = {1, 1, 1};
mip_size_get(0, extent);
int layers = 1;
if (ELEM(type_, GPU_TEXTURE_CUBE, GPU_TEXTURE_CUBE_ARRAY)) {
layers = extent[2];
extent[2] = 1;
}
VKContext &context = *VKContext::get();
const VKDevice &device = VKBackend::get().device_get();
VkImageCreateInfo image_info = {};
image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
image_info.flags = to_vk_image_create(type_);
image_info.imageType = to_vk_image_type(type_);
image_info.extent.width = extent[0];
image_info.extent.height = extent[1];
image_info.extent.depth = extent[2];
image_info.mipLevels = max_ii(mipmaps_, 1);
image_info.arrayLayers = 1;
image_info.arrayLayers = layers;
image_info.format = to_vk_format(format_);
/* Some platforms (NVIDIA) requires that attached textures are always tiled optimal.
*
@ -536,14 +562,15 @@ void VKTexture::image_view_update()
VkImageViewCreateInfo image_view_info = {};
image_view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
image_view_info.image = vk_image_;
image_view_info.viewType = to_vk_image_view_type(type_);
image_view_info.viewType = to_vk_image_view_type(type_, eImageViewUsage::ShaderBinding);
image_view_info.format = to_vk_format(format_);
image_view_info.components = to_vk_component_mapping(format_);
image_view_info.subresourceRange.aspectMask = to_vk_image_aspect_flag_bits(format_);
IndexRange mip_range = mip_map_range();
image_view_info.subresourceRange.baseMipLevel = mip_range.first();
image_view_info.subresourceRange.levelCount = mip_range.size();
image_view_info.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
image_view_info.subresourceRange.layerCount =
ELEM(type_, GPU_TEXTURE_CUBE, GPU_TEXTURE_CUBE_ARRAY) ? d_ : VK_REMAINING_ARRAY_LAYERS;
const VKDevice &device = VKBackend::get().device_get();
VkImageView image_view = VK_NULL_HANDLE;

View File

@ -86,6 +86,8 @@ class VKTexture : public Texture {
*/
bool allocate();
int layer_count();
VkImageViewType vk_image_view_type() const;
/* -------------------------------------------------------------------- */

View File

@ -121,7 +121,9 @@ typedef enum eCustomDataType {
* lazily. Derived vertex and polygon normals are stored in #Mesh_Runtime.
*/
CD_NORMAL = 8,
CD_FACEMAP = 9, /* exclusive face group, each face can only be part of one */
#ifdef DNA_DEPRECATED_ALLOW
CD_FACEMAP = 9,
#endif
CD_PROP_FLOAT = 10,
CD_PROP_INT32 = 11,
CD_PROP_STRING = 12,
@ -190,7 +192,6 @@ typedef enum eCustomDataType {
#define CD_MASK_MCOL (1 << CD_MCOL)
#define CD_MASK_ORIGINDEX (1 << CD_ORIGINDEX)
#define CD_MASK_NORMAL (1 << CD_NORMAL)
#define CD_MASK_FACEMAP (1 << CD_FACEMAP)
#define CD_MASK_PROP_FLOAT (1 << CD_PROP_FLOAT)
#define CD_MASK_PROP_INT32 (1 << CD_PROP_INT32)
#define CD_MASK_PROP_STRING (1 << CD_PROP_STRING)

View File

@ -56,15 +56,6 @@ typedef struct bDeformGroup {
char flag, _pad0[7];
} bDeformGroup;
/** Face Maps. */
typedef struct bFaceMap {
struct bFaceMap *next, *prev;
/** MAX_VGROUP_NAME. */
char name[64];
char flag;
char _pad0[7];
} bFaceMap;
#define MAX_VGROUP_NAME 64
/* bDeformGroup->flag */
@ -353,8 +344,6 @@ typedef struct Object {
ListBase modifiers;
/** List of GpencilModifierData structures. */
ListBase greasepencil_modifiers;
/** List of facemaps. */
ListBase fmaps;
/** List of viewport effects. Actually only used by grease pencil. */
ListBase shader_fx;
@ -445,8 +434,7 @@ typedef struct Object {
/** Current deformation group, NOTE: index starts at 1. */
unsigned short actdef DNA_DEPRECATED;
/** Current face map, NOTE: index starts at 1. */
unsigned short actfmap;
char _pad2[2];
char _pad2[4];
/** Object color (in most cases the material color is used for drawing). */
float color[4];

View File

@ -357,7 +357,6 @@ static void rna_AssetHandle_file_data_set(PointerRNA *ptr,
static void rna_AssetHandle_get_full_library_path(
// AssetHandle *asset,
FileDirEntry *asset_file,
AssetLibraryReference *UNUSED(asset_library), /* Deprecated. */
char r_result[/*FILE_MAX_LIBEXTRA*/])
{
AssetHandle asset = {.file_data = asset_file};
@ -537,13 +536,6 @@ static void rna_def_asset_handle_api(StructRNA *srna)
RNA_def_function_flag(func, FUNC_NO_SELF);
parm = RNA_def_pointer(func, "asset_file_handle", "FileSelectEntry", "", "");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
RNA_def_pointer(
func,
"asset_library_ref",
"AssetLibraryReference",
"",
"The asset library containing the given asset. Deprecated and optional argument, will be "
"ignored. Kept for API compatibility only");
parm = RNA_def_string(func, "result", NULL, FILE_MAX_LIBEXTRA, "result", "");
RNA_def_parameter_flags(parm, PROP_THICK_WRAP, 0);
RNA_def_function_output(func, parm);

View File

@ -694,7 +694,7 @@ static void rna_tag_animation_update(Main *bmain, ID *id)
static void rna_FCurve_update_data_ex(ID *id, FCurve *fcu, Main *bmain)
{
sort_time_fcurve(fcu);
/* TODO: Blender 4.0 should call BKE_fcurve_deduplicate_keys(fcu) here. */
BKE_fcurve_deduplicate_keys(fcu);
BKE_fcurve_handles_recalc(fcu);
rna_tag_animation_update(bmain, id);

View File

@ -86,11 +86,6 @@ static CustomData *rna_mesh_edata_helper(Mesh *me)
return (me->edit_mesh) ? &me->edit_mesh->bm->edata : &me->edata;
}
static CustomData *rna_mesh_pdata_helper(Mesh *me)
{
return (me->edit_mesh) ? &me->edit_mesh->bm->pdata : &me->pdata;
}
static CustomData *rna_mesh_ldata_helper(Mesh *me)
{
return (me->edit_mesh) ? &me->edit_mesh->bm->ldata : &me->ldata;
@ -106,11 +101,6 @@ static CustomData *rna_mesh_edata(const PointerRNA *ptr)
Mesh *me = rna_mesh(ptr);
return rna_mesh_edata_helper(me);
}
static CustomData *rna_mesh_pdata(const PointerRNA *ptr)
{
Mesh *me = rna_mesh(ptr);
return rna_mesh_pdata_helper(me);
}
static CustomData *rna_mesh_ldata(const PointerRNA *ptr)
{
@ -154,17 +144,6 @@ static void rna_MeshEdgeLayer_name_set(PointerRNA *ptr, const char *value)
}
}
# endif
static void rna_MeshPolyLayer_name_set(PointerRNA *ptr, const char *value)
{
CustomDataLayer *layer = (CustomDataLayer *)ptr->data;
if (CD_TYPE_AS_MASK(layer->type) & CD_MASK_PROP_ALL) {
BKE_id_attribute_rename(ptr->owner_id, layer->name, value, NULL);
}
else {
rna_cd_layer_name_set(rna_mesh_pdata(ptr), layer, value);
}
}
static void rna_MeshLoopLayer_name_set(PointerRNA *ptr, const char *value)
{
CustomDataLayer *layer = (CustomDataLayer *)ptr->data;
@ -1356,78 +1335,6 @@ static int rna_MeshPaintMaskLayer_data_length(PointerRNA *ptr)
/* End paint mask */
/* Face maps */
DEFINE_CUSTOMDATA_LAYER_COLLECTION(face_map, pdata, CD_FACEMAP)
DEFINE_CUSTOMDATA_LAYER_COLLECTION_ACTIVEITEM(
face_map, pdata, CD_FACEMAP, active, MeshFaceMapLayer)
static char *rna_MeshFaceMapLayer_path(const PointerRNA *ptr)
{
const CustomDataLayer *cdl = ptr->data;
char name_esc[sizeof(cdl->name) * 2];
BLI_str_escape(name_esc, cdl->name, sizeof(name_esc));
return BLI_sprintfN("face_maps[\"%s\"]", name_esc);
}
static void rna_MeshFaceMapLayer_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
Mesh *me = rna_mesh(ptr);
CustomDataLayer *layer = (CustomDataLayer *)ptr->data;
rna_iterator_array_begin(
iter, layer->data, sizeof(int), (me->edit_mesh) ? 0 : me->totpoly, 0, NULL);
}
static int rna_MeshFaceMapLayer_data_length(PointerRNA *ptr)
{
Mesh *me = rna_mesh(ptr);
return (me->edit_mesh) ? 0 : me->totpoly;
}
static PointerRNA rna_Mesh_face_map_new(struct Mesh *me, ReportList *reports, const char *name)
{
if (BKE_mesh_ensure_facemap_customdata(me) == false) {
BKE_report(reports, RPT_ERROR, "Currently only single face map layers are supported");
return PointerRNA_NULL;
}
CustomData *pdata = rna_mesh_pdata_helper(me);
int index = CustomData_get_layer_index(pdata, CD_FACEMAP);
BLI_assert(index != -1);
CustomDataLayer *cdl = &pdata->layers[index];
rna_cd_layer_name_set(pdata, cdl, name);
PointerRNA ptr;
RNA_pointer_create(&me->id, &RNA_MeshFaceMapLayer, cdl, &ptr);
return ptr;
}
static void rna_Mesh_face_map_remove(struct Mesh *me,
ReportList *reports,
struct CustomDataLayer *layer)
{
/* just for sanity check */
{
CustomData *pdata = rna_mesh_pdata_helper(me);
int index = CustomData_get_layer_index(pdata, CD_FACEMAP);
if (index != -1) {
CustomDataLayer *layer_test = &pdata->layers[index];
if (layer != layer_test) {
/* don't show name, its likely freed memory */
BKE_report(reports, RPT_ERROR, "Face map not in mesh");
return;
}
}
}
if (BKE_mesh_clear_facemap_customdata(me) == false) {
BKE_report(reports, RPT_ERROR, "Error removing face map");
}
}
/* End face maps */
/* poly.vertices - this is faked loop access for convenience */
static int rna_MeshPoly_vertices_get_length(const PointerRNA *ptr,
int length[RNA_MAX_ARRAY_DIMENSION])
@ -1702,27 +1609,6 @@ static char *rna_EdgeCustomData_data_path(const PointerRNA *ptr, const char *col
return NULL;
}
static char *rna_PolyCustomData_data_path(const PointerRNA *ptr, const char *collection, int type)
{
const CustomDataLayer *cdl;
const Mesh *me = rna_mesh(ptr);
const CustomData *pdata = rna_mesh_pdata(ptr);
int a, b, totpoly = (me->edit_mesh) ? 0 : me->totpoly;
for (cdl = pdata->layers, a = 0; a < pdata->totlayer; cdl++, a++) {
if (cdl->type == type) {
b = ((char *)ptr->data - ((char *)cdl->data)) / CustomData_sizeof(type);
if (b >= 0 && b < totpoly) {
char name_esc[sizeof(cdl->name) * 2];
BLI_str_escape(name_esc, cdl->name, sizeof(name_esc));
return BLI_sprintfN("%s[\"%s\"].data[%d]", collection, name_esc, b);
}
}
}
return NULL;
}
static char *rna_LoopCustomData_data_path(const PointerRNA *ptr, const char *collection, int type)
{
const CustomDataLayer *cdl;
@ -2053,11 +1939,6 @@ static char *rna_MeshColor_path(const PointerRNA *ptr)
return rna_LoopCustomData_data_path(ptr, "vertex_colors", CD_PROP_BYTE_COLOR);
}
static char *rna_MeshFaceMap_path(const PointerRNA *ptr)
{
return rna_PolyCustomData_data_path(ptr, "face_maps", CD_FACEMAP);
}
/***************************************/
static int rna_Mesh_tot_vert_get(PointerRNA *ptr)
@ -2153,10 +2034,6 @@ static void UNUSED_FUNCTION(rna_mesh_unused)(void)
(void)rna_Mesh_uv_layer_render_index_get;
(void)rna_Mesh_uv_layer_render_index_set;
(void)rna_Mesh_uv_layer_render_set;
(void)rna_Mesh_face_map_index_range;
(void)rna_Mesh_face_map_active_index_set;
(void)rna_Mesh_face_map_active_index_get;
(void)rna_Mesh_face_map_active_set;
(void)rna_Mesh_vertex_crease_index_range;
(void)rna_Mesh_edge_crease_index_range;
/* end unused function block */
@ -3227,85 +3104,6 @@ static void rna_def_paint_mask(BlenderRNA *brna, PropertyRNA *UNUSED(cprop))
RNA_def_property_update(prop, 0, "rna_Mesh_update_data_legacy_deg_tag_all");
}
static void rna_def_face_map(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "MeshFaceMapLayer", NULL);
RNA_def_struct_ui_text(srna, "Mesh Face Map Layer", "Per-face map index");
RNA_def_struct_sdna(srna, "CustomDataLayer");
RNA_def_struct_path_func(srna, "rna_MeshFaceMapLayer_path");
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_struct_name_property(srna, prop);
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MeshPolyLayer_name_set");
RNA_def_property_string_maxlength(prop, MAX_CUSTOMDATA_LAYER_NAME_NO_PREFIX);
RNA_def_property_ui_text(prop, "Name", "Name of face map layer");
RNA_def_property_update(prop, 0, "rna_Mesh_update_data_legacy_deg_tag_all");
prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "MeshFaceMap");
RNA_def_property_ui_text(prop, "Data", "");
RNA_def_property_collection_funcs(prop,
"rna_MeshFaceMapLayer_data_begin",
"rna_iterator_array_next",
"rna_iterator_array_end",
"rna_iterator_array_get",
"rna_MeshFaceMapLayer_data_length",
NULL,
NULL,
NULL);
/* FaceMap struct */
srna = RNA_def_struct(brna, "MeshFaceMap", NULL);
RNA_def_struct_sdna(srna, "MIntProperty");
RNA_def_struct_ui_text(srna, "Int Property", "");
RNA_def_struct_path_func(srna, "rna_MeshFaceMap_path");
prop = RNA_def_property(srna, "value", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "i");
RNA_def_property_ui_text(prop, "Value", "");
RNA_def_property_update(prop, 0, "rna_Mesh_update_data_legacy_deg_tag_all");
}
static void rna_def_face_maps(BlenderRNA *brna, PropertyRNA *cprop)
{
StructRNA *srna;
PropertyRNA *prop;
RNA_def_property_srna(cprop, "MeshFaceMapLayers");
srna = RNA_def_struct(brna, "MeshFaceMapLayers", NULL);
RNA_def_struct_ui_text(srna, "Mesh Face Map Layer", "Per-face map index");
RNA_def_struct_sdna(srna, "Mesh");
RNA_def_struct_ui_text(srna, "Mesh Face Maps", "Collection of mesh face maps");
/* add this since we only ever have one layer anyway, don't bother with active_index */
prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "MeshFaceMapLayer");
RNA_def_property_pointer_funcs(prop, "rna_Mesh_face_map_active_get", NULL, NULL, NULL);
RNA_def_property_ui_text(prop, "Active Face Map Layer", "");
RNA_def_property_update(prop, 0, "rna_Mesh_update_data_legacy_deg_tag_all");
FunctionRNA *func;
PropertyRNA *parm;
func = RNA_def_function(srna, "new", "rna_Mesh_face_map_new");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Add a float property layer to Mesh");
RNA_def_string(func, "name", "Face Map", 0, "", "Face map name");
parm = RNA_def_pointer(func, "layer", "MeshFaceMapLayer", "", "The newly created layer");
RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "remove", "rna_Mesh_face_map_remove");
RNA_def_function_ui_description(func, "Remove a face map layer");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
parm = RNA_def_pointer(func, "layer", "MeshFaceMapLayer", "", "The layer to remove");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
}
static void rna_def_looptri_poly_value(BlenderRNA *brna)
{
StructRNA *srna = RNA_def_struct(brna, "ReadOnlyInteger", NULL);
@ -3552,23 +3350,6 @@ static void rna_def_mesh(BlenderRNA *brna)
"Legacy vertex color layers. Deprecated, use color attributes instead");
rna_def_loop_colors(brna, prop);
/* face-maps */
prop = RNA_def_property(srna, "face_maps", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "pdata.layers", "pdata.totlayer");
RNA_def_property_collection_funcs(prop,
"rna_Mesh_face_maps_begin",
NULL,
NULL,
NULL,
"rna_Mesh_face_maps_length",
NULL,
NULL,
NULL);
RNA_def_property_struct_type(prop, "MeshFaceMapLayer");
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
RNA_def_property_ui_text(prop, "Face Map", "");
rna_def_face_maps(brna, prop);
/* Skin vertices */
prop = RNA_def_property(srna, "skin_vertices", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "vdata.layers", "vdata.totlayer");
@ -3866,7 +3647,6 @@ void RNA_def_mesh(BlenderRNA *brna)
rna_def_mpolygon(brna);
rna_def_mloopuv(brna);
rna_def_mloopcol(brna);
rna_def_face_map(brna);
}
#endif

View File

@ -35,7 +35,6 @@
#include "BKE_editmesh.h"
#include "BKE_layer.h"
#include "BKE_object_deform.h"
#include "BKE_object_facemap.h"
#include "BKE_paint.h"
#include "RNA_access.h"
@ -966,91 +965,6 @@ void rna_object_vgroup_name_set(PointerRNA *ptr,
result[0] = '\0';
}
static void rna_FaceMap_name_set(PointerRNA *ptr, const char *value)
{
Object *ob = (Object *)ptr->owner_id;
bFaceMap *fmap = (bFaceMap *)ptr->data;
STRNCPY_UTF8(fmap->name, value);
BKE_object_facemap_unique_name(ob, fmap);
}
static int rna_FaceMap_index_get(PointerRNA *ptr)
{
Object *ob = (Object *)ptr->owner_id;
return BLI_findindex(&ob->fmaps, ptr->data);
}
static PointerRNA rna_Object_active_face_map_get(PointerRNA *ptr)
{
Object *ob = (Object *)ptr->owner_id;
return rna_pointer_inherit_refine(ptr, &RNA_FaceMap, BLI_findlink(&ob->fmaps, ob->actfmap - 1));
}
static int rna_Object_active_face_map_index_get(PointerRNA *ptr)
{
Object *ob = (Object *)ptr->owner_id;
return ob->actfmap - 1;
}
static void rna_Object_active_face_map_index_set(PointerRNA *ptr, int value)
{
Object *ob = (Object *)ptr->owner_id;
ob->actfmap = value + 1;
}
static void rna_Object_active_face_map_index_range(
PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax))
{
Object *ob = (Object *)ptr->owner_id;
*min = 0;
*max = max_ii(0, BLI_listbase_count(&ob->fmaps) - 1);
}
void rna_object_BKE_object_facemap_name_index_get(PointerRNA *ptr, char *value, int index)
{
Object *ob = (Object *)ptr->owner_id;
bFaceMap *fmap;
fmap = BLI_findlink(&ob->fmaps, index - 1);
if (fmap) {
strcpy(value, fmap->name);
}
else {
value[0] = '\0';
}
}
int rna_object_BKE_object_facemap_name_index_length(PointerRNA *ptr, int index)
{
Object *ob = (Object *)ptr->owner_id;
bFaceMap *fmap;
fmap = BLI_findlink(&ob->fmaps, index - 1);
return (fmap) ? strlen(fmap->name) : 0;
}
void rna_object_BKE_object_facemap_name_index_set(PointerRNA *ptr, const char *value, short *index)
{
Object *ob = (Object *)ptr->owner_id;
*index = BKE_object_facemap_name_index(ob, value) + 1;
}
void rna_object_fmap_name_set(PointerRNA *ptr, const char *value, char *result, int result_maxncpy)
{
Object *ob = (Object *)ptr->owner_id;
bFaceMap *fmap = BKE_object_facemap_find_name(ob, value);
if (fmap) {
/* No need for BLI_strncpy_utf8, since this matches an existing group. */
BLI_strncpy(result, value, result_maxncpy);
return;
}
result[0] = '\0';
}
void rna_object_uvlayer_name_set(PointerRNA *ptr,
const char *value,
char *result,
@ -2151,71 +2065,6 @@ static float rna_VertexGroup_weight(ID *id, bDeformGroup *dg, ReportList *report
return weight;
}
static bFaceMap *rna_Object_fmap_new(Object *ob, const char *name)
{
bFaceMap *fmap = BKE_object_facemap_add_name(ob, name);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
return fmap;
}
static void rna_Object_fmap_remove(Object *ob, ReportList *reports, PointerRNA *fmap_ptr)
{
bFaceMap *fmap = fmap_ptr->data;
if (BLI_findindex(&ob->fmaps, fmap) == -1) {
BKE_reportf(
reports, RPT_ERROR, "Face map '%s' not in object '%s'", fmap->name, ob->id.name + 2);
return;
}
BKE_object_facemap_remove(ob, fmap);
RNA_POINTER_INVALIDATE(fmap_ptr);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
}
static void rna_Object_fmap_clear(Object *ob)
{
BKE_object_facemap_clear(ob);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
}
static void rna_FaceMap_face_add(
ID *id, bFaceMap *fmap, ReportList *reports, int index_len, int *index)
{
Object *ob = (Object *)id;
if (BKE_object_is_in_editmode(ob)) {
BKE_report(reports, RPT_ERROR, "FaceMap.add(): cannot be called while object is in edit mode");
return;
}
while (index_len--) {
ED_object_facemap_face_add(ob, fmap, *index++);
}
WM_main_add_notifier(NC_GEOM | ND_DATA, (ID *)ob->data);
}
static void rna_FaceMap_face_remove(
ID *id, bFaceMap *fmap, ReportList *reports, int index_len, int *index)
{
Object *ob = (Object *)id;
if (BKE_object_is_in_editmode(ob)) {
BKE_report(reports, RPT_ERROR, "FaceMap.add(): cannot be called while object is in edit mode");
return;
}
while (index_len--) {
ED_object_facemap_face_remove(ob, fmap, *index++);
}
WM_main_add_notifier(NC_GEOM | ND_DATA, (ID *)ob->data);
}
/* generic poll functions */
bool rna_Lattice_object_poll(PointerRNA *UNUSED(ptr), PointerRNA value)
{
@ -2486,52 +2335,6 @@ static void rna_def_vertex_group(BlenderRNA *brna)
RNA_def_function_return(func, parm);
}
static void rna_def_face_map(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
FunctionRNA *func;
PropertyRNA *parm;
srna = RNA_def_struct(brna, "FaceMap", NULL);
RNA_def_struct_sdna(srna, "bFaceMap");
RNA_def_struct_ui_text(
srna, "Face Map", "Group of faces, each face can only be part of one map");
RNA_def_struct_ui_icon(srna, ICON_MOD_TRIANGULATE);
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_property_ui_text(prop, "Name", "Face map name");
RNA_def_struct_name_property(srna, prop);
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_FaceMap_name_set");
/* update data because modifiers may use #24761. */
RNA_def_property_update(prop, NC_GEOM | ND_DATA | NA_RENAME, "rna_Object_internal_update_data");
prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SELECT);
RNA_def_property_ui_text(prop, "Select", "Face map selection state (for tools to use)");
/* important not to use a notifier here, creates a feedback loop! */
prop = RNA_def_property(srna, "index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_int_funcs(prop, "rna_FaceMap_index_get", NULL, NULL);
RNA_def_property_ui_text(prop, "Index", "Index number of the face map");
func = RNA_def_function(srna, "add", "rna_FaceMap_face_add");
RNA_def_function_ui_description(func, "Add faces to the face-map");
RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID);
/* TODO: see how array size of 0 works, this shouldn't be used. */
parm = RNA_def_int_array(func, "index", 1, NULL, 0, 0, "", "List of indices", 0, 0);
RNA_def_parameter_flags(parm, PROP_DYNAMIC, PARM_REQUIRED);
func = RNA_def_function(srna, "remove", "rna_FaceMap_face_remove");
RNA_def_function_ui_description(func, "Remove faces from the face-map");
RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID);
/* TODO: see how array size of 0 works, this shouldn't be used. */
parm = RNA_def_int_array(func, "index", 1, NULL, 0, 0, "", "List of indices", 0, 0);
RNA_def_parameter_flags(parm, PROP_DYNAMIC, PARM_REQUIRED);
}
static void rna_def_material_slot(BlenderRNA *brna)
{
StructRNA *srna;
@ -2921,56 +2724,6 @@ static void rna_def_object_vertex_groups(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_function_ui_description(func, "Delete all vertex groups from object");
}
/* object.face_maps */
static void rna_def_object_face_maps(BlenderRNA *brna, PropertyRNA *cprop)
{
StructRNA *srna;
PropertyRNA *prop;
FunctionRNA *func;
PropertyRNA *parm;
RNA_def_property_srna(cprop, "FaceMaps");
srna = RNA_def_struct(brna, "FaceMaps", NULL);
RNA_def_struct_sdna(srna, "Object");
RNA_def_struct_ui_text(srna, "Face Maps", "Collection of face maps");
prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "FaceMap");
RNA_def_property_pointer_funcs(
prop, "rna_Object_active_face_map_get", "rna_Object_active_face_map_set", NULL, NULL);
RNA_def_property_ui_text(prop, "Active Face Map", "Face maps of the object");
RNA_def_property_update(prop, NC_GEOM | ND_DATA, "rna_Object_internal_update_data");
prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_int_sdna(prop, NULL, "actfmap");
RNA_def_property_int_funcs(prop,
"rna_Object_active_face_map_index_get",
"rna_Object_active_face_map_index_set",
"rna_Object_active_face_map_index_range");
RNA_def_property_ui_text(prop, "Active Face Map Index", "Active index in face map array");
RNA_def_property_update(prop, NC_GEOM | ND_DATA, "rna_Object_internal_update_data");
/* face maps */ /* add_face_map */
func = RNA_def_function(srna, "new", "rna_Object_fmap_new");
RNA_def_function_ui_description(func, "Add face map to object");
RNA_def_string(func, "name", "Map", 0, "", "face map name"); /* optional */
parm = RNA_def_pointer(func, "fmap", "FaceMap", "", "New face map");
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "remove", "rna_Object_fmap_remove");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Delete vertex group from object");
parm = RNA_def_pointer(func, "group", "FaceMap", "", "Face map to remove");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
func = RNA_def_function(srna, "clear", "rna_Object_fmap_clear");
RNA_def_function_ui_description(func, "Delete all vertex groups from object");
}
static void rna_def_object_display(BlenderRNA *brna)
{
StructRNA *srna;
@ -3599,14 +3352,6 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Vertex Groups", "Vertex groups of the object");
rna_def_object_vertex_groups(brna, prop);
/* face maps */
prop = RNA_def_property(srna, "face_maps", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "fmaps", NULL);
RNA_def_property_struct_type(prop, "FaceMap");
RNA_def_property_override_clear_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Face Maps", "Maps of faces of the object");
rna_def_object_face_maps(brna, prop);
/* empty */
prop = RNA_def_property(srna, "empty_display_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "empty_drawtype");
@ -4017,7 +3762,6 @@ void RNA_def_object(BlenderRNA *brna)
RNA_define_animate_sdna(false);
rna_def_vertex_group(brna);
rna_def_face_map(brna);
rna_def_material_slot(brna);
rna_def_object_display(brna);
rna_def_object_lineart(brna);

View File

@ -44,12 +44,6 @@ static void rna_gizmo_draw_preset_circle(wmGizmo *gz, float matrix[16], int axis
ED_gizmo_draw_preset_circle(gz, (float(*)[4])matrix, axis, select_id);
}
static void rna_gizmo_draw_preset_facemap(
wmGizmo *gz, struct bContext *C, struct Object *ob, int facemap, int select_id)
{
ED_gizmo_draw_preset_facemap(C, gz, ob, facemap, select_id);
}
/* -------------------------------------------------------------------- */
/** \name Gizmo Property Define
* \{ */
@ -261,24 +255,6 @@ void RNA_api_gizmo(StructRNA *srna)
/* -------------------------------------------------------------------- */
/* Other Shapes */
/* draw_preset_facemap */
func = RNA_def_function(srna, "draw_preset_facemap", "rna_gizmo_draw_preset_facemap");
RNA_def_function_ui_description(func, "Draw the face-map of a mesh object");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
parm = RNA_def_pointer(func, "object", "Object", "", "Object");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
parm = RNA_def_int(func, "face_map", 0, 0, INT_MAX, "Face map index", "", 0, INT_MAX);
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
RNA_def_int(func,
"select_id",
-1,
-1,
INT_MAX,
"ID to use when gizmo is selectable. Use -1 when not selecting",
"",
-1,
INT_MAX);
/* -------------------------------------------------------------------- */
/* Property API */

View File

@ -825,36 +825,47 @@ class RenderLayerOperation : public NodeOperation {
void execute() override
{
const int view_layer = bnode().custom1;
GPUTexture *pass_texture = context().get_input_texture(view_layer, RE_PASSNAME_COMBINED);
GPUTexture *combined_texture = context().get_input_texture(view_layer, RE_PASSNAME_COMBINED);
execute_image(pass_texture);
execute_alpha(pass_texture);
execute_pass("Image", combined_texture, "compositor_read_pass_color");
execute_pass("Alpha", combined_texture, "compositor_read_pass_alpha");
/* Other output passes are not supported for now, so allocate them as invalid. */
for (const bNodeSocket *output : this->node()->output_sockets()) {
if (!STR_ELEM(output->identifier, "Image", "Alpha")) {
Result &unsupported_result = get_result(output->identifier);
if (unsupported_result.should_compute()) {
unsupported_result.allocate_invalid();
context().set_info_message("Viewport compositor setup not fully supported");
}
if (STR_ELEM(output->identifier, "Image", "Alpha")) {
continue;
}
GPUTexture *pass_texture = context().get_input_texture(view_layer, output->identifier);
if (output->type == SOCK_FLOAT) {
execute_pass(output->identifier, pass_texture, "compositor_read_pass_float");
}
else if (output->type == SOCK_VECTOR) {
execute_pass(output->identifier, pass_texture, "compositor_read_pass_vector");
}
else if (output->type == SOCK_RGBA) {
execute_pass(output->identifier, pass_texture, "compositor_read_pass_color");
}
else {
BLI_assert_unreachable();
}
}
}
void execute_image(GPUTexture *pass_texture)
void execute_pass(const char *pass_name, GPUTexture *pass_texture, const char *shader_name)
{
Result &image_result = get_result("Image");
Result &image_result = get_result(pass_name);
if (!image_result.should_compute()) {
return;
}
if (pass_texture == nullptr) {
/* Pass not rendered (yet). */
/* Pass not rendered yet, or not supported by viewport. */
image_result.allocate_invalid();
context().set_info_message("Viewport compositor setup not fully supported");
return;
}
GPUShader *shader = shader_manager().get("compositor_read_pass");
GPUShader *shader = shader_manager().get(shader_name);
GPU_shader_bind(shader);
/* The compositing space might be limited to a subset of the pass texture, so only read that
@ -876,41 +887,6 @@ class RenderLayerOperation : public NodeOperation {
GPU_texture_unbind(pass_texture);
image_result.unbind_as_image();
}
void execute_alpha(GPUTexture *pass_texture)
{
Result &alpha_result = get_result("Alpha");
if (!alpha_result.should_compute()) {
return;
}
if (pass_texture == nullptr) {
/* Pass not rendered (yet). */
alpha_result.allocate_invalid();
return;
}
GPUShader *shader = shader_manager().get("compositor_read_pass_alpha");
GPU_shader_bind(shader);
/* The compositing space might be limited to a subset of the pass texture, so only read that
* compositing region into an appropriately sized texture. */
const rcti compositing_region = context().get_compositing_region();
const int2 lower_bound = int2(compositing_region.xmin, compositing_region.ymin);
GPU_shader_uniform_2iv(shader, "compositing_region_lower_bound", lower_bound);
const int input_unit = GPU_shader_get_sampler_binding(shader, "input_tx");
GPU_texture_bind(pass_texture, input_unit);
const int2 compositing_region_size = context().get_compositing_region_size();
alpha_result.allocate_texture(Domain(compositing_region_size));
alpha_result.bind_as_image(shader, "output_img");
compute_dispatch_threads_at_least(shader, compositing_region_size);
GPU_shader_unbind();
GPU_texture_unbind(pass_texture);
alpha_result.unbind_as_image();
}
};
static NodeOperation *get_compositor_operation(Context &context, DNode node)

View File

@ -77,7 +77,7 @@ class ViewerOperation : public NodeOperation {
const Result &second_image = get_input("Image_001");
second_image.bind_as_texture(shader, "second_image_tx");
GPUTexture *output_texture = context().get_output_texture();
GPUTexture *output_texture = context().get_viewer_output_texture();
const int image_unit = GPU_shader_get_sampler_binding(shader, "output_img");
GPU_texture_image_bind(output_texture, image_unit);

View File

@ -105,7 +105,7 @@ class ViewerOperation : public NodeOperation {
color.w = alpha.get_float_value();
}
GPU_texture_clear(context().get_output_texture(), GPU_DATA_FLOAT, color);
GPU_texture_clear(context().get_viewer_output_texture(), GPU_DATA_FLOAT, color);
}
/* Executes when the alpha channel of the image is ignored. */
@ -123,7 +123,7 @@ class ViewerOperation : public NodeOperation {
const Result &image = get_input("Image");
image.bind_as_texture(shader, "input_tx");
GPUTexture *output_texture = context().get_output_texture();
GPUTexture *output_texture = context().get_viewer_output_texture();
const int image_unit = GPU_shader_get_sampler_binding(shader, "output_img");
GPU_texture_image_bind(output_texture, image_unit);
@ -151,7 +151,7 @@ class ViewerOperation : public NodeOperation {
const Result &image = get_input("Image");
image.bind_as_texture(shader, "input_tx");
GPUTexture *output_texture = context().get_output_texture();
GPUTexture *output_texture = context().get_viewer_output_texture();
const int image_unit = GPU_shader_get_sampler_binding(shader, "output_img");
GPU_texture_image_bind(output_texture, image_unit);
@ -181,7 +181,7 @@ class ViewerOperation : public NodeOperation {
const Result &alpha = get_input("Alpha");
alpha.bind_as_texture(shader, "alpha_tx");
GPUTexture *output_texture = context().get_output_texture();
GPUTexture *output_texture = context().get_viewer_output_texture();
const int image_unit = GPU_shader_get_sampler_binding(shader, "output_img");
GPU_texture_image_bind(output_texture, image_unit);

View File

@ -127,7 +127,6 @@ static void expand_mesh(Mesh &mesh,
CustomData_realloc(&mesh.edata, old_edges_num, mesh.totedge);
}
if (poly_expand != 0) {
CustomData_free_layers(&mesh.pdata, CD_FACEMAP, mesh.totpoly);
CustomData_free_layers(&mesh.pdata, CD_FREESTYLE_FACE, mesh.totpoly);
const int old_polys_num = mesh.totpoly;
mesh.totpoly += poly_expand;

View File

@ -98,8 +98,6 @@ PyDoc_STRVAR(bpy_bmlayeraccess_collection__skin_doc,
"Accessor for skin layer.\n\ntype: :class:`BMLayerCollection`");
PyDoc_STRVAR(bpy_bmlayeraccess_collection__paint_mask_doc,
"Accessor for paint mask layer.\n\ntype: :class:`BMLayerCollection`");
PyDoc_STRVAR(bpy_bmlayeraccess_collection__face_map_doc,
"FaceMap custom-data layer.\n\ntype: :class:`BMLayerCollection`");
#ifdef WITH_FREESTYLE
PyDoc_STRVAR(bpy_bmlayeraccess_collection__freestyle_edge_doc,
"Accessor for Freestyle edge layer.\n\ntype: :class:`BMLayerCollection`");
@ -302,11 +300,6 @@ static PyGetSetDef bpy_bmlayeraccess_face_getseters[] = {
(setter)NULL,
bpy_bmlayeraccess_collection__string_doc,
(void *)CD_PROP_STRING},
{"face_map",
(getter)bpy_bmlayeraccess_collection_get,
(setter)NULL,
bpy_bmlayeraccess_collection__face_map_doc,
(void *)CD_FACEMAP},
#ifdef WITH_FREESTYLE
{"freestyle",
@ -1115,8 +1108,7 @@ PyObject *BPy_BMLayerItem_GetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer)
ret = PyFloat_FromDouble(*(float *)value);
break;
}
case CD_PROP_INT32:
case CD_FACEMAP: {
case CD_PROP_INT32: {
ret = PyLong_FromLong(*(int *)value);
break;
}
@ -1194,8 +1186,7 @@ int BPy_BMLayerItem_SetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer, PyObj
}
break;
}
case CD_PROP_INT32:
case CD_FACEMAP: {
case CD_PROP_INT32: {
const int tmp_val = PyC_Long_AsI32(py_value);
if (UNLIKELY(tmp_val == -1 && PyErr_Occurred())) {
/* error is set */

View File

@ -2,9 +2,13 @@
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include <cstring>
#include "BLI_threads.h"
#include "BLI_vector.hh"
#include "MEM_guardedalloc.h"
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_node.hh"
@ -12,6 +16,9 @@
#include "DRW_engine.h"
#include "IMB_colormanagement.h"
#include "IMB_imbuf.h"
#include "COM_context.hh"
#include "COM_evaluator.hh"
@ -63,6 +70,9 @@ class Context : public realtime_compositor::Context {
/* Output combined texture. */
GPUTexture *output_texture_ = nullptr;
/* Viewer output texture. */
GPUTexture *viewer_output_texture_ = nullptr;
public:
Context(const Scene &scene,
const RenderData &render_data,
@ -81,7 +91,8 @@ class Context : public realtime_compositor::Context {
virtual ~Context()
{
GPU_texture_free(output_texture_);
GPU_TEXTURE_FREE_SAFE(output_texture_);
GPU_TEXTURE_FREE_SAFE(viewer_output_texture_);
}
const bNodeTree &get_node_tree() const override
@ -94,6 +105,11 @@ class Context : public realtime_compositor::Context {
return use_file_output_;
}
bool use_composite_output() const override
{
return true;
}
bool use_texture_color_management() const override
{
return BKE_scene_check_color_management_enabled(&scene_);
@ -121,7 +137,7 @@ class Context : public realtime_compositor::Context {
GPUTexture *get_output_texture() override
{
/* TODO: support outputting for viewers and previews.
/* TODO: support outputting for previews.
* TODO: just a temporary hack, needs to get stored in RenderResult,
* once that supports GPU buffers. */
if (output_texture_ == nullptr) {
@ -138,6 +154,25 @@ class Context : public realtime_compositor::Context {
return output_texture_;
}
GPUTexture *get_viewer_output_texture() override
{
/* TODO: support outputting previews.
* TODO: just a temporary hack, needs to get stored in RenderResult,
* once that supports GPU buffers. */
if (viewer_output_texture_ == nullptr) {
const int2 size = get_render_size();
viewer_output_texture_ = GPU_texture_create_2d("compositor_viewer_output_texture",
size.x,
size.y,
1,
GPU_RGBA16F,
GPU_TEXTURE_USAGE_GENERAL,
NULL);
}
return viewer_output_texture_;
}
GPUTexture *get_input_texture(int view_layer_id, const char *pass_name) override
{
/* TODO: eventually this should get cached on the RenderResult itself when
@ -224,6 +259,10 @@ class Context : public realtime_compositor::Context {
void output_to_render_result()
{
if (!output_texture_) {
return;
}
Render *re = RE_GetSceneRender(&scene_);
RenderResult *rr = RE_AcquireResultWrite(re);
@ -253,6 +292,55 @@ class Context : public realtime_compositor::Context {
BKE_image_signal(G.main, image, nullptr, IMA_SIGNAL_FREE);
BLI_thread_unlock(LOCK_DRAW_IMAGE);
}
void viewer_output_to_viewer_image()
{
if (!viewer_output_texture_) {
return;
}
Image *image = BKE_image_ensure_viewer(G.main, IMA_TYPE_COMPOSITE, "Viewer Node");
ImageUser image_user = {0};
image_user.multi_index = BKE_scene_multiview_view_id_get(&render_data_, view_name_);
if (BKE_scene_multiview_is_render_view_first(&render_data_, view_name_)) {
BKE_image_ensure_viewer_views(&render_data_, image, &image_user);
}
BLI_thread_lock(LOCK_DRAW_IMAGE);
void *lock;
ImBuf *image_buffer = BKE_image_acquire_ibuf(image, &image_user, &lock);
const int2 render_size = get_render_size();
if (image_buffer->x != render_size.x || image_buffer->y != render_size.y) {
imb_freerectImBuf(image_buffer);
imb_freerectfloatImBuf(image_buffer);
IMB_freezbuffloatImBuf(image_buffer);
image_buffer->x = render_size.x;
image_buffer->y = render_size.y;
imb_addrectfloatImBuf(image_buffer, 4);
image_buffer->userflags |= IB_DISPLAY_BUFFER_INVALID;
}
BKE_image_release_ibuf(image, image_buffer, lock);
BLI_thread_unlock(LOCK_DRAW_IMAGE);
GPU_memory_barrier(GPU_BARRIER_TEXTURE_UPDATE);
float *output_buffer = (float *)GPU_texture_read(viewer_output_texture_, GPU_DATA_FLOAT, 0);
std::memcpy(image_buffer->float_buffer.data,
output_buffer,
render_size.x * render_size.y * 4 * sizeof(float));
MEM_freeN(output_buffer);
BKE_image_partial_update_mark_full_update(image);
if (node_tree_.runtime->update_draw) {
node_tree_.runtime->update_draw(node_tree_.runtime->udh);
}
}
};
/* Render Realtime Compositor */
@ -289,6 +377,7 @@ void RealtimeCompositor::execute()
DRW_render_context_enable(&render_);
evaluator_->evaluate();
context_->output_to_render_result();
context_->viewer_output_to_viewer_image();
DRW_render_context_disable(&render_);
}

View File

@ -26,7 +26,6 @@ extern "C" {
#endif
struct ARegion;
struct AssetHandle;
struct GHashIterator;
struct GPUViewport;
struct ID;
@ -1444,8 +1443,7 @@ bool WM_drag_is_ID_type(const struct wmDrag *drag, int idcode);
/**
* \note Does not store \a asset in any way, so it's fine to pass a temporary.
*/
wmDragAsset *WM_drag_create_asset_data(const struct AssetHandle *asset,
const char *path,
wmDragAsset *WM_drag_create_asset_data(const struct AssetRepresentation *asset,
int /* #eAssetImportMethod */ import_type);
struct wmDragAsset *WM_drag_get_asset_data(const struct wmDrag *drag, int idcode);
struct AssetMetaData *WM_drag_get_asset_meta_data(const struct wmDrag *drag, int idcode);
@ -1475,7 +1473,7 @@ struct wmDragAssetCatalog *WM_drag_get_asset_catalog_data(const struct wmDrag *d
/**
* \note Does not store \a asset in any way, so it's fine to pass a temporary.
*/
void WM_drag_add_asset_list_item(wmDrag *drag, const struct AssetHandle *asset);
void WM_drag_add_asset_list_item(wmDrag *drag, const struct AssetRepresentation *asset);
const ListBase *WM_drag_asset_list_get(const wmDrag *drag);
const char *WM_drag_get_item_name(struct wmDrag *drag);

View File

@ -1095,16 +1095,8 @@ typedef struct wmDragID {
} wmDragID;
typedef struct wmDragAsset {
/* NOTE: Can't store the #AssetHandle here, since the #FileDirEntry it wraps may be freed while
* dragging. So store necessary data here directly. */
char name[64]; /* MAX_NAME */
/* Always freed. */
const char *path;
int id_type;
struct AssetMetaData *metadata;
int import_method; /* eAssetImportType */
bool use_relative_path;
const struct AssetRepresentation *asset;
/* FIXME: This is temporary evil solution to get scene/view-layer/etc in the copy callback of the
* #wmDropBox.

View File

@ -10,6 +10,9 @@
#include <cstring>
#include "AS_asset_representation.h"
#include "AS_asset_representation.hh"
#include "DNA_asset_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
@ -212,7 +215,7 @@ wmDrag *WM_drag_data_create(
LISTBASE_FOREACH (const CollectionPointerLink *, link, &asset_file_links) {
const FileDirEntry *asset_file = static_cast<const FileDirEntry *>(link->ptr.data);
const AssetHandle asset_handle = {asset_file};
WM_drag_add_asset_list_item(drag, &asset_handle);
WM_drag_add_asset_list_item(drag, ED_asset_handle_get_representation(&asset_handle));
}
BLI_freelistN(&asset_file_links);
break;
@ -566,23 +569,18 @@ bool WM_drag_is_ID_type(const wmDrag *drag, int idcode)
return WM_drag_get_local_ID(drag, idcode) || WM_drag_get_asset_data(drag, idcode);
}
wmDragAsset *WM_drag_create_asset_data(const AssetHandle *asset, const char *path, int import_type)
wmDragAsset *WM_drag_create_asset_data(const AssetRepresentation *asset, int import_type)
{
wmDragAsset *asset_drag = MEM_new<wmDragAsset>(__func__);
STRNCPY(asset_drag->name, ED_asset_handle_get_name(asset));
asset_drag->metadata = ED_asset_handle_get_metadata(asset);
asset_drag->path = path;
asset_drag->id_type = ED_asset_handle_get_id_type(asset);
asset_drag->asset = asset;
asset_drag->import_method = import_type;
asset_drag->use_relative_path = ED_asset_handle_get_use_relative_path(asset);
return asset_drag;
}
static void wm_drag_free_asset_data(wmDragAsset **asset_data)
{
MEM_freeN((char *)(*asset_data)->path);
MEM_SAFE_FREE(*asset_data);
}
@ -593,14 +591,15 @@ wmDragAsset *WM_drag_get_asset_data(const wmDrag *drag, int idcode)
}
wmDragAsset *asset_drag = static_cast<wmDragAsset *>(drag->poin);
return ELEM(idcode, 0, asset_drag->id_type) ? asset_drag : nullptr;
ID_Type asset_idcode = AS_asset_representation_id_type_get(asset_drag->asset);
return ELEM(idcode, 0, asset_idcode) ? asset_drag : nullptr;
}
AssetMetaData *WM_drag_get_asset_meta_data(const wmDrag *drag, int idcode)
{
wmDragAsset *drag_asset = WM_drag_get_asset_data(drag, idcode);
if (drag_asset) {
return drag_asset->metadata;
return AS_asset_representation_metadata_get(drag_asset->asset);
}
ID *local_id = WM_drag_get_local_ID(drag, idcode);
@ -618,8 +617,10 @@ ID *WM_drag_asset_id_import(wmDragAsset *asset_drag, const int flag_extra)
eFileSel_Params_Flag flag = static_cast<eFileSel_Params_Flag>(flag_extra) |
FILE_ACTIVE_COLLECTION;
const char *name = asset_drag->name;
ID_Type idtype = static_cast<ID_Type>(asset_drag->id_type);
const char *name = AS_asset_representation_name_get(asset_drag->asset);
const std::string blend_path = AS_asset_representation_full_library_path_get(asset_drag->asset);
const ID_Type idtype = AS_asset_representation_id_type_get(asset_drag->asset);
const bool use_relative_path = AS_asset_representation_use_relative_path_get(asset_drag->asset);
/* FIXME: Link/Append should happens in the operator called at the end of drop process, not from
* here. */
@ -629,15 +630,13 @@ ID *WM_drag_asset_id_import(wmDragAsset *asset_drag, const int flag_extra)
ViewLayer *view_layer = CTX_data_view_layer(asset_drag->evil_C);
View3D *view3d = CTX_wm_view3d(asset_drag->evil_C);
const bool use_relative_path = asset_drag->use_relative_path;
switch (eAssetImportMethod(asset_drag->import_method)) {
case ASSET_IMPORT_LINK:
return WM_file_link_datablock(bmain,
scene,
view_layer,
view3d,
asset_drag->path,
blend_path.c_str(),
idtype,
name,
flag | (use_relative_path ? FILE_RELPATH : 0));
@ -646,7 +645,7 @@ ID *WM_drag_asset_id_import(wmDragAsset *asset_drag, const int flag_extra)
scene,
view_layer,
view3d,
asset_drag->path,
blend_path.c_str(),
idtype,
name,
flag | BLO_LIBLINK_APPEND_RECURSIVE |
@ -657,7 +656,7 @@ ID *WM_drag_asset_id_import(wmDragAsset *asset_drag, const int flag_extra)
scene,
view_layer,
view3d,
asset_drag->path,
blend_path.c_str(),
idtype,
name,
flag | BLO_LIBLINK_APPEND_RECURSIVE | BLO_LIBLINK_APPEND_ASSET_DATA_CLEAR |
@ -708,10 +707,11 @@ void WM_drag_free_imported_drag_ID(Main *bmain, wmDrag *drag, wmDropBox *drop)
return;
}
ID_Type asset_id_type = AS_asset_representation_id_type_get(asset_drag->asset);
/* Try to find the imported ID. For this to work either a "session_uuid" or "name" property must
* have been defined (see #WM_operator_properties_id_lookup()). */
ID *id = WM_operator_properties_id_lookup_from_name_or_session_uuid(
bmain, drop->ptr, static_cast<ID_Type>(asset_drag->id_type));
bmain, drop->ptr, asset_id_type);
if (id != nullptr) {
/* Do not delete the dragged ID if it has any user, otherwise if it is a 're-used' ID it will
* cause #95636. Note that we need first to add the user that we want to remove in
@ -730,7 +730,7 @@ wmDragAssetCatalog *WM_drag_get_asset_catalog_data(const wmDrag *drag)
return static_cast<wmDragAssetCatalog *>(drag->poin);
}
void WM_drag_add_asset_list_item(wmDrag *drag, const AssetHandle *asset)
void WM_drag_add_asset_list_item(wmDrag *drag, const AssetRepresentation *asset)
{
BLI_assert(drag->type == WM_DRAG_ASSET_LIST);
@ -738,17 +738,14 @@ void WM_drag_add_asset_list_item(wmDrag *drag, const AssetHandle *asset)
/* Add to list. */
wmDragAssetListItem *drag_asset = MEM_cnew<wmDragAssetListItem>(__func__);
ID *local_id = ED_asset_handle_get_local_id(asset);
ID *local_id = AS_asset_representation_local_id_get(asset);
if (local_id) {
drag_asset->is_external = false;
drag_asset->asset_data.local_id = local_id;
}
else {
char asset_blend_path[FILE_MAX_LIBEXTRA];
ED_asset_handle_get_full_library_path(asset, asset_blend_path);
drag_asset->is_external = true;
drag_asset->asset_data.external_info = WM_drag_create_asset_data(
asset, BLI_strdup(asset_blend_path), ASSET_IMPORT_APPEND);
drag_asset->asset_data.external_info = WM_drag_create_asset_data(asset, ASSET_IMPORT_APPEND);
}
BLI_addtail(&drag->asset_items, drag_asset);
}
@ -844,7 +841,7 @@ const char *WM_drag_get_item_name(wmDrag *drag)
}
case WM_DRAG_ASSET: {
const wmDragAsset *asset_drag = WM_drag_get_asset_data(drag, 0);
return asset_drag->name;
return AS_asset_representation_name_get(asset_drag->asset);
}
case WM_DRAG_PATH: {
const wmDragPath *path_drag_data = static_cast<const wmDragPath *>(drag->poin);