Compare commits
25 Commits
asset-uuid
...
buildbot-l
Author | SHA1 | Date | |
---|---|---|---|
2cbc328bdc | |||
314783f2e7 | |||
fb0f0f4d79 | |||
f58f09c9a9 | |||
![]() |
46ae115b88 | ||
![]() |
ba2c039b05 | ||
945d0269e3 | |||
22197d7f8a | |||
26ffed7466 | |||
afd976a3b4 | |||
8bee200e2f | |||
52b125a790 | |||
b6f35531b6 | |||
e16972389e | |||
792cb8bdc7 | |||
755c5c6e4c | |||
4723644e7f | |||
6358c7754c | |||
bf5a656ff6 | |||
11a1ddfd30 | |||
f228a8948b | |||
927448a1da | |||
e9d1d1f725 | |||
2788b0261c | |||
f4f00661a5 |
34
build_files/buildbot-lts/README.md
Normal file
34
build_files/buildbot-lts/README.md
Normal 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
|
||||
|
36
build_files/buildbot-lts/docker/Dockerfile
Normal file
36
build_files/buildbot-lts/docker/Dockerfile
Normal 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"]
|
4
build_files/buildbot-lts/docker/bin/create_checksum.sh
Executable file
4
build_files/buildbot-lts/docker/bin/create_checksum.sh
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
md5sum $1 > $2.md5
|
||||
sha256sum $1 > $2.sha256
|
7
build_files/buildbot-lts/docker/bin/upload_file.sh
Executable file
7
build_files/buildbot-lts/docker/bin/upload_file.sh
Executable 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
|
20
build_files/buildbot-lts/docker/buildbot.tac
Normal file
20
build_files/buildbot-lts/docker/buildbot.tac
Normal 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)
|
36
build_files/buildbot-lts/docker/docker-compose.yml
Normal file
36
build_files/buildbot-lts/docker/docker-compose.yml
Normal 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
|
18
build_files/buildbot-lts/docker/docker-entrypoint.sh
Executable file
18
build_files/buildbot-lts/docker/docker-entrypoint.sh
Executable 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 "$@"
|
240
build_files/buildbot-lts/docker/master.cfg
Normal file
240
build_files/buildbot-lts/docker/master.cfg
Normal 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),
|
||||
}
|
27
build_files/buildbot-lts/docker/worker/Dockerfile
Normal file
27
build_files/buildbot-lts/docker/worker/Dockerfile
Normal 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"]
|
39
build_files/buildbot-lts/docker/worker/buildbot.tac
Normal file
39
build_files/buildbot-lts/docker/worker/buildbot.tac
Normal 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)
|
@@ -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"
|
||||
|
@@ -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)++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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++) {
|
||||
|
@@ -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,
|
||||
|
@@ -20,7 +20,7 @@
|
||||
/** \file
|
||||
* \ingroup bli
|
||||
*
|
||||
* Utility functions for variable size bitmasks.
|
||||
* Utility functions for variable size bit-masks.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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).
|
||||
|
@@ -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(
|
||||
|
@@ -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;
|
||||
|
@@ -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,
|
||||
|
@@ -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)
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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) {
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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];
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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(®ion->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),
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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++) {
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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++) {
|
||||
|
@@ -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");
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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) {
|
||||
|
@@ -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 */
|
||||
|
@@ -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;
|
||||
|
@@ -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");
|
||||
|
@@ -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)) {
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user