Compare commits

...

25 Commits

Author SHA1 Message Date
2cbc328bdc Build bot release pipeline
* downloads builds from builder.blender.org
* generates checksums (still need to cleanup filenames)
* create source archive
* upload to download.blender.org

Next steps
* Next step is to place them in the correct folder
* file permissions download.blender.org
* snap package
* steam packages
* release notes

TODO:
* add more generic functions in master.cfg
* use a separate folder per build
2020-07-03 16:19:50 +02:00
314783f2e7 BuildbotLTS: Project Documentation
Added README.md containing a overview of the project.
2020-07-02 16:56:26 +02:00
fb0f0f4d79 Fluid: Added offset to control frame range
Added an offset field to control when to load the simulation files. Since this is a very small but helpful addition it is in my view safe to commit at this point of the bcon cycle.
2020-07-02 16:31:35 +02:00
f58f09c9a9 Fix T78513: Modifier apply shortcut not displayed
We can't specify the "apply_as" enum value, even though it's the default.
2020-07-02 08:26:59 -04:00
Jeroen Bakker
46ae115b88 Fix T78054: Crash Editing Instanced Objects with Tangent Normals
Similar track as for normal mesh. Don't store the tangent normals in CustomData
of the mesh, but in an unassociated CustomData instance.

Reviewed By: Clément Foucault

Differential Revision: https://developer.blender.org/D8161
2020-07-02 11:34:25 +02:00
Jeroen Bakker
ba2c039b05 Fix T77686: EEVEE environment pass with film transparency
When the film is set to transparent the environment pass should still be
rendered solid. otherwise it renders black.

Reviewed By: Clément Foucault

Differential Revision: https://developer.blender.org/D8046
2020-07-02 11:27:23 +02:00
945d0269e3 Fix crash calculating vertex parent in edit-mode
Regression in deaff945d0.
2020-07-02 19:12:54 +10:00
22197d7f8a Fix T76886: GPencil - Flickering when use Background or Camera image
The problem was if some stroke was empty and the changed flag was set to the last stroke wrongly.
2020-07-02 09:29:30 +02:00
26ffed7466 Cleanup: spelling 2020-07-02 13:03:46 +10:00
afd976a3b4 Fix T76806 UV Editor: Display as Outline do not work on macOS
This is a simple workaround using polyline shader. This is temporary and
a better solution should be found when we refactor the 2D view using DRW.
2020-07-02 02:32:10 +02:00
8bee200e2f Fix T76229 Overlay: Sulpt overlay not working if object use in-front option
Simple fix similar to paint overlay.
2020-07-02 01:41:02 +02:00
52b125a790 Fix alignment test when snap to edge while in vert or edge slide 2020-07-01 17:17:05 -03:00
b6f35531b6 Revert "Fix alignment test when snap to edge while in constraint"
This reverts commit e16972389e.
2020-07-01 17:13:13 -03:00
e16972389e Fix alignment test when snap to edge while in constraint 2020-07-01 16:42:06 -03:00
792cb8bdc7 Fix T77984: Cycles OpenCL error rendering empty scene 2020-07-01 20:01:25 +02:00
755c5c6e4c EEVEE: Shadows: Remove 1 pixel padding to the cubemap
This avoid having a much higher memory footprint as the underlying texture
size allocated by the driver is likely to be much higher (rounded to next
Power of 2 or other alignement requirements).
2020-07-01 19:52:05 +02:00
4723644e7f Fix T67587 Overlay: WeightPaint color blends with background in wireframe mode
Fix this by rendering to the overlay framebuffer when using alpha blend
mode.
2020-07-01 19:15:52 +02:00
6358c7754c Cleanup: Add functions to check the first brush step and symmetry passes
This adds three functions to check the state of the stroke in the
StrokeCache, removing the references to first_time and
mirror_symmetry_pass from the code. This makes easier to understand what
each code path is doing inside of each tool.

Some tools were using mirror_symmetry_pass incorrectly, so this should
also fix unreported bugs with radial and tiling symmetry related to that.

Reviewed By: sergey

Differential Revision: https://developer.blender.org/D8164
2020-07-01 19:03:22 +02:00
bf5a656ff6 GPencil: Fix unreported primitive color always set as Vertex Color
When drawing a primitive, the color was always assigned as vertex color, so it was impossible to change it in the material settings.

Now, the color is set to material color or vertex color as expected.
2020-07-01 18:55:02 +02:00
11a1ddfd30 Fix T77780 Overlay: Weight colors are not in render in the right colorspace
This was just a missing conversion.
2020-07-01 18:53:48 +02:00
f228a8948b Cleanup: Two two spaces around python class 2020-07-01 12:36:00 -04:00
927448a1da Cleanup: typos in comment. 2020-07-01 18:10:05 +02:00
e9d1d1f725 Fix T77655 Overlay: Edit mode + wire drawtype + infront not transparent 2020-07-01 18:00:05 +02:00
2788b0261c Cloth: use the original vertex positions to build internal springs.
In order to ensure correct operation of the rest shape key feature,
it's necessary to create a temporary copy of the mesh with rest
vertex positions to run the BVH lookup on. If the rest shape key
isn't used, there is no need for additional overhead.
2020-07-01 18:16:44 +03:00
f4f00661a5 Fix T78330: Duplicating parented objects does not preserve relationships.
Caused by refactor of duplicate code in rBad6cccf058d0, we need to take
into account the duplication of groups of objects here too...
2020-07-01 17:12:12 +02:00
50 changed files with 842 additions and 179 deletions

View File

@@ -0,0 +1,34 @@
Buildbot-lts
============
This folder contains configuration files and build scripts for making a release.
It originated when we started to do LTS releases what happens once every two
weeks. The idea is to automate the manual steps where possible and provide a
pipeline process for the manual steps that still needs to happen.
By using the same software as builder.blender.org it would already put us in
the right direction when we might want to make this part of builder.blender.org
for now it is running on a VM in the blender institute as it contains user
private keys and the process needs to be controlled security wise.
But of course the source and configurations are public available for anyone to
check, develop and use.
Setting up build-bot
--------------------
instructions from https://github.com/cjolowicz/docker-buildbot.
Create custom buildbot worker containing packages we need for building (git, wget).
cd docker
docker build -t buildbot --no-cache .
cd worker
docker build -t buildbot-worker --no-cache .
docker network create net-buildbot
docker rm lts-buildbot && docker run --init --name lts-buildbot --network net-buildbot --publish=127.0.0.1:8010:8010 -t -i buildbot
docker rm lts-worker && docker run --init --name lts-worker --network net-buildbot --name lts-worker -e BUILDMASTER=lts-buildbot -e WORKERNAME=lts-worker -e WORKERPASS=secret -t -i buildbot-worker

View File

@@ -0,0 +1,36 @@
FROM ubuntu:18.04
RUN apt update && apt upgrade -y
RUN apt install -y \
gosu \
wget \
openssh-client \
build-essential \
libffi-dev \
libssl-dev \
python3-dev \
python3-pip
ENV BUILDBOT_VERSION 2.5.0
RUN pip3 --no-cache-dir install --upgrade pip && pip --no-cache-dir install \
buildbot[bundle,tls]==$BUILDBOT_VERSION \
buildbot-docker-swarm-worker
COPY buildbot.tac /var/lib/buildbot/
COPY docker-entrypoint.sh /usr/local/bin/
COPY master.cfg /etc/buildbot/
COPY bin/create_checksum.sh /var/lib/buildbot/bin/
COPY bin/upload_file.sh /var/lib/buildbot/bin/
COPY .ssh/id_rsa /var/lib/buildbot/.ssh/
RUN adduser --home /var/lib/buildbot --disabled-password --gecos '' buildbot
WORKDIR /var/lib/buildbot
RUN ln -s /etc/buildbot/master.cfg
VOLUME /var/lib/buildbot
EXPOSE 8010
EXPOSE 9989
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["twistd", "--pidfile=", "--nodaemon", "--python=buildbot.tac"]

View File

@@ -0,0 +1,4 @@
#!/bin/sh
set -e
md5sum $1 > $2.md5
sha256sum $1 > $2.sha256

View File

@@ -0,0 +1,7 @@
#!/bin/sh
set -e
if [ ! -f /var/lib/buildbot/.ssh/known_hosts ]
then
ssh-keyscan download.blender.org > /var/lib/buildbot/.ssh/known_hosts
fi
scp $1 jeroen@download.blender.org:$2

View File

@@ -0,0 +1,20 @@
import os
import sys
from twisted.application import service
from twisted.python.log import FileLogObserver
from twisted.python.log import ILogObserver
from buildbot.master import BuildMaster
basedir = os.environ.get("BUILDBOT_BASEDIR",
os.path.abspath(os.path.dirname(__file__)))
configfile = 'master.cfg'
# note: this line is matched against to check that this is a buildmaster
# directory; do not edit it.
application = service.Application('buildmaster')
application.setComponent(ILogObserver, FileLogObserver(sys.stdout).emit)
m = BuildMaster(basedir, configfile, umask=None)
m.setServiceParent(application)

View File

@@ -0,0 +1,36 @@
version: '1'
services:
buildbot:
image: buildbot/buildbot-master:master
env_file:
- db.env
environment:
- BUILDBOT_CONFIG_DIR=config
- BUILDBOT_CONFIG_URL=https://github.com/buildbot/buildbot-docker-example-config/archive/master.tar.gz
- BUILDBOT_WORKER_PORT=9989
- BUILDBOT_WEB_URL=http://localhost:8010/
- BUILDBOT_WEB_PORT=tcp:port=8010
links:
- db
depends_on:
- db
ports:
- "8010:8010"
db:
env_file:
- db.env
image: "postgres:9.4"
expose:
- 5432
worker:
image: "buildbot/buildbot-worker:master"
environment:
BUILDMASTER: buildbot
BUILDMASTER_PORT: 9989
WORKERNAME: lts-worker
WORKERPASS: pass
WORKER_ENVIRONMENT_BLACKLIST: DOCKER_BUILDBOT* BUILDBOT_ENV_* BUILDBOT_1* WORKER_ENVIRONMENT_BLACKLIST
links:
- buildbot

View File

