svn merge -r40051:40075 https://svn.blender.org/svnroot/bf-blender/trunk/blender
This commit is contained in:
531
doc/python_api/rst/gpu.rst
Normal file
531
doc/python_api/rst/gpu.rst
Normal file
@@ -0,0 +1,531 @@
|
||||
|
||||
GPU functions (gpu)
|
||||
===================
|
||||
|
||||
*****
|
||||
Intro
|
||||
*****
|
||||
|
||||
Module to provide functions concerning the GPU implementation in Blender, in particular
|
||||
the GLSL shaders that blender generates automatically to render materials in the 3D view
|
||||
and in the game engine.
|
||||
|
||||
.. warning::
|
||||
|
||||
The API provided by this module should be consider unstable. The data exposed by the API
|
||||
are are closely related to Blender's internal GLSL code and may change if the GLSL code
|
||||
is modified (e.g. new uniform type).
|
||||
|
||||
.. module:: gpu
|
||||
|
||||
*********
|
||||
Constants
|
||||
*********
|
||||
|
||||
--------------
|
||||
GLSL data type
|
||||
--------------
|
||||
|
||||
.. _data-type:
|
||||
|
||||
Type of GLSL data.
|
||||
For shader uniforms, the data type determines which glUniform function
|
||||
variant to use to send the uniform value to the GPU.
|
||||
For vertex attributes, the data type determines which glVertexAttrib function
|
||||
variant to use to send the vertex attribute to the GPU.
|
||||
|
||||
See export_shader_
|
||||
|
||||
.. data:: GPU_DATA_1I
|
||||
|
||||
one integer
|
||||
|
||||
:value: 1
|
||||
|
||||
.. data:: GPU_DATA_1F
|
||||
|
||||
one float
|
||||
|
||||
:value: 2
|
||||
|
||||
.. data:: GPU_DATA_2F
|
||||
|
||||
two floats
|
||||
|
||||
:value: 3
|
||||
|
||||
.. data:: GPU_DATA_3F
|
||||
|
||||
three floats
|
||||
|
||||
:value: 4
|
||||
|
||||
.. data:: GPU_DATA_4F
|
||||
|
||||
four floats
|
||||
|
||||
:value: 5
|
||||
|
||||
.. data:: GPU_DATA_9F
|
||||
|
||||
matrix 3x3 in column-major order
|
||||
|
||||
:value: 6
|
||||
|
||||
.. data:: GPU_DATA_16F
|
||||
|
||||
matrix 4x4 in column-major order
|
||||
|
||||
:value: 7
|
||||
|
||||
.. data:: GPU_DATA_4UB
|
||||
|
||||
four unsigned byte
|
||||
|
||||
:value: 8
|
||||
|
||||
-----------------
|
||||
GLSL uniform type
|
||||
-----------------
|
||||
|
||||
.. _uniform-type:
|
||||
|
||||
Constants that specify the type of uniform used in a GLSL shader.
|
||||
The uniform type determines the data type, origin and method
|
||||
of calculation used by Blender to compute the uniform value.
|
||||
|
||||
The calculation of some of the uniforms is based on matrices available in the scene:
|
||||
|
||||
.. _mat4_cam_to_world:
|
||||
.. _mat4_world_to_cam:
|
||||
|
||||
*mat4_cam_to_world*
|
||||
Model matrix of the camera. OpenGL 4x4 matrix that converts
|
||||
camera local coordinates to world coordinates. In blender this is obtained from the
|
||||
'matrix_world' attribute of the camera object.
|
||||
|
||||
Some uniform will need the *mat4_world_to_cam*
|
||||
matrix computed as the inverse of this matrix.
|
||||
|
||||
.. _mat4_object_to_world:
|
||||
.. _mat4_world_to_object:
|
||||
|
||||
*mat4_object_to_world*
|
||||
Model matrix of the object that is being rendered. OpenGL 4x4 matric that converts
|
||||
object local coordinates to world coordinates. In blender this is obtained from the
|
||||
'matrix_world' attribute of the object.
|
||||
|
||||
Some uniform will need the *mat4_world_to_object* matrix, computed as the inverse of this matrix.
|
||||
|
||||
.. _mat4_lamp_to_world:
|
||||
.. _mat4_world_to_lamp:
|
||||
|
||||
*mat4_lamp_to_world*
|
||||
Model matrix of the lamp lighting the object. OpenGL 4x4 matrix that converts lamp
|
||||
local coordinates to world coordinates. In blender this is obtained from the
|
||||
'matrix_world' attribute of the lamp object.
|
||||
|
||||
Some uniform will need the *mat4_world_to_lamp* matrix
|
||||
computed as the inverse of this matrix.
|
||||
|
||||
.. data:: GPU_DYNAMIC_OBJECT_VIEWMAT
|
||||
|
||||
The uniform is a 4x4 GL matrix that converts world coordinates to
|
||||
camera coordinates (see mat4_world_to_cam_). Can be set once per frame.
|
||||
There is at most one uniform of that type per shader.
|
||||
|
||||
:value: 1
|
||||
|
||||
.. data:: GPU_DYNAMIC_OBJECT_MAT
|
||||
|
||||
The uniform is a 4x4 GL matrix that converts object coordinates
|
||||
to world coordinates (see mat4_object_to_world_). Must be set before drawing the object.
|
||||
There is at most one uniform of that type per shader.
|
||||
|
||||
:value: 2
|
||||
|
||||
.. data:: GPU_DYNAMIC_OBJECT_VIEWIMAT
|
||||
|
||||
The uniform is a 4x4 GL matrix that converts coordinates
|
||||
in camera space to world coordinates (see mat4_cam_to_world_).
|
||||
Can be set once per frame.
|
||||
There is at most one uniform of that type per shader.
|
||||
|
||||
:value: 3
|
||||
|
||||
.. data:: GPU_DYNAMIC_OBJECT_IMAT
|
||||
|
||||
The uniform is a 4x4 GL matrix that converts world coodinates
|
||||
to object coordinates (see mat4_world_to_object_).
|
||||
Must be set before drawing the object.
|
||||
There is at most one uniform of that type per shader.
|
||||
|
||||
:value: 4
|
||||
|
||||
.. data:: GPU_DYNAMIC_OBJECT_COLOR
|
||||
|
||||
The uniform is a vector of 4 float representing a RGB color + alpha defined at object level.
|
||||
Each values between 0.0 and 1.0. In blender it corresponds to the 'color' attribute of the object.
|
||||
Must be set before drawing the object.
|
||||
There is at most one uniform of that type per shader.
|
||||
|
||||
:value: 5
|
||||
|
||||
.. data:: GPU_DYNAMIC_LAMP_DYNVEC
|
||||
|
||||
The uniform is a vector of 3 float representing the direction of light in camera space.
|
||||
In Blender, this is computed by
|
||||
|
||||
mat4_world_to_cam_ * (-vec3_lamp_Z_axis)
|
||||
|
||||
as the lamp Z axis points to the opposite direction of light.
|
||||
The norm of the vector should be unity. Can be set once per frame.
|
||||
There is one uniform of that type per lamp lighting the material.
|
||||
|
||||
:value: 6
|
||||
|
||||
.. data:: GPU_DYNAMIC_LAMP_DYNCO
|
||||
|
||||
The uniform is a vector of 3 float representing the position of the light in camera space.
|
||||
Computed as
|
||||
|
||||
mat4_world_to_cam_ * vec3_lamp_pos
|
||||
|
||||
Can be set once per frame.
|
||||
There is one uniform of that type per lamp lighting the material.
|
||||
|
||||
:value: 7
|
||||
|
||||
.. data:: GPU_DYNAMIC_LAMP_DYNIMAT
|
||||
|
||||
The uniform is a 4x4 GL matrix that converts vector in camera space to lamp space.
|
||||
Computed as
|
||||
|
||||
mat4_world_to_lamp_ * mat4_cam_to_world_
|
||||
|
||||
Can be set once per frame.
|
||||
There is one uniform of that type per lamp lighting the material.
|
||||
|
||||
:value: 8
|
||||
|
||||
.. data:: GPU_DYNAMIC_LAMP_DYNPERSMAT
|
||||
|
||||
The uniform is a 4x4 GL matrix that converts a vector in camera space to shadow buffer depth space.
|
||||
Computed as
|
||||
|
||||
mat4_perspective_to_depth_ * mat4_lamp_to_perspective_ * mat4_world_to_lamp_ * mat4_cam_to_world_.
|
||||
|
||||
.. _mat4_perspective_to_depth:
|
||||
|
||||
*mat4_perspective_to_depth* is a fixed matrix defined as follow::
|
||||
|
||||
0.5 0.0 0.0 0.5
|
||||
0.0 0.5 0.0 0.5
|
||||
0.0 0.0 0.5 0.5
|
||||
0.0 0.0 0.0 1.0
|
||||
|
||||
This uniform can be set once per frame. There is one uniform of that type per lamp casting shadow in the scene.
|
||||
|
||||
:value: 9
|
||||
|
||||
.. data:: GPU_DYNAMIC_LAMP_DYNENERGY
|
||||
|
||||
The uniform is a single float representing the lamp energy. In blender it corresponds
|
||||
to the 'energy' attribute of the lamp data block.
|
||||
There is one uniform of that type per lamp lighting the material.
|
||||
|
||||
:value: 10
|
||||
|
||||
.. data:: GPU_DYNAMIC_LAMP_DYNCOL
|
||||
|
||||
The uniform is a vector of 3 float representing the lamp color.
|
||||
Color elements are between 0.0 and 1.0. In blender it corresponds
|
||||
to the 'color' attribute of the lamp data block.
|
||||
There is one uniform of that type per lamp lighting the material.
|
||||
|
||||
:value: 11
|
||||
|
||||
.. data:: GPU_DYNAMIC_SAMPLER_2DBUFFER
|
||||
|
||||
The uniform is an integer representing an internal texture used for certain effect
|
||||
(color band, etc).
|
||||
|
||||
:value: 12
|
||||
|
||||
.. data:: GPU_DYNAMIC_SAMPLER_2DIMAGE
|
||||
|
||||
The uniform is an integer representing a texture loaded from an image file.
|
||||
|
||||
:value: 13
|
||||
|
||||
.. data:: GPU_DYNAMIC_SAMPLER_2DSHADOW
|
||||
|
||||
The uniform is an integer representing a shadow buffer corresponding to a lamp
|
||||
casting shadow.
|
||||
|
||||
:value: 14
|
||||
|
||||
-------------------
|
||||
GLSL attribute type
|
||||
-------------------
|
||||
|
||||
.. _attribute-type:
|
||||
|
||||
Type of the vertex attribute used in the GLSL shader. Determines the mesh custom data
|
||||
layer that contains the vertex attribute.
|
||||
|
||||
.. data:: CD_MTFACE
|
||||
|
||||
Vertex attribute is a UV layer. Data type is vector of 2 float.
|
||||
|
||||
There can be more than one attribute of that type, they are differenciated by name.
|
||||
In blender, you can retrieve the attribute data with:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
mesh.uv_textures[attribute['name']]
|
||||
|
||||
:value: 5
|
||||
|
||||
.. data:: CD_MCOL
|
||||
|
||||
Vertex attribute is color layer. Data type is vector 4 unsigned byte (RGBA).
|
||||
|
||||
There can be more than one attribute of that type, they are differenciated by name.
|
||||
In blender you can retrieve the attribute data with:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
mesh.vertex_colors[attribute['name']]
|
||||
|
||||
:value: 6
|
||||
|
||||
.. data:: CD_ORCO
|
||||
|
||||
Vertex attribute is original coordinates. Data type is vector 3 float.
|
||||
|
||||
There can be only 1 attribute of that type per shader.
|
||||
In blender you can retrieve the attribute data with:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
mesh.vertices
|
||||
|
||||
:value: 14
|
||||
|
||||
.. data:: CD_TANGENT
|
||||
|
||||
Vertex attribute is the tangent vector. Data type is vector 4 float.
|
||||
|
||||
There can be only 1 attribute of that type per shader.
|
||||
There is currently no way to retrieve this attribute data via the RNA API but a standalone
|
||||
C function to compute the tangent layer from the other layers can be obtained from
|
||||
blender.org.
|
||||
|
||||
:value: 18
|
||||
|
||||
*********
|
||||
Functions
|
||||
*********
|
||||
|
||||
.. _export_shader:
|
||||
|
||||
.. function:: export_shader(scene,material)
|
||||
|
||||
Extracts the GLSL shader producing the visual effect of material in scene for the purpose of
|
||||
reusing the shader in an external engine. This function is meant to be used in material exporter
|
||||
so that the GLSL shader can be exported entirely. The return value is a dictionary containing the
|
||||
shader source code and all associated data.
|
||||
|
||||
:arg scene: the scene in which the material in rendered.
|
||||
:type scene: :class:`bpy.types.Scene`
|
||||
:arg material: the material that you want to export the GLSL shader
|
||||
:type material: :class:`bpy.types.Material`
|
||||
:return: the shader source code and all associated data in a dictionary
|
||||
:rtype: dictionary
|
||||
|
||||
The dictionary contains the following elements:
|
||||
|
||||
* ['fragment'] : string
|
||||
fragment shader source code.
|
||||
|
||||
* ['vertex'] : string
|
||||
vertex shader source code.
|
||||
|
||||
* ['uniforms'] : sequence
|
||||
list of uniforms used in fragment shader, can be empty list. Each element of the
|
||||
sequence is a dictionary with the following elements:
|
||||
|
||||
* ['varname'] : string
|
||||
name of the uniform in the fragment shader. Always of the form 'unf<number>'.
|
||||
|
||||
* ['datatype'] : integer
|
||||
data type of the uniform variable. Can be one of the following:
|
||||
|
||||
* :data:`gpu.GPU_DATA_1I` : use glUniform1i
|
||||
* :data:`gpu.GPU_DATA_1F` : use glUniform1fv
|
||||
* :data:`gpu.GPU_DATA_2F` : use glUniform2fv
|
||||
* :data:`gpu.GPU_DATA_3F` : use glUniform3fv
|
||||
* :data:`gpu.GPU_DATA_4F` : use glUniform4fv
|
||||
* :data:`gpu.GPU_DATA_9F` : use glUniformMatrix3fv
|
||||
* :data:`gpu.GPU_DATA_16F` : use glUniformMatrix4fv
|
||||
|
||||
* ['type'] : integer
|
||||
type of uniform, determines the origin and method of calculation. See uniform-type_.
|
||||
Depending on the type, more elements will be be present.
|
||||
|
||||
* ['lamp'] : :class:`bpy.types.Object`
|
||||
Reference to the lamp object from which the uniforms value are extracted. Set for the following uniforms types:
|
||||
|
||||
.. hlist::
|
||||
:columns: 3
|
||||
|
||||
* :data:`gpu.GPU_DYNAMIC_LAMP_DYNVEC`
|
||||
* :data:`gpu.GPU_DYNAMIC_LAMP_DYNCO`
|
||||
* :data:`gpu.GPU_DYNAMIC_LAMP_DYNIMAT`
|
||||
* :data:`gpu.GPU_DYNAMIC_LAMP_DYNPERSMAT`
|
||||
* :data:`gpu.GPU_DYNAMIC_LAMP_DYNENERGY`
|
||||
* :data:`gpu.GPU_DYNAMIC_LAMP_DYNCOL`
|
||||
* :data:`gpu.GPU_DYNAMIC_SAMPLER_2DSHADOW`
|
||||
|
||||
Notes:
|
||||
|
||||
* The uniforms :data:`gpu.GPU_DYNAMIC_LAMP_DYNVEC`, :data:`gpu.GPU_DYNAMIC_LAMP_DYNCO`, :data:`gpu.GPU_DYNAMIC_LAMP_DYNIMAT` and :data:`gpu.GPU_DYNAMIC_LAMP_DYNPERSMAT`
|
||||
refer to the lamp object position and orientation, both of can be derived from the object world matrix:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
obmat = uniform['lamp'].matrix_world
|
||||
|
||||
where obmat is the mat4_lamp_to_world_ matrix of the lamp as a 2 dimensional array,
|
||||
the lamp world location location is in obmat[3].
|
||||
|
||||
* The uniform types :data:`gpu.GPU_DYNAMIC_LAMP_DYNENERGY` and :data:`gpu.GPU_DYNAMIC_LAMP_DYNCOL` refer to the lamp data bloc that you get from:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
la = uniform['lamp'].data
|
||||
|
||||
from which you get la.energy and la.color
|
||||
|
||||
* Lamp duplication is not supported: if you have duplicated lamps in your scene
|
||||
(i.e. lamp that are instantiated by dupligroup, etc), this element will only
|
||||
give you a reference to the orignal lamp and you will not know which instance
|
||||
of the lamp it is refering too. You can still handle that case in the exporter
|
||||
by distributing the uniforms amongst the duplicated lamps.
|
||||
|
||||
* ['image'] : :class:`bpy.types.Image`
|
||||
Reference to the image databloc. Set for uniform type :data:`gpu.GPU_DYNAMIC_SAMPLER_2DIMAGE`. You can get the image data from:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# full path to image file
|
||||
uniform['image'].filepath
|
||||
# image size as a 2-dimensional array of int
|
||||
uniform['image'].size
|
||||
|
||||
* ['texnumber'] : integer
|
||||
Channel number to which the texture is bound when drawing the object.
|
||||
Set for uniform types :data:`gpu.GPU_DYNAMIC_SAMPLER_2DBUFFER`, :data:`gpu.GPU_DYNAMIC_SAMPLER_2DIMAGE` and :data:`gpu.GPU_DYNAMIC_SAMPLER_2DSHADOW`.
|
||||
|
||||
This is provided for information only: when reusing the shader outside blencer,
|
||||
you are free to assign the textures to the channel of your choice and to pass
|
||||
that number channel to the GPU in the uniform.
|
||||
|
||||
* ['texpixels'] : byte array
|
||||
texture data for uniform type :data:`gpu.GPU_DYNAMIC_SAMPLER_2DBUFFER`. Although
|
||||
the corresponding uniform is a 2D sampler, the texture is always a 1D texture
|
||||
of n x 1 pixel. The texture size n is provided in ['texsize'] element.
|
||||
These texture are only used for computer generated texture (colorband, etc).
|
||||
The texture data is provided so that you can make a real image out of it in the
|
||||
exporter.
|
||||
|
||||
* ['texsize'] : integer
|
||||
horizontal size of texture for uniform type :data:`gpu.GPU_DYNAMIC_SAMPLER_2DBUFFER`.
|
||||
The texture data is in ['texpixels'].
|
||||
|
||||
* ['attributes'] : sequence
|
||||
list of attributes used in vertex shader, can be empty. Blender doesn't use
|
||||
standard attributes except for vertex position and normal. All other vertex
|
||||
attributes must be passed using the generic glVertexAttrib functions.
|
||||
The attribute data can be found in the derived mesh custom data using RNA.
|
||||
Each element of the sequence is a dictionary containing the following elements:
|
||||
|
||||
* ['varname'] : string
|
||||
name of the uniform in the vertex shader. Always of the form 'att<number>'.
|
||||
|
||||
* ['datatype'] : integer
|
||||
data type of vertex attribute, can be one of the following:
|
||||
|
||||
* :data:`gpu.GPU_DATA_2F` : use glVertexAttrib2fv
|
||||
* :data:`gpu.GPU_DATA_3F` : use glVertexAttrib3fv
|
||||
* :data:`gpu.GPU_DATA_4F` : use glVertexAttrib4fv
|
||||
* :data:`gpu.GPU_DATA_4UB` : use glVertexAttrib4ubv
|
||||
|
||||
* ['number'] : integer
|
||||
generic attribute number. This is provided for information only. Blender
|
||||
doesn't use glBindAttribLocation to place generic attributes at specific location,
|
||||
it lets the shader compiler place the attributes automatically and query the
|
||||
placement with glGetAttribLocation. The result of this placement is returned in
|
||||
this element.
|
||||
|
||||
When using this shader in a render engine, you should either use
|
||||
glBindAttribLocation to force the attribute at this location or use
|
||||
glGetAttribLocation to get the placement chosen by the compiler of your GPU.
|
||||
|
||||
* ['type'] : integer
|
||||
type of the mesh custom data from which the vertex attribute is loaded.
|
||||
See attribute-type_.
|
||||
|
||||
* ['name'] : string or integer
|
||||
custom data layer name, used for attribute type :data:`gpu.CD_MTFACE` and :data:`gpu.CD_MCOL`.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import gpu
|
||||
# get GLSL shader of material Mat.001 in scene Scene.001
|
||||
scene = bpy.data.scenes['Scene.001']
|
||||
material = bpy.data.materials['Mat.001']
|
||||
shader = gpu.export_shader(scene,material)
|
||||
# scan the uniform list and find the images used in the shader
|
||||
for uniform in shader['uniforms']:
|
||||
if uniform['type'] == gpu.GPU_DYNAMIC_SAMPLER_2DIMAGE:
|
||||
print("uniform {0} is using image {1}".format(uniform['varname'], uniform['image'].filepath))
|
||||
# scan the attribute list and find the UV layer used in the shader
|
||||
for attribute in shader['attributes']:
|
||||
if attribute['type'] == gpu.CD_MTFACE:
|
||||
print("attribute {0} is using UV layer {1}".format(attribute['varname'], attribute['name']))
|
||||
|
||||
*****
|
||||
Notes
|
||||
*****
|
||||
|
||||
.. _mat4_lamp_to_perspective:
|
||||
|
||||
1. Calculation of the *mat4_lamp_to_perspective* matrix for a spot lamp.
|
||||
|
||||
The following pseudo code shows how the *mat4_lamp_to_perspective* matrix is computed
|
||||
in blender for uniforms of :data:`gpu.GPU_DYNAMIC_LAMP_DYNPERSMAT` type::
|
||||
|
||||
#Get the lamp datablock with:
|
||||
lamp=bpy.data.objects[uniform['lamp']].data
|
||||
|
||||
#Compute the projection matrix:
|
||||
# You will need these lamp attributes:
|
||||
# lamp.clipsta : near clip plane in world unit
|
||||
# lamp.clipend : far clip plane in world unit
|
||||
# lamp.spotsize : angle in degree of the spot light
|
||||
|
||||
#The size of the projection plane is computed with the usual formula:
|
||||
wsize = lamp.clista * tan(lamp.spotsize/2)
|
||||
|
||||
#And the projection matrix:
|
||||
mat4_lamp_to_perspective = glFrustum(-wsize,wsize,-wsize,wsize,lamp.clista,lamp.clipend)
|
||||
|
||||
2. Creation of the shadow map for a spot lamp.
|
||||
|
||||
The shadow map is the depth buffer of a render performed by placing the camera at the
|
||||
spot light position. The size of the shadow map is given by the attribute lamp.bufsize :
|
||||
shadow map size in pixel, same size in both dimensions.
|
||||
@@ -768,9 +768,9 @@ class VIEW3D_PT_tools_brush_texture(PaintPanel, Panel):
|
||||
col = row.column()
|
||||
|
||||
if brush.use_texture_overlay:
|
||||
col.prop(brush, "use_texture_overlay", toggle=True, text="", icon='MUTE_IPO_OFF')
|
||||
col.prop(brush, "use_texture_overlay", toggle=True, text="", icon='RESTRICT_VIEW_OFF')
|
||||
else:
|
||||
col.prop(brush, "use_texture_overlay", toggle=True, text="", icon='MUTE_IPO_ON')
|
||||
col.prop(brush, "use_texture_overlay", toggle=True, text="", icon='RESTRICT_VIEW_ON')
|
||||
|
||||
col.active = tex_slot.map_mode in {'FIXED', 'TILED'}
|
||||
|
||||
|
||||
@@ -45,8 +45,13 @@ extern "C" {
|
||||
#define MALWAYS_INLINE MINLINE
|
||||
#else
|
||||
#define MINLINE static inline
|
||||
#if (defined(__APPLE__) && defined(__ppc__))
|
||||
/* static inline __attribute__ here breaks osx ppc gcc42 build */
|
||||
#define MALWAYS_INLINE static __attribute__((always_inline))
|
||||
#else
|
||||
#define MALWAYS_INLINE static inline __attribute__((always_inline))
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#define MINLINE
|
||||
#define MALWAYS_INLINE
|
||||
|
||||
@@ -86,12 +86,25 @@ typedef struct uiWidgetTrias {
|
||||
|
||||
} uiWidgetTrias;
|
||||
|
||||
/* max as used by round_box__edges */
|
||||
#define WIDGET_CURVE_RESOLU 9
|
||||
#define WIDGET_SIZE_MAX (WIDGET_CURVE_RESOLU*4)
|
||||
|
||||
enum {
|
||||
WIDGET_TOP_LEFT= 1,
|
||||
WIDGET_TOP_RIGHT= 2,
|
||||
WIDGET_BOTTOM_RIGHT= 4,
|
||||
WIDGET_BOTTOM_LEFT= 8,
|
||||
/* just for convenience */
|
||||
WIDGET_ALL_CORNERS= (WIDGET_TOP_LEFT | WIDGET_TOP_RIGHT | WIDGET_BOTTOM_RIGHT | WIDGET_BOTTOM_LEFT)
|
||||
};
|
||||
|
||||
typedef struct uiWidgetBase {
|
||||
|
||||
int totvert, halfwayvert;
|
||||
float outer_v[64][2];
|
||||
float inner_v[64][2];
|
||||
float inner_uv[64][2];
|
||||
float outer_v[WIDGET_SIZE_MAX][2];
|
||||
float inner_v[WIDGET_SIZE_MAX][2];
|
||||
float inner_uv[WIDGET_SIZE_MAX][2];
|
||||
|
||||
short inner, outline, emboss; /* set on/off */
|
||||
short shadedir;
|
||||
@@ -123,7 +136,7 @@ typedef struct uiWidgetType {
|
||||
|
||||
/* *********************** draw data ************************** */
|
||||
|
||||
static float cornervec[9][2]= {{0.0, 0.0}, {0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169},
|
||||
static float cornervec[WIDGET_CURVE_RESOLU][2]= {{0.0, 0.0}, {0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169},
|
||||
{0.707, 0.293}, {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}, {1.0, 1.0}};
|
||||
|
||||
static float jit[8][2]= {{0.468813 , -0.481430}, {-0.155755 , -0.352820},
|
||||
@@ -175,6 +188,7 @@ GLubyte checker_stipple_sml[32*32/8] =
|
||||
|
||||
void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3)
|
||||
{
|
||||
float tri_arr[3][2]= {{x1, y1}, {x2, y2}, {x3, y3}};
|
||||
float color[4];
|
||||
int j;
|
||||
|
||||
@@ -183,19 +197,17 @@ void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y
|
||||
color[3] *= 0.125f;
|
||||
glColor4fv(color);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(2, GL_FLOAT, 0, tri_arr);
|
||||
|
||||
/* for each AA step */
|
||||
for(j=0; j<8; j++) {
|
||||
glTranslatef(1.0f * jit[j][0], 1.0f * jit[j][1], 0.0f);
|
||||
|
||||
glBegin(GL_POLYGON);
|
||||
glVertex2f(x1, y1);
|
||||
glVertex2f(x2, y2);
|
||||
glVertex2f(x3, y3);
|
||||
glEnd();
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
glTranslatef(-1.0f * jit[j][0], -1.0f * jit[j][1], 0.0f);
|
||||
}
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
}
|
||||
@@ -216,7 +228,7 @@ static void widget_init(uiWidgetBase *wtb)
|
||||
/* return tot */
|
||||
static int round_box_shadow_edges(float (*vert)[2], rcti *rect, float rad, int roundboxalign, float step)
|
||||
{
|
||||
float vec[9][2];
|
||||
float vec[WIDGET_CURVE_RESOLU][2];
|
||||
float minx, miny, maxx, maxy;
|
||||
int a, tot= 0;
|
||||
|
||||
@@ -231,59 +243,59 @@ static int round_box_shadow_edges(float (*vert)[2], rcti *rect, float rad, int r
|
||||
maxy= rect->ymax+step;
|
||||
|
||||
/* mult */
|
||||
for(a=0; a<9; a++) {
|
||||
for(a=0; a < WIDGET_CURVE_RESOLU; a++) {
|
||||
vec[a][0]= rad*cornervec[a][0];
|
||||
vec[a][1]= rad*cornervec[a][1];
|
||||
}
|
||||
|
||||
/* start with left-top, anti clockwise */
|
||||
if(roundboxalign & 1) {
|
||||
for(a=0; a<9; a++, tot++) {
|
||||
if(roundboxalign & WIDGET_TOP_LEFT) {
|
||||
for(a=0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
|
||||
vert[tot][0]= minx+rad-vec[a][0];
|
||||
vert[tot][1]= maxy-vec[a][1];
|
||||
}
|
||||
}
|
||||
else {
|
||||
for(a=0; a<9; a++, tot++) {
|
||||
for(a=0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
|
||||
vert[tot][0]= minx;
|
||||
vert[tot][1]= maxy;
|
||||
}
|
||||
}
|
||||
|
||||
if(roundboxalign & 8) {
|
||||
for(a=0; a<9; a++, tot++) {
|
||||
if(roundboxalign & WIDGET_BOTTOM_LEFT) {
|
||||
for(a=0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
|
||||
vert[tot][0]= minx+vec[a][1];
|
||||
vert[tot][1]= miny+rad-vec[a][0];
|
||||
}
|
||||
}
|
||||
else {
|
||||
for(a=0; a<9; a++, tot++) {
|
||||
for(a=0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
|
||||
vert[tot][0]= minx;
|
||||
vert[tot][1]= miny;
|
||||
}
|
||||
}
|
||||
|
||||
if(roundboxalign & 4) {
|
||||
for(a=0; a<9; a++, tot++) {
|
||||
if(roundboxalign & WIDGET_BOTTOM_RIGHT) {
|
||||
for(a=0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
|
||||
vert[tot][0]= maxx-rad+vec[a][0];
|
||||
vert[tot][1]= miny+vec[a][1];
|
||||
}
|
||||
}
|
||||
else {
|
||||
for(a=0; a<9; a++, tot++) {
|
||||
for(a=0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
|
||||
vert[tot][0]= maxx;
|
||||
vert[tot][1]= miny;
|
||||
}
|
||||
}
|
||||
|
||||
if(roundboxalign & 2) {
|
||||
for(a=0; a<9; a++, tot++) {
|
||||
if(roundboxalign & WIDGET_TOP_RIGHT) {
|
||||
for(a=0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
|
||||
vert[tot][0]= maxx-vec[a][1];
|
||||
vert[tot][1]= maxy-rad+vec[a][0];
|
||||
}
|
||||
}
|
||||
else {
|
||||
for(a=0; a<9; a++, tot++) {
|
||||
for(a=0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
|
||||
vert[tot][0]= maxx;
|
||||
vert[tot][1]= maxy;
|
||||
}
|
||||
@@ -294,7 +306,7 @@ static int round_box_shadow_edges(float (*vert)[2], rcti *rect, float rad, int r
|
||||
/* this call has 1 extra arg to allow mask outline */
|
||||
static void round_box__edges(uiWidgetBase *wt, int roundboxalign, rcti *rect, float rad, float radi)
|
||||
{
|
||||
float vec[9][2], veci[9][2];
|
||||
float vec[WIDGET_CURVE_RESOLU][2], veci[WIDGET_CURVE_RESOLU][2];
|
||||
float minx= rect->xmin, miny= rect->ymin, maxx= rect->xmax, maxy= rect->ymax;
|
||||
float minxi= minx + 1.0f; /* boundbox inner */
|
||||
float maxxi= maxx - 1.0f;
|
||||
@@ -303,8 +315,10 @@ static void round_box__edges(uiWidgetBase *wt, int roundboxalign, rcti *rect, fl
|
||||
float facxi= (maxxi!=minxi) ? 1.0f/(maxxi-minxi) : 0.0f; /* for uv, can divide by zero */
|
||||
float facyi= (maxyi!=minyi) ? 1.0f/(maxyi-minyi) : 0.0f;
|
||||
int a, tot= 0, minsize;
|
||||
const int hnum= ((roundboxalign & (1|2))==(1|2) || (roundboxalign & (4|8))==(4|8)) ? 1 : 2;
|
||||
const int vnum= ((roundboxalign & (1|8))==(1|8) || (roundboxalign & (2|4))==(2|4)) ? 1 : 2;
|
||||
const int hnum= ((roundboxalign & (WIDGET_TOP_LEFT|WIDGET_TOP_RIGHT))==(WIDGET_TOP_LEFT|WIDGET_TOP_RIGHT) ||
|
||||
(roundboxalign & (WIDGET_BOTTOM_RIGHT|WIDGET_BOTTOM_LEFT))==(WIDGET_BOTTOM_RIGHT|WIDGET_BOTTOM_LEFT)) ? 1 : 2;
|
||||
const int vnum= ((roundboxalign & (WIDGET_TOP_LEFT|WIDGET_BOTTOM_LEFT))==(WIDGET_TOP_LEFT|WIDGET_BOTTOM_LEFT) ||
|
||||
(roundboxalign & (WIDGET_TOP_RIGHT|WIDGET_BOTTOM_RIGHT))==(WIDGET_TOP_RIGHT|WIDGET_BOTTOM_RIGHT)) ? 1 : 2;
|
||||
|
||||
minsize= MIN2((rect->xmax-rect->xmin)*hnum, (rect->ymax-rect->ymin)*vnum);
|
||||
|
||||
@@ -315,7 +329,7 @@ static void round_box__edges(uiWidgetBase *wt, int roundboxalign, rcti *rect, fl
|
||||
radi= 0.5f*minsize - 1.0f;
|
||||
|
||||
/* mult */
|
||||
for(a=0; a<9; a++) {
|
||||
for(a=0; a < WIDGET_CURVE_RESOLU; a++) {
|
||||
veci[a][0]= radi*cornervec[a][0];
|
||||
veci[a][1]= radi*cornervec[a][1];
|
||||
vec[a][0]= rad*cornervec[a][0];
|
||||
@@ -323,9 +337,9 @@ static void round_box__edges(uiWidgetBase *wt, int roundboxalign, rcti *rect, fl
|
||||
}
|
||||
|
||||
/* corner left-bottom */
|
||||
if(roundboxalign & 8) {
|
||||
if(roundboxalign & WIDGET_BOTTOM_LEFT) {
|
||||
|
||||
for(a=0; a<9; a++, tot++) {
|
||||
for(a=0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
|
||||
wt->inner_v[tot][0]= minxi+veci[a][1];
|
||||
wt->inner_v[tot][1]= minyi+radi-veci[a][0];
|
||||
|
||||
@@ -350,9 +364,9 @@ static void round_box__edges(uiWidgetBase *wt, int roundboxalign, rcti *rect, fl
|
||||
}
|
||||
|
||||
/* corner right-bottom */
|
||||
if(roundboxalign & 4) {
|
||||
if(roundboxalign & WIDGET_BOTTOM_RIGHT) {
|
||||
|
||||
for(a=0; a<9; a++, tot++) {
|
||||
for(a=0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
|
||||
wt->inner_v[tot][0]= maxxi-radi+veci[a][0];
|
||||
wt->inner_v[tot][1]= minyi+veci[a][1];
|
||||
|
||||
@@ -379,9 +393,9 @@ static void round_box__edges(uiWidgetBase *wt, int roundboxalign, rcti *rect, fl
|
||||
wt->halfwayvert= tot;
|
||||
|
||||
/* corner right-top */
|
||||
if(roundboxalign & 2) {
|
||||
if(roundboxalign & WIDGET_TOP_RIGHT) {
|
||||
|
||||
for(a=0; a<9; a++, tot++) {
|
||||
for(a=0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
|
||||
wt->inner_v[tot][0]= maxxi-veci[a][1];
|
||||
wt->inner_v[tot][1]= maxyi-radi+veci[a][0];
|
||||
|
||||
@@ -406,9 +420,9 @@ static void round_box__edges(uiWidgetBase *wt, int roundboxalign, rcti *rect, fl
|
||||
}
|
||||
|
||||
/* corner left-top */
|
||||
if(roundboxalign & 1) {
|
||||
if(roundboxalign & WIDGET_TOP_LEFT) {
|
||||
|
||||
for(a=0; a<9; a++, tot++) {
|
||||
for(a=0; a < WIDGET_CURVE_RESOLU; a++, tot++) {
|
||||
wt->inner_v[tot][0]= minxi+radi-veci[a][0];
|
||||
wt->inner_v[tot][1]= maxyi-veci[a][1];
|
||||
|
||||
@@ -434,6 +448,8 @@ static void round_box__edges(uiWidgetBase *wt, int roundboxalign, rcti *rect, fl
|
||||
tot++;
|
||||
}
|
||||
|
||||
BLI_assert(tot <= WIDGET_SIZE_MAX);
|
||||
|
||||
wt->totvert= tot;
|
||||
}
|
||||
|
||||
@@ -516,16 +532,13 @@ static void widget_scroll_circle(uiWidgetTrias *tria, rcti *rect, float triasize
|
||||
|
||||
static void widget_trias_draw(uiWidgetTrias *tria)
|
||||
{
|
||||
int a;
|
||||
|
||||
glBegin(GL_TRIANGLES);
|
||||
for(a=0; a<tria->tot; a++) {
|
||||
glVertex2fv(tria->vec[ tria->index[a][0] ]);
|
||||
glVertex2fv(tria->vec[ tria->index[a][1] ]);
|
||||
glVertex2fv(tria->vec[ tria->index[a][2] ]);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_INDEX_ARRAY);
|
||||
glIndexPointer(GL_INT, 0, tria->index);
|
||||
glVertexPointer(2, GL_FLOAT, 0, tria->vec);
|
||||
glDrawArrays(GL_TRIANGLES, 0, tria->tot*3);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_INDEX_ARRAY);
|
||||
}
|
||||
|
||||
static void widget_menu_trias(uiWidgetTrias *tria, rcti *rect)
|
||||
@@ -601,19 +614,48 @@ static void round_box_shade_col4(const char col1[4], const char col2[4], const f
|
||||
glColor4ubv(col);
|
||||
}
|
||||
|
||||
static void widgetbase_outline(uiWidgetBase *wtb)
|
||||
static void round_box_shade_col4_r(unsigned char col_r[4], const char col1[4], const char col2[4], const float fac)
|
||||
{
|
||||
const int faci= FTOCHAR(fac);
|
||||
const int facm= 255-faci;
|
||||
|
||||
col_r[0]= (faci*col1[0] + facm*col2[0])>>8;
|
||||
col_r[1]= (faci*col1[1] + facm*col2[1])>>8;
|
||||
col_r[2]= (faci*col1[2] + facm*col2[2])>>8;
|
||||
col_r[3]= (faci*col1[3] + facm*col2[3])>>8;
|
||||
}
|
||||
|
||||
static void widget_verts_to_quad_strip(uiWidgetBase *wtb, const int totvert, float quad_strip[WIDGET_SIZE_MAX*2+2][2])
|
||||
{
|
||||
int a;
|
||||
|
||||
/* outline */
|
||||
glBegin(GL_QUAD_STRIP);
|
||||
for(a=0; a<wtb->totvert; a++) {
|
||||
glVertex2fv(wtb->outer_v[a]);
|
||||
glVertex2fv(wtb->inner_v[a]);
|
||||
for(a=0; a<totvert; a++) {
|
||||
copy_v2_v2(quad_strip[a*2], wtb->outer_v[a]);
|
||||
copy_v2_v2(quad_strip[a*2+1], wtb->inner_v[a]);
|
||||
}
|
||||
glVertex2fv(wtb->outer_v[0]);
|
||||
glVertex2fv(wtb->inner_v[0]);
|
||||
glEnd();
|
||||
copy_v2_v2(quad_strip[a*2], wtb->outer_v[0]);
|
||||
copy_v2_v2(quad_strip[a*2+1], wtb->inner_v[0]);
|
||||
}
|
||||
|
||||
static void widget_verts_to_quad_strip_open(uiWidgetBase *wtb, const int totvert, float quad_strip[WIDGET_SIZE_MAX*2][2])
|
||||
{
|
||||
int a;
|
||||
for(a=0; a<totvert; a++) {
|
||||
quad_strip[a*2][0]= wtb->outer_v[a][0];
|
||||
quad_strip[a*2][1]= wtb->outer_v[a][1];
|
||||
quad_strip[a*2+1][0]= wtb->outer_v[a][0];
|
||||
quad_strip[a*2+1][1]= wtb->outer_v[a][1] - 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
static void widgetbase_outline(uiWidgetBase *wtb)
|
||||
{
|
||||
float quad_strip[WIDGET_SIZE_MAX*2+2][2]; /* + 2 because the last pair is wrapped */
|
||||
widget_verts_to_quad_strip(wtb, wtb->totvert, quad_strip);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(2, GL_FLOAT, 0, quad_strip);
|
||||
glDrawArrays(GL_QUAD_STRIP, 0, wtb->totvert*2 + 2);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
|
||||
static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
|
||||
@@ -626,100 +668,124 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
|
||||
if(wtb->inner) {
|
||||
if(wcol->shaded==0) {
|
||||
if (wcol->alpha_check) {
|
||||
float inner_v_half[WIDGET_SIZE_MAX][2];
|
||||
float x_mid= 0.0f; /* used for dumb clamping of values */
|
||||
|
||||
/* dark checkers */
|
||||
glColor4ub(UI_TRANSP_DARK, UI_TRANSP_DARK, UI_TRANSP_DARK, 255);
|
||||
glBegin(GL_POLYGON);
|
||||
for(a=0; a<wtb->totvert; a++) {
|
||||
glVertex2fv(wtb->inner_v[a]);
|
||||
}
|
||||
glEnd();
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v);
|
||||
glDrawArrays(GL_POLYGON, 0, wtb->totvert);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
/* light checkers */
|
||||
glEnable(GL_POLYGON_STIPPLE);
|
||||
glColor4ub(UI_TRANSP_LIGHT, UI_TRANSP_LIGHT, UI_TRANSP_LIGHT, 255);
|
||||
glPolygonStipple(checker_stipple_sml);
|
||||
glBegin(GL_POLYGON);
|
||||
for(a=0; a<wtb->totvert; a++) {
|
||||
glVertex2fv(wtb->inner_v[a]);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v);
|
||||
glDrawArrays(GL_POLYGON, 0, wtb->totvert);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
glDisable(GL_POLYGON_STIPPLE);
|
||||
|
||||
/* alpha fill */
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glColor4ubv((unsigned char*)wcol->inner);
|
||||
glBegin(GL_POLYGON);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
for(a=0; a<wtb->totvert; a++) {
|
||||
glVertex2fv(wtb->inner_v[a]);
|
||||
x_mid += wtb->inner_v[a][0];
|
||||
}
|
||||
x_mid /= wtb->totvert;
|
||||
glEnd();
|
||||
|
||||
glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v);
|
||||
glDrawArrays(GL_POLYGON, 0, wtb->totvert);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
/* 1/2 solid color */
|
||||
glColor4ub(wcol->inner[0], wcol->inner[1], wcol->inner[2], 255);
|
||||
glBegin(GL_POLYGON);
|
||||
for(a=0; a<wtb->totvert; a++)
|
||||
glVertex2f(MIN2(wtb->inner_v[a][0], x_mid), wtb->inner_v[a][1]);
|
||||
glEnd();
|
||||
|
||||
for(a=0; a<wtb->totvert; a++) {
|
||||
inner_v_half[a][0]= MIN2(wtb->inner_v[a][0], x_mid);
|
||||
inner_v_half[a][1]= wtb->inner_v[a][1];
|
||||
}
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(2, GL_FLOAT, 0, inner_v_half);
|
||||
glDrawArrays(GL_POLYGON, 0, wtb->totvert);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
else {
|
||||
/* simple fill */
|
||||
glColor4ubv((unsigned char*)wcol->inner);
|
||||
glBegin(GL_POLYGON);
|
||||
for(a=0; a<wtb->totvert; a++)
|
||||
glVertex2fv(wtb->inner_v[a]);
|
||||
glEnd();
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v);
|
||||
glDrawArrays(GL_POLYGON, 0, wtb->totvert);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
}
|
||||
else {
|
||||
char col1[4], col2[4];
|
||||
unsigned char col_array[WIDGET_SIZE_MAX * 4];
|
||||
unsigned char *col_pt= col_array;
|
||||
|
||||
shadecolors4(col1, col2, wcol->inner, wcol->shadetop, wcol->shadedown);
|
||||
|
||||
glShadeModel(GL_SMOOTH);
|
||||
glBegin(GL_POLYGON);
|
||||
for(a=0; a<wtb->totvert; a++) {
|
||||
round_box_shade_col4(col1, col2, wtb->inner_uv[a][wtb->shadedir]);
|
||||
glVertex2fv(wtb->inner_v[a]);
|
||||
for(a=0; a<wtb->totvert; a++, col_pt += 4) {
|
||||
round_box_shade_col4_r(col_pt, col1, col2, wtb->inner_uv[a][wtb->shadedir]);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v);
|
||||
glColorPointer(4, GL_UNSIGNED_BYTE, 0, col_array);
|
||||
glDrawArrays(GL_POLYGON, 0, wtb->totvert);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
glShadeModel(GL_FLAT);
|
||||
}
|
||||
}
|
||||
|
||||
/* for each AA step */
|
||||
if(wtb->outline) {
|
||||
float quad_strip[WIDGET_SIZE_MAX*2+2][2]; /* + 2 because the last pair is wrapped */
|
||||
float quad_strip_emboss[WIDGET_SIZE_MAX*2][2]; /* only for emboss */
|
||||
|
||||
widget_verts_to_quad_strip(wtb, wtb->totvert, quad_strip);
|
||||
|
||||
if(wtb->emboss) {
|
||||
widget_verts_to_quad_strip_open(wtb, wtb->halfwayvert, quad_strip_emboss);
|
||||
}
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
for(j=0; j<8; j++) {
|
||||
glTranslatef(1.0f * jit[j][0], 1.0f * jit[j][1], 0.0f);
|
||||
|
||||
/* outline */
|
||||
glColor4ub(wcol->outline[0], wcol->outline[1], wcol->outline[2], 32);
|
||||
glBegin(GL_QUAD_STRIP);
|
||||
for(a=0; a<wtb->totvert; a++) {
|
||||
glVertex2fv(wtb->outer_v[a]);
|
||||
glVertex2fv(wtb->inner_v[a]);
|
||||
}
|
||||
glVertex2fv(wtb->outer_v[0]);
|
||||
glVertex2fv(wtb->inner_v[0]);
|
||||
glEnd();
|
||||
|
||||
glVertexPointer(2, GL_FLOAT, 0, quad_strip);
|
||||
glDrawArrays(GL_QUAD_STRIP, 0, wtb->totvert*2 + 2);
|
||||
|
||||
/* emboss bottom shadow */
|
||||
if(wtb->emboss) {
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 0.02f);
|
||||
glBegin(GL_QUAD_STRIP);
|
||||
for(a=0; a<wtb->halfwayvert; a++) {
|
||||
glVertex2fv(wtb->outer_v[a]);
|
||||
glVertex2f(wtb->outer_v[a][0], wtb->outer_v[a][1]-1.0f);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glVertexPointer(2, GL_FLOAT, 0, quad_strip_emboss);
|
||||
glDrawArrays(GL_QUAD_STRIP, 0, wtb->halfwayvert*2);
|
||||
}
|
||||
|
||||
glTranslatef(-1.0f * jit[j][0], -1.0f * jit[j][1], 0.0f);
|
||||
}
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
|
||||
/* decoration */
|
||||
@@ -1611,7 +1677,8 @@ static void widget_softshadow(rcti *rect, int roundboxalign, float radin, float
|
||||
uiWidgetBase wtb;
|
||||
rcti rect1= *rect;
|
||||
float alpha, alphastep;
|
||||
int step, tot, a;
|
||||
int step, totvert;
|
||||
float quad_strip[WIDGET_SIZE_MAX*2][2];
|
||||
|
||||
/* prevent tooltips to not show round shadow */
|
||||
if( 2.0f*radout > 0.2f*(rect1.ymax-rect1.ymin) )
|
||||
@@ -1620,31 +1687,32 @@ static void widget_softshadow(rcti *rect, int roundboxalign, float radin, float
|
||||
rect1.ymax -= 2.0f*radout;
|
||||
|
||||
/* inner part */
|
||||
tot= round_box_shadow_edges(wtb.inner_v, &rect1, radin, roundboxalign & 12, 0.0f);
|
||||
totvert= round_box_shadow_edges(wtb.inner_v, &rect1, radin, roundboxalign & (WIDGET_BOTTOM_RIGHT | WIDGET_BOTTOM_LEFT), 0.0f);
|
||||
|
||||
/* inverse linear shadow alpha */
|
||||
alpha= 0.15;
|
||||
alphastep= 0.67;
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
for(step= 1; step<=radout; step++, alpha*=alphastep) {
|
||||
round_box_shadow_edges(wtb.outer_v, &rect1, radin, 15, (float)step);
|
||||
round_box_shadow_edges(wtb.outer_v, &rect1, radin, WIDGET_ALL_CORNERS, (float)step);
|
||||
|
||||
glColor4f(0.0f, 0.0f, 0.0f, alpha);
|
||||
|
||||
glBegin(GL_QUAD_STRIP);
|
||||
for(a=0; a<tot; a++) {
|
||||
glVertex2fv(wtb.outer_v[a]);
|
||||
glVertex2fv(wtb.inner_v[a]);
|
||||
}
|
||||
glEnd();
|
||||
widget_verts_to_quad_strip_open(&wtb, totvert, quad_strip);
|
||||
|
||||
glVertexPointer(2, GL_FLOAT, 0, quad_strip);
|
||||
glDrawArrays(GL_QUAD_STRIP, 0, totvert*2);
|
||||
}
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
|
||||
static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int direction)
|
||||
{
|
||||
uiWidgetBase wtb;
|
||||
int roundboxalign= 15;
|
||||
int roundboxalign= WIDGET_ALL_CORNERS;
|
||||
|
||||
widget_init(&wtb);
|
||||
|
||||
@@ -1654,11 +1722,11 @@ static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int dir
|
||||
//rect->ymax += 4.0;
|
||||
}
|
||||
else if (direction == UI_DOWN) {
|
||||
roundboxalign= 12;
|
||||
roundboxalign= (WIDGET_BOTTOM_RIGHT | WIDGET_BOTTOM_LEFT);
|
||||
rect->ymin -= 4.0;
|
||||
}
|
||||
else if (direction == UI_TOP) {
|
||||
roundboxalign= 3;
|
||||
roundboxalign= WIDGET_TOP_LEFT | WIDGET_TOP_RIGHT;
|
||||
rect->ymax += 4.0;
|
||||
}
|
||||
|
||||
@@ -2008,7 +2076,7 @@ static void ui_draw_but_HSV_v(uiBut *but, rcti *rect)
|
||||
widget_init(&wtb);
|
||||
|
||||
/* fully rounded */
|
||||
round_box_edges(&wtb, 15, rect, rad);
|
||||
round_box_edges(&wtb, WIDGET_ALL_CORNERS, rect, rad);
|
||||
|
||||
/* setup temp colors */
|
||||
wcol_tmp.outline[0]= wcol_tmp.outline[1]= wcol_tmp.outline[2]= 0;
|
||||
@@ -2107,16 +2175,14 @@ void ui_draw_link_bezier(rcti *rect)
|
||||
if(ui_link_bezier_points(rect, coord_array, LINK_RESOL)) {
|
||||
/* we can reuse the dist variable here to increment the GL curve eval amount*/
|
||||
// const float dist= 1.0f/(float)LINK_RESOL; // UNUSED
|
||||
int i;
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
|
||||
glBegin(GL_LINE_STRIP);
|
||||
for(i=0; i<=LINK_RESOL; i++) {
|
||||
glVertex2fv(coord_array[i]);
|
||||
}
|
||||
glEnd();
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(2, GL_FLOAT, 0, coord_array);
|
||||
glDrawArrays(GL_LINE_STRIP, 0, LINK_RESOL);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_LINE_SMOOTH);
|
||||
@@ -2148,7 +2214,7 @@ void uiWidgetScrollDraw(uiWidgetColors *wcol, rcti *rect, rcti *slider, int stat
|
||||
if(horizontal)
|
||||
SWAP(short, wcol->shadetop, wcol->shadedown);
|
||||
|
||||
round_box_edges(&wtb, 15, rect, rad);
|
||||
round_box_edges(&wtb, WIDGET_ALL_CORNERS, rect, rad);
|
||||
widgetbase_draw(&wtb, wcol);
|
||||
|
||||
/* slider */
|
||||
@@ -2176,7 +2242,7 @@ void uiWidgetScrollDraw(uiWidgetColors *wcol, rcti *rect, rcti *slider, int stat
|
||||
if (state & UI_SCROLL_NO_OUTLINE)
|
||||
SWAP(short, outline, wtb.outline);
|
||||
|
||||
round_box_edges(&wtb, 15, slider, rad);
|
||||
round_box_edges(&wtb, WIDGET_ALL_CORNERS, slider, rad);
|
||||
|
||||
if(state & UI_SCROLL_ARROWS) {
|
||||
if(wcol->item[0] > 48) wcol->item[0]-= 48;
|
||||
@@ -2343,7 +2409,7 @@ static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int s
|
||||
|
||||
/* left part of slider, always rounded */
|
||||
rect1.xmax= rect1.xmin + ceil(offs+1.0f);
|
||||
round_box_edges(&wtb1, roundboxalign & ~6, &rect1, offs);
|
||||
round_box_edges(&wtb1, roundboxalign & ~(WIDGET_TOP_RIGHT | WIDGET_BOTTOM_RIGHT), &rect1, offs);
|
||||
wtb1.outline= 0;
|
||||
widgetbase_draw(&wtb1, wcol);
|
||||
|
||||
@@ -2354,7 +2420,7 @@ static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int s
|
||||
offs*= (rect1.xmax + offs - rect->xmax)/offs;
|
||||
else
|
||||
offs= 0.0f;
|
||||
round_box_edges(&wtb1, roundboxalign & ~9, &rect1, offs);
|
||||
round_box_edges(&wtb1, roundboxalign & ~(WIDGET_TOP_LEFT | WIDGET_BOTTOM_LEFT), &rect1, offs);
|
||||
|
||||
widgetbase_draw(&wtb1, wcol);
|
||||
VECCOPY(wcol->outline, outline);
|
||||
@@ -2436,7 +2502,7 @@ static void widget_icon_has_anim(uiBut *UNUSED(but), uiWidgetColors *wcol, rcti
|
||||
wtb.outline= 0;
|
||||
|
||||
/* rounded */
|
||||
round_box_edges(&wtb, 15, rect, 10.0f);
|
||||
round_box_edges(&wtb, WIDGET_ALL_CORNERS, rect, 10.0f);
|
||||
widgetbase_draw(&wtb, wcol);
|
||||
}
|
||||
}
|
||||
@@ -2499,7 +2565,7 @@ static void widget_pulldownbut(uiWidgetColors *wcol, rcti *rect, int state, int
|
||||
widget_init(&wtb);
|
||||
|
||||
/* half rounded */
|
||||
round_box_edges(&wtb, 15, rect, rad);
|
||||
round_box_edges(&wtb, WIDGET_ALL_CORNERS, rect, rad);
|
||||
|
||||
widgetbase_draw(&wtb, wcol);
|
||||
}
|
||||
@@ -2526,7 +2592,7 @@ static void widget_list_itembut(uiWidgetColors *wcol, rcti *rect, int UNUSED(sta
|
||||
|
||||
/* rounded, but no outline */
|
||||
wtb.outline= 0;
|
||||
round_box_edges(&wtb, 15, rect, 4.0f);
|
||||
round_box_edges(&wtb, WIDGET_ALL_CORNERS, rect, 4.0f);
|
||||
|
||||
widgetbase_draw(&wtb, wcol);
|
||||
}
|
||||
@@ -2550,7 +2616,7 @@ static void widget_optionbut(uiWidgetColors *wcol, rcti *rect, int state, int UN
|
||||
recttemp.ymax-= delta;
|
||||
|
||||
/* half rounded */
|
||||
round_box_edges(&wtb, 15, &recttemp, 4.0f);
|
||||
round_box_edges(&wtb, WIDGET_ALL_CORNERS, &recttemp, 4.0f);
|
||||
|
||||
/* decoration */
|
||||
if(state & UI_SELECT) {
|
||||
@@ -2650,12 +2716,12 @@ static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType *
|
||||
UI_GetThemeColor3ubv(TH_BACK, col);
|
||||
glColor3ubv(col);
|
||||
|
||||
round_box__edges(&wtb, 15, rect, 0.0f, 4.0);
|
||||
round_box__edges(&wtb, WIDGET_ALL_CORNERS, rect, 0.0f, 4.0);
|
||||
widgetbase_outline(&wtb);
|
||||
}
|
||||
|
||||
/* outline */
|
||||
round_box_edges(&wtb, 15, rect, 5.0f);
|
||||
round_box_edges(&wtb, WIDGET_ALL_CORNERS, rect, 5.0f);
|
||||
wtb.outline= 1;
|
||||
wtb.inner= 0;
|
||||
widgetbase_draw(&wtb, &wt->wcol);
|
||||
@@ -2836,37 +2902,27 @@ static int widget_roundbox_set(uiBut *but, rcti *rect)
|
||||
|
||||
switch(but->flag & UI_BUT_ALIGN) {
|
||||
case UI_BUT_ALIGN_TOP:
|
||||
return (12);
|
||||
break;
|
||||
return WIDGET_BOTTOM_LEFT | WIDGET_BOTTOM_RIGHT;
|
||||
case UI_BUT_ALIGN_DOWN:
|
||||
return (3);
|
||||
break;
|
||||
return WIDGET_TOP_LEFT | WIDGET_TOP_RIGHT;
|
||||
case UI_BUT_ALIGN_LEFT:
|
||||
return (6);
|
||||
break;
|
||||
return WIDGET_TOP_RIGHT | WIDGET_BOTTOM_RIGHT;
|
||||
case UI_BUT_ALIGN_RIGHT:
|
||||
return (9);
|
||||
break;
|
||||
|
||||
return WIDGET_TOP_LEFT | WIDGET_BOTTOM_LEFT;
|
||||
case UI_BUT_ALIGN_DOWN | UI_BUT_ALIGN_RIGHT:
|
||||
return (1);
|
||||
break;
|
||||
return WIDGET_TOP_LEFT;
|
||||
case UI_BUT_ALIGN_DOWN | UI_BUT_ALIGN_LEFT:
|
||||
return (2);
|
||||
break;
|
||||
return WIDGET_TOP_RIGHT;
|
||||
case UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_RIGHT:
|
||||
return (8);
|
||||
break;
|
||||
return WIDGET_BOTTOM_LEFT;
|
||||
case UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_LEFT:
|
||||
return (4);
|
||||
break;
|
||||
|
||||
return WIDGET_BOTTOM_RIGHT;
|
||||
default:
|
||||
return (0);
|
||||
break;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 15;
|
||||
|
||||
return WIDGET_ALL_CORNERS;
|
||||
}
|
||||
|
||||
/* conversion from old to new buttons, so still messy */
|
||||
@@ -3104,14 +3160,14 @@ void ui_draw_search_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect)
|
||||
uiWidgetType *wt= widget_type(UI_WTYPE_BOX);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
widget_softshadow(rect, 15, 5.0f, 8.0f);
|
||||
widget_softshadow(rect, WIDGET_ALL_CORNERS, 5.0f, 8.0f);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
wt->state(wt, 0);
|
||||
if(block)
|
||||
wt->draw(&wt->wcol, rect, block->flag, 15);
|
||||
wt->draw(&wt->wcol, rect, block->flag, WIDGET_ALL_CORNERS);
|
||||
else
|
||||
wt->draw(&wt->wcol, rect, 0, 15);
|
||||
wt->draw(&wt->wcol, rect, 0, WIDGET_ALL_CORNERS);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -121,6 +121,20 @@ void ED_base_object_activate(bContext *C, Base *base)
|
||||
|
||||
/********************** Selection Operators **********************/
|
||||
|
||||
static int objects_selectable_poll(bContext *C)
|
||||
{
|
||||
/* we don't check for linked scenes here, selection is
|
||||
still allowed then for inspection of scene */
|
||||
Object *obact= CTX_data_active_object(C);
|
||||
|
||||
if(CTX_data_edit_object(C))
|
||||
return 0;
|
||||
if(obact && obact->mode)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/************************ Select by Type *************************/
|
||||
|
||||
static int object_select_by_type_exec(bContext *C, wmOperator *op)
|
||||
@@ -159,7 +173,7 @@ void OBJECT_OT_select_by_type(wmOperatorType *ot)
|
||||
/* api callbacks */
|
||||
ot->invoke= WM_menu_invoke;
|
||||
ot->exec= object_select_by_type_exec;
|
||||
ot->poll= ED_operator_objectmode;
|
||||
ot->poll= objects_selectable_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -341,7 +355,7 @@ void OBJECT_OT_select_linked(wmOperatorType *ot)
|
||||
/* api callbacks */
|
||||
ot->invoke= WM_menu_invoke;
|
||||
ot->exec= object_select_linked_exec;
|
||||
ot->poll= ED_operator_objectmode;
|
||||
ot->poll= objects_selectable_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -667,7 +681,7 @@ void OBJECT_OT_select_grouped(wmOperatorType *ot)
|
||||
/* api callbacks */
|
||||
ot->invoke= WM_menu_invoke;
|
||||
ot->exec= object_select_grouped_exec;
|
||||
ot->poll= ED_operator_objectmode;
|
||||
ot->poll= objects_selectable_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -716,7 +730,7 @@ void OBJECT_OT_select_by_layer(wmOperatorType *ot)
|
||||
/* api callbacks */
|
||||
/*ot->invoke = XXX - need a int grid popup*/
|
||||
ot->exec= object_select_by_layer_exec;
|
||||
ot->poll= ED_operator_objectmode;
|
||||
ot->poll= objects_selectable_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -754,7 +768,7 @@ void OBJECT_OT_select_inverse(wmOperatorType *ot)
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= object_select_inverse_exec;
|
||||
ot->poll= ED_operator_objectmode;
|
||||
ot->poll= objects_selectable_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -815,7 +829,7 @@ void OBJECT_OT_select_all(wmOperatorType *ot)
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= object_select_all_exec;
|
||||
ot->poll= ED_operator_objectmode;
|
||||
ot->poll= objects_selectable_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -864,7 +878,7 @@ void OBJECT_OT_select_same_group(wmOperatorType *ot)
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= object_select_same_group_exec;
|
||||
ot->poll= ED_operator_objectmode;
|
||||
ot->poll= objects_selectable_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -917,7 +931,7 @@ void OBJECT_OT_select_mirror(wmOperatorType *ot)
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= object_select_mirror_exec;
|
||||
ot->poll= ED_operator_objectmode;
|
||||
ot->poll= objects_selectable_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -974,7 +988,7 @@ void OBJECT_OT_select_name(wmOperatorType *ot)
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= object_select_name_exec;
|
||||
ot->poll= ED_operator_objectmode;
|
||||
ot->poll= objects_selectable_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
@@ -1022,7 +1036,7 @@ void OBJECT_OT_select_random(wmOperatorType *ot)
|
||||
/* api callbacks */
|
||||
/*ot->invoke= object_select_random_invoke XXX - need a number popup ;*/
|
||||
ot->exec = object_select_random_exec;
|
||||
ot->poll= ED_operator_objectmode;
|
||||
ot->poll= objects_selectable_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
|
||||
@@ -3483,8 +3483,8 @@ void ED_keymap_screen(wmKeyConfig *keyconf)
|
||||
|
||||
RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", UPARROWKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0)->ptr, "end", 1);
|
||||
RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", DOWNARROWKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0)->ptr, "end", 0);
|
||||
RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", RIGHTARROWKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0)->ptr, "end", 1);
|
||||
RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", LEFTARROWKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0)->ptr, "end", 0);
|
||||
RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", RIGHTARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "end", 1);
|
||||
RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", LEFTARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "end", 0);
|
||||
|
||||
WM_keymap_add_item(keymap, "SCREEN_OT_keyframe_jump", UPARROWKEY, KM_PRESS, 0, 0);
|
||||
RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_keyframe_jump", DOWNARROWKEY, KM_PRESS, 0, 0)->ptr, "next", 0);
|
||||
|
||||
@@ -322,8 +322,8 @@ static int load_tex(Sculpt *sd, Brush* br, ViewContext* vc)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
if (br->mtex.brush_map_mode == MTEX_MAP_MODE_FIXED) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
@@ -97,7 +97,7 @@ static void outliner_height(SpaceOops *soops, ListBase *lb, int *h)
|
||||
TreeElement *te= lb->first;
|
||||
while(te) {
|
||||
TreeStoreElem *tselem= TREESTORE(te);
|
||||
if((tselem->flag & TSE_CLOSED)==0)
|
||||
if(TSELEM_OPEN(tselem,soops))
|
||||
outliner_height(soops, &te->subtree, h);
|
||||
(*h) += UI_UNIT_Y;
|
||||
te= te->next;
|
||||
@@ -112,7 +112,7 @@ static void outliner_width(SpaceOops *soops, ListBase *lb, int *w)
|
||||
// TreeStoreElem *tselem= TREESTORE(te);
|
||||
|
||||
// XXX fixme... te->xend is not set yet
|
||||
if(tselem->flag & TSE_CLOSED) {
|
||||
if(!TSELEM_OPEN(tselem,soops)) {
|
||||
if (te->xend > *w)
|
||||
*w = te->xend;
|
||||
}
|
||||
@@ -135,7 +135,7 @@ static void outliner_rna_width(SpaceOops *soops, ListBase *lb, int *w, int start
|
||||
if(startx+100 > *w)
|
||||
*w = startx+100;
|
||||
|
||||
if((tselem->flag & TSE_CLOSED)==0)
|
||||
if(TSELEM_OPEN(tselem,soops))
|
||||
outliner_rna_width(soops, &te->subtree, w, startx+UI_UNIT_X);
|
||||
te= te->next;
|
||||
}
|
||||
@@ -519,7 +519,7 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
|
||||
}
|
||||
}
|
||||
|
||||
if((tselem->flag & TSE_CLOSED)==0) outliner_draw_restrictbuts(block, scene, ar, soops, &te->subtree);
|
||||
if(TSELEM_OPEN(tselem,soops)) outliner_draw_restrictbuts(block, scene, ar, soops, &te->subtree);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -560,7 +560,7 @@ static void outliner_draw_rnabuts(uiBlock *block, Scene *scene, ARegion *ar, Spa
|
||||
ptr= &te->rnaptr;
|
||||
prop= te->directdata;
|
||||
|
||||
if(!(RNA_property_type(prop) == PROP_POINTER && (tselem->flag & TSE_CLOSED)==0))
|
||||
if(!(RNA_property_type(prop) == PROP_POINTER && (TSELEM_OPEN(tselem,soops))) )
|
||||
uiDefAutoButR(block, ptr, prop, -1, "", ICON_NONE, sizex, (int)te->ys, OL_RNA_COL_SIZEX, UI_UNIT_Y-1);
|
||||
}
|
||||
else if(tselem->type == TSE_RNA_ARRAY_ELEM) {
|
||||
@@ -571,7 +571,7 @@ static void outliner_draw_rnabuts(uiBlock *block, Scene *scene, ARegion *ar, Spa
|
||||
}
|
||||
}
|
||||
|
||||
if((tselem->flag & TSE_CLOSED)==0) outliner_draw_rnabuts(block, scene, ar, soops, sizex, &te->subtree);
|
||||
if(TSELEM_OPEN(tselem,soops)) outliner_draw_rnabuts(block, scene, ar, soops, sizex, &te->subtree);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -828,7 +828,7 @@ static void outliner_draw_keymapbuts(uiBlock *block, ARegion *ar, SpaceOops *soo
|
||||
}
|
||||
}
|
||||
|
||||
if((tselem->flag & TSE_CLOSED)==0) outliner_draw_keymapbuts(block, ar, soops, &te->subtree);
|
||||
if(TSELEM_OPEN(tselem,soops)) outliner_draw_keymapbuts(block, ar, soops, &te->subtree);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -871,7 +871,7 @@ static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, Spa
|
||||
}
|
||||
}
|
||||
|
||||
if((tselem->flag & TSE_CLOSED)==0) outliner_buttons(C, block, ar, soops, &te->subtree);
|
||||
if(TSELEM_OPEN(tselem,soops)) outliner_buttons(C, block, ar, soops, &te->subtree);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1237,6 +1237,18 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
/* start by highlighting search matches
|
||||
* we don't expand items when searching in the datablocks but we
|
||||
* still want to highlight any filter matches.
|
||||
*/
|
||||
if ( (SEARCHING_OUTLINER(soops) || (soops->outlinevis==SO_DATABLOCKS && soops->search_string[0]!=0)) &&
|
||||
(tselem->flag & TSE_SEARCHMATCH))
|
||||
{
|
||||
/* TODO - add search highlight colour to theme? */
|
||||
glColor4f(0.2f, 0.5f, 0.2f, 0.3f);
|
||||
glRecti(startx, *starty+1, ar->v2d.cur.xmax, *starty+UI_UNIT_Y-1);
|
||||
}
|
||||
|
||||
/* colors for active/selected data */
|
||||
if(tselem->type==0) {
|
||||
if(te->idcode==ID_SCE) {
|
||||
@@ -1317,10 +1329,10 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene
|
||||
icon_x = startx+5*ufac;
|
||||
|
||||
// icons a bit higher
|
||||
if(tselem->flag & TSE_CLOSED)
|
||||
UI_icon_draw((float)icon_x, (float)*starty+2*ufac, ICON_DISCLOSURE_TRI_RIGHT);
|
||||
else
|
||||
if(TSELEM_OPEN(tselem,soops))
|
||||
UI_icon_draw((float)icon_x, (float)*starty+2*ufac, ICON_DISCLOSURE_TRI_DOWN);
|
||||
else
|
||||
UI_icon_draw((float)icon_x, (float)*starty+2*ufac, ICON_DISCLOSURE_TRI_RIGHT);
|
||||
}
|
||||
offsx+= UI_UNIT_X;
|
||||
|
||||
@@ -1356,7 +1368,7 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene
|
||||
offsx+= (int)(UI_UNIT_X + UI_GetStringWidth(te->name));
|
||||
|
||||
/* closed item, we draw the icons, not when it's a scene, or master-server list though */
|
||||
if(tselem->flag & TSE_CLOSED) {
|
||||
if(!TSELEM_OPEN(tselem,soops)) {
|
||||
if(te->subtree.first) {
|
||||
if(tselem->type==0 && te->idcode==ID_SCE);
|
||||
else if(tselem->type!=TSE_R_LAYER) { /* this tree element always has same amount of branches, so dont draw */
|
||||
@@ -1382,7 +1394,7 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene
|
||||
te->ys= (float)*starty;
|
||||
te->xend= startx+offsx;
|
||||
|
||||
if((tselem->flag & TSE_CLOSED)==0) {
|
||||
if(TSELEM_OPEN(tselem,soops)) {
|
||||
*starty-= UI_UNIT_Y;
|
||||
|
||||
for(ten= te->subtree.first; ten; ten= ten->next)
|
||||
@@ -1415,7 +1427,7 @@ static void outliner_draw_hierarchy(SpaceOops *soops, ListBase *lb, int startx,
|
||||
|
||||
*starty-= UI_UNIT_Y;
|
||||
|
||||
if((tselem->flag & TSE_CLOSED)==0)
|
||||
if(TSELEM_OPEN(tselem,soops))
|
||||
outliner_draw_hierarchy(soops, &te->subtree, startx+UI_UNIT_X, starty);
|
||||
}
|
||||
|
||||
@@ -1439,12 +1451,12 @@ static void outliner_draw_struct_marks(ARegion *ar, SpaceOops *soops, ListBase *
|
||||
tselem= TREESTORE(te);
|
||||
|
||||
/* selection status */
|
||||
if((tselem->flag & TSE_CLOSED)==0)
|
||||
if(TSELEM_OPEN(tselem,soops))
|
||||
if(tselem->type == TSE_RNA_STRUCT)
|
||||
glRecti(0, *starty+1, (int)ar->v2d.cur.xmax+V2D_SCROLL_WIDTH, *starty+UI_UNIT_Y-1);
|
||||
|
||||
*starty-= UI_UNIT_Y;
|
||||
if((tselem->flag & TSE_CLOSED)==0) {
|
||||
if(TSELEM_OPEN(tselem,soops)) {
|
||||
outliner_draw_struct_marks(ar, soops, &te->subtree, starty);
|
||||
if(tselem->type == TSE_RNA_STRUCT)
|
||||
fdrawline(0, (float)*starty+UI_UNIT_Y, ar->v2d.cur.xmax+V2D_SCROLL_WIDTH, (float)*starty+UI_UNIT_Y);
|
||||
@@ -1465,7 +1477,7 @@ static void outliner_draw_selection(ARegion *ar, SpaceOops *soops, ListBase *lb,
|
||||
glRecti(0, *starty+1, (int)ar->v2d.cur.xmax, *starty+UI_UNIT_Y-1);
|
||||
}
|
||||
*starty-= UI_UNIT_Y;
|
||||
if((tselem->flag & TSE_CLOSED)==0) outliner_draw_selection(ar, soops, &te->subtree, starty);
|
||||
if(TSELEM_OPEN(tselem,soops)) outliner_draw_selection(ar, soops, &te->subtree, starty);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -687,7 +687,7 @@ static void outliner_set_coordinates_element(SpaceOops *soops, TreeElement *te,
|
||||
te->ys= (float)(*starty);
|
||||
*starty-= UI_UNIT_Y;
|
||||
|
||||
if((tselem->flag & TSE_CLOSED)==0) {
|
||||
if(TSELEM_OPEN(tselem,soops)) {
|
||||
TreeElement *ten;
|
||||
for(ten= te->subtree.first; ten; ten= ten->next) {
|
||||
outliner_set_coordinates_element(soops, ten, startx+UI_UNIT_X, starty);
|
||||
@@ -910,7 +910,7 @@ static void tree_element_show_hierarchy(Scene *scene, SpaceOops *soops, ListBase
|
||||
}
|
||||
else tselem->flag |= TSE_CLOSED;
|
||||
|
||||
if(tselem->flag & TSE_CLOSED); else tree_element_show_hierarchy(scene, soops, &te->subtree);
|
||||
if(TSELEM_OPEN(tselem,soops)) tree_element_show_hierarchy(scene, soops, &te->subtree);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1175,7 +1175,7 @@ static void do_outliner_drivers_editop(SpaceOops *soops, ListBase *tree, ReportL
|
||||
}
|
||||
|
||||
/* go over sub-tree */
|
||||
if ((tselem->flag & TSE_CLOSED)==0)
|
||||
if (TSELEM_OPEN(tselem,soops))
|
||||
do_outliner_drivers_editop(soops, &te->subtree, reports, mode);
|
||||
}
|
||||
}
|
||||
@@ -1343,7 +1343,7 @@ static void do_outliner_keyingset_editop(SpaceOops *soops, KeyingSet *ks, ListBa
|
||||
}
|
||||
|
||||
/* go over sub-tree */
|
||||
if ((tselem->flag & TSE_CLOSED)==0)
|
||||
if (TSELEM_OPEN(tselem,soops))
|
||||
do_outliner_keyingset_editop(soops, ks, &te->subtree, mode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,6 +126,27 @@ typedef struct TreeElement {
|
||||
#define OL_RNA_COL_SPACEX (UI_UNIT_X*2.5f)
|
||||
|
||||
|
||||
/* Outliner Searching --
|
||||
|
||||
Are we looking for something in the outliner?
|
||||
If so finding matches in child items makes it more useful
|
||||
|
||||
- We want to flag parents to act as being open to filter child matches
|
||||
- and also flag matches so we can highlight them
|
||||
- Flags are stored in TreeStoreElem->flag
|
||||
- Flag options defined in DNA_outliner_types.h
|
||||
- SO_SEARCH_RECURSIVE defined in DNA_space_types.h
|
||||
|
||||
- NOT in datablocks view - searching all datablocks takes way too long
|
||||
to be useful
|
||||
- not searching into RNA items helps but isn't the complete solution
|
||||
*/
|
||||
|
||||
#define SEARCHING_OUTLINER(sov) (sov->search_flags & SO_SEARCH_RECURSIVE)
|
||||
|
||||
/* is the currrent element open? if so we also show children */
|
||||
#define TSELEM_OPEN(telm,sv) ( (telm->flag & TSE_CLOSED)==0 || (SEARCHING_OUTLINER(sv) && (telm->flag & TSE_CHILDSEARCH)) )
|
||||
|
||||
/* outliner_tree.c ----------------------------------------------- */
|
||||
|
||||
void outliner_free_tree(ListBase *lb);
|
||||
|
||||
@@ -134,7 +134,7 @@ static int outliner_select(SpaceOops *soops, ListBase *lb, int *index, short *se
|
||||
change |= 1;
|
||||
}
|
||||
}
|
||||
else if ((tselem->flag & TSE_CLOSED)==0) {
|
||||
else if (TSELEM_OPEN(tselem,soops)) {
|
||||
/* Only try selecting sub-elements if we haven't hit the right element yet
|
||||
*
|
||||
* Hack warning:
|
||||
|
||||
@@ -145,7 +145,7 @@ static void set_operation_types(SpaceOops *soops, ListBase *lb,
|
||||
}
|
||||
}
|
||||
}
|
||||
if((tselem->flag & TSE_CLOSED)==0) {
|
||||
if(TSELEM_OPEN(tselem,soops)) {
|
||||
set_operation_types(soops, &te->subtree,
|
||||
scenelevel, objectlevel, idlevel, datalevel);
|
||||
}
|
||||
@@ -250,7 +250,7 @@ static void outliner_do_libdata_operation(bContext *C, Scene *scene, SpaceOops *
|
||||
operation_cb(C, scene, te, tsep, tselem);
|
||||
}
|
||||
}
|
||||
if((tselem->flag & TSE_CLOSED)==0) {
|
||||
if(TSELEM_OPEN(tselem,soops)) {
|
||||
outliner_do_libdata_operation(C, scene, soops, &te->subtree, operation_cb);
|
||||
}
|
||||
}
|
||||
@@ -397,7 +397,7 @@ void outliner_do_object_operation(bContext *C, Scene *scene_act, SpaceOops *soop
|
||||
operation_cb(C, scene_owner ? scene_owner : scene_act, te, NULL, tselem);
|
||||
}
|
||||
}
|
||||
if((tselem->flag & TSE_CLOSED)==0) {
|
||||
if(TSELEM_OPEN(tselem,soops)) {
|
||||
outliner_do_object_operation(C, scene_act, soops, &te->subtree, operation_cb);
|
||||
}
|
||||
}
|
||||
@@ -504,7 +504,7 @@ static void outliner_do_data_operation(SpaceOops *soops, int type, int event, Li
|
||||
operation_cb(event, te, tselem);
|
||||
}
|
||||
}
|
||||
if((tselem->flag & TSE_CLOSED)==0) {
|
||||
if(TSELEM_OPEN(tselem,soops)) {
|
||||
outliner_do_data_operation(soops, type, event, &te->subtree, operation_cb);
|
||||
}
|
||||
}
|
||||
@@ -857,7 +857,7 @@ static void outliner_do_id_set_operation(SpaceOops *soops, int type, ListBase *l
|
||||
operation_cb(te, tselem, tsep, newid);
|
||||
}
|
||||
}
|
||||
if ((tselem->flag & TSE_CLOSED)==0) {
|
||||
if (TSELEM_OPEN(tselem,soops)) {
|
||||
outliner_do_id_set_operation(soops, type, &te->subtree, newid, operation_cb);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -827,6 +827,10 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
|
||||
check_persistant(soops, te, id, type, index);
|
||||
tselem= TREESTORE(te);
|
||||
|
||||
/* if we are searching for something expand to see child elements */
|
||||
if(SEARCHING_OUTLINER(soops))
|
||||
tselem->flag |= TSE_CHILDSEARCH;
|
||||
|
||||
te->parent= parent;
|
||||
te->index= index; // for data arays
|
||||
if(ELEM3(type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP));
|
||||
@@ -981,6 +985,9 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
|
||||
else
|
||||
te->name= (char*)RNA_struct_ui_name(ptr->type);
|
||||
|
||||
/* If searching don't expand RNA entries */
|
||||
if(SEARCHING_OUTLINER(soops) && BLI_strcasecmp("RNA",te->name)==0) tselem->flag &= ~TSE_CHILDSEARCH;
|
||||
|
||||
iterprop= RNA_struct_iterator_property(ptr->type);
|
||||
tot= RNA_property_collection_length(ptr, iterprop);
|
||||
|
||||
@@ -989,7 +996,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
|
||||
if(!tselem->used)
|
||||
tselem->flag &= ~TSE_CLOSED;
|
||||
|
||||
if(!(tselem->flag & TSE_CLOSED)) {
|
||||
if(TSELEM_OPEN(tselem,soops)) {
|
||||
for(a=0; a<tot; a++)
|
||||
outliner_add_element(soops, &te->subtree, (void*)ptr, te, TSE_RNA_PROPERTY, a);
|
||||
}
|
||||
@@ -1010,11 +1017,14 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
|
||||
te->directdata= prop;
|
||||
te->rnaptr= *ptr;
|
||||
|
||||
/* If searching don't expand RNA entries */
|
||||
if(SEARCHING_OUTLINER(soops) && BLI_strcasecmp("RNA",te->name)==0) tselem->flag &= ~TSE_CHILDSEARCH;
|
||||
|
||||
if(proptype == PROP_POINTER) {
|
||||
pptr= RNA_property_pointer_get(ptr, prop);
|
||||
|
||||
if(pptr.data) {
|
||||
if(!(tselem->flag & TSE_CLOSED))
|
||||
if(TSELEM_OPEN(tselem,soops))
|
||||
outliner_add_element(soops, &te->subtree, (void*)&pptr, te, TSE_RNA_STRUCT, -1);
|
||||
else
|
||||
te->flag |= TE_LAZY_CLOSED;
|
||||
@@ -1023,7 +1033,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
|
||||
else if(proptype == PROP_COLLECTION) {
|
||||
tot= RNA_property_collection_length(ptr, prop);
|
||||
|
||||
if(!(tselem->flag & TSE_CLOSED)) {
|
||||
if(TSELEM_OPEN(tselem,soops)) {
|
||||
for(a=0; a<tot; a++) {
|
||||
RNA_property_collection_lookup_int(ptr, prop, a, &pptr);
|
||||
outliner_add_element(soops, &te->subtree, (void*)&pptr, te, TSE_RNA_STRUCT, a);
|
||||
@@ -1035,7 +1045,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
|
||||
else if(ELEM3(proptype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
|
||||
tot= RNA_property_array_length(ptr, prop);
|
||||
|
||||
if(!(tselem->flag & TSE_CLOSED)) {
|
||||
if(TSELEM_OPEN(tselem,soops)) {
|
||||
for(a=0; a<tot; a++)
|
||||
outliner_add_element(soops, &te->subtree, (void*)ptr, te, TSE_RNA_ARRAY_ELEM, a);
|
||||
}
|
||||
@@ -1068,7 +1078,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
|
||||
te->directdata= idv;
|
||||
te->name= km->idname;
|
||||
|
||||
if(!(tselem->flag & TSE_CLOSED)) {
|
||||
if(TSELEM_OPEN(tselem,soops)) {
|
||||
a= 0;
|
||||
|
||||
for (kmi= km->items.first; kmi; kmi= kmi->next, a++) {
|
||||
@@ -1368,7 +1378,10 @@ static int outliner_filter_tree(SpaceOops *soops, ListBase *lb)
|
||||
*/
|
||||
tselem= TREESTORE(te);
|
||||
|
||||
if ((tselem->flag & TSE_CLOSED) || outliner_filter_tree(soops, &te->subtree)==0) {
|
||||
/* flag as not a found item */
|
||||
tselem->flag &= ~TSE_SEARCHMATCH;
|
||||
|
||||
if ((!TSELEM_OPEN(tselem,soops)) || outliner_filter_tree(soops, &te->subtree)==0) {
|
||||
outliner_free_tree(&te->subtree);
|
||||
BLI_remlink(lb, te);
|
||||
|
||||
@@ -1377,6 +1390,11 @@ static int outliner_filter_tree(SpaceOops *soops, ListBase *lb)
|
||||
}
|
||||
}
|
||||
else {
|
||||
tselem= TREESTORE(te);
|
||||
|
||||
/* flag as a found item - we can then highlight it */
|
||||
tselem->flag |= TSE_SEARCHMATCH;
|
||||
|
||||
/* filter subtree too */
|
||||
outliner_filter_tree(soops, &te->subtree);
|
||||
}
|
||||
@@ -1399,6 +1417,14 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
|
||||
TreeStoreElem *tselem;
|
||||
int show_opened= (soops->treestore==NULL); /* on first view, we open scenes */
|
||||
|
||||
/* Are we looking for something - we want to tag parents to filter child matches
|
||||
- NOT in datablocks view - searching all datablocks takes way too long to be useful
|
||||
- this variable is only set once per tree build */
|
||||
if(soops->search_string[0]!=0 && soops->outlinevis!=SO_DATABLOCKS)
|
||||
soops->search_flags |= SO_SEARCH_RECURSIVE;
|
||||
else
|
||||
soops->search_flags &= ~SO_SEARCH_RECURSIVE;
|
||||
|
||||
if(soops->tree.first && (soops->storeflag & SO_TREESTORE_REDRAW))
|
||||
return;
|
||||
|
||||
|
||||
@@ -126,6 +126,7 @@ GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex);
|
||||
int GPU_texture_target(GPUTexture *tex);
|
||||
int GPU_texture_opengl_width(GPUTexture *tex);
|
||||
int GPU_texture_opengl_height(GPUTexture *tex);
|
||||
int GPU_texture_opengl_bindcode(GPUTexture *tex);
|
||||
|
||||
/* GPU Framebuffer
|
||||
- this is a wrapper for an OpenGL framebuffer object (FBO). in practice
|
||||
@@ -179,6 +180,7 @@ typedef struct GPUVertexAttribs {
|
||||
int type;
|
||||
int glindex;
|
||||
int gltexco;
|
||||
int attribid;
|
||||
char name[32];
|
||||
} layer[GPU_MAX_ATTRIB];
|
||||
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
#ifndef __GPU_MATERIAL__
|
||||
#define __GPU_MATERIAL__
|
||||
|
||||
#include "DNA_listBase.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -46,6 +48,7 @@ struct ImageUser;
|
||||
struct Material;
|
||||
struct Object;
|
||||
struct Lamp;
|
||||
struct Image;
|
||||
struct bNode;
|
||||
struct LinkNode;
|
||||
struct Scene;
|
||||
@@ -72,7 +75,6 @@ typedef enum GPUType {
|
||||
GPU_VEC4 = 4,
|
||||
GPU_MAT3 = 9,
|
||||
GPU_MAT4 = 16,
|
||||
GPU_TEX1D = 1001,
|
||||
GPU_TEX2D = 1002,
|
||||
GPU_SHADOW2D = 1003,
|
||||
GPU_ATTRIB = 3001
|
||||
@@ -107,10 +109,10 @@ typedef struct GPUNodeStack {
|
||||
|
||||
GPUNodeLink *GPU_attribute(int type, const char *name);
|
||||
GPUNodeLink *GPU_uniform(float *num);
|
||||
GPUNodeLink *GPU_dynamic_uniform(float *num);
|
||||
GPUNodeLink *GPU_dynamic_uniform(float *num, int dynamictype, void *data);
|
||||
GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser);
|
||||
GPUNodeLink *GPU_texture(int size, float *pixels);
|
||||
GPUNodeLink *GPU_dynamic_texture(struct GPUTexture *tex);
|
||||
GPUNodeLink *GPU_dynamic_texture(struct GPUTexture *tex, int dynamictype, void *data);
|
||||
GPUNodeLink *GPU_socket(GPUNodeStack *sock);
|
||||
GPUNodeLink *GPU_builtin(GPUBuiltin builtin);
|
||||
|
||||
@@ -153,6 +155,72 @@ typedef struct GPUShadeResult {
|
||||
void GPU_shadeinput_set(GPUMaterial *mat, struct Material *ma, GPUShadeInput *shi);
|
||||
void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr);
|
||||
|
||||
/* Export GLSL shader */
|
||||
|
||||
typedef enum GPUDynamicType {
|
||||
GPU_DYNAMIC_NONE = 0,
|
||||
GPU_DYNAMIC_OBJECT_VIEWMAT = 1,
|
||||
GPU_DYNAMIC_OBJECT_MAT = 2,
|
||||
GPU_DYNAMIC_OBJECT_VIEWIMAT = 3,
|
||||
GPU_DYNAMIC_OBJECT_IMAT = 4,
|
||||
GPU_DYNAMIC_OBJECT_COLOR = 5,
|
||||
GPU_DYNAMIC_LAMP_FIRST = 6,
|
||||
GPU_DYNAMIC_LAMP_DYNVEC = 6,
|
||||
GPU_DYNAMIC_LAMP_DYNCO = 7,
|
||||
GPU_DYNAMIC_LAMP_DYNIMAT = 8,
|
||||
GPU_DYNAMIC_LAMP_DYNPERSMAT = 9,
|
||||
GPU_DYNAMIC_LAMP_DYNENERGY = 10,
|
||||
GPU_DYNAMIC_LAMP_DYNCOL = 11,
|
||||
GPU_DYNAMIC_LAMP_LAST = 11,
|
||||
GPU_DYNAMIC_SAMPLER_2DBUFFER = 12,
|
||||
GPU_DYNAMIC_SAMPLER_2DIMAGE = 13,
|
||||
GPU_DYNAMIC_SAMPLER_2DSHADOW = 14,
|
||||
} GPUDynamicType;
|
||||
|
||||
typedef enum GPUDataType {
|
||||
GPU_DATA_NONE = 0,
|
||||
GPU_DATA_1I = 1, // 1 integer
|
||||
GPU_DATA_1F = 2,
|
||||
GPU_DATA_2F = 3,
|
||||
GPU_DATA_3F = 4,
|
||||
GPU_DATA_4F = 5,
|
||||
GPU_DATA_9F = 6,
|
||||
GPU_DATA_16F = 7,
|
||||
GPU_DATA_4UB = 8,
|
||||
} GPUDataType;
|
||||
|
||||
/* this structure gives information of each uniform found in the shader */
|
||||
typedef struct GPUInputUniform {
|
||||
struct GPUInputUniform *next, *prev;
|
||||
char varname[32]; /* name of uniform in shader */
|
||||
GPUDynamicType type; /* type of uniform, data format and calculation derive from it */
|
||||
GPUDataType datatype; /* type of uniform data */
|
||||
struct Object *lamp; /* when type=GPU_DYNAMIC_LAMP_... or GPU_DYNAMIC_SAMPLER_2DSHADOW */
|
||||
struct Image *image; /* when type=GPU_DYNAMIC_SAMPLER_2DIMAGE */
|
||||
int texnumber; /* when type=GPU_DYNAMIC_SAMPLER, texture number: 0.. */
|
||||
unsigned char *texpixels; /* for internally generated texture, pixel data in RGBA format */
|
||||
int texsize; /* size in pixel of the texture in texpixels buffer: for 2D textures, this is S and T size (square texture) */
|
||||
} GPUInputUniform;
|
||||
|
||||
typedef struct GPUInputAttribute {
|
||||
struct GPUInputAttribute *next, *prev;
|
||||
char varname[32]; /* name of attribute in shader */
|
||||
int type; /* from CustomData.type, data type derives from it */
|
||||
GPUDataType datatype; /* type of attribute data */
|
||||
const char *name; /* layer name */
|
||||
int number; /* generic attribute number */
|
||||
} GPUInputAttribute;
|
||||
|
||||
typedef struct GPUShaderExport {
|
||||
ListBase uniforms;
|
||||
ListBase attributes;
|
||||
char *vertex;
|
||||
char *fragment;
|
||||
} GPUShaderExport;
|
||||
|
||||
GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma);
|
||||
void GPU_free_shader_export(GPUShaderExport *shader);
|
||||
|
||||
/* Lamps */
|
||||
|
||||
GPULamp *GPU_lamp_from_blender(struct Scene *scene, struct Object *ob, struct Object *par);
|
||||
|
||||
@@ -64,101 +64,9 @@ extern char datatoc_gpu_shader_vertex_glsl[];
|
||||
|
||||
/* structs and defines */
|
||||
|
||||
typedef enum GPUDataSource {
|
||||
GPU_SOURCE_VEC_UNIFORM,
|
||||
GPU_SOURCE_BUILTIN,
|
||||
GPU_SOURCE_TEX_PIXEL,
|
||||
GPU_SOURCE_TEX,
|
||||
GPU_SOURCE_ATTRIB
|
||||
} GPUDataSource;
|
||||
|
||||
static const char* GPU_DATATYPE_STR[17] = {"", "float", "vec2", "vec3", "vec4",
|
||||
NULL, NULL, NULL, NULL, "mat3", NULL, NULL, NULL, NULL, NULL, NULL, "mat4"};
|
||||
|
||||
struct GPUNode {
|
||||
struct GPUNode *next, *prev;
|
||||
|
||||
const char *name;
|
||||
int tag;
|
||||
|
||||
ListBase inputs;
|
||||
ListBase outputs;
|
||||
};
|
||||
|
||||
struct GPUNodeLink {
|
||||
GPUNodeStack *socket;
|
||||
|
||||
int attribtype;
|
||||
const char *attribname;
|
||||
|
||||
int image;
|
||||
|
||||
int texture;
|
||||
int texturesize;
|
||||
|
||||
void *ptr1, *ptr2;
|
||||
|
||||
int dynamic;
|
||||
|
||||
int type;
|
||||
int users;
|
||||
|
||||
GPUTexture *dynamictex;
|
||||
|
||||
GPUBuiltin builtin;
|
||||
|
||||
struct GPUOutput *output;
|
||||
};
|
||||
|
||||
typedef struct GPUOutput {
|
||||
struct GPUOutput *next, *prev;
|
||||
|
||||
GPUNode *node;
|
||||
int type; /* data type = length of vector/matrix */
|
||||
GPUNodeLink *link; /* output link */
|
||||
int id; /* unique id as created by code generator */
|
||||
} GPUOutput;
|
||||
|
||||
typedef struct GPUInput {
|
||||
struct GPUInput *next, *prev;
|
||||
|
||||
GPUNode *node;
|
||||
|
||||
int type; /* datatype */
|
||||
int source; /* data source */
|
||||
|
||||
int id; /* unique id as created by code generator */
|
||||
int texid; /* number for multitexture */
|
||||
int attribid; /* id for vertex attributes */
|
||||
int bindtex; /* input is responsible for binding the texture? */
|
||||
int definetex; /* input is responsible for defining the pixel? */
|
||||
int textarget; /* GL_TEXTURE_* */
|
||||
int textype; /* datatype */
|
||||
|
||||
struct Image *ima; /* image */
|
||||
struct ImageUser *iuser;/* image user */
|
||||
float *dynamicvec; /* vector data in case it is dynamic */
|
||||
GPUTexture *tex; /* input texture, only set at runtime */
|
||||
int shaderloc; /* id from opengl */
|
||||
char shadername[32]; /* name in shader */
|
||||
|
||||
float vec[16]; /* vector data */
|
||||
GPUNodeLink *link;
|
||||
int dynamictex; /* dynamic? */
|
||||
int attribtype; /* attribute type */
|
||||
char attribname[32]; /* attribute name */
|
||||
int attribfirst; /* this is the first one that is bound */
|
||||
GPUBuiltin builtin; /* builtin uniform */
|
||||
} GPUInput;
|
||||
|
||||
struct GPUPass {
|
||||
struct GPUPass *next, *prev;
|
||||
|
||||
ListBase inputs;
|
||||
struct GPUOutput *output;
|
||||
struct GPUShader *shader;
|
||||
};
|
||||
|
||||
/* GLSL code parsing for finding function definitions.
|
||||
* These are stored in a hash for lookup when creating a material. */
|
||||
|
||||
@@ -245,8 +153,6 @@ static void gpu_parse_functions_string(GHash *hash, char *code)
|
||||
|
||||
if(!type && gpu_str_prefix(code, "sampler2DShadow"))
|
||||
type= GPU_SHADOW2D;
|
||||
if(!type && gpu_str_prefix(code, "sampler1D"))
|
||||
type= GPU_TEX1D;
|
||||
if(!type && gpu_str_prefix(code, "sampler2D"))
|
||||
type= GPU_TEX2D;
|
||||
|
||||
@@ -298,9 +204,7 @@ static char *gpu_generate_function_prototyps(GHash *hash)
|
||||
else if(function->paramqual[a] == FUNCTION_QUAL_INOUT)
|
||||
BLI_dynstr_append(ds, "inout ");
|
||||
|
||||
if(function->paramtype[a] == GPU_TEX1D)
|
||||
BLI_dynstr_append(ds, "sampler1D");
|
||||
else if(function->paramtype[a] == GPU_TEX2D)
|
||||
if(function->paramtype[a] == GPU_TEX2D)
|
||||
BLI_dynstr_append(ds, "sampler2D");
|
||||
else if(function->paramtype[a] == GPU_SHADOW2D)
|
||||
BLI_dynstr_append(ds, "sampler2DShadow");
|
||||
@@ -542,7 +446,6 @@ static void codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes)
|
||||
/* create exactly one sampler for each texture */
|
||||
if (codegen_input_has_texture(input) && input->bindtex)
|
||||
BLI_dynstr_appendf(ds, "uniform %s samp%d;\n",
|
||||
(input->textype == GPU_TEX1D)? "sampler1D":
|
||||
(input->textype == GPU_TEX2D)? "sampler2D": "sampler2DShadow",
|
||||
input->texid);
|
||||
}
|
||||
@@ -947,6 +850,7 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type)
|
||||
input->textarget = GL_TEXTURE_2D;
|
||||
input->textype = type;
|
||||
input->dynamictex = 1;
|
||||
input->dynamicdata = link->ptr2;
|
||||
MEM_freeN(link);
|
||||
}
|
||||
else if(link->texture) {
|
||||
@@ -955,14 +859,9 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type)
|
||||
input->source = GPU_SOURCE_TEX;
|
||||
input->textype = type;
|
||||
|
||||
if (type == GPU_TEX1D) {
|
||||
input->tex = GPU_texture_create_1D(link->texturesize, link->ptr1, NULL);
|
||||
input->textarget = GL_TEXTURE_1D;
|
||||
}
|
||||
else {
|
||||
input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2, NULL);
|
||||
//input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2, NULL);
|
||||
input->tex = GPU_texture_create_2D(link->texturesize, 1, link->ptr1, NULL);
|
||||
input->textarget = GL_TEXTURE_2D;
|
||||
}
|
||||
|
||||
MEM_freeN(link->ptr1);
|
||||
MEM_freeN(link);
|
||||
@@ -993,8 +892,11 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type)
|
||||
input->source = GPU_SOURCE_VEC_UNIFORM;
|
||||
|
||||
memcpy(input->vec, link->ptr1, type*sizeof(float));
|
||||
if(link->dynamic)
|
||||
if(link->dynamic) {
|
||||
input->dynamicvec= link->ptr1;
|
||||
input->dynamictype= link->dynamictype;
|
||||
input->dynamicdata= link->ptr2;
|
||||
}
|
||||
MEM_freeN(link);
|
||||
}
|
||||
|
||||
@@ -1102,12 +1004,12 @@ static void gpu_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *a
|
||||
input->attribfirst = 1;
|
||||
|
||||
attribs->layer[a].type = input->attribtype;
|
||||
attribs->layer[a].glindex = input->attribid;
|
||||
attribs->layer[a].attribid = input->attribid;
|
||||
BLI_strncpy(attribs->layer[a].name, input->attribname,
|
||||
sizeof(attribs->layer[a].name));
|
||||
}
|
||||
else
|
||||
input->attribid = attribs->layer[a].glindex;
|
||||
input->attribid = attribs->layer[a].attribid;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1148,13 +1050,15 @@ GPUNodeLink *GPU_uniform(float *num)
|
||||
return link;
|
||||
}
|
||||
|
||||
GPUNodeLink *GPU_dynamic_uniform(float *num)
|
||||
GPUNodeLink *GPU_dynamic_uniform(float *num, int dynamictype, void *data)
|
||||
{
|
||||
GPUNodeLink *link = GPU_node_link_create(0);
|
||||
|
||||
link->ptr1= num;
|
||||
link->ptr2= NULL;
|
||||
link->ptr2= data;
|
||||
link->dynamic= 1;
|
||||
link->dynamictype = dynamictype;
|
||||
|
||||
|
||||
return link;
|
||||
}
|
||||
@@ -1181,12 +1085,14 @@ GPUNodeLink *GPU_texture(int size, float *pixels)
|
||||
return link;
|
||||
}
|
||||
|
||||
GPUNodeLink *GPU_dynamic_texture(GPUTexture *tex)
|
||||
GPUNodeLink *GPU_dynamic_texture(GPUTexture *tex, int dynamictype, void *data)
|
||||
{
|
||||
GPUNodeLink *link = GPU_node_link_create(0);
|
||||
|
||||
link->dynamic = 1;
|
||||
link->dynamictex = tex;
|
||||
link->dynamictype = dynamictype;
|
||||
link->ptr2 = data;
|
||||
|
||||
return link;
|
||||
}
|
||||
@@ -1389,8 +1295,6 @@ GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttri
|
||||
fragmentcode = code_generate_fragment(nodes, outlink->output, name);
|
||||
vertexcode = code_generate_vertex(nodes);
|
||||
shader = GPU_shader_create(vertexcode, fragmentcode, datatoc_gpu_shader_material_glsl); /*FUNCTION_LIB);*/
|
||||
MEM_freeN(fragmentcode);
|
||||
MEM_freeN(vertexcode);
|
||||
|
||||
/* failed? */
|
||||
if (!shader) {
|
||||
@@ -1405,6 +1309,9 @@ GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttri
|
||||
|
||||
pass->output = outlink->output;
|
||||
pass->shader = shader;
|
||||
pass->fragmentcode = fragmentcode;
|
||||
pass->vertexcode = vertexcode;
|
||||
pass->libcode = datatoc_gpu_shader_material_glsl;
|
||||
|
||||
/* extract dynamic inputs and throw away nodes */
|
||||
GPU_nodes_extract_dynamic_inputs(pass, nodes);
|
||||
@@ -1417,6 +1324,10 @@ void GPU_pass_free(GPUPass *pass)
|
||||
{
|
||||
GPU_shader_free(pass->shader);
|
||||
GPU_inputs_free(&pass->inputs);
|
||||
if (pass->fragmentcode)
|
||||
MEM_freeN(pass->fragmentcode);
|
||||
if (pass->vertexcode)
|
||||
MEM_freeN(pass->vertexcode);
|
||||
MEM_freeN(pass);
|
||||
}
|
||||
|
||||
|
||||
@@ -39,12 +39,15 @@
|
||||
#define __GPU_CODEGEN_H__
|
||||
|
||||
#include "DNA_listBase.h"
|
||||
#include "GPU_material.h"
|
||||
#include "GL/glew.h"
|
||||
|
||||
struct ListBase;
|
||||
struct GPUShader;
|
||||
struct GPUOutput;
|
||||
struct GPUNode;
|
||||
struct GPUVertexAttribs;
|
||||
struct GPUFrameBuffer;
|
||||
|
||||
#define MAX_FUNCTION_NAME 64
|
||||
#define MAX_PARAMETER 32
|
||||
@@ -68,7 +71,105 @@ GPUFunction *GPU_lookup_function(const char *name);
|
||||
at the end if used.
|
||||
*/
|
||||
|
||||
struct GPUPass;
|
||||
typedef enum GPUDataSource {
|
||||
GPU_SOURCE_VEC_UNIFORM,
|
||||
GPU_SOURCE_BUILTIN,
|
||||
GPU_SOURCE_TEX_PIXEL,
|
||||
GPU_SOURCE_TEX,
|
||||
GPU_SOURCE_ATTRIB
|
||||
} GPUDataSource;
|
||||
|
||||
struct GPUNode {
|
||||
struct GPUNode *next, *prev;
|
||||
|
||||
const char *name;
|
||||
int tag;
|
||||
|
||||
ListBase inputs;
|
||||
ListBase outputs;
|
||||
};
|
||||
|
||||
struct GPUNodeLink {
|
||||
GPUNodeStack *socket;
|
||||
|
||||
int attribtype;
|
||||
const char *attribname;
|
||||
|
||||
int image;
|
||||
|
||||
int texture;
|
||||
int texturesize;
|
||||
|
||||
void *ptr1, *ptr2;
|
||||
|
||||
int dynamic;
|
||||
int dynamictype;
|
||||
|
||||
int type;
|
||||
int users;
|
||||
|
||||
GPUTexture *dynamictex;
|
||||
|
||||
GPUBuiltin builtin;
|
||||
|
||||
struct GPUOutput *output;
|
||||
};
|
||||
|
||||
typedef struct GPUOutput {
|
||||
struct GPUOutput *next, *prev;
|
||||
|
||||
GPUNode *node;
|
||||
int type; /* data type = length of vector/matrix */
|
||||
GPUNodeLink *link; /* output link */
|
||||
int id; /* unique id as created by code generator */
|
||||
} GPUOutput;
|
||||
|
||||
typedef struct GPUInput {
|
||||
struct GPUInput *next, *prev;
|
||||
|
||||
GPUNode *node;
|
||||
|
||||
int type; /* datatype */
|
||||
int source; /* data source */
|
||||
|
||||
int id; /* unique id as created by code generator */
|
||||
int texid; /* number for multitexture */
|
||||
int attribid; /* id for vertex attributes */
|
||||
int bindtex; /* input is responsible for binding the texture? */
|
||||
int definetex; /* input is responsible for defining the pixel? */
|
||||
int textarget; /* GL_TEXTURE_* */
|
||||
int textype; /* datatype */
|
||||
|
||||
struct Image *ima; /* image */
|
||||
struct ImageUser *iuser;/* image user */
|
||||
float *dynamicvec; /* vector data in case it is dynamic */
|
||||
int dynamictype; /* origin of the dynamic uniform (GPUDynamicType) */
|
||||
void *dynamicdata; /* data source of the dynamic uniform */
|
||||
GPUTexture *tex; /* input texture, only set at runtime */
|
||||
int shaderloc; /* id from opengl */
|
||||
char shadername[32]; /* name in shader */
|
||||
|
||||
float vec[16]; /* vector data */
|
||||
GPUNodeLink *link;
|
||||
int dynamictex; /* dynamic? */
|
||||
int attribtype; /* attribute type */
|
||||
char attribname[32]; /* attribute name */
|
||||
int attribfirst; /* this is the first one that is bound */
|
||||
GPUBuiltin builtin; /* builtin uniform */
|
||||
} GPUInput;
|
||||
|
||||
struct GPUPass {
|
||||
struct GPUPass *next, *prev;
|
||||
|
||||
ListBase inputs;
|
||||
struct GPUOutput *output;
|
||||
struct GPUShader *shader;
|
||||
char *fragmentcode;
|
||||
char *vertexcode;
|
||||
const char *libcode;
|
||||
};
|
||||
|
||||
|
||||
typedef struct GPUPass GPUPass;
|
||||
|
||||
GPUPass *GPU_generate_pass(ListBase *nodes, struct GPUNodeLink *outlink,
|
||||
|
||||
@@ -423,7 +423,7 @@ static GPUTexture *GPU_texture_create_nD(int w, int h, int n, float *fpixels, in
|
||||
|
||||
if (tex->target != GL_TEXTURE_1D) {
|
||||
/* CLAMP_TO_BORDER is an OpenGL 1.3 core feature */
|
||||
GLenum wrapmode = (depth)? GL_CLAMP_TO_EDGE: GL_CLAMP_TO_BORDER;
|
||||
GLenum wrapmode = (depth || tex->h == 1)? GL_CLAMP_TO_EDGE: GL_CLAMP_TO_BORDER;
|
||||
glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, wrapmode);
|
||||
glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, wrapmode);
|
||||
|
||||
@@ -685,6 +685,11 @@ int GPU_texture_opengl_height(GPUTexture *tex)
|
||||
return tex->h;
|
||||
}
|
||||
|
||||
int GPU_texture_opengl_bindcode(GPUTexture *tex)
|
||||
{
|
||||
return tex->bindcode;
|
||||
}
|
||||
|
||||
GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex)
|
||||
{
|
||||
return tex->fb;
|
||||
|
||||
@@ -175,7 +175,7 @@ static void gpu_material_set_attrib_id(GPUMaterial *material)
|
||||
* removed by the glsl compiler by dead code elimination */
|
||||
|
||||
for(a=0, b=0; a<attribs->totlayer; a++) {
|
||||
sprintf(name, "att%d", attribs->layer[a].glindex);
|
||||
sprintf(name, "att%d", attribs->layer[a].attribid);
|
||||
attribs->layer[a].glindex = GPU_shader_get_attribute(shader, name);
|
||||
|
||||
if(attribs->layer[a].glindex >= 0) {
|
||||
@@ -386,12 +386,12 @@ static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNode
|
||||
/* from get_lamp_visibility */
|
||||
if(lamp->type==LA_SUN || lamp->type==LA_HEMI) {
|
||||
mat->dynproperty |= DYN_LAMP_VEC;
|
||||
GPU_link(mat, "lamp_visibility_sun_hemi", GPU_dynamic_uniform(lamp->dynvec), lv, dist, &visifac);
|
||||
GPU_link(mat, "lamp_visibility_sun_hemi", GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), lv, dist, &visifac);
|
||||
return visifac;
|
||||
}
|
||||
else {
|
||||
mat->dynproperty |= DYN_LAMP_CO;
|
||||
GPU_link(mat, "lamp_visibility_other", GPU_builtin(GPU_VIEW_POSITION), GPU_dynamic_uniform(lamp->dynco), lv, dist, &visifac);
|
||||
GPU_link(mat, "lamp_visibility_other", GPU_builtin(GPU_VIEW_POSITION), GPU_dynamic_uniform(lamp->dynco, GPU_DYNAMIC_LAMP_DYNCO, lamp->ob), lv, dist, &visifac);
|
||||
|
||||
if(lamp->type==LA_AREA)
|
||||
return visifac;
|
||||
@@ -426,11 +426,11 @@ static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNode
|
||||
if(lamp->type == LA_SPOT) {
|
||||
if(lamp->mode & LA_SQUARE) {
|
||||
mat->dynproperty |= DYN_LAMP_VEC|DYN_LAMP_IMAT;
|
||||
GPU_link(mat, "lamp_visibility_spot_square", GPU_dynamic_uniform(lamp->dynvec), GPU_dynamic_uniform((float*)lamp->dynimat), *lv, &inpr);
|
||||
GPU_link(mat, "lamp_visibility_spot_square", GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), GPU_dynamic_uniform((float*)lamp->dynimat, GPU_DYNAMIC_LAMP_DYNIMAT, lamp->ob), *lv, &inpr);
|
||||
}
|
||||
else {
|
||||
mat->dynproperty |= DYN_LAMP_VEC;
|
||||
GPU_link(mat, "lamp_visibility_spot_circle", GPU_dynamic_uniform(lamp->dynvec), *lv, &inpr);
|
||||
GPU_link(mat, "lamp_visibility_spot_circle", GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), *lv, &inpr);
|
||||
}
|
||||
|
||||
GPU_link(mat, "lamp_visibility_spot", GPU_uniform(&lamp->spotsi), GPU_uniform(&lamp->spotbl), inpr, visifac, &visifac);
|
||||
@@ -646,7 +646,7 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la
|
||||
float area[4][4]= {{0.0f}}, areasize= 0.0f;
|
||||
|
||||
mat->dynproperty |= DYN_LAMP_VEC|DYN_LAMP_CO;
|
||||
GPU_link(mat, "shade_inp_area", GPU_builtin(GPU_VIEW_POSITION), GPU_dynamic_uniform(lamp->dynco), GPU_dynamic_uniform(lamp->dynvec), vn, GPU_uniform((float*)area),
|
||||
GPU_link(mat, "shade_inp_area", GPU_builtin(GPU_VIEW_POSITION), GPU_dynamic_uniform(lamp->dynco, GPU_DYNAMIC_LAMP_DYNCO, lamp->ob), GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), vn, GPU_uniform((float*)area),
|
||||
GPU_uniform(&areasize), GPU_uniform(&lamp->k), &inp);
|
||||
}
|
||||
|
||||
@@ -684,13 +684,13 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la
|
||||
|
||||
GPU_link(mat, "test_shadowbuf",
|
||||
GPU_builtin(GPU_VIEW_POSITION),
|
||||
GPU_dynamic_texture(lamp->tex),
|
||||
GPU_dynamic_uniform((float*)lamp->dynpersmat),
|
||||
GPU_dynamic_texture(lamp->tex, GPU_DYNAMIC_SAMPLER_2DSHADOW, lamp->ob),
|
||||
GPU_dynamic_uniform((float*)lamp->dynpersmat, GPU_DYNAMIC_LAMP_DYNPERSMAT, lamp->ob),
|
||||
GPU_uniform(&lamp->bias), inp, &shadfac);
|
||||
|
||||
if(lamp->mode & LA_ONLYSHADOW) {
|
||||
GPU_link(mat, "shade_only_shadow", i, shadfac,
|
||||
GPU_dynamic_uniform(&lamp->dynenergy), &shadfac);
|
||||
GPU_dynamic_uniform(&lamp->dynenergy, GPU_DYNAMIC_LAMP_DYNENERGY, lamp->ob), &shadfac);
|
||||
|
||||
if(!(lamp->mode & LA_NO_DIFF))
|
||||
GPU_link(mat, "shade_only_shadow_diffuse", shadfac, shi->rgb,
|
||||
@@ -719,7 +719,7 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la
|
||||
if(GPU_link_changed(shi->refl) || ma->ref != 0.0f) {
|
||||
if(!(lamp->mode & LA_NO_DIFF)) {
|
||||
GPUNodeLink *rgb;
|
||||
GPU_link(mat, "shade_mul_value", i, GPU_dynamic_uniform(lamp->dyncol), &rgb);
|
||||
GPU_link(mat, "shade_mul_value", i, GPU_dynamic_uniform(lamp->dyncol, GPU_DYNAMIC_LAMP_DYNCOL, lamp->ob), &rgb);
|
||||
add_to_diffuse(mat, ma, shi, is, rgb, &shr->diff);
|
||||
}
|
||||
}
|
||||
@@ -729,7 +729,7 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la
|
||||
(GPU_link_changed(shi->spec) || ma->spec != 0.0f)) {
|
||||
if(lamp->type == LA_HEMI) {
|
||||
GPU_link(mat, "shade_hemi_spec", vn, lv, view, GPU_uniform(&ma->spec), shi->har, visifac, &t);
|
||||
GPU_link(mat, "shade_add_spec", t, GPU_dynamic_uniform(lamp->dyncol), shi->specrgb, &outcol);
|
||||
GPU_link(mat, "shade_add_spec", t, GPU_dynamic_uniform(lamp->dyncol, GPU_DYNAMIC_LAMP_DYNCOL, lamp->ob), shi->specrgb, &outcol);
|
||||
GPU_link(mat, "shade_add_clamped", shr->spec, outcol, &shr->spec);
|
||||
}
|
||||
else {
|
||||
@@ -752,11 +752,11 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la
|
||||
if(ma->mode & MA_RAMP_SPEC) {
|
||||
GPUNodeLink *spec;
|
||||
do_specular_ramp(shi, specfac, t, &spec);
|
||||
GPU_link(mat, "shade_add_spec", t, GPU_dynamic_uniform(lamp->dyncol), spec, &outcol);
|
||||
GPU_link(mat, "shade_add_spec", t, GPU_dynamic_uniform(lamp->dyncol, GPU_DYNAMIC_LAMP_DYNCOL, lamp->ob), spec, &outcol);
|
||||
GPU_link(mat, "shade_add_clamped", shr->spec, outcol, &shr->spec);
|
||||
}
|
||||
else {
|
||||
GPU_link(mat, "shade_add_spec", t, GPU_dynamic_uniform(lamp->dyncol), shi->specrgb, &outcol);
|
||||
GPU_link(mat, "shade_add_spec", t, GPU_dynamic_uniform(lamp->dyncol, GPU_DYNAMIC_LAMP_DYNCOL, lamp->ob), shi->specrgb, &outcol);
|
||||
GPU_link(mat, "shade_add_clamped", shr->spec, outcol, &shr->spec);
|
||||
}
|
||||
}
|
||||
@@ -1676,3 +1676,187 @@ int GPU_lamp_shadow_layer(GPULamp *lamp)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* export the GLSL shader */
|
||||
|
||||
GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma)
|
||||
{
|
||||
static struct {
|
||||
GPUBuiltin gputype;
|
||||
GPUDynamicType dynamictype;
|
||||
GPUDataType datatype;
|
||||
} builtins[] = {
|
||||
{ GPU_VIEW_MATRIX, GPU_DYNAMIC_OBJECT_VIEWMAT, GPU_DATA_16F },
|
||||
{ GPU_INVERSE_VIEW_MATRIX, GPU_DYNAMIC_OBJECT_VIEWIMAT, GPU_DATA_16F },
|
||||
{ GPU_OBJECT_MATRIX, GPU_DYNAMIC_OBJECT_MAT, GPU_DATA_16F },
|
||||
{ GPU_INVERSE_OBJECT_MATRIX, GPU_DYNAMIC_OBJECT_IMAT, GPU_DATA_16F },
|
||||
{ GPU_OBCOLOR, GPU_DYNAMIC_OBJECT_COLOR, GPU_DATA_4F },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
GPUShaderExport *shader = NULL;
|
||||
GPUPass *pass;
|
||||
GPUInput *input;
|
||||
GPUMaterial *mat;
|
||||
GPUInputUniform *uniform;
|
||||
GPUInputAttribute *attribute;
|
||||
GLint lastbindcode;
|
||||
int i, liblen, fraglen;
|
||||
|
||||
if(!GPU_glsl_support())
|
||||
return NULL;
|
||||
|
||||
mat = GPU_material_from_blender(scene, ma);
|
||||
pass = (mat)? mat->pass: NULL;
|
||||
|
||||
if(pass && pass->fragmentcode && pass->vertexcode) {
|
||||
shader = MEM_callocN(sizeof(GPUShaderExport), "GPUShaderExport");
|
||||
|
||||
for(input = pass->inputs.first; input; input = input->next) {
|
||||
uniform = MEM_callocN(sizeof(GPUInputUniform), "GPUInputUniform");
|
||||
|
||||
if(input->ima) {
|
||||
/* image sampler uniform */
|
||||
uniform->type = GPU_DYNAMIC_SAMPLER_2DIMAGE;
|
||||
uniform->datatype = GPU_DATA_1I;
|
||||
uniform->image = input->ima;
|
||||
uniform->texnumber = input->texid;
|
||||
BLI_strncpy(uniform->varname, input->shadername, sizeof(uniform->varname));
|
||||
}
|
||||
else if(input->tex) {
|
||||
/* generated buffer */
|
||||
uniform->texnumber = input->texid;
|
||||
uniform->datatype = GPU_DATA_1I;
|
||||
BLI_strncpy(uniform->varname, input->shadername, sizeof(uniform->varname));
|
||||
|
||||
switch(input->textype) {
|
||||
case GPU_SHADOW2D:
|
||||
uniform->type = GPU_DYNAMIC_SAMPLER_2DSHADOW;
|
||||
uniform->lamp = input->dynamicdata;
|
||||
break;
|
||||
case GPU_TEX2D:
|
||||
if(GPU_texture_opengl_bindcode(input->tex)) {
|
||||
uniform->type = GPU_DYNAMIC_SAMPLER_2DBUFFER;
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &lastbindcode);
|
||||
glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(input->tex));
|
||||
uniform->texsize = GPU_texture_opengl_width(input->tex) * GPU_texture_opengl_height(input->tex);
|
||||
uniform->texpixels = MEM_mallocN(uniform->texsize*4, "RGBApixels");
|
||||
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, uniform->texpixels);
|
||||
glBindTexture(GL_TEXTURE_2D, lastbindcode);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
uniform->type = input->dynamictype;
|
||||
BLI_strncpy(uniform->varname, input->shadername, sizeof(uniform->varname));
|
||||
switch(input->type) {
|
||||
case 1:
|
||||
uniform->datatype = GPU_DATA_1F;
|
||||
break;
|
||||
case 2:
|
||||
uniform->datatype = GPU_DATA_2F;
|
||||
break;
|
||||
case 3:
|
||||
uniform->datatype = GPU_DATA_3F;
|
||||
break;
|
||||
case 4:
|
||||
uniform->datatype = GPU_DATA_4F;
|
||||
break;
|
||||
case 9:
|
||||
uniform->datatype = GPU_DATA_9F;
|
||||
break;
|
||||
case 16:
|
||||
uniform->datatype = GPU_DATA_16F;
|
||||
break;
|
||||
}
|
||||
|
||||
if(uniform->type >= GPU_DYNAMIC_LAMP_FIRST && uniform->type <= GPU_DYNAMIC_LAMP_LAST)
|
||||
uniform->lamp = input->dynamicdata;
|
||||
}
|
||||
|
||||
if(uniform->type != GPU_DYNAMIC_NONE)
|
||||
BLI_addtail(&shader->uniforms, uniform);
|
||||
else
|
||||
MEM_freeN(uniform);
|
||||
}
|
||||
|
||||
/* process builtin uniform */
|
||||
for(i=0; builtins[i].gputype; i++) {
|
||||
if(mat->builtins & builtins[i].gputype) {
|
||||
uniform = MEM_callocN(sizeof(GPUInputUniform), "GPUInputUniform");
|
||||
uniform->type = builtins[i].dynamictype;
|
||||
uniform->datatype = builtins[i].datatype;
|
||||
BLI_strncpy(uniform->varname, GPU_builtin_name(builtins[i].gputype), sizeof(uniform->varname));
|
||||
BLI_addtail(&shader->uniforms, uniform);
|
||||
}
|
||||
}
|
||||
|
||||
// now link fragement shader with library shader
|
||||
// TBD: remove the function that are not used in the main function
|
||||
liblen = (pass->libcode) ? strlen(pass->libcode) : 0;
|
||||
fraglen = strlen(pass->fragmentcode);
|
||||
shader->fragment = (char *)MEM_mallocN(liblen+fraglen+1, "GPUFragShader");
|
||||
if(pass->libcode)
|
||||
memcpy(shader->fragment, pass->libcode, liblen);
|
||||
memcpy(&shader->fragment[liblen], pass->fragmentcode, fraglen);
|
||||
shader->fragment[liblen+fraglen] = 0;
|
||||
|
||||
// export the attribute
|
||||
for(i=0; i<mat->attribs.totlayer; i++) {
|
||||
attribute = MEM_callocN(sizeof(GPUInputAttribute), "GPUInputAttribute");
|
||||
attribute->type = mat->attribs.layer[i].type;
|
||||
attribute->number = mat->attribs.layer[i].glindex;
|
||||
BLI_snprintf(attribute->varname, sizeof(attribute->varname), "att%d", mat->attribs.layer[i].attribid);
|
||||
|
||||
switch(attribute->type) {
|
||||
case CD_TANGENT:
|
||||
attribute->datatype = GPU_DATA_4F;
|
||||
break;
|
||||
case CD_MTFACE:
|
||||
attribute->datatype = GPU_DATA_2F;
|
||||
attribute->name = mat->attribs.layer[i].name;
|
||||
break;
|
||||
case CD_MCOL:
|
||||
attribute->datatype = GPU_DATA_4UB;
|
||||
attribute->name = mat->attribs.layer[i].name;
|
||||
break;
|
||||
case CD_ORCO:
|
||||
attribute->datatype = GPU_DATA_3F;
|
||||
break;
|
||||
}
|
||||
|
||||
if(attribute->datatype != GPU_DATA_NONE)
|
||||
BLI_addtail(&shader->attributes, attribute);
|
||||
else
|
||||
MEM_freeN(attribute);
|
||||
}
|
||||
|
||||
// export the vertex shader
|
||||
shader->vertex = BLI_strdup(pass->vertexcode);
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
void GPU_free_shader_export(GPUShaderExport *shader)
|
||||
{
|
||||
GPUInputUniform *uniform;
|
||||
|
||||
if(shader == NULL)
|
||||
return;
|
||||
|
||||
for(uniform = shader->uniforms.first; uniform; uniform=uniform->next)
|
||||
if(uniform->texpixels)
|
||||
MEM_freeN(uniform->texpixels);
|
||||
|
||||
BLI_freelistN(&shader->uniforms);
|
||||
BLI_freelistN(&shader->attributes);
|
||||
|
||||
if(shader->vertex)
|
||||
MEM_freeN(shader->vertex);
|
||||
if(shader->fragment)
|
||||
MEM_freeN(shader->fragment);
|
||||
|
||||
MEM_freeN(shader);
|
||||
}
|
||||
|
||||
|
||||
@@ -308,22 +308,22 @@ void normal(vec3 dir, vec3 nor, out vec3 outnor, out float outdot)
|
||||
outdot = -dot(dir, nor);
|
||||
}
|
||||
|
||||
void curves_vec(float fac, vec3 vec, sampler1D curvemap, out vec3 outvec)
|
||||
void curves_vec(float fac, vec3 vec, sampler2D curvemap, out vec3 outvec)
|
||||
{
|
||||
outvec.x = texture1D(curvemap, (vec.x + 1.0)*0.5).x;
|
||||
outvec.y = texture1D(curvemap, (vec.y + 1.0)*0.5).y;
|
||||
outvec.z = texture1D(curvemap, (vec.z + 1.0)*0.5).z;
|
||||
outvec.x = texture2D(curvemap, vec2((vec.x + 1.0)*0.5, 0.0)).x;
|
||||
outvec.y = texture2D(curvemap, vec2((vec.y + 1.0)*0.5, 0.0)).y;
|
||||
outvec.z = texture2D(curvemap, vec2((vec.z + 1.0)*0.5, 0.0)).z;
|
||||
|
||||
if (fac != 1.0)
|
||||
outvec = (outvec*fac) + (vec*(1.0-fac));
|
||||
|
||||
}
|
||||
|
||||
void curves_rgb(float fac, vec4 col, sampler1D curvemap, out vec4 outcol)
|
||||
void curves_rgb(float fac, vec4 col, sampler2D curvemap, out vec4 outcol)
|
||||
{
|
||||
outcol.r = texture1D(curvemap, texture1D(curvemap, col.r).a).r;
|
||||
outcol.g = texture1D(curvemap, texture1D(curvemap, col.g).a).g;
|
||||
outcol.b = texture1D(curvemap, texture1D(curvemap, col.b).a).b;
|
||||
outcol.r = texture2D(curvemap, vec2(texture2D(curvemap, vec2(col.r, 0.0)).a, 0.0)).r;
|
||||
outcol.g = texture2D(curvemap, vec2(texture2D(curvemap, vec2(col.g, 0.0)).a, 0.0)).g;
|
||||
outcol.b = texture2D(curvemap, vec2(texture2D(curvemap, vec2(col.b, 0.0)).a, 0.0)).b;
|
||||
|
||||
if (fac != 1.0)
|
||||
outcol = (outcol*fac) + (col*(1.0-fac));
|
||||
@@ -635,9 +635,9 @@ void mix_linear(float fac, vec4 col1, vec4 col2, out vec4 outcol)
|
||||
outcol.b= col1.b + fac*(2.0*(col2.b) - 1.0);
|
||||
}
|
||||
|
||||
void valtorgb(float fac, sampler1D colormap, out vec4 outcol, out float outalpha)
|
||||
void valtorgb(float fac, sampler2D colormap, out vec4 outcol, out float outalpha)
|
||||
{
|
||||
outcol = texture1D(colormap, fac);
|
||||
outcol = texture2D(colormap, vec2(fac, 0.0));
|
||||
outalpha = outcol.a;
|
||||
}
|
||||
|
||||
@@ -1320,9 +1320,9 @@ void lamp_falloff_sliders(float lampdist, float ld1, float ld2, float dist, out
|
||||
visifac *= lampdistkw/(lampdistkw + ld2*dist*dist);
|
||||
}
|
||||
|
||||
void lamp_falloff_curve(float lampdist, sampler1D curvemap, float dist, out float visifac)
|
||||
void lamp_falloff_curve(float lampdist, sampler2D curvemap, float dist, out float visifac)
|
||||
{
|
||||
visifac = texture1D(curvemap, dist/lampdist).x;
|
||||
visifac = texture2D(curvemap, vec2(dist/lampdist, 0.0)).x;
|
||||
}
|
||||
|
||||
void lamp_visibility_sphere(float lampdist, float dist, float visifac, out float outvisifac)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -51,6 +51,8 @@ typedef struct TreeStore {
|
||||
#define TSE_CLOSED 1
|
||||
#define TSE_SELECTED 2
|
||||
#define TSE_TEXTBUT 4
|
||||
#define TSE_CHILDSEARCH 8
|
||||
#define TSE_SEARCHMATCH 16
|
||||
|
||||
/* TreeStoreElem types in BIF_outliner.h */
|
||||
|
||||
|
||||
@@ -861,6 +861,7 @@ enum {
|
||||
/* outliner search flags (SpaceOops->search_flags) */
|
||||
#define SO_FIND_CASE_SENSITIVE (1<<0)
|
||||
#define SO_FIND_COMPLETE (1<<1)
|
||||
#define SO_SEARCH_RECURSIVE (1<<2)
|
||||
|
||||
/* headerbuttons: 450-499 */
|
||||
|
||||
|
||||
@@ -978,7 +978,11 @@ StructRNA *ID_code_to_RNA_type(short idcode);
|
||||
|
||||
|
||||
/* macro which inserts the function name */
|
||||
#ifdef __GNUC__
|
||||
# define RNA_warning(format, args...) _RNA_warning("%s: " format "\n", __func__, ##args)
|
||||
#else /* MSVC doesnt support variable length args in macros */
|
||||
# define RNA_warning _RNA_warning
|
||||
#endif
|
||||
|
||||
void _RNA_warning(const char *format, ...)
|
||||
#ifdef __GNUC__
|
||||
|
||||
@@ -5383,6 +5383,11 @@ void _RNA_warning(const char *format, ...)
|
||||
vprintf(format, args);
|
||||
va_end(args);
|
||||
|
||||
/* gcc macro adds '\n', but cant use for other compilers */
|
||||
#ifndef __GNUC__
|
||||
fputc('\n', stdout);
|
||||
#endif
|
||||
|
||||
#ifdef WITH_PYTHON
|
||||
{
|
||||
extern void PyC_LineSpit(void);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
Import ('env')
|
||||
|
||||
incs = '. ../editors/include ../makesdna ../makesrna ../blenlib ../blenkernel ../nodes'
|
||||
incs += ' ../imbuf ../blenloader ../render/extern/include ../windowmanager'
|
||||
incs += ' ../imbuf ../blenloader ../gpu ../render/extern/include ../windowmanager'
|
||||
incs += ' #intern/guardedalloc #intern/memutil #extern/glew/include'
|
||||
incs += ' #intern/audaspace/intern ' + env['BF_PYTHON_INC']
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ set(INC
|
||||
../../makesdna
|
||||
../../makesrna
|
||||
../../windowmanager
|
||||
../../gpu
|
||||
../../../../intern/guardedalloc
|
||||
)
|
||||
|
||||
@@ -40,6 +41,7 @@ set(INC_SYS
|
||||
)
|
||||
|
||||
set(SRC
|
||||
gpu.c
|
||||
bpy.c
|
||||
bpy_app.c
|
||||
bpy_app_handlers.c
|
||||
@@ -58,6 +60,7 @@ set(SRC
|
||||
bpy_util.c
|
||||
stubs.c
|
||||
|
||||
gpu.h
|
||||
bpy.h
|
||||
bpy_app.h
|
||||
bpy_app_handlers.h
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "RNA_types.h"
|
||||
|
||||
#include "bpy.h"
|
||||
#include "gpu.h"
|
||||
#include "bpy_rna.h"
|
||||
#include "bpy_util.h"
|
||||
#include "bpy_traceback.h"
|
||||
@@ -181,6 +182,7 @@ static struct _inittab bpy_internal_modules[]= {
|
||||
#ifdef WITH_AUDASPACE
|
||||
{(char *)"aud", AUD_initPython},
|
||||
#endif
|
||||
{(char *)"gpu", GPU_initPython},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
294
source/blender/python/intern/gpu.c
Normal file
294
source/blender/python/intern/gpu.c
Normal file
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2006 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): Benoit Bolsee.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/python/intern/gpu.c
|
||||
* \ingroup pythonintern
|
||||
*/
|
||||
|
||||
/* python redefines */
|
||||
#ifdef _POSIX_C_SOURCE
|
||||
#undef _POSIX_C_SOURCE
|
||||
#endif
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
#include "GPU_material.h"
|
||||
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_image_types.h"
|
||||
#include "DNA_material_types.h"
|
||||
#include "DNA_lamp_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_ID.h"
|
||||
#include "DNA_customdata_types.h"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
#include "bpy_rna.h"
|
||||
|
||||
#define PY_MODULE_ADD_CONSTANT(module, name) PyModule_AddIntConstant(module, #name, name)
|
||||
|
||||
PyDoc_STRVAR(M_gpu_doc,
|
||||
"This module provides access to the GLSL shader.");
|
||||
|
||||
static struct PyModuleDef gpumodule = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"gpu", /* name of module */
|
||||
M_gpu_doc, /* module documentation */
|
||||
-1, /* size of per-interpreter state of the module,
|
||||
or -1 if the module keeps state in global variables. */
|
||||
NULL, NULL, NULL, NULL, NULL
|
||||
};
|
||||
|
||||
PyMODINIT_FUNC
|
||||
PyInit_gpu(void)
|
||||
{
|
||||
PyObject* m;
|
||||
|
||||
m = PyModule_Create(&gpumodule);
|
||||
if(m == NULL)
|
||||
return NULL;
|
||||
|
||||
// device constants
|
||||
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_VIEWMAT);
|
||||
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_MAT);
|
||||
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_VIEWIMAT);
|
||||
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_IMAT);
|
||||
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_COLOR);
|
||||
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNVEC);
|
||||
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNCO);
|
||||
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNIMAT);
|
||||
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNPERSMAT);
|
||||
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNENERGY);
|
||||
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNCOL);
|
||||
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_SAMPLER_2DBUFFER);
|
||||
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_SAMPLER_2DIMAGE);
|
||||
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_SAMPLER_2DSHADOW);
|
||||
|
||||
PY_MODULE_ADD_CONSTANT(m, GPU_DATA_1I);
|
||||
PY_MODULE_ADD_CONSTANT(m, GPU_DATA_1F);
|
||||
PY_MODULE_ADD_CONSTANT(m, GPU_DATA_2F);
|
||||
PY_MODULE_ADD_CONSTANT(m, GPU_DATA_3F);
|
||||
PY_MODULE_ADD_CONSTANT(m, GPU_DATA_4F);
|
||||
PY_MODULE_ADD_CONSTANT(m, GPU_DATA_9F);
|
||||
PY_MODULE_ADD_CONSTANT(m, GPU_DATA_16F);
|
||||
PY_MODULE_ADD_CONSTANT(m, GPU_DATA_4UB);
|
||||
|
||||
PY_MODULE_ADD_CONSTANT(m, CD_MTFACE);
|
||||
PY_MODULE_ADD_CONSTANT(m, CD_ORCO);
|
||||
PY_MODULE_ADD_CONSTANT(m, CD_TANGENT);
|
||||
PY_MODULE_ADD_CONSTANT(m, CD_MCOL);
|
||||
return m;
|
||||
}
|
||||
|
||||
#define PY_DICT_ADD_STRING(d,s,f) \
|
||||
val = PyUnicode_FromString(s->f); \
|
||||
PyDict_SetItemString(d, #f, val); \
|
||||
Py_DECREF(val)
|
||||
|
||||
#define PY_DICT_ADD_LONG(d,s,f) \
|
||||
val = PyLong_FromLong(s->f); \
|
||||
PyDict_SetItemString(d, #f, val); \
|
||||
Py_DECREF(val)
|
||||
|
||||
#define PY_DICT_ADD_ID(d,s,f) \
|
||||
RNA_id_pointer_create((struct ID*)s->f, &tptr); \
|
||||
val = pyrna_struct_CreatePyObject(&tptr); \
|
||||
PyDict_SetItemString(d, #f, val); \
|
||||
Py_DECREF(val)
|
||||
|
||||
#define PY_OBJ_ADD_ID(d,s,f) \
|
||||
val = PyUnicode_FromString(&s->f->id.name[2]); \
|
||||
PyObject_SetAttrString(d, #f, val); \
|
||||
Py_DECREF(val)
|
||||
|
||||
#define PY_OBJ_ADD_LONG(d,s,f) \
|
||||
val = PyLong_FromLong(s->f); \
|
||||
PyObject_SetAttrString(d, #f, val); \
|
||||
Py_DECREF(val)
|
||||
|
||||
#define PY_OBJ_ADD_STRING(d,s,f) \
|
||||
val = PyUnicode_FromString(s->f); \
|
||||
PyObject_SetAttrString(d, #f, val); \
|
||||
Py_DECREF(val)
|
||||
|
||||
static PyObject* GPU_export_shader(PyObject* UNUSED(self), PyObject *args, PyObject *kwds)
|
||||
{
|
||||
PyObject* pyscene;
|
||||
PyObject* pymat;
|
||||
PyObject* as_pointer;
|
||||
PyObject* pointer;
|
||||
PyObject* noargs;
|
||||
PyObject* result;
|
||||
PyObject* dict;
|
||||
PyObject* val;
|
||||
PyObject* seq;
|
||||
|
||||
int i;
|
||||
Scene *scene;
|
||||
PointerRNA tptr;
|
||||
Material *material;
|
||||
GPUShaderExport *shader;
|
||||
GPUInputUniform *uniform;
|
||||
GPUInputAttribute *attribute;
|
||||
|
||||
static const char *kwlist[] = {"scene", "material", NULL};
|
||||
|
||||
if(!PyArg_ParseTupleAndKeywords(args, kwds, "OO:export_shader", (char**)(kwlist), &pyscene, &pymat))
|
||||
return NULL;
|
||||
|
||||
if (!strcmp(Py_TYPE(pyscene)->tp_name, "Scene") &&
|
||||
(as_pointer = PyObject_GetAttrString(pyscene, "as_pointer")) != NULL &&
|
||||
PyCallable_Check(as_pointer)) {
|
||||
// must be a scene object
|
||||
noargs = PyTuple_New(0);
|
||||
pointer = PyObject_CallObject(as_pointer, noargs);
|
||||
Py_DECREF(noargs);
|
||||
if (!pointer) {
|
||||
PyErr_SetString(PyExc_SystemError, "scene.as_pointer() failed");
|
||||
return NULL;
|
||||
}
|
||||
scene = (Scene*)PyLong_AsVoidPtr(pointer);
|
||||
Py_DECREF(pointer);
|
||||
if (!scene) {
|
||||
PyErr_SetString(PyExc_SystemError, "scene.as_pointer() failed");
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
PyErr_SetString(PyExc_TypeError, "gpu.export_shader() first argument should be of Scene type");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!strcmp(Py_TYPE(pymat)->tp_name, "Material") &&
|
||||
(as_pointer = PyObject_GetAttrString(pymat, "as_pointer")) != NULL &&
|
||||
PyCallable_Check(as_pointer)) {
|
||||
// must be a material object
|
||||
noargs = PyTuple_New(0);
|
||||
pointer = PyObject_CallObject(as_pointer, noargs);
|
||||
Py_DECREF(noargs);
|
||||
if (!pointer) {
|
||||
PyErr_SetString(PyExc_SystemError, "scene.as_pointer() failed");
|
||||
return NULL;
|
||||
}
|
||||
material = (Material*)PyLong_AsVoidPtr(pointer);
|
||||
Py_DECREF(pointer);
|
||||
if (!material) {
|
||||
PyErr_SetString(PyExc_SystemError, "scene.as_pointer() failed");
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
PyErr_SetString(PyExc_TypeError, "gpu.export_shader() second argument should be of Material type");
|
||||
return NULL;
|
||||
}
|
||||
// we can call our internal function at last:
|
||||
shader = GPU_shader_export(scene, material);
|
||||
if (!shader) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "cannot export shader");
|
||||
return NULL;
|
||||
}
|
||||
// build a dictionary
|
||||
result = PyDict_New();
|
||||
if (shader->fragment) {
|
||||
PY_DICT_ADD_STRING(result,shader,fragment);
|
||||
}
|
||||
if (shader->vertex) {
|
||||
PY_DICT_ADD_STRING(result,shader,vertex);
|
||||
}
|
||||
seq = PyList_New(BLI_countlist(&shader->uniforms));
|
||||
for (i=0, uniform=shader->uniforms.first; uniform; uniform=uniform->next, i++) {
|
||||
dict = PyDict_New();
|
||||
PY_DICT_ADD_STRING(dict,uniform,varname);
|
||||
PY_DICT_ADD_LONG(dict,uniform,datatype);
|
||||
PY_DICT_ADD_LONG(dict,uniform,type);
|
||||
if (uniform->lamp) {
|
||||
PY_DICT_ADD_ID(dict,uniform,lamp);
|
||||
}
|
||||
if (uniform->image) {
|
||||
PY_DICT_ADD_ID(dict,uniform,image);
|
||||
}
|
||||
if (uniform->type == GPU_DYNAMIC_SAMPLER_2DBUFFER ||
|
||||
uniform->type == GPU_DYNAMIC_SAMPLER_2DIMAGE ||
|
||||
uniform->type == GPU_DYNAMIC_SAMPLER_2DSHADOW) {
|
||||
PY_DICT_ADD_LONG(dict,uniform,texnumber);
|
||||
}
|
||||
if (uniform->texpixels) {
|
||||
val = PyByteArray_FromStringAndSize((const char *)uniform->texpixels, uniform->texsize);
|
||||
PyDict_SetItemString(dict, "texpixels", val);
|
||||
Py_DECREF(val);
|
||||
PY_DICT_ADD_LONG(dict,uniform,texsize);
|
||||
}
|
||||
PyList_SET_ITEM(seq, i, dict);
|
||||
}
|
||||
PyDict_SetItemString(result, "uniforms", seq);
|
||||
Py_DECREF(seq);
|
||||
|
||||
seq = PyList_New(BLI_countlist(&shader->attributes));
|
||||
for (i=0, attribute=shader->attributes.first; attribute; attribute=attribute->next, i++) {
|
||||
dict = PyDict_New();
|
||||
PY_DICT_ADD_STRING(dict,attribute,varname);
|
||||
PY_DICT_ADD_LONG(dict,attribute,datatype);
|
||||
PY_DICT_ADD_LONG(dict,attribute,type);
|
||||
PY_DICT_ADD_LONG(dict,attribute,number);
|
||||
if (attribute->name) {
|
||||
if (attribute->name[0] != 0) {
|
||||
PY_DICT_ADD_STRING(dict,attribute,name);
|
||||
} else {
|
||||
val = PyLong_FromLong(0);
|
||||
PyDict_SetItemString(dict, "name", val);
|
||||
Py_DECREF(val);
|
||||
}
|
||||
}
|
||||
PyList_SET_ITEM(seq, i, dict);
|
||||
}
|
||||
PyDict_SetItemString(result, "attributes", seq);
|
||||
Py_DECREF(seq);
|
||||
|
||||
GPU_free_shader_export(shader);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static PyMethodDef meth_export_shader[] = {{ "export_shader", (PyCFunction)GPU_export_shader, METH_VARARGS | METH_KEYWORDS,
|
||||
"export_shader(scene,material)\n\n"
|
||||
"Returns the GLSL shader that produces the visual effect of material in scene.\n\n"
|
||||
":return: Dictionary defining the shader, uniforms and attributes.\n"
|
||||
":rtype: Dict"}};
|
||||
|
||||
PyObject* GPU_initPython(void)
|
||||
{
|
||||
PyObject* module = PyInit_gpu();
|
||||
PyModule_AddObject(module, "export_shader", (PyObject *)PyCFunction_New(meth_export_shader, NULL));
|
||||
PyDict_SetItemString(PyImport_GetModuleDict(), "gpu", module);
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
41
source/blender/python/intern/gpu.h
Normal file
41
source/blender/python/intern/gpu.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This shader 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. The Blender
|
||||
* Foundation also sells licenses for use in proprietary software under
|
||||
* the Blender License. See http://www.blender.org/BL/ for information
|
||||
* about this.
|
||||
*
|
||||
* This shader 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 shader; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2005 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): Benoit Bolsee.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/python/intern/gpu.h
|
||||
* \ingroup pythonintern
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initalizes the gpu Python module.
|
||||
*/
|
||||
PyObject* GPU_initPython(void);
|
||||
|
||||
Reference in New Issue
Block a user