Merge remote-tracking branch 'origin/master' into sculpt-dev
Also fixed a bug with eevee and color attributes.
This commit is contained in:
commit
cd316eb6c6
|
@ -13,9 +13,11 @@ CCL_NAMESPACE_BEGIN
|
|||
|
||||
BlenderImageLoader::BlenderImageLoader(BL::Image b_image,
|
||||
const int frame,
|
||||
const int tile_number,
|
||||
const bool is_preview_render)
|
||||
: b_image(b_image),
|
||||
frame(frame),
|
||||
tile_number(tile_number),
|
||||
/* Don't free cache for preview render to avoid race condition from T93560, to be fixed
|
||||
properly later as we are close to release. */
|
||||
free_cache(!is_preview_render && !b_image.has_data())
|
||||
|
@ -66,12 +68,11 @@ bool BlenderImageLoader::load_pixels(const ImageMetaData &metadata,
|
|||
{
|
||||
const size_t num_pixels = ((size_t)metadata.width) * metadata.height;
|
||||
const int channels = metadata.channels;
|
||||
const int tile = 0; /* TODO(lukas): Support tiles here? */
|
||||
|
||||
if (b_image.is_float()) {
|
||||
/* image data */
|
||||
float *image_pixels;
|
||||
image_pixels = image_get_float_pixels_for_frame(b_image, frame, tile);
|
||||
image_pixels = image_get_float_pixels_for_frame(b_image, frame, tile_number);
|
||||
|
||||
if (image_pixels && num_pixels * channels == pixels_size) {
|
||||
memcpy(pixels, image_pixels, pixels_size * sizeof(float));
|
||||
|
@ -99,7 +100,7 @@ bool BlenderImageLoader::load_pixels(const ImageMetaData &metadata,
|
|||
}
|
||||
}
|
||||
else {
|
||||
unsigned char *image_pixels = image_get_pixels_for_frame(b_image, frame, tile);
|
||||
unsigned char *image_pixels = image_get_pixels_for_frame(b_image, frame, tile_number);
|
||||
|
||||
if (image_pixels && num_pixels * channels == pixels_size) {
|
||||
memcpy(pixels, image_pixels, pixels_size * sizeof(unsigned char));
|
||||
|
@ -153,7 +154,13 @@ string BlenderImageLoader::name() const
|
|||
bool BlenderImageLoader::equals(const ImageLoader &other) const
|
||||
{
|
||||
const BlenderImageLoader &other_loader = (const BlenderImageLoader &)other;
|
||||
return b_image == other_loader.b_image && frame == other_loader.frame;
|
||||
return b_image == other_loader.b_image && frame == other_loader.frame &&
|
||||
tile_number == other_loader.tile_number;
|
||||
}
|
||||
|
||||
int BlenderImageLoader::get_tile_number() const
|
||||
{
|
||||
return tile_number;
|
||||
}
|
||||
|
||||
/* Point Density */
|
||||
|
|
|
@ -12,7 +12,10 @@ CCL_NAMESPACE_BEGIN
|
|||
|
||||
class BlenderImageLoader : public ImageLoader {
|
||||
public:
|
||||
BlenderImageLoader(BL::Image b_image, const int frame, const bool is_preview_render);
|
||||
BlenderImageLoader(BL::Image b_image,
|
||||
const int frame,
|
||||
const int tile_number,
|
||||
const bool is_preview_render);
|
||||
|
||||
bool load_metadata(const ImageDeviceFeatures &features, ImageMetaData &metadata) override;
|
||||
bool load_pixels(const ImageMetaData &metadata,
|
||||
|
@ -22,8 +25,11 @@ class BlenderImageLoader : public ImageLoader {
|
|||
string name() const override;
|
||||
bool equals(const ImageLoader &other) const override;
|
||||
|
||||
int get_tile_number() const override;
|
||||
|
||||
BL::Image b_image;
|
||||
int frame;
|
||||
int tile_number;
|
||||
bool free_cache;
|
||||
};
|
||||
|
||||
|
|
|
@ -776,9 +776,21 @@ static ShaderNode *add_node(Scene *scene,
|
|||
*/
|
||||
int scene_frame = b_scene.frame_current();
|
||||
int image_frame = image_user_frame_number(b_image_user, b_image, scene_frame);
|
||||
image->handle = scene->image_manager->add_image(
|
||||
new BlenderImageLoader(b_image, image_frame, b_engine.is_preview()),
|
||||
image->image_params());
|
||||
if (b_image.source() != BL::Image::source_TILED) {
|
||||
image->handle = scene->image_manager->add_image(
|
||||
new BlenderImageLoader(b_image, image_frame, 0, b_engine.is_preview()),
|
||||
image->image_params());
|
||||
}
|
||||
else {
|
||||
vector<ImageLoader *> loaders;
|
||||
loaders.reserve(image->get_tiles().size());
|
||||
for (int tile_number : image->get_tiles()) {
|
||||
loaders.push_back(
|
||||
new BlenderImageLoader(b_image, image_frame, tile_number, b_engine.is_preview()));
|
||||
}
|
||||
|
||||
image->handle = scene->image_manager->add_image(loaders, image->image_params());
|
||||
}
|
||||
}
|
||||
else {
|
||||
ustring filename = ustring(
|
||||
|
@ -814,7 +826,7 @@ static ShaderNode *add_node(Scene *scene,
|
|||
int scene_frame = b_scene.frame_current();
|
||||
int image_frame = image_user_frame_number(b_image_user, b_image, scene_frame);
|
||||
env->handle = scene->image_manager->add_image(
|
||||
new BlenderImageLoader(b_image, image_frame, b_engine.is_preview()),
|
||||
new BlenderImageLoader(b_image, image_frame, 0, b_engine.is_preview()),
|
||||
env->image_params());
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -1304,8 +1304,38 @@ bool OSLRenderServices::texture(ustring filename,
|
|||
break;
|
||||
}
|
||||
case OSLTextureHandle::SVM: {
|
||||
/* Packed texture. */
|
||||
float4 rgba = kernel_tex_image_interp(kernel_globals, handle->svm_slot, s, 1.0f - t);
|
||||
int id = -1;
|
||||
if (handle->svm_slots[0].w == -1) {
|
||||
/* Packed single texture. */
|
||||
id = handle->svm_slots[0].y;
|
||||
}
|
||||
else {
|
||||
/* Packed tiled texture. */
|
||||
int tx = (int)s;
|
||||
int ty = (int)t;
|
||||
int tile = 1001 + 10 * ty + tx;
|
||||
for (int4 tile_node : handle->svm_slots) {
|
||||
if (tile_node.x == tile) {
|
||||
id = tile_node.y;
|
||||
break;
|
||||
}
|
||||
if (tile_node.z == tile) {
|
||||
id = tile_node.w;
|
||||
break;
|
||||
}
|
||||
}
|
||||
s -= tx;
|
||||
t -= ty;
|
||||
}
|
||||
|
||||
float4 rgba;
|
||||
if (id == -1) {
|
||||
rgba = make_float4(
|
||||
TEX_IMAGE_MISSING_R, TEX_IMAGE_MISSING_G, TEX_IMAGE_MISSING_B, TEX_IMAGE_MISSING_A);
|
||||
}
|
||||
else {
|
||||
rgba = kernel_tex_image_interp(kernel_globals, id, s, 1.0f - t);
|
||||
}
|
||||
|
||||
result[0] = rgba[0];
|
||||
if (nchannels > 1)
|
||||
|
@ -1319,7 +1349,7 @@ bool OSLRenderServices::texture(ustring filename,
|
|||
}
|
||||
case OSLTextureHandle::IES: {
|
||||
/* IES light. */
|
||||
result[0] = kernel_ies_interp(kernel_globals, handle->svm_slot, s, t);
|
||||
result[0] = kernel_ies_interp(kernel_globals, handle->svm_slots[0].y, s, t);
|
||||
status = true;
|
||||
break;
|
||||
}
|
||||
|
@ -1413,7 +1443,7 @@ bool OSLRenderServices::texture3d(ustring filename,
|
|||
/* Packed texture. */
|
||||
ShaderData *sd = (ShaderData *)(sg->renderstate);
|
||||
KernelGlobals kernel_globals = sd->osl_globals;
|
||||
int slot = handle->svm_slot;
|
||||
int slot = handle->svm_slots[0].y;
|
||||
float3 P_float3 = make_float3(P.x, P.y, P.z);
|
||||
float4 rgba = kernel_tex_image_interp_3d(kernel_globals, slot, P_float3, INTERPOLATION_NONE);
|
||||
|
||||
|
|
|
@ -39,18 +39,26 @@ struct KernelGlobalsCPU;
|
|||
* with additional data.
|
||||
*
|
||||
* These are stored in a concurrent hash map, because OSL can compile multiple
|
||||
* shaders in parallel. */
|
||||
* shaders in parallel.
|
||||
*
|
||||
* Note: The svm_slots array contains a compressed mapping of tile to svm_slot pairs
|
||||
* stored as follows: x:tile_a, y:svm_slot_a, z:tile_b, w:svm_slot_b etc. */
|
||||
|
||||
struct OSLTextureHandle : public OIIO::RefCnt {
|
||||
enum Type { OIIO, SVM, IES, BEVEL, AO };
|
||||
|
||||
OSLTextureHandle(Type type, const vector<int4> &svm_slots)
|
||||
: type(type), svm_slots(svm_slots), oiio_handle(NULL), processor(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
OSLTextureHandle(Type type = OIIO, int svm_slot = -1)
|
||||
: type(type), svm_slot(svm_slot), oiio_handle(NULL), processor(NULL)
|
||||
: OSLTextureHandle(type, {make_int4(0, svm_slot, -1, -1)})
|
||||
{
|
||||
}
|
||||
|
||||
Type type;
|
||||
int svm_slot;
|
||||
vector<int4> svm_slots;
|
||||
OSL::TextureSystem::TextureHandle *oiio_handle;
|
||||
ColorSpaceProcessor *processor;
|
||||
};
|
||||
|
|
|
@ -117,12 +117,12 @@ void ImageHandle::clear()
|
|||
manager = NULL;
|
||||
}
|
||||
|
||||
bool ImageHandle::empty()
|
||||
bool ImageHandle::empty() const
|
||||
{
|
||||
return tile_slots.empty();
|
||||
}
|
||||
|
||||
int ImageHandle::num_tiles()
|
||||
int ImageHandle::num_tiles() const
|
||||
{
|
||||
return tile_slots.size();
|
||||
}
|
||||
|
@ -154,6 +154,35 @@ int ImageHandle::svm_slot(const int tile_index) const
|
|||
return tile_slots[tile_index];
|
||||
}
|
||||
|
||||
vector<int4> ImageHandle::get_svm_slots() const
|
||||
{
|
||||
const size_t num_nodes = divide_up(tile_slots.size(), 2);
|
||||
|
||||
vector<int4> svm_slots;
|
||||
svm_slots.reserve(num_nodes);
|
||||
for (size_t i = 0; i < num_nodes; i++) {
|
||||
int4 node;
|
||||
|
||||
int slot = tile_slots[2 * i];
|
||||
node.x = manager->images[slot]->loader->get_tile_number();
|
||||
node.y = slot;
|
||||
|
||||
if ((2 * i + 1) < tile_slots.size()) {
|
||||
slot = tile_slots[2 * i + 1];
|
||||
node.z = manager->images[slot]->loader->get_tile_number();
|
||||
node.w = slot;
|
||||
}
|
||||
else {
|
||||
node.z = -1;
|
||||
node.w = -1;
|
||||
}
|
||||
|
||||
svm_slots.push_back(node);
|
||||
}
|
||||
|
||||
return svm_slots;
|
||||
}
|
||||
|
||||
device_texture *ImageHandle::image_memory(const int tile_index) const
|
||||
{
|
||||
if (tile_index >= tile_slots.size()) {
|
||||
|
@ -266,6 +295,11 @@ ustring ImageLoader::osl_filepath() const
|
|||
return ustring();
|
||||
}
|
||||
|
||||
int ImageLoader::get_tile_number() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ImageLoader::equals(const ImageLoader *a, const ImageLoader *b)
|
||||
{
|
||||
if (a == NULL && b == NULL) {
|
||||
|
@ -397,6 +431,19 @@ ImageHandle ImageManager::add_image(ImageLoader *loader,
|
|||
return handle;
|
||||
}
|
||||
|
||||
ImageHandle ImageManager::add_image(const vector<ImageLoader *> &loaders,
|
||||
const ImageParams ¶ms)
|
||||
{
|
||||
ImageHandle handle;
|
||||
for (ImageLoader *loader : loaders) {
|
||||
const int slot = add_image_slot(loader, params, true);
|
||||
handle.tile_slots.push_back(slot);
|
||||
}
|
||||
|
||||
handle.manager = this;
|
||||
return handle;
|
||||
}
|
||||
|
||||
int ImageManager::add_image_slot(ImageLoader *loader,
|
||||
const ImageParams ¶ms,
|
||||
const bool builtin)
|
||||
|
|
|
@ -112,6 +112,9 @@ class ImageLoader {
|
|||
/* Optional for OSL texture cache. */
|
||||
virtual ustring osl_filepath() const;
|
||||
|
||||
/* Optional for tiled textures loaded externally. */
|
||||
virtual int get_tile_number() const;
|
||||
|
||||
/* Free any memory used for loading metadata and pixels. */
|
||||
virtual void cleanup(){};
|
||||
|
||||
|
@ -139,11 +142,12 @@ class ImageHandle {
|
|||
|
||||
void clear();
|
||||
|
||||
bool empty();
|
||||
int num_tiles();
|
||||
bool empty() const;
|
||||
int num_tiles() const;
|
||||
|
||||
ImageMetaData metadata();
|
||||
int svm_slot(const int tile_index = 0) const;
|
||||
vector<int4> get_svm_slots() const;
|
||||
device_texture *image_memory(const int tile_index = 0) const;
|
||||
|
||||
VDBImageLoader *vdb_loader(const int tile_index = 0) const;
|
||||
|
@ -169,6 +173,7 @@ class ImageManager {
|
|||
const ImageParams ¶ms,
|
||||
const array<int> &tiles);
|
||||
ImageHandle add_image(ImageLoader *loader, const ImageParams ¶ms, const bool builtin = true);
|
||||
ImageHandle add_image(const vector<ImageLoader *> &loaders, const ImageParams ¶ms);
|
||||
|
||||
void device_update(Device *device, Scene *scene, Progress &progress);
|
||||
void device_update_slot(Device *device, Scene *scene, int slot, Progress *progress);
|
||||
|
|
|
@ -1211,14 +1211,15 @@ void OSLCompiler::parameter_texture(const char *name, ustring filename, ustring
|
|||
parameter(name, filename);
|
||||
}
|
||||
|
||||
void OSLCompiler::parameter_texture(const char *name, int svm_slot)
|
||||
void OSLCompiler::parameter_texture(const char *name, const ImageHandle &handle)
|
||||
{
|
||||
/* Texture loaded through SVM image texture system. We generate a unique
|
||||
* name, which ends up being used in OSLRenderServices::get_texture_handle
|
||||
* to get handle again. Note that this name must be unique between multiple
|
||||
* render sessions as the render services are shared. */
|
||||
ustring filename(string_printf("@svm%d", texture_shared_unique_id++).c_str());
|
||||
services->textures.insert(filename, new OSLTextureHandle(OSLTextureHandle::SVM, svm_slot));
|
||||
services->textures.insert(filename,
|
||||
new OSLTextureHandle(OSLTextureHandle::SVM, handle.get_svm_slots()));
|
||||
parameter(name, filename);
|
||||
}
|
||||
|
||||
|
@ -1290,7 +1291,7 @@ void OSLCompiler::parameter_texture(const char * /* name */,
|
|||
{
|
||||
}
|
||||
|
||||
void OSLCompiler::parameter_texture(const char * /* name */, int /* svm_slot */)
|
||||
void OSLCompiler::parameter_texture(const char * /* name */, const ImageHandle & /*handle*/)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -147,7 +147,7 @@ class OSLCompiler {
|
|||
void parameter_attribute(const char *name, ustring s);
|
||||
|
||||
void parameter_texture(const char *name, ustring filename, ustring colorspace);
|
||||
void parameter_texture(const char *name, int svm_slot);
|
||||
void parameter_texture(const char *name, const ImageHandle &handle);
|
||||
void parameter_texture_ies(const char *name, int svm_slot);
|
||||
|
||||
ShaderType output_type()
|
||||
|
|
|
@ -453,14 +453,15 @@ void ImageTextureNode::compile(OSLCompiler &compiler)
|
|||
"filename", filename, compress_as_srgb ? u_colorspace_raw : known_colorspace);
|
||||
}
|
||||
else {
|
||||
compiler.parameter_texture("filename", handle.svm_slot());
|
||||
compiler.parameter_texture("filename", handle);
|
||||
}
|
||||
|
||||
const bool unassociate_alpha = !(ColorSpaceManager::colorspace_is_data(colorspace) ||
|
||||
alpha_type == IMAGE_ALPHA_CHANNEL_PACKED ||
|
||||
alpha_type == IMAGE_ALPHA_IGNORE);
|
||||
const bool is_tiled = (filename.find("<UDIM>") != string::npos ||
|
||||
filename.find("<UVTILE>") != string::npos);
|
||||
filename.find("<UVTILE>") != string::npos) ||
|
||||
handle.num_tiles() > 1;
|
||||
|
||||
compiler.parameter(this, "projection");
|
||||
compiler.parameter(this, "projection_blend");
|
||||
|
@ -605,7 +606,7 @@ void EnvironmentTextureNode::compile(OSLCompiler &compiler)
|
|||
"filename", filename, compress_as_srgb ? u_colorspace_raw : known_colorspace);
|
||||
}
|
||||
else {
|
||||
compiler.parameter_texture("filename", handle.svm_slot());
|
||||
compiler.parameter_texture("filename", handle);
|
||||
}
|
||||
|
||||
compiler.parameter(this, "projection");
|
||||
|
@ -960,7 +961,7 @@ void SkyTextureNode::compile(OSLCompiler &compiler)
|
|||
compiler.parameter_array("nishita_data", sunsky.nishita_data, 10);
|
||||
/* nishita texture */
|
||||
if (sky_type == NODE_SKY_NISHITA) {
|
||||
compiler.parameter_texture("filename", handle.svm_slot());
|
||||
compiler.parameter_texture("filename", handle);
|
||||
}
|
||||
compiler.add(this, "node_sky_texture");
|
||||
}
|
||||
|
@ -1855,7 +1856,7 @@ void PointDensityTextureNode::compile(OSLCompiler &compiler)
|
|||
handle = image_manager->add_image(filename.string(), image_params());
|
||||
}
|
||||
|
||||
compiler.parameter_texture("filename", handle.svm_slot());
|
||||
compiler.parameter_texture("filename", handle);
|
||||
if (space == NODE_TEX_VOXEL_SPACE_WORLD) {
|
||||
compiler.parameter("mapping", tfm);
|
||||
compiler.parameter("use_mapping", 1);
|
||||
|
|
|
@ -203,7 +203,7 @@ class DATA_PT_geometry_curve_start_end(CurveButtonsPanelCurve, Panel):
|
|||
@classmethod
|
||||
def poll(cls, context):
|
||||
# Text objects don't support these properties
|
||||
return (type(context.curve) in {Curve})
|
||||
return (type(context.curve) == Curve)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
|
|
@ -389,7 +389,8 @@ class _draw_tool_settings_context_mode:
|
|||
"strength",
|
||||
pressure_name="use_pressure_strength",
|
||||
unified_name="use_unified_strength",
|
||||
header=True)
|
||||
header=True
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
@ -537,16 +538,16 @@ class _draw_tool_settings_context_mode:
|
|||
return False
|
||||
|
||||
UnifiedPaintPanel.prop_unified(
|
||||
layout,
|
||||
context,
|
||||
brush,
|
||||
"size",
|
||||
unified_name="use_unified_size",
|
||||
pressure_name="use_pressure_size",
|
||||
text="Radius",
|
||||
slider=True,
|
||||
header=True
|
||||
)
|
||||
layout,
|
||||
context,
|
||||
brush,
|
||||
"size",
|
||||
unified_name="use_unified_size",
|
||||
pressure_name="use_pressure_size",
|
||||
text="Radius",
|
||||
slider=True,
|
||||
header=True,
|
||||
)
|
||||
|
||||
if brush.curves_sculpt_tool not in {'ADD', 'DELETE'}:
|
||||
UnifiedPaintPanel.prop_unified(
|
||||
|
@ -556,7 +557,7 @@ class _draw_tool_settings_context_mode:
|
|||
"strength",
|
||||
unified_name="use_unified_strength",
|
||||
pressure_name="use_pressure_strength",
|
||||
header=True
|
||||
header=True,
|
||||
)
|
||||
|
||||
if brush.curves_sculpt_tool == 'COMB':
|
||||
|
@ -569,7 +570,6 @@ class _draw_tool_settings_context_mode:
|
|||
layout.popover("VIEW3D_PT_curves_sculpt_add_shape", text="Curve Shape")
|
||||
layout.prop(brush, "use_frontface", text="Front Faces Only")
|
||||
|
||||
|
||||
if brush.curves_sculpt_tool == 'GROW_SHRINK':
|
||||
layout.prop(brush, "direction", expand=True, text="")
|
||||
layout.prop(brush, "falloff_shape", expand=True)
|
||||
|
|
|
@ -454,7 +454,7 @@ bool BKE_image_is_dirty_writable(struct Image *image, bool *r_is_writable);
|
|||
int BKE_image_sequence_guess_offset(struct Image *image);
|
||||
bool BKE_image_has_anim(struct Image *image);
|
||||
bool BKE_image_has_packedfile(const struct Image *image);
|
||||
bool BKE_image_has_filepath(struct Image *ima);
|
||||
bool BKE_image_has_filepath(const struct Image *ima);
|
||||
/**
|
||||
* Checks the image buffer changes with time (not keyframed values).
|
||||
*/
|
||||
|
|
|
@ -721,6 +721,9 @@ static void copy_image_packedfiles(ListBase *lb_dst, const ListBase *lb_src)
|
|||
imapf_src = imapf_src->next) {
|
||||
ImagePackedFile *imapf_dst = static_cast<ImagePackedFile *>(
|
||||
MEM_mallocN(sizeof(ImagePackedFile), "Image Packed Files (copy)"));
|
||||
|
||||
imapf_dst->view = imapf_src->view;
|
||||
imapf_dst->tile_number = imapf_src->tile_number;
|
||||
STRNCPY(imapf_dst->filepath, imapf_src->filepath);
|
||||
|
||||
if (imapf_src->packedfile) {
|
||||
|
@ -1197,7 +1200,8 @@ Image *BKE_image_add_from_imbuf(Main *bmain, ImBuf *ibuf, const char *name)
|
|||
}
|
||||
|
||||
/** Pack image buffer to memory as PNG or EXR. */
|
||||
static bool image_memorypack_imbuf(Image *ima, ImBuf *ibuf, const char *filepath)
|
||||
static bool image_memorypack_imbuf(
|
||||
Image *ima, ImBuf *ibuf, int view, int tile_number, const char *filepath)
|
||||
{
|
||||
ibuf->ftype = (ibuf->rect_float) ? IMB_FTYPE_OPENEXR : IMB_FTYPE_PNG;
|
||||
|
||||
|
@ -1219,6 +1223,8 @@ static bool image_memorypack_imbuf(Image *ima, ImBuf *ibuf, const char *filepath
|
|||
imapf = static_cast<ImagePackedFile *>(MEM_mallocN(sizeof(ImagePackedFile), "Image PackedFile"));
|
||||
STRNCPY(imapf->filepath, filepath);
|
||||
imapf->packedfile = pf;
|
||||
imapf->view = view;
|
||||
imapf->tile_number = tile_number;
|
||||
BLI_addtail(&ima->packedfiles, imapf);
|
||||
|
||||
ibuf->encodedbuffer = nullptr;
|
||||
|
@ -1234,42 +1240,47 @@ bool BKE_image_memorypack(Image *ima)
|
|||
|
||||
image_free_packedfiles(ima);
|
||||
|
||||
if (BKE_image_is_multiview(ima)) {
|
||||
/* Store each view as a separate packed files with R_IMF_VIEWS_INDIVIDUAL. */
|
||||
ImageView *iv;
|
||||
int i;
|
||||
const int tot_viewfiles = image_num_viewfiles(ima);
|
||||
const bool is_tiled = (ima->source == IMA_SRC_TILED);
|
||||
const bool is_multiview = BKE_image_is_multiview(ima);
|
||||
|
||||
for (i = 0, iv = static_cast<ImageView *>(ima->views.first); iv;
|
||||
iv = static_cast<ImageView *>(iv->next), i++) {
|
||||
ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, i, 0, nullptr);
|
||||
ImageUser iuser{};
|
||||
BKE_imageuser_default(&iuser);
|
||||
char tiled_filepath[FILE_MAX];
|
||||
|
||||
for (int view = 0; view < tot_viewfiles; view++) {
|
||||
LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
|
||||
int index = (is_multiview || is_tiled) ? view : IMA_NO_INDEX;
|
||||
int entry = is_tiled ? tile->tile_number : 0;
|
||||
ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, index, entry, nullptr);
|
||||
if (!ibuf) {
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
|
||||
/* if the image was a R_IMF_VIEWS_STEREO_3D we force _L, _R suffices */
|
||||
if (ima->views_format == R_IMF_VIEWS_STEREO_3D) {
|
||||
const char *suffix[2] = {STEREO_LEFT_SUFFIX, STEREO_RIGHT_SUFFIX};
|
||||
BLI_path_suffix(iv->filepath, FILE_MAX, suffix[i], "");
|
||||
const char *filepath = ibuf->name;
|
||||
if (is_tiled) {
|
||||
iuser.tile = tile->tile_number;
|
||||
BKE_image_user_file_path(&iuser, ima, tiled_filepath);
|
||||
filepath = tiled_filepath;
|
||||
}
|
||||
else if (is_multiview) {
|
||||
ImageView *iv = static_cast<ImageView *>(BLI_findlink(&ima->views, view));
|
||||
/* if the image was a R_IMF_VIEWS_STEREO_3D we force _L, _R suffices */
|
||||
if (ima->views_format == R_IMF_VIEWS_STEREO_3D) {
|
||||
const char *suffix[2] = {STEREO_LEFT_SUFFIX, STEREO_RIGHT_SUFFIX};
|
||||
BLI_path_suffix(iv->filepath, FILE_MAX, suffix[view], "");
|
||||
}
|
||||
filepath = iv->filepath;
|
||||
}
|
||||
|
||||
ok = ok && image_memorypack_imbuf(ima, ibuf, iv->filepath);
|
||||
ok = ok && image_memorypack_imbuf(ima, ibuf, view, tile->tile_number, filepath);
|
||||
IMB_freeImBuf(ibuf);
|
||||
}
|
||||
|
||||
ima->views_format = R_IMF_VIEWS_INDIVIDUAL;
|
||||
}
|
||||
else {
|
||||
ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, IMA_NO_INDEX, 0, nullptr);
|
||||
|
||||
if (ibuf) {
|
||||
ok = ok && image_memorypack_imbuf(ima, ibuf, ibuf->name);
|
||||
IMB_freeImBuf(ibuf);
|
||||
}
|
||||
else {
|
||||
ok = false;
|
||||
}
|
||||
if (is_multiview) {
|
||||
ima->views_format = R_IMF_VIEWS_INDIVIDUAL;
|
||||
}
|
||||
|
||||
if (ok && ima->source == IMA_SRC_GENERATED) {
|
||||
|
@ -1284,27 +1295,24 @@ void BKE_image_packfiles(ReportList *reports, Image *ima, const char *basepath)
|
|||
{
|
||||
const int tot_viewfiles = image_num_viewfiles(ima);
|
||||
|
||||
if (tot_viewfiles == 1) {
|
||||
ImagePackedFile *imapf = static_cast<ImagePackedFile *>(
|
||||
MEM_mallocN(sizeof(ImagePackedFile), "Image packed file"));
|
||||
BLI_addtail(&ima->packedfiles, imapf);
|
||||
imapf->packedfile = BKE_packedfile_new(reports, ima->filepath, basepath);
|
||||
if (imapf->packedfile) {
|
||||
STRNCPY(imapf->filepath, ima->filepath);
|
||||
}
|
||||
else {
|
||||
BLI_freelinkN(&ima->packedfiles, imapf);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (ImageView *iv = static_cast<ImageView *>(ima->views.first); iv; iv = iv->next) {
|
||||
ImageUser iuser{};
|
||||
BKE_imageuser_default(&iuser);
|
||||
for (int view = 0; view < tot_viewfiles; view++) {
|
||||
iuser.view = view;
|
||||
LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
|
||||
iuser.tile = tile->tile_number;
|
||||
char filepath[FILE_MAX];
|
||||
BKE_image_user_file_path(&iuser, ima, filepath);
|
||||
|
||||
ImagePackedFile *imapf = static_cast<ImagePackedFile *>(
|
||||
MEM_mallocN(sizeof(ImagePackedFile), "Image packed file"));
|
||||
BLI_addtail(&ima->packedfiles, imapf);
|
||||
|
||||
imapf->packedfile = BKE_packedfile_new(reports, iv->filepath, basepath);
|
||||
imapf->packedfile = BKE_packedfile_new(reports, filepath, basepath);
|
||||
imapf->view = view;
|
||||
imapf->tile_number = tile->tile_number;
|
||||
if (imapf->packedfile) {
|
||||
STRNCPY(imapf->filepath, iv->filepath);
|
||||
STRNCPY(imapf->filepath, filepath);
|
||||
}
|
||||
else {
|
||||
BLI_freelinkN(&ima->packedfiles, imapf);
|
||||
|
@ -1323,11 +1331,16 @@ void BKE_image_packfiles_from_mem(ReportList *reports,
|
|||
if (tot_viewfiles != 1) {
|
||||
BKE_report(reports, RPT_ERROR, "Cannot pack multiview images from raw data currently...");
|
||||
}
|
||||
else if (ima->source == IMA_SRC_TILED) {
|
||||
BKE_report(reports, RPT_ERROR, "Cannot pack tiled images from raw data currently...");
|
||||
}
|
||||
else {
|
||||
ImagePackedFile *imapf = static_cast<ImagePackedFile *>(
|
||||
MEM_mallocN(sizeof(ImagePackedFile), __func__));
|
||||
BLI_addtail(&ima->packedfiles, imapf);
|
||||
imapf->packedfile = BKE_packedfile_new_from_memory(data, data_len);
|
||||
imapf->view = 0;
|
||||
imapf->tile_number = 1001;
|
||||
STRNCPY(imapf->filepath, ima->filepath);
|
||||
}
|
||||
}
|
||||
|
@ -2950,8 +2963,9 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
|
|||
/* try to repack file */
|
||||
if (BKE_image_has_packedfile(ima)) {
|
||||
const int tot_viewfiles = image_num_viewfiles(ima);
|
||||
const int tot_files = tot_viewfiles * BLI_listbase_count(&ima->tiles);
|
||||
|
||||
if (tot_viewfiles != BLI_listbase_count_at_most(&ima->packedfiles, tot_viewfiles + 1)) {
|
||||
if (tot_files != BLI_listbase_count_at_most(&ima->packedfiles, tot_files + 1)) {
|
||||
/* in case there are new available files to be loaded */
|
||||
image_free_packedfiles(ima);
|
||||
BKE_image_packfiles(nullptr, ima, ID_BLEND_PATH(bmain, &ima->id));
|
||||
|
@ -3926,18 +3940,23 @@ static ImBuf *load_image_single(Image *ima,
|
|||
int flag = IB_rect | IB_multilayer;
|
||||
|
||||
*r_cache_ibuf = true;
|
||||
const int tile_number = image_get_tile_number_from_iuser(ima, iuser);
|
||||
|
||||
/* is there a PackedFile with this image ? */
|
||||
if (has_packed && !is_sequence) {
|
||||
ImagePackedFile *imapf = static_cast<ImagePackedFile *>(
|
||||
BLI_findlink(&ima->packedfiles, view_id));
|
||||
if (imapf->packedfile) {
|
||||
flag |= imbuf_alpha_flags_for_image(ima);
|
||||
ibuf = IMB_ibImageFromMemory((unsigned char *)imapf->packedfile->data,
|
||||
imapf->packedfile->size,
|
||||
flag,
|
||||
ima->colorspace_settings.name,
|
||||
"<packed data>");
|
||||
flag |= imbuf_alpha_flags_for_image(ima);
|
||||
|
||||
LISTBASE_FOREACH (ImagePackedFile *, imapf, &ima->packedfiles) {
|
||||
if (imapf->view == view_id && imapf->tile_number == tile_number) {
|
||||
if (imapf->packedfile) {
|
||||
ibuf = IMB_ibImageFromMemory((unsigned char *)imapf->packedfile->data,
|
||||
imapf->packedfile->size,
|
||||
flag,
|
||||
ima->colorspace_settings.name,
|
||||
"<packed data>");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -3996,6 +4015,8 @@ static ImBuf *load_image_single(Image *ima,
|
|||
BLI_addtail(&ima->packedfiles, imapf);
|
||||
|
||||
STRNCPY(imapf->filepath, filepath);
|
||||
imapf->view = view_id;
|
||||
imapf->tile_number = tile_number;
|
||||
imapf->packedfile = BKE_packedfile_new(
|
||||
nullptr, filepath, ID_BLEND_PATH_FROM_GLOBAL(&ima->id));
|
||||
}
|
||||
|
@ -5103,7 +5124,7 @@ bool BKE_image_has_packedfile(const Image *ima)
|
|||
return (BLI_listbase_is_empty(&ima->packedfiles) == false);
|
||||
}
|
||||
|
||||
bool BKE_image_has_filepath(Image *ima)
|
||||
bool BKE_image_has_filepath(const Image *ima)
|
||||
{
|
||||
/* This could be improved to detect cases like //../../, currently path
|
||||
* remapping empty file paths empty. */
|
||||
|
|
|
@ -237,14 +237,14 @@ void BKE_packedfile_pack_all(Main *bmain, ReportList *reports, bool verbose)
|
|||
|
||||
for (ima = bmain->images.first; ima; ima = ima->id.next) {
|
||||
if (BKE_image_has_packedfile(ima) == false && !ID_IS_LINKED(ima)) {
|
||||
if (ima->source == IMA_SRC_FILE) {
|
||||
if (ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_TILED)) {
|
||||
BKE_image_packfiles(reports, ima, ID_BLEND_PATH(bmain, &ima->id));
|
||||
tot++;
|
||||
}
|
||||
else if (BKE_image_has_multiple_ibufs(ima) && verbose) {
|
||||
else if (ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE) && verbose) {
|
||||
BKE_reportf(reports,
|
||||
RPT_WARNING,
|
||||
"Image '%s' skipped, movies, image sequences and packed files not supported",
|
||||
"Image '%s' skipped, packing movies or image sequences not supported",
|
||||
ima->id.name + 2);
|
||||
}
|
||||
}
|
||||
|
@ -494,15 +494,22 @@ static void unpack_generate_paths(const char *name,
|
|||
|
||||
if (tempname[0] == '\0') {
|
||||
/* NOTE: we generally do not have any real way to re-create extension out of data. */
|
||||
BLI_strncpy(tempname, id->name + 2, sizeof(tempname));
|
||||
const size_t len = BLI_strncpy_rlen(tempname, id->name + 2, sizeof(tempname));
|
||||
printf("%s\n", tempname);
|
||||
|
||||
/* For images we can add the file extension based on the file magic. */
|
||||
/* For images ensure that the temporary filename contains tile number information as well as
|
||||
* a file extension based on the file magic. */
|
||||
if (id_type == ID_IM) {
|
||||
ImagePackedFile *imapf = ((Image *)id)->packedfiles.last;
|
||||
Image *ima = (Image *)id;
|
||||
ImagePackedFile *imapf = ima->packedfiles.last;
|
||||
if (imapf != NULL && imapf->packedfile != NULL) {
|
||||
const PackedFile *pf = imapf->packedfile;
|
||||
enum eImbFileType ftype = IMB_ispic_type_from_memory((const uchar *)pf->data, pf->size);
|
||||
if (ima->source == IMA_SRC_TILED) {
|
||||
char tile_number[6];
|
||||
BLI_snprintf(tile_number, sizeof(tile_number), ".%d", imapf->tile_number);
|
||||
BLI_strncpy(tempname + len, tile_number, sizeof(tempname) - len);
|
||||
}
|
||||
if (ftype != IMB_FTYPE_NONE) {
|
||||
const int imtype = BKE_ftype_to_imtype(ftype, NULL);
|
||||
BKE_image_path_ensure_ext_from_imtype(tempname, imtype);
|
||||
|
@ -639,6 +646,11 @@ int BKE_packedfile_unpack_image(Main *bmain,
|
|||
/* keep the new name in the image for non-pack specific reasons */
|
||||
if (how != PF_REMOVE) {
|
||||
BLI_strncpy(ima->filepath, new_file_path, sizeof(imapf->filepath));
|
||||
if (ima->source == IMA_SRC_TILED) {
|
||||
/* Ensure that the Image filepath is kept in a tokenized format. */
|
||||
char *filename = (char *)BLI_path_basename(ima->filepath);
|
||||
BKE_image_ensure_tile_token(filename);
|
||||
}
|
||||
}
|
||||
MEM_freeN(new_file_path);
|
||||
}
|
||||
|
|
|
@ -3550,5 +3550,16 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
|||
brush->curves_sculpt_settings->points_per_curve = 8;
|
||||
}
|
||||
}
|
||||
|
||||
/* UDIM Packing. */
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "ImagePackedFile", "int", "tile_number")) {
|
||||
for (Image *ima = bmain->images.first; ima; ima = ima->id.next) {
|
||||
int view;
|
||||
LISTBASE_FOREACH_INDEX (ImagePackedFile *, imapf, &ima->packedfiles, view) {
|
||||
imapf->view = view;
|
||||
imapf->tile_number = 1001;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -505,10 +505,10 @@ static bool custom_data_match_attribute(const CustomData *custom_data,
|
|||
return false;
|
||||
}
|
||||
|
||||
ATTR_NO_OPT static uint mesh_cd_calc_gpu_layers_vcol_used(const Mesh *me_query,
|
||||
const CustomData *cd_vdata,
|
||||
const CustomData *cd_ldata,
|
||||
const char name[])
|
||||
static uint mesh_cd_calc_gpu_layers_vcol_used(const Mesh *me_query,
|
||||
const CustomData *cd_vdata,
|
||||
const CustomData *cd_ldata,
|
||||
const char name[])
|
||||
{
|
||||
CustomDataLayer *layer = NULL;
|
||||
AttributeDomain domain;
|
||||
|
@ -552,11 +552,11 @@ ATTR_NO_OPT static uint mesh_cd_calc_gpu_layers_vcol_used(const Mesh *me_query,
|
|||
return vcol_i;
|
||||
}
|
||||
|
||||
ATTR_NO_OPT static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Object *object,
|
||||
const Mesh *me,
|
||||
struct GPUMaterial **gpumat_array,
|
||||
int gpumat_array_len,
|
||||
DRW_MeshAttributes *attributes)
|
||||
static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Object *object,
|
||||
const Mesh *me,
|
||||
struct GPUMaterial **gpumat_array,
|
||||
int gpumat_array_len,
|
||||
DRW_MeshAttributes *attributes)
|
||||
{
|
||||
const Mesh *me_final = editmesh_final_or_this(object, me);
|
||||
const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final);
|
||||
|
|
|
@ -25,7 +25,7 @@ struct VColRef {
|
|||
* corresponds to the integer position of the attribute
|
||||
* within the global color attribute list.
|
||||
*/
|
||||
ATTR_NO_OPT static blender::Vector<VColRef> get_vcol_refs(const CustomData *cd_vdata,
|
||||
static blender::Vector<VColRef> get_vcol_refs(const CustomData *cd_vdata,
|
||||
const CustomData *cd_ldata,
|
||||
const uint vcol_layers)
|
||||
{
|
||||
|
@ -71,7 +71,7 @@ namespace blender::draw {
|
|||
* \{ */
|
||||
|
||||
/* Initialize the common vertex format for vcol for coarse and subdivided meshes. */
|
||||
ATTR_NO_OPT static void init_vcol_format(GPUVertFormat *format,
|
||||
static void init_vcol_format(GPUVertFormat *format,
|
||||
const MeshBatchCache *cache,
|
||||
CustomData *cd_vdata,
|
||||
CustomData *cd_ldata,
|
||||
|
@ -122,7 +122,7 @@ using gpuMeshVcol = struct gpuMeshVcol {
|
|||
ushort r, g, b, a;
|
||||
};
|
||||
|
||||
ATTR_NO_OPT static void extract_vcol_init(const MeshRenderData *mr,
|
||||
static void extract_vcol_init(const MeshRenderData *mr,
|
||||
struct MeshBatchCache *cache,
|
||||
void *buf,
|
||||
void *UNUSED(tls_data))
|
||||
|
|
|
@ -494,7 +494,7 @@ static bool add_collection_search_item(CollItemSearch *cis,
|
|||
cis->name,
|
||||
cis->data,
|
||||
cis->iconid,
|
||||
cis->has_sep_char ? UI_BUT_HAS_SEP_CHAR : 0,
|
||||
cis->has_sep_char ? (uint64_t)UI_BUT_HAS_SEP_CHAR : 0,
|
||||
name_prefix_offset);
|
||||
}
|
||||
|
||||
|
|
|
@ -2316,6 +2316,14 @@ static bool image_has_valid_path(Image *ima)
|
|||
return strchr(ima->filepath, '\\') || strchr(ima->filepath, '/');
|
||||
}
|
||||
|
||||
static bool image_should_pack_during_save_all(const Image *ima)
|
||||
{
|
||||
/* Images without a filepath (implied with IMA_SRC_GENERATED) should
|
||||
* be packed during a save_all operation. */
|
||||
return (ima->source == IMA_SRC_GENERATED) ||
|
||||
(ima->source == IMA_SRC_TILED && !BKE_image_has_filepath(ima));
|
||||
}
|
||||
|
||||
bool ED_image_should_save_modified(const Main *bmain)
|
||||
{
|
||||
ReportList reports;
|
||||
|
@ -2339,7 +2347,7 @@ int ED_image_save_all_modified_info(const Main *bmain, ReportList *reports)
|
|||
bool is_format_writable;
|
||||
|
||||
if (image_should_be_saved(ima, &is_format_writable)) {
|
||||
if (BKE_image_has_packedfile(ima) || (ima->source == IMA_SRC_GENERATED)) {
|
||||
if (BKE_image_has_packedfile(ima) || image_should_pack_during_save_all(ima)) {
|
||||
if (!ID_IS_LINKED(ima)) {
|
||||
num_saveable_images++;
|
||||
}
|
||||
|
@ -2396,7 +2404,7 @@ bool ED_image_save_all_modified(const bContext *C, ReportList *reports)
|
|||
bool is_format_writable;
|
||||
|
||||
if (image_should_be_saved(ima, &is_format_writable)) {
|
||||
if (BKE_image_has_packedfile(ima) || (ima->source == IMA_SRC_GENERATED)) {
|
||||
if (BKE_image_has_packedfile(ima) || image_should_pack_during_save_all(ima)) {
|
||||
BKE_image_memorypack(ima);
|
||||
}
|
||||
else if (is_format_writable) {
|
||||
|
@ -3040,9 +3048,8 @@ static bool image_pack_test(bContext *C, wmOperator *op)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE, IMA_SRC_TILED)) {
|
||||
BKE_report(
|
||||
op->reports, RPT_ERROR, "Packing movies, image sequences or tiled images not supported");
|
||||
if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) {
|
||||
BKE_report(op->reports, RPT_ERROR, "Packing movies or image sequences not supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -3110,9 +3117,8 @@ static int image_unpack_exec(bContext *C, wmOperator *op)
|
|||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE, IMA_SRC_TILED)) {
|
||||
BKE_report(
|
||||
op->reports, RPT_ERROR, "Unpacking movies, image sequences or tiled images not supported");
|
||||
if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) {
|
||||
BKE_report(op->reports, RPT_ERROR, "Unpacking movies or image sequences not supported");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
|
@ -3144,9 +3150,8 @@ static int image_unpack_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
|
|||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE, IMA_SRC_TILED)) {
|
||||
BKE_report(
|
||||
op->reports, RPT_ERROR, "Unpacking movies, image sequences or tiled images not supported");
|
||||
if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) {
|
||||
BKE_report(op->reports, RPT_ERROR, "Unpacking movies or image sequences not supported");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
|
|
|
@ -172,7 +172,6 @@ int GPU_max_compute_shader_storage_blocks()
|
|||
return GCaps.max_compute_shader_storage_blocks;
|
||||
}
|
||||
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
|
@ -333,6 +333,8 @@ static char attr_prefix_get(CustomDataType type)
|
|||
switch (type) {
|
||||
case CD_TANGENT:
|
||||
return 't';
|
||||
case CD_MCOL:
|
||||
return 'c';
|
||||
case CD_AUTO_FROM_NAME:
|
||||
return 'a';
|
||||
case CD_HAIRLENGTH:
|
||||
|
|
|
@ -64,6 +64,11 @@ typedef struct ImageView {
|
|||
typedef struct ImagePackedFile {
|
||||
struct ImagePackedFile *next, *prev;
|
||||
struct PackedFile *packedfile;
|
||||
|
||||
/* Which view and tile this ImagePackedFile represents. Normal images will use 0 and 1001
|
||||
* respectively when creating their ImagePackedFile. Must be provided for each packed image. */
|
||||
int view;
|
||||
int tile_number;
|
||||
/** 1024 = FILE_MAX. */
|
||||
char filepath[1024];
|
||||
} ImagePackedFile;
|
||||
|
|
|
@ -454,7 +454,7 @@ int rna_AttributeGroup_color_length(PointerRNA *ptr)
|
|||
return BKE_id_attributes_length(ptr->owner_id, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL, true);
|
||||
}
|
||||
|
||||
ATTR_NO_OPT int rna_AttributeGroup_length(PointerRNA *ptr)
|
||||
int rna_AttributeGroup_length(PointerRNA *ptr)
|
||||
{
|
||||
return BKE_id_attributes_length(ptr->owner_id, ATTR_DOMAIN_MASK_ALL, CD_MASK_PROP_ALL, false);
|
||||
}
|
||||
|
|
|
@ -737,6 +737,16 @@ static void rna_def_image_packed_files(BlenderRNA *brna)
|
|||
RNA_def_property_string_sdna(prop, NULL, "filepath");
|
||||
RNA_def_struct_name_property(srna, prop);
|
||||
|
||||
prop = RNA_def_property(srna, "view", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "view");
|
||||
RNA_def_property_ui_text(prop, "View Index", "");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
|
||||
prop = RNA_def_property(srna, "tile_number", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "tile_number");
|
||||
RNA_def_property_ui_text(prop, "Tile Number", "");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
|
||||
RNA_api_image_packed_file(srna);
|
||||
}
|
||||
|
||||
|
|
|
@ -161,9 +161,8 @@ static void rna_Image_unpack(Image *image, Main *bmain, ReportList *reports, int
|
|||
if (!BKE_image_has_packedfile(image)) {
|
||||
BKE_report(reports, RPT_ERROR, "Image not packed");
|
||||
}
|
||||
else if (BKE_image_has_multiple_ibufs(image)) {
|
||||
BKE_report(
|
||||
reports, RPT_ERROR, "Unpacking movies, image sequences or tiled images not supported");
|
||||
else if (ELEM(image->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
|
||||
BKE_report(reports, RPT_ERROR, "Unpacking movies or image sequences not supported");
|
||||
return;
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -42,10 +42,20 @@ static int node_shader_gpu_vertex_color(GPUMaterial *mat,
|
|||
GPUNodeStack *out)
|
||||
{
|
||||
NodeShaderVertexColor *vertexColor = (NodeShaderVertexColor *)node->storage;
|
||||
/* NOTE: using CD_AUTO_FROM_NAME instead of CD_MCOL or CD_PROP_COLOR as geometry nodes may
|
||||
* overwrite data which will also change the CustomDataType. This will also make EEVEE and Cycles
|
||||
/* NOTE: using CD_AUTO_FROM_NAME instead of CD_MCOL or CD_PROP_COLOR for named attributes
|
||||
* as geometry nodes may overwrite data which will also change the CustomDataType.
|
||||
* This will also make EEVEE and Cycles
|
||||
* consistent. See T93179. */
|
||||
GPUNodeLink *vertexColorLink = GPU_attribute(mat, CD_AUTO_FROM_NAME, vertexColor->layer_name);
|
||||
|
||||
GPUNodeLink *vertexColorLink;
|
||||
|
||||
if (vertexColor->layer_name[0]) {
|
||||
vertexColorLink = GPU_attribute(mat, CD_AUTO_FROM_NAME, vertexColor->layer_name);
|
||||
}
|
||||
else { /* Fall back on active render color attribute. */
|
||||
vertexColorLink = GPU_attribute(mat, CD_MCOL, vertexColor->layer_name);
|
||||
}
|
||||
|
||||
return GPU_stack_link(mat, node, "node_vertex_color", in, out, vertexColorLink);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue