WIP: Brush assets project #106303
|
@ -722,9 +722,9 @@ set(UNIFIED_RUNTIME_FILE unified-runtime-${UNIFIED_RUNTIME_VERSION}.tar.gz)
|
|||
# compiler, the versions used are taken from the following location
|
||||
# https://github.com/intel/intel-graphics-compiler/releases
|
||||
|
||||
set(IGC_VERSION 1.0.14828.26)
|
||||
set(IGC_VERSION 1.0.15468.25)
|
||||
set(IGC_URI https://github.com/intel/intel-graphics-compiler/archive/refs/tags/igc-${IGC_VERSION}.tar.gz)
|
||||
set(IGC_HASH acad90b3e149cf87875e6b9100152f9e7644d6cc79ed54eaf52698abdb42076c)
|
||||
set(IGC_HASH c2c36af98ead4f4f6975633eaa53f45b84cb96ce48d9bfa879bebfaf12367b79)
|
||||
set(IGC_HASH_TYPE SHA256)
|
||||
set(IGC_FILE igc-${IGC_VERSION}.tar.gz)
|
||||
|
||||
|
@ -768,9 +768,9 @@ set(IGC_SPIRV_TOOLS_HASH 327b2dba4515646eee28c1a5fe1332891e81c8b6ff289363f52877f
|
|||
set(IGC_SPIRV_TOOLS_HASH_TYPE SHA256)
|
||||
set(IGC_SPIRV_TOOLS_FILE SPIR-V-Tools-${IGC_SPIRV_TOOLS_VERSION}.tar.gz)
|
||||
|
||||
set(IGC_SPIRV_TRANSLATOR_VERSION 23f398bf369093b1fd67459db8071ffcc6b92658)
|
||||
set(IGC_SPIRV_TRANSLATOR_VERSION 7e332d0acc8ee57462d9fbedefaf411fc193fdd0)
|
||||
set(IGC_SPIRV_TRANSLATOR_URI https://github.com/KhronosGroup/SPIRV-LLVM-Translator/archive/${IGC_SPIRV_TRANSLATOR_VERSION}.tar.gz)
|
||||
set(IGC_SPIRV_TRANSLATOR_HASH a96447656ff6b40d9ad286524e22f4e7319d439c54136026fe72550d1162cd35)
|
||||
set(IGC_SPIRV_TRANSLATOR_HASH 29aadf5fd4e64ff1d4f86446eacd6a7439efeb280478988c36314c4441072c36)
|
||||
set(IGC_SPIRV_TRANSLATOR_HASH_TYPE SHA256)
|
||||
set(IGC_SPIRV_TRANSLATOR_FILE SPIR-V-Translator-${IGC_SPIRV_TRANSLATOR_VERSION}.tar.gz)
|
||||
|
||||
|
@ -778,15 +778,15 @@ set(IGC_SPIRV_TRANSLATOR_FILE SPIR-V-Translator-${IGC_SPIRV_TRANSLATOR_VERSION}.
|
|||
### Intel Graphics Compiler DEPS END ###
|
||||
########################################
|
||||
|
||||
set(GMMLIB_VERSION intel-gmmlib-22.3.0)
|
||||
set(GMMLIB_VERSION intel-gmmlib-22.3.11)
|
||||
set(GMMLIB_URI https://github.com/intel/gmmlib/archive/refs/tags/${GMMLIB_VERSION}.tar.gz)
|
||||
set(GMMLIB_HASH c1f33e1519edfc527127baeb0436b783430dfd256c643130169a3a71dc86aff9)
|
||||
set(GMMLIB_HASH b97f4e501c1e902a559cbd6597c008a700f4ab8c495680bf1968db99c6547afe)
|
||||
set(GMMLIB_HASH_TYPE SHA256)
|
||||
set(GMMLIB_FILE ${GMMLIB_VERSION}.tar.gz)
|
||||
|
||||
set(OCLOC_VERSION 23.30.26918.47)
|
||||
set(OCLOC_VERSION 23.43.27642.40)
|
||||
set(OCLOC_URI https://github.com/intel/compute-runtime/archive/refs/tags/${OCLOC_VERSION}.tar.gz)
|
||||
set(OCLOC_HASH 9890f29cbf27ce7eb845f3f7711fe8f3b0c4ee2164b77871fe51102548553f8f)
|
||||
set(OCLOC_HASH 67d0c6f3103ff12408a628e14f7170da3e0220313e10799693d576cea7821fe2)
|
||||
set(OCLOC_HASH_TYPE SHA256)
|
||||
set(OCLOC_FILE ocloc-${OCLOC_VERSION}.tar.gz)
|
||||
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
set -e
|
||||
|
||||
if [ `id -u` -ne 0 ]; then
|
||||
echo "This script must be run as root"
|
||||
exit 1
|
||||
echo "This script must be run as root"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Required by: config manager command below to enable powertools.
|
||||
|
@ -47,8 +47,6 @@ PACKAGES_FOR_LIBS=(
|
|||
# Used to checkout Blender's code.
|
||||
git
|
||||
git-lfs
|
||||
# Used to checkout Blender's `../lib/` directory.
|
||||
subversion
|
||||
# Used to extract packages.
|
||||
bzip2
|
||||
# Used to extract packages.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
Project: Audaspace
|
||||
URL: https://github.com/audaspace/audaspace
|
||||
License: Apache 2.0
|
||||
Upstream version: 1.4+ (0d18fe7, 2024 Jan 2)
|
||||
Local modifications: JOSResampleReader default quality set to MEDIUM
|
||||
Upstream version: 1.4+ (ae29ce2, 2024 Feb 26)
|
||||
Local modifications: none
|
||||
|
|
|
@ -560,7 +560,7 @@ AUD_API AUD_Sound* AUD_Sound_rechannel(AUD_Sound* sound, AUD_Channels channels)
|
|||
}
|
||||
}
|
||||
|
||||
AUD_API AUD_Sound* AUD_Sound_resample(AUD_Sound* sound, AUD_SampleRate rate, bool high_quality)
|
||||
AUD_API AUD_Sound* AUD_Sound_resample(AUD_Sound* sound, AUD_SampleRate rate, AUD_ResampleQuality quality)
|
||||
{
|
||||
assert(sound);
|
||||
|
||||
|
@ -570,10 +570,14 @@ AUD_API AUD_Sound* AUD_Sound_resample(AUD_Sound* sound, AUD_SampleRate rate, boo
|
|||
specs.channels = CHANNELS_INVALID;
|
||||
specs.rate = rate;
|
||||
specs.format = FORMAT_INVALID;
|
||||
if(high_quality)
|
||||
return new AUD_Sound(new JOSResample(*sound, specs));
|
||||
else
|
||||
if (quality == AUD_RESAMPLE_QUALITY_FASTEST)
|
||||
{
|
||||
return new AUD_Sound(new LinearResample(*sound, specs));
|
||||
}
|
||||
else
|
||||
{
|
||||
return new AUD_Sound(new JOSResample(*sound, specs, static_cast<ResampleQuality>(quality)));
|
||||
}
|
||||
}
|
||||
catch(Exception&)
|
||||
{
|
||||
|
|
|
@ -300,10 +300,10 @@ extern AUD_API AUD_Sound* AUD_Sound_rechannel(AUD_Sound* sound, AUD_Channels cha
|
|||
* Resamples the sound.
|
||||
* \param sound The sound to resample.
|
||||
* \param rate The new sample rate.
|
||||
* \param high_quality When true use a higher quality but slower resampler.
|
||||
* \param quality Resampling quality vs performance choice.
|
||||
* \return The resampled sound.
|
||||
*/
|
||||
extern AUD_API AUD_Sound* AUD_Sound_resample(AUD_Sound* sound, AUD_SampleRate rate, bool high_quality);
|
||||
extern AUD_API AUD_Sound* AUD_Sound_resample(AUD_Sound* sound, AUD_SampleRate rate, AUD_ResampleQuality quality);
|
||||
|
||||
/**
|
||||
* Reverses a sound. Make sure the sound source can be reversed.
|
||||
|
|
|
@ -270,14 +270,14 @@ AUD_API int AUD_readSound(AUD_Sound* sound, float* buffer, int length, int sampl
|
|||
return length;
|
||||
}
|
||||
|
||||
AUD_API int AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned int length, unsigned int buffersize, const char* filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate, void(*callback)(float, void*), void* data, char* error, size_t errorsize)
|
||||
AUD_API int AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned int length, unsigned int buffersize, const char* filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate, AUD_ResampleQuality quality, void(*callback)(float, void*), void* data, char* error, size_t errorsize)
|
||||
{
|
||||
try
|
||||
{
|
||||
Sequence* f = dynamic_cast<Sequence *>(sound->get());
|
||||
|
||||
f->setSpecs(convCToSpec(specs.specs));
|
||||
std::shared_ptr<IReader> reader = f->createQualityReader();
|
||||
std::shared_ptr<IReader> reader = f->createQualityReader(static_cast<ResampleQuality>(quality));
|
||||
reader->seek(start);
|
||||
std::shared_ptr<IWriter> writer = FileWriter::createWriter(filename, convCToDSpec(specs), static_cast<Container>(format), static_cast<Codec>(codec), bitrate);
|
||||
FileWriter::writeReader(reader, writer, length, buffersize, callback, data);
|
||||
|
@ -295,7 +295,7 @@ AUD_API int AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned int lengt
|
|||
}
|
||||
}
|
||||
|
||||
AUD_API int AUD_mixdown_per_channel(AUD_Sound* sound, unsigned int start, unsigned int length, unsigned int buffersize, const char* filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate, void(*callback)(float, void*), void* data, char* error, size_t errorsize)
|
||||
AUD_API int AUD_mixdown_per_channel(AUD_Sound* sound, unsigned int start, unsigned int length, unsigned int buffersize, const char* filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate, AUD_ResampleQuality quality, void(*callback)(float, void*), void* data, char* error, size_t errorsize)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -329,7 +329,7 @@ AUD_API int AUD_mixdown_per_channel(AUD_Sound* sound, unsigned int start, unsign
|
|||
writers.push_back(FileWriter::createWriter(stream.str(), convCToDSpec(specs), static_cast<Container>(format), static_cast<Codec>(codec), bitrate));
|
||||
}
|
||||
|
||||
std::shared_ptr<IReader> reader = f->createQualityReader();
|
||||
std::shared_ptr<IReader> reader = f->createQualityReader(static_cast<ResampleQuality>(quality));
|
||||
reader->seek(start);
|
||||
FileWriter::writeReader(reader, writers, length, buffersize, callback, data);
|
||||
|
||||
|
@ -346,19 +346,19 @@ AUD_API int AUD_mixdown_per_channel(AUD_Sound* sound, unsigned int start, unsign
|
|||
}
|
||||
}
|
||||
|
||||
AUD_API AUD_Device* AUD_openMixdownDevice(AUD_DeviceSpecs specs, AUD_Sound* sequencer, float volume, double start)
|
||||
AUD_API AUD_Device* AUD_openMixdownDevice(AUD_DeviceSpecs specs, AUD_Sound* sequencer, float volume, AUD_ResampleQuality quality, double start)
|
||||
{
|
||||
try
|
||||
{
|
||||
ReadDevice* device = new ReadDevice(convCToDSpec(specs));
|
||||
device->setQuality(true);
|
||||
device->setQuality(static_cast<ResampleQuality>(quality));
|
||||
device->setVolume(volume);
|
||||
|
||||
Sequence* f = dynamic_cast<Sequence*>(sequencer->get());
|
||||
|
||||
f->setSpecs(convCToSpec(specs.specs));
|
||||
|
||||
AUD_Handle handle = device->play(f->createQualityReader());
|
||||
AUD_Handle handle = device->play(f->createQualityReader(static_cast<ResampleQuality>(quality)));
|
||||
if(handle.get())
|
||||
{
|
||||
handle->seek(start);
|
||||
|
|
|
@ -69,6 +69,7 @@ extern AUD_API int AUD_readSound(AUD_Sound* sound, float* buffer, int length, in
|
|||
* \param format The file's container format.
|
||||
* \param codec The codec used for encoding the audio data.
|
||||
* \param bitrate The bitrate for encoding.
|
||||
* \param quality The resampling quality.
|
||||
* \param callback A callback function that is called periodically during mixdown, reporting progress if length > 0. Can be NULL.
|
||||
* \param data Pass through parameter that is passed to the callback.
|
||||
* \param error String buffer to copy the error message to in case of failure.
|
||||
|
@ -78,7 +79,7 @@ extern AUD_API int AUD_readSound(AUD_Sound* sound, float* buffer, int length, in
|
|||
extern AUD_API int AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned int length,
|
||||
unsigned int buffersize, const char* filename,
|
||||
AUD_DeviceSpecs specs, AUD_Container format,
|
||||
AUD_Codec codec, unsigned int bitrate,
|
||||
AUD_Codec codec, unsigned int bitrate, AUD_ResampleQuality quality,
|
||||
void(*callback)(float, void*), void* data, char* error, size_t errorsize);
|
||||
|
||||
/**
|
||||
|
@ -92,6 +93,7 @@ extern AUD_API int AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned in
|
|||
* \param format The file's container format.
|
||||
* \param codec The codec used for encoding the audio data.
|
||||
* \param bitrate The bitrate for encoding.
|
||||
* \param quality The resampling quality.
|
||||
* \param callback A callback function that is called periodically during mixdown, reporting progress if length > 0. Can be NULL.
|
||||
* \param data Pass through parameter that is passed to the callback.
|
||||
* \param error String buffer to copy the error message to in case of failure.
|
||||
|
@ -101,7 +103,7 @@ extern AUD_API int AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned in
|
|||
extern AUD_API int AUD_mixdown_per_channel(AUD_Sound* sound, unsigned int start, unsigned int length,
|
||||
unsigned int buffersize, const char* filename,
|
||||
AUD_DeviceSpecs specs, AUD_Container format,
|
||||
AUD_Codec codec, unsigned int bitrate,
|
||||
AUD_Codec codec, unsigned int bitrate, AUD_ResampleQuality quality,
|
||||
void(*callback)(float, void*), void* data, char* error, size_t errorsize);
|
||||
|
||||
/**
|
||||
|
@ -109,10 +111,12 @@ extern AUD_API int AUD_mixdown_per_channel(AUD_Sound* sound, unsigned int start,
|
|||
* \param specs Output audio specifications.
|
||||
* \param sequencer The sound scene to mix down.
|
||||
* \param volume The overall mixdown volume.
|
||||
* \param quality The resampling quality.
|
||||
* \param start The start time of the mixdown in the sound scene.
|
||||
* \return The read device for the mixdown.
|
||||
*/
|
||||
extern AUD_API AUD_Device* AUD_openMixdownDevice(AUD_DeviceSpecs specs, AUD_Sound* sequencer, float volume, double start);
|
||||
extern AUD_API AUD_Device* AUD_openMixdownDevice(AUD_DeviceSpecs specs, AUD_Sound* sequencer,
|
||||
float volume, AUD_ResampleQuality quality, double start);
|
||||
|
||||
/**
|
||||
* Initializes audio routines (FFMPEG/JACK if it is enabled).
|
||||
|
|
|
@ -119,6 +119,15 @@ typedef enum
|
|||
AUD_CHANNELS_SURROUND71 = 8 /// 7.1 surround sound.
|
||||
} AUD_Channels;
|
||||
|
||||
/// Resampling algorithm and quality.
|
||||
typedef enum
|
||||
{
|
||||
AUD_RESAMPLE_QUALITY_FASTEST = 0, /// Linear resample, very fast but lowest quality.
|
||||
AUD_RESAMPLE_QUALITY_LOW = 1, /// JOS resample at low quality preset.
|
||||
AUD_RESAMPLE_QUALITY_MEDIUM = 2, /// JOS resample at medium quality preset.
|
||||
AUD_RESAMPLE_QUALITY_HIGH = 3 /// JOS resample at high quality preset.
|
||||
} AUD_ResampleQuality;
|
||||
|
||||
/**
|
||||
* The sample rate tells how many samples are played back within one second.
|
||||
* Some exotic formats may use other sample rates than provided here.
|
||||
|
|
|
@ -1269,12 +1269,12 @@ Sound_rechannel(Sound* self, PyObject* args)
|
|||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Sound_resample_doc,
|
||||
".. method:: resample(rate, high_quality)\n\n"
|
||||
".. method:: resample(rate, quality)\n\n"
|
||||
" Resamples the sound.\n\n"
|
||||
" :arg rate: The new sample rate.\n"
|
||||
" :type rate: double\n"
|
||||
" :arg high_quality: When true use a higher quality but slower resampler.\n"
|
||||
" :type high_quality: bool\n"
|
||||
" :arg quality: Resampler performance vs quality choice (0=fastest, 3=slowest).\n"
|
||||
" :type quality: int\n"
|
||||
" :return: The created :class:`Sound` object.\n"
|
||||
" :rtype: :class:`Sound`");
|
||||
|
||||
|
@ -1282,20 +1282,11 @@ static PyObject *
|
|||
Sound_resample(Sound* self, PyObject* args)
|
||||
{
|
||||
double rate;
|
||||
PyObject* high_qualityo;
|
||||
bool high_quality = false;
|
||||
int quality = 0;
|
||||
|
||||
if(!PyArg_ParseTuple(args, "d|O:resample", &rate, &high_qualityo))
|
||||
if(!PyArg_ParseTuple(args, "d|i:resample", &rate, &quality))
|
||||
return nullptr;
|
||||
|
||||
if(!PyBool_Check(high_qualityo))
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "high_quality is not a boolean!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
high_quality = high_qualityo == Py_True;
|
||||
|
||||
PyTypeObject* type = Py_TYPE(self);
|
||||
Sound* parent = (Sound*)type->tp_alloc(type, 0);
|
||||
|
||||
|
@ -1307,10 +1298,10 @@ Sound_resample(Sound* self, PyObject* args)
|
|||
specs.channels = CHANNELS_INVALID;
|
||||
specs.rate = rate;
|
||||
specs.format = FORMAT_INVALID;
|
||||
if(high_quality)
|
||||
parent->sound = new std::shared_ptr<ISound>(new JOSResample(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), specs));
|
||||
else
|
||||
if (quality == int(ResampleQuality::FASTEST))
|
||||
parent->sound = new std::shared_ptr<ISound>(new LinearResample(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), specs));
|
||||
else
|
||||
parent->sound = new std::shared_ptr<ISound>(new JOSResample(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), specs, static_cast<ResampleQuality>(quality)));
|
||||
}
|
||||
catch(Exception& e)
|
||||
{
|
||||
|
|
|
@ -69,7 +69,7 @@ protected:
|
|||
* @param file The source code file in which the exception was thrown.
|
||||
* @param line The source code line from which the exception was thrown.
|
||||
*/
|
||||
Exception(std::string message, std::string file, int line);
|
||||
Exception(const std::string &message, const std::string &file, int line);
|
||||
public:
|
||||
/**
|
||||
* Destroys the object.
|
||||
|
@ -120,7 +120,7 @@ public:
|
|||
* @param file The source code file in which the exception was thrown.
|
||||
* @param line The source code line from which the exception was thrown.
|
||||
*/
|
||||
FileException(std::string message, std::string file, int line);
|
||||
FileException(const std::string &message, const std::string &file, int line);
|
||||
|
||||
/**
|
||||
* Copy constructor.
|
||||
|
@ -145,7 +145,7 @@ public:
|
|||
* @param file The source code file in which the exception was thrown.
|
||||
* @param line The source code line from which the exception was thrown.
|
||||
*/
|
||||
DeviceException(std::string message, std::string file, int line);
|
||||
DeviceException(const std::string &message, const std::string &file, int line);
|
||||
|
||||
/**
|
||||
* Copy constructor.
|
||||
|
@ -171,7 +171,7 @@ public:
|
|||
* @param file The source code file in which the exception was thrown.
|
||||
* @param line The source code line from which the exception was thrown.
|
||||
*/
|
||||
StateException(std::string message, std::string file, int line);
|
||||
StateException(const std::string &message, const std::string &file, int line);
|
||||
|
||||
/**
|
||||
* Copy constructor.
|
||||
|
|
|
@ -62,14 +62,14 @@ public:
|
|||
* @param name A representative name for the device.
|
||||
* @param factory The factory that creates the device.
|
||||
*/
|
||||
static void registerDevice(std::string name, std::shared_ptr<IDeviceFactory> factory);
|
||||
static void registerDevice(const std::string &name, std::shared_ptr<IDeviceFactory> factory);
|
||||
|
||||
/**
|
||||
* Returns the factory for a specific device.
|
||||
* @param name The representative name of the device.
|
||||
* @return The factory if it was found, or nullptr otherwise.
|
||||
*/
|
||||
static std::shared_ptr<IDeviceFactory> getDeviceFactory(std::string name);
|
||||
static std::shared_ptr<IDeviceFactory> getDeviceFactory(const std::string &name);
|
||||
|
||||
/**
|
||||
* Returns the default device based on the priorities of the registered factories.
|
||||
|
@ -92,7 +92,7 @@ public:
|
|||
* If a device is currently being handled it will be released.
|
||||
* @param name The representative name of the device.
|
||||
*/
|
||||
static void openDevice(std::string name);
|
||||
static void openDevice(const std::string &name);
|
||||
|
||||
/**
|
||||
* Opens the default device which will then be handled by the manager.
|
||||
|
|
|
@ -71,7 +71,7 @@ public:
|
|||
* Sets a name for the device.
|
||||
* \param name The internal name for the device.
|
||||
*/
|
||||
virtual void setName(std::string name)=0;
|
||||
virtual void setName(const std::string &name)=0;
|
||||
};
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
|
|
|
@ -231,9 +231,9 @@ protected:
|
|||
std::shared_ptr<Mixer> m_mixer;
|
||||
|
||||
/**
|
||||
* Whether to do high or low quality resampling.
|
||||
* Resampling quality.
|
||||
*/
|
||||
bool m_quality;
|
||||
ResampleQuality m_quality;
|
||||
|
||||
/**
|
||||
* Initializes member variables.
|
||||
|
@ -347,9 +347,9 @@ public:
|
|||
|
||||
/**
|
||||
* Sets the resampling quality.
|
||||
* \param quality Low (false) or high (true) quality.
|
||||
* \param quality Resampling quality vs performance setting.
|
||||
*/
|
||||
void setQuality(bool quality);
|
||||
void setQuality(ResampleQuality quality);
|
||||
|
||||
virtual DeviceSpecs getSpecs() const;
|
||||
virtual std::shared_ptr<IHandle> play(std::shared_ptr<IReader> reader, bool keep = false);
|
||||
|
|
|
@ -69,7 +69,7 @@ public:
|
|||
* \param filename The sound file path.
|
||||
* \param stream The index of the audio stream within the file if it contains multiple audio streams.
|
||||
*/
|
||||
File(std::string filename, int stream = 0);
|
||||
File(const std::string &filename, int stream = 0);
|
||||
|
||||
/**
|
||||
* Creates a new sound.
|
||||
|
|
|
@ -72,7 +72,7 @@ public:
|
|||
* @return The reader created.
|
||||
* @exception Exception If no file input can read the file an exception is thrown.
|
||||
*/
|
||||
static std::shared_ptr<IReader> createReader(std::string filename, int stream = 0);
|
||||
static std::shared_ptr<IReader> createReader(const std::string &filename, int stream = 0);
|
||||
|
||||
/**
|
||||
* Creates a file reader for the given buffer if a registed IFileInput is able to read it.
|
||||
|
@ -89,7 +89,7 @@ public:
|
|||
* \return A vector with as many streams as there are in the file.
|
||||
* \exception Exception Thrown if the file specified cannot be read.
|
||||
*/
|
||||
static std::vector<StreamInfo> queryStreams(std::string filename);
|
||||
static std::vector<StreamInfo> queryStreams(const std::string &filename);
|
||||
|
||||
/**
|
||||
* Queries the streams of a sound file.
|
||||
|
@ -110,7 +110,7 @@ public:
|
|||
* @return A writer that creates the file.
|
||||
* @exception Exception If no file output can write the file with the given specification an exception is thrown.
|
||||
*/
|
||||
static std::shared_ptr<IWriter> createWriter(std::string filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate);
|
||||
static std::shared_ptr<IWriter> createWriter(const std::string &filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate);
|
||||
};
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
|
|
|
@ -54,7 +54,7 @@ public:
|
|||
* \param bitrate The bitrate for encoding.
|
||||
* \return The writer to write data to.
|
||||
*/
|
||||
static std::shared_ptr<IWriter> createWriter(std::string filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate);
|
||||
static std::shared_ptr<IWriter> createWriter(const std::string &filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate);
|
||||
|
||||
/**
|
||||
* Writes a reader to a writer.
|
||||
|
|
|
@ -54,7 +54,7 @@ public:
|
|||
* \return The reader that reads the file.
|
||||
* \exception Exception Thrown if the file specified cannot be read.
|
||||
*/
|
||||
virtual std::shared_ptr<IReader> createReader(std::string filename, int stream = 0)=0;
|
||||
virtual std::shared_ptr<IReader> createReader(const std::string &filename, int stream = 0)=0;
|
||||
|
||||
/**
|
||||
* Creates a reader for a file to be read from memory.
|
||||
|
@ -71,7 +71,7 @@ public:
|
|||
* \return A vector with as many streams as there are in the file.
|
||||
* \exception Exception Thrown if the file specified cannot be read.
|
||||
*/
|
||||
virtual std::vector<StreamInfo> queryStreams(std::string filename)=0;
|
||||
virtual std::vector<StreamInfo> queryStreams(const std::string &filename)=0;
|
||||
|
||||
/**
|
||||
* Queries the streams of a sound file.
|
||||
|
|
|
@ -46,7 +46,7 @@ public:
|
|||
* \param bitrate The bitrate for encoding.
|
||||
* \exception Exception Thrown if the file specified cannot be written.
|
||||
*/
|
||||
virtual std::shared_ptr<IWriter> createWriter(std::string filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate)=0;
|
||||
virtual std::shared_ptr<IWriter> createWriter(const std::string &filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate)=0;
|
||||
};
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
|
|
|
@ -36,13 +36,15 @@ private:
|
|||
JOSResample(const JOSResample&) = delete;
|
||||
JOSResample& operator=(const JOSResample&) = delete;
|
||||
|
||||
ResampleQuality m_quality;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new sound.
|
||||
* \param sound The input sound.
|
||||
* \param specs The target specifications.
|
||||
*/
|
||||
JOSResample(std::shared_ptr<ISound> sound, DeviceSpecs specs);
|
||||
JOSResample(std::shared_ptr<ISound> sound, DeviceSpecs specs, ResampleQuality quality = ResampleQuality::HIGH);
|
||||
|
||||
virtual std::shared_ptr<IReader> createReader();
|
||||
};
|
||||
|
|
|
@ -36,39 +36,39 @@ private:
|
|||
typedef void (JOSResampleReader::*resample_f)(double target_factor, int length, sample_t* buffer);
|
||||
|
||||
/**
|
||||
* The half filter length for Quality::HIGH setting.
|
||||
* The half filter length for HIGH quality setting.
|
||||
*/
|
||||
static const int m_len_high;
|
||||
/**
|
||||
* The half filter length for Quality::MEDIUM setting.
|
||||
* The half filter length for MEDIUM quality setting.
|
||||
*/
|
||||
static const int m_len_medium;
|
||||
/**
|
||||
* The half filter length for Quality::LOW setting.
|
||||
* The half filter length for LOW quality setting.
|
||||
*/
|
||||
static const int m_len_low;
|
||||
/**
|
||||
* The filter sample step size for Quality::HIGH setting.
|
||||
* The filter sample step size for HIGH quality setting.
|
||||
*/
|
||||
static const int m_L_high;
|
||||
/**
|
||||
* The filter sample step size for Quality::MEDIUM setting.
|
||||
* The filter sample step size for MEDIUM quality setting.
|
||||
*/
|
||||
static const int m_L_medium;
|
||||
/**
|
||||
* The filter sample step size for Quality::LOW setting.
|
||||
* The filter sample step size for LOW quality setting.
|
||||
*/
|
||||
static const int m_L_low;
|
||||
/**
|
||||
* The filter coefficients for Quality::HIGH setting.
|
||||
* The filter coefficients for HIGH quality setting.
|
||||
*/
|
||||
static const float m_coeff_high[];
|
||||
/**
|
||||
* The filter coefficients for Quality::MEDIUM setting.
|
||||
* The filter coefficients for MEDIUM quality setting.
|
||||
*/
|
||||
static const float m_coeff_medium[];
|
||||
/**
|
||||
* The filter coefficients for Quality::LOW setting.
|
||||
* The filter coefficients for LOW quality setting.
|
||||
*/
|
||||
static const float m_coeff_low[];
|
||||
|
||||
|
@ -152,19 +152,13 @@ private:
|
|||
void AUD_LOCAL resample(double target_factor, int length, sample_t* buffer);
|
||||
|
||||
public:
|
||||
enum class Quality
|
||||
{
|
||||
LOW = 0,
|
||||
MEDIUM,
|
||||
HIGH,
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a resampling reader.
|
||||
* \param reader The reader to mix.
|
||||
* \param rate The target sampling rate.
|
||||
*/
|
||||
JOSResampleReader(std::shared_ptr<IReader> reader, SampleRate rate, Quality = Quality::MEDIUM);
|
||||
JOSResampleReader(std::shared_ptr<IReader> reader, SampleRate rate, ResampleQuality quality = ResampleQuality::HIGH);
|
||||
|
||||
virtual void seek(int position);
|
||||
virtual int getLength() const;
|
||||
|
|
|
@ -83,6 +83,15 @@ enum Channel
|
|||
CHANNEL_MAX
|
||||
};
|
||||
|
||||
/// Resampling algorithm and quality.
|
||||
enum class ResampleQuality
|
||||
{
|
||||
FASTEST = 0, /// Linear resample, very fast but lowest quality.
|
||||
LOW, /// JOS resample at low quality preset.
|
||||
MEDIUM, /// JOS resample at medium quality preset.
|
||||
HIGH /// JOS resample at high quality preset.
|
||||
};
|
||||
|
||||
/**
|
||||
* The sample rate tells how many samples are played back within one second.
|
||||
* Some exotic formats may use other sample rates than provided here.
|
||||
|
|
|
@ -160,10 +160,11 @@ public:
|
|||
void remove(std::shared_ptr<SequenceEntry> entry);
|
||||
|
||||
/**
|
||||
* Creates a new reader with high quality resampling.
|
||||
* Creates a new reader with indicated resampling quality.
|
||||
* \param quality The resampling quality.
|
||||
* \return The new reader.
|
||||
*/
|
||||
std::shared_ptr<IReader> createQualityReader();
|
||||
std::shared_ptr<IReader> createQualityReader(ResampleQuality quality);
|
||||
|
||||
virtual std::shared_ptr<IReader> createReader();
|
||||
};
|
||||
|
|
|
@ -74,9 +74,9 @@ public:
|
|||
/**
|
||||
* Creates a resampling reader.
|
||||
* \param sequence The sequence data.
|
||||
* \param quality Whether a high quality resample should be used for resampling.
|
||||
* \param quality Resampling quality vs performance option.
|
||||
*/
|
||||
SequenceReader(std::shared_ptr<SequenceData> sequence, bool quality = false);
|
||||
SequenceReader(std::shared_ptr<SequenceData> sequence, ResampleQuality quality = ResampleQuality::FASTEST);
|
||||
|
||||
/**
|
||||
* Destroys the reader.
|
||||
|
|
|
@ -210,7 +210,7 @@ public:
|
|||
m_buffersize = buffersize;
|
||||
}
|
||||
|
||||
virtual void setName(std::string name)
|
||||
virtual void setName(const std::string &name)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
|
|
@ -35,7 +35,7 @@ void FFMPEG::registerPlugin()
|
|||
FileManager::registerOutput(plugin);
|
||||
}
|
||||
|
||||
std::shared_ptr<IReader> FFMPEG::createReader(std::string filename, int stream)
|
||||
std::shared_ptr<IReader> FFMPEG::createReader(const std::string &filename, int stream)
|
||||
{
|
||||
return std::shared_ptr<IReader>(new FFMPEGReader(filename, stream));
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ std::shared_ptr<IReader> FFMPEG::createReader(std::shared_ptr<Buffer> buffer, in
|
|||
return std::shared_ptr<IReader>(new FFMPEGReader(buffer, stream));
|
||||
}
|
||||
|
||||
std::vector<StreamInfo> FFMPEG::queryStreams(std::string filename)
|
||||
std::vector<StreamInfo> FFMPEG::queryStreams(const std::string &filename)
|
||||
{
|
||||
return FFMPEGReader(filename).queryStreams();
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ std::vector<StreamInfo> FFMPEG::queryStreams(std::shared_ptr<Buffer> buffer)
|
|||
return FFMPEGReader(buffer).queryStreams();
|
||||
}
|
||||
|
||||
std::shared_ptr<IWriter> FFMPEG::createWriter(std::string filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate)
|
||||
std::shared_ptr<IWriter> FFMPEG::createWriter(const std::string &filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate)
|
||||
{
|
||||
return std::shared_ptr<IWriter>(new FFMPEGWriter(filename, specs, format, codec, bitrate));
|
||||
}
|
||||
|
|
|
@ -52,11 +52,11 @@ public:
|
|||
*/
|
||||
static void registerPlugin();
|
||||
|
||||
virtual std::shared_ptr<IReader> createReader(std::string filename, int stream = 0);
|
||||
virtual std::shared_ptr<IReader> createReader(const std::string &filename, int stream = 0);
|
||||
virtual std::shared_ptr<IReader> createReader(std::shared_ptr<Buffer> buffer, int stream = 0);
|
||||
virtual std::vector<StreamInfo> queryStreams(std::string filename);
|
||||
virtual std::vector<StreamInfo> queryStreams(const std::string &filename);
|
||||
virtual std::vector<StreamInfo> queryStreams(std::shared_ptr<Buffer> buffer);
|
||||
virtual std::shared_ptr<IWriter> createWriter(std::string filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate);
|
||||
virtual std::shared_ptr<IWriter> createWriter(const std::string &filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate);
|
||||
};
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
|
|
|
@ -239,7 +239,7 @@ void FFMPEGReader::init(int stream)
|
|||
m_specs.rate = (SampleRate) m_codecCtx->sample_rate;
|
||||
}
|
||||
|
||||
FFMPEGReader::FFMPEGReader(std::string filename, int stream) :
|
||||
FFMPEGReader::FFMPEGReader(const std::string &filename, int stream) :
|
||||
m_pkgbuf(),
|
||||
m_formatCtx(nullptr),
|
||||
m_codecCtx(nullptr),
|
||||
|
|
|
@ -154,7 +154,7 @@ public:
|
|||
* \exception Exception Thrown if the file specified does not exist or
|
||||
* cannot be read with ffmpeg.
|
||||
*/
|
||||
FFMPEGReader(std::string filename, int stream = 0);
|
||||
FFMPEGReader(const std::string &filename, int stream = 0);
|
||||
|
||||
/**
|
||||
* Creates a new reader.
|
||||
|
|
|
@ -158,7 +158,7 @@ void FFMPEGWriter::close()
|
|||
#endif
|
||||
}
|
||||
|
||||
FFMPEGWriter::FFMPEGWriter(std::string filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate) :
|
||||
FFMPEGWriter::FFMPEGWriter(const std::string &filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate) :
|
||||
m_position(0),
|
||||
m_specs(specs),
|
||||
m_formatCtx(nullptr),
|
||||
|
|
|
@ -135,7 +135,7 @@ public:
|
|||
* \exception Exception Thrown if the file specified does not exist or
|
||||
* cannot be read with ffmpeg.
|
||||
*/
|
||||
FFMPEGWriter(std::string filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate);
|
||||
FFMPEGWriter(const std::string &filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate);
|
||||
|
||||
/**
|
||||
* Destroys the writer and closes the file.
|
||||
|
|
|
@ -162,7 +162,7 @@ void JackDevice::jack_shutdown(void* data)
|
|||
device->m_valid = false;
|
||||
}
|
||||
|
||||
JackDevice::JackDevice(std::string name, DeviceSpecs specs, int buffersize) :
|
||||
JackDevice::JackDevice(const std::string &name, DeviceSpecs specs, int buffersize) :
|
||||
m_synchronizer(this)
|
||||
{
|
||||
if(specs.channels == CHANNELS_INVALID)
|
||||
|
@ -358,7 +358,7 @@ public:
|
|||
m_buffersize = buffersize;
|
||||
}
|
||||
|
||||
virtual void setName(std::string name)
|
||||
virtual void setName(const std::string &name)
|
||||
{
|
||||
m_name = name;
|
||||
}
|
||||
|
|
|
@ -151,7 +151,7 @@ public:
|
|||
* \param buffersize The size of the internal buffer.
|
||||
* \exception Exception Thrown if the audio device cannot be opened.
|
||||
*/
|
||||
JackDevice(std::string name, DeviceSpecs specs, int buffersize = AUD_DEFAULT_BUFFER_SIZE);
|
||||
JackDevice(const std::string &name, DeviceSpecs specs, int buffersize = AUD_DEFAULT_BUFFER_SIZE);
|
||||
|
||||
/**
|
||||
* Closes the JACK client.
|
||||
|
|
|
@ -32,7 +32,7 @@ void SndFile::registerPlugin()
|
|||
FileManager::registerOutput(plugin);
|
||||
}
|
||||
|
||||
std::shared_ptr<IReader> SndFile::createReader(std::string filename, int stream)
|
||||
std::shared_ptr<IReader> SndFile::createReader(const std::string &filename, int stream)
|
||||
{
|
||||
return std::shared_ptr<IReader>(new SndFileReader(filename));
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ std::shared_ptr<IReader> SndFile::createReader(std::shared_ptr<Buffer> buffer, i
|
|||
return std::shared_ptr<IReader>(new SndFileReader(buffer));
|
||||
}
|
||||
|
||||
std::vector<StreamInfo> SndFile::queryStreams(std::string filename)
|
||||
std::vector<StreamInfo> SndFile::queryStreams(const std::string &filename)
|
||||
{
|
||||
return SndFileReader(filename).queryStreams();
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ std::vector<StreamInfo> SndFile::queryStreams(std::shared_ptr<Buffer> buffer)
|
|||
return SndFileReader(buffer).queryStreams();
|
||||
}
|
||||
|
||||
std::shared_ptr<IWriter> SndFile::createWriter(std::string filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate)
|
||||
std::shared_ptr<IWriter> SndFile::createWriter(const std::string &filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate)
|
||||
{
|
||||
return std::shared_ptr<IWriter>(new SndFileWriter(filename, specs, format, codec, bitrate));
|
||||
}
|
||||
|
|
|
@ -52,11 +52,11 @@ public:
|
|||
*/
|
||||
static void registerPlugin();
|
||||
|
||||
virtual std::shared_ptr<IReader> createReader(std::string filename, int stream = 0);
|
||||
virtual std::shared_ptr<IReader> createReader(const std::string &filename, int stream = 0);
|
||||
virtual std::shared_ptr<IReader> createReader(std::shared_ptr<Buffer> buffer, int stream = 0);
|
||||
virtual std::vector<StreamInfo> queryStreams(std::string filename);
|
||||
virtual std::vector<StreamInfo> queryStreams(const std::string &filename);
|
||||
virtual std::vector<StreamInfo> queryStreams(std::shared_ptr<Buffer> buffer);
|
||||
virtual std::shared_ptr<IWriter> createWriter(std::string filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate);
|
||||
virtual std::shared_ptr<IWriter> createWriter(const std::string &filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate);
|
||||
};
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
|
|
|
@ -71,7 +71,7 @@ sf_count_t SndFileReader::vio_tell(void* user_data)
|
|||
return reader->m_memoffset;
|
||||
}
|
||||
|
||||
SndFileReader::SndFileReader(std::string filename) :
|
||||
SndFileReader::SndFileReader(const std::string &filename) :
|
||||
m_position(0)
|
||||
{
|
||||
SF_INFO sfinfo;
|
||||
|
|
|
@ -103,7 +103,7 @@ public:
|
|||
* \exception Exception Thrown if the file specified does not exist or
|
||||
* cannot be read with libsndfile.
|
||||
*/
|
||||
SndFileReader(std::string filename);
|
||||
SndFileReader(const std::string &filename);
|
||||
|
||||
/**
|
||||
* Creates a new reader.
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
SndFileWriter::SndFileWriter(std::string filename, DeviceSpecs specs,
|
||||
SndFileWriter::SndFileWriter(const std::string &filename, DeviceSpecs specs,
|
||||
Container format, Codec codec, unsigned int bitrate) :
|
||||
m_position(0), m_specs(specs)
|
||||
{
|
||||
|
|
|
@ -69,7 +69,7 @@ public:
|
|||
* \exception Exception Thrown if the file specified cannot be written
|
||||
* with libsndfile.
|
||||
*/
|
||||
SndFileWriter(std::string filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate);
|
||||
SndFileWriter(const std::string &filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate);
|
||||
|
||||
/**
|
||||
* Destroys the writer and closes the file.
|
||||
|
|
|
@ -1131,7 +1131,7 @@ void OpenALDevice::updateStreams()
|
|||
/**************************** IDevice Code ************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
OpenALDevice::OpenALDevice(DeviceSpecs specs, int buffersize, std::string name) :
|
||||
OpenALDevice::OpenALDevice(DeviceSpecs specs, int buffersize, const std::string &name) :
|
||||
m_name(name), m_playing(false), m_buffersize(buffersize)
|
||||
{
|
||||
// cannot determine how many channels or which format OpenAL uses, but
|
||||
|
@ -1561,7 +1561,7 @@ private:
|
|||
std::string m_name;
|
||||
|
||||
public:
|
||||
OpenALDeviceFactory(std::string name = "") :
|
||||
OpenALDeviceFactory(const std::string &name = "") :
|
||||
m_buffersize(AUD_DEFAULT_BUFFER_SIZE),
|
||||
m_name(name)
|
||||
{
|
||||
|
@ -1590,7 +1590,7 @@ public:
|
|||
m_buffersize = buffersize;
|
||||
}
|
||||
|
||||
virtual void setName(std::string name)
|
||||
virtual void setName(const std::string &name)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -1599,7 +1599,7 @@ void OpenALDevice::registerPlugin()
|
|||
{
|
||||
auto names = OpenALDevice::getDeviceNames();
|
||||
DeviceManager::registerDevice("OpenAL", std::shared_ptr<IDeviceFactory>(new OpenALDeviceFactory));
|
||||
for(std::string &name : names)
|
||||
for(const std::string &name : names)
|
||||
{
|
||||
DeviceManager::registerDevice("OpenAL - " + name, std::shared_ptr<IDeviceFactory>(new OpenALDeviceFactory(name)));
|
||||
}
|
||||
|
|
|
@ -269,7 +269,7 @@ public:
|
|||
* \note The buffersize will be multiplicated by three for this device.
|
||||
* \exception DeviceException Thrown if the audio device cannot be opened.
|
||||
*/
|
||||
OpenALDevice(DeviceSpecs specs, int buffersize = AUD_DEFAULT_BUFFER_SIZE, std::string name = "");
|
||||
OpenALDevice(DeviceSpecs specs, int buffersize = AUD_DEFAULT_BUFFER_SIZE, const std::string &name = "");
|
||||
|
||||
virtual ~OpenALDevice();
|
||||
|
||||
|
|
|
@ -121,7 +121,7 @@ void PulseAudioDevice::playing(bool playing)
|
|||
AUD_pa_threaded_mainloop_unlock(m_mainloop);
|
||||
}
|
||||
|
||||
PulseAudioDevice::PulseAudioDevice(std::string name, DeviceSpecs specs, int buffersize) :
|
||||
PulseAudioDevice::PulseAudioDevice(const std::string &name, DeviceSpecs specs, int buffersize) :
|
||||
m_synchronizer(this),
|
||||
m_playback(false),
|
||||
m_state(PA_CONTEXT_UNCONNECTED),
|
||||
|
@ -321,7 +321,7 @@ public:
|
|||
m_buffersize = buffersize;
|
||||
}
|
||||
|
||||
virtual void setName(std::string name)
|
||||
virtual void setName(const std::string &name)
|
||||
{
|
||||
m_name = name;
|
||||
}
|
||||
|
|
|
@ -128,7 +128,7 @@ public:
|
|||
* \note The specification really used for opening the device may differ.
|
||||
* \exception Exception Thrown if the audio device cannot be opened.
|
||||
*/
|
||||
PulseAudioDevice(std::string name, DeviceSpecs specs, int buffersize = AUD_DEFAULT_BUFFER_SIZE);
|
||||
PulseAudioDevice(const std::string &name, DeviceSpecs specs, int buffersize = AUD_DEFAULT_BUFFER_SIZE);
|
||||
|
||||
/**
|
||||
* Closes the PulseAudio audio device.
|
||||
|
|
|
@ -157,7 +157,7 @@ public:
|
|||
m_buffersize = buffersize;
|
||||
}
|
||||
|
||||
virtual void setName(std::string name)
|
||||
virtual void setName(const std::string &name)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
|
|
@ -458,7 +458,7 @@ public:
|
|||
m_buffersize = buffersize;
|
||||
}
|
||||
|
||||
virtual void setName(std::string name)
|
||||
virtual void setName(const std::string &name)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
|
|
@ -25,7 +25,7 @@ Exception::Exception(const Exception& exception) :
|
|||
{
|
||||
}
|
||||
|
||||
Exception::Exception(std::string message, std::string file, int line) :
|
||||
Exception::Exception(const std::string &message, const std::string &file, int line) :
|
||||
m_message(message),
|
||||
m_file(file),
|
||||
m_line(line)
|
||||
|
@ -65,7 +65,7 @@ int Exception::getLine() const
|
|||
return m_line;
|
||||
}
|
||||
|
||||
FileException::FileException(std::string message, std::string file, int line) :
|
||||
FileException::FileException(const std::string &message, const std::string &file, int line) :
|
||||
Exception(message, file, line)
|
||||
{
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ FileException::~FileException() AUD_NOEXCEPT
|
|||
{
|
||||
}
|
||||
|
||||
DeviceException::DeviceException(std::string message, std::string file, int line) :
|
||||
DeviceException::DeviceException(const std::string &message, const std::string &file, int line) :
|
||||
Exception(message, file, line)
|
||||
{
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ DeviceException::~DeviceException() AUD_NOEXCEPT
|
|||
{
|
||||
}
|
||||
|
||||
StateException::StateException(std::string message, std::string file, int line) :
|
||||
StateException::StateException(const std::string &message, const std::string &file, int line) :
|
||||
Exception(message, file, line)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -28,12 +28,12 @@ AUD_NAMESPACE_BEGIN
|
|||
std::unordered_map<std::string, std::shared_ptr<IDeviceFactory>> DeviceManager::m_factories;
|
||||
std::shared_ptr<IDevice> DeviceManager::m_device;
|
||||
|
||||
void DeviceManager::registerDevice(std::string name, std::shared_ptr<IDeviceFactory> factory)
|
||||
void DeviceManager::registerDevice(const std::string &name, std::shared_ptr<IDeviceFactory> factory)
|
||||
{
|
||||
m_factories[name] = factory;
|
||||
}
|
||||
|
||||
std::shared_ptr<IDeviceFactory> DeviceManager::getDeviceFactory(std::string name)
|
||||
std::shared_ptr<IDeviceFactory> DeviceManager::getDeviceFactory(const std::string &name)
|
||||
{
|
||||
auto it = m_factories.find(name);
|
||||
|
||||
|
@ -66,7 +66,7 @@ void DeviceManager::setDevice(std::shared_ptr<IDevice> device)
|
|||
m_device = device;
|
||||
}
|
||||
|
||||
void DeviceManager::openDevice(std::string name)
|
||||
void DeviceManager::openDevice(const std::string &name)
|
||||
{
|
||||
setDevice(getDeviceFactory(name)->openDevice());
|
||||
}
|
||||
|
|
|
@ -180,7 +180,7 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual void setName(std::string name)
|
||||
virtual void setName(const std::string &name)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
|
|
@ -718,7 +718,7 @@ void SoftwareDevice::create()
|
|||
m_doppler_factor = 1.0f;
|
||||
m_distance_model = DISTANCE_MODEL_INVERSE_CLAMPED;
|
||||
m_flags = 0;
|
||||
m_quality = false;
|
||||
m_quality = ResampleQuality::FASTEST;
|
||||
}
|
||||
|
||||
void SoftwareDevice::destroy()
|
||||
|
@ -829,7 +829,7 @@ void SoftwareDevice::setPanning(IHandle* handle, float pan)
|
|||
h->m_user_pan = pan;
|
||||
}
|
||||
|
||||
void SoftwareDevice::setQuality(bool quality)
|
||||
void SoftwareDevice::setQuality(ResampleQuality quality)
|
||||
{
|
||||
m_quality = quality;
|
||||
}
|
||||
|
@ -886,10 +886,14 @@ std::shared_ptr<IHandle> SoftwareDevice::play(std::shared_ptr<IReader> reader, b
|
|||
std::shared_ptr<ResampleReader> resampler;
|
||||
|
||||
// resample
|
||||
if(m_quality)
|
||||
resampler = std::shared_ptr<ResampleReader>(new JOSResampleReader(reader, m_specs.rate));
|
||||
else
|
||||
if (m_quality == ResampleQuality::FASTEST)
|
||||
{
|
||||
resampler = std::shared_ptr<ResampleReader>(new LinearResampleReader(reader, m_specs.rate));
|
||||
}
|
||||
else
|
||||
{
|
||||
resampler = std::shared_ptr<ResampleReader>(new JOSResampleReader(reader, m_specs.rate, m_quality));
|
||||
}
|
||||
reader = std::shared_ptr<IReader>(resampler);
|
||||
|
||||
// rechannel
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
File::File(std::string filename, int stream) :
|
||||
File::File(const std::string &filename, int stream) :
|
||||
m_filename(filename), m_stream(stream)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ void FileManager::registerOutput(std::shared_ptr<aud::IFileOutput> output)
|
|||
outputs().push_back(output);
|
||||
}
|
||||
|
||||
std::shared_ptr<IReader> FileManager::createReader(std::string filename, int stream)
|
||||
std::shared_ptr<IReader> FileManager::createReader(const std::string &filename, int stream)
|
||||
{
|
||||
for(std::shared_ptr<IFileInput> input : inputs())
|
||||
{
|
||||
|
@ -71,7 +71,7 @@ std::shared_ptr<IReader> FileManager::createReader(std::shared_ptr<Buffer> buffe
|
|||
AUD_THROW(FileException, "The file couldn't be read with any installed file reader.");
|
||||
}
|
||||
|
||||
std::vector<StreamInfo> FileManager::queryStreams(std::string filename)
|
||||
std::vector<StreamInfo> FileManager::queryStreams(const std::string &filename)
|
||||
{
|
||||
for(std::shared_ptr<IFileInput> input : inputs())
|
||||
{
|
||||
|
@ -99,7 +99,7 @@ std::vector<StreamInfo> FileManager::queryStreams(std::shared_ptr<Buffer> buffer
|
|||
AUD_THROW(FileException, "The file couldn't be read with any installed file reader.");
|
||||
}
|
||||
|
||||
std::shared_ptr<IWriter> FileManager::createWriter(std::string filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate)
|
||||
std::shared_ptr<IWriter> FileManager::createWriter(const std::string &filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate)
|
||||
{
|
||||
for(std::shared_ptr<IFileOutput> output : outputs())
|
||||
{
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
std::shared_ptr<IWriter> FileWriter::createWriter(std::string filename,DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate)
|
||||
std::shared_ptr<IWriter> FileWriter::createWriter(const std::string &filename,DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate)
|
||||
{
|
||||
return FileManager::createWriter(filename, specs, format, codec, bitrate);
|
||||
}
|
||||
|
|
|
@ -19,15 +19,14 @@
|
|||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
JOSResample::JOSResample(std::shared_ptr<ISound> sound,
|
||||
DeviceSpecs specs) :
|
||||
SpecsChanger(sound, specs)
|
||||
JOSResample::JOSResample(std::shared_ptr<ISound> sound, DeviceSpecs specs, ResampleQuality quality) :
|
||||
SpecsChanger(sound, specs), m_quality(quality)
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<IReader> JOSResample::createReader()
|
||||
{
|
||||
return std::shared_ptr<IReader>(new JOSResampleReader(getReader(), m_specs.rate));
|
||||
return std::shared_ptr<IReader>(new JOSResampleReader(getReader(), m_specs.rate, m_quality));
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
||||
|
|
|
@ -45,7 +45,7 @@ static inline int lrint_impl(double x)
|
|||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
JOSResampleReader::JOSResampleReader(std::shared_ptr<IReader> reader, SampleRate rate, Quality quality) :
|
||||
JOSResampleReader::JOSResampleReader(std::shared_ptr<IReader> reader, SampleRate rate, ResampleQuality quality) :
|
||||
ResampleReader(reader, rate),
|
||||
m_channels(CHANNELS_INVALID),
|
||||
m_n(0),
|
||||
|
@ -55,17 +55,17 @@ JOSResampleReader::JOSResampleReader(std::shared_ptr<IReader> reader, SampleRate
|
|||
{
|
||||
switch(quality)
|
||||
{
|
||||
case Quality::LOW:
|
||||
case ResampleQuality::LOW:
|
||||
m_len = m_len_low;
|
||||
m_L = m_L_low;
|
||||
m_coeff = m_coeff_low;
|
||||
break;
|
||||
case Quality::MEDIUM:
|
||||
case ResampleQuality::MEDIUM:
|
||||
m_len = m_len_medium;
|
||||
m_L = m_L_medium;
|
||||
m_coeff = m_coeff_medium;
|
||||
break;
|
||||
case Quality::HIGH:
|
||||
case ResampleQuality::HIGH:
|
||||
m_len = m_len_high;
|
||||
m_L = m_L_high;
|
||||
m_coeff = m_coeff_high;
|
||||
|
|
|
@ -100,9 +100,9 @@ void Sequence::remove(std::shared_ptr<SequenceEntry> entry)
|
|||
m_sequence->remove(entry);
|
||||
}
|
||||
|
||||
std::shared_ptr<IReader> Sequence::createQualityReader()
|
||||
std::shared_ptr<IReader> Sequence::createQualityReader(ResampleQuality quality)
|
||||
{
|
||||
return std::shared_ptr<IReader>(new SequenceReader(m_sequence, true));
|
||||
return std::shared_ptr<IReader>(new SequenceReader(m_sequence, quality));
|
||||
}
|
||||
|
||||
std::shared_ptr<IReader> Sequence::createReader()
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
SequenceReader::SequenceReader(std::shared_ptr<SequenceData> sequence, bool quality) :
|
||||
SequenceReader::SequenceReader(std::shared_ptr<SequenceData> sequence, ResampleQuality quality) :
|
||||
m_position(0), m_device(sequence->m_specs), m_sequence(sequence), m_status(0), m_entry_status(0)
|
||||
{
|
||||
m_device.setQuality(quality);
|
||||
|
|
|
@ -1655,7 +1655,7 @@ class CyclesPreferences(bpy.types.AddonPreferences):
|
|||
col.label(text=rpt_("and Windows driver version %s or newer") % driver_version,
|
||||
icon='BLANK1', translate=False)
|
||||
elif sys.platform.startswith("linux"):
|
||||
driver_version = "XX.XX.26918.50"
|
||||
driver_version = "XX.XX.27642.38"
|
||||
col.label(
|
||||
text=rpt_("Requires Intel GPU with Xe-HPG architecture and"),
|
||||
icon='BLANK1',
|
||||
|
|
|
@ -866,7 +866,7 @@ static const int lowest_supported_driver_version_win = 1015186;
|
|||
* This information is returned by `ocloc query OCL_DRIVER_VERSION`.*/
|
||||
static const int lowest_supported_driver_version_neo = 28044;
|
||||
# else
|
||||
static const int lowest_supported_driver_version_neo = 26918;
|
||||
static const int lowest_supported_driver_version_neo = 27642;
|
||||
# endif
|
||||
|
||||
int parse_driver_build_version(const sycl::device &device)
|
||||
|
|
|
@ -882,7 +882,7 @@ if(WITH_CYCLES_DEVICE_ONEAPI)
|
|||
|
||||
# Set defaults for spir64 and spir64_gen options
|
||||
if(NOT DEFINED CYCLES_ONEAPI_SYCL_OPTIONS_spir64)
|
||||
set(CYCLES_ONEAPI_SYCL_OPTIONS_spir64 "-options '-ze-opt-regular-grf-kernel integrator_intersect -ze-opt-large-grf-kernel shade -ze-opt-no-local-to-generic'")
|
||||
set(CYCLES_ONEAPI_SYCL_OPTIONS_spir64 "-options '-ze-opt-large-register-file -ze-opt-regular-grf-kernel integrator_intersect -ze-opt-large-grf-kernel shade -ze-opt-no-local-to-generic'")
|
||||
endif()
|
||||
if(NOT DEFINED CYCLES_ONEAPI_SYCL_OPTIONS_spir64_gen)
|
||||
set(CYCLES_ONEAPI_SYCL_OPTIONS_spir64_gen "${CYCLES_ONEAPI_SYCL_OPTIONS_spir64}" CACHE STRING "Extra build options for spir64_gen target")
|
||||
|
|
|
@ -19,7 +19,7 @@ PERFORMANCE OF THIS SOFTWARE.
|
|||
|
||||
------
|
||||
|
||||
** Audaspace; version 1.3.0 -- https://audaspace.github.io/
|
||||
** Audaspace; version 1.4+ (ae29ce2) -- https://audaspace.github.io/
|
||||
** Cuda Wrangler; version cbf465b -- https://github.com/CudaWrangler/cuew
|
||||
** Draco; version 1.3.6 -- https://google.github.io/draco/
|
||||
** Embree; version 4.1.0 -- https://github.com/embree/embree
|
||||
|
@ -244,7 +244,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
|
||||
* For Audaspace see also this required NOTICE:
|
||||
Copyright © 2009-2020 Jörg Müller. All rights reserved.
|
||||
Copyright © 2009-2023 Jörg Müller. All rights reserved.
|
||||
* For Cuda Wrangler see also this required NOTICE:
|
||||
Copyright 2011-2014 Blender Foundation
|
||||
* For Draco see also this required NOTICE:
|
||||
|
|
|
@ -4586,6 +4586,9 @@ def km_grease_pencil_paint_mode(_params):
|
|||
*_template_items_hide_reveal_actions("grease_pencil.layer_hide", "grease_pencil.layer_reveal"),
|
||||
|
||||
("paint.sample_color", {"type": 'X', "value": 'PRESS', "shift": True}, None),
|
||||
|
||||
# Isolate Layer
|
||||
("grease_pencil.layer_isolate", {"type": 'NUMPAD_ASTERIX', "value": 'PRESS'}, None),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
@ -4659,6 +4662,9 @@ def km_grease_pencil_edit_mode(params):
|
|||
"ctrl": True, "repeat": True}, {"properties": [("direction", "DOWN")]}),
|
||||
("grease_pencil.reorder", {"type": 'DOWN_ARROW', "value": 'PRESS',
|
||||
"ctrl": True, "shift": True}, {"properties": [("direction", "BOTTOM")]}),
|
||||
|
||||
# Isolate Layer
|
||||
("grease_pencil.layer_isolate", {"type": 'NUMPAD_ASTERIX', "value": 'PRESS'}, None),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
|
|
@ -658,70 +658,77 @@ class WM_MT_operator_presets(Menu):
|
|||
|
||||
|
||||
class WM_OT_operator_presets_cleanup(Operator):
|
||||
"""Remove outdated operator properties from presets that may cause problems"""
|
||||
|
||||
bl_idname = "wm.operator_presets_cleanup"
|
||||
bl_label = "Clean Up Operator Presets"
|
||||
bl_description = "Remove outdated operator properties from presets that may cause problems"
|
||||
|
||||
operator: StringProperty(name="operator")
|
||||
properties: CollectionProperty(name="properties", type=OperatorFileListElement)
|
||||
|
||||
def cleanup_preset(self, filepath, properties):
|
||||
from pathlib import Path
|
||||
file = Path(filepath)
|
||||
if not (file.is_file() and filepath.suffix == ".py"):
|
||||
def _cleanup_preset(self, filepath, properties_exclude):
|
||||
import os
|
||||
import re
|
||||
if not (os.path.isfile(filepath) and os.path.splitext(filepath)[1].lower() == ".py"):
|
||||
return
|
||||
lines = file.read_text().splitlines(True)
|
||||
if len(lines) == 0:
|
||||
with open(filepath, "r", encoding="utf-8") as fh:
|
||||
lines = fh.read().splitlines(True)
|
||||
if not lines:
|
||||
return
|
||||
new_lines = []
|
||||
for line in lines:
|
||||
if not any(line.startswith(("op.%s" % prop)) for prop in properties):
|
||||
new_lines.append(line)
|
||||
file.write_text("".join(new_lines))
|
||||
regex_exclude = re.compile("(" + "|".join([re.escape("op." + prop) for prop in properties_exclude]) + ")\\b")
|
||||
lines = [line for line in lines if not regex_exclude.match(line)]
|
||||
with open(filepath, "w", encoding="utf-8") as fh:
|
||||
fh.write("".join(lines))
|
||||
|
||||
def cleanup_operators_presets(self, operators, properties):
|
||||
base_preset_directory = bpy.utils.user_resource(
|
||||
'SCRIPTS', path="presets", create=False)
|
||||
def _cleanup_operators_presets(self, operators, properties_exclude):
|
||||
import os
|
||||
base_preset_directory = bpy.utils.user_resource('SCRIPTS', path="presets", create=False)
|
||||
if not base_preset_directory:
|
||||
return
|
||||
for operator in operators:
|
||||
from pathlib import Path
|
||||
operator_path = AddPresetOperator.operator_path(operator)
|
||||
directory = Path(base_preset_directory, operator_path)
|
||||
directory = os.path.join(base_preset_directory, operator_path)
|
||||
|
||||
if not directory.is_dir():
|
||||
if not os.path.isdir(directory):
|
||||
continue
|
||||
|
||||
for filepath in directory.iterdir():
|
||||
self.cleanup_preset(filepath, properties)
|
||||
for filename in os.listdir(directory):
|
||||
self._cleanup_preset(os.path.join(directory, filename), properties_exclude)
|
||||
|
||||
def execute(self, context):
|
||||
properties = []
|
||||
properties_exclude = []
|
||||
operators = []
|
||||
if self.operator:
|
||||
operators.append(self.operator)
|
||||
for prop in self.properties:
|
||||
properties.append(prop.name)
|
||||
properties_exclude.append(prop.name)
|
||||
else:
|
||||
# Cleanup by default I/O Operators Presets
|
||||
operators = ['WM_OT_alembic_export',
|
||||
'WM_OT_alembic_import',
|
||||
'WM_OT_collada_export',
|
||||
'WM_OT_collada_import',
|
||||
'WM_OT_gpencil_export_svg',
|
||||
'WM_OT_gpencil_export_pdf',
|
||||
'WM_OT_gpencil_export_svg',
|
||||
'WM_OT_gpencil_import_svg',
|
||||
'WM_OT_obj_export',
|
||||
'WM_OT_obj_import',
|
||||
'WM_OT_ply_export',
|
||||
'WM_OT_ply_import',
|
||||
'WM_OT_stl_export',
|
||||
'WM_OT_stl_import',
|
||||
'WM_OT_usd_export',
|
||||
'WM_OT_usd_import',
|
||||
]
|
||||
properties = ["filepath", "directory", "files", "filename"]
|
||||
operators = [
|
||||
"WM_OT_alembic_export",
|
||||
"WM_OT_alembic_import",
|
||||
"WM_OT_collada_export",
|
||||
"WM_OT_collada_import",
|
||||
"WM_OT_gpencil_export_svg",
|
||||
"WM_OT_gpencil_export_pdf",
|
||||
"WM_OT_gpencil_export_svg",
|
||||
"WM_OT_gpencil_import_svg",
|
||||
"WM_OT_obj_export",
|
||||
"WM_OT_obj_import",
|
||||
"WM_OT_ply_export",
|
||||
"WM_OT_ply_import",
|
||||
"WM_OT_stl_export",
|
||||
"WM_OT_stl_import",
|
||||
"WM_OT_usd_export",
|
||||
"WM_OT_usd_import",
|
||||
]
|
||||
properties_exclude = [
|
||||
"filepath",
|
||||
"directory",
|
||||
"files",
|
||||
"filename"
|
||||
]
|
||||
|
||||
self.cleanup_operators_presets(operators, properties)
|
||||
self._cleanup_operators_presets(operators, properties_exclude)
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
|
|
|
@ -410,7 +410,11 @@ class NODE_MT_geometry_node_GEO_MESH_OPERATIONS(Menu):
|
|||
node_add_menu.add_node_type(layout, "GeometryNodeFlipFaces")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshBoolean")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshToCurve")
|
||||
if context.preferences.experimental.use_new_volume_nodes:
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshToDensityGrid")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshToPoints")
|
||||
if context.preferences.experimental.use_new_volume_nodes:
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshToSDFGrid")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshToVolume")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeScaleElements")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSplitEdges")
|
||||
|
@ -471,11 +475,14 @@ class NODE_MT_category_GEO_POINT(Menu):
|
|||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeDistributePointsInVolume")
|
||||
if context.preferences.experimental.use_new_volume_nodes:
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeDistributePointsInGrid")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeDistributePointsOnFaces")
|
||||
layout.separator()
|
||||
node_add_menu.add_node_type(layout, "GeometryNodePoints")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodePointsToCurves")
|
||||
if context.preferences.experimental.use_new_volume_nodes:
|
||||
node_add_menu.add_node_type(layout, "GeometryNodePointsToSDFGrid")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodePointsToVertices")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodePointsToVolume")
|
||||
layout.separator()
|
||||
|
@ -711,6 +718,8 @@ class NODE_MT_geometry_node_GEO_VOLUME_OPERATIONS(Menu):
|
|||
def draw(self, context):
|
||||
layout = self.layout
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeVolumeToMesh")
|
||||
if context.preferences.experimental.use_new_volume_nodes:
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeGridToMesh")
|
||||
node_add_menu.draw_assets_for_catalog(layout, "Volume/Operations")
|
||||
|
||||
|
||||
|
|
|
@ -1433,6 +1433,65 @@ def brush_basic_gpencil_paint_settings(layout, context, brush, *, compact=False)
|
|||
layout.template_curve_mapping(settings, "thickness_primitive_curve", brush=True)
|
||||
|
||||
|
||||
def brush_basic_grease_pencil_paint_settings(layout, context, brush, *, compact=False):
|
||||
tool_settings = context.tool_settings
|
||||
settings = tool_settings.gpencil_paint
|
||||
gp_settings = brush.gpencil_settings
|
||||
tool = context.workspace.tools.from_space_view3d_mode(context.mode, create=False)
|
||||
if gp_settings is None:
|
||||
return
|
||||
|
||||
grease_pencil_tool = brush.gpencil_tool
|
||||
|
||||
UnifiedPaintPanel.prop_unified(
|
||||
layout,
|
||||
context,
|
||||
brush,
|
||||
"size",
|
||||
unified_name="use_unified_size",
|
||||
pressure_name="use_pressure_size",
|
||||
text="Radius",
|
||||
slider=True,
|
||||
header=compact,
|
||||
)
|
||||
|
||||
if brush.use_pressure_size and not compact:
|
||||
col = layout.column()
|
||||
col.template_curve_mapping(gp_settings, "curve_sensitivity", brush=True,
|
||||
use_negative_slope=True)
|
||||
|
||||
UnifiedPaintPanel.prop_unified(
|
||||
layout,
|
||||
context,
|
||||
brush,
|
||||
"strength",
|
||||
unified_name="use_unified_strength",
|
||||
pressure_name="use_pressure_strength",
|
||||
slider=True,
|
||||
header=compact,
|
||||
)
|
||||
|
||||
if brush.use_pressure_strength and not compact:
|
||||
col = layout.column()
|
||||
col.template_curve_mapping(gp_settings, "curve_strength", brush=True,
|
||||
use_negative_slope=True)
|
||||
|
||||
if grease_pencil_tool == 'DRAW':
|
||||
layout.prop(gp_settings, "active_smooth_factor")
|
||||
row = layout.row(align=True)
|
||||
if compact:
|
||||
row.prop(gp_settings, "caps_type", text="", expand=True)
|
||||
else:
|
||||
row.prop(gp_settings, "caps_type", text="Caps Type")
|
||||
# TODO: Remove this when caps work.
|
||||
row.enabled = False
|
||||
elif grease_pencil_tool == 'ERASE':
|
||||
layout.prop(gp_settings, "eraser_mode", expand=True)
|
||||
if gp_settings.eraser_mode == "HARD":
|
||||
layout.prop(gp_settings, "use_keep_caps_eraser")
|
||||
layout.prop(gp_settings, "use_active_layer_only")
|
||||
|
||||
|
||||
def brush_basic_gpencil_sculpt_settings(layout, _context, brush, *, compact=False):
|
||||
if brush is None:
|
||||
return
|
||||
|
|
|
@ -1699,7 +1699,7 @@ class _defs_weight_paint:
|
|||
ob.data.use_paint_mask_vertex)):
|
||||
return VIEW3D_PT_tools_active._tools_select
|
||||
elif context.pose_object:
|
||||
return (_defs_view3d_select.select,)
|
||||
return VIEW3D_PT_tools_active._tools_select
|
||||
return ()
|
||||
|
||||
@staticmethod
|
||||
|
|
|
@ -605,36 +605,12 @@ class _draw_tool_settings_context_mode:
|
|||
)
|
||||
brush_basic__draw_color_selector(context, layout, brush, brush.gpencil_settings, None)
|
||||
|
||||
UnifiedPaintPanel.prop_unified(
|
||||
layout,
|
||||
context,
|
||||
brush,
|
||||
"size",
|
||||
unified_name="use_unified_size",
|
||||
pressure_name="use_pressure_size",
|
||||
text="Radius",
|
||||
slider=True,
|
||||
header=True,
|
||||
from bl_ui.properties_paint_common import (
|
||||
brush_basic__draw_color_selector,
|
||||
brush_basic_grease_pencil_paint_settings,
|
||||
)
|
||||
|
||||
UnifiedPaintPanel.prop_unified(
|
||||
layout,
|
||||
context,
|
||||
brush,
|
||||
"strength",
|
||||
pressure_name="use_pressure_strength",
|
||||
unified_name="use_unified_strength",
|
||||
slider=True,
|
||||
header=True,
|
||||
)
|
||||
|
||||
if grease_pencil_tool == 'DRAW':
|
||||
layout.prop(brush.gpencil_settings, "active_smooth_factor")
|
||||
elif grease_pencil_tool == 'ERASE':
|
||||
layout.prop(brush.gpencil_settings, "eraser_mode", expand=True)
|
||||
if brush.gpencil_settings.eraser_mode == "HARD":
|
||||
layout.prop(brush.gpencil_settings, "use_keep_caps_eraser")
|
||||
layout.prop(brush.gpencil_settings, "use_active_layer_only")
|
||||
brush_basic_grease_pencil_paint_settings(layout, context, brush, compact=True)
|
||||
|
||||
return True
|
||||
|
||||
|
|
|
@ -2489,6 +2489,190 @@ class VIEW3D_PT_gpencil_brush_presets(Panel, PresetPanel):
|
|||
preset_add_operator = "scene.gpencil_brush_preset_add"
|
||||
|
||||
|
||||
class GreasePencilV3PaintPanel:
|
||||
bl_context = ".grease_pencil_paint"
|
||||
bl_category = "Tool"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
if context.space_data.type in {'VIEW_3D', 'PROPERTIES'}:
|
||||
# Hide for tools not using brushes.
|
||||
if tool_use_brush(context) is False:
|
||||
return False
|
||||
|
||||
return True
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_v3_brush_select(Panel, View3DPanel, GreasePencilV3PaintPanel):
|
||||
bl_label = "Brushes"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
tool_settings = context.scene.tool_settings
|
||||
gpencil_paint = tool_settings.gpencil_paint
|
||||
|
||||
row = layout.row()
|
||||
row.column().template_ID_preview(gpencil_paint, "brush", new="brush.add_gpencil", rows=3, cols=8)
|
||||
|
||||
col = row.column()
|
||||
col.menu("VIEW3D_MT_brush_gpencil_context_menu", icon='DOWNARROW_HLT', text="")
|
||||
|
||||
brush = tool_settings.gpencil_paint.brush
|
||||
if brush is not None:
|
||||
col.prop(brush, "use_custom_icon", toggle=True, icon='FILE_IMAGE', text="")
|
||||
|
||||
if brush.use_custom_icon:
|
||||
layout.row().prop(brush, "icon_filepath", text="")
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_v3_brush_settings(Panel, View3DPanel, GreasePencilV3PaintPanel):
|
||||
bl_label = "Brush Settings"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw_header_preset(self, _context):
|
||||
VIEW3D_PT_gpencil_brush_presets.draw_panel_header(self.layout)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
tool_settings = context.scene.tool_settings
|
||||
gpencil_paint = tool_settings.gpencil_paint
|
||||
|
||||
brush = gpencil_paint.brush
|
||||
|
||||
if brush is not None:
|
||||
gp_settings = brush.gpencil_settings
|
||||
|
||||
if brush.gpencil_tool in {'DRAW', 'FILL'}:
|
||||
row = layout.row(align=True)
|
||||
row_mat = row.row()
|
||||
if gp_settings.use_material_pin:
|
||||
row_mat.template_ID(gp_settings, "material", live_icon=True)
|
||||
else:
|
||||
row_mat.template_ID(context.active_object, "active_material", live_icon=True)
|
||||
row_mat.enabled = False # will otherwise allow changing material in active slot
|
||||
|
||||
row.prop(gp_settings, "use_material_pin", text="")
|
||||
|
||||
if not self.is_popover:
|
||||
from bl_ui.properties_paint_common import (
|
||||
brush_basic_grease_pencil_paint_settings,
|
||||
)
|
||||
brush_basic_grease_pencil_paint_settings(layout, context, brush, compact=False)
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_v3_brush_mixcolor(View3DPanel, Panel):
|
||||
bl_context = ".grease_pencil_paint"
|
||||
bl_label = "Color"
|
||||
bl_category = "Tool"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
ob = context.object
|
||||
tool_settings = context.tool_settings
|
||||
settings = tool_settings.gpencil_paint
|
||||
brush = settings.brush
|
||||
|
||||
if ob is None or brush is None:
|
||||
return False
|
||||
|
||||
if context.region.type == 'TOOL_HEADER':
|
||||
return False
|
||||
|
||||
from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
|
||||
tool = ToolSelectPanelHelper.tool_active_from_context(context)
|
||||
if tool and tool.idname in {'builtin.cutter', 'builtin.eyedropper', 'builtin.interpolate'}:
|
||||
return False
|
||||
|
||||
if brush.gpencil_tool == 'TINT':
|
||||
return True
|
||||
|
||||
if brush.gpencil_tool not in {'DRAW', 'FILL'}:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
tool_settings = context.tool_settings
|
||||
settings = tool_settings.gpencil_paint
|
||||
brush = settings.brush
|
||||
gp_settings = brush.gpencil_settings
|
||||
|
||||
row = layout.row()
|
||||
row.prop(settings, "color_mode", expand=True)
|
||||
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
col = layout.column()
|
||||
col.enabled = settings.color_mode == 'VERTEXCOLOR'
|
||||
|
||||
col.template_color_picker(brush, "color", value_slider=True)
|
||||
|
||||
sub_row = col.row(align=True)
|
||||
UnifiedPaintPanel.prop_unified_color(sub_row, context, brush, "color", text="")
|
||||
UnifiedPaintPanel.prop_unified_color(sub_row, context, brush, "secondary_color", text="")
|
||||
|
||||
sub_row.operator("paint.brush_colors_flip", icon='FILE_REFRESH', text="")
|
||||
|
||||
if brush.gpencil_tool in {'DRAW', 'FILL'}:
|
||||
col.prop(gp_settings, "vertex_mode", text="Mode")
|
||||
col.prop(gp_settings, "vertex_color_factor", slider=True, text="Mix Factor")
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_v3_brush_mix_palette(View3DPanel, Panel):
|
||||
bl_context = ".grease_pencil_paint"
|
||||
bl_label = "Palette"
|
||||
bl_category = "Tool"
|
||||
bl_parent_id = "VIEW3D_PT_tools_grease_pencil_v3_brush_mixcolor"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
ob = context.object
|
||||
tool_settings = context.tool_settings
|
||||
settings = tool_settings.gpencil_paint
|
||||
brush = settings.brush
|
||||
|
||||
if ob is None or brush is None:
|
||||
return False
|
||||
|
||||
from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
|
||||
tool = ToolSelectPanelHelper.tool_active_from_context(context)
|
||||
if tool and tool.idname in {'builtin.cutter', 'builtin.eyedropper', 'builtin.interpolate'}:
|
||||
return False
|
||||
|
||||
if brush.gpencil_tool == 'TINT':
|
||||
return True
|
||||
|
||||
if brush.gpencil_tool not in {'DRAW', 'FILL'}:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
tool_settings = context.tool_settings
|
||||
settings = tool_settings.gpencil_paint
|
||||
brush = settings.brush
|
||||
|
||||
col = layout.column()
|
||||
col.enabled = settings.color_mode == 'VERTEXCOLOR'
|
||||
|
||||
row = col.row(align=True)
|
||||
row.template_ID(settings, "palette", new="palette.new")
|
||||
if settings.palette:
|
||||
col.template_palette(settings, "palette", color=True)
|
||||
|
||||
|
||||
classes = (
|
||||
VIEW3D_MT_brush_context_menu,
|
||||
VIEW3D_MT_brush_gpencil_context_menu,
|
||||
|
@ -2580,6 +2764,11 @@ classes = (
|
|||
VIEW3D_PT_tools_grease_pencil_brush_mixcolor,
|
||||
VIEW3D_PT_tools_grease_pencil_brush_mix_palette,
|
||||
|
||||
VIEW3D_PT_tools_grease_pencil_v3_brush_select,
|
||||
VIEW3D_PT_tools_grease_pencil_v3_brush_settings,
|
||||
VIEW3D_PT_tools_grease_pencil_v3_brush_mixcolor,
|
||||
VIEW3D_PT_tools_grease_pencil_v3_brush_mix_palette,
|
||||
|
||||
VIEW3D_PT_tools_grease_pencil_brush_paint_falloff,
|
||||
VIEW3D_PT_tools_grease_pencil_brush_sculpt_falloff,
|
||||
VIEW3D_PT_tools_grease_pencil_brush_weight_falloff,
|
||||
|
|
|
@ -1330,6 +1330,11 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
|
|||
#define GEO_NODE_SORT_ELEMENTS 2123
|
||||
#define GEO_NODE_MENU_SWITCH 2124
|
||||
#define GEO_NODE_SAMPLE_GRID 2125
|
||||
#define GEO_NODE_MESH_TO_DENSITY_GRID 2126
|
||||
#define GEO_NODE_MESH_TO_SDF_GRID 2127
|
||||
#define GEO_NODE_POINTS_TO_SDF_GRID 2128
|
||||
#define GEO_NODE_GRID_TO_MESH 2129
|
||||
#define GEO_NODE_DISTRIBUTE_POINTS_IN_GRID 2130
|
||||
|
||||
/** \} */
|
||||
|
||||
|
|
|
@ -44,6 +44,8 @@ Mesh *volume_to_mesh(const openvdb::GridBase &grid,
|
|||
float threshold,
|
||||
float adaptivity);
|
||||
|
||||
Mesh *volume_grid_to_mesh(const openvdb::GridBase &grid, float threshold, float adaptivity);
|
||||
|
||||
/**
|
||||
* Convert an OpenVDB volume grid to corresponding mesh data: vertex positions and quad and
|
||||
* triangle indices.
|
||||
|
|
|
@ -1779,6 +1779,8 @@ void what_does_obaction(Object *ob,
|
|||
/* execute effects of Action on to workob (or its PoseChannels) */
|
||||
BKE_animsys_evaluate_animdata(&workob->id, &adt, anim_eval_context, ADT_RECALC_ANIM, false);
|
||||
}
|
||||
/* Ensure stack memory set here isn't accessed later, see !118847. */
|
||||
workob->runtime = nullptr;
|
||||
}
|
||||
|
||||
void BKE_pose_check_uids_unique_and_report(const bPose *pose)
|
||||
|
|
|
@ -1118,16 +1118,9 @@ void BKE_appdir_app_templates(ListBase *templates)
|
|||
*/
|
||||
static void where_is_temp(char *tempdir, const size_t tempdir_maxncpy, const char *userdir)
|
||||
{
|
||||
|
||||
tempdir[0] = '\0';
|
||||
|
||||
if (userdir && userdir[0] != '\0' && BLI_is_dir(userdir)) {
|
||||
BLI_strncpy(tempdir, userdir, tempdir_maxncpy);
|
||||
/* Add a trailing slash if needed. */
|
||||
BLI_path_slash_ensure(tempdir, tempdir_maxncpy);
|
||||
if (BLI_temp_directory_path_copy_if_valid(tempdir, tempdir_maxncpy, userdir)) {
|
||||
return;
|
||||
}
|
||||
|
||||
BLI_temp_directory_path_get(tempdir, tempdir_maxncpy);
|
||||
}
|
||||
|
||||
|
|
|
@ -724,13 +724,17 @@ static ModifierData &legacy_object_modifier_common(Object &object,
|
|||
return false;
|
||||
}
|
||||
StringRefNull rna_path = fcurve->rna_path;
|
||||
char legacy_name_esc[MAX_NAME * 2];
|
||||
BLI_str_escape(legacy_name_esc, legacy_md.name, sizeof(legacy_name_esc));
|
||||
const std::string legacy_root_path = fmt::format("grease_pencil_modifiers[\"{}\"]",
|
||||
legacy_md.name);
|
||||
legacy_name_esc);
|
||||
if (!rna_path.startswith(legacy_root_path)) {
|
||||
return false;
|
||||
}
|
||||
char new_name_esc[MAX_NAME * 2];
|
||||
BLI_str_escape(new_name_esc, new_md.name, sizeof(new_name_esc));
|
||||
const std::string new_rna_path = fmt::format(
|
||||
"modifiers[\"{}\"]{}", new_md.name, rna_path.substr(int64_t(legacy_root_path.size())));
|
||||
"modifiers[\"{}\"]{}", new_name_esc, rna_path.substr(int64_t(legacy_root_path.size())));
|
||||
MEM_freeN(fcurve->rna_path);
|
||||
fcurve->rna_path = BLI_strdupn(new_rna_path.c_str(), new_rna_path.size());
|
||||
return true;
|
||||
|
|
|
@ -599,7 +599,8 @@ void BKE_sound_load(Main *bmain, bSound *sound)
|
|||
AUD_Device *BKE_sound_mixdown(const Scene *scene, AUD_DeviceSpecs specs, int start, float volume)
|
||||
{
|
||||
sound_verify_evaluated_id(&scene->id);
|
||||
return AUD_openMixdownDevice(specs, scene->sound_scene, volume, start / FPS);
|
||||
return AUD_openMixdownDevice(
|
||||
specs, scene->sound_scene, volume, AUD_RESAMPLE_QUALITY_MEDIUM, start / FPS);
|
||||
}
|
||||
|
||||
void BKE_sound_create_scene(Scene *scene)
|
||||
|
|
|
@ -184,6 +184,13 @@ Mesh *volume_to_mesh(const openvdb::GridBase &grid,
|
|||
return mesh;
|
||||
}
|
||||
|
||||
Mesh *volume_grid_to_mesh(const openvdb::GridBase &grid,
|
||||
const float threshold,
|
||||
const float adaptivity)
|
||||
{
|
||||
return volume_to_mesh(grid, {VOLUME_TO_MESH_RESOLUTION_MODE_GRID}, threshold, adaptivity);
|
||||
}
|
||||
|
||||
#endif /* WITH_OPENVDB */
|
||||
|
||||
} // namespace blender::bke
|
||||
|
|
|
@ -0,0 +1,190 @@
|
|||
/* SPDX-FileCopyrightText: 2024 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "BLI_linear_allocator.hh"
|
||||
#include "BLI_struct_equality_utils.hh"
|
||||
#include "BLI_utility_mixins.hh"
|
||||
|
||||
namespace blender::linear_allocator {
|
||||
|
||||
/**
|
||||
* The list is a linked list of segments containing multiple elements. The capacity of each segment
|
||||
* is a template parameter because that removes the need to store it for every segment.
|
||||
*/
|
||||
template<typename T, int64_t Capacity> struct ChunkedListSegment {
|
||||
/** Pointer to the next segment in the list. */
|
||||
ChunkedListSegment *next = nullptr;
|
||||
/**
|
||||
* Number of constructed elements in this segment. The constructed elements are always at the
|
||||
* beginning of the array below.
|
||||
*/
|
||||
int64_t size = 0;
|
||||
/**
|
||||
* The memory that actually contains the values in the end. The values are constructed and
|
||||
* destructed by higher level code.
|
||||
*/
|
||||
std::array<TypedBuffer<T>, Capacity> values;
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a special purpose container data structure that can be used to efficiently gather many
|
||||
* elements into many (small) lists for later retrieval. Insertion order is *not* maintained.
|
||||
*
|
||||
* To use this data structure, one has to have a separate #LinearAllocator which is passed to the
|
||||
* `append` function. This allows the same allocator to be used by many lists. Passing it into the
|
||||
* append function also removes the need to store the allocator pointer in every list.
|
||||
*
|
||||
* It is an improvement over #Vector because it does not require any reallocations. #VectorList
|
||||
* could also be used to overcome the reallocation issue.
|
||||
*
|
||||
* This data structure is also an improvement over #VectorList because:
|
||||
* - It has a much lower memory footprint when empty.
|
||||
* - Allows using a #LinearAllocator for all allocations, without storing the pointer to it in
|
||||
* every vector.
|
||||
* - It wastes less memory due to over-allocations.
|
||||
*/
|
||||
template<typename T, int64_t SegmentCapacity = 4> class ChunkedList : NonCopyable {
|
||||
private:
|
||||
using Segment = ChunkedListSegment<T, SegmentCapacity>;
|
||||
Segment *current_segment_ = nullptr;
|
||||
|
||||
public:
|
||||
ChunkedList() = default;
|
||||
|
||||
ChunkedList(ChunkedList &&other)
|
||||
{
|
||||
current_segment_ = other.current_segment_;
|
||||
other.current_segment_ = nullptr;
|
||||
}
|
||||
|
||||
~ChunkedList()
|
||||
{
|
||||
/* This code assumes that the #ChunkedListSegment does not have to be destructed if the
|
||||
* contained type is trivially destructible. */
|
||||
static_assert(std::is_trivially_destructible_v<ChunkedListSegment<int, 4>>);
|
||||
if constexpr (!std::is_trivially_destructible_v<T>) {
|
||||
for (Segment *segment = current_segment_; segment; segment = segment->next) {
|
||||
for (const int64_t i : IndexRange(segment->size)) {
|
||||
T &value = *segment->values[i];
|
||||
std::destroy_at(&value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ChunkedList &operator=(ChunkedList &&other)
|
||||
{
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
}
|
||||
std::destroy_at(this);
|
||||
new (this) ChunkedList(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an element to the list. The insertion order is not maintained. The given allocator is used
|
||||
* to allocate any extra memory that may be needed.
|
||||
*/
|
||||
void append(LinearAllocator<> &allocator, const T &value)
|
||||
{
|
||||
this->append_as(allocator, value);
|
||||
}
|
||||
|
||||
void append(LinearAllocator<> &allocator, T &&value)
|
||||
{
|
||||
this->append_as(allocator, std::move(value));
|
||||
}
|
||||
|
||||
template<typename... Args> void append_as(LinearAllocator<> &allocator, Args &&...args)
|
||||
{
|
||||
if (current_segment_ == nullptr || current_segment_->size == SegmentCapacity) {
|
||||
/* Allocate a new segment if necessary. */
|
||||
static_assert(std::is_trivially_destructible_v<Segment>);
|
||||
Segment *new_segment = allocator.construct<Segment>().release();
|
||||
new_segment->next = current_segment_;
|
||||
current_segment_ = new_segment;
|
||||
}
|
||||
T *value = &*current_segment_->values[current_segment_->size++];
|
||||
new (value) T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
class ConstIterator {
|
||||
private:
|
||||
const Segment *segment_ = nullptr;
|
||||
int64_t index_ = 0;
|
||||
|
||||
public:
|
||||
ConstIterator(const Segment *segment, int64_t index = 0) : segment_(segment), index_(index) {}
|
||||
|
||||
ConstIterator &operator++()
|
||||
{
|
||||
index_++;
|
||||
if (index_ == segment_->size) {
|
||||
segment_ = segment_->next;
|
||||
index_ = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
const T &operator*() const
|
||||
{
|
||||
return *segment_->values[index_];
|
||||
}
|
||||
|
||||
BLI_STRUCT_EQUALITY_OPERATORS_2(ConstIterator, segment_, index_)
|
||||
};
|
||||
|
||||
class MutableIterator {
|
||||
private:
|
||||
Segment *segment_ = nullptr;
|
||||
int64_t index_ = 0;
|
||||
|
||||
public:
|
||||
MutableIterator(Segment *segment, int64_t index = 0) : segment_(segment), index_(index) {}
|
||||
|
||||
MutableIterator &operator++()
|
||||
{
|
||||
index_++;
|
||||
if (index_ == segment_->size) {
|
||||
segment_ = segment_->next;
|
||||
index_ = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
T &operator*()
|
||||
{
|
||||
return *segment_->values[index_];
|
||||
}
|
||||
|
||||
BLI_STRUCT_EQUALITY_OPERATORS_2(MutableIterator, segment_, index_)
|
||||
};
|
||||
|
||||
ConstIterator begin() const
|
||||
{
|
||||
return ConstIterator(current_segment_, 0);
|
||||
}
|
||||
|
||||
ConstIterator end() const
|
||||
{
|
||||
return ConstIterator(nullptr, 0);
|
||||
}
|
||||
|
||||
MutableIterator begin()
|
||||
{
|
||||
return MutableIterator(current_segment_, 0);
|
||||
}
|
||||
|
||||
MutableIterator end()
|
||||
{
|
||||
return MutableIterator(nullptr, 0);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace blender::linear_allocator
|
|
@ -14,6 +14,14 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Sets `temp_directory` from `dirpath` when it's a valid directory.
|
||||
* Simple sanitize operations are performed and a trailing slash is ensured.
|
||||
*/
|
||||
bool BLI_temp_directory_path_copy_if_valid(char *temp_directory,
|
||||
const size_t buffer_size,
|
||||
const char *dirpath);
|
||||
|
||||
/* Get the path to a directory suitable for temporary files.
|
||||
*
|
||||
* The return path is guaranteed to exist and to be a directory, as well as to contain a trailing
|
||||
|
|
|
@ -263,6 +263,7 @@ set(SRC
|
|||
BLI_lazy_threading.hh
|
||||
BLI_length_parameterize.hh
|
||||
BLI_linear_allocator.hh
|
||||
BLI_linear_allocator_chunked_list.hh
|
||||
BLI_link_utils.h
|
||||
BLI_linklist.h
|
||||
BLI_linklist_lockfree.h
|
||||
|
@ -521,6 +522,7 @@ if(WITH_GTESTS)
|
|||
tests/BLI_kdtree_test.cc
|
||||
tests/BLI_length_parameterize_test.cc
|
||||
tests/BLI_linear_allocator_test.cc
|
||||
tests/BLI_linear_allocator_chunked_list_test.cc
|
||||
tests/BLI_linklist_lockfree_test.cc
|
||||
tests/BLI_listbase_test.cc
|
||||
tests/BLI_map_test.cc
|
||||
|
|
|
@ -8,6 +8,34 @@
|
|||
#include "BLI_path_util.h"
|
||||
#include "BLI_string.h"
|
||||
|
||||
bool BLI_temp_directory_path_copy_if_valid(char *temp_directory,
|
||||
const size_t buffer_size,
|
||||
const char *dirpath)
|
||||
{
|
||||
if (dirpath == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Disallow paths starting with two forward slashes. While they are valid paths,
|
||||
* Blender interprets them as relative in situations relative paths aren't supported,
|
||||
* see #95411. */
|
||||
while (UNLIKELY(dirpath[0] == '/' && dirpath[1] == '/')) {
|
||||
dirpath++;
|
||||
}
|
||||
if (dirpath[0] == '\0') {
|
||||
return false;
|
||||
}
|
||||
if (!BLI_is_dir(dirpath)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BLI_strncpy(temp_directory, dirpath, buffer_size);
|
||||
|
||||
/* Add a trailing slash if needed. */
|
||||
BLI_path_slash_ensure(temp_directory, buffer_size);
|
||||
return true;
|
||||
}
|
||||
|
||||
void BLI_temp_directory_path_get(char *temp_directory, const size_t buffer_size)
|
||||
{
|
||||
temp_directory[0] = '\0';
|
||||
|
@ -24,9 +52,9 @@ void BLI_temp_directory_path_get(char *temp_directory, const size_t buffer_size)
|
|||
};
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(env_vars); i++) {
|
||||
const char *tmp = BLI_getenv(env_vars[i]);
|
||||
if (tmp && (tmp[0] != '\0') && BLI_is_dir(tmp)) {
|
||||
BLI_strncpy(temp_directory, tmp, buffer_size);
|
||||
if (BLI_temp_directory_path_copy_if_valid(
|
||||
temp_directory, buffer_size, BLI_getenv(env_vars[i])))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -34,10 +62,6 @@ void BLI_temp_directory_path_get(char *temp_directory, const size_t buffer_size)
|
|||
if (temp_directory[0] == '\0') {
|
||||
BLI_strncpy(temp_directory, "/tmp/", buffer_size);
|
||||
}
|
||||
else {
|
||||
/* Add a trailing slash if needed. */
|
||||
BLI_path_slash_ensure(temp_directory, buffer_size);
|
||||
}
|
||||
|
||||
BLI_dir_create_recursive(temp_directory);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
/* SPDX-FileCopyrightText: 2024 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "testing/testing.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "BLI_linear_allocator_chunked_list.hh"
|
||||
#include "BLI_set.hh"
|
||||
|
||||
#include "BLI_strict_flags.h" /* Keep last. */
|
||||
|
||||
namespace blender::linear_allocator::tests {
|
||||
|
||||
TEST(LinearAllocator_ChunkedList, Append)
|
||||
{
|
||||
LinearAllocator<> allocator;
|
||||
ChunkedList<std::string> list;
|
||||
|
||||
list.append(allocator, "1");
|
||||
list.append(allocator, "2");
|
||||
list.append(allocator, "this_is_an_extra_long_string");
|
||||
|
||||
Set<std::string> retrieved_values;
|
||||
for (const std::string &value : const_cast<const ChunkedList<std::string> &>(list)) {
|
||||
retrieved_values.add(value);
|
||||
}
|
||||
EXPECT_EQ(retrieved_values.size(), 3);
|
||||
EXPECT_TRUE(retrieved_values.contains("1"));
|
||||
EXPECT_TRUE(retrieved_values.contains("2"));
|
||||
EXPECT_TRUE(retrieved_values.contains("this_is_an_extra_long_string"));
|
||||
}
|
||||
|
||||
TEST(LinearAllocator_ChunkedList, AppendMany)
|
||||
{
|
||||
LinearAllocator<> allocator;
|
||||
ChunkedList<int> list;
|
||||
|
||||
for (const int64_t i : IndexRange(10000)) {
|
||||
list.append(allocator, int(i));
|
||||
}
|
||||
|
||||
Set<int> values;
|
||||
for (const int value : list) {
|
||||
values.add(value);
|
||||
}
|
||||
|
||||
EXPECT_EQ(values.size(), 10000);
|
||||
}
|
||||
|
||||
TEST(LinearAllocator_ChunkedList, Move)
|
||||
{
|
||||
LinearAllocator<> allocator;
|
||||
ChunkedList<int> a;
|
||||
a.append(allocator, 1);
|
||||
ChunkedList<int> b = std::move(a);
|
||||
|
||||
a.append(allocator, 2);
|
||||
b.append(allocator, 3);
|
||||
|
||||
{
|
||||
Set<int> a_values;
|
||||
for (const int value : a) {
|
||||
a_values.add(value);
|
||||
}
|
||||
Set<int> b_values;
|
||||
for (const int value : b) {
|
||||
b_values.add(value);
|
||||
}
|
||||
|
||||
EXPECT_EQ(a_values.size(), 1);
|
||||
EXPECT_TRUE(a_values.contains(2));
|
||||
|
||||
EXPECT_EQ(b_values.size(), 2);
|
||||
EXPECT_TRUE(b_values.contains(1));
|
||||
EXPECT_TRUE(b_values.contains(3));
|
||||
}
|
||||
|
||||
a = std::move(b);
|
||||
/* Want to test self-move. Using std::move twice quiets a compiler warning. */
|
||||
a = std::move(std::move(a));
|
||||
|
||||
{
|
||||
Set<int> a_values;
|
||||
for (const int value : a) {
|
||||
a_values.add(value);
|
||||
}
|
||||
Set<int> b_values;
|
||||
for (const int value : b) {
|
||||
b_values.add(value);
|
||||
}
|
||||
|
||||
EXPECT_EQ(a_values.size(), 2);
|
||||
EXPECT_TRUE(a_values.contains(1));
|
||||
EXPECT_TRUE(a_values.contains(3));
|
||||
|
||||
EXPECT_TRUE(b_values.is_empty());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blender::linear_allocator::tests
|
|
@ -54,35 +54,13 @@ void BlurNode::convert_to_operations(NodeConverter &converter,
|
|||
converter.map_input_socket(get_input_socket(1), clamp->get_input_socket(0));
|
||||
converter.add_link(zero->get_output_socket(), clamp->get_input_socket(1));
|
||||
|
||||
GaussianAlphaXBlurOperation *operationx = new GaussianAlphaXBlurOperation();
|
||||
operationx->set_data(data);
|
||||
operationx->set_quality(quality);
|
||||
operationx->set_size(1.0f);
|
||||
operationx->set_falloff(PROP_SMOOTH);
|
||||
operationx->set_subtract(false);
|
||||
operationx->set_extend_bounds(extend_bounds);
|
||||
|
||||
converter.add_operation(operationx);
|
||||
converter.add_link(clamp->get_output_socket(), operationx->get_input_socket(0));
|
||||
|
||||
GaussianAlphaYBlurOperation *operationy = new GaussianAlphaYBlurOperation();
|
||||
operationy->set_data(data);
|
||||
operationy->set_quality(quality);
|
||||
operationy->set_size(1.0f);
|
||||
operationy->set_falloff(PROP_SMOOTH);
|
||||
operationy->set_subtract(false);
|
||||
operationy->set_extend_bounds(extend_bounds);
|
||||
|
||||
converter.add_operation(operationy);
|
||||
converter.add_link(operationx->get_output_socket(), operationy->get_input_socket(0));
|
||||
|
||||
GaussianBlurReferenceOperation *operation = new GaussianBlurReferenceOperation();
|
||||
operation->set_data(data);
|
||||
operation->set_quality(quality);
|
||||
operation->set_extend_bounds(extend_bounds);
|
||||
|
||||
converter.add_operation(operation);
|
||||
converter.add_link(operationy->get_output_socket(), operation->get_input_socket(1));
|
||||
converter.add_link(clamp->get_output_socket(), operation->get_input_socket(1));
|
||||
|
||||
output_operation = operation;
|
||||
input_operation = operation;
|
||||
|
|
|
@ -26,7 +26,9 @@ class ConstantOperation : public NodeOperation {
|
|||
virtual const float *get_constant_elem() = 0;
|
||||
bool can_get_constant_elem() const;
|
||||
|
||||
void update_memory_buffer(MemoryBuffer *output, const rcti &area, Span<MemoryBuffer *> inputs);
|
||||
void update_memory_buffer(MemoryBuffer *output,
|
||||
const rcti &area,
|
||||
Span<MemoryBuffer *> inputs) override;
|
||||
};
|
||||
|
||||
} // namespace blender::compositor
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "BLI_index_range.hh"
|
||||
#include "BLI_math_vector.hh"
|
||||
|
||||
#include "COM_GaussianBokehBlurOperation.h"
|
||||
|
||||
#include "RE_pipeline.h"
|
||||
|
@ -148,7 +153,7 @@ void GaussianBokehBlurOperation::update_memory_buffer_partial(MemoryBuffer *outp
|
|||
GaussianBlurReferenceOperation::GaussianBlurReferenceOperation()
|
||||
: BlurBaseOperation(DataType::Color)
|
||||
{
|
||||
maintabs_ = nullptr;
|
||||
weights_ = nullptr;
|
||||
use_variable_size_ = true;
|
||||
}
|
||||
|
||||
|
@ -206,23 +211,45 @@ void GaussianBlurReferenceOperation::init_execution()
|
|||
|
||||
void GaussianBlurReferenceOperation::update_gauss()
|
||||
{
|
||||
int i;
|
||||
int x = std::max(filtersizex_, filtersizey_);
|
||||
maintabs_ = (float **)MEM_mallocN(x * sizeof(float *), "gauss array");
|
||||
for (i = 0; i < x; i++) {
|
||||
maintabs_[i] = make_gausstab(i + 1, i + 1);
|
||||
}
|
||||
}
|
||||
const int2 radius = int2(filtersizex_, filtersizey_);
|
||||
const float2 scale = math::safe_divide(float2(1.0f), float2(radius));
|
||||
const int2 size = radius + int2(1);
|
||||
|
||||
void GaussianBlurReferenceOperation::deinit_execution()
|
||||
{
|
||||
int x, i;
|
||||
x = std::max(filtersizex_, filtersizey_);
|
||||
for (i = 0; i < x; i++) {
|
||||
MEM_freeN(maintabs_[i]);
|
||||
rcti weights_area;
|
||||
BLI_rcti_init(&weights_area, 0, size.x, 0, size.y);
|
||||
weights_ = std::make_unique<MemoryBuffer>(DataType::Value, weights_area, false);
|
||||
|
||||
float sum = 0.0f;
|
||||
|
||||
const float center_weight = RE_filter_value(data_.filtertype, 0.0f);
|
||||
*weights_->get_elem(0, 0) = center_weight;
|
||||
sum += center_weight;
|
||||
|
||||
for (const int x : IndexRange(size.x).drop_front(1)) {
|
||||
const float weight = RE_filter_value(data_.filtertype, x * scale.x);
|
||||
*weights_->get_elem(x, 0) = weight;
|
||||
sum += weight * 2.0f;
|
||||
}
|
||||
|
||||
for (const int y : IndexRange(size.y).drop_front(1)) {
|
||||
const float weight = RE_filter_value(data_.filtertype, y * scale.y);
|
||||
*weights_->get_elem(0, y) = weight;
|
||||
sum += weight * 2.0f;
|
||||
}
|
||||
|
||||
for (const int y : IndexRange(size.y).drop_front(1)) {
|
||||
for (const int x : IndexRange(size.x).drop_front(1)) {
|
||||
const float weight = RE_filter_value(data_.filtertype, math::length(float2(x, y) * scale));
|
||||
*weights_->get_elem(x, y) = weight;
|
||||
sum += weight * 4.0f;
|
||||
}
|
||||
}
|
||||
|
||||
for (const int y : IndexRange(size.y)) {
|
||||
for (const int x : IndexRange(size.x)) {
|
||||
*weights_->get_elem(x, y) /= sum;
|
||||
}
|
||||
}
|
||||
MEM_freeN(maintabs_);
|
||||
BlurBaseOperation::deinit_execution();
|
||||
}
|
||||
|
||||
void GaussianBlurReferenceOperation::get_area_of_interest(const int input_idx,
|
||||
|
@ -246,56 +273,56 @@ void GaussianBlurReferenceOperation::update_memory_buffer_partial(MemoryBuffer *
|
|||
const rcti &area,
|
||||
Span<MemoryBuffer *> inputs)
|
||||
{
|
||||
const MemoryBuffer *size_input = inputs[SIZE_INPUT_INDEX];
|
||||
const MemoryBuffer *image_input = inputs[IMAGE_INPUT_INDEX];
|
||||
MemoryBuffer *size_input = inputs[SIZE_INPUT_INDEX];
|
||||
for (BuffersIterator<float> it = output->iterate_with({size_input}, area); !it.is_end(); ++it) {
|
||||
const float ref_size = *it.in(0);
|
||||
int ref_radx = int(ref_size * radx_);
|
||||
int ref_rady = int(ref_size * rady_);
|
||||
if (ref_radx > filtersizex_) {
|
||||
ref_radx = filtersizex_;
|
||||
}
|
||||
else if (ref_radx < 1) {
|
||||
ref_radx = 1;
|
||||
}
|
||||
if (ref_rady > filtersizey_) {
|
||||
ref_rady = filtersizey_;
|
||||
}
|
||||
else if (ref_rady < 1) {
|
||||
ref_rady = 1;
|
||||
|
||||
int2 weights_size = int2(weights_->get_width(), weights_->get_height());
|
||||
int2 base_radius = weights_size - int2(1);
|
||||
|
||||
for (BuffersIterator<float> it = output->iterate_with({}, area); !it.is_end(); ++it) {
|
||||
float4 accumulated_color = float4(0.0f);
|
||||
float4 accumulated_weight = float4(0.0f);
|
||||
|
||||
int2 radius = int2(math::ceil(float2(base_radius) * *size_input->get_elem(it.x, it.y)));
|
||||
|
||||
float4 center_color = float4(image_input->get_elem_clamped(it.x, it.y));
|
||||
float center_weight = *weights_->get_elem(0, 0);
|
||||
accumulated_color += center_color * center_weight;
|
||||
accumulated_weight += center_weight;
|
||||
|
||||
for (int x = 1; x <= radius.x; x++) {
|
||||
float weight_coordinates = (x / float(radius.x)) * base_radius.x;
|
||||
float weight;
|
||||
weights_->read_elem_bilinear(weight_coordinates, 0.0f, &weight);
|
||||
accumulated_color += float4(image_input->get_elem_clamped(it.x + x, it.y)) * weight;
|
||||
accumulated_color += float4(image_input->get_elem_clamped(it.x - x, it.y)) * weight;
|
||||
accumulated_weight += weight * 2.0f;
|
||||
}
|
||||
|
||||
const int x = it.x;
|
||||
const int y = it.y;
|
||||
if (ref_radx == 1 && ref_rady == 1) {
|
||||
image_input->read_elem(x, y, it.out);
|
||||
continue;
|
||||
for (int y = 1; y <= radius.y; y++) {
|
||||
float weight_coordinates = (y / float(radius.y)) * base_radius.y;
|
||||
float weight;
|
||||
weights_->read_elem_bilinear(0.0f, weight_coordinates, &weight);
|
||||
accumulated_color += float4(image_input->get_elem_clamped(it.x, it.y + y)) * weight;
|
||||
accumulated_color += float4(image_input->get_elem_clamped(it.x, it.y - y)) * weight;
|
||||
accumulated_weight += weight * 2.0f;
|
||||
}
|
||||
|
||||
const int w = get_width();
|
||||
const int height = get_height();
|
||||
const int minxr = x - ref_radx < 0 ? -x : -ref_radx;
|
||||
const int maxxr = x + ref_radx > w ? w - x : ref_radx;
|
||||
const int minyr = y - ref_rady < 0 ? -y : -ref_rady;
|
||||
const int maxyr = y + ref_rady > height ? height - y : ref_rady;
|
||||
|
||||
const float *gausstabx = maintabs_[ref_radx - 1];
|
||||
const float *gausstabcentx = gausstabx + ref_radx;
|
||||
const float *gausstaby = maintabs_[ref_rady - 1];
|
||||
const float *gausstabcenty = gausstaby + ref_rady;
|
||||
|
||||
float gauss_sum = 0.0f;
|
||||
float color_sum[4] = {0};
|
||||
const float *row_color = image_input->get_elem(x + minxr, y + minyr);
|
||||
for (int i = minyr; i < maxyr; i++, row_color += image_input->row_stride) {
|
||||
const float *color = row_color;
|
||||
for (int j = minxr; j < maxxr; j++, color += image_input->elem_stride) {
|
||||
const float val = gausstabcenty[i] * gausstabcentx[j];
|
||||
gauss_sum += val;
|
||||
madd_v4_v4fl(color_sum, color, val);
|
||||
for (int y = 1; y <= radius.y; y++) {
|
||||
for (int x = 1; x <= radius.x; x++) {
|
||||
float2 weight_coordinates = (float2(x, y) / float2(radius)) * float2(base_radius);
|
||||
float weight;
|
||||
weights_->read_elem_bilinear(weight_coordinates.x, weight_coordinates.y, &weight);
|
||||
accumulated_color += float4(image_input->get_elem_clamped(it.x + x, it.y + y)) * weight;
|
||||
accumulated_color += float4(image_input->get_elem_clamped(it.x - x, it.y + y)) * weight;
|
||||
accumulated_color += float4(image_input->get_elem_clamped(it.x + x, it.y - y)) * weight;
|
||||
accumulated_color += float4(image_input->get_elem_clamped(it.x - x, it.y - y)) * weight;
|
||||
accumulated_weight += weight * 4.0f;
|
||||
}
|
||||
}
|
||||
mul_v4_v4fl(it.out, color_sum, 1.0f / gauss_sum);
|
||||
|
||||
accumulated_color = math::safe_divide(accumulated_color, accumulated_weight);
|
||||
copy_v4_v4(it.out, accumulated_color);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "COM_BlurBaseOperation.h"
|
||||
#include "COM_NodeOperation.h"
|
||||
#include "COM_QualityStepHelper.h"
|
||||
|
@ -32,7 +34,7 @@ class GaussianBokehBlurOperation : public BlurBaseOperation {
|
|||
|
||||
class GaussianBlurReferenceOperation : public BlurBaseOperation {
|
||||
private:
|
||||
float **maintabs_;
|
||||
std::unique_ptr<MemoryBuffer> weights_;
|
||||
|
||||
void update_gauss();
|
||||
int filtersizex_;
|
||||
|
@ -45,8 +47,6 @@ class GaussianBlurReferenceOperation : public BlurBaseOperation {
|
|||
void init_data() override;
|
||||
void init_execution() override;
|
||||
|
||||
void deinit_execution() override;
|
||||
|
||||
void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
|
||||
void update_memory_buffer_partial(MemoryBuffer *output,
|
||||
const rcti &area,
|
||||
|
|
|
@ -135,10 +135,6 @@ class AssetCatalogSelectorTree : public ui::AbstractTreeView {
|
|||
|
||||
uiLayoutSetEmboss(&row, UI_EMBOSS);
|
||||
|
||||
if (!is_collapsible()) {
|
||||
uiItemL(&row, nullptr, ICON_BLANK1);
|
||||
}
|
||||
|
||||
uiLayout *subrow = uiLayoutRow(&row, false);
|
||||
uiLayoutSetActive(subrow, catalog_path_enabled_);
|
||||
uiItemL(subrow, catalog_item_.get_name().c_str(), ICON_NONE);
|
||||
|
|
|
@ -120,6 +120,19 @@ if(WIN32)
|
|||
add_definitions(-DNOMINMAX)
|
||||
endif()
|
||||
|
||||
if(WITH_GTESTS)
|
||||
set(TEST_SRC
|
||||
sculpt_detail_test.cc
|
||||
)
|
||||
set(TEST_INC
|
||||
)
|
||||
set(TEST_LIB
|
||||
${LIB}
|
||||
bf_rna # RNA_prototypes.h
|
||||
)
|
||||
blender_add_test_suite_lib(editor_sculpt_paint "${TEST_SRC}" "${INC};${TEST_INC}" "${INC_SYS}" "${TEST_LIB}")
|
||||
endif()
|
||||
|
||||
blender_add_lib(bf_editor_sculpt_paint "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
||||
|
||||
# RNA_prototypes.h
|
||||
|
|
|
@ -5515,17 +5515,19 @@ static void sculpt_stroke_update_step(bContext *C,
|
|||
sculpt_restore_mesh(sd, ob);
|
||||
|
||||
if (sd->flags & (SCULPT_DYNTOPO_DETAIL_CONSTANT | SCULPT_DYNTOPO_DETAIL_MANUAL)) {
|
||||
float object_space_constant_detail = 1.0f / (sd->constant_detail *
|
||||
mat4_to_scale(ob->object_to_world().ptr()));
|
||||
BKE_pbvh_bmesh_detail_size_set(ss->pbvh, object_space_constant_detail);
|
||||
BKE_pbvh_bmesh_detail_size_set(
|
||||
ss->pbvh, dyntopo::detail_size::constant_to_detail_size(sd->constant_detail, ob));
|
||||
}
|
||||
else if (sd->flags & SCULPT_DYNTOPO_DETAIL_BRUSH) {
|
||||
BKE_pbvh_bmesh_detail_size_set(ss->pbvh, ss->cache->radius * sd->detail_percent / 100.0f);
|
||||
BKE_pbvh_bmesh_detail_size_set(
|
||||
ss->pbvh,
|
||||
dyntopo::detail_size::brush_to_detail_size(sd->detail_percent, ss->cache->radius));
|
||||
}
|
||||
else {
|
||||
BKE_pbvh_bmesh_detail_size_set(ss->pbvh,
|
||||
(ss->cache->radius / ss->cache->dyntopo_pixel_radius) *
|
||||
(sd->detail_size * U.pixelsize) / 0.4f);
|
||||
BKE_pbvh_bmesh_detail_size_set(
|
||||
ss->pbvh,
|
||||
dyntopo::detail_size::relative_to_detail_size(
|
||||
sd->detail_size, ss->cache->radius, ss->cache->dyntopo_pixel_radius, U.pixelsize));
|
||||
}
|
||||
|
||||
if (dyntopo::stroke_is_dyntopo(ss, brush)) {
|
||||
|
|
|
@ -454,17 +454,16 @@ static void dyntopo_detail_size_parallel_lines_draw(uint pos3d,
|
|||
{
|
||||
float object_space_constant_detail;
|
||||
if (cd->mode == DETAILING_MODE_RESOLUTION) {
|
||||
object_space_constant_detail = 1.0f /
|
||||
(cd->current_value *
|
||||
mat4_to_scale(cd->active_object->object_to_world().ptr()));
|
||||
object_space_constant_detail = detail_size::constant_to_detail_size(cd->current_value,
|
||||
cd->active_object);
|
||||
}
|
||||
else if (cd->mode == DETAILING_MODE_BRUSH_PERCENT) {
|
||||
object_space_constant_detail = cd->brush_radius * cd->current_value / 100.0f;
|
||||
object_space_constant_detail = detail_size::brush_to_detail_size(cd->current_value,
|
||||
cd->brush_radius);
|
||||
}
|
||||
else {
|
||||
object_space_constant_detail = (cd->brush_radius / cd->pixel_radius) *
|
||||
(cd->current_value * U.pixelsize) /
|
||||
detail_size::RELATIVE_SCALE_FACTOR;
|
||||
object_space_constant_detail = detail_size::relative_to_detail_size(
|
||||
cd->current_value, cd->brush_radius, cd->pixel_radius, U.pixelsize);
|
||||
}
|
||||
|
||||
/* The constant detail represents the maximum edge length allowed before subdividing it. If the
|
||||
|
@ -614,7 +613,7 @@ static void dyntopo_detail_size_sample_from_surface(Object *ob,
|
|||
}
|
||||
else {
|
||||
sampled_value = detail_size::constant_to_relative_detail(
|
||||
detail_size, cd->brush_radius, cd->pixel_radius, cd->active_object);
|
||||
detail_size, cd->brush_radius, cd->pixel_radius, U.pixelsize, cd->active_object);
|
||||
}
|
||||
cd->current_value = clamp_f(sampled_value, cd->min_value, cd->max_value);
|
||||
}
|
||||
|
@ -870,6 +869,24 @@ void SCULPT_OT_dyntopo_detail_size_edit(wmOperatorType *ot)
|
|||
} // namespace blender::ed::sculpt_paint::dyntopo
|
||||
|
||||
namespace blender::ed::sculpt_paint::dyntopo::detail_size {
|
||||
float constant_to_detail_size(const float constant_detail, const Object *ob)
|
||||
{
|
||||
return 1.0f / (constant_detail * mat4_to_scale(ob->object_to_world().ptr()));
|
||||
}
|
||||
|
||||
float brush_to_detail_size(const float brush_percent, const float brush_radius)
|
||||
{
|
||||
return brush_radius * brush_percent / 100.0f;
|
||||
}
|
||||
|
||||
float relative_to_detail_size(const float relative_detail,
|
||||
const float brush_radius,
|
||||
const float pixel_radius,
|
||||
const float pixel_size)
|
||||
{
|
||||
return (brush_radius / pixel_radius) * (relative_detail * pixel_size) / RELATIVE_SCALE_FACTOR;
|
||||
}
|
||||
|
||||
float constant_to_brush_detail(const float constant_detail,
|
||||
const float brush_radius,
|
||||
const Object *ob)
|
||||
|
@ -882,11 +899,12 @@ float constant_to_brush_detail(const float constant_detail,
|
|||
float constant_to_relative_detail(const float constant_detail,
|
||||
const float brush_radius,
|
||||
const float pixel_radius,
|
||||
const float pixel_size,
|
||||
const Object *ob)
|
||||
{
|
||||
const float object_scale = mat4_to_scale(ob->object_to_world().ptr());
|
||||
|
||||
return (pixel_radius / brush_radius) * (RELATIVE_SCALE_FACTOR / U.pixelsize) *
|
||||
return (pixel_radius / brush_radius) * (RELATIVE_SCALE_FACTOR / pixel_size) *
|
||||
(1.0f / (constant_detail * object_scale));
|
||||
}
|
||||
} // namespace blender::ed::sculpt_paint::dyntopo::detail_size
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
#include "sculpt_intern.hh"
|
||||
|
||||
#include "BKE_object_types.hh"
|
||||
|
||||
#include "testing/testing.h"
|
||||
|
||||
namespace blender::ed::sculpt_paint::dyntopo::detail_size::test {
|
||||
constexpr float CONSTANT_DETAIL = 50.0f;
|
||||
constexpr float BRUSH_RADIUS = 0.5f;
|
||||
constexpr float PIXEL_RADIUS = 200;
|
||||
constexpr float PIXEL_SIZE = 100;
|
||||
|
||||
TEST(Conversion, ConstantToBrushDetail)
|
||||
{
|
||||
blender::bke::ObjectRuntime runtime;
|
||||
runtime.object_to_world = MatBase<float, 4, 4>::identity();
|
||||
|
||||
Object ob;
|
||||
ob.runtime = &runtime;
|
||||
|
||||
const float brush_percent = constant_to_brush_detail(CONSTANT_DETAIL, BRUSH_RADIUS, &ob);
|
||||
const float converted = brush_to_detail_size(brush_percent, BRUSH_RADIUS);
|
||||
|
||||
const float expected = constant_to_detail_size(CONSTANT_DETAIL, &ob);
|
||||
EXPECT_FLOAT_EQ(expected, converted);
|
||||
}
|
||||
TEST(Conversion, ConstantToRelativeDetail)
|
||||
{
|
||||
blender::bke::ObjectRuntime runtime;
|
||||
runtime.object_to_world = MatBase<float, 4, 4>::identity();
|
||||
|
||||
Object ob;
|
||||
ob.runtime = &runtime;
|
||||
|
||||
const float relative_detail = constant_to_relative_detail(
|
||||
CONSTANT_DETAIL, BRUSH_RADIUS, PIXEL_RADIUS, PIXEL_SIZE, &ob);
|
||||
const float converted = relative_to_detail_size(
|
||||
relative_detail, BRUSH_RADIUS, PIXEL_RADIUS, PIXEL_SIZE);
|
||||
|
||||
const float expected = constant_to_detail_size(CONSTANT_DETAIL, &ob);
|
||||
EXPECT_FLOAT_EQ(expected, converted);
|
||||
}
|
||||
} // namespace blender::ed::sculpt_paint::dyntopo::detail_size::test
|
|
@ -1230,8 +1230,30 @@ void triangulate(BMesh *bm);
|
|||
WarnFlag check_attribute_warning(Scene *scene, Object *ob);
|
||||
|
||||
namespace detail_size {
|
||||
|
||||
/**
|
||||
* Scaling factor to match the displayed size to the actual sculpted size
|
||||
*/
|
||||
constexpr float RELATIVE_SCALE_FACTOR = 0.4f;
|
||||
|
||||
/**
|
||||
* Converts from Sculpt#constant_detail to the PBVH max edge length.
|
||||
*/
|
||||
float constant_to_detail_size(const float constant_detail, const Object *ob);
|
||||
|
||||
/**
|
||||
* Converts from Sculpt#detail_percent to the PBVH max edge length.
|
||||
*/
|
||||
float brush_to_detail_size(const float brush_percent, const float brush_radius);
|
||||
|
||||
/**
|
||||
* Converts from Sculpt#detail_size to the PBVH max edge length.
|
||||
*/
|
||||
float relative_to_detail_size(const float relative_detail,
|
||||
const float brush_radius,
|
||||
const float pixel_radius,
|
||||
const float pixel_size);
|
||||
|
||||
/**
|
||||
* Converts from Sculpt#constant_detail to equivalent Sculpt#detail_percent value.
|
||||
*
|
||||
|
@ -1249,6 +1271,7 @@ float constant_to_brush_detail(const float constant_detail,
|
|||
float constant_to_relative_detail(const float constant_detail,
|
||||
const float brush_radius,
|
||||
const float pixel_radius,
|
||||
const float pixel_size,
|
||||
const Object *ob);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -370,6 +370,7 @@ static int sound_mixdown_exec(bContext *C, wmOperator *op)
|
|||
container,
|
||||
codec,
|
||||
bitrate,
|
||||
AUD_RESAMPLE_QUALITY_MEDIUM,
|
||||
nullptr,
|
||||
nullptr,
|
||||
error_message,
|
||||
|
@ -385,6 +386,7 @@ static int sound_mixdown_exec(bContext *C, wmOperator *op)
|
|||
container,
|
||||
codec,
|
||||
bitrate,
|
||||
AUD_RESAMPLE_QUALITY_MEDIUM,
|
||||
nullptr,
|
||||
nullptr,
|
||||
error_message,
|
||||
|
|
|
@ -48,23 +48,13 @@
|
|||
/** \name Channel List
|
||||
* \{ */
|
||||
|
||||
void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *region)
|
||||
void draw_channel_names(bContext *C,
|
||||
bAnimContext *ac,
|
||||
ARegion *region,
|
||||
const ListBase /* bAnimListElem */ &anim_data)
|
||||
{
|
||||
ListBase anim_data = {nullptr, nullptr};
|
||||
bAnimListElem *ale;
|
||||
eAnimFilter_Flags filter;
|
||||
|
||||
View2D *v2d = ®ion->v2d;
|
||||
size_t items;
|
||||
|
||||
/* build list of channels to draw */
|
||||
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
|
||||
items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, eAnimCont_Types(ac->datatype));
|
||||
|
||||
const int height = ANIM_UI_get_channels_total_height(v2d, items);
|
||||
const float pad_bottom = BLI_listbase_is_empty(ac->markers) ? 0 : UI_MARKER_MARGIN_Y;
|
||||
v2d->tot.ymin = -(height + pad_bottom);
|
||||
|
||||
/* need to do a view-sync here, so that the keys area doesn't jump around (it must copy this) */
|
||||
UI_view2d_sync(nullptr, ac->area, v2d, V2D_LOCK_COPY);
|
||||
|
||||
|
@ -112,9 +102,6 @@ void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *region)
|
|||
UI_block_end(C, block);
|
||||
UI_block_draw(C, block);
|
||||
}
|
||||
|
||||
/* Free temporary channels. */
|
||||
ANIM_animdata_freelist(&anim_data);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -30,7 +30,10 @@ void action_buttons_register(ARegionType *art);
|
|||
/**
|
||||
* Left hand part.
|
||||
*/
|
||||
void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *region);
|
||||
void draw_channel_names(bContext *C,
|
||||
bAnimContext *ac,
|
||||
ARegion *region,
|
||||
const ListBase /* bAnimListElem */ &anim_data);
|
||||
/**
|
||||
* Draw keyframes in each channel.
|
||||
*/
|
||||
|
|
|
@ -268,21 +268,39 @@ static void action_channel_region_init(wmWindowManager *wm, ARegion *region)
|
|||
WM_event_add_keymap_handler(®ion->handlers, keymap);
|
||||
}
|
||||
|
||||
static void set_v2d_height(View2D *v2d, const size_t item_count, const bool add_marker_padding)
|
||||
{
|
||||
const int height = ANIM_UI_get_channels_total_height(v2d, item_count);
|
||||
const float pad_bottom = add_marker_padding ? UI_MARKER_MARGIN_Y : 0;
|
||||
v2d->tot.ymin = -(height + pad_bottom);
|
||||
UI_view2d_curRect_clamp_y(v2d);
|
||||
}
|
||||
|
||||
static void action_channel_region_draw(const bContext *C, ARegion *region)
|
||||
{
|
||||
/* draw entirely, view changes should be handled here */
|
||||
bAnimContext ac;
|
||||
if (!ANIM_animdata_get_context(C, &ac)) {
|
||||
return;
|
||||
}
|
||||
|
||||
View2D *v2d = ®ion->v2d;
|
||||
|
||||
/* clear and setup matrix */
|
||||
UI_ThemeClearColor(TH_BACK);
|
||||
|
||||
UI_view2d_view_ortho(v2d);
|
||||
ListBase anim_data = {nullptr, nullptr};
|
||||
/* Build list of channels to draw. */
|
||||
const eAnimFilter_Flags filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE |
|
||||
ANIMFILTER_LIST_CHANNELS);
|
||||
const size_t item_count = ANIM_animdata_filter(
|
||||
&ac, &anim_data, filter, ac.data, eAnimCont_Types(ac.datatype));
|
||||
/* The View2D's height needs to be set before calling UI_view2d_view_ortho because the latter
|
||||
* uses the View2D's `cur` rect which might be modified when setting the height. */
|
||||
set_v2d_height(v2d, item_count, !BLI_listbase_is_empty(ac.markers));
|
||||
|
||||
/* data */
|
||||
if (ANIM_animdata_get_context(C, &ac)) {
|
||||
draw_channel_names((bContext *)C, &ac, region);
|
||||
}
|
||||
UI_view2d_view_ortho(v2d);
|
||||
draw_channel_names((bContext *)C, &ac, region, anim_data);
|
||||
|
||||
/* channel filter next to scrubbing area */
|
||||
ED_time_scrub_channel_search_draw(C, region, ac.ads);
|
||||
|
@ -291,6 +309,7 @@ static void action_channel_region_draw(const bContext *C, ARegion *region)
|
|||
UI_view2d_view_restore(C);
|
||||
|
||||
/* no scrollers here */
|
||||
ANIM_animdata_freelist(&anim_data);
|
||||
}
|
||||
|
||||
/* add handlers, stuff you only do once or on area/region changes */
|
||||
|
@ -856,12 +875,6 @@ static void action_space_blend_write(BlendWriter *writer, SpaceLink *sl)
|
|||
BLO_write_struct(writer, SpaceAction, sl);
|
||||
}
|
||||
|
||||
static void action_main_region_view2d_changed(const bContext * /*C*/, ARegion *region)
|
||||
{
|
||||
View2D *v2d = ®ion->v2d;
|
||||
UI_view2d_curRect_clamp_y(v2d);
|
||||
}
|
||||
|
||||
void ED_spacetype_action()
|
||||
{
|
||||
std::unique_ptr<SpaceType> st = std::make_unique<SpaceType>();
|
||||
|
@ -895,7 +908,6 @@ void ED_spacetype_action()
|
|||
art->draw_overlay = action_main_region_draw_overlay;
|
||||
art->listener = action_main_region_listener;
|
||||
art->message_subscribe = saction_main_region_message_subscribe;
|
||||
art->on_view2d_changed = action_main_region_view2d_changed;
|
||||
art->keymapflag = ED_KEYMAP_GIZMO | ED_KEYMAP_VIEW2D | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES;
|
||||
|
||||
BLI_addhead(&st->regiontypes, art);
|
||||
|
|
|
@ -1517,27 +1517,15 @@ void graph_draw_curves(bAnimContext *ac, SpaceGraph *sipo, ARegion *region, shor
|
|||
/** \name Channel List
|
||||
* \{ */
|
||||
|
||||
void graph_draw_channel_names(bContext *C, bAnimContext *ac, ARegion *region)
|
||||
void graph_draw_channel_names(bContext *C,
|
||||
bAnimContext *ac,
|
||||
ARegion *region,
|
||||
const ListBase /* bAnimListElem */ &anim_data)
|
||||
{
|
||||
ListBase anim_data = {nullptr, nullptr};
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
|
||||
View2D *v2d = ®ion->v2d;
|
||||
float height;
|
||||
size_t items;
|
||||
|
||||
/* build list of channels to draw */
|
||||
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS |
|
||||
ANIMFILTER_FCURVESONLY);
|
||||
items = ANIM_animdata_filter(
|
||||
ac, &anim_data, eAnimFilter_Flags(filter), ac->data, eAnimCont_Types(ac->datatype));
|
||||
|
||||
/* Update max-extent of channels here (taking into account scrollers):
|
||||
* - this is done to allow the channel list to be scrollable, but must be done here
|
||||
* to avoid regenerating the list again and/or also because channels list is drawn first */
|
||||
height = ANIM_UI_get_channels_total_height(v2d, items);
|
||||
v2d->tot.ymin = -height;
|
||||
const float channel_step = ANIM_UI_get_channel_step();
|
||||
|
||||
/* Loop through channels, and set up drawing depending on their type. */
|
||||
|
@ -1588,9 +1576,6 @@ void graph_draw_channel_names(bContext *C, bAnimContext *ac, ARegion *region)
|
|||
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
}
|
||||
|
||||
/* Free temporary channels. */
|
||||
ANIM_animdata_freelist(&anim_data);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -27,7 +27,10 @@ extern "C" {
|
|||
/**
|
||||
* Left hand part.
|
||||
*/
|
||||
void graph_draw_channel_names(struct bContext *C, struct bAnimContext *ac, struct ARegion *region);
|
||||
void graph_draw_channel_names(struct bContext *C,
|
||||
struct bAnimContext *ac,
|
||||
struct ARegion *region,
|
||||
const ListBase /* bAnimListElem */ &anim_data);
|
||||
|
||||
/**
|
||||
* This is called twice from `space_graph.cc`, #graph_main_region_draw()
|
||||
|
|
|
@ -367,20 +367,34 @@ static void graph_channel_region_init(wmWindowManager *wm, ARegion *region)
|
|||
WM_event_add_keymap_handler(®ion->handlers, keymap);
|
||||
}
|
||||
|
||||
static void set_v2d_height(View2D *v2d, const size_t item_count)
|
||||
{
|
||||
const int height = ANIM_UI_get_channels_total_height(v2d, item_count);
|
||||
v2d->tot.ymin = -height;
|
||||
UI_view2d_curRect_clamp_y(v2d);
|
||||
}
|
||||
|
||||
static void graph_channel_region_draw(const bContext *C, ARegion *region)
|
||||
{
|
||||
bAnimContext ac;
|
||||
if (!ANIM_animdata_get_context(C, &ac)) {
|
||||
return;
|
||||
}
|
||||
View2D *v2d = ®ion->v2d;
|
||||
|
||||
/* clear and setup matrix */
|
||||
UI_ThemeClearColor(TH_BACK);
|
||||
|
||||
ListBase anim_data = {nullptr, nullptr};
|
||||
const eAnimFilter_Flags filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE |
|
||||
ANIMFILTER_LIST_CHANNELS | ANIMFILTER_FCURVESONLY);
|
||||
const size_t item_count = ANIM_animdata_filter(
|
||||
&ac, &anim_data, filter, ac.data, eAnimCont_Types(ac.datatype));
|
||||
set_v2d_height(v2d, item_count);
|
||||
UI_view2d_view_ortho(v2d);
|
||||
|
||||
/* draw channels */
|
||||
if (ANIM_animdata_get_context(C, &ac)) {
|
||||
graph_draw_channel_names((bContext *)C, &ac, region);
|
||||
}
|
||||
graph_draw_channel_names((bContext *)C, &ac, region, anim_data);
|
||||
|
||||
/* channel filter next to scrubbing area */
|
||||
ED_time_scrub_channel_search_draw(C, region, ac.ads);
|
||||
|
@ -390,6 +404,8 @@ static void graph_channel_region_draw(const bContext *C, ARegion *region)
|
|||
|
||||
/* scrollers */
|
||||
UI_view2d_scrollers_draw(v2d, nullptr);
|
||||
|
||||
ANIM_animdata_freelist(&anim_data);
|
||||
}
|
||||
|
||||
/* add handlers, stuff you only do once or on area/region changes */
|
||||
|
|
|
@ -909,27 +909,14 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *region)
|
|||
/* *********************************************** */
|
||||
/* Track List */
|
||||
|
||||
void draw_nla_track_list(const bContext *C, bAnimContext *ac, ARegion *region)
|
||||
void draw_nla_track_list(const bContext *C,
|
||||
bAnimContext *ac,
|
||||
ARegion *region,
|
||||
const ListBase /* bAnimListElem */ &anim_data)
|
||||
{
|
||||
ListBase anim_data = {nullptr, nullptr};
|
||||
|
||||
SpaceNla *snla = reinterpret_cast<SpaceNla *>(ac->sl);
|
||||
View2D *v2d = ®ion->v2d;
|
||||
size_t items;
|
||||
|
||||
/* build list of tracks to draw */
|
||||
eAnimFilter_Flags filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE |
|
||||
ANIMFILTER_LIST_CHANNELS | ANIMFILTER_FCURVESONLY);
|
||||
items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, eAnimCont_Types(ac->datatype));
|
||||
|
||||
/* Update max-extent of tracks here (taking into account scrollers):
|
||||
* - this is done to allow the track list to be scrollable, but must be done here
|
||||
* to avoid regenerating the list again and/or also because tracks list is drawn first
|
||||
* - offset of NLATRACK_HEIGHT*2 is added to the height of the tracks, as first is for
|
||||
* start of list offset, and the second is as a correction for the scrollers.
|
||||
*/
|
||||
int height = NLATRACK_TOT_HEIGHT(ac, items);
|
||||
v2d->tot.ymin = -height;
|
||||
|
||||
/* need to do a view-sync here, so that the keys area doesn't jump around
|
||||
* (it must copy this) */
|
||||
|
@ -984,9 +971,6 @@ void draw_nla_track_list(const bContext *C, bAnimContext *ac, ARegion *region)
|
|||
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
}
|
||||
|
||||
/* free temporary tracks */
|
||||
ANIM_animdata_freelist(&anim_data);
|
||||
}
|
||||
|
||||
/* *********************************************** */
|
||||
|
|
|
@ -27,7 +27,10 @@ void nla_buttons_register(ARegionType *art);
|
|||
/* `nla_draw.cc` */
|
||||
|
||||
void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *region);
|
||||
void draw_nla_track_list(const bContext *C, bAnimContext *ac, ARegion *region);
|
||||
void draw_nla_track_list(const bContext *C,
|
||||
bAnimContext *ac,
|
||||
ARegion *region,
|
||||
const ListBase /* bAnimListElem */ &anim_data);
|
||||
|
||||
/* **************************************** */
|
||||
/* `nla_select.cc` */
|
||||
|
|
|
@ -176,17 +176,35 @@ static void nla_track_region_init(wmWindowManager *wm, ARegion *region)
|
|||
static void nla_track_region_draw(const bContext *C, ARegion *region)
|
||||
{
|
||||
bAnimContext ac;
|
||||
View2D *v2d = ®ion->v2d;
|
||||
if (!ANIM_animdata_get_context(C, &ac)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* clear and setup matrix */
|
||||
UI_ThemeClearColor(TH_BACK);
|
||||
|
||||
ListBase anim_data = {nullptr, nullptr};
|
||||
|
||||
SpaceNla *snla = reinterpret_cast<SpaceNla *>(ac.sl);
|
||||
View2D *v2d = ®ion->v2d;
|
||||
|
||||
const eAnimFilter_Flags filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE |
|
||||
ANIMFILTER_LIST_CHANNELS | ANIMFILTER_FCURVESONLY);
|
||||
const size_t item_count = ANIM_animdata_filter(
|
||||
&ac, &anim_data, filter, ac.data, eAnimCont_Types(ac.datatype));
|
||||
|
||||
/* Recalculate the height of the track list. Needs to be done before the call to
|
||||
* `UI_view2d_view_ortho`.*/
|
||||
int height = NLATRACK_TOT_HEIGHT(&ac, item_count);
|
||||
if (!BLI_listbase_is_empty(ED_context_get_markers(C))) {
|
||||
height -= (UI_MARKER_MARGIN_Y - NLATRACK_STEP(snla));
|
||||
}
|
||||
v2d->tot.ymin = -height;
|
||||
UI_view2d_curRect_clamp_y(v2d);
|
||||
|
||||
UI_view2d_view_ortho(v2d);
|
||||
|
||||
/* data */
|
||||
if (ANIM_animdata_get_context(C, &ac)) {
|
||||
draw_nla_track_list(C, &ac, region);
|
||||
}
|
||||
draw_nla_track_list(C, &ac, region, anim_data);
|
||||
|
||||
/* track filter next to scrubbing area */
|
||||
ED_time_scrub_channel_search_draw(C, region, ac.ads);
|
||||
|
@ -196,6 +214,7 @@ static void nla_track_region_draw(const bContext *C, ARegion *region)
|
|||
|
||||
/* scrollers */
|
||||
UI_view2d_scrollers_draw(v2d, nullptr);
|
||||
ANIM_animdata_freelist(&anim_data);
|
||||
}
|
||||
|
||||
/* add handlers, stuff you only do once or on area/region changes */
|
||||
|
@ -430,20 +449,6 @@ static void nla_main_region_message_subscribe(const wmRegionMessageSubscribePara
|
|||
}
|
||||
}
|
||||
|
||||
static void nla_main_region_view2d_changed(const bContext *C, ARegion *region)
|
||||
{
|
||||
SpaceNla *snla = CTX_wm_space_nla(C);
|
||||
View2D *v2d = ®ion->v2d;
|
||||
|
||||
/* If markers are present add region padding
|
||||
* so bottom strip isn't hidden.
|
||||
*/
|
||||
if (!BLI_listbase_is_empty(ED_context_get_markers(C))) {
|
||||
v2d->tot.ymin -= (UI_MARKER_MARGIN_Y - NLATRACK_STEP(snla));
|
||||
}
|
||||
UI_view2d_curRect_clamp_y(v2d);
|
||||
}
|
||||
|
||||
static void nla_track_region_listener(const wmRegionListenerParams *params)
|
||||
{
|
||||
ARegion *region = params->region;
|
||||
|
@ -626,7 +631,6 @@ void ED_spacetype_nla()
|
|||
art->draw_overlay = nla_main_region_draw_overlay;
|
||||
art->listener = nla_main_region_listener;
|
||||
art->message_subscribe = nla_main_region_message_subscribe;
|
||||
art->on_view2d_changed = nla_main_region_view2d_changed;
|
||||
art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES;
|
||||
|
||||
BLI_addhead(&st->regiontypes, art);
|
||||
|
|
|
@ -1709,6 +1709,9 @@ void ED_view3d_buttons_region_layout_ex(const bContext *C,
|
|||
case CTX_MODE_EDIT_GREASE_PENCIL:
|
||||
ARRAY_SET_ITEMS(contexts, ".grease_pencil_edit");
|
||||
break;
|
||||
case CTX_MODE_PAINT_GREASE_PENCIL:
|
||||
ARRAY_SET_ITEMS(contexts, ".grease_pencil_paint");
|
||||
break;
|
||||
case CTX_MODE_EDIT_POINT_CLOUD:
|
||||
ARRAY_SET_ITEMS(contexts, ".point_cloud_edit");
|
||||
break;
|
||||
|
|
|
@ -468,11 +468,16 @@ static bool view3d_selectable_data(bContext *C)
|
|||
}
|
||||
}
|
||||
else {
|
||||
if ((ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)) &&
|
||||
if ((ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_TEXTURE_PAINT)) &&
|
||||
!BKE_paint_select_elem_test(ob))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if ((ob->mode & OB_MODE_WEIGHT_PAINT) &&
|
||||
!(BKE_paint_select_elem_test(ob) || BKE_object_pose_armature_get_with_wpaint_check(ob)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -543,31 +548,24 @@ static void do_lasso_select_pose__do_tag(void *user_data,
|
|||
data->is_changed = true;
|
||||
}
|
||||
}
|
||||
static void do_lasso_tag_pose(ViewContext *vc,
|
||||
Object *ob,
|
||||
const int mcoords[][2],
|
||||
const int mcoords_len)
|
||||
static void do_lasso_tag_pose(ViewContext *vc, const int mcoords[][2], const int mcoords_len)
|
||||
{
|
||||
ViewContext vc_tmp;
|
||||
LassoSelectUserData data;
|
||||
rcti rect;
|
||||
|
||||
if ((ob->type != OB_ARMATURE) || (ob->pose == nullptr)) {
|
||||
if ((vc->obact->type != OB_ARMATURE) || (vc->obact->pose == nullptr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
vc_tmp = *vc;
|
||||
vc_tmp.obact = ob;
|
||||
|
||||
BLI_lasso_boundbox(&rect, mcoords, mcoords_len);
|
||||
|
||||
view3d_userdata_lassoselect_init(
|
||||
&data, vc, &rect, mcoords, mcoords_len, static_cast<eSelectOp>(0));
|
||||
|
||||
ED_view3d_init_mats_rv3d(vc_tmp.obact, vc->rv3d);
|
||||
ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d);
|
||||
|
||||
/* Treat bones as clipped segments (no joints). */
|
||||
pose_foreachScreenBone(&vc_tmp,
|
||||
pose_foreachScreenBone(vc,
|
||||
do_lasso_select_pose__do_tag,
|
||||
&data,
|
||||
V3D_PROJ_TEST_CLIP_DEFAULT | V3D_PROJ_TEST_CLIP_CONTENT_DEFAULT);
|
||||
|
@ -617,22 +615,37 @@ static bool do_lasso_select_objects(ViewContext *vc,
|
|||
*/
|
||||
static blender::Vector<Base *> do_pose_tag_select_op_prepare(ViewContext *vc)
|
||||
{
|
||||
blender::Vector<Base *> bases;
|
||||
|
||||
FOREACH_BASE_IN_MODE_BEGIN (
|
||||
vc->scene, vc->view_layer, vc->v3d, OB_ARMATURE, OB_MODE_POSE, base_iter)
|
||||
{
|
||||
Object *ob_iter = base_iter->object;
|
||||
bArmature *arm = static_cast<bArmature *>(ob_iter->data);
|
||||
LISTBASE_FOREACH (bPoseChannel *, pchan, &ob_iter->pose->chanbase) {
|
||||
auto bases_tag_and_append_fn = [](blender::Vector<Base *> &bases, Base *base) {
|
||||
Object *ob = base->object;
|
||||
bArmature *arm = static_cast<bArmature *>(ob->data);
|
||||
LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
|
||||
Bone *bone = pchan->bone;
|
||||
bone->flag &= ~BONE_DONE;
|
||||
}
|
||||
arm->id.tag |= LIB_TAG_DOIT;
|
||||
ob_iter->id.tag &= ~LIB_TAG_DOIT;
|
||||
bases.append(base_iter);
|
||||
ob->id.tag &= ~LIB_TAG_DOIT;
|
||||
bases.append(base);
|
||||
};
|
||||
|
||||
blender::Vector<Base *> bases;
|
||||
|
||||
/* Special case, pose + weight paint mode. */
|
||||
if (vc->obact && (vc->obact->mode & OB_MODE_WEIGHT_PAINT)) {
|
||||
Object *ob_pose = BKE_object_pose_armature_get_with_wpaint_check(vc->obact);
|
||||
BLI_assert(ob_pose != nullptr); /* Caller is expected to check. */
|
||||
Base *base = BKE_view_layer_base_find(vc->view_layer, ob_pose);
|
||||
if (base) {
|
||||
bases_tag_and_append_fn(bases, base);
|
||||
}
|
||||
}
|
||||
else {
|
||||
FOREACH_BASE_IN_MODE_BEGIN (
|
||||
vc->scene, vc->view_layer, vc->v3d, OB_ARMATURE, OB_MODE_POSE, base_iter)
|
||||
{
|
||||
bases_tag_and_append_fn(bases, base_iter);
|
||||
}
|
||||
FOREACH_BASE_IN_MODE_END;
|
||||
}
|
||||
FOREACH_BASE_IN_MODE_END;
|
||||
return bases;
|
||||
}
|
||||
|
||||
|
@ -697,10 +710,13 @@ static bool do_lasso_select_pose(ViewContext *vc,
|
|||
{
|
||||
blender::Vector<Base *> bases = do_pose_tag_select_op_prepare(vc);
|
||||
|
||||
ViewContext vc_temp = *vc;
|
||||
|
||||
for (const int i : bases.index_range()) {
|
||||
Base *base_iter = bases[i];
|
||||
Object *ob_iter = base_iter->object;
|
||||
do_lasso_tag_pose(vc, ob_iter, mcoords, mcoords_len);
|
||||
ED_view3d_viewcontext_init_object(&vc_temp, ob_iter);
|
||||
do_lasso_tag_pose(&vc_temp, mcoords, mcoords_len);
|
||||
}
|
||||
|
||||
const bool changed_multi = do_pose_tag_select_op_exec(bases, sel_op);
|
||||
|
@ -1382,20 +1398,23 @@ static bool view3d_lasso_select(bContext *C,
|
|||
else if (BKE_paint_select_vert_test(ob)) {
|
||||
changed_multi |= do_lasso_select_paintvert(vc, wm_userdata, mcoords, mcoords_len, sel_op);
|
||||
}
|
||||
else if (ob &&
|
||||
(ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)))
|
||||
{
|
||||
/* pass */
|
||||
}
|
||||
else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
|
||||
changed_multi |= PE_lasso_select(C, mcoords, mcoords_len, sel_op) != OPERATOR_CANCELLED;
|
||||
}
|
||||
else if (ob && (ob->mode & OB_MODE_POSE)) {
|
||||
else if (ob &&
|
||||
((ob->mode & OB_MODE_POSE) | ((ob->mode & OB_MODE_WEIGHT_PAINT) &&
|
||||
BKE_object_pose_armature_get_with_wpaint_check(ob))))
|
||||
{
|
||||
changed_multi |= do_lasso_select_pose(vc, mcoords, mcoords_len, sel_op);
|
||||
if (changed_multi) {
|
||||
ED_outliner_select_sync_from_pose_bone_tag(C);
|
||||
}
|
||||
}
|
||||
else if (ob &&
|
||||
(ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)))
|
||||
{
|
||||
/* pass */
|
||||
}
|
||||
else {
|
||||
changed_multi |= do_lasso_select_objects(vc, mcoords, mcoords_len, sel_op);
|
||||
if (changed_multi) {
|
||||
|
@ -4369,7 +4388,10 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op)
|
|||
else if (vc.obact && vc.obact->mode & OB_MODE_PARTICLE_EDIT) {
|
||||
changed_multi = PE_box_select(C, &rect, sel_op);
|
||||
}
|
||||
else if (vc.obact && vc.obact->mode & OB_MODE_POSE) {
|
||||
else if (vc.obact && ((vc.obact->mode & OB_MODE_POSE) ||
|
||||
((vc.obact->mode & OB_MODE_WEIGHT_PAINT) &&
|
||||
BKE_object_pose_armature_get_with_wpaint_check(vc.obact))))
|
||||
{
|
||||
changed_multi = do_pose_box_select(C, &vc, &rect, sel_op);
|
||||
if (changed_multi) {
|
||||
ED_outliner_select_sync_from_pose_bone_tag(C);
|
||||
|
@ -5345,6 +5367,14 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
|
|||
else if (obact && obact->mode & OB_MODE_SCULPT) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
else if (Object *obact_pose = (obact && (obact->mode & OB_MODE_WEIGHT_PAINT)) ?
|
||||
BKE_object_pose_armature_get_with_wpaint_check(obact) :
|
||||
nullptr)
|
||||
{
|
||||
ED_view3d_viewcontext_init_object(&vc, obact_pose);
|
||||
pose_circle_select(&vc, sel_op, mval, float(radius));
|
||||
ED_outliner_select_sync_from_pose_bone_tag(C);
|
||||
}
|
||||
else {
|
||||
if (object_circle_select(&vc, sel_op, mval, float(radius))) {
|
||||
DEG_id_tag_update(&vc.scene->id, ID_RECALC_SELECT);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue