PBVH: update mesh data pointers stored in pbvh #106271

Merged
Jacques Lucke merged 11 commits from JacquesLucke/blender:pbvh-update-pointers into main 2023-04-08 13:29:49 +02:00
30 changed files with 712 additions and 263 deletions
Showing only changes of commit 0df81b5ff8 - Show all commits

View File

@ -14,3 +14,13 @@ The first three of them were employed by the Blender Foundation during that time
Some features (random sounds, dynamic music, playback manager, convolution and HRTFs support) were added as part of the VALS (Virtual Alliances for Learning Society) project by
- Juan Francisco Crespo Galán <dethon_5@outlook.com>
The Equalizer sound effect has been added by
- Marcos Perez
Several people provided fixes:
- Aaron Carlisle
- Sebastian Parborg
- Leon Zandman

View File

@ -1,3 +1,104 @@
Audaspace 1.4
- Support for OS specific/native audio devices/backends has been added, that is PulseAudio (Linux), WASAPI (Windows) and CoreAudio (MacOS).
- New sound effects have been added, namely Modulator and Equalizer. Thanks to Marcos Perez for contributing the Equalizer.
- File stream info: if an audio file contains multiple streams you can choose which one to process instead of taking the first one (this feature is only supported by ffmpeg, not libsndfile).
- API Change: double instead of float for time values for more precise timing control.
- There have been lots of bugfixes, which are basically the majority of all changes.
- And some other minor improvements were implemented as well.
Detailed list of changes:
d4042d9 Port changes in Blender to upstream.
b60fb45 Equalizer
ab04e84 Fixes
8f0c305 Fix build error with MSVC 17.4+ ported from Blender.
ce44342 Minor documentation update.
cdcb3f4 Migrate from distuils to setuptools for python module.
21eccef Fix FindFFTW to find the float version fftw3f.
ab15e2f Bugfix: API change in new ffmpeg version.
a097be8 Clang format file added, valid from now on.
2fc9fb7 Porting bugfix from Blender upstream.
bb655b7 Bugfix: wrong sample size computation for PulseAudio.
a150495 Bugfix: Buffer did not support buffers > 2 GB.
034645c Update for ffmpeg 5.
932739c Bugfix: WASAPI hangs.
4fcd47c WASAPI: fix bug when switching the default device while there is no playback.
a16fbd2 Python API: fix to get convolution in the python API.
27ac5c1 WASAPI: always switch to default audio device.
1b03e6c Bugfix: catch exception if file cannot be read.
369ff6e PulseAudio: remove unused underflow callback.
2d8bf3a PulseAudio: improve synchronization accuracy.
4868e14 Revert PulseAudioDevice back from ThreadedDevice to threaded mainloop.
6a04446 Adding a jack style mixing thread with a ring buffer for pulseaudio.
5d4b57b Implement RingBuffer class.
e02d3aa FFMPEG: fix seeking and duration calculation.
07b9fa0 Adding file stream functionality.
5a8ad27 Porting changes from Blender.
fa47258 Bugfix: PulseAudio writing to little data on request.
ca3edb5 PulseAudio: increase buffersize.
6d36f3e Pulseaudio: may fix crackling playback start bug.
dbeac4b WASAPI: reinitialize device when lost.
0cba4d3 Bugfix Pulseaudio: might hang.
b73dc6d Bugfix: ffmpeg 4.4 requires channels to be set.
f1ecbe0 Fixed typo.
09e4f27 Rewrite PulseAudioDevice to use ThreadedDevice.
9516924 WASAPI: refactor to simplify and use ThreadedDevice.
749c974 Add ThreadedDevice.
e68b355 Fix some locks in SoftwareDevice.
44b57af Bugfix for deadlock in WASAPIDevice.
8c4b266 CMake: fix ERROR to FATAL_ERROR in MESSAGE.
5a17338 Rename NullDevice's reported name to None.
cd138d7 PulseAudio: add dynamic loading and threading fixes.
6e0250f CoreAudio: add CoreAudioClock as synchronizer.
43aff35 Fix leakage in CoreAudioDevice.cpp
7f6f059 Remove unnecessary cmake code.
a5c1a02 Add CoreAudio device for Apple.
af96f67 Indentation fix.
eec8fd5 WASAPI: use padding also for first buffer submission.
c63bd9b WASAPI: deal with IsFormatSupported case.
079cccb Hide WITH_PULSEAUDIO when not on Linux.
67b5013 Add mingw64 cross compilation toolchain on Linux.
a7bfa58 Add WASAPI backend for Windows.
be1cb25 Allow AUD_init with nullptr to use default device.
fc68868 Compilation fix for mingw.
bb79d25 Add a PulseAudio output device.
a11f593 Bugfix for unwanted volume fading at the beginning of sounds.
8510acf Bugfix: more accurate positioning of sequences.
cb816c1 Fix API docs for python playback manager play function
d125fa2 Add callback for mixing down audio.
789832e Fix numpy import.
9a6a802 Bugfix: JOS resampling type bugfix caused integer underflow.
ece0842 Fix corrupted document in python bindings
28b2ea2 SDL 2: support more audio formats.
a39b7e3 Trying to fix Travis CI build for OS X.
c924007 Some more changes of times from flaot to double.
659afd4 Porting fixes from blender.
8e5e2e6 Fix documentation warnings.
7a6054f API: All times are now double instead of float.
452a724 Mixer sample buffer added channels twice
8ddb6c1 Docs: Cleanup Line Wrapping for python examples
a0c37b2 Docs: Use class methods for api docs
2f8b2e3 Bugfix for invalid offsets provided by ffmpeg's seeking code.
20a7a28 Bug fixes for files with more than 8 channels.
94dc527 Bugfix: Fading from full volume.
2fb9862 Fix: Missing include in FileManager.h.
afadb94 Minor CMakeLists.txt formatting fixes.
734ef03 Add sample rate parameter to silence generation.
ed50f3b Bugfix: Return correct length for modulator and superpose.
cb7a314 Adding a modulator sound effect.
101c714 Bugfix: don't add non-existing devices to the device manager.
7ad99df OpenAL: recreate device if disconnected.
a2ff4e8 Bugfix: memory leak in python API.
5fb21bb Silence some warnings.
9b38605 Some fixes backported from Blender.
40a0a34 Udpate for travis.ci.
212b4b6 Support newer ffmpeg versions.
d27746c Build option: configure whether to build versioned plugins.
19c8d9f Make fftw3 optional.
aa11968 Bugfix for building with gcc7.
10413c5 Fix for seeking with modified pitch.
Audaspace 1.3
=============
@ -10,6 +111,8 @@ Audaspace 1.3
- filter python API parameter check
- finding ffmpeg with pkgconfig
Detailed list of changes:
64884a7 Windows fixes.
53ba3e6 Implemented JACK dynamic loading.
5ee0ee1 Continues last commit.
@ -46,6 +149,8 @@ Audaspace 1.2
- assuring numpy is installed
- building the Python module on Mac OS X with CMake
Detailed list of changes:
a6b6e70 Changing default sample rate from 44.1 to 48 kHz.
20f0164 Bugfix: CMake custom command for python module on OS X.
98679a2 Bugfix: using standard library (s)rand.

View File

@ -23,7 +23,7 @@ endif()
project(audaspace)
set(AUDASPACE_VERSION 1.3)
set(AUDASPACE_VERSION 1.4)
set(AUDASPACE_LONG_VERSION ${AUDASPACE_VERSION}.0)
if(DEFINED AUDASPACE_CMAKE_CFG)

View File

@ -15,7 +15,7 @@ Audaspace is written in C++ 11 so a fairly recent compiler (g++ 4.8.2, clang 3.3
- Jack (output device)
- libsndfile (file access)
- ffmpeg (file access)
- Python (language binding)
- Python (language binding, needs NumPy as well)
Getting the Code
----------------

View File

@ -32,7 +32,7 @@ The following (probably incomplete) features are supported by audaspace:
License
-------
> Copyright © 2009-2015 Jörg Müller. All rights reserved.
> Copyright © 2009-2023 Jörg Müller. All rights reserved.
>
> Licensed under the Apache License, Version 2.0 (the "License");
> you may not use this file except in compliance with the License.

View File

@ -165,6 +165,12 @@ AUD_API void AUD_SequenceEntry_move(AUD_SequenceEntry* entry, double begin, doub
(*entry)->move(begin, end, skip);
}
AUD_API void AUD_SequenceEntry_setConstantRangeAnimationData(AUD_SequenceEntry* entry, AUD_AnimateablePropertyType type, int frame_start, int frame_end, float* data)
{
AnimateableProperty* prop = (*entry)->getAnimProperty(static_cast<AnimateablePropertyType>(type));
prop->writeConstantRange(data, frame_start, frame_end);
}
AUD_API void AUD_SequenceEntry_setAnimationData(AUD_SequenceEntry* entry, AUD_AnimateablePropertyType type, int frame, float* data, char animated)
{
AnimateableProperty* prop = (*entry)->getAnimProperty(static_cast<AnimateablePropertyType>(type));

View File

@ -68,6 +68,16 @@ extern AUD_API void AUD_Sequence_remove(AUD_Sound* sequence, AUD_SequenceEntry*
* Writes animation data to a sequence.
* \param sequence The sound scene.
* \param type The type of animation data.
* \param frame_start Start of the frame range.
* \param frame_end End of the frame range.
* \param data The data to write.
*/
AUD_API void AUD_SequenceEntry_setConstantRangeAnimationData(AUD_SequenceEntry* entry, AUD_AnimateablePropertyType type, int frame_start, int frame_end, float* data);
/**
* Writes animation data to a sequenced entry.
* \param entry The sequenced entry.
* \param type The type of animation data.
* \param frame The frame this data is for.
* \param data The data to write.
* \param animated Whether the attribute is animated.

View File

@ -112,6 +112,14 @@ public:
*/
void write(const float* data, int position, int count);
/**
* Fills the properties frame range with constant value and marks it animated.
* \param data The new value.
* \param position_start The start position in the animation in frames.
* \param position_end The end position in the animation in frames.
*/
void writeConstantRange(const float* data, int position_start, int position_end);
/**
* Reads the properties value.
* \param position The position in the animation in frames.

View File

@ -198,12 +198,13 @@ public:
/**
* Adds a new entry to the scene.
* \param sound The sound this entry should play.
* \param sequence_data Reference to sequence_data. Mainly needed to get the FPS of the scene.
* \param begin The start time.
* \param end The end time or a negative value if determined by the sound.
* \param skip How much seconds should be skipped at the beginning.
* \return The entry added.
*/
std::shared_ptr<SequenceEntry> add(std::shared_ptr<ISound> sound, double begin, double end, double skip);
std::shared_ptr<SequenceEntry> add(std::shared_ptr<ISound> sound, std::shared_ptr<SequenceData> sequence_data, double begin, double end, double skip);
/**
* Removes an entry from the scene.

View File

@ -23,6 +23,7 @@
*/
#include "sequence/AnimateableProperty.h"
#include "sequence/SequenceData.h"
#include "util/ILockable.h"
#include <mutex>
@ -63,6 +64,9 @@ private:
/// How many seconds are skipped at the beginning.
double m_skip;
/// reference to sequence_data. Mainly needed to get the FPS of the scene.
std::shared_ptr<SequenceData> m_sequence_data;
/// Whether the entry is muted.
bool m_muted;
@ -122,9 +126,10 @@ public:
* \param begin The start time.
* \param end The end time or a negative value if determined by the sound.
* \param skip How much seconds should be skipped at the beginning.
* \param sequence_data Reference to sequence_data. Mainly needed to get the FPS of the scene.
* \param id The ID of the entry.
*/
SequenceEntry(std::shared_ptr<ISound> sound, double begin, double end, double skip, int id);
SequenceEntry(std::shared_ptr<ISound> sound, double begin, double end, double skip, std::shared_ptr<SequenceData> sequence_data, int id);
virtual ~SequenceEntry();
/**

View File

@ -65,6 +65,19 @@ void AnimateableProperty::write(const float* data)
std::memcpy(getBuffer(), data, m_count * sizeof(float));
}
void AnimateableProperty::writeConstantRange(const float* data, int position_start, int position_end)
{
assureSize(position_end * m_count * sizeof(float), true);
float* buffer = getBuffer();
for(int i = position_start; i < position_end; i++)
{
std::memcpy(buffer + i * m_count, data, m_count * sizeof(float));
}
m_isAnimated = true;
}
void AnimateableProperty::write(const float* data, int position, int count)
{
std::lock_guard<std::recursive_mutex> lock(m_mutex);

View File

@ -92,7 +92,7 @@ AnimateableProperty* Sequence::getAnimProperty(AnimateablePropertyType type)
std::shared_ptr<SequenceEntry> Sequence::add(std::shared_ptr<ISound> sound, double begin, double end, double skip)
{
return m_sequence->add(sound, begin, end, skip);
return m_sequence->add(sound, m_sequence, begin, end, skip);
}
void Sequence::remove(std::shared_ptr<SequenceEntry> entry)

View File

@ -149,11 +149,11 @@ AnimateableProperty* SequenceData::getAnimProperty(AnimateablePropertyType type)
}
}
std::shared_ptr<SequenceEntry> SequenceData::add(std::shared_ptr<ISound> sound, double begin, double end, double skip)
std::shared_ptr<SequenceEntry> SequenceData::add(std::shared_ptr<ISound> sound, std::shared_ptr<SequenceData> sequence_data, double begin, double end, double skip)
{
std::lock_guard<std::recursive_mutex> lock(m_mutex);
std::shared_ptr<SequenceEntry> entry = std::shared_ptr<SequenceEntry>(new SequenceEntry(sound, begin, end, skip, m_id++));
std::shared_ptr<SequenceEntry> entry = std::shared_ptr<SequenceEntry>(new SequenceEntry(sound, begin, end, skip, sequence_data, m_id++));
m_entries.push_back(entry);
m_entry_status++;

View File

@ -22,7 +22,7 @@
AUD_NAMESPACE_BEGIN
SequenceEntry::SequenceEntry(std::shared_ptr<ISound> sound, double begin, double end, double skip, int id) :
SequenceEntry::SequenceEntry(std::shared_ptr<ISound> sound, double begin, double end, double skip, std::shared_ptr<SequenceData> sequence_data, int id) :
m_status(0),
m_pos_status(1),
m_sound_status(0),
@ -31,6 +31,7 @@ SequenceEntry::SequenceEntry(std::shared_ptr<ISound> sound, double begin, double
m_begin(begin),
m_end(end),
m_skip(skip),
m_sequence_data(sequence_data),
m_muted(false),
m_relative(true),
m_volume_max(1.0f),

View File

@ -241,10 +241,38 @@ bool SequenceHandle::seek(double position)
return false;
std::lock_guard<ILockable> lock(*m_entry);
double seekpos = position - m_entry->m_begin;
if(seekpos < 0)
seekpos = 0;
seekpos += m_entry->m_skip;
double seek_frame = (position - m_entry->m_begin) * m_entry->m_sequence_data->getFPS();
if(seek_frame < 0)
seek_frame = 0;
seek_frame += m_entry->m_skip * m_entry->m_sequence_data->getFPS();
AnimateableProperty* pitch_property = m_entry->getAnimProperty(AP_PITCH);
double target_frame = 0;
if(pitch_property != nullptr)
{
int frame_start = (m_entry->m_begin - m_entry->m_skip) * m_entry->m_sequence_data->getFPS();
for(int i = 0; seek_frame > 0; i++)
{
float pitch;
pitch_property->read(frame_start + i, &pitch);
const double factor = seek_frame > 1.0 ? 1.0 : seek_frame;
target_frame += pitch * factor;
seek_frame--;
}
}
else
{
target_frame = seek_frame;
}
double seekpos = target_frame / m_entry->m_sequence_data->getFPS();
m_handle->setPitch(1.0f);
m_handle->seek(seekpos);

View File

@ -609,59 +609,60 @@ void BlenderSync::sync_particle_hair(
}
}
static std::optional<BL::FloatAttribute> find_curves_radius_attribute(BL::Curves b_curves)
static const float *find_radius_attribute(BL::Curves b_curves)
{
for (BL::Attribute &b_attribute : b_curves.attributes) {
if (b_attribute.name() != "radius") {
continue;
}
if (b_attribute.domain() != BL::Attribute::domain_POINT) {
continue;
}
if (b_attribute.data_type() != BL::Attribute::data_type_FLOAT) {
continue;
}
return BL::FloatAttribute{b_attribute};
BL::FloatAttribute b_float_attribute{b_attribute};
if (b_float_attribute.data.length() == 0) {
return nullptr;
}
return static_cast<const float *>(b_float_attribute.data[0].ptr.data);
}
return std::nullopt;
return nullptr;
}
static BL::FloatVectorAttribute find_curves_position_attribute(BL::Curves b_curves)
static const float (*find_position_attribute(BL::Curves b_curves))[3]
{
for (BL::Attribute &b_attribute : b_curves.attributes) {
if (b_attribute.name() != "position") {
continue;
}
if (b_attribute.domain() != BL::Attribute::domain_POINT) {
continue;
}
if (b_attribute.data_type() != BL::Attribute::data_type_FLOAT_VECTOR) {
continue;
}
return BL::FloatVectorAttribute{b_attribute};
BL::FloatVectorAttribute b_float3_attribute{b_attribute};
if (b_float3_attribute.data.length() == 0) {
return nullptr;
}
return static_cast<const float(*)[3]>(b_float3_attribute.data[0].ptr.data);
}
/* The position attribute must exist. */
assert(false);
return BL::FloatVectorAttribute{b_curves.attributes[0]};
return nullptr;
}
template<typename TypeInCycles, typename GetValueAtIndex>
static void fill_generic_attribute(BL::Curves &b_curves,
static void fill_generic_attribute(const int num_curves,
const int num_points,
TypeInCycles *data,
const AttributeElement element,
const GetValueAtIndex &get_value_at_index)
{
switch (element) {
case ATTR_ELEMENT_CURVE_KEY: {
const int num_points = b_curves.points.length();
for (int i = 0; i < num_points; i++) {
data[i] = get_value_at_index(i);
}
break;
}
case ATTR_ELEMENT_CURVE: {
const int num_verts = b_curves.curves.length();
for (int i = 0; i < num_verts; i++) {
for (int i = 0; i < num_curves; i++) {
data[i] = get_value_at_index(i);
}
break;
@ -681,6 +682,7 @@ static void attr_create_motion(Hair *hair, BL::Attribute &b_attribute, const flo
}
BL::FloatVectorAttribute b_vector_attribute(b_attribute);
const float(*src)[3] = static_cast<const float(*)[3]>(b_vector_attribute.data[0].ptr.data);
const int num_curve_keys = hair->get_curve_keys().size();
/* Find or add attribute */
@ -698,23 +700,24 @@ static void attr_create_motion(Hair *hair, BL::Attribute &b_attribute, const flo
float3 *mP = attr_mP->data_float3() + step * num_curve_keys;
for (int i = 0; i < num_curve_keys; i++) {
mP[i] = P[i] + get_float3(b_vector_attribute.data[i].vector()) * relative_time;
mP[i] = P[i] + make_float3(src[i][0], src[i][1], src[i][2]) * relative_time;
}
}
}
static void attr_create_uv(AttributeSet &attributes,
BL::Curves &b_curves,
const int num_curves,
const int num_points,
BL::Attribute &b_attribute,
const ustring name)
{
BL::Float2Attribute b_float2_attribute{b_attribute};
const float(*src)[2] = static_cast<const float(*)[2]>(b_float2_attribute.data[0].ptr.data);
Attribute *attr = attributes.add(ATTR_STD_UV, name);
float2 *data = attr->data_float2();
fill_generic_attribute(b_curves, data, ATTR_ELEMENT_CURVE, [&](int i) {
BL::Array<float, 2> v = b_float2_attribute.data[i].vector();
return make_float2(v[0], v[1]);
fill_generic_attribute(num_curves, num_points, data, ATTR_ELEMENT_CURVE, [&](int i) {
return make_float2(src[i][0], src[i][1]);
});
}
@ -724,6 +727,9 @@ static void attr_create_generic(Scene *scene,
const bool need_motion,
const float motion_scale)
{
const int num_keys = b_curves.points.length();
const int num_curves = b_curves.curves.length();
AttributeSet &attributes = hair->attributes;
static const ustring u_velocity("velocity");
const bool need_uv = hair->need_attribute(scene, ATTR_STD_UV);
@ -743,7 +749,7 @@ static void attr_create_generic(Scene *scene,
/* Weak, use first float2 attribute as standard UV. */
if (need_uv && !have_uv && b_data_type == BL::Attribute::data_type_FLOAT2 &&
b_domain == BL::Attribute::domain_CURVE) {
attr_create_uv(attributes, b_curves, b_attribute, name);
attr_create_uv(attributes, num_curves, num_keys, b_attribute, name);
have_uv = true;
continue;
}
@ -773,57 +779,70 @@ static void attr_create_generic(Scene *scene,
switch (b_data_type) {
case BL::Attribute::data_type_FLOAT: {
BL::FloatAttribute b_float_attribute{b_attribute};
const float *src = static_cast<const float *>(b_float_attribute.data[0].ptr.data);
Attribute *attr = attributes.add(name, TypeFloat, element);
float *data = attr->data_float();
fill_generic_attribute(
b_curves, data, element, [&](int i) { return b_float_attribute.data[i].value(); });
fill_generic_attribute(num_curves, num_keys, data, element, [&](int i) { return src[i]; });
break;
}
case BL::Attribute::data_type_BOOLEAN: {
BL::BoolAttribute b_bool_attribute{b_attribute};
const bool *src = static_cast<const bool *>(b_bool_attribute.data[0].ptr.data);
Attribute *attr = attributes.add(name, TypeFloat, element);
float *data = attr->data_float();
fill_generic_attribute(b_curves, data, element, [&](int i) {
return (float)b_bool_attribute.data[i].value();
});
fill_generic_attribute(
num_curves, num_keys, data, element, [&](int i) { return float(src[i]); });
break;
}
case BL::Attribute::data_type_INT: {
BL::IntAttribute b_int_attribute{b_attribute};
const int *src = static_cast<const int *>(b_int_attribute.data[0].ptr.data);
Attribute *attr = attributes.add(name, TypeFloat, element);
float *data = attr->data_float();
fill_generic_attribute(b_curves, data, element, [&](int i) {
return (float)b_int_attribute.data[i].value();
});
fill_generic_attribute(
num_curves, num_keys, data, element, [&](int i) { return float(src[i]); });
break;
}
case BL::Attribute::data_type_FLOAT_VECTOR: {
BL::FloatVectorAttribute b_vector_attribute{b_attribute};
const float(*src)[3] = static_cast<const float(*)[3]>(b_vector_attribute.data[0].ptr.data);
Attribute *attr = attributes.add(name, TypeVector, element);
float3 *data = attr->data_float3();
fill_generic_attribute(b_curves, data, element, [&](int i) {
BL::Array<float, 3> v = b_vector_attribute.data[i].vector();
return make_float3(v[0], v[1], v[2]);
fill_generic_attribute(num_curves, num_keys, data, element, [&](int i) {
return make_float3(src[i][0], src[i][1], src[i][2]);
});
break;
}
case BL::Attribute::data_type_BYTE_COLOR: {
BL::ByteColorAttribute b_color_attribute{b_attribute};
const uchar(*src)[4] = static_cast<const uchar(*)[4]>(b_color_attribute.data[0].ptr.data);
Attribute *attr = attributes.add(name, TypeRGBA, element);
float4 *data = attr->data_float4();
fill_generic_attribute(num_curves, num_keys, data, element, [&](int i) {
return make_float4(color_srgb_to_linear(byte_to_float(src[i][0])),
color_srgb_to_linear(byte_to_float(src[i][1])),
color_srgb_to_linear(byte_to_float(src[i][2])),
color_srgb_to_linear(byte_to_float(src[i][3])));
});
break;
}
case BL::Attribute::data_type_FLOAT_COLOR: {
BL::FloatColorAttribute b_color_attribute{b_attribute};
const float(*src)[4] = static_cast<const float(*)[4]>(b_color_attribute.data[0].ptr.data);
Attribute *attr = attributes.add(name, TypeRGBA, element);
float4 *data = attr->data_float4();
fill_generic_attribute(b_curves, data, element, [&](int i) {
BL::Array<float, 4> v = b_color_attribute.data[i].color();
return make_float4(v[0], v[1], v[2], v[3]);
fill_generic_attribute(num_curves, num_keys, data, element, [&](int i) {
return make_float4(src[i][0], src[i][1], src[i][2], src[i][3]);
});
break;
}
case BL::Attribute::data_type_FLOAT2: {
BL::Float2Attribute b_float2_attribute{b_attribute};
const float(*src)[2] = static_cast<const float(*)[2]>(b_float2_attribute.data[0].ptr.data);
Attribute *attr = attributes.add(name, TypeFloat2, element);
float2 *data = attr->data_float2();
fill_generic_attribute(b_curves, data, element, [&](int i) {
BL::Array<float, 2> v = b_float2_attribute.data[i].vector();
return make_float2(v[0], v[1]);
fill_generic_attribute(num_curves, num_keys, data, element, [&](int i) {
return make_float2(src[i][0], src[i][1]);
});
break;
}
@ -834,27 +853,28 @@ static void attr_create_generic(Scene *scene,
}
}
static float4 hair_point_as_float4(BL::FloatVectorAttribute b_attr_position,
std::optional<BL::FloatAttribute> b_attr_radius,
const int index)
static float4 curve_point_as_float4(const float (*b_attr_position)[3],
const float *b_attr_radius,
const int index)
{
float4 mP = float3_to_float4(get_float3(b_attr_position.data[index].vector()));
mP.w = b_attr_radius ? b_attr_radius->data[index].value() : 0.005f;
float4 mP = make_float4(
b_attr_position[index][0], b_attr_position[index][1], b_attr_position[index][2], 0.0f);
mP.w = b_attr_radius ? b_attr_radius[index] : 0.005f;
return mP;
}
static float4 interpolate_hair_points(BL::FloatVectorAttribute b_attr_position,
std::optional<BL::FloatAttribute> b_attr_radius,
const int first_point_index,
const int num_points,
const float step)
static float4 interpolate_curve_points(const float (*b_attr_position)[3],
const float *b_attr_radius,
const int first_point_index,
const int num_points,
const float step)
{
const float curve_t = step * (num_points - 1);
const int point_a = clamp((int)curve_t, 0, num_points - 1);
const int point_b = min(point_a + 1, num_points - 1);
const float t = curve_t - (float)point_a;
return lerp(hair_point_as_float4(b_attr_position, b_attr_radius, first_point_index + point_a),
hair_point_as_float4(b_attr_position, b_attr_radius, first_point_index + point_b),
return lerp(curve_point_as_float4(b_attr_position, b_attr_radius, first_point_index + point_a),
curve_point_as_float4(b_attr_position, b_attr_radius, first_point_index + point_b),
t);
}
@ -864,8 +884,6 @@ static void export_hair_curves(Scene *scene,
const bool need_motion,
const float motion_scale)
{
/* TODO: optimize so we can straight memcpy arrays from Blender? */
const int num_keys = b_curves.points.length();
const int num_curves = b_curves.curves.length();
@ -879,7 +897,6 @@ static void export_hair_curves(Scene *scene,
/* Add requested attributes. */
float *attr_intercept = NULL;
float *attr_length = NULL;
float *attr_random = NULL;
if (hair->need_attribute(scene, ATTR_STD_CURVE_INTERCEPT)) {
attr_intercept = hair->attributes.add(ATTR_STD_CURVE_INTERCEPT)->data_float();
@ -888,28 +905,40 @@ static void export_hair_curves(Scene *scene,
attr_length = hair->attributes.add(ATTR_STD_CURVE_LENGTH)->data_float();
}
if (hair->need_attribute(scene, ATTR_STD_CURVE_RANDOM)) {
attr_random = hair->attributes.add(ATTR_STD_CURVE_RANDOM)->data_float();
float *attr_random = hair->attributes.add(ATTR_STD_CURVE_RANDOM)->data_float();
for (int i = 0; i < num_curves; i++) {
attr_random[i] = hash_uint2_to_float(i, 0);
}
}
BL::FloatVectorAttribute b_attr_position = find_curves_position_attribute(b_curves);
std::optional<BL::FloatAttribute> b_attr_radius = find_curves_radius_attribute(b_curves);
const int *point_offsets = static_cast<const int *>(b_curves.curve_offset_data[0].ptr.data);
const float(*b_attr_position)[3] = find_position_attribute(b_curves);
const float *b_attr_radius = find_radius_attribute(b_curves);
std::copy(point_offsets, point_offsets + num_curves, curve_first_key);
std::fill(curve_shader, curve_shader + num_curves, 0);
if (b_attr_radius) {
std::copy(b_attr_radius, b_attr_radius + num_keys, curve_radius);
}
else {
std::fill(curve_radius, curve_radius + num_curves, 0.005f);
}
/* Export curves and points. */
for (int i = 0; i < num_curves; i++) {
const int first_point_index = b_curves.curve_offset_data[i].value();
const int num_points = b_curves.curve_offset_data[i + 1].value() - first_point_index;
const int first_point_index = point_offsets[i];
const int num_points = point_offsets[i + 1] - first_point_index;
float3 prev_co = zero_float3();
float length = 0.0f;
/* Position and radius. */
for (int j = 0; j < num_points; j++) {
const int point_offset = first_point_index + j;
const float3 co = get_float3(b_attr_position.data[point_offset].vector());
const float radius = b_attr_radius ? b_attr_radius->data[point_offset].value() : 0.005f;
const int point = first_point_index + j;
const float3 co = make_float3(
b_attr_position[point][0], b_attr_position[point][1], b_attr_position[point][2]);
curve_keys[point_offset] = co;
curve_radius[point_offset] = radius;
curve_keys[point] = co;
if (attr_length || attr_intercept) {
if (j > 0) {
@ -918,7 +947,7 @@ static void export_hair_curves(Scene *scene,
prev_co = co;
if (attr_intercept) {
attr_intercept[point_offset] = length;
attr_intercept[point] = length;
}
}
}
@ -926,8 +955,8 @@ static void export_hair_curves(Scene *scene,
/* Normalized 0..1 attribute along curve. */
if (attr_intercept && length > 0.0f) {
for (int j = 1; j < num_points; j++) {
const int point_offset = first_point_index + j;
attr_intercept[point_offset] /= length;
const int point = first_point_index + j;
attr_intercept[point] /= length;
}
}
@ -935,15 +964,6 @@ static void export_hair_curves(Scene *scene,
if (attr_length) {
attr_length[i] = length;
}
/* Random number per curve. */
if (attr_random != NULL) {
attr_random[i] = hash_uint2_to_float(i, 0);
}
/* Curve. */
curve_shader[i] = 0;
curve_first_key[i] = first_point_index;
}
attr_create_generic(scene, hair, b_curves, need_motion, motion_scale);
@ -968,12 +988,13 @@ static void export_hair_curves_motion(Hair *hair, BL::Curves b_curves, int motio
int num_motion_keys = 0;
int curve_index = 0;
BL::FloatVectorAttribute b_attr_position = find_curves_position_attribute(b_curves);
std::optional<BL::FloatAttribute> b_attr_radius = find_curves_radius_attribute(b_curves);
const int *point_offsets = static_cast<const int *>(b_curves.curve_offset_data[0].ptr.data);
const float(*b_attr_position)[3] = find_position_attribute(b_curves);
const float *b_attr_radius = find_radius_attribute(b_curves);
for (int i = 0; i < num_curves; i++) {
const int first_point_index = b_curves.curve_offset_data[i].value();
const int num_points = b_curves.curve_offset_data[i + 1].value() - first_point_index;
const int first_point_index = point_offsets[i];
const int num_points = point_offsets[i + 1] - first_point_index;
Hair::Curve curve = hair->get_curve(curve_index);
curve_index++;
@ -981,10 +1002,10 @@ static void export_hair_curves_motion(Hair *hair, BL::Curves b_curves, int motio
if (num_points == curve.num_keys) {
/* Number of keys matches. */
for (int i = 0; i < num_points; i++) {
int point_index = first_point_index + i;
int point = first_point_index + i;
if (point_index < num_keys) {
mP[num_motion_keys] = hair_point_as_float4(b_attr_position, b_attr_radius, point_index);
if (point < num_keys) {
mP[num_motion_keys] = curve_point_as_float4(b_attr_position, b_attr_radius, point);
num_motion_keys++;
if (!have_motion) {
@ -1003,7 +1024,7 @@ static void export_hair_curves_motion(Hair *hair, BL::Curves b_curves, int motio
const float step_size = curve.num_keys > 1 ? 1.0f / (curve.num_keys - 1) : 0.0f;
for (int i = 0; i < curve.num_keys; i++) {
const float step = i * step_size;
mP[num_motion_keys] = interpolate_hair_points(
mP[num_motion_keys] = interpolate_curve_points(
b_attr_position, b_attr_radius, first_point_index, num_points, step);
num_motion_keys++;
}

View File

@ -10,22 +10,12 @@
#include "blender/sync.h"
#include "blender/util.h"
#include "util/color.h"
#include "util/foreach.h"
#include "util/hash.h"
CCL_NAMESPACE_BEGIN
template<typename TypeInCycles, typename GetValueAtIndex>
static void fill_generic_attribute(BL::PointCloud &b_pointcloud,
TypeInCycles *data,
const GetValueAtIndex &get_value_at_index)
{
const int num_points = b_pointcloud.points.length();
for (int i = 0; i < num_points; i++) {
data[i] = get_value_at_index(i);
}
}
static void attr_create_motion(PointCloud *pointcloud,
BL::Attribute &b_attribute,
const float motion_scale)
@ -63,6 +53,11 @@ static void copy_attributes(PointCloud *pointcloud,
const bool need_motion,
const float motion_scale)
{
const int num_points = b_pointcloud.points.length();
if (num_points == 0) {
return;
}
AttributeSet &attributes = pointcloud->attributes;
static const ustring u_velocity("velocity");
for (BL::Attribute &b_attribute : b_pointcloud.attributes) {
@ -81,56 +76,73 @@ static void copy_attributes(PointCloud *pointcloud,
switch (b_data_type) {
case BL::Attribute::data_type_FLOAT: {
BL::FloatAttribute b_float_attribute{b_attribute};
const float *src = static_cast<const float *>(b_float_attribute.data[0].ptr.data);
Attribute *attr = attributes.add(name, TypeFloat, element);
float *data = attr->data_float();
fill_generic_attribute(
b_pointcloud, data, [&](int i) { return b_float_attribute.data[i].value(); });
std::copy(src, src + num_points, data);
break;
}
case BL::Attribute::data_type_BOOLEAN: {
BL::BoolAttribute b_bool_attribute{b_attribute};
const bool *src = static_cast<const bool *>(b_bool_attribute.data[0].ptr.data);
Attribute *attr = attributes.add(name, TypeFloat, element);
float *data = attr->data_float();
fill_generic_attribute(
b_pointcloud, data, [&](int i) { return (float)b_bool_attribute.data[i].value(); });
for (int i = 0; i < num_points; i++) {
data[i] = float(src[i]);
}
break;
}
case BL::Attribute::data_type_INT: {
BL::IntAttribute b_int_attribute{b_attribute};
const int *src = static_cast<const int *>(b_int_attribute.data[0].ptr.data);
Attribute *attr = attributes.add(name, TypeFloat, element);
float *data = attr->data_float();
fill_generic_attribute(
b_pointcloud, data, [&](int i) { return (float)b_int_attribute.data[i].value(); });
for (int i = 0; i < num_points; i++) {
data[i] = float(src[i]);
}
break;
}
case BL::Attribute::data_type_FLOAT_VECTOR: {
BL::FloatVectorAttribute b_vector_attribute{b_attribute};
const float(*src)[3] = static_cast<const float(*)[3]>(b_vector_attribute.data[0].ptr.data);
Attribute *attr = attributes.add(name, TypeVector, element);
float3 *data = attr->data_float3();
fill_generic_attribute(b_pointcloud, data, [&](int i) {
BL::Array<float, 3> v = b_vector_attribute.data[i].vector();
return make_float3(v[0], v[1], v[2]);
});
for (int i = 0; i < num_points; i++) {
data[i] = make_float3(src[i][0], src[i][1], src[i][2]);
}
break;
}
case BL::Attribute::data_type_BYTE_COLOR: {
BL::ByteColorAttribute b_color_attribute{b_attribute};
const uchar(*src)[4] = static_cast<const uchar(*)[4]>(b_color_attribute.data[0].ptr.data);
Attribute *attr = attributes.add(name, TypeRGBA, element);
float4 *data = attr->data_float4();
for (int i = 0; i < num_points; i++) {
data[i] = make_float4(color_srgb_to_linear(byte_to_float(src[i][0])),
color_srgb_to_linear(byte_to_float(src[i][1])),
color_srgb_to_linear(byte_to_float(src[i][2])),
color_srgb_to_linear(byte_to_float(src[i][3])));
}
break;
}
case BL::Attribute::data_type_FLOAT_COLOR: {
BL::FloatColorAttribute b_color_attribute{b_attribute};
const float(*src)[4] = static_cast<const float(*)[4]>(b_color_attribute.data[0].ptr.data);
Attribute *attr = attributes.add(name, TypeRGBA, element);
float4 *data = attr->data_float4();
fill_generic_attribute(b_pointcloud, data, [&](int i) {
BL::Array<float, 4> v = b_color_attribute.data[i].color();
return make_float4(v[0], v[1], v[2], v[3]);
});
for (int i = 0; i < num_points; i++) {
data[i] = make_float4(src[i][0], src[i][1], src[i][2], src[i][3]);
}
break;
}
case BL::Attribute::data_type_FLOAT2: {
BL::Float2Attribute b_float2_attribute{b_attribute};
const float(*src)[2] = static_cast<const float(*)[2]>(b_float2_attribute.data[0].ptr.data);
Attribute *attr = attributes.add(name, TypeFloat2, element);
float2 *data = attr->data_float2();
fill_generic_attribute(b_pointcloud, data, [&](int i) {
BL::Array<float, 2> v = b_float2_attribute.data[i].vector();
return make_float2(v[0], v[1]);
});
for (int i = 0; i < num_points; i++) {
data[i] = make_float2(src[i][0], src[i][1]);
}
break;
}
default:
@ -140,7 +152,7 @@ static void copy_attributes(PointCloud *pointcloud,
}
}
static std::optional<BL::FloatAttribute> find_radius_attribute(BL::PointCloud b_pointcloud)
static const float *find_radius_attribute(BL::PointCloud b_pointcloud)
{
for (BL::Attribute &b_attribute : b_pointcloud.attributes) {
if (b_attribute.name() != "radius") {
@ -149,12 +161,16 @@ static std::optional<BL::FloatAttribute> find_radius_attribute(BL::PointCloud b_
if (b_attribute.data_type() != BL::Attribute::data_type_FLOAT) {
continue;
}
return BL::FloatAttribute{b_attribute};
BL::FloatAttribute b_float_attribute{b_attribute};
if (b_float_attribute.data.length() == 0) {
return nullptr;
}
return static_cast<const float *>(b_float_attribute.data[0].ptr.data);
}
return std::nullopt;
return nullptr;
}
static BL::FloatVectorAttribute find_position_attribute(BL::PointCloud b_pointcloud)
static const float (*find_position_attribute(BL::PointCloud b_pointcloud))[3]
{
for (BL::Attribute &b_attribute : b_pointcloud.attributes) {
if (b_attribute.name() != "position") {
@ -163,11 +179,15 @@ static BL::FloatVectorAttribute find_position_attribute(BL::PointCloud b_pointcl
if (b_attribute.data_type() != BL::Attribute::data_type_FLOAT_VECTOR) {
continue;
}
return BL::FloatVectorAttribute{b_attribute};
BL::FloatVectorAttribute b_float3_attribute{b_attribute};
if (b_float3_attribute.data.length() == 0) {
return nullptr;
}
return static_cast<const float(*)[3]>(b_float3_attribute.data[0].ptr.data);
}
/* The position attribute must exist. */
assert(false);
return BL::FloatVectorAttribute{b_pointcloud.attributes[0]};
return nullptr;
}
static void export_pointcloud(Scene *scene,
@ -176,34 +196,36 @@ static void export_pointcloud(Scene *scene,
const bool need_motion,
const float motion_scale)
{
/* TODO: optimize so we can straight memcpy arrays from Blender? */
const int num_points = b_pointcloud.points.length();
pointcloud->resize(num_points);
/* Add requested attributes. */
Attribute *attr_random = NULL;
if (pointcloud->need_attribute(scene, ATTR_STD_POINT_RANDOM)) {
attr_random = pointcloud->attributes.add(ATTR_STD_POINT_RANDOM);
const float(*b_attr_position)[3] = find_position_attribute(b_pointcloud);
float3 *points = pointcloud->get_points().data();
for (int i = 0; i < num_points; i++) {
points[i] = make_float3(b_attr_position[i][0], b_attr_position[i][1], b_attr_position[i][2]);
}
/* Reserve memory. */
const int num_points = b_pointcloud.points.length();
pointcloud->reserve(num_points);
const float *b_attr_radius = find_radius_attribute(b_pointcloud);
float *radius = pointcloud->get_radius().data();
if (b_attr_radius) {
std::copy(b_attr_radius, b_attr_radius + num_points, radius);
}
else {
std::fill(radius, radius + num_points, 0.01f);
}
BL::FloatVectorAttribute b_attr_position = find_position_attribute(b_pointcloud);
std::optional<BL::FloatAttribute> b_attr_radius = find_radius_attribute(b_pointcloud);
int *shader = pointcloud->get_shader().data();
std::fill(shader, shader + num_points, 0);
/* Export points. */
for (int i = 0; i < num_points; i++) {
const float3 co = get_float3(b_attr_position.data[i].vector());
const float radius = b_attr_radius ? b_attr_radius->data[i].value() : 0.01f;
pointcloud->add_point(co, radius);
/* Random number per point. */
if (attr_random != NULL) {
attr_random->add(hash_uint2_to_float(i, 0));
if (pointcloud->need_attribute(scene, ATTR_STD_POINT_RANDOM)) {
Attribute *attr_random = pointcloud->attributes.add(ATTR_STD_POINT_RANDOM);
float *data = attr_random->data_float();
for (int i = 0; i < num_points; i++) {
data[i] = hash_uint2_to_float(i, 0);
}
}
/* Export attributes */
copy_attributes(pointcloud, b_pointcloud, need_motion, motion_scale);
}
@ -220,22 +242,22 @@ static void export_pointcloud_motion(PointCloud *pointcloud,
new_attribute = true;
}
/* Export motion points. */
const int num_points = pointcloud->num_points();
// Point cloud attributes are stored as float4 with the radius
// in the w element. This is explict now as float3 is no longer
// interchangeable with float4 as it is packed now.
/* Point cloud attributes are stored as float4 with the radius in the w element.
* This is explict now as float3 is no longer interchangeable with float4 as it
* is packed now. */
float4 *mP = attr_mP->data_float4() + motion_step * num_points;
bool have_motion = false;
const array<float3> &pointcloud_points = pointcloud->get_points();
const int b_points_num = b_pointcloud.points.length();
BL::FloatVectorAttribute b_attr_position = find_position_attribute(b_pointcloud);
std::optional<BL::FloatAttribute> b_attr_radius = find_radius_attribute(b_pointcloud);
const float(*b_attr_position)[3] = find_position_attribute(b_pointcloud);
const float *b_attr_radius = find_radius_attribute(b_pointcloud);
for (int i = 0; i < std::min(num_points, b_points_num); i++) {
const float3 P = get_float3(b_attr_position.data[i].vector());
const float radius = b_attr_radius ? b_attr_radius->data[i].value() : 0.01f;
const float3 P = make_float3(
b_attr_position[i][0], b_attr_position[i][1], b_attr_position[i][2]);
const float radius = b_attr_radius ? b_attr_radius[i] : 0.01f;
mP[i] = make_float4(P.x, P.y, P.z, radius);
have_motion = have_motion || (P != pointcloud_points[i]);
}
@ -277,7 +299,7 @@ void BlenderSync::sync_pointcloud(PointCloud *pointcloud, BObjectInfo &b_ob_info
0.0f;
export_pointcloud(scene, &new_pointcloud, b_pointcloud, need_motion, motion_scale);
/* update original sockets */
/* Update original sockets. */
for (const SocketType &socket : new_pointcloud.type->inputs) {
/* Those sockets are updated in sync_object, so do not modify them. */
if (socket.name == "use_motion_blur" || socket.name == "motion_steps" ||
@ -292,7 +314,7 @@ void BlenderSync::sync_pointcloud(PointCloud *pointcloud, BObjectInfo &b_ob_info
pointcloud->attributes.attributes.push_back(std::move(attr));
}
/* tag update */
/* Tag update. */
const bool rebuild = (pointcloud && old_numpoints != pointcloud->num_points());
pointcloud->tag_update(scene, rebuild);
}

View File

@ -109,6 +109,11 @@ class PassAccessor {
/* Set pass data for the given render buffers. Used for baking to read from passes. */
bool set_render_tile_pixels(RenderBuffers *render_buffers, const Source &source);
const PassAccessInfo &get_pass_access_info() const
{
return pass_access_info_;
}
protected:
virtual void init_kernel_film_convert(KernelFilmConvert *kfilm_convert,
const BufferParams &buffer_params,

View File

@ -1036,7 +1036,12 @@ bool PathTrace::get_render_tile_pixels(const PassAccessor &pass_accessor,
}
if (big_tile_denoise_work_ && render_state_.has_denoised_result) {
return big_tile_denoise_work_->get_render_tile_pixels(pass_accessor, destination);
/* Only use the big tile denoised buffer to access the denoised passes.
* The guiding passes are allowed to be modified in-place for the needs of the denoiser,
* so copy those from the original devices buffers. */
if (pass_accessor.get_pass_access_info().mode == PassMode::DENOISED) {
return big_tile_denoise_work_->get_render_tile_pixels(pass_accessor, destination);
}
}
bool success = true;

View File

@ -555,8 +555,8 @@ class NODE_MT_context_menu(Menu):
layout.operator("node.group_edit", text="Edit").exit = False
layout.operator("node.group_ungroup", text="Ungroup")
if is_nested:
layout.operator("node.tree_path_parent", text="Exit Group", icon='FILE_PARENT')
if is_nested:
layout.operator("node.tree_path_parent", text="Exit Group", icon='FILE_PARENT')
layout.separator()

View File

@ -171,6 +171,15 @@ size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst_w,
*/
int BLI_wcwidth(char32_t ucs) ATTR_WARN_UNUSED_RESULT;
int BLI_wcswidth(const char32_t *pwcs, size_t n) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
/**
* Upper and lowercase for 32-bit characters for all scripts that distinguish case. One-to-one
* mappings so this doesn't work corectly for uppercase Σ (two lowercase forms) and lowercase ß
* won't become "SS".
*/
char32_t BLI_str_utf32_char_to_upper(char32_t wc);
char32_t BLI_str_utf32_char_to_lower(char32_t wc);
/**
* \warning can return -1 on bad chars.
*/

View File

@ -399,6 +399,218 @@ int BLI_str_utf8_char_width_safe(const char *p)
return (columns < 0) ? 1 : columns;
}
char32_t BLI_str_utf32_char_to_upper(char32_t wc)
{
if (wc < U'\xFF') { /* Latin. */
if ((wc <= U'z' && wc >= U'a') || (wc <= U'\xF6' && wc >= U'\xE0') ||
(wc <= U'\xFE' && wc >= U'\xF8')) {
return wc - 32;
}
return wc;
}
if ((wc <= U'\x137' && wc >= U'\x101') || (wc <= U'\x1E95' && wc >= U'\x1E01')) {
/* Latin Extended. */
return (wc & 1) ? wc - 1 : wc;
}
if ((wc <= U'\x586' && wc >= U'\x561') || (wc <= U'\x10F5' && wc >= U'\x10D0')) {
/* Armenian and Georgian */
return wc - 48;
}
if (wc <= U'\x24E9' && wc >= U'\x24D0') { /* Enclosed Numerals. */
return wc - 26;
}
if (wc <= U'\xFF5A' && wc >= U'\xFF41') { /* Fullwidth Forms. */
return wc - 32;
}
/* There are only three remaining ranges that contain capitalization. */
if (!(wc <= U'\x0292' && wc >= U'\x00FF') && !(wc <= U'\x04F9' && wc >= U'\x03AC') &&
!(wc <= U'\x1FE1' && wc >= U'\x1E01')) {
return wc;
}
static const char32_t from[] =
U"\x00FF\x013A\x013C\x013E\x0140\x0142\x0144\x0146\x0148\x014B\x014D\x014F\x0151\x0153\x0155"
U"\x0157\x0159\x015B\x015D\x015F\x0161\x0163\x0165\x0167\x0169\x016B\x016D\x016F\x0171\x0173"
U"\x0175\x0177\x017A\x017C\x017E\x0183\x0185\x0188\x018C\x0192\x0199\x01A1\x01A3\x01A5\x01A8"
U"\x01AD\x01B0\x01B4\x01B6\x01B9\x01BD\x01C6\x01C9\x01CC\x01CE\x01D0\x01D2\x01D4\x01D6\x01D8"
U"\x01DA\x01DC\x01DF\x01E1\x01E3\x01E5\x01E7\x01E9\x01EB\x01ED\x01EF\x01F3\x01F5\x01FB\x01FD"
U"\x01FF\x0201\x0203\x0205\x0207\x0209\x020B\x020D\x020F\x0211\x0213\x0215\x0217\x0253\x0254"
U"\x0257\x0258\x0259\x025B\x0260\x0263\x0268\x0269\x026F\x0272\x0275\x0283\x0288\x028A\x028B"
U"\x0292\x03AC\x03AD\x03AE\x03AF\x03B1\x03B2\x03B3\x03B4\x03B5\x03B6\x03B7\x03B8\x03B9\x03BA"
U"\x03BB\x03BC\x03BD\x03BE\x03BF\x03C0\x03C1\x03C3\x03C4\x03C5\x03C6\x03C7\x03C8\x03C9\x03CA"
U"\x03CB\x03CC\x03CD\x03CE\x03E3\x03E5\x03E7\x03E9\x03EB\x03ED\x03EF\x0430\x0431\x0432\x0433"
U"\x0434\x0435\x0436\x0437\x0438\x0439\x043A\x043B\x043C\x043D\x043E\x043F\x0440\x0441\x0442"
U"\x0443\x0444\x0445\x0446\x0447\x0448\x0449\x044A\x044B\x044C\x044D\x044E\x044F\x0451\x0452"
U"\x0453\x0454\x0455\x0456\x0457\x0458\x0459\x045A\x045B\x045C\x045E\x045F\x0461\x0463\x0465"
U"\x0467\x0469\x046B\x046D\x046F\x0471\x0473\x0475\x0477\x0479\x047B\x047D\x047F\x0481\x0491"
U"\x0493\x0495\x0497\x0499\x049B\x049D\x049F\x04A1\x04A3\x04A5\x04A7\x04A9\x04AB\x04AD\x04AF"
U"\x04B1\x04B3\x04B5\x04B7\x04B9\x04BB\x04BD\x04BF\x04C2\x04C4\x04C8\x04CC\x04D1\x04D3\x04D5"
U"\x04D7\x04D9\x04DB\x04DD\x04DF\x04E1\x04E3\x04E5\x04E7\x04E9\x04EB\x04EF\x04F1\x04F3\x04F5"
U"\x04F9\x1EA1\x1EA3\x1EA5\x1EA7\x1EA9\x1EAB\x1EAD\x1EAF\x1EB1\x1EB3\x1EB5\x1EB7\x1EB9\x1EBB"
U"\x1EBD\x1EBF\x1EC1\x1EC3\x1EC5\x1EC7\x1EC9\x1ECB\x1ECD\x1ECF\x1ED1\x1ED3\x1ED5\x1ED7\x1ED9"
U"\x1EDB\x1EDD\x1EDF\x1EE1\x1EE3\x1EE5\x1EE7\x1EE9\x1EEB\x1EED\x1EEF\x1EF1\x1EF3\x1EF5\x1EF7"
U"\x1EF9\x1F00\x1F01\x1F02\x1F03\x1F04\x1F05\x1F06\x1F07\x1F10\x1F11\x1F12\x1F13\x1F14\x1F15"
U"\x1F20\x1F21\x1F22\x1F23\x1F24\x1F25\x1F26\x1F27\x1F30\x1F31\x1F32\x1F33\x1F34\x1F35\x1F36"
U"\x1F37\x1F40\x1F41\x1F42\x1F43\x1F44\x1F45\x1F51\x1F53\x1F55\x1F57\x1F60\x1F61\x1F62\x1F63"
U"\x1F64\x1F65\x1F66\x1F67\x1F80\x1F81\x1F82\x1F83\x1F84\x1F85\x1F86\x1F87\x1F90\x1F91\x1F92"
U"\x1F93\x1F94\x1F95\x1F96\x1F97\x1FA0\x1FA1\x1FA2\x1FA3\x1FA4\x1FA5\x1FA6\x1FA7\x1FB0\x1FB1"
U"\x1FD0\x1FD1\x1FE0\x1FE1";
static const char32_t to[] =
U"\x0178\x0139\x013B\x013D\x013F\x0141\x0143\x0145\x0147\x014A\x014C\x014E\x0150\x0152\x0154"
U"\x0156\x0158\x015A\x015C\x015E\x0160\x0162\x0164\x0166\x0168\x016A\x016C\x016E\x0170\x0172"
U"\x0174\x0176\x0179\x017B\x017D\x0182\x0184\x0187\x018B\x0191\x0198\x01A0\x01A2\x01A4\x01A7"
U"\x01AC\x01AF\x01B3\x01B5\x01B8\x01BC\x01C4\x01C7\x01CA\x01CD\x01CF\x01D1\x01D3\x01D5\x01D7"
U"\x01D9\x01DB\x01DE\x01E0\x01E2\x01E4\x01E6\x01E8\x01EA\x01EC\x01EE\x01F1\x01F4\x01FA\x01FC"
U"\x01FE\x0200\x0202\x0204\x0206\x0208\x020A\x020C\x020E\x0210\x0212\x0214\x0216\x0181\x0186"
U"\x018A\x018E\x018F\x0190\x0193\x0194\x0197\x0196\x019C\x019D\x019F\x01A9\x01AE\x01B1\x01B2"
U"\x01B7\x0386\x0388\x0389\x038A\x0391\x0392\x0393\x0394\x0395\x0396\x0397\x0398\x0399\x039A"
U"\x039B\x039C\x039D\x039E\x039F\x03A0\x03A1\x03A3\x03A4\x03A5\x03A6\x03A7\x03A8\x03A9\x03AA"
U"\x03AB\x038C\x038E\x038F\x03E2\x03E4\x03E6\x03E8\x03EA\x03EC\x03EE\x0410\x0411\x0412\x0413"
U"\x0414\x0415\x0416\x0417\x0418\x0419\x041A\x041B\x041C\x041D\x041E\x041F\x0420\x0421\x0422"
U"\x0423\x0424\x0425\x0426\x0427\x0428\x0429\x042A\x042B\x042C\x042D\x042E\x042F\x0401\x0402"
U"\x0403\x0404\x0405\x0406\x0407\x0408\x0409\x040A\x040B\x040C\x040E\x040F\x0460\x0462\x0464"
U"\x0466\x0468\x046A\x046C\x046E\x0470\x0472\x0474\x0476\x0478\x047A\x047C\x047E\x0480\x0490"
U"\x0492\x0494\x0496\x0498\x049A\x049C\x049E\x04A0\x04A2\x04A4\x04A6\x04A8\x04AA\x04AC\x04AE"
U"\x04B0\x04B2\x04B4\x04B6\x04B8\x04BA\x04BC\x04BE\x04C1\x04C3\x04C7\x04CB\x04D0\x04D2\x04D4"
U"\x04D6\x04D8\x04DA\x04DC\x04DE\x04E0\x04E2\x04E4\x04E6\x04E8\x04EA\x04EE\x04F0\x04F2\x04F4"
U"\x04F8\x1EA0\x1EA2\x1EA4\x1EA6\x1EA8\x1EAA\x1EAC\x1EAE\x1EB0\x1EB2\x1EB4\x1EB6\x1EB8\x1EBA"
U"\x1EBC\x1EBE\x1EC0\x1EC2\x1EC4\x1EC6\x1EC8\x1ECA\x1ECC\x1ECE\x1ED0\x1ED2\x1ED4\x1ED6\x1ED8"
U"\x1EDA\x1EDC\x1EDE\x1EE0\x1EE2\x1EE4\x1EE6\x1EE8\x1EEA\x1EEC\x1EEE\x1EF0\x1EF2\x1EF4\x1EF6"
U"\x1EF8\x1F08\x1F09\x1F0A\x1F0B\x1F0C\x1F0D\x1F0E\x1F0F\x1F18\x1F19\x1F1A\x1F1B\x1F1C\x1F1D"
U"\x1F28\x1F29\x1F2A\x1F2B\x1F2C\x1F2D\x1F2E\x1F2F\x1F38\x1F39\x1F3A\x1F3B\x1F3C\x1F3D\x1F3E"
U"\x1F3F\x1F48\x1F49\x1F4A\x1F4B\x1F4C\x1F4D\x1F59\x1F5B\x1F5D\x1F5F\x1F68\x1F69\x1F6A\x1F6B"
U"\x1F6C\x1F6D\x1F6E\x1F6F\x1F88\x1F89\x1F8A\x1F8B\x1F8C\x1F8D\x1F8E\x1F8F\x1F98\x1F99\x1F9A"
U"\x1F9B\x1F9C\x1F9D\x1F9E\x1F9F\x1FA8\x1FA9\x1FAA\x1FAB\x1FAC\x1FAD\x1FAE\x1FAF\x1FB8\x1FB9"
U"\x1FD8\x1FD9\x1FE8\x1FE9";
if (wc >= from[0] && wc <= from[ARRAY_SIZE(from) - 2]) {
/* Binary search since these are sorted. */
int min = 0;
int max = ARRAY_SIZE(from) - 2;
while (max >= min) {
const int mid = (min + max) / 2;
if (wc > from[mid]) {
min = mid + 1;
}
else if (wc < from[mid]) {
max = mid - 1;
}
else {
return to[mid];
}
}
}
return wc;
}
char32_t BLI_str_utf32_char_to_lower(char32_t wc)
{
if (wc < U'\xD8') { /* Latin. */
if ((wc <= U'Z' && wc >= U'A') || (wc <= U'\xD6' && wc >= U'\xC0')) {
return wc + 32;
}
return wc;
}
if ((wc <= U'\x136' && wc >= U'\x100') || (wc <= U'\x1E94' && wc >= U'\x1E00')) {
/* Latin Extended. */
return (wc % 2 == 0) ? wc + 1 : wc;
}
if ((wc <= U'\x556' && wc >= U'\x531') || (wc <= U'\x10C5' && wc >= U'\x10A0')) {
/* Armenian and Georgian. */
return wc + 48;
}
if (wc <= U'\x24CF' && wc >= U'\x24B6') { /* Enclosed Numerals. */
return wc + 26;
}
if (wc <= U'\xFF3A' && wc >= U'\xFF21') { /* Fullwidth Forms. */
return wc + 32;
}
/* There are only three remaining ranges that contain capitalization. */
if (!(wc <= U'\x0216' && wc >= U'\x00D8') && !(wc <= U'\x04F8' && wc >= U'\x0386') &&
!(wc <= U'\x1FE9' && wc >= U'\x1E00')) {
return wc;
}
static const char32_t from[] =
U"\x00D8\x00D9\x00DA\x00DB\x00DC\x00DD\x00DE\x0139\x013B\x013D\x013F\x0141\x0143\x0145\x0147"
U"\x014A\x014C\x014E\x0150\x0152\x0154\x0156\x0158\x015A\x015C\x015E\x0160\x0162\x0164\x0166"
U"\x0168\x016A\x016C\x016E\x0170\x0172\x0174\x0176\x0178\x0179\x017B\x017D\x0181\x0182\x0184"
U"\x0186\x0187\x018A\x018B\x018E\x018F\x0190\x0191\x0193\x0194\x0196\x0197\x0198\x019C\x019D"
U"\x019F\x01A0\x01A2\x01A4\x01A7\x01A9\x01AC\x01AE\x01AF\x01B1\x01B2\x01B3\x01B5\x01B7\x01B8"
U"\x01BC\x01C4\x01C5\x01C7\x01C8\x01CA\x01CB\x01CD\x01CF\x01D1\x01D3\x01D5\x01D7\x01D9\x01DB"
U"\x01DE\x01E0\x01E2\x01E4\x01E6\x01E8\x01EA\x01EC\x01EE\x01F1\x01F4\x01FA\x01FC\x01FE\x0200"
U"\x0202\x0204\x0206\x0208\x020A\x020C\x020E\x0210\x0212\x0214\x0216\x0386\x0388\x0389\x038A"
U"\x038C\x038E\x038F\x0391\x0392\x0393\x0394\x0395\x0396\x0397\x0398\x0399\x039A\x039B\x039C"
U"\x039D\x039E\x039F\x03A0\x03A1\x03A3\x03A4\x03A5\x03A6\x03A7\x03A8\x03A9\x03AA\x03AB\x03E2"
U"\x03E4\x03E6\x03E8\x03EA\x03EC\x03EE\x0401\x0402\x0403\x0404\x0405\x0406\x0407\x0408\x0409"
U"\x040A\x040B\x040C\x040E\x040F\x0410\x0411\x0412\x0413\x0414\x0415\x0416\x0417\x0418\x0419"
U"\x041A\x041B\x041C\x041D\x041E\x041F\x0420\x0421\x0422\x0423\x0424\x0425\x0426\x0427\x0428"
U"\x0429\x042A\x042B\x042C\x042D\x042E\x042F\x0460\x0462\x0464\x0466\x0468\x046A\x046C\x046E"
U"\x0470\x0472\x0474\x0476\x0478\x047A\x047C\x047E\x0480\x0490\x0492\x0494\x0496\x0498\x049A"
U"\x049C\x049E\x04A0\x04A2\x04A4\x04A6\x04A8\x04AA\x04AC\x04AE\x04B0\x04B2\x04B4\x04B6\x04B8"
U"\x04BA\x04BC\x04BE\x04C1\x04C3\x04C7\x04CB\x04D0\x04D2\x04D4\x04D6\x04D8\x04DA\x04DC\x04DE"
U"\x04E0\x04E2\x04E4\x04E6\x04E8\x04EA\x04EE\x04F0\x04F2\x04F4\x04F8\x1EA0\x1EA2\x1EA4\x1EA6"
U"\x1EA8\x1EAA\x1EAC\x1EAE\x1EB0\x1EB2\x1EB4\x1EB6\x1EB8\x1EBA\x1EBC\x1EBE\x1EC0\x1EC2\x1EC4"
U"\x1EC6\x1EC8\x1ECA\x1ECC\x1ECE\x1ED0\x1ED2\x1ED4\x1ED6\x1ED8\x1EDA\x1EDC\x1EDE\x1EE0\x1EE2"
U"\x1EE4\x1EE6\x1EE8\x1EEA\x1EEC\x1EEE\x1EF0\x1EF2\x1EF4\x1EF6\x1EF8\x1F08\x1F09\x1F0A\x1F0B"
U"\x1F0C\x1F0D\x1F0E\x1F0F\x1F18\x1F19\x1F1A\x1F1B\x1F1C\x1F1D\x1F28\x1F29\x1F2A\x1F2B\x1F2C"
U"\x1F2D\x1F2E\x1F2F\x1F38\x1F39\x1F3A\x1F3B\x1F3C\x1F3D\x1F3E\x1F3F\x1F48\x1F49\x1F4A\x1F4B"
U"\x1F4C\x1F4D\x1F59\x1F5B\x1F5D\x1F5F\x1F68\x1F69\x1F6A\x1F6B\x1F6C\x1F6D\x1F6E\x1F6F\x1F88"
U"\x1F89\x1F8A\x1F8B\x1F8C\x1F8D\x1F8E\x1F8F\x1F98\x1F99\x1F9A\x1F9B\x1F9C\x1F9D\x1F9E\x1F9F"
U"\x1FA8\x1FA9\x1FAA\x1FAB\x1FAC\x1FAD\x1FAE\x1FAF\x1FB8\x1FB9\x1FD8\x1FD9\x1FE8\x1FE9";
static const char32_t to[] =
U"\x00F8\x00F9\x00FA\x00FB\x00FC\x00FD\x00FE\x013A\x013C\x013E\x0140\x0142\x0144\x0146\x0148"
U"\x014B\x014D\x014F\x0151\x0153\x0155\x0157\x0159\x015B\x015D\x015F\x0161\x0163\x0165\x0167"
U"\x0169\x016B\x016D\x016F\x0171\x0173\x0175\x0177\x00FF\x017A\x017C\x017E\x0253\x0183\x0185"
U"\x0254\x0188\x0257\x018C\x0258\x0259\x025B\x0192\x0260\x0263\x0269\x0268\x0199\x026f\x0272"
U"\x0275\x01A1\x01A3\x01A5\x01A8\x0283\x01AD\x0288\x01B0\x028A\x028B\x01B4\x01B6\x0292\x01B9"
U"\x01BD\x01C6\x01C6\x01C9\x01C9\x01CC\x01CC\x01CE\x01D0\x01D2\x01D4\x01D6\x01D8\x01DA\x01DC"
U"\x01DF\x01E1\x01E3\x01E5\x01E7\x01E9\x01EB\x01ED\x01EF\x01F3\x01F5\x01FB\x01FD\x01FF\x0201"
U"\x0203\x0205\x0207\x0209\x020B\x020D\x020F\x0211\x0213\x0215\x0217\x03AC\x03AD\x03AE\x03AF"
U"\x03CC\x03CD\x03CE\x03B1\x03B2\x03B3\x03B4\x03B5\x03B6\x03B7\x03B8\x03B9\x03BA\x03BB\x03BC"
U"\x03BD\x03BE\x03BF\x03C0\x03C1\x03C3\x03C4\x03C5\x03C6\x03C7\x03C8\x03C9\x03CA\x03CB\x03E3"
U"\x03E5\x03E7\x03E9\x03EB\x03ED\x03EF\x0451\x0452\x0453\x0454\x0455\x0456\x0457\x0458\x0459"
U"\x045A\x045B\x045C\x045E\x045F\x0430\x0431\x0432\x0433\x0434\x0435\x0436\x0437\x0438\x0439"
U"\x043A\x043B\x043C\x043D\x043E\x043F\x0440\x0441\x0442\x0443\x0444\x0445\x0446\x0447\x0448"
U"\x0449\x044A\x044B\x044C\x044D\x044E\x044F\x0461\x0463\x0465\x0467\x0469\x046B\x046D\x046F"
U"\x0471\x0473\x0475\x0477\x0479\x047B\x047D\x047F\x0481\x0491\x0493\x0495\x0497\x0499\x049B"
U"\x049D\x049F\x04A1\x04A3\x04A5\x04A7\x04A9\x04AB\x04AD\x04AF\x04B1\x04B3\x04B5\x04B7\x04B9"
U"\x04BB\x04BD\x04BF\x04C2\x04C4\x04C8\x04CC\x04D1\x04D3\x04D5\x04D7\x04D9\x04DB\x04DD\x04DF"
U"\x04E1\x04E3\x04E5\x04E7\x04E9\x04EB\x04EF\x04F1\x04F3\x04F5\x04F9\x1EA1\x1EA3\x1EA5\x1EA7"
U"\x1EA9\x1EAB\x1EAD\x1EAF\x1EB1\x1EB3\x1EB5\x1EB7\x1EB9\x1EBB\x1EBD\x1EBF\x1EC1\x1EC3\x1EC5"
U"\x1EC7\x1EC9\x1ECB\x1ECD\x1ECF\x1ED1\x1ED3\x1ED5\x1ED7\x1ED9\x1EDB\x1EDD\x1EDF\x1EE1\x1EE3"
U"\x1EE5\x1EE7\x1EE9\x1EEB\x1EED\x1EEF\x1EF1\x1EF3\x1EF5\x1EF7\x1EF9\x1F00\x1F01\x1F02\x1F03"
U"\x1F04\x1F05\x1F06\x1F07\x1F10\x1F11\x1F12\x1F13\x1F14\x1F15\x1F20\x1F21\x1F22\x1F23\x1F24"
U"\x1F25\x1F26\x1F27\x1F30\x1F31\x1F32\x1F33\x1F34\x1F35\x1F36\x1F37\x1F40\x1F41\x1F42\x1F43"
U"\x1F44\x1F45\x1F51\x1F53\x1F55\x1F57\x1F60\x1F61\x1F62\x1F63\x1F64\x1F65\x1F66\x1F67\x1F80"
U"\x1F81\x1F82\x1F83\x1F84\x1F85\x1F86\x1F87\x1F90\x1F91\x1F92\x1F93\x1F94\x1F95\x1F96\x1F97"
U"\x1FA0\x1FA1\x1FA2\x1FA3\x1FA4\x1FA5\x1FA6\x1FA7\x1FB0\x1FB1\x1FD0\x1FD1\x1FE0\x1FE1";
if (wc >= from[0] && wc <= from[ARRAY_SIZE(from) - 2]) {
/* Binary search since these are sorted. */
int min = 0;
int max = ARRAY_SIZE(from) - 2;
while (max >= min) {
const int mid = (min + max) / 2;
if (wc > from[mid]) {
min = mid + 1;
}
else if (wc < from[mid]) {
max = mid - 1;
}
else {
return to[mid];
}
}
}
return wc;
}
/* -------------------------------------------------------------------- */
/* copied from glib's gutf8.c, added 'Err' arg */

View File

@ -25,35 +25,35 @@ enum {
* Arbitrary allocated memory
* (typically owned by #ID's, will be freed when there are no users).
*/
DATA = BLEND_MAKE_ID('D', 'A', 'T', 'A'),
BLO_CODE_DATA = BLEND_MAKE_ID('D', 'A', 'T', 'A'),
/**
* Used for #Global struct.
*/
GLOB = BLEND_MAKE_ID('G', 'L', 'O', 'B'),
BLO_CODE_GLOB = BLEND_MAKE_ID('G', 'L', 'O', 'B'),
/**
* Used for storing the encoded SDNA string
* (decoded into an #SDNA on load).
*/
DNA1 = BLEND_MAKE_ID('D', 'N', 'A', '1'),
BLO_CODE_DNA1 = BLEND_MAKE_ID('D', 'N', 'A', '1'),
/**
* Used to store thumbnail previews, written between #REND and #GLOB blocks,
* (ignored for regular file reading).
*/
TEST = BLEND_MAKE_ID('T', 'E', 'S', 'T'),
BLO_CODE_TEST = BLEND_MAKE_ID('T', 'E', 'S', 'T'),
/**
* Used for #RenderInfo, basic Scene and frame range info,
* can be easily read by other applications without writing a full blend file parser.
*/
REND = BLEND_MAKE_ID('R', 'E', 'N', 'D'),
BLO_CODE_REND = BLEND_MAKE_ID('R', 'E', 'N', 'D'),
/**
* Used for #UserDef, (user-preferences data).
* (written to #BLENDER_STARTUP_FILE & #BLENDER_USERPREF_FILE).
*/
USER = BLEND_MAKE_ID('U', 'S', 'E', 'R'),
BLO_CODE_USER = BLEND_MAKE_ID('U', 'S', 'E', 'R'),
/**
* Terminate reading (no data).
*/
ENDB = BLEND_MAKE_ID('E', 'N', 'D', 'B'),
BLO_CODE_ENDB = BLEND_MAKE_ID('E', 'N', 'D', 'B'),
};
#define BLEN_THUMB_MEMSIZE_FILE(_x, _y) (sizeof(int) * (2 + (size_t)(_x) * (size_t)(_y)))

View File

@ -89,7 +89,7 @@ void BLO_blendhandle_print_sizes(BlendHandle *bh, void *fp)
fprintf(static_cast<FILE *>(fp), "[\n");
for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
if (bhead->code == ENDB) {
if (bhead->code == BLO_CODE_ENDB) {
break;
}
@ -137,7 +137,7 @@ LinkNode *BLO_blendhandle_get_datablock_names(BlendHandle *bh,
BLI_linklist_prepend(&names, BLI_strdup(idname + 2));
tot++;
}
else if (bhead->code == ENDB) {
else if (bhead->code == BLO_CODE_ENDB) {
break;
}
}
@ -159,7 +159,7 @@ LinkNode *BLO_blendhandle_get_datablock_info(BlendHandle *bh,
const int sdna_nr_preview_image = DNA_struct_find_nr(fd->filesdna, "PreviewImage");
for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
if (bhead->code == ENDB) {
if (bhead->code == BLO_CODE_ENDB) {
break;
}
if (bhead->code == ofblocktype) {
@ -190,7 +190,7 @@ LinkNode *BLO_blendhandle_get_datablock_info(BlendHandle *bh,
bool has_preview = false;
/* See if we can find a preview in the data of this ID. */
for (BHead *data_bhead = blo_bhead_next(fd, id_bhead); data_bhead->code == DATA;
for (BHead *data_bhead = blo_bhead_next(fd, id_bhead); data_bhead->code == BLO_CODE_DATA;
data_bhead = blo_bhead_next(fd, data_bhead)) {
if (data_bhead->SDNAnr == sdna_nr_preview_image) {
has_preview = true;
@ -260,7 +260,7 @@ PreviewImage *BLO_blendhandle_get_preview_for_id(BlendHandle *bh,
const int sdna_preview_image = DNA_struct_find_nr(fd->filesdna, "PreviewImage");
for (BHead *bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
if (bhead->code == DATA) {
if (bhead->code == BLO_CODE_DATA) {
if (looking && bhead->SDNAnr == sdna_preview_image) {
PreviewImage *preview_from_file = static_cast<PreviewImage *>(
BLO_library_read_struct(fd, bhead, "PreviewImage"));
@ -275,7 +275,7 @@ PreviewImage *BLO_blendhandle_get_preview_for_id(BlendHandle *bh,
return result;
}
}
else if (looking || bhead->code == ENDB) {
else if (looking || bhead->code == BLO_CODE_ENDB) {
/* We were looking for a preview image, but didn't find any belonging to block. So it doesn't
* exist. */
break;
@ -324,7 +324,7 @@ LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *r_
break;
}
}
else if (bhead->code == DATA) {
else if (bhead->code == BLO_CODE_DATA) {
if (looking) {
if (bhead->SDNAnr == DNA_struct_find_nr(fd->filesdna, "PreviewImage")) {
prv = static_cast<PreviewImage *>(BLO_library_read_struct(fd, bhead, "PreviewImage"));
@ -337,7 +337,7 @@ LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *r_
}
}
}
else if (bhead->code == ENDB) {
else if (bhead->code == BLO_CODE_ENDB) {
break;
}
else {
@ -359,7 +359,7 @@ LinkNode *BLO_blendhandle_get_linkable_groups(BlendHandle *bh)
BHead *bhead;
for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
if (bhead->code == ENDB) {
if (bhead->code == BLO_CODE_ENDB) {
break;
}
if (BKE_idtype_idcode_is_valid(bhead->code)) {

View File

@ -199,7 +199,7 @@ struct BHeadN {
* We could change this in the future, for now it's simplest if only data is delayed
* because ID names are used in lookup tables.
*/
#define BHEAD_USE_READ_ON_DEMAND(bhead) ((bhead)->code == DATA)
#define BHEAD_USE_READ_ON_DEMAND(bhead) ((bhead)->code == BLO_CODE_DATA)
void BLO_reportf_wrap(BlendFileReadReport *reports, eReportType type, const char *format, ...)
{
@ -423,7 +423,7 @@ static void read_file_version(FileData *fd, Main *main)
BHead *bhead;
for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
if (bhead->code == GLOB) {
if (bhead->code == BLO_CODE_GLOB) {
FileGlobal *fg = static_cast<FileGlobal *>(read_struct(fd, bhead, "Global"));
if (fg) {
main->subversionfile = fg->subversion;
@ -431,7 +431,7 @@ static void read_file_version(FileData *fd, Main *main)
main->minsubversionfile = fg->minsubversion;
MEM_freeN(fg);
}
else if (bhead->code == ENDB) {
else if (bhead->code == BLO_CODE_ENDB) {
break;
}
}
@ -466,7 +466,7 @@ static void read_file_bhead_idname_map_create(FileData *fd)
/* dummy values */
bool is_link = false;
int code_prev = ENDB;
int code_prev = BLO_CODE_ENDB;
uint reserve = 0;
for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
@ -595,7 +595,7 @@ static void switch_endian_bh4(BHead4 *bhead)
bhead->code >>= 16;
}
if (bhead->code != ENDB) {
if (bhead->code != BLO_CODE_ENDB) {
BLI_endian_switch_int32(&bhead->len);
BLI_endian_switch_int32(&bhead->SDNAnr);
BLI_endian_switch_int32(&bhead->nr);
@ -609,7 +609,7 @@ static void switch_endian_bh8(BHead8 *bhead)
bhead->code >>= 16;
}
if (bhead->code != ENDB) {
if (bhead->code != BLO_CODE_ENDB) {
BLI_endian_switch_int32(&bhead->len);
BLI_endian_switch_int32(&bhead->SDNAnr);
BLI_endian_switch_int32(&bhead->nr);
@ -624,7 +624,7 @@ static void bh4_from_bh8(BHead *bhead, BHead8 *bhead8, bool do_endian_swap)
bhead4->code = bhead8->code;
bhead4->len = bhead8->len;
if (bhead4->code != ENDB) {
if (bhead4->code != BLO_CODE_ENDB) {
/* perform a endian swap on 64bit pointers, otherwise the pointer might map to zero
* 0x0000000000000000000012345678 would become 0x12345678000000000000000000000000
*/
@ -649,7 +649,7 @@ static void bh8_from_bh4(BHead *bhead, BHead4 *bhead4)
bhead8->code = bhead4->code;
bhead8->len = bhead4->len;
if (bhead8->code != ENDB) {
if (bhead8->code != BLO_CODE_ENDB) {
bhead8->old = bhead4->old;
bhead8->SDNAnr = bhead4->SDNAnr;
bhead8->nr = bhead4->nr;
@ -677,10 +677,10 @@ static BHeadN *get_bhead(FileData *fd)
* needs some special handling. We don't want to EOF just yet.
*/
if (fd->flags & FD_FLAGS_FILE_POINTSIZE_IS_4) {
bhead4.code = DATA;
bhead4.code = BLO_CODE_DATA;
readsize = fd->file->read(fd->file, &bhead4, sizeof(bhead4));
if (readsize == sizeof(bhead4) || bhead4.code == ENDB) {
if (readsize == sizeof(bhead4) || bhead4.code == BLO_CODE_ENDB) {
if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
switch_endian_bh4(&bhead4);
}
@ -700,10 +700,10 @@ static BHeadN *get_bhead(FileData *fd)
}
}
else {
bhead8.code = DATA;
bhead8.code = BLO_CODE_DATA;
readsize = fd->file->read(fd->file, &bhead8, sizeof(bhead8));
if (readsize == sizeof(bhead8) || bhead8.code == ENDB) {
if (readsize == sizeof(bhead8) || bhead8.code == BLO_CODE_ENDB) {
if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
switch_endian_bh8(&bhead8);
}
@ -957,7 +957,7 @@ static bool read_file_dna(FileData *fd, const char **r_error_message)
int subversion = 0;
for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
if (bhead->code == GLOB) {
if (bhead->code == BLO_CODE_GLOB) {
/* Before this, the subversion didn't exist in 'FileGlobal' so the subversion
* value isn't accessible for the purpose of DNA versioning in this case. */
if (fd->fileversion <= 242) {
@ -972,7 +972,7 @@ static bool read_file_dna(FileData *fd, const char **r_error_message)
num[4] = 0;
subversion = atoi(num);
}
else if (bhead->code == DNA1) {
else if (bhead->code == BLO_CODE_DNA1) {
const bool do_endian_swap = (fd->flags & FD_FLAGS_SWITCH_ENDIAN) != 0;
fd->filesdna = DNA_sdna_from_data(
@ -993,7 +993,7 @@ static bool read_file_dna(FileData *fd, const char **r_error_message)
return false;
}
else if (bhead->code == ENDB) {
else if (bhead->code == BLO_CODE_ENDB) {
break;
}
}
@ -1008,7 +1008,7 @@ static int *read_file_thumbnail(FileData *fd)
int *blend_thumb = nullptr;
for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
if (bhead->code == TEST) {
if (bhead->code == BLO_CODE_TEST) {
const bool do_endian_swap = (fd->flags & FD_FLAGS_SWITCH_ENDIAN) != 0;
int *data = (int *)(bhead + 1);
@ -1033,7 +1033,7 @@ static int *read_file_thumbnail(FileData *fd)
blend_thumb = data;
break;
}
if (bhead->code != REND) {
if (bhead->code != BLO_CODE_REND) {
/* Thumbnail is stored in TEST immediately after first REND... */
break;
}
@ -2952,7 +2952,7 @@ static BHead *read_data_into_datamap(FileData *fd, BHead *bhead, const char *all
{
bhead = blo_bhead_next(fd, bhead);
while (bhead && bhead->code == DATA) {
while (bhead && bhead->code == BLO_CODE_DATA) {
/* The code below is useful for debugging leaks in data read from the blend file.
* Without this the messages only tell us what ID-type the memory came from,
* eg: `Data from OB len 64`, see #dataname.
@ -2995,7 +2995,7 @@ static bool read_libblock_is_identical(FileData *fd, BHead *bhead)
/* Test any other data that is part of ID (logic must match read_data_into_datamap). */
bhead = blo_bhead_next(fd, bhead);
while (bhead && bhead->code == DATA) {
while (bhead && bhead->code == BLO_CODE_DATA) {
if (bhead->len && !BHEADN_FROM_BHEAD(bhead)->is_memchunk_identical) {
return false;
}
@ -3837,16 +3837,16 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
while (bhead) {
switch (bhead->code) {
case DATA:
case DNA1:
case TEST: /* used as preview since 2.5x */
case REND:
case BLO_CODE_DATA:
case BLO_CODE_DNA1:
case BLO_CODE_TEST: /* used as preview since 2.5x */
case BLO_CODE_REND:
bhead = blo_bhead_next(fd, bhead);
break;
case GLOB:
case BLO_CODE_GLOB:
bhead = read_global(bfd, fd, bhead);
break;
case USER:
case BLO_CODE_USER:
if (fd->skip_flags & BLO_READ_SKIP_USERDEF) {
bhead = blo_bhead_next(fd, bhead);
}
@ -3854,7 +3854,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
bhead = read_userdef(bfd, fd, bhead);
}
break;
case ENDB:
case BLO_CODE_ENDB:
bhead = nullptr;
break;

View File

@ -841,7 +841,7 @@ static void write_renderinfo(WriteData *wd, Main *mainvar)
BLI_strncpy(data.scene_name, sce->id.name + 2, sizeof(data.scene_name));
writedata(wd, REND, sizeof(data), &data);
writedata(wd, BLO_CODE_REND, sizeof(data), &data);
}
}
}
@ -856,7 +856,7 @@ static void write_keymapitem(BlendWriter *writer, const wmKeyMapItem *kmi)
static void write_userdef(BlendWriter *writer, const UserDef *userdef)
{
writestruct(writer->wd, USER, UserDef, 1, userdef);
writestruct(writer->wd, BLO_CODE_USER, UserDef, 1, userdef);
LISTBASE_FOREACH (const bTheme *, btheme, &userdef->themes) {
BLO_write_struct(writer, bTheme, btheme);
@ -1063,7 +1063,7 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar)
fg.build_commit_timestamp = 0;
BLI_strncpy(fg.build_hash, "unknown", sizeof(fg.build_hash));
#endif
writestruct(wd, GLOB, FileGlobal, 1, &fg);
writestruct(wd, BLO_CODE_GLOB, FileGlobal, 1, &fg);
}
/**
@ -1074,7 +1074,7 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar)
static void write_thumb(WriteData *wd, const BlendThumbnail *thumb)
{
if (thumb) {
writedata(wd, TEST, BLEN_THUMB_MEMSIZE_FILE(thumb->width, thumb->height), thumb);
writedata(wd, BLO_CODE_TEST, BLEN_THUMB_MEMSIZE_FILE(thumb->width, thumb->height), thumb);
}
}
@ -1332,11 +1332,11 @@ static bool write_file_handle(Main *mainvar,
*
* Note that we *borrow* the pointer to 'DNAstr',
* so writing each time uses the same address and doesn't cause unnecessary undo overhead. */
writedata(wd, DNA1, size_t(wd->sdna->data_len), wd->sdna->data);
writedata(wd, BLO_CODE_DNA1, size_t(wd->sdna->data_len), wd->sdna->data);
/* end of file */
memset(&bhead, 0, sizeof(BHead));
bhead.code = ENDB;
bhead.code = BLO_CODE_ENDB;
mywrite(wd, &bhead, sizeof(BHead));
blo_join_main(&mainlist);
@ -1569,7 +1569,7 @@ bool BLO_write_file_mem(Main *mainvar, MemFile *compare, MemFile *current, int w
void BLO_write_raw(BlendWriter *writer, size_t size_in_bytes, const void *data_ptr)
{
writedata(writer->wd, DATA, size_in_bytes, data_ptr);
writedata(writer->wd, BLO_CODE_DATA, size_in_bytes, data_ptr);
}
void BLO_write_struct_by_name(BlendWriter *writer, const char *struct_name, const void *data_ptr)
@ -1592,7 +1592,7 @@ void BLO_write_struct_array_by_name(BlendWriter *writer,
void BLO_write_struct_by_id(BlendWriter *writer, int struct_id, const void *data_ptr)
{
writestruct_nr(writer->wd, DATA, struct_id, 1, data_ptr);
writestruct_nr(writer->wd, BLO_CODE_DATA, struct_id, 1, data_ptr);
}
void BLO_write_struct_at_address_by_id(BlendWriter *writer,
@ -1600,7 +1600,8 @@ void BLO_write_struct_at_address_by_id(BlendWriter *writer,
const void *address,
const void *data_ptr)
{
BLO_write_struct_at_address_by_id_with_filecode(writer, DATA, struct_id, address, data_ptr);
BLO_write_struct_at_address_by_id_with_filecode(
writer, BLO_CODE_DATA, struct_id, address, data_ptr);
}
void BLO_write_struct_at_address_by_id_with_filecode(
@ -1614,18 +1615,18 @@ void BLO_write_struct_array_by_id(BlendWriter *writer,
int array_size,
const void *data_ptr)
{
writestruct_nr(writer->wd, DATA, struct_id, array_size, data_ptr);
writestruct_nr(writer->wd, BLO_CODE_DATA, struct_id, array_size, data_ptr);
}
void BLO_write_struct_array_at_address_by_id(
BlendWriter *writer, int struct_id, int array_size, const void *address, const void *data_ptr)
{
writestruct_at_address_nr(writer->wd, DATA, struct_id, array_size, address, data_ptr);
writestruct_at_address_nr(writer->wd, BLO_CODE_DATA, struct_id, array_size, address, data_ptr);
}
void BLO_write_struct_list_by_id(BlendWriter *writer, int struct_id, ListBase *list)
{
writelist_nr(writer->wd, DATA, struct_id, list);
writelist_nr(writer->wd, BLO_CODE_DATA, struct_id, list);
}
void BLO_write_struct_list_by_name(BlendWriter *writer, const char *struct_name, ListBase *list)

View File

@ -167,7 +167,7 @@ OperationNode *ComponentNode::add_operation(const DepsEvalOperationCb &op,
op_node = (OperationNode *)factory->create_node(this->owner->id_orig, "", name);
/* register opnode in this component's operation set */
OperationIDKey key(opcode, name, name_tag);
OperationIDKey key(opcode, op_node->name.c_str(), name_tag);
operations_map->add(key, op_node);
/* Set back-link. */

View File

@ -155,7 +155,7 @@ ComponentNode *IDNode::add_component(NodeType type, const char *name)
comp_node = (ComponentNode *)factory->create_node(this->id_orig, "", name);
/* Register. */
ComponentIDKey key(type, name);
ComponentIDKey key(type, comp_node->name.c_str());
components.add_new(key, comp_node);
comp_node->owner = this;
}

View File

@ -33,6 +33,8 @@
#include "BKE_report.h"
#include "BKE_vfont.h"
#include "BLI_string_utf8.h"
#include "BLT_translation.h"
#include "DEG_depsgraph.h"
@ -1972,33 +1974,16 @@ static const EnumPropertyItem case_items[] = {
static int set_case(bContext *C, int ccase)
{
Object *obedit = CTX_data_edit_object(C);
Curve *cu = obedit->data;
EditFont *ef = cu->editfont;
char32_t *str;
int len;
int selstart, selend;
if (BKE_vfont_select_get(obedit, &selstart, &selend)) {
len = (selend - selstart) + 1;
str = &ef->textbuf[selstart];
while (len) {
if (*str >= 'a' && *str <= 'z') {
*str -= 32;
}
len--;
str++;
}
Curve *cu = (Curve *)obedit->data;
EditFont *ef = cu->editfont;
char32_t *str = &ef->textbuf[selstart];
if (ccase == CASE_LOWER) {
len = (selend - selstart) + 1;
str = &ef->textbuf[selstart];
while (len) {
if (*str >= 'A' && *str <= 'Z') {
*str += 32;
}
len--;
str++;
}
for (int len = (selend - selstart) + 1; len; len--, str++) {
*str = (ccase == CASE_LOWER) ? BLI_str_utf32_char_to_lower(*str) :
BLI_str_utf32_char_to_upper(*str);
}
text_update_edited(C, obedit, FO_EDIT);

View File

@ -99,8 +99,14 @@ void MTLFrameBuffer::bind(bool enabled_srgb)
return;
}
/* Ensure local MTLAttachment data is up to date. */
this->update_attachments(true);
/* Ensure local MTLAttachment data is up to date.
* NOTE: We only refresh viewport/scissor region when attachments are updated during bind.
* This is to ensure state is consistent with the OpenGL backend. */
if (dirty_attachments_) {
this->update_attachments(true);
this->viewport_reset();
this->scissor_reset();
}
/* Ensure SRGB state is up-to-date and valid. */
bool srgb_state_changed = enabled_srgb_ != enabled_srgb;
@ -465,6 +471,11 @@ void MTLFrameBuffer::read(eGPUFrameBufferBits planes,
BLI_assert(area[2] > 0);
BLI_assert(area[3] > 0);
/* Early exit if requested read region area is zero. */
if (area[2] <= 0 || area[3] <= 0) {
return;
}
switch (planes) {
case GPU_DEPTH_BIT: {
if (this->has_depth_attachment()) {
@ -742,10 +753,6 @@ void MTLFrameBuffer::update_attachments(bool update_viewport)
height_ = 0;
}
/* Reset viewport and Scissor. */
this->viewport_reset();
this->scissor_reset();
/* We have now updated our internal structures. */
dirty_attachments_ = false;
}
@ -760,15 +767,18 @@ void MTLFrameBuffer::apply_state()
}
/* Ensure viewport has been set. NOTE: This should no longer happen, but kept for safety to
* track bugs. */
if (viewport_[2] == 0 || viewport_[3] == 0) {
* track bugs. If viewport size is zero, use framebuffer size. */
int viewport_w = viewport_[2];
int viewport_h = viewport_[3];
if (viewport_w == 0 || viewport_h == 0) {
MTL_LOG_WARNING(
"Viewport had width and height of (0,0) -- Updating -- DEBUG Safety check\n");
viewport_reset();
viewport_w = width_;
viewport_h = height_;
}
/* Update Context State. */
mtl_ctx->set_viewport(viewport_[0], viewport_[1], viewport_[2], viewport_[3]);
mtl_ctx->set_viewport(viewport_[0], viewport_[1], viewport_w, viewport_h);
mtl_ctx->set_scissor(scissor_[0], scissor_[1], scissor_[2], scissor_[3]);
mtl_ctx->set_scissor_enabled(scissor_test_);
@ -895,8 +905,6 @@ bool MTLFrameBuffer::add_color_attachment(gpu::MTLTexture *texture,
if (width_ == 0 || height_ == 0) {
this->size_set(width_of_miplayer, height_of_miplayer);
this->scissor_reset();
this->viewport_reset();
BLI_assert(width_ > 0);
BLI_assert(height_ > 0);
}
@ -1017,8 +1025,6 @@ bool MTLFrameBuffer::add_depth_attachment(gpu::MTLTexture *texture, int miplevel
/* Update Frame-buffer Resolution. */
if (width_ == 0 || height_ == 0) {
this->size_set(width_of_miplayer, height_of_miplayer);
this->scissor_reset();
this->viewport_reset();
BLI_assert(width_ > 0);
BLI_assert(height_ > 0);
}
@ -1139,8 +1145,6 @@ bool MTLFrameBuffer::add_stencil_attachment(gpu::MTLTexture *texture, int miplev
/* Update Frame-buffer Resolution. */
if (width_ == 0 || height_ == 0) {
this->size_set(width_of_miplayer, height_of_miplayer);
this->scissor_reset();
this->viewport_reset();
BLI_assert(width_ > 0);
BLI_assert(height_ > 0);
}
@ -1225,10 +1229,8 @@ void MTLFrameBuffer::ensure_render_target_size()
if (colour_attachment_count_ == 0 && !this->has_depth_attachment() &&
!this->has_stencil_attachment()) {
/* Reset Viewport and Scissor for NULL framebuffer. */
/* Reset size for empty framebuffer. */
this->size_set(0, 0);
this->scissor_reset();
this->viewport_reset();
}
}