@@ -0,0 +1,18 @@
#!/bin/sh
set -e
buildbot upgrade-master .
chown buildbot /var/lib/buildbot/
chown buildbot /var/lib/buildbot/.ssh/
chown -R buildbot /var/lib/buildbot/*
if [ -S /var/run/docker.sock ]
then
group=$(stat -c '%g' /var/run/docker.sock)
else
group=buildbot
fi
gosu buildbot:$group "$@"

View File

@@ -0,0 +1,240 @@
# -*- python -*-
# ex: set filetype=python:
import os
from buildbot.plugins import *
# This is a sample buildmaster config file. It must be installed as
# 'master.cfg' in your buildmaster's base directory.
# This is the dictionary that the buildmaster pays attention to. We also use
# a shorter alias to save typing.
c = BuildmasterConfig = {}
####### WORKERS
# The 'workers' list defines the set of recognized workers. Each element is
# a Worker object, specifying a unique worker name and password. The same
# worker name and password must be configured on the worker.
c['workers'] = [worker.Worker("lts-worker", 'secret')]
if 'BUILDBOT_MQ_URL' in os.environ:
c['mq'] = {
'type' : 'wamp',
'router_url': os.environ['BUILDBOT_MQ_URL'],
'realm': os.environ.get('BUILDBOT_MQ_REALM', 'buildbot').decode('utf-8'),
'debug' : 'BUILDBOT_MQ_DEBUG' in os.environ,
'debug_websockets' : 'BUILDBOT_MQ_DEBUG' in os.environ,
'debug_lowlevel' : 'BUILDBOT_MQ_DEBUG' in os.environ,
}
# 'protocols' contains information about protocols which master will use for
# communicating with workers. You must define at least 'port' option that workers
# could connect to your master with this protocol.
# 'port' must match the value configured into the workers (with their
# --master option)
c['protocols'] = {'pb': {'port': os.environ.get("BUILDBOT_WORKER_PORT", 9989)}}
####### CHANGESOURCES
# the 'change_source' setting tells the buildmaster how it should find out
# about source code changes. We don't build when sources change.
c['change_source'] = []
####### SCHEDULERS
# Configure the Schedulers, which decide how to react to incoming changes. In this
# case, just kick off a 'runtests' build
c['schedulers'] = [
schedulers.ForceScheduler(
name="build",
builderNames=["release-blender-283"],
properties=[
util.StringParameter(
name="blender_version",
label="Version of blender.",
default="2.83"),
util.StringParameter(
name="blender_version_full",
label="Version of blender (Full).",
default="2.83.1")
]
),
schedulers.Triggerable(
name="deploy-source-archive",
builderNames=["deploy-source-archive"]
),
schedulers.Triggerable(
name="deploy-buildbot-packages",
builderNames=["deploy-buildbot-packages"]
),
]
####### BUILDERS
# The 'builders' list defines the Builders, which tell Buildbot how to perform a build:
# what steps, and which workers can execute them. Note that any particular build will
# only take place on one worker.
deploy_source_archive_factory = util.BuildFactory()
deploy_source_archive_factory.addStep(steps.Git(name="Checkout Blender Source", repourl='https://git.blender.org/blender.git', branch=util.Interpolate('blender-v%(prop:blender_version)s-release'), mode='full'))
deploy_source_archive_factory.addStep(steps.ShellSequence(name="Make source archive", commands=[
util.ShellArg(command=["make", "source_archive"], logfile='make_source_archive'),
# The next two shell commands are only needed during development
util.ShellArg(command=["mv", "blender-2.83.2-beta.tar.xz", util.Interpolate('blender-v%(prop:blender_version_full)s.tar.xz')]),
util.ShellArg(command=["mv", "blender-2.83.2-beta.tar.xz.md5sum", util.Interpolate('blender-v%(prop:blender_version_full)s.tar.xz.md5sum')]),
]))
deploy_source_archive_factory.addStep(steps.FileUpload(
name="Upload source archive",
workersrc=util.Interpolate('blender-v%(prop:blender_version_full)s.tar.xz'),
masterdest=util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s/blender-v%(prop:blender_version_full)s.tar.xz')))
deploy_source_archive_factory.addStep(steps.FileUpload(
name="Upload source archive checksum",
workersrc=util.Interpolate('blender-v%(prop:blender_version_full)s.tar.xz.md5sum'),
masterdest=util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s/blender-v%(prop:blender_version_full)s.tar.xz.md5sum')))
deploy_source_archive_factory.addStep(steps.MasterShellCommand(
name="Upload source archive",
command=[
'sh', '-C', '/var/lib/buildbot/bin/upload_file.sh',
util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s/blender-v%(prop:blender_version_full)s.tar.xz'),
util.Interpolate('/data/www/vhosts/download.blender.org/ftp/jeroen/')]))
deploy_source_archive_factory.addStep(steps.MasterShellCommand(
name="Upload windows64.zip build",
command=[
'sh', '-C', '/var/lib/buildbot/bin/upload_file.sh',
util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s/blender-v%(prop:blender_version_full)s.tar.xz.md5sum'),
util.Interpolate('/data/www/vhosts/download.blender.org/ftp/jeroen/')]))
deploy_buildbot_packages_factory = util.BuildFactory()
deploy_buildbot_packages_factory.addStep(steps.MasterShellCommand(
name="Download linux64 build",
command=[
'wget', util.Interpolate('https://builder.blender.org/download/blender-%(prop:blender_version_full)s-linux64.tar.xz'),
"-O", util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s/blender-%(prop:blender_version_full)s-linux64.tar.xz')]))
deploy_buildbot_packages_factory.addStep(steps.MasterShellCommand(
name="Download windows64.msi build",
command=[
'wget', util.Interpolate('https://builder.blender.org/download/blender-%(prop:blender_version_full)s-windows64.msi'),
"-O", util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s/blender-%(prop:blender_version_full)s-windows64.msi')]))
deploy_buildbot_packages_factory.addStep(steps.MasterShellCommand(
name="Download windows64.zip build",
command=[
'wget', util.Interpolate('https://builder.blender.org/download/blender-%(prop:blender_version_full)s-windows64.zip'),
"-O", util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s/blender-%(prop:blender_version_full)s-windows64.zip')]))
deploy_buildbot_packages_factory.addStep(steps.MasterShellCommand(
name="Download macOS build",
command=[
'wget', util.Interpolate('https://builder.blender.org/download/blender-%(prop:blender_version_full)s-macOS.dmg'),
"-O", util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s/blender-%(prop:blender_version_full)s-macOS.dmg')]))
deploy_buildbot_packages_factory.addStep(steps.MasterShellCommand(
name="Create checksum (md5/sha256)",
command=[
'sh',
'-C',
'/var/lib/buildbot/bin/create_checksum.sh',
util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s/blender-%(prop:blender_version_full)s-*'),
util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s/blender-%(prop:blender_version_full)s'),
]))
deploy_buildbot_packages_factory.addStep(steps.MasterShellCommand(
name="Upload linux64 build",
command=[
'sh', '-C', '/var/lib/buildbot/bin/upload_file.sh',
util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s/blender-%(prop:blender_version_full)s-linux64.tar.xz'),
util.Interpolate('/data/www/vhosts/download.blender.org/ftp/jeroen/')]))
deploy_buildbot_packages_factory.addStep(steps.MasterShellCommand(
name="Upload windows64.msi build",
command=[
'sh', '-C', '/var/lib/buildbot/bin/upload_file.sh',
util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s/blender-%(prop:blender_version_full)s-windows64.msi'),
util.Interpolate('/data/www/vhosts/download.blender.org/ftp/jeroen/')]))
deploy_buildbot_packages_factory.addStep(steps.MasterShellCommand(
name="Upload windows64.zip build",
command=[
'sh', '-C', '/var/lib/buildbot/bin/upload_file.sh',
util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s/blender-%(prop:blender_version_full)s-windows64.zip'),
util.Interpolate('/data/www/vhosts/download.blender.org/ftp/jeroen/')]))
deploy_buildbot_packages_factory.addStep(steps.MasterShellCommand(
name="Upload macOS build",
command=[
'sh', '-C', '/var/lib/buildbot/bin/upload_file.sh',
util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s/blender-%(prop:blender_version_full)s-macOS.dmg'),
util.Interpolate('/data/www/vhosts/download.blender.org/ftp/jeroen/')]))
deploy_buildbot_packages_factory.addStep(steps.MasterShellCommand(
name="Upload md5 checksum",
command=[
'sh', '-C', '/var/lib/buildbot/bin/upload_file.sh',
util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s/blender-%(prop:blender_version_full)s.md5'),
util.Interpolate('/data/www/vhosts/download.blender.org/ftp/jeroen/')]))
deploy_buildbot_packages_factory.addStep(steps.MasterShellCommand(
name="Upload sha256 checksum",
command=[
'sh', '-C', '/var/lib/buildbot/bin/upload_file.sh',
util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s/blender-%(prop:blender_version_full)s.sha256'),
util.Interpolate('/data/www/vhosts/download.blender.org/ftp/jeroen/')]))
factory = util.BuildFactory()
factory.addStep(steps.MasterShellCommand(name="Init release folder", command=["mkdir", "-p", util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s')]))
factory.addStep(steps.Trigger(
name='Deploy',
schedulerNames=[
'deploy-source-archive',
'deploy-buildbot-packages',
],
waitForFinish=True,
set_properties={
'blender_version_full': util.Property('blender_version_full'),
'blender_version': util.Property('blender_version'),
}
))
# Download builds from builder.blender.org
c['builders'] = [
util.BuilderConfig(name="release-blender-283",
workernames=["lts-worker"],
factory=factory),
util.BuilderConfig(name="deploy-source-archive",
workernames=["lts-worker"],
factory=deploy_source_archive_factory),
util.BuilderConfig(name="deploy-buildbot-packages",
workernames=["lts-worker"],
factory=deploy_buildbot_packages_factory),
]
####### STATUS TARGETS
# 'status' is a list of Status Targets. The results of each build will be
# pushed to these targets. buildbot/status/*.py has a variety to choose from,
# like IRC bots.
# c['status'] = []
####### PROJECT IDENTITY
# the 'title' string will appear at the top of this buildbot installation's
# home pages (linked to the 'titleURL').
c['title'] = "Blender Release LTS"
c['titleURL'] = "https://www.blender.org/download/lts/"
# the 'buildbotURL' string should point to the location where the buildbot's
# internal web server is visible. This typically uses the port number set in
# the 'www' entry below, but with an externally-visible host name which the
# buildbot cannot figure out without some help.
c['buildbotURL'] = os.environ.get("BUILDBOT_WEB_URL", "http://localhost:8010/")
# minimalistic config to activate new web UI
c['www'] = dict(port=os.environ.get("BUILDBOT_WEB_PORT", 8010),
plugins=dict(waterfall_view={}, console_view={}))
####### DB URL
c['db'] = {
# This specifies what database buildbot uses to store its state. You can leave
# this at its default for all but the largest installations.
'db_url' : os.environ.get("BUILDBOT_DB_URL", "sqlite://").format(**os.environ),
}

View File

@@ -0,0 +1,27 @@
FROM ubuntu:18.04
RUN set -ex; \
apt-get update; \
apt-get install -y --no-install-recommends \
build-essential \
git \
wget \
python3-dev \
python3-pip \
python3-setuptools \
python3-wheel \
; \
rm -rf /var/lib/apt/lists/*
ENV BUILDBOT_VERSION 2.5.0
RUN pip3 install --upgrade pip && \
pip --no-cache-dir install twisted[tls] && \
pip --no-cache-dir install buildbot_worker==$BUILDBOT_VERSION
RUN useradd --create-home --home-dir=/var/lib/buildbot buildbot
WORKDIR /var/lib/buildbot
USER buildbot
COPY buildbot.tac .
CMD ["twistd", "--pidfile=", "--nodaemon", "--python=buildbot.tac"]

View File

@@ -0,0 +1,39 @@
import fnmatch
import os
import sys
from twisted.application import service
from twisted.python.log import FileLogObserver
from twisted.python.log import ILogObserver
from buildbot_worker.bot import Worker
# setup worker
basedir = os.path.abspath(os.path.dirname(__file__))
application = service.Application('buildbot-worker')
application.setComponent(ILogObserver, FileLogObserver(sys.stdout).emit)
# and worker on the same process!
buildmaster_host = os.environ.get("BUILDMASTER", 'localhost')
port = int(os.environ.get("BUILDMASTER_PORT", 9989))
workername = os.environ.get("WORKERNAME", 'docker')
passwd = os.environ.get("WORKERPASS")
# delete the password from the environ so that it is not leaked in the log
blacklist = os.environ.get("WORKER_ENVIRONMENT_BLACKLIST", "WORKERPASS").split()
for name in list(os.environ.keys()):
for toremove in blacklist:
if fnmatch.fnmatch(name, toremove):
del os.environ[name]
keepalive = 600
umask = None
maxdelay = 300
allow_shutdown = None
maxretries = 10
s = Worker(buildmaster_host, port, workername, passwd, basedir,
keepalive, umask=umask, maxdelay=maxdelay,
allow_shutdown=allow_shutdown, maxRetries=maxretries)
s.setServiceParent(application)

View File

@@ -1222,6 +1222,7 @@ def has_geometry_visibility(ob):
return ob and ((ob.type in {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META', 'LIGHT'}) or
(ob.instance_type == 'COLLECTION' and ob.instance_collection))
class CYCLES_OBJECT_PT_shading(CyclesButtonsPanel, Panel):
bl_label = "Shading"
bl_context = "object"
@@ -1244,6 +1245,7 @@ class CYCLES_OBJECT_PT_shading(CyclesButtonsPanel, Panel):
col = flow.column()
col.prop(cob, "shadow_terminator_offset")
class CYCLES_OBJECT_PT_visibility(CyclesButtonsPanel, Panel):
bl_label = "Visibility"
bl_context = "object"

View File

@@ -64,6 +64,9 @@ void MemoryManager::DeviceBuffer::update_device_memory(OpenCLDevice *device)
total_size += alloc_size;
}
/* Always allocate non-empty buffer, NULL pointers cause problems with some drivers. */
total_size = max(total_size, 16);
if (need_realloc) {
cl_ulong max_buffer_size;
clGetDeviceInfo(
@@ -251,7 +254,7 @@ void MemoryManager::set_kernel_arg_buffers(cl_kernel kernel, cl_uint *narg)
device->kernel_set_args(kernel, (*narg)++, *device_buffer.buffer);
}
else {
device->kernel_set_args(kernel, (*narg)++, 0);
device->kernel_set_args(kernel, (*narg)++);
}
}
}

