Compare commits
279 Commits
tmp-workbe
...
soc-2010-j
Author | SHA1 | Date | |
---|---|---|---|
ae33eeae79 | |||
cdb4eaf2a3 | |||
820f3b2e50 | |||
6870406360 | |||
3e208c5e37 | |||
1badec46ab | |||
880cb4cd3b | |||
c6c1a6a2d6 | |||
d35a381eb8 | |||
1c1a511f47 | |||
c2a5af0132 | |||
9a7fe52124 | |||
3013006dee | |||
cf43ef55a8 | |||
3cf307326b | |||
0f52f5d373 | |||
ef006405d3 | |||
c602ae5386 | |||
5da1c418b3 | |||
20e618e4c9 | |||
f05b333c43 | |||
ef3101f614 | |||
e854b75dcc | |||
220046fa03 | |||
cb67f28a6d | |||
b85c9aea7a | |||
ca2c63aa73 | |||
c93dfedd44 | |||
f050b6210f | |||
be991ffc3e | |||
3dc60d9920 | |||
f7d618c4bf | |||
629b1decaa | |||
70509696a7 | |||
2fba394c85 | |||
39028302d3 | |||
a1af6554b3 | |||
ecbee901e2 | |||
5d6c479929 | |||
2ad21270f4 | |||
e938cc25bc | |||
350a377c0e | |||
9957f7c4e7 | |||
696c9cc995 | |||
9db1fb9413 | |||
0d8a8ae8da | |||
af3560b320 | |||
560e0e6e43 | |||
72a7c7f5d6 | |||
0b5cb4b3ea | |||
203eb91efd | |||
b781c87d19 | |||
a8475e542c | |||
b2191f4b41 | |||
aeab428814 | |||
7db80e8efa | |||
dedc356012 | |||
086ccc52df | |||
a57a1880db | |||
abb4a42707 | |||
cd032c07a2 | |||
d12724a388 | |||
e82094a70a | |||
ba32b73a11 | |||
82f1583eb4 | |||
38646bce6f | |||
9215a7fe64 | |||
fce8737589 | |||
1474ee92c2 | |||
67805fcd62 | |||
cdf0aac6c9 | |||
d88fe4df3b | |||
63cdbb9af5 | |||
5476ea2247 | |||
493dde9ac1 | |||
222c4ad5ef | |||
53d0bc5aec | |||
b6d0073011 | |||
4b6447c92e | |||
fb49a4f5c8 | |||
3555c652ec | |||
2f784de397 | |||
0c486ebc4b | |||
e99c1c32d8 | |||
d4e55cdb29 | |||
39df6c7945 | |||
176420e748 | |||
e1195b384d | |||
127192ca51 | |||
e7c1cc8c32 | |||
2ab298e5f2 | |||
0eee36cc03 | |||
e3497e3032 | |||
cae7d96591 | |||
9c457e5a5d | |||
daf3b33c86 | |||
bb2d988204 | |||
cc30cbddd7 | |||
76305facaa | |||
fbe49b9572 | |||
921cc579b9 | |||
fe6bc2c69f | |||
efd97d85f5 | |||
7f8f7fbbec | |||
c9ecb5d4fa | |||
1c2c8cee36 | |||
0b87b24730 | |||
6fbf5f2f59 | |||
d88dbeb666 | |||
1d41095a1e | |||
085a1a4b7c | |||
1166064e65 | |||
c5e74fd7a7 | |||
bb4d607c84 | |||
a19a9953c8 | |||
b7420b8dbc | |||
eb20c54509 | |||
82f71b9f10 | |||
dff427723d | |||
a6af5fe147 | |||
f002c308f9 | |||
789f1105ac | |||
d09849b14f | |||
67e4c6ea11 | |||
23609c5a06 | |||
49a3054ea6 | |||
6e4f4912df | |||
58c20f610d | |||
6a1511b766 | |||
6bbf8ae7b6 | |||
cf705abfc8 | |||
0cae75dc1a | |||
4f0bf3825c | |||
f582e8227d | |||
a838ec55ed | |||
b5879cddf4 | |||
8edc4d92bd | |||
ffd8ef9b03 | |||
27fff19cc4 | |||
6d24919407 | |||
bab7ecd500 | |||
4a3bc12d85 | |||
b21a7614d5 | |||
e9044deb5e | |||
7481640e02 | |||
656add2fb4 | |||
c638c899fe | |||
a7a52794d1 | |||
e90de72310 | |||
ee0a1cb297 | |||
1cf6f6a9d6 | |||
a3da3f84cb | |||
a648b34af3 | |||
15034513ad | |||
390a426cfa | |||
e04aebef67 | |||
2eb4163ecc | |||
e5fb94c5b0 | |||
d9ff9568e1 | |||
b7964e2463 | |||
80f6f7f0f0 | |||
312a8c0e9f | |||
a6cf43cfd1 | |||
f0804bc541 | |||
d4fead4275 | |||
1102107f80 | |||
288e870f14 | |||
07adfad0a4 | |||
5d3bc7fc79 | |||
256d0beb4d | |||
6b55991561 | |||
5ea7398379 | |||
e20f2fd2df | |||
834c82c86b | |||
27632a3a04 | |||
82230f1758 | |||
8e641e4b53 | |||
f8df37cb3a | |||
4d51da159b | |||
6650c7cce5 | |||
6ccc5b6324 | |||
50c9532640 | |||
1916daf1cd | |||
3519627563 | |||
90743aba36 | |||
970448e530 | |||
309ad75d88 | |||
50dc87ba8a | |||
b43b2cb8e3 | |||
6e2872ffda | |||
9813d50d62 | |||
17b127071a | |||
c1489be2a5 | |||
ab5be0e5f6 | |||
f1e9fc155e | |||
1851c0d7e0 | |||
004c033b50 | |||
7f0491cf2e | |||
0d5a21ec9a | |||
271eca93e4 | |||
661f9822ac | |||
ca9a5d9f30 | |||
1dafc5db30 | |||
9d4a72da4c | |||
defb59adc8 | |||
5b0a704c82 | |||
a29aad5303 | |||
b8e60d6580 | |||
40072b9ec4 | |||
84126037b0 | |||
84632650d3 | |||
4ec273efd2 | |||
9c47c7a506 | |||
2a12ace1e3 | |||
e3b6db0abf | |||
9031857faf | |||
39cbe216e1 | |||
cbe1825f34 | |||
8bc35a6faf | |||
748b216e0b | |||
6129aaa025 | |||
476dd3c5ac | |||
15d18a881b | |||
32591dbbcb | |||
dc6f7371cb | |||
7f99bd216f | |||
70ce23b116 | |||
3c4dafc04d | |||
47e1c65b94 | |||
5bf86c54d8 | |||
9760c87a32 | |||
1cb2dc4cc8 | |||
66d8881098 | |||
e5199cf634 | |||
4745049f63 | |||
801b807014 | |||
27bbd3ec54 | |||
e38aee4272 | |||
f0d79eda7b | |||
76437f993e | |||
c0c3d1779b | |||
69d5ff57e5 | |||
e42409b0be | |||
63f84e789f | |||
e999d99433 | |||
cc3504505c | |||
55776bc224 | |||
c51ecdcf18 | |||
6be21d4451 | |||
fa3fb674e2 | |||
5117cf8702 | |||
615b28f1a3 | |||
070ae783ea | |||
edb4859931 | |||
f3187de906 | |||
2429c3ab77 | |||
2b540a6955 | |||
19942d1922 | |||
150de1c42c | |||
40b11a4a14 | |||
64f5ac101f | |||
03a1f75a13 | |||
3ee4280a96 | |||
f57558dba4 | |||
07771c2061 | |||
2f54416309 | |||
92bdf82f44 | |||
a09cdc7805 | |||
bf1a1b6929 | |||
aa5c75eefe | |||
9939b873f8 | |||
07fda78dde | |||
dcf30264bd | |||
deb36b3825 | |||
27db4f0dd6 | |||
59ed9a1c0d | |||
f741263037 | |||
413aca1d99 | |||
5a5bf04916 |
@@ -156,6 +156,7 @@ if(UNIX AND NOT APPLE)
|
||||
option(WITH_INSTALL_PORTABLE "Install redistributeable runtime, otherwise install into CMAKE_INSTALL_PREFIX" ON)
|
||||
endif()
|
||||
option(WITH_PYTHON_INSTALL "Copy system python into the blender install folder" ON)
|
||||
option(WITH_ONSURFACEBRUSH "Enable use of the 'on-surface brush' for paint/sculpt. Requires a stencil buffer, GL_depth_texture, and GLSL" ON)
|
||||
|
||||
# disable for now, but plan to support on all platforms eventually
|
||||
option(WITH_MEM_JEMALLOC "Enable malloc replacement (http://www.canonware.com/jemalloc)" OFF)
|
||||
@@ -988,6 +989,10 @@ if(WITH_RAYOPTIMIZATION)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_ONSURFACEBRUSH)
|
||||
add_definitions(-DWITH_ONSURFACEBRUSH)
|
||||
endif(WITH_ONSURFACEBRUSH)
|
||||
|
||||
if(WITH_IMAGE_OPENJPEG)
|
||||
if(UNIX AND NOT APPLE)
|
||||
set(OPENJPEG /usr)
|
||||
|
@@ -149,6 +149,9 @@ BF_REDCODE_LIB = ''
|
||||
BF_REDCODE_INC = '${BF_REDCODE}/include'
|
||||
BF_REDCODE_LIBPATH='${BF_REDCODE}/lib'
|
||||
|
||||
#On-Surface Brush
|
||||
WITH_BF_ONSURFACEBRUSH = True
|
||||
|
||||
# Mesa Libs should go here if your using them as well....
|
||||
WITH_BF_STATICOPENGL = 'false'
|
||||
BF_OPENGL = '/usr'
|
||||
|
@@ -265,6 +265,8 @@ if MACOSX_ARCHITECTURE == 'i386':
|
||||
elif MACOSX_ARCHITECTURE == 'x86_64':
|
||||
BF_RAYOPTIMIZATION_SSE_FLAGS = ['-msse','-msse2']
|
||||
|
||||
#On-Surface Brush
|
||||
WITH_BF_ONSURFACEBRUSH = True
|
||||
|
||||
#############################################################################
|
||||
################### various compile settings and flags ##################
|
||||
|
@@ -174,6 +174,9 @@ WITH_BF_OPENMP = True
|
||||
WITH_BF_RAYOPTIMIZATION = True
|
||||
BF_RAYOPTIMIZATION_SSE_FLAGS = ['-msse','-pthread']
|
||||
|
||||
#On-Surface Brush
|
||||
WITH_BF_ONSURFACEBRUSH = True
|
||||
|
||||
CCFLAGS = ['-pipe','-fPIC','-funsigned-char','-fno-strict-aliasing','-D_LARGEFILE_SOURCE','-D_FILE_OFFSET_BITS=64','-D_LARGEFILE64_SOURCE']
|
||||
|
||||
CPPFLAGS = []
|
||||
|
@@ -174,6 +174,9 @@ WITH_BF_OPENMP = True
|
||||
WITH_BF_RAYOPTIMIZATION = True
|
||||
BF_RAYOPTIMIZATION_SSE_FLAGS = ['-msse','-pthread']
|
||||
|
||||
#On-Surface Brush
|
||||
WITH_BF_ONSURFACEBRUSH = True
|
||||
|
||||
CCFLAGS = ['-pipe','-fPIC','-funsigned-char','-fno-strict-aliasing','-D_LARGEFILE_SOURCE','-D_FILE_OFFSET_BITS=64','-D_LARGEFILE64_SOURCE']
|
||||
|
||||
CPPFLAGS = []
|
||||
|
@@ -174,6 +174,9 @@ WITH_BF_OPENMP = True
|
||||
WITH_BF_RAYOPTIMIZATION = True
|
||||
BF_RAYOPTIMIZATION_SSE_FLAGS = ['-msse','-pthread']
|
||||
|
||||
#On-Surface Brush
|
||||
WITH_BF_ONSURFACEBRUSH = True
|
||||
|
||||
CCFLAGS = ['-pipe','-fPIC','-funsigned-char','-fno-strict-aliasing','-D_LARGEFILE_SOURCE','-D_FILE_OFFSET_BITS=64','-D_LARGEFILE64_SOURCE']
|
||||
|
||||
CPPFLAGS = []
|
||||
|
@@ -154,6 +154,8 @@ BF_OPENGL_LIB = 'GL GLU X11 Xi Xext'
|
||||
BF_OPENGL_LIBPATH = '/usr/X11R6/lib'
|
||||
BF_OPENGL_LIB_STATIC = '${BF_OPENGL}/libGL.a ${BF_OPENGL}/libGLU.a ${BF_OPENGL}/libXxf86vm.a ${BF_OPENGL}/libX11.a ${BF_OPENGL}/libXi.a ${BF_OPENGL}/libXext.a ${BF_OPENGL}/libXxf86vm.a'
|
||||
|
||||
#On-Surface Brush
|
||||
WITH_BF_ONSURFACEBRUSH = True
|
||||
|
||||
CC = 'c99'
|
||||
CXX = 'CC'
|
||||
|
@@ -192,6 +192,9 @@ WITH_BF_OPENMP = True
|
||||
WITH_BF_RAYOPTIMIZATION = True
|
||||
BF_RAYOPTIMIZATION_SSE_FLAGS = ['-msse','-pthread']
|
||||
|
||||
#On-Surface Brush
|
||||
WITH_BF_ONSURFACEBRUSH = True
|
||||
|
||||
##
|
||||
CC = 'gcc'
|
||||
CXX = 'g++'
|
||||
|
@@ -172,6 +172,9 @@ BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib ${BF_ICONV_LIBPATH}'
|
||||
WITH_BF_RAYOPTIMIZATION = True
|
||||
BF_RAYOPTIMIZATION_SSE_FLAGS = ['-msse']
|
||||
|
||||
#On-Surface Brush
|
||||
WITH_BF_ONSURFACEBRUSH = True
|
||||
|
||||
CCFLAGS = [ '-pipe', '-funsigned-char', '-fno-strict-aliasing' ]
|
||||
|
||||
CPPFLAGS = ['-DWIN32', '-DFREE_WINDOWS', '-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64', '-D_LARGEFILE64_SOURCE']
|
||||
|
@@ -111,6 +111,9 @@ BF_OPENGL_LIB = 'GL GLU X11 Xi'
|
||||
BF_OPENGL_LIBPATH = '${BF_OPENGL}/lib'
|
||||
BF_OPENGL_LIB_STATIC = '${BF_OPENGL_LIBPATH}/libGL.a ${BF_OPENGL_LIBPATH}/libGLU.a ${BF_OPENGL_LIBPATH}/libXxf86vm.a ${BF_OPENGL_LIBPATH}/libX11.a ${BF_OPENGL_LIBPATH}/libXi.a ${BF_OPENGL_LIBPATH}/libXext.a ${BF_OPENGL_LIBPATH}/libXxf86vm.a'
|
||||
|
||||
#On-Surface Brush
|
||||
WITH_BF_ONSURFACEBRUSH = True
|
||||
|
||||
##
|
||||
##CC = gcc
|
||||
##CCC = g++
|
||||
|
@@ -128,6 +128,9 @@ BF_OPENGL_LIB = 'GL GLU X11 Xi'
|
||||
BF_OPENGL_LIBPATH = '${BF_OPENGL}/lib'
|
||||
BF_OPENGL_LIB_STATIC = '${BF_OPENGL_LIBPATH}/libGL.a ${BF_OPENGL_LIBPATH}/libGLU.a ${BF_OPENGL_LIBPATH}/libXxf86vm.a ${BF_OPENGL_LIBPATH}/libX11.a ${BF_OPENGL_LIBPATH}/libXi.a ${BF_OPENGL_LIBPATH}/libXext.a ${BF_OPENGL_LIBPATH}/libXxf86vm.a'
|
||||
|
||||
#On-Surface Brush
|
||||
WITH_BF_ONSURFACEBRUSH = True
|
||||
|
||||
##
|
||||
CC = 'gcc'
|
||||
CXX = 'g++'
|
||||
|
@@ -158,6 +158,9 @@ BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib'
|
||||
WITH_BF_RAYOPTIMIZATION = False
|
||||
BF_RAYOPTIMIZATION_SSE_FLAGS = ['-msse']
|
||||
|
||||
#On-Surface Brush
|
||||
WITH_BF_ONSURFACEBRUSH = True
|
||||
|
||||
##
|
||||
CC = 'gcc'
|
||||
CXX = 'g++'
|
||||
|
@@ -153,6 +153,9 @@ BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib'
|
||||
WITH_BF_RAYOPTIMIZATION = True
|
||||
BF_RAYOPTIMIZATION_SSE_FLAGS = ['/arch:SSE']
|
||||
|
||||
#On-Surface Brush
|
||||
WITH_BF_ONSURFACEBRUSH = True
|
||||
|
||||
WITH_BF_STATICOPENGL = False
|
||||
BF_OPENGL_INC = '${BF_OPENGL}/include'
|
||||
BF_OPENGL_LIBINC = '${BF_OPENGL}/lib'
|
||||
|
@@ -155,6 +155,9 @@ BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib'
|
||||
WITH_BF_RAYOPTIMIZATION = True
|
||||
BF_RAYOPTIMIZATION_SSE_FLAGS = ['/arch:SSE','/arch:SSE2']
|
||||
|
||||
#On-Surface Brush
|
||||
WITH_BF_ONSURFACEBRUSH = True
|
||||
|
||||
WITH_BF_STATICOPENGL = False
|
||||
BF_OPENGL_INC = '${BF_OPENGL}/include'
|
||||
BF_OPENGL_LIBINC = '${BF_OPENGL}/lib'
|
||||
|
@@ -132,6 +132,7 @@ def validate_arguments(args, bc):
|
||||
'BF_GHOST_DEBUG',
|
||||
'WITH_BF_RAYOPTIMIZATION',
|
||||
'BF_RAYOPTIMIZATION_SSE_FLAGS',
|
||||
'WITH_BF_ONSURFACEBRUSH',
|
||||
'BF_NO_ELBEEM',
|
||||
'WITH_BF_CXX_GUARDEDALLOC',
|
||||
'WITH_BF_JEMALLOC', 'WITH_BF_STATICJEMALLOC', 'BF_JEMALLOC', 'BF_JEMALLOC_INC', 'BF_JEMALLOC_LIBPATH', 'BF_JEMALLOC_LIB', 'BF_JEMALLOC_LIB_STATIC'
|
||||
@@ -501,6 +502,9 @@ def read_opts(env, cfg, args):
|
||||
|
||||
(BoolVariable('WITH_BF_RAYOPTIMIZATION', 'Enable raytracer SSE/SIMD optimization.', False)),
|
||||
('BF_RAYOPTIMIZATION_SSE_FLAGS', 'SSE flags', ''),
|
||||
|
||||
(BoolVariable('WITH_BF_ONSURFACEBRUSH', 'Enable use of the "on-surface brush" for paint/sculpt. Requires a stencil buffer, GL_depth_texture, and GLSL', True)),
|
||||
|
||||
(BoolVariable('WITH_BF_CXX_GUARDEDALLOC', 'Enable GuardedAlloc for C++ memory allocation tracking.', False))
|
||||
) # end of opts.AddOptions()
|
||||
|
||||
|
@@ -1,477 +0,0 @@
|
||||
#! /usr/bin/env python3
|
||||
|
||||
# ***** BEGIN GPL LICENSE BLOCK *****
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# ***** END GPL LICENCE BLOCK *****
|
||||
|
||||
######################################################
|
||||
#
|
||||
# Name:
|
||||
# dna.py
|
||||
#
|
||||
# Description:
|
||||
# Creates a browsable DNA output to HTML.
|
||||
#
|
||||
# Author:
|
||||
# Jeroen Bakker
|
||||
#
|
||||
# Version:
|
||||
# v0.1 (12-05-2009) - migration of original source code to python.
|
||||
# Added code to support blender 2.5 branch
|
||||
# v0.2 (25-05-2009) - integrated with BlendFileReader.py
|
||||
#
|
||||
# Input:
|
||||
# blender build executable
|
||||
#
|
||||
# Output:
|
||||
# dna.html
|
||||
# dna.css (will only be created when not existing)
|
||||
#
|
||||
# Startup:
|
||||
# ./blender -P BlendFileDnaExporter.py
|
||||
#
|
||||
# Process:
|
||||
# 1: write blend file with SDNA info
|
||||
# 2: read blend header from blend file
|
||||
# 3: seek DNA1 file-block
|
||||
# 4: read dna record from blend file
|
||||
# 5: close and eventually delete temp blend file
|
||||
# 6: export dna to html and css
|
||||
# 7: quit blender
|
||||
#
|
||||
######################################################
|
||||
|
||||
import struct
|
||||
import sys
|
||||
import getopt # command line arguments handling
|
||||
from string import Template # strings completion
|
||||
|
||||
|
||||
# logs
|
||||
import logging
|
||||
log = logging.getLogger("BlendFileDnaExporter")
|
||||
|
||||
if '--dna-debug' in sys.argv:
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
else:
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
|
||||
class DNACatalogHTML:
|
||||
'''
|
||||
DNACatalog is a catalog of all information in the DNA1 file-block
|
||||
'''
|
||||
|
||||
def __init__(self, catalog, bpy_module = None):
|
||||
self.Catalog = catalog
|
||||
self.bpy = bpy_module
|
||||
|
||||
def WriteToHTML(self, handle):
|
||||
|
||||
dna_html_template = """
|
||||
<!DOCTYPE html PUBLIC -//W3C//DTD HTML 4.01 Transitional//EN http://www.w3.org/TR/html4/loose.dtd>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="dna.css" media="screen, print" />
|
||||
<meta http-equiv="Content-Type" content="text/html"; charset="ISO-8859-1" />
|
||||
<title>The mystery of the blend</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class=title>
|
||||
Blender ${version}<br/>
|
||||
Internal SDNA structures
|
||||
</div>
|
||||
Architecture: ${bitness} ${endianness}<br/>
|
||||
Build revision: <a href="https://svn.blender.org/svnroot/bf-blender/!svn/bc/${revision}/trunk/">${revision}</a><br/>
|
||||
File format reference: <a href="mystery_of_the_blend.html">The mystery of the blend</a> by Jeroen Bakker<br/>
|
||||
<h1>Index of blender structures</h1>
|
||||
<ul class=multicolumn>
|
||||
${structs_list}
|
||||
</ul>
|
||||
${structs_content}
|
||||
</body>
|
||||
</html>"""
|
||||
|
||||
header = self.Catalog.Header
|
||||
bpy = self.bpy
|
||||
|
||||
# ${version} and ${revision}
|
||||
if bpy:
|
||||
version = '.'.join(map(str, bpy.app.version))
|
||||
revision = bpy.app.build_revision[:-1]
|
||||
else:
|
||||
version = str(header.Version)
|
||||
revision = 'Unknown'
|
||||
|
||||
# ${bitness}
|
||||
if header.PointerSize == 8:
|
||||
bitness = '64 bit'
|
||||
else:
|
||||
bitness = '32 bit'
|
||||
|
||||
# ${endianness}
|
||||
if header.LittleEndianness:
|
||||
endianess= 'Little endianness'
|
||||
else:
|
||||
endianess= 'Big endianness'
|
||||
|
||||
# ${structs_list}
|
||||
log.debug("Creating structs index")
|
||||
structs_list = ''
|
||||
list_item = '<li class="multicolumn">({0}) <a href="#{1}">{1}</a></li>\n'
|
||||
structureIndex = 0
|
||||
for structure in self.Catalog.Structs:
|
||||
structs_list += list_item.format(structureIndex, structure.Type.Name)
|
||||
structureIndex+=1
|
||||
|
||||
# ${structs_content}
|
||||
log.debug("Creating structs content")
|
||||
structs_content = ''
|
||||
for structure in self.Catalog.Structs:
|
||||
log.debug(structure.Type.Name)
|
||||
structs_content += self.Structure(structure)
|
||||
|
||||
d = dict(
|
||||
version = version,
|
||||
revision = revision,
|
||||
bitness = bitness,
|
||||
endianness = endianess,
|
||||
structs_list = structs_list,
|
||||
structs_content = structs_content
|
||||
)
|
||||
|
||||
dna_html = Template(dna_html_template).substitute(d)
|
||||
dna_html = self.format(dna_html)
|
||||
handle.write(dna_html)
|
||||
|
||||
def Structure(self, structure):
|
||||
struct_table_template = """
|
||||
<table><a name="${struct_name}"></a>
|
||||
<caption><a href="#${struct_name}">${struct_name}</a></caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>reference</th>
|
||||
<th>structure</th>
|
||||
<th>type</th>
|
||||
<th>name</th>
|
||||
<th>offset</th>
|
||||
<th>size</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
${fields}
|
||||
</tbody>
|
||||
</table>
|
||||
<label>Total size: ${size} bytes</label><br/>
|
||||
<label>(<a href="#top">top</a>)</label><br/>"""
|
||||
|
||||
d = dict(
|
||||
struct_name = structure.Type.Name,
|
||||
fields = self.StructureFields(structure, None, 0),
|
||||
size = str(structure.Type.Size)
|
||||
)
|
||||
|
||||
struct_table = Template(struct_table_template).substitute(d)
|
||||
return struct_table
|
||||
|
||||
def StructureFields(self, structure, parentReference, offset):
|
||||
fields = ''
|
||||
for field in structure.Fields:
|
||||
fields += self.StructureField(field, structure, parentReference, offset)
|
||||
offset += field.Size(self.Catalog.Header)
|
||||
return fields
|
||||
|
||||
def StructureField(self, field, structure, parentReference, offset):
|
||||
structure_field_template = """
|
||||
<tr>
|
||||
<td>${reference}</td>
|
||||
<td>${struct}</td>
|
||||
<td>${type}</td>
|
||||
<td>${name}</td>
|
||||
<td>${offset}</td>
|
||||
<td>${size}</td>
|
||||
</tr>"""
|
||||
|
||||
if field.Type.Structure == None or field.Name.IsPointer():
|
||||
|
||||
# ${reference}
|
||||
reference = field.Name.AsReference(parentReference)
|
||||
|
||||
# ${struct}
|
||||
if parentReference != None:
|
||||
struct = '<a href="#{0}">{0}</a>'.format(structure.Type.Name)
|
||||
else:
|
||||
struct = structure.Type.Name
|
||||
|
||||
# ${type}
|
||||
type = field.Type.Name
|
||||
|
||||
# ${name}
|
||||
name = field.Name.Name
|
||||
|
||||
# ${offset}
|
||||
# offset already set
|
||||
|
||||
# ${size}
|
||||
size = field.Size(self.Catalog.Header)
|
||||
|
||||
d = dict(
|
||||
reference = reference,
|
||||
struct = struct,
|
||||
type = type,
|
||||
name = name,
|
||||
offset = offset,
|
||||
size = size
|
||||
)
|
||||
|
||||
structure_field = Template(structure_field_template).substitute(d)
|
||||
|
||||
elif field.Type.Structure != None:
|
||||
reference = field.Name.AsReference(parentReference)
|
||||
structure_field = self.StructureFields(field.Type.Structure, reference, offset)
|
||||
|
||||
return structure_field
|
||||
|
||||
def indent(self, input, dent, startswith = ''):
|
||||
output = ''
|
||||
if dent < 0:
|
||||
for line in input.split('\n'):
|
||||
dent = abs(dent)
|
||||
output += line[dent:] + '\n' # unindent of a desired amount
|
||||
elif dent == 0:
|
||||
for line in input.split('\n'):
|
||||
output += line.lstrip() + '\n' # remove indentation completely
|
||||
elif dent > 0:
|
||||
for line in input.split('\n'):
|
||||
output += ' '* dent + line + '\n'
|
||||
return output
|
||||
|
||||
def format(self, input):
|
||||
diff = {
|
||||
'\n<!DOCTYPE':'<!DOCTYPE',
|
||||
'\n</ul>' :'</ul>',
|
||||
'<a name' :'\n<a name',
|
||||
'<tr>\n' :'<tr>',
|
||||
'<tr>' :' <tr>',
|
||||
'</th>\n' :'</th>',
|
||||
'</td>\n' :'</td>',
|
||||
'<tbody>\n' :'<tbody>'
|
||||
}
|
||||
output = self.indent(input, 0)
|
||||
for key, value in diff.items():
|
||||
output = output.replace(key, value)
|
||||
return output
|
||||
|
||||
def WriteToCSS(self, handle):
|
||||
'''
|
||||
Write the Cascading stylesheet template to the handle
|
||||
It is expected that the handle is a Filehandle
|
||||
'''
|
||||
css = """
|
||||
@CHARSET "ISO-8859-1";
|
||||
|
||||
body {
|
||||
font-family: verdana;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
div.title {
|
||||
font-size: large;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1 {
|
||||
page-break-before: always;
|
||||
}
|
||||
|
||||
h1, h2 {
|
||||
background-color: #D3D3D3;
|
||||
color:#404040;
|
||||
margin-right: 3%;
|
||||
padding-left: 40px;
|
||||
}
|
||||
|
||||
h1:hover{
|
||||
background-color: #EBEBEB;
|
||||
}
|
||||
|
||||
h3 {
|
||||
padding-left: 40px;
|
||||
}
|
||||
|
||||
table {
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: #000000;
|
||||
border-collapse: collapse;
|
||||
width: 94%;
|
||||
margin: 20px 3% 10px;
|
||||
}
|
||||
|
||||
caption {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: #000000;
|
||||
color:#ffffff;
|
||||
padding-left:5px;
|
||||
padding-right:5px;
|
||||
}
|
||||
|
||||
tr {
|
||||
}
|
||||
|
||||
td {
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: #a0a0a0;
|
||||
padding-left:5px;
|
||||
padding-right:5px;
|
||||
}
|
||||
|
||||
label {
|
||||
float:right;
|
||||
margin-right: 3%;
|
||||
}
|
||||
|
||||
ul.multicolumn {
|
||||
list-style:none;
|
||||
float:left;
|
||||
padding-right:0px;
|
||||
margin-right:0px;
|
||||
}
|
||||
|
||||
li.multicolumn {
|
||||
float:left;
|
||||
width:200px;
|
||||
margin-right:0px;
|
||||
}
|
||||
|
||||
a {
|
||||
color:#a000a0;
|
||||
text-decoration:none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color:#a000a0;
|
||||
text-decoration:underline;
|
||||
}
|
||||
"""
|
||||
|
||||
css = self.indent(css, 0)
|
||||
|
||||
handle.write(css)
|
||||
|
||||
|
||||
def usage():
|
||||
print("\nUsage: \n\tblender2.5 -b -P BlendFileDnaExporter_25.py [-- [options]]")
|
||||
print("Options:")
|
||||
print("\t--dna-keep-blend: doesn't delete the produced blend file DNA export to html")
|
||||
print("\t--dna-debug: sets the logging level to DEBUG (lots of additional info)")
|
||||
print("\t--dna-versioned saves version informations in the html and blend filenames")
|
||||
print("\t--dna-overwrite-css overwrite dna.css, useful when modifying css in the script")
|
||||
print("Examples:")
|
||||
print("\tdefault: % blender2.5 -b -P BlendFileDnaExporter_25.py")
|
||||
print("\twith options: % blender2.5 -b -P BlendFileDnaExporter_25.py -- --dna-keep-blend --dna-debug\n")
|
||||
|
||||
|
||||
######################################################
|
||||
# Main
|
||||
######################################################
|
||||
|
||||
def main():
|
||||
|
||||
import os, os.path
|
||||
|
||||
try:
|
||||
bpy = __import__('bpy')
|
||||
|
||||
# Files
|
||||
if '--dna-versioned' in sys.argv:
|
||||
blender_version = '_'.join(map(str, bpy.app.version))
|
||||
filename = 'dna-{0}-{1}_endian-{2}-r{3}'.format(sys.arch, sys.byteorder, blender_version, bpy.app.build_revision[2:-1])
|
||||
else:
|
||||
filename = 'dna'
|
||||
dir = os.path.dirname(__file__)
|
||||
Path_Blend = os.path.join(dir, filename + '.blend') # temporary blend file
|
||||
Path_HTML = os.path.join(dir, filename + '.html') # output html file
|
||||
Path_CSS = os.path.join(dir, 'dna.css') # output css file
|
||||
|
||||
# create a blend file for dna parsing
|
||||
if not os.path.exists(Path_Blend):
|
||||
log.info("1: write temp blend file with SDNA info")
|
||||
log.info(" saving to: " + Path_Blend)
|
||||
try:
|
||||
bpy.ops.wm.save_as_mainfile(filepath = Path_Blend, copy = True, compress = False)
|
||||
except:
|
||||
log.error("Filename {0} does not exist and can't be created... quitting".format(Path_Blend))
|
||||
return
|
||||
else:
|
||||
log.info("1: found blend file with SDNA info")
|
||||
log.info(" " + Path_Blend)
|
||||
|
||||
# read blend header from blend file
|
||||
log.info("2: read file:")
|
||||
|
||||
if not dir in sys.path:
|
||||
sys.path.append(dir)
|
||||
import BlendFileReader
|
||||
|
||||
handle = BlendFileReader.openBlendFile(Path_Blend)
|
||||
blendfile = BlendFileReader.BlendFile(handle)
|
||||
catalog = DNACatalogHTML(blendfile.Catalog, bpy)
|
||||
|
||||
# close temp file
|
||||
handle.close()
|
||||
|
||||
# deleting or not?
|
||||
if '--dna-keep-blend' in sys.argv:
|
||||
# keep the blend, useful for studying hexdumps
|
||||
log.info("5: closing blend file:")
|
||||
log.info(" {0}".format(Path_Blend))
|
||||
else:
|
||||
# delete the blend
|
||||
log.info("5: close and delete temp blend:")
|
||||
log.info(" {0}".format(Path_Blend))
|
||||
os.remove(Path_Blend)
|
||||
|
||||
# export dna to xhtml
|
||||
log.info("6: export sdna to xhtml file")
|
||||
handleHTML = open(Path_HTML, "w")
|
||||
catalog.WriteToHTML(handleHTML)
|
||||
handleHTML.close()
|
||||
|
||||
# only write the css when doesn't exist or at explicit request
|
||||
if not os.path.exists(Path_CSS) or '--dna-overwrite-css' in sys.argv:
|
||||
handleCSS = open(Path_CSS, "w")
|
||||
catalog.WriteToCSS(handleCSS)
|
||||
handleCSS.close()
|
||||
|
||||
# quit blender
|
||||
if not bpy.app.background:
|
||||
log.info("7: quit blender")
|
||||
bpy.ops.wm.exit_blender()
|
||||
|
||||
except ImportError:
|
||||
log.warning(" skipping, not running in Blender")
|
||||
usage()
|
||||
sys.exit(2)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
@@ -1,446 +0,0 @@
|
||||
#! /usr/bin/env python3
|
||||
|
||||
# ***** BEGIN GPL LICENSE BLOCK *****
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# ***** END GPL LICENCE BLOCK *****
|
||||
|
||||
######################################################
|
||||
# Importing modules
|
||||
######################################################
|
||||
|
||||
import os
|
||||
import struct
|
||||
import gzip
|
||||
import tempfile
|
||||
|
||||
import logging
|
||||
log = logging.getLogger("BlendFileReader")
|
||||
|
||||
######################################################
|
||||
# module global routines
|
||||
######################################################
|
||||
|
||||
def ReadString(handle, length):
|
||||
'''
|
||||
ReadString reads a String of given length or a zero terminating String
|
||||
from a file handle
|
||||
'''
|
||||
if length != 0:
|
||||
return handle.read(length).decode()
|
||||
else:
|
||||
# length == 0 means we want a zero terminating string
|
||||
result = ""
|
||||
s = ReadString(handle, 1)
|
||||
while s!="\0":
|
||||
result += s
|
||||
s = ReadString(handle, 1)
|
||||
return result
|
||||
|
||||
|
||||
def Read(type, handle, fileheader):
|
||||
'''
|
||||
Reads the chosen type from a file handle
|
||||
'''
|
||||
def unpacked_bytes(type_char, size):
|
||||
return struct.unpack(fileheader.StructPre + type_char, handle.read(size))[0]
|
||||
|
||||
if type == 'ushort':
|
||||
return unpacked_bytes("H", 2) # unsigned short
|
||||
elif type == 'short':
|
||||
return unpacked_bytes("h", 2) # short
|
||||
elif type == 'uint':
|
||||
return unpacked_bytes("I", 4) # unsigned int
|
||||
elif type == 'int':
|
||||
return unpacked_bytes("i", 4) # int
|
||||
elif type == 'float':
|
||||
return unpacked_bytes("f", 4) # float
|
||||
elif type == 'ulong':
|
||||
return unpacked_bytes("Q", 8) # unsigned long
|
||||
elif type == 'pointer':
|
||||
# The pointersize is given by the header (BlendFileHeader).
|
||||
if fileheader.PointerSize == 4:
|
||||
return Read('uint', handle, fileheader)
|
||||
if fileheader.PointerSize == 8:
|
||||
return Read('ulong', handle, fileheader)
|
||||
|
||||
|
||||
def openBlendFile(filename):
|
||||
'''
|
||||
Open a filename, determine if the file is compressed and returns a handle
|
||||
'''
|
||||
handle = open(filename, 'rb')
|
||||
magic = ReadString(handle, 7)
|
||||
if magic in ("BLENDER", "BULLETf"):
|
||||
log.debug("normal blendfile detected")
|
||||
handle.seek(0, os.SEEK_SET)
|
||||
return handle
|
||||
else:
|
||||
log.debug("gzip blendfile detected?")
|
||||
handle.close()
|
||||
log.debug("decompressing started")
|
||||
fs = gzip.open(filename, "rb")
|
||||
handle = tempfile.TemporaryFile()
|
||||
data = fs.read(1024*1024)
|
||||
while data:
|
||||
handle.write(data)
|
||||
data = fs.read(1024*1024)
|
||||
log.debug("decompressing finished")
|
||||
fs.close()
|
||||
log.debug("resetting decompressed file")
|
||||
handle.seek(0, os.SEEK_SET)
|
||||
return handle
|
||||
|
||||
|
||||
def Align(handle):
|
||||
'''
|
||||
Aligns the filehandle on 4 bytes
|
||||
'''
|
||||
offset = handle.tell()
|
||||
trim = offset % 4
|
||||
if trim != 0:
|
||||
handle.seek(4-trim, os.SEEK_CUR)
|
||||
|
||||
|
||||
######################################################
|
||||
# module classes
|
||||
######################################################
|
||||
|
||||
class BlendFile:
|
||||
'''
|
||||
Reads a blendfile and store the header, all the fileblocks, and catalogue
|
||||
structs foound in the DNA fileblock
|
||||
|
||||
- BlendFile.Header (BlendFileHeader instance)
|
||||
- BlendFile.Blocks (list of BlendFileBlock instances)
|
||||
- BlendFile.Catalog (DNACatalog instance)
|
||||
'''
|
||||
|
||||
def __init__(self, handle):
|
||||
log.debug("initializing reading blend-file")
|
||||
self.Header = BlendFileHeader(handle)
|
||||
self.Blocks = []
|
||||
fileblock = BlendFileBlock(handle, self)
|
||||
found_dna_block = False
|
||||
while not found_dna_block:
|
||||
if fileblock.Header.Code in ("DNA1", "SDNA"):
|
||||
self.Catalog = DNACatalog(self.Header, handle)
|
||||
found_dna_block = True
|
||||
else:
|
||||
fileblock.Header.skip(handle)
|
||||
|
||||
self.Blocks.append(fileblock)
|
||||
fileblock = BlendFileBlock(handle, self)
|
||||
|
||||
# appending last fileblock, "ENDB"
|
||||
self.Blocks.append(fileblock)
|
||||
|
||||
# seems unused?
|
||||
"""
|
||||
def FindBlendFileBlocksWithCode(self, code):
|
||||
#result = []
|
||||
#for block in self.Blocks:
|
||||
#if block.Header.Code.startswith(code) or block.Header.Code.endswith(code):
|
||||
#result.append(block)
|
||||
#return result
|
||||
"""
|
||||
|
||||
|
||||
class BlendFileHeader:
|
||||
'''
|
||||
BlendFileHeader allocates the first 12 bytes of a blend file.
|
||||
It contains information about the hardware architecture.
|
||||
Header example: BLENDER_v254
|
||||
|
||||
BlendFileHeader.Magic (str)
|
||||
BlendFileHeader.PointerSize (int)
|
||||
BlendFileHeader.LittleEndianness (bool)
|
||||
BlendFileHeader.StructPre (str) see http://docs.python.org/py3k/library/struct.html#byte-order-size-and-alignment
|
||||
BlendFileHeader.Version (int)
|
||||
'''
|
||||
|
||||
def __init__(self, handle):
|
||||
log.debug("reading blend-file-header")
|
||||
|
||||
self.Magic = ReadString(handle, 7)
|
||||
log.debug(self.Magic)
|
||||
|
||||
pointersize = ReadString(handle, 1)
|
||||
log.debug(pointersize)
|
||||
if pointersize == "-":
|
||||
self.PointerSize = 8
|
||||
if pointersize == "_":
|
||||
self.PointerSize = 4
|
||||
|
||||
endianness = ReadString(handle, 1)
|
||||
log.debug(endianness)
|
||||
if endianness == "v":
|
||||
self.LittleEndianness = True
|
||||
self.StructPre = "<"
|
||||
if endianness == "V":
|
||||
self.LittleEndianness = False
|
||||
self.StructPre = ">"
|
||||
|
||||
version = ReadString(handle, 3)
|
||||
log.debug(version)
|
||||
self.Version = int(version)
|
||||
|
||||
log.debug("{0} {1} {2} {3}".format(self.Magic, self.PointerSize, self.LittleEndianness, version))
|
||||
|
||||
|
||||
class BlendFileBlock:
|
||||
'''
|
||||
BlendFileBlock.File (BlendFile)
|
||||
BlendFileBlock.Header (FileBlockHeader)
|
||||
'''
|
||||
|
||||
def __init__(self, handle, blendfile):
|
||||
self.File = blendfile
|
||||
self.Header = FileBlockHeader(handle, blendfile.Header)
|
||||
|
||||
def Get(self, handle, path):
|
||||
log.debug("find dna structure")
|
||||
dnaIndex = self.Header.SDNAIndex
|
||||
dnaStruct = self.File.Catalog.Structs[dnaIndex]
|
||||
log.debug("found " + dnaStruct.Type.Name)
|
||||
handle.seek(self.Header.FileOffset, os.SEEK_SET)
|
||||
return dnaStruct.GetField(self.File.Header, handle, path)
|
||||
|
||||
|
||||
class FileBlockHeader:
|
||||
'''
|
||||
FileBlockHeader contains the information in a file-block-header.
|
||||
The class is needed for searching to the correct file-block (containing Code: DNA1)
|
||||
|
||||
Code (str)
|
||||
Size (int)
|
||||
OldAddress (pointer)
|
||||
SDNAIndex (int)
|
||||
Count (int)
|
||||
FileOffset (= file pointer of datablock)
|
||||
'''
|
||||
|
||||
def __init__(self, handle, fileheader):
|
||||
self.Code = ReadString(handle, 4).strip()
|
||||
if self.Code != "ENDB":
|
||||
self.Size = Read('uint', handle, fileheader)
|
||||
self.OldAddress = Read('pointer', handle, fileheader)
|
||||
self.SDNAIndex = Read('uint', handle, fileheader)
|
||||
self.Count = Read('uint', handle, fileheader)
|
||||
self.FileOffset = handle.tell()
|
||||
else:
|
||||
self.Size = Read('uint', handle, fileheader)
|
||||
self.OldAddress = 0
|
||||
self.SDNAIndex = 0
|
||||
self.Count = 0
|
||||
self.FileOffset = handle.tell()
|
||||
#self.Code += ' ' * (4 - len(self.Code))
|
||||
log.debug("found blend-file-block-fileheader {0} {1}".format(self.Code, self.FileOffset))
|
||||
|
||||
def skip(self, handle):
|
||||
handle.read(self.Size)
|
||||
|
||||
|
||||
class DNACatalog:
|
||||
'''
|
||||
DNACatalog is a catalog of all information in the DNA1 file-block
|
||||
|
||||
Header = None
|
||||
Names = None
|
||||
Types = None
|
||||
Structs = None
|
||||
'''
|
||||
|
||||
def __init__(self, fileheader, handle):
|
||||
log.debug("building DNA catalog")
|
||||
self.Names=[]
|
||||
self.Types=[]
|
||||
self.Structs=[]
|
||||
self.Header = fileheader
|
||||
|
||||
SDNA = ReadString(handle, 4)
|
||||
|
||||
# names
|
||||
NAME = ReadString(handle, 4)
|
||||
numberOfNames = Read('uint', handle, fileheader)
|
||||
log.debug("building #{0} names".format(numberOfNames))
|
||||
for i in range(numberOfNames):
|
||||
name = ReadString(handle,0)
|
||||
self.Names.append(DNAName(name))
|
||||
Align(handle)
|
||||
|
||||
# types
|
||||
TYPE = ReadString(handle, 4)
|
||||
numberOfTypes = Read('uint', handle, fileheader)
|
||||
log.debug("building #{0} types".format(numberOfTypes))
|
||||
for i in range(numberOfTypes):
|
||||
type = ReadString(handle,0)
|
||||
self.Types.append(DNAType(type))
|
||||
Align(handle)
|
||||
|
||||
# type lengths
|
||||
TLEN = ReadString(handle, 4)
|
||||
log.debug("building #{0} type-lengths".format(numberOfTypes))
|
||||
for i in range(numberOfTypes):
|
||||
length = Read('ushort', handle, fileheader)
|
||||
self.Types[i].Size = length
|
||||
Align(handle)
|
||||
|
||||
# structs
|
||||
STRC = ReadString(handle, 4)
|
||||
numberOfStructures = Read('uint', handle, fileheader)
|
||||
log.debug("building #{0} structures".format(numberOfStructures))
|
||||
for structureIndex in range(numberOfStructures):
|
||||
type = Read('ushort', handle, fileheader)
|
||||
Type = self.Types[type]
|
||||
structure = DNAStructure(Type)
|
||||
self.Structs.append(structure)
|
||||
|
||||
numberOfFields = Read('ushort', handle, fileheader)
|
||||
for fieldIndex in range(numberOfFields):
|
||||
fTypeIndex = Read('ushort', handle, fileheader)
|
||||
fNameIndex = Read('ushort', handle, fileheader)
|
||||
fType = self.Types[fTypeIndex]
|
||||
fName = self.Names[fNameIndex]
|
||||
structure.Fields.append(DNAField(fType, fName))
|
||||
|
||||
|
||||
class DNAName:
|
||||
'''
|
||||
DNAName is a C-type name stored in the DNA.
|
||||
|
||||
Name = str
|
||||
'''
|
||||
|
||||
def __init__(self, name):
|
||||
self.Name = name
|
||||
|
||||
def AsReference(self, parent):
|
||||
if parent == None:
|
||||
result = ""
|
||||
else:
|
||||
result = parent+"."
|
||||
|
||||
result = result + self.ShortName()
|
||||
return result
|
||||
|
||||
def ShortName(self):
|
||||
result = self.Name;
|
||||
result = result.replace("*", "")
|
||||
result = result.replace("(", "")
|
||||
result = result.replace(")", "")
|
||||
Index = result.find("[")
|
||||
if Index != -1:
|
||||
result = result[0:Index]
|
||||
return result
|
||||
|
||||
def IsPointer(self):
|
||||
return self.Name.find("*")>-1
|
||||
|
||||
def IsMethodPointer(self):
|
||||
return self.Name.find("(*")>-1
|
||||
|
||||
def ArraySize(self):
|
||||
result = 1
|
||||
Temp = self.Name
|
||||
Index = Temp.find("[")
|
||||
|
||||
while Index != -1:
|
||||
Index2 = Temp.find("]")
|
||||
result*=int(Temp[Index+1:Index2])
|
||||
Temp = Temp[Index2+1:]
|
||||
Index = Temp.find("[")
|
||||
|
||||
return result
|
||||
|
||||
|
||||
class DNAType:
|
||||
'''
|
||||
DNAType is a C-type stored in the DNA
|
||||
|
||||
Name = str
|
||||
Size = int
|
||||
Structure = DNAStructure
|
||||
'''
|
||||
|
||||
def __init__(self, aName):
|
||||
self.Name = aName
|
||||
self.Structure=None
|
||||
|
||||
|
||||
class DNAStructure:
|
||||
'''
|
||||
DNAType is a C-type structure stored in the DNA
|
||||
|
||||
Type = DNAType
|
||||
Fields = [DNAField]
|
||||
'''
|
||||
|
||||
def __init__(self, aType):
|
||||
self.Type = aType
|
||||
self.Type.Structure = self
|
||||
self.Fields=[]
|
||||
|
||||
def GetField(self, header, handle, path):
|
||||
splitted = path.partition(".")
|
||||
name = splitted[0]
|
||||
rest = splitted[2]
|
||||
offset = 0;
|
||||
for field in self.Fields:
|
||||
if field.Name.ShortName() == name:
|
||||
log.debug("found "+name+"@"+str(offset))
|
||||
handle.seek(offset, os.SEEK_CUR)
|
||||
return field.DecodeField(header, handle, rest)
|
||||
else:
|
||||
offset += field.Size(header)
|
||||
|
||||
log.debug("error did not find "+path)
|
||||
return None
|
||||
|
||||
|
||||
class DNAField:
|
||||
'''
|
||||
DNAField is a coupled DNAType and DNAName.
|
||||
|
||||
Type = DNAType
|
||||
Name = DNAName
|
||||
'''
|
||||
|
||||
def __init__(self, aType, aName):
|
||||
self.Type = aType
|
||||
self.Name = aName
|
||||
|
||||
def Size(self, header):
|
||||
if self.Name.IsPointer() or self.Name.IsMethodPointer():
|
||||
return header.PointerSize*self.Name.ArraySize()
|
||||
else:
|
||||
return self.Type.Size*self.Name.ArraySize()
|
||||
|
||||
def DecodeField(self, header, handle, path):
|
||||
if path == "":
|
||||
if self.Name.IsPointer():
|
||||
return Read('pointer', handle, header)
|
||||
if self.Type.Name=="int":
|
||||
return Read('int', handle, header)
|
||||
if self.Type.Name=="short":
|
||||
return Read('short', handle, header)
|
||||
if self.Type.Name=="float":
|
||||
return Read('float', handle, header)
|
||||
if self.Type.Name=="char":
|
||||
return ReadString(handle, self.Name.ArraySize())
|
||||
else:
|
||||
return self.Type.Structure.GetField(header, handle, path)
|
||||
|
@@ -1,29 +0,0 @@
|
||||
To inspect the blend-file-format used by a certain version of blender 2.5x,
|
||||
navigate to this folder and run this command:
|
||||
|
||||
blender2.5 -b -P BlendFileDnaExporter_25.py
|
||||
|
||||
where "blender2.5" is your blender executable or a symlink to it.
|
||||
|
||||
This creates a temporary dna.blend to be inspected and it produces two new files:
|
||||
|
||||
* dna.html: the list of all the structures saved in a blend file with the blender2.5
|
||||
executable you have used. If you enable build informations when you build blender,
|
||||
the dna.html file will also show which svn revision the html refers to.
|
||||
* dna.css: the css for the html above
|
||||
|
||||
Below you have the help message with a list of options you can use.
|
||||
|
||||
|
||||
Usage:
|
||||
blender2.5 -b -P BlendFileDnaExporter_25.py [-- [options]]
|
||||
Options:
|
||||
--dna-keep-blend: doesn't delete the produced blend file DNA export to html
|
||||
--dna-debug: sets the logging level to DEBUG (lots of additional info)
|
||||
--dna-versioned saves version informations in the html and blend filenames
|
||||
--dna-overwrite-css overwrite dna.css, useful when modifying css in the script
|
||||
Examples:
|
||||
default: % blender2.5 -b -P BlendFileDnaExporter_25.py
|
||||
with options: % blender2.5 -b -P BlendFileDnaExporter_25.py -- --dna-keep-blend --dna-debug
|
||||
|
||||
|
@@ -1,204 +0,0 @@
|
||||
@CHARSET "ISO-8859-1";
|
||||
|
||||
table {
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: #000000;
|
||||
border-collapse: collapse;
|
||||
width: 94%;
|
||||
margin: 10px 3%;
|
||||
}
|
||||
|
||||
DIV.title {
|
||||
font-size: 30px;
|
||||
font-weight: bold;
|
||||
text-align: center
|
||||
}
|
||||
|
||||
DIV.subtitle {
|
||||
font-size: large;
|
||||
text-align: center
|
||||
}
|
||||
|
||||
DIV.contact {
|
||||
margin:30px 3%;
|
||||
}
|
||||
|
||||
@media print {
|
||||
DIV.contact {
|
||||
margin-top: 300px;
|
||||
}
|
||||
DIV.title {
|
||||
margin-top: 400px;
|
||||
}
|
||||
}
|
||||
|
||||
label {
|
||||
font-weight: bold;
|
||||
width: 100px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
label:after {
|
||||
content: ":";
|
||||
}
|
||||
|
||||
TH {
|
||||
background-color: #000000;
|
||||
color: #ffffff;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
TR {
|
||||
}
|
||||
|
||||
TD {
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: #a0a0a0;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
BODY {
|
||||
font-family: verdana;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
H1 {
|
||||
page-break-before: always;
|
||||
}
|
||||
|
||||
H1, H2, H3, H4 {
|
||||
margin-top: 30px;
|
||||
margin-right: 3%;
|
||||
padding: 3px 3%;
|
||||
color: #404040;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
H1, H2 {
|
||||
background-color: #D3D3D3;
|
||||
}
|
||||
|
||||
H3, H4 {
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
H1:hover, H2:hover, H3:hover, H4:hover {
|
||||
background-color: #EBEBEB;
|
||||
}
|
||||
|
||||
CODE.evidence {
|
||||
font-size:larger
|
||||
}
|
||||
|
||||
CODE.block {
|
||||
color: #000000;
|
||||
background-color: #DDDC75;
|
||||
margin: 10px 0;
|
||||
padding: 5px;
|
||||
border-width: 1px;
|
||||
border-style: dotted;
|
||||
border-color: #000000;
|
||||
white-space: pre;
|
||||
display: block;
|
||||
font-size: 2 em;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin: 10px 3%;
|
||||
}
|
||||
|
||||
li {
|
||||
margin: 0 -15px;
|
||||
}
|
||||
|
||||
ul.multicolumn {
|
||||
list-style: none;
|
||||
float: left;
|
||||
padding-right: 0px;
|
||||
margin-right: 0px;
|
||||
}
|
||||
|
||||
li.multicolumn {
|
||||
float: left;
|
||||
width: 200px;
|
||||
margin-right: 0px;
|
||||
}
|
||||
|
||||
@media screen {
|
||||
p {
|
||||
margin: 10px 3%;
|
||||
line-height: 130%;
|
||||
}
|
||||
}
|
||||
|
||||
span.fade {
|
||||
color: gray;
|
||||
}
|
||||
|
||||
span.header {
|
||||
color: green;
|
||||
}
|
||||
|
||||
span.header-greyed {
|
||||
color: #4CBE4B;
|
||||
}
|
||||
|
||||
span.data {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
span.data-greyed {
|
||||
color: #5D99C4;
|
||||
}
|
||||
|
||||
span.descr {
|
||||
color: red;
|
||||
}
|
||||
|
||||
div.box {
|
||||
margin: 15px 3%;
|
||||
border-style: dotted;
|
||||
border-width: 1px;
|
||||
}
|
||||
|
||||
div.box-solid {
|
||||
margin: 15px 3%;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
}
|
||||
|
||||
p.box-title {
|
||||
font-style: italic;
|
||||
font-size: 110%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
p.box-title:hover {
|
||||
background-color: #EBEBEB;
|
||||
}
|
||||
|
||||
p.code {
|
||||
font-family: "Courier New", Courier, monospace;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #a000a0;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #a000a0;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
td.skip {
|
||||
color: #808080;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
text-align: center;
|
||||
}
|
@@ -1,835 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="mystery_of_the_blend.css" media="screen, print">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>The mystery of the blend</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="title">The mystery of the blend</div>
|
||||
<div class="subtitle">The blender file-format explained</div>
|
||||
<div class="contact">
|
||||
<label>Author</label> Jeroen Bakker<br>
|
||||
<label>Email</label> <a href="mailto:j.bakker@atmind.nl">j.bakker@atmind.nl</a><br>
|
||||
<label>Website</label> <a href="http://www.atmind.nl/blender/">http://www.atmind.nl/blender</a><br>
|
||||
<label>Version</label> 06-10-2010<br>
|
||||
</div>
|
||||
|
||||
<a name="introduction" href="#introduction" ><h2>Introduction</h2></a>
|
||||
</a>
|
||||
|
||||
<p>In this article I will describe the
|
||||
blend-file-format with a request to tool-makers to support blend-file.
|
||||
|
||||
</p>
|
||||
<p>First I'll describe how Blender works with blend-files. You'll notice
|
||||
why the blend-file-format is not that well documented, as from
|
||||
Blender's perspective this is not needed.
|
||||
We look at the global file-structure of a blend-file (the file-header
|
||||
and file-blocks).
|
||||
After this is explained, we go deeper to the core of the blend-file, the
|
||||
DNA-structures. They hold the blue-prints of the blend-file and the key
|
||||
asset of understanding blend-files.
|
||||
When that's done we can use these DNA-structures to read information
|
||||
from elsewhere in the blend-file.
|
||||
|
||||
</p>
|
||||
<p>
|
||||
In this article we'll be using the default blend-file from Blender 2.54,
|
||||
with the goal to read the output resolution from the Scene.
|
||||
The article is written to be programming language independent and I've
|
||||
setup a web-site for support.
|
||||
</p>
|
||||
|
||||
<a name="loading-and-saving-in-blender" href="#loading-and-saving-in-blender">
|
||||
<h2>Loading and saving in Blender</h2>
|
||||
</a>
|
||||
|
||||
<p>
|
||||
Loading and saving in Blender is very fast and Blender is known to
|
||||
have excellent downward and upward compatibility. Ton Roosendaal
|
||||
demonstrated that in December 2008 by loading a 1.0 blend-file using
|
||||
Blender 2.48a [ref: <a href="http://www.blendernation.com/2008/12/01/blender-dna-rna-and-backward-compatibility/">http://www.blendernation.com/2008/12/01/blender-dna-rna-and-backward-compatibility/</a>].
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Saving complex scenes in Blender is done within seconds. Blender
|
||||
achieves this by saving data in memory to disk without any
|
||||
transformations or translations. Blender only adds file-block-headers to
|
||||
this data. A file-block-header contains clues on how to interpret the
|
||||
data. After the data, all internally Blender structures are stored.
|
||||
These structures will act as blue-prints when Blender loads the file.
|
||||
Blend-files can be different when stored on different hardware platforms
|
||||
or Blender releases. There is no effort taken to make blend-files
|
||||
binary the same. Blender creates the blend-files in this manner since
|
||||
release 1.0. Backward and upwards compatibility is not implemented when
|
||||
saving the file, this is done during loading.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
When Blender loads a blend-file, the DNA-structures are read first.
|
||||
Blender creates a catalog of these DNA-structures. Blender uses this
|
||||
catalog together with the data in the file, the internal Blender
|
||||
structures of the Blender release you're using and a lot of
|
||||
transformation and translation logic to implement the backward and
|
||||
upward compatibility. In the source code of blender there is actually
|
||||
logic which can transform and translate every structure used by a
|
||||
Blender release to the one of the release you're using [ref: <a href="http://download.blender.org/source/blender-2.48a.tar.gz">http://download.blender.org/source/blender-2.48a.tar.gz</a>
|
||||
<a href="https://svn.blender.org/svnroot/bf-blender/tags/blender-2.48-release/source/blender/blenloader/intern/readfile.c">blender/blenloader/intern/readfile.c</a> lines
|
||||
4946-7960]. The more difference between releases the more logic is
|
||||
executed.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The blend-file-format is not well documented, as it does not differ from
|
||||
internally used structures and the file can really explain itself.
|
||||
</p>
|
||||
|
||||
<a name="global-file-structure" href="#global-file-structure">
|
||||
<h2>Global file-structure</h2>
|
||||
</a>
|
||||
|
||||
<p>
|
||||
This section explains how the global file-structure can be read.
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>A blend-file always start with the <b>file-header</b></li>
|
||||
<li>After the file-header, follows a list of <b>file-blocks</b> (the default blend file of Blender 2.48 contains more than 400 of these file-blocks).</li>
|
||||
<li>Each file-block has a <b>file-block header</b> and <b>file-block data</b></li>
|
||||
<li>At the end of the blend-file there is a section called "<a href="#structure-DNA" style="font-weight:bold">Structure DNA</a>", which lists all the internal structures of the Blender release the file was created in</li>
|
||||
<li>The blend-file ends with a file-block called 'ENDB'</li>
|
||||
</ul>
|
||||
|
||||
<!-- file scheme -->
|
||||
<div class="box-solid" style="width:20%; margin-left:35%; font-size:0.8em;">
|
||||
|
||||
<p class="code"><b>File.blend</b></p>
|
||||
|
||||
<div class="box"><p class="code">File-header</p></div>
|
||||
|
||||
<div class="box-solid"><p class="code">File-block</p>
|
||||
<div class="box"><p class="code">Header</p></div>
|
||||
<div class="box"><p class="code">Data</p></div>
|
||||
</div>
|
||||
|
||||
<div class="box" style="border-style:dashed"><p class="code">File-block</p></div>
|
||||
<div class="box" style="border-style:dashed"><p class="code">File-block</p></div>
|
||||
|
||||
<div class="box-solid"><p class="code">File-block 'Structure DNA'</p>
|
||||
<div class="box"><p class="code">Header ('DNA1')</p></div>
|
||||
<div class="box-solid">
|
||||
<p class="code">Data ('SDNA')</p>
|
||||
<div class="box">
|
||||
<p class="code">Names ('NAME')</p>
|
||||
</div>
|
||||
<div class="box">
|
||||
<p class="code">Types ('TYPE')</p>
|
||||
</div>
|
||||
<div class="box">
|
||||
<p class="code">Lengths ('TLEN')</p>
|
||||
</div>
|
||||
<div class="box">
|
||||
<p class="code">Structures ('STRC')</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="box-solid"><p class="code">File-Block 'ENDB'</p></div>
|
||||
|
||||
</div><!-- end of file scheme -->
|
||||
|
||||
<a name="file-header" href="#file-header">
|
||||
<h3>File-Header</h3>
|
||||
</a>
|
||||
|
||||
<p>
|
||||
The first 12 bytes of every blend-file is the file-header. The
|
||||
file-header has information on Blender (version-number) and the PC the
|
||||
blend-file was saved on (pointer-size and endianness). This is required
|
||||
as all data inside the blend-file is ordered in that way, because no
|
||||
translation or transformation is done during saving.
|
||||
The next table describes the information in the file-header.
|
||||
</p>
|
||||
|
||||
<table>
|
||||
<caption>File-header</caption>
|
||||
<thead>
|
||||
<tr><th>reference</th>
|
||||
<th>structure</th>
|
||||
<th>type</th>
|
||||
<th>offset</th>
|
||||
<th>size</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td>identifier</td>
|
||||
<td>char[7]</td>
|
||||
<td>File identifier (always 'BLENDER')</td>
|
||||
<td>0</td>
|
||||
<td>7</td></tr>
|
||||
<tr><td>pointer-size</td>
|
||||
<td>char</td>
|
||||
<td>Size of a pointer; all pointers in the file are stored in this format. '_' means 4 bytes or 32 bit and '-' means 8 bytes or 64 bits.</td>
|
||||
<td>7</td>
|
||||
<td>1</td></tr>
|
||||
<tr><td>endianness</td>
|
||||
<td>char</td>
|
||||
<td>Type of byte ordering used; 'v' means little endian and 'V' means big endian.</td>
|
||||
<td>8</td>
|
||||
<td>1</td></tr>
|
||||
<tr><td>version-number</td>
|
||||
<td>char[3]</td>
|
||||
<td>Version of Blender the file was created in; '254' means version 2.54</td>
|
||||
<td>9</td>
|
||||
<td>3</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p>
|
||||
<a href="http://en.wikipedia.org/wiki/Endianness">Endianness</a> addresses the way values are ordered in a sequence of bytes(see the <a href="#example-endianess">example</a> below):
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>in a big endian ordering, the largest part of the value is placed on the first byte and
|
||||
the lowest part of the value is placed on the last byte,</li>
|
||||
<li>in a little endian ordering, largest part of the value is placed on the last byte
|
||||
and the smallest part of the value is placed on the first byte.</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Nowadays, little-endian is the most commonly used.
|
||||
</p>
|
||||
|
||||
<a name="example-endianess"></a>
|
||||
<div class="box">
|
||||
<p onclick="location.href='#example-endianess'" class="box-title">
|
||||
Endianess Example
|
||||
</p>
|
||||
<p>
|
||||
Writing the integer <code class="evidence">0x4A3B2C1Dh</code>, will be ordered:
|
||||
<ul>
|
||||
<li>in big endian as <code class="evidence">0x4Ah</code>, <code class="evidence">0x3Bh</code>, <code class="evidence">0x2Ch</code>, <code class="evidence">0x1Dh</code></li>
|
||||
<li>in little endian as <code class="evidence">0x1Dh</code>, <code class="evidence">0x2Ch</code>, <code class="evidence">0x3Bh</code>, <code class="evidence">0x4Ah</code></li>
|
||||
</ul>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Blender supports little-endian and big-endian.<br>
|
||||
This means that when the endianness
|
||||
is different between the blend-file and the PC your using, Blender changes it to the byte ordering
|
||||
of your PC.
|
||||
</p>
|
||||
|
||||
<a name="example-file-header"></a>
|
||||
<div class="box">
|
||||
<p onclick="location.href='#example-file-header'" class="box-title">
|
||||
File-header Example
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This hex-dump describes a file-header created with <code>blender</code> <code>2.54.0</code> on <code>little-endian</code> hardware with a <code>32 bits</code> pointer length.
|
||||
<code class="block"> <span class="descr">pointer-size version-number
|
||||
| |</span>
|
||||
0000 0000: [42 4C 45 4E 44 45 52] [5F] [76] [32 35 34] BLENDER_v254 <span class="descr">
|
||||
| |
|
||||
identifier endianness</span></code>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<a name="file-blocks" href="#file-blocks"><h3>File-blocks</h3></a>
|
||||
|
||||
<p>
|
||||
File-blocks contain a "<a href="#file-block-header">file-block header</a>" and "file-block data".
|
||||
</p>
|
||||
|
||||
<a name="file-block-header" href="#file-block-header"><h3>File-block headers</h3></a>
|
||||
|
||||
<p>
|
||||
The file-block-header describes:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>the type of information stored in the
|
||||
file-block</li>
|
||||
<li>the total length of the data</li>
|
||||
<li>the old memory
|
||||
pointer at the moment the data was written to disk</li>
|
||||
<li>the number of items of this information</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
As we can see below, depending on the pointer-size stored in the file-header, a file-block-header
|
||||
can be 20 or 24 bytes long, hence it is always aligned at 4 bytes.
|
||||
</p>
|
||||
|
||||
<table>
|
||||
<caption>File-block-header</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>reference</th>
|
||||
<th>structure</th>
|
||||
<th>type</th>
|
||||
<th>offset</th>
|
||||
<th>size</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td>code</td>
|
||||
<td>char[4]</td>
|
||||
<td>File-block identifier</td>
|
||||
<td>0</td>
|
||||
<td>4</td></tr>
|
||||
<tr><td>size</td>
|
||||
<td>integer</td>
|
||||
<td>Total length of the data after the file-block-header</td>
|
||||
<td>4</td>
|
||||
<td>4</td></tr>
|
||||
<tr><td>old memory address</td>
|
||||
<td>void*</td>
|
||||
<td>Memory address the structure was located when written to disk</td>
|
||||
<td>8</td>
|
||||
<td>pointer-size (4/8)</td></tr>
|
||||
<tr><td>SDNA index</td>
|
||||
<td>integer</td>
|
||||
<td>Index of the SDNA structure</td>
|
||||
<td>8+pointer-size</td>
|
||||
<td>4</td></tr>
|
||||
<tr><td>count</td>
|
||||
<td>integer</td>
|
||||
<td>Number of structure located in this file-block</td>
|
||||
<td>12+pointer-size</td>
|
||||
<td>4</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p>
|
||||
The above table describes how a file-block-header is structured:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li><code>Code</code> describes different types of file-blocks. The code determines with what logic the data must be read. <br>
|
||||
These codes also allows fast finding of data like Library, Scenes, Object or Materials as they all have a specific code. </li>
|
||||
<li><code>Size</code> contains the total length of data after the file-block-header.
|
||||
After the data a new file-block starts. The last file-block in the file
|
||||
has code 'ENDB'.</li>
|
||||
<li><code>Old memory address</code> contains the memory address when the structure
|
||||
was last stored. When loading the file the structures can be placed on
|
||||
different memory addresses. Blender updates pointers to these structures
|
||||
to the new memory addresses.</li>
|
||||
<li><code>SDNA index</code> contains the index in the DNA structures to be used when
|
||||
reading this file-block-data. <br>
|
||||
More information about this subject will be explained in the <a href="#reading-scene-information">Reading scene information section</a>.</li>
|
||||
<li><code>Count</code> tells how many elements of the specific SDNA structure can be found in the data.</li>
|
||||
</ul>
|
||||
|
||||
<a name="example-file-block-header"></a>
|
||||
<div class="box">
|
||||
<p onclick="location.href='#example-file-block-header'" class="box-title">
|
||||
Example
|
||||
</p>
|
||||
<p>
|
||||
This hex-dump describes a File-block (= <span class="header">File-block header</span> + <span class="data">File-block data</span>) created with <code>blender</code> <code>2.54</code> on <code>little-endian</code> hardware with a <code>32 bits</code> pointer length.<br>
|
||||
<code class="block"><span class="descr"> file-block
|
||||
identifier='SC' data size=1404 old pointer SDNA index=150
|
||||
| | | |</span>
|
||||
0000 4420: <span class="header">[53 43 00 00] [7C 05 00 00] [68 34 FB 0B] [96 00 00 00]</span> SC.. `... ./.. ....
|
||||
0000 4430: <span class="header">[01 00 00 00]</span> <span class="data">[xx xx xx xx xx xx xx xx xx xx xx xx</span> .... xxxx xxxx xxxx<span class="descr">
|
||||
| |
|
||||
count=1 file-block data (next 1404 bytes)</span>
|
||||
</code>
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>The code <code>'SC'+0x00h</code> identifies that it is a Scene. </li>
|
||||
<li>Size of the data is 1404 bytes (0x0000057Ch = 0x7Ch + 0x05h * 256 = 124 + 1280)</li>
|
||||
<li>The old pointer is 0x0BFB3468h</li>
|
||||
<li>The SDNA index is 150 (0x00000096h = 6 + 9 * 16 = 6 + 144)</li>
|
||||
<li>The section contains a single scene (count = 1).</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Before we can interpret the data of this file-block we first have to read the DNA structures in the file.
|
||||
The section "<a href="#structure-DNA">Structure DNA</a>" will show how to do that.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<a name="structure-DNA" href="#structure-DNA"><h2>Structure DNA</h2></a>
|
||||
|
||||
<a name="DNA1-file-block" href="#DNA1-file-block"><h3>The DNA1 file-block</h3></a>
|
||||
|
||||
<p>
|
||||
Structure DNA is stored in a file-block with code 'DNA1'. It can be just before the 'ENDB' file-block.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The 'DNA1' file-block contains all internal structures of the Blender release the
|
||||
file was created in. <br>
|
||||
These structure can be described as C-structures: they can hold fields, arrays and
|
||||
pointers to other structures, just like a normal C-structure.
|
||||
|
||||
<p>
|
||||
<code class="block">struct SceneRenderLayer {
|
||||
struct SceneRenderLayer *next, *prev;
|
||||
char name[32];
|
||||
struct Material *mat_override;
|
||||
struct Group *light_override;
|
||||
unsigned int lay;
|
||||
unsigned int lay_zmask;
|
||||
int layflag;
|
||||
int pad;
|
||||
int passflag;
|
||||
int pass_xor;
|
||||
};
|
||||
</code>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For example,a blend-file created with Blender 2.54 the 'DNA1' file-block is 57796 bytes long and contains 398 structures.
|
||||
</p>
|
||||
|
||||
<a name="DNA1-file-block-header" href="#DNA1-file-block-header"><h3>DNA1 file-block-header</h3></a>
|
||||
|
||||
<p>
|
||||
The DNA1 file-block header follows the same rules of any other file-block, see the example below.
|
||||
</p>
|
||||
|
||||
<a name="example-DNA1-file-block-header"></a>
|
||||
<div class="box">
|
||||
<p onclick="location.href='#example-DNA1-file-block-header'" class="box-title">
|
||||
Example
|
||||
</p>
|
||||
<p>
|
||||
This hex-dump describes the file-block 'DNA1' header created with <code>blender</code> <code>2.54.0</code> on <code>little-endian</code> hardware with a <code>32 bits</code> pointer length.<br>
|
||||
<code class="block"><span class="descr"> (file-block
|
||||
identifier='DNA1') data size=57796 old pointer SDNA index=0
|
||||
| | | |</span>
|
||||
0004 B060 <span class="header">[44 4E 41 31] [C4 E1 00 00] [C8 00 84 0B] [00 00 00 00]</span> DNA1............
|
||||
0004 B070 <span class="header">[01 00 00 00]</span> <span class="fade">[53 44 4E 41 4E 41 4D 45 CB 0B 00 00</span> ....<span class="fade">SDNANAME....</span><span class="descr">
|
||||
| |
|
||||
count=1 'DNA1' file-block data (next 57796 bytes)</span>
|
||||
</code>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<a name="DNA1-file-block-data" href="#DNA1-file-block-data"><h3>DNA1 file-block data</h3></a>
|
||||
<p>
|
||||
The next section describes how this information is ordered in the <b>data</b> of the 'DNA1' file-block.
|
||||
</p>
|
||||
|
||||
<table>
|
||||
<caption>Structure of the DNA file-block-data</caption>
|
||||
<thead>
|
||||
<tr><th colspan="2">repeat condition</th>
|
||||
<th>name</th>
|
||||
<th>type</th>
|
||||
<th>length</th>
|
||||
<th>description</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td></td>
|
||||
<td></td>
|
||||
<td>identifier</td>
|
||||
<td>char[4]</td>
|
||||
<td>4</td>
|
||||
<td>'SDNA'</td></tr>
|
||||
<tr><td></td>
|
||||
<td></td>
|
||||
<td>name identifier</td>
|
||||
<td>char[4]</td>
|
||||
<td>4</td>
|
||||
<td>'NAME'</td></tr>
|
||||
<tr><td></td>
|
||||
<td></td>
|
||||
<td>#names</td>
|
||||
<td>integer</td>
|
||||
<td>4</td>
|
||||
<td>Number of names follows</td></tr>
|
||||
<tr><td>for(#names)</td>
|
||||
<td></td>
|
||||
<td>name</td>
|
||||
<td>char[]</td>
|
||||
<td>?</td>
|
||||
<td>Zero terminating string of name, also contains pointer and simple array definitions (e.g. '*vertex[3]\0')</td></tr>
|
||||
<tr><td></td>
|
||||
<td></td>
|
||||
<td>type identifier</td>
|
||||
<td>char[4]</td>
|
||||
<td>4</td>
|
||||
<td>'TYPE' this field is aligned at 4 bytes</td></tr>
|
||||
<tr><td></td>
|
||||
<td></td>
|
||||
<td>#types</td>
|
||||
<td>integer</td>
|
||||
<td>4</td>
|
||||
<td>Number of types follows</td></tr>
|
||||
<tr><td>for(#types)</td>
|
||||
<td></td>
|
||||
<td>type</td>
|
||||
<td>char[]</td>
|
||||
<td>?</td>
|
||||
<td>Zero terminating string of type (e.g. 'int\0')</td></tr>
|
||||
<tr><td></td>
|
||||
<td></td>
|
||||
<td>length identifier</td>
|
||||
<td>char[4]</td>
|
||||
<td>4</td>
|
||||
<td>'TLEN' this field is aligned at 4 bytes</td></tr>
|
||||
<tr><td>for(#types)</td>
|
||||
<td></td>
|
||||
<td>length</td>
|
||||
<td>short</td>
|
||||
<td>2</td>
|
||||
<td>Length in bytes of type (e.g. 4)</td></tr>
|
||||
<tr><td></td>
|
||||
<td></td>
|
||||
<td>structure identifier</td>
|
||||
<td>char[4]</td>
|
||||
<td>4</td>
|
||||
<td>'STRC' this field is aligned at 4 bytes</td></tr>
|
||||
<tr><td></td>
|
||||
<td></td>
|
||||
<td>#structures</td>
|
||||
<td>integer</td>
|
||||
<td>4</td>
|
||||
<td>Number of structures follows</td></tr>
|
||||
<tr><td>for(#structures)</td>
|
||||
<td></td>
|
||||
<td>structure type</td>
|
||||
<td>short</td>
|
||||
<td>2</td>
|
||||
<td>Index in types containing the name of the structure</td></tr>
|
||||
<tr><td>..</td>
|
||||
<td></td>
|
||||
<td>#fields</td>
|
||||
<td>short</td>
|
||||
<td>2</td>
|
||||
<td>Number of fields in this structure</td></tr>
|
||||
<tr><td>..</td>
|
||||
<td>for(#field)</td>
|
||||
<td>field type</td>
|
||||
<td>short</td>
|
||||
<td>2</td>
|
||||
<td>Index in type</td></tr>
|
||||
<tr><td>for end</td>
|
||||
<td>for end</td>
|
||||
<td>field name</td>
|
||||
<td>short</td>
|
||||
<td>2</td>
|
||||
<td>Index in name</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p>
|
||||
As you can see, the structures are stored in 4 arrays: names, types,
|
||||
lengths and structures. Every structure also contains an array of
|
||||
fields. A field is the combination of a type and a name. From this
|
||||
information a catalog of all structures can be constructed.
|
||||
The names are stored as how a C-developer defines them. This means that
|
||||
the name also defines pointers and arrays.
|
||||
(When a name starts with '*' it is used as a pointer. when the name
|
||||
contains for example '[3]' it is used as a array of 3 long.)
|
||||
In the types you'll find simple-types (like: 'integer', 'char',
|
||||
'float'), but also complex-types like 'Scene' and 'MetaBall'.
|
||||
'TLEN' part describes the length of the types. A 'char' is 1 byte, an
|
||||
'integer' is 4 bytes and a 'Scene' is 1376 bytes long.
|
||||
</p>
|
||||
|
||||
<div class="box">
|
||||
<p class="box-title">
|
||||
Note
|
||||
</p>
|
||||
<p>
|
||||
All identifiers, are arrays of 4 chars, hence they are all aligned at 4 bytes.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<a name="example-DNA1-file-block-data"></a>
|
||||
<div class="box">
|
||||
<p onclick="location.href='#example-DNA1-file-block-data'" class="box-title">
|
||||
Example
|
||||
</p>
|
||||
<p>
|
||||
Created with <code>blender</code> <code>2.54.0</code> on <code>little-endian</code> hardware with a <code>32 bits</code> pointer length.
|
||||
</p>
|
||||
|
||||
<a name="DNA1-data-array-names" href="#DNA1-data-array-names"><h4>The names array</h4></a>
|
||||
<p>
|
||||
The first names are: *next, *prev, *data, *first, *last, x, y, xmin, xmax, ymin, ymax, *pointer, group, val, val2, type, subtype, flag, name[32], ...
|
||||
<code class="block"><span class="descr"> file-block-data identifier='SDNA' array-id='NAME' number of names=3019
|
||||
| | |</span>
|
||||
0004 B070 <span class="fade">01 00 00 00 [53 44 4E 41]</span><span class="data">[4E 41 4D 45] [CB 0B 00 00]</span> <span class="fade">....SDNA</span>NAME....
|
||||
0004 B080 <span class="data">[2A 6E 65 78 74 00][2A 70 72 65 76 00] [2A 64 61 74</span> *next.*prev.*dat<span class="descr">
|
||||
| | |
|
||||
'*next\0' '*prev\0' '*dat'</span><span class="fade">
|
||||
....
|
||||
.... (3019 names)</span>
|
||||
</code>
|
||||
</p>
|
||||
|
||||
<div class="box">
|
||||
<p class="box-title">
|
||||
Note
|
||||
</p>
|
||||
<p>
|
||||
While reading the DNA you'll will come across some strange
|
||||
names like '(*doit)()'. These are method pointers and Blender updates
|
||||
them to the correct methods.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<a name="DNA1-data-array-types" href="#DNA1-data-array-types"><h4>The types array</h4></a>
|
||||
<p>
|
||||
The first types are: char, uchar, short, ushort, int, long, ulong, float, double, void, Link, LinkData, ListBase, vec2s, vec2f, ...
|
||||
<code class="block"><span class="descr"> array-id='TYPE'
|
||||
|</span>
|
||||
0005 2440 <span class="fade">6F 6C 64 5B 34 5D 5B 34 5D 00 00 00</span> [54 59 50 45] <span class="fade">old[4][4]...</span>TYPE
|
||||
0005 2450 [C9 01 00 00] [63 68 61 72 00] [75 63 68 61 72 00][73 ....char.uchar.s<span class="descr">
|
||||
| | | |
|
||||
number of types=457 'char\0' 'uchar\0' 's'</span><span class="fade">
|
||||
....
|
||||
.... (457 types)</span>
|
||||
</code>
|
||||
</p>
|
||||
|
||||
<a name="DNA1-data-array-lengths" href="#DNA1-data-array-lengths"><h4>The lengths array</h4></a>
|
||||
<p>
|
||||
<code class="block"><span class="descr"> char uchar ushort short
|
||||
array-id length length length length
|
||||
'TLEN' 1 1 2 2</span>
|
||||
0005 3AA0 <span class="fade">45 00 00 00</span> [54 4C 45 4E] [01 00] [01 00] [02 00] [02 00] <span class="fade">E...</span>TLEN........
|
||||
<span class="fade">....</span>
|
||||
0005 3AC0 [08 00] [04 00] [08 00] [10 00] [10 00] [14 00] [4C 00] [34 00] ............L.4.<span class="descr">
|
||||
8 4 8
|
||||
ListBase vec2s vec2f ... etc
|
||||
length len length </span><span class="fade">
|
||||
....
|
||||
.... (457 lengths, same as number of types)</span>
|
||||
</code>
|
||||
</p>
|
||||
|
||||
<a name="DNA1-data-array-structures" href="#DNA1-data-array-structures"><h4>The structures array</h4></a>
|
||||
<p>
|
||||
<code class="block"><span class="descr"> array-id='STRC'
|
||||
|</span>
|
||||
0005 3E30 <span class="fade">40 00 38 00 60 00 00 00 00 00 00 00</span> [53 54 52 43] <span class="fade">@.8.`.......</span>STRC
|
||||
0005 3E40 [8E 01 00 00] [0A 00] [02 00] [0A 00] [00 00] [0A 00] [01 00] ................<span class="descr">
|
||||
398 10 2 10 0 10 0
|
||||
number of index fields index index index index
|
||||
structures in <a href="#DNA1-data-array-types">types</a> in <a href="#DNA1-data-array-types">types</a> in <a href="#DNA1-data-array-names">names</a> in <a href="#DNA1-data-array-types">types</a> in <a href="#DNA1-data-array-names">names</a></span><span class="fade">
|
||||
' '----------------' '-----------------' '
|
||||
' field 0 field 1 '
|
||||
'--------------------------------------------------------'
|
||||
structure 0
|
||||
....
|
||||
.... (398 structures, each one describeing own type, and type/name for each field)</span>
|
||||
</code>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
The DNA structures inside a Blender 2.48 blend-file can be found at <a href="http://www.atmind.nl/blender/blender-sdna.html">http://www.atmind.nl/blender/blender-sdna.html</a>.
|
||||
|
||||
If we understand the DNA part of the file it is now possible to read
|
||||
information from other parts file-blocks. The next section will tell us
|
||||
how.
|
||||
</p>
|
||||
|
||||
<a name="reading-scene-information" href="#reading-scene-information"><h2>Reading scene information</h2></a>
|
||||
|
||||
<p>
|
||||
Let us look at <a href="#example-file-block-header">the file-block header we have seen earlier</a>:<br>
|
||||
</p>
|
||||
<ul>
|
||||
<li>the file-block identifier is <code>'SC'+0x00h</code></li>
|
||||
<li>the SDNA index is 150</li>
|
||||
<li>the file-block size is 1404 bytes</li>
|
||||
</ul>
|
||||
<p>
|
||||
Now note that:
|
||||
<ul>
|
||||
<li>the structure at index 150 in the DNA is a structure of type 'Scene' (counting from 0).</li>
|
||||
<li>the associated type ('Scene') in the DNA has the length of 1404 bytes.</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
We can map the Scene structure on the data of the file-blocks.
|
||||
But before we can do that, we have to flatten the Scene-structure.
|
||||
|
||||
<code class="block">struct Scene {
|
||||
ID id; <span class="descr">// 52 bytes long (ID is different a structure)</span>
|
||||
AnimData *adt; <span class="descr">// 4 bytes long (pointer to an AnimData structure)</span>
|
||||
Object *camera; <span class="descr">// 4 bytes long (pointer to an Object structure)</span>
|
||||
World *world; <span class="descr">// 4 bytes long (pointer to an Object structure)</span>
|
||||
...
|
||||
float cursor[3]; <span class="descr">// 12 bytes long (array of 3 floats)</span>
|
||||
...
|
||||
};
|
||||
</code>
|
||||
|
||||
The first field in the Scene-structure is of type 'ID' with the name 'id'.
|
||||
Inside the list of DNA structures there is a structure defined for type 'ID' (structure index 17).
|
||||
|
||||
<code class="block">struct ID {
|
||||
void *next, *prev;
|
||||
struct ID *newid;
|
||||
struct Library *lib;
|
||||
char name[24];
|
||||
short us;
|
||||
short flag;
|
||||
int icon_id;
|
||||
IDProperty *properties;
|
||||
};
|
||||
</code>
|
||||
|
||||
The first field in this structure has type 'void' and name '*next'. <br>
|
||||
Looking in the structure list there is no structure defined for type 'void': it is a simple type and therefore the data should be read.
|
||||
The name '*next' describes a pointer.
|
||||
As we see, the first 4 bytes of the data can be mapped to 'id.next'.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Using this method we'll map a structure to its data. If we want to
|
||||
read a specific field we know at which offset in the data it is located
|
||||
and how much space it takes.<br>
|
||||
The next table shows the output of this flattening process for some
|
||||
parts of the Scene-structure. Not all rows are described in the table as
|
||||
there is a lot of information in a Scene-structure.
|
||||
</p>
|
||||
|
||||
<table>
|
||||
<caption>Flattened SDNA structure 150: Scene</caption>
|
||||
<thead>
|
||||
<tr><th>reference</th>
|
||||
<th>structure</th>
|
||||
<th>type</th><th>name</th>
|
||||
<th>offset</th><th>size</th>
|
||||
<th>description</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td>id.next</td><td><a href="#struct:ID">ID</a></td>
|
||||
<td>void</td><td>*next</td>
|
||||
<td>0</td>
|
||||
<td>4</td>
|
||||
<td>Refers to the next scene</td></tr>
|
||||
<tr><td>id.prev</td><td><a href="#struct:ID">ID</a></td>
|
||||
<td>void</td><td>*prev</td>
|
||||
<td>4</td>
|
||||
<td>4</td>
|
||||
<td>Refers to the previous scene</td></tr>
|
||||
<tr><td>id.newid</td><td><a href="#struct:ID">ID</a></td>
|
||||
<td>ID</td><td>*newid</td>
|
||||
<td>8</td>
|
||||
<td>4</td>
|
||||
<td></td></tr>
|
||||
<tr><td>id.lib</td><td><a href="#struct:ID">ID</a></td>
|
||||
<td>Library</td><td>*lib</td>
|
||||
<td>12</td>
|
||||
<td>4</td>
|
||||
<td></td></tr>
|
||||
<tr><td>id.name</td><td><a href="#struct:ID">ID</a></td>
|
||||
<td>char</td><td>name[24]</td>
|
||||
<td>16</td>
|
||||
<td>24</td>
|
||||
<td>'SC'+the name of the scene as displayed in Blender</td></tr>
|
||||
<tr><td>id.us</td><td><a href="#struct:ID">ID</a></td>
|
||||
<td>short</td><td>us</td>
|
||||
<td>40</td>
|
||||
<td>2</td>
|
||||
<td></td></tr>
|
||||
<tr><td>id.flag</td><td><a href="#struct:ID">ID</a></td>
|
||||
<td>short</td><td>flag</td><td>42</td><td>2</td>
|
||||
<td></td></tr>
|
||||
<tr><td>id.icon_id</td><td><a href="#struct:ID">ID</a></td>
|
||||
<td>int</td><td>icon_id</td><td>44</td>
|
||||
<td>4</td>
|
||||
<td></td></tr>
|
||||
<tr><td>id.properties</td><td><a href="#struct:ID">ID</a></td>
|
||||
<td>IDProperty</td><td>*properties</td>
|
||||
<td>48</td>
|
||||
<td>4</td>
|
||||
<td></td></tr>
|
||||
<tr><td>adt</td><td>Scene</td><td>AnimData</td>
|
||||
<td>*adt</td>
|
||||
<td>52</td>
|
||||
<td>4</td>
|
||||
<td></td></tr>
|
||||
<tr><td>camera</td><td>Scene</td>
|
||||
<td>Object</td>
|
||||
<td>*camera</td>
|
||||
<td>56</td>
|
||||
<td>4</td>
|
||||
<td>Pointer to the current camera</td></tr>
|
||||
<tr><td>world</td><td>Scene</td>
|
||||
<td>World</td>
|
||||
<td>*world</td>
|
||||
<td>60</td>
|
||||
<td>4</td>
|
||||
<td>Pointer to the current world</td></tr>
|
||||
|
||||
<tr><td class="skip" colspan="7">Skipped rows</td></tr>
|
||||
|
||||
<tr><td>r.xsch</td><td><a href="#struct:RenderData">RenderData</a>
|
||||
</td><td>short</td><td>xsch</td><td>382</td><td>2</td>
|
||||
<td>X-resolution of the output when rendered at 100%</td></tr>
|
||||
<tr><td>r.ysch</td><td><a href="#struct:RenderData">RenderData</a>
|
||||
</td><td>short</td><td>ysch</td><td>384</td><td>2</td>
|
||||
<td>Y-resolution of the output when rendered at 100%</td></tr>
|
||||
<tr><td>r.xparts</td><td><a href="#struct:RenderData">RenderData</a>
|
||||
</td><td>short</td><td>xparts</td><td>386</td><td>2</td>
|
||||
<td>Number of x-part used by the renderer</td></tr>
|
||||
<tr><td>r.yparts</td><td><a href="#struct:RenderData">RenderData</a>
|
||||
</td><td>short</td><td>yparts</td><td>388</td><td>2</td>
|
||||
<td>Number of x-part used by the renderer</td></tr>
|
||||
|
||||
<tr><td class="skip" colspan="7">Skipped rows</td></tr>
|
||||
|
||||
<tr><td>gpd</td><td>Scene</td><td>bGPdata</td><td>*gpd</td><td>1376</td><td>4</td>
|
||||
<td></td></tr>
|
||||
<tr><td>physics_settings.gravity</td><td><a href="#struct:PhysicsSettings">PhysicsSettings</a>
|
||||
</td><td>float</td><td>gravity[3]</td><td>1380</td><td>12</td>
|
||||
<td></td></tr>
|
||||
<tr><td>physics_settings.flag</td><td><a href="#struct:PhysicsSettings">PhysicsSettings</a>
|
||||
</td><td>int</td><td>flag</td><td>1392</td><td>4</td>
|
||||
<td></td></tr>
|
||||
<tr><td>physics_settings.quick_cache_step</td><td><a href="#struct:PhysicsSettings">PhysicsSettings</a>
|
||||
</td><td>int</td><td>quick_cache_step</td><td>1396</td><td>4</td>
|
||||
<td></td></tr>
|
||||
<tr><td>physics_settings.rt</td><td><a href="#struct:PhysicsSettings">PhysicsSettings</a>
|
||||
</td><td>int</td><td>rt</td><td>1400</td><td>4</td>
|
||||
<td></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p>
|
||||
We can now read the X and Y resolution of the Scene:
|
||||
<ul>
|
||||
<li>the X-resolution is located on offset 382 of the file-block-data and must be read as a
|
||||
short.</li>
|
||||
<li>the Y-resolution is located on offset 384 and is also a short</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<div class="box">
|
||||
<p class="box-title">
|
||||
Note
|
||||
</p>
|
||||
<p>
|
||||
An array of chars can mean 2 things. The field contains readable
|
||||
text or it contains an array of flags (not humanly readable).
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<p class="box-title">
|
||||
Note
|
||||
</p>
|
||||
<p>
|
||||
A file-block containing a list refers to the DNA structure and has a count larger
|
||||
than 1. For example Vertexes and Faces are stored in this way.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
@@ -60,6 +60,9 @@ else:
|
||||
if env['BF_GHOST_DEBUG']:
|
||||
defs.append('BF_GHOST_DEBUG')
|
||||
|
||||
if env['WITH_BF_ONSURFACEBRUSH']:
|
||||
defs.append('WITH_ONSURFACEBRUSH')
|
||||
|
||||
incs = '. ../string #extern/glew/include #source/blender/imbuf #source/blender/makesdna ' + env['BF_OPENGL_INC']
|
||||
if window_system in ('win32-vc', 'win32-mingw', 'cygwin', 'linuxcross', 'win64-vc'):
|
||||
incs = env['BF_WINTAB_INC'] + ' ' + incs
|
||||
|
@@ -52,6 +52,9 @@ AGL_RGBA,
|
||||
AGL_DOUBLEBUFFER,
|
||||
AGL_ACCELERATED,
|
||||
AGL_DEPTH_SIZE, 32,
|
||||
#ifdef WITH_ONSURFACEBRUSH
|
||||
AGL_STENCIL_SIZE, 8,
|
||||
#endif
|
||||
AGL_NONE,
|
||||
};
|
||||
|
||||
@@ -61,6 +64,9 @@ AGL_DOUBLEBUFFER,
|
||||
AGL_ACCELERATED,
|
||||
AGL_FULLSCREEN,
|
||||
AGL_DEPTH_SIZE, 32,
|
||||
#ifdef WITH_ONSURFACEBRUSH
|
||||
AGL_STENCIL_SIZE, 8,
|
||||
#endif
|
||||
AGL_NONE,
|
||||
};
|
||||
|
||||
|
@@ -365,6 +365,13 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
|
||||
|
||||
pixelFormatAttrsWindow[i++] = NSOpenGLPFAAccelerated;
|
||||
//pixelFormatAttrsWindow[i++] = NSOpenGLPFAAllowOfflineRenderers,; // Removed to allow 10.4 builds, and 2 GPUs rendering is not used anyway
|
||||
|
||||
|
||||
#ifdef WITH_ONSURFACEBRUSH
|
||||
pixelFormatAttrsWindow[i++] = NSOpenGLPFAStencilSize;
|
||||
pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 8;
|
||||
#endif
|
||||
|
||||
|
||||
pixelFormatAttrsWindow[i++] = NSOpenGLPFADepthSize;
|
||||
pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 32;
|
||||
@@ -376,6 +383,11 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
|
||||
// Multisample anti-aliasing
|
||||
pixelFormatAttrsWindow[i++] = NSOpenGLPFAMultisample;
|
||||
|
||||
#ifdef WITH_ONSURFACEBRUSH
|
||||
pixelFormatAttrsWindow[i++] = NSOpenGLPFAStencilSize;
|
||||
pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 8;
|
||||
#endif
|
||||
|
||||
pixelFormatAttrsWindow[i++] = NSOpenGLPFASampleBuffers;
|
||||
pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 1;
|
||||
|
||||
|
@@ -98,7 +98,11 @@ static PIXELFORMATDESCRIPTOR sPreferredFormat = {
|
||||
0, /* no accumulation buffer */
|
||||
0, 0, 0, 0, /* accum bits (ignored) */
|
||||
32, /* depth buffer */
|
||||
#ifdef WITH_ONSURFACEBRUSH
|
||||
8, /* stencil buffer */
|
||||
#else
|
||||
0, /* no stencil buffer */
|
||||
#endif
|
||||
0, /* no auxiliary buffers */
|
||||
PFD_MAIN_PLANE, /* main layer */
|
||||
0, /* reserved */
|
||||
@@ -1280,7 +1284,11 @@ static int WeightPixelFormat(PIXELFORMATDESCRIPTOR& pfd) {
|
||||
!(pfd.dwFlags & PFD_DRAW_TO_WINDOW) ||
|
||||
!(pfd.dwFlags & PFD_DOUBLEBUFFER) || /* Blender _needs_ this */
|
||||
( pfd.cDepthBits <= 8 ) ||
|
||||
!(pfd.iPixelType == PFD_TYPE_RGBA))
|
||||
!(pfd.iPixelType == PFD_TYPE_RGBA)
|
||||
#ifdef WITH_ONSURFACEBRUSH
|
||||
|| ( pfd.cStencilBits == 0)
|
||||
#endif
|
||||
)
|
||||
return 0;
|
||||
|
||||
weight = 1; /* it's usable */
|
||||
|
@@ -215,6 +215,9 @@ GHOST_WindowX11(
|
||||
attributes[i++] = GLX_BLUE_SIZE; attributes[i++] = 1;
|
||||
attributes[i++] = GLX_GREEN_SIZE; attributes[i++] = 1;
|
||||
attributes[i++] = GLX_DEPTH_SIZE; attributes[i++] = 1;
|
||||
#ifdef WITH_ONSURFACEBRUSH
|
||||
attributes[i++] = GLX_STENCIL_SIZE; attributes[i++] = 8;
|
||||
#endif
|
||||
/* GLX >= 1.4 required for multi-sample */
|
||||
if(samples && (glxVersionMajor >= 1) && (glxVersionMinor >= 4)) {
|
||||
attributes[i++] = GLX_SAMPLE_BUFFERS; attributes[i++] = 1;
|
||||
@@ -1292,11 +1295,11 @@ GHOST_WindowX11::
|
||||
if(m_xtablet.EraserDevice)
|
||||
XCloseDevice(m_display, m_xtablet.EraserDevice);
|
||||
#endif /* WITH_X11_XINPUT */
|
||||
|
||||
|
||||
if (m_context != s_firstContext) {
|
||||
glXDestroyContext(m_display, m_context);
|
||||
}
|
||||
|
||||
|
||||
if (p_owner == m_window) {
|
||||
XSetSelectionOwner(m_display, Primary_atom, None, CurrentTime);
|
||||
}
|
||||
|
@@ -2137,6 +2137,21 @@ class VIEW3D_PT_view3d_display(bpy.types.Panel):
|
||||
row.prop(region, "use_box_clip")
|
||||
|
||||
|
||||
class VIEW3D_PT_view3d_matcap(bpy.types.Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'UI'
|
||||
bl_label = "MatCap"
|
||||
bl_default_closed = True
|
||||
|
||||
@classmethod
|
||||
def poll(self, context):
|
||||
return (context.space_data)
|
||||
|
||||
def draw(self, context):
|
||||
#self.layout.column().template_ID_preview(context.space_data, "matcap_image", open="image.open", new="image.new", filter="is_matcap_image", rows=3, cols=3)
|
||||
self.layout.column().template_ID_preview(context.space_data, "matcap_image", open="image.open", new="image.new", rows=3, cols=3)
|
||||
|
||||
|
||||
class VIEW3D_PT_view3d_meshdisplay(bpy.types.Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'UI'
|
||||
|
@@ -540,6 +540,12 @@ class VIEW3D_PT_tools_brush(PaintPanel, bpy.types.Panel):
|
||||
row.prop(brush, "auto_smooth_factor", slider=True)
|
||||
row.prop(brush, "use_inverse_smooth_pressure", toggle=True, text="")
|
||||
|
||||
if brush.sculpt_tool not in ('GRAVITY'):
|
||||
col.separator()
|
||||
|
||||
row = col.row(align=True)
|
||||
row.prop(brush, "gravity_factor", slider=True)
|
||||
|
||||
if brush.sculpt_tool in {'GRAB', 'SNAKE_HOOK'}:
|
||||
col.separator()
|
||||
|
||||
@@ -553,10 +559,10 @@ class VIEW3D_PT_tools_brush(PaintPanel, bpy.types.Panel):
|
||||
row.prop(brush, "crease_pinch_factor", slider=True, text="Pinch")
|
||||
|
||||
if brush.sculpt_tool not in {'PINCH', 'INFLATE', 'SMOOTH'}:
|
||||
row = col.row(align=True)
|
||||
|
||||
col.separator()
|
||||
|
||||
row = col.row(align=True)
|
||||
|
||||
if brush.use_original_normal:
|
||||
row.prop(brush, "use_original_normal", toggle=True, text="", icon='LOCKED')
|
||||
else:
|
||||
@@ -564,8 +570,10 @@ class VIEW3D_PT_tools_brush(PaintPanel, bpy.types.Panel):
|
||||
|
||||
row.prop(brush, "sculpt_plane", text="")
|
||||
|
||||
#if brush.sculpt_tool in {'CLAY', 'CLAY_TUBES', 'FLATTEN', 'FILL', 'SCRAPE'}:
|
||||
if brush.sculpt_tool in {'CLAY', 'FLATTEN', 'FILL', 'SCRAPE'}:
|
||||
row = col.row()
|
||||
row.prop(brush, "sculpt_plane_range")
|
||||
|
||||
if brush.sculpt_tool in {'CLAY', 'CLAY_STRIPS', 'FLATTEN', 'FILL', 'SCRAPE'}:
|
||||
row = col.row(align=True)
|
||||
row.prop(brush, "plane_offset", slider=True)
|
||||
row.prop(brush, "use_offset_pressure", text="")
|
||||
@@ -578,26 +586,39 @@ class VIEW3D_PT_tools_brush(PaintPanel, bpy.types.Panel):
|
||||
row.active = brush.use_plane_trim
|
||||
row.prop(brush, "plane_trim", slider=True, text="Distance")
|
||||
|
||||
if brush.sculpt_tool == 'LAYER':
|
||||
row = col.row()
|
||||
row.prop(brush, "height", slider=True, text="Height")
|
||||
|
||||
col.separator()
|
||||
|
||||
row = col.row()
|
||||
row.prop(brush, "use_frontface", text="Front Faces Only")
|
||||
row.prop(brush, "use_frontface", text="Front-Faces Only")
|
||||
row= col.row()
|
||||
row.active = brush.use_frontface
|
||||
row.prop(brush, "frontface_angle", text="Angle")
|
||||
|
||||
col.separator()
|
||||
col.row().prop(brush, "direction", expand=True)
|
||||
|
||||
if brush.sculpt_tool in {'DRAW', 'CREASE', 'BLOB', 'INFLATE', 'LAYER', 'CLAY'}:
|
||||
if brush.sculpt_tool in ('DRAW', 'GRAVITY', 'CREASE', 'BLOB', 'INFLATE', 'LAYER', 'CLAY', 'CLAY_STRIP'):
|
||||
col.separator()
|
||||
|
||||
col.prop(brush, "use_accumulate")
|
||||
|
||||
if brush.sculpt_tool == 'LAYER':
|
||||
if brush.sculpt_tool not in ('LAYER', 'GRAB', 'ROTATE', 'THUMB', 'SMOOTH'):
|
||||
col.separator()
|
||||
|
||||
col.prop(brush, "use_layer", "Layer")
|
||||
else:
|
||||
col.separator()
|
||||
|
||||
col.label("Layer:")
|
||||
|
||||
if brush.sculpt_tool in ('LAYER'):
|
||||
col.separator()
|
||||
|
||||
if brush.sculpt_tool not in ('GRAB', 'ROTATE', 'THUMB', 'SMOOTH'):
|
||||
row = col.row()
|
||||
row.prop(brush, "layer_limit", "Limit")
|
||||
row.active = brush.use_layer
|
||||
|
||||
ob = context.sculpt_object
|
||||
do_persistent = True
|
||||
|
||||
@@ -607,8 +628,15 @@ class VIEW3D_PT_tools_brush(PaintPanel, bpy.types.Panel):
|
||||
do_persistent = False
|
||||
|
||||
if do_persistent:
|
||||
col.prop(brush, "use_persistent")
|
||||
col.operator("sculpt.set_persistent_base")
|
||||
row = col.row()
|
||||
row.prop(brush, "use_persistent")
|
||||
row.active = brush.use_layer
|
||||
row = col.row()
|
||||
row.operator("sculpt.set_persistent_base")
|
||||
row.active = brush.use_layer
|
||||
|
||||
col.separator()
|
||||
col.prop(brush, "use_symmetry_feather", text="Symmetry Feather")
|
||||
|
||||
# Texture Paint Mode #
|
||||
|
||||
@@ -709,44 +737,23 @@ class VIEW3D_PT_tools_brush_texture(PaintPanel, bpy.types.Panel):
|
||||
col.separator()
|
||||
|
||||
col = layout.column()
|
||||
col.active = tex_slot.map_mode in {'FIXED'}
|
||||
col.active = tex_slot.map_mode in ('FIXED', 'TILED', 'WRAP')
|
||||
col.label(text="Angle:")
|
||||
|
||||
col = layout.column()
|
||||
if not brush.use_anchor and brush.sculpt_tool not in {'GRAB', 'SNAKE_HOOK', 'THUMB', 'ROTATE'} and tex_slot.map_mode in {'FIXED'}:
|
||||
col.prop(brush, "texture_angle_source_random", text="")
|
||||
else:
|
||||
col.prop(brush, "texture_angle_source_no_random", text="")
|
||||
|
||||
#row = col.row(align=True)
|
||||
#row.label(text="Angle:")
|
||||
#row.active = tex_slot.map_mode in {'FIXED', 'TILED'}
|
||||
|
||||
#row = col.row(align=True)
|
||||
|
||||
#col = row.column()
|
||||
#col.active = tex_slot.map_mode in {'FIXED'}
|
||||
#col.prop(brush, "use_rake", toggle=True, icon='PARTICLEMODE', text="")
|
||||
col.prop(brush, "texture_angle_source_random", text="")
|
||||
|
||||
col = layout.column()
|
||||
col.prop(tex_slot, "angle", text="")
|
||||
col.active = tex_slot.map_mode in {'FIXED', 'TILED'}
|
||||
col.active = tex_slot.map_mode in ('FIXED', 'TILED', 'WRAP')
|
||||
|
||||
#col = layout.column()
|
||||
#col.prop(brush, "use_random_rotation")
|
||||
#col.active = (not brush.use_rake) and (not brush.use_anchor) and (brush.sculpt_tool not in {'GRAB', 'SNAKE_HOOK', 'THUMB', 'ROTATE'}) and tex_slot.map_mode in {'FIXED'}
|
||||
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
col = layout.column()
|
||||
col.prop(tex_slot, "offset")
|
||||
|
||||
col = split.column()
|
||||
|
||||
col = layout.column()
|
||||
col.prop(tex_slot, "scale")
|
||||
|
||||
col = layout.column()
|
||||
|
||||
row = col.row(align=True)
|
||||
row.label(text="Sample Bias:")
|
||||
row = col.row(align=True)
|
||||
@@ -754,7 +761,7 @@ class VIEW3D_PT_tools_brush_texture(PaintPanel, bpy.types.Panel):
|
||||
|
||||
row = col.row(align=True)
|
||||
row.label(text="Overlay:")
|
||||
row.active = tex_slot.map_mode in {'FIXED', 'TILED'}
|
||||
row.active = tex_slot.map_mode in ('FIXED', 'TILED', 'WRAP')
|
||||
|
||||
row = col.row(align=True)
|
||||
|
||||
@@ -765,11 +772,11 @@ class VIEW3D_PT_tools_brush_texture(PaintPanel, bpy.types.Panel):
|
||||
else:
|
||||
col.prop(brush, "use_texture_overlay", toggle=True, text="", icon='MUTE_IPO_ON')
|
||||
|
||||
col.active = tex_slot.map_mode in {'FIXED', 'TILED'}
|
||||
col.active = tex_slot.map_mode in ('FIXED', 'TILED', 'WRAP')
|
||||
|
||||
col = row.column()
|
||||
col.prop(brush, "texture_overlay_alpha", text="Alpha")
|
||||
col.active = tex_slot.map_mode in {'FIXED', 'TILED'} and brush.use_texture_overlay
|
||||
col.active = tex_slot.map_mode in ('FIXED', 'TILED', 'WRAP') and brush.use_texture_overlay
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_brush_tool(PaintPanel, bpy.types.Panel):
|
||||
@@ -846,6 +853,9 @@ class VIEW3D_PT_tools_brush_stroke(PaintPanel, bpy.types.Panel):
|
||||
row = col.row()
|
||||
row.active = brush.use_space
|
||||
row.prop(brush, "spacing", text="Spacing")
|
||||
row = col.row()
|
||||
row.active = brush.use_space
|
||||
row.prop(brush, "use_adaptive_space", text="Adaptive Spacing")
|
||||
|
||||
if (brush.sculpt_tool not in {'GRAB', 'THUMB', 'SNAKE_HOOK', 'ROTATE'}) and (not brush.use_anchor) and (not brush.use_restore_mesh):
|
||||
col = layout.column()
|
||||
@@ -954,8 +964,12 @@ class VIEW3D_PT_sculpt_options(PaintPanel, bpy.types.Panel):
|
||||
|
||||
layout.prop(sculpt, "use_threaded", text="Threaded Sculpt")
|
||||
layout.prop(sculpt, "show_low_resolution")
|
||||
layout.prop(sculpt, "show_brush")
|
||||
layout.prop(sculpt, "use_deform_only")
|
||||
layout.prop(sculpt, "show_brush")
|
||||
|
||||
row = layout.row()
|
||||
row.active = sculpt.show_brush and sculpt.is_on_surface_brush_capable()
|
||||
row.prop(sculpt, "show_brush_on_surface")
|
||||
|
||||
layout.label(text="Unified Settings:")
|
||||
layout.prop(tool_settings, "sculpt_paint_use_unified_size", text="Size")
|
||||
@@ -986,11 +1000,6 @@ class VIEW3D_PT_sculpt_symmetry(PaintPanel, bpy.types.Panel):
|
||||
|
||||
split.prop(sculpt, "radial_symmetry", text="Radial")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.prop(sculpt, "use_symmetry_feather", text="Feather")
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_brush_appearance(PaintPanel, bpy.types.Panel):
|
||||
bl_label = "Appearance"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
@@ -1008,8 +1017,7 @@ class VIEW3D_PT_tools_brush_appearance(PaintPanel, bpy.types.Panel):
|
||||
col = layout.column()
|
||||
|
||||
if context.sculpt_object and context.tool_settings.sculpt:
|
||||
#if brush.sculpt_tool in {'DRAW', 'INFLATE', 'CLAY', 'PINCH', 'CREASE', 'BLOB', 'FLATTEN', 'FILL', 'SCRAPE', 'CLAY_TUBES'}:
|
||||
if brush.sculpt_tool in {'DRAW', 'INFLATE', 'CLAY', 'PINCH', 'CREASE', 'BLOB', 'FLATTEN', 'FILL', 'SCRAPE'}:
|
||||
if brush.sculpt_tool in ('DRAW', 'GRAVITY', 'INFLATE', 'CLAY', 'CLAY_STRIPS', 'PINCH', 'CREASE', 'BLOB', 'FLATTEN', 'FILL', 'SCRAPE'):
|
||||
col.prop(brush, "cursor_color_add", text="Add Color")
|
||||
col.prop(brush, "cursor_color_subtract", text="Subtract Color")
|
||||
else:
|
||||
|
@@ -44,7 +44,7 @@ extern "C" {
|
||||
* and keep comment above the defines.
|
||||
* Use STRINGIFY() rather than defining with quotes */
|
||||
#define BLENDER_VERSION 257
|
||||
#define BLENDER_SUBVERSION 1
|
||||
#define BLENDER_SUBVERSION 2
|
||||
|
||||
#define BLENDER_MINVERSION 250
|
||||
#define BLENDER_MINSUBVERSION 0
|
||||
|
@@ -40,7 +40,7 @@ struct Brush;
|
||||
struct ImBuf;
|
||||
struct Scene;
|
||||
struct wmOperator;
|
||||
// enum CurveMappingPreset;
|
||||
//enum CurveMappingPreset;
|
||||
|
||||
/* datablock functions */
|
||||
struct Brush *add_brush(const char *name);
|
||||
@@ -94,22 +94,22 @@ struct ImBuf *brush_gen_radial_control_imbuf(struct Brush *br);
|
||||
|
||||
/* unified strength and size */
|
||||
|
||||
int brush_size(struct Brush *brush);
|
||||
int brush_size(const struct Brush *brush);
|
||||
void brush_set_size(struct Brush *brush, int value);
|
||||
|
||||
int brush_use_locked_size(struct Brush *brush);
|
||||
int brush_use_locked_size(const struct Brush *brush);
|
||||
void brush_set_use_locked_size(struct Brush *brush, int value);
|
||||
|
||||
int brush_use_alpha_pressure(struct Brush *brush);
|
||||
int brush_use_alpha_pressure(const struct Brush *brush);
|
||||
void brush_set_use_alpha_pressure(struct Brush *brush, int value);
|
||||
|
||||
int brush_use_size_pressure(struct Brush *brush);
|
||||
int brush_use_size_pressure(const struct Brush *brush);
|
||||
void brush_set_use_size_pressure(struct Brush *brush, int value);
|
||||
|
||||
float brush_unprojected_radius(struct Brush *brush);
|
||||
float brush_unprojected_radius(const struct Brush *brush);
|
||||
void brush_set_unprojected_radius(struct Brush *brush, float value);
|
||||
|
||||
float brush_alpha(struct Brush *brush);
|
||||
float brush_alpha(const struct Brush *brush);
|
||||
void brush_set_alpha(struct Brush *brush, float value);
|
||||
|
||||
/* debugging only */
|
||||
|
@@ -56,7 +56,7 @@ typedef struct Main {
|
||||
short versionfile, subversionfile;
|
||||
short minversionfile, minsubversionfile;
|
||||
int revision; /* svn revision of binary that saved file */
|
||||
|
||||
|
||||
struct Library *curlib;
|
||||
ListBase scene;
|
||||
ListBase library;
|
||||
|
@@ -52,7 +52,7 @@ void free_paint(struct Paint *p);
|
||||
void copy_paint(struct Paint *src, struct Paint *tar);
|
||||
|
||||
struct Paint *paint_get_active(struct Scene *sce);
|
||||
struct Brush *paint_brush(struct Paint *paint);
|
||||
struct Brush *paint_brush(const struct Paint *paint);
|
||||
void paint_brush_set(struct Paint *paint, struct Brush *br);
|
||||
|
||||
/* testing face select mode
|
||||
|
@@ -81,6 +81,7 @@ static void brush_set_defaults(Brush *brush)
|
||||
brush->autosmooth_factor= 0.0f;
|
||||
brush->crease_pinch_factor= 0.5f;
|
||||
brush->sculpt_plane = SCULPT_DISP_DIR_AREA;
|
||||
brush->sculpt_plane_range= 1;
|
||||
brush->plane_offset= 0.0f; /* how far above or below the plane that is found by averaging the faces */
|
||||
brush->plane_trim= 0.5f;
|
||||
brush->clone.alpha= 0.5f;
|
||||
@@ -93,7 +94,7 @@ static void brush_set_defaults(Brush *brush)
|
||||
brush->rgb[2]= 1.0f;
|
||||
|
||||
/* BRUSH STROKE SETTINGS */
|
||||
brush->flag |= (BRUSH_SPACE|BRUSH_SPACE_ATTEN);
|
||||
brush->flag |= (BRUSH_SPACE|BRUSH_SPACE_ATTEN|BRUSH_ADAPTIVE_SPACE);
|
||||
brush->spacing= 10; /* how far each brush dot should be spaced as a percentage of brush diameter */
|
||||
|
||||
brush->smooth_stroke_radius= 75;
|
||||
@@ -103,6 +104,10 @@ static void brush_set_defaults(Brush *brush)
|
||||
|
||||
brush->jitter= 0.0f;
|
||||
|
||||
brush->adaptive_space_factor= 1;
|
||||
|
||||
brush->frontface_angle= (float)(M_PI_2 * 80.0/90.0);
|
||||
|
||||
/* BRUSH TEXTURE SETTINGS */
|
||||
default_mtex(&brush->mtex);
|
||||
|
||||
@@ -192,7 +197,7 @@ void make_local_brush(Brush *brush)
|
||||
* - only local users: set flag
|
||||
* - mixed: make copy
|
||||
*/
|
||||
|
||||
|
||||
Main *bmain= G.main;
|
||||
Scene *scene;
|
||||
int local= 0, lib= 0;
|
||||
@@ -1139,7 +1144,7 @@ unsigned int *brush_gen_texture_cache(Brush *br, int half_side)
|
||||
TexResult texres= {0};
|
||||
int hasrgb, ix, iy;
|
||||
int side = half_side * 2;
|
||||
|
||||
|
||||
if(mtex->tex) {
|
||||
float x, y, step = 2.0 / side, co[3];
|
||||
|
||||
@@ -1206,6 +1211,16 @@ struct ImBuf *brush_gen_radial_control_imbuf(Brush *br)
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX: combine with loop above */
|
||||
/* XXX: sqrt and pow seem like they could be eliminated */
|
||||
/* invert the texture */
|
||||
for(i=0; i<side; ++i) {
|
||||
for(j=0; j<side; ++j) {
|
||||
if (sqrt(pow(i - half, 2) + pow(j - half, 2)) < half)
|
||||
im->rect_float[i*side+j]= 1.0f - im->rect_float[i*side+j];
|
||||
}
|
||||
}
|
||||
|
||||
MEM_freeN(texcache);
|
||||
}
|
||||
|
||||
@@ -1214,7 +1229,15 @@ struct ImBuf *brush_gen_radial_control_imbuf(Brush *br)
|
||||
|
||||
/* Unified Size and Strength */
|
||||
|
||||
static void set_unified_settings(Brush *brush, short flag, int value)
|
||||
// XXX: unified settings are stored in scene toolsettings
|
||||
// to simplify things (from an API standpoint, not implementation),
|
||||
// all of the flags in each scene are set to the same value.
|
||||
// the 'get' functions return first value, since all should be the same
|
||||
// This arrangement seems odd, is there a better whay?
|
||||
// At this point, I think UserPrefs had been ruled out, but I do not know why.
|
||||
// ~~~~jwilkins
|
||||
|
||||
static void set_unified_settings(const Brush *brush, short flag, int value)
|
||||
{
|
||||
Scene *sce;
|
||||
for (sce= G.main->scene.first; sce; sce= sce->id.next) {
|
||||
@@ -1233,7 +1256,7 @@ static void set_unified_settings(Brush *brush, short flag, int value)
|
||||
}
|
||||
}
|
||||
|
||||
static short unified_settings(Brush *brush)
|
||||
static short unified_settings(const Brush *brush)
|
||||
{
|
||||
Scene *sce;
|
||||
for (sce= G.main->scene.first; sce; sce= sce->id.next) {
|
||||
@@ -1264,7 +1287,7 @@ static short unified_settings(Brush *brush)
|
||||
// In anycase, a better solution is needed to prevent
|
||||
// inconsistency.
|
||||
|
||||
static void set_unified_size(Brush *brush, int value)
|
||||
static void set_unified_size(const Brush *brush, int value)
|
||||
{
|
||||
Scene *sce;
|
||||
for (sce= G.main->scene.first; sce; sce= sce->id.next) {
|
||||
@@ -1280,7 +1303,7 @@ static void set_unified_size(Brush *brush, int value)
|
||||
}
|
||||
}
|
||||
|
||||
static int unified_size(Brush *brush)
|
||||
static int unified_size(const Brush *brush)
|
||||
{
|
||||
Scene *sce;
|
||||
for (sce= G.main->scene.first; sce; sce= sce->id.next) {
|
||||
@@ -1298,7 +1321,7 @@ static int unified_size(Brush *brush)
|
||||
return 35; // XXX magic number
|
||||
}
|
||||
|
||||
static void set_unified_alpha(Brush *brush, float value)
|
||||
static void set_unified_alpha(const Brush *brush, float value)
|
||||
{
|
||||
Scene *sce;
|
||||
for (sce= G.main->scene.first; sce; sce= sce->id.next) {
|
||||
@@ -1314,7 +1337,7 @@ static void set_unified_alpha(Brush *brush, float value)
|
||||
}
|
||||
}
|
||||
|
||||
static float unified_alpha(Brush *brush)
|
||||
static float unified_alpha(const Brush *brush)
|
||||
{
|
||||
Scene *sce;
|
||||
for (sce= G.main->scene.first; sce; sce= sce->id.next) {
|
||||
@@ -1332,7 +1355,7 @@ static float unified_alpha(Brush *brush)
|
||||
return 0.5f; // XXX magic number
|
||||
}
|
||||
|
||||
static void set_unified_unprojected_radius(Brush *brush, float value)
|
||||
static void set_unified_unprojected_radius(const Brush *brush, float value)
|
||||
{
|
||||
Scene *sce;
|
||||
for (sce= G.main->scene.first; sce; sce= sce->id.next) {
|
||||
@@ -1348,7 +1371,7 @@ static void set_unified_unprojected_radius(Brush *brush, float value)
|
||||
}
|
||||
}
|
||||
|
||||
static float unified_unprojected_radius(Brush *brush)
|
||||
static float unified_unprojected_radius(const Brush *brush)
|
||||
{
|
||||
Scene *sce;
|
||||
for (sce= G.main->scene.first; sce; sce= sce->id.next) {
|
||||
@@ -1371,11 +1394,9 @@ void brush_set_size(Brush *brush, int size)
|
||||
set_unified_size(brush, size);
|
||||
else
|
||||
brush->size= size;
|
||||
|
||||
//WM_main_add_notifier(NC_BRUSH|NA_EDITED, brush);
|
||||
}
|
||||
|
||||
int brush_size(Brush *brush)
|
||||
int brush_size(const Brush *brush)
|
||||
{
|
||||
return (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_SIZE) ? unified_size(brush) : brush->size;
|
||||
}
|
||||
@@ -1391,11 +1412,9 @@ void brush_set_use_locked_size(Brush *brush, int value)
|
||||
else
|
||||
brush->flag &= ~BRUSH_LOCK_SIZE;
|
||||
}
|
||||
|
||||
//WM_main_add_notifier(NC_BRUSH|NA_EDITED, brush);
|
||||
}
|
||||
|
||||
int brush_use_locked_size(Brush *brush)
|
||||
int brush_use_locked_size(const Brush *brush)
|
||||
{
|
||||
return (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_SIZE) ? (unified_settings(brush) & SCULPT_PAINT_UNIFIED_LOCK_BRUSH_SIZE) : (brush->flag & BRUSH_LOCK_SIZE);
|
||||
}
|
||||
@@ -1411,11 +1430,9 @@ void brush_set_use_size_pressure(Brush *brush, int value)
|
||||
else
|
||||
brush->flag &= ~BRUSH_SIZE_PRESSURE;
|
||||
}
|
||||
|
||||
//WM_main_add_notifier(NC_BRUSH|NA_EDITED, brush);
|
||||
}
|
||||
|
||||
int brush_use_size_pressure(Brush *brush)
|
||||
int brush_use_size_pressure(const Brush *brush)
|
||||
{
|
||||
return (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_SIZE) ? (unified_settings(brush) & SCULPT_PAINT_UNIFIED_SIZE_PRESSURE) : (brush->flag & BRUSH_SIZE_PRESSURE);
|
||||
}
|
||||
@@ -1431,11 +1448,9 @@ void brush_set_use_alpha_pressure(Brush *brush, int value)
|
||||
else
|
||||
brush->flag &= ~BRUSH_ALPHA_PRESSURE;
|
||||
}
|
||||
|
||||
//WM_main_add_notifier(NC_BRUSH|NA_EDITED, brush);
|
||||
}
|
||||
|
||||
int brush_use_alpha_pressure(Brush *brush)
|
||||
int brush_use_alpha_pressure(const Brush *brush)
|
||||
{
|
||||
return (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_ALPHA) ? (unified_settings(brush) & SCULPT_PAINT_UNIFIED_ALPHA_PRESSURE) : (brush->flag & BRUSH_ALPHA_PRESSURE);
|
||||
}
|
||||
@@ -1446,11 +1461,9 @@ void brush_set_unprojected_radius(Brush *brush, float unprojected_radius)
|
||||
set_unified_unprojected_radius(brush, unprojected_radius);
|
||||
else
|
||||
brush->unprojected_radius= unprojected_radius;
|
||||
|
||||
//WM_main_add_notifier(NC_BRUSH|NA_EDITED, brush);
|
||||
}
|
||||
|
||||
float brush_unprojected_radius(Brush *brush)
|
||||
float brush_unprojected_radius(const Brush *brush)
|
||||
{
|
||||
return (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_SIZE) ? unified_unprojected_radius(brush) : brush->unprojected_radius;
|
||||
}
|
||||
@@ -1461,11 +1474,9 @@ void brush_set_alpha(Brush *brush, float alpha)
|
||||
set_unified_alpha(brush, alpha);
|
||||
else
|
||||
brush->alpha= alpha;
|
||||
|
||||
//WM_main_add_notifier(NC_BRUSH|NA_EDITED, brush);
|
||||
}
|
||||
|
||||
float brush_alpha(Brush *brush)
|
||||
float brush_alpha(const Brush *brush)
|
||||
{
|
||||
return (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_ALPHA) ? unified_alpha(brush) : brush->alpha;
|
||||
}
|
||||
|
@@ -61,10 +61,35 @@
|
||||
#include "BKE_material.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_node.h"
|
||||
|
||||
#include "BKE_texture.h"
|
||||
|
||||
#include "GPU_material.h"
|
||||
|
||||
/* material for the current MatCap */
|
||||
|
||||
Material matcap_ma;
|
||||
static MTex matcap_mtex;
|
||||
static Tex matcap_tex;
|
||||
|
||||
static void init_matcap(void)
|
||||
{
|
||||
default_tex(&matcap_tex);
|
||||
matcap_tex.type = TEX_IMAGE;
|
||||
|
||||
default_mtex(&matcap_mtex);
|
||||
matcap_mtex.texco = TEXCO_NORM;
|
||||
matcap_mtex.tex = &matcap_tex;
|
||||
|
||||
//XXX: this is a hack to eliminate artifacts around the edges
|
||||
//matcap_mtex.size[0] = 0.95f;
|
||||
//matcap_mtex.size[1] = 0.95f;
|
||||
|
||||
init_material(&matcap_ma);
|
||||
matcap_ma.mode |= MA_SHLESS;
|
||||
matcap_ma.shade_flag |= MA_OBCOLOR;
|
||||
matcap_ma.mtex[0] = &matcap_mtex;
|
||||
}
|
||||
|
||||
/* used in UI and render */
|
||||
Material defmaterial;
|
||||
|
||||
@@ -72,6 +97,7 @@ Material defmaterial;
|
||||
void init_def_material(void)
|
||||
{
|
||||
init_material(&defmaterial);
|
||||
init_matcap();
|
||||
}
|
||||
|
||||
/* not material itself */
|
||||
|
@@ -1047,7 +1047,9 @@ Object *add_only_object(int type, const char *name)
|
||||
unit_m4(ob->constinv);
|
||||
unit_m4(ob->parentinv);
|
||||
unit_m4(ob->obmat);
|
||||
ob->dt= OB_TEXTURE;
|
||||
|
||||
ob->dt= OB_MATCAP;
|
||||
|
||||
ob->empty_drawtype= OB_PLAINAXES;
|
||||
ob->empty_drawsize= 1.0;
|
||||
|
||||
|
@@ -78,7 +78,7 @@ Paint *paint_get_active(Scene *sce)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Brush *paint_brush(Paint *p)
|
||||
Brush *paint_brush(const Paint *p)
|
||||
{
|
||||
return p ? p->brush : NULL;
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id$
|
||||
* $Id: BLI_cpu.h 34966 2011-02-18 13:58:08Z jesterking $
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
|
@@ -245,6 +245,10 @@ void BLI_pbvh_node_free_proxies(PBVHNode* node);
|
||||
PBVHProxyNode* BLI_pbvh_node_add_proxy(PBVH* bvh, PBVHNode* node);
|
||||
void BLI_pbvh_gather_proxies(PBVH* pbvh, PBVHNode*** nodes, int* totnode);
|
||||
|
||||
void BLI_pbvh_draw_nodes_in_sphere(PBVH *bvh, float location[3], float radius);
|
||||
void BLI_pbvh_gather_nodes_in_sphere(PBVH *bvh, float location[3], float radius, PBVHNode ***nodes, int *totnode);
|
||||
void BLI_pbvh_node_array_draw(PBVH *bvh, PBVHNode **nodes, int totnode);
|
||||
|
||||
//void BLI_pbvh_node_BB_reset(PBVHNode* node);
|
||||
//void BLI_pbvh_node_BB_expand(PBVHNode* node, float co[3]);
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
*
|
||||
* $Id$
|
||||
* $Id: cpu.c 35246 2011-02-27 20:37:56Z jesterking $
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
|
@@ -398,6 +398,7 @@ static void build_grids_leaf_node(PBVH *bvh, PBVHNode *node)
|
||||
GPU_build_grid_buffers(bvh->grids, node->prim_indices,
|
||||
node->totprim, bvh->gridsize);
|
||||
}
|
||||
|
||||
node->flag |= PBVH_UpdateDrawBuffers;
|
||||
}
|
||||
|
||||
@@ -717,7 +718,7 @@ static PBVHNode *pbvh_iter_next_occluded(PBVHIter *iter)
|
||||
node= iter->stack[iter->stacksize].node;
|
||||
|
||||
/* on a mesh with no faces this can happen
|
||||
* can remove this check if we know meshes have at least 1 face */
|
||||
* can remove this check if we know meshes have at least 1 face */
|
||||
if(node==NULL) return NULL;
|
||||
|
||||
if(iter->scb && !iter->scb(node, iter->search_data)) continue; /* don't traverse, outside of search zone */
|
||||
@@ -792,6 +793,8 @@ void BLI_pbvh_search_callback(PBVH *bvh,
|
||||
pbvh_iter_end(&iter);
|
||||
}
|
||||
|
||||
// XXX: todo: benchmark the cost of using malloc/free for this binary tree
|
||||
|
||||
typedef struct node_tree {
|
||||
PBVHNode* data;
|
||||
|
||||
@@ -1321,7 +1324,7 @@ static int ray_face_intersection(float ray_start[3], float ray_normal[3],
|
||||
float dist;
|
||||
|
||||
if ((isect_ray_tri_epsilon_v3(ray_start, ray_normal, t0, t1, t2, &dist, NULL, 0.1f) && dist < *fdist) ||
|
||||
(t3 && isect_ray_tri_epsilon_v3(ray_start, ray_normal, t0, t2, t3, &dist, NULL, 0.1f) && dist < *fdist))
|
||||
(t3 && isect_ray_tri_epsilon_v3(ray_start, ray_normal, t0, t2, t3, &dist, NULL, 0.1f) && dist < *fdist))
|
||||
{
|
||||
*fdist = dist;
|
||||
return 1;
|
||||
@@ -1633,3 +1636,66 @@ void BLI_pbvh_gather_proxies(PBVH* pbvh, PBVHNode*** r_array, int* r_tot)
|
||||
*r_array= array;
|
||||
*r_tot= tot;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
float location[3];
|
||||
float radius_squared;
|
||||
} SearchSphereData;
|
||||
|
||||
/* Test AABB against sphere */
|
||||
static int search_sphere_cb(PBVHNode *node, void *data_v)
|
||||
{
|
||||
SearchSphereData *data = data_v;
|
||||
float *center = data->location, nearest[3];
|
||||
float t[3], bb_min[3], bb_max[3];
|
||||
int i;
|
||||
|
||||
BLI_pbvh_node_get_BB(node, bb_min, bb_max);
|
||||
|
||||
for(i = 0; i < 3; ++i) {
|
||||
if(bb_min[i] > center[i])
|
||||
nearest[i] = bb_min[i];
|
||||
else if(bb_max[i] < center[i])
|
||||
nearest[i] = bb_max[i];
|
||||
else
|
||||
nearest[i] = center[i];
|
||||
}
|
||||
|
||||
sub_v3_v3v3(t, center, nearest);
|
||||
|
||||
return dot_v3v3(t, t) < data->radius_squared;
|
||||
}
|
||||
|
||||
void BLI_pbvh_gather_nodes_in_sphere(PBVH *bvh, float location[3], float radius, PBVHNode ***nodes, int *totnode)
|
||||
{
|
||||
SearchSphereData data;
|
||||
|
||||
copy_v3_v3(data.location, location);
|
||||
data.radius_squared= radius*radius;
|
||||
|
||||
BLI_pbvh_search_gather(bvh, search_sphere_cb, &data, nodes, totnode);
|
||||
}
|
||||
|
||||
void BLI_pbvh_node_array_draw(PBVH *bvh, PBVHNode **nodes, int totnode)
|
||||
{
|
||||
int i;
|
||||
|
||||
pbvh_update_normals(bvh, nodes, totnode, NULL);
|
||||
pbvh_update_draw_buffers(bvh, nodes, totnode, 1);
|
||||
|
||||
for (i= 0; i < totnode; i++)
|
||||
BLI_pbvh_node_draw(nodes[i], 0);
|
||||
}
|
||||
|
||||
void BLI_pbvh_draw_nodes_in_sphere(PBVH *bvh, float location[3], float radius)
|
||||
{
|
||||
PBVHNode **nodes;
|
||||
int totnode;
|
||||
|
||||
BLI_pbvh_gather_nodes_in_sphere(bvh, location, radius, &nodes, &totnode);
|
||||
|
||||
if (nodes) {
|
||||
BLI_pbvh_node_array_draw(bvh, nodes, totnode);
|
||||
MEM_freeN(nodes);
|
||||
}
|
||||
}
|
||||
|
@@ -3697,7 +3697,7 @@ static void lib_link_object(FileData *fd, Main *main)
|
||||
|
||||
ob->gpd= newlibadr_us(fd, ob->id.lib, ob->gpd);
|
||||
ob->duplilist= NULL;
|
||||
|
||||
|
||||
ob->id.flag -= LIB_NEEDLINK;
|
||||
/* if id.us==0 a new base will be created later on */
|
||||
|
||||
@@ -4128,7 +4128,7 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
|
||||
if(tmd->curfalloff)
|
||||
direct_link_curvemapping(fd, tmd->curfalloff);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void direct_link_object(FileData *fd, Object *ob)
|
||||
@@ -4816,6 +4816,8 @@ static void lib_link_screen(FileData *fd, Main *main)
|
||||
if(v3d->localvd) {
|
||||
v3d->localvd->camera= newlibadr(fd, sc->id.lib, v3d->localvd->camera);
|
||||
}
|
||||
|
||||
v3d->matcap_ima= newlibadr_us(fd, sc->id.lib, v3d->matcap_ima);
|
||||
}
|
||||
else if(sl->spacetype==SPACE_IPO) {
|
||||
SpaceIpo *sipo= (SpaceIpo *)sl;
|
||||
@@ -5048,6 +5050,7 @@ void lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *curscene)
|
||||
/* not very nice, but could help */
|
||||
if((v3d->layact & v3d->lay)==0) v3d->layact= v3d->lay;
|
||||
|
||||
v3d->matcap_ima = restore_pointer_by_name(newmain, (ID *)v3d->matcap_ima, 1);
|
||||
}
|
||||
else if(sl->spacetype==SPACE_IPO) {
|
||||
SpaceIpo *sipo= (SpaceIpo *)sl;
|
||||
@@ -6530,10 +6533,10 @@ static void area_add_window_regions(ScrArea *sa, SpaceLink *sl, ListBase *lb)
|
||||
|
||||
ar->v2d.min[0]= 0.0f;
|
||||
ar->v2d.min[1]= 0.0f;
|
||||
|
||||
|
||||
ar->v2d.max[0]= MAXFRAMEF;
|
||||
ar->v2d.max[1]= FLT_MAX;
|
||||
|
||||
|
||||
ar->v2d.minzoom= 0.01f;
|
||||
ar->v2d.maxzoom= 50;
|
||||
ar->v2d.scroll = (V2D_SCROLL_BOTTOM|V2D_SCROLL_SCALE_HORIZONTAL);
|
||||
@@ -11135,7 +11138,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
||||
Scene *scene;
|
||||
bScreen *sc;
|
||||
Tex *tex;
|
||||
Brush *brush;
|
||||
|
||||
for (sc= main->screen.first; sc; sc= sc->id.next) {
|
||||
ScrArea *sa;
|
||||
@@ -11251,11 +11253,29 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
||||
SEQ_END
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* GSOC 2010 Sculpt - New settings for Brush */
|
||||
/* Sanity check on Sculpt/Paint settings */
|
||||
/* These sanity checks apply to all versions */
|
||||
{
|
||||
Scene *sce;
|
||||
for (sce= main->scene.first; sce; sce= sce->id.next) {
|
||||
if (sce->toolsettings->sculpt_paint_unified_alpha == 0)
|
||||
sce->toolsettings->sculpt_paint_unified_alpha = 0.5f;
|
||||
|
||||
if (sce->toolsettings->sculpt_paint_unified_unprojected_radius == 0)
|
||||
sce->toolsettings->sculpt_paint_unified_unprojected_radius = 0.125f;
|
||||
|
||||
if (sce->toolsettings->sculpt_paint_unified_size == 0)
|
||||
sce->toolsettings->sculpt_paint_unified_size = 35;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
Brush *brush;
|
||||
for (brush= main->brush.first; brush; brush= brush->id.next) {
|
||||
/* Sanity Check */
|
||||
/* Sanity Check for Brushes 2.52 */
|
||||
/* These sanity checks apply to all versions */
|
||||
|
||||
// infinite number of dabs
|
||||
if (brush->spacing == 0)
|
||||
@@ -11268,6 +11288,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
||||
// bad radius
|
||||
if (brush->unprojected_radius == 0)
|
||||
brush->unprojected_radius = 0.125f;
|
||||
brush->unprojected_radius = 0.125;
|
||||
|
||||
// unusable size
|
||||
if (brush->size == 0)
|
||||
@@ -11295,11 +11316,27 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
||||
|
||||
// same as dots
|
||||
if (brush->rate == 0)
|
||||
brush->rate = 0.1f;
|
||||
brush->rate= 0.1f;
|
||||
|
||||
/* Sanity Check for Brushes 2.53 */
|
||||
|
||||
// divide by zero
|
||||
if (brush->adaptive_space_factor == 0)
|
||||
brush->adaptive_space_factor= 1;
|
||||
|
||||
if (brush->sculpt_plane_range == 0)
|
||||
brush->sculpt_plane_range= 1;
|
||||
|
||||
if (brush->frontface_angle== 0)
|
||||
brush->frontface_angle= (float)(M_PI_2 * 80.0/90.0);
|
||||
|
||||
/* Sanity Check for Brushes 2.57 */
|
||||
|
||||
if (brush->layer_limit == 0)
|
||||
brush->layer_limit= 0.25f;
|
||||
|
||||
/* New Settings */
|
||||
if (main->versionfile < 252 || (main->versionfile == 252 && main->subversionfile < 5)) {
|
||||
brush->flag |= BRUSH_SPACE_ATTEN; // explicitly enable adaptive space
|
||||
brush->flag |= BRUSH_SPACE_ATTEN; // explicitly enable adaptive strength
|
||||
|
||||
// spacing was originally in pixels, convert it to percentage for new version
|
||||
// size should not be zero due to sanity check above
|
||||
@@ -11323,21 +11360,26 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
||||
brush->sub_col[2] = 1.00f;
|
||||
}
|
||||
}
|
||||
|
||||
if (main->versionfile < 257)
|
||||
brush->flag |= BRUSH_ADAPTIVE_SPACE; // explicitly enable adaptive space
|
||||
}
|
||||
}
|
||||
|
||||
/* GSOC Sculpt 2010 - Sanity check on Sculpt/Paint settings */
|
||||
if (main->versionfile < 253) {
|
||||
Scene *sce;
|
||||
for (sce= main->scene.first; sce; sce= sce->id.next) {
|
||||
if (sce->toolsettings->sculpt_paint_unified_alpha == 0)
|
||||
sce->toolsettings->sculpt_paint_unified_alpha = 0.5f;
|
||||
/* GSOC Sculpt 2011 - MatCap */
|
||||
if (main->versionfile < 257 || (main->versionfile == 257 && main->subversionfile < 2)) {
|
||||
Object *ob;
|
||||
|
||||
if (sce->toolsettings->sculpt_paint_unified_unprojected_radius == 0)
|
||||
sce->toolsettings->sculpt_paint_unified_unprojected_radius = 0.125f;
|
||||
/* MatCaps */
|
||||
for (ob=main->object.first; ob; ob=ob->id.next) {
|
||||
Scene *sce;
|
||||
|
||||
if (sce->toolsettings->sculpt_paint_unified_size == 0)
|
||||
sce->toolsettings->sculpt_paint_unified_size = 35;
|
||||
for (sce= main->scene.first; sce; sce= sce->id.next) {
|
||||
/* If max drawtype is textured then assume user won't mind if we bump it up to use MatCaps, */
|
||||
/* Otherwise, assume that if max drawtype is less than textured then user doesn't want to use MatCaps */
|
||||
if (ob->dt == OB_TEXTURE)
|
||||
ob->dt = OB_MATCAP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11525,7 +11567,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
||||
|
||||
if (main->versionfile < 256 || (main->versionfile == 256 && main->subversionfile <3)){
|
||||
bScreen *sc;
|
||||
Brush *brush;
|
||||
Object *ob;
|
||||
ParticleSettings *part;
|
||||
Material *mat;
|
||||
@@ -11557,11 +11598,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
||||
}
|
||||
}
|
||||
|
||||
for (brush= main->brush.first; brush; brush= brush->id.next) {
|
||||
if(brush->height == 0)
|
||||
brush->height= 0.4f;
|
||||
}
|
||||
|
||||
/* replace 'rim material' option for in offset*/
|
||||
for(ob = main->object.first; ob; ob = ob->id.next) {
|
||||
ModifierData *md;
|
||||
@@ -12389,13 +12425,13 @@ static void expand_object_expandModifiers(void *userData, Object *UNUSED(ob),
|
||||
ID **idpoin)
|
||||
{
|
||||
struct { FileData *fd; Main *mainvar; } *data= userData;
|
||||
|
||||
|
||||
FileData *fd= data->fd;
|
||||
Main *mainvar= data->mainvar;
|
||||
|
||||
|
||||
expand_doit(fd, mainvar, *idpoin);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void expand_object(FileData *fd, Main *mainvar, Object *ob)
|
||||
{
|
||||
ParticleSystem *psys;
|
||||
|
@@ -58,4 +58,8 @@ int ED_undo_paint_step(struct bContext *C, int type, int step, const char *name)
|
||||
void ED_undo_paint_free(void);
|
||||
int ED_undo_paint_valid(int type, const char *name);
|
||||
|
||||
void ED_draw_paint_overlay(const struct bContext *C, struct ARegion *ar);
|
||||
void ED_draw_on_surface_cursor(float modelview[16], float projection[16], float col[3], float alpha, float size[3], int viewport[4], float location[3], float inner_radius, float outer_radius, int brush_size);
|
||||
void ED_draw_fixed_overlay_on_surface(float modelview[16], float projection[16], float size[3], int viewport[4], float location[3], float outer_radius, struct Sculpt *sd, struct Brush *brush, struct ViewContext *vc, float t, float b, float l, float r, float angle);
|
||||
|
||||
#endif
|
||||
|
@@ -22,3 +22,7 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'):
|
||||
incs += ' ' + env['BF_PTHREADS_INC']
|
||||
|
||||
env.BlenderLib ( 'bf_editors_sculpt_paint', sources, Split(incs), defines=defs, libtype=['core'], priority=[40] )
|
||||
if env['WITH_BF_ONSURFACEBRUSH']:
|
||||
defs.append('WITH_ONSURFACEBRUSH')
|
||||
|
||||
env.BlenderLib ( 'bf_editors_sculpt_paint', sources, Split(incs), defines=defs, libtype=['core'], priority=[40] )
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -286,7 +286,10 @@ void BRUSH_OT_curve_preset(wmOperatorType *ot)
|
||||
ot->exec= brush_curve_preset_exec;
|
||||
ot->poll= brush_curve_preset_poll;
|
||||
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
// XXX: check the meaning of these flags, removed OPTYPE_REGISTER becauase
|
||||
// that seems to mean display a panel in the lower left, but this operator
|
||||
// as no meaningful UI to present the user in that area
|
||||
ot->flag= OPTYPE_UNDO;
|
||||
|
||||
RNA_def_enum(ot->srna, "shape", prop_shape_items, CURVE_PRESET_SMOOTH, "Mode", "");
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -107,7 +107,7 @@ typedef struct SculptUndoNode {
|
||||
char shapeName[sizeof(((KeyBlock *)0))->name];
|
||||
} SculptUndoNode;
|
||||
|
||||
SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node);
|
||||
SculptUndoNode *sculpt_undo_push_node(const Object *ob, PBVHNode *node);
|
||||
SculptUndoNode *sculpt_undo_get_node(PBVHNode *node);
|
||||
void sculpt_undo_push_begin(const char *name);
|
||||
void sculpt_undo_push_end(void);
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id$
|
||||
* $Id: sculpt_undo.c 36485 2011-05-04 13:15:42Z nazgul $
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
@@ -246,7 +246,7 @@ SculptUndoNode *sculpt_undo_get_node(PBVHNode *node)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node)
|
||||
SculptUndoNode *sculpt_undo_push_node(const Object *ob, PBVHNode *node)
|
||||
{
|
||||
ListBase *lb= undo_paint_push_get_list(UNDO_PAINT_MESH);
|
||||
SculptSession *ss = ob->sculpt;
|
||||
|
@@ -359,7 +359,7 @@ static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, O
|
||||
int istex, solidtex= 0;
|
||||
|
||||
// XXX scene->obedit warning
|
||||
if(v3d->drawtype==OB_SOLID || ((ob->mode & OB_MODE_EDIT) && v3d->drawtype!=OB_TEXTURE)) {
|
||||
if(v3d->drawtype==OB_SOLID || ((ob->mode & OB_MODE_EDIT) && !ELEM(v3d->drawtype, OB_TEXTURE, OB_MATCAP))) {
|
||||
/* draw with default lights in solid draw mode and edit mode */
|
||||
solidtex= 1;
|
||||
Gtexdraw.islit= -1;
|
||||
@@ -375,7 +375,7 @@ static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, O
|
||||
obcol[3]= CLAMPIS(ob->col[3]*255, 0, 255);
|
||||
|
||||
glCullFace(GL_BACK); glEnable(GL_CULL_FACE);
|
||||
if(solidtex || v3d->drawtype==OB_TEXTURE) istex= 1;
|
||||
if(solidtex || ELEM(v3d->drawtype, OB_TEXTURE, OB_MATCAP)) istex= 1;
|
||||
else istex= 0;
|
||||
|
||||
Gtexdraw.ob = ob;
|
||||
|
@@ -104,7 +104,7 @@
|
||||
|
||||
/* this condition has been made more complex since editmode can draw textures */
|
||||
#define CHECK_OB_DRAWTEXTURE(vd, dt) \
|
||||
((vd->drawtype==OB_TEXTURE && dt>OB_SOLID) || \
|
||||
((ELEM(vd->drawtype, OB_TEXTURE, OB_MATCAP) && dt>OB_SOLID) || \
|
||||
(vd->drawtype==OB_SOLID && vd->flag2 & V3D_SOLID_TEX))
|
||||
|
||||
static void draw_bounding_volume(Scene *scene, Object *ob);
|
||||
@@ -126,7 +126,7 @@ static int check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
|
||||
return 1;
|
||||
|
||||
/* if its drawing textures with zbuf sel, then dont draw dots */
|
||||
if(dt==OB_TEXTURE && vd->drawtype==OB_TEXTURE)
|
||||
if(ELEM(dt, OB_TEXTURE, OB_MATCAP) && ELEM(vd->drawtype, OB_TEXTURE, OB_MATCAP))
|
||||
return 0;
|
||||
|
||||
if(vd->drawtype>=OB_SOLID && vd->flag2 & V3D_SOLID_TEX)
|
||||
@@ -215,7 +215,7 @@ int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt)
|
||||
if(ob==OBACT && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))
|
||||
return 0;
|
||||
|
||||
return (scene->gm.matmode == GAME_MAT_GLSL) && (dt >= OB_SHADED);
|
||||
return ((dt == OB_MATCAP) || (scene->gm.matmode == GAME_MAT_GLSL)) && (dt >= OB_SHADED);
|
||||
}
|
||||
|
||||
static int check_material_alpha(Base *base, Mesh *me, int glsl)
|
||||
|
@@ -313,6 +313,9 @@ static void view3d_free(SpaceLink *sl)
|
||||
}
|
||||
BLI_freelistN(&vd->bgpicbase);
|
||||
|
||||
if (vd->matcap_ima)
|
||||
vd->matcap_ima->id.us--;
|
||||
|
||||
if(vd->localvd) MEM_freeN(vd->localvd);
|
||||
|
||||
if(vd->properties_storage) MEM_freeN(vd->properties_storage);
|
||||
@@ -349,6 +352,11 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl)
|
||||
if(bgpic->ima)
|
||||
bgpic->ima->id.us++;
|
||||
|
||||
v3dn->matcap_ima= v3do->matcap_ima;
|
||||
|
||||
if (v3dn->matcap_ima)
|
||||
v3dn->matcap_ima->id.us++;
|
||||
|
||||
v3dn->properties_storage= NULL;
|
||||
|
||||
return (SpaceLink *)v3dn;
|
||||
|
@@ -2078,7 +2078,7 @@ CustomDataMask ED_view3d_datamask(Scene *scene, View3D *v3d)
|
||||
/* this includes normals for mesh_create_shadedColors */
|
||||
mask |= CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_NORMAL | CD_MASK_ORCO;
|
||||
}
|
||||
if((v3d->drawtype == OB_TEXTURE) || ((v3d->drawtype == OB_SOLID) && (v3d->flag2 & V3D_SOLID_TEX))) {
|
||||
if(ELEM(v3d->drawtype, OB_TEXTURE, OB_MATCAP) || ((v3d->drawtype == OB_SOLID) && (v3d->flag2 & V3D_SOLID_TEX))) {
|
||||
mask |= CD_MASK_MTFACE | CD_MASK_MCOL;
|
||||
|
||||
if(scene->gm.matmode == GAME_MAT_GLSL)
|
||||
@@ -2100,12 +2100,10 @@ CustomDataMask ED_viewedit_datamask(bScreen *screen)
|
||||
mask |= CD_MASK_MTFACE | CD_MASK_MCOL;
|
||||
|
||||
/* check if we need tfaces & mcols due to view mode */
|
||||
for(sa = screen->areabase.first; sa; sa = sa->next) {
|
||||
if(sa->spacetype == SPACE_VIEW3D) {
|
||||
for(sa = screen->areabase.first; sa; sa = sa->next)
|
||||
if(sa->spacetype == SPACE_VIEW3D)
|
||||
mask |= ED_view3d_datamask(scene, (View3D *)sa->spacedata.first);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* check if we need mcols due to vertex paint or weightpaint */
|
||||
if(ob) {
|
||||
if(ob->mode & OB_MODE_VERTEX_PAINT)
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id$
|
||||
* $Id: view3d_fly.c 36824 2011-05-23 02:53:30Z campbellbarton $
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
|
@@ -366,10 +366,14 @@ GPUFunction *GPU_lookup_function(const char *name)
|
||||
void GPU_extensions_exit(void)
|
||||
{
|
||||
extern Material defmaterial; // render module abuse...
|
||||
extern Material matcap_ma;
|
||||
|
||||
if(defmaterial.gpumaterial.first)
|
||||
GPU_material_free(&defmaterial);
|
||||
|
||||
if(matcap_ma.gpumaterial.first)
|
||||
GPU_material_free(&matcap_ma);
|
||||
|
||||
if(FUNCTION_HASH) {
|
||||
BLI_ghash_free(FUNCTION_HASH, NULL, (GHashValFreeFP)MEM_freeN);
|
||||
FUNCTION_HASH = NULL;
|
||||
|
@@ -1,5 +1,4 @@
|
||||
/*
|
||||
* $Id$
|
||||
/* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
@@ -213,7 +212,7 @@ static int is_pow2_limit(int num)
|
||||
|
||||
/* XXX: texturepaint not global!
|
||||
if (G.f & G_TEXTUREPAINT)
|
||||
return 1;*/
|
||||
return 1;*/
|
||||
|
||||
if (U.glreslimit != 0 && num > U.glreslimit)
|
||||
return 0;
|
||||
@@ -953,6 +952,7 @@ static Material *gpu_active_node_material(Material *ma)
|
||||
|
||||
void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, Object *ob, int glsl, int *do_alpha_pass)
|
||||
{
|
||||
extern Material matcap_ma;
|
||||
Material *ma;
|
||||
GPUMaterial *gpumat;
|
||||
GPUBlendMode blendmode;
|
||||
@@ -987,51 +987,70 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O
|
||||
GMS.blendmode= GMS.blendmode_fixed;
|
||||
}
|
||||
|
||||
/* no materials assigned? */
|
||||
if(ob->totcol==0) {
|
||||
if (MIN2(v3d->drawtype, ob->dt) != OB_MATCAP) {
|
||||
/* no materials assigned? */
|
||||
if(ob->totcol==0) {
|
||||
gpu_material_to_fixed(&GMS.matbuf[0], &defmaterial, 0, ob);
|
||||
|
||||
/* do material 1 too, for displists! */
|
||||
/* do material 1 too, for displists! */
|
||||
memcpy(&GMS.matbuf[1], &GMS.matbuf[0], sizeof(GPUMaterialFixed));
|
||||
|
||||
if(glsl) {
|
||||
GMS.gmatbuf[0]= &defmaterial;
|
||||
GPU_material_from_blender(GMS.gscene, &defmaterial);
|
||||
if(glsl) {
|
||||
GMS.gmatbuf[0]= &defmaterial;
|
||||
GPU_material_from_blender(GMS.gscene, &defmaterial);
|
||||
}
|
||||
|
||||
GMS.blendmode[0]= GPU_BLEND_SOLID;
|
||||
}
|
||||
|
||||
/* setup materials */
|
||||
for(a=1; a<=ob->totcol; a++) {
|
||||
/* find a suitable material */
|
||||
ma= give_current_material(ob, a);
|
||||
if(!glsl) ma= gpu_active_node_material(ma);
|
||||
if(ma==NULL) ma= &defmaterial;
|
||||
|
||||
GMS.blendmode[0]= GPU_BLEND_SOLID;
|
||||
}
|
||||
|
||||
/* setup materials */
|
||||
for(a=1; a<=ob->totcol; a++) {
|
||||
/* find a suitable material */
|
||||
ma= give_current_material(ob, a);
|
||||
if(!glsl) ma= gpu_active_node_material(ma);
|
||||
if(ma==NULL) ma= &defmaterial;
|
||||
/* create glsl material if requested */
|
||||
gpumat = (glsl)? GPU_material_from_blender(GMS.gscene, ma): NULL;
|
||||
|
||||
/* create glsl material if requested */
|
||||
gpumat = (glsl)? GPU_material_from_blender(GMS.gscene, ma): NULL;
|
||||
|
||||
if(gpumat) {
|
||||
/* do glsl only if creating it succeed, else fallback */
|
||||
GMS.gmatbuf[a]= ma;
|
||||
blendmode = GPU_material_blend_mode(gpumat, ob->col);
|
||||
}
|
||||
else {
|
||||
/* fixed function opengl materials */
|
||||
if(gpumat) {
|
||||
/* do glsl only if creating it succeed, else fallback */
|
||||
GMS.gmatbuf[a]= ma;
|
||||
blendmode = GPU_material_blend_mode(gpumat, ob->col);
|
||||
}
|
||||
else {
|
||||
/* fixed function opengl materials */
|
||||
gpu_material_to_fixed(&GMS.matbuf[a], ma, gamma, ob);
|
||||
|
||||
blendmode = (ma->alpha == 1.0f)? GPU_BLEND_SOLID: GPU_BLEND_ALPHA;
|
||||
if(do_alpha_pass && GMS.alphapass)
|
||||
blendmode = (ma->alpha == 1.0f)? GPU_BLEND_SOLID: GPU_BLEND_ALPHA;
|
||||
if(do_alpha_pass && GMS.alphapass)
|
||||
GMS.matbuf[a].diff[3]= ma->alpha;
|
||||
else
|
||||
else
|
||||
GMS.matbuf[a].diff[3]= 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/* setting do_alpha_pass = 1 indicates this object needs to be
|
||||
* drawn in a second alpha pass for improved blending */
|
||||
if(do_alpha_pass) {
|
||||
GMS.blendmode[a]= blendmode;
|
||||
if(ELEM(blendmode, GPU_BLEND_ALPHA, GPU_BLEND_ADD) && !GMS.alphapass)
|
||||
*do_alpha_pass= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* MatCap */ {
|
||||
a = ob->totcol ? 1 : 0;
|
||||
|
||||
matcap_ma.mtex[0]->tex->ima= v3d->matcap_ima;
|
||||
|
||||
gpumat= GPU_material_from_blender(GMS.gscene, &matcap_ma);
|
||||
|
||||
GMS.gmatbuf[a]= &matcap_ma;
|
||||
blendmode= GPU_material_blend_mode(gpumat, ob->col);
|
||||
|
||||
/* setting do_alpha_pass = 1 indicates this object needs to be
|
||||
* drawn in a second alpha pass for improved blending */
|
||||
if(do_alpha_pass) {
|
||||
GMS.blendmode[a]= blendmode;
|
||||
|
||||
if(ELEM(blendmode, GPU_BLEND_ALPHA, GPU_BLEND_ADD) && !GMS.alphapass)
|
||||
*do_alpha_pass= 1;
|
||||
}
|
||||
|
@@ -1049,7 +1049,7 @@ static void do_material_tex(GPUShadeInput *shi)
|
||||
GPU_link(mat, "mtex_negate_texnormal", tnor, &tnor);
|
||||
|
||||
if(mtex->normapspace == MTEX_NSPACE_TANGENT)
|
||||
{
|
||||
{
|
||||
if(iFirstTimeNMap!=0)
|
||||
{
|
||||
// use unnormalized normal (this is how we bake it - closer to gamedev)
|
||||
@@ -1065,7 +1065,7 @@ static void do_material_tex(GPUShadeInput *shi)
|
||||
}
|
||||
else
|
||||
newnor = tnor;
|
||||
|
||||
|
||||
norfac = MIN2(fabsf(mtex->norfac), 1.0f);
|
||||
|
||||
if(norfac == 1.0f && !GPU_link_changed(stencil)) {
|
||||
@@ -1104,7 +1104,7 @@ static void do_material_tex(GPUShadeInput *shi)
|
||||
iBumpSpacePrev = 0;
|
||||
init_done = 1;
|
||||
}
|
||||
|
||||
|
||||
// find current bump space
|
||||
if( mtex->texflag & MTEX_BUMP_OBJECTSPACE )
|
||||
iBumpSpace = 1;
|
||||
@@ -1427,11 +1427,13 @@ void GPU_materials_free(void)
|
||||
Object *ob;
|
||||
Material *ma;
|
||||
extern Material defmaterial;
|
||||
extern Material matcap_ma;
|
||||
|
||||
for(ma=G.main->mat.first; ma; ma=ma->id.next)
|
||||
GPU_material_free(ma);
|
||||
|
||||
GPU_material_free(&defmaterial);
|
||||
GPU_material_free(&matcap_ma);
|
||||
|
||||
for(ob=G.main->object.first; ob; ob=ob->id.next)
|
||||
GPU_lamp_free(ob);
|
||||
|
@@ -79,9 +79,12 @@ typedef struct Brush {
|
||||
float alpha; /* opacity */
|
||||
|
||||
int sculpt_plane; /* the direction of movement for sculpt vertices */
|
||||
float sculpt_plane_range; /* adjust the range for determining the sculpt plane normal and center */
|
||||
|
||||
float plane_offset; /* offset for plane brushes (clay, flatten, fill, scrape) */
|
||||
|
||||
float frontface_angle;
|
||||
|
||||
char sculpt_tool; /* active sculpt tool */
|
||||
char vertexpaint_tool; /* active vertex/weight paint tool/blend mode */
|
||||
char imagepaint_tool; /* active image paint tool */
|
||||
@@ -91,14 +94,19 @@ typedef struct Brush {
|
||||
|
||||
float crease_pinch_factor;
|
||||
|
||||
float gravity_factor;
|
||||
|
||||
float plane_trim;
|
||||
float height; /* affectable height of brush (layer height for layer tool, i.e.) */
|
||||
|
||||
float layer_limit;
|
||||
|
||||
float texture_sample_bias;
|
||||
int texture_overlay_alpha;
|
||||
|
||||
float unprojected_radius;
|
||||
|
||||
float adaptive_space_factor;
|
||||
|
||||
float add_col[3];
|
||||
float sub_col[3];
|
||||
} Brush;
|
||||
@@ -132,30 +140,33 @@ typedef struct Brush {
|
||||
#define BRUSH_PLANE_TRIM (1<<26)
|
||||
#define BRUSH_FRONTFACE (1<<27)
|
||||
#define BRUSH_CUSTOM_ICON (1<<28)
|
||||
#define BRUSH_SYMMETRY_FEATHER (1<<29)
|
||||
#define BRUSH_LAYER (1<<30)
|
||||
|
||||
/* temporary flag which sets up autmatically for correct
|
||||
brush drawing when inverted modal operator is running */
|
||||
#define BRUSH_INVERTED (1<<29)
|
||||
|
||||
/* Brush.sculpt_tool */
|
||||
#define SCULPT_TOOL_DRAW 1
|
||||
#define SCULPT_TOOL_SMOOTH 2
|
||||
#define SCULPT_TOOL_PINCH 3
|
||||
#define SCULPT_TOOL_INFLATE 4
|
||||
#define SCULPT_TOOL_GRAB 5
|
||||
#define SCULPT_TOOL_LAYER 6
|
||||
#define SCULPT_TOOL_FLATTEN 7
|
||||
#define SCULPT_TOOL_CLAY 8
|
||||
#define SCULPT_TOOL_FILL 9
|
||||
#define SCULPT_TOOL_SCRAPE 10
|
||||
#define SCULPT_TOOL_NUDGE 11
|
||||
#define SCULPT_TOOL_THUMB 12
|
||||
#define SCULPT_TOOL_SNAKE_HOOK 13
|
||||
#define SCULPT_TOOL_ROTATE 14
|
||||
//#define SCULPT_TOOL_WAX 15 // XXX: reuse this slot later
|
||||
#define SCULPT_TOOL_CREASE 16
|
||||
#define SCULPT_TOOL_BLOB 17
|
||||
#define SCULPT_TOOL_CLAY_TUBES 18
|
||||
#define SCULPT_TOOL_DRAW 1
|
||||
#define SCULPT_TOOL_SMOOTH 2
|
||||
#define SCULPT_TOOL_PINCH 3
|
||||
#define SCULPT_TOOL_INFLATE 4
|
||||
#define SCULPT_TOOL_GRAB 5
|
||||
#define SCULPT_TOOL_LAYER 6
|
||||
#define SCULPT_TOOL_FLATTEN 7
|
||||
#define SCULPT_TOOL_CLAY 8
|
||||
#define SCULPT_TOOL_FILL 9
|
||||
#define SCULPT_TOOL_SCRAPE 10
|
||||
#define SCULPT_TOOL_NUDGE 11
|
||||
#define SCULPT_TOOL_THUMB 12
|
||||
#define SCULPT_TOOL_SNAKE_HOOK 13
|
||||
#define SCULPT_TOOL_ROTATE 14
|
||||
//#define SCULPT_TOOL_WAX 15 // XXX: reuse this slot later
|
||||
#define SCULPT_TOOL_CREASE 16
|
||||
#define SCULPT_TOOL_BLOB 17
|
||||
#define SCULPT_TOOL_CLAY_STRIPS 18
|
||||
#define SCULPT_TOOL_GRAVITY 19
|
||||
|
||||
/* ImagePaintSettings.tool */
|
||||
#define PAINT_TOOL_DRAW 0
|
||||
|
@@ -381,6 +381,7 @@ extern Object workob;
|
||||
#define OB_SOLID 3
|
||||
#define OB_SHADED 4
|
||||
#define OB_TEXTURE 5
|
||||
#define OB_MATCAP 6
|
||||
|
||||
/* dtx: flags, char! */
|
||||
#define OB_AXIS 2
|
||||
|
@@ -596,7 +596,7 @@ typedef struct Sculpt {
|
||||
|
||||
float special_rotation;
|
||||
|
||||
int pad;
|
||||
int sculpting;
|
||||
} Sculpt;
|
||||
|
||||
typedef struct VPaint {
|
||||
@@ -1157,7 +1157,7 @@ typedef enum SculptFlags {
|
||||
SCULPT_LOCK_X = (1<<3),
|
||||
SCULPT_LOCK_Y = (1<<4),
|
||||
SCULPT_LOCK_Z = (1<<5),
|
||||
SCULPT_SYMMETRY_FEATHER = (1<<6),
|
||||
// SCULPT_SYMMETRY_FEATHER = (1<<6),// flag made per-brush, reuse flag later
|
||||
SCULPT_USE_OPENMP = (1<<7),
|
||||
SCULPT_ONLY_DEFORM = (1<<8),
|
||||
} SculptFlags;
|
||||
|
@@ -489,6 +489,7 @@ typedef struct TexMapping {
|
||||
#define MTEX_MAP_MODE_FIXED 0
|
||||
#define MTEX_MAP_MODE_TILED 1
|
||||
#define MTEX_MAP_MODE_3D 2
|
||||
#define MTEX_MAP_MODE_WRAP 3
|
||||
|
||||
/* **************** EnvMap ********************* */
|
||||
|
||||
|
@@ -351,10 +351,12 @@ typedef struct UserDef {
|
||||
short gp_settings;
|
||||
short tb_leftmouse, tb_rightmouse;
|
||||
struct SolidLight light[3];
|
||||
short sculpt_paint_settings; /* user preferences for sculpt and paint */
|
||||
short tw_hotspot, tw_flag, tw_handlesize, tw_size;
|
||||
short textimeout,texcollectrate;
|
||||
short wmdrawmethod; /* removed wmpad */
|
||||
short dragthreshold;
|
||||
short pad0;
|
||||
int memcachelimit;
|
||||
int prefetchframes;
|
||||
short frameserverport;
|
||||
@@ -373,8 +375,8 @@ typedef struct UserDef {
|
||||
|
||||
short scrcastfps; /* frame rate for screencast to be played back */
|
||||
short scrcastwait; /* milliseconds between screencast snapshots */
|
||||
|
||||
short pad8, pad[3]; /* Value for Dual/Single Column UI */
|
||||
|
||||
int pad[3];
|
||||
|
||||
char versemaster[160];
|
||||
char verseuser[160];
|
||||
@@ -388,8 +390,7 @@ typedef struct UserDef {
|
||||
|
||||
struct ColorBand coba_weight; /* from texture.h */
|
||||
|
||||
float sculpt_paint_overlay_col[3];
|
||||
int pad3;
|
||||
float sculpt_paint_overlay_col[4];
|
||||
|
||||
char author[80]; /* author name for file formats supporting it */
|
||||
} UserDef;
|
||||
@@ -549,6 +550,11 @@ extern UserDef U; /* from blenkernel blender.c */
|
||||
#define GP_PAINT_DOSMOOTH (1<<0)
|
||||
#define GP_PAINT_DOSIMPLIFY (1<<1)
|
||||
|
||||
/* sculpt_paint_settings */
|
||||
#define SCULPT_PAINT_USE_UNIFIED_SIZE (1<<0)
|
||||
#define SCULPT_PAINT_USE_UNIFIED_ALPHA (1<<1)
|
||||
#define SCULPT_PAINT_UNIFIED_LOCK_BRUSH_SIZE (1<<2)
|
||||
|
||||
/* color picker types */
|
||||
#define USER_CP_CIRCLE 0
|
||||
#define USER_CP_SQUARE_SV 1
|
||||
|
@@ -163,7 +163,7 @@ typedef struct View3D {
|
||||
|
||||
/**
|
||||
* The drawing mode for the 3d display. Set to OB_WIRE, OB_SOLID,
|
||||
* OB_SHADED or OB_TEXTURE */
|
||||
* OB_SHADED, OB_TEXTURE, or OB_MATCAP */
|
||||
short drawtype;
|
||||
short ob_centre_cursor; /* optional bool for 3d cursor to define center */
|
||||
short scenelock, around;
|
||||
@@ -198,6 +198,7 @@ typedef struct View3D {
|
||||
/* XXX depricated? */
|
||||
struct bGPdata *gpd; /* Grease-Pencil Data (annotation layers) */
|
||||
|
||||
struct Image *matcap_ima;
|
||||
} View3D;
|
||||
|
||||
|
||||
@@ -233,7 +234,7 @@ typedef struct View3D {
|
||||
#define RV3D_VIEW_FRONT 1
|
||||
#define RV3D_VIEW_BACK 2
|
||||
#define RV3D_VIEW_LEFT 3
|
||||
#define RV3D_VIEW_RIGHT 4
|
||||
#define RV3D_VIEW_RIGHT 4
|
||||
#define RV3D_VIEW_TOP 5
|
||||
#define RV3D_VIEW_BOTTOM 6
|
||||
#define RV3D_VIEW_PERSPORTHO 7
|
||||
|
@@ -54,6 +54,9 @@ if env['WITH_BF_PYTHON']:
|
||||
if env['WITH_BF_COLLADA']:
|
||||
defs.append('WITH_COLLADA')
|
||||
|
||||
if env['WITH_BF_ONSURFACEBRUSH']:
|
||||
defs.append('WITH_ONSURFACEBRUSH')
|
||||
|
||||
if env['OURPLATFORM'] == 'linux2':
|
||||
cflags='-pthread'
|
||||
incs += ' ../../../extern/binreloc/include'
|
||||
|
@@ -50,11 +50,19 @@ static EnumPropertyItem prop_direction_items[]= {
|
||||
{BRUSH_DIR_IN, "SUBTRACT", 0, "Subtract", "Subtract effect of brush"},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
static EnumPropertyItem texture_angle_source_items[] = {
|
||||
{0, "USER", 0, "User", ""},
|
||||
{BRUSH_RAKE, "RAKE", 0, "Rake", ""},
|
||||
{BRUSH_RANDOM_ROTATION, "RANDOM", 0, "Random", ""},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
EnumPropertyItem brush_sculpt_tool_items[] = {
|
||||
{SCULPT_TOOL_BLOB, "BLOB", ICON_BRUSH_BLOB, "Blob", ""},
|
||||
{SCULPT_TOOL_CLAY, "CLAY", ICON_BRUSH_CLAY, "Clay", ""},
|
||||
{SCULPT_TOOL_CLAY_STRIPS, "CLAY_STRIPS", ICON_BRUSH_CLAY, "Clay Strips", ""},
|
||||
{SCULPT_TOOL_CREASE, "CREASE",ICON_BRUSH_CREASE, "Crease", ""},
|
||||
{SCULPT_TOOL_DRAW, "DRAW", ICON_BRUSH_SCULPT_DRAW, "Draw", ""},
|
||||
{SCULPT_TOOL_GRAVITY, "GRAVITY", ICON_BRUSH_SCULPT_DRAW, "Gravity", ""},
|
||||
{SCULPT_TOOL_FILL, "FILL", ICON_BRUSH_FILL, "Fill", ""},
|
||||
{SCULPT_TOOL_FLATTEN, "FLATTEN", ICON_BRUSH_FLATTEN, "Flatten", ""},
|
||||
{SCULPT_TOOL_GRAB, "GRAB", ICON_BRUSH_GRAB, "Grab", ""},
|
||||
@@ -121,7 +129,13 @@ static void rna_Brush_update(Main *bmain, Scene *scene, PointerRNA *ptr)
|
||||
{
|
||||
Brush *br= (Brush*)ptr->data;
|
||||
WM_main_add_notifier(NC_BRUSH|NA_EDITED, br);
|
||||
//WM_main_add_notifier(NC_SPACE|ND_SPACE_VIEW3D, NULL);
|
||||
}
|
||||
|
||||
static void rna_Brush_texture_overlay_update(Main *bmain, Scene *scene, PointerRNA *ptr)
|
||||
{
|
||||
Brush *br= (Brush*)ptr->data;
|
||||
WM_main_add_notifier(NC_BRUSH|NA_EDITED, br);
|
||||
WM_main_add_notifier(NC_SPACE|ND_SPACE_VIEW3D, NULL);
|
||||
}
|
||||
|
||||
static void rna_Brush_sculpt_tool_update(Main *bmain, Scene *scene, PointerRNA *ptr)
|
||||
@@ -318,6 +332,26 @@ static EnumPropertyItem *rna_Brush_direction_itemf(bContext *C, PointerRNA *ptr,
|
||||
}
|
||||
}
|
||||
|
||||
static EnumPropertyItem *rna_Brush_texture_angle_source_itemf(bContext *C, PointerRNA *ptr, int *free)
|
||||
{
|
||||
Brush *me= (Brush*)(ptr->data);
|
||||
|
||||
static EnumPropertyItem texture_angle_source_no_random_items[] = {
|
||||
{0, "USER", 0, "User", ""},
|
||||
{BRUSH_RAKE, "RAKE", 0, "Rake", ""},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
if (!(me->flag & BRUSH_ANCHORED) &&
|
||||
!ELEM4(me->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB, SCULPT_TOOL_ROTATE) &&
|
||||
ELEM(me->mtex.brush_map_mode, MTEX_MAP_MODE_FIXED, MTEX_MAP_MODE_WRAP))
|
||||
{
|
||||
return texture_angle_source_items;
|
||||
}
|
||||
else {
|
||||
return texture_angle_source_no_random_items;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void rna_def_brush_texture_slot(BlenderRNA *brna)
|
||||
@@ -326,6 +360,7 @@ static void rna_def_brush_texture_slot(BlenderRNA *brna)
|
||||
PropertyRNA *prop;
|
||||
|
||||
static EnumPropertyItem prop_map_mode_items[] = {
|
||||
{MTEX_MAP_MODE_WRAP, "WRAP", 0, "Wrap", ""},
|
||||
{MTEX_MAP_MODE_FIXED, "FIXED", 0, "Fixed", ""},
|
||||
{MTEX_MAP_MODE_TILED, "TILED", 0, "Tiled", ""},
|
||||
{MTEX_MAP_MODE_3D, "3D", 0, "3D", ""},
|
||||
@@ -372,17 +407,6 @@ static void rna_def_brush(BlenderRNA *brna)
|
||||
{BRUSH_AIRBRUSH, "AIRBRUSH", 0, "Airbrush", "Keep applying paint effect while holding mouse (spray)"},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
static EnumPropertyItem texture_angle_source_items[] = {
|
||||
{0, "USER", 0, "User", "Rotate the brush texture by given angle"},
|
||||
{BRUSH_RAKE, "RAKE", 0, "Rake", "Rotate the brush texture to match the stroke direction"},
|
||||
{BRUSH_RANDOM_ROTATION, "RANDOM", 0, "Random", "Rotate the brush texture at random"},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
static EnumPropertyItem texture_angle_source_no_random_items[] = {
|
||||
{0, "USER", 0, "User", "Rotate the brush texture by given angle"},
|
||||
{BRUSH_RAKE, "RAKE", 0, "Rake", "Rotate the brush texture to match the stroke direction"},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
static EnumPropertyItem brush_sculpt_plane_items[] = {
|
||||
{SCULPT_DISP_DIR_AREA, "AREA", 0, "Area Plane", ""},
|
||||
{SCULPT_DISP_DIR_VIEW, "VIEW", 0, "View Plane", ""},
|
||||
@@ -434,12 +458,7 @@ static void rna_def_brush(BlenderRNA *brna)
|
||||
prop= RNA_def_property(srna, "texture_angle_source_random", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
|
||||
RNA_def_property_enum_items(prop, texture_angle_source_items);
|
||||
RNA_def_property_ui_text(prop, "Texture Angle Source", "");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||
|
||||
prop= RNA_def_property(srna, "texture_angle_source_no_random", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
|
||||
RNA_def_property_enum_items(prop, texture_angle_source_no_random_items);
|
||||
RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_Brush_texture_angle_source_itemf");
|
||||
RNA_def_property_ui_text(prop, "Texture Angle Source", "");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||
|
||||
@@ -473,7 +492,7 @@ static void rna_def_brush(BlenderRNA *brna)
|
||||
RNA_def_property_int_sdna(prop, NULL, "spacing");
|
||||
RNA_def_property_range(prop, 1, 1000);
|
||||
RNA_def_property_ui_range(prop, 1, 500, 5, 0);
|
||||
RNA_def_property_ui_text(prop, "Spacing", "Spacing between brush daubs as a percentage of brush diameter");
|
||||
RNA_def_property_ui_text(prop, "Spacing", "Spacing between brush dabs as a percentage of brush diameter");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||
|
||||
prop= RNA_def_property(srna, "smooth_stroke_radius", PROP_INT, PROP_DISTANCE);
|
||||
@@ -523,13 +542,6 @@ static void rna_def_brush(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Plane Trim", "If a vertex is further from offset plane than this then it is not affected");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||
|
||||
prop= RNA_def_property(srna, "height", PROP_FLOAT, PROP_DISTANCE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "height");
|
||||
RNA_def_property_float_default(prop, 0.5f);
|
||||
RNA_def_property_range(prop, 0, 1.0f);
|
||||
RNA_def_property_ui_text(prop, "Brush Height", "Affectable height of brush (layer height for layer tool, i.e.)");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||
|
||||
prop= RNA_def_property(srna, "texture_sample_bias", PROP_FLOAT, PROP_DISTANCE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "texture_sample_bias");
|
||||
RNA_def_property_float_default(prop, 0);
|
||||
@@ -559,6 +571,37 @@ static void rna_def_brush(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Autosmooth", "Amount of smoothing to automatically apply to each stroke");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||
|
||||
prop= RNA_def_property(srna, "gravity_factor", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, NULL, "gravity_factor");
|
||||
RNA_def_property_float_default(prop, 0);
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.001, 0.001);
|
||||
RNA_def_property_ui_text(prop, "Gravity", "Amount of gravity to apply to each stroke");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||
|
||||
prop= RNA_def_property(srna, "sculpt_plane_range", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, NULL, "sculpt_plane_range");
|
||||
RNA_def_property_range(prop, 0, 10);
|
||||
RNA_def_property_float_default(prop, 1);
|
||||
RNA_def_property_ui_range(prop, 0, 2, 0, 0);
|
||||
RNA_def_property_ui_text(prop, "Sculpt Plane Range", "Determines the range, in brush radii, to sample vertexes when determining the area sculpt plane");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||
|
||||
prop= RNA_def_property(srna, "frontface_angle", PROP_FLOAT, PROP_ANGLE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "frontface_angle");
|
||||
RNA_def_property_range(prop, 0, 90);
|
||||
RNA_def_property_float_default(prop, 80);
|
||||
RNA_def_property_ui_text(prop, "Front-Face Angle", "Angle where effect of brush starts to be reduced to prevent it affecting back-faces");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||
|
||||
prop= RNA_def_property(srna, "layer_limit", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, NULL, "layer_limit");
|
||||
RNA_def_property_float_default(prop, 0);
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.001, 0.001);
|
||||
RNA_def_property_ui_text(prop, "Layer Distance", "Limit to how far a vertex can travel in a single stroke as a fraction of brush radius");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||
|
||||
/* flag */
|
||||
prop= RNA_def_property(srna, "use_airbrush", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_AIRBRUSH);
|
||||
@@ -633,6 +676,16 @@ static void rna_def_brush(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Use Front-Face", "Brush only affects vertexes that face the viewer");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||
|
||||
prop= RNA_def_property(srna, "use_symmetry_feather", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_SYMMETRY_FEATHER);
|
||||
RNA_def_property_ui_text(prop, "Symmetry Feathering", "Reduce the strength of the brush where it overlaps symmetrical dabs");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||
|
||||
prop= RNA_def_property(srna, "use_layer", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_LAYER);
|
||||
RNA_def_property_ui_text(prop, "Use Layer", "Sets a limit on how far a vertex can travel during a single stroke");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||
|
||||
prop= RNA_def_property(srna, "use_anchor", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_ANCHORED);
|
||||
RNA_def_property_ui_text(prop, "Anchored", "Keep the brush anchored to the initial location");
|
||||
@@ -663,10 +716,9 @@ static void rna_def_brush(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Use Automatic Strength Adjustment", "Automatically adjusts strength to give consistent results for different spacings");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||
|
||||
/* adaptive space is not implemented yet */
|
||||
prop= RNA_def_property(srna, "use_adaptive_space", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_ADAPTIVE_SPACE);
|
||||
RNA_def_property_ui_text(prop, "Adaptive Spacing", "Space daubs according to surface orientation instead of screen space");
|
||||
RNA_def_property_ui_text(prop, "Adaptive Spacing", "Space dabs according to surface orientation instead of screen space");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||
|
||||
prop= RNA_def_property(srna, "use_locked_size", PROP_BOOLEAN, PROP_NONE);
|
||||
@@ -678,7 +730,7 @@ static void rna_def_brush(BlenderRNA *brna)
|
||||
prop= RNA_def_property(srna, "use_texture_overlay", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_TEXTURE_OVERLAY);
|
||||
RNA_def_property_ui_text(prop, "Use Texture Overlay", "Show texture in viewport");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_texture_overlay_update");
|
||||
|
||||
prop= RNA_def_property(srna, "use_edge_to_edge", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_EDGE_TO_EDGE);
|
||||
@@ -734,13 +786,13 @@ static void rna_def_brush(BlenderRNA *brna)
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "mtex.tex");
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Texture", "");
|
||||
RNA_def_property_update(prop, NC_TEXTURE, "rna_Brush_update");
|
||||
RNA_def_property_update(prop, NC_TEXTURE, "rna_Brush_texture_overlay_update");
|
||||
|
||||
prop= RNA_def_property(srna, "texture_overlay_alpha", PROP_INT, PROP_PERCENTAGE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "texture_overlay_alpha");
|
||||
RNA_def_property_range(prop, 1, 100);
|
||||
RNA_def_property_ui_text(prop, "Texture Overlay Alpha", "");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_texture_overlay_update");
|
||||
|
||||
prop= RNA_def_property(srna, "cursor_color_add", PROP_FLOAT, PROP_COLOR);
|
||||
RNA_def_property_float_sdna(prop, NULL, "add_col");
|
||||
|
@@ -1720,6 +1720,7 @@ static void rna_def_object(BlenderRNA *brna)
|
||||
{OB_SOLID, "SOLID", 0, "Solid", "Draw the object as a solid (If solid drawing is enabled in the viewport)"},
|
||||
// disabled {OB_SHADED, "SHADED", 0, "Shaded", ""},
|
||||
{OB_TEXTURE, "TEXTURED", 0, "Textured", "Draw the object with textures (If textures are enabled in the viewport)"},
|
||||
{OB_MATCAP, "MATCAP", 0, "MatCap", ""},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
static EnumPropertyItem boundtype_items[] = {
|
||||
|
@@ -29,6 +29,8 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include "RNA_define.h"
|
||||
|
||||
#include "rna_internal.h"
|
||||
@@ -194,6 +196,20 @@ static void rna_Sculpt_update(Main *bmain, Scene *scene, PointerRNA *ptr)
|
||||
}
|
||||
}
|
||||
|
||||
static int rna_Paint_is_on_surface_brush_capable(Paint* unused)
|
||||
{
|
||||
#ifdef WITH_ONSURFACEBRUSH
|
||||
int bits;
|
||||
|
||||
(void)unused;
|
||||
|
||||
glGetIntegerv(GL_STENCIL_BITS, &bits);
|
||||
return bits > 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void rna_def_paint(BlenderRNA *brna)
|
||||
@@ -201,6 +217,9 @@ static void rna_def_paint(BlenderRNA *brna)
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
FunctionRNA *func;
|
||||
PropertyRNA *parm;
|
||||
|
||||
srna= RNA_def_struct(brna, "Paint", NULL);
|
||||
RNA_def_struct_ui_text(srna, "Paint", "");
|
||||
|
||||
@@ -222,6 +241,12 @@ static void rna_def_paint(BlenderRNA *brna)
|
||||
prop= RNA_def_property(srna, "show_low_resolution", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", PAINT_FAST_NAVIGATE);
|
||||
RNA_def_property_ui_text(prop, "Fast Navigate", "For multires, show low resolution while navigating the view");
|
||||
|
||||
/* functions */
|
||||
func= RNA_def_function(srna, "is_on_surface_brush_capable", "rna_Paint_is_on_surface_brush_capable");
|
||||
RNA_def_function_ui_description(func, "Returns true if on-surface brush is configured and all capabilities are present.");
|
||||
parm= RNA_def_boolean(func, "ret", 0, "", "");
|
||||
RNA_def_function_return(func, parm);
|
||||
}
|
||||
|
||||
static void rna_def_sculpt(BlenderRNA *brna)
|
||||
@@ -263,10 +288,6 @@ static void rna_def_sculpt(BlenderRNA *brna)
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", SCULPT_LOCK_Z);
|
||||
RNA_def_property_ui_text(prop, "Lock Z", "Disallow changes to the Z axis of vertices");
|
||||
|
||||
prop= RNA_def_property(srna, "use_symmetry_feather", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", SCULPT_SYMMETRY_FEATHER);
|
||||
RNA_def_property_ui_text(prop, "Symmetry Feathering", "Reduce the strength of the brush where it overlaps symmetrical daubs");
|
||||
|
||||
prop= RNA_def_property(srna, "use_threaded", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", SCULPT_USE_OPENMP);
|
||||
RNA_def_property_ui_text(prop, "Use OpenMP", "Take advantage of multiple CPU cores to improve sculpting performance");
|
||||
@@ -289,7 +310,7 @@ static void rna_def_vertex_paint(BlenderRNA *brna)
|
||||
prop= RNA_def_property(srna, "use_all_faces", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", VP_AREA);
|
||||
RNA_def_property_ui_text(prop, "All Faces", "Paint on all faces inside brush");
|
||||
|
||||
|
||||
prop= RNA_def_property(srna, "use_normal", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", VP_NORMALS);
|
||||
RNA_def_property_ui_text(prop, "Normals", "Applies the vertex normal before painting");
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id$
|
||||
* $Id: rna_sequencer_api.c 35238 2011-02-27 20:20:01Z jesterking $
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
|
@@ -44,6 +44,9 @@
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
#include "DNA_view3d_types.h"
|
||||
#include "DNA_material_types.h"
|
||||
|
||||
#include "GPU_material.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
@@ -100,6 +103,7 @@ EnumPropertyItem viewport_shade_items[] = {
|
||||
{OB_SOLID, "SOLID", ICON_SOLID, "Solid", "Display the object solid, lit with default OpenGL lights"},
|
||||
//{OB_SHADED, "SHADED", ICON_SMOOTH, "Shaded", "Display the object solid, with preview shading interpolated at vertices"},
|
||||
{OB_TEXTURE, "TEXTURED", ICON_POTATO, "Textured", "Display the object solid, with face-assigned textures"},
|
||||
{OB_MATCAP, "MATCAP", ICON_SMOOTH, "MatCap", "Display the object solid, with MatCap texture"},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
#ifdef RNA_RUNTIME
|
||||
@@ -834,6 +838,14 @@ static float rna_BackgroundImage_opacity_get(PointerRNA *ptr)
|
||||
return 1.0f-bgpic->blend;
|
||||
}
|
||||
|
||||
static void rna_View3D_matcap_image_changed(Main *bmain, Scene *scene, PointerRNA *ptr)
|
||||
{
|
||||
extern Material matcap_ma;
|
||||
|
||||
if(matcap_ma.gpumaterial.first)
|
||||
GPU_material_free(&matcap_ma);
|
||||
}
|
||||
|
||||
static void rna_BackgroundImage_opacity_set(PointerRNA *ptr, float value)
|
||||
{
|
||||
BGpic *bgpic= (BGpic *)ptr->data;
|
||||
@@ -1392,6 +1404,13 @@ static void rna_def_space_view3d(BlenderRNA *brna)
|
||||
RNA_def_property_pointer_funcs(prop, "rna_SpaceView3D_region_quadview_get", NULL, NULL, NULL);
|
||||
RNA_def_property_ui_text(prop, "Quad View Region", "3D region that defines the quad view settings");
|
||||
|
||||
prop= RNA_def_property(srna, "matcap_image", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "matcap_ima");
|
||||
RNA_def_property_struct_type(prop, "Image");
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "MatCap Image", "");
|
||||
RNA_def_property_update(prop, NC_SPACE|ND_SPACE_VIEW3D, "rna_View3D_matcap_image_changed");
|
||||
|
||||
/* region */
|
||||
|
||||
srna= RNA_def_struct(brna, "RegionView3D", NULL);
|
||||
|
@@ -191,6 +191,7 @@ void rna_TextureSlot_update(Main *bmain, Scene *scene, PointerRNA *ptr)
|
||||
break;
|
||||
case ID_BR:
|
||||
WM_main_add_notifier(NC_BRUSH, id);
|
||||
WM_main_add_notifier(NC_SPACE|ND_SPACE_VIEW3D, NULL);
|
||||
break;
|
||||
case ID_PA:
|
||||
{
|
||||
|
@@ -1,321 +0,0 @@
|
||||
#! /usr/bin/env python3.1
|
||||
|
||||
"""
|
||||
This script is used to help cleaning RNA api.
|
||||
|
||||
Typical line in the input file (elements in [] are optional).
|
||||
|
||||
[comment *] ToolSettings.snap_align_rotation -> use_snap_align_rotation: boolean [Align rotation with the snapping target]
|
||||
|
||||
Geterate output format from blender run this:
|
||||
./blender.bin --background --python ./release/scripts/modules/rna_info.py 2> source/blender/makesrna/rna_cleanup/out.txt
|
||||
"""
|
||||
|
||||
|
||||
def font_bold(mystring):
|
||||
"""
|
||||
Formats the string as bold, to be used in printouts.
|
||||
"""
|
||||
font_bold = "\033[1m"
|
||||
font_reset = "\033[0;0m"
|
||||
return font_bold + mystring + font_reset
|
||||
|
||||
|
||||
def usage():
|
||||
"""
|
||||
Prints script usage.
|
||||
"""
|
||||
import sys
|
||||
scriptname = sys.argv[0]
|
||||
sort_choices_string = '|'.join(sort_choices)
|
||||
message = "\nUSAGE:"
|
||||
message += "\n%s input-file (.txt|.py) order-priority (%s).\n" % (font_bold(scriptname), sort_choices_string)
|
||||
message += "%s -h for help\n" % font_bold(scriptname)
|
||||
print(message)
|
||||
exit()
|
||||
|
||||
|
||||
def help():
|
||||
"""
|
||||
Prints script' help.
|
||||
"""
|
||||
message = '\nHELP:'
|
||||
message += '\nRun this script to re-format the edits you make in the input file.\n'
|
||||
message += 'Do quick modification to important fields like \'to\' and don\'t care about fields like \'changed\' or \'description\' and save.\n'
|
||||
message += 'The script outputs 3 files:\n'
|
||||
message += ' 1) *_clean.txt: is formatted same as the .txt input, can be edited by user.\n'
|
||||
message += ' 2) *_clean.py: is formatted same as the .py input, can be edited by user.\n'
|
||||
message += ' 3) rna_api.py is not formatted for readability and go under complete check. Can be used for rna cleanup.\n'
|
||||
print(message)
|
||||
usage()
|
||||
|
||||
|
||||
def check_commandline():
|
||||
"""
|
||||
Takes parameters from the commandline.
|
||||
"""
|
||||
import sys
|
||||
# Usage
|
||||
if len(sys.argv)==1 or len(sys.argv)>3:
|
||||
usage()
|
||||
if sys.argv[1] == '-h':
|
||||
help()
|
||||
elif not (sys.argv[1].endswith(".txt") or sys.argv[1].endswith(".py")):
|
||||
print ('\nBad input file extension... exiting.')
|
||||
usage()
|
||||
else:
|
||||
inputfile = sys.argv[1]
|
||||
if len(sys.argv) == 2:
|
||||
sort_priority = default_sort_choice
|
||||
print ('\nSecond parameter missing: choosing to order by %s.' % font_bold(sort_priority))
|
||||
elif len(sys.argv)==3:
|
||||
sort_priority = sys.argv[2]
|
||||
if sort_priority not in sort_choices:
|
||||
print('\nWrong sort_priority... exiting.')
|
||||
usage()
|
||||
return (inputfile, sort_priority)
|
||||
|
||||
|
||||
def check_prefix(prop, btype):
|
||||
# reminder: props=[comment, changed, bclass, bfrom, bto, kwcheck, btype, description]
|
||||
if btype == "boolean":
|
||||
if '_' in prop:
|
||||
prefix = prop.split('_')[0]
|
||||
if prefix not in kw_prefixes:
|
||||
return 'BAD-PREFIX: ' + prefix
|
||||
else:
|
||||
return prefix + '_'
|
||||
elif prop in kw:
|
||||
return 'SPECIAL-KEYWORD: ' + prop
|
||||
else:
|
||||
return 'BAD-KEYWORD: ' + prop
|
||||
else:
|
||||
return ""
|
||||
|
||||
|
||||
def check_if_changed(a,b):
|
||||
if a != b: return 'changed'
|
||||
else: return 'same'
|
||||
|
||||
|
||||
def get_props_from_txt(input_filename):
|
||||
"""
|
||||
If the file is *.txt, the script assumes it is formatted as outlined in this script docstring
|
||||
"""
|
||||
|
||||
file=open(input_filename,'r')
|
||||
file_lines=file.readlines()
|
||||
file.close()
|
||||
|
||||
props_list=[]
|
||||
props_length_max=[0,0,0,0,0,0,0,0]
|
||||
|
||||
done_text = "+"
|
||||
done = 0
|
||||
tot = 0
|
||||
|
||||
for iii, line in enumerate(file_lines):
|
||||
|
||||
# debug
|
||||
#print(line)
|
||||
line_strip = line.strip()
|
||||
# empty line or comment
|
||||
if not line_strip:
|
||||
continue
|
||||
|
||||
if line_strip == "EOF":
|
||||
break
|
||||
|
||||
if line.startswith("#"):
|
||||
line = line[1:]
|
||||
|
||||
# class
|
||||
[bclass, tail] = [x.strip() for x in line.split('.', 1)]
|
||||
|
||||
# comment
|
||||
if '*' in bclass:
|
||||
[comment, bclass] = [x.strip() for x in bclass.split('*', 1)]
|
||||
else:
|
||||
comment= ''
|
||||
|
||||
# skipping the header if we have one.
|
||||
# the header is assumed to be "NOTE * CLASS.FROM -> TO: TYPE DESCRIPTION"
|
||||
if comment == 'NOTE' and bclass == 'CLASS':
|
||||
continue
|
||||
|
||||
# from
|
||||
[bfrom, tail] = [x.strip() for x in tail.split('->', 1)]
|
||||
|
||||
# to
|
||||
[bto, tail] = [x.strip() for x in tail.split(':', 1)]
|
||||
|
||||
# type, description
|
||||
try:
|
||||
[btype, description] = tail.split(None, 1)
|
||||
# make life easy and strip quotes
|
||||
description = description.replace("'", "").replace('"', "").replace("\\", "").strip()
|
||||
except ValueError:
|
||||
[btype, description] = [tail,'NO DESCRIPTION']
|
||||
|
||||
# keyword-check
|
||||
kwcheck = check_prefix(bto, btype)
|
||||
|
||||
# changed
|
||||
changed = check_if_changed(bfrom, bto)
|
||||
|
||||
# lists formatting
|
||||
props=[comment, changed, bclass, bfrom, bto, kwcheck, btype, description]
|
||||
props_list.append(props)
|
||||
props_length_max=list(map(max,zip(props_length_max,list(map(len,props)))))
|
||||
|
||||
if done_text in comment:
|
||||
done += 1
|
||||
tot += 1
|
||||
|
||||
print("Total done %.2f" % (done / tot * 100.0) )
|
||||
|
||||
return (props_list,props_length_max)
|
||||
|
||||
|
||||
def get_props_from_py(input_filename):
|
||||
"""
|
||||
If the file is *.py, the script assumes it contains a python list (as "rna_api=[...]")
|
||||
This means that this script executes the text in the py file with an exec(text).
|
||||
"""
|
||||
# adds the list "rna_api" to this function's scope
|
||||
rna_api = __import__(input_filename[:-3]).rna_api
|
||||
|
||||
props_length_max = [0 for i in rna_api[0]] # this way if the vector will take more elements we are safe
|
||||
for index,props in enumerate(rna_api):
|
||||
comment, changed, bclass, bfrom, bto, kwcheck, btype, description = props
|
||||
kwcheck = check_prefix(bto, btype) # keyword-check
|
||||
changed = check_if_changed(bfrom, bto) # changed?
|
||||
description = repr(description)
|
||||
description = description.replace("'", "").replace('"', "").replace("\\", "").strip()
|
||||
rna_api[index] = [comment, changed, bclass, bfrom, bto, kwcheck, btype, description]
|
||||
props_length = list(map(len,props)) # lengths
|
||||
props_length_max = list(map(max,zip(props_length_max,props_length))) # max lengths
|
||||
return (rna_api,props_length_max)
|
||||
|
||||
|
||||
def get_props(input_filename):
|
||||
if input_filename.endswith(".txt"):
|
||||
props_list,props_length_max = get_props_from_txt(input_filename)
|
||||
elif input_filename.endswith(".py"):
|
||||
props_list,props_length_max = get_props_from_py(input_filename)
|
||||
return (props_list,props_length_max)
|
||||
|
||||
|
||||
def sort(props_list, sort_priority):
|
||||
"""
|
||||
reminder
|
||||
props=[comment, changed, bclass, bfrom, bto, kwcheck, btype, description]
|
||||
"""
|
||||
|
||||
# order based on the i-th element in lists
|
||||
if sort_priority == "class.to":
|
||||
props_list = sorted(props_list, key=lambda p: (p[2], p[4]))
|
||||
else:
|
||||
i = sort_choices.index(sort_priority)
|
||||
if i == 0:
|
||||
props_list = sorted(props_list, key=lambda p: p[i], reverse=True)
|
||||
else:
|
||||
props_list = sorted(props_list, key=lambda p: p[i])
|
||||
|
||||
print ('\nSorted by %s.' % font_bold(sort_priority))
|
||||
return props_list
|
||||
|
||||
|
||||
def file_basename(input_filename):
|
||||
# if needed will use os.path
|
||||
if input_filename.endswith(".txt"):
|
||||
if input_filename.endswith("_work.txt"):
|
||||
base_filename = input_filename.replace("_work.txt", "")
|
||||
else:
|
||||
base_filename = input_filename.replace(".txt", "")
|
||||
elif input_filename.endswith(".py"):
|
||||
if input_filename.endswith("_work.py"):
|
||||
base_filename = input_filename.replace("_work.py", "")
|
||||
else:
|
||||
base_filename = input_filename.replace(".py", "")
|
||||
|
||||
return base_filename
|
||||
|
||||
|
||||
def write_files(basename, props_list, props_length_max):
|
||||
"""
|
||||
Writes in 3 files:
|
||||
* output_filename_work.txt: formatted as txt input file (can be edited)
|
||||
* output_filename_work.py: formatted for readability (can be edited)
|
||||
* rna_api.py: unformatted, just as final output
|
||||
"""
|
||||
|
||||
f_rna = open("rna_api.py",'w')
|
||||
f_txt = open(basename + '_work.txt','w')
|
||||
f_py = open(basename + '_work.py','w')
|
||||
|
||||
# reminder: props=[comment, changed, bclass, bfrom, bto, kwcheck, btype, description]
|
||||
# [comment *] ToolSettings.snap_align_rotation -> use_snap_align_rotation: boolean [Align rotation with the snapping target]
|
||||
rna = py = txt = ''
|
||||
props_list = [['NOTE', 'CHANGED', 'CLASS', 'FROM', 'TO', 'KEYWORD-CHECK', 'TYPE', 'DESCRIPTION']] + props_list
|
||||
for props in props_list:
|
||||
#txt
|
||||
|
||||
# quick way we can tell if it changed
|
||||
if props[3] == props[4]: txt += "#"
|
||||
else: txt += " "
|
||||
|
||||
if props[0] != '': txt += '%s * ' % props[0] # comment
|
||||
txt += '%s.%s -> %s: %s "%s"\n' % tuple(props[2:5] + props[6:]) # skipping keyword-check
|
||||
# rna_api
|
||||
if props[0] == 'NOTE': indent = '# '
|
||||
else: indent = ' '
|
||||
rna += indent + '("%s", "%s", "%s", "%s", "%s"),\n' % tuple(props[2:5] + props[6:]) # description is already string formatted
|
||||
# py
|
||||
blanks = [' '* (x[0]-x[1]) for x in zip(props_length_max,list(map(len,props)))]
|
||||
props = [('"%s"%s' if props[-1] != x[0] else "%s%s") % (x[0],x[1]) for x in zip(props,blanks)]
|
||||
py += indent + '(%s, %s, %s, %s, %s, %s, %s, "%s"),\n' % tuple(props)
|
||||
|
||||
f_txt.write(txt)
|
||||
f_py.write("rna_api = [\n%s]\n" % py)
|
||||
f_rna.write("rna_api = [\n%s]\n" % rna)
|
||||
|
||||
# write useful py script, wont hurt
|
||||
f_py.write("\n'''\n")
|
||||
f_py.write("for p_note, p_changed, p_class, p_from, p_to, p_check, p_type, p_desc in rna_api:\n")
|
||||
f_py.write(" print(p_to)\n")
|
||||
f_py.write("\n'''\n")
|
||||
|
||||
f_txt.close()
|
||||
f_py.close()
|
||||
f_rna.close()
|
||||
|
||||
print ('\nSaved %s, %s and %s.\n' % (font_bold(f_txt.name), font_bold(f_py.name), font_bold(f_rna.name) ) )
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
global sort_choices, default_sort_choice
|
||||
global kw_prefixes, kw
|
||||
|
||||
sort_choices = ['note','changed','class','from','to','kw', 'class.to']
|
||||
default_sort_choice = sort_choices[-1]
|
||||
kw_prefixes = [ 'active','apply','bl','exclude','has','invert','is','lock', \
|
||||
'pressed','show','show_only','use','use_only','layers','states', 'select']
|
||||
kw = ['active','hide','invert','select','layers','mute','states','use','lock']
|
||||
|
||||
input_filename, sort_priority = check_commandline()
|
||||
props_list,props_length_max = get_props(input_filename)
|
||||
props_list = sort(props_list,sort_priority)
|
||||
|
||||
output_basename = file_basename(input_filename)
|
||||
write_files(output_basename, props_list,props_length_max)
|
||||
|
||||
|
||||
if __name__=='__main__':
|
||||
import sys
|
||||
if not sys.version.startswith("3"):
|
||||
print("Incorrect python version, use python 3!")
|
||||
else:
|
||||
main()
|
||||
|
@@ -1,61 +0,0 @@
|
||||
#! /usr/bin/env python3.1
|
||||
|
||||
import sys
|
||||
|
||||
'''
|
||||
Example usage:
|
||||
python3 rna_cleaner_merge.py out_work.py rna_booleans_work.py
|
||||
'''
|
||||
def main():
|
||||
|
||||
def work_line_id(line):
|
||||
return line[2].split("|")[-1], line[3] # class/from
|
||||
|
||||
|
||||
if not (sys.argv[-1].endswith(".py") and sys.argv[-2].endswith(".py")):
|
||||
print("Only accepts 2 py files as arguments.")
|
||||
|
||||
sys.path.insert(0, ".")
|
||||
|
||||
mod_from = __import__(sys.argv[-1][:-3])
|
||||
mod_to = __import__(sys.argv[-2][:-3])
|
||||
|
||||
mod_to_dict = dict([(work_line_id(line), line) for line in mod_to.rna_api])
|
||||
mod_from_dict = dict([(work_line_id(line), line) for line in mod_from.rna_api])
|
||||
|
||||
rna_api_new = []
|
||||
|
||||
for key, val_orig in mod_to_dict.items():
|
||||
try:
|
||||
val_new = mod_from_dict.pop(key)
|
||||
except:
|
||||
# print("not found", key)
|
||||
val_new = val_orig
|
||||
|
||||
# always take the class from the base
|
||||
val = list(val_orig)
|
||||
val[0] = val_new[0] # comment
|
||||
val[4] = val_new[4] # -> to
|
||||
val = tuple(val)
|
||||
rna_api_new.append(val)
|
||||
|
||||
def write_work_file(file_path, rna_api):
|
||||
rna_api = list(rna_api)
|
||||
rna_api.sort(key=work_line_id)
|
||||
file_out = open(file_path, "w")
|
||||
file_out.write("rna_api = [\n")
|
||||
for line in rna_api:
|
||||
file_out.write(" %s,\n" % (repr(line)))
|
||||
file_out.write("]\n")
|
||||
file_out.close()
|
||||
|
||||
file_path = sys.argv[-2][:-3] + "_merged.py"
|
||||
write_work_file(file_path, rna_api_new)
|
||||
|
||||
if mod_from_dict:
|
||||
file_path = sys.argv[-2][:-3] + "_lost.py"
|
||||
write_work_file(file_path, list(mod_from_dict.values()))
|
||||
print("Warning '%s' contains lost %d items from module %s.py" % (file_path, len(mod_from_dict), mod_from.__name__))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@@ -1 +0,0 @@
|
||||
# See svn history for example formatting for this file, currently this isnt in use.
|
@@ -1,13 +0,0 @@
|
||||
cd ../../../../
|
||||
./blender.bin --background --python ./release/scripts/modules/rna_info.py 2> source/blender/makesrna/rna_cleanup/out.txt
|
||||
cd ./source/blender/makesrna/rna_cleanup/
|
||||
./rna_cleaner.py out.txt
|
||||
./rna_cleaner.py rna_properties.txt
|
||||
./rna_cleaner_merge.py out_work.py rna_properties_work.py
|
||||
./rna_cleaner.py out_work_merged.py
|
||||
./rna_cleaner.py out_work_lost.py
|
||||
mv out_work_merged_work.txt rna_properties.txt # overwrite
|
||||
mv out_work_lost_work.txt rna_properties_lost.txt
|
||||
cat rna_properties.txt | grep -v "^#" > rna_properties_edits.txt
|
||||
./rna_cleaner.py rna_properties.txt
|
||||
echo "Updated: rna_properties.txt rna_properties_edits.txt rna_properties_lost.txt "
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id$
|
||||
* $Id: mathutils_geometry.c 36871 2011-05-24 16:05:51Z campbellbarton $
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id$
|
||||
* $Id: mathutils_geometry.h 35236 2011-02-27 20:10:08Z jesterking $
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
|
@@ -38,4 +38,7 @@ if env['WITH_GHOST_COCOA']:
|
||||
if env['BF_BUILDINFO']:
|
||||
defs.append('NAN_BUILDINFO')
|
||||
|
||||
if env['WITH_BF_ONSURFACEBRUSH']:
|
||||
defs.append('WITH_ONSURFACEBRUSH')
|
||||
|
||||
env.BlenderLib ( 'bf_windowmanager', sources, Split(incs), defines=defs, libtype=['core'], priority=[5] )
|
||||
|
@@ -340,6 +340,20 @@ typedef struct wmDrawTriple {
|
||||
int x[MAX_N_TEX], y[MAX_N_TEX];
|
||||
int nx, ny;
|
||||
GLenum target;
|
||||
|
||||
#ifdef WITH_ONSURFACEBRUSH
|
||||
char* depth;
|
||||
GLenum depth_type;
|
||||
|
||||
GLuint depth_bind[MAX_N_TEX*MAX_N_TEX];
|
||||
int depth_x[MAX_N_TEX], depth_y[MAX_N_TEX];
|
||||
int depth_nx, depth_ny;
|
||||
GLenum depth_target;
|
||||
|
||||
GLenum depth_vertex_shader;
|
||||
GLenum depth_fragment_shader;
|
||||
GLenum depth_program;
|
||||
#endif
|
||||
} wmDrawTriple;
|
||||
|
||||
static int is_pow2(int n)
|
||||
@@ -408,6 +422,18 @@ static void wm_draw_triple_free(wmWindow *win)
|
||||
wmDrawTriple *triple= win->drawdata;
|
||||
|
||||
glDeleteTextures(triple->nx*triple->ny, triple->bind);
|
||||
#ifdef WITH_ONSURFACEBRUSH
|
||||
glDeleteTextures(triple->depth_nx*triple->depth_ny, triple->depth_bind);
|
||||
|
||||
if (GLEW_ARB_shader_objects) {
|
||||
glDeleteObjectARB(triple->depth_vertex_shader);
|
||||
glDeleteObjectARB(triple->depth_fragment_shader);
|
||||
glDeleteObjectARB(triple->depth_program);
|
||||
}
|
||||
|
||||
if (triple->depth)
|
||||
MEM_freeN(triple->depth);
|
||||
#endif
|
||||
|
||||
MEM_freeN(triple);
|
||||
|
||||
@@ -558,6 +584,419 @@ static void wm_triple_copy_textures(wmWindow *win, wmDrawTriple *triple)
|
||||
glBindTexture(triple->target, 0);
|
||||
}
|
||||
|
||||
#ifdef WITH_ONSURFACEBRUSH
|
||||
static void get_shading_language_version(int* major, int* minor)
|
||||
{
|
||||
const char* version;
|
||||
|
||||
version = glGetString(GL_SHADING_LANGUAGE_VERSION);
|
||||
*major = atol(version);
|
||||
version = strstr(version, ".");
|
||||
*minor = atol(version+1);
|
||||
}
|
||||
|
||||
/* compile and link the shader program needed to write a depth texture to the depth buffer */
|
||||
static void load_depth_shader_program(wmDrawTriple* triple)
|
||||
{
|
||||
int success;
|
||||
GLsizei len;
|
||||
GLbyte infoLog[1000];
|
||||
int major, minor;
|
||||
|
||||
/* This vertex program just passes the texture coordinate through and transforms the vertex position */
|
||||
/* This program should be compatible up to OpenGL 4.0 with the fixed-function compatibility profile */
|
||||
static const GLcharARB* depth_vertex_shader_source_100[] = {
|
||||
"void main()\n",
|
||||
"{\n",
|
||||
" gl_TexCoord[0] = gl_MultiTexCoord0;\n",
|
||||
" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n",
|
||||
"}\n",
|
||||
};
|
||||
|
||||
/* This fragment program is used non-rectangle textures */
|
||||
/* Compatible with version 1.0-1.2 w/o GL_ARB_texture_rectangle */
|
||||
static const GLcharARB* depth_fragment_shader_source_100[] = {
|
||||
"uniform sampler2D depth_texture;\n",
|
||||
"void main()\n",
|
||||
"{\n",
|
||||
" gl_FragDepth = texture2D(depth_texture, gl_TexCoord[0].xy).x;\n",
|
||||
"}\n",
|
||||
};
|
||||
|
||||
/* This fragment program is used for rectangular textures */
|
||||
/* Compatible with version 1.0-1.2 w/ GL_ARB_texture_rectangle */
|
||||
static const GLcharARB* depth_fragment_shader_rect_source_100[] = {
|
||||
"#extension GL_ARB_texture_rectangle : enable\n",
|
||||
"uniform sampler2DRect depth_texture;\n",
|
||||
"void main()\n",
|
||||
"{\n",
|
||||
" gl_FragDepth = texture2DRect(depth_texture, gl_TexCoord[0].xy).x;\n",
|
||||
"}\n",
|
||||
};
|
||||
|
||||
/* This fragment program is used non-rectangle textures */
|
||||
/* Compatible with version 1.3 w/o GL_ARB_texture_rectangle */
|
||||
static const GLcharARB* depth_fragment_shader_source_130[] = {
|
||||
"#version 130\n",
|
||||
"uniform sampler2D depth_texture;\n",
|
||||
"void main()\n",
|
||||
"{\n",
|
||||
" gl_FragDepth = texture(depth_texture, gl_TexCoord[0].xy).x;\n",
|
||||
"}\n",
|
||||
};
|
||||
|
||||
/* This fragment program is used for rectangular textures */
|
||||
/* Compatible with version 1.3 w/ GL_ARB_texture_rectangle */
|
||||
static const GLcharARB* depth_fragment_shader_rect_source_130[] = {
|
||||
"#version 130\n",
|
||||
"#extension GL_ARB_texture_rectangle : enable\n",
|
||||
"uniform sampler2DRect depth_texture;\n",
|
||||
"void main()\n",
|
||||
"{\n",
|
||||
" gl_FragDepth = texture(depth_texture, gl_TexCoord[0].xy).x;\n",
|
||||
"}\n",
|
||||
};
|
||||
|
||||
const GLcharARB** source;
|
||||
int source_lines;
|
||||
|
||||
get_shading_language_version(&major, &minor);
|
||||
|
||||
/* compile the vertex program */
|
||||
|
||||
triple->depth_vertex_shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
|
||||
|
||||
glShaderSourceARB(triple->depth_vertex_shader, sizeof(depth_vertex_shader_source_100)/sizeof(GLcharARB*), depth_vertex_shader_source_100, NULL);
|
||||
glCompileShaderARB(triple->depth_vertex_shader);
|
||||
|
||||
/* print any errors/warnings gotten while compiling the vertex program */
|
||||
|
||||
glGetObjectParameterivARB(triple->depth_vertex_shader, GL_OBJECT_COMPILE_STATUS_ARB, &success);
|
||||
glGetInfoLogARB(triple->depth_vertex_shader, 1000, &len, infoLog);
|
||||
|
||||
if (len > 0)
|
||||
printf("triple depth buffer vertex program compilation messages:\n%s\n", infoLog);
|
||||
|
||||
/* compile the appropriate fragment program depending on support for rectangular textures */
|
||||
|
||||
triple->depth_fragment_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
|
||||
|
||||
//if (major == 1 && minor < 30) {
|
||||
if (GLEW_ARB_texture_rectangle) {
|
||||
source = depth_fragment_shader_rect_source_100;
|
||||
source_lines = sizeof(depth_fragment_shader_rect_source_100)/sizeof(GLcharARB*);
|
||||
}
|
||||
else {
|
||||
source = depth_fragment_shader_source_100;
|
||||
source_lines = sizeof(depth_fragment_shader_source_100)/sizeof(GLcharARB*);
|
||||
}
|
||||
//}
|
||||
//else {
|
||||
// if (GLEW_ARB_texture_rectangle) {
|
||||
// source = depth_fragment_shader_rect_source_130;
|
||||
// source_lines = sizeof(depth_fragment_shader_rect_source_130)/sizeof(GLcharARB*);
|
||||
// }
|
||||
// else {
|
||||
// source = depth_fragment_shader_source_130;
|
||||
// source_lines = sizeof(depth_fragment_shader_source_130)/sizeof(GLcharARB*);
|
||||
// }
|
||||
//}
|
||||
|
||||
glShaderSourceARB(triple->depth_fragment_shader, source_lines, source, NULL);
|
||||
glCompileShaderARB(triple->depth_fragment_shader);
|
||||
|
||||
/* print any errors/warnings gotten while compiling the fragment program */
|
||||
|
||||
glGetObjectParameterivARB(triple->depth_fragment_shader, GL_OBJECT_COMPILE_STATUS_ARB, &success);
|
||||
glGetInfoLogARB(triple->depth_fragment_shader, 1000, &len, infoLog);
|
||||
|
||||
if (len > 0)
|
||||
printf("triple depth buffer fragment program compilation messages:\n%s\n", infoLog);
|
||||
|
||||
/* link the shaders into a complete program */
|
||||
|
||||
triple->depth_program = glCreateProgramObjectARB();
|
||||
|
||||
glAttachObjectARB(triple->depth_program, triple->depth_vertex_shader);
|
||||
glAttachObjectARB(triple->depth_program, triple->depth_fragment_shader);
|
||||
|
||||
glLinkProgramARB(triple->depth_program);
|
||||
|
||||
/* print any errors/warnings gotten while linking the final program */
|
||||
|
||||
glGetObjectParameterivARB(triple->depth_program, GL_OBJECT_LINK_STATUS_ARB, &success);
|
||||
glGetInfoLogARB(triple->depth_program, 1000, &len, infoLog);
|
||||
|
||||
if (len > 0)
|
||||
printf("triple depth buffer program linker messages:\n%s\n", infoLog);
|
||||
}
|
||||
|
||||
static int wm_triple_gen_depth_buffer(wmWindow *win, wmDrawTriple *triple)
|
||||
{
|
||||
/* To do this fast we need support for depth textures and GLSL */
|
||||
if (GLEW_ARB_depth_texture &&
|
||||
GLEW_ARB_shader_objects &&
|
||||
GLEW_ARB_vertex_shader &&
|
||||
GLEW_ARB_fragment_shader &&
|
||||
GLEW_ARB_shading_language_100)
|
||||
{
|
||||
GLint maxsize;
|
||||
int x, y;
|
||||
|
||||
/* XXX: this is copied from wm_triple_gen_textures.
|
||||
can probably combine them together once this is accepted into trunk */
|
||||
|
||||
/* compute texture sizes */
|
||||
if(GLEW_ARB_texture_rectangle) {
|
||||
triple->depth_target= GL_TEXTURE_RECTANGLE_ARB;
|
||||
triple->depth_nx= 1;
|
||||
triple->depth_ny= 1;
|
||||
triple->depth_x[0]= win->sizex;
|
||||
triple->depth_y[0]= win->sizey;
|
||||
}
|
||||
else if(GPU_non_power_of_two_support()) {
|
||||
triple->depth_target= GL_TEXTURE_2D;
|
||||
triple->depth_nx= 1;
|
||||
triple->depth_ny= 1;
|
||||
triple->depth_x[0]= win->sizex;
|
||||
triple->depth_y[0]= win->sizey;
|
||||
}
|
||||
else {
|
||||
triple->depth_target= GL_TEXTURE_2D;
|
||||
triple->depth_nx= 0;
|
||||
triple->depth_ny= 0;
|
||||
split_width(win->sizex, MAX_N_TEX, triple->depth_x, &triple->depth_nx);
|
||||
split_width(win->sizey, MAX_N_TEX, triple->depth_y, &triple->depth_ny);
|
||||
}
|
||||
|
||||
/* generate texture names */
|
||||
glGenTextures(triple->depth_nx*triple->depth_ny, triple->depth_bind);
|
||||
|
||||
if(!triple->depth_bind[0]) {
|
||||
/* not the typical failure case but we handle it anyway */
|
||||
printf("WM: failed to allocate depth texture for triple buffer drawing (glGenTextures).\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(y=0; y<triple->depth_ny; y++) {
|
||||
for(x=0; x<triple->depth_nx; x++) {
|
||||
/* proxy texture is only guaranteed to test for the cases that
|
||||
* there is only one texture in use, which may not be the case */
|
||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxsize);
|
||||
|
||||
if(triple->depth_x[x] > maxsize || triple->depth_y[y] > maxsize) {
|
||||
glBindTexture(triple->depth_target, 0);
|
||||
printf("WM: failed to allocate texture for triple buffer drawing (texture too large for graphics card).\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* setup actual texture */
|
||||
glBindTexture(triple->depth_target, triple->depth_bind[x + y*triple->depth_nx]);
|
||||
|
||||
/* important difference from wm_triple_gen_textures!
|
||||
use GL_DEPTH_COMPONENT as format and internalformat */
|
||||
glTexImage2D(triple->depth_target, 0, GL_DEPTH_COMPONENT, triple->depth_x[x], triple->depth_y[y], 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
|
||||
|
||||
glTexParameteri(triple->depth_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(triple->depth_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
/* important difference from wm_triple_gen_textures!
|
||||
turn off depth comparison mode that would be used if this was a shadow map */
|
||||
glTexParameteri(triple->depth_target, GL_TEXTURE_COMPARE_MODE, GL_NONE);
|
||||
|
||||
glBindTexture(triple->depth_target, 0);
|
||||
|
||||
/* not sure if this works everywhere .. */
|
||||
if(glGetError() == GL_OUT_OF_MEMORY) {
|
||||
printf("WM: failed to allocate depth texture for triple buffer drawing (out of memory).\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
load_depth_shader_program(triple);
|
||||
}
|
||||
/* otherwise, we have to fall back to the more compatible glReadBuffer/glDrawBuffer method */
|
||||
else {
|
||||
const int count = win->sizex * win->sizey;
|
||||
const int size = count*sizeof(GLfloat);
|
||||
|
||||
triple->depth_type = GL_FLOAT;
|
||||
triple->depth = MEM_mallocN(size, "wm_triple_gen_depth_buffer");
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void wm_triple_copy_depth_buffer(wmWindow *win, wmDrawTriple *triple)
|
||||
{
|
||||
/* To do this fast we need support for depth textures and GLSL */
|
||||
if (GLEW_ARB_depth_texture &&
|
||||
GLEW_ARB_shader_objects &&
|
||||
GLEW_ARB_vertex_shader &&
|
||||
GLEW_ARB_fragment_shader &&
|
||||
GLEW_ARB_shading_language_100)
|
||||
{
|
||||
int x, y, sizex, sizey, offx, offy;
|
||||
|
||||
/* XXX this is pretty much identical to wm_triple_copy_textures,
|
||||
the fact that the textures are GL_DEPTH_COMPONENT format is what makes the difference */
|
||||
|
||||
for(y=0, offy=0; y<triple->depth_ny; offy+=triple->depth_y[y], y++) {
|
||||
for(x=0, offx=0; x<triple->depth_nx; offx+=triple->depth_x[x], x++) {
|
||||
sizex= (x == triple->depth_nx-1)? win->sizex-offx: triple->depth_x[x];
|
||||
sizey= (y == triple->depth_ny-1)? win->sizey-offy: triple->depth_y[y];
|
||||
|
||||
glBindTexture(triple->depth_target, triple->depth_bind[x + y*triple->depth_nx]);
|
||||
glCopyTexSubImage2D(triple->depth_target, 0, 0, 0, offx, offy, sizex, sizey);
|
||||
}
|
||||
}
|
||||
|
||||
glBindTexture(triple->depth_target, 0);
|
||||
}
|
||||
else if (triple->depth) {
|
||||
/* For the compatibility fallback, we set the pixel store state to the defaults,
|
||||
anything else is very unlikely to be even remotely fast (and it is already slow
|
||||
using these defaults) */
|
||||
|
||||
glPushAttrib(GL_PIXEL_MODE_BIT);
|
||||
|
||||
glPixelStorei(GL_PACK_SWAP_BYTES, GL_FALSE);
|
||||
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
|
||||
glPixelStorei(GL_PACK_SKIP_ROWS, 0);
|
||||
glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 4);
|
||||
|
||||
glPixelTransferi(GL_DEPTH_SCALE, 1);
|
||||
glPixelTransferi(GL_DEPTH_BIAS, 0);
|
||||
|
||||
glReadPixels(0, 0, win->sizex, win->sizey, GL_DEPTH_COMPONENT, triple->depth_type, triple->depth);
|
||||
|
||||
glPopAttrib();
|
||||
}
|
||||
}
|
||||
|
||||
static void wm_triple_draw_depth_buffer(wmWindow *win, wmDrawTriple *triple)
|
||||
{
|
||||
/* To do this fast we need support for depth textures and GLSL */
|
||||
if (GLEW_ARB_depth_texture &&
|
||||
GLEW_ARB_shader_objects &&
|
||||
GLEW_ARB_vertex_shader &&
|
||||
GLEW_ARB_fragment_shader &&
|
||||
GLEW_ARB_shading_language_100)
|
||||
{
|
||||
float halfx, halfy, ratiox, ratioy;
|
||||
int x, y, sizex, sizey, offx, offy;
|
||||
GLint depth_texture;
|
||||
|
||||
glPushAttrib(
|
||||
GL_COLOR_BUFFER_BIT|
|
||||
GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
/* depth test has to be enabled to write to depth buffer,
|
||||
set GL_ALWAYS so that what is in the texture overwrites what
|
||||
is there, and make sure the buffer is set to be writable */
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_ALWAYS);
|
||||
glDepthMask(GL_TRUE);
|
||||
|
||||
/* since the fragment shader does not write gl_FragColor what it would
|
||||
write to the color buffer is actually undefined. Regardless, do not
|
||||
write to color buffer. */
|
||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||
|
||||
/* load the shader and bind the sampler2D to the 0th texture unit */
|
||||
glUseProgramObjectARB(triple->depth_program);
|
||||
depth_texture = glGetUniformLocationARB(triple->depth_program, "depth_texture");
|
||||
glActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
glUniform1iARB(depth_texture, 0);
|
||||
|
||||
glEnable(triple->depth_target);
|
||||
|
||||
for(y=0, offy=0; y<triple->depth_ny; offy+=triple->depth_y[y], y++) {
|
||||
for(x=0, offx=0; x<triple->depth_nx; offx+=triple->depth_x[x], x++) {
|
||||
sizex= (x == triple->depth_nx-1)? win->sizex-offx: triple->depth_x[x];
|
||||
sizey= (y == triple->depth_ny-1)? win->sizey-offy: triple->depth_y[y];
|
||||
|
||||
/* wmOrtho for the screen has this same offset */
|
||||
ratiox= sizex;
|
||||
ratioy= sizey;
|
||||
halfx= 0.375f;
|
||||
halfy= 0.375f;
|
||||
|
||||
/* texture rectangle has unnormalized coordinates */
|
||||
if(triple->depth_target == GL_TEXTURE_2D) {
|
||||
ratiox /= triple->depth_x[x];
|
||||
ratioy /= triple->depth_y[y];
|
||||
halfx /= triple->depth_x[x];
|
||||
halfy /= triple->depth_y[y];
|
||||
}
|
||||
|
||||
glBindTexture(triple->depth_target, triple->depth_bind[x + y*triple->depth_nx]);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(halfx, halfy);
|
||||
glVertex2f(offx, offy);
|
||||
|
||||
glTexCoord2f(ratiox+halfx, halfy);
|
||||
glVertex2f(offx+sizex, offy);
|
||||
|
||||
glTexCoord2f(ratiox+halfx, ratioy+halfy);
|
||||
glVertex2f(offx+sizex, offy+sizey);
|
||||
|
||||
glTexCoord2f(halfx, ratioy+halfy);
|
||||
glVertex2f(offx, offy+sizey);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
glBindTexture(triple->depth_target, 0);
|
||||
glDisable(triple->depth_target);
|
||||
|
||||
/* go back to using the fixed function pipeline */
|
||||
glUseProgramObjectARB(0);
|
||||
|
||||
glPopAttrib();
|
||||
}
|
||||
else {
|
||||
if (triple->depth) {
|
||||
glPushAttrib(
|
||||
GL_COLOR_BUFFER_BIT|
|
||||
GL_DEPTH_BUFFER_BIT|
|
||||
GL_ENABLE_BIT|
|
||||
GL_PIXEL_MODE_BIT);
|
||||
|
||||
/* About the only chance this will be remotely fast is if we use the default values */
|
||||
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
|
||||
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
||||
|
||||
glPixelTransferi(GL_DEPTH_SCALE, 1);
|
||||
glPixelTransferi(GL_DEPTH_BIAS, 0);
|
||||
|
||||
glPixelZoom(1.0, 1.0);
|
||||
|
||||
/* important, cannot write the depth buffer unless this is enabled */
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_TRUE);
|
||||
glDepthFunc(GL_ALWAYS);
|
||||
|
||||
/* make sure color buffer isn't overwritten */
|
||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||
|
||||
/* send the saved depth buffer to the screen */
|
||||
glRasterPos2i(0, 0);
|
||||
glDrawPixels(win->sizex, win->sizey, GL_DEPTH_COMPONENT, triple->depth_type, triple->depth);
|
||||
|
||||
glPopAttrib();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void wm_method_draw_triple(bContext *C, wmWindow *win)
|
||||
{
|
||||
wmWindowManager *wm= CTX_wm_manager(C);
|
||||
@@ -574,11 +1013,20 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
|
||||
wmSubWindowSet(win, screen->mainwin);
|
||||
|
||||
wm_triple_draw_textures(win, win->drawdata);
|
||||
#ifdef WITH_ONSURFACEBRUSH
|
||||
wm_triple_draw_depth_buffer(win, win->drawdata);
|
||||
#endif
|
||||
|
||||
triple= win->drawdata;
|
||||
}
|
||||
else {
|
||||
win->drawdata= MEM_callocN(sizeof(wmDrawTriple), "wmDrawTriple");
|
||||
|
||||
if(!wm_triple_gen_textures(win, win->drawdata))
|
||||
if(!wm_triple_gen_textures(win, win->drawdata)
|
||||
#ifdef WITH_ONSURFACEBRUSH
|
||||
|| !wm_triple_gen_depth_buffer(win, win->drawdata)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
wm_draw_triple_fail(C, win);
|
||||
return;
|
||||
@@ -610,6 +1058,9 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
|
||||
ED_area_overdraw(C);
|
||||
|
||||
wm_triple_copy_textures(win, triple);
|
||||
#ifdef WITH_ONSURFACEBRUSH
|
||||
wm_triple_copy_depth_buffer(win, triple);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* after area regions so we can do area 'overlay' drawing */
|
||||
|
@@ -2700,6 +2700,346 @@ void WM_OT_straightline_gesture(wmOperatorType *ot)
|
||||
/* *********************** radial control ****************** */
|
||||
|
||||
static const int WM_RADIAL_CONTROL_DISPLAY_SIZE = 200;
|
||||
#if 0
|
||||
typedef struct wmRadialControl {
|
||||
int mode;
|
||||
float initial_value, value, max_value;
|
||||
float col[4], tex_col[4];
|
||||
int initial_mouse[2];
|
||||
void *cursor;
|
||||
GLuint tex;
|
||||
} wmRadialControl;
|
||||
|
||||
extern Paint *paint_get_active(Scene *sce);
|
||||
extern struct Brush *paint_brush(struct Paint *paint);
|
||||
#ifdef WITH_ONSURFACEBRUSH
|
||||
extern int sculpt_get_brush_geometry(bContext* C, int x, int y, int* pixel_radius, float location[3], float modelview[16], float projection[16], int viewport[4]);
|
||||
extern float unproject_brush_radius(Object *ob, ViewContext *vc, float center[3], float offset);
|
||||
#endif
|
||||
|
||||
static void wm_radial_control_paint(bContext *C, int x, int y, void *customdata)
|
||||
{
|
||||
wmRadialControl *rc = (wmRadialControl*)customdata;
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
float r1=0.0f, r2=0.0f, r3=0.0f, angle=0.0f;
|
||||
|
||||
// int hit = 0;
|
||||
int hit = 0;
|
||||
|
||||
if(rc->mode == WM_RADIALCONTROL_STRENGTH)
|
||||
rc->tex_col[3]= (rc->value + 0.5f);
|
||||
|
||||
if(rc->mode == WM_RADIALCONTROL_SIZE) {
|
||||
r1= rc->value;
|
||||
r2= rc->initial_value;
|
||||
r3= r1;
|
||||
} else if(rc->mode == WM_RADIALCONTROL_STRENGTH) {
|
||||
r1= (1 - rc->value) * WM_RADIAL_CONTROL_DISPLAY_SIZE;
|
||||
r2= r3= (float)WM_RADIAL_CONTROL_DISPLAY_SIZE;
|
||||
} else if(rc->mode == WM_RADIALCONTROL_ANGLE) {
|
||||
r1= r2= r3= (float)WM_RADIAL_CONTROL_DISPLAY_SIZE;
|
||||
angle = rc->value;
|
||||
}
|
||||
|
||||
/* Keep cursor in the original place */
|
||||
x = rc->initial_mouse[0] - ar->winrct.xmin;
|
||||
y = rc->initial_mouse[1] - ar->winrct.ymin;
|
||||
|
||||
#ifdef WITH_ONSURFACEBRUSH
|
||||
if ((paint->flags & PAINT_SHOW_BRUSH_ON_SURFACE) && vc.obact->sculpt) {
|
||||
float alpha;
|
||||
|
||||
int pixel_radius, viewport[4];
|
||||
float location[3], modelview[16], projection[16];
|
||||
|
||||
float visual_strength = rc->mode == WM_RADIALCONTROL_STRENGTH ? rc->value*rc->value : brush_alpha(brush)*brush_alpha(brush);
|
||||
|
||||
const float min_alpha = 0.20f;
|
||||
const float max_alpha = 0.80f;
|
||||
|
||||
hit = sculpt_get_brush_geometry(C, x, y, &pixel_radius, location, modelview, projection, viewport);
|
||||
|
||||
alpha = min_alpha + (visual_strength*(max_alpha-min_alpha));
|
||||
|
||||
if (hit) {
|
||||
Object *ob= CTX_data_active_object(C);
|
||||
|
||||
{
|
||||
const float unprojected_radius= unproject_brush_radius(CTX_data_active_object(C), &vc, location, r1);
|
||||
const float max_thickness= 0.12;
|
||||
const float min_thickness= 0.06;
|
||||
const float thickness= 1.0 - min_thickness - visual_strength*max_thickness;
|
||||
const float inner_radius= unprojected_radius*thickness;
|
||||
const float outer_radius= unprojected_radius;
|
||||
|
||||
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
|
||||
|
||||
ED_draw_fixed_overlay_on_surface(modelview, projection, ob->size, viewport, location, outer_radius, sd, brush, &vc, y+r3, y-r3, x-r3, x+r3, -angle);
|
||||
|
||||
ED_draw_on_surface_cursor(modelview, projection, col, alpha, ob->size, viewport, location, inner_radius, outer_radius, brush_size(brush));
|
||||
|
||||
if(rc->mode == WM_RADIALCONTROL_ANGLE) {
|
||||
glTranslatef((float)x, (float)y, 0.0f);
|
||||
glEnable(GL_BLEND);
|
||||
glColor4f(col[0], col[1], col[2], 0.5f);
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
fdrawline(0, 0, WM_RADIAL_CONTROL_DISPLAY_SIZE, 0);
|
||||
glRotatef(angle, 0, 0, 1);
|
||||
fdrawline(0, 0, WM_RADIAL_CONTROL_DISPLAY_SIZE, 0);
|
||||
glDisable(GL_LINE_SMOOTH);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const float unprojected_radius= unproject_brush_radius(CTX_data_active_object(C), &vc, location, r2);
|
||||
const float max_thickness= 0.12;
|
||||
const float min_thickness= 0.06;
|
||||
const float thickness= 1.0 - min_thickness - visual_strength*max_thickness;
|
||||
const float inner_radius= unprojected_radius*thickness;
|
||||
const float outer_radius= unprojected_radius;
|
||||
|
||||
ED_draw_on_surface_cursor(modelview, projection, col, alpha, ob->size, viewport, location, inner_radius, outer_radius, brush_size(brush));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!hit) {
|
||||
#endif
|
||||
glTranslatef((float)x, (float)y, 0.0f);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
if(rc->mode == WM_RADIALCONTROL_ANGLE) {
|
||||
glRotatef(angle, 0, 0, 1);
|
||||
}
|
||||
|
||||
if (rc->tex) {
|
||||
glBindTexture(GL_TEXTURE_2D, rc->tex);
|
||||
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBegin(GL_QUADS);
|
||||
glColor4fv(rc->tex_col);
|
||||
glTexCoord2f(0,0);
|
||||
glVertex2f(-r3, -r3);
|
||||
glTexCoord2f(1,0);
|
||||
glVertex2f(r3, -r3);
|
||||
glTexCoord2f(1,1);
|
||||
glVertex2f(r3, r3);
|
||||
glTexCoord2f(0,1);
|
||||
glVertex2f(-r3, r3);
|
||||
glEnd();
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
if(rc->mode == WM_RADIALCONTROL_ANGLE) {
|
||||
glColor4fv(rc->col);
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
glRotatef(-angle, 0, 0, 1);
|
||||
fdrawline(0.0f, 0.0f, (float)WM_RADIAL_CONTROL_DISPLAY_SIZE, 0.0f);
|
||||
glRotatef(angle, 0, 0, 1);
|
||||
fdrawline(0.0f, 0.0f, (float)WM_RADIAL_CONTROL_DISPLAY_SIZE, 0.0f);
|
||||
glDisable(GL_LINE_SMOOTH);
|
||||
}
|
||||
|
||||
glColor4fv(rc->col);
|
||||
glutil_draw_lined_arc(0.0, (float)(M_PI*2.0), r1, 40);
|
||||
glutil_draw_lined_arc(0.0, (float)(M_PI*2.0), r2, 40);
|
||||
glDisable(GL_BLEND);
|
||||
#ifdef WITH_ONSURFACEBRUSH
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int WM_radial_control_modal(bContext *C, wmOperator *op, wmEvent *event)
|
||||
{
|
||||
wmRadialControl *rc = (wmRadialControl*)op->customdata;
|
||||
int mode, initial_mouse[2], delta[2];
|
||||
float dist;
|
||||
double new_value = RNA_float_get(op->ptr, "new_value");
|
||||
int ret = OPERATOR_RUNNING_MODAL;
|
||||
// float initial_value = RNA_float_get(op->ptr, "initial_value");
|
||||
|
||||
mode = RNA_enum_get(op->ptr, "mode");
|
||||
RNA_int_get_array(op->ptr, "initial_mouse", initial_mouse);
|
||||
|
||||
switch(event->type) {
|
||||
case MOUSEMOVE:
|
||||
delta[0]= initial_mouse[0] - event->x;
|
||||
delta[1]= initial_mouse[1] - event->y;
|
||||
|
||||
//if (mode == WM_RADIALCONTROL_SIZE)
|
||||
// delta[0]+= initial_value;
|
||||
//else if(mode == WM_RADIALCONTROL_STRENGTH)
|
||||
// delta[0]+= WM_RADIAL_CONTROL_DISPLAY_SIZE * (1 - initial_value);
|
||||
//else if(mode == WM_RADIALCONTROL_ANGLE) {
|
||||
// delta[0]+= WM_RADIAL_CONTROL_DISPLAY_SIZE * cos(initial_value*M_PI/180.0f);
|
||||
// delta[1]+= WM_RADIAL_CONTROL_DISPLAY_SIZE * sin(initial_value*M_PI/180.0f);
|
||||
//}
|
||||
|
||||
dist= sqrtf(delta[0]*delta[0]+delta[1]*delta[1]);
|
||||
|
||||
if(mode == WM_RADIALCONTROL_SIZE)
|
||||
new_value = dist;
|
||||
else if(mode == WM_RADIALCONTROL_STRENGTH) {
|
||||
new_value = 1 - dist / WM_RADIAL_CONTROL_DISPLAY_SIZE;
|
||||
} else if(mode == WM_RADIALCONTROL_ANGLE)
|
||||
new_value = ((int)(atan2f(delta[1], delta[0]) * (float)(180.0 / M_PI)) + 180);
|
||||
|
||||
if(event->ctrl) {
|
||||
if(mode == WM_RADIALCONTROL_STRENGTH)
|
||||
new_value = ((int)ceilf(new_value * 10.f) * 10.0f) / 100.f;
|
||||
else
|
||||
new_value = ((int)new_value + 5) / 10*10;
|
||||
}
|
||||
|
||||
break;
|
||||
case ESCKEY:
|
||||
case RIGHTMOUSE:
|
||||
ret = OPERATOR_CANCELLED;
|
||||
break;
|
||||
case LEFTMOUSE:
|
||||
case PADENTER:
|
||||
op->type->exec(C, op);
|
||||
ret = OPERATOR_FINISHED;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Clamp */
|
||||
if(new_value > rc->max_value)
|
||||
new_value = rc->max_value;
|
||||
else if(new_value < 0)
|
||||
new_value = 0;
|
||||
|
||||
/* Update paint data */
|
||||
rc->value = (float)new_value;
|
||||
|
||||
RNA_float_set(op->ptr, "new_value", rc->value);
|
||||
|
||||
if(ret != OPERATOR_RUNNING_MODAL) {
|
||||
WM_paint_cursor_end(CTX_wm_manager(C), rc->cursor);
|
||||
MEM_freeN(rc);
|
||||
}
|
||||
|
||||
ED_region_tag_redraw(CTX_wm_region(C));
|
||||
|
||||
//if (ret != OPERATOR_RUNNING_MODAL) {
|
||||
// wmWindow *win = CTX_wm_window(C);
|
||||
// WM_cursor_restore(win);
|
||||
//}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Expects the operator customdata to be an ImBuf (or NULL) */
|
||||
int WM_radial_control_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
||||
{
|
||||
wmRadialControl *rc = MEM_callocN(sizeof(wmRadialControl), "radial control");
|
||||
// wmWindow *win = CTX_wm_window(C);
|
||||
int mode = RNA_enum_get(op->ptr, "mode");
|
||||
float initial_value = RNA_float_get(op->ptr, "initial_value");
|
||||
//float initial_size = RNA_float_get(op->ptr, "initial_size");
|
||||
int mouse[2];
|
||||
|
||||
mouse[0]= event->x;
|
||||
mouse[1]= event->y;
|
||||
|
||||
//if (initial_size == 0)
|
||||
// initial_size = WM_RADIAL_CONTROL_DISPLAY_SIZE;
|
||||
|
||||
if(mode == WM_RADIALCONTROL_SIZE) {
|
||||
rc->max_value = 200;
|
||||
mouse[0]-= (int)initial_value;
|
||||
}
|
||||
else if(mode == WM_RADIALCONTROL_STRENGTH) {
|
||||
rc->max_value = 1;
|
||||
mouse[0]-= (int)(WM_RADIAL_CONTROL_DISPLAY_SIZE * (1.0f - initial_value));
|
||||
}
|
||||
else if(mode == WM_RADIALCONTROL_ANGLE) {
|
||||
rc->max_value = 360;
|
||||
mouse[0]-= (int)(WM_RADIAL_CONTROL_DISPLAY_SIZE * cos(initial_value));
|
||||
mouse[1]-= (int)(WM_RADIAL_CONTROL_DISPLAY_SIZE * sin(initial_value));
|
||||
initial_value *= 180.0f/(float)M_PI;
|
||||
}
|
||||
|
||||
if(op->customdata) {
|
||||
ImBuf *im = (ImBuf*)op->customdata;
|
||||
/* Build GL texture */
|
||||
glGenTextures(1, &rc->tex);
|
||||
glBindTexture(GL_TEXTURE_2D, rc->tex);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, im->x, im->y, 0, GL_ALPHA, GL_FLOAT, im->rect_float);
|
||||
MEM_freeN(im->rect_float);
|
||||
MEM_freeN(im);
|
||||
}
|
||||
|
||||
RNA_float_get_array(op->ptr, "color", rc->col);
|
||||
RNA_float_get_array(op->ptr, "texture_color", rc->tex_col);
|
||||
|
||||
RNA_int_set_array(op->ptr, "initial_mouse", mouse);
|
||||
RNA_float_set(op->ptr, "new_value", initial_value);
|
||||
|
||||
op->customdata = rc;
|
||||
rc->mode = mode;
|
||||
rc->initial_value = initial_value;
|
||||
rc->initial_mouse[0] = mouse[0];
|
||||
rc->initial_mouse[1] = mouse[1];
|
||||
rc->cursor = WM_paint_cursor_activate(CTX_wm_manager(C), op->type->poll,
|
||||
wm_radial_control_paint, op->customdata);
|
||||
|
||||
//WM_cursor_modal(win, CURSOR_NONE);
|
||||
|
||||
/* add modal handler */
|
||||
WM_event_add_modal_handler(C, op);
|
||||
|
||||
WM_radial_control_modal(C, op, event);
|
||||
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
/* Gets a descriptive string of the operation */
|
||||
void WM_radial_control_string(wmOperator *op, char str[], int maxlen)
|
||||
{
|
||||
int mode = RNA_enum_get(op->ptr, "mode");
|
||||
float v = RNA_float_get(op->ptr, "new_value");
|
||||
|
||||
if(mode == WM_RADIALCONTROL_SIZE)
|
||||
BLI_snprintf(str, maxlen, "Size: %d", (int)v);
|
||||
else if(mode == WM_RADIALCONTROL_STRENGTH)
|
||||
BLI_snprintf(str, maxlen, "Strength: %d", (int)v);
|
||||
else if(mode == WM_RADIALCONTROL_ANGLE)
|
||||
BLI_snprintf(str, maxlen, "Angle: %d", (int)(v * 180.0f/(float)M_PI));
|
||||
}
|
||||
|
||||
/** Important: this doesn't define an actual operator, it
|
||||
just sets up the common parts of the radial control op. **/
|
||||
void WM_OT_radial_control_partial(wmOperatorType *ot)
|
||||
{
|
||||
static EnumPropertyItem radial_mode_items[] = {
|
||||
{WM_RADIALCONTROL_SIZE, "SIZE", 0, "Size", ""},
|
||||
{WM_RADIALCONTROL_STRENGTH, "STRENGTH", 0, "Strength", ""},
|
||||
{WM_RADIALCONTROL_ANGLE, "ANGLE", 0, "Angle", ""},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
static float color[4] = {1.0f, 1.0f, 1.0f, 0.5f};
|
||||
static float tex_color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
|
||||
/* Should be set in custom invoke() */
|
||||
RNA_def_float(ot->srna, "initial_value", 0, 0, FLT_MAX, "Initial Value", "", 0, FLT_MAX);
|
||||
|
||||
/* Set internally, should be used in custom exec() to get final value */
|
||||
RNA_def_float(ot->srna, "new_value", 0, 0, FLT_MAX, "New Value", "", 0, FLT_MAX);
|
||||
|
||||
/* Should be set before calling operator */
|
||||
RNA_def_enum(ot->srna, "mode", radial_mode_items, 0, "Mode", "");
|
||||
|
||||
/* Internal */
|
||||
RNA_def_int_vector(ot->srna, "initial_mouse", 2, NULL, INT_MIN, INT_MAX, "Initial Mouse", "", INT_MIN, INT_MAX);
|
||||
|
||||
RNA_def_float_color(ot->srna, "color", 4, color, 0.0f, FLT_MAX, "Color", "Radial control color", 0.0f, 1.0f);
|
||||
RNA_def_float_color(ot->srna, "texture_color", 4, tex_color, 0.0f, FLT_MAX, "Texture Color", "Radial control texture color", 0.0f, 1.0f);
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
PropertyType type;
|
||||
|
Reference in New Issue
Block a user