Merge branch 'master' into sculpt-dev
This commit is contained in:
commit
f32d3f7b06
|
@ -200,6 +200,7 @@ set(SRC
|
|||
${MANTA_PP}/plugin/ptsplugins.cpp
|
||||
${MANTA_PP}/plugin/secondaryparticles.cpp
|
||||
${MANTA_PP}/plugin/surfaceturbulence.cpp
|
||||
${MANTA_PP}/plugin/viscosity.cpp
|
||||
${MANTA_PP}/plugin/vortexplugins.cpp
|
||||
${MANTA_PP}/plugin/waveletturbulence.cpp
|
||||
${MANTA_PP}/plugin/waves.cpp
|
||||
|
|
|
@ -1035,7 +1035,7 @@ template<class N, class T> struct RCFixedMatrix {
|
|||
typedef RCMatrix<int, Real> Matrix;
|
||||
typedef RCFixedMatrix<int, Real> FixedMatrix;
|
||||
|
||||
} // namespace Manta
|
||||
}
|
||||
|
||||
#undef parallel_for
|
||||
#undef parallel_end
|
||||
|
|
|
@ -397,7 +397,7 @@ struct UpdateSearchVec : public KernelBase {
|
|||
};
|
||||
|
||||
//*****************************************************************************
|
||||
// CG class
|
||||
// CG class
|
||||
|
||||
template<class APPLYMAT>
|
||||
GridCg<APPLYMAT>::GridCg(Grid<Real> &dst,
|
||||
|
@ -406,10 +406,8 @@ GridCg<APPLYMAT>::GridCg(Grid<Real> &dst,
|
|||
Grid<Real> &search,
|
||||
const FlagGrid &flags,
|
||||
Grid<Real> &tmp,
|
||||
Grid<Real> *pA0,
|
||||
Grid<Real> *pAi,
|
||||
Grid<Real> *pAj,
|
||||
Grid<Real> *pAk)
|
||||
std::vector<Grid<Real> *> matrixAVec,
|
||||
std::vector<Grid<Real> *> rhsVec)
|
||||
: GridCgInterface(),
|
||||
mInited(false),
|
||||
mIterations(0),
|
||||
|
@ -419,10 +417,8 @@ GridCg<APPLYMAT>::GridCg(Grid<Real> &dst,
|
|||
mSearch(search),
|
||||
mFlags(flags),
|
||||
mTmp(tmp),
|
||||
mpA0(pA0),
|
||||
mpAi(pAi),
|
||||
mpAj(pAj),
|
||||
mpAk(pAk),
|
||||
mMatrixA(matrixAVec),
|
||||
mVecRhs(rhsVec),
|
||||
mPcMethod(PC_None),
|
||||
mpPCA0(nullptr),
|
||||
mpPCAi(nullptr),
|
||||
|
@ -445,19 +441,37 @@ template<class APPLYMAT> void GridCg<APPLYMAT>::doInit()
|
|||
|
||||
if (mPcMethod == PC_ICP) {
|
||||
assertMsg(mDst.is3D(), "ICP only supports 3D grids so far");
|
||||
InitPreconditionIncompCholesky(
|
||||
mFlags, *mpPCA0, *mpPCAi, *mpPCAj, *mpPCAk, *mpA0, *mpAi, *mpAj, *mpAk);
|
||||
ApplyPreconditionIncompCholesky(
|
||||
mTmp, mResidual, mFlags, *mpPCA0, *mpPCAi, *mpPCAj, *mpPCAk, *mpA0, *mpAi, *mpAj, *mpAk);
|
||||
InitPreconditionIncompCholesky(mFlags,
|
||||
*mpPCA0,
|
||||
*mpPCAi,
|
||||
*mpPCAj,
|
||||
*mpPCAk,
|
||||
*mMatrixA[0],
|
||||
*mMatrixA[1],
|
||||
*mMatrixA[2],
|
||||
*mMatrixA[3]);
|
||||
ApplyPreconditionIncompCholesky(mTmp,
|
||||
mResidual,
|
||||
mFlags,
|
||||
*mpPCA0,
|
||||
*mpPCAi,
|
||||
*mpPCAj,
|
||||
*mpPCAk,
|
||||
*mMatrixA[0],
|
||||
*mMatrixA[1],
|
||||
*mMatrixA[2],
|
||||
*mMatrixA[3]);
|
||||
}
|
||||
else if (mPcMethod == PC_mICP) {
|
||||
assertMsg(mDst.is3D(), "mICP only supports 3D grids so far");
|
||||
InitPreconditionModifiedIncompCholesky2(mFlags, *mpPCA0, *mpA0, *mpAi, *mpAj, *mpAk);
|
||||
InitPreconditionModifiedIncompCholesky2(
|
||||
mFlags, *mpPCA0, *mMatrixA[0], *mMatrixA[1], *mMatrixA[2], *mMatrixA[3]);
|
||||
ApplyPreconditionModifiedIncompCholesky2(
|
||||
mTmp, mResidual, mFlags, *mpPCA0, *mpA0, *mpAi, *mpAj, *mpAk);
|
||||
mTmp, mResidual, mFlags, *mpPCA0, *mMatrixA[0], *mMatrixA[1], *mMatrixA[2], *mMatrixA[3]);
|
||||
}
|
||||
else if (mPcMethod == PC_MGP) {
|
||||
InitPreconditionMultigrid(mMG, *mpA0, *mpAi, *mpAj, *mpAk, mAccuracy);
|
||||
InitPreconditionMultigrid(
|
||||
mMG, *mMatrixA[0], *mMatrixA[1], *mMatrixA[2], *mMatrixA[3], mAccuracy);
|
||||
ApplyPreconditionMultigrid(mMG, mTmp, mResidual);
|
||||
}
|
||||
else {
|
||||
|
@ -465,7 +479,6 @@ template<class APPLYMAT> void GridCg<APPLYMAT>::doInit()
|
|||
}
|
||||
|
||||
mSearch.copyFrom(mTmp);
|
||||
|
||||
mSigma = GridDotProduct(mTmp, mResidual);
|
||||
}
|
||||
|
||||
|
@ -480,7 +493,7 @@ template<class APPLYMAT> bool GridCg<APPLYMAT>::iterate()
|
|||
// this could reinterpret the mpA pointers (not so clean right now)
|
||||
// tmp = applyMat(search)
|
||||
|
||||
APPLYMAT(mFlags, mTmp, mSearch, *mpA0, *mpAi, *mpAj, *mpAk);
|
||||
APPLYMAT(mFlags, mTmp, mSearch, mMatrixA, mVecRhs);
|
||||
|
||||
// alpha = sigma/dot(tmp, search)
|
||||
Real dp = GridDotProduct(mTmp, mSearch);
|
||||
|
@ -492,11 +505,20 @@ template<class APPLYMAT> bool GridCg<APPLYMAT>::iterate()
|
|||
gridScaledAdd<Real, Real>(mResidual, mTmp, -alpha); // residual += tmp * -alpha
|
||||
|
||||
if (mPcMethod == PC_ICP)
|
||||
ApplyPreconditionIncompCholesky(
|
||||
mTmp, mResidual, mFlags, *mpPCA0, *mpPCAi, *mpPCAj, *mpPCAk, *mpA0, *mpAi, *mpAj, *mpAk);
|
||||
ApplyPreconditionIncompCholesky(mTmp,
|
||||
mResidual,
|
||||
mFlags,
|
||||
*mpPCA0,
|
||||
*mpPCAi,
|
||||
*mpPCAj,
|
||||
*mpPCAk,
|
||||
*mMatrixA[0],
|
||||
*mMatrixA[1],
|
||||
*mMatrixA[2],
|
||||
*mMatrixA[3]);
|
||||
else if (mPcMethod == PC_mICP)
|
||||
ApplyPreconditionModifiedIncompCholesky2(
|
||||
mTmp, mResidual, mFlags, *mpPCA0, *mpA0, *mpAi, *mpAj, *mpAk);
|
||||
mTmp, mResidual, mFlags, *mpPCA0, *mMatrixA[0], *mMatrixA[1], *mMatrixA[2], *mMatrixA[3]);
|
||||
else if (mPcMethod == PC_MGP)
|
||||
ApplyPreconditionMultigrid(mMG, mTmp, mResidual);
|
||||
else
|
||||
|
@ -584,13 +606,15 @@ void GridCg<APPLYMAT>::setMGPreconditioner(PreconditionType method, GridMg *MG)
|
|||
assertMsg(method == PC_MGP, "GridCg<APPLYMAT>::setMGPreconditioner: Invalid method specified.");
|
||||
|
||||
mPcMethod = method;
|
||||
|
||||
mMG = MG;
|
||||
}
|
||||
|
||||
// explicit instantiation
|
||||
template class GridCg<ApplyMatrix>;
|
||||
template class GridCg<ApplyMatrix2D>;
|
||||
template class GridCg<ApplyMatrixViscosityU>;
|
||||
template class GridCg<ApplyMatrixViscosityV>;
|
||||
template class GridCg<ApplyMatrixViscosityW>;
|
||||
|
||||
//*****************************************************************************
|
||||
// diffusion for real and vec grids, e.g. for viscosity
|
||||
|
@ -638,10 +662,15 @@ void cgSolveDiffusion(const FlagGrid &flags,
|
|||
if (grid.getType() & GridBase::TypeReal) {
|
||||
Grid<Real> &u = ((Grid<Real> &)grid);
|
||||
rhs.copyFrom(u);
|
||||
if (flags.is3D())
|
||||
gcg = new GridCg<ApplyMatrix>(u, rhs, residual, search, flags, tmp, &A0, &Ai, &Aj, &Ak);
|
||||
else
|
||||
gcg = new GridCg<ApplyMatrix2D>(u, rhs, residual, search, flags, tmp, &A0, &Ai, &Aj, &Ak);
|
||||
vector<Grid<Real> *> matA{&A0, &Ai, &Aj};
|
||||
|
||||
if (flags.is3D()) {
|
||||
matA.push_back(&Ak);
|
||||
gcg = new GridCg<ApplyMatrix>(u, rhs, residual, search, flags, tmp, matA);
|
||||
}
|
||||
else {
|
||||
gcg = new GridCg<ApplyMatrix2D>(u, rhs, residual, search, flags, tmp, matA);
|
||||
}
|
||||
|
||||
gcg->setAccuracy(cgAccuracy);
|
||||
gcg->solve(maxIter);
|
||||
|
@ -653,12 +682,17 @@ void cgSolveDiffusion(const FlagGrid &flags,
|
|||
else if ((grid.getType() & GridBase::TypeVec3) || (grid.getType() & GridBase::TypeMAC)) {
|
||||
Grid<Vec3> &vec = ((Grid<Vec3> &)grid);
|
||||
Grid<Real> u(parent);
|
||||
vector<Grid<Real> *> matA{&A0, &Ai, &Aj};
|
||||
|
||||
// core solve is same as for a regular real grid
|
||||
if (flags.is3D())
|
||||
gcg = new GridCg<ApplyMatrix>(u, rhs, residual, search, flags, tmp, &A0, &Ai, &Aj, &Ak);
|
||||
else
|
||||
gcg = new GridCg<ApplyMatrix2D>(u, rhs, residual, search, flags, tmp, &A0, &Ai, &Aj, &Ak);
|
||||
if (flags.is3D()) {
|
||||
matA.push_back(&Ak);
|
||||
gcg = new GridCg<ApplyMatrix>(u, rhs, residual, search, flags, tmp, matA);
|
||||
}
|
||||
else {
|
||||
gcg = new GridCg<ApplyMatrix2D>(u, rhs, residual, search, flags, tmp, matA);
|
||||
}
|
||||
|
||||
gcg->setAccuracy(cgAccuracy);
|
||||
|
||||
// diffuse every component separately
|
||||
|
|
|
@ -78,13 +78,9 @@ template<class APPLYMAT> class GridCg : public GridCgInterface {
|
|||
Grid<Real> &search,
|
||||
const FlagGrid &flags,
|
||||
Grid<Real> &tmp,
|
||||
Grid<Real> *A0,
|
||||
Grid<Real> *pAi,
|
||||
Grid<Real> *pAj,
|
||||
Grid<Real> *pAk);
|
||||
~GridCg()
|
||||
{
|
||||
}
|
||||
std::vector<Grid<Real> *> matrixAVec,
|
||||
std::vector<Grid<Real> *> rhsVec = {});
|
||||
~GridCg(){};
|
||||
|
||||
void doInit();
|
||||
bool iterate();
|
||||
|
@ -133,7 +129,10 @@ template<class APPLYMAT> class GridCg : public GridCgInterface {
|
|||
const FlagGrid &mFlags;
|
||||
Grid<Real> &mTmp;
|
||||
|
||||
Grid<Real> *mpA0, *mpAi, *mpAj, *mpAk;
|
||||
//! shape of A matrix defined here (e.g. diagonal, positive neighbor cells, etc)
|
||||
std::vector<Grid<Real> *> mMatrixA;
|
||||
//! shape of rhs vector defined here (e.g. 1 rhs for regular fluids solve, 3 rhs for viscosity)
|
||||
std::vector<Grid<Real> *> mVecRhs;
|
||||
|
||||
PreconditionType mPcMethod;
|
||||
//! preconditioning grids
|
||||
|
@ -154,11 +153,9 @@ struct ApplyMatrix : public KernelBase {
|
|||
ApplyMatrix(const FlagGrid &flags,
|
||||
Grid<Real> &dst,
|
||||
const Grid<Real> &src,
|
||||
Grid<Real> &A0,
|
||||
Grid<Real> &Ai,
|
||||
Grid<Real> &Aj,
|
||||
Grid<Real> &Ak)
|
||||
: KernelBase(&flags, 0), flags(flags), dst(dst), src(src), A0(A0), Ai(Ai), Aj(Aj), Ak(Ak)
|
||||
const std::vector<Grid<Real> *> matrixA,
|
||||
const std::vector<Grid<Real> *> vecRhs)
|
||||
: KernelBase(&flags, 0), flags(flags), dst(dst), src(src), matrixA(matrixA), vecRhs(vecRhs)
|
||||
{
|
||||
runMessage();
|
||||
run();
|
||||
|
@ -167,11 +164,18 @@ struct ApplyMatrix : public KernelBase {
|
|||
const FlagGrid &flags,
|
||||
Grid<Real> &dst,
|
||||
const Grid<Real> &src,
|
||||
Grid<Real> &A0,
|
||||
Grid<Real> &Ai,
|
||||
Grid<Real> &Aj,
|
||||
Grid<Real> &Ak) const
|
||||
const std::vector<Grid<Real> *> matrixA,
|
||||
const std::vector<Grid<Real> *> vecRhs) const
|
||||
{
|
||||
unusedParameter(vecRhs); // Not needed in this matrix application
|
||||
|
||||
if (matrixA.size() != 4)
|
||||
errMsg("ConjugatedGrad: Invalid A matrix in apply matrix step");
|
||||
Grid<Real> &A0 = *matrixA[0];
|
||||
Grid<Real> &Ai = *matrixA[1];
|
||||
Grid<Real> &Aj = *matrixA[2];
|
||||
Grid<Real> &Ak = *matrixA[3];
|
||||
|
||||
if (!flags.isFluid(idx)) {
|
||||
dst[idx] = src[idx];
|
||||
return;
|
||||
|
@ -196,26 +200,16 @@ struct ApplyMatrix : public KernelBase {
|
|||
return src;
|
||||
}
|
||||
typedef Grid<Real> type2;
|
||||
inline Grid<Real> &getArg3()
|
||||
inline const std::vector<Grid<Real> *> &getArg3()
|
||||
{
|
||||
return A0;
|
||||
return matrixA;
|
||||
}
|
||||
typedef Grid<Real> type3;
|
||||
inline Grid<Real> &getArg4()
|
||||
typedef std::vector<Grid<Real> *> type3;
|
||||
inline const std::vector<Grid<Real> *> &getArg4()
|
||||
{
|
||||
return Ai;
|
||||
return vecRhs;
|
||||
}
|
||||
typedef Grid<Real> type4;
|
||||
inline Grid<Real> &getArg5()
|
||||
{
|
||||
return Aj;
|
||||
}
|
||||
typedef Grid<Real> type5;
|
||||
inline Grid<Real> &getArg6()
|
||||
{
|
||||
return Ak;
|
||||
}
|
||||
typedef Grid<Real> type6;
|
||||
typedef std::vector<Grid<Real> *> type4;
|
||||
void runMessage()
|
||||
{
|
||||
debMsg("Executing kernel ApplyMatrix ", 3);
|
||||
|
@ -226,7 +220,7 @@ struct ApplyMatrix : public KernelBase {
|
|||
void operator()(const tbb::blocked_range<IndexInt> &__r) const
|
||||
{
|
||||
for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++)
|
||||
op(idx, flags, dst, src, A0, Ai, Aj, Ak);
|
||||
op(idx, flags, dst, src, matrixA, vecRhs);
|
||||
}
|
||||
void run()
|
||||
{
|
||||
|
@ -235,10 +229,8 @@ struct ApplyMatrix : public KernelBase {
|
|||
const FlagGrid &flags;
|
||||
Grid<Real> &dst;
|
||||
const Grid<Real> &src;
|
||||
Grid<Real> &A0;
|
||||
Grid<Real> &Ai;
|
||||
Grid<Real> &Aj;
|
||||
Grid<Real> &Ak;
|
||||
const std::vector<Grid<Real> *> matrixA;
|
||||
const std::vector<Grid<Real> *> vecRhs;
|
||||
};
|
||||
|
||||
//! Kernel: Apply symmetric stored Matrix. 2D version
|
||||
|
@ -247,11 +239,9 @@ struct ApplyMatrix2D : public KernelBase {
|
|||
ApplyMatrix2D(const FlagGrid &flags,
|
||||
Grid<Real> &dst,
|
||||
const Grid<Real> &src,
|
||||
Grid<Real> &A0,
|
||||
Grid<Real> &Ai,
|
||||
Grid<Real> &Aj,
|
||||
Grid<Real> &Ak)
|
||||
: KernelBase(&flags, 0), flags(flags), dst(dst), src(src), A0(A0), Ai(Ai), Aj(Aj), Ak(Ak)
|
||||
const std::vector<Grid<Real> *> matrixA,
|
||||
const std::vector<Grid<Real> *> vecRhs)
|
||||
: KernelBase(&flags, 0), flags(flags), dst(dst), src(src), matrixA(matrixA), vecRhs(vecRhs)
|
||||
{
|
||||
runMessage();
|
||||
run();
|
||||
|
@ -260,12 +250,16 @@ struct ApplyMatrix2D : public KernelBase {
|
|||
const FlagGrid &flags,
|
||||
Grid<Real> &dst,
|
||||
const Grid<Real> &src,
|
||||
Grid<Real> &A0,
|
||||
Grid<Real> &Ai,
|
||||
Grid<Real> &Aj,
|
||||
Grid<Real> &Ak) const
|
||||
const std::vector<Grid<Real> *> matrixA,
|
||||
const std::vector<Grid<Real> *> vecRhs) const
|
||||
{
|
||||
unusedParameter(Ak); // only there for parameter compatibility with ApplyMatrix
|
||||
unusedParameter(vecRhs); // Not needed in this matrix application
|
||||
|
||||
if (matrixA.size() != 3)
|
||||
errMsg("ConjugatedGrad: Invalid A matrix in apply matrix step");
|
||||
Grid<Real> &A0 = *matrixA[0];
|
||||
Grid<Real> &Ai = *matrixA[1];
|
||||
Grid<Real> &Aj = *matrixA[2];
|
||||
|
||||
if (!flags.isFluid(idx)) {
|
||||
dst[idx] = src[idx];
|
||||
|
@ -290,26 +284,16 @@ struct ApplyMatrix2D : public KernelBase {
|
|||
return src;
|
||||
}
|
||||
typedef Grid<Real> type2;
|
||||
inline Grid<Real> &getArg3()
|
||||
inline const std::vector<Grid<Real> *> &getArg3()
|
||||
{
|
||||
return A0;
|
||||
return matrixA;
|
||||
}
|
||||
typedef Grid<Real> type3;
|
||||
inline Grid<Real> &getArg4()
|
||||
typedef std::vector<Grid<Real> *> type3;
|
||||
inline const std::vector<Grid<Real> *> &getArg4()
|
||||
{
|
||||
return Ai;
|
||||
return vecRhs;
|
||||
}
|
||||
typedef Grid<Real> type4;
|
||||
inline Grid<Real> &getArg5()
|
||||
{
|
||||
return Aj;
|
||||
}
|
||||
typedef Grid<Real> type5;
|
||||
inline Grid<Real> &getArg6()
|
||||
{
|
||||
return Ak;
|
||||
}
|
||||
typedef Grid<Real> type6;
|
||||
typedef std::vector<Grid<Real> *> type4;
|
||||
void runMessage()
|
||||
{
|
||||
debMsg("Executing kernel ApplyMatrix2D ", 3);
|
||||
|
@ -320,7 +304,7 @@ struct ApplyMatrix2D : public KernelBase {
|
|||
void operator()(const tbb::blocked_range<IndexInt> &__r) const
|
||||
{
|
||||
for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++)
|
||||
op(idx, flags, dst, src, A0, Ai, Aj, Ak);
|
||||
op(idx, flags, dst, src, matrixA, vecRhs);
|
||||
}
|
||||
void run()
|
||||
{
|
||||
|
@ -329,12 +313,358 @@ struct ApplyMatrix2D : public KernelBase {
|
|||
const FlagGrid &flags;
|
||||
Grid<Real> &dst;
|
||||
const Grid<Real> &src;
|
||||
Grid<Real> &A0;
|
||||
Grid<Real> &Ai;
|
||||
Grid<Real> &Aj;
|
||||
Grid<Real> &Ak;
|
||||
const std::vector<Grid<Real> *> matrixA;
|
||||
const std::vector<Grid<Real> *> vecRhs;
|
||||
};
|
||||
|
||||
struct ApplyMatrixViscosityU : public KernelBase {
|
||||
ApplyMatrixViscosityU(const FlagGrid &flags,
|
||||
Grid<Real> &dst,
|
||||
const Grid<Real> &src,
|
||||
const std::vector<Grid<Real> *> matrixA,
|
||||
const std::vector<Grid<Real> *> vecRhs)
|
||||
: KernelBase(&flags, 1), flags(flags), dst(dst), src(src), matrixA(matrixA), vecRhs(vecRhs)
|
||||
{
|
||||
runMessage();
|
||||
run();
|
||||
}
|
||||
inline void op(int i,
|
||||
int j,
|
||||
int k,
|
||||
const FlagGrid &flags,
|
||||
Grid<Real> &dst,
|
||||
const Grid<Real> &src,
|
||||
const std::vector<Grid<Real> *> matrixA,
|
||||
const std::vector<Grid<Real> *> vecRhs) const
|
||||
{
|
||||
if (matrixA.size() != 15)
|
||||
errMsg("ConjugatedGrad: Invalid A matrix in apply matrix step");
|
||||
Grid<Real> &A0 = *matrixA[0];
|
||||
Grid<Real> &Aplusi = *matrixA[1];
|
||||
Grid<Real> &Aplusj = *matrixA[2];
|
||||
Grid<Real> &Aplusk = *matrixA[3];
|
||||
Grid<Real> &Aminusi = *matrixA[4];
|
||||
Grid<Real> &Aminusj = *matrixA[5];
|
||||
Grid<Real> &Aminusk = *matrixA[6];
|
||||
|
||||
if (vecRhs.size() != 2)
|
||||
errMsg("ConjugatedGrad: Invalid rhs vector in apply matrix step");
|
||||
Grid<Real> &srcV = *vecRhs[0];
|
||||
Grid<Real> &srcW = *vecRhs[1];
|
||||
|
||||
dst(i, j, k) = src(i, j, k) * A0(i, j, k) + src(i + 1, j, k) * Aplusi(i, j, k) +
|
||||
src(i, j + 1, k) * Aplusj(i, j, k) + src(i, j, k + 1) * Aplusk(i, j, k) +
|
||||
src(i - 1, j, k) * Aminusi(i, j, k) + src(i, j - 1, k) * Aminusj(i, j, k) +
|
||||
src(i, j, k - 1) * Aminusk(i, j, k);
|
||||
|
||||
dst(i, j, k) += srcV(i, j + 1, k) * (*matrixA[7])(i, j, k) +
|
||||
srcV(i - 1, j + 1, k) * (*matrixA[8])(i, j, k) +
|
||||
srcV(i, j, k) * (*matrixA[9])(i, j, k) +
|
||||
srcV(i - 1, j, k) * (*matrixA[10])(i, j, k) +
|
||||
srcW(i, j, k + 1) * (*matrixA[11])(i, j, k) +
|
||||
srcW(i - 1, j, k + 1) * (*matrixA[12])(i, j, k) +
|
||||
srcW(i, j, k) * (*matrixA[13])(i, j, k) +
|
||||
srcW(i - 1, j, k) * (*matrixA[14])(i, j, k);
|
||||
}
|
||||
inline const FlagGrid &getArg0()
|
||||
{
|
||||
return flags;
|
||||
}
|
||||
typedef FlagGrid type0;
|
||||
inline Grid<Real> &getArg1()
|
||||
{
|
||||
return dst;
|
||||
}
|
||||
typedef Grid<Real> type1;
|
||||
inline const Grid<Real> &getArg2()
|
||||
{
|
||||
return src;
|
||||
}
|
||||
typedef Grid<Real> type2;
|
||||
inline const std::vector<Grid<Real> *> &getArg3()
|
||||
{
|
||||
return matrixA;
|
||||
}
|
||||
typedef std::vector<Grid<Real> *> type3;
|
||||
inline const std::vector<Grid<Real> *> &getArg4()
|
||||
{
|
||||
return vecRhs;
|
||||
}
|
||||
typedef std::vector<Grid<Real> *> type4;
|
||||
void runMessage()
|
||||
{
|
||||
debMsg("Executing kernel ApplyMatrixViscosityU ", 3);
|
||||
debMsg("Kernel range"
|
||||
<< " x " << maxX << " y " << maxY << " z " << minZ << " - " << maxZ << " ",
|
||||
4);
|
||||
};
|
||||
void operator()(const tbb::blocked_range<IndexInt> &__r) const
|
||||
{
|
||||
const int _maxX = maxX;
|
||||
const int _maxY = maxY;
|
||||
if (maxZ > 1) {
|
||||
for (int k = __r.begin(); k != (int)__r.end(); k++)
|
||||
for (int j = 1; j < _maxY; j++)
|
||||
for (int i = 1; i < _maxX; i++)
|
||||
op(i, j, k, flags, dst, src, matrixA, vecRhs);
|
||||
}
|
||||
else {
|
||||
const int k = 0;
|
||||
for (int j = __r.begin(); j != (int)__r.end(); j++)
|
||||
for (int i = 1; i < _maxX; i++)
|
||||
op(i, j, k, flags, dst, src, matrixA, vecRhs);
|
||||
}
|
||||
}
|
||||
void run()
|
||||
{
|
||||
if (maxZ > 1)
|
||||
tbb::parallel_for(tbb::blocked_range<IndexInt>(minZ, maxZ), *this);
|
||||
else
|
||||
tbb::parallel_for(tbb::blocked_range<IndexInt>(1, maxY), *this);
|
||||
}
|
||||
const FlagGrid &flags;
|
||||
Grid<Real> &dst;
|
||||
const Grid<Real> &src;
|
||||
const std::vector<Grid<Real> *> matrixA;
|
||||
const std::vector<Grid<Real> *> vecRhs;
|
||||
};
|
||||
|
||||
struct ApplyMatrixViscosityV : public KernelBase {
|
||||
ApplyMatrixViscosityV(const FlagGrid &flags,
|
||||
Grid<Real> &dst,
|
||||
const Grid<Real> &src,
|
||||
const std::vector<Grid<Real> *> matrixA,
|
||||
const std::vector<Grid<Real> *> vecRhs)
|
||||
: KernelBase(&flags, 1), flags(flags), dst(dst), src(src), matrixA(matrixA), vecRhs(vecRhs)
|
||||
{
|
||||
runMessage();
|
||||
run();
|
||||
}
|
||||
inline void op(int i,
|
||||
int j,
|
||||
int k,
|
||||
const FlagGrid &flags,
|
||||
Grid<Real> &dst,
|
||||
const Grid<Real> &src,
|
||||
const std::vector<Grid<Real> *> matrixA,
|
||||
const std::vector<Grid<Real> *> vecRhs) const
|
||||
{
|
||||
if (matrixA.size() != 15)
|
||||
errMsg("ConjugatedGrad: Invalid A matrix in apply matrix step");
|
||||
Grid<Real> &A0 = *matrixA[0];
|
||||
Grid<Real> &Aplusi = *matrixA[1];
|
||||
Grid<Real> &Aplusj = *matrixA[2];
|
||||
Grid<Real> &Aplusk = *matrixA[3];
|
||||
Grid<Real> &Aminusi = *matrixA[4];
|
||||
Grid<Real> &Aminusj = *matrixA[5];
|
||||
Grid<Real> &Aminusk = *matrixA[6];
|
||||
|
||||
if (vecRhs.size() != 2)
|
||||
errMsg("ConjugatedGrad: Invalid rhs vector in apply matrix step");
|
||||
Grid<Real> &srcU = *vecRhs[0];
|
||||
Grid<Real> &srcW = *vecRhs[1];
|
||||
|
||||
dst(i, j, k) = src(i, j, k) * A0(i, j, k) + src(i + 1, j, k) * Aplusi(i, j, k) +
|
||||
src(i, j + 1, k) * Aplusj(i, j, k) + src(i, j, k + 1) * Aplusk(i, j, k) +
|
||||
src(i - 1, j, k) * Aminusi(i, j, k) + src(i, j - 1, k) * Aminusj(i, j, k) +
|
||||
src(i, j, k - 1) * Aminusk(i, j, k);
|
||||
|
||||
dst(i, j, k) += srcU(i + 1, j, k) * (*matrixA[7])(i, j, k) +
|
||||
srcU(i + 1, j - 1, k) * (*matrixA[8])(i, j, k) +
|
||||
srcU(i, j, k) * (*matrixA[9])(i, j, k) +
|
||||
srcU(i, j - 1, k) * (*matrixA[10])(i, j, k) +
|
||||
srcW(i, j, k + 1) * (*matrixA[11])(i, j, k) +
|
||||
srcW(i, j - 1, k + 1) * (*matrixA[12])(i, j, k) +
|
||||
srcW(i, j, k) * (*matrixA[13])(i, j, k) +
|
||||
srcW(i, j - 1, k) * (*matrixA[14])(i, j, k);
|
||||
}
|
||||
inline const FlagGrid &getArg0()
|
||||
{
|
||||
return flags;
|
||||
}
|
||||
typedef FlagGrid type0;
|
||||
inline Grid<Real> &getArg1()
|
||||
{
|
||||
return dst;
|
||||
}
|
||||
typedef Grid<Real> type1;
|
||||
inline const Grid<Real> &getArg2()
|
||||
{
|
||||
return src;
|
||||
}
|
||||
typedef Grid<Real> type2;
|
||||
inline const std::vector<Grid<Real> *> &getArg3()
|
||||
{
|
||||
return matrixA;
|
||||
}
|
||||
typedef std::vector<Grid<Real> *> type3;
|
||||
inline const std::vector<Grid<Real> *> &getArg4()
|
||||
{
|
||||
return vecRhs;
|
||||
}
|
||||
typedef std::vector<Grid<Real> *> type4;
|
||||
void runMessage()
|
||||
{
|
||||
debMsg("Executing kernel ApplyMatrixViscosityV ", 3);
|
||||
debMsg("Kernel range"
|
||||
<< " x " << maxX << " y " << maxY << " z " << minZ << " - " << maxZ << " ",
|
||||
4);
|
||||
};
|
||||
void operator()(const tbb::blocked_range<IndexInt> &__r) const
|
||||
{
|
||||
const int _maxX = maxX;
|
||||
const int _maxY = maxY;
|
||||
if (maxZ > 1) {
|
||||
for (int k = __r.begin(); k != (int)__r.end(); k++)
|
||||
for (int j = 1; j < _maxY; j++)
|
||||
for (int i = 1; i < _maxX; i++)
|
||||
op(i, j, k, flags, dst, src, matrixA, vecRhs);
|
||||
}
|
||||
else {
|
||||
const int k = 0;
|
||||
for (int j = __r.begin(); j != (int)__r.end(); j++)
|
||||
for (int i = 1; i < _maxX; i++)
|
||||
op(i, j, k, flags, dst, src, matrixA, vecRhs);
|
||||
}
|
||||
}
|
||||
void run()
|
||||
{
|
||||
if (maxZ > 1)
|
||||
tbb::parallel_for(tbb::blocked_range<IndexInt>(minZ, maxZ), *this);
|
||||
else
|
||||
tbb::parallel_for(tbb::blocked_range<IndexInt>(1, maxY), *this);
|
||||
}
|
||||
const FlagGrid &flags;
|
||||
Grid<Real> &dst;
|
||||
const Grid<Real> &src;
|
||||
const std::vector<Grid<Real> *> matrixA;
|
||||
const std::vector<Grid<Real> *> vecRhs;
|
||||
};
|
||||
|
||||
struct ApplyMatrixViscosityW : public KernelBase {
|
||||
ApplyMatrixViscosityW(const FlagGrid &flags,
|
||||
Grid<Real> &dst,
|
||||
const Grid<Real> &src,
|
||||
const std::vector<Grid<Real> *> matrixA,
|
||||
const std::vector<Grid<Real> *> vecRhs)
|
||||
: KernelBase(&flags, 1), flags(flags), dst(dst), src(src), matrixA(matrixA), vecRhs(vecRhs)
|
||||
{
|
||||
runMessage();
|
||||
run();
|
||||
}
|
||||
inline void op(int i,
|
||||
int j,
|
||||
int k,
|
||||
const FlagGrid &flags,
|
||||
Grid<Real> &dst,
|
||||
const Grid<Real> &src,
|
||||
const std::vector<Grid<Real> *> matrixA,
|
||||
const std::vector<Grid<Real> *> vecRhs) const
|
||||
{
|
||||
if (matrixA.size() != 15)
|
||||
errMsg("ConjugatedGrad: Invalid A matrix in apply matrix step");
|
||||
Grid<Real> &A0 = *matrixA[0];
|
||||
Grid<Real> &Aplusi = *matrixA[1];
|
||||
Grid<Real> &Aplusj = *matrixA[2];
|
||||
Grid<Real> &Aplusk = *matrixA[3];
|
||||
Grid<Real> &Aminusi = *matrixA[4];
|
||||
Grid<Real> &Aminusj = *matrixA[5];
|
||||
Grid<Real> &Aminusk = *matrixA[6];
|
||||
|
||||
if (vecRhs.size() != 2)
|
||||
errMsg("ConjugatedGrad: Invalid rhs vector in apply matrix step");
|
||||
Grid<Real> &srcU = *vecRhs[0];
|
||||
Grid<Real> &srcV = *vecRhs[1];
|
||||
|
||||
dst(i, j, k) = src(i, j, k) * A0(i, j, k) + src(i + 1, j, k) * Aplusi(i, j, k) +
|
||||
src(i, j + 1, k) * Aplusj(i, j, k) + src(i, j, k + 1) * Aplusk(i, j, k) +
|
||||
src(i - 1, j, k) * Aminusi(i, j, k) + src(i, j - 1, k) * Aminusj(i, j, k) +
|
||||
src(i, j, k - 1) * Aminusk(i, j, k);
|
||||
|
||||
dst(i, j, k) += srcU(i + 1, j, k) * (*matrixA[7])(i, j, k) +
|
||||
srcU(i + 1, j, k - 1) * (*matrixA[8])(i, j, k) +
|
||||
srcU(i, j, k) * (*matrixA[9])(i, j, k) +
|
||||
srcU(i, j, k - 1) * (*matrixA[10])(i, j, k) +
|
||||
srcV(i, j + 1, k) * (*matrixA[11])(i, j, k) +
|
||||
srcV(i, j + 1, k - 1) * (*matrixA[12])(i, j, k) +
|
||||
srcV(i, j, k) * (*matrixA[13])(i, j, k) +
|
||||
srcV(i, j, k - 1) * (*matrixA[14])(i, j, k);
|
||||
}
|
||||
inline const FlagGrid &getArg0()
|
||||
{
|
||||
return flags;
|
||||
}
|
||||
typedef FlagGrid type0;
|
||||
inline Grid<Real> &getArg1()
|
||||
{
|
||||
return dst;
|
||||
}
|
||||
typedef Grid<Real> type1;
|
||||
inline const Grid<Real> &getArg2()
|
||||
{
|
||||
return src;
|
||||
}
|
||||
typedef Grid<Real> type2;
|
||||
inline const std::vector<Grid<Real> *> &getArg3()
|
||||
{
|
||||
return matrixA;
|
||||
}
|
||||
typedef std::vector<Grid<Real> *> type3;
|
||||
inline const std::vector<Grid<Real> *> &getArg4()
|
||||
{
|
||||
return vecRhs;
|
||||
}
|
||||
typedef std::vector<Grid<Real> *> type4;
|
||||
void runMessage()
|
||||
{
|
||||
debMsg("Executing kernel ApplyMatrixViscosityW ", 3);
|
||||
debMsg("Kernel range"
|
||||
<< " x " << maxX << " y " << maxY << " z " << minZ << " - " << maxZ << " ",
|
||||
4);
|
||||
};
|
||||
void operator()(const tbb::blocked_range<IndexInt> &__r) const
|
||||
{
|
||||
const int _maxX = maxX;
|
||||
const int _maxY = maxY;
|
||||
if (maxZ > 1) {
|
||||
for (int k = __r.begin(); k != (int)__r.end(); k++)
|
||||
for (int j = 1; j < _maxY; j++)
|
||||
for (int i = 1; i < _maxX; i++)
|
||||
op(i, j, k, flags, dst, src, matrixA, vecRhs);
|
||||
}
|
||||
else {
|
||||
const int k = 0;
|
||||
for (int j = __r.begin(); j != (int)__r.end(); j++)
|
||||
for (int i = 1; i < _maxX; i++)
|
||||
op(i, j, k, flags, dst, src, matrixA, vecRhs);
|
||||
}
|
||||
}
|
||||
void run()
|
||||
{
|
||||
if (maxZ > 1)
|
||||
tbb::parallel_for(tbb::blocked_range<IndexInt>(minZ, maxZ), *this);
|
||||
else
|
||||
tbb::parallel_for(tbb::blocked_range<IndexInt>(1, maxY), *this);
|
||||
}
|
||||
const FlagGrid &flags;
|
||||
Grid<Real> &dst;
|
||||
const Grid<Real> &src;
|
||||
const std::vector<Grid<Real> *> matrixA;
|
||||
const std::vector<Grid<Real> *> vecRhs;
|
||||
};
|
||||
|
||||
/* NOTE: Use this template for new matrix application kernels
|
||||
|
||||
//! Template for matrix application kernels
|
||||
KERNEL()
|
||||
void ApplyMatrixTemplate (const FlagGrid& flags, Grid<Real>& dst, const Grid<Real>& src,
|
||||
const std::vector<Grid<Real> *> matrixA, const std::vector<Grid<Real> *> vecRhs)
|
||||
{
|
||||
// The kernel must define how to use the grids from the matrixA and vecRhs lists
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
//! Kernel: Construct the matrix for the poisson equation
|
||||
|
||||
struct MakeLaplaceMatrix : public KernelBase {
|
||||
|
|
|
@ -42,7 +42,7 @@ inline void updateQtGui(bool full, int frame, float time, const std::string &cur
|
|||
# ifdef _DEBUG
|
||||
# define DEBUG 1
|
||||
# endif // _DEBUG
|
||||
#endif // DEBUG
|
||||
#endif // DEBUG
|
||||
|
||||
// Standard exception
|
||||
class Error : public std::exception {
|
||||
|
@ -242,6 +242,39 @@ inline bool c_isnan(float c)
|
|||
return d != d;
|
||||
}
|
||||
|
||||
//! Swap so that a<b
|
||||
template<class T> inline void sort(T &a, T &b)
|
||||
{
|
||||
if (a > b)
|
||||
std::swap(a, b);
|
||||
}
|
||||
|
||||
//! Swap so that a<b<c
|
||||
template<class T> inline void sort(T &a, T &b, T &c)
|
||||
{
|
||||
if (a > b)
|
||||
std::swap(a, b);
|
||||
if (a > c)
|
||||
std::swap(a, c);
|
||||
if (b > c)
|
||||
std::swap(b, c);
|
||||
}
|
||||
|
||||
//! Swap so that a<b<c<d
|
||||
template<class T> inline void sort(T &a, T &b, T &c, T &d)
|
||||
{
|
||||
if (a > b)
|
||||
std::swap(a, b);
|
||||
if (c > d)
|
||||
std::swap(c, d);
|
||||
if (a > c)
|
||||
std::swap(a, c);
|
||||
if (b > d)
|
||||
std::swap(b, d);
|
||||
if (b > c)
|
||||
std::swap(b, c);
|
||||
}
|
||||
|
||||
} // namespace Manta
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
|
||||
|
||||
#define MANTA_GIT_VERSION "commit 327917cd59b03bef3a953b5f58fc1637b3a83e01"
|
||||
#define MANTA_GIT_VERSION "commit e2285cb9bc492987f728123be6cfc1fe11fe73d6"
|
||||
|
|
|
@ -1135,26 +1135,27 @@ struct KnAddForceIfLower : public KernelBase {
|
|||
if (!curFluid && !curEmpty)
|
||||
return;
|
||||
|
||||
Real minVal, maxVal, sum;
|
||||
if (flags.isFluid(i - 1, j, k) || (curFluid && flags.isEmpty(i - 1, j, k))) {
|
||||
Real forceMACX = 0.5 * (force(i - 1, j, k).x + force(i, j, k).x);
|
||||
Real min = std::min(vel(i, j, k).x, forceMACX);
|
||||
Real max = std::max(vel(i, j, k).x, forceMACX);
|
||||
Real sum = vel(i, j, k).x + forceMACX;
|
||||
vel(i, j, k).x = (forceMACX > 0) ? std::min(sum, max) : std::max(sum, min);
|
||||
minVal = min(vel(i, j, k).x, forceMACX);
|
||||
maxVal = max(vel(i, j, k).x, forceMACX);
|
||||
sum = vel(i, j, k).x + forceMACX;
|
||||
vel(i, j, k).x = (forceMACX > 0) ? min(sum, maxVal) : max(sum, minVal);
|
||||
}
|
||||
if (flags.isFluid(i, j - 1, k) || (curFluid && flags.isEmpty(i, j - 1, k))) {
|
||||
Real forceMACY = 0.5 * (force(i, j - 1, k).y + force(i, j, k).y);
|
||||
Real min = std::min(vel(i, j, k).y, forceMACY);
|
||||
Real max = std::max(vel(i, j, k).y, forceMACY);
|
||||
Real sum = vel(i, j, k).y + forceMACY;
|
||||
vel(i, j, k).y = (forceMACY > 0) ? std::min(sum, max) : std::max(sum, min);
|
||||
minVal = min(vel(i, j, k).y, forceMACY);
|
||||
maxVal = max(vel(i, j, k).y, forceMACY);
|
||||
sum = vel(i, j, k).y + forceMACY;
|
||||
vel(i, j, k).y = (forceMACY > 0) ? min(sum, maxVal) : max(sum, minVal);
|
||||
}
|
||||
if (vel.is3D() && (flags.isFluid(i, j, k - 1) || (curFluid && flags.isEmpty(i, j, k - 1)))) {
|
||||
Real forceMACZ = 0.5 * (force(i, j, k - 1).z + force(i, j, k).z);
|
||||
Real min = std::min(vel(i, j, k).z, forceMACZ);
|
||||
Real max = std::max(vel(i, j, k).z, forceMACZ);
|
||||
Real sum = vel(i, j, k).z + forceMACZ;
|
||||
vel(i, j, k).z = (forceMACZ > 0) ? std::min(sum, max) : std::max(sum, min);
|
||||
minVal = min(vel(i, j, k).z, forceMACZ);
|
||||
maxVal = max(vel(i, j, k).z, forceMACZ);
|
||||
sum = vel(i, j, k).z + forceMACZ;
|
||||
vel(i, j, k).z = (forceMACZ > 0) ? min(sum, maxVal) : max(sum, minVal);
|
||||
}
|
||||
}
|
||||
inline const FlagGrid &getArg0()
|
||||
|
|
|
@ -1138,11 +1138,15 @@ void solvePressureSystem(Grid<Real> &rhs,
|
|||
// note: the last factor increases the max iterations for 2d, which right now can't use a
|
||||
// preconditioner
|
||||
GridCgInterface *gcg;
|
||||
if (vel.is3D())
|
||||
gcg = new GridCg<ApplyMatrix>(pressure, rhs, residual, search, flags, tmp, &A0, &Ai, &Aj, &Ak);
|
||||
else
|
||||
gcg = new GridCg<ApplyMatrix2D>(
|
||||
pressure, rhs, residual, search, flags, tmp, &A0, &Ai, &Aj, &Ak);
|
||||
vector<Grid<Real> *> matA{&A0, &Ai, &Aj};
|
||||
|
||||
if (vel.is3D()) {
|
||||
matA.push_back(&Ak);
|
||||
gcg = new GridCg<ApplyMatrix>(pressure, rhs, residual, search, flags, tmp, matA);
|
||||
}
|
||||
else {
|
||||
gcg = new GridCg<ApplyMatrix2D>(pressure, rhs, residual, search, flags, tmp, matA);
|
||||
}
|
||||
|
||||
gcg->setAccuracy(cgAccuracy);
|
||||
gcg->setUseL2Norm(useL2Norm);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -576,8 +576,10 @@ void VICintegration(VortexSheetMesh &mesh,
|
|||
|
||||
// prepare CG solver
|
||||
const int maxIter = (int)(cgMaxIterFac * vel.getSize().max());
|
||||
vector<Grid<Real> *> matA{&A0, &Ai, &Aj, &Ak};
|
||||
|
||||
GridCgInterface *gcg = new GridCg<ApplyMatrix>(
|
||||
solution, rhs, residual, search, flags, temp1, &A0, &Ai, &Aj, &Ak);
|
||||
solution, rhs, residual, search, flags, temp1, matA);
|
||||
gcg->setAccuracy(cgAccuracy);
|
||||
gcg->setUseL2Norm(true);
|
||||
gcg->setICPreconditioner(
|
||||
|
|
|
@ -423,10 +423,15 @@ void cgSolveWE(const FlagGrid &flags,
|
|||
|
||||
const int maxIter = (int)(cgMaxIterFac * flags.getSize().max()) * (flags.is3D() ? 1 : 4);
|
||||
GridCgInterface *gcg;
|
||||
if (flags.is3D())
|
||||
gcg = new GridCg<ApplyMatrix>(out, rhs, residual, search, flags, tmp, &A0, &Ai, &Aj, &Ak);
|
||||
else
|
||||
gcg = new GridCg<ApplyMatrix2D>(out, rhs, residual, search, flags, tmp, &A0, &Ai, &Aj, &Ak);
|
||||
vector<Grid<Real> *> matA{&A0, &Ai, &Aj};
|
||||
|
||||
if (flags.is3D()) {
|
||||
matA.push_back(&Ak);
|
||||
gcg = new GridCg<ApplyMatrix>(out, rhs, residual, search, flags, tmp, matA);
|
||||
}
|
||||
else {
|
||||
gcg = new GridCg<ApplyMatrix2D>(out, rhs, residual, search, flags, tmp, matA);
|
||||
}
|
||||
|
||||
gcg->setAccuracy(cgAccuracy);
|
||||
|
||||
|
|
|
@ -145,6 +145,7 @@ extern void PbRegister_flipComputeSurfaceNormals();
|
|||
extern void PbRegister_flipUpdateNeighborRatio();
|
||||
extern void PbRegister_particleSurfaceTurbulence();
|
||||
extern void PbRegister_debugCheckParts();
|
||||
extern void PbRegister_applyViscosity();
|
||||
extern void PbRegister_markAsFixed();
|
||||
extern void PbRegister_texcoordInflow();
|
||||
extern void PbRegister_meshSmokeInflow();
|
||||
|
@ -342,6 +343,7 @@ void MantaEnsureRegistration()
|
|||
PbRegister_flipUpdateNeighborRatio();
|
||||
PbRegister_particleSurfaceTurbulence();
|
||||
PbRegister_debugCheckParts();
|
||||
PbRegister_applyViscosity();
|
||||
PbRegister_markAsFixed();
|
||||
PbRegister_texcoordInflow();
|
||||
PbRegister_meshSmokeInflow();
|
||||
|
|
|
@ -351,6 +351,10 @@ static bool lookup_property(BL::ID b_id, const string &name, float4 *r_value)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (prop == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PropertyType type = RNA_property_type(prop);
|
||||
int arraylen = RNA_property_array_length(&ptr, prop);
|
||||
|
||||
|
|
|
@ -72,6 +72,7 @@ MANTA::MANTA(int *res, FluidModifierData *fmd)
|
|||
mUsingFractions = (fds->flags & FLUID_DOMAIN_USE_FRACTIONS) && mUsingLiquid;
|
||||
mUsingMesh = (fds->flags & FLUID_DOMAIN_USE_MESH) && mUsingLiquid;
|
||||
mUsingDiffusion = (fds->flags & FLUID_DOMAIN_USE_DIFFUSION) && mUsingLiquid;
|
||||
mUsingViscosity = (fds->flags & FLUID_DOMAIN_USE_VISCOSITY) && mUsingLiquid;
|
||||
mUsingMVel = (fds->flags & FLUID_DOMAIN_USE_SPEED_VECTORS) && mUsingLiquid;
|
||||
mUsingGuiding = (fds->flags & FLUID_DOMAIN_USE_GUIDE);
|
||||
mUsingDrops = (fds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY) && mUsingLiquid;
|
||||
|
@ -221,6 +222,10 @@ MANTA::MANTA(int *res, FluidModifierData *fmd)
|
|||
initSuccess &= initLiquidMesh();
|
||||
}
|
||||
|
||||
if (mUsingViscosity) {
|
||||
initSuccess &= initLiquidViscosity();
|
||||
}
|
||||
|
||||
if (mUsingDiffusion) {
|
||||
initSuccess &= initCurvature();
|
||||
}
|
||||
|
@ -440,6 +445,17 @@ bool MANTA::initLiquidMesh(FluidModifierData *fmd)
|
|||
return runPythonString(pythonCommands);
|
||||
}
|
||||
|
||||
bool MANTA::initLiquidViscosity(FluidModifierData *fmd)
|
||||
{
|
||||
vector<string> pythonCommands;
|
||||
string tmpString = fluid_variables_viscosity + fluid_solver_viscosity + liquid_alloc_viscosity;
|
||||
string finalString = parseScript(tmpString, fmd);
|
||||
pythonCommands.push_back(finalString);
|
||||
|
||||
mUsingViscosity = true;
|
||||
return runPythonString(pythonCommands);
|
||||
}
|
||||
|
||||
bool MANTA::initCurvature(FluidModifierData *fmd)
|
||||
{
|
||||
std::vector<std::string> pythonCommands;
|
||||
|
@ -871,8 +887,10 @@ void MANTA::initializeRNAMap(FluidModifierData *fmd)
|
|||
mRNAMap["CACHE_DIR"] = cacheDirectory;
|
||||
mRNAMap["COMPRESSION_OPENVDB"] = vdbCompressionMethod;
|
||||
mRNAMap["PRECISION_OPENVDB"] = vdbPrecisionHalf;
|
||||
mRNAMap["CLIP_OPENVDB"] = to_string(fds->clipping);
|
||||
mRNAMap["CLIP_OPENVDB"] = to_string(fds->clipping);
|
||||
mRNAMap["PP_PARTICLE_MAXIMUM"] = to_string(fds->sys_particle_maximum);
|
||||
mRNAMap["USING_VISCOSITY"] = getBooleanString(fds->flags & FLUID_DOMAIN_USE_VISCOSITY);
|
||||
mRNAMap["VISCOSITY_VALUE"] = to_string(fds->viscosity_value);
|
||||
|
||||
/* Fluid object names. */
|
||||
mRNAMap["NAME_FLAGS"] = FLUID_NAME_FLAGS;
|
||||
|
@ -1728,6 +1746,7 @@ bool MANTA::exportLiquidScript(FluidModifierData *fmd)
|
|||
bool guiding = fds->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE;
|
||||
bool invel = fds->active_fields & FLUID_DOMAIN_ACTIVE_INVEL;
|
||||
bool outflow = fds->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW;
|
||||
bool viscosity = fds->flags & FLUID_DOMAIN_USE_VISCOSITY;
|
||||
|
||||
string manta_script;
|
||||
|
||||
|
@ -1742,6 +1761,8 @@ bool MANTA::exportLiquidScript(FluidModifierData *fmd)
|
|||
manta_script += fluid_variables_particles + liquid_variables_particles;
|
||||
if (guiding)
|
||||
manta_script += fluid_variables_guiding;
|
||||
if (viscosity)
|
||||
manta_script += fluid_variables_viscosity;
|
||||
|
||||
/* Solvers. */
|
||||
manta_script += header_solvers + fluid_solver;
|
||||
|
@ -1751,6 +1772,8 @@ bool MANTA::exportLiquidScript(FluidModifierData *fmd)
|
|||
manta_script += fluid_solver_particles;
|
||||
if (guiding)
|
||||
manta_script += fluid_solver_guiding;
|
||||
if (viscosity)
|
||||
manta_script += fluid_solver_viscosity;
|
||||
|
||||
/* Grids. */
|
||||
manta_script += header_grids + fluid_alloc + liquid_alloc;
|
||||
|
@ -1768,6 +1791,8 @@ bool MANTA::exportLiquidScript(FluidModifierData *fmd)
|
|||
manta_script += fluid_alloc_invel;
|
||||
if (outflow)
|
||||
manta_script += fluid_alloc_outflow;
|
||||
if (viscosity)
|
||||
manta_script += liquid_alloc_viscosity;
|
||||
|
||||
/* Domain init. */
|
||||
manta_script += header_gridinit + liquid_init_phi;
|
||||
|
|
|
@ -67,6 +67,7 @@ struct MANTA {
|
|||
bool initColorsHigh(struct FluidModifierData *fmd = nullptr);
|
||||
bool initLiquid(FluidModifierData *fmd = nullptr);
|
||||
bool initLiquidMesh(FluidModifierData *fmd = nullptr);
|
||||
bool initLiquidViscosity(FluidModifierData *fmd = nullptr);
|
||||
bool initObstacle(FluidModifierData *fmd = nullptr);
|
||||
bool initCurvature(FluidModifierData *fmd = nullptr);
|
||||
bool initGuiding(FluidModifierData *fmd = nullptr);
|
||||
|
@ -757,6 +758,7 @@ struct MANTA {
|
|||
bool mUsingNoise;
|
||||
bool mUsingMesh;
|
||||
bool mUsingDiffusion;
|
||||
bool mUsingViscosity;
|
||||
bool mUsingMVel;
|
||||
bool mUsingLiquid;
|
||||
bool mUsingSmoke;
|
||||
|
|
|
@ -79,6 +79,11 @@ const std::string fluid_solver_guiding =
|
|||
mantaMsg('Solver guiding')\n\
|
||||
sg$ID$ = Solver(name='solver_guiding$ID$', gridSize=gs_sg$ID$)\n";
|
||||
|
||||
const std::string fluid_solver_viscosity =
|
||||
"\n\
|
||||
mantaMsg('Solver viscosity')\n\
|
||||
sv$ID$ = Solver(name='solver_viscosity$ID$', gridSize=gs_sv$ID$, dim=dim_s$ID$)\n";
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// VARIABLES
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
@ -133,7 +138,7 @@ end_frame_s$ID$ = $END_FRAME$\n\
|
|||
\n\
|
||||
# Fluid diffusion / viscosity\n\
|
||||
domainSize_s$ID$ = $FLUID_DOMAIN_SIZE$ # longest domain side in meters\n\
|
||||
viscosity_s$ID$ = $FLUID_VISCOSITY$ / (domainSize_s$ID$*domainSize_s$ID$) # kinematic viscosity in m^2/s\n\
|
||||
kinViscosity_s$ID$ = $FLUID_VISCOSITY$ / (domainSize_s$ID$*domainSize_s$ID$) # kinematic viscosity in m^2/s\n\
|
||||
\n\
|
||||
# Factors to convert Blender units to Manta units\n\
|
||||
ratioMetersToRes_s$ID$ = float(domainSize_s$ID$) / float(res_s$ID$) # [meters / cells]\n\
|
||||
|
@ -199,6 +204,10 @@ tau_sg$ID$ = 1.0\n\
|
|||
sigma_sg$ID$ = 0.99/tau_sg$ID$\n\
|
||||
theta_sg$ID$ = 1.0\n";
|
||||
|
||||
const std::string fluid_variables_viscosity =
|
||||
"\n\
|
||||
gs_sv$ID$ = vec3($RESX$*2, $RESY$*2, $RESZ$*2)\n";
|
||||
|
||||
const std::string fluid_with_obstacle =
|
||||
"\n\
|
||||
using_obstacle_s$ID$ = True\n";
|
||||
|
|
|
@ -40,6 +40,8 @@ radiusFactor_s$ID$ = $PARTICLE_RADIUS$\n\
|
|||
using_mesh_s$ID$ = $USING_MESH$\n\
|
||||
using_final_mesh_s$ID$ = $USING_IMPROVED_MESH$\n\
|
||||
using_fractions_s$ID$ = $USING_FRACTIONS$\n\
|
||||
using_apic_s$ID$ = $USING_APIC$\n\
|
||||
using_viscosity_s$ID$ = $USING_VISCOSITY$\n\
|
||||
fracThreshold_s$ID$ = $FRACTIONS_THRESHOLD$\n\
|
||||
fracDistance_s$ID$ = $FRACTIONS_DISTANCE$\n\
|
||||
flipRatio_s$ID$ = $FLIP_RATIO$\n\
|
||||
|
@ -51,7 +53,7 @@ smoothenNeg_s$ID$ = $MESH_SMOOTHEN_NEG$\n\
|
|||
randomness_s$ID$ = $PARTICLE_RANDOMNESS$\n\
|
||||
surfaceTension_s$ID$ = $LIQUID_SURFACE_TENSION$\n\
|
||||
maxSysParticles_s$ID$ = $PP_PARTICLE_MAXIMUM$\n\
|
||||
using_apic_s$ID$ = $USING_APIC$\n";
|
||||
viscosityValue_s$ID$ = $VISCOSITY_VALUE$\n";
|
||||
|
||||
const std::string liquid_variables_particles =
|
||||
"\n\
|
||||
|
@ -135,6 +137,13 @@ liquid_mesh_dict_s$ID$ = { 'lMesh' : mesh_sm$ID$ }\n\
|
|||
if using_speedvectors_s$ID$:\n\
|
||||
liquid_meshvel_dict_s$ID$ = { 'lVelMesh' : mVel_mesh$ID$ }\n";
|
||||
|
||||
const std::string liquid_alloc_viscosity =
|
||||
"\n\
|
||||
# Viscosity grids\n\
|
||||
volumes_s$ID$ = sv$ID$.create(RealGrid)\n\
|
||||
viscosity_s$ID$ = s$ID$.create(RealGrid)\n\
|
||||
viscosity_s$ID$.setConst(viscosityValue_s$ID$)\n";
|
||||
|
||||
const std::string liquid_alloc_curvature =
|
||||
"\n\
|
||||
mantaMsg('Liquid alloc curvature')\n\
|
||||
|
@ -306,7 +315,7 @@ def liquid_step_$ID$():\n\
|
|||
if using_diffusion_s$ID$:\n\
|
||||
mantaMsg('Viscosity')\n\
|
||||
# diffusion param for solve = const * dt / dx^2\n\
|
||||
alphaV = viscosity_s$ID$ * s$ID$.timestep * float(res_s$ID$*res_s$ID$)\n\
|
||||
alphaV = kinViscosity_s$ID$ * s$ID$.timestep * float(res_s$ID$*res_s$ID$)\n\
|
||||
setWallBcs(flags=flags_s$ID$, vel=vel_s$ID$, obvel=None if using_fractions_s$ID$ else obvel_s$ID$, phiObs=phiObs_s$ID$, fractions=fractions_s$ID$)\n\
|
||||
cgSolveDiffusion(flags_s$ID$, vel_s$ID$, alphaV)\n\
|
||||
\n\
|
||||
|
@ -315,7 +324,11 @@ def liquid_step_$ID$():\n\
|
|||
curvature_s$ID$.clamp(-1.0, 1.0)\n\
|
||||
\n\
|
||||
setWallBcs(flags=flags_s$ID$, vel=vel_s$ID$, obvel=None if using_fractions_s$ID$ else obvel_s$ID$, phiObs=phiObs_s$ID$, fractions=fractions_s$ID$)\n\
|
||||
if using_viscosity_s$ID$:\n\
|
||||
viscosity_s$ID$.setConst(viscosityValue_s$ID$)\n\
|
||||
applyViscosity(flags=flags_s$ID$, phi=phi_s$ID$, vel=vel_s$ID$, volumes=volumes_s$ID$, viscosity=viscosity_s$ID$)\n\
|
||||
\n\
|
||||
setWallBcs(flags=flags_s$ID$, vel=vel_s$ID$, obvel=None if using_fractions_s$ID$ else obvel_s$ID$, phiObs=phiObs_s$ID$, fractions=fractions_s$ID$)\n\
|
||||
if using_guiding_s$ID$:\n\
|
||||
mantaMsg('Guiding and pressure')\n\
|
||||
PD_fluid_guiding(vel=vel_s$ID$, velT=velT_s$ID$, flags=flags_s$ID$, phi=phi_s$ID$, curv=curvature_s$ID$, surfTens=surfaceTension_s$ID$, fractions=fractions_s$ID$, weight=weightGuide_s$ID$, blurRadius=beta_sg$ID$, pressure=pressure_s$ID$, tau=tau_sg$ID$, sigma=sigma_sg$ID$, theta=theta_sg$ID$, zeroPressureFixing=domainClosed_s$ID$)\n\
|
||||
|
|
|
@ -1006,6 +1006,46 @@ class PHYSICS_PT_particles(PhysicButtonsPanel, Panel):
|
|||
split.operator("fluid.free_particles", text="Free Particles")
|
||||
|
||||
|
||||
class PHYSICS_PT_viscosity(PhysicButtonsPanel, Panel):
|
||||
bl_label = "Viscosity"
|
||||
bl_parent_id = 'PHYSICS_PT_liquid'
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
# Fluid viscosity only enabled for liquids
|
||||
if not PhysicButtonsPanel.poll_liquid_domain(context):
|
||||
return False
|
||||
|
||||
return (context.engine in cls.COMPAT_ENGINES)
|
||||
|
||||
def draw_header(self, context):
|
||||
md = context.fluid.domain_settings
|
||||
domain = context.fluid.domain_settings
|
||||
is_baking_any = domain.is_cache_baking_any
|
||||
has_baked_any = domain.has_cache_baked_any
|
||||
self.layout.enabled = not is_baking_any and not has_baked_any
|
||||
self.layout.prop(md, "use_viscosity", text="")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
|
||||
domain = context.fluid.domain_settings
|
||||
layout.active = domain.use_viscosity
|
||||
|
||||
is_baking_any = domain.is_cache_baking_any
|
||||
has_baked_any = domain.has_cache_baked_any
|
||||
has_baked_data = domain.has_cache_baked_data
|
||||
|
||||
flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
|
||||
flow.enabled = not is_baking_any and not has_baked_any and not has_baked_data
|
||||
|
||||
col = flow.column(align=True)
|
||||
col.prop(domain, "viscosity_value", text="Strength")
|
||||
|
||||
|
||||
class PHYSICS_PT_diffusion(PhysicButtonsPanel, Panel):
|
||||
bl_label = "Diffusion"
|
||||
bl_parent_id = 'PHYSICS_PT_liquid'
|
||||
|
@ -1470,6 +1510,7 @@ classes = (
|
|||
PHYSICS_PT_noise,
|
||||
PHYSICS_PT_fire,
|
||||
PHYSICS_PT_liquid,
|
||||
PHYSICS_PT_viscosity,
|
||||
PHYSICS_PT_diffusion,
|
||||
PHYSICS_PT_particles,
|
||||
PHYSICS_PT_mesh,
|
||||
|
|
|
@ -514,6 +514,7 @@ geometry_node_categories = [
|
|||
NodeItem("GeometryNodePointDistribute"),
|
||||
NodeItem("GeometryNodePointInstance"),
|
||||
NodeItem("GeometryNodePointSeparate"),
|
||||
NodeItem("GeometryNodeRotatePoints"),
|
||||
]),
|
||||
GeometryNodeCategory("GEO_UTILITIES", "Utilities", items=[
|
||||
NodeItem("ShaderNodeMapRange"),
|
||||
|
|
|
@ -39,7 +39,7 @@ extern "C" {
|
|||
|
||||
/* Blender file format version. */
|
||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||
#define BLENDER_FILE_SUBVERSION 8
|
||||
#define BLENDER_FILE_SUBVERSION 9
|
||||
|
||||
/* Minimum Blender version that supports reading file written with the current
|
||||
* version. Older Blender versions will test this and show a warning if the file
|
||||
|
|
|
@ -1356,6 +1356,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
|
|||
#define GEO_NODE_ATTRIBUTE_COLOR_RAMP 1013
|
||||
#define GEO_NODE_POINT_SEPARATE 1014
|
||||
#define GEO_NODE_ATTRIBUTE_COMPARE 1015
|
||||
#define GEO_NODE_ROTATE_POINTS 1016
|
||||
|
||||
/** \} */
|
||||
|
||||
|
|
|
@ -635,9 +635,6 @@ void BKE_sculpt_sync_face_sets_visibility_to_base_mesh(struct Mesh *mesh);
|
|||
void BKE_sculpt_sync_face_sets_visibility_to_grids(struct Mesh *mesh,
|
||||
struct SubdivCCG *subdiv_ccg);
|
||||
|
||||
/* Ensures that a Face Set data-layers exists. If it does not, it creates one respecting the
|
||||
* visibility stored in the vertices of the mesh. If it does, it copies the visibility from the
|
||||
* mesh to the Face Sets. */
|
||||
void BKE_sculpt_face_sets_ensure_from_base_mesh_visibility(struct Mesh *mesh);
|
||||
|
||||
bool BKE_sculptsession_use_pbvh_draw(const struct Object *ob, const struct View3D *v3d);
|
||||
|
|
|
@ -5011,6 +5011,9 @@ void BKE_fluid_modifier_copy(const struct FluidModifierData *fmd,
|
|||
tfds->sys_particle_maximum = fds->sys_particle_maximum;
|
||||
tfds->simulation_method = fds->simulation_method;
|
||||
|
||||
/* viscosity options */
|
||||
tfds->viscosity_value = fds->viscosity_value;
|
||||
|
||||
/* diffusion options*/
|
||||
tfds->surface_tension = fds->surface_tension;
|
||||
tfds->viscosity_base = fds->viscosity_base;
|
||||
|
|
|
@ -61,8 +61,24 @@ bool multires_reshape_assign_final_coords_from_ccg(const MultiresReshapeContext
|
|||
sizeof(float[3]));
|
||||
|
||||
if (reshape_level_key.has_mask) {
|
||||
BLI_assert(grid_element.mask != NULL);
|
||||
*grid_element.mask = *CCG_grid_elem_mask(&reshape_level_key, ccg_grid, x, y);
|
||||
/* Assert about a non-NULL `grid_element.mask` may fail here, this code may be called
|
||||
* from cleanup code during COW evaluation phase by depsgraph (e.g.
|
||||
* `object_update_from_subsurf_ccg` call in `BKE_object_free_derived_caches`).
|
||||
*
|
||||
* `reshape_level_key.has_mask` is ultimately set from MultiRes modifier apply code
|
||||
* (through `multires_as_ccg` -> `multires_ccg_settings_init`), when object is in sculpt
|
||||
* mode only, and there is matching loop cdlayer.
|
||||
*
|
||||
* `grid_element.mask` is directly set from existing matching loop cdlayer during
|
||||
* initialization of `MultiresReshapeContext` struct.
|
||||
*
|
||||
* Since ccg data is preserved during undos, we may end up with a state where there is no
|
||||
* mask data in mesh loops' cdlayer, while ccg's `has_mask` is still set to true.
|
||||
*/
|
||||
// BLI_assert(grid_element.mask != NULL);
|
||||
if (grid_element.mask != NULL) {
|
||||
*grid_element.mask = *CCG_grid_elem_mask(&reshape_level_key, ccg_grid, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4744,6 +4744,7 @@ static void registerGeometryNodes(void)
|
|||
register_node_type_geo_join_geometry();
|
||||
register_node_type_geo_attribute_mix();
|
||||
register_node_type_geo_attribute_color_ramp();
|
||||
register_node_type_geo_rotate_points();
|
||||
}
|
||||
|
||||
static void registerFunctionNodes(void)
|
||||
|
|
|
@ -1596,7 +1596,7 @@ static void sculpt_update_object(Depsgraph *depsgraph,
|
|||
Scene *scene = DEG_get_input_scene(depsgraph);
|
||||
Sculpt *sd = scene->toolsettings->sculpt;
|
||||
SculptSession *ss = ob->sculpt;
|
||||
Mesh *me = BKE_object_get_original_mesh(ob);
|
||||
const Mesh *me = BKE_object_get_original_mesh(ob);
|
||||
MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob);
|
||||
const bool use_face_sets = (ob->mode & OB_MODE_SCULPT) != 0;
|
||||
|
||||
|
@ -1612,20 +1612,13 @@ static void sculpt_update_object(Depsgraph *depsgraph,
|
|||
|
||||
if (need_mask) {
|
||||
if (mmd == NULL) {
|
||||
if (!CustomData_has_layer(&me->vdata, CD_PAINT_MASK)) {
|
||||
BKE_sculpt_mask_layers_ensure(ob, NULL);
|
||||
}
|
||||
BLI_assert(CustomData_has_layer(&me->vdata, CD_PAINT_MASK));
|
||||
}
|
||||
else {
|
||||
if (!CustomData_has_layer(&me->ldata, CD_GRID_PAINT_MASK)) {
|
||||
BKE_sculpt_mask_layers_ensure(ob, mmd);
|
||||
}
|
||||
BLI_assert(CustomData_has_layer(&me->ldata, CD_GRID_PAINT_MASK));
|
||||
}
|
||||
}
|
||||
|
||||
/* tessfaces aren't used and will become invalid */
|
||||
BKE_mesh_tessface_clear(me);
|
||||
|
||||
ss->shapekey_active = (mmd == NULL) ? BKE_keyblock_from_object(ob) : NULL;
|
||||
|
||||
/* NOTE: Weight pPaint require mesh info for loop lookup, but it never uses multires code path,
|
||||
|
@ -1660,12 +1653,7 @@ static void sculpt_update_object(Depsgraph *depsgraph,
|
|||
|
||||
/* Sculpt Face Sets. */
|
||||
if (use_face_sets) {
|
||||
if (!CustomData_has_layer(&me->pdata, CD_SCULPT_FACE_SETS)) {
|
||||
/* By checking here if the data-layer already exist this avoids copying the visibility from
|
||||
* the mesh and looping over all vertices on every sculpt editing operation, using this
|
||||
* function only the first time the Face Sets data-layer needs to be created. */
|
||||
BKE_sculpt_face_sets_ensure_from_base_mesh_visibility(me);
|
||||
}
|
||||
BLI_assert(CustomData_has_layer(&me->pdata, CD_SCULPT_FACE_SETS));
|
||||
ss->face_sets = CustomData_get_layer(&me->pdata, CD_SCULPT_FACE_SETS);
|
||||
}
|
||||
else {
|
||||
|
@ -1928,6 +1916,10 @@ static bool check_sculpt_object_deformed(Object *object, const bool for_construc
|
|||
return deformed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that a Face Set data-layers exists. If it does not, it creates one respecting the
|
||||
* visibility stored in the vertices of the mesh. If it does, it copies the visibility from the
|
||||
* mesh to the Face Sets. */
|
||||
void BKE_sculpt_face_sets_ensure_from_base_mesh_visibility(Mesh *mesh)
|
||||
{
|
||||
const int face_sets_default_visible_id = 1;
|
||||
|
|
|
@ -1430,18 +1430,7 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Versioning code until next subversion bump goes here.
|
||||
*
|
||||
* \note Be sure to check when bumping the version:
|
||||
* - "versioning_userdef.c", #blo_do_versions_userdef
|
||||
* - "versioning_userdef.c", #do_versions_theme
|
||||
*
|
||||
* \note Keep this message at the bottom of the function.
|
||||
*/
|
||||
{
|
||||
/* Keep this block, even when empty. */
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 292, 9)) {
|
||||
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
|
||||
if (ntree->type == NTREE_GEOMETRY) {
|
||||
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
||||
|
@ -1474,5 +1463,32 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure that new viscosity strength field is initialized correctly. */
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "FluidModifierData", "float", "viscosity_value")) {
|
||||
LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
|
||||
LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
|
||||
if (md->type == eModifierType_Fluid) {
|
||||
FluidModifierData *fmd = (FluidModifierData *)md;
|
||||
if (fmd->domain != NULL) {
|
||||
fmd->domain->viscosity_value = 0.05;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Versioning code until next subversion bump goes here.
|
||||
*
|
||||
* \note Be sure to check when bumping the version:
|
||||
* - "versioning_userdef.c", #blo_do_versions_userdef
|
||||
* - "versioning_userdef.c", #do_versions_theme
|
||||
*
|
||||
* \note Keep this message at the bottom of the function.
|
||||
*/
|
||||
{
|
||||
/* Keep this block, even when empty. */
|
||||
}
|
||||
}
|
||||
|
|
|
@ -820,6 +820,12 @@ void blo_do_versions_userdef(UserDef *userdef)
|
|||
userdef->uiflag &= ~USER_UIFLAG_UNUSED_3;
|
||||
}
|
||||
|
||||
if (!USER_VERSION_ATLEAST(292, 9)) {
|
||||
if (BLI_listbase_is_empty(&userdef->asset_libraries)) {
|
||||
BKE_preferences_asset_library_default_add(userdef);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Versioning code until next subversion bump goes here.
|
||||
*
|
||||
|
@ -831,9 +837,6 @@ void blo_do_versions_userdef(UserDef *userdef)
|
|||
*/
|
||||
{
|
||||
/* Keep this block, even when empty. */
|
||||
if (BLI_listbase_is_empty(&userdef->asset_libraries)) {
|
||||
BKE_preferences_asset_library_default_add(userdef);
|
||||
}
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (bTheme *, btheme, &userdef->themes) {
|
||||
|
|
|
@ -26,7 +26,7 @@ ExposureNode::ExposureNode(bNode *editorNode) : Node(editorNode)
|
|||
}
|
||||
|
||||
void ExposureNode::convertToOperations(NodeConverter &converter,
|
||||
const CompositorContext & /*context*/) const
|
||||
const CompositorContext & /*context*/) const
|
||||
{
|
||||
ExposureOperation *operation = new ExposureOperation();
|
||||
converter.addOperation(operation);
|
||||
|
|
|
@ -633,6 +633,10 @@ static bool drw_uniform_property_lookup(ID *id, const char *name, float r_data[4
|
|||
return false;
|
||||
}
|
||||
|
||||
if (prop == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PropertyType type = RNA_property_type(prop);
|
||||
int arraylen = RNA_property_array_length(&ptr, prop);
|
||||
|
||||
|
|
|
@ -52,9 +52,6 @@ void ED_spacedata_id_remap(struct ScrArea *area,
|
|||
struct ID *old_id,
|
||||
struct ID *new_id);
|
||||
|
||||
void ED_OT_lib_id_load_custom_preview(struct wmOperatorType *ot);
|
||||
void ED_OT_lib_id_generate_preview(struct wmOperatorType *ot);
|
||||
|
||||
void ED_operatortypes_edutils(void);
|
||||
|
||||
/* ************** XXX OLD CRUFT WARNING ************* */
|
||||
|
|
|
@ -1626,10 +1626,10 @@ static uiButExtraOpIcon *ui_but_extra_operator_icon_add_ptr(uiBut *but,
|
|||
|
||||
extra_op_icon->icon = (BIFIconID)icon;
|
||||
extra_op_icon->optype_params = MEM_callocN(sizeof(*extra_op_icon->optype_params),
|
||||
"uiButExtraOpIcon.optype_hook");
|
||||
"uiButExtraOpIcon.optype_params");
|
||||
extra_op_icon->optype_params->optype = optype;
|
||||
extra_op_icon->optype_params->opptr = MEM_callocN(sizeof(*extra_op_icon->optype_params->opptr),
|
||||
"uiButExtraOpIcon.optype_hook.opptr");
|
||||
"uiButExtraOpIcon.optype_params.opptr");
|
||||
WM_operator_properties_create_ptr(extra_op_icon->optype_params->opptr,
|
||||
extra_op_icon->optype_params->optype);
|
||||
extra_op_icon->optype_params->opcontext = opcontext;
|
||||
|
|
|
@ -1392,7 +1392,7 @@ static void template_id_name_button(
|
|||
UI_but_extra_operator_icon_add(but, template_ui->unlink_op, WM_OP_INVOKE_DEFAULT, ICON_X);
|
||||
}
|
||||
else if (!never_unlink) {
|
||||
UI_but_extra_operator_icon_add(but, "ED_OT_lib_unlink", WM_OP_INVOKE_DEFAULT, ICON_X);
|
||||
UI_but_extra_operator_icon_add(but, "ED_OT_lib_id_unlink", WM_OP_INVOKE_DEFAULT, ICON_X);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1401,7 +1401,7 @@ static void template_id_name_button(
|
|||
if (add_extra_fake_user_icon && id->lib == NULL &&
|
||||
!(ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS))) {
|
||||
UI_but_extra_operator_icon_add(but,
|
||||
"ED_OT_lib_fake_user_toggle",
|
||||
"ED_OT_lib_id_fake_user_toggle",
|
||||
WM_OP_INVOKE_DEFAULT,
|
||||
ID_FAKE_USERS(id) ? ICON_FAKE_USER_ON : ICON_FAKE_USER_OFF);
|
||||
}
|
||||
|
|
|
@ -3138,6 +3138,8 @@ static int screen_maximize_area_exec(bContext *C, wmOperator *op)
|
|||
ScrArea *area = NULL;
|
||||
const bool hide_panels = RNA_boolean_get(op->ptr, "use_hide_panels");
|
||||
|
||||
BLI_assert(!screen->temp);
|
||||
|
||||
/* search current screen for 'fullscreen' areas */
|
||||
/* prevents restoring info header, when mouse is over it */
|
||||
LISTBASE_FOREACH (ScrArea *, area_iter, &screen->areabase) {
|
||||
|
@ -3169,11 +3171,14 @@ static int screen_maximize_area_exec(bContext *C, wmOperator *op)
|
|||
|
||||
static bool screen_maximize_area_poll(bContext *C)
|
||||
{
|
||||
const wmWindow *win = CTX_wm_window(C);
|
||||
const bScreen *screen = CTX_wm_screen(C);
|
||||
const ScrArea *area = CTX_wm_area(C);
|
||||
return ED_operator_areaactive(C) &&
|
||||
/* Don't allow maximizing global areas but allow minimizing from them. */
|
||||
((screen->state != SCREENNORMAL) || !ED_area_is_global(area));
|
||||
((screen->state != SCREENNORMAL) || !ED_area_is_global(area)) &&
|
||||
/* Don't change temporary screens. */
|
||||
!WM_window_is_temp_screen(win);
|
||||
}
|
||||
|
||||
static void SCREEN_OT_screen_full_area(wmOperatorType *ot)
|
||||
|
@ -5501,16 +5506,6 @@ void ED_operatortypes_screen(void)
|
|||
/* new/delete */
|
||||
WM_operatortype_append(SCREEN_OT_new);
|
||||
WM_operatortype_append(SCREEN_OT_delete);
|
||||
|
||||
/* tools shared by more space types */
|
||||
WM_operatortype_append(ED_OT_undo);
|
||||
WM_operatortype_append(ED_OT_undo_push);
|
||||
WM_operatortype_append(ED_OT_redo);
|
||||
WM_operatortype_append(ED_OT_undo_redo);
|
||||
WM_operatortype_append(ED_OT_undo_history);
|
||||
|
||||
WM_operatortype_append(ED_OT_lib_id_load_custom_preview);
|
||||
WM_operatortype_append(ED_OT_lib_id_generate_preview);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -1190,25 +1190,6 @@ void SCULPT_floodfill_free(SculptFloodFill *flood)
|
|||
*
|
||||
* \{ */
|
||||
|
||||
/* Check if there are any active modifiers in stack.
|
||||
* Used for flushing updates at enter/exit sculpt mode. */
|
||||
static bool sculpt_has_active_modifiers(Scene *scene, Object *ob)
|
||||
{
|
||||
ModifierData *md;
|
||||
VirtualModifierData virtualModifierData;
|
||||
|
||||
md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData);
|
||||
|
||||
/* Exception for shape keys because we can edit those. */
|
||||
for (; md; md = md->next) {
|
||||
if (BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool sculpt_tool_needs_original(const char sculpt_tool)
|
||||
{
|
||||
return ELEM(sculpt_tool,
|
||||
|
@ -8655,7 +8636,7 @@ static void sculpt_init_session(Depsgraph *depsgraph, Scene *scene, Object *ob)
|
|||
/* Here we can detect geometry that was just added to Sculpt Mode as it has the
|
||||
* SCULPT_FACE_SET_NONE assigned, so we can create a new Face Set for it. */
|
||||
/* In sculpt mode all geometry that is assigned to SCULPT_FACE_SET_NONE is considered as not
|
||||
* initialized, which is used is some operators that modify the mesh topology to preform certain
|
||||
* initialized, which is used is some operators that modify the mesh topology to perform certain
|
||||
* actions in the new polys. After these operations are finished, all polys should have a valid
|
||||
* face set ID assigned (different from SCULPT_FACE_SET_NONE) to manage their visibility
|
||||
* correctly. */
|
||||
|
@ -8669,23 +8650,6 @@ static void sculpt_init_session(Depsgraph *depsgraph, Scene *scene, Object *ob)
|
|||
ss->face_sets[i] = new_face_set;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the Face Sets visibility with the vertex visibility changes that may have been done
|
||||
* outside Sculpt Mode */
|
||||
Mesh *mesh = ob->data;
|
||||
BKE_sculpt_face_sets_ensure_from_base_mesh_visibility(mesh);
|
||||
}
|
||||
|
||||
static int ed_object_sculptmode_flush_recalc_flag(Scene *scene,
|
||||
Object *ob,
|
||||
MultiresModifierData *mmd)
|
||||
{
|
||||
int flush_recalc = 0;
|
||||
/* Multires in sculpt mode could have different from object mode subdivision level. */
|
||||
flush_recalc |= mmd && mmd->sculptlvl != mmd->lvl;
|
||||
/* If object has got active modifiers, its dm could be different in sculpt mode. */
|
||||
flush_recalc |= sculpt_has_active_modifiers(scene, ob);
|
||||
return flush_recalc;
|
||||
}
|
||||
|
||||
void ED_object_sculptmode_enter_ex(Main *bmain,
|
||||
|
@ -8703,13 +8667,6 @@ void ED_object_sculptmode_enter_ex(Main *bmain,
|
|||
|
||||
MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob);
|
||||
|
||||
const int flush_recalc = ed_object_sculptmode_flush_recalc_flag(scene, ob, mmd);
|
||||
|
||||
if (flush_recalc) {
|
||||
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
|
||||
BKE_scene_graph_evaluated_ensure(depsgraph, bmain);
|
||||
}
|
||||
|
||||
/* Create sculpt mode session data. */
|
||||
if (ob->sculpt) {
|
||||
BKE_sculptsession_free(ob);
|
||||
|
@ -8718,14 +8675,30 @@ void ED_object_sculptmode_enter_ex(Main *bmain,
|
|||
/* Copy the current mesh visibility to the Face Sets. */
|
||||
BKE_sculpt_face_sets_ensure_from_base_mesh_visibility(me);
|
||||
|
||||
sculpt_init_session(depsgraph, scene, ob);
|
||||
/* Mask layer is required for Multires. */
|
||||
BKE_sculpt_mask_layers_ensure(ob, mmd);
|
||||
|
||||
/* Mask layer is required. */
|
||||
if (mmd) {
|
||||
/* XXX, we could attempt to support adding mask data mid-sculpt mode (with multi-res)
|
||||
* but this ends up being quite tricky (and slow). */
|
||||
BKE_sculpt_mask_layers_ensure(ob, mmd);
|
||||
}
|
||||
/* Tessfaces aren't used and will become invalid. */
|
||||
BKE_mesh_tessface_clear(me);
|
||||
|
||||
/* We always need to flush updates from depsgraph here, since at the very least
|
||||
* `BKE_sculpt_face_sets_ensure_from_base_mesh_visibility()` will have updated some data layer of
|
||||
* the mesh.
|
||||
*
|
||||
* All known potential sources of updates:
|
||||
* - Addition of, or changes to, the `CD_SCULPT_FACE_SETS` data layer
|
||||
* (`BKE_sculpt_face_sets_ensure_from_base_mesh_visibility`).
|
||||
* - Addition of a `CD_PAINT_MASK` data layer (`BKE_sculpt_mask_layers_ensure`).
|
||||
* - Object has any active modifier (modifier stack can be different in Sculpt mode).
|
||||
* - Multires:
|
||||
* + Differences of subdiv levels between sculpt and object modes
|
||||
* (`mmd->sculptlvl != mmd->lvl`).
|
||||
* + Addition of a `CD_GRID_PAINT_MASK` data layer (`BKE_sculpt_mask_layers_ensure`).
|
||||
*/
|
||||
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
|
||||
BKE_scene_graph_evaluated_ensure(depsgraph, bmain);
|
||||
|
||||
sculpt_init_session(depsgraph, scene, ob);
|
||||
|
||||
if (!(fabsf(ob->scale[0] - ob->scale[1]) < 1e-4f &&
|
||||
fabsf(ob->scale[1] - ob->scale[2]) < 1e-4f)) {
|
||||
|
|
|
@ -921,7 +921,7 @@ SculptUndoNode *SCULPT_undo_get_first_node()
|
|||
return usculpt->nodes.first;
|
||||
}
|
||||
|
||||
static void sculpt_undo_alloc_and_store_hidden(PBVH *pbvh, SculptUndoNode *unode)
|
||||
static size_t sculpt_undo_alloc_and_store_hidden(PBVH *pbvh, SculptUndoNode *unode)
|
||||
{
|
||||
PBVHNode *node = unode->node;
|
||||
BLI_bitmap **grid_hidden = BKE_pbvh_grid_hidden(pbvh);
|
||||
|
@ -929,28 +929,34 @@ static void sculpt_undo_alloc_and_store_hidden(PBVH *pbvh, SculptUndoNode *unode
|
|||
int *grid_indices, totgrid;
|
||||
BKE_pbvh_node_get_grids(pbvh, node, &grid_indices, &totgrid, NULL, NULL, NULL);
|
||||
|
||||
unode->grid_hidden = MEM_callocN(sizeof(*unode->grid_hidden) * totgrid, "unode->grid_hidden");
|
||||
size_t alloc_size = sizeof(*unode->grid_hidden) * (size_t)totgrid;
|
||||
unode->grid_hidden = MEM_callocN(alloc_size, "unode->grid_hidden");
|
||||
|
||||
for (int i = 0; i < totgrid; i++) {
|
||||
if (grid_hidden[grid_indices[i]]) {
|
||||
unode->grid_hidden[i] = MEM_dupallocN(grid_hidden[grid_indices[i]]);
|
||||
alloc_size += MEM_allocN_len(unode->grid_hidden[i]);
|
||||
}
|
||||
else {
|
||||
unode->grid_hidden[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return alloc_size;
|
||||
}
|
||||
|
||||
/* Allocate node and initialize its default fields specific for the given undo type.
|
||||
* Will also add the node to the list in the undo step. */
|
||||
static SculptUndoNode *sculpt_undo_alloc_node_type(Object *object, SculptUndoType type)
|
||||
{
|
||||
SculptUndoNode *unode = MEM_callocN(sizeof(SculptUndoNode), "SculptUndoNode");
|
||||
const size_t alloc_size = sizeof(SculptUndoNode);
|
||||
SculptUndoNode *unode = MEM_callocN(alloc_size, "SculptUndoNode");
|
||||
BLI_strncpy(unode->idname, object->id.name, sizeof(unode->idname));
|
||||
unode->type = type;
|
||||
|
||||
UndoSculpt *usculpt = sculpt_undo_get_nodes();
|
||||
BLI_addtail(&usculpt->nodes, unode);
|
||||
usculpt->undo_size += alloc_size;
|
||||
|
||||
return unode;
|
||||
}
|
||||
|
@ -975,7 +981,12 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node, Sculpt
|
|||
{
|
||||
UndoSculpt *usculpt = sculpt_undo_get_nodes();
|
||||
SculptSession *ss = ob->sculpt;
|
||||
int totvert, allvert, totgrid, maxgrid, gridsize, *grids;
|
||||
int totvert = 0;
|
||||
int allvert = 0;
|
||||
int totgrid = 0;
|
||||
int maxgrid = 0;
|
||||
int gridsize = 0;
|
||||
int *grids = NULL;
|
||||
|
||||
SculptUndoNode *unode = sculpt_undo_alloc_node_type(ob, type);
|
||||
unode->node = node;
|
||||
|
@ -986,39 +997,43 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node, Sculpt
|
|||
|
||||
unode->totvert = totvert;
|
||||
}
|
||||
else {
|
||||
maxgrid = 0;
|
||||
}
|
||||
|
||||
/* General TODO, fix count_alloc. */
|
||||
switch (type) {
|
||||
case SCULPT_UNDO_COORDS:
|
||||
unode->co = MEM_callocN(sizeof(float[3]) * allvert, "SculptUndoNode.co");
|
||||
unode->no = MEM_callocN(sizeof(short[3]) * allvert, "SculptUndoNode.no");
|
||||
case SCULPT_UNDO_COORDS: {
|
||||
size_t alloc_size = sizeof(*unode->co) * (size_t)allvert;
|
||||
unode->co = MEM_callocN(alloc_size, "SculptUndoNode.co");
|
||||
usculpt->undo_size += alloc_size;
|
||||
|
||||
usculpt->undo_size = (sizeof(float[3]) + sizeof(short[3]) + sizeof(int)) * allvert;
|
||||
/* FIXME: Should explain why this is allocated here, to be freed in
|
||||
* `SCULPT_undo_push_end_ex()`? */
|
||||
alloc_size = sizeof(*unode->no) * (size_t)allvert;
|
||||
unode->no = MEM_callocN(alloc_size, "SculptUndoNode.no");
|
||||
usculpt->undo_size += alloc_size;
|
||||
break;
|
||||
case SCULPT_UNDO_HIDDEN:
|
||||
}
|
||||
case SCULPT_UNDO_HIDDEN: {
|
||||
if (maxgrid) {
|
||||
sculpt_undo_alloc_and_store_hidden(ss->pbvh, unode);
|
||||
usculpt->undo_size += sculpt_undo_alloc_and_store_hidden(ss->pbvh, unode);
|
||||
}
|
||||
else {
|
||||
unode->vert_hidden = BLI_BITMAP_NEW(allvert, "SculptUndoNode.vert_hidden");
|
||||
usculpt->undo_size += BLI_BITMAP_SIZE(allvert);
|
||||
}
|
||||
|
||||
break;
|
||||
case SCULPT_UNDO_MASK:
|
||||
unode->mask = MEM_callocN(sizeof(float) * allvert, "SculptUndoNode.mask");
|
||||
|
||||
usculpt->undo_size += (sizeof(float) * sizeof(int)) * allvert;
|
||||
|
||||
}
|
||||
case SCULPT_UNDO_MASK: {
|
||||
const size_t alloc_size = sizeof(*unode->mask) * (size_t)allvert;
|
||||
unode->mask = MEM_callocN(alloc_size, "SculptUndoNode.mask");
|
||||
usculpt->undo_size += alloc_size;
|
||||
break;
|
||||
case SCULPT_UNDO_COLOR:
|
||||
unode->col = MEM_callocN(sizeof(MPropCol) * allvert, "SculptUndoNode.col");
|
||||
|
||||
usculpt->undo_size += (sizeof(MPropCol) * sizeof(int)) * allvert;
|
||||
|
||||
}
|
||||
case SCULPT_UNDO_COLOR: {
|
||||
const size_t alloc_size = sizeof(*unode->col) * (size_t)allvert;
|
||||
unode->col = MEM_callocN(alloc_size, "SculptUndoNode.col");
|
||||
usculpt->undo_size += alloc_size;
|
||||
break;
|
||||
}
|
||||
case SCULPT_UNDO_DYNTOPO_BEGIN:
|
||||
case SCULPT_UNDO_DYNTOPO_END:
|
||||
case SCULPT_UNDO_DYNTOPO_SYMMETRIZE:
|
||||
|
@ -1033,16 +1048,24 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node, Sculpt
|
|||
unode->maxgrid = maxgrid;
|
||||
unode->totgrid = totgrid;
|
||||
unode->gridsize = gridsize;
|
||||
unode->grids = MEM_callocN(sizeof(int) * totgrid, "SculptUndoNode.grids");
|
||||
|
||||
const size_t alloc_size = sizeof(*unode->grids) * (size_t)totgrid;
|
||||
unode->grids = MEM_callocN(alloc_size, "SculptUndoNode.grids");
|
||||
usculpt->undo_size += alloc_size;
|
||||
}
|
||||
else {
|
||||
/* Regular mesh. */
|
||||
unode->maxvert = ss->totvert;
|
||||
unode->index = MEM_callocN(sizeof(int) * allvert, "SculptUndoNode.index");
|
||||
|
||||
const size_t alloc_size = sizeof(*unode->index) * (size_t)allvert;
|
||||
unode->index = MEM_callocN(alloc_size, "SculptUndoNode.index");
|
||||
usculpt->undo_size += alloc_size;
|
||||
}
|
||||
|
||||
if (ss->deform_modifiers_active) {
|
||||
unode->orig_co = MEM_callocN(allvert * sizeof(*unode->orig_co), "undoSculpt orig_cos");
|
||||
const size_t alloc_size = sizeof(*unode->orig_co) * (size_t)allvert;
|
||||
unode->orig_co = MEM_callocN(alloc_size, "undoSculpt orig_cos");
|
||||
usculpt->undo_size += alloc_size;
|
||||
}
|
||||
|
||||
return unode;
|
||||
|
@ -1364,6 +1387,7 @@ void SCULPT_undo_push_end_ex(const bool use_nested_undo)
|
|||
/* We don't need normals in the undo stack. */
|
||||
for (unode = usculpt->nodes.first; unode; unode = unode->next) {
|
||||
if (unode->no) {
|
||||
usculpt->undo_size -= MEM_allocN_len(unode->no);
|
||||
MEM_freeN(unode->no);
|
||||
unode->no = NULL;
|
||||
}
|
||||
|
|
|
@ -104,17 +104,11 @@ void ED_clip_buttons_register(ARegionType *art)
|
|||
void uiTemplateMovieClip(
|
||||
uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, bool compact)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
PointerRNA clipptr;
|
||||
MovieClip *clip;
|
||||
uiLayout *row, *split;
|
||||
uiBlock *block;
|
||||
|
||||
if (!ptr->data) {
|
||||
return;
|
||||
}
|
||||
|
||||
prop = RNA_struct_find_property(ptr, propname);
|
||||
PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
|
||||
if (!prop) {
|
||||
printf(
|
||||
"%s: property not found: %s.%s\n", __func__, RNA_struct_identifier(ptr->type), propname);
|
||||
|
@ -129,8 +123,8 @@ void uiTemplateMovieClip(
|
|||
return;
|
||||
}
|
||||
|
||||
clipptr = RNA_property_pointer_get(ptr, prop);
|
||||
clip = clipptr.data;
|
||||
PointerRNA clipptr = RNA_property_pointer_get(ptr, prop);
|
||||
MovieClip *clip = clipptr.data;
|
||||
|
||||
uiLayoutSetContextPointer(layout, "edit_movieclip", &clipptr);
|
||||
|
||||
|
@ -149,20 +143,18 @@ void uiTemplateMovieClip(
|
|||
}
|
||||
|
||||
if (clip) {
|
||||
uiLayout *col;
|
||||
|
||||
row = uiLayoutRow(layout, false);
|
||||
block = uiLayoutGetBlock(row);
|
||||
uiLayout *row = uiLayoutRow(layout, false);
|
||||
uiBlock *block = uiLayoutGetBlock(row);
|
||||
uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("File Path:"), 0, 19, 145, 19, NULL, 0, 0, 0, 0, "");
|
||||
|
||||
row = uiLayoutRow(layout, false);
|
||||
split = uiLayoutSplit(row, 0.0f, false);
|
||||
uiLayout *split = uiLayoutSplit(row, 0.0f, false);
|
||||
row = uiLayoutRow(split, true);
|
||||
|
||||
uiItemR(row, &clipptr, "filepath", 0, "", ICON_NONE);
|
||||
uiItemO(row, "", ICON_FILE_REFRESH, "clip.reload");
|
||||
|
||||
col = uiLayoutColumn(layout, false);
|
||||
uiLayout *col = uiLayoutColumn(layout, false);
|
||||
uiTemplateColorspaceSettings(col, &clipptr, "colorspace_settings");
|
||||
}
|
||||
}
|
||||
|
@ -171,17 +163,11 @@ void uiTemplateMovieClip(
|
|||
|
||||
void uiTemplateTrack(uiLayout *layout, PointerRNA *ptr, const char *propname)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
PointerRNA scopesptr;
|
||||
uiBlock *block;
|
||||
uiLayout *col;
|
||||
MovieClipScopes *scopes;
|
||||
|
||||
if (!ptr->data) {
|
||||
return;
|
||||
}
|
||||
|
||||
prop = RNA_struct_find_property(ptr, propname);
|
||||
PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
|
||||
if (!prop) {
|
||||
printf(
|
||||
"%s: property not found: %s.%s\n", __func__, RNA_struct_identifier(ptr->type), propname);
|
||||
|
@ -196,8 +182,8 @@ void uiTemplateTrack(uiLayout *layout, PointerRNA *ptr, const char *propname)
|
|||
return;
|
||||
}
|
||||
|
||||
scopesptr = RNA_property_pointer_get(ptr, prop);
|
||||
scopes = (MovieClipScopes *)scopesptr.data;
|
||||
PointerRNA scopesptr = RNA_property_pointer_get(ptr, prop);
|
||||
MovieClipScopes *scopes = (MovieClipScopes *)scopesptr.data;
|
||||
|
||||
if (scopes->track_preview_height < UI_UNIT_Y) {
|
||||
scopes->track_preview_height = UI_UNIT_Y;
|
||||
|
@ -206,8 +192,8 @@ void uiTemplateTrack(uiLayout *layout, PointerRNA *ptr, const char *propname)
|
|||
scopes->track_preview_height = UI_UNIT_Y * 20;
|
||||
}
|
||||
|
||||
col = uiLayoutColumn(layout, true);
|
||||
block = uiLayoutGetBlock(col);
|
||||
uiLayout *col = uiLayoutColumn(layout, true);
|
||||
uiBlock *block = uiLayoutGetBlock(col);
|
||||
|
||||
uiDefBut(block,
|
||||
UI_BTYPE_TRACK_PREVIEW,
|
||||
|
@ -319,8 +305,6 @@ static void marker_block_handler(bContext *C, void *arg_cb, int event)
|
|||
}
|
||||
else if (event == B_MARKER_PAT_DIM) {
|
||||
float dim[2], pat_dim[2], pat_min[2], pat_max[2];
|
||||
float scale_x, scale_y;
|
||||
int a;
|
||||
|
||||
BKE_tracking_marker_pattern_minmax(cb->marker, pat_min, pat_max);
|
||||
|
||||
|
@ -329,10 +313,10 @@ static void marker_block_handler(bContext *C, void *arg_cb, int event)
|
|||
dim[0] = cb->marker_pat[0] / width;
|
||||
dim[1] = cb->marker_pat[1] / height;
|
||||
|
||||
scale_x = dim[0] / pat_dim[0];
|
||||
scale_y = dim[1] / pat_dim[1];
|
||||
float scale_x = dim[0] / pat_dim[0];
|
||||
float scale_y = dim[1] / pat_dim[1];
|
||||
|
||||
for (a = 0; a < 4; a++) {
|
||||
for (int a = 0; a < 4; a++) {
|
||||
cb->marker->pattern_corners[a][0] *= scale_x;
|
||||
cb->marker->pattern_corners[a][1] *= scale_y;
|
||||
}
|
||||
|
@ -415,23 +399,11 @@ void uiTemplateMarker(uiLayout *layout,
|
|||
PointerRNA *trackptr,
|
||||
bool compact)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
uiBlock *block;
|
||||
uiBut *bt;
|
||||
PointerRNA clipptr;
|
||||
MovieClip *clip;
|
||||
MovieClipUser *user;
|
||||
MovieTrackingTrack *track;
|
||||
MovieTrackingMarker *marker;
|
||||
MarkerUpdateCb *cb;
|
||||
const char *tip;
|
||||
float pat_min[2], pat_max[2];
|
||||
|
||||
if (!ptr->data) {
|
||||
return;
|
||||
}
|
||||
|
||||
prop = RNA_struct_find_property(ptr, propname);
|
||||
PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
|
||||
if (!prop) {
|
||||
printf(
|
||||
"%s: property not found: %s.%s\n", __func__, RNA_struct_identifier(ptr->type), propname);
|
||||
|
@ -446,15 +418,15 @@ void uiTemplateMarker(uiLayout *layout,
|
|||
return;
|
||||
}
|
||||
|
||||
clipptr = RNA_property_pointer_get(ptr, prop);
|
||||
clip = (MovieClip *)clipptr.data;
|
||||
user = userptr->data;
|
||||
track = trackptr->data;
|
||||
PointerRNA clipptr = RNA_property_pointer_get(ptr, prop);
|
||||
MovieClip *clip = (MovieClip *)clipptr.data;
|
||||
MovieClipUser *user = userptr->data;
|
||||
MovieTrackingTrack *track = trackptr->data;
|
||||
|
||||
int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr);
|
||||
marker = BKE_tracking_marker_get(track, clip_framenr);
|
||||
MovieTrackingMarker *marker = BKE_tracking_marker_get(track, clip_framenr);
|
||||
|
||||
cb = MEM_callocN(sizeof(MarkerUpdateCb), "uiTemplateMarker update_cb");
|
||||
MarkerUpdateCb *cb = MEM_callocN(sizeof(MarkerUpdateCb), "uiTemplateMarker update_cb");
|
||||
cb->compact = compact;
|
||||
cb->clip = clip;
|
||||
cb->user = user;
|
||||
|
@ -464,7 +436,8 @@ void uiTemplateMarker(uiLayout *layout,
|
|||
cb->framenr = user->framenr;
|
||||
|
||||
if (compact) {
|
||||
block = uiLayoutGetBlock(layout);
|
||||
const char *tip;
|
||||
uiBlock *block = uiLayoutGetBlock(layout);
|
||||
|
||||
if (cb->marker_flag & MARKER_DISABLED) {
|
||||
tip = TIP_("Marker is disabled at current frame");
|
||||
|
@ -473,34 +446,32 @@ void uiTemplateMarker(uiLayout *layout,
|
|||
tip = TIP_("Marker is enabled at current frame");
|
||||
}
|
||||
|
||||
bt = uiDefIconButBitI(block,
|
||||
UI_BTYPE_TOGGLE_N,
|
||||
MARKER_DISABLED,
|
||||
0,
|
||||
ICON_HIDE_OFF,
|
||||
0,
|
||||
0,
|
||||
UI_UNIT_X,
|
||||
UI_UNIT_Y,
|
||||
&cb->marker_flag,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
tip);
|
||||
uiBut *bt = uiDefIconButBitI(block,
|
||||
UI_BTYPE_TOGGLE_N,
|
||||
MARKER_DISABLED,
|
||||
0,
|
||||
ICON_HIDE_OFF,
|
||||
0,
|
||||
0,
|
||||
UI_UNIT_X,
|
||||
UI_UNIT_Y,
|
||||
&cb->marker_flag,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
tip);
|
||||
UI_but_funcN_set(bt, marker_update_cb, cb, NULL);
|
||||
UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
|
||||
}
|
||||
else {
|
||||
int width, height, step, digits;
|
||||
float pat_dim[2], search_dim[2], search_pos[2];
|
||||
uiLayout *col;
|
||||
int width, height;
|
||||
|
||||
BKE_movieclip_get_size(clip, user, &width, &height);
|
||||
|
||||
if (track->flag & TRACK_LOCKED) {
|
||||
uiLayoutSetActive(layout, false);
|
||||
block = uiLayoutAbsoluteBlock(layout);
|
||||
uiBlock *block = uiLayoutAbsoluteBlock(layout);
|
||||
uiDefBut(block,
|
||||
UI_BTYPE_LABEL,
|
||||
0,
|
||||
|
@ -519,8 +490,8 @@ void uiTemplateMarker(uiLayout *layout,
|
|||
return;
|
||||
}
|
||||
|
||||
step = 100;
|
||||
digits = 2;
|
||||
float pat_min[2], pat_max[2];
|
||||
float pat_dim[2], search_dim[2], search_pos[2];
|
||||
|
||||
BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
|
||||
|
||||
|
@ -538,10 +509,14 @@ void uiTemplateMarker(uiLayout *layout,
|
|||
|
||||
cb->marker_flag = marker->flag;
|
||||
|
||||
block = uiLayoutAbsoluteBlock(layout);
|
||||
uiBlock *block = uiLayoutAbsoluteBlock(layout);
|
||||
UI_block_func_handle_set(block, marker_block_handler, cb);
|
||||
UI_block_funcN_set(block, marker_update_cb, cb, NULL);
|
||||
|
||||
const char *tip;
|
||||
int step = 100;
|
||||
int digits = 2;
|
||||
|
||||
if (cb->marker_flag & MARKER_DISABLED) {
|
||||
tip = TIP_("Marker is disabled at current frame");
|
||||
}
|
||||
|
@ -565,7 +540,7 @@ void uiTemplateMarker(uiLayout *layout,
|
|||
0,
|
||||
tip);
|
||||
|
||||
col = uiLayoutColumn(layout, true);
|
||||
uiLayout *col = uiLayoutColumn(layout, true);
|
||||
uiLayoutSetActive(col, (cb->marker_flag & MARKER_DISABLED) == 0);
|
||||
|
||||
block = uiLayoutAbsoluteBlock(col);
|
||||
|
@ -585,20 +560,20 @@ void uiTemplateMarker(uiLayout *layout,
|
|||
0,
|
||||
0,
|
||||
"");
|
||||
bt = uiDefButF(block,
|
||||
UI_BTYPE_NUM,
|
||||
B_MARKER_POS,
|
||||
IFACE_("X:"),
|
||||
0.5 * UI_UNIT_X,
|
||||
9 * UI_UNIT_Y,
|
||||
7.25 * UI_UNIT_X,
|
||||
UI_UNIT_Y,
|
||||
&cb->marker_pos[0],
|
||||
-10 * width,
|
||||
10.0 * width,
|
||||
0,
|
||||
0,
|
||||
TIP_("X-position of marker at frame in screen coordinates"));
|
||||
uiBut *bt = uiDefButF(block,
|
||||
UI_BTYPE_NUM,
|
||||
B_MARKER_POS,
|
||||
IFACE_("X:"),
|
||||
0.5 * UI_UNIT_X,
|
||||
9 * UI_UNIT_Y,
|
||||
7.25 * UI_UNIT_X,
|
||||
UI_UNIT_Y,
|
||||
&cb->marker_pos[0],
|
||||
-10 * width,
|
||||
10.0 * width,
|
||||
0,
|
||||
0,
|
||||
TIP_("X-position of marker at frame in screen coordinates"));
|
||||
UI_but_number_step_size_set(bt, step);
|
||||
UI_but_number_precision_set(bt, digits);
|
||||
bt = uiDefButF(block,
|
||||
|
@ -802,21 +777,11 @@ void uiTemplateMovieclipInformation(uiLayout *layout,
|
|||
const char *propname,
|
||||
PointerRNA *userptr)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
PointerRNA clipptr;
|
||||
MovieClip *clip;
|
||||
MovieClipUser *user;
|
||||
uiLayout *col;
|
||||
char str[1024];
|
||||
int width, height, framenr;
|
||||
ImBuf *ibuf;
|
||||
size_t ofs = 0;
|
||||
|
||||
if (!ptr->data) {
|
||||
return;
|
||||
}
|
||||
|
||||
prop = RNA_struct_find_property(ptr, propname);
|
||||
PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
|
||||
if (!prop) {
|
||||
printf(
|
||||
"%s: property not found: %s.%s\n", __func__, RNA_struct_identifier(ptr->type), propname);
|
||||
|
@ -831,17 +796,21 @@ void uiTemplateMovieclipInformation(uiLayout *layout,
|
|||
return;
|
||||
}
|
||||
|
||||
clipptr = RNA_property_pointer_get(ptr, prop);
|
||||
clip = (MovieClip *)clipptr.data;
|
||||
user = userptr->data;
|
||||
PointerRNA clipptr = RNA_property_pointer_get(ptr, prop);
|
||||
MovieClip *clip = (MovieClip *)clipptr.data;
|
||||
MovieClipUser *user = userptr->data;
|
||||
|
||||
col = uiLayoutColumn(layout, false);
|
||||
uiLayout *col = uiLayoutColumn(layout, false);
|
||||
uiLayoutSetAlignment(col, UI_LAYOUT_ALIGN_RIGHT);
|
||||
|
||||
ibuf = BKE_movieclip_get_ibuf_flag(clip, user, clip->flag, MOVIECLIP_CACHE_SKIP);
|
||||
ImBuf *ibuf = BKE_movieclip_get_ibuf_flag(clip, user, clip->flag, MOVIECLIP_CACHE_SKIP);
|
||||
|
||||
int width, height;
|
||||
/* Display frame dimensions, channels number and byffer type. */
|
||||
BKE_movieclip_get_size(clip, user, &width, &height);
|
||||
|
||||
char str[1024];
|
||||
size_t ofs = 0;
|
||||
ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, TIP_("%d x %d"), width, height);
|
||||
|
||||
if (ibuf) {
|
||||
|
@ -882,7 +851,7 @@ void uiTemplateMovieclipInformation(uiLayout *layout,
|
|||
uiItemL(col, str, ICON_NONE);
|
||||
|
||||
/* Display current frame number. */
|
||||
framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr);
|
||||
int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr);
|
||||
if (framenr <= clip->len) {
|
||||
BLI_snprintf(str, sizeof(str), TIP_("Frame: %d / %d"), framenr, clip->len);
|
||||
}
|
||||
|
|
|
@ -1142,7 +1142,9 @@ void ED_fileselect_exit(wmWindowManager *wm, Scene *owner_scene, SpaceFile *sfil
|
|||
return;
|
||||
}
|
||||
if (sfile->op) {
|
||||
wmWindow *temp_win = WM_window_is_temp_screen(wm->winactive) ? wm->winactive : NULL;
|
||||
wmWindow *temp_win = (wm->winactive && WM_window_is_temp_screen(wm->winactive)) ?
|
||||
wm->winactive :
|
||||
NULL;
|
||||
if (temp_win) {
|
||||
int win_size[2];
|
||||
bool is_maximized;
|
||||
|
|
|
@ -3260,6 +3260,25 @@ static void node_geometry_buts_attribute_color_ramp(uiLayout *layout,
|
|||
uiTemplateColorRamp(layout, ptr, "color_ramp", 0);
|
||||
}
|
||||
|
||||
static void node_geometry_buts_rotate_points(uiLayout *layout,
|
||||
bContext *UNUSED(C),
|
||||
PointerRNA *ptr)
|
||||
{
|
||||
NodeGeometryRotatePoints *storage = (NodeGeometryRotatePoints *)((bNode *)ptr->data)->storage;
|
||||
|
||||
uiItemR(layout, ptr, "type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE);
|
||||
uiItemR(layout, ptr, "space", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE);
|
||||
|
||||
uiLayout *col = uiLayoutColumn(layout, false);
|
||||
if (storage->type == GEO_NODE_ROTATE_POINTS_TYPE_AXIS_ANGLE) {
|
||||
uiItemR(col, ptr, "input_type_axis", DEFAULT_FLAGS, IFACE_("Axis"), ICON_NONE);
|
||||
uiItemR(col, ptr, "input_type_angle", DEFAULT_FLAGS, IFACE_("Angle"), ICON_NONE);
|
||||
}
|
||||
else {
|
||||
uiItemR(col, ptr, "input_type_rotation", DEFAULT_FLAGS, IFACE_("Rotation"), ICON_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
static void node_geometry_set_butfunc(bNodeType *ntype)
|
||||
{
|
||||
switch (ntype->type) {
|
||||
|
@ -3296,6 +3315,9 @@ static void node_geometry_set_butfunc(bNodeType *ntype)
|
|||
case GEO_NODE_ATTRIBUTE_COLOR_RAMP:
|
||||
ntype->draw_buttons = node_geometry_buts_attribute_color_ramp;
|
||||
break;
|
||||
case GEO_NODE_ROTATE_POINTS:
|
||||
ntype->draw_buttons = node_geometry_buts_rotate_points;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,50 +29,34 @@
|
|||
|
||||
#include "DNA_armature_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_packedFile_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
|
||||
#include "BLI_fileops.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_path_util.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_icons.h"
|
||||
#include "BKE_layer.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_material.h"
|
||||
#include "BKE_multires.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_packedFile.h"
|
||||
#include "BKE_paint.h"
|
||||
#include "BKE_report.h"
|
||||
#include "BKE_screen.h"
|
||||
#include "BKE_undo_system.h"
|
||||
#include "BKE_workspace.h"
|
||||
|
||||
#include "DEG_depsgraph.h"
|
||||
|
||||
#include "ED_armature.h"
|
||||
#include "ED_image.h"
|
||||
#include "ED_mesh.h"
|
||||
#include "ED_node.h"
|
||||
#include "ED_object.h"
|
||||
#include "ED_outliner.h"
|
||||
#include "ED_paint.h"
|
||||
#include "ED_render.h"
|
||||
#include "ED_space_api.h"
|
||||
#include "ED_util.h"
|
||||
|
||||
#include "GPU_immediate.h"
|
||||
#include "GPU_state.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
|
@ -484,104 +468,3 @@ void ED_spacedata_id_remap(struct ScrArea *area, struct SpaceLink *sl, ID *old_i
|
|||
st->id_remap(area, sl, old_id, new_id);
|
||||
}
|
||||
}
|
||||
|
||||
static bool lib_id_preview_editing_poll(bContext *C)
|
||||
{
|
||||
const PointerRNA idptr = CTX_data_pointer_get(C, "id");
|
||||
BLI_assert(!idptr.data || RNA_struct_is_ID(idptr.type));
|
||||
|
||||
const ID *id = idptr.data;
|
||||
if (!id) {
|
||||
return false;
|
||||
}
|
||||
if (ID_IS_LINKED(id)) {
|
||||
CTX_wm_operator_poll_msg_set(C, TIP_("Can't edit external library data"));
|
||||
return false;
|
||||
}
|
||||
if (ID_IS_OVERRIDE_LIBRARY(id)) {
|
||||
CTX_wm_operator_poll_msg_set(C, TIP_("Can't edit previews of overridden library data"));
|
||||
return false;
|
||||
}
|
||||
if (!BKE_previewimg_id_get_p(id)) {
|
||||
CTX_wm_operator_poll_msg_set(C, TIP_("Data-block does not support previews"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int lib_id_load_custom_preview_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
char path[FILE_MAX];
|
||||
|
||||
RNA_string_get(op->ptr, "filepath", path);
|
||||
|
||||
if (!BLI_is_file(path)) {
|
||||
BKE_reportf(op->reports, RPT_ERROR, "File not found '%s'", path);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
PointerRNA idptr = CTX_data_pointer_get(C, "id");
|
||||
ID *id = idptr.data;
|
||||
|
||||
BKE_previewimg_id_custom_set(id, path);
|
||||
|
||||
WM_event_add_notifier(C, NC_ASSET, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void ED_OT_lib_id_load_custom_preview(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Load Custom Preview";
|
||||
ot->description = "Choose an image to help identify the data-block visually";
|
||||
ot->idname = "ED_OT_lib_id_load_custom_preview";
|
||||
|
||||
/* api callbacks */
|
||||
ot->poll = lib_id_preview_editing_poll;
|
||||
ot->exec = lib_id_load_custom_preview_exec;
|
||||
ot->invoke = WM_operator_filesel;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_INTERNAL;
|
||||
|
||||
WM_operator_properties_filesel(ot,
|
||||
FILE_TYPE_FOLDER | FILE_TYPE_IMAGE,
|
||||
FILE_SPECIAL,
|
||||
FILE_OPENFILE,
|
||||
WM_FILESEL_FILEPATH,
|
||||
FILE_DEFAULTDISPLAY,
|
||||
FILE_SORT_DEFAULT);
|
||||
}
|
||||
|
||||
static int lib_id_generate_preview_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
PointerRNA idptr = CTX_data_pointer_get(C, "id");
|
||||
ID *id = idptr.data;
|
||||
|
||||
ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
|
||||
|
||||
PreviewImage *preview = BKE_previewimg_id_get(id);
|
||||
if (preview) {
|
||||
BKE_previewimg_clear(preview);
|
||||
}
|
||||
UI_icon_render_id(C, NULL, id, true, true);
|
||||
|
||||
WM_event_add_notifier(C, NC_ASSET, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void ED_OT_lib_id_generate_preview(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Generate Preview";
|
||||
ot->description = "Create an automatic preview for the selected data-block";
|
||||
ot->idname = "ED_OT_lib_id_generate_preview";
|
||||
|
||||
/* api callbacks */
|
||||
ot->poll = lib_id_preview_editing_poll;
|
||||
ot->exec = lib_id_generate_preview_exec;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_INTERNAL;
|
||||
}
|
||||
|
|
|
@ -22,15 +22,22 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
#include "BLI_fileops.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_icons.h"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_report.h"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "DNA_space_types.h"
|
||||
#include "DNA_windowmanager_types.h"
|
||||
|
||||
#include "ED_render.h"
|
||||
#include "ED_undo.h"
|
||||
#include "ED_util.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
@ -40,7 +47,118 @@
|
|||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
static int lib_fake_user_toggle_exec(bContext *C, wmOperator *op)
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name ID Previews
|
||||
* \{ */
|
||||
|
||||
static bool lib_id_preview_editing_poll(bContext *C)
|
||||
{
|
||||
const PointerRNA idptr = CTX_data_pointer_get(C, "id");
|
||||
BLI_assert(!idptr.data || RNA_struct_is_ID(idptr.type));
|
||||
|
||||
const ID *id = idptr.data;
|
||||
if (!id) {
|
||||
return false;
|
||||
}
|
||||
if (ID_IS_LINKED(id)) {
|
||||
CTX_wm_operator_poll_msg_set(C, TIP_("Can't edit external library data"));
|
||||
return false;
|
||||
}
|
||||
if (ID_IS_OVERRIDE_LIBRARY(id)) {
|
||||
CTX_wm_operator_poll_msg_set(C, TIP_("Can't edit previews of overridden library data"));
|
||||
return false;
|
||||
}
|
||||
if (!BKE_previewimg_id_get_p(id)) {
|
||||
CTX_wm_operator_poll_msg_set(C, TIP_("Data-block does not support previews"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int lib_id_load_custom_preview_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
char path[FILE_MAX];
|
||||
|
||||
RNA_string_get(op->ptr, "filepath", path);
|
||||
|
||||
if (!BLI_is_file(path)) {
|
||||
BKE_reportf(op->reports, RPT_ERROR, "File not found '%s'", path);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
PointerRNA idptr = CTX_data_pointer_get(C, "id");
|
||||
ID *id = idptr.data;
|
||||
|
||||
BKE_previewimg_id_custom_set(id, path);
|
||||
|
||||
WM_event_add_notifier(C, NC_ASSET, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void ED_OT_lib_id_load_custom_preview(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Load Custom Preview";
|
||||
ot->description = "Choose an image to help identify the data-block visually";
|
||||
ot->idname = "ED_OT_lib_id_load_custom_preview";
|
||||
|
||||
/* api callbacks */
|
||||
ot->poll = lib_id_preview_editing_poll;
|
||||
ot->exec = lib_id_load_custom_preview_exec;
|
||||
ot->invoke = WM_operator_filesel;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_INTERNAL;
|
||||
|
||||
WM_operator_properties_filesel(ot,
|
||||
FILE_TYPE_FOLDER | FILE_TYPE_IMAGE,
|
||||
FILE_SPECIAL,
|
||||
FILE_OPENFILE,
|
||||
WM_FILESEL_FILEPATH,
|
||||
FILE_DEFAULTDISPLAY,
|
||||
FILE_SORT_DEFAULT);
|
||||
}
|
||||
|
||||
static int lib_id_generate_preview_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
PointerRNA idptr = CTX_data_pointer_get(C, "id");
|
||||
ID *id = idptr.data;
|
||||
|
||||
ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
|
||||
|
||||
PreviewImage *preview = BKE_previewimg_id_get(id);
|
||||
if (preview) {
|
||||
BKE_previewimg_clear(preview);
|
||||
}
|
||||
UI_icon_render_id(C, NULL, id, true, true);
|
||||
|
||||
WM_event_add_notifier(C, NC_ASSET, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void ED_OT_lib_id_generate_preview(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Generate Preview";
|
||||
ot->description = "Create an automatic preview for the selected data-block";
|
||||
ot->idname = "ED_OT_lib_id_generate_preview";
|
||||
|
||||
/* api callbacks */
|
||||
ot->poll = lib_id_preview_editing_poll;
|
||||
ot->exec = lib_id_generate_preview_exec;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_INTERNAL;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Generic ID Operators
|
||||
* \{ */
|
||||
|
||||
static int lib_id_fake_user_toggle_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
PropertyPointerRNA pprop;
|
||||
PointerRNA idptr = PointerRNA_NULL;
|
||||
|
@ -74,21 +192,21 @@ static int lib_fake_user_toggle_exec(bContext *C, wmOperator *op)
|
|||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void ED_OT_lib_fake_user_toggle(wmOperatorType *ot)
|
||||
static void ED_OT_lib_id_fake_user_toggle(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Toggle Fake User";
|
||||
ot->description = "Save this data-block even if it has no users";
|
||||
ot->idname = "ED_OT_lib_fake_user_toggle";
|
||||
ot->idname = "ED_OT_lib_id_fake_user_toggle";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = lib_fake_user_toggle_exec;
|
||||
ot->exec = lib_id_fake_user_toggle_exec;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
|
||||
}
|
||||
|
||||
static int lib_unlink_exec(bContext *C, wmOperator *op)
|
||||
static int lib_id_unlink_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
PropertyPointerRNA pprop;
|
||||
PointerRNA idptr;
|
||||
|
@ -112,20 +230,26 @@ static int lib_unlink_exec(bContext *C, wmOperator *op)
|
|||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void ED_OT_lib_unlink(wmOperatorType *ot)
|
||||
static void ED_OT_lib_id_unlink(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Unlink Data-Block";
|
||||
ot->description = "Remove a usage of a data-block, clearing the assignment";
|
||||
ot->idname = "ED_OT_lib_unlink";
|
||||
ot->idname = "ED_OT_lib_id_unlink";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = lib_unlink_exec;
|
||||
ot->exec = lib_id_unlink_exec;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name General editor utils.
|
||||
* \{ */
|
||||
|
||||
static int ed_flush_edits_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
|
@ -147,9 +271,21 @@ static void ED_OT_flush_edits(wmOperatorType *ot)
|
|||
ot->flag = OPTYPE_INTERNAL;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
void ED_operatortypes_edutils(void)
|
||||
{
|
||||
WM_operatortype_append(ED_OT_lib_fake_user_toggle);
|
||||
WM_operatortype_append(ED_OT_lib_unlink);
|
||||
WM_operatortype_append(ED_OT_lib_id_load_custom_preview);
|
||||
WM_operatortype_append(ED_OT_lib_id_generate_preview);
|
||||
|
||||
WM_operatortype_append(ED_OT_lib_id_fake_user_toggle);
|
||||
WM_operatortype_append(ED_OT_lib_id_unlink);
|
||||
|
||||
WM_operatortype_append(ED_OT_flush_edits);
|
||||
|
||||
WM_operatortype_append(ED_OT_undo);
|
||||
WM_operatortype_append(ED_OT_undo_push);
|
||||
WM_operatortype_append(ED_OT_redo);
|
||||
WM_operatortype_append(ED_OT_undo_redo);
|
||||
WM_operatortype_append(ED_OT_undo_history);
|
||||
}
|
||||
|
|
|
@ -113,6 +113,7 @@
|
|||
.flip_ratio = 0.97f, \
|
||||
.sys_particle_maximum = 0, \
|
||||
.simulation_method = FLUID_DOMAIN_METHOD_FLIP, \
|
||||
.viscosity_value = 0.05f, \
|
||||
.surface_tension = 0.0f, \
|
||||
.viscosity_base = 1.0f, \
|
||||
.viscosity_exponent = 6.0f, \
|
||||
|
|
|
@ -52,6 +52,7 @@ enum {
|
|||
FLUID_DOMAIN_DELETE_IN_OBSTACLE = (1 << 14), /* Delete fluid inside obstacles. */
|
||||
FLUID_DOMAIN_USE_DIFFUSION = (1 << 15), /* Use diffusion (e.g. viscosity, surface tension). */
|
||||
FLUID_DOMAIN_USE_RESUMABLE_CACHE = (1 << 16), /* Determine if cache should be resumable. */
|
||||
FLUID_DOMAIN_USE_VISCOSITY = (1 << 17), /* Use viscosity. */
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -596,6 +597,10 @@ typedef struct FluidDomainSettings {
|
|||
short simulation_method;
|
||||
char _pad4[6];
|
||||
|
||||
/* Viscosity options. */
|
||||
float viscosity_value;
|
||||
char _pad5[4];
|
||||
|
||||
/* Diffusion options. */
|
||||
float surface_tension;
|
||||
float viscosity_base;
|
||||
|
@ -610,7 +615,7 @@ typedef struct FluidDomainSettings {
|
|||
int mesh_scale;
|
||||
int totvert;
|
||||
short mesh_generator;
|
||||
char _pad5[6]; /* Unused. */
|
||||
char _pad6[6]; /* Unused. */
|
||||
|
||||
/* Secondary particle options. */
|
||||
int particle_type;
|
||||
|
@ -631,7 +636,7 @@ typedef struct FluidDomainSettings {
|
|||
int sndparticle_update_radius;
|
||||
char sndparticle_boundary;
|
||||
char sndparticle_combined_export;
|
||||
char _pad6[6]; /* Unused. */
|
||||
char _pad7[6]; /* Unused. */
|
||||
|
||||
/* Fluid guiding options. */
|
||||
float guide_alpha; /* Guiding weight scalar (determines strength). */
|
||||
|
@ -639,7 +644,7 @@ typedef struct FluidDomainSettings {
|
|||
float guide_vel_factor; /* Multiply guiding velocity by this factor. */
|
||||
int guide_res[3]; /* Res for velocity guide grids - independent from base res. */
|
||||
short guide_source;
|
||||
char _pad7[2]; /* Unused. */
|
||||
char _pad8[2]; /* Unused. */
|
||||
|
||||
/* Cache options. */
|
||||
int cache_frame_start;
|
||||
|
@ -659,7 +664,7 @@ typedef struct FluidDomainSettings {
|
|||
char error[64]; /* Bake error description. */
|
||||
short cache_type;
|
||||
char cache_id[4]; /* Run-time only */
|
||||
char _pad8[2];
|
||||
char _pad9[2]; /* Unused. */
|
||||
|
||||
/* Time options. */
|
||||
float dt;
|
||||
|
@ -694,19 +699,19 @@ typedef struct FluidDomainSettings {
|
|||
char interp_method;
|
||||
char gridlines_color_field; /* Simulation field used to color map onto gridlines. */
|
||||
char gridlines_cell_filter;
|
||||
char _pad9[7];
|
||||
char _pad10[7]; /* Unused. */
|
||||
|
||||
/* OpenVDB cache options. */
|
||||
int openvdb_compression;
|
||||
float clipping;
|
||||
char openvdb_data_depth;
|
||||
char _pad10[7]; /* Unused. */
|
||||
char _pad11[7]; /* Unused. */
|
||||
|
||||
/* -- Deprecated / unsed options (below). -- */
|
||||
|
||||
/* View options. */
|
||||
int viewsettings;
|
||||
char _pad11[4]; /* Unused. */
|
||||
char _pad12[4]; /* Unused. */
|
||||
|
||||
/* Pointcache options. */
|
||||
/* Smoke uses only one cache from now on (index [0]), but keeping the array for now for reading
|
||||
|
@ -716,7 +721,7 @@ typedef struct FluidDomainSettings {
|
|||
int cache_comp;
|
||||
int cache_high_comp;
|
||||
char cache_file_format;
|
||||
char _pad12[7]; /* Unused. */
|
||||
char _pad13[7]; /* Unused. */
|
||||
|
||||
} FluidDomainSettings;
|
||||
|
||||
|
|
|
@ -1111,6 +1111,19 @@ typedef struct NodeInputVector {
|
|||
float vector[3];
|
||||
} NodeInputVector;
|
||||
|
||||
typedef struct NodeGeometryRotatePoints {
|
||||
/* GeometryNodeRotatePointsType */
|
||||
uint8_t type;
|
||||
/* GeometryNodeRotatePointsSpace */
|
||||
uint8_t space;
|
||||
|
||||
/* GeometryNodeAttributeInputMode */
|
||||
uint8_t input_type_axis;
|
||||
uint8_t input_type_angle;
|
||||
uint8_t input_type_rotation;
|
||||
char _pad[3];
|
||||
} NodeGeometryRotatePoints;
|
||||
|
||||
/* script node mode */
|
||||
#define NODE_SCRIPT_INTERNAL 0
|
||||
#define NODE_SCRIPT_EXTERNAL 1
|
||||
|
@ -1529,6 +1542,16 @@ typedef enum GeometryNodePointDistributeMethod {
|
|||
GEO_NODE_POINT_DISTRIBUTE_POISSON = 1,
|
||||
} GeometryNodePointDistributeMethod;
|
||||
|
||||
typedef enum GeometryNodeRotatePointsType {
|
||||
GEO_NODE_ROTATE_POINTS_TYPE_EULER = 0,
|
||||
GEO_NODE_ROTATE_POINTS_TYPE_AXIS_ANGLE = 1,
|
||||
} GeometryNodeRotatePointsType;
|
||||
|
||||
typedef enum GeometryNodeRotatePointsSpace {
|
||||
GEO_NODE_ROTATE_POINTS_SPACE_OBJECT = 0,
|
||||
GEO_NODE_ROTATE_POINTS_SPACE_POINT = 1,
|
||||
} GeometryNodeRotatePointsSpace;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1929,6 +1929,22 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
|
|||
"Maximum number of fluid particles that are allowed in this simulation");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
|
||||
|
||||
/* viscosity options */
|
||||
|
||||
prop = RNA_def_property(srna, "use_viscosity", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_DOMAIN_USE_VISCOSITY);
|
||||
RNA_def_property_ui_text(prop, "Use Viscosity", "Enable fluid viscosity settings");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
|
||||
|
||||
prop = RNA_def_property(srna, "viscosity_value", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_range(prop, 0.0, 10.0);
|
||||
RNA_def_property_ui_range(prop, 0.0, 5.0, 0.01, 3);
|
||||
RNA_def_property_ui_text(prop,
|
||||
"Strength",
|
||||
"Viscosity of liquid (higher values result in more viscous fluids, a "
|
||||
"value of 0 will still apply some viscosity)");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
|
||||
|
||||
/* diffusion options */
|
||||
|
||||
prop = RNA_def_property(srna, "use_diffusion", PROP_BOOLEAN, PROP_NONE);
|
||||
|
|
|
@ -452,6 +452,11 @@ static const EnumPropertyItem rna_node_geometry_attribute_input_type_items_float
|
|||
ITEM_FLOAT,
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
static const EnumPropertyItem rna_node_geometry_attribute_input_type_items_vector[] = {
|
||||
ITEM_ATTRIBUTE,
|
||||
ITEM_VECTOR,
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
static const EnumPropertyItem rna_node_geometry_attribute_input_type_items_no_boolean[] = {
|
||||
ITEM_ATTRIBUTE,
|
||||
ITEM_FLOAT,
|
||||
|
@ -8584,6 +8589,66 @@ static void def_geo_attribute_color_ramp(StructRNA *srna)
|
|||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
}
|
||||
|
||||
static void def_geo_rotate_points(StructRNA *srna)
|
||||
{
|
||||
static const EnumPropertyItem type_items[] = {
|
||||
{GEO_NODE_ROTATE_POINTS_TYPE_AXIS_ANGLE,
|
||||
"AXIS_ANGLE",
|
||||
ICON_NONE,
|
||||
"Axis Angle",
|
||||
"Rotate around an axis by an angle"},
|
||||
{GEO_NODE_ROTATE_POINTS_TYPE_EULER,
|
||||
"EULER",
|
||||
ICON_NONE,
|
||||
"Euler",
|
||||
"Rotate around the x, y and z axis"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
static const EnumPropertyItem space_items[] = {
|
||||
{GEO_NODE_ROTATE_POINTS_SPACE_OBJECT,
|
||||
"OBJECT",
|
||||
ICON_NONE,
|
||||
"Object",
|
||||
"Rotate points in the local space of the object"},
|
||||
{GEO_NODE_ROTATE_POINTS_SPACE_POINT,
|
||||
"POINT",
|
||||
ICON_NONE,
|
||||
"Point",
|
||||
"Rotate every point in its local space (as defined by the 'rotation' attribute)"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
PropertyRNA *prop;
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "NodeGeometryRotatePoints", "storage");
|
||||
|
||||
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, type_items);
|
||||
RNA_def_property_ui_text(prop, "Type", "Method used to describe the rotation");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
|
||||
|
||||
prop = RNA_def_property(srna, "space", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, space_items);
|
||||
RNA_def_property_ui_text(prop, "Space", "Base orientation of the points");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
|
||||
prop = RNA_def_property(srna, "input_type_axis", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_vector);
|
||||
RNA_def_property_ui_text(prop, "Input Type Axis", "");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
|
||||
|
||||
prop = RNA_def_property(srna, "input_type_angle", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_float);
|
||||
RNA_def_property_ui_text(prop, "Input Type Angle", "");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
|
||||
|
||||
prop = RNA_def_property(srna, "input_type_rotation", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_vector);
|
||||
RNA_def_property_ui_text(prop, "Input Type Rotation", "");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static void rna_def_shader_node(BlenderRNA *brna)
|
||||
|
|
|
@ -4241,8 +4241,9 @@ void rna_def_view_layer_common(StructRNA *srna, const bool scene)
|
|||
|
||||
prop = RNA_def_property(srna, "use_ztransp", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "layflag", SCE_LAY_ZTRA);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Z-Transparent", "Render Z-transparent faces in this layer (on top of Solid and Halos)");
|
||||
RNA_def_property_ui_text(prop,
|
||||
"Z-Transparent",
|
||||
"Render Z-transparent faces in this layer (on top of Solid and Halos)");
|
||||
if (scene) {
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
|
||||
}
|
||||
|
|
|
@ -155,6 +155,7 @@ set(SRC
|
|||
geometry/nodes/node_geo_point_distribute_poisson_disk.cc
|
||||
geometry/nodes/node_geo_point_instance.cc
|
||||
geometry/nodes/node_geo_point_separate.cc
|
||||
geometry/nodes/node_geo_rotate_points.cc
|
||||
geometry/nodes/node_geo_subdivision_surface.cc
|
||||
geometry/nodes/node_geo_transform.cc
|
||||
geometry/nodes/node_geo_triangulate.cc
|
||||
|
|
|
@ -42,6 +42,7 @@ void register_node_type_geo_point_separate(void);
|
|||
void register_node_type_geo_attribute_compare(void);
|
||||
void register_node_type_geo_attribute_mix(void);
|
||||
void register_node_type_geo_attribute_color_ramp(void);
|
||||
void register_node_type_geo_rotate_points(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -284,6 +284,7 @@ DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_MIX, def_geo_attribute_mix, "ATTRIBUTE_
|
|||
DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_COLOR_RAMP, def_geo_attribute_color_ramp, "ATTRIBUTE_COLOR_RAMP", AttributeColorRamp, "Attribute Color Ramp", "")
|
||||
DefNode(GeometryNode, GEO_NODE_POINT_SEPARATE, 0, "POINT_SEPARATE", PointSeparate, "Point Separate", "")
|
||||
DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_COMPARE, def_geo_attribute_attribute_compare, "ATTRIBUTE_COMPARE", AttributeCompare, "Attribute Compare", "")
|
||||
DefNode(GeometryNode, GEO_NODE_ROTATE_POINTS, def_geo_rotate_points, "ROTATE_POINTS", RotatePoints, "Rotate Points", "")
|
||||
|
||||
/* undefine macros */
|
||||
#undef DefNode
|
||||
|
|
|
@ -19,19 +19,28 @@
|
|||
|
||||
namespace blender::nodes {
|
||||
|
||||
/**
|
||||
* Update the availability of a group of input sockets with the same name,
|
||||
* used for switching between attribute inputs or single values.
|
||||
*
|
||||
* \param mode: Controls which socket of the group to make available.
|
||||
* \param name_is_available: If false, make all sockets with this name unavailable.
|
||||
*/
|
||||
void update_attribute_input_socket_availabilities(bNode &node,
|
||||
const StringRef name,
|
||||
const GeometryNodeAttributeInputMode mode)
|
||||
const GeometryNodeAttributeInputMode mode,
|
||||
const bool name_is_available)
|
||||
{
|
||||
const GeometryNodeAttributeInputMode mode_ = (GeometryNodeAttributeInputMode)mode;
|
||||
LISTBASE_FOREACH (bNodeSocket *, socket, &node.inputs) {
|
||||
if (name == socket->name) {
|
||||
const bool is_available =
|
||||
const bool socket_is_available =
|
||||
name_is_available &&
|
||||
((socket->type == SOCK_STRING && mode_ == GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE) ||
|
||||
(socket->type == SOCK_FLOAT && mode_ == GEO_NODE_ATTRIBUTE_INPUT_FLOAT) ||
|
||||
(socket->type == SOCK_VECTOR && mode_ == GEO_NODE_ATTRIBUTE_INPUT_VECTOR) ||
|
||||
(socket->type == SOCK_RGBA && mode_ == GEO_NODE_ATTRIBUTE_INPUT_COLOR));
|
||||
nodeSetSocketAvailability(socket, is_available);
|
||||
nodeSetSocketAvailability(socket, socket_is_available);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,8 @@ bool geo_node_poll_default(struct bNodeType *ntype, struct bNodeTree *ntree);
|
|||
namespace blender::nodes {
|
||||
void update_attribute_input_socket_availabilities(bNode &node,
|
||||
const StringRef name,
|
||||
const GeometryNodeAttributeInputMode mode);
|
||||
const GeometryNodeAttributeInputMode mode,
|
||||
const bool can_be_available = true);
|
||||
|
||||
CustomDataType attribute_domain_highest_complexity(Span<CustomDataType>);
|
||||
|
||||
|
|
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
* 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 "node_geometry_util.hh"
|
||||
|
||||
#include "BLI_math_rotation.h"
|
||||
|
||||
static bNodeSocketTemplate geo_node_rotate_points_in[] = {
|
||||
{SOCK_GEOMETRY, N_("Geometry")},
|
||||
{SOCK_STRING, N_("Axis")},
|
||||
{SOCK_VECTOR, N_("Axis"), 0.0, 0.0, 1.0, 0.0, -FLT_MAX, FLT_MAX, PROP_XYZ},
|
||||
{SOCK_STRING, N_("Angle")},
|
||||
{SOCK_FLOAT, N_("Angle"), 0.0, 0.0, 0.0, 0.0, -FLT_MAX, FLT_MAX, PROP_ANGLE},
|
||||
{SOCK_STRING, N_("Rotation")},
|
||||
{SOCK_VECTOR, N_("Rotation"), 0.0, 0.0, 0.0, 0.0, -FLT_MAX, FLT_MAX, PROP_EULER},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
static bNodeSocketTemplate geo_node_rotate_points_out[] = {
|
||||
{SOCK_GEOMETRY, N_("Geometry")},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
namespace blender::nodes {
|
||||
|
||||
static void rotate_points__axis_angle__object_space(const int domain_size,
|
||||
const Float3ReadAttribute &axis,
|
||||
const FloatReadAttribute &angles,
|
||||
MutableSpan<float3> rotations)
|
||||
{
|
||||
for (const int i : IndexRange(domain_size)) {
|
||||
float old_rotation[3][3];
|
||||
eul_to_mat3(old_rotation, rotations[i]);
|
||||
float rotation[3][3];
|
||||
axis_angle_to_mat3(rotation, axis[i], angles[i]);
|
||||
float new_rotation[3][3];
|
||||
mul_m3_m3m3(new_rotation, rotation, old_rotation);
|
||||
mat3_to_eul(rotations[i], new_rotation);
|
||||
}
|
||||
}
|
||||
|
||||
static void rotate_points__axis_angle__point_space(const int domain_size,
|
||||
const Float3ReadAttribute &axis,
|
||||
const FloatReadAttribute &angles,
|
||||
MutableSpan<float3> rotations)
|
||||
{
|
||||
for (const int i : IndexRange(domain_size)) {
|
||||
float old_rotation[3][3];
|
||||
eul_to_mat3(old_rotation, rotations[i]);
|
||||
float rotation[3][3];
|
||||
axis_angle_to_mat3(rotation, axis[i], angles[i]);
|
||||
float new_rotation[3][3];
|
||||
mul_m3_m3m3(new_rotation, old_rotation, rotation);
|
||||
mat3_to_eul(rotations[i], new_rotation);
|
||||
}
|
||||
}
|
||||
|
||||
static void rotate_points__euler__object_space(const int domain_size,
|
||||
const Float3ReadAttribute &eulers,
|
||||
MutableSpan<float3> rotations)
|
||||
{
|
||||
for (const int i : IndexRange(domain_size)) {
|
||||
float old_rotation[3][3];
|
||||
eul_to_mat3(old_rotation, rotations[i]);
|
||||
float rotation[3][3];
|
||||
eul_to_mat3(rotation, eulers[i]);
|
||||
float new_rotation[3][3];
|
||||
mul_m3_m3m3(new_rotation, rotation, old_rotation);
|
||||
mat3_to_eul(rotations[i], new_rotation);
|
||||
}
|
||||
}
|
||||
|
||||
static void rotate_points__euler__point_space(const int domain_size,
|
||||
const Float3ReadAttribute &eulers,
|
||||
MutableSpan<float3> rotations)
|
||||
{
|
||||
for (const int i : IndexRange(domain_size)) {
|
||||
float old_rotation[3][3];
|
||||
eul_to_mat3(old_rotation, rotations[i]);
|
||||
float rotation[3][3];
|
||||
eul_to_mat3(rotation, eulers[i]);
|
||||
float new_rotation[3][3];
|
||||
mul_m3_m3m3(new_rotation, old_rotation, rotation);
|
||||
mat3_to_eul(rotations[i], new_rotation);
|
||||
}
|
||||
}
|
||||
|
||||
static void rotate_points_on_component(GeometryComponent &component,
|
||||
const GeoNodeExecParams ¶ms)
|
||||
{
|
||||
const bNode &node = params.node();
|
||||
const NodeGeometryRotatePoints &storage = *(const NodeGeometryRotatePoints *)node.storage;
|
||||
|
||||
WriteAttributePtr rotation_attribute = component.attribute_try_ensure_for_write(
|
||||
"rotation", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3);
|
||||
if (!rotation_attribute) {
|
||||
return;
|
||||
}
|
||||
|
||||
MutableSpan<float3> rotations = rotation_attribute->get_span().typed<float3>();
|
||||
const int domain_size = rotations.size();
|
||||
|
||||
if (storage.type == GEO_NODE_ROTATE_POINTS_TYPE_AXIS_ANGLE) {
|
||||
Float3ReadAttribute axis = params.get_input_attribute<float3>(
|
||||
"Axis", component, ATTR_DOMAIN_POINT, {0, 0, 1});
|
||||
FloatReadAttribute angles = params.get_input_attribute<float>(
|
||||
"Angle", component, ATTR_DOMAIN_POINT, 0);
|
||||
|
||||
if (storage.space == GEO_NODE_ROTATE_POINTS_SPACE_OBJECT) {
|
||||
rotate_points__axis_angle__object_space(domain_size, axis, angles, rotations);
|
||||
}
|
||||
else {
|
||||
rotate_points__axis_angle__point_space(domain_size, axis, angles, rotations);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Float3ReadAttribute eulers = params.get_input_attribute<float3>(
|
||||
"Rotation", component, ATTR_DOMAIN_POINT, {0, 0, 0});
|
||||
|
||||
if (storage.space == GEO_NODE_ROTATE_POINTS_SPACE_OBJECT) {
|
||||
rotate_points__euler__object_space(domain_size, eulers, rotations);
|
||||
}
|
||||
else {
|
||||
rotate_points__euler__point_space(domain_size, eulers, rotations);
|
||||
}
|
||||
}
|
||||
|
||||
rotation_attribute->apply_span();
|
||||
}
|
||||
|
||||
static void geo_node_rotate_points_exec(GeoNodeExecParams params)
|
||||
{
|
||||
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
|
||||
|
||||
if (geometry_set.has<MeshComponent>()) {
|
||||
rotate_points_on_component(geometry_set.get_component_for_write<MeshComponent>(), params);
|
||||
}
|
||||
if (geometry_set.has<PointCloudComponent>()) {
|
||||
rotate_points_on_component(geometry_set.get_component_for_write<PointCloudComponent>(),
|
||||
params);
|
||||
}
|
||||
|
||||
params.set_output("Geometry", geometry_set);
|
||||
}
|
||||
|
||||
static void geo_node_rotate_points_init(bNodeTree *UNUSED(ntree), bNode *node)
|
||||
{
|
||||
NodeGeometryRotatePoints *node_storage = (NodeGeometryRotatePoints *)MEM_callocN(
|
||||
sizeof(NodeGeometryRotatePoints), __func__);
|
||||
|
||||
node_storage->type = GEO_NODE_ROTATE_POINTS_TYPE_EULER;
|
||||
node_storage->space = GEO_NODE_ROTATE_POINTS_SPACE_OBJECT;
|
||||
node_storage->input_type_axis = GEO_NODE_ATTRIBUTE_INPUT_VECTOR;
|
||||
node_storage->input_type_angle = GEO_NODE_ATTRIBUTE_INPUT_FLOAT;
|
||||
node_storage->input_type_rotation = GEO_NODE_ATTRIBUTE_INPUT_VECTOR;
|
||||
|
||||
node->storage = node_storage;
|
||||
}
|
||||
|
||||
static void geo_node_rotate_points_update(bNodeTree *UNUSED(ntree), bNode *node)
|
||||
{
|
||||
NodeGeometryRotatePoints *node_storage = (NodeGeometryRotatePoints *)node->storage;
|
||||
update_attribute_input_socket_availabilities(
|
||||
*node,
|
||||
"Axis",
|
||||
(GeometryNodeAttributeInputMode)node_storage->input_type_axis,
|
||||
node_storage->type == GEO_NODE_ROTATE_POINTS_TYPE_AXIS_ANGLE);
|
||||
update_attribute_input_socket_availabilities(
|
||||
*node,
|
||||
"Angle",
|
||||
(GeometryNodeAttributeInputMode)node_storage->input_type_angle,
|
||||
node_storage->type == GEO_NODE_ROTATE_POINTS_TYPE_AXIS_ANGLE);
|
||||
update_attribute_input_socket_availabilities(
|
||||
*node,
|
||||
"Rotation",
|
||||
(GeometryNodeAttributeInputMode)node_storage->input_type_rotation,
|
||||
node_storage->type == GEO_NODE_ROTATE_POINTS_TYPE_EULER);
|
||||
}
|
||||
|
||||
} // namespace blender::nodes
|
||||
|
||||
void register_node_type_geo_rotate_points()
|
||||
{
|
||||
static bNodeType ntype;
|
||||
|
||||
geo_node_type_base(&ntype, GEO_NODE_ROTATE_POINTS, "Rotate Points", NODE_CLASS_GEOMETRY, 0);
|
||||
node_type_socket_templates(&ntype, geo_node_rotate_points_in, geo_node_rotate_points_out);
|
||||
node_type_init(&ntype, blender::nodes::geo_node_rotate_points_init);
|
||||
node_type_update(&ntype, blender::nodes::geo_node_rotate_points_update);
|
||||
node_type_storage(
|
||||
&ntype, "NodeGeometryRotatePoints", node_free_standard_storage, node_copy_standard_storage);
|
||||
ntype.geometry_node_execute = blender::nodes::geo_node_rotate_points_exec;
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
|
@ -2259,38 +2259,47 @@ static int wm_handler_fileselect_do(bContext *C,
|
|||
bScreen *screen = WM_window_get_active_screen(win);
|
||||
ScrArea *file_area = screen->areabase.first;
|
||||
|
||||
if (screen->temp && (file_area->spacetype == SPACE_FILE)) {
|
||||
int win_size[2];
|
||||
bool is_maximized;
|
||||
ED_fileselect_window_params_get(win, win_size, &is_maximized);
|
||||
ED_fileselect_params_to_userdef(file_area->spacedata.first, win_size, is_maximized);
|
||||
|
||||
if (BLI_listbase_is_single(&file_area->spacedata)) {
|
||||
BLI_assert(ctx_win != win);
|
||||
|
||||
wm_window_close(C, wm, win);
|
||||
|
||||
CTX_wm_window_set(C, ctx_win); /* #wm_window_close() NULLs. */
|
||||
/* Some operators expect a drawable context (for EVT_FILESELECT_EXEC). */
|
||||
wm_window_make_drawable(wm, ctx_win);
|
||||
/* Ensure correct cursor position, otherwise, popups may close immediately after
|
||||
* opening (UI_BLOCK_MOVEMOUSE_QUIT). */
|
||||
wm_get_cursor_position(ctx_win, &ctx_win->eventstate->x, &ctx_win->eventstate->y);
|
||||
wm->winactive = ctx_win; /* Reports use this... */
|
||||
if (handler->context.win == win) {
|
||||
handler->context.win = NULL;
|
||||
}
|
||||
}
|
||||
else if (file_area->full) {
|
||||
ED_screen_full_prevspace(C, file_area);
|
||||
}
|
||||
else {
|
||||
ED_area_prevspace(C, file_area);
|
||||
}
|
||||
|
||||
temp_win = win;
|
||||
break;
|
||||
if ((file_area->spacetype != SPACE_FILE) || !WM_window_is_temp_screen(win)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ctx_area->full) {
|
||||
/* Users should not be able to maximize/fullscreen an area in a temporary screen. So if
|
||||
* there's a maximized file browser in a temporary screen, it was likely opened by
|
||||
* #EVT_FILESELECT_FULL_OPEN. */
|
||||
continue;
|
||||
}
|
||||
|
||||
int win_size[2];
|
||||
bool is_maximized;
|
||||
ED_fileselect_window_params_get(win, win_size, &is_maximized);
|
||||
ED_fileselect_params_to_userdef(file_area->spacedata.first, win_size, is_maximized);
|
||||
|
||||
if (BLI_listbase_is_single(&file_area->spacedata)) {
|
||||
BLI_assert(ctx_win != win);
|
||||
|
||||
wm_window_close(C, wm, win);
|
||||
|
||||
CTX_wm_window_set(C, ctx_win); /* #wm_window_close() NULLs. */
|
||||
/* Some operators expect a drawable context (for EVT_FILESELECT_EXEC). */
|
||||
wm_window_make_drawable(wm, ctx_win);
|
||||
/* Ensure correct cursor position, otherwise, popups may close immediately after
|
||||
* opening (UI_BLOCK_MOVEMOUSE_QUIT). */
|
||||
wm_get_cursor_position(ctx_win, &ctx_win->eventstate->x, &ctx_win->eventstate->y);
|
||||
wm->winactive = ctx_win; /* Reports use this... */
|
||||
if (handler->context.win == win) {
|
||||
handler->context.win = NULL;
|
||||
}
|
||||
}
|
||||
else if (file_area->full) {
|
||||
ED_screen_full_prevspace(C, file_area);
|
||||
}
|
||||
else {
|
||||
ED_area_prevspace(C, file_area);
|
||||
}
|
||||
|
||||
temp_win = win;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!temp_win && ctx_area->full) {
|
||||
|
|
Loading…
Reference in New Issue