diff options
author | YimingWu <xp8110@outlook.com> | 2019-09-04 06:30:16 +0300 |
---|---|---|
committer | YimingWu <xp8110@outlook.com> | 2019-09-04 06:30:16 +0300 |
commit | 55a6fc0be3ffa823052aba45bec12c6902e7bd53 (patch) | |
tree | fb8cb4e411e22fcb49e443ea4da636660618877f /source/blender | |
parent | afac2afbfcdb06a2d2655e63d0b8bc35b1aba18e (diff) | |
parent | da25aca2677ec2b566cad1809eebceee22b28b53 (diff) |
Merge remote-tracking branch 'origin/master' into soc-2019-npr
Diffstat (limited to 'source/blender')
813 files changed, 21902 insertions, 13536 deletions
diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt index 76442048594..203543b0ef0 100644 --- a/source/blender/CMakeLists.txt +++ b/source/blender/CMakeLists.txt @@ -153,3 +153,7 @@ endif() if(WITH_ALEMBIC) add_subdirectory(alembic) endif() + +if(WIN32) + add_subdirectory(blendthumb) +endif() diff --git a/source/blender/alembic/ABC_alembic.h b/source/blender/alembic/ABC_alembic.h index 653382017d6..696e0ff1810 100644 --- a/source/blender/alembic/ABC_alembic.h +++ b/source/blender/alembic/ABC_alembic.h @@ -117,6 +117,12 @@ struct Mesh *ABC_read_mesh(struct CacheReader *reader, const char **err_str, int flags); +bool ABC_mesh_topology_changed(struct CacheReader *reader, + struct Object *ob, + struct Mesh *existing_mesh, + const float time, + const char **err_str); + void CacheReader_incref(struct CacheReader *reader); void CacheReader_free(struct CacheReader *reader); diff --git a/source/blender/alembic/intern/abc_mball.h b/source/blender/alembic/intern/abc_mball.h index 770fa6fdf8c..4be977fa8f5 100644 --- a/source/blender/alembic/intern/abc_mball.h +++ b/source/blender/alembic/intern/abc_mball.h @@ -24,9 +24,7 @@ #include "abc_object.h" #include "abc_mesh.h" -struct EvaluationContext; struct Main; -struct MetaBall; struct Object; /* AbcMBallWriter converts the metaballs to meshes at every frame, diff --git a/source/blender/alembic/intern/abc_mesh.cc b/source/blender/alembic/intern/abc_mesh.cc index 6647ca83bd6..8728303923a 100644 --- a/source/blender/alembic/intern/abc_mesh.cc +++ b/source/blender/alembic/intern/abc_mesh.cc @@ -1131,6 +1131,31 @@ bool AbcMeshReader::accepts_object_type( return true; } +bool AbcMeshReader::topology_changed(Mesh *existing_mesh, const ISampleSelector &sample_sel) +{ + IPolyMeshSchema::Sample sample; + try { + sample = m_schema.getValue(sample_sel); + } + catch (Alembic::Util::Exception &ex) { + printf("Alembic: error reading mesh sample for '%s/%s' at time %f: %s\n", + m_iobject.getFullName().c_str(), + m_schema.getName().c_str(), + sample_sel.getRequestedTime(), + ex.what()); + // A similar error in read_mesh() would just return existing_mesh. + return false; + } + + const P3fArraySamplePtr &positions = sample.getPositions(); + const Alembic::Abc::Int32ArraySamplePtr &face_indices = sample.getFaceIndices(); + const Alembic::Abc::Int32ArraySamplePtr &face_counts = sample.getFaceCounts(); + + return positions->size() != existing_mesh->totvert || + face_counts->size() != existing_mesh->totpoly || + face_indices->size() != existing_mesh->totloop; +} + Mesh *AbcMeshReader::read_mesh(Mesh *existing_mesh, const ISampleSelector &sample_sel, int read_flag, @@ -1162,10 +1187,7 @@ Mesh *AbcMeshReader::read_mesh(Mesh *existing_mesh, ImportSettings settings; settings.read_flag |= read_flag; - bool topology_changed = positions->size() != existing_mesh->totvert || - face_counts->size() != existing_mesh->totpoly || - face_indices->size() != existing_mesh->totloop; - if (topology_changed) { + if (topology_changed(existing_mesh, sample_sel)) { new_mesh = BKE_mesh_new_nomain_from_template( existing_mesh, positions->size(), 0, 0, face_indices->size(), face_counts->size()); @@ -1314,7 +1336,7 @@ static void read_subd_sample(const std::string &iobject_full_name, if ((settings->read_flag & MOD_MESHSEQ_READ_POLY) != 0) { /* Alembic's 'SubD' scheme is used to store subdivision surfaces, i.e. the pre-subdivision - * mesh. Currently we don't add a subdivison modifier when we load such data. This code is + * mesh. Currently we don't add a subdivision modifier when we load such data. This code is * assuming that the subdivided surface should be smooth, and sets a flag that will eventually * mark all polygons as such. */ abc_mesh_data.poly_flag_smooth = true; diff --git a/source/blender/alembic/intern/abc_mesh.h b/source/blender/alembic/intern/abc_mesh.h index 859ab121eb6..c15fb948e03 100644 --- a/source/blender/alembic/intern/abc_mesh.h +++ b/source/blender/alembic/intern/abc_mesh.h @@ -100,16 +100,18 @@ class AbcMeshReader : public AbcObjectReader { public: AbcMeshReader(const Alembic::Abc::IObject &object, ImportSettings &settings); - bool valid() const; + bool valid() const override; bool accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header, const Object *const ob, - const char **err_str) const; - void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel); + const char **err_str) const override; + void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel) override; struct Mesh *read_mesh(struct Mesh *existing_mesh, const Alembic::Abc::ISampleSelector &sample_sel, int read_flag, - const char **err_str); + const char **err_str) override; + bool topology_changed(Mesh *existing_mesh, + const Alembic::Abc::ISampleSelector &sample_sel) override; private: void readFaceSetsSample(Main *bmain, diff --git a/source/blender/alembic/intern/abc_object.cc b/source/blender/alembic/intern/abc_object.cc index f863fe4fee7..ebebbc0da1e 100644 --- a/source/blender/alembic/intern/abc_object.cc +++ b/source/blender/alembic/intern/abc_object.cc @@ -246,6 +246,14 @@ struct Mesh *AbcObjectReader::read_mesh(struct Mesh *existing_mesh, return existing_mesh; } +bool AbcObjectReader::topology_changed(Mesh * /*existing_mesh*/, + const Alembic::Abc::ISampleSelector & /*sample_sel*/) +{ + /* The default implementation of read_mesh() just returns the original mesh, so never changes the + * topology. */ + return false; +} + void AbcObjectReader::setupObjectTransform(const float time) { bool is_constant = false; diff --git a/source/blender/alembic/intern/abc_object.h b/source/blender/alembic/intern/abc_object.h index 537f24ab7d6..efe78b9017c 100644 --- a/source/blender/alembic/intern/abc_object.h +++ b/source/blender/alembic/intern/abc_object.h @@ -190,6 +190,8 @@ class AbcObjectReader { const Alembic::Abc::ISampleSelector &sample_sel, int read_flag, const char **err_str); + virtual bool topology_changed(Mesh *existing_mesh, + const Alembic::Abc::ISampleSelector &sample_sel); /** Reads the object matrix and sets up an object transform if animated. */ void setupObjectTransform(const float time); diff --git a/source/blender/alembic/intern/abc_util.h b/source/blender/alembic/intern/abc_util.h index f7f662212fd..5eb0ed70599 100644 --- a/source/blender/alembic/intern/abc_util.h +++ b/source/blender/alembic/intern/abc_util.h @@ -44,7 +44,6 @@ using Alembic::Abc::chrono_t; class AbcObjectReader; struct ImportSettings; -struct Base; struct ID; struct Object; diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc index d63b310fef7..dc525e0c46c 100644 --- a/source/blender/alembic/intern/alembic_capi.cc +++ b/source/blender/alembic/intern/alembic_capi.cc @@ -937,12 +937,7 @@ void ABC_get_transform(CacheReader *reader, float r_mat[4][4], float time, float /* ************************************************************************** */ -Mesh *ABC_read_mesh(CacheReader *reader, - Object *ob, - Mesh *existing_mesh, - const float time, - const char **err_str, - int read_flag) +static AbcObjectReader *get_abc_reader(CacheReader *reader, Object *ob, const char **err_str) { AbcObjectReader *abc_reader = reinterpret_cast<AbcObjectReader *>(reader); IObject iobject = abc_reader->iobject(); @@ -958,12 +953,44 @@ Mesh *ABC_read_mesh(CacheReader *reader, return NULL; } + return abc_reader; +} + +static ISampleSelector sample_selector_for_time(float time) +{ /* kFloorIndex is used to be compatible with non-interpolating * properties; they use the floor. */ - ISampleSelector sample_sel(time, ISampleSelector::kFloorIndex); + return ISampleSelector(time, ISampleSelector::kFloorIndex); +} + +Mesh *ABC_read_mesh(CacheReader *reader, + Object *ob, + Mesh *existing_mesh, + const float time, + const char **err_str, + int read_flag) +{ + AbcObjectReader *abc_reader = get_abc_reader(reader, ob, err_str); + if (abc_reader == NULL) { + return NULL; + } + + ISampleSelector sample_sel = sample_selector_for_time(time); return abc_reader->read_mesh(existing_mesh, sample_sel, read_flag, err_str); } +bool ABC_mesh_topology_changed( + CacheReader *reader, Object *ob, Mesh *existing_mesh, const float time, const char **err_str) +{ + AbcObjectReader *abc_reader = get_abc_reader(reader, ob, err_str); + if (abc_reader == NULL) { + return false; + } + + ISampleSelector sample_sel = sample_selector_for_time(time); + return abc_reader->topology_changed(existing_mesh, sample_sel); +} + /* ************************************************************************** */ void CacheReader_free(CacheReader *reader) diff --git a/source/blender/blendthumb/CMakeLists.txt b/source/blender/blendthumb/CMakeLists.txt new file mode 100644 index 00000000000..6c786dfcc7a --- /dev/null +++ b/source/blender/blendthumb/CMakeLists.txt @@ -0,0 +1,38 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# The Original Code is Copyright (C) 2006, Blender Foundation +# All rights reserved. +# ***** END GPL LICENSE BLOCK ***** + +#----------------------------------------------------------------------------- +include_directories(${ZLIB_INCLUDE_DIRS}) + +set(SRC + src/BlenderThumb.cpp + src/BlendThumb.def + src/BlendThumb.rc + src/Dll.cpp +) + +add_library(BlendThumb SHARED ${SRC}) +target_link_libraries(BlendThumb ${ZLIB_LIBRARIES}) + +install( + FILES $<TARGET_FILE:BlendThumb> + COMPONENT Blender + DESTINATION "." +) diff --git a/source/blender/blendthumb/src/BlendThumb.def b/source/blender/blendthumb/src/BlendThumb.def new file mode 100644 index 00000000000..71f9236735f --- /dev/null +++ b/source/blender/blendthumb/src/BlendThumb.def @@ -0,0 +1,5 @@ +EXPORTS + DllGetClassObject PRIVATE + DllCanUnloadNow PRIVATE + DllRegisterServer PRIVATE + DllUnregisterServer PRIVATE
\ No newline at end of file diff --git a/source/blender/blendthumb/src/BlendThumb.rc b/source/blender/blendthumb/src/BlendThumb.rc new file mode 100644 index 00000000000..5dfd416b0c5 --- /dev/null +++ b/source/blender/blendthumb/src/BlendThumb.rc @@ -0,0 +1,26 @@ +#define IDR_VERSION1 1 + +IDR_VERSION1 VERSIONINFO +FILEVERSION 1,4,0,0 +PRODUCTVERSION 2,78,0,0 +FILEOS 0x00000004 +FILETYPE 0x00000002 +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "FFFF04B0" + BEGIN + VALUE "FileVersion", "1.4\0" + VALUE "ProductVersion", "2.78\0" + VALUE "FileDescription", "Blender Thumbnail Handler\0" + VALUE "OriginalFilename", "BlendThumb.dll\0" + VALUE "ProductName", "Blender\0" + VALUE "LegalCopyright", "GPL2, 2016\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 0x04B0 + END +END + diff --git a/source/blender/blendthumb/src/BlenderThumb.cpp b/source/blender/blendthumb/src/BlenderThumb.cpp new file mode 100644 index 00000000000..94dae437260 --- /dev/null +++ b/source/blender/blendthumb/src/BlenderThumb.cpp @@ -0,0 +1,313 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <shlwapi.h> +#include <thumbcache.h> // For IThumbnailProvider. +#include <new> + +#pragma comment(lib, "shlwapi.lib") + +// this thumbnail provider implements IInitializeWithStream to enable being hosted +// in an isolated process for robustness + +class CBlendThumb : public IInitializeWithStream, public IThumbnailProvider { + public: + CBlendThumb() : _cRef(1), _pStream(NULL) + { + } + + virtual ~CBlendThumb() + { + if (_pStream) { + _pStream->Release(); + } + } + + // IUnknown + IFACEMETHODIMP QueryInterface(REFIID riid, void **ppv) + { + static const QITAB qit[] = { + QITABENT(CBlendThumb, IInitializeWithStream), + QITABENT(CBlendThumb, IThumbnailProvider), + {0}, + }; + return QISearch(this, qit, riid, ppv); + } + + IFACEMETHODIMP_(ULONG) AddRef() + { + return InterlockedIncrement(&_cRef); + } + + IFACEMETHODIMP_(ULONG) Release() + { + ULONG cRef = InterlockedDecrement(&_cRef); + if (!cRef) { + delete this; + } + return cRef; + } + + // IInitializeWithStream + IFACEMETHODIMP Initialize(IStream *pStream, DWORD grfMode); + + // IThumbnailProvider + IFACEMETHODIMP GetThumbnail(UINT cx, HBITMAP *phbmp, WTS_ALPHATYPE *pdwAlpha); + + private: + long _cRef; + IStream *_pStream; // provided during initialization. +}; + +HRESULT CBlendThumb_CreateInstance(REFIID riid, void **ppv) +{ + CBlendThumb *pNew = new (std::nothrow) CBlendThumb(); + HRESULT hr = pNew ? S_OK : E_OUTOFMEMORY; + if (SUCCEEDED(hr)) { + hr = pNew->QueryInterface(riid, ppv); + pNew->Release(); + } + return hr; +} + +// IInitializeWithStream +IFACEMETHODIMP CBlendThumb::Initialize(IStream *pStream, DWORD) +{ + HRESULT hr = E_UNEXPECTED; // can only be inited once + if (_pStream == NULL) { + // take a reference to the stream if we have not been inited yet + hr = pStream->QueryInterface(&_pStream); + } + return hr; +} + +#include <math.h> +#include <zlib.h> +#include "Wincodec.h" +const unsigned char gzip_magic[3] = {0x1f, 0x8b, 0x08}; + +// IThumbnailProvider +IFACEMETHODIMP CBlendThumb::GetThumbnail(UINT cx, HBITMAP *phbmp, WTS_ALPHATYPE *pdwAlpha) +{ + ULONG BytesRead; + HRESULT hr = S_FALSE; + LARGE_INTEGER SeekPos; + + // Compressed? + unsigned char in_magic[3]; + _pStream->Read(&in_magic, 3, &BytesRead); + bool gzipped = true; + for (int i = 0; i < 3; i++) + if (in_magic[i] != gzip_magic[i]) { + gzipped = false; + break; + } + + if (gzipped) { + // Zlib inflate + z_stream stream; + stream.zalloc = Z_NULL; + stream.zfree = Z_NULL; + stream.opaque = Z_NULL; + + // Get compressed file length + SeekPos.QuadPart = 0; + _pStream->Seek(SeekPos, STREAM_SEEK_END, NULL); + + // Get compressed and uncompressed size + uLong source_size; + uLongf dest_size; + // SeekPos.QuadPart = -4; // last 4 bytes define size of uncompressed file + // ULARGE_INTEGER Tell; + //_pStream->Seek(SeekPos,STREAM_SEEK_END,&Tell); + // source_size = (uLong)Tell.QuadPart + 4; // src + //_pStream->Read(&dest_size,4,&BytesRead); // dest + dest_size = 1024 * 70; // thumbnail is currently always inside the first 65KB...if it moves or + // enlargens this line will have to change or go! + source_size = (uLong)max(SeekPos.QuadPart, dest_size); // for safety, assume no compression + + // Input + Bytef *src = new Bytef[source_size]; + stream.next_in = (Bytef *)src; + stream.avail_in = (uInt)source_size; + + // Output + Bytef *dest = new Bytef[dest_size]; + stream.next_out = (Bytef *)dest; + stream.avail_out = dest_size; + + // IStream to src + SeekPos.QuadPart = 0; + _pStream->Seek(SeekPos, STREAM_SEEK_SET, NULL); + _pStream->Read(src, source_size, &BytesRead); + + // Do the inflation + int err; + err = inflateInit2(&stream, 16); // 16 means "gzip"...nice! + err = inflate(&stream, Z_FINISH); + err = inflateEnd(&stream); + + // Replace the IStream, which is read-only + _pStream->Release(); + _pStream = SHCreateMemStream(dest, dest_size); + + delete[] src; + delete[] dest; + } + + // Blender version, early out if sub 2.5 + SeekPos.QuadPart = 9; + _pStream->Seek(SeekPos, STREAM_SEEK_SET, NULL); + char version[4]; + version[3] = '\0'; + _pStream->Read(&version, 3, &BytesRead); + if (BytesRead != 3) + return E_UNEXPECTED; + int iVersion = atoi(version); + if (iVersion < 250) + return S_FALSE; + + // 32 or 64 bit blend? + SeekPos.QuadPart = 7; + _pStream->Seek(SeekPos, STREAM_SEEK_SET, NULL); + + char _PointerSize; + _pStream->Read(&_PointerSize, 1, &BytesRead); + + int PointerSize = _PointerSize == '_' ? 4 : 8; + int HeaderSize = 16 + PointerSize; + + // Find and read thumbnail ("TEST") block + SeekPos.QuadPart = 12; + _pStream->Seek(SeekPos, STREAM_SEEK_SET, NULL); + int BlockOffset = 12; + while (_pStream) { + // Scan current block + char BlockName[5]; + BlockName[4] = '\0'; + int BlockSize = 0; + + if (_pStream->Read(BlockName, 4, &BytesRead) == S_OK && + _pStream->Read((void *)&BlockSize, 4, &BytesRead) == S_OK) { + if (strcmp(BlockName, "TEST") != 0) { + SeekPos.QuadPart = BlockOffset += HeaderSize + BlockSize; + _pStream->Seek(SeekPos, STREAM_SEEK_SET, NULL); + continue; + } + } + else + break; // eof + + // Found the block + SeekPos.QuadPart = BlockOffset + HeaderSize; + _pStream->Seek(SeekPos, STREAM_SEEK_SET, NULL); + + int width, height; + _pStream->Read((char *)&width, 4, &BytesRead); + _pStream->Read((char *)&height, 4, &BytesRead); + BlockSize -= 8; + + // Isolate RGBA data + char *pRGBA = new char[BlockSize]; + _pStream->Read(pRGBA, BlockSize, &BytesRead); + + if (BytesRead != (ULONG)BlockSize) + return E_UNEXPECTED; + + // Convert to BGRA for Windows + for (int i = 0; i < BlockSize; i += 4) { +#define RED_BYTE pRGBA[i] +#define BLUE_BYTE pRGBA[i + 2] + + char red = RED_BYTE; + RED_BYTE = BLUE_BYTE; + BLUE_BYTE = red; + } + + // Flip vertically (Blender stores it upside-down) + unsigned int LineSize = width * 4; + char *FlippedImage = new char[BlockSize]; + for (int i = 0; i < height; i++) { + if (0 != memcpy_s(&FlippedImage[(height - i - 1) * LineSize], + LineSize, + &pRGBA[i * LineSize], + LineSize)) + return E_UNEXPECTED; + } + delete[] pRGBA; + pRGBA = FlippedImage; + + // Create image + *phbmp = CreateBitmap(width, height, 1, 32, pRGBA); + if (!*phbmp) + return E_FAIL; + *pdwAlpha = WTSAT_ARGB; // it's actually BGRA, not sure why this works + + // Scale down if required + if ((unsigned)width > cx || (unsigned)height > cx) { + float scale = 1.0f / (max(width, height) / (float)cx); + LONG NewWidth = (LONG)(width * scale); + LONG NewHeight = (LONG)(height * scale); + +#ifdef _DEBUG +# if 0 + MessageBox(0,"Attach now","Debugging",MB_OK); +# endif +#endif + IWICImagingFactory *pImgFac; + hr = CoCreateInstance( + CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pImgFac)); + + IWICBitmap *WICBmp; + hr = pImgFac->CreateBitmapFromHBITMAP(*phbmp, 0, WICBitmapUseAlpha, &WICBmp); + + BITMAPINFO bmi = {}; + bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader); + bmi.bmiHeader.biWidth = NewWidth; + bmi.bmiHeader.biHeight = -NewHeight; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 32; + bmi.bmiHeader.biCompression = BI_RGB; + + BYTE *pBits; + HBITMAP ResizedHBmp = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, (void **)&pBits, NULL, 0); + hr = ResizedHBmp ? S_OK : E_OUTOFMEMORY; + if (SUCCEEDED(hr)) { + IWICBitmapScaler *pIScaler; + hr = pImgFac->CreateBitmapScaler(&pIScaler); + hr = pIScaler->Initialize(WICBmp, NewWidth, NewHeight, WICBitmapInterpolationModeFant); + + WICRect rect = {0, 0, NewWidth, NewHeight}; + hr = pIScaler->CopyPixels(&rect, NewWidth * 4, NewWidth * NewHeight * 4, pBits); + + if (SUCCEEDED(hr)) { + DeleteObject(*phbmp); + *phbmp = ResizedHBmp; + } + else + DeleteObject(ResizedHBmp); + + pIScaler->Release(); + } + WICBmp->Release(); + pImgFac->Release(); + } + else + hr = S_OK; + break; + } + return hr; +} diff --git a/source/blender/blendthumb/src/Dll.cpp b/source/blender/blendthumb/src/Dll.cpp new file mode 100644 index 00000000000..5a6fb4e692c --- /dev/null +++ b/source/blender/blendthumb/src/Dll.cpp @@ -0,0 +1,280 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <objbase.h> +#include <shlwapi.h> +#include <thumbcache.h> // For IThumbnailProvider. +#include <shlobj.h> // For SHChangeNotify +#include <new> + +extern HRESULT CBlendThumb_CreateInstance(REFIID riid, void **ppv); + +#define SZ_CLSID_BLENDTHUMBHANDLER L"{D45F043D-F17F-4e8a-8435-70971D9FA46D}" +#define SZ_BLENDTHUMBHANDLER L"Blender Thumbnail Handler" +const CLSID CLSID_BlendThumbHandler = { + 0xd45f043d, 0xf17f, 0x4e8a, {0x84, 0x35, 0x70, 0x97, 0x1d, 0x9f, 0xa4, 0x6d}}; + +typedef HRESULT (*PFNCREATEINSTANCE)(REFIID riid, void **ppvObject); +struct CLASS_OBJECT_INIT { + const CLSID *pClsid; + PFNCREATEINSTANCE pfnCreate; +}; + +// add classes supported by this module here +const CLASS_OBJECT_INIT c_rgClassObjectInit[] = { + {&CLSID_BlendThumbHandler, CBlendThumb_CreateInstance}}; + +long g_cRefModule = 0; + +// Handle the DLL's module +HINSTANCE g_hInst = NULL; + +// Standard DLL functions +STDAPI_(BOOL) DllMain(HINSTANCE hInstance, DWORD dwReason, void *) +{ + if (dwReason == DLL_PROCESS_ATTACH) { + g_hInst = hInstance; + DisableThreadLibraryCalls(hInstance); + } + return TRUE; +} + +STDAPI DllCanUnloadNow() +{ + // Only allow the DLL to be unloaded after all outstanding references have been released + return (g_cRefModule == 0) ? S_OK : S_FALSE; +} + +void DllAddRef() +{ + InterlockedIncrement(&g_cRefModule); +} + +void DllRelease() +{ + InterlockedDecrement(&g_cRefModule); +} + +class CClassFactory : public IClassFactory { + public: + static HRESULT CreateInstance(REFCLSID clsid, + const CLASS_OBJECT_INIT *pClassObjectInits, + size_t cClassObjectInits, + REFIID riid, + void **ppv) + { + *ppv = NULL; + HRESULT hr = CLASS_E_CLASSNOTAVAILABLE; + for (size_t i = 0; i < cClassObjectInits; i++) { + if (clsid == *pClassObjectInits[i].pClsid) { + IClassFactory *pClassFactory = new (std::nothrow) + CClassFactory(pClassObjectInits[i].pfnCreate); + hr = pClassFactory ? S_OK : E_OUTOFMEMORY; + if (SUCCEEDED(hr)) { + hr = pClassFactory->QueryInterface(riid, ppv); + pClassFactory->Release(); + } + break; // match found + } + } + return hr; + } + + CClassFactory(PFNCREATEINSTANCE pfnCreate) : _cRef(1), _pfnCreate(pfnCreate) + { + DllAddRef(); + } + + // IUnknown + IFACEMETHODIMP QueryInterface(REFIID riid, void **ppv) + { + static const QITAB qit[] = {QITABENT(CClassFactory, IClassFactory), {0}}; + return QISearch(this, qit, riid, ppv); + } + + IFACEMETHODIMP_(ULONG) AddRef() + { + return InterlockedIncrement(&_cRef); + } + + IFACEMETHODIMP_(ULONG) Release() + { + long cRef = InterlockedDecrement(&_cRef); + if (cRef == 0) { + delete this; + } + return cRef; + } + + // IClassFactory + IFACEMETHODIMP CreateInstance(IUnknown *punkOuter, REFIID riid, void **ppv) + { + return punkOuter ? CLASS_E_NOAGGREGATION : _pfnCreate(riid, ppv); + } + + IFACEMETHODIMP LockServer(BOOL fLock) + { + if (fLock) { + DllAddRef(); + } + else { + DllRelease(); + } + return S_OK; + } + + private: + ~CClassFactory() + { + DllRelease(); + } + + long _cRef; + PFNCREATEINSTANCE _pfnCreate; +}; + +STDAPI DllGetClassObject(REFCLSID clsid, REFIID riid, void **ppv) +{ + return CClassFactory::CreateInstance( + clsid, c_rgClassObjectInit, ARRAYSIZE(c_rgClassObjectInit), riid, ppv); +} + +// A struct to hold the information required for a registry entry + +struct REGISTRY_ENTRY { + HKEY hkeyRoot; + PCWSTR pszKeyName; + PCWSTR pszValueName; + DWORD dwValueType; + PCWSTR pszData; +}; + +// Creates a registry key (if needed) and sets the default value of the key + +HRESULT CreateRegKeyAndSetValue(const REGISTRY_ENTRY *pRegistryEntry) +{ + HKEY hKey; + HRESULT hr = HRESULT_FROM_WIN32(RegCreateKeyExW(pRegistryEntry->hkeyRoot, + pRegistryEntry->pszKeyName, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_SET_VALUE, + NULL, + &hKey, + NULL)); + if (SUCCEEDED(hr)) { + // All this just to support REG_DWORD... + DWORD size; + DWORD data; + BYTE *lpData = (LPBYTE)pRegistryEntry->pszData; + switch (pRegistryEntry->dwValueType) { + case REG_SZ: + size = ((DWORD)wcslen(pRegistryEntry->pszData) + 1) * sizeof(WCHAR); + break; + case REG_DWORD: + size = sizeof(DWORD); + data = (DWORD)pRegistryEntry->pszData; + lpData = (BYTE *)&data; + break; + default: + return E_INVALIDARG; + } + + hr = HRESULT_FROM_WIN32(RegSetValueExW( + hKey, pRegistryEntry->pszValueName, 0, pRegistryEntry->dwValueType, lpData, size)); + RegCloseKey(hKey); + } + return hr; +} + +// +// Registers this COM server +// +STDAPI DllRegisterServer() +{ + HRESULT hr; + + WCHAR szModuleName[MAX_PATH]; + + if (!GetModuleFileNameW(g_hInst, szModuleName, ARRAYSIZE(szModuleName))) { + hr = HRESULT_FROM_WIN32(GetLastError()); + } + else { + const REGISTRY_ENTRY rgRegistryEntries[] = { + // RootKey KeyName ValueName ValueType Data + {HKEY_CURRENT_USER, + L"Software\\Classes\\CLSID\\" SZ_CLSID_BLENDTHUMBHANDLER, + NULL, + REG_SZ, + SZ_BLENDTHUMBHANDLER}, + {HKEY_CURRENT_USER, + L"Software\\Classes\\CLSID\\" SZ_CLSID_BLENDTHUMBHANDLER L"\\InProcServer32", + NULL, + REG_SZ, + szModuleName}, + {HKEY_CURRENT_USER, + L"Software\\Classes\\CLSID\\" SZ_CLSID_BLENDTHUMBHANDLER L"\\InProcServer32", + L"ThreadingModel", + REG_SZ, + L"Apartment"}, + {HKEY_CURRENT_USER, + L"Software\\Classes\\.blend\\", + L"Treatment", + REG_DWORD, + 0}, // doesn't appear to do anything... + {HKEY_CURRENT_USER, + L"Software\\Classes\\.blend\\ShellEx\\{e357fccd-a995-4576-b01f-234630154e96}", + NULL, + REG_SZ, + SZ_CLSID_BLENDTHUMBHANDLER}, + }; + + hr = S_OK; + for (int i = 0; i < ARRAYSIZE(rgRegistryEntries) && SUCCEEDED(hr); i++) { + hr = CreateRegKeyAndSetValue(&rgRegistryEntries[i]); + } + } + if (SUCCEEDED(hr)) { + // This tells the shell to invalidate the thumbnail cache. This is important because any + // .blend files viewed before registering this handler would otherwise show cached blank + // thumbnails. + SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); + } + return hr; +} + +// +// Unregisters this COM server +// +STDAPI DllUnregisterServer() +{ + HRESULT hr = S_OK; + + const PCWSTR rgpszKeys[] = { + L"Software\\Classes\\CLSID\\" SZ_CLSID_BLENDTHUMBHANDLER, + L"Software\\Classes\\.blend\\ShellEx\\{e357fccd-a995-4576-b01f-234630154e96}"}; + + // Delete the registry entries + for (int i = 0; i < ARRAYSIZE(rgpszKeys) && SUCCEEDED(hr); i++) { + hr = HRESULT_FROM_WIN32(RegDeleteTreeW(HKEY_CURRENT_USER, rgpszKeys[i])); + if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) { + // If the registry entry has already been deleted, say S_OK. + hr = S_OK; + } + } + return hr; +} diff --git a/source/blender/blenfont/intern/blf_thumbs.c b/source/blender/blenfont/intern/blf_thumbs.c index d6710b91539..4e44a85443d 100644 --- a/source/blender/blenfont/intern/blf_thumbs.c +++ b/source/blender/blenfont/intern/blf_thumbs.c @@ -109,7 +109,7 @@ void BLF_thumb_preview(const char *filename, font->pos[1] -= font->glyph_cache->ascender * 1.1f; /* We fallback to default english strings in case not enough chars are available in current - * font for given translated string (useful in non-latin i18n context, like chinese, + * font for given translated string (useful in non-latin i18n context, like Chinese, * since many fonts will then show nothing but ugly 'missing char' in their preview). * Does not handle all cases, but much better than nothing. */ diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index d215f214a6d..2145a673e45 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -79,12 +79,10 @@ struct CustomData_MeshMasks; struct Depsgraph; struct MEdge; struct MFace; -struct MLoopNorSpaceArray; struct MVert; struct Mesh; struct ModifierData; struct Object; -struct PBVH; struct Scene; /* @@ -150,23 +148,6 @@ struct DerivedMesh { /** Calculate vert and face normals */ void (*calcNormals)(DerivedMesh *dm); - /** Calculate loop (split) normals */ - void (*calcLoopNormals)(DerivedMesh *dm, const bool use_split_normals, const float split_angle); - - /** Calculate loop (split) normals, and returns split loop normal spacearr. */ - void (*calcLoopNormalsSpaceArray)(DerivedMesh *dm, - const bool use_split_normals, - const float split_angle, - struct MLoopNorSpaceArray *r_lnors_spacearr); - - void (*calcLoopTangents)(DerivedMesh *dm, - bool calc_active_tangent, - const char (*tangent_names)[MAX_NAME], - int tangent_names_count); - - /** Recalculates mesh tessellation */ - void (*recalcTessellation)(DerivedMesh *dm); - /** Loop tessellation cache (WARNING! Only call inside threading-protected code!) */ void (*recalcLoopTri)(DerivedMesh *dm); /** accessor functions */ @@ -261,51 +242,6 @@ struct DerivedMesh { DMFlagMat *(*getGridFlagMats)(DerivedMesh *dm); unsigned int **(*getGridHidden)(DerivedMesh *dm); - /** Iterate over each mapped vertex in the derived mesh, calling the - * given function with the original vert and the mapped vert's new - * coordinate and normal. For historical reasons the normal can be - * passed as a float or short array, only one should be non-NULL. - */ - void (*foreachMappedVert)(DerivedMesh *dm, - void (*func)(void *userData, - int index, - const float co[3], - const float no_f[3], - const short no_s[3]), - void *userData, - DMForeachFlag flag); - - /** Iterate over each mapped edge in the derived mesh, calling the - * given function with the original edge and the mapped edge's new - * coordinates. - */ - void (*foreachMappedEdge)( - DerivedMesh *dm, - void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]), - void *userData); - - /** Iterate over each mapped loop in the derived mesh, calling the given function - * with the original loop index and the mapped loops's new coordinate and normal. - */ - void (*foreachMappedLoop)(DerivedMesh *dm, - void (*func)(void *userData, - int vertex_index, - int face_index, - const float co[3], - const float no[3]), - void *userData, - DMForeachFlag flag); - - /** Iterate over each mapped face in the derived mesh, calling the - * given function with the original face and the mapped face's (or - * faces') center and normal. - */ - void (*foreachMappedFaceCenter)( - DerivedMesh *dm, - void (*func)(void *userData, int index, const float cent[3], const float no[3]), - void *userData, - DMForeachFlag flag); - /** Iterate over all vertex points, calling DO_MINMAX with given args. * * Also called in Editmode @@ -319,9 +255,6 @@ struct DerivedMesh { /** Get vertex location, undefined if index is not valid */ void (*getVertCo)(DerivedMesh *dm, int index, float r_co[3]); - /** Fill the array (of length .getNumVerts()) with all vertex locations */ - void (*getVertCos)(DerivedMesh *dm, float (*r_cos)[3]); - /** Get smooth vertex normal, undefined if index is not valid */ void (*getVertNo)(DerivedMesh *dm, int index, float r_no[3]); void (*getPolyNo)(DerivedMesh *dm, int index, float r_no[3]); @@ -330,10 +263,6 @@ struct DerivedMesh { */ const struct MeshElemMap *(*getPolyMap)(struct Object *ob, DerivedMesh *dm); - /** Get the BVH used for paint modes - */ - struct PBVH *(*getPBVH)(struct Object *ob, DerivedMesh *dm); - /** Release reference to the DerivedMesh. This function decides internally * if the DerivedMesh will be freed, or cached for later use. */ void (*release)(DerivedMesh *dm); @@ -372,14 +301,6 @@ void DM_from_template(DerivedMesh *dm, */ int DM_release(DerivedMesh *dm); -/** utility function to convert a DerivedMesh to a Mesh - */ -void DM_to_mesh(DerivedMesh *dm, - struct Mesh *me, - struct Object *ob, - const struct CustomData_MeshMasks *mask, - bool take_ownership); - void DM_set_only_copy(DerivedMesh *dm, const struct CustomData_MeshMasks *mask); /* adds a vertex/edge/face custom data layer to a DerivedMesh, optionally @@ -446,8 +367,6 @@ DerivedMesh *mesh_create_derived_render(struct Depsgraph *depsgraph, const struct CustomData_MeshMasks *dataMask); /* same as above but wont use render settings */ -DerivedMesh *mesh_create_derived(struct Mesh *me, float (*vertCos)[3]); - struct Mesh *editbmesh_get_eval_cage(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *, @@ -464,7 +383,7 @@ struct Mesh *editbmesh_get_eval_cage_and_final(struct Depsgraph *depsgraph, const struct CustomData_MeshMasks *dataMask, struct Mesh **r_final); -float (*editbmesh_get_vertex_cos(struct BMEditMesh *em, int *r_numVerts))[3]; +float (*editbmesh_vert_coords_alloc(struct BMEditMesh *em, int *r_vert_len))[3]; bool editbmesh_modifier_is_enabled(struct Scene *scene, struct ModifierData *md, bool has_prev_mesh); diff --git a/source/blender/blenkernel/BKE_anim.h b/source/blender/blenkernel/BKE_anim.h index dab76fb79f1..dce6f337885 100644 --- a/source/blender/blenkernel/BKE_anim.h +++ b/source/blender/blenkernel/BKE_anim.h @@ -24,7 +24,6 @@ */ struct Depsgraph; struct ListBase; -struct Main; struct Object; struct ParticleSystem; struct Path; diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h index fa8e294bdc1..a2a14011595 100644 --- a/source/blender/blenkernel/BKE_animsys.h +++ b/source/blender/blenkernel/BKE_animsys.h @@ -34,7 +34,6 @@ struct KeyingSet; struct ListBase; struct Main; struct NlaKeyframingContext; -struct PathResolvedRNA; struct PointerRNA; struct PropertyRNA; struct ReportList; diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index 99c6bb405b5..3beae7a1f9d 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -25,7 +25,6 @@ struct Bone; struct Depsgraph; -struct GHash; struct ListBase; struct Main; struct Object; @@ -78,6 +77,8 @@ struct bArmature *BKE_armature_copy(struct Main *bmain, const struct bArmature * void BKE_armature_copy_bone_transforms(struct bArmature *armature_dst, const struct bArmature *armature_src); +void BKE_armature_transform(struct bArmature *arm, const float mat[4][4], const bool do_props); + /* Bounding box. */ struct BoundBox *BKE_armature_boundbox_get(struct Object *ob); @@ -100,7 +101,7 @@ float distfactor_to_bone( void BKE_armature_where_is(struct bArmature *arm); void BKE_armature_where_is_bone(struct Bone *bone, - struct Bone *prevbone, + const struct Bone *bone_parent, const bool use_recursion); void BKE_pose_clear_pointers(struct bPose *pose); void BKE_pose_remap_bone_pointers(struct bArmature *armature, struct bPose *pose); diff --git a/source/blender/blenkernel/BKE_blender_undo.h b/source/blender/blenkernel/BKE_blender_undo.h index 6c2221326e9..7392d3947a2 100644 --- a/source/blender/blenkernel/BKE_blender_undo.h +++ b/source/blender/blenkernel/BKE_blender_undo.h @@ -26,7 +26,6 @@ extern "C" { struct Main; struct MemFileUndoData; -struct Scene; struct bContext; #define BKE_UNDO_STR_MAX 64 diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 0c55ae8ee83..65086f57616 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -27,7 +27,7 @@ * \note Use #STRINGIFY() rather than defining with quotes. */ #define BLENDER_VERSION 281 -#define BLENDER_SUBVERSION 2 +#define BLENDER_SUBVERSION 5 /** Several breakages with 280, e.g. collections vs layers. */ #define BLENDER_MINVERSION 280 #define BLENDER_MINSUBVERSION 0 @@ -37,6 +37,8 @@ #define BLENDER_VERSION_CHAR /** alpha/beta/rc/release, docs use this. */ #define BLENDER_VERSION_CYCLE alpha +/** Optionally set to 1,2,... for example to to get alpha1 or rc2. */ +#define BLENDER_VERSION_CYCLE_NUMBER /** Defined in from blender.c */ extern char versionstr[]; diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h index eeebfe1f2f6..26ab7f8ba0c 100644 --- a/source/blender/blenkernel/BKE_brush.h +++ b/source/blender/blenkernel/BKE_brush.h @@ -28,8 +28,6 @@ struct Brush; struct ImBuf; struct ImagePool; struct Main; -struct Material; -struct Paint; struct Scene; struct ToolSettings; struct UnifiedPaintSettings; diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h index c88a64097bb..fdcb4066482 100644 --- a/source/blender/blenkernel/BKE_bvhutils.h +++ b/source/blender/blenkernel/BKE_bvhutils.h @@ -31,7 +31,6 @@ */ struct BMEditMesh; -struct DerivedMesh; struct MFace; struct MVert; struct Mesh; @@ -93,19 +92,18 @@ typedef struct BVHTreeFromMesh { * * free_bvhtree_from_mesh should be called when the tree is no longer needed. */ -BVHTree *bvhtree_from_editmesh_verts(BVHTreeFromEditMesh *data, - struct BMEditMesh *em, - float epsilon, - int tree_type, - int axis, - BVHCache **bvh_cache); +BVHTree *bvhtree_from_editmesh_verts( + BVHTreeFromEditMesh *data, struct BMEditMesh *em, float epsilon, int tree_type, int axis); + BVHTree *bvhtree_from_editmesh_verts_ex(BVHTreeFromEditMesh *data, struct BMEditMesh *em, const BLI_bitmap *mask, int verts_num_active, float epsilon, int tree_type, - int axis); + int axis, + const int bvh_cache_type, + BVHCache **bvh_cache); BVHTree *bvhtree_from_mesh_verts_ex(struct BVHTreeFromMesh *data, const struct MVert *vert, @@ -115,21 +113,22 @@ BVHTree *bvhtree_from_mesh_verts_ex(struct BVHTreeFromMesh *data, int verts_num_active, float epsilon, int tree_type, - int axis); - -BVHTree *bvhtree_from_editmesh_edges(BVHTreeFromEditMesh *data, - struct BMEditMesh *em, - float epsilon, - int tree_type, - int axis, - BVHCache **bvh_cache); + int axis, + const int bvh_cache_type, + BVHCache **bvh_cache); + +BVHTree *bvhtree_from_editmesh_edges( + BVHTreeFromEditMesh *data, struct BMEditMesh *em, float epsilon, int tree_type, int axis); + BVHTree *bvhtree_from_editmesh_edges_ex(BVHTreeFromEditMesh *data, struct BMEditMesh *em, const BLI_bitmap *edges_mask, int edges_num_active, float epsilon, int tree_type, - int axis); + int axis, + const int bvh_cache_type, + BVHCache **bvh_cache); BVHTree *bvhtree_from_mesh_edges_ex(struct BVHTreeFromMesh *data, const struct MVert *vert, @@ -141,7 +140,9 @@ BVHTree *bvhtree_from_mesh_edges_ex(struct BVHTreeFromMesh *data, int edges_num_active, float epsilon, int tree_type, - int axis); + int axis, + const int bvh_cache_type, + BVHCache **bvh_cache); BVHTree *bvhtree_from_mesh_faces_ex(struct BVHTreeFromMesh *data, const struct MVert *vert, @@ -153,14 +154,13 @@ BVHTree *bvhtree_from_mesh_faces_ex(struct BVHTreeFromMesh *data, int numFaces_active, float epsilon, int tree_type, - int axis); + int axis, + const int bvh_cache_type, + BVHCache **bvh_cache); + +BVHTree *bvhtree_from_editmesh_looptri( + BVHTreeFromEditMesh *data, struct BMEditMesh *em, float epsilon, int tree_type, int axis); -BVHTree *bvhtree_from_editmesh_looptri(BVHTreeFromEditMesh *data, - struct BMEditMesh *em, - float epsilon, - int tree_type, - int axis, - BVHCache **bvhCache); BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data, struct BMEditMesh *em, const BLI_bitmap *mask, @@ -168,7 +168,8 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data, float epsilon, int tree_type, int axis, - BVHCache **bvhCache); + const int bvh_cache_type, + BVHCache **bvh_cache); BVHTree *bvhtree_from_mesh_looptri_ex(struct BVHTreeFromMesh *data, const struct MVert *vert, @@ -182,13 +183,21 @@ BVHTree *bvhtree_from_mesh_looptri_ex(struct BVHTreeFromMesh *data, int looptri_num_active, float epsilon, int tree_type, - int axis); + int axis, + const int bvh_cache_type, + BVHCache **bvh_cache); BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, struct Mesh *mesh, const int type, const int tree_type); +BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data, + struct BMEditMesh *em, + const int tree_type, + const int bvh_cache_type, + BVHCache **bvh_cache); + /** * Frees data allocated by a call to bvhtree_from_mesh_*. */ diff --git a/source/blender/blenkernel/BKE_cachefile.h b/source/blender/blenkernel/BKE_cachefile.h index 257975e3c17..c8393fd3666 100644 --- a/source/blender/blenkernel/BKE_cachefile.h +++ b/source/blender/blenkernel/BKE_cachefile.h @@ -33,7 +33,6 @@ struct CacheReader; struct Depsgraph; struct Main; struct Object; -struct Scene; void BKE_cachefiles_init(void); void BKE_cachefiles_exit(void); diff --git a/source/blender/blenkernel/BKE_camera.h b/source/blender/blenkernel/BKE_camera.h index caed4959eff..da80b3d5032 100644 --- a/source/blender/blenkernel/BKE_camera.h +++ b/source/blender/blenkernel/BKE_camera.h @@ -32,14 +32,12 @@ extern "C" { struct Camera; struct Depsgraph; -struct GPUFXSettings; struct Main; struct Object; struct RegionView3D; struct RenderData; struct Scene; struct View3D; -struct ViewLayer; struct rctf; /* Camera Datablock */ diff --git a/source/blender/blenkernel/BKE_cdderivedmesh.h b/source/blender/blenkernel/BKE_cdderivedmesh.h index 08d53bf0e21..50af6c876b4 100644 --- a/source/blender/blenkernel/BKE_cdderivedmesh.h +++ b/source/blender/blenkernel/BKE_cdderivedmesh.h @@ -33,9 +33,7 @@ struct BMEditMesh; struct CustomData_MeshMasks; struct DerivedMesh; -struct MLoopNorSpaceArray; struct Mesh; -struct Object; /* creates a new CDDerivedMesh */ struct DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces, int numLoops, int numPolys); @@ -51,79 +49,16 @@ struct DerivedMesh *CDDM_from_mesh_ex(struct Mesh *mesh, eCDAllocType alloctype, const struct CustomData_MeshMasks *mask); -struct DerivedMesh *CDDM_from_bmesh(struct BMesh *bm, const bool use_mdisps); - /* creates a CDDerivedMesh from the given BMEditMesh */ -DerivedMesh *CDDM_from_editbmesh(struct BMEditMesh *em, - const bool use_mdisps, - const bool use_tessface); - -/* creates a CDDerivedMesh from the given curve object */ -struct DerivedMesh *CDDM_from_curve(struct Object *ob); - -/* creates a CDDerivedMesh from the given curve object and specified dispbase */ -/* useful for OrcoDM creation for curves with constructive modifiers */ -DerivedMesh *CDDM_from_curve_displist(struct Object *ob, struct ListBase *dispbase); +DerivedMesh *CDDM_from_editbmesh(struct BMEditMesh *em, const bool use_mdisps); /* Copies the given DerivedMesh with verts, faces & edges stored as * custom element data. */ struct DerivedMesh *CDDM_copy(struct DerivedMesh *dm); -/* creates a CDDerivedMesh with the same layer stack configuration as the - * given DerivedMesh and containing the requested numbers of elements. - * elements are initialized to all zeros - */ -struct DerivedMesh *CDDM_from_template_ex(struct DerivedMesh *source, - int numVerts, - int numEdges, - int numFaces, - int numLoops, - int numPolys, - const struct CustomData_MeshMasks *mask); -struct DerivedMesh *CDDM_from_template(struct DerivedMesh *source, - int numVerts, - int numEdges, - int numFaces, - int numLoops, - int numPolys); - -/* applies vertex coordinates or normals to a CDDerivedMesh. if the MVert - * layer is a referenced layer, it will be duplicate to not overwrite the - * original - */ -void CDDM_apply_vert_coords(struct DerivedMesh *cddm, float (*vertCoords)[3]); -void CDDM_apply_vert_normals(struct DerivedMesh *cddm, short (*vertNormals)[3]); - -/* recalculates vertex and face normals for a CDDerivedMesh - */ -void CDDM_calc_normals_mapping_ex(struct DerivedMesh *dm, const bool only_face_normals); -void CDDM_calc_normals_mapping(struct DerivedMesh *dm); -void CDDM_calc_normals(struct DerivedMesh *dm); - -void CDDM_calc_loop_normals(struct DerivedMesh *dm, - const bool use_split_normals, - const float split_angle); -void CDDM_calc_loop_normals_spacearr(struct DerivedMesh *dm, - const bool use_split_normals, - const float split_angle, - struct MLoopNorSpaceArray *r_lnors_spacearr); - -/* reconstitute face triangulation */ -void CDDM_recalc_tessellation(struct DerivedMesh *dm); -void CDDM_recalc_tessellation_ex(struct DerivedMesh *dm, const bool do_face_nor_cpy); - void CDDM_recalc_looptri(struct DerivedMesh *dm); -/* lowers the number of vertices/edges/faces in a CDDerivedMesh - * the layer data stays the same size - */ -void CDDM_lower_num_verts(struct DerivedMesh *dm, int numVerts); -void CDDM_lower_num_edges(struct DerivedMesh *dm, int numEdges); -void CDDM_lower_num_loops(struct DerivedMesh *dm, int numLoops); -void CDDM_lower_num_polys(struct DerivedMesh *dm, int numPolys); -void CDDM_lower_num_tessfaces(DerivedMesh *dm, int numTessFaces); - /* vertex/edge/face access functions * should always succeed if index is within bounds * note these return pointers - any change modifies the internals of the mesh @@ -145,13 +80,4 @@ struct MFace *CDDM_get_tessfaces(struct DerivedMesh *dm); struct MLoop *CDDM_get_loops(struct DerivedMesh *dm); struct MPoly *CDDM_get_polys(struct DerivedMesh *dm); -/* Assigns news m*** layers to the cddm. Note that you must handle - * freeing the old ones yourself. Also you must ensure dm->num****Data - * is correct.*/ -void CDDM_set_mvert(struct DerivedMesh *dm, struct MVert *mvert); -void CDDM_set_medge(struct DerivedMesh *dm, struct MEdge *medge); -void CDDM_set_mface(struct DerivedMesh *dm, struct MFace *mface); -void CDDM_set_mloop(struct DerivedMesh *dm, struct MLoop *mloop); -void CDDM_set_mpoly(struct DerivedMesh *dm, struct MPoly *mpoly); - #endif diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 43df78c33e4..01f94c39215 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -29,7 +29,6 @@ struct ClothModifierData; struct CollisionModifierData; struct Depsgraph; -struct MFace; struct Mesh; struct Object; struct Scene; diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h index 0ab101f065d..0d33d86ec16 100644 --- a/source/blender/blenkernel/BKE_collection.h +++ b/source/blender/blenkernel/BKE_collection.h @@ -35,8 +35,6 @@ extern "C" { struct BLI_Iterator; struct Base; struct Collection; -struct Depsgraph; -struct ID; struct Main; struct Object; struct Scene; @@ -72,13 +70,9 @@ struct Collection *BKE_collection_duplicate(struct Main *bmain, const bool do_hierarchy, const bool do_objects, const bool do_obdata); -struct Collection *BKE_collection_copy_master(struct Main *bmain, - struct Collection *collection, - const int flag); /* Master Collection for Scene */ -struct Collection *BKE_collection_master(const struct Scene *scene); struct Collection *BKE_collection_master_add(void); struct Scene *BKE_collection_master_scene_search(const struct Main *bmain, const struct Collection *master_collection); @@ -227,7 +221,7 @@ void BKE_scene_objects_iterator_end(struct BLI_Iterator *iter); bool is_scene_collection = (_scene) != NULL; \ \ if (_scene) { \ - _instance_next = BKE_collection_master(_scene); \ + _instance_next = _scene->master_collection; \ } \ else { \ _instance_next = (_bmain)->collections.first; \ diff --git a/source/blender/blenkernel/BKE_collision.h b/source/blender/blenkernel/BKE_collision.h index 291502a0c28..5d7a5094eb5 100644 --- a/source/blender/blenkernel/BKE_collision.h +++ b/source/blender/blenkernel/BKE_collision.h @@ -37,11 +37,9 @@ struct Collection; struct CollisionModifierData; struct Depsgraph; -struct MFace; struct MVert; struct MVertTri; struct Object; -struct Scene; //////////////////////////////////////// // used for collisions in collision.c diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index 755a155653b..105f8e82343 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -33,7 +33,6 @@ extern "C" { struct ARegion; struct Base; -struct Brush; struct CacheFile; struct Collection; struct Depsgraph; @@ -59,7 +58,6 @@ struct Text; struct ToolSettings; struct View3D; struct ViewLayer; -struct ViewRender; struct bGPDframe; struct bGPDlayer; struct bGPdata; @@ -98,7 +96,7 @@ typedef struct bContextStore { /* for the context's rna mode enum * keep aligned with data_mode_strings in context.c */ -enum eContextObjectMode { +typedef enum eContextObjectMode { CTX_MODE_EDIT_MESH = 0, CTX_MODE_EDIT_CURVE, CTX_MODE_EDIT_SURFACE, @@ -117,7 +115,7 @@ enum eContextObjectMode { CTX_MODE_EDIT_GPENCIL, CTX_MODE_SCULPT_GPENCIL, CTX_MODE_WEIGHT_GPENCIL, -}; +} eContextObjectMode; #define CTX_MODE_NUM (CTX_MODE_WEIGHT_GPENCIL + 1) /* Context */ @@ -239,7 +237,7 @@ bool CTX_data_dir(const char *member); #define CTX_DATA_BEGIN_WITH_ID(C, Type, instance, member, Type_id, instance_id) \ CTX_DATA_BEGIN (C, Type, instance, member) \ - Type_id instance_id = ctx_link->ptr.id.data; + Type_id instance_id = (Type_id)ctx_link->ptr.owner_id; int ctx_data_list_count(const bContext *C, int (*func)(const bContext *, ListBase *)); diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index 51ff4673aba..be49ca150b2 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -26,15 +26,12 @@ struct BezTriple; struct Curve; struct Depsgraph; -struct EditNurb; struct GHash; -struct LinkNode; struct ListBase; struct Main; struct Nurb; struct Object; struct Path; -struct Scene; struct TextBox; struct rctf; @@ -124,11 +121,22 @@ void BKE_curve_nurb_vert_active_set(struct Curve *cu, const struct Nurb *nu, con bool BKE_curve_nurb_vert_active_get(struct Curve *cu, struct Nurb **r_nu, void **r_vert); void BKE_curve_nurb_vert_active_validate(struct Curve *cu); -float (*BKE_curve_nurbs_vertexCos_get(struct ListBase *lb, int *r_numVerts))[3]; -void BK_curve_nurbs_vertexCos_apply(struct ListBase *lb, float (*vertexCos)[3]); +float (*BKE_curve_nurbs_vert_coords_alloc(struct ListBase *lb, int *r_vert_len))[3]; +void BKE_curve_nurbs_vert_coords_get(struct ListBase *lb, float (*vert_coords)[3], int vert_len); -float (*BKE_curve_nurbs_keyVertexCos_get(struct ListBase *lb, float *key))[3]; -void BKE_curve_nurbs_keyVertexTilts_apply(struct ListBase *lb, float *key); +void BKE_curve_nurbs_vert_coords_apply_with_mat4(struct ListBase *lb, + const float (*vert_coords)[3], + const float mat[4][4], + const bool constrain_2d); + +void BKE_curve_nurbs_vert_coords_apply(struct ListBase *lb, + const float (*vert_coords)[3], + const bool constrain_2d); + +float (*BKE_curve_nurbs_key_vert_coords_alloc(struct ListBase *lb, + float *key, + int *r_vert_len))[3]; +void BKE_curve_nurbs_key_vert_tilts_apply(struct ListBase *lb, float *key); void BKE_curve_editNurb_keyIndex_delCV(struct GHash *keyindex, const void *cv); void BKE_curve_editNurb_keyIndex_free(struct GHash **keyindex); diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h index c57639a8193..cfacbfe0a21 100644 --- a/source/blender/blenkernel/BKE_displist.h +++ b/source/blender/blenkernel/BKE_displist.h @@ -49,9 +49,7 @@ enum { /* prototypes */ struct Depsgraph; -struct LinkNode; struct ListBase; -struct Main; struct Mesh; struct Object; struct Scene; diff --git a/source/blender/blenkernel/BKE_dynamicpaint.h b/source/blender/blenkernel/BKE_dynamicpaint.h index c4f05d404ce..734bfbc019a 100644 --- a/source/blender/blenkernel/BKE_dynamicpaint.h +++ b/source/blender/blenkernel/BKE_dynamicpaint.h @@ -25,9 +25,7 @@ struct Depsgraph; struct DynamicPaintCanvasSettings; struct DynamicPaintModifierData; struct DynamicPaintRuntime; -struct Main; struct Scene; -struct ViewLayer; /* Actual surface point */ typedef struct PaintSurfaceData { diff --git a/source/blender/blenkernel/BKE_editmesh.h b/source/blender/blenkernel/BKE_editmesh.h index b7280c702d2..062968eddfc 100644 --- a/source/blender/blenkernel/BKE_editmesh.h +++ b/source/blender/blenkernel/BKE_editmesh.h @@ -31,7 +31,6 @@ struct BMLoop; struct BMesh; struct Depsgraph; -struct DerivedMesh; struct EditMeshData; struct Mesh; struct MeshStatVis; @@ -79,7 +78,7 @@ typedef struct BMEditMesh { } BMEditMesh; /* editmesh.c */ -void BKE_editmesh_tessface_calc(BMEditMesh *em); +void BKE_editmesh_looptri_calc(BMEditMesh *em); BMEditMesh *BKE_editmesh_create(BMesh *bm, const bool do_tessellate); BMEditMesh *BKE_editmesh_copy(BMEditMesh *em); BMEditMesh *BKE_editmesh_from_object(struct Object *ob); @@ -88,7 +87,7 @@ void BKE_editmesh_free(BMEditMesh *em); void BKE_editmesh_color_free(BMEditMesh *em); void BKE_editmesh_color_ensure(BMEditMesh *em, const char htype); -float (*BKE_editmesh_vertexCos_get_orco(BMEditMesh *em, int *r_numVerts))[3]; +float (*BKE_editmesh_vert_coords_alloc_orco(BMEditMesh *em, int *r_vert_len))[3]; void BKE_editmesh_lnorspace_update(BMEditMesh *em); void BKE_editmesh_ensure_autosmooth(BMEditMesh *em); @@ -98,7 +97,7 @@ void BKE_editmesh_statvis_calc(BMEditMesh *em, struct EditMeshData *emd, const struct MeshStatVis *statvis); -float (*BKE_editmesh_vertexCos_get( - struct Depsgraph *depsgraph, struct BMEditMesh *em, struct Scene *scene, int *r_numVerts))[3]; +float (*BKE_editmesh_vert_coords_alloc( + struct Depsgraph *depsgraph, struct BMEditMesh *em, struct Scene *scene, int *r_vert_len))[3]; #endif /* __BKE_EDITMESH_H__ */ diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index 4c1a115eb23..5be9a35b168 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -89,6 +89,9 @@ struct ChannelDriver *fcurve_copy_driver(const struct ChannelDriver *driver); void driver_variables_copy(struct ListBase *dst_list, const struct ListBase *src_list); +void BKE_driver_target_matrix_to_rot_channels( + float mat[4][4], int auto_order, int rotation_mode, int channel, bool angles, float r_buf[4]); + void driver_free_variable(struct ListBase *variables, struct DriverVar *dvar); void driver_free_variable_ex(struct ChannelDriver *driver, struct DriverVar *dvar); diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h index c544c065a70..b4f636199f8 100644 --- a/source/blender/blenkernel/BKE_gpencil.h +++ b/source/blender/blenkernel/BKE_gpencil.h @@ -24,31 +24,40 @@ * \ingroup bke */ -struct Scene; -struct ArrayGpencilModifierData; struct BoundBox; struct Brush; struct CurveMapping; struct Depsgraph; -struct GpencilModifierData; -struct LatticeGpencilModifierData; struct ListBase; struct Main; struct Material; struct Object; -struct SimplifyGpencilModifierData; struct ToolSettings; struct bDeformGroup; struct bGPDframe; struct bGPDlayer; -struct bGPDpalette; -struct bGPDpalettecolor; struct bGPDspoint; struct bGPDstroke; struct bGPdata; struct MDeformVert; -struct MDeformWeight; + +#define GPENCIL_SIMPLIFY(scene) ((scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ENABLE)) +#define GPENCIL_SIMPLIFY_ONPLAY(playing) \ + (((playing == true) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ON_PLAY)) || \ + ((scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ON_PLAY) == 0)) +#define GPENCIL_SIMPLIFY_FILL(scene, playing) \ + ((GPENCIL_SIMPLIFY_ONPLAY(playing) && (GPENCIL_SIMPLIFY(scene)) && \ + (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_FILL))) +#define GPENCIL_SIMPLIFY_MODIF(scene, playing) \ + ((GPENCIL_SIMPLIFY_ONPLAY(playing) && (GPENCIL_SIMPLIFY(scene)) && \ + (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_MODIFIER))) +#define GPENCIL_SIMPLIFY_FX(scene, playing) \ + ((GPENCIL_SIMPLIFY_ONPLAY(playing) && (GPENCIL_SIMPLIFY(scene)) && \ + (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_FX))) +#define GPENCIL_SIMPLIFY_BLEND(scene, playing) \ + ((GPENCIL_SIMPLIFY_ONPLAY(playing) && (GPENCIL_SIMPLIFY(scene)) && \ + (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_BLEND))) struct GPUBatch; struct GPUVertBuf; @@ -134,7 +143,7 @@ void BKE_gpencil_free_stroke(struct bGPDstroke *gps); bool BKE_gpencil_free_strokes(struct bGPDframe *gpf); void BKE_gpencil_free_frames(struct bGPDlayer *gpl); void BKE_gpencil_free_layers(struct ListBase *list); -bool BKE_gpencil_free_frame_runtime_data(struct bGPDframe *derived_gpf); +bool BKE_gpencil_free_frame_runtime_data(struct bGPDframe *gpf_eval); void BKE_gpencil_free(struct bGPdata *gpd, bool free_all); void BKE_gpencil_batch_cache_dirty_tag(struct bGPdata *gpd); @@ -220,13 +229,14 @@ struct bGPDlayer *BKE_gpencil_layer_get_index(struct bGPdata *gpd, struct bGPDlayer *BKE_gpencil_layer_getactive(struct bGPdata *gpd); void BKE_gpencil_layer_setactive(struct bGPdata *gpd, struct bGPDlayer *active); void BKE_gpencil_layer_delete(struct bGPdata *gpd, struct bGPDlayer *gpl); +void BKE_gpencil_layer_autolock_set(struct bGPdata *gpd); /* Brush */ struct Material *BKE_gpencil_brush_material_get(struct Brush *brush); void BKE_gpencil_brush_material_set(struct Brush *brush, struct Material *material); /* Object */ -struct Material *BKE_gpencil_object_material_ensure_active(struct Main *bmain, struct Object *ob); +struct Material *BKE_gpencil_object_material_ensure_active(struct Object *ob); struct Material *BKE_gpencil_object_material_ensure_from_brush(struct Main *bmain, struct Object *ob, struct Brush *brush); @@ -250,8 +260,7 @@ struct Material *BKE_gpencil_object_material_ensure_from_active_input_toolsettin struct Material *BKE_gpencil_object_material_ensure_from_active_input_brush(struct Main *bmain, struct Object *ob, struct Brush *brush); -struct Material *BKE_gpencil_object_material_ensure_from_active_input_material(struct Main *bmain, - struct Object *ob); +struct Material *BKE_gpencil_object_material_ensure_from_active_input_material(struct Object *ob); /* object boundbox */ bool BKE_gpencil_data_minmax(const struct bGPdata *gpd, float r_min[3], float r_max[3]); @@ -324,7 +333,8 @@ void BKE_gpencil_convert_curve(struct Main *bmain, struct Object *ob_gp, struct Object *ob_cu, const bool gpencil_lines, - const bool use_collections); + const bool use_collections, + const bool only_stroke); extern void (*BKE_gpencil_batch_cache_dirty_tag_cb)(struct bGPdata *gpd); extern void (*BKE_gpencil_batch_cache_free_cb)(struct bGPdata *gpd); diff --git a/source/blender/blenkernel/BKE_gpencil_modifier.h b/source/blender/blenkernel/BKE_gpencil_modifier.h index 373efadad55..36f38996c36 100644 --- a/source/blender/blenkernel/BKE_gpencil_modifier.h +++ b/source/blender/blenkernel/BKE_gpencil_modifier.h @@ -24,23 +24,16 @@ #include "BLI_compiler_attrs.h" #include "BKE_customdata.h" -struct BMEditMesh; -struct DepsNodeHandle; struct Depsgraph; -struct DerivedMesh; struct GpencilModifierData; struct ID; struct ListBase; struct Main; -struct Mesh; struct ModifierUpdateDepsgraphContext; struct Object; struct Scene; -struct ViewLayer; -struct bArmature; /* NOTE: bakeModifier() called from UI: * needs to create new databloc-ks, hence the need for this. */ -struct bContext; struct bGPDframe; struct bGPDlayer; struct bGPDstroke; diff --git a/source/blender/blenkernel/BKE_image_save.h b/source/blender/blenkernel/BKE_image_save.h index 26c377a2574..8dfece944ff 100644 --- a/source/blender/blenkernel/BKE_image_save.h +++ b/source/blender/blenkernel/BKE_image_save.h @@ -31,7 +31,6 @@ extern "C" { struct Image; struct Main; -struct RenderResult; struct ReportList; struct Scene; diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h index 58ad3f6230d..477a22b07bb 100644 --- a/source/blender/blenkernel/BKE_key.h +++ b/source/blender/blenkernel/BKE_key.h @@ -31,7 +31,6 @@ struct ListBase; struct Main; struct Mesh; struct Object; -struct WeightsArrayCache; /* Kernel prototypes */ #ifdef __cplusplus @@ -92,13 +91,17 @@ void BKE_keyblock_mesh_calc_normals(struct KeyBlock *kb, float (*r_polynors)[3], float (*r_loopnors)[3]); -void BKE_keyblock_update_from_vertcos(struct Object *ob, struct KeyBlock *kb, float (*vertCos)[3]); +void BKE_keyblock_update_from_vertcos(struct Object *ob, + struct KeyBlock *kb, + const float (*vertCos)[3]); void BKE_keyblock_convert_from_vertcos(struct Object *ob, struct KeyBlock *kb, - float (*vertCos)[3]); + const float (*vertCos)[3]); float (*BKE_keyblock_convert_to_vertcos(struct Object *ob, struct KeyBlock *kb))[3]; -void BKE_keyblock_update_from_offset(struct Object *ob, struct KeyBlock *kb, float (*ofs)[3]); +void BKE_keyblock_update_from_offset(struct Object *ob, + struct KeyBlock *kb, + const float (*ofs)[3]); /* other management */ bool BKE_keyblock_move(struct Object *ob, int org_index, int new_index); diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h index c4173cd867e..a3befa6f3bb 100644 --- a/source/blender/blenkernel/BKE_lattice.h +++ b/source/blender/blenkernel/BKE_lattice.h @@ -58,7 +58,7 @@ void outside_lattice(struct Lattice *lt); void curve_deform_verts(struct Object *cuOb, struct Object *target, - float (*vertexCos)[3], + float (*vert_coords)[3], int numVerts, struct MDeformVert *dvert, const int defgrp_index, @@ -73,14 +73,14 @@ void curve_deform_vector(struct Object *cuOb, void lattice_deform_verts(struct Object *laOb, struct Object *target, struct Mesh *mesh, - float (*vertexCos)[3], + float (*vert_coords)[3], int numVerts, const char *vgroup, float influence); void armature_deform_verts(struct Object *armOb, struct Object *target, const struct Mesh *mesh, - float (*vertexCos)[3], + float (*vert_coords)[3], float (*defMats)[3][3], int numVerts, int deformflag, @@ -88,8 +88,12 @@ void armature_deform_verts(struct Object *armOb, const char *defgrp_name, struct bGPDstroke *gps); -float (*BKE_lattice_vertexcos_get(struct Object *ob, int *r_numVerts))[3]; -void BKE_lattice_vertexcos_apply(struct Object *ob, float (*vertexCos)[3]); +float (*BKE_lattice_vert_coords_alloc(const struct Lattice *lt, int *r_vert_len))[3]; +void BKE_lattice_vert_coords_get(const struct Lattice *lt, float (*vert_coords)[3]); +void BKE_lattice_vert_coords_apply_with_mat4(struct Lattice *lt, + const float (*vert_coords)[3], + const float mat[4][4]); +void BKE_lattice_vert_coords_apply(struct Lattice *lt, const float (*vert_coords)[3]); void BKE_lattice_modifiers_calc(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob); diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h index daac35a1196..eb65b7641e1 100644 --- a/source/blender/blenkernel/BKE_layer.h +++ b/source/blender/blenkernel/BKE_layer.h @@ -37,17 +37,12 @@ extern "C" { struct Base; struct Collection; struct Depsgraph; -struct ID; -struct IDProperty; struct LayerCollection; -struct ListBase; struct Main; struct Object; -struct RenderEngine; struct Scene; struct View3D; struct ViewLayer; -struct WorkSpace; struct ViewLayer *BKE_view_layer_default_view(const struct Scene *scene); struct ViewLayer *BKE_view_layer_default_render(const struct Scene *scene); diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index c0ac71f9c96..261416dc025 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -46,17 +46,14 @@ extern "C" { * except in some specific cases requiring advanced (and potentially dangerous) handling. */ -struct BlendThumbnail; struct GHash; struct ID; -struct ImBuf; struct Library; struct ListBase; struct Main; struct PointerRNA; struct PropertyRNA; struct bContext; -struct wmWindowManager; size_t BKE_libblock_get_alloc_info(short type, const char **name); void *BKE_libblock_alloc_notest(short type) ATTR_WARN_UNUSED_RESULT; @@ -117,10 +114,7 @@ enum { LIB_ID_CREATE_NO_DEG_TAG | LIB_ID_COPY_NO_PREVIEW | LIB_ID_COPY_CACHES, }; -void BKE_libblock_copy_ex(struct Main *bmain, - const struct ID *id, - struct ID **r_newid, - const int flag); +void BKE_libblock_copy_ex(struct Main *bmain, const struct ID *id, struct ID **r_newid, int flag); void *BKE_libblock_copy(struct Main *bmain, const struct ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); /* Special version. sued by datablock localization. */ diff --git a/source/blender/blenkernel/BKE_library_override.h b/source/blender/blenkernel/BKE_library_override.h index 5440b0ebe63..93b2355ce55 100644 --- a/source/blender/blenkernel/BKE_library_override.h +++ b/source/blender/blenkernel/BKE_library_override.h @@ -35,8 +35,8 @@ bool BKE_override_library_is_enabled(void); struct IDOverrideLibrary *BKE_override_library_init(struct ID *local_id, struct ID *reference_id); void BKE_override_library_copy(struct ID *dst_id, const struct ID *src_id); -void BKE_override_library_clear(struct IDOverrideLibrary *override); -void BKE_override_library_free(struct IDOverrideLibrary **override); +void BKE_override_library_clear(struct IDOverrideLibrary *override, const bool do_id_user); +void BKE_override_library_free(struct IDOverrideLibrary **override, const bool do_id_user); struct ID *BKE_override_library_create_from_id(struct Main *bmain, struct ID *reference_id); bool BKE_override_library_create_from_tag(struct Main *bmain); diff --git a/source/blender/blenkernel/BKE_library_remap.h b/source/blender/blenkernel/BKE_library_remap.h index d51bc5c2bce..784e1a570c5 100644 --- a/source/blender/blenkernel/BKE_library_remap.h +++ b/source/blender/blenkernel/BKE_library_remap.h @@ -25,6 +25,8 @@ extern "C" { #include "BLI_compiler_attrs.h" +struct wmWindowManager; + /* BKE_libblock_free, delete are declared in BKE_library.h for convenience. */ /* Also IDRemap->flag. */ @@ -83,7 +85,7 @@ void BKE_libblock_relink_ex(struct Main *bmain, void *idv, void *old_idv, void *new_idv, - const bool us_min_never_null) ATTR_NONNULL(1, 2); + const short remap_flags) ATTR_NONNULL(1, 2); void BKE_libblock_relink_to_newid(struct ID *id) ATTR_NONNULL(); diff --git a/source/blender/blenkernel/BKE_light.h b/source/blender/blenkernel/BKE_light.h index 72bd5857526..e060f587afe 100644 --- a/source/blender/blenkernel/BKE_light.h +++ b/source/blender/blenkernel/BKE_light.h @@ -32,7 +32,6 @@ extern "C" { struct Light; struct Main; -struct Scene; void BKE_light_init(struct Light *la); struct Light *BKE_light_add(struct Main *bmain, const char *name) ATTR_WARN_UNUSED_RESULT; diff --git a/source/blender/blenkernel/BKE_linestyle.h b/source/blender/blenkernel/BKE_linestyle.h index 79579b43446..b8950e5df88 100644 --- a/source/blender/blenkernel/BKE_linestyle.h +++ b/source/blender/blenkernel/BKE_linestyle.h @@ -38,7 +38,6 @@ extern "C" { struct ColorBand; struct Main; -struct Object; struct ViewLayer; struct bContext; diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h index 1c987d5eb8e..1b2e8bcbf42 100644 --- a/source/blender/blenkernel/BKE_main.h +++ b/source/blender/blenkernel/BKE_main.h @@ -40,7 +40,6 @@ extern "C" { struct BLI_mempool; struct BlendThumbnail; -struct Depsgraph; struct GHash; struct GSet; struct ImBuf; diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index f87c73e35a2..47644ce82e9 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -38,7 +38,6 @@ struct MaskSplinePoint; struct MaskSplinePointUW; struct MovieClip; struct MovieClipUser; -struct Scene; /* mask_ops.c */ typedef enum { diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h index 5bb69c7166e..7ff9c4e6376 100644 --- a/source/blender/blenkernel/BKE_material.h +++ b/source/blender/blenkernel/BKE_material.h @@ -38,6 +38,7 @@ struct bNode; /* materials */ void init_def_material(void); +void BKE_material_gpencil_default_free(void); void BKE_material_free(struct Material *ma); void test_object_materials(struct Main *bmain, struct Object *ob, struct ID *id); void test_all_objects_materials(struct Main *bmain, struct ID *id); @@ -46,6 +47,7 @@ void BKE_material_resize_object(struct Main *bmain, const short totcol, bool do_id_user); void BKE_material_init(struct Material *ma); +void BKE_material_gpencil_init(struct Material *ma); void BKE_material_remap_object(struct Object *ob, const unsigned int *remap); void BKE_material_remap_object_calc(struct Object *ob_dst, struct Object *ob_src, @@ -92,6 +94,7 @@ bool BKE_object_material_slot_add(struct Main *bmain, struct Object *ob); bool BKE_object_material_slot_remove(struct Main *bmain, struct Object *ob); bool BKE_object_material_slot_used(struct ID *id, short actcol); +struct Material *BKE_material_gpencil_get(struct Object *ob, short act); struct MaterialGPencilStyle *BKE_material_gpencil_settings_get(struct Object *ob, short act); void BKE_texpaint_slot_refresh_cache(struct Scene *scene, struct Material *ma); @@ -104,9 +107,8 @@ void BKE_material_append_id(struct Main *bmain, struct ID *id, struct Material * struct Material *BKE_material_pop_id(struct Main *bmain, struct ID *id, /* index is an int because of RNA. */ - int index, - bool update_data); -void BKE_material_clear_id(struct Main *bmain, struct ID *id, bool update_data); + int index); +void BKE_material_clear_id(struct Main *bmain, struct ID *id); /* rendering */ void ramp_blend(int type, float r_col[3], const float fac, const float col[3]); @@ -124,6 +126,7 @@ struct Depsgraph; void BKE_material_eval(struct Depsgraph *depsgraph, struct Material *material); extern struct Material defmaterial; +extern struct Material defgpencil_material; #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h index b582e88f9cb..5447fd00866 100644 --- a/source/blender/blenkernel/BKE_mball.h +++ b/source/blender/blenkernel/BKE_mball.h @@ -63,7 +63,7 @@ bool BKE_mball_minmax_ex(const struct MetaBall *mb, bool BKE_mball_minmax(const struct MetaBall *mb, float min[3], float max[3]); bool BKE_mball_center_median(const struct MetaBall *mb, float r_cent[3]); bool BKE_mball_center_bounds(const struct MetaBall *mb, float r_cent[3]); -void BKE_mball_transform(struct MetaBall *mb, float mat[4][4], const bool do_props); +void BKE_mball_transform(struct MetaBall *mb, const float mat[4][4], const bool do_props); void BKE_mball_translate(struct MetaBall *mb, const float offset[3]); struct MetaElem *BKE_mball_element_add(struct MetaBall *mb, const int type); diff --git a/source/blender/blenkernel/BKE_mball_tessellate.h b/source/blender/blenkernel/BKE_mball_tessellate.h index ab8fbc44caf..39740458f2f 100644 --- a/source/blender/blenkernel/BKE_mball_tessellate.h +++ b/source/blender/blenkernel/BKE_mball_tessellate.h @@ -20,7 +20,6 @@ * \ingroup bke */ struct Depsgraph; -struct Main; struct Object; struct Scene; diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 94d118bde36..12978e46327 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -53,13 +53,11 @@ struct MLoopTri; struct MLoopUV; struct MPoly; struct MVert; -struct MVertTri; struct Main; struct MemArena; struct Mesh; struct ModifierData; struct Object; -struct ReportList; struct Scene; #ifdef __cplusplus @@ -123,6 +121,13 @@ struct Mesh *BKE_mesh_new_nomain_from_template(const struct Mesh *me_src, int tessface_len, int loops_len, int polys_len); +struct Mesh *BKE_mesh_new_nomain_from_template_ex(const struct Mesh *me_src, + int verts_len, + int edges_len, + int tessface_len, + int loops_len, + int polys_len, + CustomData_MeshMasks mask); void BKE_mesh_eval_delete(struct Mesh *me_eval); @@ -185,7 +190,7 @@ void BKE_mesh_material_index_remove(struct Mesh *me, short index); bool BKE_mesh_material_index_used(struct Mesh *me, short index); void BKE_mesh_material_index_clear(struct Mesh *me); void BKE_mesh_material_remap(struct Mesh *me, const unsigned int *remap, unsigned int remap_len); -void BKE_mesh_smooth_flag_set(struct Object *meshOb, int enableSmooth); +void BKE_mesh_smooth_flag_set(struct Mesh *me, const bool use_smooth); const char *BKE_mesh_cmp(struct Mesh *me1, struct Mesh *me2, float thresh); @@ -198,18 +203,6 @@ void BKE_mesh_texspace_get_reference( struct Mesh *me, short **r_texflag, float **r_loc, float **r_rot, float **r_size); void BKE_mesh_texspace_copy_from_object(struct Mesh *me, struct Object *ob); -bool BKE_mesh_uv_cdlayer_rename_index(struct Mesh *me, - const int loop_index, - const int face_index, - const char *new_name, - const bool do_tessface); -bool BKE_mesh_uv_cdlayer_rename(struct Mesh *me, - const char *old_name, - const char *new_name, - bool do_tessface); - -float (*BKE_mesh_vertexCos_get(const struct Mesh *me, int *r_numVerts))[3]; - void BKE_mesh_split_faces(struct Mesh *mesh, bool free_loop_normals); /* Create new mesh from the given object at its current state. @@ -268,8 +261,14 @@ void BKE_mesh_mselect_active_set(struct Mesh *me, int index, int type); void BKE_mesh_count_selected_items(const struct Mesh *mesh, int r_count[3]); -void BKE_mesh_apply_vert_coords(struct Mesh *mesh, float (*vertCoords)[3]); -void BKE_mesh_apply_vert_normals(struct Mesh *mesh, short (*vertNormals)[3]); +float (*BKE_mesh_vert_coords_alloc(const struct Mesh *mesh, int *r_vert_len))[3]; +void BKE_mesh_vert_coords_get(const struct Mesh *mesh, float (*vert_coords)[3]); + +void BKE_mesh_vert_coords_apply_with_mat4(struct Mesh *mesh, + const float (*vert_coords)[3], + const float mat[4][4]); +void BKE_mesh_vert_coords_apply(struct Mesh *mesh, const float (*vert_coords)[3]); +void BKE_mesh_vert_normals_apply(struct Mesh *mesh, const short (*vertNormals)[3]); /* *** mesh_evaluate.c *** */ @@ -309,11 +308,6 @@ void BKE_mesh_calc_normals_poly(struct MVert *mverts, void BKE_mesh_calc_normals(struct Mesh *me); void BKE_mesh_ensure_normals(struct Mesh *me); void BKE_mesh_ensure_normals_for_display(struct Mesh *mesh); -void BKE_mesh_calc_normals_tessface(struct MVert *mverts, - int numVerts, - const struct MFace *mfaces, - int numFaces, - float (*r_faceNors)[3]); void BKE_mesh_calc_normals_looptri(struct MVert *mverts, int numVerts, const struct MLoop *mloop, @@ -538,14 +532,14 @@ void BKE_mesh_tangent_loops_to_tessdata(struct CustomData *fdata, unsigned int (*loopindices)[4], const int num_faces, const char *layer_name); -int BKE_mesh_recalc_tessellation(struct CustomData *fdata, - struct CustomData *ldata, - struct CustomData *pdata, - struct MVert *mvert, - int totface, - int totloop, - int totpoly, - const bool do_face_nor_copy); +int BKE_mesh_tessface_calc_ex(struct CustomData *fdata, + struct CustomData *ldata, + struct CustomData *pdata, + struct MVert *mvert, + int totface, + int totloop, + int totpoly, + const bool do_face_nor_copy); void BKE_mesh_recalc_looptri(const struct MLoop *mloop, const struct MPoly *mpoly, const struct MVert *mvert, diff --git a/source/blender/blenkernel/BKE_mesh_iterators.h b/source/blender/blenkernel/BKE_mesh_iterators.h index 28fd4b8bc28..b5b65944079 100644 --- a/source/blender/blenkernel/BKE_mesh_iterators.h +++ b/source/blender/blenkernel/BKE_mesh_iterators.h @@ -20,12 +20,6 @@ * \ingroup bke */ -struct MEdge; -struct MLoop; -struct MLoopTri; -struct MLoopUV; -struct MPoly; -struct MVert; struct Mesh; typedef enum MeshForeachFlag { diff --git a/source/blender/blenkernel/BKE_mesh_runtime.h b/source/blender/blenkernel/BKE_mesh_runtime.h index 93d952bcae5..4dc9ac988e7 100644 --- a/source/blender/blenkernel/BKE_mesh_runtime.h +++ b/source/blender/blenkernel/BKE_mesh_runtime.h @@ -27,7 +27,6 @@ //#include "BKE_customdata.h" /* for CustomDataMask */ -struct ColorBand; struct CustomData; struct CustomData_MeshMasks; struct Depsgraph; diff --git a/source/blender/blenkernel/BKE_mesh_tangent.h b/source/blender/blenkernel/BKE_mesh_tangent.h index bca825ce91c..4a86dfa3832 100644 --- a/source/blender/blenkernel/BKE_mesh_tangent.h +++ b/source/blender/blenkernel/BKE_mesh_tangent.h @@ -20,6 +20,8 @@ * \ingroup bke */ +struct ReportList; + void BKE_mesh_calc_loop_tangent_single_ex(const struct MVert *mverts, const int numVerts, const struct MLoop *mloops, diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 4aab2a346e7..b2bc30c107c 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -35,7 +35,6 @@ struct Mesh; struct ModifierData; struct Object; struct Scene; -struct ViewLayer; struct bArmature; typedef enum { diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 9b2db5acd3b..cbfc8ffc7d0 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -59,7 +59,6 @@ struct RenderData; struct Scene; struct SpaceNode; struct Tex; -struct ViewRender; struct bContext; struct bNode; struct bNodeExecContext; @@ -385,6 +384,7 @@ void ntreeUserIncrefID(struct bNodeTree *ntree); void ntreeUserDecrefID(struct bNodeTree *ntree); struct bNodeTree *ntreeFromID(const struct ID *id); +struct ID *BKE_node_tree_find_owner_ID(struct Main *bmain, struct bNodeTree *ntree); void ntreeMakeLocal(struct Main *bmain, struct bNodeTree *ntree, @@ -615,6 +615,7 @@ void nodeUpdateInternalLinks(struct bNodeTree *ntree, struct bNode *node); int nodeSocketIsHidden(struct bNodeSocket *sock); void ntreeTagUsedSockets(struct bNodeTree *ntree); +void nodeSetSocketAvailability(struct bNodeSocket *sock, bool is_available); /* Node Clipboard */ void BKE_node_clipboard_init(struct bNodeTree *ntree); @@ -894,7 +895,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, #define SH_NODE_CURVE_RGB 111 #define SH_NODE_CAMERA 114 #define SH_NODE_MATH 115 -#define SH_NODE_VECT_MATH 116 +#define SH_NODE_VECTOR_MATH 116 #define SH_NODE_SQUEEZE 117 //#define SH_NODE_MATERIAL_EXT 118 #define SH_NODE_INVERT 119 @@ -977,6 +978,8 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, #define SH_NODE_BSDF_HAIR_PRINCIPLED 701 #define SH_NODE_MAP_RANGE 702 #define SH_NODE_CLAMP 703 +#define SH_NODE_TEX_WHITE_NOISE 704 +#define SH_NODE_VOLUME_INFO 705 /* custom defines options for Material node */ #define SH_NODE_MAT_DIFF 1 diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index f59bf3579be..cf4bce3a209 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -43,7 +43,6 @@ struct RegionView3D; struct RigidBodyWorld; struct Scene; struct ShaderFxData; -struct SoftBody; struct View3D; struct ViewLayer; diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 37667599488..ed02a34196f 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -32,7 +32,6 @@ struct Depsgraph; struct EnumPropertyItem; struct GridPaintMask; struct ImagePool; -struct MFace; struct MLoop; struct MLoopTri; struct MVert; @@ -47,7 +46,6 @@ struct Palette; struct PaletteColor; struct ReportList; struct Scene; -struct Sculpt; struct StrokeCache; struct SubdivCCG; struct SubdivCCG; @@ -259,8 +257,15 @@ typedef struct SculptSession { struct StrokeCache *cache; + /* Cursor data and active vertex for tools */ int active_vertex_index; + float cursor_radius; + float cursor_location[3]; + float cursor_normal[3]; + float cursor_view_normal[3]; + struct RegionView3D *rv3d; + union { struct { struct SculptVertexPaintGeomMap gmap; diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 164dbbbf482..e9b4c2b5a66 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -57,7 +57,6 @@ struct ModifierData; struct Object; struct RNG; struct Scene; -struct ViewLayer; #define PARTICLE_COLLISION_MAX_COLLISIONS 10 diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index 62544efad2c..f02d41d3c65 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -28,12 +28,10 @@ struct BMLog; struct BMesh; -struct CCGDerivedMesh; struct CCGElem; struct CCGKey; struct CustomData; struct DMFlagMat; -struct GPUBatch; struct GPU_PBVH_Buffers; struct IsectRayPrecalc; struct MLoop; @@ -134,8 +132,11 @@ bool BKE_pbvh_node_raycast(PBVH *bvh, float (*origco)[3], bool use_origco, const float ray_start[3], + const float ray_normal[3], struct IsectRayPrecalc *isect_precalc, - float *depth); + float *depth, + int *active_vertex_index, + float *face_normal); bool BKE_pbvh_bmesh_node_raycast_detail(PBVHNode *node, const float ray_start[3], @@ -278,9 +279,9 @@ float *BKE_pbvh_node_layer_disp_get(PBVH *pbvh, PBVHNode *node); void BKE_pbvh_node_layer_disp_free(PBVHNode *node); /* vertex deformer */ -float (*BKE_pbvh_get_vertCos(struct PBVH *pbvh))[3]; -void BKE_pbvh_apply_vertCos(struct PBVH *pbvh, float (*vertCos)[3], const int totvert); -bool BKE_pbvh_isDeformed(struct PBVH *pbvh); +float (*BKE_pbvh_vert_coords_alloc(struct PBVH *pbvh))[3]; +void BKE_pbvh_vert_coords_apply(struct PBVH *pbvh, const float (*vertCos)[3], const int totvert); +bool BKE_pbvh_is_deformed(struct PBVH *pbvh); /* Vertex Iterator */ diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index bcdf1fe48ca..7d564a232a7 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -38,8 +38,6 @@ struct TransformOrientation; struct UnitSettings; struct View3DCursor; struct ViewLayer; -struct ViewRender; -struct WorkSpace; typedef enum eSceneCopyMethod { SCE_COPY_NEW = 0, diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 5d3e7ad5ec2..a2ce522a895 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -24,7 +24,6 @@ */ struct ARegion; -struct GPUFXSettings; struct Header; struct ID; struct ListBase; @@ -35,7 +34,6 @@ struct ScrArea; struct ScrAreaMap; struct ScrVert; struct SpaceType; -struct TransformOrientation; struct View3D; struct View3DShading; struct WorkSpace; diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index a9e1dfb2392..e1bc16702d5 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -26,13 +26,11 @@ struct Depsgraph; struct Editing; -struct GPUFX; struct GPUOffScreen; struct GSet; struct ImBuf; struct Main; struct Mask; -struct RenderEngineType; struct Scene; struct Sequence; struct SequenceModifierData; diff --git a/source/blender/blenkernel/BKE_shader_fx.h b/source/blender/blenkernel/BKE_shader_fx.h index e90dbfcf68d..9fe42a214e9 100644 --- a/source/blender/blenkernel/BKE_shader_fx.h +++ b/source/blender/blenkernel/BKE_shader_fx.h @@ -24,22 +24,11 @@ #include "BLI_compiler_attrs.h" #include "BKE_customdata.h" -struct DepsNodeHandle; -struct Depsgraph; -struct DerivedMesh; struct ID; struct ListBase; -struct Main; -struct Mesh; struct ModifierUpdateDepsgraphContext; struct Object; -struct Scene; struct ShaderFxData; -struct ViewLayer; -struct bArmature; -struct bGPDframe; -struct bGPDlayer; -struct bGPDstroke; #define SHADER_FX_ACTIVE(_fx, _is_render) \ (((_fx->mode & eShaderFxMode_Realtime) && (_is_render == false)) || \ diff --git a/source/blender/blenkernel/BKE_shrinkwrap.h b/source/blender/blenkernel/BKE_shrinkwrap.h index 8993654254e..9ec75c39fcf 100644 --- a/source/blender/blenkernel/BKE_shrinkwrap.h +++ b/source/blender/blenkernel/BKE_shrinkwrap.h @@ -41,7 +41,6 @@ struct BVHTree; struct MDeformVert; -struct MVert; struct Mesh; struct ModifierEvalContext; struct Object; diff --git a/source/blender/blenkernel/BKE_studiolight.h b/source/blender/blenkernel/BKE_studiolight.h index d6fff528348..108e93d9caa 100644 --- a/source/blender/blenkernel/BKE_studiolight.h +++ b/source/blender/blenkernel/BKE_studiolight.h @@ -87,6 +87,11 @@ enum StudioLightFlag { STUDIOLIGHT_RADIANCE_BUFFERS_CALCULATED = (1 << 11), STUDIOLIGHT_USER_DEFINED = (1 << 12), STUDIOLIGHT_UI_EXPANDED = (1 << 13), + + STUDIOLIGHT_MATCAP_DIFFUSE_GPUTEXTURE = (1 << 14), + STUDIOLIGHT_MATCAP_SPECULAR_GPUTEXTURE = (1 << 15), + /* Is set for studio lights and matcaps with specular highlight pass. */ + STUDIOLIGHT_SPECULAR_HIGHLIGHT_PASS = (1 << 16), }; #define STUDIOLIGHT_FLAG_ALL (STUDIOLIGHT_INTERNAL | STUDIOLIGHT_EXTERNAL_FILE) @@ -97,6 +102,11 @@ enum StudioLightFlag { typedef void StudioLightFreeFunction(struct StudioLight *, void *data); +typedef struct StudioLightImage { + ImBuf *ibuf; + struct GPUTexture *gputexture; +} StudioLightImage; + typedef struct StudioLight { struct StudioLight *next, *prev; @@ -112,6 +122,8 @@ typedef struct StudioLight { int icon_id_matcap_flipped; float spherical_harmonics_coefs[STUDIOLIGHT_SH_EFFECTIVE_COEFS_LEN][3]; float light_direction[3]; + StudioLightImage matcap_diffuse; + StudioLightImage matcap_specular; ImBuf *equirect_radiance_buffer; ImBuf *equirect_irradiance_buffer; ImBuf *radiance_cubemap_buffers[6]; diff --git a/source/blender/blenkernel/BKE_subdiv.h b/source/blender/blenkernel/BKE_subdiv.h index dd139233ee3..700bf5139e0 100644 --- a/source/blender/blenkernel/BKE_subdiv.h +++ b/source/blender/blenkernel/BKE_subdiv.h @@ -29,12 +29,10 @@ struct Mesh; struct MultiresModifierData; -struct Object; struct OpenSubdiv_Converter; struct OpenSubdiv_Evaluator; struct OpenSubdiv_TopologyRefiner; struct Subdiv; -struct SubdivToMeshSettings; typedef enum eSubdivVtxBoundaryInterpolation { /* Do not interpolate boundaries. */ diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h index c17db591981..39216e98e82 100644 --- a/source/blender/blenkernel/BKE_texture.h +++ b/source/blender/blenkernel/BKE_texture.h @@ -31,17 +31,13 @@ struct Brush; struct ColorBand; struct FreestyleLineStyle; struct ImagePool; -struct Light; struct MTex; struct Main; -struct Material; struct ParticleSettings; struct PointDensity; struct Tex; struct TexMapping; struct TexResult; -struct World; -struct bNode; /* in ColorBand struct */ #define MAXCOLORBAND 32 diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index bf417403d43..c64d684de5a 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -25,7 +25,6 @@ */ struct Camera; -struct Depsgraph; struct ImBuf; struct ListBase; struct MovieClipUser; diff --git a/source/blender/blenkernel/BKE_workspace.h b/source/blender/blenkernel/BKE_workspace.h index 133cf2d6cf5..ea8978b7374 100644 --- a/source/blender/blenkernel/BKE_workspace.h +++ b/source/blender/blenkernel/BKE_workspace.h @@ -24,9 +24,6 @@ #include "BLI_compiler_attrs.h" struct Main; -struct Scene; -struct TransformOrientation; -struct ViewLayer; struct bScreen; struct bToolRef; diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 6267c095618..010e162f49d 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -87,11 +87,8 @@ # define ASSERT_IS_VALID_MESH(mesh) #endif -static CLG_LogRef LOG = {"bke.derivedmesh"}; static ThreadRWMutex loops_cache_lock = PTHREAD_RWLOCK_INITIALIZER; -static void shapekey_layers_to_keyblocks(DerivedMesh *dm, Mesh *me, int actshape_uid); - static void mesh_init_origspace(Mesh *mesh); /* -------------------------------------------------------------------- */ @@ -516,154 +513,6 @@ void DM_ensure_looptri_data(DerivedMesh *dm) } } -void DM_to_mesh( - DerivedMesh *dm, Mesh *me, Object *ob, const CustomData_MeshMasks *mask, bool take_ownership) -{ - /* dm might depend on me, so we need to do everything with a local copy */ - Mesh tmp = *me; - int totvert, totedge /*, totface */ /* UNUSED */, totloop, totpoly; - int did_shapekeys = 0; - eCDAllocType alloctype = CD_DUPLICATE; - - if (take_ownership && dm->type == DM_TYPE_CDDM && dm->needsFree) { - bool has_any_referenced_layers = CustomData_has_referenced(&dm->vertData) || - CustomData_has_referenced(&dm->edgeData) || - CustomData_has_referenced(&dm->loopData) || - CustomData_has_referenced(&dm->faceData) || - CustomData_has_referenced(&dm->polyData); - if (!has_any_referenced_layers) { - alloctype = CD_ASSIGN; - } - } - - CustomData_reset(&tmp.vdata); - CustomData_reset(&tmp.edata); - CustomData_reset(&tmp.fdata); - CustomData_reset(&tmp.ldata); - CustomData_reset(&tmp.pdata); - - DM_ensure_normals(dm); - - totvert = tmp.totvert = dm->getNumVerts(dm); - totedge = tmp.totedge = dm->getNumEdges(dm); - totloop = tmp.totloop = dm->getNumLoops(dm); - totpoly = tmp.totpoly = dm->getNumPolys(dm); - tmp.totface = 0; - - CustomData_copy(&dm->vertData, &tmp.vdata, mask->vmask, alloctype, totvert); - CustomData_copy(&dm->edgeData, &tmp.edata, mask->emask, alloctype, totedge); - CustomData_copy(&dm->loopData, &tmp.ldata, mask->lmask, alloctype, totloop); - CustomData_copy(&dm->polyData, &tmp.pdata, mask->pmask, alloctype, totpoly); - tmp.cd_flag = dm->cd_flag; - tmp.runtime.deformed_only = dm->deformedOnly; - - if (CustomData_has_layer(&dm->vertData, CD_SHAPEKEY)) { - KeyBlock *kb; - int uid; - - if (ob) { - kb = BLI_findlink(&me->key->block, ob->shapenr - 1); - if (kb) { - uid = kb->uid; - } - else { - CLOG_ERROR(&LOG, "could not find active shapekey %d!", ob->shapenr - 1); - uid = INT_MAX; - } - } - else { - /* if no object, set to INT_MAX so we don't mess up any shapekey layers */ - uid = INT_MAX; - } - - shapekey_layers_to_keyblocks(dm, me, uid); - did_shapekeys = 1; - } - - /* copy texture space */ - if (ob) { - BKE_mesh_texspace_copy_from_object(&tmp, ob); - } - - /* not all DerivedMeshes store their verts/edges/faces in CustomData, so - * we set them here in case they are missing */ - if (!CustomData_has_layer(&tmp.vdata, CD_MVERT)) { - CustomData_add_layer(&tmp.vdata, - CD_MVERT, - CD_ASSIGN, - (alloctype == CD_ASSIGN) ? dm->getVertArray(dm) : dm->dupVertArray(dm), - totvert); - } - if (!CustomData_has_layer(&tmp.edata, CD_MEDGE)) { - CustomData_add_layer(&tmp.edata, - CD_MEDGE, - CD_ASSIGN, - (alloctype == CD_ASSIGN) ? dm->getEdgeArray(dm) : dm->dupEdgeArray(dm), - totedge); - } - if (!CustomData_has_layer(&tmp.pdata, CD_MPOLY)) { - tmp.mloop = (alloctype == CD_ASSIGN) ? dm->getLoopArray(dm) : dm->dupLoopArray(dm); - tmp.mpoly = (alloctype == CD_ASSIGN) ? dm->getPolyArray(dm) : dm->dupPolyArray(dm); - - CustomData_add_layer(&tmp.ldata, CD_MLOOP, CD_ASSIGN, tmp.mloop, tmp.totloop); - CustomData_add_layer(&tmp.pdata, CD_MPOLY, CD_ASSIGN, tmp.mpoly, tmp.totpoly); - } - - /* object had got displacement layer, should copy this layer to save sculpted data */ - /* NOTE: maybe some other layers should be copied? nazgul */ - if (CustomData_has_layer(&me->ldata, CD_MDISPS)) { - if (totloop == me->totloop) { - MDisps *mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS); - CustomData_add_layer(&tmp.ldata, CD_MDISPS, alloctype, mdisps, totloop); - } - } - - /* yes, must be before _and_ after tessellate */ - BKE_mesh_update_customdata_pointers(&tmp, false); - - /* since 2.65 caller must do! */ - // BKE_mesh_tessface_calc(&tmp); - - CustomData_free(&me->vdata, me->totvert); - CustomData_free(&me->edata, me->totedge); - CustomData_free(&me->fdata, me->totface); - CustomData_free(&me->ldata, me->totloop); - CustomData_free(&me->pdata, me->totpoly); - - /* ok, this should now use new CD shapekey data, - * which should be fed through the modifier - * stack */ - if (tmp.totvert != me->totvert && !did_shapekeys && me->key) { - CLOG_WARN(&LOG, "YEEK! this should be recoded! Shape key loss!: ID '%s'", tmp.id.name); - if (tmp.key && !(tmp.id.tag & LIB_TAG_NO_MAIN)) { - id_us_min(&tmp.key->id); - } - tmp.key = NULL; - } - - /* Clear selection history */ - MEM_SAFE_FREE(tmp.mselect); - tmp.totselect = 0; - BLI_assert(ELEM(tmp.bb, NULL, me->bb)); - if (me->bb) { - MEM_freeN(me->bb); - tmp.bb = NULL; - } - - /* skip the listbase */ - MEMCPY_STRUCT_AFTER(me, &tmp, id.prev); - - if (take_ownership) { - if (alloctype == CD_ASSIGN) { - CustomData_free_typemask(&dm->vertData, dm->numVertData, ~mask->vmask); - CustomData_free_typemask(&dm->edgeData, dm->numEdgeData, ~mask->emask); - CustomData_free_typemask(&dm->loopData, dm->numLoopData, ~mask->lmask); - CustomData_free_typemask(&dm->polyData, dm->numPolyData, ~mask->pmask); - } - dm->release(dm); - } -} - /** Utility function to convert an (evaluated) Mesh to a shape key block. */ /* Just a shallow wrapper around BKE_keyblock_convert_from_mesh, * that ensures both evaluated mesh and original one has same number of vertices. */ @@ -819,21 +668,6 @@ void DM_interp_vert_data(DerivedMesh *source, &source->vertData, &dest->vertData, src_indices, weights, NULL, count, dest_index); } -DerivedMesh *mesh_create_derived(Mesh *me, float (*vertCos)[3]) -{ - DerivedMesh *dm = CDDM_from_mesh(me); - - if (!dm) { - return NULL; - } - - if (vertCos) { - CDDM_apply_vert_coords(dm, vertCos); - } - - return dm; -} - static float (*get_editbmesh_orco_verts(BMEditMesh *em))[3] { BMIter iter; @@ -904,7 +738,7 @@ static Mesh *create_orco_mesh(Object *ob, Mesh *me, BMEditMesh *em, int layer) orco = get_orco_coords(ob, em, layer, &free); if (orco) { - BKE_mesh_apply_vert_coords(mesh, orco); + BKE_mesh_vert_coords_apply(mesh, orco); if (free) { MEM_freeN(orco); } @@ -924,10 +758,10 @@ static void add_orco_mesh(Object *ob, BMEditMesh *em, Mesh *mesh, Mesh *mesh_orc free = 1; if (mesh_orco->totvert == totvert) { - orco = BKE_mesh_vertexCos_get(mesh_orco, NULL); + orco = BKE_mesh_vert_coords_alloc(mesh_orco, NULL); } else { - orco = BKE_mesh_vertexCos_get(mesh, NULL); + orco = BKE_mesh_vert_coords_alloc(mesh, NULL); } } else { @@ -963,67 +797,6 @@ static void editmesh_update_statvis_color(const Scene *scene, Object *ob) BKE_editmesh_statvis_calc(em, me->runtime.edit_data, &scene->toolsettings->statvis); } -static void shapekey_layers_to_keyblocks(DerivedMesh *dm, Mesh *me, int actshape_uid) -{ - KeyBlock *kb; - int i, j, tot; - - if (!me->key) { - return; - } - - tot = CustomData_number_of_layers(&dm->vertData, CD_SHAPEKEY); - for (i = 0; i < tot; i++) { - CustomDataLayer *layer = - &dm->vertData.layers[CustomData_get_layer_index_n(&dm->vertData, CD_SHAPEKEY, i)]; - float(*cos)[3], (*kbcos)[3]; - - for (kb = me->key->block.first; kb; kb = kb->next) { - if (kb->uid == layer->uid) { - break; - } - } - - if (!kb) { - kb = BKE_keyblock_add(me->key, layer->name); - kb->uid = layer->uid; - } - - if (kb->data) { - MEM_freeN(kb->data); - } - - cos = CustomData_get_layer_n(&dm->vertData, CD_SHAPEKEY, i); - kb->totelem = dm->numVertData; - - kb->data = kbcos = MEM_malloc_arrayN(kb->totelem, 3 * sizeof(float), "kbcos DerivedMesh.c"); - if (kb->uid == actshape_uid) { - MVert *mvert = dm->getVertArray(dm); - - for (j = 0; j < dm->numVertData; j++, kbcos++, mvert++) { - copy_v3_v3(*kbcos, mvert->co); - } - } - else { - for (j = 0; j < kb->totelem; j++, cos++, kbcos++) { - copy_v3_v3(*kbcos, *cos); - } - } - } - - for (kb = me->key->block.first; kb; kb = kb->next) { - if (kb->totelem != dm->numVertData) { - if (kb->data) { - MEM_freeN(kb->data); - } - - kb->totelem = dm->numVertData; - kb->data = MEM_calloc_arrayN(kb->totelem, 3 * sizeof(float), "kb->data derivedmesh.c"); - CLOG_ERROR(&LOG, "lost a shapekey layer: '%s'! (bmesh internal error)", kb->name); - } - } -} - static void mesh_copy_autosmooth(Mesh *me, Mesh *me_orig) { if (me_orig->flag & ME_AUTOSMOOTH) { @@ -1223,14 +996,14 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, if (mti->type == eModifierTypeType_OnlyDeform && !sculpt_dyntopo) { if (!deformed_verts) { - deformed_verts = BKE_mesh_vertexCos_get(mesh_input, &num_deformed_verts); + deformed_verts = BKE_mesh_vert_coords_alloc(mesh_input, &num_deformed_verts); } else if (isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) { if (mesh_final == NULL) { mesh_final = BKE_mesh_copy_for_eval(mesh_input, true); ASSERT_IS_VALID_MESH(mesh_final); } - BKE_mesh_apply_vert_coords(mesh_final, deformed_verts); + BKE_mesh_vert_coords_apply(mesh_final, deformed_verts); } modwrap_deformVerts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts); @@ -1254,7 +1027,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, mesh_deform = BKE_mesh_copy_for_eval(mesh_input, true); if (deformed_verts) { - BKE_mesh_apply_vert_coords(mesh_deform, deformed_verts); + BKE_mesh_vert_coords_apply(mesh_deform, deformed_verts); } } } @@ -1337,10 +1110,10 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, /* Deforming a mesh, read the vertex locations * out of the mesh and deform them. Once done with this * run of deformers verts will be written back. */ - deformed_verts = BKE_mesh_vertexCos_get(mesh_final, &num_deformed_verts); + deformed_verts = BKE_mesh_vert_coords_alloc(mesh_final, &num_deformed_verts); } else { - deformed_verts = BKE_mesh_vertexCos_get(mesh_input, &num_deformed_verts); + deformed_verts = BKE_mesh_vert_coords_alloc(mesh_input, &num_deformed_verts); } } /* if this is not the last modifier in the stack then recalculate the normals @@ -1348,7 +1121,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, else if (isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) { /* XXX, this covers bug #23673, but we may need normal calc for other types */ if (mesh_final) { - BKE_mesh_apply_vert_coords(mesh_final, deformed_verts); + BKE_mesh_vert_coords_apply(mesh_final, deformed_verts); } } @@ -1367,7 +1140,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, /* apply vertex coordinates or build a Mesh as necessary */ if (mesh_final) { if (deformed_verts) { - BKE_mesh_apply_vert_coords(mesh_final, deformed_verts); + BKE_mesh_vert_coords_apply(mesh_final, deformed_verts); } } else { @@ -1375,7 +1148,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, ASSERT_IS_VALID_MESH(mesh_final); if (deformed_verts) { - BKE_mesh_apply_vert_coords(mesh_final, deformed_verts); + BKE_mesh_vert_coords_apply(mesh_final, deformed_verts); } /* Initialize original indices the first time we evaluate a @@ -1554,7 +1327,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, } } if (deformed_verts) { - BKE_mesh_apply_vert_coords(mesh_final, deformed_verts); + BKE_mesh_vert_coords_apply(mesh_final, deformed_verts); MEM_freeN(deformed_verts); deformed_verts = NULL; } @@ -1614,14 +1387,14 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, } } -float (*editbmesh_get_vertex_cos(BMEditMesh *em, int *r_numVerts))[3] +float (*editbmesh_vert_coords_alloc(BMEditMesh *em, int *r_vert_len))[3] { BMIter iter; BMVert *eve; float(*cos)[3]; int i; - *r_numVerts = em->bm->totvert; + *r_vert_len = em->bm->totvert; cos = MEM_malloc_arrayN(em->bm->totvert, 3 * sizeof(float), "vertexcos"); @@ -1793,10 +1566,10 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, /* Deforming a derived mesh, read the vertex locations * out of the mesh and deform them. Once done with this * run of deformers verts will be written back. */ - deformed_verts = BKE_mesh_vertexCos_get(mesh_final, &num_deformed_verts); + deformed_verts = BKE_mesh_vert_coords_alloc(mesh_final, &num_deformed_verts); } else { - deformed_verts = editbmesh_get_vertex_cos(em_input, &num_deformed_verts); + deformed_verts = editbmesh_vert_coords_alloc(em_input, &num_deformed_verts); } } else if (isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) { @@ -1806,7 +1579,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, mesh_copy_autosmooth(mesh_final, mesh_input); } BLI_assert(deformed_verts != NULL); - BKE_mesh_apply_vert_coords(mesh_final, deformed_verts); + BKE_mesh_vert_coords_apply(mesh_final, deformed_verts); } if (mti->deformVertsEM) { @@ -1826,7 +1599,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, BKE_id_free(NULL, mesh_final); } mesh_final = mesh_tmp; - BKE_mesh_apply_vert_coords(mesh_final, deformed_verts); + BKE_mesh_vert_coords_apply(mesh_final, deformed_verts); } else if (mesh_final == mesh_cage) { /* 'me' may be changed by this modifier, so we need to copy it. */ @@ -1840,7 +1613,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, mesh_copy_autosmooth(mesh_final, mesh_input); if (deformed_verts) { - BKE_mesh_apply_vert_coords(mesh_final, deformed_verts); + BKE_mesh_vert_coords_apply(mesh_final, deformed_verts); } } @@ -1910,7 +1683,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, if (r_cage && i == cageIndex) { if (mesh_final && deformed_verts) { mesh_cage = BKE_mesh_copy_for_eval(mesh_final, false); - BKE_mesh_apply_vert_coords(mesh_cage, deformed_verts); + BKE_mesh_vert_coords_apply(mesh_cage, deformed_verts); } else if (mesh_final) { mesh_cage = mesh_final; @@ -1942,7 +1715,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, BKE_id_free(NULL, mesh_final); } mesh_final = mesh_tmp; - BKE_mesh_apply_vert_coords(mesh_final, deformed_verts); + BKE_mesh_vert_coords_apply(mesh_final, deformed_verts); } } else if (!deformed_verts && mesh_cage) { diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 1a34c5376f6..ab8ea37377d 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -648,7 +648,7 @@ char *BKE_animdata_driver_path_hack(bContext *C, PropertyRNA *prop, char *base_path) { - ID *id = (ID *)ptr->id.data; + ID *id = ptr->owner_id; ScrArea *sa = CTX_wm_area(C); /* get standard path which may be extended */ @@ -1656,14 +1656,14 @@ static bool animsys_store_rna_setting(PointerRNA *ptr, if (path) { /* get property to write to */ if (RNA_path_resolve_property(ptr, path, &r_result->ptr, &r_result->prop)) { - if ((ptr->id.data == NULL) || RNA_property_animateable(&r_result->ptr, r_result->prop)) { + if ((ptr->owner_id == NULL) || RNA_property_animateable(&r_result->ptr, r_result->prop)) { int array_len = RNA_property_array_length(&r_result->ptr, r_result->prop); if (array_len && array_index >= array_len) { if (G.debug & G_DEBUG) { CLOG_WARN(&LOG, "Animato: Invalid array index. ID = '%s', '%s[%d]', array length is %d", - (ptr->id.data) ? (((ID *)ptr->id.data)->name + 2) : "<No ID>", + (ptr->owner_id) ? (ptr->owner_id->name + 2) : "<No ID>", path, array_index, array_len - 1); @@ -1682,7 +1682,7 @@ static bool animsys_store_rna_setting(PointerRNA *ptr, if (G.debug & G_DEBUG) { CLOG_WARN(&LOG, "Animato: Invalid path. ID = '%s', '%s[%d]'", - (ptr->id.data) ? (((ID *)ptr->id.data)->name + 2) : "<No ID>", + (ptr->owner_id) ? (ptr->owner_id->name + 2) : "<No ID>", path, array_index); } @@ -1703,7 +1703,7 @@ static bool animsys_read_rna_setting(PathResolvedRNA *anim_rna, float *r_value) float orig_value; /* caller must ensure this is animatable */ - BLI_assert(RNA_property_animateable(ptr, prop) || ptr->id.data == NULL); + BLI_assert(RNA_property_animateable(ptr, prop) || ptr->owner_id == NULL); switch (RNA_property_type(prop)) { case PROP_BOOLEAN: { @@ -1765,7 +1765,7 @@ static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float val int array_index = anim_rna->prop_index; /* caller must ensure this is animatable */ - BLI_assert(RNA_property_animateable(ptr, prop) || ptr->id.data == NULL); + BLI_assert(RNA_property_animateable(ptr, prop) || ptr->owner_id == NULL); /* Check whether value is new. Otherwise we skip all the updates. */ float old_value; @@ -1844,7 +1844,7 @@ static bool animsys_construct_orig_pointer_rna(const PointerRNA *ptr, PointerRNA * not a valid pointer, but there are exceptions in various places of this file which handles * such pointers. * We do special trickery here as well, to quickly go from evaluated to original NlaStrip. */ - if (ptr->id.data == NULL) { + if (ptr->owner_id == NULL) { if (ptr->type != &RNA_NlaStrip) { return false; } @@ -1855,8 +1855,8 @@ static bool animsys_construct_orig_pointer_rna(const PointerRNA *ptr, PointerRNA ptr_orig->data = strip->orig_strip; } else { - ptr_orig->id.data = ((ID *)ptr_orig->id.data)->orig_id; - ptr_orig->data = ptr_orig->id.data; + ptr_orig->owner_id = ptr_orig->owner_id->orig_id; + ptr_orig->data = ptr_orig->owner_id; } return true; } @@ -2003,7 +2003,7 @@ void animsys_evaluate_action_group(PointerRNA *ptr, bAction *act, bActionGroup * return; } - action_idcode_patch_check(ptr->id.data, act); + action_idcode_patch_check(ptr->owner_id, act); /* if group is muted, don't evaluated any of the F-Curve */ if (agrp->flag & AGRP_MUTED) { @@ -2034,7 +2034,7 @@ static void animsys_evaluate_action_ex(PointerRNA *ptr, return; } - action_idcode_patch_check(ptr->id.data, act); + action_idcode_patch_check(ptr->owner_id, act); /* calculate then execute each curve */ animsys_evaluate_fcurves(ptr, &act->curves, ctime, flush_to_original); @@ -2643,7 +2643,7 @@ static NlaEvalChannel *nlaevalchan_verify(PointerRNA *ptr, NlaEvalData *nlaeval, if (G.debug & G_DEBUG) { CLOG_WARN(&LOG, "Animato: Invalid path. ID = '%s', '%s'", - (ptr->id.data) ? (((ID *)ptr->id.data)->name + 2) : "<No ID>", + (ptr->owner_id) ? (ptr->owner_id->name + 2) : "<No ID>", path); } @@ -2651,7 +2651,7 @@ static NlaEvalChannel *nlaevalchan_verify(PointerRNA *ptr, NlaEvalData *nlaeval, } /* Check that the property can be animated. */ - if (ptr->id.data != NULL && !RNA_property_animateable(&key.ptr, key.prop)) { + if (ptr->owner_id != NULL && !RNA_property_animateable(&key.ptr, key.prop)) { return NULL; } @@ -2884,7 +2884,7 @@ static bool nlaeval_blend_value(NlaBlendData *blend, if (index < 0) { if (G.debug & G_DEBUG) { - ID *id = nec->key.ptr.id.data; + ID *id = nec->key.ptr.owner_id; CLOG_WARN(&LOG, "Animato: Invalid array index. ID = '%s', '%s[%d]', array length is %d", id ? (id->name + 2) : "<No ID>", @@ -3081,7 +3081,7 @@ static void nlastrip_evaluate_actionclip(PointerRNA *ptr, return; } - action_idcode_patch_check(ptr->id.data, strip->act); + action_idcode_patch_check(ptr->owner_id, strip->act); /* join this strip's modifiers to the parent's modifiers (own modifiers first) */ nlaeval_fmodifiers_join_stacks(&tmp_modifiers, &strip->modifiers, modifiers); diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index ea927ca9333..168422a4454 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -268,6 +268,90 @@ void BKE_armature_copy_bone_transforms(bArmature *armature_dst, const bArmature } } +/** Helper for #ED_armature_transform */ +static void armature_transform_recurse(ListBase *bonebase, + const float mat[4][4], + const bool do_props, + /* Cached from 'mat'. */ + const float mat3[3][3], + const float scale, + /* Child bones. */ + const Bone *bone_parent, + const float arm_mat_parent_inv[4][4]) +{ + for (Bone *bone = bonebase->first; bone; bone = bone->next) { + + /* Transform the bone's roll. */ + if (bone_parent == NULL) { + + float roll_mat[3][3]; + { + float delta[3]; + sub_v3_v3v3(delta, bone->tail, bone->head); + vec_roll_to_mat3(delta, bone->roll, roll_mat); + } + + /* Transform the roll matrix. */ + mul_m3_m3m3(roll_mat, mat3, roll_mat); + + /* Apply the transformed roll back. */ + mat3_to_vec_roll(roll_mat, NULL, &bone->roll); + } + + mul_m4_v3(mat, bone->arm_head); + mul_m4_v3(mat, bone->arm_tail); + + /* Get the new head and tail */ + if (bone_parent) { + sub_v3_v3v3(bone->head, bone->arm_head, bone_parent->arm_tail); + sub_v3_v3v3(bone->tail, bone->arm_tail, bone_parent->arm_tail); + + mul_mat3_m4_v3(arm_mat_parent_inv, bone->head); + mul_mat3_m4_v3(arm_mat_parent_inv, bone->tail); + } + else { + copy_v3_v3(bone->head, bone->arm_head); + copy_v3_v3(bone->tail, bone->arm_tail); + } + + BKE_armature_where_is_bone(bone, bone_parent, false); + + { + float arm_mat3[3][3]; + copy_m3_m4(arm_mat3, bone->arm_mat); + mat3_to_vec_roll(arm_mat3, NULL, &bone->arm_roll); + } + + if (do_props) { + bone->rad_head *= scale; + bone->rad_tail *= scale; + bone->dist *= scale; + + /* we could be smarter and scale by the matrix along the x & z axis */ + bone->xwidth *= scale; + bone->zwidth *= scale; + } + + if (!BLI_listbase_is_empty(&bone->childbase)) { + float arm_mat_inv[4][4]; + invert_m4_m4(arm_mat_inv, bone->arm_mat); + armature_transform_recurse(&bone->childbase, mat, do_props, mat3, scale, bone, arm_mat_inv); + } + } +} + +void BKE_armature_transform(bArmature *arm, const float mat[4][4], const bool do_props) +{ + /* Store the scale of the matrix here to use on envelopes. */ + float scale = mat4_to_scale(mat); + float mat3[3][3]; + + copy_m3_m4(mat3, mat); + normalize_m3(mat3); + + armature_transform_recurse(&arm->bonebase, mat, do_props, mat3, scale, NULL, NULL); +} + static Bone *get_named_bone_bonechildren(ListBase *lb, const char *name) { Bone *curBone, *rbone; @@ -2285,7 +2369,7 @@ void vec_roll_to_mat3(const float vec[3], const float roll, float mat[3][3]) /* recursive part, calculates restposition of entire tree of children */ /* used by exiting editmode too */ -void BKE_armature_where_is_bone(Bone *bone, Bone *prevbone, const bool use_recursion) +void BKE_armature_where_is_bone(Bone *bone, const Bone *bone_parent, const bool use_recursion) { float vec[3]; @@ -2301,13 +2385,13 @@ void BKE_armature_where_is_bone(Bone *bone, Bone *prevbone, const bool use_recur bone->segments = 1; } - if (prevbone) { + if (bone_parent) { float offs_bone[4][4]; /* yoffs(b-1) + root(b) + bonemat(b) */ BKE_bone_offset_matrix_get(bone, offs_bone); /* Compose the matrix for this bone */ - mul_m4_m4m4(bone->arm_mat, prevbone->arm_mat, offs_bone); + mul_m4_m4m4(bone->arm_mat, bone_parent->arm_mat, offs_bone); } else { copy_m4_m3(bone->arm_mat, bone->bone_mat); @@ -2316,9 +2400,9 @@ void BKE_armature_where_is_bone(Bone *bone, Bone *prevbone, const bool use_recur /* and the kiddies */ if (use_recursion) { - prevbone = bone; + bone_parent = bone; for (bone = bone->childbase.first; bone; bone = bone->next) { - BKE_armature_where_is_bone(bone, prevbone, use_recursion); + BKE_armature_where_is_bone(bone, bone_parent, use_recursion); } } } diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c index bf7d81e5d63..00975976130 100644 --- a/source/blender/blenkernel/intern/armature_update.c +++ b/source/blender/blenkernel/intern/armature_update.c @@ -887,9 +887,10 @@ void BKE_pose_eval_proxy_copy_bone(struct Depsgraph *depsgraph, Object *object, } BLI_assert(ID_IS_LINKED(object) && object->proxy_from != NULL); bPoseChannel *pchan = pose_pchan_get_indexed(object, pchan_index); + BLI_assert(pchan != NULL); DEG_debug_print_eval_subdata( depsgraph, __func__, object->id.name, object, "pchan", pchan->name, pchan); - /* TODO(sergey): Use indexec lookup, once it's guaranteed to be kept + /* TODO(sergey): Use indexed lookup, once it's guaranteed to be kept * around for the time while proxies are evaluating. */ #if 0 @@ -897,8 +898,13 @@ void BKE_pose_eval_proxy_copy_bone(struct Depsgraph *depsgraph, Object *object, #else bPoseChannel *pchan_from = BKE_pose_channel_find_name(object->proxy_from->pose, pchan->name); #endif - BLI_assert(pchan != NULL); - BLI_assert(pchan_from != NULL); + if (pchan_from == NULL) { + printf( + "WARNING: Could not find bone %s in linked ID anymore... " + "You should delete and re-generate your proxy.\n", + pchan->name); + return; + } BKE_pose_copyesult_pchan_result(pchan, pchan_from); copy_dq_dq(&pchan->runtime.deform_dual_quat, &pchan_from->runtime.deform_dual_quat); BKE_pchan_bbone_segments_cache_copy(pchan, pchan_from); diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index b2d3ccfebc3..83e4a582ff1 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -72,6 +72,7 @@ static void brush_defaults(Brush *brush) brush->autosmooth_factor = 0.0f; brush->topology_rake_factor = 0.0f; brush->crease_pinch_factor = 0.5f; + brush->normal_radius_factor = 0.5f; brush->sculpt_plane = SCULPT_DISP_DIR_AREA; /* How far above or below the plane that is found by averaging the faces. */ brush->plane_offset = 0.0f; diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c index 8c125d1609b..85a12027bf2 100644 --- a/source/blender/blenkernel/intern/bvhutils.c +++ b/source/blender/blenkernel/intern/bvhutils.c @@ -425,11 +425,11 @@ static BVHTree *bvhtree_from_editmesh_verts_create_tree(float epsilon, int tree_type, int axis, BMEditMesh *em, - const int verts_num, const BLI_bitmap *verts_mask, int verts_num_active) { BM_mesh_elem_table_ensure(em->bm, BM_VERT); + const int verts_num = em->bm->totvert; if (verts_mask) { BLI_assert(IN_RANGE_INCL(verts_num_active, 0, verts_num)); } @@ -516,53 +516,53 @@ BVHTree *bvhtree_from_editmesh_verts_ex(BVHTreeFromEditMesh *data, int verts_num_active, float epsilon, int tree_type, - int axis) + int axis, + const int bvh_cache_type, + BVHCache **bvh_cache) { - BVHTree *tree = bvhtree_from_editmesh_verts_create_tree( - epsilon, tree_type, axis, em, em->bm->totvert, verts_mask, verts_num_active); - - if (tree) { - memset(data, 0, sizeof(*data)); - data->tree = tree; - data->em = em; - data->nearest_callback = NULL; - data->raycast_callback = editmesh_verts_spherecast; - } - - return tree; -} + BVHTree *tree = NULL; -BVHTree *bvhtree_from_editmesh_verts(BVHTreeFromEditMesh *data, - BMEditMesh *em, - float epsilon, - int tree_type, - int axis, - BVHCache **bvh_cache) -{ if (bvh_cache) { BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ); - data->cached = bvhcache_find(*bvh_cache, BVHTREE_FROM_EM_VERTS, &data->tree); + data->cached = bvhcache_find(*bvh_cache, bvh_cache_type, &data->tree); BLI_rw_mutex_unlock(&cache_rwlock); if (data->cached == false) { BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE); - data->cached = bvhcache_find(*bvh_cache, BVHTREE_FROM_EM_VERTS, &data->tree); + data->cached = bvhcache_find(*bvh_cache, bvh_cache_type, &data->tree); if (data->cached == false) { - data->tree = bvhtree_from_editmesh_verts_ex(data, em, NULL, -1, epsilon, tree_type, axis); + tree = bvhtree_from_editmesh_verts_create_tree( + epsilon, tree_type, axis, em, verts_mask, verts_num_active); /* Save on cache for later use */ /* printf("BVHTree built and saved on cache\n"); */ - bvhcache_insert(bvh_cache, data->tree, BVHTREE_FROM_EM_VERTS); + bvhcache_insert(bvh_cache, tree, bvh_cache_type); data->cached = true; } BLI_rw_mutex_unlock(&cache_rwlock); } } else { - data->tree = bvhtree_from_editmesh_verts_ex(data, em, NULL, -1, epsilon, tree_type, axis); + tree = bvhtree_from_editmesh_verts_create_tree( + epsilon, tree_type, axis, em, verts_mask, verts_num_active); } - return data->tree; + if (tree) { + memset(data, 0, sizeof(*data)); + data->tree = tree; + data->em = em; + data->nearest_callback = NULL; + data->raycast_callback = editmesh_verts_spherecast; + data->cached = bvh_cache != NULL; + } + + return tree; +} + +BVHTree *bvhtree_from_editmesh_verts( + BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis) +{ + return bvhtree_from_editmesh_verts_ex(data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL); } /** @@ -580,13 +580,40 @@ BVHTree *bvhtree_from_mesh_verts_ex(BVHTreeFromMesh *data, int verts_num_active, float epsilon, int tree_type, - int axis) + int axis, + const int bvh_cache_type, + BVHCache **bvh_cache) { - BVHTree *tree = bvhtree_from_mesh_verts_create_tree( - epsilon, tree_type, axis, vert, verts_num, verts_mask, verts_num_active); + bool in_cache = false; + BVHTree *tree = NULL; + if (bvh_cache) { + BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ); + in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree); + BLI_rw_mutex_unlock(&cache_rwlock); + if (in_cache == false) { + BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE); + in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree); + if (in_cache) { + BLI_rw_mutex_unlock(&cache_rwlock); + } + } + } + + if (in_cache == false) { + tree = bvhtree_from_mesh_verts_create_tree( + epsilon, tree_type, axis, vert, verts_num, verts_mask, verts_num_active); + + if (bvh_cache) { + /* Save on cache for later use */ + /* printf("BVHTree built and saved on cache\n"); */ + bvhcache_insert(bvh_cache, tree, bvh_cache_type); + BLI_rw_mutex_unlock(&cache_rwlock); + in_cache = true; + } + } /* Setup BVHTreeFromMesh */ - bvhtree_from_mesh_verts_setup_data(data, tree, false, vert, vert_allocated); + bvhtree_from_mesh_verts_setup_data(data, tree, in_cache, vert, vert_allocated); return tree; } @@ -601,11 +628,12 @@ static BVHTree *bvhtree_from_editmesh_edges_create_tree(float epsilon, int tree_type, int axis, BMEditMesh *em, - const int edges_num, const BLI_bitmap *edges_mask, int edges_num_active) { BM_mesh_elem_table_ensure(em->bm, BM_EDGE); + const int edges_num = em->bm->totedge; + if (edges_mask) { BLI_assert(IN_RANGE_INCL(edges_num_active, 0, edges_num)); } @@ -705,55 +733,53 @@ BVHTree *bvhtree_from_editmesh_edges_ex(BVHTreeFromEditMesh *data, int edges_num_active, float epsilon, int tree_type, - int axis) + int axis, + const int bvh_cache_type, + BVHCache **bvh_cache) { - int edge_num = em->bm->totedge; - - BVHTree *tree = bvhtree_from_editmesh_edges_create_tree( - epsilon, tree_type, axis, em, edge_num, edges_mask, edges_num_active); - - if (tree) { - memset(data, 0, sizeof(*data)); - data->tree = tree; - data->em = em; - data->nearest_callback = NULL; /* TODO */ - data->raycast_callback = NULL; /* TODO */ - } - - return tree; -} + BVHTree *tree = NULL; -BVHTree *bvhtree_from_editmesh_edges(BVHTreeFromEditMesh *data, - BMEditMesh *em, - float epsilon, - int tree_type, - int axis, - BVHCache **bvh_cache) -{ if (bvh_cache) { BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ); - data->cached = bvhcache_find(*bvh_cache, BVHTREE_FROM_EM_EDGES, &data->tree); + data->cached = bvhcache_find(*bvh_cache, bvh_cache_type, &data->tree); BLI_rw_mutex_unlock(&cache_rwlock); if (data->cached == false) { BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE); - data->cached = bvhcache_find(*bvh_cache, BVHTREE_FROM_EM_EDGES, &data->tree); + data->cached = bvhcache_find(*bvh_cache, bvh_cache_type, &data->tree); if (data->cached == false) { - data->tree = bvhtree_from_editmesh_edges_ex(data, em, NULL, -1, epsilon, tree_type, axis); + tree = bvhtree_from_editmesh_edges_create_tree( + epsilon, tree_type, axis, em, edges_mask, edges_num_active); /* Save on cache for later use */ /* printf("BVHTree built and saved on cache\n"); */ - bvhcache_insert(bvh_cache, data->tree, BVHTREE_FROM_EM_EDGES); + bvhcache_insert(bvh_cache, tree, bvh_cache_type); data->cached = true; } BLI_rw_mutex_unlock(&cache_rwlock); } } else { - data->tree = bvhtree_from_editmesh_edges_ex(data, em, NULL, -1, epsilon, tree_type, axis); + tree = bvhtree_from_editmesh_edges_create_tree( + epsilon, tree_type, axis, em, edges_mask, edges_num_active); } - return data->tree; + if (tree) { + memset(data, 0, sizeof(*data)); + data->tree = tree; + data->em = em; + data->nearest_callback = NULL; /* TODO */ + data->raycast_callback = NULL; /* TODO */ + data->cached = bvh_cache != NULL; + } + + return tree; +} + +BVHTree *bvhtree_from_editmesh_edges( + BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis) +{ + return bvhtree_from_editmesh_edges_ex(data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL); } /** @@ -774,14 +800,41 @@ BVHTree *bvhtree_from_mesh_edges_ex(BVHTreeFromMesh *data, int edges_num_active, float epsilon, int tree_type, - int axis) + int axis, + const int bvh_cache_type, + BVHCache **bvh_cache) { - BVHTree *tree = bvhtree_from_mesh_edges_create_tree( - vert, edge, edges_num, edges_mask, edges_num_active, epsilon, tree_type, axis); + bool in_cache = false; + BVHTree *tree = NULL; + if (bvh_cache) { + BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ); + in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree); + BLI_rw_mutex_unlock(&cache_rwlock); + if (in_cache == false) { + BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE); + in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree); + if (in_cache) { + BLI_rw_mutex_unlock(&cache_rwlock); + } + } + } + + if (in_cache == false) { + tree = bvhtree_from_mesh_edges_create_tree( + vert, edge, edges_num, edges_mask, edges_num_active, epsilon, tree_type, axis); + + if (bvh_cache) { + /* Save on cache for later use */ + /* printf("BVHTree built and saved on cache\n"); */ + bvhcache_insert(bvh_cache, tree, bvh_cache_type); + BLI_rw_mutex_unlock(&cache_rwlock); + in_cache = true; + } + } /* Setup BVHTreeFromMesh */ bvhtree_from_mesh_edges_setup_data( - data, tree, false, vert, vert_allocated, edge, edge_allocated); + data, tree, in_cache, vert, vert_allocated, edge, edge_allocated); return tree; } @@ -882,14 +935,41 @@ BVHTree *bvhtree_from_mesh_faces_ex(BVHTreeFromMesh *data, int faces_num_active, float epsilon, int tree_type, - int axis) + int axis, + const int bvh_cache_type, + BVHCache **bvh_cache) { - BVHTree *tree = bvhtree_from_mesh_faces_create_tree( - epsilon, tree_type, axis, vert, face, numFaces, faces_mask, faces_num_active); + bool in_cache = false; + BVHTree *tree = NULL; + if (bvh_cache) { + BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ); + in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree); + BLI_rw_mutex_unlock(&cache_rwlock); + if (in_cache == false) { + BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE); + in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree); + if (in_cache) { + BLI_rw_mutex_unlock(&cache_rwlock); + } + } + } + + if (in_cache == false) { + tree = bvhtree_from_mesh_faces_create_tree( + epsilon, tree_type, axis, vert, face, numFaces, faces_mask, faces_num_active); + + if (bvh_cache) { + /* Save on cache for later use */ + /* printf("BVHTree built and saved on cache\n"); */ + bvhcache_insert(bvh_cache, tree, bvh_cache_type); + BLI_rw_mutex_unlock(&cache_rwlock); + in_cache = true; + } + } /* Setup BVHTreeFromMesh */ bvhtree_from_mesh_faces_setup_data( - data, tree, false, vert, vert_allocated, face, face_allocated); + data, tree, in_cache, vert, vert_allocated, face, face_allocated); return tree; } @@ -904,12 +984,11 @@ static BVHTree *bvhtree_from_editmesh_looptri_create_tree(float epsilon, int tree_type, int axis, BMEditMesh *em, - const int looptri_num, const BLI_bitmap *looptri_mask, int looptri_num_active) { BVHTree *tree = NULL; - int i; + const int looptri_num = em->tottri; if (looptri_num) { if (looptri_mask) { @@ -923,26 +1002,24 @@ static BVHTree *bvhtree_from_editmesh_looptri_create_tree(float epsilon, /* printf("%s: building BVH, total=%d\n", __func__, numFaces); */ tree = BLI_bvhtree_new(looptri_num_active, epsilon, tree_type, axis); if (tree) { - if (em) { - const struct BMLoop *(*looptris)[3] = (void *)em->looptris; - - /* Insert BMesh-tessellation triangles into the bvh tree, unless they are hidden - * and/or selected. Even if the faces themselves are not selected for the snapped - * transform, having a vertex selected means the face (and thus it's tessellated - * triangles) will be moving and will not be a good snap targets. */ - for (i = 0; i < looptri_num; i++) { - const BMLoop **ltri = looptris[i]; - bool insert = looptri_mask ? BLI_BITMAP_TEST_BOOL(looptri_mask, i) : true; - - if (insert) { - /* No reason found to block hit-testing the triangle for snap, so insert it now.*/ - float co[3][3]; - copy_v3_v3(co[0], ltri[0]->v->co); - copy_v3_v3(co[1], ltri[1]->v->co); - copy_v3_v3(co[2], ltri[2]->v->co); - - BLI_bvhtree_insert(tree, i, co[0], 3); - } + const struct BMLoop *(*looptris)[3] = (void *)em->looptris; + + /* Insert BMesh-tessellation triangles into the bvh tree, unless they are hidden + * and/or selected. Even if the faces themselves are not selected for the snapped + * transform, having a vertex selected means the face (and thus it's tessellated + * triangles) will be moving and will not be a good snap targets. */ + for (int i = 0; i < looptri_num; i++) { + const BMLoop **ltri = looptris[i]; + bool insert = looptri_mask ? BLI_BITMAP_TEST_BOOL(looptri_mask, i) : true; + + if (insert) { + /* No reason found to block hit-testing the triangle for snap, so insert it now.*/ + float co[3][3]; + copy_v3_v3(co[0], ltri[0]->v->co); + copy_v3_v3(co[1], ltri[1]->v->co); + copy_v3_v3(co[2], ltri[2]->v->co); + + BLI_bvhtree_insert(tree, i, co[0], 3); } } BLI_assert(BLI_bvhtree_get_len(tree) == looptri_num_active); @@ -1035,33 +1112,34 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data, float epsilon, int tree_type, int axis, - BVHCache **bvhCache) + const int bvh_cache_type, + BVHCache **bvh_cache) { /* BMESH specific check that we have tessfaces, * we _could_ tessellate here but rather not - campbell */ BVHTree *tree = NULL; - if (bvhCache) { + if (bvh_cache) { BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ); - bool in_cache = bvhcache_find(*bvhCache, BVHTREE_FROM_EM_LOOPTRI, &tree); + bool in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree); BLI_rw_mutex_unlock(&cache_rwlock); if (in_cache == false) { BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE); - in_cache = bvhcache_find(*bvhCache, BVHTREE_FROM_EM_LOOPTRI, &tree); + in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree); if (in_cache == false) { tree = bvhtree_from_editmesh_looptri_create_tree( - epsilon, tree_type, axis, em, em->tottri, looptri_mask, looptri_num_active); + epsilon, tree_type, axis, em, looptri_mask, looptri_num_active); /* Save on cache for later use */ /* printf("BVHTree built and saved on cache\n"); */ - bvhcache_insert(bvhCache, tree, BVHTREE_FROM_EM_LOOPTRI); + bvhcache_insert(bvh_cache, tree, bvh_cache_type); } BLI_rw_mutex_unlock(&cache_rwlock); } } else { tree = bvhtree_from_editmesh_looptri_create_tree( - epsilon, tree_type, axis, em, em->tottri, looptri_mask, looptri_num_active); + epsilon, tree_type, axis, em, looptri_mask, looptri_num_active); } if (tree) { @@ -1069,19 +1147,15 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data, data->nearest_callback = editmesh_looptri_nearest_point; data->raycast_callback = editmesh_looptri_spherecast; data->em = em; - data->cached = bvhCache != NULL; + data->cached = bvh_cache != NULL; } return tree; } -BVHTree *bvhtree_from_editmesh_looptri(BVHTreeFromEditMesh *data, - BMEditMesh *em, - float epsilon, - int tree_type, - int axis, - BVHCache **bvhCache) +BVHTree *bvhtree_from_editmesh_looptri( + BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis) { - return bvhtree_from_editmesh_looptri_ex(data, em, NULL, -1, epsilon, tree_type, axis, bvhCache); + return bvhtree_from_editmesh_looptri_ex(data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL); } /** @@ -1101,21 +1175,54 @@ BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data, int looptri_num_active, float epsilon, int tree_type, - int axis) + int axis, + const int bvh_cache_type, + BVHCache **bvh_cache) { - BVHTree *tree = bvhtree_from_mesh_looptri_create_tree(epsilon, - tree_type, - axis, - vert, - mloop, - looptri, - looptri_num, - looptri_mask, - looptri_num_active); + bool in_cache = false; + BVHTree *tree = NULL; + if (bvh_cache) { + BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ); + in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree); + BLI_rw_mutex_unlock(&cache_rwlock); + if (in_cache == false) { + BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE); + in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree); + if (in_cache) { + BLI_rw_mutex_unlock(&cache_rwlock); + } + } + } + + if (in_cache == false) { + /* Setup BVHTreeFromMesh */ + tree = bvhtree_from_mesh_looptri_create_tree(epsilon, + tree_type, + axis, + vert, + mloop, + looptri, + looptri_num, + looptri_mask, + looptri_num_active); + + if (bvh_cache) { + bvhcache_insert(bvh_cache, tree, bvh_cache_type); + BLI_rw_mutex_unlock(&cache_rwlock); + in_cache = true; + } + } /* Setup BVHTreeFromMesh */ - bvhtree_from_mesh_looptri_setup_data( - data, tree, false, vert, vert_allocated, mloop, loop_allocated, looptri, looptri_allocated); + bvhtree_from_mesh_looptri_setup_data(data, + tree, + in_cache, + vert, + vert_allocated, + mloop, + loop_allocated, + looptri, + looptri_allocated); return tree; } @@ -1204,164 +1311,154 @@ static BLI_bitmap *looptri_no_hidden_map_get(const MPoly *mpoly, */ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, struct Mesh *mesh, - const int type, + const int bvh_cache_type, const int tree_type) { - struct BVHTreeFromMesh data_cp = {0}; + BVHTree *tree = NULL; + BVHCache **bvh_cache = &mesh->runtime.bvh_cache; BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ); - data_cp.cached = bvhcache_find(mesh->runtime.bvh_cache, type, &data_cp.tree); + bool is_cached = bvhcache_find(*bvh_cache, bvh_cache_type, &tree); BLI_rw_mutex_unlock(&cache_rwlock); - if (data_cp.cached && data_cp.tree == NULL) { + if (is_cached && tree == NULL) { memset(data, 0, sizeof(*data)); - return data_cp.tree; + return tree; } - switch (type) { + switch (bvh_cache_type) { case BVHTREE_FROM_VERTS: case BVHTREE_FROM_LOOSEVERTS: - data_cp.raycast_callback = mesh_verts_spherecast; - - data_cp.vert = mesh->mvert; + if (is_cached == false) { + BLI_bitmap *loose_verts_mask = NULL; + int loose_vert_len = -1; + int verts_len = mesh->totvert; + + if (bvh_cache_type == BVHTREE_FROM_LOOSEVERTS) { + loose_verts_mask = loose_verts_map_get( + mesh->medge, mesh->totedge, mesh->mvert, verts_len, &loose_vert_len); + } - if (data_cp.cached == false) { /* TODO: a global mutex lock held during the expensive operation of * building the BVH tree is really bad for performance. */ - BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE); - data_cp.cached = bvhcache_find(mesh->runtime.bvh_cache, type, &data_cp.tree); - - if (data_cp.cached == false) { - BLI_bitmap *loose_verts_mask = NULL; - int loose_vert_len = -1; - int verts_len = mesh->totvert; - - if (type == BVHTREE_FROM_LOOSEVERTS) { - loose_verts_mask = loose_verts_map_get( - mesh->medge, mesh->totedge, data_cp.vert, verts_len, &loose_vert_len); - } - - data_cp.tree = bvhtree_from_mesh_verts_create_tree( - 0.0, tree_type, 6, data_cp.vert, verts_len, loose_verts_mask, loose_vert_len); - - if (loose_verts_mask != NULL) { - MEM_freeN(loose_verts_mask); - } - - /* Save on cache for later use */ - /* printf("BVHTree built and saved on cache\n"); */ - bvhcache_insert(&mesh->runtime.bvh_cache, data_cp.tree, type); + tree = bvhtree_from_mesh_verts_ex(data, + mesh->mvert, + verts_len, + false, + loose_verts_mask, + loose_vert_len, + 0.0f, + tree_type, + 6, + bvh_cache_type, + bvh_cache); + + if (loose_verts_mask != NULL) { + MEM_freeN(loose_verts_mask); } - BLI_rw_mutex_unlock(&cache_rwlock); + } + else { + /* Setup BVHTreeFromMesh */ + bvhtree_from_mesh_verts_setup_data(data, tree, true, mesh->mvert, false); } break; case BVHTREE_FROM_EDGES: case BVHTREE_FROM_LOOSEEDGES: - data_cp.nearest_callback = mesh_edges_nearest_point; - data_cp.raycast_callback = mesh_edges_spherecast; - - data_cp.vert = mesh->mvert; - data_cp.edge = mesh->medge; - - if (data_cp.cached == false) { - BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE); - data_cp.cached = bvhcache_find(mesh->runtime.bvh_cache, type, &data_cp.tree); - if (data_cp.cached == false) { - BLI_bitmap *loose_edges_mask = NULL; - int loose_edges_len = -1; - int edges_len = mesh->totedge; - - if (type == BVHTREE_FROM_LOOSEEDGES) { - loose_edges_mask = loose_edges_map_get(data_cp.edge, edges_len, &loose_edges_len); - } + if (is_cached == false) { + BLI_bitmap *loose_edges_mask = NULL; + int loose_edges_len = -1; + int edges_len = mesh->totedge; - data_cp.tree = bvhtree_from_mesh_edges_create_tree(data_cp.vert, - data_cp.edge, - edges_len, - loose_edges_mask, - loose_edges_len, - 0.0, - tree_type, - 6); - - if (loose_edges_mask != NULL) { - MEM_freeN(loose_edges_mask); - } + if (bvh_cache_type == BVHTREE_FROM_LOOSEEDGES) { + loose_edges_mask = loose_edges_map_get(mesh->medge, edges_len, &loose_edges_len); + } - /* Save on cache for later use */ - /* printf("BVHTree built and saved on cache\n"); */ - bvhcache_insert(&mesh->runtime.bvh_cache, data_cp.tree, type); + tree = bvhtree_from_mesh_edges_ex(data, + mesh->mvert, + false, + mesh->medge, + edges_len, + false, + loose_edges_mask, + loose_edges_len, + 0.0, + tree_type, + 6, + bvh_cache_type, + bvh_cache); + + if (loose_edges_mask != NULL) { + MEM_freeN(loose_edges_mask); } - BLI_rw_mutex_unlock(&cache_rwlock); + } + else { + /* Setup BVHTreeFromMesh */ + bvhtree_from_mesh_edges_setup_data( + data, tree, false, mesh->mvert, false, mesh->medge, false); } break; case BVHTREE_FROM_FACES: - data_cp.nearest_callback = mesh_faces_nearest_point; - data_cp.raycast_callback = mesh_faces_spherecast; - - data_cp.vert = mesh->mvert; - data_cp.face = mesh->mface; - - if (data_cp.cached == false) { - BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE); - data_cp.cached = bvhcache_find(mesh->runtime.bvh_cache, BVHTREE_FROM_FACES, &data_cp.tree); - if (data_cp.cached == false) { - int num_faces = mesh->totface; - BLI_assert(!(num_faces == 0 && mesh->totpoly != 0)); - - data_cp.tree = bvhtree_from_mesh_faces_create_tree( - 0.0, tree_type, 6, data_cp.vert, data_cp.face, num_faces, NULL, -1); - - /* Save on cache for later use */ - /* printf("BVHTree built and saved on cache\n"); */ - bvhcache_insert(&mesh->runtime.bvh_cache, data_cp.tree, BVHTREE_FROM_FACES); - } - BLI_rw_mutex_unlock(&cache_rwlock); + if (is_cached == false) { + int num_faces = mesh->totface; + BLI_assert(!(num_faces == 0 && mesh->totpoly != 0)); + + tree = bvhtree_from_mesh_faces_ex(data, + mesh->mvert, + false, + mesh->mface, + num_faces, + false, + NULL, + -1, + 0.0, + tree_type, + 6, + bvh_cache_type, + bvh_cache); + } + else { + /* Setup BVHTreeFromMesh */ + bvhtree_from_mesh_faces_setup_data( + data, tree, true, mesh->mvert, false, mesh->mface, false); } break; case BVHTREE_FROM_LOOPTRI: case BVHTREE_FROM_LOOPTRI_NO_HIDDEN: - data_cp.nearest_callback = mesh_looptri_nearest_point; - data_cp.raycast_callback = mesh_looptri_spherecast; - - data_cp.vert = mesh->mvert; - data_cp.loop = mesh->mloop; - - /* TODO: store looptris somewhere? */ - data_cp.looptri = BKE_mesh_runtime_looptri_ensure(mesh); - - if (data_cp.cached == false) { - BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE); - data_cp.cached = bvhcache_find( - mesh->runtime.bvh_cache, BVHTREE_FROM_LOOPTRI, &data_cp.tree); - if (data_cp.cached == false) { - BLI_bitmap *looptri_mask = NULL; - int looptri_mask_active_len = -1; - int looptri_len = BKE_mesh_runtime_looptri_len(mesh); - - if (type == BVHTREE_FROM_LOOPTRI_NO_HIDDEN) { - looptri_mask = looptri_no_hidden_map_get( - mesh->mpoly, looptri_len, &looptri_mask_active_len); - } - - data_cp.tree = bvhtree_from_mesh_looptri_create_tree(0.0, - tree_type, - 6, - data_cp.vert, - data_cp.loop, - data_cp.looptri, - looptri_len, - looptri_mask, - looptri_mask_active_len); - - /* Save on cache for later use */ - /* printf("BVHTree built and saved on cache\n"); */ - bvhcache_insert(&mesh->runtime.bvh_cache, data_cp.tree, BVHTREE_FROM_LOOPTRI); + if (is_cached == false) { + const MLoopTri *mlooptri = BKE_mesh_runtime_looptri_ensure(mesh); + int looptri_len = BKE_mesh_runtime_looptri_len(mesh); + + int looptri_mask_active_len = -1; + BLI_bitmap *looptri_mask = NULL; + if (bvh_cache_type == BVHTREE_FROM_LOOPTRI_NO_HIDDEN) { + looptri_mask = looptri_no_hidden_map_get( + mesh->mpoly, looptri_len, &looptri_mask_active_len); } - BLI_rw_mutex_unlock(&cache_rwlock); + + tree = bvhtree_from_mesh_looptri_ex(data, + mesh->mvert, + false, + mesh->mloop, + false, + mlooptri, + looptri_len, + false, + looptri_mask, + looptri_mask_active_len, + 0.0, + tree_type, + 6, + bvh_cache_type, + bvh_cache); + } + else { + /* Setup BVHTreeFromMesh */ + const MLoopTri *mlooptri = BKE_mesh_runtime_looptri_ensure(mesh); + bvhtree_from_mesh_looptri_setup_data( + data, tree, true, mesh->mvert, false, mesh->mloop, false, mlooptri, false); } break; case BVHTREE_FROM_EM_VERTS: @@ -1371,23 +1468,113 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, break; } - if (data_cp.tree != NULL) { + if (data->tree != NULL) { #ifdef DEBUG - if (BLI_bvhtree_get_tree_type(data_cp.tree) != tree_type) { + if (BLI_bvhtree_get_tree_type(data->tree) != tree_type) { printf("tree_type %d obtained instead of %d\n", - BLI_bvhtree_get_tree_type(data_cp.tree), + BLI_bvhtree_get_tree_type(data->tree), tree_type); } #endif - data_cp.cached = true; - memcpy(data, &data_cp, sizeof(*data)); + BLI_assert(data->cached); } else { - free_bvhtree_from_mesh(&data_cp); + free_bvhtree_from_mesh(data); memset(data, 0, sizeof(*data)); } - return data_cp.tree; + return tree; +} + +/** + * Builds or queries a bvhcache for the cache bvhtree of the request type. + */ +BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data, + struct BMEditMesh *em, + const int tree_type, + const int bvh_cache_type, + BVHCache **bvh_cache) +{ + BVHTree *tree = NULL; + bool is_cached = false; + + memset(data, 0, sizeof(*data)); + + if (bvh_cache) { + BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ); + is_cached = bvhcache_find(*bvh_cache, bvh_cache_type, &tree); + BLI_rw_mutex_unlock(&cache_rwlock); + + if (is_cached && tree == NULL) { + return tree; + } + } + data->tree = tree; + data->em = em; + data->cached = is_cached; + + switch (bvh_cache_type) { + case BVHTREE_FROM_EM_VERTS: + if (is_cached == false) { + tree = bvhtree_from_editmesh_verts_ex( + data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache); + } + else { + data->nearest_callback = NULL; + data->raycast_callback = editmesh_verts_spherecast; + } + break; + + case BVHTREE_FROM_EM_EDGES: + if (is_cached == false) { + tree = bvhtree_from_editmesh_edges_ex( + data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache); + } + else { + /* Setup BVHTreeFromMesh */ + data->nearest_callback = NULL; /* TODO */ + data->raycast_callback = NULL; /* TODO */ + } + break; + + case BVHTREE_FROM_EM_LOOPTRI: + if (is_cached == false) { + tree = bvhtree_from_editmesh_looptri_ex( + data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache); + } + else { + /* Setup BVHTreeFromMesh */ + data->nearest_callback = editmesh_looptri_nearest_point; + data->raycast_callback = editmesh_looptri_spherecast; + } + break; + case BVHTREE_FROM_VERTS: + case BVHTREE_FROM_EDGES: + case BVHTREE_FROM_FACES: + case BVHTREE_FROM_LOOPTRI: + case BVHTREE_FROM_LOOPTRI_NO_HIDDEN: + case BVHTREE_FROM_LOOSEVERTS: + case BVHTREE_FROM_LOOSEEDGES: + BLI_assert(false); + break; + } + + if (data->tree != NULL) { +#ifdef DEBUG + if (BLI_bvhtree_get_tree_type(data->tree) != tree_type) { + printf("tree_type %d obtained instead of %d\n", + BLI_bvhtree_get_tree_type(data->tree), + tree_type); + } +#endif + BLI_assert(data->cached); + } + else { + free_bvhtree_from_editmesh(data); + memset(data, 0, sizeof(*data)); + } + + return tree; } /** \} */ @@ -1473,12 +1660,13 @@ bool bvhcache_has_tree(const BVHCache *cache, const BVHTree *tree) * as that will be done when the cache is freed. * * A call to this assumes that there was no previous cached tree of the given type + * \warning The #BVHTree can be NULL. */ void bvhcache_insert(BVHCache **cache_p, BVHTree *tree, int type) { BVHCacheItem *item = NULL; - assert(bvhcache_find(*cache_p, type, &(BVHTree *){0}) == false); + BLI_assert(bvhcache_find(*cache_p, type, &(BVHTree *){0}) == false); item = MEM_mallocN(sizeof(BVHCacheItem), "BVHCacheItem"); diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 28bd9c0cea5..a55b5dc7817 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -173,16 +173,6 @@ static void cdDM_getVertCo(DerivedMesh *dm, int index, float r_co[3]) copy_v3_v3(r_co, cddm->mvert[index].co); } -static void cdDM_getVertCos(DerivedMesh *dm, float (*r_cos)[3]) -{ - MVert *mv = CDDM_get_verts(dm); - int i; - - for (i = 0; i < dm->numVertData; i++, mv++) { - copy_v3_v3(r_cos[i], mv->co); - } -} - static void cdDM_getVertNo(DerivedMesh *dm, int index, float r_no[3]) { CDDerivedMesh *cddm = (CDDerivedMesh *)dm; @@ -203,278 +193,6 @@ static const MeshElemMap *cdDM_getPolyMap(Object *ob, DerivedMesh *dm) return cddm->pmap; } -static bool check_sculpt_object_deformed(Object *object, bool for_construction) -{ - bool deformed = false; - - /* Active modifiers means extra deformation, which can't be handled correct - * on birth of PBVH and sculpt "layer" levels, so use PBVH only for internal brush - * stuff and show final DerivedMesh so user would see actual object shape. - */ - deformed |= object->sculpt->modifiers_active; - - if (for_construction) { - deformed |= object->sculpt->kb != NULL; - } - else { - /* As in case with modifiers, we can't synchronize deformation made against - * PBVH and non-locked keyblock, so also use PBVH only for brushes and - * final DM to give final result to user. - */ - deformed |= object->sculpt->kb && (object->shapeflag & OB_SHAPE_LOCK) == 0; - } - - return deformed; -} - -static bool can_pbvh_draw(Object *ob, DerivedMesh *dm) -{ - CDDerivedMesh *cddm = (CDDerivedMesh *)dm; - Mesh *me = ob->data; - bool deformed = check_sculpt_object_deformed(ob, false); - - if (deformed) { - return false; - } - - return cddm->mvert == me->mvert || ob->sculpt->kb; -} - -static PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm) -{ - CDDerivedMesh *cddm = (CDDerivedMesh *)dm; - - if (!ob) { - cddm->pbvh = NULL; - return NULL; - } - - if (!ob->sculpt) { - return NULL; - } - - if (ob->sculpt->pbvh) { - cddm->pbvh = ob->sculpt->pbvh; - cddm->pbvh_draw = can_pbvh_draw(ob, dm); - } - - /* Sculpting on a BMesh (dynamic-topology) gets a special PBVH */ - if (!cddm->pbvh && ob->sculpt->bm) { - cddm->pbvh = BKE_pbvh_new(); - cddm->pbvh_draw = true; - - BKE_pbvh_build_bmesh(cddm->pbvh, - ob->sculpt->bm, - ob->sculpt->bm_smooth_shading, - ob->sculpt->bm_log, - ob->sculpt->cd_vert_node_offset, - ob->sculpt->cd_face_node_offset); - - pbvh_show_mask_set(cddm->pbvh, ob->sculpt->show_mask); - } - - /* always build pbvh from original mesh, and only use it for drawing if - * this derivedmesh is just original mesh. it's the multires subsurf dm - * that this is actually for, to support a pbvh on a modified mesh */ - if (!cddm->pbvh && ob->type == OB_MESH) { - Mesh *me = BKE_object_get_original_mesh(ob); - const int looptris_num = poly_to_tri_count(me->totpoly, me->totloop); - MLoopTri *looptri; - bool deformed; - - cddm->pbvh = BKE_pbvh_new(); - cddm->pbvh_draw = can_pbvh_draw(ob, dm); - - looptri = MEM_malloc_arrayN(looptris_num, sizeof(*looptri), __func__); - - BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, looptri); - - BKE_pbvh_build_mesh(cddm->pbvh, - me->mpoly, - me->mloop, - me->mvert, - me->totvert, - &me->vdata, - &me->ldata, - looptri, - looptris_num); - - pbvh_show_mask_set(cddm->pbvh, ob->sculpt->show_mask); - - deformed = check_sculpt_object_deformed(ob, true); - - if (deformed && ob->derivedDeform) { - DerivedMesh *deformdm = ob->derivedDeform; - float(*vertCos)[3]; - int totvert; - - totvert = deformdm->getNumVerts(deformdm); - vertCos = MEM_malloc_arrayN(totvert, sizeof(float[3]), "cdDM_getPBVH vertCos"); - deformdm->getVertCos(deformdm, vertCos); - BKE_pbvh_apply_vertCos(cddm->pbvh, vertCos, totvert); - MEM_freeN(vertCos); - } - } - - return cddm->pbvh; -} - -static void cdDM_foreachMappedVert(DerivedMesh *dm, - void (*func)(void *userData, - int index, - const float co[3], - const float no_f[3], - const short no_s[3]), - void *userData, - DMForeachFlag flag) -{ - MVert *mv = CDDM_get_verts(dm); - const int *index = DM_get_vert_data_layer(dm, CD_ORIGINDEX); - int i; - - if (index) { - for (i = 0; i < dm->numVertData; i++, mv++) { - const short *no = (flag & DM_FOREACH_USE_NORMAL) ? mv->no : NULL; - const int orig = *index++; - if (orig == ORIGINDEX_NONE) { - continue; - } - func(userData, orig, mv->co, NULL, no); - } - } - else { - for (i = 0; i < dm->numVertData; i++, mv++) { - const short *no = (flag & DM_FOREACH_USE_NORMAL) ? mv->no : NULL; - func(userData, i, mv->co, NULL, no); - } - } -} - -static void cdDM_foreachMappedEdge( - DerivedMesh *dm, - void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]), - void *userData) -{ - CDDerivedMesh *cddm = (CDDerivedMesh *)dm; - MVert *mv = cddm->mvert; - MEdge *med = cddm->medge; - int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX); - - for (i = 0; i < dm->numEdgeData; i++, med++) { - if (index) { - orig = *index++; - if (orig == ORIGINDEX_NONE) { - continue; - } - func(userData, orig, mv[med->v1].co, mv[med->v2].co); - } - else { - func(userData, i, mv[med->v1].co, mv[med->v2].co); - } - } -} - -static void cdDM_foreachMappedLoop(DerivedMesh *dm, - void (*func)(void *userData, - int vertex_index, - int face_index, - const float co[3], - const float no[3]), - void *userData, - DMForeachFlag flag) -{ - /* We can't use dm->getLoopDataLayout(dm) here, - * we want to always access dm->loopData, EditDerivedBMesh would - * return loop data from bmesh itself. */ - const float(*lnors)[3] = (flag & DM_FOREACH_USE_NORMAL) ? DM_get_loop_data_layer(dm, CD_NORMAL) : - NULL; - - const MVert *mv = CDDM_get_verts(dm); - const MLoop *ml = CDDM_get_loops(dm); - const MPoly *mp = CDDM_get_polys(dm); - const int *v_index = DM_get_vert_data_layer(dm, CD_ORIGINDEX); - const int *f_index = DM_get_poly_data_layer(dm, CD_ORIGINDEX); - int p_idx, i; - - for (p_idx = 0; p_idx < dm->numPolyData; ++p_idx, ++mp) { - for (i = 0; i < mp->totloop; ++i, ++ml) { - const int v_idx = v_index ? v_index[ml->v] : ml->v; - const int f_idx = f_index ? f_index[p_idx] : p_idx; - const float *no = lnors ? *lnors++ : NULL; - if (!ELEM(ORIGINDEX_NONE, v_idx, f_idx)) { - func(userData, v_idx, f_idx, mv[ml->v].co, no); - } - } - } -} - -static void cdDM_foreachMappedFaceCenter( - DerivedMesh *dm, - void (*func)(void *userData, int index, const float cent[3], const float no[3]), - void *userData, - DMForeachFlag flag) -{ - CDDerivedMesh *cddm = (CDDerivedMesh *)dm; - MVert *mvert = cddm->mvert; - MPoly *mp; - MLoop *ml; - int i, orig, *index; - - index = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX); - mp = cddm->mpoly; - for (i = 0; i < dm->numPolyData; i++, mp++) { - float cent[3]; - float *no, _no[3]; - - if (index) { - orig = *index++; - if (orig == ORIGINDEX_NONE) { - continue; - } - } - else { - orig = i; - } - - ml = &cddm->mloop[mp->loopstart]; - BKE_mesh_calc_poly_center(mp, ml, mvert, cent); - - if (flag & DM_FOREACH_USE_NORMAL) { - BKE_mesh_calc_poly_normal(mp, ml, mvert, (no = _no)); - } - else { - no = NULL; - } - - func(userData, orig, cent, no); - } -} - -void CDDM_recalc_tessellation_ex(DerivedMesh *dm, const bool do_face_nor_cpy) -{ - CDDerivedMesh *cddm = (CDDerivedMesh *)dm; - - dm->numTessFaceData = BKE_mesh_recalc_tessellation(&dm->faceData, - &dm->loopData, - &dm->polyData, - cddm->mvert, - dm->numTessFaceData, - dm->numLoopData, - dm->numPolyData, - do_face_nor_cpy); - - cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE); - - /* Tessellation recreated faceData, and the active layer indices need to get re-propagated - * from loops and polys to faces */ - CustomData_bmesh_update_active_layers(&dm->faceData, &dm->loopData); -} - -void CDDM_recalc_tessellation(DerivedMesh *dm) -{ - CDDM_recalc_tessellation_ex(dm, true); -} - void CDDM_recalc_looptri(DerivedMesh *dm) { CDDerivedMesh *cddm = (CDDerivedMesh *)dm; @@ -547,25 +265,13 @@ static CDDerivedMesh *cdDM_create(const char *desc) dm->getEdgeDataArray = DM_get_edge_data_layer; dm->getTessFaceDataArray = DM_get_tessface_data_layer; - dm->calcNormals = CDDM_calc_normals; - dm->calcLoopNormals = CDDM_calc_loop_normals; - dm->calcLoopNormalsSpaceArray = CDDM_calc_loop_normals_spacearr; - dm->calcLoopTangents = DM_calc_loop_tangents; - dm->recalcTessellation = CDDM_recalc_tessellation; dm->recalcLoopTri = CDDM_recalc_looptri; - dm->getVertCos = cdDM_getVertCos; dm->getVertCo = cdDM_getVertCo; dm->getVertNo = cdDM_getVertNo; - dm->getPBVH = cdDM_getPBVH; dm->getPolyMap = cdDM_getPolyMap; - dm->foreachMappedVert = cdDM_foreachMappedVert; - dm->foreachMappedEdge = cdDM_foreachMappedEdge; - dm->foreachMappedLoop = cdDM_foreachMappedLoop; - dm->foreachMappedFaceCenter = cdDM_foreachMappedFaceCenter; - dm->release = cdDM_release; return cddm; @@ -664,123 +370,12 @@ DerivedMesh *CDDM_from_mesh_ex(Mesh *mesh, return dm; } -DerivedMesh *CDDM_from_curve(Object *ob) -{ - ListBase disp = {NULL, NULL}; - - if (ob->runtime.curve_cache) { - disp = ob->runtime.curve_cache->disp; - } - - return CDDM_from_curve_displist(ob, &disp); -} - -DerivedMesh *CDDM_from_curve_displist(Object *ob, ListBase *dispbase) -{ - Curve *cu = (Curve *)ob->data; - DerivedMesh *dm; - CDDerivedMesh *cddm; - MVert *allvert; - MEdge *alledge; - MLoop *allloop; - MPoly *allpoly; - MLoopUV *alluv = NULL; - int totvert, totedge, totloop, totpoly; - bool use_orco_uv = (cu->flag & CU_UV_ORCO) != 0; - - if (BKE_mesh_nurbs_displist_to_mdata(ob, - dispbase, - &allvert, - &totvert, - &alledge, - &totedge, - &allloop, - &allpoly, - (use_orco_uv) ? &alluv : NULL, - &totloop, - &totpoly) != 0) { - /* Error initializing mdata. This often happens when curve is empty */ - return CDDM_new(0, 0, 0, 0, 0); - } - - dm = CDDM_new(totvert, totedge, 0, totloop, totpoly); - dm->deformedOnly = 1; - dm->dirty |= DM_DIRTY_NORMALS; - - cddm = (CDDerivedMesh *)dm; - - memcpy(cddm->mvert, allvert, totvert * sizeof(MVert)); - memcpy(cddm->medge, alledge, totedge * sizeof(MEdge)); - memcpy(cddm->mloop, allloop, totloop * sizeof(MLoop)); - memcpy(cddm->mpoly, allpoly, totpoly * sizeof(MPoly)); - - if (alluv) { - const char *uvname = "Orco"; - CustomData_add_layer_named(&cddm->dm.loopData, CD_MLOOPUV, CD_ASSIGN, alluv, totloop, uvname); - } - - MEM_freeN(allvert); - MEM_freeN(alledge); - MEM_freeN(allloop); - MEM_freeN(allpoly); - - return dm; -} - -static void loops_to_customdata_corners( - BMesh *bm, CustomData *facedata, int cdindex, const BMLoop *l3[3], int numCol, int numUV) -{ - const BMLoop *l; - // BMFace *f = l3[0]->f; - MTFace *texface; - MCol *mcol; - MLoopCol *mloopcol; - MLoopUV *mloopuv; - int i, j, hasPCol = CustomData_has_layer(&bm->ldata, CD_PREVIEW_MLOOPCOL); - - for (i = 0; i < numUV; i++) { - texface = CustomData_get_n(facedata, CD_MTFACE, cdindex, i); - - for (j = 0; j < 3; j++) { - l = l3[j]; - mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i); - copy_v2_v2(texface->uv[j], mloopuv->uv); - } - } - - for (i = 0; i < numCol; i++) { - mcol = CustomData_get_n(facedata, CD_MCOL, cdindex, i); - - for (j = 0; j < 3; j++) { - l = l3[j]; - mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPCOL, i); - MESH_MLOOPCOL_TO_MCOL(mloopcol, &mcol[j]); - } - } - - if (hasPCol) { - mcol = CustomData_get(facedata, cdindex, CD_PREVIEW_MCOL); - - for (j = 0; j < 3; j++) { - l = l3[j]; - mloopcol = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PREVIEW_MLOOPCOL); - MESH_MLOOPCOL_TO_MCOL(mloopcol, &mcol[j]); - } - } -} - /* TODO(campbell): remove, use BKE_mesh_from_bmesh_for_eval_nomain instead. */ /* used for both editbmesh and bmesh */ -static DerivedMesh *cddm_from_bmesh_ex(struct BMesh *bm, - const bool use_mdisps, - /* EditBMesh vars for use_tessface */ - const bool use_tessface, - const int em_tottri, - const BMLoop *(*em_looptris)[3]) +static DerivedMesh *cddm_from_bmesh_ex(struct BMesh *bm, const bool use_mdisps) { - DerivedMesh *dm = CDDM_new( - bm->totvert, bm->totedge, use_tessface ? em_tottri : 0, bm->totloop, bm->totface); + DerivedMesh *dm = CDDM_new(bm->totvert, bm->totedge, 0, bm->totloop, bm->totface); CDDerivedMesh *cddm = (CDDerivedMesh *)dm; BMIter iter; @@ -789,11 +384,8 @@ static DerivedMesh *cddm_from_bmesh_ex(struct BMesh *bm, BMFace *efa; MVert *mvert = cddm->mvert; MEdge *medge = cddm->medge; - MFace *mface = cddm->mface; MLoop *mloop = cddm->mloop; MPoly *mpoly = cddm->mpoly; - int numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL); - int numUV = CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV); int *index, add_orig; CustomData_MeshMasks mask = {0}; unsigned int i, j; @@ -820,11 +412,6 @@ static DerivedMesh *cddm_from_bmesh_ex(struct BMesh *bm, CustomData_merge(&bm->ldata, &dm->loopData, mask.lmask, CD_CALLOC, dm->numLoopData); CustomData_merge(&bm->pdata, &dm->polyData, mask.pmask, CD_CALLOC, dm->numPolyData); - /* add tessellation mface layers */ - if (use_tessface) { - CustomData_from_bmeshpoly(&dm->faceData, &dm->loopData, em_tottri); - } - index = dm->getVertDataArray(dm, CD_ORIGINDEX); BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { @@ -883,32 +470,6 @@ static DerivedMesh *cddm_from_bmesh_ex(struct BMesh *bm, } bm->elem_index_dirty &= ~BM_EDGE; - /* avoid this where possiblem, takes extra memory */ - if (use_tessface) { - - BM_mesh_elem_index_ensure(bm, BM_FACE); - - index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); - for (i = 0; i < dm->numTessFaceData; i++) { - MFace *mf = &mface[i]; - const BMLoop **l = em_looptris[i]; - efa = l[0]->f; - - mf->v1 = BM_elem_index_get(l[0]->v); - mf->v2 = BM_elem_index_get(l[1]->v); - mf->v3 = BM_elem_index_get(l[2]->v); - mf->v4 = 0; - mf->mat_nr = efa->mat_nr; - mf->flag = BM_face_flag_to_mflag(efa); - - /* map mfaces to polygons in the same cddm intentionally */ - *index++ = BM_elem_index_get(efa); - - loops_to_customdata_corners(bm, &dm->faceData, i, l, numCol, numUV); - test_index_face(mf, &dm->faceData, i, 3); - } - } - index = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX); j = 0; BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) { @@ -948,24 +509,9 @@ static DerivedMesh *cddm_from_bmesh_ex(struct BMesh *bm, return dm; } -struct DerivedMesh *CDDM_from_bmesh(struct BMesh *bm, const bool use_mdisps) +DerivedMesh *CDDM_from_editbmesh(BMEditMesh *em, const bool use_mdisps) { - return cddm_from_bmesh_ex(bm, - use_mdisps, - false, - /* these vars are for editmesh only */ - 0, - NULL); -} - -DerivedMesh *CDDM_from_editbmesh(BMEditMesh *em, const bool use_mdisps, const bool use_tessface) -{ - return cddm_from_bmesh_ex(em->bm, - use_mdisps, - /* editmesh */ - use_tessface, - em->tottri, - (const BMLoop *(*)[3])em->looptris); + return cddm_from_bmesh_ex(em->bm, use_mdisps); } DerivedMesh *CDDM_copy(DerivedMesh *source) @@ -1014,366 +560,11 @@ DerivedMesh *CDDM_copy(DerivedMesh *source) return dm; } -/* note, the CD_ORIGINDEX layers are all 0, so if there is a direct - * relationship between mesh data this needs to be set by the caller. */ -DerivedMesh *CDDM_from_template_ex(DerivedMesh *source, - int numVerts, - int numEdges, - int numTessFaces, - int numLoops, - int numPolys, - const CustomData_MeshMasks *mask) -{ - CDDerivedMesh *cddm = cdDM_create("CDDM_from_template dest"); - DerivedMesh *dm = &cddm->dm; - - /* ensure these are created if they are made on demand */ - source->getVertDataArray(source, CD_ORIGINDEX); - source->getEdgeDataArray(source, CD_ORIGINDEX); - source->getTessFaceDataArray(source, CD_ORIGINDEX); - source->getPolyDataArray(source, CD_ORIGINDEX); - - /* this does a copy of all non mvert/medge/mface layers */ - DM_from_template_ex( - dm, source, DM_TYPE_CDDM, numVerts, numEdges, numTessFaces, numLoops, numPolys, mask); - - /* now add mvert/medge/mface layers */ - CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts); - CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges); - CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numTessFaces); - CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_CALLOC, NULL, numLoops); - CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_CALLOC, NULL, numPolys); - - if (!CustomData_get_layer(&dm->vertData, CD_ORIGINDEX)) { - CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts); - } - if (!CustomData_get_layer(&dm->edgeData, CD_ORIGINDEX)) { - CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges); - } - if (!CustomData_get_layer(&dm->faceData, CD_ORIGINDEX)) { - CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numTessFaces); - } - - cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT); - cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE); - cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE); - cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP); - cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY); - - return dm; -} -DerivedMesh *CDDM_from_template( - DerivedMesh *source, int numVerts, int numEdges, int numTessFaces, int numLoops, int numPolys) -{ - return CDDM_from_template_ex( - source, numVerts, numEdges, numTessFaces, numLoops, numPolys, &CD_MASK_DERIVEDMESH); -} - -void CDDM_apply_vert_coords(DerivedMesh *dm, float (*vertCoords)[3]) -{ - CDDerivedMesh *cddm = (CDDerivedMesh *)dm; - MVert *vert; - int i; - - /* this will just return the pointer if it wasn't a referenced layer */ - vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, dm->numVertData); - cddm->mvert = vert; - - for (i = 0; i < dm->numVertData; ++i, ++vert) { - copy_v3_v3(vert->co, vertCoords[i]); - } - - cddm->dm.dirty |= DM_DIRTY_NORMALS; -} - -void CDDM_apply_vert_normals(DerivedMesh *dm, short (*vertNormals)[3]) -{ - CDDerivedMesh *cddm = (CDDerivedMesh *)dm; - MVert *vert; - int i; - - /* this will just return the pointer if it wasn't a referenced layer */ - vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, dm->numVertData); - cddm->mvert = vert; - - for (i = 0; i < dm->numVertData; ++i, ++vert) { - copy_v3_v3_short(vert->no, vertNormals[i]); - } - - cddm->dm.dirty &= ~DM_DIRTY_NORMALS; -} - -void CDDM_calc_normals_mapping_ex(DerivedMesh *dm, const bool only_face_normals) -{ - CDDerivedMesh *cddm = (CDDerivedMesh *)dm; - float(*face_nors)[3] = NULL; - - if (dm->numVertData == 0) { - cddm->dm.dirty &= ~DM_DIRTY_NORMALS; - return; - } - - /* now we skip calculating vertex normals for referenced layer, - * no need to duplicate verts. - * WATCH THIS, bmesh only change!, - * need to take care of the side effects here - campbell */ -#if 0 - /* we don't want to overwrite any referenced layers */ - cddm->mvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, dm->numVertData); -#endif - -#if 0 - if (dm->numTessFaceData == 0) { - /* No tessellation on this mesh yet, need to calculate one. - * - * Important not to update face normals from polys since it - * interferes with assigning the new normal layer in the following code. - */ - CDDM_recalc_tessellation_ex(dm, false); - } - else { - /* A tessellation already exists, it should always have a CD_ORIGINDEX */ - BLI_assert(CustomData_has_layer(&dm->faceData, CD_ORIGINDEX)); - CustomData_free_layers(&dm->faceData, CD_NORMAL, dm->numTessFaceData); - } -#endif - - face_nors = MEM_malloc_arrayN(dm->numPolyData, sizeof(*face_nors), "face_nors"); - - /* calculate face normals */ - BKE_mesh_calc_normals_poly(cddm->mvert, - NULL, - dm->numVertData, - CDDM_get_loops(dm), - CDDM_get_polys(dm), - dm->numLoopData, - dm->numPolyData, - face_nors, - only_face_normals); - - CustomData_add_layer(&dm->polyData, CD_NORMAL, CD_ASSIGN, face_nors, dm->numPolyData); - - cddm->dm.dirty &= ~DM_DIRTY_NORMALS; -} - -void CDDM_calc_normals_mapping(DerivedMesh *dm) -{ - /* use this to skip calculating normals on original vert's, this may need to be changed */ - const bool only_face_normals = CustomData_is_referenced_layer(&dm->vertData, CD_MVERT); - - CDDM_calc_normals_mapping_ex(dm, only_face_normals); -} - -#if 0 -/* bmesh note: this matches what we have in trunk */ -void CDDM_calc_normals(DerivedMesh *dm) -{ - CDDerivedMesh *cddm = (CDDerivedMesh *)dm; - float(*poly_nors)[3]; - - if (dm->numVertData == 0) { - return; - } - - /* we don't want to overwrite any referenced layers */ - cddm->mvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, dm->numVertData); - - /* fill in if it exists */ - poly_nors = CustomData_get_layer(&dm->polyData, CD_NORMAL); - if (!poly_nors) { - poly_nors = CustomData_add_layer(&dm->polyData, CD_NORMAL, CD_CALLOC, NULL, dm->numPolyData); - } - - BKE_mesh_calc_normals_poly(cddm->mvert, - dm->numVertData, - CDDM_get_loops(dm), - CDDM_get_polys(dm), - dm->numLoopData, - dm->numPolyData, - poly_nors, - false); - - cddm->dm.dirty &= ~DM_DIRTY_NORMALS; -} -#else - -/* poly normal layer is now only for final display */ -void CDDM_calc_normals(DerivedMesh *dm) -{ - CDDerivedMesh *cddm = (CDDerivedMesh *)dm; - - /* we don't want to overwrite any referenced layers */ - cddm->mvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, dm->numVertData); - - BKE_mesh_calc_normals_poly(cddm->mvert, - NULL, - dm->numVertData, - CDDM_get_loops(dm), - CDDM_get_polys(dm), - dm->numLoopData, - dm->numPolyData, - NULL, - false); - - cddm->dm.dirty &= ~DM_DIRTY_NORMALS; -} - -#endif - -void CDDM_calc_loop_normals(DerivedMesh *dm, const bool use_split_normals, const float split_angle) -{ - CDDM_calc_loop_normals_spacearr(dm, use_split_normals, split_angle, NULL); -} - /* #define DEBUG_CLNORS */ #ifdef DEBUG_CLNORS # include "BLI_linklist.h" #endif -void CDDM_calc_loop_normals_spacearr(DerivedMesh *dm, - const bool use_split_normals, - const float split_angle, - MLoopNorSpaceArray *r_lnors_spacearr) -{ - MVert *mverts = dm->getVertArray(dm); - MEdge *medges = dm->getEdgeArray(dm); - MLoop *mloops = dm->getLoopArray(dm); - MPoly *mpolys = dm->getPolyArray(dm); - - CustomData *ldata, *pdata; - - float(*lnors)[3]; - short(*clnor_data)[2]; - float(*pnors)[3]; - - const int numVerts = dm->getNumVerts(dm); - const int numEdges = dm->getNumEdges(dm); - const int numLoops = dm->getNumLoops(dm); - const int numPolys = dm->getNumPolys(dm); - - ldata = dm->getLoopDataLayout(dm); - if (CustomData_has_layer(ldata, CD_NORMAL)) { - lnors = CustomData_get_layer(ldata, CD_NORMAL); - } - else { - lnors = CustomData_add_layer(ldata, CD_NORMAL, CD_CALLOC, NULL, numLoops); - } - - /* Compute poly (always needed) and vert normals. */ - /* Note we can't use DM_ensure_normals, since it won't keep computed poly nors... */ - pdata = dm->getPolyDataLayout(dm); - pnors = CustomData_get_layer(pdata, CD_NORMAL); - if (!pnors) { - pnors = CustomData_add_layer(pdata, CD_NORMAL, CD_CALLOC, NULL, numPolys); - } - BKE_mesh_calc_normals_poly(mverts, - NULL, - numVerts, - mloops, - mpolys, - numLoops, - numPolys, - pnors, - (dm->dirty & DM_DIRTY_NORMALS) ? false : true); - - dm->dirty &= ~DM_DIRTY_NORMALS; - - clnor_data = CustomData_get_layer(ldata, CD_CUSTOMLOOPNORMAL); - - BKE_mesh_normals_loop_split(mverts, - numVerts, - medges, - numEdges, - mloops, - lnors, - numLoops, - mpolys, - (const float(*)[3])pnors, - numPolys, - use_split_normals, - split_angle, - r_lnors_spacearr, - clnor_data, - NULL); -#ifdef DEBUG_CLNORS - if (r_lnors_spacearr) { - int i; - for (i = 0; i < numLoops; i++) { - if (r_lnors_spacearr->lspacearr[i]->ref_alpha != 0.0f) { - LinkNode *loops = r_lnors_spacearr->lspacearr[i]->loops; - printf("Loop %d uses lnor space %p:\n", i, r_lnors_spacearr->lspacearr[i]); - print_v3("\tfinal lnor", lnors[i]); - print_v3("\tauto lnor", r_lnors_spacearr->lspacearr[i]->vec_lnor); - print_v3("\tref_vec", r_lnors_spacearr->lspacearr[i]->vec_ref); - printf("\talpha: %f\n\tbeta: %f\n\tloops: %p\n", - r_lnors_spacearr->lspacearr[i]->ref_alpha, - r_lnors_spacearr->lspacearr[i]->ref_beta, - r_lnors_spacearr->lspacearr[i]->loops); - printf("\t\t(shared with loops"); - while (loops) { - printf(" %d", POINTER_AS_INT(loops->link)); - loops = loops->next; - } - printf(")\n"); - } - else { - printf("Loop %d has no lnor space\n", i); - } - } - } -#endif -} - -void CDDM_lower_num_verts(DerivedMesh *dm, int numVerts) -{ - BLI_assert(numVerts >= 0); - if (numVerts < dm->numVertData) { - CustomData_free_elem(&dm->vertData, numVerts, dm->numVertData - numVerts); - } - - dm->numVertData = numVerts; -} - -void CDDM_lower_num_edges(DerivedMesh *dm, int numEdges) -{ - BLI_assert(numEdges >= 0); - if (numEdges < dm->numEdgeData) { - CustomData_free_elem(&dm->edgeData, numEdges, dm->numEdgeData - numEdges); - } - - dm->numEdgeData = numEdges; -} - -void CDDM_lower_num_tessfaces(DerivedMesh *dm, int numTessFaces) -{ - BLI_assert(numTessFaces >= 0); - if (numTessFaces < dm->numTessFaceData) { - CustomData_free_elem(&dm->faceData, numTessFaces, dm->numTessFaceData - numTessFaces); - } - - dm->numTessFaceData = numTessFaces; -} - -void CDDM_lower_num_loops(DerivedMesh *dm, int numLoops) -{ - BLI_assert(numLoops >= 0); - if (numLoops < dm->numLoopData) { - CustomData_free_elem(&dm->loopData, numLoops, dm->numLoopData - numLoops); - } - - dm->numLoopData = numLoops; -} - -void CDDM_lower_num_polys(DerivedMesh *dm, int numPolys) -{ - BLI_assert(numPolys >= 0); - if (numPolys < dm->numPolyData) { - CustomData_free_elem(&dm->polyData, numPolys, dm->numPolyData - numPolys); - } - - dm->numPolyData = numPolys; -} - /* mesh element access functions */ MVert *CDDM_get_vert(DerivedMesh *dm, int index) @@ -1427,58 +618,3 @@ MPoly *CDDM_get_polys(DerivedMesh *dm) { return ((CDDerivedMesh *)dm)->mpoly; } - -void CDDM_set_mvert(DerivedMesh *dm, MVert *mvert) -{ - CDDerivedMesh *cddm = (CDDerivedMesh *)dm; - - if (!CustomData_has_layer(&dm->vertData, CD_MVERT)) { - CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, mvert, dm->numVertData); - } - - cddm->mvert = mvert; -} - -void CDDM_set_medge(DerivedMesh *dm, MEdge *medge) -{ - CDDerivedMesh *cddm = (CDDerivedMesh *)dm; - - if (!CustomData_has_layer(&dm->edgeData, CD_MEDGE)) { - CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, medge, dm->numEdgeData); - } - - cddm->medge = medge; -} - -void CDDM_set_mface(DerivedMesh *dm, MFace *mface) -{ - CDDerivedMesh *cddm = (CDDerivedMesh *)dm; - - if (!CustomData_has_layer(&dm->faceData, CD_MFACE)) { - CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, mface, dm->numTessFaceData); - } - - cddm->mface = mface; -} - -void CDDM_set_mloop(DerivedMesh *dm, MLoop *mloop) -{ - CDDerivedMesh *cddm = (CDDerivedMesh *)dm; - - if (!CustomData_has_layer(&dm->loopData, CD_MLOOP)) { - CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_ASSIGN, mloop, dm->numLoopData); - } - - cddm->mloop = mloop; -} - -void CDDM_set_mpoly(DerivedMesh *dm, MPoly *mpoly) -{ - CDDerivedMesh *cddm = (CDDerivedMesh *)dm; - - if (!CustomData_has_layer(&dm->polyData, CD_MPOLY)) { - CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_ASSIGN, mpoly, dm->numPolyData); - } - - cddm->mpoly = mpoly; -} diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c index 2031576190e..f2098cc2430 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -203,6 +203,9 @@ void BKE_collection_copy_data(Main *bmain, const Collection *collection_src, const int flag) { + BLI_assert(((collection_src->flag & COLLECTION_IS_MASTER) != 0) == + ((collection_src->id.flag & LIB_PRIVATE_DATA) != 0)); + /* Do not copy collection's preview (same behavior as for objects). */ if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0 && false) { /* XXX TODO temp hack */ BKE_previewimg_id_copy(&collection_dst->id, &collection_src->id); @@ -338,8 +341,9 @@ Collection *BKE_collection_duplicate(Main *bmain, const bool do_obdata) { /* It's not allowed to copy the master collection. */ + BLI_assert((collection->id.flag & LIB_PRIVATE_DATA) == 0); + BLI_assert((collection->flag & COLLECTION_IS_MASTER) == 0); if (collection->flag & COLLECTION_IS_MASTER) { - BLI_assert("!Master collection can't be duplicated"); return NULL; } @@ -365,15 +369,6 @@ Collection *BKE_collection_duplicate(Main *bmain, return collection_new; } -Collection *BKE_collection_copy_master(Main *bmain, Collection *collection, const int flag) -{ - BLI_assert(collection->flag & COLLECTION_IS_MASTER); - - Collection *collection_dst = MEM_dupallocN(collection); - BKE_collection_copy_data(bmain, collection_dst, collection, flag); - return collection_dst; -} - void BKE_collection_make_local(Main *bmain, Collection *collection, const bool lib_local) { BKE_id_make_local_generic(bmain, &collection->id, true, lib_local); @@ -499,15 +494,11 @@ Collection *BKE_collection_master_add() /* Not an actual datablock, but owned by scene. */ Collection *master_collection = MEM_callocN(sizeof(Collection), "Master Collection"); STRNCPY(master_collection->id.name, "GRMaster Collection"); + master_collection->id.flag |= LIB_PRIVATE_DATA; master_collection->flag |= COLLECTION_IS_MASTER; return master_collection; } -Collection *BKE_collection_master(const Scene *scene) -{ - return scene->master_collection; -} - Scene *BKE_collection_master_scene_search(const Main *bmain, const Collection *master_collection) { BLI_assert((master_collection->flag & COLLECTION_IS_MASTER) != 0); @@ -584,7 +575,7 @@ bool BKE_collection_has_object_recursive(Collection *collection, Object *ob) static Collection *collection_next_find(Main *bmain, Scene *scene, Collection *collection) { - if (scene && collection == BKE_collection_master(scene)) { + if (scene && collection == scene->master_collection) { return bmain->collections.first; } else { @@ -601,7 +592,7 @@ Collection *BKE_collection_object_find(Main *bmain, collection = collection_next_find(bmain, scene, collection); } else if (scene) { - collection = BKE_collection_master(scene); + collection = scene->master_collection; } else { collection = bmain->collections.first; @@ -743,7 +734,7 @@ void BKE_collection_object_add_from(Main *bmain, Scene *scene, Object *ob_src, O if (!is_instantiated) { /* In case we could not find any non-linked collections in which instantiate our ob_dst, * fallback to scene's master collection... */ - collection_object_add(bmain, BKE_collection_master(scene), ob_dst, 0, true); + collection_object_add(bmain, scene->master_collection, ob_dst, 0, true); } BKE_main_collection_sync(bmain); @@ -885,7 +876,7 @@ void BKE_collections_child_remove_nulls(Main *bmain, Collection *collection) collection_null_children_remove(collection); } for (Scene *scene = bmain->scenes.first; scene != NULL; scene = scene->id.next) { - collection_null_children_remove(BKE_collection_master(scene)); + collection_null_children_remove(scene->master_collection); } for (collection = bmain->collections.first; collection != NULL; @@ -893,7 +884,7 @@ void BKE_collections_child_remove_nulls(Main *bmain, Collection *collection) collection_missing_parents_remove(collection); } for (Scene *scene = bmain->scenes.first; scene != NULL; scene = scene->id.next) { - collection_missing_parents_remove(BKE_collection_master(scene)); + collection_missing_parents_remove(scene->master_collection); } } else { @@ -1169,7 +1160,7 @@ static Collection *collection_from_index_recursive(Collection *collection, Collection *BKE_collection_from_index(Scene *scene, const int index) { int index_current = 0; - Collection *master_collection = BKE_collection_master(scene); + Collection *master_collection = scene->master_collection; return collection_from_index_recursive(master_collection, index, &index_current); } @@ -1363,7 +1354,7 @@ static void scene_collections_array(Scene *scene, Collection ***collections_arra return; } - collection = BKE_collection_master(scene); + collection = scene->master_collection; BLI_assert(collection != NULL); scene_collection_callback(collection, scene_collections_count, tot); diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index e1e4d138fd9..ccacb85651c 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -62,6 +62,7 @@ #include "BKE_deform.h" #include "BKE_displist.h" #include "BKE_editmesh.h" +#include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_idprop.h" #include "BKE_library.h" @@ -1808,18 +1809,25 @@ static void rotlike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar copy_v3_v3(loc, cob->matrix[3]); mat4_to_size(size, cob->matrix); + /* Select the Euler rotation order, defaulting to the owner. */ + short rot_order = cob->rotOrder; + + if (data->euler_order != CONSTRAINT_EULER_AUTO) { + rot_order = data->euler_order; + } + /* To allow compatible rotations, must get both rotations in the order of the owner... */ - mat4_to_eulO(obeul, cob->rotOrder, cob->matrix); + mat4_to_eulO(obeul, rot_order, cob->matrix); /* We must get compatible eulers from the beginning because * some of them can be modified below (see bug T21875). */ - mat4_to_compatible_eulO(eul, obeul, cob->rotOrder, ct->matrix); + mat4_to_compatible_eulO(eul, obeul, rot_order, ct->matrix); if ((data->flag & ROTLIKE_X) == 0) { eul[0] = obeul[0]; } else { if (data->flag & ROTLIKE_OFFSET) { - rotate_eulO(eul, cob->rotOrder, 'X', obeul[0]); + rotate_eulO(eul, rot_order, 'X', obeul[0]); } if (data->flag & ROTLIKE_X_INVERT) { @@ -1832,7 +1840,7 @@ static void rotlike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar } else { if (data->flag & ROTLIKE_OFFSET) { - rotate_eulO(eul, cob->rotOrder, 'Y', obeul[1]); + rotate_eulO(eul, rot_order, 'Y', obeul[1]); } if (data->flag & ROTLIKE_Y_INVERT) { @@ -1845,7 +1853,7 @@ static void rotlike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar } else { if (data->flag & ROTLIKE_OFFSET) { - rotate_eulO(eul, cob->rotOrder, 'Z', obeul[2]); + rotate_eulO(eul, rot_order, 'Z', obeul[2]); } if (data->flag & ROTLIKE_Z_INVERT) { @@ -1856,7 +1864,7 @@ static void rotlike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar /* Good to make eulers compatible again, * since we don't know how much they were changed above. */ compatible_eul(eul, obeul); - loc_eulO_size_to_mat4(cob->matrix, loc, eul, size, cob->rotOrder); + loc_eulO_size_to_mat4(cob->matrix, loc, eul, size, rot_order); } } @@ -1927,9 +1935,39 @@ static void sizelike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *ta if (VALID_CONS_TARGET(ct)) { float obsize[3], size[3]; - mat4_to_size(size, ct->matrix); mat4_to_size(obsize, cob->matrix); + /* Compute one uniform scale factor to apply to all three axes. */ + if (data->flag & SIZELIKE_UNIFORM) { + const int all_axes = SIZELIKE_X | SIZELIKE_Y | SIZELIKE_Z; + float total = 1.0f; + + /* If all axes are selected, use the determinant. */ + if ((data->flag & all_axes) == all_axes) { + total = fabsf(mat4_to_volume_scale(ct->matrix)); + } + /* Otherwise multiply individual values. */ + else { + mat4_to_size(size, ct->matrix); + + if (data->flag & SIZELIKE_X) { + total *= size[0]; + } + if (data->flag & SIZELIKE_Y) { + total *= size[1]; + } + if (data->flag & SIZELIKE_Z) { + total *= size[2]; + } + } + + copy_v3_fl(size, cbrt(total)); + } + /* Regular per-axis scaling. */ + else { + mat4_to_size(size, ct->matrix); + } + for (int i = 0; i < 3; i++) { size[i] = powf(size[i], data->power); } @@ -1948,13 +1986,13 @@ static void sizelike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *ta } } - if ((data->flag & SIZELIKE_X) && (obsize[0] != 0)) { + if ((data->flag & (SIZELIKE_X | SIZELIKE_UNIFORM)) && (obsize[0] != 0)) { mul_v3_fl(cob->matrix[0], size[0] / obsize[0]); } - if ((data->flag & SIZELIKE_Y) && (obsize[1] != 0)) { + if ((data->flag & (SIZELIKE_Y | SIZELIKE_UNIFORM)) && (obsize[1] != 0)) { mul_v3_fl(cob->matrix[1], size[1] / obsize[1]); } - if ((data->flag & SIZELIKE_Z) && (obsize[2] != 0)) { + if ((data->flag & (SIZELIKE_Z | SIZELIKE_UNIFORM)) && (obsize[2] != 0)) { mul_v3_fl(cob->matrix[2], size[2] / obsize[2]); } } @@ -3689,7 +3727,8 @@ static void transform_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t if (VALID_CONS_TARGET(ct)) { float *from_min, *from_max, *to_min, *to_max; float loc[3], eul[3], size[3]; - float dvec[3], sval[3]; + float dbuf[4], sval[3]; + float *const dvec = dbuf + 1; int i; /* obtain target effect */ @@ -3708,7 +3747,8 @@ static void transform_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t from_max = data->from_max_scale; break; case TRANS_ROTATION: - mat4_to_eulO(dvec, cob->rotOrder, ct->matrix); + BKE_driver_target_matrix_to_rot_channels( + ct->matrix, cob->rotOrder, data->from_rotation_mode, -1, true, dbuf); from_min = data->from_min_rot; from_max = data->from_max_rot; break; @@ -3720,9 +3760,16 @@ static void transform_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t break; } + /* Select the output Euler rotation order, defaulting to the owner. */ + short rot_order = cob->rotOrder; + + if (data->to == TRANS_ROTATION && data->to_euler_order != CONSTRAINT_EULER_AUTO) { + rot_order = data->to_euler_order; + } + /* extract components of owner's matrix */ copy_v3_v3(loc, cob->matrix[3]); - mat4_to_eulO(eul, cob->rotOrder, cob->matrix); + mat4_to_eulO(eul, rot_order, cob->matrix); mat4_to_size(size, cob->matrix); /* determine where in range current transforms lie */ @@ -3781,7 +3828,7 @@ static void transform_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t } /* apply to matrix */ - loc_eulO_size_to_mat4(cob->matrix, loc, eul, size, cob->rotOrder); + loc_eulO_size_to_mat4(cob->matrix, loc, eul, size, rot_order); } } diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index f536f21c3e5..bcf6bb338ff 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -1053,7 +1053,7 @@ Collection *CTX_data_collection(const bContext *C) /* fallback */ Scene *scene = CTX_data_scene(C); - return BKE_collection_master(scene); + return scene->master_collection; } enum eContextObjectMode CTX_data_mode_enum_ex(const Object *obedit, diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c index 09bbc6c0d13..fcbebd24b4a 100644 --- a/source/blender/blenkernel/intern/crazyspace.c +++ b/source/blender/blenkernel/intern/crazyspace.c @@ -293,7 +293,7 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgra BLI_linklist_free((LinkNode *)datamasks, NULL); me = BKE_mesh_from_editmesh_with_coords_thin_wrap(em, &data_mask, NULL); - deformedVerts = editbmesh_get_vertex_cos(em, &numVerts); + deformedVerts = editbmesh_vert_coords_alloc(em, &numVerts); defmats = MEM_mallocN(sizeof(*defmats) * numVerts, "defmats"); for (a = 0; a < numVerts; a++) { @@ -383,7 +383,7 @@ int BKE_sculpt_get_first_deform_matrices(struct Depsgraph *depsgraph, * state. */ Mesh *me = object_eval.data; me_eval = BKE_mesh_copy_for_eval(me, true); - deformedVerts = BKE_mesh_vertexCos_get(me, &numVerts); + deformedVerts = BKE_mesh_vert_coords_alloc(me, &numVerts); defmats = MEM_callocN(sizeof(*defmats) * numVerts, "defmats"); for (a = 0; a < numVerts; a++) { @@ -485,7 +485,7 @@ void BKE_crazyspace_build_sculpt(struct Depsgraph *depsgraph, int a, numVerts; Mesh *mesh = (Mesh *)object->data; - *deformcos = BKE_mesh_vertexCos_get(mesh, &numVerts); + *deformcos = BKE_mesh_vert_coords_alloc(mesh, &numVerts); *deformmats = MEM_callocN(sizeof(*(*deformmats)) * numVerts, "defmats"); for (a = 0; a < numVerts; a++) { diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 980e8043a42..3112e1b5ed1 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -4606,18 +4606,13 @@ void BKE_nurb_direction_switch(Nurb *nu) } } -float (*BKE_curve_nurbs_vertexCos_get(ListBase *lb, int *r_numVerts))[3] +void BKE_curve_nurbs_vert_coords_get(ListBase *lb, float (*vert_coords)[3], int vert_len) { - int i, numVerts = *r_numVerts = BKE_nurbList_verts_count(lb); - float *co, (*cos)[3] = MEM_malloc_arrayN(numVerts, sizeof(*cos), "cu_vcos"); - Nurb *nu; - - co = cos[0]; - for (nu = lb->first; nu; nu = nu->next) { + float *co = vert_coords[0]; + for (Nurb *nu = lb->first; nu; nu = nu->next) { if (nu->type == CU_BEZIER) { BezTriple *bezt = nu->bezt; - - for (i = 0; i < nu->pntsu; i++, bezt++) { + for (int i = 0; i < nu->pntsu; i++, bezt++) { copy_v3_v3(co, bezt->vec[0]); co += 3; copy_v3_v3(co, bezt->vec[1]); @@ -4628,20 +4623,31 @@ float (*BKE_curve_nurbs_vertexCos_get(ListBase *lb, int *r_numVerts))[3] } else { BPoint *bp = nu->bp; - - for (i = 0; i < nu->pntsu * nu->pntsv; i++, bp++) { + for (int i = 0; i < nu->pntsu * nu->pntsv; i++, bp++) { copy_v3_v3(co, bp->vec); co += 3; } } } + BLI_assert(co == vert_coords[vert_len]); + UNUSED_VARS_NDEBUG(vert_len); +} - return cos; +float (*BKE_curve_nurbs_vert_coords_alloc(ListBase *lb, int *r_vert_len))[3] +{ + const int vert_len = BKE_nurbList_verts_count(lb); + float(*vert_coords)[3] = MEM_malloc_arrayN(vert_len, sizeof(*vert_coords), __func__); + BKE_curve_nurbs_vert_coords_get(lb, vert_coords, vert_len); + *r_vert_len = vert_len; + return vert_coords; } -void BK_curve_nurbs_vertexCos_apply(ListBase *lb, float (*vertexCos)[3]) +void BKE_curve_nurbs_vert_coords_apply_with_mat4(ListBase *lb, + const float (*vert_coords)[3], + const float mat[4][4], + const bool constrain_2d) { - const float *co = vertexCos[0]; + const float *co = vert_coords[0]; Nurb *nu; int i; @@ -4650,6 +4656,44 @@ void BK_curve_nurbs_vertexCos_apply(ListBase *lb, float (*vertexCos)[3]) BezTriple *bezt = nu->bezt; for (i = 0; i < nu->pntsu; i++, bezt++) { + mul_v3_m4v3(bezt->vec[0], mat, co); + co += 3; + mul_v3_m4v3(bezt->vec[1], mat, co); + co += 3; + mul_v3_m4v3(bezt->vec[2], mat, co); + co += 3; + } + } + else { + BPoint *bp = nu->bp; + + for (i = 0; i < nu->pntsu * nu->pntsv; i++, bp++) { + mul_v3_m4v3(bp->vec, mat, co); + co += 3; + } + } + + if (constrain_2d) { + if (nu->flag & CU_2D) { + BKE_nurb_test_2d(nu); + } + } + + calchandlesNurb_intern(nu, true); + } +} + +void BKE_curve_nurbs_vert_coords_apply(ListBase *lb, + const float (*vert_coords)[3], + const bool constrain_2d) +{ + const float *co = vert_coords[0]; + + for (Nurb *nu = lb->first; nu; nu = nu->next) { + if (nu->type == CU_BEZIER) { + BezTriple *bezt = nu->bezt; + + for (int i = 0; i < nu->pntsu; i++, bezt++) { copy_v3_v3(bezt->vec[0], co); co += 3; copy_v3_v3(bezt->vec[1], co); @@ -4661,28 +4705,33 @@ void BK_curve_nurbs_vertexCos_apply(ListBase *lb, float (*vertexCos)[3]) else { BPoint *bp = nu->bp; - for (i = 0; i < nu->pntsu * nu->pntsv; i++, bp++) { + for (int i = 0; i < nu->pntsu * nu->pntsv; i++, bp++) { copy_v3_v3(bp->vec, co); co += 3; } } + if (constrain_2d) { + if (nu->flag & CU_2D) { + BKE_nurb_test_2d(nu); + } + } + calchandlesNurb_intern(nu, true); } } -float (*BKE_curve_nurbs_keyVertexCos_get(ListBase *lb, float *key))[3] +float (*BKE_curve_nurbs_key_vert_coords_alloc(ListBase *lb, float *key, int *r_vert_len))[3] { - int i, numVerts = BKE_nurbList_verts_count(lb); - float *co, (*cos)[3] = MEM_malloc_arrayN(numVerts, sizeof(*cos), "cu_vcos"); - Nurb *nu; + int vert_len = BKE_nurbList_verts_count(lb); + float(*cos)[3] = MEM_malloc_arrayN(vert_len, sizeof(*cos), __func__); - co = cos[0]; - for (nu = lb->first; nu; nu = nu->next) { + float *co = cos[0]; + for (Nurb *nu = lb->first; nu; nu = nu->next) { if (nu->type == CU_BEZIER) { BezTriple *bezt = nu->bezt; - for (i = 0; i < nu->pntsu; i++, bezt++) { + for (int i = 0; i < nu->pntsu; i++, bezt++) { copy_v3_v3(co, &key[0]); co += 3; copy_v3_v3(co, &key[3]); @@ -4695,18 +4744,18 @@ float (*BKE_curve_nurbs_keyVertexCos_get(ListBase *lb, float *key))[3] else { BPoint *bp = nu->bp; - for (i = 0; i < nu->pntsu * nu->pntsv; i++, bp++) { + for (int i = 0; i < nu->pntsu * nu->pntsv; i++, bp++) { copy_v3_v3(co, key); co += 3; key += KEYELEM_FLOAT_LEN_BPOINT; } } } - + *r_vert_len = vert_len; return cos; } -void BKE_curve_nurbs_keyVertexTilts_apply(ListBase *lb, float *key) +void BKE_curve_nurbs_key_vert_tilts_apply(ListBase *lb, float *key) { Nurb *nu; int i; diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 770d8662743..bc982140b29 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -294,7 +294,7 @@ static void layerInterp_mdeformvert(const void **sources, } } - /* delay writing to the destination incase dest is in sources */ + /* Delay writing to the destination in case dest is in sources. */ /* now we know how many unique deform weights there are, so realloc */ if (dvert->dw && (dvert->totweight == totweight)) { @@ -441,7 +441,7 @@ static void layerInterp_tface( } } - /* delay writing to the destination incase dest is in sources */ + /* Delay writing to the destination in case dest is in sources. */ *tf = *(MTFace *)(*sources); memcpy(tf->uv, uv, sizeof(tf->uv)); } @@ -548,7 +548,7 @@ static void layerInterp_origspace_face( } } - /* delay writing to the destination in case dest is in sources */ + /* Delay writing to the destination in case dest is in sources. */ memcpy(osf->uv, uv, sizeof(osf->uv)); } @@ -908,7 +908,7 @@ static void layerInterp_mloopcol( /* Subdivide smooth or fractal can cause problems without clamping * although weights should also not cause this situation */ - /* also delay writing to the destination incase dest is in sources */ + /* Also delay writing to the destination in case dest is in sources. */ mc->r = round_fl_to_uchar_clamp(col.r); mc->g = round_fl_to_uchar_clamp(col.g); mc->b = round_fl_to_uchar_clamp(col.b); @@ -1008,7 +1008,7 @@ static void layerInterp_mloopuv( } } - /* delay writing to the destination incase dest is in sources */ + /* Delay writing to the destination in case dest is in sources. */ copy_v2_v2(((MLoopUV *)dest)->uv, uv); ((MLoopUV *)dest)->flag = flag; } @@ -1104,7 +1104,7 @@ static void layerInterp_mloop_origspace( } } - /* delay writing to the destination incase dest is in sources */ + /* Delay writing to the destination in case dest is in sources. */ copy_v2_v2(((OrigSpaceLoop *)dest)->uv, uv); } /* --- end copy */ @@ -1152,7 +1152,7 @@ static void layerInterp_mcol( } } - /* delay writing to the destination incase dest is in sources */ + /* Delay writing to the destination in case dest is in sources. */ for (j = 0; j < 4; ++j) { /* Subdivide smooth or fractal can cause problems without clamping @@ -1220,7 +1220,7 @@ static void layerInterp_bweight(const void **sources, } } - /* delay writing to the destination incase dest is in sources */ + /* Delay writing to the destination in case dest is in sources. */ *((float *)dest) = f; } @@ -1251,7 +1251,7 @@ static void layerInterp_shapekey(const void **sources, } } - /* delay writing to the destination incase dest is in sources */ + /* Delay writing to the destination in case dest is in sources. */ copy_v3_v3((float *)dest, co); } @@ -1289,7 +1289,7 @@ static void layerInterp_mvert_skin(const void **sources, madd_v3_v3fl(radius, vs_src->radius, w); } - /* delay writing to the destination incase dest is in sources */ + /* Delay writing to the destination in case dest is in sources. */ vs_dst = dest; copy_v3_v3(vs_dst->radius, radius); vs_dst->flag &= ~MVERT_SKIN_ROOT; @@ -2828,9 +2828,7 @@ void CustomData_interp(const CustomData *source, const void *source_buf[SOURCE_BUF_SIZE]; const void **sources = source_buf; - /* slow fallback in case we're interpolating a ridiculous number of - * elements - */ + /* Slow fallback in case we're interpolating a ridiculous number of elements. */ if (count > SOURCE_BUF_SIZE) { sources = MEM_malloc_arrayN(count, sizeof(*sources), __func__); } @@ -3828,9 +3826,7 @@ void CustomData_bmesh_interp(CustomData *data, void *source_buf[SOURCE_BUF_SIZE]; const void **sources = (const void **)source_buf; - /* slow fallback in case we're interpolating a ridiculous number of - * elements - */ + /* Slow fallback in case we're interpolating a ridiculous number of elements. */ if (count > SOURCE_BUF_SIZE) { sources = MEM_malloc_arrayN(count, sizeof(*sources), __func__); } @@ -4185,7 +4181,7 @@ bool CustomData_verify_versions(struct CustomData *data, int index) if (!typeInfo->defaultname && (index > 0) && data->layers[index - 1].type == layer->type) { keeplayer = false; /* multiple layers of which we only support one */ } - /* This is a pre-emptive fix for cases that should not happen + /* This is a preemptive fix for cases that should not happen * (layers that should not be written in .blend files), * but can happen due to bugs (see e.g. T62318). * Also for forward compatibility, in future, diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 83a10344b96..cbd3c91acc7 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -892,8 +892,7 @@ static void curve_calc_modifiers_pre( * tilts, which is passed through in the modifier stack. * this is also the reason curves do not use a virtual * shape key modifier yet. */ - deformedVerts = BKE_curve_nurbs_keyVertexCos_get(nurb, keyVerts); - numVerts = BKE_nurbList_verts_count(nurb); + deformedVerts = BKE_curve_nurbs_key_vert_coords_alloc(nurb, keyVerts, &numVerts); } } @@ -909,7 +908,7 @@ static void curve_calc_modifiers_pre( } if (!deformedVerts) { - deformedVerts = BKE_curve_nurbs_vertexCos_get(nurb, &numVerts); + deformedVerts = BKE_curve_nurbs_vert_coords_alloc(nurb, &numVerts); } mti->deformVerts(md, &mectx, NULL, deformedVerts, numVerts); @@ -921,11 +920,11 @@ static void curve_calc_modifiers_pre( } if (deformedVerts) { - BK_curve_nurbs_vertexCos_apply(nurb, deformedVerts); + BKE_curve_nurbs_vert_coords_apply(nurb, deformedVerts, false); MEM_freeN(deformedVerts); } if (keyVerts) { /* these are not passed through modifier stack */ - BKE_curve_nurbs_keyVertexTilts_apply(nurb, keyVerts); + BKE_curve_nurbs_key_vert_tilts_apply(nurb, keyVerts); } if (keyVerts) { @@ -933,18 +932,18 @@ static void curve_calc_modifiers_pre( } } -static float (*displist_get_allverts(ListBase *dispbase, int *totvert))[3] +static float (*displist_vert_coords_alloc(ListBase *dispbase, int *r_vert_len))[3] { DispList *dl; float(*allverts)[3], *fp; - *totvert = 0; + *r_vert_len = 0; for (dl = dispbase->first; dl; dl = dl->next) { - *totvert += (dl->type == DL_INDEX3) ? dl->nr : dl->parts * dl->nr; + *r_vert_len += (dl->type == DL_INDEX3) ? dl->nr : dl->parts * dl->nr; } - allverts = MEM_mallocN((*totvert) * sizeof(float) * 3, "displist_get_allverts allverts"); + allverts = MEM_mallocN((*r_vert_len) * sizeof(float) * 3, "displist_vert_coords_alloc allverts"); fp = (float *)allverts; for (dl = dispbase->first; dl; dl = dl->next) { int offs = 3 * ((dl->type == DL_INDEX3) ? dl->nr : dl->parts * dl->nr); @@ -955,7 +954,7 @@ static float (*displist_get_allverts(ListBase *dispbase, int *totvert))[3] return allverts; } -static void displist_apply_allverts(ListBase *dispbase, float (*allverts)[3]) +static void displist_vert_coords_apply(ListBase *dispbase, float (*allverts)[3]) { DispList *dl; const float *fp; @@ -1027,7 +1026,7 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph, * we need to create a Mesh for each curve that uses modifiers. */ if (modified == NULL /* && need_normal */) { if (vertCos != NULL) { - displist_apply_allverts(dispbase, vertCos); + displist_vert_coords_apply(dispbase, vertCos); } if (ELEM(ob->type, OB_CURVE, OB_FONT) && (cu->flag & CU_DEFORM_FILL)) { @@ -1041,7 +1040,7 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph, (mti->type == eModifierTypeType_DeformOrConstruct && !modified)) { if (modified) { if (!vertCos) { - vertCos = BKE_mesh_vertexCos_get(modified, &totvert); + vertCos = BKE_mesh_vert_coords_alloc(modified, &totvert); } if (need_normal) { BKE_mesh_ensure_normals(modified); @@ -1050,7 +1049,7 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph, } else { if (!vertCos) { - vertCos = displist_get_allverts(dispbase, &totvert); + vertCos = displist_vert_coords_alloc(dispbase, &totvert); } mti->deformVerts(md, &mectx_deform, NULL, vertCos, totvert); } @@ -1071,12 +1070,12 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph, BKE_id_free(NULL, modified); modified = temp_mesh; - BKE_mesh_apply_vert_coords(modified, vertCos); + BKE_mesh_vert_coords_apply(modified, vertCos); } } else { if (vertCos) { - displist_apply_allverts(dispbase, vertCos); + displist_vert_coords_apply(dispbase, vertCos); } if (ELEM(ob->type, OB_CURVE, OB_FONT) && (cu->flag & CU_DEFORM_FILL)) { @@ -1115,13 +1114,13 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph, BKE_id_free(NULL, modified); modified = temp_mesh; - BKE_mesh_apply_vert_coords(modified, vertCos); + BKE_mesh_vert_coords_apply(modified, vertCos); BKE_mesh_calc_normals_mapping_simple(modified); MEM_freeN(vertCos); } else { - displist_apply_allverts(dispbase, vertCos); + displist_vert_coords_apply(dispbase, vertCos); MEM_freeN(vertCos); vertCos = NULL; } @@ -1129,15 +1128,6 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph, if (r_final) { if (modified) { - /* see: mesh_calc_modifiers */ - if (modified->totface == 0) { - BKE_mesh_tessface_calc(modified); - } - /* Even if tessellation is not needed, some modifiers might have modified CD layers - * (like mloopcol or mloopuv), hence we have to update those. */ - else if (modified->runtime.cd_dirty_vert & CD_MASK_TESSLOOPNORMAL) { - BKE_mesh_tessface_calc(modified); - } /* XXX2.8(Sybren): make sure the face normals are recalculated as well */ BKE_mesh_ensure_normals(modified); diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 04cbdbb6bcd..91b169590ac 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -2755,7 +2755,7 @@ static bool dynamicPaint_symmetrizeAdjData(PaintAdjData *ed, int active_points) for (int i = 0, idx = ed->n_index[index]; i < ed->n_num[index]; i++) { const int target = ed->n_target[idx + i]; - assert(!(ed->flags[target] & ADJ_BORDER_PIXEL)); + BLI_assert(!(ed->flags[target] & ADJ_BORDER_PIXEL)); if (!dynamicPaint_pointHasNeighbor(ed, target, index)) { new_n_num[target]++; @@ -2782,7 +2782,7 @@ static bool dynamicPaint_symmetrizeAdjData(PaintAdjData *ed, int active_points) new_n_num[index] = ed->n_num[index]; } - assert(n_pos == total_targets); + BLI_assert(n_pos == total_targets); /* Add symmetrized - this loop behavior must exactly match the count pass above */ for (int index = 0; index < active_points; index++) { @@ -5572,7 +5572,7 @@ static void dynamic_paint_border_cb(void *__restrict userdata, PaintPoint *pPoint2 = &((PaintPoint *)sData->type_data)[target]; - assert(!(sData->adj_data->flags[target] & ADJ_BORDER_PIXEL)); + BLI_assert(!(sData->adj_data->flags[target] & ADJ_BORDER_PIXEL)); madd_v3_v3fl(mix_color, pPoint2->color, pPoint2->color[3]); mix_color[3] += pPoint2->color[3]; diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c index 06f297b23e0..2df3d2f0fe9 100644 --- a/source/blender/blenkernel/intern/editderivedmesh.c +++ b/source/blender/blenkernel/intern/editderivedmesh.c @@ -517,8 +517,8 @@ static void cage_mapped_verts_callback(void *userData, } } -float (*BKE_editmesh_vertexCos_get( - struct Depsgraph *depsgraph, BMEditMesh *em, Scene *scene, int *r_numVerts))[3] +float (*BKE_editmesh_vert_coords_alloc( + struct Depsgraph *depsgraph, BMEditMesh *em, Scene *scene, int *r_vert_len))[3] { Mesh *cage; BLI_bitmap *visit_bitmap; @@ -540,8 +540,8 @@ float (*BKE_editmesh_vertexCos_get( MEM_freeN(visit_bitmap); - if (r_numVerts) { - *r_numVerts = em->bm->totvert; + if (r_vert_len) { + *r_vert_len = em->bm->totvert; } return cos_cage; diff --git a/source/blender/blenkernel/intern/editmesh.c b/source/blender/blenkernel/intern/editmesh.c index b8234ccc5bb..866c494d354 100644 --- a/source/blender/blenkernel/intern/editmesh.c +++ b/source/blender/blenkernel/intern/editmesh.c @@ -39,7 +39,7 @@ BMEditMesh *BKE_editmesh_create(BMesh *bm, const bool do_tessellate) em->bm = bm; if (do_tessellate) { - BKE_editmesh_tessface_calc(em); + BKE_editmesh_looptri_calc(em); } return em; @@ -61,11 +61,10 @@ BMEditMesh *BKE_editmesh_copy(BMEditMesh *em) /* The tessellation is NOT calculated on the copy here, * because currently all the callers of this function use - * it to make a backup copy of the BMEditMesh to restore - * it in the case of errors in an operation. For perf - * reasons, in that case it makes more sense to do the - * tessellation only when/if that copy ends up getting - * used.*/ + * it to make a backup copy of the #BMEditMesh to restore + * it in the case of errors in an operation. For performance reasons, + * in that case it makes more sense to do the + * tessellation only when/if that copy ends up getting used. */ em_copy->looptris = NULL; return em_copy; @@ -97,8 +96,8 @@ static void editmesh_tessface_calc_intern(BMEditMesh *em) BMesh *bm = em->bm; - /* this assumes all faces can be scan-filled, which isn't always true, - * worst case we over alloc a little which is acceptable */ + /* This assumes all faces can be scan-filled, which isn't always true, + * worst case we over allocate a little which is acceptable. */ const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop); const int looptris_tot_prev_alloc = em->looptris ? (MEM_allocN_len(em->looptris) / sizeof(*em->looptris)) : @@ -109,7 +108,7 @@ static void editmesh_tessface_calc_intern(BMEditMesh *em) /* this means no reallocs for quad dominant models, for */ if ((em->looptris != NULL) && /* (*em->tottri >= looptris_tot)) */ - /* check against alloc'd size incase we over alloc'd a little */ + /* Check against allocated size in case we over allocated a little. */ ((looptris_tot_prev_alloc >= looptris_tot) && (looptris_tot_prev_alloc <= looptris_tot * 2))) { looptris = em->looptris; @@ -127,7 +126,7 @@ static void editmesh_tessface_calc_intern(BMEditMesh *em) BM_mesh_calc_tessellation(em->bm, em->looptris, &em->tottri); } -void BKE_editmesh_tessface_calc(BMEditMesh *em) +void BKE_editmesh_looptri_calc(BMEditMesh *em) { editmesh_tessface_calc_intern(em); @@ -210,7 +209,7 @@ void BKE_editmesh_color_ensure(BMEditMesh *em, const char htype) } } -float (*BKE_editmesh_vertexCos_get_orco(BMEditMesh *em, int *r_numVerts))[3] +float (*BKE_editmesh_vert_coords_alloc_orco(BMEditMesh *em, int *r_vert_len))[3] { BMIter iter; BMVert *eve; @@ -223,7 +222,7 @@ float (*BKE_editmesh_vertexCos_get_orco(BMEditMesh *em, int *r_numVerts))[3] copy_v3_v3(orco[i], eve->co); } - *r_numVerts = em->bm->totvert; + *r_vert_len = em->bm->totvert; return orco; } diff --git a/source/blender/blenkernel/intern/editmesh_bvh.c b/source/blender/blenkernel/intern/editmesh_bvh.c index f23276d7be0..5af4e4c0023 100644 --- a/source/blender/blenkernel/intern/editmesh_bvh.c +++ b/source/blender/blenkernel/intern/editmesh_bvh.c @@ -73,7 +73,7 @@ BMBVHTree *BKE_bmbvh_new_ex(BMesh *bm, BMFace *f_test, *f_test_prev; bool test_fn_ret; - /* BKE_editmesh_tessface_calc() must be called already */ + /* BKE_editmesh_looptri_calc() must be called already */ BLI_assert(looptris_tot != 0 || bm->totface == 0); if (cos_cage) { diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 9580ea763fb..b596eeb9e35 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -382,8 +382,8 @@ FCurve *rna_get_fcurve_context_ui(bContext *C, } /* there must be some RNA-pointer + property combon */ - if (prop && tptr.id.data && RNA_property_animateable(&tptr, prop)) { - AnimData *adt = BKE_animdata_from_id(tptr.id.data); + if (prop && tptr.owner_id && RNA_property_animateable(&tptr, prop)) { + AnimData *adt = BKE_animdata_from_id(tptr.owner_id); int step = ( /* Always 1 in case we have no context (can't check in 'ancestors' of given RNA ptr). */ C ? 2 : 1); @@ -391,7 +391,7 @@ FCurve *rna_get_fcurve_context_ui(bContext *C, if (!adt && C) { path = BKE_animdata_driver_path_hack(C, &tptr, prop, NULL); - adt = BKE_animdata_from_id(tptr.id.data); + adt = BKE_animdata_from_id(tptr.owner_id); step--; } @@ -438,7 +438,7 @@ FCurve *rna_get_fcurve_context_ui(bContext *C, if (tpath && tpath != path) { MEM_freeN(path); path = tpath; - adt = BKE_animdata_from_id(tptr.id.data); + adt = BKE_animdata_from_id(tptr.owner_id); } else { adt = NULL; @@ -1714,7 +1714,10 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar) * of scale over all three axes unless the matrix includes shear. */ return cbrtf(mat4_to_volume_scale(mat)); } - else if (dtar->transChan >= DTAR_TRANSCHAN_SCALEX) { + else if (ELEM(dtar->transChan, + DTAR_TRANSCHAN_SCALEX, + DTAR_TRANSCHAN_SCALEY, + DTAR_TRANSCHAN_SCALEZ)) { /* Extract scale, and choose the right axis, * inline 'mat4_to_size'. */ return len_v3(mat[dtar->transChan - DTAR_TRANSCHAN_SCALEX]); @@ -1728,15 +1731,25 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar) * b) [NOT USED] directly use the original values (no decomposition) * - only an option for "transform space", if quality is really bad with a) */ - float eul[3]; + float quat[4]; + int channel; - mat4_to_eulO(eul, rot_order, mat); + if (dtar->transChan == DTAR_TRANSCHAN_ROTW) { + channel = 0; + } + else { + channel = 1 + dtar->transChan - DTAR_TRANSCHAN_ROTX; + BLI_assert(channel < 4); + } - if (use_eulers) { - compatible_eul(eul, oldEul); + BKE_driver_target_matrix_to_rot_channels( + mat, rot_order, dtar->rotation_mode, channel, false, quat); + + if (use_eulers && dtar->rotation_mode == DTAR_ROTMODE_AUTO) { + compatible_eul(quat + 1, oldEul); } - return eul[dtar->transChan - DTAR_TRANSCHAN_ROTX]; + return quat[channel]; } else { /* extract location and choose right axis */ @@ -1744,6 +1757,71 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar) } } +/* Convert a quaternion to pseudo-angles representing the weighted amount of rotation. */ +static void quaternion_to_angles(float quat[4], int channel) +{ + if (channel < 0) { + quat[0] = 2.0f * saacosf(quat[0]); + + for (int i = 1; i < 4; i++) { + quat[i] = 2.0f * saasinf(quat[i]); + } + } + else if (channel == 0) { + quat[0] = 2.0f * saacosf(quat[0]); + } + else { + quat[channel] = 2.0f * saasinf(quat[channel]); + } +} + +/* Compute channel values for a rotational Transform Channel driver variable. */ +void BKE_driver_target_matrix_to_rot_channels( + float mat[4][4], int auto_order, int rotation_mode, int channel, bool angles, float r_buf[4]) +{ + float *const quat = r_buf; + float *const eul = r_buf + 1; + + zero_v4(r_buf); + + if (rotation_mode == DTAR_ROTMODE_AUTO) { + mat4_to_eulO(eul, auto_order, mat); + } + else if (rotation_mode >= DTAR_ROTMODE_EULER_MIN && rotation_mode <= DTAR_ROTMODE_EULER_MAX) { + mat4_to_eulO(eul, rotation_mode, mat); + } + else if (rotation_mode == DTAR_ROTMODE_QUATERNION) { + mat4_to_quat(quat, mat); + + /* For Transformation constraint convenience, convert to pseudo-angles. */ + if (angles) { + quaternion_to_angles(quat, channel); + } + } + else if (rotation_mode >= DTAR_ROTMODE_SWING_TWIST_X && + rotation_mode <= DTAR_ROTMODE_SWING_TWIST_Z) { + int axis = rotation_mode - DTAR_ROTMODE_SWING_TWIST_X; + float raw_quat[4], twist; + + mat4_to_quat(raw_quat, mat); + + if (channel == axis + 1) { + /* If only the twist angle is needed, skip computing swing. */ + twist = quat_split_swing_and_twist(raw_quat, axis, NULL, NULL); + } + else { + twist = quat_split_swing_and_twist(raw_quat, axis, quat, NULL); + + quaternion_to_angles(quat, channel); + } + + quat[axis + 1] = twist; + } + else { + BLI_assert(false); + } +} + /* ......... */ /* Table of Driver Variable Type Info Data */ diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index 220584bac6a..a00be90297b 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -152,19 +152,19 @@ bool BKE_gpencil_free_strokes(bGPDframe *gpf) } /* Free strokes and colors belonging to a gp-frame */ -bool BKE_gpencil_free_frame_runtime_data(bGPDframe *derived_gpf) +bool BKE_gpencil_free_frame_runtime_data(bGPDframe *gpf_eval) { bGPDstroke *gps_next; - if (!derived_gpf) { + if (!gpf_eval) { return false; } /* free strokes */ - for (bGPDstroke *gps = derived_gpf->strokes.first; gps; gps = gps_next) { + for (bGPDstroke *gps = gpf_eval->strokes.first; gps; gps = gps_next) { gps_next = gps->next; BKE_gpencil_free_stroke(gps); } - BLI_listbase_clear(&derived_gpf->strokes); + BLI_listbase_clear(&gpf_eval->strokes); return true; } @@ -267,7 +267,8 @@ bGPDframe *BKE_gpencil_frame_addnew(bGPDlayer *gpl, int cframe) /* check whether frame was added successfully */ if (state == -1) { - CLOG_ERROR(&LOG, "Frame (%d) existed already for this layer. Using existing frame", cframe); + CLOG_ERROR( + &LOG, "Frame (%d) existed already for this layer_active. Using existing frame", cframe); /* free the newly created one, and use the old one instead */ MEM_freeN(gpf); @@ -1040,6 +1041,37 @@ void BKE_gpencil_layer_setactive(bGPdata *gpd, bGPDlayer *active) } } +/* Set locked layers for autolock mode. */ +void BKE_gpencil_layer_autolock_set(bGPdata *gpd) +{ + BLI_assert(gpd != NULL); + + bGPDlayer *gpl; + + if (gpd->flag & GP_DATA_AUTOLOCK_LAYERS) { + bGPDlayer *layer_active = BKE_gpencil_layer_getactive(gpd); + + /* Lock all other layers */ + for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { + /* unlock active layer */ + if (gpl == layer_active) { + gpl->flag &= ~GP_LAYER_LOCKED; + } + else { + gpl->flag |= GP_LAYER_LOCKED; + } + } + } + else { + /* If disable is better unlock all layers by default or it looks there is + * a problem in the UI because the user expects all layers will be unlocked + */ + for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { + gpl->flag &= ~GP_LAYER_LOCKED; + } + } +} + /* delete the active gp-layer */ void BKE_gpencil_layer_delete(bGPdata *gpd, bGPDlayer *gpl) { @@ -1190,38 +1222,34 @@ Material *BKE_gpencil_object_material_ensure_from_active_input_brush(Main *bmain brush->gpencil_settings->flag &= ~GP_BRUSH_MATERIAL_PINNED; } } - return BKE_gpencil_object_material_ensure_from_active_input_material(bmain, ob); + return BKE_gpencil_object_material_ensure_from_active_input_material(ob); } /** * Guaranteed to return a material assigned to object. Returns never NULL. * Only use this for materials unrelated to user input. */ -Material *BKE_gpencil_object_material_ensure_from_active_input_material(Main *bmain, Object *ob) +Material *BKE_gpencil_object_material_ensure_from_active_input_material(Object *ob) { Material *ma = give_current_material(ob, ob->actcol); if (ma) { return ma; } - /* If the slot is empty, remove because will be added again, - * if not, we will get an empty slot. */ - if ((ob->totcol > 0) && (ob->actcol == ob->totcol)) { - BKE_object_material_slot_remove(bmain, ob); - } - return BKE_gpencil_object_material_new(bmain, ob, "Material", NULL); + + return &defgpencil_material; } /* Get active color, and add all default settings if we don't find anything */ -Material *BKE_gpencil_object_material_ensure_active(Main *bmain, Object *ob) +Material *BKE_gpencil_object_material_ensure_active(Object *ob) { Material *ma = NULL; /* sanity checks */ - if (ELEM(NULL, bmain, ob)) { + if (ob == NULL) { return NULL; } - ma = BKE_gpencil_object_material_ensure_from_active_input_material(bmain, ob); + ma = BKE_gpencil_object_material_ensure_from_active_input_material(ob); if (ma->gp_style == NULL) { BKE_material_init_gpencil_settings(ma); } @@ -2048,33 +2076,55 @@ bool BKE_gpencil_smooth_stroke_strength(bGPDstroke *gps, int point_index, float bGPDspoint *ptb = &gps->points[point_index]; /* Do nothing if not enough points */ - if (gps->totpoints <= 2) { + if ((gps->totpoints <= 2) || (point_index < 1)) { return false; } + /* Only affect endpoints by a fraction of the normal influence */ + float inf = influence; + if ((point_index == 0) || (point_index == gps->totpoints - 1)) { + inf *= 0.01f; + } + /* Limit max influence to reduce pop effect. */ + CLAMP_MAX(inf, 0.98f); - /* Compute theoretical optimal value using distances */ - bGPDspoint *pta, *ptc; - int before = point_index - 1; - int after = point_index + 1; + float total = 0.0f; + float max_strength = 0.0f; + const int steps = 4; + const float average_fac = 1.0f / (float)(steps * 2 + 1); + int step; - CLAMP_MIN(before, 0); - CLAMP_MAX(after, gps->totpoints - 1); + /* add the point itself */ + total += ptb->strength * average_fac; + max_strength = ptb->strength; - pta = &gps->points[before]; - ptc = &gps->points[after]; + /* n-steps before/after current point */ + for (step = 1; step <= steps; step++) { + bGPDspoint *pt1, *pt2; + int before = point_index - step; + int after = point_index + step; - /* the optimal value is the corresponding to the interpolation of the strength - * at the distance of point b - */ - float fac = line_point_factor_v3(&ptb->x, &pta->x, &ptc->x); - /* sometimes the factor can be wrong due stroke geometry, so use middle point */ - if ((fac < 0.0f) || (fac > 1.0f)) { - fac = 0.5f; + CLAMP_MIN(before, 0); + CLAMP_MAX(after, gps->totpoints - 1); + + pt1 = &gps->points[before]; + pt2 = &gps->points[after]; + + /* add both these points to the average-sum (s += p[i]/n) */ + total += pt1->strength * average_fac; + total += pt2->strength * average_fac; + /* Save max value. */ + if (max_strength < pt1->strength) { + max_strength = pt1->strength; + } + if (max_strength < pt2->strength) { + max_strength = pt2->strength; + } } - const float optimal = (1.0f - fac) * pta->strength + fac * ptc->strength; - /* Based on influence factor, blend between original and optimal */ - ptb->strength = (1.0f - influence) * ptb->strength + influence * optimal; + /* Based on influence factor, blend between original and optimal smoothed value. */ + ptb->strength = interpf(ptb->strength, total, inf); + /* Clamp to maximum stroke strength to avoid weird results. */ + CLAMP_MAX(ptb->strength, max_strength); return true; } @@ -2089,31 +2139,52 @@ bool BKE_gpencil_smooth_stroke_thickness(bGPDstroke *gps, int point_index, float if ((gps->totpoints <= 2) || (point_index < 1)) { return false; } + /* Only affect endpoints by a fraction of the normal influence */ + float inf = influence; + if ((point_index == 0) || (point_index == gps->totpoints - 1)) { + inf *= 0.01f; + } + /* Limit max influence to reduce pop effect. */ + CLAMP_MAX(inf, 0.98f); - /* Compute theoretical optimal value using distances */ - bGPDspoint *pta, *ptc; - int before = point_index - 1; - int after = point_index + 1; + float total = 0.0f; + float max_pressure = 0.0f; + const int steps = 4; + const float average_fac = 1.0f / (float)(steps * 2 + 1); + int step; - CLAMP_MIN(before, 0); - CLAMP_MAX(after, gps->totpoints - 1); + /* add the point itself */ + total += ptb->pressure * average_fac; + max_pressure = ptb->pressure; - pta = &gps->points[before]; - ptc = &gps->points[after]; + /* n-steps before/after current point */ + for (step = 1; step <= steps; step++) { + bGPDspoint *pt1, *pt2; + int before = point_index - step; + int after = point_index + step; - /* the optimal value is the corresponding to the interpolation of the pressure - * at the distance of point b - */ - float fac = line_point_factor_v3(&ptb->x, &pta->x, &ptc->x); - /* sometimes the factor can be wrong due stroke geometry, so use middle point */ - if ((fac < 0.0f) || (fac > 1.0f)) { - fac = 0.5f; - } - float optimal = interpf(ptc->pressure, pta->pressure, fac); + CLAMP_MIN(before, 0); + CLAMP_MAX(after, gps->totpoints - 1); - /* Based on influence factor, blend between original and optimal */ - ptb->pressure = interpf(optimal, ptb->pressure, influence); + pt1 = &gps->points[before]; + pt2 = &gps->points[after]; + + /* add both these points to the average-sum (s += p[i]/n) */ + total += pt1->pressure * average_fac; + total += pt2->pressure * average_fac; + /* Save max value. */ + if (max_pressure < pt1->pressure) { + max_pressure = pt1->pressure; + } + if (max_pressure < pt2->pressure) { + max_pressure = pt2->pressure; + } + } + /* Based on influence factor, blend between original and optimal smoothed value. */ + ptb->pressure = interpf(ptb->pressure, total, inf); + /* Clamp to maximum stroke thickness to avoid weird results. */ + CLAMP_MAX(ptb->pressure, max_pressure); return true; } @@ -2229,6 +2300,7 @@ void BKE_gpencil_material_index_reassign(bGPdata *gpd, int totcol, int index) /* reassign strokes */ if ((gps->mat_nr > index) || (gps->mat_nr > totcol - 1)) { gps->mat_nr--; + CLAMP_MIN(gps->mat_nr, 0); } } } @@ -3134,3 +3206,397 @@ void BKE_gpencil_merge_distance_stroke(bGPDframe *gpf, BKE_gpencil_dissolve_points(gpf, gps, GP_SPOINT_TAG); } } + +/* Helper: Check materials with same color. */ +static int gpencil_check_same_material_color(Object *ob_gp, float color[4], Material **r_mat) +{ + Material *ma = NULL; + float color_cu[4]; + linearrgb_to_srgb_v3_v3(color_cu, color); + float hsv1[4]; + rgb_to_hsv_v(color_cu, hsv1); + hsv1[3] = color[3]; + + for (int i = 1; i <= ob_gp->totcol; i++) { + ma = give_current_material(ob_gp, i); + MaterialGPencilStyle *gp_style = ma->gp_style; + /* Check color with small tolerance (better in HSV). */ + float hsv2[4]; + rgb_to_hsv_v(gp_style->fill_rgba, hsv2); + hsv2[3] = gp_style->fill_rgba[3]; + if ((gp_style->fill_style == GP_STYLE_FILL_STYLE_SOLID) && (compare_v4v4(hsv1, hsv2, 0.01f))) { + *r_mat = ma; + return i - 1; + } + } + + *r_mat = NULL; + return -1; +} + +/* Helper: Add gpencil material using curve material as base. */ +static Material *gpencil_add_from_curve_material(Main *bmain, + Object *ob_gp, + float cu_color[4], + const bool gpencil_lines, + const bool fill, + int *r_idx) +{ + Material *mat_gp = BKE_gpencil_object_material_new( + bmain, ob_gp, (fill) ? "Material" : "Unassigned", r_idx); + MaterialGPencilStyle *gp_style = mat_gp->gp_style; + + /* Stroke color. */ + if (gpencil_lines) { + ARRAY_SET_ITEMS(gp_style->stroke_rgba, 0.0f, 0.0f, 0.0f, 1.0f); + gp_style->flag |= GP_STYLE_STROKE_SHOW; + } + else { + linearrgb_to_srgb_v4(gp_style->stroke_rgba, cu_color); + gp_style->flag &= ~GP_STYLE_STROKE_SHOW; + } + + /* Fill color. */ + linearrgb_to_srgb_v4(gp_style->fill_rgba, cu_color); + /* Fill is false if the original curve hasn't material assigned, so enable it. */ + if (fill) { + gp_style->flag |= GP_STYLE_FILL_SHOW; + } + + /* Check at least one is enabled. */ + if (((gp_style->flag & GP_STYLE_STROKE_SHOW) == 0) && + ((gp_style->flag & GP_STYLE_FILL_SHOW) == 0)) { + gp_style->flag |= GP_STYLE_STROKE_SHOW; + } + + return mat_gp; +} + +/* Helper: Create new stroke section. */ +static void gpencil_add_new_points(bGPDstroke *gps, + float *coord_array, + float pressure, + int init, + int totpoints, + float init_co[3], + bool last) +{ + for (int i = 0; i < totpoints; i++) { + bGPDspoint *pt = &gps->points[i + init]; + copy_v3_v3(&pt->x, &coord_array[3 * i]); + /* Be sure the last point is not on top of the first point of the curve or + * the close of the stroke will produce glitches. */ + if ((last) && (i > 0) && (i == totpoints - 1)) { + float dist = len_v3v3(init_co, &pt->x); + if (dist < 0.1f) { + /* Interpolate between previous point and current to back slightly. */ + bGPDspoint *pt_prev = &gps->points[i + init - 1]; + interp_v3_v3v3(&pt->x, &pt_prev->x, &pt->x, 0.95f); + } + } + + pt->pressure = pressure; + pt->strength = 1.0f; + } +} + +/* Helper: Get the first collection that includes the object. */ +static Collection *gpencil_get_parent_collection(Scene *scene, Object *ob) +{ + Collection *mycol = NULL; + FOREACH_SCENE_COLLECTION_BEGIN (scene, collection) { + for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) { + if ((mycol == NULL) && (cob->ob == ob)) { + mycol = collection; + } + } + } + FOREACH_SCENE_COLLECTION_END; + + return mycol; +} + +/* Helper: Convert one spline to grease pencil stroke. */ +static void gpencil_convert_spline(Main *bmain, + Object *ob_gp, + Object *ob_cu, + const bool gpencil_lines, + const bool only_stroke, + bGPDframe *gpf, + Nurb *nu) +{ + Curve *cu = (Curve *)ob_cu->data; + bool cyclic = true; + + /* Create Stroke. */ + bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "bGPDstroke"); + gps->thickness = 1.0f; + gps->gradient_f = 1.0f; + ARRAY_SET_ITEMS(gps->gradient_s, 1.0f, 1.0f); + ARRAY_SET_ITEMS(gps->caps, GP_STROKE_CAP_ROUND, GP_STROKE_CAP_ROUND); + gps->inittime = 0.0f; + + /* Enable recalculation flag by default. */ + gps->flag |= GP_STROKE_RECALC_GEOMETRY; + gps->flag &= ~GP_STROKE_SELECT; + gps->flag |= GP_STROKE_3DSPACE; + + gps->mat_nr = 0; + /* Count total points + * The total of points must consider that last point of each segment is equal to the first + * point of next segment. + */ + int totpoints = 0; + int segments = 0; + int resolu = nu->resolu + 1; + segments = nu->pntsu; + if (((nu->flagu & CU_NURB_CYCLIC) == 0) || (nu->pntsu == 2)) { + segments--; + cyclic = false; + } + totpoints = (resolu * segments) - (segments - 1); + + /* Initialize triangle memory to dummy data. */ + gps->tot_triangles = 0; + gps->triangles = NULL; + + /* Materials + * Notice: The color of the material is the color of viewport and not the final shader color. + */ + Material *mat_gp = NULL; + bool fill = true; + /* Check if grease pencil has a material with same color.*/ + float color[4]; + if ((cu->mat) && (*cu->mat)) { + Material *mat_cu = *cu->mat; + copy_v4_v4(color, &mat_cu->r); + } + else { + /* Gray (unassigned from SVG add-on) */ + zero_v4(color); + add_v3_fl(color, 0.6f); + color[3] = 1.0f; + fill = false; + } + + /* Special case: If the color was created by the SVG add-on and the name contains '_stroke' and + * there is only one color, the stroke must not be closed, fill to false and use for + * stroke the fill color. + */ + bool do_stroke = false; + if (ob_cu->totcol == 1) { + Material *ma_stroke = give_current_material(ob_cu, 1); + if ((ma_stroke) && (strstr(ma_stroke->id.name, "_stroke") != NULL)) { + do_stroke = true; + } + } + + int r_idx = gpencil_check_same_material_color(ob_gp, color, &mat_gp); + if ((ob_cu->totcol > 0) && (r_idx < 0)) { + Material *mat_curve = give_current_material(ob_cu, 1); + mat_gp = gpencil_add_from_curve_material(bmain, ob_gp, color, gpencil_lines, fill, &r_idx); + + if ((mat_curve) && (mat_curve->gp_style != NULL)) { + MaterialGPencilStyle *gp_style_cur = mat_curve->gp_style; + MaterialGPencilStyle *gp_style_gp = mat_gp->gp_style; + + copy_v4_v4(gp_style_gp->mix_rgba, gp_style_cur->mix_rgba); + gp_style_gp->fill_style = gp_style_cur->fill_style; + gp_style_gp->mix_factor = gp_style_cur->mix_factor; + gp_style_gp->gradient_angle = gp_style_cur->gradient_angle; + } + + /* If object has more than 1 material, use second material for stroke color. */ + if ((!only_stroke) && (ob_cu->totcol > 1) && (give_current_material(ob_cu, 2))) { + mat_curve = give_current_material(ob_cu, 2); + linearrgb_to_srgb_v3_v3(mat_gp->gp_style->stroke_rgba, &mat_curve->r); + mat_gp->gp_style->stroke_rgba[3] = mat_curve->a; + } + else if ((only_stroke) || (do_stroke)) { + /* Also use the first color if the fill is none for stroke color. */ + if (ob_cu->totcol > 0) { + mat_curve = give_current_material(ob_cu, 1); + linearrgb_to_srgb_v3_v3(mat_gp->gp_style->stroke_rgba, &mat_curve->r); + mat_gp->gp_style->stroke_rgba[3] = mat_curve->a; + /* Set fill and stroke depending of curve type (3D or 2D). */ + if ((cu->flag & CU_3D) || ((cu->flag & (CU_FRONT | CU_BACK)) == 0)) { + mat_gp->gp_style->flag |= GP_STYLE_STROKE_SHOW; + mat_gp->gp_style->flag &= ~GP_STYLE_FILL_SHOW; + } + else { + mat_gp->gp_style->flag &= ~GP_STYLE_STROKE_SHOW; + mat_gp->gp_style->flag |= GP_STYLE_FILL_SHOW; + } + } + } + } + CLAMP_MIN(r_idx, 0); + + /* Assign material index to stroke. */ + gps->mat_nr = r_idx; + + /* Add stroke to frame.*/ + BLI_addtail(&gpf->strokes, gps); + + float *coord_array = NULL; + float init_co[3]; + + switch (nu->type) { + case CU_POLY: { + /* Allocate memory for storage points. */ + gps->totpoints = nu->pntsu; + gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); + /* Increase thickness for this type. */ + gps->thickness = 10.0f; + + /* Get all curve points */ + for (int s = 0; s < gps->totpoints; s++) { + BPoint *bp = &nu->bp[s]; + bGPDspoint *pt = &gps->points[s]; + copy_v3_v3(&pt->x, bp->vec); + pt->pressure = bp->radius; + pt->strength = 1.0f; + } + break; + } + case CU_BEZIER: { + /* Allocate memory for storage points. */ + gps->totpoints = totpoints; + gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); + + int init = 0; + resolu = nu->resolu + 1; + segments = nu->pntsu; + if (((nu->flagu & CU_NURB_CYCLIC) == 0) || (nu->pntsu == 2)) { + segments--; + } + /* Get all interpolated curve points of Beziert */ + for (int s = 0; s < segments; s++) { + int inext = (s + 1) % nu->pntsu; + BezTriple *prevbezt = &nu->bezt[s]; + BezTriple *bezt = &nu->bezt[inext]; + bool last = (bool)(s == segments - 1); + + coord_array = MEM_callocN((size_t)3 * resolu * sizeof(float), __func__); + + for (int j = 0; j < 3; j++) { + BKE_curve_forward_diff_bezier(prevbezt->vec[1][j], + prevbezt->vec[2][j], + bezt->vec[0][j], + bezt->vec[1][j], + coord_array + j, + resolu - 1, + 3 * sizeof(float)); + } + /* Save first point coordinates. */ + if (s == 0) { + copy_v3_v3(init_co, &coord_array[0]); + } + /* Add points to the stroke */ + gpencil_add_new_points(gps, coord_array, bezt->radius, init, resolu, init_co, last); + /* Free memory. */ + MEM_SAFE_FREE(coord_array); + + /* As the last point of segment is the first point of next segment, back one array + * element to avoid duplicated points on the same location. + */ + init += resolu - 1; + } + break; + } + case CU_NURBS: { + if (nu->pntsv == 1) { + + int nurb_points; + if (nu->flagu & CU_NURB_CYCLIC) { + resolu++; + nurb_points = nu->pntsu * resolu; + } + else { + nurb_points = (nu->pntsu - 1) * resolu; + } + /* Get all curve points. */ + coord_array = MEM_callocN(sizeof(float[3]) * nurb_points, __func__); + BKE_nurb_makeCurve(nu, coord_array, NULL, NULL, NULL, resolu, sizeof(float[3])); + + /* Allocate memory for storage points. */ + gps->totpoints = nurb_points - 1; + gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); + + /* Add points. */ + gpencil_add_new_points(gps, coord_array, 1.0f, 0, gps->totpoints, init_co, false); + + MEM_SAFE_FREE(coord_array); + } + break; + } + default: { + break; + } + } + /* Cyclic curve, close stroke. */ + if ((cyclic) && (!do_stroke)) { + BKE_gpencil_close_stroke(gps); + } +} + +/* Convert a curve object to grease pencil stroke. + * + * \param bmain: Main thread pointer + * \param scene: Original scene. + * \param ob_gp: Grease pencil object to add strokes. + * \param ob_cu: Curve to convert. + * \param gpencil_lines: Use lines for strokes. + * \param use_collections: Create layers using collection names. + * \param only_stroke: The material must be only stroke without fill. + */ +void BKE_gpencil_convert_curve(Main *bmain, + Scene *scene, + Object *ob_gp, + Object *ob_cu, + const bool gpencil_lines, + const bool use_collections, + const bool only_stroke) +{ + if (ELEM(NULL, ob_gp, ob_cu) || (ob_gp->type != OB_GPENCIL) || (ob_gp->data == NULL)) { + return; + } + + Curve *cu = (Curve *)ob_cu->data; + bGPdata *gpd = (bGPdata *)ob_gp->data; + bGPDlayer *gpl = NULL; + + /* If the curve is empty, cancel. */ + if (cu->nurb.first == NULL) { + return; + } + + /* Check if there is an active layer. */ + if (use_collections) { + Collection *collection = gpencil_get_parent_collection(scene, ob_cu); + if (collection != NULL) { + gpl = BLI_findstring(&gpd->layers, collection->id.name + 2, offsetof(bGPDlayer, info)); + if (gpl == NULL) { + gpl = BKE_gpencil_layer_addnew(gpd, collection->id.name + 2, true); + } + } + } + + if (gpl == NULL) { + gpl = BKE_gpencil_layer_getactive(gpd); + if (gpl == NULL) { + gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true); + } + } + + /* Check if there is an active frame and add if needed. */ + bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_ADD_COPY); + + /* Read all splines of the curve and create a stroke for each. */ + for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) { + gpencil_convert_spline(bmain, ob_gp, ob_cu, gpencil_lines, only_stroke, gpf, nu); + } + + /* Tag for recalculation */ + DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE); +} diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c index 36d2d6316f7..1750a389788 100644 --- a/source/blender/blenkernel/intern/gpencil_modifier.c +++ b/source/blender/blenkernel/intern/gpencil_modifier.c @@ -779,26 +779,28 @@ void BKE_gpencil_subdivide(bGPDstroke *gps, int level, int flag) } /* Copy frame but do not assign new memory */ -static void gpencil_copy_frame(Object *ob, bGPDframe *gpf, bGPDframe *derived_gpf) +static void gpencil_frame_copy_noalloc(Object *ob, bGPDframe *gpf, bGPDframe *gpf_eval) { - derived_gpf->prev = gpf->prev; - derived_gpf->next = gpf->next; - derived_gpf->framenum = gpf->framenum; - derived_gpf->flag = gpf->flag; - derived_gpf->key_type = gpf->key_type; - derived_gpf->runtime = gpf->runtime; - copy_m4_m4(derived_gpf->runtime.parent_obmat, gpf->runtime.parent_obmat); + gpf_eval->prev = gpf->prev; + gpf_eval->next = gpf->next; + gpf_eval->framenum = gpf->framenum; + gpf_eval->flag = gpf->flag; + gpf_eval->key_type = gpf->key_type; + gpf_eval->runtime = gpf->runtime; + copy_m4_m4(gpf_eval->runtime.parent_obmat, gpf->runtime.parent_obmat); /* copy strokes */ - BLI_listbase_clear(&derived_gpf->strokes); + BLI_listbase_clear(&gpf_eval->strokes); for (bGPDstroke *gps_src = gpf->strokes.first; gps_src; gps_src = gps_src->next) { /* make copy of source stroke */ bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps_src); /* copy color to temp fields to apply temporal changes in the stroke */ MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps_src->mat_nr + 1); - copy_v4_v4(gps_dst->runtime.tmp_stroke_rgba, gp_style->stroke_rgba); - copy_v4_v4(gps_dst->runtime.tmp_fill_rgba, gp_style->fill_rgba); + if (gp_style) { + copy_v4_v4(gps_dst->runtime.tmp_stroke_rgba, gp_style->stroke_rgba); + copy_v4_v4(gps_dst->runtime.tmp_fill_rgba, gp_style->fill_rgba); + } /* Save original pointers for using in edit and select operators. */ gps_dst->runtime.gps_orig = gps_src; @@ -808,25 +810,27 @@ static void gpencil_copy_frame(Object *ob, bGPDframe *gpf, bGPDframe *derived_gp pt_dst->runtime.idx_orig = i; } - BLI_addtail(&derived_gpf->strokes, gps_dst); + BLI_addtail(&gpf_eval->strokes, gps_dst); } } -/* Ensure there is a derived frame */ -static void gpencil_ensure_derived_frame( - int idx, Object *ob, bGPDlayer *gpl, bGPDframe *gpf, bGPDframe **derived_gpf) +/* Ensure there is a evaluated frame */ +static void gpencil_evaluated_frame_ensure(int idx, + Object *ob, + bGPDframe *gpf, + bGPDframe **gpf_eval) { - /* create derived frames array data or expand */ - bGPDframe *derived_frames = ob->runtime.derived_frames; - *derived_gpf = &derived_frames[idx]; + /* Create evaluated frames array data or expand. */ + bGPDframe *evaluated_frames = ob->runtime.gpencil_evaluated_frames; + *gpf_eval = &evaluated_frames[idx]; - /* if derived frame create a new one */ - if (*derived_gpf != NULL) { + /* If already exist a evaluated frame create a new one. */ + if (*gpf_eval != NULL) { /* first clear temp data */ - BKE_gpencil_free_frame_runtime_data(*derived_gpf); + BKE_gpencil_free_frame_runtime_data(*gpf_eval); } - /* copy data (do not assign new memory)*/ - gpencil_copy_frame(ob, gpf, *derived_gpf); + /* Copy data (do not assign new memory). */ + gpencil_frame_copy_noalloc(ob, gpf, *gpf_eval); } /* Calculate gpencil modifiers */ @@ -836,21 +840,22 @@ void BKE_gpencil_modifiers_calc(Depsgraph *depsgraph, Scene *scene, Object *ob) Object *ob_orig = DEG_get_original_object(ob); bGPdata *gpd = (bGPdata *)ob_orig->data; const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); - const bool simplify_modif = GP_SIMPLIFY_MODIF(scene, false); + const bool simplify_modif = GPENCIL_SIMPLIFY_MODIF(scene, false); const bool is_render = (bool)(DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); const bool time_remap = BKE_gpencil_has_time_modifiers(ob); int cfra_eval = (int)DEG_get_ctime(depsgraph); - /* Create array of derived frames equal to number of layers. */ - ob->runtime.tot_layers = BLI_listbase_count(&gpd->layers); - CLAMP_MIN(ob->runtime.tot_layers, 1); - if (ob->runtime.derived_frames == NULL) { - ob->runtime.derived_frames = MEM_callocN(sizeof(struct bGPDframe) * ob->runtime.tot_layers, - __func__); + /* Create array of evaluated frames equal to number of layers. */ + ob->runtime.gpencil_tot_layers = BLI_listbase_count(&gpd->layers); + CLAMP_MIN(ob->runtime.gpencil_tot_layers, 1); + if (ob->runtime.gpencil_evaluated_frames == NULL) { + ob->runtime.gpencil_evaluated_frames = MEM_callocN( + sizeof(struct bGPDframe) * ob->runtime.gpencil_tot_layers, __func__); } else { - ob->runtime.derived_frames = MEM_recallocN(ob->runtime.derived_frames, - sizeof(struct bGPDframe) * ob->runtime.tot_layers); + ob->runtime.gpencil_evaluated_frames = MEM_recallocN(ob->runtime.gpencil_evaluated_frames, + sizeof(struct bGPDframe) * + ob->runtime.gpencil_tot_layers); } /* Init general modifiers data. */ @@ -877,8 +882,8 @@ void BKE_gpencil_modifiers_calc(Depsgraph *depsgraph, Scene *scene, Object *ob) } /* Create a duplicate data set of stroke to modify. */ - bGPDframe *derived_gpf = NULL; - gpencil_ensure_derived_frame(idx, ob, gpl, gpf, &derived_gpf); + bGPDframe *gpf_eval = NULL; + gpencil_evaluated_frame_ensure(idx, ob, gpf, &gpf_eval); /* Skip all if some disable flag is enabled. */ if ((ob->greasepencil_modifiers.first == NULL) || (is_multiedit) || (simplify_modif)) { @@ -888,13 +893,13 @@ void BKE_gpencil_modifiers_calc(Depsgraph *depsgraph, Scene *scene, Object *ob) /* Apply geometry modifiers (create new geometry). */ if (BKE_gpencil_has_geometry_modifiers(ob)) { - BKE_gpencil_geometry_modifiers(depsgraph, ob, gpl, derived_gpf, is_render); + BKE_gpencil_geometry_modifiers(depsgraph, ob, gpl, gpf_eval, is_render); } /* Loop all strokes and deform them. */ - for (bGPDstroke *gps = derived_gpf->strokes.first; gps; gps = gps->next) { + for (bGPDstroke *gps = gpf_eval->strokes.first; gps; gps = gps->next) { /* Apply modifiers that only deform geometry */ - BKE_gpencil_stroke_modifiers(depsgraph, ob, gpl, derived_gpf, gps, is_render); + BKE_gpencil_stroke_modifiers(depsgraph, ob, gpl, gpf_eval, gps, is_render); } idx++; diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index 61de6a8c06a..9a38f348361 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -2066,9 +2066,9 @@ void BKE_keyblock_mesh_calc_normals(struct KeyBlock *kb, } /************************* raw coords ************************/ -void BKE_keyblock_update_from_vertcos(Object *ob, KeyBlock *kb, float (*vertCos)[3]) +void BKE_keyblock_update_from_vertcos(Object *ob, KeyBlock *kb, const float (*vertCos)[3]) { - float(*co)[3] = vertCos; + const float(*co)[3] = vertCos; float *fp = kb->data; int tot, a; @@ -2126,7 +2126,7 @@ void BKE_keyblock_update_from_vertcos(Object *ob, KeyBlock *kb, float (*vertCos) } } -void BKE_keyblock_convert_from_vertcos(Object *ob, KeyBlock *kb, float (*vertCos)[3]) +void BKE_keyblock_convert_from_vertcos(Object *ob, KeyBlock *kb, const float (*vertCos)[3]) { int tot = 0, elemsize; @@ -2219,7 +2219,7 @@ float (*BKE_keyblock_convert_to_vertcos(Object *ob, KeyBlock *kb))[3] } /************************* raw coord offsets ************************/ -void BKE_keyblock_update_from_offset(Object *ob, KeyBlock *kb, float (*ofs)[3]) +void BKE_keyblock_update_from_offset(Object *ob, KeyBlock *kb, const float (*ofs)[3]) { int a; float *fp = kb->data; diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index 83b354ffb4a..e46b7ca5130 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -139,7 +139,7 @@ void BKE_lattice_resize(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb) BPoint *bp; int i, u, v, w; float fu, fv, fw, uc, vc, wc, du = 0.0, dv = 0.0, dw = 0.0; - float *co, (*vertexCos)[3] = NULL; + float *co, (*vert_coords)[3] = NULL; /* vertex weight groups are just freed all for now */ if (lt->dvert) { @@ -159,7 +159,7 @@ void BKE_lattice_resize(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb) } } - vertexCos = MEM_mallocN(sizeof(*vertexCos) * uNew * vNew * wNew, "tmp_vcos"); + vert_coords = MEM_mallocN(sizeof(*vert_coords) * uNew * vNew * wNew, "tmp_vcos"); calc_lat_fudu(lt->flag, uNew, &fu, &du); calc_lat_fudu(lt->flag, vNew, &fv, &dv); @@ -187,7 +187,7 @@ void BKE_lattice_resize(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb) } } - co = vertexCos[0]; + co = vert_coords[0]; for (w = 0, wc = fw; w < wNew; w++, wc += dw) { for (v = 0, vc = fv; v < vNew; v++, vc += dv) { for (u = 0, uc = fu; u < uNew; u++, co += 3, uc += du) { @@ -212,7 +212,7 @@ void BKE_lattice_resize(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb) copy_m4_m4(mat, ltOb->obmat); unit_m4(ltOb->obmat); - lattice_deform_verts(ltOb, NULL, NULL, vertexCos, uNew * vNew * wNew, NULL, 1.0f); + lattice_deform_verts(ltOb, NULL, NULL, vert_coords, uNew * vNew * wNew, NULL, 1.0f); copy_m4_m4(ltOb->obmat, mat); lt->typeu = typeu; @@ -238,10 +238,10 @@ void BKE_lattice_resize(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb) bp = lt->def; for (i = 0; i < lt->pntsu * lt->pntsv * lt->pntsw; i++, bp++) { - copy_v3_v3(bp->vec, vertexCos[i]); + copy_v3_v3(bp->vec, vert_coords[i]); } - MEM_freeN(vertexCos); + MEM_freeN(vert_coords); } void BKE_lattice_init(Lattice *lt) @@ -747,7 +747,7 @@ static bool calc_curve_deform( void curve_deform_verts(Object *cuOb, Object *target, - float (*vertexCos)[3], + float (*vert_coords)[3], int numVerts, MDeformVert *dvert, const int defgrp_index, @@ -786,11 +786,11 @@ void curve_deform_verts(Object *cuOb, const float weight = defvert_find_weight(dvert_iter, defgrp_index); if (weight > 0.0f) { - mul_m4_v3(cd.curvespace, vertexCos[a]); - copy_v3_v3(vec, vertexCos[a]); + mul_m4_v3(cd.curvespace, vert_coords[a]); + copy_v3_v3(vec, vert_coords[a]); calc_curve_deform(cuOb, vec, defaxis, &cd, NULL); - interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight); - mul_m4_v3(cd.objectspace, vertexCos[a]); + interp_v3_v3v3(vert_coords[a], vert_coords[a], vec, weight); + mul_m4_v3(cd.objectspace, vert_coords[a]); } } } @@ -800,8 +800,8 @@ void curve_deform_verts(Object *cuOb, for (a = 0, dvert_iter = dvert; a < numVerts; a++, dvert_iter++) { if (defvert_find_weight(dvert_iter, defgrp_index) > 0.0f) { - mul_m4_v3(cd.curvespace, vertexCos[a]); - minmax_v3v3_v3(cd.dmin, cd.dmax, vertexCos[a]); + mul_m4_v3(cd.curvespace, vert_coords[a]); + minmax_v3v3_v3(cd.dmin, cd.dmax, vert_coords[a]); } } @@ -810,10 +810,10 @@ void curve_deform_verts(Object *cuOb, if (weight > 0.0f) { /* already in 'cd.curvespace', prev for loop */ - copy_v3_v3(vec, vertexCos[a]); + copy_v3_v3(vec, vert_coords[a]); calc_curve_deform(cuOb, vec, defaxis, &cd, NULL); - interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight); - mul_m4_v3(cd.objectspace, vertexCos[a]); + interp_v3_v3v3(vert_coords[a], vert_coords[a], vec, weight); + mul_m4_v3(cd.objectspace, vert_coords[a]); } } } @@ -821,9 +821,9 @@ void curve_deform_verts(Object *cuOb, else { if (cu->flag & CU_DEFORM_BOUNDS_OFF) { for (a = 0; a < numVerts; a++) { - mul_m4_v3(cd.curvespace, vertexCos[a]); - calc_curve_deform(cuOb, vertexCos[a], defaxis, &cd, NULL); - mul_m4_v3(cd.objectspace, vertexCos[a]); + mul_m4_v3(cd.curvespace, vert_coords[a]); + calc_curve_deform(cuOb, vert_coords[a], defaxis, &cd, NULL); + mul_m4_v3(cd.objectspace, vert_coords[a]); } } else { @@ -831,14 +831,14 @@ void curve_deform_verts(Object *cuOb, INIT_MINMAX(cd.dmin, cd.dmax); for (a = 0; a < numVerts; a++) { - mul_m4_v3(cd.curvespace, vertexCos[a]); - minmax_v3v3_v3(cd.dmin, cd.dmax, vertexCos[a]); + mul_m4_v3(cd.curvespace, vert_coords[a]); + minmax_v3v3_v3(cd.dmin, cd.dmax, vert_coords[a]); } for (a = 0; a < numVerts; a++) { /* already in 'cd.curvespace', prev for loop */ - calc_curve_deform(cuOb, vertexCos[a], defaxis, &cd, NULL); - mul_m4_v3(cd.objectspace, vertexCos[a]); + calc_curve_deform(cuOb, vert_coords[a], defaxis, &cd, NULL); + mul_m4_v3(cd.objectspace, vert_coords[a]); } } } @@ -881,7 +881,7 @@ void curve_deform_vector( typedef struct LatticeDeformUserdata { LatticeDeformData *lattice_deform_data; - float (*vertexCos)[3]; + float (*vert_coords)[3]; MDeformVert *dvert; int defgrp_index; float fac; @@ -896,18 +896,18 @@ static void lattice_deform_vert_task(void *__restrict userdata, if (data->dvert != NULL) { const float weight = defvert_find_weight(data->dvert + index, data->defgrp_index); if (weight > 0.0f) { - calc_latt_deform(data->lattice_deform_data, data->vertexCos[index], weight * data->fac); + calc_latt_deform(data->lattice_deform_data, data->vert_coords[index], weight * data->fac); } } else { - calc_latt_deform(data->lattice_deform_data, data->vertexCos[index], data->fac); + calc_latt_deform(data->lattice_deform_data, data->vert_coords[index], data->fac); } } void lattice_deform_verts(Object *laOb, Object *target, Mesh *mesh, - float (*vertexCos)[3], + float (*vert_coords)[3], int numVerts, const char *vgroup, float fac) @@ -942,11 +942,13 @@ void lattice_deform_verts(Object *laOb, } } - LatticeDeformUserdata data = {.lattice_deform_data = lattice_deform_data, - .vertexCos = vertexCos, - .dvert = dvert, - .defgrp_index = defgrp_index, - .fac = fac}; + LatticeDeformUserdata data = { + .lattice_deform_data = lattice_deform_data, + .vert_coords = vert_coords, + .dvert = dvert, + .defgrp_index = defgrp_index, + .fac = fac, + }; TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); @@ -1055,33 +1057,37 @@ void outside_lattice(Lattice *lt) } } -float (*BKE_lattice_vertexcos_get(struct Object *ob, int *r_numVerts))[3] +void BKE_lattice_vert_coords_get(const Lattice *lt, float (*vert_coords)[3]) { - Lattice *lt = ob->data; - int i, numVerts; - float(*vertexCos)[3]; - - if (lt->editlatt) { - lt = lt->editlatt->latt; + const int vert_len = lt->pntsu * lt->pntsv * lt->pntsw; + for (int i = 0; i < vert_len; i++) { + copy_v3_v3(vert_coords[i], lt->def[i].vec); } - numVerts = *r_numVerts = lt->pntsu * lt->pntsv * lt->pntsw; +} - vertexCos = MEM_mallocN(sizeof(*vertexCos) * numVerts, "lt_vcos"); +float (*BKE_lattice_vert_coords_alloc(const Lattice *lt, int *r_vert_len))[3] +{ + const int vert_len = *r_vert_len = lt->pntsu * lt->pntsv * lt->pntsw; + float(*vert_coords)[3] = MEM_mallocN(sizeof(*vert_coords) * vert_len, __func__); + BKE_lattice_vert_coords_get(lt, vert_coords); + return vert_coords; +} +void BKE_lattice_vert_coords_apply_with_mat4(struct Lattice *lt, + const float (*vertexCos)[3], + const float mat[4][4]) +{ + int i, numVerts = lt->pntsu * lt->pntsv * lt->pntsw; for (i = 0; i < numVerts; i++) { - copy_v3_v3(vertexCos[i], lt->def[i].vec); + mul_v3_m4v3(lt->def[i].vec, mat, vertexCos[i]); } - - return vertexCos; } -void BKE_lattice_vertexcos_apply(struct Object *ob, float (*vertexCos)[3]) +void BKE_lattice_vert_coords_apply(Lattice *lt, const float (*vert_coords)[3]) { - Lattice *lt = ob->data; - int i, numVerts = lt->pntsu * lt->pntsv * lt->pntsw; - - for (i = 0; i < numVerts; i++) { - copy_v3_v3(lt->def[i].vec, vertexCos[i]); + const int vert_len = lt->pntsu * lt->pntsv * lt->pntsw; + for (int i = 0; i < vert_len; i++) { + copy_v3_v3(lt->def[i].vec, vert_coords[i]); } } @@ -1093,7 +1099,7 @@ void BKE_lattice_modifiers_calc(struct Depsgraph *depsgraph, Scene *scene, Objec Object *ob_orig = DEG_get_original_object(ob); VirtualModifierData virtualModifierData; ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); - float(*vertexCos)[3] = NULL; + float(*vert_coords)[3] = NULL; int numVerts, editmode = (lt->editlatt != NULL); const ModifierEvalContext mectx = {depsgraph, ob, 0}; @@ -1123,29 +1129,37 @@ void BKE_lattice_modifiers_calc(struct Depsgraph *depsgraph, Scene *scene, Objec continue; } - if (!vertexCos) { - vertexCos = BKE_lattice_vertexcos_get(ob_orig, &numVerts); + if (!vert_coords) { + Lattice *lt_orig = ob_orig->data; + if (lt_orig->editlatt) { + lt_orig = lt_orig->editlatt->latt; + } + vert_coords = BKE_lattice_vert_coords_alloc(lt_orig, &numVerts); } - mti->deformVerts(md, &mectx, NULL, vertexCos, numVerts); + mti->deformVerts(md, &mectx, NULL, vert_coords, numVerts); } if (ob->id.tag & LIB_TAG_COPIED_ON_WRITE) { - if (vertexCos) { - BKE_lattice_vertexcos_apply(ob, vertexCos); - MEM_freeN(vertexCos); + if (vert_coords) { + BKE_lattice_vert_coords_apply(ob->data, vert_coords); + MEM_freeN(vert_coords); } } else { /* Displist won't do anything; this is just for posterity's sake until we remove it. */ - if (!vertexCos) { - vertexCos = BKE_lattice_vertexcos_get(ob_orig, &numVerts); + if (!vert_coords) { + Lattice *lt_orig = ob_orig->data; + if (lt_orig->editlatt) { + lt_orig = lt_orig->editlatt->latt; + } + vert_coords = BKE_lattice_vert_coords_alloc(lt_orig, &numVerts); } DispList *dl = MEM_callocN(sizeof(*dl), "lt_dl"); dl->type = DL_VERTS; dl->parts = 1; dl->nr = numVerts; - dl->verts = (float *)vertexCos; + dl->verts = (float *)vert_coords; BLI_addtail(&ob->runtime.curve_cache->disp, dl); } diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c index 40608285785..de105b9b62a 100644 --- a/source/blender/blenkernel/intern/layer.c +++ b/source/blender/blenkernel/intern/layer.c @@ -494,6 +494,36 @@ static LayerCollection *collection_from_index(ListBase *lb, const int number, in } /** + * Determine if a collection is hidden, viewport visibility restricted, or excluded + */ +static bool layer_collection_hidden(ViewLayer *view_layer, LayerCollection *lc) +{ + if (lc->flag & LAYER_COLLECTION_EXCLUDE) { + return true; + } + + /* Check visiblilty restriction flags */ + if (lc->flag & LAYER_COLLECTION_HIDE || lc->collection->flag & COLLECTION_RESTRICT_VIEWPORT) { + return true; + } + else { + /* Restriction flags stay set, so we need to check parents */ + CollectionParent *parent = lc->collection->parents.first; + + if (parent) { + lc = BKE_layer_collection_first_from_scene_collection(view_layer, parent->collection); + + return lc && layer_collection_hidden(view_layer, lc); + } + else { + return false; + } + } + + return false; +} + +/** * Get the collection for a given index */ LayerCollection *BKE_layer_collection_from_index(ViewLayer *view_layer, const int index) @@ -537,8 +567,9 @@ LayerCollection *BKE_layer_collection_activate_parent(ViewLayer *view_layer, Lay lc = NULL; } - if (lc && (lc->flag & LAYER_COLLECTION_EXCLUDE)) { - /* Don't activate excluded collections. */ + /* Don't activate excluded or hidden collections to prevent creating objects in a hidden + * collection from the UI */ + if (lc && layer_collection_hidden(view_layer, lc)) { return BKE_layer_collection_activate_parent(view_layer, lc); } @@ -817,8 +848,7 @@ void BKE_layer_collection_sync(const Scene *scene, ViewLayer *view_layer) /* Always set a valid active collection. */ LayerCollection *active = view_layer->active_collection; - - if (active && (active->flag & LAYER_COLLECTION_EXCLUDE)) { + if (active && layer_collection_hidden(view_layer, active)) { BKE_layer_collection_activate_parent(view_layer, active); } else if (active == NULL) { diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index de6f5142a19..f45eba2b53f 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -851,8 +851,8 @@ void BKE_id_swap(Main *bmain, ID *id_a, ID *id_b) id_b->properties = id_a_back.properties; /* Swap will have broken internal references to itself, restore them. */ - BKE_libblock_relink_ex(bmain, id_a, id_b, id_a, false); - BKE_libblock_relink_ex(bmain, id_b, id_a, id_b, false); + BKE_libblock_relink_ex(bmain, id_a, id_b, id_a, ID_REMAP_SKIP_NEVER_NULL_USAGE); + BKE_libblock_relink_ex(bmain, id_b, id_a, id_b, ID_REMAP_SKIP_NEVER_NULL_USAGE); } /** Does *not* set ID->newid pointer. */ @@ -1408,21 +1408,24 @@ void *BKE_id_new_nomain(const short type, const char *name) return id; } -void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag) +void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, int flag) { ID *new_id = *r_newid; - /* Grrrrrrrrr... Not adding 'root' nodetrees to bmain.... grrrrrrrrrrrrrrrrrrrr! */ - /* This is taken from original ntree copy code, might be weak actually? */ - const bool use_nodetree_alloc_exception = ((GS(id->name) == ID_NT) && (bmain != NULL) && - (BLI_findindex(&bmain->nodetrees, id) < 0)); - BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) != 0 || bmain != NULL); BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) != 0 || (flag & LIB_ID_CREATE_NO_ALLOCATE) == 0); BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) == 0 || (flag & LIB_ID_CREATE_NO_USER_REFCOUNT) != 0); /* Never implicitly copy shapekeys when generating temp data outside of Main database. */ BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) == 0 || (flag & LIB_ID_COPY_SHAPEKEY) == 0); + /* 'Private ID' data handling. */ + if ((bmain != NULL) && (id->flag & LIB_PRIVATE_DATA) != 0) { + flag |= LIB_ID_CREATE_NO_MAIN; + } + + /* The id->flag bits to copy over. */ + const int copy_flag_mask = LIB_PRIVATE_DATA; + if ((flag & LIB_ID_CREATE_NO_ALLOCATE) != 0) { /* r_newid already contains pointer to allocated memory. */ /* TODO do we want to memset(0) whole mem before filling it? */ @@ -1432,10 +1435,7 @@ void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int fla /* TODO Do we want/need to copy more from ID struct itself? */ } else { - new_id = BKE_libblock_alloc(bmain, - GS(id->name), - id->name + 2, - flag | (use_nodetree_alloc_exception ? LIB_ID_CREATE_NO_MAIN : 0)); + new_id = BKE_libblock_alloc(bmain, GS(id->name), id->name + 2, flag); } BLI_assert(new_id != NULL); @@ -1448,6 +1448,8 @@ void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int fla memcpy(cpn + id_offset, cp + id_offset, id_len - id_offset); } + new_id->flag = (new_id->flag & ~copy_flag_mask) | (id->flag & copy_flag_mask); + if (id->properties) { new_id->properties = IDP_CopyProperty_ex(id->properties, flag); } @@ -1727,8 +1729,8 @@ bool BKE_id_new_name_validate(ListBase *lb, ID *id, const char *tname) /* This was in 2.43 and previous releases * however all data in blender should be sorted, not just duplicate names - * sorting should not hurt, but noting just incase it alters the way other - * functions work, so sort every time */ + * sorting should not hurt, but noting just in case it alters the way other + * functions work, so sort every time. */ #if 0 if (result) { id_sort_by_name(lb, id); diff --git a/source/blender/blenkernel/intern/library_override.c b/source/blender/blenkernel/intern/library_override.c index e435f07e38d..6532fce5778 100644 --- a/source/blender/blenkernel/intern/library_override.c +++ b/source/blender/blenkernel/intern/library_override.c @@ -111,11 +111,11 @@ void BKE_override_library_copy(ID *dst_id, const ID *src_id) if (dst_id->override_library != NULL) { if (src_id->override_library == NULL) { - BKE_override_library_free(&dst_id->override_library); + BKE_override_library_free(&dst_id->override_library, true); return; } else { - BKE_override_library_clear(dst_id->override_library); + BKE_override_library_clear(dst_id->override_library, true); } } else if (src_id->override_library == NULL) { @@ -144,7 +144,7 @@ void BKE_override_library_copy(ID *dst_id, const ID *src_id) } /** Clear any overriding data from given \a override. */ -void BKE_override_library_clear(IDOverrideLibrary *override) +void BKE_override_library_clear(IDOverrideLibrary *override, const bool do_id_user) { BLI_assert(override != NULL); @@ -153,16 +153,18 @@ void BKE_override_library_clear(IDOverrideLibrary *override) } BLI_freelistN(&override->properties); - id_us_min(override->reference); - /* override->storage should never be refcounted... */ + if (do_id_user) { + id_us_min(override->reference); + /* override->storage should never be refcounted... */ + } } /** Free given \a override. */ -void BKE_override_library_free(struct IDOverrideLibrary **override) +void BKE_override_library_free(struct IDOverrideLibrary **override, const bool do_id_user) { BLI_assert(*override != NULL); - BKE_override_library_clear(*override); + BKE_override_library_clear(*override, do_id_user); MEM_freeN(*override); *override = NULL; } @@ -205,6 +207,11 @@ ID *BKE_override_library_create_from_id(Main *bmain, ID *reference_id) * \note Set id->newid of overridden libs with newly created overrides, * caller is responsible to clean those pointers before/after usage as needed. * + * \note By default, it will only remap newly created local overriding data-blocks between + * themselves, to avoid 'enforcing' those overrides into all other usages of the linked data in + * main. You can add more local IDs to be remapped to use new overriding ones by setting their + * LIB_TAG_DOIT tag. + * * \return \a true on success, \a false otherwise. */ bool BKE_override_library_create_from_tag(Main *bmain) @@ -212,26 +219,59 @@ bool BKE_override_library_create_from_tag(Main *bmain) ID *reference_id; bool ret = true; + ListBase todo_ids = {NULL}; + LinkData *todo_id_iter; + + /* Get all IDs we want to override. */ FOREACH_MAIN_ID_BEGIN (bmain, reference_id) { if ((reference_id->tag & LIB_TAG_DOIT) != 0 && reference_id->lib != NULL) { - if ((reference_id->newid = override_library_create_from(bmain, reference_id)) == NULL) { - ret = false; - } + todo_id_iter = MEM_callocN(sizeof(*todo_id_iter), __func__); + todo_id_iter->data = reference_id; + BLI_addtail(&todo_ids, todo_id_iter); } } FOREACH_MAIN_ID_END; - FOREACH_MAIN_ID_BEGIN (bmain, reference_id) { - if ((reference_id->tag & LIB_TAG_DOIT) != 0 && reference_id->lib != NULL && - reference_id->newid != NULL) { - ID *local_id = reference_id->newid; - BKE_libblock_remap(bmain, - reference_id, - local_id, - ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_OVERRIDE_LIBRARY); + /* Override the IDs. */ + for (todo_id_iter = todo_ids.first; todo_id_iter != NULL; todo_id_iter = todo_id_iter->next) { + reference_id = todo_id_iter->data; + if ((reference_id->newid = override_library_create_from(bmain, reference_id)) == NULL) { + ret = false; + } + else { + /* We also tag the new IDs so that in next step we can remap their pointers too. */ + reference_id->newid->tag |= LIB_TAG_DOIT; } } - FOREACH_MAIN_ID_END; + + /* Only remap new local ID's pointers, we don't want to force our new overrides onto our whole + * existing linked IDs usages. */ + for (todo_id_iter = todo_ids.first; todo_id_iter != NULL; todo_id_iter = todo_id_iter->next) { + ID *other_id; + reference_id = todo_id_iter->data; + + if (reference_id->newid == NULL) { + continue; + } + + /* Still checking the whole Main, that way we can tag other local IDs as needing to be remapped + * to use newly created overriding IDs, if needed. */ + FOREACH_MAIN_ID_BEGIN (bmain, other_id) { + if ((other_id->tag & LIB_TAG_DOIT) != 0 && other_id->lib == NULL) { + ID *local_id = reference_id->newid; + /* Note that using ID_REMAP_SKIP_INDIRECT_USAGE below is superfluous, as we only remap + * local IDs usages anyway... */ + BKE_libblock_relink_ex(bmain, + other_id, + reference_id, + local_id, + ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_OVERRIDE_LIBRARY); + } + } + FOREACH_MAIN_ID_END; + } + + BLI_freelistN(&todo_ids); return ret; } @@ -628,7 +668,7 @@ void BKE_main_override_library_operations_create(Main *bmain, const bool force_a ID *id; FOREACH_MAIN_ID_BEGIN (bmain, id) { - if (force_auto || + if ((ID_IS_OVERRIDE_LIBRARY(id) && force_auto) || (ID_IS_OVERRIDE_LIBRARY_AUTO(id) && (id->tag & LIB_TAG_OVERRIDE_LIBRARY_AUTOREFRESH))) { BKE_override_library_operations_create(bmain, id, force_auto); id->tag &= ~LIB_TAG_OVERRIDE_LIBRARY_AUTOREFRESH; diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c index 8fe2552c03f..61f506a8a6c 100644 --- a/source/blender/blenkernel/intern/library_remap.c +++ b/source/blender/blenkernel/intern/library_remap.c @@ -652,12 +652,11 @@ void BKE_libblock_unlink(Main *bmain, * ... sigh */ void BKE_libblock_relink_ex( - Main *bmain, void *idv, void *old_idv, void *new_idv, const bool us_min_never_null) + Main *bmain, void *idv, void *old_idv, void *new_idv, const short remap_flags) { ID *id = idv; ID *old_id = old_idv; ID *new_id = new_idv; - int remap_flags = us_min_never_null ? 0 : ID_REMAP_SKIP_NEVER_NULL_USAGE; /* No need to lock here, we are only affecting given ID, not bmain database. */ @@ -757,7 +756,7 @@ void BKE_libblock_free_data(ID *id, const bool do_id_user) } if (id->override_library) { - BKE_override_library_free(&id->override_library); + BKE_override_library_free(&id->override_library, do_id_user); } /* XXX TODO remove animdata handling from each type's freeing func, @@ -945,7 +944,7 @@ void BKE_id_free_ex(Main *bmain, void *idv, int flag, const bool use_flag_from_i #endif if ((flag & LIB_ID_FREE_NO_USER_REFCOUNT) == 0) { - BKE_libblock_relink_ex(bmain, id, NULL, NULL, true); + BKE_libblock_relink_ex(bmain, id, NULL, NULL, 0); } BKE_libblock_free_datablock(id, flag); @@ -1091,7 +1090,7 @@ static void id_delete(Main *bmain, const bool do_tagged_deletion) bmain, id, NULL, ID_REMAP_FLAG_NEVER_NULL_USAGE | ID_REMAP_FORCE_NEVER_NULL_USAGE); /* Since we removed ID from Main, * we also need to unlink its own other IDs usages ourself. */ - BKE_libblock_relink_ex(bmain, id, NULL, NULL, true); + BKE_libblock_relink_ex(bmain, id, NULL, NULL, 0); /* Now we can safely mark that ID as not being in Main database anymore. */ id->tag |= LIB_TAG_NO_MAIN; /* This is needed because we may not have remapped usages diff --git a/source/blender/blenkernel/intern/light.c b/source/blender/blenkernel/intern/light.c index 75c9e0e42a5..07ec8d70af1 100644 --- a/source/blender/blenkernel/intern/light.c +++ b/source/blender/blenkernel/intern/light.c @@ -108,12 +108,15 @@ Light *BKE_light_add(Main *bmain, const char *name) */ void BKE_light_copy_data(Main *bmain, Light *la_dst, const Light *la_src, const int flag) { + /* We never handle usercount here for own data. */ + const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT; + /* We always need allocation of our private ID data. */ + const int flag_private_id_data = flag_subdata & ~LIB_ID_CREATE_NO_ALLOCATE; + la_dst->curfalloff = BKE_curvemapping_copy(la_src->curfalloff); if (la_src->nodetree) { - /* Note: nodetree is *not* in bmain, however this specific case is handled at lower level - * (see BKE_libblock_copy_ex()). */ - BKE_id_copy_ex(bmain, (ID *)la_src->nodetree, (ID **)&la_dst->nodetree, flag); + BKE_id_copy_ex(bmain, (ID *)la_src->nodetree, (ID **)&la_dst->nodetree, flag_private_id_data); } if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) { diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c index 7bfe5a7c8ff..e5fa5ff08b0 100644 --- a/source/blender/blenkernel/intern/linestyle.c +++ b/source/blender/blenkernel/intern/linestyle.c @@ -167,6 +167,8 @@ void BKE_linestyle_copy_data(struct Main *bmain, { /* We never handle usercount here for own data. */ const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT; + /* We always need allocation of our private ID data. */ + const int flag_private_id_data = flag_subdata & ~LIB_ID_CREATE_NO_ALLOCATE; for (int a = 0; a < MAX_MTEX; a++) { if (linestyle_src->mtex[a]) { @@ -176,9 +178,10 @@ void BKE_linestyle_copy_data(struct Main *bmain, } if (linestyle_src->nodetree) { - /* Note: nodetree is *not* in bmain, however this specific case is handled at lower level - * (see BKE_libblock_copy_ex()). */ - BKE_id_copy_ex(bmain, (ID *)linestyle_src->nodetree, (ID **)&linestyle_dst->nodetree, flag); + BKE_id_copy_ex(bmain, + (ID *)linestyle_src->nodetree, + (ID **)&linestyle_dst->nodetree, + flag_private_id_data); } LineStyleModifier *m; diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index b6d61563fe8..fc087ff91b2 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1628,7 +1628,9 @@ MaskLayerShape *BKE_mask_layer_shape_find_frame(MaskLayer *masklay, const int fr return NULL; } -/* when returning 2 - the frame isnt found but before/after frames are */ +/** + * When returning 2 - the frame isn't found but before/after frames are. + */ int BKE_mask_layer_shape_find_frame_range(MaskLayer *masklay, const float frame, MaskLayerShape **r_masklay_shape_a, diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index b01c1189fd1..c12541b3b22 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -71,6 +71,7 @@ /* used in UI and render */ Material defmaterial; +Material defgpencil_material; static CLG_LogRef LOG = {"bke.material"}; @@ -78,6 +79,13 @@ static CLG_LogRef LOG = {"bke.material"}; void init_def_material(void) { BKE_material_init(&defmaterial); + BKE_material_gpencil_init(&defgpencil_material); +} + +/* Free the GPencil data of the default material, creator.c */ +void BKE_material_gpencil_default_free(void) +{ + MEM_SAFE_FREE(defgpencil_material.gp_style); } /** Free (or release) any data used by this material (does not free the material itself). */ @@ -144,6 +152,16 @@ void BKE_material_init(Material *ma) ma->blend_shadow = MA_BS_SOLID; } +void BKE_material_gpencil_init(Material *ma) +{ + BKE_material_init(ma); + + /* grease pencil settings */ + strcpy(ma->id.name, "MADefault GPencil"); + BKE_material_init_gpencil_settings(ma); + add_v3_fl(&ma->gp_style->stroke_rgba[0], 0.6f); +} + Material *BKE_material_add(Main *bmain, const char *name) { Material *ma; @@ -180,10 +198,13 @@ Material *BKE_material_add_gpencil(Main *bmain, const char *name) */ void BKE_material_copy_data(Main *bmain, Material *ma_dst, const Material *ma_src, const int flag) { + /* We never handle usercount here for own data. */ + const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT; + /* We always need allocation of our private ID data. */ + const int flag_private_id_data = flag_subdata & ~LIB_ID_CREATE_NO_ALLOCATE; + if (ma_src->nodetree) { - /* Note: nodetree is *not* in bmain, however this specific case is handled at lower level - * (see BKE_libblock_copy_ex()). */ - BKE_id_copy_ex(bmain, (ID *)ma_src->nodetree, (ID **)&ma_dst->nodetree, flag); + BKE_id_copy_ex(bmain, (ID *)ma_src->nodetree, (ID **)&ma_dst->nodetree, flag_private_id_data); } if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) { @@ -461,7 +482,7 @@ void BKE_material_append_id(Main *bmain, ID *id, Material *ma) } } -Material *BKE_material_pop_id(Main *bmain, ID *id, int index_i, bool update_data) +Material *BKE_material_pop_id(Main *bmain, ID *id, int index_i) { short index = (short)index_i; Material *ret = NULL; @@ -489,10 +510,7 @@ Material *BKE_material_pop_id(Main *bmain, ID *id, int index_i, bool update_data test_all_objects_materials(bmain, id); } - if (update_data) { - /* decrease mat_nr index */ - material_data_index_remove_id(id, index); - } + material_data_index_remove_id(id, index); DEG_id_tag_update(id, ID_RECALC_COPY_ON_WRITE); DEG_relations_tag_update(bmain); @@ -502,7 +520,7 @@ Material *BKE_material_pop_id(Main *bmain, ID *id, int index_i, bool update_data return ret; } -void BKE_material_clear_id(Main *bmain, ID *id, bool update_data) +void BKE_material_clear_id(Main *bmain, ID *id) { Material ***matar; if ((matar = give_matarar_id(id))) { @@ -516,12 +534,9 @@ void BKE_material_clear_id(Main *bmain, ID *id, bool update_data) MEM_freeN(*matar); *matar = NULL; } - test_all_objects_materials(bmain, id); - if (update_data) { - /* decrease mat_nr index */ - material_data_index_clear_id(id); - } + test_all_objects_materials(bmain, id); + material_data_index_clear_id(id); DEG_id_tag_update(id, ID_RECALC_COPY_ON_WRITE); DEG_relations_tag_update(bmain); @@ -586,6 +601,17 @@ Material *give_current_material(Object *ob, short act) return ma_p ? *ma_p : NULL; } +Material *BKE_material_gpencil_get(Object *ob, short act) +{ + Material *ma = give_current_material(ob, act); + if (ma != NULL) { + return ma; + } + else { + return &defgpencil_material; + } +} + MaterialGPencilStyle *BKE_material_gpencil_settings_get(Object *ob, short act) { Material *ma = give_current_material(ob, act); @@ -597,7 +623,7 @@ MaterialGPencilStyle *BKE_material_gpencil_settings_get(Object *ob, short act) return ma->gp_style; } else { - return NULL; + return defgpencil_material.gp_style; } } @@ -1076,10 +1102,6 @@ bool BKE_object_material_slot_remove(Main *bmain, Object *ob) } /* check indices from gpencil */ else if (ob->type == OB_GPENCIL) { - /* need one color */ - if (ob->totcol == 0) { - BKE_gpencil_object_material_ensure_from_active_input_material(bmain, ob); - } BKE_gpencil_material_index_reassign((bGPdata *)ob->data, ob->totcol, actcol - 1); } diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index d6fa071009e..19009322975 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -364,12 +364,13 @@ bool BKE_mball_is_any_unselected(const MetaBall *mb) return false; } -/* \brief copy some properties from object to other metaball object with same base name +/** + * \brief copy some properties from object to other metaball object with same base name * * When some properties (wiresize, threshold, update flags) of metaball are changed, then this * properties are copied to all metaballs in same "group" (metaballs with same base name: MBall, * MBall.001, MBall.002, etc). The most important is to copy properties to the base metaball, - * because this metaball influence polygonisation of metaballs. */ + * because this metaball influence polygonization of metaballs. */ void BKE_mball_properties_copy(Scene *scene, Object *active_object) { Scene *sce_iter = scene; @@ -525,7 +526,7 @@ bool BKE_mball_center_bounds(const MetaBall *mb, float r_cent[3]) return false; } -void BKE_mball_transform(MetaBall *mb, float mat[4][4], const bool do_props) +void BKE_mball_transform(MetaBall *mb, const float mat[4][4], const bool do_props) { float quat[4]; const float scale = mat4_to_scale(mat); diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 4f39d34574e..61b841591a4 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -661,13 +661,13 @@ Mesh *BKE_mesh_new_nomain( return mesh; } -static Mesh *mesh_new_nomain_from_template_ex(const Mesh *me_src, - int verts_len, - int edges_len, - int tessface_len, - int loops_len, - int polys_len, - CustomData_MeshMasks mask) +Mesh *BKE_mesh_new_nomain_from_template_ex(const Mesh *me_src, + int verts_len, + int edges_len, + int tessface_len, + int loops_len, + int polys_len, + CustomData_MeshMasks mask) { /* Only do tessface if we are creating tessfaces or copying from mesh with only tessfaces. */ const bool do_tessface = (tessface_len || ((me_src->totface != 0) && (me_src->totpoly == 0))); @@ -713,7 +713,7 @@ Mesh *BKE_mesh_new_nomain_from_template(const Mesh *me_src, int loops_len, int polys_len) { - return mesh_new_nomain_from_template_ex( + return BKE_mesh_new_nomain_from_template_ex( me_src, verts_len, edges_len, tessface_len, loops_len, polys_len, CD_MASK_EVERYTHING); } @@ -801,7 +801,7 @@ Mesh *BKE_mesh_from_editmesh_with_coords_thin_wrap(BMEditMesh *em, me->runtime.is_original = true; if (vertexCos) { /* We will own this array in the future. */ - BKE_mesh_apply_vert_coords(me, vertexCos); + BKE_mesh_vert_coords_apply(me, vertexCos); MEM_freeN(vertexCos); me->runtime.is_original = false; } @@ -813,92 +813,6 @@ void BKE_mesh_make_local(Main *bmain, Mesh *me, const bool lib_local) BKE_id_make_local_generic(bmain, &me->id, true, lib_local); } -bool BKE_mesh_uv_cdlayer_rename_index(Mesh *me, - const int loop_index, - const int face_index, - const char *new_name, - const bool do_tessface) -{ - CustomData *ldata, *fdata; - CustomDataLayer *cdlu, *cdlf; - - if (me->edit_mesh) { - ldata = &me->edit_mesh->bm->ldata; - fdata = NULL; /* No tessellated data in BMesh! */ - } - else { - ldata = &me->ldata; - fdata = &me->fdata; - } - - cdlu = &ldata->layers[loop_index]; - cdlf = (face_index != -1) && fdata && do_tessface ? &fdata->layers[face_index] : NULL; - - if (cdlu->name != new_name) { - /* Mesh validate passes a name from the CD layer as the new name, - * Avoid memcpy from self to self in this case. - */ - BLI_strncpy(cdlu->name, new_name, sizeof(cdlu->name)); - CustomData_set_layer_unique_name(ldata, loop_index); - } - - if (cdlf == NULL) { - return false; - } - - BLI_strncpy(cdlf->name, cdlu->name, sizeof(cdlf->name)); - CustomData_set_layer_unique_name(fdata, face_index); - - return true; -} - -bool BKE_mesh_uv_cdlayer_rename(Mesh *me, - const char *old_name, - const char *new_name, - bool do_tessface) -{ - CustomData *ldata, *fdata; - if (me->edit_mesh) { - ldata = &me->edit_mesh->bm->ldata; - /* No tessellated data in BMesh! */ - fdata = NULL; - do_tessface = false; - } - else { - ldata = &me->ldata; - fdata = &me->fdata; - do_tessface = (do_tessface && fdata->totlayer); - } - - { - const int lidx_start = CustomData_get_layer_index(ldata, CD_MLOOPUV); - const int fidx_start = do_tessface ? CustomData_get_layer_index(fdata, CD_MTFACE) : -1; - int lidx = CustomData_get_named_layer(ldata, CD_MLOOPUV, old_name); - int fidx = do_tessface ? CustomData_get_named_layer(fdata, CD_MTFACE, old_name) : -1; - - /* None of those cases should happen, in theory! - * Note this assume we have the same number of mtexpoly, mloopuv and mtface layers! - */ - if (lidx == -1) { - if (fidx == -1) { - /* No layer found with this name! */ - return false; - } - else { - lidx = fidx; - } - } - - /* Go back to absolute indices! */ - lidx += lidx_start; - if (fidx != -1) { - fidx += fidx_start; - } - - return BKE_mesh_uv_cdlayer_rename_index(me, lidx, fidx, new_name, do_tessface); - } -} - void BKE_mesh_boundbox_calc(Mesh *me, float r_loc[3], float r_size[3]) { BoundBox *bb; @@ -1273,54 +1187,21 @@ void BKE_mesh_material_remap(Mesh *me, const unsigned int *remap, unsigned int r #undef MAT_NR_REMAP } -void BKE_mesh_smooth_flag_set(Object *meshOb, int enableSmooth) +void BKE_mesh_smooth_flag_set(Mesh *me, const bool use_smooth) { - Mesh *me = meshOb->data; - int i; - - for (i = 0; i < me->totpoly; i++) { - MPoly *mp = &me->mpoly[i]; - - if (enableSmooth) { - mp->flag |= ME_SMOOTH; - } - else { - mp->flag &= ~ME_SMOOTH; + if (use_smooth) { + for (int i = 0; i < me->totpoly; i++) { + me->mpoly[i].flag |= ME_SMOOTH; } } - - for (i = 0; i < me->totface; i++) { - MFace *mf = &me->mface[i]; - - if (enableSmooth) { - mf->flag |= ME_SMOOTH; - } - else { - mf->flag &= ~ME_SMOOTH; + else { + for (int i = 0; i < me->totpoly; i++) { + me->mpoly[i].flag &= ~ME_SMOOTH; } } } /** - * Return a newly MEM_malloc'd array of all the mesh vertex locations - * \note \a r_verts_len may be NULL - */ -float (*BKE_mesh_vertexCos_get(const Mesh *me, int *r_verts_len))[3] -{ - int i, verts_len = me->totvert; - float(*cos)[3] = MEM_malloc_arrayN(verts_len, sizeof(*cos), "vertexcos1"); - - if (r_verts_len) { - *r_verts_len = verts_len; - } - for (i = 0; i < verts_len; i++) { - copy_v3_v3(cos[i], me->mvert[i].co); - } - - return cos; -} - -/** * Find the index of the loop in 'poly' which references vertex, * returns -1 if not found */ @@ -1471,7 +1352,7 @@ void BKE_mesh_ensure_navmesh(Mesh *me) void BKE_mesh_tessface_calc(Mesh *mesh) { - mesh->totface = BKE_mesh_recalc_tessellation( + mesh->totface = BKE_mesh_tessface_calc_ex( &mesh->fdata, &mesh->ldata, &mesh->pdata, @@ -1665,35 +1546,56 @@ void BKE_mesh_count_selected_items(const Mesh *mesh, int r_count[3]) /* We could support faces in paint modes. */ } -void BKE_mesh_apply_vert_coords(Mesh *mesh, float (*vertCoords)[3]) +void BKE_mesh_vert_coords_get(const Mesh *mesh, float (*vert_coords)[3]) { - MVert *vert; - int i; - - /* this will just return the pointer if it wasn't a referenced layer */ - vert = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MVERT, mesh->totvert); - mesh->mvert = vert; + const MVert *mv = mesh->mvert; + for (int i = 0; i < mesh->totvert; i++, mv++) { + copy_v3_v3(vert_coords[i], mv->co); + } +} - for (i = 0; i < mesh->totvert; ++i, ++vert) { - copy_v3_v3(vert->co, vertCoords[i]); +float (*BKE_mesh_vert_coords_alloc(const Mesh *mesh, int *r_vert_len))[3] +{ + float(*vert_coords)[3] = MEM_mallocN(sizeof(float[3]) * mesh->totvert, __func__); + BKE_mesh_vert_coords_get(mesh, vert_coords); + if (r_vert_len) { + *r_vert_len = mesh->totvert; } + return vert_coords; +} +void BKE_mesh_vert_coords_apply(Mesh *mesh, const float (*vert_coords)[3]) +{ + /* This will just return the pointer if it wasn't a referenced layer. */ + MVert *mv = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MVERT, mesh->totvert); + mesh->mvert = mv; + for (int i = 0; i < mesh->totvert; i++, mv++) { + copy_v3_v3(mv->co, vert_coords[i]); + } mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL; } -void BKE_mesh_apply_vert_normals(Mesh *mesh, short (*vertNormals)[3]) +void BKE_mesh_vert_coords_apply_with_mat4(Mesh *mesh, + const float (*vert_coords)[3], + const float mat[4][4]) { - MVert *vert; - int i; - - /* this will just return the pointer if it wasn't a referenced layer */ - vert = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MVERT, mesh->totvert); - mesh->mvert = vert; - - for (i = 0; i < mesh->totvert; ++i, ++vert) { - copy_v3_v3_short(vert->no, vertNormals[i]); + /* This will just return the pointer if it wasn't a referenced layer. */ + MVert *mv = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MVERT, mesh->totvert); + mesh->mvert = mv; + for (int i = 0; i < mesh->totvert; i++, mv++) { + mul_v3_m4v3(mv->co, mat, vert_coords[i]); } + mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL; +} +void BKE_mesh_vert_normals_apply(Mesh *mesh, const short (*vert_normals)[3]) +{ + /* This will just return the pointer if it wasn't a referenced layer. */ + MVert *mv = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MVERT, mesh->totvert); + mesh->mvert = mv; + for (int i = 0; i < mesh->totvert; i++, mv++) { + copy_v3_v3_short(mv->no, vert_normals[i]); + } mesh->runtime.cd_dirty_vert &= ~CD_MASK_NORMAL; } diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c index 3a2ba078dce..e072a37acee 100644 --- a/source/blender/blenkernel/intern/mesh_convert.c +++ b/source/blender/blenkernel/intern/mesh_convert.c @@ -1341,11 +1341,11 @@ Mesh *BKE_mesh_create_derived_for_modifier(struct Depsgraph *depsgraph, if (mti->type == eModifierTypeType_OnlyDeform) { int numVerts; - float(*deformedVerts)[3] = BKE_mesh_vertexCos_get(me, &numVerts); + float(*deformedVerts)[3] = BKE_mesh_vert_coords_alloc(me, &numVerts); BKE_id_copy_ex(NULL, &me->id, (ID **)&result, LIB_ID_COPY_LOCALIZE); mti->deformVerts(md_eval, &mectx, result, deformedVerts, numVerts); - BKE_mesh_apply_vert_coords(result, deformedVerts); + BKE_mesh_vert_coords_apply(result, deformedVerts); if (build_shapekey_layers) { add_shapekey_layers(result, me); @@ -1434,7 +1434,6 @@ static void shapekey_layers_to_keyblocks(Mesh *mesh_src, Mesh *mesh_dst, int act } } -/* This is a Mesh-based copy of DM_to_mesh() */ void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, Mesh *mesh_dst, Object *ob, @@ -1442,7 +1441,7 @@ void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, bool take_ownership) { /* mesh_src might depend on mesh_dst, so we need to do everything with a local copy */ - /* TODO(Sybren): the above claim came from DM_to_mesh(); + /* TODO(Sybren): the above claim came from 2.7x derived-mesh code (DM_to_mesh); * check whether it is still true with Mesh */ Mesh tmp = *mesh_dst; int totvert, totedge /*, totface */ /* UNUSED */, totloop, totpoly; @@ -1594,7 +1593,6 @@ void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, } } -/* This is a Mesh-based copy of DM_to_meshkey() */ void BKE_mesh_nomain_to_meshkey(Mesh *mesh_src, Mesh *mesh_dst, KeyBlock *kb) { int a, totvert = mesh_src->totvert; diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c index 2ea275cdfb0..38762109167 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.c +++ b/source/blender/blenkernel/intern/mesh_evaluate.c @@ -448,64 +448,6 @@ void BKE_mesh_calc_normals(Mesh *mesh) mesh->runtime.cd_dirty_vert &= ~CD_MASK_NORMAL; } -void BKE_mesh_calc_normals_tessface( - MVert *mverts, int numVerts, const MFace *mfaces, int numFaces, float (*r_faceNors)[3]) -{ - float(*tnorms)[3] = MEM_calloc_arrayN((size_t)numVerts, sizeof(*tnorms), "tnorms"); - float(*fnors)[3] = (r_faceNors) ? - r_faceNors : - MEM_calloc_arrayN((size_t)numFaces, sizeof(*fnors), "meshnormals"); - int i; - - if (!tnorms || !fnors) { - goto cleanup; - } - - for (i = 0; i < numFaces; i++) { - const MFace *mf = &mfaces[i]; - float *f_no = fnors[i]; - float *n4 = (mf->v4) ? tnorms[mf->v4] : NULL; - const float *c4 = (mf->v4) ? mverts[mf->v4].co : NULL; - - if (mf->v4) { - normal_quad_v3( - f_no, mverts[mf->v1].co, mverts[mf->v2].co, mverts[mf->v3].co, mverts[mf->v4].co); - } - else { - normal_tri_v3(f_no, mverts[mf->v1].co, mverts[mf->v2].co, mverts[mf->v3].co); - } - - accumulate_vertex_normals_v3(tnorms[mf->v1], - tnorms[mf->v2], - tnorms[mf->v3], - n4, - f_no, - mverts[mf->v1].co, - mverts[mf->v2].co, - mverts[mf->v3].co, - c4); - } - - /* following Mesh convention; we use vertex coordinate itself for normal in this case */ - for (i = 0; i < numVerts; i++) { - MVert *mv = &mverts[i]; - float *no = tnorms[i]; - - if (UNLIKELY(normalize_v3(no) == 0.0f)) { - normalize_v3_v3(no, mv->co); - } - - normal_float_to_short_v3(mv->no, no); - } - -cleanup: - MEM_freeN(tnorms); - - if (fnors != r_faceNors) { - MEM_freeN(fnors); - } -} - void BKE_mesh_calc_normals_looptri(MVert *mverts, int numVerts, const MLoop *mloop, @@ -1320,7 +1262,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli } // print_v2("new clnors", clnors_avg); } - /* Extra bonus: since smallstack is local to this func, + /* Extra bonus: since small-stack is local to this function, * no more need to empty it at all cost! */ BKE_lnor_space_custom_data_to_normal(lnor_space, *clnor_ref, lnor); @@ -1336,7 +1278,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli copy_v3_v3(nor, lnor); } } - /* Extra bonus: since smallstack is local to this func, + /* Extra bonus: since small-stack is local to this funcion, * no more need to empty it at all cost! */ } } @@ -3003,14 +2945,14 @@ void BKE_mesh_tangent_loops_to_tessdata(CustomData *fdata, * * \return number of tessellation faces. */ -int BKE_mesh_recalc_tessellation(CustomData *fdata, - CustomData *ldata, - CustomData *pdata, - MVert *mvert, - int totface, - int totloop, - int totpoly, - const bool do_face_nor_copy) +int BKE_mesh_tessface_calc_ex(CustomData *fdata, + CustomData *ldata, + CustomData *pdata, + MVert *mvert, + int totface, + int totloop, + int totpoly, + const bool do_face_nor_copy) { /* use this to avoid locking pthread for _every_ polygon * and calling the fill function */ diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c index 78c0fa184f4..d908a248a28 100644 --- a/source/blender/blenkernel/intern/mesh_mapping.c +++ b/source/blender/blenkernel/intern/mesh_mapping.c @@ -845,7 +845,7 @@ static bool poly_is_island_boundary_smooth_cb(const MPoly *mp, const MPoly *mp_other = (mp == &mpoly_array[edge_poly_map->indices[0]]) ? &mpoly_array[edge_poly_map->indices[1]] : &mpoly_array[edge_poly_map->indices[0]]; - return (mp_other->flag & ME_SMOOTH) != 0; + return (mp_other->flag & ME_SMOOTH) == 0; } return true; } diff --git a/source/blender/blenkernel/intern/mesh_merge.c b/source/blender/blenkernel/intern/mesh_merge.c index 71cc20c78b7..ae808b85323 100644 --- a/source/blender/blenkernel/intern/mesh_merge.c +++ b/source/blender/blenkernel/intern/mesh_merge.c @@ -235,7 +235,7 @@ static bool poly_gset_compare_fn(const void *k1, const void *k2) * but the additional checks are costly and not necessary in the case of mirror, * because each vertex is only merged to its own mirror. * - * \note #BKE_mesh_recalc_tessellation has to run on the returned DM + * \note #BKE_mesh_tessface_calc_ex has to run on the returned DM * if you want to access tessfaces. */ Mesh *BKE_mesh_merge_verts(Mesh *mesh, diff --git a/source/blender/blenkernel/intern/mesh_remap.c b/source/blender/blenkernel/intern/mesh_remap.c index db158ca8fb2..834008ca1ac 100644 --- a/source/blender/blenkernel/intern/mesh_remap.c +++ b/source/blender/blenkernel/intern/mesh_remap.c @@ -291,7 +291,7 @@ void BKE_mesh_remap_find_best_match_from_mesh(const MVert *verts_dst, float best_match = FLT_MAX, match; const int numverts_src = me_src->totvert; - float(*vcos_src)[3] = BKE_mesh_vertexCos_get(me_src, NULL); + float(*vcos_src)[3] = BKE_mesh_vert_coords_alloc(me_src, NULL); mesh_calc_eigen_matrix(NULL, (const float(*)[3])vcos_src, numverts_src, mat_src); mesh_calc_eigen_matrix(verts_dst, NULL, numverts_dst, mat_dst); @@ -548,7 +548,7 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode, } else if (ELEM(mode, MREMAP_MODE_VERT_EDGE_NEAREST, MREMAP_MODE_VERT_EDGEINTERP_NEAREST)) { MEdge *edges_src = me_src->medge; - float(*vcos_src)[3] = BKE_mesh_vertexCos_get(me_src, NULL); + float(*vcos_src)[3] = BKE_mesh_vert_coords_alloc(me_src, NULL); BKE_bvhtree_from_mesh_get(&treedata, me_src, BVHTREE_FROM_EDGES, 2); nearest.index = -1; @@ -602,7 +602,7 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode, MREMAP_MODE_VERT_POLYINTERP_VNORPROJ)) { MPoly *polys_src = me_src->mpoly; MLoop *loops_src = me_src->mloop; - float(*vcos_src)[3] = BKE_mesh_vertexCos_get(me_src, NULL); + float(*vcos_src)[3] = BKE_mesh_vert_coords_alloc(me_src, NULL); size_t tmp_buff_size = MREMAP_DEFAULT_BUFSIZE; float(*vcos)[3] = MEM_mallocN(sizeof(*vcos) * tmp_buff_size, __func__); @@ -752,7 +752,7 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode, const int num_verts_src = me_src->totvert; const int num_edges_src = me_src->totedge; MEdge *edges_src = me_src->medge; - float(*vcos_src)[3] = BKE_mesh_vertexCos_get(me_src, NULL); + float(*vcos_src)[3] = BKE_mesh_vert_coords_alloc(me_src, NULL); MeshElemMap *vert_to_edge_src_map; int *vert_to_edge_src_map_mem; @@ -901,7 +901,7 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode, MEdge *edges_src = me_src->medge; MPoly *polys_src = me_src->mpoly; MLoop *loops_src = me_src->mloop; - float(*vcos_src)[3] = BKE_mesh_vertexCos_get(me_src, NULL); + float(*vcos_src)[3] = BKE_mesh_vert_coords_alloc(me_src, NULL); BKE_bvhtree_from_mesh_get(&treedata, me_src, BVHTREE_FROM_LOOPTRI, 2); @@ -1350,7 +1350,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, size_t islands_res_buff_size = MREMAP_DEFAULT_BUFSIZE; if (!use_from_vert) { - vcos_src = BKE_mesh_vertexCos_get(me_src, NULL); + vcos_src = BKE_mesh_vert_coords_alloc(me_src, NULL); vcos_interp = MEM_mallocN(sizeof(*vcos_interp) * buff_size_interp, __func__); indices_interp = MEM_mallocN(sizeof(*indices_interp) * buff_size_interp, __func__); @@ -1553,7 +1553,9 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, num_verts_active, 0.0, 2, - 6); + 6, + 0, + NULL); } MEM_freeN(verts_active); @@ -1594,7 +1596,9 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, num_looptri_active, 0.0, 2, - 6); + 6, + 0, + NULL); } MEM_freeN(looptri_active); diff --git a/source/blender/blenkernel/intern/multires_reshape.c b/source/blender/blenkernel/intern/multires_reshape.c index d939267ac5a..9947b96105d 100644 --- a/source/blender/blenkernel/intern/multires_reshape.c +++ b/source/blender/blenkernel/intern/multires_reshape.c @@ -891,7 +891,7 @@ bool multiresModifier_reshapeFromObject(struct Depsgraph *depsgraph, Object *src_eval = DEG_get_evaluated_object(depsgraph, src); Mesh *src_mesh_eval = mesh_get_eval_final(depsgraph, scene_eval, src_eval, &CD_MASK_BAREMESH); int num_deformed_verts; - float(*deformed_verts)[3] = BKE_mesh_vertexCos_get(src_mesh_eval, &num_deformed_verts); + float(*deformed_verts)[3] = BKE_mesh_vert_coords_alloc(src_mesh_eval, &num_deformed_verts); bool result = multires_reshape_from_vertcos( depsgraph, dst, &reshape_mmd, deformed_verts, num_deformed_verts, false); MEM_freeN(deformed_verts); @@ -926,7 +926,7 @@ bool multiresModifier_reshapeFromDeformModifier(struct Depsgraph *depsgraph, * deformation modifiers will be applied though). */ Mesh *multires_mesh = BKE_multires_create_mesh(depsgraph, scene_eval, &highest_mmd, object); int num_deformed_verts; - float(*deformed_verts)[3] = BKE_mesh_vertexCos_get(multires_mesh, &num_deformed_verts); + float(*deformed_verts)[3] = BKE_mesh_vert_coords_alloc(multires_mesh, &num_deformed_verts); /* Apply deformation modifier on the multires, */ const ModifierEvalContext modifier_ctx = { .depsgraph = depsgraph, diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 986571e34bd..2eba71fa6bd 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -1406,6 +1406,7 @@ bNodeTree *ntreeAddTree(Main *bmain, const char *name, const char *idname) } else { ntree = MEM_callocN(sizeof(bNodeTree), "new node tree"); + ntree->id.flag |= LIB_PRIVATE_DATA; *((short *)ntree->id.name) = ID_NT; BLI_strncpy(ntree->id.name + 2, name, sizeof(ntree->id.name)); } @@ -2172,6 +2173,7 @@ void ntreeSetOutput(bNodeTree *ntree) * might be different for editor or for "real" use... */ } +/* Returns the private NodeTree object of the datablock, if it has one. */ bNodeTree *ntreeFromID(const ID *id) { switch (GS(id->name)) { @@ -2192,6 +2194,28 @@ bNodeTree *ntreeFromID(const ID *id) } } +/* Finds and returns the datablock that privately owns the given tree, or NULL. */ +ID *BKE_node_tree_find_owner_ID(Main *bmain, struct bNodeTree *ntree) +{ + ListBase *lists[] = {&bmain->materials, + &bmain->lights, + &bmain->worlds, + &bmain->textures, + &bmain->scenes, + &bmain->linestyles, + NULL}; + + for (int i = 0; lists[i] != NULL; i++) { + LISTBASE_FOREACH (ID *, id, lists[i]) { + if (ntreeFromID(id) == ntree) { + return id; + } + } + } + + return NULL; +} + void ntreeMakeLocal(Main *bmain, bNodeTree *ntree, bool id_in_mainlist, const bool lib_local) { BKE_id_make_local_generic(bmain, &ntree->id, id_in_mainlist, lib_local); @@ -2799,6 +2823,16 @@ int nodeSocketIsHidden(bNodeSocket *sock) return ((sock->flag & (SOCK_HIDDEN | SOCK_UNAVAIL)) != 0); } +void nodeSetSocketAvailability(bNodeSocket *sock, bool is_available) +{ + if (is_available) { + sock->flag &= ~SOCK_UNAVAIL; + } + else { + sock->flag |= SOCK_UNAVAIL; + } +} + /* ************** Node Clipboard *********** */ #define USE_NODE_CB_VALIDATE @@ -3222,11 +3256,6 @@ void ntreeTagUsedSockets(bNodeTree *ntree) } for (link = ntree->links.first; link; link = link->next) { - /* link is unused if either side is disabled */ - if ((link->fromsock->flag & SOCK_UNAVAIL) || (link->tosock->flag & SOCK_UNAVAIL)) { - continue; - } - link->fromsock->flag |= SOCK_IN_USE; link->tosock->flag |= SOCK_IN_USE; } @@ -3928,6 +3957,7 @@ static void registerShaderNodes(void) register_node_type_sh_tex_brick(); register_node_type_sh_tex_pointdensity(); register_node_type_sh_tex_ies(); + register_node_type_sh_tex_white_noise(); } static void registerTextureNodes(void) @@ -3954,6 +3984,7 @@ static void registerTextureNodes(void) register_node_type_sh_tangent(); register_node_type_sh_normal_map(); register_node_type_sh_hair_info(); + register_node_type_sh_volume_info(); register_node_type_tex_checker(); register_node_type_tex_texture(); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index d95c02cdf7f..ed517bfc513 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -2985,6 +2985,15 @@ bool BKE_object_empty_image_data_is_visible_in_view3d(const Object *ob, const Re } } + if (visibility_flag & OB_EMPTY_IMAGE_HIDE_NON_AXIS_ALIGNED) { + float proj[3]; + project_plane_v3_v3v3(proj, ob->obmat[2], rv3d->viewinv[2]); + const float proj_length_sq = len_squared_v3(proj); + if (proj_length_sq > 1e-5f) { + return false; + } + } + return true; } @@ -3587,7 +3596,7 @@ bool BKE_object_shapekey_free(Main *bmain, Object *ob) BKE_id_free_us(bmain, key); - return false; + return true; } bool BKE_object_shapekey_remove(Main *bmain, Object *ob, KeyBlock *kb) @@ -3871,7 +3880,7 @@ int BKE_object_scenes_users_get(Main *bmain, Object *ob) { int num_scenes = 0; for (Scene *scene = bmain->scenes.first; scene != NULL; scene = scene->id.next) { - if (BKE_collection_has_object_recursive(BKE_collection_master(scene), ob)) { + if (BKE_collection_has_object_recursive(scene->master_collection, ob)) { num_scenes++; } } diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c index 9b717650e8e..3a330ea0d5a 100644 --- a/source/blender/blenkernel/intern/object_update.c +++ b/source/blender/blenkernel/intern/object_update.c @@ -436,7 +436,7 @@ void BKE_object_eval_eval_base_flags(Depsgraph *depsgraph, BKE_base_eval_flags(base); /* For render, compute base visibility again since BKE_base_eval_flags - * assumed viewport visibility. Selectability does not matter here. */ + * assumed viewport visibility. Select-ability does not matter here. */ if (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER) { if (base->flag & BASE_ENABLED_RENDER) { base->flag |= BASE_VISIBLE; diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index 39fb668c873..fcceebc3913 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -519,7 +519,7 @@ static void ocean_compute_htilda(void *__restrict userdata, int j; - /* note the <= _N/2 here, see the fftw doco + /* Note the <= _N/2 here, see the FFTW documentation * about the mechanics of the complex->real fft storage. */ for (j = 0; j <= o->_N / 2; ++j) { fftw_complex exp_param1; diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 4a41ffbfa8c..a46bb36c883 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -1222,10 +1222,10 @@ static void sculpt_update_object( BKE_sculptsession_free_deformMats(ss); ss->orig_cos = (ss->kb) ? BKE_keyblock_convert_to_vertcos(ob, ss->kb) : - BKE_mesh_vertexCos_get(me, NULL); + BKE_mesh_vert_coords_alloc(me, NULL); BKE_crazyspace_build_sculpt(depsgraph, scene, ob, &ss->deform_imats, &ss->deform_cos); - BKE_pbvh_apply_vertCos(ss->pbvh, ss->deform_cos, me->totvert); + BKE_pbvh_vert_coords_apply(ss->pbvh, ss->deform_cos, me->totvert); for (a = 0; a < me->totvert; ++a) { invert_m3(ss->deform_imats[a]); @@ -1242,14 +1242,14 @@ static void sculpt_update_object( /* if pbvh is deformed, key block is already applied to it */ if (ss->kb) { - bool pbvh_deformed = BKE_pbvh_isDeformed(ss->pbvh); + bool pbvh_deformed = BKE_pbvh_is_deformed(ss->pbvh); if (!pbvh_deformed || ss->deform_cos == NULL) { float(*vertCos)[3] = BKE_keyblock_convert_to_vertcos(ob, ss->kb); if (vertCos) { if (!pbvh_deformed) { /* apply shape keys coordinates to PBVH */ - BKE_pbvh_apply_vertCos(ss->pbvh, vertCos, me->totvert); + BKE_pbvh_vert_coords_apply(ss->pbvh, vertCos, me->totvert); } if (ss->deform_cos == NULL) { ss->deform_cos = vertCos; @@ -1477,8 +1477,8 @@ static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform) const bool is_deformed = check_sculpt_object_deformed(ob, true); if (is_deformed && me_eval_deform != NULL) { int totvert; - float(*v_cos)[3] = BKE_mesh_vertexCos_get(me_eval_deform, &totvert); - BKE_pbvh_apply_vertCos(pbvh, v_cos, totvert); + float(*v_cos)[3] = BKE_mesh_vert_coords_alloc(me_eval_deform, &totvert); + BKE_pbvh_vert_coords_apply(pbvh, v_cos, totvert); MEM_freeN(v_cos); } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index ffeba0148a2..2de8d4a643a 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -2691,7 +2691,7 @@ static void psys_thread_create_path(ParticleTask *task, pa = &psys->particles[cpa->parent]; par = pcache[cpa->parent]; - /* If particle is unexisting, try to pick a viable parent from particles + /* If particle is non-existing, try to pick a viable parent from particles * used for interpolation. */ for (k = 0; k < 4 && pa && (pa->flag & PARS_UNEXIST); k++) { if (cpa->pa[k] >= 0) { diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 31484b59127..e328ae8952e 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -3490,10 +3490,10 @@ static void do_hair_dynamics(ParticleSimulationData *sim) psys->clmd->sim_parms->effector_weights = psys->part->effector_weights; BKE_id_copy_ex(NULL, &psys->hair_in_mesh->id, (ID **)&psys->hair_out_mesh, LIB_ID_COPY_LOCALIZE); - deformedVerts = BKE_mesh_vertexCos_get(psys->hair_out_mesh, NULL); + deformedVerts = BKE_mesh_vert_coords_alloc(psys->hair_out_mesh, NULL); clothModifier_do( psys->clmd, sim->depsgraph, sim->scene, sim->ob, psys->hair_in_mesh, deformedVerts); - BKE_mesh_apply_vert_coords(psys->hair_out_mesh, deformedVerts); + BKE_mesh_vert_coords_apply(psys->hair_out_mesh, deformedVerts); MEM_freeN(deformedVerts); diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index 64a16a0e3be..7a8c082842e 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -533,7 +533,7 @@ static void pbvh_build(PBVH *bvh, BB *cb, BBC *prim_bbc, int totprim) * Do a full rebuild with on Mesh data structure. * * \note Unlike mpoly/mloop/verts, looptri is **totally owned** by PBVH - * (which means it may rewrite it if needed, see #BKE_pbvh_apply_vertCos(). + * (which means it may rewrite it if needed, see #BKE_pbvh_vert_coords_apply(). */ void BKE_pbvh_build_mesh(PBVH *bvh, const MPoly *mpoly, @@ -1753,14 +1753,21 @@ static bool pbvh_faces_node_raycast(PBVH *bvh, const PBVHNode *node, float (*origco)[3], const float ray_start[3], + const float ray_normal[3], struct IsectRayPrecalc *isect_precalc, - float *depth) + float *depth, + int *r_active_vertex_index, + float *r_face_normal) { const MVert *vert = bvh->verts; const MLoop *mloop = bvh->mloop; const int *faces = node->prim_indices; int i, totface = node->totprim; bool hit = false; + float min_depth = FLT_MAX; + float location[3] = {0.0f}; + float nearest_vertex_co[3]; + copy_v3_fl(nearest_vertex_co, 0.0f); for (i = 0; i < totface; ++i) { const MLoopTri *lt = &bvh->looptri[faces[i]]; @@ -1787,6 +1794,22 @@ static bool pbvh_faces_node_raycast(PBVH *bvh, vert[mloop[lt->tri[1]].v].co, vert[mloop[lt->tri[2]].v].co, depth); + + if (hit && *depth < min_depth) { + min_depth = *depth; + normal_tri_v3(r_face_normal, + vert[mloop[lt->tri[0]].v].co, + vert[mloop[lt->tri[1]].v].co, + vert[mloop[lt->tri[2]].v].co); + madd_v3_v3v3fl(location, ray_start, ray_normal, *depth); + for (int j = 0; j < 3; j++) { + if (len_squared_v3v3(location, vert[mloop[lt->tri[j]].v].co) < + len_squared_v3v3(location, nearest_vertex_co)) { + copy_v3_v3(nearest_vertex_co, vert[mloop[lt->tri[j]].v].co); + *r_active_vertex_index = mloop[lt->tri[j]].v; + } + } + } } } @@ -1857,8 +1880,11 @@ bool BKE_pbvh_node_raycast(PBVH *bvh, float (*origco)[3], bool use_origco, const float ray_start[3], + const float ray_normal[3], struct IsectRayPrecalc *isect_precalc, - float *depth) + float *depth, + int *active_vertex_index, + float *face_normal) { bool hit = false; @@ -1868,13 +1894,29 @@ bool BKE_pbvh_node_raycast(PBVH *bvh, switch (bvh->type) { case PBVH_FACES: - hit |= pbvh_faces_node_raycast(bvh, node, origco, ray_start, isect_precalc, depth); + hit |= pbvh_faces_node_raycast(bvh, + node, + origco, + ray_start, + ray_normal, + isect_precalc, + depth, + active_vertex_index, + face_normal); break; case PBVH_GRIDS: hit |= pbvh_grids_node_raycast(bvh, node, origco, ray_start, isect_precalc, depth); break; case PBVH_BMESH: - hit = pbvh_bmesh_node_raycast(node, ray_start, isect_precalc, depth, use_origco); + BM_mesh_elem_index_ensure(bvh->bm, BM_VERT); + hit = pbvh_bmesh_node_raycast(node, + ray_start, + ray_normal, + isect_precalc, + depth, + use_origco, + active_vertex_index, + face_normal); break; } @@ -2306,7 +2348,7 @@ void BKE_pbvh_node_layer_disp_free(PBVHNode *node) } } -float (*BKE_pbvh_get_vertCos(PBVH *pbvh))[3] +float (*BKE_pbvh_vert_coords_alloc(PBVH *pbvh))[3] { float(*vertCos)[3] = NULL; @@ -2324,7 +2366,7 @@ float (*BKE_pbvh_get_vertCos(PBVH *pbvh))[3] return vertCos; } -void BKE_pbvh_apply_vertCos(PBVH *pbvh, float (*vertCos)[3], const int totvert) +void BKE_pbvh_vert_coords_apply(PBVH *pbvh, const float (*vertCos)[3], const int totvert) { if (totvert != pbvh->totvert) { BLI_assert(!"PBVH: Given deforming vcos number does not natch PBVH vertex number!"); @@ -2368,7 +2410,7 @@ void BKE_pbvh_apply_vertCos(PBVH *pbvh, float (*vertCos)[3], const int totvert) } } -bool BKE_pbvh_isDeformed(PBVH *pbvh) +bool BKE_pbvh_is_deformed(PBVH *pbvh) { return pbvh->deformed; } diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index 1d8088c6605..c04e172f116 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -1508,12 +1508,18 @@ static bool pbvh_bmesh_collapse_short_edges(EdgeQueueContext *eq_ctx, bool pbvh_bmesh_node_raycast(PBVHNode *node, const float ray_start[3], + const float ray_normal[3], struct IsectRayPrecalc *isect_precalc, float *depth, - bool use_original) + bool use_original, + int *r_active_vertex_index, + float *r_face_normal) { bool hit = false; + float min_depth = FLT_MAX; + float nearest_vertex_co[3] = {0.0f}; + float location[3] = {0.0f}; if (use_original && node->bm_tot_ortri) { for (int i = 0; i < node->bm_tot_ortri; i++) { const int *t = node->bm_ortri[i]; @@ -1538,6 +1544,19 @@ bool pbvh_bmesh_node_raycast(PBVHNode *node, BM_face_as_array_vert_tri(f, v_tri); hit |= ray_face_intersection_tri( ray_start, isect_precalc, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co, depth); + + if (hit && *depth < min_depth) { + min_depth = *depth; + normal_tri_v3(r_face_normal, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co); + madd_v3_v3v3fl(location, ray_start, ray_normal, *depth); + for (int j = 0; j < 3; j++) { + if (len_squared_v3v3(location, v_tri[j]->co) < + len_squared_v3v3(location, nearest_vertex_co)) { + copy_v3_v3(nearest_vertex_co, v_tri[j]->co); + *r_active_vertex_index = BM_elem_index_get(v_tri[j]); + } + } + } } } } diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h index e74a8d43c68..bad103743eb 100644 --- a/source/blender/blenkernel/intern/pbvh_intern.h +++ b/source/blender/blenkernel/intern/pbvh_intern.h @@ -206,9 +206,12 @@ void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag); /* pbvh_bmesh.c */ bool pbvh_bmesh_node_raycast(PBVHNode *node, const float ray_start[3], + const float ray_normal[3], struct IsectRayPrecalc *isect_precalc, float *dist, - bool use_original); + bool use_original, + int *r_active_vertex_index, + float *r_face_normal); bool pbvh_bmesh_node_nearest_to_ray(PBVHNode *node, const float ray_start[3], const float ray_normal[3], diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 13d0f1adb84..a31cb96c6c9 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -1831,6 +1831,10 @@ void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, Object *ob, RigidBodyWorld *r pid->file_type = PTCACHE_FILE_PTCACHE; } +/** + * \param ob: Optional, may be NULL. + * \param scene: Optional may be NULL. + */ PTCacheID BKE_ptcache_id_find(Object *ob, Scene *scene, PointCache *cache) { PTCacheID result = {0}; @@ -1934,40 +1938,45 @@ static bool foreach_object_ptcache( Scene *scene, Object *object, int duplis, ForeachPtcacheCb callback, void *callback_user_data) { PTCacheID pid; - /* Soft body. */ - if (object->soft != NULL) { - BKE_ptcache_id_from_softbody(&pid, object, object->soft); - if (!callback(&pid, callback_user_data)) { + + if (object != NULL) { + /* Soft body. */ + if (object->soft != NULL) { + BKE_ptcache_id_from_softbody(&pid, object, object->soft); + if (!callback(&pid, callback_user_data)) { + return false; + } + } + /* Particle systems. */ + if (!foreach_object_particle_ptcache(object, callback, callback_user_data)) { return false; } + /* Modifiers. */ + if (!foreach_object_modifier_ptcache(object, callback, callback_user_data)) { + return false; + } + /* Consider all object in dupli groups to be part of the same object, + * for baking with linking dupligroups. Once we have better overrides + * this can be revisited so users select the local objects directly. */ + if (scene != NULL && (duplis-- > 0) && (object->instance_collection != NULL)) { + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (object->instance_collection, current_object) { + if (current_object == object) { + continue; + } + foreach_object_ptcache(scene, current_object, duplis, callback, callback_user_data); + } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; + } } - /* Particle systems. */ - if (!foreach_object_particle_ptcache(object, callback, callback_user_data)) { - return false; - } - /* Modifiers. */ - if (!foreach_object_modifier_ptcache(object, callback, callback_user_data)) { - return false; - } + /* Rigid body. */ - if (scene != NULL && object->rigidbody_object != NULL && scene->rigidbody_world != NULL) { + if (scene != NULL && (object == NULL || object->rigidbody_object != NULL) && + scene->rigidbody_world != NULL) { BKE_ptcache_id_from_rigidbody(&pid, object, scene->rigidbody_world); if (!callback(&pid, callback_user_data)) { return false; } } - /* Consider all object in dupli groups to be part of the same object, - * for baking with linking dupligroups. Once we have better overrides - * this can be revisited so users select the local objects directly. */ - if (scene != NULL && (duplis-- > 0) && (object->instance_collection != NULL)) { - FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (object->instance_collection, current_object) { - if (current_object == object) { - continue; - } - foreach_object_ptcache(scene, current_object, duplis, callback, callback_user_data); - } - FOREACH_COLLECTION_OBJECT_RECURSIVE_END; - } return true; } diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index ec73406c14c..514f000d73d 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -1452,7 +1452,7 @@ void BKE_rigidbody_remove_object(Main *bmain, Scene *scene, Object *ob) /* Some users seems to find it funny to use a view-layer instancing collection * as RBW collection... Despite this being a bad (ab)use of the system, avoid losing objects * when we remove them from RB simulation. */ - BKE_collection_object_add(bmain, BKE_collection_master(scene), ob); + BKE_collection_object_add(bmain, scene->master_collection, ob); } BKE_collection_object_remove(bmain, rbw->group, ob, false); } diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 3440c8dfb69..c4ce0cf6ed7 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -266,6 +266,8 @@ void BKE_scene_copy_data(Main *bmain, Scene *sce_dst, const Scene *sce_src, cons { /* We never handle usercount here for own data. */ const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT; + /* We always need allocation of our private ID data. */ + const int flag_private_id_data = flag_subdata & ~LIB_ID_CREATE_NO_ALLOCATE; sce_dst->ed = NULL; sce_dst->depsgraph_hash = NULL; @@ -273,8 +275,10 @@ void BKE_scene_copy_data(Main *bmain, Scene *sce_dst, const Scene *sce_src, cons /* Master Collection */ if (sce_src->master_collection) { - sce_dst->master_collection = BKE_collection_copy_master( - bmain, sce_src->master_collection, flag); + BKE_id_copy_ex(bmain, + (ID *)sce_src->master_collection, + (ID **)&sce_dst->master_collection, + flag_private_id_data); } /* View Layers */ @@ -292,10 +296,13 @@ void BKE_scene_copy_data(Main *bmain, Scene *sce_dst, const Scene *sce_src, cons BKE_keyingsets_copy(&(sce_dst->keyingsets), &(sce_src->keyingsets)); if (sce_src->nodetree) { - /* Note: nodetree is *not* in bmain, however this specific case is handled at lower level - * (see BKE_libblock_copy_ex()). */ - BKE_id_copy_ex(bmain, (ID *)sce_src->nodetree, (ID **)&sce_dst->nodetree, flag); - BKE_libblock_relink_ex(bmain, sce_dst->nodetree, (void *)(&sce_src->id), &sce_dst->id, false); + BKE_id_copy_ex( + bmain, (ID *)sce_src->nodetree, (ID **)&sce_dst->nodetree, flag_private_id_data); + BKE_libblock_relink_ex(bmain, + sce_dst->nodetree, + (void *)(&sce_src->id), + &sce_dst->id, + ID_REMAP_SKIP_NEVER_NULL_USAGE); } if (sce_src->rigidbody_world) { diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index b151bc7f092..89f3f9ef9fd 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -1646,7 +1646,7 @@ static void do_blend_effect_float( case SEQ_TYPE_DARKEN: apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_darken_float); break; - case SEQ_TYPE_BURN: + case SEQ_TYPE_COLOR_BURN: apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_burn_float); break; case SEQ_TYPE_LINEAR_BURN: @@ -1734,7 +1734,7 @@ static void do_blend_effect_byte(float facf0, case SEQ_TYPE_DARKEN: apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_darken_byte); break; - case SEQ_TYPE_BURN: + case SEQ_TYPE_COLOR_BURN: apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_burn_byte); break; case SEQ_TYPE_LINEAR_BURN: @@ -4130,7 +4130,7 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type) break; case SEQ_TYPE_SCREEN: case SEQ_TYPE_OVERLAY: - case SEQ_TYPE_BURN: + case SEQ_TYPE_COLOR_BURN: case SEQ_TYPE_LINEAR_BURN: case SEQ_TYPE_DARKEN: case SEQ_TYPE_LIGHTEN: diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 20736e28a53..d3b72fb295d 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -2705,7 +2705,7 @@ static void mesh_to_softbody(Scene *scene, Object *ob) for (a = 0; a < me->totvert; a++, bp++) { /* get scalar values needed *per vertex* from vertex group functions, - * so we can *paint* them nicly .. + * so we can *paint* them nicely .. * they are normalized [0.0..1.0] so may be we need amplitude for scale * which can be done by caller but still .. i'd like it to go this way */ diff --git a/source/blender/blenkernel/intern/studiolight.c b/source/blender/blenkernel/intern/studiolight.c index 6e83f5d75e2..b3f2a624ebe 100644 --- a/source/blender/blenkernel/intern/studiolight.c +++ b/source/blender/blenkernel/intern/studiolight.c @@ -46,13 +46,16 @@ #include "MEM_guardedalloc.h" +#include "intern/openexr/openexr_multi.h" + /* Statics */ static ListBase studiolights; static int last_studiolight_id = 0; #define STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE 96 #define STUDIOLIGHT_IRRADIANCE_EQUIRECT_HEIGHT 32 #define STUDIOLIGHT_IRRADIANCE_EQUIRECT_WIDTH (STUDIOLIGHT_IRRADIANCE_EQUIRECT_HEIGHT * 2) - +#define STUDIOLIGHT_PASSNAME_DIFFUSE "diffuse" +#define STUDIOLIGHT_PASSNAME_SPECULAR "specular" /* * The method to calculate the irradiance buffers * The irradiance buffer is only shown in the background when in LookDev. @@ -152,6 +155,10 @@ static void studiolight_free(struct StudioLight *sl) GPU_TEXTURE_SAFE_FREE(sl->equirect_irradiance_gputexture); IMB_SAFE_FREE(sl->equirect_radiance_buffer); IMB_SAFE_FREE(sl->equirect_irradiance_buffer); + GPU_TEXTURE_SAFE_FREE(sl->matcap_diffuse.gputexture); + GPU_TEXTURE_SAFE_FREE(sl->matcap_specular.gputexture); + IMB_SAFE_FREE(sl->matcap_diffuse.ibuf); + IMB_SAFE_FREE(sl->matcap_specular.ibuf); MEM_SAFE_FREE(sl->path_irr_cache); MEM_SAFE_FREE(sl->path_sh_cache); MEM_SAFE_FREE(sl); @@ -342,72 +349,232 @@ static void cube_face_uv_to_direction(float r_dir[3], float x, float y, int face normalize_v3(r_dir); } +typedef struct MultilayerConvertContext { + int num_diffuse_channels; + float *diffuse_pass; + int num_specular_channels; + float *specular_pass; +} MultilayerConvertContext; + +static void *studiolight_multilayer_addview(void *UNUSED(base), const char *UNUSED(view_name)) +{ + return NULL; +} +static void *studiolight_multilayer_addlayer(void *base, const char *UNUSED(layer_name)) +{ + return base; +} + +/* Convert a multilayer pass to ImBuf channel 4 float buffer. + * NOTE: Parameter rect will become invalid. Do not use rect after calling this + * function */ +static float *studiolight_multilayer_convert_pass(ImBuf *ibuf, + float *rect, + const unsigned int channels) +{ + if (channels == 4) { + return rect; + } + else { + float *new_rect = MEM_callocN(sizeof(float[4]) * ibuf->x * ibuf->y, __func__); + + IMB_buffer_float_from_float(new_rect, + rect, + channels, + IB_PROFILE_LINEAR_RGB, + IB_PROFILE_LINEAR_RGB, + false, + ibuf->x, + ibuf->y, + ibuf->x, + ibuf->x); + + MEM_freeN(rect); + return new_rect; + } +} + +static void studiolight_multilayer_addpass(void *base, + void *UNUSED(lay), + const char *pass_name, + float *rect, + int num_channels, + const char *UNUSED(chan_id), + const char *UNUSED(view_name)) +{ + MultilayerConvertContext *ctx = base; + /* NOTE: This function must free pass pixels data if it is not used, this + * is how IMB_exr_multilayer_convert() is working. */ + /* If we've found a first combined pass, skip all the rest ones. */ + if (STREQ(pass_name, STUDIOLIGHT_PASSNAME_DIFFUSE)) { + ctx->diffuse_pass = rect; + ctx->num_diffuse_channels = num_channels; + } + else if (STREQ(pass_name, STUDIOLIGHT_PASSNAME_SPECULAR)) { + ctx->specular_pass = rect; + ctx->num_specular_channels = num_channels; + } + else { + MEM_freeN(rect); + } +} + static void studiolight_load_equirect_image(StudioLight *sl) { if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) { - ImBuf *ibuf = NULL; - ibuf = IMB_loadiffname(sl->path, 0, NULL); - if (ibuf == NULL) { - float *colbuf = MEM_mallocN(sizeof(float[4]), __func__); - copy_v4_fl4(colbuf, 1.0f, 0.0f, 1.0f, 1.0f); - ibuf = IMB_allocFromBuffer(NULL, colbuf, 1, 1); + ImBuf *ibuf = IMB_loadiffname(sl->path, IB_multilayer, NULL); + ImBuf *specular_ibuf = NULL; + ImBuf *diffuse_ibuf = NULL; + const bool failed = (ibuf == NULL); + + if (ibuf) { + if (ibuf->ftype == IMB_FTYPE_OPENEXR && ibuf->userdata) { + /* the read file is a multilayered openexr file (userdata != NULL) + * This file is currently only supported for MATCAPS where + * the first found 'diffuse' pass will be used for diffuse lighting + * and the first found 'specular' pass will be used for specular lighting */ + MultilayerConvertContext ctx = {0}; + IMB_exr_multilayer_convert(ibuf->userdata, + &ctx, + &studiolight_multilayer_addview, + &studiolight_multilayer_addlayer, + &studiolight_multilayer_addpass); + + /* `ctx.diffuse_pass` and `ctx.specular_pass` can be freed inside + * `studiolight_multilayer_convert_pass` when conversion happens. + * When not converted we move the ownership of the buffer to the + * `converted_pass`. We only need to free `converted_pass` as it holds + * the unmodified allocation from the `ctx.*_pass` or the converted data. + */ + if (ctx.diffuse_pass != NULL) { + float *converted_pass = studiolight_multilayer_convert_pass( + ibuf, ctx.diffuse_pass, ctx.num_diffuse_channels); + diffuse_ibuf = IMB_allocFromBuffer( + NULL, converted_pass, ibuf->x, ibuf->y, ctx.num_diffuse_channels); + MEM_freeN(converted_pass); + } + + if (ctx.specular_pass != NULL) { + float *converted_pass = studiolight_multilayer_convert_pass( + ibuf, ctx.specular_pass, ctx.num_specular_channels); + specular_ibuf = IMB_allocFromBuffer( + NULL, converted_pass, ibuf->x, ibuf->y, ctx.num_specular_channels); + MEM_freeN(converted_pass); + } + + IMB_exr_close(ibuf->userdata); + ibuf->userdata = NULL; + IMB_freeImBuf(ibuf); + ibuf = NULL; + } + else { + /* read file is an single layer openexr file or the read file isn't + * an openexr file */ + IMB_float_from_rect(ibuf); + diffuse_ibuf = ibuf; + ibuf = NULL; + } + } + + if (diffuse_ibuf == NULL) { + /* Create 1x1 diffuse buffer, in case image failed to load or if there was + * only a specular pass in the multilayer file or no passes were found. */ + const float black[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + const float magenta[4] = {1.0f, 0.0f, 1.0f, 1.0f}; + diffuse_ibuf = IMB_allocFromBuffer( + NULL, (failed || (specular_ibuf == NULL)) ? magenta : black, 1, 1, 4); + } + + if ((sl->flag & STUDIOLIGHT_TYPE_MATCAP)) { + sl->matcap_diffuse.ibuf = diffuse_ibuf; + sl->matcap_specular.ibuf = specular_ibuf; + if (specular_ibuf != NULL) { + sl->flag |= STUDIOLIGHT_SPECULAR_HIGHLIGHT_PASS; + } + } + else { + sl->equirect_radiance_buffer = diffuse_ibuf; + if (specular_ibuf != NULL) { + IMB_freeImBuf(specular_ibuf); + } } - IMB_float_from_rect(ibuf); - sl->equirect_radiance_buffer = ibuf; } + sl->flag |= STUDIOLIGHT_EXTERNAL_IMAGE_LOADED; } static void studiolight_create_equirect_radiance_gputexture(StudioLight *sl) { if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) { - char error[256]; BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EXTERNAL_IMAGE_LOADED); ImBuf *ibuf = sl->equirect_radiance_buffer; - if (sl->flag & STUDIOLIGHT_TYPE_MATCAP) { - float *gpu_matcap_3components = MEM_callocN(sizeof(float[3]) * ibuf->x * ibuf->y, __func__); + sl->equirect_radiance_gputexture = GPU_texture_create_2d( + ibuf->x, ibuf->y, GPU_RGBA16F, ibuf->rect_float, NULL); + GPUTexture *tex = sl->equirect_radiance_gputexture; + GPU_texture_bind(tex, 0); + GPU_texture_filter_mode(tex, true); + GPU_texture_wrap_mode(tex, true); + GPU_texture_unbind(tex); + } + sl->flag |= STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE; +} - float(*offset4)[4] = (float(*)[4])ibuf->rect_float; - float(*offset3)[3] = (float(*)[3])gpu_matcap_3components; - for (int i = 0; i < ibuf->x * ibuf->y; i++, offset4++, offset3++) { - copy_v3_v3(*offset3, *offset4); - } +static void studiolight_create_matcap_gputexture(StudioLightImage *sli) +{ + BLI_assert(sli->ibuf); + ImBuf *ibuf = sli->ibuf; + float *gpu_matcap_3components = MEM_callocN(sizeof(float[3]) * ibuf->x * ibuf->y, __func__); + + float(*offset4)[4] = (float(*)[4])ibuf->rect_float; + float(*offset3)[3] = (float(*)[3])gpu_matcap_3components; + for (int i = 0; i < ibuf->x * ibuf->y; i++, offset4++, offset3++) { + copy_v3_v3(*offset3, *offset4); + } + + sli->gputexture = GPU_texture_create_nD(ibuf->x, + ibuf->y, + 0, + 2, + gpu_matcap_3components, + GPU_R11F_G11F_B10F, + GPU_DATA_FLOAT, + 0, + false, + NULL); + MEM_SAFE_FREE(gpu_matcap_3components); +} - sl->equirect_radiance_gputexture = GPU_texture_create_nD(ibuf->x, - ibuf->y, - 0, - 2, - gpu_matcap_3components, - GPU_R11F_G11F_B10F, - GPU_DATA_FLOAT, - 0, - false, - error); - - MEM_SAFE_FREE(gpu_matcap_3components); +static void studiolight_create_matcap_diffuse_gputexture(StudioLight *sl) +{ + if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) { + if (sl->flag & STUDIOLIGHT_TYPE_MATCAP) { + BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EXTERNAL_IMAGE_LOADED); + studiolight_create_matcap_gputexture(&sl->matcap_diffuse); } - else { - sl->equirect_radiance_gputexture = GPU_texture_create_2d( - ibuf->x, ibuf->y, GPU_RGBA16F, ibuf->rect_float, error); - GPUTexture *tex = sl->equirect_radiance_gputexture; - GPU_texture_bind(tex, 0); - GPU_texture_filter_mode(tex, true); - GPU_texture_wrap_mode(tex, true); - GPU_texture_unbind(tex); + } + sl->flag |= STUDIOLIGHT_MATCAP_DIFFUSE_GPUTEXTURE; +} +static void studiolight_create_matcap_specular_gputexture(StudioLight *sl) +{ + if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) { + if (sl->flag & STUDIOLIGHT_TYPE_MATCAP) { + BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EXTERNAL_IMAGE_LOADED); + if (sl->matcap_specular.ibuf) { + studiolight_create_matcap_gputexture(&sl->matcap_specular); + } } } - sl->flag |= STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE; + sl->flag |= STUDIOLIGHT_MATCAP_SPECULAR_GPUTEXTURE; } static void studiolight_create_equirect_irradiance_gputexture(StudioLight *sl) { if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) { - char error[256]; BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECT_IRRADIANCE_IMAGE_CALCULATED); ImBuf *ibuf = sl->equirect_irradiance_buffer; sl->equirect_irradiance_gputexture = GPU_texture_create_2d( - ibuf->x, ibuf->y, GPU_RGBA16F, ibuf->rect_float, error); + ibuf->x, ibuf->y, GPU_RGBA16F, ibuf->rect_float, NULL); GPUTexture *tex = sl->equirect_irradiance_gputexture; GPU_texture_bind(tex, 0); GPU_texture_filter_mode(tex, true); @@ -457,32 +624,32 @@ static void studiolight_calculate_radiance_cubemap_buffers(StudioLight *sl) /* front */ studiolight_calculate_radiance_buffer(ibuf, colbuf, 0, 2, 1, 1, -1, 1); sl->radiance_cubemap_buffers[STUDIOLIGHT_Y_POS] = IMB_allocFromBuffer( - NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE); + NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, 4); /* back */ studiolight_calculate_radiance_buffer(ibuf, colbuf, 0, 2, 1, 1, 1, -1); sl->radiance_cubemap_buffers[STUDIOLIGHT_Y_NEG] = IMB_allocFromBuffer( - NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE); + NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, 4); /* left */ studiolight_calculate_radiance_buffer(ibuf, colbuf, 2, 1, 0, 1, -1, 1); sl->radiance_cubemap_buffers[STUDIOLIGHT_X_POS] = IMB_allocFromBuffer( - NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE); + NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, 4); /* right */ studiolight_calculate_radiance_buffer(ibuf, colbuf, 2, 1, 0, -1, -1, -1); sl->radiance_cubemap_buffers[STUDIOLIGHT_X_NEG] = IMB_allocFromBuffer( - NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE); + NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, 4); /* top */ studiolight_calculate_radiance_buffer(ibuf, colbuf, 0, 1, 2, -1, -1, 1); sl->radiance_cubemap_buffers[STUDIOLIGHT_Z_NEG] = IMB_allocFromBuffer( - NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE); + NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, 4); /* bottom */ studiolight_calculate_radiance_buffer(ibuf, colbuf, 0, 1, 2, 1, -1, -1); sl->radiance_cubemap_buffers[STUDIOLIGHT_Z_POS] = IMB_allocFromBuffer( - NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE); + NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, 4); #if 0 IMB_saveiff(sl->radiance_cubemap_buffers[STUDIOLIGHT_X_POS], @@ -603,7 +770,8 @@ static void studiolight_spherical_harmonics_calculate_coefficients(StudioLight * /* Take monochrome SH as input */ static float studiolight_spherical_harmonics_lambda_get(float *sh, float max_laplacian) { - /* From Peter-Pike Sloan's Stupid SH Tricks http://www.ppsloan.org/publications/StupidSH36.pdf */ + /* From Peter-Pike Sloan's Stupid SH Tricks http://www.ppsloan.org/publications/StupidSH36.pdf + */ float table_l[STUDIOLIGHT_SH_BANDS]; float table_b[STUDIOLIGHT_SH_BANDS]; @@ -720,7 +888,6 @@ BLI_INLINE void studiolight_spherical_harmonics_eval(StudioLight *sl, } return; #else - /* L0 */ mul_v3_v3fl(color, sl->spherical_harmonics_coefs[0], 0.282095f); # if STUDIOLIGHT_SH_BANDS > 1 /* L1 */ @@ -1045,7 +1212,8 @@ static void studiolight_calculate_irradiance_equirect_image(StudioLight *sl) sl->equirect_irradiance_buffer = IMB_allocFromBuffer(NULL, colbuf, STUDIOLIGHT_IRRADIANCE_EQUIRECT_WIDTH, - STUDIOLIGHT_IRRADIANCE_EQUIRECT_HEIGHT); + STUDIOLIGHT_IRRADIANCE_EQUIRECT_HEIGHT, + 4); MEM_freeN(colbuf); #ifdef STUDIOLIGHT_IRRADIANCE_METHOD_RADIANCE @@ -1196,7 +1364,8 @@ static void studiolight_matcap_preview(uint *icon_buffer, StudioLight *sl, bool { BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EXTERNAL_IMAGE_LOADED); - ImBuf *ibuf = sl->equirect_radiance_buffer; + ImBuf *diffuse_buffer = sl->matcap_diffuse.ibuf; + ImBuf *specular_buffer = sl->matcap_specular.ibuf; ITER_PIXELS (uint, icon_buffer, 1, STUDIOLIGHT_ICON_SIZE, STUDIOLIGHT_ICON_SIZE) { float dy = RESCALE_COORD(y); @@ -1206,7 +1375,15 @@ static void studiolight_matcap_preview(uint *icon_buffer, StudioLight *sl, bool } float color[4]; - nearest_interpolation_color(ibuf, NULL, color, dx * ibuf->x - 1.0f, dy * ibuf->y - 1.0f); + float u = dx * diffuse_buffer->x - 1.0f; + float v = dy * diffuse_buffer->y - 1.0f; + nearest_interpolation_color(diffuse_buffer, NULL, color, u, v); + + if (specular_buffer) { + float specular[4]; + nearest_interpolation_color(specular_buffer, NULL, specular, u, v); + add_v3_v3(color, specular); + } uint alphamask = alpha_circle_mask(dx, dy, 0.5f - texel_size[0], 0.5f); @@ -1303,9 +1480,9 @@ void BKE_studiolight_default(SolidLight lights[4], float light_ambient[4]) void BKE_studiolight_init(void) { /* Add default studio light */ - StudioLight *sl = studiolight_create(STUDIOLIGHT_INTERNAL | - STUDIOLIGHT_SPHERICAL_HARMONICS_COEFFICIENTS_CALCULATED | - STUDIOLIGHT_TYPE_STUDIO); + StudioLight *sl = studiolight_create( + STUDIOLIGHT_INTERNAL | STUDIOLIGHT_SPHERICAL_HARMONICS_COEFFICIENTS_CALCULATED | + STUDIOLIGHT_TYPE_STUDIO | STUDIOLIGHT_SPECULAR_HIGHLIGHT_PASS); BLI_strncpy(sl->name, "Default", FILE_MAXFILE); BLI_addtail(&studiolights, sl); @@ -1317,7 +1494,8 @@ void BKE_studiolight_init(void) if (!BKE_appdir_app_is_portable_install()) { studiolight_add_files_from_datafolder(BLENDER_USER_DATAFILES, STUDIOLIGHT_LIGHTS_FOLDER, - STUDIOLIGHT_TYPE_STUDIO | STUDIOLIGHT_USER_DEFINED); + STUDIOLIGHT_TYPE_STUDIO | STUDIOLIGHT_USER_DEFINED | + STUDIOLIGHT_SPECULAR_HIGHLIGHT_PASS); studiolight_add_files_from_datafolder(BLENDER_USER_DATAFILES, STUDIOLIGHT_WORLD_FOLDER, STUDIOLIGHT_TYPE_WORLD | STUDIOLIGHT_USER_DEFINED); @@ -1325,8 +1503,10 @@ void BKE_studiolight_init(void) STUDIOLIGHT_MATCAP_FOLDER, STUDIOLIGHT_TYPE_MATCAP | STUDIOLIGHT_USER_DEFINED); } - studiolight_add_files_from_datafolder( - BLENDER_SYSTEM_DATAFILES, STUDIOLIGHT_LIGHTS_FOLDER, STUDIOLIGHT_TYPE_STUDIO); + studiolight_add_files_from_datafolder(BLENDER_SYSTEM_DATAFILES, + STUDIOLIGHT_LIGHTS_FOLDER, + STUDIOLIGHT_TYPE_STUDIO | + STUDIOLIGHT_SPECULAR_HIGHLIGHT_PASS); studiolight_add_files_from_datafolder( BLENDER_SYSTEM_DATAFILES, STUDIOLIGHT_WORLD_FOLDER, STUDIOLIGHT_TYPE_WORLD); studiolight_add_files_from_datafolder( @@ -1456,6 +1636,12 @@ void BKE_studiolight_ensure_flag(StudioLight *sl, int flag) studiolight_calculate_irradiance_equirect_image(sl); } } + if ((flag & STUDIOLIGHT_MATCAP_DIFFUSE_GPUTEXTURE)) { + studiolight_create_matcap_diffuse_gputexture(sl); + } + if ((flag & STUDIOLIGHT_MATCAP_SPECULAR_GPUTEXTURE)) { + studiolight_create_matcap_specular_gputexture(sl); + } } /* diff --git a/source/blender/blenkernel/intern/subdiv_mesh.c b/source/blender/blenkernel/intern/subdiv_mesh.c index 1ff9140681f..9d713d1937d 100644 --- a/source/blender/blenkernel/intern/subdiv_mesh.c +++ b/source/blender/blenkernel/intern/subdiv_mesh.c @@ -498,9 +498,14 @@ static bool subdiv_mesh_topology_info(const SubdivForeachContext *foreach_contex const int num_loops, const int num_polygons) { + /* Multires grid data will be applied or become invalid after subdivision, + * so don't try to preserve it and use memory. */ + CustomData_MeshMasks mask = CD_MASK_EVERYTHING; + mask.lmask &= ~CD_MASK_MULTIRES_GRIDS; + SubdivMeshContext *subdiv_context = foreach_context->user_data; - subdiv_context->subdiv_mesh = BKE_mesh_new_nomain_from_template( - subdiv_context->coarse_mesh, num_vertices, num_edges, 0, num_loops, num_polygons); + subdiv_context->subdiv_mesh = BKE_mesh_new_nomain_from_template_ex( + subdiv_context->coarse_mesh, num_vertices, num_edges, 0, num_loops, num_polygons, mask); subdiv_mesh_ctx_cache_custom_data_layers(subdiv_context); subdiv_mesh_prepare_accumulator(subdiv_context, num_vertices); return true; diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 3f57ae169ff..77dc438cd04 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -83,8 +83,6 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, int useSubsurfUv, DerivedMesh *dm, bool use_gpu_backend); -static int ccgDM_use_grid_pbvh(CCGDerivedMesh *ccgdm); - /// static void *arena_alloc(CCGAllocatorHDL a, int numBytes) @@ -1580,221 +1578,6 @@ static void ccgDM_copyFinalPolyArray(DerivedMesh *dm, MPoly *mpoly) } } -static void ccgdm_getVertCos(DerivedMesh *dm, float (*cos)[3]) -{ - CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm; - CCGSubSurf *ss = ccgdm->ss; - int edgeSize = ccgSubSurf_getEdgeSize(ss); - int gridSize = ccgSubSurf_getGridSize(ss); - int i; - CCGVertIterator vi; - CCGEdgeIterator ei; - CCGFaceIterator fi; - CCGFace **faceMap2; - CCGEdge **edgeMap2; - CCGVert **vertMap2; - int index, totvert, totedge, totface; - - totvert = ccgSubSurf_getNumVerts(ss); - vertMap2 = MEM_mallocN(totvert * sizeof(*vertMap2), "vertmap"); - for (ccgSubSurf_initVertIterator(ss, &vi); !ccgVertIterator_isStopped(&vi); - ccgVertIterator_next(&vi)) { - CCGVert *v = ccgVertIterator_getCurrent(&vi); - - vertMap2[POINTER_AS_INT(ccgSubSurf_getVertVertHandle(v))] = v; - } - - totedge = ccgSubSurf_getNumEdges(ss); - edgeMap2 = MEM_mallocN(totedge * sizeof(*edgeMap2), "edgemap"); - for (ccgSubSurf_initEdgeIterator(ss, &ei), i = 0; !ccgEdgeIterator_isStopped(&ei); - i++, ccgEdgeIterator_next(&ei)) { - CCGEdge *e = ccgEdgeIterator_getCurrent(&ei); - - edgeMap2[POINTER_AS_INT(ccgSubSurf_getEdgeEdgeHandle(e))] = e; - } - - totface = ccgSubSurf_getNumFaces(ss); - faceMap2 = MEM_mallocN(totface * sizeof(*faceMap2), "facemap"); - for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi); - ccgFaceIterator_next(&fi)) { - CCGFace *f = ccgFaceIterator_getCurrent(&fi); - - faceMap2[POINTER_AS_INT(ccgSubSurf_getFaceFaceHandle(f))] = f; - } - - i = 0; - for (index = 0; index < totface; index++) { - CCGFace *f = faceMap2[index]; - int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f); - - copy_v3_v3(cos[i++], ccgSubSurf_getFaceCenterData(f)); - - for (S = 0; S < numVerts; S++) { - for (x = 1; x < gridSize - 1; x++) { - copy_v3_v3(cos[i++], ccgSubSurf_getFaceGridEdgeData(ss, f, S, x)); - } - } - - for (S = 0; S < numVerts; S++) { - for (y = 1; y < gridSize - 1; y++) { - for (x = 1; x < gridSize - 1; x++) { - copy_v3_v3(cos[i++], ccgSubSurf_getFaceGridData(ss, f, S, x, y)); - } - } - } - } - - for (index = 0; index < totedge; index++) { - CCGEdge *e = edgeMap2[index]; - int x; - - for (x = 1; x < edgeSize - 1; x++) { - copy_v3_v3(cos[i++], ccgSubSurf_getEdgeData(ss, e, x)); - } - } - - for (index = 0; index < totvert; index++) { - CCGVert *v = vertMap2[index]; - copy_v3_v3(cos[i++], ccgSubSurf_getVertData(ss, v)); - } - - MEM_freeN(vertMap2); - MEM_freeN(edgeMap2); - MEM_freeN(faceMap2); -} - -static void ccgDM_foreachMappedVert(DerivedMesh *dm, - void (*func)(void *userData, - int index, - const float co[3], - const float no_f[3], - const short no_s[3]), - void *userData, - DMForeachFlag flag) -{ - CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm; - CCGVertIterator vi; - CCGKey key; - CCG_key_top_level(&key, ccgdm->ss); - - for (ccgSubSurf_initVertIterator(ccgdm->ss, &vi); !ccgVertIterator_isStopped(&vi); - ccgVertIterator_next(&vi)) { - CCGVert *v = ccgVertIterator_getCurrent(&vi); - const int index = ccgDM_getVertMapIndex(ccgdm->ss, v); - - if (index != -1) { - CCGElem *vd = ccgSubSurf_getVertData(ccgdm->ss, v); - const float *no = (flag & DM_FOREACH_USE_NORMAL) ? CCG_elem_no(&key, vd) : NULL; - func(userData, index, CCG_elem_co(&key, vd), no, NULL); - } - } -} - -static void ccgDM_foreachMappedEdge( - DerivedMesh *dm, - void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]), - void *userData) -{ - CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm; - CCGSubSurf *ss = ccgdm->ss; - CCGEdgeIterator ei; - CCGKey key; - int i, edgeSize = ccgSubSurf_getEdgeSize(ss); - - CCG_key_top_level(&key, ss); - - for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei); - ccgEdgeIterator_next(&ei)) { - CCGEdge *e = ccgEdgeIterator_getCurrent(&ei); - const int index = ccgDM_getEdgeMapIndex(ss, e); - - if (index != -1) { - CCGElem *edgeData = ccgSubSurf_getEdgeDataArray(ss, e); - for (i = 0; i < edgeSize - 1; i++) { - func(userData, - index, - CCG_elem_offset_co(&key, edgeData, i), - CCG_elem_offset_co(&key, edgeData, i + 1)); - } - } - } -} - -static void ccgDM_foreachMappedLoop(DerivedMesh *dm, - void (*func)(void *userData, - int vertex_index, - int face_index, - const float co[3], - const float no[3]), - void *userData, - DMForeachFlag flag) -{ - /* We can't use dm->getLoopDataLayout(dm) here, we want to always access dm->loopData, - * EditDerivedBMesh would return loop data from bmesh itself. */ - const float(*lnors)[3] = (flag & DM_FOREACH_USE_NORMAL) ? DM_get_loop_data_layer(dm, CD_NORMAL) : - NULL; - - MVert *mv = dm->getVertArray(dm); - MLoop *ml = dm->getLoopArray(dm); - MPoly *mp = dm->getPolyArray(dm); - const int *v_index = dm->getVertDataArray(dm, CD_ORIGINDEX); - const int *f_index = dm->getPolyDataArray(dm, CD_ORIGINDEX); - int p_idx, i; - - for (p_idx = 0; p_idx < dm->numPolyData; ++p_idx, ++mp) { - for (i = 0; i < mp->totloop; ++i, ++ml) { - const int v_idx = v_index ? v_index[ml->v] : ml->v; - const int f_idx = f_index ? f_index[p_idx] : p_idx; - const float *no = lnors ? *lnors++ : NULL; - if (!ELEM(ORIGINDEX_NONE, v_idx, f_idx)) { - func(userData, v_idx, f_idx, mv[ml->v].co, no); - } - } - } -} - -static void UNUSED_FUNCTION(ccgdm_pbvh_update)(CCGDerivedMesh *ccgdm) -{ - if (ccgdm->pbvh && ccgDM_use_grid_pbvh(ccgdm)) { - CCGFace **faces; - int totface; - - BKE_pbvh_get_grid_updates(ccgdm->pbvh, 1, (void ***)&faces, &totface); - if (totface) { - ccgSubSurf_updateFromFaces(ccgdm->ss, 0, faces, totface); - ccgSubSurf_updateNormals(ccgdm->ss, faces, totface); - MEM_freeN(faces); - } - } -} - -static void ccgDM_foreachMappedFaceCenter( - DerivedMesh *dm, - void (*func)(void *userData, int index, const float co[3], const float no[3]), - void *userData, - DMForeachFlag flag) -{ - CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm; - CCGSubSurf *ss = ccgdm->ss; - CCGKey key; - CCGFaceIterator fi; - - CCG_key_top_level(&key, ss); - - for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi); - ccgFaceIterator_next(&fi)) { - CCGFace *f = ccgFaceIterator_getCurrent(&fi); - const int index = ccgDM_getFaceMapIndex(ss, f); - - if (index != -1) { - /* Face center data normal isn't updated atm. */ - CCGElem *vd = ccgSubSurf_getFaceGridData(ss, f, 0, 0, 0); - const float *no = (flag & DM_FOREACH_USE_NORMAL) ? CCG_elem_no(&key, vd) : NULL; - func(userData, index, CCG_elem_co(&key, vd), no); - } - } -} - static void ccgDM_release(DerivedMesh *dm) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm; @@ -2222,174 +2005,6 @@ static const MeshElemMap *ccgDM_getPolyMap(Object *ob, DerivedMesh *dm) return ccgdm->pmap; } -static int ccgDM_use_grid_pbvh(CCGDerivedMesh *ccgdm) -{ - MultiresModifierData *mmd = ccgdm->multires.mmd; - - /* both of multires and subsurf modifiers are CCG, but - * grids should only be used when sculpting on multires */ - if (!mmd) { - return 0; - } - - return 1; -} - -static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm) -{ - CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm; - CCGKey key; - int numGrids; - - CCG_key_top_level(&key, ccgdm->ss); - - if (!ob) { - ccgdm->pbvh = NULL; - return NULL; - } - - if (!ob->sculpt) { - return NULL; - } - - bool grid_pbvh = ccgDM_use_grid_pbvh(ccgdm); - if ((ob->mode & OB_MODE_SCULPT) == 0) { - /* In vwpaint, we may use a grid_pbvh for multires/subsurf, under certain conditions. - * More complex cases break 'history' trail back to original vertices, - * in that case we fall back to deformed cage only (i.e. original deformed mesh). */ - VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); - - grid_pbvh = true; - bool has_one_ccg_modifier = false; - for (; md; md = md->next) { - /* We can only accept to use this ccgdm if: - * - it's the only active ccgdm in the stack. - * - there is no topology-modifying modifier in the stack. - * Otherwise, there is no way to map back to original geometry from grid-generated PBVH. - */ - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); - - if (!modifier_isEnabled(NULL, md, eModifierMode_Realtime)) { - continue; - } - if (ELEM(mti->type, eModifierTypeType_OnlyDeform, eModifierTypeType_NonGeometrical)) { - continue; - } - - if (ELEM(md->type, eModifierType_Subsurf, eModifierType_Multires)) { - if (has_one_ccg_modifier) { - /* We only allow a single active ccg modifier in the stack. */ - grid_pbvh = false; - break; - } - has_one_ccg_modifier = true; - continue; - } - - /* Any other non-deforming modifier makes it impossible to use grid pbvh. */ - grid_pbvh = false; - break; - } - } - - if (ob->sculpt->pbvh) { - /* Note that we have to clean up existing pbvh instead of updating it in case it does not - * match current grid_pbvh status. */ - const PBVHType pbvh_type = BKE_pbvh_type(ob->sculpt->pbvh); - if (grid_pbvh) { - if (pbvh_type == PBVH_GRIDS) { - /* pbvh's grids, gridadj and gridfaces points to data inside ccgdm - * but this can be freed on ccgdm release, this updates the pointers - * when the ccgdm gets remade, the assumption is that the topology - * does not change. */ - ccgdm_create_grids(dm); - BKE_pbvh_grids_update(ob->sculpt->pbvh, - ccgdm->gridData, - (void **)ccgdm->gridFaces, - ccgdm->gridFlagMats, - ccgdm->gridHidden); - } - else { - BKE_pbvh_free(ob->sculpt->pbvh); - ob->sculpt->pbvh = NULL; - } - } - else if (pbvh_type == PBVH_GRIDS) { - BKE_pbvh_free(ob->sculpt->pbvh); - ob->sculpt->pbvh = NULL; - } - - ccgdm->pbvh = ob->sculpt->pbvh; - } - - if (ccgdm->pbvh) { - return ccgdm->pbvh; - } - - /* No pbvh exists yet, we need to create one. only in case of multires - * we build a pbvh over the modified mesh, in other cases the base mesh - * is being sculpted, so we build a pbvh from that. */ - /* Note: vwpaint tries to always build a pbvh over the modified mesh. */ - if (grid_pbvh) { - ccgdm_create_grids(dm); - - numGrids = ccgDM_getNumGrids(dm); - - ob->sculpt->pbvh = ccgdm->pbvh = BKE_pbvh_new(); - BKE_pbvh_build_grids(ccgdm->pbvh, - ccgdm->gridData, - numGrids, - &key, - (void **)ccgdm->gridFaces, - ccgdm->gridFlagMats, - ccgdm->gridHidden); - } - else if (ob->type == OB_MESH) { - Mesh *me = BKE_object_get_original_mesh(ob); - const int looptris_num = poly_to_tri_count(me->totpoly, me->totloop); - MLoopTri *looptri; - - looptri = MEM_mallocN(sizeof(*looptri) * looptris_num, __func__); - - BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, looptri); - - ob->sculpt->pbvh = ccgdm->pbvh = BKE_pbvh_new(); - BKE_pbvh_build_mesh(ccgdm->pbvh, - me->mpoly, - me->mloop, - me->mvert, - me->totvert, - &me->vdata, - &me->ldata, - looptri, - looptris_num); - - if (ob->sculpt->modifiers_active && ob->derivedDeform != NULL) { - DerivedMesh *deformdm = ob->derivedDeform; - float(*vertCos)[3]; - int totvert; - - totvert = deformdm->getNumVerts(deformdm); - vertCos = MEM_malloc_arrayN(totvert, sizeof(float[3]), "ccgDM_getPBVH vertCos"); - deformdm->getVertCos(deformdm, vertCos); - BKE_pbvh_apply_vertCos(ccgdm->pbvh, vertCos, totvert); - MEM_freeN(vertCos); - } - } - - if (ccgdm->pbvh != NULL) { - pbvh_show_mask_set(ccgdm->pbvh, ob->sculpt->show_mask); - } - - return ccgdm->pbvh; -} - -static void ccgDM_recalcTessellation(DerivedMesh *UNUSED(dm)) -{ - /* Nothing to do: CCG handles creating its own tessfaces */ -} - /* WARNING! *MUST* be called in an 'loops_cache_rwlock' protected thread context! */ static void ccgDM_recalcLoopTri(DerivedMesh *dm) { @@ -2425,12 +2040,6 @@ static void ccgDM_recalcLoopTri(DerivedMesh *dm) dm->looptris.array_wip = NULL; } -static void ccgDM_calcNormals(DerivedMesh *dm) -{ - /* Nothing to do: CCG calculates normals during drawing */ - dm->dirty &= ~DM_DIRTY_NORMALS; -} - static void set_default_ccgdm_callbacks(CCGDerivedMesh *ccgdm) { ccgdm->dm.getMinMax = ccgDM_getMinMax; @@ -2471,21 +2080,9 @@ static void set_default_ccgdm_callbacks(CCGDerivedMesh *ccgdm) ccgdm->dm.getGridFlagMats = ccgDM_getGridFlagMats; ccgdm->dm.getGridHidden = ccgDM_getGridHidden; ccgdm->dm.getPolyMap = ccgDM_getPolyMap; - ccgdm->dm.getPBVH = ccgDM_getPBVH; - ccgdm->dm.calcNormals = ccgDM_calcNormals; - ccgdm->dm.calcLoopNormals = CDDM_calc_loop_normals; - ccgdm->dm.calcLoopNormalsSpaceArray = CDDM_calc_loop_normals_spacearr; - ccgdm->dm.calcLoopTangents = DM_calc_loop_tangents; - ccgdm->dm.recalcTessellation = ccgDM_recalcTessellation; ccgdm->dm.recalcLoopTri = ccgDM_recalcLoopTri; - ccgdm->dm.getVertCos = ccgdm_getVertCos; - ccgdm->dm.foreachMappedVert = ccgDM_foreachMappedVert; - ccgdm->dm.foreachMappedEdge = ccgDM_foreachMappedEdge; - ccgdm->dm.foreachMappedLoop = ccgDM_foreachMappedLoop; - ccgdm->dm.foreachMappedFaceCenter = ccgDM_foreachMappedFaceCenter; - ccgdm->dm.release = ccgDM_release; } diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index ad7c5e3f660..5c03b7730aa 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -423,6 +423,11 @@ MTex *BKE_texture_mtex_add_id(ID *id, int slot) */ void BKE_texture_copy_data(Main *bmain, Tex *tex_dst, const Tex *tex_src, const int flag) { + /* We never handle usercount here for own data. */ + const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT; + /* We always need allocation of our private ID data. */ + const int flag_private_id_data = flag_subdata & ~LIB_ID_CREATE_NO_ALLOCATE; + if (!BKE_texture_is_image_user(tex_src)) { tex_dst->ima = NULL; } @@ -434,9 +439,8 @@ void BKE_texture_copy_data(Main *bmain, Tex *tex_dst, const Tex *tex_src, const if (tex_src->nodetree->execdata) { ntreeTexEndExecTree(tex_src->nodetree->execdata); } - /* Note: nodetree is *not* in bmain, however this specific case is handled at lower level - * (see BKE_libblock_copy_ex()). */ - BKE_id_copy_ex(bmain, (ID *)tex_src->nodetree, (ID **)&tex_dst->nodetree, flag); + BKE_id_copy_ex( + bmain, (ID *)tex_src->nodetree, (ID **)&tex_dst->nodetree, flag_private_id_data); } if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) { diff --git a/source/blender/blenkernel/intern/tracking_solver.c b/source/blender/blenkernel/intern/tracking_solver.c index 7e7a839b645..ab741eed410 100644 --- a/source/blender/blenkernel/intern/tracking_solver.c +++ b/source/blender/blenkernel/intern/tracking_solver.c @@ -221,7 +221,7 @@ static bool reconstruct_retrieve_libmv_tracks(MovieReconstructContext *context, * * There's one weak part tho, which is requirement object * motion starts at the same frame as camera motion does, - * otherwise that;' be a russian roulette whether object is + * otherwise that;' be a Russian roulette whether object is * aligned correct or not. */ if (!origin_set) { diff --git a/source/blender/blenkernel/intern/tracking_stabilize.c b/source/blender/blenkernel/intern/tracking_stabilize.c index 03229c654fb..7da36ba9af9 100644 --- a/source/blender/blenkernel/intern/tracking_stabilize.c +++ b/source/blender/blenkernel/intern/tracking_stabilize.c @@ -1129,8 +1129,8 @@ static void stabilization_data_to_mat4(float pixel_aspect, } /* Calculate scale factor necessary to eliminate black image areas - * caused by the compensating movements of the stabilizator. - * This function visits every frame where stabilisation data is + * caused by the compensating movements of the stabilizer. + * This function visits every frame where stabilization data is * available and determines the factor for this frame. The overall * largest factor found is returned as result. * diff --git a/source/blender/blenkernel/intern/undo_system.c b/source/blender/blenkernel/intern/undo_system.c index 07cf5205cab..36b950fb8f9 100644 --- a/source/blender/blenkernel/intern/undo_system.c +++ b/source/blender/blenkernel/intern/undo_system.c @@ -503,7 +503,7 @@ bool BKE_undosys_step_push_with_type(UndoStack *ustack, /* Might not be final place for this to be called - probably only want to call it from some * undo handlers, not all of them? */ if (BKE_override_library_is_enabled()) { - BKE_main_override_library_operations_create(G.main, false); + BKE_main_override_library_operations_create(CTX_data_main(C), false); } /* Remove all undos after (also when 'ustack->step_active == NULL'). */ diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c index e30ea687b13..ac1b5e4ab0b 100644 --- a/source/blender/blenkernel/intern/unit.c +++ b/source/blender/blenkernel/intern/unit.c @@ -501,12 +501,12 @@ static PreferredUnits preferred_units_from_UnitSettings(const UnitSettings *sett return units; } -static size_t unit_as_string_splitted(char *str, - int len_max, - double value, - int prec, - const bUnitCollection *usys, - const bUnitDef *main_unit) +static size_t unit_as_string_split_pair(char *str, + int len_max, + double value, + int prec, + const bUnitCollection *usys, + const bUnitDef *main_unit) { const bUnitDef *unit_a, *unit_b; double value_a, value_b; @@ -602,7 +602,7 @@ static size_t unit_as_string_main(char *str, } if (split && unit_should_be_split(type)) { - int length = unit_as_string_splitted(str, len_max, value, prec, usys, main_unit); + int length = unit_as_string_split_pair(str, len_max, value, prec, usys, main_unit); /* failed when length is negative, fallback to no split */ if (length >= 0) { return length; diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index 109d615ae83..31fc87d7021 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -106,10 +106,14 @@ World *BKE_world_add(Main *bmain, const char *name) */ void BKE_world_copy_data(Main *bmain, World *wrld_dst, const World *wrld_src, const int flag) { + /* We never handle usercount here for own data. */ + const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT; + /* We always need allocation of our private ID data. */ + const int flag_private_id_data = flag_subdata & ~LIB_ID_CREATE_NO_ALLOCATE; + if (wrld_src->nodetree) { - /* Note: nodetree is *not* in bmain, however this specific case is handled at lower level - * (see BKE_libblock_copy_ex()). */ - BKE_id_copy_ex(bmain, (ID *)wrld_src->nodetree, (ID **)&wrld_dst->nodetree, flag); + BKE_id_copy_ex( + bmain, (ID *)wrld_src->nodetree, (ID **)&wrld_dst->nodetree, flag_private_id_data); } BLI_listbase_clear(&wrld_dst->gpumaterial); diff --git a/source/blender/blenkernel/nla_private.h b/source/blender/blenkernel/nla_private.h index 1705cd4effc..ed653182a3e 100644 --- a/source/blender/blenkernel/nla_private.h +++ b/source/blender/blenkernel/nla_private.h @@ -24,8 +24,6 @@ #ifndef __NLA_PRIVATE_H__ #define __NLA_PRIVATE_H__ -struct Depsgraph; - #include "RNA_types.h" #include "BLI_bitmap.h" #include "BLI_ghash.h" diff --git a/source/blender/blenlib/BLI_array.h b/source/blender/blenlib/BLI_array.h index a61eff7329e..d687838a896 100644 --- a/source/blender/blenlib/BLI_array.h +++ b/source/blender/blenlib/BLI_array.h @@ -83,9 +83,9 @@ void _bli_array_grow_func(void **arr_p, ((void *)(_##arr##_static) != \ NULL) && /* don't add _##arr##_len below because it must be zero */ \ (_bli_array_totalsize_static(arr) >= \ - _##arr##_len + (num))) ? /* we have an empty array and a static var big enough */ \ + (size_t)(_##arr##_len + (num)))) ? /* we have an empty array and a static var big enough */ \ (void)(arr = (void *)_##arr##_static) : /* use existing static array or allocate */ \ - (LIKELY(_bli_array_totalsize(arr) >= _##arr##_len + (num)) ? \ + (LIKELY(_bli_array_totalsize(arr) >= (size_t)(_##arr##_len + (num))) ? \ (void)0 /* do nothing */ : \ _bli_array_grow_func((void **)&(arr), \ _##arr##_static, \ diff --git a/source/blender/blenlib/BLI_dynstr.h b/source/blender/blenlib/BLI_dynstr.h index 72a6a1b0150..87e58d90d3f 100644 --- a/source/blender/blenlib/BLI_dynstr.h +++ b/source/blender/blenlib/BLI_dynstr.h @@ -35,7 +35,6 @@ #include "BLI_compiler_attrs.h" struct DynStr; -struct MemArena; /** The abstract DynStr type */ typedef struct DynStr DynStr; diff --git a/source/blender/blenlib/BLI_fileops.h b/source/blender/blenlib/BLI_fileops.h index d8daa81b58d..d78f167a8fd 100644 --- a/source/blender/blenlib/BLI_fileops.h +++ b/source/blender/blenlib/BLI_fileops.h @@ -99,8 +99,13 @@ void BLI_filelist_entry_size_to_string(const struct stat *st, void BLI_filelist_entry_mode_to_string( const struct stat *st, const bool compact, char r_mode1[], char r_mode2[], char r_mode3[]); void BLI_filelist_entry_owner_to_string(const struct stat *st, const bool compact, char r_owner[]); -void BLI_filelist_entry_datetime_to_string( - const struct stat *st, const int64_t ts, const bool compact, char r_time[], char r_date[]); +void BLI_filelist_entry_datetime_to_string(const struct stat *st, + const int64_t ts, + const bool compact, + char r_time[], + char r_date[], + bool *r_is_today, + bool *r_is_yesterday); /* Files */ diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h index a348694c4da..abfd561200c 100644 --- a/source/blender/blenlib/BLI_kdopbvh.h +++ b/source/blender/blenlib/BLI_kdopbvh.h @@ -177,6 +177,12 @@ int BLI_bvhtree_find_nearest(BVHTree *tree, BVHTree_NearestPointCallback callback, void *userdata); +int BLI_bvhtree_find_nearest_first(BVHTree *tree, + const float co[3], + const float dist_sq, + BVHTree_NearestPointCallback callback, + void *userdata); + int BLI_bvhtree_ray_cast_ex(BVHTree *tree, const float co[3], const float dir[3], diff --git a/source/blender/blenlib/BLI_listbase.h b/source/blender/blenlib/BLI_listbase.h index c235a72e7e4..b8b62dd3451 100644 --- a/source/blender/blenlib/BLI_listbase.h +++ b/source/blender/blenlib/BLI_listbase.h @@ -171,12 +171,21 @@ struct LinkData *BLI_genericNodeN(void *data); #define LISTBASE_FOREACH(type, var, list) \ for (type var = (type)((list)->first); var != NULL; var = (type)(((Link *)(var))->next)) +#define LISTBASE_FOREACH_BACKWARD(type, var, list) \ + for (type var = (type)((list)->last); var != NULL; var = (type)(((Link *)(var))->prev)) + /** A version of #LISTBASE_FOREACH that supports removing the item we're looping over. */ #define LISTBASE_FOREACH_MUTABLE(type, var, list) \ for (type var = (type)((list)->first), *var##_iter_next; \ ((var != NULL) ? ((void)(var##_iter_next = (type)(((Link *)(var))->next)), 1) : 0); \ var = var##_iter_next) +/** A version of #LISTBASE_FOREACH_BACKWARD that supports removing the item we're looping over. */ +#define LISTBASE_FOREACH_BACKWARD_MUTABLE(type, var, list) \ + for (type var = (type)((list)->last), *var##_iter_prev; \ + ((var != NULL) ? ((void)(var##_iter_prev = (type)(((Link *)(var))->prev)), 1) : 0); \ + var = var##_iter_prev) + #ifdef __cplusplus } #endif diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h index deb29605552..7b770f2dd3e 100644 --- a/source/blender/blenlib/BLI_math_base.h +++ b/source/blender/blenlib/BLI_math_base.h @@ -121,6 +121,9 @@ MINLINE float max_fff(float a, float b, float c); MINLINE float min_ffff(float a, float b, float c, float d); MINLINE float max_ffff(float a, float b, float c, float d); +MINLINE double min_dd(double a, double b); +MINLINE double max_dd(double a, double b); + MINLINE int min_ii(int a, int b); MINLINE int max_ii(int a, int b); MINLINE int min_iii(int a, int b, int c); diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index 39b1b96d009..caecc0aebc2 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -188,6 +188,10 @@ float dist_squared_to_projected_aabb_simple(const float projmat[4][4], const float bbmax[3]); float closest_to_line_v2(float r_close[2], const float p[2], const float l1[2], const float l2[2]); +double closest_to_line_v2_db(double r_close[2], + const double p[2], + const double l1[2], + const double l2[2]); float closest_to_line_v3(float r_close[3], const float p[3], const float l1[3], const float l2[3]); void closest_to_line_segment_v2(float r_close[2], const float p[2], @@ -267,7 +271,12 @@ bool isect_seg_seg_v2_simple(const float v1[2], const float v2[2], const float v3[2], const float v4[2]); - +int isect_seg_seg_v2_lambda_mu_db(const double v1[2], + const double v2[2], + const double v3[2], + const double v4[2], + double *r_lambda, + double *r_mu); int isect_line_sphere_v3(const float l1[3], const float l2[3], const float sp[3], diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h index 52d976daa2d..f5d87667b73 100644 --- a/source/blender/blenlib/BLI_math_matrix.h +++ b/source/blender/blenlib/BLI_math_matrix.h @@ -41,6 +41,7 @@ void zero_m4(float R[4][4]); void unit_m2(float R[2][2]); void unit_m3(float R[3][3]); void unit_m4(float R[4][4]); +void unit_m4_db(double m[4][4]); void copy_m2_m2(float R[2][2], const float A[2][2]); void copy_m3_m3(float R[3][3], const float A[3][3]); @@ -48,9 +49,14 @@ void copy_m4_m4(float R[4][4], const float A[4][4]); void copy_m3_m4(float R[3][3], const float A[4][4]); void copy_m4_m3(float R[4][4], const float A[3][3]); +void copy_m4_m4_db(double m1[4][4], const double m2[4][4]); + /* double->float */ void copy_m3_m3d(float R[3][3], const double A[3][3]); +/* float->double */ +void copy_m4d_m4(double R[4][4], const float A[4][4]); + void swap_m3m3(float A[3][3], float B[3][3]); void swap_m4m4(float A[4][4], float B[4][4]); @@ -82,6 +88,8 @@ void mul_m3_m3m3_uniq(float R[3][3], const float A[3][3], const float B[3][3]); void mul_m3_m3_pre(float R[3][3], const float A[3][3]); void mul_m3_m3_post(float R[3][3], const float B[3][3]); void mul_m4_m4m4_uniq(float R[4][4], const float A[4][4], const float B[4][4]); +void mul_m4_m4m4_db_uniq(double R[4][4], const double A[4][4], const double B[4][4]); +void mul_m4db_m4db_m4fl_uniq(double R[4][4], const double A[4][4], const float B[4][4]); void mul_m4_m4_pre(float R[4][4], const float A[4][4]); void mul_m4_m4_post(float R[4][4], const float B[4][4]); @@ -173,11 +181,14 @@ void _va_mul_m4_series_9(float R[4][4], void mul_m4_v3(const float M[4][4], float r[3]); void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3]); +void mul_v3_m4v3_db(double r[3], const double mat[4][4], const double vec[3]); +void mul_v4_m4v3_db(double r[4], const double mat[4][4], const double vec[3]); void mul_v2_m4v3(float r[2], const float M[4][4], const float v[3]); void mul_v2_m2v2(float r[2], const float M[2][2], const float v[2]); void mul_m2v2(const float M[2][2], float v[2]); void mul_mat3_m4_v3(const float M[4][4], float r[3]); void mul_v3_mat3_m4v3(float r[3], const float M[4][4], const float v[3]); +void mul_v3_mat3_m4v3_db(double r[3], const double M[4][4], const double v[3]); void mul_m4_v4(const float M[4][4], float r[4]); void mul_v4_m4v4(float r[4], const float M[4][4], const float v[4]); void mul_v4_m4v3(float r[4], const float M[4][4], const float v[3]); /* v has implicit w = 1.0f */ diff --git a/source/blender/blenlib/BLI_math_rotation.h b/source/blender/blenlib/BLI_math_rotation.h index 7a4ac14970f..1e56b80bcf2 100644 --- a/source/blender/blenlib/BLI_math_rotation.h +++ b/source/blender/blenlib/BLI_math_rotation.h @@ -96,6 +96,8 @@ void rotation_between_vecs_to_mat3(float m[3][3], const float v1[3], const float void rotation_between_vecs_to_quat(float q[4], const float v1[3], const float v2[3]); void rotation_between_quats_to_quat(float q[4], const float q1[4], const float q2[4]); +float quat_split_swing_and_twist(const float q[4], int axis, float r_swing[4], float r_twist[4]); + float angle_normalized_qt(const float q[4]); float angle_normalized_qtqt(const float q1[4], const float q2[4]); float angle_qt(const float q[4]); diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h index 53e686c87a6..31d725af5ad 100644 --- a/source/blender/blenlib/BLI_math_vector.h +++ b/source/blender/blenlib/BLI_math_vector.h @@ -103,9 +103,11 @@ MINLINE void add_v2_fl(float r[2], float f); MINLINE void add_v3_fl(float r[3], float f); MINLINE void add_v4_fl(float r[4], float f); MINLINE void add_v2_v2(float r[2], const float a[2]); +MINLINE void add_v2_v2_db(double r[2], const double a[2]); MINLINE void add_v2_v2v2(float r[2], const float a[2], const float b[2]); MINLINE void add_v2_v2v2_int(int r[2], const int a[2], const int b[2]); MINLINE void add_v3_v3(float r[3], const float a[3]); +MINLINE void add_v3_v3_db(double r[3], const double a[3]); MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3]); MINLINE void add_v4_v4(float r[4], const float a[4]); MINLINE void add_v4_v4v4(float r[4], const float a[4], const float b[4]); @@ -115,10 +117,12 @@ MINLINE void add_v3fl_v3fl_v3s(float r[3], const float a[3], const short b[3]); MINLINE void sub_v2_v2(float r[2], const float a[2]); MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2]); +MINLINE void sub_v2_v2v2_db(double r[2], const double a[2], const double b[2]); MINLINE void sub_v2_v2v2_int(int r[2], const int a[2], const int b[2]); MINLINE void sub_v3_v3(float r[3], const float a[3]); MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3]); MINLINE void sub_v3_v3v3_int(int r[3], const int a[3], const int b[3]); +MINLINE void sub_v3_v3v3_db(double r[3], const double a[3], const double b[3]); MINLINE void sub_v4_v4(float r[4], const float a[4]); MINLINE void sub_v4_v4v4(float r[4], const float a[4], const float b[4]); @@ -127,6 +131,7 @@ MINLINE void sub_v3db_v3fl_v3fl(double r[3], const float a[3], const float b[3]) MINLINE void mul_v2_fl(float r[2], float f); MINLINE void mul_v2_v2fl(float r[2], const float a[2], float f); MINLINE void mul_v3_fl(float r[3], float f); +MINLINE void mul_v3db_db(double r[3], double f); MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f); MINLINE void mul_v2_v2(float r[2], const float a[2]); MINLINE void mul_v2_v2v2(float r[2], const float a[2], const float b[2]); @@ -181,6 +186,7 @@ MINLINE void abs_v4(float r[4]); MINLINE void abs_v4_v4(float r[4], const float a[4]); MINLINE float dot_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT; +MINLINE double dot_v2v2_db(const double a[2], const double b[2]) ATTR_WARN_UNUSED_RESULT; MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT; MINLINE float dot_v3v3v3(const float p[3], const float a[3], @@ -189,9 +195,12 @@ MINLINE float dot_v4v4(const float a[4], const float b[4]) ATTR_WARN_UNUSED_RESU MINLINE double dot_v3db_v3fl(const double a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT; +MINLINE double dot_v3v3_db(const double a[3], const double b[3]) ATTR_WARN_UNUSED_RESULT; + MINLINE float cross_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT; MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3]); MINLINE void cross_v3_v3v3_hi_prec(float r[3], const float a[3], const float b[3]); +MINLINE void cross_v3_v3v3_db(double r[3], const double a[3], const double b[3]); MINLINE void add_newell_cross_v3_v3v3(float n[3], const float v_prev[3], const float v_curr[3]); @@ -206,8 +215,10 @@ MINLINE int len_manhattan_v2_int(const int v[2]) ATTR_WARN_UNUSED_RESULT; MINLINE float len_manhattan_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT; MINLINE float len_v2(const float a[2]) ATTR_WARN_UNUSED_RESULT; MINLINE float len_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT; +MINLINE double len_v2v2_db(const double a[2], const double b[2]) ATTR_WARN_UNUSED_RESULT; MINLINE float len_v2v2_int(const int v1[2], const int v2[2]); MINLINE float len_squared_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT; +MINLINE double len_squared_v2v2_db(const double a[2], const double b[2]) ATTR_WARN_UNUSED_RESULT; MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT; MINLINE float len_squared_v4v4(const float a[4], const float b[4]) ATTR_WARN_UNUSED_RESULT; MINLINE float len_manhattan_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT; diff --git a/source/blender/blenlib/BLI_memiter.h b/source/blender/blenlib/BLI_memiter.h index 6f6316e15e4..9f5be292dd8 100644 --- a/source/blender/blenlib/BLI_memiter.h +++ b/source/blender/blenlib/BLI_memiter.h @@ -33,7 +33,6 @@ extern "C" { #define BLI_MEMITER_DEFAULT_SIZE (1 << 19) struct BLI_memiter; -struct BLI_memiter_chunk; typedef struct BLI_memiter BLI_memiter; diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index 99e86615e50..75d5cb286ac 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -29,8 +29,6 @@ extern "C" { #include "BLI_compiler_attrs.h" -struct ListBase; - void BLI_setenv(const char *env, const char *val) ATTR_NONNULL(1); void BLI_setenv_if_new(const char *env, const char *val) ATTR_NONNULL(1); const char *BLI_getenv(const char *env) ATTR_NONNULL(1); diff --git a/source/blender/blenlib/BLI_polyfill_2d_beautify.h b/source/blender/blenlib/BLI_polyfill_2d_beautify.h index f815459fdf5..042cb7e0ea9 100644 --- a/source/blender/blenlib/BLI_polyfill_2d_beautify.h +++ b/source/blender/blenlib/BLI_polyfill_2d_beautify.h @@ -36,9 +36,10 @@ float BLI_polyfill_beautify_quad_rotate_calc_ex(const float v1[2], const float v2[2], const float v3[2], const float v4[2], - const bool lock_degenerate); + const bool lock_degenerate, + float *r_area); #define BLI_polyfill_beautify_quad_rotate_calc(v1, v2, v3, v4) \ - BLI_polyfill_beautify_quad_rotate_calc_ex(v1, v2, v3, v4, false) + BLI_polyfill_beautify_quad_rotate_calc_ex(v1, v2, v3, v4, false, NULL) /* avoid realloc's when creating new structures for polyfill ngons */ #define BLI_POLYFILL_ALLOC_NGON_RESERVE 64 diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h index 70ffb46e952..cab2e68ca2b 100644 --- a/source/blender/blenlib/BLI_string.h +++ b/source/blender/blenlib/BLI_string.h @@ -100,7 +100,7 @@ char *BLI_strncasestr(const char *s, const char *find, size_t len) ATTR_WARN_UNU int BLI_strcasecmp(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); int BLI_strncasecmp(const char *s1, const char *s2, size_t len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -int BLI_natstrcmp(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +int BLI_strcasecmp_natural(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); int BLI_strcmp_ignore_pad(const char *str1, const char *str2, const char pad) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); diff --git a/source/blender/blenlib/BLI_system.h b/source/blender/blenlib/BLI_system.h index f4c0399e959..8c0c9ad99bf 100644 --- a/source/blender/blenlib/BLI_system.h +++ b/source/blender/blenlib/BLI_system.h @@ -19,11 +19,16 @@ #include <stdio.h> +#ifdef __cplusplus +extern "C" { +#endif + /** \file * \ingroup bli */ int BLI_cpu_support_sse2(void); +int BLI_cpu_support_sse41(void); void BLI_system_backtrace(FILE *fp); /* Get CPU brand, result is to be MEM_freeN()-ed. */ @@ -52,4 +57,8 @@ int BLI_system_memory_max_in_megabytes_int(void); # define BLI_SYSTEM_PID_H <unistd.h> #endif +#ifdef __cplusplus +} +#endif + #endif /* __BLI_SYSTEM_H__ */ diff --git a/source/blender/blenlib/intern/BLI_filelist.c b/source/blender/blenlib/intern/BLI_filelist.c index 91f16ca9b7b..c92505acb54 100644 --- a/source/blender/blenlib/intern/BLI_filelist.c +++ b/source/blender/blenlib/intern/BLI_filelist.c @@ -107,7 +107,7 @@ static int bli_compare(struct direntry *entry1, struct direntry *entry2) return 1; } - return (BLI_natstrcmp(entry1->relname, entry2->relname)); + return (BLI_strcasecmp_natural(entry1->relname, entry2->relname)); } struct BuildDirCtx { @@ -261,36 +261,17 @@ unsigned int BLI_filelist_dir_contents(const char *dirname, struct direntry **r_ */ void BLI_filelist_entry_size_to_string(const struct stat *st, const uint64_t sz, - const bool compact, + /* Used to change MB -> M, etc. - is that really useful? */ + const bool UNUSED(compact), char r_size[FILELIST_DIRENTRY_SIZE_LEN]) { - double size; - const char *fmt; - const char *units[] = {"KiB", "MiB", "GiB", "TiB", NULL}; - const char *units_compact[] = {"K", "M", "G", "T", NULL}; - const char *unit = "B"; - /* * Seems st_size is signed 32-bit value in *nix and Windows. This * will buy us some time until files get bigger than 4GB or until * everyone starts using __USE_FILE_OFFSET64 or equivalent. */ - size = (double)(st ? st->st_size : sz); - - if (size > 1024.0) { - const char **u; - for (u = compact ? units_compact : units, size /= 1024.0; size > 1024.0 && *(u + 1); - u++, size /= 1024.0) { - /* pass */ - } - fmt = size > 100.0 ? "%.0f %s" : (size > 10.0 ? "%.1f %s" : "%.2f %s"); - unit = *u; - } - else { - fmt = "%.0f %s"; - } - - BLI_snprintf(r_size, sizeof(*r_size) * FILELIST_DIRENTRY_SIZE_LEN, fmt, size, unit); + double size = (double)(st ? st->st_size : sz); + BLI_str_format_byte_unit(r_size, size, true); } /** @@ -366,14 +347,45 @@ void BLI_filelist_entry_owner_to_string(const struct stat *st, /** * Convert given entry's time into human-readable strings. + * + * \param r_is_today: optional, returns true if the date matches today's. + * \param r_is_yesterday: optional, returns true if the date matches yesterday's. */ void BLI_filelist_entry_datetime_to_string(const struct stat *st, const int64_t ts, const bool compact, char r_time[FILELIST_DIRENTRY_TIME_LEN], - char r_date[FILELIST_DIRENTRY_DATE_LEN]) + char r_date[FILELIST_DIRENTRY_DATE_LEN], + bool *r_is_today, + bool *r_is_yesterday) { - time_t ts_mtime = ts; + int today_year = 0; + int today_yday = 0; + int yesterday_year = 0; + int yesterday_yday = 0; + + if (r_is_today || r_is_yesterday) { + /* Localtime() has only one buffer so need to get data out before called again. */ + const time_t ts_now = time(NULL); + struct tm *today = localtime(&ts_now); + + today_year = today->tm_year; + today_yday = today->tm_yday; + /* Handle a yesterday that spans a year */ + today->tm_mday--; + mktime(today); + yesterday_year = today->tm_year; + yesterday_yday = today->tm_yday; + + if (r_is_today) { + *r_is_today = false; + } + if (r_is_yesterday) { + *r_is_yesterday = false; + } + } + + const time_t ts_mtime = ts; const struct tm *tm = localtime(st ? &st->st_mtime : &ts_mtime); const time_t zero = 0; @@ -385,12 +397,20 @@ void BLI_filelist_entry_datetime_to_string(const struct stat *st, if (r_time) { strftime(r_time, sizeof(*r_time) * FILELIST_DIRENTRY_TIME_LEN, "%H:%M", tm); } + if (r_date) { strftime(r_date, sizeof(*r_date) * FILELIST_DIRENTRY_DATE_LEN, - compact ? "%d/%m/%y" : "%d-%b-%y", + compact ? "%d/%m/%y" : "%d %b %Y", tm); } + + if (r_is_today && (tm->tm_year == today_year) && (tm->tm_yday == today_yday)) { + *r_is_today = true; + } + else if (r_is_yesterday && (tm->tm_year == yesterday_year) && (tm->tm_yday == yesterday_yday)) { + *r_is_yesterday = true; + } } /** diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index 769bb02e2b9..05ffb02597d 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -886,7 +886,7 @@ bool BLI_ghash_ensure_p_ex(GHash *gh, const void *key, void ***r_key, void ***r_ const bool haskey = (e != NULL); if (!haskey) { - /* pass 'key' incase we resize */ + /* Pass 'key' in case we resize. */ e = BLI_mempool_alloc(gh->entrypool); ghash_insert_ex_keyonly_entry(gh, (void *)key, bucket_index, (Entry *)e); e->e.key = NULL; /* caller must re-assign */ @@ -1189,7 +1189,7 @@ bool BLI_gset_ensure_p_ex(GSet *gs, const void *key, void ***r_key) const bool haskey = (e != NULL); if (!haskey) { - /* pass 'key' incase we resize */ + /* Pass 'key' in case we resize */ e = BLI_mempool_alloc(((GHash *)gs)->entrypool); ghash_insert_ex_keyonly_entry((GHash *)gs, (void *)key, bucket_index, (Entry *)e); e->key = NULL; /* caller must re-assign */ diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 0e93fd8e13b..ed3c7096865 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -1467,6 +1467,95 @@ int BLI_bvhtree_find_nearest(BVHTree *tree, /** \} */ /* -------------------------------------------------------------------- */ +/** \name BLI_bvhtree_find_nearest_first + * \{ */ + +static bool isect_aabb_v3(BVHNode *node, const float co[3]) +{ + const BVHTreeAxisRange *bv = (const BVHTreeAxisRange *)node->bv; + + if (co[0] > bv[0].min && co[0] < bv[0].max && co[1] > bv[1].min && co[1] < bv[1].max && + co[2] > bv[2].min && co[2] < bv[2].max) { + return true; + } + + return false; +} + +static bool dfs_find_duplicate_fast_dfs(BVHNearestData *data, BVHNode *node) +{ + if (node->totnode == 0) { + if (isect_aabb_v3(node, data->co)) { + if (data->callback) { + const float dist_sq = data->nearest.dist_sq; + data->callback(data->userdata, node->index, data->co, &data->nearest); + return (data->nearest.dist_sq < dist_sq); + } + else { + data->nearest.index = node->index; + return true; + } + } + } + else { + /* Better heuristic to pick the closest node to dive on */ + int i; + + if (data->proj[node->main_axis] <= node->children[0]->bv[node->main_axis * 2 + 1]) { + for (i = 0; i != node->totnode; i++) { + if (isect_aabb_v3(node->children[i], data->co)) { + if (dfs_find_duplicate_fast_dfs(data, node->children[i])) { + return true; + } + } + } + } + else { + for (i = node->totnode; i--;) { + if (isect_aabb_v3(node->children[i], data->co)) { + if (dfs_find_duplicate_fast_dfs(data, node->children[i])) { + return true; + } + } + } + } + } + return false; +} + +/** + * Find the first node nearby. + * Favors speed over quality since it doesn't find the best target node. + */ +int BLI_bvhtree_find_nearest_first(BVHTree *tree, + const float co[3], + const float dist_sq, + BVHTree_NearestPointCallback callback, + void *userdata) +{ + BVHNearestData data; + BVHNode *root = tree->nodes[tree->totleaf]; + + /* init data to search */ + data.tree = tree; + data.co = co; + + data.callback = callback; + data.userdata = userdata; + data.nearest.index = -1; + data.nearest.dist_sq = dist_sq; + + /* dfs search */ + if (root) { + dfs_find_duplicate_fast_dfs(&data, root); + } + + return data.nearest.index; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name BLI_bvhtree_ray_cast * * raycast is done by performing a DFS on the BVHTree and saving the closest hit. diff --git a/source/blender/blenlib/intern/boxpack_2d.c b/source/blender/blenlib/intern/boxpack_2d.c index 196d45967be..ddc7f9ee4c7 100644 --- a/source/blender/blenlib/intern/boxpack_2d.c +++ b/source/blender/blenlib/intern/boxpack_2d.c @@ -273,12 +273,12 @@ static int vertex_sort(const void *p1, const void *p2, void *vs_ctx_p) /** \} */ /** - * Main boxpacking function accessed from other functions + * Main box-packing function accessed from other functions * This sets boxes x,y to positive values, sorting from 0,0 outwards. * There is no limit to the space boxes may take, only that they will be packed * tightly into the lower left hand corner (0,0) * - * \param boxarray: a pre allocated array of boxes. + * \param boxarray: a pre-allocated array of boxes. * only the 'box->x' and 'box->y' are set, 'box->w' and 'box->h' are used, * 'box->index' is not used at all, the only reason its there * is that the box array is sorted by area and programs need to be able diff --git a/source/blender/blenlib/intern/delaunay_2d.c b/source/blender/blenlib/intern/delaunay_2d.c index 23f560c5463..102ea8eb234 100644 --- a/source/blender/blenlib/intern/delaunay_2d.c +++ b/source/blender/blenlib/intern/delaunay_2d.c @@ -115,99 +115,6 @@ static void validate_face_centroid(SymEdge *se); static void validate_cdt(CDT_state *cdt, bool check_all_tris); #endif -/* TODO: move these to BLI_vector... and BLI_math... */ -static double max_dd(const double a, const double b) -{ - return (a > b) ? a : b; -} - -static double len_v2v2_db(const double a[2], const double b[2]) -{ - return sqrt((b[0] - a[0]) * (b[0] - a[0]) + (b[1] - a[1]) * (b[1] - a[1])); -} - -static double len_squared_v2v2_db(const double a[2], const double b[2]) -{ - return (b[0] - a[0]) * (b[0] - a[0]) + (b[1] - a[1]) * (b[1] - a[1]); -} - -static void add_v2_v2_db(double a[2], const double b[2]) -{ - a[0] += b[0]; - a[1] += b[1]; -} - -static void sub_v2_v2v2_db(double *a, const double *b, const double *c) -{ - a[0] = b[0] - c[0]; - a[1] = b[1] - c[1]; -} - -static double dot_v2v2_db(const double *a, const double *b) -{ - return a[0] * b[0] + a[1] * b[1]; -} - -static double closest_to_line_v2_db(double r_close[2], - const double p[2], - const double l1[2], - const double l2[2]) -{ - double h[2], u[2], lambda, denom; - sub_v2_v2v2_db(u, l2, l1); - sub_v2_v2v2_db(h, p, l1); - denom = dot_v2v2_db(u, u); - if (denom < DBL_EPSILON) { - r_close[0] = l1[0]; - r_close[1] = l1[1]; - return 0.0; - } - lambda = dot_v2v2_db(u, h) / dot_v2v2_db(u, u); - r_close[0] = l1[0] + u[0] * lambda; - r_close[1] = l1[1] + u[1] * lambda; - return lambda; -} - -/** - * If intersection == ISECT_LINE_LINE_CROSS or ISECT_LINE_LINE_NONE: - * <pre> - * pt = v1 + lamba * (v2 - v1) = v3 + mu * (v4 - v3) - * </pre> - */ -static int isect_seg_seg_v2_lambda_mu_db(const double v1[2], - const double v2[2], - const double v3[2], - const double v4[2], - double *r_lambda, - double *r_mu) -{ - double div, lambda, mu; - - div = (v2[0] - v1[0]) * (v4[1] - v3[1]) - (v2[1] - v1[1]) * (v4[0] - v3[0]); - if (fabs(div) < DBL_EPSILON) { - return ISECT_LINE_LINE_COLINEAR; - } - - lambda = ((v1[1] - v3[1]) * (v4[0] - v3[0]) - (v1[0] - v3[0]) * (v4[1] - v3[1])) / div; - - mu = ((v1[1] - v3[1]) * (v2[0] - v1[0]) - (v1[0] - v3[0]) * (v2[1] - v1[1])) / div; - - if (r_lambda) { - *r_lambda = lambda; - } - if (r_mu) { - *r_mu = mu; - } - - if (lambda >= 0.0 && lambda <= 1.0 && mu >= 0.0 && mu <= 1.0) { - if (lambda == 0.0 || lambda == 1.0 || mu == 0.0 || mu == 1.0) { - return ISECT_LINE_LINE_EXACT; - } - return ISECT_LINE_LINE_CROSS; - } - return ISECT_LINE_LINE_NONE; -} - /** return 1 if a,b,c forms CCW angle, -1 if a CW angle, 0 if straight */ static int CCW_test(const double a[2], const double b[2], const double c[2]) { diff --git a/source/blender/blenlib/intern/freetypefont.c b/source/blender/blenlib/intern/freetypefont.c index 7be7674069c..b5a950d6851 100644 --- a/source/blender/blenlib/intern/freetypefont.c +++ b/source/blender/blenlib/intern/freetypefont.c @@ -565,7 +565,7 @@ VChar *BLI_vfontchar_copy(const VChar *vchar_src, const int UNUSED(flag)) * between them * </pre> * - * Each glyph's original outline points are located on a grid of indivisible units. + * Each glyphs original outline points are located on a grid of indivisible units. * The points are stored in the font file as 16-bit integer grid coordinates, * with the grid origin's being at (0, 0); they thus range from -16384 to 16383. * diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c index 320f8a0f1ab..47327a878d4 100644 --- a/source/blender/blenlib/intern/math_base_inline.c +++ b/source/blender/blenlib/intern/math_base_inline.c @@ -353,6 +353,15 @@ MINLINE float max_ff(float a, float b) return (a > b) ? a : b; } +MINLINE double min_dd(double a, double b) +{ + return (a < b) ? a : b; +} +MINLINE double max_dd(double a, double b) +{ + return (a > b) ? a : b; +} + MINLINE int min_ii(int a, int b) { return (a < b) ? a : b; diff --git a/source/blender/blenlib/intern/math_color.c b/source/blender/blenlib/intern/math_color.c index f07c2ec159e..cc29ebe4f20 100644 --- a/source/blender/blenlib/intern/math_color.c +++ b/source/blender/blenlib/intern/math_color.c @@ -153,7 +153,7 @@ void rgb_to_ycc(float r, float g, float b, float *ly, float *lcb, float *lcr, in cr = (0.5f * sr) - (0.41869f * sg) - (0.08131f * sb) + 128.0f; break; default: - assert(!"invalid colorspace"); + BLI_assert(!"invalid colorspace"); break; } diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index 06fd5c70772..f1575ed2b2d 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -1356,6 +1356,52 @@ bool isect_seg_seg_v2_simple(const float v1[2], } /** + * If intersection == ISECT_LINE_LINE_CROSS or ISECT_LINE_LINE_NONE: + * <pre> + * pt = v1 + lambda * (v2 - v1) = v3 + mu * (v4 - v3) + * </pre> + * \returns intersection type: + * - ISECT_LINE_LINE_COLINEAR: collinear. + * - ISECT_LINE_LINE_EXACT: intersection at an endpoint of either. + * - ISECT_LINE_LINE_CROSS: interaction, not at an endpoint. + * - ISECT_LINE_LINE_NONE: no intersection. + * Also returns lambda and mu in r_lambda and r_mu. + */ +int isect_seg_seg_v2_lambda_mu_db(const double v1[2], + const double v2[2], + const double v3[2], + const double v4[2], + double *r_lambda, + double *r_mu) +{ + double div, lambda, mu; + + div = (v2[0] - v1[0]) * (v4[1] - v3[1]) - (v2[1] - v1[1]) * (v4[0] - v3[0]); + if (fabs(div) < DBL_EPSILON) { + return ISECT_LINE_LINE_COLINEAR; + } + + lambda = ((v1[1] - v3[1]) * (v4[0] - v3[0]) - (v1[0] - v3[0]) * (v4[1] - v3[1])) / div; + + mu = ((v1[1] - v3[1]) * (v2[0] - v1[0]) - (v1[0] - v3[0]) * (v2[1] - v1[1])) / div; + + if (r_lambda) { + *r_lambda = lambda; + } + if (r_mu) { + *r_mu = mu; + } + + if (lambda >= 0.0 && lambda <= 1.0 && mu >= 0.0 && mu <= 1.0) { + if (lambda == 0.0 || lambda == 1.0 || mu == 0.0 || mu == 1.0) { + return ISECT_LINE_LINE_EXACT; + } + return ISECT_LINE_LINE_CROSS; + } + return ISECT_LINE_LINE_NONE; +} + +/** * \param l1, l2: Coordinates (point of line). * \param sp, r: Coordinate and radius (sphere). * \return r_p1, r_p2: Intersection coordinates. @@ -3187,6 +3233,26 @@ float closest_to_line_v2(float r_close[2], const float p[2], const float l1[2], return lambda; } +double closest_to_line_v2_db(double r_close[2], + const double p[2], + const double l1[2], + const double l2[2]) +{ + double h[2], u[2], lambda, denom; + sub_v2_v2v2_db(u, l2, l1); + sub_v2_v2v2_db(h, p, l1); + denom = dot_v2v2_db(u, u); + if (denom < DBL_EPSILON) { + r_close[0] = l1[0]; + r_close[1] = l1[1]; + return 0.0; + } + lambda = dot_v2v2_db(u, h) / dot_v2v2_db(u, u); + r_close[0] = l1[0] + u[0] * lambda; + r_close[1] = l1[1] + u[1] * lambda; + return lambda; +} + float ray_point_factor_v3_ex(const float p[3], const float ray_origin[3], const float ray_direction[3], @@ -3452,7 +3518,7 @@ bool clip_segment_v3_plane( } } - /* incase input/output values match (above also) */ + /* In case input/output values match (above also). */ const float p1_copy[3] = {UNPACK3(p1)}; copy_v3_v3(r_p2, p2); copy_v3_v3(r_p1, p1_copy); @@ -3511,7 +3577,7 @@ bool clip_segment_v3_plane_n(const float p1[3], } } - /* incase input/output values match */ + /* In case input/output values match. */ const float p1_copy[3] = {UNPACK3(p1)}; madd_v3_v3v3fl(r_p1, p1_copy, dp, p1_fac); diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c index 7c64206134b..2568d42566c 100644 --- a/source/blender/blenlib/intern/math_matrix.c +++ b/source/blender/blenlib/intern/math_matrix.c @@ -71,6 +71,15 @@ void unit_m4(float m[4][4]) m[3][0] = m[3][1] = m[3][2] = 0.0f; } +void unit_m4_db(double m[4][4]) +{ + m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f; + m[0][1] = m[0][2] = m[0][3] = 0.0f; + m[1][0] = m[1][2] = m[1][3] = 0.0f; + m[2][0] = m[2][1] = m[2][3] = 0.0f; + m[3][0] = m[3][1] = m[3][2] = 0.0f; +} + void copy_m2_m2(float m1[2][2], const float m2[2][2]) { memcpy(m1, m2, sizeof(float[2][2])); @@ -87,6 +96,11 @@ void copy_m4_m4(float m1[4][4], const float m2[4][4]) memcpy(m1, m2, sizeof(float[4][4])); } +void copy_m4_m4_db(double m1[4][4], const double m2[4][4]) +{ + memcpy(m1, m2, sizeof(double[4][4])); +} + void copy_m3_m4(float m1[3][3], const float m2[4][4]) { m1[0][0] = m2[0][0]; @@ -127,6 +141,29 @@ void copy_m4_m3(float m1[4][4], const float m2[3][3]) /* no clear */ m1[3][3] = 1.0f; } +void copy_m4d_m4(double m1[4][4], const float m2[4][4]) +{ + m1[0][0] = m2[0][0]; + m1[0][1] = m2[0][1]; + m1[0][2] = m2[0][2]; + m1[0][3] = m2[0][3]; + + m1[1][0] = m2[1][0]; + m1[1][1] = m2[1][1]; + m1[1][2] = m2[1][2]; + m1[1][3] = m2[1][3]; + + m1[2][0] = m2[2][0]; + m1[2][1] = m2[2][1]; + m1[2][2] = m2[2][2]; + m1[2][3] = m2[2][3]; + + m1[3][0] = m2[3][0]; + m1[3][1] = m2[3][1]; + m1[3][2] = m2[3][2]; + m1[3][3] = m2[3][3]; +} + void copy_m3_m3d(float R[3][3], const double A[3][3]) { /* Keep it stupid simple for better data flow in CPU. */ @@ -231,6 +268,61 @@ void mul_m4_m4m4_uniq(float R[4][4], const float A[4][4], const float B[4][4]) #endif } +void mul_m4_m4m4_db_uniq(double R[4][4], const double A[4][4], const double B[4][4]) +{ + BLI_assert(R != A && R != B); + + /* matrix product: R[j][k] = A[j][i] . B[i][k] */ + + R[0][0] = B[0][0] * A[0][0] + B[0][1] * A[1][0] + B[0][2] * A[2][0] + B[0][3] * A[3][0]; + R[0][1] = B[0][0] * A[0][1] + B[0][1] * A[1][1] + B[0][2] * A[2][1] + B[0][3] * A[3][1]; + R[0][2] = B[0][0] * A[0][2] + B[0][1] * A[1][2] + B[0][2] * A[2][2] + B[0][3] * A[3][2]; + R[0][3] = B[0][0] * A[0][3] + B[0][1] * A[1][3] + B[0][2] * A[2][3] + B[0][3] * A[3][3]; + + R[1][0] = B[1][0] * A[0][0] + B[1][1] * A[1][0] + B[1][2] * A[2][0] + B[1][3] * A[3][0]; + R[1][1] = B[1][0] * A[0][1] + B[1][1] * A[1][1] + B[1][2] * A[2][1] + B[1][3] * A[3][1]; + R[1][2] = B[1][0] * A[0][2] + B[1][1] * A[1][2] + B[1][2] * A[2][2] + B[1][3] * A[3][2]; + R[1][3] = B[1][0] * A[0][3] + B[1][1] * A[1][3] + B[1][2] * A[2][3] + B[1][3] * A[3][3]; + + R[2][0] = B[2][0] * A[0][0] + B[2][1] * A[1][0] + B[2][2] * A[2][0] + B[2][3] * A[3][0]; + R[2][1] = B[2][0] * A[0][1] + B[2][1] * A[1][1] + B[2][2] * A[2][1] + B[2][3] * A[3][1]; + R[2][2] = B[2][0] * A[0][2] + B[2][1] * A[1][2] + B[2][2] * A[2][2] + B[2][3] * A[3][2]; + R[2][3] = B[2][0] * A[0][3] + B[2][1] * A[1][3] + B[2][2] * A[2][3] + B[2][3] * A[3][3]; + + R[3][0] = B[3][0] * A[0][0] + B[3][1] * A[1][0] + B[3][2] * A[2][0] + B[3][3] * A[3][0]; + R[3][1] = B[3][0] * A[0][1] + B[3][1] * A[1][1] + B[3][2] * A[2][1] + B[3][3] * A[3][1]; + R[3][2] = B[3][0] * A[0][2] + B[3][1] * A[1][2] + B[3][2] * A[2][2] + B[3][3] * A[3][2]; + R[3][3] = B[3][0] * A[0][3] + B[3][1] * A[1][3] + B[3][2] * A[2][3] + B[3][3] * A[3][3]; +} + +void mul_m4db_m4db_m4fl_uniq(double R[4][4], const double A[4][4], const float B[4][4]) +{ + /* Remove second check since types don't match. */ + BLI_assert(R != A /* && R != B */); + + /* matrix product: R[j][k] = A[j][i] . B[i][k] */ + + R[0][0] = B[0][0] * A[0][0] + B[0][1] * A[1][0] + B[0][2] * A[2][0] + B[0][3] * A[3][0]; + R[0][1] = B[0][0] * A[0][1] + B[0][1] * A[1][1] + B[0][2] * A[2][1] + B[0][3] * A[3][1]; + R[0][2] = B[0][0] * A[0][2] + B[0][1] * A[1][2] + B[0][2] * A[2][2] + B[0][3] * A[3][2]; + R[0][3] = B[0][0] * A[0][3] + B[0][1] * A[1][3] + B[0][2] * A[2][3] + B[0][3] * A[3][3]; + + R[1][0] = B[1][0] * A[0][0] + B[1][1] * A[1][0] + B[1][2] * A[2][0] + B[1][3] * A[3][0]; + R[1][1] = B[1][0] * A[0][1] + B[1][1] * A[1][1] + B[1][2] * A[2][1] + B[1][3] * A[3][1]; + R[1][2] = B[1][0] * A[0][2] + B[1][1] * A[1][2] + B[1][2] * A[2][2] + B[1][3] * A[3][2]; + R[1][3] = B[1][0] * A[0][3] + B[1][1] * A[1][3] + B[1][2] * A[2][3] + B[1][3] * A[3][3]; + + R[2][0] = B[2][0] * A[0][0] + B[2][1] * A[1][0] + B[2][2] * A[2][0] + B[2][3] * A[3][0]; + R[2][1] = B[2][0] * A[0][1] + B[2][1] * A[1][1] + B[2][2] * A[2][1] + B[2][3] * A[3][1]; + R[2][2] = B[2][0] * A[0][2] + B[2][1] * A[1][2] + B[2][2] * A[2][2] + B[2][3] * A[3][2]; + R[2][3] = B[2][0] * A[0][3] + B[2][1] * A[1][3] + B[2][2] * A[2][3] + B[2][3] * A[3][3]; + + R[3][0] = B[3][0] * A[0][0] + B[3][1] * A[1][0] + B[3][2] * A[2][0] + B[3][3] * A[3][0]; + R[3][1] = B[3][0] * A[0][1] + B[3][1] * A[1][1] + B[3][2] * A[2][1] + B[3][3] * A[3][1]; + R[3][2] = B[3][0] * A[0][2] + B[3][1] * A[1][2] + B[3][2] * A[2][2] + B[3][3] * A[3][2]; + R[3][3] = B[3][0] * A[0][3] + B[3][1] * A[1][3] + B[3][2] * A[2][3] + B[3][3] * A[3][3]; +} + void mul_m4_m4_pre(float R[4][4], const float A[4][4]) { BLI_assert(A != R); @@ -604,6 +696,26 @@ void mul_v3_m4v3(float r[3], const float mat[4][4], const float vec[3]) r[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2] + mat[3][2]; } +void mul_v3_m4v3_db(double r[3], const double mat[4][4], const double vec[3]) +{ + const double x = vec[0]; + const double y = vec[1]; + + r[0] = x * mat[0][0] + y * mat[1][0] + mat[2][0] * vec[2] + mat[3][0]; + r[1] = x * mat[0][1] + y * mat[1][1] + mat[2][1] * vec[2] + mat[3][1]; + r[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2] + mat[3][2]; +} +void mul_v4_m4v3_db(double r[4], const double mat[4][4], const double vec[3]) +{ + const double x = vec[0]; + const double y = vec[1]; + + r[0] = x * mat[0][0] + y * mat[1][0] + mat[2][0] * vec[2] + mat[3][0]; + r[1] = x * mat[0][1] + y * mat[1][1] + mat[2][1] * vec[2] + mat[3][1]; + r[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2] + mat[3][2]; + r[3] = x * mat[0][3] + y * mat[1][3] + mat[2][3] * vec[2] + mat[3][3]; +} + void mul_v2_m4v3(float r[2], const float mat[4][4], const float vec[3]) { const float x = vec[0]; @@ -646,6 +758,16 @@ void mul_v3_mat3_m4v3(float r[3], const float mat[4][4], const float vec[3]) r[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2]; } +void mul_v3_mat3_m4v3_db(double r[3], const double mat[4][4], const double vec[3]) +{ + const double x = vec[0]; + const double y = vec[1]; + + r[0] = x * mat[0][0] + y * mat[1][0] + mat[2][0] * vec[2]; + r[1] = x * mat[0][1] + y * mat[1][1] + mat[2][1] * vec[2]; + r[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2]; +} + void mul_project_m4_v3(const float mat[4][4], float vec[3]) { /* absolute value to not flip the frustum upside down behind the camera */ @@ -1891,7 +2013,7 @@ void rotate_m4(float mat[4][4], const char axis, const float angle) const float angle_cos = cosf(angle); const float angle_sin = sinf(angle); - assert(axis >= 'X' && axis <= 'Z'); + BLI_assert(axis >= 'X' && axis <= 'Z'); switch (axis) { case 'X': diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c index 47814b1080c..5762d164914 100644 --- a/source/blender/blenlib/intern/math_rotation.c +++ b/source/blender/blenlib/intern/math_rotation.c @@ -535,6 +535,49 @@ void rotation_between_quats_to_quat(float q[4], const float q1[4], const float q mul_qt_qtqt(q, tquat, q2); } +/** Decompose a quaternion into a swing rotation (quaternion with the selected + * axis component locked at zero), followed by a twist rotation around the axis. + * + * \param q: input quaternion. + * \param axis: twist axis in [0,1,2] + * \param r_swing[out]: if not NULL, receives the swing quaternion. + * \param r_twist[out]: if not NULL, receives the twist quaternion. + * \returns twist angle. + */ +float quat_split_swing_and_twist(const float q[4], int axis, float r_swing[4], float r_twist[4]) +{ + BLI_assert(axis >= 0 && axis <= 2); + + /* Half-twist angle can be computed directly. */ + float t = atan2f(q[axis + 1], q[0]); + + if (r_swing || r_twist) { + float sin_t = sinf(t), cos_t = cosf(t); + + /* Compute swing by multiplying the original quaternion by inverted twist. */ + if (r_swing) { + float twist_inv[4]; + + twist_inv[0] = cos_t; + zero_v3(twist_inv + 1); + twist_inv[axis + 1] = -sin_t; + + mul_qt_qtqt(r_swing, q, twist_inv); + + BLI_assert(fabsf(r_swing[axis + 1]) < BLI_ASSERT_UNIT_EPSILON); + } + + /* Output twist last just in case q ovelaps r_twist. */ + if (r_twist) { + r_twist[0] = cos_t; + zero_v3(r_twist + 1); + r_twist[axis + 1] = sin_t; + } + } + + return 2.0f * t; +} + /* -------------------------------------------------------------------- */ /** \name Quaternion Angle * @@ -644,8 +687,8 @@ void vec_to_quat(float q[4], const float vec[3], short axis, const short upflag) float nor[3], tvec[3]; float angle, si, co, len; - assert(axis >= 0 && axis <= 5); - assert(upflag >= 0 && upflag <= 2); + BLI_assert(axis >= 0 && axis <= 5); + BLI_assert(upflag >= 0 && upflag <= 2); /* first set the quat to unit */ unit_qt(q); @@ -1194,7 +1237,7 @@ void axis_angle_to_quat_single(float q[4], const char axis, const float angle) const float angle_sin = sinf(angle_half); const int axis_index = (axis - 'X'); - assert(axis >= 'X' && axis <= 'Z'); + BLI_assert(axis >= 'X' && axis <= 'Z'); q[0] = angle_cos; zero_v3(q + 1); @@ -1398,7 +1441,7 @@ void rotate_eul(float beul[3], const char axis, const float ang) { float eul[3], mat1[3][3], mat2[3][3], totmat[3][3]; - assert(axis >= 'X' && axis <= 'Z'); + BLI_assert(axis >= 'X' && axis <= 'Z'); eul[0] = eul[1] = eul[2] = 0.0f; if (axis == 'X') { @@ -1544,7 +1587,7 @@ static const RotOrderInfo rotOrders[] = { */ static const RotOrderInfo *get_rotation_order_info(const short order) { - assert(order >= 0 && order <= 6); + BLI_assert(order >= 0 && order <= 6); if (order < 1) { return &rotOrders[0]; } @@ -1813,7 +1856,7 @@ void rotate_eulO(float beul[3], const short order, char axis, float ang) { float eul[3], mat1[3][3], mat2[3][3], totmat[3][3]; - assert(axis >= 'X' && axis <= 'Z'); + BLI_assert(axis >= 'X' && axis <= 'Z'); zero_v3(eul); @@ -2119,8 +2162,8 @@ void quat_apply_track(float quat[4], short axis, short upflag) {0.0, sqrt_1_2, sqrt_1_2, 0.0}, }; - assert(axis >= 0 && axis <= 5); - assert(upflag >= 0 && upflag <= 2); + BLI_assert(axis >= 0 && axis <= 5); + BLI_assert(upflag >= 0 && upflag <= 2); mul_qt_qtqt(quat, quat, quat_track[axis]); @@ -2142,7 +2185,7 @@ void vec_apply_track(float vec[3], short axis) { float tvec[3]; - assert(axis >= 0 && axis <= 5); + BLI_assert(axis >= 0 && axis <= 5); copy_v3_v3(tvec, vec); diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c index 865c2f5dc25..b4b53a1dd58 100644 --- a/source/blender/blenlib/intern/math_vector_inline.c +++ b/source/blender/blenlib/intern/math_vector_inline.c @@ -355,6 +355,12 @@ MINLINE void add_v2_v2(float r[2], const float a[2]) r[1] += a[1]; } +MINLINE void add_v2_v2_db(double r[2], const double a[2]) +{ + r[0] += a[0]; + r[1] += a[1]; +} + MINLINE void add_v2_v2v2(float r[2], const float a[2], const float b[2]) { r[0] = a[0] + b[0]; @@ -374,6 +380,13 @@ MINLINE void add_v3_v3(float r[3], const float a[3]) r[2] += a[2]; } +MINLINE void add_v3_v3_db(double r[3], const double a[3]) +{ + r[0] += a[0]; + r[1] += a[1]; + r[2] += a[2]; +} + MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3]) { r[0] = a[0] + b[0]; @@ -423,6 +436,12 @@ MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2]) r[1] = a[1] - b[1]; } +MINLINE void sub_v2_v2v2_db(double r[2], const double a[2], const double b[2]) +{ + r[0] = a[0] - b[0]; + r[1] = a[1] - b[1]; +} + MINLINE void sub_v2_v2v2_int(int r[2], const int a[2], const int b[2]) { r[0] = a[0] - b[0]; @@ -450,6 +469,13 @@ MINLINE void sub_v3_v3v3_int(int r[3], const int a[3], const int b[3]) r[2] = a[2] - b[2]; } +MINLINE void sub_v3_v3v3_db(double r[3], const double a[3], const double b[3]) +{ + r[0] = a[0] - b[0]; + r[1] = a[1] - b[1]; + r[2] = a[2] - b[2]; +} + MINLINE void sub_v3db_v3fl_v3fl(double r[3], const float a[3], const float b[3]) { r[0] = (double)a[0] - (double)b[0]; @@ -492,6 +518,13 @@ MINLINE void mul_v3_fl(float r[3], float f) r[2] *= f; } +MINLINE void mul_v3db_db(double r[3], double f) +{ + r[0] *= f; + r[1] *= f; + r[2] *= f; +} + MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f) { r[0] = a[0] * f; @@ -809,6 +842,11 @@ MINLINE float dot_v2v2(const float a[2], const float b[2]) return a[0] * b[0] + a[1] * b[1]; } +MINLINE double dot_v2v2_db(const double a[2], const double b[2]) +{ + return a[0] * b[0] + a[1] * b[1]; +} + MINLINE float dot_v3v3(const float a[3], const float b[3]) { return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; @@ -836,6 +874,11 @@ MINLINE double dot_v3db_v3fl(const double a[3], const float b[3]) return a[0] * (double)b[0] + a[1] * (double)b[1] + a[2] * (double)b[2]; } +MINLINE double dot_v3v3_db(const double a[3], const double b[3]) +{ + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; +} + MINLINE float cross_v2v2(const float a[2], const float b[2]) { return a[0] * b[1] - a[1] * b[0]; @@ -859,6 +902,14 @@ MINLINE void cross_v3_v3v3_hi_prec(float r[3], const float a[3], const float b[3 r[2] = (float)((double)a[0] * (double)b[1] - (double)a[1] * (double)b[0]); } +MINLINE void cross_v3_v3v3_db(double r[3], const double a[3], const double b[3]) +{ + BLI_assert(r != a && r != b); + r[0] = a[1] * b[2] - a[2] * b[1]; + r[1] = a[2] * b[0] - a[0] * b[2]; + r[2] = a[0] * b[1] - a[1] * b[0]; +} + /* Newell's Method */ /* excuse this fairly specific function, * its used for polygon normals all over the place @@ -922,6 +973,15 @@ MINLINE float len_v2v2(const float v1[2], const float v2[2]) return sqrtf(x * x + y * y); } +MINLINE double len_v2v2_db(const double v1[2], const double v2[2]) +{ + double x, y; + + x = v1[0] - v2[0]; + y = v1[1] - v2[1]; + return sqrt(x * x + y * y); +} + MINLINE float len_v2v2_int(const int v1[2], const int v2[2]) { float x, y; @@ -944,6 +1004,14 @@ MINLINE float len_squared_v2v2(const float a[2], const float b[2]) return dot_v2v2(d, d); } +MINLINE double len_squared_v2v2_db(const double a[2], const double b[2]) +{ + double d[2]; + + sub_v2_v2v2_db(d, b, a); + return dot_v2v2_db(d, d); +} + MINLINE float len_squared_v3v3(const float a[3], const float b[3]) { float d[3]; diff --git a/source/blender/blenlib/intern/polyfill_2d_beautify.c b/source/blender/blenlib/intern/polyfill_2d_beautify.c index 3e94ae8de1f..ab397b86b1a 100644 --- a/source/blender/blenlib/intern/polyfill_2d_beautify.c +++ b/source/blender/blenlib/intern/polyfill_2d_beautify.c @@ -75,7 +75,7 @@ static int oedge_cmp(const void *a1, const void *a2) return -1; } - /* only for pradictability */ + /* Only for predictability. */ if (x1->e_half > x2->e_half) { return 1; } @@ -100,6 +100,10 @@ BLI_INLINE bool is_boundary_edge(uint i_a, uint i_b, const uint coord_last) * - When true, an existing zero area face on either side of the (2 - 4 * split will return a positive value. * - When false, the check must be non-biased towards either split direction. + * \param r_area: Return the area of the quad, + * This can be useful when comparing the return value with near zero epsilons. + * In this case the epsilon can be scaled by the area to avoid the return value + * of very large faces not having a reliable way to detect near-zero output. * * \return (negative number means the edge can be rotated, lager == better). */ @@ -107,7 +111,8 @@ float BLI_polyfill_beautify_quad_rotate_calc_ex(const float v1[2], const float v2[2], const float v3[2], const float v4[2], - const bool lock_degenerate) + const bool lock_degenerate, + float *r_area) { /* not a loop (only to be able to break out) */ do { @@ -121,6 +126,13 @@ float BLI_polyfill_beautify_quad_rotate_calc_ex(const float v1[2], BLI_assert((ELEM(v1, v2, v3, v4) == false) && (ELEM(v2, v1, v3, v4) == false) && (ELEM(v3, v1, v2, v4) == false) && (ELEM(v4, v1, v2, v3) == false)); + + if (r_area) { + *r_area = fabsf(area_2x_234) + fabsf(area_2x_241) + + /* Include both pairs for predictable results. */ + fabsf(area_2x_123) + fabsf(area_2x_134) / 8.0f; + } + /* * Test for unusable (1-3) state. * - Area sign flipping to check faces aren't going to point in opposite directions. @@ -191,7 +203,8 @@ float BLI_polyfill_beautify_quad_rotate_calc_ex(const float v1[2], static float polyedge_rotate_beauty_calc(const float (*coords)[2], const struct HalfEdge *edges, - const struct HalfEdge *e_a) + const struct HalfEdge *e_a, + float *r_area) { const struct HalfEdge *e_b = &edges[e_a->e_radial]; @@ -205,7 +218,7 @@ static float polyedge_rotate_beauty_calc(const float (*coords)[2], v3 = coords[e_b_other->v]; v4 = coords[e_b->v]; - return BLI_polyfill_beautify_quad_rotate_calc(v1, v2, v3, v4); + return BLI_polyfill_beautify_quad_rotate_calc_ex(v1, v2, v3, v4, false, r_area); } static void polyedge_beauty_cost_update_single(const float (*coords)[2], @@ -216,13 +229,18 @@ static void polyedge_beauty_cost_update_single(const float (*coords)[2], { const uint i = e->base_index; /* recalculate edge */ - const float cost = polyedge_rotate_beauty_calc(coords, edges, e); + float area; + const float cost = polyedge_rotate_beauty_calc(coords, edges, e, &area); /* We can get cases where both choices generate very small negative costs, * which leads to infinite loop. Anyway, costs above that are not worth recomputing, * maybe we could even optimize it to a smaller limit? * Actually, FLT_EPSILON is too small in some cases, 1e-6f seems to work OK hopefully? - * See T43578, T49478. */ - if (cost < -1e-6f) { + * See T43578, T49478. + * + * In fact a larger epsilon can still fail when the area of the face is very large, + * now the epsilon is scaled by the face area. + * See T56532. */ + if (cost < -1e-6f * max_ff(area, 1.0f)) { BLI_heap_insert_or_update(eheap, &eheap_table[i], cost, e); } else { @@ -381,7 +399,7 @@ void BLI_polyfill_beautify(const float (*coords)[2], for (uint i = 0; i < half_edges_len; i++, e++) { /* Accounts for boundary edged too (UINT_MAX). */ if (e->e_radial < i) { - const float cost = polyedge_rotate_beauty_calc(coords, half_edges, e); + const float cost = polyedge_rotate_beauty_calc(coords, half_edges, e, NULL); if (cost < 0.0f) { eheap_table[e->base_index] = BLI_heap_insert(eheap, cost, e); } diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index 3b69e257f45..4059e0401c0 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -663,8 +663,11 @@ static int left_number_strcmp(const char *s1, const char *s2, int *tiebreaker) return 0; } -/* natural string compare, keeping numbers in order */ -int BLI_natstrcmp(const char *s1, const char *s2) +/** + * Case insensitive, *natural* string comparison, + * keeping numbers in order. + */ +int BLI_strcasecmp_natural(const char *s1, const char *s2) { register int d1 = 0, d2 = 0; register char c1, c2; @@ -675,10 +678,7 @@ int BLI_natstrcmp(const char *s1, const char *s2) * numeric, else do a tolower and char compare */ while (1) { - c1 = tolower(s1[d1]); - c2 = tolower(s2[d2]); - - if (isdigit(c1) && isdigit(c2)) { + if (isdigit(s1[d1]) && isdigit(s2[d2])) { int numcompare = left_number_strcmp(s1 + d1, s2 + d2, &tiebreaker); if (numcompare != 0) { @@ -693,11 +693,11 @@ int BLI_natstrcmp(const char *s1, const char *s2) while (isdigit(s2[d2])) { d2++; } - - c1 = tolower(s1[d1]); - c2 = tolower(s2[d2]); } + c1 = tolower(s1[d1]); + c2 = tolower(s2[d2]); + /* first check for '.' so "foo.bar" comes before "foo 1.bar" */ if (c1 == '.' && c2 != '.') { return -1; diff --git a/source/blender/blenlib/intern/system.c b/source/blender/blenlib/intern/system.c index 88f2e2625e8..941c2b608e6 100644 --- a/source/blender/blenlib/intern/system.c +++ b/source/blender/blenlib/intern/system.c @@ -179,6 +179,19 @@ char *BLI_cpu_brand_string(void) return NULL; } +int BLI_cpu_support_sse41(void) +{ + int result[4], num; + __cpuid(result, 0); + num = result[0]; + + if (num >= 1) { + __cpuid(result, 0x00000001); + return (result[2] & ((int)1 << 19)) != 0; + } + return 0; +} + void BLI_hostname_get(char *buffer, size_t bufsize) { #ifndef WIN32 diff --git a/source/blender/blenlib/intern/winstuff.c b/source/blender/blenlib/intern/winstuff.c index 9e6ea0bb6ee..724f27f4667 100644 --- a/source/blender/blenlib/intern/winstuff.c +++ b/source/blender/blenlib/intern/winstuff.c @@ -172,17 +172,7 @@ void RegisterBlendExtension(void) BLI_getInstallationDir(InstallDir); GetSystemDirectory(SysDir, FILE_MAXDIR); -# ifdef _WIN64 - ThumbHandlerDLL = "BlendThumb64.dll"; -# else - IsWow64Process(GetCurrentProcess(), &IsWOW64); - if (IsWOW64 == true) { - ThumbHandlerDLL = "BlendThumb64.dll"; - } - else { - ThumbHandlerDLL = "BlendThumb.dll"; - } -# endif + ThumbHandlerDLL = "BlendThumb.dll"; snprintf( RegCmd, MAX_PATH * 2, "%s\\regsvr32 /s \"%s\\%s\"", SysDir, InstallDir, ThumbHandlerDLL); system(RegCmd); diff --git a/source/blender/blenloader/BLO_blend_defs.h b/source/blender/blenloader/BLO_blend_defs.h index 0787d054141..fec61605dca 100644 --- a/source/blender/blenloader/BLO_blend_defs.h +++ b/source/blender/blenloader/BLO_blend_defs.h @@ -18,7 +18,7 @@ /** \file * \ingroup blenloader - * \brief defines for blendfile codes + * \brief defines for blend-file codes. */ /* INTEGER CODES */ diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h index 8944dfdb711..adf3bf00d48 100644 --- a/source/blender/blenloader/BLO_readfile.h +++ b/source/blender/blenloader/BLO_readfile.h @@ -41,7 +41,6 @@ struct UserDef; struct View3D; struct ViewLayer; struct WorkSpace; -struct bContext; struct bScreen; struct wmWindowManager; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 91221ed3740..52d80c0cba1 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -223,7 +223,7 @@ * which keeps large arrays in memory from data-blocks we may not even use. * * \note This is disabled when using compression, - * while zlib supports seek ist's unusably slow, see: T61880. + * while zlib supports seek it's unusably slow, see: T61880. */ #define USE_BHEAD_READ_ON_DEMAND @@ -234,7 +234,7 @@ #define USE_GHASH_RESTORE_POINTER /* Define this to have verbose debug prints. */ -#define USE_DEBUG_PRINT +//#define USE_DEBUG_PRINT #ifdef USE_DEBUG_PRINT # define DEBUG_PRINTF(...) printf(__VA_ARGS__) @@ -272,13 +272,13 @@ typedef struct BHeadN { * because ID names are used in lookup tables. */ #define BHEAD_USE_READ_ON_DEMAND(bhead) ((bhead)->code == DATA) -/* this function ensures that reports are printed, - * in the case of libraray linking errors this is important! +/** + * This function ensures that reports are printed, + * in the case of library linking errors this is important! * * bit kludge but better then doubling up on prints, * we could alternatively have a versions of a report function which forces printing - campbell */ - void blo_reportf_wrap(ReportList *reports, ReportType type, const char *format, ...) { char fixed_buf[1024]; /* should be long enough */ @@ -534,7 +534,7 @@ static void split_libdata(ListBase *lb_src, Main **lib_main_array, const uint li if (id->lib) { if (((uint)id->lib->temp_index < lib_main_array_len) && - /* this check should never fail, just incase 'id->lib' is a dangling pointer. */ + /* this check should never fail, just in case 'id->lib' is a dangling pointer. */ (lib_main_array[id->lib->temp_index]->curlib == id->lib)) { Main *mainvar = lib_main_array[id->lib->temp_index]; ListBase *lb_dst = which_libbase(mainvar, GS(id->name)); @@ -2499,16 +2499,13 @@ static void IDP_DirectLinkProperty(IDProperty *prop, int switch_endian, FileData IDP_DirectLinkIDPArray(prop, switch_endian, fd); break; case IDP_DOUBLE: - /* erg, stupid doubles. since I'm storing them - * in the same field as int val; val2 in the - * IDPropertyData struct, they have to deal with - * endianness specifically + /* Workaround for doubles. + * They are stored in the same field as `int val, val2` in the IDPropertyData struct, + * they have to deal with endianness specifically. * - * in theory, val and val2 would've already been swapped + * In theory, val and val2 would've already been swapped * if switch_endian is true, so we have to first unswap - * them then reswap them as a single 64-bit entity. - */ - + * them then re-swap them as a single 64-bit entity. */ if (switch_endian) { BLI_endian_switch_int32(&prop->data.val); BLI_endian_switch_int32(&prop->data.val2); @@ -4899,21 +4896,13 @@ static void lib_link_mesh(FileData *fd, Main *main) G_MAIN = gmain; } - /* - * Re-tessellate, even if the polys were just created from tessfaces, this - * is important because it: - * - fill the CD_ORIGINDEX layer - * - gives consistency of tessface between loading from a file and - * converting an edited BMesh back into a mesh (i.e. it replaces - * quad tessfaces in a loaded mesh immediately, instead of lazily - * waiting until edit mode has been entered/exited, making it easier - * to recognize problems that would otherwise only show up after edits). - */ -#ifdef USE_TESSFACE_DEFAULT - BKE_mesh_tessface_calc(me); -#else + /* Deprecated, only kept for conversion. */ BKE_mesh_tessface_clear(me); -#endif + + /* Moved from do_versions because we need updated polygons for calculating normals. */ + if (MAIN_VERSION_OLDER(main, 256, 6)) { + BKE_mesh_calc_normals(me); + } me->id.tag &= ~LIB_TAG_NEED_LINK; } @@ -7719,8 +7708,8 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm) win->addmousemove = true; win->stereo3d_format = newdataadr(fd, win->stereo3d_format); - /* multiview always fallback to anaglyph at file opening - * otherwise quadbuffer saved files can break Blender */ + /* Multi-view always fallback to anaglyph at file opening + * otherwise quad-buffer saved files can break Blender. */ if (win->stereo3d_format) { win->stereo3d_format->display_mode = S3D_DISPLAY_ANAGLYPH; } @@ -9225,7 +9214,7 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, const int ta * flags dependency graph does not do animation update to avoid loss of unkeyed changes., * which conflicts with undo/redo of changes to animation data itself. * - * But for regular file load we clear the flag, since the flags might have been changed sinde + * But for regular file load we clear the flag, since the flags might have been changed since * the version the file has been saved with. */ if (!fd->memfile) { id->recalc = 0; @@ -11314,7 +11303,7 @@ static void add_collections_to_scene(Main *mainvar, } /* We do not want to force instantiation of indirectly linked collections, * not even when appending. Users can now easily instantiate collections (and their objects) - * as needed by themsleves. See T67032. */ + * as needed by themselves. See T67032. */ else if ((collection->id.tag & LIB_TAG_INDIRECT) == 0) { bool do_add_collection = (collection->id.tag & LIB_TAG_DOIT) != 0; if (!do_add_collection) { diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c index 6a5cfc45628..ba4dc2d33c7 100644 --- a/source/blender/blenloader/intern/versioning_250.c +++ b/source/blender/blenloader/intern/versioning_250.c @@ -2080,11 +2080,12 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *bmain) } } - if (bmain->versionfile < 256 || (bmain->versionfile == 256 && bmain->subversionfile < 6)) { - Mesh *me; - - for (me = bmain->meshes.first; me; me = me->id.next) { - BKE_mesh_calc_normals_tessface(me->mvert, me->totvert, me->mface, me->totface, NULL); + if (0) { + if (bmain->versionfile < 256 || (bmain->versionfile == 256 && bmain->subversionfile < 6)) { + for (Mesh *me = bmain->meshes.first; me; me = me->id.next) { + /* Vertex normal calculation from legacy 'MFace' has been removed. + * update after calculating polygons in file reading code instead. */ + } } } diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index b61692799ed..5010cc8071d 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -1748,7 +1748,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *bmain) for (Brush *br = bmain->brushes.first; br; br = br->id.next) { br->falloff_angle = DEG2RADF(80); br->flag &= ~(BRUSH_FLAG_UNUSED_1 | BRUSH_FLAG_UNUSED_6 | BRUSH_FLAG_UNUSED_7 | - BRUSH_FLAG_UNUSED_17 | BRUSH_FRONTFACE_FALLOFF); + BRUSH_SCENE_SPACING | BRUSH_FRONTFACE_FALLOFF); } for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) { diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index 1d2490229da..51c8a0d2a72 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -125,8 +125,8 @@ static void do_version_workspaces_create_from_screens(Main *bmain) } if (screen_parent) { - /* fullscreen with "Back to Previous" option, don't create - * a new workspace, add layout workspace containing parent */ + /* Full-screen with "Back to Previous" option, don't create + * a new workspace, add layout workspace containing parent. */ workspace = BLI_findstring( &bmain->workspaces, screen_parent->id.name + 2, offsetof(ID, name) + 2); } @@ -406,7 +406,7 @@ static void do_version_layers_to_collections(Main *bmain, Scene *scene) } /* Create collections from layers. */ - Collection *collection_master = BKE_collection_master(scene); + Collection *collection_master = scene->master_collection; Collection *collections[20] = {NULL}; for (int layer = 0; layer < 20; layer++) { @@ -735,13 +735,9 @@ static void do_versions_seq_alloc_transform_and_crop(ListBase *seqbase) } /* Return true if there is something to convert. */ -static bool do_versions_material_convert_legacy_blend_mode(bNodeTree *ntree, - char blend_method, - GSet *nodegrp_tree_set, - GSet *nooutput_tree_set) +static void do_versions_material_convert_legacy_blend_mode(bNodeTree *ntree, char blend_method) { bool need_update = false; - bool do_conversion = false; /* Iterate backwards from end so we don't encounter newly added links. */ bNodeLink *prevlink; @@ -754,31 +750,6 @@ static bool do_versions_material_convert_legacy_blend_mode(bNodeTree *ntree, bNode *tonode = link->tonode; bNodeSocket *tosock = link->tosock; - if (nodegrp_tree_set) { - if (fromnode->type == NODE_GROUP && fromnode->id != NULL) { - bNodeTree *group_ntree = (bNodeTree *)fromnode->id; - if (BLI_gset_add(nodegrp_tree_set, group_ntree)) { - /* Recursive but not convert (blend_method = -1). Conversion happens after. */ - if (!do_versions_material_convert_legacy_blend_mode( - group_ntree, -1, nodegrp_tree_set, nooutput_tree_set)) { - /* There is no output to convert in the tree. */ - BLI_gset_add(nooutput_tree_set, group_ntree); - } - } - } - if (tonode->type == NODE_GROUP && tonode->id != NULL) { - bNodeTree *group_ntree = (bNodeTree *)tonode->id; - if (BLI_gset_add(nodegrp_tree_set, group_ntree)) { - /* Recursive but not convert (blend_method = -1). Conversion happens after. */ - if (!do_versions_material_convert_legacy_blend_mode( - group_ntree, -1, nodegrp_tree_set, nooutput_tree_set)) { - /* There is no output to convert in the tree. */ - BLI_gset_add(nooutput_tree_set, group_ntree); - } - } - } - } - if (!(tonode->type == SH_NODE_OUTPUT_MATERIAL && STREQ(tosock->identifier, "Surface"))) { continue; } @@ -788,8 +759,6 @@ static bool do_versions_material_convert_legacy_blend_mode(bNodeTree *ntree, continue; } - do_conversion = true; - if (blend_method == 1 /* MA_BM_ADD */) { nodeRemLink(ntree, link); @@ -854,11 +823,9 @@ static bool do_versions_material_convert_legacy_blend_mode(bNodeTree *ntree, if (need_update) { ntreeUpdateTree(NULL, ntree); } - - return do_conversion; } -void do_versions_after_linking_280(Main *bmain, ReportList *reports) +void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports)) { bool use_collection_compat_28 = true; @@ -1259,74 +1226,20 @@ void do_versions_after_linking_280(Main *bmain, ReportList *reports) * now that we use dualsource blending. */ /* We take care of doing only nodetrees that are always part of materials * with old blending modes. */ - GSet *ntrees_additive = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); - GSet *ntrees_multiply = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); - GSet *ntrees_nolegacy = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); - GSet *ntrees_nooutput = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); for (Material *ma = bmain->materials.first; ma; ma = ma->id.next) { bNodeTree *ntree = ma->nodetree; if (ma->blend_method == 1 /* MA_BM_ADD */) { if (ma->use_nodes) { - do_versions_material_convert_legacy_blend_mode( - ntree, ma->blend_method, ntrees_additive, ntrees_nooutput); + do_versions_material_convert_legacy_blend_mode(ntree, 1 /* MA_BM_ADD */); } ma->blend_method = MA_BM_BLEND; } else if (ma->blend_method == 2 /* MA_BM_MULTIPLY */) { if (ma->use_nodes) { - do_versions_material_convert_legacy_blend_mode( - ntree, ma->blend_method, ntrees_multiply, ntrees_nooutput); + do_versions_material_convert_legacy_blend_mode(ntree, 2 /* MA_BM_MULTIPLY */); } ma->blend_method = MA_BM_BLEND; } - else { - /* Still tag the group nodes as not using legacy blend modes. */ - if (ma->use_nodes) { - do_versions_material_convert_legacy_blend_mode( - ntree, -1, ntrees_nolegacy, ntrees_nooutput); - } - } - } - GHashIterState iter = {0}; - bNodeTree *ntree; - /* Remove trees that have no output nodes. - * This is done separately to avoid infinite recursion. */ - while (BLI_gset_pop(ntrees_nooutput, (GSetIterState *)&iter, (void **)&ntree)) { - BLI_gset_remove(ntrees_additive, ntree, NULL); - BLI_gset_remove(ntrees_multiply, ntree, NULL); - BLI_gset_remove(ntrees_nolegacy, ntree, NULL); - } - BLI_gset_free(ntrees_nooutput, NULL); - /* Remove group nodetree that are used by material using non-legacy blend mode. */ - GHashIterState iter_rm = {0}; - bool error = false; - while (BLI_gset_pop(ntrees_nolegacy, (GSetIterState *)&iter_rm, (void **)&ntree)) { - if (BLI_gset_remove(ntrees_additive, ntree, NULL)) { - error = true; - } - if (BLI_gset_remove(ntrees_multiply, ntree, NULL)) { - error = true; - } - } - BLI_gset_free(ntrees_nolegacy, NULL); - /* Convert remaining group nodetree. */ - GHashIterState iter_add = {0}; - GHashIterState iter_mul = {0}; - while (BLI_gset_pop(ntrees_additive, (GSetIterState *)&iter_add, (void **)&ntree)) { - do_versions_material_convert_legacy_blend_mode(ntree, 1 /* MA_BM_ADD */, NULL, NULL); - } - while (BLI_gset_pop(ntrees_multiply, (GSetIterState *)&iter_mul, (void **)&ntree)) { - do_versions_material_convert_legacy_blend_mode(ntree, 2 /* MA_BM_MULTIPLY */, NULL, NULL); - } - BLI_gset_free(ntrees_additive, NULL); - BLI_gset_free(ntrees_multiply, NULL); - - if (error) { - BKE_report(reports, RPT_ERROR, "Eevee material conversion problem. Error in console"); - printf( - "One or more group nodetrees containing a material output were found" - " in both a material using deprecated blend mode and a normal one.\n" - "Nothing in these nodetrees was changed and manual update is required.\n"); } } } @@ -3792,8 +3705,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } } - { - /* Versioning code until next subversion bump goes here. */ + if (!MAIN_VERSION_ATLEAST(bmain, 281, 3)) { if (U.view_rotate_sensitivity_turntable == 0) { U.view_rotate_sensitivity_turntable = DEG2RADF(0.4f); U.view_rotate_sensitivity_trackball = 1.0f; @@ -3808,6 +3720,12 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) ar->alignment = RGN_ALIGN_RIGHT; } } + /* Mark outliners as dirty for syncing and enable synced selection */ + if (sl->spacetype == SPACE_OUTLINER) { + SpaceOutliner *soutliner = (SpaceOutliner *)sl; + soutliner->sync_select_dirty |= WM_OUTLINER_SYNC_SELECT_FROM_ALL; + soutliner->flag |= SO_SYNC_SELECT; + } } } } @@ -3817,4 +3735,69 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } } } + + if (!MAIN_VERSION_ATLEAST(bmain, 281, 4)) { + ID *id; + FOREACH_MAIN_ID_BEGIN (bmain, id) { + bNodeTree *ntree = ntreeFromID(id); + if (ntree) { + ntree->id.flag |= LIB_PRIVATE_DATA; + } + } + FOREACH_MAIN_ID_END; + } + + if (!MAIN_VERSION_ATLEAST(bmain, 281, 5)) { + for (Brush *br = bmain->brushes.first; br; br = br->id.next) { + if (br->ob_mode & OB_MODE_SCULPT && br->normal_radius_factor == 0.0f) { + br->normal_radius_factor = 0.5f; + } + } + + LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { + /* Older files do not have a master collection, which is then added through + * `BKE_collection_master_add()`, so everything is fine. */ + if (scene->master_collection != NULL) { + scene->master_collection->id.flag |= LIB_PRIVATE_DATA; + } + } + } + + { + /* Versioning code until next subversion bump goes here. */ + + for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) { + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { + for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) { + if (sl->spacetype == SPACE_FILE) { + SpaceFile *sfile = (SpaceFile *)sl; + ListBase *regionbase = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase; + ARegion *ar_ui = do_versions_find_region(regionbase, RGN_TYPE_UI); + ARegion *ar_header = do_versions_find_region(regionbase, RGN_TYPE_HEADER); + ARegion *ar_toolprops = do_versions_find_region_or_null(regionbase, + RGN_TYPE_TOOL_PROPS); + + /* Reinsert UI region so that it spawns entire area width */ + BLI_remlink(regionbase, ar_ui); + BLI_insertlinkafter(regionbase, ar_header, ar_ui); + + ar_ui->flag |= RGN_FLAG_DYNAMIC_SIZE; + + if (ar_toolprops && (ar_toolprops->alignment == (RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV))) { + SpaceType *stype = BKE_spacetype_from_id(sl->spacetype); + + /* Remove empty region at old location. */ + BLI_assert(sfile->op == NULL); + BKE_area_region_free(stype, ar_toolprops); + BLI_freelinkN(regionbase, ar_toolprops); + } + + if (sfile->params) { + sfile->params->details_flags |= FILE_DETAILS_SIZE | FILE_DETAILS_DATETIME; + } + } + } + } + } + } } diff --git a/source/blender/blenloader/intern/versioning_cycles.c b/source/blender/blenloader/intern/versioning_cycles.c index cebe15e2719..a3e9b8dc206 100644 --- a/source/blender/blenloader/intern/versioning_cycles.c +++ b/source/blender/blenloader/intern/versioning_cycles.c @@ -26,6 +26,7 @@ #include "BLI_math.h" #include "BLI_string.h" +#include "BLI_listbase.h" #include "BLI_utildefines.h" #include "DNA_color_types.h" @@ -44,6 +45,11 @@ #include "BLO_readfile.h" #include "readfile.h" +static bool socket_is_used(bNodeSocket *sock) +{ + return sock->flag & SOCK_IN_USE; +} + static float *cycles_node_socket_float_value(bNodeSocket *socket) { bNodeSocketValueFloat *socket_data = socket->default_value; @@ -56,6 +62,12 @@ static float *cycles_node_socket_rgba_value(bNodeSocket *socket) return socket_data->value; } +static float *cycles_node_socket_vector_value(bNodeSocket *socket) +{ + bNodeSocketValueVector *socket_data = socket->default_value; + return socket_data->value; +} + static IDProperty *cycles_properties_from_ID(ID *id) { IDProperty *idprop = IDP_GetProperties(id, false); @@ -185,7 +197,7 @@ static void square_roughness_node_insert(bNodeTree *ntree) /* Add sqrt node. */ bNode *node = nodeAddStaticNode(NULL, ntree, SH_NODE_MATH); - node->custom1 = NODE_MATH_POW; + node->custom1 = NODE_MATH_POWER; node->locx = 0.5f * (fromnode->locx + tonode->locx); node->locy = 0.5f * (fromnode->locy + tonode->locy); @@ -385,6 +397,365 @@ static void light_emission_unify(Light *light, const char *engine) } } +/* The B input of the Math node is no longer used for single-operand operators. + * Previously, if the B input was linked and the A input was not, the B input + * was used as the input of the operator. To correct this, we move the link + * from B to A if B is linked and A is not. + */ +static void update_math_node_single_operand_operators(bNodeTree *ntree) +{ + bool need_update = false; + + for (bNode *node = ntree->nodes.first; node; node = node->next) { + if (node->type == SH_NODE_MATH) { + if (ELEM(node->custom1, + NODE_MATH_SQRT, + NODE_MATH_CEIL, + NODE_MATH_SINE, + NODE_MATH_ROUND, + NODE_MATH_FLOOR, + NODE_MATH_COSINE, + NODE_MATH_ARCSINE, + NODE_MATH_TANGENT, + NODE_MATH_ABSOLUTE, + NODE_MATH_FRACTION, + NODE_MATH_ARCCOSINE, + NODE_MATH_ARCTANGENT)) { + bNodeSocket *sockA = BLI_findlink(&node->inputs, 0); + bNodeSocket *sockB = BLI_findlink(&node->inputs, 1); + if (!sockA->link && sockB->link) { + nodeAddLink(ntree, sockB->link->fromnode, sockB->link->fromsock, node, sockA); + nodeRemLink(ntree, sockB->link); + need_update = true; + } + } + } + } + + if (need_update) { + ntreeUpdateTree(NULL, ntree); + } +} + +/* The Value output of the Vector Math node is no longer available in the Add + * and Subtract operators. Previously, this Value output was computed from the + * Vector output V as follows: + * + * Value = (abs(V.x) + abs(V.y) + abs(V.z)) / 3 + * + * Or more compactly using vector operators: + * + * Value = dot(abs(V), (1 / 3, 1 / 3, 1 / 3)) + * + * To correct this, if the Value output was used, we are going to compute + * it using the second equation by adding an absolute and a dot node, and + * then connect them appropriately. + */ +static void update_vector_math_node_add_and_subtract_operators(bNodeTree *ntree) +{ + bool need_update = false; + + for (bNode *node = ntree->nodes.first; node; node = node->next) { + if (node->type == SH_NODE_VECTOR_MATH) { + bNodeSocket *sockOutValue = nodeFindSocket(node, SOCK_OUT, "Value"); + if (socket_is_used(sockOutValue) && + ELEM(node->custom1, NODE_VECTOR_MATH_ADD, NODE_VECTOR_MATH_SUBTRACT)) { + + bNode *absNode = nodeAddStaticNode(NULL, ntree, SH_NODE_VECTOR_MATH); + absNode->custom1 = NODE_VECTOR_MATH_ABSOLUTE; + absNode->locx = node->locx + node->width + 20.0f; + absNode->locy = node->locy; + + bNode *dotNode = nodeAddStaticNode(NULL, ntree, SH_NODE_VECTOR_MATH); + dotNode->custom1 = NODE_VECTOR_MATH_DOT_PRODUCT; + dotNode->locx = absNode->locx + absNode->width + 20.0f; + dotNode->locy = absNode->locy; + bNodeSocket *sockDotB = BLI_findlink(&dotNode->inputs, 1); + bNodeSocket *sockDotOutValue = nodeFindSocket(dotNode, SOCK_OUT, "Value"); + copy_v3_fl(cycles_node_socket_vector_value(sockDotB), 1 / 3.0f); + + LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) { + if (link->fromsock == sockOutValue) { + nodeAddLink(ntree, dotNode, sockDotOutValue, link->tonode, link->tosock); + nodeRemLink(ntree, link); + } + } + + bNodeSocket *sockAbsA = BLI_findlink(&absNode->inputs, 0); + bNodeSocket *sockDotA = BLI_findlink(&dotNode->inputs, 0); + bNodeSocket *sockOutVector = nodeFindSocket(node, SOCK_OUT, "Vector"); + bNodeSocket *sockAbsOutVector = nodeFindSocket(absNode, SOCK_OUT, "Vector"); + + nodeAddLink(ntree, node, sockOutVector, absNode, sockAbsA); + nodeAddLink(ntree, absNode, sockAbsOutVector, dotNode, sockDotA); + + need_update = true; + } + } + } + + if (need_update) { + ntreeUpdateTree(NULL, ntree); + } +} + +/* The Vector output of the Vector Math node is no longer available in the Dot + * Product operator. Previously, this Vector was always zero initialized. To + * correct this, we zero out any socket the Vector Output was connected to. + */ +static void update_vector_math_node_dot_product_operator(bNodeTree *ntree) +{ + bool need_update = false; + + for (bNode *node = ntree->nodes.first; node; node = node->next) { + if (node->type == SH_NODE_VECTOR_MATH) { + bNodeSocket *sockOutVector = nodeFindSocket(node, SOCK_OUT, "Vector"); + if (socket_is_used(sockOutVector) && node->custom1 == NODE_VECTOR_MATH_DOT_PRODUCT) { + LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) { + if (link->fromsock == sockOutVector) { + switch (link->tosock->type) { + case SOCK_FLOAT: + *cycles_node_socket_float_value(link->tosock) = 0.0f; + break; + case SOCK_VECTOR: + copy_v3_fl(cycles_node_socket_vector_value(link->tosock), 0.0f); + break; + case SOCK_RGBA: + copy_v4_fl(cycles_node_socket_rgba_value(link->tosock), 0.0f); + break; + } + nodeRemLink(ntree, link); + } + } + need_update = true; + } + } + } + + if (need_update) { + ntreeUpdateTree(NULL, ntree); + } +} + +/* Previously, the Vector output of the cross product operator was normalized. + * To correct this, a Normalize node is added to normalize the output if used. + * Moreover, the Value output was removed. This Value was equal to the length + * of the cross product. To correct this, a Length node is added if needed. + */ +static void update_vector_math_node_cross_product_operator(bNodeTree *ntree) +{ + bool need_update = false; + + for (bNode *node = ntree->nodes.first; node; node = node->next) { + if (node->type == SH_NODE_VECTOR_MATH) { + if (node->custom1 == NODE_VECTOR_MATH_CROSS_PRODUCT) { + bNodeSocket *sockOutVector = nodeFindSocket(node, SOCK_OUT, "Vector"); + if (socket_is_used(sockOutVector)) { + bNode *normalizeNode = nodeAddStaticNode(NULL, ntree, SH_NODE_VECTOR_MATH); + normalizeNode->custom1 = NODE_VECTOR_MATH_NORMALIZE; + normalizeNode->locx = node->locx + node->width + 20.0f; + normalizeNode->locy = node->locy; + bNodeSocket *sockNormalizeOut = nodeFindSocket(normalizeNode, SOCK_OUT, "Vector"); + + LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) { + if (link->fromsock == sockOutVector) { + nodeAddLink(ntree, normalizeNode, sockNormalizeOut, link->tonode, link->tosock); + nodeRemLink(ntree, link); + } + } + bNodeSocket *sockNormalizeA = BLI_findlink(&normalizeNode->inputs, 0); + nodeAddLink(ntree, node, sockOutVector, normalizeNode, sockNormalizeA); + + need_update = true; + } + + bNodeSocket *sockOutValue = nodeFindSocket(node, SOCK_OUT, "Value"); + if (socket_is_used(sockOutValue)) { + bNode *lengthNode = nodeAddStaticNode(NULL, ntree, SH_NODE_VECTOR_MATH); + lengthNode->custom1 = NODE_VECTOR_MATH_LENGTH; + lengthNode->locx = node->locx + node->width + 20.0f; + if (socket_is_used(sockOutVector)) { + lengthNode->locy = node->locy - lengthNode->height - 20.0f; + } + else { + lengthNode->locy = node->locy; + } + bNodeSocket *sockLengthOut = nodeFindSocket(lengthNode, SOCK_OUT, "Value"); + + LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) { + if (link->fromsock == sockOutValue) { + nodeAddLink(ntree, lengthNode, sockLengthOut, link->tonode, link->tosock); + nodeRemLink(ntree, link); + } + } + bNodeSocket *sockLengthA = BLI_findlink(&lengthNode->inputs, 0); + nodeAddLink(ntree, node, sockOutVector, lengthNode, sockLengthA); + + need_update = true; + } + } + } + } + + if (need_update) { + ntreeUpdateTree(NULL, ntree); + } +} + +/* The Value output of the Vector Math node is no longer available in the + * Normalize operator. This Value output was equal to the length of the + * the input vector A. To correct this, we either add a Length node or + * convert the Normalize node into a Length node, depending on if the + * Vector output is needed. + */ +static void update_vector_math_node_normalize_operator(bNodeTree *ntree) +{ + bool need_update = false; + + for (bNode *node = ntree->nodes.first; node; node = node->next) { + if (node->type == SH_NODE_VECTOR_MATH) { + bNodeSocket *sockOutValue = nodeFindSocket(node, SOCK_OUT, "Value"); + if (node->custom1 == NODE_VECTOR_MATH_NORMALIZE && socket_is_used(sockOutValue)) { + bNodeSocket *sockOutVector = nodeFindSocket(node, SOCK_OUT, "Vector"); + if (socket_is_used(sockOutVector)) { + bNode *lengthNode = nodeAddStaticNode(NULL, ntree, SH_NODE_VECTOR_MATH); + lengthNode->custom1 = NODE_VECTOR_MATH_LENGTH; + lengthNode->locx = node->locx + node->width + 20.0f; + lengthNode->locy = node->locy; + bNodeSocket *sockLengthValue = nodeFindSocket(lengthNode, SOCK_OUT, "Value"); + + LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) { + if (link->fromsock == sockOutValue) { + nodeAddLink(ntree, lengthNode, sockLengthValue, link->tonode, link->tosock); + nodeRemLink(ntree, link); + } + } + bNodeSocket *sockA = BLI_findlink(&node->inputs, 0); + bNodeSocket *sockLengthA = BLI_findlink(&lengthNode->inputs, 0); + if (sockA->link) { + bNodeLink *link = sockA->link; + nodeAddLink(ntree, link->fromnode, link->fromsock, lengthNode, sockLengthA); + } + else { + copy_v3_v3(cycles_node_socket_vector_value(sockLengthA), + cycles_node_socket_vector_value(sockA)); + } + + need_update = true; + } + else { + node->custom1 = NODE_VECTOR_MATH_LENGTH; + } + } + } + } + if (need_update) { + ntreeUpdateTree(NULL, ntree); + } +} + +/* The Vector Math operator types didn't have an enum, but rather, their + * values were hard coded into the code. After the enum was created and + * after more vector operators were added, the hard coded values needs + * to be remapped to their correct enum values. To fix this, we remap + * the values according to the following rules: + * + * Dot Product Operator : 3 -> 7 + * Normalize Operator : 5 -> 11 + * + * Additionally, since the Average operator was removed, it is assigned + * a value of -1 just to be identified later in the versioning code: + * + * Average Operator : 2 -> -1 + * + */ +static void update_vector_math_node_operators_enum_mapping(bNodeTree *ntree) +{ + for (bNode *node = ntree->nodes.first; node; node = node->next) { + if (node->type == SH_NODE_VECTOR_MATH) { + switch (node->custom1) { + case 2: + node->custom1 = -1; + break; + case 3: + node->custom1 = 7; + break; + case 5: + node->custom1 = 11; + break; + } + } + } +} + +/* The Average operator is no longer available in the Vector Math node. + * The Vector output was equal to the normalized sum of input vectors while + * the Value output was equal to the length of the sum of input vectors. + * To correct this, we convert the node into an Add node and add a length + * node or a normalize node if needed. + */ +static void update_vector_math_node_average_operator(bNodeTree *ntree) +{ + bool need_update = false; + + for (bNode *node = ntree->nodes.first; node; node = node->next) { + if (node->type == SH_NODE_VECTOR_MATH) { + /* See update_vector_math_node_operators_enum_mapping. */ + if (node->custom1 == -1) { + node->custom1 = NODE_VECTOR_MATH_ADD; + bNodeSocket *sockOutVector = nodeFindSocket(node, SOCK_OUT, "Vector"); + if (socket_is_used(sockOutVector)) { + bNode *normalizeNode = nodeAddStaticNode(NULL, ntree, SH_NODE_VECTOR_MATH); + normalizeNode->custom1 = NODE_VECTOR_MATH_NORMALIZE; + normalizeNode->locx = node->locx + node->width + 20.0f; + normalizeNode->locy = node->locy; + bNodeSocket *sockNormalizeOut = nodeFindSocket(normalizeNode, SOCK_OUT, "Vector"); + + LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) { + if (link->fromsock == sockOutVector) { + nodeAddLink(ntree, normalizeNode, sockNormalizeOut, link->tonode, link->tosock); + nodeRemLink(ntree, link); + } + } + bNodeSocket *sockNormalizeA = BLI_findlink(&normalizeNode->inputs, 0); + nodeAddLink(ntree, node, sockOutVector, normalizeNode, sockNormalizeA); + + need_update = true; + } + + bNodeSocket *sockOutValue = nodeFindSocket(node, SOCK_OUT, "Value"); + if (socket_is_used(sockOutValue)) { + bNode *lengthNode = nodeAddStaticNode(NULL, ntree, SH_NODE_VECTOR_MATH); + lengthNode->custom1 = NODE_VECTOR_MATH_LENGTH; + lengthNode->locx = node->locx + node->width + 20.0f; + if (socket_is_used(sockOutVector)) { + lengthNode->locy = node->locy - lengthNode->height - 20.0f; + } + else { + lengthNode->locy = node->locy; + } + bNodeSocket *sockLengthOut = nodeFindSocket(lengthNode, SOCK_OUT, "Value"); + + LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) { + if (link->fromsock == sockOutValue) { + nodeAddLink(ntree, lengthNode, sockLengthOut, link->tonode, link->tosock); + nodeRemLink(ntree, link); + } + } + bNodeSocket *sockLengthA = BLI_findlink(&lengthNode->inputs, 0); + nodeAddLink(ntree, node, sockOutVector, lengthNode, sockLengthA); + + need_update = true; + } + } + } + } + + if (need_update) { + ntreeUpdateTree(NULL, ntree); + } +} + void blo_do_versions_cycles(FileData *UNUSED(fd), Library *UNUSED(lib), Main *bmain) { /* Particle shape shared with Eevee. */ @@ -417,6 +788,15 @@ void blo_do_versions_cycles(FileData *UNUSED(fd), Library *UNUSED(lib), Main *bm } } } + + if (!MAIN_VERSION_ATLEAST(bmain, 281, 3)) { + FOREACH_NODETREE_BEGIN (bmain, ntree, id) { + if (ntree->type == NTREE_SHADER) { + update_vector_math_node_operators_enum_mapping(ntree); + } + } + FOREACH_NODETREE_END; + } } void do_versions_after_linking_cycles(Main *bmain) @@ -526,4 +906,26 @@ void do_versions_after_linking_cycles(Main *bmain) } } } + + if (!MAIN_VERSION_ATLEAST(bmain, 281, 2)) { + FOREACH_NODETREE_BEGIN (bmain, ntree, id) { + if (ntree->type == NTREE_SHADER) { + update_math_node_single_operand_operators(ntree); + } + } + FOREACH_NODETREE_END; + } + + if (!MAIN_VERSION_ATLEAST(bmain, 281, 3)) { + FOREACH_NODETREE_BEGIN (bmain, ntree, id) { + if (ntree->type == NTREE_SHADER) { + update_vector_math_node_add_and_subtract_operators(ntree); + update_vector_math_node_dot_product_operator(ntree); + update_vector_math_node_cross_product_operator(ntree); + update_vector_math_node_normalize_operator(ntree); + update_vector_math_node_average_operator(ntree); + } + } + FOREACH_NODETREE_END; + } } diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c index fa69892584a..fa22fd46068 100644 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ b/source/blender/blenloader/intern/versioning_defaults.c @@ -329,6 +329,14 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template) BLI_strncpy(screen->id.name + 2, workspace->id.name + 2, sizeof(screen->id.name) - 2); BLI_libblock_ensure_unique_name(bmain, screen->id.name); } + + /* For some reason we have unused screens, needed until re-saving. + * Clear unused layouts because they're visible in the outliner & Python API. */ + LISTBASE_FOREACH_MUTABLE (WorkSpaceLayout *, layout_iter, &workspace->layouts) { + if (layout != layout_iter) { + BKE_workspace_layout_remove(bmain, workspace, layout_iter); + } + } } /* Scenes */ diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c index e987a623d0b..67b8ce1d0de 100644 --- a/source/blender/blenloader/intern/versioning_userdef.c +++ b/source/blender/blenloader/intern/versioning_userdef.c @@ -141,10 +141,16 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme) FROM_DEFAULT_V4_UCHAR(space_outliner.row_alternate); } + if (!USER_VERSION_ATLEAST(281, 3)) { + FROM_DEFAULT_V4_UCHAR(space_outliner.selected_highlight); + FROM_DEFAULT_V4_UCHAR(space_outliner.active); + } + /** * Include next version bump. */ { + FROM_DEFAULT_V4_UCHAR(space_file.execution_buts); } #undef FROM_DEFAULT_V4_UCHAR diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index d8889db7f2d..e81fa9fd2ff 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1143,9 +1143,12 @@ typedef struct RenderInfo { char scene_name[MAX_ID_NAME - 2]; } RenderInfo; -/* was for historic render-deamon feature, - * now write because it can be easily extracted without - * reading the whole blend file */ +/** + * This was originally added for the historic render-daemon feature, + * now write because it can be easily extracted without reading the whole blend file. + * + * See: `release/scripts/modules/blend_render_info.py` + */ static void write_renderinfo(WriteData *wd, Main *mainvar) { bScreen *curscreen; diff --git a/source/blender/blentranslation/msgfmt/msgfmt.c b/source/blender/blentranslation/msgfmt/msgfmt.c index 215c92f87de..4691d791301 100644 --- a/source/blender/blentranslation/msgfmt/msgfmt.c +++ b/source/blender/blentranslation/msgfmt/msgfmt.c @@ -24,7 +24,7 @@ * * Generate binary message catalog from textual translation description. * - * This program converts a textual Uniforum-style message catalog (.po file) + * This program converts a textual Uniform-style message catalog (.po file) * into a binary GNU catalog (.mo file). * This is essentially the same function as the GNU msgfmt program, * however, it is a simpler implementation. diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c index 5aec59ccd5d..788edc348d9 100644 --- a/source/blender/bmesh/intern/bmesh_marking.c +++ b/source/blender/bmesh/intern/bmesh_marking.c @@ -870,9 +870,11 @@ void BM_editselection_normal(BMEditSelection *ese, float r_normal[3]) } } -/* Calculate a plane that is rightangles to the edge/vert/faces normal +/** + * Calculate a plane that is right angles to the edge/vert/faces normal * also make the plane run along an axis that is related to the geometry, - * because this is used for the gizmos Y axis. */ + * because this is used for the gizmos Y axis. + */ void BM_editselection_plane(BMEditSelection *ese, float r_plane[3]) { if (ese->htype == BM_VERT) { diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c index 2000689b496..9bab959f0a2 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.c +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c @@ -422,7 +422,7 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar /* don't use 'j' since we may have skipped some faces, hence some loops. */ BM_elem_index_set(l_iter, totloops++); /* set_ok */ - /* Save index of correspsonding MLoop */ + /* Save index of corresponding #MLoop. */ CustomData_to_bmesh_block(&me->ldata, &bm->ldata, j++, &l_iter->head.data, true); } while ((l_iter = l_iter->next) != l_first); diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index b9f0bcc05f0..7086cea1ace 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -369,28 +369,6 @@ static BMOpDefine bmo_remove_doubles_def = { }; /* - * Auto Merge. - * - * Finds groups of vertices closer then **dist** and merges them together, - * using the weld verts bmop. The merges must go from a vert not in - * **verts** to one in **verts**. - */ -static BMOpDefine bmo_automerge_def = { - "automerge", - /* slots_in */ - {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input verts */ - {"dist", BMO_OP_SLOT_FLT}, /* maximum distance */ - {{'\0'}}, - }, - {{{'\0'}}}, /* no output */ - bmo_automerge_exec, - (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | - BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH | - BMO_OPTYPE_FLAG_SELECT_VALIDATE), -}; - -/* * Collapse Connected. * * Collapses connected vertices @@ -2073,7 +2051,6 @@ static BMOpDefine bmo_symmetrize_def = { /* clang-format on */ const BMOpDefine *bmo_opdefines[] = { - &bmo_automerge_def, &bmo_average_vert_facedata_def, &bmo_beautify_fill_def, &bmo_bevel_def, diff --git a/source/blender/bmesh/intern/bmesh_operators_private.h b/source/blender/bmesh/intern/bmesh_operators_private.h index 8658f6c233c..137c5aa338e 100644 --- a/source/blender/bmesh/intern/bmesh_operators_private.h +++ b/source/blender/bmesh/intern/bmesh_operators_private.h @@ -24,7 +24,6 @@ struct BMOperator; struct BMesh; -void bmo_automerge_exec(BMesh *bm, BMOperator *op); void bmo_average_vert_facedata_exec(BMesh *bm, BMOperator *op); void bmo_beautify_fill_exec(BMesh *bm, BMOperator *op); void bmo_bevel_exec(BMesh *bm, BMOperator *op); diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index dc839054987..915ad6bf5c4 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -483,7 +483,7 @@ void BM_face_calc_tangent_edge_diagonal(const BMFace *f, float r_tangent[3]) l_iter = l_first = BM_FACE_FIRST_LOOP(f); - /* incase of degenerate faces */ + /* In case of degenerate faces. */ zero_v3(r_tangent); /* warning: O(n^2) loop here, take care! */ @@ -520,7 +520,7 @@ void BM_face_calc_tangent_vert_diagonal(const BMFace *f, float r_tangent[3]) l_iter = l_first = BM_FACE_FIRST_LOOP(f); - /* incase of degenerate faces */ + /* In case of degenerate faces. */ zero_v3(r_tangent); /* warning: O(n^2) loop here, take care! */ diff --git a/source/blender/bmesh/intern/bmesh_query.c b/source/blender/bmesh/intern/bmesh_query.c index 4a47bcccb25..219bec15e5b 100644 --- a/source/blender/bmesh/intern/bmesh_query.c +++ b/source/blender/bmesh/intern/bmesh_query.c @@ -207,6 +207,34 @@ bool BM_vert_pair_share_face_check_cb(BMVert *v_a, return false; } +BMFace *BM_vert_pair_shared_face_cb(BMVert *v_a, + BMVert *v_b, + const bool allow_adjacent, + bool (*callback)(BMFace *, BMLoop *, BMLoop *, void *userdata), + void *user_data, + BMLoop **r_l_a, + BMLoop **r_l_b) +{ + if (v_a->e && v_b->e) { + BMIter iter; + BMLoop *l_a, *l_b; + + BM_ITER_ELEM (l_a, &iter, v_a, BM_LOOPS_OF_VERT) { + BMFace *f = l_a->f; + l_b = BM_face_vert_share_loop(f, v_b); + if (l_b && (allow_adjacent || !BM_loop_is_adjacent(l_a, l_b)) && + callback(f, l_a, l_b, user_data)) { + *r_l_a = l_a; + *r_l_b = l_b; + + return f; + } + } + } + + return NULL; +} + /** * Given 2 verts, find the smallest face they share and give back both loops. */ @@ -1542,7 +1570,7 @@ float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon_sq, /** * #BM_loop_calc_face_normal_safe_ex with pre-defined sane epsilon. * - * Since this doesn't scale baed on triangle size, fixed value works well. + * Since this doesn't scale based on triangle size, fixed value works well. */ float BM_loop_calc_face_normal_safe(const BMLoop *l, float r_normal[3]) { diff --git a/source/blender/bmesh/intern/bmesh_query.h b/source/blender/bmesh/intern/bmesh_query.h index e96984490c0..3a864fbb5dd 100644 --- a/source/blender/bmesh/intern/bmesh_query.h +++ b/source/blender/bmesh/intern/bmesh_query.h @@ -62,6 +62,13 @@ bool BM_vert_pair_share_face_check_cb(BMVert *v_a, bool (*test_fn)(BMFace *f, void *user_data), void *user_data) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3); +BMFace *BM_vert_pair_shared_face_cb(BMVert *v_a, + BMVert *v_b, + const bool allow_adjacent, + bool (*callback)(BMFace *, BMLoop *, BMLoop *, void *userdata), + void *user_data, + BMLoop **r_l_a, + BMLoop **r_l_b) ATTR_NONNULL(1, 2, 4, 6, 7); BMFace *BM_vert_pair_share_face_by_len(BMVert *v_a, BMVert *v_b, BMLoop **r_l_a, diff --git a/source/blender/bmesh/intern/bmesh_walkers_impl.c b/source/blender/bmesh/intern/bmesh_walkers_impl.c index ade6fdfcbed..f317c59b8d1 100644 --- a/source/blender/bmesh/intern/bmesh_walkers_impl.c +++ b/source/blender/bmesh/intern/bmesh_walkers_impl.c @@ -648,7 +648,7 @@ static void *bmw_ConnectedVertexWalker_step(BMWalker *walker) * \note that this doesn't work on non-manifold geometry. * it might be better to rewrite this to extract * boundary info from the island walker, rather then directly walking - * over the boundary. raises an error if it encounters nonmanifold geometry. + * over the boundary. raises an error if it encounters non-manifold geometry. * * \todo Add restriction flag/callback for wire edges. */ diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c index f23c420295b..1570c802bee 100644 --- a/source/blender/bmesh/operators/bmo_inset.c +++ b/source/blender/bmesh/operators/bmo_inset.c @@ -588,7 +588,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op) /* tag if boundary is enabled */ (use_boundary && BM_edge_is_boundary(e) && BM_elem_flag_test(e->l->f, BM_ELEM_TAG)) || - /* tag if edge is an interior edge inbetween a tagged and untagged face */ + /* tag if edge is an interior edge in between a tagged and untagged face */ (bm_edge_is_mixed_face_tag(e->l))) { /* tag */ BM_elem_flag_enable(e->v1, BM_ELEM_TAG); diff --git a/source/blender/bmesh/operators/bmo_removedoubles.c b/source/blender/bmesh/operators/bmo_removedoubles.c index d783842c017..1d28d8223cd 100644 --- a/source/blender/bmesh/operators/bmo_removedoubles.c +++ b/source/blender/bmesh/operators/bmo_removedoubles.c @@ -706,34 +706,3 @@ void bmo_find_doubles_exec(BMesh *bm, BMOperator *op) slot_targetmap_out = BMO_slot_get(op->slots_out, "targetmap.out"); bmesh_find_doubles_common(bm, op, op, slot_targetmap_out); } - -void bmo_automerge_exec(BMesh *bm, BMOperator *op) -{ - BMOperator findop, weldop; - BMIter viter; - BMVert *v; - - /* The "verts" input sent to this op is the set of verts that - * can be merged away into any other verts. Mark all other verts - * as VERT_KEEP. */ - BMO_slot_buffer_flag_enable(bm, op->slots_in, "verts", BM_VERT, VERT_IN); - BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { - if (!BMO_vert_flag_test(bm, v, VERT_IN)) { - BMO_vert_flag_enable(bm, v, VERT_KEEP); - } - } - - /* Search for doubles among all vertices, but only merge non-VERT_KEEP - * vertices into VERT_KEEP vertices. */ - BMO_op_initf(bm, &findop, op->flag, "find_doubles verts=%av keep_verts=%fv", VERT_KEEP); - BMO_slot_copy(op, slots_in, "dist", &findop, slots_in, "dist"); - BMO_op_exec(bm, &findop); - - /* weld the vertices */ - BMO_op_init(bm, &weldop, op->flag, "weld_verts"); - BMO_slot_copy(&findop, slots_out, "targetmap.out", &weldop, slots_in, "targetmap"); - BMO_op_exec(bm, &weldop); - - BMO_op_finish(bm, &findop); - BMO_op_finish(bm, &weldop); -} diff --git a/source/blender/bmesh/tools/bmesh_beautify.c b/source/blender/bmesh/tools/bmesh_beautify.c index 5d511374989..dabdbc3c97a 100644 --- a/source/blender/bmesh/tools/bmesh_beautify.c +++ b/source/blender/bmesh/tools/bmesh_beautify.c @@ -199,7 +199,7 @@ static float bm_edge_calc_rotate_beauty__area(const float v1[3], * Allowing to rotate out of a degenerate state can flip the faces * (when performed iteratively). */ - return BLI_polyfill_beautify_quad_rotate_calc_ex(v1_xy, v2_xy, v3_xy, v4_xy, true); + return BLI_polyfill_beautify_quad_rotate_calc_ex(v1_xy, v2_xy, v3_xy, v4_xy, true, NULL); } while (false); return FLT_MAX; diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index 94935f2090b..797e2ca864e 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -3122,6 +3122,7 @@ static void adjust_offsets(BevelParams *bp, BMesh *bm) } if (!iscycle) { /* right->left direction, changing vchainstart at each step */ + v->adjchain = NULL; v = vchainstart; bvcur = bv; do { diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c index e32a9334343..198b4c8e76b 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c +++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c @@ -363,7 +363,7 @@ static void bm_decim_build_edge_cost(BMesh *bm, struct KD_Symmetry_Data { /* pre-flipped coords */ float e_v1_co[3], e_v2_co[3]; - /* Use to compare the correct endpoints incase v1/v2 are swapped */ + /* Use to compare the correct endpoints in case v1/v2 are swapped. */ float e_dir[3]; int e_found_index; @@ -1371,8 +1371,8 @@ void BM_mesh_decimate_collapse(BMesh *bm, /* handy to detect corruptions elsewhere */ BLI_assert(BM_elem_index_get(e) < tot_edge_orig); - /* under normal conditions wont be accessed again, - * but NULL just incase so we don't use freed node */ + /* Under normal conditions wont be accessed again, + * but NULL just in case so we don't use freed node. */ eheap_table[BM_elem_index_get(e)] = NULL; bm_decim_edge_collapse(bm, diff --git a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c index 27b4fa15f26..2cc86a7c93f 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c +++ b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c @@ -231,7 +231,7 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool if (BMO_vert_flag_test(bm, v, ELE_VERT_TAG)) #endif { - /* check again incase the topology changed */ + /* Check again in case the topology changed. */ if (bm_vert_dissolve_fan_test(v)) { v_first = v; } diff --git a/source/blender/bmesh/tools/bmesh_region_match.c b/source/blender/bmesh/tools/bmesh_region_match.c index 943f7532960..c30992fa296 100644 --- a/source/blender/bmesh/tools/bmesh_region_match.c +++ b/source/blender/bmesh/tools/bmesh_region_match.c @@ -1099,7 +1099,7 @@ static BMEdge *bm_face_region_pivot_edge_find(BMFace **faces_region, } } else { - /* use incase (depth == 0), no interior verts */ + /* Use in case (depth == 0), no interior verts. */ e_pivot_fallback = e; } } while ((l_iter = l_iter->next) != l_first); diff --git a/source/blender/collada/AnimationExporter.h b/source/blender/collada/AnimationExporter.h index 27474cc2b58..2be2dadeeeb 100644 --- a/source/blender/collada/AnimationExporter.h +++ b/source/blender/collada/AnimationExporter.h @@ -78,8 +78,6 @@ extern "C" { #include <map> #include <algorithm> // std::find -struct Depsgraph; - typedef enum BC_animation_source_type { BC_SOURCE_TYPE_VALUE, BC_SOURCE_TYPE_ANGLE, diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp index 54177560eb5..79593f07383 100644 --- a/source/blender/collada/AnimationImporter.cpp +++ b/source/blender/collada/AnimationImporter.cpp @@ -733,7 +733,7 @@ void AnimationImporter::Assign_float_animations(const COLLADAFW::UniqueId &listi * Reason: old blender versions stored spot_size in radians (was a bug) */ if (this->import_from_version == "" || - BLI_natstrcmp(this->import_from_version.c_str(), "2.69.10") != -1) { + BLI_strcasecmp_natural(this->import_from_version.c_str(), "2.69.10") != -1) { fcurve_deg_to_rad(fcu); } } diff --git a/source/blender/collada/CMakeLists.txt b/source/blender/collada/CMakeLists.txt index 5f28ca4ffbb..40762db759e 100644 --- a/source/blender/collada/CMakeLists.txt +++ b/source/blender/collada/CMakeLists.txt @@ -28,10 +28,7 @@ FIND_FILE(OPENCOLLADA_ANIMATION_CLIP ) IF(OPENCOLLADA_ANIMATION_CLIP) - message(STATUS "Found opencollada: ${OPENCOLLADA_ANIMATION_CLIP} ") add_definitions(-DWITH_OPENCOLLADA_ANIMATION_CLIP) -ELSE() - message(STATUS "opencollada: Build without animation clip support") ENDIF() set(INC diff --git a/source/blender/collada/ControllerExporter.h b/source/blender/collada/ControllerExporter.h index 200f8431f62..ce2ed9fe453 100644 --- a/source/blender/collada/ControllerExporter.h +++ b/source/blender/collada/ControllerExporter.h @@ -47,7 +47,6 @@ #include "BKE_key.h" -struct Depsgraph; class SceneExporter; class ControllerExporter : public COLLADASW::LibraryControllers, diff --git a/source/blender/collada/GeometryExporter.h b/source/blender/collada/GeometryExporter.h index 7262784db82..8c7a38fc407 100644 --- a/source/blender/collada/GeometryExporter.h +++ b/source/blender/collada/GeometryExporter.h @@ -39,8 +39,6 @@ #include "BlenderContext.h" #include "BKE_key.h" -struct Depsgraph; - class Normal { public: float x; @@ -58,8 +56,6 @@ class GeometryExporter : COLLADASW::LibraryGeometries { unsigned int v1, v2, v3, v4; }; - Normal n; - public: /* TODO: optimize UV sets by making indexed list with duplicates removed */ GeometryExporter(BlenderContext &blender_context, diff --git a/source/blender/collada/collada.h b/source/blender/collada/collada.h index df6e72cbf3a..72753e170a3 100644 --- a/source/blender/collada/collada.h +++ b/source/blender/collada/collada.h @@ -34,9 +34,6 @@ extern "C" { #include "BLI_path_util.h" #include "RNA_types.h" -struct Depsgraph; -struct Scene; -struct ViewLayer; struct bContext; /* diff --git a/source/blender/collada/collada_utils.h b/source/blender/collada/collada_utils.h index c23e33df76d..c0425e59d1a 100644 --- a/source/blender/collada/collada_utils.h +++ b/source/blender/collada/collada_utils.h @@ -69,8 +69,6 @@ extern "C" { constexpr int LIMITTED_PRECISION = 6; -struct Depsgraph; - typedef std::map<COLLADAFW::UniqueId, Image *> UidImageMap; typedef std::map<std::string, Image *> KeyImageMap; typedef std::map<COLLADAFW::TextureMapId, std::vector<MTex *>> TexIndexTextureArrayMap; diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt index 50b5951f99f..2a8914c8cd9 100644 --- a/source/blender/compositor/CMakeLists.txt +++ b/source/blender/compositor/CMakeLists.txt @@ -280,8 +280,8 @@ set(SRC nodes/COM_BlurNode.h nodes/COM_BokehBlurNode.cpp nodes/COM_BokehBlurNode.h - nodes/COM_DenoiseNode.h nodes/COM_DenoiseNode.cpp + nodes/COM_DenoiseNode.h nodes/COM_DespeckleNode.cpp nodes/COM_DespeckleNode.h nodes/COM_DilateErodeNode.cpp @@ -491,8 +491,8 @@ set(SRC operations/COM_ConvolutionEdgeFilterOperation.h operations/COM_ConvolutionFilterOperation.cpp operations/COM_ConvolutionFilterOperation.h - operations/COM_DenoiseOperation.h operations/COM_DenoiseOperation.cpp + operations/COM_DenoiseOperation.h operations/COM_DespeckleOperation.cpp operations/COM_DespeckleOperation.h operations/COM_DilateErodeOperation.cpp diff --git a/source/blender/compositor/intern/COM_CompositorContext.h b/source/blender/compositor/intern/COM_CompositorContext.h index f4cd60e3ee0..b28d5ff0cdf 100644 --- a/source/blender/compositor/intern/COM_CompositorContext.h +++ b/source/blender/compositor/intern/COM_CompositorContext.h @@ -215,7 +215,7 @@ class CompositorContext { } /** - * \brief get the current framenumber of the scene in this context + * \brief get the current frame-number of the scene in this context */ int getFramenumber() const; diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.h b/source/blender/compositor/intern/COM_MemoryBuffer.h index df936818f33..7e5b0264aa3 100644 --- a/source/blender/compositor/intern/COM_MemoryBuffer.h +++ b/source/blender/compositor/intern/COM_MemoryBuffer.h @@ -73,7 +73,7 @@ class MemoryBuffer { rcti m_rect; /** - * brief refers to the chunknumber within the executiongroup where related to the MemoryProxy + * brief refers to the chunk-number within the execution-group where related to the MemoryProxy * \see memoryProxy */ unsigned int m_chunkNumber; diff --git a/source/blender/compositor/intern/COM_NodeOperation.h b/source/blender/compositor/intern/COM_NodeOperation.h index af9ed2648c9..6b073452771 100644 --- a/source/blender/compositor/intern/COM_NodeOperation.h +++ b/source/blender/compositor/intern/COM_NodeOperation.h @@ -368,7 +368,7 @@ class NodeOperation : public SocketReader { return true; } - inline bool isBreaked() const + inline bool isBraked() const { return this->m_btree->test_break(this->m_btree->tbh); } diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.cpp b/source/blender/compositor/intern/COM_OpenCLDevice.cpp index 0aa054b8c77..2529637801d 100644 --- a/source/blender/compositor/intern/COM_OpenCLDevice.cpp +++ b/source/blender/compositor/intern/COM_OpenCLDevice.cpp @@ -248,7 +248,7 @@ void OpenCLDevice::COM_clEnqueueRange(cl_kernel kernel, printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); } clFlush(this->m_queue); - if (operation->isBreaked()) { + if (operation->isBraked()) { breaked = false; } } diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.h b/source/blender/compositor/intern/COM_OpenCLDevice.h index 7a83bda162c..45ce77acac7 100644 --- a/source/blender/compositor/intern/COM_OpenCLDevice.h +++ b/source/blender/compositor/intern/COM_OpenCLDevice.h @@ -78,8 +78,8 @@ class OpenCLDevice : public Device { bool initialize(); /** - * \brief deinitialize the device - * During deintiialization the command queue is cleared + * \brief de-initialize the device + * During de-initialization the command queue is cleared */ void deinitialize(); diff --git a/source/blender/compositor/nodes/COM_ImageNode.cpp b/source/blender/compositor/nodes/COM_ImageNode.cpp index dc3f65deb1f..6bce56ffd52 100644 --- a/source/blender/compositor/nodes/COM_ImageNode.cpp +++ b/source/blender/compositor/nodes/COM_ImageNode.cpp @@ -195,7 +195,7 @@ void ImageNode::convertToOperations(NodeConverter &converter, } } - /* incase we can't load the layer */ + /* In case we can't load the layer. */ if (operation == NULL) { converter.setInvalidOutput(getOutputSocket(index)); } diff --git a/source/blender/compositor/nodes/COM_MathNode.cpp b/source/blender/compositor/nodes/COM_MathNode.cpp index 5a2f934f37f..d13b34bb6b5 100644 --- a/source/blender/compositor/nodes/COM_MathNode.cpp +++ b/source/blender/compositor/nodes/COM_MathNode.cpp @@ -29,61 +29,61 @@ void MathNode::convertToOperations(NodeConverter &converter, case NODE_MATH_ADD: operation = new MathAddOperation(); break; - case NODE_MATH_SUB: + case NODE_MATH_SUBTRACT: operation = new MathSubtractOperation(); break; - case NODE_MATH_MUL: + case NODE_MATH_MULTIPLY: operation = new MathMultiplyOperation(); break; case NODE_MATH_DIVIDE: operation = new MathDivideOperation(); break; - case NODE_MATH_SIN: + case NODE_MATH_SINE: operation = new MathSineOperation(); break; - case NODE_MATH_COS: + case NODE_MATH_COSINE: operation = new MathCosineOperation(); break; - case NODE_MATH_TAN: + case NODE_MATH_TANGENT: operation = new MathTangentOperation(); break; - case NODE_MATH_ASIN: + case NODE_MATH_ARCSINE: operation = new MathArcSineOperation(); break; - case NODE_MATH_ACOS: + case NODE_MATH_ARCCOSINE: operation = new MathArcCosineOperation(); break; - case NODE_MATH_ATAN: + case NODE_MATH_ARCTANGENT: operation = new MathArcTangentOperation(); break; - case NODE_MATH_POW: + case NODE_MATH_POWER: operation = new MathPowerOperation(); break; - case NODE_MATH_LOG: + case NODE_MATH_LOGARITHM: operation = new MathLogarithmOperation(); break; - case NODE_MATH_MIN: + case NODE_MATH_MINIMUM: operation = new MathMinimumOperation(); break; - case NODE_MATH_MAX: + case NODE_MATH_MAXIMUM: operation = new MathMaximumOperation(); break; case NODE_MATH_ROUND: operation = new MathRoundOperation(); break; - case NODE_MATH_LESS: + case NODE_MATH_LESS_THAN: operation = new MathLessThanOperation(); break; - case NODE_MATH_GREATER: + case NODE_MATH_GREATER_THAN: operation = new MathGreaterThanOperation(); break; - case NODE_MATH_MOD: + case NODE_MATH_MODULO: operation = new MathModuloOperation(); break; - case NODE_MATH_ABS: + case NODE_MATH_ABSOLUTE: operation = new MathAbsoluteOperation(); break; - case NODE_MATH_ATAN2: + case NODE_MATH_ARCTAN2: operation = new MathArcTan2Operation(); break; case NODE_MATH_FLOOR: @@ -92,7 +92,7 @@ void MathNode::convertToOperations(NodeConverter &converter, case NODE_MATH_CEIL: operation = new MathCeilOperation(); break; - case NODE_MATH_FRACT: + case NODE_MATH_FRACTION: operation = new MathFractOperation(); break; case NODE_MATH_SQRT: diff --git a/source/blender/compositor/nodes/COM_MixNode.cpp b/source/blender/compositor/nodes/COM_MixNode.cpp index 27a605e28d4..b3bcefaccb5 100644 --- a/source/blender/compositor/nodes/COM_MixNode.cpp +++ b/source/blender/compositor/nodes/COM_MixNode.cpp @@ -52,7 +52,7 @@ void MixNode::convertToOperations(NodeConverter &converter, convertProg = new MixLightenOperation(); break; case MA_RAMP_BURN: - convertProg = new MixBurnOperation(); + convertProg = new MixColorBurnOperation(); break; case MA_RAMP_HUE: convertProg = new MixHueOperation(); diff --git a/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cpp b/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cpp index 68b5af3089a..1578a805d1e 100644 --- a/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cpp +++ b/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cpp @@ -22,7 +22,7 @@ inline float colorbalance_lgg(float in, float lift_lgg, float gamma_inv, float gain) { /* 1:1 match with the sequencer with linear/srgb conversions, the conversion isnt pretty - * but best keep it this way, sice testing for durian shows a similar calculation + * but best keep it this way, since testing for durian shows a similar calculation * without lin/srgb conversions gives bad results (over-saturated shadows) with colors * slightly below 1.0. some correction can be done but it ends up looking bad for shadows or * lighter tones - campbell */ diff --git a/source/blender/compositor/operations/COM_CompositorOperation.cpp b/source/blender/compositor/operations/COM_CompositorOperation.cpp index 40315d217ce..5bd466658c0 100644 --- a/source/blender/compositor/operations/COM_CompositorOperation.cpp +++ b/source/blender/compositor/operations/COM_CompositorOperation.cpp @@ -78,7 +78,7 @@ void CompositorOperation::deinitExecution() return; } - if (!isBreaked()) { + if (!isBraked()) { Render *re = RE_GetSceneRender(this->m_scene); RenderResult *rr = RE_AcquireResultWrite(re); @@ -207,7 +207,7 @@ void CompositorOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/) zbuffer[offset] = color[0]; offset4 += COM_NUM_CHANNELS_COLOR; offset++; - if (isBreaked()) { + if (isBraked()) { breaked = true; } } diff --git a/source/blender/compositor/operations/COM_DenoiseOperation.cpp b/source/blender/compositor/operations/COM_DenoiseOperation.cpp index af568490c72..3aeaba539f9 100644 --- a/source/blender/compositor/operations/COM_DenoiseOperation.cpp +++ b/source/blender/compositor/operations/COM_DenoiseOperation.cpp @@ -21,16 +21,19 @@ #include "COM_DenoiseOperation.h" #include "BLI_math.h" +#include "BLI_system.h" #ifdef WITH_OPENIMAGEDENOISE +# include "BLI_threads.h" # include <OpenImageDenoise/oidn.hpp> +static pthread_mutex_t oidn_lock = BLI_MUTEX_INITIALIZER; #endif #include <iostream> DenoiseOperation::DenoiseOperation() : SingleThreadedOperation() { this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_COLOR); this->addInputSocket(COM_DT_VECTOR); + this->addInputSocket(COM_DT_COLOR); this->addOutputSocket(COM_DT_COLOR); this->m_settings = NULL; } @@ -38,23 +41,23 @@ void DenoiseOperation::initExecution() { SingleThreadedOperation::initExecution(); this->m_inputProgramColor = getInputSocketReader(0); - this->m_inputProgramAlbedo = getInputSocketReader(1); - this->m_inputProgramNormal = getInputSocketReader(2); + this->m_inputProgramNormal = getInputSocketReader(1); + this->m_inputProgramAlbedo = getInputSocketReader(2); } void DenoiseOperation::deinitExecution() { this->m_inputProgramColor = NULL; - this->m_inputProgramAlbedo = NULL; this->m_inputProgramNormal = NULL; + this->m_inputProgramAlbedo = NULL; SingleThreadedOperation::deinitExecution(); } MemoryBuffer *DenoiseOperation::createMemoryBuffer(rcti *rect2) { MemoryBuffer *tileColor = (MemoryBuffer *)this->m_inputProgramColor->initializeTileData(rect2); - MemoryBuffer *tileAlbedo = (MemoryBuffer *)this->m_inputProgramAlbedo->initializeTileData(rect2); MemoryBuffer *tileNormal = (MemoryBuffer *)this->m_inputProgramNormal->initializeTileData(rect2); + MemoryBuffer *tileAlbedo = (MemoryBuffer *)this->m_inputProgramAlbedo->initializeTileData(rect2); rcti rect; rect.xmin = 0; rect.ymin = 0; @@ -62,7 +65,7 @@ MemoryBuffer *DenoiseOperation::createMemoryBuffer(rcti *rect2) rect.ymax = getHeight(); MemoryBuffer *result = new MemoryBuffer(COM_DT_COLOR, &rect); float *data = result->getBuffer(); - this->generateDenoise(data, tileColor, tileAlbedo, tileNormal, this->m_settings); + this->generateDenoise(data, tileColor, tileNormal, tileAlbedo, this->m_settings); return result; } @@ -85,8 +88,8 @@ bool DenoiseOperation::determineDependingAreaOfInterest(rcti * /*input*/, void DenoiseOperation::generateDenoise(float *data, MemoryBuffer *inputTileColor, - MemoryBuffer *inputTileAlbedo, MemoryBuffer *inputTileNormal, + MemoryBuffer *inputTileAlbedo, NodeDenoise *settings) { float *inputBufferColor = inputTileColor->getBuffer(); @@ -95,60 +98,69 @@ void DenoiseOperation::generateDenoise(float *data, return; } #ifdef WITH_OPENIMAGEDENOISE - oidn::DeviceRef device = oidn::newDevice(); - device.commit(); + if (BLI_cpu_support_sse41()) { + oidn::DeviceRef device = oidn::newDevice(); + device.commit(); - oidn::FilterRef filter = device.newFilter("RT"); - filter.setImage("color", - inputBufferColor, - oidn::Format::Float3, - inputTileColor->getWidth(), - inputTileColor->getHeight(), - 0, - 4 * sizeof(float)); - if (inputTileAlbedo && inputTileAlbedo->getBuffer()) { - filter.setImage("albedo", - inputTileAlbedo->getBuffer(), + oidn::FilterRef filter = device.newFilter("RT"); + filter.setImage("color", + inputBufferColor, oidn::Format::Float3, - inputTileAlbedo->getWidth(), - inputTileAlbedo->getHeight(), + inputTileColor->getWidth(), + inputTileColor->getHeight(), 0, 4 * sizeof(float)); - } - if (inputTileNormal && inputTileNormal->getBuffer()) { - filter.setImage("normal", - inputTileNormal->getBuffer(), + if (inputTileNormal && inputTileNormal->getBuffer()) { + filter.setImage("normal", + inputTileNormal->getBuffer(), + oidn::Format::Float3, + inputTileNormal->getWidth(), + inputTileNormal->getHeight(), + 0, + 3 * sizeof(float)); + } + if (inputTileAlbedo && inputTileAlbedo->getBuffer()) { + filter.setImage("albedo", + inputTileAlbedo->getBuffer(), + oidn::Format::Float3, + inputTileAlbedo->getWidth(), + inputTileAlbedo->getHeight(), + 0, + 4 * sizeof(float)); + } + filter.setImage("output", + data, oidn::Format::Float3, - inputTileNormal->getWidth(), - inputTileNormal->getHeight(), + inputTileColor->getWidth(), + inputTileColor->getHeight(), 0, - 3 * sizeof(float)); - } - filter.setImage("output", - data, - oidn::Format::Float3, - inputTileColor->getWidth(), - inputTileColor->getHeight(), - 0, - 4 * sizeof(float)); + 4 * sizeof(float)); - BLI_assert(settings); - if (settings) { - filter.set("hdr", settings->hdr); - filter.set("srgb", false); - } + BLI_assert(settings); + if (settings) { + filter.set("hdr", settings->hdr); + filter.set("srgb", false); + } - filter.commit(); - filter.execute(); + filter.commit(); + /* Since it's memory intensive, it's better to run only one instance of OIDN at a time. + * OpenImageDenoise is multithreaded internally and should use all available cores nonetheless. + */ + BLI_mutex_lock(&oidn_lock); + filter.execute(); + BLI_mutex_unlock(&oidn_lock); - /* copy the alpha channel, OpenImageDenoise currently only supports RGB */ - size_t numPixels = inputTileColor->getWidth() * inputTileColor->getHeight(); - for (size_t i = 0; i < numPixels; ++i) { - data[i * 4 + 3] = inputBufferColor[i * 4 + 3]; + /* copy the alpha channel, OpenImageDenoise currently only supports RGB */ + size_t numPixels = inputTileColor->getWidth() * inputTileColor->getHeight(); + for (size_t i = 0; i < numPixels; ++i) { + data[i * 4 + 3] = inputBufferColor[i * 4 + 3]; + } + return; } -#else +#endif + /* If built without OIDN or running on an unsupported CPU, just pass through. */ + UNUSED_VARS(inputTileAlbedo, inputTileNormal, settings); ::memcpy(data, inputBufferColor, inputTileColor->getWidth() * inputTileColor->getHeight() * sizeof(float) * 4); -#endif } diff --git a/source/blender/compositor/operations/COM_DenoiseOperation.h b/source/blender/compositor/operations/COM_DenoiseOperation.h index 6e19bd6034a..73165174932 100644 --- a/source/blender/compositor/operations/COM_DenoiseOperation.h +++ b/source/blender/compositor/operations/COM_DenoiseOperation.h @@ -62,8 +62,8 @@ class DenoiseOperation : public SingleThreadedOperation { protected: void generateDenoise(float *data, MemoryBuffer *inputTileColor, - MemoryBuffer *inputTileAlbedo, MemoryBuffer *inputTileNormal, + MemoryBuffer *inputTileAlbedo, NodeDenoise *settings); MemoryBuffer *createMemoryBuffer(rcti *rect); diff --git a/source/blender/compositor/operations/COM_GlareGhostOperation.cpp b/source/blender/compositor/operations/COM_GlareGhostOperation.cpp index 944a1d9c5dc..9f01cf5d63a 100644 --- a/source/blender/compositor/operations/COM_GlareGhostOperation.cpp +++ b/source/blender/compositor/operations/COM_GlareGhostOperation.cpp @@ -51,7 +51,7 @@ void GlareGhostOperation::generateGlare(float *data, MemoryBuffer *inputTile, No if (!breaked) { FastGaussianBlurOperation::IIR_gauss(tbuf1, s1, 1, 3); } - if (isBreaked()) { + if (isBraked()) { breaked = true; } if (!breaked) { @@ -60,19 +60,19 @@ void GlareGhostOperation::generateGlare(float *data, MemoryBuffer *inputTile, No MemoryBuffer *tbuf2 = tbuf1->duplicate(); - if (isBreaked()) { + if (isBraked()) { breaked = true; } if (!breaked) { FastGaussianBlurOperation::IIR_gauss(tbuf2, s2, 0, 3); } - if (isBreaked()) { + if (isBraked()) { breaked = true; } if (!breaked) { FastGaussianBlurOperation::IIR_gauss(tbuf2, s2, 1, 3); } - if (isBreaked()) { + if (isBraked()) { breaked = true; } if (!breaked) { @@ -117,7 +117,7 @@ void GlareGhostOperation::generateGlare(float *data, MemoryBuffer *inputTile, No gbuf->writePixel(x, y, c); } - if (isBreaked()) { + if (isBraked()) { breaked = true; } } @@ -142,7 +142,7 @@ void GlareGhostOperation::generateGlare(float *data, MemoryBuffer *inputTile, No } tbuf1->addPixel(x, y, tc); } - if (isBreaked()) { + if (isBraked()) { breaked = true; } } diff --git a/source/blender/compositor/operations/COM_GlareSimpleStarOperation.cpp b/source/blender/compositor/operations/COM_GlareSimpleStarOperation.cpp index 1ceeba18960..75c2ae51bde 100644 --- a/source/blender/compositor/operations/COM_GlareSimpleStarOperation.cpp +++ b/source/blender/compositor/operations/COM_GlareSimpleStarOperation.cpp @@ -58,7 +58,7 @@ void GlareSimpleStarOperation::generateGlare(float *data, c[3] = 1.0f; tbuf2->writePixel(x, y, c); } - if (isBreaked()) { + if (isBraked()) { breaked = true; } } @@ -87,7 +87,7 @@ void GlareSimpleStarOperation::generateGlare(float *data, c[3] = 1.0f; tbuf2->writePixel(x, y, c); } - if (isBreaked()) { + if (isBraked()) { breaked = true; } } diff --git a/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp b/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp index 78ca373faaf..951dec9281e 100644 --- a/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp +++ b/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp @@ -78,7 +78,7 @@ void GlareStreaksOperation::generateGlare(float *data, tdstcol[2] = 0.5f * (tdstcol[2] + c1[2] + wt * (c2[2] + wt * (c3[2] + wt * c4[2]))); tdstcol[3] = 1.0f; } - if (isBreaked()) { + if (isBraked()) { breaked = true; } } diff --git a/source/blender/compositor/operations/COM_MaskOperation.cpp b/source/blender/compositor/operations/COM_MaskOperation.cpp index 0c9208fb6bb..88a3a5c535c 100644 --- a/source/blender/compositor/operations/COM_MaskOperation.cpp +++ b/source/blender/compositor/operations/COM_MaskOperation.cpp @@ -148,7 +148,7 @@ void MaskOperation::executePixelSampled(float output[4], } } else { - /* incase loop below fails */ + /* In case loop below fails. */ output[0] = 0.0f; for (unsigned int i = 0; i < this->m_rasterMaskHandleTot; i++) { diff --git a/source/blender/compositor/operations/COM_MixOperation.cpp b/source/blender/compositor/operations/COM_MixOperation.cpp index a610cb0d1e8..6b8a0caa13b 100644 --- a/source/blender/compositor/operations/COM_MixOperation.cpp +++ b/source/blender/compositor/operations/COM_MixOperation.cpp @@ -162,12 +162,15 @@ void MixBlendOperation::executePixelSampled(float output[4], /* ******** Mix Burn Operation ******** */ -MixBurnOperation::MixBurnOperation() : MixBaseOperation() +MixColorBurnOperation::MixColorBurnOperation() : MixBaseOperation() { /* pass */ } -void MixBurnOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void MixColorBurnOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) { float inputColor1[4]; float inputColor2[4]; diff --git a/source/blender/compositor/operations/COM_MixOperation.h b/source/blender/compositor/operations/COM_MixOperation.h index 6ea55a3edfd..fbf60fb9d37 100644 --- a/source/blender/compositor/operations/COM_MixOperation.h +++ b/source/blender/compositor/operations/COM_MixOperation.h @@ -95,9 +95,9 @@ class MixBlendOperation : public MixBaseOperation { void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; -class MixBurnOperation : public MixBaseOperation { +class MixColorBurnOperation : public MixBaseOperation { public: - MixBurnOperation(); + MixColorBurnOperation(); void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; diff --git a/source/blender/compositor/operations/COM_ViewerOperation.cpp b/source/blender/compositor/operations/COM_ViewerOperation.cpp index d5b9edae719..3f7619523e3 100644 --- a/source/blender/compositor/operations/COM_ViewerOperation.cpp +++ b/source/blender/compositor/operations/COM_ViewerOperation.cpp @@ -111,7 +111,7 @@ void ViewerOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/) offset++; offset4 += 4; } - if (isBreaked()) { + if (isBraked()) { breaked = true; } offset += offsetadd; diff --git a/source/blender/compositor/operations/COM_WriteBufferOperation.cpp b/source/blender/compositor/operations/COM_WriteBufferOperation.cpp index beba29e6755..6c5e45472a8 100644 --- a/source/blender/compositor/operations/COM_WriteBufferOperation.cpp +++ b/source/blender/compositor/operations/COM_WriteBufferOperation.cpp @@ -76,7 +76,7 @@ void WriteBufferOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/ this->m_input->read(&(buffer[offset4]), x, y, data); offset4 += num_channels; } - if (isBreaked()) { + if (isBraked()) { breaked = true; } } @@ -100,7 +100,7 @@ void WriteBufferOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/ this->m_input->readSampled(&(buffer[offset4]), x, y, COM_PS_NEAREST); offset4 += num_channels; } - if (isBreaked()) { + if (isBraked()) { breaked = true; } } @@ -119,7 +119,7 @@ void WriteBufferOperation::executeOpenCLRegion(OpenCLDevice *device, /* * 1. create cl_mem from outputbuffer * 2. call NodeOperation (input) executeOpenCLChunk(.....) - * 3. schedule readback from opencl to main device (outputbuffer) + * 3. schedule read back from opencl to main device (outputbuffer) * 4. schedule native callback * * note: list of cl_mem will be filled by 2, and needs to be cleaned up by 4 diff --git a/source/blender/depsgraph/DEG_depsgraph.h b/source/blender/depsgraph/DEG_depsgraph.h index bdcb4061096..7553eca9b64 100644 --- a/source/blender/depsgraph/DEG_depsgraph.h +++ b/source/blender/depsgraph/DEG_depsgraph.h @@ -55,9 +55,6 @@ typedef struct Depsgraph Depsgraph; struct Main; -struct PointerRNA; -struct PropertyRNA; -struct RenderEngineType; struct Scene; struct ViewLayer; @@ -111,6 +108,8 @@ void DEG_graph_on_visible_update(struct Main *bmain, Depsgraph *depsgraph, const /* Update all dependency graphs when visible scenes/layers changes. */ void DEG_on_visible_update(struct Main *bmain, const bool do_time); +/* NOTE: Will return NULL if the flag is not known, allowing to gracefully handle situations + * when recalc flag has been removed. */ const char *DEG_update_tag_as_string(IDRecalcFlag flag); void DEG_id_tag_update(struct ID *id, int flag); diff --git a/source/blender/depsgraph/DEG_depsgraph_build.h b/source/blender/depsgraph/DEG_depsgraph_build.h index 18e06410adf..37dfaf2c3e2 100644 --- a/source/blender/depsgraph/DEG_depsgraph_build.h +++ b/source/blender/depsgraph/DEG_depsgraph_build.h @@ -34,12 +34,9 @@ struct Depsgraph; /* ------------------------------------------------ */ struct CacheFile; -struct Collection; struct CustomData_MeshMasks; -struct EffectorWeights; struct ID; struct Main; -struct ModifierData; struct Object; struct Scene; struct ViewLayer; diff --git a/source/blender/depsgraph/DEG_depsgraph_query.h b/source/blender/depsgraph/DEG_depsgraph_query.h index e3381e79e9c..82f7f33411a 100644 --- a/source/blender/depsgraph/DEG_depsgraph_query.h +++ b/source/blender/depsgraph/DEG_depsgraph_query.h @@ -32,14 +32,13 @@ /* Needed for the instance iterator. */ #include "DNA_object_types.h" -struct ID; - struct BLI_Iterator; -struct Base; struct CustomData_MeshMasks; struct Depsgraph; struct DupliObject; +struct ID; struct ListBase; +struct PointerRNA; struct Scene; struct ViewLayer; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_cache.cc b/source/blender/depsgraph/intern/builder/deg_builder_cache.cc index 3df707e92c1..3cfb4f95e5e 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_cache.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_cache.cc @@ -103,9 +103,9 @@ void animated_property_cb(ID * /*id*/, FCurve *fcurve, void *data_v) /* Get storage for the ID. * This is needed to deal with cases when nested datablock is animated by its parent. */ AnimatedPropertyStorage *animated_property_storage = data->animated_property_storage; - if (pointer_rna.id.data != data->pointer_rna.id.data) { + if (pointer_rna.owner_id != data->pointer_rna.owner_id) { animated_property_storage = data->builder_cache->ensureAnimatedPropertyStorage( - reinterpret_cast<ID *>(pointer_rna.id.data)); + pointer_rna.owner_id); } /* Set the property as animated. */ animated_property_storage->tagPropertyAsAnimated(&pointer_rna, property_rna); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc b/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc index d11a60b77dd..bfb1a981c4d 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc @@ -149,7 +149,7 @@ bool check_relation_can_murder(Relation *relation) Relation *select_relation_to_murder(Relation *relation, StackEntry *cycle_start_entry) { - /* More or less russian roulette solver, which will make sure only + /* More or less Russian roulette solver, which will make sure only * specially marked relations are kept alive. * * TODO(sergey): There might be better strategies here. */ diff --git a/source/blender/depsgraph/intern/builder/deg_builder_map.h b/source/blender/depsgraph/intern/builder/deg_builder_map.h index 0767837a587..65b493e2467 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_map.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_map.h @@ -25,7 +25,6 @@ #include "intern/depsgraph_type.h" -struct GSet; struct ID; namespace DEG { diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h index de9f0e4d6cd..65f3521b556 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h @@ -31,7 +31,6 @@ #include "DEG_depsgraph.h" -struct Base; struct CacheFile; struct Camera; struct Collection; @@ -44,14 +43,12 @@ struct LayerCollection; struct Light; struct LightProbe; struct ListBase; -struct MTex; struct Main; struct Mask; struct Material; struct MovieClip; struct Object; struct ParticleSettings; -struct Probe; struct Scene; struct Speaker; struct Tex; @@ -64,15 +61,12 @@ struct bNodeTree; struct bPoseChannel; struct bSound; -struct PropertyRNA; - namespace DEG { struct ComponentNode; struct Depsgraph; class DepsgraphBuilderCache; struct IDNode; -struct Node; struct OperationNode; struct TimeSourceNode; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 3c226338bfd..c7b545e9feb 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -807,13 +807,25 @@ void DepsgraphRelationBuilder::build_object_parent(Object *object) { Object *parent = object->parent; ID *parent_id = &object->parent->id; - ComponentKey ob_key(&object->id, NodeType::TRANSFORM); - /* Type-specific links/ */ + ComponentKey object_transform_key(&object->id, NodeType::TRANSFORM); + /* Type-specific links. */ switch (object->partype) { /* Armature Deform (Virtual Modifier) */ case PARSKEL: { - ComponentKey parent_key(parent_id, NodeType::TRANSFORM); - add_relation(parent_key, ob_key, "Armature Deform Parent"); + ComponentKey parent_transform_key(parent_id, NodeType::TRANSFORM); + add_relation(parent_transform_key, object_transform_key, "Parent Armature Transform"); + + if (parent->type == OB_ARMATURE) { + ComponentKey object_geometry_key(&object->id, NodeType::GEOMETRY); + ComponentKey parent_pose_key(parent_id, NodeType::EVAL_POSE); + add_relation( + parent_transform_key, object_geometry_key, "Parent Armature Transform -> Geometry"); + add_relation(parent_pose_key, object_geometry_key, "Parent Armature Pose -> Geometry"); + + add_depends_on_transform_relation( + &object->id, object_geometry_key, "Virtual Armature Modifier"); + } + break; } @@ -821,7 +833,7 @@ void DepsgraphRelationBuilder::build_object_parent(Object *object) case PARVERT1: case PARVERT3: { ComponentKey parent_key(parent_id, NodeType::GEOMETRY); - add_relation(parent_key, ob_key, "Vertex Parent"); + add_relation(parent_key, object_transform_key, "Vertex Parent"); /* Original index is used for optimizations of lookups for subdiv * only meshes. * TODO(sergey): This optimization got lost at 2.8, so either verify @@ -833,7 +845,7 @@ void DepsgraphRelationBuilder::build_object_parent(Object *object) DEGCustomDataMeshMasks::MaskFace(CD_MASK_ORIGINDEX) | DEGCustomDataMeshMasks::MaskPoly(CD_MASK_ORIGINDEX)); ComponentKey transform_key(parent_id, NodeType::TRANSFORM); - add_relation(transform_key, ob_key, "Vertex Parent TFM"); + add_relation(transform_key, object_transform_key, "Vertex Parent TFM"); break; } @@ -842,8 +854,8 @@ void DepsgraphRelationBuilder::build_object_parent(Object *object) ComponentKey parent_bone_key(parent_id, NodeType::BONE, object->parsubstr); OperationKey parent_transform_key( parent_id, NodeType::TRANSFORM, OperationCode::TRANSFORM_FINAL); - add_relation(parent_bone_key, ob_key, "Bone Parent"); - add_relation(parent_transform_key, ob_key, "Armature Parent"); + add_relation(parent_bone_key, object_transform_key, "Bone Parent"); + add_relation(parent_transform_key, object_transform_key, "Armature Parent"); break; } @@ -852,8 +864,8 @@ void DepsgraphRelationBuilder::build_object_parent(Object *object) /* Lattice Deform Parent - Virtual Modifier. */ ComponentKey parent_key(parent_id, NodeType::TRANSFORM); ComponentKey geom_key(parent_id, NodeType::GEOMETRY); - add_relation(parent_key, ob_key, "Lattice Deform Parent"); - add_relation(geom_key, ob_key, "Lattice Deform Parent Geom"); + add_relation(parent_key, object_transform_key, "Lattice Deform Parent"); + add_relation(geom_key, object_transform_key, "Lattice Deform Parent Geom"); } else if (object->parent->type == OB_CURVE) { Curve *cu = (Curve *)object->parent->data; @@ -861,20 +873,20 @@ void DepsgraphRelationBuilder::build_object_parent(Object *object) if (cu->flag & CU_PATH) { /* Follow Path. */ ComponentKey parent_key(parent_id, NodeType::GEOMETRY); - add_relation(parent_key, ob_key, "Curve Follow Parent"); + add_relation(parent_key, object_transform_key, "Curve Follow Parent"); ComponentKey transform_key(parent_id, NodeType::TRANSFORM); - add_relation(transform_key, ob_key, "Curve Follow TFM"); + add_relation(transform_key, object_transform_key, "Curve Follow TFM"); } else { /* Standard Parent. */ ComponentKey parent_key(parent_id, NodeType::TRANSFORM); - add_relation(parent_key, ob_key, "Curve Parent"); + add_relation(parent_key, object_transform_key, "Curve Parent"); } } else { /* Standard Parent. */ ComponentKey parent_key(parent_id, NodeType::TRANSFORM); - add_relation(parent_key, ob_key, "Parent"); + add_relation(parent_key, object_transform_key, "Parent"); } break; } @@ -887,7 +899,7 @@ void DepsgraphRelationBuilder::build_object_parent(Object *object) ComponentKey parent_geometry_key(parent_id, NodeType::GEOMETRY); /* NOTE: Metaballs are evaluating geometry only after their transform, * so we only hook up to transform channel here. */ - add_relation(parent_geometry_key, ob_key, "Parent"); + add_relation(parent_geometry_key, object_transform_key, "Parent"); } /* Dupliverts uses original vertex index. */ @@ -1384,7 +1396,7 @@ void DepsgraphRelationBuilder::build_driver_data(ID *id, FCurve *fcu) * it. This is necessary to provide more granular dependencies specifically for * Bone objects, because the armature data doesn't have per-bone components, * and generic add_relation can only add one link. */ - ID *id_ptr = (ID *)property_entry_key.ptr.id.data; + ID *id_ptr = property_entry_key.ptr.owner_id; bool is_bone = id_ptr && property_entry_key.ptr.type == &RNA_Bone; /* If the Bone property is referenced via obj.pose.bones[].bone, * the RNA pointer refers to the Object ID, so skip to data. */ @@ -1433,8 +1445,8 @@ void DepsgraphRelationBuilder::build_driver_data(ID *id, FCurve *fcu) PointerRNA ptr; RNA_id_pointer_create(id, &id_ptr); if (RNA_path_resolve_full(&id_ptr, fcu->rna_path, &ptr, NULL, NULL)) { - if (id_ptr.id.data != ptr.id.data) { - ComponentKey cow_key((ID *)ptr.id.data, NodeType::COPY_ON_WRITE); + if (id_ptr.owner_id != ptr.owner_id) { + ComponentKey cow_key(ptr.owner_id, NodeType::COPY_ON_WRITE); add_relation(cow_key, driver_key, "Driven CoW -> Driver", RELATION_CHECK_BEFORE_ADD); } } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h index 0e15818622f..e58ef989ac9 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h @@ -51,7 +51,6 @@ struct Camera; struct Collection; struct EffectorWeights; struct FCurve; -struct GHash; struct ID; struct Image; struct Key; @@ -59,11 +58,9 @@ struct LayerCollection; struct Light; struct LightProbe; struct ListBase; -struct MTex; struct Main; struct Mask; struct Material; -struct ModifierData; struct MovieClip; struct Object; struct ParticleSettings; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc index be494104522..d3ae3da9b56 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc @@ -177,7 +177,7 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr, return node_identifier; } /* Set default values for returns. */ - node_identifier.id = static_cast<ID *>(ptr->id.data); + node_identifier.id = ptr->owner_id; node_identifier.component_name = ""; node_identifier.operation_code = OperationCode::OPERATION; node_identifier.operation_name = ""; @@ -239,7 +239,7 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr, return node_identifier; } else if (RNA_struct_is_a(ptr->type, &RNA_Constraint)) { - const Object *object = static_cast<const Object *>(ptr->id.data); + const Object *object = reinterpret_cast<const Object *>(ptr->owner_id); const bConstraint *constraint = static_cast<const bConstraint *>(ptr->data); RNANodeQueryIDData *id_data = ensure_id_data(&object->id); /* Check whether is object or bone constraint. */ @@ -259,7 +259,7 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr, return node_identifier; } else if (ELEM(ptr->type, &RNA_ConstraintTarget, &RNA_ConstraintTargetBone)) { - Object *object = (Object *)ptr->id.data; + Object *object = reinterpret_cast<Object *>(ptr->owner_id); bConstraintTarget *tgt = (bConstraintTarget *)ptr->data; /* Check whether is object or bone constraint. */ bPoseChannel *pchan = NULL; @@ -323,14 +323,14 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr, } else if (ptr->type == &RNA_ShapeKey) { KeyBlock *key_block = static_cast<KeyBlock *>(ptr->data); - node_identifier.id = static_cast<ID *>(ptr->id.data); + node_identifier.id = ptr->owner_id; node_identifier.type = NodeType::PARAMETERS; node_identifier.operation_code = OperationCode::PARAMETERS_EVAL; node_identifier.operation_name = key_block->name; return node_identifier; } else if (ptr->type == &RNA_Key) { - node_identifier.id = static_cast<ID *>(ptr->id.data); + node_identifier.id = ptr->owner_id; node_identifier.type = NodeType::GEOMETRY; return node_identifier; } @@ -348,12 +348,12 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr, return node_identifier; } else if (ELEM(ptr->type, &RNA_Curve, &RNA_TextCurve)) { - node_identifier.id = (ID *)ptr->id.data; + node_identifier.id = ptr->owner_id; node_identifier.type = NodeType::GEOMETRY; return node_identifier; } else if (ELEM(ptr->type, &RNA_BezierSplinePoint, &RNA_SplinePoint)) { - node_identifier.id = (ID *)ptr->id.data; + node_identifier.id = ptr->owner_id; node_identifier.type = NodeType::GEOMETRY; return node_identifier; } diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h index 15ce57cb169..96b1a2a1f8a 100644 --- a/source/blender/depsgraph/intern/depsgraph.h +++ b/source/blender/depsgraph/intern/depsgraph.h @@ -45,13 +45,11 @@ struct GHash; struct GSet; struct ID; -struct Main; struct Scene; struct ViewLayer; namespace DEG { -struct ComponentNode; struct IDNode; struct Node; struct OperationNode; diff --git a/source/blender/depsgraph/intern/depsgraph_query.cc b/source/blender/depsgraph/intern/depsgraph_query.cc index 23f2bf4194f..8556a351e2b 100644 --- a/source/blender/depsgraph/intern/depsgraph_query.cc +++ b/source/blender/depsgraph/intern/depsgraph_query.cc @@ -205,11 +205,11 @@ void DEG_get_evaluated_rna_pointer(const Depsgraph *depsgraph, if ((ptr == NULL) || (r_ptr_eval == NULL)) { return; } - ID *orig_id = (ID *)ptr->id.data; + ID *orig_id = ptr->owner_id; ID *cow_id = DEG_get_evaluated_id(depsgraph, orig_id); - if (ptr->id.data == ptr->data) { + if (ptr->owner_id == ptr->data) { /* For ID pointers, it's easy... */ - r_ptr_eval->id.data = (void *)cow_id; + r_ptr_eval->owner_id = cow_id; r_ptr_eval->data = (void *)cow_id; r_ptr_eval->type = ptr->type; } @@ -220,7 +220,7 @@ void DEG_get_evaluated_rna_pointer(const Depsgraph *depsgraph, const Object *ob_eval = (Object *)cow_id; bPoseChannel *pchan = (bPoseChannel *)ptr->data; const bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name); - r_ptr_eval->id.data = (void *)cow_id; + r_ptr_eval->owner_id = cow_id; r_ptr_eval->data = (void *)pchan_eval; r_ptr_eval->type = ptr->type; } diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc index 392514990e3..72ef495f1d5 100644 --- a/source/blender/depsgraph/intern/depsgraph_tag.cc +++ b/source/blender/depsgraph/intern/depsgraph_tag.cc @@ -412,11 +412,15 @@ static void graph_id_tag_update_single_flag(Main *bmain, string stringify_append_bit(const string &str, IDRecalcFlag tag) { + const char *tag_name = DEG_update_tag_as_string(tag); + if (tag_name == NULL) { + return str; + } string result = str; if (!result.empty()) { result += ", "; } - result += DEG_update_tag_as_string(tag); + result += tag_name; return result; } @@ -638,7 +642,7 @@ void graph_id_tag_update( * This way IDs in the undo steps will have this flag preserved, making it possible to restore * all needed tags when new dependency graph is created on redo. * This is the only way to ensure modifications to animation data (such as keyframes i.e.) - * properly triggers animation update for the newely constructed dependency graph on redo (while + * properly triggers animation update for the newly constructed dependency graph on redo (while * usually newly created dependency graph skips animation update to avoid loss of unkeyed * changes). */ if (update_source == DEG_UPDATE_SOURCE_USER_EDIT) { @@ -717,8 +721,7 @@ const char *DEG_update_tag_as_string(IDRecalcFlag flag) case ID_RECALC_ALL: return "ALL"; } - BLI_assert(!"Unhandled update flag, should never happen!"); - return "UNKNOWN"; + return NULL; } /* Data-Based Tagging */ diff --git a/source/blender/depsgraph/intern/node/deg_node.h b/source/blender/depsgraph/intern/node/deg_node.h index eea69502baa..acfc8d19bc7 100644 --- a/source/blender/depsgraph/intern/node/deg_node.h +++ b/source/blender/depsgraph/intern/node/deg_node.h @@ -29,7 +29,6 @@ #include "DEG_depsgraph_build.h" -struct GHash; struct ID; struct Scene; diff --git a/source/blender/depsgraph/intern/node/deg_node_id.h b/source/blender/depsgraph/intern/node/deg_node_id.h index e6eb91a6b2d..35184253f5c 100644 --- a/source/blender/depsgraph/intern/node/deg_node_id.h +++ b/source/blender/depsgraph/intern/node/deg_node_id.h @@ -26,6 +26,8 @@ #include "intern/node/deg_node.h" #include "BLI_sys_types.h" +struct GHash; + namespace DEG { struct ComponentNode; diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.h b/source/blender/depsgraph/intern/node/deg_node_operation.h index b0776d186bb..87c1a7f10a1 100644 --- a/source/blender/depsgraph/intern/node/deg_node_operation.h +++ b/source/blender/depsgraph/intern/node/deg_node_operation.h @@ -28,7 +28,6 @@ #include "intern/depsgraph_type.h" struct Depsgraph; -struct ID; namespace DEG { diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index fc91ac371cb..9b0f5f743f6 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -328,6 +328,7 @@ data_to_c_simple(modes/shaders/overlay_face_wireframe_geom.glsl SRC) data_to_c_simple(modes/shaders/overlay_face_wireframe_frag.glsl SRC) data_to_c_simple(modes/shaders/object_camera_image_frag.glsl SRC) data_to_c_simple(modes/shaders/object_camera_image_vert.glsl SRC) +data_to_c_simple(modes/shaders/object_color_axes_vert.glsl SRC) data_to_c_simple(modes/shaders/object_empty_axes_vert.glsl SRC) data_to_c_simple(modes/shaders/object_empty_image_frag.glsl SRC) data_to_c_simple(modes/shaders/object_empty_image_vert.glsl SRC) diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h index 6cae9ceb7d6..34d3ae1d207 100644 --- a/source/blender/draw/DRW_engine.h +++ b/source/blender/draw/DRW_engine.h @@ -26,28 +26,20 @@ #include "BLI_sys_types.h" /* for bool */ struct ARegion; -struct Base; struct DRWInstanceDataList; -struct DRWPass; struct Depsgraph; struct DrawEngineType; struct GPUMaterial; struct GPUOffScreen; struct GPUViewport; struct ID; -struct IDProperty; struct Main; -struct Material; struct Object; -struct RegionView3D; struct RenderEngine; struct RenderEngineType; struct Scene; struct View3D; -struct ViewContext; struct ViewLayer; -struct ViewportEngineData; -struct WorkSpace; struct bContext; struct rcti; @@ -166,8 +158,8 @@ void DRW_opengl_context_disable_ex(bool restore); void DRW_opengl_render_context_enable(void *re_gl_context); void DRW_opengl_render_context_disable(void *re_gl_context); -void DRW_gawain_render_context_enable(void *re_gpu_context); -void DRW_gawain_render_context_disable(void *re_gpu_context); +void DRW_gpu_render_context_enable(void *re_gpu_context); +void DRW_gpu_render_context_disable(void *re_gpu_context); void DRW_deferred_shader_remove(struct GPUMaterial *mat); diff --git a/source/blender/draw/DRW_select_buffer.h b/source/blender/draw/DRW_select_buffer.h index 4aa1c403710..0ad13af81ba 100644 --- a/source/blender/draw/DRW_select_buffer.h +++ b/source/blender/draw/DRW_select_buffer.h @@ -30,7 +30,6 @@ struct Base; struct Depsgraph; struct Object; struct View3D; -struct ViewLayer; struct rcti; typedef struct SELECTID_ObjectData { @@ -58,9 +57,6 @@ struct ObjectOffsets { }; struct SELECTID_Context { - struct GPUFrameBuffer *framebuffer_select_id; - struct GPUTexture *texture_u32; - /* All context objects */ struct Object **objects; uint objects_len; @@ -131,7 +127,4 @@ void DRW_select_buffer_context_create(struct Base **bases, const uint bases_len, short select_mode); -/* select_engine.c */ -struct SELECTID_Context *DRW_select_engine_context_get(void); - #endif /* __DRW_SELECT_BUFFER_H__ */ diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c index 93521c71127..0ca1e0b2858 100644 --- a/source/blender/draw/engines/eevee/eevee_effects.c +++ b/source/blender/draw/engines/eevee/eevee_effects.c @@ -509,7 +509,7 @@ void EEVEE_downsample_buffer(EEVEE_Data *vedata, GPUTexture *texture_src, int le } /** - * Simple downsampling algorithm for cubemap. Reconstruct mip chain up to mip level. + * Simple down-sampling algorithm for cubemap. Reconstruct mip chain up to mip level. */ void EEVEE_downsample_cube_buffer(EEVEE_Data *vedata, GPUTexture *texture_src, int level) { @@ -580,7 +580,7 @@ void EEVEE_draw_effects(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) /* NOTE: Lookdev drawing happens before TAA but after * motion blur and dof to avoid distortions. * Velocity resolve use a hack to exclude lookdev - * spheres from creating shimering reprojection vectors. */ + * spheres from creating shimmering re-projection vectors. */ EEVEE_lookdev_draw(vedata); EEVEE_velocity_resolve(vedata); diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c index c82a112b343..05aea652591 100644 --- a/source/blender/draw/engines/eevee/eevee_lightcache.c +++ b/source/blender/draw/engines/eevee/eevee_lightcache.c @@ -80,8 +80,8 @@ extern void DRW_opengl_context_disable(void); extern void DRW_opengl_render_context_enable(void *re_gl_context); extern void DRW_opengl_render_context_disable(void *re_gl_context); -extern void DRW_gawain_render_context_enable(void *re_gpu_context); -extern void DRW_gawain_render_context_disable(void *re_gpu_context); +extern void DRW_gpu_render_context_enable(void *re_gpu_context); +extern void DRW_gpu_render_context_disable(void *re_gpu_context); typedef struct EEVEE_LightBake { Depsgraph *depsgraph; @@ -138,7 +138,7 @@ typedef struct EEVEE_LightBake { float vis_res; /** Result of previous light bounce. */ GPUTexture *grid_prev; - /** Pointer to the id.data of the probe object. */ + /** Pointer to the owner_id of the probe object. */ LightProbe **grid_prb; /* Reflection probe */ @@ -148,7 +148,7 @@ typedef struct EEVEE_LightBake { int ref_cube_res; /** Index of the current cube. */ int cube_offset; - /** Pointer to the id.data of the probe object. */ + /** Pointer to the owner_id of the probe object. */ LightProbe **cube_prb; /* Dummy Textures */ @@ -412,7 +412,7 @@ static void eevee_lightbake_context_enable(EEVEE_LightBake *lbake) if (lbake->gpu_context == NULL) { lbake->gpu_context = GPU_context_create(0); } - DRW_gawain_render_context_enable(lbake->gpu_context); + DRW_gpu_render_context_enable(lbake->gpu_context); } else { DRW_opengl_context_enable(); @@ -422,7 +422,7 @@ static void eevee_lightbake_context_enable(EEVEE_LightBake *lbake) static void eevee_lightbake_context_disable(EEVEE_LightBake *lbake) { if (lbake->gl_context) { - DRW_gawain_render_context_disable(lbake->gpu_context); + DRW_gpu_render_context_disable(lbake->gpu_context); DRW_opengl_render_context_disable(lbake->gl_context); } else { @@ -654,7 +654,7 @@ static void eevee_lightbake_delete_resources(EEVEE_LightBake *lbake) if (lbake->gl_context) { DRW_opengl_render_context_enable(lbake->gl_context); - DRW_gawain_render_context_enable(lbake->gpu_context); + DRW_gpu_render_context_enable(lbake->gpu_context); } else if (!lbake->resource_only) { DRW_opengl_context_enable(); @@ -675,8 +675,8 @@ static void eevee_lightbake_delete_resources(EEVEE_LightBake *lbake) } if (lbake->gpu_context) { - DRW_gawain_render_context_disable(lbake->gpu_context); - DRW_gawain_render_context_enable(lbake->gpu_context); + DRW_gpu_render_context_disable(lbake->gpu_context); + DRW_gpu_render_context_enable(lbake->gpu_context); GPU_context_discard(lbake->gpu_context); } diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.h b/source/blender/draw/engines/eevee/eevee_lightcache.h index 5aea712a910..ede2de13dce 100644 --- a/source/blender/draw/engines/eevee/eevee_lightcache.h +++ b/source/blender/draw/engines/eevee/eevee_lightcache.h @@ -26,7 +26,6 @@ #include "BLI_sys_types.h" /* for bool */ struct EEVEE_Data; -struct EEVEE_LightBake; struct EEVEE_ViewLayerData; struct LightCache; struct Scene; diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c index 2026b44fe87..8b1309e8537 100644 --- a/source/blender/draw/engines/eevee/eevee_lightprobes.c +++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c @@ -1213,7 +1213,7 @@ void EEVEE_lightbake_filter_visibility(EEVEE_ViewLayerData *sldata, DRW_draw_pass(psl->probe_visibility_compute); } -/* Actually a simple downsampling */ +/* Actually a simple down-sampling. */ static void downsample_planar(void *vedata, int level) { EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl; diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c index c15872b31fa..0bfc23b8354 100644 --- a/source/blender/draw/engines/eevee/eevee_lights.c +++ b/source/blender/draw/engines/eevee/eevee_lights.c @@ -779,7 +779,7 @@ static void eevee_light_setup(Object *ob, EEVEE_Light *evli) /** * Special ball distribution: - * Point are distributed in a way that when they are orthogonaly + * Point are distributed in a way that when they are orthogonally * projected into any plane, the resulting distribution is (close to) * a uniform disc distribution. */ diff --git a/source/blender/draw/engines/eevee/eevee_lut.c b/source/blender/draw/engines/eevee/eevee_lut.c index 8db45e4cee6..b380269db99 100644 --- a/source/blender/draw/engines/eevee/eevee_lut.c +++ b/source/blender/draw/engines/eevee/eevee_lut.c @@ -21,6 +21,8 @@ * \ingroup gpu */ +#include "eevee_lut.h" /* own include */ + const float ltc_mat_ggx[64 * 64 * 4] = { 1.000000, 0.000000, 0.000000, 0.000020, 1.000000, 0.000000, 0.000000, 0.000504, 1.000000, 0.000000, 0.000000, 0.002016, 1.000000, 0.000000, 0.000000, 0.004535, diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 27edd44075b..3cdafee95a2 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -30,7 +30,6 @@ struct EEVEE_ShadowCasterBuffer; struct GPUFrameBuffer; struct Object; struct RenderLayer; -struct RenderResult; extern struct DrawEngineType draw_engine_eevee_type; diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c index b0608343ab3..33e6d73eeeb 100644 --- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c +++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c @@ -349,13 +349,13 @@ void DRW_gpencil_freecache(struct Object *ob) } } - /* clear all frames derived data */ - for (int i = 0; i < ob->runtime.tot_layers; i++) { - bGPDframe *derived_gpf = &ob->runtime.derived_frames[i]; - BKE_gpencil_free_frame_runtime_data(derived_gpf); - derived_gpf = NULL; + /* clear all frames evaluated data */ + for (int i = 0; i < ob->runtime.gpencil_tot_layers; i++) { + bGPDframe *gpf_eval = &ob->runtime.gpencil_evaluated_frames[i]; + BKE_gpencil_free_frame_runtime_data(gpf_eval); + gpf_eval = NULL; } - ob->runtime.tot_layers = 0; - MEM_SAFE_FREE(ob->runtime.derived_frames); + ob->runtime.gpencil_tot_layers = 0; + MEM_SAFE_FREE(ob->runtime.gpencil_evaluated_frames); } diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c index 1ec02cac109..541a9e31586 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c @@ -821,7 +821,7 @@ void gpencil_get_edit_geom(struct GpencilBatchCacheElem *be, void gpencil_get_edlin_geom(struct GpencilBatchCacheElem *be, bGPDstroke *gps, float alpha, - short UNUSED(dflag)) + const bool hide_select) { const DRWContextState *draw_ctx = DRW_context_state_get(); Object *ob = draw_ctx->obact; @@ -866,7 +866,7 @@ void gpencil_get_edlin_geom(struct GpencilBatchCacheElem *be, copy_v4_v4(fcolor, selectColor); } else { - if (pt->flag & GP_SPOINT_SELECT) { + if ((pt->flag & GP_SPOINT_SELECT) && (!hide_select)) { copy_v4_v4(fcolor, selectColor); } else { diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c index 85ad1689c23..bef72b9a054 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c @@ -65,8 +65,7 @@ static void gpencil_calc_vertex(GPENCIL_StorageList *stl, tGPencilObjectCache *cache_ob, GpencilBatchCache *cache, - bGPdata *gpd, - int cfra_eval) + bGPdata *gpd) { if (!cache->is_dirty) { return; @@ -88,13 +87,13 @@ static void gpencil_calc_vertex(GPENCIL_StorageList *stl, cache_ob->tot_vertex = 0; cache_ob->tot_triangles = 0; - int derived_idx = 0; + int idx_eval = 0; for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { bGPDframe *init_gpf = NULL; const bool is_onion = ((do_onion) && (gpl->onion_flag & GP_LAYER_ONIONSKIN)); if (gpl->flag & GP_LAYER_HIDE) { - derived_idx++; + idx_eval++; continue; } @@ -103,7 +102,7 @@ static void gpencil_calc_vertex(GPENCIL_StorageList *stl, init_gpf = gpl->frames.first; } else { - init_gpf = &ob->runtime.derived_frames[derived_idx]; + init_gpf = &ob->runtime.gpencil_evaluated_frames[idx_eval]; } if (init_gpf == NULL) { @@ -119,7 +118,7 @@ static void gpencil_calc_vertex(GPENCIL_StorageList *stl, break; } } - derived_idx++; + idx_eval++; } cache->b_fill.tot_vertex = cache_ob->tot_triangles * 3; @@ -939,6 +938,17 @@ static void gpencil_add_editpoints_vertexdata(GpencilBatchCache *cache, { const DRWContextState *draw_ctx = DRW_context_state_get(); View3D *v3d = draw_ctx->v3d; + ToolSettings *ts = draw_ctx->scene->toolsettings; + const bool use_sculpt_mask = (GPENCIL_SCULPT_MODE(gpd) && (ts->gpencil_selectmode_sculpt & + (GP_SCULPT_MASK_SELECTMODE_POINT | + GP_SCULPT_MASK_SELECTMODE_STROKE | + GP_SCULPT_MASK_SELECTMODE_SEGMENT))); + + const bool show_sculpt_points = (GPENCIL_SCULPT_MODE(gpd) && + (ts->gpencil_selectmode_sculpt & + (GP_SCULPT_MASK_SELECTMODE_POINT | + GP_SCULPT_MASK_SELECTMODE_SEGMENT))); + MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1); /* alpha factor for edit points/line to make them more subtle */ @@ -951,11 +961,24 @@ static void gpencil_add_editpoints_vertexdata(GpencilBatchCache *cache, } const bool is_weight_paint = (gpd) && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE); + /* If Sculpt mode and the mask is disabled, the select must be hidden. */ + const bool hide_select = GPENCIL_SCULPT_MODE(gpd) && !use_sculpt_mask; + + /* Show Edit points if: + * Edit mode: Not in Stroke selection mode + * Sculpt mode: Not in Stroke mask mode and any other mask mode enabled + * Weight mode: Always + */ + const bool show_points = (show_sculpt_points) || (is_weight_paint) || + (GPENCIL_EDIT_MODE(gpd) && + ((ts->gpencil_selectmode_edit & GP_SELECTMODE_STROKE) == 0)); + if (cache->is_dirty) { if ((obact == ob) && ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) && (v3d->gp_flag & V3D_GP_SHOW_EDIT_LINES)) { + /* line of the original stroke */ - gpencil_get_edlin_geom(&cache->b_edlin, gps, edit_alpha, gpd->flag); + gpencil_get_edlin_geom(&cache->b_edlin, gps, edit_alpha, hide_select); /* add to list of groups */ cache->grp_cache = gpencil_group_cache_add(cache->grp_cache, @@ -968,6 +991,12 @@ static void gpencil_add_editpoints_vertexdata(GpencilBatchCache *cache, &cache->grp_size, &cache->grp_used); } + + /* If the points are hidden return. */ + if ((!show_points) || (hide_select)) { + return; + } + /* edit points */ if ((gps->flag & GP_STROKE_SELECT) || (is_weight_paint)) { if ((gpl->flag & GP_LAYER_UNLOCK_COLOR) || @@ -1797,7 +1826,7 @@ void gpencil_populate_multiedit(GPENCIL_e_data *e_data, const bool playing = stl->storage->is_playing; /* calc max size of VBOs */ - gpencil_calc_vertex(stl, cache_ob, cache, gpd, cfra_eval); + gpencil_calc_vertex(stl, cache_ob, cache, gpd); /* draw strokes */ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { @@ -1860,6 +1889,14 @@ void gpencil_populate_datablock(GPENCIL_e_data *e_data, const ViewLayer *view_layer = DEG_get_evaluated_view_layer(draw_ctx->depsgraph); Scene *scene = draw_ctx->scene; + /* TODO: Review why is needed this recalc when render cycles + GP object in background. + * We need these lines to keep running the background render, but asap we get an alternative + * solution, we must remove it and keep all logic inside gpencil_modifier module. (antoniov) + */ + if (ob->runtime.gpencil_tot_layers == 0) { + BKE_gpencil_modifiers_calc(draw_ctx->depsgraph, draw_ctx->scene, ob); + } + /* Use original data to shared in edit/transform operators */ bGPdata *gpd_eval = (bGPdata *)ob->data; bGPdata *gpd = (bGPdata *)DEG_get_original_id(&gpd_eval->id); @@ -1867,7 +1904,7 @@ void gpencil_populate_datablock(GPENCIL_e_data *e_data, View3D *v3d = draw_ctx->v3d; int cfra_eval = (int)DEG_get_ctime(draw_ctx->depsgraph); - bGPDframe *derived_gpf = NULL; + bGPDframe *gpf_eval = NULL; const bool overlay = v3d != NULL ? (bool)((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) : true; const bool time_remap = BKE_gpencil_has_time_modifiers(ob); @@ -1887,7 +1924,7 @@ void gpencil_populate_datablock(GPENCIL_e_data *e_data, } /* calc max size of VBOs */ - gpencil_calc_vertex(stl, cache_ob, cache, gpd, cfra_eval); + gpencil_calc_vertex(stl, cache_ob, cache, gpd); /* draw normal strokes */ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { @@ -1936,9 +1973,9 @@ void gpencil_populate_datablock(GPENCIL_e_data *e_data, opacity = opacity * v3d->overlay.gpencil_fade_layer; } - /* Get derived frames array data */ - int derived_idx = BLI_findindex(&gpd->layers, gpl); - derived_gpf = &ob->runtime.derived_frames[derived_idx]; + /* Get evaluated frames array data */ + int idx_eval = BLI_findindex(&gpd->layers, gpl); + gpf_eval = &ob->runtime.gpencil_evaluated_frames[idx_eval]; /* draw onion skins */ if (!ID_IS_LINKED(&gpd->id)) { @@ -1952,17 +1989,8 @@ void gpencil_populate_datablock(GPENCIL_e_data *e_data, } } /* draw normal strokes */ - gpencil_draw_strokes(cache, - e_data, - vedata, - ob, - gpd, - gpl, - derived_gpf, - opacity, - gpl->tintcolor, - false, - cache_ob); + gpencil_draw_strokes( + cache, e_data, vedata, ob, gpd, gpl, gpf_eval, opacity, gpl->tintcolor, false, cache_ob); } /* create batchs and shading groups */ diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c index b0898cb33f3..d03f975ca37 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.c +++ b/source/blender/draw/engines/gpencil/gpencil_engine.c @@ -405,10 +405,10 @@ void GPENCIL_cache_init(void *vedata) } /* save simplify flags (can change while drawing, so it's better to save) */ - stl->storage->simplify_fill = GP_SIMPLIFY_FILL(scene, stl->storage->is_playing); - stl->storage->simplify_modif = GP_SIMPLIFY_MODIF(scene, stl->storage->is_playing); - stl->storage->simplify_fx = GP_SIMPLIFY_FX(scene, stl->storage->is_playing); - stl->storage->simplify_blend = GP_SIMPLIFY_BLEND(scene, stl->storage->is_playing); + stl->storage->simplify_fill = GPENCIL_SIMPLIFY_FILL(scene, stl->storage->is_playing); + stl->storage->simplify_modif = GPENCIL_SIMPLIFY_MODIF(scene, stl->storage->is_playing); + stl->storage->simplify_fx = GPENCIL_SIMPLIFY_FX(scene, stl->storage->is_playing); + stl->storage->simplify_blend = GPENCIL_SIMPLIFY_BLEND(scene, stl->storage->is_playing); /* xray mode */ if (v3d) { diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h index c3167e21f27..f29e83f64cf 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.h +++ b/source/blender/draw/engines/gpencil/gpencil_engine.h @@ -28,15 +28,14 @@ struct GPENCIL_Data; struct GPENCIL_StorageList; struct MaterialGPencilStyle; -struct ModifierData; struct Object; struct RenderEngine; struct RenderLayer; struct bGPDstroke; -struct tGPspoint; -struct GpencilBatchCache; -struct GpencilBatchCacheElem; -struct GpencilBatchGroup; + +struct GPUBatch; +struct GPUVertBuf; +struct GPUVertFormat; #define GPENCIL_CACHE_BLOCK_SIZE 8 #define GPENCIL_MAX_SHGROUPS 65536 @@ -327,6 +326,64 @@ typedef struct GPENCIL_e_data { } GPENCIL_e_data; /* Engine data */ +/* GPUBatch Cache Element */ +typedef struct GpencilBatchCacheElem { + GPUBatch *batch; + GPUVertBuf *vbo; + int vbo_len; + /* attr ids */ + GPUVertFormat *format; + uint pos_id; + uint color_id; + uint thickness_id; + uint uvdata_id; + uint prev_pos_id; + + /* size for VBO alloc */ + int tot_vertex; +} GpencilBatchCacheElem; + +/* Defines each batch group to define later the shgroup */ +typedef struct GpencilBatchGroup { + struct bGPDlayer *gpl; /* reference to original layer */ + struct bGPDframe *gpf; /* reference to original frame */ + struct bGPDstroke *gps; /* reference to original stroke */ + short type; /* type of element */ + bool onion; /* the group is part of onion skin */ + int vertex_idx; /* index of vertex data */ +} GpencilBatchGroup; + +typedef enum GpencilBatchGroup_Type { + eGpencilBatchGroupType_Stroke = 1, + eGpencilBatchGroupType_Point = 2, + eGpencilBatchGroupType_Fill = 3, + eGpencilBatchGroupType_Edit = 4, + eGpencilBatchGroupType_Edlin = 5, +} GpencilBatchGroup_Type; + +/* Runtime data for GPU and evaluated frames after applying modifiers */ +typedef struct GpencilBatchCache { + GpencilBatchCacheElem b_stroke; + GpencilBatchCacheElem b_point; + GpencilBatchCacheElem b_fill; + GpencilBatchCacheElem b_edit; + GpencilBatchCacheElem b_edlin; + + /** Cache is dirty */ + bool is_dirty; + /** Edit mode flag */ + bool is_editmode; + /** Last cache frame */ + int cache_frame; + + /** Total groups in arrays */ + int grp_used; + /** Max size of the array */ + int grp_size; + /** Array of cache elements */ + struct GpencilBatchGroup *grp_cache; +} GpencilBatchCache; + /* general drawing functions */ struct DRWShadingGroup *gpencil_shgroup_stroke_create(struct GPENCIL_Data *vedata, struct DRWPass *pass, @@ -380,7 +437,7 @@ void gpencil_get_edit_geom(struct GpencilBatchCacheElem *be, void gpencil_get_edlin_geom(struct GpencilBatchCacheElem *be, struct bGPDstroke *gps, float alpha, - short dflag); + const bool hide_select); struct GPUBatch *gpencil_get_buffer_stroke_geom(struct bGPdata *gpd, short thickness); struct GPUBatch *gpencil_get_buffer_fill_geom(struct bGPdata *gpd); diff --git a/source/blender/draw/engines/select/select_draw_utils.c b/source/blender/draw/engines/select/select_draw_utils.c index 268cd60a8aa..6a51c28c242 100644 --- a/source/blender/draw/engines/select/select_draw_utils.c +++ b/source/blender/draw/engines/select/select_draw_utils.c @@ -44,48 +44,6 @@ /** \name Draw Utilities * \{ */ -static void select_id_framebuffer_setup(struct SELECTID_Context *select_ctx) -{ - DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - int size[2]; - size[0] = GPU_texture_width(dtxl->depth); - size[1] = GPU_texture_height(dtxl->depth); - - if (select_ctx->framebuffer_select_id == NULL) { - select_ctx->framebuffer_select_id = GPU_framebuffer_create(); - } - - if ((select_ctx->texture_u32 != NULL) && - ((GPU_texture_width(select_ctx->texture_u32) != size[0]) || - (GPU_texture_height(select_ctx->texture_u32) != size[1]))) { - GPU_texture_free(select_ctx->texture_u32); - select_ctx->texture_u32 = NULL; - } - - /* Make sure the depth texture is attached. - * It may disappear when loading another Blender session. */ - GPU_framebuffer_texture_attach(select_ctx->framebuffer_select_id, dtxl->depth, 0, 0); - - if (select_ctx->texture_u32 == NULL) { - select_ctx->texture_u32 = GPU_texture_create_2d(size[0], size[1], GPU_R32UI, NULL, NULL); - GPU_framebuffer_texture_attach( - select_ctx->framebuffer_select_id, select_ctx->texture_u32, 0, 0); - - GPU_framebuffer_check_valid(select_ctx->framebuffer_select_id, NULL); - } -} - -/* Remove all tags from drawn or culled objects. */ -void select_id_context_clear(struct SELECTID_Context *select_ctx) -{ - select_ctx->objects_drawn_len = 0; - select_ctx->index_drawn_len = 1; - select_id_framebuffer_setup(select_ctx); - GPU_framebuffer_bind(select_ctx->framebuffer_select_id); - GPU_framebuffer_clear_color_depth( - select_ctx->framebuffer_select_id, (const float[4]){0.0f}, 1.0f); -} - void select_id_object_min_max(Object *obj, float r_min[3], float r_max[3]) { BoundBox *bb; @@ -104,13 +62,19 @@ void select_id_object_min_max(Object *obj, float r_min[3], float r_max[3]) short select_id_get_object_select_mode(Scene *scene, Object *ob) { short r_select_mode = 0; - if (ob->mode & (OB_MODE_WEIGHT_PAINT | OB_MODE_VERTEX_PAINT | OB_MODE_TEXTURE_PAINT)) { + if (ob->mode & (OB_MODE_WEIGHT_PAINT | OB_MODE_VERTEX_PAINT)) { Mesh *me_orig = DEG_get_original_object(ob)->data; if (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL) { r_select_mode = SCE_SELECT_FACE; } - if (me_orig->editflag & ME_EDIT_PAINT_VERT_SEL) { - r_select_mode |= SCE_SELECT_VERTEX; + else if (me_orig->editflag & ME_EDIT_PAINT_VERT_SEL) { + r_select_mode = SCE_SELECT_VERTEX; + } + } + else if (ob->mode & OB_MODE_TEXTURE_PAINT) { + Mesh *me_orig = DEG_get_original_object(ob)->data; + if (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL) { + r_select_mode = SCE_SELECT_FACE; } } else { @@ -151,12 +115,11 @@ static void draw_select_id_edit_mesh(SELECTID_StorageList *stl, BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE); - struct GPUBatch *geom_faces; - DRWShadingGroup *face_shgrp; if (select_mode & SCE_SELECT_FACE) { - geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me); - face_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_face_flat); + struct GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me); + DRWShadingGroup *face_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_face_flat); DRW_shgroup_uniform_int_copy(face_shgrp, "offset", *(int *)&initial_offset); + DRW_shgroup_call_no_cull(face_shgrp, geom_faces, ob); if (draw_facedot) { struct GPUBatch *geom_facedots = DRW_mesh_batch_cache_get_facedots_with_select_id(me); @@ -165,11 +128,13 @@ static void draw_select_id_edit_mesh(SELECTID_StorageList *stl, *r_face_offset = initial_offset + em->bm->totface; } else { - geom_faces = DRW_mesh_batch_cache_get_surface(me); - face_shgrp = stl->g_data->shgrp_face_unif; + if (ob->dt >= OB_SOLID) { + struct GPUBatch *geom_faces = DRW_mesh_batch_cache_get_surface(me); + DRWShadingGroup *face_shgrp = stl->g_data->shgrp_face_unif; + DRW_shgroup_call_no_cull(face_shgrp, geom_faces, ob); + } *r_face_offset = initial_offset; } - DRW_shgroup_call_no_cull(face_shgrp, geom_faces, ob); /* Unlike faces, only draw edges if edge select mode. */ if (select_mode & SCE_SELECT_EDGE) { diff --git a/source/blender/draw/engines/select/select_engine.c b/source/blender/draw/engines/select/select_engine.c index 4c158312e0f..c294bba2083 100644 --- a/source/blender/draw/engines/select/select_engine.c +++ b/source/blender/draw/engines/select/select_engine.c @@ -40,10 +40,13 @@ /* *********** STATIC *********** */ static struct { + struct GPUFrameBuffer *framebuffer_select_id; + struct GPUTexture *texture_u32; + SELECTID_Shaders sh_data[GPU_SHADER_CFG_LEN]; struct SELECTID_Context context; uint runtime_new_objects; -} e_data = {{{NULL}}}; /* Engine data */ +} e_data = {NULL}; /* Engine data */ /* Shaders */ extern char datatoc_common_view_lib_glsl[]; @@ -51,6 +54,41 @@ extern char datatoc_selection_id_3D_vert_glsl[]; extern char datatoc_selection_id_frag_glsl[]; /* -------------------------------------------------------------------- */ +/** \name Utils + * \{ */ + +static void select_engine_framebuffer_setup(void) +{ + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + int size[2]; + size[0] = GPU_texture_width(dtxl->depth); + size[1] = GPU_texture_height(dtxl->depth); + + if (e_data.framebuffer_select_id == NULL) { + e_data.framebuffer_select_id = GPU_framebuffer_create(); + } + + if ((e_data.texture_u32 != NULL) && ((GPU_texture_width(e_data.texture_u32) != size[0]) || + (GPU_texture_height(e_data.texture_u32) != size[1]))) { + GPU_texture_free(e_data.texture_u32); + e_data.texture_u32 = NULL; + } + + /* Make sure the depth texture is attached. + * It may disappear when loading another Blender session. */ + GPU_framebuffer_texture_attach(e_data.framebuffer_select_id, dtxl->depth, 0, 0); + + if (e_data.texture_u32 == NULL) { + e_data.texture_u32 = GPU_texture_create_2d(size[0], size[1], GPU_R32UI, NULL, NULL); + GPU_framebuffer_texture_attach(e_data.framebuffer_select_id, e_data.texture_u32, 0, 0); + + GPU_framebuffer_check_valid(e_data.framebuffer_select_id, NULL); + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Engine Functions * \{ */ @@ -125,6 +163,13 @@ static void select_cache_init(void *vedata) if (e_data.context.select_mode == -1) { e_data.context.select_mode = select_id_get_object_select_mode(draw_ctx->scene, draw_ctx->obact); + if (e_data.context.select_mode == 0) { + /* Need for sampling weights. */ + if (draw_ctx->object_mode & OB_MODE_WEIGHT_PAINT) { + e_data.context.select_mode = SCE_SELECT_FACE; + } + } + BLI_assert(e_data.context.select_mode != 0); } @@ -186,8 +231,13 @@ static void select_cache_init(void *vedata) float(*persmat)[4] = draw_ctx->rv3d->persmat; e_data.context.is_dirty = !compare_m4m4(e_data.context.persmat, persmat, FLT_EPSILON); if (e_data.context.is_dirty) { + /* Remove all tags from drawn or culled objects. */ copy_m4_m4(e_data.context.persmat, persmat); - select_id_context_clear(&e_data.context); + e_data.context.objects_drawn_len = 0; + e_data.context.index_drawn_len = 1; + select_engine_framebuffer_setup(); + GPU_framebuffer_bind(e_data.framebuffer_select_id); + GPU_framebuffer_clear_color_depth(e_data.framebuffer_select_id, (const float[4]){0.0f}, 1.0f); } e_data.runtime_new_objects = 0; } @@ -204,14 +254,14 @@ static void select_cache_populate(void *vedata, Object *ob) /* The object indices have already been drawn. Fill depth pass. * Opti: Most of the time this depth pass is not used. */ struct Mesh *me = ob->data; - struct GPUBatch *geom_faces; if (e_data.context.select_mode & SCE_SELECT_FACE) { - geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me); + struct GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me); + DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_faces, ob->obmat); } - else { - geom_faces = DRW_mesh_batch_cache_get_surface(me); + else if (ob->dt >= OB_SOLID) { + struct GPUBatch *geom_faces = DRW_mesh_batch_cache_get_surface(me); + DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_faces, ob->obmat); } - DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_faces, ob->obmat); if (e_data.context.select_mode & SCE_SELECT_EDGE) { struct GPUBatch *geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(me); @@ -283,7 +333,7 @@ static void select_draw_scene(void *vedata) } /* Setup framebuffer */ - GPU_framebuffer_bind(e_data.context.framebuffer_select_id); + GPU_framebuffer_bind(e_data.framebuffer_select_id); DRW_draw_pass(psl->select_id_face_pass); @@ -306,8 +356,8 @@ static void select_engine_free(void) DRW_SHADER_FREE_SAFE(sh_data->select_id_uniform); } - DRW_TEXTURE_FREE_SAFE(e_data.context.texture_u32); - GPU_FRAMEBUFFER_FREE_SAFE(e_data.context.framebuffer_select_id); + DRW_TEXTURE_FREE_SAFE(e_data.texture_u32); + GPU_FRAMEBUFFER_FREE_SAFE(e_data.framebuffer_select_id); MEM_SAFE_FREE(e_data.context.objects); MEM_SAFE_FREE(e_data.context.index_offsets); MEM_SAFE_FREE(e_data.context.objects_drawn); @@ -368,6 +418,16 @@ struct SELECTID_Context *DRW_select_engine_context_get(void) return &e_data.context; } +GPUFrameBuffer *DRW_engine_select_framebuffer_get(void) +{ + return e_data.framebuffer_select_id; +} + +GPUTexture *DRW_engine_select_texture_get(void) +{ + return e_data.texture_u32; +} + /** \} */ #undef SELECT_ENGINE diff --git a/source/blender/draw/engines/select/select_engine.h b/source/blender/draw/engines/select/select_engine.h index 5b900ccaf27..79139d9deaf 100644 --- a/source/blender/draw/engines/select/select_engine.h +++ b/source/blender/draw/engines/select/select_engine.h @@ -26,4 +26,9 @@ extern DrawEngineType draw_engine_select_type; extern RenderEngineType DRW_engine_viewport_select_type; -#endif /* __SELECT_ID_ENGINE_H__ */ +struct SELECTID_Context *DRW_select_engine_context_get(void); + +struct GPUFrameBuffer *DRW_engine_select_framebuffer_get(void); +struct GPUTexture *DRW_engine_select_texture_get(void); + +#endif /* __SELECT_ENGINE_H__ */ diff --git a/source/blender/draw/engines/select/select_private.h b/source/blender/draw/engines/select/select_private.h index e48ce4314ae..642cd6ffc56 100644 --- a/source/blender/draw/engines/select/select_private.h +++ b/source/blender/draw/engines/select/select_private.h @@ -66,7 +66,6 @@ typedef struct SELECTID_PrivateData { } SELECTID_PrivateData; /* Transient data */ /* select_draw_utils.c */ -void select_id_context_clear(struct SELECTID_Context *select_ctx); void select_id_object_min_max(struct Object *obj, float r_min[3], float r_max[3]); short select_id_get_object_select_mode(Scene *scene, Object *ob); void select_id_draw_object(void *vedata, diff --git a/source/blender/draw/engines/select/shaders/selection_id_frag.glsl b/source/blender/draw/engines/select/shaders/selection_id_frag.glsl index ea86ddc7301..a84bbbb2cac 100644 --- a/source/blender/draw/engines/select/shaders/selection_id_frag.glsl +++ b/source/blender/draw/engines/select/shaders/selection_id_frag.glsl @@ -1,14 +1,15 @@ #ifdef UNIFORM_ID uniform int id; -# define id floatBitsToUint(intBitsToFloat(id)) +# define _id floatBitsToUint(intBitsToFloat(id)) #else flat in uint id; +# define _id id #endif out uint fragColor; void main() { - fragColor = id; + fragColor = _id; } diff --git a/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl index a1f80440404..fd4cea4279a 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl @@ -5,7 +5,8 @@ uniform sampler2D materialBuffer; uniform sampler2D normalBuffer; /* normalBuffer contains viewport normals */ uniform sampler2D cavityBuffer; -uniform sampler2D matcapImage; +uniform sampler2D matcapDiffuseImage; +uniform sampler2D matcapSpecularImage; uniform vec2 invertedViewportSize; uniform vec4 viewvecs[3]; @@ -55,8 +56,15 @@ void main() normal_viewport = (metallic > 0.0) ? normal_viewport : -normal_viewport; bool flipped = world_data.matcap_orientation != 0; vec2 matcap_uv = matcap_uv_compute(I_vs, normal_viewport, flipped); - vec3 matcap = textureLod(matcapImage, matcap_uv, 0.0).rgb; - vec3 shaded_color = matcap * base_color; + vec3 matcap_diffuse = textureLod(matcapDiffuseImage, matcap_uv, 0.0).rgb; + +# ifdef V3D_SHADING_SPECULAR_HIGHLIGHT + vec3 matcap_specular = textureLod(matcapSpecularImage, matcap_uv, 0.0).rgb; +# else + vec3 matcap_specular = vec3(0.0); +# endif + + vec3 shaded_color = matcap_diffuse * base_color + matcap_specular; #elif defined(V3D_LIGHTING_STUDIO) diff --git a/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl index c78b2182d04..3333dfeff38 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl @@ -27,7 +27,8 @@ in vec2 uv_interp; in vec3 vertexColor; #endif #ifdef V3D_LIGHTING_MATCAP -uniform sampler2D matcapImage; +uniform sampler2D matcapDiffuseImage; +uniform sampler2D matcapSpecularImage; #endif layout(std140) uniform world_block @@ -68,8 +69,13 @@ void main() #elif defined(V3D_LIGHTING_MATCAP) bool flipped = world_data.matcap_orientation != 0; vec2 matcap_uv = matcap_uv_compute(I_vs, nor, flipped); - vec3 matcap = textureLod(matcapImage, matcap_uv, 0.0).rgb; - vec3 shaded_color = matcap * diffuse_color.rgb; + vec3 matcap_diffuse = textureLod(matcapDiffuseImage, matcap_uv, 0.0).rgb; +# ifdef V3D_SHADING_SPECULAR_HIGHLIGHT + vec3 matcap_specular = textureLod(matcapSpecularImage, matcap_uv, 0.0).rgb; +# else + vec3 matcap_specular = vec3(0.0); +# endif + vec3 shaded_color = matcap_diffuse * diffuse_color.rgb + matcap_specular; #elif defined(V3D_LIGHTING_STUDIO) vec3 shaded_color = get_world_lighting( diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c index add49462de1..c1c9d8b5a96 100644 --- a/source/blender/draw/engines/workbench/workbench_deferred.c +++ b/source/blender/draw/engines/workbench/workbench_deferred.c @@ -694,16 +694,22 @@ static void workbench_composite_uniforms(WORKBENCH_PrivateData *wpd, DRWShadingG if (CAVITY_ENABLED(wpd)) { DRW_shgroup_uniform_texture_ref(grp, "cavityBuffer", &e_data.cavity_buffer_tx); } - if (SPECULAR_HIGHLIGHT_ENABLED(wpd) || STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) { + if (workbench_is_specular_highlight_enabled(wpd) || STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) { DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)wpd->viewvecs, 3); } - if (SPECULAR_HIGHLIGHT_ENABLED(wpd) || STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) { + if (workbench_is_specular_highlight_enabled(wpd) || STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) { DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); } if (STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) { - BKE_studiolight_ensure_flag(wpd->studio_light, STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE); + BKE_studiolight_ensure_flag(wpd->studio_light, + STUDIOLIGHT_MATCAP_DIFFUSE_GPUTEXTURE | + STUDIOLIGHT_MATCAP_SPECULAR_GPUTEXTURE); DRW_shgroup_uniform_texture( - grp, "matcapImage", wpd->studio_light->equirect_radiance_gputexture); + grp, "matcapDiffuseImage", wpd->studio_light->matcap_diffuse.gputexture); + if (workbench_is_specular_highlight_enabled(wpd)) { + DRW_shgroup_uniform_texture( + grp, "matcapSpecularImage", wpd->studio_light->matcap_specular.gputexture); + } } } diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c index 4c1fce550e8..824c6e7bd76 100644 --- a/source/blender/draw/engines/workbench/workbench_forward.c +++ b/source/blender/draw/engines/workbench/workbench_forward.c @@ -186,11 +186,17 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_ DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)wpd->viewvecs, 3); workbench_material_copy(material, &material_template); if (STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) { - BKE_studiolight_ensure_flag(wpd->studio_light, STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE); + BKE_studiolight_ensure_flag(wpd->studio_light, + STUDIOLIGHT_MATCAP_DIFFUSE_GPUTEXTURE | + STUDIOLIGHT_MATCAP_SPECULAR_GPUTEXTURE); DRW_shgroup_uniform_texture( - grp, "matcapImage", wpd->studio_light->equirect_radiance_gputexture); + grp, "matcapDiffuseImage", wpd->studio_light->matcap_diffuse.gputexture); + if (workbench_is_specular_highlight_enabled(wpd)) { + DRW_shgroup_uniform_texture( + grp, "matcapSpecularImage", wpd->studio_light->matcap_specular.gputexture); + } } - if (SPECULAR_HIGHLIGHT_ENABLED(wpd) || MATCAP_ENABLED(wpd)) { + if (workbench_is_specular_highlight_enabled(wpd) || MATCAP_ENABLED(wpd)) { DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); } if (SHADOW_ENABLED(wpd)) { @@ -528,11 +534,17 @@ static void workbench_forward_cache_populate_particles(WORKBENCH_Data *vedata, O float hair_alpha = XRAY_ALPHA(wpd) * 0.33f; DRW_shgroup_uniform_float_copy(shgrp, "alpha", hair_alpha); if (STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) { - BKE_studiolight_ensure_flag(wpd->studio_light, STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE); + BKE_studiolight_ensure_flag(wpd->studio_light, + STUDIOLIGHT_MATCAP_DIFFUSE_GPUTEXTURE | + STUDIOLIGHT_MATCAP_SPECULAR_GPUTEXTURE); DRW_shgroup_uniform_texture( - shgrp, "matcapImage", wpd->studio_light->equirect_radiance_gputexture); + shgrp, "matcapDiffuseImage", wpd->studio_light->matcap_diffuse.gputexture); + if (workbench_is_specular_highlight_enabled(wpd)) { + DRW_shgroup_uniform_texture( + shgrp, "matcapSpecularImage", wpd->studio_light->matcap_specular.gputexture); + } } - if (SPECULAR_HIGHLIGHT_ENABLED(wpd) || MATCAP_ENABLED(wpd)) { + if (workbench_is_specular_highlight_enabled(wpd) || MATCAP_ENABLED(wpd)) { DRW_shgroup_uniform_vec2(shgrp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); } diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c index 6699a1954ba..e050877187e 100644 --- a/source/blender/draw/engines/workbench/workbench_materials.c +++ b/source/blender/draw/engines/workbench/workbench_materials.c @@ -79,7 +79,7 @@ void workbench_material_update_data(WORKBENCH_PrivateData *wpd, /* V3D_SHADING_MATERIAL_COLOR or V3D_SHADING_TEXTURE_COLOR */ if (mat) { data->alpha *= mat->a; - if (SPECULAR_HIGHLIGHT_ENABLED(wpd)) { + if (workbench_is_specular_highlight_enabled(wpd)) { copy_v3_v3(data->base_color, &mat->r); mul_v3_v3fl(data->diffuse_color, &mat->r, 1.0f - mat->metallic); mul_v3_v3fl(data->specular_color, &mat->r, mat->metallic); @@ -121,7 +121,7 @@ char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, if (SSAO_ENABLED(wpd) || CURVATURE_ENABLED(wpd)) { BLI_dynstr_append(ds, "#define WB_CAVITY\n"); } - if (SPECULAR_HIGHLIGHT_ENABLED(wpd)) { + if (workbench_is_specular_highlight_enabled(wpd)) { BLI_dynstr_append(ds, "#define V3D_SHADING_SPECULAR_HIGHLIGHT\n"); } if (STUDIOLIGHT_ENABLED(wpd)) { @@ -195,11 +195,12 @@ int workbench_material_get_composite_shader_index(WORKBENCH_PrivateData *wpd) /* NOTE: change MAX_COMPOSITE_SHADERS accordingly when modifying this function. */ int index = 0; /* 2 bits FLAT/STUDIO/MATCAP + Specular highlight */ - index = SPECULAR_HIGHLIGHT_ENABLED(wpd) ? 3 : wpd->shading.light; + index = wpd->shading.light; SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_SHADOW, 1 << 2); SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_CAVITY, 1 << 3); SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE, 1 << 4); SET_FLAG_FROM_TEST(index, workbench_is_matdata_pass_enabled(wpd), 1 << 5); + SET_FLAG_FROM_TEST(index, workbench_is_specular_highlight_enabled(wpd), 1 << 6); BLI_assert(index < MAX_COMPOSITE_SHADERS); return index; } @@ -246,12 +247,13 @@ int workbench_material_get_accum_shader_index(WORKBENCH_PrivateData *wpd, /* NOTE: change MAX_ACCUM_SHADERS accordingly when modifying this function. */ int index = 0; /* 2 bits FLAT/STUDIO/MATCAP + Specular highlight */ - index = SPECULAR_HIGHLIGHT_ENABLED(wpd) ? 3 : wpd->shading.light; + index = wpd->shading.light; SET_FLAG_FROM_TEST(index, use_textures, 1 << 2); SET_FLAG_FROM_TEST(index, use_vertex_colors, 1 << 3); SET_FLAG_FROM_TEST(index, is_hair, 1 << 4); /* 1 bits SHADOWS (only facing factor) */ SET_FLAG_FROM_TEST(index, SHADOW_ENABLED(wpd), 1 << 5); + SET_FLAG_FROM_TEST(index, workbench_is_specular_highlight_enabled(wpd), 1 << 6); BLI_assert(index < MAX_ACCUM_SHADERS); return index; } @@ -333,7 +335,7 @@ void workbench_material_shgroup_uniform(WORKBENCH_PrivateData *wpd, 1); } - if (SPECULAR_HIGHLIGHT_ENABLED(wpd)) { + if (workbench_is_specular_highlight_enabled(wpd)) { if (use_metallic) { DRW_shgroup_uniform_float(grp, "materialMetallic", &material->metallic, 1); } diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h index 255b036eebb..d880d5d58b5 100644 --- a/source/blender/draw/engines/workbench/workbench_private.h +++ b/source/blender/draw/engines/workbench/workbench_private.h @@ -36,9 +36,9 @@ #define WORKBENCH_ENGINE "BLENDER_WORKBENCH" #define M_GOLDEN_RATION_CONJUGATE 0.618033988749895 -#define MAX_COMPOSITE_SHADERS (1 << 6) +#define MAX_COMPOSITE_SHADERS (1 << 7) #define MAX_PREPASS_SHADERS (1 << 7) -#define MAX_ACCUM_SHADERS (1 << 6) +#define MAX_ACCUM_SHADERS (1 << 7) #define MAX_CAVITY_SHADERS (1 << 3) #define TEXTURE_DRAWING_ENABLED(wpd) (wpd->shading.color_type == V3D_SHADING_TEXTURE_COLOR) @@ -77,9 +77,6 @@ #define IS_NAVIGATING(wpd) \ ((DRW_context_state_get()->rv3d) && (DRW_context_state_get()->rv3d->rflag & RV3D_NAVIGATING)) -#define SPECULAR_HIGHLIGHT_ENABLED(wpd) \ - (STUDIOLIGHT_ENABLED(wpd) && (wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT) && \ - (!STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd))) #define OBJECT_OUTLINE_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE) #define OBJECT_ID_PASS_ENABLED(wpd) (OBJECT_OUTLINE_ENABLED(wpd) || CURVATURE_ENABLED(wpd)) #define NORMAL_VIEWPORT_COMP_PASS_ENABLED(wpd) \ @@ -316,6 +313,16 @@ typedef struct WORKBENCH_ObjectData { } WORKBENCH_ObjectData; /* inline helper functions */ +BLI_INLINE bool workbench_is_specular_highlight_enabled(WORKBENCH_PrivateData *wpd) +{ + if ((wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT)) { + if (STUDIOLIGHT_ENABLED(wpd) || MATCAP_ENABLED(wpd)) { + return (wpd->studio_light->flag & STUDIOLIGHT_SPECULAR_HIGHLIGHT_PASS) != 0; + } + } + return false; +} + BLI_INLINE bool workbench_is_taa_enabled(WORKBENCH_PrivateData *wpd) { if (DRW_state_is_image_render()) { diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index 8e4ca1cefab..a289152807c 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -61,7 +61,6 @@ #include "DEG_depsgraph.h" -struct DRWTextStore; struct DefaultFramebufferList; struct DefaultTextureList; struct GPUBatch; @@ -70,12 +69,9 @@ struct GPUMaterial; struct GPUShader; struct GPUTexture; struct GPUUniformBuffer; -struct LightEngineData; struct Object; struct ParticleSystem; struct RenderEngineType; -struct ViewportEngineData; -struct ViewportEngineData_Info; struct bContext; struct rcti; diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index bad4b55eb1a..520932bc429 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -4001,7 +4001,7 @@ GPUBatch *DRW_cache_cursor_get(bool crosshair_lines) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Batch Cache Impl. common +/** \name Batch Cache Implementation (common) * \{ */ void drw_batch_cache_validate(Object *ob) diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h index 5dadcdc1457..273e97c6e49 100644 --- a/source/blender/draw/intern/draw_cache.h +++ b/source/blender/draw/intern/draw_cache.h @@ -27,8 +27,8 @@ struct GPUBatch; struct GPUMaterial; struct ModifierData; struct Object; -struct ParticleSystem; struct PTCacheEdit; +struct ParticleSystem; void DRW_shape_cache_free(void); void DRW_shape_cache_reset(void); diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.c b/source/blender/draw/intern/draw_cache_extract_mesh.c index 95b984747bd..d952965de35 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.c +++ b/source/blender/draw/intern/draw_cache_extract_mesh.c @@ -454,7 +454,8 @@ static void *extract_tris_init(const MeshRenderData *mr, void *UNUSED(ibo)) BMFace *efa; BM_ITER_MESH (efa, &iter, mr->bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { - mat_tri_len[efa->mat_nr] += efa->len - 2; + int mat = min_ii(efa->mat_nr, mr->mat_len - 1); + mat_tri_len[mat] += efa->len - 2; } } } @@ -462,7 +463,8 @@ static void *extract_tris_init(const MeshRenderData *mr, void *UNUSED(ibo)) const MPoly *mpoly = mr->mpoly; for (int p = 0; p < mr->poly_len; p++, mpoly++) { if (!(mr->use_hide && (mpoly->flag & ME_HIDE))) { - mat_tri_len[mpoly->mat_nr] += mpoly->totloop - 2; + int mat = min_ii(mpoly->mat_nr, mr->mat_len - 1); + mat_tri_len[mat] += mpoly->totloop - 2; } } } @@ -505,11 +507,12 @@ static void extract_tris_looptri_mesh(const MeshRenderData *mr, void *_data) { const MPoly *mpoly = &mr->mpoly[mlt->poly]; - if (!(mpoly->flag & ME_HIDE)) { + if (!(mr->use_hide && (mpoly->flag & ME_HIDE))) { MeshExtract_Tri_Data *data = _data; int *mat_tri_ofs = data->tri_mat_end; + int mat = min_ii(mpoly->mat_nr, mr->mat_len - 1); GPU_indexbuf_set_tri_verts( - &data->elb, mat_tri_ofs[mpoly->mat_nr]++, mlt->tri[0], mlt->tri[1], mlt->tri[2]); + &data->elb, mat_tri_ofs[mat]++, mlt->tri[0], mlt->tri[1], mlt->tri[2]); } } @@ -534,18 +537,20 @@ static void extract_tris_finish(const MeshRenderData *mr, void *ibo, void *_data MEM_freeN(data); } -const MeshExtract extract_tris = {extract_tris_init, - extract_tris_looptri_bmesh, - extract_tris_looptri_mesh, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - extract_tris_finish, - 0, - false}; +static const MeshExtract extract_tris = { + extract_tris_init, + extract_tris_looptri_bmesh, + extract_tris_looptri_mesh, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + extract_tris_finish, + 0, + false, +}; /** \} */ @@ -645,18 +650,20 @@ static void extract_lines_finish(const MeshRenderData *mr, void *ibo, void *elb) } } -const MeshExtract extract_lines = {extract_lines_init, - NULL, - NULL, - extract_lines_loop_bmesh, - extract_lines_loop_mesh, - extract_lines_ledge_bmesh, - extract_lines_ledge_mesh, - NULL, - NULL, - extract_lines_finish, - 0, - false}; +static const MeshExtract extract_lines = { + extract_lines_init, + NULL, + NULL, + extract_lines_loop_bmesh, + extract_lines_loop_mesh, + extract_lines_ledge_bmesh, + extract_lines_ledge_mesh, + NULL, + NULL, + extract_lines_finish, + 0, + false, +}; /** \} */ @@ -750,18 +757,20 @@ static void extract_points_finish(const MeshRenderData *UNUSED(mr), void *ibo, v MEM_freeN(elb); } -const MeshExtract extract_points = {extract_points_init, - NULL, - NULL, - extract_points_loop_bmesh, - extract_points_loop_mesh, - extract_points_ledge_bmesh, - extract_points_ledge_mesh, - extract_points_lvert_bmesh, - extract_points_lvert_mesh, - extract_points_finish, - 0, - false}; +static const MeshExtract extract_points = { + extract_points_init, + NULL, + NULL, + extract_points_loop_bmesh, + extract_points_loop_mesh, + extract_points_ledge_bmesh, + extract_points_ledge_mesh, + extract_points_lvert_bmesh, + extract_points_lvert_mesh, + extract_points_finish, + 0, + false, +}; /** \} */ @@ -813,18 +822,20 @@ static void extract_fdots_finish(const MeshRenderData *UNUSED(mr), void *ibo, vo MEM_freeN(elb); } -const MeshExtract extract_fdots = {extract_fdots_init, - NULL, - NULL, - extract_fdots_loop_bmesh, - extract_fdots_loop_mesh, - NULL, - NULL, - NULL, - NULL, - extract_fdots_finish, - 0, - false}; +static const MeshExtract extract_fdots = { + extract_fdots_init, + NULL, + NULL, + extract_fdots_loop_bmesh, + extract_fdots_loop_mesh, + NULL, + NULL, + NULL, + NULL, + extract_fdots_finish, + 0, + false, +}; /** \} */ @@ -886,18 +897,20 @@ static void extract_lines_paint_mask_finish(const MeshRenderData *UNUSED(mr), MEM_freeN(data); } -const MeshExtract extract_lines_paint_mask = {extract_lines_paint_mask_init, - NULL, - NULL, - NULL, - extract_lines_paint_mask_loop_mesh, - NULL, - NULL, - NULL, - NULL, - extract_lines_paint_mask_finish, - 0, - false}; +static const MeshExtract extract_lines_paint_mask = { + extract_lines_paint_mask_init, + NULL, + NULL, + NULL, + extract_lines_paint_mask_loop_mesh, + NULL, + NULL, + NULL, + NULL, + extract_lines_paint_mask_finish, + 0, + false, +}; /** \} */ @@ -919,7 +932,7 @@ static void *extract_lines_adjacency_init(const MeshRenderData *mr, void *UNUSED { /* Similar to poly_to_tri_count(). * There is always loop + tri - 1 edges inside a polygon. - * Cummulate for all polys and you get : */ + * Accumulate for all polys and you get : */ uint tess_edge_len = mr->loop_len + mr->tri_len - mr->poly_len; size_t vert_to_loop_size = sizeof(uint) * mr->vert_len; @@ -1038,18 +1051,20 @@ static void extract_lines_adjacency_finish(const MeshRenderData *mr, void *ibo, #undef NO_EDGE -const MeshExtract extract_lines_adjacency = {extract_lines_adjacency_init, - extract_lines_adjacency_looptri_bmesh, - extract_lines_adjacency_looptri_mesh, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - extract_lines_adjacency_finish, - 0, - false}; +static const MeshExtract extract_lines_adjacency = { + extract_lines_adjacency_init, + extract_lines_adjacency_looptri_bmesh, + extract_lines_adjacency_looptri_mesh, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + extract_lines_adjacency_finish, + 0, + false, +}; /** \} */ @@ -1112,18 +1127,20 @@ static void extract_edituv_tris_finish(const MeshRenderData *UNUSED(mr), void *i MEM_freeN(extract_data); } -const MeshExtract extract_edituv_tris = {extract_edituv_tris_init, - extract_edituv_tris_looptri_bmesh, - extract_edituv_tris_looptri_mesh, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - extract_edituv_tris_finish, - 0, - false}; +static const MeshExtract extract_edituv_tris = { + extract_edituv_tris_init, + extract_edituv_tris_looptri_bmesh, + extract_edituv_tris_looptri_mesh, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + extract_edituv_tris_finish, + 0, + false, +}; /** \} */ @@ -1185,18 +1202,20 @@ static void extract_edituv_lines_finish(const MeshRenderData *UNUSED(mr), void * MEM_freeN(extract_data); } -const MeshExtract extract_edituv_lines = {extract_edituv_lines_init, - NULL, - NULL, - extract_edituv_lines_loop_bmesh, - extract_edituv_lines_loop_mesh, - NULL, - NULL, - NULL, - NULL, - extract_edituv_lines_finish, - 0, - false}; +static const MeshExtract extract_edituv_lines = { + extract_edituv_lines_init, + NULL, + NULL, + extract_edituv_lines_loop_bmesh, + extract_edituv_lines_loop_mesh, + NULL, + NULL, + NULL, + NULL, + extract_edituv_lines_finish, + 0, + false, +}; /** \} */ @@ -1254,18 +1273,20 @@ static void extract_edituv_points_finish(const MeshRenderData *UNUSED(mr), void MEM_freeN(extract_data); } -const MeshExtract extract_edituv_points = {extract_edituv_points_init, - NULL, - NULL, - extract_edituv_points_loop_bmesh, - extract_edituv_points_loop_mesh, - NULL, - NULL, - NULL, - NULL, - extract_edituv_points_finish, - 0, - false}; +static const MeshExtract extract_edituv_points = { + extract_edituv_points_init, + NULL, + NULL, + extract_edituv_points_loop_bmesh, + extract_edituv_points_loop_mesh, + NULL, + NULL, + NULL, + NULL, + extract_edituv_points_finish, + 0, + false, +}; /** \} */ @@ -1330,18 +1351,20 @@ static void extract_edituv_fdots_finish(const MeshRenderData *UNUSED(mr), void * MEM_freeN(data); } -const MeshExtract extract_edituv_fdots = {extract_edituv_fdots_init, - NULL, - NULL, - extract_edituv_fdots_loop_bmesh, - extract_edituv_fdots_loop_mesh, - NULL, - NULL, - NULL, - NULL, - extract_edituv_fdots_finish, - 0, - false}; +static const MeshExtract extract_edituv_fdots = { + extract_edituv_fdots_init, + NULL, + NULL, + extract_edituv_fdots_loop_bmesh, + extract_edituv_fdots_loop_mesh, + NULL, + NULL, + NULL, + NULL, + extract_edituv_fdots_finish, + 0, + false, +}; /** \} */ @@ -1410,7 +1433,7 @@ static void extract_pos_nor_loop_mesh(const MeshRenderData *mr, int l, const MLoop *mloop, int UNUSED(p), - const MPoly *mpoly, + const MPoly *UNUSED(mpoly), void *_data) { MeshExtract_PosNor_Data *data = _data; @@ -1419,12 +1442,15 @@ static void extract_pos_nor_loop_mesh(const MeshRenderData *mr, copy_v3_v3(vert->pos, mvert->co); vert->nor = data->packed_nor[mloop->v]; /* Flag for paint mode overlay. */ - if (mpoly->flag & ME_HIDE) + if (mvert->flag & ME_HIDE) { vert->nor.w = -1; - else if (mpoly->flag & ME_FACE_SEL) + } + else if (mvert->flag & SELECT) { vert->nor.w = 1; - else + } + else { vert->nor.w = 0; + } } static void extract_pos_nor_ledge_bmesh(const MeshRenderData *mr, int e, BMEdge *eed, void *_data) @@ -1479,18 +1505,20 @@ static void extract_pos_nor_finish(const MeshRenderData *UNUSED(mr), void *UNUSE MEM_freeN(data); } -const MeshExtract extract_pos_nor = {extract_pos_nor_init, - NULL, - NULL, - extract_pos_nor_loop_bmesh, - extract_pos_nor_loop_mesh, - extract_pos_nor_ledge_bmesh, - extract_pos_nor_ledge_mesh, - extract_pos_nor_lvert_bmesh, - extract_pos_nor_lvert_mesh, - extract_pos_nor_finish, - 0, - true}; +static const MeshExtract extract_pos_nor = { + extract_pos_nor_init, + NULL, + NULL, + extract_pos_nor_loop_bmesh, + extract_pos_nor_loop_mesh, + extract_pos_nor_ledge_bmesh, + extract_pos_nor_ledge_mesh, + extract_pos_nor_lvert_bmesh, + extract_pos_nor_lvert_mesh, + extract_pos_nor_finish, + 0, + true, +}; /** \} */ /* ---------------------------------------------------------------------- */ @@ -1501,7 +1529,7 @@ static void *extract_lnor_init(const MeshRenderData *mr, void *buf) { static GPUVertFormat format = {0}; if (format.attr_len == 0) { - GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I10, 3, GPU_FETCH_INT_TO_FLOAT_UNIT); + GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); GPU_vertformat_alias_add(&format, "lnor"); } GPUVertBuf *vbo = buf; @@ -1536,20 +1564,32 @@ static void extract_lnor_loop_mesh( else { ((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(mr->poly_normals[p]); } -} - -const MeshExtract extract_lnor = {extract_lnor_init, - NULL, - NULL, - extract_lnor_loop_bmesh, - extract_lnor_loop_mesh, - NULL, - NULL, - NULL, - NULL, - NULL, - MR_DATA_LOOP_NOR, - true}; + /* Flag for paint mode overlay. */ + if (mpoly->flag & ME_HIDE) { + ((GPUPackedNormal *)data)[l].w = -1; + } + else if (mpoly->flag & ME_FACE_SEL) { + ((GPUPackedNormal *)data)[l].w = 1; + } + else { + ((GPUPackedNormal *)data)[l].w = 0; + } +} + +static const MeshExtract extract_lnor = { + extract_lnor_init, + NULL, + NULL, + extract_lnor_loop_bmesh, + extract_lnor_loop_mesh, + NULL, + NULL, + NULL, + NULL, + NULL, + MR_DATA_LOOP_NOR, + true, +}; /** \} */ @@ -1633,8 +1673,21 @@ static void *extract_uv_init(const MeshRenderData *mr, void *buf) return NULL; } -const MeshExtract extract_uv = { - extract_uv_init, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, false}; +static const MeshExtract extract_uv = { + extract_uv_init, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + 0, + false, +}; + /** \} */ /* ---------------------------------------------------------------------- */ @@ -1775,18 +1828,20 @@ static void *extract_tan_init(const MeshRenderData *mr, void *buf) return NULL; } -const MeshExtract extract_tan = {extract_tan_init, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI, - false}; +static const MeshExtract extract_tan = { + extract_tan_init, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI, + false, +}; /** \} */ @@ -1840,10 +1895,21 @@ static void *extract_vcol_init(const MeshRenderData *mr, void *buf) return NULL; } -const MeshExtract extract_vcol = { - extract_vcol_init, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, false}; +static const MeshExtract extract_vcol = { + extract_vcol_init, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + 0, + false, +}; -/** \} */ /** \} */ +/** \} */ /* ---------------------------------------------------------------------- */ /** \name Extract Orco @@ -1859,8 +1925,8 @@ static void *extract_orco_init(const MeshRenderData *mr, void *buf) static GPUVertFormat format = {0}; if (format.attr_len == 0) { /* FIXME(fclem): We use the last component as a way to differentiate from generic vertex - * attribs. This is a substential waste of Vram and should be done another way. - * Unfortunately, at the time of writting, I did not found any other "non disruptive" + * attribs. This is a substantial waste of Vram and should be done another way. + * Unfortunately, at the time of writing, I did not found any other "non disruptive" * alternative. */ GPU_vertformat_attr_add(&format, "orco", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); } @@ -1908,18 +1974,20 @@ static void extract_orco_finish(const MeshRenderData *UNUSED(mr), void *UNUSED(b MEM_freeN(data); } -const MeshExtract extract_orco = {extract_orco_init, - NULL, - NULL, - extract_orco_loop_bmesh, - extract_orco_loop_mesh, - NULL, - NULL, - NULL, - NULL, - extract_orco_finish, - 0, - true}; +static const MeshExtract extract_orco = { + extract_orco_init, + NULL, + NULL, + extract_orco_loop_bmesh, + extract_orco_loop_mesh, + NULL, + NULL, + NULL, + NULL, + extract_orco_finish, + 0, + true, +}; /** \} */ @@ -2085,18 +2153,20 @@ static void extract_edge_fac_finish(const MeshRenderData *mr, void *buf, void *_ MEM_freeN(data); } -const MeshExtract extract_edge_fac = {extract_edge_fac_init, - NULL, - NULL, - extract_edge_fac_loop_bmesh, - extract_edge_fac_loop_mesh, - extract_edge_fac_ledge_bmesh, - extract_edge_fac_ledge_mesh, - NULL, - NULL, - extract_edge_fac_finish, - MR_DATA_POLY_NOR, - false}; +static const MeshExtract extract_edge_fac = { + extract_edge_fac_init, + NULL, + NULL, + extract_edge_fac_loop_bmesh, + extract_edge_fac_loop_mesh, + extract_edge_fac_ledge_bmesh, + extract_edge_fac_ledge_mesh, + NULL, + NULL, + extract_edge_fac_finish, + MR_DATA_POLY_NOR, + false, +}; /** \} */ /* ---------------------------------------------------------------------- */ @@ -2213,18 +2283,20 @@ static void extract_weights_finish(const MeshRenderData *UNUSED(mr), void *UNUSE MEM_freeN(data); } -const MeshExtract extract_weights = {extract_weights_init, - NULL, - NULL, - extract_weights_loop_bmesh, - extract_weights_loop_mesh, - NULL, - NULL, - NULL, - NULL, - extract_weights_finish, - 0, - true}; +static const MeshExtract extract_weights = { + extract_weights_init, + NULL, + NULL, + extract_weights_loop_bmesh, + extract_weights_loop_mesh, + NULL, + NULL, + NULL, + NULL, + extract_weights_finish, + 0, + true, +}; /** \} */ @@ -2479,18 +2551,20 @@ static void extract_edit_data_lvert_mesh(const MeshRenderData *mr, } } -const MeshExtract extract_edit_data = {extract_edit_data_init, - NULL, - NULL, - extract_edit_data_loop_bmesh, - extract_edit_data_loop_mesh, - extract_edit_data_ledge_bmesh, - extract_edit_data_ledge_mesh, - extract_edit_data_lvert_bmesh, - extract_edit_data_lvert_mesh, - NULL, - 0, - true}; +static const MeshExtract extract_edit_data = { + extract_edit_data_init, + NULL, + NULL, + extract_edit_data_loop_bmesh, + extract_edit_data_loop_mesh, + extract_edit_data_ledge_bmesh, + extract_edit_data_ledge_mesh, + extract_edit_data_lvert_bmesh, + extract_edit_data_lvert_mesh, + NULL, + 0, + true, +}; /** \} */ @@ -2516,7 +2590,7 @@ static void *extract_edituv_data_init(const MeshRenderData *mr, void *buf) GPU_vertbuf_init_with_format(vbo, &format); GPU_vertbuf_data_alloc(vbo, mr->loop_len); - CustomData *cd_ldata = &mr->me->ldata; + CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata; MeshExtract_EditUVData_Data *data = MEM_callocN(sizeof(*data), __func__); data->vbo_data = (EditLoopData *)vbo->data; @@ -2577,18 +2651,20 @@ static void extract_edituv_data_finish(const MeshRenderData *UNUSED(mr), MEM_freeN(data); } -const MeshExtract extract_edituv_data = {extract_edituv_data_init, - NULL, - NULL, - extract_edituv_data_loop_bmesh, - extract_edituv_data_loop_mesh, - NULL, - NULL, - NULL, - NULL, - extract_edituv_data_finish, - 0, - true}; +static const MeshExtract extract_edituv_data = { + extract_edituv_data_init, + NULL, + NULL, + extract_edituv_data_loop_bmesh, + extract_edituv_data_loop_mesh, + NULL, + NULL, + NULL, + NULL, + extract_edituv_data_finish, + 0, + true, +}; /** \} */ @@ -2708,18 +2784,20 @@ static void mesh_stretch_area_finish(const MeshRenderData *mr, void *buf, void * MEM_freeN(area_ratio); } -const MeshExtract extract_stretch_area = {extract_stretch_area_init, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - mesh_stretch_area_finish, - 0, - false}; +static const MeshExtract extract_stretch_area = { + extract_stretch_area_init, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + mesh_stretch_area_finish, + 0, + false, +}; /** \} */ @@ -2744,8 +2822,8 @@ static void compute_normalize_edge_vectors(float auv[2][2], float av[2][3], const float uv[2], const float uv_prev[2], - const float co[2], - const float co_prev[2]) + const float co[3], + const float co_prev[3]) { /* Move previous edge. */ copy_v2_v2(auv[0], auv[1]); @@ -2896,18 +2974,20 @@ static void extract_stretch_angle_finish(const MeshRenderData *UNUSED(mr), MEM_freeN(data); } -const MeshExtract extract_stretch_angle = {extract_stretch_angle_init, - NULL, - NULL, - extract_stretch_angle_loop_bmesh, - extract_stretch_angle_loop_mesh, - NULL, - NULL, - NULL, - NULL, - extract_stretch_angle_finish, - 0, - true}; +static const MeshExtract extract_stretch_angle = { + extract_stretch_angle_init, + NULL, + NULL, + extract_stretch_angle_loop_bmesh, + extract_stretch_angle_loop_mesh, + NULL, + NULL, + NULL, + NULL, + extract_stretch_angle_finish, + 0, + false, +}; /** \} */ @@ -3479,20 +3559,22 @@ static void extract_mesh_analysis_finish(const MeshRenderData *mr, void *buf, vo } } -const MeshExtract extract_mesh_analysis = {extract_mesh_analysis_init, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - extract_mesh_analysis_finish, - /* This is not needed for all vis type. - * Maybe split into different extract. */ - MR_DATA_POLY_NOR | MR_DATA_LOOPTRI, - false}; +static const MeshExtract extract_mesh_analysis = { + extract_mesh_analysis_init, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + extract_mesh_analysis_finish, + /* This is not needed for all vis type. + * Maybe split into different extract. */ + MR_DATA_POLY_NOR | MR_DATA_LOOPTRI, + false, +}; /** \} */ @@ -3546,18 +3628,20 @@ static void extract_fdots_pos_loop_mesh(const MeshRenderData *mr, } } -const MeshExtract extract_fdots_pos = {extract_fdots_pos_init, - NULL, - NULL, - extract_fdots_pos_loop_bmesh, - extract_fdots_pos_loop_mesh, - NULL, - NULL, - NULL, - NULL, - NULL, - 0, - true}; +static const MeshExtract extract_fdots_pos = { + extract_fdots_pos_init, + NULL, + NULL, + extract_fdots_pos_loop_bmesh, + extract_fdots_pos_loop_mesh, + NULL, + NULL, + NULL, + NULL, + NULL, + 0, + true, +}; /** \} */ @@ -3604,18 +3688,20 @@ static void extract_fdots_nor_finish(const MeshRenderData *mr, void *buf, void * } } -const MeshExtract extract_fdots_nor = {extract_fdots_nor_init, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - extract_fdots_nor_finish, - MR_DATA_POLY_NOR, - false}; +static const MeshExtract extract_fdots_nor = { + extract_fdots_nor_init, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + extract_fdots_nor_finish, + MR_DATA_POLY_NOR, + false, +}; /** \} */ @@ -3686,18 +3772,20 @@ static void extract_fdots_uv_finish(const MeshRenderData *UNUSED(mr), MEM_freeN(data); } -const MeshExtract extract_fdots_uv = {extract_fdots_uv_init, - NULL, - NULL, - extract_fdots_uv_loop_bmesh, - extract_fdots_uv_loop_mesh, - NULL, - NULL, - NULL, - NULL, - extract_fdots_uv_finish, - 0, - true}; +static const MeshExtract extract_fdots_uv = { + extract_fdots_uv_init, + NULL, + NULL, + extract_fdots_uv_loop_bmesh, + extract_fdots_uv_loop_mesh, + NULL, + NULL, + NULL, + NULL, + extract_fdots_uv_finish, + 0, + true, +}; /** \} */ /* ---------------------------------------------------------------------- */ @@ -3759,18 +3847,20 @@ static void extract_fdots_edituv_data_finish(const MeshRenderData *UNUSED(mr), MEM_freeN(data); } -const MeshExtract extract_fdots_edituv_data = {extract_fdots_edituv_data_init, - NULL, - NULL, - extract_fdots_edituv_data_loop_bmesh, - extract_fdots_edituv_data_loop_mesh, - NULL, - NULL, - NULL, - NULL, - extract_fdots_edituv_data_finish, - 0, - true}; +static const MeshExtract extract_fdots_edituv_data = { + extract_fdots_edituv_data_init, + NULL, + NULL, + extract_fdots_edituv_data_loop_bmesh, + extract_fdots_edituv_data_loop_mesh, + NULL, + NULL, + NULL, + NULL, + extract_fdots_edituv_data_finish, + 0, + true, +}; /** \} */ /* ---------------------------------------------------------------------- */ @@ -3790,7 +3880,7 @@ static void *extract_select_idx_init(const MeshRenderData *mr, void *buf) return vbo->data; } -/* TODO Use glVertexID to get loop index and use the data structure on the CPU to retreive the +/* TODO Use glVertexID to get loop index and use the data structure on the CPU to retrieve the * select element associated with this loop ID. This would remove the need for this separate index * VBOs. We could upload the p/e/v_origindex as a buffer texture and sample it inside the shader to * output original index. */ @@ -3898,44 +3988,50 @@ static void extract_vert_idx_lvert_mesh(const MeshRenderData *mr, ((uint32_t *)data)[mr->loop_len + mr->edge_loose_len * 2 + v] = v_orig; } -const MeshExtract extract_poly_idx = {extract_select_idx_init, - NULL, - NULL, - extract_poly_idx_loop_bmesh, - extract_poly_idx_loop_mesh, - NULL, - NULL, - NULL, - NULL, - NULL, - 0, - true}; - -const MeshExtract extract_edge_idx = {extract_select_idx_init, - NULL, - NULL, - extract_edge_idx_loop_bmesh, - extract_edge_idx_loop_mesh, - extract_edge_idx_ledge_bmesh, - extract_edge_idx_ledge_mesh, - NULL, - NULL, - NULL, - 0, - true}; - -const MeshExtract extract_vert_idx = {extract_select_idx_init, - NULL, - NULL, - extract_vert_idx_loop_bmesh, - extract_vert_idx_loop_mesh, - extract_vert_idx_ledge_bmesh, - extract_vert_idx_ledge_mesh, - extract_vert_idx_lvert_bmesh, - extract_vert_idx_lvert_mesh, - NULL, - 0, - true}; +static const MeshExtract extract_poly_idx = { + extract_select_idx_init, + NULL, + NULL, + extract_poly_idx_loop_bmesh, + extract_poly_idx_loop_mesh, + NULL, + NULL, + NULL, + NULL, + NULL, + 0, + true, +}; + +static const MeshExtract extract_edge_idx = { + extract_select_idx_init, + NULL, + NULL, + extract_edge_idx_loop_bmesh, + extract_edge_idx_loop_mesh, + extract_edge_idx_ledge_bmesh, + extract_edge_idx_ledge_mesh, + NULL, + NULL, + NULL, + 0, + true, +}; + +static const MeshExtract extract_vert_idx = { + extract_select_idx_init, + NULL, + NULL, + extract_vert_idx_loop_bmesh, + extract_vert_idx_loop_mesh, + extract_vert_idx_ledge_bmesh, + extract_vert_idx_ledge_mesh, + extract_vert_idx_lvert_bmesh, + extract_vert_idx_lvert_mesh, + NULL, + 0, + true, +}; static void *extract_select_fdot_idx_init(const MeshRenderData *mr, void *buf) { @@ -3968,18 +4064,20 @@ static void extract_fdot_idx_loop_mesh(const MeshRenderData *mr, ((uint32_t *)data)[p] = (mr->p_origindex) ? mr->p_origindex[p] : p; } -const MeshExtract extract_fdot_idx = {extract_select_fdot_idx_init, - NULL, - NULL, - extract_fdot_idx_loop_bmesh, - extract_fdot_idx_loop_mesh, - NULL, - NULL, - NULL, - NULL, - NULL, - 0, - true}; +static const MeshExtract extract_fdot_idx = { + extract_select_fdot_idx_init, + NULL, + NULL, + extract_fdot_idx_loop_bmesh, + extract_fdot_idx_loop_mesh, + NULL, + NULL, + NULL, + NULL, + NULL, + 0, + true, +}; /** \} */ diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h index d392db63938..3e33346c7d8 100644 --- a/source/blender/draw/intern/draw_cache_impl.h +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -23,18 +23,14 @@ #ifndef __DRAW_CACHE_IMPL_H__ #define __DRAW_CACHE_IMPL_H__ -struct CurveCache; struct GPUBatch; struct GPUIndexBuf; struct GPUMaterial; -struct GPUTexture; struct GPUVertBuf; struct ListBase; struct ModifierData; struct PTCacheEdit; struct ParticleSystem; -struct SpaceImage; -struct ToolSettings; struct Curve; struct Lattice; diff --git a/source/blender/draw/intern/draw_cache_impl_displist.c b/source/blender/draw/intern/draw_cache_impl_displist.c index 90bbf996851..eef108b1f2f 100644 --- a/source/blender/draw/intern/draw_cache_impl_displist.c +++ b/source/blender/draw/intern/draw_cache_impl_displist.c @@ -66,7 +66,7 @@ static int dl_tri_len(const DispList *dl) return 0; } -/* see: displist_get_allverts */ +/* see: displist_vert_coords_alloc */ static int curve_render_surface_vert_len_get(const ListBase *lb) { int vert_len = 0; diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index 12c6a715685..456e21db6ed 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -549,6 +549,7 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode) { GPU_INDEXBUF_DISCARD_SAFE(mbufcache->ibo.lines_paint_mask); GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.pos_nor); + GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.lnor); } GPU_BATCH_DISCARD_SAFE(cache->batch.surface); GPU_BATCH_DISCARD_SAFE(cache->batch.wire_loops); @@ -969,6 +970,7 @@ void DRW_mesh_batch_cache_free_old(Mesh *me, int ctime) void DRW_mesh_batch_cache_create_requested( Object *ob, Mesh *me, const Scene *scene, const bool is_paint_mode, const bool use_hide) { + GPUIndexBuf **saved_elem_ranges = NULL; const ToolSettings *ts = NULL; if (scene) { ts = scene->toolsettings; @@ -1031,6 +1033,17 @@ void DRW_mesh_batch_cache_create_requested( GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.vcol); } } + /* XXX save element buffer to avoid recreating them. + * This is only if the cd_needed changes so it is ok to keep them.*/ + if (cache->surface_per_mat[0] && cache->surface_per_mat[0]->elem) { + saved_elem_ranges = MEM_callocN(sizeof(saved_elem_ranges) * cache->mat_len, __func__); + for (int i = 0; i < cache->mat_len; ++i) { + saved_elem_ranges[i] = cache->surface_per_mat[i]->elem; + /* Avoid deletion as the batch is owner. */ + cache->surface_per_mat[i]->elem = NULL; + cache->surface_per_mat[i]->owns_flag &= ~GPU_BATCH_OWNS_INDEX; + } + } /* We can't discard batches at this point as they have been * referenced for drawing. Just clear them in place. */ for (int i = 0; i < cache->mat_len; ++i) { @@ -1128,6 +1141,8 @@ void DRW_mesh_batch_cache_create_requested( } if (DRW_batch_requested(cache->batch.wire_loops, GPU_PRIM_LINES)) { DRW_ibo_request(cache->batch.wire_loops, &mbufcache->ibo.lines_paint_mask); + /* Order matters. First ones override latest vbos' attribs. */ + DRW_vbo_request(cache->batch.wire_loops, &mbufcache->vbo.lnor); DRW_vbo_request(cache->batch.wire_loops, &mbufcache->vbo.pos_nor); } if (DRW_batch_requested(cache->batch.wire_edges, GPU_PRIM_LINES)) { @@ -1151,7 +1166,13 @@ void DRW_mesh_batch_cache_create_requested( /* Per Material */ for (int i = 0; i < cache->mat_len; ++i) { if (DRW_batch_requested(cache->surface_per_mat[i], GPU_PRIM_TRIS)) { - DRW_ibo_request(cache->surface_per_mat[i], &mbufcache->ibo.tris); + if (saved_elem_ranges && saved_elem_ranges[i]) { + /* XXX assign old element buffer range (it did not change).*/ + GPU_batch_elembuf_set(cache->surface_per_mat[i], saved_elem_ranges[i], true); + } + else { + DRW_ibo_request(cache->surface_per_mat[i], &mbufcache->ibo.tris); + } /* Order matters. First ones override latest vbos' attribs. */ DRW_vbo_request(cache->surface_per_mat[i], &mbufcache->vbo.lnor); DRW_vbo_request(cache->surface_per_mat[i], &mbufcache->vbo.pos_nor); @@ -1170,6 +1191,8 @@ void DRW_mesh_batch_cache_create_requested( } } + MEM_SAFE_FREE(saved_elem_ranges); + mbufcache = (do_cage) ? &cache->cage : &cache->final; /* Edit Mesh */ diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c index e3867eef8d8..2f4a08d4525 100644 --- a/source/blender/draw/intern/draw_common.c +++ b/source/blender/draw/intern/draw_common.c @@ -243,6 +243,7 @@ extern char datatoc_gpu_shader_point_varying_color_frag_glsl[]; extern char datatoc_object_mball_handles_vert_glsl[]; extern char datatoc_object_empty_axes_vert_glsl[]; +extern char datatoc_object_color_axes_vert_glsl[]; typedef struct COMMON_Shaders { struct GPUShader *shape_outline; @@ -262,6 +263,7 @@ typedef struct COMMON_Shaders { struct GPUShader *volume_velocity_needle_sh; struct GPUShader *volume_velocity_sh; struct GPUShader *empty_axes_sh; + struct GPUShader *color_axes_sh; struct GPUShader *mball_handles; } COMMON_Shaders; @@ -549,6 +551,37 @@ struct DRWCallBuffer *buffer_instance_empty_axes(DRWPass *pass, return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_sized, geom); } +struct DRWCallBuffer *buffer_instance_color_axes(DRWPass *pass, + struct GPUBatch *geom, + DRWShadingGroup **r_grp, + eGPUShaderConfig sh_cfg) +{ + COMMON_Shaders *sh_data = &g_shaders[sh_cfg]; + if (sh_data->color_axes_sh == NULL) { + const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg]; + sh_data->color_axes_sh = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, datatoc_object_color_axes_vert_glsl, NULL}, + .frag = (const char *[]){datatoc_gpu_shader_flat_color_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, NULL}, + }); + } + + DRW_shgroup_instance_format(g_formats.instance_sized, + { + {"color", DRW_ATTR_FLOAT, 3}, + {"size", DRW_ATTR_FLOAT, 1}, + {"InstanceModelMatrix", DRW_ATTR_FLOAT, 16}, + }); + + DRWShadingGroup *grp = DRW_shgroup_create(sh_data->color_axes_sh, pass); + DRW_shgroup_uniform_vec3(grp, "screenVecs[0]", DRW_viewport_screenvecs_get(), 2); + if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); + } + *r_grp = grp; + return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_sized, geom); +} + struct DRWCallBuffer *buffer_instance_outline(DRWPass *pass, struct GPUBatch *geom, const int *baseid, diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h index 05d7bafa00d..9899b6c0194 100644 --- a/source/blender/draw/intern/draw_common.h +++ b/source/blender/draw/intern/draw_common.h @@ -30,7 +30,6 @@ struct GPUBatch; struct GPUMaterial; struct ModifierData; struct Object; -struct PTCacheEdit; struct ParticleSystem; struct ViewLayer; @@ -113,7 +112,6 @@ typedef struct GlobalsUboStorage { /* Pack individual float at the end of the buffer to avoid alignment errors */ float sizeLightCenter, sizeLightCircle, sizeLightCircleShadow; float sizeVertex, sizeEdge, sizeEdgeFix, sizeFaceDot; - float gridDistance, gridResolution, gridSubdivisions, gridScale; float pad_globalsBlock; } GlobalsUboStorage; @@ -162,6 +160,10 @@ struct DRWCallBuffer *buffer_instance_screen_aligned(struct DRWPass *pass, struct DRWCallBuffer *buffer_instance_empty_axes(struct DRWPass *pass, struct GPUBatch *geom, eGPUShaderConfig sh_cfg); +struct DRWCallBuffer *buffer_instance_color_axes(struct DRWPass *pass, + struct GPUBatch *geom, + struct DRWShadingGroup **r_grp, + eGPUShaderConfig sh_cfg); struct DRWCallBuffer *buffer_instance_scaled(struct DRWPass *pass, struct GPUBatch *geom, eGPUShaderConfig sh_cfg); diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c index fa1f1f2aab4..44ed01c47aa 100644 --- a/source/blender/draw/intern/draw_hair.c +++ b/source/blender/draw/intern/draw_hair.c @@ -253,7 +253,7 @@ void DRW_hair_update(void) * On some system it crashes (see T58489) and on some other it renders garbage (see T60171). * * So instead of using transform feedback we render to a texture, - * readback the result to system memory and reupload as VBO data. + * read back the result to system memory and re-upload as VBO data. * It is really not ideal performance wise, but it is the simplest * and the most local workaround that still uses the power of the GPU. */ diff --git a/source/blender/draw/intern/draw_instance_data.c b/source/blender/draw/intern/draw_instance_data.c index 802f49d6549..8f26cc72a02 100644 --- a/source/blender/draw/intern/draw_instance_data.c +++ b/source/blender/draw/intern/draw_instance_data.c @@ -23,7 +23,7 @@ /** * DRW Instance Data Manager * This is a special memory manager that keeps memory blocks ready to send as vbo data in one - * continuous allocation. This way we avoid feeding gawain each instance data one by one and + * continuous allocation. This way we avoid feeding #GPUBatch each instance data one by one and * unnecessary memcpy. Since we loose which memory block was used each #DRWShadingGroup we need to * redistribute them in the same order/size to avoid to realloc each frame. This is why * #DRWInstanceDatas are sorted in a list for each different data size. diff --git a/source/blender/draw/intern/draw_instance_data.h b/source/blender/draw/intern/draw_instance_data.h index d88de1a58e2..2ede68e16d8 100644 --- a/source/blender/draw/intern/draw_instance_data.h +++ b/source/blender/draw/intern/draw_instance_data.h @@ -35,8 +35,6 @@ typedef struct DRWInstanceData DRWInstanceData; typedef struct DRWInstanceDataList DRWInstanceDataList; -struct DRWShadingGroup; - void *DRW_instance_data_next(DRWInstanceData *idata); DRWInstanceData *DRW_instance_data_request(DRWInstanceDataList *idatalist, uint attr_size); diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index ebbe3694df8..d88629e9bb7 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -33,6 +33,7 @@ #include "BKE_anim.h" #include "BKE_colortools.h" +#include "BKE_context.h" #include "BKE_curve.h" #include "BKE_editmesh.h" #include "BKE_global.h" @@ -41,6 +42,7 @@ #include "BKE_main.h" #include "BKE_mball.h" #include "BKE_mesh.h" +#include "BKE_modifier.h" #include "BKE_object.h" #include "BKE_particle.h" #include "BKE_paint.h" @@ -604,6 +606,7 @@ static DRWCallState *draw_unit_state_create(void) state->ob_index = 0; state->ob_random = 0.0f; + copy_v3_fl(state->ob_color, 1.0f); /* TODO(fclem) get rid of this. */ state->culling = BLI_memblock_alloc(DST.vmempool->cullstates); @@ -1865,7 +1868,7 @@ void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph DRW_opengl_render_context_enable(re_gl_context); /* We need to query gpu context after a gl context has been bound. */ re_gpu_context = RE_gpu_context_get(render); - DRW_gawain_render_context_enable(re_gpu_context); + DRW_gpu_render_context_enable(re_gpu_context); } else { DRW_opengl_context_enable(); @@ -1950,13 +1953,13 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph) DRW_opengl_render_context_enable(re_gl_context); /* We need to query gpu context after a gl context has been bound. */ re_gpu_context = RE_gpu_context_get(render); - DRW_gawain_render_context_enable(re_gpu_context); + DRW_gpu_render_context_enable(re_gpu_context); } else { DRW_opengl_context_enable(); } - /* IMPORTANT: We dont support immediate mode in render mode! + /* IMPORTANT: We don't support immediate mode in render mode! * This shall remain in effect until immediate mode supports * multiple threads. */ @@ -2041,7 +2044,7 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph) /* Changing Context */ if (re_gl_context != NULL) { - DRW_gawain_render_context_disable(re_gpu_context); + DRW_gpu_render_context_disable(re_gpu_context); DRW_opengl_render_context_disable(re_gl_context); } else { @@ -2204,24 +2207,43 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, drw_state_prepare_clean_for_draw(&DST); bool use_obedit = false; - int obedit_mode = 0; + /* obedit_ctx_mode is used for selecting the right draw engines */ + eContextObjectMode obedit_ctx_mode; + /* object_mode is used for filtering objects in the depsgraph */ + eObjectMode object_mode; + int object_type = 0; if (obedit != NULL) { + object_type = obedit->type; + object_mode = obedit->mode; if (obedit->type == OB_MBALL) { use_obedit = true; - obedit_mode = CTX_MODE_EDIT_METABALL; + obedit_ctx_mode = CTX_MODE_EDIT_METABALL; } else if (obedit->type == OB_ARMATURE) { use_obedit = true; - obedit_mode = CTX_MODE_EDIT_ARMATURE; + obedit_ctx_mode = CTX_MODE_EDIT_ARMATURE; } } if (v3d->overlay.flag & V3D_OVERLAY_BONE_SELECT) { if (!(v3d->flag2 & V3D_HIDE_OVERLAYS)) { /* Note: don't use "BKE_object_pose_armature_get" here, it breaks selection. */ Object *obpose = OBPOSE_FROM_OBACT(obact); + if (obpose == NULL) { + Object *obweight = OBWEIGHTPAINT_FROM_OBACT(obact); + if (obweight) { + /* Only use Armature pose selection, when connected armature is in pose mode. */ + Object *ob_armature = modifiers_isDeformedByArmature(obweight); + if (ob_armature && ob_armature->mode == OB_MODE_POSE) { + obpose = ob_armature; + } + } + } + if (obpose) { use_obedit = true; - obedit_mode = CTX_MODE_POSE; + object_type = obpose->type; + object_mode = obpose->mode; + obedit_ctx_mode = CTX_MODE_POSE; } } } @@ -2235,8 +2257,8 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, /* Get list of enabled engines */ if (use_obedit) { - drw_engines_enable_from_paint_mode(obedit_mode); - drw_engines_enable_from_mode(obedit_mode); + drw_engines_enable_from_paint_mode(obedit_ctx_mode); + drw_engines_enable_from_mode(obedit_ctx_mode); } else if (!draw_surface) { /* grease pencil selection */ @@ -2283,7 +2305,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, drw_engines_world_update(scene); if (use_obedit) { - FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, obact->type, obact->mode, ob_iter) { + FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, object_type, object_mode, ob_iter) { drw_engines_cache_populate(ob_iter); } FOREACH_OBJECT_IN_MODE_END; @@ -2563,7 +2585,6 @@ void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *ar, View3D *v3d, const rc /* Reset before using it. */ drw_state_prepare_clean_for_draw(&DST); - DST.buffer_finish_called = true; /* Instead of 'DRW_context_state_init(C, &DST.draw_ctx)', assign from args */ DST.draw_ctx = (DRWContextState){ @@ -2601,6 +2622,8 @@ void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *ar, View3D *v3d, const rc } drw_engines_cache_finish(); + + DRW_render_instance_buffer_finish(); } /* Start Drawing */ @@ -2610,6 +2633,8 @@ void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *ar, View3D *v3d, const rc drw_engines_disable(); + drw_viewport_cache_resize(); + #ifdef DEBUG /* Avoid accidental reuse. */ drw_state_ensure_not_reused(&DST); @@ -2923,7 +2948,7 @@ void DRW_opengl_context_create(void) /* This changes the active context. */ DST.gl_context = WM_opengl_context_create(); WM_opengl_context_activate(DST.gl_context); - /* Be sure to create gawain.context too. */ + /* Be sure to create gpu_context too. */ DST.gpu_context = GPU_context_create(0); if (!G.background) { immActivate(); @@ -3022,7 +3047,7 @@ void DRW_opengl_render_context_disable(void *re_gl_context) } /* Needs to be called AFTER DRW_opengl_render_context_enable() */ -void DRW_gawain_render_context_enable(void *re_gpu_context) +void DRW_gpu_render_context_enable(void *re_gpu_context) { /* If thread is main you should use DRW_opengl_context_enable(). */ BLI_assert(!BLI_thread_is_main()); @@ -3032,7 +3057,7 @@ void DRW_gawain_render_context_enable(void *re_gpu_context) } /* Needs to be called BEFORE DRW_opengl_render_context_disable() */ -void DRW_gawain_render_context_disable(void *UNUSED(re_gpu_context)) +void DRW_gpu_render_context_disable(void *UNUSED(re_gpu_context)) { DRW_shape_cache_reset(); /* XXX fix that too. */ GPU_context_active_set(NULL); diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h index f37e713e374..85f6cf05e83 100644 --- a/source/blender/draw/intern/draw_manager.h +++ b/source/blender/draw/intern/draw_manager.h @@ -101,6 +101,7 @@ enum { DRW_CALL_MODELVIEWPROJECTION = (1 << 1), DRW_CALL_ORCOTEXFAC = (1 << 2), DRW_CALL_OBJECTINFO = (1 << 3), + DRW_CALL_OBJECTCOLOR = (1 << 4), }; typedef struct DRWCullingState { @@ -122,6 +123,7 @@ typedef struct DRWCallState { float modelinverse[4][4]; float orcotexfac[2][3]; float ob_random; + float ob_color[4]; } DRWCallState; typedef struct DRWCall { @@ -196,6 +198,7 @@ struct DRWShadingGroup { int orcotexfac; int callid; int objectinfo; + int objectcolor; uchar matflag; /* Matrices needed, same as DRWCall.flag */ DRWPass *pass_parent; /* backlink to pass we're in */ diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c index 99ab25645d2..8b7cb9c1dad 100644 --- a/source/blender/draw/intern/draw_manager_data.c +++ b/source/blender/draw/intern/draw_manager_data.c @@ -387,6 +387,10 @@ static void drw_call_state_update_matflag(DRWCallState *state, } state->ob_random = random * (1.0f / (float)0xFFFFFFFF); } + + if (new_flags & DRW_CALL_OBJECTCOLOR) { + copy_v4_v4(state->ob_color, ob->color); + } } static DRWCallState *drw_call_state_create(DRWShadingGroup *shgroup, float (*obmat)[4], Object *ob) @@ -836,6 +840,7 @@ static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader) shgroup->modelviewprojection = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MVP); shgroup->orcotexfac = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_ORCO); shgroup->objectinfo = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_OBJECT_INFO); + shgroup->objectcolor = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_OBJECT_COLOR); shgroup->callid = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_CALLID); shgroup->matflag = 0; @@ -851,6 +856,9 @@ static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader) if (shgroup->objectinfo > -1) { shgroup->matflag |= DRW_CALL_OBJECTINFO; } + if (shgroup->objectcolor > -1) { + shgroup->matflag |= DRW_CALL_OBJECTCOLOR; + } } static DRWShadingGroup *drw_shgroup_create_ex(struct GPUShader *shader, DRWPass *pass) diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c index 3bf442b4f39..50408015fbc 100644 --- a/source/blender/draw/intern/draw_manager_exec.c +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -592,6 +592,10 @@ static void draw_geometry_prepare(DRWShadingGroup *shgroup, DRWCall *call) infos[3] = (state->flag & DRW_CALL_NEGSCALE) ? -1.0f : 1.0f; GPU_shader_uniform_vector(shgroup->shader, shgroup->objectinfo, 4, 1, (float *)infos); } + if (shgroup->objectcolor != -1) { + GPU_shader_uniform_vector( + shgroup->shader, shgroup->objectcolor, 4, 1, (float *)state->ob_color); + } if (shgroup->orcotexfac != -1) { GPU_shader_uniform_vector( shgroup->shader, shgroup->orcotexfac, 3, 2, (float *)state->orcotexfac); @@ -622,12 +626,12 @@ BLI_INLINE void draw_geometry_execute(DRWShadingGroup *shgroup, GPU_batch_bind(geom); } - /* XXX hacking gawain. we don't want to call glUseProgram! (huge performance loss) */ + /* XXX hacking #GPUBatch. we don't want to call glUseProgram! (huge performance loss) */ geom->program_in_use = true; GPU_batch_draw_advanced(geom, vert_first, vert_count, inst_first, inst_count); - geom->program_in_use = false; /* XXX hacking gawain */ + geom->program_in_use = false; /* XXX hacking #GPUBatch */ } enum { diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c index d0aa6d55c03..9c34cdbac3b 100644 --- a/source/blender/draw/intern/draw_manager_shader.c +++ b/source/blender/draw/intern/draw_manager_shader.c @@ -178,7 +178,7 @@ static void drw_deferred_shader_compilation_free(void *custom_data) static void drw_deferred_shader_add(GPUMaterial *mat, bool deferred) { - /* Do not deferre the compilation if we are rendering for image. + /* Do not defer the compilation if we are rendering for image. * deferred rendering is only possible when `evil_C` is available */ if (DST.draw_ctx.evil_C == NULL || DRW_state_is_image_render() || !USE_DEFERRED_COMPILATION || !deferred) { diff --git a/source/blender/draw/intern/draw_select_buffer.c b/source/blender/draw/intern/draw_select_buffer.c index 974ea22ccea..6454fc71e56 100644 --- a/source/blender/draw/intern/draw_select_buffer.c +++ b/source/blender/draw/intern/draw_select_buffer.c @@ -75,14 +75,15 @@ uint *DRW_select_buffer_read(struct Depsgraph *depsgraph, DRW_draw_select_id(depsgraph, ar, v3d, rect); if (select_ctx->index_drawn_len > 1) { - BLI_assert(ar->winx == GPU_texture_width(select_ctx->texture_u32) && - ar->winy == GPU_texture_height(select_ctx->texture_u32)); + BLI_assert(ar->winx == GPU_texture_width(DRW_engine_select_texture_get()) && + ar->winy == GPU_texture_height(DRW_engine_select_texture_get())); /* Read the UI32 pixels. */ buf_len = BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect); r_buf = MEM_mallocN(buf_len * sizeof(*r_buf), __func__); - GPU_framebuffer_bind(select_ctx->framebuffer_select_id); + GPUFrameBuffer *select_id_fb = DRW_engine_select_framebuffer_get(); + GPU_framebuffer_bind(select_id_fb); glReadBuffer(GL_COLOR_ATTACHMENT0); glReadPixels(rect_clamp.xmin, rect_clamp.ymin, diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c index 87fc74f1f72..716372560db 100644 --- a/source/blender/draw/modes/object_mode.c +++ b/source/blender/draw/modes/object_mode.c @@ -234,6 +234,7 @@ typedef struct OBJECT_ShadingGroupList { /* Helpers */ DRWCallBuffer *relationship_lines; DRWCallBuffer *constraint_lines; + DRWCallBuffer *origin_xform; /* Camera */ DRWCallBuffer *camera; @@ -332,7 +333,7 @@ static struct { OBJECT_Shaders sh_data[GPU_SHADER_CFG_LEN]; - float grid_settings[5]; + float grid_distance; float grid_mesh_size; int grid_flag; float grid_axes[3]; @@ -340,6 +341,7 @@ static struct { int zneg_flag; float zplane_axes[3]; float inv_viewport_size[2]; + float grid_steps[8]; bool draw_grid; /* Temp buffer textures */ struct GPUTexture *outlines_depth_tx; @@ -559,8 +561,6 @@ static void OBJECT_engine_init(void *vedata) View3D *v3d = draw_ctx->v3d; Scene *scene = draw_ctx->scene; RegionView3D *rv3d = draw_ctx->rv3d; - float grid_scale = ED_view3d_grid_scale(scene, v3d, NULL); - float grid_res; const bool show_axis_x = (v3d->gridflag & V3D_SHOW_X) != 0; const bool show_axis_y = (v3d->gridflag & V3D_SHOW_Y) != 0; @@ -576,21 +576,6 @@ static void OBJECT_engine_init(void *vedata) /* if perps */ if (winmat[3][3] == 0.0f) { - float fov; - float viewvecs[2][4] = { - {1.0f, -1.0f, -1.0f, 1.0f}, - {-1.0f, 1.0f, -1.0f, 1.0f}, - }; - - /* convert the view vectors to view space */ - for (int i = 0; i < 2; i++) { - mul_m4_v4(wininv, viewvecs[i]); - mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]); /* perspective divide */ - } - - fov = angle_v3v3(viewvecs[0], viewvecs[1]) / 2.0f; - grid_res = fabsf(tanf(fov)) / grid_scale; - e_data.grid_flag = (1 << 4); /* XY plane */ if (show_axis_x) { e_data.grid_flag |= SHOW_AXIS_X; @@ -603,14 +588,6 @@ static void OBJECT_engine_init(void *vedata) } } else { - if (rv3d->view != RV3D_VIEW_USER) { - /* Allow 3 more subdivisions. */ - grid_scale /= powf(v3d->gridsubdiv, 3); - } - - float viewdist = 1.0f / max_ff(fabsf(winmat[0][0]), fabsf(winmat[1][1])); - grid_res = viewdist / grid_scale; - if (ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT)) { e_data.draw_grid = show_ortho_grid; e_data.grid_flag = PLANE_YZ | SHOW_AXIS_Y | SHOW_AXIS_Z | SHOW_GRID | GRID_BACK; @@ -688,12 +665,7 @@ static void OBJECT_engine_init(void *vedata) dist = v3d->clip_end; } - e_data.grid_settings[0] = dist / 2.0f; /* gridDistance */ - e_data.grid_settings[1] = grid_res; /* gridResolution */ - e_data.grid_settings[2] = grid_scale; /* gridScale */ - e_data.grid_settings[3] = v3d->gridsubdiv; /* gridSubdiv */ - e_data.grid_settings[4] = (v3d->gridsubdiv > 1) ? 1.0f / logf(v3d->gridsubdiv) : - 0.0f; /* 1/log(gridSubdiv) */ + e_data.grid_distance = dist / 2.0f; /* gridDistance */ if (winmat[3][3] == 0.0f) { e_data.grid_mesh_size = dist; @@ -702,6 +674,8 @@ static void OBJECT_engine_init(void *vedata) float viewdist = 1.0f / min_ff(fabsf(winmat[0][0]), fabsf(winmat[1][1])); e_data.grid_mesh_size = viewdist * dist; } + + ED_view3d_grid_steps(scene, v3d, rv3d, e_data.grid_steps); } copy_v2_v2(e_data.inv_viewport_size, DRW_viewport_size_get()); @@ -1512,10 +1486,10 @@ static void OBJECT_cache_init(void *vedata) DRWShadingGroup *grp = DRW_shgroup_create(sh_data->grid, psl->grid); DRW_shgroup_uniform_int(grp, "gridFlag", &e_data.zneg_flag, 1); DRW_shgroup_uniform_vec3(grp, "planeAxes", e_data.zplane_axes, 1); - DRW_shgroup_uniform_vec4(grp, "gridSettings", e_data.grid_settings, 1); + DRW_shgroup_uniform_vec3(grp, "screenVecs[0]", DRW_viewport_screenvecs_get(), 2); + DRW_shgroup_uniform_float(grp, "gridDistance", &e_data.grid_distance, 1); DRW_shgroup_uniform_float_copy(grp, "lineKernel", grid_line_size); DRW_shgroup_uniform_float_copy(grp, "meshSize", e_data.grid_mesh_size); - DRW_shgroup_uniform_float(grp, "gridOneOverLogSubdiv", &e_data.grid_settings[4], 1); DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); DRW_shgroup_call(grp, geom, NULL); @@ -1525,6 +1499,7 @@ static void OBJECT_cache_init(void *vedata) DRW_shgroup_uniform_vec3(grp, "planeAxes", e_data.grid_axes, 1); DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); + DRW_shgroup_uniform_float(grp, "gridSteps", e_data.grid_steps, ARRAY_SIZE(e_data.grid_steps)); DRW_shgroup_call(grp, geom, NULL); grp = DRW_shgroup_create(sh_data->grid, psl->grid); @@ -1761,6 +1736,16 @@ static void OBJECT_cache_init(void *vedata) sgl->constraint_lines = buffer_dynlines_dashed_uniform_color( sgl->non_meshes, gb->colorGridAxisZ, draw_ctx->sh_cfg); + { + DRWShadingGroup *grp_axes; + sgl->origin_xform = buffer_instance_color_axes( + sgl->non_meshes, DRW_cache_bone_arrows_get(), &grp_axes, draw_ctx->sh_cfg); + + DRW_shgroup_state_disable(grp_axes, DRW_STATE_DEPTH_LESS_EQUAL); + DRW_shgroup_state_enable(grp_axes, DRW_STATE_DEPTH_ALWAYS); + DRW_shgroup_state_enable(grp_axes, DRW_STATE_WIRE_SMOOTH); + } + /* Force Field Curve Guide End (here because of stipple) */ /* TODO port to shader stipple */ geom = DRW_cache_screenspace_circle_get(); @@ -3701,6 +3686,15 @@ static void OBJECT_cache_populate(void *vedata, Object *ob) DRW_shgroup_bounds(sgl, ob, theme_id); } + /* Helpers for when we're transforming origins. */ + if (scene->toolsettings->transform_flag & SCE_XFORM_DATA_ORIGIN) { + if (ob->base_flag & BASE_SELECTED) { + const float color[4] = {0.75, 0.75, 0.75, 0.5}; + float axes_size = 1.0f; + DRW_buffer_add_entry(sgl->origin_xform, color, &axes_size, ob->obmat); + } + } + /* don't show object extras in set's */ if ((ob->base_flag & (BASE_FROM_SET | BASE_FROM_DUPLI)) == 0) { if ((draw_ctx->object_mode & (OB_MODE_ALL_PAINT | OB_MODE_ALL_PAINT_GPENCIL)) == 0) { @@ -3711,7 +3705,7 @@ static void OBJECT_cache_populate(void *vedata, Object *ob) DRW_shgroup_relationship_lines(sgl, draw_ctx->depsgraph, scene, ob); } - const bool draw_extra = (ob->dtx != 0); + const bool draw_extra = ob->dtx & (OB_DRAWNAME | OB_TEXSPACE | OB_DRAWBOUNDOX); if (draw_extra && (theme_id == TH_UNDEFINED)) { theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); } diff --git a/source/blender/draw/modes/shaders/common_globals_lib.glsl b/source/blender/draw/modes/shaders/common_globals_lib.glsl index f75ef06b6d9..e559224eb9e 100644 --- a/source/blender/draw/modes/shaders/common_globals_lib.glsl +++ b/source/blender/draw/modes/shaders/common_globals_lib.glsl @@ -75,11 +75,6 @@ layout(std140) uniform globalsBlock float sizeEdgeFix; float sizeFaceDot; - float gridDistance; - float gridResolution; - float gridSubdivisions; - float gridScale; - float pad_globalsBlock; }; diff --git a/source/blender/draw/modes/shaders/object_color_axes_vert.glsl b/source/blender/draw/modes/shaders/object_color_axes_vert.glsl new file mode 100644 index 00000000000..239dec30c42 --- /dev/null +++ b/source/blender/draw/modes/shaders/object_color_axes_vert.glsl @@ -0,0 +1,35 @@ + +uniform mat4 ViewProjectionMatrix; +uniform vec3 screenVecs[3]; + +/* ---- Instantiated Attrs ---- */ +in float axis; /* position on the axis. [0.0-1.0] is X axis, [1.0-2.0] is Y, etc... */ +in vec2 screenPos; +in vec3 colorAxis; + +/* ---- Per instance Attrs ---- */ +in mat4 InstanceModelMatrix; +in vec4 color; + +flat out vec4 finalColor; + +void main() +{ + float draw_size = 4.0; + vec3 chosen_axis = InstanceModelMatrix[int(axis)].xyz; + vec3 loc = InstanceModelMatrix[3].xyz; + vec3 wpos = loc + chosen_axis * fract(axis) * draw_size; + vec3 spos = screenVecs[0].xyz * screenPos.x + screenVecs[1].xyz * screenPos.y; + /* Scale uniformly by axis length */ + spos *= length(chosen_axis) * draw_size; + + vec4 pos_4d = vec4(wpos + spos, 1.0); + gl_Position = ViewProjectionMatrix * pos_4d; + + finalColor.rgb = mix(colorAxis, color.rgb, color.a); + finalColor.a = 1.0; + +#ifdef USE_WORLD_CLIP_PLANES + world_clip_planes_calc_clip_distance(pos_4d.xyz); +#endif +} diff --git a/source/blender/draw/modes/shaders/object_empty_image_frag.glsl b/source/blender/draw/modes/shaders/object_empty_image_frag.glsl index 7dfbf469adc..e33aa6cdcc1 100644 --- a/source/blender/draw/modes/shaders/object_empty_image_frag.glsl +++ b/source/blender/draw/modes/shaders/object_empty_image_frag.glsl @@ -37,9 +37,15 @@ void main() if (depthMode == DEPTH_BACK) { gl_FragDepth = 0.999999; +#ifdef USE_WIRE + gl_FragDepth -= 1e-5; +#endif } else if (depthMode == DEPTH_FRONT) { gl_FragDepth = 0.000001; +#ifdef USE_WIRE + gl_FragDepth -= 1e-5; +#endif } else if (depthMode == DEPTH_UNCHANGED) { gl_FragDepth = gl_FragCoord.z; diff --git a/source/blender/draw/modes/shaders/object_grid_frag.glsl b/source/blender/draw/modes/shaders/object_grid_frag.glsl index a20f12efd93..751d839eb79 100644 --- a/source/blender/draw/modes/shaders/object_grid_frag.glsl +++ b/source/blender/draw/modes/shaders/object_grid_frag.glsl @@ -9,21 +9,19 @@ in vec3 local_pos; out vec4 FragColor; uniform vec3 planeAxes; -uniform vec4 gridSettings; +uniform vec3 screenVecs[2]; +uniform float gridDistance; uniform float meshSize; uniform float lineKernel = 0.0; -uniform float gridOneOverLogSubdiv; uniform sampler2D depthBuffer; -#define gridDistance gridSettings.x -#define gridResolution gridSettings.y -#define gridScale gridSettings.z -#define gridSubdiv gridSettings.w - #define cameraPos (ViewMatrixInverse[3].xyz) uniform int gridFlag; +#define STEPS_LEN 8 +uniform float gridSteps[STEPS_LEN] = float[](0.001, 0.01, 0.1, 1.0, 10.0, 100.0, 1000.0, 10000.0); + #define AXIS_X (1 << 0) #define AXIS_Y (1 << 1) #define AXIS_Z (1 << 2) @@ -73,10 +71,14 @@ vec3 get_axes(vec3 co, vec3 fwidthCos, float line_size) axes_domain - (line_size + lineKernel)); } +#define linearstep(p0, p1, v) (clamp(((v) - (p0)) / abs((p1) - (p0)), 0.0, 1.0)) + void main() { vec3 wPos = local_pos * meshSize; - vec3 fwidthPos = fwidth(wPos); + vec3 dFdxPos = dFdx(wPos); + vec3 dFdyPos = dFdy(wPos); + vec3 fwidthPos = abs(dFdxPos) + abs(dFdyPos); wPos += cameraPos * planeAxes; float dist, fade; @@ -116,15 +118,54 @@ void main() } if ((gridFlag & GRID) != 0) { - float grid_res = log(dist * gridResolution) * gridOneOverLogSubdiv; + /* Using `max(dot(dFdxPos, screenVecs[0]), dot(dFdyPos, screenVecs[1]))` + * would be more accurate, but not really necessary. */ + float grid_res = dot(dFdxPos, screenVecs[0]); - float blend = fract(-max(grid_res, 0.0)); - float lvl = floor(grid_res); + /* The gride begins to appear when it comprises 4 pixels */ + grid_res *= 4; /* from biggest to smallest */ - float scaleA = gridScale * pow(gridSubdiv, max(lvl - 1.0, 0.0)); - float scaleB = gridScale * pow(gridSubdiv, max(lvl + 0.0, 0.0)); - float scaleC = gridScale * pow(gridSubdiv, max(lvl + 1.0, 1.0)); + vec4 scale; +#if 0 + int step_id = 0; + scale[0] = 0.0; + scale[1] = gridSteps[0]; + while (scale[1] < grid_res && step_id != STEPS_LEN - 1) { + scale[0] = scale[1]; + scale[1] = gridSteps[++step_id]; + } + scale[2] = gridSteps[min(step_id + 1, STEPS_LEN - 1)]; + scale[3] = gridSteps[min(step_id + 2, STEPS_LEN - 1)]; +#else + /* For more efficiency, unroll the loop above. */ + if (gridSteps[0] > grid_res) { + scale = vec4(0.0, gridSteps[0], gridSteps[1], gridSteps[2]); + } + else if (gridSteps[1] > grid_res) { + scale = vec4(gridSteps[0], gridSteps[1], gridSteps[2], gridSteps[3]); + } + else if (gridSteps[2] > grid_res) { + scale = vec4(gridSteps[1], gridSteps[2], gridSteps[3], gridSteps[4]); + } + else if (gridSteps[3] > grid_res) { + scale = vec4(gridSteps[2], gridSteps[3], gridSteps[4], gridSteps[5]); + } + else if (gridSteps[4] > grid_res) { + scale = vec4(gridSteps[3], gridSteps[4], gridSteps[5], gridSteps[6]); + } + else if (gridSteps[5] > grid_res) { + scale = vec4(gridSteps[4], gridSteps[5], gridSteps[6], gridSteps[7]); + } + else if (gridSteps[6] > grid_res) { + scale = vec4(gridSteps[5], gridSteps[6], gridSteps[7], gridSteps[7]); + } + else { + scale = vec4(gridSteps[6], gridSteps[7], gridSteps[7], gridSteps[7]); + } +#endif + float blend = 1.0 - linearstep(scale[0], scale[1], grid_res); + blend = blend * blend * blend; vec2 grid_pos, grid_fwidth; if ((gridFlag & PLANE_XZ) != 0) { @@ -140,9 +181,9 @@ void main() grid_fwidth = fwidthPos.xy; } - float gridA = get_grid(grid_pos, grid_fwidth, scaleA); - float gridB = get_grid(grid_pos, grid_fwidth, scaleB); - float gridC = get_grid(grid_pos, grid_fwidth, scaleC); + float gridA = get_grid(grid_pos, grid_fwidth, scale[1]); + float gridB = get_grid(grid_pos, grid_fwidth, scale[2]); + float gridC = get_grid(grid_pos, grid_fwidth, scale[3]); FragColor = colorGrid; FragColor.a *= gridA * blend; diff --git a/source/blender/draw/modes/shaders/object_grid_vert.glsl b/source/blender/draw/modes/shaders/object_grid_vert.glsl index d247967b03a..496bb011c74 100644 --- a/source/blender/draw/modes/shaders/object_grid_vert.glsl +++ b/source/blender/draw/modes/shaders/object_grid_vert.glsl @@ -3,14 +3,8 @@ * Clément Foucault */ uniform vec3 planeAxes; -uniform vec4 gridSettings; uniform float meshSize; -#define gridDistance gridSettings.x -#define gridResolution gridSettings.y -#define gridScale gridSettings.z -#define gridSubdiv gridSettings.w - uniform int gridFlag; #define cameraPos (ViewMatrixInverse[3].xyz) diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 1649744ba8d..d80b96f0d74 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -4847,7 +4847,7 @@ void ANIM_channel_draw_widgets(const bContext *C, /* step 4) draw text - check if renaming widget is in use... */ if (is_being_renamed) { - PointerRNA ptr = {{NULL}}; + PointerRNA ptr = {NULL}; PropertyRNA *prop = NULL; /* draw renaming widget if we can get RNA pointer for it diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 7e913014a87..61b8e4a2341 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -3114,6 +3114,7 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index, ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, gpl, ANIMTYPE_GPLAYER); /* update other layer status */ BKE_gpencil_layer_setactive(gpd, gpl); + BKE_gpencil_layer_autolock_set(gpd); } /* Grease Pencil updates */ diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index a78a63f1347..48493c9e961 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -630,9 +630,8 @@ static bAnimListElem *make_new_animlistelem(void *data, /* do specifics */ switch (datatype) { case ANIMTYPE_SUMMARY: { - /* nothing to include for now... this is just a dummy wrappy around all the other channels - * in the DopeSheet, and gets included at the start of the list - */ + /* Nothing to include for now... this is just a dummy wrapper around + * all the other channels in the DopeSheet, and gets included at the start of the list. */ ale->key_data = NULL; ale->datatype = ALE_ALL; break; diff --git a/source/blender/editors/animation/anim_ipo_utils.c b/source/blender/editors/animation/anim_ipo_utils.c index fad9a1a8e49..5b729c856c0 100644 --- a/source/blender/editors/animation/anim_ipo_utils.c +++ b/source/blender/editors/animation/anim_ipo_utils.c @@ -122,7 +122,7 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu) MEM_freeN(constName); } } - else if (ptr.data != ptr.id.data) { + else if (ptr.data != ptr.owner_id) { PropertyRNA *nameprop = RNA_struct_name_property(ptr.type); if (nameprop) { /* this gets a string which will need to be freed */ diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index ded59466370..8c873eb6b45 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -486,7 +486,7 @@ static void draw_marker( float name_y = UI_DPI_FAC * 18; /* Give an offset to the marker name when selected, * or when near the current frame (5 frames range, starting from the current one). */ - if ((marker->flag & SELECT) || (IN_RANGE_INCL(marker->frame, cfra, cfra - 4))) { + if ((marker->flag & SELECT) || (IN_RANGE_INCL(marker->frame, cfra - 4, cfra))) { name_y += UI_DPI_FAC * 10; } draw_marker_name(fstyle, marker, xpos, name_y); diff --git a/source/blender/editors/animation/anim_motion_paths.c b/source/blender/editors/animation/anim_motion_paths.c index 7a5b57b1ce6..bd4886817cd 100644 --- a/source/blender/editors/animation/anim_motion_paths.c +++ b/source/blender/editors/animation/anim_motion_paths.c @@ -60,9 +60,8 @@ typedef struct MPathTarget { Object *ob; /* source object */ bPoseChannel *pchan; /* source posechannel (if applicable) */ - /* "Evaluated" Copies (these come from the background COW copie - * that provide all the coordinates we want to save off) - */ + /* "Evaluated" Copies (these come from the background COW copy + * that provide all the coordinates we want to save off). */ Object *ob_eval; /* evaluated object */ } MPathTarget; diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c index 935d11a388f..7b9e6a10f44 100644 --- a/source/blender/editors/animation/drivers.c +++ b/source/blender/editors/animation/drivers.c @@ -218,7 +218,7 @@ static int add_driver_with_target(ReportList *UNUSED(reports), /* Create a driver variable for the target * - For transform properties, we want to automatically use "transform channel" instead - * (The only issue is with quat rotations vs euler channels...) + * (The only issue is with quaternion rotations vs euler channels...) * - To avoid problems with transform properties depending on the final transform that they * control (thus creating pseudo-cycles - see T48734), we don't use transform channels * when both the source and destinations are in same places. @@ -934,7 +934,7 @@ static const EnumPropertyItem *driver_mapping_type_itemsf(bContext *C, EnumPropertyItem *input = prop_driver_create_mapping_types; EnumPropertyItem *item = NULL; - PointerRNA ptr = {{NULL}}; + PointerRNA ptr = {NULL}; PropertyRNA *prop = NULL; int index; @@ -946,7 +946,7 @@ static const EnumPropertyItem *driver_mapping_type_itemsf(bContext *C, UI_context_active_but_prop_get(C, &ptr, &prop, &index); - if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { + if (ptr.owner_id && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { const bool is_array = RNA_property_array_check(prop); while (input->identifier) { @@ -971,7 +971,7 @@ static const EnumPropertyItem *driver_mapping_type_itemsf(bContext *C, static bool add_driver_button_poll(bContext *C) { - PointerRNA ptr = {{NULL}}; + PointerRNA ptr = {NULL}; PropertyRNA *prop = NULL; int index; bool driven, special; @@ -979,7 +979,7 @@ static bool add_driver_button_poll(bContext *C) /* this operator can only run if there's a property button active, and it can be animated */ UI_context_active_but_prop_get(C, &ptr, &prop, &index); - if (!(ptr.id.data && ptr.data && prop)) { + if (!(ptr.owner_id && ptr.data && prop)) { return false; } if (!RNA_property_animateable(&ptr, prop)) { @@ -995,7 +995,7 @@ static bool add_driver_button_poll(bContext *C) * (i.e. "manual/add later"). */ static int add_driver_button_none(bContext *C, wmOperator *op, short mapping_type) { - PointerRNA ptr = {{NULL}}; + PointerRNA ptr = {NULL}; PropertyRNA *prop = NULL; int index; int success = 0; @@ -1006,12 +1006,13 @@ static int add_driver_button_none(bContext *C, wmOperator *op, short mapping_typ index = -1; } - if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { + if (ptr.owner_id && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL); short flags = CREATEDRIVER_WITH_DEFAULT_DVAR; if (path) { - success += ANIM_add_driver(op->reports, ptr.id.data, path, index, flags, DRIVER_TYPE_PYTHON); + success += ANIM_add_driver( + op->reports, ptr.owner_id, path, index, flags, DRIVER_TYPE_PYTHON); MEM_freeN(path); } } @@ -1095,28 +1096,29 @@ static void UNUSED_FUNCTION(ANIM_OT_driver_button_add_menu)(wmOperatorType *ot) static int add_driver_button_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - PointerRNA ptr = {{NULL}}; + PointerRNA ptr = {NULL}; PropertyRNA *prop = NULL; int index; /* try to find driver using property retrieved from UI */ UI_context_active_but_prop_get(C, &ptr, &prop, &index); - if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { + if (ptr.owner_id && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { /* 1) Create a new "empty" driver for this property */ char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL); short flags = CREATEDRIVER_WITH_DEFAULT_DVAR; short success = 0; if (path) { - success += ANIM_add_driver(op->reports, ptr.id.data, path, index, flags, DRIVER_TYPE_PYTHON); + success += ANIM_add_driver( + op->reports, ptr.owner_id, path, index, flags, DRIVER_TYPE_PYTHON); MEM_freeN(path); } if (success) { /* send updates */ UI_context_update_anim_flag(C); - DEG_id_tag_update(ptr.id.data, ID_RECALC_COPY_ON_WRITE); + DEG_id_tag_update(ptr.owner_id, ID_RECALC_COPY_ON_WRITE); DEG_relations_tag_update(CTX_data_main(C)); WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL); } @@ -1149,7 +1151,7 @@ void ANIM_OT_driver_button_add(wmOperatorType *ot) static int remove_driver_button_exec(bContext *C, wmOperator *op) { - PointerRNA ptr = {{NULL}}; + PointerRNA ptr = {NULL}; PropertyRNA *prop = NULL; short success = 0; int index; @@ -1162,11 +1164,11 @@ static int remove_driver_button_exec(bContext *C, wmOperator *op) index = -1; } - if (ptr.id.data && ptr.data && prop) { + if (ptr.owner_id && ptr.data && prop) { char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL); if (path) { - success = ANIM_remove_driver(op->reports, ptr.id.data, path, index, 0); + success = ANIM_remove_driver(op->reports, ptr.owner_id, path, index, 0); MEM_freeN(path); } @@ -1205,14 +1207,14 @@ void ANIM_OT_driver_button_remove(wmOperatorType *ot) static int edit_driver_button_exec(bContext *C, wmOperator *op) { - PointerRNA ptr = {{NULL}}; + PointerRNA ptr = {NULL}; PropertyRNA *prop = NULL; int index; /* try to find driver using property retrieved from UI */ UI_context_active_but_prop_get(C, &ptr, &prop, &index); - if (ptr.id.data && ptr.data && prop) { + if (ptr.owner_id && ptr.data && prop) { UI_popover_panel_invoke(C, "GRAPH_PT_drivers_popover", true, op->reports); } @@ -1239,7 +1241,7 @@ void ANIM_OT_driver_button_edit(wmOperatorType *ot) static int copy_driver_button_exec(bContext *C, wmOperator *op) { - PointerRNA ptr = {{NULL}}; + PointerRNA ptr = {NULL}; PropertyRNA *prop = NULL; short success = 0; int index; @@ -1247,12 +1249,12 @@ static int copy_driver_button_exec(bContext *C, wmOperator *op) /* try to create driver using property retrieved from UI */ UI_context_active_but_prop_get(C, &ptr, &prop, &index); - if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { + if (ptr.owner_id && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL); if (path) { /* only copy the driver for the button that this was involved for */ - success = ANIM_copy_driver(op->reports, ptr.id.data, path, index, 0); + success = ANIM_copy_driver(op->reports, ptr.owner_id, path, index, 0); UI_context_update_anim_flag(C); @@ -1283,7 +1285,7 @@ void ANIM_OT_copy_driver_button(wmOperatorType *ot) static int paste_driver_button_exec(bContext *C, wmOperator *op) { - PointerRNA ptr = {{NULL}}; + PointerRNA ptr = {NULL}; PropertyRNA *prop = NULL; short success = 0; int index; @@ -1291,18 +1293,18 @@ static int paste_driver_button_exec(bContext *C, wmOperator *op) /* try to create driver using property retrieved from UI */ UI_context_active_but_prop_get(C, &ptr, &prop, &index); - if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { + if (ptr.owner_id && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL); if (path) { /* only copy the driver for the button that this was involved for */ - success = ANIM_paste_driver(op->reports, ptr.id.data, path, index, 0); + success = ANIM_paste_driver(op->reports, ptr.owner_id, path, index, 0); UI_context_update_anim_flag(C); DEG_relations_tag_update(CTX_data_main(C)); - DEG_id_tag_update(ptr.id.data, ID_RECALC_ANIMATION); + DEG_id_tag_update(ptr.owner_id, ID_RECALC_ANIMATION); WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL); // XXX diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c index b42e8102c5b..705351522f8 100644 --- a/source/blender/editors/animation/fmodifier_ui.c +++ b/source/blender/editors/animation/fmodifier_ui.c @@ -197,7 +197,7 @@ static void draw_modifier__generator(uiLayout *layout, &data->poly_order, 1, 100, - 0, + 1, 0, TIP_("'Order' of the Polynomial (for a polynomial with n terms, 'order' is n-1)")); UI_but_func_set(but, validate_fmodifier_cb, fcm, fcurve_owner_id); @@ -335,7 +335,7 @@ static void draw_modifier__generator(uiLayout *layout, &data->poly_order, 1, 100, - 0, + 1, 0, TIP_("'Order' of the Polynomial (for a polynomial with n terms, 'order' is n-1)")); UI_but_func_set(but, validate_fmodifier_cb, fcm, fcurve_owner_id); diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c index 889d27480df..ca7e0eae136 100644 --- a/source/blender/editors/animation/keyframes_draw.c +++ b/source/blender/editors/animation/keyframes_draw.c @@ -814,8 +814,10 @@ static void draw_keylist(View2D *v2d, uint outline_color_id = GPU_vertformat_attr_add( format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); uint flags_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT); - immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND); + GPU_program_point_size(true); + immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND); + immUniform1f("outline_scale", 1.0f); immUniform2f( "ViewportSize", BLI_rcti_size_x(&v2d->mask) + 1, BLI_rcti_size_y(&v2d->mask) + 1); immBegin(GPU_PRIM_POINTS, key_len); diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index dcc596e67e1..0f8b8742659 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -222,7 +222,7 @@ FCurve *verify_fcurve(Main *bmain, /* sync bone group colors if applicable */ if (ptr && (ptr->type == &RNA_PoseBone)) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; bPoseChannel *pchan = (bPoseChannel *)ptr->data; bPose *pose = ob->pose; bActionGroup *grp; @@ -286,7 +286,7 @@ void update_autoflags_fcurve(FCurve *fcu, bContext *C, ReportList *reports, Poin PropertyRNA *prop; int old_flag = fcu->flag; - if ((ptr->id.data == NULL) && (ptr->data == NULL)) { + if ((ptr->owner_id == NULL) && (ptr->data == NULL)) { BKE_report(reports, RPT_ERROR, "No RNA pointer available to retrieve values for this fcurve"); return; } @@ -294,7 +294,7 @@ void update_autoflags_fcurve(FCurve *fcu, bContext *C, ReportList *reports, Poin /* try to get property we should be affecting */ if (RNA_path_resolve_property(ptr, fcu->rna_path, &tmp_ptr, &prop) == false) { /* property not found... */ - const char *idname = (ptr->id.data) ? ((ID *)ptr->id.data)->name : TIP_("<No ID pointer>"); + const char *idname = (ptr->owner_id) ? ptr->owner_id->name : TIP_("<No ID pointer>"); BKE_reportf(reports, RPT_ERROR, @@ -1203,7 +1203,7 @@ bool insert_keyframe_direct(ReportList *reports, } /* if no property given yet, try to validate from F-Curve info */ - if ((ptr.id.data == NULL) && (ptr.data == NULL)) { + if ((ptr.owner_id == NULL) && (ptr.data == NULL)) { BKE_report( reports, RPT_ERROR, "No RNA pointer available to retrieve values for keyframing from"); return false; @@ -1214,7 +1214,7 @@ bool insert_keyframe_direct(ReportList *reports, /* try to get property we should be affecting */ if (RNA_path_resolve_property(&ptr, fcu->rna_path, &tmp_ptr, &prop) == false) { /* property not found... */ - const char *idname = (ptr.id.data) ? ((ID *)ptr.id.data)->name : TIP_("<No ID pointer>"); + const char *idname = (ptr.owner_id) ? ptr.owner_id->name : TIP_("<No ID pointer>"); BKE_reportf(reports, RPT_ERROR, @@ -1544,9 +1544,9 @@ static bool delete_keyframe_fcurve(AnimData *adt, FCurve *fcu, float cfra) static void deg_tag_after_keyframe_delete(Main *bmain, ID *id, AnimData *adt) { if (adt->action == NULL) { - /* In the case last f-curve wes removed need to inform dependency graph + /* In the case last f-curve was removed need to inform dependency graph * about relations update, since it needs to get rid of animation operation - * for this datablock. */ + * for this data-block. */ DEG_id_tag_update_ex(bmain, id, ID_RECALC_ANIMATION_NO_FLUSH); DEG_relations_tag_update(bmain); } @@ -2350,7 +2350,7 @@ static int insert_key_button_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); ToolSettings *ts = scene->toolsettings; - PointerRNA ptr = {{NULL}}; + PointerRNA ptr = {NULL}; PropertyRNA *prop = NULL; char *path; uiBut *but; @@ -2369,7 +2369,7 @@ static int insert_key_button_exec(bContext *C, wmOperator *op) return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH); } - if ((ptr.id.data && ptr.data && prop) && RNA_property_animateable(&ptr, prop)) { + if ((ptr.owner_id && ptr.data && prop) && RNA_property_animateable(&ptr, prop)) { if (ptr.type == &RNA_NlaStrip) { /* Handle special properties for NLA Strips, whose F-Curves are stored on the * strips themselves. These are stored separately or else the properties will @@ -2435,7 +2435,7 @@ static int insert_key_button_exec(bContext *C, wmOperator *op) success = insert_keyframe(bmain, op->reports, - ptr.id.data, + ptr.owner_id, NULL, group, path, @@ -2473,7 +2473,7 @@ static int insert_key_button_exec(bContext *C, wmOperator *op) } if (success) { - ID *id = ptr.id.data; + ID *id = ptr.owner_id; AnimData *adt = BKE_animdata_from_id(id); if (adt->action != NULL) { DEG_id_tag_update(&adt->action->id, ID_RECALC_ANIMATION_NO_FLUSH); @@ -2513,7 +2513,7 @@ void ANIM_OT_keyframe_insert_button(wmOperatorType *ot) static int delete_key_button_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - PointerRNA ptr = {{NULL}}; + PointerRNA ptr = {NULL}; PropertyRNA *prop = NULL; Main *bmain = CTX_data_main(C); char *path; @@ -2528,13 +2528,13 @@ static int delete_key_button_exec(bContext *C, wmOperator *op) return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH); } - if (ptr.id.data && ptr.data && prop) { + if (ptr.owner_id && ptr.data && prop) { if (BKE_nlastrip_has_curves_for_property(&ptr, prop)) { /* Handle special properties for NLA Strips, whose F-Curves are stored on the * strips themselves. These are stored separately or else the properties will * not have any effect. */ - ID *id = ptr.id.data; + ID *id = ptr.owner_id; NlaStrip *strip = (NlaStrip *)ptr.data; FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), 0); @@ -2577,7 +2577,7 @@ static int delete_key_button_exec(bContext *C, wmOperator *op) } success = delete_keyframe( - bmain, op->reports, ptr.id.data, NULL, NULL, path, index, cfra, 0); + bmain, op->reports, ptr.owner_id, NULL, NULL, path, index, cfra, 0); MEM_freeN(path); } else if (G.debug & G_DEBUG) { @@ -2622,7 +2622,7 @@ void ANIM_OT_keyframe_delete_button(wmOperatorType *ot) static int clear_key_button_exec(bContext *C, wmOperator *op) { - PointerRNA ptr = {{NULL}}; + PointerRNA ptr = {NULL}; PropertyRNA *prop = NULL; Main *bmain = CTX_data_main(C); char *path; @@ -2636,7 +2636,7 @@ static int clear_key_button_exec(bContext *C, wmOperator *op) return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH); } - if (ptr.id.data && ptr.data && prop) { + if (ptr.owner_id && ptr.data && prop) { path = RNA_path_from_ID_to_property(&ptr, prop); if (path) { @@ -2645,7 +2645,7 @@ static int clear_key_button_exec(bContext *C, wmOperator *op) index = -1; } - success += clear_keyframe(bmain, op->reports, ptr.id.data, NULL, NULL, path, index, 0); + success += clear_keyframe(bmain, op->reports, ptr.owner_id, NULL, NULL, path, index, 0); MEM_freeN(path); } else if (G.debug & G_DEBUG) { diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c index ccd0fc54611..258c0e4f1f6 100644 --- a/source/blender/editors/animation/keyingsets.c +++ b/source/blender/editors/animation/keyingsets.c @@ -287,7 +287,7 @@ static int add_keyingset_button_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); KeyingSet *ks = NULL; PropertyRNA *prop = NULL; - PointerRNA ptr = {{NULL}}; + PointerRNA ptr = {NULL}; char *path = NULL; short success = 0; int index = 0, pflag = 0; @@ -332,7 +332,7 @@ static int add_keyingset_button_exec(bContext *C, wmOperator *op) } /* check if property is able to be added */ - if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { + if (ptr.owner_id && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { path = RNA_path_from_ID_to_property(&ptr, prop); if (path) { @@ -348,7 +348,7 @@ static int add_keyingset_button_exec(bContext *C, wmOperator *op) } /* add path to this setting */ - BKE_keyingset_add_path(ks, ptr.id.data, NULL, path, index, pflag, KSP_GROUP_KSNAME); + BKE_keyingset_add_path(ks, ptr.owner_id, NULL, path, index, pflag, KSP_GROUP_KSNAME); ks->active_path = BLI_listbase_count(&ks->paths); success = 1; @@ -393,7 +393,7 @@ static int remove_keyingset_button_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); KeyingSet *ks = NULL; PropertyRNA *prop = NULL; - PointerRNA ptr = {{NULL}}; + PointerRNA ptr = {NULL}; char *path = NULL; short success = 0; int index = 0; @@ -420,14 +420,14 @@ static int remove_keyingset_button_exec(bContext *C, wmOperator *op) ks = BLI_findlink(&scene->keyingsets, scene->active_keyingset - 1); } - if (ptr.id.data && ptr.data && prop) { + if (ptr.owner_id && ptr.data && prop) { path = RNA_path_from_ID_to_property(&ptr, prop); if (path) { KS_Path *ksp; /* try to find a path matching this description */ - ksp = BKE_keyingset_find_path(ks, ptr.id.data, ks->name, path, index, KSP_GROUP_KSNAME); + ksp = BKE_keyingset_find_path(ks, ptr.owner_id, ks->name, path, index, KSP_GROUP_KSNAME); if (ksp) { BKE_keyingset_free_path(ks, ksp); @@ -712,9 +712,9 @@ int ANIM_scene_get_keyingset_index(Scene *scene, KeyingSet *ks) } } - /* still here, so try builtins list too - * - builtins are from (<= -1) - * - none/invalid is (= 0) + /* Still here, so try built-ins list too: + * - Built-ins are from (<= -1). + * - None/Invalid is (= 0). */ index = BLI_findindex(&builtin_keyingsets, ks); if (index != -1) { diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c index d2fa77f90be..1073034383d 100644 --- a/source/blender/editors/armature/armature_add.c +++ b/source/blender/editors/armature/armature_add.c @@ -769,7 +769,7 @@ static int armature_symmetrize_exec(bContext *C, wmOperator *op) EditBone *ebone = ebone_iter->temp.ebone; - /* copy flags incase bone is pre-existing data */ + /* Copy flags in case bone is pre-existing data. */ ebone->flag = (ebone->flag & ~flag_copy) | (ebone_iter->flag & flag_copy); if (ebone_iter->parent == NULL) { diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c index 4e6661b1d15..c4c10549da3 100644 --- a/source/blender/editors/armature/armature_edit.c +++ b/source/blender/editors/armature/armature_edit.c @@ -62,22 +62,10 @@ /* ************************** Object Tools Exports ******************************* */ /* NOTE: these functions are exported to the Object module to be called from the tools there */ -void ED_armature_transform_apply(Main *bmain, Object *ob, float mat[4][4], const bool do_props) -{ - bArmature *arm = ob->data; - - /* Put the armature into editmode */ - ED_armature_to_edit(arm); - - /* Transform the bones */ - ED_armature_transform_bones(arm, mat, do_props); - - /* Turn the list into an armature */ - ED_armature_from_edit(bmain, arm); - ED_armature_edit_free(arm); -} - -void ED_armature_transform_bones(struct bArmature *arm, float mat[4][4], const bool do_props) +/** + * See #BKE_armature_transform for object-mode transform. + */ +void ED_armature_edit_transform(bArmature *arm, const float mat[4][4], const bool do_props) { EditBone *ebone; float scale = mat4_to_scale(mat); /* store the scale of the matrix here to use on envelopes */ @@ -114,21 +102,13 @@ void ED_armature_transform_bones(struct bArmature *arm, float mat[4][4], const b } } -void ED_armature_transform(Main *bmain, bArmature *arm, float mat[4][4], const bool do_props) +void ED_armature_transform(bArmature *arm, const float mat[4][4], const bool do_props) { if (arm->edbo) { - ED_armature_transform_bones(arm, mat, do_props); + ED_armature_edit_transform(arm, mat, do_props); } else { - /* Put the armature into editmode */ - ED_armature_to_edit(arm); - - /* Transform the bones */ - ED_armature_transform_bones(arm, mat, do_props); - - /* Go back to object mode*/ - ED_armature_from_edit(bmain, arm); - ED_armature_edit_free(arm); + BKE_armature_transform(arm, mat, do_props); } } diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h index 569eb7e2e04..fa562ab0f44 100644 --- a/source/blender/editors/armature/armature_intern.h +++ b/source/blender/editors/armature/armature_intern.h @@ -30,7 +30,6 @@ struct wmOperatorType; struct Base; struct Object; struct Scene; -struct bAction; struct bContext; struct bPoseChannel; diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c index 23ddf77e63d..eff621d7b71 100644 --- a/source/blender/editors/armature/armature_select.c +++ b/source/blender/editors/armature/armature_select.c @@ -46,6 +46,7 @@ #include "ED_armature.h" #include "ED_object.h" +#include "ED_outliner.h" #include "ED_screen.h" #include "ED_select_utils.h" #include "ED_view3d.h" @@ -356,6 +357,8 @@ static int armature_select_linked_invoke(bContext *C, wmOperator *op, const wmEv } } + ED_outliner_select_sync_from_edit_bone_tag(C); + ED_armature_edit_sync_selection(arm->edbo); WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, base->object); @@ -1027,6 +1030,8 @@ static int armature_de_select_all_exec(bContext *C, wmOperator *op) } CTX_DATA_END; + ED_outliner_select_sync_from_edit_bone_tag(C); + WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, NULL); return OPERATOR_FINISHED; @@ -1148,6 +1153,8 @@ static int armature_de_select_more_exec(bContext *C, wmOperator *UNUSED(op)) WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob); } MEM_freeN(objects); + + ED_outliner_select_sync_from_edit_bone_tag(C); return OPERATOR_FINISHED; } @@ -1178,6 +1185,8 @@ static int armature_de_select_less_exec(bContext *C, wmOperator *UNUSED(op)) WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob); } MEM_freeN(objects); + + ED_outliner_select_sync_from_edit_bone_tag(C); return OPERATOR_FINISHED; } @@ -1569,6 +1578,8 @@ static int armature_select_similar_exec(bContext *C, wmOperator *op) #undef STRUCT_SIZE_AND_OFFSET + ED_outliner_select_sync_from_edit_bone_tag(C); + return OPERATOR_FINISHED; } @@ -1663,6 +1674,8 @@ static int armature_select_hierarchy_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } + ED_outliner_select_sync_from_edit_bone_tag(C); + ED_armature_edit_sync_selection(arm->edbo); WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob); @@ -1748,6 +1761,8 @@ static int armature_select_mirror_exec(bContext *C, wmOperator *op) arm->act_edbone = ebone_mirror_act; } + ED_outliner_select_sync_from_edit_bone_tag(C); + ED_armature_edit_sync_selection(arm->edbo); WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob); @@ -1876,6 +1891,7 @@ static int armature_shortest_path_pick_invoke(bContext *C, wmOperator *op, const if (changed) { arm->act_edbone = ebone_dst; + ED_outliner_select_sync_from_edit_bone_tag(C); ED_armature_edit_sync_selection(arm->edbo); WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit); diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c index d8777b7e0b7..cd299906b4c 100644 --- a/source/blender/editors/armature/armature_utils.c +++ b/source/blender/editors/armature/armature_utils.c @@ -381,23 +381,37 @@ void armature_tag_unselect(bArmature *arm) void ED_armature_ebone_transform_mirror_update(bArmature *arm, EditBone *ebo, bool check_select) { + /* TODO When this function is called by property updates, + * cancelling the value change will not restore mirrored bone correctly. */ + + /* Currently check_select==true when this function is called from a transform operator, + * eg. from 3d viewport. */ + /* no layer check, correct mirror is more important */ if (!check_select || ebo->flag & (BONE_TIPSEL | BONE_ROOTSEL)) { EditBone *eboflip = ED_armature_ebone_get_mirrored(arm->edbo, ebo); if (eboflip) { - /* we assume X-axis flipping for now */ - if (check_select && ebo->flag & BONE_TIPSEL) { - EditBone *children; + /* We assume X-axis flipping for now. */ + + /* Always mirror roll, since it can be changed by moving either head or tail. */ + eboflip->roll = -ebo->roll; + + if (!check_select || ebo->flag & BONE_TIPSEL) { + /* Mirror tail properties. */ eboflip->tail[0] = -ebo->tail[0]; eboflip->tail[1] = ebo->tail[1]; eboflip->tail[2] = ebo->tail[2]; eboflip->rad_tail = ebo->rad_tail; - eboflip->roll = -ebo->roll; eboflip->curve_out_x = -ebo->curve_out_x; + eboflip->curve_out_y = ebo->curve_out_y; + eboflip->scale_out_x = ebo->scale_out_x; + eboflip->scale_out_y = ebo->scale_out_y; + eboflip->ease2 = ebo->ease2; eboflip->roll2 = -ebo->roll2; - /* Also move connected children, in case children's name aren't mirrored properly */ + /* Also move connected children, in case children's name aren't mirrored properly. */ + EditBone *children; for (children = arm->edbo->first; children; children = children->next) { if (children->parent == eboflip && children->flag & BONE_CONNECTED) { copy_v3_v3(children->head, eboflip->tail); @@ -405,32 +419,39 @@ void ED_armature_ebone_transform_mirror_update(bArmature *arm, EditBone *ebo, bo } } } + if (!check_select || ebo->flag & BONE_ROOTSEL) { + /* Mirror head properties. */ eboflip->head[0] = -ebo->head[0]; eboflip->head[1] = ebo->head[1]; eboflip->head[2] = ebo->head[2]; eboflip->rad_head = ebo->rad_head; - eboflip->roll = -ebo->roll; + eboflip->curve_in_x = -ebo->curve_in_x; + eboflip->curve_in_y = ebo->curve_in_y; + eboflip->scale_in_x = ebo->scale_in_x; + eboflip->scale_in_y = ebo->scale_in_y; + eboflip->ease1 = ebo->ease1; eboflip->roll1 = -ebo->roll1; - /* Also move connected parent, in case parent's name isn't mirrored properly */ + /* Also move connected parent, in case parent's name isn't mirrored properly. */ if (eboflip->parent && eboflip->flag & BONE_CONNECTED) { EditBone *parent = eboflip->parent; copy_v3_v3(parent->tail, eboflip->head); parent->rad_tail = ebo->rad_head; } } + if (!check_select || ebo->flag & BONE_SELECTED) { + /* Mirror bone body properties (both head and tail are selected). */ + /* TODO: These values can also be changed from pose mode, + * so only mirroring them in edit mode is not ideal. */ eboflip->dist = ebo->dist; - eboflip->roll = -ebo->roll; + eboflip->weight = ebo->weight; + + eboflip->segments = ebo->segments; eboflip->xwidth = ebo->xwidth; eboflip->zwidth = ebo->zwidth; - - eboflip->curve_in_x = -ebo->curve_in_x; - eboflip->curve_out_x = -ebo->curve_out_x; - eboflip->roll1 = -ebo->roll1; - eboflip->roll2 = -ebo->roll2; } } } diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c index 8434fee6e78..a59067e60c1 100644 --- a/source/blender/editors/armature/pose_select.c +++ b/source/blender/editors/armature/pose_select.c @@ -54,6 +54,7 @@ #include "ED_keyframing.h" #include "ED_mesh.h" #include "ED_object.h" +#include "ED_outliner.h" #include "ED_screen.h" #include "ED_select_utils.h" #include "ED_view3d.h" @@ -449,6 +450,8 @@ static int pose_select_connected_invoke(bContext *C, wmOperator *op, const wmEve selectconnected_posebonechildren(base->object, curBone, extend); } + ED_outliner_select_sync_from_pose_bone_tag(C); + ED_pose_bone_select_tag_update(base->object); return OPERATOR_FINISHED; @@ -514,6 +517,8 @@ static int pose_de_select_all_exec(bContext *C, wmOperator *op) } CTX_DATA_END; + ED_outliner_select_sync_from_pose_bone_tag(C); + WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, NULL); return OPERATOR_FINISHED; @@ -560,6 +565,8 @@ static int pose_select_parent_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; } + ED_outliner_select_sync_from_pose_bone_tag(C); + ED_pose_bone_select_tag_update(ob); return OPERATOR_FINISHED; } @@ -624,6 +631,8 @@ static int pose_select_constraint_target_exec(bContext *C, wmOperator *UNUSED(op return OPERATOR_CANCELLED; } + ED_outliner_select_sync_from_pose_bone_tag(C); + return OPERATOR_FINISHED; } @@ -712,6 +721,8 @@ static int pose_select_hierarchy_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } + ED_outliner_select_sync_from_pose_bone_tag(C); + ED_pose_bone_select_tag_update(ob); return OPERATOR_FINISHED; @@ -796,7 +807,7 @@ static bool pose_select_same_group(bContext *C, bool extend) group_flags = NULL; ob_index = -1; ob_prev = NULL; - CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, pchan, visible_pose_bones, Object, *ob) { + CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, pchan, visible_pose_bones, Object *, ob) { if (ob != ob_prev) { ob_index++; group_flags = group_flags_array + (ob_index * groups_len); @@ -1061,6 +1072,8 @@ static int pose_select_grouped_exec(bContext *C, wmOperator *op) /* report done status */ if (changed) { + ED_outliner_select_sync_from_pose_bone_tag(C); + return OPERATOR_FINISHED; } else { @@ -1172,6 +1185,8 @@ static int pose_select_mirror_exec(bContext *C, wmOperator *op) } MEM_freeN(objects); + ED_outliner_select_sync_from_pose_bone_tag(C); + return OPERATOR_FINISHED; } diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c index c8e79b879a4..6274eb549da 100644 --- a/source/blender/editors/armature/pose_slide.c +++ b/source/blender/editors/armature/pose_slide.c @@ -442,7 +442,7 @@ static void pose_slide_apply_props(tPoseSlideOp *pso, tPChanFCurveLink *pfl, const char prop_prefix[]) { - PointerRNA ptr = {{NULL}}; + PointerRNA ptr = {NULL}; LinkData *ld; int len = strlen(pfl->pchan_path); diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index c93531bb6cc..d7650db546d 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -51,6 +51,7 @@ #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" +#include "DEG_depsgraph_query.h" #include "WM_api.h" #include "WM_types.h" @@ -5679,6 +5680,7 @@ static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event) }, mval, NULL, + NULL, location, NULL); @@ -7104,14 +7106,15 @@ static int match_texture_space_exec(bContext *C, wmOperator *UNUSED(op)) (void)depsgraph; Object *object = CTX_data_active_object(C); + Object *object_eval = DEG_get_evaluated_object(depsgraph, object); Curve *curve = (Curve *)object->data; float min[3], max[3], size[3], loc[3]; int a; - BLI_assert(object->runtime.curve_cache != NULL); + BLI_assert(object_eval->runtime.curve_cache != NULL); INIT_MINMAX(min, max); - BKE_displist_minmax(&object->runtime.curve_cache->disp, min, max); + BKE_displist_minmax(&object_eval->runtime.curve_cache->disp, min, max); mid_v3_v3v3(loc, min, max); @@ -7138,6 +7141,7 @@ static int match_texture_space_exec(bContext *C, wmOperator *UNUSED(op)) curve->texflag &= ~CU_AUTOSPACE; WM_event_add_notifier(C, NC_GEOM | ND_DATA, curve); + DEG_id_tag_update(&curve->id, ID_RECALC_GEOMETRY); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/curve/editcurve_paint.c b/source/blender/editors/curve/editcurve_paint.c index 5e0053782d4..c7c19aa2d02 100644 --- a/source/blender/editors/curve/editcurve_paint.c +++ b/source/blender/editors/curve/editcurve_paint.c @@ -120,7 +120,7 @@ struct CurveDrawData { struct { float mouse[2]; - /* used incase we can't calculate the depth */ + /* Used in case we can't calculate the depth. */ float location_world[3]; float location_world_valid[3]; @@ -1053,7 +1053,7 @@ static int curve_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event) const bool is_modal = RNA_boolean_get(op->ptr, "wait_for_input"); - /* fallback (incase we can't find the depth on first test) */ + /* Fallback (in case we can't find the depth on first test). */ { const float mval_fl[2] = {UNPACK2(event->mval)}; float center[3]; diff --git a/source/blender/editors/curve/editcurve_select.c b/source/blender/editors/curve/editcurve_select.c index d3f0ebfda3c..f67ccf1e4bd 100644 --- a/source/blender/editors/curve/editcurve_select.c +++ b/source/blender/editors/curve/editcurve_select.c @@ -1417,7 +1417,7 @@ void CURVE_OT_select_nth(wmOperatorType *ot) { /* identifiers */ ot->name = "Checker Deselect"; - ot->description = "Deselect every other vertex"; + ot->description = "Deselect every Nth point starting from the active one"; ot->idname = "CURVE_OT_select_nth"; /* api callbacks */ diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index f0c1abff201..781eb2634fb 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -71,7 +71,11 @@ static int kill_selection(Object *obedit, int ins); -/************************* utilities ******************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Internal Utilities + * \{ */ static wchar_t findaccent(wchar_t char1, unsigned int code) { @@ -440,8 +444,48 @@ static void text_update_edited(bContext *C, Object *obedit, int mode) WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); } +static int kill_selection(Object *obedit, int ins) /* 1 == new character */ +{ + Curve *cu = obedit->data; + EditFont *ef = cu->editfont; + int selend, selstart, direction; + int offset = 0; + int getfrom; + + direction = BKE_vfont_select_get(obedit, &selstart, &selend); + if (direction) { + int size; + if (ins) { + offset = 1; + } + if (ef->pos >= selstart) { + ef->pos = selstart + offset; + } + if ((direction == -1) && ins) { + selstart++; + selend++; + } + getfrom = selend + offset; + if (ins == 0) { + getfrom++; + } + size = (ef->len * sizeof(wchar_t)) - (selstart * sizeof(wchar_t)) + (offset * sizeof(wchar_t)); + memmove(ef->textbuf + selstart, ef->textbuf + getfrom, size); + memmove(ef->textbufinfo + selstart, + ef->textbufinfo + getfrom, + ((ef->len - selstart) + offset) * sizeof(CharInfo)); + ef->len -= ((selend - selstart) + 1); + ef->selstart = ef->selend = 0; + } + + return (direction); +} + +/** \} */ + /* -------------------------------------------------------------------- */ -/* Generic Paste Functions */ +/** \name Generic Paste Functions + * \{ */ /* text_update_edited(C, scene, obedit, 1, FO_EDIT); */ static bool font_paste_wchar(Object *obedit, @@ -506,8 +550,11 @@ static bool font_paste_utf8(bContext *C, const char *str, const size_t str_len) return retval; } +/** \} */ + /* -------------------------------------------------------------------- */ -/* Paste From File*/ +/** \name Paste From File Operator + * \{ */ static int paste_from_file(bContext *C, ReportList *reports, const char *filename) { @@ -585,7 +632,11 @@ void FONT_OT_text_paste_from_file(wmOperatorType *ot) FILE_SORT_ALPHA); } -/******************* text to object operator ********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Text To Object + * \{ */ static void txt_add_object(bContext *C, TextLine *firstline, int totline, const float offset[3]) { @@ -703,46 +754,11 @@ void ED_text_to_object(bContext *C, Text *text, const bool split_lines) } } -/********************** utilities ***************************/ - -static int kill_selection(Object *obedit, int ins) /* 1 == new character */ -{ - Curve *cu = obedit->data; - EditFont *ef = cu->editfont; - int selend, selstart, direction; - int offset = 0; - int getfrom; - - direction = BKE_vfont_select_get(obedit, &selstart, &selend); - if (direction) { - int size; - if (ins) { - offset = 1; - } - if (ef->pos >= selstart) { - ef->pos = selstart + offset; - } - if ((direction == -1) && ins) { - selstart++; - selend++; - } - getfrom = selend + offset; - if (ins == 0) { - getfrom++; - } - size = (ef->len * sizeof(wchar_t)) - (selstart * sizeof(wchar_t)) + (offset * sizeof(wchar_t)); - memmove(ef->textbuf + selstart, ef->textbuf + getfrom, size); - memmove(ef->textbufinfo + selstart, - ef->textbufinfo + getfrom, - ((ef->len - selstart) + offset) * sizeof(CharInfo)); - ef->len -= ((selend - selstart) + 1); - ef->selstart = ef->selend = 0; - } - - return (direction); -} +/** \} */ -/******************* set style operator ********************/ +/* -------------------------------------------------------------------- */ +/** \name Set Style Operator + * \{ */ static const EnumPropertyItem style_items[] = { {CU_CHINFO_BOLD, "BOLD", 0, "Bold", ""}, @@ -806,7 +822,11 @@ void FONT_OT_style_set(wmOperatorType *ot) RNA_def_boolean(ot->srna, "clear", 0, "Clear", "Clear style rather than setting it"); } -/******************* toggle style operator ********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Toggle Style Operator + * \{ */ static int toggle_style_exec(bContext *C, wmOperator *op) { @@ -845,8 +865,11 @@ void FONT_OT_style_toggle(wmOperatorType *ot) ot->srna, "style", style_items, CU_CHINFO_BOLD, "Style", "Style to set selection to"); } +/** \} */ + /* -------------------------------------------------------------------- */ -/* Select All */ +/** \name Select All Operator + * \{ */ static int font_select_all_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -883,7 +906,11 @@ void FONT_OT_select_all(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/******************* copy text operator ********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Copy Text Operator + * \{ */ static void copy_selection(Object *obedit) { @@ -932,7 +959,11 @@ void FONT_OT_text_copy(wmOperatorType *ot) ot->poll = ED_operator_editfont; } -/******************* cut text operator ********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Cut Text Operator + * \{ */ static int cut_text_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -966,7 +997,11 @@ void FONT_OT_text_cut(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/******************* paste text operator ********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Paste Text Operator + * \{ */ static bool paste_selection(Object *obedit, ReportList *reports) { @@ -1066,7 +1101,11 @@ void FONT_OT_text_paste(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/************************ move operator ************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Move Operator + * \{ */ static const EnumPropertyItem move_type_items[] = { {LINE_BEGIN, "LINE_BEGIN", 0, "Line Begin", ""}, @@ -1232,7 +1271,11 @@ void FONT_OT_move(wmOperatorType *ot) RNA_def_enum(ot->srna, "type", move_type_items, LINE_BEGIN, "Type", "Where to move cursor to"); } -/******************* move select operator ********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Move Select Operator + * \{ */ static int move_select_exec(bContext *C, wmOperator *op) { @@ -1264,7 +1307,11 @@ void FONT_OT_move_select(wmOperatorType *ot) "Where to move cursor to, to make a selection"); } -/************************* change spacing **********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Change Spacing + * \{ */ static int change_spacing_exec(bContext *C, wmOperator *op) { @@ -1314,7 +1361,11 @@ void FONT_OT_change_spacing(wmOperatorType *ot) 20); } -/************************* change character **********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Change Character + * \{ */ static int change_character_exec(bContext *C, wmOperator *op) { @@ -1368,7 +1419,11 @@ void FONT_OT_change_character(wmOperatorType *ot) 255); } -/******************* line break operator ********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Line Break Operator + * \{ */ static int line_break_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -1400,7 +1455,11 @@ void FONT_OT_line_break(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/******************* delete operator **********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Delete Operator + * \{ */ static const EnumPropertyItem delete_type_items[] = { {DEL_NEXT_CHAR, "NEXT_CHARACTER", 0, "Next Character", ""}, @@ -1549,7 +1608,11 @@ void FONT_OT_delete(wmOperatorType *ot) "Which part of the text to delete"); } -/*********************** insert text operator *************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Insert Text Operator + * \{ */ static int insert_text_exec(bContext *C, wmOperator *op) { @@ -1700,7 +1763,12 @@ void FONT_OT_text_insert(wmOperatorType *ot) "Next typed character will strike through previous, for special character input"); } -/*********************** textbox add operator *************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Textbox Add Operator + * \{ */ + static int textbox_add_exec(bContext *C, wmOperator *UNUSED(op)) { Object *obedit = CTX_data_active_object(C); @@ -1736,7 +1804,11 @@ void FONT_OT_textbox_add(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/*********************** textbox remove operator *************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Textbox Remove Operator + * \{ */ static int textbox_remove_exec(bContext *C, wmOperator *op) { @@ -1778,7 +1850,11 @@ void FONT_OT_textbox_remove(wmOperatorType *ot) RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "The current text box", 0, INT_MAX); } -/***************** editmode enter/exit ********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Editmode Enter/Exit + * \{ */ void ED_curve_editfont_make(Object *obedit) { @@ -1851,7 +1927,11 @@ void ED_curve_editfont_free(Object *obedit) BKE_curve_editfont_free((Curve *)obedit->data); } -/********************** set case operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Set Case Operator + * \{ */ static const EnumPropertyItem case_items[] = { {CASE_LOWER, "LOWER", 0, "Lower", ""}, @@ -1920,7 +2000,11 @@ void FONT_OT_case_set(wmOperatorType *ot) RNA_def_enum(ot->srna, "case", case_items, CASE_LOWER, "Case", "Lower or upper case"); } -/********************** toggle case operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Toggle Case Operator + * \{ */ static int toggle_case_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -2031,7 +2115,7 @@ static int open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event) if (pprop->prop) { idptr = RNA_property_pointer_get((PointerRNA *)pprop, pprop->prop); - vfont = idptr.id.data; + vfont = (VFont *)idptr.owner_id; } path = (vfont && !BKE_vfont_is_builtin(vfont)) ? vfont->name : U.fontdir; @@ -2071,7 +2155,11 @@ void FONT_OT_open(wmOperatorType *ot) FILE_SORT_ALPHA); } -/******************* delete operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Delete Operator + * \{ */ static int font_unlink_exec(bContext *C, wmOperator *op) { @@ -2190,3 +2278,5 @@ bool ED_curve_editfont_select_pick( return false; } } + +/** \} */ diff --git a/source/blender/editors/gizmo_library/gizmo_types/arrow3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/arrow3d_gizmo.c index d23965269ab..fa9c0f1fbb2 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/arrow3d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/arrow3d_gizmo.c @@ -363,8 +363,8 @@ static void gizmo_arrow_exit(bContext *C, wmGizmo *gz, const bool cancel) const bool is_prop_valid = WM_gizmo_target_property_is_valid(gz_prop); if (!cancel) { - /* Assign incase applying the operation needs an updated offset - * editmesh bisect needs this. */ + /* Assign in case applying the operation needs an updated offset + * edit-mesh bisect needs this. */ if (is_prop_valid) { const int transform_flag = RNA_enum_get(arrow->gizmo.ptr, "transform"); const bool constrained = (transform_flag & ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED) != 0; diff --git a/source/blender/editors/gizmo_library/gizmo_types/cage3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/cage3d_gizmo.c index e2a86469da1..406f76bc65e 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/cage3d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/cage3d_gizmo.c @@ -358,7 +358,7 @@ static void gizmo_cage3d_draw_intern( bool show = false; if (gz->highlight_part == ED_GIZMO_CAGE3D_PART_TRANSLATE) { /* Only show if we're drawing the center handle - * otherwise the entire rectangle is the hotspot. */ + * otherwise the entire rectangle is the hot-spot. */ if (draw_options & ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) { show = true; } diff --git a/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c index 21f779b72b1..37ee95d5058 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c @@ -283,6 +283,7 @@ static int gizmo_move_modal(bContext *C, .use_occlusion_test = true, }, mval_fl, + NULL, &dist_px, co, NULL)) { diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c index 07b61751b22..22f1753a810 100644 --- a/source/blender/editors/gpencil/annotate_paint.c +++ b/source/blender/editors/gpencil/annotate_paint.c @@ -1156,7 +1156,7 @@ static tGPsdata *gp_session_initpaint(bContext *C) /* create new context data */ p = MEM_callocN(sizeof(tGPsdata), "Annotation Drawing Data"); - /* Try to initialise context data + /* Try to initialize context data * WARNING: This may not always succeed (e.g. using GP in an annotation-only context) */ if (gp_session_initdata(C, p) == 0) { @@ -1252,15 +1252,6 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps /* Ensure active frame is set correctly... */ p->gpf = p->gpl->actframe; - /* Restrict eraser to only affecting selected strokes, if the "selection mask" is on - * (though this is only available in editmode) - */ - if (p->gpd->flag & GP_DATA_STROKE_EDITMODE) { - if (ts->gp_sculpt.flag & GP_SCULPT_SETT_FLAG_SELECT_MASK) { - p->flags |= GP_PAINTFLAG_SELECTMASK; - } - } - if (has_layer_to_erase == false) { p->status = GP_STATUS_CAPTURE; // if (G.debug & G_DEBUG) diff --git a/source/blender/editors/gpencil/gpencil_add_monkey.c b/source/blender/editors/gpencil/gpencil_add_monkey.c index c4528518009..139697ad0e3 100644 --- a/source/blender/editors/gpencil/gpencil_add_monkey.c +++ b/source/blender/editors/gpencil/gpencil_add_monkey.c @@ -54,7 +54,7 @@ static int gpencil_monkey_color( short *totcol = give_totcolp(ob); Material *ma = NULL; for (short i = 0; i < *totcol; i++) { - ma = give_current_material(ob, i + 1); + ma = BKE_material_gpencil_get(ob, i + 1); if (STREQ(ma->id.name, pct->name)) { return i; } diff --git a/source/blender/editors/gpencil/gpencil_add_stroke.c b/source/blender/editors/gpencil/gpencil_add_stroke.c index 80e239c9ae5..74617599eaa 100644 --- a/source/blender/editors/gpencil/gpencil_add_stroke.c +++ b/source/blender/editors/gpencil/gpencil_add_stroke.c @@ -53,7 +53,7 @@ static int gp_stroke_material(Main *bmain, Object *ob, const ColorTemplate *pct, short *totcol = give_totcolp(ob); Material *ma = NULL; for (short i = 0; i < *totcol; i++) { - ma = give_current_material(ob, i + 1); + ma = BKE_material_gpencil_get(ob, i + 1); if (STREQ(ma->id.name, pct->name)) { return i; } diff --git a/source/blender/editors/gpencil/gpencil_brush.c b/source/blender/editors/gpencil/gpencil_brush.c index 9124c0f5d51..d1c4f271321 100644 --- a/source/blender/editors/gpencil/gpencil_brush.c +++ b/source/blender/editors/gpencil/gpencil_brush.c @@ -105,6 +105,7 @@ typedef struct tGP_BrushEditData { eGP_Sculpt_Types brush_type; eGP_Sculpt_Types brush_type_old; eGP_Sculpt_Flag flag; + eGP_Sculpt_SelectMaskFlag mask; /* Space Conversion Data */ GP_SpaceConversion gsc; @@ -133,8 +134,8 @@ typedef struct tGP_BrushEditData { /* - effect vector (e.g. 2D/3D translation for grab brush) */ float dvec[3]; - /* rotation for derived data */ - float rot; + /* rotation for evaluated data */ + float rot_eval; /* - multiframe falloff factor */ float mf_falloff; @@ -300,6 +301,20 @@ static float gp_brush_influence_calc(tGP_BrushEditData *gso, const int radius, c return influence; } +/* Force recal filling data */ +static void gp_recalc_geometry(bGPDstroke *gps) +{ + bGPDstroke *gps_orig = gps->runtime.gps_orig; + if (gps_orig) { + gps_orig->flag |= GP_STROKE_RECALC_GEOMETRY; + gps_orig->tot_triangles = 0; + } + else { + gps->flag |= GP_STROKE_RECALC_GEOMETRY; + gps->tot_triangles = 0; + } +} + /* ************************************************ */ /* Brush Callbacks */ /* This section defines the callbacks used by each brush to perform their magic. @@ -313,7 +328,7 @@ static float gp_brush_influence_calc(tGP_BrushEditData *gso, const int radius, c * smooth-brush implementation to test the algorithm for stroke smoothing. */ static bool gp_brush_smooth_apply(tGP_BrushEditData *gso, bGPDstroke *gps, - float UNUSED(rot), + float UNUSED(rot_eval), int pt_index, const int radius, const int co[2]) @@ -341,7 +356,7 @@ static bool gp_brush_smooth_apply(tGP_BrushEditData *gso, BKE_gpencil_smooth_stroke_uv(gps, pt_index, inf); } - gps->flag |= GP_STROKE_RECALC_GEOMETRY; + gp_recalc_geometry(gps); return true; } @@ -352,7 +367,7 @@ static bool gp_brush_smooth_apply(tGP_BrushEditData *gso, /* Make lines thicker or thinner by the specified amounts */ static bool gp_brush_thickness_apply(tGP_BrushEditData *gso, bGPDstroke *gps, - float UNUSED(rot), + float UNUSED(rot_eval), int pt_index, const int radius, const int co[2]) @@ -396,7 +411,7 @@ static bool gp_brush_thickness_apply(tGP_BrushEditData *gso, /* Make color more or less transparent by the specified amounts */ static bool gp_brush_strength_apply(tGP_BrushEditData *gso, bGPDstroke *gps, - float UNUSED(rot), + float UNUSED(rot_eval), int pt_index, const int radius, const int co[2]) @@ -443,7 +458,7 @@ typedef struct tGPSB_Grab_StrokeData { /* array of influence weights for each of the included points */ float *weights; /* angles to calc transformation */ - float *rot; + float *rot_eval; /* capacity of the arrays */ int capacity; @@ -471,7 +486,7 @@ static void gp_brush_grab_stroke_init(tGP_BrushEditData *gso, bGPDstroke *gps) memset(data->points, 0, sizeof(int) * data->capacity); memset(data->weights, 0, sizeof(float) * data->capacity); - memset(data->rot, 0, sizeof(float) * data->capacity); + memset(data->rot_eval, 0, sizeof(float) * data->capacity); } else { /* Create new instance */ @@ -482,7 +497,7 @@ static void gp_brush_grab_stroke_init(tGP_BrushEditData *gso, bGPDstroke *gps) data->points = MEM_callocN(sizeof(int) * data->capacity, "GP Stroke Grab Indices"); data->weights = MEM_callocN(sizeof(float) * data->capacity, "GP Stroke Grab Weights"); - data->rot = MEM_callocN(sizeof(float) * data->capacity, "GP Stroke Grab X"); + data->rot_eval = MEM_callocN(sizeof(float) * data->capacity, "GP Stroke Grab Rotations"); /* hook up to the cache */ BLI_ghash_insert(gso->stroke_customdata, gps, data); @@ -492,7 +507,7 @@ static void gp_brush_grab_stroke_init(tGP_BrushEditData *gso, bGPDstroke *gps) /* store references to stroke points in the initial stage */ static bool gp_brush_grab_store_points(tGP_BrushEditData *gso, bGPDstroke *gps, - float rot, + float rot_eval, int pt_index, const int radius, const int co[2]) @@ -506,7 +521,7 @@ static bool gp_brush_grab_store_points(tGP_BrushEditData *gso, /* insert this point into the set of affected points */ data->points[data->size] = pt_index; data->weights[data->size] = inf; - data->rot[data->size] = rot; + data->rot_eval[data->size] = rot_eval; data->size++; /* done */ @@ -530,10 +545,10 @@ static void gp_brush_grab_calc_dvec(tGP_BrushEditData *gso) mval_f[0] = (float)(gso->mval[0] - gso->mval_prev[0]); mval_f[1] = (float)(gso->mval[1] - gso->mval_prev[1]); - /* apply derived data transformation */ - if (gso->rot != 0.0f) { - const float cval = cos(gso->rot); - const float sval = sin(gso->rot); + /* apply evaluated data transformation */ + if (gso->rot_eval != 0.0f) { + const float cval = cos(gso->rot_eval); + const float sval = sin(gso->rot_eval); float r[2]; r[0] = (mval_f[0] * cval) - (mval_f[1] * sval); r[1] = (mval_f[0] * sval) + (mval_f[1] * cval); @@ -564,8 +579,8 @@ static void gp_brush_grab_apply_cached(tGP_BrushEditData *gso, bGPDspoint *pt = &gps->points[data->points[i]]; float delta[3] = {0.0f}; - /* get derived transformation */ - gso->rot = data->rot[i]; + /* get evaluated transformation */ + gso->rot_eval = data->rot_eval[i]; gp_brush_grab_calc_dvec(gso); /* adjust the amount of displacement to apply */ @@ -586,7 +601,7 @@ static void gp_brush_grab_apply_cached(tGP_BrushEditData *gso, /* compute lock axis */ gpsculpt_compute_lock_axis(gso, pt, save_pt); } - gps->flag |= GP_STROKE_RECALC_GEOMETRY; + gp_recalc_geometry(gps); } /* free customdata used for handling this stroke */ @@ -597,7 +612,7 @@ static void gp_brush_grab_stroke_free(void *ptr) /* free arrays */ MEM_SAFE_FREE(data->points); MEM_SAFE_FREE(data->weights); - MEM_SAFE_FREE(data->rot); + MEM_SAFE_FREE(data->rot_eval); /* ... and this item itself, since it was also allocated */ MEM_freeN(data); @@ -608,7 +623,7 @@ static void gp_brush_grab_stroke_free(void *ptr) /* NOTE: Depends on gp_brush_grab_calc_dvec() */ static bool gp_brush_push_apply(tGP_BrushEditData *gso, bGPDstroke *gps, - float UNUSED(rot), + float UNUSED(rot_eval), int pt_index, const int radius, const int co[2]) @@ -676,7 +691,7 @@ static void gp_brush_calc_midpoint(tGP_BrushEditData *gso) /* Shrink distance between midpoint and this point... */ static bool gp_brush_pinch_apply(tGP_BrushEditData *gso, bGPDstroke *gps, - float UNUSED(rot), + float UNUSED(rot_eval), int pt_index, const int radius, const int co[2]) @@ -721,7 +736,7 @@ static bool gp_brush_pinch_apply(tGP_BrushEditData *gso, /* compute lock axis */ gpsculpt_compute_lock_axis(gso, pt, save_pt); - gps->flag |= GP_STROKE_RECALC_GEOMETRY; + gp_recalc_geometry(gps); /* done */ return true; @@ -735,7 +750,7 @@ static bool gp_brush_pinch_apply(tGP_BrushEditData *gso, static bool gp_brush_twist_apply(tGP_BrushEditData *gso, bGPDstroke *gps, - float UNUSED(rot), + float UNUSED(rot_eval), int pt_index, const int radius, const int co[2]) @@ -809,7 +824,7 @@ static bool gp_brush_twist_apply(tGP_BrushEditData *gso, } } - gps->flag |= GP_STROKE_RECALC_GEOMETRY; + gp_recalc_geometry(gps); /* done */ return true; @@ -820,7 +835,7 @@ static bool gp_brush_twist_apply(tGP_BrushEditData *gso, /* Apply some random jitter to the point */ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso, bGPDstroke *gps, - float UNUSED(rot), + float UNUSED(rot_eval), int pt_index, const int radius, const int co[2]) @@ -929,7 +944,7 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso, CLAMP(pt->uv_rot, -M_PI_2, M_PI_2); } - gps->flag |= GP_STROKE_RECALC_GEOMETRY; + gp_recalc_geometry(gps); /* done */ return true; @@ -939,7 +954,7 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso, /* Change weight paint for vertex groups */ static bool gp_brush_weight_apply(tGP_BrushEditData *gso, bGPDstroke *gps, - float UNUSED(rot), + float UNUSED(rot_eval), int pt_index, const int radius, const int co[2]) @@ -1175,7 +1190,7 @@ static void gp_brush_clone_adjust(tGP_BrushEditData *gso) size_t snum; /* Compute the amount of movement to apply (overwrites dvec) */ - gso->rot = 0.0f; + gso->rot_eval = 0.0f; gp_brush_grab_calc_dvec(gso); /* For each of the stored strokes, apply the offset to each point */ @@ -1323,6 +1338,9 @@ static bool gpsculpt_brush_init(bContext *C, wmOperator *op) gso->sa = CTX_wm_area(C); gso->ar = CTX_wm_region(C); + /* save mask */ + gso->mask = ts->gpencil_selectmode_sculpt; + /* multiframe settings */ gso->is_multiframe = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gso->gpd); gso->use_multiframe_falloff = (ts->gp_sculpt.flag & GP_SCULPT_SETT_FLAG_FRAME_FALLOFF) != 0; @@ -1486,35 +1504,38 @@ static void gpsculpt_brush_init_stroke(tGP_BrushEditData *gso) /* Apply ----------------------------------------------- */ -/* Get angle of the segment relative to the original segment before any transformation */ -static float gpsculpt_transform_rot_get(GP_SpaceConversion *gsc, - bGPDstroke *gps_derived, - bGPDspoint *pt_derived, - int idx_derived) +/* Get angle of the segment relative to the original segment before any transformation + * For strokes with one point only this is impossible to calculate because there isn't a + * valid reference point. + */ +static float gpsculpt_rotation_eval_get(GP_SpaceConversion *gsc, + bGPDstroke *gps_eval, + bGPDspoint *pt_eval, + int idx_eval) { - bGPDstroke *gps_orig = gps_derived->runtime.gps_orig; - bGPDspoint *pt_orig = &gps_orig->points[pt_derived->runtime.idx_orig]; - bGPDspoint *pt_derived_prev = NULL; + bGPDstroke *gps_orig = gps_eval->runtime.gps_orig; + bGPDspoint *pt_orig = &gps_orig->points[pt_eval->runtime.idx_orig]; + bGPDspoint *pt_prev_eval = NULL; bGPDspoint *pt_orig_prev = NULL; - if (idx_derived != 0) { - pt_derived_prev = &gps_derived->points[idx_derived - 1]; + if (idx_eval != 0) { + pt_prev_eval = &gps_eval->points[idx_eval - 1]; } else { - if (gps_derived->totpoints > 1) { - pt_derived_prev = &gps_derived->points[idx_derived + 1]; + if (gps_eval->totpoints > 1) { + pt_prev_eval = &gps_eval->points[idx_eval + 1]; } else { return 0.0f; } } - if (pt_derived->runtime.idx_orig != 0) { - pt_orig_prev = &gps_orig->points[pt_derived->runtime.idx_orig - 1]; + if (pt_eval->runtime.idx_orig != 0) { + pt_orig_prev = &gps_orig->points[pt_eval->runtime.idx_orig - 1]; } else { if (gps_orig->totpoints > 1) { - pt_orig_prev = &gps_orig->points[pt_derived->runtime.idx_orig + 1]; + pt_orig_prev = &gps_orig->points[pt_eval->runtime.idx_orig + 1]; } else { return 0.0f; @@ -1522,17 +1543,17 @@ static float gpsculpt_transform_rot_get(GP_SpaceConversion *gsc, } /* create 2D vectors of the stroke segments */ - float v_orig_a[2], v_orig_b[2], v_derived_a[2], v_derived_b[2]; + float v_orig_a[2], v_orig_b[2], v_eval_a[2], v_eval_b[2]; gp_point_3d_to_xy(gsc, GP_STROKE_3DSPACE, &pt_orig->x, v_orig_a); gp_point_3d_to_xy(gsc, GP_STROKE_3DSPACE, &pt_orig_prev->x, v_orig_b); sub_v2_v2(v_orig_a, v_orig_b); - gp_point_3d_to_xy(gsc, GP_STROKE_3DSPACE, &pt_derived->x, v_derived_a); - gp_point_3d_to_xy(gsc, GP_STROKE_3DSPACE, &pt_derived_prev->x, v_derived_b); - sub_v2_v2(v_derived_a, v_derived_b); + gp_point_3d_to_xy(gsc, GP_STROKE_3DSPACE, &pt_eval->x, v_eval_a); + gp_point_3d_to_xy(gsc, GP_STROKE_3DSPACE, &pt_prev_eval->x, v_eval_b); + sub_v2_v2(v_eval_a, v_eval_b); - return angle_v2v2(v_orig_a, v_derived_a); + return angle_v2v2(v_orig_a, v_eval_a); } /* Apply brush operation to points in this stroke */ @@ -1555,7 +1576,7 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso, int i; bool include_last = false; bool changed = false; - float rot = 0.0f; + float rot_eval = 0.0f; if (gps->totpoints == 1) { bGPDspoint pt_temp; pt = &gps->points[0]; @@ -1570,8 +1591,8 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso, if (len_v2v2_int(mval_i, pc1) <= radius) { /* apply operation to this point */ if (pt->runtime.pt_orig != NULL) { - rot = gpsculpt_transform_rot_get(&gso->gsc, gps, pt, 0); - changed = apply(gso, gps->runtime.gps_orig, rot, pt->runtime.idx_orig, radius, pc1); + rot_eval = gpsculpt_rotation_eval_get(&gso->gsc, gps, pt, 0); + changed = apply(gso, gps->runtime.gps_orig, rot_eval, pt->runtime.idx_orig, radius, pc1); } } } @@ -1587,7 +1608,7 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso, /* Skip if neither one is selected * (and we are only allowed to edit/consider selected points) */ - if ((gso->settings->flag & GP_SCULPT_SETT_FLAG_SELECT_MASK) && (!gso->is_weight_mode)) { + if ((GPENCIL_ANY_SCULPT_MASK(gso->mask)) && (!gso->is_weight_mode)) { if (!(pt1->flag & GP_SPOINT_SELECT) && !(pt2->flag & GP_SPOINT_SELECT)) { include_last = false; continue; @@ -1615,8 +1636,8 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso, /* To each point individually... */ pt = &gps->points[i]; if (pt->runtime.pt_orig != NULL) { - rot = gpsculpt_transform_rot_get(&gso->gsc, gps, pt, i); - ok = apply(gso, gps->runtime.gps_orig, rot, pt->runtime.idx_orig, radius, pc1); + rot_eval = gpsculpt_rotation_eval_get(&gso->gsc, gps, pt, i); + ok = apply(gso, gps->runtime.gps_orig, rot_eval, pt->runtime.idx_orig, radius, pc1); } /* Only do the second point if this is the last segment, @@ -1630,8 +1651,8 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso, if (i + 1 == gps->totpoints - 1) { pt = &gps->points[i + 1]; if (pt->runtime.pt_orig != NULL) { - rot = gpsculpt_transform_rot_get(&gso->gsc, gps, pt, i + 1); - ok |= apply(gso, gps->runtime.gps_orig, rot, pt->runtime.idx_orig, radius, pc2); + rot_eval = gpsculpt_rotation_eval_get(&gso->gsc, gps, pt, i + 1); + ok |= apply(gso, gps->runtime.gps_orig, rot_eval, pt->runtime.idx_orig, radius, pc2); include_last = false; } } @@ -1649,8 +1670,9 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso, */ pt = &gps->points[i]; if (pt->runtime.pt_orig != NULL) { - rot = gpsculpt_transform_rot_get(&gso->gsc, gps, pt, i); - changed |= apply(gso, gps->runtime.gps_orig, rot, pt->runtime.idx_orig, radius, pc1); + rot_eval = gpsculpt_rotation_eval_get(&gso->gsc, gps, pt, i); + changed |= apply( + gso, gps->runtime.gps_orig, rot_eval, pt->runtime.idx_orig, radius, pc1); include_last = false; } } @@ -1752,10 +1774,7 @@ static bool gpsculpt_brush_do_frame( break; } /* Triangulation must be calculated if changed */ - if (changed) { - gps->flag |= GP_STROKE_RECALC_GEOMETRY; - gps->tot_triangles = 0; - } + gp_recalc_geometry(gps); } return changed; @@ -1777,7 +1796,7 @@ static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso) case GP_SCULPT_TYPE_PUSH: /* Push points */ { /* calculate amount of displacement to apply */ - gso->rot = 0.0f; + gso->rot_eval = 0.0f; gp_brush_grab_calc_dvec(gso); break; } @@ -1793,7 +1812,7 @@ static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso) case GP_SCULPT_TYPE_RANDOMIZE: /* Random jitter */ { /* compute the displacement vector for the cursor (in data space) */ - gso->rot = 0.0f; + gso->rot_eval = 0.0f; gp_brush_grab_calc_dvec(gso); break; } @@ -1808,10 +1827,10 @@ static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso) if (gpl->actframe == NULL) { continue; } - /* Get derived frames array data */ - int derived_idx = BLI_findindex(&gpd->layers, gpl); - bGPDframe *derived_gpf = &ob_eval->runtime.derived_frames[derived_idx]; - if (derived_gpf == NULL) { + /* Get evaluated frames array data */ + int idx_eval = BLI_findindex(&gpd->layers, gpl); + bGPDframe *gpf_eval = &ob_eval->runtime.gpencil_evaluated_frames[idx_eval]; + if (gpf_eval == NULL) { continue; } @@ -1845,14 +1864,14 @@ static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso) /* affect strokes in this frame */ changed |= gpsculpt_brush_do_frame( - C, gso, gpl, (gpf == gpl->actframe) ? derived_gpf : gpf, diff_mat); + C, gso, gpl, (gpf == gpl->actframe) ? gpf_eval : gpf, diff_mat); } } } else { /* Apply to active frame's strokes */ gso->mf_falloff = 1.0f; - changed |= gpsculpt_brush_do_frame(C, gso, gpl, derived_gpf, diff_mat); + changed |= gpsculpt_brush_do_frame(C, gso, gpl, gpf_eval, diff_mat); } } CTX_DATA_END; diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c index 0928913aad5..e763eec1b0d 100644 --- a/source/blender/editors/gpencil/gpencil_data.c +++ b/source/blender/editors/gpencil/gpencil_data.c @@ -105,7 +105,7 @@ static bool gp_data_add_poll(bContext *C) /* add new datablock - wrapper around API */ static int gp_data_add_exec(bContext *C, wmOperator *op) { - PointerRNA gpd_owner = {{NULL}}; + PointerRNA gpd_owner = {NULL}; bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, &gpd_owner); bool is_annotation = ED_gpencil_data_owner_is_annotation(&gpd_owner); @@ -231,7 +231,7 @@ void GPENCIL_OT_data_unlink(wmOperatorType *ot) /* add new layer - wrapper around API */ static int gp_layer_add_exec(bContext *C, wmOperator *op) { - PointerRNA gpd_owner = {{NULL}}; + PointerRNA gpd_owner = {NULL}; bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, &gpd_owner); bool is_annotation = ED_gpencil_data_owner_is_annotation(&gpd_owner); @@ -538,10 +538,12 @@ static int gp_layer_duplicate_object_exec(bContext *C, wmOperator *op) * otherwise add the slot with the material */ Material *ma_src = give_current_material(ob_src, gps_src->mat_nr + 1); - int idx = BKE_gpencil_object_material_ensure(bmain, ob_dst, ma_src); + if (ma_src != NULL) { + int idx = BKE_gpencil_object_material_ensure(bmain, ob_dst, ma_src); - /* Reassign the stroke material to the right slot in destination object. */ - gps_dst->mat_nr = idx; + /* Reassign the stroke material to the right slot in destination object. */ + gps_dst->mat_nr = idx; + } /* add new stroke to frame */ BLI_addtail(&gpf_dst->strokes, gps_dst); @@ -840,6 +842,10 @@ static int gp_hide_exec(bContext *C, wmOperator *op) if (gpl != layer) { gpl->flag |= GP_LAYER_HIDE; } + else { + /* Be sure the active layer is unhidden. */ + gpl->flag &= ~GP_LAYER_HIDE; + } } } else { @@ -1419,7 +1425,7 @@ static int gp_stroke_change_color_exec(bContext *C, wmOperator *op) bGPdata *gpd = ED_gpencil_data_get_active(C); Object *ob = CTX_data_active_object(C); if (name[0] == '\0') { - ma = give_current_material(ob, ob->actcol); + ma = BKE_material_gpencil_get(ob, ob->actcol); } else { ma = (Material *)BKE_libblock_find_name(bmain, ID_MA, name); @@ -1539,9 +1545,10 @@ static int gp_stroke_lock_color_exec(bContext *C, wmOperator *UNUSED(op)) } /* unlock color */ Material *tmp_ma = give_current_material(ob, gps->mat_nr + 1); - - tmp_ma->gp_style->flag &= ~GP_STYLE_COLOR_LOCKED; - DEG_id_tag_update(&tmp_ma->id, ID_RECALC_COPY_ON_WRITE); + if (tmp_ma) { + tmp_ma->gp_style->flag &= ~GP_STYLE_COLOR_LOCKED; + DEG_id_tag_update(&tmp_ma->id, ID_RECALC_COPY_ON_WRITE); + } } } } @@ -2291,7 +2298,7 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op) short *totcol = give_totcolp(ob_src); for (short i = 0; i < *totcol; i++) { - Material *tmp_ma = give_current_material(ob_src, i + 1); + Material *tmp_ma = BKE_material_gpencil_get(ob_src, i + 1); BKE_gpencil_object_material_ensure(bmain, ob_dst, tmp_ma); } @@ -2325,7 +2332,7 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op) for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { /* Reassign material. Look old material and try to find in destination. */ - ma_src = give_current_material(ob_src, gps->mat_nr + 1); + ma_src = BKE_material_gpencil_get(ob_src, gps->mat_nr + 1); gps->mat_nr = BKE_gpencil_object_material_ensure(bmain, ob_dst, ma_src); bGPDspoint *pt; @@ -2433,7 +2440,7 @@ static int gpencil_lock_layer_exec(bContext *C, wmOperator *UNUSED(op)) } for (short i = 0; i < *totcol; i++) { - ma = give_current_material(ob, i + 1); + ma = BKE_material_gpencil_get(ob, i + 1); if (ma) { gp_style = ma->gp_style; gp_style->flag |= GP_STYLE_COLOR_LOCKED; @@ -2453,7 +2460,7 @@ static int gpencil_lock_layer_exec(bContext *C, wmOperator *UNUSED(op)) continue; } - ma = give_current_material(ob, gps->mat_nr + 1); + ma = BKE_material_gpencil_get(ob, gps->mat_nr + 1); DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE); gp_style = ma->gp_style; @@ -2496,7 +2503,7 @@ static int gpencil_color_isolate_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); Object *ob = CTX_data_active_object(C); - Material *active_ma = give_current_material(ob, ob->actcol); + Material *active_ma = BKE_material_gpencil_get(ob, ob->actcol); MaterialGPencilStyle *active_color = BKE_material_gpencil_settings_get(ob, ob->actcol); MaterialGPencilStyle *gp_style; @@ -2516,7 +2523,7 @@ static int gpencil_color_isolate_exec(bContext *C, wmOperator *op) Material *ma = NULL; short *totcol = give_totcolp(ob); for (short i = 0; i < *totcol; i++) { - ma = give_current_material(ob, i + 1); + ma = BKE_material_gpencil_get(ob, i + 1); /* Skip if this is the active one */ if ((ma == NULL) || (ma == active_ma)) { continue; @@ -2536,7 +2543,7 @@ static int gpencil_color_isolate_exec(bContext *C, wmOperator *op) if (isolate) { /* Set flags on all "other" colors */ for (short i = 0; i < *totcol; i++) { - ma = give_current_material(ob, i + 1); + ma = BKE_material_gpencil_get(ob, i + 1); if (ma == NULL) { continue; } @@ -2553,7 +2560,7 @@ static int gpencil_color_isolate_exec(bContext *C, wmOperator *op) else { /* Clear flags - Restore everything else */ for (short i = 0; i < *totcol; i++) { - ma = give_current_material(ob, i + 1); + ma = BKE_material_gpencil_get(ob, i + 1); if (ma == NULL) { continue; } @@ -2618,7 +2625,7 @@ static int gpencil_color_hide_exec(bContext *C, wmOperator *op) /* hide unselected */ MaterialGPencilStyle *color = NULL; for (short i = 0; i < *totcol; i++) { - ma = give_current_material(ob, i + 1); + ma = BKE_material_gpencil_get(ob, i + 1); if (ma) { color = ma->gp_style; if (active_color != color) { @@ -2681,7 +2688,7 @@ static int gpencil_color_reveal_exec(bContext *C, wmOperator *UNUSED(op)) MaterialGPencilStyle *gp_style = NULL; for (short i = 0; i < *totcol; i++) { - ma = give_current_material(ob, i + 1); + ma = BKE_material_gpencil_get(ob, i + 1); if (ma) { gp_style = ma->gp_style; gp_style->flag &= ~GP_STYLE_COLOR_HIDE; @@ -2734,7 +2741,7 @@ static int gpencil_color_lock_all_exec(bContext *C, wmOperator *UNUSED(op)) MaterialGPencilStyle *gp_style = NULL; for (short i = 0; i < *totcol; i++) { - ma = give_current_material(ob, i + 1); + ma = BKE_material_gpencil_get(ob, i + 1); if (ma) { gp_style = ma->gp_style; gp_style->flag |= GP_STYLE_COLOR_LOCKED; @@ -2787,7 +2794,7 @@ static int gpencil_color_unlock_all_exec(bContext *C, wmOperator *UNUSED(op)) MaterialGPencilStyle *gp_style = NULL; for (short i = 0; i < *totcol; i++) { - ma = give_current_material(ob, i + 1); + ma = BKE_material_gpencil_get(ob, i + 1); if (ma) { gp_style = ma->gp_style; gp_style->flag &= ~GP_STYLE_COLOR_LOCKED; diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index cc229fcb383..12b3792e36e 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -222,6 +222,17 @@ void GPENCIL_OT_editmode_toggle(wmOperatorType *ot) } /* set select mode */ +static bool gpencil_selectmode_toggle_poll(bContext *C) +{ + /* edit only supported with grease pencil objects */ + Object *ob = CTX_data_active_object(C); + if ((ob == NULL) || (ob->type != OB_GPENCIL) || (ob->mode != OB_MODE_EDIT_GPENCIL)) { + return false; + } + + return ED_operator_view3d_active(C); +} + static int gpencil_selectmode_toggle_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); @@ -229,7 +240,7 @@ static int gpencil_selectmode_toggle_exec(bContext *C, wmOperator *op) const int mode = RNA_int_get(op->ptr, "mode"); /* Just set mode */ - ts->gpencil_selectmode = mode; + ts->gpencil_selectmode_edit = mode; WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, NULL); DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); @@ -248,7 +259,7 @@ void GPENCIL_OT_selectmode_toggle(wmOperatorType *ot) /* callbacks */ ot->exec = gpencil_selectmode_toggle_exec; - ot->poll = gp_strokes_edit3d_poll; + ot->poll = gpencil_selectmode_toggle_poll; /* flags */ ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER; @@ -1180,10 +1191,15 @@ static int gp_strokes_copy_exec(bContext *C, wmOperator *op) GHash *ma_to_name = gp_strokes_copypastebuf_colors_material_to_name_create(bmain); for (bGPDstroke *gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) { if (ED_gpencil_stroke_can_use(C, gps)) { + Material *ma = give_current_material(ob, gps->mat_nr + 1); + /* Avoid default material. */ + if (ma == NULL) { + continue; + } + char **ma_name_val; if (!BLI_ghash_ensure_p( gp_strokes_copypastebuf_colors, &gps->mat_nr, (void ***)&ma_name_val)) { - Material *ma = give_current_material(ob, gps->mat_nr + 1); char *ma_name = BLI_ghash_lookup(ma_to_name, ma); *ma_name_val = MEM_dupallocN(ma_name); } @@ -1230,8 +1246,8 @@ static bool gp_strokes_paste_poll(bContext *C) } typedef enum eGP_PasteMode { - GP_COPY_ONLY = -1, - GP_COPY_MERGE = 1, + GP_COPY_BY_LAYER = -1, + GP_COPY_TO_ACTIVE = 1, } eGP_PasteMode; static int gp_strokes_paste_exec(bContext *C, wmOperator *op) @@ -1264,7 +1280,7 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op) /* no active layer - let's just create one */ gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true); } - else if ((gpencil_layer_is_editable(gpl) == false) && (type == GP_COPY_MERGE)) { + else if ((gpencil_layer_is_editable(gpl) == false) && (type == GP_COPY_TO_ACTIVE)) { BKE_report( op->reports, RPT_ERROR, "Can not paste strokes when active layer is hidden or locked"); return OPERATOR_CANCELLED; @@ -1317,7 +1333,7 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op) for (bGPDstroke *gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) { if (ED_gpencil_stroke_can_use(C, gps)) { /* Need to verify if layer exists */ - if (type != GP_COPY_MERGE) { + if (type != GP_COPY_TO_ACTIVE) { gpl = BLI_findstring(&gpd->layers, gps->runtime.tmp_layerinfo, offsetof(bGPDlayer, info)); if (gpl == NULL) { /* no layer - use active (only if layer deleted before paste) */ @@ -1350,7 +1366,7 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op) /* Remap material */ Material *ma = BLI_ghash_lookup(new_colors, POINTER_FROM_INT(new_stroke->mat_nr)); new_stroke->mat_nr = BKE_gpencil_object_material_get_index(ob, ma); - BLI_assert(new_stroke->mat_nr >= 0); /* have to add the material first */ + CLAMP_MIN(new_stroke->mat_nr, 0); } } } @@ -1368,15 +1384,15 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op) void GPENCIL_OT_paste(wmOperatorType *ot) { static const EnumPropertyItem copy_type[] = { - {GP_COPY_ONLY, "COPY", 0, "Copy", ""}, - {GP_COPY_MERGE, "MERGE", 0, "Merge", ""}, + {GP_COPY_TO_ACTIVE, "ACTIVE", 0, "Paste to Active", ""}, + {GP_COPY_BY_LAYER, "LAYER", 0, "Paste by Layer", ""}, {0, NULL, 0, NULL, NULL}, }; /* identifiers */ ot->name = "Paste Strokes"; ot->idname = "GPENCIL_OT_paste"; - ot->description = "Paste previously copied strokes or copy and merge in active layer"; + ot->description = "Paste previously copied strokes to active layer or to original layer"; /* callbacks */ ot->exec = gp_strokes_paste_exec; @@ -1386,33 +1402,18 @@ void GPENCIL_OT_paste(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ - ot->prop = RNA_def_enum(ot->srna, "type", copy_type, 0, "Type", ""); + ot->prop = RNA_def_enum(ot->srna, "type", copy_type, GP_COPY_TO_ACTIVE, "Type", ""); } /* ******************* Move To Layer ****************************** */ -static int gp_move_to_layer_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(evt)) -{ - uiPopupMenu *pup; - uiLayout *layout; - - /* call the menu, which will call this operator again, hence the canceled */ - pup = UI_popup_menu_begin(C, op->type->name, ICON_NONE); - layout = UI_popup_menu_layout(pup); - uiItemsEnumO(layout, "GPENCIL_OT_move_to_layer", "layer"); - UI_popup_menu_end(C, pup); - - return OPERATOR_INTERFACE; -} - -// FIXME: allow moving partial strokes static int gp_move_to_layer_exec(bContext *C, wmOperator *op) { bGPdata *gpd = CTX_data_gpencil_data(C); Scene *scene = CTX_data_scene(C); bGPDlayer *target_layer = NULL; ListBase strokes = {NULL, NULL}; - int layer_num = RNA_enum_get(op->ptr, "layer"); + int layer_num = RNA_int_get(op->ptr, "layer"); const bool use_autolock = (bool)(gpd->flag & GP_DATA_AUTOLOCK_LAYERS); if (GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)) { @@ -1425,23 +1426,16 @@ static int gp_move_to_layer_exec(bContext *C, wmOperator *op) gpd->flag &= ~GP_DATA_AUTOLOCK_LAYERS; } - /* Get layer or create new one */ - if (layer_num == -1) { - /* Create layer */ - target_layer = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true); - } - else { - /* Try to get layer */ - target_layer = BLI_findlink(&gpd->layers, layer_num); + /* Try to get layer */ + target_layer = BLI_findlink(&gpd->layers, layer_num); - if (target_layer == NULL) { - /* back autolock status */ - if (use_autolock) { - gpd->flag |= GP_DATA_AUTOLOCK_LAYERS; - } - BKE_reportf(op->reports, RPT_ERROR, "There is no layer number %d", layer_num); - return OPERATOR_CANCELLED; + if (target_layer == NULL) { + /* back autolock status */ + if (use_autolock) { + gpd->flag |= GP_DATA_AUTOLOCK_LAYERS; } + BKE_reportf(op->reports, RPT_ERROR, "There is no layer number %d", layer_num); + return OPERATOR_CANCELLED; } /* Extract all strokes to move to this layer @@ -1509,16 +1503,14 @@ void GPENCIL_OT_move_to_layer(wmOperatorType *ot) "Move selected strokes to another layer"; // XXX: allow moving individual points too? /* callbacks */ - ot->invoke = gp_move_to_layer_invoke; ot->exec = gp_move_to_layer_exec; ot->poll = gp_stroke_edit_poll; // XXX? /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* gp layer to use (dynamic enum) */ - ot->prop = RNA_def_enum(ot->srna, "layer", DummyRNA_DEFAULT_items, 0, "Grease Pencil Layer", ""); - RNA_def_enum_funcs(ot->prop, ED_gpencil_layers_with_new_enum_itemf); + /* GPencil layer to use. */ + ot->prop = RNA_def_int(ot->srna, "layer", 0, 0, INT_MAX, "Grease Pencil Layer", "", 0, INT_MAX); } /* ********************* Add Blank Frame *************************** */ @@ -3333,7 +3325,7 @@ typedef enum eGP_ReprojectModes { GP_REPROJECT_FRONT = 0, GP_REPROJECT_SIDE, GP_REPROJECT_TOP, - /* On same plane, parallel to viewplane */ + /* On same plane, parallel to view-plane. */ GP_REPROJECT_VIEW, /* Reprojected on to the scene geometry */ GP_REPROJECT_SURFACE, @@ -3344,11 +3336,14 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); Scene *scene = CTX_data_scene(C); + Main *bmain = CTX_data_main(C); ToolSettings *ts = CTX_data_tool_settings(C); Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); Object *ob = CTX_data_active_object(C); ARegion *ar = CTX_wm_region(C); RegionView3D *rv3d = ar->regiondata; + SnapObjectContext *sctx = NULL; + int oldframe = (int)DEG_get_ctime(depsgraph); GP_SpaceConversion gsc = {NULL}; eGP_ReprojectModes mode = RNA_enum_get(op->ptr, "type"); @@ -3358,28 +3353,33 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op) /* init space conversion stuff */ gp_point_conversion_init(C, &gsc); - /* init autodist for geometry projection */ - if (mode == GP_REPROJECT_SURFACE) { - view3d_region_operator_needs_opengl(CTX_wm_window(C), gsc.ar); - ED_view3d_autodist_init(depsgraph, gsc.ar, CTX_wm_view3d(C), 0); - } - - // TODO: For deforming geometry workflow, create new frames? + int cfra_prv = INT_MIN; + /* init snap context for geometry projection */ + sctx = ED_transform_snap_object_context_create_view3d( + bmain, scene, depsgraph, 0, ar, CTX_wm_view3d(C)); /* Go through each editable + selected stroke, adjusting each of its points one by one... */ GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) { if (gps->flag & GP_STROKE_SELECT) { + + /* update frame to get the new location of objects */ + if ((mode == GP_REPROJECT_SURFACE) && (cfra_prv != gpf_->framenum)) { + cfra_prv = gpf_->framenum; + CFRA = gpf_->framenum; + BKE_scene_graph_update_for_newframe(depsgraph, bmain); + } + bGPDspoint *pt; int i; /* Adjust each point */ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { float xy[2]; - /* 3D to Screenspace */ - /* Note: We can't use gp_point_to_xy() here because that uses ints for the screenspace - * coordinates, resulting in lost precision, which in turn causes stairstepping - * artifacts in the final points. - */ + /* 3D to Screen-space */ + /* Note: We can't use gp_point_to_xy() here because that uses ints for the screen-space + * coordinates, resulting in lost precision, which in turn causes stair-stepping + * artifacts in the final points. */ + bGPDspoint pt2; gp_point_to_parent_space(pt, gpstroke_iter.diff_mat, &pt2); gp_point_to_xy_fl(&gsc, gps, &pt2, &xy[0], &xy[1]); @@ -3428,26 +3428,34 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op) /* apply parent again */ gp_apply_parent_point(depsgraph, ob, gpd, gpl, pt); } - /* Project screenspace back to 3D space (from current perspective) - * so that all points have been treated the same way - */ + /* Project screen-space back to 3D space (from current perspective) + * so that all points have been treated the same way. */ else if (mode == GP_REPROJECT_VIEW) { - /* Planar - All on same plane parallel to the viewplane */ + /* Planar - All on same plane parallel to the view-plane. */ gp_point_xy_to_3d(&gsc, scene, xy, &pt->x); } else { /* Geometry - Snap to surfaces of visible geometry */ - /* XXX: There will be precision loss (possible stairstep artifacts) - * from this conversion to satisfy the API's */ - const int screen_co[2] = {(int)xy[0], (int)xy[1]}; - - int depth_margin = 0; // XXX: 4 for strokes, 0 for normal - float depth; - - /* XXX: The proper procedure computes the depths into an array, - * to have smooth transitions when all else fails... */ - if (ED_view3d_autodist_depth(gsc.ar, screen_co, depth_margin, &depth)) { - ED_view3d_autodist_simple(gsc.ar, screen_co, &pt->x, 0, &depth); + float ray_start[3]; + float ray_normal[3]; + /* magic value for initial depth copied from the default + * value of Python's Scene.ray_cast function + */ + float depth = 1.70141e+38f; + float location[3] = {0.0f, 0.0f, 0.0f}; + float normal[3] = {0.0f, 0.0f, 0.0f}; + + ED_view3d_win_to_ray(ar, xy, &ray_start[0], &ray_normal[0]); + if (ED_transform_snap_object_project_ray(sctx, + &(const struct SnapObjectParams){ + .snap_select = SNAP_ALL, + }, + &ray_start[0], + &ray_normal[0], + &depth, + &location[0], + &normal[0])) { + copy_v3_v3(&pt->x, location); } else { /* Default to planar */ @@ -3464,6 +3472,15 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op) } GP_EDITABLE_STROKES_END(gpstroke_iter); + /* return frame state and DB to original state */ + CFRA = oldframe; + BKE_scene_graph_update_for_newframe(depsgraph, bmain); + + if (sctx != NULL) { + ED_transform_snap_object_context_destroy(sctx); + } + + /* update changed data */ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); return OPERATOR_FINISHED; @@ -3549,7 +3566,7 @@ static void gp_smooth_stroke(bContext *C, wmOperator *op) } if (smooth_thickness) { /* thickness need to repeat process several times */ - for (int r2 = 0; r2 < r * 10; r2++) { + for (int r2 = 0; r2 < r * 20; r2++) { BKE_gpencil_smooth_stroke_thickness(gps, i, factor); } } @@ -4055,7 +4072,7 @@ static int gp_stroke_separate_exec(bContext *C, wmOperator *op) /* add duplicate materials */ /* XXX same material can be in multiple slots. */ - ma = give_current_material(ob, gps->mat_nr + 1); + ma = BKE_material_gpencil_get(ob, gps->mat_nr + 1); idx = BKE_gpencil_object_material_ensure(bmain, ob_dst, ma); @@ -4128,7 +4145,7 @@ static int gp_stroke_separate_exec(bContext *C, wmOperator *op) if (ED_gpencil_stroke_can_use(C, gps) == false) { continue; } - ma = give_current_material(ob, gps->mat_nr + 1); + ma = BKE_material_gpencil_get(ob, gps->mat_nr + 1); gps->mat_nr = BKE_gpencil_object_material_ensure(bmain, ob_dst, ma); } } @@ -4305,7 +4322,7 @@ void GPENCIL_OT_stroke_smooth(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ - prop = RNA_def_int(ot->srna, "repeat", 1, 1, 10, "Repeat", "", 1, 5); + prop = RNA_def_int(ot->srna, "repeat", 1, 1, 50, "Repeat", "", 1, 20); RNA_def_property_flag(prop, PROP_SKIP_SAVE); RNA_def_float(ot->srna, "factor", 0.5f, 0.0f, 2.0f, "Factor", "", 0.0f, 2.0f); @@ -4441,7 +4458,7 @@ static int gpencil_cutter_lasso_select(bContext *C, if ((pt->flag & GP_SPOINT_SELECT) || (pt->flag & GP_SPOINT_TAG)) { continue; } - /* convert point coords to screenspace */ + /* convert point coords to screen-space */ const bool is_inside = is_inside_fn(gps, pt, &gsc, gpstroke_iter.diff_mat, user_data); if (is_inside) { tot_inside++; diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c index 5637e755198..372973e1040 100644 --- a/source/blender/editors/gpencil/gpencil_fill.c +++ b/source/blender/editors/gpencil/gpencil_fill.c @@ -48,6 +48,7 @@ #include "BKE_context.h" #include "BKE_screen.h" #include "BKE_paint.h" +#include "BKE_report.h" #include "ED_gpencil.h" #include "ED_screen.h" @@ -1038,7 +1039,15 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf) gps->flag |= GP_STROKE_CYCLIC; gps->flag |= GP_STROKE_3DSPACE; - gps->mat_nr = BKE_gpencil_object_material_ensure(tgpf->bmain, tgpf->ob, tgpf->mat); + gps->mat_nr = BKE_gpencil_object_material_get_index_from_brush(tgpf->ob, brush); + if (gps->mat_nr < 0) { + if (tgpf->ob->actcol - 1 < 0) { + gps->mat_nr = 0; + } + else { + gps->mat_nr = tgpf->ob->actcol - 1; + } + } /* allocate memory for storage points */ gps->totpoints = tgpf->sbuffer_used; @@ -1346,8 +1355,28 @@ static int gpencil_fill_init(bContext *C, wmOperator *op) /* start of interactive part of operator */ static int gpencil_fill_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { + Object *ob = CTX_data_active_object(C); + ToolSettings *ts = CTX_data_tool_settings(C); + Brush *brush = BKE_paint_brush(&ts->gp_paint->paint); tGPDfill *tgpf = NULL; + /* Fill tool needs a material (cannot use default material) */ + bool valid = true; + if ((brush) && (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED)) { + if (brush->gpencil_settings->material == NULL) { + valid = false; + } + } + else { + if (give_current_material(ob, ob->actcol) == NULL) { + valid = false; + } + } + if (!valid) { + BKE_report(op->reports, RPT_ERROR, "Fill tool needs active material."); + return OPERATOR_CANCELLED; + } + /* try to initialize context data needed */ if (!gpencil_fill_init(C, op)) { gpencil_fill_exit(C, op); diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h index 7f36eb50802..f7fc7e34460 100644 --- a/source/blender/editors/gpencil/gpencil_intern.h +++ b/source/blender/editors/gpencil/gpencil_intern.h @@ -637,8 +637,12 @@ struct GP_EditableStrokes_Iter { } \ (void)0 +#define GPENCIL_ANY_SCULPT_MASK(flag) \ + ((flag & (GP_SCULPT_MASK_SELECTMODE_POINT | GP_SCULPT_MASK_SELECTMODE_STROKE | \ + GP_SCULPT_MASK_SELECTMODE_SEGMENT))) + /** - * Iterate over all editable strokes using derived data in the current context, + * Iterate over all editable strokes using evaluated data in the current context, * stopping on each usable layer + stroke pair (i.e. gpl and gps) * to perform some operations on the stroke. * @@ -647,15 +651,15 @@ struct GP_EditableStrokes_Iter { * \param gps: The identifier to use for current stroke being processed. * Choose a suitable value to avoid name clashes. */ -#define GP_DERIVED_STROKES_BEGIN(gpstroke_iter, C, gpl, gps) \ +#define GP_EVALUATED_STROKES_BEGIN(gpstroke_iter, C, gpl, gps) \ { \ struct GP_EditableStrokes_Iter gpstroke_iter = {{{0}}}; \ - Depsgraph *depsgraph_ = CTX_data_depsgraph_pointer(C); \ + Depsgraph *depsgraph_ = CTX_data_ensure_evaluated_depsgraph(C); \ Object *obact_ = CTX_data_active_object(C); \ Object *obeval_ = DEG_get_evaluated_object(depsgraph_, obact_); \ bGPdata *gpd_ = CTX_data_gpencil_data(C); \ const bool is_multiedit_ = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd_); \ - int derived_idx = 0; \ + int idx_eval = 0; \ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { \ if (gpencil_layer_is_editable(gpl)) { \ bGPDframe *init_gpf_ = gpl->actframe; \ @@ -665,10 +669,11 @@ struct GP_EditableStrokes_Iter { for (bGPDframe *gpf_ = init_gpf_; gpf_; gpf_ = gpf_->next) { \ if ((gpf_ == gpl->actframe) || ((gpf_->flag & GP_FRAME_SELECT) && is_multiedit_)) { \ ED_gpencil_parent_location(depsgraph_, obact_, gpd_, gpl, gpstroke_iter.diff_mat); \ - /* get derived frame with modifiers applied */ \ - bGPDframe *derived_gpf_ = &obeval_->runtime.derived_frames[derived_idx]; \ + invert_m4_m4(gpstroke_iter.inverse_diff_mat, gpstroke_iter.diff_mat); \ + /* get evaluated frame with modifiers applied */ \ + bGPDframe *gpf_eval_ = &obeval_->runtime.gpencil_evaluated_frames[idx_eval]; \ /* loop over strokes */ \ - for (bGPDstroke *gps = derived_gpf_->strokes.first; gps; gps = gps->next) { \ + for (bGPDstroke *gps = gpf_eval_->strokes.first; gps; gps = gps->next) { \ /* skip strokes that are invalid for current view */ \ if (ED_gpencil_stroke_can_use(C, gps) == false) \ continue; \ @@ -677,7 +682,7 @@ struct GP_EditableStrokes_Iter { continue; \ /* ... Do Stuff With Strokes ... */ -#define GP_DERIVED_STROKES_END(gpstroke_iter) \ +#define GP_EVALUATED_STROKES_END(gpstroke_iter) \ } \ } \ if (!is_multiedit_) { \ @@ -685,7 +690,7 @@ struct GP_EditableStrokes_Iter { } \ } \ } \ - derived_idx++; \ + idx_eval++; \ } \ } \ (void)0 diff --git a/source/blender/editors/gpencil/gpencil_merge.c b/source/blender/editors/gpencil/gpencil_merge.c index cb11bb4cd63..930911ffac5 100644 --- a/source/blender/editors/gpencil/gpencil_merge.c +++ b/source/blender/editors/gpencil/gpencil_merge.c @@ -449,7 +449,7 @@ static bool gp_strokes_merge_poll(bContext *C) /* check material */ Material *ma = NULL; - ma = give_current_material(ob, ob->actcol); + ma = BKE_material_gpencil_get(ob, ob->actcol); if ((ma == NULL) || (ma->gp_style == NULL)) { return false; } diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index a5425d64c2e..3217c94eebd 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -423,7 +423,7 @@ static void gp_stroke_convertcoords(tGPsdata *p, const float mval[2], float out[ /* add small offset to keep stroke over the surface */ if ((depth) && (gpd->zdepth_offset > 0.0f) && (*p->align_flag & GP_PROJECT_DEPTH_VIEW)) { - *depth *= (1.0f - gpd->zdepth_offset); + *depth *= (1.0f - (gpd->zdepth_offset / 1000.0f)); } int mval_i[2]; @@ -563,7 +563,7 @@ static void gp_brush_angle(bGPdata *gpd, Brush *brush, tGPspoint *pt, const floa static void gp_smooth_buffer(tGPsdata *p, float inf, int idx) { bGPdata *gpd = p->gpd; - short num_points = gpd->runtime.sbuffer_used; + const short num_points = gpd->runtime.sbuffer_used; /* Do nothing if not enough points to smooth out */ if ((num_points < 3) || (idx < 3) || (inf == 0.0f)) { @@ -571,10 +571,7 @@ static void gp_smooth_buffer(tGPsdata *p, float inf, int idx) } tGPspoint *points = (tGPspoint *)gpd->runtime.sbuffer; - float steps = 4.0f; - if (idx < 4) { - steps--; - } + const float steps = (idx < 4) ? 3.0f : 4.0f; tGPspoint *pta = idx >= 4 ? &points[idx - 4] : NULL; tGPspoint *ptb = idx >= 3 ? &points[idx - 3] : NULL; @@ -583,29 +580,36 @@ static void gp_smooth_buffer(tGPsdata *p, float inf, int idx) float sco[2] = {0.0f}; float a[2], b[2], c[2], d[2]; + float pressure = 0.0f; const float average_fac = 1.0f / steps; /* Compute smoothed coordinate by taking the ones nearby */ if (pta) { copy_v2_v2(a, &pta->x); madd_v2_v2fl(sco, a, average_fac); + pressure += pta->pressure * average_fac; } if (ptb) { copy_v2_v2(b, &ptb->x); madd_v2_v2fl(sco, b, average_fac); + pressure += ptb->pressure * average_fac; } if (ptc) { copy_v2_v2(c, &ptc->x); madd_v2_v2fl(sco, c, average_fac); + pressure += ptc->pressure * average_fac; } if (ptd) { copy_v2_v2(d, &ptd->x); madd_v2_v2fl(sco, d, average_fac); + pressure += ptd->pressure * average_fac; } - /* Based on influence factor, blend between original and optimal smoothed coordinate */ + /* Based on influence factor, blend between original and optimal smoothed coordinate. */ interp_v2_v2v2(c, c, sco, inf); copy_v2_v2(&ptc->x, c); + /* Interpolate pressure. */ + ptc->pressure = interpf(ptc->pressure, pressure, inf); } /* add current stroke-point to buffer (returns whether point was successfully added) */ @@ -1240,6 +1244,14 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) /* Save material index */ gps->mat_nr = BKE_gpencil_object_material_get_index_from_brush(p->ob, p->brush); + if (gps->mat_nr < 0) { + if (p->ob->actcol - 1 < 0) { + gps->mat_nr = 0; + } + else { + gps->mat_nr = p->ob->actcol - 1; + } + } /* calculate UVs along the stroke */ ED_gpencil_calc_stroke_uv(obact, gps); @@ -2128,15 +2140,6 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps /* Ensure this gets set... */ p->gpf = p->gpl->actframe; - /* Restrict eraser to only affecting selected strokes, if the "selection mask" is on - * (though this is only available in editmode) - */ - if (p->gpd->flag & GP_DATA_STROKE_EDITMODE) { - if (ts->gp_sculpt.flag & GP_SCULPT_SETT_FLAG_SELECT_MASK) { - p->flags |= GP_PAINTFLAG_SELECTMASK; - } - } - if (has_layer_to_erase == false) { p->status = GP_STATUS_ERROR; return; diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c index 25913fe821a..8d4c75d2e8c 100644 --- a/source/blender/editors/gpencil/gpencil_primitive.c +++ b/source/blender/editors/gpencil/gpencil_primitive.c @@ -330,7 +330,15 @@ static void gp_primitive_set_initdata(bContext *C, tGPDprimitive *tgpi) gps->flag |= GP_STROKE_3DSPACE; - gps->mat_nr = BKE_gpencil_object_material_get_index(tgpi->ob, tgpi->mat); + gps->mat_nr = BKE_gpencil_object_material_get_index_from_brush(tgpi->ob, tgpi->brush); + if (gps->mat_nr < 0) { + if (tgpi->ob->actcol - 1 < 0) { + gps->mat_nr = 0; + } + else { + gps->mat_nr = tgpi->ob->actcol - 1; + } + } /* allocate memory for storage points, but keep empty */ gps->totpoints = 0; @@ -959,7 +967,7 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) /* add small offset to keep stroke over the surface */ if ((depth_arr) && (gpd->zdepth_offset > 0.0f)) { - depth_arr[i] *= (1.0f - gpd->zdepth_offset); + depth_arr[i] *= (1.0f - (gpd->zdepth_offset / 1000.0f)); } /* convert screen-coordinates to 3D coordinates */ diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c index 01a2ac757d6..f4484624d5a 100644 --- a/source/blender/editors/gpencil/gpencil_select.c +++ b/source/blender/editors/gpencil/gpencil_select.c @@ -67,13 +67,30 @@ /** \name Shared Utilities * \{ */ +/* Convert sculpt mask mode to Select mode */ +static int gpencil_select_mode_from_sculpt(eGP_Sculpt_SelectMaskFlag mode) +{ + if (mode & GP_SCULPT_MASK_SELECTMODE_POINT) { + return GP_SELECTMODE_POINT; + } + else if (mode & GP_SCULPT_MASK_SELECTMODE_STROKE) { + return GP_SELECTMODE_STROKE; + } + else if (mode & GP_SCULPT_MASK_SELECTMODE_SEGMENT) { + return GP_SELECTMODE_SEGMENT; + } + else { + return GP_SELECTMODE_POINT; + } +} + static bool gpencil_select_poll(bContext *C) { bGPdata *gpd = ED_gpencil_data_get_active(C); if (GPENCIL_SCULPT_MODE(gpd)) { ToolSettings *ts = CTX_data_tool_settings(C); - if ((ts->gp_sculpt.flag & GP_SCULPT_SETT_FLAG_SELECT_MASK) == 0) { + if (!(GPENCIL_ANY_SCULPT_MASK(ts->gpencil_selectmode_sculpt))) { return false; } } @@ -94,6 +111,19 @@ static bool gpencil_select_poll(bContext *C) /* -------------------------------------------------------------------- */ /** \name Select All Operator * \{ */ +static bool gpencil_select_all_poll(bContext *C) +{ + bGPdata *gpd = ED_gpencil_data_get_active(C); + + /* we just need some visible strokes, and to be in editmode or other modes only to catch event */ + if (GPENCIL_ANY_MODE(gpd)) { + if (gpd->layers.first) { + return true; + } + } + + return false; +} static int gpencil_select_all_exec(bContext *C, wmOperator *op) { @@ -110,6 +140,14 @@ static int gpencil_select_all_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } + /* For sculpt mode, if mask is disable, only allows deselect */ + if (GPENCIL_SCULPT_MODE(gpd)) { + ToolSettings *ts = CTX_data_tool_settings(C); + if ((!(GPENCIL_ANY_SCULPT_MASK(ts->gpencil_selectmode_sculpt))) && (action != SEL_DESELECT)) { + return OPERATOR_CANCELLED; + } + } + ED_gpencil_select_toggle_all(C, action); /* updates */ @@ -132,7 +170,7 @@ void GPENCIL_OT_select_all(wmOperatorType *ot) /* callbacks */ ot->exec = gpencil_select_all_exec; - ot->poll = gpencil_select_poll; + ot->poll = gpencil_select_all_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -928,7 +966,11 @@ static int gpencil_circle_select_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); ToolSettings *ts = CTX_data_tool_settings(C); - const int selectmode = ts->gpencil_selectmode; + Object *ob = CTX_data_active_object(C); + + const int selectmode = (ob && ob->mode == OB_MODE_SCULPT_GPENCIL) ? + gpencil_select_mode_from_sculpt(ts->gpencil_selectmode_sculpt) : + ts->gpencil_selectmode_edit; const float scale = ts->gp_sculpt.isect_threshold; /* if not edit/sculpt mode, the event is catched but not processed */ @@ -972,12 +1014,12 @@ static int gpencil_circle_select_exec(bContext *C, wmOperator *op) rect.ymax = my + radius; /* find visible strokes, and select if hit */ - GP_DERIVED_STROKES_BEGIN(gpstroke_iter, C, gpl, gps) + GP_EVALUATED_STROKES_BEGIN(gpstroke_iter, C, gpl, gps) { changed |= gp_stroke_do_circle_sel( gpl, gps, &gsc, mx, my, radius, select, &rect, gpstroke_iter.diff_mat, selectmode, scale); } - GP_DERIVED_STROKES_END(gpstroke_iter); + GP_EVALUATED_STROKES_END(gpstroke_iter); /* updates */ if (changed) { @@ -1035,12 +1077,18 @@ static int gpencil_generic_select_exec(bContext *C, GPencilTestFn is_inside_fn, void *user_data) { + Object *ob = CTX_data_active_object(C); bGPdata *gpd = ED_gpencil_data_get_active(C); ToolSettings *ts = CTX_data_tool_settings(C); ScrArea *sa = CTX_wm_area(C); - const bool strokemode = ((ts->gpencil_selectmode == GP_SELECTMODE_STROKE) && + + const short selectmode = (ob && ob->mode == OB_MODE_SCULPT_GPENCIL) ? + gpencil_select_mode_from_sculpt(ts->gpencil_selectmode_sculpt) : + ts->gpencil_selectmode_edit; + + const bool strokemode = ((selectmode == GP_SELECTMODE_STROKE) && ((gpd->flag & GP_DATA_STROKE_PAINTMODE) == 0)); - const bool segmentmode = ((ts->gpencil_selectmode == GP_SELECTMODE_SEGMENT) && + const bool segmentmode = ((selectmode == GP_SELECTMODE_SEGMENT) && ((gpd->flag & GP_DATA_STROKE_PAINTMODE) == 0)); const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); const float scale = ts->gp_sculpt.isect_threshold; @@ -1075,7 +1123,7 @@ static int gpencil_generic_select_exec(bContext *C, } /* select/deselect points */ - GP_DERIVED_STROKES_BEGIN(gpstroke_iter, C, gpl, gps) + GP_EVALUATED_STROKES_BEGIN(gpstroke_iter, C, gpl, gps) { bGPDspoint *pt; @@ -1088,7 +1136,6 @@ static int gpencil_generic_select_exec(bContext *C, /* convert point coords to screenspace */ const bool is_inside = is_inside_fn(gps, pt, &gsc, gpstroke_iter.diff_mat, user_data); - if (strokemode == false) { const bool is_select = (pt->runtime.pt_orig->flag & GP_SPOINT_SELECT) != 0; const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); @@ -1143,7 +1190,7 @@ static int gpencil_generic_select_exec(bContext *C, /* Ensure that stroke selection is in sync with its points */ BKE_gpencil_stroke_sync_selection(gps->runtime.gps_orig); } - GP_DERIVED_STROKES_END(gpstroke_iter); + GP_EVALUATED_STROKES_END(gpstroke_iter); /* if paint mode,delete selected points */ if (gpd->flag & GP_DATA_STROKE_PAINTMODE) { @@ -1318,6 +1365,7 @@ static void deselect_all_selected(bContext *C) static int gpencil_select_exec(bContext *C, wmOperator *op) { ScrArea *sa = CTX_wm_area(C); + Object *ob = CTX_data_active_object(C); bGPdata *gpd = ED_gpencil_data_get_active(C); ToolSettings *ts = CTX_data_tool_settings(C); const float scale = ts->gp_sculpt.isect_threshold; @@ -1348,8 +1396,12 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) } /* if select mode is stroke, use whole stroke */ - if (ts->gpencil_selectmode == GP_SELECTMODE_STROKE) { - whole = true; + if ((ob) && (ob->mode == OB_MODE_SCULPT_GPENCIL)) { + whole = (bool)(gpencil_select_mode_from_sculpt(ts->gpencil_selectmode_sculpt) == + GP_SELECTMODE_STROKE); + } + else { + whole = (bool)(ts->gpencil_selectmode_edit == GP_SELECTMODE_STROKE); } /* init space conversion stuff */ @@ -1360,7 +1412,7 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) /* First Pass: Find stroke point which gets hit */ /* XXX: maybe we should go from the top of the stack down instead... */ - GP_DERIVED_STROKES_BEGIN(gpstroke_iter, C, gpl, gps) + GP_EVALUATED_STROKES_BEGIN(gpstroke_iter, C, gpl, gps) { bGPDspoint *pt; int i; @@ -1393,7 +1445,7 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) } } } - GP_DERIVED_STROKES_END(gpstroke_iter); + GP_EVALUATED_STROKES_END(gpstroke_iter); /* Abort if nothing hit... */ if (ELEM(NULL, hit_stroke, hit_point)) { @@ -1454,7 +1506,11 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) hit_stroke->flag |= GP_STROKE_SELECT; /* expand selection to segment */ - if (ts->gpencil_selectmode == GP_SELECTMODE_SEGMENT) { + const short selectmode = (ob && ob->mode == OB_MODE_SCULPT_GPENCIL) ? + gpencil_select_mode_from_sculpt(ts->gpencil_selectmode_sculpt) : + ts->gpencil_selectmode_edit; + + if (selectmode == GP_SELECTMODE_SEGMENT) { float r_hita[3], r_hitb[3]; bool hit_select = (bool)(hit_point->flag & GP_SPOINT_SELECT); ED_gpencil_select_stroke_segment( diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index 2a0f16a4bbf..d7492b5be4d 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -401,17 +401,7 @@ const EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(bContext *C, /* Create new layer */ /* TODO: have some way of specifying that we don't want this? */ - { - /* "New Layer" entry */ - item_tmp.identifier = "__CREATE__"; - item_tmp.name = "New Layer"; - item_tmp.value = -1; - item_tmp.icon = ICON_ADD; - RNA_enum_item_add(&item, &totitem, &item_tmp); - /* separator */ - RNA_enum_item_add_separator(&item, &totitem); - } const int tot = BLI_listbase_count(&gpd->layers); /* Existing layers */ for (gpl = gpd->layers.last, i = 0; gpl; gpl = gpl->prev, i++) { @@ -428,6 +418,17 @@ const EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(bContext *C, RNA_enum_item_add(&item, &totitem, &item_tmp); } + { + /* separator */ + RNA_enum_item_add_separator(&item, &totitem); + + /* "New Layer" entry */ + item_tmp.identifier = "__CREATE__"; + item_tmp.name = "New Layer"; + item_tmp.value = -1; + item_tmp.icon = ICON_ADD; + RNA_enum_item_add(&item, &totitem, &item_tmp); + } RNA_enum_item_end(&item, &totitem); *r_free = true; @@ -2063,7 +2064,7 @@ void ED_gpencil_update_color_uv(Main *bmain, Material *mat) if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { continue; } - gps_ma = give_current_material(ob, gps->mat_nr + 1); + gps_ma = BKE_material_gpencil_get(ob, gps->mat_nr + 1); /* update */ if ((gps_ma) && (gps_ma == mat)) { ED_gpencil_calc_stroke_uv(ob, gps); diff --git a/source/blender/editors/include/BIF_glutil.h b/source/blender/editors/include/BIF_glutil.h index 101a65d151a..a49f02d28fe 100644 --- a/source/blender/editors/include/BIF_glutil.h +++ b/source/blender/editors/include/BIF_glutil.h @@ -24,7 +24,6 @@ #ifndef __BIF_GLUTIL_H__ #define __BIF_GLUTIL_H__ -struct rctf; struct rcti; struct ColorManagedDisplaySettings; diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h index 6629eed8328..48d0a5fe8be 100644 --- a/source/blender/editors/include/ED_armature.h +++ b/source/blender/editors/include/ED_armature.h @@ -42,7 +42,6 @@ struct ReportList; struct Scene; struct UndoType; struct View3D; -struct ViewContext; struct ViewLayer; struct bArmature; struct bContext; @@ -75,12 +74,14 @@ typedef struct EditBone { int flag; int layer; + /* Envelope distance & weight */ float dist, weight; /** put them in order! transform uses this as scale */ float xwidth, length, zwidth; float rad_head, rad_tail; /* Bendy-Bone parameters */ + short segments; float roll1, roll2; float curve_in_x, curve_in_y; float curve_out_x, curve_out_y; @@ -91,8 +92,6 @@ typedef struct EditBone { /** for envelope scaling */ float oldlength; - short segments; - /** Type of next/prev bone handles */ char bbone_prev_type; char bbone_next_type; @@ -229,15 +228,9 @@ void ED_armature_edit_transform_mirror_update(struct Object *obedit); void ED_armature_origin_set( struct Main *bmain, struct Object *ob, const float cursor[3], int centermode, int around); -void ED_armature_transform_bones(struct bArmature *arm, float mat[4][4], const bool do_props); -void ED_armature_transform_apply(struct Main *bmain, - struct Object *ob, - float mat[4][4], - const bool do_props); -void ED_armature_transform(struct Main *bmain, - struct bArmature *arm, - float mat[4][4], - const bool do_props); +void ED_armature_edit_transform(struct bArmature *arm, const float mat[4][4], const bool do_props); + +void ED_armature_transform(struct bArmature *arm, const float mat[4][4], const bool do_props); #define ARM_GROUPS_NAME 1 #define ARM_GROUPS_ENVELOPE 2 diff --git a/source/blender/editors/include/ED_clip.h b/source/blender/editors/include/ED_clip.h index 7cee5a358f4..22bf22e04d3 100644 --- a/source/blender/editors/include/ED_clip.h +++ b/source/blender/editors/include/ED_clip.h @@ -29,7 +29,6 @@ struct ImBuf; struct Main; struct Mask; struct MovieClip; -struct Scene; struct SpaceClip; struct bContext; struct bScreen; diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h index 7273f857a41..dc42237d804 100644 --- a/source/blender/editors/include/ED_fileselect.h +++ b/source/blender/editors/include/ED_fileselect.h @@ -34,17 +34,32 @@ struct wmWindowManager; #define FILE_LAYOUT_HOR 1 #define FILE_LAYOUT_VER 2 -#define MAX_FILE_COLUMN 4 - -typedef enum FileListColumns { +typedef enum FileAttributeColumnType { + COLUMN_NONE = -1, COLUMN_NAME = 0, - COLUMN_DATE, - COLUMN_TIME, + COLUMN_DATETIME, COLUMN_SIZE, -} FileListColumns; + + ATTRIBUTE_COLUMN_MAX +} FileAttributeColumnType; + +typedef struct FileAttributeColumn { + /** UI name for this column */ + const char *name; + + float width; + /* The sort type to use when sorting by this column. */ + int sort_type; /* eFileSortType */ + + /* Alignment of column texts, header text is always left aligned */ + int text_align; /* eFontStyle_Align */ +} FileAttributeColumn; typedef struct FileLayout { /* view settings - XXX - move into own struct */ + int offset_top; + /* Height of the header for the different FileAttributeColumn's. */ + int attribute_column_header_h; int prv_w; int prv_h; int tile_w; @@ -54,13 +69,17 @@ typedef struct FileLayout { int prv_border_x; int prv_border_y; int rows; - int columns; + /* Those are the major layout columns the files are distributed across, not to be confused with + * 'attribute_columns' array below. */ + int flow_columns; int width; int height; int flag; int dirty; int textheight; - float column_widths[MAX_FILE_COLUMN]; + /* The columns for each item (name, modification date/time, size). Not to be confused with the + * 'flow_columns' above. */ + FileAttributeColumn attribute_columns[ATTRIBUTE_COLUMN_MAX]; /* When we change display size, we may have to update static strings like size of files... */ short curr_size; @@ -72,6 +91,7 @@ typedef struct FileSelection { } FileSelection; struct rcti; +struct View2D; struct FileSelectParams *ED_fileselect_get_params(struct SpaceFile *sfile); @@ -87,6 +107,17 @@ int ED_fileselect_layout_numfiles(FileLayout *layout, struct ARegion *ar); int ED_fileselect_layout_offset(FileLayout *layout, int x, int y); FileSelection ED_fileselect_layout_offset_rect(FileLayout *layout, const struct rcti *rect); +void ED_fileselect_layout_maskrect(const FileLayout *layout, + const struct View2D *v2d, + struct rcti *r_rect); +bool ED_fileselect_layout_is_inside_pt(const FileLayout *layout, + const struct View2D *v2d, + int x, + int y); +bool ED_fileselect_layout_isect_rect(const FileLayout *layout, + const struct View2D *v2d, + const struct rcti *rect, + struct rcti *r_dst); void ED_fileselect_layout_tilepos(FileLayout *layout, int tile, int *x, int *y); void ED_operatormacros_file(void); diff --git a/source/blender/editors/include/ED_gizmo_library.h b/source/blender/editors/include/ED_gizmo_library.h index f14648bc026..a3e2e643509 100644 --- a/source/blender/editors/include/ED_gizmo_library.h +++ b/source/blender/editors/include/ED_gizmo_library.h @@ -43,10 +43,8 @@ void ED_gizmotypes_value_2d(void); void ED_gizmogrouptypes_value_2d(void); struct Object; -struct Scene; struct bContext; struct wmGizmo; -struct wmGizmoGroup; /* -------------------------------------------------------------------- */ /* Shape Presets diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h index 6410e6630a7..470eb58c72b 100644 --- a/source/blender/editors/include/ED_gpencil.h +++ b/source/blender/editors/include/ED_gpencil.h @@ -27,7 +27,6 @@ struct ID; struct ListBase; struct PointerRNA; -struct rcti; struct Brush; struct bGPDframe; @@ -39,13 +38,11 @@ struct tGPspoint; struct ARegion; struct Depsgraph; -struct EvaluationContext; struct Main; struct RegionView3D; struct ReportList; struct Scene; struct ScrArea; -struct ToolSettings; struct View3D; struct ViewLayer; struct bContext; @@ -58,8 +55,6 @@ struct bAnimContext; struct wmKeyConfig; struct wmOperator; -struct wmWindow; -struct wmWindowManager; /* ------------- Grease-Pencil Runtime Data ---------------- */ diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h index a09e1d579fd..7d69f86dbf8 100644 --- a/source/blender/editors/include/ED_image.h +++ b/source/blender/editors/include/ED_image.h @@ -31,7 +31,6 @@ struct ImageUser; struct ReportList; struct Scene; struct SpaceImage; -struct ToolSettings; struct ViewLayer; struct bContext; struct wmWindowManager; diff --git a/source/blender/editors/include/ED_keyframes_draw.h b/source/blender/editors/include/ED_keyframes_draw.h index 05f641abe91..2630feaa9d3 100644 --- a/source/blender/editors/include/ED_keyframes_draw.h +++ b/source/blender/editors/include/ED_keyframes_draw.h @@ -31,7 +31,6 @@ struct FCurve; struct ListBase; struct MaskLayer; struct Object; -struct Palette; struct Scene; struct View2D; struct bAction; diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h index bbeeeade822..42e5add2ef0 100644 --- a/source/blender/editors/include/ED_keyframing.h +++ b/source/blender/editors/include/ED_keyframing.h @@ -44,8 +44,6 @@ struct bPoseChannel; struct ReportList; struct bContext; -struct Depsgraph; - struct EnumPropertyItem; struct PointerRNA; struct PropertyRNA; diff --git a/source/blender/editors/include/ED_markers.h b/source/blender/editors/include/ED_markers.h index a883187327f..a9e57ecc13d 100644 --- a/source/blender/editors/include/ED_markers.h +++ b/source/blender/editors/include/ED_markers.h @@ -29,7 +29,6 @@ struct TimeMarker; struct bAnimContext; struct bContext; struct wmKeyConfig; -struct wmKeyMap; /* Drawing API ------------------------------ */ diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 5ebba4e5d25..ee4798430ef 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -45,7 +45,6 @@ struct Mesh; struct Object; struct ReportList; struct Scene; -struct ToolSettings; struct UndoType; struct UvMapVert; struct UvMapVert; @@ -55,7 +54,6 @@ struct View3D; struct ViewContext; struct bContext; struct bDeformGroup; -struct rcti; struct wmKeyConfig; struct wmOperator; @@ -105,7 +103,9 @@ bool EDBM_vert_color_check(struct BMEditMesh *em); bool EDBM_mesh_hide(struct BMEditMesh *em, bool swap); bool EDBM_mesh_reveal(struct BMEditMesh *em, bool select); -void EDBM_update_generic(struct BMEditMesh *em, const bool do_tessface, const bool is_destructive); +void EDBM_update_generic(struct BMEditMesh *em, + const bool do_tessellation, + const bool is_destructive); struct UvElementMap *BM_uv_element_map_create(struct BMesh *bm, const bool selected, @@ -138,13 +138,21 @@ bool BMBVH_EdgeVisible(struct BMBVHTree *tree, struct View3D *v3d, struct Object *obedit); +/* editmesh_automerge.c */ +void EDBM_automerge(struct Object *ob, bool update, const char hflag, const float dist); +void EDBM_automerge_and_split(struct Object *ob, + bool split_edges, + bool split_faces, + bool update, + const char hflag, + const float dist); + /* editmesh_undo.c */ void ED_mesh_undosys_type(struct UndoType *ut); /* editmesh_select.c */ void EDBM_select_mirrored( struct BMEditMesh *em, const int axis, const bool extend, int *r_totmirr, int *r_totfail); -void EDBM_automerge(struct Scene *scene, struct Object *ob, bool update, const char hflag); struct BMVert *EDBM_vert_find_nearest_ex(struct ViewContext *vc, float *r_dist, @@ -188,8 +196,11 @@ bool EDBM_unified_findnearest(struct ViewContext *vc, bool EDBM_unified_findnearest_from_raycast(struct ViewContext *vc, struct Base **bases, const uint bases_len, - bool use_boundary, - int *r_base_index, + bool use_boundary_vertices, + bool use_boundary_edges, + int *r_base_index_vert, + int *r_base_index_edge, + int *r_base_index_face, struct BMVert **r_eve, struct BMEdge **r_eed, struct BMFace **r_efa); @@ -239,15 +250,30 @@ void EDBM_preselect_edgering_update_from_edge(struct EditMesh_PreSelEdgeRing *ps /* editmesh_preselect_elem.c */ struct EditMesh_PreSelElem; +typedef enum eEditMesh_PreSelPreviewAction { + PRESELECT_ACTION_TRANSFORM = 1, + PRESELECT_ACTION_CREATE = 2, + PRESELECT_ACTION_DELETE = 3, +} eEditMesh_PreSelPreviewAction; + struct EditMesh_PreSelElem *EDBM_preselect_elem_create(void); void EDBM_preselect_elem_destroy(struct EditMesh_PreSelElem *psel); void EDBM_preselect_elem_clear(struct EditMesh_PreSelElem *psel); +void EDBM_preselect_preview_clear(struct EditMesh_PreSelElem *psel); void EDBM_preselect_elem_draw(struct EditMesh_PreSelElem *psel, const float matrix[4][4]); void EDBM_preselect_elem_update_from_single(struct EditMesh_PreSelElem *psel, struct BMesh *bm, struct BMElem *ele, const float (*coords)[3]); +void EDBM_preselect_elem_update_preview(struct EditMesh_PreSelElem *psel, + struct ViewContext *vc, + struct BMesh *bm, + struct BMElem *ele, + const int mval[2]); +void EDBM_preselect_action_set(struct EditMesh_PreSelElem *psel, + eEditMesh_PreSelPreviewAction action); +eEditMesh_PreSelPreviewAction EDBM_preselect_action_get(struct EditMesh_PreSelElem *psel); /* mesh_ops.c */ void ED_operatortypes_mesh(void); void ED_operatormacros_mesh(void); @@ -358,21 +384,14 @@ void ED_mesh_geometry_add( struct Mesh *mesh, struct ReportList *reports, int verts, int edges, int faces); #endif void ED_mesh_polys_add(struct Mesh *mesh, struct ReportList *reports, int count); -void ED_mesh_tessfaces_add(struct Mesh *mesh, struct ReportList *reports, int count); void ED_mesh_edges_add(struct Mesh *mesh, struct ReportList *reports, int count); void ED_mesh_loops_add(struct Mesh *mesh, struct ReportList *reports, int count); void ED_mesh_vertices_add(struct Mesh *mesh, struct ReportList *reports, int count); -void ED_mesh_faces_remove(struct Mesh *mesh, struct ReportList *reports, int count); void ED_mesh_edges_remove(struct Mesh *mesh, struct ReportList *reports, int count); void ED_mesh_vertices_remove(struct Mesh *mesh, struct ReportList *reports, int count); -void ED_mesh_calc_tessface(struct Mesh *mesh, bool free_mpoly); -void ED_mesh_update(struct Mesh *mesh, - struct bContext *C, - bool calc_edges, - bool calc_edges_loose, - bool calc_tessface); +void ED_mesh_update(struct Mesh *mesh, struct bContext *C, bool calc_edges, bool calc_edges_loose); void ED_mesh_uv_texture_ensure(struct Mesh *me, const char *name); int ED_mesh_uv_texture_add(struct Mesh *me, diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index 7b9a96e4d07..c481c19a552 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -34,7 +34,6 @@ struct EnumPropertyItem; struct EnumPropertyItem; struct ID; struct Main; -struct Menu; struct ModifierData; struct Object; struct PointerRNA; @@ -44,16 +43,15 @@ struct Scene; struct ShaderFxData; struct View3D; struct ViewLayer; +struct XFormObjectData; struct bConstraint; struct bContext; struct bFaceMap; struct bPoseChannel; struct uiLayout; struct wmKeyConfig; -struct wmKeyMap; struct wmOperator; struct wmOperatorType; -struct wmWindow; struct wmWindowManager; #include "DNA_object_enums.h" @@ -403,6 +401,12 @@ bool ED_object_jump_to_bone(struct bContext *C, void ED_object_facemap_face_add(struct Object *ob, struct bFaceMap *fmap, int facenum); void ED_object_facemap_face_remove(struct Object *ob, struct bFaceMap *fmap, int facenum); +/* object_data_transform.c */ +struct XFormObjectData *ED_object_data_xform_create(struct ID *id); +void ED_object_data_xform_destroy(struct XFormObjectData *xod); + +void ED_object_data_xform_by_mat4(struct XFormObjectData *xod, const float mat[4][4]); + #ifdef __cplusplus } #endif diff --git a/source/blender/editors/include/ED_outliner.h b/source/blender/editors/include/ED_outliner.h index e94aedc2b2b..3015d8d9cdc 100644 --- a/source/blender/editors/include/ED_outliner.h +++ b/source/blender/editors/include/ED_outliner.h @@ -30,4 +30,18 @@ bool ED_outliner_collections_editor_poll(struct bContext *C); void ED_outliner_selected_objects_get(const struct bContext *C, struct ListBase *objects); +Base *ED_outliner_give_base_under_cursor(struct bContext *C, const int mval[2]); + +void ED_outliner_select_sync_from_object_tag(struct bContext *C); +void ED_outliner_select_sync_from_edit_bone_tag(struct bContext *C); +void ED_outliner_select_sync_from_pose_bone_tag(struct bContext *C); +void ED_outliner_select_sync_from_sequence_tag(struct bContext *C); +void ED_outliner_select_sync_from_all_tag(struct bContext *C); + +bool ED_outliner_select_sync_is_dirty(const struct bContext *C); + +void ED_outliner_select_sync_from_outliner(struct bContext *C, struct SpaceOutliner *soops); + +void ED_outliner_select_sync_flag_outliners(const struct bContext *C); + #endif /* __ED_OUTLINER_H__ */ diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index c7ee7be49b5..d0fab134dcc 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -39,10 +39,8 @@ struct Depsgraph; struct IDProperty; struct Main; struct MenuType; -struct PropertyRNA; struct Scene; struct SpaceLink; -struct ViewLayer; struct WorkSpace; struct WorkSpaceInstanceHook; struct bContext; @@ -50,7 +48,6 @@ struct bScreen; struct rcti; struct uiBlock; struct uiLayout; -struct wmEvent; struct wmKeyConfig; struct wmMsgBus; struct wmMsgSubscribeKey; diff --git a/source/blender/editors/include/ED_sculpt.h b/source/blender/editors/include/ED_sculpt.h index 034e002f86a..d907ba4e581 100644 --- a/source/blender/editors/include/ED_sculpt.h +++ b/source/blender/editors/include/ED_sculpt.h @@ -25,10 +25,7 @@ #define __ED_SCULPT_H__ struct ARegion; -struct ListBase; struct Object; -struct RegionView3D; -struct UndoStep; struct UndoType; struct ViewContext; struct bContext; diff --git a/source/blender/editors/include/ED_time_scrub_ui.h b/source/blender/editors/include/ED_time_scrub_ui.h index b43e674224c..f010c45d939 100644 --- a/source/blender/editors/include/ED_time_scrub_ui.h +++ b/source/blender/editors/include/ED_time_scrub_ui.h @@ -24,7 +24,6 @@ #ifndef __ED_TIME_SCRUB_UI_H__ #define __ED_TIME_SCRUB_UI_H__ -struct View2DGrid; struct bContext; struct bDopeSheet; struct wmEvent; diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index 3605a245187..d8b65aa5975 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -26,18 +26,11 @@ /* ******************* Registration Function ********************** */ -struct ARegion; -struct ListBase; -struct Main; struct Object; struct SnapObjectContext; struct SnapObjectParams; -struct View3D; -struct WorkSpace; struct bContext; -struct wmEvent; struct wmKeyConfig; -struct wmKeyMap; struct wmOperatorType; void ED_keymap_transform(struct wmKeyConfig *keyconf); @@ -97,6 +90,10 @@ enum TfmMode { #define CTX_PAINT_CURVE (1 << 8) #define CTX_GPENCIL_STROKES (1 << 9) #define CTX_CURSOR (1 << 10) +/** When transforming object's, adjust the object data so it stays in the same place. */ +#define CTX_OBMODE_XFORM_OBDATA (1 << 11) +/** Transform object parents without moving their children. */ +#define CTX_OBMODE_XFORM_SKIP_CHILDREN (1 << 12) /* Standalone call to get the transformation center corresponding to the current situation * returns 1 if successful, 0 otherwise (usually means there's no selection) @@ -112,7 +109,6 @@ struct Scene; struct TransInfo; struct wmGizmoGroup; struct wmGizmoGroupType; -struct wmOperator; /* UNUSED */ // int BIF_snappingSupported(struct Object *obedit); @@ -197,12 +193,12 @@ bool peelObjectsSnapContext(struct SnapObjectContext *sctx, float r_no[3], float *r_thickness); -bool snapObjectsTransform(struct TransInfo *t, - const float mval[2], - float *dist_px, - /* return args */ - float r_loc[3], - float r_no[3]); +short snapObjectsTransform(struct TransInfo *t, + const float mval[2], + float *dist_px, + /* return args */ + float r_loc[3], + float r_no[3]); bool snapNodesTransform(struct TransInfo *t, const int mval[2], /* return args */ diff --git a/source/blender/editors/include/ED_transform_snap_object_context.h b/source/blender/editors/include/ED_transform_snap_object_context.h index f27523bb1f8..40e0005b487 100644 --- a/source/blender/editors/include/ED_transform_snap_object_context.h +++ b/source/blender/editors/include/ED_transform_snap_object_context.h @@ -32,8 +32,6 @@ struct Main; struct Object; struct Scene; struct View3D; -struct ViewLayer; -struct bContext; /* transform_snap_object.c */ @@ -125,6 +123,7 @@ short ED_transform_snap_object_project_view3d_ex(struct SnapObjectContext *sctx, const unsigned short snap_to, const struct SnapObjectParams *params, const float mval[2], + const float prev_co[3], float *dist_px, float r_loc[3], float r_no[3], @@ -135,6 +134,7 @@ bool ED_transform_snap_object_project_view3d(struct SnapObjectContext *sctx, const unsigned short snap_to, const struct SnapObjectParams *params, const float mval[2], + const float prev_co[3], float *dist_px, /* return args */ float r_loc[3], diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h index 8dd2dab5209..1856ad8454b 100644 --- a/source/blender/editors/include/ED_uvedit.h +++ b/source/blender/editors/include/ED_uvedit.h @@ -37,7 +37,6 @@ struct Object; struct Scene; struct SpaceImage; struct ToolSettings; -struct View3D; struct ViewLayer; struct bNode; struct wmKeyConfig; diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 67dfb184d19..139b306b533 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -38,8 +38,6 @@ struct Camera; struct CustomData_MeshMasks; struct Depsgraph; struct EditBone; -struct GPUFX; -struct GPUFXSettings; struct GPUOffScreen; struct GPUViewport; struct ID; @@ -58,7 +56,6 @@ struct View3D; struct View3DShading; struct ViewContext; struct ViewLayer; -struct WorkSpace; struct bContext; struct bPoseChannel; struct bScreen; @@ -690,6 +687,10 @@ bool ED_view3d_distance_set_from_location(struct RegionView3D *rv3d, float ED_scene_grid_scale(struct Scene *scene, const char **grid_unit); float ED_view3d_grid_scale(struct Scene *scene, struct View3D *v3d, const char **grid_unit); +void ED_view3d_grid_steps(struct Scene *scene, + struct View3D *v3d, + struct RegionView3D *rv3d, + float *r_grid_steps); float ED_view3d_grid_view_scale(struct Scene *scene, struct View3D *v3d, struct RegionView3D *rv3d, diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h index 03a49943ed3..41ac1b6b452 100644 --- a/source/blender/editors/include/UI_icons.h +++ b/source/blender/editors/include/UI_icons.h @@ -483,7 +483,7 @@ DEF_ICON(UNDERLINE) DEF_ICON(SMALL_CAPS) DEF_ICON_BLANK(742) DEF_ICON_BLANK(743) -DEF_ICON_BLANK(744) +DEF_ICON_MODIFIER(CON_ACTION) DEF_ICON_BLANK(745) DEF_ICON_BLANK(746) DEF_ICON_BLANK(747) @@ -667,8 +667,8 @@ DEF_ICON(PARTICLE_PATH) /* EDITING */ DEF_ICON_BLANK(669) DEF_ICON_BLANK(670) -DEF_ICON_BLANK(671) -DEF_ICON_BLANK(672) +DEF_ICON(SNAP_PERPENDICULAR) +DEF_ICON(SNAP_MIDPOINT) DEF_ICON(SNAP_OFF) DEF_ICON(SNAP_ON) DEF_ICON(SNAP_NORMAL) @@ -866,8 +866,8 @@ DEF_ICON(SEQ_LUMA_WAVEFORM) DEF_ICON(SEQ_CHROMA_SCOPE) DEF_ICON(SEQ_HISTOGRAM) DEF_ICON(SEQ_SPLITVIEW) -DEF_ICON_BLANK(870) -DEF_ICON_BLANK(871) +DEF_ICON(SEQ_STRIP_META) +DEF_ICON(SEQ_STRIP_DUPLICATE) DEF_ICON_BLANK(872) DEF_ICON(IMAGE_RGB) // XXX CHANGE TO STRAIGHT ALPHA, Z ETC DEF_ICON(IMAGE_RGB_ALPHA) diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 5ef3e5d8987..aa1044647c8 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -31,7 +31,6 @@ /* Struct Declarations */ struct ARegion; -struct ARegionType; struct AutoComplete; struct ID; struct IDProperty; @@ -90,7 +89,7 @@ typedef struct uiPopupBlockHandle uiPopupBlockHandle; * For #ARegion.overlap regions, pass events though if they don't overlap * the regions contents (the usable part of the #View2D and buttons). * - * The margin is needed so it's not possible to accidentally click inbetween buttons. + * The margin is needed so it's not possible to accidentally click in between buttons. */ #define UI_REGION_OVERLAP_MARGIN (U.widget_unit / 3) diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index 1db584f0f59..a73e2655b7d 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -255,6 +255,7 @@ typedef enum ThemeColorID { TH_MATCH, /* highlight color for search matches */ TH_SELECT_HIGHLIGHT, /* highlight color for selected outliner item */ + TH_SELECT_ACTIVE, /* highlight color for active outliner item */ TH_SELECTED_OBJECT, /* selected object color for outliner */ TH_ACTIVE_OBJECT, /* active object color for outliner */ TH_EDITED_OBJECT, /* edited object color for outliner */ diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 7a123599be5..ee354df3a25 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -908,12 +908,12 @@ void UI_but_execute(const bContext *C, ARegion *ar, uiBut *but) * returns false if undo needs to be disabled. */ static bool ui_but_is_rna_undo(const uiBut *but) { - if (but->rnapoin.id.data) { + if (but->rnapoin.owner_id) { /* avoid undo push for buttons who's ID are screen or wm level * we could disable undo for buttons with no ID too but may have * unforeseen consequences, so best check for ID's we _know_ are not * handled by undo - campbell */ - ID *id = but->rnapoin.id.data; + ID *id = but->rnapoin.owner_id; if (ID_CHECK_UNDO(id) == false) { return false; } @@ -1226,8 +1226,8 @@ static bool ui_but_event_property_operator_string(const bContext *C, */ char *data_path = NULL; - if (ptr->id.data) { - ID *id = ptr->id.data; + if (ptr->owner_id) { + ID *id = ptr->owner_id; if (GS(id->name) == ID_SCR) { /* screen/editor property @@ -1731,7 +1731,7 @@ static void ui_block_message_subscribe(ARegion *ar, struct wmMsgBus *mbus, uiBlo if ((but_prev && (but_prev->rnaprop == but->rnaprop) && (but_prev->rnapoin.type == but->rnapoin.type) && (but_prev->rnapoin.data == but->rnapoin.data) && - (but_prev->rnapoin.id.data == but->rnapoin.id.data)) == false) { + (but_prev->rnapoin.owner_id == but->rnapoin.owner_id)) == false) { /* TODO: could make this into utility function. */ WM_msg_subscribe_rna(mbus, &but->rnapoin, @@ -2055,7 +2055,7 @@ bool ui_but_is_compatible(const uiBut *but_a, const uiBut *but_b) } if (but_a->rnaprop) { - /* skip 'rnapoin.data', 'rnapoin.id.data' + /* skip 'rnapoin.data', 'rnapoin.owner_id' * allow different data to have the same props edited at once */ if (but_a->rnapoin.type != but_b->rnapoin.type) { return false; @@ -2479,7 +2479,7 @@ void ui_but_string_get_ex(uiBut *but, /* uiBut.custom_data points to data this tab represents (e.g. workspace). * uiBut.rnapoin/prop store an active value (e.g. active workspace). */ - RNA_pointer_create(but->rnapoin.id.data, ptr_type, but->custom_data, &ptr); + RNA_pointer_create(but->rnapoin.owner_id, ptr_type, but->custom_data, &ptr); buf = RNA_struct_name_get_alloc(&ptr, str, maxlen, &buf_len); } else if (type == PROP_STRING) { @@ -2822,7 +2822,7 @@ bool ui_but_string_set(bContext *C, uiBut *but, const char *str) /* uiBut.custom_data points to data this tab represents (e.g. workspace). * uiBut.rnapoin/prop store an active value (e.g. active workspace). */ - RNA_pointer_create(but->rnapoin.id.data, ptr_type, but->custom_data, &ptr); + RNA_pointer_create(but->rnapoin.owner_id, ptr_type, but->custom_data, &ptr); prop = RNA_struct_name_property(ptr_type); if (RNA_property_editable(&ptr, prop)) { RNA_property_string_set(&ptr, prop, str); @@ -3586,6 +3586,14 @@ static uiBut *ui_def_but(uiBlock *block, (a1 != 0.0f && a1 != 1.0f)) == false); } + /* Number buttons must have a click-step, + * assert instead of correcting the value to ensure the caller knows what they're doing. */ + if ((type & BUTTYPE) == UI_BTYPE_NUM) { + if (ELEM((type & UI_BUT_POIN_TYPES), UI_BUT_POIN_CHAR, UI_BUT_POIN_SHORT, UI_BUT_POIN_INT)) { + BLI_assert((int)a1 > 0); + } + } + if (type & UI_BUT_POIN_TYPES) { /* a pointer is required */ if (poin == NULL) { BLI_assert(0); diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c index 4d87cc22ef2..168c6051327 100644 --- a/source/blender/editors/interface/interface_anim.c +++ b/source/blender/editors/interface/interface_anim.c @@ -228,7 +228,7 @@ bool ui_but_anim_expression_create(uiBut *but, const char *str) /* make sure we have animdata for this */ /* FIXME: until materials can be handled by depsgraph, * don't allow drivers to be created for them */ - id = (ID *)but->rnapoin.id.data; + id = but->rnapoin.owner_id; if ((id == NULL) || (GS(id->name) == ID_MA) || (GS(id->name) == ID_TE)) { if (G.debug & G_DEBUG) { printf("ERROR: create expression failed - invalid data-block for adding drivers (%p)\n", id); @@ -314,7 +314,7 @@ void ui_but_anim_autokey(bContext *C, uiBut *but, Scene *scene, float cfra) } } else { - id = but->rnapoin.id.data; + id = but->rnapoin.owner_id; /* TODO: this should probably respect the keyingset only option for anim */ if (autokeyframe_cfra_can_key(scene, id)) { diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c index 22b75da4968..580ff527bf6 100644 --- a/source/blender/editors/interface/interface_context_menu.c +++ b/source/blender/editors/interface/interface_context_menu.c @@ -176,11 +176,21 @@ static uiBlock *menu_change_shortcut(bContext *C, ARegion *ar, void *arg) UI_block_flag_enable(block, UI_BLOCK_MOVEMOUSE_QUIT); UI_block_direction_set(block, UI_DIR_CENTER_Y); - layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 200, 20, 0, style); - + layout = UI_block_layout(block, + UI_LAYOUT_VERTICAL, + UI_LAYOUT_PANEL, + 0, + 0, + U.widget_unit * 10, + U.widget_unit * 2, + 0, + style); + + uiItemL(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Change Shortcut"), ICON_HAND); uiItemR(layout, &ptr, "type", UI_ITEM_R_FULL_EVENT | UI_ITEM_R_IMMEDIATE, "", ICON_NONE); - UI_block_bounds_set_popup(block, 6, (const int[2]){-50, 26}); + UI_block_bounds_set_popup( + block, 6 * U.dpi_fac, (const int[2]){-100 * U.dpi_fac, 36 * U.dpi_fac}); shortcut_free_operator_property(prop); @@ -227,11 +237,21 @@ static uiBlock *menu_add_shortcut(bContext *C, ARegion *ar, void *arg) UI_block_func_handle_set(block, but_shortcut_name_func, but); UI_block_direction_set(block, UI_DIR_CENTER_Y); - layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 200, 20, 0, style); - + layout = UI_block_layout(block, + UI_LAYOUT_VERTICAL, + UI_LAYOUT_PANEL, + 0, + 0, + U.widget_unit * 10, + U.widget_unit * 2, + 0, + style); + + uiItemL(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Assign Shortcut"), ICON_HAND); uiItemR(layout, &ptr, "type", UI_ITEM_R_FULL_EVENT | UI_ITEM_R_IMMEDIATE, "", ICON_NONE); - UI_block_bounds_set_popup(block, 6, (const int[2]){-50, 26}); + UI_block_bounds_set_popup( + block, 6 * U.dpi_fac, (const int[2]){-100 * U.dpi_fac, 36 * U.dpi_fac}); #ifdef USE_KEYMAP_ADD_HACK g_kmi_id_hack = kmi_id; @@ -470,8 +490,9 @@ static void ui_but_menu_add_path_operators(uiLayout *layout, PointerRNA *ptr, Pr bool ui_popup_context_menu_for_button(bContext *C, uiBut *but) { - /* having this menu for some buttons makes no sense */ - if (but->type == UI_BTYPE_IMAGE) { + /* ui_but_is_interactive() may let some buttons through that should not get a context menu - it + * doesn't make sense for them. */ + if (ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_IMAGE)) { return false; } @@ -904,7 +925,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but) ICON_NONE, "UI_OT_copy_data_path_button"); - if (ptr->id.data && !is_whole_array && + if (ptr->owner_id && !is_whole_array && ELEM(type, PROP_BOOLEAN, PROP_INT, PROP_FLOAT, PROP_ENUM)) { uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy As New Driver"), @@ -1222,7 +1243,7 @@ void ui_popup_context_menu_for_panel(bContext *C, ARegion *ar, Panel *pa) sizeof(tmpstr), "%s" UI_SEP_CHAR_S "%s", IFACE_("Pin"), - IFACE_("Shift+Left Mouse")); + IFACE_("Shift Left Mouse")); uiItemR(layout, &ptr, "use_pin", 0, tmpstr, ICON_NONE); /* evil, force shortcut flag */ @@ -1230,6 +1251,7 @@ void ui_popup_context_menu_for_panel(bContext *C, ARegion *ar, Panel *pa) uiBlock *block = uiLayoutGetBlock(layout); uiBut *but = block->buttons.last; but->flag |= UI_BUT_HAS_SEP_CHAR; + but->drawflag |= UI_BUT_HAS_SHORTCUT; } } UI_popup_menu_end(C, pup); diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index 76630de96db..b7a0812c5f2 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -750,7 +750,7 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), /** * Draw title and text safe areas. * - * \Note This functionn is to be used with the 2D dashed shader enabled. + * \note This function is to be used with the 2D dashed shader enabled. * * \param pos: is a PRIM_FLOAT, 2, GPU_FETCH_FLOAT vertex attribute. * \param line_origin: is a PRIM_FLOAT, 2, GPU_FETCH_FLOAT vertex attribute. diff --git a/source/blender/editors/interface/interface_eyedropper_datablock.c b/source/blender/editors/interface/interface_eyedropper_datablock.c index 658aa4f67f9..336fae45895 100644 --- a/source/blender/editors/interface/interface_eyedropper_datablock.c +++ b/source/blender/editors/interface/interface_eyedropper_datablock.c @@ -51,6 +51,7 @@ #include "ED_space_api.h" #include "ED_screen.h" #include "ED_view3d.h" +#include "ED_outliner.h" #include "interface_intern.h" #include "interface_eyedropper_intern.h" @@ -67,6 +68,7 @@ typedef struct DataDropper { ID *init_id; /* for resetting on cancel */ + ScrArea *cursor_area; /* Area under the cursor */ ARegionType *art; void *draw_handle_pixel; char name[200]; @@ -103,6 +105,7 @@ static int datadropper_init(bContext *C, wmOperator *op) ddr->is_undo = UI_but_flag_is_set(but, UI_BUT_UNDO); + ddr->cursor_area = CTX_wm_area(C); ddr->art = art; ddr->draw_handle_pixel = ED_region_draw_cb_activate( art, datadropper_draw_cb, ddr, REGION_DRAW_POST_PIXEL); @@ -115,7 +118,7 @@ static int datadropper_init(bContext *C, wmOperator *op) ddr->idcode_name = TIP_(BKE_idcode_to_name(ddr->idcode)); PointerRNA ptr = RNA_property_pointer_get(&ddr->ptr, ddr->prop); - ddr->init_id = ptr.id.data; + ddr->init_id = ptr.owner_id; return true; } @@ -141,7 +144,7 @@ static void datadropper_exit(bContext *C, wmOperator *op) /* *** datadropper id helper functions *** */ /** - * \brief get the ID from the screen. + * \brief get the ID from the 3D view or outliner. */ static void datadropper_id_sample_pt(bContext *C, DataDropper *ddr, int mx, int my, ID **r_id) { @@ -155,7 +158,7 @@ static void datadropper_id_sample_pt(bContext *C, DataDropper *ddr, int mx, int ddr->name[0] = '\0'; if (sa) { - if (sa->spacetype == SPACE_VIEW3D) { + if (ELEM(sa->spacetype, SPACE_VIEW3D, SPACE_OUTLINER)) { ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my); if (ar) { const int mval[2] = {mx - ar->winrct.xmin, my - ar->winrct.ymin}; @@ -167,7 +170,13 @@ static void datadropper_id_sample_pt(bContext *C, DataDropper *ddr, int mx, int /* grr, always draw else we leave stale text */ ED_region_tag_redraw(ar); - base = ED_view3d_give_base_under_cursor(C, mval); + if (sa->spacetype == SPACE_VIEW3D) { + base = ED_view3d_give_base_under_cursor(C, mval); + } + else { + base = ED_outliner_give_base_under_cursor(C, mval); + } + if (base) { Object *ob = base->object; ID *id = NULL; @@ -213,7 +222,7 @@ static bool datadropper_id_set(bContext *C, DataDropper *ddr, ID *id) ptr_value = RNA_property_pointer_get(&ddr->ptr, ddr->prop); - return (ptr_value.id.data == id); + return (ptr_value.owner_id == id); } /* single point sample & set */ @@ -232,6 +241,36 @@ static void datadropper_cancel(bContext *C, wmOperator *op) datadropper_exit(C, op); } +/* To switch the draw callback when region under mouse event changes */ +static void datadropper_set_draw_callback_region(bContext *C, + DataDropper *ddr, + const int mx, + const int my) +{ + bScreen *screen = CTX_wm_screen(C); + ScrArea *sa = BKE_screen_find_area_xy(screen, -1, mx, my); + + if (sa) { + /* If spacetype changed */ + if (sa->spacetype != ddr->cursor_area->spacetype) { + /* Remove old callback */ + ED_region_draw_cb_exit(ddr->art, ddr->draw_handle_pixel); + + /* Redraw old area */ + ARegion *ar = BKE_area_find_region_type(ddr->cursor_area, RGN_TYPE_WINDOW); + ED_region_tag_redraw(ar); + + /* Set draw callback in new region */ + ARegionType *art = BKE_regiontype_from_id(sa->type, RGN_TYPE_WINDOW); + + ddr->cursor_area = sa; + ddr->art = art; + ddr->draw_handle_pixel = ED_region_draw_cb_activate( + art, datadropper_draw_cb, ddr, REGION_DRAW_POST_PIXEL); + } + } +} + /* main modal status check */ static int datadropper_modal(bContext *C, wmOperator *op, const wmEvent *event) { @@ -260,6 +299,10 @@ static int datadropper_modal(bContext *C, wmOperator *op, const wmEvent *event) } else if (event->type == MOUSEMOVE) { ID *id = NULL; + + /* Set the region for eyedropper cursor text drawing */ + datadropper_set_draw_callback_region(C, ddr, event->x, event->y); + datadropper_id_sample_pt(C, ddr, event->x, event->y, &id); } diff --git a/source/blender/editors/interface/interface_eyedropper_driver.c b/source/blender/editors/interface/interface_eyedropper_driver.c index c1aee190cd3..e6fc52bc3bc 100644 --- a/source/blender/editors/interface/interface_eyedropper_driver.c +++ b/source/blender/editors/interface/interface_eyedropper_driver.c @@ -116,10 +116,10 @@ static void driverdropper_sample(bContext *C, wmOperator *op, const wmEvent *eve /* Now create driver(s) */ if (target_path && dst_path) { int success = ANIM_add_driver_with_target(op->reports, - ddr->ptr.id.data, + ddr->ptr.owner_id, dst_path, ddr->index, - target_ptr->id.data, + target_ptr->owner_id, target_path, target_index, flag, @@ -130,7 +130,7 @@ static void driverdropper_sample(bContext *C, wmOperator *op, const wmEvent *eve /* send updates */ UI_context_update_anim_flag(C); DEG_relations_tag_update(CTX_data_main(C)); - DEG_id_tag_update(ddr->ptr.id.data, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); + DEG_id_tag_update(ddr->ptr.owner_id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL); // XXX } } diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 0cb0dbdc85c..55980099116 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -757,7 +757,7 @@ static void ui_apply_but_undo(uiBut *but) } /* Optionally override undo when undo system doesn't support storing properties. */ - if (but->rnapoin.id.data) { + if (but->rnapoin.owner_id) { /* Exception for renaming ID data, we always need undo pushes in this case, * because undo systems track data by their ID, see: T67002. */ extern PropertyRNA rna_ID_name; @@ -765,7 +765,7 @@ static void ui_apply_but_undo(uiBut *but) /* pass */ } else { - ID *id = but->rnapoin.id.data; + ID *id = but->rnapoin.owner_id; if (!ED_undo_is_legacy_compatible_for_property(but->block->evil_C, id)) { str = ""; } @@ -1558,7 +1558,7 @@ static bool ui_selectcontext_begin(bContext *C, uiBut *but, uiSelectContextStore if (use_path_from_id) { /* Path relative to ID. */ lprop = NULL; - RNA_id_pointer_create(link->ptr.id.data, &idptr); + RNA_id_pointer_create(link->ptr.owner_id, &idptr); RNA_path_resolve_property(&idptr, path, &lptr, &lprop); } else if (path) { @@ -2760,7 +2760,7 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con startx += UI_DPI_ICON_SIZE / aspect; } } - /* but this extra .05 makes clicks inbetween characters feel nicer */ + /* But this extra .05 makes clicks in between characters feel nicer. */ startx += ((UI_TEXT_MARGIN_X + 0.05f) * U.widget_unit) / aspect; /* mouse dragged outside the widget to the left */ @@ -4800,18 +4800,19 @@ static int ui_do_but_NUM( if (click) { /* we can click on the side arrows to increment/decrement, * or click inside to edit the value directly */ - const float softmin = but->softmin; - const float softmax = but->softmax; if (!ui_but_is_float(but)) { /* Integer Value. */ if (but->drawflag & (UI_BUT_ACTIVE_LEFT | UI_BUT_ACTIVE_RIGHT)) { button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); + const int value_step = (int)but->a1; BLI_assert(value_step > 0); + const int softmin = round_fl_to_int_clamp(but->softmin); + const int softmax = round_fl_to_int_clamp(but->softmax); const double value_test = (but->drawflag & UI_BUT_ACTIVE_LEFT) ? - (double)max_ii((int)softmin, (int)data->value - value_step) : - (double)min_ii((int)softmax, (int)data->value + value_step); + (double)max_ii(softmin, (int)data->value - value_step) : + (double)min_ii(softmax, (int)data->value + value_step); if (value_test != data->value) { data->value = (double)value_test; } @@ -4828,11 +4829,14 @@ static int ui_do_but_NUM( /* Float Value. */ if (but->drawflag & (UI_BUT_ACTIVE_LEFT | UI_BUT_ACTIVE_RIGHT)) { button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); + const double value_step = (double)but->a1 * UI_PRECISION_FLOAT_SCALE; BLI_assert(value_step > 0.0f); const double value_test = (but->drawflag & UI_BUT_ACTIVE_LEFT) ? - (double)max_ff(softmin, (float)(data->value - value_step)) : - (double)min_ff(softmax, (float)(data->value + value_step)); + (double)max_ff(but->softmin, + (float)(data->value - value_step)) : + (double)min_ff(but->softmax, + (float)(data->value + value_step)); if (value_test != data->value) { data->value = value_test; } @@ -5484,7 +5488,7 @@ static bool ui_numedit_but_UNITVEC( static void ui_palette_set_active(uiBut *but) { if ((int)(but->a1) == UI_PALETTE_COLOR) { - Palette *palette = but->rnapoin.id.data; + Palette *palette = (Palette *)but->rnapoin.owner_id; PaletteColor *color = but->rnapoin.data; palette->active_color = BLI_findindex(&palette->colors, color); } @@ -5547,7 +5551,7 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co } else if ((int)(but->a1) == UI_PALETTE_COLOR && event->type == DELKEY && event->val == KM_PRESS) { - Palette *palette = but->rnapoin.id.data; + Palette *palette = (Palette *)but->rnapoin.owner_id; PaletteColor *color = but->rnapoin.data; BKE_palette_color_remove(palette, color); @@ -8184,7 +8188,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but) else { /* Do this so we can still mouse-up, closing the menu and running the button. * This is nice to support but there are times when the button gets left pressed. - * Keep disavled for now. */ + * Keep disabled for now. */ WM_event_remove_timer(data->wm, data->window, data->hold_action_timer); data->hold_action_timer = NULL; } diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index e9aa18394fa..7ada4755a64 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -154,8 +154,8 @@ typedef struct IconType { } IconType; /* ******************* STATIC LOCAL VARS ******************* */ -/* static here to cache results of icon directory scan, so it's not - * scanning the filesystem each time the menu is drawn */ +/* Static here to cache results of icon directory scan, so it's not + * scanning the file-system each time the menu is drawn. */ static struct ListBase iconfilelist = {NULL, NULL}; static IconTexture icongltex = {{0, 0}, 0, 0, 0, 0.0f, 0.0f}; @@ -317,8 +317,9 @@ static void vicon_keytype_draw_wrapper( format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); uint flags_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT); - immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND); GPU_program_point_size(true); + immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND); + immUniform1f("outline_scale", 1.0f); immUniform2f("ViewportSize", -1.0f, -1.0f); immBegin(GPU_PRIM_POINTS, 1); @@ -2136,7 +2137,7 @@ int UI_rnaptr_icon_get(bContext *C, PointerRNA *ptr, int rnaicon, const bool big /* try ID, material, texture or dynapaint slot */ if (RNA_struct_is_ID(ptr->type)) { - id = ptr->id.data; + id = ptr->owner_id; } else if (RNA_struct_is_a(ptr->type, &RNA_MaterialSlot)) { id = RNA_pointer_get(ptr, "material").data; @@ -2243,6 +2244,8 @@ int UI_idcode_icon_get(const int idcode) return ICON_FONT_DATA; case ID_WO: return ICON_WORLD_DATA; + case ID_WS: + return ICON_WORKSPACE; default: return ICON_NONE; } diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 78eed98eb77..529cb0712df 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -1180,11 +1180,6 @@ static uiBut *uiItemFullO_ptr_ex(uiLayout *layout, assert(but->optype != NULL); - /* text alignment for toolbar buttons */ - if ((layout->root->type == UI_LAYOUT_TOOLBAR) && !icon) { - but->drawflag |= UI_BUT_TEXT_LEFT; - } - if (flag & UI_ITEM_R_NO_BG) { layout->emboss = prev_emboss; } @@ -1878,7 +1873,8 @@ void uiItemFullR(uiLayout *layout, uiBut *but; } ui_decorate = { .use_prop_decorate = (((layout->item.flag & UI_ITEM_PROP_DECORATE) != 0) && - (use_prop_sep && ptr->id.data && id_can_have_animdata(ptr->id.data))), + (use_prop_sep && ptr->owner_id && + id_can_have_animdata(ptr->owner_id))), }; #endif /* UI_PROP_DECORATE */ @@ -2951,7 +2947,7 @@ void uiItemLDrag(uiLayout *layout, PointerRNA *ptr, const char *name, int icon) if (ptr && ptr->type) { if (RNA_struct_is_ID(ptr->type)) { - UI_but_drag_set_id(but, ptr->id.data); + UI_but_drag_set_id(but, ptr->owner_id); } } } diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 6051bf5ca40..68d21e88211 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -27,7 +27,7 @@ #include "DNA_armature_types.h" #include "DNA_screen_types.h" -#include "DNA_text_types.h" /* for UI_OT_reports_to_text */ +#include "DNA_text_types.h" #include "DNA_object_types.h" /* for OB_DATA_SUPPORT_ID */ #include "BLI_blenlib.h" @@ -45,7 +45,7 @@ #include "BKE_node.h" #include "BKE_report.h" #include "BKE_screen.h" -#include "BKE_text.h" /* for UI_OT_reports_to_text */ +#include "BKE_text.h" #include "IMB_colormanagement.h" @@ -86,7 +86,7 @@ static bool copy_data_path_button_poll(bContext *C) UI_context_active_but_prop_get(C, &ptr, &prop, &index); - if (ptr.id.data && ptr.data && prop) { + if (ptr.owner_id && ptr.data && prop) { path = RNA_path_from_ID_to_property(&ptr, prop); if (path) { @@ -100,29 +100,33 @@ static bool copy_data_path_button_poll(bContext *C) static int copy_data_path_button_exec(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); PointerRNA ptr; PropertyRNA *prop; char *path; int index; + ID *id; const bool full_path = RNA_boolean_get(op->ptr, "full_path"); /* try to create driver using property retrieved from UI */ UI_context_active_but_prop_get(C, &ptr, &prop, &index); - if (ptr.id.data != NULL) { - + if (ptr.owner_id != NULL) { if (full_path) { - if (prop) { - path = RNA_path_full_property_py_ex(&ptr, prop, index, true); + path = RNA_path_full_property_py_ex(bmain, &ptr, prop, index, true); } else { - path = RNA_path_full_struct_py(&ptr); + path = RNA_path_full_struct_py(bmain, &ptr); } } else { - path = RNA_path_from_ID_to_property(&ptr, prop); + path = RNA_path_from_real_ID_to_property_index(bmain, &ptr, prop, 0, -1, &id); + + if (!path) { + path = RNA_path_from_ID_to_property(&ptr, prop); + } } if (path) { @@ -171,7 +175,7 @@ static bool copy_as_driver_button_poll(bContext *C) UI_context_active_but_prop_get(C, &ptr, &prop, &index); - if (ptr.id.data && ptr.data && prop && + if (ptr.owner_id && ptr.data && prop && ELEM(RNA_property_type(prop), PROP_BOOLEAN, PROP_INT, PROP_FLOAT, PROP_ENUM) && (index >= 0 || !RNA_property_array_check(prop))) { path = RNA_path_from_ID_to_property(&ptr, prop); @@ -185,8 +189,9 @@ static bool copy_as_driver_button_poll(bContext *C) return 0; } -static int copy_as_driver_button_exec(bContext *C, wmOperator *UNUSED(op)) +static int copy_as_driver_button_exec(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); PointerRNA ptr; PropertyRNA *prop; int index; @@ -194,15 +199,20 @@ static int copy_as_driver_button_exec(bContext *C, wmOperator *UNUSED(op)) /* try to create driver using property retrieved from UI */ UI_context_active_but_prop_get(C, &ptr, &prop, &index); - if (ptr.id.data && ptr.data && prop) { + if (ptr.owner_id && ptr.data && prop) { + ID *id; int dim = RNA_property_array_dimension(&ptr, prop, NULL); - char *path = RNA_path_from_ID_to_property_index(&ptr, prop, dim, index); + char *path = RNA_path_from_real_ID_to_property_index(bmain, &ptr, prop, dim, index, &id); if (path) { - ANIM_copy_as_driver(ptr.id.data, path, RNA_property_identifier(prop)); + ANIM_copy_as_driver(id, path, RNA_property_identifier(prop)); MEM_freeN(path); return OPERATOR_FINISHED; } + else { + BKE_reportf(op->reports, RPT_ERROR, "Could not compute a valid data path"); + return OPERATOR_CANCELLED; + } } return OPERATOR_CANCELLED; @@ -287,7 +297,7 @@ static void UI_OT_copy_python_command_button(wmOperatorType *ot) static int operator_button_property_finish(bContext *C, PointerRNA *ptr, PropertyRNA *prop) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; /* perform updates required for this property */ RNA_property_update(C, ptr, prop); @@ -542,7 +552,7 @@ static int override_type_set_button_exec(bContext *C, wmOperator *op) /* try to reset the nominated setting to its default value */ UI_context_active_but_prop_get(C, &ptr, &prop, &index); - BLI_assert(ptr.id.data != NULL); + BLI_assert(ptr.owner_id != NULL); if (all) { index = -1; @@ -605,7 +615,7 @@ static bool override_remove_button_poll(bContext *C) const int override_status = RNA_property_override_library_status(&ptr, prop, index); - return (ptr.data && ptr.id.data && prop && (override_status & RNA_OVERRIDE_STATUS_OVERRIDDEN)); + return (ptr.data && ptr.owner_id && prop && (override_status & RNA_OVERRIDE_STATUS_OVERRIDDEN)); } static int override_remove_button_exec(bContext *C, wmOperator *op) @@ -619,7 +629,7 @@ static int override_remove_button_exec(bContext *C, wmOperator *op) /* try to reset the nominated setting to its default value */ UI_context_active_but_prop_get(C, &ptr, &prop, &index); - ID *id = ptr.id.data; + ID *id = ptr.owner_id; IDOverrideLibraryProperty *oprop = RNA_property_override_property_find(&ptr, prop); BLI_assert(oprop != NULL); BLI_assert(id != NULL && id->override_library != NULL); @@ -629,8 +639,9 @@ static int override_remove_button_exec(bContext *C, wmOperator *op) /* We need source (i.e. linked data) to restore values of deleted overrides... * If this is an override template, we obviously do not need to restore anything. */ if (!is_template) { + PropertyRNA *src_prop; RNA_id_pointer_create(id->override_library->reference, &id_refptr); - if (!RNA_path_resolve(&id_refptr, oprop->rna_path, &src, NULL)) { + if (!RNA_path_resolve_property(&id_refptr, oprop->rna_path, &src, &src_prop)) { BLI_assert(0 && "Failed to create matching source (linked data) RNA pointer"); } } @@ -720,7 +731,7 @@ bool UI_context_copy_to_selected_list(bContext *C, CollectionPointerLink *link; for (link = lb.first; link; link = link->next) { bPoseChannel *pchan = link->ptr.data; - RNA_pointer_create(link->ptr.id.data, &RNA_Bone, pchan->bone, &link->ptr); + RNA_pointer_create(link->ptr.owner_id, &RNA_Bone, pchan->bone, &link->ptr); } } @@ -739,7 +750,7 @@ bool UI_context_copy_to_selected_list(bContext *C, /* Get the node we're editing */ if (RNA_struct_is_a(ptr->type, &RNA_NodeSocket)) { - bNodeTree *ntree = ptr->id.data; + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; bNodeSocket *sock = ptr->data; if (nodeFindNode(ntree, sock, &node, NULL)) { if ((path = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_Node)) != NULL) { @@ -773,8 +784,8 @@ bool UI_context_copy_to_selected_list(bContext *C, *r_lb = lb; *r_path = path; } - else if (ptr->id.data) { - ID *id = ptr->id.data; + else if (ptr->owner_id) { + ID *id = ptr->owner_id; if (GS(id->name) == ID_OB) { *r_lb = CTX_data_collection_get(C, "selected_editable_objects"); @@ -792,7 +803,7 @@ bool UI_context_copy_to_selected_list(bContext *C, CollectionPointerLink *link, *link_next; for (link = lb.first; link; link = link->next) { - Object *ob = link->ptr.id.data; + Object *ob = (Object *)link->ptr.owner_id; if (ob->data) { ID *id_data = ob->data; id_data->tag |= LIB_TAG_DOIT; @@ -800,7 +811,7 @@ bool UI_context_copy_to_selected_list(bContext *C, } for (link = lb.first; link; link = link_next) { - Object *ob = link->ptr.id.data; + Object *ob = (Object *)link->ptr.owner_id; ID *id_data = ob->data; link_next = link->next; @@ -872,7 +883,7 @@ static bool copy_to_selected_button(bContext *C, bool all, bool poll) if (use_path_from_id) { /* Path relative to ID. */ lprop = NULL; - RNA_id_pointer_create(link->ptr.id.data, &idptr); + RNA_id_pointer_create(link->ptr.owner_id, &idptr); RNA_path_resolve_property(&idptr, path, &lptr, &lprop); } else if (path) { @@ -982,12 +993,12 @@ static bool jump_to_target_ptr(bContext *C, PointerRNA ptr, const bool poll) /* Find the containing Object. */ ViewLayer *view_layer = CTX_data_view_layer(C); Base *base = NULL; - const short id_type = GS(((ID *)ptr.id.data)->name); + const short id_type = GS(ptr.owner_id->name); if (id_type == ID_OB) { - base = BKE_view_layer_base_find(view_layer, ptr.id.data); + base = BKE_view_layer_base_find(view_layer, (Object *)ptr.owner_id); } else if (OB_DATA_SUPPORT_ID(id_type)) { - base = ED_object_find_first_by_data_id(view_layer, ptr.id.data); + base = ED_object_find_first_by_data_id(view_layer, ptr.owner_id); } bool ok = false; @@ -1096,60 +1107,6 @@ static void UI_OT_jump_to_target_button(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Reports to Textblock Operator - * \{ */ - -/* FIXME: this is just a temporary operator so that we can see all the reports somewhere - * when there are too many to display... - */ - -static bool reports_to_text_poll(bContext *C) -{ - return CTX_wm_reports(C) != NULL; -} - -static int reports_to_text_exec(bContext *C, wmOperator *UNUSED(op)) -{ - ReportList *reports = CTX_wm_reports(C); - Main *bmain = CTX_data_main(C); - Text *txt; - char *str; - - /* create new text-block to write to */ - txt = BKE_text_add(bmain, "Recent Reports"); - - /* convert entire list to a display string, and add this to the text-block - * - if commandline debug option enabled, show debug reports too - * - otherwise, up to info (which is what users normally see) - */ - str = BKE_reports_string(reports, (G.debug & G_DEBUG) ? RPT_DEBUG : RPT_INFO); - - if (str) { - BKE_text_write(txt, str); - MEM_freeN(str); - - return OPERATOR_FINISHED; - } - else { - return OPERATOR_CANCELLED; - } -} - -static void UI_OT_reports_to_textblock(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Reports to Text Block"; - ot->idname = "UI_OT_reports_to_textblock"; - ot->description = "Write the reports "; - - /* callbacks */ - ot->poll = reports_to_text_poll; - ot->exec = reports_to_text_exec; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Edit Python Source Operator * \{ */ @@ -1750,7 +1707,6 @@ void ED_operatortypes_ui(void) WM_operatortype_append(UI_OT_override_remove_button); WM_operatortype_append(UI_OT_copy_to_selected_button); WM_operatortype_append(UI_OT_jump_to_target_button); - WM_operatortype_append(UI_OT_reports_to_textblock); /* XXX: temp? */ WM_operatortype_append(UI_OT_drop_color); #ifdef WITH_PYTHON WM_operatortype_append(UI_OT_editsource); diff --git a/source/blender/editors/interface/interface_region_popup.c b/source/blender/editors/interface/interface_region_popup.c index f3e18cc2f24..2073117d51c 100644 --- a/source/blender/editors/interface/interface_region_popup.c +++ b/source/blender/editors/interface/interface_region_popup.c @@ -690,9 +690,11 @@ uiBlock *ui_popup_block_refresh(bContext *C, /* Avoid menu moving down and losing cursor focus by keeping it at * the same height. */ if (handle->refresh && handle->prev_block_rect.ymax > block->rect.ymax) { - float offset = handle->prev_block_rect.ymax - block->rect.ymax; - UI_block_translate(block, 0, offset); - block->rect.ymin = handle->prev_block_rect.ymin; + if (block->bounds_type != UI_BLOCK_BOUNDS_POPUP_CENTER) { + float offset = handle->prev_block_rect.ymax - block->rect.ymax; + UI_block_translate(block, 0, offset); + block->rect.ymin = handle->prev_block_rect.ymin; + } } handle->prev_block_rect = block->rect; diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c index 6aad9e41e7d..7387fe5eb1c 100644 --- a/source/blender/editors/interface/interface_region_tooltip.c +++ b/source/blender/editors/interface/interface_region_tooltip.c @@ -765,8 +765,8 @@ static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but) } } - if (but->rnapoin.id.data) { - const ID *id = but->rnapoin.id.data; + if (but->rnapoin.owner_id) { + const ID *id = but->rnapoin.owner_id; if (ID_IS_LINKED(id)) { uiTooltipField *field = text_field_add(data, &(uiTooltipFormat){ @@ -847,7 +847,7 @@ static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but) } } - if (but->rnapoin.id.data) { + if (but->rnapoin.owner_id) { uiTooltipField *field = text_field_add(data, &(uiTooltipFormat){ .style = UI_TIP_STYLE_MONO, @@ -860,10 +860,10 @@ static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but) /* move ownership (no need for re-alloc) */ if (but->rnaprop) { field->text = RNA_path_full_property_py_ex( - &but->rnapoin, but->rnaprop, but->rnaindex, true); + CTX_data_main(C), &but->rnapoin, but->rnaprop, but->rnaindex, true); } else { - field->text = RNA_path_full_struct_py(&but->rnapoin); + field->text = RNA_path_full_struct_py(CTX_data_main(C), &but->rnapoin); } } } diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 37eb1770f68..f53bef877c4 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -121,7 +121,7 @@ static void template_add_button_search_menu(const bContext *C, { PointerRNA active_ptr = RNA_property_pointer_get(ptr, prop); ID *id = (active_ptr.data && RNA_struct_is_ID(active_ptr.type)) ? active_ptr.data : NULL; - const ID *idfrom = ptr->id.data; + const ID *idfrom = ptr->owner_id; const StructRNA *type = active_ptr.type ? active_ptr.type : RNA_property_pointer_type(ptr, prop); uiBut *but; @@ -310,7 +310,7 @@ static bool id_search_add(const bContext *C, uiSearchItems *items, ID *id) { - ID *id_from = template_ui->ptr.id.data; + ID *id_from = template_ui->ptr.owner_id; if (!((flag & PROP_ID_SELF_CHECK) && id == id_from)) { @@ -401,7 +401,7 @@ static void id_search_cb_objects_from_scene(const bContext *C, TemplateID *template_ui = (TemplateID *)arg_template; ListBase *lb = template_ui->idlb; Scene *scene = NULL; - ID *id_from = template_ui->ptr.id.data; + ID *id_from = template_ui->ptr.owner_id; if (id_from && GS(id_from->name) == ID_SCE) { scene = (Scene *)id_from; @@ -538,7 +538,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) break; case UI_ID_OVERRIDE: if (id && id->override_library) { - BKE_override_library_free(&id->override_library); + BKE_override_library_free(&id->override_library, true); /* reassign to get get proper updates/notifiers */ idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop); RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL); @@ -667,7 +667,7 @@ static uiBut *template_id_def_new_but(uiBlock *block, const bool use_tab_but, int but_height) { - ID *idfrom = template_ui->ptr.id.data; + ID *idfrom = template_ui->ptr.owner_id; uiBut *but; const int w = id ? UI_UNIT_X : id_open ? UI_UNIT_X * 3 : UI_UNIT_X * 6; const int but_type = use_tab_but ? UI_BTYPE_TAB : UI_BTYPE_BUT; @@ -769,7 +769,7 @@ static void template_ID(bContext *C, idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop); id = idptr.data; - idfrom = template_ui->ptr.id.data; + idfrom = template_ui->ptr.owner_id; // lb = template_ui->idlb; block = uiLayoutGetBlock(layout); @@ -2037,7 +2037,7 @@ uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr) return NULL; } - ob = ptr->id.data; + ob = (Object *)ptr->owner_id; md = ptr->data; if (!ob || !(GS(ob->id.name) == ID_OB)) { @@ -2179,7 +2179,7 @@ uiLayout *uiTemplateGpencilModifier(uiLayout *layout, bContext *UNUSED(C), Point return NULL; } - ob = ptr->id.data; + ob = (Object *)ptr->owner_id; md = ptr->data; if (!ob || !(GS(ob->id.name) == ID_OB)) { @@ -2297,7 +2297,7 @@ uiLayout *uiTemplateShaderFx(uiLayout *layout, bContext *UNUSED(C), PointerRNA * return NULL; } - ob = ptr->id.data; + ob = (Object *)ptr->owner_id; fx = ptr->data; if (!ob || !(GS(ob->id.name) == ID_OB)) { @@ -2523,7 +2523,7 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con) /* enabled */ UI_block_emboss_set(block, UI_EMBOSS_NONE); - uiItemR(row, &ptr, "mute", 0, "", (con->flag & CONSTRAINT_OFF) ? ICON_HIDE_ON : ICON_HIDE_OFF); + uiItemR(row, &ptr, "mute", 0, "", 0); UI_block_emboss_set(block, UI_EMBOSS); uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT); @@ -2579,7 +2579,7 @@ uiLayout *uiTemplateConstraint(uiLayout *layout, PointerRNA *ptr) return NULL; } - ob = ptr->id.data; + ob = (Object *)ptr->owner_id; con = ptr->data; if (!ob || !(GS(ob->id.name) == ID_OB)) { @@ -3098,7 +3098,7 @@ static void colorband_buttons_layout(uiLayout *layout, float ys = butr->ymin; PointerRNA ptr; - RNA_pointer_create(cb->ptr.id.data, &RNA_ColorRamp, coba, &ptr); + RNA_pointer_create(cb->ptr.owner_id, &RNA_ColorRamp, coba, &ptr); split = uiLayoutSplit(layout, 0.4f, false); @@ -3190,7 +3190,7 @@ static void colorband_buttons_layout(uiLayout *layout, if (coba->tot) { CBData *cbd = coba->data + coba->cur; - RNA_pointer_create(cb->ptr.id.data, &RNA_ColorRampElement, cbd, &ptr); + RNA_pointer_create(cb->ptr.owner_id, &RNA_ColorRampElement, cbd, &ptr); if (!expand) { split = uiLayoutSplit(layout, 0.3f, false); @@ -3207,7 +3207,7 @@ static void colorband_buttons_layout(uiLayout *layout, &coba->cur, 0.0, (float)(MAX2(0, coba->tot - 1)), - 0, + 1, 0, TIP_("Choose active color stop")); row = uiLayoutRow(split, false); @@ -3237,7 +3237,7 @@ static void colorband_buttons_layout(uiLayout *layout, &coba->cur, 0.0, (float)(MAX2(0, coba->tot - 1)), - 0, + 1, 0, TIP_("Choose active color stop")); row = uiLayoutRow(subsplit, false); @@ -3283,7 +3283,7 @@ void uiTemplateColorRamp(uiLayout *layout, PointerRNA *ptr, const char *propname block = uiLayoutAbsoluteBlock(layout); - id = cptr.id.data; + id = cptr.owner_id; UI_block_lock_set(block, (id && ID_IS_LINKED(id)), ERROR_LIBDATA_MESSAGE); colorband_buttons_layout(layout, block, cptr.data, &rect, cb, expand); @@ -3745,12 +3745,11 @@ static uiBlock *curvemap_clipping_func(bContext *C, ARegion *ar, void *cumap_v) float width = 8 * UI_UNIT_X; block = UI_block_begin(C, ar, __func__, UI_EMBOSS); - - /* use this for a fake extra empty space around the buttons */ - uiDefBut(block, UI_BTYPE_LABEL, 0, "", -4, 16, width + 8, 6 * UI_UNIT_Y, NULL, 0, 0, 0, 0, ""); + UI_block_flag_enable(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_MOVEMOUSE_QUIT); + UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP); bt = uiDefButBitI(block, - UI_BTYPE_TOGGLE, + UI_BTYPE_CHECKBOX, CUMA_DO_CLIP, 1, IFACE_("Use Clipping"), @@ -3770,7 +3769,7 @@ static uiBlock *curvemap_clipping_func(bContext *C, ARegion *ar, void *cumap_v) uiDefButF(block, UI_BTYPE_NUM, 0, - IFACE_("Min X "), + IFACE_("Min X:"), 0, 4 * UI_UNIT_Y, width, @@ -3784,7 +3783,7 @@ static uiBlock *curvemap_clipping_func(bContext *C, ARegion *ar, void *cumap_v) uiDefButF(block, UI_BTYPE_NUM, 0, - IFACE_("Min Y "), + IFACE_("Min Y:"), 0, 3 * UI_UNIT_Y, width, @@ -3798,7 +3797,7 @@ static uiBlock *curvemap_clipping_func(bContext *C, ARegion *ar, void *cumap_v) uiDefButF(block, UI_BTYPE_NUM, 0, - IFACE_("Max X "), + IFACE_("Max X:"), 0, 2 * UI_UNIT_Y, width, @@ -3812,7 +3811,7 @@ static uiBlock *curvemap_clipping_func(bContext *C, ARegion *ar, void *cumap_v) uiDefButF(block, UI_BTYPE_NUM, 0, - IFACE_("Max Y "), + IFACE_("Max Y:"), 0, UI_UNIT_Y, width, @@ -3824,7 +3823,8 @@ static uiBlock *curvemap_clipping_func(bContext *C, ARegion *ar, void *cumap_v) 2, ""); - UI_block_direction_set(block, UI_DIR_RIGHT); + UI_block_bounds_set_normal(block, 0.3f * U.widget_unit); + UI_block_direction_set(block, UI_DIR_DOWN); return block; } @@ -4405,7 +4405,7 @@ void uiTemplateCurveMapping(uiLayout *layout, cb->ptr = *ptr; cb->prop = prop; - id = cptr.id.data; + id = cptr.owner_id; UI_block_lock_set(block, (id && ID_IS_LINKED(id)), ERROR_LIBDATA_MESSAGE); curvemap_buttons_layout(layout, &cptr, type, levels, brush, neg_slope, tone, cb); @@ -6378,7 +6378,7 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C) if (reports->list.first != reports->list.last) { uiDefIconButO(block, UI_BTYPE_BUT, - "UI_OT_reports_to_textblock", + "SCREEN_OT_info_log_show", WM_OP_INVOKE_REGION_WIN, icon, 2, @@ -6392,22 +6392,17 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C) block, UI_BTYPE_LABEL, 0, icon, 2, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, ""); } - UI_block_emboss_set(block, UI_EMBOSS); - - uiDefBut(block, - UI_BTYPE_LABEL, - 0, - report->message, - UI_UNIT_X + 5, - 0, - UI_UNIT_X + width, - UI_UNIT_Y, - NULL, - 0.0f, - 0.0f, - 0, - 0, - ""); + but = uiDefButO(block, + UI_BTYPE_BUT, + "SCREEN_OT_info_log_show", + WM_OP_INVOKE_REGION_WIN, + report->message, + UI_UNIT_X + 5, + 0, + UI_UNIT_X + width, + UI_UNIT_Y, + "Show in Info Log"); + rgba_float_to_uchar(but->col, rti->col); } void uiTemplateInputStatus(uiLayout *layout, struct bContext *C) @@ -6627,7 +6622,7 @@ static uiBlock *component_menu(bContext *C, ARegion *ar, void *args_v) uiItemR(layout, &args->ptr, args->propname, UI_ITEM_R_EXPAND, "", ICON_NONE); - UI_block_bounds_set_normal(block, 6); + UI_block_bounds_set_normal(block, 0.3f * U.widget_unit); UI_block_direction_set(block, UI_DIR_DOWN); return block; diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c index 9c8787d002f..63e382e2280 100644 --- a/source/blender/editors/interface/interface_utils.c +++ b/source/blender/editors/interface/interface_utils.c @@ -405,7 +405,7 @@ void ui_rna_collection_search_cb(const struct bContext *C, RNA_PROP_BEGIN (&data->search_ptr, itemptr, data->search_prop) { if (flag & PROP_ID_SELF_CHECK) { - if (itemptr.data == data->target_ptr.id.data) { + if (itemptr.data == data->target_ptr.owner_id) { continue; } } @@ -566,7 +566,7 @@ int UI_calc_float_precision(int prec, double value) bool UI_but_online_manual_id(const uiBut *but, char *r_str, size_t maxlength) { - if (but->rnapoin.id.data && but->rnapoin.data && but->rnaprop) { + if (but->rnapoin.owner_id && but->rnapoin.data && but->rnaprop) { BLI_snprintf(r_str, maxlength, "%s.%s", diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 9c4d628cec5..8d22c5b85bb 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -2188,7 +2188,7 @@ static void widget_draw_text(const uiFontStyle *fstyle, drawstr_right = strrchr(drawstr + but->ofs, ':'); if (drawstr_right) { drawstr_right++; - drawstr_left_len = (drawstr_right - drawstr); + drawstr_left_len = (drawstr_right - drawstr - 1); while (*drawstr_right == ' ') { drawstr_right++; @@ -2587,6 +2587,10 @@ static void widget_state(uiWidgetType *wt, int state, int drawflag) } } else { + if (state & UI_BUT_ACTIVE_DEFAULT) { + copy_v4_v4_uchar(wt->wcol.inner, wt->wcol.inner_sel); + copy_v4_v4_uchar(wt->wcol.text, wt->wcol.text_sel); + } if (color_blend != NULL) { widget_state_blend(wt->wcol.inner, color_blend, wcol_state->blend); } @@ -2709,10 +2713,10 @@ static void widget_state_menu_item(uiWidgetType *wt, int state, int UNUSED(drawf /* active and disabled (not so common) */ if ((state & UI_BUT_DISABLED) && (state & UI_ACTIVE)) { - widget_state_blend(wt->wcol.text, wt->wcol.text_sel, 0.5f); /* draw the backdrop at low alpha, helps navigating with keys * when disabled items are active */ - copy_v4_v4_uchar(wt->wcol.inner, wt->wcol.inner_sel); + wt->wcol.text[3] = 128; + widget_state_blend(wt->wcol.inner, wt->wcol.text, 0.5f); wt->wcol.inner[3] = 64; } else { @@ -3268,20 +3272,6 @@ static void ui_draw_but_HSV_v(uiBut *but, const rcti *rect) ui_hsv_cursor(x, y); } -/* Generic round-box drawing. */ -static void ui_draw_roundbox(const rcti *rect, const float rad, const uiWidgetColors *wcol) -{ - uiWidgetBase wtb; - widget_init(&wtb); - round_box_edges(&wtb, UI_CNR_ALL, rect, rad); - widgetbase_draw(&wtb, wcol); - - /* We are drawing on top of widget bases. Flush cache. */ - GPU_blend(true); - UI_widgetbase_draw_cache_flush(); - GPU_blend(false); -} - /* ************ separator, for menus etc ***************** */ static void ui_draw_separator(const rcti *rect, const uiWidgetColors *wcol) { @@ -3802,7 +3792,7 @@ static void widget_swatch( widgetbase_draw_ex(&wtb, wcol, show_alpha_checkers); if (but->a1 == UI_PALETTE_COLOR && - ((Palette *)but->rnapoin.id.data)->active_color == (int)but->a2) { + ((Palette *)but->rnapoin.owner_id)->active_color == (int)but->a2) { float width = rect->xmax - rect->xmin; float height = rect->ymax - rect->ymin; /* find color luminance and change it slightly */ @@ -4497,10 +4487,6 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct const uiFontStyle *fstyle = &style->widget; uiWidgetType *wt = NULL; -#ifdef USE_UI_POPOVER_ONCE - const rcti rect_orig = *rect; -#endif - /* handle menus separately */ if (but->dt == UI_EMBOSS_PULLDOWN) { switch (but->type) { @@ -4786,6 +4772,14 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct ui_widget_color_disabled(wt); } +#ifdef USE_UI_POPOVER_ONCE + if (but->block->flag & UI_BLOCK_POPOVER_ONCE) { + if ((state & UI_ACTIVE) && ui_but_is_popover_once_compat(but)) { + state |= UI_BUT_ACTIVE_DEFAULT; + } + } +#endif + wt->state(wt, state, drawflag); if (wt->custom) { wt->custom(but, &wt->wcol, rect, state, roundboxalign); @@ -4798,42 +4792,10 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct GPU_blend(true); } - bool show_semi_highlight = false; - -#ifdef USE_UI_POPOVER_ONCE - if (but->block->flag & UI_BLOCK_POPOVER_ONCE) { - if ((state & UI_ACTIVE) && ui_but_is_popover_once_compat(but)) { - show_semi_highlight = true; - } - } -#endif - if (but->flag & UI_BUT_ACTIVE_DEFAULT) { - show_semi_highlight = true; - } - - if (show_semi_highlight) { - uiWidgetType wt_back = *wt; - uiWidgetType *wt_temp = widget_type(UI_WTYPE_MENU_ITEM); - wt_temp->state(wt_temp, state, drawflag); - copy_v4_v4_uchar(wt->wcol.inner, wt->wcol.inner_sel); - wt->wcol.inner[3] = 128; - wt->wcol.roundness = 0.5f; - ui_draw_roundbox(&rect_orig, - 0.25f * min_ff(BLI_rcti_size_x(&rect_orig), BLI_rcti_size_y(&rect_orig)), - &wt_temp->wcol); - *wt = wt_back; - } - wt->text(fstyle, &wt->wcol, but, rect); if (disabled) { GPU_blend(false); } - - // if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) { - // if (but->dt != UI_EMBOSS_PULLDOWN) { - // widget_disabled(&disablerect); - // } - // } } } diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 1e74ee50dab..93a93fb6918 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -794,6 +794,10 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid) cp = ts->selected_highlight; break; + case TH_SELECT_ACTIVE: + cp = ts->active; + break; + case TH_SELECTED_OBJECT: cp = ts->selected_object; break; diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index f32fcffabd4..032fb7e4cc2 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -1844,7 +1844,7 @@ static void scroller_activate_init(bContext *C, */ scrollers = UI_view2d_scrollers_calc(v2d, NULL); - /* use a union of 'cur' & 'tot' incase the current view is far outside 'tot'. In this cases + /* Use a union of 'cur' & 'tot' in case the current view is far outside 'tot'. In this cases * moving the scroll bars has far too little effect and the view can get stuck T31476. */ tot_cur_union = v2d->tot; BLI_rctf_union(&tot_cur_union, &v2d->cur); diff --git a/source/blender/editors/mask/mask_shapekey.c b/source/blender/editors/mask/mask_shapekey.c index edc22943124..1abe805192d 100644 --- a/source/blender/editors/mask/mask_shapekey.c +++ b/source/blender/editors/mask/mask_shapekey.c @@ -81,6 +81,7 @@ void MASK_OT_shape_key_insert(wmOperatorType *ot) { /* identifiers */ ot->name = "Insert Shape Key"; + ot->description = "Insert mask shape keyframe for active mask layer at the current frame"; ot->idname = "MASK_OT_shape_key_insert"; /* api callbacks */ @@ -129,6 +130,7 @@ void MASK_OT_shape_key_clear(wmOperatorType *ot) { /* identifiers */ ot->name = "Clear Shape Key"; + ot->description = "Remove mask shape keyframe for active mask layer at the current frame"; ot->idname = "MASK_OT_shape_key_clear"; /* api callbacks */ diff --git a/source/blender/editors/mesh/CMakeLists.txt b/source/blender/editors/mesh/CMakeLists.txt index 9a779db4812..d7d020ae19d 100644 --- a/source/blender/editors/mesh/CMakeLists.txt +++ b/source/blender/editors/mesh/CMakeLists.txt @@ -43,6 +43,7 @@ set(SRC editface.c editmesh_add.c editmesh_add_gizmo.c + editmesh_automerge.c editmesh_bevel.c editmesh_bisect.c editmesh_extrude.c diff --git a/source/blender/editors/mesh/editmesh_automerge.c b/source/blender/editors/mesh/editmesh_automerge.c new file mode 100644 index 00000000000..82f53aafad8 --- /dev/null +++ b/source/blender/editors/mesh/editmesh_automerge.c @@ -0,0 +1,517 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup edmesh + * + * Utility functions for merging geometry once transform has finished: + * + * - #EDBM_automerge + * - #EDBM_automerge_and_split + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_bitmap.h" +#include "BLI_math.h" +#include "BLI_sort.h" + +#include "BKE_bvhutils.h" +#include "BKE_editmesh.h" + +#include "WM_api.h" + +#include "ED_mesh.h" +#include "ED_screen.h" +#include "ED_transform.h" + +#include "DNA_object_types.h" + +#include "DEG_depsgraph.h" + +/* use bmesh operator flags for a few operators */ +#define BMO_ELE_TAG 1 + +/* -------------------------------------------------------------------- */ +/** \name Auto-Merge Selection + * + * Used after transform operations. + * \{ */ + +void EDBM_automerge(Object *obedit, bool update, const char hflag, const float dist) +{ + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMesh *bm = em->bm; + int totvert_prev = bm->totvert; + + BMOperator findop, weldop; + + /* Search for doubles among all vertices, but only merge non-VERT_KEEP + * vertices into VERT_KEEP vertices. */ + BMO_op_initf(bm, + &findop, + BMO_FLAG_DEFAULTS, + "find_doubles verts=%av keep_verts=%Hv dist=%f", + hflag, + dist); + + BMO_op_exec(bm, &findop); + + /* weld the vertices */ + BMO_op_init(bm, &weldop, BMO_FLAG_DEFAULTS, "weld_verts"); + BMO_slot_copy(&findop, slots_out, "targetmap.out", &weldop, slots_in, "targetmap"); + BMO_op_exec(bm, &weldop); + + BMO_op_finish(bm, &findop); + BMO_op_finish(bm, &weldop); + + if ((totvert_prev != bm->totvert) && update) { + EDBM_update_generic(em, true, true); + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Auto-Merge & Split Selection + * + * Used after transform operations. + * \{ */ + +struct EDBMSplitEdge { + BMVert *v; + BMEdge *e; + float lambda; +}; + +struct EDBMSplitBestFaceData { + BMEdge **edgenet; + int edgenet_len; + + /** + * Track the range of vertices in edgenet along the faces normal, + * find the lowest since it's most likely to be most co-planar with the face. + */ + float best_face_range_on_normal_axis; + BMFace *r_best_face; +}; + +struct EDBMSplitEdgeData { + BMesh *bm; + + BMEdge *r_edge; + float r_lambda; +}; + +static bool edbm_vert_pair_share_best_splittable_face_cb(BMFace *f, + BMLoop *UNUSED(l_a), + BMLoop *UNUSED(l_b), + void *userdata) +{ + struct EDBMSplitBestFaceData *data = userdata; + float no[3], min = FLT_MAX, max = -FLT_MAX; + copy_v3_v3(no, f->no); + + BMVert *verts[2] = {NULL}; + BMEdge **e_iter = &data->edgenet[0]; + for (int i = data->edgenet_len; i--; e_iter++) { + BMIter iter; + BMVert *v; + BM_ITER_ELEM (v, &iter, *e_iter, BM_VERTS_OF_EDGE) { + if (!ELEM(v, verts[0], verts[1])) { + float dot = dot_v3v3(v->co, no); + if (dot < min) { + min = dot; + } + if (dot > max) { + max = dot; + } + } + } + verts[0] = (*e_iter)->v1; + verts[1] = (*e_iter)->v2; + } + + const float test_face_range_on_normal_axis = max - min; + if (test_face_range_on_normal_axis < data->best_face_range_on_normal_axis) { + data->best_face_range_on_normal_axis = test_face_range_on_normal_axis; + data->r_best_face = f; + } + + return false; +} + +/* find the best splittable face between the two vertices. */ +static bool edbm_vert_pair_share_splittable_face_cb(BMFace *UNUSED(f), + BMLoop *l_a, + BMLoop *l_b, + void *userdata) +{ + float(*data)[3] = userdata; + float *v_a_co = data[0]; + float *v_a_b_dir = data[1]; + + float lambda; + if (isect_ray_seg_v3(v_a_co, v_a_b_dir, l_a->prev->v->co, l_a->next->v->co, &lambda)) { + if (IN_RANGE(lambda, 0.0f, 1.0f)) { + return true; + } + else if (isect_ray_seg_v3(v_a_co, v_a_b_dir, l_b->prev->v->co, l_b->next->v->co, &lambda)) { + return IN_RANGE(lambda, 0.0f, 1.0f); + } + } + return false; +} + +static void edbm_automerge_weld_linked_wire_edges_into_linked_faces(BMesh *bm, + BMVert *v, + BMEdge **r_edgenet[], + int *r_edgenet_alloc_len) +{ + BMEdge **edgenet = *r_edgenet; + int edgenet_alloc_len = *r_edgenet_alloc_len; + + BMIter iter; + BMEdge *e; + BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { + int edgenet_len = 0; + BMVert *v_other = v; + while (BM_edge_is_wire(e)) { + if (edgenet_alloc_len == edgenet_len) { + edgenet_alloc_len = (edgenet_alloc_len + 1) * 2; + edgenet = MEM_reallocN(edgenet, (edgenet_alloc_len) * sizeof(*edgenet)); + } + edgenet[edgenet_len++] = e; + v_other = BM_edge_other_vert(e, v_other); + if (v_other == v) { + /* Endless loop. */ + break; + } + + BMEdge *e_next = BM_DISK_EDGE_NEXT(e, v_other); + if (e_next == e) { + /* Vert is wire_endpoint */ + edgenet_len = 0; + break; + } + e = e_next; + } + + BMLoop *dummy; + BMFace *best_face; + if (edgenet_len == 0) { + /* Nothing to do. */ + continue; + } + if (edgenet_len == 1) { + float data[2][3]; + copy_v3_v3(data[0], v_other->co); + sub_v3_v3v3(data[1], v->co, data[0]); + best_face = BM_vert_pair_shared_face_cb( + v_other, v, true, edbm_vert_pair_share_splittable_face_cb, &data, &dummy, &dummy); + } + else { + struct EDBMSplitBestFaceData data = { + .edgenet = edgenet, + .edgenet_len = edgenet_len, + .best_face_range_on_normal_axis = FLT_MAX, + .r_best_face = NULL, + }; + BM_vert_pair_shared_face_cb( + v_other, v, true, edbm_vert_pair_share_best_splittable_face_cb, &data, &dummy, &dummy); + + best_face = data.r_best_face; + } + + if (best_face) { + BM_face_split_edgenet(bm, best_face, edgenet, edgenet_len, NULL, NULL); + } + } + + *r_edgenet = edgenet; + *r_edgenet_alloc_len = edgenet_alloc_len; +} + +static void ebbm_automerge_and_split_find_duplicate_cb(void *userdata, + int index, + const float co[3], + BVHTreeNearest *nearest) +{ + struct EDBMSplitEdgeData *data = userdata; + BMEdge *e = BM_edge_at_index(data->bm, index); + float lambda = line_point_factor_v3_ex(co, e->v1->co, e->v2->co, 0.0f, -1.0f); + if (IN_RANGE(lambda, 0.0f, 1.0f)) { + float near_co[3]; + interp_v3_v3v3(near_co, e->v1->co, e->v2->co, lambda); + float dist_sq = len_squared_v3v3(near_co, co); + if (dist_sq < nearest->dist_sq) { + nearest->dist_sq = dist_sq; + nearest->index = index; + + data->r_edge = e; + data->r_lambda = lambda; + } + } +} + +static int edbm_automerge_and_split_sort_cmp_by_keys_cb(const void *index1_v, + const void *index2_v, + void *keys_v) +{ + const struct EDBMSplitEdge *cuts = keys_v; + const int *index1 = (int *)index1_v; + const int *index2 = (int *)index2_v; + + if (cuts[*index1].lambda > cuts[*index2].lambda) { + return 1; + } + else { + return -1; + } +} + +void EDBM_automerge_and_split(Object *obedit, + bool split_edges, + bool split_faces, + bool update, + const char hflag, + const float dist) +{ + bool ok = false; + + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMesh *bm = em->bm; + BMOperator findop, weldop; + BMOpSlot *slot_targetmap; + BMIter iter; + BMVert *v; + + /* tag and count the verts to be tested. */ + BM_mesh_elem_toolflags_ensure(bm); + int verts_len = 0; + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(v, hflag)) { + BM_elem_flag_enable(v, BM_ELEM_TAG); + BMO_vert_flag_enable(bm, v, BMO_ELE_TAG); + verts_len++; + } + else { + BM_elem_flag_disable(v, BM_ELEM_TAG); + } + } + + /* Search for doubles among all vertices, but only merge non-BMO_ELE_TAG + * vertices into BMO_ELE_TAG vertices. */ + BMO_op_initf(bm, &findop, 0, "find_doubles verts=%av keep_verts=%Fv dist=%f", BMO_ELE_TAG, dist); + BMO_op_exec(bm, &findop); + + /* Init weld_verts operator to later fill the targetmap. */ + BMO_op_init(bm, &weldop, 0, "weld_verts"); + BMO_slot_copy(&findop, slots_out, "targetmap.out", &weldop, slots_in, "targetmap"); + + slot_targetmap = BMO_slot_get(weldop.slots_in, "targetmap"); + + /* Remove duplicate vertices from the split edge test and check and split faces. */ + GHashIterator gh_iter; + GHash *ghash_targetmap = BMO_SLOT_AS_GHASH(slot_targetmap); + GHASH_ITER (gh_iter, ghash_targetmap) { + v = BLI_ghashIterator_getKey(&gh_iter); + BMVert *v_dst = BLI_ghashIterator_getValue(&gh_iter); + if (!BM_elem_flag_test(v, BM_ELEM_TAG)) { + /* Should this happen? */ + SWAP(BMVert *, v, v_dst); + } + BLI_assert(BM_elem_flag_test(v, BM_ELEM_TAG)); + BM_elem_flag_disable(v, BM_ELEM_TAG); + + ok = true; + verts_len--; + } + + int totedge = bm->totedge; + if (totedge == 0 || verts_len == 0) { + split_edges = false; + } + + if (split_edges) { + /* Count and tag edges. */ + BMEdge *e; + int edges_len = 0; + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN) && !BM_elem_flag_test(e->v1, BM_ELEM_TAG) && + !BM_elem_flag_test(e->v2, BM_ELEM_TAG)) { + BM_elem_flag_enable(e, BM_ELEM_TAG); + edges_len++; + } + else { + BM_elem_flag_disable(e, BM_ELEM_TAG); + } + } + + if (edges_len) { + /* Use `e->head.index` to count intersections. */ + bm->elem_index_dirty &= ~BM_EDGE; + + /* Create a BVHTree of edges with `dist` as epsilon. */ + BVHTree *tree_edges = BLI_bvhtree_new(edges_len, dist, 2, 6); + int i; + BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) { + if (BM_elem_flag_test(e, BM_ELEM_TAG)) { + float co[2][3]; + copy_v3_v3(co[0], e->v1->co); + copy_v3_v3(co[1], e->v2->co); + + BLI_bvhtree_insert(tree_edges, i, co[0], 2); + + e->head.index = 0; + } + } + BLI_bvhtree_balance(tree_edges); + + struct EDBMSplitEdge *cuts_iter, *cuts; + + /* Store all intersections in this array. */ + cuts = MEM_mallocN(verts_len * sizeof(*cuts), __func__); + cuts_iter = &cuts[0]; + + int cuts_len = 0; + int cut_edges_len = 0; + float dist_sq = SQUARE(dist); + struct EDBMSplitEdgeData data = {bm}; + + /* Start the search for intersections. */ + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(v, BM_ELEM_TAG)) { + float co[3]; + copy_v3_v3(co, v->co); + int e_index = BLI_bvhtree_find_nearest_first( + tree_edges, co, dist_sq, ebbm_automerge_and_split_find_duplicate_cb, &data); + + if (e_index != -1) { + e = data.r_edge; + e->head.index++; + + cuts_iter->v = v; + cuts_iter->e = e; + cuts_iter->lambda = data.r_lambda; + cuts_iter++; + cuts_len++; + + if (BM_elem_flag_test(e, BM_ELEM_TAG)) { + BM_elem_flag_disable(e, BM_ELEM_TAG); + cut_edges_len++; + } + } + } + } + BLI_bvhtree_free(tree_edges); + + if (cuts_len) { + /* Map intersections per edge. */ + union { + struct { + int cuts_len; + int cuts_index[]; + }; + int as_int[0]; + } * e_map_iter, *e_map; + + e_map = MEM_mallocN((cut_edges_len * sizeof(*e_map)) + + (cuts_len * sizeof(*(e_map->cuts_index))), + __func__); + + int map_len = 0; + cuts_iter = &cuts[0]; + for (i = 0; i < cuts_len; i++, cuts_iter++) { + e = cuts_iter->e; + if (!BM_elem_flag_test(e, BM_ELEM_TAG)) { + BM_elem_flag_enable(e, BM_ELEM_TAG); + int e_cuts_len = e->head.index; + + e_map_iter = (void *)&e_map->as_int[map_len]; + e_map_iter->cuts_len = e_cuts_len; + e_map_iter->cuts_index[0] = i; + + /* Use `e->head.index` to indicate which slot to fill with the `cuts` index. */ + e->head.index = map_len + 1; + map_len += 1 + e_cuts_len; + } + else { + e_map->as_int[++e->head.index] = i; + } + } + + /* Split Edges and Faces. */ + for (i = 0; i < map_len; + e_map_iter = (void *)&e_map->as_int[i], i += 1 + e_map_iter->cuts_len) { + + /* sort by lambda. */ + BLI_qsort_r(e_map_iter->cuts_index, + e_map_iter->cuts_len, + sizeof(*(e_map->cuts_index)), + edbm_automerge_and_split_sort_cmp_by_keys_cb, + cuts); + + float lambda, lambda_prev = 0.0f; + for (int j = 0; j < e_map_iter->cuts_len; j++) { + cuts_iter = &cuts[e_map_iter->cuts_index[j]]; + lambda = (cuts_iter->lambda - lambda_prev) / (1.0f - lambda_prev); + lambda_prev = cuts_iter->lambda; + v = cuts_iter->v; + e = cuts_iter->e; + + BMVert *v_new = BM_edge_split(bm, e, e->v1, NULL, lambda); + + BMO_slot_map_elem_insert(&weldop, slot_targetmap, v_new, v); + } + } + + ok = true; + MEM_freeN(e_map); + } + + MEM_freeN(cuts); + } + } + + BMO_op_exec(bm, &weldop); + + BMEdge **edgenet = NULL; + int edgenet_alloc_len = 0; + if (split_faces) { + GHASH_ITER (gh_iter, ghash_targetmap) { + v = BLI_ghashIterator_getValue(&gh_iter); + BLI_assert(BM_elem_flag_test(v, hflag) || hflag == BM_ELEM_TAG); + edbm_automerge_weld_linked_wire_edges_into_linked_faces(bm, v, &edgenet, &edgenet_alloc_len); + } + } + + if (edgenet) { + MEM_freeN(edgenet); + } + + BMO_op_finish(bm, &findop); + BMO_op_finish(bm, &weldop); + + if (LIKELY(ok) && update) { + EDBM_update_generic(em, true, true); + } +} + +/** \} */ diff --git a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c index 74700e59e99..7155348fed5 100644 --- a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c +++ b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c @@ -1008,8 +1008,17 @@ static void gizmo_mesh_spin_redo_setup(const bContext *C, wmGizmoGroup *gzgroup) }); } - /* Become modal as soon as it's started. */ - gizmo_mesh_spin_redo_modal_from_setup(C, gzgroup); + wmWindow *win = CTX_wm_window(C); + if (win && win->active) { + bScreen *screen = WM_window_get_active_screen(win); + if (screen->active_region) { + ARegion *ar = CTX_wm_region(C); + if (screen->active_region == ar) { + /* Become modal as soon as it's started. */ + gizmo_mesh_spin_redo_modal_from_setup(C, gzgroup); + } + } + } } static void gizmo_mesh_spin_redo_draw_prepare(const bContext *UNUSED(C), wmGizmoGroup *gzgroup) diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index bb584094580..61f9dc43c0f 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -2658,7 +2658,7 @@ static void knifetool_init_bmbvh(KnifeTool_OpData *kcd) Object *obedit_eval = (Object *)DEG_get_evaluated_id(kcd->vc.depsgraph, &kcd->em->ob->id); BMEditMesh *em_eval = BKE_editmesh_from_object(obedit_eval); - kcd->cagecos = (const float(*)[3])BKE_editmesh_vertexCos_get( + kcd->cagecos = (const float(*)[3])BKE_editmesh_vert_coords_alloc( kcd->vc.depsgraph, em_eval, scene_eval, NULL); kcd->bmbvh = BKE_bmbvh_new_from_editmesh( @@ -2949,7 +2949,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event) case KNF_MODAL_ADD_CUT_CLOSED: if (kcd->mode == MODE_DRAGGING) { - /* shouldn't be possible with default key-layout, just incase... */ + /* Shouldn't be possible with default key-layout, just in case. */ if (kcd->is_drag_hold) { kcd->is_drag_hold = false; knifetool_update_mval(kcd, kcd->curr.mval); diff --git a/source/blender/editors/mesh/editmesh_polybuild.c b/source/blender/editors/mesh/editmesh_polybuild.c index 088d1672cc9..21c850160dd 100644 --- a/source/blender/editors/mesh/editmesh_polybuild.c +++ b/source/blender/editors/mesh/editmesh_polybuild.c @@ -122,15 +122,160 @@ static bool edbm_preselect_or_active_init_viewcontext(bContext *C, return ok; } +static int edbm_polybuild_transform_at_cursor_invoke(bContext *C, + wmOperator *UNUSED(op), + const wmEvent *UNUSED(event)) +{ + ViewContext vc; + Base *basact = NULL; + BMElem *ele_act = NULL; + edbm_preselect_or_active_init_viewcontext(C, &vc, &basact, &ele_act); + BMEditMesh *em = vc.em; + BMesh *bm = em->bm; + + invert_m4_m4(vc.obedit->imat, vc.obedit->obmat); + ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d); + + if (!ele_act) { + return OPERATOR_CANCELLED; + } + + edbm_selectmode_ensure(vc.scene, vc.em, SCE_SELECT_VERTEX); + + edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT); + + if (ele_act->head.htype == BM_VERT) { + BM_vert_select_set(bm, (BMVert *)ele_act, true); + } + if (ele_act->head.htype == BM_EDGE) { + BM_edge_select_set(bm, (BMEdge *)ele_act, true); + } + if (ele_act->head.htype == BM_FACE) { + BM_face_select_set(bm, (BMFace *)ele_act, true); + } + + EDBM_mesh_normals_update(em); + EDBM_update_generic(em, true, true); + if (basact != NULL) { + if (vc.view_layer->basact != basact) { + ED_object_base_activate(C, basact); + } + } + BM_select_history_store(bm, ele_act); + WM_event_add_mousemove(C); + return OPERATOR_FINISHED; +} + +void MESH_OT_polybuild_transform_at_cursor(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Poly Build Transform at Cursor"; + ot->idname = "MESH_OT_polybuild_transform_at_cursor"; + + /* api callbacks */ + ot->invoke = edbm_polybuild_transform_at_cursor_invoke; + ot->poll = EDBM_view3d_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* to give to transform */ + Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR_DUMMY); +} + +static int edbm_polybuild_delete_at_cursor_invoke(bContext *C, + wmOperator *op, + const wmEvent *UNUSED(event)) +{ + bool changed = false; + + ViewContext vc; + Base *basact = NULL; + BMElem *ele_act = NULL; + edbm_preselect_or_active_init_viewcontext(C, &vc, &basact, &ele_act); + BMEditMesh *em = vc.em; + BMesh *bm = em->bm; + + invert_m4_m4(vc.obedit->imat, vc.obedit->obmat); + ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d); + + if (!ele_act) { + return OPERATOR_CANCELLED; + } + + edbm_selectmode_ensure(vc.scene, vc.em, SCE_SELECT_VERTEX); + + if (ele_act->head.htype == BM_FACE) { + BMFace *f_act = (BMFace *)ele_act; + EDBM_flag_disable_all(em, BM_ELEM_TAG); + BM_elem_flag_enable(f_act, BM_ELEM_TAG); + if (!EDBM_op_callf(em, op, "delete geom=%hf context=%i", BM_ELEM_TAG, DEL_FACES)) { + return OPERATOR_CANCELLED; + } + changed = true; + } + if (ele_act->head.htype == BM_VERT) { + BMVert *v_act = (BMVert *)ele_act; + if (BM_vert_is_edge_pair(v_act)) { + BM_edge_collapse(bm, v_act->e, v_act, true, true); + changed = true; + } + else { + EDBM_flag_disable_all(em, BM_ELEM_TAG); + BM_elem_flag_enable(v_act, BM_ELEM_TAG); + + if (!EDBM_op_callf(em, + op, + "dissolve_verts verts=%hv use_face_split=%b use_boundary_tear=%b", + BM_ELEM_TAG, + false, + false)) { + return OPERATOR_CANCELLED; + } + changed = true; + } + } + + if (changed) { + EDBM_mesh_normals_update(em); + EDBM_update_generic(em, true, true); + if (basact != NULL) { + if (vc.view_layer->basact != basact) { + ED_object_base_activate(C, basact); + } + } + WM_event_add_mousemove(C); + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } +} + +void MESH_OT_polybuild_delete_at_cursor(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Poly Build Delete at Cursor"; + ot->idname = "MESH_OT_polybuild_delete_at_cursor"; + + /* api callbacks */ + ot->invoke = edbm_polybuild_delete_at_cursor_invoke; + ot->poll = EDBM_view3d_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* to give to transform */ + Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR_DUMMY); +} + /** \} */ /* -------------------------------------------------------------------- */ /** \name Face at Cursor * \{ */ -static int edbm_polybuild_face_at_cursor_invoke(bContext *C, - wmOperator *UNUSED(op), - const wmEvent *event) +static int edbm_polybuild_face_at_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *event) { float center[3]; bool changed = false; @@ -168,20 +313,27 @@ static int edbm_polybuild_face_at_cursor_invoke(bContext *C, mul_m4_v3(vc.obedit->obmat, center); ED_view3d_win_to_3d_int(vc.v3d, vc.ar, center, event->mval, center); mul_m4_v3(vc.obedit->imat, center); - - BMVert *v_tri[3]; - v_tri[0] = e_act->v1; - v_tri[1] = e_act->v2; - v_tri[2] = BM_vert_create(bm, center, NULL, BM_CREATE_NOP); - if (e_act->l && e_act->l->v == v_tri[0]) { - SWAP(BMVert *, v_tri[0], v_tri[1]); + if (f_reference->len == 3 && RNA_boolean_get(op->ptr, "create_quads")) { + const float fac = line_point_factor_v3(center, e_act->v1->co, e_act->v2->co); + BMVert *v_new = BM_edge_split(bm, e_act, e_act->v1, NULL, CLAMPIS(fac, 0.0f, 1.0f)); + copy_v3_v3(v_new->co, center); + edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT); + BM_vert_select_set(bm, v_new, true); + BM_select_history_store(bm, v_new); + } + else { + BMVert *v_tri[3]; + v_tri[0] = e_act->v1; + v_tri[1] = e_act->v2; + v_tri[2] = BM_vert_create(bm, center, NULL, BM_CREATE_NOP); + if (e_act->l && e_act->l->v == v_tri[0]) { + SWAP(BMVert *, v_tri[0], v_tri[1]); + } + BM_face_create_verts(bm, v_tri, 3, f_reference, BM_CREATE_NOP, true); + edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT); + BM_vert_select_set(bm, v_tri[2], true); + BM_select_history_store(bm, v_tri[2]); } - // BMFace *f_new = - BM_face_create_verts(bm, v_tri, 3, f_reference, BM_CREATE_NOP, true); - - edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT); - BM_vert_select_set(bm, v_tri[2], true); - BM_select_history_store(bm, v_tri[2]); changed = true; } else if (ele_act->head.htype == BM_VERT) { @@ -281,6 +433,11 @@ void MESH_OT_polybuild_face_at_cursor(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + RNA_def_boolean(ot->srna, + "create_quads", + true, + "Create quads", + "Automatically split edges in triangles to maintain quad topology"); /* to give to transform */ Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR_DUMMY); } diff --git a/source/blender/editors/mesh/editmesh_preselect_elem.c b/source/blender/editors/mesh/editmesh_preselect_elem.c index a3e684a5493..05c4da68355 100644 --- a/source/blender/editors/mesh/editmesh_preselect_elem.c +++ b/source/blender/editors/mesh/editmesh_preselect_elem.c @@ -75,20 +75,49 @@ struct EditMesh_PreSelElem { float (*verts)[3]; int verts_len; + + float (*preview_tris)[3][3]; + int preview_tris_len; + float (*preview_lines)[2][3]; + int preview_lines_len; + + eEditMesh_PreSelPreviewAction preview_action; }; +void EDBM_preselect_action_set(struct EditMesh_PreSelElem *psel, + eEditMesh_PreSelPreviewAction action) +{ + psel->preview_action = action; +} + +eEditMesh_PreSelPreviewAction EDBM_preselect_action_get(struct EditMesh_PreSelElem *psel) +{ + return psel->preview_action; +} + struct EditMesh_PreSelElem *EDBM_preselect_elem_create(void) { struct EditMesh_PreSelElem *psel = MEM_callocN(sizeof(*psel), __func__); + psel->preview_action = PRESELECT_ACTION_TRANSFORM; return psel; } void EDBM_preselect_elem_destroy(struct EditMesh_PreSelElem *psel) { EDBM_preselect_elem_clear(psel); + EDBM_preselect_preview_clear(psel); MEM_freeN(psel); } +void EDBM_preselect_preview_clear(struct EditMesh_PreSelElem *psel) +{ + MEM_SAFE_FREE(psel->preview_tris); + psel->preview_tris_len = 0; + + MEM_SAFE_FREE(psel->preview_lines); + psel->preview_lines_len = 0; +} + void EDBM_preselect_elem_clear(struct EditMesh_PreSelElem *psel) { MEM_SAFE_FREE(psel->edges); @@ -112,9 +141,42 @@ void EDBM_preselect_elem_draw(struct EditMesh_PreSelElem *psel, const float matr uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - immUniformColor3ub(255, 0, 255); + + immUniformColor4ub(141, 171, 186, 100); + if (psel->preview_action != PRESELECT_ACTION_TRANSFORM) { + if (psel->preview_tris_len > 0) { + immBegin(GPU_PRIM_TRIS, psel->preview_tris_len * 3); + + for (int i = 0; i < psel->preview_tris_len; i++) { + immVertex3fv(pos, psel->preview_tris[i][0]); + immVertex3fv(pos, psel->preview_tris[i][1]); + immVertex3fv(pos, psel->preview_tris[i][2]); + } + immEnd(); + } + + if (psel->preview_lines_len > 0) { + + immUniformColor4ub(3, 161, 252, 200); + GPU_line_width(2.0f); + immBegin(GPU_PRIM_LINES, psel->preview_lines_len * 2); + for (int i = 0; i < psel->preview_lines_len; i++) { + immVertex3fv(pos, psel->preview_lines[i][0]); + immVertex3fv(pos, psel->preview_lines[i][1]); + } + immEnd(); + } + } + + if (psel->preview_action == PRESELECT_ACTION_DELETE) { + immUniformColor4ub(252, 49, 10, 200); + } + else { + immUniformColor4ub(3, 161, 252, 200); + } if (psel->edges_len > 0) { + GPU_line_width(3.0f); immBegin(GPU_PRIM_LINES, psel->edges_len * 2); for (int i = 0; i < psel->edges_len; i++) { @@ -126,7 +188,7 @@ void EDBM_preselect_elem_draw(struct EditMesh_PreSelElem *psel, const float matr } if (psel->verts_len > 0) { - GPU_point_size(3.0f); + GPU_point_size(4.0f); immBegin(GPU_PRIM_POINTS, psel->verts_len); @@ -167,6 +229,122 @@ static void view3d_preselect_mesh_elem_update_from_edge(struct EditMesh_PreSelEl psel->edges_len = 1; } +static void view3d_preselect_update_preview_triangle_from_vert(struct EditMesh_PreSelElem *psel, + ViewContext *vc, + BMesh *UNUSED(bm), + BMVert *eed, + const int mval[2]) +{ + BMVert *v_act = eed; + BMEdge *e_pair[2] = {NULL}; + float center[3]; + + if (v_act->e != NULL) { + for (uint allow_wire = 0; allow_wire < 2 && (e_pair[1] == NULL); allow_wire++) { + int i = 0; + BMEdge *e_iter = v_act->e; + do { + if ((BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN) == false) && + (allow_wire ? BM_edge_is_wire(e_iter) : BM_edge_is_boundary(e_iter))) { + if (i == 2) { + e_pair[0] = e_pair[1] = NULL; + break; + } + e_pair[i++] = e_iter; + } + } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v_act)) != v_act->e); + } + } + + if (e_pair[1] != NULL) { + mul_v3_m4v3(center, vc->obedit->obmat, v_act->co); + ED_view3d_win_to_3d_int(vc->v3d, vc->ar, center, mval, center); + mul_m4_v3(vc->obedit->imat, center); + + psel->preview_tris = MEM_mallocN(sizeof(*psel->preview_tris) * 2, __func__); + psel->preview_lines = MEM_mallocN(sizeof(*psel->preview_lines) * 4, __func__); + + copy_v3_v3(psel->preview_tris[0][0], e_pair[0]->v1->co); + copy_v3_v3(psel->preview_tris[0][1], e_pair[0]->v2->co); + copy_v3_v3(psel->preview_tris[0][2], center); + + copy_v3_v3(psel->preview_tris[1][0], e_pair[1]->v1->co); + copy_v3_v3(psel->preview_tris[1][1], e_pair[1]->v2->co); + copy_v3_v3(psel->preview_tris[1][2], center); + + copy_v3_v3(psel->preview_lines[0][0], e_pair[0]->v1->co); + copy_v3_v3(psel->preview_lines[0][1], e_pair[0]->v2->co); + + copy_v3_v3(psel->preview_lines[1][0], e_pair[1]->v1->co); + copy_v3_v3(psel->preview_lines[1][1], e_pair[1]->v2->co); + + copy_v3_v3(psel->preview_lines[2][0], center); + if (e_pair[0]->v1 == v_act) { + copy_v3_v3(psel->preview_lines[2][1], e_pair[0]->v2->co); + } + else { + copy_v3_v3(psel->preview_lines[2][1], e_pair[0]->v1->co); + } + + copy_v3_v3(psel->preview_lines[3][0], center); + if (e_pair[1]->v1 == v_act) { + copy_v3_v3(psel->preview_lines[3][1], e_pair[1]->v2->co); + } + else { + copy_v3_v3(psel->preview_lines[3][1], e_pair[1]->v1->co); + } + psel->preview_tris_len = 2; + psel->preview_lines_len = 4; + } +} + +static void view3d_preselect_update_preview_triangle_from_face(struct EditMesh_PreSelElem *psel, + ViewContext *UNUSED(vc), + BMesh *UNUSED(bm), + BMFace *efa, + const int UNUSED(mval[2])) +{ + float(*preview_lines)[2][3] = MEM_mallocN(sizeof(*psel->edges) * efa->len, __func__); + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(efa); + int i = 0; + do { + vcos_get_pair(&l_iter->e->v1, preview_lines[i++], NULL); + } while ((l_iter = l_iter->next) != l_first); + psel->preview_lines = preview_lines; + psel->preview_lines_len = efa->len; +} + +static void view3d_preselect_update_preview_triangle_from_edge(struct EditMesh_PreSelElem *psel, + ViewContext *vc, + BMesh *UNUSED(bm), + BMEdge *eed, + const int mval[2]) +{ + float center[3]; + psel->preview_tris = MEM_mallocN(sizeof(*psel->preview_tris), __func__); + psel->preview_lines = MEM_mallocN(sizeof(*psel->preview_lines) * 3, __func__); + mid_v3_v3v3(center, eed->v1->co, eed->v2->co); + mul_m4_v3(vc->obedit->obmat, center); + ED_view3d_win_to_3d_int(vc->v3d, vc->ar, center, mval, center); + mul_m4_v3(vc->obedit->imat, center); + + copy_v3_v3(psel->preview_tris[0][0], eed->v1->co); + copy_v3_v3(psel->preview_tris[0][1], eed->v2->co); + copy_v3_v3(psel->preview_tris[0][2], center); + + copy_v3_v3(psel->preview_lines[0][0], eed->v1->co); + copy_v3_v3(psel->preview_lines[0][1], eed->v2->co); + + copy_v3_v3(psel->preview_lines[1][0], eed->v2->co); + copy_v3_v3(psel->preview_lines[1][1], center); + + copy_v3_v3(psel->preview_lines[2][0], center); + copy_v3_v3(psel->preview_lines[2][1], eed->v1->co); + psel->preview_tris_len = 1; + psel->preview_lines_len = 3; +} + static void view3d_preselect_mesh_elem_update_from_face(struct EditMesh_PreSelElem *psel, BMesh *UNUSED(bm), BMFace *efa, @@ -209,4 +387,28 @@ void EDBM_preselect_elem_update_from_single(struct EditMesh_PreSelElem *psel, } } +void EDBM_preselect_elem_update_preview(struct EditMesh_PreSelElem *psel, + struct ViewContext *vc, + struct BMesh *bm, + struct BMElem *ele, + const int mval[2]) +{ + EDBM_preselect_preview_clear(psel); + + switch (ele->head.htype) { + case BM_VERT: + if (EDBM_preselect_action_get(psel) == PRESELECT_ACTION_CREATE) { + view3d_preselect_update_preview_triangle_from_vert(psel, vc, bm, (BMVert *)ele, mval); + } + break; + case BM_EDGE: + view3d_preselect_update_preview_triangle_from_edge(psel, vc, bm, (BMEdge *)ele, mval); + break; + case BM_FACE: + view3d_preselect_update_preview_triangle_from_face(psel, vc, bm, (BMFace *)ele, mval); + break; + default: + BLI_assert(0); + } +} /** \} */ diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 94ffd9a34d6..c0bd9e9f14c 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -24,7 +24,6 @@ #include "MEM_guardedalloc.h" #include "BLI_bitmap.h" -#include "BLI_bitmap_draw_2d.h" #include "BLI_listbase.h" #include "BLI_linklist.h" #include "BLI_linklist_stack.h" @@ -35,13 +34,9 @@ #include "BKE_context.h" #include "BKE_report.h" -#include "BKE_paint.h" #include "BKE_editmesh.h" #include "BKE_layer.h" -#include "IMB_imbuf_types.h" -#include "IMB_imbuf.h" - #include "WM_api.h" #include "WM_types.h" @@ -67,7 +62,6 @@ #include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" -#include "DRW_engine.h" #include "DRW_select_buffer.h" #include "mesh_intern.h" /* own include */ @@ -172,30 +166,6 @@ void EDBM_select_mirrored( /** \} */ /* -------------------------------------------------------------------- */ -/** \name Select Auto-Merge - * - * Used after transform operations. - * \{ */ - -void EDBM_automerge(Scene *scene, Object *obedit, bool update, const char hflag) -{ - bool ok; - BMEditMesh *em = BKE_editmesh_from_object(obedit); - - ok = BMO_op_callf(em->bm, - BMO_FLAG_DEFAULTS, - "automerge verts=%hv dist=%f", - hflag, - scene->toolsettings->doublimit); - - if (LIKELY(ok) && update) { - EDBM_update_generic(em, true, true); - } -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Back-Buffer OpenGL Selection * \{ */ @@ -1031,8 +1001,11 @@ bool EDBM_unified_findnearest(ViewContext *vc, bool EDBM_unified_findnearest_from_raycast(ViewContext *vc, Base **bases, const uint bases_len, - bool use_boundary, - int *r_base_index, + bool use_boundary_vertices, + bool use_boundary_edges, + int *r_base_index_vert, + int *r_base_index_edge, + int *r_base_index_face, struct BMVert **r_eve, struct BMEdge **r_eed, struct BMFace **r_efa) @@ -1045,10 +1018,30 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc, uint base_index; BMElem *ele; } best = {0, NULL}; + /* Currently unused, keep since we may want to pick the best. */ + UNUSED_VARS(best); + + struct { + uint base_index; + BMElem *ele; + } best_vert = {0, NULL}; + + struct { + uint base_index; + BMElem *ele; + } best_edge = {0, NULL}; + + struct { + uint base_index; + BMElem *ele; + } best_face = {0, NULL}; if (ED_view3d_win_to_ray_clipped( vc->depsgraph, vc->ar, vc->v3d, mval_fl, ray_origin, ray_direction, true)) { float dist_sq_best = FLT_MAX; + float dist_sq_best_vert = FLT_MAX; + float dist_sq_best_edge = FLT_MAX; + float dist_sq_best_face = FLT_MAX; const bool use_vert = (r_eve != NULL); const bool use_edge = (r_eed != NULL); @@ -1078,18 +1071,23 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc, BM_mesh_elem_index_ensure(bm, BM_VERT); } - if (use_boundary && (use_vert || use_edge)) { + if ((use_boundary_vertices || use_boundary_edges) && (use_vert || use_edge)) { BMEdge *e; BMIter eiter; BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { if ((BM_elem_flag_test(e, BM_ELEM_HIDDEN) == false) && (BM_edge_is_boundary(e))) { - if (use_vert) { + if (use_vert && use_boundary_vertices) { for (uint j = 0; j < 2; j++) { BMVert *v = *((&e->v1) + j); float point[3]; mul_v3_m4v3(point, obedit->obmat, coords ? coords[BM_elem_index_get(v)] : v->co); const float dist_sq_test = dist_squared_to_ray_v3_normalized( ray_origin, ray_direction, point); + if (dist_sq_test < dist_sq_best_vert) { + dist_sq_best_vert = dist_sq_test; + best_vert.base_index = base_index; + best_vert.ele = (BMElem *)v; + } if (dist_sq_test < dist_sq_best) { dist_sq_best = dist_sq_test; best.base_index = base_index; @@ -1098,7 +1096,7 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc, } } - if (use_edge) { + if (use_edge && use_boundary_edges) { float point[3]; #if 0 const float dist_sq_test = dist_squared_ray_to_seg_v3( @@ -1114,6 +1112,11 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc, mul_m4_v3(obedit->obmat, point); const float dist_sq_test = dist_squared_to_ray_v3_normalized( ray_origin, ray_direction, point); + if (dist_sq_test < dist_sq_best_edge) { + dist_sq_best_edge = dist_sq_test; + best_edge.base_index = base_index; + best_edge.ele = (BMElem *)e; + } if (dist_sq_test < dist_sq_best) { dist_sq_best = dist_sq_test; best.base_index = base_index; @@ -1124,46 +1127,55 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc, } } } - else { - /* Non boundary case. */ - if (use_vert) { - BMVert *v; - BMIter viter; - BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { - if (BM_elem_flag_test(v, BM_ELEM_HIDDEN) == false) { - float point[3]; - mul_v3_m4v3(point, obedit->obmat, v->co); - const float dist_sq_test = dist_squared_to_ray_v3_normalized( - ray_origin, ray_direction, v->co); - if (dist_sq_test < dist_sq_best) { - dist_sq_best = dist_sq_test; - best.base_index = base_index; - best.ele = (BMElem *)v; - } + /* Non boundary case. */ + if (use_vert && !use_boundary_vertices) { + BMVert *v; + BMIter viter; + BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(v, BM_ELEM_HIDDEN) == false) { + float point[3]; + mul_v3_m4v3(point, obedit->obmat, coords ? coords[BM_elem_index_get(v)] : v->co); + const float dist_sq_test = dist_squared_to_ray_v3_normalized( + ray_origin, ray_direction, point); + if (dist_sq_test < dist_sq_best_vert) { + dist_sq_best_vert = dist_sq_test; + best_vert.base_index = base_index; + best_vert.ele = (BMElem *)v; + } + if (dist_sq_test < dist_sq_best) { + dist_sq_best = dist_sq_test; + best.base_index = base_index; + best.ele = (BMElem *)v; } } } - if (use_edge) { - BMEdge *e; - BMIter eiter; - BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == false) { - float point[3]; - if (coords) { - mid_v3_v3v3( - point, coords[BM_elem_index_get(e->v1)], coords[BM_elem_index_get(e->v2)]); - } - else { - mid_v3_v3v3(point, e->v1->co, e->v2->co); - } - mul_m4_v3(obedit->obmat, point); - const float dist_sq_test = dist_squared_to_ray_v3_normalized( - ray_origin, ray_direction, point); - if (dist_sq_test < dist_sq_best) { - dist_sq_best = dist_sq_test; - best.base_index = base_index; - best.ele = (BMElem *)e; - } + } + + if (use_edge && !use_boundary_edges) { + BMEdge *e; + BMIter eiter; + BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == false) { + float point[3]; + if (coords) { + mid_v3_v3v3( + point, coords[BM_elem_index_get(e->v1)], coords[BM_elem_index_get(e->v2)]); + } + else { + mid_v3_v3v3(point, e->v1->co, e->v2->co); + } + mul_m4_v3(obedit->obmat, point); + const float dist_sq_test = dist_squared_to_ray_v3_normalized( + ray_origin, ray_direction, point); + if (dist_sq_test < dist_sq_best_edge) { + dist_sq_best_edge = dist_sq_test; + best_edge.base_index = base_index; + best_edge.ele = (BMElem *)e; + } + if (dist_sq_test < dist_sq_best) { + dist_sq_best = dist_sq_test; + best.base_index = base_index; + best.ele = (BMElem *)e; } } } @@ -1184,6 +1196,11 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc, mul_m4_v3(obedit->obmat, point); const float dist_sq_test = dist_squared_to_ray_v3_normalized( ray_origin, ray_direction, point); + if (dist_sq_test < dist_sq_best_face) { + dist_sq_best_face = dist_sq_test; + best_face.base_index = base_index; + best_face.ele = (BMElem *)f; + } if (dist_sq_test < dist_sq_best) { dist_sq_best = dist_sq_test; best.base_index = base_index; @@ -1195,7 +1212,10 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc, } } - *r_base_index = best.base_index; + *r_base_index_vert = best_vert.base_index; + *r_base_index_edge = best_edge.base_index; + *r_base_index_face = best_face.base_index; + if (r_eve) { *r_eve = NULL; } @@ -1206,22 +1226,17 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc, *r_efa = NULL; } - if (best.ele) { - switch (best.ele->head.htype) { - case BM_VERT: - *r_eve = (BMVert *)best.ele; - break; - case BM_EDGE: - *r_eed = (BMEdge *)best.ele; - break; - case BM_FACE: - *r_efa = (BMFace *)best.ele; - break; - default: - BLI_assert(0); - } + if (best_vert.ele) { + *r_eve = (BMVert *)best_vert.ele; + } + if (best_edge.ele) { + *r_eed = (BMEdge *)best_edge.ele; } - return (best.ele != NULL); + if (best_face.ele) { + *r_efa = (BMFace *)best_face.ele; + } + + return (best_vert.ele != NULL || best_edge.ele != NULL || best_face.ele != NULL); } /** \} */ diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 65c058556f5..0c4db012786 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -437,6 +437,7 @@ void EDBM_project_snap_verts(bContext *C, Depsgraph *depsgraph, ARegion *ar, BME }, mval, NULL, + NULL, co_proj, NULL)) { mul_v3_m4v3(eve->co, obedit->imat, co_proj); @@ -3130,12 +3131,7 @@ static int edbm_remove_doubles_exec(bContext *C, wmOperator *op) BM_mesh_elem_hflag_enable_test(em->bm, htype_select, BM_ELEM_TAG, true, true, BM_ELEM_SELECT); if (use_unselected) { - EDBM_op_init(em, &bmop, op, "automerge verts=%hv dist=%f", BM_ELEM_SELECT, threshold); - BMO_op_exec(em->bm, &bmop); - - if (!EDBM_op_finish(em, &bmop, op, true)) { - continue; - } + EDBM_automerge(obedit, false, BM_ELEM_SELECT, threshold); } else { EDBM_op_init(em, &bmop, op, "find_doubles verts=%hv dist=%f", BM_ELEM_SELECT, threshold); @@ -4040,7 +4036,7 @@ static void mesh_separate_material_assign_mat_nr(Main *bmain, Object *ob, const ma_obdata = NULL; } - BKE_material_clear_id(bmain, obdata, true); + BKE_material_clear_id(bmain, obdata); BKE_material_resize_object(bmain, ob, 1, true); BKE_material_resize_id(bmain, obdata, 1, true); @@ -4051,7 +4047,7 @@ static void mesh_separate_material_assign_mat_nr(Main *bmain, Object *ob, const id_us_plus((ID *)ma_obdata); } else { - BKE_material_clear_id(bmain, obdata, true); + BKE_material_clear_id(bmain, obdata); BKE_material_resize_object(bmain, ob, 0, true); BKE_material_resize_id(bmain, obdata, 0, true); } @@ -5710,7 +5706,7 @@ void MESH_OT_dissolve_limited(wmOperatorType *ot) "use_dissolve_boundaries", false, "All Boundaries", - "Dissolve all vertices inbetween face boundaries"); + "Dissolve all vertices in between face boundaries"); RNA_def_enum_flag(ot->srna, "delimit", rna_enum_mesh_delimit_mode_items, diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index d7ed14184fa..522c2f32d27 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -85,7 +85,7 @@ void EDBM_redo_state_restore(BMBackup backup, BMEditMesh *em, int recalctess) tmpbm = NULL; if (recalctess) { - BKE_editmesh_tessface_calc(em); + BKE_editmesh_looptri_calc(em); } } @@ -105,7 +105,7 @@ void EDBM_redo_state_free(BMBackup *backup, BMEditMesh *em, int recalctess) backup->bmcopy = NULL; if (recalctess && em) { - BKE_editmesh_tessface_calc(em); + BKE_editmesh_looptri_calc(em); } } @@ -162,7 +162,7 @@ bool EDBM_op_finish(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const bool /* when copying, tessellation isn't to for faster copying, * but means we need to re-tessellate here */ if (em->looptris == NULL) { - BKE_editmesh_tessface_calc(em); + BKE_editmesh_looptri_calc(em); } if (em->ob) { @@ -292,10 +292,6 @@ void EDBM_mesh_make(Object *ob, const int select_mode, const bool add_key_index) Mesh *me = ob->data; BMesh *bm; - if (UNLIKELY(!me->mpoly && me->totface)) { - BKE_mesh_convert_mfaces_to_mpolys(me); - } - bm = BKE_mesh_to_bmesh(me, ob, add_key_index, @@ -347,10 +343,6 @@ void EDBM_mesh_load(Main *bmain, Object *ob) .calc_object_remap = true, })); -#ifdef USE_TESSFACE_DEFAULT - BKE_mesh_tessface_calc(me); -#endif - /* Free derived mesh. usually this would happen through depsgraph but there * are exceptions like file save that will not cause this, and we want to * avoid ending up with an invalid derived mesh then. @@ -1397,15 +1389,15 @@ void EDBM_stats_update(BMEditMesh *em) /* so many tools call these that we better make it a generic function. */ -void EDBM_update_generic(BMEditMesh *em, const bool do_tessface, const bool is_destructive) +void EDBM_update_generic(BMEditMesh *em, const bool do_tessellation, const bool is_destructive) { Object *ob = em->ob; /* order of calling isn't important */ DEG_id_tag_update(ob->data, ID_RECALC_GEOMETRY); WM_main_add_notifier(NC_GEOM | ND_DATA, ob->data); - if (do_tessface) { - BKE_editmesh_tessface_calc(em); + if (do_tessellation) { + BKE_editmesh_looptri_calc(em); } if (is_destructive) { diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c index ee8de9d8ea9..569994bead1 100644 --- a/source/blender/editors/mesh/mesh_data.c +++ b/source/blender/editors/mesh/mesh_data.c @@ -289,18 +289,14 @@ int ED_mesh_uv_texture_add(Mesh *me, const char *name, const bool active_set, co if (me->mloopuv && do_init) { CustomData_add_layer_named( &me->ldata, CD_MLOOPUV, CD_DUPLICATE, me->mloopuv, me->totloop, name); - CustomData_add_layer_named( - &me->fdata, CD_MTFACE, CD_DUPLICATE, me->mtface, me->totface, name); is_init = true; } else { CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, me->totloop, name); - CustomData_add_layer_named(&me->fdata, CD_MTFACE, CD_DEFAULT, NULL, me->totface, name); } if (active_set || layernum_dst == 0) { CustomData_set_layer_active(&me->ldata, CD_MLOOPUV, layernum_dst); - CustomData_set_layer_active(&me->fdata, CD_MTFACE, layernum_dst); } BKE_mesh_update_customdata_pointers(me, true); @@ -418,16 +414,13 @@ int ED_mesh_color_add(Mesh *me, const char *name, const bool active_set, const b if (me->mloopcol && do_init) { CustomData_add_layer_named( &me->ldata, CD_MLOOPCOL, CD_DUPLICATE, me->mloopcol, me->totloop, name); - CustomData_add_layer_named(&me->fdata, CD_MCOL, CD_DUPLICATE, me->mcol, me->totface, name); } else { CustomData_add_layer_named(&me->ldata, CD_MLOOPCOL, CD_DEFAULT, NULL, me->totloop, name); - CustomData_add_layer_named(&me->fdata, CD_MCOL, CD_DEFAULT, NULL, me->totface, name); } if (active_set || layernum == 0) { CustomData_set_layer_active(&me->ldata, CD_MLOOPCOL, layernum); - CustomData_set_layer_active(&me->fdata, CD_MCOL, layernum); } BKE_mesh_update_customdata_pointers(me, true); @@ -885,18 +878,8 @@ void MESH_OT_customdata_custom_splitnormals_clear(wmOperatorType *ot) /************************** Add Geometry Layers *************************/ -void ED_mesh_update( - Mesh *mesh, bContext *C, bool calc_edges, bool calc_edges_loose, bool calc_tessface) +void ED_mesh_update(Mesh *mesh, bContext *C, bool calc_edges, bool calc_edges_loose) { - bool tessface_input = false; - - if (mesh->totface > 0 && mesh->totpoly == 0) { - BKE_mesh_convert_mfaces_to_mpolys(mesh); - - /* would only be converting back again, don't bother */ - tessface_input = true; - } - if (calc_edges_loose && mesh->totedge) { BKE_mesh_calc_edges_loose(mesh); } @@ -905,15 +888,8 @@ void ED_mesh_update( BKE_mesh_calc_edges(mesh, calc_edges, true); } - if (calc_tessface) { - if (tessface_input == false) { - BKE_mesh_tessface_calc(mesh); - } - } - else { - /* default state is not to have tessface's so make sure this is the case */ - BKE_mesh_tessface_clear(mesh); - } + /* Default state is not to have tessface's so make sure this is the case. */ + BKE_mesh_tessface_clear(mesh); BKE_mesh_calc_normals(mesh); @@ -988,39 +964,6 @@ static void mesh_add_edges(Mesh *mesh, int len) mesh->totedge = totedge; } -static void mesh_add_tessfaces(Mesh *mesh, int len) -{ - CustomData fdata; - MFace *mface; - int i, totface; - - if (len == 0) { - return; - } - - totface = mesh->totface + len; /* new face count */ - - /* update customdata */ - CustomData_copy(&mesh->fdata, &fdata, CD_MASK_MESH.fmask, CD_DEFAULT, totface); - CustomData_copy_data(&mesh->fdata, &fdata, 0, 0, mesh->totface); - - if (!CustomData_has_layer(&fdata, CD_MFACE)) { - CustomData_add_layer(&fdata, CD_MFACE, CD_CALLOC, NULL, totface); - } - - CustomData_free(&mesh->fdata, mesh->totface); - mesh->fdata = fdata; - BKE_mesh_update_customdata_pointers(mesh, true); - - /* set default flags */ - mface = &mesh->mface[mesh->totface]; - for (i = 0; i < len; i++, mface++) { - mface->flag = ME_FACE_SEL; - } - - mesh->totface = totface; -} - static void mesh_add_loops(Mesh *mesh, int len) { CustomData ldata; @@ -1109,20 +1052,6 @@ static void mesh_remove_edges(Mesh *mesh, int len) mesh->totedge = totedge; } -static void mesh_remove_faces(Mesh *mesh, int len) -{ - int totface; - - if (len == 0) { - return; - } - - totface = mesh->totface - len; /* new face count */ - CustomData_free_elem(&mesh->fdata, totface, len); - - mesh->totface = totface; -} - #if 0 void ED_mesh_geometry_add(Mesh *mesh, ReportList *reports, int verts, int edges, int faces) { @@ -1143,21 +1072,6 @@ void ED_mesh_geometry_add(Mesh *mesh, ReportList *reports, int verts, int edges, } #endif -void ED_mesh_tessfaces_add(Mesh *mesh, ReportList *reports, int count) -{ - if (mesh->edit_mesh) { - BKE_report(reports, RPT_ERROR, "Cannot add tessfaces in edit mode"); - return; - } - - if (mesh->mpoly) { - BKE_report(reports, RPT_ERROR, "Cannot add tessfaces to a mesh that already has polygons"); - return; - } - - mesh_add_tessfaces(mesh, count); -} - void ED_mesh_edges_add(Mesh *mesh, ReportList *reports, int count) { if (mesh->edit_mesh) { @@ -1178,20 +1092,6 @@ void ED_mesh_vertices_add(Mesh *mesh, ReportList *reports, int count) mesh_add_verts(mesh, count); } -void ED_mesh_faces_remove(Mesh *mesh, ReportList *reports, int count) -{ - if (mesh->edit_mesh) { - BKE_report(reports, RPT_ERROR, "Cannot remove faces in edit mode"); - return; - } - else if (count > mesh->totface) { - BKE_report(reports, RPT_ERROR, "Cannot remove more faces than the mesh contains"); - return; - } - - mesh_remove_faces(mesh, count); -} - void ED_mesh_edges_remove(Mesh *mesh, ReportList *reports, int count) { if (mesh->edit_mesh) { @@ -1240,26 +1140,6 @@ void ED_mesh_polys_add(Mesh *mesh, ReportList *reports, int count) mesh_add_polys(mesh, count); } -void ED_mesh_calc_tessface(Mesh *mesh, bool free_mpoly) -{ - if (mesh->edit_mesh) { - BKE_editmesh_tessface_calc(mesh->edit_mesh); - } - else { - BKE_mesh_tessface_calc(mesh); - } - if (free_mpoly) { - CustomData_free(&mesh->ldata, mesh->totloop); - CustomData_free(&mesh->pdata, mesh->totpoly); - mesh->totloop = 0; - mesh->totpoly = 0; - mesh->mloop = NULL; - mesh->mloopcol = NULL; - mesh->mloopuv = NULL; - mesh->mpoly = NULL; - } -} - void ED_mesh_report_mirror_ex(wmOperator *op, int totmirr, int totfail, char selectmode) { const char *elem_type; diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index 8d585977105..3558a07c6fb 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -122,6 +122,8 @@ void MESH_GGT_spin_redo(struct wmGizmoGroupType *gzgt); void MESH_OT_polybuild_face_at_cursor(struct wmOperatorType *ot); void MESH_OT_polybuild_split_at_cursor(struct wmOperatorType *ot); void MESH_OT_polybuild_dissolve_at_cursor(struct wmOperatorType *ot); +void MESH_OT_polybuild_transform_at_cursor(struct wmOperatorType *ot); +void MESH_OT_polybuild_delete_at_cursor(struct wmOperatorType *ot); /* *** editmesh_inset.c *** */ void MESH_OT_inset(struct wmOperatorType *ot); diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index c3387dcfc09..9b6e991a9f5 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -145,6 +145,8 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_polybuild_face_at_cursor); WM_operatortype_append(MESH_OT_polybuild_split_at_cursor); WM_operatortype_append(MESH_OT_polybuild_dissolve_at_cursor); + WM_operatortype_append(MESH_OT_polybuild_transform_at_cursor); + WM_operatortype_append(MESH_OT_polybuild_delete_at_cursor); WM_operatortype_append(MESH_OT_uv_texture_add); WM_operatortype_append(MESH_OT_uv_texture_remove); @@ -331,6 +333,25 @@ void ED_operatormacros_mesh(void) otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); RNA_boolean_set(otmacro->ptr, "use_proportional_edit", false); RNA_boolean_set(otmacro->ptr, "mirror", false); + + ot = WM_operatortype_append_macro("MESH_OT_polybuild_transform_at_cursor_move", + "Transform at Cursor Move", + "", + OPTYPE_UNDO | OPTYPE_REGISTER); + WM_operatortype_macro_define(ot, "MESH_OT_polybuild_transform_at_cursor"); + otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); + RNA_boolean_set(otmacro->ptr, "use_proportional_edit", false); + RNA_boolean_set(otmacro->ptr, "mirror", false); + + ot = WM_operatortype_append_macro("MESH_OT_polybuild_extrude_at_cursor_move", + "Extrude at Cursor Move", + "", + OPTYPE_UNDO | OPTYPE_REGISTER); + WM_operatortype_macro_define(ot, "MESH_OT_polybuild_transform_at_cursor"); + otmacro = WM_operatortype_macro_define(ot, "MESH_OT_extrude_edges_indiv"); + otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); + RNA_boolean_set(otmacro->ptr, "use_proportional_edit", false); + RNA_boolean_set(otmacro->ptr, "mirror", false); } /* note mesh keymap also for other space? */ diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt index 2490f88b5eb..aabfa78cf58 100644 --- a/source/blender/editors/object/CMakeLists.txt +++ b/source/blender/editors/object/CMakeLists.txt @@ -48,6 +48,7 @@ set(SRC object_collection.c object_constraint.c object_data_transfer.c + object_data_transform.c object_edit.c object_facemap_ops.c object_gpencil_modifier.c diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index db1aa6ca37f..3d5ec3d4ed5 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -103,6 +103,7 @@ #include "ED_mesh.h" #include "ED_node.h" #include "ED_object.h" +#include "ED_outliner.h" #include "ED_physics.h" #include "ED_render.h" #include "ED_screen.h" @@ -502,6 +503,8 @@ Object *ED_object_add_type(bContext *C, /* TODO(sergey): Use proper flag for tagging here. */ DEG_id_tag_update(&scene->id, 0); + ED_outliner_select_sync_from_object_tag(C); + return ob; } @@ -2383,13 +2386,22 @@ static int convert_exec(bContext *C, wmOperator *op) BKE_object_free_curve_cache(newob); } else if (target == OB_GPENCIL) { - /* Create a new grease pencil object */ - if (gpencil_ob == NULL) { - const float *cur = scene->cursor.location; - ushort local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uuid : 0; - gpencil_ob = ED_gpencil_add_object(C, scene, cur, local_view_bits); + if (ob->type != OB_CURVE) { + BKE_report( + op->reports, RPT_ERROR, "Convert Surfaces to Grease Pencil is not supported."); + } + else { + /* Create a new grease pencil object only if it was not created before. + * All curves selected are converted as strokes of the same grease pencil object. + * Nurbs Surface are not supported. + */ + if (gpencil_ob == NULL) { + const float *cur = scene->cursor.location; + ushort local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uuid : 0; + gpencil_ob = ED_gpencil_add_object(C, scene, cur, local_view_bits); + } + BKE_gpencil_convert_curve(bmain, scene, gpencil_ob, ob, false, false, true); } - BKE_gpencil_convert_curve(bmain, scene, gpencil_ob, ob, gpencil_lines, use_collections); } } else if (ob->type == OB_MBALL && target == OB_MESH) { diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index 7343dba420f..8981221cb9c 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -493,8 +493,12 @@ static void test_constraint( CONSTRAINT_TYPE_CLAMPTO, CONSTRAINT_TYPE_SPLINEIK)) { if (ct->tar) { + /* The object type check is only needed here in case we have a placeholder + * object assigned (because the library containing the curve is missing). + * + * In other cases it should be impossible to have a type mismatch. + */ if (ct->tar->type != OB_CURVE) { - ct->tar = NULL; con->flag |= CONSTRAINT_DISABLE; } else { @@ -507,8 +511,12 @@ static void test_constraint( } else if (con->type == CONSTRAINT_TYPE_ARMATURE) { if (ct->tar) { + /* The object type check is only needed here in case we have a placeholder + * object assigned (because the library containing the armature is missing). + * + * In other cases it should be impossible to have a type mismatch. + */ if (ct->tar->type != OB_ARMATURE) { - ct->tar = NULL; con->flag |= CONSTRAINT_DISABLE; } else if (!BKE_armature_find_bone_name(BKE_armature_from_object(ct->tar), @@ -636,7 +644,7 @@ static const EnumPropertyItem constraint_owner_items[] = { static bool edit_constraint_poll_generic(bContext *C, StructRNA *rna_type) { PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", rna_type); - Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C); + Object *ob = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C); if (!ptr.data) { CTX_wm_operator_poll_msg_set(C, "Context missing 'constraint'"); @@ -648,7 +656,7 @@ static bool edit_constraint_poll_generic(bContext *C, StructRNA *rna_type) return 0; } - if (ID_IS_LINKED(ob) || (ptr.id.data && ID_IS_LINKED(ptr.id.data))) { + if (ID_IS_LINKED(ob) || (ptr.owner_id && ID_IS_LINKED(ptr.owner_id))) { CTX_wm_operator_poll_msg_set(C, "Cannot edit library data"); return 0; } @@ -680,7 +688,7 @@ static void edit_constraint_properties(wmOperatorType *ot) static int edit_constraint_invoke_properties(bContext *C, wmOperator *op) { PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint); - Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C); + Object *ob = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C); bConstraint *con; ListBase *list; @@ -1422,14 +1430,14 @@ void ED_object_constraint_dependency_tag_update(Main *bmain, Object *ob, bConstr static bool constraint_poll(bContext *C) { PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint); - return (ptr.id.data && ptr.data); + return (ptr.owner_id && ptr.data); } static int constraint_delete_exec(bContext *C, wmOperator *UNUSED(op)) { Main *bmain = CTX_data_main(C); PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint); - Object *ob = ptr.id.data; + Object *ob = (Object *)ptr.owner_id; bConstraint *con = ptr.data; ListBase *lb = get_constraint_lb(ob, con, NULL); diff --git a/source/blender/editors/object/object_data_transform.c b/source/blender/editors/object/object_data_transform.c new file mode 100644 index 00000000000..ee86c79ead5 --- /dev/null +++ b/source/blender/editors/object/object_data_transform.c @@ -0,0 +1,333 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + */ + +/** \file + * \ingroup edobj + * + * Use to transform object origins only. + * + * This is a small API to store & apply transformations to object data, + * where a transformation matrix can be continually applied ontop of the original values + * so we don't loose precision over time. + */ + +#include <stdlib.h> +#include <string.h> + +#include "DNA_anim_types.h" +#include "DNA_armature_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meta_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_collection_types.h" +#include "DNA_lattice_types.h" + +#include "BLI_math.h" +#include "BLI_listbase.h" +#include "BLI_utildefines.h" + +#include "BKE_curve.h" +#include "BKE_mball.h" +#include "BKE_mesh.h" +#include "BKE_armature.h" +#include "BKE_lattice.h" + +#include "DEG_depsgraph.h" + +#include "WM_types.h" + +#include "ED_object.h" + +#include "MEM_guardedalloc.h" + +/* -------------------------------------------------------------------- */ +/** \name Internal Transform Get/Apply + * + * Some object data types don't have utility functions to access their transformation data. + * Define these locally. + * + * \{ */ + +/* Armature */ + +struct ElemData_Armature { + float tail[3]; + float head[3]; + float roll; + float arm_tail[3]; + float arm_head[3]; + float arm_roll; + float rad_tail; + float rad_head; + float dist; + float xwidth; + float zwidth; +}; + +static struct ElemData_Armature *armature_coords_and_quats_get_recurse( + const ListBase *bone_base, struct ElemData_Armature *elem_array) +{ + struct ElemData_Armature *elem = elem_array; + for (const Bone *bone = bone_base->first; bone; bone = bone->next) { + +#define COPY_PTR(member) memcpy(elem->member, bone->member, sizeof(bone->member)) +#define COPY_VAL(member) memcpy(&elem->member, &bone->member, sizeof(bone->member)) + COPY_PTR(head); + COPY_PTR(tail); + COPY_VAL(roll); + COPY_PTR(arm_head); + COPY_PTR(arm_tail); + COPY_VAL(arm_roll); + COPY_VAL(rad_tail); + COPY_VAL(rad_head); + COPY_VAL(dist); + COPY_VAL(xwidth); + COPY_VAL(zwidth); +#undef COPY_PTR +#undef COPY_VAL + + elem = armature_coords_and_quats_get_recurse(&bone->childbase, elem + 1); + } + return elem; +} + +static void armature_coords_and_quats_get(const bArmature *arm, + struct ElemData_Armature *elem_array) +{ + armature_coords_and_quats_get_recurse(&arm->bonebase, elem_array); +} + +static const struct ElemData_Armature *armature_coords_and_quats_apply_with_mat4_recurse( + ListBase *bone_base, const struct ElemData_Armature *elem_array, const float mat[4][4]) +{ + const struct ElemData_Armature *elem = elem_array; + for (Bone *bone = bone_base->first; bone; bone = bone->next) { + +#define COPY_PTR(member) memcpy(bone->member, elem->member, sizeof(bone->member)) +#define COPY_VAL(member) memcpy(&bone->member, &elem->member, sizeof(bone->member)) + COPY_PTR(head); + COPY_PTR(tail); + COPY_VAL(roll); + COPY_PTR(arm_head); + COPY_PTR(arm_tail); + COPY_VAL(arm_roll); + COPY_VAL(rad_tail); + COPY_VAL(rad_head); + COPY_VAL(dist); + COPY_VAL(xwidth); + COPY_VAL(zwidth); +#undef COPY_PTR +#undef COPY_VAL + + elem = armature_coords_and_quats_apply_with_mat4_recurse(&bone->childbase, elem + 1, mat); + } + return elem; +} + +static void armature_coords_and_quats_apply_with_mat4(bArmature *arm, + const struct ElemData_Armature *elem_array, + const float mat[4][4]) +{ + armature_coords_and_quats_apply_with_mat4_recurse(&arm->bonebase, elem_array, mat); + BKE_armature_transform(arm, mat, true); +} + +/* MetaBall */ + +struct ElemData_MetaBall { + float co[3]; + float quat[4]; + float exp[3]; + float rad; +}; + +static void metaball_coords_and_quats_get(const MetaBall *mb, struct ElemData_MetaBall *elem_array) +{ + struct ElemData_MetaBall *elem = elem_array; + for (const MetaElem *ml = mb->elems.first; ml; ml = ml->next, elem++) { + copy_v3_v3(elem->co, &ml->x); + copy_qt_qt(elem->quat, ml->quat); + copy_v3_v3(elem->exp, &ml->expx); + elem->rad = ml->rad; + } +} + +static void metaball_coords_and_quats_apply_with_mat4(MetaBall *mb, + const struct ElemData_MetaBall *elem_array, + const float mat[4][4]) +{ + const struct ElemData_MetaBall *elem = elem_array; + for (MetaElem *ml = mb->elems.first; ml; ml = ml->next, elem++) { + copy_v3_v3(&ml->x, elem->co); + copy_qt_qt(ml->quat, elem->quat); + copy_v3_v3(&ml->expx, elem->exp); + ml->rad = elem->rad; + } + BKE_mball_transform(mb, mat, true); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Public Object Data Storage API + * + * Used for interactively transforming object data. + * + * Store object data transformation in an opaque struct. + * \{ */ + +struct XFormObjectData { + ID *id; +}; + +struct XFormObjectData_Mesh { + struct XFormObjectData base; + float elem_array[0][3]; +}; + +struct XFormObjectData_Lattice { + struct XFormObjectData base; + float elem_array[0][3]; +}; + +struct XFormObjectData_Curve { + struct XFormObjectData base; + float elem_array[0][3]; +}; + +struct XFormObjectData_Armature { + struct XFormObjectData base; + struct ElemData_Armature elem_array[0]; +}; + +struct XFormObjectData_MetaBall { + struct XFormObjectData base; + struct ElemData_MetaBall elem_array[0]; +}; + +struct XFormObjectData *ED_object_data_xform_create(ID *id) +{ + struct XFormObjectData *xod_base = NULL; + switch (GS(id->name)) { + case ID_ME: { + Mesh *me = (Mesh *)id; + const int elem_array_len = me->totvert; + struct XFormObjectData_Mesh *xod = MEM_mallocN( + sizeof(*xod) + (sizeof(*xod->elem_array) * elem_array_len), __func__); + BKE_mesh_vert_coords_get(me, xod->elem_array); + xod_base = &xod->base; + break; + } + case ID_LT: { + Lattice *lt = (Lattice *)id; + const int elem_array_len = lt->pntsu * lt->pntsv * lt->pntsw; + struct XFormObjectData_Lattice *xod = MEM_mallocN( + sizeof(*xod) + (sizeof(*xod->elem_array) * elem_array_len), __func__); + BKE_lattice_vert_coords_get(lt, xod->elem_array); + xod_base = &xod->base; + break; + } + case ID_CU: { + Curve *cu = (Curve *)id; + const short ob_type = BKE_curve_type_get(cu); + if (ob_type == OB_FONT) { + /* We could support translation. */ + break; + } + const int elem_array_len = BKE_nurbList_verts_count(&cu->nurb); + struct XFormObjectData_Curve *xod = MEM_mallocN( + sizeof(*xod) + (sizeof(*xod->elem_array) * elem_array_len), __func__); + BKE_curve_nurbs_vert_coords_get(&cu->nurb, xod->elem_array, elem_array_len); + xod_base = &xod->base; + break; + } + case ID_AR: { + bArmature *arm = (bArmature *)id; + const int elem_array_len = BKE_armature_bonelist_count(&arm->bonebase); + struct XFormObjectData_Armature *xod = MEM_mallocN( + sizeof(*xod) + (sizeof(*xod->elem_array) * elem_array_len), __func__); + armature_coords_and_quats_get(arm, xod->elem_array); + xod_base = &xod->base; + break; + } + case ID_MB: { + MetaBall *mb = (MetaBall *)id; + const int elem_array_len = BLI_listbase_count(&mb->elems); + struct XFormObjectData_MetaBall *xod = MEM_mallocN( + sizeof(*xod) + (sizeof(*xod->elem_array) * elem_array_len), __func__); + metaball_coords_and_quats_get(mb, xod->elem_array); + xod_base = &xod->base; + break; + } + default: { + break; + } + } + if (xod_base) { + xod_base->id = id; + } + return xod_base; +} + +void ED_object_data_xform_destroy(struct XFormObjectData *xod) +{ + MEM_freeN(xod); +} + +void ED_object_data_xform_by_mat4(struct XFormObjectData *xod_base, const float mat[4][4]) +{ + switch (GS(xod_base->id->name)) { + case ID_ME: { + Mesh *me = (Mesh *)xod_base->id; + struct XFormObjectData_Mesh *xod = (struct XFormObjectData_Mesh *)xod_base; + BKE_mesh_vert_coords_apply_with_mat4(me, xod->elem_array, mat); + break; + } + case ID_LT: { + Lattice *lt = (Lattice *)xod_base->id; + struct XFormObjectData_Lattice *xod = (struct XFormObjectData_Lattice *)xod_base; + BKE_lattice_vert_coords_apply_with_mat4(lt, xod->elem_array, mat); + break; + } + case ID_CU: { + Curve *cu = (Curve *)xod_base->id; + struct XFormObjectData_Curve *xod = (struct XFormObjectData_Curve *)xod_base; + BKE_curve_nurbs_vert_coords_apply_with_mat4(&cu->nurb, xod->elem_array, mat, true); + break; + } + case ID_AR: { + bArmature *arm = (bArmature *)xod_base->id; + struct XFormObjectData_Armature *xod = (struct XFormObjectData_Armature *)xod_base; + armature_coords_and_quats_apply_with_mat4(arm, xod->elem_array, mat); + break; + } + case ID_MB: { + MetaBall *mb = (MetaBall *)xod_base->id; + struct XFormObjectData_MetaBall *xod = (struct XFormObjectData_MetaBall *)xod_base; + metaball_coords_and_quats_apply_with_mat4(mb, xod->elem_array, mat); + break; + } + default: { + break; + } + } +} + +/** \} */ diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index ed40a4eb948..33c7ffefb8b 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -116,6 +116,7 @@ typedef struct MoveToCollectionData MoveToCollectionData; static void move_to_collection_menus_items(struct uiLayout *layout, struct MoveToCollectionData *menu); +static ListBase selected_objects_get(bContext *C); /* ************* XXX **************** */ static void error(const char *UNUSED(arg)) @@ -593,7 +594,7 @@ bool ED_object_editmode_enter_ex(Main *bmain, Scene *scene, Object *ob, int flag if (LIKELY(em)) { /* order doesn't matter */ EDBM_mesh_normals_update(em); - BKE_editmesh_tessface_calc(em); + BKE_editmesh_looptri_calc(em); } WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_MESH, NULL); @@ -1199,7 +1200,7 @@ static int shade_smooth_exec(bContext *C, wmOperator *op) } if (ob->type == OB_MESH) { - BKE_mesh_smooth_flag_set(ob, !clear); + BKE_mesh_smooth_flag_set(ob->data, !clear); BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL); DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); @@ -1460,6 +1461,23 @@ void OBJECT_OT_mode_set_or_submode(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } +static ListBase selected_objects_get(bContext *C) +{ + ListBase objects = {NULL}; + + if (CTX_wm_space_outliner(C) != NULL) { + ED_outliner_selected_objects_get(C, &objects); + } + else { + CTX_DATA_BEGIN (C, Object *, ob, selected_objects) { + BLI_addtail(&objects, BLI_genericNodeN(ob)); + } + CTX_DATA_END; + } + + return objects; +} + static bool move_to_collection_poll(bContext *C) { if (CTX_wm_space_outliner(C) != NULL) { @@ -1472,7 +1490,7 @@ static bool move_to_collection_poll(bContext *C) return false; } - return ED_operator_object_active_editable(C); + return ED_operator_objectmode(C); } } @@ -1498,15 +1516,7 @@ static int move_to_collection_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - if (CTX_wm_space_outliner(C) != NULL) { - ED_outliner_selected_objects_get(C, &objects); - } - else { - CTX_DATA_BEGIN (C, Object *, ob, selected_objects) { - BLI_addtail(&objects, BLI_genericNodeN(ob)); - } - CTX_DATA_END; - } + objects = selected_objects_get(C); if (is_new) { char new_collection_name[MAX_NAME]; @@ -1650,6 +1660,13 @@ static int move_to_collection_invoke(bContext *C, wmOperator *op, const wmEvent { Scene *scene = CTX_data_scene(C); + ListBase objects = selected_objects_get(C); + if (BLI_listbase_is_empty(&objects)) { + BKE_report(op->reports, RPT_ERROR, "No objects selected"); + return OPERATOR_CANCELLED; + } + BLI_freelistN(&objects); + /* Reset the menus data for the current master collection, and free previously allocated data. */ move_to_collection_menus_free(&master_collection_menu); @@ -1674,7 +1691,7 @@ static int move_to_collection_invoke(bContext *C, wmOperator *op, const wmEvent return move_to_collection_exec(C, op); } - Collection *master_collection = BKE_collection_master(scene); + Collection *master_collection = scene->master_collection; /* We need the data to be allocated so it's available during menu drawing. * Technically we could use wmOperator->customdata. However there is no free callback diff --git a/source/blender/editors/object/object_gpencil_modifier.c b/source/blender/editors/object/object_gpencil_modifier.c index 075cd5acad6..9138e65dd2f 100644 --- a/source/blender/editors/object/object_gpencil_modifier.c +++ b/source/blender/editors/object/object_gpencil_modifier.c @@ -390,7 +390,7 @@ void OBJECT_OT_gpencil_modifier_add(wmOperatorType *ot) static int gpencil_edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag) { PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", rna_type); - Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C); + Object *ob = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C); if (!ob || ID_IS_LINKED(ob)) { return 0; @@ -398,7 +398,7 @@ static int gpencil_edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0) { return 0; } - if (ptr.id.data && ID_IS_LINKED(ptr.id.data)) { + if (ptr.owner_id && ID_IS_LINKED(ptr.owner_id)) { return 0; } diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c index 15c5ea40991..bcbf7ddf9a6 100644 --- a/source/blender/editors/object/object_hook.c +++ b/source/blender/editors/object/object_hook.c @@ -352,7 +352,7 @@ static bool object_hook_index_array(Main *bmain, em = me->edit_mesh; EDBM_mesh_normals_update(em); - BKE_editmesh_tessface_calc(em); + BKE_editmesh_looptri_calc(em); /* check selected vertices first */ if (return_editmesh_indexar(em, r_tot, r_indexar, r_cent) == 0) { @@ -436,7 +436,7 @@ static void object_hook_from_context( HookModifierData *hmd; if (ptr->data) { /* if modifier context is available, use that */ - ob = ptr->id.data; + ob = (Object *)ptr->owner_id; hmd = ptr->data; } else { /* use the provided property */ diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 8818fd71190..88d01936882 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -52,6 +52,7 @@ #include "BKE_editmesh.h" #include "BKE_effect.h" #include "BKE_global.h" +#include "BKE_gpencil_modifier.h" #include "BKE_key.h" #include "BKE_lattice.h" #include "BKE_library.h" @@ -110,6 +111,9 @@ static void object_force_modifier_update_for_bind(Depsgraph *depsgraph, Object * else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { BKE_displist_make_curveTypes(depsgraph, scene_eval, ob_eval, false, false); } + else if (ob->type == OB_GPENCIL) { + BKE_gpencil_modifiers_calc(depsgraph, scene_eval, ob_eval); + } } static void object_force_modifier_bind_simple_options(Depsgraph *depsgraph, @@ -714,9 +718,9 @@ static int modifier_apply_obdata( RPT_INFO, "Applied modifier only changed CV points, not tessellated/bevel vertices"); - vertexCos = BKE_curve_nurbs_vertexCos_get(&curve_eval->nurb, &numVerts); + vertexCos = BKE_curve_nurbs_vert_coords_alloc(&curve_eval->nurb, &numVerts); mti->deformVerts(md_eval, &mectx, NULL, vertexCos, numVerts); - BK_curve_nurbs_vertexCos_apply(&curve->nurb, vertexCos); + BKE_curve_nurbs_vert_coords_apply(&curve->nurb, vertexCos, false); MEM_freeN(vertexCos); @@ -918,7 +922,7 @@ bool edit_modifier_poll_generic(bContext *C, const bool is_editmode_allowed) { PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", rna_type); - Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C); + Object *ob = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C); if (!ob || ID_IS_LINKED(ob)) { return 0; @@ -926,7 +930,7 @@ bool edit_modifier_poll_generic(bContext *C, if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0) { return 0; } - if (ptr.id.data && ID_IS_LINKED(ptr.id.data)) { + if (ptr.owner_id && ID_IS_LINKED(ptr.owner_id)) { return 0; } diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index a69f4872e72..06c360ed1cd 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -149,7 +149,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op) em = me->edit_mesh; EDBM_mesh_normals_update(em); - BKE_editmesh_tessface_calc(em); + BKE_editmesh_looptri_calc(em); /* Make sure the evaluated mesh is updated. * @@ -1434,7 +1434,7 @@ static int make_links_scene_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - Collection *collection_to = BKE_collection_master(scene_to); + Collection *collection_to = scene_to->master_collection; CTX_DATA_BEGIN (C, Base *, base, selected_bases) { BKE_collection_object_add(bmain, collection_to, base->object); } @@ -1744,7 +1744,7 @@ static Collection *single_object_users_collection(Main *bmain, } /* Since master collection has already be duplicated as part of scene copy, - * we do not duplictae it here. + * we do not duplicate it here. * However, this means its children need to be re-added manually here, * otherwise their parent lists are empty (which will lead to crashes, see T63101). */ CollectionChild *child_next, *child = collection->children.first; @@ -1771,7 +1771,7 @@ static void single_object_users( Main *bmain, Scene *scene, View3D *v3d, const int flag, const bool copy_collections) { /* duplicate all the objects of the scene (and matching collections, if required). */ - Collection *master_collection = BKE_collection_master(scene); + Collection *master_collection = scene->master_collection; single_object_users_collection(bmain, scene, master_collection, flag, copy_collections, true); /* duplicate collections that consist entirely of duplicated objects */ @@ -2426,6 +2426,8 @@ static int make_override_library_exec(bContext *C, wmOperator *op) if (!ID_IS_LINKED(obact) && obact->instance_collection != NULL && ID_IS_LINKED(obact->instance_collection)) { + BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); + Object *obcollection = obact; Collection *collection = obcollection->instance_collection; @@ -2471,7 +2473,11 @@ static int make_override_library_exec(bContext *C, wmOperator *op) DEG_id_tag_update_ex(bmain, &new_ob->id, ID_RECALC_TRANSFORM | ID_RECALC_BASE_FLAGS); } /* parent to 'collection' empty */ - if (new_ob->parent == NULL) { + /* Disabled for now, according to some artist this is probably not really useful anyway. + * And it breaks things like objects parented to bones + * (most likely due to missing proper setting of inverse parent matrix?)... */ + /* Note: we might even actually want to get rid of that instanciating empty... */ + if (0 && new_ob->parent == NULL) { new_ob->parent = obcollection; } if (new_ob == (Object *)obact->id.newid) { @@ -2499,7 +2505,7 @@ static int make_override_library_exec(bContext *C, wmOperator *op) /* Cleanup. */ BKE_main_id_clear_newpoins(bmain); - BKE_main_id_tag_listbase(&bmain->objects, LIB_TAG_DOIT, false); + BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); } /* Else, poll func ensures us that ID_IS_LINKED(obact) is true. */ else if (obact->type == OB_ARMATURE) { @@ -2518,7 +2524,7 @@ static int make_override_library_exec(bContext *C, wmOperator *op) /* Cleanup. */ BKE_main_id_clear_newpoins(bmain); - BKE_main_id_tag_listbase(&bmain->objects, LIB_TAG_DOIT, false); + BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); } /* TODO: probably more cases where we want to do automated smart things in the future! */ else { @@ -2706,7 +2712,7 @@ static int object_unlink_data_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - id = pprop.ptr.id.data; + id = pprop.ptr.owner_id; if (GS(id->name) == ID_OB) { Object *ob = (Object *)id; diff --git a/source/blender/editors/object/object_remesh.c b/source/blender/editors/object/object_remesh.c index 1bcac9b4739..5f464084a9b 100644 --- a/source/blender/editors/object/object_remesh.c +++ b/source/blender/editors/object/object_remesh.c @@ -108,7 +108,7 @@ static int voxel_remesh_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - Mesh *obj_mesh_copy; + Mesh *obj_mesh_copy = NULL; if (mesh->flag & ME_REMESH_REPROJECT_PAINT_MASK) { obj_mesh_copy = BKE_mesh_new_nomain_from_template(mesh, mesh->totvert, 0, 0, 0, 0); CustomData_copy( @@ -126,7 +126,7 @@ static int voxel_remesh_exec(bContext *C, wmOperator *op) } if (mesh->flag & ME_REMESH_SMOOTH_NORMALS) { - BKE_mesh_smooth_flag_set(ob, true); + BKE_mesh_smooth_flag_set(ob->data, true); } if (ob->mode == OB_MODE_SCULPT) { diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c index da06707ebac..28242b986f1 100644 --- a/source/blender/editors/object/object_select.c +++ b/source/blender/editors/object/object_select.c @@ -69,6 +69,7 @@ #include "ED_armature.h" #include "ED_object.h" +#include "ED_outliner.h" #include "ED_screen.h" #include "ED_select_utils.h" #include "ED_keyframing.h" @@ -436,6 +437,8 @@ static int object_select_by_type_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + ED_outliner_select_sync_from_object_tag(C); + return OPERATOR_FINISHED; } @@ -717,6 +720,7 @@ static int object_select_linked_exec(bContext *C, wmOperator *op) if (changed) { DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + ED_outliner_select_sync_from_object_tag(C); return OPERATOR_FINISHED; } @@ -1100,6 +1104,7 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op) if (changed) { DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + ED_outliner_select_sync_from_object_tag(C); return OPERATOR_FINISHED; } @@ -1150,6 +1155,8 @@ static int object_select_all_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + ED_outliner_select_sync_from_object_tag(C); + return OPERATOR_FINISHED; } else if (any_visible == false) { @@ -1218,6 +1225,8 @@ static int object_select_same_collection_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + ED_outliner_select_sync_from_object_tag(C); + return OPERATOR_FINISHED; } @@ -1281,6 +1290,8 @@ static int object_select_mirror_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + ED_outliner_select_sync_from_object_tag(C); + return OPERATOR_FINISHED; } @@ -1369,6 +1380,9 @@ static int object_select_more_exec(bContext *C, wmOperator *UNUSED(op)) Scene *scene = CTX_data_scene(C); DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + + ED_outliner_select_sync_from_object_tag(C); + return OPERATOR_FINISHED; } else { @@ -1399,6 +1413,9 @@ static int object_select_less_exec(bContext *C, wmOperator *UNUSED(op)) Scene *scene = CTX_data_scene(C); DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + + ED_outliner_select_sync_from_object_tag(C); + return OPERATOR_FINISHED; } else { @@ -1448,6 +1465,8 @@ static int object_select_random_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + ED_outliner_select_sync_from_object_tag(C); + return OPERATOR_FINISHED; } diff --git a/source/blender/editors/object/object_shader_fx.c b/source/blender/editors/object/object_shader_fx.c index 457d2421253..db0c8c54186 100644 --- a/source/blender/editors/object/object_shader_fx.c +++ b/source/blender/editors/object/object_shader_fx.c @@ -294,7 +294,7 @@ void OBJECT_OT_shaderfx_add(wmOperatorType *ot) static bool edit_shaderfx_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag) { PointerRNA ptr = CTX_data_pointer_get_type(C, "shaderfx", rna_type); - Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C); + Object *ob = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C); if (!ptr.data) { CTX_wm_operator_poll_msg_set(C, "Context missing 'shaderfx'"); @@ -307,7 +307,7 @@ static bool edit_shaderfx_poll_generic(bContext *C, StructRNA *rna_type, int obt if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0) { return 0; } - if (ptr.id.data && ID_IS_LINKED(ptr.id.data)) { + if (ptr.owner_id && ID_IS_LINKED(ptr.owner_id)) { return 0; } diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index 975aa0f5bac..2a8b306b085 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -77,7 +77,9 @@ #include "object_intern.h" -/*************************** Clear Transformation ****************************/ +/* -------------------------------------------------------------------- */ +/** \name Clear Transformation Utilities + * \{ */ /* clear location of object */ static void object_clear_loc(Object *ob, const bool clear_delta) @@ -284,8 +286,6 @@ static void object_clear_scale(Object *ob, const bool clear_delta) } } -/* --------------- */ - /* generic exec for clear-transform operators */ static int object_clear_transform_generic_exec(bContext *C, wmOperator *op, @@ -329,7 +329,11 @@ static int object_clear_transform_generic_exec(bContext *C, return OPERATOR_FINISHED; } -/* --------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Clear Location Operator + * \{ */ static int object_location_clear_exec(bContext *C, wmOperator *op) { @@ -359,6 +363,12 @@ void OBJECT_OT_location_clear(wmOperatorType *ot) "Clear delta location in addition to clearing the normal location transform"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Clear Rotation Operator + * \{ */ + static int object_rotation_clear_exec(bContext *C, wmOperator *op) { return object_clear_transform_generic_exec(C, op, object_clear_rot, ANIM_KS_ROTATION_ID); @@ -387,6 +397,12 @@ void OBJECT_OT_rotation_clear(wmOperatorType *ot) "Clear delta rotation in addition to clearing the normal rotation transform"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Clear Scale Operator + * \{ */ + static int object_scale_clear_exec(bContext *C, wmOperator *op) { return object_clear_transform_generic_exec(C, op, object_clear_scale, ANIM_KS_SCALING_ID); @@ -415,7 +431,11 @@ void OBJECT_OT_scale_clear(wmOperatorType *ot) "Clear delta scale in addition to clearing the normal scale transform"); } -/* --------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Clear Origin Operator + * \{ */ static int object_origin_clear_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -457,7 +477,11 @@ void OBJECT_OT_origin_clear(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/*************************** Apply Transformation ****************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Apply Transformation Operator + * \{ */ /* use this when the loc/size/rot of the parent has changed but the children * should stay in the same place, e.g. for apply-size-rot or object center */ @@ -744,7 +768,8 @@ static int apply_objects_internal(bContext *C, BKE_mesh_calc_normals(me); } else if (ob->type == OB_ARMATURE) { - ED_armature_transform_apply(bmain, ob, mat, do_props); + bArmature *arm = ob->data; + BKE_armature_transform(arm, mat, do_props); } else if (ob->type == OB_LATTICE) { Lattice *lt = ob->data; @@ -960,7 +985,11 @@ void OBJECT_OT_transform_apply(wmOperatorType *ot) "Modify properties such as curve vertex radius, font size and bone envelope"); } -/********************* Set Object Center ************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Set Object Center Operator + * \{ */ enum { GEOMETRY_TO_ORIGIN = 0, @@ -1152,7 +1181,8 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { Curve *cu = ob->data; - if (centermode == ORIGIN_TO_CURSOR) { /* done */ + if (centermode == ORIGIN_TO_CURSOR) { + /* done */ } else if (around == V3D_AROUND_CENTER_MEDIAN) { BKE_curve_center_median(cu, cent); @@ -1244,7 +1274,8 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) else if (ob->type == OB_MBALL) { MetaBall *mb = ob->data; - if (centermode == ORIGIN_TO_CURSOR) { /* done */ + if (centermode == ORIGIN_TO_CURSOR) { + /* done */ } else if (around == V3D_AROUND_CENTER_MEDIAN) { BKE_mball_center_median(mb, cent); @@ -1270,7 +1301,8 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) else if (ob->type == OB_LATTICE) { Lattice *lt = ob->data; - if (centermode == ORIGIN_TO_CURSOR) { /* done */ + if (centermode == ORIGIN_TO_CURSOR) { + /* done */ } else if (around == V3D_AROUND_CENTER_MEDIAN) { BKE_lattice_center_median(lt, cent); @@ -1323,11 +1355,6 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) invert_m4_m4(inverse_diff_mat, diff_mat); for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) { for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { - /* skip strokes that are invalid for current view */ - if (ED_gpencil_stroke_can_use(C, gps) == false) { - continue; - } - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { float mpt[3]; mul_v3_m4v3(mpt, inverse_diff_mat, &pt->x); @@ -1509,6 +1536,8 @@ void OBJECT_OT_origin_set(wmOperatorType *ot) RNA_def_enum(ot->srna, "center", prop_set_bounds_types, V3D_AROUND_CENTER_MEDIAN, "Center", ""); } +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Transform Axis Target * diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 08fe5e818b2..ce385b12608 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -3794,7 +3794,7 @@ static int vgroup_sort_name(const void *def_a_ptr, const void *def_b_ptr) const bDeformGroup *def_a = def_a_ptr; const bDeformGroup *def_b = def_b_ptr; - return BLI_natstrcmp(def_a->name, def_b->name); + return BLI_strcasecmp_natural(def_a->name, def_b->name); } /** diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c index 0999d1f3588..fbaf02b7b3f 100644 --- a/source/blender/editors/physics/particle_object.c +++ b/source/blender/editors/physics/particle_object.c @@ -186,7 +186,7 @@ static int new_particle_settings_exec(bContext *C, wmOperator *UNUSED(op)) part = BKE_particlesettings_add(bmain, "ParticleSettings"); } - ob = ptr.id.data; + ob = (Object *)ptr.owner_id; if (psys->part) { id_us_min(&psys->part->id); @@ -226,7 +226,7 @@ static int new_particle_target_exec(bContext *C, wmOperator *UNUSED(op)) Main *bmain = CTX_data_main(C); PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); ParticleSystem *psys = ptr.data; - Object *ob = ptr.id.data; + Object *ob = (Object *)ptr.owner_id; ParticleTarget *pt; @@ -273,7 +273,7 @@ static int remove_particle_target_exec(bContext *C, wmOperator *UNUSED(op)) Main *bmain = CTX_data_main(C); PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); ParticleSystem *psys = ptr.data; - Object *ob = ptr.id.data; + Object *ob = (Object *)ptr.owner_id; ParticleTarget *pt; @@ -323,7 +323,7 @@ static int target_move_up_exec(bContext *C, wmOperator *UNUSED(op)) { PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); ParticleSystem *psys = ptr.data; - Object *ob = ptr.id.data; + Object *ob = (Object *)ptr.owner_id; ParticleTarget *pt; if (!psys) { @@ -363,7 +363,7 @@ static int target_move_down_exec(bContext *C, wmOperator *UNUSED(op)) { PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); ParticleSystem *psys = ptr.data; - Object *ob = ptr.id.data; + Object *ob = (Object *)ptr.owner_id; ParticleTarget *pt; if (!psys) { @@ -1140,6 +1140,7 @@ static bool copy_particle_systems_to_object(const bContext *C, /* append to the object */ BLI_addtail(&ob_to->particlesystem, psys); + psys_unique_name(ob_to, psys, psys->name); /* add a particle system modifier for each system */ md = modifier_new(eModifierType_ParticleSystem); diff --git a/source/blender/editors/physics/physics_intern.h b/source/blender/editors/physics/physics_intern.h index 9ebbba07fdf..fc2f3d21bb6 100644 --- a/source/blender/editors/physics/physics_intern.h +++ b/source/blender/editors/physics/physics_intern.h @@ -30,7 +30,6 @@ struct PTCacheEdit; struct ParticleSystem; struct PointCache; struct Scene; -struct ViewLayer; struct wmOperatorType; /* particle_edit.c */ diff --git a/source/blender/editors/physics/physics_pointcache.c b/source/blender/editors/physics/physics_pointcache.c index bc2f1d6cef6..700a94e4f93 100644 --- a/source/blender/editors/physics/physics_pointcache.c +++ b/source/blender/editors/physics/physics_pointcache.c @@ -57,7 +57,7 @@ static bool ptcache_bake_all_poll(bContext *C) static bool ptcache_poll(bContext *C) { PointerRNA ptr = CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache); - return (ptr.data && ptr.id.data); + return (ptr.data && ptr.owner_id); } typedef struct PointCacheJob { @@ -165,7 +165,7 @@ static PTCacheBaker *ptcache_baker_create(bContext *C, wmOperator *op, bool all) if (!all) { PointerRNA ptr = CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache); - Object *ob = ptr.id.data; + Object *ob = (Object *)ptr.owner_id; PointCache *cache = ptr.data; baker->pid = BKE_ptcache_id_find(ob, baker->scene, cache); } @@ -300,7 +300,7 @@ static int ptcache_free_bake_exec(bContext *C, wmOperator *UNUSED(op)) { PointerRNA ptr = CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache); PointCache *cache = ptr.data; - Object *ob = ptr.id.data; + Object *ob = (Object *)ptr.owner_id; ptcache_free_bake(cache); @@ -312,7 +312,7 @@ static int ptcache_bake_from_cache_exec(bContext *C, wmOperator *UNUSED(op)) { PointerRNA ptr = CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache); PointCache *cache = ptr.data; - Object *ob = ptr.id.data; + Object *ob = (Object *)ptr.owner_id; cache->flag |= PTCACHE_BAKED; @@ -372,7 +372,7 @@ static int ptcache_add_new_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); PointerRNA ptr = CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache); - Object *ob = ptr.id.data; + Object *ob = (Object *)ptr.owner_id; PointCache *cache = ptr.data; PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache); @@ -392,7 +392,7 @@ static int ptcache_remove_exec(bContext *C, wmOperator *UNUSED(op)) { PointerRNA ptr = CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache); Scene *scene = CTX_data_scene(C); - Object *ob = ptr.id.data; + Object *ob = (Object *)ptr.owner_id; PointCache *cache = ptr.data; PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache); diff --git a/source/blender/editors/render/render_intern.h b/source/blender/editors/render/render_intern.h index 50f0b53c037..88b913b84ca 100644 --- a/source/blender/editors/render/render_intern.h +++ b/source/blender/editors/render/render_intern.h @@ -24,7 +24,6 @@ #ifndef __RENDER_INTERN_H__ #define __RENDER_INTERN_H__ -struct RenderEngine; struct ScrArea; struct bContext; struct wmOperatorType; diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index 01740c13c9d..9f13431f25a 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -1836,7 +1836,7 @@ void SCENE_OT_freestyle_stroke_material_create(wmOperatorType *ot) static int texture_slot_move_exec(bContext *C, wmOperator *op) { - ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data; + ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).owner_id; if (id) { MTex **mtex_ar, *mtexswap; @@ -2031,7 +2031,7 @@ static void paste_mtex_copybuf(ID *id) static int copy_mtex_exec(bContext *C, wmOperator *UNUSED(op)) { - ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data; + ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).owner_id; if (id == NULL) { /* copying empty slot */ @@ -2046,7 +2046,7 @@ static int copy_mtex_exec(bContext *C, wmOperator *UNUSED(op)) static bool copy_mtex_poll(bContext *C) { - ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data; + ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).owner_id; return (id != NULL); } @@ -2069,7 +2069,7 @@ void TEXTURE_OT_slot_copy(wmOperatorType *ot) static int paste_mtex_exec(bContext *C, wmOperator *UNUSED(op)) { - ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data; + ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).owner_id; if (id == NULL) { Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data; diff --git a/source/blender/editors/render/render_view.c b/source/blender/editors/render/render_view.c index cd5edcdc3f4..3154d5d0985 100644 --- a/source/blender/editors/render/render_view.c +++ b/source/blender/editors/render/render_view.c @@ -223,8 +223,8 @@ ScrArea *render_view_open(bContext *C, int mx, int my, ReportList *reports) /* get the correct image, and scale it */ sima->image = BKE_image_verify_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result"); - /* if we're rendering to full screen, set appropriate hints on image editor - * so it can restore properly on pressing esc */ + /* If we're rendering to full screen, set appropriate hints on image editor + * so it can restore properly on pressing escape. */ if (sa->full) { sima->flag |= SI_FULLWINDOW; diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 1775a0c55a2..b0c9e3b9378 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -1052,16 +1052,11 @@ static void region_azones_scrollbars_initialize(ScrArea *sa, ARegion *ar) } /* *************************************************************** */ - -static void region_azones_add(const bScreen *screen, ScrArea *sa, ARegion *ar, const int alignment) +static void region_azones_add_edge(ScrArea *sa, + ARegion *ar, + const int alignment, + const bool is_fullscreen) { - const bool is_fullscreen = screen->state == SCREENFULL; - - /* Only display tab or icons when the header region is hidden - * (not the tool header - they overlap). */ - if (ar->regiontype == RGN_TYPE_TOOL_HEADER) { - return; - } /* edge code (t b l r) is along which area edge azone will be drawn */ if (alignment == RGN_ALIGN_TOP) { @@ -1076,6 +1071,25 @@ static void region_azones_add(const bScreen *screen, ScrArea *sa, ARegion *ar, c else if (alignment == RGN_ALIGN_LEFT) { region_azone_edge_initialize(sa, ar, AE_RIGHT_TO_TOPLEFT, is_fullscreen); } +} + +static void region_azones_add(const bScreen *screen, ScrArea *sa, ARegion *ar) +{ + const bool is_fullscreen = screen->state == SCREENFULL; + + /* Only display tab or icons when the header region is hidden + * (not the tool header - they overlap). */ + if (ar->regiontype == RGN_TYPE_TOOL_HEADER) { + return; + } + + region_azones_add_edge(sa, ar, RGN_ALIGN_ENUM_FROM_MASK(ar->alignment), is_fullscreen); + + /* For a split region also continue the azone edge from the next region if this region is aligned + * with the next */ + if ((ar->alignment & RGN_SPLIT_PREV) && ar->prev) { + region_azones_add_edge(sa, ar, RGN_ALIGN_ENUM_FROM_MASK(ar->prev->alignment), is_fullscreen); + } if (is_fullscreen) { fullscreen_azone_initialize(sa, ar); @@ -1251,9 +1265,6 @@ static void region_rect_recursive( else if (ED_area_is_global(sa)) { prefsizey = ED_region_global_size_y(); } - else if (ar->regiontype == RGN_TYPE_UI && sa->spacetype == SPACE_FILE) { - prefsizey = UI_UNIT_Y * 2 + (UI_UNIT_Y / 2); - } else { prefsizey = UI_DPI_FAC * (ar->sizey > 1 ? ar->sizey + 0.5f : ar->type->prefsizey); } @@ -1695,7 +1706,7 @@ void ED_area_update_region_sizes(wmWindowManager *wm, wmWindow *win, ScrArea *ar } /* Some AZones use View2D data which is only updated in region init, so call that first! */ - region_azones_add(screen, area, ar, RGN_ALIGN_ENUM_FROM_MASK(ar->alignment)); + region_azones_add(screen, area, ar); } ED_area_azones_update(area, &win->eventstate->x); @@ -1766,7 +1777,7 @@ void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa) } /* Some AZones use View2D data which is only updated in region init, so call that first! */ - region_azones_add(screen, sa, ar, RGN_ALIGN_ENUM_FROM_MASK(ar->alignment)); + region_azones_add(screen, sa, ar); } /* Avoid re-initializing tools while resizing the window. */ diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c index 2eb7f732534..6f8b25f782b 100644 --- a/source/blender/editors/screen/screen_context.c +++ b/source/blender/editors/screen/screen_context.c @@ -533,7 +533,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult gpd_ptr = ED_gpencil_data_get_pointers_direct((ID *)sc, sa, scene, obact, &ptr); if (gpd_ptr) { - CTX_data_pointer_set(result, ptr.id.data, ptr.type, ptr.data); + CTX_data_pointer_set(result, ptr.owner_id, ptr.type, ptr.data); return 1; } } diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index dddc33e3ad0..b37aa47aba6 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -292,33 +292,45 @@ void screen_new_activate_prepare(const wmWindow *win, bScreen *screen_new) /* used with join operator */ int area_getorientation(ScrArea *sa, ScrArea *sb) { - ScrVert *sav1, *sav2, *sav3, *sav4; - ScrVert *sbv1, *sbv2, *sbv3, *sbv4; - if (sa == NULL || sb == NULL) { return -1; } - sav1 = sa->v1; - sav2 = sa->v2; - sav3 = sa->v3; - sav4 = sa->v4; - sbv1 = sb->v1; - sbv2 = sb->v2; - sbv3 = sb->v3; - sbv4 = sb->v4; + ScrVert *saBL = sa->v1; + ScrVert *saTL = sa->v2; + ScrVert *saTR = sa->v3; + ScrVert *saBR = sa->v4; - if (sav1 == sbv4 && sav2 == sbv3) { /* sa to right of sb = W */ - return 0; + ScrVert *sbBL = sb->v1; + ScrVert *sbTL = sb->v2; + ScrVert *sbTR = sb->v3; + ScrVert *sbBR = sb->v4; + + int tolerance = U.pixelsize * 4; + + if (saBL->vec.x == sbBR->vec.x && saTL->vec.x == sbTR->vec.x) { /* sa to right of sb = W */ + if ((ABS(saBL->vec.y - sbBR->vec.y) <= tolerance) && + (ABS(saTL->vec.y - sbTR->vec.y) <= tolerance)) { + return 0; + } } - else if (sav2 == sbv1 && sav3 == sbv4) { /* sa to bottom of sb = N */ - return 1; + else if (saTL->vec.y == sbBL->vec.y && saTR->vec.y == sbBR->vec.y) { /* sa to bottom of sb = N */ + if ((ABS(saTL->vec.x - sbBL->vec.x) <= tolerance) && + (ABS(saTR->vec.x - sbBR->vec.x) <= tolerance)) { + return 1; + } } - else if (sav3 == sbv2 && sav4 == sbv1) { /* sa to left of sb = E */ - return 2; + else if (saTR->vec.x == sbTL->vec.x && saBR->vec.x == sbBL->vec.x) { /* sa to left of sb = E */ + if ((ABS(saTR->vec.y - sbTL->vec.y) <= tolerance) && + (ABS(saBR->vec.y - sbBL->vec.y) <= tolerance)) { + return 2; + } } - else if (sav1 == sbv2 && sav4 == sbv3) { /* sa on top of sb = S*/ - return 3; + else if (saBL->vec.y == sbTL->vec.y && saBR->vec.y == sbTR->vec.y) { /* sa on top of sb = S*/ + if ((ABS(saBL->vec.x - sbTL->vec.x) <= tolerance) && + (ABS(saBR->vec.x - sbTR->vec.x) <= tolerance)) { + return 3; + } } return -1; @@ -329,36 +341,50 @@ int area_getorientation(ScrArea *sa, ScrArea *sb) */ int screen_area_join(bContext *C, bScreen *scr, ScrArea *sa1, ScrArea *sa2) { - int dir; - - dir = area_getorientation(sa1, sa2); - /*printf("dir is : %i\n", dir);*/ + int dir = area_getorientation(sa1, sa2); if (dir == -1) { return 0; } - if (dir == 0) { - sa1->v1 = sa2->v1; - sa1->v2 = sa2->v2; + /* Align areas if they are not. Do sanity checking before getting here. */ + + if (dir == 0 || dir == 2) { + /* horizontal join, so vertically align source vert to target */ + sa2->v1->vec.y = sa1->v1->vec.y; /* vertical align sa1 BL */ + sa2->v2->vec.y = sa1->v2->vec.y; /* vertical align sa1 TL */ + sa2->v3->vec.y = sa1->v3->vec.y; /* vertical align sa1 TR */ + sa2->v4->vec.y = sa1->v4->vec.y; /* vertical align sa1 BR */ + } + else { + /* vertical join, so horizontally align source verts to target */ + sa2->v1->vec.x = sa1->v1->vec.x; /* vertical align sa1 BL */ + sa2->v2->vec.x = sa1->v2->vec.x; /* vertical align sa1 TL */ + sa2->v3->vec.x = sa1->v3->vec.x; /* vertical align sa1 TR */ + sa2->v4->vec.x = sa1->v4->vec.x; /* vertical align sa1 BR */ + } + + if (dir == 0) { /* sa1 to right of sa2 = W */ + sa1->v1 = sa2->v1; /* BL */ + sa1->v2 = sa2->v2; /* TL */ screen_geom_edge_add(scr, sa1->v2, sa1->v3); screen_geom_edge_add(scr, sa1->v1, sa1->v4); } - else if (dir == 1) { - sa1->v2 = sa2->v2; - sa1->v3 = sa2->v3; + else if (dir == 1) { /* sa1 to bottom of sa2 = N */ + sa1->v2 = sa2->v2; /* TL */ + sa1->v3 = sa2->v3; /* TR */ screen_geom_edge_add(scr, sa1->v1, sa1->v2); screen_geom_edge_add(scr, sa1->v3, sa1->v4); } - else if (dir == 2) { - sa1->v3 = sa2->v3; - sa1->v4 = sa2->v4; + else if (dir == 2) { /* sa1 to left of sa2 = E */ + sa1->v3 = sa2->v3; /* TR */ + sa1->v4 = sa2->v4; /* BR */ screen_geom_edge_add(scr, sa1->v2, sa1->v3); screen_geom_edge_add(scr, sa1->v1, sa1->v4); } - else if (dir == 3) { - sa1->v1 = sa2->v1; - sa1->v4 = sa2->v4; + else if (dir == 3) { /* sa1 on top of sa2 = S */ + sa1->v1 = sa2->v1; /* BL */ + sa1->v4 = sa2->v4; /* BR */ screen_geom_edge_add(scr, sa1->v1, sa1->v2); screen_geom_edge_add(scr, sa1->v3, sa1->v4); } @@ -1116,7 +1142,7 @@ void ED_screen_full_prevspace(bContext *C, ScrArea *sa) void ED_screen_restore_temp_type(bContext *C, ScrArea *sa) { - /* incase nether functions below run */ + /* In case nether functions below run. */ ED_area_tag_redraw(sa); if (sa->flag & AREA_FLAG_TEMP_TYPE) { diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 8377fd0e128..50e5597ac0c 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -1121,6 +1121,47 @@ static void SCREEN_OT_actionzone(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ +/** \name Area edge detection utility + * \{ */ + +static ScrEdge *screen_area_edge_from_cursor(const bContext *C, + const int cursor[2], + ScrArea **r_sa1, + ScrArea **r_sa2) +{ + wmWindow *win = CTX_wm_window(C); + bScreen *sc = CTX_wm_screen(C); + ScrEdge *actedge; + rcti window_rect; + WM_window_rect_calc(win, &window_rect); + actedge = screen_geom_area_map_find_active_scredge( + AREAMAP_FROM_SCREEN(sc), &window_rect, cursor[0], cursor[1]); + *r_sa1 = NULL; + *r_sa2 = NULL; + if (actedge == NULL) { + return NULL; + } + int borderwidth = (4 * UI_DPI_FAC); + ScrArea *sa1, *sa2; + if (screen_geom_edge_is_horizontal(actedge)) { + sa1 = BKE_screen_find_area_xy(sc, SPACE_TYPE_ANY, cursor[0], cursor[1] + borderwidth); + sa2 = BKE_screen_find_area_xy(sc, SPACE_TYPE_ANY, cursor[0], cursor[1] - borderwidth); + } + else { + sa1 = BKE_screen_find_area_xy(sc, SPACE_TYPE_ANY, cursor[0] + borderwidth, cursor[1]); + sa2 = BKE_screen_find_area_xy(sc, SPACE_TYPE_ANY, cursor[0] - borderwidth, cursor[1]); + } + bool isGlobal = ((sa1 && ED_area_is_global(sa1)) || (sa2 && ED_area_is_global(sa2))); + if (!isGlobal) { + *r_sa1 = sa1; + *r_sa2 = sa2; + } + return actedge; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Swap Area Operator * \{ */ @@ -1139,6 +1180,7 @@ static void SCREEN_OT_actionzone(wmOperatorType *ot) * callbacks: * * invoke() gets called on shift+lmb drag in action-zone + * exec() execute without any user interaction, based on properties * call init(), add handler * * modal() accept modal events while doing it @@ -1229,6 +1271,19 @@ static int area_swap_modal(bContext *C, wmOperator *op, const wmEvent *event) return OPERATOR_RUNNING_MODAL; } +static int area_swap_exec(bContext *C, wmOperator *op) +{ + ScrArea *sa1, *sa2; + int cursor[2]; + RNA_int_get_array(op->ptr, "cursor", cursor); + screen_area_edge_from_cursor(C, cursor, &sa1, &sa2); + if (sa1 == NULL || sa2 == NULL) { + return OPERATOR_CANCELLED; + } + ED_area_swapspace(C, sa1, sa2); + return OPERATOR_FINISHED; +} + static void SCREEN_OT_area_swap(wmOperatorType *ot) { ot->name = "Swap Areas"; @@ -1237,10 +1292,15 @@ static void SCREEN_OT_area_swap(wmOperatorType *ot) ot->invoke = area_swap_invoke; ot->modal = area_swap_modal; - ot->poll = ED_operator_areaactive; + ot->exec = area_swap_exec; + ot->poll = screen_active_editable; ot->cancel = area_swap_cancel; ot->flag = OPTYPE_BLOCKING; + + /* rna */ + RNA_def_int_vector( + ot->srna, "cursor", 2, NULL, INT_MIN, INT_MAX, "Cursor", "", INT_MIN, INT_MAX); } /** \} */ @@ -2458,6 +2518,14 @@ static int area_max_regionsize(ScrArea *sa, ARegion *scalear, AZEdge edge) return dist; } +static bool is_split_edge(const int alignment, const AZEdge edge) +{ + return ((alignment == RGN_ALIGN_BOTTOM) && (edge == AE_TOP_TO_BOTTOMRIGHT)) || + ((alignment == RGN_ALIGN_TOP) && (edge == AE_BOTTOM_TO_TOPLEFT)) || + ((alignment == RGN_ALIGN_LEFT) && (edge == AE_RIGHT_TO_TOPLEFT)) || + ((alignment == RGN_ALIGN_RIGHT) && (edge == AE_LEFT_TO_TOPRIGHT)); +} + static int region_scale_invoke(bContext *C, wmOperator *op, const wmEvent *event) { sActionzoneData *sad = event->customdata; @@ -2476,7 +2544,16 @@ static int region_scale_invoke(bContext *C, wmOperator *op, const wmEvent *event op->customdata = rmd; rmd->az = az; - rmd->ar = az->ar; + /* special case for region within region - this allows the scale of + * the parent region if the azone edge is not the edge splitting + * both regions */ + if ((az->ar->alignment & RGN_SPLIT_PREV) && az->ar->prev && + !is_split_edge(RGN_ALIGN_ENUM_FROM_MASK(az->ar->alignment), az->edge)) { + rmd->ar = az->ar->prev; + } + else { + rmd->ar = az->ar; + } rmd->sa = sad->sa1; rmd->edge = az->edge; rmd->origx = event->x; @@ -3163,40 +3240,19 @@ static void area_join_draw_cb(const struct wmWindow *UNUSED(win), void *userdata /* validate selection inside screen, set variables OK */ /* return 0: init failed */ -/* XXX todo: find edge based on (x,y) and set other area? */ -static int area_join_init(bContext *C, wmOperator *op) +static int area_join_init(bContext *C, wmOperator *op, ScrArea *sa1, ScrArea *sa2) { - const wmWindow *win = CTX_wm_window(C); - bScreen *screen = CTX_wm_screen(C); - ScrArea *sa1, *sa2; - sAreaJoinData *jd = NULL; - int x1, y1; - int x2, y2; - - /* required properties, make negative to get return 0 if not set by caller */ - x1 = RNA_int_get(op->ptr, "min_x"); - y1 = RNA_int_get(op->ptr, "min_y"); - x2 = RNA_int_get(op->ptr, "max_x"); - y2 = RNA_int_get(op->ptr, "max_y"); - - sa1 = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, x1, y1); - if (sa1 == NULL) { - sa1 = BKE_screen_area_map_find_area_xy(&win->global_areas, SPACE_TYPE_ANY, x1, y1); - } - sa2 = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, x2, y2); - if (sa2 == NULL) { - sa2 = BKE_screen_area_map_find_area_xy(&win->global_areas, SPACE_TYPE_ANY, x2, y2); - } - if ((sa1 && ED_area_is_global(sa1)) || (sa2 && ED_area_is_global(sa2))) { - BKE_report( - op->reports, RPT_ERROR, "Global areas (Top Bar, Status Bar) do not support joining"); - return 0; + if (sa1 == NULL || sa2 == NULL) { + /* Get areas from cursor location if not specified. */ + int cursor[2]; + RNA_int_get_array(op->ptr, "cursor", cursor); + screen_area_edge_from_cursor(C, cursor, &sa1, &sa2); } - else if (sa1 == NULL || sa2 == NULL || sa1 == sa2) { + if (sa1 == NULL || sa2 == NULL) { return 0; } - jd = (sAreaJoinData *)MEM_callocN(sizeof(sAreaJoinData), "op_area_join"); + sAreaJoinData *jd = MEM_callocN(sizeof(sAreaJoinData), "op_area_join"); jd->sa1 = sa1; jd->sa2 = sa2; @@ -3249,7 +3305,7 @@ static void area_join_exit(bContext *C, wmOperator *op) static int area_join_exec(bContext *C, wmOperator *op) { - if (!area_join_init(C, op)) { + if (!area_join_init(C, op, NULL, NULL)) { return OPERATOR_CANCELLED; } @@ -3279,16 +3335,11 @@ static int area_join_invoke(bContext *C, wmOperator *op, const wmEvent *event) if (sad->sa1 == sad->sa2) { return OPERATOR_PASS_THROUGH; } - - /* prepare operator state vars */ - RNA_int_set(op->ptr, "min_x", sad->sa1->totrct.xmin); - RNA_int_set(op->ptr, "min_y", sad->sa1->totrct.ymin); - RNA_int_set(op->ptr, "max_x", sad->sa2->totrct.xmin); - RNA_int_set(op->ptr, "max_y", sad->sa2->totrct.ymin); - } - - if (!area_join_init(C, op)) { - return OPERATOR_CANCELLED; + else { + if (!area_join_init(C, op, sad->sa1, sad->sa2)) { + return OPERATOR_CANCELLED; + } + } } /* add temp handler */ @@ -3309,7 +3360,14 @@ static int area_join_modal(bContext *C, wmOperator *op, const wmEvent *event) { bScreen *sc = CTX_wm_screen(C); wmWindow *win = CTX_wm_window(C); - sAreaJoinData *jd = (sAreaJoinData *)op->customdata; + sAreaJoinData *jd; + + if (op->customdata == NULL) { + if (!area_join_init(C, op, NULL, NULL)) { + return OPERATOR_CANCELLED; + } + } + jd = (sAreaJoinData *)op->customdata; /* execute the events */ switch (event->type) { @@ -3419,10 +3477,8 @@ static void SCREEN_OT_area_join(wmOperatorType *ot) ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL; /* rna */ - RNA_def_int(ot->srna, "min_x", -100, INT_MIN, INT_MAX, "X 1", "", INT_MIN, INT_MAX); - RNA_def_int(ot->srna, "min_y", -100, INT_MIN, INT_MAX, "Y 1", "", INT_MIN, INT_MAX); - RNA_def_int(ot->srna, "max_x", -100, INT_MIN, INT_MAX, "X 2", "", INT_MIN, INT_MAX); - RNA_def_int(ot->srna, "max_y", -100, INT_MIN, INT_MAX, "Y 2", "", INT_MIN, INT_MAX); + RNA_def_int_vector( + ot->srna, "cursor", 2, NULL, INT_MIN, INT_MAX, "Cursor", "", INT_MIN, INT_MAX); } /** \} */ @@ -3433,36 +3489,74 @@ static void SCREEN_OT_area_join(wmOperatorType *ot) static int screen_area_options_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - const wmWindow *win = CTX_wm_window(C); - const bScreen *sc = CTX_wm_screen(C); uiPopupMenu *pup; uiLayout *layout; PointerRNA ptr; - ScrEdge *actedge; - rcti window_rect; - WM_window_rect_calc(win, &window_rect); - actedge = screen_geom_area_map_find_active_scredge( - AREAMAP_FROM_SCREEN(sc), &window_rect, event->x, event->y); + ScrArea *sa1, *sa2; - if (actedge == NULL) { + if (screen_area_edge_from_cursor(C, &event->x, &sa1, &sa2) == NULL) { return OPERATOR_CANCELLED; } pup = UI_popup_menu_begin(C, WM_operatortype_name(op->type, op->ptr), ICON_NONE); layout = UI_popup_menu_layout(pup); - uiItemFullO( - layout, "SCREEN_OT_area_split", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, &ptr); - /* store initial mouse cursor position */ + /* Vertical Split */ + uiItemFullO(layout, + "SCREEN_OT_area_split", + IFACE_("Vertical Split"), + ICON_NONE, + NULL, + WM_OP_INVOKE_DEFAULT, + 0, + &ptr); + /* store initial mouse cursor position. */ + RNA_int_set_array(&ptr, "cursor", &event->x); + RNA_enum_set(&ptr, "direction", 'v'); + + /* Horizontal Split */ + uiItemFullO(layout, + "SCREEN_OT_area_split", + IFACE_("Horizontal Split"), + ICON_NONE, + NULL, + WM_OP_INVOKE_DEFAULT, + 0, + &ptr); + /* store initial mouse cursor position. */ RNA_int_set_array(&ptr, "cursor", &event->x); + RNA_enum_set(&ptr, "direction", 'h'); - uiItemFullO(layout, "SCREEN_OT_area_join", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, &ptr); - /* mouse cursor on edge, '4' can fail on wide edges... */ - RNA_int_set(&ptr, "min_x", event->x + 4); - RNA_int_set(&ptr, "min_y", event->y + 4); - RNA_int_set(&ptr, "max_x", event->x - 4); - RNA_int_set(&ptr, "max_y", event->y - 4); + if (sa1 && sa2) { + uiItemS(layout); + } + + /* Join needs two very similar areas. */ + if (sa1 && sa2 && (area_getorientation(sa1, sa2) != -1)) { + uiItemFullO(layout, + "SCREEN_OT_area_join", + IFACE_("Join Areas"), + ICON_NONE, + NULL, + WM_OP_INVOKE_DEFAULT, + 0, + &ptr); + RNA_int_set_array(&ptr, "cursor", &event->x); + } + + /* Swap just needs two areas. */ + if (sa1 && sa2) { + uiItemFullO(layout, + "SCREEN_OT_area_swap", + IFACE_("Swap Areas"), + ICON_NONE, + NULL, + WM_OP_EXEC_DEFAULT, + 0, + &ptr); + RNA_int_set_array(&ptr, "cursor", &event->x); + } UI_popup_menu_end(C, pup); @@ -3660,7 +3754,7 @@ static void SCREEN_OT_redo_last(wmOperatorType *ot) { /* identifiers */ ot->name = "Redo Last"; - ot->description = "Display menu for last action performed"; + ot->description = "Display parameters for last action performed"; ot->idname = "SCREEN_OT_redo_last"; /* api callbacks */ @@ -3711,7 +3805,7 @@ static int region_quadview_exec(bContext *C, wmOperator *op) /* some rules... */ if (ar->regiontype != RGN_TYPE_WINDOW) { - BKE_report(op->reports, RPT_ERROR, "Only window region can be 4-splitted"); + BKE_report(op->reports, RPT_ERROR, "Only window region can be 4-split"); } else if (ar->alignment == RGN_ALIGN_QSPLIT) { /* Exit quad-view */ @@ -3742,7 +3836,7 @@ static int region_quadview_exec(bContext *C, wmOperator *op) rv3d->viewlock = 0; rv3d->rflag &= ~RV3D_CLIPPING; - /* accumulate locks, incase they're mixed */ + /* Accumulate locks, in case they're mixed. */ for (ar_iter = sa->regionbase.first; ar_iter; ar_iter = ar_iter->next) { if (ar_iter->regiontype == RGN_TYPE_WINDOW) { RegionView3D *rv3d_iter = ar_iter->regiondata; @@ -3764,7 +3858,7 @@ static int region_quadview_exec(bContext *C, wmOperator *op) WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); } else if (ar->next) { - BKE_report(op->reports, RPT_ERROR, "Only last region can be 4-splitted"); + BKE_report(op->reports, RPT_ERROR, "Only last region can be 4-split"); } else { /* Enter quad-view */ @@ -3842,6 +3936,65 @@ static void SCREEN_OT_region_quadview(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ +/** \name Region Toggle Operator + * \{ */ + +static int region_toggle_exec(bContext *C, wmOperator *op) +{ + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "region_type"); + ARegion *region; + + if (RNA_property_is_set(op->ptr, prop)) { + region = BKE_area_find_region_type(CTX_wm_area(C), RNA_property_enum_get(op->ptr, prop)); + } + else { + region = CTX_wm_region(C); + } + + if (region) { + ED_region_toggle_hidden(C, region); + } + ED_region_tag_redraw(region); + + return OPERATOR_FINISHED; +} + +static bool region_toggle_poll(bContext *C) +{ + ScrArea *area = CTX_wm_area(C); + + /* don't flip anything around in topbar */ + if (area && area->spacetype == SPACE_TOPBAR) { + CTX_wm_operator_poll_msg_set(C, "Toggling regions in the Top-bar is not allowed"); + return 0; + } + + return ED_operator_areaactive(C); +} + +static void SCREEN_OT_region_toggle(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Toggle Region"; + ot->idname = "SCREEN_OT_region_toggle"; + ot->description = "Hide or unhide the region"; + + /* api callbacks */ + ot->exec = region_toggle_exec; + ot->poll = region_toggle_poll; + ot->flag = 0; + + RNA_def_enum(ot->srna, + "region_type", + rna_enum_region_type_items, + 0, + "Region Type", + "Type of the region to toggle"); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Region Flip Operator * \{ */ @@ -4714,7 +4867,7 @@ static void SCREEN_OT_userpref_show(struct wmOperatorType *ot) static int drivers_editor_show_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - PointerRNA ptr = {{NULL}}; + PointerRNA ptr = {NULL}; PropertyRNA *prop = NULL; int index = -1; uiBut *but = NULL; @@ -4775,6 +4928,40 @@ static void SCREEN_OT_drivers_editor_show(struct wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ +/** \name Show Info Log Operator + * \{ */ + +static int info_log_show_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + int sizex = 900 * UI_DPI_FAC; + int sizey = 580 * UI_DPI_FAC; + int shift_y = 480; + + /* changes context! */ + if (WM_window_open_temp(C, event->x, event->y + shift_y, sizex, sizey, WM_WINDOW_INFO) != NULL) { + return OPERATOR_FINISHED; + } + else { + BKE_report(op->reports, RPT_ERROR, "Failed to open window!"); + return OPERATOR_CANCELLED; + } +} + +static void SCREEN_OT_info_log_show(struct wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Show Info Log"; + ot->description = "Show info log in a separate window"; + ot->idname = "SCREEN_OT_info_log_show"; + + /* api callbacks */ + ot->invoke = info_log_show_invoke; + ot->poll = ED_operator_screenactive; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name New Screen Operator * \{ */ @@ -4903,7 +5090,9 @@ static void region_blend_end(bContext *C, ARegion *ar, const bool is_running) WM_event_remove_timer(CTX_wm_manager(C), NULL, ar->regiontimer); /* frees rgi */ ar->regiontimer = NULL; } -/* assumes that *ar itself is not a splitted version from previous region */ +/** + * \note Assumes that \a ar itself is not a split version from previous region. + */ void ED_region_visibility_change_update_animated(bContext *C, ScrArea *sa, ARegion *ar) { wmWindowManager *wm = CTX_wm_manager(C); @@ -5231,6 +5420,7 @@ void ED_operatortypes_screen(void) WM_operatortype_append(SCREEN_OT_area_swap); WM_operatortype_append(SCREEN_OT_region_quadview); WM_operatortype_append(SCREEN_OT_region_scale); + WM_operatortype_append(SCREEN_OT_region_toggle); WM_operatortype_append(SCREEN_OT_region_flip); WM_operatortype_append(SCREEN_OT_header_toggle_menus); WM_operatortype_append(SCREEN_OT_region_context_menu); @@ -5241,6 +5431,7 @@ void ED_operatortypes_screen(void) WM_operatortype_append(SCREEN_OT_screenshot); WM_operatortype_append(SCREEN_OT_userpref_show); WM_operatortype_append(SCREEN_OT_drivers_editor_show); + WM_operatortype_append(SCREEN_OT_info_log_show); WM_operatortype_append(SCREEN_OT_region_blend); WM_operatortype_append(SCREEN_OT_space_type_set_or_cycle); WM_operatortype_append(SCREEN_OT_space_context_cycle); diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c index 65e10f98753..4a552fb3744 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.c +++ b/source/blender/editors/sculpt_paint/paint_cursor.c @@ -45,13 +45,17 @@ #include "BKE_node.h" #include "BKE_paint.h" #include "BKE_colortools.h" +#include "BKE_object.h" #include "WM_api.h" +#include "wm_cursors.h" #include "IMB_imbuf_types.h" #include "ED_view3d.h" +#include "DEG_depsgraph.h" + #include "GPU_draw.h" #include "GPU_immediate.h" #include "GPU_immediate_util.h" @@ -602,7 +606,7 @@ static bool sculpt_get_brush_geometry(bContext *C, /* Draw an overlay that shows what effect the brush's texture will * have on brush strength */ -static void paint_draw_tex_overlay(UnifiedPaintSettings *ups, +static bool paint_draw_tex_overlay(UnifiedPaintSettings *ups, Brush *brush, ViewContext *vc, int x, @@ -622,7 +626,7 @@ static void paint_draw_tex_overlay(UnifiedPaintSettings *ups, if (!(mtex->tex) || !((mtex->brush_map_mode == MTEX_MAP_MODE_STENCIL) || (valid && ELEM(mtex->brush_map_mode, MTEX_MAP_MODE_VIEW, MTEX_MAP_MODE_TILED)))) { - return; + return false; } if (load_tex(brush, vc, zoom, col, primary)) { @@ -728,18 +732,19 @@ static void paint_draw_tex_overlay(UnifiedPaintSettings *ups, GPU_matrix_pop(); } } + return true; } /* Draw an overlay that shows what effect the brush's texture will * have on brush strength */ -static void paint_draw_cursor_overlay( +static bool paint_draw_cursor_overlay( UnifiedPaintSettings *ups, Brush *brush, ViewContext *vc, int x, int y, float zoom) { rctf quad; /* check for overlay mode */ if (!(brush->overlay_flags & BRUSH_OVERLAY_CURSOR)) { - return; + return false; } if (load_tex_cursor(brush, vc, zoom)) { @@ -811,9 +816,10 @@ static void paint_draw_cursor_overlay( GPU_matrix_pop(); } } + return true; } -static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, +static bool paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush, ViewContext *vc, int x, @@ -824,6 +830,9 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, /* Color means that primary brush texture is colored and * secondary is used for alpha/mask control. */ bool col = ELEM(mode, PAINT_MODE_TEXTURE_3D, PAINT_MODE_TEXTURE_2D, PAINT_MODE_VERTEX); + + bool alpha_overlay_active = false; + eOverlayControlFlags flags = BKE_paint_get_overlay_flags(); gpuPushAttr(GPU_DEPTH_BUFFER_BIT | GPU_BLEND_BIT); @@ -836,26 +845,28 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, /* Colored overlay should be drawn separately. */ if (col) { if (!(flags & PAINT_OVERLAY_OVERRIDE_PRIMARY)) { - paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, true, true); + alpha_overlay_active = paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, true, true); } if (!(flags & PAINT_OVERLAY_OVERRIDE_SECONDARY)) { - paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, false, false); + alpha_overlay_active = paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, false, false); } if (!(flags & PAINT_OVERLAY_OVERRIDE_CURSOR)) { - paint_draw_cursor_overlay(ups, brush, vc, x, y, zoom); + alpha_overlay_active = paint_draw_cursor_overlay(ups, brush, vc, x, y, zoom); } } else { if (!(flags & PAINT_OVERLAY_OVERRIDE_PRIMARY) && (mode != PAINT_MODE_WEIGHT)) { - paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, false, true); + alpha_overlay_active = paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, false, true); } if (!(flags & PAINT_OVERLAY_OVERRIDE_CURSOR)) { - paint_draw_cursor_overlay(ups, brush, vc, x, y, zoom); + alpha_overlay_active = paint_draw_cursor_overlay(ups, brush, vc, x, y, zoom); } } GPU_matrix_pop(); gpuPopAttr(); + + return alpha_overlay_active; } BLI_INLINE void draw_tri_point( @@ -1074,6 +1085,98 @@ static bool ommit_cursor_drawing(Paint *paint, ePaintMode mode, Brush *brush) return true; } +static void cursor_draw_point_screen_space(const uint gpuattr, + const ARegion *ar, + float true_location[3], + float obmat[4][4]) +{ + float translation_vertex_cursor[3], location[3]; + copy_v3_v3(location, true_location); + mul_m4_v3(obmat, location); + ED_view3d_project(ar, location, translation_vertex_cursor); + imm_draw_circle_fill_3d( + gpuattr, translation_vertex_cursor[0], translation_vertex_cursor[1], 3, 10); +} + +static void cursor_draw_tiling_preview(const uint gpuattr, + const ARegion *ar, + float true_location[3], + Sculpt *sd, + Object *ob, + float radius) +{ + BoundBox *bb = BKE_object_boundbox_get(ob); + float orgLoc[3], location[3]; + int dim, tile_pass = 0; + int start[3]; + int end[3]; + int cur[3]; + const float *bbMin = bb->vec[0]; + const float *bbMax = bb->vec[6]; + const float *step = sd->paint.tile_offset; + + copy_v3_v3(orgLoc, true_location); + for (dim = 0; dim < 3; ++dim) { + if ((sd->paint.symmetry_flags & (PAINT_TILE_X << dim)) && step[dim] > 0) { + start[dim] = (bbMin[dim] - orgLoc[dim] - radius) / step[dim]; + end[dim] = (bbMax[dim] - orgLoc[dim] + radius) / step[dim]; + } + else + start[dim] = end[dim] = 0; + } + copy_v3_v3_int(cur, start); + for (cur[0] = start[0]; cur[0] <= end[0]; cur[0]++) { + for (cur[1] = start[1]; cur[1] <= end[1]; cur[1]++) { + for (cur[2] = start[2]; cur[2] <= end[2]; cur[2]++) { + if (!cur[0] && !cur[1] && !cur[2]) + continue; /* skip tile at orgLoc, this was already handled before all others */ + tile_pass++; + for (dim = 0; dim < 3; dim++) { + location[dim] = cur[dim] * step[dim] + orgLoc[dim]; + } + cursor_draw_point_screen_space(gpuattr, ar, location, ob->obmat); + } + } + } +} + +static void cursor_draw_point_with_symmetry(const uint gpuattr, + const ARegion *ar, + const float true_location[3], + Sculpt *sd, + Object *ob, + float radius) +{ + const char symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL; + float location[3], symm_rot_mat[4][4]; + + for (int i = 0; i <= symm; ++i) { + if (i == 0 || (symm & i && (symm != 5 || i != 3) && (symm != 6 || (i != 3 && i != 5)))) { + + /* Axis Symmetry */ + flip_v3_v3(location, true_location, (char)i); + cursor_draw_point_screen_space(gpuattr, ar, location, ob->obmat); + + /* Tiling */ + cursor_draw_tiling_preview(gpuattr, ar, location, sd, ob, radius); + + /* Radial Symmetry */ + for (char raxis = 0; raxis < 3; raxis++) { + for (int r = 1; r < sd->radial_symm[raxis]; r++) { + float angle = 2 * M_PI * r / sd->radial_symm[(int)raxis]; + flip_v3_v3(location, true_location, (char)i); + unit_m4(symm_rot_mat); + rotate_m4(symm_rot_mat, raxis + 'X', angle); + mul_m4_v3(symm_rot_mat, location); + + cursor_draw_tiling_preview(gpuattr, ar, location, sd, ob, radius); + cursor_draw_point_screen_space(gpuattr, ar, location, ob->obmat); + } + } + } + } +} + static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) { Scene *scene = CTX_data_scene(C); @@ -1121,7 +1224,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) } /* draw overlay */ - paint_draw_alpha_overlay(ups, brush, &vc, x, y, zoomx, mode); + bool alpha_overlay_active = paint_draw_alpha_overlay(ups, brush, &vc, x, y, zoomx, mode); /* TODO: as sculpt and other paint modes are unified, this * special mode of drawing will go away */ @@ -1158,12 +1261,12 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) } /* make lines pretty */ - GPU_line_width(1.0f); + GPU_line_width(2.0f); GPU_blend(true); /* TODO: also set blend mode? */ GPU_line_smooth(true); - uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* set brush color */ immUniformColor3fvAlpha(outline_col, outline_alpha); @@ -1176,7 +1279,103 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) /* outer at half alpha */ immUniformColor3fvAlpha(outline_col, outline_alpha * 0.5f); } - imm_draw_circle_wire_2d(pos, translation[0], translation[1], final_radius, 40); + + /* Only sculpt mode cursor for now */ + + /* Disable for PBVH_GRIDS */ + SculptSession *ss = vc.obact->sculpt; + bool is_multires = ss && ss->pbvh && BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS; + + if ((mode == PAINT_MODE_SCULPT) && ss && !is_multires && + !(brush->falloff_shape & BRUSH_AIRBRUSH)) { + Sculpt *sd = CTX_data_tool_settings(C)->sculpt; + wmWindow *win = CTX_wm_window(C); + + /* Update WM mouse cursor, disable when the 3D brush cursor is enabled */ + if (sd->paint.brush->overlay_flags & BRUSH_OVERLAY_CURSOR) { + WM_cursor_set(win, CURSOR_STD); + } + else { + WM_cursor_set(win, CURSOR_EDIT); + } + + if (!ups->stroke_active) { + SculptCursorGeometryInfo gi; + float mouse[2] = {x - ar->winrct.xmin, y - ar->winrct.ymin}; + if (sculpt_cursor_geometry_info_update(C, &gi, mouse, true) && !alpha_overlay_active) { + + float rds; + if (!BKE_brush_use_locked_size(scene, brush)) { + rds = paint_calc_object_space_radius(&vc, gi.location, BKE_brush_size_get(scene, brush)); + } + else { + rds = BKE_brush_unprojected_radius_get(scene, brush); + } + + wmViewport(&ar->winrct); + + /* Draw 3D active vertex preview with symmetry*/ + if (len_v3v3(gi.active_vertex_co, gi.location) < rds) { + cursor_draw_point_with_symmetry(pos, ar, gi.active_vertex_co, sd, vc.obact, rds); + } + + /* Draw 3D brush cursor */ + GPU_matrix_push_projection(); + ED_view3d_draw_setup_view(CTX_wm_window(C), + CTX_data_depsgraph_pointer(C), + CTX_data_scene(C), + ar, + CTX_wm_view3d(C), + NULL, + NULL, + NULL); + + float cursor_trans[4][4], cursor_rot[4][4]; + float z_axis[4] = {0.0f, 0.0f, 1.0f, 0.0f}; + float quat[4]; + + copy_m4_m4(cursor_trans, vc.obact->obmat); + translate_m4(cursor_trans, gi.location[0], gi.location[1], gi.location[2]); + rotation_between_vecs_to_quat(quat, z_axis, gi.normal); + quat_to_mat4(cursor_rot, quat); + + GPU_matrix_push(); + GPU_matrix_mul(cursor_trans); + GPU_matrix_mul(cursor_rot); + imm_draw_circle_wire_3d(pos, 0, 0, rds, 40); + GPU_matrix_pop(); + + GPU_matrix_pop_projection(); + + wmWindowViewport(win); + } + else { + /* Draw default cursor when the mouse is not over the mesh or there are no supported + * overlays active */ + GPU_line_width(1.0f); + imm_draw_circle_wire_3d(pos, translation[0], translation[1], final_radius, 40); + } + } + else { + if (vc.obact->sculpt->cache && !vc.obact->sculpt->cache->first_time) { + /* Draw cursor location preview when the stroke is active using the data from StrokeCache + */ + float cursor_location[3]; + wmViewport(&ar->winrct); + copy_v3_v3(cursor_location, ss->cache->true_location); + if (ss->cache->brush->sculpt_tool == SCULPT_TOOL_GRAB) { + add_v3_v3(cursor_location, ss->cache->grab_delta); + } + cursor_draw_point_with_symmetry(pos, ar, cursor_location, sd, vc.obact, ss->cache->radius); + wmWindowViewport(win); + } + } + } + else { + /* Draw default cursor in unsupported modes */ + GPU_line_width(1.0f); + imm_draw_circle_wire_3d(pos, translation[0], translation[1], final_radius, 40); + } immUnbindProgram(); diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 342d0b6e820..397b2981ace 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -1719,9 +1719,9 @@ static float project_paint_uvpixel_mask(const ProjPaintState *ps, normalize_v3(no); } else { - /* incase the */ #if 1 - /* normalizing per pixel isn't optimal, we could cache or check ps->*/ + /* In case the normalizing per pixel isn't optimal, + * we could cache or access from evaluated mesh. */ normal_tri_v3(no, ps->mvert_eval[lt_vtri[0]].co, ps->mvert_eval[lt_vtri[1]].co, diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h index ea4814857ba..5efedf69fe4 100644 --- a/source/blender/editors/sculpt_paint/paint_intern.h +++ b/source/blender/editors/sculpt_paint/paint_intern.h @@ -33,7 +33,6 @@ struct ListBase; struct MTex; struct Object; struct Paint; -struct PaintCurve; struct PaintStroke; struct PointerRNA; struct RegionView3D; diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 694dae49d30..b4b1ae3b0af 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -57,6 +57,7 @@ #include "IMB_imbuf_types.h" #include "paint_intern.h" +#include "sculpt_intern.h" #include <float.h> #include <math.h> @@ -93,6 +94,8 @@ typedef struct PaintStroke { int cur_sample; float last_mouse_position[2]; + float last_scene_space_position[3]; + bool stroke_over_mesh; /* space distance covered so far */ float stroke_distance; @@ -233,6 +236,17 @@ static bool paint_tool_require_location(Brush *brush, ePaintMode mode) return true; } +static bool paint_stroke_use_scene_spacing(Brush *brush, ePaintMode mode) +{ + switch (mode) { + case PAINT_MODE_SCULPT: + return brush->flag & BRUSH_SCENE_SPACING; + default: + break; + } + return false; +} + static bool paint_tool_require_inbetween_mouse_events(Brush *brush, ePaintMode mode) { switch (mode) { @@ -523,6 +537,10 @@ static void paint_brush_stroke_add_step(bContext *C, copy_v2_v2(stroke->last_mouse_position, mouse_in); stroke->last_pressure = pressure; + if (paint_stroke_use_scene_spacing(brush, mode)) { + sculpt_stroke_get_location(C, stroke->last_scene_space_position, stroke->last_mouse_position); + } + if (paint_stroke_use_jitter(mode, brush, stroke->stroke_mode == BRUSH_STROKE_INVERT)) { float delta[2]; float factor = stroke->zoom_2d; @@ -600,14 +618,32 @@ static bool paint_smooth_stroke(PaintStroke *stroke, return true; } -static float paint_space_stroke_spacing(const Scene *scene, +static float paint_space_stroke_spacing(bContext *C, + const Scene *scene, PaintStroke *stroke, float size_pressure, float spacing_pressure) { - /* brushes can have a minimum size of 1.0 but with pressure it can be smaller then a pixel - * causing very high step sizes, hanging blender [#32381] */ - const float size_clamp = max_ff(1.0f, BKE_brush_size_get(scene, stroke->brush) * size_pressure); + Paint *paint = BKE_paint_get_active_from_context(C); + ePaintMode mode = BKE_paintmode_get_active_from_context(C); + Brush *brush = BKE_paint_brush(paint); + float size_clamp = 0.0f; + float size = BKE_brush_size_get(scene, stroke->brush) * size_pressure; + if (paint_stroke_use_scene_spacing(brush, mode)) { + if (!BKE_brush_use_locked_size(scene, brush)) { + size_clamp = paint_calc_object_space_radius( + &stroke->vc, stroke->last_scene_space_position, size); + } + else { + size_clamp = BKE_brush_unprojected_radius_get(scene, brush) * size_pressure; + } + } + else { + /* brushes can have a minimum size of 1.0 but with pressure it can be smaller then a pixel + * causing very high step sizes, hanging blender [#32381] */ + size_clamp = max_ff(1.0f, size); + } + float spacing = stroke->brush->spacing; /* apply spacing pressure */ @@ -619,7 +655,12 @@ static float paint_space_stroke_spacing(const Scene *scene, * the fact that brush can be scaled there. */ spacing *= stroke->zoom_2d; - return max_ff(1.0, size_clamp * spacing / 50.0f); + if (paint_stroke_use_scene_spacing(brush, mode)) { + return size_clamp * spacing / 50.0f; + } + else { + return max_ff(1.0, size_clamp * spacing / 50.0f); + } } static float paint_stroke_overlapped_curve(Brush *br, float x, float spacing) @@ -677,14 +718,18 @@ static float paint_stroke_integrate_overlap(Brush *br, float factor) } } -static float paint_space_stroke_spacing_variable( - const Scene *scene, PaintStroke *stroke, float pressure, float dpressure, float length) +static float paint_space_stroke_spacing_variable(bContext *C, + const Scene *scene, + PaintStroke *stroke, + float pressure, + float dpressure, + float length) { if (BKE_brush_use_size_pressure(scene, stroke->brush)) { /* use pressure to modify size. set spacing so that at 100%, the circles * are aligned nicely with no overlap. for this the spacing needs to be * the average of the previous and next size. */ - float s = paint_space_stroke_spacing(scene, stroke, 1.0f, pressure); + float s = paint_space_stroke_spacing(C, scene, stroke, 1.0f, pressure); float q = s * dpressure / (2.0f * length); float pressure_fac = (1.0f + q) / (1.0f - q); @@ -692,14 +737,15 @@ static float paint_space_stroke_spacing_variable( float new_size_pressure = stroke->last_pressure * pressure_fac; /* average spacing */ - float last_spacing = paint_space_stroke_spacing(scene, stroke, last_size_pressure, pressure); - float new_spacing = paint_space_stroke_spacing(scene, stroke, new_size_pressure, pressure); + float last_spacing = paint_space_stroke_spacing( + C, scene, stroke, last_size_pressure, pressure); + float new_spacing = paint_space_stroke_spacing(C, scene, stroke, new_size_pressure, pressure); return 0.5f * (last_spacing + new_spacing); } else { /* no size pressure */ - return paint_space_stroke_spacing(scene, stroke, 1.0f, pressure); + return paint_space_stroke_spacing(C, scene, stroke, 1.0f, pressure); } } @@ -711,29 +757,57 @@ static int paint_space_stroke(bContext *C, float final_pressure) { const Scene *scene = CTX_data_scene(C); + ARegion *ar = CTX_wm_region(C); PaintStroke *stroke = op->customdata; UnifiedPaintSettings *ups = stroke->ups; + Paint *paint = BKE_paint_get_active_from_context(C); + ePaintMode mode = BKE_paintmode_get_active_from_context(C); + Brush *brush = BKE_paint_brush(paint); int cnt = 0; float pressure, dpressure; float mouse[2], dmouse[2]; + float scene_space_position[3], d_scene_space_position[3], final_scene_space_position[3]; float length; - float no_pressure_spacing = paint_space_stroke_spacing(scene, stroke, 1.0f, 1.0f); - - sub_v2_v2v2(dmouse, final_mouse, stroke->last_mouse_position); - + float no_pressure_spacing = paint_space_stroke_spacing(C, scene, stroke, 1.0f, 1.0f); pressure = stroke->last_pressure; dpressure = final_pressure - stroke->last_pressure; - + sub_v2_v2v2(dmouse, final_mouse, stroke->last_mouse_position); length = normalize_v2(dmouse); + if (paint_stroke_use_scene_spacing(brush, mode)) { + bool hit = sculpt_stroke_get_location(C, scene_space_position, final_mouse); + if (hit && stroke->stroke_over_mesh) { + sub_v3_v3v3(d_scene_space_position, scene_space_position, stroke->last_scene_space_position); + length = len_v3(d_scene_space_position); + stroke->stroke_over_mesh = true; + } + else { + length = 0.0f; + stroke->stroke_over_mesh = hit; + if (stroke->stroke_over_mesh) { + copy_v3_v3(stroke->last_scene_space_position, scene_space_position); + } + } + } + while (length > 0.0f) { float spacing = paint_space_stroke_spacing_variable( - scene, stroke, pressure, dpressure, length); + C, scene, stroke, pressure, dpressure, length); if (length >= spacing) { - mouse[0] = stroke->last_mouse_position[0] + dmouse[0] * spacing; - mouse[1] = stroke->last_mouse_position[1] + dmouse[1] * spacing; + if (paint_stroke_use_scene_spacing(brush, mode)) { + normalize_v3(d_scene_space_position); + mul_v3_v3fl(final_scene_space_position, d_scene_space_position, spacing); + add_v3_v3v3(final_scene_space_position, + stroke->last_scene_space_position, + final_scene_space_position); + ED_view3d_project(ar, final_scene_space_position, mouse); + } + else { + mouse[0] = stroke->last_mouse_position[0] + dmouse[0] * spacing; + mouse[1] = stroke->last_mouse_position[1] + dmouse[1] * spacing; + } pressure = stroke->last_pressure + (spacing / length) * dpressure; ups->overlap_factor = paint_stroke_integrate_overlap(stroke->brush, @@ -1079,7 +1153,7 @@ static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *str if (br->flag & BRUSH_CURVE) { UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings; const Scene *scene = CTX_data_scene(C); - const float spacing = paint_space_stroke_spacing(scene, stroke, 1.0f, 1.0f); + const float spacing = paint_space_stroke_spacing(C, scene, stroke, 1.0f, 1.0f); PaintCurve *pc = br->paint_curve; PaintCurvePoint *pcp; float length_residue = 0.0f; @@ -1250,6 +1324,10 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event) if (!stroke->stroke_started) { stroke->last_pressure = sample_average.pressure; copy_v2_v2(stroke->last_mouse_position, sample_average.mouse); + if (paint_stroke_use_scene_spacing(br, mode)) { + stroke->stroke_over_mesh = sculpt_stroke_get_location( + C, stroke->last_scene_space_position, sample_average.mouse); + } stroke->stroke_started = stroke->test_start(C, op, sample_average.mouse); BLI_assert((stroke->stroke_started & ~1) == 0); /* 0/1 */ diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 440c4d42cae..5aa913ad006 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -96,7 +96,18 @@ /* Do not use these functions while working with PBVH_GRIDS data in SculptSession */ -/* TODO: why is this kept, should it be removed? */ +static float *sculpt_vertex_co_get(SculptSession *ss, int index) +{ + switch (BKE_pbvh_type(ss->pbvh)) { + case PBVH_FACES: + return ss->mvert[index].co; + case PBVH_BMESH: + return BM_vert_at_index(BKE_pbvh_get_bmesh(ss->pbvh), index)->co; + default: + return NULL; + } +} + #if 0 /* UNUSED */ static int sculpt_active_vertex_get(SculptSession *ss) @@ -136,18 +147,6 @@ static void sculpt_vertex_normal_get(SculptSession *ss, int index, float no[3]) } } -static float *sculpt_vertex_co_get(SculptSession *ss, int index) -{ - switch (BKE_pbvh_type(ss->pbvh)) { - case PBVH_FACES: - return ss->mvert[index].co; - case PBVH_BMESH: - return BM_vert_at_index(BKE_pbvh_get_bmesh(ss->pbvh), index)->co; - default: - return NULL; - } -} - static void sculpt_vertex_co_set(SculptSession *ss, int index, float co[3]) { switch (BKE_pbvh_type(ss->pbvh)) { @@ -748,17 +747,26 @@ void ED_sculpt_redraw_planes_get(float planes[4][4], ARegion *ar, Object *ob) void sculpt_brush_test_init(SculptSession *ss, SculptBrushTest *test) { - RegionView3D *rv3d = ss->cache->vc->rv3d; + RegionView3D *rv3d = ss->cache ? ss->cache->vc->rv3d : ss->rv3d; + + test->radius_squared = ss->cache ? ss->cache->radius_squared : + ss->cursor_radius * ss->cursor_radius; + if (ss->cache) { + copy_v3_v3(test->location, ss->cache->location); + test->mirror_symmetry_pass = ss->cache->mirror_symmetry_pass; + } + else { + copy_v3_v3(test->location, ss->cursor_location); + test->mirror_symmetry_pass = 0; + } - test->radius_squared = ss->cache->radius_squared; - copy_v3_v3(test->location, ss->cache->location); test->dist = 0.0f; /* just for initialize */ /* Only for 2D projection. */ zero_v4(test->plane_view); zero_v4(test->plane_tool); - test->mirror_symmetry_pass = ss->cache->mirror_symmetry_pass; + test->mirror_symmetry_pass = ss->cache ? ss->cache->mirror_symmetry_pass : 0; if (rv3d->rflag & RV3D_CLIPPING) { test->clip_rv3d = rv3d; @@ -1050,7 +1058,7 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata, int private_count[2] = {0}; bool use_original = false; - if (ss->cache->original) { + if (ss->cache && ss->cache->original) { unode = sculpt_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_COORDS); use_original = (unode->co || unode->bm_entry); } @@ -1059,6 +1067,13 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata, SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + /* Update the test radius to sample the normal using the normal radius of the brush */ + if (data->brush->ob_mode == OB_MODE_SCULPT) { + float test_radius = sqrtf(test.radius_squared); + test_radius *= data->brush->normal_radius_factor; + test.radius_squared = test_radius * test_radius; + } + /* when the mesh is edited we can't rely on original coords * (original mesh may not even have verts in brush radius) */ if (use_original && data->has_bm_orco) { @@ -1120,6 +1135,8 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata, const float *no; int flip_index; + data->any_vertex_sampled = true; + if (use_original) { normal_short_to_float_v3(no_buf, no_s); no = no_buf; @@ -1134,7 +1151,8 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata, } } - flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); + flip_index = (dot_v3v3(ss->cache ? ss->cache->view_normal : ss->cursor_view_normal, no) <= + 0.0f); if (area_cos) { add_v3_v3(private_co[flip_index], co); } @@ -1223,7 +1241,7 @@ static void calc_area_normal( } /* expose 'calc_area_normal' externally. */ -void sculpt_pbvh_calc_area_normal(const Brush *brush, +bool sculpt_pbvh_calc_area_normal(const Brush *brush, Object *ob, PBVHNode **nodes, int totnode, @@ -1249,6 +1267,7 @@ void sculpt_pbvh_calc_area_normal(const Brush *brush, .area_cos = NULL, .area_nos = area_nos, .count = count, + .any_vertex_sampled = false, }; BLI_mutex_init(&data.mutex); @@ -1265,6 +1284,8 @@ void sculpt_pbvh_calc_area_normal(const Brush *brush, break; } } + + return data.any_vertex_sampled; } /* this calculates flatten center and area normal together, @@ -1508,7 +1529,8 @@ float tex_strength(SculptSession *ss, bool sculpt_search_sphere_cb(PBVHNode *node, void *data_v) { SculptSearchSphereData *data = data_v; - float *center = data->ss->cache->location, nearest[3]; + float *center, nearest[3]; + center = data->ss->cache ? data->ss->cache->location : data->ss->cursor_location; float t[3], bb_min[3], bb_max[3]; int i; @@ -1585,12 +1607,13 @@ static PBVHNode **sculpt_pbvh_gather_generic(Object *ob, SculptSession *ss = ob->sculpt; PBVHNode **nodes = NULL; - /* Build a list of all nodes that are potentially within the brush's area of influence */ + /* Build a list of all nodes that are potentially within the cursor or brush's area of influence + */ if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE) { SculptSearchSphereData data = { .ss = ss, .sd = sd, - .radius_squared = SQUARE(ss->cache->radius * radius_scale), + .radius_squared = ss->cache ? SQUARE(ss->cache->radius * radius_scale) : ss->cursor_radius, .original = use_original, }; BKE_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, r_totnode); @@ -1602,7 +1625,7 @@ static PBVHNode **sculpt_pbvh_gather_generic(Object *ob, SculptSearchCircleData data = { .ss = ss, .sd = sd, - .radius_squared = SQUARE(ss->cache->radius * radius_scale), + .radius_squared = ss->cache ? SQUARE(ss->cache->radius * radius_scale) : ss->cursor_radius, .original = use_original, .dist_ray_to_aabb_precalc = &dist_ray_to_aabb_precalc, }; @@ -1964,10 +1987,14 @@ typedef struct SculptDoBrushSmoothGridDataChunk { typedef struct { SculptSession *ss; const float *ray_start; + const float *ray_normal; bool hit; float depth; bool original; + int active_vertex_index; + float *face_normal; + struct IsectRayPrecalc isect_precalc; } SculptRaycastData; @@ -3987,7 +4014,7 @@ static void do_gravity(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, fl BLI_task_parallel_range(0, totnode, &data, do_gravity_task_cb_ex, &settings); } -void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3]) +void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, const float (*vertCos)[3]) { Mesh *me = (Mesh *)ob->data; float(*ofs)[3] = NULL; @@ -4349,7 +4376,7 @@ static void sculpt_update_keyblock(Object *ob) vertCos = ss->orig_cos; } else { - vertCos = BKE_pbvh_get_vertCos(ss->pbvh); + vertCos = BKE_pbvh_vert_coords_alloc(ss->pbvh); } if (vertCos) { @@ -4513,7 +4540,7 @@ static void do_tiled( float orgLoc[3]; /* position of the "prototype" stroke for tiling */ copy_v3_v3(orgLoc, cache->location); - for (dim = 0; dim < 3; ++dim) { + for (dim = 0; dim < 3; dim++) { if ((sd->paint.symmetry_flags & (PAINT_TILE_X << dim)) && step[dim] > 0) { start[dim] = (bbMin[dim] - orgLoc[dim] - radius) / step[dim]; end[dim] = (bbMax[dim] - orgLoc[dim] + radius) / step[dim]; @@ -4529,16 +4556,16 @@ static void do_tiled( /* now do it for all the tiles */ copy_v3_v3_int(cur, start); - for (cur[0] = start[0]; cur[0] <= end[0]; ++cur[0]) { - for (cur[1] = start[1]; cur[1] <= end[1]; ++cur[1]) { - for (cur[2] = start[2]; cur[2] <= end[2]; ++cur[2]) { + for (cur[0] = start[0]; cur[0] <= end[0]; cur[0]++) { + for (cur[1] = start[1]; cur[1] <= end[1]; cur[1]++) { + for (cur[2] = start[2]; cur[2] <= end[2]; cur[2]++) { if (!cur[0] && !cur[1] && !cur[2]) { continue; /* skip tile at orgLoc, this was already handled before all others */ } ++cache->tile_pass; - for (dim = 0; dim < 3; ++dim) { + for (dim = 0; dim < 3; dim++) { cache->location[dim] = cur[dim] * step[dim] + orgLoc[dim]; cache->plane_offset[dim] = cur[dim] * step[dim]; } @@ -5154,10 +5181,11 @@ static bool sculpt_any_smooth_mode(const Brush *brush, StrokeCache *cache, int s static void sculpt_stroke_modifiers_check(const bContext *C, Object *ob, const Brush *brush) { SculptSession *ss = ob->sculpt; + View3D *v3d = CTX_wm_view3d(C); - if (ss->kb || ss->modifiers_active) { + bool need_pmap = sculpt_any_smooth_mode(brush, ss->cache, 0); + if (ss->kb || ss->modifiers_active || (!BKE_sculptsession_use_pbvh_draw(ob, v3d) && need_pmap)) { Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); - bool need_pmap = sculpt_any_smooth_mode(brush, ss->cache, 0); BKE_sculpt_update_object_for_edit(depsgraph, ob, need_pmap, false); } } @@ -5186,8 +5214,11 @@ static void sculpt_raycast_cb(PBVHNode *node, void *data_v, float *tmin) origco, use_origco, srd->ray_start, + srd->ray_normal, &srd->isect_precalc, - &srd->depth)) { + &srd->depth, + &srd->active_vertex_index, + srd->face_normal)) { srd->hit = 1; *tmin = srd->depth; } @@ -5275,6 +5306,120 @@ static float sculpt_raycast_init(ViewContext *vc, return dist; } +/* Gets the normal, location and active vertex location of the geometry under the cursor. This also + * updates + * the active vertex and cursor related data of the SculptSession using the mouse position */ +bool sculpt_cursor_geometry_info_update(bContext *C, + SculptCursorGeometryInfo *out, + const float mouse[2], + bool use_sampled_normal) +{ + Scene *scene = CTX_data_scene(C); + Sculpt *sd = scene->toolsettings->sculpt; + Object *ob; + SculptSession *ss; + ViewContext vc; + const Brush *brush = BKE_paint_brush(BKE_paint_get_active_from_context(C)); + float ray_start[3], ray_end[3], ray_normal[3], depth, face_normal[3], sampled_normal[3], + mat[3][3]; + float viewDir[3] = {0.0f, 0.0f, 1.0f}; + int totnode; + bool original = false, hit = false; + + ED_view3d_viewcontext_init(C, &vc); + + ob = vc.obact; + ss = ob->sculpt; + + if (!ss->pbvh) { + copy_v3_fl(out->location, 0.0f); + copy_v3_fl(out->normal, 0.0f); + copy_v3_fl(out->active_vertex_co, 0.0f); + return false; + } + + /* PBVH raycast to get active vertex and face normal */ + depth = sculpt_raycast_init(&vc, mouse, ray_start, ray_end, ray_normal, original); + sculpt_stroke_modifiers_check(C, ob, brush); + + SculptRaycastData srd = { + .original = original, + .ss = ob->sculpt, + .hit = 0, + .ray_start = ray_start, + .ray_normal = ray_normal, + .depth = depth, + .face_normal = face_normal, + }; + isect_ray_tri_watertight_v3_precalc(&srd.isect_precalc, ray_normal); + BKE_pbvh_raycast(ss->pbvh, sculpt_raycast_cb, &srd, ray_start, ray_normal, srd.original); + + /* Cursor is not over the mesh, return default values */ + if (!srd.hit) { + copy_v3_fl(out->location, 0.0f); + copy_v3_fl(out->normal, 0.0f); + copy_v3_fl(out->active_vertex_co, 0.0f); + return false; + } + + /* Update the active vertex of the SculptSession */ + ss->active_vertex_index = srd.active_vertex_index; + + copy_v3_v3(out->active_vertex_co, sculpt_vertex_co_get(ss, srd.active_vertex_index)); + copy_v3_v3(out->location, ray_normal); + mul_v3_fl(out->location, srd.depth); + add_v3_v3(out->location, ray_start); + + /* Option to return the face normal directly for performance o accuracy reasons */ + if (!use_sampled_normal) { + copy_v3_v3(out->normal, srd.face_normal); + return hit; + } + + /* Sampled normal calculation */ + const float radius_scale = 1.0f; + float radius; + + /* Update cursor data in SculptSession */ + invert_m4_m4(ob->imat, ob->obmat); + copy_m3_m4(mat, vc.rv3d->viewinv); + mul_m3_v3(mat, viewDir); + copy_m3_m4(mat, ob->imat); + mul_m3_v3(mat, viewDir); + normalize_v3_v3(ss->cursor_view_normal, viewDir); + copy_v3_v3(ss->cursor_normal, srd.face_normal); + copy_v3_v3(ss->cursor_location, out->location); + ss->rv3d = vc.rv3d; + + if (!BKE_brush_use_locked_size(scene, brush)) { + radius = paint_calc_object_space_radius(&vc, out->location, BKE_brush_size_get(scene, brush)); + } + else { + radius = BKE_brush_unprojected_radius_get(scene, brush); + } + ss->cursor_radius = radius; + + PBVHNode **nodes = sculpt_pbvh_gather_generic(ob, sd, brush, original, radius_scale, &totnode); + + /* In case there are no nodes under the cursor, return the face normal */ + if (!totnode) { + MEM_freeN(nodes); + copy_v3_v3(out->normal, srd.face_normal); + return true; + } + + /* Calculate the sampled normal */ + if (sculpt_pbvh_calc_area_normal(brush, ob, nodes, totnode, true, sampled_normal)) { + copy_v3_v3(out->normal, sampled_normal); + } + else { + /* Use face normal when there are no vertices to sample inside the cursor radius */ + copy_v3_v3(out->normal, srd.face_normal); + } + MEM_freeN(nodes); + return true; +} + /* Do a raycast in the tree to find the 3d brush location * (This allows us to ignore the GL depth buffer) * Returns 0 if the ray doesn't hit the mesh, non-zero otherwise @@ -5284,7 +5429,7 @@ bool sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2]) Object *ob; SculptSession *ss; StrokeCache *cache; - float ray_start[3], ray_end[3], ray_normal[3], depth; + float ray_start[3], ray_end[3], ray_normal[3], depth, face_normal[3]; bool original; ViewContext vc; @@ -5302,14 +5447,21 @@ bool sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2]) depth = sculpt_raycast_init(&vc, mouse, ray_start, ray_end, ray_normal, original); + if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) { + BM_mesh_elem_table_ensure(ss->bm, BM_VERT); + BM_mesh_elem_index_ensure(ss->bm, BM_VERT); + } + bool hit = false; { SculptRaycastData srd; srd.ss = ob->sculpt; srd.ray_start = ray_start; + srd.ray_normal = ray_normal; srd.hit = 0; srd.depth = depth; srd.original = original; + srd.face_normal = face_normal; isect_ray_tri_watertight_v3_precalc(&srd.isect_precalc, ray_normal); BKE_pbvh_raycast(ss->pbvh, sculpt_raycast_cb, &srd, ray_start, ray_normal, srd.original); @@ -5577,7 +5729,6 @@ static void sculpt_stroke_update_step(bContext *C, } do_symmetrical_brush_actions(sd, ob, do_brush_action, ups); - sculpt_combine_proxies(sd, ob); /* hack to fix noise texture tearing mesh */ diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index e646accf108..9f1cb7a53a4 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -34,9 +34,7 @@ #include "BKE_pbvh.h" struct KeyBlock; -struct Main; struct Object; -struct SculptOrigVertData; struct SculptUndoNode; struct bContext; @@ -47,7 +45,18 @@ bool sculpt_poll(struct bContext *C); bool sculpt_poll_view3d(struct bContext *C); /* Stroke */ + +typedef struct SculptCursorGeometryInfo { + float location[3]; + float normal[3]; + float active_vertex_co[3]; +} SculptCursorGeometryInfo; + bool sculpt_stroke_get_location(struct bContext *C, float out[3], const float mouse[2]); +bool sculpt_cursor_geometry_info_update(bContext *C, + SculptCursorGeometryInfo *out, + const float mouse[2], + bool use_sampled_normal); /* Dynamic topology */ void sculpt_pbvh_clear(Object *ob); @@ -164,6 +173,7 @@ typedef struct SculptThreadedTaskData { float (*area_cos)[3]; float (*area_nos)[3]; int *count; + bool any_vertex_sampled; ThreadMutex mutex; @@ -228,7 +238,7 @@ float tex_strength(struct SculptSession *ss, const int thread_id); /* just for vertex paint. */ -void sculpt_pbvh_calc_area_normal(const struct Brush *brush, +bool sculpt_pbvh_calc_area_normal(const struct Brush *brush, Object *ob, PBVHNode **nodes, int totnode, @@ -342,7 +352,7 @@ SculptUndoNode *sculpt_undo_get_node(PBVHNode *node); void sculpt_undo_push_begin(const char *name); void sculpt_undo_push_end(void); -void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3]); +void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, const float (*vertCos)[3]); void sculpt_update_object_bounding_box(struct Object *ob); diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c index 3a3487227a3..cb8afd5d7fa 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.c +++ b/source/blender/editors/sculpt_paint/sculpt_undo.c @@ -189,7 +189,7 @@ static bool sculpt_undo_restore_coords(bContext *C, Depsgraph *depsgraph, Sculpt /* pbvh uses it's own mvert array, so coords should be */ /* propagated to pbvh here */ - BKE_pbvh_apply_vertCos(ss->pbvh, vertCos, ss->kb->totelem); + BKE_pbvh_vert_coords_apply(ss->pbvh, vertCos, ss->kb->totelem); MEM_freeN(vertCos); } diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c index 51231ccf634..4e710d31cbb 100644 --- a/source/blender/editors/sound/sound_ops.c +++ b/source/blender/editors/sound/sound_ops.c @@ -710,7 +710,7 @@ static void SOUND_OT_mixdown(wmOperatorType *ot) FILE_TYPE_FOLDER | FILE_TYPE_SOUND, FILE_SPECIAL, FILE_SAVE, - WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, + WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH | WM_FILESEL_SHOW_PROPS, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); #ifdef WITH_AUDASPACE diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c index bc7f8a0f79d..5ceaefd6309 100644 --- a/source/blender/editors/space_action/action_data.c +++ b/source/blender/editors/space_action/action_data.c @@ -220,7 +220,7 @@ static int action_new_exec(bContext *C, wmOperator *UNUSED(op)) PointerRNA oldptr; oldptr = RNA_property_pointer_get(&ptr, prop); - oldact = (bAction *)oldptr.id.data; + oldact = (bAction *)oldptr.owner_id; /* stash the old action to prevent it from being lost */ if (ptr.type == &RNA_AnimData) { diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c index a7b6f399187..0c57113956d 100644 --- a/source/blender/editors/space_action/action_draw.c +++ b/source/blender/editors/space_action/action_draw.c @@ -352,179 +352,231 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) /* ************************************************************************* */ /* Timeline - Caches */ -void timeline_draw_cache(SpaceAction *saction, Object *ob, Scene *scene) +static bool timeline_cache_is_hidden_by_setting(SpaceAction *saction, PTCacheID *pid) { - PTCacheID *pid; - ListBase pidlist; - const float cache_draw_height = (4.0f * UI_DPI_FAC * U.pixelsize); - float yoffs = 0.f; - - if (!(saction->cache_display & TIME_CACHE_DISPLAY) || (!ob)) { - return; + switch (pid->type) { + case PTCACHE_TYPE_SOFTBODY: + if ((saction->cache_display & TIME_CACHE_SOFTBODY) == 0) { + return true; + } + break; + case PTCACHE_TYPE_PARTICLES: + if ((saction->cache_display & TIME_CACHE_PARTICLES) == 0) { + return true; + } + break; + case PTCACHE_TYPE_CLOTH: + if ((saction->cache_display & TIME_CACHE_CLOTH) == 0) { + return true; + } + break; + case PTCACHE_TYPE_SMOKE_DOMAIN: + case PTCACHE_TYPE_SMOKE_HIGHRES: + if ((saction->cache_display & TIME_CACHE_SMOKE) == 0) { + return true; + } + break; + case PTCACHE_TYPE_DYNAMICPAINT: + if ((saction->cache_display & TIME_CACHE_DYNAMICPAINT) == 0) { + return true; + } + break; + case PTCACHE_TYPE_RIGIDBODY: + if ((saction->cache_display & TIME_CACHE_RIGIDBODY) == 0) { + return true; + } + break; } + return false; +} - BKE_ptcache_ids_from_object(&pidlist, ob, scene, 0); +static void timeline_cache_color_get(PTCacheID *pid, float color[4]) +{ + switch (pid->type) { + case PTCACHE_TYPE_SOFTBODY: + color[0] = 1.0; + color[1] = 0.4; + color[2] = 0.02; + color[3] = 0.1; + break; + case PTCACHE_TYPE_PARTICLES: + color[0] = 1.0; + color[1] = 0.1; + color[2] = 0.02; + color[3] = 0.1; + break; + case PTCACHE_TYPE_CLOTH: + color[0] = 0.1; + color[1] = 0.1; + color[2] = 0.75; + color[3] = 0.1; + break; + case PTCACHE_TYPE_SMOKE_DOMAIN: + case PTCACHE_TYPE_SMOKE_HIGHRES: + color[0] = 0.2; + color[1] = 0.2; + color[2] = 0.2; + color[3] = 0.1; + break; + case PTCACHE_TYPE_DYNAMICPAINT: + color[0] = 1.0; + color[1] = 0.1; + color[2] = 0.75; + color[3] = 0.1; + break; + case PTCACHE_TYPE_RIGIDBODY: + color[0] = 1.0; + color[1] = 0.6; + color[2] = 0.0; + color[3] = 0.1; + break; + default: + color[0] = 1.0; + color[1] = 0.0; + color[2] = 1.0; + color[3] = 0.1; + BLI_assert(0); + break; + } +} - uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); +static void timeline_cache_modify_color_based_on_state(PointCache *cache, float color[4]) +{ + if (cache->flag & PTCACHE_BAKED) { + color[0] -= 0.4f; + color[1] -= 0.4f; + color[2] -= 0.4f; + } + else if (cache->flag & PTCACHE_OUTDATED) { + color[0] += 0.4f; + color[1] += 0.4f; + color[2] += 0.4f; + } +} - /* iterate over pointcaches on the active object, and draw each one's range */ - for (pid = pidlist.first; pid; pid = pid->next) { - float col[4]; +static bool timeline_cache_find_next_cached_segment(PointCache *cache, + int search_start_frame, + int *r_segment_start, + int *r_segment_end) +{ + int offset = cache->startframe; + int current = search_start_frame; - switch (pid->type) { - case PTCACHE_TYPE_SOFTBODY: - if (!(saction->cache_display & TIME_CACHE_SOFTBODY)) { - continue; - } - break; - case PTCACHE_TYPE_PARTICLES: - if (!(saction->cache_display & TIME_CACHE_PARTICLES)) { - continue; - } - break; - case PTCACHE_TYPE_CLOTH: - if (!(saction->cache_display & TIME_CACHE_CLOTH)) { - continue; - } - break; - case PTCACHE_TYPE_SMOKE_DOMAIN: - case PTCACHE_TYPE_SMOKE_HIGHRES: - if (!(saction->cache_display & TIME_CACHE_SMOKE)) { - continue; - } - break; - case PTCACHE_TYPE_DYNAMICPAINT: - if (!(saction->cache_display & TIME_CACHE_DYNAMICPAINT)) { - continue; - } - break; - case PTCACHE_TYPE_RIGIDBODY: - if (!(saction->cache_display & TIME_CACHE_RIGIDBODY)) { - continue; - } - break; + /* Find segment start frame. */ + while (true) { + if (current > cache->endframe) { + return false; } - - if (pid->cache->cached_frames == NULL) { - continue; + if (cache->cached_frames[current - offset]) { + *r_segment_start = current; + break; } + current++; + } - GPU_matrix_push(); - GPU_matrix_translate_2f(0.0, (float)V2D_SCROLL_HANDLE_HEIGHT + yoffs); - GPU_matrix_scale_2f(1.0, cache_draw_height); - - switch (pid->type) { - case PTCACHE_TYPE_SOFTBODY: - col[0] = 1.0; - col[1] = 0.4; - col[2] = 0.02; - col[3] = 0.1; - break; - case PTCACHE_TYPE_PARTICLES: - col[0] = 1.0; - col[1] = 0.1; - col[2] = 0.02; - col[3] = 0.1; - break; - case PTCACHE_TYPE_CLOTH: - col[0] = 0.1; - col[1] = 0.1; - col[2] = 0.75; - col[3] = 0.1; - break; - case PTCACHE_TYPE_SMOKE_DOMAIN: - case PTCACHE_TYPE_SMOKE_HIGHRES: - col[0] = 0.2; - col[1] = 0.2; - col[2] = 0.2; - col[3] = 0.1; - break; - case PTCACHE_TYPE_DYNAMICPAINT: - col[0] = 1.0; - col[1] = 0.1; - col[2] = 0.75; - col[3] = 0.1; - break; - case PTCACHE_TYPE_RIGIDBODY: - col[0] = 1.0; - col[1] = 0.6; - col[2] = 0.0; - col[3] = 0.1; - break; - default: - col[0] = 1.0; - col[1] = 0.0; - col[2] = 1.0; - col[3] = 0.1; - BLI_assert(0); - break; + /* Find segment end frame. */ + while (true) { + if (current > cache->endframe) { + *r_segment_end = current - 1; + return true; + } + if (!cache->cached_frames[current - offset]) { + *r_segment_end = current - 1; + return true; } + current++; + } +} + +static uint timeline_cache_segments_count(PointCache *cache) +{ + uint count = 0; + + int current = cache->startframe; + int segment_start; + int segment_end; + while (timeline_cache_find_next_cached_segment(cache, current, &segment_start, &segment_end)) { + count++; + current = segment_end + 1; + } + + return count; +} - const int sta = pid->cache->startframe, end = pid->cache->endframe; +static void timeline_cache_draw_cached_segments(PointCache *cache, uint pos_id) +{ + uint segments_count = timeline_cache_segments_count(cache); + if (segments_count == 0) { + return; + } - GPU_blend(true); + immBeginAtMost(GPU_PRIM_TRIS, segments_count * 6); - immUniformColor4fv(col); - immRectf(pos, (float)sta, 0.0, (float)end, 1.0); + int current = cache->startframe; + int segment_start; + int segment_end; + while (timeline_cache_find_next_cached_segment(cache, current, &segment_start, &segment_end)) { + immRectf_fast(pos_id, segment_start - 0.5f, 0, segment_end + 0.5f, 1.0f); + current = segment_end + 1; + } - col[3] = 0.4f; - if (pid->cache->flag & PTCACHE_BAKED) { - col[0] -= 0.4f; - col[1] -= 0.4f; - col[2] -= 0.4f; - } - else if (pid->cache->flag & PTCACHE_OUTDATED) { - col[0] += 0.4f; - col[1] += 0.4f; - col[2] += 0.4f; - } + immEnd(); +} - immUniformColor4fv(col); +static void timeline_cache_draw_single(PTCacheID *pid, float y_offset, float height, uint pos_id) +{ + GPU_matrix_push(); + GPU_matrix_translate_2f(0.0, (float)V2D_SCROLL_HANDLE_HEIGHT + y_offset); + GPU_matrix_scale_2f(1.0, height); - { - /* draw a quad for each chunk of consecutive cached frames */ - const int chunk_tot = 32; - int chunk_len = 0; - int ista = 0, iend = -1; + float color[4]; + timeline_cache_color_get(pid, color); - for (int i = sta; i <= end; i++) { - if (pid->cache->cached_frames[i - sta]) { - if (chunk_len == 0) { - immBeginAtMost(GPU_PRIM_TRIS, chunk_tot * 6); - } - if (ista > iend) { - chunk_len++; - ista = i; - } - iend = i; - } - else { - if (ista <= iend) { - immRectf_fast(pos, (float)ista - 0.5f, 0.0f, (float)iend + 0.5f, 1.0f); - iend = ista - 1; - } - if (chunk_len >= chunk_tot) { - immEnd(); - chunk_len = 0; - } - } - } - if (ista <= iend) { - immRectf_fast(pos, (float)ista - 0.5f, 0.0f, (float)iend + 0.5f, 1.0f); - } - if (chunk_len != 0) { - immEnd(); - } + immUniformColor4fv(color); + immRectf(pos_id, (float)pid->cache->startframe, 0.0, (float)pid->cache->endframe, 1.0); + + color[3] = 0.4f; + timeline_cache_modify_color_based_on_state(pid->cache, color); + immUniformColor4fv(color); + + timeline_cache_draw_cached_segments(pid->cache, pos_id); + + GPU_matrix_pop(); +} + +void timeline_draw_cache(SpaceAction *saction, Object *ob, Scene *scene) +{ + if ((saction->cache_display & TIME_CACHE_DISPLAY) == 0 || ob == NULL) { + return; + } + + ListBase pidlist; + BKE_ptcache_ids_from_object(&pidlist, ob, scene, 0); + + uint pos_id = GPU_vertformat_attr_add( + immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + GPU_blend(true); + + /* Iterate over pointcaches on the active object, and draw each one's range. */ + float y_offset = 0.0f; + const float cache_draw_height = 4.0f * UI_DPI_FAC * U.pixelsize; + for (PTCacheID *pid = pidlist.first; pid; pid = pid->next) { + if (timeline_cache_is_hidden_by_setting(saction, pid)) { + continue; } - GPU_blend(false); + if (pid->cache->cached_frames == NULL) { + continue; + } - GPU_matrix_pop(); + timeline_cache_draw_single(pid, y_offset, cache_draw_height, pos_id); - yoffs += cache_draw_height; + y_offset += cache_draw_height; } + GPU_blend(false); immUnbindProgram(); BLI_freelistN(&pidlist); diff --git a/source/blender/editors/space_action/action_intern.h b/source/blender/editors/space_action/action_intern.h index eaca7968a34..c227b794ae7 100644 --- a/source/blender/editors/space_action/action_intern.h +++ b/source/blender/editors/space_action/action_intern.h @@ -28,9 +28,7 @@ struct ARegion; struct ARegionType; struct Object; struct Scene; -struct ScrArea; struct SpaceAction; -struct View2D; struct bAnimContext; struct bContext; struct wmOperatorType; diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index 9e2634b183a..cbf4d0628e6 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -1717,22 +1717,26 @@ static void mouse_action_keys(bAnimContext *ac, /* Highlight GPencil Layer */ if (ale != NULL && ale->data != NULL && ale->type == ANIMTYPE_GPLAYER) { + bGPdata *gpd = (bGPdata *)ale->id; bGPDlayer *gpl = ale->data; gpl->flag |= GP_LAYER_SELECT; - // gpencil_layer_setactive(gpd, gpl); + /* Update other layer status. */ + if (BKE_gpencil_layer_getactive(gpd) != gpl) { + BKE_gpencil_layer_setactive(gpd, gpl); + BKE_gpencil_layer_autolock_set(gpd); + WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL); + } } } else if (ac->datatype == ANIMCONT_MASK) { /* deselect all other channels first */ ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR); - /* Highlight GPencil Layer */ if (ale != NULL && ale->data != NULL && ale->type == ANIMTYPE_MASKLAYER) { MaskLayer *masklay = ale->data; masklay->flag |= MASK_LAYERFLAG_SELECT; - // gpencil_layer_setactive(gpd, gpl); } } } diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c index 3c879b03126..1685852dd02 100644 --- a/source/blender/editors/space_action/space_action.c +++ b/source/blender/editors/space_action/space_action.c @@ -373,7 +373,7 @@ static void saction_channel_region_message_subscribe(const struct bContext *UNUS * so just whitelist the entire structs for updates */ { - wmMsgParams_RNA msg_key_params = {{{0}}}; + wmMsgParams_RNA msg_key_params = {{0}}; StructRNA *type_array[] = { &RNA_DopeSheet, /* dopesheet filters */ diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index 78d5ed0f98a..56a0f472010 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -76,7 +76,7 @@ static int set_pointer_type(ButsContextPath *path, bContextDataResult *result, S ptr = &path->ptr[a]; if (RNA_struct_is_a(ptr->type, type)) { - CTX_data_pointer_set(result, ptr->id.data, ptr->type, ptr->data); + CTX_data_pointer_set(result, ptr->owner_id, ptr->type, ptr->data); return 1; } } @@ -930,7 +930,7 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r if (ct->user && ct->user->ptr.data) { ButsTextureUser *user = ct->user; - CTX_data_pointer_set(result, user->ptr.id.data, user->ptr.type, user->ptr.data); + CTX_data_pointer_set(result, user->ptr.owner_id, user->ptr.type, user->ptr.data); } return 1; @@ -1018,7 +1018,7 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r PointerRNA *ptr = get_pointer_type(path, &RNA_ParticleSettings); if (ptr && ptr->data) { - CTX_data_pointer_set(result, ptr->id.data, &RNA_ParticleSettings, ptr->data); + CTX_data_pointer_set(result, ptr->owner_id, &RNA_ParticleSettings, ptr->data); return 1; } else { @@ -1027,7 +1027,7 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r if (ptr && ptr->data) { ParticleSettings *part = ((ParticleSystem *)ptr->data)->part; - CTX_data_pointer_set(result, ptr->id.data, &RNA_ParticleSettings, part); + CTX_data_pointer_set(result, ptr->owner_id, &RNA_ParticleSettings, part); return 1; } } @@ -1285,8 +1285,8 @@ ID *buttons_context_id_path(const bContext *C) } } - if (ptr->id.data) { - return ptr->id.data; + if (ptr->owner_id) { + return ptr->owner_id; } } } diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c index 500efe4bb4d..3ea6d183969 100644 --- a/source/blender/editors/space_buttons/buttons_ops.c +++ b/source/blender/editors/space_buttons/buttons_ops.c @@ -103,7 +103,7 @@ static int file_browse_exec(bContext *C, wmOperator *op) /* add slash for directories, important for some properties */ if (RNA_property_subtype(fbo->prop) == PROP_DIRPATH) { const bool is_relative = RNA_boolean_get(op->ptr, "relative_path"); - id = fbo->ptr.id.data; + id = fbo->ptr.owner_id; BLI_strncpy(path, str, FILE_MAX); BLI_path_abs(path, id ? ID_BLEND_PATH(bmain, id) : BKE_main_blendfile_path(bmain)); diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c index 87ea011e0a7..03c8fbb4e66 100644 --- a/source/blender/editors/space_buttons/buttons_texture.c +++ b/source/blender/editors/space_buttons/buttons_texture.c @@ -385,7 +385,7 @@ static void template_texture_select(bContext *C, void *user_p, void *UNUSED(arg) if (user->ptr.type == &RNA_ParticleSettingsTextureSlot) { /* stupid exception for particle systems which still uses influence * from the old texture system, set the active texture slots as well */ - ParticleSettings *part = user->ptr.id.data; + ParticleSettings *part = (ParticleSettings *)user->ptr.owner_id; int a; for (a = 0; a < MAX_MTEX; a++) { diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c index b3690bf2fe3..6008d06e376 100644 --- a/source/blender/editors/space_buttons/space_buttons.c +++ b/source/blender/editors/space_buttons/space_buttons.c @@ -404,8 +404,6 @@ static void buttons_area_listener(wmWindow *UNUSED(win), buttons_area_redraw(sa, BCONTEXT_DATA); /* autotexpace flag */ break; case ND_POSE: - buttons_area_redraw(sa, BCONTEXT_DATA); - break; case ND_BONE_ACTIVE: case ND_BONE_SELECT: buttons_area_redraw(sa, BCONTEXT_BONE); @@ -567,7 +565,7 @@ static void buttons_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, int i; for (i = 0; i < path->len; i++) { - if (path->ptr[i].id.data == old_id) { + if (path->ptr[i].owner_id == old_id) { break; } } diff --git a/source/blender/editors/space_clip/clip_dopesheet_draw.c b/source/blender/editors/space_clip/clip_dopesheet_draw.c index 599a92ff77f..3c2d3eb1d97 100644 --- a/source/blender/editors/space_clip/clip_dopesheet_draw.c +++ b/source/blender/editors/space_clip/clip_dopesheet_draw.c @@ -222,8 +222,9 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene) format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); uint flags_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT); - immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND); GPU_program_point_size(true); + immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND); + immUniform1f("outline_scale", 1.0f); immUniform2f( "ViewportSize", BLI_rcti_size_x(&v2d->mask) + 1, BLI_rcti_size_y(&v2d->mask) + 1); immBegin(GPU_PRIM_POINTS, keyframe_len); diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c index 999255aef88..f5c02dbd724 100644 --- a/source/blender/editors/space_console/space_console.c +++ b/source/blender/editors/space_console/space_console.c @@ -26,6 +26,7 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "BKE_global.h" #include "BKE_context.h" #include "BKE_screen.h" @@ -173,7 +174,7 @@ static void id_drop_copy(wmDrag *drag, wmDropBox *drop) ID *id = WM_drag_ID(drag, 0); /* copy drag path to properties */ - char *text = RNA_path_full_ID_py(id); + char *text = RNA_path_full_ID_py(G_MAIN, id); RNA_string_set(drop->ptr, "text", text); MEM_freeN(text); } diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index 3a6d59c1dbf..0083fc244d8 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -26,6 +26,7 @@ #include <errno.h> #include "BLI_blenlib.h" +#include "BLI_fileops_types.h" #include "BLI_utildefines.h" #include "BLI_math.h" @@ -77,234 +78,6 @@ static char *file_draw_tooltip_func(bContext *UNUSED(C), void *argN, const char return BLI_strdup(dyn_tooltip); } -/* Note: This function uses pixelspace (0, 0, winx, winy), not view2d. - * The controls are laid out as follows: - * - * ------------------------------------------- - * | Directory input | execute | - * ------------------------------------------- - * | Filename input | + | - | cancel | - * ------------------------------------------- - * - * The input widgets will stretch to fill any excess space. - * When there isn't enough space for all controls to be shown, they are - * hidden in this order: x/-, execute/cancel, input widgets. - */ -void file_draw_buttons(const bContext *C, ARegion *ar) -{ - /* Button layout. */ - const int max_x = ar->winx - 10; - const int line1_y = ar->winy - (IMASEL_BUTTONS_HEIGHT / 2 + IMASEL_BUTTONS_MARGIN); - const int line2_y = line1_y - (IMASEL_BUTTONS_HEIGHT / 2 + IMASEL_BUTTONS_MARGIN); - const int input_minw = 20; - const int btn_h = UI_UNIT_Y; - const int btn_fn_w = UI_UNIT_X; - const int btn_minw = 80; - const int btn_margin = 20; - const int separator = 4; - - /* Additional locals. */ - char uiblockstr[32]; - int loadbutton; - int fnumbuttons; - int min_x = 10; - int chan_offs = 0; - int available_w = max_x - min_x; - int line1_w = available_w; - int line2_w = available_w; - - uiBut *but; - uiBlock *block; - SpaceFile *sfile = CTX_wm_space_file(C); - FileSelectParams *params = ED_fileselect_get_params(sfile); - ARegion *artmp; - const bool is_browse_only = (sfile->op == NULL); - - /* Initialize UI block. */ - BLI_snprintf(uiblockstr, sizeof(uiblockstr), "win %p", (void *)ar); - block = UI_block_begin(C, ar, uiblockstr, UI_EMBOSS); - - /* exception to make space for collapsed region icon */ - for (artmp = CTX_wm_area(C)->regionbase.first; artmp; artmp = artmp->next) { - if (artmp->regiontype == RGN_TYPE_TOOLS && artmp->flag & RGN_FLAG_HIDDEN) { - chan_offs = 16; - min_x += chan_offs; - available_w -= chan_offs; - } - } - - /* Is there enough space for the execute / cancel buttons? */ - - if (is_browse_only) { - loadbutton = 0; - } - else { - const uiFontStyle *fstyle = UI_FSTYLE_WIDGET; - loadbutton = UI_fontstyle_string_width(fstyle, params->title) + btn_margin; - CLAMP_MIN(loadbutton, btn_minw); - if (available_w <= loadbutton + separator + input_minw) { - loadbutton = 0; - } - } - - if (loadbutton) { - line1_w -= (loadbutton + separator); - line2_w = line1_w; - } - - /* Is there enough space for file number increment/decrement buttons? */ - fnumbuttons = 2 * btn_fn_w; - if (!loadbutton || line2_w <= fnumbuttons + separator + input_minw) { - fnumbuttons = 0; - } - else { - line2_w -= (fnumbuttons + separator); - } - - /* Text input fields for directory and file. */ - if (available_w > 0) { - const struct FileDirEntry *file = sfile->files ? - filelist_file(sfile->files, params->active_file) : - NULL; - int overwrite_alert = file_draw_check_exists(sfile); - const bool is_active_dir = file && (file->typeflag & FILE_TYPE_FOLDER); - - /* callbacks for operator check functions */ - UI_block_func_set(block, file_draw_check_cb, NULL, NULL); - - but = uiDefBut(block, - UI_BTYPE_TEXT, - -1, - "", - min_x, - line1_y, - line1_w - chan_offs, - btn_h, - params->dir, - 0.0, - (float)FILE_MAX, - 0, - 0, - TIP_("File path")); - UI_but_func_complete_set(but, autocomplete_directory, NULL); - UI_but_flag_enable(but, UI_BUT_NO_UTF8); - UI_but_flag_disable(but, UI_BUT_UNDO); - UI_but_funcN_set(but, file_directory_enter_handle, NULL, but); - - /* TODO, directory editing is non-functional while a library is loaded - * until this is properly supported just disable it. */ - if (sfile->files && filelist_lib(sfile->files)) { - UI_but_flag_enable(but, UI_BUT_DISABLED); - } - - if ((params->flag & FILE_DIRSEL_ONLY) == 0) { - but = uiDefBut( - block, - UI_BTYPE_TEXT, - -1, - "", - min_x, - line2_y, - line2_w - chan_offs, - btn_h, - is_active_dir ? (char *)"" : params->file, - 0.0, - (float)FILE_MAXFILE, - 0, - 0, - TIP_(overwrite_alert ? N_("File name, overwrite existing") : N_("File name"))); - UI_but_func_complete_set(but, autocomplete_file, NULL); - UI_but_flag_enable(but, UI_BUT_NO_UTF8); - UI_but_flag_disable(but, UI_BUT_UNDO); - /* silly workaround calling NFunc to ensure this does not get called - * immediate ui_apply_but_func but only after button deactivates */ - UI_but_funcN_set(but, file_filename_enter_handle, NULL, but); - - /* check if this overrides a file and if the operator option is used */ - if (overwrite_alert) { - UI_but_flag_enable(but, UI_BUT_REDALERT); - } - } - - /* clear func */ - UI_block_func_set(block, NULL, NULL, NULL); - } - - /* Filename number increment / decrement buttons. */ - if (fnumbuttons && (params->flag & FILE_DIRSEL_ONLY) == 0) { - UI_block_align_begin(block); - but = uiDefIconButO(block, - UI_BTYPE_BUT, - "FILE_OT_filenum", - 0, - ICON_REMOVE, - min_x + line2_w + separator - chan_offs, - line2_y, - btn_fn_w, - btn_h, - TIP_("Decrement the filename number")); - RNA_int_set(UI_but_operator_ptr_get(but), "increment", -1); - - but = uiDefIconButO(block, - UI_BTYPE_BUT, - "FILE_OT_filenum", - 0, - ICON_ADD, - min_x + line2_w + separator + btn_fn_w - chan_offs, - line2_y, - btn_fn_w, - btn_h, - TIP_("Increment the filename number")); - RNA_int_set(UI_but_operator_ptr_get(but), "increment", 1); - UI_block_align_end(block); - } - - /* Execute / cancel buttons. */ - if (loadbutton) { - const struct FileDirEntry *file = sfile->files ? - filelist_file(sfile->files, params->active_file) : - NULL; - char const *str_exec; - - if (file && FILENAME_IS_PARENT(file->relpath)) { - str_exec = IFACE_("Parent Directory"); - } - else if (file && file->typeflag & FILE_TYPE_DIR) { - str_exec = IFACE_("Open Directory"); - } - else { - str_exec = params->title; /* params->title is already translated! */ - } - - but = uiDefButO(block, - UI_BTYPE_BUT, - "FILE_OT_execute", - WM_OP_EXEC_REGION_WIN, - str_exec, - max_x - loadbutton, - line1_y, - loadbutton, - btn_h, - ""); - /* Just a display hint. */ - UI_but_flag_enable(but, UI_BUT_ACTIVE_DEFAULT); - - uiDefButO(block, - UI_BTYPE_BUT, - "FILE_OT_cancel", - WM_OP_EXEC_REGION_WIN, - IFACE_("Cancel"), - max_x - loadbutton, - line2_y, - loadbutton, - btn_h, - ""); - } - - UI_block_end(C, block); - UI_block_draw(C, block); -} - static void draw_tile(int sx, int sy, int width, int height, int colorid, int shade) { float color[4]; @@ -349,7 +122,7 @@ static void file_draw_string(int sx, rcti rect; char fname[FILE_MAXFILE]; - if (string[0] == '\0') { + if (string[0] == '\0' || width < 1) { return; } @@ -362,7 +135,7 @@ static void file_draw_string(int sx, /* no text clipping needed, UI_fontstyle_draw does it but is a bit too strict * (for buttons it works) */ rect.xmin = sx; - rect.xmax = (int)(sx + ceil(width + 5.0f / UI_DPI_FAC)); + rect.xmax = sx + round_fl_to_int(width); rect.ymin = sy - height; rect.ymax = sy; @@ -404,8 +177,8 @@ static void file_draw_preview(uiBlock *block, float scaledx, scaledy; float scale; int ex, ey; - bool use_dropshadow = !is_icon && (typeflags & FILE_TYPE_IMAGE); - float col[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + bool use_dropshadow = !is_icon && + (typeflags & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_BLENDER)); BLI_assert(imb != NULL); @@ -442,13 +215,27 @@ static void file_draw_preview(uiBlock *block, /* shadow */ if (use_dropshadow) { - UI_draw_box_shadow(220, (float)xco, (float)yco, (float)(xco + ex), (float)(yco + ey)); + UI_draw_box_shadow(128, (float)xco, (float)yco, (float)(xco + ex), (float)(yco + ey)); } GPU_blend(true); - /* the image */ - if (!is_icon && typeflags & FILE_TYPE_FTFONT) { + /* the large image */ + + float col[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + if (is_icon) { + /* File and Folder icons draw with lowered opacity until we add themes */ + col[3] = 0.6f; + /* Use dark images if background is light */ + float bg[3]; + UI_GetThemeColor3fv(TH_BACK, bg); + if (rgb_to_grayscale(bg) > 0.5f) { + col[0] = 0; + col[1] = 0; + col[2] = 0; + } + } + else if (typeflags & FILE_TYPE_FTFONT) { UI_GetThemeColor4fv(TH_TEXT, col); } @@ -477,30 +264,61 @@ static void file_draw_preview(uiBlock *block, GPU_blend_set_func_separate( GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); - if (icon) { - UI_icon_draw_ex((float)xco + (7 * UI_DPI_FAC), - (float)yco + (7 * UI_DPI_FAC), - icon, - icon_aspect, - 1.0f, - 0.0f, - NULL, - false); + if (icon && (icon != ICON_FILE_FONT)) { + /* size of center icon is scaled to fit container and UI scale */ + float icon_x, icon_y; + + if (is_icon) { + const float icon_size = 16.0f / icon_aspect * U.dpi_fac; + float icon_opacity = MIN2(icon_aspect, 0.7); + uchar icon_color[4] = {255, 255, 255, 255}; + float bg[3]; + /* base this off theme color of file or folder later */ + UI_GetThemeColor3fv(TH_BACK, bg); + if (rgb_to_grayscale(bg) > 0.5f) { + icon_color[0] = 0; + icon_color[1] = 0; + icon_color[2] = 0; + } + icon_x = xco + (ex / 2.0f) - (icon_size / 2.0f); + icon_y = yco + (ey / 2.0f) - (icon_size * ((typeflags & FILE_TYPE_DIR) ? 0.78f : 0.65f)); + UI_icon_draw_ex( + icon_x, icon_y, icon, icon_aspect / U.dpi_fac, icon_opacity, 0.0f, icon_color, false); + } + else { + const uchar dark[4] = {0, 0, 0, 255}; + const uchar light[4] = {255, 255, 255, 255}; + + /* Smaller, fainter icon for preview image thumbnail. */ + icon_x = xco + (2.0f * UI_DPI_FAC); + icon_y = yco + (2.0f * UI_DPI_FAC); + + UI_icon_draw_ex(icon_x + 1, icon_y - 1, icon, 1.0f / U.dpi_fac, 0.2f, 0.0f, dark, false); + UI_icon_draw_ex(icon_x, icon_y, icon, 1.0f / U.dpi_fac, 0.6f, 0.0f, light, false); + } } /* border */ if (use_dropshadow) { GPUVertFormat *format = immVertexFormat(); - uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + uint pos_attr = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + uint col_attr = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - immUniformColor4f(0.0f, 0.0f, 0.0f, 0.4f); - imm_draw_box_wire_2d(pos, (float)xco, (float)yco, (float)(xco + ex), (float)(yco + ey)); + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + immBegin(GPU_PRIM_LINE_LOOP, 4); + immAttr4f(col_attr, 1.0f, 1.0f, 1.0f, 0.15f); + immVertex2f(pos_attr, (float)xco + 1, (float)(yco + ey)); + immAttr4f(col_attr, 1.0f, 1.0f, 1.0f, 0.2f); + immVertex2f(pos_attr, (float)(xco + ex), (float)(yco + ey)); + immAttr4f(col_attr, 0.0f, 0.0f, 0.0f, 0.2f); + immVertex2f(pos_attr, (float)(xco + ex), (float)yco + 1); + immAttr4f(col_attr, 0.0f, 0.0f, 0.0f, 0.3f); + immVertex2f(pos_attr, (float)xco + 1, (float)yco + 1); + immEnd(); immUnbindProgram(); } but = uiDefBut(block, UI_BTYPE_LABEL, 0, "", xco, yco, ex, ey, NULL, 0.0, 0.0, 0, 0, NULL); - UI_but_func_tooltip_set(but, file_draw_tooltip_func, BLI_strdup(path)); /* dragregion */ if (drag) { @@ -557,6 +375,7 @@ static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname) static void draw_background(FileLayout *layout, View2D *v2d) { + const int item_height = layout->tile_h + (2 * layout->tile_border_y); int i; int sy; @@ -565,9 +384,11 @@ static void draw_background(FileLayout *layout, View2D *v2d) immUniformThemeColorShade(TH_BACK, -7); /* alternating flat shade background */ - for (i = 0; (i <= layout->rows); i += 2) { - sy = (int)v2d->cur.ymax - i * (layout->tile_h + 2 * layout->tile_border_y) - - layout->tile_border_y; + for (i = 2; (i <= layout->rows + 1); i += 2) { + sy = (int)v2d->cur.ymax - layout->offset_top - i * item_height - layout->tile_border_y; + + /* Offsett pattern slightly to add scroll effect. */ + sy += round_fl_to_int(item_height * (v2d->tot.ymax - v2d->cur.ymax) / item_height); immRectf(pos, v2d->cur.xmin, @@ -632,6 +453,176 @@ static void draw_dividers(FileLayout *layout, View2D *v2d) } } +static void draw_columnheader_background(const FileLayout *layout, const View2D *v2d) +{ + uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformThemeColorShade(TH_BACK, 11); + + immRectf(pos, + v2d->cur.xmin, + v2d->cur.ymax - layout->attribute_column_header_h, + v2d->cur.xmax, + v2d->cur.ymax); + + immUnbindProgram(); +} + +static void draw_columnheader_columns(const FileSelectParams *params, + FileLayout *layout, + const View2D *v2d, + const uchar text_col[4]) +{ + const float divider_pad = 0.2 * layout->attribute_column_header_h; + int sx = v2d->cur.xmin, sy = v2d->cur.ymax; + + for (FileAttributeColumnType column_type = 0; column_type < ATTRIBUTE_COLUMN_MAX; + column_type++) { + if (!file_attribute_column_type_enabled(params, column_type)) { + continue; + } + const FileAttributeColumn *column = &layout->attribute_columns[column_type]; + + /* Active sort type triangle */ + if (params->sort == column->sort_type) { + float tri_color[4]; + + rgba_uchar_to_float(tri_color, text_col); + UI_draw_icon_tri(sx + column->width - (0.3f * U.widget_unit) - + ATTRIBUTE_COLUMN_PADDING / 2.0f, + sy + (0.1f * U.widget_unit) - (layout->attribute_column_header_h / 2), + (params->flag & FILE_SORT_INVERT) ? 't' : 'v', + tri_color); + } + + file_draw_string(sx + ATTRIBUTE_COLUMN_PADDING, + sy - layout->tile_border_y, + IFACE_(column->name), + column->width - 2 * ATTRIBUTE_COLUMN_PADDING, + layout->attribute_column_header_h - layout->tile_border_y, + UI_STYLE_TEXT_LEFT, + text_col); + + /* Separator line */ + if (column_type != COLUMN_NAME) { + uint pos = GPU_vertformat_attr_add( + immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformThemeColorShade(TH_BACK, -10); + immBegin(GPU_PRIM_LINES, 2); + immVertex2f(pos, sx - 1, sy - divider_pad); + immVertex2f(pos, sx - 1, sy - layout->attribute_column_header_h + divider_pad); + immEnd(); + immUnbindProgram(); + } + + sx += column->width; + } + + /* Vertical separator lines line */ + { + uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformThemeColorShade(TH_BACK, -10); + immBegin(GPU_PRIM_LINES, 4); + immVertex2f(pos, v2d->cur.xmin, sy); + immVertex2f(pos, v2d->cur.xmax, sy); + immVertex2f(pos, v2d->cur.xmin, sy - layout->attribute_column_header_h); + immVertex2f(pos, v2d->cur.xmax, sy - layout->attribute_column_header_h); + immEnd(); + immUnbindProgram(); + } +} + +/** + * Updates the stat string stored in file->entry if necessary. + */ +static const char *filelist_get_details_column_string(FileAttributeColumnType column, + const FileDirEntry *file, + const bool small_size, + const bool update_stat_strings) +{ + switch (column) { + case COLUMN_DATETIME: + if (!(file->typeflag & FILE_TYPE_BLENDERLIB) && !FILENAME_IS_CURRPAR(file->relpath)) { + if ((file->entry->datetime_str[0] == '\0') || update_stat_strings) { + char date[FILELIST_DIRENTRY_DATE_LEN], time[FILELIST_DIRENTRY_TIME_LEN]; + bool is_today, is_yesterday; + + BLI_filelist_entry_datetime_to_string( + NULL, file->entry->time, small_size, time, date, &is_today, &is_yesterday); + + if (is_today || is_yesterday) { + BLI_strncpy(date, is_today ? N_("Today") : N_("Yesterday"), sizeof(date)); + } + BLI_snprintf( + file->entry->datetime_str, sizeof(file->entry->datetime_str), "%s %s", date, time); + } + + return file->entry->datetime_str; + } + break; + case COLUMN_SIZE: + if ((file->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) || + !(file->typeflag & (FILE_TYPE_DIR | FILE_TYPE_BLENDERLIB))) { + if ((file->entry->size_str[0] == '\0') || update_stat_strings) { + BLI_filelist_entry_size_to_string( + NULL, file->entry->size, small_size, file->entry->size_str); + } + + return file->entry->size_str; + } + break; + default: + break; + } + + return NULL; +} + +static void draw_details_columns(const FileSelectParams *params, + const FileLayout *layout, + const FileDirEntry *file, + const int pos_x, + const int pos_y, + const uchar text_col[4]) +{ + const bool small_size = SMALL_SIZE_CHECK(params->thumbnail_size); + const bool update_stat_strings = small_size != SMALL_SIZE_CHECK(layout->curr_size); + int sx = pos_x - layout->tile_border_x - (UI_UNIT_X * 0.1f), sy = pos_y; + + for (FileAttributeColumnType column_type = 0; column_type < ATTRIBUTE_COLUMN_MAX; + column_type++) { + const FileAttributeColumn *column = &layout->attribute_columns[column_type]; + + /* Name column is not a detail column (should already be drawn), always skip here. */ + if (column_type == COLUMN_NAME) { + sx += column->width; + continue; + } + if (!file_attribute_column_type_enabled(params, column_type)) { + continue; + } + + const char *str = filelist_get_details_column_string( + column_type, file, small_size, update_stat_strings); + + if (str) { + file_draw_string(sx + ATTRIBUTE_COLUMN_PADDING, + sy - layout->tile_border_y, + IFACE_(str), + column->width - 2 * ATTRIBUTE_COLUMN_PADDING, + layout->tile_h, + column->text_align, + text_col); + } + + sx += column->width; + } +} + void file_draw_list(const bContext *C, ARegion *ar) { SpaceFile *sfile = CTX_wm_space_file(C); @@ -652,18 +643,14 @@ void file_draw_list(const bContext *C, ARegion *ar) bool is_icon; eFontStyle_Align align; bool do_drag; - int column_space = 0.6f * UI_UNIT_X; unsigned char text_col[4]; - const bool small_size = SMALL_SIZE_CHECK(params->thumbnail_size); - const bool update_stat_strings = small_size != SMALL_SIZE_CHECK(layout->curr_size); - const float thumb_icon_aspect = sqrtf(64.0f / (float)(params->thumbnail_size)); + const bool draw_columnheader = (params->display == FILE_VERTICALDISPLAY); + const float thumb_icon_aspect = MIN2(64.0f / (float)(params->thumbnail_size), 1.0f); numfiles = filelist_files_ensure(files); if (params->display != FILE_IMGDISPLAY) { - draw_background(layout, v2d); - draw_dividers(layout, v2d); } @@ -679,13 +666,14 @@ void file_draw_list(const bContext *C, ARegion *ar) numfiles_layout += layout->rows; } else { - numfiles_layout += layout->columns; + numfiles_layout += layout->flow_columns; } filelist_file_cache_slidingwindow_set(files, numfiles_layout); - textwidth = (FILE_IMGDISPLAY == params->display) ? layout->tile_w : - (int)layout->column_widths[COLUMN_NAME]; + textwidth = (FILE_IMGDISPLAY == params->display) ? + layout->tile_w : + round_fl_to_int(layout->attribute_columns[COLUMN_NAME].width); textheight = (int)(layout->textheight * 3.0 / 2.0 + 0.5); align = (FILE_IMGDISPLAY == params->display) ? UI_STYLE_TEXT_CENTER : UI_STYLE_TEXT_LEFT; @@ -719,11 +707,16 @@ void file_draw_list(const bContext *C, ARegion *ar) BLF_batch_draw_begin(); + UI_GetThemeColor4ubv(TH_TEXT, text_col); + for (i = offset; (i < numfiles) && (i < offset + numfiles_layout); i++) { unsigned int file_selflag; char path[FILE_MAX_LIBEXTRA]; + int padx = 0.1f * UI_UNIT_X; + int icon_ofs = 0; + ED_fileselect_layout_tilepos(layout, i, &sx, &sy); - sx += (int)(v2d->tot.xmin + 0.1f * UI_UNIT_X); + sx += (int)(v2d->tot.xmin + padx); sy = (int)(v2d->tot.ymax - sy); file = filelist_file(files, i); @@ -737,15 +730,14 @@ void file_draw_list(const bContext *C, ARegion *ar) int colorid = (file_selflag & FILE_SEL_SELECTED) ? TH_HILITE : TH_BACK; int shade = (params->highlight_file == i) || (file_selflag & FILE_SEL_HIGHLIGHTED) ? 35 : 0; + const short width = ELEM(params->display, FILE_VERTICALDISPLAY, FILE_HORIZONTALDISPLAY) ? + layout->tile_w - (2 * padx) : + layout->tile_w; BLI_assert(i == 0 || !FILENAME_IS_CURRPAR(file->relpath)); - draw_tile(sx, - sy - 1, - layout->tile_w + 4, - sfile->layout->tile_h + layout->tile_border_y, - colorid, - shade); + draw_tile( + sx, sy - 1, width, sfile->layout->tile_h + layout->tile_border_y, colorid, shade); } } UI_draw_roundbox_corner_set(UI_CNR_NONE); @@ -778,38 +770,28 @@ void file_draw_list(const bContext *C, ARegion *ar) file_draw_icon(block, path, sx, - sy - (UI_UNIT_Y / 6), + sy - layout->tile_border_y, filelist_geticon(files, i, true), ICON_DEFAULT_WIDTH_SCALE, ICON_DEFAULT_HEIGHT_SCALE, do_drag); - sx += ICON_DEFAULT_WIDTH_SCALE + 0.2f * UI_UNIT_X; + icon_ofs += ICON_DEFAULT_WIDTH_SCALE + 0.2f * UI_UNIT_X; } - UI_GetThemeColor4ubv(TH_TEXT, text_col); - if (file_selflag & FILE_SEL_EDITING) { uiBut *but; - short width; - - if (params->display == FILE_SHORTDISPLAY) { - width = layout->tile_w - (ICON_DEFAULT_WIDTH_SCALE + 0.2f * UI_UNIT_X); - } - else if (params->display == FILE_LONGDISPLAY) { - width = layout->column_widths[COLUMN_NAME] + (column_space * 3.5f); - } - else { - BLI_assert(params->display == FILE_IMGDISPLAY); - width = textwidth; - } + const short width = (params->display == FILE_IMGDISPLAY) ? + textwidth : + layout->attribute_columns[COLUMN_NAME].width - + ATTRIBUTE_COLUMN_PADDING; but = uiDefBut(block, UI_BTYPE_TEXT, 1, "", - sx, + sx + icon_ofs, sy - layout->tile_h - 0.15f * UI_UNIT_X, - width, + width - icon_ofs, textheight, sfile->params->renamefile, 1.0f, @@ -825,74 +807,19 @@ void file_draw_list(const bContext *C, ARegion *ar) sfile->files, file, FILE_SEL_REMOVE, FILE_SEL_EDITING, CHECK_ALL); } } - - if (!(file_selflag & FILE_SEL_EDITING)) { - int tpos = (FILE_IMGDISPLAY == params->display) ? sy - layout->tile_h + layout->textheight : - sy; - file_draw_string(sx + 1, tpos, file->name, (float)textwidth, textheight, align, text_col); - } - - sx += (int)layout->column_widths[COLUMN_NAME] + column_space; - if (params->display == FILE_SHORTDISPLAY) { - if ((file->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) || - !(file->typeflag & (FILE_TYPE_DIR | FILE_TYPE_BLENDERLIB))) { - if ((file->entry->size_str[0] == '\0') || update_stat_strings) { - BLI_filelist_entry_size_to_string( - NULL, file->entry->size, small_size, file->entry->size_str); - } - file_draw_string(sx, - sy, - file->entry->size_str, - layout->column_widths[COLUMN_SIZE], - layout->tile_h, - align, - text_col); - } - sx += (int)layout->column_widths[COLUMN_SIZE] + column_space; + else { + const int txpos = (params->display == FILE_IMGDISPLAY) ? sx : sx + 1 + icon_ofs; + const int typos = (params->display == FILE_IMGDISPLAY) ? + sy - layout->tile_h + layout->textheight : + sy - layout->tile_border_y; + const int twidth = (params->display == FILE_IMGDISPLAY) ? + textwidth : + textwidth - 1 - icon_ofs - padx - layout->tile_border_x; + file_draw_string(txpos, typos, file->name, (float)twidth, textheight, align, text_col); } - else if (params->display == FILE_LONGDISPLAY) { - if (!(file->typeflag & FILE_TYPE_BLENDERLIB) && !FILENAME_IS_CURRPAR(file->relpath)) { - if ((file->entry->date_str[0] == '\0') || update_stat_strings) { - BLI_filelist_entry_datetime_to_string( - NULL, file->entry->time, small_size, file->entry->time_str, file->entry->date_str); - } - file_draw_string(sx, - sy, - file->entry->date_str, - layout->column_widths[COLUMN_DATE], - layout->tile_h, - align, - text_col); - sx += (int)layout->column_widths[COLUMN_DATE] + column_space; - file_draw_string(sx, - sy, - file->entry->time_str, - layout->column_widths[COLUMN_TIME], - layout->tile_h, - align, - text_col); - sx += (int)layout->column_widths[COLUMN_TIME] + column_space; - } - else { - sx += (int)layout->column_widths[COLUMN_DATE] + column_space; - sx += (int)layout->column_widths[COLUMN_TIME] + column_space; - } - if ((file->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) || - !(file->typeflag & (FILE_TYPE_DIR | FILE_TYPE_BLENDERLIB))) { - if ((file->entry->size_str[0] == '\0') || update_stat_strings) { - BLI_filelist_entry_size_to_string( - NULL, file->entry->size, small_size, file->entry->size_str); - } - file_draw_string(sx, - sy, - file->entry->size_str, - layout->column_widths[COLUMN_SIZE], - layout->tile_h, - align, - text_col); - } - sx += (int)layout->column_widths[COLUMN_SIZE] + column_space; + if (params->display != FILE_IMGDISPLAY) { + draw_details_columns(params, layout, file, sx, sy, text_col); } } @@ -901,5 +828,11 @@ void file_draw_list(const bContext *C, ARegion *ar) UI_block_end(C, block); UI_block_draw(C, block); + /* Draw last, on top of file list. */ + if (draw_columnheader) { + draw_columnheader_background(layout, v2d); + draw_columnheader_columns(params, layout, v2d, text_col); + } + layout->curr_size = params->thumbnail_size; } diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h index bad25511dd5..61f13098783 100644 --- a/source/blender/editors/space_file/file_intern.h +++ b/source/blender/editors/space_file/file_intern.h @@ -30,9 +30,11 @@ struct ARegion; struct ARegionType; struct FileSelectParams; struct SpaceFile; +struct View2D; /* file_ops.c */ struct ARegion *file_tools_region(struct ScrArea *sa); +struct ARegion *file_tool_props_region(struct ScrArea *sa); /* file_draw.c */ #define TILE_BORDER_X (UI_UNIT_X / 4) @@ -42,9 +44,10 @@ struct ARegion *file_tools_region(struct ScrArea *sa); #define IMASEL_BUTTONS_HEIGHT (UI_UNIT_Y * 2) #define IMASEL_BUTTONS_MARGIN (UI_UNIT_Y / 6) +#define ATTRIBUTE_COLUMN_PADDING (0.5f * UI_UNIT_X) + #define SMALL_SIZE_CHECK(_size) ((_size) < 64) /* Related to FileSelectParams.thumbnail_size. */ -void file_draw_buttons(const bContext *C, ARegion *ar); void file_calc_previews(const bContext *C, ARegion *ar); void file_draw_list(const bContext *C, ARegion *ar); @@ -64,6 +67,7 @@ typedef enum WalkSelectDirection { } WalkSelectDirections; void FILE_OT_highlight(struct wmOperatorType *ot); +void FILE_OT_sort_column_ui_context(struct wmOperatorType *ot); void FILE_OT_select(struct wmOperatorType *ot); void FILE_OT_select_walk(struct wmOperatorType *ot); void FILE_OT_select_all(struct wmOperatorType *ot); @@ -112,6 +116,16 @@ void file_operator_to_sfile(bContext *C, struct SpaceFile *sfile, struct wmOpera /* filesel.c */ void fileselect_file_set(SpaceFile *sfile, const int index); +bool file_attribute_column_type_enabled(const FileSelectParams *params, + FileAttributeColumnType column); +bool file_attribute_column_header_is_inside(const struct View2D *v2d, + const FileLayout *layout, + int x, + int y); +FileAttributeColumnType file_attribute_column_type_find_isect(const View2D *v2d, + const FileSelectParams *params, + FileLayout *layout, + int x); float file_string_width(const char *str); float file_font_pointsize(void); diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index eb5f02b6e13..5168300d21e 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -78,7 +78,12 @@ static FileSelection find_file_mouse_rect(SpaceFile *sfile, ARegion *ar, const r BLI_rctf_rcti_copy(&rect_region_fl, rect_region); + /* Okay, manipulating v2d rects here is hacky... */ + v2d->mask.ymax -= sfile->layout->offset_top; + v2d->cur.ymax -= sfile->layout->offset_top; UI_view2d_region_to_view_rctf(v2d, &rect_region_fl, &rect_view_fl); + v2d->mask.ymax += sfile->layout->offset_top; + v2d->cur.ymax += sfile->layout->offset_top; BLI_rcti_init(&rect_view, (int)(v2d->tot.xmin + rect_view_fl.xmin), @@ -190,7 +195,6 @@ static FileSelect file_select_do(bContext *C, int selected_idx, bool do_diropen) const bool is_parent_dir = FILENAME_IS_PARENT(file->relpath); if (do_diropen == false) { - params->file[0] = '\0'; retval = FILE_SELECT_DIR; } /* the path is too long and we are not going up! */ @@ -262,8 +266,8 @@ static void file_ensure_inside_viewbounds(ARegion *ar, SpaceFile *sfile, const i cur->ymax = cur->ymin + ar->winy; } /* up */ - else if (cur->ymax < rect.ymax) { - cur->ymax = rect.ymax + layout->tile_border_y; + else if ((cur->ymax - layout->offset_top) < rect.ymax) { + cur->ymax = rect.ymax + layout->tile_border_y + layout->offset_top; cur->ymin = cur->ymax - ar->winy; } /* left - also use if tile is wider than viewbounds so view is aligned to file name */ @@ -278,7 +282,7 @@ static void file_ensure_inside_viewbounds(ARegion *ar, SpaceFile *sfile, const i } else { BLI_assert(cur->xmin <= rect.xmin && cur->xmax >= rect.xmax && cur->ymin <= rect.ymin && - cur->ymax >= rect.ymax); + (cur->ymax - layout->offset_top) >= rect.ymax); changed = false; } @@ -384,7 +388,7 @@ static int file_box_select_modal(bContext *C, wmOperator *op, const wmEvent *eve if (result == OPERATOR_RUNNING_MODAL) { WM_operator_properties_border_to_rcti(op, &rect); - BLI_rcti_isect(&(ar->v2d.mask), &rect, &rect); + ED_fileselect_layout_isect_rect(sfile->layout, &ar->v2d, &rect, &rect); sel = file_selection_get(C, &rect, 0); if ((sel.first != params->sel_first) || (sel.last != params->sel_last)) { @@ -440,13 +444,13 @@ static int file_box_select_exec(bContext *C, wmOperator *op) file_deselect_all(sfile, FILE_SEL_SELECTED); } - BLI_rcti_isect(&(ar->v2d.mask), &rect, &rect); + ED_fileselect_layout_isect_rect(sfile->layout, &ar->v2d, &rect, &rect); ret = file_select(C, &rect, select ? FILE_SEL_ADD : FILE_SEL_REMOVE, false, false); /* unselect '..' parent entry - it's not supposed to be selected if more than * one file is selected */ - filelist_entry_select_index_set(sfile->files, 0, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL); + filelist_entry_parent_select_set(sfile->files, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL); if (FILE_SELECT_DIR == ret) { WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL); @@ -493,7 +497,7 @@ static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) rect.xmin = rect.xmax = event->mval[0]; rect.ymin = rect.ymax = event->mval[1]; - if (!BLI_rcti_isect_pt(&ar->v2d.mask, rect.xmin, rect.ymin)) { + if (!ED_fileselect_layout_is_inside_pt(sfile->layout, &ar->v2d, rect.xmin, rect.ymin)) { return OPERATOR_CANCELLED; } @@ -514,8 +518,7 @@ static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) if (extend) { /* unselect '..' parent entry - it's not supposed to be selected if more * than one file is selected */ - filelist_entry_select_index_set( - sfile->files, 0, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL); + filelist_entry_parent_select_set(sfile->files, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL); } if (FILE_SELECT_DIR == ret) { @@ -580,6 +583,11 @@ static bool file_walk_select_selection_set(bContext *C, BLI_assert(params); + if (numfiles == 0) { + /* No files visible, nothing to do. */ + return false; + } + if (has_selection) { if (extend && filelist_entry_select_index_get(files, active_old, CHECK_ALL) && filelist_entry_select_index_get(files, active_new, CHECK_ALL)) { @@ -609,7 +617,7 @@ static bool file_walk_select_selection_set(bContext *C, } /* select first file */ else if (ELEM(direction, FILE_SELECT_WALK_DOWN, FILE_SELECT_WALK_RIGHT)) { - params->active_file = active = extend ? 1 : 0; + params->active_file = active = 0; } else { BLI_assert(0); @@ -626,7 +634,7 @@ static bool file_walk_select_selection_set(bContext *C, /* unselect '..' parent entry - it's not supposed to be selected if more * than one file is selected */ - filelist_entry_select_index_set(files, 0, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL); + filelist_entry_parent_select_set(files, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL); } else { /* deselect all first */ @@ -641,11 +649,6 @@ static bool file_walk_select_selection_set(bContext *C, if (fill) { FileSelection sel = {MIN2(active, last_sel), MAX2(active, last_sel)}; - /* clamping selection to not include '..' parent entry */ - if (sel.first == 0) { - sel.first = 1; - } - /* fill selection between last and first selected file */ filelist_entries_select_index_range_set( files, &sel, deselect ? FILE_SEL_REMOVE : FILE_SEL_ADD, FILE_SEL_SELECTED, CHECK_ALL); @@ -653,6 +656,12 @@ static bool file_walk_select_selection_set(bContext *C, if (deselect) { filelist_entry_select_index_set(files, active, FILE_SEL_ADD, FILE_SEL_SELECTED, CHECK_ALL); } + + /* unselect '..' parent entry - it's not supposed to be selected if more + * than one file is selected */ + if ((sel.last - sel.first) > 1) { + filelist_entry_parent_select_set(files, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL); + } } else { filelist_entry_select_index_set( @@ -688,10 +697,15 @@ static bool file_walk_select_do(bContext *C, /* *** get all needed files for handling selection *** */ + if (numfiles == 0) { + /* No files visible, nothing to do. */ + return false; + } + if (has_selection) { ARegion *ar = CTX_wm_region(C); FileLayout *layout = ED_fileselect_get_layout(sfile, ar); - const int idx_shift = (layout->flag & FILE_LAYOUT_HOR) ? layout->rows : layout->columns; + const int idx_shift = (layout->flag & FILE_LAYOUT_HOR) ? layout->rows : layout->flow_columns; if ((layout->flag & FILE_LAYOUT_HOR && direction == FILE_SELECT_WALK_UP) || (layout->flag & FILE_LAYOUT_VER && direction == FILE_SELECT_WALK_LEFT)) { @@ -718,7 +732,7 @@ static bool file_walk_select_do(bContext *C, BLI_assert(0); } - if (!IN_RANGE(active_new, 0, numfiles)) { + if (!IN_RANGE(active_new, -1, numfiles)) { if (extend) { /* extend to invalid file -> abort */ return false; @@ -1185,7 +1199,7 @@ int file_highlight_set(SpaceFile *sfile, ARegion *ar, int mx, int my) mx -= ar->winrct.xmin; my -= ar->winrct.ymin; - if (BLI_rcti_isect_pt(&ar->v2d.mask, mx, my)) { + if (ED_fileselect_layout_is_inside_pt(sfile->layout, v2d, mx, my)) { float fx, fy; int highlight_file; @@ -1234,6 +1248,53 @@ void FILE_OT_highlight(struct wmOperatorType *ot) ot->poll = ED_operator_file_active; } +static int file_column_sort_ui_context_invoke(bContext *C, + wmOperator *UNUSED(op), + const wmEvent *event) +{ + const ARegion *ar = CTX_wm_region(C); + SpaceFile *sfile = CTX_wm_space_file(C); + + if (file_attribute_column_header_is_inside( + &ar->v2d, sfile->layout, event->mval[0], event->mval[1])) { + const FileAttributeColumnType column_type = file_attribute_column_type_find_isect( + &ar->v2d, sfile->params, sfile->layout, event->mval[0]); + + if (column_type != COLUMN_NONE) { + const FileAttributeColumn *column = &sfile->layout->attribute_columns[column_type]; + + if (column->sort_type != FILE_SORT_NONE) { + if (sfile->params->sort == column->sort_type) { + /* Already sorting by selected column -> toggle sort invert (three state logic). */ + sfile->params->flag ^= FILE_SORT_INVERT; + } + else { + sfile->params->sort = column->sort_type; + sfile->params->flag &= ~FILE_SORT_INVERT; + } + + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); + } + } + } + + return OPERATOR_PASS_THROUGH; +} + +void FILE_OT_sort_column_ui_context(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Sort from Column"; + ot->description = "Change sorting to use column under cursor"; + ot->idname = "FILE_OT_sort_column_ui_context"; + + /* api callbacks */ + ot->invoke = file_column_sort_ui_context_invoke; + ot->poll = ED_operator_file_active; + + ot->flag = OPTYPE_INTERNAL; +} + int file_cancel_exec(bContext *C, wmOperator *UNUSED(unused)) { wmWindowManager *wm = CTX_wm_manager(C); @@ -1713,7 +1774,7 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w /* Number of items in a block (i.e. lines in a column in horizontal layout, or columns in a line * in vertical layout). */ - const int items_block_size = is_horizontal ? sfile->layout->rows : sfile->layout->columns; + const int items_block_size = is_horizontal ? sfile->layout->rows : sfile->layout->flow_columns; /* Scroll offset is the first file in the row/column we are editing in. */ if (sfile->scroll_offset == 0) { @@ -1998,7 +2059,6 @@ void FILE_OT_directory_new(struct wmOperatorType *ot) ot->idname = "FILE_OT_directory_new"; /* api callbacks */ - ot->invoke = WM_operator_confirm; ot->exec = file_directory_new_exec; ot->poll = ED_operator_file_active; /* <- important, handler is on window level */ @@ -2260,10 +2320,29 @@ ARegion *file_tools_region(ScrArea *sa) arnew->regiontype = RGN_TYPE_TOOLS; arnew->alignment = RGN_ALIGN_LEFT; - ar = MEM_callocN(sizeof(ARegion), "tool props for file"); - BLI_insertlinkafter(&sa->regionbase, arnew, ar); - ar->regiontype = RGN_TYPE_TOOL_PROPS; - ar->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV; + return arnew; +} + +ARegion *file_tool_props_region(ScrArea *sa) +{ + ARegion *ar, *arnew; + + if ((ar = BKE_area_find_region_type(sa, RGN_TYPE_TOOL_PROPS)) != NULL) { + return ar; + } + + /* add subdiv level; after execute region */ + ar = BKE_area_find_region_type(sa, RGN_TYPE_EXECUTE); + + /* is error! */ + if (ar == NULL) { + return NULL; + } + + arnew = MEM_callocN(sizeof(ARegion), "tool props for file"); + BLI_insertlinkafter(&sa->regionbase, ar, arnew); + arnew->regiontype = RGN_TYPE_TOOL_PROPS; + arnew->alignment = RGN_ALIGN_RIGHT; return arnew; } @@ -2292,6 +2371,17 @@ void FILE_OT_bookmark_toggle(struct wmOperatorType *ot) ot->poll = ED_operator_file_active; /* <- important, handler is on window level */ } +static bool file_filenum_poll(bContext *C) +{ + SpaceFile *sfile = CTX_wm_space_file(C); + + if (!ED_operator_file_active(C)) { + return false; + } + + return sfile->params && (sfile->params->action_type == FILE_SAVE); +} + /** * Looks for a string of digits within name (using BLI_stringdec) and adjusts it by add. */ @@ -2349,7 +2439,7 @@ void FILE_OT_filenum(struct wmOperatorType *ot) /* api callbacks */ ot->exec = file_filenum_exec; - ot->poll = ED_operator_file_active; /* <- important, handler is on window level */ + ot->poll = file_filenum_poll; /* props */ RNA_def_int(ot->srna, "increment", 1, -100, 100, "Increment", "", -100, 100); diff --git a/source/blender/editors/space_file/file_panels.c b/source/blender/editors/space_file/file_panels.c index d9a6e70121f..b41358f575f 100644 --- a/source/blender/editors/space_file/file_panels.c +++ b/source/blender/editors/space_file/file_panels.c @@ -103,6 +103,7 @@ void file_panels_register(ARegionType *art) strcpy(pt->idname, "FILE_PT_operator"); strcpy(pt->label, N_("Operator")); strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); + pt->flag = PNL_NO_HEADER; pt->poll = file_panel_operator_poll; pt->draw_header = file_panel_operator_header; pt->draw = file_panel_operator; diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index f7dda1defe8..46302e0d087 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -329,25 +329,20 @@ enum { FL_IS_PENDING = 1 << 2, FL_NEED_SORTING = 1 << 3, FL_NEED_FILTERING = 1 << 4, + FL_SORT_INVERT = 1 << 5, }; -#define SPECIAL_IMG_SIZE 48 -#define SPECIAL_IMG_ROWS 4 -#define SPECIAL_IMG_COLS 4 +#define SPECIAL_IMG_SIZE 256 +#define SPECIAL_IMG_ROWS 1 +#define SPECIAL_IMG_COLS 6 enum { - SPECIAL_IMG_FOLDER = 0, - SPECIAL_IMG_PARENT = 1, - SPECIAL_IMG_REFRESH = 2, - SPECIAL_IMG_BLENDFILE = 3, - SPECIAL_IMG_SOUNDFILE = 4, - SPECIAL_IMG_MOVIEFILE = 5, - SPECIAL_IMG_PYTHONFILE = 6, - SPECIAL_IMG_TEXTFILE = 7, - SPECIAL_IMG_FONTFILE = 8, - SPECIAL_IMG_UNKNOWNFILE = 9, - SPECIAL_IMG_LOADING = 10, - SPECIAL_IMG_BACKUP = 11, + SPECIAL_IMG_DOCUMENT = 0, + SPECIAL_IMG_FOLDER = 1, + SPECIAL_IMG_PARENT = 2, + SPECIAL_IMG_DRIVE_FIXED = 3, + SPECIAL_IMG_DRIVE_ATTACHED = 4, + SPECIAL_IMG_DRIVE_REMOTE = 5, SPECIAL_IMG_MAX, }; @@ -369,6 +364,19 @@ static void filelist_cache_clear(FileListEntryCache *cache, size_t new_size); /* ********** Sort helpers ********** */ +struct FileSortData { + bool inverted; +}; + +static int compare_apply_inverted(int val, const struct FileSortData *sort_data) +{ + return sort_data->inverted ? -val : val; +} + +/** + * Handles inverted sorting itself (currently there's nothing to invert), so if this returns non-0, + * it should be used as-is and not inverted. + */ static int compare_direntry_generic(const FileListInternEntry *entry1, const FileListInternEntry *entry2) { @@ -420,10 +428,11 @@ static int compare_direntry_generic(const FileListInternEntry *entry1, return 0; } -static int compare_name(void *UNUSED(user_data), const void *a1, const void *a2) +static int compare_name(void *user_data, const void *a1, const void *a2) { const FileListInternEntry *entry1 = a1; const FileListInternEntry *entry2 = a2; + const struct FileSortData *sort_data = user_data; char *name1, *name2; int ret; @@ -434,13 +443,14 @@ static int compare_name(void *UNUSED(user_data), const void *a1, const void *a2) name1 = entry1->name; name2 = entry2->name; - return BLI_natstrcmp(name1, name2); + return compare_apply_inverted(BLI_strcasecmp_natural(name1, name2), sort_data); } -static int compare_date(void *UNUSED(user_data), const void *a1, const void *a2) +static int compare_date(void *user_data, const void *a1, const void *a2) { const FileListInternEntry *entry1 = a1; const FileListInternEntry *entry2 = a2; + const struct FileSortData *sort_data = user_data; char *name1, *name2; int64_t time1, time2; int ret; @@ -452,22 +462,23 @@ static int compare_date(void *UNUSED(user_data), const void *a1, const void *a2) time1 = (int64_t)entry1->st.st_mtime; time2 = (int64_t)entry2->st.st_mtime; if (time1 < time2) { - return 1; + return compare_apply_inverted(1, sort_data); } if (time1 > time2) { - return -1; + return compare_apply_inverted(-1, sort_data); } name1 = entry1->name; name2 = entry2->name; - return BLI_natstrcmp(name1, name2); + return compare_apply_inverted(BLI_strcasecmp_natural(name1, name2), sort_data); } -static int compare_size(void *UNUSED(user_data), const void *a1, const void *a2) +static int compare_size(void *user_data, const void *a1, const void *a2) { const FileListInternEntry *entry1 = a1; const FileListInternEntry *entry2 = a2; + const struct FileSortData *sort_data = user_data; char *name1, *name2; uint64_t size1, size2; int ret; @@ -479,22 +490,23 @@ static int compare_size(void *UNUSED(user_data), const void *a1, const void *a2) size1 = entry1->st.st_size; size2 = entry2->st.st_size; if (size1 < size2) { - return 1; + return compare_apply_inverted(1, sort_data); } if (size1 > size2) { - return -1; + return compare_apply_inverted(-1, sort_data); } name1 = entry1->name; name2 = entry2->name; - return BLI_natstrcmp(name1, name2); + return compare_apply_inverted(BLI_strcasecmp_natural(name1, name2), sort_data); } -static int compare_extension(void *UNUSED(user_data), const void *a1, const void *a2) +static int compare_extension(void *user_data, const void *a1, const void *a2) { const FileListInternEntry *entry1 = a1; const FileListInternEntry *entry2 = a2; + const struct FileSortData *sort_data = user_data; char *name1, *name2; int ret; @@ -516,10 +528,10 @@ static int compare_extension(void *UNUSED(user_data), const void *a1, const void return -1; } if (entry1->blentype < entry2->blentype) { - return -1; + return compare_apply_inverted(-1, sort_data); } if (entry1->blentype > entry2->blentype) { - return 1; + return compare_apply_inverted(1, sort_data); } } else { @@ -539,48 +551,58 @@ static int compare_extension(void *UNUSED(user_data), const void *a1, const void } if ((ret = BLI_strcasecmp(sufix1, sufix2))) { - return ret; + return compare_apply_inverted(ret, sort_data); } } name1 = entry1->name; name2 = entry2->name; - return BLI_natstrcmp(name1, name2); + return compare_apply_inverted(BLI_strcasecmp_natural(name1, name2), sort_data); } void filelist_sort(struct FileList *filelist) { if ((filelist->flags & FL_NEED_SORTING) && (filelist->sort != FILE_SORT_NONE)) { + void *sort_cb = NULL; + switch (filelist->sort) { case FILE_SORT_ALPHA: - BLI_listbase_sort_r(&filelist->filelist_intern.entries, compare_name, NULL); + sort_cb = compare_name; break; case FILE_SORT_TIME: - BLI_listbase_sort_r(&filelist->filelist_intern.entries, compare_date, NULL); + sort_cb = compare_date; break; case FILE_SORT_SIZE: - BLI_listbase_sort_r(&filelist->filelist_intern.entries, compare_size, NULL); + sort_cb = compare_size; break; case FILE_SORT_EXTENSION: - BLI_listbase_sort_r(&filelist->filelist_intern.entries, compare_extension, NULL); + sort_cb = compare_extension; break; case FILE_SORT_NONE: /* Should never reach this point! */ default: BLI_assert(0); break; } + BLI_listbase_sort_r( + &filelist->filelist_intern.entries, + sort_cb, + &(struct FileSortData){.inverted = (filelist->flags & FL_SORT_INVERT) != 0}); filelist_filter_clear(filelist); filelist->flags &= ~FL_NEED_SORTING; } } -void filelist_setsorting(struct FileList *filelist, const short sort) +void filelist_setsorting(struct FileList *filelist, const short sort, bool invert_sort) { - if (filelist->sort != sort) { + const bool was_invert_sort = filelist->flags & FL_SORT_INVERT; + + if ((filelist->sort != sort) || (was_invert_sort != invert_sort)) { filelist->sort = sort; filelist->flags |= FL_NEED_SORTING; + filelist->flags = invert_sort ? (filelist->flags | FL_SORT_INVERT) : + (filelist->flags & ~FL_SORT_INVERT); } } @@ -635,9 +657,9 @@ static bool is_filtered_file(FileListInternEntry *file, { bool is_filtered = !is_hidden_file(file->relpath, filter); - if (is_filtered && (filter->flags & FLF_DO_FILTER) && !FILENAME_IS_CURRPAR(file->relpath)) { + if (is_filtered && !FILENAME_IS_CURRPAR(file->relpath)) { /* We only check for types if some type are enabled in filtering. */ - if (filter->filter) { + if (filter->filter && (filter->flags & FLF_DO_FILTER)) { if (file->typeflag & FILE_TYPE_DIR) { if (file->typeflag & (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) { @@ -657,6 +679,7 @@ static bool is_filtered_file(FileListInternEntry *file, } } } + /* If there's a filter string, apply it as filter even if FLF_DO_FILTER is not set. */ if (is_filtered && (filter->filter_search[0] != '\0')) { if (fnmatch(filter->filter_search, file->relpath, FNM_CASEFOLD) != 0) { is_filtered = false; @@ -676,9 +699,9 @@ static bool is_filtered_lib(FileListInternEntry *file, const char *root, FileLis if (BLO_library_path_explode(path, dir, &group, &name)) { is_filtered = !is_hidden_file(file->relpath, filter); - if (is_filtered && (filter->flags & FLF_DO_FILTER) && !FILENAME_IS_CURRPAR(file->relpath)) { + if (is_filtered && !FILENAME_IS_CURRPAR(file->relpath)) { /* We only check for types if some type are enabled in filtering. */ - if (filter->filter || filter->filter_id) { + if ((filter->filter || filter->filter_id) && (filter->flags & FLF_DO_FILTER)) { if (file->typeflag & FILE_TYPE_DIR) { if (file->typeflag & (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) { @@ -704,6 +727,7 @@ static bool is_filtered_lib(FileListInternEntry *file, const char *root, FileLis } } } + /* If there's a filter string, apply it as filter even if FLF_DO_FILTER is not set. */ if (is_filtered && (filter->filter_search[0] != '\0')) { if (fnmatch(filter->filter_search, file->relpath, FNM_CASEFOLD) != 0) { is_filtered = false; @@ -904,42 +928,12 @@ static ImBuf *filelist_geticon_image_ex(const unsigned int typeflag, const char if (FILENAME_IS_PARENT(relpath)) { ibuf = gSpecialFileImages[SPECIAL_IMG_PARENT]; } - else if (FILENAME_IS_CURRENT(relpath)) { - ibuf = gSpecialFileImages[SPECIAL_IMG_REFRESH]; - } else { ibuf = gSpecialFileImages[SPECIAL_IMG_FOLDER]; } } - else if (typeflag & FILE_TYPE_BLENDER) { - ibuf = gSpecialFileImages[SPECIAL_IMG_BLENDFILE]; - } - else if (typeflag & FILE_TYPE_BLENDERLIB) { - ibuf = gSpecialFileImages[SPECIAL_IMG_UNKNOWNFILE]; - } - else if (typeflag & (FILE_TYPE_MOVIE)) { - ibuf = gSpecialFileImages[SPECIAL_IMG_MOVIEFILE]; - } - else if (typeflag & FILE_TYPE_SOUND) { - ibuf = gSpecialFileImages[SPECIAL_IMG_SOUNDFILE]; - } - else if (typeflag & FILE_TYPE_PYSCRIPT) { - ibuf = gSpecialFileImages[SPECIAL_IMG_PYTHONFILE]; - } - else if (typeflag & FILE_TYPE_FTFONT) { - ibuf = gSpecialFileImages[SPECIAL_IMG_FONTFILE]; - } - else if (typeflag & FILE_TYPE_TEXT) { - ibuf = gSpecialFileImages[SPECIAL_IMG_TEXTFILE]; - } - else if (typeflag & FILE_TYPE_IMAGE) { - ibuf = gSpecialFileImages[SPECIAL_IMG_LOADING]; - } - else if (typeflag & FILE_TYPE_BLENDER_BACKUP) { - ibuf = gSpecialFileImages[SPECIAL_IMG_BACKUP]; - } else { - ibuf = gSpecialFileImages[SPECIAL_IMG_UNKNOWNFILE]; + ibuf = gSpecialFileImages[SPECIAL_IMG_DOCUMENT]; } return ibuf; @@ -1001,10 +995,13 @@ static int filelist_geticon_ex(const int typeflag, return ICON_FILE_BLANK; } else if (typeflag & FILE_TYPE_COLLADA) { - return ICON_FILE_BLANK; + return ICON_FILE_3D; } else if (typeflag & FILE_TYPE_ALEMBIC) { - return ICON_FILE_BLANK; + return ICON_FILE_3D; + } + else if (typeflag & FILE_TYPE_OBJECT_IO) { + return ICON_FILE_3D; } else if (typeflag & FILE_TYPE_TEXT) { return ICON_FILE_TEXT; @@ -1243,7 +1240,8 @@ static void filelist_cache_previews_clear(FileListEntryCache *cache) BLI_task_pool_cancel(cache->previews_pool); while ((preview = BLI_thread_queue_pop_timeout(cache->previews_done, 0))) { - // printf("%s: DONE %d - %s - %p\n", __func__, preview->index, preview->path, preview->img); + // printf("%s: DONE %d - %s - %p\n", __func__, preview->index, preview->path, + // preview->img); if (preview->img) { IMB_freeImBuf(preview->img); } @@ -2128,6 +2126,9 @@ int ED_path_extension_type(const char *path) else if (BLI_path_extension_check(path, ".abc")) { return FILE_TYPE_ALEMBIC; } + else if (BLI_path_extension_check_n(path, ".obj", ".3ds", ".fbx", ".glb", ".gltf", NULL)) { + return FILE_TYPE_OBJECT_IO; + } else if (BLI_path_extension_check_array(path, imb_ext_image)) { return FILE_TYPE_IMAGE; } @@ -2177,9 +2178,9 @@ int ED_file_extension_icon(const char *path) case FILE_TYPE_BTX: return ICON_FILE_BLANK; case FILE_TYPE_COLLADA: - return ICON_FILE_BLANK; case FILE_TYPE_ALEMBIC: - return ICON_FILE_BLANK; + case FILE_TYPE_OBJECT_IO: + return ICON_FILE_3D; case FILE_TYPE_TEXT: return ICON_FILE_TEXT; default: @@ -2298,6 +2299,19 @@ unsigned int filelist_entry_select_index_get(FileList *filelist, return 0; } +/** + * Set selection of the '..' parent entry, but only if it's actually visible. + */ +void filelist_entry_parent_select_set(FileList *filelist, + FileSelType select, + unsigned int flag, + FileCheckType check) +{ + if ((filelist->filter_data.flags & FLF_HIDE_PARENT) == 0) { + filelist_entry_select_index_set(filelist, 0, select, flag, check); + } +} + /* WARNING! dir must be FILE_MAX_LIBEXTRA long! */ bool filelist_islibrary(struct FileList *filelist, char *dir, char **group) { diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h index caf77246797..9b1107294ff 100644 --- a/source/blender/editors/space_file/filelist.h +++ b/source/blender/editors/space_file/filelist.h @@ -55,7 +55,7 @@ void folderlist_pushdir(struct ListBase *folderlist, const char *dir); const char *folderlist_peeklastdir(struct ListBase *folderdist); int folderlist_clear_next(struct SpaceFile *sfile); -void filelist_setsorting(struct FileList *filelist, const short sort); +void filelist_setsorting(struct FileList *filelist, const short sort, bool invert_sort); void filelist_sort(struct FileList *filelist); void filelist_setfilter_options(struct FileList *filelist, @@ -117,6 +117,10 @@ unsigned int filelist_entry_select_get(struct FileList *filelist, unsigned int filelist_entry_select_index_get(struct FileList *filelist, const int index, FileCheckType check); +void filelist_entry_parent_select_set(struct FileList *filelist, + FileSelType select, + unsigned int flag, + FileCheckType check); void filelist_setrecursion(struct FileList *filelist, const int recursion_level); diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index db42d007b8e..3223fe0c6ce 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -49,6 +49,8 @@ #include "BLI_utildefines.h" #include "BLI_fnmatch.h" +#include "BLT_translation.h" + #include "BKE_appdir.h" #include "BKE_context.h" #include "BKE_main.h" @@ -69,6 +71,8 @@ #include "file_intern.h" #include "filelist.h" +#define VERTLIST_MAJORCOLUMN_WIDTH (25 * UI_UNIT_X) + FileSelectParams *ED_fileselect_get_params(struct SpaceFile *sfile) { if (!sfile->params) { @@ -99,6 +103,8 @@ short ED_fileselect_set_params(SpaceFile *sfile) sfile->params->filter_glob[0] = '\0'; /* set the default thumbnails size */ sfile->params->thumbnail_size = 128; + /* Show size column by default. */ + sfile->params->details_flags = FILE_DETAILS_SIZE | FILE_DETAILS_DATETIME; } params = sfile->params; @@ -161,6 +167,10 @@ short ED_fileselect_set_params(SpaceFile *sfile) params->flag &= ~FILE_DIRSEL_ONLY; } + if ((prop = RNA_struct_find_property(op->ptr, "hide_props_region"))) { + params->flag |= RNA_property_boolean_get(op->ptr, prop) ? FILE_HIDE_TOOL_PROPS : 0; + } + params->filter = 0; if ((prop = RNA_struct_find_property(op->ptr, "filter_blender"))) { params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_BLENDER : 0; @@ -261,6 +271,10 @@ short ED_fileselect_set_params(SpaceFile *sfile) params->sort = FILE_SORT_ALPHA; } + if ((prop = RNA_struct_find_property(op->ptr, "action_type"))) { + params->action_type = RNA_property_enum_get(op->ptr, prop); + } + if (params->display == FILE_DEFAULTDISPLAY) { if (params->display_previous == FILE_DEFAULTDISPLAY) { if (U.uiflag & USER_SHOW_THUMBNAILS) { @@ -268,11 +282,11 @@ short ED_fileselect_set_params(SpaceFile *sfile) params->display = FILE_IMGDISPLAY; } else { - params->display = FILE_SHORTDISPLAY; + params->display = FILE_VERTICALDISPLAY; } } else { - params->display = FILE_SHORTDISPLAY; + params->display = FILE_VERTICALDISPLAY; } } else { @@ -293,7 +307,7 @@ short ED_fileselect_set_params(SpaceFile *sfile) params->type = FILE_UNIX; params->flag |= FILE_HIDE_DOT; params->flag &= ~FILE_DIRSEL_ONLY; - params->display = FILE_SHORTDISPLAY; + params->display = FILE_VERTICALDISPLAY; params->display_previous = FILE_DEFAULTDISPLAY; params->sort = FILE_SORT_ALPHA; params->filter = 0; @@ -344,7 +358,7 @@ void ED_fileselect_reset_params(SpaceFile *sfile) void fileselect_file_set(SpaceFile *sfile, const int index) { const struct FileDirEntry *file = filelist_file(sfile->files, index); - if (file && file->relpath && file->relpath[0] && !(file->typeflag & FILE_TYPE_FOLDER)) { + if (file && file->relpath && file->relpath[0] && !(file->typeflag & FILE_TYPE_DIR)) { BLI_strncpy(sfile->params->file, file->relpath, FILE_MAXFILE); } } @@ -372,10 +386,10 @@ int ED_fileselect_layout_numfiles(FileLayout *layout, ARegion *ar) } else { const int y_item = layout->tile_h + (2 * layout->tile_border_y); - const int y_view = (int)(BLI_rctf_size_y(&ar->v2d.cur)); + const int y_view = (int)(BLI_rctf_size_y(&ar->v2d.cur)) - layout->offset_top; const int y_over = y_item - (y_view % y_item); numfiles = (int)((float)(y_view + y_over) / (float)(y_item)); - return numfiles * layout->columns; + return numfiles * layout->flow_columns; } } @@ -395,19 +409,19 @@ FileSelection ED_fileselect_layout_offset_rect(FileLayout *layout, const rcti *r } colmin = (rect->xmin) / (layout->tile_w + 2 * layout->tile_border_x); - rowmin = (rect->ymin) / (layout->tile_h + 2 * layout->tile_border_y); + rowmin = (rect->ymin - layout->offset_top) / (layout->tile_h + 2 * layout->tile_border_y); colmax = (rect->xmax) / (layout->tile_w + 2 * layout->tile_border_x); - rowmax = (rect->ymax) / (layout->tile_h + 2 * layout->tile_border_y); + rowmax = (rect->ymax - layout->offset_top) / (layout->tile_h + 2 * layout->tile_border_y); - if (is_inside(colmin, rowmin, layout->columns, layout->rows) || - is_inside(colmax, rowmax, layout->columns, layout->rows)) { - CLAMP(colmin, 0, layout->columns - 1); + if (is_inside(colmin, rowmin, layout->flow_columns, layout->rows) || + is_inside(colmax, rowmax, layout->flow_columns, layout->rows)) { + CLAMP(colmin, 0, layout->flow_columns - 1); CLAMP(rowmin, 0, layout->rows - 1); - CLAMP(colmax, 0, layout->columns - 1); + CLAMP(colmax, 0, layout->flow_columns - 1); CLAMP(rowmax, 0, layout->rows - 1); } - if ((colmin > layout->columns - 1) || (rowmin > layout->rows - 1)) { + if ((colmin > layout->flow_columns - 1) || (rowmin > layout->rows - 1)) { sel.first = -1; } else { @@ -415,10 +429,10 @@ FileSelection ED_fileselect_layout_offset_rect(FileLayout *layout, const rcti *r sel.first = layout->rows * colmin + rowmin; } else { - sel.first = colmin + layout->columns * rowmin; + sel.first = colmin + layout->flow_columns * rowmin; } } - if ((colmax > layout->columns - 1) || (rowmax > layout->rows - 1)) { + if ((colmax > layout->flow_columns - 1) || (rowmax > layout->rows - 1)) { sel.last = -1; } else { @@ -426,7 +440,7 @@ FileSelection ED_fileselect_layout_offset_rect(FileLayout *layout, const rcti *r sel.last = layout->rows * colmax + rowmax; } else { - sel.last = colmax + layout->columns * rowmax; + sel.last = colmax + layout->flow_columns * rowmax; } } @@ -443,9 +457,9 @@ int ED_fileselect_layout_offset(FileLayout *layout, int x, int y) } offsetx = (x) / (layout->tile_w + 2 * layout->tile_border_x); - offsety = (y) / (layout->tile_h + 2 * layout->tile_border_y); + offsety = (y - layout->offset_top) / (layout->tile_h + 2 * layout->tile_border_y); - if (offsetx > layout->columns - 1) { + if (offsetx > layout->flow_columns - 1) { return -1; } if (offsety > layout->rows - 1) { @@ -456,25 +470,121 @@ int ED_fileselect_layout_offset(FileLayout *layout, int x, int y) active_file = layout->rows * offsetx + offsety; } else { - active_file = offsetx + layout->columns * offsety; + active_file = offsetx + layout->flow_columns * offsety; } return active_file; } +/** + * Get the currently visible bounds of the layout in screen space. Matches View2D.mask minus the + * top column-header row. + */ +void ED_fileselect_layout_maskrect(const FileLayout *layout, const View2D *v2d, rcti *r_rect) +{ + *r_rect = v2d->mask; + r_rect->ymax -= layout->offset_top; +} + +bool ED_fileselect_layout_is_inside_pt(const FileLayout *layout, const View2D *v2d, int x, int y) +{ + rcti maskrect; + ED_fileselect_layout_maskrect(layout, v2d, &maskrect); + return BLI_rcti_isect_pt(&maskrect, x, y); +} + +bool ED_fileselect_layout_isect_rect(const FileLayout *layout, + const View2D *v2d, + const rcti *rect, + rcti *r_dst) +{ + rcti maskrect; + ED_fileselect_layout_maskrect(layout, v2d, &maskrect); + return BLI_rcti_isect(&maskrect, rect, r_dst); +} + void ED_fileselect_layout_tilepos(FileLayout *layout, int tile, int *x, int *y) { if (layout->flag == FILE_LAYOUT_HOR) { *x = layout->tile_border_x + (tile / layout->rows) * (layout->tile_w + 2 * layout->tile_border_x); - *y = layout->tile_border_y + + *y = layout->offset_top + layout->tile_border_y + (tile % layout->rows) * (layout->tile_h + 2 * layout->tile_border_y); } else { *x = layout->tile_border_x + - ((tile) % layout->columns) * (layout->tile_w + 2 * layout->tile_border_x); - *y = layout->tile_border_y + - ((tile) / layout->columns) * (layout->tile_h + 2 * layout->tile_border_y); + ((tile) % layout->flow_columns) * (layout->tile_w + 2 * layout->tile_border_x); + *y = layout->offset_top + layout->tile_border_y + + ((tile) / layout->flow_columns) * (layout->tile_h + 2 * layout->tile_border_y); + } +} + +/** + * Check if the region coordinate defined by \a x and \a y are inside the column header. + */ +bool file_attribute_column_header_is_inside(const View2D *v2d, + const FileLayout *layout, + int x, + int y) +{ + rcti header_rect = v2d->mask; + header_rect.ymin = header_rect.ymax - layout->attribute_column_header_h; + return BLI_rcti_isect_pt(&header_rect, x, y); +} + +bool file_attribute_column_type_enabled(const FileSelectParams *params, + FileAttributeColumnType column) +{ + switch (column) { + case COLUMN_NAME: + /* Always enabled */ + return true; + case COLUMN_DATETIME: + return (params->details_flags & FILE_DETAILS_DATETIME) != 0; + case COLUMN_SIZE: + return (params->details_flags & FILE_DETAILS_SIZE) != 0; + default: + return false; + } +} + +/** + * Find the column type at region coordinate given by \a x (y doesn't matter for this). + */ +FileAttributeColumnType file_attribute_column_type_find_isect(const View2D *v2d, + const FileSelectParams *params, + FileLayout *layout, + int x) +{ + float mx, my; + int offset_tile; + + UI_view2d_region_to_view(v2d, x, v2d->mask.ymax - layout->offset_top - 1, &mx, &my); + offset_tile = ED_fileselect_layout_offset( + layout, (int)(v2d->tot.xmin + mx), (int)(v2d->tot.ymax - my)); + if (offset_tile > -1) { + int tile_x, tile_y; + int pos_x = 0; + int rel_x; /* x relative to the hovered tile */ + + ED_fileselect_layout_tilepos(layout, offset_tile, &tile_x, &tile_y); + /* Column header drawing doesn't use left tile border, so subtract it. */ + rel_x = mx - (tile_x - layout->tile_border_x); + + for (FileAttributeColumnType column = 0; column < ATTRIBUTE_COLUMN_MAX; column++) { + if (!file_attribute_column_type_enabled(params, column)) { + continue; + } + const int width = layout->attribute_columns[column].width; + + if (IN_RANGE(rel_x, pos_x, pos_x + width)) { + return column; + } + + pos_x += width; + } } + + return COLUMN_NONE; } float file_string_width(const char *str) @@ -512,20 +622,52 @@ float file_font_pointsize(void) #endif } -static void column_widths(FileSelectParams *params, struct FileLayout *layout) +static void file_attribute_columns_widths(const FileSelectParams *params, FileLayout *layout) { - int i; + FileAttributeColumn *columns = layout->attribute_columns; const bool small_size = SMALL_SIZE_CHECK(params->thumbnail_size); + const int pad = small_size ? 0 : ATTRIBUTE_COLUMN_PADDING * 2; - for (i = 0; i < MAX_FILE_COLUMN; ++i) { - layout->column_widths[i] = 0; + for (int i = 0; i < ATTRIBUTE_COLUMN_MAX; ++i) { + layout->attribute_columns[i].width = 0; } - layout->column_widths[COLUMN_NAME] = ((float)params->thumbnail_size / 8.0f) * UI_UNIT_X; /* Biggest possible reasonable values... */ - layout->column_widths[COLUMN_DATE] = file_string_width(small_size ? "23/08/89" : "23-Dec-89"); - layout->column_widths[COLUMN_TIME] = file_string_width("23:59"); - layout->column_widths[COLUMN_SIZE] = file_string_width(small_size ? "98.7 M" : "98.7 MiB"); + columns[COLUMN_DATETIME].width = file_string_width(small_size ? "23/08/89" : + "23 Dec 6789, 23:59") + + pad; + columns[COLUMN_SIZE].width = file_string_width(small_size ? "98.7 M" : "098.7 MB") + pad; + if (params->display == FILE_IMGDISPLAY) { + columns[COLUMN_NAME].width = ((float)params->thumbnail_size / 8.0f) * UI_UNIT_X; + } + /* Name column uses remaining width */ + else { + int remwidth = layout->tile_w; + for (FileAttributeColumnType column_type = ATTRIBUTE_COLUMN_MAX - 1; column_type >= 0; + column_type--) { + if ((column_type == COLUMN_NAME) || + !file_attribute_column_type_enabled(params, column_type)) { + continue; + } + remwidth -= columns[column_type].width; + } + columns[COLUMN_NAME].width = remwidth; + } +} + +static void file_attribute_columns_init(const FileSelectParams *params, FileLayout *layout) +{ + file_attribute_columns_widths(params, layout); + + layout->attribute_columns[COLUMN_NAME].name = N_("Name"); + layout->attribute_columns[COLUMN_NAME].sort_type = FILE_SORT_ALPHA; + layout->attribute_columns[COLUMN_NAME].text_align = UI_STYLE_TEXT_LEFT; + layout->attribute_columns[COLUMN_DATETIME].name = N_("Date Modified"); + layout->attribute_columns[COLUMN_DATETIME].sort_type = FILE_SORT_TIME; + layout->attribute_columns[COLUMN_DATETIME].text_align = UI_STYLE_TEXT_LEFT; + layout->attribute_columns[COLUMN_SIZE].name = N_("Size"); + layout->attribute_columns[COLUMN_SIZE].sort_type = FILE_SORT_SIZE; + layout->attribute_columns[COLUMN_SIZE].text_align = UI_STYLE_TEXT_RIGHT; } void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *ar) @@ -533,7 +675,6 @@ void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *ar) FileSelectParams *params = ED_fileselect_get_params(sfile); FileLayout *layout = NULL; View2D *v2d = &ar->v2d; - int maxlen = 0; int numfiles; int textheight; @@ -560,57 +701,66 @@ void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *ar) layout->tile_w = layout->prv_w + 2 * layout->prv_border_x; layout->tile_h = layout->prv_h + 2 * layout->prv_border_y + textheight; layout->width = (int)(BLI_rctf_size_x(&v2d->cur) - 2 * layout->tile_border_x); - layout->columns = layout->width / (layout->tile_w + 2 * layout->tile_border_x); - if (layout->columns > 0) { - layout->rows = numfiles / layout->columns + 1; // XXX dirty, modulo is zero + layout->flow_columns = layout->width / (layout->tile_w + 2 * layout->tile_border_x); + layout->attribute_column_header_h = 0; + layout->offset_top = 0; + if (layout->flow_columns > 0) { + layout->rows = numfiles / layout->flow_columns + 1; // XXX dirty, modulo is zero } else { - layout->columns = 1; + layout->flow_columns = 1; layout->rows = numfiles + 1; // XXX dirty, modulo is zero } layout->height = sfile->layout->rows * (layout->tile_h + 2 * layout->tile_border_y) + - layout->tile_border_y * 2; + layout->tile_border_y * 2 - layout->offset_top; layout->flag = FILE_LAYOUT_VER; } - else { - int column_space = 0.6f * UI_UNIT_X; - int column_icon_space = 0.2f * UI_UNIT_X; + else if (params->display == FILE_VERTICALDISPLAY) { + int rowcount; - layout->prv_w = 0; - layout->prv_h = 0; + layout->prv_w = ((float)params->thumbnail_size / 20.0f) * UI_UNIT_X; + layout->prv_h = ((float)params->thumbnail_size / 20.0f) * UI_UNIT_Y; + layout->tile_border_x = 0.4f * UI_UNIT_X; + layout->tile_border_y = 0.1f * UI_UNIT_Y; + layout->tile_h = textheight * 3 / 2; + layout->width = (int)(BLI_rctf_size_x(&v2d->cur) - 2 * layout->tile_border_x); + layout->tile_w = layout->width; + layout->flow_columns = 1; + layout->attribute_column_header_h = layout->tile_h * 1.2f + 2 * layout->tile_border_y; + layout->offset_top = layout->attribute_column_header_h; + rowcount = (int)(BLI_rctf_size_y(&v2d->cur) - layout->offset_top - 2 * layout->tile_border_y) / + (layout->tile_h + 2 * layout->tile_border_y); + file_attribute_columns_init(params, layout); + + layout->rows = MAX2(rowcount, numfiles); + BLI_assert(layout->rows != 0); + layout->height = sfile->layout->rows * (layout->tile_h + 2 * layout->tile_border_y) + + layout->tile_border_y * 2 + layout->offset_top; + layout->flag = FILE_LAYOUT_VER; + } + else if (params->display == FILE_HORIZONTALDISPLAY) { + layout->prv_w = ((float)params->thumbnail_size / 20.0f) * UI_UNIT_X; + layout->prv_h = ((float)params->thumbnail_size / 20.0f) * UI_UNIT_Y; layout->tile_border_x = 0.4f * UI_UNIT_X; layout->tile_border_y = 0.1f * UI_UNIT_Y; - layout->prv_border_x = 0; - layout->prv_border_y = 0; layout->tile_h = textheight * 3 / 2; + layout->attribute_column_header_h = 0; + layout->offset_top = layout->attribute_column_header_h; layout->height = (int)(BLI_rctf_size_y(&v2d->cur) - 2 * layout->tile_border_y); /* Padding by full scrollbar H is too much, can overlap tile border Y. */ layout->rows = (layout->height - V2D_SCROLL_HEIGHT + layout->tile_border_y) / (layout->tile_h + 2 * layout->tile_border_y); + layout->tile_w = VERTLIST_MAJORCOLUMN_WIDTH; + file_attribute_columns_init(params, layout); - column_widths(params, layout); - - if (params->display == FILE_SHORTDISPLAY) { - maxlen = ICON_DEFAULT_WIDTH_SCALE + column_icon_space + - (int)layout->column_widths[COLUMN_NAME] + column_space + - (int)layout->column_widths[COLUMN_SIZE] + column_space; - } - else { - maxlen = ICON_DEFAULT_WIDTH_SCALE + column_icon_space + - (int)layout->column_widths[COLUMN_NAME] + column_space + - (int)layout->column_widths[COLUMN_DATE] + column_space + - (int)layout->column_widths[COLUMN_TIME] + column_space + - (int)layout->column_widths[COLUMN_SIZE] + column_space; - } - layout->tile_w = maxlen; if (layout->rows > 0) { - layout->columns = numfiles / layout->rows + 1; // XXX dirty, modulo is zero + layout->flow_columns = numfiles / layout->rows + 1; // XXX dirty, modulo is zero } else { layout->rows = 1; - layout->columns = numfiles + 1; // XXX dirty, modulo is zero + layout->flow_columns = numfiles + 1; // XXX dirty, modulo is zero } - layout->width = sfile->layout->columns * (layout->tile_w + 2 * layout->tile_border_x) + + layout->width = sfile->layout->flow_columns * (layout->tile_w + 2 * layout->tile_border_x) + layout->tile_border_x * 2; layout->flag = FILE_LAYOUT_HOR; } diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 1fd878e4662..1befdd52d7d 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -72,23 +72,40 @@ static SpaceLink *file_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scen /* Ignore user preference "USER_HEADER_BOTTOM" here (always show top for new types). */ ar->alignment = RGN_ALIGN_TOP; + /* ui list region */ + ar = MEM_callocN(sizeof(ARegion), "ui region for file"); + BLI_addtail(&sfile->regionbase, ar); + ar->regiontype = RGN_TYPE_UI; + ar->alignment = RGN_ALIGN_TOP; + ar->flag |= RGN_FLAG_DYNAMIC_SIZE; + /* Tools region */ ar = MEM_callocN(sizeof(ARegion), "tools region for file"); BLI_addtail(&sfile->regionbase, ar); ar->regiontype = RGN_TYPE_TOOLS; ar->alignment = RGN_ALIGN_LEFT; + /* Tools region (lower split region) */ + ar = MEM_callocN(sizeof(ARegion), "lower tools region for file"); + BLI_addtail(&sfile->regionbase, ar); + ar->regiontype = RGN_TYPE_TOOLS; + ar->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV; + ar->flag |= RGN_FLAG_DYNAMIC_SIZE; + + /* Execute region */ + ar = MEM_callocN(sizeof(ARegion), "execute region for file"); + BLI_addtail(&sfile->regionbase, ar); + ar->regiontype = RGN_TYPE_EXECUTE; + ar->alignment = RGN_ALIGN_BOTTOM; + ar->flag |= RGN_FLAG_DYNAMIC_SIZE; + /* Tool props region is added as needed. */ +#if 0 /* Tool props (aka operator) region */ ar = MEM_callocN(sizeof(ARegion), "tool props region for file"); BLI_addtail(&sfile->regionbase, ar); ar->regiontype = RGN_TYPE_TOOL_PROPS; - ar->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV; - - /* ui list region */ - ar = MEM_callocN(sizeof(ARegion), "ui region for file"); - BLI_addtail(&sfile->regionbase, ar); - ar->regiontype = RGN_TYPE_UI; - ar->alignment = RGN_ALIGN_TOP; + ar->alignment = RGN_ALIGN_RIGHT; +#endif /* main region */ ar = MEM_callocN(sizeof(ARegion), "main region for file"); @@ -204,6 +221,7 @@ static SpaceLink *file_duplicate(SpaceLink *sl) static void file_refresh(const bContext *C, ScrArea *sa) { wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win = CTX_wm_window(C); SpaceFile *sfile = CTX_wm_space_file(C); FileSelectParams *params = ED_fileselect_get_params(sfile); struct FSMenu *fsmenu = ED_fsmenu_get(); @@ -217,15 +235,16 @@ static void file_refresh(const bContext *C, ScrArea *sa) } filelist_setdir(sfile->files, params->dir); filelist_setrecursion(sfile->files, params->recursion_level); - filelist_setsorting(sfile->files, params->sort); - filelist_setfilter_options(sfile->files, - (params->flag & FILE_FILTER) != 0, - (params->flag & FILE_HIDE_DOT) != 0, - false, /* TODO hide_parent, should be controllable? */ - params->filter, - params->filter_id, - params->filter_glob, - params->filter_search); + filelist_setsorting(sfile->files, params->sort, params->flag & FILE_SORT_INVERT); + filelist_setfilter_options( + sfile->files, + (params->flag & FILE_FILTER) != 0, + (params->flag & FILE_HIDE_DOT) != 0, + true, /* Just always hide parent, prefer to not add an extra user option for this. */ + params->filter, + params->filter_id, + params->filter_glob, + params->filter_search); /* Update the active indices of bookmarks & co. */ sfile->systemnr = fsmenu_get_active_indices(fsmenu, FS_CATEGORY_SYSTEM, params->dir); @@ -254,7 +273,7 @@ static void file_refresh(const bContext *C, ScrArea *sa) else { filelist_cache_previews_set(sfile->files, false); if (sfile->previews_timer) { - WM_event_remove_timer_notifier(wm, CTX_wm_window(C), sfile->previews_timer); + WM_event_remove_timer_notifier(wm, win, sfile->previews_timer); sfile->previews_timer = NULL; } } @@ -269,10 +288,20 @@ static void file_refresh(const bContext *C, ScrArea *sa) /* Might be called with NULL sa, see file_main_region_draw() below. */ if (sa && BKE_area_find_region_type(sa, RGN_TYPE_TOOLS) == NULL) { - /* Create TOOLS/TOOL_PROPS regions. */ + /* Create TOOLS region. */ file_tools_region(sa); - ED_area_initialize(wm, CTX_wm_window(C), sa); + ED_area_initialize(wm, win, sa); + } + if (sa && sfile->op && BKE_area_find_region_type(sa, RGN_TYPE_TOOL_PROPS) == NULL) { + /* Create TOOL_PROPS region. */ + ARegion *region_props = file_tool_props_region(sa); + + if (params->flag & FILE_HIDE_TOOL_PROPS) { + region_props->flag |= RGN_FLAG_HIDDEN; + } + + ED_area_initialize(wm, win, sa); } ED_area_tag_redraw(sa); @@ -406,6 +435,11 @@ static void file_main_region_draw(const bContext *C, ARegion *ar) v2d->keepofs &= ~V2D_LOCKOFS_Y; v2d->keepofs |= V2D_LOCKOFS_X; } + else if (params->display == FILE_VERTICALDISPLAY) { + v2d->scroll = V2D_SCROLL_RIGHT; + v2d->keepofs &= ~V2D_LOCKOFS_Y; + v2d->keepofs |= V2D_LOCKOFS_X; + } else { v2d->scroll = V2D_SCROLL_BOTTOM; v2d->keepofs &= ~V2D_LOCKOFS_X; @@ -439,7 +473,9 @@ static void file_main_region_draw(const bContext *C, ARegion *ar) UI_view2d_view_restore(C); /* scrollers */ - scrollers = UI_view2d_scrollers_calc(v2d, NULL); + rcti view_rect; + ED_fileselect_layout_maskrect(sfile->layout, v2d, &view_rect); + scrollers = UI_view2d_scrollers_calc(v2d, &view_rect); UI_view2d_scrollers_draw(v2d, scrollers); UI_view2d_scrollers_free(scrollers); } @@ -452,6 +488,7 @@ static void file_operatortypes(void) WM_operatortype_append(FILE_OT_select_box); WM_operatortype_append(FILE_OT_select_bookmark); WM_operatortype_append(FILE_OT_highlight); + WM_operatortype_append(FILE_OT_sort_column_ui_context); WM_operatortype_append(FILE_OT_execute); WM_operatortype_append(FILE_OT_cancel); WM_operatortype_append(FILE_OT_parent); @@ -538,7 +575,8 @@ static void file_ui_region_init(wmWindowManager *wm, ARegion *ar) { wmKeyMap *keymap; - UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy); + ED_region_panels_init(wm, ar); + ar->v2d.keepzoom |= V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y; /* own keymap */ keymap = WM_keymap_ensure(wm->defaultconf, "File Browser", SPACE_FILE, 0); @@ -550,22 +588,18 @@ static void file_ui_region_init(wmWindowManager *wm, ARegion *ar) static void file_ui_region_draw(const bContext *C, ARegion *ar) { - float col[3]; - /* clear */ - UI_GetThemeColor3fv(TH_BACK, col); - GPU_clear_color(col[0], col[1], col[2], 0.0); - GPU_clear(GPU_COLOR_BIT); - - /* scrolling here is just annoying, disable it */ - ar->v2d.cur.ymax = BLI_rctf_size_y(&ar->v2d.cur); - ar->v2d.cur.ymin = 0; - - /* set view2d view matrix for scrolling (without scrollers) */ - UI_view2d_view_ortho(&ar->v2d); + ED_region_panels(C, ar); +} - file_draw_buttons(C, ar); +static void file_execution_region_init(wmWindowManager *wm, ARegion *ar) +{ + ED_region_panels_init(wm, ar); + ar->v2d.keepzoom |= V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y; +} - UI_view2d_view_restore(C); +static void file_execution_region_draw(const bContext *C, ARegion *ar) +{ + ED_region_panels(C, ar); } static void file_ui_region_listener(wmWindow *UNUSED(win), @@ -656,13 +690,21 @@ void ED_spacetype_file(void) /* regions: ui */ art = MEM_callocN(sizeof(ARegionType), "spacetype file region"); art->regionid = RGN_TYPE_UI; - art->prefsizey = 60; art->keymapflag = ED_KEYMAP_UI; art->listener = file_ui_region_listener; art->init = file_ui_region_init; art->draw = file_ui_region_draw; BLI_addhead(&st->regiontypes, art); + /* regions: execution */ + art = MEM_callocN(sizeof(ARegionType), "spacetype file region"); + art->regionid = RGN_TYPE_EXECUTE; + art->keymapflag = ED_KEYMAP_UI; + art->listener = file_ui_region_listener; + art->init = file_execution_region_init; + art->draw = file_execution_region_draw; + BLI_addhead(&st->regiontypes, art); + /* regions: channels (directories) */ art = MEM_callocN(sizeof(ARegionType), "spacetype file region"); art->regionid = RGN_TYPE_TOOLS; @@ -677,8 +719,8 @@ void ED_spacetype_file(void) /* regions: tool properties */ art = MEM_callocN(sizeof(ARegionType), "spacetype file operator region"); art->regionid = RGN_TYPE_TOOL_PROPS; - art->prefsizex = 0; - art->prefsizey = 360; + art->prefsizex = 240; + art->prefsizey = 60; art->keymapflag = ED_KEYMAP_UI; art->listener = file_tools_region_listener; art->init = file_tools_region_init; diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index c727c5225c9..708d91a82bb 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -861,6 +861,11 @@ static void graph_panel_driverVar__transChan(uiLayout *layout, ID *id, DriverVar sub = uiLayoutColumn(layout, true); uiItemR(sub, &dtar_ptr, "transform_type", 0, NULL, ICON_NONE); + + if (ELEM(dtar->transChan, DTAR_TRANSCHAN_ROTX, DTAR_TRANSCHAN_ROTY, DTAR_TRANSCHAN_ROTZ)) { + uiItemR(sub, &dtar_ptr, "rotation_mode", 0, IFACE_("Mode"), ICON_NONE); + } + uiItemR(sub, &dtar_ptr, "transform_space", 0, IFACE_("Space"), ICON_NONE); } @@ -1236,7 +1241,7 @@ static void graph_panel_drivers_popover(const bContext *C, Panel *pa) { uiLayout *layout = pa->layout; - PointerRNA ptr = {{NULL}}; + PointerRNA ptr = {NULL}; PropertyRNA *prop = NULL; int index = -1; uiBut *but = NULL; @@ -1258,7 +1263,7 @@ static void graph_panel_drivers_popover(const bContext *C, Panel *pa) /* Populate Panel - With a combination of the contents of the Driven and Driver panels */ if (fcu && fcu->driver) { - ID *id = ptr.id.data; + ID *id = ptr.owner_id; PointerRNA ptr_fcurve; RNA_pointer_create(id, &RNA_FCurve, fcu, &ptr_fcurve); diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c index e7ba498fc11..e18a440f7c0 100644 --- a/source/blender/editors/space_graph/graph_draw.c +++ b/source/blender/editors/space_graph/graph_draw.c @@ -205,7 +205,7 @@ static void draw_fcurve_keyframe_vertices(FCurve *fcu, View2D *v2d, bool edit, u { immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); - immUniform1f("size", UI_GetThemeValuef(TH_VERTEX_SIZE) * U.pixelsize); + immUniform1f("size", UI_GetThemeValuef(TH_VERTEX_SIZE) * U.dpi_fac); draw_fcurve_selected_keyframe_vertices(fcu, v2d, edit, false, pos); draw_fcurve_selected_keyframe_vertices(fcu, v2d, edit, true, pos); @@ -269,8 +269,8 @@ static void draw_fcurve_handle_vertices(FCurve *fcu, immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA); /* set handle size */ - immUniform1f("size", (1.4f * UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE)) * U.pixelsize); - immUniform1f("outlineWidth", 1.5f * U.pixelsize); + immUniform1f("size", (1.4f * UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE)) * U.dpi_fac); + immUniform1f("outlineWidth", 1.5f * U.dpi_fac); draw_fcurve_selected_handle_vertices(fcu, v2d, false, sel_handle_only, pos); draw_fcurve_selected_handle_vertices(fcu, v2d, true, sel_handle_only, pos); diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index b624e21937f..329067de545 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -1538,7 +1538,7 @@ void GRAPH_OT_sound_bake(wmOperatorType *ot) FILE_TYPE_FOLDER | FILE_TYPE_SOUND | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE, - WM_FILESEL_FILEPATH, + WM_FILESEL_FILEPATH | WM_FILESEL_SHOW_PROPS, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); RNA_def_float(ot->srna, diff --git a/source/blender/editors/space_graph/graph_intern.h b/source/blender/editors/space_graph/graph_intern.h index 168c38b66a4..320240221b5 100644 --- a/source/blender/editors/space_graph/graph_intern.h +++ b/source/blender/editors/space_graph/graph_intern.h @@ -26,7 +26,6 @@ struct ARegion; struct ARegionType; -struct ScrArea; struct SpaceGraph; struct bAnimContext; struct bAnimListElem; diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index 6c5ebf77bf4..91e5ab61dd9 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -527,7 +527,7 @@ static void graph_region_message_subscribe(const struct bContext *UNUSED(C), * so just whitelist the entire structs for updates */ { - wmMsgParams_RNA msg_key_params = {{{0}}}; + wmMsgParams_RNA msg_key_params = {{0}}; StructRNA *type_array[] = { &RNA_DopeSheet, /* dopesheet filters */ diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index f1a29a1542d..64e1c02590e 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -991,7 +991,7 @@ void uiTemplateImage(uiLayout *layout, void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, bool color_management) { ImageFormatData *imf = imfptr->data; - ID *id = imfptr->id.data; + ID *id = imfptr->owner_id; PointerRNA display_settings_ptr; PropertyRNA *prop; const int depth_ok = BKE_imtype_valid_depths(imf->imtype); diff --git a/source/blender/editors/space_image/image_intern.h b/source/blender/editors/space_image/image_intern.h index 2c723f45e94..1abb6715fdb 100644 --- a/source/blender/editors/space_image/image_intern.h +++ b/source/blender/editors/space_image/image_intern.h @@ -27,7 +27,6 @@ /* internal exports only */ struct ARegion; struct ARegionType; -struct ScrArea; struct SpaceImage; struct bContext; struct bNodeTree; diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 05ba82b8bde..e338a450db6 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1431,7 +1431,7 @@ static int image_open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED( Image *oldima; oldptr = RNA_property_pointer_get(&ptr, prop); - oldima = (Image *)oldptr.id.data; + oldima = (Image *)oldptr.owner_id; /* unlikely to fail but better avoid strange crash */ if (oldima && GS(oldima->id.name) == ID_IM) { ima = oldima; @@ -1773,6 +1773,7 @@ static int image_save_options_init(Main *bmain, } else { BLI_snprintf(opts->filepath, sizeof(opts->filepath), "//%s", ima->id.name + 2); + BLI_path_make_safe(opts->filepath); BLI_path_abs(opts->filepath, is_prev_save ? G.ima : BKE_main_blendfile_path(bmain)); } } diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 33e77d3623e..5fa4fe3e077 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -586,7 +586,7 @@ static void image_main_region_draw(const bContext *C, ARegion *ar) float col[3]; /* XXX This is in order to draw UI batches with the DRW - * olg context since we now use it for drawing the entire area */ + * old context since we now use it for drawing the entire area. */ gpu_batch_presets_reset(); GPUViewport *viewport = diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c index 946274de882..106edc290d5 100644 --- a/source/blender/editors/space_info/info_stats.c +++ b/source/blender/editors/space_info/info_stats.c @@ -574,7 +574,7 @@ void ED_info_stats_clear(ViewLayer *view_layer) const char *ED_info_stats_string(Main *bmain, Scene *scene, ViewLayer *view_layer) { - /* Loopin through dependency graph when interface is locked in not safe. + /* Looping through dependency graph when interface is locked in not safe. * Thew interface is marked as locked when jobs wants to modify the * dependency graph. */ wmWindowManager *wm = bmain->wm.first; diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c index 24d3008b1e7..97d5faa9c13 100644 --- a/source/blender/editors/space_info/textview.c +++ b/source/blender/editors/space_info/textview.c @@ -313,7 +313,7 @@ int textview_draw( /* constants for the sequencer context */ cdc.font_id = font_id; cdc.cwidth = (int)BLF_fixed_width(font_id); - assert(cdc.cwidth > 0); + BLI_assert(cdc.cwidth > 0); cdc.lheight = tvc->lheight; cdc.lofs = -BLF_descender(font_id); /* note, scroll bar must be already subtracted () */ diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c index 719efc7eeac..126b20a028e 100644 --- a/source/blender/editors/space_nla/nla_buttons.c +++ b/source/blender/editors/space_nla/nla_buttons.c @@ -268,8 +268,8 @@ static void nla_panel_animdata(const bContext *C, Panel *pa) /* icon + id-block name of block where AnimData came from to prevent * accidentally changing the properties of the wrong action */ - if (adt_ptr.id.data) { - ID *id = adt_ptr.id.data; + if (adt_ptr.owner_id) { + ID *id = adt_ptr.owner_id; PointerRNA id_ptr; RNA_id_pointer_create(id, &id_ptr); @@ -513,7 +513,7 @@ static void nla_panel_modifiers(const bContext *C, Panel *pa) for (fcm = strip->modifiers.first; fcm; fcm = fcm->next) { col = uiLayoutColumn(pa->layout, true); - ANIM_uiTemplate_fmodifier_draw(col, strip_ptr.id.data, &strip->modifiers, fcm); + ANIM_uiTemplate_fmodifier_draw(col, strip_ptr.owner_id, &strip->modifiers, fcm); } } diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index e5c116e85de..456eb783706 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -446,7 +446,7 @@ static int nlachannels_pushdown_exec(bContext *C, wmOperator *op) /* get anim-channel to use (or more specifically, the animdata block behind it) */ if (channel_index == -1) { - PointerRNA adt_ptr = {{NULL}}; + PointerRNA adt_ptr = {NULL}; /* active animdata block */ if (nla_panel_context(C, &adt_ptr, NULL, NULL) == 0 || (adt_ptr.data == NULL)) { @@ -458,7 +458,7 @@ static int nlachannels_pushdown_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } else { - id = adt_ptr.id.data; + id = adt_ptr.owner_id; adt = adt_ptr.data; } } @@ -581,7 +581,7 @@ static int nla_action_unlink_exec(bContext *C, wmOperator *op) /* do unlinking */ if (adt && adt->action) { bool force_delete = RNA_boolean_get(op->ptr, "force_delete"); - ED_animedit_unlink_action(C, adt_ptr.id.data, adt, adt->action, op->reports, force_delete); + ED_animedit_unlink_action(C, adt_ptr.owner_id, adt, adt->action, op->reports, force_delete); } return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 5cf9646210e..9d6ccd6fe35 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -141,8 +141,10 @@ static void nla_action_draw_keyframes( uint outline_color_id = GPU_vertformat_attr_add( format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); uint flags_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT); - immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND); + GPU_program_point_size(true); + immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND); + immUniform1f("outline_scale", 1.0f); immUniform2f("ViewportSize", BLI_rcti_size_x(&v2d->mask) + 1, BLI_rcti_size_y(&v2d->mask) + 1); immBegin(GPU_PRIM_POINTS, key_len); diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c index 3bdd2804efc..f274f3c93ec 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -522,7 +522,7 @@ static void nla_channel_region_message_subscribe(const struct bContext *UNUSED(C * so just whitelist the entire struct for updates */ { - wmMsgParams_RNA msg_key_params = {{{0}}}; + wmMsgParams_RNA msg_key_params = {{0}}; StructRNA *type_array[] = { &RNA_DopeSheet, }; diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 748e485f614..b89f163f579 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -24,6 +24,7 @@ #include "BLI_blenlib.h" #include "BLI_math.h" +#include "BLI_system.h" #include "DNA_node_types.h" #include "DNA_object_types.h" @@ -90,7 +91,7 @@ static void node_buts_value(uiLayout *layout, bContext *UNUSED(C), PointerRNA *p /* first output stores value */ bNodeSocket *output = node->outputs.first; PointerRNA sockptr; - RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, output, &sockptr); + RNA_pointer_create(ptr->owner_id, &RNA_NodeSocket, output, &sockptr); uiItemR(layout, &sockptr, "default_value", 0, "", ICON_NONE); } @@ -102,7 +103,7 @@ static void node_buts_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr bNodeSocket *output = node->outputs.first; PointerRNA sockptr; uiLayout *col; - RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, output, &sockptr); + RNA_pointer_create(ptr->owner_id, &RNA_NodeSocket, output, &sockptr); col = uiLayoutColumn(layout, false); uiTemplateColorPicker(col, &sockptr, "default_value", 1, 0, 0, 0); @@ -113,7 +114,7 @@ static void node_buts_mix_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA { uiLayout *row, *col; - bNodeTree *ntree = (bNodeTree *)ptr->id.data; + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; col = uiLayoutColumn(layout, false); row = uiLayoutRow(col, true); @@ -193,7 +194,7 @@ static void node_buts_normal(uiLayout *layout, bContext *UNUSED(C), PointerRNA * /* first output stores normal */ bNodeSocket *output = node->outputs.first; PointerRNA sockptr; - RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, output, &sockptr); + RNA_pointer_create(ptr->owner_id, &RNA_NodeSocket, output, &sockptr); uiItemR(layout, &sockptr, "default_value", 0, "", ICON_NONE); } @@ -1186,6 +1187,11 @@ static void node_shader_buts_ambient_occlusion(uiLayout *layout, uiItemR(layout, ptr, "only_local", 0, NULL, ICON_NONE); } +static void node_shader_buts_white_noise(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "dimensions", 0, "", ICON_NONE); +} + /* only once called */ static void node_shader_set_butfunc(bNodeType *ntype) { @@ -1220,7 +1226,7 @@ static void node_shader_set_butfunc(bNodeType *ntype) case SH_NODE_MATH: ntype->draw_buttons = node_buts_math; break; - case SH_NODE_VECT_MATH: + case SH_NODE_VECTOR_MATH: ntype->draw_buttons = node_shader_buts_vect_math; break; case SH_NODE_VECT_TRANSFORM: @@ -1330,6 +1336,9 @@ static void node_shader_set_butfunc(bNodeType *ntype) case SH_NODE_AMBIENT_OCCLUSION: ntype->draw_buttons = node_shader_buts_ambient_occlusion; break; + case SH_NODE_TEX_WHITE_NOISE: + ntype->draw_buttons = node_shader_buts_white_noise; + break; } } @@ -1363,7 +1372,7 @@ static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA * bNode *node = ptr->data; PointerRNA imaptr, iuserptr; - RNA_pointer_create((ID *)ptr->id.data, &RNA_ImageUser, node->storage, &iuserptr); + RNA_pointer_create(ptr->owner_id, &RNA_ImageUser, node->storage, &iuserptr); uiLayoutSetContextPointer(layout, "image_user", &iuserptr); uiTemplateID(layout, C, @@ -1390,7 +1399,7 @@ static void node_composit_buts_image_ex(uiLayout *layout, bContext *C, PointerRN bNode *node = ptr->data; PointerRNA iuserptr; - RNA_pointer_create((ID *)ptr->id.data, &RNA_ImageUser, node->storage, &iuserptr); + RNA_pointer_create(ptr->owner_id, &RNA_ImageUser, node->storage, &iuserptr); uiLayoutSetContextPointer(layout, "image_user", &iuserptr); uiTemplateImage(layout, C, ptr, "image", &iuserptr, 0, 1); } @@ -1951,7 +1960,7 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi } /* XXX collection lookup does not return the ID part of the pointer, * setting this manually here */ - active_input_ptr.id.data = ptr->id.data; + active_input_ptr.owner_id = ptr->owner_id; col = uiLayoutColumn(row, true); ot = WM_operatortype_find("NODE_OT_output_file_move_active_socket", false); @@ -2695,6 +2704,10 @@ static void node_composit_buts_denoise(uiLayout *layout, bContext *UNUSED(C), Po { #ifndef WITH_OPENIMAGEDENOISE uiItemL(layout, IFACE_("Disabled, built without OpenImageDenoise"), ICON_ERROR); +#else + if (!BLI_cpu_support_sse41()) { + uiItemL(layout, IFACE_("Disabled, CPU with SSE4.1 is required"), ICON_ERROR); + } #endif uiItemR(layout, ptr, "use_hdr", 0, NULL, ICON_NONE); @@ -2959,7 +2972,7 @@ static void node_texture_buts_proc(uiLayout *layout, bContext *UNUSED(C), Pointe { PointerRNA tex_ptr; bNode *node = ptr->data; - ID *id = ptr->id.data; + ID *id = ptr->owner_id; Tex *tex = (Tex *)node->storage; uiLayout *col, *row; @@ -3053,7 +3066,7 @@ static void node_texture_buts_image_ex(uiLayout *layout, bContext *C, PointerRNA bNode *node = ptr->data; PointerRNA iuserptr; - RNA_pointer_create((ID *)ptr->id.data, &RNA_ImageUser, node->storage, &iuserptr); + RNA_pointer_create(ptr->owner_id, &RNA_ImageUser, node->storage, &iuserptr); uiTemplateImage(layout, C, ptr, "image", &iuserptr, 0, 0); } @@ -3115,7 +3128,7 @@ static void node_texture_set_butfunc(bNodeType *ntype) static void node_property_update_default(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - bNodeTree *ntree = ptr->id.data; + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; bNode *node = ptr->data; ED_node_tag_update_nodetree(bmain, ntree, node); } @@ -3285,7 +3298,7 @@ static void node_file_output_socket_draw(bContext *C, PointerRNA *ptr, PointerRNA *node_ptr) { - bNodeTree *ntree = ptr->id.data; + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; bNodeSocket *sock = ptr->data; uiLayout *row; PointerRNA inputptr, imfptr; @@ -3358,8 +3371,13 @@ static void std_node_socket_draw( uiTemplateComponentMenu(layout, ptr, "default_value", text); } else { - uiLayout *column = uiLayoutColumn(layout, true); - uiItemR(column, ptr, "default_value", 0, text, 0); + if (sock->typeinfo->subtype == PROP_DIRECTION) { + uiItemR(layout, ptr, "default_value", 0, "", ICON_NONE); + } + else { + uiLayout *column = uiLayoutColumn(layout, true); + uiItemR(column, ptr, "default_value", 0, text, ICON_NONE); + } } break; case SOCK_RGBA: diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index 1c3544077c4..6dc2182b684 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -713,15 +713,28 @@ static void node_draw_mute_line(View2D *v2d, SpaceNode *snode, bNode *node) GPU_blend(false); } -static void node_socket_circle_draw(const bContext *C, - bNodeTree *ntree, - PointerRNA node_ptr, - bNodeSocket *sock, - unsigned pos, - unsigned col) +/* flags used in gpu_shader_keyframe_diamond_frag.glsl */ +#define MARKER_SHAPE_DIAMOND 0x1 +#define MARKER_SHAPE_SQUARE 0xC +#define MARKER_SHAPE_CIRCLE 0x2 +#define MARKER_SHAPE_INNER_DOT 0x10 + +static void node_socket_draw(const bContext *C, + bNodeTree *ntree, + PointerRNA node_ptr, + bNodeSocket *sock, + unsigned pos_id, + unsigned col_id, + unsigned shape_id, + unsigned size_id, + unsigned outline_col_id, + float size, + bool selected) { PointerRNA ptr; float color[4]; + float outline_color[4]; + unsigned int flags = 0; RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr); sock->typeinfo->draw_color((bContext *)C, &ptr, &node_ptr, color); @@ -731,8 +744,44 @@ static void node_socket_circle_draw(const bContext *C, color[3] *= 0.25f; } - immAttr4fv(col, color); - immVertex2f(pos, sock->locx, sock->locy); + if (selected) { + UI_GetThemeColor4fv(TH_TEXT_HI, outline_color); + outline_color[3] = 0.9f; + } + else { + copy_v4_fl(outline_color, 0.0f); + outline_color[3] = 0.6f; + } + + /* sets shape flags */ + switch (sock->display_shape) { + case SOCK_DISPLAY_SHAPE_DIAMOND: + case SOCK_DISPLAY_SHAPE_DIAMOND_DOT: + flags = MARKER_SHAPE_DIAMOND; + break; + case SOCK_DISPLAY_SHAPE_SQUARE: + case SOCK_DISPLAY_SHAPE_SQUARE_DOT: + flags = MARKER_SHAPE_SQUARE; + break; + default: + case SOCK_DISPLAY_SHAPE_CIRCLE: + case SOCK_DISPLAY_SHAPE_CIRCLE_DOT: + flags = MARKER_SHAPE_CIRCLE; + break; + } + + if (ELEM(sock->display_shape, + SOCK_DISPLAY_SHAPE_DIAMOND_DOT, + SOCK_DISPLAY_SHAPE_SQUARE_DOT, + SOCK_DISPLAY_SHAPE_CIRCLE_DOT)) { + flags |= MARKER_SHAPE_INNER_DOT; + } + + immAttr4fv(col_id, color); + immAttr1u(shape_id, flags); + immAttr1f(size_id, size); + immAttr4fv(outline_col_id, outline_color); + immVertex2f(pos_id, sock->locx, sock->locy); } /* ************** Socket callbacks *********** */ @@ -888,26 +937,28 @@ void node_draw_sockets(View2D *v2d, PointerRNA node_ptr; RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr); - float scale; - UI_view2d_scale_get(v2d, &scale, NULL); + bool selected = false; GPUVertFormat *format = immVertexFormat(); - uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + uint col_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + uint shape_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT); + uint size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + uint outline_col_id = GPU_vertformat_attr_add( + format, "outlineColor", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); GPU_blend(true); GPU_program_point_size(true); - - immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_AA); + immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND); + immUniform1f("outline_scale", 0.7f); + immUniform2f("ViewportSize", -1.0f, -1.0f); /* set handle size */ - immUniform1f("size", 2.0f * NODE_SOCKSIZE * scale); /* 2 * size to have diameter */ + float scale; + UI_view2d_scale_get(v2d, &scale, NULL); + scale *= 2.25f * NODE_SOCKSIZE; if (!select_all) { - /* outline for unselected sockets */ - immUniform1f("outlineWidth", 1.0f); - immUniform4f("outlineColor", 0.0f, 0.0f, 0.0f, 0.6f); - immBeginAtMost(GPU_PRIM_POINTS, total_input_len + total_output_len); } @@ -923,7 +974,17 @@ void node_draw_sockets(View2D *v2d, continue; } - node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col); + node_socket_draw(C, + ntree, + node_ptr, + sock, + pos_id, + col_id, + shape_id, + size_id, + outline_col_id, + scale, + selected); } /* socket outputs */ @@ -938,7 +999,17 @@ void node_draw_sockets(View2D *v2d, continue; } - node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col); + node_socket_draw(C, + ntree, + node_ptr, + sock, + pos_id, + col_id, + shape_id, + size_id, + outline_col_id, + scale, + selected); } } @@ -949,10 +1020,8 @@ void node_draw_sockets(View2D *v2d, /* go back and draw selected sockets */ if (selected_input_len + selected_output_len > 0) { /* outline for selected sockets */ - float c[3]; - UI_GetThemeColor3fv(TH_TEXT_HI, c); - immUniform4f("outlineColor", c[0], c[1], c[2], 1.0f); - immUniform1f("outlineWidth", 1.5f); + + selected = true; immBegin(GPU_PRIM_POINTS, selected_input_len + selected_output_len); @@ -963,7 +1032,17 @@ void node_draw_sockets(View2D *v2d, continue; } if (select_all || (sock->flag & SELECT)) { - node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col); + node_socket_draw(C, + ntree, + node_ptr, + sock, + pos_id, + col_id, + shape_id, + size_id, + outline_col_id, + scale, + selected); if (--selected_input_len == 0) { break; /* stop as soon as last one is drawn */ } @@ -978,7 +1057,17 @@ void node_draw_sockets(View2D *v2d, continue; } if (select_all || (sock->flag & SELECT)) { - node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col); + node_socket_draw(C, + ntree, + node_ptr, + sock, + pos_id, + col_id, + shape_id, + size_id, + outline_col_id, + scale, + selected); if (--selected_output_len == 0) { break; /* stop as soon as last one is drawn */ } diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index d31256a1425..dcf901216f5 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -1838,7 +1838,7 @@ static int node_output_file_add_socket_exec(bContext *C, wmOperator *op) if (ptr.data) { node = ptr.data; - ntree = ptr.id.data; + ntree = (bNodeTree *)ptr.owner_id; } else if (snode && snode->edittree) { ntree = snode->edittree; @@ -1886,7 +1886,7 @@ static int node_output_file_remove_active_socket_exec(bContext *C, wmOperator *U if (ptr.data) { node = ptr.data; - ntree = ptr.id.data; + ntree = (bNodeTree *)ptr.owner_id; } else if (snode && snode->edittree) { ntree = snode->edittree; @@ -2535,7 +2535,7 @@ static int node_shader_script_update_exec(bContext *C, wmOperator *op) /* get node */ if (nodeptr.data) { - ntree_base = nodeptr.id.data; + ntree_base = (bNodeTree *)nodeptr.owner_id; node = nodeptr.data; } else if (snode && snode->edittree) { @@ -2734,7 +2734,7 @@ static int node_cryptomatte_add_socket_exec(bContext *C, wmOperator *UNUSED(op)) if (ptr.data) { node = ptr.data; - ntree = ptr.id.data; + ntree = (bNodeTree *)ptr.owner_id; } else if (snode && snode->edittree) { ntree = snode->edittree; @@ -2778,7 +2778,7 @@ static int node_cryptomatte_remove_socket_exec(bContext *C, wmOperator *UNUSED(o if (ptr.data) { node = ptr.data; - ntree = ptr.id.data; + ntree = (bNodeTree *)ptr.owner_id; } else if (snode && snode->edittree) { ntree = snode->edittree; diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c index 78f36719880..450cf28cce1 100644 --- a/source/blender/editors/space_node/node_select.c +++ b/source/blender/editors/space_node/node_select.c @@ -1234,8 +1234,18 @@ static uiBlock *node_find_menu(bContext *C, ARegion *ar, void *arg_op) UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_SEARCH_MENU); UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP); - but = uiDefSearchBut( - block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 10, 9 * UI_UNIT_X, UI_UNIT_Y, 0, 0, ""); + but = uiDefSearchBut(block, + search, + 0, + ICON_VIEWZOOM, + sizeof(search), + 10, + 10, + UI_searchbox_size_x(), + UI_UNIT_Y, + 0, + 0, + ""); UI_but_func_search_set(but, NULL, node_find_cb, op->type, false, node_find_call_cb, NULL); UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT); @@ -1256,7 +1266,7 @@ static uiBlock *node_find_menu(bContext *C, ARegion *ar, void *arg_op) NULL); /* Move it downwards, mouse over button. */ - UI_block_bounds_set_popup(block, 6, (const int[2]){0, -UI_UNIT_Y}); + UI_block_bounds_set_popup(block, 0.3f * U.widget_unit, (const int[2]){0, -UI_UNIT_Y}); return block; } diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c index 8cc57a82fe0..423dec13c69 100644 --- a/source/blender/editors/space_node/node_templates.c +++ b/source/blender/editors/space_node/node_templates.c @@ -441,7 +441,7 @@ static int ui_node_item_name_compare(const void *a, const void *b) { const bNodeType *type_a = *(const bNodeType **)a; const bNodeType *type_b = *(const bNodeType **)b; - return BLI_natstrcmp(type_a->ui_name, type_b->ui_name); + return BLI_strcasecmp_natural(type_a->ui_name, type_b->ui_name); } static bool ui_node_item_special_poll(const bNodeTree *UNUSED(ntree), const bNodeType *ntype) diff --git a/source/blender/editors/space_outliner/CMakeLists.txt b/source/blender/editors/space_outliner/CMakeLists.txt index d235dd47136..616915dbc2c 100644 --- a/source/blender/editors/space_outliner/CMakeLists.txt +++ b/source/blender/editors/space_outliner/CMakeLists.txt @@ -41,6 +41,7 @@ set(SRC outliner_edit.c outliner_ops.c outliner_select.c + outliner_sync.c outliner_tools.c outliner_tree.c outliner_utils.c diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c index 4740c412083..309446db83b 100644 --- a/source/blender/editors/space_outliner/outliner_collections.c +++ b/source/blender/editors/space_outliner/outliner_collections.c @@ -89,7 +89,7 @@ Collection *outliner_collection_from_tree_element(const TreeElement *te) } else if (ELEM(tselem->type, TSE_SCENE_COLLECTION_BASE, TSE_VIEW_COLLECTION_BASE)) { Scene *scene = (Scene *)tselem->id; - return BKE_collection_master(scene); + return scene->master_collection; } else if (tselem->type == 0 && te->idcode == ID_GR) { return (Collection *)tselem->id; @@ -199,7 +199,7 @@ static int collection_new_exec(bContext *C, wmOperator *op) } if (data.collection == NULL || ID_IS_LINKED(data.collection)) { - data.collection = BKE_collection_master(scene); + data.collection = scene->master_collection; } if (ID_IS_LINKED(scene)) { @@ -514,14 +514,14 @@ static int collection_duplicate_exec(bContext *C, wmOperator *op) * This can happen when a whole scene is linked e.g. */ if (parent != NULL && ID_IS_LINKED(parent)) { Scene *scene = CTX_data_scene(C); - parent = ID_IS_LINKED(scene) ? NULL : BKE_collection_master(scene); + parent = ID_IS_LINKED(scene) ? NULL : scene->master_collection; } else if (parent != NULL && (parent->flag & COLLECTION_IS_MASTER) != 0) { Scene *scene = BKE_collection_master_scene_search(bmain, parent); BLI_assert(scene != NULL); if (ID_IS_LINKED(scene)) { scene = CTX_data_scene(C); - parent = ID_IS_LINKED(scene) ? NULL : BKE_collection_master(scene); + parent = ID_IS_LINKED(scene) ? NULL : scene->master_collection; } } diff --git a/source/blender/editors/space_outliner/outliner_dragdrop.c b/source/blender/editors/space_outliner/outliner_dragdrop.c index d8276aa2bbc..6e30157d216 100644 --- a/source/blender/editors/space_outliner/outliner_dragdrop.c +++ b/source/blender/editors/space_outliner/outliner_dragdrop.c @@ -326,38 +326,57 @@ static bool parent_drop_poll(bContext *C, return false; } -static int parent_drop_exec(bContext *C, wmOperator *op) +static void parent_drop_set_parents( + bContext *C, ReportList *reports, wmDragID *drag, Object *parent, short parent_type) { - Object *par = NULL, *ob = NULL; Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - int partype = -1; - char parname[MAX_NAME], childname[MAX_NAME]; + SpaceOutliner *soops = CTX_wm_space_outliner(C); - partype = RNA_enum_get(op->ptr, "type"); - RNA_string_get(op->ptr, "parent", parname); - par = (Object *)BKE_libblock_find_name(bmain, ID_OB, parname); - RNA_string_get(op->ptr, "child", childname); - ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, childname); + TreeElement *te = outliner_find_id(soops, &soops->tree, &parent->id); + Scene *scene = (Scene *)outliner_search_back(soops, te, ID_SCE); - if (ID_IS_LINKED(ob)) { - BKE_report(op->reports, RPT_INFO, "Can't edit library linked object"); - return OPERATOR_CANCELLED; + if (scene == NULL) { + /* currently outliner organized in a way, that if there's no parent scene + * element for object it means that all displayed objects belong to + * active scene and parenting them is allowed (sergey) + */ + + scene = CTX_data_scene(C); } - ED_object_parent_set(op->reports, C, scene, ob, par, partype, false, false, NULL); + bool parent_set = false; + bool linked_objects = false; - DEG_relations_tag_update(bmain); - WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); - WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL); + for (wmDragID *drag_id = drag; drag_id; drag_id = drag_id->next) { + if (GS(drag_id->id->name) == ID_OB) { + Object *object = (Object *)drag_id->id; - return OPERATOR_FINISHED; + /* Do nothing to linked data */ + if (ID_IS_LINKED(object)) { + linked_objects = true; + continue; + } + + if (ED_object_parent_set( + reports, C, scene, object, parent, parent_type, false, false, NULL)) { + parent_set = true; + } + } + } + + if (linked_objects) { + BKE_report(reports, RPT_INFO, "Can't edit library linked object(s)"); + } + + if (parent_set) { + DEG_relations_tag_update(bmain); + WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); + WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL); + } } static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - Main *bmain = CTX_data_main(C); - SpaceOutliner *soops = CTX_wm_space_outliner(C); TreeElement *te = outliner_drop_find(C, event); TreeStoreElem *tselem = te ? TREESTORE(te) : NULL; @@ -374,107 +393,15 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) if (ob == par) { return OPERATOR_CANCELLED; } - if (ID_IS_LINKED(ob)) { - BKE_report(op->reports, RPT_INFO, "Can't edit library linked object"); - return OPERATOR_CANCELLED; - } - - char childname[MAX_NAME]; - char parname[MAX_NAME]; - STRNCPY(childname, ob->id.name + 2); - STRNCPY(parname, par->id.name + 2); - RNA_string_set(op->ptr, "child", childname); - RNA_string_set(op->ptr, "parent", parname); - Scene *scene = (Scene *)outliner_search_back(soops, te, ID_SCE); - - if (scene == NULL) { - /* currently outlier organized in a way, that if there's no parent scene - * element for object it means that all displayed objects belong to - * active scene and parenting them is allowed (sergey) - */ - - scene = CTX_data_scene(C); + if (event->custom != EVT_DATA_DRAGDROP) { + return OPERATOR_CANCELLED; } - if ((par->type != OB_ARMATURE) && (par->type != OB_CURVE) && (par->type != OB_LATTICE)) { - int partype = 0; - if (ED_object_parent_set(op->reports, C, scene, ob, par, partype, false, false, NULL)) { - DEG_relations_tag_update(bmain); - WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); - WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL); - } - } - else { - /* Menu creation */ - wmOperatorType *ot = WM_operatortype_find("OUTLINER_OT_parent_drop", false); - uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Set Parent To"), ICON_NONE); - uiLayout *layout = UI_popup_menu_layout(pup); - PointerRNA ptr; - - /* Cannot use uiItemEnumO()... have multiple properties to set. */ - uiItemFullO_ptr(layout, ot, IFACE_("Object"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr); - RNA_string_set(&ptr, "parent", parname); - RNA_string_set(&ptr, "child", childname); - RNA_enum_set(&ptr, "type", PAR_OBJECT); - - /* par becomes parent, make the associated menus */ - if (par->type == OB_ARMATURE) { - uiItemFullO_ptr(layout, ot, IFACE_("Armature Deform"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr); - RNA_string_set(&ptr, "parent", parname); - RNA_string_set(&ptr, "child", childname); - RNA_enum_set(&ptr, "type", PAR_ARMATURE); - - uiItemFullO_ptr( - layout, ot, IFACE_(" With Empty Groups"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr); - RNA_string_set(&ptr, "parent", parname); - RNA_string_set(&ptr, "child", childname); - RNA_enum_set(&ptr, "type", PAR_ARMATURE_NAME); - - uiItemFullO_ptr( - layout, ot, IFACE_(" With Envelope Weights"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr); - RNA_string_set(&ptr, "parent", parname); - RNA_string_set(&ptr, "child", childname); - RNA_enum_set(&ptr, "type", PAR_ARMATURE_ENVELOPE); - - uiItemFullO_ptr( - layout, ot, IFACE_(" With Automatic Weights"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr); - RNA_string_set(&ptr, "parent", parname); - RNA_string_set(&ptr, "child", childname); - RNA_enum_set(&ptr, "type", PAR_ARMATURE_AUTO); - - uiItemFullO_ptr(layout, ot, IFACE_("Bone"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr); - RNA_string_set(&ptr, "parent", parname); - RNA_string_set(&ptr, "child", childname); - RNA_enum_set(&ptr, "type", PAR_BONE); - } - else if (par->type == OB_CURVE) { - uiItemFullO_ptr(layout, ot, IFACE_("Curve Deform"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr); - RNA_string_set(&ptr, "parent", parname); - RNA_string_set(&ptr, "child", childname); - RNA_enum_set(&ptr, "type", PAR_CURVE); - - uiItemFullO_ptr(layout, ot, IFACE_("Follow Path"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr); - RNA_string_set(&ptr, "parent", parname); - RNA_string_set(&ptr, "child", childname); - RNA_enum_set(&ptr, "type", PAR_FOLLOW); - - uiItemFullO_ptr(layout, ot, IFACE_("Path Constraint"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr); - RNA_string_set(&ptr, "parent", parname); - RNA_string_set(&ptr, "child", childname); - RNA_enum_set(&ptr, "type", PAR_PATH_CONST); - } - else if (par->type == OB_LATTICE) { - uiItemFullO_ptr(layout, ot, IFACE_("Lattice Deform"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr); - RNA_string_set(&ptr, "parent", parname); - RNA_string_set(&ptr, "child", childname); - RNA_enum_set(&ptr, "type", PAR_LATTICE); - } - - UI_popup_menu_end(C, pup); + ListBase *lb = event->customdata; + wmDrag *drag = lb->first; - return OPERATOR_INTERFACE; - } + parent_drop_set_parents(C, op->reports, drag->ids.first, par, PAR_OBJECT); return OPERATOR_FINISHED; } @@ -488,17 +415,11 @@ void OUTLINER_OT_parent_drop(wmOperatorType *ot) /* api callbacks */ ot->invoke = parent_drop_invoke; - ot->exec = parent_drop_exec; ot->poll = ED_operator_outliner_active; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; - - /* properties */ - RNA_def_string(ot->srna, "child", "Object", MAX_NAME, "Child", "Child Object"); - RNA_def_string(ot->srna, "parent", "Object", MAX_NAME, "Parent", "Parent Object"); - RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", ""); } /* ******************** Parent Clear Operator *********************** */ @@ -549,13 +470,21 @@ static bool parent_clear_poll(bContext *C, static int parent_clear_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { Main *bmain = CTX_data_main(C); - Object *ob = (Object *)WM_drag_ID_from_event(event, ID_OB); - if (ob == NULL) { + if (event->custom != EVT_DATA_DRAGDROP) { return OPERATOR_CANCELLED; } - ED_object_parent_clear(ob, 0); + ListBase *lb = event->customdata; + wmDrag *drag = lb->first; + + for (wmDragID *drag_id = drag->ids.first; drag_id; drag_id = drag_id->next) { + if (GS(drag_id->id->name) == ID_OB) { + Object *object = (Object *)drag_id->id; + + ED_object_parent_clear(object, 0); + } + } DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); @@ -608,7 +537,7 @@ static int scene_drop_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent Collection *collection; if (scene != CTX_data_scene(C)) { /* when linking to an inactive scene link to the master collection */ - collection = BKE_collection_master(scene); + collection = scene->master_collection; } else { collection = CTX_data_collection(C); @@ -966,6 +895,12 @@ static int outliner_item_drag_drop_invoke(bContext *C, return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH); } + float view_mval[2]; + UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]); + if (outliner_item_is_co_within_close_toggle(te, view_mval[0])) { + return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH); + } + wmDrag *drag = WM_event_start_drag(C, data.icon, WM_DRAG_ID, NULL, 0.0, WM_DRAG_NOP); if (ELEM(GS(data.drag_id->name), ID_OB, ID_GR)) { @@ -1032,7 +967,7 @@ static int outliner_item_drag_drop_invoke(bContext *C, } else { Scene *scene = CTX_data_scene(C); - parent = BKE_collection_master(scene); + parent = scene->master_collection; } WM_drag_add_ID(drag, id, &parent->id); diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index e4881a6f13d..a2ca3254b30 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -31,6 +31,7 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_sequence_types.h" +#include "DNA_constraint_types.h" #include "DNA_object_force_types.h" #include "BLI_math.h" @@ -60,6 +61,7 @@ #include "ED_armature.h" #include "ED_keyframing.h" #include "ED_object.h" +#include "ED_outliner.h" #include "ED_screen.h" #include "WM_api.h" @@ -175,8 +177,9 @@ static void restrictbutton_r_lay_cb(bContext *C, void *poin, void *UNUSED(poin2) WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, poin); } -static void restrictbutton_bone_visibility_cb(bContext *C, void *UNUSED(poin), void *poin2) +static void restrictbutton_bone_visibility_cb(bContext *C, void *poin, void *poin2) { + bArmature *arm = (bArmature *)poin; Bone *bone = (Bone *)poin2; if (bone->flag & BONE_HIDDEN_P) { bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); @@ -187,6 +190,7 @@ static void restrictbutton_bone_visibility_cb(bContext *C, void *UNUSED(poin), v } WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL); + DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE); } static void restrictbutton_bone_select_cb(bContext *C, void *UNUSED(poin), void *poin2) @@ -848,6 +852,7 @@ typedef struct RestrictProperties { PropertyRNA *layer_collection_holdout, *layer_collection_indirect_only, *layer_collection_hide_viewport; PropertyRNA *modifier_show_viewport, *modifier_show_render; + PropertyRNA *constraint_enable; } RestrictProperties; /* We don't care about the value of the property @@ -865,6 +870,7 @@ typedef struct RestrictPropertiesActive { bool layer_collection_hide_viewport; bool modifier_show_viewport; bool modifier_show_render; + bool constraint_enable; } RestrictPropertiesActive; static void outliner_restrict_properties_enable_collection_set( @@ -878,6 +884,7 @@ static void outliner_restrict_properties_enable_collection_set( props_active->layer_collection_indirect_only = false; props_active->object_hide_render = false; props_active->modifier_show_render = false; + props_active->constraint_enable = false; } } @@ -891,6 +898,7 @@ static void outliner_restrict_properties_enable_collection_set( props_active->object_hide_viewport = false; props_active->base_hide_viewport = false; props_active->modifier_show_viewport = false; + props_active->constraint_enable = false; } } @@ -995,6 +1003,8 @@ static void outliner_draw_restrictbuts(uiBlock *block, props.modifier_show_viewport = RNA_struct_type_find_property(&RNA_Modifier, "show_viewport"); props.modifier_show_render = RNA_struct_type_find_property(&RNA_Modifier, "show_render"); + props.constraint_enable = RNA_struct_type_find_property(&RNA_Constraint, "mute"); + props.initialized = true; } @@ -1181,6 +1191,35 @@ static void outliner_draw_restrictbuts(uiBlock *block, } } } + else if (tselem->type == TSE_CONSTRAINT) { + bConstraint *con = (bConstraint *)te->directdata; + + PointerRNA ptr; + RNA_pointer_create(tselem->id, &RNA_Constraint, con, &ptr); + + if (soops->show_restrict_flags & SO_RESTRICT_HIDE) { + bt = uiDefIconButR_prop(block, + UI_BTYPE_ICON_TOGGLE, + 0, + 0, + (int)(ar->v2d.cur.xmax - restrict_offsets.hide), + te->ys, + UI_UNIT_X, + UI_UNIT_Y, + &ptr, + props.constraint_enable, + -1, + 0, + 0, + -1, + -1, + NULL); + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + if (!props_active.constraint_enable) { + UI_but_flag_enable(bt, UI_BUT_INACTIVE); + } + } + } else if (tselem->type == TSE_MODIFIER) { ModifierData *md = (ModifierData *)te->directdata; @@ -1243,7 +1282,7 @@ static void outliner_draw_restrictbuts(uiBlock *block, UI_BTYPE_ICON_TOGGLE, BONE_HIDDEN_P, 0, - ICON_HIDE_OFF, + ICON_RESTRICT_VIEW_OFF, (int)(ar->v2d.cur.xmax - restrict_offsets.viewport), te->ys, UI_UNIT_X, @@ -1878,6 +1917,9 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te) case TSE_DEFGROUP_BASE: data.icon = ICON_GROUP_VERTEX; break; + case TSE_DEFGROUP: + data.icon = ICON_GROUP_VERTEX; + break; case TSE_BONE: case TSE_EBONE: data.icon = ICON_BONE_DATA; @@ -1885,6 +1927,100 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te) case TSE_CONSTRAINT_BASE: data.icon = ICON_CONSTRAINT; break; + case TSE_CONSTRAINT: { + bConstraint *con = te->directdata; + switch ((eBConstraint_Types)con->type) { + case CONSTRAINT_TYPE_CAMERASOLVER: + data.icon = ICON_CON_CAMERASOLVER; + break; + case CONSTRAINT_TYPE_FOLLOWTRACK: + data.icon = ICON_CON_FOLLOWTRACK; + break; + case CONSTRAINT_TYPE_OBJECTSOLVER: + data.icon = ICON_CON_OBJECTSOLVER; + break; + case CONSTRAINT_TYPE_LOCLIKE: + data.icon = ICON_CON_LOCLIKE; + break; + case CONSTRAINT_TYPE_ROTLIKE: + data.icon = ICON_CON_ROTLIKE; + break; + case CONSTRAINT_TYPE_SIZELIKE: + data.icon = ICON_CON_SIZELIKE; + break; + case CONSTRAINT_TYPE_TRANSLIKE: + data.icon = ICON_CON_TRANSLIKE; + break; + case CONSTRAINT_TYPE_DISTLIMIT: + data.icon = ICON_CON_DISTLIMIT; + break; + case CONSTRAINT_TYPE_LOCLIMIT: + data.icon = ICON_CON_LOCLIMIT; + break; + case CONSTRAINT_TYPE_ROTLIMIT: + data.icon = ICON_CON_ROTLIMIT; + break; + case CONSTRAINT_TYPE_SIZELIMIT: + data.icon = ICON_CON_SIZELIMIT; + break; + case CONSTRAINT_TYPE_SAMEVOL: + data.icon = ICON_CON_SAMEVOL; + break; + case CONSTRAINT_TYPE_TRANSFORM: + data.icon = ICON_CON_TRANSFORM; + break; + case CONSTRAINT_TYPE_TRANSFORM_CACHE: + data.icon = ICON_CON_TRANSFORM_CACHE; + break; + case CONSTRAINT_TYPE_CLAMPTO: + data.icon = ICON_CON_CLAMPTO; + break; + case CONSTRAINT_TYPE_DAMPTRACK: + data.icon = ICON_CON_TRACKTO; + break; + case CONSTRAINT_TYPE_KINEMATIC: + data.icon = ICON_CON_KINEMATIC; + break; + case CONSTRAINT_TYPE_LOCKTRACK: + data.icon = ICON_CON_LOCKTRACK; + break; + case CONSTRAINT_TYPE_SPLINEIK: + data.icon = ICON_CON_SPLINEIK; + break; + case CONSTRAINT_TYPE_STRETCHTO: + data.icon = ICON_CON_STRETCHTO; + break; + case CONSTRAINT_TYPE_TRACKTO: + data.icon = ICON_CON_TRACKTO; + break; + case CONSTRAINT_TYPE_ACTION: + data.icon = ICON_CON_ACTION; + break; + case CONSTRAINT_TYPE_ARMATURE: + data.icon = ICON_CON_ARMATURE; + break; + case CONSTRAINT_TYPE_CHILDOF: + data.icon = ICON_CON_CHILDOF; + break; + case CONSTRAINT_TYPE_MINMAX: + data.icon = ICON_CON_FLOOR; + break; + case CONSTRAINT_TYPE_FOLLOWPATH: + data.icon = ICON_CON_FOLLOWPATH; + break; + case CONSTRAINT_TYPE_PIVOT: + data.icon = ICON_CON_PIVOT; + break; + case CONSTRAINT_TYPE_SHRINKWRAP: + data.icon = ICON_CON_SHRINKWRAP; + break; + + default: + data.icon = ICON_DOT; + break; + } + break; + } case TSE_MODIFIER_BASE: data.icon = ICON_MODIFIER_DATA; break; @@ -2137,30 +2273,64 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te) data.icon = ICON_GROUP_BONE; break; case TSE_SEQUENCE: - if (te->idcode == SEQ_TYPE_MOVIE) { - data.icon = ICON_SEQUENCE; - } - else if (te->idcode == SEQ_TYPE_META) { - data.icon = ICON_DOT; - } - else if (te->idcode == SEQ_TYPE_SCENE) { - data.icon = ICON_SCENE; - } - else if (te->idcode == SEQ_TYPE_SOUND_RAM) { - data.icon = ICON_SOUND; - } - else if (te->idcode == SEQ_TYPE_IMAGE) { - data.icon = ICON_IMAGE; - } - else { - data.icon = ICON_PARTICLES; + switch (te->idcode) { + case SEQ_TYPE_SCENE: + data.icon = ICON_SCENE_DATA; + break; + case SEQ_TYPE_MOVIECLIP: + data.icon = ICON_TRACKER; + break; + case SEQ_TYPE_MASK: + data.icon = ICON_MOD_MASK; + break; + case SEQ_TYPE_MOVIE: + data.icon = ICON_FILE_MOVIE; + break; + case SEQ_TYPE_SOUND_RAM: + data.icon = ICON_SOUND; + break; + case SEQ_TYPE_IMAGE: + data.icon = ICON_FILE_IMAGE; + break; + case SEQ_TYPE_COLOR: + case SEQ_TYPE_ADJUSTMENT: + data.icon = ICON_COLOR; + break; + case SEQ_TYPE_TEXT: + data.icon = ICON_FONT_DATA; + break; + case SEQ_TYPE_ADD: + case SEQ_TYPE_SUB: + case SEQ_TYPE_MUL: + case SEQ_TYPE_OVERDROP: + case SEQ_TYPE_ALPHAOVER: + case SEQ_TYPE_ALPHAUNDER: + case SEQ_TYPE_COLORMIX: + case SEQ_TYPE_MULTICAM: + case SEQ_TYPE_TRANSFORM: + case SEQ_TYPE_SPEED: + case SEQ_TYPE_GLOW: + case SEQ_TYPE_GAUSSIAN_BLUR: + data.icon = ICON_SHADERFX; + break; + case SEQ_TYPE_CROSS: + case SEQ_TYPE_GAMCROSS: + case SEQ_TYPE_WIPE: + data.icon = ICON_ARROW_LEFTRIGHT; + break; + case SEQ_TYPE_META: + data.icon = ICON_SEQ_STRIP_META; + break; + default: + data.icon = ICON_DOT; + break; } break; case TSE_SEQ_STRIP: data.icon = ICON_LIBRARY_DATA_DIRECT; break; case TSE_SEQUENCE_DUP: - data.icon = ICON_OBJECT_DATA; + data.icon = ICON_SEQ_STRIP_DUPLICATE; break; case TSE_RNA_STRUCT: if (RNA_struct_is_ID(te->rnaptr.type)) { @@ -2459,7 +2629,11 @@ static void tselem_draw_icon(uiBlock *block, return; } + /* Icon is covered by restrict buttons */ if (!is_clickable || x >= xmax) { + /* Reduce alpha to match icon buttons */ + alpha *= 0.8f; + /* placement of icons, copied from interface_widgets.c */ float aspect = (0.8f * UI_UNIT_Y) / ICON_DEFAULT_HEIGHT; x += 2.0f * aspect; @@ -2567,7 +2741,6 @@ static void outliner_draw_iconrow_doit(uiBlock *block, float ufac = UI_UNIT_X / 20.0f; float icon_color[4], icon_border[4]; outliner_icon_background_colors(icon_color, icon_border); - icon_color[3] *= alpha_fac; if (active == OL_DRAWSEL_ACTIVE) { UI_GetThemeColor4fv(TH_EDITED_OBJECT, icon_color); icon_border[3] = 0.3f; @@ -2592,6 +2765,9 @@ static void outliner_draw_iconrow_doit(uiBlock *block, GPU_blend(true); /* Roundbox disables. */ } + if (tselem->flag & TSE_HIGHLIGHTED) { + alpha_fac += 0.5; + } tselem_draw_icon(block, xmax, (float)*offsx, (float)ys, tselem, te, alpha_fac, false); te->xs = *offsx; te->ys = ys; @@ -2599,7 +2775,12 @@ static void outliner_draw_iconrow_doit(uiBlock *block, if (num_elements > 1) { outliner_draw_iconrow_number(fstyle, *offsx, ys, num_elements); + te->flag |= TE_ICONROW_MERGED; } + else { + te->flag |= TE_ICONROW; + } + (*offsx) += UI_UNIT_X; } @@ -2609,7 +2790,7 @@ static void outliner_draw_iconrow_doit(uiBlock *block, * We use a continuum of indices until we get to the object data-blocks * and we then make room for the object types. */ -static int tree_element_id_type_to_index(TreeElement *te) +int tree_element_id_type_to_index(TreeElement *te) { TreeStoreElem *tselem = TREESTORE(te); @@ -2739,7 +2920,7 @@ static void outliner_set_coord_tree_element(TreeElement *te, int startx, int sta TreeElement *ten; /* closed items may be displayed in row of parent, don't change their coordinate! */ - if ((te->flag & TE_ICONROW) == 0) { + if ((te->flag & TE_ICONROW) == 0 && (te->flag & TE_ICONROW_MERGED) == 0) { /* store coord and continue, we need coordinates for elements outside view too */ te->xs = startx; te->ys = starty; @@ -3193,6 +3374,7 @@ static void outliner_draw_highlights_recursive(unsigned pos, const SpaceOutliner *soops, const ListBase *lb, const float col_selection[4], + const float col_active[4], const float col_highlight[4], const float col_searchmatch[4], int start_x, @@ -3206,7 +3388,11 @@ static void outliner_draw_highlights_recursive(unsigned pos, const int start_y = *io_start_y; /* selection status */ - if (tselem->flag & TSE_SELECTED) { + if ((tselem->flag & TSE_ACTIVE) && (tselem->flag & TSE_SELECTED)) { + immUniformColor4fv(col_active); + immRecti(pos, 0, start_y, (int)ar->v2d.cur.xmax, start_y + UI_UNIT_Y); + } + else if (tselem->flag & TSE_SELECTED) { immUniformColor4fv(col_selection); immRecti(pos, 0, start_y, (int)ar->v2d.cur.xmax, start_y + UI_UNIT_Y); } @@ -3260,6 +3446,7 @@ static void outliner_draw_highlights_recursive(unsigned pos, soops, &te->subtree, col_selection, + col_active, col_highlight, col_searchmatch, start_x + UI_UNIT_X, @@ -3271,10 +3458,12 @@ static void outliner_draw_highlights_recursive(unsigned pos, static void outliner_draw_highlights(ARegion *ar, SpaceOutliner *soops, int startx, int *starty) { const float col_highlight[4] = {1.0f, 1.0f, 1.0f, 0.13f}; - float col_selection[4], col_searchmatch[4]; + float col_selection[4], col_active[4], col_searchmatch[4]; UI_GetThemeColor3fv(TH_SELECT_HIGHLIGHT, col_selection); col_selection[3] = 1.0f; /* no alpha */ + UI_GetThemeColor3fv(TH_SELECT_ACTIVE, col_active); + col_active[3] = 1.0f; /* no alpha */ UI_GetThemeColor4fv(TH_MATCH, col_searchmatch); col_searchmatch[3] = 0.5f; @@ -3282,8 +3471,16 @@ static void outliner_draw_highlights(ARegion *ar, SpaceOutliner *soops, int star GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - outliner_draw_highlights_recursive( - pos, ar, soops, &soops->tree, col_selection, col_highlight, col_searchmatch, startx, starty); + outliner_draw_highlights_recursive(pos, + ar, + soops, + &soops->tree, + col_selection, + col_active, + col_highlight, + col_searchmatch, + startx, + starty); immUnbindProgram(); GPU_blend(false); } @@ -3439,6 +3636,17 @@ void draw_outliner(const bContext *C) outliner_build_tree(mainvar, scene, view_layer, soops, ar); // always + /* If global sync select is dirty, flag other outliners */ + if (ED_outliner_select_sync_is_dirty(C)) { + ED_outliner_select_sync_flag_outliners(C); + } + + /* Sync selection state from view layer */ + if (!ELEM(soops->outlinevis, SO_LIBRARIES, SO_DATA_API, SO_ID_ORPHANS) && + soops->flag & SO_SYNC_SELECT) { + outliner_sync_selection(C, soops); + } + /* force display to pixel coords */ v2d->flag |= (V2D_PIXELOFS_X | V2D_PIXELOFS_Y); /* set matrix for 2d-view controls */ diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index de6e89e47c4..943993cb810 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -101,9 +101,15 @@ static int outliner_highlight_update(bContext *C, wmOperator *UNUSED(op), const ARegion *ar = CTX_wm_region(C); SpaceOutliner *soops = CTX_wm_space_outliner(C); - const float my = UI_view2d_region_to_view_y(&ar->v2d, event->mval[1]); - TreeElement *hovered_te = outliner_find_item_at_y(soops, &soops->tree, my); + float view_mval[2]; + UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]); + + TreeElement *hovered_te = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]); + + if (hovered_te) { + hovered_te = outliner_find_item_at_x_in_row(soops, hovered_te, view_mval[0], NULL); + } bool changed = false; if (!hovered_te || !(hovered_te->store_elem->flag & TSE_HIGHLIGHTED)) { @@ -134,59 +140,108 @@ void OUTLINER_OT_highlight_update(wmOperatorType *ot) /* Toggle Open/Closed ------------------------------------------- */ -static int do_outliner_item_openclose( - bContext *C, SpaceOutliner *soops, TreeElement *te, const bool all, const float mval[2]) +/* Open or close a tree element, optionally toggling all children recursively */ +void outliner_item_openclose(TreeElement *te, bool open, bool toggle_all) { + TreeStoreElem *tselem = TREESTORE(te); - if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) { - TreeStoreElem *tselem = TREESTORE(te); + if (open) { + tselem->flag &= ~TSE_CLOSED; + } + else { + tselem->flag |= TSE_CLOSED; + } - /* all below close/open? */ - if (all) { - tselem->flag &= ~TSE_CLOSED; - outliner_flag_set( - &te->subtree, TSE_CLOSED, !outliner_flag_is_any_test(&te->subtree, TSE_CLOSED, 1)); - } - else { - if (tselem->flag & TSE_CLOSED) { - tselem->flag &= ~TSE_CLOSED; - } - else { - tselem->flag |= TSE_CLOSED; + if (toggle_all) { + outliner_flag_set(&te->subtree, TSE_CLOSED, !open); + } +} + +typedef struct OpenCloseData { + TreeStoreElem *prev_tselem; + bool open; + int x_location; +} OpenCloseData; + +static int outliner_item_openclose_modal(bContext *C, wmOperator *op, const wmEvent *event) +{ + ARegion *ar = CTX_wm_region(C); + SpaceOutliner *soops = CTX_wm_space_outliner(C); + + float view_mval[2]; + UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]); + + if (event->type == MOUSEMOVE) { + TreeElement *te = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]); + + OpenCloseData *data = (OpenCloseData *)op->customdata; + + /* Only openclose if mouse is not over the previously toggled element */ + if (te && TREESTORE(te) != data->prev_tselem) { + + /* Only toggle openclose on the same level as the first clicked element */ + if (te->xs == data->x_location) { + outliner_item_openclose(te, data->open, false); + ED_region_tag_redraw(ar); } } - return 1; + if (te) { + data->prev_tselem = TREESTORE(te); + } + else { + data->prev_tselem = NULL; + } } + else if (event->val == KM_RELEASE) { + MEM_freeN(op->customdata); - for (te = te->subtree.first; te; te = te->next) { - if (do_outliner_item_openclose(C, soops, te, all, mval)) { - return 1; - } + return OPERATOR_FINISHED; } - return 0; + + return OPERATOR_RUNNING_MODAL; } -/* event can enterkey, then it opens/closes */ -static int outliner_item_openclose(bContext *C, wmOperator *op, const wmEvent *event) +static int outliner_item_openclose_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ARegion *ar = CTX_wm_region(C); SpaceOutliner *soops = CTX_wm_space_outliner(C); - TreeElement *te; - float fmval[2]; - const bool all = RNA_boolean_get(op->ptr, "all"); - UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]); + const bool toggle_all = RNA_boolean_get(op->ptr, "all"); - for (te = soops->tree.first; te; te = te->next) { - if (do_outliner_item_openclose(C, soops, te, all, fmval)) { - break; + float view_mval[2]; + UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]); + + TreeElement *te = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]); + + if (te && outliner_item_is_co_within_close_toggle(te, view_mval[0])) { + TreeStoreElem *tselem = TREESTORE(te); + + const bool open = (tselem->flag & TSE_CLOSED) || + (toggle_all && (outliner_flag_is_any_test(&te->subtree, TSE_CLOSED, 1))); + + outliner_item_openclose(te, open, toggle_all); + ED_region_tag_redraw(ar); + + /* Only toggle once for single click toggling */ + if (event->type == LEFTMOUSE) { + return OPERATOR_FINISHED; } - } - ED_region_tag_redraw(ar); + /* Store last expanded tselem and x coordinate of disclosure triangle */ + OpenCloseData *toggle_data = MEM_callocN(sizeof(OpenCloseData), "open_close_data"); + toggle_data->prev_tselem = tselem; + toggle_data->open = open; + toggle_data->x_location = te->xs; - return OPERATOR_FINISHED; + /* Store the first clicked on element */ + op->customdata = toggle_data; + + WM_event_add_modal_handler(C, op); + return OPERATOR_RUNNING_MODAL; + } + + return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH; } void OUTLINER_OT_item_openclose(wmOperatorType *ot) @@ -195,11 +250,12 @@ void OUTLINER_OT_item_openclose(wmOperatorType *ot) ot->idname = "OUTLINER_OT_item_openclose"; ot->description = "Toggle whether item under cursor is enabled or closed"; - ot->invoke = outliner_item_openclose; + ot->invoke = outliner_item_openclose_invoke; + ot->modal = outliner_item_openclose_modal; ot->poll = ED_operator_outliner_active; - RNA_def_boolean(ot->srna, "all", 1, "All", "Close or open all items"); + RNA_def_boolean(ot->srna, "all", false, "All", "Close or open all items"); } /* -------------------------------------------------------------------- */ @@ -330,10 +386,10 @@ void item_rename_cb(bContext *C, do_item_rename(ar, te, tselem, reports); } -static int do_outliner_item_rename(ReportList *reports, - ARegion *ar, - TreeElement *te, - const float mval[2]) +static void do_outliner_item_rename(ReportList *reports, + ARegion *ar, + TreeElement *te, + const float mval[2]) { if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) { TreeStoreElem *tselem = TREESTORE(te); @@ -341,17 +397,12 @@ static int do_outliner_item_rename(ReportList *reports, /* click on name */ if (mval[0] > te->xs + UI_UNIT_X * 2 && mval[0] < te->xend) { do_item_rename(ar, te, tselem, reports); - return 1; } - return 0; } for (te = te->subtree.first; te; te = te->next) { - if (do_outliner_item_rename(reports, ar, te, mval)) { - return 1; - } + do_outliner_item_rename(reports, ar, te, mval); } - return 0; } static int outliner_item_rename(bContext *C, wmOperator *op, const wmEvent *event) @@ -360,25 +411,34 @@ static int outliner_item_rename(bContext *C, wmOperator *op, const wmEvent *even SpaceOutliner *soops = CTX_wm_space_outliner(C); TreeElement *te; float fmval[2]; - bool changed = false; - UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]); + /* Rename active element if key pressed, otherwise rename element at cursor coordinates */ + if (event->val == KM_PRESS) { + TreeElement *active_element = outliner_find_element_with_flag(&soops->tree, TSE_ACTIVE); - for (te = soops->tree.first; te; te = te->next) { - if (do_outliner_item_rename(op->reports, ar, te, fmval)) { - changed = true; - break; + if (active_element) { + do_item_rename(ar, active_element, TREESTORE(active_element), op->reports); + } + else { + BKE_report(op->reports, RPT_WARNING, "No active item to rename"); } } + else { + UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]); - return changed ? OPERATOR_FINISHED : OPERATOR_PASS_THROUGH; + for (te = soops->tree.first; te; te = te->next) { + do_outliner_item_rename(op->reports, ar, te, fmval); + } + } + + return OPERATOR_FINISHED; } void OUTLINER_OT_item_rename(wmOperatorType *ot) { ot->name = "Rename"; ot->idname = "OUTLINER_OT_item_rename"; - ot->description = "Rename item under cursor"; + ot->description = "Rename the active element"; ot->invoke = outliner_item_rename; @@ -1103,6 +1163,10 @@ static int outliner_select_all_exec(bContext *C, wmOperator *op) break; } + if (soops->flag & SO_SYNC_SELECT) { + ED_outliner_select_sync_from_outliner(C, soops); + } + DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); ED_region_tag_redraw_no_rebuild(ar); @@ -1179,20 +1243,17 @@ static int outliner_open_back(TreeElement *te) return retval; } -static int outliner_show_active_exec(bContext *C, wmOperator *UNUSED(op)) +/* Return element representing the active base or bone in the outliner, or NULL if none exists */ +static TreeElement *outliner_show_active_get_element(bContext *C, + SpaceOutliner *so, + ViewLayer *view_layer) { - SpaceOutliner *so = CTX_wm_space_outliner(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - ARegion *ar = CTX_wm_region(C); - View2D *v2d = &ar->v2d; - TreeElement *te; - int xdelta, ytop; Object *obact = OBACT(view_layer); if (!obact) { - return OPERATOR_CANCELLED; + return NULL; } te = outliner_find_id(so, &so->tree, &obact->id); @@ -1215,25 +1276,50 @@ static int outliner_show_active_exec(bContext *C, wmOperator *UNUSED(op)) } } - if (te) { - /* open up tree to active object/bone */ + return te; +} + +static void outliner_show_active(SpaceOutliner *so, ARegion *ar, TreeElement *te, ID *id) +{ + /* open up tree to active object/bone */ + if (TREESTORE(te)->id == id) { if (outliner_open_back(te)) { outliner_set_coordinates(ar, so); } + return; + } + + for (TreeElement *ten = te->subtree.first; ten; ten = ten->next) { + outliner_show_active(so, ar, ten, id); + } +} + +static int outliner_show_active_exec(bContext *C, wmOperator *UNUSED(op)) +{ + SpaceOutliner *so = CTX_wm_space_outliner(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + ARegion *ar = CTX_wm_region(C); + View2D *v2d = &ar->v2d; + + TreeElement *active_element = outliner_show_active_get_element(C, so, view_layer); - /* make te->ys center of view */ - ytop = te->ys + BLI_rcti_size_y(&v2d->mask) / 2; - if (ytop > 0) { - ytop = 0; + if (active_element) { + ID *id = TREESTORE(active_element)->id; + + /* Expand all elements in the outliner with matching ID */ + for (TreeElement *te = so->tree.first; te; te = te->next) { + outliner_show_active(so, ar, te, id); } - v2d->cur.ymax = (float)ytop; - v2d->cur.ymin = (float)(ytop - BLI_rcti_size_y(&v2d->mask)); + /* Center view on first element found */ + int size_y = BLI_rcti_size_y(&v2d->mask) + 1; + int ytop = (active_element->ys + (size_y / 2)); + int delta_y = ytop - v2d->cur.ymax; - /* make te->xs ==> te->xend center of view */ - xdelta = (int)(te->xs - v2d->cur.xmin); - v2d->cur.xmin += xdelta; - v2d->cur.xmax += xdelta; + outliner_scroll_view(ar, delta_y); + } + else { + return OPERATOR_CANCELLED; } ED_region_tag_redraw_no_rebuild(ar); @@ -1259,18 +1345,15 @@ void OUTLINER_OT_show_active(wmOperatorType *ot) static int outliner_scroll_page_exec(bContext *C, wmOperator *op) { ARegion *ar = CTX_wm_region(C); - int dy = BLI_rcti_size_y(&ar->v2d.mask); - int up = 0; + int size_y = BLI_rcti_size_y(&ar->v2d.mask) + 1; - if (RNA_boolean_get(op->ptr, "up")) { - up = 1; - } + bool up = RNA_boolean_get(op->ptr, "up"); - if (up == 0) { - dy = -dy; + if (!up) { + size_y = -size_y; } - ar->v2d.cur.ymin += dy; - ar->v2d.cur.ymax += dy; + + outliner_scroll_view(ar, size_y); ED_region_tag_redraw_no_rebuild(ar); @@ -1697,7 +1780,7 @@ static void tree_element_to_path(TreeElement *te, /* no ID, so check if entry is RNA-struct, * and if that RNA-struct is an ID datablock to extract info from. */ if (tse->type == TSE_RNA_STRUCT) { - /* ptr->data not ptr->id.data seems to be the one we want, + /* ptr->data not ptr->owner_id seems to be the one we want, * since ptr->data is sometimes the owner of this ID? */ if (RNA_struct_is_ID(ptr->type)) { *id = (ID *)ptr->data; diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index fa28d119244..95e37dea249 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -40,7 +40,6 @@ struct TreeStoreElem; struct ViewLayer; struct bContext; struct bPoseChannel; -struct wmEvent; struct wmKeyConfig; struct wmOperatorType; @@ -50,6 +49,14 @@ typedef enum TreeElementInsertType { TE_INSERT_INTO, } TreeElementInsertType; +/* Use generic walk select after D4771 is committed */ +typedef enum WalkSelectDirection { + OUTLINER_SELECT_WALK_UP, + OUTLINER_SELECT_WALK_DOWN, + OUTLINER_SELECT_WALK_LEFT, + OUTLINER_SELECT_WALK_RIGHT, +} WalkSelectDirection; + typedef enum TreeTraversalAction { /* Continue traversal regularly, don't skip children. */ TRAVERSE_CONTINUE = 0, @@ -131,6 +138,9 @@ enum { TE_DISABLED = (1 << 4), TE_DRAGGING = (1 << 5), TE_CHILD_NOT_IN_COLLECTION = (1 << 6), + /* Child elements of the same type in the icon-row are drawn merged as one icon. + * This flag is set for an element that is part of these merged child icons. */ + TE_ICONROW_MERGED = (1 << 7), }; /* button events */ @@ -223,6 +233,8 @@ void outliner_collection_isolate_flag(struct Scene *scene, const char *propname, const bool value); +int tree_element_id_type_to_index(TreeElement *te); + /* outliner_select.c -------------------------------------------- */ eOLDrawState tree_element_type_active(struct bContext *C, struct Scene *scene, @@ -253,6 +265,10 @@ void outliner_object_mode_toggle(struct bContext *C, ViewLayer *view_layer, Base *base); +void outliner_element_activate(struct SpaceOutliner *soops, struct TreeStoreElem *tselem); + +bool outliner_item_is_co_within_close_toggle(TreeElement *te, float view_co_x); + /* outliner_edit.c ---------------------------------------------- */ typedef void (*outliner_operation_cb)(struct bContext *C, struct ReportList *, @@ -337,6 +353,8 @@ void item_object_mode_exit_cb(struct bContext *C, void outliner_set_coordinates(struct ARegion *ar, struct SpaceOutliner *soops); +void outliner_item_openclose(TreeElement *te, bool open, bool toggle_all); + /* outliner_dragdrop.c */ void outliner_dropboxes(void); @@ -364,6 +382,7 @@ void OUTLINER_OT_show_active(struct wmOperatorType *ot); void OUTLINER_OT_show_hierarchy(struct wmOperatorType *ot); void OUTLINER_OT_select_box(struct wmOperatorType *ot); +void OUTLINER_OT_select_walk(struct wmOperatorType *ot); void OUTLINER_OT_select_all(struct wmOperatorType *ot); void OUTLINER_OT_expanded_toggle(struct wmOperatorType *ot); @@ -380,6 +399,10 @@ void OUTLINER_OT_orphans_purge(struct wmOperatorType *ot); /* outliner_tools.c ---------------------------------------------- */ +void merged_element_search_menu_invoke(struct bContext *C, + TreeElement *parent_te, + TreeElement *activate_te); + void OUTLINER_OT_operation(struct wmOperatorType *ot); void OUTLINER_OT_scene_operation(struct wmOperatorType *ot); void OUTLINER_OT_object_operation(struct wmOperatorType *ot); @@ -439,7 +462,8 @@ TreeElement *outliner_find_item_at_y(const SpaceOutliner *soops, float view_co_y); TreeElement *outliner_find_item_at_x_in_row(const SpaceOutliner *soops, const TreeElement *parent_te, - float view_co_x); + float view_co_x, + bool *multiple_objects); TreeElement *outliner_find_tse(struct SpaceOutliner *soops, const TreeStoreElem *tse); TreeElement *outliner_find_tree_element(ListBase *lb, const TreeStoreElem *store_elem); TreeElement *outliner_find_parent_element(ListBase *lb, @@ -456,5 +480,12 @@ bool outliner_tree_traverse(const SpaceOutliner *soops, TreeTraversalFunc func, void *customdata); float outliner_restrict_columns_width(const struct SpaceOutliner *soops); +TreeElement *outliner_find_element_with_flag(const ListBase *lb, short flag); +bool outliner_is_element_visible(const TreeElement *te); +void outliner_scroll_view(struct ARegion *ar, int delta_y); + +/* outliner_sync.c ---------------------------------------------- */ + +void outliner_sync_selection(const struct bContext *C, struct SpaceOutliner *soops); #endif /* __OUTLINER_INTERN_H__ */ diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c index f155a2d5f89..4b57d4ad771 100644 --- a/source/blender/editors/space_outliner/outliner_ops.c +++ b/source/blender/editors/space_outliner/outliner_ops.c @@ -50,6 +50,7 @@ void outliner_operatortypes(void) WM_operatortype_append(OUTLINER_OT_highlight_update); WM_operatortype_append(OUTLINER_OT_item_activate); WM_operatortype_append(OUTLINER_OT_select_box); + WM_operatortype_append(OUTLINER_OT_select_walk); WM_operatortype_append(OUTLINER_OT_item_openclose); WM_operatortype_append(OUTLINER_OT_item_rename); WM_operatortype_append(OUTLINER_OT_item_drag_drop); diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index 7f45c4d22fa..44e67fa1508 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -51,14 +51,16 @@ #include "BKE_workspace.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" #include "ED_armature.h" +#include "ED_gpencil.h" #include "ED_object.h" +#include "ED_outliner.h" #include "ED_screen.h" #include "ED_select_utils.h" #include "ED_sequencer.h" #include "ED_undo.h" -#include "ED_gpencil.h" #include "WM_api.h" #include "WM_types.h" @@ -251,9 +253,7 @@ static eOLDrawState active_viewlayer(bContext *C, } /** - * Select object tree: - * CTRL+LMB: Select/Deselect object and all children. - * CTRL+SHIFT+LMB: Add/Remove object and all children. + * Select object tree */ static void do_outliner_object_select_recursive(ViewLayer *view_layer, Object *ob_parent, @@ -450,9 +450,9 @@ static eOLDrawState tree_element_active_material(bContext *C, return OL_DRAWSEL_NONE; } -static eOLDrawState tree_element_active_camera(bContext *UNUSED(C), +static eOLDrawState tree_element_active_camera(bContext *C, Scene *scene, - ViewLayer *UNUSED(sl), + ViewLayer *UNUSED(view_layer), SpaceOutliner *soops, TreeElement *te, const eOLSetState set) @@ -460,10 +460,21 @@ static eOLDrawState tree_element_active_camera(bContext *UNUSED(C), Object *ob = (Object *)outliner_search_back(soops, te, ID_OB); if (set != OL_SETSEL_NONE) { + scene->camera = ob; + + Main *bmain = CTX_data_main(C); + wmWindowManager *wm = bmain->wm.first; + + WM_windows_scene_data_sync(&wm->windows, scene); + DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); + DEG_relations_tag_update(bmain); + WM_event_add_notifier(C, NC_SCENE | NA_EDITED, NULL); + return OL_DRAWSEL_NONE; } - - return scene->camera == ob; + else { + return scene->camera == ob; + } } static eOLDrawState tree_element_active_world(bContext *C, @@ -1083,6 +1094,13 @@ eOLDrawState tree_element_type_active(bContext *C, /* ================================================ */ +/* Activate a tree store element and set the walk navigation start element */ +void outliner_element_activate(SpaceOutliner *soops, TreeStoreElem *tselem) +{ + outliner_flag_set(&soops->tree, TSE_ACTIVE | TSE_ACTIVE_WALK, false); + tselem->flag |= TSE_ACTIVE | TSE_ACTIVE_WALK; +} + /** * Action when clicking to activate an item (typically under the mouse cursor), * but don't do any cursor intersection checks. @@ -1114,7 +1132,8 @@ static void do_outliner_item_activate_tree_element(bContext *C, else if (tselem->type == TSE_POSE_BASE) { /* Support pose mode toggle, keeping the active object as is. */ } - else { + else if (soops->flag & SO_SYNC_SELECT) { + /* Only activate when synced selection is enabled */ tree_element_set_active_object(C, scene, view_layer, @@ -1125,6 +1144,9 @@ static void do_outliner_item_activate_tree_element(bContext *C, recursive && tselem->type == 0); } + /* Mark as active in the outliner */ + outliner_element_activate(soops, tselem); + if (tselem->type == 0) { // the lib blocks /* editmode? */ if (te->idcode == ID_SCE) { @@ -1189,7 +1211,7 @@ static void do_outliner_item_activate_tree_element(bContext *C, tree_element_active(C, scene, view_layer, soops, te, OL_SETSEL_NORMAL, false); } } - else { + else if (soops->flag & SO_SYNC_SELECT) { tree_element_type_active(C, scene, view_layer, @@ -1211,7 +1233,8 @@ void outliner_item_select(SpaceOutliner *soops, const bool toggle) { TreeStoreElem *tselem = TREESTORE(te); - const short new_flag = toggle ? (tselem->flag ^ TSE_SELECTED) : (tselem->flag | TSE_SELECTED); + const short new_flag = (toggle && (tselem->flag & TSE_ACTIVE)) ? (tselem->flag ^ TSE_SELECTED) : + (tselem->flag | TSE_SELECTED); if (extend == false) { outliner_flag_set(&soops->tree, TSE_SELECTED, false); @@ -1219,24 +1242,72 @@ void outliner_item_select(SpaceOutliner *soops, tselem->flag = new_flag; } -static void outliner_item_toggle_closed(TreeElement *te, const bool toggle_children) +static bool do_outliner_range_select_recursive(ListBase *lb, + TreeElement *active, + TreeElement *cursor, + bool selecting) { - TreeStoreElem *tselem = TREESTORE(te); - if (toggle_children) { - tselem->flag &= ~TSE_CLOSED; + for (TreeElement *te = lb->first; te; te = te->next) { + TreeStoreElem *tselem = TREESTORE(te); - const bool all_opened = !outliner_flag_is_any_test(&te->subtree, TSE_CLOSED, 1); - outliner_flag_set(&te->subtree, TSE_CLOSED, all_opened); - } - else { - tselem->flag ^= TSE_CLOSED; + if (selecting) { + tselem->flag |= TSE_SELECTED; + } + + /* Set state for selection */ + if (te == active || te == cursor) { + selecting = !selecting; + } + + if (selecting) { + tselem->flag |= TSE_SELECTED; + } + + /* Don't look inside closed elements */ + if (!(tselem->flag & TSE_CLOSED)) { + selecting = do_outliner_range_select_recursive(&te->subtree, active, cursor, selecting); + } } + + return selecting; } -static bool outliner_item_is_co_within_close_toggle(TreeElement *te, float view_co_x) +/* Select a range of items between cursor and active element */ +static void do_outliner_range_select(bContext *C, + SpaceOutliner *soops, + TreeElement *cursor, + const bool extend) { - return ((te->flag & TE_ICONROW) == 0) && (view_co_x > te->xs) && - (view_co_x < te->xs + UI_UNIT_X); + TreeElement *active = outliner_find_element_with_flag(&soops->tree, TSE_ACTIVE); + + /* If no active element exists, activate the element under the cursor */ + if (!active) { + outliner_item_select(soops, cursor, false, false); + outliner_item_do_activate_from_tree_element(C, cursor, TREESTORE(cursor), false, false); + return; + } + + TreeStoreElem *tselem = TREESTORE(active); + const bool active_selected = (tselem->flag & TSE_SELECTED); + + if (!extend) { + outliner_flag_set(&soops->tree, TSE_SELECTED, false); + } + + /* Select active if under cursor */ + if (active == cursor) { + TREESTORE(cursor)->flag |= TSE_SELECTED; + return; + } + + /* If active is not selected, select the element under the cursor */ + if (!active_selected || !outliner_is_element_visible(active)) { + outliner_item_select(soops, cursor, false, false); + outliner_item_do_activate_from_tree_element(C, cursor, TREESTORE(cursor), false, false); + return; + } + + do_outliner_range_select_recursive(&soops->tree, active, cursor, false); } static bool outliner_is_co_within_restrict_columns(const SpaceOutliner *soops, @@ -1247,7 +1318,7 @@ static bool outliner_is_co_within_restrict_columns(const SpaceOutliner *soops, } /** - * A version of #outliner_item_do_acticate_from_cursor that takes the tree element directly. + * A version of #outliner_item_do_activate_from_cursor that takes the tree element directly. * and doesn't depend on the pointer position. * * This allows us to simulate clicking on an item without dealing with the mouse cursor. @@ -1271,10 +1342,11 @@ void outliner_item_do_activate_from_tree_element( static int outliner_item_do_activate_from_cursor(bContext *C, const int mval[2], const bool extend, - const bool recursive, + const bool use_range, const bool deselect_all) { ARegion *ar = CTX_wm_region(C); + Scene *scene = CTX_data_scene(C); SpaceOutliner *soops = CTX_wm_space_outliner(C); TreeElement *te; float view_mval[2]; @@ -1292,28 +1364,36 @@ static int outliner_item_do_activate_from_cursor(bContext *C, changed = true; } } - else if (outliner_item_is_co_within_close_toggle(te, view_mval[0])) { - outliner_item_toggle_closed(te, extend); - changed = true; - rebuild_tree = true; + /* Don't allow toggle on scene collection */ + else if ((TREESTORE(te)->type != TSE_VIEW_COLLECTION_BASE) && + outliner_item_is_co_within_close_toggle(te, view_mval[0])) { + return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH; } else { - Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - /* the row may also contain children, if one is hovered we want this instead of current te */ - TreeElement *activate_te = outliner_find_item_at_x_in_row(soops, te, view_mval[0]); - TreeStoreElem *activate_tselem = TREESTORE(activate_te); - outliner_item_select(soops, activate_te, extend, extend); + /* The row may also contain children, if one is hovered we want this instead of current te */ + bool merged_elements = false; + TreeElement *activate_te = outliner_find_item_at_x_in_row( + soops, te, view_mval[0], &merged_elements); - /* Only change modes when clicking on the icon/text, - * otherwise we can't easily select without changing modes. */ - if ((te->flag & TE_ICONROW) == 0) { - if (view_mval[0] >= te->xs && view_mval[0] <= te->xend) { - do_outliner_item_activate_tree_element( - C, scene, view_layer, soops, activate_te, activate_tselem, extend, recursive); - } + /* If the selected icon was an aggregate of multiple elements, run the search popup */ + if (merged_elements) { + merged_element_search_menu_invoke(C, te, activate_te); + return OPERATOR_CANCELLED; + } + + TreeStoreElem *activate_tselem = TREESTORE(activate_te); + + if (use_range) { + do_outliner_range_select(C, soops, activate_te, extend); + } + else { + outliner_item_select(soops, activate_te, extend, extend); + do_outliner_item_activate_tree_element( + C, scene, view_layer, soops, activate_te, activate_tselem, extend, false); } + changed = true; } @@ -1324,7 +1404,10 @@ static int outliner_item_do_activate_from_cursor(bContext *C, else { ED_region_tag_redraw_no_rebuild(ar); } - ED_undo_push(C, "Outliner selection change"); + + if (soops->flag & SO_SYNC_SELECT) { + ED_outliner_select_sync_from_outliner(C, soops); + } } return OPERATOR_FINISHED; @@ -1334,9 +1417,9 @@ static int outliner_item_do_activate_from_cursor(bContext *C, static int outliner_item_activate_invoke(bContext *C, wmOperator *op, const wmEvent *event) { const bool extend = RNA_boolean_get(op->ptr, "extend"); - const bool recursive = RNA_boolean_get(op->ptr, "recursive"); + const bool use_range = RNA_boolean_get(op->ptr, "extend_range"); const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all"); - return outliner_item_do_activate_from_cursor(C, event->mval, extend, recursive, deselect_all); + return outliner_item_do_activate_from_cursor(C, event->mval, extend, use_range, deselect_all); } void OUTLINER_OT_item_activate(wmOperatorType *ot) @@ -1349,9 +1432,14 @@ void OUTLINER_OT_item_activate(wmOperatorType *ot) ot->poll = ED_operator_outliner_active; + ot->flag |= OPTYPE_REGISTER | OPTYPE_UNDO; + PropertyRNA *prop; RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend selection for activation"); - RNA_def_boolean(ot->srna, "recursive", false, "Recursive", "Select Objects and their children"); + prop = RNA_def_boolean( + ot->srna, "extend_range", false, "Extend Range", "Select a range from active element"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "deselect_all", false, @@ -1409,9 +1497,44 @@ static int outliner_box_select_exec(bContext *C, wmOperator *op) WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); ED_region_tag_redraw(ar); + if (soops->flag & SO_SYNC_SELECT) { + ED_outliner_select_sync_from_outliner(C, soops); + } + return OPERATOR_FINISHED; } +/* Find if x coordinate is over an icon or name */ +static bool outliner_item_is_co_over_name_icons(TreeElement *te, float view_co_x) +{ + /* Special case: count area left of Scene Collection as empty space */ + bool outside_left = (TREESTORE(te)->type == TSE_VIEW_COLLECTION_BASE) ? + (view_co_x > te->xs + UI_UNIT_X) : + (view_co_x > te->xs); + + return outside_left && (view_co_x < te->xend); +} + +static int outliner_box_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + SpaceOutliner *soops = CTX_wm_space_outliner(C); + ARegion *ar = CTX_wm_region(C); + float view_mval[2]; + const bool tweak = RNA_boolean_get(op->ptr, "tweak"); + + UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]); + + /* Find element clicked on */ + TreeElement *te = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]); + + /* Pass through if click is over name or icons, or not tweak event */ + if (te && tweak && outliner_item_is_co_over_name_icons(te, view_mval[0])) { + return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH; + } + + return WM_gesture_box_invoke(C, op, event); +} + void OUTLINER_OT_select_box(wmOperatorType *ot) { /* identifiers */ @@ -1420,7 +1543,7 @@ void OUTLINER_OT_select_box(wmOperatorType *ot) ot->description = "Use box selection to select tree elements"; /* api callbacks */ - ot->invoke = WM_gesture_box_invoke; + ot->invoke = outliner_box_select_invoke; ot->exec = outliner_box_select_exec; ot->modal = WM_gesture_box_modal; ot->cancel = WM_gesture_box_cancel; @@ -1431,8 +1554,242 @@ void OUTLINER_OT_select_box(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ + PropertyRNA *prop; + + prop = RNA_def_boolean( + ot->srna, "tweak", false, "Tweak", "Tweak gesture from empty space for box selection"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + WM_operator_properties_gesture_box(ot); WM_operator_properties_select_operation_simple(ot); } /* ****************************************************** */ + +/* **************** Walk Select Tool ****************** */ + +/* Given a tree element return the rightmost child that is visible in the outliner */ +static TreeElement *outliner_find_rightmost_visible_child(SpaceOutliner *soops, TreeElement *te) +{ + while (te->subtree.last) { + if (TSELEM_OPEN(TREESTORE(te), soops)) { + te = te->subtree.last; + } + else { + break; + } + } + return te; +} + +/* Find previous visible element in the tree */ +static TreeElement *outliner_find_previous_element(SpaceOutliner *soops, TreeElement *walk_element) +{ + if (walk_element->prev) { + walk_element = outliner_find_rightmost_visible_child(soops, walk_element->prev); + } + else if (walk_element->parent) { + /* Use parent if at beginning of list */ + walk_element = walk_element->parent; + } + + return walk_element; +} + +/* Recursively search up the tree until a successor to a given element is found */ +static TreeElement *outliner_element_find_successor_in_parents(TreeElement *te) +{ + TreeElement *successor = te; + while (successor->parent) { + if (successor->parent->next) { + te = successor->parent->next; + break; + } + else { + successor = successor->parent; + } + } + + return te; +} + +/* Find next visible element in the tree */ +static TreeElement *outliner_find_next_element(SpaceOutliner *soops, TreeElement *walk_element) +{ + TreeStoreElem *tselem = TREESTORE(walk_element); + + if (TSELEM_OPEN(tselem, soops) && walk_element->subtree.first) { + walk_element = walk_element->subtree.first; + } + else if (walk_element->next) { + walk_element = walk_element->next; + } + else { + walk_element = outliner_element_find_successor_in_parents(walk_element); + } + + return walk_element; +} + +static TreeElement *do_outliner_select_walk(SpaceOutliner *soops, + TreeElement *walk_element, + const int direction, + const bool extend, + const bool toggle_all) +{ + TreeStoreElem *tselem = TREESTORE(walk_element); + + if (!extend) { + outliner_flag_set(&soops->tree, TSE_SELECTED, false); + } + tselem->flag &= ~TSE_ACTIVE_WALK; + + switch (direction) { + case OUTLINER_SELECT_WALK_UP: + walk_element = outliner_find_previous_element(soops, walk_element); + break; + case OUTLINER_SELECT_WALK_DOWN: + walk_element = outliner_find_next_element(soops, walk_element); + break; + case OUTLINER_SELECT_WALK_LEFT: + outliner_item_openclose(walk_element, false, toggle_all); + break; + case OUTLINER_SELECT_WALK_RIGHT: + outliner_item_openclose(walk_element, true, toggle_all); + break; + } + + TreeStoreElem *tselem_new = TREESTORE(walk_element); + + /* If new element is already selected, deselect the previous element */ + if (extend) { + tselem->flag = (tselem_new->flag & TSE_SELECTED) ? (tselem->flag & ~TSE_SELECTED) : + (tselem->flag | TSE_SELECTED); + } + + tselem_new->flag |= TSE_SELECTED | TSE_ACTIVE_WALK; + + return walk_element; +} + +/* Find walk select element, or set it if it does not exist. + * Changed is set to true if walk element is found, false if it was set */ +static TreeElement *find_walk_select_start_element(SpaceOutliner *soops, bool *changed) +{ + TreeElement *walk_element = outliner_find_element_with_flag(&soops->tree, TSE_ACTIVE_WALK); + + *changed = false; + + /* If no walk element exists, start from active */ + if (!walk_element) { + TreeElement *active_element = outliner_find_element_with_flag(&soops->tree, TSE_ACTIVE); + + /* If no active element exists, use the first element in the tree */ + if (!active_element) { + walk_element = soops->tree.first; + } + else { + walk_element = active_element; + } + + *changed = true; + } + + /* If walk element is not visible, set that element's first visible parent as walk element */ + if (!outliner_is_element_visible(walk_element)) { + TREESTORE(walk_element)->flag &= ~TSE_ACTIVE_WALK; + + while (!outliner_is_element_visible(walk_element)) { + walk_element = walk_element->parent; + } + *changed = true; + } + + return walk_element; +} + +/* Scroll the outliner when the walk element reaches the top or bottom boundary */ +static void outliner_walk_scroll(ARegion *ar, TreeElement *te) +{ + /* Account for the header height */ + int y_max = ar->v2d.cur.ymax - UI_UNIT_Y; + int y_min = ar->v2d.cur.ymin; + + /* Scroll if walked position is beyond the border */ + if (te->ys > y_max) { + outliner_scroll_view(ar, te->ys - y_max); + } + else if (te->ys < y_min) { + outliner_scroll_view(ar, -(y_min - te->ys)); + } +} + +static int outliner_walk_select_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + SpaceOutliner *soops = CTX_wm_space_outliner(C); + ARegion *ar = CTX_wm_region(C); + + const short direction = RNA_enum_get(op->ptr, "direction"); + const bool extend = RNA_boolean_get(op->ptr, "extend"); + const bool toggle_all = RNA_boolean_get(op->ptr, "toggle_all"); + + bool changed; + TreeElement *walk_element = find_walk_select_start_element(soops, &changed); + + /* If finding the starting walk select element did not move the element, proceed to walk */ + if (!changed) { + walk_element = do_outliner_select_walk(soops, walk_element, direction, extend, toggle_all); + } + else { + TREESTORE(walk_element)->flag |= TSE_SELECTED | TSE_ACTIVE_WALK; + } + + /* Scroll outliner to focus on walk element */ + outliner_walk_scroll(ar, walk_element); + + if (soops->flag & SO_SYNC_SELECT) { + ED_outliner_select_sync_from_outliner(C, soops); + } + ED_region_tag_redraw(ar); + + return OPERATOR_FINISHED; +} + +void OUTLINER_OT_select_walk(wmOperatorType *ot) +{ + static const EnumPropertyItem direction_items[] = { + {OUTLINER_SELECT_WALK_UP, "UP", 0, "Up", ""}, + {OUTLINER_SELECT_WALK_DOWN, "DOWN", 0, "Down", ""}, + {OUTLINER_SELECT_WALK_LEFT, "LEFT", 0, "Left", ""}, + {OUTLINER_SELECT_WALK_RIGHT, "RIGHT", 0, "Right", ""}, + {0, NULL, 0, NULL, NULL}, + }; + + /* identifiers */ + ot->name = "Walk Select"; + ot->idname = "OUTLINER_OT_select_walk"; + ot->description = "Use walk navigation to select tree elements"; + + /* api callbacks */ + ot->invoke = outliner_walk_select_invoke; + ot->poll = ED_operator_outliner_active; + + ot->flag |= OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + PropertyRNA *prop; + prop = RNA_def_enum(ot->srna, + "direction", + direction_items, + 0, + "Walk Direction", + "Select element in this direction"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection on walk"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean( + ot->srna, "toggle_all", false, "Toggle All", "Toggle open/close hierarchy"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); +} + +/* ****************************************************** */ diff --git a/source/blender/editors/space_outliner/outliner_sync.c b/source/blender/editors/space_outliner/outliner_sync.c new file mode 100644 index 00000000000..29c820bce92 --- /dev/null +++ b/source/blender/editors/space_outliner/outliner_sync.c @@ -0,0 +1,575 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2004 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup spoutliner + */ + +#include <stdio.h> + +#include "DNA_armature_types.h" +#include "DNA_layer_types.h" +#include "DNA_outliner_types.h" +#include "DNA_screen_types.h" +#include "DNA_sequence_types.h" +#include "DNA_space_types.h" + +#include "BLI_compiler_compat.h" +#include "BLI_ghash.h" + +#include "BKE_armature.h" +#include "BKE_context.h" +#include "BKE_layer.h" +#include "BKE_main.h" +#include "BKE_sequencer.h" + +#include "DEG_depsgraph.h" + +#include "ED_armature.h" +#include "ED_object.h" +#include "ED_outliner.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "outliner_intern.h" + +/* Functions for tagging outliner selection syncing is dirty from operators */ +void ED_outliner_select_sync_from_object_tag(bContext *C) +{ + wmWindowManager *wm = CTX_wm_manager(C); + wm->outliner_sync_select_dirty |= WM_OUTLINER_SYNC_SELECT_FROM_OBJECT; +} + +void ED_outliner_select_sync_from_edit_bone_tag(bContext *C) +{ + wmWindowManager *wm = CTX_wm_manager(C); + wm->outliner_sync_select_dirty |= WM_OUTLINER_SYNC_SELECT_FROM_EDIT_BONE; +} + +void ED_outliner_select_sync_from_pose_bone_tag(bContext *C) +{ + wmWindowManager *wm = CTX_wm_manager(C); + wm->outliner_sync_select_dirty |= WM_OUTLINER_SYNC_SELECT_FROM_POSE_BONE; +} + +void ED_outliner_select_sync_from_sequence_tag(bContext *C) +{ + wmWindowManager *wm = CTX_wm_manager(C); + wm->outliner_sync_select_dirty |= WM_OUTLINER_SYNC_SELECT_FROM_SEQUENCE; +} + +void ED_outliner_select_sync_from_all_tag(bContext *C) +{ + wmWindowManager *wm = CTX_wm_manager(C); + wm->outliner_sync_select_dirty |= WM_OUTLINER_SYNC_SELECT_FROM_ALL; +} + +bool ED_outliner_select_sync_is_dirty(const bContext *C) +{ + wmWindowManager *wm = CTX_wm_manager(C); + return wm->outliner_sync_select_dirty & WM_OUTLINER_SYNC_SELECT_FROM_ALL; +} + +/* Copy sync select dirty flag from window manager to all outliners to be synced lazily on draw */ +void ED_outliner_select_sync_flag_outliners(const bContext *C) +{ + Main *bmain = CTX_data_main(C); + wmWindowManager *wm = CTX_wm_manager(C); + + for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) { + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { + for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) { + if (sl->spacetype == SPACE_OUTLINER) { + SpaceOutliner *soutliner = (SpaceOutliner *)sl; + + soutliner->sync_select_dirty |= wm->outliner_sync_select_dirty; + } + } + } + } + + /* Clear global sync flag */ + wm->outliner_sync_select_dirty = 0; +} + +/** + * Outliner sync select dirty flags are not enough to determine which types to sync, + * outliner display mode also needs to be considered. This stores the types of data + * to sync to increase code clarity. + */ +typedef struct SyncSelectTypes { + bool object; + bool edit_bone; + bool pose_bone; + bool sequence; +} SyncSelectTypes; + +/** + * Set which types of data to sync when syncing selection from the outliner based on object + * interaction mode and outliner display mode + */ +static void outliner_sync_select_from_outliner_set_types(bContext *C, + SpaceOutliner *soops, + SyncSelectTypes *sync_types) +{ + Object *obact = CTX_data_active_object(C); + Object *obedit = CTX_data_edit_object(C); + + const bool sequence_view = soops->outlinevis == SO_SEQUENCE; + + sync_types->object = !sequence_view; + sync_types->edit_bone = !sequence_view && (obedit && obedit->type == OB_ARMATURE); + sync_types->pose_bone = !sequence_view && (obact && obact->mode == OB_MODE_POSE); + sync_types->sequence = sequence_view; +} + +/** + * Current dirty flags and outliner display mode determine which type of syncing should occur. + * This is to ensure sync flag data is not lost on sync in the wrong display mode. + * Returns true if a sync is needed. + */ +static bool outliner_sync_select_to_outliner_set_types(const bContext *C, + SpaceOutliner *soops, + SyncSelectTypes *sync_types) +{ + Object *obact = CTX_data_active_object(C); + Object *obedit = CTX_data_edit_object(C); + + const bool sequence_view = soops->outlinevis == SO_SEQUENCE; + + sync_types->object = !sequence_view && + (soops->sync_select_dirty & WM_OUTLINER_SYNC_SELECT_FROM_OBJECT); + sync_types->edit_bone = !sequence_view && (obedit && obedit->type == OB_ARMATURE) && + (soops->sync_select_dirty & WM_OUTLINER_SYNC_SELECT_FROM_EDIT_BONE); + sync_types->pose_bone = !sequence_view && (obact && obact->mode == OB_MODE_POSE) && + (soops->sync_select_dirty & WM_OUTLINER_SYNC_SELECT_FROM_POSE_BONE); + sync_types->sequence = sequence_view && + (soops->sync_select_dirty & WM_OUTLINER_SYNC_SELECT_FROM_SEQUENCE); + + return sync_types->object || sync_types->edit_bone || sync_types->pose_bone || + sync_types->sequence; +} + +/** + * Stores items selected from a sync from the outliner. Prevents syncing the selection + * state of the last instance of an object linked in multiple collections. + */ +typedef struct SelectedItems { + GSet *objects; + GSet *edit_bones; + GSet *pose_bones; +} SelectedItems; + +static void selected_items_init(SelectedItems *selected_items) +{ + selected_items->objects = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); + selected_items->edit_bones = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); + selected_items->pose_bones = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); +} + +static void selected_items_free(SelectedItems *selected_items) +{ + BLI_gset_free(selected_items->objects, NULL); + BLI_gset_free(selected_items->edit_bones, NULL); + BLI_gset_free(selected_items->pose_bones, NULL); +} + +/* Check if an instance of this object been selected by the sync */ +static bool is_object_selected(GSet *selected_objects, Base *base) +{ + return BLI_gset_haskey(selected_objects, base); +} + +/* Check if an instance of this edit bone been selected by the sync */ +static bool is_edit_bone_selected(GSet *selected_ebones, EditBone *ebone) +{ + return BLI_gset_haskey(selected_ebones, ebone); +} + +/* Check if an instance of this pose bone been selected by the sync */ +static bool is_pose_bone_selected(GSet *selected_pbones, bPoseChannel *pchan) +{ + return BLI_gset_haskey(selected_pbones, pchan); +} + +/* Add element's data to selected item set */ +static void add_selected_item(GSet *selected, void *data) +{ + BLI_gset_add(selected, data); +} + +static void outliner_select_sync_to_object(ViewLayer *view_layer, + TreeElement *te, + TreeStoreElem *tselem, + GSet *selected_objects) +{ + Object *ob = (Object *)tselem->id; + Base *base = (te->directdata) ? (Base *)te->directdata : + BKE_view_layer_base_find(view_layer, ob); + + if (base && (base->flag & BASE_SELECTABLE)) { + if (tselem->flag & TSE_SELECTED) { + ED_object_base_select(base, BA_SELECT); + + add_selected_item(selected_objects, base); + } + else if (!is_object_selected(selected_objects, base)) { + ED_object_base_select(base, BA_DESELECT); + } + } +} + +static void outliner_select_sync_to_edit_bone(ViewLayer *view_layer, + TreeElement *te, + TreeStoreElem *tselem, + GSet *selected_ebones) +{ + bArmature *arm = (bArmature *)tselem->id; + EditBone *ebone = (EditBone *)te->directdata; + + short bone_flag = ebone->flag; + + if (EBONE_SELECTABLE(arm, ebone)) { + if (tselem->flag & TSE_SELECTED) { + ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + + add_selected_item(selected_ebones, ebone); + } + else if (!is_edit_bone_selected(selected_ebones, ebone)) { + ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + } + } + + /* Tag if selection changed */ + if (bone_flag != ebone->flag) { + Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + DEG_id_tag_update(&arm->id, ID_RECALC_SELECT); + WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, obedit); + } +} + +static void outliner_select_sync_to_pose_bone(TreeElement *te, + TreeStoreElem *tselem, + GSet *selected_pbones) +{ + Object *ob = (Object *)tselem->id; + bArmature *arm = ob->data; + bPoseChannel *pchan = (bPoseChannel *)te->directdata; + + short bone_flag = pchan->bone->flag; + + if (PBONE_SELECTABLE(arm, pchan->bone)) { + if (tselem->flag & TSE_SELECTED) { + pchan->bone->flag |= BONE_SELECTED; + + add_selected_item(selected_pbones, pchan); + } + else if (!is_pose_bone_selected(selected_pbones, pchan)) { + pchan->bone->flag &= ~BONE_SELECTED; + } + } + + /* Tag if selection changed */ + if (bone_flag != pchan->bone->flag) { + DEG_id_tag_update(&arm->id, ID_RECALC_SELECT); + WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, ob); + } +} + +static void outliner_select_sync_to_sequence(Scene *scene, TreeStoreElem *tselem) +{ + Sequence *seq = (Sequence *)tselem->id; + + if (tselem->flag & TSE_ACTIVE) { + BKE_sequencer_active_set(scene, seq); + } + + if (tselem->flag & TSE_SELECTED) { + seq->flag |= SELECT; + } + else { + seq->flag &= ~SELECT; + } +} + +/** Sync select and active flags from outliner to active view layer, bones, and sequencer. */ +static void outliner_sync_selection_from_outliner(Scene *scene, + ViewLayer *view_layer, + ListBase *tree, + const SyncSelectTypes *sync_types, + SelectedItems *selected_items) +{ + + for (TreeElement *te = tree->first; te; te = te->next) { + TreeStoreElem *tselem = TREESTORE(te); + + if (tselem->type == 0 && te->idcode == ID_OB) { + if (sync_types->object) { + outliner_select_sync_to_object(view_layer, te, tselem, selected_items->objects); + } + } + else if (tselem->type == TSE_EBONE) { + if (sync_types->edit_bone) { + outliner_select_sync_to_edit_bone(view_layer, te, tselem, selected_items->edit_bones); + } + } + else if (tselem->type == TSE_POSE_CHANNEL) { + if (sync_types->pose_bone) { + outliner_select_sync_to_pose_bone(te, tselem, selected_items->pose_bones); + } + } + else if (tselem->type == TSE_SEQUENCE) { + if (sync_types->sequence) { + outliner_select_sync_to_sequence(scene, tselem); + } + } + + outliner_sync_selection_from_outliner( + scene, view_layer, &te->subtree, sync_types, selected_items); + } +} + +/* Set clean outliner and mark other outliners for syncing */ +void ED_outliner_select_sync_from_outliner(bContext *C, SpaceOutliner *soops) +{ + /* Don't sync in certain outliner display modes */ + if (ELEM(soops->outlinevis, SO_LIBRARIES, SO_DATA_API, SO_ID_ORPHANS)) { + return; + } + + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + + SyncSelectTypes sync_types; + outliner_sync_select_from_outliner_set_types(C, soops, &sync_types); + + /* To store elements that have been selected to prevent linked object sync errors */ + SelectedItems selected_items; + + selected_items_init(&selected_items); + + outliner_sync_selection_from_outliner( + scene, view_layer, &soops->tree, &sync_types, &selected_items); + + selected_items_free(&selected_items); + + /* Tag for updates and clear dirty flag toprevent a sync to the outliner on draw */ + if (sync_types.object) { + soops->sync_select_dirty &= ~WM_OUTLINER_SYNC_SELECT_FROM_OBJECT; + DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + } + else if (sync_types.edit_bone) { + soops->sync_select_dirty &= ~WM_OUTLINER_SYNC_SELECT_FROM_EDIT_BONE; + } + else if (sync_types.pose_bone) { + soops->sync_select_dirty &= ~WM_OUTLINER_SYNC_SELECT_FROM_POSE_BONE; + } + if (sync_types.sequence) { + soops->sync_select_dirty &= ~WM_OUTLINER_SYNC_SELECT_FROM_SEQUENCE; + WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene); + } +} + +static void outliner_select_sync_from_object(ViewLayer *view_layer, + SpaceOutliner *soops, + Object *obact, + TreeElement *te, + TreeStoreElem *tselem) +{ + Object *ob = (Object *)tselem->id; + Base *base = (te->directdata) ? (Base *)te->directdata : + BKE_view_layer_base_find(view_layer, ob); + const bool is_selected = (base != NULL) && ((base->flag & BASE_SELECTED) != 0); + + if (base && (ob == obact)) { + outliner_element_activate(soops, tselem); + } + else { + tselem->flag &= ~TSE_ACTIVE; + } + + if (is_selected) { + tselem->flag |= TSE_SELECTED; + } + else { + tselem->flag &= ~TSE_SELECTED; + } +} + +static void outliner_select_sync_from_edit_bone(SpaceOutliner *soops, + EditBone *ebone_active, + TreeElement *te, + TreeStoreElem *tselem) +{ + EditBone *ebone = (EditBone *)te->directdata; + + if (ebone == ebone_active) { + outliner_element_activate(soops, tselem); + } + else { + tselem->flag &= ~TSE_ACTIVE; + } + + if (ebone->flag & BONE_SELECTED) { + tselem->flag |= TSE_SELECTED; + } + else { + tselem->flag &= ~TSE_SELECTED; + } +} + +static void outliner_select_sync_from_pose_bone(SpaceOutliner *soops, + bPoseChannel *pchan_active, + TreeElement *te, + TreeStoreElem *tselem) +{ + bPoseChannel *pchan = (bPoseChannel *)te->directdata; + Bone *bone = pchan->bone; + + if (pchan == pchan_active) { + outliner_element_activate(soops, tselem); + } + else { + tselem->flag &= ~TSE_ACTIVE; + } + + if (bone->flag & BONE_SELECTED) { + tselem->flag |= TSE_SELECTED; + } + else { + tselem->flag &= ~TSE_SELECTED; + } +} + +static void outliner_select_sync_from_sequence(SpaceOutliner *soops, + Sequence *sequence_active, + TreeStoreElem *tselem) +{ + Sequence *seq = (Sequence *)tselem->id; + + if (seq == sequence_active) { + outliner_element_activate(soops, tselem); + } + else { + tselem->flag &= ~TSE_ACTIVE; + } + + if (seq->flag & SELECT) { + tselem->flag |= TSE_SELECTED; + } + else { + tselem->flag &= ~TSE_SELECTED; + } +} + +/** + * Contains active object, bones, and sequence for syncing to prevent getting active data + * repeatedly throughout syncing to the outliner. + */ +typedef struct SyncSelectActiveData { + Object *object; + EditBone *edit_bone; + bPoseChannel *pose_channel; + Sequence *sequence; +} SyncSelectActiveData; + +/** Sync select and active flags from active view layer, bones, and sequences to the outliner. */ +static void outliner_sync_selection_to_outliner(ViewLayer *view_layer, + SpaceOutliner *soops, + ListBase *tree, + SyncSelectActiveData *active_data, + const SyncSelectTypes *sync_types) +{ + for (TreeElement *te = tree->first; te; te = te->next) { + TreeStoreElem *tselem = TREESTORE(te); + + if (tselem->type == 0 && te->idcode == ID_OB) { + if (sync_types->object) { + outliner_select_sync_from_object(view_layer, soops, active_data->object, te, tselem); + } + } + else if (tselem->type == TSE_EBONE) { + if (sync_types->edit_bone) { + outliner_select_sync_from_edit_bone(soops, active_data->edit_bone, te, tselem); + } + } + else if (tselem->type == TSE_POSE_CHANNEL) { + if (sync_types->pose_bone) { + outliner_select_sync_from_pose_bone(soops, active_data->pose_channel, te, tselem); + } + } + else if (tselem->type == TSE_SEQUENCE) { + if (sync_types->sequence) { + outliner_select_sync_from_sequence(soops, active_data->sequence, tselem); + } + } + else { + tselem->flag &= ~TSE_SELECTED; + } + + /* Sync subtree elements */ + outliner_sync_selection_to_outliner(view_layer, soops, &te->subtree, active_data, sync_types); + } +} + +/* Get active data from context */ +static void get_sync_select_active_data(const bContext *C, SyncSelectActiveData *active_data) +{ + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + active_data->object = OBACT(view_layer); + active_data->edit_bone = CTX_data_active_bone(C); + active_data->pose_channel = CTX_data_active_pose_bone(C); + active_data->sequence = BKE_sequencer_active_get(scene); +} + +/* If outliner is dirty sync selection from view layer and sequwncer */ +void outliner_sync_selection(const bContext *C, SpaceOutliner *soops) +{ + /* Set which types of data to sync from sync dirty flag and outliner display mode */ + SyncSelectTypes sync_types; + const bool sync_required = outliner_sync_select_to_outliner_set_types(C, soops, &sync_types); + + if (sync_required) { + ViewLayer *view_layer = CTX_data_view_layer(C); + + /* Store active object, bones, and sequence */ + SyncSelectActiveData active_data; + get_sync_select_active_data(C, &active_data); + + outliner_sync_selection_to_outliner( + view_layer, soops, &soops->tree, &active_data, &sync_types); + + /* Keep any unsynced data in the dirty flag */ + if (sync_types.object) { + soops->sync_select_dirty &= ~WM_OUTLINER_SYNC_SELECT_FROM_OBJECT; + } + if (sync_types.edit_bone) { + soops->sync_select_dirty &= ~WM_OUTLINER_SYNC_SELECT_FROM_EDIT_BONE; + } + if (sync_types.pose_bone) { + soops->sync_select_dirty &= ~WM_OUTLINER_SYNC_SELECT_FROM_POSE_BONE; + } + if (sync_types.sequence) { + soops->sync_select_dirty &= ~WM_OUTLINER_SYNC_SELECT_FROM_SEQUENCE; + } + } +} diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index f9905cc4fcd..a2d988f1142 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -63,6 +63,7 @@ #include "ED_armature.h" #include "ED_object.h" +#include "ED_outliner.h" #include "ED_scene.h" #include "ED_screen.h" #include "ED_sequencer.h" @@ -298,7 +299,7 @@ static void unlink_collection_cb(bContext *C, } else if (GS(tsep->id->name) == ID_SCE) { Scene *scene = (Scene *)tsep->id; - Collection *parent = BKE_collection_master(scene); + Collection *parent = scene->master_collection; id_fake_user_set(&collection->id); BKE_collection_child_remove(bmain, parent, collection); DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); @@ -337,7 +338,7 @@ static void unlink_object_cb(bContext *C, } else if (GS(tsep->id->name) == ID_SCE) { Scene *scene = (Scene *)tsep->id; - Collection *parent = BKE_collection_master(scene); + Collection *parent = scene->master_collection; BKE_collection_object_remove(bmain, parent, ob, true); DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); DEG_relations_tag_update(bmain); @@ -478,6 +479,129 @@ void OUTLINER_OT_scene_operation(wmOperatorType *ot) } /* ******************************************** */ +/** + * Stores the parent and a child element of a merged icon-row icon for + * the merged select popup menu. The sub-tree of the parent is searched and + * the child is needed to only show elements of the same type in the popup. + */ +typedef struct MergedSearchData { + TreeElement *parent_element; + TreeElement *select_element; +} MergedSearchData; + +static void merged_element_search_cb_recursive( + const ListBase *tree, short tselem_type, short type, const char *str, uiSearchItems *items) +{ + char name[64]; + int iconid; + + for (TreeElement *te = tree->first; te; te = te->next) { + TreeStoreElem *tselem = TREESTORE(te); + + if (tree_element_id_type_to_index(te) == type && tselem_type == tselem->type) { + if (BLI_strcasestr(te->name, str)) { + BLI_strncpy(name, te->name, 64); + + iconid = tree_element_get_icon(tselem, te).icon; + + /* Don't allow duplicate named items */ + if (UI_search_items_find_index(items, name) == -1) { + if (!UI_search_item_add(items, name, te, iconid)) { + break; + } + } + } + } + + merged_element_search_cb_recursive(&te->subtree, tselem_type, type, str, items); + } +} + +/* Get a list of elements that match the search string */ +static void merged_element_search_cb(const bContext *UNUSED(C), + void *data, + const char *str, + uiSearchItems *items) +{ + MergedSearchData *search_data = (MergedSearchData *)data; + TreeElement *parent = search_data->parent_element; + TreeElement *te = search_data->select_element; + + int type = tree_element_id_type_to_index(te); + + merged_element_search_cb_recursive(&parent->subtree, TREESTORE(te)->type, type, str, items); +} + +/* Activate an element from the merged element search menu */ +static void merged_element_search_call_cb(struct bContext *C, void *UNUSED(arg1), void *element) +{ + SpaceOutliner *soops = CTX_wm_space_outliner(C); + TreeElement *te = (TreeElement *)element; + + outliner_item_select(soops, te, false, false); + outliner_item_do_activate_from_tree_element(C, te, te->store_elem, false, false); + + if (soops->flag & SO_SYNC_SELECT) { + ED_outliner_select_sync_from_outliner(C, soops); + } +} + +/** Merged element search menu + * Created on activation of a merged or aggregated icon-row icon. + */ +static uiBlock *merged_element_search_menu(bContext *C, ARegion *ar, void *data) +{ + static char search[64] = ""; + uiBlock *block; + uiBut *but; + + /* Clear search on each menu creation */ + *search = '\0'; + + block = UI_block_begin(C, ar, __func__, UI_EMBOSS); + UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_SEARCH_MENU); + UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP); + + short menu_width = 10 * UI_UNIT_X; + but = uiDefSearchBut( + block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 10, menu_width, UI_UNIT_Y, 0, 0, ""); + UI_but_func_search_set( + but, NULL, merged_element_search_cb, data, false, merged_element_search_call_cb, NULL); + UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT); + + /* Fake button to hold space for search items */ + uiDefBut(block, + UI_BTYPE_LABEL, + 0, + "", + 10, + 10 - UI_searchbox_size_y(), + menu_width, + UI_searchbox_size_y(), + NULL, + 0, + 0, + 0, + 0, + NULL); + + /* Center the menu on the cursor */ + UI_block_bounds_set_popup(block, 6, (const int[2]){-(menu_width / 2), 0}); + + return block; +} + +void merged_element_search_menu_invoke(bContext *C, + TreeElement *parent_te, + TreeElement *activate_te) +{ + MergedSearchData *select_data = MEM_callocN(sizeof(MergedSearchData), "merge_search_data"); + select_data->parent_element = parent_te; + select_data->select_element = activate_te; + + UI_popup_block_invoke(C, merged_element_search_menu, select_data, MEM_freeN); +} + static void object_select_cb(bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), @@ -556,12 +680,7 @@ static void object_delete_cb(bContext *C, if (ob == CTX_data_edit_object(C)) { ED_object_editmode_exit(C, EM_FREEDATA); } - ED_object_base_free_and_unlink(CTX_data_main(C), scene, ob); - /* leave for ED_outliner_id_unref to handle */ -#if 0 - te->directdata = NULL; - tselem->id = NULL; -#endif + BKE_id_delete(bmain, ob); } } @@ -654,7 +773,7 @@ static void singleuser_action_cb(bContext *C, if (id) { IdAdtTemplate *iat = (IdAdtTemplate *)tsep->id; - PointerRNA ptr = {{NULL}}; + PointerRNA ptr = {NULL}; PropertyRNA *prop; RNA_pointer_create(&iat->id, &RNA_AnimData, iat->adt, &ptr); @@ -677,7 +796,7 @@ static void singleuser_world_cb(bContext *C, /* need to use parent scene not just scene, otherwise may end up getting wrong one */ if (id) { Scene *parscene = (Scene *)tsep->id; - PointerRNA ptr = {{NULL}}; + PointerRNA ptr = {NULL}; PropertyRNA *prop; RNA_id_pointer_create(&parscene->id, &ptr); @@ -1080,11 +1199,6 @@ static void object_delete_hierarchy_cb(bContext *C, } outline_delete_hierarchy(C, reports, scene, base); - /* leave for ED_outliner_id_unref to handle */ -#if 0 - te->directdata = NULL; - tselem->id = NULL; -#endif } DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); @@ -1168,11 +1282,6 @@ static void object_batch_delete_hierarchy_cb(bContext *C, } outline_batch_delete_hierarchy(reports, CTX_data_main(C), view_layer, scene, base); - /* leave for ED_outliner_id_unref to handle */ -#if 0 - te->directdata = NULL; - tselem->id = NULL; -#endif } } diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index cc062467dbe..fd6a052b84d 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -297,7 +297,7 @@ static void outliner_add_scene_contents(SpaceOutliner *soops, ViewLayer *view_layer; for (view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) { - TreeElement *tenlay = outliner_add_element(soops, &ten->subtree, sce, te, TSE_R_LAYER, 0); + TreeElement *tenlay = outliner_add_element(soops, &ten->subtree, sce, ten, TSE_R_LAYER, 0); tenlay->name = view_layer->name; tenlay->directdata = view_layer; } @@ -314,7 +314,7 @@ static void outliner_add_scene_contents(SpaceOutliner *soops, ten = outliner_add_element(soops, lb, sce, te, TSE_SCENE_OBJECTS_BASE, 0); ten->name = IFACE_("Objects"); FOREACH_SCENE_OBJECT_BEGIN (sce, ob) { - outliner_add_element(soops, &ten->subtree, ob, NULL, 0, 0); + outliner_add_element(soops, &ten->subtree, ob, ten, 0, 0); } FOREACH_SCENE_OBJECT_END; outliner_make_object_parent_hierarchy(&ten->subtree); @@ -766,7 +766,7 @@ static TreeElement *outliner_add_element( ID *id = idv; if (ELEM(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) { - id = ((PointerRNA *)idv)->id.data; + id = ((PointerRNA *)idv)->owner_id; if (!id) { id = ((PointerRNA *)idv)->data; } @@ -1601,7 +1601,7 @@ typedef struct tTreeSort { short idcode; } tTreeSort; -/* alphabetical comparator, tryping to put objects first */ +/* alphabetical comparator, trying to put objects first */ static int treesort_alpha_ob(const void *v1, const void *v2) { const tTreeSort *x1 = v1, *x2 = v2; @@ -1627,7 +1627,7 @@ static int treesort_alpha_ob(const void *v1, const void *v2) return (x1->te->flag & TE_CHILD_NOT_IN_COLLECTION) ? 1 : -1; } - comp = strcmp(x1->name, x2->name); + comp = BLI_strcasecmp_natural(x1->name, x2->name); if (comp > 0) { return 1; @@ -1659,7 +1659,7 @@ static int treesort_alpha(const void *v1, const void *v2) const tTreeSort *x1 = v1, *x2 = v2; int comp; - comp = strcmp(x1->name, x2->name); + comp = BLI_strcasecmp_natural(x1->name, x2->name); if (comp > 0) { return 1; @@ -1697,7 +1697,7 @@ static int treesort_obtype_alpha(const void *v1, const void *v2) } } else { - int comp = strcmp(x1->name, x2->name); + int comp = BLI_strcasecmp_natural(x1->name, x2->name); if (comp > 0) { return 1; @@ -2008,6 +2008,9 @@ static int outliner_exclude_filter_get(SpaceOutliner *soops) case SO_FILTER_OB_VISIBLE: exclude_filter |= SO_FILTER_OB_STATE_VISIBLE; break; + case SO_FILTER_OB_HIDDEN: + exclude_filter |= SO_FILTER_OB_STATE_HIDDEN; + break; case SO_FILTER_OB_SELECTED: exclude_filter |= SO_FILTER_OB_STATE_SELECTED; break; @@ -2086,6 +2089,11 @@ static bool outliner_element_visible_get(ViewLayer *view_layer, return false; } } + else if (exclude_filter & SO_FILTER_OB_STATE_HIDDEN) { + if ((base->flag & BASE_VISIBLE) != 0) { + return false; + } + } else if (exclude_filter & SO_FILTER_OB_STATE_SELECTED) { if ((base->flag & BASE_SELECTED) == 0) { return false; @@ -2339,7 +2347,8 @@ void outliner_build_tree( te = outliner_add_element(soops, &soops->tree, sce, NULL, 0, 0); tselem = TREESTORE(te); - if (sce == scene && show_opened) { + /* New scene elements open by default */ + if ((sce == scene && show_opened) || !tselem->used) { tselem->flag &= ~TSE_CLOSED; } diff --git a/source/blender/editors/space_outliner/outliner_utils.c b/source/blender/editors/space_outliner/outliner_utils.c index f57dce97b38..5dfdf6f129b 100644 --- a/source/blender/editors/space_outliner/outliner_utils.c +++ b/source/blender/editors/space_outliner/outliner_utils.c @@ -24,11 +24,15 @@ #include "BLI_utildefines.h" #include "DNA_action_types.h" +#include "DNA_screen_types.h" #include "DNA_space_types.h" +#include "BKE_context.h" #include "BKE_outliner_treehash.h" +#include "BKE_layer.h" #include "ED_armature.h" +#include "ED_outliner.h" #include "UI_interface.h" #include "UI_view2d.h" @@ -62,6 +66,38 @@ TreeElement *outliner_find_item_at_y(const SpaceOutliner *soops, return NULL; } +static TreeElement *outliner_find_item_at_x_in_row_recursive(const TreeElement *parent_te, + float view_co_x, + bool *r_merged) +{ + TreeElement *child_te = parent_te->subtree.first; + + bool over_element = false; + + while (child_te) { + over_element = (view_co_x > child_te->xs) && (view_co_x < child_te->xend); + if ((child_te->flag & TE_ICONROW) && over_element) { + return child_te; + } + else if ((child_te->flag & TE_ICONROW_MERGED) && over_element) { + if (r_merged) { + *r_merged = true; + } + return child_te; + } + + TreeElement *te = outliner_find_item_at_x_in_row_recursive(child_te, view_co_x, r_merged); + if (te != child_te) { + return te; + } + + child_te = child_te->next; + } + + /* return parent if no child is hovered */ + return (TreeElement *)parent_te; +} + /** * Collapsed items can show their children as click-able icons. This function tries to find * such an icon that represents the child item at x-coordinate \a view_co_x (view-space). @@ -70,24 +106,14 @@ TreeElement *outliner_find_item_at_y(const SpaceOutliner *soops, */ TreeElement *outliner_find_item_at_x_in_row(const SpaceOutliner *soops, const TreeElement *parent_te, - float view_co_x) + float view_co_x, + bool *r_merged) { - /* if parent_te is opened, it doesn't show childs in row */ + /* if parent_te is opened, it doesn't show children in row */ if (!TSELEM_OPEN(TREESTORE(parent_te), soops)) { - /* no recursion, items can only display their direct children in the row */ - for (TreeElement *child_te = parent_te->subtree.first; - /* don't look further if co_x is smaller than child position*/ - child_te && view_co_x >= child_te->xs; - - child_te = child_te->next) { - if ((child_te->flag & TE_ICONROW) && (view_co_x > child_te->xs) && - (view_co_x < child_te->xend)) { - return child_te; - } - } + return outliner_find_item_at_x_in_row_recursive(parent_te, view_co_x, r_merged); } - /* return parent if no child is hovered */ return (TreeElement *)parent_te; } @@ -300,3 +326,89 @@ float outliner_restrict_columns_width(const SpaceOutliner *soops) } return (num_columns * UI_UNIT_X + V2D_SCROLL_WIDTH); } + +/* Find first tree element in tree with matching treestore flag */ +TreeElement *outliner_find_element_with_flag(const ListBase *lb, short flag) +{ + for (TreeElement *te = lb->first; te; te = te->next) { + if ((TREESTORE(te)->flag & flag) == flag) { + return te; + } + TreeElement *active_element = outliner_find_element_with_flag(&te->subtree, flag); + if (active_element) { + return active_element; + } + } + return NULL; +} + +/* Find if element is visible in the outliner tree */ +bool outliner_is_element_visible(const TreeElement *te) +{ + TreeStoreElem *tselem; + + while (te->parent) { + tselem = TREESTORE(te->parent); + + if (tselem->flag & TSE_CLOSED) { + return false; + } + else { + te = te->parent; + } + } + + return true; +} + +/* Find if x coordinate is over element disclosure toggle */ +bool outliner_item_is_co_within_close_toggle(TreeElement *te, float view_co_x) +{ + return (view_co_x > te->xs) && (view_co_x < te->xs + UI_UNIT_X); +} + +/* Scroll view vertically while keeping within total bounds */ +void outliner_scroll_view(ARegion *ar, int delta_y) +{ + int y_min = MIN2(ar->v2d.cur.ymin, ar->v2d.tot.ymin); + + ar->v2d.cur.ymax += delta_y; + ar->v2d.cur.ymin += delta_y; + + /* Adjust view if delta placed view outside total area */ + int offset; + if (ar->v2d.cur.ymax > -UI_UNIT_Y) { + offset = ar->v2d.cur.ymax; + ar->v2d.cur.ymax -= offset; + ar->v2d.cur.ymin -= offset; + } + else if (ar->v2d.cur.ymin < y_min) { + offset = y_min - ar->v2d.cur.ymin; + ar->v2d.cur.ymax += offset; + ar->v2d.cur.ymin += offset; + } +} + +/* Get base of object under cursor. Used for eyedropper tool */ +Base *ED_outliner_give_base_under_cursor(bContext *C, const int mval[2]) +{ + ARegion *ar = CTX_wm_region(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + SpaceOutliner *soops = CTX_wm_space_outliner(C); + TreeElement *te; + Base *base = NULL; + float view_mval[2]; + + UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &view_mval[0], &view_mval[1]); + + te = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]); + if (te) { + TreeStoreElem *tselem = TREESTORE(te); + if (tselem->type == 0) { + Object *ob = (Object *)tselem->id; + base = (te->directdata) ? (Base *)te->directdata : BKE_view_layer_base_find(view_layer, ob); + } + } + + return base; +} diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c index 091efc56c09..79880c68120 100644 --- a/source/blender/editors/space_outliner/space_outliner.c +++ b/source/blender/editors/space_outliner/space_outliner.c @@ -131,6 +131,9 @@ static void outliner_main_region_listener(wmWindow *UNUSED(win), ED_region_tag_redraw(ar); break; } + if (wmn->action & NA_EDITED) { + ED_region_tag_redraw(ar); + } break; case NC_OBJECT: switch (wmn->data) { @@ -145,13 +148,8 @@ static void outliner_main_region_listener(wmWindow *UNUSED(win), ED_region_tag_redraw(ar); break; case ND_CONSTRAINT: - switch (wmn->action) { - case NA_ADDED: - case NA_REMOVED: - case NA_RENAME: - ED_region_tag_redraw(ar); - break; - } + /* all constraint actions now, for reordering */ + ED_region_tag_redraw(ar); break; case ND_MODIFIER: /* all modifier actions now */ @@ -304,6 +302,8 @@ static SpaceLink *outliner_new(const ScrArea *UNUSED(area), const Scene *UNUSED( soutliner->filter_id_type = ID_GR; soutliner->show_restrict_flags = SO_RESTRICT_ENABLE | SO_RESTRICT_HIDE; soutliner->outlinevis = SO_VIEW_LAYER; + soutliner->sync_select_dirty |= WM_OUTLINER_SYNC_SELECT_FROM_ALL; + soutliner->flag |= SO_SYNC_SELECT; /* header */ ar = MEM_callocN(sizeof(ARegion), "header for outliner"); @@ -349,6 +349,9 @@ static SpaceLink *outliner_duplicate(SpaceLink *sl) soutlinern->treestore = NULL; soutlinern->treehash = NULL; + soutlinern->flag |= (soutliner->flag & SO_SYNC_SELECT); + soutlinern->sync_select_dirty = WM_OUTLINER_SYNC_SELECT_FROM_ALL; + return (SpaceLink *)soutlinern; } @@ -415,7 +418,7 @@ void ED_spacetype_outliner(void) /* regions: main window */ art = MEM_callocN(sizeof(ARegionType), "spacetype outliner region"); art->regionid = RGN_TYPE_WINDOW; - art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES; + art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D; art->init = outliner_main_region_init; art->draw = outliner_main_region_draw; @@ -428,7 +431,7 @@ void ED_spacetype_outliner(void) art = MEM_callocN(sizeof(ARegionType), "spacetype outliner header region"); art->regionid = RGN_TYPE_HEADER; art->prefsizey = HEADERY; - art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER; + art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER; art->init = outliner_header_region_init; art->draw = outliner_header_region_draw; diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 07350b5269e..b15acb12d00 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -1045,9 +1045,8 @@ ImBuf *sequencer_ibuf_get(struct Main *bmain, bmain, depsgraph, scene, rectx, recty, proxy_size, false, &context); context.view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname); - /* sequencer could start rendering, in this case we need to be sure it wouldn't be canceled - * by Esc pressed somewhere in the past - */ + /* Sequencer could start rendering, in this case we need to be sure it wouldn't be canceled + * by Escape pressed somewhere in the past. */ G.is_break = false; /* Rendering can change OGL context. Save & Restore framebuffer. */ diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index ed0303564c6..22b73c32bfe 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -3405,6 +3405,7 @@ void SEQUENCER_OT_copy(wmOperatorType *ot) /* identifiers */ ot->name = "Copy"; ot->idname = "SEQUENCER_OT_copy"; + ot->description = "Copy selected strips to clipboard"; /* api callbacks */ ot->exec = sequencer_copy_exec; @@ -3470,6 +3471,7 @@ void SEQUENCER_OT_paste(wmOperatorType *ot) /* identifiers */ ot->name = "Paste"; ot->idname = "SEQUENCER_OT_paste"; + ot->description = "Paste strips from clipboard"; /* api callbacks */ ot->exec = sequencer_paste_exec; diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h index dd04260d80e..851d3b5f3aa 100644 --- a/source/blender/editors/space_sequencer/sequencer_intern.h +++ b/source/blender/editors/space_sequencer/sequencer_intern.h @@ -34,7 +34,6 @@ struct ARegionType; struct Depsgraph; struct Main; struct Scene; -struct ScrArea; struct Sequence; struct SpaceSeq; struct StripElem; diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c index 57f86059d9d..affb6d3fd88 100644 --- a/source/blender/editors/space_sequencer/sequencer_select.c +++ b/source/blender/editors/space_sequencer/sequencer_select.c @@ -41,6 +41,7 @@ /* for menu/popup icons etc etc*/ +#include "ED_outliner.h" #include "ED_screen.h" #include "ED_sequencer.h" #include "ED_select_utils.h" @@ -49,6 +50,7 @@ /* own include */ #include "sequencer_intern.h" + static void *find_nearest_marker(int UNUSED(d1), int UNUSED(d2)) { return NULL; @@ -254,6 +256,8 @@ static int sequencer_de_select_all_exec(bContext *C, wmOperator *op) } } + ED_outliner_select_sync_from_sequence_tag(C); + WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene); return OPERATOR_FINISHED; @@ -293,6 +297,8 @@ static int sequencer_select_inverse_exec(bContext *C, wmOperator *UNUSED(op)) } } + ED_outliner_select_sync_from_sequence_tag(C); + WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene); return OPERATOR_FINISHED; @@ -542,6 +548,8 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e } } + ED_outliner_select_sync_from_sequence_tag(C); + WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene); /* allowing tweaks */ @@ -668,6 +676,8 @@ static int sequencer_select_more_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; } + ED_outliner_select_sync_from_sequence_tag(C); + WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene); return OPERATOR_FINISHED; @@ -699,6 +709,8 @@ static int sequencer_select_less_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; } + ED_outliner_select_sync_from_sequence_tag(C); + WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene); return OPERATOR_FINISHED; @@ -750,6 +762,8 @@ static int sequencer_select_linked_pick_invoke(bContext *C, wmOperator *op, cons selected = select_more_less_seq__internal(scene, 1, 1); } + ED_outliner_select_sync_from_sequence_tag(C); + WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene); return OPERATOR_FINISHED; @@ -784,6 +798,8 @@ static int sequencer_select_linked_exec(bContext *C, wmOperator *UNUSED(op)) selected = select_more_less_seq__internal(scene, true, true); } + ED_outliner_select_sync_from_sequence_tag(C); + WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene); return OPERATOR_FINISHED; @@ -832,6 +848,8 @@ static int sequencer_select_handles_exec(bContext *C, wmOperator *op) } } + ED_outliner_select_sync_from_sequence_tag(C); + WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene); return OPERATOR_FINISHED; @@ -876,6 +894,8 @@ static int sequencer_select_active_side_exec(bContext *C, wmOperator *op) select_active_side( ed->seqbasep, RNA_enum_get(op->ptr, "side"), seq_act->machine, seq_act->startdisp); + ED_outliner_select_sync_from_sequence_tag(C); + WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene); return OPERATOR_FINISHED; @@ -934,6 +954,8 @@ static int sequencer_box_select_exec(bContext *C, wmOperator *op) } } + ED_outliner_select_sync_from_sequence_tag(C); + WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene); return OPERATOR_FINISHED; @@ -1311,6 +1333,7 @@ static int sequencer_select_grouped_exec(bContext *C, wmOperator *op) } if (changed) { + ED_outliner_select_sync_from_sequence_tag(C); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index 9aa9d14cbc8..e1cf6d00b90 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -597,7 +597,7 @@ static void sequencer_main_region_message_subscribe(const struct bContext *UNUSE &RNA_SequenceModifier, &RNA_SequenceColorBalanceData, }; - wmMsgParams_RNA msg_key_params = {{{0}}}; + wmMsgParams_RNA msg_key_params = {{0}}; for (int i = 0; i < ARRAY_SIZE(type_array); i++) { msg_key_params.ptr.type = type_array[i]; WM_msg_subscribe_rna_params( diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c index c1a3c79b0d8..9f39313b9ab 100644 --- a/source/blender/editors/space_text/space_text.c +++ b/source/blender/editors/space_text/space_text.c @@ -29,6 +29,7 @@ #include "BLI_blenlib.h" +#include "BKE_global.h" #include "BKE_context.h" #include "BKE_library.h" #include "BKE_screen.h" @@ -356,7 +357,7 @@ static void text_drop_paste(wmDrag *drag, wmDropBox *drop) ID *id = WM_drag_ID(drag, 0); /* copy drag path to properties */ - text = RNA_path_full_ID_py(id); + text = RNA_path_full_ID_py(G_MAIN, id); RNA_string_set(drop->ptr, "text", text); MEM_freeN(text); } diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index e1550deb659..caefb5070fb 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -142,7 +142,7 @@ static char *buf_tabs_to_spaces(const char *in_buf, const int tab_size) BLI_INLINE int text_pixel_x_to_column(SpaceText *st, const int x) { - /* add half the char width so mouse cursor selection is inbetween letters */ + /* Add half the char width so mouse cursor selection is in between letters. */ return (x + (st->cwidth / 2)) / st->cwidth; } diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 38e8d285c77..b412a72cce1 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -145,7 +145,7 @@ void ED_draw_object_facemap(Depsgraph *depsgraph, facemap_data = CustomData_get_layer(&me->pdata, CD_FACEMAP); - /* use gawain immediate mode fore now */ + /* Make a batch and free it each time for now. */ const int looptris_len = poly_to_tri_count(mpoly_len, mloop_len); const int vbo_len_capacity = looptris_len * 3; int vbo_len_used = 0; diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 7acff998e2b..8c4f2f62602 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -992,7 +992,7 @@ static void view3d_main_region_message_subscribe(const struct bContext *C, * accepting some redundant redraws. * * For other space types we might try avoid this, keep the 3D view as an exceptional case! */ - wmMsgParams_RNA msg_key_params = {{{0}}}; + wmMsgParams_RNA msg_key_params = {{0}}; /* Only subscribe to types. */ StructRNA *type_array[] = { @@ -1177,7 +1177,7 @@ static void view3d_header_region_message_subscribe(const struct bContext *UNUSED struct ARegion *ar, struct wmMsgBus *mbus) { - wmMsgParams_RNA msg_key_params = {{{0}}}; + wmMsgParams_RNA msg_key_params = {{0}}; /* Only subscribe to types. */ StructRNA *type_array[] = { diff --git a/source/blender/editors/space_view3d/view3d_camera_control.c b/source/blender/editors/space_view3d/view3d_camera_control.c index 0045094542f..260546738f4 100644 --- a/source/blender/editors/space_view3d/view3d_camera_control.c +++ b/source/blender/editors/space_view3d/view3d_camera_control.c @@ -87,8 +87,7 @@ typedef struct View3DCameraControl { float ofs_backup[3]; /* backup the views offset in case the user cancels flying in non camera mode */ - /* backup the views quat in case the user cancels flying in non camera mode. - * (quat for view, eul for camera) */ + /* backup the views quat in case the user cancels flying in non camera mode. */ float rot_backup[4]; /* remember if were ortho or not, only used for restoring the view if it was a ortho view */ char persp_backup; @@ -209,8 +208,8 @@ void ED_view3d_cameracontrol_update(View3DCameraControl *vctrl, const bool do_rotate, const bool do_translate) { - /* we are in camera view so apply the view ofs and quat to the view matrix and set the camera - * to the view */ + /* We are in camera view so apply the view offset and rotation to the view matrix + * and set the camera to the view. */ Scene *scene = vctrl->ctx_scene; View3D *v3d = vctrl->ctx_v3d; diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 6c534ee1b98..f6afa112f08 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -859,6 +859,51 @@ float ED_view3d_grid_scale(Scene *scene, View3D *v3d, const char **grid_unit) return v3d->grid * ED_scene_grid_scale(scene, grid_unit); } +#define STEPS_LEN 8 +void ED_view3d_grid_steps(Scene *scene, + View3D *v3d, + RegionView3D *rv3d, + float r_grid_steps[STEPS_LEN]) +{ + const void *usys; + int i, len; + bUnit_GetSystem(scene->unit.system, B_UNIT_LENGTH, &usys, &len); + float grid_scale = v3d->grid; + + if (usys) { + if (rv3d->view == RV3D_VIEW_USER) { + /* Skip steps */ + len = bUnit_GetBaseUnit(usys) + 1; + } + + grid_scale /= scene->unit.scale_length; + + for (i = 0; i < len; i++) { + r_grid_steps[i] = (float)bUnit_GetScaler(usys, len - 1 - i) * grid_scale; + } + for (; i < STEPS_LEN; i++) { + /* Fill last slots */ + r_grid_steps[i] = 10.0f * r_grid_steps[i - 1]; + } + } + else { + if (rv3d->view != RV3D_VIEW_USER) { + /* Allow 3 more subdivisions. */ + grid_scale /= powf(v3d->gridsubdiv, 3); + } + int subdiv = 1; + for (i = 0;; i++) { + r_grid_steps[i] = grid_scale * subdiv; + + if (i == STEPS_LEN - 1) { + break; + } + subdiv *= v3d->gridsubdiv; + } + } +} +#undef STEPS_LEN + /* Simulates the grid scale that is actually viewed. * The actual code is seen in `object_grid_frag.glsl` (see `grid_res`). * Currently the simulation is only done when RV3D_VIEW_IS_AXIS. */ @@ -867,24 +912,35 @@ float ED_view3d_grid_view_scale(Scene *scene, RegionView3D *rv3d, const char **grid_unit) { - float grid_scale = ED_view3d_grid_scale(scene, v3d, grid_unit); + float grid_scale; if (!rv3d->is_persp && RV3D_VIEW_IS_AXIS(rv3d->view)) { /* Decrease the distance between grid snap points depending on zoom. */ - float grid_subdiv = v3d->gridsubdiv; - if (grid_subdiv > 1) { - /* Allow 3 more subdivisions (see OBJECT_engine_init). */ - grid_scale /= powf(grid_subdiv, 3); - - /* `3.0` was a value obtained by trial and error in order to get - * a nice snap distance.*/ - float grid_res = 3.0 * (rv3d->dist / v3d->lens); - float lvl = (logf(grid_res / grid_scale) / logf(grid_subdiv)); + /* `0.38` was a value visually obtained in order to get a snap distance + * that matches previous versions Blender.*/ + float min_dist = 0.38f * (rv3d->dist / v3d->lens); + float grid_steps[8]; + ED_view3d_grid_steps(scene, v3d, rv3d, grid_steps); + int i; + for (i = 0; i < ARRAY_SIZE(grid_steps); i++) { + grid_scale = grid_steps[i]; + if (grid_scale > min_dist) { + break; + } + } - CLAMP_MIN(lvl, 0.0f); + if (grid_unit) { + const void *usys; + int len; + bUnit_GetSystem(scene->unit.system, B_UNIT_LENGTH, &usys, &len); - grid_scale *= pow(grid_subdiv, (int)lvl); + if (usys) { + *grid_unit = bUnit_GetNameDisplay(usys, len - i - 1); + } } } + else { + grid_scale = ED_view3d_grid_scale(scene, v3d, grid_unit); + } return grid_scale; } @@ -1360,6 +1416,27 @@ static void draw_selected_name( BLF_disable(font_id, BLF_SHADOW); } +static void draw_grid_unit_name( + Scene *scene, RegionView3D *rv3d, View3D *v3d, int xoffset, int *yoffset) +{ + if (!rv3d->is_persp && RV3D_VIEW_IS_AXIS(rv3d->view)) { + const char *grid_unit = NULL; + ED_view3d_grid_view_scale(scene, v3d, rv3d, &grid_unit); + + if (grid_unit) { + char numstr[32] = ""; + UI_FontThemeColor(BLF_default(), TH_TEXT_HI); + if (v3d->grid != 1.0f) { + BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid); + } + + *yoffset -= U.widget_unit; + BLF_draw_default_ascii( + xoffset, *yoffset, 0.0f, numstr[0] ? numstr : grid_unit, sizeof(numstr)); + } + } +} + /** * Information drawn on top of the solid plates and composed data */ @@ -1421,19 +1498,10 @@ void view3d_draw_region_info(const bContext *C, ARegion *ar) draw_selected_name(scene, view_layer, ob, xoffset, &yoffset); } -#if 0 /* TODO */ - if (grid_unit) { /* draw below the viewport name */ - char numstr[32] = ""; - - UI_FontThemeColor(BLF_default(), TH_TEXT_HI); - if (v3d->grid != 1.0f) { - BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid); - } - - *yoffset -= U.widget_unit; - BLF_draw_default_ascii(xoffset, *yoffset, numstr[0] ? numstr : grid_unit, sizeof(numstr)); + if (v3d->gridflag & (V3D_SHOW_FLOOR | V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_Z)) { + /* draw below the viewport name */ + draw_grid_unit_name(scene, rv3d, v3d, xoffset, &yoffset); } -#endif } if ((v3d->overlay.flag & V3D_OVERLAY_HIDE_TEXT) == 0) { @@ -1492,7 +1560,7 @@ void view3d_main_region_draw(const bContext *C, ARegion *ar) GPU_pass_cache_garbage_collect(); /* XXX This is in order to draw UI batches with the DRW - * olg context since we now use it for drawing the entire area */ + * old context since we now use it for drawing the entire area. */ gpu_batch_presets_reset(); /* No depth test for drawing action zones afterwards. */ diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c index 02ad481e6ce..d5772e5052a 100644 --- a/source/blender/editors/space_view3d/view3d_draw_legacy.c +++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c @@ -162,6 +162,7 @@ static void validate_object_select_id( Object *obact_eval = DEG_get_evaluated_object(depsgraph, obact); BLI_assert(ar->regiontype == RGN_TYPE_WINDOW); + UNUSED_VARS_NDEBUG(ar); if (obact_eval && (obact_eval->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT) || BKE_paint_select_face_test(obact_eval))) { diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 9a9fe81a13e..e76ef2b0458 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -404,9 +404,7 @@ static void viewops_data_create(bContext *C, if (viewops_flag & VIEWOPS_FLAG_PERSP_ENSURE) { if (ED_view3d_persp_ensure(depsgraph, vod->v3d, vod->ar)) { /* If we're switching from camera view to the perspective one, - * need to tag viewport update, so camera vuew and borders - * are properly updated. - */ + * need to tag viewport update, so camera view and borders are properly updated. */ ED_region_tag_redraw(vod->ar); } } @@ -4946,6 +4944,7 @@ void ED_view3d_cursor3d_position_rotation(bContext *C, .use_object_edit_cage = false, }, mval_fl, + NULL, &dist_px, ray_co, ray_no, @@ -5052,7 +5051,7 @@ void ED_view3d_cursor3d_update(bContext *C, { struct wmMsgBus *mbus = CTX_wm_message_bus(C); - wmMsgParams_RNA msg_key_params = {{{0}}}; + wmMsgParams_RNA msg_key_params = {{0}}; RNA_pointer_create(&scene->id, &RNA_View3DCursor, &scene->cursor, &msg_key_params.ptr); WM_msg_publish_rna_params(mbus, &msg_key_params); } diff --git a/source/blender/editors/space_view3d/view3d_gizmo_camera.c b/source/blender/editors/space_view3d/view3d_gizmo_camera.c index 1bb10697936..42931d5abb5 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_camera.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_camera.c @@ -100,7 +100,7 @@ static void WIDGETGROUP_camera_setup(const bContext *C, wmGizmoGroup *gzgroup) wmGizmo *gz; gz = cagzgroup->dop_dist = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL); RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_CROSS); - WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_HOVER, true); + WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_HOVER | WM_GIZMO_DRAW_NO_SCALE, true); UI_GetThemeColor3fv(TH_GIZMO_A, gz->color); UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi); @@ -152,9 +152,11 @@ static void WIDGETGROUP_camera_refresh(const bContext *C, wmGizmoGroup *gzgroup) WM_gizmo_set_scale(cagzgroup->dop_dist, ca->drawsize); WM_gizmo_set_flag(cagzgroup->dop_dist, WM_GIZMO_HIDDEN, false); - /* need to set property here for undo. TODO would prefer to do this in _init */ + /* Need to set property here for undo. TODO would prefer to do this in _init */ + PointerRNA camera_dof_ptr; + RNA_pointer_create(&ca->id, &RNA_CameraDOFSettings, &ca->dof, &camera_dof_ptr); WM_gizmo_target_property_def_rna( - cagzgroup->dop_dist, "offset", &camera_ptr, "dof.focus_distance", -1); + cagzgroup->dop_dist, "offset", &camera_dof_ptr, "focus_distance", -1); } else { WM_gizmo_set_flag(cagzgroup->dop_dist, WM_GIZMO_HIDDEN, true); diff --git a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c index a984e339305..68159e2d684 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c @@ -77,7 +77,20 @@ static void gizmo_preselect_elem_draw(const bContext *UNUSED(C), wmGizmo *gz) static int gizmo_preselect_elem_test_select(bContext *C, wmGizmo *gz, const int mval[2]) { + wmEvent *event = CTX_wm_window(C)->eventstate; MeshElemGizmo3D *gz_ele = (MeshElemGizmo3D *)gz; + + /* Hack: Switch action mode based on key input */ + const bool is_ctrl_pressed = WM_event_modifier_flag(event) & KM_CTRL; + const bool is_shift_pressed = WM_event_modifier_flag(event) & KM_SHIFT; + EDBM_preselect_action_set(gz_ele->psel, PRESELECT_ACTION_TRANSFORM); + if (is_ctrl_pressed && !is_shift_pressed) { + EDBM_preselect_action_set(gz_ele->psel, PRESELECT_ACTION_CREATE); + } + if (!is_ctrl_pressed && is_shift_pressed) { + EDBM_preselect_action_set(gz_ele->psel, PRESELECT_ACTION_DELETE); + } + struct { Object *ob; BMElem *ele; @@ -87,18 +100,6 @@ static int gizmo_preselect_elem_test_select(bContext *C, wmGizmo *gz, const int .dist = ED_view3d_select_dist_px(), }; - struct { - int base_index; - int vert_index; - int edge_index; - int face_index; - } prev = { - .base_index = gz_ele->base_index, - .vert_index = gz_ele->vert_index, - .edge_index = gz_ele->edge_index, - .face_index = gz_ele->face_index, - }; - { ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); @@ -115,32 +116,66 @@ static int gizmo_preselect_elem_test_select(bContext *C, wmGizmo *gz, const int { /* TODO: support faces. */ - int base_index = -1; + int base_index_vert = -1; + int base_index_edge = -1; + int base_index_face = -1; BMVert *eve_test; BMEdge *eed_test; + BMFace *efa_test; if (EDBM_unified_findnearest_from_raycast(&vc, gz_ele->bases, gz_ele->bases_len, + false, true, - &base_index, + &base_index_vert, + &base_index_edge, + &base_index_face, &eve_test, &eed_test, - NULL)) { - Base *base = gz_ele->bases[base_index]; - best.ob = base->object; - if (eve_test) { - best.ele = (BMElem *)eve_test; - } - else if (eed_test) { - best.ele = (BMElem *)eed_test; + &efa_test)) { + if (EDBM_preselect_action_get(gz_ele->psel) == PRESELECT_ACTION_DELETE) { + /* Delete action */ + if (efa_test) { + best.ele = (BMElem *)efa_test; + best.base_index = base_index_face; + } } + else { - BLI_assert(0); + /* Transform and create action */ + if (eed_test) { + best.ele = (BMElem *)eed_test; + best.base_index = base_index_edge; + } + } + + /* All actions use same vertex pre-selection. */ + /* Re-topology should always prioritize edge pre-selection. + * Only pre-select a vertex when the cursor is really close to it. */ + if (eve_test) { + BMVert *vert = (BMVert *)eve_test; + float vert_p_co[3], vert_co[3]; + float mval_f[2] = {UNPACK2(vc.mval)}; + mul_v3_m4v3(vert_co, gz_ele->bases[base_index_vert]->object->obmat, vert->co); + ED_view3d_project(vc.ar, vert_co, vert_p_co); + float len = len_v2v2(vert_p_co, mval_f); + if (len < 35) { + best.ele = (BMElem *)eve_test; + best.base_index = base_index_vert; + } + if (!BM_vert_is_boundary(vert) && + EDBM_preselect_action_get(gz_ele->psel) != PRESELECT_ACTION_DELETE) { + best.ele = (BMElem *)eve_test; + best.base_index = base_index_vert; + } } - best.base_index = base_index; + /* Check above should never fail, if it does it's an internal error. */ BLI_assert(best.base_index != -1); + + Base *base = gz_ele->bases[best.base_index]; + best.ob = base->object; } } @@ -167,32 +202,30 @@ static int gizmo_preselect_elem_test_select(bContext *C, wmGizmo *gz, const int } } - if ((prev.base_index == gz_ele->base_index) && (prev.vert_index == gz_ele->vert_index) && - (prev.edge_index == gz_ele->edge_index) && (prev.face_index == gz_ele->face_index)) { - /* pass (only recalculate on change) */ - } - else { - if (best.ele) { - const float(*coords)[3] = NULL; - { - Object *ob = gz_ele->bases[gz_ele->base_index]->object; - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - Mesh *me_eval = (Mesh *)DEG_get_evaluated_id(depsgraph, ob->data); - if (me_eval->runtime.edit_data) { - coords = me_eval->runtime.edit_data->vertexCos; - } + if (best.ele) { + const float(*coords)[3] = NULL; + { + Object *ob = gz_ele->bases[gz_ele->base_index]->object; + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + Mesh *me_eval = (Mesh *)DEG_get_evaluated_id(depsgraph, ob->data); + if (me_eval->runtime.edit_data) { + coords = me_eval->runtime.edit_data->vertexCos; } - EDBM_preselect_elem_update_from_single(gz_ele->psel, bm, best.ele, coords); - } - else { - EDBM_preselect_elem_clear(gz_ele->psel); } + EDBM_preselect_elem_update_from_single(gz_ele->psel, bm, best.ele, coords); + EDBM_preselect_elem_update_preview(gz_ele->psel, &vc, bm, best.ele, mval); + } + else { + EDBM_preselect_elem_clear(gz_ele->psel); + EDBM_preselect_preview_clear(gz_ele->psel); + } - RNA_int_set(gz->ptr, "object_index", gz_ele->base_index); - RNA_int_set(gz->ptr, "vert_index", gz_ele->vert_index); - RNA_int_set(gz->ptr, "edge_index", gz_ele->edge_index); - RNA_int_set(gz->ptr, "face_index", gz_ele->face_index); + RNA_int_set(gz->ptr, "object_index", gz_ele->base_index); + RNA_int_set(gz->ptr, "vert_index", gz_ele->vert_index); + RNA_int_set(gz->ptr, "edge_index", gz_ele->edge_index); + RNA_int_set(gz->ptr, "face_index", gz_ele->face_index); + if (best.ele) { ARegion *ar = CTX_wm_region(C); ED_region_tag_redraw(ar); } @@ -471,5 +504,4 @@ void ED_view3d_gizmo_mesh_preselect_get_active(bContext *C, } } } - /** \} */ diff --git a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c index 97a12c7100e..f4e3dc85447 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c @@ -343,6 +343,7 @@ static bool view3d_ruler_item_mousemove(RulerInfo *ruler_info, .use_object_edit_cage = true, }, mval_fl, + NULL, &dist_px, co, ray_normal)) { @@ -363,16 +364,31 @@ static bool view3d_ruler_item_mousemove(RulerInfo *ruler_info, } else if (do_snap) { const float mval_fl[2] = {UNPACK2(mval)}; + float *prev_point = NULL; + + if (inter->co_index != 1) { + if (ruler_item->flag & RULERITEM_USE_ANGLE) { + prev_point = ruler_item->co[1]; + } + else if (inter->co_index == 0) { + prev_point = ruler_item->co[2]; + } + else { + prev_point = ruler_item->co[0]; + } + } if (ED_transform_snap_object_project_view3d( ruler_info->snap_context, - (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE), + (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE | + SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR), &(const struct SnapObjectParams){ .snap_select = SNAP_ALL, .use_object_edit_cage = true, .use_occlusion_test = true, }, mval_fl, + prev_point, &dist_px, co, NULL)) { diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 3a6825aacb4..6b5c27b68f4 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -30,18 +30,11 @@ struct ARegion; struct ARegionType; -struct Base; struct BoundBox; struct Depsgraph; -struct GPUBatch; -struct Mesh; struct Object; -struct SmokeDomainSettings; struct ViewLayer; -struct bAnimVizSettings; struct bContext; -struct bMotionPath; -struct bPoseChannel; struct wmGizmoGroupType; struct wmGizmoType; struct wmKeyConfig; diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 725f655c8ce..1c9ce142165 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -88,6 +88,7 @@ #include "ED_particle.h" #include "ED_mesh.h" #include "ED_object.h" +#include "ED_outliner.h" #include "ED_screen.h" #include "ED_select_utils.h" #include "ED_sculpt.h" @@ -1280,9 +1281,15 @@ static bool view3d_lasso_select( } else if (ob && (ob->mode & OB_MODE_POSE)) { changed_multi |= do_lasso_select_pose(vc, mcords, moves, sel_op); + if (changed_multi) { + ED_outliner_select_sync_from_pose_bone_tag(C); + } } else { changed_multi |= do_lasso_select_objects(vc, mcords, moves, sel_op); + if (changed_multi) { + ED_outliner_select_sync_from_object_tag(C); + } } } else { /* Edit Mode */ @@ -1303,12 +1310,15 @@ static bool view3d_lasso_select( break; case OB_ARMATURE: changed = do_lasso_select_armature(vc, mcords, moves, sel_op); + if (changed) { + ED_outliner_select_sync_from_edit_bone_tag(C); + } break; case OB_MBALL: changed = do_lasso_select_meta(vc, mcords, moves, sel_op); break; default: - assert(!"lasso select on incorrect object type"); + BLI_assert(!"lasso select on incorrect object type"); break; } @@ -1488,6 +1498,9 @@ static int object_select_menu_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + + ED_outliner_select_sync_from_object_tag(C); + return OPERATOR_FINISHED; } else { @@ -2350,6 +2363,9 @@ static int view3d_select_exec(bContext *C, wmOperator *op) if (!retval && deselect_all) { retval = ED_armature_edit_deselect_all_visible_multi(C); } + if (retval) { + ED_outliner_select_sync_from_edit_bone_tag(C); + } } else if (obedit->type == OB_LATTICE) { retval = ED_lattice_select_pick(C, location, extend, deselect, toggle); @@ -2410,6 +2426,15 @@ static int view3d_select_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); } } + + if (retval) { + if (obact && obact->mode & OB_MODE_POSE) { + ED_outliner_select_sync_from_pose_bone_tag(C); + } + else { + ED_outliner_select_sync_from_object_tag(C); + } + } } /* Pass-through allows tweaks @@ -3230,6 +3255,7 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op) if (changed) { DEG_id_tag_update(&vc.obedit->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, vc.obedit); + ED_outliner_select_sync_from_edit_bone_tag(C); } break; case OB_LATTICE: @@ -3240,7 +3266,7 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op) } break; default: - assert(!"box select on incorrect object type"); + BLI_assert(!"box select on incorrect object type"); break; } changed_multi |= changed; @@ -3264,9 +3290,15 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op) } else if (vc.obact && vc.obact->mode & OB_MODE_POSE) { changed_multi = do_pose_box_select(C, &vc, &rect, sel_op); + if (changed_multi) { + ED_outliner_select_sync_from_pose_bone_tag(C); + } } else { /* object mode with none active */ changed_multi = do_object_box_select(C, &vc, &rect, sel_op); + if (changed_multi) { + ED_outliner_select_sync_from_object_tag(C); + } } } @@ -3890,7 +3922,8 @@ static bool mball_circle_select(ViewContext *vc, /** Callbacks for circle selection in Editmode */ -static bool obedit_circle_select(ViewContext *vc, +static bool obedit_circle_select(bContext *C, + ViewContext *vc, wmGenericUserData *wm_userdata, const eSelectOp sel_op, const int mval[2], @@ -3911,6 +3944,9 @@ static bool obedit_circle_select(ViewContext *vc, break; case OB_ARMATURE: changed = armature_circle_select(vc, sel_op, mval, rad); + if (changed) { + ED_outliner_select_sync_from_edit_bone_tag(C); + } break; case OB_MBALL: changed = mball_circle_select(vc, sel_op, mval, rad); @@ -3999,7 +4035,7 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op) obedit = vc.obedit; if (obedit) { - obedit_circle_select(&vc, wm_userdata, sel_op, mval, (float)radius); + obedit_circle_select(C, &vc, wm_userdata, sel_op, mval, (float)radius); } else if (BKE_paint_select_face_test(obact)) { paint_facesel_circle_select(&vc, wm_userdata, sel_op, mval, (float)radius); @@ -4009,6 +4045,7 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op) } else if (obact->mode & OB_MODE_POSE) { pose_circle_select(&vc, sel_op, mval, (float)radius); + ED_outliner_select_sync_from_pose_bone_tag(C); } else { BLI_assert(0); @@ -4029,6 +4066,8 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op) if (object_circle_select(&vc, sel_op, mval, (float)radius)) { DEG_id_tag_update(&vc.scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc.scene); + + ED_outliner_select_sync_from_object_tag(C); } } diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c index 7f930f1d876..1af94e3ade5 100644 --- a/source/blender/editors/space_view3d/view3d_utils.c +++ b/source/blender/editors/space_view3d/view3d_utils.c @@ -622,8 +622,8 @@ bool ED_view3d_camera_autokey( /** * Call after modifying a locked view. * - * \note Not every view edit currently auto-keys (numpad for eg), - * this is complicated because of smoothview. + * \note Not every view edit currently auto-keys (num-pad for eg), + * this is complicated because of smooth-view. */ bool ED_view3d_camera_lock_autokey(View3D *v3d, RegionView3D *rv3d, diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 14995144c5c..c344b6c8649 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -3520,7 +3520,7 @@ static void initShear_mouseInputMode(TransInfo *t) copy_v3_v3(dir, t->orient_matrix[t->orient_axis_ortho]); } else { - cross_v3_v3v3(dir, t->orient_matrix[t->orient_axis_ortho], t->orient_matrix[t->orient_axis]); + cross_v3_v3v3(dir, t->orient_matrix[t->orient_axis], t->orient_matrix[t->orient_axis_ortho]); } /* Without this, half the gizmo handles move in the opposite direction. */ @@ -6601,7 +6601,7 @@ static void slide_origdata_interp_data_vert(SlideOrigData *sod, * and we do not want to mess up other shape keys */ BM_loop_interp_from_face(bm, l, f_copy, false, false); - /* make sure face-attributes are correct (e.g. MTexPoly) */ + /* make sure face-attributes are correct (e.g. #MLoopUV, #MLoopCol) */ BM_elem_attrs_copy_ex(sod->bm_origfaces, bm, f_copy, l->f, 0x0, CD_MASK_NORMAL); /* weight the loop */ diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index b023199fa1b..45efde24d83 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -42,7 +42,6 @@ struct EditBone; struct NumInput; struct Object; struct RNG; -struct RenderEngineType; struct ReportList; struct Scene; struct ScrArea; @@ -52,7 +51,6 @@ struct TransDataContainer; struct TransInfo; struct TransSnap; struct TransformOrientation; -struct View3D; struct ViewLayer; struct bConstraint; struct bContext; @@ -85,7 +83,9 @@ typedef struct TransSnap { bool snap_self; bool peel; bool snap_spatial_grid; - short status; + char status; + /* Snapped Element Type (currently for objects only). */ + char snapElem; /** snapping from this point (in global-space). */ float snapPoint[3]; /** to this point (in global-space). */ @@ -375,6 +375,7 @@ typedef struct VertSlideParams { typedef struct BoneInitData { struct EditBone *bone; float tail[3]; + float rad_head; float rad_tail; float roll; float head[3]; @@ -1164,4 +1165,7 @@ bool checkUseAxisMatrix(TransInfo *t); th != tc_end; \ th++, i++) +void trans_obdata_in_obmode_update_all(struct TransInfo *t); +void trans_obchild_in_obmode_update_all(struct TransInfo *t); + #endif diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index ef9d23d1db8..611992c1d3c 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -52,6 +52,7 @@ #include "BLI_string.h" #include "BLI_bitmap.h" #include "BLI_rect.h" +#include "BLI_kdtree.h" #include "BKE_action.h" #include "BKE_animsys.h" @@ -235,8 +236,9 @@ static void sort_trans_data_selected_first(TransInfo *t) } } -/* distance calculated from not-selected vertex to nearest selected vertex - * warning; this is loops inside loop, has minor N^2 issues, but by sorting list it is OK */ +/** + * Distance calculated from not-selected vertex to nearest selected vertex. + */ static void set_prop_dist(TransInfo *t, const bool with_dist) { int a; @@ -255,54 +257,124 @@ static void set_prop_dist(TransInfo *t, const bool with_dist) } } + /* Count number of selected. */ + int td_table_len = 0; FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *tob = tc->data; - for (a = 0; a < tc->data_len; a++, tob++) { + TransData *td = tc->data; + for (a = 0; a < tc->data_len; a++, td++) { + if (td->flag & TD_SELECTED) { + td_table_len++; + } + else { + /* By definition transform-data has selected items in beginning. */ + break; + } + } + } - tob->rdist = 0.0f; // init, it was mallocced + /* Pointers to selected's #TransData. + * Used to find #TransData from the index returned by #BLI_kdtree_find_nearest. */ + TransData **td_table = MEM_mallocN(sizeof(*td_table) * td_table_len, __func__); - if ((tob->flag & TD_SELECTED) == 0) { - TransData *td; - int i; - float dist_sq, vec[3]; + /* Create and fill kd-tree of selected's positions - in global or proj_vec space. */ + KDTree_3d *td_tree = BLI_kdtree_3d_new(td_table_len); - tob->rdist = -1.0f; // signal for next loop + int td_table_index = 0; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (a = 0; a < tc->data_len; a++, td++) { + if (td->flag & TD_SELECTED) { + /* Initialize, it was mallocced. */ + float vec[3]; + td->rdist = 0.0f; + + if (use_island) { + if (tc->use_local_mat) { + mul_v3_m4v3(vec, tc->mat, td->iloc); + } + else { + mul_v3_m3v3(vec, td->mtx, td->iloc); + } + } + else { + if (tc->use_local_mat) { + mul_v3_m4v3(vec, tc->mat, td->center); + } + else { + mul_v3_m3v3(vec, td->mtx, td->center); + } + } - for (i = 0, td = tc->data; i < tc->data_len; i++, td++) { - if (td->flag & TD_SELECTED) { - if (use_island) { - sub_v3_v3v3(vec, tob->iloc, td->iloc); - } - else { - sub_v3_v3v3(vec, tob->center, td->center); - } - mul_m3_v3(tob->mtx, vec); + if (proj_vec) { + float vec_p[3]; + project_v3_v3v3(vec_p, vec, proj_vec); + sub_v3_v3(vec, vec_p); + } - if (proj_vec) { - float vec_p[3]; - project_v3_v3v3(vec_p, vec, proj_vec); - sub_v3_v3(vec, vec_p); - } + BLI_kdtree_3d_insert(td_tree, td_table_index, vec); + td_table[td_table_index++] = td; + } + else { + /* By definition transform-data has selected items in beginning. */ + break; + } + } + } + BLI_assert(td_table_index == td_table_len); - dist_sq = len_squared_v3(vec); - if ((tob->rdist == -1.0f) || (dist_sq < SQUARE(tob->rdist))) { - tob->rdist = sqrtf(dist_sq); - if (use_island) { - copy_v3_v3(tob->center, td->center); - copy_m3_m3(tob->axismtx, td->axismtx); - } - } + BLI_kdtree_3d_balance(td_tree); + + /* For each non-selected vertex, find distance to the nearest selected vertex. */ + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (a = 0; a < tc->data_len; a++, td++) { + if ((td->flag & TD_SELECTED) == 0) { + float vec[3]; + + if (use_island) { + if (tc->use_local_mat) { + mul_v3_m4v3(vec, tc->mat, td->iloc); } else { - break; /* by definition transdata has selected items in beginning */ + mul_v3_m3v3(vec, td->mtx, td->iloc); } } + else { + if (tc->use_local_mat) { + mul_v3_m4v3(vec, tc->mat, td->center); + } + else { + mul_v3_m3v3(vec, td->mtx, td->center); + } + } + + if (proj_vec) { + float vec_p[3]; + project_v3_v3v3(vec_p, vec, proj_vec); + sub_v3_v3(vec, vec_p); + } + + KDTreeNearest_3d nearest; + const int td_index = BLI_kdtree_3d_find_nearest(td_tree, vec, &nearest); + + td->rdist = -1.0f; + if (td_index != -1) { + td->rdist = nearest.dist; + if (use_island) { + copy_v3_v3(td->center, td_table[td_index]->center); + copy_m3_m3(td->axismtx, td_table[td_index]->axismtx); + } + } + if (with_dist) { - tob->dist = tob->rdist; + td->dist = td->rdist; } } } } + + BLI_kdtree_3d_free(td_tree); + MEM_freeN(td_table); } /* ************************** CONVERSIONS ************************* */ @@ -1445,6 +1517,7 @@ void restoreBones(TransDataContainer *tc) ebo = bid->bone; ebo->dist = bid->dist; + ebo->rad_head = bid->rad_head; ebo->rad_tail = bid->rad_tail; ebo->roll = bid->roll; ebo->xwidth = bid->xwidth; @@ -1710,6 +1783,7 @@ static void createTransArmatureVerts(TransInfo *t) if (eboflip) { bid[i].bone = eboflip; bid[i].dist = eboflip->dist; + bid[i].rad_head = eboflip->rad_head; bid[i].rad_tail = eboflip->rad_tail; bid[i].roll = eboflip->roll; bid[i].xwidth = eboflip->xwidth; @@ -6462,11 +6536,14 @@ static void flush_trans_object_base_deps_flag(Depsgraph *depsgraph, Object *obje depsgraph, &object->id, DEG_OB_COMP_TRANSFORM, set_trans_object_base_deps_flag_cb, NULL); } -static void trans_object_base_deps_flag_finish(ViewLayer *view_layer) +static void trans_object_base_deps_flag_finish(const TransInfo *t, ViewLayer *view_layer) { - for (Base *base = view_layer->object_bases.first; base; base = base->next) { - if (base->object->id.tag & LIB_TAG_DOIT) { - base->flag_legacy |= BA_SNAP_FIX_DEPS_FIASCO; + + if ((t->options & CTX_OBMODE_XFORM_OBDATA) == 0) { + for (Base *base = view_layer->object_bases.first; base; base = base->next) { + if (base->object->id.tag & LIB_TAG_DOIT) { + base->flag_legacy |= BA_SNAP_FIX_DEPS_FIASCO; + } } } } @@ -6495,7 +6572,7 @@ static void set_trans_object_base_flags(TransInfo *t) trans_object_base_deps_flag_prepare(view_layer); /* Traverse all bases and set all possible flags. */ for (Base *base = view_layer->object_bases.first; base; base = base->next) { - base->flag_legacy &= ~BA_WAS_SEL; + base->flag_legacy &= ~(BA_WAS_SEL | BA_TRANSFORM_LOCKED_IN_PLACE); if (BASE_SELECTED_EDITABLE(v3d, base)) { Object *ob = base->object; Object *parsel = ob->parent; @@ -6528,7 +6605,7 @@ static void set_trans_object_base_flags(TransInfo *t) /* Store temporary bits in base indicating that base is being modified * (directly or indirectly) by transforming objects. */ - trans_object_base_deps_flag_finish(view_layer); + trans_object_base_deps_flag_finish(t, view_layer); } static bool mark_children(Object *ob) @@ -6596,7 +6673,7 @@ static int count_proportional_objects(TransInfo *t) /* Store temporary bits in base indicating that base is being modified * (directly or indirectly) by transforming objects. */ - trans_object_base_deps_flag_finish(view_layer); + trans_object_base_deps_flag_finish(t, view_layer); return total; } @@ -6611,7 +6688,8 @@ static void clear_trans_object_base_flags(TransInfo *t) } base->flag_legacy &= ~(BA_WAS_SEL | BA_SNAP_FIX_DEPS_FIASCO | BA_TEMP_TAG | - BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT); + BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT | + BA_TRANSFORM_LOCKED_IN_PLACE); } } @@ -7049,7 +7127,15 @@ static void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t) hflag = BM_ELEM_SELECT; } - EDBM_automerge(t->scene, tc->obedit, true, hflag); + if (t->scene->toolsettings->automerge & AUTO_MERGE) { + if (t->scene->toolsettings->automerge & AUTO_MERGE_AND_SPLIT) { + EDBM_automerge_and_split( + tc->obedit, true, true, true, hflag, t->scene->toolsettings->doublimit); + } + else { + EDBM_automerge(tc->obedit, true, hflag, t->scene->toolsettings->doublimit); + } + } /* Special case, this is needed or faces won't re-select. * Flush selected edges to faces. */ @@ -7433,7 +7519,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t) else if (t->flag & T_POSE && (t->mode == TFM_BONESIZE)) { /* Handle the exception where for TFM_BONESIZE in edit mode we pretend to be * in pose mode (to use bone orientation matrix), - * in that case we don't do operations like autokeyframing. */ + * in that case we don't do operations like auto-keyframing. */ FOREACH_TRANS_DATA_CONTAINER (t, tc) { ob = tc->poseobj; DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); @@ -7604,6 +7690,278 @@ int special_transform_moving(TransInfo *t) return 0; } +/* -------------------------------------------------------------------- */ +/** \name Object Mode Custom Data + * \{ */ + +typedef struct TransDataObject { + + /** + * Object to object data transform table. + * Don't add these to transform data because we may want to include child objects + * which aren't being transformed. + * - The key is object data #ID. + * - The value is #XFormObjectData_Extra. + */ + struct GHash *obdata_in_obmode_map; + + /** + * Transform + * - The key is object data #Object. + * - The value is #XFormObjectSkipChild. + */ + struct GHash *obchild_in_obmode_map; + +} TransDataObject; + +/** \} */ + +static void trans_obdata_in_obmode_free_all(TransDataObject *tdo); +static void trans_obchild_in_obmode_free_all(TransDataObject *tdo); + +static void freeTransObjectCustomData(TransInfo *t, + TransDataContainer *UNUSED(tc), + TransCustomData *custom_data) +{ + TransDataObject *tdo = custom_data->data; + custom_data->data = NULL; + + if (t->options & CTX_OBMODE_XFORM_OBDATA) { + trans_obdata_in_obmode_free_all(tdo); + } + + if (t->options & CTX_OBMODE_XFORM_SKIP_CHILDREN) { + trans_obchild_in_obmode_free_all(tdo); + } + MEM_freeN(tdo); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Object Data in Object Mode + * + * Use to implement 'Affect Only Origins' feature. + * We need this to be detached from transform data because, + * unlike transforming regular objects, we need to transform the children. + * + * \{ */ + +struct XFormObjectData_Extra { + Object *ob; + float obmat_orig[4][4]; + struct XFormObjectData *xod; +}; + +static void trans_obdata_in_obmode_ensure_object(TransDataObject *tdo, Object *ob) +{ + if (tdo->obdata_in_obmode_map == NULL) { + tdo->obdata_in_obmode_map = BLI_ghash_ptr_new(__func__); + } + + void **xf_p; + if (!BLI_ghash_ensure_p(tdo->obdata_in_obmode_map, ob->data, &xf_p)) { + struct XFormObjectData_Extra *xf = MEM_mallocN(sizeof(*xf), __func__); + copy_m4_m4(xf->obmat_orig, ob->obmat); + xf->ob = ob; + /* Result may be NULL, that's OK. */ + xf->xod = ED_object_data_xform_create(ob->data); + *xf_p = xf; + } +} + +void trans_obdata_in_obmode_update_all(TransInfo *t) +{ + TransDataObject *tdo = t->custom.type.data; + if (tdo->obdata_in_obmode_map == NULL) { + return; + } + + struct Main *bmain = CTX_data_main(t->context); + BKE_scene_graph_evaluated_ensure(t->depsgraph, bmain); + + GHashIterator gh_iter; + GHASH_ITER (gh_iter, tdo->obdata_in_obmode_map) { + ID *id = BLI_ghashIterator_getKey(&gh_iter); + struct XFormObjectData_Extra *xf = BLI_ghashIterator_getValue(&gh_iter); + if (xf->xod == NULL) { + continue; + } + + Object *ob_eval = DEG_get_evaluated_object(t->depsgraph, xf->ob); + float imat[4][4], dmat[4][4]; + invert_m4_m4(imat, xf->obmat_orig); + mul_m4_m4m4(dmat, imat, ob_eval->obmat); + invert_m4(dmat); + + ED_object_data_xform_by_mat4(xf->xod, dmat); + DEG_id_tag_update(id, ID_RECALC_GEOMETRY); + } +} + +/** Callback for #GHash free. */ +static void trans_obdata_in_obmode_free_elem(void *xf_p) +{ + struct XFormObjectData_Extra *xf = xf_p; + if (xf->xod) { + ED_object_data_xform_destroy(xf->xod); + } + MEM_freeN(xf); +} + +static void trans_obdata_in_obmode_free_all(TransDataObject *tdo) +{ + if (tdo->obdata_in_obmode_map != NULL) { + BLI_ghash_free(tdo->obdata_in_obmode_map, NULL, trans_obdata_in_obmode_free_elem); + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Object Child Skip + * + * Don't transform unselected children, this is done using the parent inverse matrix. + * + * \note The complex logic here is caused by mixed selection within a single selection chain, + * otherwise we only need #OB_SKIP_CHILD_PARENT_IS_XFORM for single objects. + * + * \{ */ + +enum { + /** + * The parent is transformed, this is held in place. + */ + OB_SKIP_CHILD_PARENT_IS_XFORM = 1, + /** + * The same as #OB_SKIP_CHILD_PARENT_IS_XFORM, + * however this objects parent isn't transformed directly. + */ + OB_SKIP_CHILD_PARENT_IS_XFORM_INDIRECT = 3, + /** + * Use the parent invert matrix to apply transformation, + * this is needed, because breaks in the selection chain prevents this from being transformed. + * This is used to add the transform which would have been added + * if there weren't breaks in the parent/child chain. + */ + OB_SKIP_CHILD_PARENT_APPLY_TRANSFORM = 2, +}; + +struct XFormObjectSkipChild { + float obmat_orig[4][4]; + float parent_obmat_orig[4][4]; + float parent_obmat_inv_orig[4][4]; + float parent_recurse_obmat_orig[4][4]; + float parentinv_orig[4][4]; + Object *ob_parent_recurse; + int mode; +}; + +static void trans_obchild_in_obmode_ensure_object(TransDataObject *tdo, + Object *ob, + Object *ob_parent_recurse, + int mode) +{ + if (tdo->obchild_in_obmode_map == NULL) { + tdo->obchild_in_obmode_map = BLI_ghash_ptr_new(__func__); + } + + void **xf_p; + if (!BLI_ghash_ensure_p(tdo->obchild_in_obmode_map, ob, &xf_p)) { + struct XFormObjectSkipChild *xf = MEM_mallocN(sizeof(*xf), __func__); + copy_m4_m4(xf->parentinv_orig, ob->parentinv); + copy_m4_m4(xf->obmat_orig, ob->obmat); + copy_m4_m4(xf->parent_obmat_orig, ob->parent->obmat); + invert_m4_m4(xf->parent_obmat_inv_orig, ob->parent->obmat); + if (ob_parent_recurse) { + copy_m4_m4(xf->parent_recurse_obmat_orig, ob_parent_recurse->obmat); + } + xf->mode = mode; + xf->ob_parent_recurse = ob_parent_recurse; + *xf_p = xf; + } +} + +void trans_obchild_in_obmode_update_all(TransInfo *t) +{ + TransDataObject *tdo = t->custom.type.data; + if (tdo->obchild_in_obmode_map == NULL) { + return; + } + + struct Main *bmain = CTX_data_main(t->context); + BKE_scene_graph_evaluated_ensure(t->depsgraph, bmain); + + GHashIterator gh_iter; + GHASH_ITER (gh_iter, tdo->obchild_in_obmode_map) { + Object *ob = BLI_ghashIterator_getKey(&gh_iter); + struct XFormObjectSkipChild *xf = BLI_ghashIterator_getValue(&gh_iter); + + /* The following blocks below assign 'dmat'. */ + float dmat[4][4]; + + if (xf->mode == OB_SKIP_CHILD_PARENT_IS_XFORM) { + /* Parent is transformed, this isn't so compensate. */ + Object *ob_parent_eval = DEG_get_evaluated_object(t->depsgraph, ob->parent); + mul_m4_m4m4(dmat, xf->parent_obmat_inv_orig, ob_parent_eval->obmat); + invert_m4(dmat); + } + else if (xf->mode == OB_SKIP_CHILD_PARENT_IS_XFORM_INDIRECT) { + /* Calculate parent matrix (from the root transform). */ + Object *ob_parent_recurse_eval = DEG_get_evaluated_object(t->depsgraph, + xf->ob_parent_recurse); + float parent_recurse_obmat_inv[4][4]; + invert_m4_m4(parent_recurse_obmat_inv, ob_parent_recurse_eval->obmat); + mul_m4_m4m4(dmat, xf->parent_recurse_obmat_orig, parent_recurse_obmat_inv); + invert_m4(dmat); + float parent_obmat_calc[4][4]; + mul_m4_m4m4(parent_obmat_calc, dmat, xf->parent_obmat_orig); + + /* Apply to the parent inverse matrix. */ + mul_m4_m4m4(dmat, xf->parent_obmat_inv_orig, parent_obmat_calc); + invert_m4(dmat); + } + else { + BLI_assert(xf->mode == OB_SKIP_CHILD_PARENT_APPLY_TRANSFORM); + /* Transform this - without transform data. */ + Object *ob_parent_recurse_eval = DEG_get_evaluated_object(t->depsgraph, + xf->ob_parent_recurse); + float parent_recurse_obmat_inv[4][4]; + invert_m4_m4(parent_recurse_obmat_inv, ob_parent_recurse_eval->obmat); + mul_m4_m4m4(dmat, xf->parent_recurse_obmat_orig, parent_recurse_obmat_inv); + invert_m4(dmat); + float obmat_calc[4][4]; + mul_m4_m4m4(obmat_calc, dmat, xf->obmat_orig); + /* obmat_calc is just obmat. */ + + /* Get the matrices relative to the parent. */ + float obmat_parent_relative_orig[4][4]; + float obmat_parent_relative_calc[4][4]; + float obmat_parent_relative_inv_orig[4][4]; + + mul_m4_m4m4(obmat_parent_relative_orig, xf->parent_obmat_inv_orig, xf->obmat_orig); + mul_m4_m4m4(obmat_parent_relative_calc, xf->parent_obmat_inv_orig, obmat_calc); + invert_m4_m4(obmat_parent_relative_inv_orig, obmat_parent_relative_orig); + + /* Apply to the parent inverse matrix. */ + mul_m4_m4m4(dmat, obmat_parent_relative_calc, obmat_parent_relative_inv_orig); + } + + mul_m4_m4m4(ob->parentinv, dmat, xf->parentinv_orig); + + DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM); + } +} + +static void trans_obchild_in_obmode_free_all(TransDataObject *tdo) +{ + if (tdo->obchild_in_obmode_map != NULL) { + BLI_ghash_free(tdo->obchild_in_obmode_map, NULL, MEM_freeN); + } +} + +/** \} */ + static void createTransObject(bContext *C, TransInfo *t) { TransData *td = NULL; @@ -7630,6 +7988,10 @@ static void createTransObject(bContext *C, TransInfo *t) td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransOb"); tx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension), "TransObExtension"); + TransDataObject *tdo = MEM_callocN(sizeof(*tdo), __func__); + t->custom.type.data = tdo; + t->custom.type.free_cb = freeTransObjectCustomData; + CTX_DATA_BEGIN (C, Base *, base, selected_bases) { Object *ob = base->object; @@ -7648,6 +8010,24 @@ static void createTransObject(bContext *C, TransInfo *t) td->flag |= TD_SKIP; } + if (t->options & CTX_OBMODE_XFORM_OBDATA) { + ID *id = ob->data; + if (!id || id->lib) { + td->flag |= TD_SKIP; + } + else if (BKE_object_is_in_editmode(ob)) { + /* The object could have edit-mode data from another view-layer, + * it's such a corner-case it can be skipped for now - Campbell. */ + td->flag |= TD_SKIP; + } + } + + if (t->options & CTX_OBMODE_XFORM_OBDATA) { + if ((td->flag & TD_SKIP) == 0) { + trans_obdata_in_obmode_ensure_object(tdo, ob); + } + } + ObjectToTransData(t, td, ob); td->val = NULL; td++; @@ -7679,6 +8059,123 @@ static void createTransObject(bContext *C, TransInfo *t) } } } + + if (t->options & CTX_OBMODE_XFORM_OBDATA) { + GSet *objects_in_transdata = BLI_gset_ptr_new_ex(__func__, tc->data_len); + td = tc->data; + for (int i = 0; i < tc->data_len; i++, td++) { + if ((td->flag & TD_SKIP) == 0) { + BLI_gset_add(objects_in_transdata, td->ob); + } + } + + ViewLayer *view_layer = t->view_layer; + View3D *v3d = t->view; + + for (Base *base = view_layer->object_bases.first; base; base = base->next) { + Object *ob = base->object; + + /* if base is not selected, not a parent of selection + * or not a child of selection and it is editable and selectable */ + if ((base->flag_legacy & BA_WAS_SEL) && (base->flag & BASE_SELECTED) == 0 && + BASE_EDITABLE(v3d, base) && BASE_SELECTABLE(v3d, base)) { + + Object *ob_parent = ob->parent; + if (ob_parent != NULL) { + if (!BLI_gset_haskey(objects_in_transdata, ob)) { + bool parent_in_transdata = false; + while (ob_parent != NULL) { + if (BLI_gset_haskey(objects_in_transdata, ob_parent)) { + parent_in_transdata = true; + break; + } + ob_parent = ob_parent->parent; + } + if (parent_in_transdata) { + trans_obdata_in_obmode_ensure_object(tdo, ob); + } + } + } + } + } + BLI_gset_free(objects_in_transdata, NULL); + } + + if (t->options & CTX_OBMODE_XFORM_SKIP_CHILDREN) { + +#define BASE_XFORM_INDIRECT(base) \ + ((base->flag_legacy & BA_WAS_SEL) && (base->flag & BASE_SELECTED) == 0) + + GSet *objects_in_transdata = BLI_gset_ptr_new_ex(__func__, tc->data_len); + GHash *objects_parent_root = BLI_ghash_ptr_new_ex(__func__, tc->data_len); + td = tc->data; + for (int i = 0; i < tc->data_len; i++, td++) { + if ((td->flag & TD_SKIP) == 0) { + BLI_gset_add(objects_in_transdata, td->ob); + } + } + + ViewLayer *view_layer = t->view_layer; + + for (Base *base = view_layer->object_bases.first; base; base = base->next) { + Object *ob = base->object; + if (ob->parent != NULL) { + if (ob->parent && !BLI_gset_haskey(objects_in_transdata, ob->parent) && + !BLI_gset_haskey(objects_in_transdata, ob)) { + if (((base->flag_legacy & BA_WAS_SEL) && (base->flag & BASE_SELECTED) == 0)) { + Base *base_parent = BKE_view_layer_base_find(view_layer, ob->parent); + if (base_parent && !BASE_XFORM_INDIRECT(base_parent)) { + Object *ob_parent_recurse = ob->parent; + if (ob_parent_recurse != NULL) { + while (ob_parent_recurse != NULL) { + if (BLI_gset_haskey(objects_in_transdata, ob_parent_recurse)) { + break; + } + ob_parent_recurse = ob_parent_recurse->parent; + } + + if (ob_parent_recurse) { + trans_obchild_in_obmode_ensure_object( + tdo, ob, ob_parent_recurse, OB_SKIP_CHILD_PARENT_APPLY_TRANSFORM); + BLI_ghash_insert(objects_parent_root, ob, ob_parent_recurse); + base->flag_legacy |= BA_TRANSFORM_LOCKED_IN_PLACE; + } + } + } + } + } + } + } + + for (Base *base = view_layer->object_bases.first; base; base = base->next) { + Object *ob = base->object; + + if (BASE_XFORM_INDIRECT(base) || BLI_gset_haskey(objects_in_transdata, ob)) { + /* pass. */ + } + else if (ob->parent != NULL) { + Base *base_parent = BKE_view_layer_base_find(view_layer, ob->parent); + if (base_parent) { + if (BASE_XFORM_INDIRECT(base_parent) || + BLI_gset_haskey(objects_in_transdata, ob->parent)) { + trans_obchild_in_obmode_ensure_object(tdo, ob, NULL, OB_SKIP_CHILD_PARENT_IS_XFORM); + base->flag_legacy |= BA_TRANSFORM_LOCKED_IN_PLACE; + } + else { + Object *ob_parent_recurse = BLI_ghash_lookup(objects_parent_root, ob->parent); + if (ob_parent_recurse) { + trans_obchild_in_obmode_ensure_object( + tdo, ob, ob_parent_recurse, OB_SKIP_CHILD_PARENT_IS_XFORM_INDIRECT); + } + } + } + } + } + BLI_gset_free(objects_in_transdata, NULL); + BLI_ghash_free(objects_parent_root, NULL, NULL); + +#undef BASE_XFORM_INDIRECT + } } /* transcribe given node into TransData2D for Transforming */ @@ -9665,6 +10162,13 @@ void createTransData(bContext *C, TransInfo *t) /* Needed for correct Object.obmat after duplication, see: T62135. */ BKE_scene_graph_evaluated_ensure(t->depsgraph, CTX_data_main(t->context)); + if ((scene->toolsettings->transform_flag & SCE_XFORM_DATA_ORIGIN) != 0) { + t->options |= CTX_OBMODE_XFORM_OBDATA; + } + if ((scene->toolsettings->transform_flag & SCE_XFORM_SKIP_CHILDREN) != 0) { + t->options |= CTX_OBMODE_XFORM_SKIP_CHILDREN; + } + createTransObject(C, t); countAndCleanTransDataContainer(t); t->flag |= T_OBJECT; diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 969e2558abb..7ae140e1815 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -81,6 +81,7 @@ #include "BKE_workspace.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" #include "ED_anim_api.h" #include "ED_armature.h" @@ -900,7 +901,7 @@ static void recalcData_objects(TransInfo *t) DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); EDBM_mesh_normals_update(em); - BKE_editmesh_tessface_calc(em); + BKE_editmesh_looptri_calc(em); } } else if (t->obedit_type == OB_ARMATURE) { /* no recalc flag, does pose */ @@ -1149,6 +1150,14 @@ static void recalcData_objects(TransInfo *t) /* Update motion paths once for all transformed objects. */ ED_objects_recalculate_paths(t->context, t->scene, true); } + + if (t->options & CTX_OBMODE_XFORM_SKIP_CHILDREN) { + trans_obchild_in_obmode_update_all(t); + } + + if (t->options & CTX_OBMODE_XFORM_OBDATA) { + trans_obdata_in_obmode_update_all(t); + } } } diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c index fbfeb4f53de..355cf139abf 100644 --- a/source/blender/editors/transform/transform_gizmo_3d.c +++ b/source/blender/editors/transform/transform_gizmo_3d.c @@ -1392,7 +1392,8 @@ void drawDial3d(const TransInfo *t) scale *= ED_view3d_pixel_size_no_ui_scale(t->ar->regiondata, mat_final[3]); mul_mat3_m4_fl(mat_final, scale); - if ((t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)) && activeSnap(t)) { + if (activeSnap(t) && (!transformModeUseSnap(t) || + (t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)))) { increment = (t->modifiers & MOD_PRECISION) ? t->snap[2] : t->snap[1]; } else { diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c index 6ebed88878f..e771fe43bd8 100644 --- a/source/blender/editors/transform/transform_input.c +++ b/source/blender/editors/transform/transform_input.c @@ -299,7 +299,7 @@ static void calcSpringFactor(MouseInput *mi) void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode) { - /* incase we allocate a new value */ + /* In case we allocate a new value. */ void *mi_data_prev = mi->data; mi->use_virtual_mval = true; diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index f8e33fe70ad..604c5bbc083 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -139,22 +139,22 @@ const EnumPropertyItem rna_enum_transform_mode_types[] = { {TFM_CREASE, "CREASE", 0, "Crease", ""}, {TFM_MIRROR, "MIRROR", 0, "Mirror", ""}, {TFM_BONESIZE, "BONE_SIZE", 0, "Bonesize", ""}, - {TFM_BONE_ENVELOPE, "BONE_ENVELOPE", 0, "Bone_Envelope", ""}, - {TFM_BONE_ENVELOPE_DIST, "BONE_ENVELOPE_DIST", 0, "Bone_Envelope_Distance", ""}, - {TFM_CURVE_SHRINKFATTEN, "CURVE_SHRINKFATTEN", 0, "Curve_Shrinkfatten", ""}, - {TFM_MASK_SHRINKFATTEN, "MASK_SHRINKFATTEN", 0, "Mask_Shrinkfatten", ""}, - {TFM_GPENCIL_SHRINKFATTEN, "GPENCIL_SHRINKFATTEN", 0, "GPencil_Shrinkfatten", ""}, - {TFM_BONE_ROLL, "BONE_ROLL", 0, "Bone_Roll", ""}, - {TFM_TIME_TRANSLATE, "TIME_TRANSLATE", 0, "Time_Translate", ""}, - {TFM_TIME_SLIDE, "TIME_SLIDE", 0, "Time_Slide", ""}, - {TFM_TIME_SCALE, "TIME_SCALE", 0, "Time_Scale", ""}, - {TFM_TIME_EXTEND, "TIME_EXTEND", 0, "Time_Extend", ""}, - {TFM_BAKE_TIME, "BAKE_TIME", 0, "Bake_Time", ""}, + {TFM_BONE_ENVELOPE, "BONE_ENVELOPE", 0, "Bone Envelope", ""}, + {TFM_BONE_ENVELOPE_DIST, "BONE_ENVELOPE_DIST", 0, "Bone Envelope Distance", ""}, + {TFM_CURVE_SHRINKFATTEN, "CURVE_SHRINKFATTEN", 0, "Curve Shrinkfatten", ""}, + {TFM_MASK_SHRINKFATTEN, "MASK_SHRINKFATTEN", 0, "Mask Shrinkfatten", ""}, + {TFM_GPENCIL_SHRINKFATTEN, "GPENCIL_SHRINKFATTEN", 0, "GPencil Shrinkfatten", ""}, + {TFM_BONE_ROLL, "BONE_ROLL", 0, "Bone Roll", ""}, + {TFM_TIME_TRANSLATE, "TIME_TRANSLATE", 0, "Time Translate", ""}, + {TFM_TIME_SLIDE, "TIME_SLIDE", 0, "Time Slide", ""}, + {TFM_TIME_SCALE, "TIME_SCALE", 0, "Time Scale", ""}, + {TFM_TIME_EXTEND, "TIME_EXTEND", 0, "Time Extend", ""}, + {TFM_BAKE_TIME, "BAKE_TIME", 0, "Bake Time", ""}, {TFM_BWEIGHT, "BWEIGHT", 0, "Bweight", ""}, {TFM_ALIGN, "ALIGN", 0, "Align", ""}, {TFM_EDGE_SLIDE, "EDGESLIDE", 0, "Edge Slide", ""}, {TFM_SEQ_SLIDE, "SEQSLIDE", 0, "Sequence Slide", ""}, - {TFM_GPENCIL_OPACITY, "GPENCIL_OPACITY", 0, "GPencil_Opacity", ""}, + {TFM_GPENCIL_OPACITY, "GPENCIL_OPACITY", 0, "GPencil Opacity", ""}, {0, NULL, 0, NULL, NULL}, }; @@ -573,7 +573,7 @@ void Transform_Properties(struct wmOperatorType *ot, int flags) if (flags & P_ORIENT_AXIS_ORTHO) { prop = RNA_def_property(ot->srna, "orient_axis_ortho", PROP_ENUM, PROP_NONE); RNA_def_property_ui_text(prop, "Axis Ortho", ""); - RNA_def_property_enum_default(prop, 1); + RNA_def_property_enum_default(prop, 0); RNA_def_property_enum_items(prop, rna_enum_axis_xyz_items); RNA_def_property_flag(prop, PROP_SKIP_SAVE); } diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index dbcc6c1b04a..571ce7a6bc2 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -166,7 +166,10 @@ void drawSnapping(const struct bContext *C, TransInfo *t) activeCol[3] = 192; if (t->spacetype == SPACE_VIEW3D) { - if (validSnap(t)) { + bool draw_target = (t->tsnap.status & TARGET_INIT) && + (t->scene->toolsettings->snap_mode & SCE_SNAP_MODE_EDGE_PERPENDICULAR); + + if (draw_target || validSnap(t)) { TransSnapPoint *p; RegionView3D *rv3d = CTX_wm_region_view3d(C); float imat[4][4]; @@ -214,6 +217,48 @@ void drawSnapping(const struct bContext *C, TransInfo *t) immEnd(); } + if (draw_target) { + /* Draw snapTarget */ + float targ_co[3], vx[3], vy[3], v1[3], v2[3], v3[3], v4[4]; + copy_v3_v3(targ_co, t->tsnap.snapTarget); + float px_size = 0.75f * size * ED_view3d_pixel_size(rv3d, targ_co); + + mul_v3_v3fl(vx, imat[0], px_size); + mul_v3_v3fl(vy, imat[1], px_size); + + add_v3_v3v3(v1, vx, vy); + sub_v3_v3v3(v2, vx, vy); + negate_v3_v3(v3, v1); + negate_v3_v3(v4, v2); + + add_v3_v3(v1, targ_co); + add_v3_v3(v2, targ_co); + add_v3_v3(v3, targ_co); + add_v3_v3(v4, targ_co); + + immUniformColor4ubv(col); + immBegin(GPU_PRIM_LINES, 4); + immVertex3fv(pos, v3); + immVertex3fv(pos, v1); + immVertex3fv(pos, v4); + immVertex3fv(pos, v2); + immEnd(); + + if (t->tsnap.snapElem & SCE_SNAP_MODE_EDGE_PERPENDICULAR) { + immUnbindProgram(); + + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); + immUniform1f("dash_width", 6.0f * U.pixelsize); + immUniform1f("dash_factor", 1.0f / 4.0f); + immUniformColor4ubv(col); + + immBegin(GPU_PRIM_LINES, 2); + immVertex3fv(pos, targ_co); + immVertex3fv(pos, t->tsnap.snapPoint); + immEnd(); + } + } + immUnbindProgram(); GPU_depth_test(true); @@ -328,6 +373,7 @@ void applyProject(TransInfo *t) .use_occlusion_test = false, }, mval_fl, + NULL, 0, loc, no)) { @@ -586,12 +632,18 @@ static void initSnappingMode(TransInfo *t) else if (t->tsnap.applySnap != NULL && // A snapping function actually exist (obedit_type == -1)) // Object Mode { - /* In "Edit Strokes" mode, - * snap tool can perform snap to selected or active objects (see T49632) - * TODO: perform self snap in gpencil_strokes */ - t->tsnap.modeSelect = (((t->options & (CTX_GPENCIL_STROKES | CTX_CURSOR)) != 0) ? - SNAP_ALL : - SNAP_NOT_SELECTED); + + if (t->options & (CTX_GPENCIL_STROKES | CTX_CURSOR | CTX_OBMODE_XFORM_OBDATA)) { + /* In "Edit Strokes" mode, + * snap tool can perform snap to selected or active objects (see T49632) + * TODO: perform self snap in gpencil_strokes. + * + * When we're moving the origins, allow snapping onto our own geometry (see T69132). */ + t->tsnap.modeSelect = SNAP_ALL; + } + else { + t->tsnap.modeSelect = SNAP_NOT_SELECTED; + } } else { /* Grid if snap is not possible */ @@ -993,18 +1045,25 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec)) float no[3]; float mval[2]; bool found = false; + short snap_elem = 0; float dist_px = SNAP_MIN_DISTANCE; // Use a user defined value here mval[0] = t->mval[0]; mval[1] = t->mval[1]; - if (t->tsnap.mode & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE)) { + if (t->tsnap.mode & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE | + SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) { zero_v3(no); /* objects won't set this */ - found = snapObjectsTransform(t, mval, &dist_px, loc, no); + snap_elem = snapObjectsTransform(t, mval, &dist_px, loc, no); + found = snap_elem != 0; } if ((found == false) && (t->tsnap.mode & SCE_SNAP_MODE_VOLUME)) { found = peelObjectsTransform( t, mval, (t->settings->snap_flag & SCE_SNAP_PEEL_OBJECT) != 0, loc, no, NULL); + + if (found) { + snap_elem = SCE_SNAP_MODE_VOLUME; + } } if (found == true) { @@ -1016,6 +1075,8 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec)) else { t->tsnap.status &= ~POINT_INIT; } + + t->tsnap.snapElem = (char)snap_elem; } else if (t->spacetype == SPACE_IMAGE && t->obedit_type == OB_MESH) { if (t->tsnap.mode & SCE_SNAP_MODE_VERTEX) { @@ -1186,7 +1247,11 @@ static void TargetSnapClosest(TransInfo *t) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (td = tc->data, i = 0; i < tc->data_len && td->flag & TD_SELECTED; i++, td++) { - struct BoundBox *bb = BKE_object_boundbox_get(td->ob); + const BoundBox *bb = NULL; + + if ((t->options & CTX_OBMODE_XFORM_OBDATA) == 0) { + bb = BKE_object_boundbox_get(td->ob); + } /* use boundbox if possible */ if (bb) { @@ -1259,10 +1324,10 @@ static void TargetSnapClosest(TransInfo *t) } } -bool snapObjectsTransform( +short snapObjectsTransform( TransInfo *t, const float mval[2], float *dist_px, float r_loc[3], float r_no[3]) { - return ED_transform_snap_object_project_view3d( + return ED_transform_snap_object_project_view3d_ex( t->tsnap.object_context, t->scene->toolsettings->snap_mode, &(const struct SnapObjectParams){ @@ -1271,9 +1336,13 @@ bool snapObjectsTransform( .use_occlusion_test = t->scene->toolsettings->snap_mode != SCE_SNAP_MODE_FACE, }, mval, + t->tsnap.snapTarget, dist_px, r_loc, - r_no); + r_no, + NULL, + NULL, + NULL); } /******************** PEELING *********************************/ diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index 67bd107ab49..d3cf52ce3fd 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -221,22 +221,40 @@ static void iter_snap_objects(SnapObjectContext *sctx, Base *base_act = view_layer->basact; for (Base *base = view_layer->object_bases.first; base != NULL; base = base->next) { - if ((BASE_VISIBLE(v3d, base)) && (base->flag_legacy & BA_SNAP_FIX_DEPS_FIASCO) == 0 && - !((snap_select == SNAP_NOT_SELECTED && - ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL))) || - (snap_select == SNAP_NOT_ACTIVE && base == base_act))) { - Object *obj_eval = DEG_get_evaluated_object(sctx->depsgraph, base->object); - if (obj_eval->transflag & OB_DUPLI) { - DupliObject *dupli_ob; - ListBase *lb = object_duplilist(sctx->depsgraph, sctx->scene, obj_eval); - for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) { - sob_callback(sctx, use_object_edit_cage, dupli_ob->ob, dupli_ob->mat, data); - } - free_object_duplilist(lb); + + if (!BASE_VISIBLE(v3d, base)) { + continue; + } + + if (base->flag_legacy & BA_TRANSFORM_LOCKED_IN_PLACE) { + /* pass */ + } + else if (base->flag_legacy & BA_SNAP_FIX_DEPS_FIASCO) { + continue; + } + + if (snap_select == SNAP_NOT_SELECTED) { + if ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL)) { + continue; + } + } + else if (snap_select == SNAP_NOT_ACTIVE) { + if (base == base_act) { + continue; } + } - sob_callback(sctx, use_object_edit_cage, obj_eval, obj_eval->obmat, data); + Object *obj_eval = DEG_get_evaluated_object(sctx->depsgraph, base->object); + if (obj_eval->transflag & OB_DUPLI) { + DupliObject *dupli_ob; + ListBase *lb = object_duplilist(sctx->depsgraph, sctx->scene, obj_eval); + for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) { + sob_callback(sctx, use_object_edit_cage, dupli_ob->ob, dupli_ob->mat, data); + } + free_object_duplilist(lb); } + + sob_callback(sctx, use_object_edit_cage, obj_eval, obj_eval->obmat, data); } } @@ -583,37 +601,31 @@ static bool raycastEditMesh(SnapObjectContext *sctx, } if (treedata->tree == NULL) { - BVHCache **bvh_cache = NULL; - BLI_bitmap *elem_mask = NULL; - BMEditMesh *em_orig; - int looptri_num_active = -1; - /* Get original version of the edit_mesh. */ - em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob)); + BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob)); if (sctx->callbacks.edit_mesh.test_face_fn) { BMesh *bm = em_orig->bm; BLI_assert(poly_to_tri_count(bm->totface, bm->totloop) == em_orig->tottri); - elem_mask = BLI_BITMAP_NEW(em_orig->tottri, __func__); - looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface( + BLI_bitmap *elem_mask = BLI_BITMAP_NEW(em_orig->tottri, __func__); + int looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface( bm, elem_mask, sctx->callbacks.edit_mesh.test_face_fn, sctx->callbacks.edit_mesh.user_data); + + bvhtree_from_editmesh_looptri_ex( + treedata, em_orig, elem_mask, looptri_num_active, 0.0f, 4, 6, 0, NULL); + + MEM_freeN(elem_mask); } else { /* Only cache if bvhtree is created without a mask. * This helps keep a standardized bvhtree in cache. */ - bvh_cache = em_bvh_cache; + BKE_bvhtree_from_editmesh_get(treedata, em_orig, 4, BVHTREE_FROM_EM_LOOPTRI, em_bvh_cache); } - bvhtree_from_editmesh_looptri_ex( - treedata, em_orig, elem_mask, looptri_num_active, 0.0f, 4, 6, bvh_cache); - - if (elem_mask) { - MEM_freeN(elem_mask); - } if (treedata->tree == NULL) { return retval; } @@ -1260,7 +1272,8 @@ static short snap_mesh_polygon(SnapObjectContext *sctx, const MPoly *mp = &((SnapObjectData_Mesh *)sod)->poly[*r_index]; const MLoop *ml = &treedata->loop[mp->loopstart]; - if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) { + if (snapdata->snap_to_flag & + (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) { elem = SCE_SNAP_MODE_EDGE; BLI_assert(treedata->edge != NULL); for (int i = mp->totloop; i--; ml++) { @@ -1297,7 +1310,8 @@ static short snap_mesh_polygon(SnapObjectContext *sctx, BMFace *f = BM_face_at_index(em->bm, *r_index); BMLoop *l_iter, *l_first; l_iter = l_first = BM_FACE_FIRST_LOOP(f); - if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) { + if (snapdata->snap_to_flag & + (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) { elem = SCE_SNAP_MODE_EDGE; BM_mesh_elem_index_ensure(em->bm, BM_EDGE); BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE); @@ -1352,6 +1366,7 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx, Object *ob, float obmat[4][4], float original_dist_px, + const float prev_co[3], /* read/write args */ float *dist_px, /* return args */ @@ -1420,19 +1435,74 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx, &lambda)) { /* do nothing */ } - else if (lambda < 0.25f || 0.75f < lambda) { - int v_id = lambda < 0.5f ? 0 : 1; + else { + if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) { + if (lambda < 0.25f || 0.75f < lambda) { + int v_id = lambda < 0.5f ? 0 : 1; - if (test_projected_vert_dist(&neasrest_precalc, - NULL, - 0, - nearest2d.is_persp, - v_pair[v_id], - &nearest.dist_sq, - nearest.co)) { - nearest.index = vindex[v_id]; - nearest2d.copy_vert_no(vindex[v_id], nearest.no, nearest2d.userdata); - elem = SCE_SNAP_MODE_VERTEX; + if (test_projected_vert_dist(&neasrest_precalc, + NULL, + 0, + nearest2d.is_persp, + v_pair[v_id], + &nearest.dist_sq, + nearest.co)) { + nearest.index = vindex[v_id]; + nearest2d.copy_vert_no(vindex[v_id], nearest.no, nearest2d.userdata); + elem = SCE_SNAP_MODE_VERTEX; + } + } + } + + if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE_MIDPOINT) { + if (0.375f < lambda && lambda < 0.625f) { + float vmid[3]; + mid_v3_v3v3(vmid, v_pair[0], v_pair[1]); + + if (test_projected_vert_dist(&neasrest_precalc, + NULL, + 0, + nearest2d.is_persp, + vmid, + &nearest.dist_sq, + nearest.co)) { + float v_nor[2][3]; + nearest2d.copy_vert_no(vindex[0], v_nor[0], nearest2d.userdata); + nearest2d.copy_vert_no(vindex[1], v_nor[1], nearest2d.userdata); + mid_v3_v3v3(nearest.no, v_nor[0], v_nor[1]); + nearest.index = *r_index; + elem = SCE_SNAP_MODE_EDGE_MIDPOINT; + } + } + } + + if (prev_co && (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE_PERPENDICULAR)) { + float v_near[3], va_g[3], vb_g[3]; + + mul_v3_m4v3(va_g, obmat, v_pair[0]); + mul_v3_m4v3(vb_g, obmat, v_pair[1]); + lambda = line_point_factor_v3(prev_co, va_g, vb_g); + + if (IN_RANGE(lambda, 0.0f, 1.0f)) { + interp_v3_v3v3(v_near, va_g, vb_g, lambda); + + if ((len_squared_v3v3(prev_co, v_near) > FLT_EPSILON) && + test_projected_vert_dist(&neasrest_precalc, + NULL, + 0, + nearest2d.is_persp, + v_near, + &nearest.dist_sq, + nearest.co)) { + float v_nor[2][3]; + nearest2d.copy_vert_no(vindex[0], v_nor[0], nearest2d.userdata); + nearest2d.copy_vert_no(vindex[1], v_nor[1], nearest2d.userdata); + mid_v3_v3v3(nearest.no, v_nor[0], v_nor[1]); + + nearest.index = *r_index; + elem = SCE_SNAP_MODE_EDGE_PERPENDICULAR; + } + } } } @@ -1440,7 +1510,9 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx, *dist_px = sqrtf(nearest.dist_sq); copy_v3_v3(r_loc, nearest.co); - mul_m4_v3(obmat, r_loc); + if (elem != SCE_SNAP_MODE_EDGE_PERPENDICULAR) { + mul_m4_v3(obmat, r_loc); + } if (r_no) { float imat[4][4]; @@ -1926,13 +1998,13 @@ static short snapMesh(SnapObjectContext *sctx, { BLI_assert(snapdata->snap_to_flag != SCE_SNAP_MODE_FACE); - if ((snapdata->snap_to_flag & ~SCE_SNAP_MODE_FACE) == SCE_SNAP_MODE_EDGE) { - if (me->totedge == 0) { + if ((snapdata->snap_to_flag & ~SCE_SNAP_MODE_FACE) == SCE_SNAP_MODE_VERTEX) { + if (me->totvert == 0) { return 0; } } else { - if (me->totvert == 0) { + if (me->totedge == 0) { return 0; } } @@ -2066,7 +2138,8 @@ static short snapMesh(SnapObjectContext *sctx, last_index = nearest.index; } - if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) { + if (snapdata->snap_to_flag & + (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) { if (bvhtree[0]) { /* snap to loose edges */ BLI_bvhtree_find_nearest_projected(bvhtree[0], @@ -2164,13 +2237,13 @@ static short snapEditMesh(SnapObjectContext *sctx, { BLI_assert(snapdata->snap_to_flag != SCE_SNAP_MODE_FACE); - if ((snapdata->snap_to_flag & ~SCE_SNAP_MODE_FACE) == SCE_SNAP_MODE_EDGE) { - if (em->bm->totedge == 0) { + if ((snapdata->snap_to_flag & ~SCE_SNAP_MODE_FACE) == SCE_SNAP_MODE_VERTEX) { + if (em->bm->totvert == 0) { return 0; } } else { - if (em->bm->totvert == 0) { + if (em->bm->totedge == 0) { return 0; } } @@ -2223,16 +2296,17 @@ static short snapEditMesh(SnapObjectContext *sctx, sctx->callbacks.edit_mesh.user_data); bvhtree_from_editmesh_verts_ex( - treedata_vert, em, verts_mask, verts_num_active, 0.0f, 2, 6); + treedata_vert, em, verts_mask, verts_num_active, 0.0f, 2, 6, 0, NULL); MEM_freeN(verts_mask); } else { - bvhtree_from_editmesh_verts(treedata_vert, em, 0.0f, 2, 6, em_bvh_cache); + BKE_bvhtree_from_editmesh_get(treedata_vert, em, 2, BVHTREE_FROM_EM_VERTS, em_bvh_cache); } } } - if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) { + if (snapdata->snap_to_flag & + (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) { if (sod->bvh_trees[1] == NULL) { sod->bvh_trees[1] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(**sod->bvh_trees)); } @@ -2258,11 +2332,11 @@ static short snapEditMesh(SnapObjectContext *sctx, sctx->callbacks.edit_mesh.user_data); bvhtree_from_editmesh_edges_ex( - treedata_edge, em, edges_mask, edges_num_active, 0.0f, 2, 6); + treedata_edge, em, edges_mask, edges_num_active, 0.0f, 2, 6, 0, NULL); MEM_freeN(edges_mask); } else { - bvhtree_from_editmesh_edges(treedata_edge, em, 0.0f, 2, 6, em_bvh_cache); + BKE_bvhtree_from_editmesh_get(treedata_edge, em, 2, BVHTREE_FROM_EM_EDGES, em_bvh_cache); } } } @@ -2279,7 +2353,6 @@ static short snapEditMesh(SnapObjectContext *sctx, .index = -1, .dist_sq = dist_px_sq, }; - int last_index = nearest.index; short elem = SCE_SNAP_MODE_VERTEX; float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4]; @@ -2300,11 +2373,12 @@ static short snapEditMesh(SnapObjectContext *sctx, &nearest, cb_snap_vert, &nearest2d); - - last_index = nearest.index; } - if (treedata_edge && snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) { + if (treedata_edge && snapdata->snap_to_flag & (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT | + SCE_SNAP_MODE_EDGE_PERPENDICULAR)) { + int last_index = nearest.index; + nearest.index = -1; BM_mesh_elem_table_ensure(em->bm, BM_EDGE | BM_VERT); BLI_bvhtree_find_nearest_projected(treedata_edge->tree, lpmat, @@ -2316,9 +2390,12 @@ static short snapEditMesh(SnapObjectContext *sctx, cb_snap_edge, &nearest2d); - if (last_index != nearest.index) { + if (nearest.index != -1) { elem = SCE_SNAP_MODE_EDGE; } + else { + nearest.index = last_index; + } } if (nearest.index != -1) { @@ -2700,6 +2777,7 @@ static short transform_snap_context_project_view3d_mixed_impl( const unsigned short snap_to_flag, const struct SnapObjectParams *params, const float mval[2], + const float prev_co[3], float *dist_px, float r_loc[3], float r_no[3], @@ -2707,7 +2785,8 @@ static short transform_snap_context_project_view3d_mixed_impl( Object **r_ob, float r_obmat[4][4]) { - BLI_assert((snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE)) != + BLI_assert((snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE | + SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) != 0); short retval = 0; @@ -2733,7 +2812,7 @@ static short transform_snap_context_project_view3d_mixed_impl( ray_normal, ray_start, true)) { - return false; + return 0; } float dummy_ray_depth = BVH_RAYCAST_DIST_MAX; @@ -2746,7 +2825,8 @@ static short transform_snap_context_project_view3d_mixed_impl( } } - if (snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE)) { + if (snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT | + SCE_SNAP_MODE_EDGE_PERPENDICULAR)) { short elem; float dist_px_tmp = *dist_px; @@ -2799,11 +2879,18 @@ static short transform_snap_context_project_view3d_mixed_impl( retval = elem; } - if ((retval == SCE_SNAP_MODE_EDGE) && (snapdata.snap_to_flag & SCE_SNAP_MODE_VERTEX)) { - retval = snap_mesh_edge_verts_mixed( - sctx, &snapdata, ob, obmat, *dist_px, &dist_px_tmp, loc, no, &index); + if ((retval == SCE_SNAP_MODE_EDGE) && + (snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE_MIDPOINT | + SCE_SNAP_MODE_EDGE_PERPENDICULAR))) { + elem = snap_mesh_edge_verts_mixed( + sctx, &snapdata, ob, obmat, *dist_px, prev_co, &dist_px_tmp, loc, no, &index); + } + + if (elem) { + retval = elem; } + retval &= snap_to_flag; *dist_px = dist_px_tmp; } @@ -2831,6 +2918,7 @@ short ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx, const unsigned short snap_to, const struct SnapObjectParams *params, const float mval[2], + const float prev_co[3], float *dist_px, float r_loc[3], float r_no[3], @@ -2839,7 +2927,7 @@ short ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx, float r_obmat[4][4]) { return transform_snap_context_project_view3d_mixed_impl( - sctx, snap_to, params, mval, dist_px, r_loc, r_no, r_index, r_ob, r_obmat) != 0; + sctx, snap_to, params, mval, prev_co, dist_px, r_loc, r_no, r_index, r_ob, r_obmat); } /** @@ -2849,6 +2937,7 @@ short ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx, * * \param sctx: Snap context. * \param mval: Screenspace coordinate. + * \param prev_co: Coordinate for perpendicular point calculation (optional). * \param dist_px: Maximum distance to snap (in pixels). * \param r_co: hit location. * \param r_no: hit normal (optional). @@ -2858,12 +2947,13 @@ bool ED_transform_snap_object_project_view3d(SnapObjectContext *sctx, const unsigned short snap_to, const struct SnapObjectParams *params, const float mval[2], + const float prev_co[3], float *dist_px, float r_loc[3], float r_no[3]) { return ED_transform_snap_object_project_view3d_ex( - sctx, snap_to, params, mval, dist_px, r_loc, r_no, NULL, NULL, NULL) != 0; + sctx, snap_to, params, mval, prev_co, dist_px, r_loc, r_no, NULL, NULL, NULL) != 0; } /** diff --git a/source/blender/editors/undo/ed_undo.c b/source/blender/editors/undo/ed_undo.c index c84d7539cce..e0f4d1cf465 100644 --- a/source/blender/editors/undo/ed_undo.c +++ b/source/blender/editors/undo/ed_undo.c @@ -53,6 +53,7 @@ #include "ED_gpencil.h" #include "ED_render.h" #include "ED_object.h" +#include "ED_outliner.h" #include "ED_screen.h" #include "ED_undo.h" @@ -390,6 +391,8 @@ static int ed_undo_exec(bContext *C, wmOperator *op) /* Keep button under the cursor active. */ WM_event_add_mousemove(C); } + + ED_outliner_select_sync_from_all_tag(C); return ret; } @@ -417,6 +420,8 @@ static int ed_redo_exec(bContext *C, wmOperator *op) /* Keep button under the cursor active. */ WM_event_add_mousemove(C); } + + ED_outliner_select_sync_from_all_tag(C); return ret; } diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index d97714061c0..fe761f65702 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -205,14 +205,14 @@ static void draw_uvs_shadow(SpaceImage *UNUSED(sima), Object *obedit, Depsgraph *depsgraph) { - Object *eval_ob = DEG_get_evaluated_object(depsgraph, obedit); - Mesh *me = eval_ob->data; + Object *ob_eval = DEG_get_evaluated_object(depsgraph, obedit); + Mesh *me = ob_eval->data; float col[4]; UI_GetThemeColor4fv(TH_UV_SHADOW, col); DRW_mesh_batch_cache_validate(me); GPUBatch *edges = DRW_mesh_batch_cache_get_uv_edges(me); - DRW_mesh_batch_cache_create_requested(eval_ob, me, scene, false, false); + DRW_mesh_batch_cache_create_requested(ob_eval, me, scene, false, false); if (edges) { GPU_batch_program_set_builtin(edges, GPU_SHADER_2D_UV_UNIFORM_COLOR); @@ -223,8 +223,8 @@ static void draw_uvs_shadow(SpaceImage *UNUSED(sima), static void draw_uvs_texpaint(Scene *scene, Object *ob, Depsgraph *depsgraph) { - Object *eval_ob = DEG_get_evaluated_object(depsgraph, ob); - Mesh *me = eval_ob->data; + Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); + Mesh *me = ob_eval->data; ToolSettings *ts = scene->toolsettings; float col[4]; UI_GetThemeColor4fv(TH_UV_SHADOW, col); @@ -235,7 +235,7 @@ static void draw_uvs_texpaint(Scene *scene, Object *ob, Depsgraph *depsgraph) DRW_mesh_batch_cache_validate(me); GPUBatch *geom = DRW_mesh_batch_cache_get_uv_edges(me); - DRW_mesh_batch_cache_create_requested(eval_ob, me, scene, false, false); + DRW_mesh_batch_cache_create_requested(ob_eval, me, scene, false, false); GPU_batch_program_set_builtin(geom, GPU_SHADER_2D_UV_UNIFORM_COLOR); GPU_batch_uniform_4fv(geom, "color", col); @@ -246,7 +246,7 @@ static void draw_uvs_texpaint(Scene *scene, Object *ob, Depsgraph *depsgraph) MPoly *mpoly = me->mpoly; uint draw_start = 0; uint idx = 0; - bool prev_ma_match = (mpoly->mat_nr == (eval_ob->actcol - 1)); + bool prev_ma_match = (mpoly->mat_nr == (ob_eval->actcol - 1)); GPU_matrix_bind(geom->interface); GPU_batch_bind(geom); @@ -255,7 +255,7 @@ static void draw_uvs_texpaint(Scene *scene, Object *ob, Depsgraph *depsgraph) * we can use multi draw indirect drawcalls for this. * (not implemented in GPU module at the time of writing). */ for (int a = 0; a < me->totpoly; a++, mpoly++) { - bool ma_match = (mpoly->mat_nr == (eval_ob->actcol - 1)); + bool ma_match = (mpoly->mat_nr == (ob_eval->actcol - 1)); if (ma_match != prev_ma_match) { if (ma_match == false) { GPU_batch_draw_advanced(geom, draw_start, idx - draw_start, 0, 0); @@ -282,13 +282,13 @@ static void draw_uvs_texpaint(Scene *scene, Object *ob, Depsgraph *depsgraph) static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit, Depsgraph *depsgraph) { GPUBatch *faces, *edges, *verts, *facedots; - Object *eval_ob = DEG_get_evaluated_object(depsgraph, obedit); + Object *ob_eval = DEG_get_evaluated_object(depsgraph, obedit); const ToolSettings *ts = scene->toolsettings; float col1[4], col2[4], col3[4], transparent[4] = {0.0f, 0.0f, 0.0f, 0.0f}; if (sima->flag & SI_DRAWSHADOW) { bool is_cage_like_final_meshes = false; - Mesh *me = (Mesh *)eval_ob->data; + Mesh *me = (Mesh *)ob_eval->data; BMEditMesh *embm = me->edit_mesh; is_cage_like_final_meshes = embm && embm->mesh_eval_final && embm->mesh_eval_final->runtime.is_original; @@ -300,7 +300,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit, Depsgraph * } } - uvedit_get_batches(eval_ob, sima, scene, &faces, &edges, &verts, &facedots); + uvedit_get_batches(ob_eval, sima, scene, &faces, &edges, &verts, &facedots); bool interpedges; bool draw_stretch = (sima->flag & SI_DRAW_STRETCH) != 0; @@ -367,33 +367,33 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit, Depsgraph * break; } case SI_UVDT_BLACK: - case SI_UVDT_WHITE: { - GPU_line_width(1.0f); - GPU_batch_program_set_builtin(edges, GPU_SHADER_2D_UNIFORM_COLOR); - if (sima->dt_uv == SI_UVDT_WHITE) { - GPU_batch_uniform_4f(edges, "color", 1.0f, 1.0f, 1.0f, 1.0f); - } - else { - GPU_batch_uniform_4f(edges, "color", 0.0f, 0.0f, 0.0f, 1.0f); - } - GPU_batch_draw(edges); - break; - } + case SI_UVDT_WHITE: case SI_UVDT_OUTLINE: { /* We could modify the vbo's data filling * instead of modifying the provoking vert. */ glProvokingVertex(GL_FIRST_VERTEX_CONVENTION); - UI_GetThemeColor4fv(TH_WIRE_EDIT, col1); UI_GetThemeColor4fv(TH_EDGE_SELECT, col2); GPU_batch_program_set_builtin( edges, (interpedges) ? GPU_SHADER_2D_UV_EDGES_SMOOTH : GPU_SHADER_2D_UV_EDGES); - /* Black Outline. */ - GPU_line_width(3.0f); - GPU_batch_uniform_4f(edges, "edgeColor", 0.0f, 0.0f, 0.0f, 1.0f); - GPU_batch_uniform_4f(edges, "selectColor", 0.0f, 0.0f, 0.0f, 1.0f); - GPU_batch_draw(edges); + + if (sima->dt_uv == SI_UVDT_OUTLINE) { + /* Black Outline. */ + GPU_line_width(3.0f); + GPU_batch_uniform_4f(edges, "edgeColor", 0.0f, 0.0f, 0.0f, 1.0f); + GPU_batch_uniform_4f(edges, "selectColor", 0.0f, 0.0f, 0.0f, 1.0f); + GPU_batch_draw(edges); + + UI_GetThemeColor4fv(TH_WIRE_EDIT, col1); + } + else if (sima->dt_uv == SI_UVDT_WHITE) { + copy_v4_fl4(col1, 1.0f, 1.0f, 1.0f, 1.0f); + } + else { + copy_v4_fl4(col1, 0.0f, 0.0f, 0.0f, 1.0f); + } + /* Inner Line. Use depth test to insure selection is drawn on top. */ GPU_depth_test(true); GPU_line_width(1.0f); diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h index 3f544ad90d1..7bc6b048585 100644 --- a/source/blender/editors/uvedit/uvedit_intern.h +++ b/source/blender/editors/uvedit/uvedit_intern.h @@ -24,7 +24,6 @@ #ifndef __UVEDIT_INTERN_H__ #define __UVEDIT_INTERN_H__ -struct BMEditMesh; struct BMFace; struct BMLoop; struct Image; diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index dcf1d04ffb3..cd7e5f9ba09 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -138,7 +138,7 @@ static int UNUSED_FUNCTION(ED_operator_uvmap_mesh)(bContext *C) if (ob && ob->type == OB_MESH) { Mesh *me = ob->data; - if (CustomData_get_layer(&me->fdata, CD_MTFACE) != NULL) { + if (CustomData_get_layer(&me->ldata, CD_MLOOPUV) != NULL) { return 1; } } diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index a42a6eba3ff..2d8f40ea5af 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -524,7 +524,7 @@ static ParamHandle *construct_param_handle_subsurfed(Scene *scene, smd.levels = smd_real->levels; smd.subdivType = smd_real->subdivType; - initialDerived = CDDM_from_editbmesh(em, false, false); + initialDerived = CDDM_from_editbmesh(em, false); derivedMesh = subsurf_make_derived_from_derived( initialDerived, &smd, scene, NULL, SUBSURF_IN_EDIT_MODE); diff --git a/source/blender/freestyle/FRS_freestyle.h b/source/blender/freestyle/FRS_freestyle.h index bad279ed9d9..dc8a0c79072 100644 --- a/source/blender/freestyle/FRS_freestyle.h +++ b/source/blender/freestyle/FRS_freestyle.h @@ -29,7 +29,6 @@ struct FreestyleConfig; struct FreestyleLineStyle; struct Material; struct Render; -struct RenderLayer; struct FreestyleGlobals { struct Scene *scene; diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp index 984a2d01a68..98da8e8f6d3 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp @@ -865,7 +865,7 @@ Object *BlenderStrokeRenderer::NewMesh() const BLI_snprintf(name, MAX_ID_NAME, "0%08xME", mesh_id); ob->data = BKE_mesh_add(freestyle_bmain, name); - Collection *collection_master = BKE_collection_master(freestyle_scene); + Collection *collection_master = freestyle_scene->master_collection; BKE_collection_object_add(freestyle_bmain, collection_master, ob); DEG_graph_tag_relations_update(freestyle_depsgraph); diff --git a/source/blender/freestyle/intern/scene_graph/FrsMaterial.h b/source/blender/freestyle/intern/scene_graph/FrsMaterial.h index c5a87c3baaf..80cd783f164 100644 --- a/source/blender/freestyle/intern/scene_graph/FrsMaterial.h +++ b/source/blender/freestyle/intern/scene_graph/FrsMaterial.h @@ -36,14 +36,14 @@ class FrsMaterial { /*! Default constructor */ inline FrsMaterial(); - /*! Builds a Material from its line, diffuse, ambiant, specular, emissive + /*! Builds a Material from its line, diffuse, ambient, specular, emissive * colors, a shininess coefficient and line color priority. * \param iLine: * A 4 element float-array containing the line color. * \param iDiffuse: * A 4 element float-array containing the diffuse color. * \param iAmbiant: - * A 4 element float-array containing the ambiant color. + * A 4 element float-array containing the ambient color. * \param iSpecular: * A 4 element float-array containing the specular color. * \param iEmission: @@ -159,31 +159,31 @@ class FrsMaterial { return Specular[3]; } - /*! Returns the ambiant color as a 4 float array */ + /*! Returns the ambient color as a 4 float array */ inline const float *ambient() const { return Ambient; } - /*! Returns the red component of the ambiant color */ + /*! Returns the red component of the ambient color */ inline const float ambientR() const { return Ambient[0]; } - /*! Returns the green component of the ambiant color */ + /*! Returns the green component of the ambient color */ inline const float ambientG() const { return Ambient[1]; } - /*! Returns the blue component of the ambiant color */ + /*! Returns the blue component of the ambient color */ inline const float ambientB() const { return Ambient[2]; } - /*! Returns the alpha component of the ambiant color */ + /*! Returns the alpha component of the ambient color */ inline const float ambientA() const { return Ambient[3]; @@ -267,7 +267,7 @@ class FrsMaterial { */ inline void setSpecular(const float r, const float g, const float b, const float a); - /*! Sets the ambiant color. + /*! Sets the ambient color. * \param r: * Red component * \param g: diff --git a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h index d70794d9b78..f8dd25913c1 100644 --- a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h +++ b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h @@ -19,7 +19,7 @@ /** \file * \ingroup freestyle - * \brief A Set of indexed faces to represent a surfacic object + * \brief A Set of indexed faces to represent a surface object */ #include <memory.h> diff --git a/source/blender/freestyle/intern/scene_graph/NodeTransform.h b/source/blender/freestyle/intern/scene_graph/NodeTransform.h index ddae714f9d4..1118417657f 100644 --- a/source/blender/freestyle/intern/scene_graph/NodeTransform.h +++ b/source/blender/freestyle/intern/scene_graph/NodeTransform.h @@ -48,7 +48,7 @@ class NodeTransform : public NodeGroup { /*! multiplies the current matrix by the x, y, z translation matrix. */ void Translate(real x, real y, real z); - /*! multiplis the current matrix by a rotation matrix + /*! multiplies the current matrix by a rotation matrix * iAngle * The rotation angle * x, y, z @@ -56,13 +56,13 @@ class NodeTransform : public NodeGroup { */ void Rotate(real iAngle, real x, real y, real z); - /*! multiplys the current matrix by a scaling matrix. + /*! multiplies the current matrix by a scaling matrix. * x, y, z * The scaling coefficients with respect to the x,y,z axis */ void Scale(real x, real y, real z); - /*! Multiplys the current matrix by iMatrix */ + /*! Multiplies the current matrix by iMatrix */ void MultiplyMatrix(const Matrix44r &iMatrix); /*! Sets the current matrix to iMatrix */ diff --git a/source/blender/freestyle/intern/stroke/Curve.h b/source/blender/freestyle/intern/stroke/Curve.h index 7eadfa830ce..8a233eef4ab 100644 --- a/source/blender/freestyle/intern/stroke/Curve.h +++ b/source/blender/freestyle/intern/stroke/Curve.h @@ -56,7 +56,7 @@ using namespace Geometry; /*! Class to represent a point of a curve. * A CurvePoint can be any point of a 1D curve (it doesn't have to be a vertex of the curve). * Any Interface1D is built upon ViewEdges, themselves built upon FEdges. Therefore, a curve is - * basically a polyline made of a list SVertex. Thus, a CurvePoint is built by lineraly + * basically a polyline made of a list SVertex. Thus, a CurvePoint is built by linearly * interpolating two SVertex. CurvePoint can be used as virtual points while querying 0D * information along a curve at a given resolution. */ diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c index c0ecd3bf0eb..72385fd2f2c 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c @@ -76,9 +76,10 @@ void gpencil_modifier_type_init(GpencilModifierTypeInfo *types[]) #undef INIT_GP_TYPE } -/* verify if valid layer and pass index */ +/* verify if valid layer, material and pass index */ bool is_stroke_affected_by_modifier(Object *ob, char *mlayername, + char *mmaterialname, int mpassindex, int gpl_passindex, int minpoints, @@ -86,9 +87,11 @@ bool is_stroke_affected_by_modifier(Object *ob, bGPDstroke *gps, bool inv1, bool inv2, - bool inv3) + bool inv3, + bool inv4) { - MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1); + Material *ma = BKE_material_gpencil_get(ob, gps->mat_nr + 1); + MaterialGPencilStyle *gp_style = ma->gp_style; /* omit if filter by layer */ if (mlayername[0] != '\0') { @@ -103,6 +106,19 @@ bool is_stroke_affected_by_modifier(Object *ob, } } } + /* omit if filter by material */ + if (mmaterialname[0] != '\0') { + if (inv4 == false) { + if (!STREQ(mmaterialname, ma->id.name + 2)) { + return false; + } + } + else { + if (STREQ(mmaterialname, ma->id.name + 2)) { + return false; + } + } + } /* verify layer pass */ if (gpl_passindex > 0) { if (inv3 == false) { diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h index c3dbd341e10..7f00e072cda 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h @@ -34,6 +34,7 @@ struct bGPDstroke; bool is_stroke_affected_by_modifier(struct Object *ob, char *mlayername, + char *mmaterialname, int mpassindex, int gpl_passindex, int minpoints, @@ -41,7 +42,8 @@ bool is_stroke_affected_by_modifier(struct Object *ob, bGPDstroke *gps, bool inv1, bool inv2, - bool inv3); + bool inv3, + bool inv4); float get_modifier_point_weight(struct MDeformVert *dvert, bool inverse, int def_nr); diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c index 4297cbb545c..1f2f0554dd5 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c @@ -155,7 +155,11 @@ static bool isDisabled(GpencilModifierData *md, int UNUSED(userRenderParams)) { ArmatureGpencilModifierData *mmd = (ArmatureGpencilModifierData *)md; - return !mmd->object; + /* The object type check is only needed here in case we have a placeholder + * object assigned (because the library containing the armature is missing). + * + * In other cases it should be impossible to have a type mismatch. */ + return !mmd->object || mmd->object->type != OB_ARMATURE; } static void updateDepsgraph(GpencilModifierData *md, const ModifierUpdateDepsgraphContext *ctx) diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c index 0a391a6e63e..c311497ffbb 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c @@ -171,6 +171,7 @@ static void generate_geometry(GpencilModifierData *md, */ if (is_stroke_affected_by_modifier(ob, mmd->layername, + mmd->materialname, mmd->pass_index, mmd->layer_pass, 1, @@ -178,7 +179,8 @@ static void generate_geometry(GpencilModifierData *md, gps, mmd->flag & GP_ARRAY_INVERT_LAYER, mmd->flag & GP_ARRAY_INVERT_PASS, - mmd->flag & GP_ARRAY_INVERT_LAYERPASS)) { + mmd->flag & GP_ARRAY_INVERT_LAYERPASS, + mmd->flag & GP_ARRAY_INVERT_MATERIAL)) { valid_strokes[idx] = true; num_valid++; } diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c index 13329e4176d..cb429b874a2 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c @@ -51,6 +51,7 @@ static void initData(GpencilModifierData *md) gpmd->pass_index = 0; ARRAY_SET_ITEMS(gpmd->hsv, 0.5f, 1.0f, 1.0f); gpmd->layername[0] = '\0'; + gpmd->materialname[0] = '\0'; gpmd->flag |= GP_COLOR_CREATE_COLORS; gpmd->modify_color = GP_MODIFY_COLOR_BOTH; } @@ -74,6 +75,7 @@ static void deformStroke(GpencilModifierData *md, if (!is_stroke_affected_by_modifier(ob, mmd->layername, + mmd->materialname, mmd->pass_index, mmd->layer_pass, 1, @@ -81,7 +83,8 @@ static void deformStroke(GpencilModifierData *md, gps, mmd->flag & GP_COLOR_INVERT_LAYER, mmd->flag & GP_COLOR_INVERT_PASS, - mmd->flag & GP_COLOR_INVERT_LAYERPASS)) { + mmd->flag & GP_COLOR_INVERT_LAYERPASS, + mmd->flag & GP_COLOR_INVERT_MATERIAL)) { return; } @@ -116,7 +119,7 @@ static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) { for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { - Material *mat = give_current_material(ob, gps->mat_nr + 1); + Material *mat = BKE_material_gpencil_get(ob, gps->mat_nr + 1); if (mat == NULL) { continue; } diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c index a3dbcdf23de..810a2ba7e25 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c @@ -77,6 +77,7 @@ static void initData(GpencilModifierData *md) HookGpencilModifierData *gpmd = (HookGpencilModifierData *)md; gpmd->pass_index = 0; gpmd->layername[0] = '\0'; + gpmd->materialname[0] = '\0'; gpmd->vgname[0] = '\0'; gpmd->object = NULL; gpmd->force = 0.5f; @@ -206,6 +207,7 @@ static void deformStroke(GpencilModifierData *md, if (!is_stroke_affected_by_modifier(ob, mmd->layername, + mmd->materialname, mmd->pass_index, mmd->layer_pass, 1, @@ -213,7 +215,8 @@ static void deformStroke(GpencilModifierData *md, gps, mmd->flag & GP_HOOK_INVERT_LAYER, mmd->flag & GP_HOOK_INVERT_PASS, - mmd->flag & GP_HOOK_INVERT_LAYERPASS)) { + mmd->flag & GP_HOOK_INVERT_LAYERPASS, + mmd->flag & GP_HOOK_INVERT_MATERIAL)) { return; } diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c b/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c index aa5015bac35..6b74f96ce31 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c @@ -55,6 +55,7 @@ static void initData(GpencilModifierData *md) LatticeGpencilModifierData *gpmd = (LatticeGpencilModifierData *)md; gpmd->pass_index = 0; gpmd->layername[0] = '\0'; + gpmd->materialname[0] = '\0'; gpmd->vgname[0] = '\0'; gpmd->object = NULL; gpmd->cache_data = NULL; @@ -78,6 +79,7 @@ static void deformStroke(GpencilModifierData *md, if (!is_stroke_affected_by_modifier(ob, mmd->layername, + mmd->materialname, mmd->pass_index, mmd->layer_pass, 1, @@ -85,7 +87,8 @@ static void deformStroke(GpencilModifierData *md, gps, mmd->flag & GP_LATTICE_INVERT_LAYER, mmd->flag & GP_LATTICE_INVERT_PASS, - mmd->flag & GP_LATTICE_INVERT_LAYERPASS)) { + mmd->flag & GP_LATTICE_INVERT_LAYERPASS, + mmd->flag & GP_LATTICE_INVERT_MATERIAL)) { return; } @@ -166,7 +169,12 @@ static bool isDisabled(GpencilModifierData *md, int UNUSED(userRenderParams)) { LatticeGpencilModifierData *mmd = (LatticeGpencilModifierData *)md; - return !mmd->object; + /* The object type check is only needed here in case we have a placeholder + * object assigned (because the library containing the lattice is missing). + * + * In other cases it should be impossible to have a type mismatch. + */ + return !mmd->object || mmd->object->type != OB_LATTICE; } static void updateDepsgraph(GpencilModifierData *md, const ModifierUpdateDepsgraphContext *ctx) diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c index 058f60a69ac..112dfc2e9dc 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c @@ -57,6 +57,7 @@ static void initData(GpencilModifierData *md) MirrorGpencilModifierData *gpmd = (MirrorGpencilModifierData *)md; gpmd->pass_index = 0; gpmd->layername[0] = '\0'; + gpmd->materialname[0] = '\0'; gpmd->object = NULL; gpmd->flag |= GP_MIRROR_AXIS_X; } @@ -134,6 +135,7 @@ static void generateStrokes(GpencilModifierData *md, for (i = 0, gps = gpf->strokes.first; i < tot_strokes; i++, gps = gps->next) { if (is_stroke_affected_by_modifier(ob, mmd->layername, + mmd->materialname, mmd->pass_index, mmd->layer_pass, 1, @@ -141,7 +143,8 @@ static void generateStrokes(GpencilModifierData *md, gps, mmd->flag & GP_MIRROR_INVERT_LAYER, mmd->flag & GP_MIRROR_INVERT_PASS, - mmd->flag & GP_MIRROR_INVERT_LAYERPASS)) { + mmd->flag & GP_MIRROR_INVERT_LAYERPASS, + mmd->flag & GP_MIRROR_INVERT_MATERIAL)) { gps_new = BKE_gpencil_stroke_duplicate(gps); update_position(ob, mmd, gps_new, xi); BLI_addtail(&gpf->strokes, gps_new); diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c index 2c4d99adeee..b286b55829e 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c @@ -55,6 +55,7 @@ static void initData(GpencilModifierData *md) gpmd->flag |= GP_NOISE_USE_RANDOM; gpmd->factor = 0.5f; gpmd->layername[0] = '\0'; + gpmd->materialname[0] = '\0'; gpmd->vgname[0] = '\0'; gpmd->step = 1; gpmd->seed = 0; @@ -92,6 +93,7 @@ static void deformStroke(GpencilModifierData *md, if (!is_stroke_affected_by_modifier(ob, mmd->layername, + mmd->materialname, mmd->pass_index, mmd->layer_pass, 1, @@ -99,7 +101,8 @@ static void deformStroke(GpencilModifierData *md, gps, mmd->flag & GP_NOISE_INVERT_LAYER, mmd->flag & GP_NOISE_INVERT_PASS, - mmd->flag & GP_NOISE_INVERT_LAYERPASS)) { + mmd->flag & GP_NOISE_INVERT_LAYERPASS, + mmd->flag & GP_NOISE_INVERT_MATERIAL)) { return; } diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c index 399fc407455..08f67eedc86 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c @@ -48,6 +48,7 @@ static void initData(GpencilModifierData *md) OffsetGpencilModifierData *gpmd = (OffsetGpencilModifierData *)md; gpmd->pass_index = 0; gpmd->layername[0] = '\0'; + gpmd->materialname[0] = '\0'; gpmd->vgname[0] = '\0'; ARRAY_SET_ITEMS(gpmd->loc, 0.0f, 0.0f, 0.0f); ARRAY_SET_ITEMS(gpmd->rot, 0.0f, 0.0f, 0.0f); @@ -75,6 +76,7 @@ static void deformStroke(GpencilModifierData *md, if (!is_stroke_affected_by_modifier(ob, mmd->layername, + mmd->materialname, mmd->pass_index, mmd->layer_pass, 1, @@ -82,7 +84,8 @@ static void deformStroke(GpencilModifierData *md, gps, mmd->flag & GP_OFFSET_INVERT_LAYER, mmd->flag & GP_OFFSET_INVERT_PASS, - mmd->flag & GP_OFFSET_INVERT_LAYERPASS)) { + mmd->flag & GP_OFFSET_INVERT_LAYERPASS, + mmd->flag & GP_OFFSET_INVERT_MATERIAL)) { return; } diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c index 92c25f955fb..22610771045 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c @@ -52,6 +52,7 @@ static void initData(GpencilModifierData *md) gpmd->pass_index = 0; gpmd->factor = 1.0f; gpmd->layername[0] = '\0'; + gpmd->materialname[0] = '\0'; gpmd->vgname[0] = '\0'; gpmd->flag |= GP_OPACITY_CREATE_COLORS; gpmd->modify_color = GP_MODIFY_COLOR_BOTH; @@ -75,6 +76,7 @@ static void deformStroke(GpencilModifierData *md, if (!is_stroke_affected_by_modifier(ob, mmd->layername, + mmd->materialname, mmd->pass_index, mmd->layer_pass, 1, @@ -82,7 +84,8 @@ static void deformStroke(GpencilModifierData *md, gps, mmd->flag & GP_OPACITY_INVERT_LAYER, mmd->flag & GP_OPACITY_INVERT_PASS, - mmd->flag & GP_OPACITY_INVERT_LAYERPASS)) { + mmd->flag & GP_OPACITY_INVERT_LAYERPASS, + mmd->flag & GP_OPACITY_INVERT_MATERIAL)) { return; } @@ -109,22 +112,7 @@ static void deformStroke(GpencilModifierData *md, if (mmd->factor > 1.0f) { for (int i = 0; i < gps->totpoints; i++) { bGPDspoint *pt = &gps->points[i]; - MDeformVert *dvert = gps->dvert != NULL ? &gps->dvert[i] : NULL; - - /* verify vertex group */ - float weight = get_modifier_point_weight( - dvert, (mmd->flag & GP_OPACITY_INVERT_VGROUP) != 0, def_nr); - if (weight < 0.0f) { - continue; - } - if (def_nr < 0) { - pt->strength += mmd->factor - 1.0f; - } - else { - CLAMP(weight, 0.0f, 1.0f); - weight = 1.0f - weight; - pt->strength += (mmd->factor * weight) - 1.0f; - } + pt->strength += mmd->factor - 1.0f; CLAMP(pt->strength, 0.0f, 1.0f); } } @@ -145,14 +133,12 @@ static void deformStroke(GpencilModifierData *md, pt->strength += mmd->factor - 1.0f; } else { - CLAMP(weight, 0.0f, 1.0f); - weight = 1.0f - weight; /* High factor values, change weight too. */ if ((mmd->factor > 1.0f) && (weight < 1.0f)) { weight += mmd->factor - 1.0f; CLAMP(weight, 0.0f, 1.0f); } - pt->strength += (mmd->factor * weight) - 1.0f; + pt->strength += (mmd->factor - 1) * weight; } CLAMP(pt->strength, 0.0f, 1.0f); } @@ -169,7 +155,7 @@ static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) { for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { - Material *mat = give_current_material(ob, gps->mat_nr + 1); + Material *mat = BKE_material_gpencil_get(ob, gps->mat_nr + 1); if (mat == NULL) { continue; } @@ -184,8 +170,10 @@ static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData deformStroke(md, depsgraph, ob, gpl, gpf, gps); - gpencil_apply_modifier_material( - bmain, ob, mat, gh_color, gps, (bool)(mmd->flag & GP_OPACITY_CREATE_COLORS)); + if (mmd->opacity_mode == GP_OPACITY_MODE_MATERIAL) { + gpencil_apply_modifier_material( + bmain, ob, mat, gh_color, gps, (bool)(mmd->flag & GP_OPACITY_CREATE_COLORS)); + } } } } diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c index 2168e7f07ec..25a56c4385c 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c @@ -48,6 +48,7 @@ static void initData(GpencilModifierData *md) gpmd->length = 0.1f; gpmd->distance = 0.1f; gpmd->layername[0] = '\0'; + gpmd->materialname[0] = '\0'; } static void copyData(const GpencilModifierData *md, GpencilModifierData *target) @@ -66,6 +67,7 @@ static void deformStroke(GpencilModifierData *md, if (!is_stroke_affected_by_modifier(ob, mmd->layername, + mmd->materialname, mmd->pass_index, mmd->layer_pass, mmd->mode == GP_SIMPLIFY_SAMPLE ? 3 : 4, @@ -73,7 +75,8 @@ static void deformStroke(GpencilModifierData *md, gps, mmd->flag & GP_SIMPLIFY_INVERT_LAYER, mmd->flag & GP_SIMPLIFY_INVERT_PASS, - mmd->flag & GP_SIMPLIFY_INVERT_LAYERPASS)) { + mmd->flag & GP_SIMPLIFY_INVERT_LAYERPASS, + mmd->flag & GP_SIMPLIFY_INVERT_MATERIAL)) { return; } diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c index 7c639bd8af0..5ec7fe4ff18 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c @@ -46,6 +46,7 @@ static void initData(GpencilModifierData *md) gpmd->flag |= GP_SMOOTH_MOD_LOCATION; gpmd->factor = 0.5f; gpmd->layername[0] = '\0'; + gpmd->materialname[0] = '\0'; gpmd->vgname[0] = '\0'; gpmd->step = 1; } @@ -68,6 +69,7 @@ static void deformStroke(GpencilModifierData *md, if (!is_stroke_affected_by_modifier(ob, mmd->layername, + mmd->materialname, mmd->pass_index, mmd->layer_pass, 3, @@ -75,7 +77,8 @@ static void deformStroke(GpencilModifierData *md, gps, mmd->flag & GP_SMOOTH_INVERT_LAYER, mmd->flag & GP_SMOOTH_INVERT_PASS, - mmd->flag & GP_SMOOTH_INVERT_LAYERPASS)) { + mmd->flag & GP_SMOOTH_INVERT_LAYERPASS, + mmd->flag & GP_SMOOTH_INVERT_MATERIAL)) { return; } diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c index c8962cd58c9..741555722b5 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c @@ -47,6 +47,7 @@ static void initData(GpencilModifierData *md) gpmd->pass_index = 0; gpmd->level = 1; gpmd->layername[0] = '\0'; + gpmd->materialname[0] = '\0'; } static void copyData(const GpencilModifierData *md, GpencilModifierData *target) @@ -66,6 +67,7 @@ static void deformStroke(GpencilModifierData *md, if (!is_stroke_affected_by_modifier(ob, mmd->layername, + mmd->materialname, mmd->pass_index, mmd->layer_pass, 3, @@ -73,7 +75,8 @@ static void deformStroke(GpencilModifierData *md, gps, mmd->flag & GP_SUBDIV_INVERT_LAYER, mmd->flag & GP_SUBDIV_INVERT_PASS, - mmd->flag & GP_SUBDIV_INVERT_LAYERPASS)) { + mmd->flag & GP_SUBDIV_INVERT_LAYERPASS, + mmd->flag & GP_SUBDIV_INVERT_MATERIAL)) { return; } diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c index 53abfdf177c..cc38df141d1 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c @@ -47,6 +47,7 @@ static void initData(GpencilModifierData *md) gpmd->pass_index = 0; gpmd->thickness = 2; gpmd->layername[0] = '\0'; + gpmd->materialname[0] = '\0'; gpmd->vgname[0] = '\0'; gpmd->curve_thickness = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); if (gpmd->curve_thickness) { @@ -91,6 +92,7 @@ static void deformStroke(GpencilModifierData *md, if (!is_stroke_affected_by_modifier(ob, mmd->layername, + mmd->materialname, mmd->pass_index, mmd->layer_pass, 1, @@ -98,20 +100,46 @@ static void deformStroke(GpencilModifierData *md, gps, mmd->flag & GP_THICK_INVERT_LAYER, mmd->flag & GP_THICK_INVERT_PASS, - mmd->flag & GP_THICK_INVERT_LAYERPASS)) { + mmd->flag & GP_THICK_INVERT_LAYERPASS, + mmd->flag & GP_THICK_INVERT_MATERIAL)) { return; } - /* if normalize, set stroke thickness */ + /* Check to see if we normalize the whole stroke or only certain points along it. */ + bool gps_has_affected_points = false; + bool gps_has_unaffected_points = false; + if (mmd->flag & GP_THICK_NORMALIZE) { + for (int i = 0; i < gps->totpoints; i++) { + MDeformVert *dvert = gps->dvert != NULL ? &gps->dvert[i] : NULL; + const float weight = get_modifier_point_weight( + dvert, (mmd->flag & GP_THICK_INVERT_VGROUP) != 0, def_nr); + if (weight < 0.0f) { + gps_has_unaffected_points = true; + } + else { + gps_has_affected_points = true; + } + + /* If both checks are true, we have what we need so we can stop looking. */ + if (gps_has_affected_points && gps_has_unaffected_points) { + break; + } + } + } + + /* If we are normalizing and all points of the stroke are affected, it's safe to reset thickness + */ + if (mmd->flag & GP_THICK_NORMALIZE && gps_has_affected_points && !gps_has_unaffected_points) { gps->thickness = mmd->thickness; } + /* Without this check, modifier alters the thickness of strokes which have no points in scope */ for (int i = 0; i < gps->totpoints; i++) { bGPDspoint *pt = &gps->points[i]; MDeformVert *dvert = gps->dvert != NULL ? &gps->dvert[i] : NULL; float curvef = 1.0f; - /* verify vertex group */ + /* Verify point is part of vertex group. */ const float weight = get_modifier_point_weight( dvert, (mmd->flag & GP_THICK_INVERT_VGROUP) != 0, def_nr); if (weight < 0.0f) { @@ -127,11 +155,21 @@ static void deformStroke(GpencilModifierData *md, float new_pressure = weight * curvef; if (mmd->flag & GP_THICK_NORMALIZE) { - pt->pressure = 1.0f * new_pressure; + if (gps_has_unaffected_points) { + /* Clamp value for very weird situations when stroke thickness can be zero. */ + CLAMP_MIN(gps->thickness, 1); + /* Calculate pressure value to match the width of strokes with reset thickness and 1.0 + * pressure. */ + pt->pressure = (float)mmd->thickness / (float)gps->thickness; + } + else { + /* Reset point pressure values so only stroke thickness counts. */ + pt->pressure = 1.0f; + } } else { if ((mmd->flag & GP_THICK_CUSTOM_CURVE) && (mmd->curve_thickness)) { - /* normalize value to evaluate curve */ + /* Normalize value to evaluate curve. */ float value = (float)i / (gps->totpoints - 1); curvef = BKE_curvemapping_evaluateF(mmd->curve_thickness, 0, value); } diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c index d70d975c3a7..f6ddcf89bcf 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c @@ -50,6 +50,7 @@ static void initData(GpencilModifierData *md) gpmd->pass_index = 0; gpmd->factor = 0.5f; gpmd->layername[0] = '\0'; + gpmd->materialname[0] = '\0'; ARRAY_SET_ITEMS(gpmd->rgb, 1.0f, 1.0f, 1.0f); gpmd->flag |= GP_TINT_CREATE_COLORS; gpmd->modify_color = GP_MODIFY_COLOR_BOTH; @@ -72,6 +73,7 @@ static void deformStroke(GpencilModifierData *md, if (!is_stroke_affected_by_modifier(ob, mmd->layername, + mmd->materialname, mmd->pass_index, mmd->layer_pass, 1, @@ -79,7 +81,8 @@ static void deformStroke(GpencilModifierData *md, gps, mmd->flag & GP_TINT_INVERT_LAYER, mmd->flag & GP_TINT_INVERT_PASS, - mmd->flag & GP_TINT_INVERT_LAYERPASS)) { + mmd->flag & GP_TINT_INVERT_LAYERPASS, + mmd->flag & GP_TINT_INVERT_MATERIAL)) { return; } @@ -122,7 +125,7 @@ static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) { for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { - Material *mat = give_current_material(ob, gps->mat_nr + 1); + Material *mat = BKE_material_gpencil_get(ob, gps->mat_nr + 1); if (mat == NULL) { continue; } diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index fb7d3c1ace8..f11dcc9bcf0 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -116,6 +116,7 @@ set(SRC intern/gpu_batch_private.h intern/gpu_codegen.h intern/gpu_context_private.h + intern/gpu_material_library.h intern/gpu_matrix_private.h intern/gpu_primitive_private.h intern/gpu_private.h @@ -231,7 +232,94 @@ data_to_c_simple(shaders/gpu_shader_keyframe_diamond_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_keyframe_diamond_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_geometry.glsl SRC) -data_to_c_simple(shaders/gpu_shader_material.glsl SRC) + +data_to_c_simple(shaders/material/gpu_shader_material_add_shader.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_ambient_occlusion.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_anisotropic.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_attribute.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_background.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_bevel.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_blackbody.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_bright_contrast.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_bump.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_camera.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_cell_noise.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_clamp.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_color_ramp.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_color_util.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_combine_hsv.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_combine_rgb.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_combine_xyz.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_diffuse.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_displacement.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_eevee_specular.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_emission.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_fractal_noise.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_fresnel.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_gamma.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_geometry.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_glass.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_glossy.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_hair_info.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_hash.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_holdout.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_hue_sat_val.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_invert.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_layer_weight.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_light_falloff.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_light_path.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_mapping.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_map_range.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_math.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_math_util.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_mix_rgb.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_mix_shader.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_noise.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_normal.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_normal_map.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_object_info.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_output_material.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_output_world.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_particle_info.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_principled.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_refraction.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_rgb_curves.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_rgb_to_bw.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_separate_hsv.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_separate_rgb.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_separate_xyz.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_set.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_shader_to_rgba.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_squeeze.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_subsurface_scattering.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_tangent.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_tex_brick.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_tex_checker.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_tex_environment.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_tex_gradient.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_tex_image.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_tex_magic.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_tex_musgrave.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_tex_noise.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_tex_sky.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_texture_coordinates.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_tex_voronoi.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_tex_wave.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_tex_white_noise.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_toon.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_translucent.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_transparent.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_uv_map.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_vector_curves.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_vector_displacement.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_vector_math.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_velvet.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_volume_absorption.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_volume_info.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_volume_principled.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_volume_scatter.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_wireframe.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_world_normals.glsl SRC) data_to_c_simple(shaders/gpu_shader_gpencil_stroke_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_gpencil_stroke_frag.glsl SRC) diff --git a/source/blender/gpu/GPU_batch_presets.h b/source/blender/gpu/GPU_batch_presets.h index 4b95783e6fa..55d2e461b30 100644 --- a/source/blender/gpu/GPU_batch_presets.h +++ b/source/blender/gpu/GPU_batch_presets.h @@ -27,9 +27,6 @@ #ifndef __GPU_BATCH_PRESETS_H__ #define __GPU_BATCH_PRESETS_H__ -struct GPUVertFormat; -struct rctf; - #include "BLI_compiler_attrs.h" #include "BLI_sys_types.h" diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h index 507baa9531e..7814c723fec 100644 --- a/source/blender/gpu/GPU_draw.h +++ b/source/blender/gpu/GPU_draw.h @@ -28,17 +28,11 @@ extern "C" { #endif -struct DupliObject; struct ImBuf; struct Image; struct ImageUser; struct Main; -struct Object; -struct RegionView3D; -struct Scene; struct SmokeModifierData; -struct View3D; -struct ViewLayer; #include "DNA_object_enums.h" diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index dd5292d9c58..4dc0019978a 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -45,10 +45,7 @@ struct ImageUser; struct ListBase; struct Main; struct Material; -struct Object; -struct PreviewImage; struct Scene; -struct World; struct bNode; struct bNodeTree; @@ -92,7 +89,7 @@ typedef enum eGPUBuiltin { GPU_INVERSE_OBJECT_MATRIX = (1 << 3), GPU_VIEW_POSITION = (1 << 4), GPU_VIEW_NORMAL = (1 << 5), - GPU_OBCOLOR = (1 << 6), + GPU_OBJECT_COLOR = (1 << 6), GPU_AUTO_BUMPSCALE = (1 << 7), GPU_CAMERA_TEXCO_FACTORS = (1 << 8), GPU_PARTICLE_SCALAR_PROPS = (1 << 9), diff --git a/source/blender/gpu/GPU_shader_interface.h b/source/blender/gpu/GPU_shader_interface.h index d3a9a18b392..ec97e1b085e 100644 --- a/source/blender/gpu/GPU_shader_interface.h +++ b/source/blender/gpu/GPU_shader_interface.h @@ -48,9 +48,10 @@ typedef enum { GPU_UNIFORM_ORCO, /* vec3 OrcoTexCoFactors[] */ GPU_UNIFORM_CLIPPLANES, /* vec4 WorldClipPlanes[] */ - GPU_UNIFORM_COLOR, /* vec4 color */ - GPU_UNIFORM_CALLID, /* int callId */ - GPU_UNIFORM_OBJECT_INFO, /* vec3 objectInfo */ + GPU_UNIFORM_COLOR, /* vec4 color */ + GPU_UNIFORM_CALLID, /* int callId */ + GPU_UNIFORM_OBJECT_INFO, /* vec3 objectInfo */ + GPU_UNIFORM_OBJECT_COLOR, /* vec4 objectColor */ GPU_UNIFORM_CUSTOM, /* custom uniform, not one of the above built-ins */ diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h index 2b61d99e852..a8e8ca72023 100644 --- a/source/blender/gpu/GPU_texture.h +++ b/source/blender/gpu/GPU_texture.h @@ -36,7 +36,6 @@ struct ImageUser; struct MovieClip; struct MovieClipUser; struct PreviewImage; -struct rcti; struct GPUFrameBuffer; typedef struct GPUTexture GPUTexture; diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index 0e15fdd000b..d655a43561e 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -51,15 +51,11 @@ #include "BLI_sys_types.h" /* for intptr_t support */ #include "gpu_codegen.h" +#include "gpu_material_library.h" #include <string.h> #include <stdarg.h> -extern char datatoc_gpu_shader_material_glsl[]; -extern char datatoc_gpu_shader_geometry_glsl[]; - -static char *glsl_material_library = NULL; - /* -------------------- GPUPass Cache ------------------ */ /** * Internal shader cache: This prevent the shader recompilation / stall when @@ -147,6 +143,7 @@ typedef struct GPUFunction { eGPUType paramtype[MAX_PARAMETER]; GPUFunctionQual paramqual[MAX_PARAMETER]; int totparam; + GPUMaterialLibrary *library; } GPUFunction; /* Indices match the eGPUType enum */ @@ -230,15 +227,17 @@ static char *gpu_str_skip_token(char *str, char *token, int max) return str; } -static void gpu_parse_functions_string(GHash *hash, char *code) +static void gpu_parse_material_library(GHash *hash, GPUMaterialLibrary *library) { GPUFunction *function; eGPUType type; GPUFunctionQual qual; int i; + char *code = library->code; while ((code = strstr(code, "void "))) { function = MEM_callocN(sizeof(GPUFunction), "GPUFunction"); + function->library = library; code = gpu_str_skip_token(code, NULL, 0); code = gpu_str_skip_token(code, function->name, MAX_FUNCTION_NAME); @@ -367,11 +366,6 @@ static char *gpu_generate_function_prototyps(GHash *hash) static GPUFunction *gpu_lookup_function(const char *name) { - if (!FUNCTION_HASH) { - FUNCTION_HASH = BLI_ghash_str_new("GPU_lookup_function gh"); - gpu_parse_functions_string(FUNCTION_HASH, glsl_material_library); - } - return BLI_ghash_lookup(FUNCTION_HASH, (const void *)name); } @@ -395,11 +389,6 @@ void gpu_codegen_exit(void) GPU_shader_free_builtin_shaders(); - if (glsl_material_library) { - MEM_freeN(glsl_material_library); - glsl_material_library = NULL; - } - #if 0 if (FUNCTION_PROTOTYPES) { MEM_freeN(FUNCTION_PROTOTYPES); @@ -425,7 +414,7 @@ static void codegen_convert_datatype(DynStr *ds, int from, int to, const char *t } else if (to == GPU_FLOAT) { if (from == GPU_VEC4) { - BLI_dynstr_appendf(ds, "convert_rgba_to_float(%s)", name); + BLI_dynstr_appendf(ds, "dot(%s.rgb, vec3(0.2126, 0.7152, 0.0722))", name); } else if (from == GPU_VEC3) { BLI_dynstr_appendf(ds, "(%s.r + %s.g + %s.b) / 3.0", name, name, name); @@ -542,8 +531,8 @@ const char *GPU_builtin_name(eGPUBuiltin builtin) else if (builtin == GPU_VIEW_NORMAL) { return "varnormal"; } - else if (builtin == GPU_OBCOLOR) { - return "unfobcolor"; + else if (builtin == GPU_OBJECT_COLOR) { + return "unfobjectcolor"; } else if (builtin == GPU_AUTO_BUMPSCALE) { return "unfobautobumpscale"; @@ -1381,20 +1370,15 @@ static char *code_generate_geometry(ListBase *nodes, const char *geom_code, cons void GPU_code_generate_glsl_lib(void) { - DynStr *ds; - - /* only initialize the library once */ - if (glsl_material_library) { + /* Only parse GLSL shader files once. */ + if (FUNCTION_HASH) { return; } - ds = BLI_dynstr_new(); - - BLI_dynstr_append(ds, datatoc_gpu_shader_material_glsl); - - glsl_material_library = BLI_dynstr_get_cstring(ds); - - BLI_dynstr_free(ds); + FUNCTION_HASH = BLI_ghash_str_new("GPU_lookup_function gh"); + for (int i = 0; gpu_material_libraries[i]; i++) { + gpu_parse_material_library(FUNCTION_HASH, gpu_material_libraries[i]); + } } /* GPU pass binding/unbinding */ @@ -1796,6 +1780,22 @@ GPUNodeLink *GPU_builtin(eGPUBuiltin builtin) return link; } +static void gpu_material_use_library_with_dependencies(GSet *used_libraries, + GPUMaterialLibrary *library) +{ + if (BLI_gset_add(used_libraries, library->code)) { + for (int i = 0; library->dependencies[i]; i++) { + gpu_material_use_library_with_dependencies(used_libraries, library->dependencies[i]); + } + } +} + +static void gpu_material_use_library(GPUMaterial *material, GPUMaterialLibrary *library) +{ + GSet *used_libraries = gpu_material_used_libraries(material); + gpu_material_use_library_with_dependencies(used_libraries, library); +} + bool GPU_link(GPUMaterial *mat, const char *name, ...) { GPUNode *node; @@ -1810,6 +1810,8 @@ bool GPU_link(GPUMaterial *mat, const char *name, ...) return false; } + gpu_material_use_library(mat, function->library); + node = GPU_node_begin(name); va_start(params, name); @@ -1849,6 +1851,8 @@ bool GPU_stack_link(GPUMaterial *material, return false; } + gpu_material_use_library(material, function->library); + node = GPU_node_begin(name); totin = 0; totout = 0; @@ -1962,6 +1966,34 @@ static bool gpu_pass_is_valid(GPUPass *pass) return (pass->compiled == false || pass->shader != NULL); } +static char *code_generate_material_library(GPUMaterial *material, const char *frag_lib) +{ + DynStr *ds = BLI_dynstr_new(); + + if (frag_lib) { + BLI_dynstr_append(ds, frag_lib); + } + + GSet *used_libraries = gpu_material_used_libraries(material); + + /* Always include those because they may be needed by the execution function. */ + gpu_material_use_library_with_dependencies(used_libraries, + &gpu_shader_material_world_normals_library); + + /* Add library code in order, for dependencies. */ + for (int i = 0; gpu_material_libraries[i]; i++) { + GPUMaterialLibrary *library = gpu_material_libraries[i]; + if (BLI_gset_haskey(used_libraries, library->code)) { + BLI_dynstr_append(ds, library->code); + } + } + + char *result = BLI_dynstr_get_cstring(ds); + BLI_dynstr_free(ds); + + return result; +} + GPUPass *GPU_generate_pass(GPUMaterial *material, GPUNodeLink *frag_outlink, struct GPUVertAttrLayers *attrs, @@ -2000,7 +2032,7 @@ GPUPass *GPU_generate_pass(GPUMaterial *material, /* Either the shader is not compiled or there is a hash collision... * continue generating the shader strings. */ - char *tmp = BLI_strdupcat(frag_lib, glsl_material_library); + char *tmp = code_generate_material_library(material, frag_lib); geometrycode = code_generate_geometry(nodes, geom_code, defines); vertexcode = code_generate_vertex(nodes, vert_code, (geometrycode != NULL)); diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h index ae34e21b9cd..4e09f16ebf8 100644 --- a/source/blender/gpu/intern/gpu_codegen.h +++ b/source/blender/gpu/intern/gpu_codegen.h @@ -33,8 +33,8 @@ struct GPUNode; struct GPUOutput; struct GPUShader; struct GPUVertAttrLayers; +struct GSet; struct ListBase; -struct PreviewImage; /* Pass Generation * - Takes a list of nodes and a desired output, and makes a pass. This @@ -208,4 +208,6 @@ struct GPUTexture **gpu_material_ramp_texture_row_set(GPUMaterial *mat, float *pixels, float *row); +struct GSet *gpu_material_used_libraries(struct GPUMaterial *material); + #endif diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index be3655648f5..859b1e4a10d 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -348,7 +348,7 @@ static void gpu_texture_update_scaled( } /* Scale pixels. */ - ImBuf *ibuf = IMB_allocFromBuffer((uint *)rect, rect_float, w, h); + ImBuf *ibuf = IMB_allocFromBuffer((uint *)rect, rect_float, w, h, 4); IMB_scaleImBuf(ibuf, sub_w, sub_h); if (ibuf->rect_float) { @@ -648,13 +648,13 @@ void GPU_create_gl_tex(uint *bind, recth = smaller_power_of_2_limit(recth); if (frect) { - ibuf = IMB_allocFromBuffer(NULL, frect, tpx, tpy); + ibuf = IMB_allocFromBuffer(NULL, frect, tpx, tpy, 4); IMB_scaleImBuf(ibuf, rectw, recth); frect = ibuf->rect_float; } else { - ibuf = IMB_allocFromBuffer(rect, NULL, tpx, tpy); + ibuf = IMB_allocFromBuffer(rect, NULL, tpx, tpy, 4); IMB_scaleImBuf(ibuf, rectw, recth); rect = ibuf->rect; diff --git a/source/blender/gpu/intern/gpu_element.c b/source/blender/gpu/intern/gpu_element.c index 6c9331b4903..3f3f246d6d9 100644 --- a/source/blender/gpu/intern/gpu_element.c +++ b/source/blender/gpu/intern/gpu_element.c @@ -267,9 +267,9 @@ static uint index_range(const uint values[], uint value_len, uint *min_out, uint *max_out = 0; return 0; } - uint min_value = values[0]; - uint max_value = values[0]; - for (uint i = 1; i < value_len; ++i) { + uint min_value = RESTART_INDEX; + uint max_value = 0; + for (uint i = 0; i < value_len; ++i) { const uint value = values[i]; if (value == RESTART_INDEX) { continue; @@ -281,9 +281,16 @@ static uint index_range(const uint values[], uint value_len, uint *min_out, uint max_value = value; } } - *min_out = min_value; - *max_out = max_value; - return max_value - min_value; + if (min_value == RESTART_INDEX) { + *min_out = 0; + *max_out = 0; + return 0; + } + else { + *min_out = min_value; + *max_out = max_value; + return max_value - min_value; + } } static void squeeze_indices_short(GPUIndexBufBuilder *builder, diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index 99dbff05453..5839b34cd19 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -309,6 +309,7 @@ void gpu_extensions_init(void) } else if ((strstr(renderer, "Mesa DRI R")) || (strstr(renderer, "Radeon") && strstr(vendor, "X.Org")) || + (strstr(renderer, "AMD") && strstr(vendor, "X.Org")) || (strstr(renderer, "Gallium ") && strstr(renderer, " on ATI ")) || (strstr(renderer, "Gallium ") && strstr(renderer, " on AMD "))) { GG.device = GPU_DEVICE_ATI; diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 20b91c0c95d..05d991105c0 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -37,6 +37,7 @@ #include "BLI_utildefines.h" #include "BLI_string.h" #include "BLI_string_utils.h" +#include "BLI_ghash.h" #include "BKE_main.h" #include "BKE_node.h" @@ -102,6 +103,8 @@ struct GPUMaterial { GPUTexture *coba_tex; /* 1D Texture array containing all color bands. */ GPUColorBandBuilder *coba_builder; + GSet *used_libraries; + #ifndef NDEBUG char name[64]; #endif @@ -183,6 +186,8 @@ static void gpu_material_free_single(GPUMaterial *material) if (material->coba_tex != NULL) { GPU_texture_free(material->coba_tex); } + + BLI_gset_free(material->used_libraries, NULL); } void GPU_material_free(ListBase *gpumaterial) @@ -582,6 +587,11 @@ void gpu_material_add_node(GPUMaterial *material, GPUNode *node) BLI_addtail(&material->nodes, node); } +GSet *gpu_material_used_libraries(GPUMaterial *material) +{ + return material->used_libraries; +} + /* Return true if the material compilation has not yet begin or begin. */ eGPUMaterialStatus GPU_material_status(GPUMaterial *mat) { @@ -659,6 +669,9 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene, UNUSED_VARS(name); #endif + mat->used_libraries = BLI_gset_new( + BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "GPUMaterial.used_libraries"); + /* localize tree to create links for reroute and mute */ bNodeTree *localtree = ntreeLocalize(ntree); ntreeGPUMaterialNodes(localtree, mat, &has_surface_output, &has_volume_output); diff --git a/source/blender/gpu/intern/gpu_material_library.h b/source/blender/gpu/intern/gpu_material_library.h new file mode 100644 index 00000000000..99a71094753 --- /dev/null +++ b/source/blender/gpu/intern/gpu_material_library.h @@ -0,0 +1,657 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup gpu + * + * List of all gpu_shader_material_*.glsl files used by GLSL materials. These + * will be parsed to make all functions in them available to use for GPU_link(). + * + * If a file uses functions from another file, it must be added to the list of + * dependencies, and be placed after that file in the list. */ + +#ifndef __GPU_MATERIAL_LIBRARY_H__ +#define __GPU_MATERIAL_LIBRARY_H__ + +typedef struct GPUMaterialLibrary { + char *code; + struct GPUMaterialLibrary *dependencies[8]; +} GPUMaterialLibrary; + +extern char datatoc_gpu_shader_material_add_shader_glsl[]; +extern char datatoc_gpu_shader_material_ambient_occlusion_glsl[]; +extern char datatoc_gpu_shader_material_anisotropic_glsl[]; +extern char datatoc_gpu_shader_material_attribute_glsl[]; +extern char datatoc_gpu_shader_material_background_glsl[]; +extern char datatoc_gpu_shader_material_bevel_glsl[]; +extern char datatoc_gpu_shader_material_blackbody_glsl[]; +extern char datatoc_gpu_shader_material_bright_contrast_glsl[]; +extern char datatoc_gpu_shader_material_bump_glsl[]; +extern char datatoc_gpu_shader_material_camera_glsl[]; +extern char datatoc_gpu_shader_material_cell_noise_glsl[]; +extern char datatoc_gpu_shader_material_clamp_glsl[]; +extern char datatoc_gpu_shader_material_color_ramp_glsl[]; +extern char datatoc_gpu_shader_material_color_util_glsl[]; +extern char datatoc_gpu_shader_material_combine_hsv_glsl[]; +extern char datatoc_gpu_shader_material_combine_rgb_glsl[]; +extern char datatoc_gpu_shader_material_combine_xyz_glsl[]; +extern char datatoc_gpu_shader_material_diffuse_glsl[]; +extern char datatoc_gpu_shader_material_displacement_glsl[]; +extern char datatoc_gpu_shader_material_eevee_specular_glsl[]; +extern char datatoc_gpu_shader_material_emission_glsl[]; +extern char datatoc_gpu_shader_material_fractal_noise_glsl[]; +extern char datatoc_gpu_shader_material_fresnel_glsl[]; +extern char datatoc_gpu_shader_material_gamma_glsl[]; +extern char datatoc_gpu_shader_material_geometry_glsl[]; +extern char datatoc_gpu_shader_material_glass_glsl[]; +extern char datatoc_gpu_shader_material_glossy_glsl[]; +extern char datatoc_gpu_shader_material_hair_info_glsl[]; +extern char datatoc_gpu_shader_material_hash_glsl[]; +extern char datatoc_gpu_shader_material_holdout_glsl[]; +extern char datatoc_gpu_shader_material_hue_sat_val_glsl[]; +extern char datatoc_gpu_shader_material_invert_glsl[]; +extern char datatoc_gpu_shader_material_layer_weight_glsl[]; +extern char datatoc_gpu_shader_material_light_falloff_glsl[]; +extern char datatoc_gpu_shader_material_light_path_glsl[]; +extern char datatoc_gpu_shader_material_mapping_glsl[]; +extern char datatoc_gpu_shader_material_map_range_glsl[]; +extern char datatoc_gpu_shader_material_math_glsl[]; +extern char datatoc_gpu_shader_material_math_util_glsl[]; +extern char datatoc_gpu_shader_material_mix_rgb_glsl[]; +extern char datatoc_gpu_shader_material_mix_shader_glsl[]; +extern char datatoc_gpu_shader_material_noise_glsl[]; +extern char datatoc_gpu_shader_material_normal_glsl[]; +extern char datatoc_gpu_shader_material_normal_map_glsl[]; +extern char datatoc_gpu_shader_material_object_info_glsl[]; +extern char datatoc_gpu_shader_material_output_material_glsl[]; +extern char datatoc_gpu_shader_material_output_world_glsl[]; +extern char datatoc_gpu_shader_material_particle_info_glsl[]; +extern char datatoc_gpu_shader_material_principled_glsl[]; +extern char datatoc_gpu_shader_material_refraction_glsl[]; +extern char datatoc_gpu_shader_material_rgb_curves_glsl[]; +extern char datatoc_gpu_shader_material_rgb_to_bw_glsl[]; +extern char datatoc_gpu_shader_material_separate_hsv_glsl[]; +extern char datatoc_gpu_shader_material_separate_rgb_glsl[]; +extern char datatoc_gpu_shader_material_separate_xyz_glsl[]; +extern char datatoc_gpu_shader_material_set_glsl[]; +extern char datatoc_gpu_shader_material_shader_to_rgba_glsl[]; +extern char datatoc_gpu_shader_material_squeeze_glsl[]; +extern char datatoc_gpu_shader_material_subsurface_scattering_glsl[]; +extern char datatoc_gpu_shader_material_tangent_glsl[]; +extern char datatoc_gpu_shader_material_tex_brick_glsl[]; +extern char datatoc_gpu_shader_material_tex_checker_glsl[]; +extern char datatoc_gpu_shader_material_tex_environment_glsl[]; +extern char datatoc_gpu_shader_material_tex_gradient_glsl[]; +extern char datatoc_gpu_shader_material_tex_image_glsl[]; +extern char datatoc_gpu_shader_material_tex_magic_glsl[]; +extern char datatoc_gpu_shader_material_tex_musgrave_glsl[]; +extern char datatoc_gpu_shader_material_tex_noise_glsl[]; +extern char datatoc_gpu_shader_material_tex_sky_glsl[]; +extern char datatoc_gpu_shader_material_texture_coordinates_glsl[]; +extern char datatoc_gpu_shader_material_tex_voronoi_glsl[]; +extern char datatoc_gpu_shader_material_tex_wave_glsl[]; +extern char datatoc_gpu_shader_material_tex_white_noise_glsl[]; +extern char datatoc_gpu_shader_material_toon_glsl[]; +extern char datatoc_gpu_shader_material_translucent_glsl[]; +extern char datatoc_gpu_shader_material_transparent_glsl[]; +extern char datatoc_gpu_shader_material_uv_map_glsl[]; +extern char datatoc_gpu_shader_material_vector_curves_glsl[]; +extern char datatoc_gpu_shader_material_vector_displacement_glsl[]; +extern char datatoc_gpu_shader_material_vector_math_glsl[]; +extern char datatoc_gpu_shader_material_velvet_glsl[]; +extern char datatoc_gpu_shader_material_volume_absorption_glsl[]; +extern char datatoc_gpu_shader_material_volume_info_glsl[]; +extern char datatoc_gpu_shader_material_volume_principled_glsl[]; +extern char datatoc_gpu_shader_material_volume_scatter_glsl[]; +extern char datatoc_gpu_shader_material_wireframe_glsl[]; +extern char datatoc_gpu_shader_material_world_normals_glsl[]; + +static GPUMaterialLibrary gpu_shader_material_math_util_library = { + .code = datatoc_gpu_shader_material_math_util_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_color_util_library = { + .code = datatoc_gpu_shader_material_color_util_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_hash_library = { + .code = datatoc_gpu_shader_material_hash_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_noise_library = { + .code = datatoc_gpu_shader_material_noise_glsl, + .dependencies = {&gpu_shader_material_math_util_library, + &gpu_shader_material_hash_library, + NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_fractal_noise_library = { + .code = datatoc_gpu_shader_material_fractal_noise_glsl, + .dependencies = {&gpu_shader_material_noise_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_cell_noise_library = { + .code = datatoc_gpu_shader_material_cell_noise_glsl, + .dependencies = {&gpu_shader_material_math_util_library, + &gpu_shader_material_hash_library, + NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_add_shader_library = { + .code = datatoc_gpu_shader_material_add_shader_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_ambient_occlusion_library = { + .code = datatoc_gpu_shader_material_ambient_occlusion_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_glossy_library = { + .code = datatoc_gpu_shader_material_glossy_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_anisotropic_library = { + .code = datatoc_gpu_shader_material_anisotropic_glsl, + .dependencies = {&gpu_shader_material_glossy_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_attribute_library = { + .code = datatoc_gpu_shader_material_attribute_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_background_library = { + .code = datatoc_gpu_shader_material_background_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_bevel_library = { + .code = datatoc_gpu_shader_material_bevel_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_blackbody_library = { + .code = datatoc_gpu_shader_material_blackbody_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_bright_contrast_library = { + .code = datatoc_gpu_shader_material_bright_contrast_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_bump_library = { + .code = datatoc_gpu_shader_material_bump_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_camera_library = { + .code = datatoc_gpu_shader_material_camera_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_clamp_library = { + .code = datatoc_gpu_shader_material_clamp_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_color_ramp_library = { + .code = datatoc_gpu_shader_material_color_ramp_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_combine_hsv_library = { + .code = datatoc_gpu_shader_material_combine_hsv_glsl, + .dependencies = {&gpu_shader_material_color_util_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_combine_rgb_library = { + .code = datatoc_gpu_shader_material_combine_rgb_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_combine_xyz_library = { + .code = datatoc_gpu_shader_material_combine_xyz_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_diffuse_library = { + .code = datatoc_gpu_shader_material_diffuse_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_displacement_library = { + .code = datatoc_gpu_shader_material_displacement_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_eevee_specular_library = { + .code = datatoc_gpu_shader_material_eevee_specular_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_emission_library = { + .code = datatoc_gpu_shader_material_emission_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_fresnel_library = { + .code = datatoc_gpu_shader_material_fresnel_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_gamma_library = { + .code = datatoc_gpu_shader_material_gamma_glsl, + .dependencies = {&gpu_shader_material_math_util_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_tangent_library = { + .code = datatoc_gpu_shader_material_tangent_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_geometry_library = { + .code = datatoc_gpu_shader_material_geometry_glsl, + .dependencies = {&gpu_shader_material_tangent_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_glass_library = { + .code = datatoc_gpu_shader_material_glass_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_hair_info_library = { + .code = datatoc_gpu_shader_material_hair_info_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_holdout_library = { + .code = datatoc_gpu_shader_material_holdout_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_hue_sat_val_library = { + .code = datatoc_gpu_shader_material_hue_sat_val_glsl, + .dependencies = {&gpu_shader_material_color_util_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_invert_library = { + .code = datatoc_gpu_shader_material_invert_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_layer_weight_library = { + .code = datatoc_gpu_shader_material_layer_weight_glsl, + .dependencies = {&gpu_shader_material_fresnel_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_light_falloff_library = { + .code = datatoc_gpu_shader_material_light_falloff_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_light_path_library = { + .code = datatoc_gpu_shader_material_light_path_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_mapping_library = { + .code = datatoc_gpu_shader_material_mapping_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_map_range_library = { + .code = datatoc_gpu_shader_material_map_range_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_math_library = { + .code = datatoc_gpu_shader_material_math_glsl, + .dependencies = {&gpu_shader_material_math_util_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_mix_rgb_library = { + .code = datatoc_gpu_shader_material_mix_rgb_glsl, + .dependencies = {&gpu_shader_material_color_util_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_mix_shader_library = { + .code = datatoc_gpu_shader_material_mix_shader_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_normal_library = { + .code = datatoc_gpu_shader_material_normal_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_normal_map_library = { + .code = datatoc_gpu_shader_material_normal_map_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_object_info_library = { + .code = datatoc_gpu_shader_material_object_info_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_output_material_library = { + .code = datatoc_gpu_shader_material_output_material_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_output_world_library = { + .code = datatoc_gpu_shader_material_output_world_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_particle_info_library = { + .code = datatoc_gpu_shader_material_particle_info_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_principled_library = { + .code = datatoc_gpu_shader_material_principled_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_refraction_library = { + .code = datatoc_gpu_shader_material_refraction_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_rgb_curves_library = { + .code = datatoc_gpu_shader_material_rgb_curves_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_rgb_to_bw_library = { + .code = datatoc_gpu_shader_material_rgb_to_bw_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_separate_hsv_library = { + .code = datatoc_gpu_shader_material_separate_hsv_glsl, + .dependencies = {&gpu_shader_material_color_util_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_separate_rgb_library = { + .code = datatoc_gpu_shader_material_separate_rgb_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_separate_xyz_library = { + .code = datatoc_gpu_shader_material_separate_xyz_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_set_library = { + .code = datatoc_gpu_shader_material_set_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_shader_to_rgba_library = { + .code = datatoc_gpu_shader_material_shader_to_rgba_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_squeeze_library = { + .code = datatoc_gpu_shader_material_squeeze_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_subsurface_scattering_library = { + .code = datatoc_gpu_shader_material_subsurface_scattering_glsl, + .dependencies = {&gpu_shader_material_diffuse_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_tex_brick_library = { + .code = datatoc_gpu_shader_material_tex_brick_glsl, + .dependencies = {&gpu_shader_material_math_util_library, + &gpu_shader_material_hash_library, + NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_tex_checker_library = { + .code = datatoc_gpu_shader_material_tex_checker_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_tex_environment_library = { + .code = datatoc_gpu_shader_material_tex_environment_glsl, + .dependencies = {&gpu_shader_material_math_util_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_tex_gradient_library = { + .code = datatoc_gpu_shader_material_tex_gradient_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_tex_image_library = { + .code = datatoc_gpu_shader_material_tex_image_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_tex_magic_library = { + .code = datatoc_gpu_shader_material_tex_magic_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_tex_musgrave_library = { + .code = datatoc_gpu_shader_material_tex_musgrave_glsl, + .dependencies = {&gpu_shader_material_noise_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_tex_noise_library = { + .code = datatoc_gpu_shader_material_tex_noise_glsl, + .dependencies = {&gpu_shader_material_fractal_noise_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_tex_sky_library = { + .code = datatoc_gpu_shader_material_tex_sky_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_texture_coordinates_library = { + .code = datatoc_gpu_shader_material_texture_coordinates_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_tex_voronoi_library = { + .code = datatoc_gpu_shader_material_tex_voronoi_glsl, + .dependencies = {&gpu_shader_material_math_util_library, + &gpu_shader_material_cell_noise_library, + NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_tex_wave_library = { + .code = datatoc_gpu_shader_material_tex_wave_glsl, + .dependencies = {&gpu_shader_material_fractal_noise_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_tex_white_noise_library = { + .code = datatoc_gpu_shader_material_tex_white_noise_glsl, + .dependencies = {&gpu_shader_material_hash_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_toon_library = { + .code = datatoc_gpu_shader_material_toon_glsl, + .dependencies = {&gpu_shader_material_diffuse_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_translucent_library = { + .code = datatoc_gpu_shader_material_translucent_glsl, + .dependencies = {&gpu_shader_material_diffuse_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_transparent_library = { + .code = datatoc_gpu_shader_material_transparent_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_uv_map_library = { + .code = datatoc_gpu_shader_material_uv_map_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_vector_curves_library = { + .code = datatoc_gpu_shader_material_vector_curves_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_vector_displacement_library = { + .code = datatoc_gpu_shader_material_vector_displacement_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_vector_math_library = { + .code = datatoc_gpu_shader_material_vector_math_glsl, + .dependencies = {&gpu_shader_material_math_util_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_velvet_library = { + .code = datatoc_gpu_shader_material_velvet_glsl, + .dependencies = {&gpu_shader_material_diffuse_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_volume_absorption_library = { + .code = datatoc_gpu_shader_material_volume_absorption_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_volume_info_library = { + .code = datatoc_gpu_shader_material_volume_info_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_volume_principled_library = { + .code = datatoc_gpu_shader_material_volume_principled_glsl, + .dependencies = {&gpu_shader_material_blackbody_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_volume_scatter_library = { + .code = datatoc_gpu_shader_material_volume_scatter_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_wireframe_library = { + .code = datatoc_gpu_shader_material_wireframe_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_world_normals_library = { + .code = datatoc_gpu_shader_material_world_normals_glsl, + .dependencies = {&gpu_shader_material_texture_coordinates_library, NULL}, +}; + +static GPUMaterialLibrary *gpu_material_libraries[] = { + &gpu_shader_material_math_util_library, + &gpu_shader_material_color_util_library, + &gpu_shader_material_hash_library, + &gpu_shader_material_noise_library, + &gpu_shader_material_fractal_noise_library, + &gpu_shader_material_cell_noise_library, + &gpu_shader_material_add_shader_library, + &gpu_shader_material_ambient_occlusion_library, + &gpu_shader_material_glossy_library, + &gpu_shader_material_anisotropic_library, + &gpu_shader_material_attribute_library, + &gpu_shader_material_background_library, + &gpu_shader_material_bevel_library, + &gpu_shader_material_blackbody_library, + &gpu_shader_material_bright_contrast_library, + &gpu_shader_material_bump_library, + &gpu_shader_material_camera_library, + &gpu_shader_material_clamp_library, + &gpu_shader_material_color_ramp_library, + &gpu_shader_material_combine_hsv_library, + &gpu_shader_material_combine_rgb_library, + &gpu_shader_material_combine_xyz_library, + &gpu_shader_material_diffuse_library, + &gpu_shader_material_displacement_library, + &gpu_shader_material_eevee_specular_library, + &gpu_shader_material_emission_library, + &gpu_shader_material_fresnel_library, + &gpu_shader_material_gamma_library, + &gpu_shader_material_tangent_library, + &gpu_shader_material_geometry_library, + &gpu_shader_material_glass_library, + &gpu_shader_material_hair_info_library, + &gpu_shader_material_holdout_library, + &gpu_shader_material_hue_sat_val_library, + &gpu_shader_material_invert_library, + &gpu_shader_material_layer_weight_library, + &gpu_shader_material_light_falloff_library, + &gpu_shader_material_light_path_library, + &gpu_shader_material_mapping_library, + &gpu_shader_material_map_range_library, + &gpu_shader_material_math_library, + &gpu_shader_material_mix_rgb_library, + &gpu_shader_material_mix_shader_library, + &gpu_shader_material_normal_library, + &gpu_shader_material_normal_map_library, + &gpu_shader_material_object_info_library, + &gpu_shader_material_output_material_library, + &gpu_shader_material_output_world_library, + &gpu_shader_material_particle_info_library, + &gpu_shader_material_principled_library, + &gpu_shader_material_refraction_library, + &gpu_shader_material_rgb_curves_library, + &gpu_shader_material_rgb_to_bw_library, + &gpu_shader_material_separate_hsv_library, + &gpu_shader_material_separate_rgb_library, + &gpu_shader_material_separate_xyz_library, + &gpu_shader_material_set_library, + &gpu_shader_material_shader_to_rgba_library, + &gpu_shader_material_squeeze_library, + &gpu_shader_material_subsurface_scattering_library, + &gpu_shader_material_tex_brick_library, + &gpu_shader_material_tex_checker_library, + &gpu_shader_material_tex_environment_library, + &gpu_shader_material_tex_gradient_library, + &gpu_shader_material_tex_image_library, + &gpu_shader_material_tex_magic_library, + &gpu_shader_material_tex_musgrave_library, + &gpu_shader_material_tex_noise_library, + &gpu_shader_material_tex_sky_library, + &gpu_shader_material_texture_coordinates_library, + &gpu_shader_material_tex_voronoi_library, + &gpu_shader_material_tex_wave_library, + &gpu_shader_material_tex_white_noise_library, + &gpu_shader_material_toon_library, + &gpu_shader_material_translucent_library, + &gpu_shader_material_transparent_library, + &gpu_shader_material_uv_map_library, + &gpu_shader_material_vector_curves_library, + &gpu_shader_material_vector_displacement_library, + &gpu_shader_material_vector_math_library, + &gpu_shader_material_velvet_library, + &gpu_shader_material_volume_absorption_library, + &gpu_shader_material_volume_info_library, + &gpu_shader_material_volume_principled_library, + &gpu_shader_material_volume_scatter_library, + &gpu_shader_material_wireframe_library, + &gpu_shader_material_world_normals_library, + NULL}; +#endif diff --git a/source/blender/gpu/intern/gpu_private.h b/source/blender/gpu/intern/gpu_private.h index 4b90f8daa8c..43b2da13e28 100644 --- a/source/blender/gpu/intern/gpu_private.h +++ b/source/blender/gpu/intern/gpu_private.h @@ -21,9 +21,6 @@ #ifndef __GPU_PRIVATE_H__ #define __GPU_PRIVATE_H__ -struct GPUContext; -struct GPUFrameBuffer; - /* call this before running any of the functions below */ void gpu_extensions_init(void); void gpu_extensions_exit(void); diff --git a/source/blender/gpu/intern/gpu_shader_interface.c b/source/blender/gpu/intern/gpu_shader_interface.c index e34c6e23024..f205ef31ed2 100644 --- a/source/blender/gpu/intern/gpu_shader_interface.c +++ b/source/blender/gpu/intern/gpu_shader_interface.c @@ -67,6 +67,7 @@ static const char *BuiltinUniform_name(GPUUniformBuiltin u) [GPU_UNIFORM_COLOR] = "color", [GPU_UNIFORM_CALLID] = "callId", [GPU_UNIFORM_OBJECT_INFO] = "unfobjectinfo", + [GPU_UNIFORM_OBJECT_COLOR] = "unfobjectcolor", [GPU_UNIFORM_CUSTOM] = NULL, [GPU_NUM_UNIFORMS] = NULL, diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c index dab17fcd72a..955b11036ef 100644 --- a/source/blender/gpu/intern/gpu_texture.c +++ b/source/blender/gpu/intern/gpu_texture.c @@ -1598,7 +1598,7 @@ void GPU_texture_generate_mipmap(GPUTexture *tex) if (GPU_texture_depth(tex)) { /* Some drivers have bugs when using glGenerateMipmap with depth textures (see T56789). - * In this case we just create a complete texture with mipmaps manually without downsampling. + * In this case we just create a complete texture with mipmaps manually without down-sampling. * You must initialize the texture levels using other methods like * GPU_framebuffer_recursive_downsample(). */ int levels = 1 + floor(log2(max_ii(tex->w, tex->h))); diff --git a/source/blender/gpu/intern/gpu_vertex_format.c b/source/blender/gpu/intern/gpu_vertex_format.c index 11df86c0b3a..66e5e254734 100644 --- a/source/blender/gpu/intern/gpu_vertex_format.c +++ b/source/blender/gpu/intern/gpu_vertex_format.c @@ -253,7 +253,7 @@ void GPU_vertformat_safe_attrib_name(const char *attrib_name, *(uint *)&data[4] = BLI_ghashutil_strhash_p_murmur(attrib_name + 4); } else { - /* Copy the whole name. Collision is barelly possible + /* Copy the whole name. Collision is barely possible * (hash would have to be equal to the last 4 bytes). */ for (int i = 0; i < 8 && attrib_name[i] != '\0'; i++) { data[i] = attrib_name[i]; diff --git a/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_vert.glsl b/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_vert.glsl index 8dc92a2b415..2ba89230d80 100644 --- a/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_vert.glsl @@ -1,11 +1,11 @@ uniform mat4 ModelViewProjectionMatrix; uniform vec2 ViewportSize = vec2(-1, -1); +uniform float outline_scale = 1.0; const float line_falloff = 1.0; const float circle_scale = sqrt(2.0 / 3.1416); const float square_scale = sqrt(0.5); - const float diagonal_scale = sqrt(0.5); in vec2 pos; @@ -58,7 +58,7 @@ void main() float line_width = half_width + line_falloff; /* Outline thresholds. */ - thresholds.xy = line_thresholds(line_width); + thresholds.xy = line_thresholds(line_width * outline_scale); /* Inner dot thresholds. */ thresholds.zw = line_thresholds(line_width * 1.6); diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl deleted file mode 100644 index f077ae55d8f..00000000000 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ /dev/null @@ -1,3615 +0,0 @@ - -/* Converters */ - -float convert_rgba_to_float(vec4 color) -{ - return dot(color.rgb, vec3(0.2126, 0.7152, 0.0722)); -} - -float exp_blender(float f) -{ - return pow(2.71828182846, f); -} - -float compatible_pow(float x, float y) -{ - if (y == 0.0) { /* x^0 -> 1, including 0^0 */ - return 1.0; - } - - /* glsl pow doesn't accept negative x */ - if (x < 0.0) { - if (mod(-y, 2.0) == 0.0) { - return pow(-x, y); - } - else { - return -pow(-x, y); - } - } - else if (x == 0.0) { - return 0.0; - } - - return pow(x, y); -} - -void rgb_to_hsv(vec4 rgb, out vec4 outcol) -{ - float cmax, cmin, h, s, v, cdelta; - vec3 c; - - cmax = max(rgb[0], max(rgb[1], rgb[2])); - cmin = min(rgb[0], min(rgb[1], rgb[2])); - cdelta = cmax - cmin; - - v = cmax; - if (cmax != 0.0) { - s = cdelta / cmax; - } - else { - s = 0.0; - h = 0.0; - } - - if (s == 0.0) { - h = 0.0; - } - else { - c = (vec3(cmax) - rgb.xyz) / cdelta; - - if (rgb.x == cmax) { - h = c[2] - c[1]; - } - else if (rgb.y == cmax) { - h = 2.0 + c[0] - c[2]; - } - else { - h = 4.0 + c[1] - c[0]; - } - - h /= 6.0; - - if (h < 0.0) { - h += 1.0; - } - } - - outcol = vec4(h, s, v, rgb.w); -} - -void hsv_to_rgb(vec4 hsv, out vec4 outcol) -{ - float i, f, p, q, t, h, s, v; - vec3 rgb; - - h = hsv[0]; - s = hsv[1]; - v = hsv[2]; - - if (s == 0.0) { - rgb = vec3(v, v, v); - } - else { - if (h == 1.0) { - h = 0.0; - } - - h *= 6.0; - i = floor(h); - f = h - i; - rgb = vec3(f, f, f); - p = v * (1.0 - s); - q = v * (1.0 - (s * f)); - t = v * (1.0 - (s * (1.0 - f))); - - if (i == 0.0) { - rgb = vec3(v, t, p); - } - else if (i == 1.0) { - rgb = vec3(q, v, p); - } - else if (i == 2.0) { - rgb = vec3(p, v, t); - } - else if (i == 3.0) { - rgb = vec3(p, q, v); - } - else if (i == 4.0) { - rgb = vec3(t, p, v); - } - else { - rgb = vec3(v, p, q); - } - } - - outcol = vec4(rgb, hsv.w); -} - -void color_to_normal_new_shading(vec3 color, out vec3 normal) -{ - normal = vec3(2.0) * color - vec3(1.0); -} - -void color_to_blender_normal_new_shading(vec3 color, out vec3 normal) -{ - normal = vec3(2.0, -2.0, -2.0) * color - vec3(1.0); -} - -#ifndef M_PI -# define M_PI 3.14159265358979323846 -#endif -#ifndef M_1_PI -# define M_1_PI 0.318309886183790671538 -#endif - -/*********** SHADER NODES ***************/ - -void particle_info(vec4 sprops, - vec4 loc, - vec3 vel, - vec3 avel, - out float index, - out float random, - out float age, - out float life_time, - out vec3 location, - out float size, - out vec3 velocity, - out vec3 angular_velocity) -{ - index = sprops.x; - random = loc.w; - age = sprops.y; - life_time = sprops.z; - size = sprops.w; - - location = loc.xyz; - velocity = vel; - angular_velocity = avel; -} - -void vect_normalize(vec3 vin, out vec3 vout) -{ - vout = normalize(vin); -} - -void direction_transform_m4v3(vec3 vin, mat4 mat, out vec3 vout) -{ - vout = (mat * vec4(vin, 0.0)).xyz; -} - -void normal_transform_transposed_m4v3(vec3 vin, mat4 mat, out vec3 vout) -{ - vout = transpose(mat3(mat)) * vin; -} - -void point_transform_m4v3(vec3 vin, mat4 mat, out vec3 vout) -{ - vout = (mat * vec4(vin, 1.0)).xyz; -} - -void point_texco_remap_square(vec3 vin, out vec3 vout) -{ - vout = vin * 2.0 - 1.0; -} - -void point_texco_clamp(vec3 vin, sampler2D ima, out vec3 vout) -{ - vec2 half_texel_size = 0.5 / vec2(textureSize(ima, 0).xy); - vout = clamp(vin, half_texel_size.xyy, 1.0 - half_texel_size.xyy); -} - -void point_map_to_sphere(vec3 vin, out vec3 vout) -{ - float len = length(vin); - float v, u; - if (len > 0.0) { - if (vin.x == 0.0 && vin.y == 0.0) { - u = 0.0; - } - else { - u = (1.0 - atan(vin.x, vin.y) / M_PI) / 2.0; - } - - v = 1.0 - acos(vin.z / len) / M_PI; - } - else { - v = u = 0.0; - } - - vout = vec3(u, v, 0.0); -} - -void point_map_to_tube(vec3 vin, out vec3 vout) -{ - float u, v; - v = (vin.z + 1.0) * 0.5; - float len = sqrt(vin.x * vin.x + vin.y * vin[1]); - if (len > 0.0) { - u = (1.0 - (atan(vin.x / len, vin.y / len) / M_PI)) * 0.5; - } - else { - v = u = 0.0; - } - - vout = vec3(u, v, 0.0); -} - -void mapping( - vec3 vec, vec4 m0, vec4 m1, vec4 m2, vec4 m3, vec3 minvec, vec3 maxvec, out vec3 outvec) -{ - mat4 mat = mat4(m0, m1, m2, m3); - outvec = (mat * vec4(vec, 1.0)).xyz; - outvec = clamp(outvec, minvec, maxvec); -} - -void camera(vec3 co, out vec3 outview, out float outdepth, out float outdist) -{ - outdepth = abs(co.z); - outdist = length(co); - outview = normalize(co); -} - -void math_add(float val1, float val2, out float outval) -{ - outval = val1 + val2; -} - -void math_subtract(float val1, float val2, out float outval) -{ - outval = val1 - val2; -} - -void math_multiply(float val1, float val2, out float outval) -{ - outval = val1 * val2; -} - -void math_divide(float val1, float val2, out float outval) -{ - if (val2 == 0.0) { - outval = 0.0; - } - else { - outval = val1 / val2; - } -} - -void math_sine(float val, out float outval) -{ - outval = sin(val); -} - -void math_cosine(float val, out float outval) -{ - outval = cos(val); -} - -void math_tangent(float val, out float outval) -{ - outval = tan(val); -} - -void math_asin(float val, out float outval) -{ - if (val <= 1.0 && val >= -1.0) { - outval = asin(val); - } - else { - outval = 0.0; - } -} - -void math_acos(float val, out float outval) -{ - if (val <= 1.0 && val >= -1.0) { - outval = acos(val); - } - else { - outval = 0.0; - } -} - -void math_atan(float val, out float outval) -{ - outval = atan(val); -} - -void math_pow(float val1, float val2, out float outval) -{ - if (val1 >= 0.0) { - outval = compatible_pow(val1, val2); - } - else { - float val2_mod_1 = mod(abs(val2), 1.0); - - if (val2_mod_1 > 0.999 || val2_mod_1 < 0.001) { - outval = compatible_pow(val1, floor(val2 + 0.5)); - } - else { - outval = 0.0; - } - } -} - -void math_log(float val1, float val2, out float outval) -{ - if (val1 > 0.0 && val2 > 0.0) { - outval = log2(val1) / log2(val2); - } - else { - outval = 0.0; - } -} - -void math_max(float val1, float val2, out float outval) -{ - outval = max(val1, val2); -} - -void math_min(float val1, float val2, out float outval) -{ - outval = min(val1, val2); -} - -void math_round(float val, out float outval) -{ - outval = floor(val + 0.5); -} - -void math_less_than(float val1, float val2, out float outval) -{ - if (val1 < val2) { - outval = 1.0; - } - else { - outval = 0.0; - } -} - -void math_greater_than(float val1, float val2, out float outval) -{ - if (val1 > val2) { - outval = 1.0; - } - else { - outval = 0.0; - } -} - -void math_modulo(float val1, float val2, out float outval) -{ - if (val2 == 0.0 || val1 == val2) { - outval = 0.0; - } - else { - /* change sign to match C convention, mod in GLSL will take absolute for negative numbers, - * see https://www.opengl.org/sdk/docs/man/html/mod.xhtml */ - outval = sign(val1) * mod(abs(val1), val2); - } -} - -void math_abs(float val1, out float outval) -{ - outval = abs(val1); -} - -void math_atan2(float val1, float val2, out float outval) -{ - outval = atan(val1, val2); -} - -void math_floor(float val, out float outval) -{ - outval = floor(val); -} - -void math_ceil(float val, out float outval) -{ - outval = ceil(val); -} - -void math_fract(float val, out float outval) -{ - outval = val - floor(val); -} - -void math_sqrt(float val, out float outval) -{ - if (val > 0.0) { - outval = sqrt(val); - } - else { - outval = 0.0; - } -} - -void squeeze(float val, float width, float center, out float outval) -{ - outval = 1.0 / (1.0 + pow(2.71828183, -((val - center) * width))); -} - -void map_range( - float value, float fromMin, float fromMax, float toMin, float toMax, out float result) -{ - if (fromMax != fromMin) { - result = toMin + ((value - fromMin) / (fromMax - fromMin)) * (toMax - toMin); - } - else { - result = 0.0; - } -} - -void vec_math_add(vec3 v1, vec3 v2, out vec3 outvec, out float outval) -{ - outvec = v1 + v2; - outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2])) * 0.333333; -} - -void vec_math_sub(vec3 v1, vec3 v2, out vec3 outvec, out float outval) -{ - outvec = v1 - v2; - outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2])) * 0.333333; -} - -void vec_math_average(vec3 v1, vec3 v2, out vec3 outvec, out float outval) -{ - outvec = v1 + v2; - outval = length(outvec); - outvec = normalize(outvec); -} -void vec_math_mix(float strength, vec3 v1, vec3 v2, out vec3 outvec) -{ - outvec = strength * v1 + (1 - strength) * v2; -} - -void vec_math_dot(vec3 v1, vec3 v2, out vec3 outvec, out float outval) -{ - outvec = vec3(0); - outval = dot(v1, v2); -} - -void vec_math_cross(vec3 v1, vec3 v2, out vec3 outvec, out float outval) -{ - outvec = cross(v1, v2); - outval = length(outvec); - outvec /= outval; -} - -void vec_math_normalize(vec3 v, out vec3 outvec, out float outval) -{ - outval = length(v); - outvec = normalize(v); -} - -void vec_math_negate(vec3 v, out vec3 outv) -{ - outv = -v; -} - -void invert_z(vec3 v, out vec3 outv) -{ - v.z = -v.z; - outv = v; -} - -void normal_new_shading(vec3 nor, vec3 dir, out vec3 outnor, out float outdot) -{ - outnor = dir; - outdot = dot(normalize(nor), dir); -} - -void curves_vec(float fac, vec3 vec, sampler1DArray curvemap, float layer, out vec3 outvec) -{ - vec4 co = vec4(vec * 0.5 + 0.5, layer); - outvec.x = texture(curvemap, co.xw).x; - outvec.y = texture(curvemap, co.yw).y; - outvec.z = texture(curvemap, co.zw).z; - outvec = mix(vec, outvec, fac); -} - -/* ext is vec4(in_x, in_dy, out_x, out_dy). */ -float curve_extrapolate(float x, float y, vec4 ext) -{ - if (x < 0.0) { - return y + x * ext.y; - } - else if (x > 1.0) { - return y + (x - 1.0) * ext.w; - } - else { - return y; - } -} - -#define RANGE_RESCALE(x, min, range) ((x - min) * range) - -void curves_rgb(float fac, - vec4 col, - sampler1DArray curvemap, - float layer, - vec4 range, - vec4 ext_r, - vec4 ext_g, - vec4 ext_b, - vec4 ext_a, - out vec4 outcol) -{ - vec4 co = vec4(RANGE_RESCALE(col.rgb, ext_a.x, range.a), layer); - vec3 samp; - samp.r = texture(curvemap, co.xw).a; - samp.g = texture(curvemap, co.yw).a; - samp.b = texture(curvemap, co.zw).a; - - samp.r = curve_extrapolate(co.x, samp.r, ext_a); - samp.g = curve_extrapolate(co.y, samp.g, ext_a); - samp.b = curve_extrapolate(co.z, samp.b, ext_a); - - vec3 rgb_min = vec3(ext_r.x, ext_g.x, ext_b.x); - co.xyz = RANGE_RESCALE(samp.rgb, rgb_min, range.rgb); - - samp.r = texture(curvemap, co.xw).r; - samp.g = texture(curvemap, co.yw).g; - samp.b = texture(curvemap, co.zw).b; - - outcol.r = curve_extrapolate(co.x, samp.r, ext_r); - outcol.g = curve_extrapolate(co.y, samp.g, ext_g); - outcol.b = curve_extrapolate(co.z, samp.b, ext_b); - outcol.a = col.a; - - outcol = mix(col, outcol, fac); -} - -void curves_rgb_opti(float fac, - vec4 col, - sampler1DArray curvemap, - float layer, - vec4 range, - vec4 ext_a, - out vec4 outcol) -{ - vec4 co = vec4(RANGE_RESCALE(col.rgb, ext_a.x, range.a), layer); - vec3 samp; - samp.r = texture(curvemap, co.xw).a; - samp.g = texture(curvemap, co.yw).a; - samp.b = texture(curvemap, co.zw).a; - - outcol.r = curve_extrapolate(co.x, samp.r, ext_a); - outcol.g = curve_extrapolate(co.y, samp.g, ext_a); - outcol.b = curve_extrapolate(co.z, samp.b, ext_a); - outcol.a = col.a; - - outcol = mix(col, outcol, fac); -} - -void set_value(float val, out float outval) -{ - outval = val; -} - -void set_rgb(vec3 col, out vec3 outcol) -{ - outcol = col; -} - -void set_rgba(vec4 col, out vec4 outcol) -{ - outcol = col; -} - -void set_value_zero(out float outval) -{ - outval = 0.0; -} - -void set_value_one(out float outval) -{ - outval = 1.0; -} - -void set_rgb_zero(out vec3 outval) -{ - outval = vec3(0.0); -} - -void set_rgb_one(out vec3 outval) -{ - outval = vec3(1.0); -} - -void set_rgba_zero(out vec4 outval) -{ - outval = vec4(0.0); -} - -void set_rgba_one(out vec4 outval) -{ - outval = vec4(1.0); -} - -void brightness_contrast(vec4 col, float brightness, float contrast, out vec4 outcol) -{ - float a = 1.0 + contrast; - float b = brightness - contrast * 0.5; - - outcol.r = max(a * col.r + b, 0.0); - outcol.g = max(a * col.g + b, 0.0); - outcol.b = max(a * col.b + b, 0.0); - outcol.a = col.a; -} - -void mix_blend(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - outcol = mix(col1, col2, fac); - outcol.a = col1.a; -} - -void mix_add(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - outcol = mix(col1, col1 + col2, fac); - outcol.a = col1.a; -} - -void mix_mult(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - outcol = mix(col1, col1 * col2, fac); - outcol.a = col1.a; -} - -void mix_screen(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - float facm = 1.0 - fac; - - outcol = vec4(1.0) - (vec4(facm) + fac * (vec4(1.0) - col2)) * (vec4(1.0) - col1); - outcol.a = col1.a; -} - -void mix_overlay(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - float facm = 1.0 - fac; - - outcol = col1; - - if (outcol.r < 0.5) { - outcol.r *= facm + 2.0 * fac * col2.r; - } - else { - outcol.r = 1.0 - (facm + 2.0 * fac * (1.0 - col2.r)) * (1.0 - outcol.r); - } - - if (outcol.g < 0.5) { - outcol.g *= facm + 2.0 * fac * col2.g; - } - else { - outcol.g = 1.0 - (facm + 2.0 * fac * (1.0 - col2.g)) * (1.0 - outcol.g); - } - - if (outcol.b < 0.5) { - outcol.b *= facm + 2.0 * fac * col2.b; - } - else { - outcol.b = 1.0 - (facm + 2.0 * fac * (1.0 - col2.b)) * (1.0 - outcol.b); - } -} - -void mix_sub(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - outcol = mix(col1, col1 - col2, fac); - outcol.a = col1.a; -} - -void mix_div(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - float facm = 1.0 - fac; - - outcol = col1; - - if (col2.r != 0.0) { - outcol.r = facm * outcol.r + fac * outcol.r / col2.r; - } - if (col2.g != 0.0) { - outcol.g = facm * outcol.g + fac * outcol.g / col2.g; - } - if (col2.b != 0.0) { - outcol.b = facm * outcol.b + fac * outcol.b / col2.b; - } -} - -void mix_diff(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - outcol = mix(col1, abs(col1 - col2), fac); - outcol.a = col1.a; -} - -void mix_dark(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - outcol.rgb = min(col1.rgb, col2.rgb * fac); - outcol.a = col1.a; -} - -void mix_light(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - outcol.rgb = max(col1.rgb, col2.rgb * fac); - outcol.a = col1.a; -} - -void mix_dodge(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - outcol = col1; - - if (outcol.r != 0.0) { - float tmp = 1.0 - fac * col2.r; - if (tmp <= 0.0) { - outcol.r = 1.0; - } - else if ((tmp = outcol.r / tmp) > 1.0) { - outcol.r = 1.0; - } - else { - outcol.r = tmp; - } - } - if (outcol.g != 0.0) { - float tmp = 1.0 - fac * col2.g; - if (tmp <= 0.0) { - outcol.g = 1.0; - } - else if ((tmp = outcol.g / tmp) > 1.0) { - outcol.g = 1.0; - } - else { - outcol.g = tmp; - } - } - if (outcol.b != 0.0) { - float tmp = 1.0 - fac * col2.b; - if (tmp <= 0.0) { - outcol.b = 1.0; - } - else if ((tmp = outcol.b / tmp) > 1.0) { - outcol.b = 1.0; - } - else { - outcol.b = tmp; - } - } -} - -void mix_burn(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - float tmp, facm = 1.0 - fac; - - outcol = col1; - - tmp = facm + fac * col2.r; - if (tmp <= 0.0) { - outcol.r = 0.0; - } - else if ((tmp = (1.0 - (1.0 - outcol.r) / tmp)) < 0.0) { - outcol.r = 0.0; - } - else if (tmp > 1.0) { - outcol.r = 1.0; - } - else { - outcol.r = tmp; - } - - tmp = facm + fac * col2.g; - if (tmp <= 0.0) { - outcol.g = 0.0; - } - else if ((tmp = (1.0 - (1.0 - outcol.g) / tmp)) < 0.0) { - outcol.g = 0.0; - } - else if (tmp > 1.0) { - outcol.g = 1.0; - } - else { - outcol.g = tmp; - } - - tmp = facm + fac * col2.b; - if (tmp <= 0.0) { - outcol.b = 0.0; - } - else if ((tmp = (1.0 - (1.0 - outcol.b) / tmp)) < 0.0) { - outcol.b = 0.0; - } - else if (tmp > 1.0) { - outcol.b = 1.0; - } - else { - outcol.b = tmp; - } -} - -void mix_hue(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - float facm = 1.0 - fac; - - outcol = col1; - - vec4 hsv, hsv2, tmp; - rgb_to_hsv(col2, hsv2); - - if (hsv2.y != 0.0) { - rgb_to_hsv(outcol, hsv); - hsv.x = hsv2.x; - hsv_to_rgb(hsv, tmp); - - outcol = mix(outcol, tmp, fac); - outcol.a = col1.a; - } -} - -void mix_sat(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - float facm = 1.0 - fac; - - outcol = col1; - - vec4 hsv, hsv2; - rgb_to_hsv(outcol, hsv); - - if (hsv.y != 0.0) { - rgb_to_hsv(col2, hsv2); - - hsv.y = facm * hsv.y + fac * hsv2.y; - hsv_to_rgb(hsv, outcol); - } -} - -void mix_val(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - float facm = 1.0 - fac; - - vec4 hsv, hsv2; - rgb_to_hsv(col1, hsv); - rgb_to_hsv(col2, hsv2); - - hsv.z = facm * hsv.z + fac * hsv2.z; - hsv_to_rgb(hsv, outcol); -} - -void mix_color(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - float facm = 1.0 - fac; - - outcol = col1; - - vec4 hsv, hsv2, tmp; - rgb_to_hsv(col2, hsv2); - - if (hsv2.y != 0.0) { - rgb_to_hsv(outcol, hsv); - hsv.x = hsv2.x; - hsv.y = hsv2.y; - hsv_to_rgb(hsv, tmp); - - outcol = mix(outcol, tmp, fac); - outcol.a = col1.a; - } -} - -void mix_soft(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - float facm = 1.0 - fac; - - vec4 one = vec4(1.0); - vec4 scr = one - (one - col2) * (one - col1); - outcol = facm * col1 + fac * ((one - col1) * col2 * col1 + col1 * scr); -} - -void mix_linear(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - - outcol = col1 + fac * (2.0 * (col2 - vec4(0.5))); -} - -void valtorgb_opti_constant( - float fac, float edge, vec4 color1, vec4 color2, out vec4 outcol, out float outalpha) -{ - outcol = (fac > edge) ? color2 : color1; - outalpha = outcol.a; -} - -void valtorgb_opti_linear( - float fac, vec2 mulbias, vec4 color1, vec4 color2, out vec4 outcol, out float outalpha) -{ - fac = clamp(fac * mulbias.x + mulbias.y, 0.0, 1.0); - outcol = mix(color1, color2, fac); - outalpha = outcol.a; -} - -void valtorgb(float fac, sampler1DArray colormap, float layer, out vec4 outcol, out float outalpha) -{ - outcol = texture(colormap, vec2(fac, layer)); - outalpha = outcol.a; -} - -void valtorgb_nearest( - float fac, sampler1DArray colormap, float layer, out vec4 outcol, out float outalpha) -{ - fac = clamp(fac, 0.0, 1.0); - outcol = texelFetch(colormap, ivec2(fac * (textureSize(colormap, 0).x - 1), layer), 0); - outalpha = outcol.a; -} - -void rgbtobw(vec4 color, out float outval) -{ - vec3 factors = vec3(0.2126, 0.7152, 0.0722); - outval = dot(color.rgb, factors); -} - -void invert(float fac, vec4 col, out vec4 outcol) -{ - outcol.xyz = mix(col.xyz, vec3(1.0) - col.xyz, fac); - outcol.w = col.w; -} - -void clamp_vec3(vec3 vec, vec3 min, vec3 max, out vec3 out_vec) -{ - out_vec = clamp(vec, min, max); -} - -void clamp_value(float value, float min, float max, out float result) -{ - result = clamp(value, min, max); -} - -void hue_sat(float hue, float sat, float value, float fac, vec4 col, out vec4 outcol) -{ - vec4 hsv; - - rgb_to_hsv(col, hsv); - - hsv[0] = fract(hsv[0] + hue + 0.5); - hsv[1] = clamp(hsv[1] * sat, 0.0, 1.0); - hsv[2] = hsv[2] * value; - - hsv_to_rgb(hsv, outcol); - - outcol = mix(col, outcol, fac); -} - -void separate_rgb(vec4 col, out float r, out float g, out float b) -{ - r = col.r; - g = col.g; - b = col.b; -} - -void combine_rgb(float r, float g, float b, out vec4 col) -{ - col = vec4(r, g, b, 1.0); -} - -void separate_xyz(vec3 vec, out float x, out float y, out float z) -{ - x = vec.r; - y = vec.g; - z = vec.b; -} - -void combine_xyz(float x, float y, float z, out vec3 vec) -{ - vec = vec3(x, y, z); -} - -void separate_hsv(vec4 col, out float h, out float s, out float v) -{ - vec4 hsv; - - rgb_to_hsv(col, hsv); - h = hsv[0]; - s = hsv[1]; - v = hsv[2]; -} - -void combine_hsv(float h, float s, float v, out vec4 col) -{ - hsv_to_rgb(vec4(h, s, v, 1.0), col); -} - -void output_node(vec4 rgb, float alpha, out vec4 outrgb) -{ - outrgb = vec4(rgb.rgb, alpha); -} - -/*********** TEXTURES ***************/ - -void texco_norm(vec3 normal, out vec3 outnormal) -{ - /* corresponds to shi->orn, which is negated so cancels - out blender normal negation */ - outnormal = normalize(normal); -} - -vec3 mtex_2d_mapping(vec3 vec) -{ - return vec3(vec.xy * 0.5 + vec2(0.5), vec.z); -} - -/** helper method to extract the upper left 3x3 matrix from a 4x4 matrix */ -mat3 to_mat3(mat4 m4) -{ - mat3 m3; - m3[0] = m4[0].xyz; - m3[1] = m4[1].xyz; - m3[2] = m4[2].xyz; - return m3; -} - -/*********** NEW SHADER UTILITIES **************/ - -float fresnel_dielectric_0(float eta) -{ - /* compute fresnel reflactance at normal incidence => cosi = 1.0 */ - float A = (eta - 1.0) / (eta + 1.0); - - return A * A; -} - -float fresnel_dielectric_cos(float cosi, float eta) -{ - /* compute fresnel reflectance without explicitly computing - * the refracted direction */ - float c = abs(cosi); - float g = eta * eta - 1.0 + c * c; - float result; - - if (g > 0.0) { - g = sqrt(g); - float A = (g - c) / (g + c); - float B = (c * (g + c) - 1.0) / (c * (g - c) + 1.0); - result = 0.5 * A * A * (1.0 + B * B); - } - else { - result = 1.0; /* TIR (no refracted component) */ - } - - return result; -} - -float fresnel_dielectric(vec3 Incoming, vec3 Normal, float eta) -{ - /* compute fresnel reflectance without explicitly computing - * the refracted direction */ - return fresnel_dielectric_cos(dot(Incoming, Normal), eta); -} - -float hypot(float x, float y) -{ - return sqrt(x * x + y * y); -} - -void generated_from_orco(vec3 orco, out vec3 generated) -{ -#ifdef VOLUMETRICS -# ifdef MESH_SHADER - generated = volumeObjectLocalCoord; -# else - generated = worldPosition; -# endif -#else - generated = orco; -#endif -} - -int floor_to_int(float x) -{ - return int(floor(x)); -} - -int quick_floor(float x) -{ - return int(x) - ((x < 0) ? 1 : 0); -} - -float integer_noise(int n) -{ - int nn; - n = (n + 1013) & 0x7fffffff; - n = (n >> 13) ^ n; - nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff; - return 0.5 * (float(nn) / 1073741824.0); -} - -uint hash(uint kx, uint ky, uint kz) -{ -#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k)))) -#define final(a, b, c) \ - { \ - c ^= b; \ - c -= rot(b, 14); \ - a ^= c; \ - a -= rot(c, 11); \ - b ^= a; \ - b -= rot(a, 25); \ - c ^= b; \ - c -= rot(b, 16); \ - a ^= c; \ - a -= rot(c, 4); \ - b ^= a; \ - b -= rot(a, 14); \ - c ^= b; \ - c -= rot(b, 24); \ - } - // now hash the data! - uint a, b, c, len = 3u; - a = b = c = 0xdeadbeefu + (len << 2u) + 13u; - - c += kz; - b += ky; - a += kx; - final(a, b, c); - - return c; -#undef rot -#undef final -} - -uint hash(int kx, int ky, int kz) -{ - return hash(uint(kx), uint(ky), uint(kz)); -} - -float bits_to_01(uint bits) -{ - return (float(bits) / 4294967295.0); -} - -float cellnoise(vec3 p) -{ - int ix = quick_floor(p.x); - int iy = quick_floor(p.y); - int iz = quick_floor(p.z); - - return bits_to_01(hash(uint(ix), uint(iy), uint(iz))); -} - -vec3 cellnoise_color(vec3 p) -{ - float r = cellnoise(p.xyz); - float g = cellnoise(p.yxz); - float b = cellnoise(p.yzx); - - return vec3(r, g, b); -} - -float floorfrac(float x, out int i) -{ - float x_floor = floor(x); - i = int(x_floor); - return x - x_floor; -} - -/* bsdfs */ - -vec3 tint_from_color(vec3 color) -{ - float lum = dot(color, vec3(0.3, 0.6, 0.1)); /* luminance approx. */ - return (lum > 0) ? color / lum : vec3(1.0); /* normalize lum. to isolate hue+sat */ -} - -void convert_metallic_to_specular_tinted(vec3 basecol, - vec3 basecol_tint, - float metallic, - float specular_fac, - float specular_tint, - out vec3 diffuse, - out vec3 f0) -{ - vec3 tmp_col = mix(vec3(1.0), basecol_tint, specular_tint); - f0 = mix((0.08 * specular_fac) * tmp_col, basecol, metallic); - diffuse = basecol * (1.0 - metallic); -} - -vec3 principled_sheen(float NV, vec3 basecol_tint, float sheen_tint) -{ - float f = 1.0 - NV; - /* Temporary fix for T59784. Normal map seems to contain NaNs for tangent space normal maps, - * therefore we need to clamp value. */ - f = clamp(f, 0.0, 1.0); - /* Empirical approximation (manual curve fitting). Can be refined. */ - float sheen = f * f * f * 0.077 + f * 0.01 + 0.00026; - return sheen * mix(vec3(1.0), basecol_tint, sheen_tint); -} - -#ifndef VOLUMETRICS -void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out Closure result) -{ - N = normalize(N); - result = CLOSURE_DEFAULT; - eevee_closure_diffuse(N, color.rgb, 1.0, result.radiance); - closure_load_ssr_data(vec3(0.0), 0.0, N, viewCameraVec, -1, result); - result.radiance *= color.rgb; -} - -void node_bsdf_glossy(vec4 color, float roughness, vec3 N, float ssr_id, out Closure result) -{ - N = normalize(N); - vec3 out_spec, ssr_spec; - eevee_closure_glossy(N, vec3(1.0), vec3(1.0), int(ssr_id), roughness, 1.0, out_spec, ssr_spec); - vec3 vN = mat3(ViewMatrix) * N; - result = CLOSURE_DEFAULT; - result.radiance = out_spec * color.rgb; - closure_load_ssr_data(ssr_spec * color.rgb, roughness, N, viewCameraVec, int(ssr_id), result); -} - -void node_bsdf_anisotropic(vec4 color, - float roughness, - float anisotropy, - float rotation, - vec3 N, - vec3 T, - out Closure result) -{ - node_bsdf_glossy(color, roughness, N, -1, result); -} - -void node_bsdf_glass( - vec4 color, float roughness, float ior, vec3 N, float ssr_id, out Closure result) -{ - N = normalize(N); - vec3 out_spec, out_refr, ssr_spec; - vec3 refr_color = (refractionDepth > 0.0) ? color.rgb * color.rgb : - color.rgb; /* Simulate 2 transmission event */ - eevee_closure_glass( - N, vec3(1.0), vec3(1.0), int(ssr_id), roughness, 1.0, ior, out_spec, out_refr, ssr_spec); - out_refr *= refr_color; - out_spec *= color.rgb; - float fresnel = F_eta(ior, dot(N, cameraVec)); - vec3 vN = mat3(ViewMatrix) * N; - result = CLOSURE_DEFAULT; - result.radiance = mix(out_refr, out_spec, fresnel); - closure_load_ssr_data( - ssr_spec * color.rgb * fresnel, roughness, N, viewCameraVec, int(ssr_id), result); -} - -void node_bsdf_toon(vec4 color, float size, float tsmooth, vec3 N, out Closure result) -{ - node_bsdf_diffuse(color, 0.0, N, result); -} - -void node_bsdf_principled(vec4 base_color, - float subsurface, - vec3 subsurface_radius, - vec4 subsurface_color, - float metallic, - float specular, - float specular_tint, - float roughness, - float anisotropic, - float anisotropic_rotation, - float sheen, - float sheen_tint, - float clearcoat, - float clearcoat_roughness, - float ior, - float transmission, - float transmission_roughness, - vec4 emission, - float alpha, - vec3 N, - vec3 CN, - vec3 T, - vec3 I, - float ssr_id, - float sss_id, - vec3 sss_scale, - out Closure result) -{ - N = normalize(N); - ior = max(ior, 1e-5); - metallic = saturate(metallic); - transmission = saturate(transmission); - float dielectric = 1.0 - metallic; - transmission *= dielectric; - sheen *= dielectric; - subsurface_color *= dielectric; - - vec3 diffuse, f0, out_diff, out_spec, out_trans, out_refr, ssr_spec; - vec3 ctint = tint_from_color(base_color.rgb); - convert_metallic_to_specular_tinted( - base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0); - - float NV = dot(N, cameraVec); - vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint); - - /* Far from being accurate, but 2 glossy evaluation is too expensive. - * Most noticeable difference is at grazing angles since the bsdf lut - * f0 color interpolation is done on top of this interpolation. */ - vec3 f0_glass = mix(vec3(1.0), base_color.rgb, specular_tint); - float fresnel = F_eta(ior, NV); - vec3 spec_col = F_color_blend(ior, fresnel, f0_glass) * fresnel; - f0 = mix(f0, spec_col, transmission); - - vec3 f90 = mix(vec3(1.0), f0, (1.0 - specular) * metallic); - - vec3 mixed_ss_base_color = mix(diffuse, subsurface_color.rgb, subsurface); - - float sss_scalef = avg(sss_scale) * subsurface; - eevee_closure_principled(N, - mixed_ss_base_color, - f0, - f90, - int(ssr_id), - roughness, - CN, - clearcoat * 0.25, - clearcoat_roughness, - 1.0, - sss_scalef, - ior, - out_diff, - out_trans, - out_spec, - out_refr, - ssr_spec); - - vec3 refr_color = base_color.rgb; - refr_color *= (refractionDepth > 0.0) ? refr_color : - vec3(1.0); /* Simulate 2 transmission event */ - out_refr *= refr_color * (1.0 - fresnel) * transmission; - - result = CLOSURE_DEFAULT; - result.radiance = out_spec + out_refr; - result.radiance += out_diff * out_sheen; /* Coarse approx. */ - - closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); - - vec3 sss_radiance = (out_diff + out_trans) * alpha; -# ifndef USE_SSS - result.radiance += sss_radiance * mixed_ss_base_color * (1.0 - transmission); -# else -# ifdef USE_SSS_ALBEDO - vec3 sss_albedo = mixed_ss_base_color; -# else - sss_radiance *= mixed_ss_base_color; -# endif - sss_radiance *= (1.0 - transmission); - closure_load_sss_data(sss_scalef, - sss_radiance, -# ifdef USE_SSS_ALBEDO - sss_albedo, -# endif - int(sss_id), - result); -# endif /* USE_SSS */ - - result.radiance += emission.rgb; - result.radiance *= alpha; - result.transmittance = vec3(1.0 - alpha); -} - -void node_bsdf_principled_dielectric(vec4 base_color, - float subsurface, - vec3 subsurface_radius, - vec4 subsurface_color, - float metallic, - float specular, - float specular_tint, - float roughness, - float anisotropic, - float anisotropic_rotation, - float sheen, - float sheen_tint, - float clearcoat, - float clearcoat_roughness, - float ior, - float transmission, - float transmission_roughness, - vec4 emission, - float alpha, - vec3 N, - vec3 CN, - vec3 T, - vec3 I, - float ssr_id, - float sss_id, - vec3 sss_scale, - out Closure result) -{ - N = normalize(N); - metallic = saturate(metallic); - float dielectric = 1.0 - metallic; - - vec3 diffuse, f0, out_diff, out_spec, ssr_spec; - vec3 ctint = tint_from_color(base_color.rgb); - convert_metallic_to_specular_tinted( - base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0); - - float NV = dot(N, cameraVec); - vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint); - - eevee_closure_default( - N, diffuse, f0, vec3(1.0), int(ssr_id), roughness, 1.0, out_diff, out_spec, ssr_spec); - - result = CLOSURE_DEFAULT; - result.radiance = out_spec + out_diff * (diffuse + out_sheen); - closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); - result.radiance += emission.rgb; - result.radiance *= alpha; - result.transmittance = vec3(1.0 - alpha); -} - -void node_bsdf_principled_metallic(vec4 base_color, - float subsurface, - vec3 subsurface_radius, - vec4 subsurface_color, - float metallic, - float specular, - float specular_tint, - float roughness, - float anisotropic, - float anisotropic_rotation, - float sheen, - float sheen_tint, - float clearcoat, - float clearcoat_roughness, - float ior, - float transmission, - float transmission_roughness, - vec4 emission, - float alpha, - vec3 N, - vec3 CN, - vec3 T, - vec3 I, - float ssr_id, - float sss_id, - vec3 sss_scale, - out Closure result) -{ - N = normalize(N); - vec3 out_spec, ssr_spec; - - vec3 f90 = mix(vec3(1.0), base_color.rgb, (1.0 - specular) * metallic); - - eevee_closure_glossy(N, base_color.rgb, f90, int(ssr_id), roughness, 1.0, out_spec, ssr_spec); - - result = CLOSURE_DEFAULT; - result.radiance = out_spec; - closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); - result.radiance += emission.rgb; - result.radiance *= alpha; - result.transmittance = vec3(1.0 - alpha); -} - -void node_bsdf_principled_clearcoat(vec4 base_color, - float subsurface, - vec3 subsurface_radius, - vec4 subsurface_color, - float metallic, - float specular, - float specular_tint, - float roughness, - float anisotropic, - float anisotropic_rotation, - float sheen, - float sheen_tint, - float clearcoat, - float clearcoat_roughness, - float ior, - float transmission, - float transmission_roughness, - vec4 emission, - float alpha, - vec3 N, - vec3 CN, - vec3 T, - vec3 I, - float ssr_id, - float sss_id, - vec3 sss_scale, - out Closure result) -{ - vec3 out_spec, ssr_spec; - N = normalize(N); - - vec3 f90 = mix(vec3(1.0), base_color.rgb, (1.0 - specular) * metallic); - - eevee_closure_clearcoat(N, - base_color.rgb, - f90, - int(ssr_id), - roughness, - CN, - clearcoat * 0.25, - clearcoat_roughness, - 1.0, - out_spec, - ssr_spec); - - result = CLOSURE_DEFAULT; - result.radiance = out_spec; - closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); - result.radiance += emission.rgb; - result.radiance *= alpha; - result.transmittance = vec3(1.0 - alpha); -} - -void node_bsdf_principled_subsurface(vec4 base_color, - float subsurface, - vec3 subsurface_radius, - vec4 subsurface_color, - float metallic, - float specular, - float specular_tint, - float roughness, - float anisotropic, - float anisotropic_rotation, - float sheen, - float sheen_tint, - float clearcoat, - float clearcoat_roughness, - float ior, - float transmission, - float transmission_roughness, - vec4 emission, - float alpha, - vec3 N, - vec3 CN, - vec3 T, - vec3 I, - float ssr_id, - float sss_id, - vec3 sss_scale, - out Closure result) -{ - metallic = saturate(metallic); - N = normalize(N); - - vec3 diffuse, f0, out_diff, out_spec, out_trans, ssr_spec; - vec3 ctint = tint_from_color(base_color.rgb); - convert_metallic_to_specular_tinted( - base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0); - - subsurface_color = subsurface_color * (1.0 - metallic); - vec3 mixed_ss_base_color = mix(diffuse, subsurface_color.rgb, subsurface); - float sss_scalef = avg(sss_scale) * subsurface; - - float NV = dot(N, cameraVec); - vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint); - - vec3 f90 = mix(vec3(1.0), base_color.rgb, (1.0 - specular) * metallic); - - eevee_closure_skin(N, - mixed_ss_base_color, - f0, - f90, - int(ssr_id), - roughness, - 1.0, - sss_scalef, - out_diff, - out_trans, - out_spec, - ssr_spec); - - result = CLOSURE_DEFAULT; - result.radiance = out_spec; - closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); - - vec3 sss_radiance = (out_diff + out_trans) * alpha; -# ifndef USE_SSS - result.radiance += sss_radiance * mixed_ss_base_color * (1.0 - transmission); -# else -# ifdef USE_SSS_ALBEDO - vec3 sss_albedo = mixed_ss_base_color; -# else - sss_radiance *= mixed_ss_base_color; -# endif - sss_radiance *= (1.0 - transmission); - closure_load_sss_data(sss_scalef, - sss_radiance, -# ifdef USE_SSS_ALBEDO - sss_albedo, -# endif - int(sss_id), - result); -# endif /* USE_SSS */ - - result.radiance += out_diff * out_sheen; - result.radiance += emission.rgb; - result.radiance *= alpha; - result.transmittance = vec3(1.0 - alpha); -} - -void node_bsdf_principled_glass(vec4 base_color, - float subsurface, - vec3 subsurface_radius, - vec4 subsurface_color, - float metallic, - float specular, - float specular_tint, - float roughness, - float anisotropic, - float anisotropic_rotation, - float sheen, - float sheen_tint, - float clearcoat, - float clearcoat_roughness, - float ior, - float transmission, - float transmission_roughness, - vec4 emission, - float alpha, - vec3 N, - vec3 CN, - vec3 T, - vec3 I, - float ssr_id, - float sss_id, - vec3 sss_scale, - out Closure result) -{ - ior = max(ior, 1e-5); - N = normalize(N); - - vec3 f0, out_spec, out_refr, ssr_spec; - f0 = mix(vec3(1.0), base_color.rgb, specular_tint); - - eevee_closure_glass( - N, vec3(1.0), vec3(1.0), int(ssr_id), roughness, 1.0, ior, out_spec, out_refr, ssr_spec); - - vec3 refr_color = base_color.rgb; - refr_color *= (refractionDepth > 0.0) ? refr_color : - vec3(1.0); /* Simulate 2 transmission events */ - out_refr *= refr_color; - - float fresnel = F_eta(ior, dot(N, cameraVec)); - vec3 spec_col = F_color_blend(ior, fresnel, f0); - out_spec *= spec_col; - ssr_spec *= spec_col * fresnel; - - result = CLOSURE_DEFAULT; - result.radiance = mix(out_refr, out_spec, fresnel); - closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); - result.radiance += emission.rgb; - result.radiance *= alpha; - result.transmittance = vec3(1.0 - alpha); -} - -void node_bsdf_translucent(vec4 color, vec3 N, out Closure result) -{ - node_bsdf_diffuse(color, 0.0, -N, result); -} - -void node_bsdf_transparent(vec4 color, out Closure result) -{ - result = CLOSURE_DEFAULT; - result.radiance = vec3(0.0); - result.transmittance = abs(color.rgb); -} - -void node_bsdf_velvet(vec4 color, float sigma, vec3 N, out Closure result) -{ - node_bsdf_diffuse(color, 0.0, N, result); -} - -void node_subsurface_scattering(vec4 color, - float scale, - vec3 radius, - float sharpen, - float texture_blur, - vec3 N, - float sss_id, - out Closure result) -{ -# if defined(USE_SSS) - N = normalize(N); - vec3 out_diff, out_trans; - vec3 vN = mat3(ViewMatrix) * N; - result = CLOSURE_DEFAULT; - closure_load_ssr_data(vec3(0.0), 0.0, N, viewCameraVec, -1, result); - - eevee_closure_subsurface(N, color.rgb, 1.0, scale, out_diff, out_trans); - - vec3 sss_radiance = out_diff + out_trans; -# ifdef USE_SSS_ALBEDO - /* Not perfect for texture_blur not exactly equal to 0.0 or 1.0. */ - vec3 sss_albedo = mix(color.rgb, vec3(1.0), texture_blur); - sss_radiance *= mix(vec3(1.0), color.rgb, texture_blur); -# else - sss_radiance *= color.rgb; -# endif - closure_load_sss_data(scale, - sss_radiance, -# ifdef USE_SSS_ALBEDO - sss_albedo, -# endif - int(sss_id), - result); -# else - node_bsdf_diffuse(color, 0.0, N, result); -# endif -} - -void node_bsdf_refraction(vec4 color, float roughness, float ior, vec3 N, out Closure result) -{ - N = normalize(N); - vec3 out_refr; - color.rgb *= (refractionDepth > 0.0) ? color.rgb : vec3(1.0); /* Simulate 2 absorption event. */ - eevee_closure_refraction(N, roughness, ior, out_refr); - vec3 vN = mat3(ViewMatrix) * N; - result = CLOSURE_DEFAULT; - result.ssr_normal = normal_encode(vN, viewCameraVec); - result.radiance = out_refr * color.rgb; -} - -void node_ambient_occlusion( - vec4 color, float distance, vec3 normal, out vec4 result_color, out float result_ao) -{ - vec3 bent_normal; - vec4 rand = texelFetch(utilTex, ivec3(ivec2(gl_FragCoord.xy) % LUT_SIZE, 2.0), 0); - result_ao = occlusion_compute(normalize(normal), viewPosition, 1.0, rand, bent_normal); - result_color = result_ao * color; -} - -void node_wireframe(float size, vec2 barycentric, vec3 barycentric_dist, out float fac) -{ - vec3 barys = barycentric.xyy; - barys.z = 1.0 - barycentric.x - barycentric.y; - - size *= 0.5; - vec3 s = step(-size, -barys * barycentric_dist); - - fac = max(s.x, max(s.y, s.z)); -} - -void node_wireframe_screenspace(float size, vec2 barycentric, out float fac) -{ - vec3 barys = barycentric.xyy; - barys.z = 1.0 - barycentric.x - barycentric.y; - - size *= (1.0 / 3.0); - vec3 dx = dFdx(barys); - vec3 dy = dFdy(barys); - vec3 deltas = sqrt(dx * dx + dy * dy); - - vec3 s = step(-deltas * size, -barys); - - fac = max(s.x, max(s.y, s.z)); -} - -#else /* VOLUMETRICS */ - -/* Stub all bsdf functions not compatible with volumetrics. */ -# define node_bsdf_diffuse -# define node_bsdf_glossy -# define node_bsdf_anisotropic -# define node_bsdf_glass -# define node_bsdf_toon -# define node_bsdf_principled -# define node_bsdf_principled_dielectric -# define node_bsdf_principled_metallic -# define node_bsdf_principled_clearcoat -# define node_bsdf_principled_subsurface -# define node_bsdf_principled_glass -# define node_bsdf_translucent -# define node_bsdf_transparent -# define node_bsdf_velvet -# define node_subsurface_scattering -# define node_bsdf_refraction -# define node_ambient_occlusion -# define node_wireframe -# define node_wireframe_screenspace - -#endif /* VOLUMETRICS */ - -/* emission */ - -void node_emission(vec4 color, float strength, vec3 vN, out Closure result) -{ - result = CLOSURE_DEFAULT; -#ifndef VOLUMETRICS - result.radiance = color.rgb * strength; - result.ssr_normal = normal_encode(vN, viewCameraVec); -#else - result.emission = color.rgb * strength; -#endif -} - -/* background */ - -void node_tex_environment_texco(vec3 viewvec, out vec3 worldvec) -{ -#ifdef MESH_SHADER - worldvec = worldPosition; -#else - vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); - vec4 co_homogenous = (ProjectionMatrixInverse * v); - - vec3 co = co_homogenous.xyz / co_homogenous.w; -# if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE) - worldvec = mat3(ViewMatrixInverse) * co; -# else - worldvec = mat3(ModelMatrixInverse) * (mat3(ViewMatrixInverse) * co); -# endif -#endif -} - -void node_background(vec4 color, float strength, out Closure result) -{ -#ifndef VOLUMETRICS - color *= strength; - result = CLOSURE_DEFAULT; - result.radiance = color.rgb; - result.transmittance = vec3(0.0); -#else - result = CLOSURE_DEFAULT; -#endif -} - -/* volumes */ - -void node_volume_scatter(vec4 color, float density, float anisotropy, out Closure result) -{ -#ifdef VOLUMETRICS - result = Closure(vec3(0.0), color.rgb * density, vec3(0.0), anisotropy); -#else - result = CLOSURE_DEFAULT; -#endif -} - -void node_volume_absorption(vec4 color, float density, out Closure result) -{ -#ifdef VOLUMETRICS - result = Closure((1.0 - color.rgb) * density, vec3(0.0), vec3(0.0), 0.0); -#else - result = CLOSURE_DEFAULT; -#endif -} - -void node_blackbody(float temperature, sampler1DArray spectrummap, float layer, out vec4 color) -{ - if (temperature >= 12000.0) { - color = vec4(0.826270103, 0.994478524, 1.56626022, 1.0); - } - else if (temperature < 965.0) { - color = vec4(4.70366907, 0.0, 0.0, 1.0); - } - else { - float t = (temperature - 965.0) / (12000.0 - 965.0); - color = vec4(texture(spectrummap, vec2(t, layer)).rgb, 1.0); - } -} - -void node_volume_principled(vec4 color, - float density, - float anisotropy, - vec4 absorption_color, - float emission_strength, - vec4 emission_color, - float blackbody_intensity, - vec4 blackbody_tint, - float temperature, - float density_attribute, - vec4 color_attribute, - float temperature_attribute, - sampler1DArray spectrummap, - float layer, - out Closure result) -{ -#ifdef VOLUMETRICS - vec3 absorption_coeff = vec3(0.0); - vec3 scatter_coeff = vec3(0.0); - vec3 emission_coeff = vec3(0.0); - - /* Compute density. */ - density = max(density, 0.0); - - if (density > 1e-5) { - density = max(density * density_attribute, 0.0); - } - - if (density > 1e-5) { - /* Compute scattering and absorption coefficients. */ - vec3 scatter_color = color.rgb * color_attribute.rgb; - - scatter_coeff = scatter_color * density; - absorption_color.rgb = sqrt(max(absorption_color.rgb, 0.0)); - absorption_coeff = max(1.0 - scatter_color, 0.0) * max(1.0 - absorption_color.rgb, 0.0) * - density; - } - - /* Compute emission. */ - emission_strength = max(emission_strength, 0.0); - - if (emission_strength > 1e-5) { - emission_coeff += emission_strength * emission_color.rgb; - } - - if (blackbody_intensity > 1e-3) { - /* Add temperature from attribute. */ - float T = max(temperature * max(temperature_attribute, 0.0), 0.0); - - /* Stefan-Boltzman law. */ - float T2 = T * T; - float T4 = T2 * T2; - float sigma = 5.670373e-8 * 1e-6 / M_PI; - float intensity = sigma * mix(1.0, T4, blackbody_intensity); - - if (intensity > 1e-5) { - vec4 bb; - node_blackbody(T, spectrummap, layer, bb); - emission_coeff += bb.rgb * blackbody_tint.rgb * intensity; - } - } - - result = Closure(absorption_coeff, scatter_coeff, emission_coeff, anisotropy); -#else - result = CLOSURE_DEFAULT; -#endif -} - -void node_holdout(out Closure result) -{ - result = CLOSURE_DEFAULT; -#ifndef VOLUMETRICS - result.holdout = 1.0; - result.flag = CLOSURE_HOLDOUT_FLAG; -#endif -} - -/* closures */ - -void node_mix_shader(float fac, Closure shader1, Closure shader2, out Closure shader) -{ - shader = closure_mix(shader1, shader2, fac); -} - -void node_add_shader(Closure shader1, Closure shader2, out Closure shader) -{ - shader = closure_add(shader1, shader2); -} - -/* fresnel */ - -void node_fresnel(float ior, vec3 N, vec3 I, out float result) -{ - N = normalize(N); - /* handle perspective/orthographic */ - vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); - - float eta = max(ior, 0.00001); - result = fresnel_dielectric(I_view, N, (gl_FrontFacing) ? eta : 1.0 / eta); -} - -/* layer_weight */ - -void node_layer_weight(float blend, vec3 N, vec3 I, out float fresnel, out float facing) -{ - N = normalize(N); - - /* fresnel */ - float eta = max(1.0 - blend, 0.00001); - vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); - - fresnel = fresnel_dielectric(I_view, N, (gl_FrontFacing) ? 1.0 / eta : eta); - - /* facing */ - facing = abs(dot(I_view, N)); - if (blend != 0.5) { - blend = clamp(blend, 0.0, 0.99999); - blend = (blend < 0.5) ? 2.0 * blend : 0.5 / (1.0 - blend); - facing = pow(facing, blend); - } - facing = 1.0 - facing; -} - -/* gamma */ - -void node_gamma(vec4 col, float gamma, out vec4 outcol) -{ - outcol = col; - - if (col.r > 0.0) { - outcol.r = compatible_pow(col.r, gamma); - } - if (col.g > 0.0) { - outcol.g = compatible_pow(col.g, gamma); - } - if (col.b > 0.0) { - outcol.b = compatible_pow(col.b, gamma); - } -} - -/* geometry */ - -void node_attribute_volume_density(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf) -{ -#if defined(MESH_SHADER) && defined(VOLUMETRICS) - vec3 cos = volumeObjectLocalCoord; -#else - vec3 cos = vec3(0.0); -#endif - outvec = texture(tex, cos).aaa; - outcol = vec4(outvec, 1.0); - outf = avg(outvec); -} - -uniform vec3 volumeColor = vec3(1.0); - -void node_attribute_volume_color(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf) -{ -#if defined(MESH_SHADER) && defined(VOLUMETRICS) - vec3 cos = volumeObjectLocalCoord; -#else - vec3 cos = vec3(0.0); -#endif - - vec4 value = texture(tex, cos).rgba; - /* Density is premultiplied for interpolation, divide it out here. */ - if (value.a > 1e-8) { - value.rgb /= value.a; - } - - outvec = value.rgb * volumeColor; - outcol = vec4(outvec, 1.0); - outf = avg(outvec); -} - -void node_attribute_volume_flame(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf) -{ -#if defined(MESH_SHADER) && defined(VOLUMETRICS) - vec3 cos = volumeObjectLocalCoord; -#else - vec3 cos = vec3(0.0); -#endif - outf = texture(tex, cos).r; - outvec = vec3(outf, outf, outf); - outcol = vec4(outf, outf, outf, 1.0); -} - -void node_attribute_volume_temperature( - sampler3D tex, vec2 temperature, out vec4 outcol, out vec3 outvec, out float outf) -{ -#if defined(MESH_SHADER) && defined(VOLUMETRICS) - vec3 cos = volumeObjectLocalCoord; -#else - vec3 cos = vec3(0.0); -#endif - float flame = texture(tex, cos).r; - - outf = (flame > 0.01) ? temperature.x + flame * (temperature.y - temperature.x) : 0.0; - outvec = vec3(outf, outf, outf); - outcol = vec4(outf, outf, outf, 1.0); -} - -void node_attribute(vec3 attr, out vec4 outcol, out vec3 outvec, out float outf) -{ - outcol = vec4(attr, 1.0); - outvec = attr; - outf = avg(attr); -} - -void node_uvmap(vec3 attr_uv, out vec3 outvec) -{ - outvec = attr_uv; -} - -void tangent_orco_x(vec3 orco_in, out vec3 orco_out) -{ - orco_out = orco_in.xzy * vec3(0.0, -0.5, 0.5) + vec3(0.0, 0.25, -0.25); -} - -void tangent_orco_y(vec3 orco_in, out vec3 orco_out) -{ - orco_out = orco_in.zyx * vec3(-0.5, 0.0, 0.5) + vec3(0.25, 0.0, -0.25); -} - -void tangent_orco_z(vec3 orco_in, out vec3 orco_out) -{ - orco_out = orco_in.yxz * vec3(-0.5, 0.5, 0.0) + vec3(0.25, -0.25, 0.0); -} - -void node_tangentmap(vec4 attr_tangent, out vec3 tangent) -{ - tangent = normalize(attr_tangent.xyz); -} - -void node_tangent(vec3 N, vec3 orco, mat4 objmat, out vec3 T) -{ - T = (objmat * vec4(orco, 0.0)).xyz; - T = cross(N, normalize(cross(T, N))); -} - -void node_geometry(vec3 I, - vec3 N, - vec3 orco, - mat4 objmat, - mat4 toworld, - vec2 barycentric, - out vec3 position, - out vec3 normal, - out vec3 tangent, - out vec3 true_normal, - out vec3 incoming, - out vec3 parametric, - out float backfacing, - out float pointiness) -{ - /* handle perspective/orthographic */ - vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); - incoming = -(toworld * vec4(I_view, 0.0)).xyz; - -#if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE) - position = -incoming; - true_normal = normal = incoming; - tangent = parametric = vec3(0.0); - vec3(0.0); - backfacing = 0.0; - pointiness = 0.0; -#else - - position = worldPosition; -# ifndef VOLUMETRICS - normal = normalize(N); - vec3 B = dFdx(worldPosition); - vec3 T = dFdy(worldPosition); - true_normal = normalize(cross(B, T)); -# else - normal = (toworld * vec4(N, 0.0)).xyz; - true_normal = normal; -# endif - tangent_orco_z(orco, orco); - node_tangent(N, orco, objmat, tangent); - - parametric = vec3(barycentric, 0.0); - backfacing = (gl_FrontFacing) ? 0.0 : 1.0; - pointiness = 0.5; -#endif -} - -void generated_texco(vec3 I, vec3 attr_orco, out vec3 generated) -{ - vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); - vec4 co_homogenous = (ProjectionMatrixInverse * v); - vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0); - co.xyz = normalize(co.xyz); -#if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE) - generated = (ViewMatrixInverse * co).xyz; -#else - generated_from_orco(attr_orco, generated); -#endif -} - -void node_tex_coord(vec3 I, - vec3 wN, - mat4 obmatinv, - vec4 camerafac, - vec3 attr_orco, - vec3 attr_uv, - out vec3 generated, - out vec3 normal, - out vec3 uv, - out vec3 object, - out vec3 camera, - out vec3 window, - out vec3 reflection) -{ - generated = attr_orco; - normal = normalize(normal_world_to_object(wN)); - uv = attr_uv; - object = (obmatinv * (ViewMatrixInverse * vec4(I, 1.0))).xyz; - camera = vec3(I.xy, -I.z); - vec4 projvec = ProjectionMatrix * vec4(I, 1.0); - window = vec3(mtex_2d_mapping(projvec.xyz / projvec.w).xy * camerafac.xy + camerafac.zw, 0.0); - reflection = -reflect(cameraVec, normalize(wN)); -} - -void node_tex_coord_background(vec3 I, - vec3 N, - mat4 obmatinv, - vec4 camerafac, - vec3 attr_orco, - vec3 attr_uv, - out vec3 generated, - out vec3 normal, - out vec3 uv, - out vec3 object, - out vec3 camera, - out vec3 window, - out vec3 reflection) -{ - vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); - vec4 co_homogenous = (ProjectionMatrixInverse * v); - - vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0); - - co = normalize(co); - - vec3 coords = (ViewMatrixInverse * co).xyz; - - generated = coords; - normal = -coords; - uv = vec3(attr_uv.xy, 0.0); - object = (obmatinv * vec4(coords, 1.0)).xyz; - - camera = vec3(co.xy, -co.z); - window = vec3(mtex_2d_mapping(I).xy * camerafac.xy + camerafac.zw, 0.0); - - reflection = -coords; -} - -#if defined(WORLD_BACKGROUND) || (defined(PROBE_CAPTURE) && !defined(MESH_SHADER)) -# define node_tex_coord node_tex_coord_background -#endif - -/* textures */ - -float calc_gradient(vec3 p, int gradient_type) -{ - float x, y, z; - x = p.x; - y = p.y; - z = p.z; - if (gradient_type == 0) { /* linear */ - return x; - } - else if (gradient_type == 1) { /* quadratic */ - float r = max(x, 0.0); - return r * r; - } - else if (gradient_type == 2) { /* easing */ - float r = min(max(x, 0.0), 1.0); - float t = r * r; - return (3.0 * t - 2.0 * t * r); - } - else if (gradient_type == 3) { /* diagonal */ - return (x + y) * 0.5; - } - else if (gradient_type == 4) { /* radial */ - return atan(y, x) / (M_PI * 2) + 0.5; - } - else { - /* Bias a little bit for the case where p is a unit length vector, - * to get exactly zero instead of a small random value depending - * on float precision. */ - float r = max(0.999999 - sqrt(x * x + y * y + z * z), 0.0); - if (gradient_type == 5) { /* quadratic sphere */ - return r * r; - } - else if (gradient_type == 6) { /* sphere */ - return r; - } - } - return 0.0; -} - -void node_tex_gradient(vec3 co, float gradient_type, out vec4 color, out float fac) -{ - float f = calc_gradient(co, int(gradient_type)); - f = clamp(f, 0.0, 1.0); - - color = vec4(f, f, f, 1.0); - fac = f; -} - -void node_tex_checker( - vec3 co, vec4 color1, vec4 color2, float scale, out vec4 color, out float fac) -{ - vec3 p = co * scale; - - /* Prevent precision issues on unit coordinates. */ - p = (p + 0.000001) * 0.999999; - - int xi = int(abs(floor(p.x))); - int yi = int(abs(floor(p.y))); - int zi = int(abs(floor(p.z))); - - bool check = ((mod(xi, 2) == mod(yi, 2)) == bool(mod(zi, 2))); - - color = check ? color1 : color2; - fac = check ? 1.0 : 0.0; -} - -vec2 calc_brick_texture(vec3 p, - float mortar_size, - float mortar_smooth, - float bias, - float brick_width, - float row_height, - float offset_amount, - int offset_frequency, - float squash_amount, - int squash_frequency) -{ - int bricknum, rownum; - float offset = 0.0; - float x, y; - - rownum = floor_to_int(p.y / row_height); - - if (offset_frequency != 0 && squash_frequency != 0) { - brick_width *= (rownum % squash_frequency != 0) ? 1.0 : squash_amount; /* squash */ - offset = (rownum % offset_frequency != 0) ? 0.0 : (brick_width * offset_amount); /* offset */ - } - - bricknum = floor_to_int((p.x + offset) / brick_width); - - x = (p.x + offset) - brick_width * bricknum; - y = p.y - row_height * rownum; - - float tint = clamp((integer_noise((rownum << 16) + (bricknum & 0xFFFF)) + bias), 0.0, 1.0); - - float min_dist = min(min(x, y), min(brick_width - x, row_height - y)); - if (min_dist >= mortar_size) { - return vec2(tint, 0.0); - } - else if (mortar_smooth == 0.0) { - return vec2(tint, 1.0); - } - else { - min_dist = 1.0 - min_dist / mortar_size; - return vec2(tint, smoothstep(0.0, mortar_smooth, min_dist)); - } -} - -void node_tex_brick(vec3 co, - vec4 color1, - vec4 color2, - vec4 mortar, - float scale, - float mortar_size, - float mortar_smooth, - float bias, - float brick_width, - float row_height, - float offset_amount, - float offset_frequency, - float squash_amount, - float squash_frequency, - out vec4 color, - out float fac) -{ - vec2 f2 = calc_brick_texture(co * scale, - mortar_size, - mortar_smooth, - bias, - brick_width, - row_height, - offset_amount, - int(offset_frequency), - squash_amount, - int(squash_frequency)); - float tint = f2.x; - float f = f2.y; - if (f != 1.0) { - float facm = 1.0 - tint; - color1 = facm * color1 + tint * color2; - } - color = mix(color1, mortar, f); - fac = f; -} - -void node_tex_clouds(vec3 co, float size, out vec4 color, out float fac) -{ - color = vec4(1.0); - fac = 1.0; -} - -void node_tex_environment_equirectangular(vec3 co, float clamp_size, sampler2D ima, out vec3 uv) -{ - vec3 nco = normalize(co); - uv.x = -atan(nco.y, nco.x) / (2.0 * M_PI) + 0.5; - uv.y = atan(nco.z, hypot(nco.x, nco.y)) / M_PI + 0.5; - - /* Fix pole bleeding */ - float half_height = clamp_size / float(textureSize(ima, 0).y); - uv.y = clamp(uv.y, half_height, 1.0 - half_height); - uv.z = 0.0; -} - -void node_tex_environment_mirror_ball(vec3 co, out vec3 uv) -{ - vec3 nco = normalize(co); - nco.y -= 1.0; - - float div = 2.0 * sqrt(max(-0.5 * nco.y, 0.0)); - nco /= max(1e-8, div); - - uv = 0.5 * nco.xzz + 0.5; -} - -void node_tex_environment_empty(vec3 co, out vec4 color) -{ - color = vec4(1.0, 0.0, 1.0, 1.0); -} - -/* 16bits floats limits. Higher/Lower values produce +/-inf. */ -#define safe_color(a) (clamp(a, -65520.0, 65520.0)) - -void tex_color_alpha_clear(vec4 color, out vec4 result) -{ - result = vec4(color.rgb, 1.0); -} - -void tex_color_alpha_premultiply(vec4 color, out vec4 result) -{ - result = vec4(color.rgb * color.a, 1.0); -} - -void tex_color_alpha_unpremultiply(vec4 color, out vec4 result) -{ - if (color.a == 0.0 || color.a == 1.0) { - result = vec4(color.rgb, 1.0); - } - else { - result = vec4(color.rgb / color.a, 1.0); - } -} - -void node_tex_image_linear(vec3 co, sampler2D ima, out vec4 color, out float alpha) -{ - color = safe_color(texture(ima, co.xy)); - alpha = color.a; -} - -void node_tex_image_linear_no_mip(vec3 co, sampler2D ima, out vec4 color, out float alpha) -{ - color = safe_color(textureLod(ima, co.xy, 0.0)); - alpha = color.a; -} - -void node_tex_image_nearest(vec3 co, sampler2D ima, out vec4 color, out float alpha) -{ - ivec2 pix = ivec2(fract(co.xy) * textureSize(ima, 0).xy); - color = safe_color(texelFetch(ima, pix, 0)); - alpha = color.a; -} - -/* @arg f: signed distance to texel center. */ -void cubic_bspline_coefs(vec2 f, out vec2 w0, out vec2 w1, out vec2 w2, out vec2 w3) -{ - vec2 f2 = f * f; - vec2 f3 = f2 * f; - /* Bspline coefs (optimized) */ - w3 = f3 / 6.0; - w0 = -w3 + f2 * 0.5 - f * 0.5 + 1.0 / 6.0; - w1 = f3 * 0.5 - f2 * 1.0 + 2.0 / 3.0; - w2 = 1.0 - w0 - w1 - w3; -} - -void node_tex_image_cubic_ex( - vec3 co, sampler2D ima, float do_extend, out vec4 color, out float alpha) -{ - vec2 tex_size = vec2(textureSize(ima, 0).xy); - - co.xy *= tex_size; - /* texel center */ - vec2 tc = floor(co.xy - 0.5) + 0.5; - vec2 w0, w1, w2, w3; - cubic_bspline_coefs(co.xy - tc, w0, w1, w2, w3); - -#if 1 /* Optimized version using 4 filtered tap. */ - vec2 s0 = w0 + w1; - vec2 s1 = w2 + w3; - - vec2 f0 = w1 / (w0 + w1); - vec2 f1 = w3 / (w2 + w3); - - vec4 final_co; - final_co.xy = tc - 1.0 + f0; - final_co.zw = tc + 1.0 + f1; - - if (do_extend == 1.0) { - final_co = clamp(final_co, vec4(0.5), tex_size.xyxy - 0.5); - } - final_co /= tex_size.xyxy; - - color = safe_color(textureLod(ima, final_co.xy, 0.0)) * s0.x * s0.y; - color += safe_color(textureLod(ima, final_co.zy, 0.0)) * s1.x * s0.y; - color += safe_color(textureLod(ima, final_co.xw, 0.0)) * s0.x * s1.y; - color += safe_color(textureLod(ima, final_co.zw, 0.0)) * s1.x * s1.y; - -#else /* Reference bruteforce 16 tap. */ - color = texelFetch(ima, ivec2(tc + vec2(-1.0, -1.0)), 0) * w0.x * w0.y; - color += texelFetch(ima, ivec2(tc + vec2(0.0, -1.0)), 0) * w1.x * w0.y; - color += texelFetch(ima, ivec2(tc + vec2(1.0, -1.0)), 0) * w2.x * w0.y; - color += texelFetch(ima, ivec2(tc + vec2(2.0, -1.0)), 0) * w3.x * w0.y; - - color += texelFetch(ima, ivec2(tc + vec2(-1.0, 0.0)), 0) * w0.x * w1.y; - color += texelFetch(ima, ivec2(tc + vec2(0.0, 0.0)), 0) * w1.x * w1.y; - color += texelFetch(ima, ivec2(tc + vec2(1.0, 0.0)), 0) * w2.x * w1.y; - color += texelFetch(ima, ivec2(tc + vec2(2.0, 0.0)), 0) * w3.x * w1.y; - - color += texelFetch(ima, ivec2(tc + vec2(-1.0, 1.0)), 0) * w0.x * w2.y; - color += texelFetch(ima, ivec2(tc + vec2(0.0, 1.0)), 0) * w1.x * w2.y; - color += texelFetch(ima, ivec2(tc + vec2(1.0, 1.0)), 0) * w2.x * w2.y; - color += texelFetch(ima, ivec2(tc + vec2(2.0, 1.0)), 0) * w3.x * w2.y; - - color += texelFetch(ima, ivec2(tc + vec2(-1.0, 2.0)), 0) * w0.x * w3.y; - color += texelFetch(ima, ivec2(tc + vec2(0.0, 2.0)), 0) * w1.x * w3.y; - color += texelFetch(ima, ivec2(tc + vec2(1.0, 2.0)), 0) * w2.x * w3.y; - color += texelFetch(ima, ivec2(tc + vec2(2.0, 2.0)), 0) * w3.x * w3.y; -#endif - - alpha = color.a; -} - -void node_tex_image_cubic(vec3 co, sampler2D ima, out vec4 color, out float alpha) -{ - node_tex_image_cubic_ex(co, ima, 0.0, color, alpha); -} - -void node_tex_image_cubic_extend(vec3 co, sampler2D ima, out vec4 color, out float alpha) -{ - node_tex_image_cubic_ex(co, ima, 1.0, color, alpha); -} - -void node_tex_image_smart(vec3 co, sampler2D ima, out vec4 color, out float alpha) -{ - /* use cubic for now */ - node_tex_image_cubic_ex(co, ima, 0.0, color, alpha); -} - -void tex_box_sample_linear( - vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3) -{ - /* X projection */ - vec2 uv = texco.yz; - if (N.x < 0.0) { - uv.x = 1.0 - uv.x; - } - color1 = texture(ima, uv); - /* Y projection */ - uv = texco.xz; - if (N.y > 0.0) { - uv.x = 1.0 - uv.x; - } - color2 = texture(ima, uv); - /* Z projection */ - uv = texco.yx; - if (N.z > 0.0) { - uv.x = 1.0 - uv.x; - } - color3 = texture(ima, uv); -} - -void tex_box_sample_nearest( - vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3) -{ - /* X projection */ - vec2 uv = texco.yz; - if (N.x < 0.0) { - uv.x = 1.0 - uv.x; - } - ivec2 pix = ivec2(uv.xy * textureSize(ima, 0).xy); - color1 = texelFetch(ima, pix, 0); - /* Y projection */ - uv = texco.xz; - if (N.y > 0.0) { - uv.x = 1.0 - uv.x; - } - pix = ivec2(uv.xy * textureSize(ima, 0).xy); - color2 = texelFetch(ima, pix, 0); - /* Z projection */ - uv = texco.yx; - if (N.z > 0.0) { - uv.x = 1.0 - uv.x; - } - pix = ivec2(uv.xy * textureSize(ima, 0).xy); - color3 = texelFetch(ima, pix, 0); -} - -void tex_box_sample_cubic( - vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3) -{ - float alpha; - /* X projection */ - vec2 uv = texco.yz; - if (N.x < 0.0) { - uv.x = 1.0 - uv.x; - } - node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color1, alpha); - /* Y projection */ - uv = texco.xz; - if (N.y > 0.0) { - uv.x = 1.0 - uv.x; - } - node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color2, alpha); - /* Z projection */ - uv = texco.yx; - if (N.z > 0.0) { - uv.x = 1.0 - uv.x; - } - node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color3, alpha); -} - -void tex_box_sample_smart( - vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3) -{ - tex_box_sample_cubic(texco, N, ima, color1, color2, color3); -} - -void node_tex_image_box(vec3 texco, - vec3 N, - vec4 color1, - vec4 color2, - vec4 color3, - sampler2D ima, - float blend, - out vec4 color, - out float alpha) -{ - /* project from direction vector to barycentric coordinates in triangles */ - N = abs(N); - N /= dot(N, vec3(1.0)); - - /* basic idea is to think of this as a triangle, each corner representing - * one of the 3 faces of the cube. in the corners we have single textures, - * in between we blend between two textures, and in the middle we a blend - * between three textures. - * - * the Nxyz values are the barycentric coordinates in an equilateral - * triangle, which in case of blending, in the middle has a smaller - * equilateral triangle where 3 textures blend. this divides things into - * 7 zones, with an if () test for each zone - * EDIT: Now there is only 4 if's. */ - - float limit = 0.5 + 0.5 * blend; - - vec3 weight; - weight = N.xyz / (N.xyx + N.yzz); - weight = clamp((weight - 0.5 * (1.0 - blend)) / max(1e-8, blend), 0.0, 1.0); - - /* test for mixes between two textures */ - if (N.z < (1.0 - limit) * (N.y + N.x)) { - weight.z = 0.0; - weight.y = 1.0 - weight.x; - } - else if (N.x < (1.0 - limit) * (N.y + N.z)) { - weight.x = 0.0; - weight.z = 1.0 - weight.y; - } - else if (N.y < (1.0 - limit) * (N.x + N.z)) { - weight.y = 0.0; - weight.x = 1.0 - weight.z; - } - else { - /* last case, we have a mix between three */ - weight = ((2.0 - limit) * N + (limit - 1.0)) / max(1e-8, blend); - } - - color = weight.x * color1 + weight.y * color2 + weight.z * color3; - alpha = color.a; -} - -void tex_clip_linear(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha) -{ - vec2 tex_size = vec2(textureSize(ima, 0).xy); - vec2 minco = min(co.xy, 1.0 - co.xy); - minco = clamp(minco * tex_size + 0.5, 0.0, 1.0); - float fac = minco.x * minco.y; - - color = mix(vec4(0.0), icolor, fac); - alpha = color.a; -} - -void tex_clip_nearest(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha) -{ - vec4 minco = vec4(co.xy, 1.0 - co.xy); - color = (any(lessThan(minco, vec4(0.0)))) ? vec4(0.0) : icolor; - alpha = color.a; -} - -void tex_clip_cubic(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha) -{ - vec2 tex_size = vec2(textureSize(ima, 0).xy); - - co.xy *= tex_size; - /* texel center */ - vec2 tc = floor(co.xy - 0.5) + 0.5; - vec2 w0, w1, w2, w3; - cubic_bspline_coefs(co.xy - tc, w0, w1, w2, w3); - - /* TODO Optimize this part. I'm sure there is a smarter way to do that. - * Could do that when sampling? */ -#define CLIP_CUBIC_SAMPLE(samp, size) \ - (float(all(greaterThan(samp, vec2(-0.5)))) * float(all(lessThan(ivec2(samp), itex_size)))) - ivec2 itex_size = textureSize(ima, 0).xy; - float fac; - fac = CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, -1.0), itex_size) * w0.x * w0.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, -1.0), itex_size) * w1.x * w0.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, -1.0), itex_size) * w2.x * w0.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, -1.0), itex_size) * w3.x * w0.y; - - fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 0.0), itex_size) * w0.x * w1.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, 0.0), itex_size) * w1.x * w1.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, 0.0), itex_size) * w2.x * w1.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, 0.0), itex_size) * w3.x * w1.y; - - fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 1.0), itex_size) * w0.x * w2.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, 1.0), itex_size) * w1.x * w2.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, 1.0), itex_size) * w2.x * w2.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, 1.0), itex_size) * w3.x * w2.y; - - fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 2.0), itex_size) * w0.x * w3.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, 2.0), itex_size) * w1.x * w3.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, 2.0), itex_size) * w2.x * w3.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, 2.0), itex_size) * w3.x * w3.y; -#undef CLIP_CUBIC_SAMPLE - - color = mix(vec4(0.0), icolor, fac); - alpha = color.a; -} - -void tex_clip_smart(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha) -{ - tex_clip_cubic(co, ima, icolor, color, alpha); -} - -void node_tex_image_empty(vec3 co, out vec4 color, out float alpha) -{ - color = vec4(0.0); - alpha = 0.0; -} - -void node_tex_magic( - vec3 co, float scale, float distortion, float depth, out vec4 color, out float fac) -{ - vec3 p = co * scale; - float x = sin((p.x + p.y + p.z) * 5.0); - float y = cos((-p.x + p.y - p.z) * 5.0); - float z = -cos((-p.x - p.y + p.z) * 5.0); - - if (depth > 0) { - x *= distortion; - y *= distortion; - z *= distortion; - y = -cos(x - y + z); - y *= distortion; - if (depth > 1) { - x = cos(x - y - z); - x *= distortion; - if (depth > 2) { - z = sin(-x - y - z); - z *= distortion; - if (depth > 3) { - x = -cos(-x + y - z); - x *= distortion; - if (depth > 4) { - y = -sin(-x + y + z); - y *= distortion; - if (depth > 5) { - y = -cos(-x + y + z); - y *= distortion; - if (depth > 6) { - x = cos(x + y + z); - x *= distortion; - if (depth > 7) { - z = sin(x + y - z); - z *= distortion; - if (depth > 8) { - x = -cos(-x - y + z); - x *= distortion; - if (depth > 9) { - y = -sin(x - y + z); - y *= distortion; - } - } - } - } - } - } - } - } - } - } - if (distortion != 0.0) { - distortion *= 2.0; - x /= distortion; - y /= distortion; - z /= distortion; - } - - color = vec4(0.5 - x, 0.5 - y, 0.5 - z, 1.0); - fac = (color.x + color.y + color.z) / 3.0; -} - -float noise_fade(float t) -{ - return t * t * t * (t * (t * 6.0 - 15.0) + 10.0); -} - -float noise_scale3(float result) -{ - return 0.9820 * result; -} - -float noise_nerp(float t, float a, float b) -{ - return (1.0 - t) * a + t * b; -} - -float noise_grad(uint hash, float x, float y, float z) -{ - uint h = hash & 15u; - float u = h < 8u ? x : y; - float vt = ((h == 12u) || (h == 14u)) ? x : z; - float v = h < 4u ? y : vt; - return (((h & 1u) != 0u) ? -u : u) + (((h & 2u) != 0u) ? -v : v); -} - -float noise_perlin(float x, float y, float z) -{ - int X; - float fx = floorfrac(x, X); - int Y; - float fy = floorfrac(y, Y); - int Z; - float fz = floorfrac(z, Z); - - float u = noise_fade(fx); - float v = noise_fade(fy); - float w = noise_fade(fz); - - float noise_u[2], noise_v[2]; - - noise_u[0] = noise_nerp( - u, noise_grad(hash(X, Y, Z), fx, fy, fz), noise_grad(hash(X + 1, Y, Z), fx - 1.0, fy, fz)); - - noise_u[1] = noise_nerp(u, - noise_grad(hash(X, Y + 1, Z), fx, fy - 1.0, fz), - noise_grad(hash(X + 1, Y + 1, Z), fx - 1.0, fy - 1.0, fz)); - - noise_v[0] = noise_nerp(v, noise_u[0], noise_u[1]); - - noise_u[0] = noise_nerp(u, - noise_grad(hash(X, Y, Z + 1), fx, fy, fz - 1.0), - noise_grad(hash(X + 1, Y, Z + 1), fx - 1.0, fy, fz - 1.0)); - - noise_u[1] = noise_nerp(u, - noise_grad(hash(X, Y + 1, Z + 1), fx, fy - 1.0, fz - 1.0), - noise_grad(hash(X + 1, Y + 1, Z + 1), fx - 1.0, fy - 1.0, fz - 1.0)); - - noise_v[1] = noise_nerp(v, noise_u[0], noise_u[1]); - - float r = noise_scale3(noise_nerp(w, noise_v[0], noise_v[1])); - - return (isinf(r)) ? 0.0 : r; -} - -float noise(vec3 p) -{ - return 0.5 * noise_perlin(p.x, p.y, p.z) + 0.5; -} - -float snoise(vec3 p) -{ - return noise_perlin(p.x, p.y, p.z); -} - -float noise_turbulence(vec3 p, float octaves, int hard) -{ - float fscale = 1.0; - float amp = 1.0; - float sum = 0.0; - octaves = clamp(octaves, 0.0, 16.0); - int n = int(octaves); - for (int i = 0; i <= n; i++) { - float t = noise(fscale * p); - if (hard != 0) { - t = abs(2.0 * t - 1.0); - } - sum += t * amp; - amp *= 0.5; - fscale *= 2.0; - } - float rmd = octaves - floor(octaves); - if (rmd != 0.0) { - float t = noise(fscale * p); - if (hard != 0) { - t = abs(2.0 * t - 1.0); - } - float sum2 = sum + t * amp; - sum *= (float(1 << n) / float((1 << (n + 1)) - 1)); - sum2 *= (float(1 << (n + 1)) / float((1 << (n + 2)) - 1)); - return (1.0 - rmd) * sum + rmd * sum2; - } - else { - sum *= (float(1 << n) / float((1 << (n + 1)) - 1)); - return sum; - } -} - -void node_tex_noise( - vec3 co, float scale, float detail, float distortion, out vec4 color, out float fac) -{ - vec3 p = co * scale; - int hard = 0; - if (distortion != 0.0) { - vec3 r, offset = vec3(13.5, 13.5, 13.5); - r.x = noise(p + offset) * distortion; - r.y = noise(p) * distortion; - r.z = noise(p - offset) * distortion; - p += r; - } - - fac = noise_turbulence(p, detail, hard); - color = vec4(fac, - noise_turbulence(vec3(p.y, p.x, p.z), detail, hard), - noise_turbulence(vec3(p.y, p.z, p.x), detail, hard), - 1); -} - -/* Musgrave fBm - * - * H: fractal increment parameter - * lacunarity: gap between successive frequencies - * octaves: number of frequencies in the fBm - * - * from "Texturing and Modelling: A procedural approach" - */ - -float noise_musgrave_fBm(vec3 p, float H, float lacunarity, float octaves) -{ - float rmd; - float value = 0.0; - float pwr = 1.0; - float pwHL = pow(lacunarity, -H); - - for (int i = 0; i < int(octaves); i++) { - value += snoise(p) * pwr; - pwr *= pwHL; - p *= lacunarity; - } - - rmd = octaves - floor(octaves); - if (rmd != 0.0) { - value += rmd * snoise(p) * pwr; - } - - return value; -} - -/* Musgrave Multifractal - * - * H: highest fractal dimension - * lacunarity: gap between successive frequencies - * octaves: number of frequencies in the fBm - */ - -float noise_musgrave_multi_fractal(vec3 p, float H, float lacunarity, float octaves) -{ - float rmd; - float value = 1.0; - float pwr = 1.0; - float pwHL = pow(lacunarity, -H); - - for (int i = 0; i < int(octaves); i++) { - value *= (pwr * snoise(p) + 1.0); - pwr *= pwHL; - p *= lacunarity; - } - - rmd = octaves - floor(octaves); - if (rmd != 0.0) { - value *= (rmd * pwr * snoise(p) + 1.0); /* correct? */ - } - - return value; -} - -/* Musgrave Heterogeneous Terrain - * - * H: fractal dimension of the roughest area - * lacunarity: gap between successive frequencies - * octaves: number of frequencies in the fBm - * offset: raises the terrain from `sea level' - */ - -float noise_musgrave_hetero_terrain(vec3 p, float H, float lacunarity, float octaves, float offset) -{ - float value, increment, rmd; - float pwHL = pow(lacunarity, -H); - float pwr = pwHL; - - /* first unscaled octave of function; later octaves are scaled */ - value = offset + snoise(p); - p *= lacunarity; - - for (int i = 1; i < int(octaves); i++) { - increment = (snoise(p) + offset) * pwr * value; - value += increment; - pwr *= pwHL; - p *= lacunarity; - } - - rmd = octaves - floor(octaves); - if (rmd != 0.0) { - increment = (snoise(p) + offset) * pwr * value; - value += rmd * increment; - } - - return value; -} - -/* Hybrid Additive/Multiplicative Multifractal Terrain - * - * H: fractal dimension of the roughest area - * lacunarity: gap between successive frequencies - * octaves: number of frequencies in the fBm - * offset: raises the terrain from `sea level' - */ - -float noise_musgrave_hybrid_multi_fractal( - vec3 p, float H, float lacunarity, float octaves, float offset, float gain) -{ - float result, signal, weight, rmd; - float pwHL = pow(lacunarity, -H); - float pwr = pwHL; - - result = snoise(p) + offset; - weight = gain * result; - p *= lacunarity; - - for (int i = 1; (weight > 0.001f) && (i < int(octaves)); i++) { - if (weight > 1.0) { - weight = 1.0; - } - - signal = (snoise(p) + offset) * pwr; - pwr *= pwHL; - result += weight * signal; - weight *= gain * signal; - p *= lacunarity; - } - - rmd = octaves - floor(octaves); - if (rmd != 0.0) { - result += rmd * ((snoise(p) + offset) * pwr); - } - - return result; -} - -/* Ridged Multifractal Terrain - * - * H: fractal dimension of the roughest area - * lacunarity: gap between successive frequencies - * octaves: number of frequencies in the fBm - * offset: raises the terrain from `sea level' - */ - -float noise_musgrave_ridged_multi_fractal( - vec3 p, float H, float lacunarity, float octaves, float offset, float gain) -{ - float result, signal, weight; - float pwHL = pow(lacunarity, -H); - float pwr = pwHL; - - signal = offset - abs(snoise(p)); - signal *= signal; - result = signal; - weight = 1.0; - - for (int i = 1; i < int(octaves); i++) { - p *= lacunarity; - weight = clamp(signal * gain, 0.0, 1.0); - signal = offset - abs(snoise(p)); - signal *= signal; - signal *= weight; - result += signal * pwr; - pwr *= pwHL; - } - - return result; -} - -float svm_musgrave(int type, - float dimension, - float lacunarity, - float octaves, - float offset, - float intensity, - float gain, - vec3 p) -{ - if (type == 0 /* NODE_MUSGRAVE_MULTIFRACTAL */) { - return intensity * noise_musgrave_multi_fractal(p, dimension, lacunarity, octaves); - } - else if (type == 1 /* NODE_MUSGRAVE_FBM */) { - return intensity * noise_musgrave_fBm(p, dimension, lacunarity, octaves); - } - else if (type == 2 /* NODE_MUSGRAVE_HYBRID_MULTIFRACTAL */) { - return intensity * - noise_musgrave_hybrid_multi_fractal(p, dimension, lacunarity, octaves, offset, gain); - } - else if (type == 3 /* NODE_MUSGRAVE_RIDGED_MULTIFRACTAL */) { - return intensity * - noise_musgrave_ridged_multi_fractal(p, dimension, lacunarity, octaves, offset, gain); - } - else if (type == 4 /* NODE_MUSGRAVE_HETERO_TERRAIN */) { - return intensity * noise_musgrave_hetero_terrain(p, dimension, lacunarity, octaves, offset); - } - return 0.0; -} - -void node_tex_musgrave(vec3 co, - float scale, - float detail, - float dimension, - float lacunarity, - float offset, - float gain, - float type, - out vec4 color, - out float fac) -{ - fac = svm_musgrave(int(type), dimension, lacunarity, detail, offset, 1.0, gain, co *scale); - - color = vec4(fac, fac, fac, 1.0); -} - -void node_tex_sky(vec3 co, out vec4 color) -{ - color = vec4(1.0); -} - -void node_tex_voronoi(vec3 co, - float scale, - float exponent, - float coloring, - float metric, - float feature, - out vec4 color, - out float fac) -{ - vec3 p = co * scale; - int xx, yy, zz, xi, yi, zi; - vec4 da = vec4(1e10); - vec3 pa[4] = vec3[4](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0)); - - xi = floor_to_int(p[0]); - yi = floor_to_int(p[1]); - zi = floor_to_int(p[2]); - - for (xx = xi - 1; xx <= xi + 1; xx++) { - for (yy = yi - 1; yy <= yi + 1; yy++) { - for (zz = zi - 1; zz <= zi + 1; zz++) { - vec3 ip = vec3(xx, yy, zz); - vec3 vp = cellnoise_color(ip); - vec3 pd = p - (vp + ip); - - float d = 0.0; - if (metric == 0.0) { /* SHD_VORONOI_DISTANCE 0 */ - d = dot(pd, pd); - } - else if (metric == 1.0) { /* SHD_VORONOI_MANHATTAN 1 */ - d = abs(pd[0]) + abs(pd[1]) + abs(pd[2]); - } - else if (metric == 2.0) { /* SHD_VORONOI_CHEBYCHEV 2 */ - d = max(abs(pd[0]), max(abs(pd[1]), abs(pd[2]))); - } - else if (metric == 3.0) { /* SHD_VORONOI_MINKOWSKI 3 */ - d = pow(pow(abs(pd[0]), exponent) + pow(abs(pd[1]), exponent) + - pow(abs(pd[2]), exponent), - 1.0 / exponent); - } - - vp += vec3(xx, yy, zz); - if (d < da[0]) { - da.yzw = da.xyz; - da[0] = d; - - pa[3] = pa[2]; - pa[2] = pa[1]; - pa[1] = pa[0]; - pa[0] = vp; - } - else if (d < da[1]) { - da.zw = da.yz; - da[1] = d; - - pa[3] = pa[2]; - pa[2] = pa[1]; - pa[1] = vp; - } - else if (d < da[2]) { - da[3] = da[2]; - da[2] = d; - - pa[3] = pa[2]; - pa[2] = vp; - } - else if (d < da[3]) { - da[3] = d; - pa[3] = vp; - } - } - } - } - - if (coloring == 0.0) { - /* Intensity output */ - if (feature == 0.0) { /* F1 */ - fac = abs(da[0]); - } - else if (feature == 1.0) { /* F2 */ - fac = abs(da[1]); - } - else if (feature == 2.0) { /* F3 */ - fac = abs(da[2]); - } - else if (feature == 3.0) { /* F4 */ - fac = abs(da[3]); - } - else if (feature == 4.0) { /* F2F1 */ - fac = abs(da[1] - da[0]); - } - color = vec4(fac, fac, fac, 1.0); - } - else { - /* Color output */ - vec3 col = vec3(fac, fac, fac); - if (feature == 0.0) { /* F1 */ - col = pa[0]; - } - else if (feature == 1.0) { /* F2 */ - col = pa[1]; - } - else if (feature == 2.0) { /* F3 */ - col = pa[2]; - } - else if (feature == 3.0) { /* F4 */ - col = pa[3]; - } - else if (feature == 4.0) { /* F2F1 */ - col = abs(pa[1] - pa[0]); - } - - color = vec4(cellnoise_color(col), 1.0); - fac = (color.x + color.y + color.z) * (1.0 / 3.0); - } -} - -float calc_wave( - vec3 p, float distortion, float detail, float detail_scale, int wave_type, int wave_profile) -{ - float n; - - if (wave_type == 0) { /* type bands */ - n = (p.x + p.y + p.z) * 10.0; - } - else { /* type rings */ - n = length(p) * 20.0; - } - - if (distortion != 0.0) { - n += distortion * noise_turbulence(p * detail_scale, detail, 0); - } - - if (wave_profile == 0) { /* profile sin */ - return 0.5 + 0.5 * sin(n); - } - else { /* profile saw */ - n /= 2.0 * M_PI; - n -= int(n); - return (n < 0.0) ? n + 1.0 : n; - } -} - -void node_tex_wave(vec3 co, - float scale, - float distortion, - float detail, - float detail_scale, - float wave_type, - float wave_profile, - out vec4 color, - out float fac) -{ - float f; - f = calc_wave(co * scale, distortion, detail, detail_scale, int(wave_type), int(wave_profile)); - - color = vec4(f, f, f, 1.0); - fac = f; -} - -/* light path */ - -void node_light_path(out float is_camera_ray, - out float is_shadow_ray, - out float is_diffuse_ray, - out float is_glossy_ray, - out float is_singular_ray, - out float is_reflection_ray, - out float is_transmission_ray, - out float ray_length, - out float ray_depth, - out float diffuse_depth, - out float glossy_depth, - out float transparent_depth, - out float transmission_depth) -{ - /* Supported. */ - is_camera_ray = (rayType == EEVEE_RAY_CAMERA) ? 1.0 : 0.0; - is_shadow_ray = (rayType == EEVEE_RAY_SHADOW) ? 1.0 : 0.0; - is_diffuse_ray = (rayType == EEVEE_RAY_DIFFUSE) ? 1.0 : 0.0; - is_glossy_ray = (rayType == EEVEE_RAY_GLOSSY) ? 1.0 : 0.0; - /* Kind of supported. */ - is_singular_ray = is_glossy_ray; - is_reflection_ray = is_glossy_ray; - is_transmission_ray = is_glossy_ray; - ray_depth = rayDepth; - diffuse_depth = (is_diffuse_ray == 1.0) ? rayDepth : 0.0; - glossy_depth = (is_glossy_ray == 1.0) ? rayDepth : 0.0; - transmission_depth = (is_transmission_ray == 1.0) ? glossy_depth : 0.0; - /* Not supported. */ - ray_length = 1.0; - transparent_depth = 0.0; -} - -void node_light_falloff( - float strength, float tsmooth, out float quadratic, out float linear, out float constant) -{ - quadratic = strength; - linear = strength; - constant = strength; -} - -void node_object_info(mat4 obmat, - vec4 info, - float mat_index, - out vec3 location, - out float object_index, - out float material_index, - out float random) -{ - location = obmat[3].xyz; - object_index = info.x; - material_index = mat_index; - random = info.z; -} - -void node_normal_map(vec4 info, vec4 tangent, vec3 normal, vec3 texnormal, out vec3 outnormal) -{ - if (all(equal(tangent, vec4(0.0, 0.0, 0.0, 1.0)))) { - outnormal = normal; - return; - } - tangent *= (gl_FrontFacing ? 1.0 : -1.0); - vec3 B = tangent.w * cross(normal, tangent.xyz) * info.w; - - outnormal = texnormal.x * tangent.xyz + texnormal.y * B + texnormal.z * normal; - outnormal = normalize(outnormal); -} - -void node_bump( - float strength, float dist, float height, vec3 N, vec3 surf_pos, float invert, out vec3 result) -{ - N = mat3(ViewMatrix) * normalize(N); - dist *= gl_FrontFacing ? invert : -invert; - - vec3 dPdx = dFdx(surf_pos); - vec3 dPdy = dFdy(surf_pos); - - /* Get surface tangents from normal. */ - vec3 Rx = cross(dPdy, N); - vec3 Ry = cross(N, dPdx); - - /* Compute surface gradient and determinant. */ - float det = dot(dPdx, Rx); - - float dHdx = dFdx(height); - float dHdy = dFdy(height); - vec3 surfgrad = dHdx * Rx + dHdy * Ry; - - strength = max(strength, 0.0); - - result = normalize(abs(det) * N - dist * sign(det) * surfgrad); - result = normalize(mix(N, result, strength)); - - result = mat3(ViewMatrixInverse) * result; -} - -void node_bevel(float radius, vec3 N, out vec3 result) -{ - result = N; -} - -void node_hair_info(out float is_strand, - out float intercept, - out float thickness, - out vec3 tangent, - out float random) -{ -#ifdef HAIR_SHADER - is_strand = 1.0; - intercept = hairTime; - thickness = hairThickness; - tangent = normalize(worldNormal); - random = wang_hash_noise( - uint(hairStrandID)); /* TODO: could be precomputed per strand instead. */ -#else - is_strand = 0.0; - intercept = 0.0; - thickness = 0.0; - tangent = vec3(1.0); - random = 0.0; -#endif -} - -void node_displacement_object( - float height, float midlevel, float scale, vec3 N, mat4 obmat, out vec3 result) -{ - N = (vec4(N, 0.0) * obmat).xyz; - result = (height - midlevel) * scale * normalize(N); - result = (obmat * vec4(result, 0.0)).xyz; -} - -void node_displacement_world(float height, float midlevel, float scale, vec3 N, out vec3 result) -{ - result = (height - midlevel) * scale * normalize(N); -} - -void node_vector_displacement_tangent(vec4 vector, - float midlevel, - float scale, - vec4 tangent, - vec3 normal, - mat4 obmat, - mat4 viewmat, - out vec3 result) -{ - /* TODO(fclem) this is broken. revisit latter. */ - vec3 N_object = normalize(((vec4(normal, 0.0) * viewmat) * obmat).xyz); - vec3 T_object = normalize(((vec4(tangent.xyz, 0.0) * viewmat) * obmat).xyz); - vec3 B_object = tangent.w * normalize(cross(N_object, T_object)); - - vec3 offset = (vector.xyz - vec3(midlevel)) * scale; - result = offset.x * T_object + offset.y * N_object + offset.z * B_object; - result = (obmat * vec4(result, 0.0)).xyz; -} - -void node_vector_displacement_object( - vec4 vector, float midlevel, float scale, mat4 obmat, out vec3 result) -{ - result = (vector.xyz - vec3(midlevel)) * scale; - result = (obmat * vec4(result, 0.0)).xyz; -} - -void node_vector_displacement_world(vec4 vector, float midlevel, float scale, out vec3 result) -{ - result = (vector.xyz - vec3(midlevel)) * scale; -} - -/* output */ - -void node_output_material(Closure surface, Closure volume, vec3 displacement, out Closure result) -{ -#ifdef VOLUMETRICS - result = volume; -#else - result = surface; -#endif -} - -uniform float backgroundAlpha; - -void node_output_world(Closure surface, Closure volume, out Closure result) -{ -#ifndef VOLUMETRICS - result.radiance = surface.radiance * backgroundAlpha; - result.transmittance = vec3(1.0 - backgroundAlpha); -#else - result = volume; -#endif /* VOLUMETRICS */ -} - -/* TODO : clean this ifdef mess */ -/* EEVEE output */ -void world_normals_get(out vec3 N) -{ -#ifndef VOLUMETRICS -# ifdef HAIR_SHADER - vec3 B = normalize(cross(worldNormal, hairTangent)); - float cos_theta; - if (hairThicknessRes == 1) { - vec4 rand = texelFetch(utilTex, ivec3(ivec2(gl_FragCoord.xy) % LUT_SIZE, 2.0), 0); - /* Random cosine normal distribution on the hair surface. */ - cos_theta = rand.x * 2.0 - 1.0; - } - else { - /* Shade as a cylinder. */ - cos_theta = hairThickTime / hairThickness; - } - float sin_theta = sqrt(max(0.0, 1.0 - cos_theta * cos_theta)); - N = normalize(worldNormal * sin_theta + B * cos_theta); -# else - N = gl_FrontFacing ? worldNormal : -worldNormal; -# endif -#else - generated_from_orco(vec3(0.0), N); -#endif -} - -#ifndef VOLUMETRICS -void node_eevee_specular(vec4 diffuse, - vec4 specular, - float roughness, - vec4 emissive, - float transp, - vec3 normal, - float clearcoat, - float clearcoat_roughness, - vec3 clearcoat_normal, - float occlusion, - float ssr_id, - out Closure result) -{ - normal = normalize(normal); - - vec3 out_diff, out_spec, ssr_spec; - eevee_closure_default_clearcoat(normal, - diffuse.rgb, - specular.rgb, - vec3(1.0), - int(ssr_id), - roughness, - clearcoat_normal, - clearcoat * 0.25, - clearcoat_roughness, - occlusion, - out_diff, - out_spec, - ssr_spec); - - float alpha = 1.0 - transp; - result = CLOSURE_DEFAULT; - result.radiance = out_diff * diffuse.rgb + out_spec + emissive.rgb; - result.radiance *= alpha; - result.transmittance = vec3(transp); - - closure_load_ssr_data(ssr_spec * alpha, roughness, normal, viewCameraVec, int(ssr_id), result); -} - -void node_shader_to_rgba(Closure cl, out vec4 outcol, out float outalpha) -{ - vec4 spec_accum = vec4(0.0); - if (ssrToggle && FLAG_TEST(cl.flag, CLOSURE_SSR_FLAG)) { - vec3 V = cameraVec; - vec3 vN = normal_decode(cl.ssr_normal, viewCameraVec); - vec3 N = transform_direction(ViewMatrixInverse, vN); - float roughness = cl.ssr_data.a; - float roughnessSquared = max(1e-3, roughness * roughness); - fallback_cubemap(N, V, worldPosition, viewPosition, roughness, roughnessSquared, spec_accum); - } - - outalpha = avg(cl.transmittance); - outcol = vec4((spec_accum.rgb * cl.ssr_data.rgb) + cl.radiance, 1.0); - -# ifdef USE_SSS -# ifdef USE_SSS_ALBEDO - outcol.rgb += cl.sss_data.rgb * cl.sss_albedo; -# else - outcol.rgb += cl.sss_data.rgb; -# endif -# endif -} - -#endif /* VOLUMETRICS */ diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_add_shader.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_add_shader.glsl new file mode 100644 index 00000000000..99117400c57 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_add_shader.glsl @@ -0,0 +1,4 @@ +void node_add_shader(Closure shader1, Closure shader2, out Closure shader) +{ + shader = closure_add(shader1, shader2); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_ambient_occlusion.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_ambient_occlusion.glsl new file mode 100644 index 00000000000..8f8ebebb5f1 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_ambient_occlusion.glsl @@ -0,0 +1,13 @@ +#ifndef VOLUMETRICS +void node_ambient_occlusion( + vec4 color, float distance, vec3 normal, out vec4 result_color, out float result_ao) +{ + vec3 bent_normal; + vec4 rand = texelFetch(utilTex, ivec3(ivec2(gl_FragCoord.xy) % LUT_SIZE, 2.0), 0); + result_ao = occlusion_compute(normalize(normal), viewPosition, 1.0, rand, bent_normal); + result_color = result_ao * color; +} +#else +/* Stub ambient occlusion because it is not compatible with volumetrics. */ +# define node_ambient_occlusion +#endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_anisotropic.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_anisotropic.glsl new file mode 100644 index 00000000000..a8a900b40c6 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_anisotropic.glsl @@ -0,0 +1,15 @@ +#ifndef VOLUMETRICS +void node_bsdf_anisotropic(vec4 color, + float roughness, + float anisotropy, + float rotation, + vec3 N, + vec3 T, + out Closure result) +{ + node_bsdf_glossy(color, roughness, N, -1, result); +} +#else +/* Stub anisotropic because it is not compatible with volumetrics. */ +# define node_bsdf_anisotropic +#endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_attribute.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_attribute.glsl new file mode 100644 index 00000000000..10e1b4563bc --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_attribute.glsl @@ -0,0 +1,6 @@ +void node_attribute(vec3 attr, out vec4 outcol, out vec3 outvec, out float outf) +{ + outcol = vec4(attr, 1.0); + outvec = attr; + outf = avg(attr); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_background.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_background.glsl new file mode 100644 index 00000000000..69ef4dcb7c7 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_background.glsl @@ -0,0 +1,11 @@ +void node_background(vec4 color, float strength, out Closure result) +{ +#ifndef VOLUMETRICS + color *= strength; + result = CLOSURE_DEFAULT; + result.radiance = color.rgb; + result.transmittance = vec3(0.0); +#else + result = CLOSURE_DEFAULT; +#endif +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_bevel.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_bevel.glsl new file mode 100644 index 00000000000..0d99390c2f9 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_bevel.glsl @@ -0,0 +1,4 @@ +void node_bevel(float radius, vec3 N, out vec3 result) +{ + result = N; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_blackbody.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_blackbody.glsl new file mode 100644 index 00000000000..d0111aa3839 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_blackbody.glsl @@ -0,0 +1,13 @@ +void node_blackbody(float temperature, sampler1DArray spectrummap, float layer, out vec4 color) +{ + if (temperature >= 12000.0) { + color = vec4(0.826270103, 0.994478524, 1.56626022, 1.0); + } + else if (temperature < 965.0) { + color = vec4(4.70366907, 0.0, 0.0, 1.0); + } + else { + float t = (temperature - 965.0) / (12000.0 - 965.0); + color = vec4(texture(spectrummap, vec2(t, layer)).rgb, 1.0); + } +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_bright_contrast.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_bright_contrast.glsl new file mode 100644 index 00000000000..a5a10833065 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_bright_contrast.glsl @@ -0,0 +1,10 @@ +void brightness_contrast(vec4 col, float brightness, float contrast, out vec4 outcol) +{ + float a = 1.0 + contrast; + float b = brightness - contrast * 0.5; + + outcol.r = max(a * col.r + b, 0.0); + outcol.g = max(a * col.g + b, 0.0); + outcol.b = max(a * col.b + b, 0.0); + outcol.a = col.a; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_bump.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_bump.glsl new file mode 100644 index 00000000000..1137e5acdc6 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_bump.glsl @@ -0,0 +1,27 @@ +void node_bump( + float strength, float dist, float height, vec3 N, vec3 surf_pos, float invert, out vec3 result) +{ + N = mat3(ViewMatrix) * normalize(N); + dist *= gl_FrontFacing ? invert : -invert; + + vec3 dPdx = dFdx(surf_pos); + vec3 dPdy = dFdy(surf_pos); + + /* Get surface tangents from normal. */ + vec3 Rx = cross(dPdy, N); + vec3 Ry = cross(N, dPdx); + + /* Compute surface gradient and determinant. */ + float det = dot(dPdx, Rx); + + float dHdx = dFdx(height); + float dHdy = dFdy(height); + vec3 surfgrad = dHdx * Rx + dHdy * Ry; + + strength = max(strength, 0.0); + + result = normalize(abs(det) * N - dist * sign(det) * surfgrad); + result = normalize(mix(N, result, strength)); + + result = mat3(ViewMatrixInverse) * result; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_camera.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_camera.glsl new file mode 100644 index 00000000000..03e61e9f472 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_camera.glsl @@ -0,0 +1,6 @@ +void camera(vec3 co, out vec3 outview, out float outdepth, out float outdist) +{ + outdepth = abs(co.z); + outdist = length(co); + outview = normalize(co); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_cell_noise.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_cell_noise.glsl new file mode 100644 index 00000000000..881f2386cd4 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_cell_noise.glsl @@ -0,0 +1,17 @@ +float cellnoise(vec3 p) +{ + int ix = quick_floor(p.x); + int iy = quick_floor(p.y); + int iz = quick_floor(p.z); + + return hash_uint3_to_float(uint(ix), uint(iy), uint(iz)); +} + +vec3 cellnoise_color(vec3 p) +{ + float r = cellnoise(p.xyz); + float g = cellnoise(p.yxz); + float b = cellnoise(p.yzx); + + return vec3(r, g, b); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_clamp.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_clamp.glsl new file mode 100644 index 00000000000..b8842064b6f --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_clamp.glsl @@ -0,0 +1,4 @@ +void clamp_value(float value, float min, float max, out float result) +{ + result = clamp(value, min, max); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_color_ramp.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_color_ramp.glsl new file mode 100644 index 00000000000..9fe45f91f45 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_color_ramp.glsl @@ -0,0 +1,28 @@ +void valtorgb_opti_constant( + float fac, float edge, vec4 color1, vec4 color2, out vec4 outcol, out float outalpha) +{ + outcol = (fac > edge) ? color2 : color1; + outalpha = outcol.a; +} + +void valtorgb_opti_linear( + float fac, vec2 mulbias, vec4 color1, vec4 color2, out vec4 outcol, out float outalpha) +{ + fac = clamp(fac * mulbias.x + mulbias.y, 0.0, 1.0); + outcol = mix(color1, color2, fac); + outalpha = outcol.a; +} + +void valtorgb(float fac, sampler1DArray colormap, float layer, out vec4 outcol, out float outalpha) +{ + outcol = texture(colormap, vec2(fac, layer)); + outalpha = outcol.a; +} + +void valtorgb_nearest( + float fac, sampler1DArray colormap, float layer, out vec4 outcol, out float outalpha) +{ + fac = clamp(fac, 0.0, 1.0); + outcol = texelFetch(colormap, ivec2(fac * (textureSize(colormap, 0).x - 1), layer), 0); + outalpha = outcol.a; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_color_util.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_color_util.glsl new file mode 100644 index 00000000000..a5c3a990d90 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_color_util.glsl @@ -0,0 +1,111 @@ +void rgb_to_hsv(vec4 rgb, out vec4 outcol) +{ + float cmax, cmin, h, s, v, cdelta; + vec3 c; + + cmax = max(rgb[0], max(rgb[1], rgb[2])); + cmin = min(rgb[0], min(rgb[1], rgb[2])); + cdelta = cmax - cmin; + + v = cmax; + if (cmax != 0.0) { + s = cdelta / cmax; + } + else { + s = 0.0; + h = 0.0; + } + + if (s == 0.0) { + h = 0.0; + } + else { + c = (vec3(cmax) - rgb.xyz) / cdelta; + + if (rgb.x == cmax) { + h = c[2] - c[1]; + } + else if (rgb.y == cmax) { + h = 2.0 + c[0] - c[2]; + } + else { + h = 4.0 + c[1] - c[0]; + } + + h /= 6.0; + + if (h < 0.0) { + h += 1.0; + } + } + + outcol = vec4(h, s, v, rgb.w); +} + +void hsv_to_rgb(vec4 hsv, out vec4 outcol) +{ + float i, f, p, q, t, h, s, v; + vec3 rgb; + + h = hsv[0]; + s = hsv[1]; + v = hsv[2]; + + if (s == 0.0) { + rgb = vec3(v, v, v); + } + else { + if (h == 1.0) { + h = 0.0; + } + + h *= 6.0; + i = floor(h); + f = h - i; + rgb = vec3(f, f, f); + p = v * (1.0 - s); + q = v * (1.0 - (s * f)); + t = v * (1.0 - (s * (1.0 - f))); + + if (i == 0.0) { + rgb = vec3(v, t, p); + } + else if (i == 1.0) { + rgb = vec3(q, v, p); + } + else if (i == 2.0) { + rgb = vec3(p, v, t); + } + else if (i == 3.0) { + rgb = vec3(p, q, v); + } + else if (i == 4.0) { + rgb = vec3(t, p, v); + } + else { + rgb = vec3(v, p, q); + } + } + + outcol = vec4(rgb, hsv.w); +} + +void color_alpha_clear(vec4 color, out vec4 result) +{ + result = vec4(color.rgb, 1.0); +} + +void color_alpha_premultiply(vec4 color, out vec4 result) +{ + result = vec4(color.rgb * color.a, 1.0); +} + +void color_alpha_unpremultiply(vec4 color, out vec4 result) +{ + if (color.a == 0.0 || color.a == 1.0) { + result = vec4(color.rgb, 1.0); + } + else { + result = vec4(color.rgb / color.a, 1.0); + } +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_combine_hsv.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_combine_hsv.glsl new file mode 100644 index 00000000000..2ce061da3cb --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_combine_hsv.glsl @@ -0,0 +1,4 @@ +void combine_hsv(float h, float s, float v, out vec4 col) +{ + hsv_to_rgb(vec4(h, s, v, 1.0), col); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_combine_rgb.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_combine_rgb.glsl new file mode 100644 index 00000000000..d9c882a048f --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_combine_rgb.glsl @@ -0,0 +1,4 @@ +void combine_rgb(float r, float g, float b, out vec4 col) +{ + col = vec4(r, g, b, 1.0); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_combine_xyz.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_combine_xyz.glsl new file mode 100644 index 00000000000..d8d132ff1f9 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_combine_xyz.glsl @@ -0,0 +1,4 @@ +void combine_xyz(float x, float y, float z, out vec3 vec) +{ + vec = vec3(x, y, z); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl new file mode 100644 index 00000000000..14acf9925a2 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl @@ -0,0 +1,13 @@ +#ifndef VOLUMETRICS +void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out Closure result) +{ + N = normalize(N); + result = CLOSURE_DEFAULT; + eevee_closure_diffuse(N, color.rgb, 1.0, result.radiance); + closure_load_ssr_data(vec3(0.0), 0.0, N, viewCameraVec, -1, result); + result.radiance *= color.rgb; +} +#else +/* Stub diffuse because it is not compatible with volumetrics. */ +# define node_bsdf_diffuse +#endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_displacement.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_displacement.glsl new file mode 100644 index 00000000000..0838b5c8b71 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_displacement.glsl @@ -0,0 +1,12 @@ +void node_displacement_object( + float height, float midlevel, float scale, vec3 N, mat4 obmat, out vec3 result) +{ + N = (vec4(N, 0.0) * obmat).xyz; + result = (height - midlevel) * scale * normalize(N); + result = (obmat * vec4(result, 0.0)).xyz; +} + +void node_displacement_world(float height, float midlevel, float scale, vec3 N, out vec3 result) +{ + result = (height - midlevel) * scale * normalize(N); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_eevee_specular.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_eevee_specular.glsl new file mode 100644 index 00000000000..e69a53b6596 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_eevee_specular.glsl @@ -0,0 +1,40 @@ +#ifndef VOLUMETRICS +void node_eevee_specular(vec4 diffuse, + vec4 specular, + float roughness, + vec4 emissive, + float transp, + vec3 normal, + float clearcoat, + float clearcoat_roughness, + vec3 clearcoat_normal, + float occlusion, + float ssr_id, + out Closure result) +{ + normal = normalize(normal); + + vec3 out_diff, out_spec, ssr_spec; + eevee_closure_default_clearcoat(normal, + diffuse.rgb, + specular.rgb, + vec3(1.0), + int(ssr_id), + roughness, + clearcoat_normal, + clearcoat * 0.25, + clearcoat_roughness, + occlusion, + out_diff, + out_spec, + ssr_spec); + + float alpha = 1.0 - transp; + result = CLOSURE_DEFAULT; + result.radiance = out_diff * diffuse.rgb + out_spec + emissive.rgb; + result.radiance *= alpha; + result.transmittance = vec3(transp); + + closure_load_ssr_data(ssr_spec * alpha, roughness, normal, viewCameraVec, int(ssr_id), result); +} +#endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_emission.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_emission.glsl new file mode 100644 index 00000000000..092b9ed08bb --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_emission.glsl @@ -0,0 +1,10 @@ +void node_emission(vec4 color, float strength, vec3 vN, out Closure result) +{ + result = CLOSURE_DEFAULT; +#ifndef VOLUMETRICS + result.radiance = color.rgb * strength; + result.ssr_normal = normal_encode(vN, viewCameraVec); +#else + result.emission = color.rgb * strength; +#endif +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_fractal_noise.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_fractal_noise.glsl new file mode 100644 index 00000000000..2a925c2a622 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_fractal_noise.glsl @@ -0,0 +1,32 @@ +float noise_turbulence(vec3 p, float octaves, int hard) +{ + float fscale = 1.0; + float amp = 1.0; + float sum = 0.0; + octaves = clamp(octaves, 0.0, 16.0); + int n = int(octaves); + for (int i = 0; i <= n; i++) { + float t = noise(fscale * p); + if (hard != 0) { + t = abs(2.0 * t - 1.0); + } + sum += t * amp; + amp *= 0.5; + fscale *= 2.0; + } + float rmd = octaves - floor(octaves); + if (rmd != 0.0) { + float t = noise(fscale * p); + if (hard != 0) { + t = abs(2.0 * t - 1.0); + } + float sum2 = sum + t * amp; + sum *= (float(1 << n) / float((1 << (n + 1)) - 1)); + sum2 *= (float(1 << (n + 1)) / float((1 << (n + 2)) - 1)); + return (1.0 - rmd) * sum + rmd * sum2; + } + else { + sum *= (float(1 << n) / float((1 << (n + 1)) - 1)); + return sum; + } +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_fresnel.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_fresnel.glsl new file mode 100644 index 00000000000..7a4d28f2dd6 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_fresnel.glsl @@ -0,0 +1,37 @@ +float fresnel_dielectric_cos(float cosi, float eta) +{ + /* compute fresnel reflectance without explicitly computing + * the refracted direction */ + float c = abs(cosi); + float g = eta * eta - 1.0 + c * c; + float result; + + if (g > 0.0) { + g = sqrt(g); + float A = (g - c) / (g + c); + float B = (c * (g + c) - 1.0) / (c * (g - c) + 1.0); + result = 0.5 * A * A * (1.0 + B * B); + } + else { + result = 1.0; /* TIR (no refracted component) */ + } + + return result; +} + +float fresnel_dielectric(vec3 Incoming, vec3 Normal, float eta) +{ + /* compute fresnel reflectance without explicitly computing + * the refracted direction */ + return fresnel_dielectric_cos(dot(Incoming, Normal), eta); +} + +void node_fresnel(float ior, vec3 N, vec3 I, out float result) +{ + N = normalize(N); + /* handle perspective/orthographic */ + vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); + + float eta = max(ior, 0.00001); + result = fresnel_dielectric(I_view, N, (gl_FrontFacing) ? eta : 1.0 / eta); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_gamma.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_gamma.glsl new file mode 100644 index 00000000000..5733992f8dd --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_gamma.glsl @@ -0,0 +1,14 @@ +void node_gamma(vec4 col, float gamma, out vec4 outcol) +{ + outcol = col; + + if (col.r > 0.0) { + outcol.r = compatible_pow(col.r, gamma); + } + if (col.g > 0.0) { + outcol.g = compatible_pow(col.g, gamma); + } + if (col.b > 0.0) { + outcol.b = compatible_pow(col.b, gamma); + } +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_geometry.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_geometry.glsl new file mode 100644 index 00000000000..79614495499 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_geometry.glsl @@ -0,0 +1,46 @@ +void node_geometry(vec3 I, + vec3 N, + vec3 orco, + mat4 objmat, + mat4 toworld, + vec2 barycentric, + out vec3 position, + out vec3 normal, + out vec3 tangent, + out vec3 true_normal, + out vec3 incoming, + out vec3 parametric, + out float backfacing, + out float pointiness) +{ + /* handle perspective/orthographic */ + vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); + incoming = -(toworld * vec4(I_view, 0.0)).xyz; + +#if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE) + position = -incoming; + true_normal = normal = incoming; + tangent = parametric = vec3(0.0); + vec3(0.0); + backfacing = 0.0; + pointiness = 0.0; +#else + + position = worldPosition; +# ifndef VOLUMETRICS + normal = normalize(N); + vec3 B = dFdx(worldPosition); + vec3 T = dFdy(worldPosition); + true_normal = normalize(cross(B, T)); +# else + normal = (toworld * vec4(N, 0.0)).xyz; + true_normal = normal; +# endif + tangent_orco_z(orco, orco); + node_tangent(N, orco, objmat, tangent); + + parametric = vec3(barycentric, 0.0); + backfacing = (gl_FrontFacing) ? 0.0 : 1.0; + pointiness = 0.5; +#endif +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_glass.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_glass.glsl new file mode 100644 index 00000000000..8cc8ba2dd15 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_glass.glsl @@ -0,0 +1,23 @@ +#ifndef VOLUMETRICS +void node_bsdf_glass( + vec4 color, float roughness, float ior, vec3 N, float ssr_id, out Closure result) +{ + N = normalize(N); + vec3 out_spec, out_refr, ssr_spec; + vec3 refr_color = (refractionDepth > 0.0) ? color.rgb * color.rgb : + color.rgb; /* Simulate 2 transmission event */ + eevee_closure_glass( + N, vec3(1.0), vec3(1.0), int(ssr_id), roughness, 1.0, ior, out_spec, out_refr, ssr_spec); + out_refr *= refr_color; + out_spec *= color.rgb; + float fresnel = F_eta(ior, dot(N, cameraVec)); + vec3 vN = mat3(ViewMatrix) * N; + result = CLOSURE_DEFAULT; + result.radiance = mix(out_refr, out_spec, fresnel); + closure_load_ssr_data( + ssr_spec * color.rgb * fresnel, roughness, N, viewCameraVec, int(ssr_id), result); +} +#else +/* Stub glass because it is not compatible with volumetrics. */ +# define node_bsdf_glass +#endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_glossy.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_glossy.glsl new file mode 100644 index 00000000000..4d582e63725 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_glossy.glsl @@ -0,0 +1,15 @@ +#ifndef VOLUMETRICS +void node_bsdf_glossy(vec4 color, float roughness, vec3 N, float ssr_id, out Closure result) +{ + N = normalize(N); + vec3 out_spec, ssr_spec; + eevee_closure_glossy(N, vec3(1.0), vec3(1.0), int(ssr_id), roughness, 1.0, out_spec, ssr_spec); + vec3 vN = mat3(ViewMatrix) * N; + result = CLOSURE_DEFAULT; + result.radiance = out_spec * color.rgb; + closure_load_ssr_data(ssr_spec * color.rgb, roughness, N, viewCameraVec, int(ssr_id), result); +} +#else +/* Stub glossy because it is not compatible with volumetrics. */ +# define node_bsdf_glossy +#endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_hair_info.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_hair_info.glsl new file mode 100644 index 00000000000..3b23ac976ae --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_hair_info.glsl @@ -0,0 +1,21 @@ +void node_hair_info(out float is_strand, + out float intercept, + out float thickness, + out vec3 tangent, + out float random) +{ +#ifdef HAIR_SHADER + is_strand = 1.0; + intercept = hairTime; + thickness = hairThickness; + tangent = normalize(worldNormal); + random = wang_hash_noise( + uint(hairStrandID)); /* TODO: could be precomputed per strand instead. */ +#else + is_strand = 0.0; + intercept = 0.0; + thickness = 0.0; + tangent = vec3(1.0); + random = 0.0; +#endif +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_hash.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_hash.glsl new file mode 100644 index 00000000000..86191451e5f --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_hash.glsl @@ -0,0 +1,217 @@ +/* ***** Jenkins Lookup3 Hash Functions ***** */ + +/* Source: http://burtleburtle.net/bob/c/lookup3.c */ + +#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k)))) + +#define mix(a, b, c) \ + { \ + a -= c; \ + a ^= rot(c, 4); \ + c += b; \ + b -= a; \ + b ^= rot(a, 6); \ + a += c; \ + c -= b; \ + c ^= rot(b, 8); \ + b += a; \ + a -= c; \ + a ^= rot(c, 16); \ + c += b; \ + b -= a; \ + b ^= rot(a, 19); \ + a += c; \ + c -= b; \ + c ^= rot(b, 4); \ + b += a; \ + } + +#define final(a, b, c) \ + { \ + c ^= b; \ + c -= rot(b, 14); \ + a ^= c; \ + a -= rot(c, 11); \ + b ^= a; \ + b -= rot(a, 25); \ + c ^= b; \ + c -= rot(b, 16); \ + a ^= c; \ + a -= rot(c, 4); \ + b ^= a; \ + b -= rot(a, 14); \ + c ^= b; \ + c -= rot(b, 24); \ + } + +uint hash_uint(uint kx) +{ + uint a, b, c; + a = b = c = 0xdeadbeefu + (1u << 2u) + 13u; + + a += kx; + final(a, b, c); + + return c; +} + +uint hash_uint2(uint kx, uint ky) +{ + uint a, b, c; + a = b = c = 0xdeadbeefu + (2u << 2u) + 13u; + + b += ky; + a += kx; + final(a, b, c); + + return c; +} + +uint hash_uint3(uint kx, uint ky, uint kz) +{ + uint a, b, c; + a = b = c = 0xdeadbeefu + (3u << 2u) + 13u; + + c += kz; + b += ky; + a += kx; + final(a, b, c); + + return c; +} + +uint hash_uint4(uint kx, uint ky, uint kz, uint kw) +{ + uint a, b, c; + a = b = c = 0xdeadbeefu + (4u << 2u) + 13u; + + a += kx; + b += ky; + c += kz; + mix(a, b, c); + + a += kw; + final(a, b, c); + + return c; +} + +#undef rot +#undef final +#undef mix + +uint hash_int(int kx) +{ + return hash_uint(uint(kx)); +} + +uint hash_int2(int kx, int ky) +{ + return hash_uint2(uint(kx), uint(ky)); +} + +uint hash_int3(int kx, int ky, int kz) +{ + return hash_uint3(uint(kx), uint(ky), uint(kz)); +} + +uint hash_int4(int kx, int ky, int kz, int kw) +{ + return hash_uint4(uint(kx), uint(ky), uint(kz), uint(kw)); +} + +/* Hashing uint or uint[234] into a float in the range [0, 1]. */ + +float hash_uint_to_float(uint kx) +{ + return float(hash_uint(kx)) / float(0xFFFFFFFFu); +} + +float hash_uint2_to_float(uint kx, uint ky) +{ + return float(hash_uint2(kx, ky)) / float(0xFFFFFFFFu); +} + +float hash_uint3_to_float(uint kx, uint ky, uint kz) +{ + return float(hash_uint3(kx, ky, kz)) / float(0xFFFFFFFFu); +} + +float hash_uint4_to_float(uint kx, uint ky, uint kz, uint kw) +{ + return float(hash_uint4(kx, ky, kz, kw)) / float(0xFFFFFFFFu); +} + +/* Hashing float or vec[234] into a float in the range [0, 1]. */ + +float hash_float_to_float(float k) +{ + return hash_uint_to_float(floatBitsToUint(k)); +} + +float hash_vec2_to_float(vec2 k) +{ + return hash_uint2_to_float(floatBitsToUint(k.x), floatBitsToUint(k.y)); +} + +float hash_vec3_to_float(vec3 k) +{ + return hash_uint3_to_float(floatBitsToUint(k.x), floatBitsToUint(k.y), floatBitsToUint(k.z)); +} + +float hash_vec4_to_float(vec4 k) +{ + return hash_uint4_to_float( + floatBitsToUint(k.x), floatBitsToUint(k.y), floatBitsToUint(k.z), floatBitsToUint(k.w)); +} + +/* Hashing vec[234] into vec[234] of components in the range [0, 1]. */ + +vec2 hash_vec2_to_vec2(vec2 k) +{ + return vec2(hash_vec2_to_float(k), hash_vec3_to_float(vec3(k, 1.0))); +} + +vec3 hash_vec3_to_vec3(vec3 k) +{ + return vec3( + hash_vec3_to_float(k), hash_vec4_to_float(vec4(k, 1.0)), hash_vec4_to_float(vec4(k, 2.0))); +} + +vec4 hash_vec4_to_vec4(vec4 k) +{ + return vec4(hash_vec4_to_float(k.xyzw), + hash_vec4_to_float(k.wxyz), + hash_vec4_to_float(k.zwxy), + hash_vec4_to_float(k.yzwx)); +} + +/* Hashing float or vec[234] into vec3 of components in range [0, 1]. */ + +vec3 hash_float_to_vec3(float k) +{ + return vec3( + hash_float_to_float(k), hash_vec2_to_float(vec2(k, 1.0)), hash_vec2_to_float(vec2(k, 2.0))); +} + +vec3 hash_vec2_to_vec3(vec2 k) +{ + return vec3( + hash_vec2_to_float(k), hash_vec3_to_float(vec3(k, 1.0)), hash_vec3_to_float(vec3(k, 2.0))); +} + +vec3 hash_vec4_to_vec3(vec4 k) +{ + return vec3(hash_vec4_to_float(k.xyzw), hash_vec4_to_float(k.zxwy), hash_vec4_to_float(k.wzyx)); +} + +/* Other Hash Functions */ + +float integer_noise(int n) +{ + int nn; + n = (n + 1013) & 0x7fffffff; + n = (n >> 13) ^ n; + nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff; + return 0.5 * (float(nn) / 1073741824.0); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_holdout.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_holdout.glsl new file mode 100644 index 00000000000..50ce2bf2ab8 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_holdout.glsl @@ -0,0 +1,8 @@ +void node_holdout(out Closure result) +{ + result = CLOSURE_DEFAULT; +#ifndef VOLUMETRICS + result.holdout = 1.0; + result.flag = CLOSURE_HOLDOUT_FLAG; +#endif +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_hue_sat_val.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_hue_sat_val.glsl new file mode 100644 index 00000000000..64ac73ecdf3 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_hue_sat_val.glsl @@ -0,0 +1,14 @@ +void hue_sat(float hue, float sat, float value, float fac, vec4 col, out vec4 outcol) +{ + vec4 hsv; + + rgb_to_hsv(col, hsv); + + hsv[0] = fract(hsv[0] + hue + 0.5); + hsv[1] = clamp(hsv[1] * sat, 0.0, 1.0); + hsv[2] = hsv[2] * value; + + hsv_to_rgb(hsv, outcol); + + outcol = mix(col, outcol, fac); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_invert.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_invert.glsl new file mode 100644 index 00000000000..5cf362a9947 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_invert.glsl @@ -0,0 +1,5 @@ +void invert(float fac, vec4 col, out vec4 outcol) +{ + outcol.xyz = mix(col.xyz, vec3(1.0) - col.xyz, fac); + outcol.w = col.w; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_layer_weight.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_layer_weight.glsl new file mode 100644 index 00000000000..588d295bcc4 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_layer_weight.glsl @@ -0,0 +1,19 @@ +void node_layer_weight(float blend, vec3 N, vec3 I, out float fresnel, out float facing) +{ + N = normalize(N); + + /* fresnel */ + float eta = max(1.0 - blend, 0.00001); + vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); + + fresnel = fresnel_dielectric(I_view, N, (gl_FrontFacing) ? 1.0 / eta : eta); + + /* facing */ + facing = abs(dot(I_view, N)); + if (blend != 0.5) { + blend = clamp(blend, 0.0, 0.99999); + blend = (blend < 0.5) ? 2.0 * blend : 0.5 / (1.0 - blend); + facing = pow(facing, blend); + } + facing = 1.0 - facing; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_light_falloff.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_light_falloff.glsl new file mode 100644 index 00000000000..f3eae653f95 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_light_falloff.glsl @@ -0,0 +1,7 @@ +void node_light_falloff( + float strength, float tsmooth, out float quadratic, out float linear, out float constant) +{ + quadratic = strength; + linear = strength; + constant = strength; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_light_path.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_light_path.glsl new file mode 100644 index 00000000000..50c87e3f105 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_light_path.glsl @@ -0,0 +1,31 @@ +void node_light_path(out float is_camera_ray, + out float is_shadow_ray, + out float is_diffuse_ray, + out float is_glossy_ray, + out float is_singular_ray, + out float is_reflection_ray, + out float is_transmission_ray, + out float ray_length, + out float ray_depth, + out float diffuse_depth, + out float glossy_depth, + out float transparent_depth, + out float transmission_depth) +{ + /* Supported. */ + is_camera_ray = (rayType == EEVEE_RAY_CAMERA) ? 1.0 : 0.0; + is_shadow_ray = (rayType == EEVEE_RAY_SHADOW) ? 1.0 : 0.0; + is_diffuse_ray = (rayType == EEVEE_RAY_DIFFUSE) ? 1.0 : 0.0; + is_glossy_ray = (rayType == EEVEE_RAY_GLOSSY) ? 1.0 : 0.0; + /* Kind of supported. */ + is_singular_ray = is_glossy_ray; + is_reflection_ray = is_glossy_ray; + is_transmission_ray = is_glossy_ray; + ray_depth = rayDepth; + diffuse_depth = (is_diffuse_ray == 1.0) ? rayDepth : 0.0; + glossy_depth = (is_glossy_ray == 1.0) ? rayDepth : 0.0; + transmission_depth = (is_transmission_ray == 1.0) ? glossy_depth : 0.0; + /* Not supported. */ + ray_length = 1.0; + transparent_depth = 0.0; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_map_range.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_map_range.glsl new file mode 100644 index 00000000000..a185774f4b3 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_map_range.glsl @@ -0,0 +1,10 @@ +void map_range( + float value, float fromMin, float fromMax, float toMin, float toMax, out float result) +{ + if (fromMax != fromMin) { + result = toMin + ((value - fromMin) / (fromMax - fromMin)) * (toMax - toMin); + } + else { + result = 0.0; + } +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_mapping.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_mapping.glsl new file mode 100644 index 00000000000..ef47ac2be98 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_mapping.glsl @@ -0,0 +1,7 @@ +void mapping( + vec3 vec, vec4 m0, vec4 m1, vec4 m2, vec4 m3, vec3 minvec, vec3 maxvec, out vec3 outvec) +{ + mat4 mat = mat4(m0, m1, m2, m3); + outvec = (mat * vec4(vec, 1.0)).xyz; + outvec = clamp(outvec, minvec, maxvec); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_math.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_math.glsl new file mode 100644 index 00000000000..4fac770e8fe --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_math.glsl @@ -0,0 +1,130 @@ +void math_add(float a, float b, out float result) +{ + result = a + b; +} + +void math_subtract(float a, float b, out float result) +{ + result = a - b; +} + +void math_multiply(float a, float b, out float result) +{ + result = a * b; +} + +void math_divide(float a, float b, out float result) +{ + result = safe_divide(a, b); +} + +void math_power(float a, float b, out float result) +{ + if (a >= 0.0) { + result = compatible_pow(a, b); + } + else { + float fraction = mod(abs(b), 1.0); + if (fraction > 0.999 || fraction < 0.001) { + result = compatible_pow(a, floor(b + 0.5)); + } + else { + result = 0.0; + } + } +} + +void math_logarithm(float a, float b, out float result) +{ + result = (a > 0.0 && b > 0.0) ? log2(a) / log2(b) : 0.0; +} + +void math_sqrt(float a, float b, out float result) +{ + result = (a > 0.0) ? sqrt(a) : 0.0; +} + +void math_absolute(float a, float b, out float result) +{ + result = abs(a); +} + +void math_minimum(float a, float b, out float result) +{ + result = min(a, b); +} + +void math_maximum(float a, float b, out float result) +{ + result = max(a, b); +} + +void math_less_than(float a, float b, out float result) +{ + result = (a < b) ? 1.0 : 0.0; +} + +void math_greater_than(float a, float b, out float result) +{ + result = (a > b) ? 1.0 : 0.0; +} + +void math_round(float a, float b, out float result) +{ + result = floor(a + 0.5); +} + +void math_floor(float a, float b, out float result) +{ + result = floor(a); +} + +void math_ceil(float a, float b, out float result) +{ + result = ceil(a); +} + +void math_fraction(float a, float b, out float result) +{ + result = a - floor(a); +} + +void math_modulo(float a, float b, out float result) +{ + result = c_mod(a, b); +} + +void math_sine(float a, float b, out float result) +{ + result = sin(a); +} + +void math_cosine(float a, float b, out float result) +{ + result = cos(a); +} + +void math_tangent(float a, float b, out float result) +{ + result = tan(a); +} + +void math_arcsine(float a, float b, out float result) +{ + result = (a <= 1.0 && a >= -1.0) ? asin(a) : 0.0; +} + +void math_arccosine(float a, float b, out float result) +{ + result = (a <= 1.0 && a >= -1.0) ? acos(a) : 0.0; +} + +void math_arctangent(float a, float b, out float result) +{ + result = atan(a); +} + +void math_arctan2(float a, float b, out float result) +{ + result = atan(a, b); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_math_util.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_math_util.glsl new file mode 100644 index 00000000000..0be7da0cc4c --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_math_util.glsl @@ -0,0 +1,101 @@ +/* Float Math */ + +float safe_divide(float a, float b) +{ + return (b != 0.0) ? a / b : 0.0; +} + +/* Modulo with C sign convention. mod in GLSL will take absolute for negative numbers. */ +float c_mod(float a, float b) +{ + return (b != 0.0 && a != b) ? sign(a) * mod(abs(a), b) : 0.0; +} + +float compatible_pow(float x, float y) +{ + if (y == 0.0) { /* x^0 -> 1, including 0^0 */ + return 1.0; + } + + /* glsl pow doesn't accept negative x */ + if (x < 0.0) { + if (mod(-y, 2.0) == 0.0) { + return pow(-x, y); + } + else { + return -pow(-x, y); + } + } + else if (x == 0.0) { + return 0.0; + } + + return pow(x, y); +} + +float hypot(float x, float y) +{ + return sqrt(x * x + y * y); +} + +int floor_to_int(float x) +{ + return int(floor(x)); +} + +int quick_floor(float x) +{ + return int(x) - ((x < 0) ? 1 : 0); +} + +float floorfrac(float x, out int i) +{ + float x_floor = floor(x); + i = int(x_floor); + return x - x_floor; +} + +/* Vector Math */ + +vec3 safe_divide(vec3 a, vec3 b) +{ + return vec3(safe_divide(a.x, b.x), safe_divide(a.y, b.y), safe_divide(a.z, b.z)); +} + +vec3 c_mod(vec3 a, vec3 b) +{ + return vec3(c_mod(a.x, b.x), c_mod(a.y, b.y), c_mod(a.z, b.z)); +} + +void vector_mix(float strength, vec3 a, vec3 b, out vec3 outVector) +{ + outVector = strength * a + (1 - strength) * b; +} + +void invert_z(vec3 v, out vec3 outv) +{ + v.z = -v.z; + outv = v; +} + +void vector_normalize(vec3 normal, out vec3 outnormal) +{ + outnormal = normalize(normal); +} + +/* Matirx Math */ + +void direction_transform_m4v3(vec3 vin, mat4 mat, out vec3 vout) +{ + vout = (mat * vec4(vin, 0.0)).xyz; +} + +void normal_transform_transposed_m4v3(vec3 vin, mat4 mat, out vec3 vout) +{ + vout = transpose(mat3(mat)) * vin; +} + +void point_transform_m4v3(vec3 vin, mat4 mat, out vec3 vout) +{ + vout = (mat * vec4(vin, 1.0)).xyz; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_mix_rgb.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_mix_rgb.glsl new file mode 100644 index 00000000000..abe6081489d --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_mix_rgb.glsl @@ -0,0 +1,291 @@ +void mix_blend(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + outcol = mix(col1, col2, fac); + outcol.a = col1.a; +} + +void mix_add(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + outcol = mix(col1, col1 + col2, fac); + outcol.a = col1.a; +} + +void mix_mult(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + outcol = mix(col1, col1 * col2, fac); + outcol.a = col1.a; +} + +void mix_screen(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; + + outcol = vec4(1.0) - (vec4(facm) + fac * (vec4(1.0) - col2)) * (vec4(1.0) - col1); + outcol.a = col1.a; +} + +void mix_overlay(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; + + outcol = col1; + + if (outcol.r < 0.5) { + outcol.r *= facm + 2.0 * fac * col2.r; + } + else { + outcol.r = 1.0 - (facm + 2.0 * fac * (1.0 - col2.r)) * (1.0 - outcol.r); + } + + if (outcol.g < 0.5) { + outcol.g *= facm + 2.0 * fac * col2.g; + } + else { + outcol.g = 1.0 - (facm + 2.0 * fac * (1.0 - col2.g)) * (1.0 - outcol.g); + } + + if (outcol.b < 0.5) { + outcol.b *= facm + 2.0 * fac * col2.b; + } + else { + outcol.b = 1.0 - (facm + 2.0 * fac * (1.0 - col2.b)) * (1.0 - outcol.b); + } +} + +void mix_sub(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + outcol = mix(col1, col1 - col2, fac); + outcol.a = col1.a; +} + +void mix_div(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; + + outcol = col1; + + if (col2.r != 0.0) { + outcol.r = facm * outcol.r + fac * outcol.r / col2.r; + } + if (col2.g != 0.0) { + outcol.g = facm * outcol.g + fac * outcol.g / col2.g; + } + if (col2.b != 0.0) { + outcol.b = facm * outcol.b + fac * outcol.b / col2.b; + } +} + +void mix_diff(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + outcol = mix(col1, abs(col1 - col2), fac); + outcol.a = col1.a; +} + +void mix_dark(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + outcol.rgb = min(col1.rgb, col2.rgb * fac); + outcol.a = col1.a; +} + +void mix_light(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + outcol.rgb = max(col1.rgb, col2.rgb * fac); + outcol.a = col1.a; +} + +void mix_dodge(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + outcol = col1; + + if (outcol.r != 0.0) { + float tmp = 1.0 - fac * col2.r; + if (tmp <= 0.0) { + outcol.r = 1.0; + } + else if ((tmp = outcol.r / tmp) > 1.0) { + outcol.r = 1.0; + } + else { + outcol.r = tmp; + } + } + if (outcol.g != 0.0) { + float tmp = 1.0 - fac * col2.g; + if (tmp <= 0.0) { + outcol.g = 1.0; + } + else if ((tmp = outcol.g / tmp) > 1.0) { + outcol.g = 1.0; + } + else { + outcol.g = tmp; + } + } + if (outcol.b != 0.0) { + float tmp = 1.0 - fac * col2.b; + if (tmp <= 0.0) { + outcol.b = 1.0; + } + else if ((tmp = outcol.b / tmp) > 1.0) { + outcol.b = 1.0; + } + else { + outcol.b = tmp; + } + } +} + +void mix_burn(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float tmp, facm = 1.0 - fac; + + outcol = col1; + + tmp = facm + fac * col2.r; + if (tmp <= 0.0) { + outcol.r = 0.0; + } + else if ((tmp = (1.0 - (1.0 - outcol.r) / tmp)) < 0.0) { + outcol.r = 0.0; + } + else if (tmp > 1.0) { + outcol.r = 1.0; + } + else { + outcol.r = tmp; + } + + tmp = facm + fac * col2.g; + if (tmp <= 0.0) { + outcol.g = 0.0; + } + else if ((tmp = (1.0 - (1.0 - outcol.g) / tmp)) < 0.0) { + outcol.g = 0.0; + } + else if (tmp > 1.0) { + outcol.g = 1.0; + } + else { + outcol.g = tmp; + } + + tmp = facm + fac * col2.b; + if (tmp <= 0.0) { + outcol.b = 0.0; + } + else if ((tmp = (1.0 - (1.0 - outcol.b) / tmp)) < 0.0) { + outcol.b = 0.0; + } + else if (tmp > 1.0) { + outcol.b = 1.0; + } + else { + outcol.b = tmp; + } +} + +void mix_hue(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; + + outcol = col1; + + vec4 hsv, hsv2, tmp; + rgb_to_hsv(col2, hsv2); + + if (hsv2.y != 0.0) { + rgb_to_hsv(outcol, hsv); + hsv.x = hsv2.x; + hsv_to_rgb(hsv, tmp); + + outcol = mix(outcol, tmp, fac); + outcol.a = col1.a; + } +} + +void mix_sat(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; + + outcol = col1; + + vec4 hsv, hsv2; + rgb_to_hsv(outcol, hsv); + + if (hsv.y != 0.0) { + rgb_to_hsv(col2, hsv2); + + hsv.y = facm * hsv.y + fac * hsv2.y; + hsv_to_rgb(hsv, outcol); + } +} + +void mix_val(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; + + vec4 hsv, hsv2; + rgb_to_hsv(col1, hsv); + rgb_to_hsv(col2, hsv2); + + hsv.z = facm * hsv.z + fac * hsv2.z; + hsv_to_rgb(hsv, outcol); +} + +void mix_color(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; + + outcol = col1; + + vec4 hsv, hsv2, tmp; + rgb_to_hsv(col2, hsv2); + + if (hsv2.y != 0.0) { + rgb_to_hsv(outcol, hsv); + hsv.x = hsv2.x; + hsv.y = hsv2.y; + hsv_to_rgb(hsv, tmp); + + outcol = mix(outcol, tmp, fac); + outcol.a = col1.a; + } +} + +void mix_soft(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; + + vec4 one = vec4(1.0); + vec4 scr = one - (one - col2) * (one - col1); + outcol = facm * col1 + fac * ((one - col1) * col2 * col1 + col1 * scr); +} + +void mix_linear(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + + outcol = col1 + fac * (2.0 * (col2 - vec4(0.5))); +} + +void clamp_color(vec3 vec, vec3 min, vec3 max, out vec3 out_vec) +{ + out_vec = clamp(vec, min, max); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_mix_shader.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_mix_shader.glsl new file mode 100644 index 00000000000..c303d21d7c1 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_mix_shader.glsl @@ -0,0 +1,4 @@ +void node_mix_shader(float fac, Closure shader1, Closure shader2, out Closure shader) +{ + shader = closure_mix(shader1, shader2, fac); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_noise.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_noise.glsl new file mode 100644 index 00000000000..8c6a10e3fe7 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_noise.glsl @@ -0,0 +1,74 @@ +float noise_fade(float t) +{ + return t * t * t * (t * (t * 6.0 - 15.0) + 10.0); +} + +float noise_scale3(float result) +{ + return 0.9820 * result; +} + +float noise_nerp(float t, float a, float b) +{ + return (1.0 - t) * a + t * b; +} + +float noise_grad(uint hash, float x, float y, float z) +{ + uint h = hash & 15u; + float u = h < 8u ? x : y; + float vt = ((h == 12u) || (h == 14u)) ? x : z; + float v = h < 4u ? y : vt; + return (((h & 1u) != 0u) ? -u : u) + (((h & 2u) != 0u) ? -v : v); +} + +float noise_perlin(float x, float y, float z) +{ + int X; + float fx = floorfrac(x, X); + int Y; + float fy = floorfrac(y, Y); + int Z; + float fz = floorfrac(z, Z); + + float u = noise_fade(fx); + float v = noise_fade(fy); + float w = noise_fade(fz); + + float noise_u[2], noise_v[2]; + + noise_u[0] = noise_nerp(u, + noise_grad(hash_int3(X, Y, Z), fx, fy, fz), + noise_grad(hash_int3(X + 1, Y, Z), fx - 1.0, fy, fz)); + + noise_u[1] = noise_nerp(u, + noise_grad(hash_int3(X, Y + 1, Z), fx, fy - 1.0, fz), + noise_grad(hash_int3(X + 1, Y + 1, Z), fx - 1.0, fy - 1.0, fz)); + + noise_v[0] = noise_nerp(v, noise_u[0], noise_u[1]); + + noise_u[0] = noise_nerp(u, + noise_grad(hash_int3(X, Y, Z + 1), fx, fy, fz - 1.0), + noise_grad(hash_int3(X + 1, Y, Z + 1), fx - 1.0, fy, fz - 1.0)); + + noise_u[1] = noise_nerp( + u, + noise_grad(hash_int3(X, Y + 1, Z + 1), fx, fy - 1.0, fz - 1.0), + noise_grad(hash_int3(X + 1, Y + 1, Z + 1), fx - 1.0, fy - 1.0, fz - 1.0)); + + noise_v[1] = noise_nerp(v, noise_u[0], noise_u[1]); + + float r = noise_scale3(noise_nerp(w, noise_v[0], noise_v[1])); + + return (isinf(r)) ? 0.0 : r; +} + +float noise(vec3 p) +{ + return 0.5 * noise_perlin(p.x, p.y, p.z) + 0.5; +} + +float snoise(vec3 p) +{ + return noise_perlin(p.x, p.y, p.z); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_normal.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_normal.glsl new file mode 100644 index 00000000000..4f6e68909ad --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_normal.glsl @@ -0,0 +1,5 @@ +void normal_new_shading(vec3 nor, vec3 dir, out vec3 outnor, out float outdot) +{ + outnor = dir; + outdot = dot(normalize(nor), dir); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_normal_map.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_normal_map.glsl new file mode 100644 index 00000000000..6930e0c5dad --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_normal_map.glsl @@ -0,0 +1,22 @@ +void node_normal_map(vec4 info, vec4 tangent, vec3 normal, vec3 texnormal, out vec3 outnormal) +{ + if (all(equal(tangent, vec4(0.0, 0.0, 0.0, 1.0)))) { + outnormal = normal; + return; + } + tangent *= (gl_FrontFacing ? 1.0 : -1.0); + vec3 B = tangent.w * cross(normal, tangent.xyz) * info.w; + + outnormal = texnormal.x * tangent.xyz + texnormal.y * B + texnormal.z * normal; + outnormal = normalize(outnormal); +} + +void color_to_normal_new_shading(vec3 color, out vec3 normal) +{ + normal = vec3(2.0) * color - vec3(1.0); +} + +void color_to_blender_normal_new_shading(vec3 color, out vec3 normal) +{ + normal = vec3(2.0, -2.0, -2.0) * color - vec3(1.0); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_object_info.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_object_info.glsl new file mode 100644 index 00000000000..ff77b0beea2 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_object_info.glsl @@ -0,0 +1,16 @@ +void node_object_info(mat4 obmat, + vec4 obcolor, + vec4 info, + float mat_index, + out vec3 location, + out vec4 color, + out float object_index, + out float material_index, + out float random) +{ + location = obmat[3].xyz; + color = obcolor; + object_index = info.x; + material_index = mat_index; + random = info.z; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_output_material.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_output_material.glsl new file mode 100644 index 00000000000..62f76d46088 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_output_material.glsl @@ -0,0 +1,8 @@ +void node_output_material(Closure surface, Closure volume, vec3 displacement, out Closure result) +{ +#ifdef VOLUMETRICS + result = volume; +#else + result = surface; +#endif +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_output_world.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_output_world.glsl new file mode 100644 index 00000000000..ba391df185e --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_output_world.glsl @@ -0,0 +1,11 @@ +uniform float backgroundAlpha; + +void node_output_world(Closure surface, Closure volume, out Closure result) +{ +#ifndef VOLUMETRICS + result.radiance = surface.radiance * backgroundAlpha; + result.transmittance = vec3(1.0 - backgroundAlpha); +#else + result = volume; +#endif /* VOLUMETRICS */ +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_particle_info.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_particle_info.glsl new file mode 100644 index 00000000000..bdd60c20a81 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_particle_info.glsl @@ -0,0 +1,23 @@ +void particle_info(vec4 sprops, + vec4 loc, + vec3 vel, + vec3 avel, + out float index, + out float random, + out float age, + out float life_time, + out vec3 location, + out float size, + out vec3 velocity, + out vec3 angular_velocity) +{ + index = sprops.x; + random = loc.w; + age = sprops.y; + life_time = sprops.z; + size = sprops.w; + + location = loc.xyz; + velocity = vel; + angular_velocity = avel; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl new file mode 100644 index 00000000000..c6b640c572d --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl @@ -0,0 +1,439 @@ +#ifndef VOLUMETRICS +vec3 tint_from_color(vec3 color) +{ + float lum = dot(color, vec3(0.3, 0.6, 0.1)); /* luminance approx. */ + return (lum > 0) ? color / lum : vec3(1.0); /* normalize lum. to isolate hue+sat */ +} + +void convert_metallic_to_specular_tinted(vec3 basecol, + vec3 basecol_tint, + float metallic, + float specular_fac, + float specular_tint, + out vec3 diffuse, + out vec3 f0) +{ + vec3 tmp_col = mix(vec3(1.0), basecol_tint, specular_tint); + f0 = mix((0.08 * specular_fac) * tmp_col, basecol, metallic); + diffuse = basecol * (1.0 - metallic); +} + +vec3 principled_sheen(float NV, vec3 basecol_tint, float sheen_tint) +{ + float f = 1.0 - NV; + /* Temporary fix for T59784. Normal map seems to contain NaNs for tangent space normal maps, + * therefore we need to clamp value. */ + f = clamp(f, 0.0, 1.0); + /* Empirical approximation (manual curve fitting). Can be refined. */ + float sheen = f * f * f * 0.077 + f * 0.01 + 0.00026; + return sheen * mix(vec3(1.0), basecol_tint, sheen_tint); +} + +void node_bsdf_principled(vec4 base_color, + float subsurface, + vec3 subsurface_radius, + vec4 subsurface_color, + float metallic, + float specular, + float specular_tint, + float roughness, + float anisotropic, + float anisotropic_rotation, + float sheen, + float sheen_tint, + float clearcoat, + float clearcoat_roughness, + float ior, + float transmission, + float transmission_roughness, + vec4 emission, + float alpha, + vec3 N, + vec3 CN, + vec3 T, + vec3 I, + float ssr_id, + float sss_id, + vec3 sss_scale, + out Closure result) +{ + N = normalize(N); + ior = max(ior, 1e-5); + metallic = saturate(metallic); + transmission = saturate(transmission); + float dielectric = 1.0 - metallic; + transmission *= dielectric; + sheen *= dielectric; + subsurface_color *= dielectric; + + vec3 diffuse, f0, out_diff, out_spec, out_trans, out_refr, ssr_spec; + vec3 ctint = tint_from_color(base_color.rgb); + convert_metallic_to_specular_tinted( + base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0); + + float NV = dot(N, cameraVec); + vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint); + + /* Far from being accurate, but 2 glossy evaluation is too expensive. + * Most noticeable difference is at grazing angles since the bsdf lut + * f0 color interpolation is done on top of this interpolation. */ + vec3 f0_glass = mix(vec3(1.0), base_color.rgb, specular_tint); + float fresnel = F_eta(ior, NV); + vec3 spec_col = F_color_blend(ior, fresnel, f0_glass) * fresnel; + f0 = mix(f0, spec_col, transmission); + + vec3 f90 = mix(vec3(1.0), f0, (1.0 - specular) * metallic); + + vec3 mixed_ss_base_color = mix(diffuse, subsurface_color.rgb, subsurface); + + float sss_scalef = avg(sss_scale) * subsurface; + eevee_closure_principled(N, + mixed_ss_base_color, + f0, + f90, + int(ssr_id), + roughness, + CN, + clearcoat * 0.25, + clearcoat_roughness, + 1.0, + sss_scalef, + ior, + out_diff, + out_trans, + out_spec, + out_refr, + ssr_spec); + + vec3 refr_color = base_color.rgb; + refr_color *= (refractionDepth > 0.0) ? refr_color : + vec3(1.0); /* Simulate 2 transmission event */ + out_refr *= refr_color * (1.0 - fresnel) * transmission; + + result = CLOSURE_DEFAULT; + result.radiance = out_spec + out_refr; + result.radiance += out_diff * out_sheen; /* Coarse approx. */ + + closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); + + vec3 sss_radiance = (out_diff + out_trans) * alpha; +# ifndef USE_SSS + result.radiance += sss_radiance * mixed_ss_base_color * (1.0 - transmission); +# else +# ifdef USE_SSS_ALBEDO + vec3 sss_albedo = mixed_ss_base_color; +# else + sss_radiance *= mixed_ss_base_color; +# endif + sss_radiance *= (1.0 - transmission); + closure_load_sss_data(sss_scalef, + sss_radiance, +# ifdef USE_SSS_ALBEDO + sss_albedo, +# endif + int(sss_id), + result); +# endif /* USE_SSS */ + + result.radiance += emission.rgb; + result.radiance *= alpha; + result.transmittance = vec3(1.0 - alpha); +} + +void node_bsdf_principled_dielectric(vec4 base_color, + float subsurface, + vec3 subsurface_radius, + vec4 subsurface_color, + float metallic, + float specular, + float specular_tint, + float roughness, + float anisotropic, + float anisotropic_rotation, + float sheen, + float sheen_tint, + float clearcoat, + float clearcoat_roughness, + float ior, + float transmission, + float transmission_roughness, + vec4 emission, + float alpha, + vec3 N, + vec3 CN, + vec3 T, + vec3 I, + float ssr_id, + float sss_id, + vec3 sss_scale, + out Closure result) +{ + N = normalize(N); + metallic = saturate(metallic); + float dielectric = 1.0 - metallic; + + vec3 diffuse, f0, out_diff, out_spec, ssr_spec; + vec3 ctint = tint_from_color(base_color.rgb); + convert_metallic_to_specular_tinted( + base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0); + + float NV = dot(N, cameraVec); + vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint); + + eevee_closure_default( + N, diffuse, f0, vec3(1.0), int(ssr_id), roughness, 1.0, out_diff, out_spec, ssr_spec); + + result = CLOSURE_DEFAULT; + result.radiance = out_spec + out_diff * (diffuse + out_sheen); + closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); + result.radiance += emission.rgb; + result.radiance *= alpha; + result.transmittance = vec3(1.0 - alpha); +} + +void node_bsdf_principled_metallic(vec4 base_color, + float subsurface, + vec3 subsurface_radius, + vec4 subsurface_color, + float metallic, + float specular, + float specular_tint, + float roughness, + float anisotropic, + float anisotropic_rotation, + float sheen, + float sheen_tint, + float clearcoat, + float clearcoat_roughness, + float ior, + float transmission, + float transmission_roughness, + vec4 emission, + float alpha, + vec3 N, + vec3 CN, + vec3 T, + vec3 I, + float ssr_id, + float sss_id, + vec3 sss_scale, + out Closure result) +{ + N = normalize(N); + vec3 out_spec, ssr_spec; + + vec3 f90 = mix(vec3(1.0), base_color.rgb, (1.0 - specular) * metallic); + + eevee_closure_glossy(N, base_color.rgb, f90, int(ssr_id), roughness, 1.0, out_spec, ssr_spec); + + result = CLOSURE_DEFAULT; + result.radiance = out_spec; + closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); + result.radiance += emission.rgb; + result.radiance *= alpha; + result.transmittance = vec3(1.0 - alpha); +} + +void node_bsdf_principled_clearcoat(vec4 base_color, + float subsurface, + vec3 subsurface_radius, + vec4 subsurface_color, + float metallic, + float specular, + float specular_tint, + float roughness, + float anisotropic, + float anisotropic_rotation, + float sheen, + float sheen_tint, + float clearcoat, + float clearcoat_roughness, + float ior, + float transmission, + float transmission_roughness, + vec4 emission, + float alpha, + vec3 N, + vec3 CN, + vec3 T, + vec3 I, + float ssr_id, + float sss_id, + vec3 sss_scale, + out Closure result) +{ + vec3 out_spec, ssr_spec; + N = normalize(N); + + vec3 f90 = mix(vec3(1.0), base_color.rgb, (1.0 - specular) * metallic); + + eevee_closure_clearcoat(N, + base_color.rgb, + f90, + int(ssr_id), + roughness, + CN, + clearcoat * 0.25, + clearcoat_roughness, + 1.0, + out_spec, + ssr_spec); + + result = CLOSURE_DEFAULT; + result.radiance = out_spec; + closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); + result.radiance += emission.rgb; + result.radiance *= alpha; + result.transmittance = vec3(1.0 - alpha); +} + +void node_bsdf_principled_subsurface(vec4 base_color, + float subsurface, + vec3 subsurface_radius, + vec4 subsurface_color, + float metallic, + float specular, + float specular_tint, + float roughness, + float anisotropic, + float anisotropic_rotation, + float sheen, + float sheen_tint, + float clearcoat, + float clearcoat_roughness, + float ior, + float transmission, + float transmission_roughness, + vec4 emission, + float alpha, + vec3 N, + vec3 CN, + vec3 T, + vec3 I, + float ssr_id, + float sss_id, + vec3 sss_scale, + out Closure result) +{ + metallic = saturate(metallic); + N = normalize(N); + + vec3 diffuse, f0, out_diff, out_spec, out_trans, ssr_spec; + vec3 ctint = tint_from_color(base_color.rgb); + convert_metallic_to_specular_tinted( + base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0); + + subsurface_color = subsurface_color * (1.0 - metallic); + vec3 mixed_ss_base_color = mix(diffuse, subsurface_color.rgb, subsurface); + float sss_scalef = avg(sss_scale) * subsurface; + + float NV = dot(N, cameraVec); + vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint); + + vec3 f90 = mix(vec3(1.0), base_color.rgb, (1.0 - specular) * metallic); + + eevee_closure_skin(N, + mixed_ss_base_color, + f0, + f90, + int(ssr_id), + roughness, + 1.0, + sss_scalef, + out_diff, + out_trans, + out_spec, + ssr_spec); + + result = CLOSURE_DEFAULT; + result.radiance = out_spec; + closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); + + vec3 sss_radiance = (out_diff + out_trans) * alpha; +# ifndef USE_SSS + result.radiance += sss_radiance * mixed_ss_base_color * (1.0 - transmission); +# else +# ifdef USE_SSS_ALBEDO + vec3 sss_albedo = mixed_ss_base_color; +# else + sss_radiance *= mixed_ss_base_color; +# endif + sss_radiance *= (1.0 - transmission); + closure_load_sss_data(sss_scalef, + sss_radiance, +# ifdef USE_SSS_ALBEDO + sss_albedo, +# endif + int(sss_id), + result); +# endif /* USE_SSS */ + + result.radiance += out_diff * out_sheen; + result.radiance += emission.rgb; + result.radiance *= alpha; + result.transmittance = vec3(1.0 - alpha); +} + +void node_bsdf_principled_glass(vec4 base_color, + float subsurface, + vec3 subsurface_radius, + vec4 subsurface_color, + float metallic, + float specular, + float specular_tint, + float roughness, + float anisotropic, + float anisotropic_rotation, + float sheen, + float sheen_tint, + float clearcoat, + float clearcoat_roughness, + float ior, + float transmission, + float transmission_roughness, + vec4 emission, + float alpha, + vec3 N, + vec3 CN, + vec3 T, + vec3 I, + float ssr_id, + float sss_id, + vec3 sss_scale, + out Closure result) +{ + ior = max(ior, 1e-5); + N = normalize(N); + + vec3 f0, out_spec, out_refr, ssr_spec; + f0 = mix(vec3(1.0), base_color.rgb, specular_tint); + + eevee_closure_glass( + N, vec3(1.0), vec3(1.0), int(ssr_id), roughness, 1.0, ior, out_spec, out_refr, ssr_spec); + + vec3 refr_color = base_color.rgb; + refr_color *= (refractionDepth > 0.0) ? refr_color : + vec3(1.0); /* Simulate 2 transmission events */ + out_refr *= refr_color; + + float fresnel = F_eta(ior, dot(N, cameraVec)); + vec3 spec_col = F_color_blend(ior, fresnel, f0); + out_spec *= spec_col; + ssr_spec *= spec_col * fresnel; + + result = CLOSURE_DEFAULT; + result.radiance = mix(out_refr, out_spec, fresnel); + closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); + result.radiance += emission.rgb; + result.radiance *= alpha; + result.transmittance = vec3(1.0 - alpha); +} +#else +/* Stub principled because it is not compatible with volumetrics. */ +# define node_bsdf_principled +# define node_bsdf_principled_dielectric +# define node_bsdf_principled_metallic +# define node_bsdf_principled_clearcoat +# define node_bsdf_principled_subsurface +# define node_bsdf_principled_glass +#endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl new file mode 100644 index 00000000000..04394a9420b --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl @@ -0,0 +1,16 @@ +#ifndef VOLUMETRICS +void node_bsdf_refraction(vec4 color, float roughness, float ior, vec3 N, out Closure result) +{ + N = normalize(N); + vec3 out_refr; + color.rgb *= (refractionDepth > 0.0) ? color.rgb : vec3(1.0); /* Simulate 2 absorption event. */ + eevee_closure_refraction(N, roughness, ior, out_refr); + vec3 vN = mat3(ViewMatrix) * N; + result = CLOSURE_DEFAULT; + result.ssr_normal = normal_encode(vN, viewCameraVec); + result.radiance = out_refr * color.rgb; +} +#else +/* Stub refraction because it is not compatible with volumetrics. */ +# define node_bsdf_refraction +#endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_rgb_curves.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_rgb_curves.glsl new file mode 100644 index 00000000000..054fdddf7c3 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_rgb_curves.glsl @@ -0,0 +1,73 @@ +/* ext is vec4(in_x, in_dy, out_x, out_dy). */ +float curve_extrapolate(float x, float y, vec4 ext) +{ + if (x < 0.0) { + return y + x * ext.y; + } + else if (x > 1.0) { + return y + (x - 1.0) * ext.w; + } + else { + return y; + } +} + +#define RANGE_RESCALE(x, min, range) ((x - min) * range) + +void curves_rgb(float fac, + vec4 col, + sampler1DArray curvemap, + float layer, + vec4 range, + vec4 ext_r, + vec4 ext_g, + vec4 ext_b, + vec4 ext_a, + out vec4 outcol) +{ + vec4 co = vec4(RANGE_RESCALE(col.rgb, ext_a.x, range.a), layer); + vec3 samp; + samp.r = texture(curvemap, co.xw).a; + samp.g = texture(curvemap, co.yw).a; + samp.b = texture(curvemap, co.zw).a; + + samp.r = curve_extrapolate(co.x, samp.r, ext_a); + samp.g = curve_extrapolate(co.y, samp.g, ext_a); + samp.b = curve_extrapolate(co.z, samp.b, ext_a); + + vec3 rgb_min = vec3(ext_r.x, ext_g.x, ext_b.x); + co.xyz = RANGE_RESCALE(samp.rgb, rgb_min, range.rgb); + + samp.r = texture(curvemap, co.xw).r; + samp.g = texture(curvemap, co.yw).g; + samp.b = texture(curvemap, co.zw).b; + + outcol.r = curve_extrapolate(co.x, samp.r, ext_r); + outcol.g = curve_extrapolate(co.y, samp.g, ext_g); + outcol.b = curve_extrapolate(co.z, samp.b, ext_b); + outcol.a = col.a; + + outcol = mix(col, outcol, fac); +} + +void curves_rgb_opti(float fac, + vec4 col, + sampler1DArray curvemap, + float layer, + vec4 range, + vec4 ext_a, + out vec4 outcol) +{ + vec4 co = vec4(RANGE_RESCALE(col.rgb, ext_a.x, range.a), layer); + vec3 samp; + samp.r = texture(curvemap, co.xw).a; + samp.g = texture(curvemap, co.yw).a; + samp.b = texture(curvemap, co.zw).a; + + outcol.r = curve_extrapolate(co.x, samp.r, ext_a); + outcol.g = curve_extrapolate(co.y, samp.g, ext_a); + outcol.b = curve_extrapolate(co.z, samp.b, ext_a); + outcol.a = col.a; + + outcol = mix(col, outcol, fac); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_rgb_to_bw.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_rgb_to_bw.glsl new file mode 100644 index 00000000000..ceca02a2356 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_rgb_to_bw.glsl @@ -0,0 +1,5 @@ +void rgbtobw(vec4 color, out float outval) +{ + vec3 factors = vec3(0.2126, 0.7152, 0.0722); + outval = dot(color.rgb, factors); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_separate_hsv.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_separate_hsv.glsl new file mode 100644 index 00000000000..fb64e424c6c --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_separate_hsv.glsl @@ -0,0 +1,9 @@ +void separate_hsv(vec4 col, out float h, out float s, out float v) +{ + vec4 hsv; + + rgb_to_hsv(col, hsv); + h = hsv[0]; + s = hsv[1]; + v = hsv[2]; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_separate_rgb.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_separate_rgb.glsl new file mode 100644 index 00000000000..4232b4c001e --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_separate_rgb.glsl @@ -0,0 +1,6 @@ +void separate_rgb(vec4 col, out float r, out float g, out float b) +{ + r = col.r; + g = col.g; + b = col.b; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_separate_xyz.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_separate_xyz.glsl new file mode 100644 index 00000000000..fac29ccc135 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_separate_xyz.glsl @@ -0,0 +1,6 @@ +void separate_xyz(vec3 vec, out float x, out float y, out float z) +{ + x = vec.r; + y = vec.g; + z = vec.b; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_set.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_set.glsl new file mode 100644 index 00000000000..dc2ecb05351 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_set.glsl @@ -0,0 +1,44 @@ +void set_value(float val, out float outval) +{ + outval = val; +} + +void set_rgb(vec3 col, out vec3 outcol) +{ + outcol = col; +} + +void set_rgba(vec4 col, out vec4 outcol) +{ + outcol = col; +} + +void set_value_zero(out float outval) +{ + outval = 0.0; +} + +void set_value_one(out float outval) +{ + outval = 1.0; +} + +void set_rgb_zero(out vec3 outval) +{ + outval = vec3(0.0); +} + +void set_rgb_one(out vec3 outval) +{ + outval = vec3(1.0); +} + +void set_rgba_zero(out vec4 outval) +{ + outval = vec4(0.0); +} + +void set_rgba_one(out vec4 outval) +{ + outval = vec4(1.0); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_shader_to_rgba.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_shader_to_rgba.glsl new file mode 100644 index 00000000000..0a587c7e471 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_shader_to_rgba.glsl @@ -0,0 +1,25 @@ +#ifndef VOLUMETRICS +void node_shader_to_rgba(Closure cl, out vec4 outcol, out float outalpha) +{ + vec4 spec_accum = vec4(0.0); + if (ssrToggle && FLAG_TEST(cl.flag, CLOSURE_SSR_FLAG)) { + vec3 V = cameraVec; + vec3 vN = normal_decode(cl.ssr_normal, viewCameraVec); + vec3 N = transform_direction(ViewMatrixInverse, vN); + float roughness = cl.ssr_data.a; + float roughnessSquared = max(1e-3, roughness * roughness); + fallback_cubemap(N, V, worldPosition, viewPosition, roughness, roughnessSquared, spec_accum); + } + + outalpha = avg(cl.transmittance); + outcol = vec4((spec_accum.rgb * cl.ssr_data.rgb) + cl.radiance, 1.0); + +# ifdef USE_SSS +# ifdef USE_SSS_ALBEDO + outcol.rgb += cl.sss_data.rgb * cl.sss_albedo; +# else + outcol.rgb += cl.sss_data.rgb; +# endif +# endif +} +#endif /* VOLUMETRICS */ diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_squeeze.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_squeeze.glsl new file mode 100644 index 00000000000..b73bdebf7f6 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_squeeze.glsl @@ -0,0 +1,4 @@ +void squeeze(float val, float width, float center, out float outval) +{ + outval = 1.0 / (1.0 + pow(2.71828183, -((val - center) * width))); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl new file mode 100644 index 00000000000..fc81f3c4674 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl @@ -0,0 +1,42 @@ +#ifndef VOLUMETRICS +void node_subsurface_scattering(vec4 color, + float scale, + vec3 radius, + float sharpen, + float texture_blur, + vec3 N, + float sss_id, + out Closure result) +{ +# if defined(USE_SSS) + N = normalize(N); + vec3 out_diff, out_trans; + vec3 vN = mat3(ViewMatrix) * N; + result = CLOSURE_DEFAULT; + closure_load_ssr_data(vec3(0.0), 0.0, N, viewCameraVec, -1, result); + + eevee_closure_subsurface(N, color.rgb, 1.0, scale, out_diff, out_trans); + + vec3 sss_radiance = out_diff + out_trans; +# ifdef USE_SSS_ALBEDO + /* Not perfect for texture_blur not exactly equal to 0.0 or 1.0. */ + vec3 sss_albedo = mix(color.rgb, vec3(1.0), texture_blur); + sss_radiance *= mix(vec3(1.0), color.rgb, texture_blur); +# else + sss_radiance *= color.rgb; +# endif + closure_load_sss_data(scale, + sss_radiance, +# ifdef USE_SSS_ALBEDO + sss_albedo, +# endif + int(sss_id), + result); +# else + node_bsdf_diffuse(color, 0.0, N, result); +# endif +} +#else +/* Stub subsurface scattering because it is not compatible with volumetrics. */ +# define node_subsurface_scattering +#endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tangent.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tangent.glsl new file mode 100644 index 00000000000..ff2dbc7ead3 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_tangent.glsl @@ -0,0 +1,25 @@ +void tangent_orco_x(vec3 orco_in, out vec3 orco_out) +{ + orco_out = orco_in.xzy * vec3(0.0, -0.5, 0.5) + vec3(0.0, 0.25, -0.25); +} + +void tangent_orco_y(vec3 orco_in, out vec3 orco_out) +{ + orco_out = orco_in.zyx * vec3(-0.5, 0.0, 0.5) + vec3(0.25, 0.0, -0.25); +} + +void tangent_orco_z(vec3 orco_in, out vec3 orco_out) +{ + orco_out = orco_in.yxz * vec3(-0.5, 0.5, 0.0) + vec3(0.25, -0.25, 0.0); +} + +void node_tangentmap(vec4 attr_tangent, out vec3 tangent) +{ + tangent = normalize(attr_tangent.xyz); +} + +void node_tangent(vec3 N, vec3 orco, mat4 objmat, out vec3 T) +{ + T = (objmat * vec4(orco, 0.0)).xyz; + T = cross(N, normalize(cross(T, N))); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_brick.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_brick.glsl new file mode 100644 index 00000000000..e252e5ba726 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_brick.glsl @@ -0,0 +1,78 @@ +vec2 calc_brick_texture(vec3 p, + float mortar_size, + float mortar_smooth, + float bias, + float brick_width, + float row_height, + float offset_amount, + int offset_frequency, + float squash_amount, + int squash_frequency) +{ + int bricknum, rownum; + float offset = 0.0; + float x, y; + + rownum = floor_to_int(p.y / row_height); + + if (offset_frequency != 0 && squash_frequency != 0) { + brick_width *= (rownum % squash_frequency != 0) ? 1.0 : squash_amount; /* squash */ + offset = (rownum % offset_frequency != 0) ? 0.0 : (brick_width * offset_amount); /* offset */ + } + + bricknum = floor_to_int((p.x + offset) / brick_width); + + x = (p.x + offset) - brick_width * bricknum; + y = p.y - row_height * rownum; + + float tint = clamp((integer_noise((rownum << 16) + (bricknum & 0xFFFF)) + bias), 0.0, 1.0); + + float min_dist = min(min(x, y), min(brick_width - x, row_height - y)); + if (min_dist >= mortar_size) { + return vec2(tint, 0.0); + } + else if (mortar_smooth == 0.0) { + return vec2(tint, 1.0); + } + else { + min_dist = 1.0 - min_dist / mortar_size; + return vec2(tint, smoothstep(0.0, mortar_smooth, min_dist)); + } +} + +void node_tex_brick(vec3 co, + vec4 color1, + vec4 color2, + vec4 mortar, + float scale, + float mortar_size, + float mortar_smooth, + float bias, + float brick_width, + float row_height, + float offset_amount, + float offset_frequency, + float squash_amount, + float squash_frequency, + out vec4 color, + out float fac) +{ + vec2 f2 = calc_brick_texture(co * scale, + mortar_size, + mortar_smooth, + bias, + brick_width, + row_height, + offset_amount, + int(offset_frequency), + squash_amount, + int(squash_frequency)); + float tint = f2.x; + float f = f2.y; + if (f != 1.0) { + float facm = 1.0 - tint; + color1 = facm * color1 + tint * color2; + } + color = mix(color1, mortar, f); + fac = f; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_checker.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_checker.glsl new file mode 100644 index 00000000000..f534f3bddf3 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_checker.glsl @@ -0,0 +1,17 @@ +void node_tex_checker( + vec3 co, vec4 color1, vec4 color2, float scale, out vec4 color, out float fac) +{ + vec3 p = co * scale; + + /* Prevent precision issues on unit coordinates. */ + p = (p + 0.000001) * 0.999999; + + int xi = int(abs(floor(p.x))); + int yi = int(abs(floor(p.y))); + int zi = int(abs(floor(p.z))); + + bool check = ((mod(xi, 2) == mod(yi, 2)) == bool(mod(zi, 2))); + + color = check ? color1 : color2; + fac = check ? 1.0 : 0.0; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl new file mode 100644 index 00000000000..9bd36f8a757 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl @@ -0,0 +1,44 @@ +void node_tex_environment_texco(vec3 viewvec, out vec3 worldvec) +{ +#ifdef MESH_SHADER + worldvec = worldPosition; +#else + vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); + vec4 co_homogenous = (ProjectionMatrixInverse * v); + + vec3 co = co_homogenous.xyz / co_homogenous.w; +# if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE) + worldvec = mat3(ViewMatrixInverse) * co; +# else + worldvec = mat3(ModelMatrixInverse) * (mat3(ViewMatrixInverse) * co); +# endif +#endif +} + +void node_tex_environment_equirectangular(vec3 co, float clamp_size, sampler2D ima, out vec3 uv) +{ + vec3 nco = normalize(co); + uv.x = -atan(nco.y, nco.x) / (2.0 * M_PI) + 0.5; + uv.y = atan(nco.z, hypot(nco.x, nco.y)) / M_PI + 0.5; + + /* Fix pole bleeding */ + float half_height = clamp_size / float(textureSize(ima, 0).y); + uv.y = clamp(uv.y, half_height, 1.0 - half_height); + uv.z = 0.0; +} + +void node_tex_environment_mirror_ball(vec3 co, out vec3 uv) +{ + vec3 nco = normalize(co); + nco.y -= 1.0; + + float div = 2.0 * sqrt(max(-0.5 * nco.y, 0.0)); + nco /= max(1e-8, div); + + uv = 0.5 * nco.xzz + 0.5; +} + +void node_tex_environment_empty(vec3 co, out vec4 color) +{ + color = vec4(1.0, 0.0, 1.0, 1.0); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_gradient.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_gradient.glsl new file mode 100644 index 00000000000..f2f7e615267 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_gradient.glsl @@ -0,0 +1,47 @@ +float calc_gradient(vec3 p, int gradient_type) +{ + float x, y, z; + x = p.x; + y = p.y; + z = p.z; + if (gradient_type == 0) { /* linear */ + return x; + } + else if (gradient_type == 1) { /* quadratic */ + float r = max(x, 0.0); + return r * r; + } + else if (gradient_type == 2) { /* easing */ + float r = min(max(x, 0.0), 1.0); + float t = r * r; + return (3.0 * t - 2.0 * t * r); + } + else if (gradient_type == 3) { /* diagonal */ + return (x + y) * 0.5; + } + else if (gradient_type == 4) { /* radial */ + return atan(y, x) / (M_PI * 2) + 0.5; + } + else { + /* Bias a little bit for the case where p is a unit length vector, + * to get exactly zero instead of a small random value depending + * on float precision. */ + float r = max(0.999999 - sqrt(x * x + y * y + z * z), 0.0); + if (gradient_type == 5) { /* quadratic sphere */ + return r * r; + } + else if (gradient_type == 6) { /* sphere */ + return r; + } + } + return 0.0; +} + +void node_tex_gradient(vec3 co, float gradient_type, out vec4 color, out float fac) +{ + float f = calc_gradient(co, int(gradient_type)); + f = clamp(f, 0.0, 1.0); + + color = vec4(f, f, f, 1.0); + fac = f; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl new file mode 100644 index 00000000000..c234e064d36 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl @@ -0,0 +1,355 @@ +void point_texco_remap_square(vec3 vin, out vec3 vout) +{ + vout = vin * 2.0 - 1.0; +} + +void point_texco_clamp(vec3 vin, sampler2D ima, out vec3 vout) +{ + vec2 half_texel_size = 0.5 / vec2(textureSize(ima, 0).xy); + vout = clamp(vin, half_texel_size.xyy, 1.0 - half_texel_size.xyy); +} + +void point_map_to_sphere(vec3 vin, out vec3 vout) +{ + float len = length(vin); + float v, u; + if (len > 0.0) { + if (vin.x == 0.0 && vin.y == 0.0) { + u = 0.0; + } + else { + u = (1.0 - atan(vin.x, vin.y) / M_PI) / 2.0; + } + + v = 1.0 - acos(vin.z / len) / M_PI; + } + else { + v = u = 0.0; + } + + vout = vec3(u, v, 0.0); +} + +void point_map_to_tube(vec3 vin, out vec3 vout) +{ + float u, v; + v = (vin.z + 1.0) * 0.5; + float len = sqrt(vin.x * vin.x + vin.y * vin[1]); + if (len > 0.0) { + u = (1.0 - (atan(vin.x / len, vin.y / len) / M_PI)) * 0.5; + } + else { + v = u = 0.0; + } + + vout = vec3(u, v, 0.0); +} + +/* 16bits floats limits. Higher/Lower values produce +/-inf. */ +#define safe_color(a) (clamp(a, -65520.0, 65520.0)) + +void node_tex_image_linear(vec3 co, sampler2D ima, out vec4 color, out float alpha) +{ + color = safe_color(texture(ima, co.xy)); + alpha = color.a; +} + +void node_tex_image_linear_no_mip(vec3 co, sampler2D ima, out vec4 color, out float alpha) +{ + color = safe_color(textureLod(ima, co.xy, 0.0)); + alpha = color.a; +} + +void node_tex_image_nearest(vec3 co, sampler2D ima, out vec4 color, out float alpha) +{ + ivec2 pix = ivec2(fract(co.xy) * textureSize(ima, 0).xy); + color = safe_color(texelFetch(ima, pix, 0)); + alpha = color.a; +} + +/* @arg f: signed distance to texel center. */ +void cubic_bspline_coefs(vec2 f, out vec2 w0, out vec2 w1, out vec2 w2, out vec2 w3) +{ + vec2 f2 = f * f; + vec2 f3 = f2 * f; + /* Bspline coefs (optimized) */ + w3 = f3 / 6.0; + w0 = -w3 + f2 * 0.5 - f * 0.5 + 1.0 / 6.0; + w1 = f3 * 0.5 - f2 * 1.0 + 2.0 / 3.0; + w2 = 1.0 - w0 - w1 - w3; +} + +void node_tex_image_cubic_ex( + vec3 co, sampler2D ima, float do_extend, out vec4 color, out float alpha) +{ + vec2 tex_size = vec2(textureSize(ima, 0).xy); + + co.xy *= tex_size; + /* texel center */ + vec2 tc = floor(co.xy - 0.5) + 0.5; + vec2 w0, w1, w2, w3; + cubic_bspline_coefs(co.xy - tc, w0, w1, w2, w3); + +#if 1 /* Optimized version using 4 filtered tap. */ + vec2 s0 = w0 + w1; + vec2 s1 = w2 + w3; + + vec2 f0 = w1 / (w0 + w1); + vec2 f1 = w3 / (w2 + w3); + + vec4 final_co; + final_co.xy = tc - 1.0 + f0; + final_co.zw = tc + 1.0 + f1; + + if (do_extend == 1.0) { + final_co = clamp(final_co, vec4(0.5), tex_size.xyxy - 0.5); + } + final_co /= tex_size.xyxy; + + color = safe_color(textureLod(ima, final_co.xy, 0.0)) * s0.x * s0.y; + color += safe_color(textureLod(ima, final_co.zy, 0.0)) * s1.x * s0.y; + color += safe_color(textureLod(ima, final_co.xw, 0.0)) * s0.x * s1.y; + color += safe_color(textureLod(ima, final_co.zw, 0.0)) * s1.x * s1.y; + +#else /* Reference bruteforce 16 tap. */ + color = texelFetch(ima, ivec2(tc + vec2(-1.0, -1.0)), 0) * w0.x * w0.y; + color += texelFetch(ima, ivec2(tc + vec2(0.0, -1.0)), 0) * w1.x * w0.y; + color += texelFetch(ima, ivec2(tc + vec2(1.0, -1.0)), 0) * w2.x * w0.y; + color += texelFetch(ima, ivec2(tc + vec2(2.0, -1.0)), 0) * w3.x * w0.y; + + color += texelFetch(ima, ivec2(tc + vec2(-1.0, 0.0)), 0) * w0.x * w1.y; + color += texelFetch(ima, ivec2(tc + vec2(0.0, 0.0)), 0) * w1.x * w1.y; + color += texelFetch(ima, ivec2(tc + vec2(1.0, 0.0)), 0) * w2.x * w1.y; + color += texelFetch(ima, ivec2(tc + vec2(2.0, 0.0)), 0) * w3.x * w1.y; + + color += texelFetch(ima, ivec2(tc + vec2(-1.0, 1.0)), 0) * w0.x * w2.y; + color += texelFetch(ima, ivec2(tc + vec2(0.0, 1.0)), 0) * w1.x * w2.y; + color += texelFetch(ima, ivec2(tc + vec2(1.0, 1.0)), 0) * w2.x * w2.y; + color += texelFetch(ima, ivec2(tc + vec2(2.0, 1.0)), 0) * w3.x * w2.y; + + color += texelFetch(ima, ivec2(tc + vec2(-1.0, 2.0)), 0) * w0.x * w3.y; + color += texelFetch(ima, ivec2(tc + vec2(0.0, 2.0)), 0) * w1.x * w3.y; + color += texelFetch(ima, ivec2(tc + vec2(1.0, 2.0)), 0) * w2.x * w3.y; + color += texelFetch(ima, ivec2(tc + vec2(2.0, 2.0)), 0) * w3.x * w3.y; +#endif + + alpha = color.a; +} + +void node_tex_image_cubic(vec3 co, sampler2D ima, out vec4 color, out float alpha) +{ + node_tex_image_cubic_ex(co, ima, 0.0, color, alpha); +} + +void node_tex_image_cubic_extend(vec3 co, sampler2D ima, out vec4 color, out float alpha) +{ + node_tex_image_cubic_ex(co, ima, 1.0, color, alpha); +} + +void node_tex_image_smart(vec3 co, sampler2D ima, out vec4 color, out float alpha) +{ + /* use cubic for now */ + node_tex_image_cubic_ex(co, ima, 0.0, color, alpha); +} + +void tex_box_sample_linear( + vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3) +{ + /* X projection */ + vec2 uv = texco.yz; + if (N.x < 0.0) { + uv.x = 1.0 - uv.x; + } + color1 = texture(ima, uv); + /* Y projection */ + uv = texco.xz; + if (N.y > 0.0) { + uv.x = 1.0 - uv.x; + } + color2 = texture(ima, uv); + /* Z projection */ + uv = texco.yx; + if (N.z > 0.0) { + uv.x = 1.0 - uv.x; + } + color3 = texture(ima, uv); +} + +void tex_box_sample_nearest( + vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3) +{ + /* X projection */ + vec2 uv = texco.yz; + if (N.x < 0.0) { + uv.x = 1.0 - uv.x; + } + ivec2 pix = ivec2(uv.xy * textureSize(ima, 0).xy); + color1 = texelFetch(ima, pix, 0); + /* Y projection */ + uv = texco.xz; + if (N.y > 0.0) { + uv.x = 1.0 - uv.x; + } + pix = ivec2(uv.xy * textureSize(ima, 0).xy); + color2 = texelFetch(ima, pix, 0); + /* Z projection */ + uv = texco.yx; + if (N.z > 0.0) { + uv.x = 1.0 - uv.x; + } + pix = ivec2(uv.xy * textureSize(ima, 0).xy); + color3 = texelFetch(ima, pix, 0); +} + +void tex_box_sample_cubic( + vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3) +{ + float alpha; + /* X projection */ + vec2 uv = texco.yz; + if (N.x < 0.0) { + uv.x = 1.0 - uv.x; + } + node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color1, alpha); + /* Y projection */ + uv = texco.xz; + if (N.y > 0.0) { + uv.x = 1.0 - uv.x; + } + node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color2, alpha); + /* Z projection */ + uv = texco.yx; + if (N.z > 0.0) { + uv.x = 1.0 - uv.x; + } + node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color3, alpha); +} + +void tex_box_sample_smart( + vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3) +{ + tex_box_sample_cubic(texco, N, ima, color1, color2, color3); +} + +void node_tex_image_box(vec3 texco, + vec3 N, + vec4 color1, + vec4 color2, + vec4 color3, + sampler2D ima, + float blend, + out vec4 color, + out float alpha) +{ + /* project from direction vector to barycentric coordinates in triangles */ + N = abs(N); + N /= dot(N, vec3(1.0)); + + /* basic idea is to think of this as a triangle, each corner representing + * one of the 3 faces of the cube. in the corners we have single textures, + * in between we blend between two textures, and in the middle we a blend + * between three textures. + * + * the Nxyz values are the barycentric coordinates in an equilateral + * triangle, which in case of blending, in the middle has a smaller + * equilateral triangle where 3 textures blend. this divides things into + * 7 zones, with an if () test for each zone + * EDIT: Now there is only 4 if's. */ + + float limit = 0.5 + 0.5 * blend; + + vec3 weight; + weight = N.xyz / (N.xyx + N.yzz); + weight = clamp((weight - 0.5 * (1.0 - blend)) / max(1e-8, blend), 0.0, 1.0); + + /* test for mixes between two textures */ + if (N.z < (1.0 - limit) * (N.y + N.x)) { + weight.z = 0.0; + weight.y = 1.0 - weight.x; + } + else if (N.x < (1.0 - limit) * (N.y + N.z)) { + weight.x = 0.0; + weight.z = 1.0 - weight.y; + } + else if (N.y < (1.0 - limit) * (N.x + N.z)) { + weight.y = 0.0; + weight.x = 1.0 - weight.z; + } + else { + /* last case, we have a mix between three */ + weight = ((2.0 - limit) * N + (limit - 1.0)) / max(1e-8, blend); + } + + color = weight.x * color1 + weight.y * color2 + weight.z * color3; + alpha = color.a; +} + +void tex_clip_linear(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha) +{ + vec2 tex_size = vec2(textureSize(ima, 0).xy); + vec2 minco = min(co.xy, 1.0 - co.xy); + minco = clamp(minco * tex_size + 0.5, 0.0, 1.0); + float fac = minco.x * minco.y; + + color = mix(vec4(0.0), icolor, fac); + alpha = color.a; +} + +void tex_clip_nearest(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha) +{ + vec4 minco = vec4(co.xy, 1.0 - co.xy); + color = (any(lessThan(minco, vec4(0.0)))) ? vec4(0.0) : icolor; + alpha = color.a; +} + +void tex_clip_cubic(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha) +{ + vec2 tex_size = vec2(textureSize(ima, 0).xy); + + co.xy *= tex_size; + /* texel center */ + vec2 tc = floor(co.xy - 0.5) + 0.5; + vec2 w0, w1, w2, w3; + cubic_bspline_coefs(co.xy - tc, w0, w1, w2, w3); + + /* TODO Optimize this part. I'm sure there is a smarter way to do that. + * Could do that when sampling? */ +#define CLIP_CUBIC_SAMPLE(samp, size) \ + (float(all(greaterThan(samp, vec2(-0.5)))) * float(all(lessThan(ivec2(samp), itex_size)))) + ivec2 itex_size = textureSize(ima, 0).xy; + float fac; + fac = CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, -1.0), itex_size) * w0.x * w0.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, -1.0), itex_size) * w1.x * w0.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, -1.0), itex_size) * w2.x * w0.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, -1.0), itex_size) * w3.x * w0.y; + + fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 0.0), itex_size) * w0.x * w1.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, 0.0), itex_size) * w1.x * w1.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, 0.0), itex_size) * w2.x * w1.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, 0.0), itex_size) * w3.x * w1.y; + + fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 1.0), itex_size) * w0.x * w2.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, 1.0), itex_size) * w1.x * w2.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, 1.0), itex_size) * w2.x * w2.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, 1.0), itex_size) * w3.x * w2.y; + + fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 2.0), itex_size) * w0.x * w3.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, 2.0), itex_size) * w1.x * w3.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, 2.0), itex_size) * w2.x * w3.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, 2.0), itex_size) * w3.x * w3.y; +#undef CLIP_CUBIC_SAMPLE + + color = mix(vec4(0.0), icolor, fac); + alpha = color.a; +} + +void tex_clip_smart(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha) +{ + tex_clip_cubic(co, ima, icolor, color, alpha); +} + +void node_tex_image_empty(vec3 co, out vec4 color, out float alpha) +{ + color = vec4(0.0); + alpha = 0.0; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_magic.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_magic.glsl new file mode 100644 index 00000000000..942c507cc38 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_magic.glsl @@ -0,0 +1,61 @@ +void node_tex_magic( + vec3 co, float scale, float distortion, float depth, out vec4 color, out float fac) +{ + vec3 p = co * scale; + float x = sin((p.x + p.y + p.z) * 5.0); + float y = cos((-p.x + p.y - p.z) * 5.0); + float z = -cos((-p.x - p.y + p.z) * 5.0); + + if (depth > 0) { + x *= distortion; + y *= distortion; + z *= distortion; + y = -cos(x - y + z); + y *= distortion; + if (depth > 1) { + x = cos(x - y - z); + x *= distortion; + if (depth > 2) { + z = sin(-x - y - z); + z *= distortion; + if (depth > 3) { + x = -cos(-x + y - z); + x *= distortion; + if (depth > 4) { + y = -sin(-x + y + z); + y *= distortion; + if (depth > 5) { + y = -cos(-x + y + z); + y *= distortion; + if (depth > 6) { + x = cos(x + y + z); + x *= distortion; + if (depth > 7) { + z = sin(x + y - z); + z *= distortion; + if (depth > 8) { + x = -cos(-x - y + z); + x *= distortion; + if (depth > 9) { + y = -sin(x - y + z); + y *= distortion; + } + } + } + } + } + } + } + } + } + } + if (distortion != 0.0) { + distortion *= 2.0; + x /= distortion; + y /= distortion; + z /= distortion; + } + + color = vec4(0.5 - x, 0.5 - y, 0.5 - z, 1.0); + fac = (color.x + color.y + color.z) / 3.0; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_musgrave.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_musgrave.glsl new file mode 100644 index 00000000000..52332c45c3d --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_musgrave.glsl @@ -0,0 +1,208 @@ +/* Musgrave fBm + * + * H: fractal increment parameter + * lacunarity: gap between successive frequencies + * octaves: number of frequencies in the fBm + * + * from "Texturing and Modelling: A procedural approach" + */ + +float noise_musgrave_fBm(vec3 p, float H, float lacunarity, float octaves) +{ + float rmd; + float value = 0.0; + float pwr = 1.0; + float pwHL = pow(lacunarity, -H); + + for (int i = 0; i < int(octaves); i++) { + value += snoise(p) * pwr; + pwr *= pwHL; + p *= lacunarity; + } + + rmd = octaves - floor(octaves); + if (rmd != 0.0) { + value += rmd * snoise(p) * pwr; + } + + return value; +} + +/* Musgrave Multifractal + * + * H: highest fractal dimension + * lacunarity: gap between successive frequencies + * octaves: number of frequencies in the fBm + */ + +float noise_musgrave_multi_fractal(vec3 p, float H, float lacunarity, float octaves) +{ + float rmd; + float value = 1.0; + float pwr = 1.0; + float pwHL = pow(lacunarity, -H); + + for (int i = 0; i < int(octaves); i++) { + value *= (pwr * snoise(p) + 1.0); + pwr *= pwHL; + p *= lacunarity; + } + + rmd = octaves - floor(octaves); + if (rmd != 0.0) { + value *= (rmd * pwr * snoise(p) + 1.0); /* correct? */ + } + + return value; +} + +/* Musgrave Heterogeneous Terrain + * + * H: fractal dimension of the roughest area + * lacunarity: gap between successive frequencies + * octaves: number of frequencies in the fBm + * offset: raises the terrain from `sea level' + */ + +float noise_musgrave_hetero_terrain(vec3 p, float H, float lacunarity, float octaves, float offset) +{ + float value, increment, rmd; + float pwHL = pow(lacunarity, -H); + float pwr = pwHL; + + /* first unscaled octave of function; later octaves are scaled */ + value = offset + snoise(p); + p *= lacunarity; + + for (int i = 1; i < int(octaves); i++) { + increment = (snoise(p) + offset) * pwr * value; + value += increment; + pwr *= pwHL; + p *= lacunarity; + } + + rmd = octaves - floor(octaves); + if (rmd != 0.0) { + increment = (snoise(p) + offset) * pwr * value; + value += rmd * increment; + } + + return value; +} + +/* Hybrid Additive/Multiplicative Multifractal Terrain + * + * H: fractal dimension of the roughest area + * lacunarity: gap between successive frequencies + * octaves: number of frequencies in the fBm + * offset: raises the terrain from `sea level' + */ + +float noise_musgrave_hybrid_multi_fractal( + vec3 p, float H, float lacunarity, float octaves, float offset, float gain) +{ + float result, signal, weight, rmd; + float pwHL = pow(lacunarity, -H); + float pwr = pwHL; + + result = snoise(p) + offset; + weight = gain * result; + p *= lacunarity; + + for (int i = 1; (weight > 0.001f) && (i < int(octaves)); i++) { + if (weight > 1.0) { + weight = 1.0; + } + + signal = (snoise(p) + offset) * pwr; + pwr *= pwHL; + result += weight * signal; + weight *= gain * signal; + p *= lacunarity; + } + + rmd = octaves - floor(octaves); + if (rmd != 0.0) { + result += rmd * ((snoise(p) + offset) * pwr); + } + + return result; +} + +/* Ridged Multifractal Terrain + * + * H: fractal dimension of the roughest area + * lacunarity: gap between successive frequencies + * octaves: number of frequencies in the fBm + * offset: raises the terrain from `sea level' + */ + +float noise_musgrave_ridged_multi_fractal( + vec3 p, float H, float lacunarity, float octaves, float offset, float gain) +{ + float result, signal, weight; + float pwHL = pow(lacunarity, -H); + float pwr = pwHL; + + signal = offset - abs(snoise(p)); + signal *= signal; + result = signal; + weight = 1.0; + + for (int i = 1; i < int(octaves); i++) { + p *= lacunarity; + weight = clamp(signal * gain, 0.0, 1.0); + signal = offset - abs(snoise(p)); + signal *= signal; + signal *= weight; + result += signal * pwr; + pwr *= pwHL; + } + + return result; +} + +float svm_musgrave(int type, + float dimension, + float lacunarity, + float octaves, + float offset, + float intensity, + float gain, + vec3 p) +{ + if (type == 0 /* NODE_MUSGRAVE_MULTIFRACTAL */) { + return intensity * noise_musgrave_multi_fractal(p, dimension, lacunarity, octaves); + } + else if (type == 1 /* NODE_MUSGRAVE_FBM */) { + return intensity * noise_musgrave_fBm(p, dimension, lacunarity, octaves); + } + else if (type == 2 /* NODE_MUSGRAVE_HYBRID_MULTIFRACTAL */) { + return intensity * + noise_musgrave_hybrid_multi_fractal(p, dimension, lacunarity, octaves, offset, gain); + } + else if (type == 3 /* NODE_MUSGRAVE_RIDGED_MULTIFRACTAL */) { + return intensity * + noise_musgrave_ridged_multi_fractal(p, dimension, lacunarity, octaves, offset, gain); + } + else if (type == 4 /* NODE_MUSGRAVE_HETERO_TERRAIN */) { + return intensity * noise_musgrave_hetero_terrain(p, dimension, lacunarity, octaves, offset); + } + return 0.0; +} + +void node_tex_musgrave(vec3 co, + float scale, + float detail, + float dimension, + float lacunarity, + float offset, + float gain, + float type, + out vec4 color, + out float fac) +{ + fac = svm_musgrave(int(type), dimension, lacunarity, detail, offset, 1.0, gain, co *scale); + + color = vec4(fac, fac, fac, 1.0); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_noise.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_noise.glsl new file mode 100644 index 00000000000..30e27da16e8 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_noise.glsl @@ -0,0 +1,19 @@ +void node_tex_noise( + vec3 co, float scale, float detail, float distortion, out vec4 color, out float fac) +{ + vec3 p = co * scale; + int hard = 0; + if (distortion != 0.0) { + vec3 r, offset = vec3(13.5, 13.5, 13.5); + r.x = noise(p + offset) * distortion; + r.y = noise(p) * distortion; + r.z = noise(p - offset) * distortion; + p += r; + } + + fac = noise_turbulence(p, detail, hard); + color = vec4(fac, + noise_turbulence(vec3(p.y, p.x, p.z), detail, hard), + noise_turbulence(vec3(p.y, p.z, p.x), detail, hard), + 1); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_sky.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_sky.glsl new file mode 100644 index 00000000000..981d17b4283 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_sky.glsl @@ -0,0 +1,4 @@ +void node_tex_sky(vec3 co, out vec4 color) +{ + color = vec4(1.0); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_voronoi.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_voronoi.glsl new file mode 100644 index 00000000000..018b74fd1a5 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_voronoi.glsl @@ -0,0 +1,116 @@ +void node_tex_voronoi(vec3 co, + float scale, + float exponent, + float coloring, + float metric, + float feature, + out vec4 color, + out float fac) +{ + vec3 p = co * scale; + int xx, yy, zz, xi, yi, zi; + vec4 da = vec4(1e10); + vec3 pa[4] = vec3[4](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0)); + + xi = floor_to_int(p[0]); + yi = floor_to_int(p[1]); + zi = floor_to_int(p[2]); + + for (xx = xi - 1; xx <= xi + 1; xx++) { + for (yy = yi - 1; yy <= yi + 1; yy++) { + for (zz = zi - 1; zz <= zi + 1; zz++) { + vec3 ip = vec3(xx, yy, zz); + vec3 vp = cellnoise_color(ip); + vec3 pd = p - (vp + ip); + + float d = 0.0; + if (metric == 0.0) { /* SHD_VORONOI_DISTANCE 0 */ + d = dot(pd, pd); + } + else if (metric == 1.0) { /* SHD_VORONOI_MANHATTAN 1 */ + d = abs(pd[0]) + abs(pd[1]) + abs(pd[2]); + } + else if (metric == 2.0) { /* SHD_VORONOI_CHEBYCHEV 2 */ + d = max(abs(pd[0]), max(abs(pd[1]), abs(pd[2]))); + } + else if (metric == 3.0) { /* SHD_VORONOI_MINKOWSKI 3 */ + d = pow(pow(abs(pd[0]), exponent) + pow(abs(pd[1]), exponent) + + pow(abs(pd[2]), exponent), + 1.0 / exponent); + } + + vp += vec3(xx, yy, zz); + if (d < da[0]) { + da.yzw = da.xyz; + da[0] = d; + + pa[3] = pa[2]; + pa[2] = pa[1]; + pa[1] = pa[0]; + pa[0] = vp; + } + else if (d < da[1]) { + da.zw = da.yz; + da[1] = d; + + pa[3] = pa[2]; + pa[2] = pa[1]; + pa[1] = vp; + } + else if (d < da[2]) { + da[3] = da[2]; + da[2] = d; + + pa[3] = pa[2]; + pa[2] = vp; + } + else if (d < da[3]) { + da[3] = d; + pa[3] = vp; + } + } + } + } + + if (coloring == 0.0) { + /* Intensity output */ + if (feature == 0.0) { /* F1 */ + fac = abs(da[0]); + } + else if (feature == 1.0) { /* F2 */ + fac = abs(da[1]); + } + else if (feature == 2.0) { /* F3 */ + fac = abs(da[2]); + } + else if (feature == 3.0) { /* F4 */ + fac = abs(da[3]); + } + else if (feature == 4.0) { /* F2F1 */ + fac = abs(da[1] - da[0]); + } + color = vec4(fac, fac, fac, 1.0); + } + else { + /* Color output */ + vec3 col = vec3(fac, fac, fac); + if (feature == 0.0) { /* F1 */ + col = pa[0]; + } + else if (feature == 1.0) { /* F2 */ + col = pa[1]; + } + else if (feature == 2.0) { /* F3 */ + col = pa[2]; + } + else if (feature == 3.0) { /* F4 */ + col = pa[3]; + } + else if (feature == 4.0) { /* F2F1 */ + col = abs(pa[1] - pa[0]); + } + + color = vec4(cellnoise_color(col), 1.0); + fac = (color.x + color.y + color.z) * (1.0 / 3.0); + } +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_wave.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_wave.glsl new file mode 100644 index 00000000000..2196848a4ef --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_wave.glsl @@ -0,0 +1,42 @@ +float calc_wave( + vec3 p, float distortion, float detail, float detail_scale, int wave_type, int wave_profile) +{ + float n; + + if (wave_type == 0) { /* type bands */ + n = (p.x + p.y + p.z) * 10.0; + } + else { /* type rings */ + n = length(p) * 20.0; + } + + if (distortion != 0.0) { + n += distortion * noise_turbulence(p * detail_scale, detail, 0); + } + + if (wave_profile == 0) { /* profile sin */ + return 0.5 + 0.5 * sin(n); + } + else { /* profile saw */ + n /= 2.0 * M_PI; + n -= int(n); + return (n < 0.0) ? n + 1.0 : n; + } +} + +void node_tex_wave(vec3 co, + float scale, + float distortion, + float detail, + float detail_scale, + float wave_type, + float wave_profile, + out vec4 color, + out float fac) +{ + float f; + f = calc_wave(co * scale, distortion, detail, detail_scale, int(wave_type), int(wave_profile)); + + color = vec4(f, f, f, 1.0); + fac = f; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_white_noise.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_white_noise.glsl new file mode 100644 index 00000000000..fce511deb79 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_white_noise.glsl @@ -0,0 +1,21 @@ +/* White Noise */ + +void node_white_noise_1d(vec3 vector, float w, out float value) +{ + value = hash_float_to_float(w); +} + +void node_white_noise_2d(vec3 vector, float w, out float value) +{ + value = hash_vec2_to_float(vector.xy); +} + +void node_white_noise_3d(vec3 vector, float w, out float value) +{ + value = hash_vec3_to_float(vector); +} + +void node_white_noise_4d(vec3 vector, float w, out float value) +{ + value = hash_vec4_to_float(vec4(vector, w)); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_texture_coordinates.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_texture_coordinates.glsl new file mode 100644 index 00000000000..24276156d55 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_texture_coordinates.glsl @@ -0,0 +1,92 @@ +vec3 mtex_2d_mapping(vec3 vec) +{ + return vec3(vec.xy * 0.5 + vec2(0.5), vec.z); +} + +void generated_from_orco(vec3 orco, out vec3 generated) +{ +#ifdef VOLUMETRICS +# ifdef MESH_SHADER + generated = volumeObjectLocalCoord; +# else + generated = worldPosition; +# endif +#else + generated = orco; +#endif +} + +void generated_texco(vec3 I, vec3 attr_orco, out vec3 generated) +{ + vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); + vec4 co_homogenous = (ProjectionMatrixInverse * v); + vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0); + co.xyz = normalize(co.xyz); +#if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE) + generated = (ViewMatrixInverse * co).xyz; +#else + generated_from_orco(attr_orco, generated); +#endif +} + +void node_tex_coord(vec3 I, + vec3 wN, + mat4 obmatinv, + vec4 camerafac, + vec3 attr_orco, + vec3 attr_uv, + out vec3 generated, + out vec3 normal, + out vec3 uv, + out vec3 object, + out vec3 camera, + out vec3 window, + out vec3 reflection) +{ + generated = attr_orco; + normal = normalize(normal_world_to_object(wN)); + uv = attr_uv; + object = (obmatinv * (ViewMatrixInverse * vec4(I, 1.0))).xyz; + camera = vec3(I.xy, -I.z); + vec4 projvec = ProjectionMatrix * vec4(I, 1.0); + window = vec3(mtex_2d_mapping(projvec.xyz / projvec.w).xy * camerafac.xy + camerafac.zw, 0.0); + reflection = -reflect(cameraVec, normalize(wN)); +} + +void node_tex_coord_background(vec3 I, + vec3 N, + mat4 obmatinv, + vec4 camerafac, + vec3 attr_orco, + vec3 attr_uv, + out vec3 generated, + out vec3 normal, + out vec3 uv, + out vec3 object, + out vec3 camera, + out vec3 window, + out vec3 reflection) +{ + vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); + vec4 co_homogenous = (ProjectionMatrixInverse * v); + + vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0); + + co = normalize(co); + + vec3 coords = (ViewMatrixInverse * co).xyz; + + generated = coords; + normal = -coords; + uv = vec3(attr_uv.xy, 0.0); + object = (obmatinv * vec4(coords, 1.0)).xyz; + + camera = vec3(co.xy, -co.z); + window = vec3(mtex_2d_mapping(I).xy * camerafac.xy + camerafac.zw, 0.0); + + reflection = -coords; +} + +#if defined(WORLD_BACKGROUND) || (defined(PROBE_CAPTURE) && !defined(MESH_SHADER)) +# define node_tex_coord node_tex_coord_background +#endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_toon.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_toon.glsl new file mode 100644 index 00000000000..02d288d42bf --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_toon.glsl @@ -0,0 +1,9 @@ +#ifndef VOLUMETRICS +void node_bsdf_toon(vec4 color, float size, float tsmooth, vec3 N, out Closure result) +{ + node_bsdf_diffuse(color, 0.0, N, result); +} +#else +/* Stub toon because it is not compatible with volumetrics. */ +# define node_bsdf_toon +#endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_translucent.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_translucent.glsl new file mode 100644 index 00000000000..ea41790e6aa --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_translucent.glsl @@ -0,0 +1,9 @@ +#ifndef VOLUMETRICS +void node_bsdf_translucent(vec4 color, vec3 N, out Closure result) +{ + node_bsdf_diffuse(color, 0.0, -N, result); +} +#else +/* Stub translucent because it is not compatible with volumetrics. */ +# define node_bsdf_translucent +#endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_transparent.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_transparent.glsl new file mode 100644 index 00000000000..800d0f81d4a --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_transparent.glsl @@ -0,0 +1,11 @@ +#ifndef VOLUMETRICS +void node_bsdf_transparent(vec4 color, out Closure result) +{ + result = CLOSURE_DEFAULT; + result.radiance = vec3(0.0); + result.transmittance = abs(color.rgb); +} +#else +/* Stub transparent because it is not compatible with volumetrics. */ +# define node_bsdf_transparent +#endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_uv_map.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_uv_map.glsl new file mode 100644 index 00000000000..d8fcbbfc361 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_uv_map.glsl @@ -0,0 +1,4 @@ +void node_uvmap(vec3 attr_uv, out vec3 outvec) +{ + outvec = attr_uv; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_vector_curves.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_vector_curves.glsl new file mode 100644 index 00000000000..35d2e903cf4 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_vector_curves.glsl @@ -0,0 +1,8 @@ +void curves_vec(float fac, vec3 vec, sampler1DArray curvemap, float layer, out vec3 outvec) +{ + vec4 co = vec4(vec * 0.5 + 0.5, layer); + outvec.x = texture(curvemap, co.xw).x; + outvec.y = texture(curvemap, co.yw).y; + outvec.z = texture(curvemap, co.zw).z; + outvec = mix(vec, outvec, fac); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_vector_displacement.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_vector_displacement.glsl new file mode 100644 index 00000000000..b6b955dcdb4 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_vector_displacement.glsl @@ -0,0 +1,30 @@ +void node_vector_displacement_tangent(vec4 vector, + float midlevel, + float scale, + vec4 tangent, + vec3 normal, + mat4 obmat, + mat4 viewmat, + out vec3 result) +{ + /* TODO(fclem) this is broken. revisit latter. */ + vec3 N_object = normalize(((vec4(normal, 0.0) * viewmat) * obmat).xyz); + vec3 T_object = normalize(((vec4(tangent.xyz, 0.0) * viewmat) * obmat).xyz); + vec3 B_object = tangent.w * normalize(cross(N_object, T_object)); + + vec3 offset = (vector.xyz - vec3(midlevel)) * scale; + result = offset.x * T_object + offset.y * N_object + offset.z * B_object; + result = (obmat * vec4(result, 0.0)).xyz; +} + +void node_vector_displacement_object( + vec4 vector, float midlevel, float scale, mat4 obmat, out vec3 result) +{ + result = (vector.xyz - vec3(midlevel)) * scale; + result = (obmat * vec4(result, 0.0)).xyz; +} + +void node_vector_displacement_world(vec4 vector, float midlevel, float scale, out vec3 result) +{ + result = (vector.xyz - vec3(midlevel)) * scale; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_vector_math.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_vector_math.glsl new file mode 100644 index 00000000000..93132b6044f --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_vector_math.glsl @@ -0,0 +1,100 @@ +void vector_math_add(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outVector = a + b; +} + +void vector_math_subtract(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outVector = a - b; +} + +void vector_math_multiply(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outVector = a * b; +} + +void vector_math_divide(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outVector = safe_divide(a, b); +} + +void vector_math_cross(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outVector = cross(a, b); +} + +void vector_math_project(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + float lenSquared = dot(b, b); + outVector = (lenSquared != 0.0) ? (dot(a, b) / lenSquared) * b : vec3(0.0); +} + +void vector_math_reflect(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outVector = reflect(a, normalize(b)); +} + +void vector_math_dot(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outValue = dot(a, b); +} + +void vector_math_distance(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outValue = distance(a, b); +} + +void vector_math_length(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outValue = length(a); +} + +void vector_math_scale(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outVector = a * scale; +} + +void vector_math_normalize(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outVector = normalize(a); +} + +void vector_math_snap(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outVector = floor(safe_divide(a, b)) * b; +} + +void vector_math_floor(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outVector = floor(a); +} + +void vector_math_ceil(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outVector = ceil(a); +} + +void vector_math_modulo(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outVector = c_mod(a, b); +} + +void vector_math_fraction(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outVector = fract(a); +} + +void vector_math_absolute(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outVector = abs(a); +} + +void vector_math_minimum(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outVector = min(a, b); +} + +void vector_math_maximum(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outVector = max(a, b); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_velvet.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_velvet.glsl new file mode 100644 index 00000000000..9646ffff8ca --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_velvet.glsl @@ -0,0 +1,9 @@ +#ifndef VOLUMETRICS +void node_bsdf_velvet(vec4 color, float sigma, vec3 N, out Closure result) +{ + node_bsdf_diffuse(color, 0.0, N, result); +} +#else +/* Stub velvet because it is not compatible with volumetrics. */ +# define node_bsdf_velvet +#endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_volume_absorption.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_volume_absorption.glsl new file mode 100644 index 00000000000..e6c0880cd07 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_volume_absorption.glsl @@ -0,0 +1,8 @@ +void node_volume_absorption(vec4 color, float density, out Closure result) +{ +#ifdef VOLUMETRICS + result = Closure((1.0 - color.rgb) * density, vec3(0.0), vec3(0.0), 0.0); +#else + result = CLOSURE_DEFAULT; +#endif +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_volume_info.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_volume_info.glsl new file mode 100644 index 00000000000..501aeb6f34e --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_volume_info.glsl @@ -0,0 +1,88 @@ +void node_attribute_volume_density(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf) +{ +#if defined(MESH_SHADER) && defined(VOLUMETRICS) + vec3 cos = volumeObjectLocalCoord; +#else + vec3 cos = vec3(0.0); +#endif + outvec = texture(tex, cos).aaa; + outcol = vec4(outvec, 1.0); + outf = avg(outvec); +} + +uniform vec3 volumeColor = vec3(1.0); + +void node_attribute_volume_color(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf) +{ +#if defined(MESH_SHADER) && defined(VOLUMETRICS) + vec3 cos = volumeObjectLocalCoord; +#else + vec3 cos = vec3(0.0); +#endif + + vec4 value = texture(tex, cos).rgba; + /* Density is premultiplied for interpolation, divide it out here. */ + if (value.a > 1e-8) { + value.rgb /= value.a; + } + + outvec = value.rgb * volumeColor; + outcol = vec4(outvec, 1.0); + outf = avg(outvec); +} + +void node_attribute_volume_flame(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf) +{ +#if defined(MESH_SHADER) && defined(VOLUMETRICS) + vec3 cos = volumeObjectLocalCoord; +#else + vec3 cos = vec3(0.0); +#endif + outf = texture(tex, cos).r; + outvec = vec3(outf, outf, outf); + outcol = vec4(outf, outf, outf, 1.0); +} + +void node_attribute_volume_temperature( + sampler3D tex, vec2 temperature, out vec4 outcol, out vec3 outvec, out float outf) +{ +#if defined(MESH_SHADER) && defined(VOLUMETRICS) + vec3 cos = volumeObjectLocalCoord; +#else + vec3 cos = vec3(0.0); +#endif + float flame = texture(tex, cos).r; + + outf = (flame > 0.01) ? temperature.x + flame * (temperature.y - temperature.x) : 0.0; + outvec = vec3(outf, outf, outf); + outcol = vec4(outf, outf, outf, 1.0); +} + +void node_volume_info(sampler3D densitySampler, + sampler3D flameSampler, + vec2 temperature, + out vec4 outColor, + out float outDensity, + out float outFlame, + out float outTemprature) +{ +#if defined(MESH_SHADER) && defined(VOLUMETRICS) + vec3 p = volumeObjectLocalCoord; +#else + vec3 p = vec3(0.0); +#endif + + vec4 density = texture(densitySampler, p); + outDensity = density.a; + + /* Density is premultiplied for interpolation, divide it out here. */ + if (density.a > 1e-8) { + density.rgb /= density.a; + } + outColor = vec4(density.rgb * volumeColor, 1.0); + + float flame = texture(flameSampler, p).r; + outFlame = flame; + + outTemprature = (flame > 0.01) ? temperature.x + flame * (temperature.y - temperature.x) : 0.0; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_volume_principled.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_volume_principled.glsl new file mode 100644 index 00000000000..884d5415c51 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_volume_principled.glsl @@ -0,0 +1,67 @@ +void node_volume_principled(vec4 color, + float density, + float anisotropy, + vec4 absorption_color, + float emission_strength, + vec4 emission_color, + float blackbody_intensity, + vec4 blackbody_tint, + float temperature, + float density_attribute, + vec4 color_attribute, + float temperature_attribute, + sampler1DArray spectrummap, + float layer, + out Closure result) +{ +#ifdef VOLUMETRICS + vec3 absorption_coeff = vec3(0.0); + vec3 scatter_coeff = vec3(0.0); + vec3 emission_coeff = vec3(0.0); + + /* Compute density. */ + density = max(density, 0.0); + + if (density > 1e-5) { + density = max(density * density_attribute, 0.0); + } + + if (density > 1e-5) { + /* Compute scattering and absorption coefficients. */ + vec3 scatter_color = color.rgb * color_attribute.rgb; + + scatter_coeff = scatter_color * density; + absorption_color.rgb = sqrt(max(absorption_color.rgb, 0.0)); + absorption_coeff = max(1.0 - scatter_color, 0.0) * max(1.0 - absorption_color.rgb, 0.0) * + density; + } + + /* Compute emission. */ + emission_strength = max(emission_strength, 0.0); + + if (emission_strength > 1e-5) { + emission_coeff += emission_strength * emission_color.rgb; + } + + if (blackbody_intensity > 1e-3) { + /* Add temperature from attribute. */ + float T = max(temperature * max(temperature_attribute, 0.0), 0.0); + + /* Stefan-Boltzman law. */ + float T2 = T * T; + float T4 = T2 * T2; + float sigma = 5.670373e-8 * 1e-6 / M_PI; + float intensity = sigma * mix(1.0, T4, blackbody_intensity); + + if (intensity > 1e-5) { + vec4 bb; + node_blackbody(T, spectrummap, layer, bb); + emission_coeff += bb.rgb * blackbody_tint.rgb * intensity; + } + } + + result = Closure(absorption_coeff, scatter_coeff, emission_coeff, anisotropy); +#else + result = CLOSURE_DEFAULT; +#endif +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_volume_scatter.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_volume_scatter.glsl new file mode 100644 index 00000000000..02c54658be5 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_volume_scatter.glsl @@ -0,0 +1,8 @@ +void node_volume_scatter(vec4 color, float density, float anisotropy, out Closure result) +{ +#ifdef VOLUMETRICS + result = Closure(vec3(0.0), color.rgb * density, vec3(0.0), anisotropy); +#else + result = CLOSURE_DEFAULT; +#endif +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_wireframe.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_wireframe.glsl new file mode 100644 index 00000000000..2fcf1b8d914 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_wireframe.glsl @@ -0,0 +1,31 @@ +#ifndef VOLUMETRICS +void node_wireframe(float size, vec2 barycentric, vec3 barycentric_dist, out float fac) +{ + vec3 barys = barycentric.xyy; + barys.z = 1.0 - barycentric.x - barycentric.y; + + size *= 0.5; + vec3 s = step(-size, -barys * barycentric_dist); + + fac = max(s.x, max(s.y, s.z)); +} + +void node_wireframe_screenspace(float size, vec2 barycentric, out float fac) +{ + vec3 barys = barycentric.xyy; + barys.z = 1.0 - barycentric.x - barycentric.y; + + size *= (1.0 / 3.0); + vec3 dx = dFdx(barys); + vec3 dy = dFdy(barys); + vec3 deltas = sqrt(dx * dx + dy * dy); + + vec3 s = step(-deltas * size, -barys); + + fac = max(s.x, max(s.y, s.z)); +} +#else +/* Stub wireframe because it is not compatible with volumetrics. */ +# define node_wireframe +# define node_wireframe_screenspace +#endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_world_normals.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_world_normals.glsl new file mode 100644 index 00000000000..f9691beee6f --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_world_normals.glsl @@ -0,0 +1,25 @@ +/* TODO : clean this ifdef mess */ +void world_normals_get(out vec3 N) +{ +#ifndef VOLUMETRICS +# ifdef HAIR_SHADER + vec3 B = normalize(cross(worldNormal, hairTangent)); + float cos_theta; + if (hairThicknessRes == 1) { + vec4 rand = texelFetch(utilTex, ivec3(ivec2(gl_FragCoord.xy) % LUT_SIZE, 2.0), 0); + /* Random cosine normal distribution on the hair surface. */ + cos_theta = rand.x * 2.0 - 1.0; + } + else { + /* Shade as a cylinder. */ + cos_theta = hairThickTime / hairThickness; + } + float sin_theta = sqrt(max(0.0, 1.0 - cos_theta * cos_theta)); + N = normalize(worldNormal * sin_theta + B * cos_theta); +# else + N = gl_FrontFacing ? worldNormal : -worldNormal; +# endif +#else + generated_from_orco(vec3(0.0), N); +#endif +} diff --git a/source/blender/ikplugin/intern/itasc_plugin.cpp b/source/blender/ikplugin/intern/itasc_plugin.cpp index 883919d76ec..2ceedca59f7 100644 --- a/source/blender/ikplugin/intern/itasc_plugin.cpp +++ b/source/blender/ikplugin/intern/itasc_plugin.cpp @@ -879,7 +879,7 @@ static bool joint_callback(const iTaSC::Timestamp ×tamp, bPoseChannel *chan = ikchan->pchan; int dof; - // a channel can be splitted into multiple joints, so we get called multiple + // a channel can be split into multiple joints, so we get called multiple // times for one channel (this callback is only for 1 joint in the armature) // the IK_JointTarget structure is shared between multiple joint constraint // and the target joint values is computed only once, remember this in jointValid diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index 791e939db7f..7e7e489a6c3 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -46,8 +46,7 @@ * * IMB needs: * - \ref DNA module - * The listbase types are used for handling the memory - * management. + * The #ListBase types are used for handling the memory management. * - \ref blenlib module * blenlib handles guarded memory management in blender-style. * BLI_winstuff.h makes a few windows specific behaviors @@ -146,7 +145,8 @@ bool IMB_initImBuf( struct ImBuf *IMB_allocFromBuffer(const unsigned int *rect, const float *rectf, unsigned int w, - unsigned int h); + unsigned int h, + unsigned int channels); /** * diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c index 7d2f51af65e..75db3fd3c73 100644 --- a/source/blender/imbuf/intern/allocimbuf.c +++ b/source/blender/imbuf/intern/allocimbuf.c @@ -428,7 +428,8 @@ bool imb_addrectImBuf(ImBuf *ibuf) struct ImBuf *IMB_allocFromBuffer(const unsigned int *rect, const float *rectf, unsigned int w, - unsigned int h) + unsigned int h, + unsigned int channels) { ImBuf *ibuf = NULL; @@ -438,6 +439,7 @@ struct ImBuf *IMB_allocFromBuffer(const unsigned int *rect, ibuf = IMB_allocImBuf(w, h, 32, 0); + ibuf->channels = channels; if (rectf) { ibuf->rect_float = MEM_dupallocN(rectf); ibuf->flags |= IB_rectfloat; diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c index 28557277d72..46ddee25b0f 100644 --- a/source/blender/imbuf/intern/scaling.c +++ b/source/blender/imbuf/intern/scaling.c @@ -1629,8 +1629,8 @@ bool IMB_scaleImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int newy) return false; } - /* scaleup / scaledown functions below change ibuf->x and ibuf->y - * so we first scale the Z-buffer (if any) */ + /* Scale-up / scale-down functions below change ibuf->x and ibuf->y + * so we first scale the Z-buffer (if any). */ scalefast_Z_ImBuf(ibuf, newx, newy); /* try to scale common cases in a fast way */ diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index ef9069acb78..ed7416e06c9 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -467,7 +467,11 @@ typedef enum ID_Type { /* id->flag (persitent). */ enum { + /* Don't delete the datablock even if unused. */ LIB_FAKEUSER = 1 << 9, + /* The datablock structure is a sub-object of a different one. + * Direct persistent references are not allowed. */ + LIB_PRIVATE_DATA = 1 << 10, }; /** diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index a4cd31a1357..b7834e2c7e0 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -847,8 +847,7 @@ typedef enum eSAction_Flag { SACTION_POSEMARKERS_SHOW = (1 << 6), /* don't draw action channels using group colors (where applicable) */ SACTION_NODRAWGCOLORS = (1 << 7), - /* don't draw current frame number beside frame indicator */ - SACTION_NODRAWCFRANUM = (1 << 8), + /* SACTION_NODRAWCFRANUM = (1 << 8), DEPRECATED */ /* don't perform realtime updates */ SACTION_NOREALTIMEUPDATES = (1 << 10), /* move markers as well as keyframes */ diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index 1718aabc51d..70add4c156f 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -319,6 +319,10 @@ typedef struct DriverTarget { /** Transform channel index (for DVAR_TYPE_TRANSFORM_CHAN.)*/ short transChan; + /** Rotation channel calculation type. */ + char rotation_mode; + char _pad[7]; + /** * Flags for the validity of the target * (NOTE: these get reset every time the types change). @@ -358,10 +362,36 @@ typedef enum eDriverTarget_TransformChannels { DTAR_TRANSCHAN_SCALEY, DTAR_TRANSCHAN_SCALEZ, DTAR_TRANSCHAN_SCALE_AVG, + DTAR_TRANSCHAN_ROTW, MAX_DTAR_TRANSCHAN_TYPES, } eDriverTarget_TransformChannels; +/* Rotation channel mode for Driver Targets */ +typedef enum eDriverTarget_RotationMode { + /** Automatic euler mode. */ + DTAR_ROTMODE_AUTO = 0, + + /** Explicit euler rotation modes - must sync with BLI_math_rotation.h defines. */ + DTAR_ROTMODE_EULER_XYZ = 1, + DTAR_ROTMODE_EULER_XZY, + DTAR_ROTMODE_EULER_YXZ, + DTAR_ROTMODE_EULER_YZX, + DTAR_ROTMODE_EULER_ZXY, + DTAR_ROTMODE_EULER_ZYX, + + DTAR_ROTMODE_QUATERNION, + + /** Implements the very common Damped Track + child trick to decompose + * rotation into bending followed by twist around the remaining axis. */ + DTAR_ROTMODE_SWING_TWIST_X, + DTAR_ROTMODE_SWING_TWIST_Y, + DTAR_ROTMODE_SWING_TWIST_Z, + + DTAR_ROTMODE_EULER_MIN = DTAR_ROTMODE_EULER_XYZ, + DTAR_ROTMODE_EULER_MAX = DTAR_ROTMODE_EULER_ZYX, +} eDriverTarget_RotationMode; + /* --- */ /* maximum number of driver targets per variable */ diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index 93ce3d9769b..bae9c8f40ea 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -295,6 +295,8 @@ typedef struct Brush { float crease_pinch_factor; + float normal_radius_factor; + float plane_trim; /** Affectable height of brush (layer height for layer tool, i.e.). */ float height; @@ -302,7 +304,6 @@ typedef struct Brush { float texture_sample_bias; int curve_preset; - char _pad1[4]; /* overlay */ int texture_overlay_alpha; @@ -395,7 +396,7 @@ typedef enum eBrushFlags { BRUSH_LOCK_ALPHA = (1 << 14), BRUSH_ORIGINAL_NORMAL = (1 << 15), BRUSH_OFFSET_PRESSURE = (1 << 16), - BRUSH_FLAG_UNUSED_17 = (1 << 17), /* cleared */ + BRUSH_SCENE_SPACING = (1 << 17), BRUSH_SPACE_ATTEN = (1 << 18), BRUSH_ADAPTIVE_SPACE = (1 << 19), BRUSH_LOCK_SIZE = (1 << 20), diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index eda52fdf14a..42d58cb34d0 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -271,7 +271,8 @@ typedef struct bTrackToConstraint { typedef struct bRotateLikeConstraint { struct Object *tar; int flag; - int reserved1; + char euler_order; + char _pad[3]; /** MAX_ID_NAME-2. */ char subtarget[64]; } bRotateLikeConstraint; @@ -441,6 +442,13 @@ typedef struct bTransformConstraint { /** Extrapolate motion? if 0, confine to ranges. */ char expo; + /** Input rotation type - uses the same values as driver targets. */ + char from_rotation_mode; + /** Output euler order override. */ + char to_euler_order; + + char _pad[6]; + /** From_min/max defines range of target transform. */ float from_min[3]; /** To map on to to_min/max range. */ @@ -715,6 +723,20 @@ typedef enum eConstraintChannel_Flags { CONSTRAINT_CHANNEL_PROTECTED = (1 << 1), } eConstraintChannel_Flags; +/* Common enum for constraints that support override. */ +typedef enum eConstraint_EulerOrder { + /** Automatic euler mode. */ + CONSTRAINT_EULER_AUTO = 0, + + /** Explicit euler rotation modes - must sync with BLI_math_rotation.h defines. */ + CONSTRAINT_EULER_XYZ = 1, + CONSTRAINT_EULER_XZY, + CONSTRAINT_EULER_YXZ, + CONSTRAINT_EULER_YZX, + CONSTRAINT_EULER_ZXY, + CONSTRAINT_EULER_ZYX, +} eConstraint_EulerOrder; + /* -------------------------------------- */ /* bRotateLikeConstraint.flag */ @@ -748,6 +770,7 @@ typedef enum eCopyScale_Flags { SIZELIKE_Z = (1 << 2), SIZELIKE_OFFSET = (1 << 3), SIZELIKE_MULTIPLY = (1 << 4), + SIZELIKE_UNIFORM = (1 << 5), } eCopyScale_Flags; /* bTransformConstraint.to/from */ diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h index 5a169fe1d16..415eb03e26d 100644 --- a/source/blender/makesdna/DNA_customdata_types.h +++ b/source/blender/makesdna/DNA_customdata_types.h @@ -197,6 +197,9 @@ typedef enum CustomDataType { /** Data types that may be defined for all mesh elements types. */ #define CD_MASK_GENERIC_DATA (CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR) +/** Multires loop data. */ +#define CD_MASK_MULTIRES_GRIDS (CD_MASK_MDISPS | CD_GRID_PAINT_MASK) + typedef struct CustomData_MeshMasks { uint64_t vmask; uint64_t emask; diff --git a/source/blender/makesdna/DNA_documentation.h b/source/blender/makesdna/DNA_documentation.h index be11b3d9040..0251625292c 100644 --- a/source/blender/makesdna/DNA_documentation.h +++ b/source/blender/makesdna/DNA_documentation.h @@ -27,7 +27,7 @@ * blender file. There is an executable that scans all files, looking * for struct-s to serialize (hence sdna: Struct \ref DNA). From this * information, it builds a file with numbers that encode the format, - * the names of variables, and the plce to look for them. + * the names of variables, and the place to look for them. * * \section dnaissues Known issues with DNA * diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h index 663e4dd8e44..f934d70fcdf 100644 --- a/source/blender/makesdna/DNA_gpencil_modifier_types.h +++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h @@ -28,8 +28,6 @@ * (ONLY ADD NEW ITEMS AT THE END) */ -struct RNG; - typedef enum GpencilModifierType { eGpencilModifierType_None = 0, eGpencilModifierType_Noise = 1, @@ -82,6 +80,8 @@ typedef struct NoiseGpencilModifierData { GpencilModifierData modifier; /** Layer name. */ char layername[64]; + /** Material name. */ + char materialname[64]; /** Optional vertexgroup name, MAX_VGROUP_NAME. */ char vgname[64]; /** Custom index for passes. */ @@ -110,12 +110,15 @@ typedef enum eNoiseGpencil_Flag { GP_NOISE_INVERT_VGROUP = (1 << 8), GP_NOISE_MOD_UV = (1 << 9), GP_NOISE_INVERT_LAYERPASS = (1 << 10), + GP_NOISE_INVERT_MATERIAL = (1 << 11), } eNoiseGpencil_Flag; typedef struct SubdivGpencilModifierData { GpencilModifierData modifier; /** Layer name. */ char layername[64]; + /** Material name. */ + char materialname[64]; /** Custom index for passes. */ int pass_index; /** Flags. */ @@ -131,12 +134,15 @@ typedef enum eSubdivGpencil_Flag { GP_SUBDIV_INVERT_LAYER = (1 << 1), GP_SUBDIV_INVERT_PASS = (1 << 2), GP_SUBDIV_INVERT_LAYERPASS = (1 << 3), + GP_SUBDIV_INVERT_MATERIAL = (1 << 4), } eSubdivGpencil_Flag; typedef struct ThickGpencilModifierData { GpencilModifierData modifier; /** Layer name. */ char layername[64]; + /** Material name. */ + char materialname[64]; /** Optional vertexgroup name, MAX_VGROUP_NAME. */ char vgname[64]; /** Custom index for passes. */ @@ -157,6 +163,7 @@ typedef enum eThickGpencil_Flag { GP_THICK_CUSTOM_CURVE = (1 << 3), GP_THICK_NORMALIZE = (1 << 4), GP_THICK_INVERT_LAYERPASS = (1 << 5), + GP_THICK_INVERT_MATERIAL = (1 << 6), } eThickGpencil_Flag; typedef struct TimeGpencilModifierData { @@ -204,6 +211,8 @@ typedef struct TintGpencilModifierData { GpencilModifierData modifier; /** Layer name. */ char layername[64]; + /** Material name. */ + char materialname[64]; /** Custom index for passes. */ int pass_index; /** Flags. */ @@ -225,12 +234,15 @@ typedef enum eTintGpencil_Flag { GP_TINT_INVERT_LAYER = (1 << 1), GP_TINT_INVERT_PASS = (1 << 2), GP_TINT_INVERT_LAYERPASS = (1 << 3), + GP_TINT_INVERT_MATERIAL = (1 << 4), } eTintGpencil_Flag; typedef struct ColorGpencilModifierData { GpencilModifierData modifier; /** Layer name. */ char layername[64]; + /** Material name. */ + char materialname[64]; /** Custom index for passes. */ int pass_index; /** Flags. */ @@ -250,12 +262,15 @@ typedef enum eColorGpencil_Flag { GP_COLOR_INVERT_LAYER = (1 << 1), GP_COLOR_INVERT_PASS = (1 << 2), GP_COLOR_INVERT_LAYERPASS = (1 << 3), + GP_COLOR_INVERT_MATERIAL = (1 << 4), } eColorGpencil_Flag; typedef struct OpacityGpencilModifierData { GpencilModifierData modifier; /** Layer name. */ char layername[64]; + /** Material name. */ + char materialname[64]; /** Optional vertexgroup name, MAX_VGROUP_NAME. */ char vgname[64]; /** Custom index for passes. */ @@ -280,6 +295,7 @@ typedef enum eOpacityGpencil_Flag { GP_OPACITY_INVERT_VGROUP = (1 << 2), GP_OPACITY_CREATE_COLORS = (1 << 3), GP_OPACITY_INVERT_LAYERPASS = (1 << 4), + GP_OPACITY_INVERT_MATERIAL = (1 << 5), } eOpacityGpencil_Flag; typedef struct ArrayGpencilModifierData { @@ -309,6 +325,8 @@ typedef struct ArrayGpencilModifierData { int pass_index; /** Layer name. */ char layername[64]; + /** Material name. */ + char materialname[64]; /** Material replace (0 keep default). */ int mat_rpl; /** Custom index for passes. */ @@ -322,6 +340,7 @@ typedef enum eArrayGpencil_Flag { GP_ARRAY_INVERT_PASS = (1 << 3), GP_ARRAY_KEEP_ONTOP = (1 << 4), GP_ARRAY_INVERT_LAYERPASS = (1 << 5), + GP_ARRAY_INVERT_MATERIAL = (1 << 6), } eArrayGpencil_Flag; typedef struct BuildGpencilModifierData { @@ -331,6 +350,9 @@ typedef struct BuildGpencilModifierData { char layername[64]; int pass_index; + /** Material name. */ + char materialname[64]; + /** Custom index for passes. */ int layer_pass; @@ -401,6 +423,8 @@ typedef struct LatticeGpencilModifierData { struct Object *object; /** Layer name. */ char layername[64]; + /** Material name. */ + char materialname[64]; /** Optional vertexgroup name, MAX_VGROUP_NAME. */ char vgname[64]; /** Custom index for passes. */ @@ -419,6 +443,7 @@ typedef enum eLatticeGpencil_Flag { GP_LATTICE_INVERT_PASS = (1 << 1), GP_LATTICE_INVERT_VGROUP = (1 << 2), GP_LATTICE_INVERT_LAYERPASS = (1 << 3), + GP_LATTICE_INVERT_MATERIAL = (1 << 4), } eLatticeGpencil_Flag; typedef struct MirrorGpencilModifierData { @@ -426,6 +451,8 @@ typedef struct MirrorGpencilModifierData { struct Object *object; /** Layer name. */ char layername[64]; + /** Material name. */ + char materialname[64]; /** Custom index for passes. */ int pass_index; /** Flags. */ @@ -443,6 +470,7 @@ typedef enum eMirrorGpencil_Flag { GP_MIRROR_AXIS_Y = (1 << 4), GP_MIRROR_AXIS_Z = (1 << 5), GP_MIRROR_INVERT_LAYERPASS = (1 << 6), + GP_MIRROR_INVERT_MATERIAL = (1 << 7), } eMirrorGpencil_Flag; typedef struct HookGpencilModifierData { @@ -453,6 +481,8 @@ typedef struct HookGpencilModifierData { char subtarget[64]; /** Layer name. */ char layername[64]; + /** Material name. */ + char materialname[64]; /** Optional vertexgroup name, MAX_VGROUP_NAME. */ char vgname[64]; /** Custom index for passes. */ @@ -481,6 +511,7 @@ typedef enum eHookGpencil_Flag { GP_HOOK_INVERT_VGROUP = (1 << 2), GP_HOOK_UNIFORM_SPACE = (1 << 3), GP_HOOK_INVERT_LAYERPASS = (1 << 4), + GP_HOOK_INVERT_MATERIAL = (1 << 5), } eHookGpencil_Flag; typedef enum eHookGpencil_Falloff { @@ -499,6 +530,8 @@ typedef struct SimplifyGpencilModifierData { GpencilModifierData modifier; /** Layer name. */ char layername[64]; + /** Material name. */ + char materialname[64]; /** Custom index for passes. */ int pass_index; /** Flags. */ @@ -522,6 +555,7 @@ typedef enum eSimplifyGpencil_Flag { GP_SIMPLIFY_INVERT_LAYER = (1 << 0), GP_SIMPLIFY_INVERT_PASS = (1 << 1), GP_SIMPLIFY_INVERT_LAYERPASS = (1 << 2), + GP_SIMPLIFY_INVERT_MATERIAL = (1 << 3), } eSimplifyGpencil_Flag; typedef enum eSimplifyGpencil_Mode { @@ -539,6 +573,8 @@ typedef struct OffsetGpencilModifierData { GpencilModifierData modifier; /** Layer name. */ char layername[64]; + /** Material name. */ + char materialname[64]; /** Optional vertexgroup name, MAX_VGROUP_NAME. */ char vgname[64]; /** Custom index for passes. */ @@ -557,12 +593,15 @@ typedef enum eOffsetGpencil_Flag { GP_OFFSET_INVERT_PASS = (1 << 1), GP_OFFSET_INVERT_VGROUP = (1 << 2), GP_OFFSET_INVERT_LAYERPASS = (1 << 3), + GP_OFFSET_INVERT_MATERIAL = (1 << 4), } eOffsetGpencil_Flag; typedef struct SmoothGpencilModifierData { GpencilModifierData modifier; /** Layer name. */ char layername[64]; + /** Material name. */ + char materialname[64]; /** Optional vertexgroup name, MAX_VGROUP_NAME. */ char vgname[64]; /** Custom index for passes. */ @@ -587,6 +626,7 @@ typedef enum eSmoothGpencil_Flag { GP_SMOOTH_INVERT_VGROUP = (1 << 5), GP_SMOOTH_MOD_UV = (1 << 6), GP_SMOOTH_INVERT_LAYERPASS = (1 << 7), + GP_SMOOTH_INVERT_MATERIAL = (1 << 4), } eSmoothGpencil_Flag; typedef struct ArmatureGpencilModifierData { diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h index 0de7d8bdd16..58962dd9469 100644 --- a/source/blender/makesdna/DNA_gpencil_types.h +++ b/source/blender/makesdna/DNA_gpencil_types.h @@ -30,8 +30,6 @@ struct ARegion; struct AnimData; -struct CurveMapping; -struct GHash; struct MDeformVert; #define GP_DEFAULT_PIX_FACTOR 1.0f diff --git a/source/blender/makesdna/DNA_light_types.h b/source/blender/makesdna/DNA_light_types.h index 5e881053910..82cab5d1594 100644 --- a/source/blender/makesdna/DNA_light_types.h +++ b/source/blender/makesdna/DNA_light_types.h @@ -34,7 +34,6 @@ struct AnimData; struct CurveMapping; struct Ipo; -struct MTex; struct bNodeTree; typedef struct Light { diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index caa7c98335a..cb6991ce67a 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -40,7 +40,6 @@ struct MLoopCol; struct MLoopTri; struct MLoopUV; struct MPoly; -struct MTexPoly; struct MVert; struct Material; struct Mesh; @@ -270,10 +269,4 @@ enum { #define MESH_MAX_VERTS 2000000000L -/* this is so we can save bmesh files that load in trunk, ignoring NGons - * will eventually be removed */ - -/* enable this so meshes get tessfaces calculated by default */ -/* #define USE_TESSFACE_DEFAULT */ - #endif diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h index f924368de1d..50402bbdc87 100644 --- a/source/blender/makesdna/DNA_meshdata_types.h +++ b/source/blender/makesdna/DNA_meshdata_types.h @@ -27,8 +27,6 @@ #include "DNA_customdata_types.h" #include "DNA_listBase.h" -struct Image; - /*tessellation face, see MLoop/MPoly for the real face data*/ typedef struct MFace { unsigned int v1, v2, v3, v4; @@ -188,10 +186,6 @@ typedef struct MVertTri { unsigned int tri[3]; } MVertTri; -// typedef struct MTexPoly { -// void *_pad; -//} MTexPoly; - typedef struct MLoopUV { float uv[2]; int flag; diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 37c0065b166..5d71d33733d 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -29,8 +29,6 @@ */ struct Mesh; -struct Scene; -struct Subdiv; typedef enum ModifierType { eModifierType_None = 0, diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 3ad857ac7b7..af66add01f3 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -113,7 +113,7 @@ typedef struct bNodeSocket { short stack_index; /* XXX deprecated, kept for forward compatibility */ short stack_type DNA_DEPRECATED; - char draw_shape; + char display_shape; char _pad[3]; /** Cached data from execution. */ @@ -153,11 +153,14 @@ typedef enum eNodeSocketDatatype { } eNodeSocketDatatype; /* socket shape */ -typedef enum eNodeSocketDrawShape { - SOCK_DRAW_SHAPE_CIRCLE = 0, - SOCK_DRAW_SHAPE_SQUARE = 1, - SOCK_DRAW_SHAPE_DIAMOND = 2, -} eNodeSocketDrawShape; +typedef enum eNodeSocketDisplayShape { + SOCK_DISPLAY_SHAPE_CIRCLE = 0, + SOCK_DISPLAY_SHAPE_SQUARE = 1, + SOCK_DISPLAY_SHAPE_DIAMOND = 2, + SOCK_DISPLAY_SHAPE_CIRCLE_DOT = 3, + SOCK_DISPLAY_SHAPE_SQUARE_DOT = 4, + SOCK_DISPLAY_SHAPE_DIAMOND_DOT = 5, +} eNodeSocketDisplayShape; /* socket side (input/output) */ typedef enum eNodeSocketInOut { @@ -1167,34 +1170,61 @@ typedef struct NodeDenoise { /* math node clamp */ #define SHD_MATH_CLAMP 1 -/* Math node operation/ */ +/* Math node operations. */ enum { NODE_MATH_ADD = 0, - NODE_MATH_SUB = 1, - NODE_MATH_MUL = 2, + NODE_MATH_SUBTRACT = 1, + NODE_MATH_MULTIPLY = 2, NODE_MATH_DIVIDE = 3, - NODE_MATH_SIN = 4, - NODE_MATH_COS = 5, - NODE_MATH_TAN = 6, - NODE_MATH_ASIN = 7, - NODE_MATH_ACOS = 8, - NODE_MATH_ATAN = 9, - NODE_MATH_POW = 10, - NODE_MATH_LOG = 11, - NODE_MATH_MIN = 12, - NODE_MATH_MAX = 13, + NODE_MATH_SINE = 4, + NODE_MATH_COSINE = 5, + NODE_MATH_TANGENT = 6, + NODE_MATH_ARCSINE = 7, + NODE_MATH_ARCCOSINE = 8, + NODE_MATH_ARCTANGENT = 9, + NODE_MATH_POWER = 10, + NODE_MATH_LOGARITHM = 11, + NODE_MATH_MINIMUM = 12, + NODE_MATH_MAXIMUM = 13, NODE_MATH_ROUND = 14, - NODE_MATH_LESS = 15, - NODE_MATH_GREATER = 16, - NODE_MATH_MOD = 17, - NODE_MATH_ABS = 18, - NODE_MATH_ATAN2 = 19, + NODE_MATH_LESS_THAN = 15, + NODE_MATH_GREATER_THAN = 16, + NODE_MATH_MODULO = 17, + NODE_MATH_ABSOLUTE = 18, + NODE_MATH_ARCTAN2 = 19, NODE_MATH_FLOOR = 20, NODE_MATH_CEIL = 21, - NODE_MATH_FRACT = 22, + NODE_MATH_FRACTION = 22, NODE_MATH_SQRT = 23, }; +/* Vector Math node operations. */ +enum { + NODE_VECTOR_MATH_ADD = 0, + NODE_VECTOR_MATH_SUBTRACT = 1, + NODE_VECTOR_MATH_MULTIPLY = 2, + NODE_VECTOR_MATH_DIVIDE = 3, + + NODE_VECTOR_MATH_CROSS_PRODUCT = 4, + NODE_VECTOR_MATH_PROJECT = 5, + NODE_VECTOR_MATH_REFLECT = 6, + NODE_VECTOR_MATH_DOT_PRODUCT = 7, + + NODE_VECTOR_MATH_DISTANCE = 8, + NODE_VECTOR_MATH_LENGTH = 9, + NODE_VECTOR_MATH_SCALE = 10, + NODE_VECTOR_MATH_NORMALIZE = 11, + + NODE_VECTOR_MATH_SNAP = 12, + NODE_VECTOR_MATH_FLOOR = 13, + NODE_VECTOR_MATH_CEIL = 14, + NODE_VECTOR_MATH_MODULO = 15, + NODE_VECTOR_MATH_FRACTION = 16, + NODE_VECTOR_MATH_ABSOLUTE = 17, + NODE_VECTOR_MATH_MINIMUM = 18, + NODE_VECTOR_MATH_MAXIMUM = 19, +}; + /* mix rgb node flags */ #define SHD_MIXRGB_USE_ALPHA 1 #define SHD_MIXRGB_CLAMP 2 diff --git a/source/blender/makesdna/DNA_object_fluidsim_types.h b/source/blender/makesdna/DNA_object_fluidsim_types.h index 40502fc27c9..4e821ad5f07 100644 --- a/source/blender/makesdna/DNA_object_fluidsim_types.h +++ b/source/blender/makesdna/DNA_object_fluidsim_types.h @@ -32,7 +32,6 @@ extern "C" { #endif struct Ipo; -struct Mesh; typedef struct FluidVertexVelocity { float vel[3]; diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index beff286ab40..f307fc8fc2d 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -47,7 +47,6 @@ struct Material; struct Mesh; struct Object; struct PartDeflect; -struct ParticleSystem; struct Path; struct RigidBodyOb; struct SculptSession; @@ -163,12 +162,14 @@ typedef struct Object_Runtime { struct Mesh *mesh_eval; /** * Mesh structure created during object evaluation. - * It has deforemation only modifiers applied on it. + * It has deformation only modifiers applied on it. */ struct Mesh *mesh_deform_eval; - /* This is a mesh representation of corresponding object. - * It created when Python calls `object.to_mesh()`. */ + /** + * This is a mesh representation of corresponding object. + * It created when Python calls `object.to_mesh()`. + */ struct Mesh *object_as_temp_mesh; /** Runtime evaluated curve-specific data, not stored in the file. */ @@ -176,11 +177,11 @@ typedef struct Object_Runtime { /** Runtime grease pencil drawing data */ struct GpencilBatchCache *gpencil_cache; - /** Runtime grease pencil total layers used for derived data created by modifiers */ - int tot_layers; + /** Runtime grease pencil total layers used for evaluated data created by modifiers */ + int gpencil_tot_layers; char _pad4[4]; - /** Runtime grease pencil derived data created by modifiers */ - struct bGPDframe *derived_frames; + /** Runtime grease pencil evaluated data created by modifiers */ + struct bGPDframe *gpencil_evaluated_frames; void *_pad2; /* Padding is here for win32s unconventional struct alignment rules. */ } Object_Runtime; @@ -515,7 +516,7 @@ enum { OB_DUPLIROT = 1 << 5, OB_TRANSFLAG_UNUSED_6 = 1 << 6, /* cleared */ /* runtime, calculate derivedmesh for dupli before it's used */ - OB_DUPLICALCDERIVED = 1 << 7, + OB_TRANSFLAG_UNUSED_7 = 1 << 7, /* dirty */ OB_DUPLICOLLECTION = 1 << 8, OB_DUPLIFACES = 1 << 9, OB_DUPLIFACES_SCALE = 1 << 10, @@ -619,7 +620,11 @@ enum { /* NOTE: this was used as a proper setting in past, so nullify before using */ #define BA_TEMP_TAG (1 << 5) -/* #define BA_FROMSET (1 << 7) */ /*UNUSED*/ +/** + * Even if this is is tagged for transform, this flag means it's being locked in place. + * Use for #SCE_XFORM_SKIP_CHILDREN. + */ +#define BA_TRANSFORM_LOCKED_IN_PLACE (1 << 7) #define BA_TRANSFORM_CHILD (1 << 8) /* child of a transformed object */ #define BA_TRANSFORM_PARENT (1 << 13) /* parent of a transformed object */ @@ -698,6 +703,7 @@ enum { OB_EMPTY_IMAGE_HIDE_ORTHOGRAPHIC = 1 << 1, OB_EMPTY_IMAGE_HIDE_BACK = 1 << 2, OB_EMPTY_IMAGE_HIDE_FRONT = 1 << 3, + OB_EMPTY_IMAGE_HIDE_NON_AXIS_ALIGNED = 1 << 4, }; /** #Object.empty_image_flag */ diff --git a/source/blender/makesdna/DNA_outliner_types.h b/source/blender/makesdna/DNA_outliner_types.h index 1462d955f81..9776063f220 100644 --- a/source/blender/makesdna/DNA_outliner_types.h +++ b/source/blender/makesdna/DNA_outliner_types.h @@ -60,6 +60,10 @@ enum { TSE_DRAG_INTO = (1 << 6), TSE_DRAG_BEFORE = (1 << 7), TSE_DRAG_AFTER = (1 << 8), + /* Needed because outliner-only elements can be active */ + TSE_ACTIVE = (1 << 9), + /* Needed because walk selection should not activate */ + TSE_ACTIVE_WALK = (1 << 10), TSE_DRAG_ANY = (TSE_DRAG_INTO | TSE_DRAG_BEFORE | TSE_DRAG_AFTER), }; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index a6544a7f950..45d80029eac 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -58,8 +58,6 @@ struct MovieClip; struct Object; struct Scene; struct SceneCollection; -struct SceneStats; -struct Text; struct World; struct bGPdata; struct bNodeTree; @@ -1125,7 +1123,7 @@ typedef struct GP_Sculpt_Settings { /* GP_Sculpt_Settings.flag */ typedef enum eGP_Sculpt_SettingsFlag { /* only affect selected points */ - GP_SCULPT_SETT_FLAG_SELECT_MASK = (1 << 0), + GP_SCULPT_SETT_FLAG_DEPRECATED = (1 << 0), /* apply brush to position */ GP_SCULPT_SETT_FLAG_APPLY_POSITION = (1 << 1), /* apply brush to strength */ @@ -1142,6 +1140,16 @@ typedef enum eGP_Sculpt_SettingsFlag { GP_SCULPT_SETT_FLAG_PRIMITIVE_CURVE = (1 << 7), } eGP_Sculpt_SettingsFlag; +/* GP_Sculpt_Settings.gpencil_selectmode_sculpt */ +typedef enum eGP_Sculpt_SelectMaskFlag { + /* only affect selected points */ + GP_SCULPT_MASK_SELECTMODE_POINT = (1 << 0), + /* only affect selected strokes */ + GP_SCULPT_MASK_SELECTMODE_STROKE = (1 << 1), + /* only affect selected segmenst */ + GP_SCULPT_MASK_SELECTMODE_SEGMENT = (1 << 2), +} eGP_Sculpt_SelectMaskFlag; + /* Settings for GP Interpolation Operators */ typedef struct GP_Interpolate_Settings { /** #eGP_Interpolate_SettingsFlag. */ @@ -1358,6 +1366,12 @@ typedef struct MeshStatVis { /* *************************************************************** */ /* Tool Settings */ +/* CurvePaintSettings.surface_plane */ +enum { + AUTO_MERGE = 1 << 0, + AUTO_MERGE_AND_SPLIT = 1 << 1, +}; + typedef struct ToolSettings { /** Vertex paint. */ VPaint *vpaint; @@ -1412,8 +1426,10 @@ typedef struct ToolSettings { /** Default stroke thickness for annotation strokes. */ short annotate_thickness; - /** Stroke selection mode. */ - short gpencil_selectmode; + /** Stroke selection mode for Edit. */ + char gpencil_selectmode_edit; + /** Stroke selection mode for Sculpt. */ + char gpencil_selectmode_sculpt; /* Grease Pencil Sculpt */ struct GP_Sculpt_Settings gp_sculpt; @@ -2072,6 +2088,8 @@ extern const char *RE_engine_id_CYCLES; (((workspace)->object_mode & OD_MODE_EDIT) ? OBACT(_view_layer) : NULL) #define OBEDIT_FROM_OBACT(ob) ((ob) ? (((ob)->mode & OB_MODE_EDIT) ? ob : NULL) : NULL) #define OBPOSE_FROM_OBACT(ob) ((ob) ? (((ob)->mode & OB_MODE_POSE) ? ob : NULL) : NULL) +#define OBWEIGHTPAINT_FROM_OBACT(ob) \ + ((ob) ? (((ob)->mode & OB_MODE_WEIGHT_PAINT) ? ob : NULL) : NULL) #define OBEDIT_FROM_VIEW_LAYER(view_layer) OBEDIT_FROM_OBACT(OBACT(view_layer)) #define V3D_CAMERA_LOCAL(v3d) ((!(v3d)->scenelock && (v3d)->camera) ? (v3d)->camera : NULL) @@ -2094,6 +2112,8 @@ extern const char *RE_engine_id_CYCLES; /* ToolSettings.transform_flag */ enum { SCE_XFORM_AXIS_ALIGN = (1 << 0), + SCE_XFORM_DATA_ORIGIN = (1 << 1), + SCE_XFORM_SKIP_CHILDREN = (1 << 2), }; /* ToolSettings.object_flag */ @@ -2121,11 +2141,15 @@ enum { #define SCE_SNAP_MODE_FACE (1 << 2) #define SCE_SNAP_MODE_VOLUME (1 << 3) #define SCE_SNAP_MODE_INCREMENT (1 << 4) +#define SCE_SNAP_MODE_EDGE_MIDPOINT (1 << 5) +#define SCE_SNAP_MODE_EDGE_PERPENDICULAR (1 << 6) /* ToolSettings.snap_node_mode */ -#define SCE_SNAP_MODE_GRID (1 << 5) -#define SCE_SNAP_MODE_NODE_X (1 << 6) -#define SCE_SNAP_MODE_NODE_Y (1 << 7) +#define SCE_SNAP_MODE_NODE_X (1 << 5) +#define SCE_SNAP_MODE_NODE_Y (1 << 6) + +/* ToolSettings.snap_mode and ToolSettings.snap_node_mode */ +#define SCE_SNAP_MODE_GRID (1 << 7) /** #ToolSettings.snap_transform_mode_flag */ enum { diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index 5240de4aff9..087d30ce312 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -584,7 +584,7 @@ enum { SEQ_TYPE_LIGHTEN = 44, SEQ_TYPE_DODGE = 45, SEQ_TYPE_DARKEN = 46, - SEQ_TYPE_BURN = 47, + SEQ_TYPE_COLOR_BURN = 47, SEQ_TYPE_LINEAR_BURN = 48, SEQ_TYPE_OVERLAY = 49, SEQ_TYPE_HARD_LIGHT = 50, diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 2a6a771bbeb..498ab290f31 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -246,7 +246,12 @@ typedef struct SpaceOutliner { char search_string[64]; struct TreeStoreElem search_tse; - short flag, outlinevis, storeflag, search_flags; + short flag, outlinevis, storeflag; + char search_flags; + + /** Selection syncing flag (#WM_OUTLINER_SYNC_SELECT_FROM_OBJECT and similar flags). */ + char sync_select_dirty; + int filter; char filter_state; char show_restrict_flags; @@ -265,6 +270,7 @@ typedef enum eSpaceOutliner_Flag { SO_FLAG_UNUSED_1 = (1 << 2), /* cleared */ SO_HIDE_KEYINGSETINFO = (1 << 3), SO_SKIP_SORT_ALPHA = (1 << 4), + SO_SYNC_SELECT = (1 << 5), } eSpaceOutliner_Flag; /* SpaceOutliner.filter */ @@ -285,11 +291,12 @@ typedef enum eSpaceOutliner_Filter { SO_FILTER_UNUSED_12 = (1 << 12), /* cleared */ SO_FILTER_OB_STATE_VISIBLE = (1 << 13), /* Not set via DNA. */ - SO_FILTER_OB_STATE_SELECTED = (1 << 14), /* Not set via DNA. */ - SO_FILTER_OB_STATE_ACTIVE = (1 << 15), /* Not set via DNA. */ - SO_FILTER_NO_COLLECTION = (1 << 16), + SO_FILTER_OB_STATE_HIDDEN = (1 << 14), /* Not set via DNA. */ + SO_FILTER_OB_STATE_SELECTED = (1 << 15), /* Not set via DNA. */ + SO_FILTER_OB_STATE_ACTIVE = (1 << 16), /* Not set via DNA. */ + SO_FILTER_NO_COLLECTION = (1 << 17), - SO_FILTER_ID_TYPE = (1 << 17), + SO_FILTER_ID_TYPE = (1 << 18), } eSpaceOutliner_Filter; #define SO_FILTER_OB_TYPE \ @@ -297,7 +304,8 @@ typedef enum eSpaceOutliner_Filter { SO_FILTER_NO_OB_LAMP | SO_FILTER_NO_OB_CAMERA | SO_FILTER_NO_OB_OTHERS) #define SO_FILTER_OB_STATE \ - (SO_FILTER_OB_STATE_VISIBLE | SO_FILTER_OB_STATE_SELECTED | SO_FILTER_OB_STATE_ACTIVE) + (SO_FILTER_OB_STATE_VISIBLE | SO_FILTER_OB_STATE_HIDDEN | SO_FILTER_OB_STATE_SELECTED | \ + SO_FILTER_OB_STATE_ACTIVE) #define SO_FILTER_ANY \ (SO_FILTER_NO_OB_CONTENT | SO_FILTER_NO_CHILDREN | SO_FILTER_OB_TYPE | SO_FILTER_OB_STATE | \ @@ -307,8 +315,9 @@ typedef enum eSpaceOutliner_Filter { typedef enum eSpaceOutliner_StateFilter { SO_FILTER_OB_ALL = 0, SO_FILTER_OB_VISIBLE = 1, - SO_FILTER_OB_SELECTED = 2, - SO_FILTER_OB_ACTIVE = 3, + SO_FILTER_OB_HIDDEN = 2, + SO_FILTER_OB_SELECTED = 3, + SO_FILTER_OB_ACTIVE = 4, } eSpaceOutliner_StateFilter; /* SpaceOutliner.show_restrict_flags */ @@ -420,8 +429,7 @@ typedef enum eGraphEdit_Flag { SIPO_NOTRANSKEYCULL = (1 << 1), /* don't show any keyframe handles at all */ SIPO_NOHANDLES = (1 << 2), - /* don't show current frame number beside indicator line */ - SIPO_NODRAWCFRANUM = (1 << 3), + /* SIPO_NODRAWCFRANUM = (1 << 3), DEPRECATED */ /* show timing in seconds instead of frames */ SIPO_DRAWTIME = (1 << 4), /* only show keyframes for selected F-Curves */ @@ -496,8 +504,7 @@ typedef enum eSpaceNla_Flag { /* draw timing in seconds instead of frames */ SNLA_DRAWTIME = (1 << 2), SNLA_FLAG_UNUSED_3 = (1 << 3), - /* don't draw frame number beside frame indicator */ - SNLA_NODRAWCFRANUM = (1 << 4), + /* SNLA_NODRAWCFRANUM = (1 << 4), DEPRECATED */ /* don't draw influence curves on strips */ SNLA_NOSTRIPCURVES = (1 << 5), /* don't perform realtime updates */ @@ -581,7 +588,7 @@ typedef enum eSpaceSeq_Flag { SEQ_DRAW_COLOR_SEPARATED = (1 << 2), SEQ_SHOW_SAFE_MARGINS = (1 << 3), SEQ_SHOW_GPENCIL = (1 << 4), - SEQ_NO_DRAW_CFRANUM = (1 << 5), + /* SEQ_NO_DRAW_CFRANUM = (1 << 5), DEPRECATED */ SEQ_USE_ALPHA = (1 << 6), /* use RGBA display mode for preview */ SEQ_ALL_WAVEFORMS = (1 << 7), /* draw all waveforms */ SEQ_NO_WAVEFORMS = (1 << 8), /* draw no waveforms */ @@ -672,8 +679,11 @@ typedef struct FileSelectParams { /** Display mode flag. */ short display; short display_previous; + /** Details toggles (file size, creation date, etc.) */ + char details_flags; + /* The type of file action (opening or saving) */ + char action_type; /* eFileSel_Action */ /** Filter when (flags & FILE_FILTER) is true. */ - char _pad2[2]; int filter; /** Max number of levels in dirtree to show at once, 0 to disable recursion. */ @@ -731,8 +741,8 @@ typedef struct SpaceFile { /* FileSelectParams.display */ enum eFileDisplayType { FILE_DEFAULTDISPLAY = 0, - FILE_SHORTDISPLAY = 1, - FILE_LONGDISPLAY = 2, + FILE_VERTICALDISPLAY = 1, + FILE_HORIZONTALDISPLAY = 2, FILE_IMGDISPLAY = 3, }; @@ -745,6 +755,12 @@ enum eFileSortType { FILE_SORT_SIZE = 4, }; +/* FileSelectParams.details_flags */ +enum eFileDetails { + FILE_DETAILS_SIZE = (1 << 0), + FILE_DETAILS_DATETIME = (1 << 1), +}; + /* these values need to be hardcoded in structs, dna does not recognize defines */ /* also defined in BKE */ #define FILE_MAXDIR 768 @@ -782,6 +798,8 @@ typedef enum eFileSel_Params_Flag { FILE_FILTER = (1 << 8), FILE_PARAMS_FLAG_UNUSED_9 = (1 << 9), /* cleared */ FILE_GROUP_INSTANCE = (1 << 10), + FILE_SORT_INVERT = (1 << 11), + FILE_HIDE_TOOL_PROPS = (1 << 12) } eFileSel_Params_Flag; /* sfile->params->rename_flag */ @@ -819,6 +837,8 @@ typedef enum eFileSel_File_Types { FILE_TYPE_OPERATOR = (1 << 14), FILE_TYPE_APPLICATIONBUNDLE = (1 << 15), FILE_TYPE_ALEMBIC = (1 << 16), + /** For all kinds of recognized import/export formats. No need for specialized types. */ + FILE_TYPE_OBJECT_IO = (1 << 17), /** An FS directory (i.e. S_ISDIR on its path is true). */ FILE_TYPE_DIR = (1 << 30), @@ -877,8 +897,7 @@ typedef struct FileDirEntryRevision { int64_t time; /* Temp caching of UI-generated strings... */ char size_str[16]; - char time_str[8]; - char date_str[16]; + char datetime_str[16 + 8]; } FileDirEntryRevision; /* Container for a variant, only relevant in asset context. @@ -1113,8 +1132,6 @@ typedef enum eSpaceImage_Flag { SI_SHOW_R = (1 << 27), SI_SHOW_G = (1 << 28), SI_SHOW_B = (1 << 29), - - SI_NO_DRAWEDGES = (1 << 30), } eSpaceImage_Flag; /* SpaceImage.other_uv_filter */ diff --git a/source/blender/makesdna/DNA_texture_types.h b/source/blender/makesdna/DNA_texture_types.h index 3fad1c57427..ead1bcc943d 100644 --- a/source/blender/makesdna/DNA_texture_types.h +++ b/source/blender/makesdna/DNA_texture_types.h @@ -35,7 +35,6 @@ extern "C" { struct AnimData; struct ColorBand; struct CurveMapping; -struct ImBuf; struct Image; struct Ipo; struct Object; diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index b8914c7a74f..8eabbc0df0d 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -717,7 +717,7 @@ typedef struct UserDef { /** Overall sensitivity of 3D mouse. */ float ndof_sensitivity; float ndof_orbit_sensitivity; - /** Deadzone of 3D mouse. */ + /** Dead-zone of 3D mouse. */ float ndof_deadzone; /** #eNdof_Flag, flags for 3D mouse. */ int ndof_flag; @@ -868,6 +868,7 @@ typedef enum eUserPref_Flag { USER_NONEGFRAMES = (1 << 24), USER_TXT_TABSTOSPACES_DISABLE = (1 << 25), USER_TOOLTIPS_PYTHON = (1 << 26), + USER_ADDONS_ENABLED_ONLY = (1 << 27), } eUserPref_Flag; typedef enum eUserPref_PrefFlag { diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 3ba33cfe3d4..51655790fbd 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -25,11 +25,6 @@ #define __DNA_VIEW3D_TYPES_H__ struct BoundBox; -struct GPUViewport; -struct Image; -struct Material; -struct MovieClip; -struct MovieClipUser; struct Object; struct RenderEngine; struct SmoothView3DStore; diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index 8dcae41aaa2..57c0a29382d 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -48,7 +48,6 @@ struct PointerRNA; struct Report; struct ReportList; struct Stereo3dFormat; -struct UndoStep; struct bContext; struct bScreen; struct uiLayout; @@ -131,12 +130,15 @@ typedef struct wmWindowManager { ListBase windows; /** Set on file read. */ - int initialized; + short initialized; /** Indicator whether data was saved. */ short file_saved; /** Operator stack depth to avoid nested undo pushes. */ short op_undo_depth; + /** Set after selection to notify outliner to sync. Stores type of selection */ + short outliner_sync_select_dirty; + /** Operator registry. */ ListBase operators; @@ -186,6 +188,18 @@ enum { WM_KEYCONFIG_IS_INITIALIZED = (1 << 1), }; +/* wmWindowManager.outliner_sync_select_dirty */ +enum { + WM_OUTLINER_SYNC_SELECT_FROM_OBJECT = (1 << 0), + WM_OUTLINER_SYNC_SELECT_FROM_EDIT_BONE = (1 << 1), + WM_OUTLINER_SYNC_SELECT_FROM_POSE_BONE = (1 << 2), + WM_OUTLINER_SYNC_SELECT_FROM_SEQUENCE = (1 << 3), +}; + +#define WM_OUTLINER_SYNC_SELECT_FROM_ALL \ + (WM_OUTLINER_SYNC_SELECT_FROM_OBJECT | WM_OUTLINER_SYNC_SELECT_FROM_EDIT_BONE | \ + WM_OUTLINER_SYNC_SELECT_FROM_POSE_BONE | WM_OUTLINER_SYNC_SELECT_FROM_SEQUENCE) + #define WM_KEYCONFIG_STR_DEFAULT "blender" /* IME is win32 only! */ diff --git a/source/blender/makesdna/DNA_world_types.h b/source/blender/makesdna/DNA_world_types.h index 5143f667083..af1e5123dc8 100644 --- a/source/blender/makesdna/DNA_world_types.h +++ b/source/blender/makesdna/DNA_world_types.h @@ -29,7 +29,6 @@ struct AnimData; struct Ipo; -struct MTex; struct bNodeTree; #ifndef MAX_MTEX diff --git a/source/blender/makesdna/intern/dna_genfile.c b/source/blender/makesdna/intern/dna_genfile.c index 5252c8f3350..09a7a157996 100644 --- a/source/blender/makesdna/intern/dna_genfile.c +++ b/source/blender/makesdna/intern/dna_genfile.c @@ -339,7 +339,7 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error data = (int *)sdna->data; - /* clear pointers incase of error */ + /* Clear pointers in case of error. */ sdna->names = NULL; sdna->types = NULL; sdna->structs = NULL; @@ -1102,7 +1102,7 @@ static void reconstruct_elem(const SDNA *newsdna, * - cast type * - name partially equal (array differs) * - type equal: memcpy - * - types casten + * - type cast (per element). * (nzc 2-4-2001 I want the 'unsigned' bit to be parsed as well. Where * can I force this?) */ diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 613df728dc9..0b60d1fa344 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -1158,24 +1158,37 @@ struct PropertyElemRNA { }; bool RNA_path_resolve_elements(PointerRNA *ptr, const char *path, struct ListBase *r_elements); +struct ID *RNA_find_real_ID_and_path(struct Main *bmain, struct ID *id, const char **r_path); + char *RNA_path_from_ID_to_struct(PointerRNA *ptr); + +char *RNA_path_from_real_ID_to_struct(struct Main *bmain, PointerRNA *ptr, struct ID **r_real); + char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop); char *RNA_path_from_ID_to_property_index(PointerRNA *ptr, PropertyRNA *prop, int array_dim, int index); +char *RNA_path_from_real_ID_to_property_index(struct Main *bmain, + PointerRNA *ptr, + PropertyRNA *prop, + int array_dim, + int index, + struct ID **r_real_id); + char *RNA_path_resolve_from_type_to_property(struct PointerRNA *ptr, struct PropertyRNA *prop, const struct StructRNA *type); -char *RNA_path_full_ID_py(struct ID *id); -char *RNA_path_full_struct_py(struct PointerRNA *ptr); -char *RNA_path_full_property_py_ex(PointerRNA *ptr, - PropertyRNA *prop, - int index, - bool use_fallback); -char *RNA_path_full_property_py(struct PointerRNA *ptr, struct PropertyRNA *prop, int index); +char *RNA_path_full_ID_py(struct Main *bmain, struct ID *id); +char *RNA_path_full_struct_py(struct Main *bmain, struct PointerRNA *ptr); +char *RNA_path_full_property_py_ex( + struct Main *bmain, PointerRNA *ptr, PropertyRNA *prop, int index, bool use_fallback); +char *RNA_path_full_property_py(struct Main *bmain, + struct PointerRNA *ptr, + struct PropertyRNA *prop, + int index); char *RNA_path_struct_property_py(struct PointerRNA *ptr, struct PropertyRNA *prop, int index); char *RNA_path_property_py(struct PointerRNA *ptr, struct PropertyRNA *prop, int index); @@ -1418,8 +1431,8 @@ StructRNA *ID_code_to_RNA_type(short idcode); #define RNA_POINTER_INVALIDATE(ptr) \ { \ /* this is checked for validity */ \ - (ptr)->type = /* should not be needed but prevent bad pointer access, just in case */ \ - (ptr)->id.data = NULL; \ + (ptr)->type = NULL; /* should not be needed but prevent bad pointer access, just in case */ \ + (ptr)->owner_id = NULL; \ } \ (void)0 @@ -1511,8 +1524,8 @@ bool RNA_struct_override_store(struct Main *bmain, struct IDOverrideLibrary *override); void RNA_struct_override_apply(struct Main *bmain, - struct PointerRNA *ptr_local, - struct PointerRNA *ptr_override, + struct PointerRNA *ptr_dst, + struct PointerRNA *ptr_src, struct PointerRNA *ptr_storage, struct IDOverrideLibrary *override); diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h index 02aaef44a1f..b3e1f22f413 100644 --- a/source/blender/makesrna/RNA_enum_types.h +++ b/source/blender/makesrna/RNA_enum_types.h @@ -91,6 +91,7 @@ extern const EnumPropertyItem rna_enum_beztriple_keyframe_type_items[]; extern const EnumPropertyItem rna_enum_beztriple_interpolation_mode_items[]; extern const EnumPropertyItem rna_enum_beztriple_interpolation_easing_items[]; extern const EnumPropertyItem rna_enum_keyframe_handle_type_items[]; +extern const EnumPropertyItem rna_enum_driver_target_rotation_mode_items[]; extern const EnumPropertyItem rna_enum_keyblock_type_items[]; diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h index 38631d1acf2..2a341249247 100644 --- a/source/blender/makesrna/RNA_types.h +++ b/source/blender/makesrna/RNA_types.h @@ -29,6 +29,7 @@ extern "C" { struct BlenderRNA; struct FunctionRNA; +struct ID; struct Main; struct ParameterList; struct PropertyRNA; @@ -44,10 +45,7 @@ struct bContext; * the properties and validate them. */ typedef struct PointerRNA { - struct { - void *data; - } id; - + struct ID *owner_id; struct StructRNA *type; void *data; } PointerRNA; @@ -534,7 +532,7 @@ typedef struct ParameterDynAlloc { typedef enum FunctionFlag { /** * Pass ID owning 'self' data - * (i.e. ptr->id.data, might be same as self in case data is an ID...). + * (i.e. ptr->owner_id, might be same as self in case data is an ID...). */ FUNC_USE_SELF_ID = (1 << 11), diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index ab13c6c9ed4..05408f1a41a 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -365,9 +365,11 @@ add_custom_command( # Build bf_rna set(SRC rna_access.c + rna_access_compare_override.c ${GENSRC} ${SRC_RNA_INC} + rna_access_internal.h rna_internal.h rna_internal_types.h rna_mesh_utils.h diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index f6c248acdb5..1617d85b6c2 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -389,7 +389,7 @@ static void rna_print_data_get(FILE *f, PropertyDefRNA *dp) static void rna_print_id_get(FILE *f, PropertyDefRNA *UNUSED(dp)) { - fprintf(f, " ID *id = ptr->id.data;\n"); + fprintf(f, " ID *id = ptr->owner_id;\n"); } static void rna_construct_function_name( @@ -2470,7 +2470,7 @@ static void rna_def_struct_function_call_impl_cpp(FILE *f, StructRNA *srna, Func dsrna = rna_find_struct_def(srna); if (func->flag & FUNC_USE_SELF_ID) { - WRITE_PARAM("(::ID *) ptr.id.data"); + WRITE_PARAM("(::ID *) ptr.owner_id"); } if ((func->flag & FUNC_NO_SELF) == 0) { @@ -2579,7 +2579,7 @@ static void rna_def_struct_function_impl_cpp(FILE *f, StructRNA *srna, FunctionD } else { fprintf(f, - "\t\tRNA_pointer_create((::ID *) ptr.id.data, &RNA_%s, retdata, &result);\n", + "\t\tRNA_pointer_create((::ID *) ptr.owner_id, &RNA_%s, retdata, &result);\n", (const char *)pprop->type); } } @@ -2792,7 +2792,7 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA /* assign self */ if (func->flag & FUNC_USE_SELF_ID) { - fprintf(f, "\t_selfid = (struct ID *)_ptr->id.data;\n"); + fprintf(f, "\t_selfid = (struct ID *)_ptr->owner_id;\n"); } if ((func->flag & FUNC_NO_SELF) == 0) { diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 57cdbbadeb8..5a4b4a3fa3d 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -620,9 +620,9 @@ static int rna_IDPArray_length(PointerRNA *ptr) int rna_IDMaterials_assign_int(PointerRNA *ptr, int key, const PointerRNA *assign_ptr) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; short *totcol = give_totcolp_id(id); - Material *mat_id = assign_ptr->id.data; + Material *mat_id = (Material *)assign_ptr->owner_id; if (totcol && (key >= 0 && key < *totcol)) { BLI_assert(BKE_id_is_in_global_main(id)); BLI_assert(BKE_id_is_in_global_main(&mat_id->id)); @@ -642,8 +642,7 @@ static void rna_IDMaterials_append_id(ID *id, Main *bmain, Material *ma) WM_main_add_notifier(NC_OBJECT | ND_OB_SHADING, id); } -static Material *rna_IDMaterials_pop_id( - ID *id, Main *bmain, ReportList *reports, int index_i, bool remove_material_slot) +static Material *rna_IDMaterials_pop_id(ID *id, Main *bmain, ReportList *reports, int index_i) { Material *ma; short *totcol = give_totcolp_id(id); @@ -657,7 +656,7 @@ static Material *rna_IDMaterials_pop_id( return NULL; } - ma = BKE_material_pop_id(bmain, id, index_i, remove_material_slot); + ma = BKE_material_pop_id(bmain, id, index_i); if (*totcol == totcol_orig) { BKE_report(reports, RPT_ERROR, "No material to removed"); @@ -671,9 +670,9 @@ static Material *rna_IDMaterials_pop_id( return ma; } -static void rna_IDMaterials_clear_id(ID *id, Main *bmain, bool remove_material_slot) +static void rna_IDMaterials_clear_id(ID *id, Main *bmain) { - BKE_material_clear_id(bmain, id, remove_material_slot); + BKE_material_clear_id(bmain, id); DEG_id_tag_update(id, ID_RECALC_GEOMETRY); WM_main_add_notifier(NC_OBJECT | ND_DRAW, id); @@ -691,7 +690,7 @@ static void rna_Library_filepath_set(PointerRNA *ptr, const char *value) static void rna_ImagePreview_is_custom_set(PointerRNA *ptr, int value, enum eIconSizes size) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; PreviewImage *prv_img = (PreviewImage *)ptr->data; if (id != NULL) { @@ -717,7 +716,7 @@ static void rna_ImagePreview_is_custom_set(PointerRNA *ptr, int value, enum eIco static void rna_ImagePreview_size_get(PointerRNA *ptr, int *values, enum eIconSizes size) { - ID *id = (ID *)ptr->id.data; + ID *id = ptr->owner_id; PreviewImage *prv_img = (PreviewImage *)ptr->data; if (id != NULL) { @@ -732,7 +731,7 @@ static void rna_ImagePreview_size_get(PointerRNA *ptr, int *values, enum eIconSi static void rna_ImagePreview_size_set(PointerRNA *ptr, const int *values, enum eIconSizes size) { - ID *id = (ID *)ptr->id.data; + ID *id = ptr->owner_id; PreviewImage *prv_img = (PreviewImage *)ptr->data; if (id != NULL) { @@ -755,7 +754,7 @@ static int rna_ImagePreview_pixels_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION], enum eIconSizes size) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; PreviewImage *prv_img = (PreviewImage *)ptr->data; if (id != NULL) { @@ -771,7 +770,7 @@ static int rna_ImagePreview_pixels_get_length(PointerRNA *ptr, static void rna_ImagePreview_pixels_get(PointerRNA *ptr, int *values, enum eIconSizes size) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; PreviewImage *prv_img = (PreviewImage *)ptr->data; if (id != NULL) { @@ -785,7 +784,7 @@ static void rna_ImagePreview_pixels_get(PointerRNA *ptr, int *values, enum eIcon static void rna_ImagePreview_pixels_set(PointerRNA *ptr, const int *values, enum eIconSizes size) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; PreviewImage *prv_img = (PreviewImage *)ptr->data; if (id != NULL) { @@ -800,7 +799,7 @@ static int rna_ImagePreview_pixels_float_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION], enum eIconSizes size) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; PreviewImage *prv_img = (PreviewImage *)ptr->data; BLI_assert(sizeof(unsigned int) == 4); @@ -818,7 +817,7 @@ static int rna_ImagePreview_pixels_float_get_length(PointerRNA *ptr, static void rna_ImagePreview_pixels_float_get(PointerRNA *ptr, float *values, enum eIconSizes size) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; PreviewImage *prv_img = (PreviewImage *)ptr->data; unsigned char *data = (unsigned char *)prv_img->rect[size]; @@ -842,7 +841,7 @@ static void rna_ImagePreview_pixels_float_set(PointerRNA *ptr, const float *values, enum eIconSizes size) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; PreviewImage *prv_img = (PreviewImage *)ptr->data; unsigned char *data = (unsigned char *)prv_img->rect[size]; @@ -959,7 +958,7 @@ static int rna_ImagePreview_icon_id_get(PointerRNA *ptr) { /* Using a callback here allows us to only generate icon matching * that preview when icon_id is requested. */ - return BKE_icon_preview_ensure(ptr->id.data, (PreviewImage *)(ptr->data)); + return BKE_icon_preview_ensure(ptr->owner_id, (PreviewImage *)(ptr->data)); } static void rna_ImagePreview_icon_reload(PreviewImage *prv) { @@ -1116,16 +1115,12 @@ static void rna_def_ID_materials(BlenderRNA *brna) RNA_def_function_ui_description(func, "Remove a material from the data-block"); parm = RNA_def_int( func, "index", -1, -MAXMAT, MAXMAT, "", "Index of material to remove", 0, MAXMAT); - RNA_def_boolean( - func, "update_data", 0, "", "Update data by re-adjusting the material slots assigned"); parm = RNA_def_pointer(func, "material", "Material", "", "Material to remove"); RNA_def_function_return(func, parm); func = RNA_def_function(srna, "clear", "rna_IDMaterials_clear_id"); RNA_def_function_flag(func, FUNC_USE_MAIN); RNA_def_function_ui_description(func, "Remove all materials from the data-block"); - RNA_def_boolean( - func, "update_data", 0, "", "Update data by re-adjusting the material slots assigned"); } static void rna_def_image_preview(BlenderRNA *brna) @@ -1455,6 +1450,7 @@ static void rna_def_ID(BlenderRNA *brna) "Actual data-block from .blend file (Main database) that generated that evaluated one"); RNA_def_property_pointer_funcs(prop, "rna_ID_original_get", NULL, NULL, NULL); RNA_def_property_clear_flag(prop, PROP_EDITABLE | PROP_PTR_NO_OWNERSHIP); + RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON); prop = RNA_def_property(srna, "users", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "us"); @@ -1483,6 +1479,7 @@ static void rna_def_ID(BlenderRNA *brna) prop = RNA_def_property(srna, "library", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "lib"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON); RNA_def_property_ui_text(prop, "Library", "Library file the data-block is linked from"); prop = RNA_def_pointer( @@ -1607,6 +1604,7 @@ static void rna_def_library(BlenderRNA *brna) prop = RNA_def_property(srna, "parent", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "Library"); + RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON); RNA_def_property_ui_text(prop, "Parent", ""); prop = RNA_def_property(srna, "packed_file", PROP_POINTER, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 330d45c2fa5..61634a84d41 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -37,21 +37,18 @@ #include "BLI_ghash.h" #include "BLI_math.h" -#ifdef DEBUG_OVERRIDE_TIMEIT -# include "PIL_time_utildefines.h" -#endif - #include "BLF_api.h" #include "BLT_translation.h" #include "BKE_animsys.h" +#include "BKE_collection.h" #include "BKE_context.h" #include "BKE_idcode.h" #include "BKE_idprop.h" #include "BKE_fcurve.h" -#include "BKE_library_override.h" #include "BKE_main.h" #include "BKE_report.h" +#include "BKE_node.h" #include "DEG_depsgraph.h" @@ -67,8 +64,9 @@ #include "WM_types.h" #include "rna_internal.h" +#include "rna_access_internal.h" -const PointerRNA PointerRNA_NULL = {{NULL}}; +const PointerRNA PointerRNA_NULL = {NULL}; /* Init/Exit */ @@ -116,7 +114,7 @@ void RNA_exit(void) void RNA_main_pointer_create(struct Main *main, PointerRNA *r_ptr) { - r_ptr->id.data = NULL; + r_ptr->owner_id = NULL; r_ptr->type = &RNA_BlendData; r_ptr->data = main; } @@ -126,7 +124,7 @@ void RNA_id_pointer_create(ID *id, PointerRNA *r_ptr) StructRNA *type, *idtype = NULL; if (id) { - PointerRNA tmp = {{NULL}}; + PointerRNA tmp = {NULL}; tmp.data = id; idtype = rna_ID_refine(&tmp); @@ -142,7 +140,7 @@ void RNA_id_pointer_create(ID *id, PointerRNA *r_ptr) } } - r_ptr->id.data = id; + r_ptr->owner_id = id; r_ptr->type = idtype; r_ptr->data = id; } @@ -153,13 +151,13 @@ void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr) StructRNA *idtype = NULL; if (id) { - PointerRNA tmp = {{0}}; + PointerRNA tmp = {0}; tmp.data = id; idtype = rna_ID_refine(&tmp); } #endif - r_ptr->id.data = id; + r_ptr->owner_id = id; r_ptr->type = type; r_ptr->data = data; @@ -179,22 +177,22 @@ void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr) bool RNA_pointer_is_null(const PointerRNA *ptr) { - return !((ptr->data != NULL) && (ptr->id.data != NULL) && (ptr->type != NULL)); + return !((ptr->data != NULL) && (ptr->owner_id != NULL) && (ptr->type != NULL)); } static void rna_pointer_inherit_id(StructRNA *type, PointerRNA *parent, PointerRNA *ptr) { if (type && type->flag & STRUCT_ID) { - ptr->id.data = ptr->data; + ptr->owner_id = ptr->data; } else { - ptr->id.data = parent->id.data; + ptr->owner_id = parent->owner_id; } } void RNA_blender_rna_pointer_create(PointerRNA *r_ptr) { - r_ptr->id.data = NULL; + r_ptr->owner_id = NULL; r_ptr->type = &RNA_BlenderRNA; r_ptr->data = &BLENDER_RNA; } @@ -229,7 +227,7 @@ void RNA_pointer_recast(PointerRNA *ptr, PointerRNA *r_ptr) #if 0 /* works but this case if covered by more general code below. */ if (RNA_struct_is_ID(ptr->type)) { /* simple case */ - RNA_id_pointer_create(ptr->id.data, r_ptr); + RNA_id_pointer_create(ptr->owner_id, r_ptr); } else #endif @@ -249,7 +247,7 @@ void RNA_pointer_recast(PointerRNA *ptr, PointerRNA *r_ptr) /* ID Properties */ -static void rna_idproperty_touch(IDProperty *idprop) +void rna_idproperty_touch(IDProperty *idprop) { /* so the property is seen as 'set' by rna */ idprop->flag &= ~IDP_FLAG_GHOST; @@ -619,7 +617,7 @@ PropertyRNA *rna_ensure_property_realdata(PropertyRNA **prop, PointerRNA *ptr) return rna_idproperty_check_ex(prop, ptr, true); } -static PropertyRNA *rna_ensure_property(PropertyRNA *prop) +PropertyRNA *rna_ensure_property(PropertyRNA *prop) { /* the quick version if we don't need the idproperty */ @@ -1171,11 +1169,6 @@ int RNA_property_flag(PropertyRNA *prop) return rna_ensure_property(prop)->flag; } -int RNA_property_override_flag(PropertyRNA *prop) -{ - return rna_ensure_property(prop)->flag_override; -} - /** * Get the tags set for \a prop as int bitfield. * \note Doesn't perform any validity check on the set bits. #RNA_def_property_tags does this @@ -2067,7 +2060,7 @@ int RNA_property_ui_icon(PropertyRNA *prop) bool RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; int flag; const char *dummy_info; @@ -2085,7 +2078,7 @@ bool RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop) */ bool RNA_property_editable_info(PointerRNA *ptr, PropertyRNA *prop, const char **r_info) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; int flag; prop = rna_ensure_property(prop); @@ -2152,7 +2145,7 @@ bool RNA_property_editable_index(PointerRNA *ptr, PropertyRNA *prop, int index) flag &= prop->itemeditable(ptr, index); } - id = ptr->id.data; + id = ptr->owner_id; return (flag & PROP_EDITABLE) && (!id || !ID_IS_LINKED(id) || (prop->flag & PROP_LIB_EXCEPTION)); } @@ -2160,7 +2153,7 @@ bool RNA_property_editable_index(PointerRNA *ptr, PropertyRNA *prop, int index) bool RNA_property_animateable(PointerRNA *ptr, PropertyRNA *prop) { /* check that base ID-block can support animation data */ - if (!id_can_have_animdata(ptr->id.data)) { + if (!id_can_have_animdata(ptr->owner_id)) { return false; } @@ -2194,77 +2187,6 @@ bool RNA_property_animated(PointerRNA *ptr, PropertyRNA *prop) return false; } - -/** \note Does not take into account editable status, this has to be checked separately - * (using #RNA_property_editable_flag() usually). */ -bool RNA_property_overridable_get(PointerRNA *ptr, PropertyRNA *prop) -{ - if (prop->magic == RNA_MAGIC) { - /* Special handling for insertions of constraints or modifiers... */ - /* TODO Note We may want to add a more generic system to RNA - * (like a special property in struct of items) - * if we get more overrideable collections, - * for now we can live with those special-cases handling I think. */ - if (RNA_struct_is_a(ptr->type, &RNA_Constraint)) { - bConstraint *con = ptr->data; - if (con->flag & CONSTRAINT_OVERRIDE_LIBRARY_LOCAL) { - return true; - } - } - else if (RNA_struct_is_a(ptr->type, &RNA_Modifier)) { - ModifierData *mod = ptr->data; - if (mod->flag & eModifierFlag_OverrideLibrary_Local) { - return true; - } - } - /* If this is a RNA-defined property (real or 'virtual' IDProp), - * we want to use RNA prop flag. */ - return !(prop->flag_override & PROPOVERRIDE_NO_COMPARISON) && - (prop->flag_override & PROPOVERRIDE_OVERRIDABLE_LIBRARY); - } - else { - /* If this is a real 'pure' IDProp (aka custom property), we want to use the IDProp flag. */ - return !(prop->flag_override & PROPOVERRIDE_NO_COMPARISON) && - (((IDProperty *)prop)->flag & IDP_FLAG_OVERRIDABLE_LIBRARY); - } -} - -/* Should only be used for custom properties */ -bool RNA_property_overridable_library_set(PointerRNA *UNUSED(ptr), - PropertyRNA *prop, - const bool is_overridable) -{ - /* Only works for pure custom properties IDProps. */ - if (prop->magic != RNA_MAGIC) { - IDProperty *idprop = (IDProperty *)prop; - - idprop->flag = is_overridable ? (idprop->flag | IDP_FLAG_OVERRIDABLE_LIBRARY) : - (idprop->flag & ~IDP_FLAG_OVERRIDABLE_LIBRARY); - return true; - } - - return false; -} - -bool RNA_property_overridden(PointerRNA *ptr, PropertyRNA *prop) -{ - char *rna_path = RNA_path_from_ID_to_property(ptr, prop); - ID *id = ptr->id.data; - - if (rna_path == NULL || id == NULL || id->override_library == NULL) { - return false; - } - - return (BKE_override_library_property_find(id->override_library, rna_path) != NULL); -} - -bool RNA_property_comparable(PointerRNA *UNUSED(ptr), PropertyRNA *prop) -{ - prop = rna_ensure_property(prop); - - return !(prop->flag_override & PROPOVERRIDE_NO_COMPARISON); -} - /* this function is to check if its possible to create a valid path from the ID * its slow so don't call in a loop */ bool RNA_property_path_from_ID_check(PointerRNA *ptr, PropertyRNA *prop) @@ -2277,7 +2199,7 @@ bool RNA_property_path_from_ID_check(PointerRNA *ptr, PropertyRNA *prop) PointerRNA r_ptr; PropertyRNA *r_prop; - RNA_id_pointer_create(ptr->id.data, &id_ptr); + RNA_id_pointer_create(ptr->owner_id, &id_ptr); if (RNA_path_resolve(&id_ptr, path, &r_ptr, &r_prop) == true) { ret = (prop == r_prop); } @@ -2316,7 +2238,7 @@ static void rna_property_update( /* TODO(campbell): Should eventually be replaced entirely by message bus (below) * for now keep since COW, bugs are hard to track when we have other missing updates. */ if (prop->noteflag) { - WM_main_add_notifier(prop->noteflag, ptr->id.data); + WM_main_add_notifier(prop->noteflag, ptr->owner_id); } #endif @@ -2327,10 +2249,10 @@ static void rna_property_update( /* we could add NULL check, for now don't */ WM_msg_publish_rna(mbus, ptr, prop); } - if (ptr->id.data != NULL && ((prop->flag & PROP_NO_DEG_UPDATE) == 0)) { - const short id_type = GS(((ID *)ptr->id.data)->name); + if (ptr->owner_id != NULL && ((prop->flag & PROP_NO_DEG_UPDATE) == 0)) { + const short id_type = GS(ptr->owner_id->name); if (ID_TYPE_IS_COW(id_type)) { - DEG_id_tag_update(ptr->id.data, ID_RECALC_COPY_ON_WRITE); + DEG_id_tag_update(ptr->owner_id, ID_RECALC_COPY_ON_WRITE); } } /* End message bus. */ @@ -2339,14 +2261,14 @@ static void rna_property_update( if (!is_rna || (prop->flag & PROP_IDPROPERTY)) { /* WARNING! This is so property drivers update the display! * not especially nice */ - DEG_id_tag_update(ptr->id.data, + DEG_id_tag_update(ptr->owner_id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_PARAMETERS); WM_main_add_notifier(NC_WINDOW, NULL); /* Not nice as well, but the only way to make sure material preview * is updated with custom nodes. */ - if ((prop->flag & PROP_IDPROPERTY) != 0 && (ptr->id.data != NULL) && - (GS(((ID *)ptr->id.data)->name) == ID_NT)) { + if ((prop->flag & PROP_IDPROPERTY) != 0 && (ptr->owner_id != NULL) && + (GS(ptr->owner_id->name) == ID_NT)) { WM_main_add_notifier(NC_MATERIAL | ND_SHADING, NULL); } } @@ -2379,7 +2301,7 @@ void RNA_property_update_main(Main *bmain, Scene *scene, PointerRNA *ptr, Proper * property updates to actually work). * * The cache is structured with a dual-layer structure - * - L1 = PointerRNA used as key; id.data is used (it should always be defined, + * - L1 = PointerRNA used as key; owner_id is used (it should always be defined, * and most updates end up using just that anyways) * - L2 = Update functions to be called on those PointerRNA's */ @@ -2423,7 +2345,7 @@ void RNA_property_update_cache_add(PointerRNA *ptr, PropertyRNA *prop) * since most update calls that we'll encounter only really care about this. */ /* TODO: later, the cache might need to have some nesting on L1 to cope better * with these problems + some tagging to indicate we need this */ - if (uce->ptr.id.data == ptr->id.data) { + if (uce->ptr.owner_id == ptr->owner_id) { break; } } @@ -2433,7 +2355,7 @@ void RNA_property_update_cache_add(PointerRNA *ptr, PropertyRNA *prop) BLI_addtail(&rna_updates_cache, uce); /* copy pointer */ - RNA_pointer_create(ptr->id.data, ptr->type, ptr->data, &uce->ptr); + RNA_pointer_create(ptr->owner_id, ptr->type, ptr->data, &uce->ptr); } /* check on the update func */ @@ -3851,7 +3773,7 @@ void RNA_property_pointer_set(PointerRNA *ptr, /* RNA */ if (pprop->set && !((prop->flag & PROP_NEVER_NULL) && ptr_value.data == NULL) && - !((prop->flag & PROP_ID_SELF_CHECK) && ptr->id.data == ptr_value.id.data)) { + !((prop->flag & PROP_ID_SELF_CHECK) && ptr->owner_id == ptr_value.owner_id)) { pprop->set(ptr, ptr_value, reports); } /* IDProperty */ @@ -5440,6 +5362,10 @@ static bool rna_path_parse(PointerRNA *ptr, * Resolve the given RNA Path to find the pointer and/or property * indicated by fully resolving the path. * + * \warning Unlike \a RNA_path_resolve_property(), that one *will* try to follow RNAPointers, + * e.g. the path 'parent' applied to a RNAObject \a ptr will return the object.parent in \a r_ptr, + * and a NULL \a r_prop... + * * \note Assumes all pointers provided are valid * \return True if path can be resolved to a valid "pointer + property" OR "pointer only" */ @@ -5814,14 +5740,14 @@ static char *rna_path_from_ID_to_idpgroup(PointerRNA *ptr) IDProperty *haystack; IDProperty *needle; - BLI_assert(ptr->id.data != NULL); + BLI_assert(ptr->owner_id != NULL); /* TODO, Support Bones/PoseBones. no pointers stored to the bones from here, only the ID. * See example in T25746. * Unless this is added only way to find this is to also search * all bones and pose bones of an armature or object. */ - RNA_id_pointer_create(ptr->id.data, &id_ptr); + RNA_id_pointer_create(ptr->owner_id, &id_ptr); haystack = RNA_struct_idprops(&id_ptr, false); if (haystack) { /* can fail when called on bones */ @@ -5833,11 +5759,79 @@ static char *rna_path_from_ID_to_idpgroup(PointerRNA *ptr) } } +/** + * Find the actual ID pointer and path from it to the given ID. + * + * \param id: ID reference to search the global owner for. + * \param[out] r_path: Path from the real ID to the initial ID. + * \return The ID pointer, or NULL in case of failure. + */ +ID *RNA_find_real_ID_and_path(Main *bmain, ID *id, const char **r_path) +{ + if (r_path) { + *r_path = ""; + } + + if ((id != NULL) && (id->flag & LIB_PRIVATE_DATA)) { + switch (GS(id->name)) { + case ID_NT: + if (r_path) { + *r_path = "node_tree"; + } + return BKE_node_tree_find_owner_ID(bmain, (bNodeTree *)id); + case ID_GR: + if (r_path) { + *r_path = "collection"; + } + return (ID *)BKE_collection_master_scene_search(bmain, (Collection *)id); + + default: + return NULL; + } + } + else { + return id; + } +} + +static char *rna_prepend_real_ID_path(Main *bmain, ID *id, char *path, ID **r_real_id) +{ + if (r_real_id != NULL) { + *r_real_id = NULL; + } + + const char *prefix; + ID *real_id = RNA_find_real_ID_and_path(bmain, id, &prefix); + + if (r_real_id != NULL) { + *r_real_id = real_id; + } + + if (path != NULL) { + char *new_path = NULL; + + if (real_id) { + if (prefix[0]) { + new_path = BLI_sprintfN("%s%s%s", prefix, path[0] == '[' ? "" : ".", path); + } + else { + return path; + } + } + + MEM_freeN(path); + return new_path; + } + else { + return prefix[0] != '\0' ? BLI_strdup(prefix) : NULL; + } +} + char *RNA_path_from_ID_to_struct(PointerRNA *ptr) { char *ptrpath = NULL; - if (!ptr->id.data || !ptr->data) { + if (!ptr->owner_id || !ptr->data) { return NULL; } @@ -5853,7 +5847,7 @@ char *RNA_path_from_ID_to_struct(PointerRNA *ptr) /* find the property in the struct we're nested in that references this struct, and * use its identifier as the first part of the path used... */ - RNA_id_pointer_create(ptr->id.data, &parentptr); + RNA_id_pointer_create(ptr->owner_id, &parentptr); userprop = RNA_struct_find_nested(&parentptr, ptr->type); if (userprop) { @@ -5875,6 +5869,13 @@ char *RNA_path_from_ID_to_struct(PointerRNA *ptr) return ptrpath; } +char *RNA_path_from_real_ID_to_struct(Main *bmain, PointerRNA *ptr, struct ID **r_real) +{ + char *path = RNA_path_from_ID_to_struct(ptr); + + return rna_prepend_real_ID_path(bmain, ptr->owner_id, path, r_real); +} + static void rna_path_array_multi_from_flat_index(const int dimsize[RNA_MAX_ARRAY_LENGTH], const int totdims, const int index_dim, @@ -5929,7 +5930,7 @@ char *RNA_path_from_ID_to_property_index(PointerRNA *ptr, const char *propname; char *ptrpath, *path; - if (!ptr->id.data || !ptr->data) { + if (!ptr->owner_id || !ptr->data) { return NULL; } @@ -5981,6 +5982,14 @@ char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop) return RNA_path_from_ID_to_property_index(ptr, prop, 0, -1); } +char *RNA_path_from_real_ID_to_property_index( + Main *bmain, PointerRNA *ptr, PropertyRNA *prop, int index_dim, int index, ID **r_real_id) +{ + char *path = RNA_path_from_ID_to_property_index(ptr, prop, index_dim, index); + + return rna_prepend_real_ID_path(bmain, ptr->owner_id, path, r_real_id); +} + /** * \return the path to given ptr/prop from the closest ancestor of given type, * if any (else return NULL). @@ -6000,7 +6009,7 @@ char *RNA_path_resolve_from_type_to_property(PointerRNA *ptr, return NULL; } - RNA_id_pointer_create(ptr->id.data, &idptr); + RNA_id_pointer_create(ptr->owner_id, &idptr); if (RNA_path_resolve_elements(&idptr, full_path, &path_elems)) { PropertyElemRNA *prop_elem; @@ -6027,32 +6036,46 @@ char *RNA_path_resolve_from_type_to_property(PointerRNA *ptr, * Get the ID as a python representation, eg: * bpy.data.foo["bar"] */ -char *RNA_path_full_ID_py(ID *id) +char *RNA_path_full_ID_py(Main *bmain, ID *id) { + const char *path; + ID *id_real = RNA_find_real_ID_and_path(bmain, id, &path); + + if (id_real) { + id = id_real; + } + else { + path = ""; + } + char id_esc[(sizeof(id->name) - 2) * 2]; BLI_strescape(id_esc, id->name + 2, sizeof(id_esc)); - return BLI_sprintfN("bpy.data.%s[\"%s\"]", BKE_idcode_to_name_plural(GS(id->name)), id_esc); + return BLI_sprintfN("bpy.data.%s[\"%s\"]%s%s", + BKE_idcode_to_name_plural(GS(id->name)), + id_esc, + path[0] ? "." : "", + path); } /** * Get the ID.struct as a python representation, eg: * bpy.data.foo["bar"].some_struct */ -char *RNA_path_full_struct_py(struct PointerRNA *ptr) +char *RNA_path_full_struct_py(Main *bmain, struct PointerRNA *ptr) { char *id_path; char *data_path; char *ret; - if (!ptr->id.data) { + if (!ptr->owner_id) { return NULL; } /* never fails */ - id_path = RNA_path_full_ID_py(ptr->id.data); + id_path = RNA_path_full_ID_py(bmain, ptr->owner_id); data_path = RNA_path_from_ID_to_struct(ptr); @@ -6072,10 +6095,8 @@ char *RNA_path_full_struct_py(struct PointerRNA *ptr) * Get the ID.struct.property as a python representation, eg: * bpy.data.foo["bar"].some_struct.some_prop[10] */ -char *RNA_path_full_property_py_ex(PointerRNA *ptr, - PropertyRNA *prop, - int index, - bool use_fallback) +char *RNA_path_full_property_py_ex( + Main *bmain, PointerRNA *ptr, PropertyRNA *prop, int index, bool use_fallback) { char *id_path; const char *data_delim; @@ -6084,12 +6105,12 @@ char *RNA_path_full_property_py_ex(PointerRNA *ptr, char *ret; - if (!ptr->id.data) { + if (!ptr->owner_id) { return NULL; } /* never fails */ - id_path = RNA_path_full_ID_py(ptr->id.data); + id_path = RNA_path_full_ID_py(bmain, ptr->owner_id); data_path = RNA_path_from_ID_to_property(ptr, prop); if (data_path) { @@ -6122,9 +6143,9 @@ char *RNA_path_full_property_py_ex(PointerRNA *ptr, return ret; } -char *RNA_path_full_property_py(PointerRNA *ptr, PropertyRNA *prop, int index) +char *RNA_path_full_property_py(Main *bmain, PointerRNA *ptr, PropertyRNA *prop, int index) { - return RNA_path_full_property_py_ex(ptr, prop, index, false); + return RNA_path_full_property_py_ex(bmain, ptr, prop, index, false); } /** @@ -6137,7 +6158,7 @@ char *RNA_path_struct_property_py(PointerRNA *ptr, PropertyRNA *prop, int index) char *ret; - if (!ptr->id.data) { + if (!ptr->owner_id) { return NULL; } @@ -6722,16 +6743,16 @@ char *RNA_pointer_as_string_id(bContext *C, PointerRNA *ptr) return cstring; } -static char *rna_pointer_as_string__bldata(PointerRNA *ptr) +static char *rna_pointer_as_string__bldata(Main *bmain, PointerRNA *ptr) { - if (ptr->type == NULL || ptr->id.data == NULL) { + if (ptr->type == NULL || ptr->owner_id == NULL) { return BLI_strdup("None"); } else if (RNA_struct_is_ID(ptr->type)) { - return RNA_path_full_ID_py(ptr->id.data); + return RNA_path_full_ID_py(bmain, ptr->owner_id); } else { - return RNA_path_full_struct_py(ptr); + return RNA_path_full_struct_py(bmain, ptr); } } @@ -6748,7 +6769,7 @@ char *RNA_pointer_as_string(bContext *C, return RNA_pointer_as_string_id(C, ptr_prop); } else { - return rna_pointer_as_string__bldata(ptr_prop); + return rna_pointer_as_string__bldata(CTX_data_main(C), ptr_prop); } } @@ -8115,59 +8136,6 @@ bool RNA_property_assign_default(PointerRNA *ptr, PropertyRNA *prop) } } -static bool rna_property_override_operation_apply(Main *bmain, - PointerRNA *ptr_local, - PointerRNA *ptr_override, - PointerRNA *ptr_storage, - PropertyRNA *prop_local, - PropertyRNA *prop_override, - PropertyRNA *prop_storage, - PointerRNA *ptr_item_local, - PointerRNA *ptr_item_override, - PointerRNA *ptr_item_storage, - IDOverrideLibraryPropertyOperation *opop); - -bool RNA_property_copy( - Main *bmain, PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop, int index) -{ - if (!RNA_property_editable(ptr, prop)) { - return false; - } - - PropertyRNA *prop_dst = prop; - PropertyRNA *prop_src = prop; - - /* Ensure we get real property data, - * be it an actual RNA property, or an IDProperty in disguise. */ - prop_dst = rna_ensure_property_realdata(&prop_dst, ptr); - prop_src = rna_ensure_property_realdata(&prop_src, fromptr); - - /* IDprops: destination may not exist, if source does and is set, try to create it. */ - /* Note: this is sort of quick hack/bandage to fix the issue, - * we need to rethink how IDProps are handled in 'diff' RNA code completely, imho... */ - if (prop_src != NULL && prop_dst == NULL && RNA_property_is_set(fromptr, prop)) { - BLI_assert(prop_src->magic != RNA_MAGIC); - IDProperty *idp_dst = RNA_struct_idprops(ptr, true); - IDProperty *prop_idp_dst = IDP_CopyProperty((IDProperty *)prop_src); - IDP_AddToGroup(idp_dst, prop_idp_dst); - rna_idproperty_touch(prop_idp_dst); - /* Nothing else to do here... */ - return true; - } - - if (ELEM(NULL, prop_dst, prop_src)) { - return false; - } - - IDOverrideLibraryPropertyOperation opop = { - .operation = IDOVERRIDE_LIBRARY_OP_REPLACE, - .subitem_reference_index = index, - .subitem_local_index = index, - }; - return rna_property_override_operation_apply( - bmain, ptr, fromptr, NULL, prop_dst, prop_src, NULL, NULL, NULL, NULL, &opop); -} - /* use RNA_warning macro which includes __func__ suffix */ void _RNA_warning(const char *format, ...) { @@ -8190,865 +8158,6 @@ void _RNA_warning(const char *format, ...) #endif } -static int rna_property_override_diff(Main *bmain, - PointerRNA *ptr_a, - PointerRNA *ptr_b, - PropertyRNA *prop, - PropertyRNA *prop_a, - PropertyRNA *prop_b, - const char *rna_path, - eRNACompareMode mode, - IDOverrideLibrary *override, - const int flags, - eRNAOverrideMatchResult *r_report_flags); - -bool RNA_property_equals( - Main *bmain, PointerRNA *ptr_a, PointerRNA *ptr_b, PropertyRNA *prop, eRNACompareMode mode) -{ - BLI_assert(ELEM(mode, RNA_EQ_STRICT, RNA_EQ_UNSET_MATCH_ANY, RNA_EQ_UNSET_MATCH_NONE)); - - return (rna_property_override_diff( - bmain, ptr_a, ptr_b, prop, NULL, NULL, NULL, mode, NULL, 0, NULL) == 0); -} - -bool RNA_struct_equals(Main *bmain, PointerRNA *ptr_a, PointerRNA *ptr_b, eRNACompareMode mode) -{ - CollectionPropertyIterator iter; - PropertyRNA *iterprop; - bool equals = true; - - if (ptr_a == NULL && ptr_b == NULL) { - return true; - } - else if (ptr_a == NULL || ptr_b == NULL) { - return false; - } - else if (ptr_a->type != ptr_b->type) { - return false; - } - - iterprop = RNA_struct_iterator_property(ptr_a->type); - - RNA_property_collection_begin(ptr_a, iterprop, &iter); - for (; iter.valid; RNA_property_collection_next(&iter)) { - PropertyRNA *prop = iter.ptr.data; - - if (!RNA_property_equals(bmain, ptr_a, ptr_b, prop, mode)) { - equals = false; - break; - } - } - RNA_property_collection_end(&iter); - - return equals; -} - -/* Low-level functions, also used by non-override RNA API like copy or equality check. */ - -/** Generic RNA property diff function. - * - * \note about \a prop and \a prop_a/prop_b parameters: - * the former is expected to be an 'un-resolved' one, - * while the two later are expected to be fully resolved ones - * (i.e. to be the IDProps when they should be, etc.). - * When \a prop is given, \a prop_a and \a prop_b should always be NULL, and vice-versa. - * This is necessary, because we cannot perform 'set/unset' checks on resolved properties - * (unset IDProps would merely be NULL then). - * - * \note When there is no equality, - * but we cannot determine an order (greater than/lesser than), we return 1. - */ -static int rna_property_override_diff(Main *bmain, - PointerRNA *ptr_a, - PointerRNA *ptr_b, - PropertyRNA *prop, - PropertyRNA *prop_a, - PropertyRNA *prop_b, - const char *rna_path, - eRNACompareMode mode, - IDOverrideLibrary *override, - const int flags, - eRNAOverrideMatchResult *r_report_flags) -{ - if (prop != NULL) { - BLI_assert(prop_a == NULL && prop_b == NULL); - prop_a = prop; - prop_b = prop; - } - - if (ELEM(NULL, prop_a, prop_b)) { - return (prop_a == prop_b) ? 0 : 1; - } - - if (!RNA_property_comparable(ptr_a, prop_a) || !RNA_property_comparable(ptr_b, prop_b)) { - return 0; - } - - if (mode == RNA_EQ_UNSET_MATCH_ANY) { - /* uninitialized properties are assumed to match anything */ - if (!RNA_property_is_set(ptr_a, prop_a) || !RNA_property_is_set(ptr_b, prop_b)) { - return 0; - } - } - else if (mode == RNA_EQ_UNSET_MATCH_NONE) { - /* unset properties never match set properties */ - if (RNA_property_is_set(ptr_a, prop_a) != RNA_property_is_set(ptr_b, prop_b)) { - return 1; - } - } - - if (prop != NULL) { - /* Ensure we get real property data, be it an actual RNA property, - * or an IDProperty in disguise. */ - prop_a = rna_ensure_property_realdata(&prop_a, ptr_a); - prop_b = rna_ensure_property_realdata(&prop_b, ptr_b); - - if (ELEM(NULL, prop_a, prop_b)) { - return (prop_a == prop_b) ? 0 : 1; - } - } - - /* Check if we are working with arrays. */ - const bool is_array_a = RNA_property_array_check(prop_a); - const bool is_array_b = RNA_property_array_check(prop_b); - - if (is_array_a != is_array_b) { - /* Should probably never happen actually... */ - BLI_assert(0); - return is_array_a ? 1 : -1; - } - - /* Get the length of the array to work with. */ - const int len_a = RNA_property_array_length(ptr_a, prop_a); - const int len_b = RNA_property_array_length(ptr_b, prop_b); - - if (len_a != len_b) { - /* Do not handle override in that case, - * we do not support insertion/deletion from arrays for now. */ - return len_a > len_b ? 1 : -1; - } - - if (is_array_a && len_a == 0) { - /* Empty arrays, will happen in some case with dynamic ones. */ - return 0; - } - - RNAPropOverrideDiff override_diff = NULL; - /* Special case for IDProps, we use default callback then. */ - if (prop_a->magic != RNA_MAGIC) { - override_diff = rna_property_override_diff_default; - if (prop_b->magic == RNA_MAGIC && prop_b->override_diff != override_diff) { - override_diff = NULL; - } - } - else if (prop_b->magic != RNA_MAGIC) { - override_diff = rna_property_override_diff_default; - if (prop_a->override_diff != override_diff) { - override_diff = NULL; - } - } - else if (prop_a->override_diff == prop_b->override_diff) { - override_diff = prop_a->override_diff; - } - - if (override_diff == NULL) { -#ifndef NDEBUG - printf("'%s' gives unmatching or NULL RNA diff callbacks, should not happen (%d vs. %d).\n", - rna_path ? - rna_path : - (prop_a->magic != RNA_MAGIC ? ((IDProperty *)prop_a)->name : prop_a->identifier), - prop_a->magic == RNA_MAGIC, - prop_b->magic == RNA_MAGIC); -#endif - BLI_assert(0); - return 1; - } - - bool override_changed = false; - int diff_flags = flags; - if (!RNA_property_overridable_get(ptr_a, prop_a)) { - diff_flags &= ~RNA_OVERRIDE_COMPARE_CREATE; - } - const int diff = override_diff(bmain, - ptr_a, - ptr_b, - prop_a, - prop_b, - len_a, - len_b, - mode, - override, - rna_path, - diff_flags, - &override_changed); - if (override_changed && r_report_flags) { - *r_report_flags |= RNA_OVERRIDE_MATCH_RESULT_CREATED; - } - - return diff; -} - -/* Modify local data-block to make it ready for override application - * (only needed for diff operations, where we use - * the local data-block's data as second operand). */ -static bool rna_property_override_operation_store(Main *bmain, - PointerRNA *ptr_local, - PointerRNA *ptr_reference, - PointerRNA *ptr_storage, - PropertyRNA *prop_local, - PropertyRNA *prop_reference, - PropertyRNA *prop_storage, - IDOverrideLibraryProperty *op) -{ - int len_local, len_reference, len_storage = 0; - bool changed = false; - - if (ptr_storage == NULL) { - return changed; - } - - /* get the length of the array to work with */ - len_local = RNA_property_array_length(ptr_local, prop_local); - len_reference = RNA_property_array_length(ptr_reference, prop_reference); - if (prop_storage) { - len_storage = RNA_property_array_length(ptr_storage, prop_storage); - } - - if (len_local != len_reference || len_local != len_storage) { - /* Do not handle override in that case, - * we do not support insertion/deletion from arrays for now. */ - return changed; - } - - BLI_assert(prop_local->override_store == prop_reference->override_store && - (!ptr_storage || prop_local->override_store == prop_storage->override_store) && - prop_local->override_store != NULL); - - for (IDOverrideLibraryPropertyOperation *opop = op->operations.first; opop; opop = opop->next) { - /* Only needed for diff operations. */ - if (!ELEM(opop->operation, - IDOVERRIDE_LIBRARY_OP_ADD, - IDOVERRIDE_LIBRARY_OP_SUBTRACT, - IDOVERRIDE_LIBRARY_OP_MULTIPLY)) { - continue; - } - - if (prop_local->override_store(bmain, - ptr_local, - ptr_reference, - ptr_storage, - prop_local, - prop_reference, - prop_storage, - len_local, - len_reference, - len_storage, - opop)) { - changed = true; - } - } - - return changed; -} - -static bool rna_property_override_operation_apply(Main *bmain, - PointerRNA *ptr_local, - PointerRNA *ptr_override, - PointerRNA *ptr_storage, - PropertyRNA *prop_local, - PropertyRNA *prop_override, - PropertyRNA *prop_storage, - PointerRNA *ptr_item_local, - PointerRNA *ptr_item_override, - PointerRNA *ptr_item_storage, - IDOverrideLibraryPropertyOperation *opop) -{ - int len_local, len_reference, len_storage = 0; - - const short override_op = opop->operation; - - if (override_op == IDOVERRIDE_LIBRARY_OP_NOOP) { - return true; - } - - if (ELEM(override_op, - IDOVERRIDE_LIBRARY_OP_ADD, - IDOVERRIDE_LIBRARY_OP_SUBTRACT, - IDOVERRIDE_LIBRARY_OP_MULTIPLY) && - !ptr_storage) { - /* We cannot apply 'diff' override operations without some reference storage. - * This should typically only happen at read time of .blend file... */ - return false; - } - - if (ELEM(override_op, - IDOVERRIDE_LIBRARY_OP_ADD, - IDOVERRIDE_LIBRARY_OP_SUBTRACT, - IDOVERRIDE_LIBRARY_OP_MULTIPLY) && - !prop_storage) { - /* We cannot apply 'diff' override operations without some reference storage. - * This should typically only happen at read time of .blend file... */ - return false; - } - - RNAPropOverrideApply override_apply = NULL; - /* Special case for IDProps, we use default callback then. */ - if (prop_local->magic != RNA_MAGIC) { - override_apply = rna_property_override_apply_default; - if (prop_override->magic == RNA_MAGIC && prop_override->override_apply != override_apply) { - override_apply = NULL; - } - } - else if (prop_override->magic != RNA_MAGIC) { - override_apply = rna_property_override_apply_default; - if (prop_local->override_apply != override_apply) { - override_apply = NULL; - } - } - else if (prop_local->override_apply == prop_override->override_apply) { - override_apply = prop_local->override_apply; - } - - if (ptr_storage && prop_storage->magic == RNA_MAGIC && - prop_storage->override_apply != override_apply) { - override_apply = NULL; - } - - if (override_apply == NULL) { -#ifndef NDEBUG - printf("'%s' gives unmatching or NULL RNA copy callbacks, should not happen (%d vs. %d).\n", - prop_local->magic != RNA_MAGIC ? ((IDProperty *)prop_local)->name : - prop_local->identifier, - prop_local->magic == RNA_MAGIC, - prop_override->magic == RNA_MAGIC); -#endif - BLI_assert(0); - return false; - } - - /* get the length of the array to work with */ - len_local = RNA_property_array_length(ptr_local, prop_local); - len_reference = RNA_property_array_length(ptr_override, prop_override); - if (ptr_storage) { - len_storage = RNA_property_array_length(ptr_storage, prop_storage); - } - - if (len_local != len_reference || (ptr_storage && len_local != len_storage)) { - /* Do not handle override in that case, - * we do not support insertion/deletion from arrays for now. */ - return false; - } - - /* get and set the default values as appropriate for the various types */ - return override_apply(bmain, - ptr_local, - ptr_override, - ptr_storage, - prop_local, - prop_override, - prop_storage, - len_local, - len_reference, - len_storage, - ptr_item_local, - ptr_item_override, - ptr_item_storage, - opop); -} - -/** - * Check whether reference and local overridden data match (are the same), - * with respect to given restrictive sets of properties. - * If requested, will generate needed new property overrides, and/or restore values from reference. - * - * \param r_report_flags: If given, - * will be set with flags matching actions taken by the function on \a ptr_local. - * - * \return True if _resulting_ \a ptr_local does match \a ptr_reference. - */ -bool RNA_struct_override_matches(Main *bmain, - PointerRNA *ptr_local, - PointerRNA *ptr_reference, - const char *root_path, - IDOverrideLibrary *override, - const eRNAOverrideMatch flags, - eRNAOverrideMatchResult *r_report_flags) -{ - CollectionPropertyIterator iter; - PropertyRNA *iterprop; - bool matching = true; - - BLI_assert(ptr_local->type == ptr_reference->type); - BLI_assert(ptr_local->id.data && ptr_reference->id.data); - - const bool ignore_non_overridable = (flags & RNA_OVERRIDE_COMPARE_IGNORE_NON_OVERRIDABLE) != 0; - const bool ignore_overridden = (flags & RNA_OVERRIDE_COMPARE_IGNORE_OVERRIDDEN) != 0; - const bool do_create = (flags & RNA_OVERRIDE_COMPARE_CREATE) != 0; - const bool do_restore = (flags & RNA_OVERRIDE_COMPARE_RESTORE) != 0; - -//#define DEBUG_OVERRIDE_TIMEIT -#ifdef DEBUG_OVERRIDE_TIMEIT - static float _sum_time_global = 0.0f; - static float _num_time_global = 0.0f; - double _timeit_time_global; - static float _sum_time_diffing = 0.0f; - static float _delta_time_diffing = 0.0f; - static int _num_delta_time_diffing = 0.0f; - static float _num_time_diffing = 0.0f; - double _timeit_time_diffing; - - if (!root_path) { - _delta_time_diffing = 0.0f; - _num_delta_time_diffing = 0; - _timeit_time_global = PIL_check_seconds_timer(); - } -#endif - - iterprop = RNA_struct_iterator_property(ptr_local->type); - - for (RNA_property_collection_begin(ptr_local, iterprop, &iter); iter.valid; - RNA_property_collection_next(&iter)) { - PropertyRNA *prop_local = iter.ptr.data; - PropertyRNA *prop_reference = iter.ptr.data; - - /* Ensure we get real property data, be it an actual RNA property, - * or an IDProperty in disguise. */ - prop_local = rna_ensure_property_realdata(&prop_local, ptr_local); - prop_reference = rna_ensure_property_realdata(&prop_reference, ptr_reference); - - if (ELEM(NULL, prop_local, prop_reference)) { - continue; - } - - if (ignore_non_overridable && !RNA_property_overridable_get(ptr_local, prop_local)) { - continue; - } - -#if 0 /* This actually makes things slower, since it has to check for animation paths etc! */ - if (RNA_property_animated(ptr_local, prop_local)) { - /* We cannot do anything here really, animation is some kind of dynamic overrides that has - * precedence over static one... */ - continue; - } -#endif - -#define RNA_PATH_BUFFSIZE 8192 -#define RNA_PATH_PRINTF(_str, ...) \ - if (BLI_snprintf(rna_path, RNA_PATH_BUFFSIZE, (_str), __VA_ARGS__) >= RNA_PATH_BUFFSIZE) { \ - rna_path = BLI_sprintfN((_str), __VA_ARGS__); \ - } \ - (void)0 -#define RNA_PATH_FREE \ - if (rna_path != rna_path_buffer) \ - MEM_freeN(rna_path) - - char rna_path_buffer[RNA_PATH_BUFFSIZE]; - char *rna_path = rna_path_buffer; - - /* XXX TODO this will have to be refined to handle collections insertions, and array items */ - if (root_path) { - /* Inlined building, much much more efficient. */ - if (prop_local->magic == RNA_MAGIC) { - RNA_PATH_PRINTF("%s.%s", root_path, RNA_property_identifier(prop_local)); - } - else { - RNA_PATH_PRINTF("%s[\"%s\"]", root_path, RNA_property_identifier(prop_local)); - } - } - else { - /* This is rather slow, but is not much called, so not really worth optimizing. */ - rna_path = RNA_path_from_ID_to_property(ptr_local, prop_local); - } - if (rna_path == NULL) { - continue; - } - - // printf("Override Checking %s\n", rna_path); - - if (ignore_overridden && BKE_override_library_property_find(override, rna_path) != NULL) { - RNA_PATH_FREE; - continue; - } - -#ifdef DEBUG_OVERRIDE_TIMEIT - if (!root_path) { - _timeit_time_diffing = PIL_check_seconds_timer(); - } -#endif - - eRNAOverrideMatchResult report_flags = 0; - const int diff = rna_property_override_diff(bmain, - ptr_local, - ptr_reference, - NULL, - prop_local, - prop_reference, - rna_path, - RNA_EQ_STRICT, - override, - flags, - &report_flags); - -#ifdef DEBUG_OVERRIDE_TIMEIT - if (!root_path) { - const float _delta_time = (float)(PIL_check_seconds_timer() - _timeit_time_diffing); - _delta_time_diffing += _delta_time; - _num_delta_time_diffing++; - } -#endif - - matching = matching && diff == 0; - if (r_report_flags) { - *r_report_flags |= report_flags; - } - - if (diff != 0) { - /* XXX TODO: refine this for per-item overriding of arrays... */ - IDOverrideLibraryProperty *op = BKE_override_library_property_find(override, rna_path); - IDOverrideLibraryPropertyOperation *opop = op ? op->operations.first : NULL; - - if (do_restore && (report_flags & RNA_OVERRIDE_MATCH_RESULT_CREATED) == 0) { - /* We are allowed to restore to reference's values. */ - if (ELEM(NULL, op, opop) || opop->operation == IDOVERRIDE_LIBRARY_OP_NOOP) { - /* We should restore that property to its reference value */ - if (RNA_property_editable(ptr_local, prop_local)) { - IDOverrideLibraryPropertyOperation opop_tmp = { - .operation = IDOVERRIDE_LIBRARY_OP_REPLACE, - .subitem_reference_index = -1, - .subitem_local_index = -1, - }; - rna_property_override_operation_apply(bmain, - ptr_local, - ptr_reference, - NULL, - prop_local, - prop_reference, - NULL, - NULL, - NULL, - NULL, - &opop_tmp); - if (r_report_flags) { - *r_report_flags |= RNA_OVERRIDE_MATCH_RESULT_RESTORED; - } - } - else { - /* Too noisy for now, this triggers on runtime props like transform matrices etc. */ -#if 0 - BLI_assert(!"We have differences between reference and " - "overriding data on non-editable property."); -#endif - matching = false; - } - } - } - else if ((report_flags & RNA_OVERRIDE_MATCH_RESULT_CREATED) == 0 && ELEM(NULL, op, opop)) { - /* This property is not overridden, and differs from reference, so we have no match. */ - matching = false; - if (!(do_create || do_restore)) { - /* Since we have no 'changing' action allowed, we can break here. */ - MEM_SAFE_FREE(rna_path); - break; - } - } - } - - RNA_PATH_FREE; - -#undef RNA_PATH_BUFFSIZE -#undef RNA_PATH_PRINTF -#undef RNA_PATH_FREE - } - RNA_property_collection_end(&iter); - -#ifdef DEBUG_OVERRIDE_TIMEIT - if (!root_path) { - const float _delta_time = (float)(PIL_check_seconds_timer() - _timeit_time_global); - _sum_time_global += _delta_time; - _num_time_global++; - _sum_time_diffing += _delta_time_diffing; - _num_time_diffing++; - printf("ID: %s\n", ((ID *)ptr_local->id.data)->name); - printf("time end (%s): %.6f\n", __func__, _delta_time); - printf("time averaged (%s): %.6f (total: %.6f, in %d runs)\n", - __func__, - (_sum_time_global / _num_time_global), - _sum_time_global, - (int)_num_time_global); - printf("diffing time end (%s): %.6f (in %d runs)\n", - __func__, - _delta_time_diffing, - _num_delta_time_diffing); - printf("diffing time averaged (%s): %.6f (total: %.6f, in %d runs)\n", - __func__, - (_sum_time_diffing / _num_time_diffing), - _sum_time_diffing, - (int)_num_time_diffing); - } -#endif - - return matching; -} - -/** Store needed second operands into \a storage data-block - * for differential override operations. */ -bool RNA_struct_override_store(Main *bmain, - PointerRNA *ptr_local, - PointerRNA *ptr_reference, - PointerRNA *ptr_storage, - IDOverrideLibrary *override) -{ - bool changed = false; - -#ifdef DEBUG_OVERRIDE_TIMEIT - TIMEIT_START_AVERAGED(RNA_struct_override_store); -#endif - for (IDOverrideLibraryProperty *op = override->properties.first; op; op = op->next) { - /* Simplified for now! */ - PointerRNA data_reference, data_local; - PropertyRNA *prop_reference, *prop_local; - - if (RNA_path_resolve_property(ptr_local, op->rna_path, &data_local, &prop_local) && - RNA_path_resolve_property(ptr_reference, op->rna_path, &data_reference, &prop_reference)) { - PointerRNA data_storage; - PropertyRNA *prop_storage = NULL; - - /* It is totally OK if this does not success, - * only a subset of override operations actually need storage. */ - if (ptr_storage && (ptr_storage->id.data != NULL)) { - RNA_path_resolve_property(ptr_storage, op->rna_path, &data_storage, &prop_storage); - } - - if (rna_property_override_operation_store(bmain, - &data_local, - &data_reference, - &data_storage, - prop_reference, - prop_local, - prop_storage, - op)) { - changed = true; - } - } - } -#ifdef DEBUG_OVERRIDE_TIMEIT - TIMEIT_END_AVERAGED(RNA_struct_override_store); -#endif - - return changed; -} - -static void rna_property_override_apply_ex(Main *bmain, - PointerRNA *ptr_local, - PointerRNA *ptr_override, - PointerRNA *ptr_storage, - PropertyRNA *prop_local, - PropertyRNA *prop_override, - PropertyRNA *prop_storage, - PointerRNA *ptr_item_local, - PointerRNA *ptr_item_override, - PointerRNA *ptr_item_storage, - IDOverrideLibraryProperty *op, - const bool do_insert) -{ - for (IDOverrideLibraryPropertyOperation *opop = op->operations.first; opop; opop = opop->next) { - if (!do_insert != !ELEM(opop->operation, - IDOVERRIDE_LIBRARY_OP_INSERT_AFTER, - IDOVERRIDE_LIBRARY_OP_INSERT_BEFORE)) { - if (!do_insert) { - printf("Skipping insert override operations in first pass (%s)!\n", op->rna_path); - } - continue; - } - if (!rna_property_override_operation_apply(bmain, - ptr_local, - ptr_override, - ptr_storage, - prop_local, - prop_override, - prop_storage, - ptr_item_local, - ptr_item_override, - ptr_item_storage, - opop)) { - /* TODO No assert here, would be much much better to just report as warning, - * failing override applications will probably be fairly common! */ - BLI_assert(0); - } - } -} - -/** Apply given \a override operations on \a ptr_local, using \a ptr_override - * (and \a ptr_storage form differential ops) as source. */ -void RNA_struct_override_apply(Main *bmain, - PointerRNA *ptr_local, - PointerRNA *ptr_override, - PointerRNA *ptr_storage, - IDOverrideLibrary *override) -{ -#ifdef DEBUG_OVERRIDE_TIMEIT - TIMEIT_START_AVERAGED(RNA_struct_override_apply); -#endif - /* Note: Applying insert operations in a separate pass is mandatory. - * We could optimize this later, but for now, as inefficient as it is, - * don't think this is a critical point. - */ - bool do_insert = false; - for (int i = 0; i < 2; i++, do_insert = true) { - for (IDOverrideLibraryProperty *op = override->properties.first; op; op = op->next) { - /* Simplified for now! */ - PointerRNA data_override, data_local; - PointerRNA data_item_override, data_item_local; - PropertyRNA *prop_override, *prop_local; - - if (RNA_path_resolve_property_and_item_pointer( - ptr_local, op->rna_path, &data_local, &prop_local, &data_item_local) && - RNA_path_resolve_property_and_item_pointer( - ptr_override, op->rna_path, &data_override, &prop_override, &data_item_override)) { - PointerRNA data_storage, data_item_storage; - PropertyRNA *prop_storage = NULL; - - /* It is totally OK if this does not success, - * only a subset of override operations actually need storage. */ - if (ptr_storage && (ptr_storage->id.data != NULL)) { - RNA_path_resolve_property_and_item_pointer( - ptr_storage, op->rna_path, &data_storage, &prop_storage, &data_item_storage); - } - - rna_property_override_apply_ex(bmain, - &data_local, - &data_override, - prop_storage ? &data_storage : NULL, - prop_local, - prop_override, - prop_storage, - &data_item_local, - &data_item_override, - prop_storage ? &data_item_storage : NULL, - op, - do_insert); - } -#ifndef NDEBUG - else { - printf( - "Failed to apply library override operation to '%s.%s' " - "(could not resolve some properties, local: %d, override: %d)\n", - ((ID *)ptr_override->id.data)->name, - op->rna_path, - RNA_path_resolve_property(ptr_local, op->rna_path, &data_local, &prop_local), - RNA_path_resolve_property(ptr_override, op->rna_path, &data_override, &prop_override)); - } -#endif - } - } -#ifdef DEBUG_OVERRIDE_TIMEIT - TIMEIT_END_AVERAGED(RNA_struct_override_apply); -#endif -} - -IDOverrideLibraryProperty *RNA_property_override_property_find(PointerRNA *ptr, PropertyRNA *prop) -{ - ID *id = ptr->id.data; - - if (!id || !id->override_library) { - return NULL; - } - - char *rna_path = RNA_path_from_ID_to_property(ptr, prop); - if (rna_path) { - IDOverrideLibraryProperty *op = BKE_override_library_property_find(id->override_library, - rna_path); - MEM_freeN(rna_path); - return op; - } - return NULL; -} - -IDOverrideLibraryProperty *RNA_property_override_property_get(PointerRNA *ptr, - PropertyRNA *prop, - bool *r_created) -{ - ID *id = ptr->id.data; - - if (!id || !id->override_library) { - return NULL; - } - - char *rna_path = RNA_path_from_ID_to_property(ptr, prop); - if (rna_path) { - IDOverrideLibraryProperty *op = BKE_override_library_property_get( - id->override_library, rna_path, r_created); - MEM_freeN(rna_path); - return op; - } - return NULL; -} - -IDOverrideLibraryPropertyOperation *RNA_property_override_property_operation_find( - PointerRNA *ptr, PropertyRNA *prop, const int index, const bool strict, bool *r_strict) -{ - IDOverrideLibraryProperty *op = RNA_property_override_property_find(ptr, prop); - - if (!op) { - return NULL; - } - - return BKE_override_library_property_operation_find( - op, NULL, NULL, index, index, strict, r_strict); -} - -IDOverrideLibraryPropertyOperation *RNA_property_override_property_operation_get( - PointerRNA *ptr, - PropertyRNA *prop, - const short operation, - const int index, - const bool strict, - bool *r_strict, - bool *r_created) -{ - IDOverrideLibraryProperty *op = RNA_property_override_property_get(ptr, prop, NULL); - - if (!op) { - return NULL; - } - - return BKE_override_library_property_operation_get( - op, operation, NULL, NULL, index, index, strict, r_strict, r_created); -} - -eRNAOverrideStatus RNA_property_override_library_status(PointerRNA *ptr, - PropertyRNA *prop, - const int index) -{ - int override_status = 0; - - if (!BKE_override_library_is_enabled()) { - return override_status; - } - - if (!ptr || !prop || !ptr->id.data || !((ID *)ptr->id.data)->override_library) { - return override_status; - } - - if (RNA_property_overridable_get(ptr, prop) && RNA_property_editable_flag(ptr, prop)) { - override_status |= RNA_OVERRIDE_STATUS_OVERRIDABLE; - } - - IDOverrideLibraryPropertyOperation *opop = RNA_property_override_property_operation_find( - ptr, prop, index, false, NULL); - if (opop != NULL) { - override_status |= RNA_OVERRIDE_STATUS_OVERRIDDEN; - if (opop->flag & IDOVERRIDE_LIBRARY_FLAG_MANDATORY) { - override_status |= RNA_OVERRIDE_STATUS_MANDATORY; - } - if (opop->flag & IDOVERRIDE_LIBRARY_FLAG_LOCKED) { - override_status |= RNA_OVERRIDE_STATUS_LOCKED; - } - } - - return override_status; -} - bool RNA_path_resolved_create(PointerRNA *ptr, struct PropertyRNA *prop, const int prop_index, diff --git a/source/blender/makesrna/intern/rna_access_compare_override.c b/source/blender/makesrna/intern/rna_access_compare_override.c new file mode 100644 index 00000000000..b0a83ea38c6 --- /dev/null +++ b/source/blender/makesrna/intern/rna_access_compare_override.c @@ -0,0 +1,1099 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup RNA + */ + +#include "MEM_guardedalloc.h" + +#include "DNA_ID.h" +#include "DNA_constraint_types.h" +#include "DNA_modifier_types.h" + +#include "BLI_utildefines.h" +#include "BLI_string.h" + +#ifdef DEBUG_OVERRIDE_TIMEIT +# include "PIL_time_utildefines.h" +#endif + +#include "BKE_idprop.h" +#include "BKE_library_override.h" +#include "BKE_main.h" + +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "rna_internal.h" +#include "rna_access_internal.h" + +int RNA_property_override_flag(PropertyRNA *prop) +{ + return rna_ensure_property(prop)->flag_override; +} + +/** \note Does not take into account editable status, this has to be checked separately + * (using #RNA_property_editable_flag() usually). */ +bool RNA_property_overridable_get(PointerRNA *ptr, PropertyRNA *prop) +{ + if (prop->magic == RNA_MAGIC) { + /* Special handling for insertions of constraints or modifiers... */ + /* TODO Note We may want to add a more generic system to RNA + * (like a special property in struct of items) + * if we get more overrideable collections, + * for now we can live with those special-cases handling I think. */ + if (RNA_struct_is_a(ptr->type, &RNA_Constraint)) { + bConstraint *con = ptr->data; + if (con->flag & CONSTRAINT_OVERRIDE_LIBRARY_LOCAL) { + return true; + } + } + else if (RNA_struct_is_a(ptr->type, &RNA_Modifier)) { + ModifierData *mod = ptr->data; + if (mod->flag & eModifierFlag_OverrideLibrary_Local) { + return true; + } + } + /* If this is a RNA-defined property (real or 'virtual' IDProp), + * we want to use RNA prop flag. */ + return !(prop->flag_override & PROPOVERRIDE_NO_COMPARISON) && + (prop->flag_override & PROPOVERRIDE_OVERRIDABLE_LIBRARY); + } + else { + /* If this is a real 'pure' IDProp (aka custom property), we want to use the IDProp flag. */ + return !(prop->flag_override & PROPOVERRIDE_NO_COMPARISON) && + (((IDProperty *)prop)->flag & IDP_FLAG_OVERRIDABLE_LIBRARY); + } +} + +/* Should only be used for custom properties */ +bool RNA_property_overridable_library_set(PointerRNA *UNUSED(ptr), + PropertyRNA *prop, + const bool is_overridable) +{ + /* Only works for pure custom properties IDProps. */ + if (prop->magic != RNA_MAGIC) { + IDProperty *idprop = (IDProperty *)prop; + + idprop->flag = is_overridable ? (idprop->flag | IDP_FLAG_OVERRIDABLE_LIBRARY) : + (idprop->flag & ~IDP_FLAG_OVERRIDABLE_LIBRARY); + return true; + } + + return false; +} + +bool RNA_property_overridden(PointerRNA *ptr, PropertyRNA *prop) +{ + char *rna_path = RNA_path_from_ID_to_property(ptr, prop); + ID *id = ptr->owner_id; + + if (rna_path == NULL || id == NULL || id->override_library == NULL) { + return false; + } + + return (BKE_override_library_property_find(id->override_library, rna_path) != NULL); +} + +bool RNA_property_comparable(PointerRNA *UNUSED(ptr), PropertyRNA *prop) +{ + prop = rna_ensure_property(prop); + + return !(prop->flag_override & PROPOVERRIDE_NO_COMPARISON); +} + +static bool rna_property_override_operation_apply(Main *bmain, + PointerRNA *ptr_local, + PointerRNA *ptr_override, + PointerRNA *ptr_storage, + PropertyRNA *prop_local, + PropertyRNA *prop_override, + PropertyRNA *prop_storage, + PointerRNA *ptr_item_local, + PointerRNA *ptr_item_override, + PointerRNA *ptr_item_storage, + IDOverrideLibraryPropertyOperation *opop); + +bool RNA_property_copy( + Main *bmain, PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop, int index) +{ + if (!RNA_property_editable(ptr, prop)) { + return false; + } + + PropertyRNA *prop_dst = prop; + PropertyRNA *prop_src = prop; + + /* Ensure we get real property data, + * be it an actual RNA property, or an IDProperty in disguise. */ + prop_dst = rna_ensure_property_realdata(&prop_dst, ptr); + prop_src = rna_ensure_property_realdata(&prop_src, fromptr); + + /* IDprops: destination may not exist, if source does and is set, try to create it. */ + /* Note: this is sort of quick hack/bandage to fix the issue, + * we need to rethink how IDProps are handled in 'diff' RNA code completely, imho... */ + if (prop_src != NULL && prop_dst == NULL && RNA_property_is_set(fromptr, prop)) { + BLI_assert(prop_src->magic != RNA_MAGIC); + IDProperty *idp_dst = RNA_struct_idprops(ptr, true); + IDProperty *prop_idp_dst = IDP_CopyProperty((IDProperty *)prop_src); + IDP_AddToGroup(idp_dst, prop_idp_dst); + rna_idproperty_touch(prop_idp_dst); + /* Nothing else to do here... */ + return true; + } + + if (ELEM(NULL, prop_dst, prop_src)) { + return false; + } + + IDOverrideLibraryPropertyOperation opop = { + .operation = IDOVERRIDE_LIBRARY_OP_REPLACE, + .subitem_reference_index = index, + .subitem_local_index = index, + }; + return rna_property_override_operation_apply( + bmain, ptr, fromptr, NULL, prop_dst, prop_src, NULL, NULL, NULL, NULL, &opop); +} + +static int rna_property_override_diff(Main *bmain, + PointerRNA *ptr_a, + PointerRNA *ptr_b, + PropertyRNA *prop, + PropertyRNA *prop_a, + PropertyRNA *prop_b, + const char *rna_path, + eRNACompareMode mode, + IDOverrideLibrary *override, + const int flags, + eRNAOverrideMatchResult *r_report_flags); + +bool RNA_property_equals( + Main *bmain, PointerRNA *ptr_a, PointerRNA *ptr_b, PropertyRNA *prop, eRNACompareMode mode) +{ + BLI_assert(ELEM(mode, RNA_EQ_STRICT, RNA_EQ_UNSET_MATCH_ANY, RNA_EQ_UNSET_MATCH_NONE)); + + return (rna_property_override_diff( + bmain, ptr_a, ptr_b, prop, NULL, NULL, NULL, mode, NULL, 0, NULL) == 0); +} + +bool RNA_struct_equals(Main *bmain, PointerRNA *ptr_a, PointerRNA *ptr_b, eRNACompareMode mode) +{ + CollectionPropertyIterator iter; + PropertyRNA *iterprop; + bool equals = true; + + if (ptr_a == NULL && ptr_b == NULL) { + return true; + } + else if (ptr_a == NULL || ptr_b == NULL) { + return false; + } + else if (ptr_a->type != ptr_b->type) { + return false; + } + + iterprop = RNA_struct_iterator_property(ptr_a->type); + + RNA_property_collection_begin(ptr_a, iterprop, &iter); + for (; iter.valid; RNA_property_collection_next(&iter)) { + PropertyRNA *prop = iter.ptr.data; + + if (!RNA_property_equals(bmain, ptr_a, ptr_b, prop, mode)) { + equals = false; + break; + } + } + RNA_property_collection_end(&iter); + + return equals; +} + +/* Low-level functions, also used by non-override RNA API like copy or equality check. */ + +/** Generic RNA property diff function. + * + * \note about \a prop and \a prop_a/prop_b parameters: + * the former is expected to be an 'un-resolved' one, + * while the two later are expected to be fully resolved ones + * (i.e. to be the IDProps when they should be, etc.). + * When \a prop is given, \a prop_a and \a prop_b should always be NULL, and vice-versa. + * This is necessary, because we cannot perform 'set/unset' checks on resolved properties + * (unset IDProps would merely be NULL then). + * + * \note When there is no equality, + * but we cannot determine an order (greater than/lesser than), we return 1. + */ +static int rna_property_override_diff(Main *bmain, + PointerRNA *ptr_a, + PointerRNA *ptr_b, + PropertyRNA *prop, + PropertyRNA *prop_a, + PropertyRNA *prop_b, + const char *rna_path, + eRNACompareMode mode, + IDOverrideLibrary *override, + const int flags, + eRNAOverrideMatchResult *r_report_flags) +{ + if (prop != NULL) { + BLI_assert(prop_a == NULL && prop_b == NULL); + prop_a = prop; + prop_b = prop; + } + + if (ELEM(NULL, prop_a, prop_b)) { + return (prop_a == prop_b) ? 0 : 1; + } + + if (!RNA_property_comparable(ptr_a, prop_a) || !RNA_property_comparable(ptr_b, prop_b)) { + return 0; + } + + if (mode == RNA_EQ_UNSET_MATCH_ANY) { + /* uninitialized properties are assumed to match anything */ + if (!RNA_property_is_set(ptr_a, prop_a) || !RNA_property_is_set(ptr_b, prop_b)) { + return 0; + } + } + else if (mode == RNA_EQ_UNSET_MATCH_NONE) { + /* unset properties never match set properties */ + if (RNA_property_is_set(ptr_a, prop_a) != RNA_property_is_set(ptr_b, prop_b)) { + return 1; + } + } + + if (prop != NULL) { + /* Ensure we get real property data, be it an actual RNA property, + * or an IDProperty in disguise. */ + prop_a = rna_ensure_property_realdata(&prop_a, ptr_a); + prop_b = rna_ensure_property_realdata(&prop_b, ptr_b); + + if (ELEM(NULL, prop_a, prop_b)) { + return (prop_a == prop_b) ? 0 : 1; + } + } + + /* Check if we are working with arrays. */ + const bool is_array_a = RNA_property_array_check(prop_a); + const bool is_array_b = RNA_property_array_check(prop_b); + + if (is_array_a != is_array_b) { + /* Should probably never happen actually... */ + BLI_assert(0); + return is_array_a ? 1 : -1; + } + + /* Get the length of the array to work with. */ + const int len_a = RNA_property_array_length(ptr_a, prop_a); + const int len_b = RNA_property_array_length(ptr_b, prop_b); + + if (len_a != len_b) { + /* Do not handle override in that case, + * we do not support insertion/deletion from arrays for now. */ + return len_a > len_b ? 1 : -1; + } + + if (is_array_a && len_a == 0) { + /* Empty arrays, will happen in some case with dynamic ones. */ + return 0; + } + + RNAPropOverrideDiff override_diff = NULL; + /* Special case for IDProps, we use default callback then. */ + if (prop_a->magic != RNA_MAGIC) { + override_diff = rna_property_override_diff_default; + if (prop_b->magic == RNA_MAGIC && prop_b->override_diff != override_diff) { + override_diff = NULL; + } + } + else if (prop_b->magic != RNA_MAGIC) { + override_diff = rna_property_override_diff_default; + if (prop_a->override_diff != override_diff) { + override_diff = NULL; + } + } + else if (prop_a->override_diff == prop_b->override_diff) { + override_diff = prop_a->override_diff; + } + + if (override_diff == NULL) { +#ifndef NDEBUG + printf("'%s' gives unmatching or NULL RNA diff callbacks, should not happen (%d vs. %d).\n", + rna_path ? + rna_path : + (prop_a->magic != RNA_MAGIC ? ((IDProperty *)prop_a)->name : prop_a->identifier), + prop_a->magic == RNA_MAGIC, + prop_b->magic == RNA_MAGIC); +#endif + BLI_assert(0); + return 1; + } + + bool override_changed = false; + int diff_flags = flags; + if (!RNA_property_overridable_get(ptr_a, prop_a)) { + diff_flags &= ~RNA_OVERRIDE_COMPARE_CREATE; + } + const int diff = override_diff(bmain, + ptr_a, + ptr_b, + prop_a, + prop_b, + len_a, + len_b, + mode, + override, + rna_path, + diff_flags, + &override_changed); + if (override_changed && r_report_flags) { + *r_report_flags |= RNA_OVERRIDE_MATCH_RESULT_CREATED; + } + + return diff; +} + +/* Modify local data-block to make it ready for override application + * (only needed for diff operations, where we use + * the local data-block's data as second operand). */ +static bool rna_property_override_operation_store(Main *bmain, + PointerRNA *ptr_local, + PointerRNA *ptr_reference, + PointerRNA *ptr_storage, + PropertyRNA *prop_local, + PropertyRNA *prop_reference, + PropertyRNA *prop_storage, + IDOverrideLibraryProperty *op) +{ + int len_local, len_reference, len_storage = 0; + bool changed = false; + + if (ptr_storage == NULL) { + return changed; + } + + /* get the length of the array to work with */ + len_local = RNA_property_array_length(ptr_local, prop_local); + len_reference = RNA_property_array_length(ptr_reference, prop_reference); + if (prop_storage) { + len_storage = RNA_property_array_length(ptr_storage, prop_storage); + } + + if (len_local != len_reference || len_local != len_storage) { + /* Do not handle override in that case, + * we do not support insertion/deletion from arrays for now. */ + return changed; + } + + BLI_assert(prop_local->override_store == prop_reference->override_store && + (!ptr_storage || prop_local->override_store == prop_storage->override_store) && + prop_local->override_store != NULL); + + for (IDOverrideLibraryPropertyOperation *opop = op->operations.first; opop; opop = opop->next) { + /* Only needed for diff operations. */ + if (!ELEM(opop->operation, + IDOVERRIDE_LIBRARY_OP_ADD, + IDOVERRIDE_LIBRARY_OP_SUBTRACT, + IDOVERRIDE_LIBRARY_OP_MULTIPLY)) { + continue; + } + + if (prop_local->override_store(bmain, + ptr_local, + ptr_reference, + ptr_storage, + prop_local, + prop_reference, + prop_storage, + len_local, + len_reference, + len_storage, + opop)) { + changed = true; + } + } + + return changed; +} + +static bool rna_property_override_operation_apply(Main *bmain, + PointerRNA *ptr_dst, + PointerRNA *ptr_src, + PointerRNA *ptr_storage, + PropertyRNA *prop_dst, + PropertyRNA *prop_src, + PropertyRNA *prop_storage, + PointerRNA *ptr_item_dst, + PointerRNA *ptr_item_src, + PointerRNA *ptr_item_storage, + IDOverrideLibraryPropertyOperation *opop) +{ + int len_dst, len_src, len_storage = 0; + + const short override_op = opop->operation; + + if (override_op == IDOVERRIDE_LIBRARY_OP_NOOP) { + return true; + } + + if (ELEM(override_op, + IDOVERRIDE_LIBRARY_OP_ADD, + IDOVERRIDE_LIBRARY_OP_SUBTRACT, + IDOVERRIDE_LIBRARY_OP_MULTIPLY) && + !ptr_storage) { + /* We cannot apply 'diff' override operations without some reference storage. + * This should typically only happen at read time of .blend file... */ + return false; + } + + if (ELEM(override_op, + IDOVERRIDE_LIBRARY_OP_ADD, + IDOVERRIDE_LIBRARY_OP_SUBTRACT, + IDOVERRIDE_LIBRARY_OP_MULTIPLY) && + !prop_storage) { + /* We cannot apply 'diff' override operations without some reference storage. + * This should typically only happen at read time of .blend file... */ + return false; + } + + RNAPropOverrideApply override_apply = NULL; + /* Special case for IDProps, we use default callback then. */ + if (prop_dst->magic != RNA_MAGIC) { + override_apply = rna_property_override_apply_default; + if (prop_src->magic == RNA_MAGIC && prop_src->override_apply != override_apply) { + override_apply = NULL; + } + } + else if (prop_src->magic != RNA_MAGIC) { + override_apply = rna_property_override_apply_default; + if (prop_dst->override_apply != override_apply) { + override_apply = NULL; + } + } + else if (prop_dst->override_apply == prop_src->override_apply) { + override_apply = prop_dst->override_apply; + } + + if (ptr_storage && prop_storage->magic == RNA_MAGIC && + prop_storage->override_apply != override_apply) { + override_apply = NULL; + } + + if (override_apply == NULL) { +#ifndef NDEBUG + printf("'%s' gives unmatching or NULL RNA copy callbacks, should not happen (%d vs. %d).\n", + prop_dst->magic != RNA_MAGIC ? ((IDProperty *)prop_dst)->name : prop_dst->identifier, + prop_dst->magic == RNA_MAGIC, + prop_src->magic == RNA_MAGIC); +#endif + BLI_assert(0); + return false; + } + + /* get the length of the array to work with */ + len_dst = RNA_property_array_length(ptr_dst, prop_dst); + len_src = RNA_property_array_length(ptr_src, prop_src); + if (ptr_storage) { + len_storage = RNA_property_array_length(ptr_storage, prop_storage); + } + + if (len_dst != len_src || (ptr_storage && len_dst != len_storage)) { + /* Do not handle override in that case, + * we do not support insertion/deletion from arrays for now. */ + return false; + } + + /* get and set the default values as appropriate for the various types */ + return override_apply(bmain, + ptr_dst, + ptr_src, + ptr_storage, + prop_dst, + prop_src, + prop_storage, + len_dst, + len_src, + len_storage, + ptr_item_dst, + ptr_item_src, + ptr_item_storage, + opop); +} + +/** + * Check whether reference and local overridden data match (are the same), + * with respect to given restrictive sets of properties. + * If requested, will generate needed new property overrides, and/or restore values from reference. + * + * \param r_report_flags: If given, + * will be set with flags matching actions taken by the function on \a ptr_local. + * + * \return True if _resulting_ \a ptr_local does match \a ptr_reference. + */ +bool RNA_struct_override_matches(Main *bmain, + PointerRNA *ptr_local, + PointerRNA *ptr_reference, + const char *root_path, + IDOverrideLibrary *override, + const eRNAOverrideMatch flags, + eRNAOverrideMatchResult *r_report_flags) +{ + CollectionPropertyIterator iter; + PropertyRNA *iterprop; + bool matching = true; + + BLI_assert(ptr_local->type == ptr_reference->type); + BLI_assert(ptr_local->owner_id && ptr_reference->owner_id); + + const bool ignore_non_overridable = (flags & RNA_OVERRIDE_COMPARE_IGNORE_NON_OVERRIDABLE) != 0; + const bool ignore_overridden = (flags & RNA_OVERRIDE_COMPARE_IGNORE_OVERRIDDEN) != 0; + const bool do_create = (flags & RNA_OVERRIDE_COMPARE_CREATE) != 0; + const bool do_restore = (flags & RNA_OVERRIDE_COMPARE_RESTORE) != 0; + +//#define DEBUG_OVERRIDE_TIMEIT +#ifdef DEBUG_OVERRIDE_TIMEIT + static float _sum_time_global = 0.0f; + static float _num_time_global = 0.0f; + double _timeit_time_global; + static float _sum_time_diffing = 0.0f; + static float _delta_time_diffing = 0.0f; + static int _num_delta_time_diffing = 0.0f; + static float _num_time_diffing = 0.0f; + double _timeit_time_diffing; + + if (!root_path) { + _delta_time_diffing = 0.0f; + _num_delta_time_diffing = 0; + _timeit_time_global = PIL_check_seconds_timer(); + } +#endif + + iterprop = RNA_struct_iterator_property(ptr_local->type); + + for (RNA_property_collection_begin(ptr_local, iterprop, &iter); iter.valid; + RNA_property_collection_next(&iter)) { + PropertyRNA *prop_local = iter.ptr.data; + PropertyRNA *prop_reference = iter.ptr.data; + + /* Ensure we get real property data, be it an actual RNA property, + * or an IDProperty in disguise. */ + prop_local = rna_ensure_property_realdata(&prop_local, ptr_local); + prop_reference = rna_ensure_property_realdata(&prop_reference, ptr_reference); + + if (ELEM(NULL, prop_local, prop_reference)) { + continue; + } + + if (ignore_non_overridable && !RNA_property_overridable_get(ptr_local, prop_local)) { + continue; + } + +#if 0 /* This actually makes things slower, since it has to check for animation paths etc! */ + if (RNA_property_animated(ptr_local, prop_local)) { + /* We cannot do anything here really, animation is some kind of dynamic overrides that has + * precedence over static one... */ + continue; + } +#endif + +#define RNA_PATH_BUFFSIZE 8192 +#define RNA_PATH_PRINTF(_str, ...) \ + if (BLI_snprintf(rna_path, RNA_PATH_BUFFSIZE, (_str), __VA_ARGS__) >= RNA_PATH_BUFFSIZE) { \ + rna_path = BLI_sprintfN((_str), __VA_ARGS__); \ + } \ + (void)0 +#define RNA_PATH_FREE \ + if (rna_path != rna_path_buffer) \ + MEM_freeN(rna_path) + + char rna_path_buffer[RNA_PATH_BUFFSIZE]; + char *rna_path = rna_path_buffer; + + /* XXX TODO this will have to be refined to handle collections insertions, and array items */ + if (root_path) { + /* Inlined building, much much more efficient. */ + if (prop_local->magic == RNA_MAGIC) { + RNA_PATH_PRINTF("%s.%s", root_path, RNA_property_identifier(prop_local)); + } + else { + RNA_PATH_PRINTF("%s[\"%s\"]", root_path, RNA_property_identifier(prop_local)); + } + } + else { + /* This is rather slow, but is not much called, so not really worth optimizing. */ + rna_path = RNA_path_from_ID_to_property(ptr_local, prop_local); + } + if (rna_path == NULL) { + continue; + } + + // printf("Override Checking %s\n", rna_path); + + if (ignore_overridden && BKE_override_library_property_find(override, rna_path) != NULL) { + RNA_PATH_FREE; + continue; + } + +#ifdef DEBUG_OVERRIDE_TIMEIT + if (!root_path) { + _timeit_time_diffing = PIL_check_seconds_timer(); + } +#endif + + eRNAOverrideMatchResult report_flags = 0; + const int diff = rna_property_override_diff(bmain, + ptr_local, + ptr_reference, + NULL, + prop_local, + prop_reference, + rna_path, + RNA_EQ_STRICT, + override, + flags, + &report_flags); + +#ifdef DEBUG_OVERRIDE_TIMEIT + if (!root_path) { + const float _delta_time = (float)(PIL_check_seconds_timer() - _timeit_time_diffing); + _delta_time_diffing += _delta_time; + _num_delta_time_diffing++; + } +#endif + + matching = matching && diff == 0; + if (r_report_flags) { + *r_report_flags |= report_flags; + } + + if (diff != 0) { + /* XXX TODO: refine this for per-item overriding of arrays... */ + IDOverrideLibraryProperty *op = BKE_override_library_property_find(override, rna_path); + IDOverrideLibraryPropertyOperation *opop = op ? op->operations.first : NULL; + + if (do_restore && (report_flags & RNA_OVERRIDE_MATCH_RESULT_CREATED) == 0) { + /* We are allowed to restore to reference's values. */ + if (ELEM(NULL, op, opop) || opop->operation == IDOVERRIDE_LIBRARY_OP_NOOP) { + /* We should restore that property to its reference value */ + if (RNA_property_editable(ptr_local, prop_local)) { + IDOverrideLibraryPropertyOperation opop_tmp = { + .operation = IDOVERRIDE_LIBRARY_OP_REPLACE, + .subitem_reference_index = -1, + .subitem_local_index = -1, + }; + rna_property_override_operation_apply(bmain, + ptr_local, + ptr_reference, + NULL, + prop_local, + prop_reference, + NULL, + NULL, + NULL, + NULL, + &opop_tmp); + if (r_report_flags) { + *r_report_flags |= RNA_OVERRIDE_MATCH_RESULT_RESTORED; + } + } + else { + /* Too noisy for now, this triggers on runtime props like transform matrices etc. */ +#if 0 + BLI_assert(!"We have differences between reference and " + "overriding data on non-editable property."); +#endif + matching = false; + } + } + } + else if ((report_flags & RNA_OVERRIDE_MATCH_RESULT_CREATED) == 0 && ELEM(NULL, op, opop)) { + /* This property is not overridden, and differs from reference, so we have no match. */ + matching = false; + if (!(do_create || do_restore)) { + /* Since we have no 'changing' action allowed, we can break here. */ + MEM_SAFE_FREE(rna_path); + break; + } + } + } + + RNA_PATH_FREE; + +#undef RNA_PATH_BUFFSIZE +#undef RNA_PATH_PRINTF +#undef RNA_PATH_FREE + } + RNA_property_collection_end(&iter); + +#ifdef DEBUG_OVERRIDE_TIMEIT + if (!root_path) { + const float _delta_time = (float)(PIL_check_seconds_timer() - _timeit_time_global); + _sum_time_global += _delta_time; + _num_time_global++; + _sum_time_diffing += _delta_time_diffing; + _num_time_diffing++; + printf("ID: %s\n", ((ID *)ptr_local->owner_id)->name); + printf("time end (%s): %.6f\n", __func__, _delta_time); + printf("time averaged (%s): %.6f (total: %.6f, in %d runs)\n", + __func__, + (_sum_time_global / _num_time_global), + _sum_time_global, + (int)_num_time_global); + printf("diffing time end (%s): %.6f (in %d runs)\n", + __func__, + _delta_time_diffing, + _num_delta_time_diffing); + printf("diffing time averaged (%s): %.6f (total: %.6f, in %d runs)\n", + __func__, + (_sum_time_diffing / _num_time_diffing), + _sum_time_diffing, + (int)_num_time_diffing); + } +#endif + + return matching; +} + +/** Store needed second operands into \a storage data-block + * for differential override operations. */ +bool RNA_struct_override_store(Main *bmain, + PointerRNA *ptr_local, + PointerRNA *ptr_reference, + PointerRNA *ptr_storage, + IDOverrideLibrary *override) +{ + bool changed = false; + +#ifdef DEBUG_OVERRIDE_TIMEIT + TIMEIT_START_AVERAGED(RNA_struct_override_store); +#endif + for (IDOverrideLibraryProperty *op = override->properties.first; op; op = op->next) { + /* Simplified for now! */ + PointerRNA data_reference, data_local; + PropertyRNA *prop_reference, *prop_local; + + if (RNA_path_resolve_property(ptr_local, op->rna_path, &data_local, &prop_local) && + RNA_path_resolve_property(ptr_reference, op->rna_path, &data_reference, &prop_reference)) { + PointerRNA data_storage; + PropertyRNA *prop_storage = NULL; + + /* It is totally OK if this does not success, + * only a subset of override operations actually need storage. */ + if (ptr_storage && (ptr_storage->owner_id != NULL)) { + RNA_path_resolve_property(ptr_storage, op->rna_path, &data_storage, &prop_storage); + } + + if (rna_property_override_operation_store(bmain, + &data_local, + &data_reference, + &data_storage, + prop_reference, + prop_local, + prop_storage, + op)) { + changed = true; + } + } + } +#ifdef DEBUG_OVERRIDE_TIMEIT + TIMEIT_END_AVERAGED(RNA_struct_override_store); +#endif + + return changed; +} + +static void rna_property_override_apply_ex(Main *bmain, + PointerRNA *ptr_dst, + PointerRNA *ptr_src, + PointerRNA *ptr_storage, + PropertyRNA *prop_dst, + PropertyRNA *prop_src, + PropertyRNA *prop_storage, + PointerRNA *ptr_item_dst, + PointerRNA *ptr_item_src, + PointerRNA *ptr_item_storage, + IDOverrideLibraryProperty *op, + const bool do_insert) +{ + for (IDOverrideLibraryPropertyOperation *opop = op->operations.first; opop; opop = opop->next) { + if (!do_insert != !ELEM(opop->operation, + IDOVERRIDE_LIBRARY_OP_INSERT_AFTER, + IDOVERRIDE_LIBRARY_OP_INSERT_BEFORE)) { + if (!do_insert) { + printf("Skipping insert override operations in first pass (%s)!\n", op->rna_path); + } + continue; + } + + /* Note: will have to think about putting that logic into its own function maybe? + * Would be nice to have it in a single place... + * Note that here, src is the local saved ID, and dst is a copy of the linked ID (since we use + * local ID as storage to apply local changes on top of a clean copy of the linked data). */ + PointerRNA private_ptr_item_dst, private_ptr_item_src, private_ptr_item_storage; + if (opop->subitem_local_name != NULL || opop->subitem_reference_name != NULL || + opop->subitem_local_index != -1 || opop->subitem_reference_index != -1) { + RNA_POINTER_INVALIDATE(&private_ptr_item_dst); + RNA_POINTER_INVALIDATE(&private_ptr_item_src); + RNA_POINTER_INVALIDATE(&private_ptr_item_storage); + if (opop->subitem_local_name != NULL) { + RNA_property_collection_lookup_string( + ptr_src, prop_src, opop->subitem_local_name, &private_ptr_item_src); + if (opop->subitem_reference_name != NULL) { + RNA_property_collection_lookup_string( + ptr_dst, prop_dst, opop->subitem_reference_name, &private_ptr_item_dst); + } + else { + RNA_property_collection_lookup_string( + ptr_dst, prop_dst, opop->subitem_local_name, &private_ptr_item_dst); + } + } + else if (opop->subitem_reference_name != NULL) { + RNA_property_collection_lookup_string( + ptr_src, prop_src, opop->subitem_reference_name, &private_ptr_item_src); + RNA_property_collection_lookup_string( + ptr_dst, prop_dst, opop->subitem_reference_name, &private_ptr_item_dst); + } + else if (opop->subitem_local_index != -1) { + RNA_property_collection_lookup_int( + ptr_src, prop_src, opop->subitem_local_index, &private_ptr_item_src); + if (opop->subitem_reference_index != -1) { + RNA_property_collection_lookup_int( + ptr_dst, prop_dst, opop->subitem_reference_index, &private_ptr_item_dst); + } + else { + RNA_property_collection_lookup_int( + ptr_dst, prop_dst, opop->subitem_local_index, &private_ptr_item_dst); + } + } + else if (opop->subitem_reference_index != -1) { + RNA_property_collection_lookup_int( + ptr_src, prop_src, opop->subitem_reference_index, &private_ptr_item_src); + RNA_property_collection_lookup_int( + ptr_dst, prop_dst, opop->subitem_reference_index, &private_ptr_item_dst); + } + if (prop_storage != NULL) { + if (opop->subitem_local_name != NULL) { + RNA_property_collection_lookup_string( + ptr_storage, prop_storage, opop->subitem_local_name, &private_ptr_item_storage); + } + else if (opop->subitem_reference_name != NULL) { + RNA_property_collection_lookup_string( + ptr_storage, prop_storage, opop->subitem_reference_name, &private_ptr_item_storage); + } + else if (opop->subitem_local_index != -1) { + RNA_property_collection_lookup_int( + ptr_storage, prop_storage, opop->subitem_local_index, &private_ptr_item_storage); + } + else if (opop->subitem_reference_index != -1) { + RNA_property_collection_lookup_int( + ptr_storage, prop_storage, opop->subitem_reference_index, &private_ptr_item_storage); + } + } + ptr_item_dst = &private_ptr_item_dst; + ptr_item_src = &private_ptr_item_src; + ptr_item_storage = &private_ptr_item_storage; + } + + if (!rna_property_override_operation_apply(bmain, + ptr_dst, + ptr_src, + ptr_storage, + prop_dst, + prop_src, + prop_storage, + ptr_item_dst, + ptr_item_src, + ptr_item_storage, + opop)) { + /* TODO No assert here, would be much much better to just report as warning, + * failing override applications will probably be fairly common! */ + BLI_assert(0); + } + } +} + +/** Apply given \a override operations on \a ptr_dst, using \a ptr_src + * (and \a ptr_storage for differential ops) as source. */ +void RNA_struct_override_apply(Main *bmain, + PointerRNA *ptr_dst, + PointerRNA *ptr_src, + PointerRNA *ptr_storage, + IDOverrideLibrary *override) +{ +#ifdef DEBUG_OVERRIDE_TIMEIT + TIMEIT_START_AVERAGED(RNA_struct_override_apply); +#endif + /* Note: Applying insert operations in a separate pass is mandatory. + * We could optimize this later, but for now, as inefficient as it is, + * don't think this is a critical point. + */ + bool do_insert = false; + for (int i = 0; i < 2; i++, do_insert = true) { + for (IDOverrideLibraryProperty *op = override->properties.first; op; op = op->next) { + /* Simplified for now! */ + PointerRNA data_src, data_dst; + PointerRNA data_item_src, data_item_dst; + PropertyRNA *prop_src, *prop_dst; + + if (RNA_path_resolve_property_and_item_pointer( + ptr_dst, op->rna_path, &data_dst, &prop_dst, &data_item_dst) && + RNA_path_resolve_property_and_item_pointer( + ptr_src, op->rna_path, &data_src, &prop_src, &data_item_src)) { + PointerRNA data_storage, data_item_storage; + PropertyRNA *prop_storage = NULL; + + /* It is totally OK if this does not success, + * only a subset of override operations actually need storage. */ + if (ptr_storage && (ptr_storage->owner_id != NULL)) { + RNA_path_resolve_property_and_item_pointer( + ptr_storage, op->rna_path, &data_storage, &prop_storage, &data_item_storage); + } + + rna_property_override_apply_ex(bmain, + &data_dst, + &data_src, + prop_storage ? &data_storage : NULL, + prop_dst, + prop_src, + prop_storage, + &data_item_dst, + &data_item_src, + prop_storage ? &data_item_storage : NULL, + op, + do_insert); + } +#ifndef NDEBUG + else { + printf( + "Failed to apply library override operation to '%s.%s' " + "(could not resolve some properties, local: %d, override: %d)\n", + ((ID *)ptr_src->owner_id)->name, + op->rna_path, + RNA_path_resolve_property(ptr_dst, op->rna_path, &data_dst, &prop_dst), + RNA_path_resolve_property(ptr_src, op->rna_path, &data_src, &prop_src)); + } +#endif + } + } +#ifdef DEBUG_OVERRIDE_TIMEIT + TIMEIT_END_AVERAGED(RNA_struct_override_apply); +#endif +} + +IDOverrideLibraryProperty *RNA_property_override_property_find(PointerRNA *ptr, PropertyRNA *prop) +{ + ID *id = ptr->owner_id; + + if (!id || !id->override_library) { + return NULL; + } + + char *rna_path = RNA_path_from_ID_to_property(ptr, prop); + if (rna_path) { + IDOverrideLibraryProperty *op = BKE_override_library_property_find(id->override_library, + rna_path); + MEM_freeN(rna_path); + return op; + } + return NULL; +} + +IDOverrideLibraryProperty *RNA_property_override_property_get(PointerRNA *ptr, + PropertyRNA *prop, + bool *r_created) +{ + ID *id = ptr->owner_id; + + if (!id || !id->override_library) { + return NULL; + } + + char *rna_path = RNA_path_from_ID_to_property(ptr, prop); + if (rna_path) { + IDOverrideLibraryProperty *op = BKE_override_library_property_get( + id->override_library, rna_path, r_created); + MEM_freeN(rna_path); + return op; + } + return NULL; +} + +IDOverrideLibraryPropertyOperation *RNA_property_override_property_operation_find( + PointerRNA *ptr, PropertyRNA *prop, const int index, const bool strict, bool *r_strict) +{ + IDOverrideLibraryProperty *op = RNA_property_override_property_find(ptr, prop); + + if (!op) { + return NULL; + } + + return BKE_override_library_property_operation_find( + op, NULL, NULL, index, index, strict, r_strict); +} + +IDOverrideLibraryPropertyOperation *RNA_property_override_property_operation_get( + PointerRNA *ptr, + PropertyRNA *prop, + const short operation, + const int index, + const bool strict, + bool *r_strict, + bool *r_created) +{ + IDOverrideLibraryProperty *op = RNA_property_override_property_get(ptr, prop, NULL); + + if (!op) { + return NULL; + } + + return BKE_override_library_property_operation_get( + op, operation, NULL, NULL, index, index, strict, r_strict, r_created); +} + +eRNAOverrideStatus RNA_property_override_library_status(PointerRNA *ptr, + PropertyRNA *prop, + const int index) +{ + int override_status = 0; + + if (!BKE_override_library_is_enabled()) { + return override_status; + } + + if (!ptr || !prop || !ptr->owner_id || !(ptr->owner_id)->override_library) { + return override_status; + } + + if (RNA_property_overridable_get(ptr, prop) && RNA_property_editable_flag(ptr, prop)) { + override_status |= RNA_OVERRIDE_STATUS_OVERRIDABLE; + } + + IDOverrideLibraryPropertyOperation *opop = RNA_property_override_property_operation_find( + ptr, prop, index, false, NULL); + if (opop != NULL) { + override_status |= RNA_OVERRIDE_STATUS_OVERRIDDEN; + if (opop->flag & IDOVERRIDE_LIBRARY_FLAG_MANDATORY) { + override_status |= RNA_OVERRIDE_STATUS_MANDATORY; + } + if (opop->flag & IDOVERRIDE_LIBRARY_FLAG_LOCKED) { + override_status |= RNA_OVERRIDE_STATUS_LOCKED; + } + } + + return override_status; +} diff --git a/source/blender/makesrna/intern/rna_access_internal.h b/source/blender/makesrna/intern/rna_access_internal.h new file mode 100644 index 00000000000..28ec504e376 --- /dev/null +++ b/source/blender/makesrna/intern/rna_access_internal.h @@ -0,0 +1,34 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup RNA + */ + +#ifndef __RNA_ACCESS_INTERNAL_H__ +#define __RNA_ACCESS_INTERNAL_H__ + +#include "BLI_utildefines.h" + +#include "rna_internal_types.h" + +struct IDProperty; + +PropertyRNA *rna_ensure_property(PropertyRNA *prop); + +void rna_idproperty_touch(struct IDProperty *idprop); + +#endif /* __ACCESS_RNA_INTERNAL_H__ */ diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c index 4ad2aa55c75..24f8d5c4e3d 100644 --- a/source/blender/makesrna/intern/rna_action.c +++ b/source/blender/makesrna/intern/rna_action.c @@ -249,15 +249,15 @@ static void rna_Action_active_pose_marker_index_range( static void rna_Action_frame_range_get(PointerRNA *ptr, float *values) { /* don't include modifiers because they too easily can have very large * ranges: MINAFRAMEF to MAXFRAMEF. */ - calc_action_range(ptr->id.data, values, values + 1, false); + calc_action_range((bAction *)ptr->owner_id, values, values + 1, false); } /* Used to check if an action (value pointer) * is suitable to be assigned to the ID-block that is ptr. */ bool rna_Action_id_poll(PointerRNA *ptr, PointerRNA value) { - ID *srcId = (ID *)ptr->id.data; - bAction *act = (bAction *)value.id.data; + ID *srcId = ptr->owner_id; + bAction *act = (bAction *)value.owner_id; if (act) { /* there can still be actions that will have undefined id-root @@ -280,7 +280,7 @@ bool rna_Action_id_poll(PointerRNA *ptr, PointerRNA value) bool rna_Action_actedit_assign_poll(PointerRNA *ptr, PointerRNA value) { SpaceAction *saction = (SpaceAction *)ptr->data; - bAction *act = (bAction *)value.id.data; + bAction *act = (bAction *)value.owner_id; if (act) { /* there can still be actions that will have undefined id-root diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c index 3d14616bcc9..6157ec41f19 100644 --- a/source/blender/makesrna/intern/rna_animation.c +++ b/source/blender/makesrna/intern/rna_animation.c @@ -128,7 +128,7 @@ const EnumPropertyItem rna_enum_keying_flag_items_api[] = { static void rna_AnimData_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; ANIM_id_update(bmain, id); } @@ -157,7 +157,7 @@ static void rna_AnimData_action_set(PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) { - ID *ownerId = (ID *)ptr->id.data; + ID *ownerId = ptr->owner_id; /* set action */ BKE_animdata_set_action(NULL, ownerId, value.data); @@ -303,7 +303,7 @@ static StructRNA *rna_KeyingSetInfo_register(Main *bmain, { KeyingSetInfo dummyksi = {NULL}; KeyingSetInfo *ksi; - PointerRNA dummyptr = {{NULL}}; + PointerRNA dummyptr = {NULL}; int have_function[3]; /* setup dummy type info to store static properties in */ @@ -727,12 +727,12 @@ bool rna_AnimaData_override_apply(Main *UNUSED(bmain), if (adt_dst == NULL && adt_src != NULL) { /* Copy anim data from reference into final local ID. */ - BKE_animdata_copy_id(NULL, ptr_dst->id.data, ptr_src->id.data, 0); + BKE_animdata_copy_id(NULL, ptr_dst->owner_id, ptr_src->owner_id, 0); return true; } else if (adt_dst != NULL && adt_src == NULL) { /* Override has cleared/removed anim data from its reference. */ - BKE_animdata_free(ptr_dst->id.data, true); + BKE_animdata_free(ptr_dst->owner_id, true); return true; } diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c index 59e5c584811..7949db9055f 100644 --- a/source/blender/makesrna/intern/rna_armature.c +++ b/source/blender/makesrna/intern/rna_armature.c @@ -50,7 +50,7 @@ static void rna_Armature_update_data(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; DEG_id_tag_update(id, 0); WM_main_add_notifier(NC_GEOM | ND_DATA, id); @@ -59,7 +59,7 @@ static void rna_Armature_update_data(Main *UNUSED(bmain), Scene *UNUSED(scene), static void rna_Armature_dependency_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; DEG_relations_tag_update(bmain); @@ -73,12 +73,12 @@ static void rna_Armature_act_bone_set(PointerRNA *ptr, { bArmature *arm = (bArmature *)ptr->data; - if (value.id.data == NULL && value.data == NULL) { + if (value.owner_id == NULL && value.data == NULL) { arm->act_bone = NULL; } else { - if (value.id.data != arm) { - Object *ob = (Object *)value.id.data; + if (value.owner_id != &arm->id) { + Object *ob = (Object *)value.owner_id; if (GS(ob->id.name) != ID_OB || (ob->data != arm)) { printf("ERROR: armature set active bone - new active doesn't come from this armature\n"); @@ -97,11 +97,11 @@ static void rna_Armature_act_edit_bone_set(PointerRNA *ptr, { bArmature *arm = (bArmature *)ptr->data; - if (value.id.data == NULL && value.data == NULL) { + if (value.owner_id == NULL && value.data == NULL) { arm->act_edbone = NULL; } else { - if (value.id.data != arm) { + if (value.owner_id != &arm->id) { /* raise an error! */ } else { @@ -151,7 +151,7 @@ static void rna_Armature_edit_bone_remove(bArmature *arm, static void rna_Armature_update_layers(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - bArmature *arm = ptr->id.data; + bArmature *arm = (bArmature *)ptr->owner_id; Object *ob; /* proxy lib exception, store it here so we can restore layers on file @@ -168,7 +168,7 @@ static void rna_Armature_update_layers(Main *bmain, Scene *UNUSED(scene), Pointe static void rna_Armature_redraw_data(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; DEG_id_tag_update(id, ID_RECALC_COPY_ON_WRITE); WM_main_add_notifier(NC_GEOM | ND_DATA, id); @@ -177,7 +177,7 @@ static void rna_Armature_redraw_data(Main *UNUSED(bmain), Scene *UNUSED(scene), /* called whenever a bone is renamed */ static void rna_Bone_update_renamed(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; /* redraw view */ WM_main_add_notifier(NC_GEOM | ND_DATA, id); @@ -188,7 +188,7 @@ static void rna_Bone_update_renamed(Main *UNUSED(bmain), Scene *UNUSED(scene), P static void rna_Bone_select_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; /* 1) special updates for cases where rigs try to hook into armature drawing stuff * e.g. Mask Modifier - 'Armature' option @@ -225,7 +225,7 @@ static void rna_Bone_select_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Po static char *rna_Bone_path(PointerRNA *ptr) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; Bone *bone = (Bone *)ptr->data; char name_esc[sizeof(bone->name) * 2]; @@ -295,7 +295,7 @@ static void rna_bone_layer_set(int *layer, const bool *values) static void rna_Bone_layer_set(PointerRNA *ptr, const bool *values) { - bArmature *arm = (bArmature *)ptr->id.data; + bArmature *arm = (bArmature *)ptr->owner_id; Bone *bone = (Bone *)ptr->data; rna_bone_layer_set(&bone->layer, values); @@ -331,7 +331,7 @@ static void rna_Armature_layer_set(PointerRNA *ptr, const bool *values) static void rna_EditBone_name_set(PointerRNA *ptr, const char *value) { - bArmature *arm = (bArmature *)ptr->id.data; + bArmature *arm = (bArmature *)ptr->owner_id; EditBone *ebone = (EditBone *)ptr->data; char oldname[sizeof(ebone->name)], newname[sizeof(ebone->name)]; @@ -345,7 +345,7 @@ static void rna_EditBone_name_set(PointerRNA *ptr, const char *value) static void rna_Bone_name_set(PointerRNA *ptr, const char *value) { - bArmature *arm = (bArmature *)ptr->id.data; + bArmature *arm = (bArmature *)ptr->owner_id; Bone *bone = (Bone *)ptr->data; char oldname[sizeof(bone->name)], newname[sizeof(bone->name)]; @@ -417,7 +417,7 @@ static void rna_EditBone_parent_set(PointerRNA *ptr, } else { /* within same armature */ - if (value.id.data != ptr->id.data) { + if (value.owner_id != ptr->owner_id) { return; } @@ -451,7 +451,7 @@ static void rna_EditBone_matrix_set(PointerRNA *ptr, const float *values) static void rna_Bone_bbone_handle_update(Main *bmain, Scene *scene, PointerRNA *ptr) { - bArmature *arm = (bArmature *)ptr->id.data; + bArmature *arm = (bArmature *)ptr->owner_id; Bone *bone = (Bone *)ptr->data; /* Update all users of this armature after changing B-Bone handles. */ @@ -483,7 +483,7 @@ static void rna_EditBone_bbone_prev_set(PointerRNA *ptr, EditBone *hbone = (EditBone *)value.data; /* Within the same armature? */ - if (hbone == NULL || value.id.data == ptr->id.data) { + if (hbone == NULL || value.owner_id == ptr->owner_id) { ebone->bbone_prev = hbone; } } @@ -496,7 +496,7 @@ static void rna_Bone_bbone_prev_set(PointerRNA *ptr, Bone *hbone = (Bone *)value.data; /* Within the same armature? */ - if (hbone == NULL || value.id.data == ptr->id.data) { + if (hbone == NULL || value.owner_id == ptr->owner_id) { bone->bbone_prev = hbone; } } @@ -515,7 +515,7 @@ static void rna_EditBone_bbone_next_set(PointerRNA *ptr, EditBone *hbone = (EditBone *)value.data; /* Within the same armature? */ - if (hbone == NULL || value.id.data == ptr->id.data) { + if (hbone == NULL || value.owner_id == ptr->owner_id) { ebone->bbone_next = hbone; } } @@ -528,14 +528,14 @@ static void rna_Bone_bbone_next_set(PointerRNA *ptr, Bone *hbone = (Bone *)value.data; /* Within the same armature? */ - if (hbone == NULL || value.id.data == ptr->id.data) { + if (hbone == NULL || value.owner_id == ptr->owner_id) { bone->bbone_next = hbone; } } static void rna_Armature_editbone_transform_update(Main *bmain, Scene *scene, PointerRNA *ptr) { - bArmature *arm = (bArmature *)ptr->id.data; + bArmature *arm = (bArmature *)ptr->owner_id; EditBone *ebone = (EditBone *)ptr->data; EditBone *child; @@ -590,7 +590,7 @@ static int rna_Armature_bones_lookup_string(PointerRNA *ptr, const char *key, Po bArmature *arm = (bArmature *)ptr->data; Bone *bone = BKE_armature_find_bone_name(arm, key); if (bone) { - RNA_pointer_create(ptr->id.data, &RNA_Bone, bone, r_ptr); + RNA_pointer_create(ptr->owner_id, &RNA_Bone, bone, r_ptr); return true; } else { @@ -600,26 +600,29 @@ static int rna_Armature_bones_lookup_string(PointerRNA *ptr, const char *key, Po static bool rna_Armature_is_editmode_get(PointerRNA *ptr) { - bArmature *arm = (bArmature *)ptr->id.data; + bArmature *arm = (bArmature *)ptr->owner_id; return (arm->edbo != NULL); } -static void rna_Armature_transform(struct bArmature *arm, Main *bmain, float *mat) +static void rna_Armature_transform(bArmature *arm, float *mat) { - ED_armature_transform(bmain, arm, (float(*)[4])mat, true); + ED_armature_transform(arm, (const float(*)[4])mat, true); } #else /* Settings for curved bbone settings - * The posemode values get applied over the top of the editmode ones. */ -void rna_def_bone_curved_common(StructRNA *srna, bool is_posebone) +void rna_def_bone_curved_common(StructRNA *srna, bool is_posebone, bool is_editbone) { -# define RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone) \ +# define RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone, is_editbone) \ { \ if (is_posebone) { \ RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update"); \ } \ + else if (is_editbone) { \ + RNA_def_property_update(prop, 0, "rna_Armature_editbone_transform_update"); \ + } \ else { \ RNA_def_property_update(prop, 0, "rna_Armature_update_data"); \ } \ @@ -634,14 +637,14 @@ void rna_def_bone_curved_common(StructRNA *srna, bool is_posebone) RNA_def_property_ui_range(prop, -M_PI * 2, M_PI * 2, 10, 2); RNA_def_property_ui_text( prop, "Roll In", "Roll offset for the start of the B-Bone, adjusts twist"); - RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone); + RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone, is_editbone); prop = RNA_def_property(srna, "bbone_rollout", PROP_FLOAT, PROP_ANGLE); RNA_def_property_float_sdna(prop, NULL, "roll2"); RNA_def_property_ui_range(prop, -M_PI * 2, M_PI * 2, 10, 2); RNA_def_property_ui_text( prop, "Roll Out", "Roll offset for the end of the B-Bone, adjusts twist"); - RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone); + RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone, is_editbone); if (is_posebone == false) { prop = RNA_def_property(srna, "use_endroll_as_inroll", PROP_BOOLEAN, PROP_NONE); @@ -658,28 +661,28 @@ void rna_def_bone_curved_common(StructRNA *srna, bool is_posebone) RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); RNA_def_property_ui_text( prop, "In X", "X-axis handle offset for start of the B-Bone's curve, adjusts curvature"); - RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone); + RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone, is_editbone); prop = RNA_def_property(srna, "bbone_curveiny", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "curve_in_y"); RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); RNA_def_property_ui_text( prop, "In Y", "Y-axis handle offset for start of the B-Bone's curve, adjusts curvature"); - RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone); + RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone, is_editbone); prop = RNA_def_property(srna, "bbone_curveoutx", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "curve_out_x"); RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); RNA_def_property_ui_text( prop, "Out X", "X-axis handle offset for end of the B-Bone's curve, adjusts curvature"); - RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone); + RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone, is_editbone); prop = RNA_def_property(srna, "bbone_curveouty", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "curve_out_y"); RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); RNA_def_property_ui_text( prop, "Out Y", "Y-axis handle offset for end of the B-Bone's curve, adjusts curvature"); - RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone); + RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone, is_editbone); /* Ease In/Out */ prop = RNA_def_property(srna, "bbone_easein", PROP_FLOAT, PROP_NONE); @@ -687,14 +690,14 @@ void rna_def_bone_curved_common(StructRNA *srna, bool is_posebone) RNA_def_property_ui_range(prop, -5.0f, 5.0f, 1, 3); RNA_def_property_float_default(prop, 1.0f); RNA_def_property_ui_text(prop, "Ease In", "Length of first Bezier Handle (for B-Bones only)"); - RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone); + RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone, is_editbone); prop = RNA_def_property(srna, "bbone_easeout", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "ease2"); RNA_def_property_ui_range(prop, -5.0f, 5.0f, 1, 3); RNA_def_property_float_default(prop, 1.0f); RNA_def_property_ui_text(prop, "Ease Out", "Length of second Bezier Handle (for B-Bones only)"); - RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone); + RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone, is_editbone); /* Scale In/Out */ prop = RNA_def_property(srna, "bbone_scaleinx", PROP_FLOAT, PROP_NONE); @@ -706,7 +709,7 @@ void rna_def_bone_curved_common(StructRNA *srna, bool is_posebone) "Scale In X", "X-axis scale factor for start of the B-Bone, " "adjusts thickness (for tapering effects)"); - RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone); + RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone, is_editbone); prop = RNA_def_property(srna, "bbone_scaleiny", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "scale_in_y"); @@ -717,7 +720,7 @@ void rna_def_bone_curved_common(StructRNA *srna, bool is_posebone) "Scale In Y", "Y-axis scale factor for start of the B-Bone, " "adjusts thickness (for tapering effects)"); - RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone); + RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone, is_editbone); prop = RNA_def_property(srna, "bbone_scaleoutx", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "scale_out_x"); @@ -728,7 +731,7 @@ void rna_def_bone_curved_common(StructRNA *srna, bool is_posebone) "Scale Out X", "X-axis scale factor for end of the B-Bone, " "adjusts thickness (for tapering effects)"); - RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone); + RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone, is_editbone); prop = RNA_def_property(srna, "bbone_scaleouty", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "scale_out_y"); @@ -739,7 +742,7 @@ void rna_def_bone_curved_common(StructRNA *srna, bool is_posebone) "Scale Out Y", "Y-axis scale factor for end of the B-Bone, " "adjusts thickness (for tapering effects)"); - RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone); + RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone, is_editbone); # undef RNA_DEF_CURVEBONE_UPDATE } @@ -871,11 +874,16 @@ static void rna_def_bone_common(StructRNA *srna, int editbone) /* Number values */ /* envelope deform settings */ prop = RNA_def_property(srna, "envelope_distance", PROP_FLOAT, PROP_DISTANCE); + if (editbone) { + RNA_def_property_update(prop, 0, "rna_Armature_editbone_transform_update"); + } + else { + RNA_def_property_update(prop, 0, "rna_Armature_update_data"); + } RNA_def_property_float_sdna(prop, NULL, "dist"); RNA_def_property_range(prop, 0.0f, 1000.0f); RNA_def_property_ui_text( prop, "Envelope Deform Distance", "Bone deformation distance (for Envelope deform only)"); - RNA_def_property_update(prop, 0, "rna_Armature_update_data"); prop = RNA_def_property(srna, "envelope_weight", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "weight"); @@ -914,23 +922,38 @@ static void rna_def_bone_common(StructRNA *srna, int editbone) /* b-bones deform settings */ prop = RNA_def_property(srna, "bbone_segments", PROP_INT, PROP_NONE); + if (editbone) { + RNA_def_property_update(prop, 0, "rna_Armature_editbone_transform_update"); + } + else { + RNA_def_property_update(prop, 0, "rna_Armature_dependency_update"); + } RNA_def_property_int_sdna(prop, NULL, "segments"); RNA_def_property_range(prop, 1, 32); RNA_def_property_ui_text( prop, "B-Bone Segments", "Number of subdivisions of bone (for B-Bones only)"); - RNA_def_property_update(prop, 0, "rna_Armature_dependency_update"); prop = RNA_def_property(srna, "bbone_x", PROP_FLOAT, PROP_NONE); + if (editbone) { + RNA_def_property_update(prop, 0, "rna_Armature_editbone_transform_update"); + } + else { + RNA_def_property_update(prop, 0, "rna_Armature_update_data"); + } RNA_def_property_float_sdna(prop, NULL, "xwidth"); RNA_def_property_ui_range(prop, 0.0f, 1000.0f, 1, RNA_TRANSLATION_PREC_DEFAULT); RNA_def_property_ui_text(prop, "B-Bone Display X Width", "B-Bone X size"); - RNA_def_property_update(prop, 0, "rna_Armature_update_data"); prop = RNA_def_property(srna, "bbone_z", PROP_FLOAT, PROP_NONE); + if (editbone) { + RNA_def_property_update(prop, 0, "rna_Armature_editbone_transform_update"); + } + else { + RNA_def_property_update(prop, 0, "rna_Armature_update_data"); + } RNA_def_property_float_sdna(prop, NULL, "zwidth"); RNA_def_property_ui_range(prop, 0.0f, 1000.0f, 1, RNA_TRANSLATION_PREC_DEFAULT); RNA_def_property_ui_text(prop, "B-Bone Display Z Width", "B-Bone Z size"); - RNA_def_property_update(prop, 0, "rna_Armature_update_data"); prop = RNA_def_property(srna, "bbone_handle_type_start", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "bbone_prev_type"); @@ -1010,7 +1033,7 @@ static void rna_def_bone(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Children", "Bones which are children of this bone"); rna_def_bone_common(srna, 0); - rna_def_bone_curved_common(srna, 0); + rna_def_bone_curved_common(srna, false, false); /* XXX should we define this in PoseChannel wrapping code instead? * But PoseChannels directly get some of their flags from here... */ @@ -1133,7 +1156,7 @@ static void rna_def_edit_bone(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Armature_editbone_transform_update"); rna_def_bone_common(srna, 1); - rna_def_bone_curved_common(srna, 0); + rna_def_bone_curved_common(srna, false, true); prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_HIDDEN_A); @@ -1300,7 +1323,6 @@ static void rna_def_armature(BlenderRNA *brna) RNA_def_struct_sdna(srna, "bArmature"); func = RNA_def_function(srna, "transform", "rna_Armature_transform"); - RNA_def_function_flag(func, FUNC_USE_MAIN); RNA_def_function_ui_description(func, "Transform armature bones by a matrix"); parm = RNA_def_float_matrix(func, "matrix", 4, 4, NULL, 0.0f, 0.0f, "", "Matrix", 0.0f, 0.0f); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); diff --git a/source/blender/makesrna/intern/rna_boid.c b/source/blender/makesrna/intern/rna_boid.c index 8f30a7e0a98..722b7b12271 100644 --- a/source/blender/makesrna/intern/rna_boid.c +++ b/source/blender/makesrna/intern/rna_boid.c @@ -130,10 +130,10 @@ static void rna_Boids_reset(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRN psys->recalc = ID_RECALC_PSYS_RESET; - DEG_id_tag_update(ptr->id.data, ID_RECALC_GEOMETRY); + DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY); } else { - DEG_id_tag_update(ptr->id.data, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET); + DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET); } WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, NULL); @@ -145,10 +145,10 @@ static void rna_Boids_reset_deps(Main *bmain, Scene *UNUSED(scene), PointerRNA * psys->recalc = ID_RECALC_PSYS_RESET; - DEG_id_tag_update(ptr->id.data, ID_RECALC_GEOMETRY); + DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY); } else { - DEG_id_tag_update(ptr->id.data, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET); + DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET); } DEG_relations_tag_update(bmain); @@ -240,7 +240,7 @@ static void rna_BoidState_active_boid_rule_index_set(struct PointerRNA *ptr, int static int particle_id_check(PointerRNA *ptr) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; return (GS(id->name) == ID_PA); } @@ -250,7 +250,7 @@ static char *rna_BoidSettings_path(PointerRNA *ptr) BoidSettings *boids = (BoidSettings *)ptr->data; if (particle_id_check(ptr)) { - ParticleSettings *part = (ParticleSettings *)ptr->id.data; + ParticleSettings *part = (ParticleSettings *)ptr->owner_id; if (part->boids == boids) { return BLI_strdup("boids"); diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index 713ddfa0067..14aa9c5d8cf 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -434,27 +434,27 @@ static bool rna_BrushCapabilitiesImagePaint_has_radius_get(PointerRNA *ptr) static PointerRNA rna_Sculpt_tool_capabilities_get(PointerRNA *ptr) { - return rna_pointer_inherit_refine(ptr, &RNA_BrushCapabilitiesSculpt, ptr->id.data); + return rna_pointer_inherit_refine(ptr, &RNA_BrushCapabilitiesSculpt, ptr->owner_id); } static PointerRNA rna_Imapaint_tool_capabilities_get(PointerRNA *ptr) { - return rna_pointer_inherit_refine(ptr, &RNA_BrushCapabilitiesImagePaint, ptr->id.data); + return rna_pointer_inherit_refine(ptr, &RNA_BrushCapabilitiesImagePaint, ptr->owner_id); } static PointerRNA rna_Vertexpaint_tool_capabilities_get(PointerRNA *ptr) { - return rna_pointer_inherit_refine(ptr, &RNA_BrushCapabilitiesVertexPaint, ptr->id.data); + return rna_pointer_inherit_refine(ptr, &RNA_BrushCapabilitiesVertexPaint, ptr->owner_id); } static PointerRNA rna_Weightpaint_tool_capabilities_get(PointerRNA *ptr) { - return rna_pointer_inherit_refine(ptr, &RNA_BrushCapabilitiesWeightPaint, ptr->id.data); + return rna_pointer_inherit_refine(ptr, &RNA_BrushCapabilitiesWeightPaint, ptr->owner_id); } static PointerRNA rna_Brush_capabilities_get(PointerRNA *ptr) { - return rna_pointer_inherit_refine(ptr, &RNA_BrushCapabilities, ptr->id.data); + return rna_pointer_inherit_refine(ptr, &RNA_BrushCapabilities, ptr->owner_id); } static void rna_Brush_reset_icon(Brush *br) @@ -764,7 +764,7 @@ static void rna_BrushGpencilSettings_use_material_pin_update(bContext *C, Pointe { ViewLayer *view_layer = CTX_data_view_layer(C); Object *ob = OBACT(view_layer); - Brush *brush = ptr->id.data; + Brush *brush = (Brush *)ptr->owner_id; if (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED) { Material *material = give_current_material(ob, ob->actcol); @@ -1571,6 +1571,16 @@ static void rna_def_brush(BlenderRNA *brna) {0, NULL, 0, NULL, NULL}, }; + static const EnumPropertyItem brush_spacing_unit_items[] = { + {0, "VIEW", 0, "View", "Calculate brush spacing relative to the view"}, + {BRUSH_SCENE_SPACING, + "SCENE", + 0, + "Scene", + "Calculate brush spacing relative to the scene using the stroke location"}, + {0, NULL, 0, NULL, NULL}, + }; + static const EnumPropertyItem brush_curve_preset_items[] = { {BRUSH_CURVE_CUSTOM, "CUSTOM", ICON_RNDCURVE, "Custom", ""}, {BRUSH_CURVE_SMOOTH, "SMOOTH", ICON_SMOOTHCURVE, "Smooth", ""}, @@ -1835,6 +1845,17 @@ static void rna_def_brush(BlenderRNA *brna) "Best used on low-poly meshes as it has a performance impact"); RNA_def_property_update(prop, 0, "rna_Brush_update"); + prop = RNA_def_property(srna, "normal_radius_factor", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "normal_radius_factor"); + RNA_def_property_float_default(prop, 0.5f); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.001, 3); + RNA_def_property_ui_text(prop, + "Normal Radius", + "Ratio between the brush radius and the radius that is going to be " + "used to sample the normal"); + RNA_def_property_update(prop, 0, "rna_Brush_update"); + prop = RNA_def_property(srna, "stencil_pos", PROP_FLOAT, PROP_XYZ); RNA_def_property_float_sdna(prop, NULL, "stencil_pos"); RNA_def_property_array(prop, 2); @@ -1920,6 +1941,13 @@ static void rna_def_brush(BlenderRNA *brna) "When locked keep using normal of surface where stroke was initiated"); RNA_def_property_update(prop, 0, "rna_Brush_update"); + prop = RNA_def_property(srna, "use_scene_spacing", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); + RNA_def_property_enum_items(prop, brush_spacing_unit_items); + RNA_def_property_ui_text( + prop, "Spacing distance", "Calculate the brush spacing using view or scene distance"); + RNA_def_property_update(prop, 0, "rna_Brush_update"); + prop = RNA_def_property(srna, "use_pressure_strength", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_ALPHA_PRESSURE); RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c index bb236fc3ef4..88083f600f8 100644 --- a/source/blender/makesrna/intern/rna_camera.c +++ b/source/blender/makesrna/intern/rna_camera.c @@ -43,52 +43,52 @@ static float rna_Camera_angle_get(PointerRNA *ptr) { - Camera *cam = ptr->id.data; + Camera *cam = (Camera *)ptr->owner_id; float sensor = BKE_camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y); return focallength_to_fov(cam->lens, sensor); } static void rna_Camera_angle_set(PointerRNA *ptr, float value) { - Camera *cam = ptr->id.data; + Camera *cam = (Camera *)ptr->owner_id; float sensor = BKE_camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y); cam->lens = fov_to_focallength(value, sensor); } static float rna_Camera_angle_x_get(PointerRNA *ptr) { - Camera *cam = ptr->id.data; + Camera *cam = (Camera *)ptr->owner_id; return focallength_to_fov(cam->lens, cam->sensor_x); } static void rna_Camera_angle_x_set(PointerRNA *ptr, float value) { - Camera *cam = ptr->id.data; + Camera *cam = (Camera *)ptr->owner_id; cam->lens = fov_to_focallength(value, cam->sensor_x); } static float rna_Camera_angle_y_get(PointerRNA *ptr) { - Camera *cam = ptr->id.data; + Camera *cam = (Camera *)ptr->owner_id; return focallength_to_fov(cam->lens, cam->sensor_y); } static void rna_Camera_angle_y_set(PointerRNA *ptr, float value) { - Camera *cam = ptr->id.data; + Camera *cam = (Camera *)ptr->owner_id; cam->lens = fov_to_focallength(value, cam->sensor_y); } static void rna_Camera_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Camera *camera = (Camera *)ptr->id.data; + Camera *camera = (Camera *)ptr->owner_id; DEG_id_tag_update(&camera->id, 0); } static void rna_Camera_dependency_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - Camera *camera = (Camera *)ptr->id.data; + Camera *camera = (Camera *)ptr->owner_id; DEG_relations_tag_update(bmain); DEG_id_tag_update(&camera->id, 0); } @@ -136,8 +136,8 @@ char *rna_CameraDOFSettings_path(PointerRNA *ptr) * since the name used is the name of the texture assigned, but the texture * may be used multiple times in the same stack */ - if (ptr->id.data) { - if (GS(((ID *)ptr->id.data)->name) == ID_CA) { + if (ptr->owner_id) { + if (GS(ptr->owner_id->name) == ID_CA) { return BLI_strdup("dof"); } } @@ -203,12 +203,14 @@ static void rna_def_camera_background_image(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "ima"); RNA_def_property_ui_text(prop, "Image", "Image displayed and edited in this space"); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); prop = RNA_def_property(srna, "clip", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "clip"); RNA_def_property_ui_text(prop, "MovieClip", "Movie clip displayed and edited in this space"); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); prop = RNA_def_property(srna, "image_user", PROP_POINTER, PROP_NONE); @@ -428,6 +430,7 @@ static void rna_def_camera_dof_settings_data(BlenderRNA *brna) RNA_def_property_struct_type(prop, "Object"); RNA_def_property_pointer_sdna(prop, NULL, "focus_object"); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text( prop, "Focus Object", "Use this object to define the depth of field focal point"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_dependency_update"); diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c index 548ed656d7b..036aeebda52 100644 --- a/source/blender/makesrna/intern/rna_cloth.c +++ b/source/blender/makesrna/intern/rna_cloth.c @@ -45,7 +45,7 @@ static void rna_cloth_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob); @@ -59,7 +59,7 @@ static void rna_cloth_dependency_update(Main *bmain, Scene *scene, PointerRNA *p static void rna_cloth_pinning_changed(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; /* ClothSimSettings *settings = (ClothSimSettings *)ptr->data; */ ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); @@ -311,7 +311,7 @@ static void rna_CollSettings_selfcol_vgroup_set(PointerRNA *ptr, const char *val static PointerRNA rna_ClothSettings_rest_shape_key_get(PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; ClothSimSettings *sim = (ClothSimSettings *)ptr->data; return rna_object_shapekey_index_get(ob->data, sim->shapekey_rest); @@ -321,7 +321,7 @@ static void rna_ClothSettings_rest_shape_key_set(PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; ClothSimSettings *sim = (ClothSimSettings *)ptr->data; sim->shapekey_rest = rna_object_shapekey_index_set(ob->data, value, sim->shapekey_rest); @@ -347,7 +347,7 @@ static void rna_ClothSettings_gravity_set(PointerRNA *ptr, const float *values) static char *rna_ClothSettings_path(PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth); if (md) { @@ -362,7 +362,7 @@ static char *rna_ClothSettings_path(PointerRNA *ptr) static char *rna_ClothCollisionSettings_path(PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth); if (md) { @@ -891,6 +891,7 @@ static void rna_def_cloth_collision_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "collection", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "group"); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Collision Collection", "Limit colliders to this Collection"); RNA_def_property_update(prop, 0, "rna_cloth_dependency_update"); diff --git a/source/blender/makesrna/intern/rna_collection.c b/source/blender/makesrna/intern/rna_collection.c index 12fdebbb8ca..e1c29dc906e 100644 --- a/source/blender/makesrna/intern/rna_collection.c +++ b/source/blender/makesrna/intern/rna_collection.c @@ -130,11 +130,11 @@ static bool rna_Collection_objects_override_apply(Main *bmain, PointerRNA *UNUSED(ptr_item_storage), IDOverrideLibraryPropertyOperation *opop) { - (void)opop; BLI_assert(opop->operation == IDOVERRIDE_LIBRARY_OP_REPLACE && "Unsupported RNA override operation on collections' objects"); + UNUSED_VARS_NDEBUG(opop); - Collection *coll_dst = ptr_dst->id.data; + Collection *coll_dst = (Collection *)ptr_dst->owner_id; if (ptr_item_dst->type == NULL || ptr_item_src->type == NULL) { BLI_assert(0 && "invalid source or destination object."); @@ -233,11 +233,11 @@ static bool rna_Collection_children_override_apply(Main *bmain, PointerRNA *UNUSED(ptr_item_storage), IDOverrideLibraryPropertyOperation *opop) { - (void)opop; BLI_assert(opop->operation == IDOVERRIDE_LIBRARY_OP_REPLACE && - "Unsupported RNA override operation on collections' objects"); + "Unsupported RNA override operation on collections' children"); + UNUSED_VARS_NDEBUG(opop); - Collection *coll_dst = ptr_dst->id.data; + Collection *coll_dst = (Collection *)ptr_dst->owner_id; if (ptr_item_dst->type == NULL || ptr_item_src->type == NULL) { BLI_assert(0 && "invalid source or destination sub-collection."); @@ -482,6 +482,7 @@ void RNA_def_collections(BlenderRNA *brna) RNA_def_property_struct_type(prop, "Object"); RNA_def_property_ui_text( prop, "All Objects", "Objects that are in this collection and its child collections"); + RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON); RNA_def_property_collection_funcs(prop, "rna_Collection_all_objects_begin", "rna_iterator_listbase_next", diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index 6bfd2b9f63b..011e373cc61 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -164,8 +164,8 @@ static char *rna_ColorRamp_path(PointerRNA *ptr) char *path = NULL; /* handle the cases where a single data-block may have 2 ramp types */ - if (ptr->id.data) { - ID *id = ptr->id.data; + if (ptr->owner_id) { + ID *id = ptr->owner_id; switch (GS(id->name)) { case ID_NT: { @@ -237,8 +237,8 @@ static char *rna_ColorRampElement_path(PointerRNA *ptr) /* determine the path from the ID-block to the ramp */ /* FIXME: this is a very slow way to do it, but it will have to suffice... */ - if (ptr->id.data) { - ID *id = ptr->id.data; + if (ptr->owner_id) { + ID *id = ptr->owner_id; switch (GS(id->name)) { case ID_NT: { @@ -286,12 +286,12 @@ static char *rna_ColorRampElement_path(PointerRNA *ptr) static void rna_ColorRamp_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - if (ptr->id.data) { - ID *id = ptr->id.data; + if (ptr->owner_id) { + ID *id = ptr->owner_id; switch (GS(id->name)) { case ID_MA: { - Material *ma = ptr->id.data; + Material *ma = (Material *)ptr->owner_id; DEG_id_tag_update(&ma->id, 0); WM_main_add_notifier(NC_MATERIAL | ND_SHADING_DRAW, ma); @@ -309,20 +309,20 @@ static void rna_ColorRamp_update(Main *bmain, Scene *UNUSED(scene), PointerRNA * break; } case ID_TE: { - Tex *tex = ptr->id.data; + Tex *tex = (Tex *)ptr->owner_id; DEG_id_tag_update(&tex->id, 0); WM_main_add_notifier(NC_TEXTURE, tex); break; } case ID_LS: { - FreestyleLineStyle *linestyle = ptr->id.data; + FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->owner_id; WM_main_add_notifier(NC_LINESTYLE, linestyle); break; } case ID_PA: { - ParticleSettings *part = ptr->id.data; + ParticleSettings *part = (ParticleSettings *)ptr->owner_id; DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_REDO); WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, part); @@ -417,7 +417,7 @@ static void rna_ColorManagedDisplaySettings_display_device_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; if (!id) { return; @@ -582,7 +582,7 @@ static void rna_ColorManagedColorspaceSettings_reload_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; if (GS(id->name) == ID_IM) { Image *ima = (Image *)id; @@ -657,7 +657,7 @@ static char *rna_ColorManagedInputColorspaceSettings_path(PointerRNA *UNUSED(ptr static void rna_ColorManagement_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; if (!id) { return; diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 6e57d16df27..05154dcc20e 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -256,6 +256,17 @@ static const EnumPropertyItem track_axis_items[] = { {0, NULL, 0, NULL, NULL}, }; +static const EnumPropertyItem euler_order_items[] = { + {CONSTRAINT_EULER_AUTO, "AUTO", 0, "Default", "Euler using the default rotation order"}, + {CONSTRAINT_EULER_XYZ, "XYZ", 0, "XYZ Euler", "Euler using the XYZ rotation order"}, + {CONSTRAINT_EULER_XZY, "XZY", 0, "XZY Euler", "Euler using the XZY rotation order"}, + {CONSTRAINT_EULER_YXZ, "YXZ", 0, "YXZ Euler", "Euler using the YXZ rotation order"}, + {CONSTRAINT_EULER_YZX, "YZX", 0, "YZX Euler", "Euler using the YZX rotation order"}, + {CONSTRAINT_EULER_ZXY, "ZXY", 0, "ZXY Euler", "Euler using the ZXY rotation order"}, + {CONSTRAINT_EULER_ZYX, "ZYX", 0, "ZYX Euler", "Euler using the ZYX rotation order"}, + {0, NULL, 0, NULL, NULL}, +}; + #ifdef RNA_RUNTIME static const EnumPropertyItem space_object_items[] = { @@ -376,8 +387,8 @@ static void rna_Constraint_name_set(PointerRNA *ptr, const char *value) BLI_strncpy_utf8(con->name, value, sizeof(con->name)); /* make sure name is unique */ - if (ptr->id.data) { - Object *ob = ptr->id.data; + if (ptr->owner_id) { + Object *ob = (Object *)ptr->owner_id; ListBase *list = get_constraint_lb(ob, con, NULL); /* if we have the list, check for unique name, otherwise give up */ @@ -418,7 +429,7 @@ static char *rna_Constraint_do_compute_path(Object *ob, bConstraint *con) static char *rna_Constraint_path(PointerRNA *ptr) { - Object *ob = ptr->id.data; + Object *ob = (Object *)ptr->owner_id; bConstraint *con = ptr->data; return rna_Constraint_do_compute_path(ob, con); @@ -426,7 +437,7 @@ static char *rna_Constraint_path(PointerRNA *ptr) static bConstraint *rna_constraint_from_target(PointerRNA *ptr) { - Object *ob = ptr->id.data; + Object *ob = (Object *)ptr->owner_id; bConstraintTarget *tgt = ptr->data; return BKE_constraint_find_from_target(ob, tgt, NULL); @@ -434,7 +445,7 @@ static bConstraint *rna_constraint_from_target(PointerRNA *ptr) static char *rna_ConstraintTarget_path(PointerRNA *ptr) { - Object *ob = ptr->id.data; + Object *ob = (Object *)ptr->owner_id; bConstraintTarget *tgt = ptr->data; bConstraint *con = rna_constraint_from_target(ptr); int index = -1; @@ -469,29 +480,30 @@ static char *rna_ConstraintTarget_path(PointerRNA *ptr) static void rna_Constraint_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - ED_object_constraint_tag_update(bmain, ptr->id.data, ptr->data); + ED_object_constraint_tag_update(bmain, (Object *)ptr->owner_id, ptr->data); } static void rna_Constraint_dependency_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - ED_object_constraint_dependency_tag_update(bmain, ptr->id.data, ptr->data); + ED_object_constraint_dependency_tag_update(bmain, (Object *)ptr->owner_id, ptr->data); } static void rna_ConstraintTarget_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - ED_object_constraint_tag_update(bmain, ptr->id.data, rna_constraint_from_target(ptr)); + ED_object_constraint_tag_update(bmain, (Object *)ptr->owner_id, rna_constraint_from_target(ptr)); } static void rna_ConstraintTarget_dependency_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - ED_object_constraint_dependency_tag_update(bmain, ptr->id.data, rna_constraint_from_target(ptr)); + ED_object_constraint_dependency_tag_update( + bmain, (Object *)ptr->owner_id, rna_constraint_from_target(ptr)); } static void rna_Constraint_influence_update(Main *bmain, Scene *scene, PointerRNA *ptr) { - Object *ob = ptr->id.data; + Object *ob = (Object *)ptr->owner_id; if (ob->pose) { ob->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK); @@ -523,7 +535,7 @@ static const EnumPropertyItem *rna_Constraint_owner_space_itemf(bContext *UNUSED PropertyRNA *UNUSED(prop), bool *UNUSED(r_free)) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; bConstraint *con = (bConstraint *)ptr->data; if (BLI_findindex(&ob->constraints, con) == -1) { @@ -671,7 +683,7 @@ static bool rna_Constraint_cameraObject_poll(PointerRNA *ptr, PointerRNA value) Object *ob = (Object *)value.data; if (ob) { - if (ob->type == OB_CAMERA && ob != (Object *)ptr->id.data) { + if (ob->type == OB_CAMERA && ob != (Object *)ptr->owner_id) { return 1; } } @@ -688,7 +700,7 @@ static void rna_Constraint_followTrack_camera_set(PointerRNA *ptr, Object *ob = (Object *)value.data; if (ob) { - if (ob->type == OB_CAMERA && ob != (Object *)ptr->id.data) { + if (ob->type == OB_CAMERA && ob != (Object *)ptr->owner_id) { data->camera = ob; id_lib_extern((ID *)ob); } @@ -707,7 +719,7 @@ static void rna_Constraint_followTrack_depthObject_set(PointerRNA *ptr, Object *ob = (Object *)value.data; if (ob) { - if (ob->type == OB_MESH && ob != (Object *)ptr->id.data) { + if (ob->type == OB_MESH && ob != (Object *)ptr->owner_id) { data->depth_ob = ob; id_lib_extern((ID *)ob); } @@ -722,7 +734,7 @@ static bool rna_Constraint_followTrack_depthObject_poll(PointerRNA *ptr, Pointer Object *ob = (Object *)value.data; if (ob) { - if (ob->type == OB_MESH && ob != (Object *)ptr->id.data) { + if (ob->type == OB_MESH && ob != (Object *)ptr->owner_id) { return 1; } } @@ -739,7 +751,7 @@ static void rna_Constraint_objectSolver_camera_set(PointerRNA *ptr, Object *ob = (Object *)value.data; if (ob) { - if (ob->type == OB_CAMERA && ob != (Object *)ptr->id.data) { + if (ob->type == OB_CAMERA && ob != (Object *)ptr->owner_id) { data->camera = ob; id_lib_extern((ID *)ob); } @@ -1009,7 +1021,7 @@ static void rna_def_constraint_armature_deform(BlenderRNA *brna) RNA_def_struct_ui_text( srna, "Armature Constraint", "Applies transformations done by the Armature modifier"); RNA_def_struct_sdna_from(srna, "bArmatureConstraint", "data"); - RNA_def_struct_ui_icon(srna, ICON_MOD_ARMATURE); + RNA_def_struct_ui_icon(srna, ICON_CON_ARMATURE); prop = RNA_def_property(srna, "targets", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "targets", NULL); @@ -1323,6 +1335,12 @@ static void rna_def_constraint_rotate_like(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Invert Z", "Invert the Z rotation"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + prop = RNA_def_property(srna, "euler_order", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "euler_order"); + RNA_def_property_enum_items(prop, euler_order_items); + RNA_def_property_ui_text(prop, "Euler Order", "Explicitly specify the euler rotation order"); + RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + prop = RNA_def_property(srna, "use_offset", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", ROTLIKE_OFFSET); RNA_def_property_ui_text(prop, "Offset", "Add original rotation into copied rotation"); @@ -1363,6 +1381,14 @@ static void rna_def_constraint_size_like(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Power", "Raise the target's scale to the specified power"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + prop = RNA_def_property(srna, "use_make_uniform", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SIZELIKE_UNIFORM); + RNA_def_property_ui_text(prop, + "Make Uniform", + "Redistribute the copied change in volume equally " + "between the three axes of the owner"); + RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + prop = RNA_def_property(srna, "use_offset", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SIZELIKE_OFFSET); RNA_def_property_ui_text(prop, "Offset", "Combine original scale with copied scale"); @@ -1876,6 +1902,18 @@ static void rna_def_constraint_transform(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Extrapolate Motion", "Extrapolate ranges"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + prop = RNA_def_property(srna, "from_rotation_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "from_rotation_mode"); + RNA_def_property_enum_items(prop, rna_enum_driver_target_rotation_mode_items); + RNA_def_property_ui_text(prop, "From Mode", "Specify the type of rotation channels to use"); + RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + prop = RNA_def_property(srna, "to_euler_order", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "to_euler_order"); + RNA_def_property_enum_items(prop, euler_order_items); + RNA_def_property_ui_text(prop, "To Order", "Explicitly specify the output euler rotation order"); + RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + /* Loc */ prop = RNA_def_property(srna, "from_min_x", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "from_min[0]"); @@ -3026,6 +3064,7 @@ void RNA_def_constraint(BlenderRNA *brna) RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Disable", "Enable/Disable Constraint"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + RNA_def_property_ui_icon(prop, ICON_HIDE_OFF, -1); prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE); RNA_def_property_flag(prop, PROP_NO_DEG_UPDATE); diff --git a/source/blender/makesrna/intern/rna_context.c b/source/blender/makesrna/intern/rna_context.c index 735cd1fd923..579dd92b703 100644 --- a/source/blender/makesrna/intern/rna_context.c +++ b/source/blender/makesrna/intern/rna_context.c @@ -178,14 +178,14 @@ static PointerRNA rna_Context_collection_get(PointerRNA *ptr) static PointerRNA rna_Context_layer_collection_get(PointerRNA *ptr) { bContext *C = (bContext *)ptr->data; - ptr->id.data = CTX_data_scene(C); + ptr->owner_id = &CTX_data_scene(C)->id; return rna_pointer_inherit_refine(ptr, &RNA_LayerCollection, CTX_data_layer_collection(C)); } static PointerRNA rna_Context_tool_settings_get(PointerRNA *ptr) { bContext *C = (bContext *)ptr->data; - ptr->id.data = CTX_data_scene(C); + ptr->owner_id = &CTX_data_scene(C)->id; return rna_pointer_inherit_refine(ptr, &RNA_ToolSettings, CTX_data_tool_settings(C)); } diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c index 644d0b712a2..a7dac4100db 100644 --- a/source/blender/makesrna/intern/rna_curve.c +++ b/source/blender/makesrna/intern/rna_curve.c @@ -326,7 +326,7 @@ static void rna_Curve_texspace_size_set(PointerRNA *ptr, const float *values) static void rna_Curve_material_index_range( PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax)) { - Curve *cu = (Curve *)ptr->id.data; + Curve *cu = (Curve *)ptr->owner_id; *min = 0; *max = max_ii(0, cu->totcol - 1); } @@ -347,14 +347,14 @@ static void rna_ChariInfo_material_index_set(PointerRNA *ptr, int value) static void rna_Curve_active_textbox_index_range( PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax)) { - Curve *cu = (Curve *)ptr->id.data; + Curve *cu = (Curve *)ptr->owner_id; *min = 0; *max = max_ii(0, cu->totbox - 1); } static void rna_Curve_dimension_set(PointerRNA *ptr, int value) { - Curve *cu = (Curve *)ptr->id.data; + Curve *cu = (Curve *)ptr->owner_id; if (value == CU_3D) { cu->flag |= CU_3D; } @@ -370,7 +370,7 @@ static const EnumPropertyItem *rna_Curve_fill_mode_itemf(bContext *UNUSED(C), PropertyRNA *UNUSED(prop), bool *UNUSED(r_free)) { - Curve *cu = (Curve *)ptr->id.data; + Curve *cu = (Curve *)ptr->owner_id; /* cast to quiet warning it IS a const still */ return (EnumPropertyItem *)((cu->flag & CU_3D) ? curve3d_fill_mode_items : @@ -388,7 +388,7 @@ static int rna_Nurb_length(PointerRNA *ptr) static void rna_Nurb_type_set(PointerRNA *ptr, int value) { - Curve *cu = (Curve *)ptr->id.data; + Curve *cu = (Curve *)ptr->owner_id; Nurb *nu = (Nurb *)ptr->data; const int pntsu_prev = nu->pntsu; @@ -418,7 +418,7 @@ static void rna_Curve_update_data_id(Main *UNUSED(bmain), Scene *UNUSED(scene), static void rna_Curve_update_data(Main *bmain, Scene *scene, PointerRNA *ptr) { - rna_Curve_update_data_id(bmain, scene, ptr->id.data); + rna_Curve_update_data_id(bmain, scene, ptr->owner_id); } static void rna_Curve_update_deps(Main *bmain, Scene *scene, PointerRNA *ptr) @@ -429,7 +429,7 @@ static void rna_Curve_update_deps(Main *bmain, Scene *scene, PointerRNA *ptr) static void rna_Curve_update_points(Main *bmain, Scene *scene, PointerRNA *ptr) { - Curve *cu = (Curve *)ptr->id.data; + Curve *cu = (Curve *)ptr->owner_id; Nurb *nu = curve_nurb_from_point(cu, ptr->data, NULL, NULL); if (nu) { @@ -441,7 +441,7 @@ static void rna_Curve_update_points(Main *bmain, Scene *scene, PointerRNA *ptr) static PointerRNA rna_Curve_bevelObject_get(PointerRNA *ptr) { - Curve *cu = (Curve *)ptr->id.data; + Curve *cu = (Curve *)ptr->owner_id; Object *ob = cu->bevobj; if (ob) { @@ -455,7 +455,7 @@ static void rna_Curve_bevelObject_set(PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) { - Curve *cu = (Curve *)ptr->id.data; + Curve *cu = (Curve *)ptr->owner_id; Object *ob = (Object *)value.data; if (ob) { @@ -473,7 +473,7 @@ static void rna_Curve_bevelObject_set(PointerRNA *ptr, static bool rna_Curve_otherObject_poll(PointerRNA *ptr, PointerRNA value) { - Curve *cu = (Curve *)ptr->id.data; + Curve *cu = (Curve *)ptr->owner_id; Object *ob = (Object *)value.data; if (ob) { @@ -487,7 +487,7 @@ static bool rna_Curve_otherObject_poll(PointerRNA *ptr, PointerRNA value) static PointerRNA rna_Curve_taperObject_get(PointerRNA *ptr) { - Curve *cu = (Curve *)ptr->id.data; + Curve *cu = (Curve *)ptr->owner_id; Object *ob = cu->taperobj; if (ob) { @@ -501,7 +501,7 @@ static void rna_Curve_taperObject_set(PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) { - Curve *cu = (Curve *)ptr->id.data; + Curve *cu = (Curve *)ptr->owner_id; Object *ob = (Object *)value.data; if (ob) { @@ -519,7 +519,7 @@ static void rna_Curve_taperObject_set(PointerRNA *ptr, static void rna_Curve_resolution_u_update_data(Main *bmain, Scene *scene, PointerRNA *ptr) { - Curve *cu = (Curve *)ptr->id.data; + Curve *cu = (Curve *)ptr->owner_id; ListBase *nurbs = BKE_curve_nurbs_get(cu); Nurb *nu = nurbs->first; @@ -533,7 +533,7 @@ static void rna_Curve_resolution_u_update_data(Main *bmain, Scene *scene, Pointe static void rna_Curve_resolution_v_update_data(Main *bmain, Scene *scene, PointerRNA *ptr) { - Curve *cu = (Curve *)ptr->id.data; + Curve *cu = (Curve *)ptr->owner_id; ListBase *nurbs = BKE_curve_nurbs_get(cu); Nurb *nu = nurbs->first; @@ -547,26 +547,26 @@ static void rna_Curve_resolution_v_update_data(Main *bmain, Scene *scene, Pointe static float rna_Curve_offset_get(PointerRNA *ptr) { - Curve *cu = (Curve *)ptr->id.data; + Curve *cu = (Curve *)ptr->owner_id; return cu->width - 1.0f; } static void rna_Curve_offset_set(PointerRNA *ptr, float value) { - Curve *cu = (Curve *)ptr->id.data; + Curve *cu = (Curve *)ptr->owner_id; cu->width = 1.0f + value; } static int rna_Curve_body_length(PointerRNA *ptr); static void rna_Curve_body_get(PointerRNA *ptr, char *value) { - Curve *cu = (Curve *)ptr->id.data; + Curve *cu = (Curve *)ptr->owner_id; BLI_strncpy(value, cu->str, rna_Curve_body_length(ptr) + 1); } static int rna_Curve_body_length(PointerRNA *ptr) { - Curve *cu = (Curve *)ptr->id.data; + Curve *cu = (Curve *)ptr->owner_id; return cu->len; } @@ -576,7 +576,7 @@ static void rna_Curve_body_set(PointerRNA *ptr, const char *value) size_t len_bytes; size_t len_chars = BLI_strlen_utf8_ex(value, &len_bytes); - Curve *cu = (Curve *)ptr->id.data; + Curve *cu = (Curve *)ptr->owner_id; cu->len_wchar = len_chars; cu->len = len_bytes; @@ -770,7 +770,7 @@ static void rna_Curve_active_spline_set(PointerRNA *ptr, static char *rna_Curve_spline_path(PointerRNA *ptr) { - Curve *cu = (Curve *)ptr->id.data; + Curve *cu = (Curve *)ptr->owner_id; ListBase *nubase = BKE_curve_nurbs_get(cu); Nurb *nu = ptr->data; int index = BLI_findindex(nubase, nu); @@ -786,7 +786,7 @@ static char *rna_Curve_spline_path(PointerRNA *ptr) /* use for both bezier and nurbs */ static char *rna_Curve_spline_point_path(PointerRNA *ptr) { - Curve *cu = (Curve *)ptr->id.data; + Curve *cu = (Curve *)ptr->owner_id; Nurb *nu; void *point = ptr->data; int nu_index, pt_index; @@ -808,7 +808,7 @@ static char *rna_Curve_spline_point_path(PointerRNA *ptr) static char *rna_TextBox_path(PointerRNA *ptr) { - Curve *cu = (Curve *)ptr->id.data; + Curve *cu = (Curve *)ptr->owner_id; TextBox *tb = ptr->data; int index = (int)(tb - cu->tb); @@ -822,13 +822,13 @@ static char *rna_TextBox_path(PointerRNA *ptr) static void rna_Curve_splines_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { - Curve *cu = (Curve *)ptr->id.data; + Curve *cu = (Curve *)ptr->owner_id; rna_iterator_listbase_begin(iter, BKE_curve_nurbs_get(cu), NULL); } static bool rna_Curve_is_editmode_get(PointerRNA *ptr) { - Curve *cu = (Curve *)ptr->id.data; + Curve *cu = (Curve *)ptr->owner_id; const short type = BKE_curve_type_get(cu); if (type == OB_FONT) { return (cu->editfont != NULL); @@ -1229,6 +1229,7 @@ static void rna_def_font(BlenderRNA *UNUSED(brna), StructRNA *srna) RNA_def_property_pointer_sdna(prop, NULL, "textoncurve"); RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Curve_otherObject_poll"); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Text on Curve", "Curve deforming text object"); RNA_def_property_update(prop, 0, "rna_Curve_update_deps"); @@ -1236,24 +1237,28 @@ static void rna_def_font(BlenderRNA *UNUSED(brna), StructRNA *srna) RNA_def_property_pointer_sdna(prop, NULL, "vfont"); RNA_def_property_ui_text(prop, "Font", ""); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); prop = RNA_def_property(srna, "font_bold", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "vfontb"); RNA_def_property_ui_text(prop, "Font Bold", ""); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); prop = RNA_def_property(srna, "font_italic", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "vfonti"); RNA_def_property_ui_text(prop, "Font Italic", ""); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); prop = RNA_def_property(srna, "font_bold_italic", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "vfontbi"); RNA_def_property_ui_text(prop, "Font Bold Italic", ""); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); prop = RNA_def_property(srna, "edit_format", PROP_POINTER, PROP_NONE); @@ -1646,6 +1651,7 @@ static void rna_def_curve(BlenderRNA *brna) RNA_def_property_struct_type(prop, "Object"); RNA_def_property_pointer_sdna(prop, NULL, "bevobj"); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Bevel Object", "Curve object name that defines the bevel shape"); RNA_def_property_update(prop, 0, "rna_Curve_update_deps"); RNA_def_property_pointer_funcs(prop, @@ -1658,6 +1664,7 @@ static void rna_def_curve(BlenderRNA *brna) RNA_def_property_struct_type(prop, "Object"); RNA_def_property_pointer_sdna(prop, NULL, "taperobj"); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text( prop, "Taper Object", "Curve object name that defines the taper (width)"); RNA_def_property_update(prop, 0, "rna_Curve_update_deps"); diff --git a/source/blender/makesrna/intern/rna_dynamicpaint.c b/source/blender/makesrna/intern/rna_dynamicpaint.c index 792c4450b9c..30a68a4919e 100644 --- a/source/blender/makesrna/intern/rna_dynamicpaint.c +++ b/source/blender/makesrna/intern/rna_dynamicpaint.c @@ -92,7 +92,7 @@ static void rna_DynamicPaint_redoModifier(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - DEG_id_tag_update(ptr->id.data, ID_RECALC_GEOMETRY); + DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY); } static void rna_DynamicPaintSurfaces_updateFrames(Main *UNUSED(bmain), diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c index 222d2fc69da..254f3bc3710 100644 --- a/source/blender/makesrna/intern/rna_fcurve.c +++ b/source/blender/makesrna/intern/rna_fcurve.c @@ -132,6 +132,33 @@ const EnumPropertyItem rna_enum_beztriple_interpolation_easing_items[] = { {0, NULL, 0, NULL, NULL}, }; +const EnumPropertyItem rna_enum_driver_target_rotation_mode_items[] = { + {DTAR_ROTMODE_AUTO, "AUTO", 0, "Auto Euler", "Euler using the rotation order of the target"}, + {DTAR_ROTMODE_EULER_XYZ, "XYZ", 0, "XYZ Euler", "Euler using the XYZ rotation order"}, + {DTAR_ROTMODE_EULER_XZY, "XZY", 0, "XZY Euler", "Euler using the XZY rotation order"}, + {DTAR_ROTMODE_EULER_YXZ, "YXZ", 0, "YXZ Euler", "Euler using the YXZ rotation order"}, + {DTAR_ROTMODE_EULER_YZX, "YZX", 0, "YZX Euler", "Euler using the YZX rotation order"}, + {DTAR_ROTMODE_EULER_ZXY, "ZXY", 0, "ZXY Euler", "Euler using the ZXY rotation order"}, + {DTAR_ROTMODE_EULER_ZYX, "ZYX", 0, "ZYX Euler", "Euler using the ZYX rotation order"}, + {DTAR_ROTMODE_QUATERNION, "QUATERNION", 0, "Quaternion", "Quaternion rotation"}, + {DTAR_ROTMODE_SWING_TWIST_X, + "SWING_TWIST_X", + 0, + "Swing and X Twist", + "Decompose into a swing rotation to aim the X axis, followed by twist around it"}, + {DTAR_ROTMODE_SWING_TWIST_Y, + "SWING_TWIST_Y", + 0, + "Swing and Y Twist", + "Decompose into a swing rotation to aim the Y axis, followed by twist around it"}, + {DTAR_ROTMODE_SWING_TWIST_Z, + "SWING_TWIST_Z", + 0, + "Swing and Z Twist", + "Decompose into a swing rotation to aim the Z axis, followed by twist around it"}, + {0, NULL, 0, NULL, NULL}, +}; + #ifdef RNA_RUNTIME # include "WM_api.h" @@ -183,7 +210,7 @@ static bool rna_ChannelDriver_is_simple_expression_get(PointerRNA *ptr) static void rna_ChannelDriver_update_data(Main *bmain, Scene *scene, PointerRNA *ptr) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; ChannelDriver *driver = ptr->data; driver->flag &= ~DRIVER_FLAG_INVALID; @@ -211,7 +238,7 @@ static void rna_DriverTarget_update_data(Main *bmain, Scene *scene, PointerRNA * PointerRNA driverptr; ChannelDriver *driver; FCurve *fcu; - AnimData *adt = BKE_animdata_from_id(ptr->id.data); + AnimData *adt = BKE_animdata_from_id(ptr->owner_id); /* find the driver this belongs to and update it */ for (fcu = adt->drivers.first; fcu; fcu = fcu->next) { @@ -221,7 +248,7 @@ static void rna_DriverTarget_update_data(Main *bmain, Scene *scene, PointerRNA * if (driver) { /* FIXME: need to be able to search targets for required one... */ /*BLI_findindex(&driver->targets, ptr->data) != -1) */ - RNA_pointer_create(ptr->id.data, &RNA_Driver, driver, &driverptr); + RNA_pointer_create(ptr->owner_id, &RNA_Driver, driver, &driverptr); rna_ChannelDriver_update_data(bmain, scene, &driverptr); return; } @@ -466,8 +493,8 @@ static void rna_FCurve_group_set(PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) { - ID *pid = (ID *)ptr->id.data; - ID *vid = (ID *)value.id.data; + ID *pid = ptr->owner_id; + ID *vid = value.owner_id; FCurve *fcu = ptr->data; bAction *act = NULL; @@ -491,7 +518,7 @@ static void rna_FCurve_group_set(PointerRNA *ptr, } else { /* the ID given is the owner of the F-Curve (for drivers) */ - AnimData *adt = BKE_animdata_from_id(ptr->id.data); + AnimData *adt = BKE_animdata_from_id(ptr->owner_id); act = (adt) ? adt->action : NULL; } @@ -572,7 +599,7 @@ static void rna_FCurve_update_data_ex(ID *id, FCurve *fcu, Main *bmain) static void rna_FCurve_update_data(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { BLI_assert(ptr->type == &RNA_FCurve); - rna_FCurve_update_data_ex((ID *)ptr->id.data, (FCurve *)ptr->data, bmain); + rna_FCurve_update_data_ex(ptr->owner_id, (FCurve *)ptr->data, bmain); } static void rna_FCurve_update_data_relations(Main *bmain, @@ -587,7 +614,7 @@ static void rna_FCurve_update_data_relations(Main *bmain, */ static void rna_FCurve_update_eval(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - rna_tag_animation_update(bmain, (ID *)ptr->id.data, true); + rna_tag_animation_update(bmain, ptr->owner_id, true); } static PointerRNA rna_FCurve_active_modifier_get(PointerRNA *ptr) @@ -700,7 +727,7 @@ static void rna_FModifier_blending_range( static void rna_FModifier_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; FModifier *fcm = (FModifier *)ptr->data; if (fcm->curve && fcm->type == FMODIFIER_TYPE_CYCLES) { @@ -1065,7 +1092,7 @@ static void rna_FModifierEnvelope_points_remove( static void rna_Keyframe_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - rna_tag_animation_update(bmain, (ID *)ptr->id.data, true); + rna_tag_animation_update(bmain, ptr->owner_id, true); } #else @@ -1671,9 +1698,12 @@ static void rna_def_drivertarget(BlenderRNA *brna) {DTAR_TRANSCHAN_LOCX, "LOC_X", 0, "X Location", ""}, {DTAR_TRANSCHAN_LOCY, "LOC_Y", 0, "Y Location", ""}, {DTAR_TRANSCHAN_LOCZ, "LOC_Z", 0, "Z Location", ""}, + {0, "", 0, NULL, NULL}, {DTAR_TRANSCHAN_ROTX, "ROT_X", 0, "X Rotation", ""}, {DTAR_TRANSCHAN_ROTY, "ROT_Y", 0, "Y Rotation", ""}, {DTAR_TRANSCHAN_ROTZ, "ROT_Z", 0, "Z Rotation", ""}, + {DTAR_TRANSCHAN_ROTW, "ROT_W", 0, "W Rotation", ""}, + {0, "", 0, NULL, NULL}, {DTAR_TRANSCHAN_SCALEX, "SCALE_X", 0, "X Scale", ""}, {DTAR_TRANSCHAN_SCALEY, "SCALE_Y", 0, "Y Scale", ""}, {DTAR_TRANSCHAN_SCALEZ, "SCALE_Z", 0, "Z Scale", ""}, @@ -1749,6 +1779,12 @@ static void rna_def_drivertarget(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Type", "Driver variable type"); RNA_def_property_update(prop, 0, "rna_DriverTarget_update_data"); + prop = RNA_def_property(srna, "rotation_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "rotation_mode"); + RNA_def_property_enum_items(prop, rna_enum_driver_target_rotation_mode_items); + RNA_def_property_ui_text(prop, "Rotation Mode", "Mode for calculating rotation channel values"); + RNA_def_property_update(prop, 0, "rna_DriverTarget_update_data"); + prop = RNA_def_property(srna, "transform_space", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); RNA_def_property_enum_items(prop, prop_local_space_items); diff --git a/source/blender/makesrna/intern/rna_fluidsim.c b/source/blender/makesrna/intern/rna_fluidsim.c index 45361702384..5d21e718934 100644 --- a/source/blender/makesrna/intern/rna_fluidsim.c +++ b/source/blender/makesrna/intern/rna_fluidsim.c @@ -75,7 +75,7 @@ static StructRNA *rna_FluidSettings_refine(struct PointerRNA *ptr) static void rna_fluid_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Object *ob = ptr->id.data; + Object *ob = (Object *)ptr->owner_id; DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob); @@ -101,7 +101,7 @@ static int fluidsim_find_lastframe(Main *bmain, Object *ob, FluidsimSettings *fs static void rna_fluid_find_enframe(Main *bmain, Scene *scene, PointerRNA *ptr) { - Object *ob = ptr->id.data; + Object *ob = (Object *)ptr->owner_id; FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType( ob, eModifierType_Fluidsim); @@ -116,7 +116,7 @@ static void rna_fluid_find_enframe(Main *bmain, Scene *scene, PointerRNA *ptr) static void rna_FluidSettings_update_type(Main *bmain, Scene *scene, PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; FluidsimModifierData *fluidmd; ParticleSystemModifierData *psmd; ParticleSystem *psys, *next_psys; @@ -177,7 +177,7 @@ static void rna_DomainFluidSettings_memory_estimate_get(PointerRNA *ptr, char *v (void)ptr; value[0] = '\0'; # else - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; FluidsimSettings *fss = (FluidsimSettings *)ptr->data; fluid_estimate_memory(ob, fss, value); diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c index 2671246b589..01ecf2f8cae 100644 --- a/source/blender/makesrna/intern/rna_gpencil.c +++ b/source/blender/makesrna/intern/rna_gpencil.c @@ -144,37 +144,14 @@ static EnumPropertyItem rna_enum_gpencil_caps_modes_items[] = { static void rna_GPencil_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - DEG_id_tag_update(ptr->id.data, ID_RECALC_GEOMETRY); + DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY); WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL); } static void rna_GPencil_autolock(Main *bmain, Scene *scene, PointerRNA *ptr) { - bGPdata *gpd = (bGPdata *)ptr->id.data; - bGPDlayer *gpl = NULL; - - if (gpd->flag & GP_DATA_AUTOLOCK_LAYERS) { - bGPDlayer *layer = BKE_gpencil_layer_getactive(gpd); - - /* Lock all other layers */ - for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { - /* unlock active layer */ - if (gpl == layer) { - gpl->flag &= ~GP_LAYER_LOCKED; - } - else { - gpl->flag |= GP_LAYER_LOCKED; - } - } - } - else { - /* If disable is better unlock all layers by default or it looks there is - * a problem in the UI because the user expects all layers will be unlocked - */ - for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { - gpl->flag &= ~GP_LAYER_LOCKED; - } - } + bGPdata *gpd = (bGPdata *)ptr->owner_id; + BKE_gpencil_layer_autolock_set(gpd); /* standard update */ rna_GPencil_update(bmain, scene, ptr); @@ -182,7 +159,7 @@ static void rna_GPencil_autolock(Main *bmain, Scene *scene, PointerRNA *ptr) static void rna_GPencil_editmode_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - bGPdata *gpd = (bGPdata *)ptr->id.data; + bGPdata *gpd = (bGPdata *)ptr->owner_id; DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); /* Notify all places where GPencil data lives that the editing state is different */ @@ -194,7 +171,7 @@ static void UNUSED_FUNCTION(rna_GPencil_onion_skinning_update)(Main *bmain, Scene *scene, PointerRNA *ptr) { - bGPdata *gpd = (bGPdata *)ptr->id.data; + bGPdata *gpd = (bGPdata *)ptr->owner_id; bGPDlayer *gpl; bool enabled = false; @@ -362,7 +339,7 @@ static bool rna_GPencilLayer_is_parented_get(PointerRNA *ptr) static PointerRNA rna_GPencil_active_layer_get(PointerRNA *ptr) { - bGPdata *gpd = ptr->id.data; + bGPdata *gpd = (bGPdata *)ptr->owner_id; if (GS(gpd->id.name) == ID_GD) { /* why would this ever be not GD */ bGPDlayer *gl; @@ -385,7 +362,7 @@ static void rna_GPencil_active_layer_set(PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) { - bGPdata *gpd = ptr->id.data; + bGPdata *gpd = (bGPdata *)ptr->owner_id; /* Don't allow setting active layer to NULL if layers exist * as this breaks various tools. Tools should be used instead @@ -414,7 +391,7 @@ static void rna_GPencil_active_layer_set(PointerRNA *ptr, static int rna_GPencil_active_layer_index_get(PointerRNA *ptr) { - bGPdata *gpd = (bGPdata *)ptr->id.data; + bGPdata *gpd = (bGPdata *)ptr->owner_id; bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); return BLI_findindex(&gpd->layers, gpl); @@ -422,7 +399,7 @@ static int rna_GPencil_active_layer_index_get(PointerRNA *ptr) static void rna_GPencil_active_layer_index_set(PointerRNA *ptr, int value) { - bGPdata *gpd = (bGPdata *)ptr->id.data; + bGPdata *gpd = (bGPdata *)ptr->owner_id; bGPDlayer *gpl = BLI_findlink(&gpd->layers, value); BKE_gpencil_layer_setactive(gpd, gpl); @@ -435,7 +412,7 @@ static void rna_GPencil_active_layer_index_set(PointerRNA *ptr, int value) static void rna_GPencil_active_layer_index_range( PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax) { - bGPdata *gpd = (bGPdata *)ptr->id.data; + bGPdata *gpd = (bGPdata *)ptr->owner_id; *min = 0; *max = max_ii(0, BLI_listbase_count(&gpd->layers) - 1); @@ -449,7 +426,7 @@ static const EnumPropertyItem *rna_GPencil_active_layer_itemf(bContext *C, PropertyRNA *UNUSED(prop), bool *r_free) { - bGPdata *gpd = (bGPdata *)ptr->id.data; + bGPdata *gpd = (bGPdata *)ptr->owner_id; bGPDlayer *gpl; EnumPropertyItem *item = NULL, item_tmp = {0}; int totitem = 0; @@ -478,7 +455,7 @@ static const EnumPropertyItem *rna_GPencil_active_layer_itemf(bContext *C, static void rna_GPencilLayer_info_set(PointerRNA *ptr, const char *value) { - bGPdata *gpd = ptr->id.data; + bGPdata *gpd = (bGPdata *)ptr->owner_id; bGPDlayer *gpl = ptr->data; char oldname[128] = ""; @@ -539,7 +516,7 @@ static bGPDstroke *rna_GPencil_stroke_point_find_stroke(const bGPdata *gpd, static void rna_GPencil_stroke_point_select_set(PointerRNA *ptr, const bool value) { - bGPdata *gpd = ptr->id.data; + bGPdata *gpd = (bGPdata *)ptr->owner_id; bGPDspoint *pt = ptr->data; bGPDstroke *gps = NULL; @@ -1510,6 +1487,7 @@ static void rna_def_gpencil_layer(BlenderRNA *brna) prop = RNA_def_property(srna, "parent", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_funcs(prop, NULL, "rna_GPencilLayer_parent_set", NULL, NULL); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Parent", "Parent Object"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); @@ -1648,7 +1626,7 @@ static void rna_def_gpencil_grid(BlenderRNA *brna) prop = RNA_def_property(srna, "lines", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "lines"); - RNA_def_property_range(prop, 0, INT_MAX); + RNA_def_property_range(prop, 0, SHRT_MAX); RNA_def_property_int_default(prop, GP_DEFAULT_GRID_LINES); RNA_def_property_ui_text( prop, "Grid Subdivisions", "Number of subdivisions in each side of symmetry line"); @@ -1913,7 +1891,7 @@ static void rna_def_gpencil_data(BlenderRNA *brna) prop = RNA_def_property(srna, "zdepth_offset", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "zdepth_offset"); RNA_def_property_range(prop, 0.0f, 1.0f); - RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.001, 5); + RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1f, 3); RNA_def_property_ui_text(prop, "Surface Offset", "Offset amount when drawing in surface mode"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c index 04175d8cfd9..4a0cf4d7ce2 100644 --- a/source/blender/makesrna/intern/rna_gpencil_modifier.c +++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c @@ -252,8 +252,8 @@ static void rna_GpencilModifier_name_set(PointerRNA *ptr, const char *value) BLI_strncpy_utf8(gmd->name, value, sizeof(gmd->name)); /* make sure the name is truly unique */ - if (ptr->id.data) { - Object *ob = ptr->id.data; + if (ptr->owner_id) { + Object *ob = (Object *)ptr->owner_id; BKE_gpencil_modifier_unique_name(&ob->greasepencil_modifiers, gmd); } @@ -272,8 +272,8 @@ static char *rna_GpencilModifier_path(PointerRNA *ptr) static void rna_GpencilModifier_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - DEG_id_tag_update(ptr->id.data, ID_RECALC_GEOMETRY); - WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ptr->id.data); + DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY); + WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ptr->owner_id); } static void rna_GpencilModifier_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr) @@ -324,7 +324,7 @@ static void greasepencil_modifier_object_set(Object *self, PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) \ { \ _type##GpencilModifierData *tmd = (_type##GpencilModifierData *)ptr->data; \ - greasepencil_modifier_object_set(ptr->id.data, &tmd->_prop, _obtype, value); \ + greasepencil_modifier_object_set((Object *)ptr->owner_id, &tmd->_prop, _obtype, value); \ } RNA_GP_MOD_OBJECT_SET(Armature, object, OB_ARMATURE); @@ -384,6 +384,11 @@ static void rna_def_modifier_gpencilnoise(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Layer", "Layer name"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "materialname"); + RNA_def_property_ui_text(prop, "Material", "Material name"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "vgname"); RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name for modulating the deform"); @@ -458,6 +463,11 @@ static void rna_def_modifier_gpencilnoise(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "invert_materials", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_NOISE_INVERT_MATERIAL); + RNA_def_property_ui_text(prop, "Inverse Materials", "Inverse filter"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "invert_material_pass", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_NOISE_INVERT_PASS); RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter"); @@ -495,6 +505,11 @@ static void rna_def_modifier_gpencilsmooth(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Layer", "Layer name"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "materialname"); + RNA_def_property_ui_text(prop, "Material", "Material name"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "vgname"); RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name for modulating the deform"); @@ -549,6 +564,11 @@ static void rna_def_modifier_gpencilsmooth(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "invert_materials", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SMOOTH_INVERT_MATERIAL); + RNA_def_property_ui_text(prop, "Inverse Materials", "Inverse filter"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "invert_material_pass", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SMOOTH_INVERT_PASS); RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter"); @@ -586,6 +606,11 @@ static void rna_def_modifier_gpencilsubdiv(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Layer", "Layer name"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "materialname"); + RNA_def_property_ui_text(prop, "Material", "Material name"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "level", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "level"); RNA_def_property_range(prop, 0, 5); @@ -608,6 +633,11 @@ static void rna_def_modifier_gpencilsubdiv(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "invert_materials", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SUBDIV_INVERT_MATERIAL); + RNA_def_property_ui_text(prop, "Inverse Materials", "Inverse filter"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "invert_material_pass", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SUBDIV_INVERT_PASS); RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter"); @@ -664,6 +694,11 @@ static void rna_def_modifier_gpencilsimplify(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Layer", "Layer name"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "materialname"); + RNA_def_property_ui_text(prop, "Material", "Material name"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "factor"); RNA_def_property_range(prop, 0, 100.0); @@ -682,6 +717,11 @@ static void rna_def_modifier_gpencilsimplify(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "invert_materials", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SIMPLIFY_INVERT_MATERIAL); + RNA_def_property_ui_text(prop, "Inverse Materials", "Inverse filter"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "invert_material_pass", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SIMPLIFY_INVERT_PASS); RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter"); @@ -721,7 +761,7 @@ static void rna_def_modifier_gpencilsimplify(BlenderRNA *brna) prop = RNA_def_property(srna, "distance", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "distance"); RNA_def_property_range(prop, 0, 100.0f); - RNA_def_property_ui_text(prop, "Distance", "Distance between vertex"); + RNA_def_property_ui_text(prop, "Distance", "Distance between points"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); } @@ -740,6 +780,11 @@ static void rna_def_modifier_gpencilthick(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Layer", "Layer name"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "materialname"); + RNA_def_property_ui_text(prop, "Material", "Material name"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "vgname"); RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name for modulating the deform"); @@ -763,6 +808,11 @@ static void rna_def_modifier_gpencilthick(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "invert_materials", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_THICK_INVERT_MATERIAL); + RNA_def_property_ui_text(prop, "Inverse Materials", "Inverse filter"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "invert_material_pass", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_THICK_INVERT_PASS); RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter"); @@ -815,6 +865,11 @@ static void rna_def_modifier_gpenciloffset(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Layer", "Layer name"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "materialname"); + RNA_def_property_ui_text(prop, "Material", "Material name"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "vgname"); RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name for modulating the deform"); @@ -832,6 +887,11 @@ static void rna_def_modifier_gpenciloffset(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "invert_materials", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_OFFSET_INVERT_MATERIAL); + RNA_def_property_ui_text(prop, "Inverse Materials", "Inverse filter"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "invert_material_pass", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_OFFSET_INVERT_PASS); RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter"); @@ -892,6 +952,11 @@ static void rna_def_modifier_gpenciltint(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Layer", "Layer name"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "materialname"); + RNA_def_property_ui_text(prop, "Material", "Material name"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_range(prop, 0.0, 1.0); RNA_def_property_float_sdna(prop, NULL, "rgb"); @@ -921,6 +986,11 @@ static void rna_def_modifier_gpenciltint(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "invert_materials", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_TINT_INVERT_MATERIAL); + RNA_def_property_ui_text(prop, "Inverse Materials", "Inverse filter"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "invert_material_pass", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_TINT_INVERT_PASS); RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter"); @@ -977,7 +1047,7 @@ static void rna_def_modifier_gpenciltime(BlenderRNA *brna) prop = RNA_def_property(srna, "offset", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "offset"); - RNA_def_property_range(prop, -INT_MAX, INT_MAX); + RNA_def_property_range(prop, SHRT_MIN, SHRT_MAX); RNA_def_property_ui_text( prop, "Frame Offset", "Number of frames to offset original keyframe number or frame to fix"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); @@ -1039,6 +1109,11 @@ static void rna_def_modifier_gpencilcolor(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Layer", "Layer name"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "materialname"); + RNA_def_property_ui_text(prop, "Material", "Material name"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "hue", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.0, 1.0); RNA_def_property_ui_range(prop, 0.0, 1.0, 0.1, 3); @@ -1076,6 +1151,11 @@ static void rna_def_modifier_gpencilcolor(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "invert_materials", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_COLOR_INVERT_MATERIAL); + RNA_def_property_ui_text(prop, "Inverse Materials", "Inverse filter"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "invert_material_pass", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_COLOR_INVERT_PASS); RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter"); @@ -1118,6 +1198,11 @@ static void rna_def_modifier_gpencilopacity(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Layer", "Layer name"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "materialname"); + RNA_def_property_ui_text(prop, "Material", "Material name"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "vgname"); RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name for modulating the deform"); @@ -1146,6 +1231,11 @@ static void rna_def_modifier_gpencilopacity(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "invert_materials", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_OPACITY_INVERT_MATERIAL); + RNA_def_property_ui_text(prop, "Inverse Materials", "Inverse filter"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "invert_material_pass", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_OPACITY_INVERT_PASS); RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter"); @@ -1183,6 +1273,11 @@ static void rna_def_modifier_gpencilinstance(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Layer", "Layer name"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "materialname"); + RNA_def_property_ui_text(prop, "Material", "Material name"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "pass_index"); RNA_def_property_range(prop, 0, 100); @@ -1190,7 +1285,7 @@ static void rna_def_modifier_gpencilinstance(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); prop = RNA_def_property(srna, "count", PROP_INT, PROP_NONE); - RNA_def_property_range(prop, 1, INT_MAX); + RNA_def_property_range(prop, 1, SHRT_MAX); RNA_def_property_ui_range(prop, 1, 50, 1, -1); RNA_def_property_ui_text(prop, "Count", "Number of items"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); @@ -1204,6 +1299,7 @@ static void rna_def_modifier_gpencilinstance(BlenderRNA *brna) "Use the location and rotation of another object to determine the distance and " "rotational change between arrayed items"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update"); prop = RNA_def_property(srna, "offset", PROP_FLOAT, PROP_TRANSLATION); @@ -1254,7 +1350,7 @@ static void rna_def_modifier_gpencilinstance(BlenderRNA *brna) prop = RNA_def_property(srna, "replace_material", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "mat_rpl"); - RNA_def_property_range(prop, 0, INT_MAX); + RNA_def_property_range(prop, 0, SHRT_MAX); RNA_def_property_ui_text( prop, "Material", @@ -1266,6 +1362,11 @@ static void rna_def_modifier_gpencilinstance(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "invert_materials", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_ARRAY_INVERT_MATERIAL); + RNA_def_property_ui_text(prop, "Inverse Materials", "Inverse filter"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "invert_material_pass", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_ARRAY_INVERT_PASS); RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter"); @@ -1452,6 +1553,11 @@ static void rna_def_modifier_gpencillattice(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Layer", "Layer name"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "materialname"); + RNA_def_property_ui_text(prop, "Material", "Material name"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "vgname"); RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name for modulating the deform"); @@ -1469,6 +1575,11 @@ static void rna_def_modifier_gpencillattice(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "invert_materials", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LATTICE_INVERT_MATERIAL); + RNA_def_property_ui_text(prop, "Inverse Materials", "Inverse filter"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "invert_material_pass", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LATTICE_INVERT_PASS); RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter"); @@ -1495,6 +1606,7 @@ static void rna_def_modifier_gpencillattice(BlenderRNA *brna) RNA_def_property_pointer_funcs( prop, NULL, "rna_LatticeGpencilModifier_object_set", NULL, "rna_Lattice_object_poll"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update"); prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE); @@ -1520,6 +1632,11 @@ static void rna_def_modifier_gpencilmirror(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Layer", "Layer name"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "materialname"); + RNA_def_property_ui_text(prop, "Material", "Material name"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "pass_index"); RNA_def_property_range(prop, 0, 100); @@ -1531,6 +1648,11 @@ static void rna_def_modifier_gpencilmirror(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "invert_materials", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_MIRROR_INVERT_MATERIAL); + RNA_def_property_ui_text(prop, "Inverse Materials", "Inverse filter"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "invert_material_pass", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_MIRROR_INVERT_PASS); RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter"); @@ -1551,6 +1673,7 @@ static void rna_def_modifier_gpencilmirror(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Object", "Object used as center"); RNA_def_property_pointer_funcs(prop, NULL, "rna_MirrorGpencilModifier_object_set", NULL, NULL); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update"); prop = RNA_def_property(srna, "use_clip", PROP_BOOLEAN, PROP_NONE); @@ -1589,6 +1712,7 @@ static void rna_def_modifier_gpencilhook(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Object", "Parent Object for hook, also recalculates and clears offset"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_pointer_funcs(prop, NULL, "rna_HookGpencilModifier_object_set", NULL, NULL); RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update"); @@ -1605,6 +1729,11 @@ static void rna_def_modifier_gpencilhook(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Layer", "Layer name"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "materialname"); + RNA_def_property_ui_text(prop, "Material", "Material name"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "vgname"); RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name for modulating the deform"); @@ -1622,6 +1751,11 @@ static void rna_def_modifier_gpencilhook(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "invert_materials", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_HOOK_INVERT_MATERIAL); + RNA_def_property_ui_text(prop, "Inverse Materials", "Inverse filter"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "invert_material_pass", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_HOOK_INVERT_PASS); RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter"); diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c index 75867b2fe13..517bd2b7276 100644 --- a/source/blender/makesrna/intern/rna_image.c +++ b/source/blender/makesrna/intern/rna_image.c @@ -91,7 +91,7 @@ static bool rna_Image_dirty_get(PointerRNA *ptr) static void rna_Image_source_set(PointerRNA *ptr, int value) { - Image *ima = ptr->id.data; + Image *ima = (Image *)ptr->owner_id; if (value != ima->source) { ima->source = value; @@ -105,7 +105,7 @@ static void rna_Image_source_set(PointerRNA *ptr, int value) static void rna_Image_reload_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - Image *ima = ptr->id.data; + Image *ima = (Image *)ptr->owner_id; BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_RELOAD); WM_main_add_notifier(NC_IMAGE | NA_EDITED, &ima->id); DEG_id_tag_update(&ima->id, 0); @@ -114,13 +114,13 @@ static void rna_Image_reload_update(Main *bmain, Scene *UNUSED(scene), PointerRN static void rna_Image_generated_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - Image *ima = ptr->id.data; + Image *ima = (Image *)ptr->owner_id; BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_FREE); } static void rna_Image_colormanage_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - Image *ima = ptr->id.data; + Image *ima = (Image *)ptr->owner_id; BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_COLORMANAGE); DEG_id_tag_update(&ima->id, 0); DEG_id_tag_update(&ima->id, ID_RECALC_EDITORS); @@ -130,7 +130,7 @@ static void rna_Image_colormanage_update(Main *bmain, Scene *UNUSED(scene), Poin static void rna_Image_views_format_update(Main *bmain, Scene *scene, PointerRNA *ptr) { - Image *ima = ptr->id.data; + Image *ima = (Image *)ptr->owner_id; ImBuf *ibuf; void *lock; @@ -148,7 +148,7 @@ static void rna_Image_views_format_update(Main *bmain, Scene *scene, PointerRNA static void rna_ImageUser_update(Main *bmain, Scene *scene, PointerRNA *ptr) { ImageUser *iuser = ptr->data; - ID *id = ptr->id.data; + ID *id = ptr->owner_id; BKE_image_user_frame_calc(NULL, iuser, scene->r.cfra); @@ -173,10 +173,10 @@ static void rna_ImageUser_relations_update(Main *bmain, Scene *scene, PointerRNA static char *rna_ImageUser_path(PointerRNA *ptr) { - if (ptr->id.data) { + if (ptr->owner_id) { /* ImageUser *iuser = ptr->data; */ - switch (GS(((ID *)ptr->id.data)->name)) { + switch (GS(ptr->owner_id->name)) { case ID_OB: case ID_TE: { return BLI_strdup("image_user"); @@ -331,7 +331,7 @@ static int rna_Image_depth_get(PointerRNA *ptr) static int rna_Image_frame_duration_get(PointerRNA *ptr) { - Image *ima = ptr->id.data; + Image *ima = (Image *)ptr->owner_id; int duration = 1; if (BKE_image_has_anim(ima)) { @@ -352,7 +352,7 @@ static int rna_Image_frame_duration_get(PointerRNA *ptr) static int rna_Image_pixels_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION]) { - Image *ima = ptr->id.data; + Image *ima = (Image *)ptr->owner_id; ImBuf *ibuf; void *lock; @@ -372,7 +372,7 @@ static int rna_Image_pixels_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY static void rna_Image_pixels_get(PointerRNA *ptr, float *values) { - Image *ima = ptr->id.data; + Image *ima = (Image *)ptr->owner_id; ImBuf *ibuf; void *lock; int i, size; @@ -397,7 +397,7 @@ static void rna_Image_pixels_get(PointerRNA *ptr, float *values) static void rna_Image_pixels_set(PointerRNA *ptr, const float *values) { - Image *ima = ptr->id.data; + Image *ima = (Image *)ptr->owner_id; ImBuf *ibuf; void *lock; int i, size; @@ -463,7 +463,7 @@ static bool rna_Image_is_float_get(PointerRNA *ptr) static PointerRNA rna_Image_packed_file_get(PointerRNA *ptr) { - Image *ima = (Image *)ptr->id.data; + Image *ima = (Image *)ptr->owner_id; if (BKE_image_has_packedfile(ima)) { ImagePackedFile *imapf = ima->packedfiles.first; @@ -485,7 +485,7 @@ static void rna_RenderSlot_clear(ID *id, RenderSlot *slot, ImageUser *iuser) static PointerRNA rna_render_slots_active_get(PointerRNA *ptr) { - Image *image = (Image *)ptr->id.data; + Image *image = (Image *)ptr->owner_id; RenderSlot *render_slot = BKE_image_get_renderslot(image, image->render_slot); return rna_pointer_inherit_refine(ptr, &RNA_RenderSlot, render_slot); @@ -495,8 +495,8 @@ static void rna_render_slots_active_set(PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) { - Image *image = (Image *)ptr->id.data; - if (value.id.data == image) { + Image *image = (Image *)ptr->owner_id; + if (value.owner_id == &image->id) { RenderSlot *slot = (RenderSlot *)value.data; int index = BLI_findindex(&image->renderslots, slot); if (index != -1) { @@ -507,13 +507,13 @@ static void rna_render_slots_active_set(PointerRNA *ptr, static int rna_render_slots_active_index_get(PointerRNA *ptr) { - Image *image = (Image *)ptr->id.data; + Image *image = (Image *)ptr->owner_id; return image->render_slot; } static void rna_render_slots_active_index_set(PointerRNA *ptr, int value) { - Image *image = (Image *)ptr->id.data; + Image *image = (Image *)ptr->owner_id; int num_slots = BLI_listbase_count(&image->renderslots); image->render_slot = value; CLAMP(image->render_slot, 0, num_slots - 1); @@ -522,7 +522,7 @@ static void rna_render_slots_active_index_set(PointerRNA *ptr, int value) static void rna_render_slots_active_index_range( PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax)) { - Image *image = (Image *)ptr->id.data; + Image *image = (Image *)ptr->owner_id; *min = 0; *max = max_ii(0, BLI_listbase_count(&image->renderslots) - 1); } diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index 96cdc06d901..e5058626180 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -29,15 +29,12 @@ #define RNA_MAGIC ((int)~0) -struct Depsgraph; struct FreestyleSettings; struct ID; struct IDOverrideLibrary; -struct IDOverrideLibraryProperty; struct IDOverrideLibraryPropertyOperation; struct IDProperty; struct Main; -struct Mesh; struct Object; struct ReportList; struct SDNA; @@ -227,7 +224,7 @@ bool rna_AnimaData_override_apply(struct Main *bmain, void rna_def_animviz_common(struct StructRNA *srna); void rna_def_motionpath_common(struct StructRNA *srna); -void rna_def_bone_curved_common(struct StructRNA *srna, bool is_posebone); +void rna_def_bone_curved_common(struct StructRNA *srna, bool is_posebone, bool is_editbone); void rna_def_texmat_common(struct StructRNA *srna, const char *texspace_editable); void rna_def_mtex_common(struct BlenderRNA *brna, diff --git a/source/blender/makesrna/intern/rna_internal_types.h b/source/blender/makesrna/intern/rna_internal_types.h index 60cf443383e..7c6a471b1d7 100644 --- a/source/blender/makesrna/intern/rna_internal_types.h +++ b/source/blender/makesrna/intern/rna_internal_types.h @@ -31,7 +31,6 @@ struct ContainerRNA; struct FunctionRNA; struct GHash; struct IDOverrideLibrary; -struct IDOverrideLibraryProperty; struct IDOverrideLibraryPropertyOperation; struct IDProperty; struct Main; diff --git a/source/blender/makesrna/intern/rna_key.c b/source/blender/makesrna/intern/rna_key.c index 8ab2127d898..46c3adbd6ef 100644 --- a/source/blender/makesrna/intern/rna_key.c +++ b/source/blender/makesrna/intern/rna_key.c @@ -87,8 +87,8 @@ static void rna_ShapeKey_name_set(PointerRNA *ptr, const char *value) BLI_strncpy_utf8(kb->name, value, sizeof(kb->name)); /* make sure the name is truly unique */ - if (ptr->id.data) { - Key *key = rna_ShapeKey_find_key(ptr->id.data); + if (ptr->owner_id) { + Key *key = rna_ShapeKey_find_key(ptr->owner_id); BLI_uniquename(&key->block, kb, CTX_DATA_(BLT_I18NCONTEXT_ID_SHAPEKEY, "Key"), @@ -174,7 +174,7 @@ static void rna_ShapeKey_slider_max_set(PointerRNA *ptr, float value) static Mesh *rna_KeyBlock_normals_get_mesh(PointerRNA *ptr, ID *id) { - Key *key = rna_ShapeKey_find_key((id == NULL && ptr != NULL) ? ptr->id.data : id); + Key *key = rna_ShapeKey_find_key((id == NULL && ptr != NULL) ? ptr->owner_id : id); id = key ? key->from : NULL; if (id != NULL) { @@ -315,7 +315,7 @@ static PointerRNA rna_ShapeKey_relative_key_get(PointerRNA *ptr) { KeyBlock *kb = (KeyBlock *)ptr->data; - return rna_object_shapekey_index_get(ptr->id.data, kb->relative); + return rna_object_shapekey_index_get(ptr->owner_id, kb->relative); } static void rna_ShapeKey_relative_key_set(PointerRNA *ptr, @@ -324,7 +324,7 @@ static void rna_ShapeKey_relative_key_set(PointerRNA *ptr, { KeyBlock *kb = (KeyBlock *)ptr->data; - kb->relative = rna_object_shapekey_index_set(ptr->id.data, value, kb->relative); + kb->relative = rna_object_shapekey_index_set(ptr->owner_id, value, kb->relative); } static void rna_ShapeKeyPoint_co_get(PointerRNA *ptr, float *values) @@ -565,7 +565,7 @@ static void rna_ShapeKey_data_begin_mixed(CollectionPropertyIterator *iter, static void rna_ShapeKey_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { - Key *key = rna_ShapeKey_find_key(ptr->id.data); + Key *key = rna_ShapeKey_find_key(ptr->owner_id); KeyBlock *kb = (KeyBlock *)ptr->data; int tot = kb->totelem, size = key->elemsize; @@ -602,7 +602,7 @@ static void rna_ShapeKey_data_begin(CollectionPropertyIterator *iter, PointerRNA static int rna_ShapeKey_data_length(PointerRNA *ptr) { - Key *key = rna_ShapeKey_find_key(ptr->id.data); + Key *key = rna_ShapeKey_find_key(ptr->owner_id); KeyBlock *kb = (KeyBlock *)ptr->data; int tot = kb->totelem; @@ -615,7 +615,7 @@ static int rna_ShapeKey_data_length(PointerRNA *ptr) static PointerRNA rna_ShapeKey_data_get(CollectionPropertyIterator *iter) { - Key *key = rna_ShapeKey_find_key(iter->parent.id.data); + Key *key = rna_ShapeKey_find_key(iter->parent.owner_id); void *ptr = rna_iterator_array_get(iter); StructRNA *type = &RNA_ShapeKeyPoint; @@ -637,7 +637,7 @@ static PointerRNA rna_ShapeKey_data_get(CollectionPropertyIterator *iter) int rna_ShapeKey_data_lookup_int(PointerRNA *ptr, int index, PointerRNA *r_ptr) { - Key *key = rna_ShapeKey_find_key(ptr->id.data); + Key *key = rna_ShapeKey_find_key(ptr->owner_id); KeyBlock *kb = (KeyBlock *)ptr->data; int elemsize = key->elemsize; char *databuf = kb->data; @@ -672,7 +672,7 @@ int rna_ShapeKey_data_lookup_int(PointerRNA *ptr, int index, PointerRNA *r_ptr) static char *rna_ShapeKey_path(PointerRNA *ptr) { KeyBlock *kb = (KeyBlock *)ptr->data; - ID *id = ptr->id.data; + ID *id = ptr->owner_id; char name_esc[sizeof(kb->name) * 2]; BLI_strescape(name_esc, kb->name, sizeof(name_esc)); @@ -687,7 +687,7 @@ static char *rna_ShapeKey_path(PointerRNA *ptr) static void rna_Key_update_data(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - Key *key = ptr->id.data; + Key *key = (Key *)ptr->owner_id; Object *ob; for (ob = bmain->objects.first; ob; ob = ob->id.next) { @@ -756,8 +756,8 @@ static int rna_ShapeKeyPoint_get_index(Key *key, KeyBlock *kb, float *point) static char *rna_ShapeKeyPoint_path(PointerRNA *ptr) { - ID *id = (ID *)ptr->id.data; - Key *key = rna_ShapeKey_find_key(ptr->id.data); + ID *id = ptr->owner_id; + Key *key = rna_ShapeKey_find_key(ptr->owner_id); KeyBlock *kb; float *point = (float *)ptr->data; @@ -1034,6 +1034,7 @@ static void rna_def_key(BlenderRNA *brna) prop = RNA_def_property(srna, "user", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON); RNA_def_property_pointer_sdna(prop, NULL, "from"); RNA_def_property_ui_text(prop, "User", "Data-block using these shape keys"); diff --git a/source/blender/makesrna/intern/rna_lattice.c b/source/blender/makesrna/intern/rna_lattice.c index 5a8223af28a..34f5b6caee1 100644 --- a/source/blender/makesrna/intern/rna_lattice.c +++ b/source/blender/makesrna/intern/rna_lattice.c @@ -49,7 +49,7 @@ static void rna_LatticePoint_co_get(PointerRNA *ptr, float *values) { - Lattice *lt = (Lattice *)ptr->id.data; + Lattice *lt = (Lattice *)ptr->owner_id; BPoint *bp = (BPoint *)ptr->data; int index = bp - lt->def; int u, v, w; @@ -63,7 +63,7 @@ static void rna_LatticePoint_co_get(PointerRNA *ptr, float *values) static void rna_LatticePoint_groups_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { - Lattice *lt = (Lattice *)ptr->id.data; + Lattice *lt = (Lattice *)ptr->owner_id; if (lt->dvert) { BPoint *bp = (BPoint *)ptr->data; @@ -95,7 +95,7 @@ static void rna_Lattice_points_begin(CollectionPropertyIterator *iter, PointerRN static void rna_Lattice_update_data(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; DEG_id_tag_update(id, 0); WM_main_add_notifier(NC_GEOM | ND_DATA, id); @@ -109,8 +109,8 @@ static void rna_Lattice_update_data_editlatt(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - ID *id = ptr->id.data; - Lattice *lt = (Lattice *)ptr->id.data; + ID *id = ptr->owner_id; + Lattice *lt = (Lattice *)ptr->owner_id; if (lt->editlatt) { Lattice *lt_em = lt->editlatt->latt; @@ -127,7 +127,7 @@ static void rna_Lattice_update_data_editlatt(Main *UNUSED(bmain), static void rna_Lattice_update_size(Main *bmain, Scene *scene, PointerRNA *ptr) { - Lattice *lt = ptr->id.data; + Lattice *lt = (Lattice *)ptr->owner_id; Object *ob; int newu, newv, neww; @@ -224,7 +224,7 @@ static void rna_Lattice_vg_name_set(PointerRNA *ptr, const char *value) /* annoying, but is a consequence of RNA structures... */ static char *rna_LatticePoint_path(PointerRNA *ptr) { - Lattice *lt = (Lattice *)ptr->id.data; + Lattice *lt = (Lattice *)ptr->owner_id; void *point = ptr->data; BPoint *points = NULL; @@ -251,7 +251,7 @@ static char *rna_LatticePoint_path(PointerRNA *ptr) static bool rna_Lattice_is_editmode_get(PointerRNA *ptr) { - Lattice *lt = (Lattice *)ptr->id.data; + Lattice *lt = (Lattice *)ptr->owner_id; return (lt->editlatt != NULL); } diff --git a/source/blender/makesrna/intern/rna_layer.c b/source/blender/makesrna/intern/rna_layer.c index c9b51707759..1ad006cbc37 100644 --- a/source/blender/makesrna/intern/rna_layer.c +++ b/source/blender/makesrna/intern/rna_layer.c @@ -152,7 +152,7 @@ static int rna_ViewLayer_objects_selected_skip(CollectionPropertyIterator *iter, static PointerRNA rna_ViewLayer_depsgraph_get(PointerRNA *ptr) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; if (GS(id->name) == ID_SCE) { Scene *scene = (Scene *)id; ViewLayer *view_layer = (ViewLayer *)ptr->data; @@ -274,7 +274,7 @@ static void rna_LayerCollection_exclude_update_recursive(ListBase *lb, const boo static void rna_LayerCollection_exclude_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; LayerCollection *lc = (LayerCollection *)ptr->data; ViewLayer *view_layer = BKE_view_layer_find_from_collection(scene, lc); @@ -294,7 +294,7 @@ static void rna_LayerCollection_exclude_update(Main *bmain, Scene *UNUSED(scene) static void rna_LayerCollection_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; LayerCollection *lc = (LayerCollection *)ptr->data; ViewLayer *view_layer = BKE_view_layer_find_from_collection(scene, lc); diff --git a/source/blender/makesrna/intern/rna_light.c b/source/blender/makesrna/intern/rna_light.c index 79ba5970007..8640c35f1b8 100644 --- a/source/blender/makesrna/intern/rna_light.c +++ b/source/blender/makesrna/intern/rna_light.c @@ -77,7 +77,7 @@ static StructRNA *rna_Light_refine(struct PointerRNA *ptr) static void rna_Light_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Light *la = ptr->id.data; + Light *la = (Light *)ptr->owner_id; DEG_id_tag_update(&la->id, 0); WM_main_add_notifier(NC_LAMP | ND_LIGHTING, la); @@ -85,7 +85,7 @@ static void rna_Light_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerR static void rna_Light_draw_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Light *la = ptr->id.data; + Light *la = (Light *)ptr->owner_id; DEG_id_tag_update(&la->id, 0); WM_main_add_notifier(NC_LAMP | ND_LIGHTING_DRAW, la); diff --git a/source/blender/makesrna/intern/rna_lightprobe.c b/source/blender/makesrna/intern/rna_lightprobe.c index b6d6fac587e..463cefdf3f0 100644 --- a/source/blender/makesrna/intern/rna_lightprobe.c +++ b/source/blender/makesrna/intern/rna_lightprobe.c @@ -43,7 +43,7 @@ static void rna_LightProbe_recalc(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - DEG_id_tag_update(ptr->id.data, ID_RECALC_GEOMETRY); + DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY); } #else @@ -212,6 +212,7 @@ static void rna_def_lightprobe(BlenderRNA *brna) RNA_def_property_struct_type(prop, "Collection"); RNA_def_property_pointer_sdna(prop, NULL, "visibility_grp"); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text( prop, "Visibility Collection", "Restrict objects visible for this probe"); RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, "rna_LightProbe_recalc"); diff --git a/source/blender/makesrna/intern/rna_linestyle.c b/source/blender/makesrna/intern/rna_linestyle.c index 936a5e6a53d..f6cfc33c82e 100644 --- a/source/blender/makesrna/intern/rna_linestyle.c +++ b/source/blender/makesrna/intern/rna_linestyle.c @@ -287,7 +287,7 @@ static char *rna_LineStyle_geometry_modifier_path(PointerRNA *ptr) static void rna_LineStyleColorModifier_name_set(PointerRNA *ptr, const char *value) { - FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->id.data; + FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->owner_id; LineStyleModifier *m = (LineStyleModifier *)ptr->data; BLI_strncpy_utf8(m->name, value, sizeof(m->name)); @@ -301,7 +301,7 @@ static void rna_LineStyleColorModifier_name_set(PointerRNA *ptr, const char *val static void rna_LineStyleAlphaModifier_name_set(PointerRNA *ptr, const char *value) { - FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->id.data; + FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->owner_id; LineStyleModifier *m = (LineStyleModifier *)ptr->data; BLI_strncpy_utf8(m->name, value, sizeof(m->name)); @@ -315,7 +315,7 @@ static void rna_LineStyleAlphaModifier_name_set(PointerRNA *ptr, const char *val static void rna_LineStyleThicknessModifier_name_set(PointerRNA *ptr, const char *value) { - FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->id.data; + FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->owner_id; LineStyleModifier *m = (LineStyleModifier *)ptr->data; BLI_strncpy_utf8(m->name, value, sizeof(m->name)); @@ -329,7 +329,7 @@ static void rna_LineStyleThicknessModifier_name_set(PointerRNA *ptr, const char static void rna_LineStyleGeometryModifier_name_set(PointerRNA *ptr, const char *value) { - FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->id.data; + FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->owner_id; LineStyleModifier *m = (LineStyleModifier *)ptr->data; BLI_strncpy_utf8(m->name, value, sizeof(m->name)); @@ -343,13 +343,13 @@ static void rna_LineStyleGeometryModifier_name_set(PointerRNA *ptr, const char * static void rna_LineStyle_mtex_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { - FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->id.data; + FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->owner_id; rna_iterator_array_begin(iter, (void *)linestyle->mtex, sizeof(MTex *), MAX_MTEX, 0, NULL); } static PointerRNA rna_LineStyle_active_texture_get(PointerRNA *ptr) { - FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->id.data; + FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->owner_id; Tex *tex; tex = give_current_linestyle_texture(linestyle); @@ -360,14 +360,14 @@ static void rna_LineStyle_active_texture_set(PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) { - FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->id.data; + FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->owner_id; set_current_linestyle_texture(linestyle, value.data); } static void rna_LineStyle_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - FreestyleLineStyle *linestyle = ptr->id.data; + FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->owner_id; DEG_id_tag_update(&linestyle->id, 0); WM_main_add_notifier(NC_LINESTYLE, linestyle); diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c index abbbd04143c..adc041174aa 100644 --- a/source/blender/makesrna/intern/rna_mask.c +++ b/source/blender/makesrna/intern/rna_mask.c @@ -58,7 +58,7 @@ static void rna_Mask_update_data(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Mask *mask = ptr->id.data; + Mask *mask = (Mask *)ptr->owner_id; WM_main_add_notifier(NC_MASK | ND_DATA, mask); DEG_id_tag_update(&mask->id, 0); @@ -147,21 +147,21 @@ static void rna_MaskParent_id_type_set(PointerRNA *ptr, int value) static void rna_Mask_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { - Mask *mask = (Mask *)ptr->id.data; + Mask *mask = (Mask *)ptr->owner_id; rna_iterator_listbase_begin(iter, &mask->masklayers, NULL); } static int rna_Mask_layer_active_index_get(PointerRNA *ptr) { - Mask *mask = (Mask *)ptr->id.data; + Mask *mask = (Mask *)ptr->owner_id; return mask->masklay_act; } static void rna_Mask_layer_active_index_set(PointerRNA *ptr, int value) { - Mask *mask = (Mask *)ptr->id.data; + Mask *mask = (Mask *)ptr->owner_id; mask->masklay_act = value; } @@ -169,7 +169,7 @@ static void rna_Mask_layer_active_index_set(PointerRNA *ptr, int value) static void rna_Mask_layer_active_index_range( PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax) { - Mask *mask = (Mask *)ptr->id.data; + Mask *mask = (Mask *)ptr->owner_id; *min = 0; *max = max_ii(0, mask->masklay_tot - 1); @@ -188,7 +188,7 @@ static char *rna_MaskLayer_path(PointerRNA *ptr) static PointerRNA rna_Mask_layer_active_get(PointerRNA *ptr) { - Mask *mask = (Mask *)ptr->id.data; + Mask *mask = (Mask *)ptr->owner_id; MaskLayer *masklay = BKE_mask_layer_active(mask); return rna_pointer_inherit_refine(ptr, &RNA_MaskLayer, masklay); @@ -198,7 +198,7 @@ static void rna_Mask_layer_active_set(PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) { - Mask *mask = (Mask *)ptr->id.data; + Mask *mask = (Mask *)ptr->owner_id; MaskLayer *masklay = (MaskLayer *)value.data; BKE_mask_layer_active_set(mask, masklay); @@ -213,7 +213,7 @@ static void rna_MaskLayer_splines_begin(CollectionPropertyIterator *iter, Pointe static void rna_MaskLayer_name_set(PointerRNA *ptr, const char *value) { - Mask *mask = (Mask *)ptr->id.data; + Mask *mask = (Mask *)ptr->owner_id; MaskLayer *masklay = (MaskLayer *)ptr->data; char oldname[sizeof(masklay->name)], newname[sizeof(masklay->name)]; @@ -351,7 +351,7 @@ static void rna_MaskSplinePoint_handle_type_set(PointerRNA *ptr, int value) { MaskSplinePoint *point = (MaskSplinePoint *)ptr->data; BezTriple *bezt = &point->bezt; - MaskSpline *spline = mask_spline_from_point((Mask *)ptr->id.data, point); + MaskSpline *spline = mask_spline_from_point((Mask *)ptr->owner_id, point); bezt->h1 = bezt->h2 = value; mask_point_check_stick(point); @@ -370,7 +370,7 @@ static void rna_MaskSplinePoint_handle_left_type_set(PointerRNA *ptr, int value) { MaskSplinePoint *point = (MaskSplinePoint *)ptr->data; BezTriple *bezt = &point->bezt; - MaskSpline *spline = mask_spline_from_point((Mask *)ptr->id.data, point); + MaskSpline *spline = mask_spline_from_point((Mask *)ptr->owner_id, point); bezt->h1 = value; mask_point_check_stick(point); @@ -389,7 +389,7 @@ static void rna_MaskSplinePoint_handle_right_type_set(PointerRNA *ptr, int value { MaskSplinePoint *point = (MaskSplinePoint *)ptr->data; BezTriple *bezt = &point->bezt; - MaskSpline *spline = mask_spline_from_point((Mask *)ptr->id.data, point); + MaskSpline *spline = mask_spline_from_point((Mask *)ptr->owner_id, point); bezt->h2 = value; mask_point_check_stick(point); diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c index 3a7e58fbaa4..885df13724f 100644 --- a/source/blender/makesrna/intern/rna_material.c +++ b/source/blender/makesrna/intern/rna_material.c @@ -39,7 +39,7 @@ const EnumPropertyItem rna_enum_ramp_blend_items[] = { {0, "", ICON_NONE, NULL, NULL}, {MA_RAMP_DARK, "DARKEN", 0, "Darken", ""}, {MA_RAMP_MULT, "MULTIPLY", 0, "Multiply", ""}, - {MA_RAMP_BURN, "BURN", 0, "Burn", ""}, + {MA_RAMP_BURN, "BURN", 0, "Color Burn", ""}, {0, "", ICON_NONE, NULL, NULL}, {MA_RAMP_LIGHT, "LIGHTEN", 0, "Lighten", ""}, {MA_RAMP_SCREEN, "SCREEN", 0, "Screen", ""}, @@ -91,7 +91,7 @@ const EnumPropertyItem rna_enum_ramp_blend_items[] = { static void rna_Material_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Material *ma = ptr->id.data; + Material *ma = (Material *)ptr->owner_id; DEG_id_tag_update(&ma->id, ID_RECALC_SHADING); WM_main_add_notifier(NC_MATERIAL | ND_SHADING, ma); @@ -101,7 +101,7 @@ static void rna_Material_update_previews(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Material *ma = ptr->id.data; + Material *ma = (Material *)ptr->owner_id; if (ma->nodetree) { BKE_node_preview_clear_tree(ma->nodetree); @@ -112,7 +112,7 @@ static void rna_Material_update_previews(Main *UNUSED(bmain), static void rna_MaterialGpencil_update(Main *bmain, Scene *scene, PointerRNA *ptr) { - Material *ma = ptr->id.data; + Material *ma = (Material *)ptr->owner_id; rna_Material_update(bmain, scene, ptr); WM_main_add_notifier(NC_GPENCIL | ND_DATA, ma); @@ -120,7 +120,7 @@ static void rna_MaterialGpencil_update(Main *bmain, Scene *scene, PointerRNA *pt static void rna_MaterialGpencil_nopreview_update(Main *bmain, Scene *scene, PointerRNA *ptr) { - Material *ma = ptr->id.data; + Material *ma = (Material *)ptr->owner_id; rna_Material_update(bmain, scene, ptr); WM_main_add_notifier(NC_GPENCIL | ND_DATA, ma); @@ -128,7 +128,7 @@ static void rna_MaterialGpencil_nopreview_update(Main *bmain, Scene *scene, Poin static void rna_Material_draw_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Material *ma = ptr->id.data; + Material *ma = (Material *)ptr->owner_id; DEG_id_tag_update(&ma->id, ID_RECALC_SHADING); WM_main_add_notifier(NC_MATERIAL | ND_SHADING_DRAW, ma); @@ -146,7 +146,7 @@ static void rna_Material_active_paint_texture_index_update(Main *bmain, PointerRNA *ptr) { bScreen *sc; - Material *ma = ptr->id.data; + Material *ma = (Material *)ptr->owner_id; if (ma->use_nodes && ma->nodetree) { struct bNode *node = BKE_texpaint_slot_material_find_node(ma, ma->paint_active_slot); @@ -305,7 +305,7 @@ static bool rna_is_grease_pencil_get(PointerRNA *ptr) static void rna_gpcolordata_uv_update(Main *bmain, Scene *scene, PointerRNA *ptr) { /* update all uv strokes of this color */ - Material *ma = ptr->id.data; + Material *ma = (Material *)ptr->owner_id; ED_gpencil_update_color_uv(bmain, ma); rna_MaterialGpencil_update(bmain, scene, ptr); @@ -421,12 +421,14 @@ static void rna_def_material_display(StructRNA *srna) prop = RNA_def_property(srna, "diffuse_color", PROP_FLOAT, PROP_COLOR); RNA_def_property_float_sdna(prop, NULL, "r"); RNA_def_property_array(prop, 4); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Diffuse Color", "Diffuse color of the material"); RNA_def_property_update(prop, 0, "rna_Material_draw_update"); prop = RNA_def_property(srna, "specular_color", PROP_FLOAT, PROP_COLOR); RNA_def_property_float_sdna(prop, NULL, "specr"); RNA_def_property_array(prop, 3); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Specular Color", "Specular color of the material"); RNA_def_property_update(prop, 0, "rna_Material_draw_update"); @@ -434,6 +436,7 @@ static void rna_def_material_display(StructRNA *srna) RNA_def_property_float_sdna(prop, NULL, "roughness"); RNA_def_property_float_default(prop, 0.25f); RNA_def_property_range(prop, 0, 1); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Roughness", "Roughness of the material"); RNA_def_property_update(prop, 0, "rna_Material_draw_update"); @@ -441,12 +444,14 @@ static void rna_def_material_display(StructRNA *srna) RNA_def_property_float_sdna(prop, NULL, "spec"); RNA_def_property_float_default(prop, 0.5f); RNA_def_property_range(prop, 0, 1); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Specular", "How intense (bright) the specular reflection is"); RNA_def_property_update(prop, 0, "rna_Material_draw_update"); prop = RNA_def_property(srna, "metallic", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "metallic"); RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Metallic", "Amount of mirror reflection for raytrace"); RNA_def_property_update(prop, 0, "rna_Material_update"); @@ -778,6 +783,7 @@ static void rna_def_material_greasepencil(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "sima"); RNA_def_property_pointer_funcs(prop, NULL, "rna_GpencilColorData_stroke_image_set", NULL, NULL); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Image", ""); RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update"); @@ -800,6 +806,7 @@ static void rna_def_material_greasepencil(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "ima"); RNA_def_property_pointer_funcs(prop, NULL, "rna_GpencilColorData_fill_image_set", NULL, NULL); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Image", ""); RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update"); diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 99428fd872b..704bb11fc8a 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -80,7 +80,7 @@ const EnumPropertyItem rna_enum_mesh_delimit_mode_items[] = { static Mesh *rna_mesh(PointerRNA *ptr) { - Mesh *me = (Mesh *)ptr->id.data; + Mesh *me = (Mesh *)ptr->owner_id; return me; } @@ -146,7 +146,7 @@ static void rna_cd_layer_name_set(CustomData *cdata, CustomDataLayer *cdl, const static CustomData *rna_cd_from_layer(PointerRNA *ptr, CustomDataLayer *cdl) { /* find out where we come from by */ - Mesh *me = ptr->id.data; + Mesh *me = (Mesh *)ptr->owner_id; CustomData *cd; /* rely on negative values wrapping */ @@ -202,7 +202,7 @@ static bool rna_Mesh_has_custom_normals_get(PointerRNA *ptr) static void rna_Mesh_update_data(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; /* cheating way for importers to avoid slow updates */ if (id->us > 0) { @@ -226,7 +226,7 @@ static void rna_Mesh_update_data_edit_active_color(Main *bmain, Scene *scene, Po } static void rna_Mesh_update_select(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; /* cheating way for importers to avoid slow updates */ if (id->us > 0) { WM_main_add_notifier(NC_GEOM | ND_SELECT, id); @@ -235,7 +235,7 @@ static void rna_Mesh_update_select(Main *UNUSED(bmain), Scene *UNUSED(scene), Po void rna_Mesh_update_draw(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; /* cheating way for importers to avoid slow updates */ if (id->us > 0) { WM_main_add_notifier(NC_GEOM | ND_DATA, id); @@ -403,7 +403,7 @@ static void rna_MeshPolygon_center_get(PointerRNA *ptr, float *values) static float rna_MeshPolygon_area_get(PointerRNA *ptr) { - Mesh *me = (Mesh *)ptr->id.data; + Mesh *me = (Mesh *)ptr->owner_id; MPoly *mp = (MPoly *)ptr->data; return BKE_mesh_calc_poly_area(mp, me->mloop + mp->loopstart, me->mvert); @@ -571,7 +571,7 @@ static int rna_CustomDataLayer_clone_get(PointerRNA *ptr, CustomData *data, int static void rna_CustomDataLayer_active_set( PointerRNA *ptr, CustomData *data, int value, int type, int render) { - Mesh *me = ptr->id.data; + Mesh *me = (Mesh *)ptr->owner_id; int n = (((CustomDataLayer *)ptr->data) - data->layers) - CustomData_get_layer_index(data, type); if (value == 0) { @@ -651,14 +651,6 @@ static void rna_MPoly_freestyle_face_mark_set(PointerRNA *ptr, int value) } } -/* Generic UV rename! */ -static void rna_MeshUVLayer_name_set(PointerRNA *ptr, const char *name) -{ - char buf[MAX_CUSTOMDATA_LAYER_NAME]; - BLI_strncpy_utf8(buf, name, MAX_CUSTOMDATA_LAYER_NAME); - BKE_mesh_uv_cdlayer_rename(rna_mesh(ptr), ((CustomDataLayer *)ptr->data)->name, buf, true); -} - /* uv_layers */ DEFINE_CUSTOMDATA_LAYER_COLLECTION(uv_layer, ldata, CD_MLOOPUV) @@ -1378,7 +1370,7 @@ static int rna_MeshPolygonStringPropertyLayer_data_length(PointerRNA *ptr) } /* XXX, we dont have proper byte string support yet, so for now use the (bytes + 1) - * bmesh API exposes correct python/bytestring access */ + * bmesh API exposes correct python/byte-string access. */ void rna_MeshStringProperty_s_get(PointerRNA *ptr, char *value) { MStringProperty *ms = (MStringProperty *)ptr->data; @@ -1941,7 +1933,7 @@ static void rna_def_mloopuv(BlenderRNA *brna) prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_struct_name_property(srna, prop); - RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MeshUVLayer_name_set"); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MeshLoopLayer_name_set"); RNA_def_property_ui_text(prop, "Name", "Name of UV map"); RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); @@ -2789,6 +2781,7 @@ static void rna_def_mesh(BlenderRNA *brna) prop = RNA_def_property(srna, "texture_mesh", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "texcomesh"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text( prop, "Texture Mesh", @@ -3053,6 +3046,7 @@ static void rna_def_mesh(BlenderRNA *brna) prop = RNA_def_property(srna, "texco_mesh", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "texcomesh"); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text( prop, "Texture Space Mesh", "Derive texture coordinates from another mesh"); diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c index 283590fc529..0b3a7802082 100644 --- a/source/blender/makesrna/intern/rna_mesh_api.c +++ b/source/blender/makesrna/intern/rna_mesh_api.c @@ -311,11 +311,6 @@ void RNA_api_mesh(StructRNA *srna) 0, "Calculate Loose Edges", "Calculate the loose state of each edge"); - RNA_def_boolean(func, - "calc_loop_triangles", - 0, - "Calculate Triangules", - "Force recalculation of triangle tessellation"); RNA_def_function_flag(func, FUNC_USE_CONTEXT); RNA_def_function(srna, "update_gpu_tag", "rna_Mesh_update_gpu_tag"); diff --git a/source/blender/makesrna/intern/rna_meta.c b/source/blender/makesrna/intern/rna_meta.c index 743bac2b709..451bdda45f5 100644 --- a/source/blender/makesrna/intern/rna_meta.c +++ b/source/blender/makesrna/intern/rna_meta.c @@ -89,7 +89,7 @@ static void rna_Meta_texspace_size_set(PointerRNA *ptr, const float *values) static void rna_MetaBall_update_data(Main *bmain, Scene *scene, PointerRNA *ptr) { - MetaBall *mb = ptr->id.data; + MetaBall *mb = (MetaBall *)ptr->owner_id; Object *ob; /* cheating way for importers to avoid slow updates */ @@ -158,13 +158,13 @@ static void rna_MetaBall_elements_clear(MetaBall *mb) static bool rna_Meta_is_editmode_get(PointerRNA *ptr) { - MetaBall *mb = ptr->id.data; + MetaBall *mb = (MetaBall *)ptr->owner_id; return (mb->editelems != NULL); } static char *rna_MetaElement_path(PointerRNA *ptr) { - MetaBall *mb = ptr->id.data; + MetaBall *mb = (MetaBall *)ptr->owner_id; MetaElem *ml = ptr->data; int index = -1; diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index cae9e2a8c9b..18cf57c5624 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -609,8 +609,8 @@ static void rna_Modifier_name_set(PointerRNA *ptr, const char *value) BLI_strncpy_utf8(md->name, value, sizeof(md->name)); /* make sure the name is truly unique */ - if (ptr->id.data) { - Object *ob = ptr->id.data; + if (ptr->owner_id) { + Object *ob = (Object *)ptr->owner_id; modifier_unique_name(&ob->modifiers, md); } @@ -629,8 +629,8 @@ static char *rna_Modifier_path(PointerRNA *ptr) static void rna_Modifier_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - DEG_id_tag_update(ptr->id.data, ID_RECALC_GEOMETRY); - WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ptr->id.data); + DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY); + WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ptr->owner_id); } static void rna_Modifier_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr) @@ -737,7 +737,7 @@ static void modifier_object_set(Object *self, Object **ob_p, int type, PointerRN PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) \ { \ _type##ModifierData *tmd = (_type##ModifierData *)ptr->data; \ - modifier_object_set(ptr->id.data, &tmd->_prop, _obtype, value); \ + modifier_object_set((Object *)ptr->owner_id, &tmd->_prop, _obtype, value); \ } RNA_MOD_OBJECT_SET(Armature, object, OB_ARMATURE); @@ -760,7 +760,7 @@ static void rna_HookModifier_object_set(PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) { - Object *owner = (Object *)ptr->id.data; + Object *owner = (Object *)ptr->owner_id; HookModifierData *hmd = ptr->data; Object *ob = (Object *)value.data; @@ -769,9 +769,50 @@ static void rna_HookModifier_object_set(PointerRNA *ptr, BKE_object_modifier_hook_reset(owner, hmd); } +static bool rna_HookModifier_object_override_apply(Main *UNUSED(bmain), + PointerRNA *ptr_dst, + PointerRNA *ptr_src, + PointerRNA *ptr_storage, + PropertyRNA *prop_dst, + PropertyRNA *prop_src, + PropertyRNA *UNUSED(prop_storage), + const int len_dst, + const int len_src, + const int len_storage, + PointerRNA *UNUSED(ptr_item_dst), + PointerRNA *UNUSED(ptr_item_src), + PointerRNA *UNUSED(ptr_item_storage), + IDOverrideLibraryPropertyOperation *opop) +{ + BLI_assert(len_dst == len_src && (!ptr_storage || len_dst == len_storage) && len_dst == 0); + BLI_assert(opop->operation == IDOVERRIDE_LIBRARY_OP_REPLACE && + "Unsupported RNA override operation on Hook modifier target objet pointer"); + UNUSED_VARS_NDEBUG(ptr_storage, len_dst, len_src, len_storage, opop); + + /* We need a special handling here because setting hook target resets invert parent matrix, + * which is evil in our case. */ + HookModifierData *hmd = ptr_dst->data; + Object *owner = (Object *)ptr_dst->owner_id; + Object *target_dst = RNA_property_pointer_get(ptr_dst, prop_dst).data; + Object *target_src = RNA_property_pointer_get(ptr_src, prop_src).data; + + BLI_assert(target_dst == hmd->object); + + if (target_src == target_dst) { + return false; + } + + hmd->object = target_src; + if (target_src == NULL) { + /* The only case where we do want default behavior (with matrix reset). */ + BKE_object_modifier_hook_reset(owner, hmd); + } + return true; +} + static void rna_HookModifier_subtarget_set(PointerRNA *ptr, const char *value) { - Object *owner = (Object *)ptr->id.data; + Object *owner = (Object *)ptr->owner_id; HookModifierData *hmd = ptr->data; BLI_strncpy(hmd->subtarget, value, sizeof(hmd->subtarget)); @@ -858,7 +899,7 @@ static void rna_UVProjector_object_set(PointerRNA *ptr, static void rna_Smoke_set_type(Main *bmain, Scene *scene, PointerRNA *ptr) { SmokeModifierData *smd = (SmokeModifierData *)ptr->data; - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; /* nothing changed */ if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) { @@ -885,7 +926,7 @@ static void rna_Smoke_set_type(Main *bmain, Scene *scene, PointerRNA *ptr) static void rna_MultiresModifier_type_set(PointerRNA *ptr, int value) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; MultiresModifierData *mmd = (MultiresModifierData *)ptr->data; multires_force_update(ob); @@ -903,7 +944,7 @@ static void rna_MultiresModifier_level_range( static bool rna_MultiresModifier_external_get(PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; Mesh *me = ob->data; return CustomData_external_test(&me->ldata, CD_MDISPS); @@ -911,7 +952,7 @@ static bool rna_MultiresModifier_external_get(PointerRNA *ptr) static void rna_MultiresModifier_filepath_get(PointerRNA *ptr, char *value) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; CustomDataExternal *external = ((Mesh *)ob->data)->ldata.external; BLI_strncpy(value, (external) ? external->filename : "", sizeof(external->filename)); @@ -919,7 +960,7 @@ static void rna_MultiresModifier_filepath_get(PointerRNA *ptr, char *value) static void rna_MultiresModifier_filepath_set(PointerRNA *ptr, const char *value) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; CustomDataExternal *external = ((Mesh *)ob->data)->ldata.external; if (external && !STREQ(external->filename, value)) { @@ -930,7 +971,7 @@ static void rna_MultiresModifier_filepath_set(PointerRNA *ptr, const char *value static int rna_MultiresModifier_filepath_length(PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; CustomDataExternal *external = ((Mesh *)ob->data)->ldata.external; return strlen((external) ? external->filename : ""); @@ -955,19 +996,19 @@ static bool rna_MeshDeformModifier_is_bound_get(PointerRNA *ptr) static PointerRNA rna_SoftBodyModifier_settings_get(PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; return rna_pointer_inherit_refine(ptr, &RNA_SoftBodySettings, ob->soft); } static PointerRNA rna_SoftBodyModifier_point_cache_get(PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; return rna_pointer_inherit_refine(ptr, &RNA_PointCache, ob->soft->shared->pointcache); } static PointerRNA rna_CollisionModifier_settings_get(PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; return rna_pointer_inherit_refine(ptr, &RNA_CollisionSettings, ob->pd); } @@ -1574,6 +1615,7 @@ static void rna_def_modifier_generic_map_info(StructRNA *srna) prop = RNA_def_property(srna, "texture", PROP_POINTER, PROP_NONE); RNA_def_property_ui_text(prop, "Texture", ""); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); prop = RNA_def_property(srna, "texture_coords", PROP_ENUM, PROP_NONE); @@ -1593,6 +1635,7 @@ static void rna_def_modifier_generic_map_info(StructRNA *srna) RNA_def_property_ui_text( prop, "Texture Coordinate Object", "Object to set the texture coordinates"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); } @@ -1609,11 +1652,13 @@ static void rna_def_modifier_warp(BlenderRNA *brna) prop = RNA_def_property(srna, "object_from", PROP_POINTER, PROP_NONE); RNA_def_property_ui_text(prop, "From", "Object to transform from"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); prop = RNA_def_property(srna, "object_to", PROP_POINTER, PROP_NONE); RNA_def_property_ui_text(prop, "To", "Object to transform to"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE); @@ -1729,6 +1774,7 @@ static void rna_def_modifier_lattice(BlenderRNA *brna) RNA_def_property_pointer_funcs( prop, NULL, "rna_LatticeModifier_object_set", NULL, "rna_Lattice_object_poll"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); @@ -1772,6 +1818,7 @@ static void rna_def_modifier_curve(BlenderRNA *brna) RNA_def_property_pointer_funcs( prop, NULL, "rna_CurveModifier_object_set", NULL, "rna_Curve_object_poll"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_CurveModifier_dependency_update"); prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); @@ -1930,6 +1977,7 @@ static void rna_def_modifier_mirror(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "mirror_ob"); RNA_def_property_ui_text(prop, "Mirror Object", "Object to use as mirror"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); } @@ -2028,7 +2076,7 @@ static void rna_def_modifier_decimate(BlenderRNA *brna) prop = RNA_def_property(srna, "use_dissolve_boundaries", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_DECIM_FLAG_ALL_BOUNDARY_VERTS); RNA_def_property_ui_text( - prop, "All Boundaries", "Dissolve all vertices inbetween face boundaries (planar only)"); + prop, "All Boundaries", "Dissolve all vertices in between face boundaries (planar only)"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); prop = RNA_def_property(srna, "delimit", PROP_ENUM, PROP_NONE); @@ -2139,6 +2187,7 @@ static void rna_def_modifier_wave(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "objectcenter"); RNA_def_property_ui_text(prop, "Start Position Object", "Object which defines the wave center"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); @@ -2294,6 +2343,8 @@ static void rna_def_modifier_hook(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Object", "Parent Object for hook, also recalculates and clears offset"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + RNA_def_property_override_funcs(prop, NULL, NULL, "rna_HookModifier_object_override_apply"); RNA_def_property_pointer_funcs(prop, NULL, "rna_HookModifier_object_set", NULL, NULL); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); @@ -2394,6 +2445,7 @@ static void rna_def_modifier_boolean(BlenderRNA *brna) RNA_def_property_pointer_funcs( prop, NULL, "rna_BooleanModifier_object_set", NULL, "rna_Mesh_object_poll"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); prop = RNA_def_property(srna, "operation", PROP_ENUM, PROP_NONE); @@ -2482,6 +2534,7 @@ static void rna_def_modifier_array(BlenderRNA *brna) RNA_def_property_pointer_funcs( prop, NULL, "rna_ArrayModifier_curve_ob_set", NULL, "rna_Curve_object_poll"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_ArrayModifier_dependency_update"); /* Offset parameters */ @@ -2545,6 +2598,7 @@ static void rna_def_modifier_array(BlenderRNA *brna) "Use the location and rotation of another object to determine the distance and " "rotational change between arrayed items"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); /* Caps */ @@ -2553,6 +2607,7 @@ static void rna_def_modifier_array(BlenderRNA *brna) RNA_def_property_pointer_funcs( prop, NULL, "rna_ArrayModifier_start_cap_set", NULL, "rna_Mesh_object_poll"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Modifier_update"); prop = RNA_def_property(srna, "end_cap", PROP_POINTER, PROP_NONE); @@ -2560,6 +2615,7 @@ static void rna_def_modifier_array(BlenderRNA *brna) RNA_def_property_pointer_funcs( prop, NULL, "rna_ArrayModifier_end_cap_set", NULL, "rna_Mesh_object_poll"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); prop = RNA_def_property(srna, "offset_u", PROP_FLOAT, PROP_FACTOR); @@ -2772,6 +2828,7 @@ static void rna_def_modifier_uvproject(BlenderRNA *brna) RNA_def_property_pointer_funcs( prop, "rna_UVProjector_object_get", "rna_UVProjector_object_set", NULL, NULL); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Object", "Object to use as projector transform"); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); } @@ -3016,6 +3073,7 @@ static void rna_def_modifier_cast(BlenderRNA *brna) "Control object: if available, its location determines the center of the effect"); RNA_def_property_pointer_funcs(prop, NULL, "rna_CastModifier_object_set", NULL, NULL); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); prop = RNA_def_property(srna, "use_x", PROP_BOOLEAN, PROP_NONE); @@ -3098,6 +3156,7 @@ static void rna_def_modifier_meshdeform(BlenderRNA *brna) RNA_def_property_pointer_funcs( prop, NULL, "rna_MeshDeformModifier_object_set", NULL, "rna_Mesh_object_poll"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); prop = RNA_def_property(srna, "is_bound", PROP_BOOLEAN, PROP_NONE); @@ -3183,6 +3242,7 @@ static void rna_def_modifier_particleinstance(BlenderRNA *brna) RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Mesh_object_poll"); RNA_def_property_ui_text(prop, "Object", "Object that has the particle system"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); prop = RNA_def_property(srna, "particle_system_index", PROP_INT, PROP_NONE); @@ -3750,6 +3810,7 @@ static void rna_def_modifier_shrinkwrap(BlenderRNA *brna) RNA_def_property_pointer_funcs( prop, NULL, "rna_ShrinkwrapModifier_target_set", NULL, "rna_Mesh_object_poll"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); prop = RNA_def_property(srna, "auxiliary_target", PROP_POINTER, PROP_NONE); @@ -3758,6 +3819,7 @@ static void rna_def_modifier_shrinkwrap(BlenderRNA *brna) RNA_def_property_pointer_funcs( prop, NULL, "rna_ShrinkwrapModifier_auxTarget_set", NULL, "rna_Mesh_object_poll"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); @@ -3875,6 +3937,7 @@ static void rna_def_modifier_mask(BlenderRNA *brna) RNA_def_property_pointer_funcs( prop, NULL, "rna_MaskModifier_ob_arm_set", NULL, "rna_Armature_object_poll"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); @@ -3953,6 +4016,7 @@ static void rna_def_modifier_simpledeform(BlenderRNA *brna) prop = RNA_def_property(srna, "origin", PROP_POINTER, PROP_NONE); RNA_def_property_ui_text(prop, "Origin", "Offset the origin and orientation of the deformation"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_NONE); @@ -4146,6 +4210,7 @@ static void rna_def_modifier_screw(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "ob_axis"); RNA_def_property_ui_text(prop, "Object", "Object to define the screw axis"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); prop = RNA_def_property(srna, "steps", PROP_INT, PROP_UNSIGNED); @@ -4272,6 +4337,7 @@ static void rna_def_modifier_uvwarp(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "object_src"); RNA_def_property_ui_text(prop, "Object From", "Object defining offset"); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); prop = RNA_def_property(srna, "bone_from", PROP_STRING, PROP_NONE); @@ -4283,6 +4349,7 @@ static void rna_def_modifier_uvwarp(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "object_dst"); RNA_def_property_ui_text(prop, "Object To", "Object defining offset"); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); prop = RNA_def_property(srna, "bone_to", PROP_STRING, PROP_NONE); @@ -4350,6 +4417,7 @@ static void rna_def_modifier_weightvg_mask(BlenderRNA *UNUSED(brna), prop = RNA_def_property(srna, "mask_texture", PROP_POINTER, PROP_NONE); RNA_def_property_ui_text(prop, "Masking Tex", "Masking texture"); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); prop = RNA_def_property(srna, "mask_tex_use_channel", PROP_ENUM, PROP_NONE); @@ -4378,6 +4446,7 @@ static void rna_def_modifier_weightvg_mask(BlenderRNA *UNUSED(brna), "Which object to take texture " "coordinates from"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); } @@ -4647,6 +4716,7 @@ static void rna_def_modifier_weightvgproximity(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "proximity_ob_target"); RNA_def_property_ui_text(prop, "Target Object", "Object to calculate vertices distances from"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); prop = RNA_def_property(srna, "min_dist", PROP_FLOAT, PROP_DISTANCE); @@ -5210,6 +5280,7 @@ static void rna_def_modifier_meshseqcache(BlenderRNA *brna) RNA_def_property_struct_type(prop, "CacheFile"); RNA_def_property_ui_text(prop, "Cache File", ""); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); prop = RNA_def_property(srna, "object_path", PROP_STRING, PROP_NONE); @@ -5411,6 +5482,7 @@ static void rna_def_modifier_datatransfer(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "ob_source"); RNA_def_property_ui_text(prop, "Source Object", "Object to transfer data from"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_pointer_funcs( prop, NULL, "rna_DataTransferModifier_ob_source_set", NULL, "rna_Mesh_object_poll"); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); @@ -5816,6 +5888,7 @@ static void rna_def_modifier_normaledit(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Target", "Target object used to affect normals"); RNA_def_property_pointer_funcs(prop, NULL, "rna_NormalEditModifier_target_set", NULL, NULL); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); prop = RNA_def_property(srna, "use_direction_parallel", PROP_BOOLEAN, PROP_NONE); @@ -5843,6 +5916,7 @@ static void rna_def_modifier_surfacedeform(BlenderRNA *brna) RNA_def_property_pointer_funcs( prop, NULL, "rna_SurfaceDeformModifier_target_set", NULL, "rna_Mesh_object_poll"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); prop = RNA_def_property(srna, "falloff", PROP_FLOAT, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_movieclip.c b/source/blender/makesrna/intern/rna_movieclip.c index 10e19b92dda..9bfa93ceba5 100644 --- a/source/blender/makesrna/intern/rna_movieclip.c +++ b/source/blender/makesrna/intern/rna_movieclip.c @@ -53,14 +53,14 @@ static void rna_MovieClip_reload_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; DEG_id_tag_update(&clip->id, ID_RECALC_SOURCE); } static void rna_MovieClip_size_get(PointerRNA *ptr, int *values) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; values[0] = clip->lastsize[0]; values[1] = clip->lastsize[1]; @@ -68,13 +68,13 @@ static void rna_MovieClip_size_get(PointerRNA *ptr, int *values) static float rna_MovieClip_fps_get(PointerRNA *ptr) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; return BKE_movieclip_get_fps(clip); } static void rna_MovieClip_use_proxy_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; BKE_movieclip_clear_cache(clip); BKE_sequence_invalidate_movieclip_strips(bmain, clip); } @@ -83,7 +83,7 @@ static void rna_MovieClipUser_proxy_render_settings_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - ID *id = (ID *)ptr->id.data; + ID *id = ptr->owner_id; MovieClipUser *user = (MovieClipUser *)ptr->data; /* when changing render settings of space clip user diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c index 6f55fb4e24c..97cab783aed 100644 --- a/source/blender/makesrna/intern/rna_nla.c +++ b/source/blender/makesrna/intern/rna_nla.c @@ -65,8 +65,8 @@ static void rna_NlaStrip_name_set(PointerRNA *ptr, const char *value) BLI_strncpy_utf8(data->name, value, sizeof(data->name)); /* validate if there's enough info to do so */ - if (ptr->id.data) { - AnimData *adt = BKE_animdata_from_id(ptr->id.data); + if (ptr->owner_id) { + AnimData *adt = BKE_animdata_from_id(ptr->owner_id); BKE_nlastrip_validate_name(adt, data); } } @@ -74,7 +74,7 @@ static void rna_NlaStrip_name_set(PointerRNA *ptr, const char *value) static char *rna_NlaStrip_path(PointerRNA *ptr) { NlaStrip *strip = (NlaStrip *)ptr->data; - AnimData *adt = BKE_animdata_from_id(ptr->id.data); + AnimData *adt = BKE_animdata_from_id(ptr->owner_id); /* if we're attached to AnimData, try to resolve path back to AnimData */ if (adt) { @@ -103,7 +103,7 @@ static char *rna_NlaStrip_path(PointerRNA *ptr) static void rna_NlaStrip_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; ANIM_id_update(bmain, id); } @@ -122,9 +122,9 @@ static void rna_NlaStrip_transform_update(Main *bmain, Scene *scene, PointerRNA BKE_nlameta_flush_transforms(strip); /* set the flag */ - if ((strip->flag & NLASTRIP_FLAG_AUTO_BLENDS) && ptr->id.data) { + if ((strip->flag & NLASTRIP_FLAG_AUTO_BLENDS) && ptr->owner_id) { /* validate state to ensure that auto-blend gets applied immediately */ - IdAdtTemplate *iat = (IdAdtTemplate *)ptr->id.data; + IdAdtTemplate *iat = (IdAdtTemplate *)ptr->owner_id; if (iat->adt) { BKE_nla_validate_state(iat->adt); @@ -274,8 +274,8 @@ static void rna_NlaStrip_use_auto_blend_set(PointerRNA *ptr, bool value) data->flag |= NLASTRIP_FLAG_AUTO_BLENDS; /* validate state to ensure that auto-blend gets applied immediately */ - if (ptr->id.data) { - IdAdtTemplate *iat = (IdAdtTemplate *)ptr->id.data; + if (ptr->owner_id) { + IdAdtTemplate *iat = (IdAdtTemplate *)ptr->owner_id; if (iat->adt) { BKE_nla_validate_state(iat->adt); @@ -298,8 +298,8 @@ static int rna_NlaStrip_action_editable(PointerRNA *ptr, const char **UNUSED(r_i NlaStrip *strip = (NlaStrip *)ptr->data; /* strip actions shouldn't be editable if NLA tweakmode is on */ - if (ptr->id.data) { - AnimData *adt = BKE_animdata_from_id(ptr->id.data); + if (ptr->owner_id) { + AnimData *adt = BKE_animdata_from_id(ptr->owner_id); if (adt) { /* active action is only editable when it is not a tweaking strip */ @@ -475,7 +475,7 @@ static void rna_NlaStrip_remove( static void rna_NlaTrack_solo_set(PointerRNA *ptr, bool value) { NlaTrack *data = (NlaTrack *)ptr->data; - AnimData *adt = BKE_animdata_from_id(ptr->id.data); + AnimData *adt = BKE_animdata_from_id(ptr->owner_id); NlaTrack *nt; if (data == NULL) { diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index c9815a6cc37..0909aa42a4d 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -63,10 +63,13 @@ const EnumPropertyItem rna_enum_node_socket_in_out_items[] = { {SOCK_IN, "IN", 0, "Input", ""}, {SOCK_OUT, "OUT", 0, "Output", ""}, {0, NULL, 0, NULL, NULL}}; #ifndef RNA_RUNTIME -static const EnumPropertyItem rna_enum_node_socket_draw_shape_items[] = { - {SOCK_DRAW_SHAPE_CIRCLE, "CIRCLE", 0, "Circle", ""}, - {SOCK_DRAW_SHAPE_SQUARE, "SQUARE", 0, "Square", ""}, - {SOCK_DRAW_SHAPE_DIAMOND, "DIAMOND", 0, "Diamond", ""}, +static const EnumPropertyItem rna_enum_node_socket_display_shape_items[] = { + {SOCK_DISPLAY_SHAPE_CIRCLE, "CIRCLE", 0, "Circle", ""}, + {SOCK_DISPLAY_SHAPE_SQUARE, "SQUARE", 0, "Square", ""}, + {SOCK_DISPLAY_SHAPE_DIAMOND, "DIAMOND", 0, "Diamond", ""}, + {SOCK_DISPLAY_SHAPE_CIRCLE_DOT, "CIRCLE_DOT", 0, "Circle with inner dot", ""}, + {SOCK_DISPLAY_SHAPE_SQUARE_DOT, "SQUARE_DOT", 0, "Square with inner dot", ""}, + {SOCK_DISPLAY_SHAPE_DIAMOND_DOT, "DIAMOND_DOT", 0, "Diamond with inner dot", ""}, {0, NULL, 0, NULL, NULL}}; static const EnumPropertyItem node_socket_type_items[] = { @@ -100,44 +103,81 @@ static const EnumPropertyItem node_chunksize_items[] = { #endif const EnumPropertyItem rna_enum_node_math_items[] = { - {NODE_MATH_ADD, "ADD", 0, "Add", ""}, - {NODE_MATH_SUB, "SUBTRACT", 0, "Subtract", ""}, - {NODE_MATH_MUL, "MULTIPLY", 0, "Multiply", ""}, - {NODE_MATH_DIVIDE, "DIVIDE", 0, "Divide", ""}, + {NODE_MATH_ADD, "ADD", 0, "Add", "A + B"}, + {NODE_MATH_SUBTRACT, "SUBTRACT", 0, "Subtract", "A - B"}, + {NODE_MATH_MULTIPLY, "MULTIPLY", 0, "Multiply", "A * B"}, + {NODE_MATH_DIVIDE, "DIVIDE", 0, "Divide", "A / B"}, {0, "", ICON_NONE, NULL, NULL}, - {NODE_MATH_POW, "POWER", 0, "Power", ""}, - {NODE_MATH_LOG, "LOGARITHM", 0, "Logarithm", ""}, - {NODE_MATH_SQRT, "SQRT", 0, "Square Root", ""}, - {NODE_MATH_ABS, "ABSOLUTE", 0, "Absolute", ""}, + {NODE_MATH_POWER, "POWER", 0, "Power", "A power B"}, + {NODE_MATH_LOGARITHM, "LOGARITHM", 0, "Logarithm", "Logarithm A base B"}, + {NODE_MATH_SQRT, "SQRT", 0, "Square Root", "Square root of A"}, + {NODE_MATH_ABSOLUTE, "ABSOLUTE", 0, "Absolute", "Magnitude of A"}, {0, "", ICON_NONE, NULL, NULL}, - {NODE_MATH_MIN, "MINIMUM", 0, "Minimum", ""}, - {NODE_MATH_MAX, "MAXIMUM", 0, "Maximum", ""}, - {NODE_MATH_LESS, "LESS_THAN", 0, "Less Than", ""}, - {NODE_MATH_GREATER, "GREATER_THAN", 0, "Greater Than", ""}, + {NODE_MATH_MINIMUM, "MINIMUM", 0, "Minimum", "The minimum from A and B"}, + {NODE_MATH_MAXIMUM, "MAXIMUM", 0, "Maximum", "The maximum from A and B"}, + {NODE_MATH_LESS_THAN, "LESS_THAN", 0, "Less Than", "1 if A < B else 0"}, + {NODE_MATH_GREATER_THAN, "GREATER_THAN", 0, "Greater Than", "1 if A > B else 0"}, {0, "", ICON_NONE, NULL, NULL}, - {NODE_MATH_ROUND, "ROUND", 0, "Round", ""}, - {NODE_MATH_FLOOR, "FLOOR", 0, "Floor", ""}, - {NODE_MATH_CEIL, "CEIL", 0, "Ceil", ""}, - {NODE_MATH_FRACT, "FRACT", 0, "Fract", ""}, - {NODE_MATH_MOD, "MODULO", 0, "Modulo", ""}, + {NODE_MATH_ROUND, + "ROUND", + 0, + "Round", + "Round A to the nearest integer. Round upward if the fraction part is 0.5"}, + {NODE_MATH_FLOOR, "FLOOR", 0, "Floor", "The largest integer smaller than or equal A"}, + {NODE_MATH_CEIL, "CEIL", 0, "Ceil", "The smallest integer greater than or equal A"}, + {NODE_MATH_FRACTION, "FRACT", 0, "Fraction", "The fraction part of A"}, + {NODE_MATH_MODULO, "MODULO", 0, "Modulo", "A mod B"}, {0, "", ICON_NONE, NULL, NULL}, - {NODE_MATH_SIN, "SINE", 0, "Sine", ""}, - {NODE_MATH_COS, "COSINE", 0, "Cosine", ""}, - {NODE_MATH_TAN, "TANGENT", 0, "Tangent", ""}, - {NODE_MATH_ASIN, "ARCSINE", 0, "Arcsine", ""}, - {NODE_MATH_ACOS, "ARCCOSINE", 0, "Arccosine", ""}, - {NODE_MATH_ATAN, "ARCTANGENT", 0, "Arctangent", ""}, - {NODE_MATH_ATAN2, "ARCTAN2", 0, "Arctan2", ""}, + {NODE_MATH_SINE, "SINE", 0, "Sine", "sin(A)"}, + {NODE_MATH_COSINE, "COSINE", 0, "Cosine", "cos(A)"}, + {NODE_MATH_TANGENT, "TANGENT", 0, "Tangent", "tan(A)"}, + {NODE_MATH_ARCSINE, "ARCSINE", 0, "Arcsine", "arcsin(A)"}, + {NODE_MATH_ARCCOSINE, "ARCCOSINE", 0, "Arccosine", "arccos(A)"}, + {NODE_MATH_ARCTANGENT, "ARCTANGENT", 0, "Arctangent", "arctan(A)"}, + {NODE_MATH_ARCTAN2, "ARCTAN2", 0, "Arctan2", "The signed angle arctan(A / B)"}, {0, NULL, 0, NULL, NULL}, }; const EnumPropertyItem rna_enum_node_vec_math_items[] = { - {0, "ADD", 0, "Add", ""}, - {1, "SUBTRACT", 0, "Subtract", ""}, - {2, "AVERAGE", 0, "Average", ""}, - {3, "DOT_PRODUCT", 0, "Dot Product", ""}, - {4, "CROSS_PRODUCT", 0, "Cross Product", ""}, - {5, "NORMALIZE", 0, "Normalize", ""}, + {NODE_VECTOR_MATH_ADD, "ADD", 0, "Add", "A + B"}, + {NODE_VECTOR_MATH_SUBTRACT, "SUBTRACT", 0, "Subtract", "A - B"}, + {NODE_VECTOR_MATH_MULTIPLY, "MULTIPLY", 0, "Multiply", "Entrywise multiply"}, + {NODE_VECTOR_MATH_DIVIDE, "DIVIDE", 0, "Divide", "Entrywise divide"}, + {0, "", ICON_NONE, NULL, NULL}, + {NODE_VECTOR_MATH_CROSS_PRODUCT, "CROSS_PRODUCT", 0, "Cross Product", "A cross B"}, + {NODE_VECTOR_MATH_PROJECT, "PROJECT", 0, "Project", "Project A onto B"}, + {NODE_VECTOR_MATH_REFLECT, + "REFLECT", + 0, + "Reflect", + "Reflect A around the normal B. B needn't be normalized"}, + {NODE_VECTOR_MATH_DOT_PRODUCT, "DOT_PRODUCT", 0, "Dot Product", "A dot B"}, + {0, "", ICON_NONE, NULL, NULL}, + {NODE_VECTOR_MATH_DISTANCE, "DISTANCE", 0, "Distance", "Distance between A and B"}, + {NODE_VECTOR_MATH_LENGTH, "LENGTH", 0, "Length", "Length of A"}, + {NODE_VECTOR_MATH_SCALE, "SCALE", 0, "Scale", "A multiplied by Scale"}, + {NODE_VECTOR_MATH_NORMALIZE, "NORMALIZE", 0, "Normalize", "Normalize A"}, + {0, "", ICON_NONE, NULL, NULL}, + {NODE_VECTOR_MATH_SNAP, + "SNAP", + 0, + "Snap", + "Round A to the largest integer multiple of B less than or equal A"}, + {NODE_VECTOR_MATH_FLOOR, "FLOOR", 0, "Floor", "Entrywise floor"}, + {NODE_VECTOR_MATH_CEIL, "CEIL", 0, "Ceil", "Entrywise ceil"}, + {NODE_VECTOR_MATH_MODULO, "MODULO", 0, "Modulo", "Entrywise modulo"}, + {NODE_VECTOR_MATH_FRACTION, "FRACTION", 0, "Fraction", "The fraction part of A entrywise"}, + {NODE_VECTOR_MATH_ABSOLUTE, "ABSOLUTE", 0, "Absolute", "Entrywise absolute"}, + {NODE_VECTOR_MATH_MINIMUM, "MINIMUM", 0, "Minimum", "Entrywise minimum"}, + {NODE_VECTOR_MATH_MAXIMUM, "MAXIMUM", 0, "Maximum", "Entrywise maximum"}, + {0, NULL, 0, NULL, NULL}, +}; + +static const EnumPropertyItem rna_enum_node_tex_dimensions_items[] = { + {1, "1D", 0, "1D", "Use the scalar value W as input"}, + {2, "2D", 0, "2D", "Use the 2D vector (x, y) as input. The z component is ignored"}, + {3, "3D", 0, "3D", "Use the 3D vector Vector as input"}, + {4, "4D", 0, "4D", "Use the 4D vector (x, y, z, w) as input"}, {0, NULL, 0, NULL, NULL}, }; @@ -720,7 +760,7 @@ static bool rna_NodeTree_check(bNodeTree *ntree, ReportList *reports) static void rna_NodeTree_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - bNodeTree *ntree = (bNodeTree *)ptr->id.data; + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; bNode *node = (bNode *)ptr->data; WM_main_add_notifier(NC_NODE | NA_EDITED, NULL); @@ -1201,7 +1241,7 @@ static char *rna_Node_path(PointerRNA *ptr) char *rna_Node_ImageUser_path(PointerRNA *ptr) { - bNodeTree *ntree = (bNodeTree *)ptr->id.data; + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; bNode *node; char name_esc[sizeof(node->name) * 2]; @@ -1706,7 +1746,7 @@ static bool rna_Node_parent_poll(PointerRNA *ptr, PointerRNA value) static void rna_Node_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - bNodeTree *ntree = (bNodeTree *)ptr->id.data; + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; bNode *node = (bNode *)ptr->data; ED_node_tag_update_nodetree(bmain, ntree, node); } @@ -1730,7 +1770,7 @@ static void rna_Node_select_set(PointerRNA *ptr, bool value) static void rna_Node_name_set(PointerRNA *ptr, const char *value) { - bNodeTree *ntree = (bNodeTree *)ptr->id.data; + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; bNode *node = (bNode *)ptr->data; char oldname[sizeof(node->name)]; @@ -2082,7 +2122,7 @@ static StructRNA *rna_NodeSocket_refine(PointerRNA *ptr) static char *rna_NodeSocket_path(PointerRNA *ptr) { - bNodeTree *ntree = (bNodeTree *)ptr->id.data; + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; bNodeSocket *sock = (bNodeSocket *)ptr->data; bNode *node; int socketindex; @@ -2116,7 +2156,7 @@ static IDProperty *rna_NodeSocket_idprops(PointerRNA *ptr, bool create) static PointerRNA rna_NodeSocket_node_get(PointerRNA *ptr) { - bNodeTree *ntree = (bNodeTree *)ptr->id.data; + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; bNodeSocket *sock = (bNodeSocket *)ptr->data; bNode *node; PointerRNA r_ptr; @@ -2129,7 +2169,7 @@ static PointerRNA rna_NodeSocket_node_get(PointerRNA *ptr) static void rna_NodeSocket_type_set(PointerRNA *ptr, int value) { - bNodeTree *ntree = (bNodeTree *)ptr->id.data; + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; bNodeSocket *sock = (bNodeSocket *)ptr->data; bNode *node; nodeFindNode(ntree, sock, &node, NULL); @@ -2138,7 +2178,7 @@ static void rna_NodeSocket_type_set(PointerRNA *ptr, int value) static void rna_NodeSocket_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - bNodeTree *ntree = (bNodeTree *)ptr->id.data; + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; bNodeSocket *sock = (bNodeSocket *)ptr->data; bNode *node; if (nodeFindNode(ntree, sock, &node, NULL)) { @@ -2398,7 +2438,7 @@ static StructRNA *rna_NodeSocketInterface_refine(PointerRNA *ptr) static char *rna_NodeSocketInterface_path(PointerRNA *ptr) { - bNodeTree *ntree = (bNodeTree *)ptr->id.data; + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; bNodeSocket *sock = (bNodeSocket *)ptr->data; int socketindex; @@ -2429,7 +2469,7 @@ static IDProperty *rna_NodeSocketInterface_idprops(PointerRNA *ptr, bool create) static void rna_NodeSocketInterface_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - bNodeTree *ntree = ptr->id.data; + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; bNodeSocket *stemp = ptr->data; if (!stemp->typeinfo) { @@ -2545,7 +2585,7 @@ static void rna_NodeSocketStandard_value_update(struct bContext *C, PointerRNA * /* try to use node from context, faster */ node = CTX_data_pointer_get(C, "node").data; if (!node) { - bNodeTree *ntree = ptr->id.data; + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; bNodeSocket *sock = ptr->data; /* fall back to searching node in the tree */ @@ -2763,7 +2803,7 @@ static void rna_CompositorNode_tag_need_exec(bNode *node) static void rna_Node_tex_image_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - bNodeTree *ntree = (bNodeTree *)ptr->id.data; + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; bNode *node = (bNode *)ptr->data; ED_node_tag_update_nodetree(bmain, ntree, node); @@ -2772,7 +2812,7 @@ static void rna_Node_tex_image_update(Main *bmain, Scene *UNUSED(scene), Pointer static void rna_NodeGroup_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - bNodeTree *ntree = (bNodeTree *)ptr->id.data; + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; bNode *node = (bNode *)ptr->data; if (node->id) { @@ -2786,7 +2826,7 @@ static void rna_NodeGroup_node_tree_set(PointerRNA *ptr, const PointerRNA value, struct ReportList *UNUSED(reports)) { - bNodeTree *ntree = ptr->id.data; + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; bNode *node = ptr->data; bNodeTree *ngroup = value.data; @@ -2804,7 +2844,7 @@ static void rna_NodeGroup_node_tree_set(PointerRNA *ptr, static bool rna_NodeGroup_node_tree_poll(PointerRNA *ptr, const PointerRNA value) { - bNodeTree *ntree = ptr->id.data; + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; bNodeTree *ngroup = value.data; /* only allow node trees of the same type as the group node's tree */ @@ -2831,7 +2871,7 @@ static StructRNA *rna_NodeGroup_interface_typef(PointerRNA *ptr) static StructRNA *rna_NodeGroupInputOutput_interface_typef(PointerRNA *ptr) { - bNodeTree *ntree = ptr->id.data; + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; if (ntree) { StructRNA *srna = ntreeInterfaceTypeGet(ntree, true); @@ -3166,7 +3206,7 @@ static const EnumPropertyItem *rna_Node_channel_itemf(bContext *UNUSED(C), static void rna_Image_Node_update_id(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - bNodeTree *ntree = (bNodeTree *)ptr->id.data; + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; bNode *node = (bNode *)ptr->data; node->update |= NODE_UPDATE_ID; @@ -3190,19 +3230,19 @@ static PointerRNA rna_NodeOutputFile_slot_file_get(CollectionPropertyIterator *i { PointerRNA ptr; bNodeSocket *sock = rna_iterator_listbase_get(iter); - RNA_pointer_create(iter->parent.id.data, &RNA_NodeOutputFileSlotFile, sock->storage, &ptr); + RNA_pointer_create(iter->parent.owner_id, &RNA_NodeOutputFileSlotFile, sock->storage, &ptr); return ptr; } static void rna_NodeColorBalance_update_lgg(Main *bmain, Scene *scene, PointerRNA *ptr) { - ntreeCompositColorBalanceSyncFromLGG(ptr->id.data, ptr->data); + ntreeCompositColorBalanceSyncFromLGG((bNodeTree *)ptr->owner_id, ptr->data); rna_Node_update(bmain, scene, ptr); } static void rna_NodeColorBalance_update_cdl(Main *bmain, Scene *scene, PointerRNA *ptr) { - ntreeCompositColorBalanceSyncFromCDL(ptr->id.data, ptr->data); + ntreeCompositColorBalanceSyncFromCDL((bNodeTree *)ptr->owner_id, ptr->data); rna_Node_update(bmain, scene, ptr); } @@ -3241,13 +3281,13 @@ static void rna_NodeCryptomatte_matte_set(PointerRNA *ptr, const char *value) static void rna_NodeCryptomatte_update_add(Main *bmain, Scene *scene, PointerRNA *ptr) { - ntreeCompositCryptomatteSyncFromAdd(ptr->id.data, ptr->data); + ntreeCompositCryptomatteSyncFromAdd((bNodeTree *)ptr->owner_id, ptr->data); rna_Node_update(bmain, scene, ptr); } static void rna_NodeCryptomatte_update_remove(Main *bmain, Scene *scene, PointerRNA *ptr) { - ntreeCompositCryptomatteSyncFromRemove(ptr->id.data, ptr->data); + ntreeCompositCryptomatteSyncFromRemove((bNodeTree *)ptr->owner_id, ptr->data); rna_Node_update(bmain, scene, ptr); } @@ -3257,7 +3297,7 @@ static PointerRNA rna_NodeOutputFile_slot_layer_get(CollectionPropertyIterator * { PointerRNA ptr; bNodeSocket *sock = rna_iterator_listbase_get(iter); - RNA_pointer_create(iter->parent.id.data, &RNA_NodeOutputFileSlotLayer, sock->storage, &ptr); + RNA_pointer_create(iter->parent.owner_id, &RNA_NodeOutputFileSlotLayer, sock->storage, &ptr); return ptr; } @@ -3287,7 +3327,7 @@ static int rna_NodeOutputFileSocket_find_node(bNodeTree *ntree, static void rna_NodeOutputFileSlotFile_path_set(PointerRNA *ptr, const char *value) { - bNodeTree *ntree = ptr->id.data; + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; NodeImageMultiFileSocket *sockdata = ptr->data; bNode *node; bNodeSocket *sock; @@ -3299,7 +3339,7 @@ static void rna_NodeOutputFileSlotFile_path_set(PointerRNA *ptr, const char *val static void rna_NodeOutputFileSlotLayer_name_set(PointerRNA *ptr, const char *value) { - bNodeTree *ntree = ptr->id.data; + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; NodeImageMultiFileSocket *sockdata = ptr->data; bNode *node; bNodeSocket *sock; @@ -3420,7 +3460,7 @@ static void rna_ShaderNodeScript_bytecode_set(PointerRNA *ptr, const char *value static void rna_ShaderNodeScript_update(Main *bmain, Scene *scene, PointerRNA *ptr) { - bNodeTree *ntree = (bNodeTree *)ptr->id.data; + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; bNode *node = (bNode *)ptr->data; RenderEngineType *engine_type = RE_engines_find(scene->r.engine); @@ -3436,7 +3476,7 @@ static void rna_ShaderNodeScript_update(Main *bmain, Scene *scene, PointerRNA *p static void rna_ShaderNode_socket_update(Main *bmain, Scene *scene, PointerRNA *ptr) { - bNodeTree *ntree = (bNodeTree *)ptr->id.data; + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; bNode *node = (bNode *)ptr->data; nodeUpdate(ntree, node); @@ -3445,7 +3485,7 @@ static void rna_ShaderNode_socket_update(Main *bmain, Scene *scene, PointerRNA * static void rna_CompositorNodeScale_update(Main *bmain, Scene *scene, PointerRNA *ptr) { - bNodeTree *ntree = (bNodeTree *)ptr->id.data; + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; bNode *node = (bNode *)ptr->data; nodeUpdate(ntree, node); @@ -3476,7 +3516,7 @@ static void rna_ShaderNodePointDensity_psys_set(PointerRNA *ptr, NodeShaderTexPointDensity *shader_point_density = node->storage; Object *ob = (Object *)node->id; - if (ob && value.id.data == ob) { + if (ob && value.owner_id == &ob->id) { shader_point_density->particle_system = BLI_findindex(&ob->particlesystem, value.data) + 1; } else { @@ -3780,6 +3820,7 @@ static void def_group(StructRNA *srna) RNA_def_property_pointer_funcs( prop, NULL, "rna_NodeGroup_node_tree_set", NULL, "rna_NodeGroup_node_tree_poll"); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Node Tree", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeGroup_update"); @@ -3852,7 +3893,7 @@ static void def_math(StructRNA *srna) RNA_def_property_enum_sdna(prop, NULL, "custom1"); RNA_def_property_enum_items(prop, rna_enum_node_math_items); RNA_def_property_ui_text(prop, "Operation", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNode_socket_update"); prop = RNA_def_property(srna, "use_clamp", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "custom2", SHD_MATH_CLAMP); @@ -3868,7 +3909,7 @@ static void def_vector_math(StructRNA *srna) RNA_def_property_enum_sdna(prop, NULL, "custom1"); RNA_def_property_enum_items(prop, rna_enum_node_vec_math_items); RNA_def_property_ui_text(prop, "Operation", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNode_socket_update"); } static void def_rgb_curve(StructRNA *srna) @@ -3954,6 +3995,7 @@ static void def_texture(StructRNA *srna) RNA_def_property_pointer_sdna(prop, NULL, "id"); RNA_def_property_struct_type(prop, "Texture"); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Texture", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); @@ -4152,6 +4194,7 @@ static void def_sh_tex_environment(StructRNA *srna) RNA_def_property_pointer_sdna(prop, NULL, "id"); RNA_def_property_struct_type(prop, "Image"); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Image", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_tex_image_update"); @@ -4230,6 +4273,7 @@ static void def_sh_tex_image(StructRNA *srna) RNA_def_property_pointer_sdna(prop, NULL, "id"); RNA_def_property_struct_type(prop, "Image"); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Image", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_tex_image_update"); @@ -4464,6 +4508,18 @@ static void def_sh_tex_wave(StructRNA *srna) RNA_def_property_update(prop, 0, "rna_Node_update"); } +static void def_sh_tex_white_noise(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "dimensions", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "custom1"); + RNA_def_property_enum_items(prop, rna_enum_node_tex_dimensions_items); + RNA_def_property_ui_text( + prop, "Dimensions", "The number of dimensions to evaluate the noise in"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNode_socket_update"); +} + static void def_sh_tex_coord(StructRNA *srna) { PropertyRNA *prop; @@ -4472,6 +4528,7 @@ static void def_sh_tex_coord(StructRNA *srna) RNA_def_property_pointer_sdna(prop, NULL, "id"); RNA_def_property_struct_type(prop, "Object"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text( prop, "Object", "Use coordinates from this object (for object texture coordinates output)"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update_relations"); @@ -4606,6 +4663,7 @@ static void def_sh_tex_pointdensity(StructRNA *srna) RNA_def_property_pointer_sdna(prop, NULL, "id"); RNA_def_property_struct_type(prop, "Object"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Object", "Object to take point data from"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); @@ -5459,6 +5517,7 @@ static void def_cmp_image(StructRNA *srna) RNA_def_property_pointer_sdna(prop, NULL, "id"); RNA_def_property_struct_type(prop, "Image"); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Image", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Image_Node_update_id"); @@ -5486,6 +5545,7 @@ static void def_cmp_render_layers(StructRNA *srna) RNA_def_property_pointer_funcs(prop, NULL, "rna_Node_scene_set", NULL, NULL); RNA_def_property_struct_type(prop, "Scene"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Scene", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_view_layer_update"); @@ -6172,6 +6232,7 @@ static void def_cmp_defocus(StructRNA *srna) RNA_def_property_pointer_funcs(prop, NULL, "rna_Node_scene_set", NULL, NULL); RNA_def_property_struct_type(prop, "Scene"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text( prop, "Scene", "Scene from which to select the active camera (render scene if undefined)"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); @@ -6672,7 +6733,7 @@ static void def_cmp_colorbalance(StructRNA *srna) RNA_def_property_float_sdna(prop, NULL, "offset"); RNA_def_property_array(prop, 3); RNA_def_property_ui_range(prop, 0, 1, 0.1, 3); - RNA_def_property_ui_text(prop, "Offset", "Correction for Shadows"); + RNA_def_property_ui_text(prop, "Offset", "Correction for entire tonal range"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeColorBalance_update_cdl"); prop = RNA_def_property(srna, "power", PROP_FLOAT, PROP_COLOR_GAMMA); @@ -7800,10 +7861,10 @@ static void rna_def_node_socket(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Type", "Data type"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update"); - prop = RNA_def_property(srna, "draw_shape", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "draw_shape"); - RNA_def_property_enum_items(prop, rna_enum_node_socket_draw_shape_items); - RNA_def_property_enum_default(prop, SOCK_DRAW_SHAPE_CIRCLE); + prop = RNA_def_property(srna, "display_shape", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "display_shape"); + RNA_def_property_enum_items(prop, rna_enum_node_socket_display_shape_items); + RNA_def_property_enum_default(prop, SOCK_DISPLAY_SHAPE_CIRCLE); RNA_def_property_ui_text(prop, "Shape", "Socket shape"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update"); diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index a12f45732d6..c9061c7c087 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -299,27 +299,27 @@ const EnumPropertyItem rna_enum_object_axis_items[] = { static void rna_Object_internal_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - DEG_id_tag_update(ptr->id.data, ID_RECALC_TRANSFORM); + DEG_id_tag_update(ptr->owner_id, ID_RECALC_TRANSFORM); } static void rna_Object_internal_update_draw(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - DEG_id_tag_update(ptr->id.data, ID_RECALC_TRANSFORM); - WM_main_add_notifier(NC_OBJECT | ND_DRAW, ptr->id.data); + DEG_id_tag_update(ptr->owner_id, ID_RECALC_TRANSFORM); + WM_main_add_notifier(NC_OBJECT | ND_DRAW, ptr->owner_id); } static void rna_Object_matrix_world_update(Main *bmain, Scene *scene, PointerRNA *ptr) { /* don't use compat so we get predictable rotation */ - BKE_object_apply_mat4(ptr->id.data, ((Object *)ptr->id.data)->obmat, false, true); + BKE_object_apply_mat4((Object *)ptr->owner_id, ((Object *)ptr->owner_id)->obmat, false, true); rna_Object_internal_update(bmain, scene, ptr); } static void rna_Object_hide_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - Object *ob = ptr->id.data; + Object *ob = (Object *)ptr->owner_id; BKE_main_collection_sync_remap(bmain); DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE); DEG_relations_tag_update(bmain); @@ -328,7 +328,7 @@ static void rna_Object_hide_update(Main *bmain, Scene *UNUSED(scene), PointerRNA static void rna_MaterialIndex_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; if (ob && ob->type == OB_GPENCIL) { /* notifying material property in topbar */ WM_main_add_notifier(NC_SPACE | ND_SPACE_VIEW3D, NULL); @@ -337,13 +337,13 @@ static void rna_MaterialIndex_update(Main *UNUSED(bmain), Scene *UNUSED(scene), static void rna_Object_matrix_local_get(PointerRNA *ptr, float values[16]) { - Object *ob = ptr->id.data; + Object *ob = (Object *)ptr->owner_id; BKE_object_matrix_local_get(ob, (float(*)[4])values); } static void rna_Object_matrix_local_set(PointerRNA *ptr, const float values[16]) { - Object *ob = ptr->id.data; + Object *ob = (Object *)ptr->owner_id; float local_mat[4][4]; /* Localspace matrix is truly relative to the parent, @@ -365,20 +365,20 @@ static void rna_Object_matrix_local_set(PointerRNA *ptr, const float values[16]) static void rna_Object_matrix_basis_get(PointerRNA *ptr, float values[16]) { - Object *ob = ptr->id.data; + Object *ob = (Object *)ptr->owner_id; BKE_object_to_mat4(ob, (float(*)[4])values); } static void rna_Object_matrix_basis_set(PointerRNA *ptr, const float values[16]) { - Object *ob = ptr->id.data; + Object *ob = (Object *)ptr->owner_id; BKE_object_apply_mat4(ob, (float(*)[4])values, false, false); } void rna_Object_internal_update_data(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - DEG_id_tag_update(ptr->id.data, ID_RECALC_GEOMETRY); - WM_main_add_notifier(NC_OBJECT | ND_DRAW, ptr->id.data); + DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY); + WM_main_add_notifier(NC_OBJECT | ND_DRAW, ptr->owner_id); } void rna_Object_internal_update_data_dependency(Main *bmain, Scene *scene, PointerRNA *ptr) @@ -389,7 +389,7 @@ void rna_Object_internal_update_data_dependency(Main *bmain, Scene *scene, Point static void rna_Object_active_shape_update(bContext *C, PointerRNA *ptr) { - Object *ob = ptr->id.data; + Object *ob = (Object *)ptr->owner_id; Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); @@ -403,7 +403,7 @@ static void rna_Object_active_shape_update(bContext *C, PointerRNA *ptr) DEG_id_tag_update(ob->data, 0); EDBM_mesh_normals_update(((Mesh *)ob->data)->edit_mesh); - BKE_editmesh_tessface_calc(((Mesh *)ob->data)->edit_mesh); + BKE_editmesh_looptri_calc(((Mesh *)ob->data)->edit_mesh); break; case OB_CURVE: case OB_SURF: @@ -422,9 +422,9 @@ static void rna_Object_active_shape_update(bContext *C, PointerRNA *ptr) static void rna_Object_dependency_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - DEG_id_tag_update(ptr->id.data, ID_RECALC_TRANSFORM); + DEG_id_tag_update(ptr->owner_id, ID_RECALC_TRANSFORM); DEG_relations_tag_update(bmain); - WM_main_add_notifier(NC_OBJECT | ND_PARENT, ptr->id.data); + WM_main_add_notifier(NC_OBJECT | ND_PARENT, ptr->owner_id); } static void rna_Object_data_set(PointerRNA *ptr, PointerRNA value, struct ReportList *reports) @@ -546,27 +546,27 @@ static void rna_Object_parent_set(PointerRNA *ptr, } } -bool rna_Object_parent_override_apply(Main *UNUSED(bmain), - PointerRNA *ptr_dst, - PointerRNA *ptr_src, - PointerRNA *ptr_storage, - PropertyRNA *prop_dst, - PropertyRNA *prop_src, - PropertyRNA *UNUSED(prop_storage), - const int len_dst, - const int len_src, - const int len_storage, - PointerRNA *UNUSED(ptr_item_dst), - PointerRNA *UNUSED(ptr_item_src), - PointerRNA *UNUSED(ptr_item_storage), - IDOverrideLibraryPropertyOperation *opop) +static bool rna_Object_parent_override_apply(Main *UNUSED(bmain), + PointerRNA *ptr_dst, + PointerRNA *ptr_src, + PointerRNA *ptr_storage, + PropertyRNA *prop_dst, + PropertyRNA *prop_src, + PropertyRNA *UNUSED(prop_storage), + const int len_dst, + const int len_src, + const int len_storage, + PointerRNA *UNUSED(ptr_item_dst), + PointerRNA *UNUSED(ptr_item_src), + PointerRNA *UNUSED(ptr_item_storage), + IDOverrideLibraryPropertyOperation *opop) { BLI_assert(len_dst == len_src && (!ptr_storage || len_dst == len_storage) && len_dst == 0); BLI_assert(opop->operation == IDOVERRIDE_LIBRARY_OP_REPLACE && - "Unsupported RNA override operation on animdata pointer"); + "Unsupported RNA override operation on object parent pointer"); UNUSED_VARS_NDEBUG(ptr_storage, len_dst, len_src, len_storage, opop); - /* We need a special handling here because setting parent resets pinvert parent matrix, + /* We need a special handling here because setting parent resets invert parent matrix, * which is evil in our case. */ Object *ob = (Object *)ptr_dst->data; Object *parent_dst = RNA_property_pointer_get(ptr_dst, prop_dst).data; @@ -691,7 +691,7 @@ static void rna_Object_dup_collection_set(PointerRNA *ptr, static void rna_VertexGroup_name_set(PointerRNA *ptr, const char *value) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; bDeformGroup *dg = (bDeformGroup *)ptr->data; BLI_strncpy_utf8(dg->name, value, sizeof(dg->name)); defgroup_unique_name(dg, ob); @@ -699,34 +699,34 @@ static void rna_VertexGroup_name_set(PointerRNA *ptr, const char *value) static int rna_VertexGroup_index_get(PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; return BLI_findindex(&ob->defbase, ptr->data); } static PointerRNA rna_Object_active_vertex_group_get(PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; return rna_pointer_inherit_refine( ptr, &RNA_VertexGroup, BLI_findlink(&ob->defbase, ob->actdef - 1)); } static int rna_Object_active_vertex_group_index_get(PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; return ob->actdef - 1; } static void rna_Object_active_vertex_group_index_set(PointerRNA *ptr, int value) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; ob->actdef = value + 1; } static void rna_Object_active_vertex_group_index_range( PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax)) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; *min = 0; *max = max_ii(0, BLI_listbase_count(&ob->defbase) - 1); @@ -734,7 +734,7 @@ static void rna_Object_active_vertex_group_index_range( void rna_object_vgroup_name_index_get(PointerRNA *ptr, char *value, int index) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; bDeformGroup *dg; dg = BLI_findlink(&ob->defbase, index - 1); @@ -749,7 +749,7 @@ void rna_object_vgroup_name_index_get(PointerRNA *ptr, char *value, int index) int rna_object_vgroup_name_index_length(PointerRNA *ptr, int index) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; bDeformGroup *dg; dg = BLI_findlink(&ob->defbase, index - 1); @@ -758,13 +758,13 @@ int rna_object_vgroup_name_index_length(PointerRNA *ptr, int index) void rna_object_vgroup_name_index_set(PointerRNA *ptr, const char *value, short *index) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; *index = defgroup_name_index(ob, value) + 1; } void rna_object_vgroup_name_set(PointerRNA *ptr, const char *value, char *result, int maxlen) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; bDeformGroup *dg = defgroup_find_name(ob, value); if (dg) { /* No need for BLI_strncpy_utf8, since this matches an existing group. */ @@ -777,7 +777,7 @@ void rna_object_vgroup_name_set(PointerRNA *ptr, const char *value, char *result static void rna_FaceMap_name_set(PointerRNA *ptr, const char *value) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; bFaceMap *fmap = (bFaceMap *)ptr->data; BLI_strncpy_utf8(fmap->name, value, sizeof(fmap->name)); BKE_object_facemap_unique_name(ob, fmap); @@ -785,33 +785,33 @@ static void rna_FaceMap_name_set(PointerRNA *ptr, const char *value) static int rna_FaceMap_index_get(PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; return BLI_findindex(&ob->fmaps, ptr->data); } static PointerRNA rna_Object_active_face_map_get(PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; return rna_pointer_inherit_refine(ptr, &RNA_FaceMap, BLI_findlink(&ob->fmaps, ob->actfmap - 1)); } static int rna_Object_active_face_map_index_get(PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; return ob->actfmap - 1; } static void rna_Object_active_face_map_index_set(PointerRNA *ptr, int value) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; ob->actfmap = value + 1; } static void rna_Object_active_face_map_index_range( PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax)) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; *min = 0; *max = max_ii(0, BLI_listbase_count(&ob->fmaps) - 1); @@ -819,7 +819,7 @@ static void rna_Object_active_face_map_index_range( void rna_object_BKE_object_facemap_name_index_get(PointerRNA *ptr, char *value, int index) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; bFaceMap *fmap; fmap = BLI_findlink(&ob->fmaps, index - 1); @@ -834,7 +834,7 @@ void rna_object_BKE_object_facemap_name_index_get(PointerRNA *ptr, char *value, int rna_object_BKE_object_facemap_name_index_length(PointerRNA *ptr, int index) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; bFaceMap *fmap; fmap = BLI_findlink(&ob->fmaps, index - 1); @@ -843,13 +843,13 @@ int rna_object_BKE_object_facemap_name_index_length(PointerRNA *ptr, int index) void rna_object_BKE_object_facemap_name_index_set(PointerRNA *ptr, const char *value, short *index) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; *index = BKE_object_facemap_name_index(ob, value) + 1; } void rna_object_fmap_name_set(PointerRNA *ptr, const char *value, char *result, int maxlen) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; bFaceMap *fmap = BKE_object_facemap_find_name(ob, value); if (fmap) { /* No need for BLI_strncpy_utf8, since this matches an existing group. */ @@ -862,7 +862,7 @@ void rna_object_fmap_name_set(PointerRNA *ptr, const char *value, char *result, void rna_object_uvlayer_name_set(PointerRNA *ptr, const char *value, char *result, int maxlen) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; Mesh *me; CustomDataLayer *layer; int a; @@ -885,7 +885,7 @@ void rna_object_uvlayer_name_set(PointerRNA *ptr, const char *value, char *resul void rna_object_vcollayer_name_set(PointerRNA *ptr, const char *value, char *result, int maxlen) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; Mesh *me; CustomDataLayer *layer; int a; @@ -908,13 +908,13 @@ void rna_object_vcollayer_name_set(PointerRNA *ptr, const char *value, char *res static int rna_Object_active_material_index_get(PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; return MAX2(ob->actcol - 1, 0); } static void rna_Object_active_material_index_set(PointerRNA *ptr, int value) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; ob->actcol = value + 1; if (ob->type == OB_MESH) { @@ -929,7 +929,7 @@ static void rna_Object_active_material_index_set(PointerRNA *ptr, int value) static void rna_Object_active_material_index_range( PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax)) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; *min = 0; *max = max_ii(ob->totcol - 1, 0); } @@ -937,7 +937,7 @@ static void rna_Object_active_material_index_range( /* returns active base material */ static PointerRNA rna_Object_active_material_get(PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; Material *ma; ma = (ob->totcol) ? give_current_material(ob, ob->actcol) : NULL; @@ -948,7 +948,7 @@ static void rna_Object_active_material_set(PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; DEG_id_tag_update(value.data, 0); BLI_assert(BKE_id_is_in_global_main(&ob->id)); @@ -963,7 +963,7 @@ static void rna_Object_active_material_set(PointerRNA *ptr, static int rna_Object_active_material_editable(PointerRNA *ptr, const char **UNUSED(r_info)) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; bool is_editable; if ((ob->matbits == NULL) || (ob->actcol == 0) || ob->matbits[ob->actcol - 1]) { @@ -979,20 +979,20 @@ static int rna_Object_active_material_editable(PointerRNA *ptr, const char **UNU static void rna_Object_active_particle_system_index_range( PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax)) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; *min = 0; *max = max_ii(0, BLI_listbase_count(&ob->particlesystem) - 1); } static int rna_Object_active_particle_system_index_get(PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; return psys_get_current_num(ob); } static void rna_Object_active_particle_system_index_set(PointerRNA *ptr, int value) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; psys_set_current_num(ob, value); } @@ -1000,7 +1000,7 @@ static void rna_Object_particle_update(Main *UNUSED(bmain), Scene *scene, Pointe { /* TODO: Disabled for now, because bContext is not available. */ # if 0 - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; PE_current_changed(NULL, scene, ob); # else (void)scene; @@ -1137,7 +1137,7 @@ static int rna_Object_rotation_4d_editable(PointerRNA *ptr, int index) static int rna_MaterialSlot_material_editable(PointerRNA *ptr, const char **UNUSED(r_info)) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; const int index = (Material **)ptr->data - ob->mat; bool is_editable; @@ -1153,7 +1153,7 @@ static int rna_MaterialSlot_material_editable(PointerRNA *ptr, const char **UNUS static PointerRNA rna_MaterialSlot_material_get(PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; Material *ma; const int index = (Material **)ptr->data - ob->mat; @@ -1165,7 +1165,7 @@ static void rna_MaterialSlot_material_set(PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; int index = (Material **)ptr->data - ob->mat; BLI_assert(BKE_id_is_in_global_main(&ob->id)); @@ -1175,7 +1175,7 @@ static void rna_MaterialSlot_material_set(PointerRNA *ptr, static bool rna_MaterialSlot_material_poll(PointerRNA *ptr, PointerRNA value) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; Material *ma = (Material *)value.data; if (ob->type == OB_GPENCIL) { @@ -1190,7 +1190,7 @@ static bool rna_MaterialSlot_material_poll(PointerRNA *ptr, PointerRNA value) static int rna_MaterialSlot_link_get(PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; int index = (Material **)ptr->data - ob->mat; return ob->matbits[index] != 0; @@ -1198,7 +1198,7 @@ static int rna_MaterialSlot_link_get(PointerRNA *ptr) static void rna_MaterialSlot_link_set(PointerRNA *ptr, int value) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; int index = (Material **)ptr->data - ob->mat; if (value) { @@ -1213,7 +1213,7 @@ static void rna_MaterialSlot_link_set(PointerRNA *ptr, int value) static int rna_MaterialSlot_name_length(PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; Material *ma; int index = (Material **)ptr->data - ob->mat; @@ -1228,7 +1228,7 @@ static int rna_MaterialSlot_name_length(PointerRNA *ptr) static void rna_MaterialSlot_name_get(PointerRNA *ptr, char *str) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; Material *ma; int index = (Material **)ptr->data - ob->mat; @@ -1246,14 +1246,14 @@ static void rna_MaterialSlot_update(Main *bmain, Scene *scene, PointerRNA *ptr) { rna_Object_internal_update(bmain, scene, ptr); - WM_main_add_notifier(NC_OBJECT | ND_OB_SHADING, ptr->id.data); + WM_main_add_notifier(NC_OBJECT | ND_OB_SHADING, ptr->owner_id); WM_main_add_notifier(NC_MATERIAL | ND_SHADING_LINKS, NULL); DEG_relations_tag_update(bmain); } static char *rna_MaterialSlot_path(PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; int index = (Material **)ptr->data - ob->mat; return BLI_sprintfN("material_slots[%d]", index); @@ -1271,7 +1271,7 @@ static char *rna_ObjectDisplay_path(PointerRNA *UNUSED(ptr)) static PointerRNA rna_Object_active_particle_system_get(PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; ParticleSystem *psys = psys_get_current(ob); return rna_pointer_inherit_refine(ptr, &RNA_ParticleSystem, psys); } @@ -1279,7 +1279,7 @@ static PointerRNA rna_Object_active_particle_system_get(PointerRNA *ptr) static void rna_Object_active_shape_key_index_range( PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax)) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; Key *key = BKE_key_from_object(ob); *min = 0; @@ -1296,21 +1296,21 @@ static void rna_Object_active_shape_key_index_range( static int rna_Object_active_shape_key_index_get(PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; return MAX2(ob->shapenr - 1, 0); } static void rna_Object_active_shape_key_index_set(PointerRNA *ptr, int value) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; ob->shapenr = value + 1; } static PointerRNA rna_Object_active_shape_key_get(PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; Key *key = BKE_key_from_object(ob); KeyBlock *kb; PointerRNA keyptr; @@ -1326,7 +1326,7 @@ static PointerRNA rna_Object_active_shape_key_get(PointerRNA *ptr) static PointerRNA rna_Object_field_get(PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; /* weak */ if (!ob->pd) { @@ -1338,7 +1338,7 @@ static PointerRNA rna_Object_field_get(PointerRNA *ptr) static PointerRNA rna_Object_collision_get(PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; if (ob->type != OB_MESH) { return PointerRNA_NULL; @@ -1354,7 +1354,7 @@ static PointerRNA rna_Object_collision_get(PointerRNA *ptr) static PointerRNA rna_Object_active_constraint_get(PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; bConstraint *con = BKE_constraints_active_get(&ob->constraints); return rna_pointer_inherit_refine(ptr, &RNA_Constraint, con); } @@ -1363,7 +1363,7 @@ static void rna_Object_active_constraint_set(PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; BKE_constraints_active_set(&ob->constraints, (bConstraint *)value.data); } @@ -1428,12 +1428,12 @@ bool rna_Object_constraints_override_apply(Main *UNUSED(bmain), BLI_assert(opop->operation == IDOVERRIDE_LIBRARY_OP_INSERT_AFTER && "Unsupported RNA override operation on constraints collection"); - Object *ob_dst = (Object *)ptr_dst->id.data; - Object *ob_src = (Object *)ptr_src->id.data; + Object *ob_dst = (Object *)ptr_dst->owner_id; + Object *ob_src = (Object *)ptr_src->owner_id; /* Remember that insertion operations are defined and stored in correct order, which means that - * even if we insert several items in a row, we alays insert first one, then second one, etc. - * So we should always find 'anchor' constraint in both _src *and* _dst> */ + * even if we insert several items in a row, we always insert first one, then second one, etc. + * So we should always find 'anchor' constraint in both _src *and* _dst. */ bConstraint *con_anchor = NULL; if (opop->subitem_local_name && opop->subitem_local_name[0]) { con_anchor = BLI_findstring( @@ -1516,12 +1516,12 @@ bool rna_Object_modifiers_override_apply(Main *UNUSED(bmain), BLI_assert(opop->operation == IDOVERRIDE_LIBRARY_OP_INSERT_AFTER && "Unsupported RNA override operation on modifiers collection"); - Object *ob_dst = (Object *)ptr_dst->id.data; - Object *ob_src = (Object *)ptr_src->id.data; + Object *ob_dst = (Object *)ptr_dst->owner_id; + Object *ob_src = (Object *)ptr_src->owner_id; /* Remember that insertion operations are defined and stored in correct order, which means that - * even if we insert several items in a row, we alays insert first one, then second one, etc. - * So we should always find 'anchor' constraint in both _src *and* _dst> */ + * even if we insert several items in a row, we always insert first one, then second one, etc. + * So we should always find 'anchor' constraint in both _src *and* _dst. */ ModifierData *mod_anchor = NULL; if (opop->subitem_local_name && opop->subitem_local_name[0]) { mod_anchor = BLI_findstring( @@ -1619,7 +1619,7 @@ static void rna_Object_shaderfx_clear(Object *object, bContext *C) static void rna_Object_boundbox_get(PointerRNA *ptr, float *values) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; BoundBox *bb = BKE_object_boundbox_get(ob); if (bb) { memcpy(values, bb->vec, sizeof(bb->vec)); @@ -1791,42 +1791,42 @@ static void rna_FaceMap_face_remove( /* generic poll functions */ bool rna_Lattice_object_poll(PointerRNA *UNUSED(ptr), PointerRNA value) { - return ((Object *)value.id.data)->type == OB_LATTICE; + return ((Object *)value.owner_id)->type == OB_LATTICE; } bool rna_Curve_object_poll(PointerRNA *UNUSED(ptr), PointerRNA value) { - return ((Object *)value.id.data)->type == OB_CURVE; + return ((Object *)value.owner_id)->type == OB_CURVE; } bool rna_Armature_object_poll(PointerRNA *UNUSED(ptr), PointerRNA value) { - return ((Object *)value.id.data)->type == OB_ARMATURE; + return ((Object *)value.owner_id)->type == OB_ARMATURE; } bool rna_Mesh_object_poll(PointerRNA *UNUSED(ptr), PointerRNA value) { - return ((Object *)value.id.data)->type == OB_MESH; + return ((Object *)value.owner_id)->type == OB_MESH; } bool rna_Camera_object_poll(PointerRNA *UNUSED(ptr), PointerRNA value) { - return ((Object *)value.id.data)->type == OB_CAMERA; + return ((Object *)value.owner_id)->type == OB_CAMERA; } bool rna_Light_object_poll(PointerRNA *UNUSED(ptr), PointerRNA value) { - return ((Object *)value.id.data)->type == OB_LAMP; + return ((Object *)value.owner_id)->type == OB_LAMP; } bool rna_GPencil_object_poll(PointerRNA *UNUSED(ptr), PointerRNA value) { - return ((Object *)value.id.data)->type == OB_GPENCIL; + return ((Object *)value.owner_id)->type == OB_GPENCIL; } int rna_Object_use_dynamic_topology_sculpting_get(PointerRNA *ptr) { - SculptSession *ss = ((Object *)ptr->id.data)->sculpt; + SculptSession *ss = ((Object *)ptr->owner_id)->sculpt; return (ss && ss->bm); } @@ -2509,10 +2509,12 @@ static void rna_def_object(BlenderRNA *brna) /* proxy */ prop = RNA_def_property(srna, "proxy", PROP_POINTER, PROP_NONE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON); RNA_def_property_ui_text(prop, "Proxy", "Library object this proxy object controls"); prop = RNA_def_property(srna, "proxy_collection", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "proxy_group"); + RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON); RNA_def_property_ui_text( prop, "Proxy Collection", "Library collection duplicator object this proxy object controls"); @@ -2848,6 +2850,14 @@ static void rna_def_object(BlenderRNA *brna) prop, "Display in Orthographic Mode", "Display image in orthographic mode"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + prop = RNA_def_property(srna, "show_empty_image_only_axis_aligned", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna( + prop, NULL, "empty_image_visibility_flag", OB_EMPTY_IMAGE_HIDE_NON_AXIS_ALIGNED); + RNA_def_property_ui_text(prop, + "Display Only Axis Aligned", + "Only display the image when it is aligned with the view axis"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + prop = RNA_def_property(srna, "use_empty_image_alpha", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "empty_image_flag", OB_EMPTY_IMAGE_USE_ALPHA_BLEND); RNA_def_property_ui_text( @@ -2878,7 +2888,7 @@ static void rna_def_object(BlenderRNA *brna) prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR); RNA_def_property_ui_text( prop, "Color", "Object color and alpha, used when faces have the ObColor mode enabled"); - RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update_draw"); /* physics */ prop = RNA_def_property(srna, "field", PROP_POINTER, PROP_NONE); @@ -2983,6 +2993,7 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_struct_type(prop, "Collection"); RNA_def_property_pointer_sdna(prop, NULL, "instance_collection"); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_pointer_funcs(prop, NULL, "rna_Object_dup_collection_set", NULL, NULL); RNA_def_property_ui_text(prop, "Instance Collection", "Instance an existing collection"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_dependency_update"); diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index 3f0b5546a03..5bec6f0c7d3 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -244,7 +244,7 @@ static Base *rna_Object_local_view_property_helper( static bool rna_Object_local_view_get(Object *ob, ReportList *reports, PointerRNA *v3d_ptr) { - bScreen *sc = v3d_ptr->id.data; + bScreen *sc = (bScreen *)v3d_ptr->owner_id; View3D *v3d = v3d_ptr->data; Base *base = rna_Object_local_view_property_helper(sc, v3d, ob, reports, NULL); if (base == NULL) { @@ -258,7 +258,7 @@ static void rna_Object_local_view_set(Object *ob, PointerRNA *v3d_ptr, bool state) { - bScreen *sc = v3d_ptr->id.data; + bScreen *sc = (bScreen *)v3d_ptr->owner_id; View3D *v3d = v3d_ptr->data; Scene *scene; Base *base = rna_Object_local_view_property_helper(sc, v3d, ob, reports, &scene); @@ -704,7 +704,7 @@ bool rna_Object_generate_gpencil_strokes(Object *ob, Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - BKE_gpencil_convert_curve(bmain, scene, ob_gpencil, ob, gpencil_lines, use_collections); + BKE_gpencil_convert_curve(bmain, scene, ob_gpencil, ob, gpencil_lines, use_collections, false); WM_main_add_notifier(NC_GPENCIL | ND_DATA, NULL); diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c index 066e350ab3e..430059c7a18 100644 --- a/source/blender/makesrna/intern/rna_object_force.c +++ b/source/blender/makesrna/intern/rna_object_force.c @@ -87,15 +87,15 @@ static const EnumPropertyItem empty_shape_items[] = { static const EnumPropertyItem vortex_shape_items[] = { {PFIELD_SHAPE_POINT, "POINT", 0, "Point", ""}, {PFIELD_SHAPE_PLANE, "PLANE", 0, "Plane", ""}, - {PFIELD_SHAPE_SURFACE, "SURFACE", 0, "Surface falloff (New)", ""}, - {PFIELD_SHAPE_POINTS, "POINTS", 0, "Every Point (New)", ""}, + {PFIELD_SHAPE_SURFACE, "SURFACE", 0, "Surface", ""}, + {PFIELD_SHAPE_POINTS, "POINTS", 0, "Every Point", ""}, {0, NULL, 0, NULL, NULL}, }; static const EnumPropertyItem curve_vortex_shape_items[] = { {PFIELD_SHAPE_POINT, "POINT", 0, "Point", ""}, {PFIELD_SHAPE_PLANE, "PLANE", 0, "Plane", ""}, - {PFIELD_SHAPE_SURFACE, "SURFACE", 0, "Curve (New)", ""}, + {PFIELD_SHAPE_SURFACE, "SURFACE", 0, "Curve", ""}, {0, NULL, 0, NULL, NULL}, }; @@ -120,18 +120,38 @@ static const EnumPropertyItem empty_vortex_shape_items[] = { # include "ED_object.h" +static bool rna_Cache_get_valid_owner_ID(PointerRNA *ptr, Object **ob, Scene **scene) +{ + switch (GS(ptr->owner_id->name)) { + case ID_OB: + *ob = (Object *)ptr->owner_id; + break; + case ID_SCE: + *scene = (Scene *)ptr->owner_id; + break; + default: + BLI_assert(!"Trying to get PTCacheID from an invalid ID type " + "(Only scenes and objects are supported)."); + break; + } + + return (*ob != NULL || *scene != NULL); +} + static void rna_Cache_change(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; - PointCache *cache = (PointCache *)ptr->data; + Object *ob = NULL; + Scene *scene = NULL; - if (!ob) { + if (!rna_Cache_get_valid_owner_ID(ptr, &ob, &scene)) { return; } + PointCache *cache = (PointCache *)ptr->data; + cache->flag |= PTCACHE_OUTDATED; - PTCacheID pid = BKE_ptcache_id_find(ob, NULL, cache); + PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache); DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); @@ -146,14 +166,16 @@ static void rna_Cache_change(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerR static void rna_Cache_toggle_disk_cache(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; - PointCache *cache = (PointCache *)ptr->data; + Object *ob = NULL; + Scene *scene = NULL; - if (!ob) { + if (!rna_Cache_get_valid_owner_ID(ptr, &ob, &scene)) { return; } - PTCacheID pid = BKE_ptcache_id_find(ob, NULL, cache); + PointCache *cache = (PointCache *)ptr->data; + + PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache); /* smoke can only use disk cache */ if (pid.cache && pid.type != PTCACHE_TYPE_SMOKE_DOMAIN) { @@ -166,18 +188,20 @@ static void rna_Cache_toggle_disk_cache(Main *UNUSED(bmain), Scene *UNUSED(scene static void rna_Cache_idname_change(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; - PointCache *cache = (PointCache *)ptr->data; - bool use_new_name = true; + Object *ob = NULL; + Scene *scene = NULL; - if (!ob) { + if (!rna_Cache_get_valid_owner_ID(ptr, &ob, &scene)) { return; } + PointCache *cache = (PointCache *)ptr->data; + bool use_new_name = true; + /* TODO: check for proper characters */ if (cache->flag & PTCACHE_EXTERNAL) { - PTCacheID pid = BKE_ptcache_id_find(ob, NULL, cache); + PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache); if (pid.cache) { BKE_ptcache_load_external(&pid); @@ -190,7 +214,7 @@ static void rna_Cache_idname_change(Main *UNUSED(bmain), Scene *UNUSED(scene), P PTCacheID *pid = NULL, *pid2 = NULL; ListBase pidlist; - BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0); + BKE_ptcache_ids_from_object(&pidlist, ob, scene, 0); for (pid = pidlist.first; pid; pid = pid->next) { if (pid->cache == cache) { @@ -240,13 +264,19 @@ static void rna_Cache_list_begin(CollectionPropertyIterator *iter, PointerRNA *p static void rna_Cache_active_point_cache_index_range( PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax)) { - Object *ob = ptr->id.data; - PointCache *cache = ptr->data; - PTCacheID pid = BKE_ptcache_id_find(ob, NULL, cache); - *min = 0; *max = 0; + Object *ob = NULL; + Scene *scene = NULL; + + if (!rna_Cache_get_valid_owner_ID(ptr, &ob, &scene)) { + return; + } + + PointCache *cache = ptr->data; + PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache); + if (pid.cache) { *max = max_ii(0, BLI_listbase_count(pid.ptcaches) - 1); } @@ -254,11 +284,18 @@ static void rna_Cache_active_point_cache_index_range( static int rna_Cache_active_point_cache_index_get(PointerRNA *ptr) { - Object *ob = ptr->id.data; - PointCache *cache = ptr->data; - PTCacheID pid = BKE_ptcache_id_find(ob, NULL, cache); int num = 0; + Object *ob = NULL; + Scene *scene = NULL; + + if (!rna_Cache_get_valid_owner_ID(ptr, &ob, &scene)) { + return num; + } + + PointCache *cache = ptr->data; + PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache); + if (pid.cache) { num = BLI_findindex(pid.ptcaches, cache); } @@ -268,9 +305,15 @@ static int rna_Cache_active_point_cache_index_get(PointerRNA *ptr) static void rna_Cache_active_point_cache_index_set(struct PointerRNA *ptr, int value) { - Object *ob = ptr->id.data; + Object *ob = NULL; + Scene *scene = NULL; + + if (!rna_Cache_get_valid_owner_ID(ptr, &ob, &scene)) { + return; + } + PointCache *cache = ptr->data; - PTCacheID pid = BKE_ptcache_id_find(ob, NULL, cache); + PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache); if (pid.cache) { *(pid.cache_ptr) = BLI_findlink(pid.ptcaches, value); @@ -280,13 +323,19 @@ static void rna_Cache_active_point_cache_index_set(struct PointerRNA *ptr, int v static void rna_PointCache_frame_step_range( PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax)) { - Object *ob = ptr->id.data; - PointCache *cache = ptr->data; - PTCacheID pid = BKE_ptcache_id_find(ob, NULL, cache); - *min = 1; *max = 20; + Object *ob = NULL; + Scene *scene = NULL; + + if (!rna_Cache_get_valid_owner_ID(ptr, &ob, &scene)) { + return; + } + + PointCache *cache = ptr->data; + PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache); + if (pid.cache) { *max = pid.max_step; } @@ -294,14 +343,16 @@ static void rna_PointCache_frame_step_range( int rna_Cache_info_length(PointerRNA *ptr) { - PointCache *cache = (PointCache *)ptr->data; - Object *ob = (Object *)ptr->id.data; + Object *ob = NULL; + Scene *scene = NULL; - if (!ob) { + if (!rna_Cache_get_valid_owner_ID(ptr, &ob, &scene)) { return 0; } - PTCacheID pid = BKE_ptcache_id_find(ob, NULL, cache); + PointCache *cache = (PointCache *)ptr->data; + + PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache); if (cache->flag & PTCACHE_FLAG_INFO_DIRTY) { BKE_ptcache_update_info(&pid); @@ -314,7 +365,7 @@ static char *rna_CollisionSettings_path(PointerRNA *UNUSED(ptr)) { /* both methods work ok, but return the shorter path */ # if 0 - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; ModifierData *md = (ModifierData *)modifiers_findByType(ob, eModifierType_Collision); if (md) { @@ -334,13 +385,13 @@ static char *rna_CollisionSettings_path(PointerRNA *UNUSED(ptr)) static bool rna_SoftBodySettings_use_edges_get(PointerRNA *ptr) { - Object *data = (Object *)(ptr->id.data); + Object *data = (Object *)(ptr->owner_id); return (((data->softflag) & OB_SB_EDGES) != 0); } static void rna_SoftBodySettings_use_edges_set(PointerRNA *ptr, bool value) { - Object *data = (Object *)(ptr->id.data); + Object *data = (Object *)(ptr->owner_id); if (value) { data->softflag |= OB_SB_EDGES; } @@ -351,13 +402,13 @@ static void rna_SoftBodySettings_use_edges_set(PointerRNA *ptr, bool value) static bool rna_SoftBodySettings_use_goal_get(PointerRNA *ptr) { - Object *data = (Object *)(ptr->id.data); + Object *data = (Object *)(ptr->owner_id); return (((data->softflag) & OB_SB_GOAL) != 0); } static void rna_SoftBodySettings_use_goal_set(PointerRNA *ptr, bool value) { - Object *data = (Object *)(ptr->id.data); + Object *data = (Object *)(ptr->owner_id); if (value) { data->softflag |= OB_SB_GOAL; } @@ -368,13 +419,13 @@ static void rna_SoftBodySettings_use_goal_set(PointerRNA *ptr, bool value) static bool rna_SoftBodySettings_stiff_quads_get(PointerRNA *ptr) { - Object *data = (Object *)(ptr->id.data); + Object *data = (Object *)(ptr->owner_id); return (((data->softflag) & OB_SB_QUADS) != 0); } static void rna_SoftBodySettings_stiff_quads_set(PointerRNA *ptr, bool value) { - Object *data = (Object *)(ptr->id.data); + Object *data = (Object *)(ptr->owner_id); if (value) { data->softflag |= OB_SB_QUADS; } @@ -385,13 +436,13 @@ static void rna_SoftBodySettings_stiff_quads_set(PointerRNA *ptr, bool value) static bool rna_SoftBodySettings_self_collision_get(PointerRNA *ptr) { - Object *data = (Object *)(ptr->id.data); + Object *data = (Object *)(ptr->owner_id); return (((data->softflag) & OB_SB_SELF) != 0); } static void rna_SoftBodySettings_self_collision_set(PointerRNA *ptr, bool value) { - Object *data = (Object *)(ptr->id.data); + Object *data = (Object *)(ptr->owner_id); if (value) { data->softflag |= OB_SB_SELF; } @@ -402,7 +453,7 @@ static void rna_SoftBodySettings_self_collision_set(PointerRNA *ptr, bool value) static int rna_SoftBodySettings_new_aero_get(PointerRNA *ptr) { - Object *data = (Object *)(ptr->id.data); + Object *data = (Object *)(ptr->owner_id); if (data->softflag & OB_SB_AERO_ANGLE) { return 1; } @@ -413,7 +464,7 @@ static int rna_SoftBodySettings_new_aero_get(PointerRNA *ptr) static void rna_SoftBodySettings_new_aero_set(PointerRNA *ptr, int value) { - Object *data = (Object *)(ptr->id.data); + Object *data = (Object *)(ptr->owner_id); if (value == 1) { data->softflag |= OB_SB_AERO_ANGLE; } @@ -424,13 +475,13 @@ static void rna_SoftBodySettings_new_aero_set(PointerRNA *ptr, int value) static bool rna_SoftBodySettings_face_collision_get(PointerRNA *ptr) { - Object *data = (Object *)(ptr->id.data); + Object *data = (Object *)(ptr->owner_id); return (((data->softflag) & OB_SB_FACECOLL) != 0); } static void rna_SoftBodySettings_face_collision_set(PointerRNA *ptr, bool value) { - Object *data = (Object *)(ptr->id.data); + Object *data = (Object *)(ptr->owner_id); if (value) { data->softflag |= OB_SB_FACECOLL; } @@ -441,13 +492,13 @@ static void rna_SoftBodySettings_face_collision_set(PointerRNA *ptr, bool value) static bool rna_SoftBodySettings_edge_collision_get(PointerRNA *ptr) { - Object *data = (Object *)(ptr->id.data); + Object *data = (Object *)(ptr->owner_id); return (((data->softflag) & OB_SB_EDGECOLL) != 0); } static void rna_SoftBodySettings_edge_collision_set(PointerRNA *ptr, bool value) { - Object *data = (Object *)(ptr->id.data); + Object *data = (Object *)(ptr->owner_id); if (value) { data->softflag |= OB_SB_EDGECOLL; } @@ -488,7 +539,7 @@ static void rna_SoftBodySettings_spring_vgroup_set(PointerRNA *ptr, const char * static char *rna_SoftBodySettings_path(PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; ModifierData *md = (ModifierData *)modifiers_findByType(ob, eModifierType_Softbody); char name_esc[sizeof(md->name) * 2]; @@ -498,7 +549,7 @@ static char *rna_SoftBodySettings_path(PointerRNA *ptr) static int particle_id_check(PointerRNA *ptr) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; return (GS(id->name) == ID_PA); } @@ -506,7 +557,7 @@ static int particle_id_check(PointerRNA *ptr) static void rna_FieldSettings_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { if (particle_id_check(ptr)) { - ParticleSettings *part = (ParticleSettings *)ptr->id.data; + ParticleSettings *part = (ParticleSettings *)ptr->owner_id; if (part->pd->forcefield != PFIELD_TEXTURE && part->pd->tex) { id_us_min(&part->pd->tex->id); @@ -524,7 +575,7 @@ static void rna_FieldSettings_update(Main *UNUSED(bmain), Scene *UNUSED(scene), WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL); } else { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; if (ob->pd->forcefield != PFIELD_TEXTURE && ob->pd->tex) { id_us_min(&ob->pd->tex->id); @@ -539,7 +590,7 @@ static void rna_FieldSettings_update(Main *UNUSED(bmain), Scene *UNUSED(scene), static void rna_FieldSettings_shape_update(Main *bmain, Scene *scene, PointerRNA *ptr) { if (!particle_id_check(ptr)) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; ED_object_check_force_modifiers(bmain, scene, ob); DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM); @@ -555,7 +606,7 @@ static void rna_FieldSettings_type_set(PointerRNA *ptr, int value) part_deflect->forcefield = value; if (!particle_id_check(ptr)) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; ob->pd->forcefield = value; if (ELEM(value, PFIELD_WIND, PFIELD_VORTEX)) { ob->empty_drawtype = OB_SINGLE_ARROW; @@ -571,12 +622,12 @@ static void rna_FieldSettings_dependency_update(Main *bmain, Scene *scene, Point DEG_relations_tag_update(bmain); if (particle_id_check(ptr)) { - DEG_id_tag_update((ID *)ptr->id.data, + DEG_id_tag_update(ptr->owner_id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION | ID_RECALC_PSYS_RESET); } else { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; rna_FieldSettings_shape_update(bmain, scene, ptr); @@ -599,7 +650,7 @@ static char *rna_FieldSettings_path(PointerRNA *ptr) if (particle_id_check(ptr)) { /* particle system force field */ - ParticleSettings *part = (ParticleSettings *)ptr->id.data; + ParticleSettings *part = (ParticleSettings *)ptr->owner_id; if (part->pd == pd) { return BLI_strdup("force_field_1"); @@ -610,7 +661,7 @@ static char *rna_FieldSettings_path(PointerRNA *ptr) } else { /* object force field */ - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; if (ob->pd == pd) { return BLI_strdup("field"); @@ -621,7 +672,7 @@ static char *rna_FieldSettings_path(PointerRNA *ptr) static void rna_EffectorWeight_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; if (id && GS(id->name) == ID_SCE) { Scene *scene = (Scene *)id; @@ -642,7 +693,7 @@ static void rna_EffectorWeight_dependency_update(Main *bmain, { DEG_relations_tag_update(bmain); - DEG_id_tag_update((ID *)ptr->id.data, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET); + DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET); WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL); } @@ -654,14 +705,14 @@ static char *rna_EffectorWeight_path(PointerRNA *ptr) if (particle_id_check(ptr)) { /* particle effector weights */ - ParticleSettings *part = (ParticleSettings *)ptr->id.data; + ParticleSettings *part = (ParticleSettings *)ptr->owner_id; if (part->effector_weights == ew) { return BLI_strdup("effector_weights"); } } else { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; ModifierData *md; /* check softbody modifier */ @@ -727,7 +778,7 @@ static char *rna_EffectorWeight_path(PointerRNA *ptr) static void rna_CollisionSettings_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; ModifierData *md = modifiers_findByType(ob, eModifierType_Collision); /* add/remove modifier as needed */ @@ -745,7 +796,7 @@ static void rna_CollisionSettings_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION); WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob); @@ -753,7 +804,7 @@ static void rna_CollisionSettings_update(Main *UNUSED(bmain), static void rna_softbody_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob); @@ -776,7 +827,7 @@ static const EnumPropertyItem *rna_Effector_shape_itemf(bContext *UNUSED(C), return empty_shape_items; } - ob = (Object *)ptr->id.data; + ob = (Object *)ptr->owner_id; if (ob->type == OB_CURVE) { if (ob->pd->forcefield == PFIELD_VORTEX) { @@ -888,7 +939,7 @@ static void rna_def_pointcache_common(StructRNA *srna) prop = RNA_def_property(srna, "info", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "info"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); - /* Note that we do not actually need a getter here, `rna_Cache_info_length` will upate the info + /* Note that we do not actually need a getter here, `rna_Cache_info_length` will update the info * string just as well. */ RNA_def_property_string_funcs(prop, NULL, "rna_Cache_info_length", NULL); RNA_def_property_string_maxlength( @@ -1262,13 +1313,17 @@ static void rna_def_field(BlenderRNA *brna) ICON_FORCE_LENNARDJONES, "Lennard-Jones", "Forcefield based on the Lennard-Jones potential"}, - {PFIELD_TEXTURE, "TEXTURE", ICON_FORCE_TEXTURE, "Texture", "Forcefield based on a texture"}, + {PFIELD_TEXTURE, "TEXTURE", ICON_FORCE_TEXTURE, "Texture", "Force field based on a texture"}, {PFIELD_GUIDE, "GUIDE", ICON_FORCE_CURVE, "Curve Guide", "Create a force along a curve object"}, - {PFIELD_BOID, "BOID", ICON_FORCE_BOID, "Boid", ""}, + {PFIELD_BOID, + "BOID", + ICON_FORCE_BOID, + "Boid", + "Create a force that acts as a boid's predators or target"}, {PFIELD_TURBULENCE, "TURBULENCE", ICON_FORCE_TURBULENCE, diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index 86ce0ade96b..98ecb053641 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -146,7 +146,7 @@ static void rna_ParticleHairKey_location_object_info(PointerRNA *ptr, ParticleData **pa_pt) { HairKey *hkey = (HairKey *)ptr->data; - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; ModifierData *md; ParticleSystemModifierData *psmd = NULL; ParticleSystem *psys; @@ -193,7 +193,7 @@ static void rna_ParticleHairKey_location_object_info(PointerRNA *ptr, static void rna_ParticleHairKey_location_object_get(PointerRNA *ptr, float *values) { HairKey *hkey = (HairKey *)ptr->data; - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; ParticleSystemModifierData *psmd; ParticleData *pa; @@ -221,7 +221,7 @@ static void rna_ParticleHairKey_location_object_get(PointerRNA *ptr, float *valu static void rna_ParticleHairKey_location_object_set(PointerRNA *ptr, const float *values) { HairKey *hkey = (HairKey *)ptr->data; - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; ParticleSystemModifierData *psmd; ParticleData *pa; @@ -618,7 +618,7 @@ static void rna_ParticleSystem_mcol_on_emitter(ParticleSystem *particlesystem, static void particle_recalc(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr, short flag) { if (ptr->type == &RNA_ParticleSystem) { - Object *ob = ptr->id.data; + Object *ob = (Object *)ptr->owner_id; ParticleSystem *psys = (ParticleSystem *)ptr->data; psys->recalc = flag; @@ -626,7 +626,7 @@ static void particle_recalc(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRN DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); } else { - DEG_id_tag_update(ptr->id.data, ID_RECALC_GEOMETRY | flag); + DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY | flag); } WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, NULL); @@ -663,7 +663,7 @@ static void rna_Particle_reset_dependency(Main *bmain, Scene *scene, PointerRNA static void rna_Particle_change_type(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - ParticleSettings *part = ptr->id.data; + ParticleSettings *part = (ParticleSettings *)ptr->owner_id; /* Iterating over all object is slow, but no better solution exists at the moment. */ for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) { @@ -716,7 +716,7 @@ static void rna_Particle_redo_child(Main *bmain, Scene *scene, PointerRNA *ptr) static void rna_Particle_cloth_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob); @@ -741,7 +741,7 @@ static ParticleSystem *rna_particle_system_for_target(Object *ob, ParticleTarget static void rna_Particle_target_reset(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { if (ptr->type == &RNA_ParticleTarget) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; ParticleTarget *pt = (ParticleTarget *)ptr->data; ParticleSystem *kpsys = NULL, *psys = rna_particle_system_for_target(ob, pt); @@ -780,7 +780,7 @@ static void rna_Particle_target_reset(Main *bmain, Scene *UNUSED(scene), Pointer static void rna_Particle_target_redo(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { if (ptr->type == &RNA_ParticleTarget) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; ParticleTarget *pt = (ParticleTarget *)ptr->data; ParticleSystem *psys = rna_particle_system_for_target(ob, pt); @@ -793,7 +793,7 @@ static void rna_Particle_target_redo(Main *UNUSED(bmain), Scene *UNUSED(scene), static void rna_Particle_hair_dynamics_update(Main *bmain, Scene *scene, PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; ParticleSystem *psys = (ParticleSystem *)ptr->data; if (psys && !psys->clmd) { @@ -823,7 +823,7 @@ static void rna_particle_settings_set(PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) { - Object *ob = ptr->id.data; + Object *ob = (Object *)ptr->owner_id; ParticleSystem *psys = (ParticleSystem *)ptr->data; int old_type = 0; @@ -1000,7 +1000,7 @@ static void rna_ParticleSettings_use_twist_curve_update(Main *bmain, Scene *scen static void rna_ParticleSystem_name_set(PointerRNA *ptr, const char *value) { - Object *ob = ptr->id.data; + Object *ob = (Object *)ptr->owner_id; ParticleSystem *part = (ParticleSystem *)ptr->data; /* copy the new name into the name slot */ @@ -1076,7 +1076,7 @@ static void rna_ParticleTarget_name_get(PointerRNA *ptr, char *str) psys = BLI_findlink(&pt->ob->particlesystem, pt->psys - 1); } else { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; psys = BLI_findlink(&ob->particlesystem, pt->psys - 1); } @@ -1108,7 +1108,7 @@ static int rna_ParticleTarget_name_length(PointerRNA *ptr) static int particle_id_check(PointerRNA *ptr) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; return (GS(id->name) == ID_PA); } @@ -1118,7 +1118,7 @@ static char *rna_SPHFluidSettings_path(PointerRNA *ptr) SPHFluidSettings *fluid = (SPHFluidSettings *)ptr->data; if (particle_id_check(ptr)) { - ParticleSettings *part = (ParticleSettings *)ptr->id.data; + ParticleSettings *part = (ParticleSettings *)ptr->owner_id; if (part->fluid == fluid) { return BLI_strdup("fluid"); @@ -1152,7 +1152,7 @@ static bool rna_ParticleSystem_edited_get(PointerRNA *ptr) } static PointerRNA rna_ParticleDupliWeight_active_get(PointerRNA *ptr) { - ParticleSettings *part = (ParticleSettings *)ptr->id.data; + ParticleSettings *part = (ParticleSettings *)ptr->owner_id; ParticleDupliWeight *dw = part->instance_weights.first; for (; dw; dw = dw->next) { @@ -1165,14 +1165,14 @@ static PointerRNA rna_ParticleDupliWeight_active_get(PointerRNA *ptr) static void rna_ParticleDupliWeight_active_index_range( PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax)) { - ParticleSettings *part = (ParticleSettings *)ptr->id.data; + ParticleSettings *part = (ParticleSettings *)ptr->owner_id; *min = 0; *max = max_ii(0, BLI_listbase_count(&part->instance_weights) - 1); } static int rna_ParticleDupliWeight_active_index_get(PointerRNA *ptr) { - ParticleSettings *part = (ParticleSettings *)ptr->id.data; + ParticleSettings *part = (ParticleSettings *)ptr->owner_id; ParticleDupliWeight *dw = part->instance_weights.first; int i = 0; @@ -1187,7 +1187,7 @@ static int rna_ParticleDupliWeight_active_index_get(PointerRNA *ptr) static void rna_ParticleDupliWeight_active_index_set(struct PointerRNA *ptr, int value) { - ParticleSettings *part = (ParticleSettings *)ptr->id.data; + ParticleSettings *part = (ParticleSettings *)ptr->owner_id; ParticleDupliWeight *dw = part->instance_weights.first; int i = 0; @@ -1203,7 +1203,7 @@ static void rna_ParticleDupliWeight_active_index_set(struct PointerRNA *ptr, int static void rna_ParticleDupliWeight_name_get(PointerRNA *ptr, char *str) { - ParticleSettings *part = (ParticleSettings *)ptr->id.data; + ParticleSettings *part = (ParticleSettings *)ptr->owner_id; psys_find_group_weights(part); ParticleDupliWeight *dw = ptr->data; @@ -1241,7 +1241,7 @@ static const EnumPropertyItem *rna_Particle_dist_itemf(bContext *UNUSED(C), PropertyRNA *UNUSED(prop), bool *UNUSED(r_free)) { - ParticleSettings *part = ptr->id.data; + ParticleSettings *part = (ParticleSettings *)ptr->owner_id; if (part->type == PART_HAIR) { return part_hair_dist_items; @@ -1256,7 +1256,7 @@ static const EnumPropertyItem *rna_Particle_draw_as_itemf(bContext *UNUSED(C), PropertyRNA *UNUSED(prop), bool *UNUSED(r_free)) { - ParticleSettings *part = ptr->id.data; + ParticleSettings *part = (ParticleSettings *)ptr->owner_id; if (part->type == PART_HAIR) { return part_hair_draw_as_items; @@ -1271,7 +1271,7 @@ static const EnumPropertyItem *rna_Particle_ren_as_itemf(bContext *UNUSED(C), PropertyRNA *UNUSED(prop), bool *UNUSED(r_free)) { - ParticleSettings *part = ptr->id.data; + ParticleSettings *part = (ParticleSettings *)ptr->owner_id; if (part->type == PART_HAIR) { return part_hair_ren_as_items; @@ -1283,7 +1283,7 @@ static const EnumPropertyItem *rna_Particle_ren_as_itemf(bContext *UNUSED(C), static PointerRNA rna_Particle_field1_get(PointerRNA *ptr) { - ParticleSettings *part = (ParticleSettings *)ptr->id.data; + ParticleSettings *part = (ParticleSettings *)ptr->owner_id; /* weak */ if (!part->pd) { @@ -1295,7 +1295,7 @@ static PointerRNA rna_Particle_field1_get(PointerRNA *ptr) static PointerRNA rna_Particle_field2_get(PointerRNA *ptr) { - ParticleSettings *part = (ParticleSettings *)ptr->id.data; + ParticleSettings *part = (ParticleSettings *)ptr->owner_id; /* weak */ if (!part->pd2) { @@ -1307,7 +1307,7 @@ static PointerRNA rna_Particle_field2_get(PointerRNA *ptr) static void psys_vg_name_get__internal(PointerRNA *ptr, char *value, int index) { - Object *ob = ptr->id.data; + Object *ob = (Object *)ptr->owner_id; ParticleSystem *psys = (ParticleSystem *)ptr->data; if (psys->vgroup[index] > 0) { @@ -1323,7 +1323,7 @@ static void psys_vg_name_get__internal(PointerRNA *ptr, char *value, int index) } static int psys_vg_name_len__internal(PointerRNA *ptr, int index) { - Object *ob = ptr->id.data; + Object *ob = (Object *)ptr->owner_id; ParticleSystem *psys = (ParticleSystem *)ptr->data; if (psys->vgroup[index] > 0) { @@ -1337,7 +1337,7 @@ static int psys_vg_name_len__internal(PointerRNA *ptr, int index) } static void psys_vg_name_set__internal(PointerRNA *ptr, const char *value, int index) { - Object *ob = ptr->id.data; + Object *ob = (Object *)ptr->owner_id; ParticleSystem *psys = (ParticleSystem *)ptr->data; if (value[0] == '\0') { @@ -2041,6 +2041,7 @@ static void rna_def_particle_settings_mtex(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "object"); RNA_def_property_struct_type(prop, "Object"); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text( prop, "Object", "Object to use for mapping with Object texture coordinates"); RNA_def_property_update(prop, 0, "rna_Particle_reset_dependency"); @@ -2986,6 +2987,7 @@ static void rna_def_particle_settings(BlenderRNA *brna) RNA_def_property_struct_type(prop, "Collection"); RNA_def_property_pointer_sdna(prop, NULL, "collision_group"); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Collision Collection", "Limit colliders to this collection"); RNA_def_property_update(prop, 0, "rna_Particle_reset_dependency"); @@ -3313,6 +3315,7 @@ static void rna_def_particle_settings(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "instance_collection"); RNA_def_property_struct_type(prop, "Collection"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text( prop, "Dupli Collection", "Show Objects in this collection in place of particles"); RNA_def_property_update(prop, 0, "rna_Particle_redo_count"); @@ -3338,6 +3341,7 @@ static void rna_def_particle_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "instance_object", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "Object"); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Instance Object", "Show this Object in place of particles"); RNA_def_property_update(prop, 0, "rna_Particle_redo_dependency"); @@ -3456,6 +3460,7 @@ static void rna_def_particle_target(BlenderRNA *brna) prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "ob"); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text( prop, "Target Object", @@ -3570,6 +3575,7 @@ static void rna_def_particle_system(BlenderRNA *brna) prop = RNA_def_property(srna, "reactor_target_object", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "target_ob"); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Reactor Target Object", "For reactor systems, the object that has the target particle system " @@ -3822,6 +3828,7 @@ static void rna_def_particle_system(BlenderRNA *brna) prop = RNA_def_property(srna, "parent", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "parent"); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text( prop, "Parent", "Use this object's coordinate system instead of global coordinate system"); RNA_def_property_update(prop, 0, "rna_Particle_redo"); diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index d359726b3bd..33d7d7d99cf 100644 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -99,25 +99,25 @@ static void rna_Pose_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRN { /* XXX when to use this? ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK); */ - DEG_id_tag_update(ptr->id.data, ID_RECALC_GEOMETRY); - WM_main_add_notifier(NC_OBJECT | ND_POSE, ptr->id.data); + DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY); + WM_main_add_notifier(NC_OBJECT | ND_POSE, ptr->owner_id); } static void rna_Pose_dependency_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { DEG_relations_tag_update(bmain); - DEG_id_tag_update(ptr->id.data, ID_RECALC_GEOMETRY); - WM_main_add_notifier(NC_OBJECT | ND_POSE, ptr->id.data); + DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY); + WM_main_add_notifier(NC_OBJECT | ND_POSE, ptr->owner_id); } static void rna_Pose_IK_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { /* XXX when to use this? ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK); */ - Object *ob = ptr->id.data; + Object *ob = (Object *)ptr->owner_id; DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - WM_main_add_notifier(NC_OBJECT | ND_POSE, ptr->id.data); + WM_main_add_notifier(NC_OBJECT | ND_POSE, ptr->owner_id); BIK_clear_data(ob->pose); } @@ -183,7 +183,7 @@ bool rna_ActionGroup_is_custom_colorset_get(PointerRNA *ptr) static void rna_BoneGroup_name_set(PointerRNA *ptr, const char *value) { - Object *ob = ptr->id.data; + Object *ob = (Object *)ptr->owner_id; bActionGroup *agrp = ptr->data; /* copy the new name into the name slot */ @@ -227,7 +227,7 @@ static void rna_Pose_ik_solver_set(struct PointerRNA *ptr, int value) static void rna_Pose_ik_solver_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - Object *ob = ptr->id.data; + Object *ob = (Object *)ptr->owner_id; bPose *pose = ptr->data; BKE_pose_tag_recalc(bmain, pose); /* checks & sorts pose channels */ @@ -276,7 +276,7 @@ static void rna_PoseChannel_rotation_mode_set(PointerRNA *ptr, int value) static void rna_PoseChannel_name_set(PointerRNA *ptr, const char *value) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; bPoseChannel *pchan = (bPoseChannel *)ptr->data; char oldname[sizeof(pchan->name)], newname[sizeof(pchan->name)]; @@ -291,19 +291,19 @@ static void rna_PoseChannel_name_set(PointerRNA *ptr, const char *value) static PointerRNA rna_PoseChannel_bone_get(PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; bPoseChannel *pchan = (bPoseChannel *)ptr->data; PointerRNA tmp_ptr = *ptr; /* Replace the id_data pointer with the Armature ID. */ - tmp_ptr.id.data = ob->data; + tmp_ptr.owner_id = ob->data; return rna_pointer_inherit_refine(&tmp_ptr, &RNA_Bone, pchan->bone); } static bool rna_PoseChannel_has_ik_get(PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; bPoseChannel *pchan = (bPoseChannel *)ptr->data; return BKE_pose_channel_in_IK_chain(ob, pchan); @@ -341,7 +341,7 @@ static StructRNA *rna_Pose_ikparam_typef(PointerRNA *ptr) static void rna_Itasc_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Object *ob = ptr->id.data; + Object *ob = (Object *)ptr->owner_id; bItasc *itasc = ptr->data; /* verify values */ @@ -373,7 +373,7 @@ static void rna_Itasc_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerR static void rna_Itasc_update_rebuild(Main *bmain, Scene *scene, PointerRNA *ptr) { - Object *ob = ptr->id.data; + Object *ob = (Object *)ptr->owner_id; bPose *pose = ob->pose; BKE_pose_tag_recalc(bmain, pose); /* checks & sorts pose channels */ @@ -398,7 +398,7 @@ static void rna_PoseChannel_bone_custom_set(PointerRNA *ptr, static PointerRNA rna_PoseChannel_bone_group_get(PointerRNA *ptr) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; bPose *pose = (ob) ? ob->pose : NULL; bPoseChannel *pchan = (bPoseChannel *)ptr->data; bActionGroup *grp; @@ -417,7 +417,7 @@ static void rna_PoseChannel_bone_group_set(PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; bPose *pose = (ob) ? ob->pose : NULL; bPoseChannel *pchan = (bPoseChannel *)ptr->data; @@ -444,7 +444,7 @@ static void rna_PoseChannel_bone_group_index_set(PointerRNA *ptr, int value) static void rna_PoseChannel_bone_group_index_range( PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax)) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; bPose *pose = (ob) ? ob->pose : NULL; *min = 0; @@ -663,7 +663,7 @@ bool rna_PoseChannel_constraints_override_apply(Main *UNUSED(bmain), static int rna_PoseChannel_proxy_editable(PointerRNA *ptr, const char **r_info) { - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; bArmature *arm = ob->data; bPoseChannel *pchan = (bPoseChannel *)ptr->data; @@ -762,7 +762,7 @@ static int rna_PoseBones_lookup_string(PointerRNA *ptr, const char *key, Pointer bPose *pose = (bPose *)ptr->data; bPoseChannel *pchan = BKE_pose_channel_find_name(pose, key); if (pchan) { - RNA_pointer_create(ptr->id.data, &RNA_PoseBone, pchan, r_ptr); + RNA_pointer_create(ptr->owner_id, &RNA_PoseBone, pchan, r_ptr); return true; } else { @@ -785,7 +785,7 @@ static void rna_PoseChannel_matrix_basis_set(PointerRNA *ptr, const float *value static void rna_PoseChannel_matrix_set(PointerRNA *ptr, const float *values) { bPoseChannel *pchan = (bPoseChannel *)ptr->data; - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; float tmat[4][4]; BKE_armature_mat_pose_to_bone_ex(NULL, ob, pchan, (float(*)[4])values, tmat); @@ -812,9 +812,9 @@ static void rna_PoseChannel_custom_shape_transform_set(PointerRNA *ptr, struct ReportList *UNUSED(reports)) { bPoseChannel *pchan = (bPoseChannel *)ptr->data; - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; - pchan->custom_tx = rna_PoseChannel_ensure_own_pchan(ob, value.id.data, value.data); + pchan->custom_tx = rna_PoseChannel_ensure_own_pchan(ob, (Object *)value.owner_id, value.data); } #else @@ -1044,7 +1044,7 @@ static void rna_def_pose_channel(BlenderRNA *brna) RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update"); /* Curved bones settings - Applied on top of restpose values */ - rna_def_bone_curved_common(srna, true); + rna_def_bone_curved_common(srna, true, false); /* Custom BBone next/prev sources */ prop = RNA_def_property(srna, "bbone_custom_handle_start", PROP_POINTER, PROP_NONE); @@ -1256,6 +1256,7 @@ static void rna_def_pose_channel(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "custom"); RNA_def_property_struct_type(prop, "Object"); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON); RNA_def_property_pointer_funcs(prop, NULL, "rna_PoseChannel_bone_custom_set", NULL, NULL); RNA_def_property_ui_text( prop, "Custom Object", "Object that defines custom draw type for this bone"); diff --git a/source/blender/makesrna/intern/rna_rigidbody.c b/source/blender/makesrna/intern/rna_rigidbody.c index cb6776c2c06..03937a5434e 100644 --- a/source/blender/makesrna/intern/rna_rigidbody.c +++ b/source/blender/makesrna/intern/rna_rigidbody.c @@ -215,7 +215,7 @@ static void rna_RigidBodyOb_reset(Main *UNUSED(bmain), Scene *scene, PointerRNA static void rna_RigidBodyOb_shape_update(Main *bmain, Scene *scene, PointerRNA *ptr) { - Object *ob = ptr->id.data; + Object *ob = (Object *)ptr->owner_id; rna_RigidBodyOb_reset(bmain, scene, ptr); @@ -859,6 +859,7 @@ static void rna_def_rigidbody_world(BlenderRNA *brna) RNA_def_property_struct_type(prop, "Collection"); RNA_def_property_pointer_sdna(prop, NULL, "group"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text( prop, "Collection", "Collection containing objects participating in this simulation"); RNA_def_property_update(prop, NC_SCENE, "rna_RigidBodyWorld_objects_collection_update"); @@ -866,6 +867,7 @@ static void rna_def_rigidbody_world(BlenderRNA *brna) prop = RNA_def_property(srna, "constraints", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "Collection"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text( prop, "Constraints", "Collection containing rigid body constraint objects"); RNA_def_property_update(prop, NC_SCENE, "rna_RigidBodyWorld_constraints_collection_update"); @@ -1224,15 +1226,15 @@ static void rna_def_rigidbody_constraint(BlenderRNA *brna) prop = RNA_def_property(srna, "object1", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "ob1"); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Object 1", "First Rigid Body Object to be constrained"); - RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); prop = RNA_def_property(srna, "object2", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "ob2"); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Object 2", "Second Rigid Body Object to be constrained"); - RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); /* Breaking Threshold */ diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c index 631ad72e146..6e21d02c0b3 100644 --- a/source/blender/makesrna/intern/rna_rna.c +++ b/source/blender/makesrna/intern/rna_rna.c @@ -388,10 +388,10 @@ void rna_builtin_properties_begin(CollectionPropertyIterator *iter, PointerRNA * newptr.data = ptr->type; if (ptr->type->flag & STRUCT_ID) { - newptr.id.data = ptr->data; + newptr.owner_id = ptr->data; } else { - newptr.id.data = NULL; + newptr.owner_id = NULL; } iter->parent = newptr; @@ -414,7 +414,7 @@ int rna_builtin_properties_lookup_string(PointerRNA *ptr, const char *key, Point { StructRNA *srna; PropertyRNA *prop; - PointerRNA propptr = {{NULL}}; + PointerRNA propptr = {NULL}; srna = ptr->type; @@ -770,7 +770,8 @@ static void rna_IntProperty_default_array_get(PointerRNA *ptr, int *values) PropertyRNA *prop = (PropertyRNA *)ptr->data; rna_idproperty_check(&prop, ptr); if (prop->totarraylength > 0) { - RNA_property_int_get_default_array(ptr, prop, values); + PointerRNA null_ptr = PointerRNA_NULL; + RNA_property_int_get_default_array(&null_ptr, prop, values); } } @@ -779,7 +780,8 @@ static void rna_BoolProperty_default_array_get(PointerRNA *ptr, bool *values) PropertyRNA *prop = (PropertyRNA *)ptr->data; rna_idproperty_check(&prop, ptr); if (prop->totarraylength > 0) { - RNA_property_boolean_get_default_array(ptr, prop, values); + PointerRNA null_ptr = PointerRNA_NULL; + RNA_property_boolean_get_default_array(&null_ptr, prop, values); } } @@ -788,7 +790,8 @@ static void rna_FloatProperty_default_array_get(PointerRNA *ptr, float *values) PropertyRNA *prop = (PropertyRNA *)ptr->data; rna_idproperty_check(&prop, ptr); if (prop->totarraylength > 0) { - RNA_property_float_get_default_array(ptr, prop, values); + PointerRNA null_ptr = PointerRNA_NULL; + RNA_property_float_get_default_array(&null_ptr, prop, values); } } @@ -1226,7 +1229,7 @@ static bool rna_property_override_diff_propptr_validate_diffing(PointerRNA *prop } if (*r_is_id) { - BLI_assert(propptr_a->data == propptr_a->id.data && propptr_b->data == propptr_b->id.data); + BLI_assert(propptr_a->data == propptr_a->owner_id && propptr_b->data == propptr_b->owner_id); } return is_valid_for_diffing; @@ -1241,6 +1244,10 @@ static int rna_property_override_diff_propptr(Main *bmain, const bool no_prop_name, IDOverrideLibrary *override, const char *rna_path, + const char *rna_itemname_a, + const char *rna_itemname_b, + const int rna_itemindex_a, + const int rna_itemindex_b, const int flags, bool *r_override_changed) { @@ -1282,9 +1289,18 @@ static int rna_property_override_diff_propptr(Main *bmain, IDOverrideLibraryProperty *op = BKE_override_library_property_get( override, rna_path, &created); - if (op != NULL && created) { /* If not yet overridden... */ - BKE_override_library_property_operation_get( - op, IDOVERRIDE_LIBRARY_OP_REPLACE, NULL, NULL, -1, -1, true, NULL, NULL); + /* If not yet overridden, or if we are handling sub-items (inside a collection)... */ + if (op != NULL && (created || rna_itemname_a != NULL || rna_itemname_b != NULL || + rna_itemindex_a != -1 || rna_itemindex_b != -1)) { + BKE_override_library_property_operation_get(op, + IDOVERRIDE_LIBRARY_OP_REPLACE, + rna_itemname_b, + rna_itemname_a, + rna_itemindex_b, + rna_itemindex_a, + true, + NULL, + &created); if (r_override_changed) { *r_override_changed = created; } @@ -1294,12 +1310,56 @@ static int rna_property_override_diff_propptr(Main *bmain, return comp; } else { + /* In case we got some array/collection like items identifiers, now is the time to generate a + * proper rna path from those. */ +# define RNA_PATH_BUFFSIZE 8192 + + char extended_rna_path_buffer[RNA_PATH_BUFFSIZE]; + char *extended_rna_path = extended_rna_path_buffer; + +# define RNA_PATH_PRINTF(_str, ...) \ + if (BLI_snprintf(extended_rna_path_buffer, RNA_PATH_BUFFSIZE, (_str), __VA_ARGS__) >= \ + RNA_PATH_BUFFSIZE - 1) { \ + extended_rna_path = BLI_sprintfN((_str), __VA_ARGS__); \ + } \ + (void)0 +# define RNA_PATH_FREE() \ + if (extended_rna_path != extended_rna_path_buffer && extended_rna_path != rna_path) \ + MEM_freeN(extended_rna_path) + + /* There may be a propname defined in some cases, while no actual name set + * (e.g. happens with point cache), in that case too we want to fall back to index. + * Note that we do not need the RNA path for insertion operations. */ + if (rna_path) { + if ((rna_itemname_a != NULL && rna_itemname_a[0] != '\0') && + (rna_itemname_b != NULL && rna_itemname_b[0] != '\0')) { + BLI_assert(STREQ(rna_itemname_a, rna_itemname_b)); + char esc_item_name[RNA_PATH_BUFFSIZE]; + BLI_strescape(esc_item_name, rna_itemname_a, RNA_PATH_BUFFSIZE); + RNA_PATH_PRINTF("%s[\"%s\"]", rna_path, esc_item_name); + } + else if (rna_itemindex_a != -1) { /* Based on index... */ + BLI_assert(rna_itemindex_a == rna_itemindex_b); + RNA_PATH_PRINTF("%s[%d]", rna_path, rna_itemindex_a); + } + else { + extended_rna_path = (char *)rna_path; + } + } + eRNAOverrideMatchResult report_flags = 0; const bool match = RNA_struct_override_matches( - bmain, propptr_a, propptr_b, rna_path, override, flags, &report_flags); + bmain, propptr_a, propptr_b, extended_rna_path, override, flags, &report_flags); if (r_override_changed && (report_flags & RNA_OVERRIDE_MATCH_RESULT_CREATED) != 0) { *r_override_changed = true; } + + RNA_PATH_FREE(); + +# undef RNA_PATH_BUFFSIZE +# undef RNA_PATH_PRINTF +# undef RNA_PATH_FREE + return !match; } } @@ -1616,6 +1676,10 @@ int rna_property_override_diff_default(Main *bmain, no_prop_name, override, rna_path, + NULL, + NULL, + -1, + -1, flags, r_override_changed); } @@ -1636,21 +1700,6 @@ int rna_property_override_diff_default(Main *bmain, int idx_a = 0; int idx_b = 0; -# define RNA_PATH_BUFFSIZE 8192 - - char extended_rna_path_buffer[RNA_PATH_BUFFSIZE]; - char *extended_rna_path = extended_rna_path_buffer; - -# define RNA_PATH_PRINTF(_str, ...) \ - if (BLI_snprintf(extended_rna_path_buffer, RNA_PATH_BUFFSIZE, (_str), __VA_ARGS__) >= \ - RNA_PATH_BUFFSIZE - 1) { \ - extended_rna_path = BLI_sprintfN((_str), __VA_ARGS__); \ - } \ - (void)0 -# define RNA_PATH_FREE() \ - if (extended_rna_path != extended_rna_path_buffer) \ - MEM_freeN(extended_rna_path) - CollectionPropertyIterator iter_a, iter_b; RNA_property_collection_begin(ptr_a, prop_a, &iter_a); RNA_property_collection_begin(ptr_b, prop_b, &iter_b); @@ -1730,41 +1779,15 @@ int rna_property_override_diff_default(Main *bmain, # endif if (!(is_id || is_valid_for_diffing || is_valid_for_insertion)) { - /* Differences we cannot handle, we can break here - * (we do not support replacing ID pointers in collections e.g.). */ + /* Differences we cannot handle, we can break here. */ equals = false; abort = true; break; } - /* There may be a propname defined in some cases, while no actual name set - * (e.g. happens with point cache), in that case too we want to fall back to index. - * Note that we do not need the RNA path for insertion operations. */ - if (is_id || is_valid_for_diffing) { - if ((propname_a != NULL && propname_a[0] != '\0') && - (propname_b != NULL && propname_b[0] != '\0')) { - if (rna_path) { - /* In case of name, either it is valid for diffing, and _a and _b are identical, - * or it is valid for insertion, and we need to use _a. */ - char esc_item_name[RNA_PATH_BUFFSIZE]; - BLI_strescape(esc_item_name, propname_a, RNA_PATH_BUFFSIZE); - RNA_PATH_PRINTF("%s[\"%s\"]", rna_path, esc_item_name); - } - } - else { /* Based on index... */ - if (rna_path) { - /* In case of indices, we need _a one for insertion, - * but _b ones for in-depth diffing. - * Insertion always happen once all 'replace' operations have been done, - * otherwise local and reference paths for those would have to be different! */ - RNA_PATH_PRINTF("%s[%d]", rna_path, is_valid_for_insertion ? idx_a : idx_b); - } - } - } - - /* Collections do not support replacement of their data - * (since they do not support removing), only in *some* cases, insertion. - * We also assume then that _a data is the one where things are inserted. */ + /* Collections do not support replacement of their data (except for collections of ID + * pointers), since they do not support removing, only in *some* cases, insertion. We + * also assume then that _a data is the one where things are inserted. */ if (is_valid_for_insertion && use_insertion) { bool created; IDOverrideLibraryProperty *op = BKE_override_library_property_get( @@ -1812,7 +1835,11 @@ int rna_property_override_diff_default(Main *bmain, no_ownership, no_prop_name, override, - extended_rna_path, + rna_path, + propname_a, + propname_b, + idx_a, + idx_b, flags, r_override_changed); equals = equals && eq; @@ -1839,7 +1866,6 @@ int rna_property_override_diff_default(Main *bmain, propname_b = buff_b; } propname_b[0] = '\0'; - RNA_PATH_FREE(); if (!do_create && !equals) { abort = true; /* Early out in case we do not want to loop over whole collection. */ @@ -1864,10 +1890,6 @@ int rna_property_override_diff_default(Main *bmain, RNA_property_collection_next(&iter_b); idx_b++; } - -# undef RNA_PATH_BUFFSIZE -# undef RNA_PATH_PRINTF -# undef RNA_PATH_FREE } /* Not same number of items in both collections. */ diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 4397d204972..3d2d91d2334 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -168,6 +168,16 @@ const EnumPropertyItem rna_enum_snap_element_items[] = { {SCE_SNAP_MODE_EDGE, "EDGE", ICON_SNAP_EDGE, "Edge", "Snap to edges"}, {SCE_SNAP_MODE_FACE, "FACE", ICON_SNAP_FACE, "Face", "Snap to faces"}, {SCE_SNAP_MODE_VOLUME, "VOLUME", ICON_SNAP_VOLUME, "Volume", "Snap to volume"}, + {SCE_SNAP_MODE_EDGE_MIDPOINT, + "EDGE_MIDPOINT", + ICON_SNAP_MIDPOINT, + "Edge Center", + "Snap to the middle of edges"}, + {SCE_SNAP_MODE_EDGE_PERPENDICULAR, + "EDGE_PERPENDICULAR", + ICON_SNAP_PERPENDICULAR, + "Edge Perpendicular", + "Snap to the nearest point on an edge"}, {0, NULL, 0, NULL, NULL}, }; @@ -740,6 +750,65 @@ static void rna_GPencilInterpolateSettings_type_set(PointerRNA *ptr, int value) } } +static void rna_Gpencil_selectmode_update(bContext *C, PointerRNA *ptr) +{ + ToolSettings *ts = (ToolSettings *)ptr->data; + /* If the mode is not Stroke, don't extend selection. */ + if ((ts->gpencil_selectmode_edit & GP_SELECTMODE_STROKE) == 0) { + return; + } + + /* Extend selection to all points in all selected strokes. */ + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *ob = OBACT(view_layer); + if ((ob) && (ob->type == OB_GPENCIL)) { + bGPdata *gpd = (bGPdata *)ob->data; + CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) { + if ((gps->flag & GP_STROKE_SELECT) && (gps->totpoints > 1)) { + bGPDspoint *pt; + for (int i = 0; i < gps->totpoints; i++) { + pt = &gps->points[i]; + pt->flag |= GP_SPOINT_SELECT; + } + } + } + CTX_DATA_END; + + gpd->flag |= GP_DATA_CACHE_IS_DIRTY; + DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); + } +} + +static void rna_Gpencil_mask_point_update(Main *UNUSED(bmain), + Scene *UNUSED(scene), + PointerRNA *ptr) +{ + ToolSettings *ts = (ToolSettings *)ptr->data; + + ts->gpencil_selectmode_sculpt &= ~GP_SCULPT_MASK_SELECTMODE_STROKE; + ts->gpencil_selectmode_sculpt &= ~GP_SCULPT_MASK_SELECTMODE_SEGMENT; +} + +static void rna_Gpencil_mask_stroke_update(Main *UNUSED(bmain), + Scene *UNUSED(scene), + PointerRNA *ptr) +{ + ToolSettings *ts = (ToolSettings *)ptr->data; + + ts->gpencil_selectmode_sculpt &= ~GP_SCULPT_MASK_SELECTMODE_POINT; + ts->gpencil_selectmode_sculpt &= ~GP_SCULPT_MASK_SELECTMODE_SEGMENT; +} + +static void rna_Gpencil_mask_segment_update(Main *UNUSED(bmain), + Scene *UNUSED(scene), + PointerRNA *ptr) +{ + ToolSettings *ts = (ToolSettings *)ptr->data; + + ts->gpencil_selectmode_sculpt &= ~GP_SCULPT_MASK_SELECTMODE_POINT; + ts->gpencil_selectmode_sculpt &= ~GP_SCULPT_MASK_SELECTMODE_STROKE; +} + /* Read-only Iterator of all the scene objects. */ static void rna_Scene_objects_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) @@ -796,7 +865,7 @@ static void rna_Scene_set_set(PointerRNA *ptr, void rna_Scene_set_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; DEG_relations_tag_update(bmain); DEG_id_tag_update_ex(bmain, &scene->id, 0); @@ -822,8 +891,8 @@ static void rna_Scene_fps_update(Main *bmain, Scene *scene, PointerRNA *UNUSED(p { DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_FPS | ID_RECALC_SEQUENCER_STRIPS); /* NOTE: Tag via dependency graph will take care of all the updates ion the evaluated domain, - * however, changes in FPS actually modifies an original stip length, so this we take care about - * here. */ + * however, changes in FPS actually modifies an original skip length, + * so this we take care about here. */ BKE_sequencer_refresh_sound_length(bmain, scene); } @@ -834,7 +903,7 @@ static void rna_Scene_listener_update(Main *UNUSED(bmain), Scene *scene, Pointer static void rna_Scene_volume_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_VOLUME | ID_RECALC_SEQUENCER_STRIPS); } @@ -958,7 +1027,7 @@ static void rna_Scene_show_subframe_update(Main *UNUSED(bmain), Scene *UNUSED(current_scene), PointerRNA *ptr) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; scene->r.subframe = 0.0f; } @@ -966,7 +1035,7 @@ static void rna_Scene_frame_update(Main *UNUSED(bmain), Scene *UNUSED(current_scene), PointerRNA *ptr) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_SEEK); WM_main_add_notifier(NC_SCENE | ND_FRAME, scene); } @@ -1079,7 +1148,7 @@ static char *rna_BakeSettings_path(PointerRNA *UNUSED(ptr)) static char *rna_ImageFormatSettings_path(PointerRNA *ptr) { ImageFormatData *imf = (ImageFormatData *)ptr->data; - ID *id = ptr->id.data; + ID *id = ptr->owner_id; switch (GS(id->name)) { case ID_SCE: { @@ -1150,7 +1219,7 @@ static bool rna_RenderSettings_is_movie_format_get(PointerRNA *ptr) static void rna_ImageFormatSettings_file_format_set(PointerRNA *ptr, int value) { ImageFormatData *imf = (ImageFormatData *)ptr->data; - ID *id = ptr->id.data; + ID *id = ptr->owner_id; imf->imtype = value; const bool is_render = (id && GS(id->name) == ID_SCE); @@ -1191,7 +1260,7 @@ static void rna_ImageFormatSettings_file_format_set(PointerRNA *ptr, int value) } if (id && GS(id->name) == ID_SCE) { - Scene *scene = ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; RenderData *rd = &scene->r; # ifdef WITH_FFMPEG BKE_ffmpeg_image_type_verify(rd, imf); @@ -1205,7 +1274,7 @@ static const EnumPropertyItem *rna_ImageFormatSettings_file_format_itemf(bContex PropertyRNA *UNUSED(prop), bool *UNUSED(r_free)) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; if (id && GS(id->name) == ID_SCE) { return rna_enum_image_type_items; } @@ -1220,7 +1289,7 @@ static const EnumPropertyItem *rna_ImageFormatSettings_color_mode_itemf(bContext bool *r_free) { ImageFormatData *imf = (ImageFormatData *)ptr->data; - ID *id = ptr->id.data; + ID *id = ptr->owner_id; const bool is_render = (id && GS(id->name) == ID_SCE); /* note, we need to act differently for render @@ -1236,7 +1305,7 @@ static const EnumPropertyItem *rna_ImageFormatSettings_color_mode_itemf(bContext * the same MPEG format with QTRLE codec can easily handle alpha channel. * not sure how to deal with such cases in a nicer way (sergey) */ if (is_render) { - Scene *scene = ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; RenderData *rd = &scene->r; if (BKE_ffmpeg_alpha_channel_is_supported(rd)) { @@ -1405,7 +1474,7 @@ static void rna_SceneRender_file_ext_get(PointerRNA *ptr, char *str) # ifdef WITH_FFMPEG static void rna_FFmpegSettings_lossless_output_set(PointerRNA *ptr, bool value) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; RenderData *rd = &scene->r; if (value) { @@ -1422,7 +1491,7 @@ static void rna_FFmpegSettings_codec_settings_update(Main *UNUSED(bmain), Scene *UNUSED(scene_unused), PointerRNA *ptr) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; RenderData *rd = &scene->r; BKE_ffmpeg_codec_settings_verify(rd); @@ -1521,7 +1590,7 @@ static void rna_RenderSettings_engine_set(PointerRNA *ptr, int value) if (type) { BLI_strncpy_utf8(rd->engine, type->idname, sizeof(rd->engine)); - DEG_id_tag_update(ptr->id.data, ID_RECALC_COPY_ON_WRITE); + DEG_id_tag_update(ptr->owner_id, ID_RECALC_COPY_ON_WRITE); } } @@ -1577,20 +1646,20 @@ static bool rna_RenderSettings_multiple_engines_get(PointerRNA *UNUSED(ptr)) static bool rna_RenderSettings_use_spherical_stereo_get(PointerRNA *ptr) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; return BKE_scene_use_spherical_stereo(scene); } void rna_Scene_glsl_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; DEG_id_tag_update(&scene->id, 0); } static void rna_Scene_world_update(Main *bmain, Scene *scene, PointerRNA *ptr) { - Scene *sc = (Scene *)ptr->id.data; + Scene *sc = (Scene *)ptr->owner_id; rna_Scene_glsl_update(bmain, scene, ptr); WM_main_add_notifier(NC_WORLD | ND_WORLD, &sc->id); @@ -1599,7 +1668,7 @@ static void rna_Scene_world_update(Main *bmain, Scene *scene, PointerRNA *ptr) void rna_Scene_freestyle_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; DEG_id_tag_update(&scene->id, 0); } @@ -1615,7 +1684,7 @@ void rna_Scene_use_view_map_cache_update(Main *UNUSED(bmain), void rna_ViewLayer_name_set(PointerRNA *ptr, const char *value) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; ViewLayer *view_layer = (ViewLayer *)ptr->data; BLI_assert(BKE_id_is_in_global_main(&scene->id)); BKE_view_layer_rename(G_MAIN, scene, view_layer, value); @@ -1623,7 +1692,7 @@ void rna_ViewLayer_name_set(PointerRNA *ptr, const char *value) static void rna_SceneRenderView_name_set(PointerRNA *ptr, const char *value) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; SceneRenderView *rv = (SceneRenderView *)ptr->data; BLI_strncpy_utf8(rv->name, value, sizeof(rv->name)); BLI_uniquename(&scene->r.views, @@ -1636,14 +1705,14 @@ static void rna_SceneRenderView_name_set(PointerRNA *ptr, const char *value) void rna_ViewLayer_material_override_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; rna_Scene_glsl_update(bmain, scene, ptr); DEG_relations_tag_update(bmain); } void rna_ViewLayer_pass_update(Main *bmain, Scene *activescene, PointerRNA *ptr) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; if (scene->nodetree) { ntreeCompositUpdateRLayers(scene->nodetree); @@ -1676,7 +1745,7 @@ static void rna_Physics_relations_update(Main *bmain, static void rna_Physics_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; FOREACH_SCENE_OBJECT_BEGIN (scene, ob) { BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH); } @@ -1763,7 +1832,7 @@ static void object_simplify_update(Object *ob) static void rna_Scene_use_simplify_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - Scene *sce = ptr->id.data; + Scene *sce = (Scene *)ptr->owner_id; Scene *sce_iter; Base *base; @@ -1784,7 +1853,7 @@ static void rna_Scene_use_simplify_update(Main *bmain, Scene *UNUSED(scene), Poi static void rna_Scene_simplify_update(Main *bmain, Scene *scene, PointerRNA *ptr) { - Scene *sce = ptr->id.data; + Scene *sce = (Scene *)ptr->owner_id; if (sce->r.mode & R_SIMPLIFY) { rna_Scene_use_simplify_update(bmain, scene, ptr); @@ -1795,7 +1864,7 @@ static void rna_Scene_use_persistent_data_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Scene *sce = ptr->id.data; + Scene *sce = (Scene *)ptr->owner_id; if (!(sce->r.mode & R_PERSISTENT_DATA)) { RE_FreePersistentData(); @@ -1806,7 +1875,7 @@ static void rna_Scene_use_persistent_data_update(Main *UNUSED(bmain), static void rna_Scene_transform_orientation_slots_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; TransformOrientationSlot *orient_slot = &scene->orientation_slots[0]; rna_iterator_array_begin( iter, orient_slot, sizeof(*orient_slot), ARRAY_SIZE(scene->orientation_slots), 0, NULL); @@ -1814,7 +1883,7 @@ static void rna_Scene_transform_orientation_slots_begin(CollectionPropertyIterat static int rna_Scene_transform_orientation_slots_length(PointerRNA *ptr) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; return ARRAY_SIZE(scene->orientation_slots); } @@ -2062,7 +2131,7 @@ static void rna_Scene_update_active_object_data(bContext *C, PointerRNA *UNUSED( static void rna_SceneCamera_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; Object *camera = scene->camera; BKE_sequence_invalidate_scene_strips(bmain, scene); @@ -2203,7 +2272,7 @@ void rna_FreestyleSettings_module_remove(ID *id, static void rna_Stereo3dFormat_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; if (id && GS(id->name) == ID_IM) { Image *ima = (Image *)id; @@ -2251,7 +2320,7 @@ static void rna_ViewLayer_remove( static int rna_TransformOrientationSlot_type_get(PointerRNA *ptr) { - Scene *scene = ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; TransformOrientationSlot *orient_slot = ptr->data; if (orient_slot != &scene->orientation_slots[SCE_ORIENT_DEFAULT]) { if ((orient_slot->flag & SELECT) == 0) { @@ -2263,7 +2332,7 @@ static int rna_TransformOrientationSlot_type_get(PointerRNA *ptr) void rna_TransformOrientationSlot_type_set(PointerRNA *ptr, int value) { - Scene *scene = ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; TransformOrientationSlot *orient_slot = ptr->data; if (orient_slot != &scene->orientation_slots[SCE_ORIENT_DEFAULT]) { @@ -2281,7 +2350,7 @@ void rna_TransformOrientationSlot_type_set(PointerRNA *ptr, int value) static PointerRNA rna_TransformOrientationSlot_get(PointerRNA *ptr) { - Scene *scene = ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; TransformOrientationSlot *orient_slot = ptr->data; TransformOrientation *orientation; if (orient_slot->type < V3D_ORIENT_CUSTOM) { @@ -2339,8 +2408,8 @@ const EnumPropertyItem *rna_TransformOrientation_itemf(bContext *C, bool *r_free) { Scene *scene; - if (ptr->id.data && (GS(((ID *)ptr->id.data)->name) == ID_SCE)) { - scene = ptr->id.data; + if (ptr->owner_id && (GS(ptr->owner_id->name) == ID_SCE)) { + scene = (Scene *)ptr->owner_id; } else { scene = CTX_data_scene(C); @@ -2353,7 +2422,7 @@ const EnumPropertyItem *rna_TransformOrientation_with_scene_itemf(bContext *UNUS PropertyRNA *UNUSED(prop), bool *r_free) { - Scene *scene = ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; TransformOrientationSlot *orient_slot = ptr->data; bool include_default = (orient_slot != &scene->orientation_slots[SCE_ORIENT_DEFAULT]); return rna_TransformOrientation_impl_itemf(scene, include_default, r_free); @@ -2954,14 +3023,29 @@ static void rna_def_tool_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "use_transform_pivot_point_align", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "transform_flag", SCE_XFORM_AXIS_ALIGN); RNA_def_property_ui_text( - prop, "Only Origins", "Manipulate origins (object, pose and weight paint mode only)"); - RNA_def_property_ui_icon(prop, ICON_CENTER_ONLY, 0); - RNA_def_property_update(prop, NC_SCENE, NULL); + prop, "Only Locations", "Manipulate origins (object, pose and weight paint mode only)"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + + prop = RNA_def_property(srna, "use_transform_data_origin", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "transform_flag", SCE_XFORM_DATA_ORIGIN); + RNA_def_property_ui_text(prop, "Data Origins", "Manipulate object data"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + + prop = RNA_def_property(srna, "use_transform_skip_children", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "transform_flag", SCE_XFORM_SKIP_CHILDREN); + RNA_def_property_ui_text(prop, "Skip Children", "Don't transform children"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); prop = RNA_def_property(srna, "use_mesh_automerge", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "automerge", 0); + RNA_def_property_boolean_sdna(prop, NULL, "automerge", AUTO_MERGE); RNA_def_property_ui_text( - prop, "Auto Merge", "Automatically merge vertices moved to the same location"); + prop, "Auto Merge Vertices", "Automatically merge vertices moved to the same location"); + RNA_def_property_ui_icon(prop, ICON_AUTOMERGE_OFF, 1); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ + + prop = RNA_def_property(srna, "use_mesh_automerge_and_split", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "automerge", AUTO_MERGE_AND_SPLIT); + RNA_def_property_ui_text(prop, "Split Edges & Faces", "Automatically split edges and faces"); RNA_def_property_ui_icon(prop, ICON_AUTOMERGE_OFF, 1); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ @@ -3117,12 +3201,40 @@ static void rna_def_tool_settings(BlenderRNA *brna) prop, "Only Endpoints", "Only use the first and last parts of the stroke for snapping"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); - /* Grease Pencil - Select mode */ - prop = RNA_def_property(srna, "gpencil_selectmode", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "gpencil_selectmode"); + /* Grease Pencil - Select mode Edit */ + prop = RNA_def_property(srna, "gpencil_selectmode_edit", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "gpencil_selectmode_edit"); RNA_def_property_enum_items(prop, gpencil_selectmode_items); RNA_def_property_ui_text(prop, "Select Mode", ""); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_Gpencil_selectmode_update"); + + /* Grease Pencil - Select mode Sculpt */ + prop = RNA_def_property(srna, "use_gpencil_select_mask_point", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna( + prop, NULL, "gpencil_selectmode_sculpt", GP_SCULPT_MASK_SELECTMODE_POINT); + RNA_def_property_ui_text(prop, "Selection Mask", "Only sculpt selected stroke points"); + RNA_def_property_ui_icon(prop, ICON_GP_SELECT_POINTS, 0); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_Gpencil_mask_point_update"); + + prop = RNA_def_property(srna, "use_gpencil_select_mask_stroke", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna( + prop, NULL, "gpencil_selectmode_sculpt", GP_SCULPT_MASK_SELECTMODE_STROKE); + RNA_def_property_ui_text(prop, "Selection Mask", "Only sculpt selected stroke"); + RNA_def_property_ui_icon(prop, ICON_GP_SELECT_STROKES, 0); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_Gpencil_mask_stroke_update"); + + prop = RNA_def_property(srna, "use_gpencil_select_mask_segment", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna( + prop, NULL, "gpencil_selectmode_sculpt", GP_SCULPT_MASK_SELECTMODE_SEGMENT); + RNA_def_property_ui_text( + prop, "Selection Mask", "Only sculpt selected stroke points between other strokes"); + RNA_def_property_ui_icon(prop, ICON_GP_SELECT_BETWEEN_STROKES, 0); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_Gpencil_mask_segment_update"); /* Annotations - 2D Views Stroke Placement */ prop = RNA_def_property(srna, "annotation_stroke_placement_view2d", PROP_ENUM, PROP_NONE); @@ -3708,6 +3820,7 @@ void rna_def_view_layer_common(StructRNA *srna, const bool scene) RNA_def_property_pointer_sdna(prop, NULL, "mat_override"); RNA_def_property_struct_type(prop, "Material"); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text( prop, "Material Override", "Material to override all other materials in this view layer"); RNA_def_property_update( @@ -5019,7 +5132,7 @@ static void rna_def_image_format_stereo3d_format(BlenderRNA *brna) /* use for render output and image save operator, * note: there are some cases where the members act differently when this is * used from a scene, video formats can only be selected for render output - * for example, this is checked by seeing if the ptr->id.data is a Scene id */ + * for example, this is checked by seeing if the ptr->owner_id is a Scene id */ static void rna_def_scene_image_format_data(BlenderRNA *brna) { @@ -7477,6 +7590,7 @@ void RNA_def_scene(BlenderRNA *brna) /* Global Settings */ prop = RNA_def_property(srna, "camera", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Camera_object_poll"); RNA_def_property_ui_text(prop, "Camera", "Active camera, used for rendering the scene"); RNA_def_property_update(prop, NC_SCENE | NA_EDITED, "rna_Scene_camera_update"); @@ -7485,12 +7599,14 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "set"); RNA_def_property_struct_type(prop, "Scene"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_pointer_funcs(prop, NULL, "rna_Scene_set_set", NULL, NULL); RNA_def_property_ui_text(prop, "Background Scene", "Background set scene"); RNA_def_property_update(prop, NC_SCENE | NA_EDITED, "rna_Scene_set_update"); prop = RNA_def_property(srna, "world", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "World", "World used for rendering the scene"); RNA_def_property_update(prop, NC_SCENE | ND_WORLD, "rna_Scene_world_update"); @@ -7851,6 +7967,7 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_pointer_funcs( prop, NULL, NULL, NULL, "rna_GPencil_datablocks_annotations_poll"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text( prop, "Annotations", "Grease Pencil data-block used for annotations in the 3D view"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); diff --git a/source/blender/makesrna/intern/rna_screen.c b/source/blender/makesrna/intern/rna_screen.c index c868c79e968..728ef3fb706 100644 --- a/source/blender/makesrna/intern/rna_screen.c +++ b/source/blender/makesrna/intern/rna_screen.c @@ -149,7 +149,7 @@ static void rna_Area_type_set(PointerRNA *ptr, int value) static void rna_Area_type_update(bContext *C, PointerRNA *ptr) { - bScreen *sc = (bScreen *)ptr->id.data; + bScreen *sc = (bScreen *)ptr->owner_id; ScrArea *sa = (ScrArea *)ptr->data; /* Running update without having called 'set', see: T64049 */ diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c index 84f2cb7c1be..2e3f41d656b 100644 --- a/source/blender/makesrna/intern/rna_sculpt_paint.c +++ b/source/blender/makesrna/intern/rna_sculpt_paint.c @@ -319,7 +319,7 @@ static char *rna_ParticleEdit_path(PointerRNA *UNUSED(ptr)) static bool rna_Brush_mode_poll(PointerRNA *ptr, PointerRNA value) { const Paint *paint = ptr->data; - Brush *brush = value.id.data; + Brush *brush = (Brush *)value.owner_id; const uint tool_offset = paint->runtime.tool_offset; const eObjectMode ob_mode = paint->runtime.ob_mode; UNUSED_VARS_NDEBUG(tool_offset); @@ -350,10 +350,10 @@ static bool paint_contains_brush_slot(const Paint *paint, const PaintToolSlot *t static bool rna_Brush_mode_with_tool_poll(PointerRNA *ptr, PointerRNA value) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; const PaintToolSlot *tslot = ptr->data; ToolSettings *ts = scene->toolsettings; - Brush *brush = value.id.data; + Brush *brush = (Brush *)value.owner_id; int mode = 0; int slot_index = 0; @@ -438,7 +438,7 @@ static char *rna_Sculpt_path(PointerRNA *UNUSED(ptr)) static char *rna_VertexPaint_path(PointerRNA *ptr) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; ToolSettings *ts = scene->toolsettings; if (ptr->data == ts->vpaint) { return BLI_strdup("tool_settings.vertex_paint"); @@ -1420,13 +1420,6 @@ static void rna_def_gpencil_sculpt(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text(prop, "Guide", ""); - prop = RNA_def_property(srna, "use_select_mask", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SCULPT_SETT_FLAG_SELECT_MASK); - RNA_def_property_ui_text(prop, "Selection Mask", "Only sculpt selected stroke points"); - RNA_def_property_ui_icon(prop, ICON_GP_ONLY_SELECTED, 0); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); - prop = RNA_def_property(srna, "use_edit_position", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SCULPT_SETT_FLAG_APPLY_POSITION); RNA_def_property_ui_text(prop, "Affect Position", "The brush affects the position of the point"); diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 80a4defba00..efb2fd376b3 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -100,7 +100,7 @@ static void meta_tmp_ref(Sequence *seq_par, Sequence *seq) static void rna_SequenceElement_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; Editing *ed = BKE_sequencer_editing_get(scene, false); if (ed) { @@ -119,7 +119,7 @@ static void rna_Sequence_invalidate_raw_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; Editing *ed = BKE_sequencer_editing_get(scene, false); if (ed) { @@ -133,7 +133,7 @@ static void rna_Sequence_invalidate_preprocessed_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; Editing *ed = BKE_sequencer_editing_get(scene, false); if (ed) { @@ -147,7 +147,7 @@ static void rna_Sequence_invalidate_composite_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; Editing *ed = BKE_sequencer_editing_get(scene, false); if (ed) { @@ -179,7 +179,7 @@ static void rna_Sequence_use_sequence(Main *bmain, Scene *scene, PointerRNA *ptr static void rna_SequenceEditor_sequences_all_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; Editing *ed = BKE_sequencer_editing_get(scene, false); meta_tmp_ref(NULL, ed->seqbase.first); @@ -281,7 +281,7 @@ static void do_sequence_frame_change_update(Scene *scene, Sequence *seq) */ static void rna_Sequence_frame_change_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; do_sequence_frame_change_update(scene, (Sequence *)ptr->data); rna_Sequence_invalidate_preprocessed_update(bmain, scene, ptr); } @@ -289,7 +289,7 @@ static void rna_Sequence_frame_change_update(Main *bmain, Scene *UNUSED(scene), static void rna_Sequence_start_frame_set(PointerRNA *ptr, int value) { Sequence *seq = (Sequence *)ptr->data; - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; BKE_sequence_translate(scene, seq, value - seq->start); do_sequence_frame_change_update(scene, seq); @@ -298,7 +298,7 @@ static void rna_Sequence_start_frame_set(PointerRNA *ptr, int value) static void rna_Sequence_start_frame_final_set(PointerRNA *ptr, int value) { Sequence *seq = (Sequence *)ptr->data; - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; BKE_sequence_tx_set_final_left(seq, value); BKE_sequence_single_fix(seq); @@ -308,7 +308,7 @@ static void rna_Sequence_start_frame_final_set(PointerRNA *ptr, int value) static void rna_Sequence_end_frame_final_set(PointerRNA *ptr, int value) { Sequence *seq = (Sequence *)ptr->data; - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; BKE_sequence_tx_set_final_right(seq, value); BKE_sequence_single_fix(seq); @@ -318,7 +318,7 @@ static void rna_Sequence_end_frame_final_set(PointerRNA *ptr, int value) static void rna_Sequence_anim_startofs_final_set(PointerRNA *ptr, int value) { Sequence *seq = (Sequence *)ptr->data; - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; seq->anim_startofs = MIN2(value, seq->len + seq->anim_startofs); @@ -329,7 +329,7 @@ static void rna_Sequence_anim_startofs_final_set(PointerRNA *ptr, int value) static void rna_Sequence_anim_endofs_final_set(PointerRNA *ptr, int value) { Sequence *seq = (Sequence *)ptr->data; - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; seq->anim_endofs = MIN2(value, seq->len + seq->anim_endofs); @@ -340,7 +340,7 @@ static void rna_Sequence_anim_endofs_final_set(PointerRNA *ptr, int value) static void rna_Sequence_frame_length_set(PointerRNA *ptr, int value) { Sequence *seq = (Sequence *)ptr->data; - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; BKE_sequence_tx_set_final_right(seq, BKE_sequence_tx_get_final_left(seq, false) + value); do_sequence_frame_change_update(scene, seq); @@ -362,7 +362,7 @@ static int rna_Sequence_frame_editable(PointerRNA *ptr, const char **UNUSED(r_in static void rna_Sequence_channel_set(PointerRNA *ptr, int value) { Sequence *seq = (Sequence *)ptr->data; - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; Editing *ed = BKE_sequencer_editing_get(scene, false); ListBase *seqbase = BKE_sequence_seqbase(&ed->seqbase, seq); @@ -445,7 +445,7 @@ static Sequence *sequence_get_by_transform(Editing *ed, StripTransform *transfor static char *rna_SequenceTransform_path(PointerRNA *ptr) { - Scene *scene = ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; Editing *ed = BKE_sequencer_editing_get(scene, false); Sequence *seq = sequence_get_by_transform(ed, ptr->data); @@ -464,7 +464,7 @@ static void rna_SequenceTransform_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; Editing *ed = BKE_sequencer_editing_get(scene, false); Sequence *seq = sequence_get_by_transform(ed, ptr->data); @@ -497,7 +497,7 @@ static Sequence *sequence_get_by_crop(Editing *ed, StripCrop *crop) static char *rna_SequenceCrop_path(PointerRNA *ptr) { - Scene *scene = ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; Editing *ed = BKE_sequencer_editing_get(scene, false); Sequence *seq = sequence_get_by_crop(ed, ptr->data); @@ -514,7 +514,7 @@ static char *rna_SequenceCrop_path(PointerRNA *ptr) static void rna_SequenceCrop_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; Editing *ed = BKE_sequencer_editing_get(scene, false); Sequence *seq = sequence_get_by_crop(ed, ptr->data); @@ -551,7 +551,7 @@ static int rna_Sequence_name_length(PointerRNA *ptr) static void rna_Sequence_name_set(PointerRNA *ptr, const char *value) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; Sequence *seq = (Sequence *)ptr->data; char oldname[sizeof(seq->name)]; AnimData *adt; @@ -782,7 +782,7 @@ static void rna_SequenceElement_filename_set(PointerRNA *ptr, const char *value) static void rna_Sequence_reopen_files_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; Editing *ed = BKE_sequencer_editing_get(scene, false); BKE_sequencer_free_imbuf(scene, &ed->seqbase, false); @@ -795,14 +795,14 @@ static void rna_Sequence_reopen_files_update(Main *bmain, Scene *UNUSED(scene), static void rna_Sequence_mute_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); } static void rna_Sequence_filepath_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; Sequence *seq = (Sequence *)(ptr->data); BKE_sequence_reload_new_file(bmain, scene, seq, true); BKE_sequence_calc(scene, seq); @@ -838,7 +838,7 @@ static Sequence *sequence_get_by_proxy(Editing *ed, StripProxy *proxy) static void rna_Sequence_tcindex_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; Editing *ed = BKE_sequencer_editing_get(scene, false); Sequence *seq = sequence_get_by_proxy(ed, ptr->data); @@ -848,7 +848,7 @@ static void rna_Sequence_tcindex_update(Main *bmain, Scene *UNUSED(scene), Point static void rna_SequenceProxy_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; Editing *ed = BKE_sequencer_editing_get(scene, false); Sequence *seq = sequence_get_by_proxy(ed, ptr->data); @@ -911,7 +911,7 @@ static Sequence *sequence_get_by_colorbalance(Editing *ed, static char *rna_SequenceColorBalance_path(PointerRNA *ptr) { - Scene *scene = ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; SequenceModifierData *smd; Editing *ed = BKE_sequencer_editing_get(scene, false); Sequence *seq = sequence_get_by_colorbalance(ed, ptr->data, &smd); @@ -944,7 +944,7 @@ static void rna_SequenceColorBalance_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; Editing *ed = BKE_sequencer_editing_get(scene, false); SequenceModifierData *smd; Sequence *seq = sequence_get_by_colorbalance(ed, ptr->data, &smd); @@ -954,7 +954,7 @@ static void rna_SequenceColorBalance_update(Main *UNUSED(bmain), static void rna_SequenceEditor_overlay_lock_set(PointerRNA *ptr, bool value) { - Scene *scene = ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; Editing *ed = BKE_sequencer_editing_get(scene, false); if (ed == NULL) { @@ -974,7 +974,7 @@ static void rna_SequenceEditor_overlay_lock_set(PointerRNA *ptr, bool value) static int rna_SequenceEditor_overlay_frame_get(PointerRNA *ptr) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; Editing *ed = BKE_sequencer_editing_get(scene, false); if (ed == NULL) { @@ -991,7 +991,7 @@ static int rna_SequenceEditor_overlay_frame_get(PointerRNA *ptr) static void rna_SequenceEditor_overlay_frame_set(PointerRNA *ptr, int value) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; Editing *ed = BKE_sequencer_editing_get(scene, false); if (ed == NULL) { @@ -1055,7 +1055,7 @@ static StructRNA *rna_SequenceModifier_refine(struct PointerRNA *ptr) static char *rna_SequenceModifier_path(PointerRNA *ptr) { - Scene *scene = ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; Editing *ed = BKE_sequencer_editing_get(scene, false); SequenceModifierData *smd = ptr->data; Sequence *seq = sequence_get_by_modifier(ed, smd); @@ -1077,7 +1077,7 @@ static char *rna_SequenceModifier_path(PointerRNA *ptr) static void rna_SequenceModifier_name_set(PointerRNA *ptr, const char *value) { SequenceModifierData *smd = ptr->data; - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; Editing *ed = BKE_sequencer_editing_get(scene, false); Sequence *seq = sequence_get_by_modifier(ed, smd); AnimData *adt; @@ -1106,7 +1106,7 @@ static void rna_SequenceModifier_name_set(PointerRNA *ptr, const char *value) static void rna_SequenceModifier_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { /* strip from other scenes could be modified, so using active scene is not reliable */ - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; Editing *ed = BKE_sequencer_editing_get(scene, false); Sequence *seq = sequence_get_by_modifier(ed, ptr->data); @@ -1115,7 +1115,7 @@ static void rna_SequenceModifier_update(Main *UNUSED(bmain), Scene *UNUSED(scene static bool rna_SequenceModifier_otherSequence_poll(PointerRNA *ptr, PointerRNA value) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; Editing *ed = BKE_sequencer_editing_get(scene, false); Sequence *seq = sequence_get_by_modifier(ed, ptr->data); Sequence *cur = (Sequence *)value.data; @@ -1181,7 +1181,7 @@ static void rna_Sequence_modifier_clear(Sequence *seq, bContext *C) static float rna_Sequence_fps_get(PointerRNA *ptr) { - Scene *scene = (Scene *)ptr->id.data; + Scene *scene = (Scene *)ptr->owner_id; Sequence *seq = (Sequence *)(ptr->data); return BKE_sequence_get_fps(scene, seq); } @@ -1457,7 +1457,7 @@ static const EnumPropertyItem blend_mode_items[] = { {0, "", ICON_NONE, NULL, NULL}, {SEQ_TYPE_DARKEN, "DARKEN", 0, "Darken", ""}, {SEQ_TYPE_MUL, "MULTIPLY", 0, "Multiply", ""}, - {SEQ_TYPE_BURN, "BURN", 0, "Burn", ""}, + {SEQ_TYPE_COLOR_BURN, "BURN", 0, "Color Burn", ""}, {SEQ_TYPE_LINEAR_BURN, "LINEAR_BURN", 0, "Linear Burn", ""}, {0, "", ICON_NONE, NULL, NULL}, {SEQ_TYPE_LIGHTEN, "LIGHTEN", 0, "Lighten", ""}, @@ -2758,14 +2758,16 @@ static void rna_def_text(StructRNA *srna) prop = RNA_def_property(srna, "align_x", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "align"); RNA_def_property_enum_items(prop, text_align_x_items); - RNA_def_property_ui_text(prop, "Align X", "Align the text along the X axis"); + RNA_def_property_ui_text( + prop, "Align X", "Align the text along the X axis, relative to the text midpoint"); RNA_def_property_update( prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "align_y", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "align_y"); RNA_def_property_enum_items(prop, text_align_y_items); - RNA_def_property_ui_text(prop, "Align Y", "Align the image along the Y axis"); + RNA_def_property_ui_text( + prop, "Align Y", "Align the image along the Y axis, relative to the text midpoint"); RNA_def_property_update( prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); @@ -2792,7 +2794,7 @@ static void rna_def_color_mix(StructRNA *srna) {SEQ_TYPE_SCREEN, "SCREEN", 0, "Screen", ""}, {SEQ_TYPE_OVERLAY, "OVERLAY", 0, "Overlay", ""}, {SEQ_TYPE_DODGE, "DODGE", 0, "Dodge", ""}, - {SEQ_TYPE_BURN, "BURN", 0, "Burn", ""}, + {SEQ_TYPE_COLOR_BURN, "BURN", 0, "Color Burn", ""}, {SEQ_TYPE_LINEAR_BURN, "LINEAR_BURN", 0, "Linear Burn", ""}, {SEQ_TYPE_SOFT_LIGHT, "SOFT_LIGHT", 0, "Soft Light", ""}, {SEQ_TYPE_HARD_LIGHT, "HARD_LIGHT", 0, "Hard Light", ""}, diff --git a/source/blender/makesrna/intern/rna_shader_fx.c b/source/blender/makesrna/intern/rna_shader_fx.c index e48e682018d..acf525e1788 100644 --- a/source/blender/makesrna/intern/rna_shader_fx.c +++ b/source/blender/makesrna/intern/rna_shader_fx.c @@ -140,8 +140,8 @@ static void rna_ShaderFx_name_set(PointerRNA *ptr, const char *value) BLI_strncpy_utf8(gmd->name, value, sizeof(gmd->name)); /* make sure the name is truly unique */ - if (ptr->id.data) { - Object *ob = ptr->id.data; + if (ptr->owner_id) { + Object *ob = (Object *)ptr->owner_id; BKE_shaderfx_unique_name(&ob->shader_fx, gmd); } @@ -160,8 +160,8 @@ static char *rna_ShaderFx_path(PointerRNA *ptr) static void rna_ShaderFx_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - DEG_id_tag_update(ptr->id.data, ID_RECALC_GEOMETRY); - WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ptr->id.data); + DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY); + WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ptr->owner_id); } static void rna_ShaderFx_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr) @@ -189,7 +189,7 @@ static void shaderfx_object_set(Object *self, Object **ob_p, int type, PointerRN PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) \ { \ _type##ShaderFxData *tmd = (_type##ShaderFxData *)ptr->data; \ - shaderfx_object_set(ptr->id.data, &tmd->_prop, _obtype, value); \ + shaderfx_object_set((Object *)ptr->owner_id, &tmd->_prop, _obtype, value); \ } RNA_FX_OBJECT_SET(Light, object, OB_EMPTY); @@ -212,7 +212,7 @@ static void rna_def_shader_fx_blur(BlenderRNA *brna) prop = RNA_def_property(srna, "factor", PROP_INT, PROP_PIXEL); RNA_def_property_int_sdna(prop, NULL, "radius"); - RNA_def_property_range(prop, 0, INT_MAX); + RNA_def_property_range(prop, 0, SHRT_MAX); RNA_def_property_ui_text(prop, "Factor", "Factor of Blur"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update"); @@ -329,7 +329,7 @@ static void rna_def_shader_fx_pixel(BlenderRNA *brna) prop = RNA_def_property(srna, "size", PROP_INT, PROP_PIXEL); RNA_def_property_int_sdna(prop, NULL, "size"); - RNA_def_property_range(prop, 1, INT_MAX); + RNA_def_property_range(prop, 1, SHRT_MAX); RNA_def_property_array(prop, 2); RNA_def_property_ui_text(prop, "Size", "Pixel size"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update"); @@ -359,7 +359,7 @@ static void rna_def_shader_fx_rim(BlenderRNA *brna) prop = RNA_def_property(srna, "offset", PROP_INT, PROP_PIXEL); RNA_def_property_int_sdna(prop, NULL, "offset"); - RNA_def_property_range(prop, -INT_MAX, INT_MAX); + RNA_def_property_range(prop, SHRT_MIN, SHRT_MAX); RNA_def_property_ui_text(prop, "Offset", "Offset of the rim"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update"); @@ -385,7 +385,7 @@ static void rna_def_shader_fx_rim(BlenderRNA *brna) prop = RNA_def_property(srna, "blur", PROP_INT, PROP_PIXEL); RNA_def_property_int_sdna(prop, NULL, "blur"); - RNA_def_property_range(prop, 0, INT_MAX); + RNA_def_property_range(prop, 0, SHRT_MAX); RNA_def_property_ui_text( prop, "Blur", "Number of pixels for blurring rim (set to 0 to disable)"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update"); @@ -418,11 +418,12 @@ static void rna_def_shader_fx_shadow(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Object", "Object to determine center of rotation"); RNA_def_property_pointer_funcs(prop, NULL, "rna_ShadowShaderFx_object_set", NULL, NULL); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_ShaderFx_dependency_update"); prop = RNA_def_property(srna, "offset", PROP_INT, PROP_PIXEL); RNA_def_property_int_sdna(prop, NULL, "offset"); - RNA_def_property_range(prop, -INT_MAX, INT_MAX); + RNA_def_property_range(prop, SHRT_MIN, SHRT_MAX); RNA_def_property_ui_text(prop, "Offset", "Offset of the shadow"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update"); @@ -472,7 +473,7 @@ static void rna_def_shader_fx_shadow(BlenderRNA *brna) prop = RNA_def_property(srna, "blur", PROP_INT, PROP_PIXEL); RNA_def_property_int_sdna(prop, NULL, "blur"); - RNA_def_property_range(prop, 0, INT_MAX); + RNA_def_property_range(prop, 0, SHRT_MAX); RNA_def_property_ui_text( prop, "Blur", "Number of pixels for blurring shadow (set to 0 to disable)"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update"); @@ -537,7 +538,7 @@ static void rna_def_shader_fx_glow(BlenderRNA *brna) * but only makes public first array element. */ prop = RNA_def_property(srna, "radius", PROP_INT, PROP_PIXEL); RNA_def_property_int_sdna(prop, NULL, "blur[0]"); - RNA_def_property_range(prop, 0, INT_MAX); + RNA_def_property_range(prop, 0, SHRT_MAX); RNA_def_property_ui_text( prop, "Radius", "Number of pixels for blurring glow (set to 0 to disable)"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update"); @@ -568,7 +569,7 @@ static void rna_def_shader_fx_swirl(BlenderRNA *brna) prop = RNA_def_property(srna, "radius", PROP_INT, PROP_PIXEL); RNA_def_property_int_sdna(prop, NULL, "radius"); - RNA_def_property_range(prop, 0, INT_MAX); + RNA_def_property_range(prop, 0, SHRT_MAX); RNA_def_property_ui_text(prop, "Radius", "Radius to apply"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update"); @@ -588,6 +589,7 @@ static void rna_def_shader_fx_swirl(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Object", "Object to determine center location"); RNA_def_property_pointer_funcs(prop, NULL, "rna_SwirlShaderFx_object_set", NULL, NULL); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_ShaderFx_dependency_update"); } @@ -640,6 +642,7 @@ static void rna_def_shader_fx_light(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Object", "Object to determine light source location"); RNA_def_property_pointer_funcs(prop, NULL, "rna_LightShaderFx_object_set", NULL, NULL); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_ShaderFx_dependency_update"); } diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c index 5c04802ac3c..fa0297ac306 100644 --- a/source/blender/makesrna/intern/rna_smoke.c +++ b/source/blender/makesrna/intern/rna_smoke.c @@ -55,7 +55,7 @@ static void rna_Smoke_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - DEG_id_tag_update(ptr->id.data, ID_RECALC_GEOMETRY); + DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY); } static void rna_Smoke_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr) @@ -70,13 +70,13 @@ static void rna_Smoke_resetCache(Main *UNUSED(bmain), Scene *UNUSED(scene), Poin if (settings->smd && settings->smd->domain) { settings->point_cache[0]->flag |= PTCACHE_OUTDATED; } - DEG_id_tag_update(ptr->id.data, ID_RECALC_GEOMETRY); + DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY); } static void rna_Smoke_cachetype_set(struct PointerRNA *ptr, int value) { SmokeDomainSettings *settings = (SmokeDomainSettings *)ptr->data; - Object *ob = (Object *)ptr->id.data; + Object *ob = (Object *)ptr->owner_id; if (value != settings->cache_file_format) { /* Clear old caches. */ diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 8108311319b..d866e1a98be 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -422,19 +422,19 @@ const EnumPropertyItem rna_enum_file_sort_items[] = { {FILE_SORT_ALPHA, "FILE_SORT_ALPHA", ICON_SORTALPHA, - "Sort alphabetically", + "Name", "Sort the file list alphabetically"}, {FILE_SORT_EXTENSION, "FILE_SORT_EXTENSION", ICON_SORTBYEXT, - "Sort by extension", + "Extension", "Sort the file list by extension/type"}, {FILE_SORT_TIME, "FILE_SORT_TIME", ICON_SORTTIME, - "Sort by time", + "Modified Date", "Sort files by modification time"}, - {FILE_SORT_SIZE, "FILE_SORT_SIZE", ICON_SORTSIZE, "Sort by size", "Sort files by size"}, + {FILE_SORT_SIZE, "FILE_SORT_SIZE", ICON_SORTSIZE, "Size", "Sort files by size"}, {0, NULL, 0, NULL, NULL}, }; @@ -524,7 +524,7 @@ static StructRNA *rna_Space_refine(struct PointerRNA *ptr) static ScrArea *rna_area_from_space(PointerRNA *ptr) { - bScreen *sc = (bScreen *)ptr->id.data; + bScreen *sc = (bScreen *)ptr->owner_id; SpaceLink *link = (SpaceLink *)ptr->data; return BKE_screen_find_area_from_space(sc, link); } @@ -553,7 +553,7 @@ static void area_region_from_regiondata(bScreen *sc, static void rna_area_region_from_regiondata(PointerRNA *ptr, ScrArea **r_sa, ARegion **r_ar) { - bScreen *sc = (bScreen *)ptr->id.data; + bScreen *sc = (bScreen *)ptr->owner_id; void *regiondata = ptr->data; area_region_from_regiondata(sc, regiondata, r_sa, r_ar); @@ -771,7 +771,7 @@ static void rna_Space_view2d_sync_update(Main *UNUSED(bmain), ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); if (ar) { - bScreen *sc = (bScreen *)ptr->id.data; + bScreen *sc = (bScreen *)ptr->owner_id; View2D *v2d = &ar->v2d; UI_view2d_sync(sc, sa, v2d, V2D_LOCK_SET); @@ -804,7 +804,7 @@ static void rna_SpaceView3D_camera_update(Main *bmain, Scene *scene, PointerRNA static void rna_SpaceView3D_use_local_camera_set(PointerRNA *ptr, bool value) { View3D *v3d = (View3D *)(ptr->data); - bScreen *sc = (bScreen *)ptr->id.data; + bScreen *sc = (bScreen *)ptr->owner_id; v3d->scenelock = !value; @@ -817,7 +817,7 @@ static void rna_SpaceView3D_use_local_camera_set(PointerRNA *ptr, bool value) static float rna_View3DOverlay_GridScaleUnit_get(PointerRNA *ptr) { View3D *v3d = (View3D *)(ptr->data); - bScreen *screen = ptr->id.data; + bScreen *screen = (bScreen *)ptr->owner_id; Scene *scene = ED_screen_scene_find(screen, G_MAIN->wm.first); return ED_view3d_grid_scale(scene, v3d, NULL); @@ -934,7 +934,7 @@ static bool rna_RegionView3D_is_orthographic_side_view_get(PointerRNA *ptr) static void rna_3DViewShading_type_update(Main *bmain, Scene *scene, PointerRNA *ptr) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; if (GS(id->name) == ID_SCE) { return; } @@ -951,7 +951,7 @@ static void rna_3DViewShading_type_update(Main *bmain, Scene *scene, PointerRNA } } - bScreen *screen = ptr->id.data; + bScreen *screen = (bScreen *)ptr->owner_id; for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) { if (sl->spacetype == SPACE_VIEW3D) { @@ -968,12 +968,12 @@ static void rna_3DViewShading_type_update(Main *bmain, Scene *scene, PointerRNA static Scene *rna_3DViewShading_scene(PointerRNA *ptr) { /* Get scene, depends if using 3D view or OpenGL render settings. */ - ID *id = ptr->id.data; + ID *id = ptr->owner_id; if (GS(id->name) == ID_SCE) { return (Scene *)id; } else { - bScreen *screen = ptr->id.data; + bScreen *screen = (bScreen *)ptr->owner_id; return WM_windows_scene_get_from_screen(G_MAIN->wm.first, screen); } } @@ -1296,7 +1296,7 @@ static bool rna_SpaceImageEditor_show_paint_get(PointerRNA *ptr) static bool rna_SpaceImageEditor_show_uvedit_get(PointerRNA *ptr) { SpaceImage *sima = (SpaceImage *)(ptr->data); - bScreen *sc = (bScreen *)ptr->id.data; + bScreen *sc = (bScreen *)ptr->owner_id; wmWindow *win = ED_screen_window_find(sc, G_MAIN->wm.first); ViewLayer *view_layer = WM_window_get_active_view_layer(win); Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); @@ -1306,7 +1306,7 @@ static bool rna_SpaceImageEditor_show_uvedit_get(PointerRNA *ptr) static bool rna_SpaceImageEditor_show_maskedit_get(PointerRNA *ptr) { SpaceImage *sima = (SpaceImage *)(ptr->data); - bScreen *sc = (bScreen *)ptr->id.data; + bScreen *sc = (bScreen *)ptr->owner_id; wmWindow *win = ED_screen_window_find(sc, G_MAIN->wm.first); ViewLayer *view_layer = WM_window_get_active_view_layer(win); return ED_space_image_check_show_maskedit(sima, view_layer); @@ -1317,7 +1317,7 @@ static void rna_SpaceImageEditor_image_set(PointerRNA *ptr, struct ReportList *UNUSED(reports)) { SpaceImage *sima = (SpaceImage *)(ptr->data); - bScreen *sc = (bScreen *)ptr->id.data; + bScreen *sc = (bScreen *)ptr->owner_id; wmWindow *win = ED_screen_window_find(sc, G_MAIN->wm.first); ViewLayer *view_layer = WM_window_get_active_view_layer(win); Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); @@ -2106,7 +2106,7 @@ static void rna_SpaceClipEditor_clip_set(PointerRNA *ptr, struct ReportList *UNUSED(reports)) { SpaceClip *sc = (SpaceClip *)(ptr->data); - bScreen *screen = (bScreen *)ptr->id.data; + bScreen *screen = (bScreen *)ptr->owner_id; ED_space_clip_set_clip(NULL, screen, sc, (MovieClip *)value.data); } @@ -2156,6 +2156,18 @@ static void rna_SpaceClipEditor_view_type_update(Main *UNUSED(bmain), /* File browser. */ +int rna_FileSelectParams_filename_editable(struct PointerRNA *ptr, const char **r_info) +{ + FileSelectParams *params = ptr->data; + + if (params && (params->flag & FILE_DIRSEL_ONLY)) { + *r_info = "Only directories can be chosen for the current operation."; + return 0; + } + + return params ? PROP_EDITABLE : 0; +} + static bool rna_FileSelectParams_use_lib_get(PointerRNA *ptr) { FileSelectParams *params = ptr->data; @@ -2725,11 +2737,6 @@ static void rna_def_space_image_uv(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Display Faces", "Display faces over the image"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL); - prop = RNA_def_property(srna, "show_edges", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SI_NO_DRAWEDGES); - RNA_def_property_ui_text(prop, "Display Edges", "Display edges in vertex select mode"); - RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL); - /* todo: move edge and face drawing options here from G.f */ prop = RNA_def_property(srna, "pixel_snap_mode", PROP_ENUM, PROP_NONE); @@ -2791,6 +2798,7 @@ static void rna_def_space_outliner(BlenderRNA *brna) static const EnumPropertyItem filter_state_items[] = { {SO_FILTER_OB_ALL, "ALL", 0, "All", "Show all objects in the view layer"}, {SO_FILTER_OB_VISIBLE, "VISIBLE", 0, "Visible", "Show visible objects"}, + {SO_FILTER_OB_HIDDEN, "HIDDEN", 0, "Hidden", "Show hidden objects"}, {SO_FILTER_OB_SELECTED, "SELECTED", 0, "Selected", "Show selected objects"}, {SO_FILTER_OB_ACTIVE, "ACTIVE", 0, "Active", "Show only the active object"}, {0, NULL, 0, NULL, NULL}, @@ -2829,6 +2837,12 @@ static void rna_def_space_outliner(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Sort Alphabetically", ""); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL); + prop = RNA_def_property(srna, "use_sync_select", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SO_SYNC_SELECT); + RNA_def_property_ui_text( + prop, "Sync Outliner Selection", "Sync outliner selection with other editors"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL); + /* Granular restriction column option. */ prop = RNA_def_property(srna, "show_restrict_column_enable", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "show_restrict_flags", SO_RESTRICT_ENABLE); @@ -3788,7 +3802,7 @@ static void rna_def_space_view3d(BlenderRNA *brna) prop = RNA_def_property(srna, "show_gizmo_navigate", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "gizmo_flag", V3D_GIZMO_HIDE_NAVIGATE); - RNA_def_property_ui_text(prop, "Navigate Gizmo", ""); + RNA_def_property_ui_text(prop, "Navigate Gizmo", "Viewport navigation gizmo"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); prop = RNA_def_property(srna, "show_gizmo_context", PROP_BOOLEAN, PROP_NONE); @@ -4440,13 +4454,6 @@ static void rna_def_space_sequencer(BlenderRNA *brna) RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL); /* flags */ - prop = RNA_def_property(srna, "show_frame_indicator", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SEQ_NO_DRAW_CFRANUM); - RNA_def_property_ui_text(prop, - "Show Frame Number Indicator", - "Show frame number beside the current frame indicator line"); - RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL); - prop = RNA_def_property(srna, "show_frames", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_DRAWFRAMES); RNA_def_property_ui_text(prop, "Display Frames", "Display frames rather than seconds"); @@ -4734,13 +4741,6 @@ static void rna_def_space_dopesheet(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Show Seconds", "Show timing in seconds not frames"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_DOPESHEET, NULL); - prop = RNA_def_property(srna, "show_frame_indicator", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SACTION_NODRAWCFRANUM); - RNA_def_property_ui_text(prop, - "Show Frame Number Indicator", - "Show frame number beside the current frame indicator line"); - RNA_def_property_update(prop, NC_SPACE | ND_SPACE_DOPESHEET, NULL); - prop = RNA_def_property(srna, "show_sliders", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SACTION_SLIDERS); RNA_def_property_ui_text(prop, "Show Sliders", "Show sliders beside F-Curve channels"); @@ -4896,13 +4896,6 @@ static void rna_def_space_graph(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Show Seconds", "Show timing in seconds not frames"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL); - prop = RNA_def_property(srna, "show_frame_indicator", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SIPO_NODRAWCFRANUM); - RNA_def_property_ui_text(prop, - "Show Frame Number Indicator", - "Show frame number beside the current frame indicator line"); - RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL); - prop = RNA_def_property(srna, "show_sliders", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SIPO_SLIDERS); RNA_def_property_ui_text(prop, "Show Sliders", "Show sliders beside F-Curve channels"); @@ -5040,13 +5033,6 @@ static void rna_def_space_nla(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Show Seconds", "Show timing in seconds not frames"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NLA, NULL); - prop = RNA_def_property(srna, "show_frame_indicator", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SNLA_NODRAWCFRANUM); - RNA_def_property_ui_text(prop, - "Show Frame Number Indicator", - "Show frame number beside the current frame indicator line"); - RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NLA, NULL); - prop = RNA_def_property(srna, "show_strip_curves", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SNLA_NOSTRIPCURVES); RNA_def_property_ui_text(prop, "Show Control F-Curves", "Show influence F-Curves on strips"); @@ -5173,25 +5159,25 @@ static void rna_def_fileselect_params(BlenderRNA *brna) PropertyRNA *prop; static const EnumPropertyItem file_display_items[] = { - {FILE_SHORTDISPLAY, - "LIST_SHORT", - ICON_SHORTDISPLAY, - "Short List", - "Display files as short list"}, - {FILE_LONGDISPLAY, - "LIST_LONG", + {FILE_VERTICALDISPLAY, + "LIST_VERTICAL", ICON_LONGDISPLAY, - "Long List", - "Display files as a detailed list"}, + "Vertical List", + "Display files as a vertical list"}, + {FILE_HORIZONTALDISPLAY, + "LIST_HORIZONTAL", + ICON_SHORTDISPLAY, + "Horizontal List", + "Display files as a horizontal list"}, {FILE_IMGDISPLAY, "THUMBNAIL", ICON_IMGDISPLAY, "Thumbnails", "Display files as thumbnails"}, {0, NULL, 0, NULL, NULL}, }; static const EnumPropertyItem display_size_items[] = { - {32, "TINY", 0, "Tiny", ""}, - {64, "SMALL", 0, "Small", ""}, + {64, "TINY", 0, "Tiny", ""}, + {96, "SMALL", 0, "Small", ""}, {128, "NORMAL", 0, "Regular", ""}, - {256, "LARGE", 0, "Large", ""}, + {192, "LARGE", 0, "Large", ""}, {0, NULL, 0, NULL, NULL}, }; @@ -5307,7 +5293,10 @@ static void rna_def_fileselect_params(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Title", "Title for the file browser"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); - prop = RNA_def_property(srna, "directory", PROP_STRING, PROP_DIRPATH); + /* Use BYTESTRING rather than DIRPATH as subtype so UI code doesn't add OT_directory_browse + * button when displaying this prop in the file browser (it would just open a file browser). That + * should be the only effective difference between the two. */ + prop = RNA_def_property(srna, "directory", PROP_STRING, PROP_BYTESTRING); RNA_def_property_string_sdna(prop, NULL, "dir"); RNA_def_property_ui_text(prop, "Directory", "Directory displayed in the file browser"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); @@ -5315,6 +5304,7 @@ static void rna_def_fileselect_params(BlenderRNA *brna) prop = RNA_def_property(srna, "filename", PROP_STRING, PROP_FILENAME); RNA_def_property_string_sdna(prop, NULL, "file"); RNA_def_property_ui_text(prop, "File Name", "Active file in the file browser"); + RNA_def_property_editable_func(prop, "rna_FileSelectParams_filename_editable"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); prop = RNA_def_property(srna, "use_library_browsing", PROP_BOOLEAN, PROP_NONE); @@ -5335,6 +5325,19 @@ static void rna_def_fileselect_params(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Recursion", "Numbers of dirtree levels to show simultaneously"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); + prop = RNA_def_property(srna, "show_details_size", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "details_flags", FILE_DETAILS_SIZE); + RNA_def_property_ui_text(prop, "File Size", "Draw a column listing the size of each file"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); + + prop = RNA_def_property(srna, "show_details_datetime", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "details_flags", FILE_DETAILS_DATETIME); + RNA_def_property_ui_text( + prop, + "File Modification Date", + "Draw a column listing the date and time of modification for each file"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); + prop = RNA_def_property(srna, "use_filter", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", FILE_FILTER); RNA_def_property_ui_text(prop, "Filter Files", "Enable filtering of files"); @@ -5351,6 +5354,12 @@ static void rna_def_fileselect_params(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Sort", ""); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); + prop = RNA_def_property(srna, "use_sort_invert", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", FILE_SORT_INVERT); + RNA_def_property_ui_text( + prop, "Reverse Sorting", "Sort items descending, from highest value to lowest"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); + prop = RNA_def_property(srna, "use_filter_image", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "filter", FILE_TYPE_IMAGE); RNA_def_property_ui_text(prop, "Filter Images", "Show image files"); diff --git a/source/blender/makesrna/intern/rna_speaker.c b/source/blender/makesrna/intern/rna_speaker.c index 0c63cf5eae8..8f156a67e08 100644 --- a/source/blender/makesrna/intern/rna_speaker.c +++ b/source/blender/makesrna/intern/rna_speaker.c @@ -61,6 +61,7 @@ static void rna_def_speaker(BlenderRNA *brna) RNA_def_property_struct_type(prop, "Sound"); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Sound", "Sound data-block used by this speaker"); /* RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_sound_set", NULL); */ /* RNA_def_property_update(prop, 0, "rna_Speaker_update"); */ diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c index 28d2d722460..2015356d071 100644 --- a/source/blender/makesrna/intern/rna_texture.c +++ b/source/blender/makesrna/intern/rna_texture.c @@ -186,10 +186,10 @@ static StructRNA *rna_Texture_refine(struct PointerRNA *ptr) static void rna_Texture_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; if (GS(id->name) == ID_TE) { - Tex *tex = ptr->id.data; + Tex *tex = (Tex *)ptr->owner_id; DEG_id_tag_update(&tex->id, 0); DEG_id_tag_update(&tex->id, ID_RECALC_EDITORS); @@ -197,7 +197,7 @@ static void rna_Texture_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *pt WM_main_add_notifier(NC_MATERIAL | ND_SHADING_DRAW, NULL); } else if (GS(id->name) == ID_NT) { - bNodeTree *ntree = ptr->id.data; + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; ED_node_tag_update_nodetree(bmain, ntree, NULL); } } @@ -219,7 +219,7 @@ static void rna_Color_mapping_update(Main *UNUSED(bmain), /* Used for Texture Properties, used (also) for/in Nodes */ static void rna_Texture_nodes_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - Tex *tex = ptr->id.data; + Tex *tex = (Tex *)ptr->owner_id; DEG_id_tag_update(&tex->id, 0); DEG_id_tag_update(&tex->id, ID_RECALC_EDITORS); @@ -235,7 +235,7 @@ static void rna_Texture_type_set(PointerRNA *ptr, int value) void rna_TextureSlot_update(bContext *C, PointerRNA *ptr) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; DEG_id_tag_update(id, 0); @@ -290,8 +290,8 @@ char *rna_TextureSlot_path(PointerRNA *ptr) * since the name used is the name of the texture assigned, but the texture * may be used multiple times in the same stack */ - if (ptr->id.data) { - if (GS(((ID *)ptr->id.data)->name) == ID_BR) { + if (ptr->owner_id) { + if (GS(ptr->owner_id->name) == ID_BR) { return BLI_strdup("texture_slot"); } else { @@ -299,7 +299,7 @@ char *rna_TextureSlot_path(PointerRNA *ptr) PropertyRNA *prop; /* find the 'textures' property of the ID-struct */ - RNA_id_pointer_create(ptr->id.data, &id_ptr); + RNA_id_pointer_create(ptr->owner_id, &id_ptr); prop = RNA_struct_find_property(&id_ptr, "texture_slots"); /* get an iterator for this property, and try to find the relevant index */ @@ -630,6 +630,7 @@ static void rna_def_mtex(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "tex"); RNA_def_property_struct_type(prop, "Texture"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_CONTEXT_UPDATE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Texture", "Texture data-block used by this texture slot"); RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING_LINKS, "rna_TextureSlot_update"); @@ -834,7 +835,7 @@ static void rna_def_texture_clouds(BlenderRNA *brna) prop = RNA_def_property(srna, "noise_depth", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "noisedepth"); RNA_def_property_range(prop, 0, 30); - RNA_def_property_ui_range(prop, 0, 24, 0, 2); + RNA_def_property_ui_range(prop, 0, 24, 1, 2); RNA_def_property_ui_text(prop, "Noise Depth", "Depth of the cloud calculation"); RNA_def_property_update(prop, 0, "rna_Texture_nodes_update"); @@ -973,7 +974,7 @@ static void rna_def_texture_marble(BlenderRNA *brna) prop = RNA_def_property(srna, "noise_depth", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "noisedepth"); RNA_def_property_range(prop, 0, 30); - RNA_def_property_ui_range(prop, 0, 24, 0, 2); + RNA_def_property_ui_range(prop, 0, 24, 1, 2); RNA_def_property_ui_text(prop, "Noise Depth", "Depth of the cloud calculation"); RNA_def_property_update(prop, 0, "rna_Texture_update"); @@ -1027,7 +1028,7 @@ static void rna_def_texture_magic(BlenderRNA *brna) prop = RNA_def_property(srna, "noise_depth", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "noisedepth"); RNA_def_property_range(prop, 0, 30); - RNA_def_property_ui_range(prop, 0, 24, 0, 2); + RNA_def_property_ui_range(prop, 0, 24, 1, 2); RNA_def_property_ui_text(prop, "Noise Depth", "Depth of the noise"); RNA_def_property_update(prop, 0, "rna_Texture_update"); } @@ -1277,6 +1278,7 @@ static void rna_def_texture_image(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "ima"); RNA_def_property_struct_type(prop, "Image"); RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Image", ""); RNA_def_property_update(prop, 0, "rna_Texture_update"); diff --git a/source/blender/makesrna/intern/rna_timeline.c b/source/blender/makesrna/intern/rna_timeline.c index 3308a493212..ed17a509fc2 100644 --- a/source/blender/makesrna/intern/rna_timeline.c +++ b/source/blender/makesrna/intern/rna_timeline.c @@ -70,6 +70,7 @@ static void rna_def_timeline_marker(BlenderRNA *brna) prop = RNA_def_property(srna, "camera", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "Object"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Camera", "Camera that becomes active on this frame"); # endif } diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c index 84bde91e654..0a824b3c67a 100644 --- a/source/blender/makesrna/intern/rna_tracking.c +++ b/source/blender/makesrna/intern/rna_tracking.c @@ -61,7 +61,7 @@ static void rna_tracking_defaultSettings_patternUpdate(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; MovieTracking *tracking = &clip->tracking; MovieTrackingSettings *settings = &tracking->settings; @@ -74,7 +74,7 @@ static void rna_tracking_defaultSettings_searchUpdate(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; MovieTracking *tracking = &clip->tracking; MovieTrackingSettings *settings = &tracking->settings; @@ -85,7 +85,7 @@ static void rna_tracking_defaultSettings_searchUpdate(Main *UNUSED(bmain), static char *rna_trackingTrack_path(PointerRNA *ptr) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; MovieTrackingTrack *track = (MovieTrackingTrack *)ptr->data; /* Escaped object name, escaped track name, rest of the path. */ char rna_path[MAX_NAME * 4 + 64]; @@ -95,35 +95,35 @@ static char *rna_trackingTrack_path(PointerRNA *ptr) static void rna_trackingTracks_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; rna_iterator_listbase_begin(iter, &clip->tracking.tracks, NULL); } static void rna_trackingPlaneTracks_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; rna_iterator_listbase_begin(iter, &clip->tracking.plane_tracks, NULL); } static void rna_trackingObjects_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; rna_iterator_listbase_begin(iter, &clip->tracking.objects, NULL); } static int rna_tracking_active_object_index_get(PointerRNA *ptr) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; return clip->tracking.objectnr; } static void rna_tracking_active_object_index_set(PointerRNA *ptr, int value) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; clip->tracking.objectnr = value; BKE_tracking_dopesheet_tag_update(&clip->tracking); @@ -132,7 +132,7 @@ static void rna_tracking_active_object_index_set(PointerRNA *ptr, int value) static void rna_tracking_active_object_index_range( PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax)) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; *min = 0; *max = max_ii(0, clip->tracking.tot_object - 1); @@ -140,7 +140,7 @@ static void rna_tracking_active_object_index_range( static PointerRNA rna_tracking_active_track_get(PointerRNA *ptr) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; MovieTrackingTrack *act_track = BKE_tracking_track_get_active(&clip->tracking); return rna_pointer_inherit_refine(ptr, &RNA_MovieTrackingTrack, act_track); @@ -150,7 +150,7 @@ static void rna_tracking_active_track_set(PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; MovieTrackingTrack *track = (MovieTrackingTrack *)value.data; ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking); int index = BLI_findindex(tracksbase, track); @@ -165,7 +165,7 @@ static void rna_tracking_active_track_set(PointerRNA *ptr, static PointerRNA rna_tracking_active_plane_track_get(PointerRNA *ptr) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; MovieTrackingPlaneTrack *act_plane_track = BKE_tracking_plane_track_get_active(&clip->tracking); return rna_pointer_inherit_refine(ptr, &RNA_MovieTrackingPlaneTrack, act_plane_track); @@ -175,7 +175,7 @@ static void rna_tracking_active_plane_track_set(PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; MovieTrackingPlaneTrack *plane_track = (MovieTrackingPlaneTrack *)value.data; ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking); int index = BLI_findindex(plane_tracks_base, plane_track); @@ -190,7 +190,7 @@ static void rna_tracking_active_plane_track_set(PointerRNA *ptr, static void rna_trackingTrack_name_set(PointerRNA *ptr, const char *value) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; MovieTrackingTrack *track = (MovieTrackingTrack *)ptr->data; ListBase *tracksbase = BKE_tracking_find_tracks_list_for_track(&clip->tracking, track); /* Store old name, for the animation fix later. */ @@ -233,7 +233,7 @@ static void rna_trackingTrack_select_set(PointerRNA *ptr, bool value) static void rna_trackingPlaneMarker_frame_set(PointerRNA *ptr, int value) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; MovieTracking *tracking = &clip->tracking; MovieTrackingPlaneMarker *plane_marker = (MovieTrackingPlaneMarker *)ptr->data; MovieTrackingObject *tracking_object; @@ -268,7 +268,7 @@ static void rna_trackingPlaneMarker_frame_set(PointerRNA *ptr, int value) static char *rna_trackingPlaneTrack_path(PointerRNA *ptr) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; MovieTrackingPlaneTrack *plane_track = (MovieTrackingPlaneTrack *)ptr->data; /* Escaped object name, escaped track name, rest of the path. */ char rna_path[MAX_NAME * 4 + 64]; @@ -279,7 +279,7 @@ static char *rna_trackingPlaneTrack_path(PointerRNA *ptr) static void rna_trackingPlaneTrack_name_set(PointerRNA *ptr, const char *value) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; MovieTrackingPlaneTrack *plane_track = (MovieTrackingPlaneTrack *)ptr->data; ListBase *plane_tracks_base = BKE_tracking_find_tracks_list_for_plane_track(&clip->tracking, plane_track); @@ -307,7 +307,7 @@ static char *rna_trackingCamera_path(PointerRNA *UNUSED(ptr)) static float rna_trackingCamera_focal_mm_get(PointerRNA *ptr) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; MovieTrackingCamera *camera = &clip->tracking.camera; float val = camera->focal; @@ -320,7 +320,7 @@ static float rna_trackingCamera_focal_mm_get(PointerRNA *ptr) static void rna_trackingCamera_focal_mm_set(PointerRNA *ptr, float value) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; MovieTrackingCamera *camera = &clip->tracking.camera; if (clip->lastsize[0]) { @@ -362,26 +362,26 @@ static int rna_track_2d_stabilization_rotation(CollectionPropertyIterator *UNUSE static void rna_tracking_stabTracks_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; rna_iterator_listbase_begin(iter, &clip->tracking.tracks, rna_track_2d_stabilization); } static int rna_tracking_stabTracks_active_index_get(PointerRNA *ptr) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; return clip->tracking.stabilization.act_track; } static void rna_tracking_stabTracks_active_index_set(PointerRNA *ptr, int value) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; clip->tracking.stabilization.act_track = value; } static void rna_tracking_stabTracks_active_index_range( PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax)) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; *min = 0; *max = max_ii(0, clip->tracking.stabilization.tot_track - 1); @@ -389,26 +389,26 @@ static void rna_tracking_stabTracks_active_index_range( static void rna_tracking_stabRotTracks_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; rna_iterator_listbase_begin(iter, &clip->tracking.tracks, rna_track_2d_stabilization_rotation); } static int rna_tracking_stabRotTracks_active_index_get(PointerRNA *ptr) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; return clip->tracking.stabilization.act_rot_track; } static void rna_tracking_stabRotTracks_active_index_set(PointerRNA *ptr, int value) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; clip->tracking.stabilization.act_rot_track = value; } static void rna_tracking_stabRotTracks_active_index_range( PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax)) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; *min = 0; *max = max_ii(0, clip->tracking.stabilization.tot_rot_track - 1); @@ -416,7 +416,7 @@ static void rna_tracking_stabRotTracks_active_index_range( static void rna_tracking_flushUpdate(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; nodeUpdateID(scene->nodetree, &clip->id); @@ -429,7 +429,7 @@ static void rna_tracking_resetIntrinsics(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; MovieTracking *tracking = &clip->tracking; if (tracking->camera.intrinsics) { @@ -443,7 +443,7 @@ static void rna_trackingObject_tracks_begin(CollectionPropertyIterator *iter, Po MovieTrackingObject *object = (MovieTrackingObject *)ptr->data; if (object->flag & TRACKING_OBJECT_CAMERA) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; rna_iterator_listbase_begin(iter, &clip->tracking.tracks, NULL); } @@ -458,7 +458,7 @@ static void rna_trackingObject_plane_tracks_begin(CollectionPropertyIterator *it MovieTrackingObject *object = (MovieTrackingObject *)ptr->data; if (object->flag & TRACKING_OBJECT_CAMERA) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; rna_iterator_listbase_begin(iter, &clip->tracking.plane_tracks, NULL); } @@ -472,7 +472,7 @@ static PointerRNA rna_trackingObject_reconstruction_get(PointerRNA *ptr) MovieTrackingObject *object = (MovieTrackingObject *)ptr->data; if (object->flag & TRACKING_OBJECT_CAMERA) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; return rna_pointer_inherit_refine( ptr, &RNA_MovieTrackingReconstruction, &clip->tracking.reconstruction); @@ -485,7 +485,7 @@ static PointerRNA rna_trackingObject_reconstruction_get(PointerRNA *ptr) static PointerRNA rna_tracking_active_object_get(PointerRNA *ptr) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; MovieTrackingObject *object = BLI_findlink(&clip->tracking.objects, clip->tracking.objectnr); return rna_pointer_inherit_refine(ptr, &RNA_MovieTrackingObject, object); @@ -495,7 +495,7 @@ static void rna_tracking_active_object_set(PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; MovieTrackingObject *object = (MovieTrackingObject *)value.data; int index = BLI_findindex(&clip->tracking.objects, object); @@ -509,7 +509,7 @@ static void rna_tracking_active_object_set(PointerRNA *ptr, static void rna_trackingObject_name_set(PointerRNA *ptr, const char *value) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; MovieTrackingObject *object = (MovieTrackingObject *)ptr->data; BLI_strncpy(object->name, value, sizeof(object->name)); @@ -521,7 +521,7 @@ static void rna_trackingObject_flushUpdate(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, NULL); DEG_id_tag_update(&clip->id, 0); @@ -529,7 +529,7 @@ static void rna_trackingObject_flushUpdate(Main *UNUSED(bmain), static void rna_trackingMarker_frame_set(PointerRNA *ptr, int value) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; MovieTracking *tracking = &clip->tracking; MovieTrackingMarker *marker = (MovieTrackingMarker *)ptr->data; MovieTrackingObject *tracking_object; @@ -594,7 +594,7 @@ static void rna_trackingDopesheet_tagUpdate(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - MovieClip *clip = (MovieClip *)ptr->id.data; + MovieClip *clip = (MovieClip *)ptr->owner_id; MovieTrackingDopesheet *dopesheet = &clip->tracking.dopesheet; dopesheet->ok = 0; diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c index 097e62a1fea..a7f0c8ff19c 100644 --- a/source/blender/makesrna/intern/rna_ui.c +++ b/source/blender/makesrna/intern/rna_ui.c @@ -1410,7 +1410,7 @@ static void rna_def_panel(BlenderRNA *brna) prop = RNA_def_property(srna, "use_pin", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", PNL_PIN); - RNA_def_property_ui_text(prop, "Pin", ""); + RNA_def_property_ui_text(prop, "Pin", "Show the panel on all tabs"); /* XXX, should only tag region for redraw */ RNA_def_property_update(prop, NC_WINDOW, NULL); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index a449ed850e9..64ed284eb1f 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -912,6 +912,13 @@ static bool rna_UserDef_studiolight_is_user_defined_get(PointerRNA *ptr) return (sl->flag & STUDIOLIGHT_USER_DEFINED) != 0; } +/* StudioLight.is_user_defined */ +static bool rna_UserDef_studiolight_has_specular_highlight_pass_get(PointerRNA *ptr) +{ + StudioLight *sl = (StudioLight *)ptr->data; + return sl->flag & STUDIOLIGHT_SPECULAR_HIGHLIGHT_PASS; +} + /* StudioLight.type */ static int rna_UserDef_studiolight_type_get(PointerRNA *ptr) @@ -2297,6 +2304,11 @@ static void rna_def_userdef_theme_space_outliner(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Selected Highlight", ""); RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + prop = RNA_def_property(srna, "active", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Active Highlight", ""); + RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + prop = RNA_def_property(srna, "selected_object", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Selected Objects", ""); @@ -3695,6 +3707,15 @@ static void rna_def_userdef_studiolight(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "User Defined", ""); + prop = RNA_def_property(srna, "has_specular_highlight_pass", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_funcs( + prop, "rna_UserDef_studiolight_has_specular_highlight_pass_get", NULL); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text( + prop, + "Has Specular Highlight", + "Studio light image file has separate \"diffuse\" and \"specular\" passes"); + prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, rna_enum_studio_light_type_items); RNA_def_property_enum_funcs(prop, "rna_UserDef_studiolight_type_get", NULL, NULL); @@ -4090,6 +4111,12 @@ static void rna_def_userdef_view(BlenderRNA *brna) "Show the frames per second screen refresh rate, while animation is played back"); RNA_def_property_update(prop, 0, "rna_userdef_update"); + prop = RNA_def_property(srna, "show_addons_enabled_only", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_ADDONS_ENABLED_ONLY); + RNA_def_property_ui_text(prop, + "Enabled Add-ons Only", + "Only show enabled add-ons. Un-check to see all installed add-ons"); + static const EnumPropertyItem factor_display_items[] = { {USER_FACTOR_AS_FACTOR, "FACTOR", 0, "Factor", "Display factors as values between 0 and 1"}, {USER_FACTOR_AS_PERCENTAGE, "PERCENTAGE", 0, "Percentage", "Display factors as percentages"}, diff --git a/source/blender/makesrna/intern/rna_vfont.c b/source/blender/makesrna/intern/rna_vfont.c index cf61fe07c68..3e96b5816e5 100644 --- a/source/blender/makesrna/intern/rna_vfont.c +++ b/source/blender/makesrna/intern/rna_vfont.c @@ -40,7 +40,7 @@ /* matching fnction in rna_ID.c */ static int rna_VectorFont_filepath_editable(PointerRNA *ptr, const char **UNUSED(r_info)) { - VFont *vfont = ptr->id.data; + VFont *vfont = (VFont *)ptr->owner_id; if (BKE_vfont_is_builtin(vfont)) { return 0; } @@ -51,7 +51,7 @@ static void rna_VectorFont_reload_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - VFont *vf = ptr->id.data; + VFont *vf = (VFont *)ptr->owner_id; BKE_vfont_free_data(vf); /* update */ diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index 123ec9634c9..c3ffeaf6f6f 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -530,7 +530,7 @@ const EnumPropertyItem rna_enum_wm_report_items[] = { static wmOperator *rna_OperatorProperties_find_operator(PointerRNA *ptr) { - wmWindowManager *wm = ptr->id.data; + wmWindowManager *wm = (wmWindowManager *)ptr->owner_id; if (wm) { IDProperty *properties = (IDProperty *)ptr->data; @@ -668,7 +668,7 @@ static PointerRNA rna_PopupMenu_layout_get(PointerRNA *ptr) uiLayout *layout = UI_popup_menu_layout(pup); PointerRNA rptr; - RNA_pointer_create(ptr->id.data, &RNA_UILayout, layout, &rptr); + RNA_pointer_create(ptr->owner_id, &RNA_UILayout, layout, &rptr); return rptr; } @@ -679,7 +679,7 @@ static PointerRNA rna_PopoverMenu_layout_get(PointerRNA *ptr) uiLayout *layout = UI_popover_layout(pup); PointerRNA rptr; - RNA_pointer_create(ptr->id.data, &RNA_UILayout, layout, &rptr); + RNA_pointer_create(ptr->owner_id, &RNA_UILayout, layout, &rptr); return rptr; } @@ -690,7 +690,7 @@ static PointerRNA rna_PieMenu_layout_get(PointerRNA *ptr) uiLayout *layout = UI_pie_menu_layout(pie); PointerRNA rptr; - RNA_pointer_create(ptr->id.data, &RNA_UILayout, layout, &rptr); + RNA_pointer_create(ptr->owner_id, &RNA_UILayout, layout, &rptr); return rptr; } @@ -804,7 +804,7 @@ static void rna_Window_screen_set(PointerRNA *ptr, static bool rna_Window_screen_assign_poll(PointerRNA *UNUSED(ptr), PointerRNA value) { - bScreen *screen = value.id.data; + bScreen *screen = (bScreen *)value.owner_id; return !screen->temp; } diff --git a/source/blender/makesrna/intern/rna_wm_gizmo.c b/source/blender/makesrna/intern/rna_wm_gizmo.c index 534e3042768..ba26929d808 100644 --- a/source/blender/makesrna/intern/rna_wm_gizmo.c +++ b/source/blender/makesrna/intern/rna_wm_gizmo.c @@ -252,7 +252,7 @@ static void rna_Gizmo_update_redraw(Main *UNUSED(bmain), Scene *UNUSED(scene), P static wmGizmo *rna_GizmoProperties_find_operator(PointerRNA *ptr) { # if 0 - wmWindowManager *wm = ptr->id.data; + wmWindowManager *wm = (wmWindowManager *)ptr->owner_id; # endif /* We could try workaruond this lookup, but not trivial. */ diff --git a/source/blender/makesrna/intern/rna_workspace.c b/source/blender/makesrna/intern/rna_workspace.c index 6349b5206d6..47138653af1 100644 --- a/source/blender/makesrna/intern/rna_workspace.c +++ b/source/blender/makesrna/intern/rna_workspace.c @@ -58,7 +58,7 @@ static void rna_window_update_all(Main *UNUSED(bmain), void rna_workspace_screens_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { - WorkSpace *workspace = ptr->id.data; + WorkSpace *workspace = (WorkSpace *)ptr->owner_id; rna_iterator_listbase_begin(iter, BKE_workspace_layouts_get(workspace), NULL); } diff --git a/source/blender/makesrna/intern/rna_world.c b/source/blender/makesrna/intern/rna_world.c index 9b5611f30d7..07db2755523 100644 --- a/source/blender/makesrna/intern/rna_world.c +++ b/source/blender/makesrna/intern/rna_world.c @@ -48,17 +48,17 @@ static PointerRNA rna_World_lighting_get(PointerRNA *ptr) { - return rna_pointer_inherit_refine(ptr, &RNA_WorldLighting, ptr->id.data); + return rna_pointer_inherit_refine(ptr, &RNA_WorldLighting, ptr->owner_id); } static PointerRNA rna_World_mist_get(PointerRNA *ptr) { - return rna_pointer_inherit_refine(ptr, &RNA_WorldMistSettings, ptr->id.data); + return rna_pointer_inherit_refine(ptr, &RNA_WorldMistSettings, ptr->owner_id); } static void rna_World_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - World *wo = ptr->id.data; + World *wo = (World *)ptr->owner_id; DEG_id_tag_update(&wo->id, 0); WM_main_add_notifier(NC_WORLD | ND_WORLD, wo); @@ -67,7 +67,7 @@ static void rna_World_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerR # if 0 static void rna_World_draw_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - World *wo = ptr->id.data; + World *wo = (World *)ptr->owner_id; DEG_id_tag_update(&wo->id, 0); WM_main_add_notifier(NC_WORLD | ND_WORLD_DRAW, wo); @@ -76,7 +76,7 @@ static void rna_World_draw_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Poi static void rna_World_draw_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - World *wo = ptr->id.data; + World *wo = (World *)ptr->owner_id; DEG_id_tag_update(&wo->id, 0); WM_main_add_notifier(NC_WORLD | ND_WORLD_DRAW, wo); diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt index 3d8f96d1abc..8ff66de18b0 100644 --- a/source/blender/modifiers/CMakeLists.txt +++ b/source/blender/modifiers/CMakeLists.txt @@ -143,6 +143,10 @@ if(WITH_MOD_OCEANSIM) add_definitions(-DWITH_OCEANSIM) endif() +if(WITH_OPENSUBDIV) + add_definitions(-DWITH_OPENSUBDIV) +endif() + if(WITH_BULLET) list(APPEND LIB extern_bullet diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c index 7ae5fda7111..9f3802a4fa1 100644 --- a/source/blender/modifiers/intern/MOD_armature.c +++ b/source/blender/modifiers/intern/MOD_armature.c @@ -82,7 +82,7 @@ static bool isDisabled(const struct Scene *UNUSED(scene), /* The object type check is only needed here in case we have a placeholder * object assigned (because the library containing the armature is missing). * - * In other cases it should be impossible. + * In other cases it should be impossible to have a type mismatch. */ return !amd->object || amd->object->type != OB_ARMATURE; } diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index fd6f58a21d4..9e368d2c050 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -395,7 +395,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, count = amd->count; Object *start_cap_ob = amd->start_cap; - if (start_cap_ob && start_cap_ob != ctx->object && start_cap_ob->type == OB_MESH) { + if (start_cap_ob && start_cap_ob != ctx->object) { vgroup_start_cap_remap = BKE_object_defgroup_index_map_create( start_cap_ob, ctx->object, &vgroup_start_cap_remap_len); @@ -408,7 +408,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, } } Object *end_cap_ob = amd->end_cap; - if (end_cap_ob && end_cap_ob != ctx->object && end_cap_ob->type == OB_MESH) { + if (end_cap_ob && end_cap_ob != ctx->object) { vgroup_end_cap_remap = BKE_object_defgroup_index_map_create( end_cap_ob, ctx->object, &vgroup_end_cap_remap_len); @@ -465,13 +465,10 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, if (amd->fit_type == MOD_ARR_FITCURVE && amd->curve_ob != NULL) { Object *curve_ob = amd->curve_ob; - Curve *cu = curve_ob->data; - if (cu) { - CurveCache *curve_cache = curve_ob->runtime.curve_cache; - if (curve_cache != NULL && curve_cache->path != NULL) { - float scale_fac = mat4_to_scale(curve_ob->obmat); - length = scale_fac * curve_cache->path->totdist; - } + CurveCache *curve_cache = curve_ob->runtime.curve_cache; + if (curve_cache != NULL && curve_cache->path != NULL) { + float scale_fac = mat4_to_scale(curve_ob->obmat); + length = scale_fac * curve_cache->path->totdist; } } @@ -769,6 +766,31 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes return arrayModifier_doArray(amd, ctx, mesh); } +static bool isDisabled(const struct Scene *UNUSED(scene), + ModifierData *md, + bool UNUSED(useRenderParams)) +{ + ArrayModifierData *amd = (ArrayModifierData *)md; + + /* The object type check is only needed here in case we have a placeholder + * object assigned (because the library containing the curve/mesh is missing). + * + * In other cases it should be impossible to have a type mismatch. + */ + + if (amd->curve_ob && amd->curve_ob->type != OB_CURVE) { + return true; + } + else if (amd->start_cap && amd->start_cap->type != OB_MESH) { + return true; + } + else if (amd->end_cap && amd->end_cap->type != OB_MESH) { + return true; + } + + return false; +} + ModifierTypeInfo modifierType_Array = { /* name */ "Array", /* structName */ "ArrayModifierData", @@ -789,7 +811,7 @@ ModifierTypeInfo modifierType_Array = { /* initData */ initData, /* requiredDataMask */ NULL, /* freeData */ NULL, - /* isDisabled */ NULL, + /* isDisabled */ isDisabled, /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c index dc4898c83ff..e55eeddbfa5 100644 --- a/source/blender/modifiers/intern/MOD_boolean.c +++ b/source/blender/modifiers/intern/MOD_boolean.c @@ -71,7 +71,12 @@ static bool isDisabled(const struct Scene *UNUSED(scene), { BooleanModifierData *bmd = (BooleanModifierData *)md; - return !bmd->object; + /* The object type check is only needed here in case we have a placeholder + * object assigned (because the library containing the mesh is missing). + * + * In other cases it should be impossible to have a type mismatch. + */ + return !bmd->object || bmd->object->type != OB_MESH; } static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c index 1a6d172d2f9..cc91e345c8f 100644 --- a/source/blender/modifiers/intern/MOD_cloth.c +++ b/source/blender/modifiers/intern/MOD_cloth.c @@ -114,7 +114,7 @@ static void deformVerts(ModifierData *md, } } - BKE_mesh_apply_vert_coords(mesh_src, vertexCos); + BKE_mesh_vert_coords_apply(mesh_src, vertexCos); clothModifier_do(clmd, ctx->depsgraph, scene, ctx->object, mesh_src, vertexCos); diff --git a/source/blender/modifiers/intern/MOD_collision.c b/source/blender/modifiers/intern/MOD_collision.c index 1bbc25643a1..3d43c6de88e 100644 --- a/source/blender/modifiers/intern/MOD_collision.c +++ b/source/blender/modifiers/intern/MOD_collision.c @@ -120,7 +120,7 @@ static void deformVerts(ModifierData *md, float current_time = 0; unsigned int mvert_num = 0; - BKE_mesh_apply_vert_coords(mesh_src, vertexCos); + BKE_mesh_vert_coords_apply(mesh_src, vertexCos); BKE_mesh_calc_normals(mesh_src); current_time = DEG_get_ctime(ctx->depsgraph); diff --git a/source/blender/modifiers/intern/MOD_correctivesmooth.c b/source/blender/modifiers/intern/MOD_correctivesmooth.c index be1580f0d70..a234f468e45 100644 --- a/source/blender/modifiers/intern/MOD_correctivesmooth.c +++ b/source/blender/modifiers/intern/MOD_correctivesmooth.c @@ -635,12 +635,12 @@ static void correctivesmooth_modifier_do(ModifierData *md, if (csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) { /* caller needs to do sanity check here */ csmd->bind_coords_num = numVerts; - rest_coords = (const float(*)[3])csmd->bind_coords; + rest_coords = csmd->bind_coords; } else { int me_numVerts; - rest_coords = (const float(*)[3])((em) ? BKE_editmesh_vertexCos_get_orco(em, &me_numVerts) : - BKE_mesh_vertexCos_get(ob->data, &me_numVerts)); + rest_coords = em ? BKE_editmesh_vert_coords_alloc_orco(em, &me_numVerts) : + BKE_mesh_vert_coords_alloc(ob->data, &me_numVerts); BLI_assert((unsigned int)me_numVerts == numVerts); is_rest_coords_alloc = true; diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c index 7a07d9b28eb..f9137572d6f 100644 --- a/source/blender/modifiers/intern/MOD_curve.c +++ b/source/blender/modifiers/intern/MOD_curve.c @@ -66,7 +66,12 @@ static bool isDisabled(const Scene *UNUSED(scene), ModifierData *md, bool UNUSED { CurveModifierData *cmd = (CurveModifierData *)md; - return !cmd->object; + /* The object type check is only needed here in case we have a placeholder + * object assigned (because the library containing the curve is missing). + * + * In other cases it should be impossible to have a type mismatch. + */ + return !cmd->object || cmd->object->type != OB_CURVE; } static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c index c994a680fb0..bb032f9725c 100644 --- a/source/blender/modifiers/intern/MOD_datatransfer.c +++ b/source/blender/modifiers/intern/MOD_datatransfer.c @@ -141,9 +141,14 @@ static bool isDisabled(const struct Scene *UNUSED(scene), ModifierData *md, bool UNUSED(useRenderParams)) { - DataTransferModifierData *dtmd = (DataTransferModifierData *)md; /* If no source object, bypass. */ - return (dtmd->ob_source == NULL); + DataTransferModifierData *dtmd = (DataTransferModifierData *)md; + /* The object type check is only needed here in case we have a placeholder + * object assigned (because the library containing the mesh is missing). + * + * In other cases it should be impossible to have a type mismatch. + */ + return !dtmd->ob_source || dtmd->ob_source->type != OB_MESH; } #define HIGH_POLY_WARNING 10000 diff --git a/source/blender/modifiers/intern/MOD_fluidsim_util.c b/source/blender/modifiers/intern/MOD_fluidsim_util.c index 3083d89d555..587aa108fd1 100644 --- a/source/blender/modifiers/intern/MOD_fluidsim_util.c +++ b/source/blender/modifiers/intern/MOD_fluidsim_util.c @@ -290,7 +290,7 @@ static Mesh *fluidsim_read_obj(const char *filename, const MPoly *mp_example) gzclose(gzf); BKE_mesh_calc_edges(mesh, false, false); - BKE_mesh_apply_vert_normals(mesh, (short(*)[3])normals); + BKE_mesh_vert_normals_apply(mesh, (short(*)[3])normals); MEM_freeN(normals); // CDDM_calc_normals(result); diff --git a/source/blender/modifiers/intern/MOD_fluidsim_util.h b/source/blender/modifiers/intern/MOD_fluidsim_util.h index 0d2be3e7074..da70568353e 100644 --- a/source/blender/modifiers/intern/MOD_fluidsim_util.h +++ b/source/blender/modifiers/intern/MOD_fluidsim_util.h @@ -27,8 +27,6 @@ struct FluidsimModifierData; struct Mesh; struct ModifierEvalContext; -struct Object; -struct Scene; /* new fluid-modifier interface */ void fluidsim_init(struct FluidsimModifierData *fluidmd); diff --git a/source/blender/modifiers/intern/MOD_lattice.c b/source/blender/modifiers/intern/MOD_lattice.c index b639e874a88..a73e96da975 100644 --- a/source/blender/modifiers/intern/MOD_lattice.c +++ b/source/blender/modifiers/intern/MOD_lattice.c @@ -64,7 +64,12 @@ static bool isDisabled(const struct Scene *UNUSED(scene), { LatticeModifierData *lmd = (LatticeModifierData *)md; - return !lmd->object; + /* The object type check is only needed here in case we have a placeholder + * object assigned (because the library containing the lattice is missing). + * + * In other cases it should be impossible to have a type mismatch. + */ + return !lmd->object || lmd->object->type != OB_LATTICE; } static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) diff --git a/source/blender/modifiers/intern/MOD_mask.c b/source/blender/modifiers/intern/MOD_mask.c index 3417aaeeb5c..df8f68862e6 100644 --- a/source/blender/modifiers/intern/MOD_mask.c +++ b/source/blender/modifiers/intern/MOD_mask.c @@ -138,10 +138,10 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes return mesh; } - /* Determine whether each vertexgroup is associated with a selected bone or not: - * - Each cell is a boolean saying whether bone corresponding to the ith group is selected. + /* Determine whether each vertex-group is associated with a selected bone or not: + * - Each cell is a boolean saying whether bone corresponding to the i'th group selected. * - Groups that don't match a bone are treated as not existing - * (along with the corresponding ungrouped verts). + * (along with the corresponding un-grouped verts). */ bone_select_array = MEM_malloc_arrayN((size_t)defbase_tot, sizeof(char), "mask array"); @@ -344,6 +344,20 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes return result; } +static bool isDisabled(const struct Scene *UNUSED(scene), + ModifierData *md, + bool UNUSED(useRenderParams)) +{ + MaskModifierData *mmd = (MaskModifierData *)md; + + /* The object type check is only needed here in case we have a placeholder + * object assigned (because the library containing the armature is missing). + * + * In other cases it should be impossible to have a type mismatch. + */ + return mmd->ob_arm && mmd->ob_arm->type != OB_ARMATURE; +} + ModifierTypeInfo modifierType_Mask = { /* name */ "Mask", /* structName */ "MaskModifierData", @@ -363,7 +377,7 @@ ModifierTypeInfo modifierType_Mask = { /* initData */ NULL, /* requiredDataMask */ requiredDataMask, /* freeData */ NULL, - /* isDisabled */ NULL, + /* isDisabled */ isDisabled, /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c index da261b4f835..408e38f43ab 100644 --- a/source/blender/modifiers/intern/MOD_meshdeform.c +++ b/source/blender/modifiers/intern/MOD_meshdeform.c @@ -139,7 +139,12 @@ static bool isDisabled(const struct Scene *UNUSED(scene), { MeshDeformModifierData *mmd = (MeshDeformModifierData *)md; - return !mmd->object; + /* The object type check is only needed here in case we have a placeholder + * object assigned (because the library containing the mesh is missing). + * + * In other cases it should be impossible to have a type mismatch. + */ + return !mmd->object || mmd->object->type != OB_MESH; } static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) @@ -401,7 +406,7 @@ static void meshdeformModifier_do(ModifierData *md, } /* setup deformation data */ - cagecos = BKE_mesh_vertexCos_get(cagemesh, NULL); + cagecos = BKE_mesh_vert_coords_alloc(cagemesh, NULL); bindcagecos = (float(*)[3])mmd->bindcagecos; /* We allocate 1 element extra to make it possible to diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.c b/source/blender/modifiers/intern/MOD_meshsequencecache.c index 760830ffb24..0f57b759e38 100644 --- a/source/blender/modifiers/intern/MOD_meshsequencecache.c +++ b/source/blender/modifiers/intern/MOD_meshsequencecache.c @@ -114,10 +114,20 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes } } + /* If this invocation is for the ORCO mesh, and the mesh in Alembic hasn't changed topology, we + * must return the mesh as-is instead of deforming it. */ + if (ctx->flag & MOD_APPLY_ORCO && + !ABC_mesh_topology_changed(mcmd->reader, ctx->object, mesh, time, &err_str)) { + return mesh; + } + if (me != NULL) { MVert *mvert = mesh->mvert; MEdge *medge = mesh->medge; MPoly *mpoly = mesh->mpoly; + + /* TODO(sybren+bastien): possibly check relevant custom data layers (UV/color depending on + * flags) and duplicate those too. */ if ((me->mvert == mvert) || (me->medge == medge) || (me->mpoly == mpoly)) { /* We need to duplicate data here, otherwise we'll modify org mesh, see T51701. */ BKE_id_copy_ex(NULL, diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c index c64d9be1158..dd7c001931c 100644 --- a/source/blender/modifiers/intern/MOD_multires.c +++ b/source/blender/modifiers/intern/MOD_multires.c @@ -168,6 +168,10 @@ static Mesh *multires_as_ccg(MultiresModifierData *mmd, static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { Mesh *result = mesh; +#if !defined(WITH_OPENSUBDIV) + modifier_setError(md, "Disabled, built without OpenSubdiv"); + return result; +#endif MultiresModifierData *mmd = (MultiresModifierData *)md; SubdivSettings subdiv_settings; BKE_multires_subdiv_settings_init(&subdiv_settings, mmd); diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c index 71913378277..49bb8691764 100644 --- a/source/blender/modifiers/intern/MOD_particleinstance.c +++ b/source/blender/modifiers/intern/MOD_particleinstance.c @@ -80,7 +80,12 @@ static bool isDisabled(const struct Scene *scene, ModifierData *md, bool useRend ParticleSystem *psys; ModifierData *ob_md; - if (!pimd->ob) { + /* The object type check is only needed here in case we have a placeholder + * object assigned (because the library containing the mesh is missing). + * + * In other cases it should be impossible to have a type mismatch. + */ + if (!pimd->ob || pimd->ob->type != OB_MESH) { return true; } diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c index 021e61bd46d..a7c7c207cd6 100644 --- a/source/blender/modifiers/intern/MOD_particlesystem.c +++ b/source/blender/modifiers/intern/MOD_particlesystem.c @@ -152,7 +152,7 @@ static void deformVerts(ModifierData *md, /* make new mesh */ psmd->mesh_final = BKE_mesh_copy_for_eval(mesh_src, false); - BKE_mesh_apply_vert_coords(psmd->mesh_final, vertexCos); + BKE_mesh_vert_coords_apply(psmd->mesh_final, vertexCos); BKE_mesh_calc_normals(psmd->mesh_final); BKE_mesh_tessface_ensure(psmd->mesh_final); diff --git a/source/blender/modifiers/intern/MOD_remesh.c b/source/blender/modifiers/intern/MOD_remesh.c index 23da1ec2754..631401d9d9e 100644 --- a/source/blender/modifiers/intern/MOD_remesh.c +++ b/source/blender/modifiers/intern/MOD_remesh.c @@ -105,7 +105,7 @@ static void dualcon_add_vert(void *output_v, const float co[3]) DualConOutput *output = output_v; Mesh *mesh = output->mesh; - assert(output->curvert < mesh->totvert); + BLI_assert(output->curvert < mesh->totvert); copy_v3_v3(mesh->mvert[output->curvert].co, co); output->curvert++; @@ -119,7 +119,7 @@ static void dualcon_add_quad(void *output_v, const int vert_indices[4]) MPoly *cur_poly; int i; - assert(output->curface < mesh->totpoly); + BLI_assert(output->curface < mesh->totpoly); mloop = mesh->mloop; cur_poly = &mesh->mpoly[output->curface]; diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c index 07182d82fdc..4bca48852a2 100644 --- a/source/blender/modifiers/intern/MOD_shrinkwrap.c +++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c @@ -75,7 +75,19 @@ static bool isDisabled(const struct Scene *UNUSED(scene), bool UNUSED(useRenderParams)) { ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md; - return !smd->target; + + /* The object type check is only needed here in case we have a placeholder + * object assigned (because the library containing the mesh is missing). + * + * In other cases it should be impossible to have a type mismatch. + */ + if (!smd->target || smd->target->type != OB_MESH) { + return true; + } + else if (smd->auxTarget && smd->auxTarget->type != OB_MESH) { + return true; + } + return false; } static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c index 0b1249e263c..08a884fa879 100644 --- a/source/blender/modifiers/intern/MOD_subsurf.c +++ b/source/blender/modifiers/intern/MOD_subsurf.c @@ -208,6 +208,10 @@ static SubsurfRuntimeData *subsurf_ensure_runtime(SubsurfModifierData *smd) static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { Mesh *result = mesh; +#if !defined(WITH_OPENSUBDIV) + modifier_setError(md, "Disabled, built without OpenSubdiv"); + return result; +#endif SubsurfModifierData *smd = (SubsurfModifierData *)md; SubdivSettings subdiv_settings; subdiv_settings_init(&subdiv_settings, smd); diff --git a/source/blender/modifiers/intern/MOD_surface.c b/source/blender/modifiers/intern/MOD_surface.c index dcc6371e024..840914aa313 100644 --- a/source/blender/modifiers/intern/MOD_surface.c +++ b/source/blender/modifiers/intern/MOD_surface.c @@ -130,7 +130,7 @@ static void deformVerts(ModifierData *md, float *vec; MVert *x, *v; - BKE_mesh_apply_vert_coords(surmd->mesh, vertexCos); + BKE_mesh_vert_coords_apply(surmd->mesh, vertexCos); BKE_mesh_calc_normals(surmd->mesh); numverts = surmd->mesh->totvert; diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c index c428325e42b..b34688d27d6 100644 --- a/source/blender/modifiers/intern/MOD_surfacedeform.c +++ b/source/blender/modifiers/intern/MOD_surfacedeform.c @@ -1279,7 +1279,13 @@ static bool isDisabled(const Scene *UNUSED(scene), ModifierData *md, bool UNUSED { SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md; - return smd->target == NULL && !(smd->verts != NULL && !(smd->flags & MOD_SDEF_BIND)); + /* The object type check is only needed here in case we have a placeholder + * object assigned (because the library containing the mesh is missing). + * + * In other cases it should be impossible to have a type mismatch. + */ + return (smd->target == NULL || smd->target->type != OB_MESH) && + !(smd->verts != NULL && !(smd->flags & MOD_SDEF_BIND)); } ModifierTypeInfo modifierType_SurfaceDeform = { diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c index 452c9ff945d..71163388707 100644 --- a/source/blender/modifiers/intern/MOD_util.c +++ b/source/blender/modifiers/intern/MOD_util.c @@ -198,7 +198,7 @@ Mesh *MOD_deform_mesh_eval_get(Object *ob, /* TODO(sybren): after modifier conversion of DM to Mesh is done, check whether * we really need vertexCos here. */ if (vertexCos) { - BKE_mesh_apply_vert_coords(mesh, vertexCos); + BKE_mesh_vert_coords_apply(mesh, vertexCos); mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL; } diff --git a/source/blender/modifiers/intern/MOD_util.h b/source/blender/modifiers/intern/MOD_util.h index ba3ca44c026..e1991de3bb8 100644 --- a/source/blender/modifiers/intern/MOD_util.h +++ b/source/blender/modifiers/intern/MOD_util.h @@ -31,8 +31,6 @@ struct Mesh; struct ModifierData; struct ModifierEvalContext; struct Object; -struct Scene; -struct Tex; void MOD_init_texture(struct MappingInfoModifierData *dmd, const struct ModifierEvalContext *ctx); void MOD_get_texture_coords(struct MappingInfoModifierData *dmd, diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c index f9eb92cd132..5f1eae0297a 100644 --- a/source/blender/modifiers/intern/MOD_uvproject.c +++ b/source/blender/modifiers/intern/MOD_uvproject.c @@ -204,7 +204,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, mloop_uv = CustomData_duplicate_referenced_layer_named( &mesh->ldata, CD_MLOOPUV, uvname, numLoops); - coords = BKE_mesh_vertexCos_get(mesh, &numVerts); + coords = BKE_mesh_vert_coords_alloc(mesh, &numVerts); /* convert coords to world space */ for (i = 0, co = coords; i < numVerts; ++i, ++co) { diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c index 86d1b310d0c..95b15b4a924 100644 --- a/source/blender/modifiers/intern/MOD_weightvgproximity.c +++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c @@ -492,7 +492,7 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes /* Get our vertex coordinates. */ if (numIdx != numVerts) { - float(*tv_cos)[3] = BKE_mesh_vertexCos_get(mesh, NULL); + float(*tv_cos)[3] = BKE_mesh_vert_coords_alloc(mesh, NULL); v_cos = MEM_malloc_arrayN(numIdx, sizeof(float[3]), "WeightVGProximity Modifier, v_cos"); for (i = 0; i < numIdx; i++) { copy_v3_v3(v_cos[i], tv_cos[indices[i]]); @@ -500,7 +500,7 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes MEM_freeN(tv_cos); } else { - v_cos = BKE_mesh_vertexCos_get(mesh, NULL); + v_cos = BKE_mesh_vert_coords_alloc(mesh, NULL); } /* Compute wanted distances. */ diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 284eaa8b70b..5cf5e1ac6d3 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -200,14 +200,16 @@ set(SRC shader/nodes/node_shader_tex_sky.c shader/nodes/node_shader_tex_voronoi.c shader/nodes/node_shader_tex_wave.c + shader/nodes/node_shader_tex_white_noise.c shader/nodes/node_shader_uvAlongStroke.c shader/nodes/node_shader_uvmap.c shader/nodes/node_shader_valToRgb.c shader/nodes/node_shader_value.c - shader/nodes/node_shader_vectMath.c + shader/nodes/node_shader_vector_math.c shader/nodes/node_shader_vectTransform.c shader/nodes/node_shader_vector_displacement.c shader/nodes/node_shader_volume_absorption.c + shader/nodes/node_shader_volume_info.c shader/nodes/node_shader_volume_principled.c shader/nodes/node_shader_volume_scatter.c shader/nodes/node_shader_wavelength.c diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h index 9349a428021..30673e7cd31 100644 --- a/source/blender/nodes/NOD_shader.h +++ b/source/blender/nodes/NOD_shader.h @@ -81,6 +81,7 @@ void register_node_type_sh_layer_weight(void); void register_node_type_sh_tex_coord(void); void register_node_type_sh_particle_info(void); void register_node_type_sh_hair_info(void); +void register_node_type_sh_volume_info(void); void register_node_type_sh_script(void); void register_node_type_sh_normal_map(void); void register_node_type_sh_tangent(void); @@ -131,6 +132,7 @@ void register_node_type_sh_tex_noise(void); void register_node_type_sh_tex_checker(void); void register_node_type_sh_bump(void); void register_node_type_sh_tex_ies(void); +void register_node_type_sh_tex_white_noise(void); void register_node_type_sh_custom_group(bNodeType *ntype); diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index c72e97642a2..d14511504f0 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -53,7 +53,7 @@ DefNode(ShaderNode, SH_NODE_CAMERA, 0, "CAMERA DefNode(ShaderNode, SH_NODE_MAP_RANGE, def_map_range, "MAP_RANGE", MapRange, "Map Range", "" ) DefNode(ShaderNode, SH_NODE_CLAMP, 0, "CLAMP", Clamp, "Clamp", "" ) DefNode(ShaderNode, SH_NODE_MATH, def_math, "MATH", Math, "Math", "" ) -DefNode(ShaderNode, SH_NODE_VECT_MATH, def_vector_math, "VECT_MATH", VectorMath, "Vector Math", "" ) +DefNode(ShaderNode, SH_NODE_VECTOR_MATH, def_vector_math, "VECT_MATH", VectorMath, "Vector Math", "" ) DefNode(ShaderNode, SH_NODE_SQUEEZE, 0, "SQUEEZE", Squeeze, "Squeeze Value", "" ) DefNode(ShaderNode, SH_NODE_INVERT, 0, "INVERT", Invert, "Invert", "" ) DefNode(ShaderNode, SH_NODE_SEPRGB, 0, "SEPRGB", SeparateRGB, "Separate RGB", "" ) @@ -96,6 +96,7 @@ DefNode(ShaderNode, SH_NODE_LIGHT_FALLOFF, 0, "LIG DefNode(ShaderNode, SH_NODE_OBJECT_INFO, 0, "OBJECT_INFO", ObjectInfo, "Object Info", "" ) DefNode(ShaderNode, SH_NODE_PARTICLE_INFO, 0, "PARTICLE_INFO", ParticleInfo, "Particle Info", "" ) DefNode(ShaderNode, SH_NODE_HAIR_INFO, 0, "HAIR_INFO", HairInfo, "Hair Info", "" ) +DefNode(ShaderNode, SH_NODE_VOLUME_INFO, 0, "VOLUME_INFO", VolumeInfo, "Volume Info", "" ) DefNode(ShaderNode, SH_NODE_WIREFRAME, def_sh_tex_wireframe, "WIREFRAME", Wireframe, "Wireframe", "" ) DefNode(ShaderNode, SH_NODE_WAVELENGTH, 0, "WAVELENGTH", Wavelength, "Wavelength", "" ) DefNode(ShaderNode, SH_NODE_BLACKBODY, 0, "BLACKBODY", Blackbody, "Blackbody", "" ) @@ -127,6 +128,7 @@ DefNode(ShaderNode, SH_NODE_BEVEL, def_sh_bevel, "BEV DefNode(ShaderNode, SH_NODE_DISPLACEMENT, def_sh_displacement, "DISPLACEMENT", Displacement, "Displacement", "" ) DefNode(ShaderNode, SH_NODE_VECTOR_DISPLACEMENT,def_sh_vector_displacement,"VECTOR_DISPLACEMENT",VectorDisplacement,"Vector Displacement","" ) DefNode(ShaderNode, SH_NODE_TEX_IES, def_sh_tex_ies, "TEX_IES", TexIES, "IES Texture", "" ) +DefNode(ShaderNode, SH_NODE_TEX_WHITE_NOISE, def_sh_tex_white_noise, "TEX_WHITE_NOISE", TexWhiteNoise, "White Noise", "" ) DefNode(CompositorNode, CMP_NODE_VIEWER, def_cmp_viewer, "VIEWER", Viewer, "Viewer", "" ) DefNode(CompositorNode, CMP_NODE_RGB, 0, "RGB", RGB, "RGB", "" ) diff --git a/source/blender/nodes/composite/nodes/node_composite_denoise.c b/source/blender/nodes/composite/nodes/node_composite_denoise.c index e2fdb08816a..bb62869f470 100644 --- a/source/blender/nodes/composite/nodes/node_composite_denoise.c +++ b/source/blender/nodes/composite/nodes/node_composite_denoise.c @@ -33,8 +33,8 @@ static bNodeSocketTemplate cmp_node_denoise_in[] = { {SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f}, - {SOCK_RGBA, 1, N_("Albedo"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f}, {SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f}, + {SOCK_RGBA, 1, N_("Albedo"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f}, {-1, 0, ""}}; static bNodeSocketTemplate cmp_node_denoise_out[] = {{SOCK_RGBA, 0, N_("Image")}, {-1, 0, ""}}; diff --git a/source/blender/nodes/composite/nodes/node_composite_outputFile.c b/source/blender/nodes/composite/nodes/node_composite_outputFile.c index faf9e20da51..af806a37341 100644 --- a/source/blender/nodes/composite/nodes/node_composite_outputFile.c +++ b/source/blender/nodes/composite/nodes/node_composite_outputFile.c @@ -191,7 +191,7 @@ void ntreeCompositOutputFileSetLayer(bNode *node, bNodeSocket *sock, const char static void init_output_file(const bContext *C, PointerRNA *ptr) { Scene *scene = CTX_data_scene(C); - bNodeTree *ntree = ptr->id.data; + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; bNode *node = ptr->data; NodeImageMultiFile *nimf = MEM_callocN(sizeof(NodeImageMultiFile), "node image multi file"); ImageFormatData *format = NULL; diff --git a/source/blender/nodes/composite/nodes/node_composite_switchview.c b/source/blender/nodes/composite/nodes/node_composite_switchview.c index 92e06307afb..cecd8204f4a 100644 --- a/source/blender/nodes/composite/nodes/node_composite_switchview.c +++ b/source/blender/nodes/composite/nodes/node_composite_switchview.c @@ -116,7 +116,7 @@ static void cmp_node_switch_view_update(bNodeTree *ntree, bNode *node) static void init_switch_view(const bContext *C, PointerRNA *ptr) { Scene *scene = CTX_data_scene(C); - bNodeTree *ntree = ptr->id.data; + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; bNode *node = ptr->data; SceneRenderView *srv; bNodeSocket *sock; diff --git a/source/blender/nodes/intern/node_socket.c b/source/blender/nodes/intern/node_socket.c index 8aeada7bde0..3485bd41660 100644 --- a/source/blender/nodes/intern/node_socket.c +++ b/source/blender/nodes/intern/node_socket.c @@ -39,8 +39,6 @@ #include "NOD_socket.h" -struct Main; - struct bNodeSocket *node_add_socket_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp, diff --git a/source/blender/nodes/intern/node_util.c b/source/blender/nodes/intern/node_util.c index e9a825b5b3f..0d7f19fb67a 100644 --- a/source/blender/nodes/intern/node_util.c +++ b/source/blender/nodes/intern/node_util.c @@ -100,7 +100,7 @@ void node_math_label(bNodeTree *UNUSED(ntree), bNode *node, char *label, int max BLI_strncpy(label, IFACE_(name), maxlen); } -void node_vect_math_label(bNodeTree *UNUSED(ntree), bNode *node, char *label, int maxlen) +void node_vector_math_label(bNodeTree *UNUSED(ntree), bNode *node, char *label, int maxlen) { const char *name; RNA_enum_name(rna_enum_node_vec_math_items, node->custom1, &name); diff --git a/source/blender/nodes/intern/node_util.h b/source/blender/nodes/intern/node_util.h index 7eef70db498..49117b38aba 100644 --- a/source/blender/nodes/intern/node_util.h +++ b/source/blender/nodes/intern/node_util.h @@ -71,7 +71,7 @@ extern void *node_initexec_curves(struct bNodeExecContext *context, void node_blend_label(struct bNodeTree *ntree, struct bNode *node, char *label, int maxlen); void node_image_label(struct bNodeTree *ntree, struct bNode *node, char *label, int maxlen); void node_math_label(struct bNodeTree *ntree, struct bNode *node, char *label, int maxlen); -void node_vect_math_label(struct bNodeTree *ntree, struct bNode *node, char *label, int maxlen); +void node_vector_math_label(struct bNodeTree *ntree, struct bNode *node, char *label, int maxlen); void node_filter_label(struct bNodeTree *ntree, struct bNode *node, char *label, int maxlen); /*** Link Handling */ diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c index 4891fb323ad..41f13087f67 100644 --- a/source/blender/nodes/shader/node_shader_tree.c +++ b/source/blender/nodes/shader/node_shader_tree.c @@ -799,13 +799,15 @@ static void ntree_shader_relink_displacement(bNodeTree *ntree, bNode *output_nod nodeRemLink(ntree, displacement_link); /* Convert displacement vector to bump height. */ - bNode *dot_node = nodeAddStaticNode(NULL, ntree, SH_NODE_VECT_MATH); + bNode *dot_node = nodeAddStaticNode(NULL, ntree, SH_NODE_VECTOR_MATH); bNode *geo_node = nodeAddStaticNode(NULL, ntree, SH_NODE_NEW_GEOMETRY); bNodeSocket *normal_socket = ntree_shader_node_find_output(geo_node, "Normal"); - dot_node->custom1 = 3; /* dot product */ + bNodeSocket *dot_input1 = dot_node->inputs.first; + bNodeSocket *dot_input2 = dot_input1->next; + dot_node->custom1 = NODE_VECTOR_MATH_DOT_PRODUCT; - nodeAddLink(ntree, displacement_node, displacement_socket, dot_node, dot_node->inputs.first); - nodeAddLink(ntree, geo_node, normal_socket, dot_node, dot_node->inputs.last); + nodeAddLink(ntree, displacement_node, displacement_socket, dot_node, dot_input1); + nodeAddLink(ntree, geo_node, normal_socket, dot_node, dot_input2); displacement_node = dot_node; displacement_socket = ntree_shader_node_find_output(dot_node, "Value"); diff --git a/source/blender/nodes/shader/node_shader_util.c b/source/blender/nodes/shader/node_shader_util.c index 2e8f81979a8..65676a5ea91 100644 --- a/source/blender/nodes/shader/node_shader_util.c +++ b/source/blender/nodes/shader/node_shader_util.c @@ -283,7 +283,7 @@ void node_shader_gpu_tex_mapping(GPUMaterial *mat, GPU_link(mat, "mapping", in[0].link, tmat0, tmat1, tmat2, tmat3, tmin, tmax, &in[0].link); if (texmap->type == TEXMAP_TYPE_NORMAL) { - GPU_link(mat, "texco_norm", in[0].link, &in[0].link); + GPU_link(mat, "vector_normalize", in[0].link, &in[0].link); } } } diff --git a/source/blender/nodes/shader/nodes/node_shader_mapping.c b/source/blender/nodes/shader/nodes/node_shader_mapping.c index eca0d96f2c8..e58a5d72f28 100644 --- a/source/blender/nodes/shader/nodes/node_shader_mapping.c +++ b/source/blender/nodes/shader/nodes/node_shader_mapping.c @@ -115,7 +115,7 @@ static int gpu_shader_mapping(GPUMaterial *mat, GPU_stack_link(mat, node, "mapping", in, out, tmat0, tmat1, tmat2, tmat3, tmin, tmax); if (texmap->type == TEXMAP_TYPE_NORMAL) { - GPU_link(mat, "texco_norm", out[0].link, &out[0].link); + GPU_link(mat, "vector_normalize", out[0].link, &out[0].link); } return true; diff --git a/source/blender/nodes/shader/nodes/node_shader_math.c b/source/blender/nodes/shader/nodes/node_shader_math.c index 29c6d855eae..aaedc4aa1b7 100644 --- a/source/blender/nodes/shader/nodes/node_shader_math.c +++ b/source/blender/nodes/shader/nodes/node_shader_math.c @@ -31,272 +31,6 @@ static bNodeSocketTemplate sh_node_math_in[] = { static bNodeSocketTemplate sh_node_math_out[] = {{SOCK_FLOAT, 0, N_("Value")}, {-1, 0, ""}}; -static void node_shader_exec_math(void *UNUSED(data), - int UNUSED(thread), - bNode *node, - bNodeExecData *UNUSED(execdata), - bNodeStack **in, - bNodeStack **out) -{ - float a, b, r = 0.0f; - - nodestack_get_vec(&a, SOCK_FLOAT, in[0]); - nodestack_get_vec(&b, SOCK_FLOAT, in[1]); - - switch (node->custom1) { - - case NODE_MATH_ADD: - r = a + b; - break; - case NODE_MATH_SUB: - r = a - b; - break; - case NODE_MATH_MUL: - r = a * b; - break; - case NODE_MATH_DIVIDE: { - if (b == 0) { /* We don't want to divide by zero. */ - r = 0.0; - } - else { - r = a / b; - } - break; - } - case NODE_MATH_SIN: { - /* This one only takes one input, so we've got to choose. */ - if (in[0]->hasinput || !in[1]->hasinput) { - r = sinf(a); - } - else { - r = sinf(b); - } - break; - } - case NODE_MATH_COS: { - /* This one only takes one input, so we've got to choose. */ - if (in[0]->hasinput || !in[1]->hasinput) { - r = cosf(a); - } - else { - r = cosf(b); - } - break; - } - case NODE_MATH_TAN: { - /* This one only takes one input, so we've got to choose. */ - if (in[0]->hasinput || !in[1]->hasinput) { - r = tanf(a); - } - else { - r = tanf(b); - } - break; - } - case NODE_MATH_ASIN: { - /* This one only takes one input, so we've got to choose. */ - if (in[0]->hasinput || !in[1]->hasinput) { - /* Can't do the impossible... */ - if (a <= 1 && a >= -1) { - r = asinf(a); - } - else { - r = 0.0; - } - } - else { - /* Can't do the impossible... */ - if (b <= 1 && b >= -1) { - r = asinf(b); - } - else { - r = 0.0; - } - } - break; - } - case NODE_MATH_ACOS: { - /* This one only takes one input, so we've got to choose. */ - if (in[0]->hasinput || !in[1]->hasinput) { - /* Can't do the impossible... */ - if (a <= 1 && a >= -1) { - r = acosf(a); - } - else { - r = 0.0; - } - } - else { - /* Can't do the impossible... */ - if (b <= 1 && b >= -1) { - r = acosf(b); - } - else { - r = 0.0; - } - } - break; - } - case NODE_MATH_ATAN: { - /* This one only takes one input, so we've got to choose. */ - if (in[0]->hasinput || !in[1]->hasinput) { - r = atan(a); - } - else { - r = atan(b); - } - break; - } - case NODE_MATH_POW: { - /* Only raise negative numbers by full integers */ - if (a >= 0) { - r = pow(a, b); - } - else { - float y_mod_1 = fabsf(fmodf(b, 1.0f)); - - /* if input value is not nearly an integer, - * fall back to zero, nicer than straight rounding. */ - if (y_mod_1 > 0.999f || y_mod_1 < 0.001f) { - r = powf(a, floorf(b + 0.5f)); - } - else { - r = 0.0f; - } - } - - break; - } - case NODE_MATH_LOG: { - /* Don't want any imaginary numbers... */ - if (a > 0 && b > 0) { - r = log(a) / log(b); - } - else { - r = 0.0; - } - break; - } - case NODE_MATH_MIN: { - if (a < b) { - r = a; - } - else { - r = b; - } - break; - } - case NODE_MATH_MAX: { - if (a > b) { - r = a; - } - else { - r = b; - } - break; - } - case NODE_MATH_ROUND: { - /* This one only takes one input, so we've got to choose. */ - if (in[0]->hasinput || !in[1]->hasinput) { - r = (a < 0) ? (int)(a - 0.5f) : (int)(a + 0.5f); - } - else { - r = (b < 0) ? (int)(b - 0.5f) : (int)(b + 0.5f); - } - break; - } - case NODE_MATH_LESS: { - if (a < b) { - r = 1.0f; - } - else { - r = 0.0f; - } - break; - } - case NODE_MATH_GREATER: { - if (a > b) { - r = 1.0f; - } - else { - r = 0.0f; - } - break; - } - case NODE_MATH_MOD: { - if (b == 0.0f) { - r = 0.0f; - } - else { - r = fmod(a, b); - } - break; - } - case NODE_MATH_ABS: { - r = fabsf(a); - break; - } - case NODE_MATH_ATAN2: { - r = atan2(a, b); - break; - } - case NODE_MATH_FLOOR: { - /* This one only takes one input, so we've got to choose. */ - if (in[0]->hasinput || !in[1]->hasinput) { - r = floorf(a); - } - else { - r = floorf(b); - } - break; - } - case NODE_MATH_CEIL: { - /* This one only takes one input, so we've got to choose. */ - if (in[0]->hasinput || !in[1]->hasinput) { - r = ceilf(a); - } - else { - r = ceilf(b); - } - break; - } - case NODE_MATH_FRACT: { - /* This one only takes one input, so we've got to choose. */ - if (in[0]->hasinput || !in[1]->hasinput) { - r = a - floorf(a); - } - else { - r = b - floorf(b); - } - break; - } - case NODE_MATH_SQRT: { - /* This one only takes one input, so we've got to choose. */ - if (in[0]->hasinput || !in[1]->hasinput) { - if (a > 0) { - r = sqrt(a); - } - else { - r = 0.0; - } - } - else { - if (b > 0) { - r = sqrt(b); - } - else { - r = 0.0; - } - } - break; - } - } - if (node->custom2 & SHD_MATH_CLAMP) { - CLAMP(r, 0.0f, 1.0f); - } - out[0]->vec[0] = r; -} - static int gpu_shader_math(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), @@ -304,68 +38,65 @@ static int gpu_shader_math(GPUMaterial *mat, GPUNodeStack *out) { static const char *names[] = { - "math_add", "math_subtract", "math_multiply", "math_divide", "math_sine", - "math_cosine", "math_tangent", "math_asin", "math_acos", "math_atan", - "math_pow", "math_log", "math_min", "math_max", "math_round", - "math_less_than", "math_greater_than", "math_modulo", "math_abs", "math_atan2", - "math_floor", "math_ceil", "math_fract", "math_sqrt", + [NODE_MATH_ADD] = "math_add", + [NODE_MATH_SUBTRACT] = "math_subtract", + [NODE_MATH_MULTIPLY] = "math_multiply", + [NODE_MATH_DIVIDE] = "math_divide", + + [NODE_MATH_POWER] = "math_power", + [NODE_MATH_LOGARITHM] = "math_logarithm", + [NODE_MATH_SQRT] = "math_sqrt", + [NODE_MATH_ABSOLUTE] = "math_absolute", + + [NODE_MATH_MINIMUM] = "math_minimum", + [NODE_MATH_MAXIMUM] = "math_maximum", + [NODE_MATH_LESS_THAN] = "math_less_than", + [NODE_MATH_GREATER_THAN] = "math_greater_than", + + [NODE_MATH_ROUND] = "math_round", + [NODE_MATH_FLOOR] = "math_floor", + [NODE_MATH_CEIL] = "math_ceil", + [NODE_MATH_FRACTION] = "math_fraction", + [NODE_MATH_MODULO] = "math_modulo", + + [NODE_MATH_SINE] = "math_sine", + [NODE_MATH_COSINE] = "math_cosine", + [NODE_MATH_TANGENT] = "math_tangent", + [NODE_MATH_ARCSINE] = "math_arcsine", + [NODE_MATH_ARCCOSINE] = "math_arccosine", + [NODE_MATH_ARCTANGENT] = "math_arctangent", + [NODE_MATH_ARCTAN2] = "math_arctan2", }; - switch (node->custom1) { - case NODE_MATH_ADD: - case NODE_MATH_SUB: - case NODE_MATH_MUL: - case NODE_MATH_DIVIDE: - case NODE_MATH_POW: - case NODE_MATH_LOG: - case NODE_MATH_MIN: - case NODE_MATH_MAX: - case NODE_MATH_LESS: - case NODE_MATH_GREATER: - case NODE_MATH_MOD: - case NODE_MATH_ATAN2: - GPU_stack_link(mat, node, names[node->custom1], in, out); - break; - case NODE_MATH_SIN: - case NODE_MATH_COS: - case NODE_MATH_TAN: - case NODE_MATH_ASIN: - case NODE_MATH_ACOS: - case NODE_MATH_ATAN: - case NODE_MATH_ROUND: - case NODE_MATH_ABS: - case NODE_MATH_FLOOR: - case NODE_MATH_FRACT: - case NODE_MATH_CEIL: - case NODE_MATH_SQRT: - if (in[0].hasinput || !in[1].hasinput) { - /* use only first item and terminator */ - GPUNodeStack tmp_in[2]; - memcpy(&tmp_in[0], &in[0], sizeof(GPUNodeStack)); - memcpy(&tmp_in[1], &in[2], sizeof(GPUNodeStack)); - GPU_stack_link(mat, node, names[node->custom1], tmp_in, out); - } - else { - /* use only second item and terminator */ - GPUNodeStack tmp_in[2]; - memcpy(&tmp_in[0], &in[1], sizeof(GPUNodeStack)); - memcpy(&tmp_in[1], &in[2], sizeof(GPUNodeStack)); - GPU_stack_link(mat, node, names[node->custom1], tmp_in, out); - } - break; - default: - return 0; - } + GPU_stack_link(mat, node, names[node->custom1], in, out); if (node->custom2 & SHD_MATH_CLAMP) { float min[3] = {0.0f, 0.0f, 0.0f}; float max[3] = {1.0f, 1.0f, 1.0f}; GPU_link(mat, "clamp_value", out[0].link, GPU_constant(min), GPU_constant(max), &out[0].link); } - return 1; } +static void node_shader_update_math(bNodeTree *UNUSED(ntree), bNode *node) +{ + bNodeSocket *sock = BLI_findlink(&node->inputs, 1); + nodeSetSocketAvailability(sock, + !ELEM(node->custom1, + NODE_MATH_SQRT, + NODE_MATH_CEIL, + NODE_MATH_SINE, + NODE_MATH_ROUND, + NODE_MATH_FLOOR, + NODE_MATH_COSINE, + NODE_MATH_ARCSINE, + NODE_MATH_TANGENT, + NODE_MATH_ABSOLUTE, + NODE_MATH_FRACTION, + NODE_MATH_ARCCOSINE, + NODE_MATH_ARCTANGENT)); +} + void register_node_type_sh_math(void) { static bNodeType ntype; @@ -373,9 +104,8 @@ void register_node_type_sh_math(void) sh_node_type_base(&ntype, SH_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, 0); node_type_socket_templates(&ntype, sh_node_math_in, sh_node_math_out); node_type_label(&ntype, node_math_label); - node_type_storage(&ntype, "", NULL, NULL); - node_type_exec(&ntype, NULL, NULL, node_shader_exec_math); node_type_gpu(&ntype, gpu_shader_math); + node_type_update(&ntype, node_shader_update_math); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_mixRgb.c b/source/blender/nodes/shader/nodes/node_shader_mixRgb.c index 872f4f9da9c..ae2184d8237 100644 --- a/source/blender/nodes/shader/nodes/node_shader_mixRgb.c +++ b/source/blender/nodes/shader/nodes/node_shader_mixRgb.c @@ -92,7 +92,7 @@ static int gpu_shader_mix_rgb(GPUMaterial *mat, if (ret && node->custom2 & SHD_MIXRGB_CLAMP) { float min[3] = {0.0f, 0.0f, 0.0f}; float max[3] = {1.0f, 1.0f, 1.0f}; - GPU_link(mat, "clamp_vec3", out[0].link, GPU_constant(min), GPU_constant(max), &out[0].link); + GPU_link(mat, "clamp_color", out[0].link, GPU_constant(min), GPU_constant(max), &out[0].link); } return ret; } diff --git a/source/blender/nodes/shader/nodes/node_shader_normal.c b/source/blender/nodes/shader/nodes/node_shader_normal.c index 074cc3dd87f..9dd89258446 100644 --- a/source/blender/nodes/shader/nodes/node_shader_normal.c +++ b/source/blender/nodes/shader/nodes/node_shader_normal.c @@ -25,7 +25,7 @@ /* **************** NORMAL ******************** */ static bNodeSocketTemplate sh_node_normal_in[] = { - {SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_DIRECTION}, + {SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, 1.0f, PROP_DIRECTION}, {-1, 0, ""}, }; diff --git a/source/blender/nodes/shader/nodes/node_shader_normal_map.c b/source/blender/nodes/shader/nodes/node_shader_normal_map.c index 4976d038065..18015d94f03 100644 --- a/source/blender/nodes/shader/nodes/node_shader_normal_map.c +++ b/source/blender/nodes/shader/nodes/node_shader_normal_map.c @@ -58,7 +58,7 @@ static int gpu_shader_normal_map(GPUMaterial *mat, GPUNodeLink *realnorm; GPUNodeLink *strength; - float d[4] = {0, 0, 0, 0}; + float strength_min[4] = {0, 0, 0, 0}; if (in[0].link) { strength = in[0].link; @@ -85,7 +85,7 @@ static int gpu_shader_normal_map(GPUMaterial *mat, } negnorm = GPU_builtin(GPU_WORLD_NORMAL); - GPU_link(mat, "math_max", strength, GPU_constant(d), &strength); + GPU_link(mat, "math_maximum", strength, GPU_constant(strength_min), &strength); const char *color_to_normal_fnc_name = "color_to_normal_new_shading"; if (nm->space == SHD_SPACE_BLENDER_OBJECT || nm->space == SHD_SPACE_BLENDER_WORLD) { @@ -114,8 +114,8 @@ static int gpu_shader_normal_map(GPUMaterial *mat, break; } - GPU_link(mat, "vec_math_mix", strength, realnorm, negnorm, &out[0].link); - GPU_link(mat, "vect_normalize", out[0].link, &out[0].link); + GPU_link(mat, "vector_mix", strength, realnorm, negnorm, &out[0].link); + GPU_link(mat, "vector_normalize", out[0].link, &out[0].link); return true; } diff --git a/source/blender/nodes/shader/nodes/node_shader_object_info.c b/source/blender/nodes/shader/nodes/node_shader_object_info.c index 118b8136693..58449a53706 100644 --- a/source/blender/nodes/shader/nodes/node_shader_object_info.c +++ b/source/blender/nodes/shader/nodes/node_shader_object_info.c @@ -23,6 +23,7 @@ static bNodeSocketTemplate sh_node_object_info_out[] = { {SOCK_VECTOR, 0, N_("Location"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + {SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, {SOCK_FLOAT, 0, N_("Object Index"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, {SOCK_FLOAT, 0, N_("Material Index"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, {SOCK_FLOAT, 0, N_("Random"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, @@ -36,38 +37,25 @@ static int node_shader_gpu_object_info(GPUMaterial *mat, GPUNodeStack *out) { Material *ma = GPU_material_get_material(mat); - /* Convert to float. */ - float index = ma ? ma->index : 0; + float index = ma ? ma->index : 0.0f; return GPU_stack_link(mat, node, "node_object_info", in, out, GPU_builtin(GPU_OBJECT_MATRIX), + GPU_builtin(GPU_OBJECT_COLOR), GPU_builtin(GPU_OBJECT_INFO), GPU_constant(&index)); } -static void node_shader_exec_object_info(void *UNUSED(data), - int UNUSED(thread), - bNode *UNUSED(node), - bNodeExecData *UNUSED(execdata), - bNodeStack **UNUSED(in), - bNodeStack **UNUSED(out)) -{ -} - -/* node type definition */ void register_node_type_sh_object_info(void) { static bNodeType ntype; sh_node_type_base(&ntype, SH_NODE_OBJECT_INFO, "Object Info", NODE_CLASS_INPUT, 0); node_type_socket_templates(&ntype, NULL, sh_node_object_info_out); - node_type_init(&ntype, NULL); - node_type_storage(&ntype, "", NULL, NULL); node_type_gpu(&ntype, node_shader_gpu_object_info); - node_type_exec(&ntype, NULL, NULL, node_shader_exec_object_info); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c index bd8355ec885..a02262950a8 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c @@ -124,15 +124,15 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, if (ELEM(ima->alpha_mode, IMA_ALPHA_IGNORE, IMA_ALPHA_CHANNEL_PACKED) || IMB_colormanagement_space_name_is_data(ima->colorspace_settings.name)) { /* Don't let alpha affect color output in these cases. */ - GPU_link(mat, "tex_color_alpha_clear", out[0].link, &out[0].link); + GPU_link(mat, "color_alpha_clear", out[0].link, &out[0].link); } else { /* Always output with premultiplied alpha. */ if (ima->alpha_mode == IMA_ALPHA_PREMUL) { - GPU_link(mat, "tex_color_alpha_clear", out[0].link, &out[0].link); + GPU_link(mat, "color_alpha_clear", out[0].link, &out[0].link); } else { - GPU_link(mat, "tex_color_alpha_premultiply", out[0].link, &out[0].link); + GPU_link(mat, "color_alpha_premultiply", out[0].link, &out[0].link); } } } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.c index 6f3614e357d..5eaf09659d8 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c @@ -183,7 +183,7 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, if (ELEM(ima->alpha_mode, IMA_ALPHA_IGNORE, IMA_ALPHA_CHANNEL_PACKED) || IMB_colormanagement_space_name_is_data(ima->colorspace_settings.name)) { /* Don't let alpha affect color output in these cases. */ - GPU_link(mat, "tex_color_alpha_clear", out[0].link, &out[0].link); + GPU_link(mat, "color_alpha_clear", out[0].link, &out[0].link); } else { /* Output premultiplied alpha depending on alpha socket usage. This makes @@ -192,18 +192,18 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, * not, then there will be no artifacts from zero alpha areas. */ if (ima->alpha_mode == IMA_ALPHA_PREMUL) { if (out[1].hasoutput) { - GPU_link(mat, "tex_color_alpha_unpremultiply", out[0].link, &out[0].link); + GPU_link(mat, "color_alpha_unpremultiply", out[0].link, &out[0].link); } else { - GPU_link(mat, "tex_color_alpha_clear", out[0].link, &out[0].link); + GPU_link(mat, "color_alpha_clear", out[0].link, &out[0].link); } } else { if (out[1].hasoutput) { - GPU_link(mat, "tex_color_alpha_clear", out[0].link, &out[0].link); + GPU_link(mat, "color_alpha_clear", out[0].link, &out[0].link); } else { - GPU_link(mat, "tex_color_alpha_premultiply", out[0].link, &out[0].link); + GPU_link(mat, "color_alpha_premultiply", out[0].link, &out[0].link); } } } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.c b/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.c new file mode 100644 index 00000000000..c0f9a033476 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.c @@ -0,0 +1,76 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + */ + +#include "../node_shader_util.h" + +/* **************** WHITE NOISE **************** */ + +static bNodeSocketTemplate sh_node_tex_white_noise_in[] = { + {SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f, PROP_NONE}, + {SOCK_FLOAT, 1, N_("W"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f, PROP_NONE}, + {-1, 0, ""}}; + +static bNodeSocketTemplate sh_node_tex_white_noise_out[] = { + {SOCK_FLOAT, 0, N_("Value")}, + {-1, 0, ""}, +}; + +static void node_shader_init_tex_white_noise(bNodeTree *UNUSED(ntree), bNode *node) +{ + node->custom1 = 3; +} + +static int gpu_shader_tex_white_noise(GPUMaterial *mat, + bNode *node, + bNodeExecData *UNUSED(execdata), + GPUNodeStack *in, + GPUNodeStack *out) +{ + static const char *names[] = { + "", + "node_white_noise_1d", + "node_white_noise_2d", + "node_white_noise_3d", + "node_white_noise_4d", + }; + + return GPU_stack_link(mat, node, names[node->custom1], in, out); +} + +static void node_shader_update_tex_white_noise(bNodeTree *UNUSED(ntree), bNode *node) +{ + bNodeSocket *sockVector = nodeFindSocket(node, SOCK_IN, "Vector"); + bNodeSocket *sockW = nodeFindSocket(node, SOCK_IN, "W"); + + nodeSetSocketAvailability(sockVector, node->custom1 != 1); + nodeSetSocketAvailability(sockW, node->custom1 == 1 || node->custom1 == 4); +} + +void register_node_type_sh_tex_white_noise(void) +{ + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_TEX_WHITE_NOISE, "White Noise Texture", NODE_CLASS_TEXTURE, 0); + node_type_socket_templates(&ntype, sh_node_tex_white_noise_in, sh_node_tex_white_noise_out); + node_type_init(&ntype, node_shader_init_tex_white_noise); + node_type_gpu(&ntype, gpu_shader_tex_white_noise); + node_type_update(&ntype, node_shader_update_tex_white_noise); + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_vectMath.c b/source/blender/nodes/shader/nodes/node_shader_vectMath.c deleted file mode 100644 index 41273a6dc1d..00000000000 --- a/source/blender/nodes/shader/nodes/node_shader_vectMath.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2005 Blender Foundation. - * All rights reserved. - */ - -/** \file - * \ingroup shdnodes - */ - -#include "node_shader_util.h" - -/* **************** VECTOR MATH ******************** */ -static bNodeSocketTemplate sh_node_vect_math_in[] = { - {SOCK_VECTOR, 1, N_("Vector"), 0.5f, 0.5f, 0.5f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, - {SOCK_VECTOR, 1, N_("Vector"), 0.5f, 0.5f, 0.5f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, - {-1, 0, ""}}; - -static bNodeSocketTemplate sh_node_vect_math_out[] = { - {SOCK_VECTOR, 0, N_("Vector")}, {SOCK_FLOAT, 0, N_("Value")}, {-1, 0, ""}}; - -static void node_shader_exec_vect_math(void *UNUSED(data), - int UNUSED(thread), - bNode *node, - bNodeExecData *UNUSED(execdata), - bNodeStack **in, - bNodeStack **out) -{ - float vec1[3], vec2[3]; - - nodestack_get_vec(vec1, SOCK_VECTOR, in[0]); - nodestack_get_vec(vec2, SOCK_VECTOR, in[1]); - - if (node->custom1 == 0) { /* Add */ - out[0]->vec[0] = vec1[0] + vec2[0]; - out[0]->vec[1] = vec1[1] + vec2[1]; - out[0]->vec[2] = vec1[2] + vec2[2]; - - out[1]->vec[0] = (fabsf(out[0]->vec[0]) + fabsf(out[0]->vec[1]) + fabsf(out[0]->vec[2])) / - 3.0f; - } - else if (node->custom1 == 1) { /* Subtract */ - out[0]->vec[0] = vec1[0] - vec2[0]; - out[0]->vec[1] = vec1[1] - vec2[1]; - out[0]->vec[2] = vec1[2] - vec2[2]; - - out[1]->vec[0] = (fabsf(out[0]->vec[0]) + fabsf(out[0]->vec[1]) + fabsf(out[0]->vec[2])) / - 3.0f; - } - else if (node->custom1 == 2) { /* Average */ - out[0]->vec[0] = vec1[0] + vec2[0]; - out[0]->vec[1] = vec1[1] + vec2[1]; - out[0]->vec[2] = vec1[2] + vec2[2]; - - out[1]->vec[0] = normalize_v3(out[0]->vec); - } - else if (node->custom1 == 3) { /* Dot product */ - out[1]->vec[0] = (vec1[0] * vec2[0]) + (vec1[1] * vec2[1]) + (vec1[2] * vec2[2]); - } - else if (node->custom1 == 4) { /* Cross product */ - out[0]->vec[0] = (vec1[1] * vec2[2]) - (vec1[2] * vec2[1]); - out[0]->vec[1] = (vec1[2] * vec2[0]) - (vec1[0] * vec2[2]); - out[0]->vec[2] = (vec1[0] * vec2[1]) - (vec1[1] * vec2[0]); - - out[1]->vec[0] = normalize_v3(out[0]->vec); - } - else if (node->custom1 == 5) { /* Normalize */ - /* This one only takes one input, so we've got to choose. */ - if (in[0]->hasinput || !in[1]->hasinput) { - out[0]->vec[0] = vec1[0]; - out[0]->vec[1] = vec1[1]; - out[0]->vec[2] = vec1[2]; - } - else { - out[0]->vec[0] = vec2[0]; - out[0]->vec[1] = vec2[1]; - out[0]->vec[2] = vec2[2]; - } - - out[1]->vec[0] = normalize_v3(out[0]->vec); - } -} - -static int gpu_shader_vect_math(GPUMaterial *mat, - bNode *node, - bNodeExecData *UNUSED(execdata), - GPUNodeStack *in, - GPUNodeStack *out) -{ - static const char *names[] = { - "vec_math_add", - "vec_math_sub", - "vec_math_average", - "vec_math_dot", - "vec_math_cross", - "vec_math_normalize", - }; - - switch (node->custom1) { - case 0: - case 1: - case 2: - case 3: - case 4: - GPU_stack_link(mat, node, names[node->custom1], in, out); - break; - case 5: - if (in[0].hasinput || !in[1].hasinput) { - /* use only first item and terminator */ - GPUNodeStack tmp_in[2]; - memcpy(&tmp_in[0], &in[0], sizeof(GPUNodeStack)); - memcpy(&tmp_in[1], &in[2], sizeof(GPUNodeStack)); - GPU_stack_link(mat, node, names[node->custom1], tmp_in, out); - } - else { - /* use only second item and terminator */ - GPUNodeStack tmp_in[2]; - memcpy(&tmp_in[0], &in[1], sizeof(GPUNodeStack)); - memcpy(&tmp_in[1], &in[2], sizeof(GPUNodeStack)); - GPU_stack_link(mat, node, names[node->custom1], tmp_in, out); - } - break; - default: - return false; - } - - return true; -} - -void register_node_type_sh_vect_math(void) -{ - static bNodeType ntype; - - sh_node_type_base(&ntype, SH_NODE_VECT_MATH, "Vector Math", NODE_CLASS_CONVERTOR, 0); - node_type_socket_templates(&ntype, sh_node_vect_math_in, sh_node_vect_math_out); - node_type_label(&ntype, node_vect_math_label); - node_type_storage(&ntype, "", NULL, NULL); - node_type_exec(&ntype, NULL, NULL, node_shader_exec_vect_math); - node_type_gpu(&ntype, gpu_shader_vect_math); - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/shader/nodes/node_shader_vectTransform.c b/source/blender/nodes/shader/nodes/node_shader_vectTransform.c index fe0e7b1d638..563ef89162b 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vectTransform.c +++ b/source/blender/nodes/shader/nodes/node_shader_vectTransform.c @@ -132,7 +132,7 @@ static int gpu_shader_vect_transform(GPUMaterial *mat, } if (nodeprop->type == SHD_VECT_TRANSFORM_TYPE_NORMAL) { - GPU_link(mat, "vect_normalize", out[0].link, &out[0].link); + GPU_link(mat, "vector_normalize", out[0].link, &out[0].link); } return true; diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_math.c b/source/blender/nodes/shader/nodes/node_shader_vector_math.c new file mode 100644 index 00000000000..03de83655b5 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_vector_math.c @@ -0,0 +1,113 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup shdnodes + */ + +#include "node_shader_util.h" + +/* **************** VECTOR MATH ******************** */ +static bNodeSocketTemplate sh_node_vector_math_in[] = { + {SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, + {SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, + {SOCK_FLOAT, 1, N_("Scale"), 1.0f, 1.0f, 1.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, + {-1, 0, ""}}; + +static bNodeSocketTemplate sh_node_vector_math_out[] = { + {SOCK_VECTOR, 0, N_("Vector")}, {SOCK_FLOAT, 0, N_("Value")}, {-1, 0, ""}}; + +static int gpu_shader_vector_math(GPUMaterial *mat, + bNode *node, + bNodeExecData *UNUSED(execdata), + GPUNodeStack *in, + GPUNodeStack *out) +{ + static const char *names[] = { + [NODE_VECTOR_MATH_ADD] = "vector_math_add", + [NODE_VECTOR_MATH_SUBTRACT] = "vector_math_subtract", + [NODE_VECTOR_MATH_MULTIPLY] = "vector_math_multiply", + [NODE_VECTOR_MATH_DIVIDE] = "vector_math_divide", + + [NODE_VECTOR_MATH_CROSS_PRODUCT] = "vector_math_cross", + [NODE_VECTOR_MATH_PROJECT] = "vector_math_project", + [NODE_VECTOR_MATH_REFLECT] = "vector_math_reflect", + [NODE_VECTOR_MATH_DOT_PRODUCT] = "vector_math_dot", + + [NODE_VECTOR_MATH_DISTANCE] = "vector_math_distance", + [NODE_VECTOR_MATH_LENGTH] = "vector_math_length", + [NODE_VECTOR_MATH_SCALE] = "vector_math_scale", + [NODE_VECTOR_MATH_NORMALIZE] = "vector_math_normalize", + + [NODE_VECTOR_MATH_SNAP] = "vector_math_snap", + [NODE_VECTOR_MATH_FLOOR] = "vector_math_floor", + [NODE_VECTOR_MATH_CEIL] = "vector_math_ceil", + [NODE_VECTOR_MATH_MODULO] = "vector_math_modulo", + [NODE_VECTOR_MATH_FRACTION] = "vector_math_fraction", + [NODE_VECTOR_MATH_ABSOLUTE] = "vector_math_absolute", + [NODE_VECTOR_MATH_MINIMUM] = "vector_math_minimum", + [NODE_VECTOR_MATH_MAXIMUM] = "vector_math_maximum", + }; + + GPU_stack_link(mat, node, names[node->custom1], in, out); + return true; +} + +static void node_shader_update_vector_math(bNodeTree *UNUSED(ntree), bNode *node) +{ + bNodeSocket *sockB = BLI_findlink(&node->inputs, 1); + bNodeSocket *sockScale = nodeFindSocket(node, SOCK_IN, "Scale"); + + bNodeSocket *sockVector = nodeFindSocket(node, SOCK_OUT, "Vector"); + bNodeSocket *sockValue = nodeFindSocket(node, SOCK_OUT, "Value"); + + nodeSetSocketAvailability(sockB, + !ELEM(node->custom1, + NODE_VECTOR_MATH_CEIL, + NODE_VECTOR_MATH_SCALE, + NODE_VECTOR_MATH_FLOOR, + NODE_VECTOR_MATH_LENGTH, + NODE_VECTOR_MATH_ABSOLUTE, + NODE_VECTOR_MATH_FRACTION, + NODE_VECTOR_MATH_NORMALIZE)); + nodeSetSocketAvailability(sockScale, node->custom1 == NODE_VECTOR_MATH_SCALE); + nodeSetSocketAvailability(sockVector, + !ELEM(node->custom1, + NODE_VECTOR_MATH_LENGTH, + NODE_VECTOR_MATH_DISTANCE, + NODE_VECTOR_MATH_DOT_PRODUCT)); + nodeSetSocketAvailability(sockValue, + ELEM(node->custom1, + NODE_VECTOR_MATH_LENGTH, + NODE_VECTOR_MATH_DISTANCE, + NODE_VECTOR_MATH_DOT_PRODUCT)); +} + +void register_node_type_sh_vect_math(void) +{ + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_VECTOR_MATH, "Vector Math", NODE_CLASS_CONVERTOR, 0); + node_type_socket_templates(&ntype, sh_node_vector_math_in, sh_node_vector_math_out); + node_type_label(&ntype, node_vector_math_label); + node_type_gpu(&ntype, gpu_shader_vector_math); + node_type_update(&ntype, node_shader_update_vector_math); + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_info.c b/source/blender/nodes/shader/nodes/node_shader_volume_info.c new file mode 100644 index 00000000000..98c44dd590b --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_volume_info.c @@ -0,0 +1,56 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + */ + +#include "../node_shader_util.h" + +static bNodeSocketTemplate sh_node_volume_info_out[] = { + {SOCK_RGBA, 0, N_("Color")}, + {SOCK_FLOAT, 0, N_("Density")}, + {SOCK_FLOAT, 0, N_("Flame")}, + {SOCK_FLOAT, 0, N_("Temperature")}, + {-1, 0, ""}, +}; + +static int node_shader_gpu_volume_info(GPUMaterial *mat, + bNode *node, + bNodeExecData *UNUSED(execdata), + GPUNodeStack *in, + GPUNodeStack *out) +{ + + return GPU_stack_link(mat, + node, + "node_volume_info", + in, + out, + GPU_builtin(GPU_VOLUME_DENSITY), + GPU_builtin(GPU_VOLUME_FLAME), + GPU_builtin(GPU_VOLUME_TEMPERATURE)); +} + +void register_node_type_sh_volume_info(void) +{ + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_VOLUME_INFO, "Volume Info", NODE_CLASS_INPUT, 0); + node_type_socket_templates(&ntype, NULL, sh_node_volume_info_out); + node_type_gpu(&ntype, node_shader_gpu_volume_info); + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/texture/nodes/node_texture_math.c b/source/blender/nodes/texture/nodes/node_texture_math.c index 2eb32e0addc..b1d67a5a953 100644 --- a/source/blender/nodes/texture/nodes/node_texture_math.c +++ b/source/blender/nodes/texture/nodes/node_texture_math.c @@ -46,10 +46,10 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor case NODE_MATH_ADD: *out = in0 + in1; break; - case NODE_MATH_SUB: + case NODE_MATH_SUBTRACT: *out = in0 - in1; break; - case NODE_MATH_MUL: + case NODE_MATH_MULTIPLY: *out = in0 * in1; break; case NODE_MATH_DIVIDE: { @@ -62,19 +62,19 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor } break; } - case NODE_MATH_SIN: { + case NODE_MATH_SINE: { *out = sinf(in0); break; } - case NODE_MATH_COS: { + case NODE_MATH_COSINE: { *out = cosf(in0); break; } - case NODE_MATH_TAN: { + case NODE_MATH_TANGENT: { *out = tanf(in0); break; } - case NODE_MATH_ASIN: { + case NODE_MATH_ARCSINE: { /* Can't do the impossible... */ if (in0 <= 1 && in0 >= -1) { *out = asinf(in0); @@ -84,7 +84,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor } break; } - case NODE_MATH_ACOS: { + case NODE_MATH_ARCCOSINE: { /* Can't do the impossible... */ if (in0 <= 1 && in0 >= -1) { *out = acosf(in0); @@ -94,11 +94,11 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor } break; } - case NODE_MATH_ATAN: { + case NODE_MATH_ARCTANGENT: { *out = atan(in0); break; } - case NODE_MATH_POW: { + case NODE_MATH_POWER: { /* Only raise negative numbers by full integers */ if (in0 >= 0) { out[0] = pow(in0, in1); @@ -114,7 +114,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor } break; } - case NODE_MATH_LOG: { + case NODE_MATH_LOGARITHM: { /* Don't want any imaginary numbers... */ if (in0 > 0 && in1 > 0) { *out = log(in0) / log(in1); @@ -124,7 +124,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor } break; } - case NODE_MATH_MIN: { + case NODE_MATH_MINIMUM: { if (in0 < in1) { *out = in0; } @@ -133,7 +133,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor } break; } - case NODE_MATH_MAX: { + case NODE_MATH_MAXIMUM: { if (in0 > in1) { *out = in0; } @@ -147,7 +147,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor break; } - case NODE_MATH_LESS: { + case NODE_MATH_LESS_THAN: { if (in0 < in1) { *out = 1.0f; } @@ -157,7 +157,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor break; } - case NODE_MATH_GREATER: { + case NODE_MATH_GREATER_THAN: { if (in0 > in1) { *out = 1.0f; } @@ -167,7 +167,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor break; } - case NODE_MATH_MOD: { + case NODE_MATH_MODULO: { if (in1 == 0.0f) { *out = 0.0f; } @@ -177,12 +177,12 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor break; } - case NODE_MATH_ABS: { + case NODE_MATH_ABSOLUTE: { *out = fabsf(in0); break; } - case NODE_MATH_ATAN2: { + case NODE_MATH_ARCTAN2: { *out = atan2(in0, in1); break; } @@ -197,7 +197,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor break; } - case NODE_MATH_FRACT: { + case NODE_MATH_FRACTION: { *out = in0 - floorf(in0); break; } diff --git a/source/blender/physics/BPH_mass_spring.h b/source/blender/physics/BPH_mass_spring.h index 9666f9ba9ed..c0ceff4d8cf 100644 --- a/source/blender/physics/BPH_mass_spring.h +++ b/source/blender/physics/BPH_mass_spring.h @@ -33,7 +33,6 @@ struct Depsgraph; struct Implicit_Data; struct ListBase; struct Object; -struct VoxelData; typedef enum eMassSpringSolverStatus { BPH_SOLVER_SUCCESS = (1 << 0), diff --git a/source/blender/physics/intern/BPH_mass_spring.cpp b/source/blender/physics/intern/BPH_mass_spring.cpp index 95c16c2f033..07cb3370eec 100644 --- a/source/blender/physics/intern/BPH_mass_spring.cpp +++ b/source/blender/physics/intern/BPH_mass_spring.cpp @@ -393,7 +393,7 @@ BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s) if (s->type & CLOTH_SPRING_TYPE_SEWING) { /* TODO: verify, half verified (couldn't see error) * sewing springs usually have a large distance at first so clamp the force so we don't get - * tunnelling through collision objects. */ + * tunneling through collision objects. */ BPH_mass_spring_force_spring_linear(data, s->ij, s->kl, diff --git a/source/blender/physics/intern/implicit.h b/source/blender/physics/intern/implicit.h index a88a5785fee..32416fa01ab 100644 --- a/source/blender/physics/intern/implicit.h +++ b/source/blender/physics/intern/implicit.h @@ -186,8 +186,6 @@ bool BPH_mass_spring_force_spring_goal(struct Implicit_Data *data, struct HairGrid; -struct VoxelData; - #define MAX_HAIR_GRID_RES 256 struct HairGrid *BPH_hair_volume_create_vertex_grid(float cellsize, diff --git a/source/blender/python/bmesh/bmesh_py_types_meshdata.c b/source/blender/python/bmesh/bmesh_py_types_meshdata.c index 0aa01ddb594..2e15c1d9ce0 100644 --- a/source/blender/python/bmesh/bmesh_py_types_meshdata.c +++ b/source/blender/python/bmesh/bmesh_py_types_meshdata.c @@ -20,8 +20,8 @@ /** \file * \ingroup pybmesh * - * This file defines customdata types which can't be accessed as primitive - * python types such as MDeformVert, MLoopUV, MTexPoly + * This file defines custom-data types which can't be accessed as primitive + * python types such as #MDeformVert, #MLoopUV. */ #include <Python.h> @@ -515,8 +515,8 @@ static PySequenceMethods bpy_bmdeformvert_as_sequence = { NULL, /* sq_concat */ NULL, /* sq_repeat */ - /* note: if this is set PySequence_Check() returns True, - * but in this case we dont want to be treated as a seq */ + /* Note: if this is set #PySequence_Check() returns True, + * but in this case we don't want to be treated as a seq. */ NULL, /* sq_item */ NULL, /* sq_slice */ diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt index fc945562c98..a5f71e92438 100644 --- a/source/blender/python/intern/CMakeLists.txt +++ b/source/blender/python/intern/CMakeLists.txt @@ -231,6 +231,10 @@ if(WITH_OPENAL) add_definitions(-DWITH_OPENAL) endif() +if(WITH_OPENSUBDIV) + add_definitions(-DWITH_OPENSUBDIV) +endif() + if(WITH_SDL) list(APPEND INC_SYS ${SDL_INCLUDE_DIR} diff --git a/source/blender/python/intern/bpy_app_build_options.c b/source/blender/python/intern/bpy_app_build_options.c index a841e974e85..afb2f6b3636 100644 --- a/source/blender/python/intern/bpy_app_build_options.c +++ b/source/blender/python/intern/bpy_app_build_options.c @@ -46,6 +46,7 @@ static PyStructSequence_Field app_builtopts_info_fields[] = { {(char *)"audaspace", NULL}, {(char *)"international", NULL}, {(char *)"openal", NULL}, + {(char *)"opensubdiv", NULL}, {(char *)"sdl", NULL}, {(char *)"sdl_dynload", NULL}, {(char *)"jack", NULL}, @@ -190,6 +191,12 @@ static PyObject *make_builtopts_info(void) SetObjIncref(Py_False); #endif +#ifdef WITH_OPENSUBDIV + SetObjIncref(Py_True); +#else + SetObjIncref(Py_False); +#endif + #ifdef WITH_SDL SetObjIncref(Py_True); #else diff --git a/source/blender/python/intern/bpy_app_translations.c b/source/blender/python/intern/bpy_app_translations.c index a48cd742448..3c1dbfba72e 100644 --- a/source/blender/python/intern/bpy_app_translations.c +++ b/source/blender/python/intern/bpy_app_translations.c @@ -890,7 +890,7 @@ PyObject *BPY_app_translations_struct(void) void BPY_app_translations_end(void) { - /* Incase the object remains in a module's namespace, see T44127. */ + /* In case the object remains in a module's name-space, see T44127. */ #ifdef WITH_INTERNATIONAL _clear_translations_cache(); #endif diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index 71bc01d6b98..a73e4034ca6 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -808,7 +808,7 @@ int BPY_context_member_get(bContext *C, const char *member, bContextDataResult * ptr = &(((BPy_StructRNA *)item)->ptr); // result->ptr = ((BPy_StructRNA *)item)->ptr; - CTX_data_pointer_set(result, ptr->id.data, ptr->type, ptr->data); + CTX_data_pointer_set(result, ptr->owner_id, ptr->type, ptr->data); CTX_data_type_set(result, CTX_DATA_TYPE_POINTER); done = true; } @@ -834,7 +834,7 @@ int BPY_context_member_get(bContext *C, const char *member, bContextDataResult * BLI_addtail(&result->list, link); #endif ptr = &(((BPy_StructRNA *)list_item)->ptr); - CTX_data_list_add(result, ptr->id.data, ptr->type, ptr->data); + CTX_data_list_add(result, ptr->owner_id, ptr->type, ptr->data); } else { CLOG_INFO(BPY_LOG_CONTEXT, diff --git a/source/blender/python/intern/bpy_msgbus.c b/source/blender/python/intern/bpy_msgbus.c index 9db4201c252..630a0392dbd 100644 --- a/source/blender/python/intern/bpy_msgbus.c +++ b/source/blender/python/intern/bpy_msgbus.c @@ -269,7 +269,7 @@ static PyObject *bpy_msgbus_subscribe_rna(PyObject *UNUSED(self), PyObject *args /* Note: we may want to have a way to pass this in. */ bContext *C = (bContext *)BPy_GetContext(); struct wmMsgBus *mbus = CTX_wm_message_bus(C); - wmMsgParams_RNA msg_key_params = {{{0}}}; + wmMsgParams_RNA msg_key_params = {{0}}; wmMsgSubscribeValue msg_val_params = {0}; @@ -342,7 +342,7 @@ static PyObject *bpy_msgbus_publish_rna(PyObject *UNUSED(self), PyObject *args, /* Note: we may want to have a way to pass this in. */ bContext *C = (bContext *)BPy_GetContext(); struct wmMsgBus *mbus = CTX_wm_message_bus(C); - wmMsgParams_RNA msg_key_params = {{{0}}}; + wmMsgParams_RNA msg_key_params = {{0}}; if (py_msgbus_rna_key_from_py(py_sub, &msg_key_params, error_prefix) == -1) { return NULL; diff --git a/source/blender/python/intern/bpy_operator_wrap.c b/source/blender/python/intern/bpy_operator_wrap.c index 8f2f08c7c37..2e88a2a5b06 100644 --- a/source/blender/python/intern/bpy_operator_wrap.c +++ b/source/blender/python/intern/bpy_operator_wrap.c @@ -58,7 +58,7 @@ static void operator_properties_init(wmOperatorType *ot) /* set the default property: ot->prop */ { /* Picky developers will notice that 'bl_property' won't work with inheritance - * get direct from the dict to avoid raising a load of attribute errors (yes this isnt ideal) + * get direct from the dict to avoid raising a load of attribute errors (yes this isn't ideal) * - campbell. */ PyObject *py_class_dict = py_class->tp_dict; PyObject *bl_property = PyDict_GetItem(py_class_dict, bpy_intern_str_bl_property); diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 9a8d8c5ec21..12005b92388 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -139,7 +139,7 @@ static void id_release_gc(struct ID *id) if (PyType_IsSubtype(Py_TYPE(ob), &pyrna_struct_Type) || PyType_IsSubtype(Py_TYPE(ob), &pyrna_prop_Type)) { BPy_DummyPointerRNA *ob_ptr = (BPy_DummyPointerRNA *)ob; - if (ob_ptr->ptr.id.data == id) { + if (ob_ptr->ptr.owner_id == id) { pyrna_invalidate(ob_ptr); // printf("freeing: %p %s, %.200s\n", (void *)ob, id->name, Py_TYPE(ob)->tp_name); // i++; @@ -308,7 +308,7 @@ static bool rna_disallow_writes = false; static bool rna_id_write_error(PointerRNA *ptr, PyObject *key) { - ID *id = ptr->id.data; + ID *id = ptr->owner_id; if (id) { const short idcode = GS(id->name); /* May need more ID types added here. */ @@ -907,7 +907,7 @@ static PyObject *pyrna_struct_str(BPy_StructRNA *self) static PyObject *pyrna_struct_repr(BPy_StructRNA *self) { - ID *id = self->ptr.id.data; + ID *id = self->ptr.owner_id; PyObject *tmp_str; PyObject *ret; @@ -918,21 +918,21 @@ static PyObject *pyrna_struct_repr(BPy_StructRNA *self) tmp_str = PyUnicode_FromString(id->name + 2); - if (RNA_struct_is_ID(self->ptr.type)) { + if (RNA_struct_is_ID(self->ptr.type) && (id->flag & LIB_PRIVATE_DATA) == 0) { ret = PyUnicode_FromFormat( "bpy.data.%s[%R]", BKE_idcode_to_name_plural(GS(id->name)), tmp_str); } else { const char *path; - path = RNA_path_from_ID_to_struct(&self->ptr); + ID *real_id = NULL; + path = RNA_path_from_real_ID_to_struct(G_MAIN, &self->ptr, &real_id); if (path) { - if (GS(id->name) == ID_NT) { /* Nodetree paths are not accurate. */ - ret = PyUnicode_FromFormat("bpy.data...%s", path); - } - else { - ret = PyUnicode_FromFormat( - "bpy.data.%s[%R].%s", BKE_idcode_to_name_plural(GS(id->name)), tmp_str, path); + if (real_id != id) { + Py_DECREF(tmp_str); + tmp_str = PyUnicode_FromString(real_id->name + 2); } + ret = PyUnicode_FromFormat( + "bpy.data.%s[%R].%s", BKE_idcode_to_name_plural(GS(real_id->name)), tmp_str, path); MEM_freeN((void *)path); } @@ -1019,7 +1019,7 @@ static PyObject *pyrna_prop_str(BPy_PropertyRNA *self) static PyObject *pyrna_prop_repr_ex(BPy_PropertyRNA *self, const int index_dim, const int index) { - ID *id = self->ptr.id.data; + ID *id = self->ptr.owner_id; PyObject *tmp_str; PyObject *ret; const char *path; @@ -1033,20 +1033,23 @@ static PyObject *pyrna_prop_repr_ex(BPy_PropertyRNA *self, const int index_dim, tmp_str = PyUnicode_FromString(id->name + 2); - path = RNA_path_from_ID_to_property_index(&self->ptr, self->prop, index_dim, index); + /* Note that using G_MAIN is absolutely not ideal, but we have no access to actual Main DB from + * here. */ + ID *real_id = NULL; + path = RNA_path_from_real_ID_to_property_index( + G_MAIN, &self->ptr, self->prop, index_dim, index, &real_id); if (path) { - const char *data_delim = (path[0] == '[') ? "" : "."; - if (GS(id->name) == ID_NT) { /* Nodetree paths are not accurate. */ - ret = PyUnicode_FromFormat("bpy.data...%s", path); - } - else { - ret = PyUnicode_FromFormat("bpy.data.%s[%R]%s%s", - BKE_idcode_to_name_plural(GS(id->name)), - tmp_str, - data_delim, - path); + if (real_id != id) { + Py_DECREF(tmp_str); + tmp_str = PyUnicode_FromString(real_id->name + 2); } + const char *data_delim = (path[0] == '[') ? "" : "."; + ret = PyUnicode_FromFormat("bpy.data.%s[%R]%s%s", + BKE_idcode_to_name_plural(GS(real_id->name)), + tmp_str, + data_delim, + path); MEM_freeN((void *)path); } @@ -1982,7 +1985,7 @@ static int pyrna_py_to_prop( return -1; } else if ((value != Py_None) && ((flag & PROP_ID_SELF_CHECK) && - ptr->id.data == ((BPy_StructRNA *)value)->ptr.id.data)) { + ptr->owner_id == ((BPy_StructRNA *)value)->ptr.owner_id)) { PyErr_Format(PyExc_TypeError, "%.200s %.200s.%.200s ID type does not support assignment to itself", error_prefix, @@ -3447,7 +3450,7 @@ static PyObject *pyrna_struct_subscript(BPy_StructRNA *self, PyObject *key) return NULL; } - return BPy_IDGroup_WrapData(self->ptr.id.data, idprop, group); + return BPy_IDGroup_WrapData(self->ptr.owner_id, idprop, group); } static int pyrna_struct_ass_subscript(BPy_StructRNA *self, PyObject *key, PyObject *value) @@ -3543,7 +3546,7 @@ static PyObject *pyrna_struct_items(BPy_PropertyRNA *self) return PyList_New(0); } - return BPy_Wrap_GetItems(self->ptr.id.data, group); + return BPy_Wrap_GetItems(self->ptr.owner_id, group); } PyDoc_STRVAR(pyrna_struct_values_doc, @@ -3571,7 +3574,7 @@ static PyObject *pyrna_struct_values(BPy_PropertyRNA *self) return PyList_New(0); } - return BPy_Wrap_GetValues(self->ptr.id.data, group); + return BPy_Wrap_GetValues(self->ptr.owner_id, group); } PyDoc_STRVAR(pyrna_struct_is_property_set_doc, @@ -4708,9 +4711,9 @@ PyDoc_STRVAR(pyrna_struct_get_id_data_doc, static PyObject *pyrna_struct_get_id_data(BPy_DummyPointerRNA *self) { /* Used for struct and pointer since both have a ptr. */ - if (self->ptr.id.data) { + if (self->ptr.owner_id) { PointerRNA id_ptr; - RNA_id_pointer_create((ID *)self->ptr.id.data, &id_ptr); + RNA_id_pointer_create((ID *)self->ptr.owner_id, &id_ptr); return pyrna_struct_CreatePyObject(&id_ptr); } @@ -4894,7 +4897,7 @@ static PyObject *pyrna_struct_get(BPy_StructRNA *self, PyObject *args) idprop = IDP_GetPropertyFromGroup(group, key); if (idprop) { - return BPy_IDGroup_WrapData(self->ptr.id.data, idprop, group); + return BPy_IDGroup_WrapData(self->ptr.owner_id, idprop, group); } } @@ -4937,7 +4940,7 @@ static PyObject *pyrna_struct_pop(BPy_StructRNA *self, PyObject *args) idprop = IDP_GetPropertyFromGroup(group, key); if (idprop) { - PyObject *ret = BPy_IDGroup_WrapData(self->ptr.id.data, idprop, group); + PyObject *ret = BPy_IDGroup_WrapData(self->ptr.owner_id, idprop, group); IDP_RemoveFromGroup(group, idprop); return ret; } @@ -5787,7 +5790,7 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat * and will break if a function returns a pointer from * another ID block, watch this! - it should at least be * easy to debug since they are all ID's */ - RNA_pointer_create(ptr->id.data, ptype, *(void **)data, &newptr); + RNA_pointer_create(ptr->owner_id, ptype, *(void **)data, &newptr); } } @@ -5903,7 +5906,7 @@ static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject /* include the ID pointer for pyrna_param_to_py() so we can include the * ID pointer on return values, this only works when returned values have * the same ID as the functions. */ - RNA_pointer_create(self_ptr->id.data, &RNA_Function, self_func, &funcptr); + RNA_pointer_create(self_ptr->owner_id, &RNA_Function, self_func, &funcptr); pyargs_len = PyTuple_GET_SIZE(args); pykw_len = kw ? PyDict_Size(kw) : 0; @@ -6987,7 +6990,7 @@ static void pyrna_subtype_set_rna(PyObject *newclass, StructRNA *srna) /* Add staticmethods and classmethods. */ { - const PointerRNA func_ptr = {{NULL}, srna, NULL}; + const PointerRNA func_ptr = {NULL, srna, NULL}; const ListBase *lb; Link *link; @@ -7285,8 +7288,8 @@ PyObject *pyrna_struct_CreatePyObject(PointerRNA *ptr) // PyC_ObSpit("NewStructRNA: ", (PyObject *)pyrna); #ifdef USE_PYRNA_INVALIDATE_WEAKREF - if (ptr->id.data) { - id_weakref_pool_add(ptr->id.data, (BPy_DummyPointerRNA *)pyrna); + if (ptr->owner_id) { + id_weakref_pool_add(ptr->owner_id, (BPy_DummyPointerRNA *)pyrna); } #endif return (PyObject *)pyrna; @@ -7334,8 +7337,8 @@ PyObject *pyrna_prop_CreatePyObject(PointerRNA *ptr, PropertyRNA *prop) pyrna->prop = prop; #ifdef USE_PYRNA_INVALIDATE_WEAKREF - if (ptr->id.data) { - id_weakref_pool_add(ptr->id.data, (BPy_DummyPointerRNA *)pyrna); + if (ptr->owner_id) { + id_weakref_pool_add(ptr->owner_id, (BPy_DummyPointerRNA *)pyrna); } #endif @@ -7358,7 +7361,7 @@ PyObject *pyrna_id_CreatePyObject(ID *id) bool pyrna_id_FromPyObject(PyObject *obj, ID **id) { if (pyrna_id_CheckPyObject(obj)) { - *id = ((BPy_StructRNA *)obj)->ptr.id.data; + *id = ((BPy_StructRNA *)obj)->ptr.owner_id; return true; } else { @@ -8557,9 +8560,10 @@ static PyObject *pyrna_register_class(PyObject *UNUSED(self), PyObject *py_class } if (PyDict_GetItem(((PyTypeObject *)py_class)->tp_dict, bpy_intern_str_bl_rna)) { - PyErr_SetString(PyExc_ValueError, - "register_class(...): " - "already registered as a subclass"); + PyErr_Format(PyExc_ValueError, + "register_class(...): " + "already registered as a subclass '%.200s'", + ((PyTypeObject *)py_class)->tp_name); return NULL; } diff --git a/source/blender/python/intern/bpy_rna_anim.c b/source/blender/python/intern/bpy_rna_anim.c index 7a3499d0295..5e535d0e3ce 100644 --- a/source/blender/python/intern/bpy_rna_anim.c +++ b/source/blender/python/intern/bpy_rna_anim.c @@ -88,7 +88,7 @@ static int pyrna_struct_anim_args_parse_ex(PointerRNA *ptr, path); return -1; } - else if (ptr->id.data != r_ptr.id.data) { + else if (ptr->owner_id != r_ptr.owner_id) { PyErr_Format(PyExc_ValueError, "%.200s path spans ID blocks", error_prefix, path); return -1; } @@ -370,7 +370,7 @@ PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyOb return PyBool_FromLong(result); } else { - ID *id = self->ptr.id.data; + ID *id = self->ptr.owner_id; ReportList reports; short result; @@ -451,7 +451,7 @@ PyObject *pyrna_struct_keyframe_delete(BPy_StructRNA *self, PyObject *args, PyOb } if (prop) { - ID *id = ptr.id.data; + ID *id = ptr.owner_id; NlaStrip *strip = (NlaStrip *)ptr.data; FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), index); @@ -502,7 +502,7 @@ PyObject *pyrna_struct_keyframe_delete(BPy_StructRNA *self, PyObject *args, PyOb BKE_reports_init(&reports, RPT_STORE); result = delete_keyframe( - G.main, &reports, (ID *)self->ptr.id.data, NULL, group_name, path_full, index, cfra, 0); + G.main, &reports, (ID *)self->ptr.owner_id, NULL, group_name, path_full, index, cfra, 0); MEM_freeN((void *)path_full); if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1) { @@ -548,7 +548,7 @@ PyObject *pyrna_struct_driver_add(BPy_StructRNA *self, PyObject *args) BKE_reports_init(&reports, RPT_STORE); result = ANIM_add_driver(&reports, - (ID *)self->ptr.id.data, + (ID *)self->ptr.owner_id, path_full, index, CREATEDRIVER_WITH_FMODIFIER, @@ -559,7 +559,7 @@ PyObject *pyrna_struct_driver_add(BPy_StructRNA *self, PyObject *args) } if (result) { - ID *id = self->ptr.id.data; + ID *id = self->ptr.owner_id; AnimData *adt = BKE_animdata_from_id(id); FCurve *fcu; @@ -629,7 +629,7 @@ PyObject *pyrna_struct_driver_remove(BPy_StructRNA *self, PyObject *args) BKE_reports_init(&reports, RPT_STORE); - result = ANIM_remove_driver(&reports, (ID *)self->ptr.id.data, path_full, index, 0); + result = ANIM_remove_driver(&reports, (ID *)self->ptr.owner_id, path_full, index, 0); if (path != path_full) { MEM_freeN((void *)path_full); diff --git a/source/blender/python/intern/bpy_rna_driver.c b/source/blender/python/intern/bpy_rna_driver.c index e9e8d05aa74..a8d8252b231 100644 --- a/source/blender/python/intern/bpy_rna_driver.c +++ b/source/blender/python/intern/bpy_rna_driver.c @@ -91,7 +91,7 @@ bool pyrna_driver_is_equal_anim_rna(const PathResolvedRNA *anim_rna, const PyObj const PointerRNA *ptr_a = &anim_rna->ptr; const PointerRNA *ptr_b = &(((const BPy_StructRNA *)py_anim_rna)->ptr); - if ((ptr_a->id.data == ptr_b->id.data) && (ptr_a->type == ptr_b->type) && + if ((ptr_a->owner_id == ptr_b->owner_id) && (ptr_a->type == ptr_b->type) && (ptr_a->data == ptr_b->data)) { return true; } diff --git a/source/blender/python/mathutils/mathutils_Quaternion.c b/source/blender/python/mathutils/mathutils_Quaternion.c index 23fd65319a6..267971408bf 100644 --- a/source/blender/python/mathutils/mathutils_Quaternion.c +++ b/source/blender/python/mathutils/mathutils_Quaternion.c @@ -1015,7 +1015,7 @@ static PyObject *Quaternion_matmul(PyObject *q1, PyObject *q2) return NULL; } /*------------------------obj @= obj------------------------------ - * inplace quaternion multiplication */ + * in-place quaternion multiplication */ static PyObject *Quaternion_imatmul(PyObject *q1, PyObject *q2) { float quat[QUAT_SIZE]; diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c index 490a1d9dd76..aa7cbadde14 100644 --- a/source/blender/python/mathutils/mathutils_Vector.c +++ b/source/blender/python/mathutils/mathutils_Vector.c @@ -786,10 +786,8 @@ static PyObject *Vector_to_track_quat(VectorObject *self, PyObject *args) return NULL; } - /* - * flip vector around, since vectoquat expect a vector from target to tracking object - * and the python function expects the inverse (a vector to the target). - */ + /* Flip vector around, since #vec_to_quat expect a vector from target to tracking object + * and the python function expects the inverse (a vector to the target). */ negate_v3_v3(vec, self->vec); vec_to_quat(quat, vec, track, up); diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c index a6dded4ee8b..13d36e5af91 100644 --- a/source/blender/python/mathutils/mathutils_geometry.c +++ b/source/blender/python/mathutils/mathutils_geometry.c @@ -1213,7 +1213,7 @@ static PyObject *M_Geometry_tessellate_polygon(PyObject *UNUSED(self), PyObject PyObject *polyLine, *polyVec; int i, len_polylines, len_polypoints, ls_error = 0; - /* display listbase */ + /* Display #ListBase. */ ListBase dispbase = {NULL, NULL}; DispList *dl; float *fp; /*pointer to the array of malloced dl->verts to set the points from the vectors */ @@ -1299,7 +1299,7 @@ static PyObject *M_Geometry_tessellate_polygon(PyObject *UNUSED(self), PyObject BKE_displist_fill(&dispbase, &dispbase, NULL, false); /* The faces are stored in a new DisplayList - * that's added to the head of the listbase */ + * that's added to the head of the #ListBase. */ dl = dispbase.first; tri_list = PyList_New(dl->parts); @@ -1510,7 +1510,7 @@ static PyObject *M_Geometry_convex_hull_2d(PyObject *UNUSED(self), PyObject *poi /* Return a PyObject that is a list of lists, using the flattened list array * to fill values, with start_table and len_table giving the start index - * and length of the toplevel_len sublists + * and length of the toplevel_len sub-lists. */ static PyObject *list_of_lists_from_arrays(int *array, int *start_table, diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h index dee8dbfaa24..12e9123b5cb 100644 --- a/source/blender/render/extern/include/RE_engine.h +++ b/source/blender/render/extern/include/RE_engine.h @@ -33,7 +33,6 @@ struct BakePixel; struct Depsgraph; -struct IDProperty; struct Main; struct Object; struct Render; diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index 93b85b6b96a..dc18bac541f 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -28,11 +28,9 @@ #include "DNA_vec_types.h" #include "DEG_depsgraph.h" -struct Depsgraph; struct Image; struct ImageFormatData; struct Main; -struct NodeBlurData; struct Object; struct RenderData; struct RenderResult; @@ -41,7 +39,6 @@ struct Scene; struct StampData; struct ViewLayer; struct bMovieHandle; -struct bNodeTree; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* this include is what is exposed of render to outside world */ @@ -256,7 +253,7 @@ void RE_SetView(struct Render *re, float mat[4][4]); /* get current view and window transform */ void RE_GetViewPlane(struct Render *re, rctf *r_viewplane, rcti *r_disprect); -/* set the render threads based on the commandline and autothreads setting */ +/* set the render threads based on the command-line and autothreads setting */ void RE_init_threadcount(Render *re); bool RE_WriteRenderViewsImage(struct ReportList *reports, diff --git a/source/blender/render/extern/include/RE_render_ext.h b/source/blender/render/extern/include/RE_render_ext.h index 6771eb53abd..bca3b749192 100644 --- a/source/blender/render/extern/include/RE_render_ext.h +++ b/source/blender/render/extern/include/RE_render_ext.h @@ -31,9 +31,6 @@ struct Depsgraph; struct ImagePool; struct MTex; -struct Render; -struct Scene; -struct ViewLayer; /* render_texture.c */ /* used by particle.c, effect.c, editmesh_modes.c and brush.c, returns 1 if rgb, 0 otherwise */ diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h index c5e3575d1f9..792b2b7e071 100644 --- a/source/blender/render/extern/include/RE_shader_ext.h +++ b/source/blender/render/extern/include/RE_shader_ext.h @@ -41,10 +41,8 @@ typedef struct BakeImBufuserData { } BakeImBufuserData; /* node shaders... */ -struct ImBuf; struct ImagePool; struct MTex; -struct Object; struct Tex; /* this one uses nodes */ diff --git a/source/blender/render/intern/source/bake_api.c b/source/blender/render/intern/source/bake_api.c index c61c9b4dd7a..4e5a83555eb 100644 --- a/source/blender/render/intern/source/bake_api.c +++ b/source/blender/render/intern/source/bake_api.c @@ -700,7 +700,7 @@ void RE_bake_pixels_populate(Mesh *me, } else { int uv_id = CustomData_get_named_layer(&me->ldata, CD_MLOOPUV, uv_layer); - mloopuv = CustomData_get_layer_n(&me->ldata, CD_MTFACE, uv_id); + mloopuv = CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, uv_id); } if (mloopuv == NULL) { diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c index e9175d8d024..9672184cec8 100644 --- a/source/blender/render/intern/source/imagetexture.c +++ b/source/blender/render/intern/source/imagetexture.c @@ -267,7 +267,7 @@ int imagewrap(Tex *tex, if (texres->nor) { if (tex->imaflag & TEX_NORMALMAP) { - /* qdn: normal from color + /* Normal from color: * The invert of the red channel is to make * the normal map compliant with the outside world. * It needs to be done because in Blender diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 6284fa2d119..b4d0c2147f2 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -1992,8 +1992,8 @@ static int render_initialize_from_main(Render *re, winx = (rd->size * rd->xsch) / 100; winy = (rd->size * rd->ysch) / 100; - /* We always render smaller part, inserting it in larger image is compositor bizz, - * it uses disprect for it. */ + /* We always render smaller part, inserting it in larger image is compositor business, + * it uses 'disprect' for it. */ if (scene->r.mode & R_BORDER) { disprect.xmin = rd->border.xmin * winx; disprect.xmax = rd->border.xmax * winx; diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index cf87afa2a34..c7b18adf9b1 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -53,19 +53,15 @@ struct PropertyRNA; struct ScrArea; struct ViewLayer; struct bContext; -struct bToolRef_Runtime; struct rcti; struct wmDrag; struct wmDropBox; struct wmEvent; -struct wmEventHandler; struct wmEventHandler_Keymap; struct wmEventHandler_UI; struct wmGenericUserData; struct wmGesture; struct wmJob; -struct wmMsgSubscribeKey; -struct wmMsgSubscribeValue; struct wmOperator; struct wmOperatorType; struct wmPaintCursor; @@ -162,7 +158,8 @@ enum { WM_WINDOW_RENDER = 1, WM_WINDOW_USERPREFS, WM_WINDOW_DRIVERS, - // WM_WINDOW_FILESEL // UNUSED + WM_WINDOW_INFO, + WM_WINDOW_FILESEL, }; struct wmWindow *WM_window_open(struct bContext *C, const struct rcti *rect); @@ -496,6 +493,8 @@ bool WM_operator_properties_checker_interval_test(const struct CheckerIntervalPa #define WM_FILESEL_FILENAME (1 << 2) #define WM_FILESEL_FILEPATH (1 << 3) #define WM_FILESEL_FILES (1 << 4) +/* Show the properties sidebar by default. */ +#define WM_FILESEL_SHOW_PROPS (1 << 5) /* operator as a python command (resultuing string must be freed) */ char *WM_operator_pystring_ex(struct bContext *C, diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 195822efd7e..7fdbf79248b 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -117,7 +117,6 @@ struct ID; struct ImBuf; struct bContext; struct wmEvent; -struct wmMsgBus; struct wmOperator; struct wmWindowManager; diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_intern.h b/source/blender/windowmanager/gizmo/intern/wm_gizmo_intern.h index f0771437518..00df6edef22 100644 --- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_intern.h +++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_intern.h @@ -22,8 +22,6 @@ #define __WM_GIZMO_INTERN_H__ struct BLI_Buffer; -struct GHashIterator; -struct GizmoGeomInfo; struct wmGizmoMap; struct wmKeyConfig; diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_target_props.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_target_props.c index f5ae5427ac7..094fdf3f514 100644 --- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_target_props.c +++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_target_props.c @@ -84,6 +84,7 @@ void WM_gizmo_target_property_def_rna_ptr(wmGizmo *gz, /* if gizmo evokes an operator we cannot use it for property manipulation */ BLI_assert(gz->op_data == NULL); + BLI_assert(prop != NULL); gz_prop->type = gz_prop_type; @@ -101,6 +102,9 @@ void WM_gizmo_target_property_def_rna( { const wmGizmoPropertyType *gz_prop_type = WM_gizmotype_target_property_find(gz->type, idname); PropertyRNA *prop = RNA_struct_find_property(ptr, propname); + if (prop == NULL) { + RNA_warning("%s: %s.%s not found", __func__, RNA_struct_identifier(ptr->type), propname); + } WM_gizmo_target_property_def_rna_ptr(gz, gz_prop_type, ptr, prop, index); } diff --git a/source/blender/windowmanager/gizmo/wm_gizmo_fn.h b/source/blender/windowmanager/gizmo/wm_gizmo_fn.h index 242b0f6de80..58b58fa01d0 100644 --- a/source/blender/windowmanager/gizmo/wm_gizmo_fn.h +++ b/source/blender/windowmanager/gizmo/wm_gizmo_fn.h @@ -25,6 +25,8 @@ #include "BLI_compiler_attrs.h" +struct wmMsgBus; + /* wmGizmoGroup */ typedef bool (*wmGizmoGroupFnPoll)(const struct bContext *, struct wmGizmoGroupType *) ATTR_WARN_UNUSED_RESULT; diff --git a/source/blender/windowmanager/gizmo/wm_gizmo_wmapi.h b/source/blender/windowmanager/gizmo/wm_gizmo_wmapi.h index 33c0d305e59..cc9ccc5f4bb 100644 --- a/source/blender/windowmanager/gizmo/wm_gizmo_wmapi.h +++ b/source/blender/windowmanager/gizmo/wm_gizmo_wmapi.h @@ -31,11 +31,9 @@ #ifndef __WM_GIZMO_WMAPI_H__ #define __WM_GIZMO_WMAPI_H__ -struct wmEventHandler; struct wmEventHandler_Gizmo; struct wmEventHandler_Op; struct wmGizmoMap; -struct wmOperator; struct wmOperatorType; /* -------------------------------------------------------------------- */ diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 832bf1e9b6d..7192b25a7d5 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -2259,7 +2259,7 @@ static int wm_handler_operator_call(bContext *C, if (ot && wm_operator_check_locked_interface(C, ot)) { bool use_last_properties = true; - PointerRNA tool_properties = {{0}}; + PointerRNA tool_properties = {0}; bToolRef *keymap_tool = ((handler_base->type == WM_HANDLER_TYPE_KEYMAP) ? ((wmEventHandler_Keymap *)handler_base)->keymap_tool : @@ -2339,46 +2339,36 @@ static int wm_handler_fileselect_do(bContext *C, switch (val) { case EVT_FILESELECT_FULL_OPEN: { - ScrArea *sa; + wmWindow *win = CTX_wm_window(C); + const int sizex = 1020 * UI_DPI_FAC; + const int sizey = 600 * UI_DPI_FAC; + + if (WM_window_open_temp(C, + WM_window_pixels_x(win) / 2, + WM_window_pixels_y(win) / 2, + sizex, + sizey, + WM_WINDOW_FILESEL) != NULL) { + ScrArea *area = CTX_wm_area(C); + ARegion *region_header = BKE_area_find_region_type(area, RGN_TYPE_HEADER); - /* sa can be null when window A is active, but mouse is over window B - * in this case, open file select in original window A. Also don't - * use global areas. */ - if (handler->context.area == NULL || ED_area_is_global(handler->context.area)) { - bScreen *screen = CTX_wm_screen(C); - sa = (ScrArea *)screen->areabase.first; - } - else { - sa = handler->context.area; - } + BLI_assert(area->spacetype == SPACE_FILE); - if (sa->full) { - /* ensure the first area becomes the file browser, because the second one is the small - * top (info-)area which might be too small (in fullscreens we have max two areas) */ - if (sa->prev) { - sa = sa->prev; - } - ED_area_newspace(C, sa, SPACE_FILE, true); /* 'sa' is modified in-place */ - /* we already had a fullscreen here -> mark new space as a stacked fullscreen */ - sa->flag |= (AREA_FLAG_STACKED_FULLSCREEN | AREA_FLAG_TEMP_TYPE); - } - else if (sa->spacetype == SPACE_FILE) { - sa = ED_screen_state_toggle(C, CTX_wm_window(C), sa, SCREENMAXIMIZED); + region_header->flag |= RGN_FLAG_HIDDEN; + /* Header on bottom, AZone triangle to toggle header looks misplaced at the top */ + region_header->alignment = RGN_ALIGN_BOTTOM; + + /* settings for filebrowser, sfile is not operator owner but sends events */ + sfile = (SpaceFile *)area->spacedata.first; + sfile->op = handler->op; + + ED_fileselect_set_params(sfile); } else { - sa = ED_screen_full_newspace(C, sa, SPACE_FILE); /* sets context */ + BKE_report(&wm->reports, RPT_ERROR, "Failed to open window!"); + return OPERATOR_CANCELLED; } - /* note, getting the 'sa' back from the context causes a nasty bug where the newly created - * 'sa' != CTX_wm_area(C). removed the line below and set 'sa' in the 'if' above */ - /* sa = CTX_wm_area(C); */ - - /* settings for filebrowser, sfile is not operator owner but sends events */ - sfile = (SpaceFile *)sa->spacedata.first; - sfile->op = handler->op; - - ED_fileselect_set_params(sfile); - action = WM_HANDLER_BREAK; break; } @@ -2390,14 +2380,27 @@ static int wm_handler_fileselect_do(bContext *C, BLI_remlink(handlers, handler); if (val != EVT_FILESELECT_EXTERNAL_CANCEL) { - ScrArea *sa = CTX_wm_area(C); + for (wmWindow *win = wm->windows.first; win; win = win->next) { + if (WM_window_is_temp_screen(win)) { + bScreen *screen = WM_window_get_active_screen(win); + ScrArea *file_sa = screen->areabase.first; - if (sa->full) { - ED_screen_full_prevspace(C, sa); - } - /* user may have left fullscreen */ - else { - ED_area_prevspace(C, sa); + BLI_assert(file_sa->spacetype == SPACE_FILE); + + if (BLI_listbase_is_single(&file_sa->spacedata)) { + wmWindow *ctx_win = CTX_wm_window(C); + wm_window_close(C, wm, win); + CTX_wm_window_set(C, ctx_win); // wm_window_close() NULLs. + } + else if (file_sa->full) { + ED_screen_full_prevspace(C, file_sa); + } + else { + ED_area_prevspace(C, file_sa); + } + + break; + } } } diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 189c4f18613..af841f20620 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -77,6 +77,7 @@ #include "BKE_context.h" #include "BKE_global.h" #include "BKE_idprop.h" +#include "BKE_library_override.h" #include "BKE_main.h" #include "BKE_packedFile.h" #include "BKE_report.h" @@ -100,6 +101,7 @@ #include "ED_datafiles.h" #include "ED_fileselect.h" #include "ED_image.h" +#include "ED_outliner.h" #include "ED_screen.h" #include "ED_view3d.h" #include "ED_util.h" @@ -1203,6 +1205,8 @@ static ImBuf *blend_file_thumb(const bContext *C, /* will be scaled down, but gives some nice oversampling */ ImBuf *ibuf; BlendThumbnail *thumb; + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *windrawable_old = wm->windrawable; char err_out[256] = "unknown"; /* screen if no camera found */ @@ -1236,6 +1240,9 @@ static ImBuf *blend_file_thumb(const bContext *C, /* gets scaled to BLEN_THUMB_SIZE */ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + /* Offscreen drawing requires a drawable window context. */ + wm_window_make_drawable(wm, CTX_wm_window(C)); + if (scene->camera) { ibuf = ED_view3d_draw_offscreen_imbuf_simple(depsgraph, scene, @@ -1268,6 +1275,14 @@ static ImBuf *blend_file_thumb(const bContext *C, err_out); } + /* Reset to old drawable. */ + if (windrawable_old) { + wm_window_make_drawable(wm, windrawable_old); + } + else { + wm_window_clear_drawable(wm); + } + if (ibuf) { float aspect = (scene->r.xsch * scene->r.xasp) / (scene->r.ysch * scene->r.yasp); @@ -1351,10 +1366,13 @@ static bool wm_file_write(bContext *C, const char *filepath, int fileflags, Repo } } - /* Call pre-save callbacks befores writing preview, + /* Call pre-save callbacks before writing preview, * that way you can generate custom file thumbnail. */ BLI_callback_exec(bmain, NULL, BLI_CB_EVT_SAVE_PRE); + /* Enforce full override check/generation on file save. */ + BKE_main_override_library_operations_create(bmain, true); + /* blend file thumbnail */ /* Save before exit_editmode, otherwise derivedmeshes for shared data corrupt T27765. */ /* Main now can store a '.blend' thumbnail, useful for background mode @@ -1967,6 +1985,10 @@ static int wm_homefile_read_exec(bContext *C, wmOperator *op) } } + if (G.fileflags & G_FILE_NO_UI) { + ED_outliner_select_sync_from_all_tag(C); + } + return OPERATOR_FINISHED; } @@ -2222,6 +2244,9 @@ static int wm_open_mainfile__open(bContext *C, wmOperator *op) BKE_report_print_level_set(op->reports, RPT_WARNING); if (success) { + if (G.fileflags & G_FILE_NO_UI) { + ED_outliner_select_sync_from_all_tag(C); + } return OPERATOR_FINISHED; } else { @@ -2310,7 +2335,7 @@ static void wm_open_mainfile_ui(bContext *UNUSED(C), wmOperator *op) void WM_OT_open_mainfile(wmOperatorType *ot) { - ot->name = "Open Blender File"; + ot->name = "Open"; ot->idname = "WM_OT_open_mainfile"; ot->description = "Open a Blender file"; @@ -2492,7 +2517,7 @@ void WM_OT_recover_auto_save(wmOperatorType *ot) FILE_BLENDER, FILE_OPENFILE, WM_FILESEL_FILEPATH, - FILE_LONGDISPLAY, + FILE_HORIZONTALDISPLAY, FILE_SORT_TIME); } @@ -2626,7 +2651,7 @@ void WM_OT_save_as_mainfile(wmOperatorType *ot) { PropertyRNA *prop; - ot->name = "Save As Blender File"; + ot->name = "Save As"; ot->idname = "WM_OT_save_as_mainfile"; ot->description = "Save the current file in the desired location"; @@ -2832,6 +2857,12 @@ static uiBlock *block_create_autorun_warning(struct bContext *C, /* Buttons */ uiBut *but; uiLayout *split = uiLayoutSplit(layout, 0.0f, true); + uiLayoutSetScaleY(split, 1.2f); + + /* empty space */ + col = uiLayoutColumn(split, false); + uiItemS(col); + col = uiLayoutColumn(split, false); /* Allow reload if we have a saved file. @@ -2872,12 +2903,9 @@ static uiBlock *block_create_autorun_warning(struct bContext *C, TIP_("Enable scripts")); UI_but_func_set(but, wm_block_autorun_warning_enable_scripts, block, NULL); } + UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT); - /* empty space between buttons */ col = uiLayoutColumn(split, false); - uiItemS(col); - - col = uiLayoutColumn(split, 1); but = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, @@ -2894,8 +2922,10 @@ static uiBlock *block_create_autorun_warning(struct bContext *C, 0, TIP_("Continue using file without Python scripts")); UI_but_func_set(but, wm_block_autorun_warning_ignore, block, NULL); + UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT); + UI_but_flag_enable(but, UI_BUT_ACTIVE_DEFAULT); - UI_block_bounds_set_centered(block, 10); + UI_block_bounds_set_centered(block, 14 * U.dpi_fac); return block; } @@ -2998,7 +3028,7 @@ static void wm_block_file_close_cancel_button(uiBlock *block, wmGenericCallback static void wm_block_file_close_discard_button(uiBlock *block, wmGenericCallback *post_action) { uiBut *but = uiDefIconTextBut( - block, UI_BTYPE_BUT, 0, 0, IFACE_("Discard Changes"), 0, 0, 0, UI_UNIT_Y, 0, 0, 0, 0, 0, ""); + block, UI_BTYPE_BUT, 0, 0, IFACE_("Don't Save"), 0, 0, 0, UI_UNIT_Y, 0, 0, 0, 0, 0, ""); UI_but_func_set(but, wm_block_file_close_discard, block, post_action); UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT); } @@ -3018,8 +3048,28 @@ static uiBlock *block_create__close_file_dialog(struct bContext *C, struct ARegi { wmGenericCallback *post_action = (wmGenericCallback *)arg1; Main *bmain = CTX_data_main(C); - uiStyle *style = UI_style_get(); + uiFontStyle *fs = &style->widgetlabel; + + /* Filename */ + const char *blendfile_pathpath = BKE_main_blendfile_path(bmain); + char filename[FILE_MAX]; + if (blendfile_pathpath[0] != '\0') { + BLI_split_file_part(blendfile_pathpath, filename, sizeof(filename)); + BLI_path_extension_replace(filename, sizeof(filename), ""); + } + else { + STRNCPY(filename, IFACE_("Untitled")); + } + + /* Title */ + char title[FILE_MAX + 100]; + UI_text_clip_middle_ex( + fs, filename, U.widget_unit * 9, U.widget_unit * 2, sizeof(filename), '\0'); + BLI_snprintf(title, sizeof(title), TIP_("Save changes to \"%s\" before closing?"), filename); + int title_width = MAX2(UI_fontstyle_string_width(fs, title), U.widget_unit * 22); + + /* Create dialog */ uiBlock *block = UI_block_begin(C, ar, close_file_dialog_name, UI_EMBOSS); UI_block_flag_enable( @@ -3032,25 +3082,25 @@ static uiBlock *block_create__close_file_dialog(struct bContext *C, struct ARegi UI_LAYOUT_PANEL, 10, 2, - U.widget_unit * 24, + U.widget_unit * 2 + title_width, U.widget_unit * 6, 0, style); /* Title */ - bool blend_file_is_saved = BKE_main_blendfile_path(bmain)[0] != '\0'; - if (blend_file_is_saved) { - uiItemL(layout, "This file has unsaved changes.", ICON_INFO); - } - else { - uiItemL(layout, "This file has not been saved yet.", ICON_INFO); - } + uiItemL(layout, title, ICON_ERROR); /* Image Saving */ ReportList reports; BKE_reports_init(&reports, RPT_STORE); uint modified_images_count = ED_image_save_all_modified_info(C, &reports); + LISTBASE_FOREACH (Report *, report, &reports.list) { + uiLayout *row = uiLayoutRow(layout, false); + uiLayoutSetRedAlert(row, true); + uiItemL(row, report->message, ICON_CANCEL); + } + if (modified_images_count > 0) { char message[64]; BLI_snprintf(message, @@ -3058,6 +3108,7 @@ static uiBlock *block_create__close_file_dialog(struct bContext *C, struct ARegi (modified_images_count == 1) ? "Save %u modified image" : "Save %u modified images", modified_images_count); + uiItemS(layout); uiDefButBitC(block, UI_BTYPE_CHECKBOX, 1, @@ -3075,13 +3126,9 @@ static uiBlock *block_create__close_file_dialog(struct bContext *C, struct ARegi ""); } - LISTBASE_FOREACH (Report *, report, &reports.list) { - uiItemL(layout, report->message, ICON_ERROR); - } - BKE_reports_clear(&reports); - uiItemL(layout, "", ICON_NONE); + uiItemS_ex(layout, 3.0f); /* Buttons */ #ifdef _WIN32 @@ -3090,10 +3137,12 @@ static uiBlock *block_create__close_file_dialog(struct bContext *C, struct ARegi const bool windows_layout = false; #endif - uiLayout *split = uiLayoutSplit(layout, 0.0f, true); - if (windows_layout) { /* Windows standard layout. */ + + uiLayout *split = uiLayoutSplit(layout, 0.18f, true); + uiLayoutSetScaleY(split, 1.2f); + uiLayout *col = uiLayoutColumn(split, false); uiItemS(col); @@ -3108,20 +3157,24 @@ static uiBlock *block_create__close_file_dialog(struct bContext *C, struct ARegi } else { /* macOS and Linux standard layout. */ - uiLayout *col = uiLayoutColumn(split, false); + + uiLayout *split = uiLayoutSplit(layout, 0.0f, true); + uiLayoutSetScaleY(split, 1.2f); + + uiLayout *col = uiLayoutColumn(split, true); wm_block_file_close_discard_button(block, post_action); - col = uiLayoutColumn(split, false); + col = uiLayoutColumn(split, true); uiItemS(col); - col = uiLayoutColumn(split, false); + col = uiLayoutColumn(split, true); wm_block_file_close_cancel_button(block, post_action); col = uiLayoutColumn(split, false); wm_block_file_close_save_button(block, post_action); } - UI_block_bounds_set_centered(block, 10); + UI_block_bounds_set_centered(block, 14 * U.dpi_fac); return block; } diff --git a/source/blender/windowmanager/intern/wm_files_link.c b/source/blender/windowmanager/intern/wm_files_link.c index 5a6606984ba..2cd2cf0636a 100644 --- a/source/blender/windowmanager/intern/wm_files_link.c +++ b/source/blender/windowmanager/intern/wm_files_link.c @@ -561,7 +561,7 @@ static void wm_link_append_properties_common(wmOperatorType *ot, bool is_link) void WM_OT_link(wmOperatorType *ot) { - ot->name = "Link from Library"; + ot->name = "Link"; ot->idname = "WM_OT_link"; ot->description = "Link from a Library .blend file"; @@ -585,7 +585,7 @@ void WM_OT_link(wmOperatorType *ot) void WM_OT_append(wmOperatorType *ot) { - ot->name = "Append from Library"; + ot->name = "Append"; ot->idname = "WM_OT_append"; ot->description = "Append from a Library .blend file"; diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 29cb02888ac..d08f4e236ee 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -524,6 +524,7 @@ void WM_exit_ex(bContext *C, const bool do_python) BKE_addon_pref_type_free(); BKE_keyconfig_pref_type_free(); + BKE_material_gpencil_default_free(); wm_operatortype_free(); wm_dropbox_free(); diff --git a/source/blender/windowmanager/intern/wm_operator_props.c b/source/blender/windowmanager/intern/wm_operator_props.c index fcb55d3f801..663e4adf06b 100644 --- a/source/blender/windowmanager/intern/wm_operator_props.c +++ b/source/blender/windowmanager/intern/wm_operator_props.c @@ -65,19 +65,27 @@ void WM_operator_properties_filesel(wmOperatorType *ot, 0, "Default", "Automatically determine display type for files"}, - {FILE_SHORTDISPLAY, - "LIST_SHORT", - ICON_SHORTDISPLAY, + {FILE_VERTICALDISPLAY, + "LIST_VERTICAL", + ICON_SHORTDISPLAY, /* Name of deprecated short list */ "Short List", "Display files as short list"}, - {FILE_LONGDISPLAY, - "LIST_LONG", - ICON_LONGDISPLAY, + {FILE_HORIZONTALDISPLAY, + "LIST_HORIZONTAL", + ICON_LONGDISPLAY, /* Name of deprecated long list */ "Long List", "Display files as a detailed list"}, {FILE_IMGDISPLAY, "THUMBNAIL", ICON_IMGDISPLAY, "Thumbnails", "Display files as thumbnails"}, {0, NULL, 0, NULL, NULL}, }; + static const EnumPropertyItem file_action_types[] = { + {FILE_OPENFILE, + "OPENFILE", + 0, + "Open", + "Use the file browser for opening files or a directory"}, + {FILE_SAVE, "SAVE", 0, "Save", "Use the file browser for saving a file"}, + }; if (flag & WM_FILESEL_FILEPATH) { RNA_def_string_file_path(ot->srna, "filepath", NULL, FILE_MAX, "File Path", "Path to file"); @@ -99,6 +107,15 @@ void WM_operator_properties_filesel(wmOperatorType *ot, RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } + if ((flag & WM_FILESEL_SHOW_PROPS) == 0) { + prop = RNA_def_boolean(ot->srna, + "hide_props_region", + true, + "Hide Operator Properties", + "Collapse the region displaying the operator settings"); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + } + if (action == FILE_SAVE) { /* note, this is only used to check if we should highlight the filename area red when the * filepath is an existing file. */ @@ -186,6 +203,9 @@ void WM_operator_properties_filesel(wmOperatorType *ot, prop = RNA_def_enum( ot->srna, "sort_method", rna_enum_file_sort_items, sort, "File sorting mode", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + + prop = RNA_def_enum(ot->srna, "action_type", file_action_types, action, "Action Type", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } static void wm_operator_properties_select_action_ex(wmOperatorType *ot, diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 29ecf798b3c..9657347a1c4 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -368,7 +368,7 @@ static const char *wm_context_member_from_ptr(bContext *C, const PointerRNA *ptr continue; } - if (ptr->id.data == ctx_item_ptr.id.data) { + if (ptr->owner_id == ctx_item_ptr.owner_id) { if ((ptr->data == ctx_item_ptr.data) && (ptr->type == ctx_item_ptr.type)) { /* found! */ member_found = identifier; @@ -402,13 +402,13 @@ static const char *wm_context_member_from_ptr(bContext *C, const PointerRNA *ptr { const char *member_id = NULL; - if (ptr->id.data) { + if (ptr->owner_id) { # define CTX_TEST_PTR_ID(C, member, idptr) \ { \ const char *ctx_member = member; \ PointerRNA ctx_item_ptr = CTX_data_pointer_get(C, ctx_member); \ - if (ctx_item_ptr.id.data == idptr) { \ + if (ctx_item_ptr.owner_id == idptr) { \ member_id = ctx_member; \ break; \ } \ @@ -420,7 +420,7 @@ static const char *wm_context_member_from_ptr(bContext *C, const PointerRNA *ptr const char *ctx_member = member; \ const char *ctx_member_full = member_full; \ PointerRNA ctx_item_ptr = CTX_data_pointer_get(C, ctx_member); \ - if (ctx_item_ptr.id.data && cast(ctx_item_ptr.id.data) == idptr) { \ + if (ctx_item_ptr.owner_id && (ID *)cast(ctx_item_ptr.owner_id) == idptr) { \ member_id = ctx_member_full; \ break; \ } \ @@ -447,19 +447,19 @@ static const char *wm_context_member_from_ptr(bContext *C, const PointerRNA *ptr } \ (void)0 - switch (GS(((ID *)ptr->id.data)->name)) { + switch (GS(ptr->owner_id->name)) { case ID_SCE: { - CTX_TEST_PTR_ID(C, "scene", ptr->id.data); + CTX_TEST_PTR_ID(C, "scene", ptr->owner_id); break; } case ID_OB: { - CTX_TEST_PTR_ID(C, "object", ptr->id.data); + CTX_TEST_PTR_ID(C, "object", ptr->owner_id); break; } /* from rna_Main_objects_new */ case OB_DATA_SUPPORT_ID_CASE: { # define ID_CAST_OBDATA(id_pt) (((Object *)(id_pt))->data) - CTX_TEST_PTR_ID_CAST(C, "object", "object.data", ID_CAST_OBDATA, ptr->id.data); + CTX_TEST_PTR_ID_CAST(C, "object", "object.data", ID_CAST_OBDATA, ptr->owner_id); break; # undef ID_CAST_OBDATA } @@ -467,18 +467,18 @@ static const char *wm_context_member_from_ptr(bContext *C, const PointerRNA *ptr # define ID_CAST_OBMATACT(id_pt) \ (give_current_material(((Object *)id_pt), ((Object *)id_pt)->actcol)) CTX_TEST_PTR_ID_CAST( - C, "object", "object.active_material", ID_CAST_OBMATACT, ptr->id.data); + C, "object", "object.active_material", ID_CAST_OBMATACT, ptr->owner_id); break; # undef ID_CAST_OBMATACT } case ID_WO: { # define ID_CAST_SCENEWORLD(id_pt) (((Scene *)(id_pt))->world) - CTX_TEST_PTR_ID_CAST(C, "scene", "scene.world", ID_CAST_SCENEWORLD, ptr->id.data); + CTX_TEST_PTR_ID_CAST(C, "scene", "scene.world", ID_CAST_SCENEWORLD, ptr->owner_id); break; # undef ID_CAST_SCENEWORLD } case ID_SCR: { - CTX_TEST_PTR_ID(C, "screen", ptr->id.data); + CTX_TEST_PTR_ID(C, "screen", ptr->owner_id); SpaceLink *space_data = CTX_wm_space_data(C); @@ -539,7 +539,7 @@ char *WM_prop_pystring_assign(bContext *C, PointerRNA *ptr, PropertyRNA *prop, i if (lhs == NULL) { /* fallback to bpy.data.foo[id] if we dont find in the context */ - lhs = RNA_path_full_property_py(ptr, prop, index); + lhs = RNA_path_full_property_py(CTX_data_main(C), ptr, prop, index); } if (!lhs) { @@ -850,7 +850,7 @@ static uiBlock *wm_enum_search_menu(bContext *C, ARegion *ar, void *arg) NULL); /* Move it downwards, mouse over button. */ - UI_block_bounds_set_popup(block, 6, (const int[2]){0, -UI_UNIT_Y}); + UI_block_bounds_set_popup(block, 0.3f * U.widget_unit, (const int[2]){0, -UI_UNIT_Y}); UI_but_focus_on_enter_event(win, but); @@ -1111,7 +1111,7 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op) /* if register is not enabled, the operator gets freed on OPERATOR_FINISHED * ui_apply_but_funcs_after calls ED_undo_operator_repeate_cb and crashes */ - assert(op->type->flag & OPTYPE_REGISTER); + BLI_assert(op->type->flag & OPTYPE_REGISTER); UI_block_func_handle_set(block, wm_block_redo_cb, arg_op); layout = UI_block_layout( @@ -1126,18 +1126,15 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op) if (op->type->flag & OPTYPE_MACRO) { for (op = op->macro.first; op; op = op->next) { uiTemplateOperatorPropertyButs( - C, layout, op, UI_BUT_LABEL_ALIGN_SPLIT_COLUMN, UI_TEMPLATE_OP_PROPS_SHOW_TITLE); - if (op->next) { - uiItemS(layout); - } + C, layout, op, UI_BUT_LABEL_ALIGN_NONE, UI_TEMPLATE_OP_PROPS_SHOW_TITLE); } } else { uiTemplateOperatorPropertyButs( - C, layout, op, UI_BUT_LABEL_ALIGN_SPLIT_COLUMN, UI_TEMPLATE_OP_PROPS_SHOW_TITLE); + C, layout, op, UI_BUT_LABEL_ALIGN_NONE, UI_TEMPLATE_OP_PROPS_SHOW_TITLE); } - UI_block_bounds_set_popup(block, 4, NULL); + UI_block_bounds_set_popup(block, 6 * U.dpi_fac, NULL); return block; } @@ -1217,7 +1214,8 @@ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *ar, void *userData) } /* center around the mouse */ - UI_block_bounds_set_popup(block, 4, (const int[2]){data->width / -2, data->height / 2}); + UI_block_bounds_set_popup( + block, 6 * U.dpi_fac, (const int[2]){data->width / -2, data->height / 2}); UI_block_active_only_flagged_buttons(C, ar, block); @@ -1245,7 +1243,7 @@ static uiBlock *wm_operator_ui_create(bContext *C, ARegion *ar, void *userData) UI_block_func_set(block, NULL, NULL, NULL); - UI_block_bounds_set_popup(block, 4, NULL); + UI_block_bounds_set_popup(block, 6 * U.dpi_fac, NULL); UI_block_active_only_flagged_buttons(C, ar, block); @@ -1516,7 +1514,7 @@ static uiBlock *wm_block_search_menu(bContext *C, ARegion *ar, void *userdata) NULL); /* Move it downwards, mouse over button. */ - UI_block_bounds_set_popup(block, 6, (const int[2]){0, -UI_UNIT_Y}); + UI_block_bounds_set_popup(block, 0.3f * U.widget_unit, (const int[2]){0, -UI_UNIT_Y}); return block; } @@ -3011,7 +3009,7 @@ static void WM_OT_redraw_timer(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Reporet Memory Statistics +/** \name Report Memory Statistics * * Use for testing/debugging. * \{ */ diff --git a/source/blender/windowmanager/intern/wm_splash_screen.c b/source/blender/windowmanager/intern/wm_splash_screen.c index 8629997030f..d3f7661a008 100644 --- a/source/blender/windowmanager/intern/wm_splash_screen.c +++ b/source/blender/windowmanager/intern/wm_splash_screen.c @@ -113,31 +113,37 @@ static void wm_block_splash_add_label(uiBlock *block, const char *label, int x, static void wm_block_splash_add_labels(uiBlock *block, int x, int y) { /* Version number. */ - const char *version_suffix = NULL; + const char *version_cycle = NULL; bool show_build_info = true; if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "alpha")) { - version_suffix = " Alpha"; + version_cycle = " Alpha"; } else if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "beta")) { - version_suffix = " Beta"; + version_cycle = " Beta"; } else if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "rc")) { - version_suffix = " Release Candidate"; + version_cycle = " Release Candidate"; show_build_info = false; } else if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "release")) { - version_suffix = STRINGIFY(BLENDER_VERSION_CHAR); + version_cycle = STRINGIFY(BLENDER_VERSION_CHAR); show_build_info = false; } + const char *version_cycle_number = ""; + if (strlen(STRINGIFY(BLENDER_VERSION_CYCLE_NUMBER))) { + version_cycle_number = " " STRINGIFY(BLENDER_VERSION_CYCLE_NUMBER); + } + char version_buf[256] = "\0"; BLI_snprintf(version_buf, sizeof(version_buf), - "v %d.%d%s", + "v %d.%d%s%s", BLENDER_VERSION / 100, BLENDER_VERSION % 100, - version_suffix); + version_cycle, + version_cycle_number); wm_block_splash_add_label(block, version_buf, x, &y); diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index d17b8817691..91173804b18 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -482,8 +482,8 @@ void wm_window_title(wmWindowManager *wm, wmWindow *win) } /* Informs GHOST of unsaved changes, to set window modified visual indicator (macOS) - * and to give hint of unsaved changes for a user warning mechanism in case of OS - * application terminate request (e.g. OS Shortcut Alt+F4, Cmd+Q, (...), or session end). */ + * and to give hint of unsaved changes for a user warning mechanism in case of OS application + * terminate request (e.g. OS Shortcut Alt+F4, Command+Q, (...), or session end). */ GHOST_SetWindowModifiedState(win->ghostwin, (GHOST_TUns8)!wm->file_saved); } } @@ -658,7 +658,7 @@ void wm_window_ghostwindows_ensure(wmWindowManager *wm) BLI_assert(G.background == false); - /* no commandline prefsize? then we set this. + /* No command-line prefsize? then we set this. * Note that these values will be used only * when there is no startup.blend yet. */ @@ -807,6 +807,7 @@ wmWindow *WM_window_open_temp(bContext *C, int x, int y, int sizex, int sizey, i ScrArea *sa; Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); + eSpace_Type space_type = SPACE_EMPTY; const char *title; /* convert to native OS window coordinates */ @@ -888,14 +889,24 @@ wmWindow *WM_window_open_temp(bContext *C, int x, int y, int sizex, int sizey, i CTX_wm_area_set(C, sa); if (type == WM_WINDOW_RENDER) { - ED_area_newspace(C, sa, SPACE_IMAGE, false); + space_type = SPACE_IMAGE; } else if (type == WM_WINDOW_DRIVERS) { - ED_area_newspace(C, sa, SPACE_GRAPH, false); + space_type = SPACE_GRAPH; + } + else if (type == WM_WINDOW_USERPREFS) { + space_type = SPACE_USERPREF; + } + else if (type == WM_WINDOW_FILESEL) { + space_type = SPACE_FILE; + } + else if (type == WM_WINDOW_INFO) { + space_type = SPACE_INFO; } else { - ED_area_newspace(C, sa, SPACE_USERPREF, false); + BLI_assert(false); } + ED_area_newspace(C, sa, space_type, false); ED_screen_change(C, screen); ED_screen_refresh(CTX_wm_manager(C), win); /* test scale */ @@ -917,6 +928,9 @@ wmWindow *WM_window_open_temp(bContext *C, int x, int y, int sizex, int sizey, i else if (sa->spacetype == SPACE_GRAPH) { title = IFACE_("Blender Drivers Editor"); } + else if (sa->spacetype == SPACE_INFO) { + title = IFACE_("Blender Info Log"); + } else { title = "Blender"; } diff --git a/source/blender/windowmanager/message_bus/intern/wm_message_bus_rna.c b/source/blender/windowmanager/message_bus/intern/wm_message_bus_rna.c index 73758e2d98f..0c2ce9783ec 100644 --- a/source/blender/windowmanager/message_bus/intern/wm_message_bus_rna.c +++ b/source/blender/windowmanager/message_bus/intern/wm_message_bus_rna.c @@ -50,7 +50,7 @@ static uint wm_msg_rna_gset_hash(const void *key_p) // printf("%s\n", RNA_struct_identifier(params->ptr.type)); uint k = void_hash_uint(params->ptr.type); k ^= void_hash_uint(params->ptr.data); - k ^= void_hash_uint(params->ptr.id.data); + k ^= void_hash_uint(params->ptr.owner_id); k ^= void_hash_uint(params->prop); return k; } @@ -59,7 +59,7 @@ static bool wm_msg_rna_gset_cmp(const void *key_a_p, const void *key_b_p) const wmMsgParams_RNA *params_a = &((const wmMsgSubscribeKey_RNA *)key_a_p)->msg.params; const wmMsgParams_RNA *params_b = &((const wmMsgSubscribeKey_RNA *)key_b_p)->msg.params; return !((params_a->ptr.type == params_b->ptr.type) && - (params_a->ptr.id.data == params_b->ptr.id.data) && + (params_a->ptr.owner_id == params_b->ptr.owner_id) && (params_a->ptr.data == params_b->ptr.data) && (params_a->prop == params_b->prop)); } static void wm_msg_rna_gset_key_free(void *key_p) @@ -100,7 +100,7 @@ static void wm_msg_rna_update_by_id(struct wmMsgBus *mbus, ID *id_src, ID *id_ds while (BLI_gsetIterator_done(&gs_iter) == false) { wmMsgSubscribeKey_RNA *key = BLI_gsetIterator_getKey(&gs_iter); BLI_gsetIterator_step(&gs_iter); - if (key->msg.params.ptr.id.data == id_src) { + if (key->msg.params.ptr.owner_id == id_src) { /* GSet always needs updating since the key changes. */ BLI_gset_remove(gs, key, NULL); @@ -123,10 +123,10 @@ static void wm_msg_rna_update_by_id(struct wmMsgBus *mbus, ID *id_src, ID *id_ds if (BLI_listbase_is_empty(&key->head.values)) { /* Remove, no reason to keep. */ } - else if (key->msg.params.ptr.data == key->msg.params.ptr.id.data) { + else if (key->msg.params.ptr.data == key->msg.params.ptr.owner_id) { /* Simple, just update the ID. */ key->msg.params.ptr.data = id_dst; - key->msg.params.ptr.id.data = id_dst; + key->msg.params.ptr.owner_id = id_dst; remove = false; } else { @@ -177,7 +177,7 @@ static void wm_msg_rna_remove_by_id(struct wmMsgBus *mbus, const ID *id) while (BLI_gsetIterator_done(&gs_iter) == false) { wmMsgSubscribeKey_RNA *key = BLI_gsetIterator_getKey(&gs_iter); BLI_gsetIterator_step(&gs_iter); - if (key->msg.params.ptr.id.data == id) { + if (key->msg.params.ptr.owner_id == id) { /* Clear here so we can decrement 'messages_tag_count'. */ for (wmMsgSubscribeValueLink *msg_lnk = key->head.values.first, *msg_lnk_next; msg_lnk; msg_lnk = msg_lnk_next) { @@ -226,7 +226,7 @@ void WM_msg_publish_rna_params(struct wmMsgBus *mbus, const wmMsgParams_RNA *msg CLOG_INFO(WM_LOG_MSGBUS_PUB, 2, "rna(id='%s', %s.%s)", - msg_key_params->ptr.id.data ? ((ID *)msg_key_params->ptr.id.data)->name : none, + msg_key_params->ptr.owner_id ? ((ID *)msg_key_params->ptr.owner_id)->name : none, msg_key_params->ptr.type ? RNA_struct_identifier(msg_key_params->ptr.type) : none, msg_key_params->prop ? RNA_property_identifier((PropertyRNA *)msg_key_params->prop) : none); @@ -237,7 +237,7 @@ void WM_msg_publish_rna_params(struct wmMsgBus *mbus, const wmMsgParams_RNA *msg /* Support anonymous subscribers, this may be some extra overhead * but we want to be able to be more ambiguous. */ - if (msg_key_params->ptr.id.data || msg_key_params->ptr.data) { + if (msg_key_params->ptr.owner_id || msg_key_params->ptr.data) { wmMsgParams_RNA msg_key_params_anon = *msg_key_params; /* We might want to enable this later? */ @@ -250,7 +250,7 @@ void WM_msg_publish_rna_params(struct wmMsgBus *mbus, const wmMsgParams_RNA *msg msg_key_params_anon.prop = msg_key_params->prop; } - msg_key_params_anon.ptr.id.data = NULL; + msg_key_params_anon.ptr.owner_id = NULL; msg_key_params_anon.ptr.data = NULL; if ((key = WM_msg_lookup_rna(mbus, &msg_key_params_anon))) { WM_msg_publish_with_key(mbus, &key->head); @@ -292,7 +292,7 @@ void WM_msg_subscribe_rna_params(struct wmMsgBus *mbus, CLOG_INFO(WM_LOG_MSGBUS_SUB, 3, "rna(id='%s', %s.%s, info='%s')", - msg_key_params->ptr.id.data ? ((ID *)msg_key_params->ptr.id.data)->name : none, + msg_key_params->ptr.owner_id ? ((ID *)msg_key_params->ptr.owner_id)->name : none, msg_key_params->ptr.type ? RNA_struct_identifier(msg_key_params->ptr.type) : none, msg_key_params->prop ? RNA_property_identifier((PropertyRNA *)msg_key_params->prop) : none, @@ -303,7 +303,7 @@ void WM_msg_subscribe_rna_params(struct wmMsgBus *mbus, if (msg_val_params->is_persistent) { if (msg_key->msg.params.data_path == NULL) { - if (msg_key->msg.params.ptr.data != msg_key->msg.params.ptr.id.data) { + if (msg_key->msg.params.ptr.data != msg_key->msg.params.ptr.owner_id) { /* We assume prop type can't change. */ msg_key->msg.params.data_path = RNA_path_from_ID_to_struct(&msg_key->msg.params.ptr); } @@ -339,14 +339,14 @@ void WM_msg_subscribe_ID(struct wmMsgBus *mbus, const wmMsgSubscribeValue *msg_val_params, const char *id_repr) { - wmMsgParams_RNA msg_key_params = {{{NULL}}}; + wmMsgParams_RNA msg_key_params = {NULL}; RNA_id_pointer_create(id, &msg_key_params.ptr); WM_msg_subscribe_rna_params(mbus, &msg_key_params, msg_val_params, id_repr); } void WM_msg_publish_ID(struct wmMsgBus *mbus, ID *id) { - wmMsgParams_RNA msg_key_params = {{{NULL}}}; + wmMsgParams_RNA msg_key_params = {NULL}; RNA_id_pointer_create(id, &msg_key_params.ptr); WM_msg_publish_rna_params(mbus, &msg_key_params); } diff --git a/source/blender/windowmanager/message_bus/wm_message_bus.h b/source/blender/windowmanager/message_bus/wm_message_bus.h index 4a8bce52992..4ee087593ac 100644 --- a/source/blender/windowmanager/message_bus/wm_message_bus.h +++ b/source/blender/windowmanager/message_bus/wm_message_bus.h @@ -23,7 +23,6 @@ #include <stdio.h> -struct GSet; struct ID; struct bContext; struct wmMsg; @@ -173,7 +172,7 @@ void WM_msg_subscribe_static(struct wmMsgBus *mbus, /* wm_message_bus_rna.c */ typedef struct wmMsgParams_RNA { - /** when #PointerRNA.data & id.data are NULL. match against all. */ + /** when #PointerRNA.data & owner_id are NULL. match against all. */ PointerRNA ptr; /** when NULL, match against any property. */ const PropertyRNA *prop; @@ -233,7 +232,7 @@ void WM_msg_publish_ID(struct wmMsgBus *mbus, struct ID *id); #define WM_msg_publish_rna_prop(mbus, id_, data_, type_, prop_) \ { \ - wmMsgParams_RNA msg_key_params_ = {{{0}}}; \ + wmMsgParams_RNA msg_key_params_ = {{0}}; \ _WM_MESSAGE_EXTERN_BEGIN; \ extern PropertyRNA rna_##type_##_##prop_; \ _WM_MESSAGE_EXTERN_END; \ @@ -244,7 +243,7 @@ void WM_msg_publish_ID(struct wmMsgBus *mbus, struct ID *id); ((void)0) #define WM_msg_subscribe_rna_prop(mbus, id_, data_, type_, prop_, value) \ { \ - wmMsgParams_RNA msg_key_params_ = {{{0}}}; \ + wmMsgParams_RNA msg_key_params_ = {{0}}; \ _WM_MESSAGE_EXTERN_BEGIN; \ extern PropertyRNA rna_##type_##_##prop_; \ _WM_MESSAGE_EXTERN_END; \ diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h index 90c580818c9..b0329f7415e 100644 --- a/source/blender/windowmanager/wm_window.h +++ b/source/blender/windowmanager/wm_window.h @@ -24,10 +24,6 @@ #ifndef __WM_WINDOW_H__ #define __WM_WINDOW_H__ -struct EnumPropertyItem; -struct PointerRNA; -struct PropertyRNA; -struct wmEvent; struct wmOperator; /* *************** internal api ************** */ |