Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndre Susano Pinto <andresusanopinto@gmail.com>2008-09-15 18:20:31 +0400
committerAndre Susano Pinto <andresusanopinto@gmail.com>2008-09-15 18:20:31 +0400
commita1d611e9bd3379dd2c002cd5a895c788962a19a5 (patch)
tree3c4bedb765464e1f2deadf2b1124c1228cd3d7e7 /source/blender/blenkernel
parent039ed9cb7f3edd2cae640065979aed4a7eb31103 (diff)
svn merge -r 16231:16536 https://svn.blender.org/svnroot/bf-blender/trunk/blender
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h49
-rw-r--r--source/blender/blenkernel/BKE_action.h2
-rw-r--r--source/blender/blenkernel/BKE_bad_level_calls.h4
-rw-r--r--source/blender/blenkernel/BKE_blender.h2
-rw-r--r--source/blender/blenkernel/BKE_colortools.h1
-rw-r--r--source/blender/blenkernel/BKE_global.h9
-rw-r--r--source/blender/blenkernel/BKE_mesh.h1
-rw-r--r--source/blender/blenkernel/BKE_node.h8
-rw-r--r--source/blender/blenkernel/BKE_particle.h1
-rw-r--r--source/blender/blenkernel/BKE_suggestions.h93
-rw-r--r--source/blender/blenkernel/BKE_text.h29
-rw-r--r--source/blender/blenkernel/BKE_texture.h1
-rw-r--r--source/blender/blenkernel/BKE_utildefines.h2
-rw-r--r--source/blender/blenkernel/CMakeLists.txt2
-rw-r--r--source/blender/blenkernel/SConscript1
-rw-r--r--source/blender/blenkernel/bad_level_call_stubs/stubs.c32
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c407
-rw-r--r--source/blender/blenkernel/intern/Makefile4
-rw-r--r--source/blender/blenkernel/intern/action.c4
-rw-r--r--source/blender/blenkernel/intern/anim.c21
-rw-r--r--source/blender/blenkernel/intern/armature.c21
-rw-r--r--source/blender/blenkernel/intern/blender.c36
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c138
-rw-r--r--source/blender/blenkernel/intern/colortools.c21
-rw-r--r--source/blender/blenkernel/intern/constraint.c108
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c15
-rw-r--r--source/blender/blenkernel/intern/effect.c15
-rw-r--r--source/blender/blenkernel/intern/exotic.c14
-rw-r--r--source/blender/blenkernel/intern/image.c11
-rw-r--r--source/blender/blenkernel/intern/ipo.c27
-rw-r--r--source/blender/blenkernel/intern/material.c7
-rw-r--r--source/blender/blenkernel/intern/mesh.c39
-rw-r--r--source/blender/blenkernel/intern/modifier.c14
-rw-r--r--source/blender/blenkernel/intern/node.c114
-rw-r--r--source/blender/blenkernel/intern/object.c15
-rw-r--r--source/blender/blenkernel/intern/particle.c33
-rw-r--r--source/blender/blenkernel/intern/particle_system.c623
-rw-r--r--source/blender/blenkernel/intern/shrinkwrap.c14
-rw-r--r--source/blender/blenkernel/intern/softbody.c76
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c179
-rw-r--r--source/blender/blenkernel/intern/suggestions.c254
-rw-r--r--source/blender/blenkernel/intern/text.c564
-rw-r--r--source/blender/blenkernel/intern/texture.c12
43 files changed, 2356 insertions, 667 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index 7dc10c53e22..171a73f72c4 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -55,6 +55,7 @@ struct EditMesh;
struct ModifierData;
struct MCol;
struct ColorBand;
+struct GPUVertexAttribs;
/* number of sub-elements each mesh element has (for interpolation) */
#define SUB_ELEMS_VERT 0
@@ -198,7 +199,8 @@ struct DerivedMesh {
*
* Also called for *final* editmode DerivedMeshes
*/
- void (*drawFacesSolid)(DerivedMesh *dm, int (*setMaterial)(int));
+ void (*drawFacesSolid)(DerivedMesh *dm,
+ int (*setMaterial)(int, void *attribs));
/* Draw all faces
* o If useTwoSided, draw front and back using col arrays
@@ -215,6 +217,13 @@ struct DerivedMesh {
int (*setDrawOptions)(struct MTFace *tface,
struct MCol *mcol, int matnr));
+ /* Draw all faces with GLSL materials
+ * o setMaterial is called for every different material nr
+ * o Only if setMaterial returns true
+ */
+ void (*drawFacesGLSL)(DerivedMesh *dm,
+ int (*setMaterial)(int, void *attribs));
+
/* Draw mapped faces (no color, or texture)
* o Only if !setDrawOptions or
* setDrawOptions(userData, mapped-face-index, drawSmooth_r)
@@ -241,6 +250,15 @@ struct DerivedMesh {
int index),
void *userData);
+ /* Draw mapped faces with GLSL materials
+ * o setMaterial is called for every different material nr
+ * o setDrawOptions is called for every face
+ * o Only if setMaterial and setDrawOptions return true
+ */
+ void (*drawMappedFacesGLSL)(DerivedMesh *dm,
+ int (*setMaterial)(int, void *attribs),
+ int (*setDrawOptions)(void *userData, int index), void *userData);
+
/* Draw mapped edges as lines
* o Only if !setDrawOptions or setDrawOptions(userData, mapped-edge)
* returns true
@@ -437,6 +455,35 @@ void weight_to_rgb(float input, float *fr, float *fg, float *fb);
/* determines required DerivedMesh data according to view and edit modes */
CustomDataMask get_viewedit_datamask();
+/* convert layers requested by a GLSL material to actually available layers in
+ * the DerivedMesh, with both a pointer for arrays and an offset for editmesh */
+typedef struct DMVertexAttribs {
+ struct {
+ struct MTFace *array;
+ int emOffset, glIndex;
+ } tface[MAX_MTFACE];
+
+ struct {
+ struct MCol *array;
+ int emOffset, glIndex;
+ } mcol[MAX_MCOL];
+
+ struct {
+ float (*array)[3];
+ int emOffset, glIndex;
+ } tang;
+
+ struct {
+ float (*array)[3];
+ int emOffset, glIndex;
+ } orco;
+
+ int tottface, totmcol, tottang, totorco;
+} DMVertexAttribs;
+
+void DM_vertex_attributes_from_gpu(DerivedMesh *dm,
+ struct GPUVertexAttribs *gattribs, DMVertexAttribs *attribs);
+
void DM_add_tangent_layer(DerivedMesh *dm);
#endif
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h
index 716eac81b55..4a13fa31f6c 100644
--- a/source/blender/blenkernel/BKE_action.h
+++ b/source/blender/blenkernel/BKE_action.h
@@ -159,7 +159,7 @@ float get_action_frame(struct Object *ob, float cframe);
/* map strip time to global time (frame nr) */
float get_action_frame_inv(struct Object *ob, float cframe);
/* builds a list of NlaIpoChannel with ipo values to write in datablock */
-void extract_ipochannels_from_action(ListBase *lb, struct ID *id, struct bAction *act, char *name, float ctime);
+void extract_ipochannels_from_action(ListBase *lb, struct ID *id, struct bAction *act, const char *name, float ctime);
/* write values returned by extract_ipochannels_from_action, returns the number of value written */
int execute_ipochannels(ListBase *lb);
diff --git a/source/blender/blenkernel/BKE_bad_level_calls.h b/source/blender/blenkernel/BKE_bad_level_calls.h
index 3e45749c26a..8dee9a27f49 100644
--- a/source/blender/blenkernel/BKE_bad_level_calls.h
+++ b/source/blender/blenkernel/BKE_bad_level_calls.h
@@ -115,10 +115,6 @@ void free_editArmature(void);
void docenter_new(void);
int saveover(char *str);
-/* image.c */
-#include "DNA_image_types.h"
-void free_realtime_image(Image *ima); // has to become a callback, opengl stuff
-
/* ipo.c */
void copy_view3d_lock(short val); // was a hack, to make scene layer ipo's possible
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index e403fc33e06..0591937ea4c 100644
--- a/source/blender/blenkernel/BKE_blender.h
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -41,7 +41,7 @@ struct ListBase;
struct MemFile;
#define BLENDER_VERSION 247
-#define BLENDER_SUBVERSION 1
+#define BLENDER_SUBVERSION 2
#define BLENDER_MINVERSION 245
#define BLENDER_MINSUBVERSION 15
diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h
index e78882220a9..555b467b1d6 100644
--- a/source/blender/blenkernel/BKE_colortools.h
+++ b/source/blender/blenkernel/BKE_colortools.h
@@ -57,6 +57,7 @@ void curvemapping_do_ibuf(struct CurveMapping *cumap, struct ImBuf *ibuf);
void curvemapping_premultiply(struct CurveMapping *cumap, int restore);
int curvemapping_RGBA_does_something(struct CurveMapping *cumap);
void curvemapping_initialize(struct CurveMapping *cumap);
+void curvemapping_table_RGBA(struct CurveMapping *cumap, float **array, int *size);
#endif
diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h
index 8c9634cba06..1cc336db69e 100644
--- a/source/blender/blenkernel/BKE_global.h
+++ b/source/blender/blenkernel/BKE_global.h
@@ -218,8 +218,15 @@ typedef struct Global {
#define G_FILE_NO_UI (1 << 10)
#define G_FILE_GAME_TO_IPO (1 << 11)
#define G_FILE_GAME_MAT (1 << 12)
-#define G_FILE_DIAPLAY_LISTS (1 << 13)
+#define G_FILE_DISPLAY_LISTS (1 << 13)
#define G_FILE_SHOW_PHYSICS (1 << 14)
+#define G_FILE_GAME_MAT_GLSL (1 << 15)
+#define G_FILE_GLSL_NO_LIGHTS (1 << 16)
+#define G_FILE_GLSL_NO_SHADERS (1 << 17)
+#define G_FILE_GLSL_NO_SHADOWS (1 << 18)
+#define G_FILE_GLSL_NO_RAMPS (1 << 19)
+#define G_FILE_GLSL_NO_NODES (1 << 20)
+#define G_FILE_GLSL_NO_EXTRA_TEX (1 << 21)
/* G.windowstate */
#define G_WINDOWSTATE_USERDEF 0
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index d4ae76e8984..2ca4b3aa39a 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -68,7 +68,6 @@ void mball_to_mesh(struct ListBase *lb, struct Mesh *me);
void nurbs_to_mesh(struct Object *ob);
void free_dverts(struct MDeformVert *dvert, int totvert);
void copy_dverts(struct MDeformVert *dst, struct MDeformVert *src, int totvert); /* __NLA */
-int update_realtime_texture(struct MTFace *tface, double time);
void mesh_delete_material_index(struct Mesh *me, int index);
void mesh_set_smooth_flag(struct Object *meshOb, int enableSmooth);
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index b3b68a9b3ff..01c54663c6d 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -47,6 +47,9 @@ struct rctf;
struct ListBase;
struct RenderData;
struct Scene;
+struct GPUMaterial;
+struct GPUNode;
+struct GPUNodeStack;
#define SOCK_IN 1
#define SOCK_OUT 2
@@ -91,6 +94,9 @@ typedef struct bNodeType {
void *pynode; /* holds pointer to python script */
void *pydict; /* holds pointer to python script dictionary (scope)*/
+ /* gpu */
+ int (*gpufunc)(struct GPUMaterial *mat, struct bNode *node, struct GPUNodeStack *in, struct GPUNodeStack *out);
+
} bNodeType;
/* node->exec, now in use for composites (#define for break is same as ready yes) */
@@ -252,6 +258,8 @@ void nodeShaderSynchronizeID(struct bNode *node, int copyto);
extern void (*node_shader_lamp_loop)(struct ShadeInput *, struct ShadeResult *);
void set_node_shader_lamp_loop(void (*lamp_loop_func)(struct ShadeInput *, struct ShadeResult *));
+void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMaterial *mat);
+
/* ************** COMPOSITE NODES *************** */
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index 944a9081679..ea1dc7407db 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -302,6 +302,7 @@ int psys_particle_dm_face_lookup(struct Object *ob, struct DerivedMesh *dm, int
#define PSYS_RESET_ALL 1
#define PSYS_RESET_DEPSGRAPH 2
#define PSYS_RESET_CHILDREN 3
+#define PSYS_RESET_CACHE_MISS 4
/* ParticleEffectorCache->type */
#define PSYS_EC_EFFECTOR 1
diff --git a/source/blender/blenkernel/BKE_suggestions.h b/source/blender/blenkernel/BKE_suggestions.h
new file mode 100644
index 00000000000..d58b8f58bf5
--- /dev/null
+++ b/source/blender/blenkernel/BKE_suggestions.h
@@ -0,0 +1,93 @@
+/**
+ * $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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008, Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef BKE_SUGGESTIONS_H
+#define BKE_SUGGESTIONS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ****************************************************************************
+Suggestions should be added in sorted order although a linear sorting method is
+implemented. The list is then divided up based on the prefix provided by
+update_suggestions:
+
+Example:
+ Prefix: ab
+ aaa <-- first
+ aab
+ aba <-- firstmatch
+ abb <-- lastmatch
+ baa
+ bab <-- last
+**************************************************************************** */
+
+struct Text;
+
+typedef struct SuggItem {
+ struct SuggItem *prev, *next;
+ char *name;
+ char type;
+} SuggItem;
+
+typedef struct SuggList {
+ SuggItem *first, *last;
+ SuggItem *firstmatch, *lastmatch;
+ SuggItem *selected;
+ int top;
+} SuggList;
+
+/* Free all text tool memory */
+void free_texttools();
+
+/* Used to identify which Text object the current tools should appear against */
+void texttool_text_set_active(Text *text);
+void texttool_text_clear();
+short texttool_text_is_active(Text *text);
+
+/* Suggestions */
+void texttool_suggest_add(const char *name, char type);
+void texttool_suggest_prefix(const char *prefix);
+void texttool_suggest_clear();
+SuggItem *texttool_suggest_first();
+SuggItem *texttool_suggest_last();
+void texttool_suggest_select(SuggItem *sel);
+SuggItem *texttool_suggest_selected();
+int *texttool_suggest_top();
+
+/* Documentation */
+void texttool_docs_show(const char *docs);
+char *texttool_docs_get();
+void texttool_docs_clear();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h
index 6f891ab4887..002c804f17f 100644
--- a/source/blender/blenkernel/BKE_text.h
+++ b/source/blender/blenkernel/BKE_text.h
@@ -52,20 +52,24 @@ void txt_free_cut_buffer (void);
char* txt_to_buf (struct Text *text);
void txt_clean_text (struct Text *text);
void txt_order_cursors (struct Text *text);
-int txt_find_string (struct Text *text, char *findstr);
+int txt_find_string (struct Text *text, char *findstr, int wrap);
int txt_has_sel (struct Text *text);
int txt_get_span (struct TextLine *from, struct TextLine *to);
void txt_move_up (struct Text *text, short sel);
void txt_move_down (struct Text *text, short sel);
void txt_move_left (struct Text *text, short sel);
void txt_move_right (struct Text *text, short sel);
+void txt_jump_left (struct Text *text, short sel);
+void txt_jump_right (struct Text *text, short sel);
void txt_move_bof (struct Text *text, short sel);
void txt_move_eof (struct Text *text, short sel);
void txt_move_bol (struct Text *text, short sel);
void txt_move_eol (struct Text *text, short sel);
void txt_move_toline (struct Text *text, unsigned int line, short sel);
+void txt_move_to (struct Text *text, unsigned int line, unsigned int ch, short sel);
void txt_pop_sel (struct Text *text);
void txt_delete_char (struct Text *text);
+void txt_delete_word (struct Text *text);
void txt_copy_sel (struct Text *text);
void txt_sel_all (struct Text *text);
void txt_sel_line (struct Text *text);
@@ -80,8 +84,10 @@ void txt_do_undo (struct Text *text);
void txt_do_redo (struct Text *text);
void txt_split_curline (struct Text *text);
void txt_backspace_char (struct Text *text);
+void txt_backspace_word (struct Text *text);
int txt_add_char (struct Text *text, char add);
-void txt_find_panel (struct SpaceText *st, int again);
+int txt_replace_char (struct Text *text, char add);
+void find_and_replace (struct SpaceText *st, short mode);
void run_python_script (struct SpaceText *st);
int jumptoline_interactive (struct SpaceText *st);
void txt_export_to_object (struct Text *text);
@@ -94,6 +100,17 @@ int setcurr_tab (struct Text *text);
void convert_tabs (struct SpaceText *st, int tab);
void txt_copy_clipboard (struct Text *text);
void txt_paste_clipboard (struct Text *text);
+
+void txt_add_marker (struct Text *text, struct TextLine *line, int start, int end, char color[4], int group, int flags);
+short txt_clear_marker_region (struct Text *text, struct TextLine *line, int start, int end, int group, int flags);
+short txt_clear_markers (struct Text *text, int group, int flags);
+struct TextMarker *txt_find_marker (struct Text *text, struct TextLine *line, int curs, int group, int flags);
+struct TextMarker *txt_find_marker_region (struct Text *text, struct TextLine *line, int start, int end, int group, int flags);
+struct TextMarker *txt_prev_marker (struct Text *text, struct TextMarker *marker);
+struct TextMarker *txt_next_marker (struct Text *text, struct TextMarker *marker);
+struct TextMarker *txt_prev_marker_color (struct Text *text, struct TextMarker *marker);
+struct TextMarker *txt_next_marker_color (struct Text *text, struct TextMarker *marker);
+
/* Undo opcodes */
/* Simple main cursor movement */
@@ -135,6 +152,14 @@ void txt_paste_clipboard (struct Text *text);
#define UNDO_COMMENT 034
#define UNDO_UNCOMMENT 035
+/* Find and replace flags */
+#define TXT_FIND_WRAP 0x01
+#define TXT_FIND_ALLTEXTS 0x02
+
+/* Marker flags */
+#define TMARK_TEMP 0x01 /* Remove on non-editing events, don't save */
+#define TMARK_EDITALL 0x02 /* Edit all markers of the same group as one */
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h
index c162a04e055..cfcae3c44bc 100644
--- a/source/blender/blenkernel/BKE_texture.h
+++ b/source/blender/blenkernel/BKE_texture.h
@@ -53,6 +53,7 @@ void free_plugin_tex(struct PluginTex *pit);
void init_colorband(struct ColorBand *coba, int rangetype);
struct ColorBand *add_colorband(int rangetype);
int do_colorband(struct ColorBand *coba, float in, float out[4]);
+void colorband_table_RGBA(struct ColorBand *coba, float **array, int *size);
void default_tex(struct Tex *tex);
struct Tex *add_texture(char *name);
diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h
index f389521ffa0..d647a74c6e2 100644
--- a/source/blender/blenkernel/BKE_utildefines.h
+++ b/source/blender/blenkernel/BKE_utildefines.h
@@ -55,6 +55,8 @@
#define ELEM7(a, b, c, d, e, f, g, h) ( ELEM3(a, b, c, d) || ELEM4(a, e, f, g, h) )
#define ELEM8(a, b, c, d, e, f, g, h, i) ( ELEM4(a, b, c, d, e) || ELEM4(a, f, g, h, i) )
#define ELEM9(a, b, c, d, e, f, g, h, i, j) ( ELEM4(a, b, c, d, e) || ELEM5(a, f, g, h, i, j) )
+#define ELEM10(a, b, c, d, e, f, g, h, i, j, k) ( ELEM4(a, b, c, d, e) || ELEM6(a, f, g, h, i, j, k) )
+#define ELEM11(a, b, c, d, e, f, g, h, i, j, k, l) ( ELEM4(a, b, c, d, e) || ELEM7(a, f, g, h, i, j, k, l) )
/* shift around elements */
#define SHIFT3(type, a, b, c) { type tmp; tmp = a; a = c; c = b; b = tmp; }
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 9088b410e27..0345711c9c3 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -32,7 +32,7 @@ SET(INC
../imbuf ../avi ../../../intern/elbeem/extern ../../../intern/opennl/extern
../../../intern/iksolver/extern ../blenloader ../quicktime
../../../intern/bmfont ../../../extern/bullet2/src
- ../nodes
+ ../nodes ../../../extern/glew/include ../gpu
${SDL_INC}
${ZLIB_INC}
${PYTHON_INC}
diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript
index 1bb98239a68..db67251f44e 100644
--- a/source/blender/blenkernel/SConscript
+++ b/source/blender/blenkernel/SConscript
@@ -10,6 +10,7 @@ incs += ' #/intern/iksolver/extern ../blenloader ../quicktime'
incs += ' #/extern/bullet2/src'
incs += ' #/intern/bmfont'
incs += ' #/intern/opennl/extern'
+incs += ' ../gpu #/extern/glew/include'
incs += ' ' + env['BF_PYTHON_INC']
incs += ' ' + env['BF_OPENGL_INC']
diff --git a/source/blender/blenkernel/bad_level_call_stubs/stubs.c b/source/blender/blenkernel/bad_level_call_stubs/stubs.c
index 561d8d7c2a6..f4beca262d7 100644
--- a/source/blender/blenkernel/bad_level_call_stubs/stubs.c
+++ b/source/blender/blenkernel/bad_level_call_stubs/stubs.c
@@ -60,7 +60,7 @@ struct EditFace;
char *getIpoCurveName( struct IpoCurve * icu );
void insert_vert_icu(struct IpoCurve *icu, float x, float y, short fast);
-struct IpoCurve *verify_ipocurve(struct ID *id, short a, char *b, char *d, int e);
+struct IpoCurve *verify_ipocurve(struct ID *id, short a, char *b, char *d, int e, short f);
void elbeemDebugOut(char *msg);
void fluidsimSettingsFree(struct FluidsimSettings* sb);
void fluidsimSettingsCopy(struct FluidsimSettings* sb);
@@ -88,7 +88,7 @@ void insert_vert_icu(struct IpoCurve *icu, float x, float y, short fast)
}
-struct IpoCurve *verify_ipocurve(struct ID *id, short a, char *b, char *d, int e)
+struct IpoCurve *verify_ipocurve(struct ID *id, short a, char *b, char *d, int e, short f)
{
return 0;
}
@@ -176,10 +176,6 @@ void free_editMesh(struct EditMesh *em){}
void docenter_new(void){}
int saveover(char *str){ return 0;}
-/* image.c */
-#include "DNA_image_types.h"
-void free_realtime_image(Image *ima){} // has to become a callback, opengl stuff
-
/* ipo.c */
void copy_view3d_lock(short val){} // was a hack, to make scene layer ipo's possible
@@ -220,30 +216,6 @@ struct EditEdge *findedgelist(struct EditVert *v1, struct EditVert *v2) { retur
void countall(void) {}
-
-/* IKsolver stubs */
-#include "IK_solver.h"
-
-IK_Segment *IK_CreateSegment(int flag) { return 0; }
-void IK_FreeSegment(IK_Segment *seg) {}
-
-void IK_SetParent(IK_Segment *seg, IK_Segment *parent) {}
-void IK_SetTransform(IK_Segment *seg, float start[3], float rest_basis[][3], float basis[][3], float length) {}
-void IK_GetBasisChange(IK_Segment *seg, float basis_change[][3]) {}
-void IK_GetTranslationChange(IK_Segment *seg, float *translation_change) {};
-void IK_SetLimit(IK_Segment *seg, IK_SegmentAxis axis, float lower, float upper) {};
-void IK_SetStiffness(IK_Segment *seg, IK_SegmentAxis axis, float stiffness) {};
-
-IK_Solver *IK_CreateSolver(IK_Segment *root) { return 0; }
-void IK_FreeSolver(IK_Solver *solver) {};
-
-void IK_SolverAddGoal(IK_Solver *solver, IK_Segment *tip, float goal[3], float weight) {}
-void IK_SolverAddGoalOrientation(IK_Solver *solver, IK_Segment *tip, float goal[][3], float weight) {}
-void IK_SolverSetPoleVectorConstraint(IK_Solver *solver, IK_Segment *tip, float goal[3], float polegoal[3], float poleangle, int getangle) {}
-float IK_SolverGetPoleAngle(IK_Solver *solver) { return 0.0f; }
-
-int IK_Solve(IK_Solver *solver, float tolerance, int max_iterations) { return 0; }
-
/* exotic.c */
int BPY_call_importloader(char *name)
{
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 1dabab98a6e..328dcada01a 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -88,6 +88,10 @@
#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_draw.h"
+#include "GPU_extensions.h"
+#include "GPU_material.h"
+
// headers for fluidsim bobj meshes
#include <stdlib.h>
#include "LBM_fluidsim.h"
@@ -411,6 +415,8 @@ void DM_swap_face_data(DerivedMesh *dm, int index, int *corner_indices)
CustomData_swap(&dm->faceData, index, corner_indices);
}
+///
+
static DerivedMesh *getMeshDerivedMesh(Mesh *me, Object *ob, float (*vertCos)[3])
{
DerivedMesh *dm = CDDM_from_mesh(me, ob);
@@ -894,6 +900,162 @@ static void emDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void
emDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
}
+static void emDM_drawMappedFacesGLSL(DerivedMesh *dm,
+ int (*setMaterial)(int, void *attribs),
+ int (*setDrawOptions)(void *userData, int index), void *userData)
+{
+ EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+ EditMesh *em= emdm->em;
+ float (*vertexCos)[3]= emdm->vertexCos;
+ float (*vertexNos)[3]= emdm->vertexNos;
+ EditVert *eve;
+ EditFace *efa;
+ DMVertexAttribs attribs;
+ GPUVertexAttribs gattribs;
+ MTFace *tf;
+ int transp, new_transp, orig_transp, tfoffset;
+ int i, b, matnr, new_matnr, dodraw, layer;
+
+ dodraw = 0;
+ matnr = -1;
+
+ transp = GPU_get_material_blend_mode();
+ orig_transp = transp;
+ layer = CustomData_get_layer_index(&em->fdata, CD_MTFACE);
+ tfoffset = (layer == -1)? -1: em->fdata.layers[layer].offset;
+
+ memset(&attribs, 0, sizeof(attribs));
+
+ /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
+ glShadeModel(GL_SMOOTH);
+
+ for (i=0,eve=em->verts.first; eve; eve= eve->next)
+ eve->tmp.l = (long) i++;
+
+#define PASSATTRIB(efa, eve, vert) { \
+ if(attribs.totorco) { \
+ float *orco = attribs.orco.array[eve->tmp.l]; \
+ glVertexAttrib3fvARB(attribs.orco.glIndex, orco); \
+ } \
+ for(b = 0; b < attribs.tottface; b++) { \
+ MTFace *tf = (MTFace*)((char*)efa->data + attribs.tface[b].emOffset); \
+ glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]); \
+ } \
+ for(b = 0; b < attribs.totmcol; b++) { \
+ MCol *cp = (MCol*)((char*)efa->data + attribs.mcol[b].emOffset); \
+ GLubyte col[4]; \
+ col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; \
+ glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col); \
+ } \
+ if(attribs.tottang) { \
+ float *tang = attribs.tang.array[i*4 + vert]; \
+ glVertexAttrib3fvARB(attribs.tang.glIndex, tang); \
+ } \
+}
+
+ for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) {
+ int drawSmooth= (efa->flag & ME_SMOOTH);
+
+ if(setDrawOptions && !setDrawOptions(userData, i))
+ continue;
+
+ new_matnr = efa->mat_nr + 1;
+ if(new_matnr != matnr) {
+ dodraw = setMaterial(matnr = new_matnr, &gattribs);
+ if(dodraw)
+ DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
+ }
+
+ if(tfoffset != -1) {
+ tf = (MTFace*)((char*)efa->data)+tfoffset;
+ new_transp = tf->transp;
+
+ if(new_transp != transp) {
+ if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
+ GPU_set_material_blend_mode(orig_transp);
+ else
+ GPU_set_material_blend_mode(new_transp);
+ transp = new_transp;
+ }
+ }
+
+ if(dodraw) {
+ glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
+ if (!drawSmooth) {
+ if(vertexCos) glNormal3fv(emdm->faceNos[i]);
+ else glNormal3fv(efa->n);
+
+ PASSATTRIB(efa, efa->v1, 0);
+ if(vertexCos) glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
+ else glVertex3fv(efa->v1->co);
+
+ PASSATTRIB(efa, efa->v2, 1);
+ if(vertexCos) glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
+ else glVertex3fv(efa->v2->co);
+
+ PASSATTRIB(efa, efa->v3, 2);
+ if(vertexCos) glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
+ else glVertex3fv(efa->v3->co);
+
+ if(efa->v4) {
+ PASSATTRIB(efa, efa->v4, 3);
+ if(vertexCos) glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
+ else glVertex3fv(efa->v4->co);
+ }
+ } else {
+ PASSATTRIB(efa, efa->v1, 0);
+ if(vertexCos) {
+ glNormal3fv(vertexNos[(int) efa->v1->tmp.l]);
+ glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
+ }
+ else {
+ glNormal3fv(efa->v1->no);
+ glVertex3fv(efa->v1->co);
+ }
+
+ PASSATTRIB(efa, efa->v2, 1);
+ if(vertexCos) {
+ glNormal3fv(vertexNos[(int) efa->v2->tmp.l]);
+ glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
+ }
+ else {
+ glNormal3fv(efa->v2->no);
+ glVertex3fv(efa->v2->co);
+ }
+
+ PASSATTRIB(efa, efa->v3, 2);
+ if(vertexCos) {
+ glNormal3fv(vertexNos[(int) efa->v3->tmp.l]);
+ glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
+ }
+ else {
+ glNormal3fv(efa->v3->no);
+ glVertex3fv(efa->v3->co);
+ }
+
+ if(efa->v4) {
+ PASSATTRIB(efa, efa->v4, 3);
+ if(vertexCos) {
+ glNormal3fv(vertexNos[(int) efa->v4->tmp.l]);
+ glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
+ }
+ else {
+ glNormal3fv(efa->v4->no);
+ glVertex3fv(efa->v4->co);
+ }
+ }
+ }
+ glEnd();
+ }
+ }
+}
+
+static void emDM_drawFacesGLSL(DerivedMesh *dm,
+ int (*setMaterial)(int, void *attribs))
+{
+ dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
+}
+
static void emDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
{
EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
@@ -1099,6 +1261,43 @@ void emDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
}
}
+static void *emDM_getFaceDataArray(DerivedMesh *dm, int type)
+{
+ EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+ EditMesh *em= emdm->em;
+ EditFace *efa;
+ char *data, *emdata;
+ void *datalayer;
+ int index, offset, size;
+
+ datalayer = DM_get_face_data_layer(dm, type);
+ if(datalayer)
+ return datalayer;
+
+ /* layers are store per face for editmesh, we convert to a temporary
+ * data layer array in the derivedmesh when these are requested */
+ if(type == CD_MTFACE || type == CD_MCOL) {
+ index = CustomData_get_layer_index(&em->fdata, type);
+
+ if(index != -1) {
+ offset = em->fdata.layers[index].offset;
+ size = CustomData_sizeof(type);
+
+ DM_add_face_layer(dm, type, CD_CALLOC, NULL);
+ index = CustomData_get_layer_index(&dm->faceData, type);
+ dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY;
+
+ data = datalayer = DM_get_face_data_layer(dm, type);
+ for(efa=em->faces.first; efa; efa=efa->next, data+=size) {
+ emdata = CustomData_em_get(&em->fdata, efa->data, type);
+ memcpy(data, emdata, size);
+ }
+ }
+ }
+
+ return datalayer;
+}
+
static void emDM_release(DerivedMesh *dm)
{
EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
@@ -1134,6 +1333,7 @@ static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em, Object *ob,
emdm->dm.copyVertArray = emDM_copyVertArray;
emdm->dm.copyEdgeArray = emDM_copyEdgeArray;
emdm->dm.copyFaceArray = emDM_copyFaceArray;
+ emdm->dm.getFaceDataArray = emDM_getFaceDataArray;
emdm->dm.foreachMappedVert = emDM_foreachMappedVert;
emdm->dm.foreachMappedEdge = emDM_foreachMappedEdge;
@@ -1144,7 +1344,9 @@ static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em, Object *ob,
emdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp;
emdm->dm.drawMappedFaces = emDM_drawMappedFaces;
emdm->dm.drawMappedFacesTex = emDM_drawMappedFacesTex;
+ emdm->dm.drawMappedFacesGLSL = emDM_drawMappedFacesGLSL;
emdm->dm.drawFacesTex = emDM_drawFacesTex;
+ emdm->dm.drawFacesGLSL = emDM_drawFacesGLSL;
emdm->dm.drawUVEdges = emDM_drawUVEdges;
emdm->dm.release = emDM_release;
@@ -1574,7 +1776,7 @@ static void vDM_drawUVEdges(DerivedMesh *dm)
}
/* draw all VerseFaces */
-static void vDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int))
+static void vDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *attribs))
{
VDerivedMesh *vdm = (VDerivedMesh*)dm;
struct VerseFace *vface;
@@ -1674,6 +1876,8 @@ static void vDM_drawMappedFacesTex(
int (*setDrawParams)(void *userData, int index),
void *userData)
{
+ /* not supported yet */
+ vDM_drawFacesTex(dm, NULL);
}
/**/
@@ -1815,19 +2019,23 @@ CustomDataMask get_viewedit_datamask()
ScrArea *sa;
/* check if we need tfaces & mcols due to face select or texture paint */
- if(FACESEL_PAINT_TEST || G.f & G_TEXTUREPAINT) {
+ if(FACESEL_PAINT_TEST || G.f & G_TEXTUREPAINT)
mask |= CD_MASK_MTFACE | CD_MASK_MCOL;
- } else {
- /* check if we need tfaces & mcols due to view mode */
- for(sa = G.curscreen->areabase.first; sa; sa = sa->next) {
- if(sa->spacetype == SPACE_VIEW3D) {
- View3D *view = sa->spacedata.first;
- if(view->drawtype == OB_SHADED) {
- /* this includes normals for mesh_create_shadedColors */
- mask |= CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_NORMAL | CD_MASK_ORCO;
- }
- if((view->drawtype == OB_TEXTURE) || ((view->drawtype == OB_SOLID) && (view->flag2 & V3D_SOLID_TEX))) {
- mask |= CD_MASK_MTFACE | CD_MASK_MCOL;
+
+ /* check if we need tfaces & mcols due to view mode */
+ for(sa = G.curscreen->areabase.first; sa; sa = sa->next) {
+ if(sa->spacetype == SPACE_VIEW3D) {
+ View3D *view = sa->spacedata.first;
+ if(view->drawtype == OB_SHADED) {
+ /* this includes normals for mesh_create_shadedColors */
+ mask |= CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_NORMAL | CD_MASK_ORCO;
+ }
+ if((view->drawtype == OB_TEXTURE) || ((view->drawtype == OB_SOLID) && (view->flag2 & V3D_SOLID_TEX))) {
+ mask |= CD_MASK_MTFACE | CD_MASK_MCOL;
+
+ if((G.fileflags & G_FILE_GAME_MAT) &&
+ (G.fileflags & G_FILE_GAME_MAT_GLSL)) {
+ mask |= CD_MASK_ORCO;
}
}
}
@@ -1840,13 +2048,41 @@ CustomDataMask get_viewedit_datamask()
return mask;
}
-static DerivedMesh *create_orco_dm(Object *ob, Mesh *me)
+static float *get_editmesh_orco_verts(EditMesh *em)
+{
+ EditVert *eve;
+ float *orco;
+ int a, totvert;
+
+ /* these may not really be the orco's, but it's only for preview.
+ * could be solver better once, but isn't simple */
+
+ totvert= 0;
+ for(eve=em->verts.first; eve; eve=eve->next)
+ totvert++;
+
+ orco = MEM_mallocN(sizeof(float)*3*totvert, "EditMesh Orco");
+
+ for(a=0, eve=em->verts.first; eve; eve=eve->next, a+=3)
+ VECCOPY(orco+a, eve->co);
+
+ return orco;
+}
+
+static DerivedMesh *create_orco_dm(Object *ob, Mesh *me, EditMesh *em)
{
DerivedMesh *dm;
float (*orco)[3];
- dm= CDDM_from_mesh(me, ob);
- orco= (float(*)[3])get_mesh_orco_verts(ob);
+ if(em) {
+ dm= CDDM_from_editmesh(em, me);
+ orco= (float(*)[3])get_editmesh_orco_verts(em);
+ }
+ else {
+ dm= CDDM_from_mesh(me, ob);
+ orco= (float(*)[3])get_mesh_orco_verts(ob);
+ }
+
CDDM_apply_vert_coords(dm, orco);
CDDM_calc_normals(dm);
MEM_freeN(orco);
@@ -1854,7 +2090,7 @@ static DerivedMesh *create_orco_dm(Object *ob, Mesh *me)
return dm;
}
-static void add_orco_dm(Object *ob, DerivedMesh *dm, DerivedMesh *orcodm)
+static void add_orco_dm(Object *ob, EditMesh *em, DerivedMesh *dm, DerivedMesh *orcodm)
{
float (*orco)[3], (*layerorco)[3];
int totvert;
@@ -1869,8 +2105,10 @@ static void add_orco_dm(Object *ob, DerivedMesh *dm, DerivedMesh *orcodm)
else
dm->getVertCos(dm, orco);
}
- else
- orco= (float(*)[3])get_mesh_orco_verts(ob);
+ else {
+ if(em) orco= (float(*)[3])get_editmesh_orco_verts(em);
+ else orco= (float(*)[3])get_mesh_orco_verts(ob);
+ }
transform_mesh_orco_verts(ob->data, orco, totvert, 0);
@@ -2016,7 +2254,7 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3],
if(dm && mti->requiredDataMask) {
mask = mti->requiredDataMask(md);
if(mask & CD_MASK_ORCO)
- add_orco_dm(ob, dm, orcodm);
+ add_orco_dm(ob, NULL, dm, orcodm);
}
/* How to apply modifier depends on (a) what we already have as
@@ -2069,7 +2307,7 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3],
mask= (CustomDataMask)curr->link;
if(mask & CD_MASK_ORCO) {
if(!orcodm)
- orcodm= create_orco_dm(ob, me);
+ orcodm= create_orco_dm(ob, me, NULL);
mask &= ~CD_MASK_ORCO;
DM_set_only_copy(orcodm, mask);
@@ -2146,10 +2384,10 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3],
/* add an orco layer if needed */
if(dataMask & CD_MASK_ORCO) {
- add_orco_dm(ob, finaldm, orcodm);
+ add_orco_dm(ob, NULL, finaldm, orcodm);
if(deform_r && *deform_r)
- add_orco_dm(ob, *deform_r, NULL);
+ add_orco_dm(ob, NULL, *deform_r, NULL);
}
*final_r = finaldm;
@@ -2205,7 +2443,8 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r,
EditMesh *em = G.editMesh;
ModifierData *md;
float (*deformedVerts)[3] = NULL;
- DerivedMesh *dm;
+ CustomDataMask mask;
+ DerivedMesh *dm, *orcodm = NULL;
int i, numVerts = 0, cageIndex = modifiers_getCageIndex(ob, NULL);
LinkNode *datamasks, *curr;
@@ -2230,6 +2469,13 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r,
if(!editmesh_modifier_is_enabled(md, dm))
continue;
+ /* add an orco layer if needed by this modifier */
+ if(dm && mti->requiredDataMask) {
+ mask = mti->requiredDataMask(md);
+ if(mask & CD_MASK_ORCO)
+ add_orco_dm(ob, em, dm, orcodm);
+ }
+
/* How to apply modifier depends on (a) what we already have as
* a result of previous modifiers (could be a DerivedMesh or just
* deformed vertices) and (b) what type the modifier is.
@@ -2280,6 +2526,23 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r,
}
}
+ /* create an orco derivedmesh in parallel */
+ mask= (CustomDataMask)curr->link;
+ if(mask & CD_MASK_ORCO) {
+ if(!orcodm)
+ orcodm= create_orco_dm(ob, ob->data, em);
+
+ mask &= ~CD_MASK_ORCO;
+ DM_set_only_copy(orcodm, mask);
+ ndm = mti->applyModifierEM(md, ob, em, orcodm);
+
+ if(ndm) {
+ /* if the modifier returned a new dm, release the old one */
+ if(orcodm && orcodm != ndm) orcodm->release(orcodm);
+ orcodm = ndm;
+ }
+ }
+
/* set the DerivedMesh to only copy needed data */
DM_set_only_copy(dm, (CustomDataMask)curr->link);
@@ -2338,6 +2601,13 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r,
deformedVerts = NULL;
}
+ /* add an orco layer if needed */
+ if(dataMask & CD_MASK_ORCO)
+ add_orco_dm(ob, em, *final_r, orcodm);
+
+ if(orcodm)
+ orcodm->release(orcodm);
+
if(deformedVerts)
MEM_freeN(deformedVerts);
}
@@ -2632,7 +2902,7 @@ void multires_render_final(Object *ob, Mesh *me, DerivedMesh **dm, float *vert_c
old->release(old);
if(dataMask & CD_MASK_ORCO)
- add_orco_dm(ob, *dm, NULL);
+ add_orco_dm(ob, NULL, *dm, NULL);
/* Restore the original verts */
me->mr->newlvl= BLI_countlist(&me->mr->levels);
@@ -2847,6 +3117,8 @@ int editmesh_get_first_deform_matrices(float (**deformmats)[3][3], float (**defo
return numleft;
}
+/* ******************* GLSL ******************** */
+
void DM_add_tangent_layer(DerivedMesh *dm)
{
/* mesh vars */
@@ -2967,6 +3239,91 @@ void DM_add_tangent_layer(DerivedMesh *dm)
MEM_freeN(vtangents);
}
+void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, DMVertexAttribs *attribs)
+{
+ CustomData *vdata, *fdata, *tfdata = NULL;
+ int a, b, layer;
+
+ /* From the layers requested by the GLSL shader, figure out which ones are
+ * actually available for this derivedmesh, and retrieve the pointers */
+
+ memset(attribs, 0, sizeof(DMVertexAttribs));
+
+ vdata = &dm->vertData;
+ fdata = &dm->faceData;
+
+ /* ugly hack, editmesh derivedmesh doesn't copy face data, this way we
+ * can use offsets instead */
+ if(dm->release == emDM_release)
+ tfdata = &((EditMeshDerivedMesh*)dm)->em->fdata;
+ else
+ tfdata = fdata;
+
+ /* add a tangent layer if necessary */
+ for(b = 0; b < gattribs->totlayer; b++)
+ if(gattribs->layer[b].type == CD_TANGENT)
+ if(CustomData_get_layer_index(fdata, CD_TANGENT) == -1)
+ DM_add_tangent_layer(dm);
+
+ for(b = 0; b < gattribs->totlayer; b++) {
+ if(gattribs->layer[b].type == CD_MTFACE) {
+ /* uv coordinates */
+ if(gattribs->layer[b].name[0])
+ layer = CustomData_get_named_layer_index(tfdata, CD_MTFACE,
+ gattribs->layer[b].name);
+ else
+ layer = CustomData_get_active_layer_index(tfdata, CD_MTFACE);
+
+ if(layer != -1) {
+ a = attribs->tottface++;
+
+ attribs->tface[a].array = tfdata->layers[layer].data;
+ attribs->tface[a].emOffset = tfdata->layers[layer].offset;
+ attribs->tface[a].glIndex = gattribs->layer[b].glindex;
+ }
+ }
+ else if(gattribs->layer[b].type == CD_MCOL) {
+ /* vertex colors */
+ if(gattribs->layer[b].name[0])
+ layer = CustomData_get_named_layer_index(tfdata, CD_MCOL,
+ gattribs->layer[b].name);
+ else
+ layer = CustomData_get_active_layer_index(tfdata, CD_MCOL);
+
+ if(layer != -1) {
+ a = attribs->totmcol++;
+
+ attribs->mcol[a].array = tfdata->layers[layer].data;
+ attribs->mcol[a].emOffset = tfdata->layers[layer].offset;
+ attribs->mcol[a].glIndex = gattribs->layer[b].glindex;
+ }
+ }
+ else if(gattribs->layer[b].type == CD_TANGENT) {
+ /* tangents */
+ layer = CustomData_get_layer_index(fdata, CD_TANGENT);
+
+ if(layer != -1) {
+ attribs->tottang = 1;
+
+ attribs->tang.array = fdata->layers[layer].data;
+ attribs->tang.emOffset = fdata->layers[layer].offset;
+ attribs->tang.glIndex = gattribs->layer[b].glindex;
+ }
+ }
+ else if(gattribs->layer[b].type == CD_ORCO) {
+ /* original coordinates */
+ layer = CustomData_get_layer_index(vdata, CD_ORCO);
+
+ if(layer != -1) {
+ attribs->totorco = 1;
+
+ attribs->orco.array = vdata->layers[layer].data;
+ attribs->orco.emOffset = vdata->layers[layer].offset;
+ attribs->orco.glIndex = gattribs->layer[b].glindex;
+ }
+ }
+ }
+}
/* ************************* fluidsim bobj file handling **************************** */
diff --git a/source/blender/blenkernel/intern/Makefile b/source/blender/blenkernel/intern/Makefile
index 74c6c551a83..8921ea5d3b7 100644
--- a/source/blender/blenkernel/intern/Makefile
+++ b/source/blender/blenkernel/intern/Makefile
@@ -36,6 +36,7 @@ include nan_compile.mk
CFLAGS += $(LEVEL_1_C_WARNINGS)
# OpenGL and Python
+CPPFLAGS += -I$(NAN_GLEW)/include
CPPFLAGS += -I$(OPENGL_HEADERS)
CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
@@ -74,6 +75,9 @@ CPPFLAGS += -I$(NAN_ZLIB)/include
#path to nodes
CPPFLAGS += -I../../nodes
+#path to gpu
+CPPFLAGS += -I../../gpu
+
# path to our own external headerfiles
CPPFLAGS += -I..
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index 5b96bf11056..043ede5987a 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -347,6 +347,8 @@ static void copy_pose_channel_data(bPoseChannel *pchan, const bPoseChannel *chan
VECCOPY(pchan->loc, chan->loc);
VECCOPY(pchan->size, chan->size);
QUATCOPY(pchan->quat, chan->quat);
+ Mat4CpyMat4(pchan->chan_mat, (float(*)[4])chan->chan_mat);
+ Mat4CpyMat4(pchan->pose_mat, (float(*)[4])chan->pose_mat);
pchan->flag= chan->flag;
con= chan->constraints.first;
@@ -860,7 +862,7 @@ typedef struct NlaIpoChannel {
int type;
} NlaIpoChannel;
-void extract_ipochannels_from_action(ListBase *lb, ID *id, bAction *act, char *name, float ctime)
+void extract_ipochannels_from_action(ListBase *lb, ID *id, bAction *act, const char *name, float ctime)
{
bActionChannel *achan= get_action_channel(act, name);
IpoCurve *icu;
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
index 1592c3e5504..ceb0e132ff9 100644
--- a/source/blender/blenkernel/intern/anim.c
+++ b/source/blender/blenkernel/intern/anim.c
@@ -303,7 +303,7 @@ static void group_duplilist(ListBase *lb, Object *ob, int level, int animated)
DupliObject *dob;
Group *group;
GroupObject *go;
- float mat[4][4];
+ float mat[4][4], tmat[4][4];
if(ob->dup_group==NULL) return;
group= ob->dup_group;
@@ -320,7 +320,15 @@ static void group_duplilist(ListBase *lb, Object *ob, int level, int animated)
/* note, if you check on layer here, render goes wrong... it still deforms verts and uses parent imat */
if(go->ob!=ob) {
- Mat4MulMat4(mat, go->ob->obmat, ob->obmat);
+ /* Group Dupli Offset, should apply after everything else */
+ if (group->dupli_ofs[0] || group->dupli_ofs[1] || group->dupli_ofs[2]) {
+ Mat4CpyMat4(tmat, go->ob->obmat);
+ VecSubf(tmat[3], tmat[3], group->dupli_ofs);
+ Mat4MulMat4(mat, tmat, ob->obmat);
+ } else {
+ Mat4MulMat4(mat, go->ob->obmat, ob->obmat);
+ }
+
dob= new_dupli_object(lb, go->ob, mat, ob->lay, 0, OB_DUPLIGROUP, animated);
dob->no_draw= (dob->origlay & group->layer)==0;
@@ -775,6 +783,10 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_
hair= (totchild == 0 || psys->childcache) && psys->pathcache;
if(!hair)
return;
+
+ /* we use cache, update totchild according to cached data */
+ totchild = psys->totchildcache;
+ totpart = psys->totcached;
}
psys->lattice = psys_get_lattice(par, psys);
@@ -857,6 +869,8 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_
}
VECCOPY(pamat[3], cache->co);
+ pamat[3][3]= 1.0f;
+
}
else if(step_nbr) {
/* other keys */
@@ -1059,7 +1073,8 @@ static void object_duplilist_recursive(ID *id, Object *ob, ListBase *duplilist,
}
}
-/* note; group dupli's already set transform matrix. see note in group_duplilist() */
+/* Returns a list of DupliObject
+ * note; group dupli's already set transform matrix. see note in group_duplilist() */
ListBase *object_duplilist(Scene *sce, Object *ob)
{
ListBase *duplilist= MEM_mallocN(sizeof(ListBase), "duplilist");
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index fb7d59c137a..720ed0513ed 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -1690,7 +1690,7 @@ static void initialize_posetree(struct Object *ob, bPoseChannel *pchan_tip)
were executed & assigned. Now as last we do an IK pass */
static void execute_posetree(Object *ob, PoseTree *tree)
{
- float R_parmat[3][3];
+ float R_parmat[3][3], identity[3][3];
float iR_parmat[3][3];
float R_bonemat[3][3];
float goalrot[3][3], goalpos[3];
@@ -1699,7 +1699,8 @@ static void execute_posetree(Object *ob, PoseTree *tree)
float irest_basis[3][3], full_basis[3][3];
float end_pose[4][4], world_pose[4][4];
float length, basis[3][3], rest_basis[3][3], start[3], *ikstretch=NULL;
- int a, flag, hasstretch=0;
+ float resultinf=0.0f;
+ int a, flag, hasstretch=0, resultblend=0;
bPoseChannel *pchan;
IK_Segment *seg, *parent, **iktree, *iktarget;
IK_Solver *solver;
@@ -1844,6 +1845,12 @@ static void execute_posetree(Object *ob, PoseTree *tree)
Mat4MulMat4(goal, rootmat, goalinv);
VECCOPY(polepos, goal[3]);
poleconstrain= 1;
+
+ /* for pole targets, we blend the result of the ik solver
+ * instead of the target position, otherwise we can't get
+ * a smooth transition */
+ resultblend= 1;
+ resultinf= target->con->enforce;
if(data->flag & CONSTRAINT_IK_GETANGLE) {
poleangledata= data;
@@ -1853,7 +1860,7 @@ static void execute_posetree(Object *ob, PoseTree *tree)
}
/* do we need blending? */
- if (target->con->enforce!=1.0) {
+ if (!resultblend && target->con->enforce!=1.0) {
float q1[4], q2[4], q[4];
float fac= target->con->enforce;
float mfac= 1.0-fac;
@@ -1903,7 +1910,7 @@ static void execute_posetree(Object *ob, PoseTree *tree)
tree->basis_change= MEM_mallocN(sizeof(float[3][3])*tree->totchannel, "ik basis change");
if(hasstretch)
ikstretch= MEM_mallocN(sizeof(float)*tree->totchannel, "ik stretch");
-
+
for(a=0; a<tree->totchannel; a++) {
IK_GetBasisChange(iktree[a], tree->basis_change[a]);
@@ -1931,6 +1938,12 @@ static void execute_posetree(Object *ob, PoseTree *tree)
VecMulf(tree->basis_change[a][1], stretch);
VecMulf(tree->basis_change[a][2], stretch);
}
+
+ if(resultblend && resultinf!=1.0f) {
+ Mat3One(identity);
+ Mat3BlendMat3(tree->basis_change[a], identity,
+ tree->basis_change[a], resultinf);
+ }
IK_FreeSegment(iktree[a]);
}
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index aca51e56c6e..1fe6447752e 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -525,6 +525,7 @@ typedef struct UndoElem {
char str[FILE_MAXDIR+FILE_MAXFILE];
char name[MAXUNDONAME];
MemFile memfile;
+ uintptr_t undosize;
} UndoElem;
static ListBase undobase={NULL, NULL};
@@ -555,6 +556,7 @@ static int read_undosave(UndoElem *uel)
/* name can be a dynamic string */
void BKE_write_undo(char *name)
{
+ uintptr_t maxmem, totmem, memused;
int nr, success;
UndoElem *uel;
@@ -616,8 +618,36 @@ void BKE_write_undo(char *name)
if(curundo->prev) prevfile= &(curundo->prev->memfile);
+ memused= MEM_get_memory_in_use();
success= BLO_write_file_mem(prevfile, &curundo->memfile, G.fileflags, &err);
-
+ curundo->undosize= MEM_get_memory_in_use() - memused;
+ }
+
+ if(U.undomemory != 0) {
+ /* limit to maximum memory (afterwards, we can't know in advance) */
+ totmem= 0;
+ maxmem= ((uintptr_t)U.undomemory)*1024*1024;
+
+ /* keep at least two (original + other) */
+ uel= undobase.last;
+ while(uel && uel->prev) {
+ totmem+= uel->undosize;
+ if(totmem>maxmem) break;
+ uel= uel->prev;
+ }
+
+ if(uel) {
+ if(uel->prev && uel->prev->prev)
+ uel= uel->prev;
+
+ while(undobase.first!=uel) {
+ UndoElem *first= undobase.first;
+ BLI_remlink(&undobase, first);
+ /* the merge is because of compression */
+ BLO_merge_memfile(&first->memfile, &first->next->memfile);
+ MEM_freeN(first);
+ }
+ }
}
}
@@ -683,14 +713,14 @@ char *BKE_undo_menu_string(void)
UndoElem *uel;
DynStr *ds= BLI_dynstr_new();
char *menu;
-
+
BLI_dynstr_append(ds, "Global Undo History %t");
for(uel= undobase.first; uel; uel= uel->next) {
BLI_dynstr_append(ds, "|");
BLI_dynstr_append(ds, uel->name);
}
-
+
menu= BLI_dynstr_get_cstring(ds);
BLI_dynstr_free(ds);
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 472df3d0f26..9d5dcb8109b 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -58,6 +58,10 @@
#include "MEM_guardedalloc.h"
+#include "GPU_draw.h"
+#include "GPU_extensions.h"
+#include "GPU_material.h"
+
#include <string.h>
#include <limits.h>
@@ -243,7 +247,7 @@ static void cdDM_drawLooseEdges(DerivedMesh *dm)
glEnd();
}
-static void cdDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int))
+static void cdDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *attribs))
{
CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
MVert *mvert = cddm->mvert;
@@ -271,7 +275,7 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int))
|| new_shademodel != shademodel) {
glEnd();
- drawCurrentMat = setMaterial(matnr = new_matnr);
+ drawCurrentMat = setMaterial(matnr = new_matnr, NULL);
glShadeModel(shademodel = new_shademodel);
glBegin(glmode = new_glmode);
@@ -556,6 +560,134 @@ static void cdDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void
cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
}
+static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData)
+{
+ CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
+ GPUVertexAttribs gattribs;
+ DMVertexAttribs attribs;
+ MVert *mvert = cddm->mvert;
+ MFace *mface = cddm->mface;
+ MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE);
+ float (*nors)[3] = dm->getFaceDataArray(dm, CD_NORMAL);
+ int a, b, dodraw, smoothnormal, matnr, new_matnr;
+ int transp, new_transp, orig_transp;
+ int orig, *index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
+
+ matnr = -1;
+ smoothnormal = 0;
+ dodraw = 0;
+ transp = GPU_get_material_blend_mode();
+ orig_transp = transp;
+
+ memset(&attribs, 0, sizeof(attribs));
+
+ glShadeModel(GL_SMOOTH);
+ glBegin(GL_QUADS);
+
+ for(a = 0; a < dm->numFaceData; a++, mface++) {
+ new_matnr = mface->mat_nr + 1;
+
+ if(new_matnr != matnr) {
+ glEnd();
+
+ dodraw = setMaterial(matnr = new_matnr, &gattribs);
+ if(dodraw)
+ DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
+
+ glBegin(GL_QUADS);
+ }
+
+ if(!dodraw) {
+ continue;
+ }
+ else if(setDrawOptions) {
+ orig = index[a];
+
+ if(orig == ORIGINDEX_NONE)
+ continue;
+ else if(!setDrawOptions(userData, orig))
+ continue;
+ }
+
+ if(tf) {
+ new_transp = tf[a].transp;
+
+ if(new_transp != transp) {
+ glEnd();
+
+ if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
+ GPU_set_material_blend_mode(orig_transp);
+ else
+ GPU_set_material_blend_mode(new_transp);
+ transp = new_transp;
+
+ glBegin(GL_QUADS);
+ }
+ }
+
+ smoothnormal = (mface->flag & ME_SMOOTH);
+
+ if(!smoothnormal) {
+ if(nors) {
+ glNormal3fv(nors[a]);
+ }
+ else {
+ /* TODO ideally a normal layer should always be available */
+ float nor[3];
+ if(mface->v4) {
+ CalcNormFloat4(mvert[mface->v1].co, mvert[mface->v2].co,
+ mvert[mface->v3].co, mvert[mface->v4].co,
+ nor);
+ } else {
+ CalcNormFloat(mvert[mface->v1].co, mvert[mface->v2].co,
+ mvert[mface->v3].co, nor);
+ }
+ glNormal3fv(nor);
+ }
+ }
+
+#define PASSVERT(index, vert) { \
+ if(attribs.totorco) \
+ glVertexAttrib3fvARB(attribs.orco.glIndex, attribs.orco.array[index]); \
+ for(b = 0; b < attribs.tottface; b++) { \
+ MTFace *tf = &attribs.tface[b].array[a]; \
+ glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]); \
+ } \
+ for(b = 0; b < attribs.totmcol; b++) { \
+ MCol *cp = &attribs.mcol[b].array[a*4 + vert]; \
+ GLubyte col[4]; \
+ col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; \
+ glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col); \
+ } \
+ if(attribs.tottang) { \
+ float *tang = attribs.tang.array[a*4 + vert]; \
+ glVertexAttrib3fvARB(attribs.tang.glIndex, tang); \
+ } \
+ if(smoothnormal) \
+ glNormal3sv(mvert[index].no); \
+ glVertex3fv(mvert[index].co); \
+}
+
+ PASSVERT(mface->v1, 0);
+ PASSVERT(mface->v2, 1);
+ PASSVERT(mface->v3, 2);
+ if(mface->v4)
+ PASSVERT(mface->v4, 3)
+ else
+ PASSVERT(mface->v3, 2)
+
+#undef PASSVERT
+ }
+ glEnd();
+
+ glShadeModel(GL_FLAT);
+}
+
+static void cdDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs))
+{
+ dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
+}
+
static void cdDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
{
CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
@@ -713,8 +845,10 @@ static CDDerivedMesh *cdDM_create(const char *desc)
dm->drawFacesSolid = cdDM_drawFacesSolid;
dm->drawFacesColored = cdDM_drawFacesColored;
dm->drawFacesTex = cdDM_drawFacesTex;
+ dm->drawFacesGLSL = cdDM_drawFacesGLSL;
dm->drawMappedFaces = cdDM_drawMappedFaces;
dm->drawMappedFacesTex = cdDM_drawMappedFacesTex;
+ dm->drawMappedFacesGLSL = cdDM_drawMappedFacesGLSL;
dm->foreachMappedVert = cdDM_foreachMappedVert;
dm->foreachMappedEdge = cdDM_foreachMappedEdge;
diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c
index 295b8fe3552..45b8bb7935c 100644
--- a/source/blender/blenkernel/intern/colortools.c
+++ b/source/blender/blenkernel/intern/colortools.c
@@ -730,3 +730,24 @@ void curvemapping_initialize(CurveMapping *cumap)
curvemap_make_table(cumap->cm+a, &cumap->clipr);
}
}
+
+void curvemapping_table_RGBA(CurveMapping *cumap, float **array, int *size)
+{
+ int a;
+
+ *size = CM_TABLE+1;
+ *array = MEM_callocN(sizeof(float)*(*size)*4, "CurveMapping");
+ curvemapping_initialize(cumap);
+
+ for(a=0; a<*size; a++) {
+ if(cumap->cm[0].table)
+ (*array)[a*4+0]= cumap->cm[0].table[a].y;
+ if(cumap->cm[1].table)
+ (*array)[a*4+1]= cumap->cm[1].table[a].y;
+ if(cumap->cm[2].table)
+ (*array)[a*4+2]= cumap->cm[2].table[a].y;
+ if(cumap->cm[3].table)
+ (*array)[a*4+3]= cumap->cm[3].table[a].y;
+ }
+}
+
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 1d7d4d1fda0..5f72bf316ab 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -369,19 +369,12 @@ void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4
case CONSTRAINT_SPACE_WORLD: /* ---------- FROM WORLDSPACE ---------- */
{
/* world to pose */
- if (to==CONSTRAINT_SPACE_POSE || to==CONSTRAINT_SPACE_LOCAL || to==CONSTRAINT_SPACE_PARLOCAL) {
- Mat4Invert(imat, ob->obmat);
- Mat4CpyMat4(tempmat, mat);
- Mat4MulMat4(mat, tempmat, imat);
- }
+ Mat4Invert(imat, ob->obmat);
+ Mat4CpyMat4(tempmat, mat);
+ Mat4MulMat4(mat, tempmat, imat);
- /* pose to local */
- if (to == CONSTRAINT_SPACE_LOCAL) {
- /* call self with slightly different values */
- constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to);
- }
- /* pose to local + parent */
- else if (to == CONSTRAINT_SPACE_PARLOCAL) {
+ /* use pose-space as stepping stone for other spaces... */
+ if (ELEM(to, CONSTRAINT_SPACE_LOCAL, CONSTRAINT_SPACE_PARLOCAL)) {
/* call self with slightly different values */
constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to);
}
@@ -447,68 +440,65 @@ void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4
break;
case CONSTRAINT_SPACE_LOCAL: /* ------------ FROM LOCALSPACE --------- */
{
- /* local to pose */
- if (to==CONSTRAINT_SPACE_POSE || to==CONSTRAINT_SPACE_WORLD) {
- /* do inverse procedure that was done for pose to local */
- if (pchan->bone) {
- /* we need the posespace_matrix = local_matrix + (parent_posespace_matrix + restpos) */
- if (pchan->parent) {
- float offs_bone[4][4];
+ /* local to pose - do inverse procedure that was done for pose to local */
+ if (pchan->bone) {
+ /* we need the posespace_matrix = local_matrix + (parent_posespace_matrix + restpos) */
+ if (pchan->parent) {
+ float offs_bone[4][4];
+
+ /* construct offs_bone the same way it is done in armature.c */
+ Mat4CpyMat3(offs_bone, pchan->bone->bone_mat);
+ VECCOPY(offs_bone[3], pchan->bone->head);
+ offs_bone[3][1]+= pchan->bone->parent->length;
+
+ if (pchan->bone->flag & BONE_HINGE) {
+ /* pose_mat = par_pose-space_location * chan_mat */
+ float tmat[4][4];
- /* construct offs_bone the same way it is done in armature.c */
- Mat4CpyMat3(offs_bone, pchan->bone->bone_mat);
- VECCOPY(offs_bone[3], pchan->bone->head);
- offs_bone[3][1]+= pchan->bone->parent->length;
- if (pchan->bone->flag & BONE_HINGE) {
- /* pose_mat = par_pose-space_location * chan_mat */
- float tmat[4][4];
-
- /* the rotation of the parent restposition */
- Mat4CpyMat4(tmat, pchan->bone->parent->arm_mat);
-
- /* the location of actual parent transform */
- VECCOPY(tmat[3], offs_bone[3]);
- offs_bone[3][0]= offs_bone[3][1]= offs_bone[3][2]= 0.0f;
- Mat4MulVecfl(pchan->parent->pose_mat, tmat[3]);
-
- Mat4MulMat4(diff_mat, offs_bone, tmat);
- Mat4CpyMat4(tempmat, mat);
- Mat4MulMat4(mat, tempmat, diff_mat);
- }
- else {
- /* pose_mat = par_pose_mat * bone_mat * chan_mat */
- Mat4MulMat4(diff_mat, offs_bone, pchan->parent->pose_mat);
- Mat4CpyMat4(tempmat, mat);
- Mat4MulMat4(mat, tempmat, diff_mat);
- }
+ /* the rotation of the parent restposition */
+ Mat4CpyMat4(tmat, pchan->bone->parent->arm_mat);
+ /* the location of actual parent transform */
+ VECCOPY(tmat[3], offs_bone[3]);
+ offs_bone[3][0]= offs_bone[3][1]= offs_bone[3][2]= 0.0f;
+ Mat4MulVecfl(pchan->parent->pose_mat, tmat[3]);
+
+ Mat4MulMat4(diff_mat, offs_bone, tmat);
+ Mat4CpyMat4(tempmat, mat);
+ Mat4MulMat4(mat, tempmat, diff_mat);
}
else {
- Mat4CpyMat4(diff_mat, pchan->bone->arm_mat);
-
+ /* pose_mat = par_pose_mat * bone_mat * chan_mat */
+ Mat4MulMat4(diff_mat, offs_bone, pchan->parent->pose_mat);
Mat4CpyMat4(tempmat, mat);
Mat4MulMat4(mat, tempmat, diff_mat);
}
}
+ else {
+ Mat4CpyMat4(diff_mat, pchan->bone->arm_mat);
+
+ Mat4CpyMat4(tempmat, mat);
+ Mat4MulMat4(mat, tempmat, diff_mat);
+ }
}
- /* local to world */
- if (to == CONSTRAINT_SPACE_WORLD) {
+
+ /* use pose-space as stepping stone for other spaces */
+ if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_PARLOCAL)) {
/* call self with slightly different values */
constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to);
- }
+ }
}
break;
case CONSTRAINT_SPACE_PARLOCAL: /* -------------- FROM LOCAL WITH PARENT ---------- */
{
- /* local to pose */
- if (to==CONSTRAINT_SPACE_POSE || to==CONSTRAINT_SPACE_WORLD) {
- if (pchan->bone) {
- Mat4CpyMat4(diff_mat, pchan->bone->arm_mat);
- Mat4CpyMat4(tempmat, mat);
- Mat4MulMat4(mat, diff_mat, tempmat);
- }
+ /* local + parent to pose */
+ if (pchan->bone) {
+ Mat4CpyMat4(diff_mat, pchan->bone->arm_mat);
+ Mat4CpyMat4(tempmat, mat);
+ Mat4MulMat4(mat, diff_mat, tempmat);
}
- /* local to world */
- if (to == CONSTRAINT_SPACE_WORLD) {
+
+ /* use pose-space as stepping stone for other spaces */
+ if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL)) {
/* call self with slightly different values */
constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to);
}
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index 80f450000bb..1be0a2aafdb 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -1924,8 +1924,10 @@ static void dag_object_time_update_flags(Object *ob)
}
}
}
- else if(ob->scriptlink.totscript) ob->recalc |= OB_RECALC_OB;
- else if(ob->parent) {
+
+ if(ob->scriptlink.totscript) ob->recalc |= OB_RECALC_OB;
+
+ if(ob->parent) {
/* motion path or bone child */
if(ob->parent->type==OB_CURVE || ob->parent->type==OB_ARMATURE) ob->recalc |= OB_RECALC_OB;
}
@@ -1946,10 +1948,11 @@ static void dag_object_time_update_flags(Object *ob)
}
}
}
- else if(modifiers_isSoftbodyEnabled(ob)) ob->recalc |= OB_RECALC_DATA;
- else if(object_modifiers_use_time(ob)) ob->recalc |= OB_RECALC_DATA;
- else if((ob->pose) && (ob->pose->flag & POSE_CONSTRAINTS_TIMEDEPEND)) ob->recalc |= OB_RECALC_DATA;
- else {
+
+ if(object_modifiers_use_time(ob)) ob->recalc |= OB_RECALC_DATA;
+ if((ob->pose) && (ob->pose->flag & POSE_CONSTRAINTS_TIMEDEPEND)) ob->recalc |= OB_RECALC_DATA;
+
+ {
Mesh *me;
Curve *cu;
Lattice *lt;
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index 0842e55a0ea..327008c60de 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -267,7 +267,7 @@ static float eff_calc_visibility(Object *ob, float *co, float *dir)
hit.dist = len + FLT_EPSILON;
// check if the way is blocked
- if(BLI_bvhtree_ray_cast(collmd->bvhtree, co, norm, &hit, eff_tri_ray_hit, NULL)>=0)
+ if(BLI_bvhtree_ray_cast(collmd->bvhtree, co, norm, 0.0f, &hit, eff_tri_ray_hit, NULL)>=0)
{
// visibility is only between 0 and 1, calculated from 1-absorption
visibility *= MAX2(0.0, MIN2(1.0, (1.0-((float)collmd->absorption)*0.01)));
@@ -406,12 +406,15 @@ void do_physical_effector(Object *ob, float *opco, short type, float force_val,
else
VecCopyf(mag_vec,vec_to_part);
+ Normalize(mag_vec);
+
VecMulf(mag_vec,force_val*falloff);
VecAddf(field,field,mag_vec);
break;
case PFIELD_VORTEX:
Crossf(mag_vec,eff_vel,vec_to_part);
+
Normalize(mag_vec);
VecMulf(mag_vec,force_val*distance*falloff);
@@ -425,6 +428,8 @@ void do_physical_effector(Object *ob, float *opco, short type, float force_val,
/* magnetic field of a moving charge */
Crossf(temp,eff_vel,vec_to_part);
+ Normalize(temp);
+
Crossf(temp2,velocity,temp);
VecAddf(mag_vec,mag_vec,temp2);
@@ -437,6 +442,8 @@ void do_physical_effector(Object *ob, float *opco, short type, float force_val,
else
VecCopyf(mag_vec,vec_to_part);
+ Normalize(mag_vec);
+
VecMulf(mag_vec,force_val*falloff);
VecSubf(field,field,mag_vec);
@@ -451,6 +458,8 @@ void do_physical_effector(Object *ob, float *opco, short type, float force_val,
else
VecCopyf(mag_vec,vec_to_part);
+ Normalize(mag_vec);
+
VecMulf(mag_vec,charge*force_val*falloff);
VecAddf(field,field,mag_vec);
break;
@@ -535,10 +544,6 @@ void pdDoEffectors(ListBase *lb, float *opco, float *force, float *speed, float
where_is_object_time(ob,cur_time);
/* use center of object for distance calculus */
- obloc= ob->obmat[3];
- VECSUB(vect_to_vert, obloc, opco);
- distance = VecLength(vect_to_vert);
-
VecSubf(vec_to_part, opco, ob->obmat[3]);
distance = VecLength(vec_to_part);
diff --git a/source/blender/blenkernel/intern/exotic.c b/source/blender/blenkernel/intern/exotic.c
index fb48c875995..479be2ee644 100644
--- a/source/blender/blenkernel/intern/exotic.c
+++ b/source/blender/blenkernel/intern/exotic.c
@@ -2632,17 +2632,17 @@ static void write_videoscape_mesh(Object *ob, char *str)
if(evl->v4==0) {
fprintf(fp, "3 %ld %ld %ld 0x%x\n",
- evl->v1->tmp.l,
- evl->v2->tmp.l,
- evl->v3->tmp.l,
+ (long int) evl->v1->tmp.l,
+ (long int) evl->v2->tmp.l,
+ (long int) evl->v3->tmp.l,
kleur[evl->mat_nr]);
}
else {
fprintf(fp, "4 %ld %ld %ld %ld 0x%x\n",
- evl->v1->tmp.l,
- evl->v2->tmp.l,
- evl->v3->tmp.l,
- evl->v4->tmp.l,
+ (long int) evl->v1->tmp.l,
+ (long int) evl->v2->tmp.l,
+ (long int) evl->v3->tmp.l,
+ (long int) evl->v4->tmp.l,
kleur[evl->mat_nr]);
}
evl= evl->next;
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 07537e3a81c..27fa00ac239 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -53,6 +53,7 @@
#include "DNA_packedFile_types.h"
#include "DNA_scene_types.h"
#include "DNA_camera_types.h"
+#include "DNA_sequence_types.h"
#include "DNA_texture_types.h"
#include "DNA_userdef_types.h"
@@ -77,15 +78,15 @@
#include "RE_pipeline.h"
-/* bad level; call to free_realtime_image */
-#include "BKE_bad_level_calls.h"
-
/* for stamp drawing to an image */
#include "BMF_Api.h"
#include "blendef.h"
#include "BSE_time.h"
+#include "GPU_extensions.h"
+#include "GPU_draw.h"
+
#include "BLO_sys_types.h" // for intptr_t support
/* max int, to indicate we don't store sequences in ibuf */
@@ -240,7 +241,7 @@ static void image_free_buffers(Image *ima)
ima->rr= NULL;
}
- free_realtime_image(ima);
+ GPU_free_image(ima);
ima->ok= IMA_OK;
}
@@ -620,7 +621,7 @@ void free_old_images()
This gives textures a "second chance" to be used before dying.
*/
if(ima->bindcode || ima->repbind) {
- free_realtime_image(ima);
+ GPU_free_image(ima);
ima->lastused = ctime;
}
/* Otherwise, just kill the buffers */
diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c
index 4af25ee99e7..e8a25aaaf80 100644
--- a/source/blender/blenkernel/intern/ipo.c
+++ b/source/blender/blenkernel/intern/ipo.c
@@ -1390,6 +1390,14 @@ void *get_ipo_poin(ID *id, IpoCurve *icu, int *type)
else if(icu->adrcode & MA_MAP8) mtex= ma->mtex[7];
else if(icu->adrcode & MA_MAP9) mtex= ma->mtex[8];
else if(icu->adrcode & MA_MAP10) mtex= ma->mtex[9];
+ else if(icu->adrcode & MA_MAP12) mtex= ma->mtex[11];
+ else if(icu->adrcode & MA_MAP11) mtex= ma->mtex[10];
+ else if(icu->adrcode & MA_MAP13) mtex= ma->mtex[12];
+ else if(icu->adrcode & MA_MAP14) mtex= ma->mtex[13];
+ else if(icu->adrcode & MA_MAP15) mtex= ma->mtex[14];
+ else if(icu->adrcode & MA_MAP16) mtex= ma->mtex[15];
+ else if(icu->adrcode & MA_MAP17) mtex= ma->mtex[16];
+ else if(icu->adrcode & MA_MAP18) mtex= ma->mtex[17];
if(mtex) {
poin= give_mtex_poin(mtex, icu->adrcode & (MA_MAP1-1) );
@@ -1479,7 +1487,14 @@ void *get_ipo_poin(ID *id, IpoCurve *icu, int *type)
else if(icu->adrcode & MA_MAP8) mtex= wo->mtex[7];
else if(icu->adrcode & MA_MAP9) mtex= wo->mtex[8];
else if(icu->adrcode & MA_MAP10) mtex= wo->mtex[9];
-
+ else if(icu->adrcode & MA_MAP11) mtex= wo->mtex[10];
+ else if(icu->adrcode & MA_MAP12) mtex= wo->mtex[11];
+ else if(icu->adrcode & MA_MAP13) mtex= wo->mtex[12];
+ else if(icu->adrcode & MA_MAP14) mtex= wo->mtex[13];
+ else if(icu->adrcode & MA_MAP15) mtex= wo->mtex[14];
+ else if(icu->adrcode & MA_MAP16) mtex= wo->mtex[15];
+ else if(icu->adrcode & MA_MAP17) mtex= wo->mtex[16];
+ else if(icu->adrcode & MA_MAP18) mtex= wo->mtex[17];
if(mtex) {
poin= give_mtex_poin(mtex, icu->adrcode & (MA_MAP1-1) );
}
@@ -1524,6 +1539,14 @@ void *get_ipo_poin(ID *id, IpoCurve *icu, int *type)
else if(icu->adrcode & MA_MAP8) mtex= la->mtex[7];
else if(icu->adrcode & MA_MAP9) mtex= la->mtex[8];
else if(icu->adrcode & MA_MAP10) mtex= la->mtex[9];
+ else if(icu->adrcode & MA_MAP11) mtex= la->mtex[10];
+ else if(icu->adrcode & MA_MAP12) mtex= la->mtex[11];
+ else if(icu->adrcode & MA_MAP13) mtex= la->mtex[12];
+ else if(icu->adrcode & MA_MAP14) mtex= la->mtex[13];
+ else if(icu->adrcode & MA_MAP15) mtex= la->mtex[14];
+ else if(icu->adrcode & MA_MAP16) mtex= la->mtex[15];
+ else if(icu->adrcode & MA_MAP17) mtex= la->mtex[16];
+ else if(icu->adrcode & MA_MAP18) mtex= la->mtex[17];
if(mtex) {
poin= give_mtex_poin(mtex, icu->adrcode & (MA_MAP1-1) );
@@ -1672,6 +1695,8 @@ void set_icu_vars(IpoCurve *icu)
icu->ymax= 5.0; break;
case MA_ADD:
icu->ymax= 1.0; break;
+ case MA_EMIT:
+ icu->ymax= 2.0; break;
default:
icu->ymax= 1.0; break;
}
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 3983eecdaba..f05b84f6e90 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -61,6 +61,8 @@
#include "BPY_extern.h"
+#include "GPU_material.h"
+
/* used in UI and render */
Material defmaterial;
@@ -96,6 +98,9 @@ void free_material(Material *ma)
ntreeFreeTree(ma->nodetree);
MEM_freeN(ma->nodetree);
}
+
+ if(ma->gpumaterial.first)
+ GPU_material_free(ma);
}
void init_material(Material *ma)
@@ -207,6 +212,8 @@ Material *copy_material(Material *ma)
if(ma->nodetree) {
man->nodetree= ntreeCopyTree(ma->nodetree, 0); /* 0 == full new tree */
}
+
+ man->gpumaterial.first= man->gpumaterial.last= NULL;
return man;
}
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 43e48c3bacd..77b9ea4fa2d 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -79,45 +79,6 @@
#include "BLI_editVert.h"
#include "BLI_arithb.h"
-int update_realtime_texture(MTFace *tface, double time)
-{
- Image *ima;
- int inc = 0;
- float diff;
- int newframe;
-
- ima = tface->tpage;
-
- if (!ima)
- return 0;
-
- if (ima->lastupdate<0)
- ima->lastupdate = 0;
-
- if (ima->lastupdate>time)
- ima->lastupdate=(float)time;
-
- if(ima->tpageflag & IMA_TWINANIM) {
- if(ima->twend >= ima->xrep*ima->yrep) ima->twend= ima->xrep*ima->yrep-1;
-
- /* check: is the bindcode not in the array? Then free. (still to do) */
-
- diff = (float)(time-ima->lastupdate);
-
- inc = (int)(diff*(float)ima->animspeed);
-
- ima->lastupdate+=((float)inc/(float)ima->animspeed);
-
- newframe = ima->lastframe+inc;
-
- if (newframe > (int)ima->twend)
- newframe = (int)ima->twsta-1 + (newframe-ima->twend)%(ima->twend-ima->twsta);
-
- ima->lastframe = newframe;
- }
- return inc;
-}
-
void mesh_update_customdata_pointers(Mesh *me)
{
me->mvert = CustomData_get_layer(&me->vdata, CD_MVERT);
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index e8453ef934c..97e3bc9e9bd 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -794,12 +794,18 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
if(amd->fit_type == MOD_ARR_FITCURVE && amd->curve_ob) {
Curve *cu = amd->curve_ob->data;
if(cu) {
+ float tmp_mat[3][3];
+ float scale;
+
+ object_to_mat3(amd->curve_ob, tmp_mat);
+ scale = Mat3ToScalef(tmp_mat);
+
if(!cu->path) {
cu->flag |= CU_PATH; // needed for path & bevlist
makeDispListCurveTypes(amd->curve_ob, 0);
}
if(cu->path)
- length = cu->path->totdist;
+ length = scale*cu->path->totdist;
}
}
@@ -5288,6 +5294,11 @@ static void softbodyModifier_deformVerts(
sbObjectStep(ob, (float)G.scene->r.cfra, vertexCos, numVerts);
}
+static int softbodyModifier_dependsOnTime(ModifierData *md)
+{
+ return 1;
+}
+
/* Cloth */
@@ -7637,6 +7648,7 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
mti->flags = eModifierTypeFlag_AcceptsCVs
| eModifierTypeFlag_RequiresOriginalData;
mti->deformVerts = softbodyModifier_deformVerts;
+ mti->dependsOnTime = softbodyModifier_dependsOnTime;
mti = INIT_TYPE(Cloth);
mti->type = eModifierTypeType_Nonconstructive;
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 4e36df35a14..94a21cdd5df 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -68,6 +68,9 @@
#include "SHD_node.h"
+#include "GPU_extensions.h"
+#include "GPU_material.h"
+
static ListBase empty_list = {NULL, NULL};
ListBase node_all_composit = {NULL, NULL};
ListBase node_all_shaders = {NULL, NULL};
@@ -2352,6 +2355,117 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview)
ntreeEndExecTree(ntree);
}
+/* GPU material from shader nodes */
+
+static void gpu_from_node_stack(ListBase *sockets, bNodeStack **ns, GPUNodeStack *gs)
+{
+ bNodeSocket *sock;
+ int i;
+
+ for (sock=sockets->first, i=0; sock; sock=sock->next, i++) {
+ memset(&gs[i], 0, sizeof(gs[i]));
+
+ QUATCOPY(gs[i].vec, ns[i]->vec);
+ gs[i].link= ns[i]->data;
+
+ if (sock->type == SOCK_VALUE)
+ gs[i].type= GPU_FLOAT;
+ else if (sock->type == SOCK_VECTOR)
+ gs[i].type= GPU_VEC3;
+ else if (sock->type == SOCK_RGBA)
+ gs[i].type= GPU_VEC4;
+ else
+ gs[i].type= GPU_NONE;
+
+ gs[i].name = "";
+ gs[i].hasinput= ns[i]->hasinput && ns[i]->data;
+ gs[i].hasoutput= ns[i]->hasinput && ns[i]->data;
+ gs[i].sockettype= ns[i]->sockettype;
+ }
+
+ gs[i].type= GPU_NONE;
+}
+
+static void data_from_gpu_stack(ListBase *sockets, bNodeStack **ns, GPUNodeStack *gs)
+{
+ bNodeSocket *sock;
+ int i;
+
+ for (sock=sockets->first, i=0; sock; sock=sock->next, i++) {
+ ns[i]->data= gs[i].link;
+ ns[i]->hasinput= gs[i].hasinput && gs[i].link;
+ ns[i]->hasoutput= gs[i].hasoutput;
+ ns[i]->sockettype= gs[i].sockettype;
+ }
+}
+
+static void gpu_node_group_execute(bNodeStack *stack, GPUMaterial *mat, bNode *gnode, bNodeStack **in, bNodeStack **out)
+{
+ bNode *node;
+ bNodeTree *ntree= (bNodeTree *)gnode->id;
+ bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */
+ bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */
+ GPUNodeStack gpuin[MAX_SOCKET+1], gpuout[MAX_SOCKET+1];
+ int doit = 0;
+
+ if(ntree==NULL) return;
+
+ stack+= gnode->stack_index;
+
+ for(node= ntree->nodes.first; node; node= node->next) {
+ if(node->typeinfo->gpufunc) {
+ group_node_get_stack(node, stack, nsin, nsout, in, out);
+
+ doit = 0;
+
+ /* for groups, only execute outputs for edited group */
+ if(node->typeinfo->nclass==NODE_CLASS_OUTPUT) {
+ if(gnode->flag & NODE_GROUP_EDIT)
+ if(node->flag & NODE_DO_OUTPUT)
+ doit = 1;
+ }
+ else
+ doit = 1;
+
+ if(doit) {
+ gpu_from_node_stack(&node->inputs, nsin, gpuin);
+ gpu_from_node_stack(&node->outputs, nsout, gpuout);
+ if(node->typeinfo->gpufunc(mat, node, gpuin, gpuout))
+ data_from_gpu_stack(&node->outputs, nsout, gpuout);
+ }
+ }
+ }
+}
+
+void ntreeGPUMaterialNodes(bNodeTree *ntree, GPUMaterial *mat)
+{
+ bNode *node;
+ bNodeStack *stack;
+ bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */
+ bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */
+ GPUNodeStack gpuin[MAX_SOCKET+1], gpuout[MAX_SOCKET+1];
+
+ if((ntree->init & NTREE_EXEC_INIT)==0)
+ ntreeBeginExecTree(ntree);
+
+ stack= ntree->stack;
+
+ for(node= ntree->nodes.first; node; node= node->next) {
+ if(node->typeinfo->gpufunc) {
+ node_get_stack(node, stack, nsin, nsout);
+ gpu_from_node_stack(&node->inputs, nsin, gpuin);
+ gpu_from_node_stack(&node->outputs, nsout, gpuout);
+ if(node->typeinfo->gpufunc(mat, node, gpuin, gpuout))
+ data_from_gpu_stack(&node->outputs, nsout, gpuout);
+ }
+ else if(node->type==NODE_GROUP && node->id) {
+ node_get_stack(node, stack, nsin, nsout);
+ gpu_node_group_execute(stack, mat, node, nsin, nsout);
+ }
+ }
+
+ ntreeEndExecTree(ntree);
+}
/* **************** call to switch lamploop for material node ************ */
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 7b36e46d45e..e63d6047cc6 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -112,6 +112,8 @@
#include "BPY_extern.h"
+#include "GPU_material.h"
+
#include "blendef.h"
/* Local function protos */
@@ -268,6 +270,7 @@ void free_object(Object *ob)
}
if(ob->soft) sbFree(ob->soft);
if(ob->fluidsimSettings) fluidsimSettingsFree(ob->fluidsimSettings);
+ if(ob->gpulamp.first) GPU_lamp_free(ob);
}
static void unlink_object__unlinkModifierLinks(void *userData, Object *ob, Object **obpoin)
@@ -694,9 +697,11 @@ float dof_camera(Object *ob)
if (cam->dof_ob) {
/* too simple, better to return the distance on the view axis only
* return VecLenf(ob->obmat[3], cam->dof_ob->obmat[3]); */
+ float mat[4][4], obmat[4][4];
- float mat[4][4];
- Mat4Invert(ob->imat, ob->obmat);
+ Mat4CpyMat4(obmat, ob->obmat);
+ Mat4Ortho(obmat);
+ Mat4Invert(ob->imat, obmat);
Mat4MulMat4(mat, cam->dof_ob->obmat, ob->imat);
return fabs(mat[3][2]);
}
@@ -918,7 +923,7 @@ Object *add_only_object(int type, char *name)
QuatOne(ob->dquat);
#endif
- ob->col[0]= ob->col[1]= ob->col[2]= 0.0;
+ ob->col[0]= ob->col[1]= ob->col[2]= 1.0;
ob->col[3]= 1.0;
ob->loc[0]= ob->loc[1]= ob->loc[2]= 0.0;
@@ -955,7 +960,8 @@ Object *add_only_object(int type, char *name)
ob->anisotropicFriction[0] = 1.0f;
ob->anisotropicFriction[1] = 1.0f;
ob->anisotropicFriction[2] = 1.0f;
- ob->gameflag= OB_PROP;
+ ob->gameflag= OB_PROP|OB_PHYSICS;
+ ob->margin = 0.0;
/* NT fluid sim defaults */
ob->fluidsimFlag = 0;
@@ -1226,6 +1232,7 @@ Object *copy_object(Object *ob)
obn->vnode = NULL;
#endif
+ obn->gpulamp.first = obn->gpulamp.last = NULL;
return obn;
}
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 2f4696fc442..db3576f0c50 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -379,8 +379,11 @@ void psys_free_children(ParticleSystem *psys)
}
/* free everything */
void psys_free(Object *ob, ParticleSystem * psys)
-{
+{
if(psys){
+ int nr = 0;
+ ParticleSystem * tpsys;
+
if(ob->particlesystem.first == NULL && G.f & G_PARTICLEEDIT)
G.f &= ~G_PARTICLEEDIT;
@@ -406,6 +409,21 @@ void psys_free(Object *ob, ParticleSystem * psys)
if(psys->effectors.first)
psys_end_effectors(psys);
+
+ // check if we are last non-visible particle system
+ for(tpsys=ob->particlesystem.first; tpsys; tpsys=tpsys->next){
+ if(tpsys->part)
+ {
+ if(ELEM(tpsys->part->draw_as,PART_DRAW_OB,PART_DRAW_GR))
+ {
+ nr++;
+ break;
+ }
+ }
+ }
+ // clear do-not-draw-flag
+ if(!nr)
+ ob->transflag &= ~OB_DUPLIPARTS;
if(psys->part){
psys->part->id.us--;
@@ -417,7 +435,7 @@ void psys_free(Object *ob, ParticleSystem * psys)
if(psys->pointcache)
BKE_ptcache_free(psys->pointcache);
-
+
MEM_freeN(psys);
}
}
@@ -3823,7 +3841,7 @@ void psys_get_dupli_texture(Object *ob, ParticleSettings *part, ParticleSystemMo
void psys_get_dupli_path_transform(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa, ParticleCacheKey *cache, float mat[][4], float *scale)
{
- float loc[3], nor[3], vec[3], side[3], len, obrotmat[4][4], qmat[4][4];
+ float loc[3], nor[3], vec[3], len, obrotmat[4][4], qmat[4][4];
float xvec[3] = {-1.0, 0.0, 0.0}, q[4];
VecSubf(vec, (cache+cache->steps-1)->co, cache->co);
@@ -3848,14 +3866,9 @@ void psys_get_dupli_path_transform(Object *ob, ParticleSystem *psys, ParticleSys
Mat4MulMat4(mat, obrotmat, qmat);
}
else {
- Crossf(side, nor, vec);
- Normalize(side);
- Crossf(nor, vec, side);
-
+ Normalize(nor);
Mat4One(mat);
- VECCOPY(mat[0], vec);
- VECCOPY(mat[1], side);
- VECCOPY(mat[2], nor);
+ VECCOPY(mat[2], nor); // mat[2] is normal/direction
}
*scale= len;
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index ef8373ee977..df193bc3802 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -53,12 +53,14 @@
#include "BLI_arithb.h"
#include "BLI_blenlib.h"
#include "BLI_kdtree.h"
+#include "BLI_kdopbvh.h"
#include "BLI_linklist.h"
#include "BLI_threads.h"
#include "BKE_anim.h"
#include "BKE_bad_level_calls.h"
#include "BKE_cdderivedmesh.h"
+#include "BKE_collision.h"
#include "BKE_displist.h"
#include "BKE_effect.h"
#include "BKE_particle.h"
@@ -76,6 +78,8 @@
#include "BKE_modifier.h"
#include "BKE_scene.h"
+#include "PIL_time.h"
+
#include "BSE_headerbuttons.h"
#include "blendef.h"
@@ -146,6 +150,14 @@ void psys_reset(ParticleSystem *psys, int mode)
BLI_freelistN(&psys->reactevents);
}
}
+ else if(mode == PSYS_RESET_CACHE_MISS) {
+ /* set all particles to be skipped */
+ ParticleData *pa = psys->particles;
+ int p=0;
+
+ for(; p<psys->totpart; p++, pa++)
+ pa->flag = PARS_NO_DISP;
+ }
/* reset children */
if(psys->child) {
@@ -2301,7 +2313,15 @@ static void add_to_effectors(ListBase *lb, Object *ob, Object *obsrc, ParticleSy
}
}
else if(pd->forcefield)
+ {
type |= PSYS_EC_EFFECTOR;
+
+ if(pd->forcefield == PFIELD_WIND)
+ {
+ pd->rng = rng_new(1);
+ rng_srandom(pd->rng, (unsigned int)(ceil(PIL_check_seconds_timer()))); // use better seed
+ }
+ }
}
if(pd && pd->deflect)
@@ -2413,13 +2433,16 @@ void psys_end_effectors(ParticleSystem *psys)
if(ec->tree)
BLI_kdtree_free(ec->tree);
+
+ if(ec->ob->pd && (ec->ob->pd->forcefield == PFIELD_WIND))
+ rng_free(ec->ob->pd->rng);
}
BLI_freelistN(lb);
}
}
-static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd)
+static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra)
{
ListBase *lb=&psys->effectors;
ParticleEffectorCache *ec;
@@ -2459,96 +2482,20 @@ static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemMo
}
}
}
- else if(ec->type==PSYS_EC_DEFLECT){
- DerivedMesh *dm;
- MFace *mface=0;
- MVert *mvert=0;
- int i, totface;
- float v1[3],v2[3],v3[3],v4[4], *min, *max;
-
- if(ob==ec->ob)
- dm=psmd->dm;
- else{
- psys_disable_all(ec->ob);
-
- dm=mesh_get_derived_final(ec->ob,0);
-
- psys_enable_all(ec->ob);
- }
-
- if(dm){
- totvert=dm->getNumVerts(dm);
- totface=dm->getNumFaces(dm);
- mface=dm->getFaceDataArray(dm,CD_MFACE);
- mvert=dm->getVertDataArray(dm,CD_MVERT);
-
- /* Decide which is faster to calculate by the amount of*/
- /* matrice multiplications needed to convert spaces. */
- /* With size deflect we have to convert allways because */
- /* the object can be scaled nonuniformly (sphere->ellipsoid). */
- if(totvert<2*psys->totpart || part->flag & PART_SIZE_DEFL){
- co=ec->vert_cos=MEM_callocN(sizeof(float)*3*totvert,"Particle deflection vert cos");
- /* convert vert coordinates to global (particle) coordinates */
- for(i=0; i<totvert; i++, co+=3){
- VECCOPY(co,mvert[i].co);
- Mat4MulVecfl(ec->ob->obmat,co);
- }
- co=ec->vert_cos;
- }
- else
- ec->vert_cos=0;
-
- INIT_MINMAX(ec->ob_minmax,ec->ob_minmax+3);
-
- min=ec->face_minmax=MEM_callocN(sizeof(float)*6*totface,"Particle deflection face minmax");
- max=min+3;
-
- for(i=0; i<totface; i++,mface++,min+=6,max+=6){
- if(co){
- VECCOPY(v1,co+3*mface->v1);
- VECCOPY(v2,co+3*mface->v2);
- VECCOPY(v3,co+3*mface->v3);
- }
- else{
- VECCOPY(v1,mvert[mface->v1].co);
- VECCOPY(v2,mvert[mface->v2].co);
- VECCOPY(v3,mvert[mface->v3].co);
- }
- INIT_MINMAX(min,max);
- DO_MINMAX(v1,min,max);
- DO_MINMAX(v2,min,max);
- DO_MINMAX(v3,min,max);
-
- if(mface->v4){
- if(co){
- VECCOPY(v4,co+3*mface->v4);
- }
- else{
- VECCOPY(v4,mvert[mface->v4].co);
- }
- DO_MINMAX(v4,min,max);
- }
-
- DO_MINMAX(min,ec->ob_minmax,ec->ob_minmax+3);
- DO_MINMAX(max,ec->ob_minmax,ec->ob_minmax+3);
- }
- }
- else
- ec->face_minmax=0;
- }
else if(ec->type==PSYS_EC_PARTICLE){
+ Object *eob = ec->ob;
+ ParticleSystem *epsys = BLI_findlink(&eob->particlesystem,ec->psys_nbr);
+ ParticleSettings *epart = epsys->part;
+ ParticleData *epa = epsys->particles;
+ int totepart = epsys->totpart;
+
if(psys->part->phystype==PART_PHYS_BOIDS){
- Object *eob = ec->ob;
- ParticleSystem *epsys;
- ParticleSettings *epart;
ParticleData *epa;
ParticleKey state;
PartDeflect *pd;
- int totepart, p;
- epsys= BLI_findlink(&eob->particlesystem,ec->psys_nbr);
- epart= epsys->part;
+ int p;
+
pd= epart->pd;
- totepart= epsys->totpart;
if(pd->forcefield==PFIELD_FORCE && totepart){
KDTree *tree;
@@ -2563,6 +2510,11 @@ static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemMo
}
}
}
+ else if(ec->type==PSYS_EC_DEFLECT) {
+ CollisionModifierData *collmd = ( CollisionModifierData * ) ( modifiers_findByType ( ec->ob, eModifierType_Collision ) );
+ if(collmd)
+ collision_move_object(collmd, 1.0, 0.0);
+ }
}
}
@@ -2665,7 +2617,7 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P
state->vel,force_field,0, pd->rng, pd->f_noise,charge,pa->size);
}
}
- else if(pd->forcefield==PFIELD_HARMONIC && cfra-framestep <= epa->dietime && cfra>epa->dietime){
+ else if(pd && pd->forcefield==PFIELD_HARMONIC && cfra-framestep <= epa->dietime && cfra>epa->dietime){
/* first step after key release */
psys_get_particle_state(eob,epsys,p,&estate,1);
VECADD(vel,vel,estate.vel);
@@ -3011,37 +2963,124 @@ int psys_intersect_dm(Object *ob, DerivedMesh *dm, float *vert_cos, float *co1,
}
return intersect;
}
+
+/* container for moving data between deflet_particle and particle_intersect_face */
+typedef struct ParticleCollision
+{
+ struct Object *ob, *ob_t; // collided and current objects
+ struct CollisionModifierData *md; // collision modifier for ob_t;
+ float nor[3]; // normal at collision point
+ float vel[3]; // velocity of collision point
+ float co1[3], co2[3]; // ray start and end points
+ float ray_len; // original length of co2-co1, needed for collision time evaluation
+ float t; // time of previous collision, needed for substracting face velocity
+}
+ParticleCollision;
+
+static void particle_intersect_face(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
+{
+ ParticleCollision *col = (ParticleCollision *) userdata;
+ MFace *face = col->md->mfaces + index;
+ MVert *x = col->md->x;
+ MVert *v = col->md->current_v;
+ float dir[3], vel[3], co1[3], co2[3], uv[2], ipoint[3], temp[3], dist, t, threshold;
+ int ret=0;
+
+ float *t0, *t1, *t2, *t3;
+ t0 = x[ face->v1 ].co;
+ t1 = x[ face->v2 ].co;
+ t2 = x[ face->v3 ].co;
+ t3 = face->v4 ? x[ face->v4].co : NULL;
+
+ /* calculate average velocity of face */
+ VECCOPY(vel, v[ face->v1 ].co);
+ VECADD(vel, vel, v[ face->v2 ].co);
+ VECADD(vel, vel, v[ face->v3 ].co);
+ VecMulf(vel, 0.33334f);
+
+ /* substract face velocity, in other words convert to
+ a coordinate system where only the particle moves */
+ VECADDFAC(co1, col->co1, vel, -col->t);
+ VECSUB(co2, col->co2, vel);
+
+ do
+ {
+ if(ray->radius == 0.0f) {
+ if(LineIntersectsTriangle(co1, co2, t0, t1, t2, &t, uv)) {
+ if(t >= 0.0f && t < hit->dist/col->ray_len) {
+ hit->dist = col->ray_len * t;
+ hit->index = index;
+
+ /* calculate normal that's facing the particle */
+ CalcNormFloat(t0, t1, t2, col->nor);
+ VECSUB(temp, co2, co1);
+ if(Inpf(col->nor, temp) > 0.0f)
+ VecMulf(col->nor, -1.0f);
+
+ VECCOPY(col->vel,vel);
+
+ col->ob = col->ob_t;
+ }
+ }
+ }
+ else {
+ if(SweepingSphereIntersectsTriangleUV(co1, co2, ray->radius, t0, t1, t2, &t, ipoint)) {
+ if(t >=0.0f && t < hit->dist/col->ray_len) {
+ hit->dist = col->ray_len * t;
+ hit->index = index;
+
+ VecLerpf(temp, co1, co2, t);
+
+ VECSUB(col->nor, temp, ipoint);
+ Normalize(col->nor);
+
+ VECCOPY(col->vel,vel);
+
+ col->ob = col->ob_t;
+ }
+ }
+ }
+
+ t1 = t2;
+ t2 = t3;
+ t3 = NULL;
+
+ } while(t2);
+}
/* particle - mesh collision code */
/* in addition to basic point to surface collisions handles friction & damping,*/
/* angular momentum <-> linear momentum and swept sphere - mesh collisions */
/* 1. check for all possible deflectors for closest intersection on particle path */
/* 2. if deflection was found kill the particle or calculate new coordinates */
-static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, ParticleSystem *psys, ParticleSettings *part, ParticleData *pa, int p, float dfra, float cfra, ParticleKey *state, int *pa_die){
- Object *ob, *min_ob;
- MFace *mface;
- MVert *mvert;
- DerivedMesh *dm;
+static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, ParticleSystem *psys, ParticleSettings *part, ParticleData *pa, int p, float timestep, float dfra, float cfra, ParticleKey *state){
+ Object *ob;
ListBase *lb=&psys->effectors;
ParticleEffectorCache *ec;
- ParticleKey cstate;
- float imat[4][4];
- float co1[3],co2[3],def_loc[3],def_nor[3],unit_nor[3],def_tan[3],dvec[3],def_vel[3],dave[3],dvel[3];
- float pa_minmax[6];
- float min_w[4], zerovec[3]={0.0,0.0,0.0}, ipoint[3];
- float min_d,dotprod,damp,frict,o_len,d_len,radius=-1.0f;
- int min_face=0, intersect=1, through=0;
- short deflections=0, global=0;
-
- VECCOPY(def_loc,pa->state.co);
- VECCOPY(def_vel,pa->state.vel);
+ ParticleKey reaction_state;
+ ParticleCollision col;
+ CollisionModifierData *collmd;
+ BVHTreeRayHit hit;
+ float ray_dir[3], zerovec[3]={0.0,0.0,0.0};
+ float radius = ((part->flag & PART_SIZE_DEFL)?pa->size:0.0f);
+ int deflections=0, max_deflections=10;
+
+ VECCOPY(col.co1, pa->state.co);
+ VECCOPY(col.co2, state->co);
+ col.t = 0.0f;
/* 10 iterations to catch multiple deflections */
- if(lb->first) while(deflections<10){
- intersect=0;
- global=0;
- min_d=20000.0;
- min_ob=NULL;
+ if(lb->first) while(deflections < max_deflections){
/* 1. */
+
+ VECSUB(ray_dir, col.co2, col.co1);
+ hit.index = -1;
+ hit.dist = col.ray_len = VecLength(ray_dir);
+
+ /* even if particle is stationary we want to check for moving colliders */
+ /* if hit.dist is zero the bvhtree_ray_cast will just ignore everything */
+ if(hit.dist == 0.0f)
+ hit.dist = col.ray_len = 0.000001f;
+
for(ec=lb->first; ec; ec=ec->next){
if(ec->type & PSYS_EC_DEFLECT){
ob= ec->ob;
@@ -3049,263 +3088,165 @@ static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, Part
if(part->type!=PART_HAIR)
where_is_object_time(ob,cfra);
- if(ob==pob){
- dm=psmd->dm;
- /* particles should not collide with emitter at birth */
- if(pa->time < cfra && pa->time >= psys->cfra)
- continue;
- }
- else
- dm=0;
-
- VECCOPY(co1,def_loc);
- VECCOPY(co2,state->co);
-
- if(ec->vert_cos==0){
- /* convert particle coordinates to object coordinates */
- Mat4Invert(imat,ob->obmat);
- Mat4MulVecfl(imat,co1);
- Mat4MulVecfl(imat,co2);
- }
-
- INIT_MINMAX(pa_minmax,pa_minmax+3);
- DO_MINMAX(co1,pa_minmax,pa_minmax+3);
- DO_MINMAX(co2,pa_minmax,pa_minmax+3);
- if(part->flag&PART_SIZE_DEFL){
- pa_minmax[0]-=pa->size;
- pa_minmax[1]-=pa->size;
- pa_minmax[2]-=pa->size;
- pa_minmax[3]+=pa->size;
- pa_minmax[4]+=pa->size;
- pa_minmax[5]+=pa->size;
-
- radius=pa->size;
- }
-
- if(ec->face_minmax==0 || AabbIntersectAabb(pa_minmax,pa_minmax+3,ec->ob_minmax,ec->ob_minmax+3)) {
- if(psys_intersect_dm(ob,dm,ec->vert_cos,co1,co2,&min_d,&min_face,min_w,
- ec->face_minmax,pa_minmax,radius,ipoint)){
+ /* particles should not collide with emitter at birth */
+ if(ob==pob && pa->time < cfra && pa->time >= psys->cfra)
+ continue;
- min_ob=ob;
+ col.md = ( CollisionModifierData * ) ( modifiers_findByType ( ec->ob, eModifierType_Collision ) );
+ col.ob_t = ob;
- if(ec->vert_cos)
- global=1;
- else
- global=0;
- }
- }
+ if(col.md->bvhtree)
+ BLI_bvhtree_ray_cast(col.md->bvhtree, col.co1, ray_dir, radius, &hit, particle_intersect_face, &col);
}
}
/* 2. */
- if(min_ob){
- BLI_srandom((int)cfra+p);
- ob=min_ob;
-
- if(ob==pob){
- dm=psmd->dm;
- }
- else{
- psys_disable_all(ob);
-
- dm=mesh_get_derived_final(ob,0);
-
- psys_enable_all(ob);
- }
-
- mface=dm->getFaceDataArray(dm,CD_MFACE);
- mface+=min_face;
- mvert=dm->getVertDataArray(dm,CD_MVERT);
-
- /* permeability check */
- if(BLI_frand()<ob->pd->pdef_perm)
- through=1;
- else
- through=0;
-
- if(through==0 && (part->flag & PART_DIE_ON_COL || ob->pd->flag & PDEFLE_KILL_PART)){
- pa->dietime = cfra-(1.0f-min_d)*dfra;
- VecLerpf(def_loc,def_loc,state->co,min_d);
-
- VECCOPY(state->co,def_loc);
- VecLerpf(state->vel,pa->state.vel,state->vel,min_d);
- QuatInterpol(state->rot,pa->state.rot,state->rot,min_d);
- VecLerpf(state->ave,pa->state.ave,state->ave,min_d);
-
- *pa_die=1;
+ if(hit.index>=0) {
+ PartDeflect *pd = col.ob->pd;
+ int through = (BLI_frand() < pd->pdef_perm) ? 1 : 0;
+ float co[3]; /* point of collision */
+ float vec[3]; /* movement through collision */
+ float vel[3]; /* velocity after collision */
+ float t = hit.dist/col.ray_len; /* time of collision between this iteration */
+ float dt = col.t + t * (1.0f - col.t); /* time of collision between frame change*/
+
+ VecLerpf(co, col.co1, col.co2, t);
+ VECSUB(vec, col.co2, col.co1);
+
+ VecMulf(col.vel, 1.0f-col.t);
+
+ /* particle dies in collision */
+ if(through == 0 && (part->flag & PART_DIE_ON_COL || pd->flag & PDEFLE_KILL_PART)) {
+ pa->alive = PARS_DYING;
+ pa->dietime = pa->state.time + (cfra - pa->state.time) * dt;
+ VECCOPY(state->co, co);
+ VecLerpf(state->vel, pa->state.vel, state->vel, dt);
+ QuatInterpol(state->rot, pa->state.rot, state->rot, dt);
+ VecLerpf(state->ave, pa->state.ave, state->ave, dt);
/* particle is dead so we don't need to calculate further */
- deflections=10;
+ deflections=max_deflections;
/* store for reactors */
- copy_particle_key(&cstate,state,0);
+ copy_particle_key(&reaction_state,state,0);
if(part->flag & PART_STICKY){
pa->stick_ob=ob;
pa->flag |= PARS_STICKY;
}
}
- else{
- VECCOPY(co1,def_loc);
- VECCOPY(co2,state->co);
+ else {
+ float nor_vec[3], tan_vec[3], tan_vel[3], vel[3];
+ float damp, frict;
+ float inp, inp_v;
+
+ /* get damping & friction factors */
+ damp = pd->pdef_damp + pd->pdef_rdamp * 2 * (BLI_frand() - 0.5f);
+ CLAMP(damp,0.0,1.0);
- if(global==0){
- /* convert particle coordinates to object coordinates */
- Mat4Invert(imat,ob->obmat);
- Mat4MulVecfl(imat,co1);
- Mat4MulVecfl(imat,co2);
- }
+ frict = pd->pdef_frict + pd->pdef_rfrict * 2 * (BLI_frand() - 0.5f);
+ CLAMP(frict,0.0,1.0);
- VecLerpf(def_loc,co1,co2,min_d);
+ /* treat normal & tangent components separately */
+ inp = Inpf(col.nor, vec);
+ inp_v = Inpf(col.nor, col.vel);
- if(radius>0.0f){
- VECSUB(unit_nor,def_loc,ipoint);
- }
- else{
- /* get deflection point & normal */
- psys_interpolate_face(mvert,mface,0,0,min_w,ipoint,unit_nor,0,0,0,0);
- if(global){
- Mat4Mul3Vecfl(ob->obmat,unit_nor);
- Mat4MulVecfl(ob->obmat,ipoint);
- }
- }
+ VECADDFAC(tan_vec, vec, col.nor, -inp);
+ VECADDFAC(tan_vel, col.vel, col.nor, -inp_v);
+ if((part->flag & PART_ROT_DYN)==0)
+ VecLerpf(tan_vec, tan_vec, tan_vel, frict);
- Normalize(unit_nor);
+ VECCOPY(nor_vec, col.nor);
+ inp *= 1.0f - damp;
- VECSUB(dvec,co1,co2);
- /* scale to remaining length after deflection */
- VecMulf(dvec,1.0f-min_d);
+ if(through)
+ inp_v *= damp;
- /* flip normal to face particle */
- if(Inpf(unit_nor,dvec)<0.0f)
- VecMulf(unit_nor,-1.0f);
+ /* special case for object hitting the particle from behind */
+ if(through==0 && ((inp_v>0 && inp>0 && inp_v>inp) || (inp_v<0 && inp<0 && inp_v<inp)))
+ VecMulf(nor_vec, inp_v);
+ else
+ VecMulf(nor_vec, inp_v + (through ? 1.0f : -1.0f) * inp);
- /* store for easy velocity calculation */
- o_len=VecLength(dvec);
+ /* angular <-> linear velocity - slightly more physical and looks even nicer than before */
+ if(part->flag & PART_ROT_DYN) {
+ float surface_vel[3], rot_vel[3], friction[3], dave[3], dvel[3];
- /* project particle movement to normal & create tangent */
- dotprod=Inpf(dvec,unit_nor);
- VECCOPY(def_nor,unit_nor);
- VecMulf(def_nor,dotprod);
- VECSUB(def_tan,def_nor,dvec);
+ /* apparent velocity along collision surface */
+ VECSUB(surface_vel, tan_vec, tan_vel);
- damp=ob->pd->pdef_damp+ob->pd->pdef_rdamp*2*(BLI_frand()-0.5f);
+ /* direction of rolling friction */
+ Crossf(rot_vel, state->ave, col.nor);
+ /* convert to current dt */
+ VecMulf(rot_vel, (timestep*dfra) * (1.0f - col.t));
+ VecMulf(rot_vel, pa->size);
- /* create location after deflection */
- VECCOPY(dvec,def_nor);
- damp=ob->pd->pdef_damp+ob->pd->pdef_rdamp*2*(BLI_frand()-0.5f);
- CLAMP(damp,0.0,1.0);
- VecMulf(dvec,1.0f-damp);
- if(through)
- VecMulf(dvec,-1.0);
-
- frict=ob->pd->pdef_frict+ob->pd->pdef_rfrict*2.0f*(BLI_frand()-0.5f);
- CLAMP(frict,0.0,1.0);
- VECADDFAC(dvec,dvec,def_tan,1.0f-frict);
+ /* apply sliding friction */
+ VECSUB(surface_vel, surface_vel, rot_vel);
+ VECCOPY(friction, surface_vel);
- /* store for easy velocity calculation */
- d_len=VecLength(dvec);
+ VecMulf(surface_vel, 1.0 - frict);
+ VecMulf(friction, frict);
- /* just to be sure we don't hit the current face again */
- if(through){
- VECADDFAC(ipoint,ipoint,unit_nor,-0.0001f);
- VECADDFAC(def_loc,def_loc,unit_nor,-0.0001f);
+ /* sliding changes angular velocity */
+ Crossf(dave, col.nor, friction);
+ VecMulf(dave, 1.0f/MAX2(pa->size, 0.001));
- if(part->flag & PART_ROT_DYN){
- VECADDFAC(def_tan,def_tan,unit_nor,-0.0001f);
- VECADDFAC(def_nor,def_nor,unit_nor,-0.0001f);
- }
- }
- else{
- VECADDFAC(ipoint,ipoint,unit_nor,0.0001f);
- VECADDFAC(def_loc,def_loc,unit_nor,0.0001f);
+ /* we assume rolling friction is around 0.01 of sliding friction */
+ VecMulf(rot_vel, 1.0 - frict*0.01);
- if(part->flag & PART_ROT_DYN){
- VECADDFAC(def_tan,def_tan,unit_nor,0.0001f);
- VECADDFAC(def_nor,def_nor,unit_nor,0.0001f);
- }
- }
+ /* change in angular velocity has to be added to the linear velocity too */
+ Crossf(dvel, dave, col.nor);
+ VecMulf(dvel, pa->size);
+ VECADD(rot_vel, rot_vel, dvel);
- /* lets get back to global space */
- if(global==0){
- Mat4Mul3Vecfl(ob->obmat,dvec);
- Mat4MulVecfl(ob->obmat,ipoint);
- Mat4MulVecfl(ob->obmat,def_loc);/* def_loc remains as intersection point for next iteration */
- }
+ VECADD(surface_vel, surface_vel, rot_vel);
+ VECADD(tan_vec, surface_vel, tan_vel);
- /* store for reactors */
- VECCOPY(cstate.co,ipoint);
- VecLerpf(cstate.vel,pa->state.vel,state->vel,min_d);
- QuatInterpol(cstate.rot,pa->state.rot,state->rot,min_d);
-
- /* slightly unphysical but looks nice enough */
- if(part->flag & PART_ROT_DYN){
- if(global==0){
- Mat4Mul3Vecfl(ob->obmat,def_nor);
- Mat4Mul3Vecfl(ob->obmat,def_tan);
- }
+ /* convert back to normal time */
+ VecMulf(dave, 1.0f/MAX2((timestep*dfra) * (1.0f - col.t), 0.00001));
- Normalize(def_tan);
- Normalize(def_nor);
- VECCOPY(unit_nor,def_nor);
+ VecMulf(state->ave, 1.0 - frict*0.01);
+ VECADD(state->ave, state->ave, dave);
+ }
- /* create normal velocity */
- VecMulf(def_nor,Inpf(pa->state.vel,def_nor));
+ /* combine components together again */
+ VECADD(vec, nor_vec, tan_vec);
- /* create tangential velocity */
- VecMulf(def_tan,Inpf(pa->state.vel,def_tan));
-
- /* angular velocity change due to tangential velocity */
- Crossf(dave,unit_nor,def_tan);
- VecMulf(dave,1.0f/pa->size);
+ /* calculate velocity from collision vector */
+ VECCOPY(vel, vec);
+ VecMulf(vel, 1.0f/MAX2((timestep*dfra) * (1.0f - col.t), 0.00001));
- /* linear velocity change due to angular velocity */
- VecMulf(unit_nor,pa->size); /* point of impact from particle center */
- Crossf(dvel,pa->state.ave,unit_nor);
+ /* make sure we don't hit the current face again */
+ VECADDFAC(co, co, col.nor, (through ? -0.0001f : 0.0001f));
- if(through)
- VecMulf(def_nor,-1.0);
+ /* store state for reactors */
+ VECCOPY(reaction_state.co, co);
+ VecLerpf(reaction_state.vel, pa->state.vel, state->vel, dt);
+ QuatInterpol(reaction_state.rot, pa->state.rot, state->rot, dt);
- VecMulf(def_nor,1.0f-damp);
- VECSUB(dvel,dvel,def_nor);
+ /* set coordinates for next iteration */
+ VECCOPY(col.co1, co);
+ VECADDFAC(col.co2, co, vec, 1.0f - t);
+ col.t = dt;
- VecMulf(dvel,1.0f-frict);
- VecMulf(dave,1.0f-frict);
- }
-
- if(d_len<0.001 && VecLength(pa->state.vel)<0.001){
+ if(VecLength(vec) < 0.001 && VecLength(pa->state.vel) < 0.001) {
/* kill speed to stop slipping */
VECCOPY(state->vel,zerovec);
- VECCOPY(state->co,def_loc);
- if(part->flag & PART_ROT_DYN)
+ VECCOPY(state->co, co);
+ if(part->flag & PART_ROT_DYN) {
VECCOPY(state->ave,zerovec);
- deflections=10;
- }
- else{
-
- /* apply new coordinates */
- VECADD(state->co,def_loc,dvec);
-
- Normalize(dvec);
-
- /* we have to use original velocity because otherwise we get slipping */
- /* when forces like gravity balance out damping & friction */
- VecMulf(dvec,VecLength(pa->state.vel)*(d_len/o_len));
- VECCOPY(state->vel,dvec);
-
- if(part->flag & PART_ROT_DYN){
- VECADD(state->vel,state->vel,dvel);
- VecMulf(state->vel,0.5);
- VECADD(state->ave,state->ave,dave);
- VecMulf(state->ave,0.5);
}
}
+ else {
+ VECCOPY(state->co, col.co2);
+ VECCOPY(state->vel, vel);
+ }
}
deflections++;
- cstate.time=cfra-(1.0f-min_d)*dfra;
- //particle_react_to_collision(min_ob,pob,psys,pa,p,&cstate);
- push_reaction(pob,psys,p,PART_EVENT_COLLIDE,&cstate);
+ reaction_state.time = cfra - (1.0f - dt) * dfra;
+ push_reaction(col.ob, psys, p, PART_EVENT_COLLIDE, &reaction_state);
}
else
return;
@@ -3469,7 +3410,7 @@ static int add_boid_acc(BoidVecFunc *bvf, float lat_max, float tan_max, float *l
}
}
/* determines the acceleration that the boid tries to acchieve */
-static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleSystem *psys, ParticleSettings *part, KDTree *tree, float timestep, float cfra, float *acc, int *pa_die)
+static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleSystem *psys, ParticleSettings *part, KDTree *tree, float timestep, float cfra, float *acc)
{
ParticleData *pars=psys->particles;
KDTreeNearest ptn[MAX_BOIDNEIGHBOURS+1];
@@ -3536,7 +3477,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS
distance=Normalize(dvec);
if(part->flag & PART_DIE_ON_COL && distance < pd->mindist){
- *pa_die=1;
+ pa->alive = PARS_DYING;
pa->dietime=cfra;
i=BOID_TOT_RULES;
break;
@@ -3565,7 +3506,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS
pd= epart->pd;
totepart= epsys->totpart;
- if(pd->forcefield==PFIELD_FORCE && pd->f_strength<0.0){
+ if(pd->forcefield==PFIELD_FORCE && pd->f_strength<0.0 && ec->tree){
count=BLI_kdtree_find_n_nearest(ec->tree,epart->boidneighbours,pa->state.co,NULL,ptn2);
for(p=0; p<count; p++){
state.time=-1.0;
@@ -3575,7 +3516,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS
distance = Normalize(dvec);
if(part->flag & PART_DIE_ON_COL && distance < (epsys->particles+ptn2[p].index)->size){
- *pa_die=1;
+ pa->alive = PARS_DYING;
pa->dietime=cfra;
i=BOID_TOT_RULES;
break;
@@ -3712,7 +3653,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS
pd= epart->pd;
totepart= epsys->totpart;
- if(pd->forcefield==PFIELD_FORCE && pd->f_strength>0.0){
+ if(pd->forcefield==PFIELD_FORCE && pd->f_strength>0.0 && ec->tree){
count=BLI_kdtree_find_n_nearest(ec->tree,epart->boidneighbours,pa->state.co,NULL,ptn2);
for(p=0; p<count; p++){
state.time=-1.0;
@@ -3862,7 +3803,7 @@ static void boid_body(BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys,
state->vel[2]=0.0;
state->co[2]=part->groundz;
- if(psys->keyed_ob){
+ if(psys->keyed_ob && (psys->keyed_ob->type == OB_MESH)){
Object *zob=psys->keyed_ob;
int min_face;
float co1[3],co2[3],min_d=2.0,min_w[4],imat[4][4];
@@ -3984,7 +3925,7 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi
IpoCurve *icu_esize=find_ipocurve(part->ipo,PART_EMIT_SIZE);
Material *ma=give_current_material(ob,part->omat);
float timestep;
- int p, totpart, pa_die;
+ int p, totpart;
/* current time */
float ctime, ipotime;
/* frame & time changes */
@@ -4064,7 +4005,7 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi
psys_init_effectors(ob,part->eff_group,psys);
if(psys->effectors.first)
- precalc_effectors(ob,psys,psmd);
+ precalc_effectors(ob,psys,psmd,cfra);
if(part->phystype==PART_PHYS_BOIDS){
/* create particle tree for fast inter-particle comparisons */
@@ -4093,15 +4034,13 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi
}
pa->size=psys_get_size(ob,ma,psmd,icu_esize,psys,part,pa,vg_size);
- pa_die=0;
-
birthtime = pa->time + pa->loop * pa->lifetime;
+ /* allways reset particles to emitter before birth */
if(pa->alive==PARS_UNBORN
|| pa->alive==PARS_KILLED
|| ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED)
|| birthtime >= cfra){
- /* allways reset particles to emitter before birth */
reset_particle(pa,psys,psmd,ob,dtime,cfra,vg_vel,vg_tan,vg_rot);
copy_particle_key(key,&pa->state,1);
}
@@ -4126,32 +4065,31 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi
/* particle dies some time between this and last step */
pa_dfra = dietime - psys->cfra;
pa_dtime = pa_dfra * timestep;
- pa_die = 1;
+ pa->alive = PARS_DYING;
}
else if(dietime < cfra){
- /* TODO: figure out if there's something to be done when particle is dead */
+ /* nothing to be done when particle is dead */
}
copy_particle_key(key,&pa->state,1);
- if(dfra>0.0 && pa->alive==PARS_ALIVE){
+ if(dfra>0.0 && ELEM(pa->alive,PARS_ALIVE,PARS_DYING)){
switch(part->phystype){
case PART_PHYS_NEWTON:
/* do global forces & effectors */
apply_particle_forces(p,pa,ob,psys,part,timestep,pa_dfra,cfra,key);
-
+
/* deflection */
- deflect_particle(ob,psmd,psys,part,pa,p,pa_dfra,cfra,key,&pa_die);
+ deflect_particle(ob,psmd,psys,part,pa,p,timestep,pa_dfra,cfra,key);
/* rotations */
rotate_particle(part,pa,pa_dfra,timestep,key);
-
break;
case PART_PHYS_BOIDS:
{
float acc[3];
- boid_brain(&bvf,pa,ob,psys,part,tree,timestep,cfra,acc,&pa_die);
- if(pa_die==0)
+ boid_brain(&bvf,pa,ob,psys,part,tree,timestep,cfra,acc);
+ if(pa->alive != PARS_DYING)
boid_body(&bvf,pa,psys,part,timestep,acc,key);
break;
}
@@ -4159,7 +4097,7 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi
push_reaction(ob,psys,p,PART_EVENT_NEAR,key);
- if(pa_die){
+ if(pa->alive == PARS_DYING){
push_reaction(ob,psys,p,PART_EVENT_DEATH,key);
if(part->flag & PART_LOOP && part->type!=PART_HAIR){
@@ -4181,6 +4119,7 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi
}
}
}
+
/* apply outstates to particles */
for(p=0, pa=psys->particles, key=outstate; p<totpart; p++,pa++,key++)
copy_particle_key(&pa->state,key,1);
@@ -4260,7 +4199,7 @@ static void hair_step(Object *ob, ParticleSystemModifierData *psmd, ParticleSyst
psys_init_effectors(ob,part->eff_group,psys);
if(psys->effectors.first)
- precalc_effectors(ob,psys,psmd);
+ precalc_effectors(ob,psys,psmd,cfra);
if(psys_in_edit_mode(psys))
PE_recalc_world_cos(ob, psys);
@@ -4288,7 +4227,7 @@ static void cached_step(Object *ob, ParticleSystemModifierData *psmd, ParticleSy
//if(part->flag & (PART_BAKED_GUIDES+PART_BAKED_DEATHS)){
psys_init_effectors(ob,part->eff_group,psys);
if(psys->effectors.first)
- precalc_effectors(ob,psys,psmd);
+ precalc_effectors(ob,psys,psmd,cfra);
//}
disp= (float)get_current_display_percentage(psys)/50.0f-1.0f;
@@ -4542,7 +4481,7 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier
if(usecache) {
/* frame clamping */
if(framenr < startframe) {
- psys_reset(psys, PSYS_RESET_DEPSGRAPH);
+ psys_reset(psys, PSYS_RESET_CACHE_MISS);
psys->cfra = cfra;
psys->recalc = 0;
return;
@@ -4622,14 +4561,14 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier
return;
}
else if(ob->id.lib || (cache->flag & PTCACHE_BAKED)) {
- psys_reset(psys, PSYS_RESET_DEPSGRAPH);
+ psys_reset(psys, PSYS_RESET_CACHE_MISS);
psys->cfra=cfra;
psys->recalc = 0;
return;
}
if(framenr != startframe && framedelta != 1) {
- psys_reset(psys, PSYS_RESET_DEPSGRAPH);
+ psys_reset(psys, PSYS_RESET_CACHE_MISS);
psys->cfra = cfra;
psys->recalc = 0;
return;
diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c
index 292a800e9cd..76af9a763ee 100644
--- a/source/blender/blenkernel/intern/shrinkwrap.c
+++ b/source/blender/blenkernel/intern/shrinkwrap.c
@@ -113,23 +113,23 @@ void space_transform_from_matrixs(SpaceTransform *data, float local[4][4], float
void space_transform_apply(const SpaceTransform *data, float *co)
{
- VecMat4MulVecfl(co, data->local2target, co);
+ VecMat4MulVecfl(co, ((SpaceTransform*)data)->local2target, co);
}
void space_transform_invert(const SpaceTransform *data, float *co)
{
- VecMat4MulVecfl(co, data->target2local, co);
+ VecMat4MulVecfl(co, ((SpaceTransform*)data)->target2local, co);
}
void space_transform_apply_normal(const SpaceTransform *data, float *no)
{
- Mat4Mul3Vecfl(data->local2target, no);
+ Mat4Mul3Vecfl( ((SpaceTransform*)data)->local2target, no);
Normalize(no); // TODO: could we just determine de scale value from the matrix?
}
void space_transform_invert_normal(const SpaceTransform *data, float *no)
{
- Mat4Mul3Vecfl(data->target2local, no);
+ Mat4Mul3Vecfl(((SpaceTransform*)data)->target2local, no);
Normalize(no); // TODO: could we just determine de scale value from the matrix?
}
@@ -291,7 +291,7 @@ int normal_projection_project_vertex(char options, const float *vert, const floa
space_transform_apply_normal( transf, tmp_no );
no = tmp_no;
- hit_tmp.dist *= Mat4ToScalef( transf->local2target );
+ hit_tmp.dist *= Mat4ToScalef( ((SpaceTransform*)transf)->local2target );
}
else
{
@@ -301,7 +301,7 @@ int normal_projection_project_vertex(char options, const float *vert, const floa
hit_tmp.index = -1;
- BLI_bvhtree_ray_cast(tree, co, no, &hit_tmp, callback, userdata);
+ BLI_bvhtree_ray_cast(tree, co, no, 0.0f, &hit_tmp, callback, userdata);
if(hit_tmp.index != -1)
{
@@ -318,7 +318,7 @@ int normal_projection_project_vertex(char options, const float *vert, const floa
space_transform_invert( transf, hit_tmp.co );
space_transform_invert_normal( transf, hit_tmp.no );
- hit_tmp.dist = VecLenf( vert, hit_tmp.co );
+ hit_tmp.dist = VecLenf( (float*)vert, hit_tmp.co );
}
memcpy(hit, &hit_tmp, sizeof(hit_tmp) );
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index d465c058d30..508b2233536 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -1622,23 +1622,23 @@ void *exec_scan_for_ext_spring_forces(void *data)
void sb_sfesf_threads_run(struct Object *ob, float timenow,int totsprings,int *ptr_to_break_func())
{
- ListBase *do_effector = NULL;
+ ListBase *do_effector = NULL;
ListBase threads;
SB_thread_context *sb_threads;
int i, totthread,left,dec;
- int lowsprings =10; /* wild guess .. may increase with better thread management 'above' or even be UI option sb->spawn_cf_threads_nopts */
+ int lowsprings =100; /* wild guess .. may increase with better thread management 'above' or even be UI option sb->spawn_cf_threads_nopts */
do_effector= pdInitEffectors(ob,NULL);
/* figure the number of threads while preventing pretty pointless threading overhead */
- if(totsprings < lowsprings) {totthread=1;}
- else{
- if(G.scene->r.mode & R_FIXED_THREADS)
- totthread= G.scene->r.threads;
- else
- totthread= BLI_system_thread_count();
+ if(G.scene->r.mode & R_FIXED_THREADS)
+ totthread= G.scene->r.threads;
+ else
+ totthread= BLI_system_thread_count();
+ /* what if we got zillions of CPUs running but less to spread*/
+ while ((totsprings/totthread < lowsprings) && (totthread > 1)) {
+ totthread--;
}
- /*left to do--> what if we got zillions of CPUs running but 'totsprings' tasks to spread*/
sb_threads= MEM_callocN(sizeof(SB_thread_context)*totthread, "SBSpringsThread");
memset(sb_threads, 0, sizeof(SB_thread_context)*totthread);
@@ -2279,6 +2279,11 @@ int _softbody_calc_forces_slice_in_a_thread(Object *ob, float forcetime, float t
float kd = 1.0f;
if (sb_deflect_face(ob,bp->pos,facenormal,defforce,&cf,timenow,vel,&intrusion)){
+ if (intrusion < 0.0f){
+ sb->scratch->flag |= SBF_DOFUZZY;
+ bp->flag |= SBF_DOFUZZY;
+ bp->choke = sb->choke*0.01f;
+ }
VECSUB(cfforce,bp->vec,vel);
Vec3PlusStVec(bp->force,-cf*50.0f,cfforce);
@@ -2326,17 +2331,19 @@ void sb_cf_threads_run(struct Object *ob, float forcetime, float timenow,int tot
ListBase threads;
SB_thread_context *sb_threads;
int i, totthread,left,dec;
- int lowpoints =10; /* wild guess .. may increase with better thread management 'above' or even be UI option sb->spawn_cf_threads_nopts */
+ int lowpoints =100; /* wild guess .. may increase with better thread management 'above' or even be UI option sb->spawn_cf_threads_nopts */
/* figure the number of threads while preventing pretty pointless threading overhead */
- if(totpoint < lowpoints) {totthread=1;}
- else{
- if(G.scene->r.mode & R_FIXED_THREADS)
- totthread= G.scene->r.threads;
- else
- totthread= BLI_system_thread_count();
+ if(G.scene->r.mode & R_FIXED_THREADS)
+ totthread= G.scene->r.threads;
+ else
+ totthread= BLI_system_thread_count();
+ /* what if we got zillions of CPUs running but less to spread*/
+ while ((totpoint/totthread < lowpoints) && (totthread > 1)) {
+ totthread--;
}
- /*left to do--> what if we got zillions of CPUs running but 'totpoint' tasks to spread*/
+
+ /* printf("sb_cf_threads_run spawning %d threads \n",totthread); */
sb_threads= MEM_callocN(sizeof(SB_thread_context)*totthread, "SBThread");
memset(sb_threads, 0, sizeof(SB_thread_context)*totthread);
@@ -2425,7 +2432,7 @@ static void softbody_calc_forcesEx(Object *ob, float forcetime, float timenow, i
static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int nl_flags)
{
/* redirection to the new threaded Version */
- if (G.rt !=16){
+ if (!(G.rt & 0x10)){ // 16
softbody_calc_forcesEx(ob, forcetime, timenow, nl_flags);
return;
}
@@ -2433,6 +2440,10 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int
/* so the following will die */
/* |||||||||||||||||||||||||| */
/* VVVVVVVVVVVVVVVVVVVVVVVVVV */
+ /*backward compatibility note:
+ fixing bug [17428] which forces adaptive step size to tiny steps
+ in some situations
+ .. keeping G.rt==17 0x11 option for old files 'needing' the bug*/
/* rule we never alter free variables :bp->vec bp->pos in here !
* this will ruin adaptive stepsize AKA heun! (BM)
@@ -2681,14 +2692,25 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int
if (sb_deflect_face(ob,bp->pos,facenormal,defforce,&cf,timenow,vel,&intrusion)){
if ((!nl_flags)&&(intrusion < 0.0f)){
- /*bjornmose: uugh.. what an evil hack
- violation of the 'don't touch bp->pos in here' rule
- but works nice, like this-->
- we predict the solution beeing out of the collider
- in heun step No1 and leave the heun step No2 adapt to it
- so we kind of introduced a implicit solver for this case
- */
- Vec3PlusStVec(bp->pos,-intrusion,facenormal);
+ if(G.rt & 0x01){ // 17 we did check for bit 0x10 before
+ /*fixing bug [17428] this forces adaptive step size to tiny steps
+ in some situations .. keeping G.rt==17 option for old files 'needing' the bug
+ */
+ /*bjornmose: uugh.. what an evil hack
+ violation of the 'don't touch bp->pos in here' rule
+ but works nice, like this-->
+ we predict the solution beeing out of the collider
+ in heun step No1 and leave the heun step No2 adapt to it
+ so we kind of introduced a implicit solver for this case
+ */
+ Vec3PlusStVec(bp->pos,-intrusion,facenormal);
+ }
+ else{
+
+ VECSUB(cfforce,bp->vec,vel);
+ Vec3PlusStVec(bp->force,-cf*50.0f,cfforce);
+ }
+
sb->scratch->flag |= SBF_DOFUZZY;
bp->flag |= SBF_DOFUZZY;
@@ -4040,7 +4062,7 @@ static void softbody_step(Object *ob, SoftBody *sb, float dtime)
if(sb->solverflags & SBSO_MONITOR ){
sct=PIL_check_seconds_timer();
- if (sct-sst > 0.5f) printf(" solver time %f sec %s \n",sct-sst,ob->id.name);
+ if ((sct-sst > 0.5f) || (G.f & G_DEBUG)) printf(" solver time %f sec %s \n",sct-sst,ob->id.name);
}
}
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index bba79bd6d28..e6797186b53 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -61,6 +61,10 @@
#include "BIF_gl.h"
+#include "GPU_draw.h"
+#include "GPU_extensions.h"
+#include "GPU_material.h"
+
#include "CCGSubSurf.h"
typedef struct _VertData {
@@ -696,6 +700,7 @@ DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
for(index = 0; index < totedge; index++) {
CCGEdge *e = edgeMap2[index];
unsigned int flags = 0;
+ char bweight = 0;
int edgeIdx = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(ss, e));
if(!ccgSubSurf_getEdgeNumFaces(ss, e)) flags |= ME_LOOSEEDGE;
@@ -706,12 +711,14 @@ DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
dm->getEdge(dm, edgeIdx, &origMed);
flags |= origMed.flag;
+ bweight = origMed.bweight;
}
for(x = 0; x < edgeSize - 1; x++) {
med->v1 = getEdgeIndex(ss, e, x, edgeSize);
med->v2 = getEdgeIndex(ss, e, x + 1, edgeSize);
med->flag = flags;
+ med->bweight = bweight;
*origIndex = ccgDM_getEdgeMapIndex(NULL, ss, e);
++med;
++origIndex;
@@ -973,7 +980,7 @@ static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv)
memset(mv, 0, sizeof(*mv));
- if(vertNum < ccgdm->edgeMap[0].startVert) {
+ if((vertNum < ccgdm->edgeMap[0].startVert) && (ccgSubSurf_getNumFaces(ss) > 0)) {
/* this vert comes from face data */
int lastface = ccgSubSurf_getNumFaces(ss) - 1;
CCGFace *f;
@@ -1014,7 +1021,7 @@ static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv)
x = offset % gridSideVerts + 1;
VecCopyf(mv->co, ccgSubSurf_getFaceGridData(ss, f, grid, x, y));
}
- } else if(vertNum < ccgdm->vertMap[0].startVert) {
+ } else if((vertNum < ccgdm->vertMap[0].startVert) && (ccgSubSurf_getNumEdges(ss) > 0)) {
/* this vert comes from edge data */
CCGEdge *e;
int lastedge = ccgSubSurf_getNumEdges(ss) - 1;
@@ -1599,7 +1606,7 @@ static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d)
}
/* Only used by non-editmesh types */
-static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int)) {
+static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) {
CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
CCGSubSurf *ss = ccgdm->ss;
CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
@@ -1621,7 +1628,7 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int)) {
mat_nr= 0;
}
- if (!setMaterial(mat_nr+1))
+ if (!setMaterial(mat_nr+1, NULL))
continue;
glShadeModel(drawSmooth? GL_SMOOTH: GL_FLAT);
@@ -1666,6 +1673,168 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int)) {
ccgFaceIterator_free(fi);
}
+
+ /* Only used by non-editmesh types */
+static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData) {
+ CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
+ CCGSubSurf *ss = ccgdm->ss;
+ CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
+ GPUVertexAttribs gattribs;
+ DMVertexAttribs attribs;
+ MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE);
+ int gridSize = ccgSubSurf_getGridSize(ss);
+ int gridFaces = gridSize - 1;
+ int edgeSize = ccgSubSurf_getEdgeSize(ss);
+ int transp, orig_transp, new_transp;
+ char *faceFlags = DM_get_face_data_layer(dm, CD_FLAGS);
+ int a, b, i, doDraw, numVerts, matnr, new_matnr, totface;
+
+ doDraw = 0;
+ numVerts = 0;
+ matnr = -1;
+ transp = GPU_get_material_blend_mode();
+ orig_transp = transp;
+
+ memset(&attribs, 0, sizeof(attribs));
+
+#define PASSATTRIB(dx, dy, vert) { \
+ if(attribs.totorco) { \
+ index = getFaceIndex(ss, f, S, x+dx, y+dy, edgeSize, gridSize); \
+ glVertexAttrib3fvARB(attribs.orco.glIndex, attribs.orco.array[index]); \
+ } \
+ for(b = 0; b < attribs.tottface; b++) { \
+ MTFace *tf = &attribs.tface[b].array[a]; \
+ glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]); \
+ } \
+ for(b = 0; b < attribs.totmcol; b++) { \
+ MCol *cp = &attribs.mcol[b].array[a*4 + vert]; \
+ GLubyte col[4]; \
+ col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; \
+ glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col); \
+ } \
+ if(attribs.tottang) { \
+ float *tang = attribs.tang.array[a*4 + vert]; \
+ glVertexAttrib3fvARB(attribs.tang.glIndex, tang); \
+ } \
+}
+
+ totface = ccgSubSurf_getNumFaces(ss);
+ for(a = 0, i = 0; i < totface; i++) {
+ CCGFace *f = ccgdm->faceMap[i].face;
+ int S, x, y, drawSmooth;
+ int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
+ int origIndex = ccgDM_getFaceMapIndex(ccgdm, ss, f);
+
+ numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
+
+ if(faceFlags) {
+ drawSmooth = (faceFlags[index*4] & ME_SMOOTH);
+ new_matnr= faceFlags[index*4 + 1] + 1;
+ }
+ else {
+ drawSmooth = 1;
+ new_matnr= 1;
+ }
+
+ if(new_matnr != matnr) {
+ doDraw = setMaterial(matnr = new_matnr, &gattribs);
+ if(doDraw)
+ DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
+ }
+
+ if(!doDraw || (setDrawOptions && !setDrawOptions(userData, origIndex))) {
+ a += gridFaces*gridFaces*numVerts;
+ continue;
+ }
+
+ if(tf) {
+ new_transp = tf[i].transp;
+
+ if(new_transp != transp) {
+ if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
+ GPU_set_material_blend_mode(orig_transp);
+ else
+ GPU_set_material_blend_mode(new_transp);
+ transp = new_transp;
+ }
+ }
+
+ glShadeModel(drawSmooth? GL_SMOOTH: GL_FLAT);
+ for (S=0; S<numVerts; S++) {
+ VertData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
+ VertData *vda, *vdb;
+
+ if (drawSmooth) {
+ for (y=0; y<gridFaces; y++) {
+ glBegin(GL_QUAD_STRIP);
+ for (x=0; x<gridFaces; x++) {
+ vda = &faceGridData[(y+0)*gridSize + x];
+ vdb = &faceGridData[(y+1)*gridSize + x];
+
+ PASSATTRIB(0, 0, 0);
+ glNormal3fv(vda->no);
+ glVertex3fv(vda->co);
+
+ PASSATTRIB(0, 1, 1);
+ glNormal3fv(vdb->no);
+ glVertex3fv(vdb->co);
+
+ if(x != gridFaces-1)
+ a++;
+ }
+
+ vda = &faceGridData[(y+0)*gridSize + x];
+ vdb = &faceGridData[(y+1)*gridSize + x];
+
+ PASSATTRIB(0, 0, 3);
+ glNormal3fv(vda->no);
+ glVertex3fv(vda->co);
+
+ PASSATTRIB(0, 1, 2);
+ glNormal3fv(vdb->no);
+ glVertex3fv(vdb->co);
+
+ glEnd();
+
+ a++;
+ }
+ } else {
+ glBegin(GL_QUADS);
+ for (y=0; y<gridFaces; y++) {
+ for (x=0; x<gridFaces; x++) {
+ float *aco = faceGridData[(y+0)*gridSize + x].co;
+ float *bco = faceGridData[(y+0)*gridSize + x + 1].co;
+ float *cco = faceGridData[(y+1)*gridSize + x + 1].co;
+ float *dco = faceGridData[(y+1)*gridSize + x].co;
+
+ ccgDM_glNormalFast(aco, bco, cco, dco);
+
+ PASSATTRIB(0, 1, 1);
+ glVertex3fv(dco);
+ PASSATTRIB(1, 1, 2);
+ glVertex3fv(cco);
+ PASSATTRIB(1, 0, 3);
+ glVertex3fv(bco);
+ PASSATTRIB(0, 0, 0);
+ glVertex3fv(aco);
+
+ a++;
+ }
+ }
+ glEnd();
+ }
+ }
+ }
+
+#undef PASSATTRIB
+
+ ccgFaceIterator_free(fi);
+}
+
+static void ccgDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) {
+ dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
+}
+
static void ccgDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2) {
CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
CCGSubSurf *ss = ccgdm->ss;
@@ -2143,8 +2312,10 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
ccgdm->dm.drawFacesSolid = ccgDM_drawFacesSolid;
ccgdm->dm.drawFacesColored = ccgDM_drawFacesColored;
ccgdm->dm.drawFacesTex = ccgDM_drawFacesTex;
+ ccgdm->dm.drawFacesGLSL = ccgDM_drawFacesGLSL;
ccgdm->dm.drawMappedFaces = ccgDM_drawMappedFaces;
ccgdm->dm.drawMappedFacesTex = ccgDM_drawMappedFacesTex;
+ ccgdm->dm.drawMappedFacesGLSL = ccgDM_drawMappedFacesGLSL;
ccgdm->dm.drawUVEdges = ccgDM_drawUVEdges;
ccgdm->dm.drawMappedEdgesInterp = ccgDM_drawMappedEdgesInterp;
diff --git a/source/blender/blenkernel/intern/suggestions.c b/source/blender/blenkernel/intern/suggestions.c
new file mode 100644
index 00000000000..6530909336c
--- /dev/null
+++ b/source/blender/blenkernel/intern/suggestions.c
@@ -0,0 +1,254 @@
+/**
+ * $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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008, Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Ian Thompson.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "MEM_guardedalloc.h"
+#include "BLI_blenlib.h"
+#include "DNA_text_types.h"
+#include "BKE_text.h"
+#include "BKE_suggestions.h"
+
+/**********************/
+/* Static definitions */
+/**********************/
+
+static Text *activeToolText = NULL;
+static SuggList suggestions = {NULL, NULL, NULL, NULL, NULL};
+static char *documentation = NULL;
+//static int doc_lines = 0;
+
+static int txttl_cmp(const char *first, const char *second, int len) {
+ int cmp, i;
+ for (cmp=0, i=0; i<len; i++) {
+ if ( (cmp= toupper(first[i])-toupper(second[i])) ) {
+ break;
+ }
+ }
+ return cmp;
+}
+
+static void txttl_free_suggest() {
+ SuggItem *item, *prev;
+ for (item = suggestions.last; item; item=prev) {
+ prev = item->prev;
+ MEM_freeN(item);
+ }
+ suggestions.first = suggestions.last = NULL;
+ suggestions.firstmatch = suggestions.lastmatch = NULL;
+ suggestions.selected = NULL;
+ suggestions.top = 0;
+}
+
+static void txttl_free_docs() {
+ if (documentation) {
+ MEM_freeN(documentation);
+ documentation = NULL;
+ }
+}
+
+/**************************/
+/* General tool functions */
+/**************************/
+
+void free_texttools() {
+ txttl_free_suggest();
+ txttl_free_docs();
+}
+
+void texttool_text_set_active(Text *text) {
+ if (activeToolText == text) return;
+ texttool_text_clear();
+ activeToolText = text;
+}
+
+void texttool_text_clear() {
+ free_texttools();
+ activeToolText = NULL;
+}
+
+short texttool_text_is_active(Text *text) {
+ return activeToolText==text ? 1 : 0;
+}
+
+/***************************/
+/* Suggestion list methods */
+/***************************/
+
+void texttool_suggest_add(const char *name, char type) {
+ SuggItem *newitem, *item;
+ int len, cmp;
+
+ newitem = MEM_mallocN(sizeof(SuggItem) + strlen(name) + 1, "SuggestionItem");
+ if (!newitem) {
+ printf("Failed to allocate memory for suggestion.\n");
+ return;
+ }
+
+ newitem->name = (char *) (newitem + 1);
+ len = strlen(name);
+ strncpy(newitem->name, name, len);
+ newitem->name[len] = '\0';
+ newitem->type = type;
+ newitem->prev = newitem->next = NULL;
+
+ /* Perform simple linear search for ordered storage */
+ if (!suggestions.first || !suggestions.last) {
+ suggestions.first = suggestions.last = newitem;
+ } else {
+ cmp = -1;
+ for (item=suggestions.last; item; item=item->prev) {
+ cmp = txttl_cmp(name, item->name, len);
+
+ /* Newitem comes after this item, insert here */
+ if (cmp >= 0) {
+ newitem->prev = item;
+ if (item->next)
+ item->next->prev = newitem;
+ newitem->next = item->next;
+ item->next = newitem;
+
+ /* At last item, set last pointer here */
+ if (item == suggestions.last)
+ suggestions.last = newitem;
+ break;
+ }
+ }
+ /* Reached beginning of list, insert before first */
+ if (cmp < 0) {
+ newitem->next = suggestions.first;
+ suggestions.first->prev = newitem;
+ suggestions.first = newitem;
+ }
+ }
+ suggestions.firstmatch = suggestions.lastmatch = suggestions.selected = NULL;
+ suggestions.top= 0;
+}
+
+void texttool_suggest_prefix(const char *prefix) {
+ SuggItem *match, *first, *last;
+ int cmp, len = strlen(prefix), top = 0;
+
+ if (!suggestions.first) return;
+ if (len==0) {
+ suggestions.selected = suggestions.firstmatch = suggestions.first;
+ suggestions.lastmatch = suggestions.last;
+ return;
+ }
+
+ first = last = NULL;
+ for (match=suggestions.first; match; match=match->next) {
+ cmp = txttl_cmp(prefix, match->name, len);
+ if (cmp==0) {
+ if (!first) {
+ first = match;
+ suggestions.top = top;
+ }
+ } else if (cmp<0) {
+ if (!last) {
+ last = match->prev;
+ break;
+ }
+ }
+ top++;
+ }
+ if (first) {
+ if (!last) last = suggestions.last;
+ suggestions.firstmatch = first;
+ suggestions.lastmatch = last;
+ suggestions.selected = first;
+ } else {
+ suggestions.firstmatch = NULL;
+ suggestions.lastmatch = NULL;
+ suggestions.selected = NULL;
+ suggestions.top = 0;
+ }
+}
+
+void texttool_suggest_clear() {
+ txttl_free_suggest();
+}
+
+SuggItem *texttool_suggest_first() {
+ return suggestions.firstmatch;
+}
+
+SuggItem *texttool_suggest_last() {
+ return suggestions.lastmatch;
+}
+
+void texttool_suggest_select(SuggItem *sel) {
+ suggestions.selected = sel;
+}
+
+SuggItem *texttool_suggest_selected() {
+ return suggestions.selected;
+}
+
+int *texttool_suggest_top() {
+ return &suggestions.top;
+}
+
+/*************************/
+/* Documentation methods */
+/*************************/
+
+void texttool_docs_show(const char *docs) {
+ int len;
+
+ if (!docs) return;
+
+ len = strlen(docs);
+
+ if (documentation) {
+ MEM_freeN(documentation);
+ documentation = NULL;
+ }
+
+ /* Ensure documentation ends with a '\n' */
+ if (docs[len-1] != '\n') {
+ documentation = MEM_mallocN(len+2, "Documentation");
+ strncpy(documentation, docs, len);
+ documentation[len++] = '\n';
+ } else {
+ documentation = MEM_mallocN(len+1, "Documentation");
+ strncpy(documentation, docs, len);
+ }
+ documentation[len] = '\0';
+}
+
+char *texttool_docs_get() {
+ return documentation;
+}
+
+void texttool_docs_clear() {
+ txttl_free_docs();
+}
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 53b7bb975a3..5f1a1e63da4 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -30,6 +30,8 @@
*/
#include <string.h> /* strstr */
+#include <sys/types.h>
+#include <sys/stat.h>
#include "MEM_guardedalloc.h"
@@ -81,12 +83,19 @@ The st->top determines at what line the top of the text is displayed.
If the user moves the cursor the st containing that cursor should
be popped ... other st's retain their own top location.
-*/ /***************/
-
+Markers
+--
+The mrk->flags define the behaviour and relationships between markers. The
+upper two bytes are used to hold a group ID, the lower two are normal flags. If
+TMARK_EDITALL is set the group ID defines which other markers should be edited.
-/****************/ /*
- Undo
+The mrk->clr field is used to visually group markers where the flags may not
+match. A template system, for example, may allow editing of repeating tokens
+(in one group) but include other marked positions (in another group) all in the
+same template with the same colour.
+Undo
+--
Undo/Redo works by storing
events in a queue, and a pointer
to the current position in the
@@ -145,6 +154,7 @@ void free_text(Text *text)
}
BLI_freelistN(&text->lines);
+ BLI_freelistN(&text->markers);
if(text->name) MEM_freeN(text->name);
MEM_freeN(text->undo_buf);
@@ -169,10 +179,11 @@ Text *add_empty_text(char *name)
ta->flags= TXT_ISDIRTY | TXT_ISTMP | TXT_ISMEM;
ta->lines.first= ta->lines.last= NULL;
+ ta->markers.first= ta->markers.last= NULL;
tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
tmp->line= (char*) MEM_mallocN(1, "textline_string");
- tmp->format= (char*) MEM_mallocN(2, "Syntax_format");
+ tmp->format= NULL;
tmp->line[0]=0;
tmp->len= 0;
@@ -209,11 +220,12 @@ static void cleanup_textline(TextLine * tl)
int reopen_text(Text *text)
{
FILE *fp;
- int i, llen, len;
+ int i, llen, len, res;
unsigned char *buffer;
TextLine *tmp;
char sfile[FILE_MAXFILE];
char str[FILE_MAXDIR+FILE_MAXFILE];
+ struct stat st;
if (!text || !text->name) return 0;
@@ -242,7 +254,7 @@ int reopen_text(Text *text)
text->undo_len= TXT_INIT_UNDO;
text->undo_buf= MEM_mallocN(text->undo_len, "undo buf");
- text->flags= TXT_ISDIRTY | TXT_ISTMP;
+ text->flags= TXT_ISTMP;
fseek(fp, 0L, SEEK_END);
len= ftell(fp);
@@ -256,6 +268,9 @@ int reopen_text(Text *text)
len = fread(buffer, 1, len, fp);
fclose(fp);
+
+ res= stat(str, &st);
+ text->mtime= st.st_mtime;
text->nlines=0;
i=0;
@@ -264,7 +279,7 @@ int reopen_text(Text *text)
if (buffer[i]=='\n') {
tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
tmp->line= (char*) MEM_mallocN(llen+1, "textline_string");
- tmp->format= (char*) MEM_mallocN(llen+2, "Syntax_format");
+ tmp->format= NULL;
if(llen) memcpy(tmp->line, &buffer[i-llen], llen);
tmp->line[llen]=0;
@@ -284,7 +299,7 @@ int reopen_text(Text *text)
if (llen!=0 || text->nlines==0) {
tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
tmp->line= (char*) MEM_mallocN(llen+1, "textline_string");
- tmp->format= (char*) MEM_mallocN(llen+2, "Syntax_format");
+ tmp->format= NULL;
if(llen) memcpy(tmp->line, &buffer[i-llen], llen);
@@ -307,12 +322,13 @@ int reopen_text(Text *text)
Text *add_text(char *file)
{
FILE *fp;
- int i, llen, len;
+ int i, llen, len, res;
unsigned char *buffer;
TextLine *tmp;
Text *ta;
char sfile[FILE_MAXFILE];
char str[FILE_MAXDIR+FILE_MAXFILE];
+ struct stat st;
BLI_strncpy(str, file, FILE_MAXDIR+FILE_MAXFILE);
if (G.scene) /* can be NULL (bg mode) */
@@ -326,6 +342,7 @@ Text *add_text(char *file)
ta->id.us= 1;
ta->lines.first= ta->lines.last= NULL;
+ ta->markers.first= ta->markers.last= NULL;
ta->curl= ta->sell= NULL;
/* ta->flags= TXT_ISTMP | TXT_ISEXT; */
@@ -348,6 +365,9 @@ Text *add_text(char *file)
len = fread(buffer, 1, len, fp);
fclose(fp);
+
+ res= stat(str, &st);
+ ta->mtime= st.st_mtime;
ta->nlines=0;
i=0;
@@ -356,7 +376,7 @@ Text *add_text(char *file)
if (buffer[i]=='\n') {
tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
tmp->line= (char*) MEM_mallocN(llen+1, "textline_string");
- tmp->format= (char*) MEM_mallocN(llen+2, "Syntax_format");
+ tmp->format= NULL;
if(llen) memcpy(tmp->line, &buffer[i-llen], llen);
tmp->line[llen]=0;
@@ -376,7 +396,7 @@ Text *add_text(char *file)
if (llen!=0 || ta->nlines==0) {
tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
tmp->line= (char*) MEM_mallocN(llen+1, "textline_string");
- tmp->format= (char*) MEM_mallocN(llen+2, "Syntax_format");
+ tmp->format= NULL;
if(llen) memcpy(tmp->line, &buffer[i-llen], llen);
@@ -410,6 +430,7 @@ Text *copy_text(Text *ta)
tan->flags = ta->flags | TXT_ISDIRTY | TXT_ISTMP;
tan->lines.first= tan->lines.last= NULL;
+ tan->markers.first= tan->markers.last= NULL;
tan->curl= tan->sell= NULL;
tan->nlines= ta->nlines;
@@ -419,7 +440,7 @@ Text *copy_text(Text *ta)
while (line) {
tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline");
tmp->line= MEM_mallocN(line->len+1, "textline_string");
- tmp->format= MEM_mallocN(line->len+2, "Syntax_format");
+ tmp->format= NULL;
strcpy(tmp->line, line->line);
@@ -440,14 +461,14 @@ Text *copy_text(Text *ta)
/* Editing utility functions */
/*****************************/
-static void make_new_line (TextLine *line, char *newline, char *newformat)
+static void make_new_line (TextLine *line, char *newline)
{
if (line->line) MEM_freeN(line->line);
if (line->format) MEM_freeN(line->format);
line->line= newline;
line->len= strlen(newline);
- line->format= newformat;
+ line->format= NULL;
}
static TextLine *txt_new_line(char *str)
@@ -458,7 +479,7 @@ static TextLine *txt_new_line(char *str)
tmp= (TextLine *) MEM_mallocN(sizeof(TextLine), "textline");
tmp->line= MEM_mallocN(strlen(str)+1, "textline_string");
- tmp->format= MEM_mallocN(strlen(str)+2, "Syntax_format");
+ tmp->format= NULL;
strcpy(tmp->line, str);
@@ -476,7 +497,7 @@ static TextLine *txt_new_linen(char *str, int n)
tmp= (TextLine *) MEM_mallocN(sizeof(TextLine), "textline");
tmp->line= MEM_mallocN(n+1, "textline_string");
- tmp->format= MEM_mallocN(n+2, "Syntax_format");
+ tmp->format= NULL;
BLI_strncpy(tmp->line, str, n+1);
@@ -553,6 +574,19 @@ static void txt_make_dirty (Text *text)
if (text->compiled) BPY_free_compiled_text(text);
}
+/* 0:whitespace, 1:punct, 2:alphanumeric */
+static short txt_char_type (char ch)
+{
+ if (ch <= ' ') return 0;
+ if (ch <= '/') return 1;
+ if (ch <= '9') return 2;
+ if (ch <= '@') return 1;
+ if (ch <= 'Z') return 2;
+ if (ch <= '`') return 1;
+ if (ch <= 'z') return 2;
+ return 1;
+}
+
/****************************/
/* Cursor utility functions */
/****************************/
@@ -606,8 +640,7 @@ void txt_move_up(Text *text, short sel)
if(!undoing) txt_undo_add_op(text, sel?UNDO_SUP:UNDO_CUP);
}
} else {
- *charp= 0;
- if(!undoing) txt_undo_add_op(text, sel?UNDO_SUP:UNDO_CUP);
+ txt_move_bol(text, sel);
}
if(!sel) txt_pop_sel(text);
@@ -632,8 +665,7 @@ void txt_move_down(Text *text, short sel)
} else
if(!undoing) txt_undo_add_op(text, sel?UNDO_SDOWN:UNDO_CDOWN);
} else {
- *charp= (*linep)->len;
- if(!undoing) txt_undo_add_op(text, sel?UNDO_SDOWN:UNDO_CDOWN);
+ txt_move_eol(text, sel);
}
if(!sel) txt_pop_sel(text);
@@ -689,6 +721,68 @@ void txt_move_right(Text *text, short sel)
if(!sel) txt_pop_sel(text);
}
+void txt_jump_left(Text *text, short sel)
+{
+ TextLine **linep, *oldl;
+ int *charp, oldc, count, i;
+ unsigned char oldu;
+
+ if (!text) return;
+ if(sel) txt_curs_sel(text, &linep, &charp);
+ else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); }
+ if (!*linep) return;
+
+ oldl= *linep;
+ oldc= *charp;
+ oldu= undoing;
+ undoing= 1; /* Don't push individual moves to undo stack */
+
+ count= 0;
+ for (i=0; i<3; i++) {
+ if (count < 2) {
+ while (*charp>0 && txt_char_type((*linep)->line[*charp-1])==i) {
+ txt_move_left(text, sel);
+ count++;
+ }
+ }
+ }
+ if (count==0) txt_move_left(text, sel);
+
+ undoing= oldu;
+ if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, oldl), oldc, txt_get_span(text->lines.first, *linep), (unsigned short)*charp);
+}
+
+void txt_jump_right(Text *text, short sel)
+{
+ TextLine **linep, *oldl;
+ int *charp, oldc, count, i;
+ unsigned char oldu;
+
+ if (!text) return;
+ if(sel) txt_curs_sel(text, &linep, &charp);
+ else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); }
+ if (!*linep) return;
+
+ oldl= *linep;
+ oldc= *charp;
+ oldu= undoing;
+ undoing= 1; /* Don't push individual moves to undo stack */
+
+ count= 0;
+ for (i=0; i<3; i++) {
+ if (count < 2) {
+ while (*charp<(*linep)->len && txt_char_type((*linep)->line[*charp])==i) {
+ txt_move_right(text, sel);
+ count++;
+ }
+ }
+ }
+ if (count==0) txt_move_right(text, sel);
+
+ undoing= oldu;
+ if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, oldl), oldc, txt_get_span(text->lines.first, *linep), (unsigned short)*charp);
+}
+
void txt_move_bol (Text *text, short sel)
{
TextLine **linep;
@@ -761,6 +855,11 @@ void txt_move_eof (Text *text, short sel)
void txt_move_toline (Text *text, unsigned int line, short sel)
{
+ txt_move_to(text, line, 0, sel);
+}
+
+void txt_move_to (Text *text, unsigned int line, unsigned int ch, short sel)
+{
TextLine **linep, *oldl;
int *charp, oldc;
unsigned int i;
@@ -777,10 +876,12 @@ void txt_move_toline (Text *text, unsigned int line, short sel)
if ((*linep)->next) *linep= (*linep)->next;
else break;
}
- *charp= 0;
+ if (ch>(*linep)->len)
+ ch= (*linep)->len;
+ *charp= ch;
if(!sel) txt_pop_sel(text);
- if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, oldl), oldc, txt_get_span(text->lines.first, *linep), (unsigned short)*charp);
+ if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, oldl), oldc, txt_get_span(text->lines.first, *linep), (unsigned short)*charp);
}
/****************************/
@@ -865,7 +966,9 @@ int txt_has_sel(Text *text)
static void txt_delete_sel (Text *text)
{
TextLine *tmpl;
- char *buf, *format;
+ TextMarker *mrk;
+ char *buf;
+ int move, lineno;
if (!text) return;
if (!text->curl) return;
@@ -882,13 +985,33 @@ static void txt_delete_sel (Text *text)
}
buf= MEM_mallocN(text->curc+(text->sell->len - text->selc)+1, "textline_string");
- format= MEM_mallocN(text->curc+(text->sell->len - text->selc)+2, "Syntax_format");
+ if (text->curl != text->sell) {
+ txt_clear_marker_region(text, text->curl, text->curc, text->curl->len, 0, 0);
+ move= txt_get_span(text->curl, text->sell);
+ } else {
+ mrk= txt_find_marker_region(text, text->curl, text->curc, text->selc, 0, 0);
+ if (mrk && (mrk->start > text->curc || mrk->end < text->selc))
+ txt_clear_marker_region(text, text->curl, text->curc, text->selc, 0, 0);
+ move= 0;
+ }
+
+ mrk= txt_find_marker_region(text, text->sell, text->selc-1, text->sell->len, 0, 0);
+ if (mrk) {
+ lineno= mrk->lineno;
+ do {
+ mrk->lineno -= move;
+ if (mrk->start > text->curc) mrk->start -= text->selc - text->curc;
+ mrk->end -= text->selc - text->curc;
+ mrk= mrk->next;
+ } while (mrk && mrk->lineno==lineno);
+ }
+
strncpy(buf, text->curl->line, text->curc);
strcpy(buf+text->curc, text->sell->line + text->selc);
buf[text->curc+(text->sell->len - text->selc)]=0;
- make_new_line(text->curl, buf, format);
+ make_new_line(text->curl, buf);
tmpl= text->sell;
while (tmpl != text->curl) {
@@ -995,22 +1118,31 @@ char *txt_to_buf (Text *text)
return buf;
}
-int txt_find_string(Text *text, char *findstr)
+int txt_find_string(Text *text, char *findstr, int wrap)
{
TextLine *tl, *startl;
char *s= NULL;
+ int oldcl, oldsl, oldcc, oldsc;
if (!text || !text->curl || !text->sell) return 0;
txt_order_cursors(text);
+ oldcl= txt_get_span(text->lines.first, text->curl);
+ oldsl= txt_get_span(text->lines.first, text->sell);
tl= startl= text->sell;
+ oldcc= text->curc;
+ oldsc= text->selc;
s= strstr(&tl->line[text->selc], findstr);
while (!s) {
tl= tl->next;
- if (!tl)
- tl= text->lines.first;
+ if (!tl) {
+ if (wrap)
+ tl= text->lines.first;
+ else
+ break;
+ }
s= strstr(tl->line, findstr);
if (tl==startl)
@@ -1018,10 +1150,10 @@ int txt_find_string(Text *text, char *findstr)
}
if (s) {
- text->curl= text->sell= tl;
- text->curc= (int) (s-tl->line);
- text->selc= text->curc + strlen(findstr);
-
+ int newl= txt_get_span(text->lines.first, tl);
+ int newc= (int)(s-tl->line);
+ txt_move_to(text, newl, newc, 0);
+ txt_move_to(text, newl, newc + strlen(findstr), 1);
return 1;
} else
return 0;
@@ -1621,7 +1753,6 @@ void txt_do_undo(Text *text)
case UNDO_SWAP:
txt_curs_swap(text);
- txt_do_undo(text); /* swaps should appear transparent */
break;
case UNDO_DBLOCK:
@@ -1736,6 +1867,19 @@ void txt_do_undo(Text *text)
break;
}
+
+ /* next undo step may need evaluating */
+ if (text->undo_pos>=0) {
+ switch (text->undo_buf[text->undo_pos]) {
+ case UNDO_STO:
+ txt_do_undo(text);
+ txt_do_redo(text); /* selections need restoring */
+ break;
+ case UNDO_SWAP:
+ txt_do_undo(text); /* swaps should appear transparent */
+ break;
+ }
+ }
undoing= 0;
}
@@ -1810,7 +1954,7 @@ void txt_do_redo(Text *text)
case UNDO_SWAP:
txt_curs_swap(text);
- txt_do_undo(text); /* swaps should appear transparent a*/
+ txt_do_redo(text); /* swaps should appear transparent a*/
break;
case UNDO_CTO:
@@ -1947,22 +2091,37 @@ void txt_do_redo(Text *text)
void txt_split_curline (Text *text)
{
TextLine *ins;
- char *left, *right, *fleft, *fright;
+ TextMarker *mrk;
+ char *left, *right;
+ int lineno= -1;
if (!text) return;
if (!text->curl) return;
- txt_delete_sel(text);
+ txt_delete_sel(text);
+
+ /* Move markers */
+
+ lineno= txt_get_span(text->lines.first, text->curl);
+ mrk= text->markers.first;
+ while (mrk) {
+ if (mrk->lineno==lineno && mrk->start>text->curc) {
+ mrk->lineno++;
+ mrk->start -= text->curc;
+ mrk->end -= text->curc;
+ } else if (mrk->lineno > lineno) {
+ mrk->lineno++;
+ }
+ mrk= mrk->next;
+ }
/* Make the two half strings */
left= MEM_mallocN(text->curc+1, "textline_string");
- fleft= MEM_mallocN(text->curc+2, "Syntax_format");
if (text->curc) memcpy(left, text->curl->line, text->curc);
left[text->curc]=0;
right= MEM_mallocN(text->curl->len - text->curc+1, "textline_string");
- fright= MEM_mallocN(text->curl->len - text->curc+2, "Syntax_format");
if (text->curl->len - text->curc) memcpy(right, text->curl->line+text->curc, text->curl->len-text->curc);
right[text->curl->len - text->curc]=0;
@@ -1973,11 +2132,11 @@ void txt_split_curline (Text *text)
ins= MEM_mallocN(sizeof(TextLine), "textline");
ins->line= left;
- ins->format= fleft;
+ ins->format= NULL;
ins->len= text->curc;
text->curl->line= right;
- text->curl->format= fright;
+ text->curl->format= NULL;
text->curl->len= text->curl->len - text->curc;
BLI_insertlinkbefore(&text->lines, text->curl, ins);
@@ -1993,9 +2152,23 @@ void txt_split_curline (Text *text)
static void txt_delete_line (Text *text, TextLine *line)
{
+ TextMarker *mrk=NULL, *nxt;
+ int lineno= -1;
+
if (!text) return;
if (!text->curl) return;
+ lineno= txt_get_span(text->lines.first, line);
+ mrk= text->markers.first;
+ while (mrk) {
+ nxt= mrk->next;
+ if (mrk->lineno==lineno)
+ BLI_freelinkN(&text->markers, mrk);
+ else if (mrk->lineno > lineno)
+ mrk->lineno--;
+ mrk= nxt;
+ }
+
BLI_remlink (&text->lines, line);
if (line->line) MEM_freeN(line->line);
@@ -2009,21 +2182,35 @@ static void txt_delete_line (Text *text, TextLine *line)
static void txt_combine_lines (Text *text, TextLine *linea, TextLine *lineb)
{
- char *tmp, *format;
+ char *tmp;
+ TextMarker *mrk= NULL;
+ int lineno=-1;
if (!text) return;
if(!linea || !lineb) return;
+
+ mrk= txt_find_marker_region(text, lineb, 0, lineb->len, 0, 0);
+ if (mrk) {
+ lineno= mrk->lineno;
+ do {
+ mrk->lineno--;
+ mrk->start += linea->len;
+ mrk->end += linea->len;
+ mrk= mrk->next;
+ } while (mrk && mrk->lineno==lineno);
+ }
+ if (lineno==-1) lineno= txt_get_span(text->lines.first, lineb);
+ if (!mrk) mrk= text->markers.first;
tmp= MEM_mallocN(linea->len+lineb->len+1, "textline_string");
- format= MEM_mallocN(linea->len+lineb->len+1, "Syntax_format");
strcpy(tmp, linea->line);
strcat(tmp, lineb->line);
- make_new_line(linea, tmp, format);
+ make_new_line(linea, tmp);
- txt_delete_line(text, lineb);
+ txt_delete_line(text, lineb);
txt_make_dirty(text);
txt_clean_text(text);
@@ -2037,8 +2224,9 @@ void txt_delete_char (Text *text)
if (!text->curl) return;
if (txt_has_sel(text)) { /* deleting a selection */
- txt_delete_sel(text);
- return;
+ txt_delete_sel(text);
+ txt_make_dirty(text);
+ return;
}
else if (text->curc== text->curl->len) { /* Appending two lines */
if (text->curl->next) {
@@ -2047,6 +2235,25 @@ void txt_delete_char (Text *text)
}
} else { /* Just deleting a char */
int i= text->curc;
+
+ TextMarker *mrk= txt_find_marker_region(text, text->curl, i-1, text->curl->len, 0, 0);
+ if (mrk) {
+ int lineno= mrk->lineno;
+ if (mrk->end==i) {
+ if ((mrk->flags & TMARK_TEMP) && !(mrk->flags & TMARK_EDITALL)) {
+ txt_clear_markers(text, mrk->group, TMARK_TEMP);
+ } else {
+ //TextMarker *nxt= mrk->next;
+ BLI_freelinkN(&text->markers, mrk);
+ }
+ return;
+ }
+ do {
+ if (mrk->start>i) mrk->start--;
+ mrk->end--;
+ mrk= mrk->next;
+ } while (mrk && mrk->lineno==lineno);
+ }
c= text->curl->line[i];
while(i< text->curl->len) {
@@ -2064,6 +2271,12 @@ void txt_delete_char (Text *text)
if(!undoing) txt_undo_add_charop(text, UNDO_DEL, c);
}
+void txt_delete_word (Text *text)
+{
+ txt_jump_right(text, 1);
+ txt_delete_sel(text);
+}
+
void txt_backspace_char (Text *text)
{
char c='\n';
@@ -2072,8 +2285,9 @@ void txt_backspace_char (Text *text)
if (!text->curl) return;
if (txt_has_sel(text)) { /* deleting a selection */
- txt_delete_sel(text);
- return;
+ txt_delete_sel(text);
+ txt_make_dirty(text);
+ return;
}
else if (text->curc==0) { /* Appending two lines */
if (!text->curl->prev) return;
@@ -2083,19 +2297,38 @@ void txt_backspace_char (Text *text)
txt_combine_lines(text, text->curl, text->curl->next);
txt_pop_sel(text);
- }
+ }
else { /* Just backspacing a char */
- int i= text->curc-1;
-
- c= text->curl->line[i];
- while(i< text->curl->len) {
- text->curl->line[i]= text->curl->line[i+1];
- i++;
- }
- text->curl->len--;
- text->curc--;
+ int i= text->curc-1;
+
+ TextMarker *mrk= txt_find_marker_region(text, text->curl, i, text->curl->len, 0, 0);
+ if (mrk) {
+ int lineno= mrk->lineno;
+ if (mrk->start==i+1) {
+ if ((mrk->flags & TMARK_TEMP) && !(mrk->flags & TMARK_EDITALL)) {
+ txt_clear_markers(text, mrk->group, TMARK_TEMP);
+ } else {
+ //TextMarker *nxt= mrk->next;
+ BLI_freelinkN(&text->markers, mrk);
+ }
+ return;
+ }
+ do {
+ if (mrk->start>i) mrk->start--;
+ mrk->end--;
+ mrk= mrk->next;
+ } while (mrk && mrk->lineno==lineno);
+ }
- txt_pop_sel(text);
+ c= text->curl->line[i];
+ while(i< text->curl->len) {
+ text->curl->line[i]= text->curl->line[i+1];
+ i++;
+ }
+ text->curl->len--;
+ text->curc--;
+
+ txt_pop_sel(text);
}
txt_make_dirty(text);
@@ -2104,10 +2337,17 @@ void txt_backspace_char (Text *text)
if(!undoing) txt_undo_add_charop(text, UNDO_BS, c);
}
+void txt_backspace_word (Text *text)
+{
+ txt_jump_left(text, 1);
+ txt_delete_sel(text);
+}
+
int txt_add_char (Text *text, char add)
{
- int len;
- char *tmp, *format;
+ int len, lineno;
+ char *tmp;
+ TextMarker *mrk;
if (!text) return 0;
if (!text->curl) return 0;
@@ -2119,8 +2359,17 @@ int txt_add_char (Text *text, char add)
txt_delete_sel(text);
+ mrk= txt_find_marker_region(text, text->curl, text->curc-1, text->curl->len, 0, 0);
+ if (mrk) {
+ lineno= mrk->lineno;
+ do {
+ if (mrk->start>text->curc) mrk->start++;
+ mrk->end++;
+ mrk= mrk->next;
+ } while (mrk && mrk->lineno==lineno);
+ }
+
tmp= MEM_mallocN(text->curl->len+2, "textline_string");
- format= MEM_mallocN(text->curl->len+4, "Syntax_format");
if(text->curc) memcpy(tmp, text->curl->line, text->curc);
tmp[text->curc]= add;
@@ -2128,7 +2377,7 @@ int txt_add_char (Text *text, char add)
len= text->curl->len - text->curc;
if(len>0) memcpy(tmp+text->curc+1, text->curl->line+text->curc, len);
tmp[text->curl->len+1]=0;
- make_new_line(text->curl, tmp, format);
+ make_new_line(text->curl, tmp);
text->curc++;
@@ -2141,10 +2390,42 @@ int txt_add_char (Text *text, char add)
return 1;
}
+int txt_replace_char (Text *text, char add)
+{
+ char del;
+
+ if (!text) return 0;
+ if (!text->curl) return 0;
+
+ /* If text is selected or we're at the end of the line just use txt_add_char */
+ if (text->curc==text->curl->len || txt_has_sel(text) || add=='\n') {
+ TextMarker *mrk;
+ int i= txt_add_char(text, add);
+ mrk= txt_find_marker(text, text->curl, text->curc, 0, 0);
+ if (mrk && mrk->end==text->curc) mrk->end--;
+ return i;
+ }
+
+ del= text->curl->line[text->curc];
+ text->curl->line[text->curc]= (unsigned char) add;
+ text->curc++;
+ txt_pop_sel(text);
+
+ txt_make_dirty(text);
+ txt_clean_text(text);
+
+ /* Should probably create a new op for this */
+ if(!undoing) {
+ txt_undo_add_charop(text, UNDO_DEL, del);
+ txt_undo_add_charop(text, UNDO_INSERT, add);
+ }
+ return 1;
+}
+
void indent(Text *text)
{
int len, num;
- char *tmp, *format;
+ char *tmp;
char add = '\t';
if (!text) return;
@@ -2155,7 +2436,6 @@ void indent(Text *text)
while (TRUE)
{
tmp= MEM_mallocN(text->curl->len+2, "textline_string");
- format= MEM_mallocN(text->curl->len+3, "Syntax_format");
text->curc = 0;
if(text->curc) memcpy(tmp, text->curl->line, text->curc);
@@ -2165,7 +2445,7 @@ void indent(Text *text)
if(len>0) memcpy(tmp+text->curc+1, text->curl->line+text->curc, len);
tmp[text->curl->len+1]=0;
- make_new_line(text->curl, tmp, format);
+ make_new_line(text->curl, tmp);
text->curc++;
@@ -2246,7 +2526,7 @@ void unindent(Text *text)
void comment(Text *text)
{
int len, num;
- char *tmp, *format;
+ char *tmp;
char add = '#';
if (!text) return;
@@ -2257,7 +2537,6 @@ void comment(Text *text)
while (TRUE)
{
tmp= MEM_mallocN(text->curl->len+2, "textline_string");
- format = MEM_mallocN(text->curl->len+3, "Syntax_format");
text->curc = 0;
if(text->curc) memcpy(tmp, text->curl->line, text->curc);
@@ -2267,7 +2546,7 @@ void comment(Text *text)
if(len>0) memcpy(tmp+text->curc+1, text->curl->line+text->curc, len);
tmp[text->curl->len+1]=0;
- make_new_line(text->curl, tmp, format);
+ make_new_line(text->curl, tmp);
text->curc++;
@@ -2398,3 +2677,148 @@ int setcurr_tab (Text *text)
return i;
}
+/*********************************/
+/* Text marker utility functions */
+/*********************************/
+
+static int color_match(TextMarker *a, TextMarker *b) {
+ return (a->color[0]==b->color[0] &&
+ a->color[1]==b->color[1] &&
+ a->color[2]==b->color[2] &&
+ a->color[3]==b->color[3]);
+}
+
+/* Creates and adds a marker to the list maintaining sorted order */
+void txt_add_marker(Text *text, TextLine *line, int start, int end, char color[4], int group, int flags) {
+ TextMarker *tmp, *marker;
+
+ marker= MEM_mallocN(sizeof(TextMarker), "text_marker");
+
+ marker->lineno= txt_get_span(text->lines.first, line);
+ marker->start= MIN2(start, end);
+ marker->end= MAX2(start, end);
+ marker->group= group;
+ marker->flags= flags;
+
+ marker->color[0]= color[0];
+ marker->color[1]= color[1];
+ marker->color[2]= color[2];
+ marker->color[3]= color[3];
+
+ for (tmp=text->markers.last; tmp; tmp=tmp->prev)
+ if (tmp->lineno < marker->lineno || (tmp->lineno==marker->lineno && tmp->start < marker->start))
+ break;
+
+ if (tmp) BLI_insertlinkafter(&text->markers, tmp, marker);
+ else BLI_addhead(&text->markers, marker);
+}
+
+/* Returns the first matching marker on the specified line between two points.
+ If the group or flags fields are non-zero the returned flag must be in the
+ specified group and have at least the specified flags set. */
+TextMarker *txt_find_marker_region(Text *text, TextLine *line, int start, int end, int group, int flags) {
+ TextMarker *marker, *next;
+ int lineno= txt_get_span(text->lines.first, line);
+
+ for (marker=text->markers.first; marker; marker=next) {
+ next= marker->next;
+
+ if (group && marker->group != group) continue;
+ else if ((marker->flags & flags) != flags) continue;
+ else if (marker->lineno < lineno) continue;
+ else if (marker->lineno > lineno) break;
+
+ if ((marker->start==marker->end && start<=marker->start && marker->start<=end) ||
+ (marker->start<end && marker->end>start))
+ return marker;
+ }
+ return NULL;
+}
+
+/* Clears all markers on the specified line between two points. If the group or
+ flags fields are non-zero the returned flag must be in the specified group
+ and have at least the specified flags set. */
+short txt_clear_marker_region(Text *text, TextLine *line, int start, int end, int group, int flags) {
+ TextMarker *marker, *next;
+ int lineno= txt_get_span(text->lines.first, line);
+ short cleared= 0;
+
+ for (marker=text->markers.first; marker; marker=next) {
+ next= marker->next;
+
+ if (group && marker->group != group) continue;
+ else if ((marker->flags & flags) != flags) continue;
+ else if (marker->lineno < lineno) continue;
+ else if (marker->lineno > lineno) break;
+
+ if ((marker->start==marker->end && start<=marker->start && marker->start<=end) ||
+ (marker->start<end && marker->end>start)) {
+ BLI_freelinkN(&text->markers, marker);
+ cleared= 1;
+ }
+ }
+ return cleared;
+}
+
+/* Clears all markers in the specified group (if given) with at least the
+ specified flags set. Useful for clearing temporary markers (group=0,
+ flags=TMARK_TEMP) */
+short txt_clear_markers(Text *text, int group, int flags) {
+ TextMarker *marker, *next;
+ short cleared= 0;
+
+ for (marker=text->markers.first; marker; marker=next) {
+ next= marker->next;
+
+ if ((!group || marker->group==group) &&
+ (marker->flags & flags) == flags) {
+ BLI_freelinkN(&text->markers, marker);
+ cleared= 1;
+ }
+ }
+ return cleared;
+}
+
+/* Finds the marker at the specified line and cursor position with at least the
+ specified flags set in the given group (if non-zero). */
+TextMarker *txt_find_marker(Text *text, TextLine *line, int curs, int group, int flags) {
+ TextMarker *marker;
+ int lineno= txt_get_span(text->lines.first, line);
+
+ for (marker=text->markers.first; marker; marker=marker->next) {
+ if (group && marker->group != group) continue;
+ else if ((marker->flags & flags) != flags) continue;
+ else if (marker->lineno < lineno) continue;
+ else if (marker->lineno > lineno) break;
+
+ if (marker->start <= curs && curs <= marker->end)
+ return marker;
+ }
+ return NULL;
+}
+
+/* Finds the previous marker in the same group. If no other is found, the same
+ marker will be returned */
+TextMarker *txt_prev_marker(Text *text, TextMarker *marker) {
+ TextMarker *tmp= marker;
+ while (tmp) {
+ if (tmp->prev) tmp= tmp->prev;
+ else tmp= text->markers.last;
+ if (tmp->group == marker->group)
+ return tmp;
+ }
+ return NULL; /* Only if marker==NULL */
+}
+
+/* Finds the next marker in the same group. If no other is found, the same
+ marker will be returned */
+TextMarker *txt_next_marker(Text *text, TextMarker *marker) {
+ TextMarker *tmp= marker;
+ while (tmp) {
+ if (tmp->next) tmp= tmp->next;
+ else tmp= text->markers.first;
+ if (tmp->group == marker->group)
+ return tmp;
+ }
+ return NULL; /* Only if marker==NULL */
+}
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index 936381c85cc..bb726887d32 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -53,6 +53,7 @@
#include "DNA_world_types.h"
#include "DNA_brush_types.h"
#include "DNA_node_types.h"
+#include "DNA_color_types.h"
#include "DNA_scene_types.h"
#include "IMB_imbuf_types.h"
@@ -390,6 +391,17 @@ int do_colorband(ColorBand *coba, float in, float out[4])
return 1; /* OK */
}
+void colorband_table_RGBA(ColorBand *coba, float **array, int *size)
+{
+ int a;
+
+ *size = CM_TABLE+1;
+ *array = MEM_callocN(sizeof(float)*(*size)*4, "ColorBand");
+
+ for(a=0; a<*size; a++)
+ do_colorband(coba, (float)a/(float)CM_TABLE, &(*array)[a*4]);
+}
+
/* ******************* TEX ************************ */
void free_texture(Tex *tex)