View File

@@ -266,7 +266,7 @@ inline void processor_apply_pixels(const OCIO::Processor *processor, T *pixels,
{
/* TODO: implement faster version for when we know the conversion
* is a simple matrix transform between linear spaces. In that case
* unpremultiply is not needed. */
* un-premultiply is not needed. */
/* Process large images in chunks to keep temporary memory requirement down. */
const size_t chunk_size = std::min((size_t)(16 * 1024 * 1024), num_pixels);
@@ -354,7 +354,7 @@ void ColorSpaceManager::to_scene_linear(ColorSpaceProcessor *processor_,
processor->applyRGB(pixel);
}
else {
/* Unassociate and associate alpha since color management should not
/* Un-associate and associate alpha since color management should not
* be affected by transparency. */
float alpha = pixel[3];
float inv_alpha = 1.0f / alpha;

View File

@@ -942,12 +942,12 @@ void ShaderGraph::refine_bump_nodes()
foreach (NodePair &pair, nodes_dy)
add(pair.second);
/* connect what is connected is bump to samplecenter input*/
/* Connect what is connected is bump to sample-center input. */
connect(out, node->input("SampleCenter"));
/* bump input is just for connectivity purpose for the graph input,
* we re-connected this input to samplecenter, so lets disconnect it
* from bump input */
/* Bump input is just for connectivity purpose for the graph input,
* we re-connected this input to sample-center, so lets disconnect it
* from bump input. */
disconnect(bump_input);
}
}

View File

@@ -1135,22 +1135,22 @@ class PHYSICS_PT_cache(PhysicButtonsPanel, Panel):
flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
col = flow.column()
col.prop(domain, "cache_type", expand=False)
col.enabled = not is_baking_any
col.separator()
row = col.row()
col = row.column(align=True)
col.prop(domain, "cache_frame_start", text="Frame Start")
col.prop(domain, "cache_frame_end", text="End")
row.enabled = not is_baking_any
row = row.column(align=True)
row.prop(domain, "cache_frame_start", text="Frame Start")
row.prop(domain, "cache_frame_end", text="End")
row = col.row()
row.enabled = domain.cache_type in {'MODULAR', 'ALL'}
row.prop(domain, "cache_frame_offset", text="Offset")
col.separator()
col = flow.column()
col.enabled = not is_baking_any and not has_baked_data
col.prop(domain, "cache_resumable", text="Is Resumable")
col.prop(domain, "cache_type", expand=False)
row = col.row()
row.enabled = not is_baking_any and not has_baked_data
row.prop(domain, "cache_resumable", text="Is Resumable")
row = col.row()
row.enabled = not is_baking_any and not has_baked_data

View File

@@ -43,6 +43,7 @@
#include "BKE_cloth.h"
#include "BKE_effect.h"
#include "BKE_global.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
#include "BKE_modifier.h"
#include "BKE_pointcache.h"
@@ -1270,6 +1271,21 @@ static void cloth_update_verts(Object *ob, ClothModifierData *clmd, Mesh *mesh)
}
}
/* Write rest vert locations to a copy of the mesh. */
static Mesh *cloth_make_rest_mesh(ClothModifierData *clmd, Mesh *mesh)
{
Mesh *new_mesh = BKE_mesh_copy_for_eval(mesh, false);
ClothVertex *verts = clmd->clothObject->verts;
MVert *mvert = new_mesh->mvert;
/* vertex count is already ensured to match */
for (unsigned i = 0; i < mesh->totvert; i++, verts++) {
copy_v3_v3(mvert[i].co, verts->xrest);
}
return new_mesh;
}
/* Update spring rest length, for dynamically deformable cloth */
static void cloth_update_spring_lengths(ClothModifierData *clmd, Mesh *mesh)
{
@@ -1598,10 +1614,18 @@ static int cloth_build_springs(ClothModifierData *clmd, Mesh *mesh)
BVHTreeFromMesh treedata = {NULL};
unsigned int tar_v_idx;
BLI_bitmap *verts_used = NULL;
Mesh *tmp_mesh = NULL;
RNG *rng;
/* If using the rest shape key, it's necessary to make a copy of the mesh. */
if (clmd->sim_parms->shapekey_rest &&
!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_DYNAMIC_BASEMESH)) {
tmp_mesh = cloth_make_rest_mesh(clmd, mesh);
BKE_mesh_calc_normals(tmp_mesh);
}
verts_used = BLI_BITMAP_NEW(mvert_num * mvert_num, __func__);
BKE_bvhtree_from_mesh_get(&treedata, mesh, BVHTREE_FROM_LOOPTRI, 2);
BKE_bvhtree_from_mesh_get(&treedata, tmp_mesh ? tmp_mesh : mesh, BVHTREE_FROM_LOOPTRI, 2);
rng = BLI_rng_new_srandom(0);
for (int i = 0; i < mvert_num; i++) {
@@ -1646,12 +1670,18 @@ static int cloth_build_springs(ClothModifierData *clmd, Mesh *mesh)
cloth_free_errorsprings(cloth, edgelist, spring_ref);
MEM_freeN(verts_used);
free_bvhtree_from_mesh(&treedata);
if (tmp_mesh) {
BKE_mesh_free(tmp_mesh);
}
return 0;
}
}
}
MEM_freeN(verts_used);
free_bvhtree_from_mesh(&treedata);
if (tmp_mesh) {
BKE_mesh_free(tmp_mesh);
}
BLI_rng_free(rng);
}

View File

@@ -3724,10 +3724,31 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd,
bool is_startframe, has_advanced;
is_startframe = (scene_framenr == mds->cache_frame_start);
has_advanced = (scene_framenr == mmd->time + 1);
int mode = mds->cache_type;
/* Do not process modifier if current frame is out of cache range. */
if (scene_framenr < mds->cache_frame_start || scene_framenr > mds->cache_frame_end) {
return;
switch (mode) {
case FLUID_DOMAIN_CACHE_ALL:
case FLUID_DOMAIN_CACHE_MODULAR:
if (mds->cache_frame_offset > 0) {
if (scene_framenr < mds->cache_frame_start ||
scene_framenr > mds->cache_frame_end + mds->cache_frame_offset) {
return;
}
}
else {
if (scene_framenr < mds->cache_frame_start + mds->cache_frame_offset ||
scene_framenr > mds->cache_frame_end) {
return;
}
}
break;
case FLUID_DOMAIN_CACHE_REPLAY:
default:
if (scene_framenr < mds->cache_frame_start || scene_framenr > mds->cache_frame_end) {
return;
}
break;
}
/* Reset fluid if no fluid present. Also resets active fields. */
@@ -3865,7 +3886,6 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd,
with_gdomain = (mds->guide_source == FLUID_DOMAIN_GUIDE_SRC_DOMAIN);
int o_res[3], o_min[3], o_max[3], o_shift[3];
int mode = mds->cache_type;
/* Cache mode specific settings. */
switch (mode) {
@@ -3875,6 +3895,12 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd,
if (!baking_data && !baking_noise && !baking_mesh && !baking_particles && !baking_guide) {
read_cache = true;
bake_cache = false;
/* Apply frame offset. */
data_frame -= mmd->domain->cache_frame_offset;
noise_frame -= mmd->domain->cache_frame_offset;
mesh_frame -= mmd->domain->cache_frame_offset;
particles_frame -= mmd->domain->cache_frame_offset;
break;
}
@@ -4905,6 +4931,7 @@ void BKE_fluid_modifier_create_type_data(struct FluidModifierData *mmd)
mmd->domain->cache_frame_pause_mesh = 0;
mmd->domain->cache_frame_pause_particles = 0;
mmd->domain->cache_frame_pause_guide = 0;
mmd->domain->cache_frame_offset = 0;
mmd->domain->cache_flag = 0;
mmd->domain->cache_type = FLUID_DOMAIN_CACHE_REPLAY;
mmd->domain->cache_mesh_format = FLUID_DOMAIN_FILE_BIN_OBJECT;
@@ -5151,6 +5178,7 @@ void BKE_fluid_modifier_copy(const struct FluidModifierData *mmd,
tmds->cache_frame_pause_mesh = mds->cache_frame_pause_mesh;
tmds->cache_frame_pause_particles = mds->cache_frame_pause_particles;
tmds->cache_frame_pause_guide = mds->cache_frame_pause_guide;
tmds->cache_frame_offset = mds->cache_frame_offset;
tmds->cache_flag = mds->cache_flag;
tmds->cache_type = mds->cache_type;
tmds->cache_mesh_format = mds->cache_mesh_format;

View File

@@ -95,7 +95,7 @@ bool BKE_gpencil_data_minmax(const bGPdata *gpd, float r_min[3], float r_max[3])
if (gpf != NULL) {
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
changed = BKE_gpencil_stroke_minmax(gps, false, r_min, r_max);
changed |= BKE_gpencil_stroke_minmax(gps, false, r_min, r_max);
}
}
}

View File

@@ -2486,9 +2486,10 @@ static void give_parvert(Object *par, int nr, float vec[3])
if (me_eval) {
int count = 0;
const int numVerts = me_eval->totvert;
int numVerts = me_eval->totvert;
if (em && me_eval->runtime.is_original) {
if (em && me_eval->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) {
numVerts = em->bm->totvert;
if (em->bm->elem_table_dirty & BM_VERT) {
#ifdef VPARENT_THREADING_HACK
BLI_mutex_lock(&vparent_lock);
@@ -2501,10 +2502,18 @@ static void give_parvert(Object *par, int nr, float vec[3])
BM_mesh_elem_table_ensure(em->bm, BM_VERT);
#endif
}
if (nr < numVerts) {
if (me_eval && me_eval->runtime.edit_data && me_eval->runtime.edit_data->vertexCos) {
add_v3_v3(vec, me_eval->runtime.edit_data->vertexCos[nr]);
}
else {
const BMVert *v = BM_vert_at_index(em->bm, nr);
add_v3_v3(vec, v->co);
}
count++;
}
}
if (CustomData_has_layer(&me_eval->vdata, CD_ORIGINDEX) &&
!(em && me_eval->runtime.is_original)) {
else if (CustomData_has_layer(&me_eval->vdata, CD_ORIGINDEX)) {
const int *index = CustomData_get_layer(&me_eval->vdata, CD_ORIGINDEX);
/* Get the average of all verts with (original index == nr). */
for (int i = 0; i < numVerts; i++) {

View File

@@ -1032,12 +1032,14 @@ bool BLI_bvhtree_update_node(
return true;
}
/* call BLI_bvhtree_update_node() first for every node/point/triangle */
/**
* Call #BLI_bvhtree_update_node() first for every node/point/triangle.
*/
void BLI_bvhtree_update_tree(BVHTree *tree)
{
/* Update bottom=>top
* TRICKY: the way we build the tree all the childs have an index greater than the parent
* This allows us todo a bottom up update by starting on the bigger numbered branch */
* TRICKY: the way we build the tree all the children have an index greater than the parent
* This allows us todo a bottom up update by starting on the bigger numbered branch. */
BVHNode **root = tree->nodes + tree->totleaf;
BVHNode **index = tree->nodes + tree->totleaf + tree->totbranch - 1;
@@ -2309,7 +2311,7 @@ static bool bvhtree_walk_dfs_recursive(BVHTree_WalkData *walk_data, const BVHNod
}
/**
* This is a generic function to perform a depth first search on the BVHTree
* This is a generic function to perform a depth first search on the #BVHTree
* where the search order and nodes traversed depend on callbacks passed in.
*
* \param tree: Tree to walk.
@@ -2317,7 +2319,7 @@ static bool bvhtree_walk_dfs_recursive(BVHTree_WalkData *walk_data, const BVHNod
* \param walk_leaf_cb: Callback to test leaf nodes, callback must store its own result,
* returning false exits early.
* \param walk_order_cb: Callback that indicates which direction to search,
* either from the node with the lower or higher k-dop axis value.
* either from the node with the lower or higher K-DOP axis value.
* \param userdata: Argument passed to all callbacks.
*/
void BLI_bvhtree_walk_dfs(BVHTree *tree,

View File

@@ -20,7 +20,7 @@
/** \file
* \ingroup bli
*
* Utility functions for variable size bitmasks.
* Utility functions for variable size bit-masks.
*/
#include <limits.h>

View File

@@ -409,7 +409,7 @@ char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict
/**
* string with all instances of substr_old replaced with substr_new,
* Returns a copy of the cstring \a str into a newly mallocN'd
* Returns a copy of the c-string \a str into a newly #MEM_mallocN'd
* and returns it.
*
* \note A rather wasteful string-replacement utility, though this shall do for now...
@@ -430,53 +430,49 @@ char *BLI_str_replaceN(const char *__restrict str,
BLI_assert(substr_old[0] != '\0');
/* while we can still find a match for the old substring that we're searching for,
* keep dicing and replacing
*/
/* While we can still find a match for the old sub-string that we're searching for,
* keep dicing and replacing. */
while ((match = strstr(str, substr_old))) {
/* the assembly buffer only gets created when we actually need to rebuild the string */
if (ds == NULL) {
ds = BLI_dynstr_new();
}
/* if the match position does not match the current position in the string,
* copy the text up to this position and advance the current position in the string
*/
/* If the match position does not match the current position in the string,
* copy the text up to this position and advance the current position in the string. */
if (str != match) {
/* add the segment of the string from str to match to the buffer,
* then restore the value at match */
/* Add the segment of the string from `str` to match to the buffer,
* then restore the value at match. */
BLI_dynstr_nappend(ds, str, (match - str));
/* now our current position should be set on the start of the match */
str = match;
}
/* add the replacement text to the accumulation buffer */
/* Add the replacement text to the accumulation buffer. */
BLI_dynstr_append(ds, substr_new);
/* advance the current position of the string up to the end of the replaced segment */
/* Advance the current position of the string up to the end of the replaced segment. */
str += len_old;
}
/* finish off and return a new string that has had all occurrences of */
/* Finish off and return a new string that has had all occurrences of. */
if (ds) {
char *str_new;
/* add what's left of the string to the assembly buffer
* - we've been adjusting str to point at the end of the replaced segments
*/
/* Add what's left of the string to the assembly buffer
* - we've been adjusting `str` to point at the end of the replaced segments. */
BLI_dynstr_append(ds, str);
/* convert to new c-string (MEM_malloc'd), and free the buffer */
/* Convert to new c-string (MEM_malloc'd), and free the buffer. */
str_new = BLI_dynstr_get_cstring(ds);
BLI_dynstr_free(ds);
return str_new;
}
else {
/* just create a new copy of the entire string - we avoid going through the assembly buffer
* for what should be a bit more efficiency...
*/
/* Just create a new copy of the entire string - we avoid going through the assembly buffer
* for what should be a bit more efficiency. */
return BLI_strdup(str);
}
}

View File

@@ -901,16 +901,17 @@ static void math_layer_info_init(BevelParams *bp, BMesh *bm)
MEM_freeN(stack);
}
/* Use a tie-breaking rule to choose a representative face when
* there are number of choices, face[0], face[1], ..., face[nfaces].
/**
* Use a tie-breaking rule to choose a representative face when
* there are number of choices, `face[0]`, `face[1]`, ..., `face[nfaces]`.
* This is needed when there are an odd number of segments, and the center
* segmment (and its continuation into vmesh) can usually arbitrarily be
* segment (and its continuation into vmesh) can usually arbitrarily be
* the previous face or the next face.
* Or, for the center polygon of a corner, all of the faces around
* the vertex are possible choices.
* If we just choose randomly, the resulting UV maps or material
* assignment can look ugly/inconsistent.
* Allow for the case when args are null.
* Allow for the case when arguments are null.
*/
static BMFace *choose_rep_face(BevelParams *bp, BMFace **face, int nfaces)
{
@@ -2948,7 +2949,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
bool betodd = (between % 2) == 1;
int i = 0;
/* Put first half of in-between edges at index 0, second half at index bp->seg.
* If between is odd, put middle one at midindex. */
* If between is odd, put middle one at mid-index. */
for (e3 = e->next; e3 != e2; e3 = e3->next) {
v1->elast = e3;
if (i < bet2) {
@@ -4682,10 +4683,11 @@ static float interp_poly_area(BevVert *bv, BMFace *frep)
}
/**
* If we make a poly out of verts around bv, snapping to rep frep, will uv poly have zero area?
* The uv poly is made by snapping all outside-of-frep vertices to the closest edge in frep.
* If we make a poly out of verts around \a bv, snapping to rep \a frep,
* will uv poly have zero area?
* The uv poly is made by snapping all `outside-of-frep` vertices to the closest edge in \a frep.
* Sometimes this results in a zero or very small area polygon, which translates to a zero
* or very small area polygong in UV space -- not good for interpolating textures.
* or very small area polygon in UV space -- not good for interpolating textures.
*/
static bool is_bad_uv_poly(BevVert *bv, BMFace *frep)
{
@@ -4693,8 +4695,8 @@ static bool is_bad_uv_poly(BevVert *bv, BMFace *frep)
return area < BEVEL_EPSILON_BIG;
}
/*
* Pick a good face from all the faces around bv to use for
/**
* Pick a good face from all the faces around \a bv to use for
* a representative face, using choose_rep_face.
* We want to choose from among the faces that would be
* chosen for a single-segment edge polygon between two successive
@@ -4801,10 +4803,12 @@ static void build_center_ngon(BevelParams *bp, BMesh *bm, BevVert *bv, int mat_n
BLI_array_free(ve);
}
/* Special case of bevel_build_rings when tri-corner and profile is 0.
/**
* Special case of #bevel_build_rings when triangle-corner and profile is 0.
* There is no corner mesh except, if nseg odd, for a center poly.
* Boundary verts merge with previous ones according to pattern:
* (i, 0, k) merged with (i+1, 0, ns-k) for k <= ns/2. */
* (i, 0, k) merged with (i+1, 0, ns-k) for k <= ns/2.
*/
static void build_square_in_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv, VMesh *vm1)
{
int n, ns, ns2, odd, i, k;
@@ -4838,7 +4842,9 @@ static void build_square_in_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv, VMesh
}
}
/* Copy whichever of a and b is closer to v into r. */
/**
* Copy whichever of \a a and \a b is closer to v into \a r.
*/
static void closer_v3_v3v3v3(float r[3], float a[3], float b[3], float v[3])
{
if (len_squared_v3v3(a, v) <= len_squared_v3v3(b, v)) {
@@ -4998,7 +5004,7 @@ static VMesh *square_out_adj_vmesh(BevelParams *bp, BevVert *bv)
bndv = bndv->next;
}
/* Fill in rest of centerlines by interpolation. */
/* Fill in rest of center-lines by interpolation. */
copy_v3_v3(co2, bv->v->co);
bndv = vm->boundstart;
for (i = 0; i < n_bndv; i++) {
@@ -5049,7 +5055,7 @@ static VMesh *square_out_adj_vmesh(BevelParams *bp, BevVert *bv)
}
vmesh_copy_equiv_verts(vm);
/* Fill in interior points by interpolation from edges to centerlines. */
/* Fill in interior points by interpolation from edges to center-lines. */
bndv = vm->boundstart;
for (i = 0; i < n_bndv; i++) {
im1 = (i == 0) ? n_bndv - 1 : i - 1;
@@ -5087,9 +5093,9 @@ static VMesh *square_out_adj_vmesh(BevelParams *bp, BevVert *bv)
}
/**
* Given that the boundary is built and the boundary BMVerts have been made,
* Given that the boundary is built and the boundary #BMVert's have been made,
* calculate the positions of the interior mesh points for the M_ADJ pattern,
* using cubic subdivision, then make the BMVerts and the new faces.
* using cubic subdivision, then make the #BMVert's and the new faces.
*/
static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv, BoundVert *vpipe)
{
@@ -5312,7 +5318,7 @@ static void bevel_build_cutoff(BevelParams *bp, BMesh *bm, BevVert *bv)
i = bndv->index;
/* Find the "down" direction for this side of the cutoff face. */
/* Find the direction along the intersection of the two adjecent profile normals. */
/* Find the direction along the intersection of the two adjacent profile normals. */
cross_v3_v3v3(down_direction, bndv->profile.plane_no, bndv->prev->profile.plane_no);
if (dot_v3v3(down_direction, bv->v->no) > 0.0f) {
negate_v3(down_direction);
@@ -7121,7 +7127,7 @@ static float find_profile_fullness(BevelParams *bp)
/**
* Fills the ProfileSpacing struct with the 2D coordinates for the profile's vertices.
* The superellipse used for multisegment profiles does not have a closed-form way
* The superellipse used for multi-segment profiles does not have a closed-form way
* to generate evenly spaced points along an arc. We use an expensive search procedure
* to find the parameter values that lead to bp->seg even chords.
* We also want spacing for a number of segments that is a power of 2 >= bp->seg (but at least 4).

View File

@@ -325,27 +325,31 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata,
if (sldata->renderpass_ubo.combined == NULL) {
sldata->renderpass_ubo.combined = DRW_uniformbuffer_create(
sizeof(EEVEE_RenderPassData),
&(const EEVEE_RenderPassData){true, true, true, true, true, false});
&(const EEVEE_RenderPassData){true, true, true, true, true, false, false});
sldata->renderpass_ubo.diff_color = DRW_uniformbuffer_create(
sizeof(EEVEE_RenderPassData),
&(const EEVEE_RenderPassData){true, false, false, false, false, true});
&(const EEVEE_RenderPassData){true, false, false, false, false, true, false});
sldata->renderpass_ubo.diff_light = DRW_uniformbuffer_create(
sizeof(EEVEE_RenderPassData),
&(const EEVEE_RenderPassData){true, true, false, false, false, false});
&(const EEVEE_RenderPassData){true, true, false, false, false, false, false});
sldata->renderpass_ubo.spec_color = DRW_uniformbuffer_create(
sizeof(EEVEE_RenderPassData),
&(const EEVEE_RenderPassData){false, false, true, false, false, false});
&(const EEVEE_RenderPassData){false, false, true, false, false, false, false});
sldata->renderpass_ubo.spec_light = DRW_uniformbuffer_create(
sizeof(EEVEE_RenderPassData),
&(const EEVEE_RenderPassData){false, false, true, true, false, false});
&(const EEVEE_RenderPassData){false, false, true, true, false, false, false});
sldata->renderpass_ubo.emit = DRW_uniformbuffer_create(
sizeof(EEVEE_RenderPassData),
&(const EEVEE_RenderPassData){false, false, false, false, true, false});
&(const EEVEE_RenderPassData){false, false, false, false, true, false, false});
sldata->renderpass_ubo.environment = DRW_uniformbuffer_create(
sizeof(EEVEE_RenderPassData),
&(const EEVEE_RenderPassData){true, true, true, true, true, false, true});
}
/* Used combined pass by default. */
@@ -408,7 +412,7 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_uniform_block_ref(grp, "renderpass_block", &stl->g_data->renderpass_ubo);
DRW_shgroup_call(grp, geom, NULL);
}
@@ -1073,7 +1077,7 @@ void EEVEE_material_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
DRWPass *material_accum_ps = psl->material_accum_ps;
if (pd->render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) {
material_renderpass_accumulate(
fbl, psl->background_accum_ps, pd, txl->env_accum, sldata->renderpass_ubo.combined);
fbl, psl->background_accum_ps, pd, txl->env_accum, sldata->renderpass_ubo.environment);
}
if (pd->render_passes & EEVEE_RENDER_PASS_EMIT) {
material_renderpass_accumulate(

View File

@@ -417,7 +417,8 @@ typedef struct EEVEE_RenderPassData {
int renderPassGlossyLight;
int renderPassEmit;
int renderPassSSSColor;
int _pad[2];
int renderPassEnvironment;
int _pad[1];
} EEVEE_RenderPassData;
/* ************ LIGHT UBO ************* */
@@ -835,6 +836,7 @@ typedef struct EEVEE_ViewLayerData {
/* Material Render passes */
struct {
struct GPUUniformBuffer *combined;
struct GPUUniformBuffer *environment;
struct GPUUniformBuffer *diff_color;
struct GPUUniformBuffer *diff_light;
struct GPUUniformBuffer *spec_color;

View File

@@ -260,10 +260,8 @@ void EEVEE_shadows_update(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
}
if (!sldata->shadow_cube_pool) {
/* TODO shadowcube array. */
int cube_size = linfo->shadow_cube_size + ((true) ? 2 : 0);
sldata->shadow_cube_pool = DRW_texture_create_2d_array(cube_size,
cube_size,
sldata->shadow_cube_pool = DRW_texture_create_2d_array(linfo->shadow_cube_size,
linfo->shadow_cube_size,
max_ii(1, linfo->num_cube_layer * 6),
shadow_pool_format,
DRW_TEX_FILTER | DRW_TEX_COMPARE,

View File

@@ -94,6 +94,7 @@ layout(std140) uniform renderpass_block
bool renderPassGlossyLight;
bool renderPassEmit;
bool renderPassSSSColor;
bool renderPassEnvironment;
};
vec3 render_pass_diffuse_mask(vec3 diffuse_color, vec3 diffuse_light)

View File

@@ -269,6 +269,7 @@ void OVERLAY_edit_mesh_cache_populate(OVERLAY_Data *vedata, Object *ob)
OVERLAY_PrivateData *pd = vedata->stl->pd;
struct GPUBatch *geom = NULL;
bool draw_as_solid = (ob->dt > OB_WIRE);
bool do_in_front = (ob->dtx & OB_DRAWXRAY) != 0;
bool do_occlude_wire = (pd->edit_mesh.flag & V3D_OVERLAY_EDIT_OCCLUDE_WIRE) != 0;
bool do_show_mesh_analysis = (pd->edit_mesh.flag & V3D_OVERLAY_EDIT_STATVIS) != 0;
@@ -283,7 +284,7 @@ void OVERLAY_edit_mesh_cache_populate(OVERLAY_Data *vedata, Object *ob)
}
}
if (do_occlude_wire || do_in_front) {
if (do_occlude_wire || (do_in_front && draw_as_solid)) {
geom = DRW_cache_mesh_surface_get(ob);
DRW_shgroup_call_no_cull(pd->edit_mesh_depth_grp[do_in_front], geom, ob);
}

View File

@@ -254,11 +254,18 @@ void OVERLAY_paint_draw(OVERLAY_Data *vedata)
OVERLAY_PrivateData *pd = stl->pd;
OVERLAY_PassList *psl = vedata->psl;
OVERLAY_FramebufferList *fbl = vedata->fbl;
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
if (DRW_state_is_fbo()) {
/* Paint overlay needs final color because of multiply blend mode. */
GPU_framebuffer_bind(pd->painting.in_front ? dfbl->in_front_fb : dfbl->default_fb);
if (pd->painting.alpha_blending) {
GPU_framebuffer_bind(pd->painting.in_front ? fbl->overlay_in_front_fb :
fbl->overlay_default_fb);
}
else {
/* Paint overlay needs final color because of multiply blend mode. */
GPU_framebuffer_bind(pd->painting.in_front ? dfbl->in_front_fb : dfbl->default_fb);
}
}
if (psl->paint_depth_ps) {

View File

@@ -62,10 +62,11 @@ void OVERLAY_sculpt_cache_populate(OVERLAY_Data *vedata, Object *ob)
void OVERLAY_sculpt_draw(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
if (DRW_state_is_fbo()) {
GPU_framebuffer_bind(dfbl->default_fb);
GPU_framebuffer_bind(pd->painting.in_front ? dfbl->in_front_fb : dfbl->default_fb);
}
DRW_draw_pass(psl->sculpt_mask_ps);

View File

@@ -2356,7 +2356,6 @@ static void extract_tan_ex(const MeshRenderData *mr, GPUVertBuf *vbo, const bool
/* Start Fresh */
CustomData loop_data;
CustomData_reset(&loop_data);
CustomData *ldata = cd_ldata;
if (tan_len != 0 || use_orco_tan) {
short tangent_mask = 0;
bool calc_active_tangent = false;
@@ -2368,7 +2367,7 @@ static void extract_tan_ex(const MeshRenderData *mr, GPUVertBuf *vbo, const bool
mr->poly_normals,
mr->loop_normals,
orco,
cd_ldata,
&loop_data,
mr->loop_len,
&tangent_mask);
}
@@ -2389,13 +2388,12 @@ static void extract_tan_ex(const MeshRenderData *mr, GPUVertBuf *vbo, const bool
&loop_data,
mr->loop_len,
&tangent_mask);
ldata = &loop_data;
}
}
if (use_orco_tan) {
char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
const char *layer_name = CustomData_get_layer_name(cd_ldata, CD_TANGENT, 0);
const char *layer_name = CustomData_get_layer_name(&loop_data, CD_TANGENT, 0);
GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
BLI_snprintf(attr_name, sizeof(*attr_name), "t%s", attr_safe_name);
GPU_vertformat_attr_add(&format, attr_name, comp_type, 4, fetch_mode);
@@ -2421,7 +2419,8 @@ static void extract_tan_ex(const MeshRenderData *mr, GPUVertBuf *vbo, const bool
short(*tan_data)[4] = (short(*)[4])vbo->data;
for (int i = 0; i < tan_len; i++) {
const char *name = tangent_names[i];
float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_named(ldata, CD_TANGENT, name);
float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_named(
&loop_data, CD_TANGENT, name);
for (int ml_index = 0; ml_index < mr->loop_len; ml_index++) {
normal_float_to_short_v3(*tan_data, layer_data[ml_index]);
(*tan_data)[3] = (layer_data[ml_index][3] > 0.0f) ? SHRT_MAX : SHRT_MIN;
@@ -2429,7 +2428,7 @@ static void extract_tan_ex(const MeshRenderData *mr, GPUVertBuf *vbo, const bool
}
}
if (use_orco_tan) {
float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_n(ldata, CD_TANGENT, 0);
float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_n(&loop_data, CD_TANGENT, 0);
for (int ml_index = 0; ml_index < mr->loop_len; ml_index++) {
normal_float_to_short_v3(*tan_data, layer_data[ml_index]);
(*tan_data)[3] = (layer_data[ml_index][3] > 0.0f) ? SHRT_MAX : SHRT_MIN;
@@ -2441,7 +2440,8 @@ static void extract_tan_ex(const MeshRenderData *mr, GPUVertBuf *vbo, const bool
GPUPackedNormal *tan_data = (GPUPackedNormal *)vbo->data;
for (int i = 0; i < tan_len; i++) {
const char *name = tangent_names[i];
float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_named(ldata, CD_TANGENT, name);
float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_named(
&loop_data, CD_TANGENT, name);
for (int ml_index = 0; ml_index < mr->loop_len; ml_index++) {
*tan_data = GPU_normal_convert_i10_v3(layer_data[ml_index]);
tan_data->w = (layer_data[ml_index][3] > 0.0f) ? 1 : -2;
@@ -2449,7 +2449,7 @@ static void extract_tan_ex(const MeshRenderData *mr, GPUVertBuf *vbo, const bool
}
}
if (use_orco_tan) {
float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_n(ldata, CD_TANGENT, 0);
float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_n(&loop_data, CD_TANGENT, 0);
for (int ml_index = 0; ml_index < mr->loop_len; ml_index++) {
*tan_data = GPU_normal_convert_i10_v3(layer_data[ml_index]);
tan_data->w = (layer_data[ml_index][3] > 0.0f) ? 1 : -2;
@@ -2458,7 +2458,6 @@ static void extract_tan_ex(const MeshRenderData *mr, GPUVertBuf *vbo, const bool
}
}
CustomData_free_layers(ldata, CD_TANGENT, mr->loop_len);
CustomData_free(&loop_data, mr->loop_len);
}

View File

@@ -509,5 +509,5 @@ static GPUTexture *DRW_create_weight_colorramp_texture(void)
pixels[i][3] = 1.0f;
}
return GPU_texture_create_1d(256, GPU_RGBA8, pixels[0], error);
return GPU_texture_create_1d(256, GPU_SRGB8_A8, pixels[0], error);
}

View File

@@ -695,6 +695,7 @@ static void gpencil_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
bool is_depth = (bool)(*align_flag & (GP_PROJECT_DEPTH_VIEW | GP_PROJECT_DEPTH_STROKE));
const bool is_camera = (bool)(ts->gp_sculpt.lock_axis == 0) &&
(tgpi->rv3d->persp == RV3D_CAMOB) && (!is_depth);
const bool is_vertex_stroke = GPENCIL_USE_VERTEX_COLOR_STROKE(ts, brush);
if (tgpi->type == GP_STROKE_BOX) {
gps->totpoints = (tgpi->tot_edges * 4 + tgpi->tot_stored_edges);
@@ -1019,7 +1020,12 @@ static void gpencil_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
pt->time = 0.0f;
pt->flag = 0;
pt->uv_fac = tpt->uv_fac;
copy_v4_v4(pt->vert_color, tpt->vert_color);
if (is_vertex_stroke) {
copy_v4_v4(pt->vert_color, tpt->vert_color);
}
else {
zero_v4(pt->vert_color);
}
if (gps->dvert != NULL) {
MDeformVert *dvert = &gps->dvert[i];

View File

@@ -1772,6 +1772,21 @@ static void copy_object_set_idnew(bContext *C)
}
CTX_DATA_END;
#ifndef NDEBUG
/* Call to `BKE_libblock_relink_to_newid` above is supposed to have cleared all those flags. */
ID *id_iter;
FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
if (GS(id_iter->name) == ID_OB) {
/* Not all duplicated objects would be used by other newly duplicated data, so their flag
* will not always be cleared. */
continue;
}
BLI_assert((id_iter->tag & LIB_TAG_NEW) == 0);
}
FOREACH_MAIN_ID_END;
#endif
BKE_main_id_tag_all(bmain, LIB_TAG_NEW, false);
BKE_main_id_clear_newpoins(bmain);
}
@@ -2907,9 +2922,14 @@ static int duplicate_exec(bContext *C, wmOperator *op)
const bool linked = RNA_boolean_get(op->ptr, "linked");
const eDupli_ID_Flags dupflag = (linked) ? 0 : (eDupli_ID_Flags)U.dupflag;
/* We need to handle that here ourselves, because we may duplicate several objects, in which case
* we also want to remap pointers between those... */
BKE_main_id_tag_all(bmain, LIB_TAG_NEW, false);
BKE_main_id_clear_newpoins(bmain);
CTX_DATA_BEGIN (C, Base *, base, selected_bases) {
Base *basen = object_add_duplicate_internal(
bmain, scene, view_layer, base->object, dupflag, 0);
bmain, scene, view_layer, base->object, dupflag, LIB_ID_DUPLICATE_IS_SUBPROCESS);
/* note that this is safe to do with this context iterator,
* the list is made in advance */
@@ -2931,6 +2951,7 @@ static int duplicate_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
/* Note that this will also clear newid pointers and tags. */
copy_object_set_idnew(C);
ED_outliner_select_sync_from_object_tag(C);

View File

@@ -2409,9 +2409,9 @@ static int make_override_library_exec(bContext *C, wmOperator *op)
}
}
/* The we tag all intermediary data-blocks in-between to overridden ones (e.g. if a shapekey has
* a driver using an armature object's bone, we need to override the shapekey/obdata, the objects
* using them, etc.) */
/* Then we tag all intermediary data-blocks in-between two overridden ones (e.g. if a shapekey
* has a driver using an armature object's bone, we need to override the shapekey/obdata, the
* objects using them, etc.) */
make_override_hierarchy_recursive_tag(bmain, id_root);
BKE_main_relations_free(bmain);

View File

@@ -1567,7 +1567,8 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
}
}
else {
if (vc.obact->sculpt->cache && !vc.obact->sculpt->cache->first_time) {
if (vc.obact->sculpt->cache &&
!SCULPT_stroke_is_first_brush_step_of_symmetry_pass(vc.obact->sculpt->cache)) {
wmViewport(&region->winrct);
/* Draw cached dynamic mesh preview lines. */
@@ -1593,7 +1594,8 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
}
if (brush->sculpt_tool == SCULPT_TOOL_MULTIPLANE_SCRAPE &&
brush->flag2 & BRUSH_MULTIPLANE_SCRAPE_PLANES_PREVIEW && !ss->cache->first_time) {
brush->flag2 & BRUSH_MULTIPLANE_SCRAPE_PLANES_PREVIEW &&
!SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) {
GPU_matrix_push_projection();
ED_view3d_draw_setup_view(wm,
CTX_wm_window(C),
@@ -1611,7 +1613,8 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
GPU_matrix_pop_projection();
}
if (brush->sculpt_tool == SCULPT_TOOL_CLOTH && !ss->cache->first_time) {
if (brush->sculpt_tool == SCULPT_TOOL_CLOTH &&
!SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) {
GPU_matrix_push_projection();
ED_view3d_draw_setup_view(CTX_wm_manager(C),
CTX_wm_window(C),

View File

@@ -106,7 +106,7 @@
* This is read-only, for writing use PBVH vertex iterators. There vd.index matches
* the indices used here.
*
* For multires, the same vertex in multiple grids is counted multiple times, with
* For multi-resolution, the same vertex in multiple grids is counted multiple times, with
* different index for each grid. */
void SCULPT_vertex_random_access_init(SculptSession *ss)
@@ -778,6 +778,38 @@ bool SCULPT_vertex_is_boundary(SculptSession *ss, const int index)
}
/* Utils */
/**
* Returns true when the step belongs to the stroke that is directly performed by the brush and
* not by one of the symmetry passes.
*/
bool SCULPT_stroke_is_main_symmetry_pass(StrokeCache *cache)
{
return cache->mirror_symmetry_pass == 0 && cache->radial_symmetry_pass == 0 &&
cache->tile_pass == 0;
}
/**
* Return true only once per stroke on the first symmetry pass, regardless of the symmetry passes
* enabled.
*
* This should be used for functionality that needs to be computed once per stroke of a particular
* tool (allocating memory, updating random seeds...).
*/
bool SCULPT_stroke_is_first_brush_step(StrokeCache *cache)
{
return cache->first_time && cache->mirror_symmetry_pass == 0 &&
cache->radial_symmetry_pass == 0 && cache->tile_pass == 0;
}
/**
* Returns true on the first brush step of each symmetry pass.
*/
bool SCULPT_stroke_is_first_brush_step_of_symmetry_pass(StrokeCache *cache)
{
return cache->first_time;
}
bool SCULPT_check_vertex_pivot_symmetry(const float vco[3], const float pco[3], const char symm)
{
bool is_in_symmetry_area = true;
@@ -1094,8 +1126,10 @@ typedef enum StrokeFlags {
CLIP_Z = 4,
} StrokeFlags;
/* Initialize a SculptOrigVertData for accessing original vertex data;
* handles BMesh, mesh, and multires. */
/**
* Initialize a #SculptOrigVertData for accessing original vertex data;
* handles #BMesh, #Mesh, and multi-resolution.
*/
void SCULPT_orig_vert_data_unode_init(SculptOrigVertData *data, Object *ob, SculptUndoNode *unode)
{
SculptSession *ss = ob->sculpt;
@@ -1115,8 +1149,10 @@ void SCULPT_orig_vert_data_unode_init(SculptOrigVertData *data, Object *ob, Scul
}
}
/* Initialize a SculptOrigVertData for accessing original vertex data;
* handles BMesh, mesh, and multires. */
/**
* Initialize a #SculptOrigVertData for accessing original vertex data;
* handles #BMesh, #Mesh, and multi-resolution.
*/
void SCULPT_orig_vert_data_init(SculptOrigVertData *data, Object *ob, PBVHNode *node)
{
SculptUndoNode *unode;
@@ -1124,8 +1160,9 @@ void SCULPT_orig_vert_data_init(SculptOrigVertData *data, Object *ob, PBVHNode *
SCULPT_orig_vert_data_unode_init(data, ob, unode);
}
/* Update a SculptOrigVertData for a particular vertex from the PBVH
* iterator. */
/**
* Update a #SculptOrigVertData for a particular vertex from the PBVH iterator.
*/
void SCULPT_orig_vert_data_update(SculptOrigVertData *orig_data, PBVHVertexIter *iter)
{
if (orig_data->unode->type == SCULPT_UNDO_COORDS) {
@@ -1261,8 +1298,8 @@ static void sculpt_project_v3(const SculptProjectVector *spvc, const float vec[3
* otherwise.
*
* Factors: some brushes like grab cannot do dynamic topology.
* Others, like smooth, are better without. Same goes for alt-
* key smoothing. */
* Others, like smooth, are better without.
* Same goes for alt-key smoothing. */
bool SCULPT_stroke_is_dynamic_topology(const SculptSession *ss, const Brush *brush)
{
return ((BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) &&
@@ -2118,9 +2155,11 @@ static void calc_area_normal_and_center(
/** \} */
/* Return modified brush strength. Includes the direction of the brush, positive
/**
* Return modified brush strength. Includes the direction of the brush, positive
* values pull vertices, negative values push. Uses tablet pressure and a
* special multiplier found experimentally to scale the strength factor. */
* special multiplier found experimentally to scale the strength factor.
*/
static float brush_strength(const Sculpt *sd,
const StrokeCache *cache,
const float feather,
@@ -2436,7 +2475,9 @@ bool SCULPT_search_circle_cb(PBVHNode *node, void *data_v)
return dist_sq < data->radius_squared || true;
}
/* Handles clipping against a mirror modifier and SCULPT_LOCK axis flags. */
/**
* Handles clipping against a mirror modifier and #SCULPT_LOCK_X/Y/Z axis flags.
*/
void SCULPT_clip(Sculpt *sd, SculptSession *ss, float co[3], const float val[3])
{
for (int i = 0; i < 3; i++) {
@@ -2558,7 +2599,7 @@ static void update_sculpt_normal(Sculpt *sd, Object *ob, PBVHNode **nodes, int t
cache->normal_weight > 0.0f);
if (cache->mirror_symmetry_pass == 0 && cache->radial_symmetry_pass == 0 &&
(cache->first_time || update_normal)) {
(SCULPT_stroke_is_first_brush_step_of_symmetry_pass(cache) || update_normal)) {
calc_sculpt_normal(sd, ob, nodes, totnode, cache->sculpt_normal);
if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) {
project_plane_v3_v3v3(cache->sculpt_normal, cache->sculpt_normal, cache->view_normal);
@@ -3144,7 +3185,7 @@ static void do_slide_relax_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
if (ss->cache->first_time) {
if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) {
return;
}
@@ -3175,10 +3216,9 @@ static void calc_sculpt_plane(
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
if (ss->cache->mirror_symmetry_pass == 0 && ss->cache->radial_symmetry_pass == 0 &&
ss->cache->tile_pass == 0 &&
(ss->cache->first_time || !(brush->flag & BRUSH_ORIGINAL_PLANE) ||
!(brush->flag & BRUSH_ORIGINAL_NORMAL))) {
if (SCULPT_stroke_is_main_symmetry_pass(ss->cache) &&
(SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache) ||
!(brush->flag & BRUSH_ORIGINAL_PLANE) || !(brush->flag & BRUSH_ORIGINAL_NORMAL))) {
switch (brush->sculpt_plane) {
case SCULPT_DISP_DIR_VIEW:
copy_v3_v3(r_area_no, ss->cache->true_view_normal);
@@ -3215,7 +3255,8 @@ static void calc_sculpt_plane(
}
/* For area normal. */
if ((!ss->cache->first_time) && (brush->flag & BRUSH_ORIGINAL_NORMAL)) {
if ((!SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) &&
(brush->flag & BRUSH_ORIGINAL_NORMAL)) {
copy_v3_v3(r_area_no, ss->cache->sculpt_normal);
}
else {
@@ -3223,7 +3264,8 @@ static void calc_sculpt_plane(
}
/* For flatten center. */
if ((!ss->cache->first_time) && (brush->flag & BRUSH_ORIGINAL_PLANE)) {
if ((!SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) &&
(brush->flag & BRUSH_ORIGINAL_PLANE)) {
copy_v3_v3(r_area_co, ss->cache->last_center);
}
else {
@@ -3450,7 +3492,7 @@ static void do_pinch_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
calc_sculpt_plane(sd, ob, nodes, totnode, area_no, area_co);
/* delay the first daub because grab delta is not setup */
if (ss->cache->first_time) {
if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) {
return;
}
@@ -3728,10 +3770,9 @@ void SCULPT_calc_brush_plane(
zero_v3(r_area_co);
zero_v3(r_area_no);
if (ss->cache->mirror_symmetry_pass == 0 && ss->cache->radial_symmetry_pass == 0 &&
ss->cache->tile_pass == 0 &&
(ss->cache->first_time || !(brush->flag & BRUSH_ORIGINAL_PLANE) ||
!(brush->flag & BRUSH_ORIGINAL_NORMAL))) {
if (SCULPT_stroke_is_main_symmetry_pass(ss->cache) &&
(SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache) ||
!(brush->flag & BRUSH_ORIGINAL_PLANE) || !(brush->flag & BRUSH_ORIGINAL_NORMAL))) {
switch (brush->sculpt_plane) {
case SCULPT_DISP_DIR_VIEW:
copy_v3_v3(r_area_no, ss->cache->true_view_normal);
@@ -3768,7 +3809,8 @@ void SCULPT_calc_brush_plane(
}
/* For area normal. */
if ((!ss->cache->first_time) && (brush->flag & BRUSH_ORIGINAL_NORMAL)) {
if ((!SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) &&
(brush->flag & BRUSH_ORIGINAL_NORMAL)) {
copy_v3_v3(r_area_no, ss->cache->sculpt_normal);
}
else {
@@ -3776,7 +3818,8 @@ void SCULPT_calc_brush_plane(
}
/* For flatten center. */
if ((!ss->cache->first_time) && (brush->flag & BRUSH_ORIGINAL_PLANE)) {
if ((!SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) &&
(brush->flag & BRUSH_ORIGINAL_PLANE)) {
copy_v3_v3(r_area_co, ss->cache->last_center);
}
else {
@@ -4725,7 +4768,7 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t
}
/* Delay the first daub because grab delta is not setup. */
if (ss->cache->first_time) {
if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) {
return;
}
@@ -5088,14 +5131,14 @@ static void do_clay_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
}
/* Delay the first daub because grab delta is not setup. */
if (ss->cache->first_time) {
if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) {
ss->cache->clay_thumb_front_angle = 0.0f;
return;
}
/* Simulate the clay accumulation by increasing the plane angle as more samples are added to the
* stroke. */
if (ss->cache->mirror_symmetry_pass == 0) {
if (SCULPT_stroke_is_main_symmetry_pass(ss->cache)) {
ss->cache->clay_thumb_front_angle += 0.8f;
CLAMP(ss->cache->clay_thumb_front_angle, 0.0f, 60.0f);
}
@@ -5407,8 +5450,8 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
* vertices and uses regular coords undo. */
/* It also assigns the paint_face_set here as it needs to be done regardless of the stroke type
* and the number of nodes under the brush influence. */
if (brush->sculpt_tool == SCULPT_TOOL_DRAW_FACE_SETS && ss->cache->first_time &&
ss->cache->mirror_symmetry_pass == 0 && !ss->cache->alt_smooth) {
if (brush->sculpt_tool == SCULPT_TOOL_DRAW_FACE_SETS &&
SCULPT_stroke_is_first_brush_step(ss->cache) && !ss->cache->alt_smooth) {
/* Dyntopo does not support Face Sets data, so it can't store/restore it from undo. */
/* TODO (pablodp606): This check should be done in the undo code and not here, but the rest of
@@ -5450,14 +5493,13 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
update_brush_local_mat(sd, ob);
}
if (ss->cache->first_time && ss->cache->mirror_symmetry_pass == 0) {
if (SCULPT_stroke_is_first_brush_step(ss->cache)) {
if (SCULPT_is_automasking_enabled(sd, ss, brush)) {
SCULPT_automasking_init(sd, ob);
}
}
if (brush->sculpt_tool == SCULPT_TOOL_POSE && ss->cache->first_time &&
ss->cache->mirror_symmetry_pass == 0) {
if (brush->sculpt_tool == SCULPT_TOOL_POSE && SCULPT_stroke_is_first_brush_step(ss->cache)) {
SCULPT_pose_brush_init(sd, ob, ss, brush);
}
@@ -5941,9 +5983,10 @@ static void do_radial_symmetry(Sculpt *sd,
}
}
/* Noise texture gives different values for the same input coord; this
* can tear a multires mesh during sculpting so do a stitch in this
* case. */
/**
* Noise texture gives different values for the same input coord; this
* can tear a multi-resolution mesh during sculpting so do a stitch in this case.
*/
static void sculpt_fix_noise_tear(Sculpt *sd, Object *ob)
{
SculptSession *ss = ob->sculpt;
@@ -5970,7 +6013,7 @@ static void do_symmetrical_brush_actions(Sculpt *sd,
cache->bstrength = brush_strength(sd, cache, feather, ups);
cache->symmetry = symm;
/* symm is a bit combination of XYZ -
/* `symm` is a bit combination of XYZ -
* 1 is mirror X; 2 is Y; 3 is XY; 4 is Z; 5 is XZ; 6 is YZ; 7 is XYZ */
for (int i = 0; i <= symm; i++) {
if (i == 0 || (symm & i && (symm != 5 || i != 3) && (symm != 6 || (i != 3 && i != 5)))) {
@@ -6390,7 +6433,7 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru
sculpt_brush_use_topology_rake(ss, brush)) {
float grab_location[3], imat[4][4], delta[3], loc[3];
if (cache->first_time) {
if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) {
if (tool == SCULPT_TOOL_GRAB && brush->flag & BRUSH_GRAB_ACTIVE_VERTEX) {
copy_v3_v3(cache->orig_grab_location, SCULPT_active_vertex_co_get(ss));
}
@@ -6407,7 +6450,7 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru
ED_view3d_win_to_3d(cache->vc->v3d, cache->vc->region, loc, mouse, grab_location);
/* Compute delta to move verts by. */
if (!cache->first_time) {
if (!SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) {
if (sculpt_needs_delta_from_anchored_origin(brush)) {
sub_v3_v3v3(delta, grab_location, cache->old_grab_location);
invert_m4_m4(imat, ob->obmat);
@@ -6471,7 +6514,7 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru
invert_m4_m4(imat, ob->obmat);
mul_mat3_m4_v3(imat, grab_location);
if (cache->first_time) {
if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) {
copy_v3_v3(cache->rake_data.follow_co, grab_location);
}
@@ -6525,7 +6568,7 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, Po
StrokeCache *cache = ss->cache;
Brush *brush = BKE_paint_brush(&sd->paint);
if (cache->first_time ||
if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache) ||
!((brush->flag & BRUSH_ANCHORED) || (brush->sculpt_tool == SCULPT_TOOL_SNAKE_HOOK) ||
(brush->sculpt_tool == SCULPT_TOOL_ROTATE) || SCULPT_is_cloth_deform_brush(brush))) {
RNA_float_get_array(ptr, "location", cache->true_location);
@@ -6543,7 +6586,7 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, Po
}
/* Truly temporary data that isn't stored in properties. */
if (cache->first_time) {
if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) {
if (!BKE_brush_use_locked_size(scene, brush)) {
cache->initial_radius = paint_calc_object_space_radius(
cache->vc, cache->true_location, BKE_brush_size_get(scene, brush));
@@ -6556,7 +6599,7 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, Po
/* Clay stabilized pressure. */
if (brush->sculpt_tool == SCULPT_TOOL_CLAY_THUMB) {
if (ss->cache->first_time) {
if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) {
for (int i = 0; i < SCULPT_CLAY_STABILIZER_LEN; i++) {
ss->cache->clay_pressure_stabilizer[i] = 0.0f;
}

View File

@@ -640,10 +640,10 @@ void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
* nodes inside the simulation's limits. */
/* Brush stroke types that restore the mesh on each brush step also need the cloth sim data to be
* created on each step. */
if (ss->cache->first_time || !ss->cache->cloth_sim) {
if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache) || !ss->cache->cloth_sim) {
/* The simulation structure only needs to be created on the first symmetry pass. */
if (ss->cache->mirror_symmetry_pass == 0) {
if (SCULPT_stroke_is_first_brush_step(ss->cache)) {
ss->cache->cloth_sim = cloth_brush_simulation_create(
ss, brush->cloth_mass, brush->cloth_damping);
for (int i = 0; i < totverts; i++) {

View File

@@ -183,6 +183,10 @@ bool SCULPT_vertex_any_face_set_visible_get(SculptSession *ss, int index);
void SCULPT_face_sets_visibility_invert(SculptSession *ss);
void SCULPT_face_sets_visibility_all_set(SculptSession *ss, bool visible);
bool SCULPT_stroke_is_main_symmetry_pass(struct StrokeCache *cache);
bool SCULPT_stroke_is_first_brush_step(struct StrokeCache *cache);
bool SCULPT_stroke_is_first_brush_step_of_symmetry_pass(struct StrokeCache *cache);
/* Sculpt Original Data */
typedef struct {
struct BMLog *bm_log;

View File

@@ -257,7 +257,7 @@ void SCULPT_do_multiplane_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes,
}
/* Delay the first daub because grab delta is not setup. */
if (ss->cache->first_time) {
if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) {
ss->cache->multiplane_scrape_angle = 0.0f;
return;
}

View File

@@ -247,8 +247,10 @@ void SCULPT_do_paint_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
return;
}
if (ss->cache->first_time && ss->cache->mirror_symmetry_pass == 0) {
ss->cache->density_seed = BLI_hash_int_01(ss->cache->location[0] * 1000);
if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) {
if (SCULPT_stroke_is_first_brush_step(ss->cache)) {
ss->cache->density_seed = BLI_hash_int_01(ss->cache->location[0] * 1000);
}
return;
}
@@ -444,7 +446,7 @@ void SCULPT_do_smear_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
const int totvert = SCULPT_vertex_count_get(ss);
if (ss->cache->first_time && ss->cache->mirror_symmetry_pass == 0) {
if (SCULPT_stroke_is_first_brush_step(ss->cache)) {
if (!ss->cache->prev_colors) {
ss->cache->prev_colors = MEM_callocN(sizeof(float) * 4 * totvert, "prev colors");
for (int i = 0; i < totvert; i++) {

View File

@@ -612,8 +612,7 @@ void SCULPT_do_surface_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, in
Brush *brush = BKE_paint_brush(&sd->paint);
SculptSession *ss = ob->sculpt;
if (ss->cache->first_time && ss->cache->mirror_symmetry_pass == 0 &&
ss->cache->radial_symmetry_pass == 0) {
if (SCULPT_stroke_is_first_brush_step(ss->cache)) {
BLI_assert(ss->cache->surface_smooth_laplacian_disp == NULL);
ss->cache->surface_smooth_laplacian_disp = MEM_callocN(
SCULPT_vertex_count_get(ss) * 3 * sizeof(float), "HC smooth laplacian b");

View File

@@ -1316,6 +1316,7 @@ static void edge_slide_snap_apply(TransInfo *t, float *value)
if (t->tsnap.snapElem & (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE)) {
float co_dir[3];
sub_v3_v3v3(co_dir, co_dest[side_index], co_orig);
normalize_v3(co_dir);
if (t->tsnap.snapElem & SCE_SNAP_MODE_EDGE) {
transform_constraint_snap_axis_to_edge(t, co_dir, dvec);
}

View File

@@ -556,13 +556,14 @@ static void vert_slide_snap_apply(TransInfo *t, float *value)
getSnapPoint(t, dvec);
sub_v3_v3(dvec, t->tsnap.snapTarget);
if (t->tsnap.snapElem & (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE)) {
float co_dir_3d[3];
sub_v3_v3v3(co_dir_3d, co_curr_3d, co_orig_3d);
float co_dir[3];
sub_v3_v3v3(co_dir, co_curr_3d, co_orig_3d);
normalize_v3(co_dir);
if (t->tsnap.snapElem & SCE_SNAP_MODE_EDGE) {
transform_constraint_snap_axis_to_edge(t, co_dir_3d, dvec);
transform_constraint_snap_axis_to_edge(t, co_dir, dvec);
}
else {
transform_constraint_snap_axis_to_face(t, co_dir_3d, dvec);
transform_constraint_snap_axis_to_face(t, co_dir, dvec);
}
}

View File

@@ -418,18 +418,36 @@ static void draw_uvs(SpaceImage *sima,
col2[3] = overlay_alpha;
float dash_width = (sima->dt_uv & SI_UVDT_DASH) ? (4.0f * UI_DPI_FAC) : 9999.0f;
eGPUBuiltinShader shader = (interpedges) ? GPU_SHADER_2D_UV_EDGES_SMOOTH :
GPU_SHADER_2D_UV_EDGES;
GPU_batch_program_set_builtin(
batch->edges, (interpedges) ? GPU_SHADER_2D_UV_EDGES_SMOOTH : GPU_SHADER_2D_UV_EDGES);
#ifndef __APPLE__
GPU_batch_program_set_builtin(batch->edges, shader);
#endif
if (sima->dt_uv == SI_UVDT_OUTLINE) {
#ifdef __APPLE__
/* Apple drivers do not support wide line. This is a workaround awaiting the 2D view
* refactor. Limiting to OSX since this will slow down the drawing. (see T76806) */
GPU_batch_program_set_builtin(batch->edges, GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
float viewport[4];
GPU_viewport_size_get_f(viewport);
/* No U.pixelsize scaling for now since the inner line is not scalled. */
GPU_batch_uniform_1f(batch->edges, "lineWidth", 2.0f);
GPU_batch_uniform_4f(batch->edges, "color", 0.0f, 0.0f, 0.0f, 1.0f);
GPU_batch_uniform_2fv(batch->edges, "viewportSize", &viewport[2]);
GPU_batch_draw(batch->edges);
#else
/* Black Outline. */
GPU_line_width(3.0f);
GPU_batch_uniform_4f(batch->edges, "edgeColor", 0.0f, 0.0f, 0.0f, overlay_alpha);
GPU_batch_uniform_4f(batch->edges, "selectColor", 0.0f, 0.0f, 0.0f, overlay_alpha);
GPU_batch_uniform_1f(batch->edges, "dashWidth", dash_width);
GPU_batch_draw(batch->edges);
#endif
UI_GetThemeColor3fv(TH_WIRE_EDIT, col1);
}
else if (sima->dt_uv == SI_UVDT_BLACK) {

View File

@@ -3,8 +3,9 @@ uniform float backgroundAlpha;
void node_output_world(Closure surface, Closure volume, out Closure result)
{
#ifndef VOLUMETRICS
result.radiance = surface.radiance * backgroundAlpha;
result.transmittance = vec3(1.0 - backgroundAlpha);
float alpha = renderPassEnvironment ? 1.0 : backgroundAlpha;
result.radiance = surface.radiance * alpha;
result.transmittance = vec3(1.0 - alpha);
#else
result = volume;
#endif /* VOLUMETRICS */

View File

@@ -580,6 +580,7 @@ typedef struct FluidDomainSettings {
int cache_frame_pause_mesh;
int cache_frame_pause_particles;
int cache_frame_pause_guide;
int cache_frame_offset;
int cache_flag;
char cache_mesh_format;
char cache_data_format;
@@ -589,7 +590,7 @@ typedef struct FluidDomainSettings {
char error[64]; /* Bake error description. */
short cache_type;
char cache_id[4]; /* Run-time only */
char _pad8[6];
char _pad8[2];
/* Time options. */
float dt;

View File

@@ -2002,13 +2002,28 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "cache_frame_start");
RNA_def_property_range(prop, -MAXFRAME, MAXFRAME);
RNA_def_property_int_funcs(prop, NULL, "rna_Fluid_cache_startframe_set", NULL);
RNA_def_property_ui_text(prop, "Start", "Frame on which the simulation starts");
RNA_def_property_ui_text(
prop,
"Start",
"Frame on which the simulation starts. This is the first frame that will be baked");
prop = RNA_def_property(srna, "cache_frame_end", PROP_INT, PROP_TIME);
RNA_def_property_int_sdna(prop, NULL, "cache_frame_end");
RNA_def_property_range(prop, -MAXFRAME, MAXFRAME);
RNA_def_property_int_funcs(prop, NULL, "rna_Fluid_cache_endframe_set", NULL);
RNA_def_property_ui_text(prop, "End", "Frame on which the simulation stops");
RNA_def_property_ui_text(
prop,
"End",
"Frame on which the simulation stops. This is the last frame that will be baked");
prop = RNA_def_property(srna, "cache_frame_offset", PROP_INT, PROP_TIME);
RNA_def_property_int_sdna(prop, NULL, "cache_frame_offset");
RNA_def_property_range(prop, -MAXFRAME, MAXFRAME);
RNA_def_property_ui_text(
prop,
"Offset",
"Frame offset that is used when loading the simulation from the cache. It is not considered "
"when baking the simulation, only when loading it");
prop = RNA_def_property(srna, "cache_frame_pause_data", PROP_INT, PROP_TIME);
RNA_def_property_int_sdna(prop, NULL, "cache_frame_pause_data");

View File

@@ -236,12 +236,10 @@ static void modifier_ops_extra_draw(bContext *C, uiLayout *layout, void *md_v)
uiLayoutSetUnitsX(layout, 4.0f);
/* Apply. */
uiItemEnumO(layout,
"OBJECT_OT_modifier_apply",
CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply"),
ICON_CHECKMARK,
"apply_as",
MODIFIER_APPLY_DATA);
uiItemO(layout,
CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply"),
ICON_CHECKMARK,
"OBJECT_OT_modifier_apply");
/* Apply as shapekey. */
if (BKE_modifier_is_same_topology(md) && !BKE_modifier_is_non_geometrical(md)) {

View File

@@ -125,7 +125,7 @@ void main_python_exit(void);
* patched USD (see usd.diff) to avoid that particular static constructor, and have an
* initialization function instead.
*
* This function is implemented in the USD source code, pxr/base/lib/plug/initConfig.cpp.
* This function is implemented in the USD source code, `pxr/base/lib/plug/initConfig.cpp`.
*/
void usd_initialise_plugin_path(const char *datafiles_usd_path);
#endif