Patch D246: Texture Marks for freestyle strokes, written and contributed by Paolo Acampora.

Reviewers: brecht, kjym3, #freestyle

Reviewed By: brecht, kjym3

Differential Revision: https://developer.blender.org/D246
This commit is contained in:
Tamito Kajiyama 2014-05-03 18:51:53 +09:00
parent 6ec2d72eca
commit b7f085d9c1
44 changed files with 1337 additions and 191 deletions

@ -30,6 +30,7 @@ to be a collection of examples for shader definition in Python
from _freestyle import (
BackboneStretcherShader,
BezierCurveShader,
BlenderTextureShader,
CalligraphicShader,
ColorNoiseShader,
ColorVariationPatternShader,
@ -44,6 +45,7 @@ from _freestyle import (
SmoothingShader,
SpatialNoiseShader,
StrokeTextureShader,
StrokeTextureStepShader,
TextureAssignerShader,
ThicknessNoiseShader,
ThicknessVariationPatternShader,

@ -66,12 +66,14 @@ from freestyle.predicates import (
from freestyle.shaders import (
BackboneStretcherShader,
BezierCurveShader,
BlenderTextureShader,
ConstantColorShader,
GuidingLinesShader,
PolygonalizationShader,
SamplingShader,
SpatialNoiseShader,
StrokeShader,
StrokeTextureStepShader,
TipRemoverShader,
pyBluePrintCirclesShader,
pyBluePrintEllipsesShader,
@ -1368,6 +1370,14 @@ def process(layer_name, lineset_name):
shaders_list.append(Transform2DShader(
m.pivot, m.scale_x, m.scale_y, m.angle, m.pivot_u, m.pivot_x, m.pivot_y))
color = linestyle.color
if linestyle.use_texture:
has_tex = False
for slot in linestyle.texture_slots:
if slot is not None:
shaders_list.append(BlenderTextureShader(slot))
has_tex = True
if has_tex:
shaders_list.append(StrokeTextureStepShader(linestyle.texture_spacing))
if (not linestyle.use_chaining) or (linestyle.chaining == 'PLAIN' and linestyle.use_same_object):
thickness_position = linestyle.thickness_position
else:

@ -674,6 +674,19 @@ class RENDERLAYER_PT_freestyle_linestyle(RenderLayerFreestyleEditorButtonsPanel,
for modifier in linestyle.geometry_modifiers:
self.draw_geometry_modifier(context, modifier)
elif linestyle.panel == 'TEXTURE':
layout.separator()
row = layout.row()
row.prop(linestyle, "use_texture", text="Use Textures")
row.prop(linestyle, "texture_spacing", text="Spacing Along Stroke")
row = layout.row()
op = row.operator("wm.properties_context_change",
text="Go to Linestyle Textures Properties",
icon='TEXTURE')
op.context = 'TEXTURE'
elif linestyle.panel == 'MISC':
pass

@ -25,6 +25,7 @@ from bpy.types import (Brush,
Material,
Object,
ParticleSettings,
FreestyleLineStyle,
Texture,
World)
@ -94,6 +95,10 @@ def context_tex_datablock(context):
if idblock:
return idblock
idblock = context.line_style
if idblock:
return idblock
if context.particle_system:
idblock = context.particle_system.settings
@ -134,6 +139,7 @@ class TEXTURE_PT_context_texture(TextureButtonsPanel, Panel):
context.world or
context.lamp or
context.texture or
context.line_style or
context.particle_system or
isinstance(context.space_data.pin_id, ParticleSettings) or
context.texture_user) and
@ -952,11 +958,28 @@ class TEXTURE_PT_mapping(TextureSlotPanel, Panel):
split.label(text="Object:")
split.prop(tex, "object", text="")
elif tex.texture_coords == 'ALONG_STROKE':
split = layout.split(percentage=0.3)
split.label(text="Use Tips:")
split.prop(tex, "use_tips", text="")
if isinstance(idblock, Brush):
if context.sculpt_object or context.image_paint_object:
brush_texture_settings(layout, idblock, context.sculpt_object)
else:
if isinstance(idblock, Material):
if isinstance(idblock, FreestyleLineStyle):
split = layout.split(percentage=0.3)
split.label(text="Projection:")
split.prop(tex, "mapping", text="")
split = layout.split(percentage=0.3)
split.separator()
row = split.row()
row.prop(tex, "mapping_x", text="")
row.prop(tex, "mapping_y", text="")
row.prop(tex, "mapping_z", text="")
elif isinstance(idblock, Material):
split = layout.split(percentage=0.3)
split.label(text="Projection:")
split.prop(tex, "mapping", text="")
@ -1129,6 +1152,15 @@ class TEXTURE_PT_influence(TextureSlotPanel, Panel):
factor_but(col, "use_map_kink", "kink_factor", "Kink")
factor_but(col, "use_map_rough", "rough_factor", "Rough")
elif isinstance(idblock, FreestyleLineStyle):
split = layout.split()
col = split.column()
factor_but(col, "use_map_color_diffuse", "diffuse_color_factor", "Color")
col = split.column()
factor_but(col, "use_map_alpha", "alpha_factor", "Alpha")
layout.separator()
if not isinstance(idblock, ParticleSettings):

@ -234,6 +234,7 @@ int ctx_data_list_count(const bContext *C, int (*func)(const bContext *, ListBas
struct Main *CTX_data_main(const bContext *C);
struct Scene *CTX_data_scene(const bContext *C);
struct ToolSettings *CTX_data_tool_settings(const bContext *C);
struct FreestyleLineStyle *CTX_data_linestyle_from_scene(struct Scene *scene);
const char *CTX_data_mode_string(const bContext *C);
int CTX_data_mode_enum(const bContext *C);

@ -44,6 +44,7 @@
#include "DNA_scene_types.h"
#include "DNA_texture_types.h"
#include "DNA_world_types.h"
#include "DNA_linestyle_types.h"
#include "RNA_types.h"
@ -632,6 +633,7 @@ struct NodeTreeIterStore {
Tex *tex;
Lamp *lamp;
World *world;
FreestyleLineStyle *linestyle;
};
void BKE_node_tree_iter_init(struct NodeTreeIterStore *ntreeiter, struct Main *bmain);

@ -41,6 +41,7 @@ struct bNode;
struct Brush;
struct ColorBand;
struct EnvMap;
struct FreestyleLineStyle;
struct HaloRen;
struct Lamp;
struct LampRen;
@ -85,6 +86,7 @@ void BKE_texture_make_local(struct Tex *tex);
struct Tex *give_current_object_texture(struct Object *ob);
struct Tex *give_current_material_texture(struct Material *ma);
struct Tex *give_current_lamp_texture(struct Lamp *la);
struct Tex *give_current_linestyle_texture(struct FreestyleLineStyle *linestyle);
struct Tex *give_current_world_texture(struct World *world);
struct Tex *give_current_brush_texture(struct Brush *br);
struct Tex *give_current_particle_texture(struct ParticleSettings *part);
@ -98,6 +100,7 @@ void set_current_brush_texture(struct Brush *br, struct Tex *tex);
void set_current_world_texture(struct World *wo, struct Tex *tex);
void set_current_material_texture(struct Material *ma, struct Tex *tex);
void set_current_lamp_texture(struct Lamp *la, struct Tex *tex);
void set_current_linestyle_texture(struct FreestyleLineStyle *linestyle, struct Tex *tex);
void set_current_particle_texture(struct ParticleSettings *part, struct Tex *tex);
bool has_current_material_texture(struct Material *ma);

@ -36,6 +36,7 @@
#include "DNA_view3d_types.h"
#include "DNA_windowmanager_types.h"
#include "DNA_object_types.h"
#include "DNA_linestyle_types.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
@ -47,6 +48,7 @@
#include "BKE_context.h"
#include "BKE_main.h"
#include "BKE_screen.h"
#include "BKE_freestyle.h"
#include "RNA_access.h"
@ -1090,3 +1092,15 @@ int CTX_data_visible_pose_bones(const bContext *C, ListBase *list)
return ctx_data_collection_get(C, "visible_pose_bones", list);
}
FreestyleLineStyle *CTX_data_linestyle_from_scene(Scene *scene)
{
SceneRenderLayer *actsrl = BLI_findlink(&scene->r.layers, scene->r.actlay);
FreestyleConfig *config = &actsrl->freestyleConfig;
FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(config);
if (lineset) {
return lineset->linestyle;
}
return NULL;
}

@ -52,6 +52,7 @@
#include "DNA_key_types.h"
#include "DNA_lamp_types.h"
#include "DNA_lattice_types.h"
#include "DNA_linestyle_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
@ -1364,6 +1365,7 @@ void id_clear_lib_data(Main *bmain, ID *id)
case ID_LA: ntree = ((Lamp *)id)->nodetree; break;
case ID_WO: ntree = ((World *)id)->nodetree; break;
case ID_TE: ntree = ((Tex *)id)->nodetree; break;
case ID_LS: ntree = ((FreestyleLineStyle *)id)->nodetree; break;
}
if (ntree)
ntree->id.lib = NULL;

@ -39,6 +39,7 @@
#include "DNA_key_types.h"
#include "DNA_lamp_types.h"
#include "DNA_lattice_types.h"
#include "DNA_linestyle_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
@ -450,6 +451,19 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
}
break;
}
case ID_LS:
{
FreestyleLineStyle *linestyle = (FreestyleLineStyle *) id;
for (i = 0; i < MAX_MTEX; i++) {
if (linestyle->mtex[i]) {
library_foreach_mtex(&data, linestyle->mtex[i]);
}
}
CALLBACK_INVOKE(linestyle->nodetree, IDWALK_NOP);
break;
}
}
#undef CALLBACK_INVOKE_ID

@ -46,6 +46,7 @@
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_linestyle.h"
#include "BKE_node.h"
#include "BKE_texture.h"
#include "BKE_colortools.h"
#include "BKE_animsys.h"
@ -80,7 +81,7 @@ static void default_linestyle_settings(FreestyleLineStyle *linestyle)
linestyle->thickness = 3.0f;
linestyle->thickness_position = LS_THICKNESS_CENTER;
linestyle->thickness_ratio = 0.5f;
linestyle->flag = LS_SAME_OBJECT | LS_NO_SORTING;
linestyle->flag = LS_SAME_OBJECT | LS_NO_SORTING | LS_TEXTURE;
linestyle->chaining = LS_CHAINING_PLAIN;
linestyle->rounds = 3;
linestyle->min_angle = DEG2RADF(0.0f);
@ -90,6 +91,7 @@ static void default_linestyle_settings(FreestyleLineStyle *linestyle)
linestyle->split_length = 100;
linestyle->sort_key = LS_SORT_KEY_DISTANCE_FROM_CAMERA;
linestyle->integration_type = LS_INTEGRATION_MEAN;
linestyle->texstep = 1.0f;
BLI_listbase_clear(&linestyle->color_modifiers);
BLI_listbase_clear(&linestyle->alpha_modifiers);
@ -119,6 +121,19 @@ void BKE_free_linestyle(FreestyleLineStyle *linestyle)
{
LineStyleModifier *m;
MTex *mtex;
int a;
for (a = 0; a < MAX_MTEX; a++) {
mtex = linestyle->mtex[a];
if (mtex && mtex->tex) mtex->tex->id.us--;
if (mtex) MEM_freeN(mtex);
}
if (linestyle->nodetree) {
ntreeFreeTree(linestyle->nodetree);
MEM_freeN(linestyle->nodetree);
}
BKE_free_animdata(&linestyle->id);
while ((m = (LineStyleModifier *)linestyle->color_modifiers.first))
BKE_remove_linestyle_color_modifier(linestyle, m);
@ -134,10 +149,22 @@ FreestyleLineStyle *BKE_copy_linestyle(FreestyleLineStyle *linestyle)
{
FreestyleLineStyle *new_linestyle;
LineStyleModifier *m;
int a;
new_linestyle = BKE_new_linestyle(linestyle->id.name + 2, NULL);
BKE_free_linestyle(new_linestyle);
for (a = 0; a < MAX_MTEX; a++) {
if (linestyle->mtex[a]) {
new_linestyle->mtex[a] = MEM_mallocN(sizeof(MTex), "BKE_copy_linestyle");
memcpy(new_linestyle->mtex[a], linestyle->mtex[a], sizeof(MTex));
id_us_plus((ID *)new_linestyle->mtex[a]->tex);
}
}
if (linestyle->nodetree) {
linestyle->nodetree = ntreeCopyTree(linestyle->nodetree);
}
new_linestyle->r = linestyle->r;
new_linestyle->g = linestyle->g;
new_linestyle->b = linestyle->b;
@ -167,6 +194,7 @@ FreestyleLineStyle *BKE_copy_linestyle(FreestyleLineStyle *linestyle)
new_linestyle->dash3 = linestyle->dash3;
new_linestyle->gap3 = linestyle->gap3;
new_linestyle->panel = linestyle->panel;
new_linestyle->texstep = linestyle->texstep;
for (m = (LineStyleModifier *)linestyle->color_modifiers.first; m; m = m->next)
BKE_copy_linestyle_color_modifier(new_linestyle, m);
for (m = (LineStyleModifier *)linestyle->alpha_modifiers.first; m; m = m->next)

@ -44,6 +44,7 @@
#include "DNA_scene_types.h"
#include "DNA_texture_types.h"
#include "DNA_world_types.h"
#include "DNA_linestyle_types.h"
#include "BLI_string.h"
#include "BLI_math.h"
@ -1866,6 +1867,7 @@ bNodeTree *ntreeFromID(ID *id)
case ID_WO: return ((World *)id)->nodetree;
case ID_TE: return ((Tex *)id)->nodetree;
case ID_SCE: return ((Scene *)id)->nodetree;
case ID_LS: return ((FreestyleLineStyle *)id)->nodetree;
default: return NULL;
}
}
@ -3661,6 +3663,7 @@ void BKE_node_tree_iter_init(struct NodeTreeIterStore *ntreeiter, struct Main *b
ntreeiter->tex = bmain->tex.first;
ntreeiter->lamp = bmain->lamp.first;
ntreeiter->world = bmain->world.first;
ntreeiter->linestyle = bmain->linestyle.first;
}
bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter,
bNodeTree **r_nodetree, struct ID **r_id)
@ -3695,6 +3698,11 @@ bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter,
*r_id = (ID *)ntreeiter->world;
ntreeiter->world = ntreeiter->world->id.next;
}
else if (ntreeiter->linestyle) {
*r_nodetree = ntreeiter->linestyle->nodetree;
*r_id = (ID *)ntreeiter->linestyle;
ntreeiter->linestyle = ntreeiter->linestyle->id.next;
}
else {
return false;
}

@ -51,6 +51,7 @@
#include "DNA_node_types.h"
#include "DNA_color_types.h"
#include "DNA_particle_types.h"
#include "DNA_linestyle_types.h"
#include "IMB_imbuf.h"
@ -999,6 +1000,41 @@ void set_current_lamp_texture(Lamp *la, Tex *newtex)
}
}
Tex *give_current_linestyle_texture(FreestyleLineStyle *linestyle)
{
MTex *mtex = NULL;
Tex *tex = NULL;
if (linestyle) {
mtex = linestyle->mtex[(int)(linestyle->texact)];
if (mtex) tex = mtex->tex;
}
return tex;
}
void set_current_linestyle_texture(FreestyleLineStyle *linestyle, Tex *newtex)
{
int act = linestyle->texact;
if (linestyle->mtex[act] && linestyle->mtex[act]->tex)
id_us_min(&linestyle->mtex[act]->tex->id);
if (newtex) {
if (!linestyle->mtex[act]) {
linestyle->mtex[act] = add_mtex();
linestyle->mtex[act]->texco = TEXCO_STROKE;
}
linestyle->mtex[act]->tex = newtex;
id_us_plus(&newtex->id);
}
else if (linestyle->mtex[act]) {
MEM_freeN(linestyle->mtex[act]);
linestyle->mtex[act] = NULL;
}
}
bNode *give_current_material_texture_node(Material *ma)
{
if (ma && ma->use_nodes && ma->nodetree)
@ -1048,6 +1084,10 @@ bool give_active_mtex(ID *id, MTex ***mtex_ar, short *act)
*mtex_ar = ((Lamp *)id)->mtex;
if (act) *act = (((Lamp *)id)->texact);
break;
case ID_LS:
*mtex_ar = ((FreestyleLineStyle *)id)->mtex;
if (act) *act = (((FreestyleLineStyle *)id)->texact);
break;
case ID_PA:
*mtex_ar = ((ParticleSettings *)id)->mtex;
if (act) *act = (((ParticleSettings *)id)->texact);
@ -1076,6 +1116,9 @@ void set_active_mtex(ID *id, short act)
case ID_LA:
((Lamp *)id)->texact = act;
break;
case ID_LS:
((FreestyleLineStyle *)id)->texact = act;
break;
case ID_PA:
((ParticleSettings *)id)->texact = act;
break;

@ -2380,6 +2380,7 @@ static bNodeTree *nodetree_from_id(ID *id)
case ID_WO: return ((World *)id)->nodetree;
case ID_LA: return ((Lamp *)id)->nodetree;
case ID_TE: return ((Tex *)id)->nodetree;
case ID_LS: return ((FreestyleLineStyle *)id)->nodetree;
}
return NULL;
}
@ -6910,6 +6911,8 @@ static void lib_link_linestyle(FileData *fd, Main *main)
{
FreestyleLineStyle *linestyle;
LineStyleModifier *m;
MTex *mtex;
int a;
linestyle = main->linestyle.first;
while (linestyle) {
@ -6950,6 +6953,17 @@ static void lib_link_linestyle(FileData *fd, Main *main)
break;
}
}
for (a=0; a < MAX_MTEX; a++) {
mtex = linestyle->mtex[a];
if (mtex) {
mtex->tex = newlibadr_us(fd, linestyle->id.lib, mtex->tex);
mtex->object = newlibadr(fd, linestyle->id.lib, mtex->object);
}
}
if (linestyle->nodetree) {
lib_link_ntree(fd, &linestyle->id, linestyle->nodetree);
linestyle->nodetree->id.lib = linestyle->id.lib;
}
}
linestyle = linestyle->id.next;
}
@ -7059,6 +7073,7 @@ static void direct_link_linestyle_geometry_modifier(FileData *UNUSED(fd), LineSt
static void direct_link_linestyle(FileData *fd, FreestyleLineStyle *linestyle)
{
int a;
LineStyleModifier *modifier;
linestyle->adt= newdataadr(fd, linestyle->adt);
@ -7075,6 +7090,14 @@ static void direct_link_linestyle(FileData *fd, FreestyleLineStyle *linestyle)
link_list(fd, &linestyle->geometry_modifiers);
for (modifier = linestyle->geometry_modifiers.first; modifier; modifier = modifier->next)
direct_link_linestyle_geometry_modifier(fd, modifier);
for (a = 0; a < MAX_MTEX; a++) {
linestyle->mtex[a] = newdataadr(fd, linestyle->mtex[a]);
}
linestyle->nodetree = newdataadr(fd, linestyle->nodetree);
if (linestyle->nodetree) {
direct_link_id(fd, &linestyle->nodetree->id);
direct_link_nodetree(fd, linestyle->nodetree);
}
}
/* ************** GENERAL & MAIN ******************** */
@ -8562,8 +8585,18 @@ static void expand_mask(FileData *fd, Main *mainvar, Mask *mask)
static void expand_linestyle(FileData *fd, Main *mainvar, FreestyleLineStyle *linestyle)
{
int a;
LineStyleModifier *m;
for (a = 0; a < MAX_MTEX; a++) {
if (linestyle->mtex[a]) {
expand_doit(fd, mainvar, linestyle->mtex[a]->tex);
expand_doit(fd, mainvar, linestyle->mtex[a]->object);
}
}
if (linestyle->nodetree)
expand_nodetree(fd, mainvar, linestyle->nodetree);
if (linestyle->adt)
expand_animdata(fd, mainvar, linestyle->adt);
for (m = linestyle->color_modifiers.first; m; m = m->next) {

@ -60,9 +60,10 @@ void BLO_update_defaults_startup_blend(Main *main)
}
for (linestyle = main->linestyle.first; linestyle; linestyle = linestyle->id.next) {
linestyle->flag = LS_SAME_OBJECT | LS_NO_SORTING;
linestyle->flag = LS_SAME_OBJECT | LS_NO_SORTING | LS_TEXTURE;
linestyle->sort_key = LS_SORT_KEY_DISTANCE_FROM_CAMERA;
linestyle->integration_type = LS_INTEGRATION_MEAN;
linestyle->texstep = 1.0;
}
{

@ -3248,6 +3248,7 @@ static void write_linestyle_geometry_modifiers(WriteData *wd, ListBase *modifier
static void write_linestyles(WriteData *wd, ListBase *idbase)
{
FreestyleLineStyle *linestyle;
int a;
for (linestyle = idbase->first; linestyle; linestyle = linestyle->id.next) {
if (linestyle->id.us>0 || wd->current) {
@ -3260,6 +3261,13 @@ static void write_linestyles(WriteData *wd, ListBase *idbase)
write_linestyle_alpha_modifiers(wd, &linestyle->alpha_modifiers);
write_linestyle_thickness_modifiers(wd, &linestyle->thickness_modifiers);
write_linestyle_geometry_modifiers(wd, &linestyle->geometry_modifiers);
for (a=0; a<MAX_MTEX; a++) {
if (linestyle->mtex[a]) writestruct(wd, DATA, "MTex", 1, linestyle->mtex[a]);
}
if (linestyle->nodetree) {
writestruct(wd, DATA, "bNodeTree", 1, linestyle->nodetree);
write_nodetree(wd, linestyle->nodetree);
}
}
}
}

@ -34,6 +34,7 @@ bool ED_texture_context_check_world(const struct bContext *C);
bool ED_texture_context_check_material(const struct bContext *C);
bool ED_texture_context_check_lamp(const struct bContext *C);
bool ED_texture_context_check_particles(const struct bContext *C);
bool ED_texture_context_check_linestyle(const bContext *C);
bool ED_texture_context_check_others(const struct bContext *C);
#endif /* __ED_BUTTONS_H__ */

@ -54,6 +54,7 @@
#include "BKE_global.h"
#include "BKE_idcode.h"
#include "BKE_library.h"
#include "BKE_linestyle.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
@ -1302,8 +1303,8 @@ void uiTemplatePreview(uiLayout *layout, bContext *C, ID *id, int show_buttons,
char _preview_id[UI_MAX_NAME_STR];
if (id && !ELEM4(GS(id->name), ID_MA, ID_TE, ID_WO, ID_LA)) {
RNA_warning("Expected ID of type material, texture, lamp or world");
if (id && !ELEM5(GS(id->name), ID_MA, ID_TE, ID_WO, ID_LA, ID_LS)) {
RNA_warning("Expected ID of type material, texture, lamp, world or line style");
return;
}
@ -1318,6 +1319,8 @@ void uiTemplatePreview(uiLayout *layout, bContext *C, ID *id, int show_buttons,
pr_texture = &((World *)parent)->pr_texture;
else if (parent && (GS(parent->name) == ID_LA))
pr_texture = &((Lamp *)parent)->pr_texture;
else if (parent && (GS(parent->name) == ID_LS))
pr_texture = &((FreestyleLineStyle *)parent)->pr_texture;
if (pr_texture) {
if (*pr_texture == TEX_PR_OTHER)
@ -1398,6 +1401,10 @@ void uiTemplatePreview(uiLayout *layout, bContext *C, ID *id, int show_buttons,
uiDefButS(block, ROW, B_MATPRV, IFACE_("World"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
}
else if (GS(parent->name) == ID_LS) {
uiDefButS(block, ROW, B_MATPRV, IFACE_("Line Style"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
}
uiDefButS(block, ROW, B_MATPRV, IFACE_("Both"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
pr_texture, 10, TEX_PR_BOTH, 0, 0, "");

@ -1575,6 +1575,9 @@ static void copy_mtex_copybuf(ID *id)
case ID_PA:
mtex = &(((ParticleSettings *)id)->mtex[(int)((ParticleSettings *)id)->texact]);
break;
case ID_LS:
mtex = &(((FreestyleLineStyle *)id)->mtex[(int)((FreestyleLineStyle *)id)->texact]);
break;
}
if (mtex && *mtex) {
@ -1608,6 +1611,9 @@ static void paste_mtex_copybuf(ID *id)
case ID_PA:
mtex = &(((ParticleSettings *)id)->mtex[(int)((ParticleSettings *)id)->texact]);
break;
case ID_LS:
mtex = &(((FreestyleLineStyle *)id)->mtex[(int)((FreestyleLineStyle *)id)->texact]);
break;
default:
BLI_assert("invalid id type");
return;
@ -1674,6 +1680,7 @@ static int paste_mtex_exec(bContext *C, wmOperator *UNUSED(op))
Lamp *la = CTX_data_pointer_get_type(C, "lamp", &RNA_Lamp).data;
World *wo = CTX_data_pointer_get_type(C, "world", &RNA_World).data;
ParticleSystem *psys = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data;
FreestyleLineStyle *linestyle = CTX_data_pointer_get_type(C, "line_style", &RNA_FreestyleLineStyle).data;
if (ma)
id = &ma->id;
@ -1683,6 +1690,8 @@ static int paste_mtex_exec(bContext *C, wmOperator *UNUSED(op))
id = &wo->id;
else if (psys)
id = &psys->part->id;
else if (linestyle)
id = &linestyle->id;
if (id == NULL)
return OPERATOR_CANCELLED;

@ -45,6 +45,7 @@
#include "DNA_scene_types.h"
#include "DNA_world_types.h"
#include "DNA_brush_types.h"
#include "DNA_linestyle_types.h"
#include "BKE_context.h"
#include "BKE_action.h"
@ -139,6 +140,30 @@ static int buttons_context_path_world(ButsContextPath *path)
return 0;
}
static int buttons_context_path_linestyle(ButsContextPath *path)
{
Scene *scene;
FreestyleLineStyle *linestyle;
PointerRNA *ptr = &path->ptr[path->len - 1];
/* if we already have a (pinned) linestyle, we're done */
if (RNA_struct_is_a(ptr->type, &RNA_FreestyleLineStyle)) {
return 1;
}
/* if we have a scene, use the lineset's linestyle */
else if (buttons_context_path_scene(path)) {
scene = path->ptr[path->len - 1].data;
linestyle = CTX_data_linestyle_from_scene(scene);
if (linestyle) {
RNA_id_pointer_create(&linestyle->id, &path->ptr[path->len]);
path->len++;
return 1;
}
}
/* no path to a linestyle possible */
return 0;
}
static int buttons_context_path_object(ButsContextPath *path)
{
@ -395,6 +420,8 @@ static int buttons_context_path_texture(ButsContextPath *path, ButsContextTextur
buttons_context_path_particle(path);
else if (GS(id->name) == ID_OB)
buttons_context_path_object(path);
else if (GS(id->name) == ID_LS)
buttons_context_path_linestyle(path);
}
if (ct->texture) {
@ -410,6 +437,7 @@ static int buttons_context_path_texture(ButsContextPath *path, ButsContextTextur
Lamp *la;
World *wo;
ParticleSystem *psys;
FreestyleLineStyle *ls;
Tex *tex;
PointerRNA *ptr = &path->ptr[path->len - 1];
@ -470,6 +498,18 @@ static int buttons_context_path_texture(ButsContextPath *path, ButsContextTextur
if (la) {
tex = give_current_lamp_texture(la);
RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
path->len++;
return 1;
}
}
/* try linestyle */
else if ((path->tex_ctx == SB_TEXC_LINESTYLE) && buttons_context_path_linestyle(path)) {
ls = path->ptr[path->len - 1].data;
if (ls) {
tex = give_current_linestyle_texture(ls);
RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
path->len++;
return 1;
@ -481,6 +521,22 @@ static int buttons_context_path_texture(ButsContextPath *path, ButsContextTextur
return 0;
}
static bool buttons_context_linestyle_pinnable(const bContext *C)
{
Scene *scene = CTX_data_scene(C);
SpaceButs *sbuts;
/* if Freestyle is disabled in the scene */
if ((scene->r.mode & R_EDGE_FRS) == 0) {
return false;
}
/* if the scene has already been pinned */
sbuts = CTX_wm_space_buts(C);
if (sbuts->pinid && sbuts->pinid == &scene->id) {
return false;
}
return true;
}
static int buttons_context_path(const bContext *C, ButsContextPath *path, int mainb, int flag)
{
@ -512,7 +568,17 @@ static int buttons_context_path(const bContext *C, ButsContextPath *path, int ma
switch (mainb) {
case BCONTEXT_SCENE:
case BCONTEXT_RENDER:
found = buttons_context_path_scene(path);
break;
case BCONTEXT_RENDER_LAYER:
#ifdef WITH_FREESTYLE
if (buttons_context_linestyle_pinnable(C)) {
found = buttons_context_path_linestyle(path);
if (found) {
break;
}
}
#endif
found = buttons_context_path_scene(path);
break;
case BCONTEXT_WORLD:
@ -662,7 +728,8 @@ const char *buttons_context_dir[] = {
"meta_ball", "lamp", "speaker", "camera", "material", "material_slot",
"texture", "texture_user", "texture_user_property", "bone", "edit_bone",
"pose_bone", "particle_system", "particle_system_editable", "particle_settings",
"cloth", "soft_body", "fluid", "smoke", "collision", "brush", "dynamic_paint", NULL
"cloth", "soft_body", "fluid", "smoke", "collision", "brush", "dynamic_paint",
"line_style", NULL
};
int buttons_context(const bContext *C, const char *member, bContextDataResult *result)
@ -860,6 +927,12 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
if (wo)
CTX_data_pointer_set(result, &wo->id, &RNA_WorldTextureSlot, wo->mtex[(int)wo->texact]);
}
else if ((ptr = get_pointer_type(path, &RNA_FreestyleLineStyle))) {
FreestyleLineStyle *ls = ptr->data;
if (ls)
CTX_data_pointer_set(result, &ls->id, &RNA_LineStyleTextureSlot, ls->mtex[(int)ls->texact]);
}
return 1;
}
@ -972,6 +1045,10 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
return 1;
}
}
else if (CTX_data_equals(member, "line_style")) {
set_pointer_type(path, result, &RNA_FreestyleLineStyle);
return 1;
}
else {
return 0; /* not found */
}

@ -51,6 +51,8 @@
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DNA_world_types.h"
#include "DNA_linestyle_types.h"
#include "BKE_context.h"
#include "BKE_material.h"
@ -99,6 +101,13 @@ bool ED_texture_context_check_particles(const bContext *C)
return (ob && ob->particlesystem.first);
}
bool ED_texture_context_check_linestyle(const bContext *C)
{
Scene *scene = CTX_data_scene(C);
FreestyleLineStyle *ls = CTX_data_linestyle_from_scene(scene);
return (scene && (scene->r.mode & R_EDGE_FRS) && ls && (ls->flag & LS_TEXTURE));
}
static void texture_context_check_modifier_foreach(void *userData, Object *UNUSED(ob), ModifierData *UNUSED(md),
const char *UNUSED(propname))
{
@ -148,6 +157,7 @@ static void set_texture_context(const bContext *C, SpaceButs *sbuts)
bool valid_material = ED_texture_context_check_material(C);
bool valid_lamp = ED_texture_context_check_lamp(C);
bool valid_particles = ED_texture_context_check_particles(C);
bool valid_linestyle = ED_texture_context_check_linestyle(C);
bool valid_others = ED_texture_context_check_others(C);
/* this is similar to direct user action, no need to keep "better" ctxt in _prev */
@ -163,6 +173,9 @@ static void set_texture_context(const bContext *C, SpaceButs *sbuts)
else if ((sbuts->mainb == BCONTEXT_PARTICLE) && valid_particles) {
sbuts->texture_context = sbuts->texture_context_prev = SB_TEXC_PARTICLES;
}
else if ((sbuts->mainb == BCONTEXT_RENDER_LAYER) && valid_linestyle) {
sbuts->texture_context = sbuts->texture_context_prev = SB_TEXC_LINESTYLE;
}
else if ((ELEM(sbuts->mainb, BCONTEXT_MODIFIER, BCONTEXT_PHYSICS)) && valid_others) {
sbuts->texture_context = sbuts->texture_context_prev = SB_TEXC_OTHER;
}
@ -172,6 +185,7 @@ static void set_texture_context(const bContext *C, SpaceButs *sbuts)
((sbuts->texture_context_prev == SB_TEXC_MATERIAL) && valid_material) ||
((sbuts->texture_context_prev == SB_TEXC_LAMP) && valid_lamp) ||
((sbuts->texture_context_prev == SB_TEXC_PARTICLES) && valid_particles) ||
((sbuts->texture_context_prev == SB_TEXC_LINESTYLE) && valid_linestyle) ||
((sbuts->texture_context_prev == SB_TEXC_OTHER) && valid_others)))
{
sbuts->texture_context = sbuts->texture_context_prev;
@ -181,6 +195,7 @@ static void set_texture_context(const bContext *C, SpaceButs *sbuts)
((sbuts->texture_context == SB_TEXC_MATERIAL) && !valid_material) ||
((sbuts->texture_context == SB_TEXC_LAMP) && !valid_lamp) ||
((sbuts->texture_context == SB_TEXC_PARTICLES) && !valid_particles) ||
((sbuts->texture_context == SB_TEXC_LINESTYLE) && !valid_linestyle) ||
((sbuts->texture_context == SB_TEXC_OTHER) && !valid_others))
{
/* this is default fallback, do keep "better" ctxt in _prev */
@ -194,6 +209,9 @@ static void set_texture_context(const bContext *C, SpaceButs *sbuts)
else if (valid_particles) {
sbuts->texture_context = SB_TEXC_PARTICLES;
}
else if (valid_linestyle) {
sbuts->texture_context = SB_TEXC_LINESTYLE;
}
else if (valid_world) {
sbuts->texture_context = SB_TEXC_WORLD;
}
@ -284,6 +302,7 @@ static void buttons_texture_users_from_context(ListBase *users, const bContext *
Material *ma = NULL;
Lamp *la = NULL;
World *wrld = NULL;
FreestyleLineStyle *linestyle = NULL;
Brush *brush = NULL;
ID *pinid = sbuts->pinid;
bool limited_mode = (sbuts->flag & SB_TEX_USER_LIMITED) != 0;
@ -302,6 +321,8 @@ static void buttons_texture_users_from_context(ListBase *users, const bContext *
ma = (Material *)pinid;
else if (GS(pinid->name) == ID_BR)
brush = (Brush *)pinid;
else if (GS(pinid->name) == ID_LS)
linestyle = (FreestyleLineStyle *)pinid;
}
if (!scene)
@ -311,6 +332,7 @@ static void buttons_texture_users_from_context(ListBase *users, const bContext *
ob = (scene->basact) ? scene->basact->object : NULL;
wrld = scene->world;
brush = BKE_paint_brush(BKE_paint_get_active_from_context(C));
linestyle = CTX_data_linestyle_from_scene(scene);
}
if (ob && ob->type == OB_LAMP && !la)
@ -327,6 +349,8 @@ static void buttons_texture_users_from_context(ListBase *users, const bContext *
buttons_texture_users_find_nodetree(users, &la->id, la->nodetree, "Lamp");
if (wrld && !limited_mode)
buttons_texture_users_find_nodetree(users, &wrld->id, wrld->nodetree, "World");
if (linestyle && !limited_mode)
buttons_texture_users_find_nodetree(users, &linestyle->id, linestyle->nodetree, "LineStyle");
if (ob) {
ParticleSystem *psys = psys_get_current(ob);

@ -36,6 +36,7 @@
#include "DNA_space_types.h"
#include "DNA_texture_types.h"
#include "DNA_world_types.h"
#include "DNA_linestyle_types.h"
#include "BLI_math.h"
#include "BLI_blenlib.h"
@ -106,6 +107,8 @@ static bNodeTree *node_tree_from_ID(ID *id)
return ((Scene *)id)->nodetree;
case ID_TE:
return ((Tex *)id)->nodetree;
case ID_LS:
return ((FreestyleLineStyle *)id)->nodetree;
}
}

@ -185,6 +185,8 @@ set(SRC
intern/python/StrokeShader/BPy_BackboneStretcherShader.h
intern/python/StrokeShader/BPy_BezierCurveShader.cpp
intern/python/StrokeShader/BPy_BezierCurveShader.h
intern/python/StrokeShader/BPy_BlenderTextureShader.cpp
intern/python/StrokeShader/BPy_BlenderTextureShader.h
intern/python/StrokeShader/BPy_CalligraphicShader.cpp
intern/python/StrokeShader/BPy_CalligraphicShader.h
intern/python/StrokeShader/BPy_ColorNoiseShader.cpp
@ -213,6 +215,8 @@ set(SRC
intern/python/StrokeShader/BPy_SpatialNoiseShader.h
intern/python/StrokeShader/BPy_StrokeTextureShader.cpp
intern/python/StrokeShader/BPy_StrokeTextureShader.h
intern/python/StrokeShader/BPy_StrokeTextureStepShader.cpp
intern/python/StrokeShader/BPy_StrokeTextureStepShader.h
intern/python/StrokeShader/BPy_TextureAssignerShader.cpp
intern/python/StrokeShader/BPy_TextureAssignerShader.h
intern/python/StrokeShader/BPy_ThicknessNoiseShader.cpp

@ -34,7 +34,6 @@ extern "C" {
#include "MEM_guardedalloc.h"
#include "DNA_camera_types.h"
#include "DNA_customdata_types.h"
#include "DNA_listBase.h"
#include "DNA_meshdata_types.h"
#include "DNA_mesh_types.h"
@ -137,19 +136,31 @@ BlenderStrokeRenderer::BlenderStrokeRenderer(Render *re, int render_count) : Str
freestyle_scene->camera = object_camera;
// Material
material = BKE_material_add(freestyle_bmain, "stroke_material");
material->mode |= MA_VERTEXCOLP;
material->mode |= MA_TRANSP;
material->mode |= MA_SHLESS;
material->vcol_alpha = 1;
// Reset serial mesh ID (used for BlenderStrokeRenderer::NewMesh())
_mesh_id = 0xffffffff;
}
BlenderStrokeRenderer::~BlenderStrokeRenderer()
{
// release materials
Link *lnk = (Link *)freestyle_bmain->mat.first;
while (lnk)
{
Material *ma = (Material*)lnk;
// We want to retain the linestyle mtexs, so let's detach them first
for (int a = 0; a < MAX_MTEX; a++) {
if (ma->mtex[a]) {
ma->mtex[a] = NULL;
}
else {
break; // Textures are ordered, no empty slots between two textures
}
}
lnk = lnk->next;
BKE_libblock_free(freestyle_bmain, ma);
}
if (0 != _textureManager) {
delete _textureManager;
_textureManager = NULL;
@ -185,9 +196,6 @@ BlenderStrokeRenderer::~BlenderStrokeRenderer()
}
}
BLI_freelistN(&freestyle_scene->base);
// release material
BKE_libblock_free(freestyle_bmain, material);
}
float BlenderStrokeRenderer::get_stroke_vertex_z(void) const
@ -210,6 +218,55 @@ unsigned int BlenderStrokeRenderer::get_stroke_mesh_id(void) const
void BlenderStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const
{
bool has_mat = false;
int a = 0;
// Look for a good existing material
for (Link *lnk = (Link *)freestyle_bmain->mat.first; lnk; lnk = lnk->next) {
Material *ma = (Material*) lnk;
bool texs_are_good = true;
// as soon as textures differ it's not the right one
for (int a = 0; a < MAX_MTEX; a++) {
if (ma->mtex[a] != iStrokeRep->getMTex(a)) {
texs_are_good = false;
break;
}
}
if (texs_are_good) {
iStrokeRep->setMaterial(ma);
has_mat = true;
break; // if textures are good, no need to search anymore
}
}
// If still no material, create one
if (!has_mat) {
Material *ma = BKE_material_add(freestyle_bmain, "stroke_material");
ma->mode |= MA_VERTEXCOLP;
ma->mode |= MA_TRANSP;
ma->mode |= MA_SHLESS;
ma->vcol_alpha = 1;
// Textures
//for (int a = 0; a < MAX_MTEX; a++) {
while (iStrokeRep->getMTex(a)) {
ma->mtex[a] = (MTex *) iStrokeRep->getMTex(a);
// We'll generate both with tips and without tips
// coordinates, on two different UV layers.
if (ma->mtex[a]->texflag & MTEX_TIPS) {
BLI_strncpy(ma->mtex[a]->uvname, "along_stroke_tips", sizeof(ma->mtex[a]->uvname));
}
else {
BLI_strncpy(ma->mtex[a]->uvname, "along_stroke", sizeof(ma->mtex[a]->uvname));
}
a++;
}
iStrokeRep->setMaterial(ma);
}
RenderStrokeRepBasic(iStrokeRep);
}
@ -277,7 +334,7 @@ void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
#endif
Mesh *mesh = (Mesh *)object_mesh->data;
mesh->mat = (Material **)MEM_mallocN(1 * sizeof(Material *), "MaterialList");
mesh->mat[0] = material;
mesh->mat[0] = iStrokeRep->getMaterial();
mesh->totcol = 1;
test_object_materials(freestyle_bmain, (ID *)mesh);
@ -309,6 +366,7 @@ void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
MPoly *polys = mesh->mpoly;
MLoop *loops = mesh->mloop;
MLoopCol *colors = mesh->mloopcol;
MLoopUV *loopsuv[2];
v[0] = strip_vertices.begin();
v[1] = v[0] + 1;
@ -317,6 +375,24 @@ void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
vertex_index = edge_index = loop_index = 0;
visible = false;
// First UV layer
CustomData_add_layer_named(&mesh->pdata, CD_MTEXPOLY, CD_CALLOC, NULL, mesh->totpoly, "along_stroke");
CustomData_add_layer_named(&mesh->ldata, CD_MLOOPUV, CD_CALLOC, NULL, mesh->totloop, "along_stroke");
CustomData_set_layer_active(&mesh->pdata, CD_MTEXPOLY, 0);
CustomData_set_layer_active(&mesh->ldata, CD_MLOOPUV, 0);
BKE_mesh_update_customdata_pointers(mesh, true);
loopsuv[0] = mesh->mloopuv;
// Second UV layer
CustomData_add_layer_named(&mesh->pdata, CD_MTEXPOLY, CD_CALLOC, NULL, mesh->totpoly, "along_stroke_tips");
CustomData_add_layer_named(&mesh->ldata, CD_MLOOPUV, CD_CALLOC, NULL, mesh->totloop, "along_stroke_tips");
CustomData_set_layer_active(&mesh->pdata, CD_MTEXPOLY, 1);
CustomData_set_layer_active(&mesh->ldata, CD_MLOOPUV, 1);
BKE_mesh_update_customdata_pointers(mesh, true);
loopsuv[1] = mesh->mloopuv;
// Note: Mesh generation in the following loop assumes stroke strips
// to be triangle strips.
for (n = 2; n < strip_vertex_count; n++, v[0]++, v[1]++, v[2]++) {
@ -394,18 +470,10 @@ void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
polys->totloop = 3;
++polys;
// Even and odd loops connect triangles vertices differently
bool is_odd = n % 2;
// loops
if (n % 2 == 0) {
loops[0].v = vertex_index - 1;
loops[0].e = edge_index - 1;
loops[1].v = vertex_index - 2;
loops[1].e = edge_index - 3;
loops[2].v = vertex_index - 3;
loops[2].e = edge_index - 2;
}
else {
if (is_odd) {
loops[0].v = vertex_index - 1;
loops[0].e = edge_index - 2;
@ -415,27 +483,54 @@ void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
loops[2].v = vertex_index - 2;
loops[2].e = edge_index - 1;
}
else {
loops[0].v = vertex_index - 1;
loops[0].e = edge_index - 1;
loops[1].v = vertex_index - 2;
loops[1].e = edge_index - 3;
loops[2].v = vertex_index - 3;
loops[2].e = edge_index - 2;
}
loops += 3;
loop_index += 3;
// colors
if (n % 2 == 0) {
colors[0].r = (short)(255.0f * svRep[2]->color()[0]);
colors[0].g = (short)(255.0f * svRep[2]->color()[1]);
colors[0].b = (short)(255.0f * svRep[2]->color()[2]);
colors[0].a = (short)(255.0f * svRep[2]->alpha());
// UV
if (iStrokeRep->getMTex(0)) {
// First UV layer (loopsuv[0]) has no tips (texCoord(0)).
// Second UV layer (loopsuv[1]) has tips: (texCoord(1)).
for (int L = 0; L < 2; L++) {
if (is_odd) {
loopsuv[L][0].uv[0] = svRep[2]->texCoord(L).x();
loopsuv[L][0].uv[1] = svRep[2]->texCoord(L).y();
colors[1].r = (short)(255.0f * svRep[1]->color()[0]);
colors[1].g = (short)(255.0f * svRep[1]->color()[1]);
colors[1].b = (short)(255.0f * svRep[1]->color()[2]);
colors[1].a = (short)(255.0f * svRep[1]->alpha());
loopsuv[L][1].uv[0] = svRep[0]->texCoord(L).x();
loopsuv[L][1].uv[1] = svRep[0]->texCoord(L).y();
colors[2].r = (short)(255.0f * svRep[0]->color()[0]);
colors[2].g = (short)(255.0f * svRep[0]->color()[1]);
colors[2].b = (short)(255.0f * svRep[0]->color()[2]);
colors[2].a = (short)(255.0f * svRep[0]->alpha());
loopsuv[L][2].uv[0] = svRep[1]->texCoord(L).x();
loopsuv[L][2].uv[1] = svRep[1]->texCoord(L).y();
}
else {
loopsuv[L][0].uv[0] = svRep[2]->texCoord(L).x();
loopsuv[L][0].uv[1] = svRep[2]->texCoord(L).y();
loopsuv[L][1].uv[0] = svRep[1]->texCoord(L).x();
loopsuv[L][1].uv[1] = svRep[1]->texCoord(L).y();
loopsuv[L][2].uv[0] = svRep[0]->texCoord(L).x();
loopsuv[L][2].uv[1] = svRep[0]->texCoord(L).y();
}
/* freestyle tex-origin is upside-down */
for (int i = 0; i < 3; i++) {
loopsuv[L][i].uv[1] *= -1;
}
loopsuv[L] += 3;
}
}
// colors
if (is_odd) {
colors[0].r = (short)(255.0f * svRep[2]->color()[0]);
colors[0].g = (short)(255.0f * svRep[2]->color()[1]);
colors[0].b = (short)(255.0f * svRep[2]->color()[2]);
@ -451,6 +546,22 @@ void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
colors[2].b = (short)(255.0f * svRep[1]->color()[2]);
colors[2].a = (short)(255.0f * svRep[1]->alpha());
}
else {
colors[0].r = (short)(255.0f * svRep[2]->color()[0]);
colors[0].g = (short)(255.0f * svRep[2]->color()[1]);
colors[0].b = (short)(255.0f * svRep[2]->color()[2]);
colors[0].a = (short)(255.0f * svRep[2]->alpha());
colors[1].r = (short)(255.0f * svRep[1]->color()[0]);
colors[1].g = (short)(255.0f * svRep[1]->color()[1]);
colors[1].b = (short)(255.0f * svRep[1]->color()[2]);
colors[1].a = (short)(255.0f * svRep[1]->alpha());
colors[2].r = (short)(255.0f * svRep[0]->color()[0]);
colors[2].g = (short)(255.0f * svRep[0]->color()[1]);
colors[2].b = (short)(255.0f * svRep[0]->color()[2]);
colors[2].a = (short)(255.0f * svRep[0]->alpha());
}
colors += 3;
}
} // loop over strip vertices

@ -57,7 +57,6 @@ protected:
Main *freestyle_bmain;
Scene *old_scene;
Scene *freestyle_scene;
Material *material;
float _width, _height;
float _z, _z_delta;
unsigned int _mesh_id;

@ -301,6 +301,7 @@ static char module_docstring[] =
"\n"
" - :class:`BackboneStretcherShader`\n"
" - :class:`BezierCurveShader`\n"
" - :class:`BlenderTextureShader`\n"
" - :class:`CalligraphicShader`\n"
" - :class:`ColorNoiseShader`\n"
" - :class:`ColorVariationPatternShader`\n"
@ -315,6 +316,7 @@ static char module_docstring[] =
" - :class:`SmoothingShader`\n"
" - :class:`SpatialNoiseShader`\n"
" - :class:`StrokeTextureShader`\n"
" - :class:`StrokeTextureStepShader`\n"
" - :class:`TextureAssignerShader`\n"
" - :class:`ThicknessNoiseShader`\n"
" - :class:`ThicknessVariationPatternShader`\n"

@ -29,6 +29,7 @@
#include "StrokeShader/BPy_BackboneStretcherShader.h"
#include "StrokeShader/BPy_BezierCurveShader.h"
#include "StrokeShader/BPy_BlenderTextureShader.h"
#include "StrokeShader/BPy_CalligraphicShader.h"
#include "StrokeShader/BPy_ColorNoiseShader.h"
#include "StrokeShader/BPy_ColorVariationPatternShader.h"
@ -45,6 +46,7 @@
#include "StrokeShader/BPy_SpatialNoiseShader.h"
#include "StrokeShader/BPy_streamShader.h"
#include "StrokeShader/BPy_StrokeTextureShader.h"
#include "StrokeShader/BPy_StrokeTextureStepShader.h"
#include "StrokeShader/BPy_TextureAssignerShader.h"
#include "StrokeShader/BPy_ThicknessNoiseShader.h"
#include "StrokeShader/BPy_ThicknessVariationPatternShader.h"
@ -77,6 +79,11 @@ int StrokeShader_Init(PyObject *module)
Py_INCREF(&BezierCurveShader_Type);
PyModule_AddObject(module, "BezierCurveShader", (PyObject *)&BezierCurveShader_Type);
if (PyType_Ready(&BlenderTextureShader_Type) < 0)
return -1;
Py_INCREF(&BlenderTextureShader_Type);
PyModule_AddObject(module, "BlenderTextureShader", (PyObject *)&BlenderTextureShader_Type);
if (PyType_Ready(&CalligraphicShader_Type) < 0)
return -1;
Py_INCREF(&CalligraphicShader_Type);
@ -158,6 +165,11 @@ int StrokeShader_Init(PyObject *module)
Py_INCREF(&StrokeTextureShader_Type);
PyModule_AddObject(module, "StrokeTextureShader", (PyObject *)&StrokeTextureShader_Type);
if (PyType_Ready(&StrokeTextureStepShader_Type) < 0)
return -1;
Py_INCREF(&StrokeTextureStepShader_Type);
PyModule_AddObject(module, "StrokeTextureStepShader", (PyObject *)&StrokeTextureStepShader_Type);
if (PyType_Ready(&TextureAssignerShader_Type) < 0)
return -1;
Py_INCREF(&TextureAssignerShader_Type);

@ -0,0 +1,125 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_BlenderTextureShader.cpp
* \ingroup freestyle
*/
#include "BPy_BlenderTextureShader.h"
#include "../../stroke/BasicStrokeShaders.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "../../../../python/generic/py_capi_utils.h"
///////////////////////////////////////////////////////////////////////////////////////////
//------------------------INSTANCE METHODS ----------------------------------
static char BlenderTextureShader___doc__[] =
"Class hierarchy: :class:`StrokeShader` > :class:`BlenderTextureShader`\n"
"\n"
"[Texture shader]\n"
"\n"
".. method:: __init__(LineStyleTextureSlot)\n"
"\n"
" Builds a BlenderTextureShader object.\n"
"\n"
" :arg mtex: texture slot to add to stroke shading.\n"
" :type mtex: LineStyleTextureSlot\n"
"\n"
".. method:: shade(stroke)\n"
"\n"
" Assigns a blender texture slot to the stroke shading\n"
" in order to simulate marks.\n"
"\n"
" :arg stroke: A Stroke object.\n"
" :type stroke: :class:`Stroke`\n";
static int BlenderTextureShader___init__(BPy_BlenderTextureShader *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"LineStyleTextureSlot", NULL};
PyObject *py_mtex;
MTex *_mtex;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", (char **)kwlist, &py_mtex))
return -1;
_mtex = (MTex*)PyC_RNA_AsPointer(py_mtex, "LineStyleTextureSlot");
if (_mtex) {
self->py_ss.ss = new StrokeShaders::BlenderTextureShader(_mtex);
}
return 0;
}
/*-----------------------BPy_BlenderTextureShader type definition ------------------------------*/
PyTypeObject BlenderTextureShader_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"BlenderTextureShader", /* tp_name */
sizeof(BPy_BlenderTextureShader), /* tp_basicsize */
0, /* tp_itemsize */
0, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_reserved */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
BlenderTextureShader___doc__, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
&StrokeShader_Type, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)BlenderTextureShader___init__, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
};
///////////////////////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
}
#endif

@ -0,0 +1,57 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_BlenderTextureShader.h
* \ingroup freestyle
*/
#ifndef __FREESTYLE_PYTHON_BLENDERTEXTURESHADER_H__
#define __FREESTYLE_PYTHON_BLENDERTEXTURESHADER_H__
#include "../BPy_StrokeShader.h"
#ifdef __cplusplus
extern "C" {
#endif
struct MTex;
///////////////////////////////////////////////////////////////////////////////////////////
#include <Python.h>
extern PyTypeObject BlenderTextureShader_Type;
#define BPy_BlenderTextureShader_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&BlenderTextureShader_Type))
/*---------------------------Python BPy_BlenderTextureShader structure definition-----------*/
typedef struct {
BPy_StrokeShader py_ss;
} BPy_BlenderTextureShader;
///////////////////////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
}
#endif
#endif /* __FREESTYLE_PYTHON_BLENDERTEXTURESHADER_H__ */

@ -0,0 +1,114 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureStepShader.cpp
* \ingroup freestyle
*/
#include "BPy_StrokeTextureStepShader.h"
#include "../../stroke/BasicStrokeShaders.h"
#ifdef __cplusplus
extern "C" {
#endif
///////////////////////////////////////////////////////////////////////////////////////////
//------------------------INSTANCE METHODS ----------------------------------
static char StrokeTextureStepShader___doc__[] =
"Class hierarchy: :class:`StrokeShader` > :class:`StrokeTextureStepShader`\n"
"\n"
"[Texture shader]\n"
"\n"
".. method:: __init__(step)\n"
"\n"
" Builds a StrokeTextureStepShader object.\n"
"\n"
" :arg step: The spacing along the stroke.\n"
" :type step: float\n"
"\n"
".. method:: shade(stroke)\n"
"\n"
" Assigns a spacing factor to the texture coordinates of the Stroke.\n"
"\n"
" :arg stroke: A Stroke object.\n"
" :type stroke: :class:`Stroke`\n";
static int StrokeTextureStepShader___init__(BPy_StrokeTextureStepShader *self, PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"step", NULL};
float step = 0.1;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "f", (char **)kwlist, &step))
return -1;
self->py_ss.ss = new StrokeShaders::StrokeTextureStepShader(step);
return 0;
}
/*-----------------------BPy_StrokeTextureStepShader type definition ------------------------------*/
PyTypeObject StrokeTextureStepShader_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"StrokeTextureStepShader", /* tp_name */
sizeof(BPy_StrokeTextureStepShader), /* tp_basicsize */
0, /* tp_itemsize */
0, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_reserved */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
StrokeTextureStepShader___doc__, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
&StrokeShader_Type, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)StrokeTextureStepShader___init__, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
};
///////////////////////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
}
#endif

@ -0,0 +1,55 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureStepShader.h
* \ingroup freestyle
*/
#ifndef __FREESTYLE_PYTHON_STROKETEXTURESTEPSHADER_H__
#define __FREESTYLE_PYTHON_STROKETEXTURESTEPSHADER_H__
#include "../BPy_StrokeShader.h"
#ifdef __cplusplus
extern "C" {
#endif
///////////////////////////////////////////////////////////////////////////////////////////
#include <Python.h>
extern PyTypeObject StrokeTextureStepShader_Type;
#define BPy_StrokeTextureStepShader_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&StrokeTextureStepShader_Type))
/*---------------------------Python BPy_StrokeTextureStepShader structure definition----------*/
typedef struct {
BPy_StrokeShader py_ss;
} BPy_StrokeTextureStepShader;
///////////////////////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
}
#endif
#endif /* __FREESTYLE_PYTHON_STROKETEXTURESTEPSHADER_H__ */

@ -449,6 +449,17 @@ int ColorNoiseShader::shade(Stroke& stroke) const
//
///////////////////////////////////////////////////////////////////////////////
int BlenderTextureShader::shade(Stroke& stroke) const
{
return stroke.setMTex(_mtex);
}
int StrokeTextureStepShader::shade(Stroke& stroke) const
{
stroke.setTextureStep(_step);
return 0;
}
int TextureAssignerShader::shade(Stroke& stroke) const
{
#if 0

@ -36,6 +36,8 @@
#include "../geometry/Bezier.h"
#include "../geometry/Geom.h"
struct MTex;
using namespace std;
namespace Freestyle {
@ -894,6 +896,62 @@ public:
virtual int shade(Stroke& stroke) const;
};
/*! [ Texture Shader ].
* Shader to assign texture to the Stroke material.
*/
class BlenderTextureShader : public StrokeShader
{
private:
MTex *_mtex;
public:
/*! Builds the shader.
* \param mtex
* The blender texture to use.
*/
BlenderTextureShader(MTex *mtex) : StrokeShader()
{
_mtex = mtex;
}
virtual string getName() const
{
return "BlenderTextureShader";
}
/*! The shading method */
virtual int shade(Stroke& stroke) const;
};
/*! [ Texture Shader ].
* Shader to assign texture to the Stroke material.
*/
class StrokeTextureStepShader : public StrokeShader
{
private:
float _step;
public:
/*! Builds the shader.
* \param id
* The number of the preset to use.
*/
StrokeTextureStepShader(float step) : StrokeShader()
{
_step = step;
}
virtual string getName() const
{
return "StrokeTextureStepShader";
}
/*! The shading method */
virtual int shade(Stroke& stroke) const;
};
} // end of namespace StrokeShaders
} /* namespace Freestyle */

@ -393,6 +393,10 @@ Stroke::Stroke()
//_mediumType = DEFAULT_STROKE;
_mediumType = OPAQUE_MEDIUM;
_textureId = 0;
_textureStep = 1.0;
for (int a = 0; a < MAX_MTEX; a++) {
_mtex[a] = NULL;
}
_tips = false;
_rep = NULL;
}
@ -411,6 +415,15 @@ Stroke::Stroke(const Stroke& iBrother)
_sampling = iBrother._sampling;
_mediumType = iBrother._mediumType;
_textureId = iBrother._textureId;
_textureStep = iBrother._textureStep;
for (int a = 0; a < MAX_MTEX; a++) {
if (iBrother._mtex) {
_mtex[a] = iBrother._mtex[a];
}
else {
_mtex[a] = NULL;
}
}
_tips = iBrother._tips;
if (iBrother._rep)
_rep = new StrokeRep(*(iBrother._rep));

@ -43,6 +43,14 @@
#include "MEM_guardedalloc.h"
#endif
extern "C" {
#include "DNA_material_types.h"
}
#ifndef MAX_MTEX
#define MAX_MTEX 18
#endif
namespace Freestyle {
//
@ -528,9 +536,11 @@ private:
float _Length; // The stroke length
viewedge_container _ViewEdges;
float _sampling;
float _textureStep;
// StrokeRenderer *_renderer; // mark implementation OpenGL renderer
MediumType _mediumType;
unsigned int _textureId;
MTex *_mtex[MAX_MTEX];
bool _tips;
Vec2r _extremityOrientations[2]; // the orientations of the first and last extermity
StrokeRep *_rep;
@ -635,6 +645,13 @@ public:
/*! Returns the id of the texture used to simulate th marks system for this Stroke */
inline unsigned int getTextureId() {return _textureId;}
/*! Returns the spacing of texture coordinates along the stroke lenght */
inline float getTextureStep() {return _textureStep;}
/*! Returns the texture used at given index to simulate the marks system for this Stroke */
inline MTex *getMTex(int idx) {
return _mtex[idx];}
/*! Returns true if this Stroke uses a texture with tips, false otherwise. */
inline bool hasTips() const
{
@ -725,6 +742,25 @@ public:
_textureId = id;
}
/*! sets the spacing of texture coordinates along the stroke lenght. */
inline void setTextureStep(float step)
{
_textureStep = step;
}
/*! assigns a blender texture to the first available slot. */
inline int setMTex(MTex *mtex)
{
for (int a = 0; a < MAX_MTEX; a++) {
if (!_mtex[a]) {
_mtex[a] = mtex;
return 0;
}
}
return -1; /* no free slots */
}
/*! sets the flag telling whether this stroke is using a texture with tips or not. */
inline void setTips(bool iTips)
{

@ -45,6 +45,7 @@ StrokeVertexRep::StrokeVertexRep(const StrokeVertexRep& iBrother)
{
_point2d = iBrother._point2d;
_texCoord = iBrother._texCoord;
_texCoord_w_tips = iBrother._texCoord_w_tips;
_color = iBrother._color;
_alpha = iBrother._alpha;
}
@ -53,13 +54,13 @@ StrokeVertexRep::StrokeVertexRep(const StrokeVertexRep& iBrother)
// STRIP
/////////////////////////////////////
Strip::Strip(const vector<StrokeVertex*>& iStrokeVertices, bool hasTips, bool beginTip, bool endTip)
Strip::Strip(const vector<StrokeVertex*>& iStrokeVertices, bool hasTips, bool beginTip, bool endTip, float texStep)
{
createStrip(iStrokeVertices);
if (!hasTips)
computeTexCoord (iStrokeVertices);
else
computeTexCoordWithTips (iStrokeVertices, beginTip, endTip);
// We compute both kinds of coordinates to use different kinds of textures
computeTexCoord (iStrokeVertices, texStep);
computeTexCoordWithTips (iStrokeVertices, beginTip, endTip, texStep);
}
Strip::Strip(const Strip& iBrother)
@ -485,21 +486,19 @@ void Strip::cleanUpSingularities (const vector<StrokeVertex*>& iStrokeVertices)
// Texture coordinates
////////////////////////////////
void Strip::computeTexCoord (const vector<StrokeVertex *>& iStrokeVertices)
void Strip::computeTexCoord (const vector<StrokeVertex *>& iStrokeVertices, float texStep)
{
vector<StrokeVertex *>::const_iterator v, vend;
StrokeVertex *sv;
int i = 0;
for (v = iStrokeVertices.begin(), vend = iStrokeVertices.end(); v != vend; v++) {
sv = (*v);
_vertices[i]->setTexCoord(Vec2r((real)(sv->curvilinearAbscissa() / _averageThickness), 0));
_vertices[i]->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
sv->attribute().getColor()[2]));
_vertices[i]->setTexCoord(Vec2r((real)(sv->curvilinearAbscissa() / (_averageThickness * texStep)), 0));
_vertices[i]->setColor(Vec3r(sv->attribute().getColorRGB()));
_vertices[i]->setAlpha(sv->attribute().getAlpha());
i++;
_vertices[i]->setTexCoord(Vec2r((real)(sv->curvilinearAbscissa() / _averageThickness), 1));
_vertices[i]->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
sv->attribute().getColor()[2]));
_vertices[i]->setTexCoord(Vec2r((real)(sv->curvilinearAbscissa() / (_averageThickness * texStep)), 1));
_vertices[i]->setColor(Vec3r(sv->attribute().getColorRGB()));
_vertices[i]->setAlpha(sv->attribute().getAlpha());
i++;
#if 0
@ -509,23 +508,23 @@ void Strip::computeTexCoord (const vector<StrokeVertex *>& iStrokeVertices)
}
}
void Strip::computeTexCoordWithTips (const vector<StrokeVertex*>& iStrokeVertices, bool tipBegin, bool tipEnd)
void Strip::computeTexCoordWithTips (const vector<StrokeVertex*>& iStrokeVertices, bool tipBegin, bool tipEnd, float texStep)
{
//soc unused - unsigned int sizeStrip = _vertices.size() + 8; //for the transition between the tip and the body
vector<StrokeVertex*>::const_iterator v, vend;
StrokeVertex *sv = NULL;
StrokeVertexRep *tvRep[2] = {NULL};
float l, fact, t;
float u = 0, uPrev = 0;
int tiles;
int i = 0;
float spacedThickness = _averageThickness * texStep;
v = iStrokeVertices.begin();
vend = iStrokeVertices.end();
float l = (*v)->strokeLength() / _averageThickness;
int tiles = int(l);
float fact = (float(tiles) + 0.5) / l;
//soc unused - float uTip2 = float(tiles) + 0.25;
float u = 0;
float uPrev = 0;
int i = 0;
float t;
StrokeVertexRep *tvRep1, *tvRep2;
l = (*v)->strokeLength() / spacedThickness;
tiles = int(l + 0.5); // round to the nearest
fact = (float(tiles) + 0.5) / l;
#if 0
cerr << "l=" << l << " tiles=" << tiles << " _averageThicnkess="
@ -538,97 +537,68 @@ void Strip::computeTexCoordWithTips (const vector<StrokeVertex*>& iStrokeVertice
for (; v != vend; v++) {
sv = (*v);
svRep = *currentSV;
u = sv->curvilinearAbscissa() / _averageThickness * fact;
u = sv->curvilinearAbscissa() / spacedThickness * fact;
if (u > 0.25)
break;
svRep->setTexCoord(Vec2r((real)u, 0.5));
svRep->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
sv->attribute().getColor()[2]));
svRep->setAlpha(sv->attribute().getAlpha());
svRep->setTexCoord(Vec2r((real)u, 0.5), true);
i++;
++currentSV;
svRep = *currentSV;
svRep->setTexCoord(Vec2r((real)u, 1));
svRep->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
sv->attribute().getColor()[2]));
svRep->setAlpha(sv->attribute().getAlpha());
svRep->setTexCoord(Vec2r((real)u, 1), true);
i++;
++currentSV;
uPrev = u;
}
//first transition vertex
// first transition vertex
if (fabs(u - uPrev) > ZERO)
t = (0.25 - uPrev) / (u - uPrev);
else
t = 0;
#if 0
if (!tiles)
t = 0.5;
#endif
tvRep1 = new StrokeVertexRep(Vec2r((1 - t) * _vertices[i - 2]->point2d() + t * _vertices[i]->point2d()));
tvRep1->setTexCoord(Vec2r(0.25, 0.5));
tvRep1->setColor(Vec3r((1 - t) * _vertices[i - 2]->color() +
t * Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
sv->attribute().getColor()[2])));
tvRep1->setAlpha((1 - t) * _vertices[i - 2]->alpha() + t * sv->attribute().getAlpha());
for (int k = 0; k < 2; k++) {
tvRep[k] = new StrokeVertexRep((1 - t) * _vertices[i - 2]->point2d() + t * _vertices[i]->point2d());
tvRep[k]->setTexCoord((1 - t) * _vertices[i - 2]->texCoord() + t * _vertices[i]->texCoord());
// v coord is 0.5 for tvRep[0], 1.0 for tvRep[1]
tvRep[k]->setTexCoord(Vec2r(0.25, 0.5 * (k + 1)), true);
tvRep[k]->setColor((1 - t) * _vertices[i - 2]->color() + t * Vec3r(sv->attribute().getColorRGB()));
tvRep[k]->setAlpha((1 - t) * _vertices[i - 2]->alpha() + t * sv->attribute().getAlpha());
i++;
tvRep2 = new StrokeVertexRep(Vec2r((1 - t) * _vertices[i - 2]->point2d() + t *_vertices[i]->point2d()));
tvRep2->setTexCoord(Vec2r(0.25, 1));
tvRep2->setColor(Vec3r((1 - t) * _vertices[i - 2]->color() +
t * Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
sv->attribute().getColor()[2])));
tvRep2->setAlpha((1 - t) * _vertices[i - 2]->alpha() + t * sv->attribute().getAlpha());
i++;
currentSV = _vertices.insert(currentSV, tvRep1);
++currentSV;
currentSV = _vertices.insert(currentSV, tvRep2);
}
for (int k = 0; k < 2; k++) {
currentSV = _vertices.insert(currentSV, tvRep[k]);
++currentSV;
}
// copy the vertices with different texture coordinates
tvRep1 = new StrokeVertexRep(_vertices[i - 2]->point2d());
tvRep1->setTexCoord(Vec2r(0.25, 0));
tvRep1->setColor(_vertices[i - 2]->color());
tvRep1->setAlpha(_vertices[i - 2]->alpha());
for (int k = 0; k < 2; k++) {
tvRep[k] = new StrokeVertexRep(*(_vertices[i - 2]));
// v coord is 0.0 for tvRep[0], 0.5 for tvRep[1]
tvRep[k]->setTexCoord(Vec2r(0.0, 0.5 * k), true); // FIXED u coord
i++;
tvRep2 = new StrokeVertexRep(_vertices[i - 2]->point2d());
tvRep2->setTexCoord(Vec2r(0.25, 0.5));
tvRep2->setColor(_vertices[i - 2]->color());
tvRep2->setAlpha(_vertices[i - 2]->alpha());
i++;
currentSV = _vertices.insert(currentSV, tvRep1);
++currentSV;
currentSV = _vertices.insert(currentSV, tvRep2);
}
for (int k = 0; k < 2; k++) {
currentSV = _vertices.insert(currentSV, tvRep[k]);
++currentSV;
}
}
uPrev = 0;
// body of the stroke
for (; v != vend; v++) {
sv = (*v);
svRep = *currentSV;
u = sv->curvilinearAbscissa() / _averageThickness * fact - 0.25;
u = sv->curvilinearAbscissa() / spacedThickness * fact - 0.25;
if (u > tiles)
break;
svRep->setTexCoord(Vec2r((real)u, 0));
svRep->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
sv->attribute().getColor()[2]));
svRep->setAlpha(sv->attribute().getAlpha());
svRep->setTexCoord(Vec2r((real)u, 0), true);
i++;
++currentSV;
svRep = *currentSV;
svRep->setTexCoord(Vec2r((real)u, 0.5));
svRep->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
sv->attribute().getColor()[2]));
svRep->setAlpha(sv->attribute().getAlpha());
svRep->setTexCoord(Vec2r((real)u, 0.5), true);
i++;
++currentSV;
@ -636,68 +606,48 @@ void Strip::computeTexCoordWithTips (const vector<StrokeVertex*>& iStrokeVertice
}
if (tipEnd) {
// second transition vertex
if ((fabs(u - uPrev) > ZERO))
if (fabs(u - uPrev) > ZERO)
t = (float(tiles) - uPrev) / (u - uPrev);
else
t = 0;
tvRep1 = new StrokeVertexRep(Vec2r((1 - t) * _vertices[i - 2]->point2d() + t * _vertices[i]->point2d()));
tvRep1->setTexCoord(Vec2r((real)tiles, 0));
tvRep1->setColor(Vec3r((1 - t) * _vertices[i - 2]->color() +
t * Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
sv->attribute().getColor()[2])));
tvRep1->setAlpha((1 - t) * _vertices[i - 2]->alpha() + t * sv->attribute().getAlpha());
for (int k = 0; k < 2; k++) {
tvRep[k] = new StrokeVertexRep((1 - t) * _vertices[i - 2]->point2d() + t * _vertices[i]->point2d());
tvRep[k]->setTexCoord((1 - t) * _vertices[i - 2]->texCoord() + t * _vertices[i]->texCoord());
// v coord is 0.0 for tvRep[0], 0.5 for tvRep[1]
tvRep[k]->setTexCoord(Vec2r((real)tiles, 0.5 * k), true); // FIXED u coord
tvRep[k]->setColor((1 - t) * _vertices[i - 2]->color() + t * Vec3r(sv->attribute().getColorRGB()));
tvRep[k]->setAlpha((1 - t) * _vertices[i - 2]->alpha() + t * sv->attribute().getAlpha());
i++;
tvRep2 = new StrokeVertexRep(Vec2r((1 - t) * _vertices[i - 2]->point2d() + t * _vertices[i]->point2d()));
tvRep2->setTexCoord(Vec2r((real)tiles, 0.5));
tvRep2->setColor(Vec3r((1 - t) * _vertices[i - 2]->color() +
t * Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
sv->attribute().getColor()[2])));
tvRep2->setAlpha((1 - t) * _vertices[i - 2]->alpha() + t * sv->attribute().getAlpha());
i++;
currentSV = _vertices.insert(currentSV, tvRep1);
++currentSV;
currentSV = _vertices.insert(currentSV, tvRep2);
}
for (int k = 0; k < 2; k++) {
currentSV = _vertices.insert(currentSV, tvRep[k]);
++currentSV;
}
// copy the vertices with different texture coordinates
tvRep1 = new StrokeVertexRep(_vertices[i - 2]->point2d());
tvRep1->setTexCoord(Vec2r(0.75, 0.5));
tvRep1->setColor(_vertices[i - 2]->color());
tvRep1->setAlpha(_vertices[i - 2]->alpha());
for (int k = 0; k < 2; k++) {
tvRep[k] = new StrokeVertexRep(*(_vertices[i - 2]));
// v coord is 0.5 for tvRep[0], 1.0 for tvRep[1]
tvRep[k]->setTexCoord(Vec2r(0.75, 0.5 * (k + 1)), true);
i++;
tvRep2 = new StrokeVertexRep(_vertices[i - 2]->point2d());
tvRep2->setTexCoord(Vec2r(0.75, 1));
tvRep2->setColor(_vertices[i - 2]->color());
tvRep2->setAlpha(_vertices[i - 2]->alpha());
i++;
currentSV = _vertices.insert(currentSV, tvRep1);
++currentSV;
currentSV = _vertices.insert(currentSV, tvRep2);
}
for (int k = 0; k < 2; k++) {
currentSV = _vertices.insert(currentSV, tvRep[k]);
++currentSV;
}
// end tip
for (; v != vend; v++) {
sv = (*v);
svRep = *currentSV;
u = 0.75 + sv->curvilinearAbscissa() / _averageThickness * fact - float(tiles) - 0.25;
u = 0.75 + sv->curvilinearAbscissa() / spacedThickness * fact - float(tiles) - 0.25;
svRep->setTexCoord(Vec2r((real)u, 0.5));
svRep->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
sv->attribute().getColor()[2]));
svRep->setAlpha(sv->attribute().getAlpha());
svRep->setTexCoord(Vec2r((real)u, 0.5), true);
i++;
++currentSV;
svRep = *currentSV;
svRep->setTexCoord(Vec2r((real)u, 1));
svRep->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
sv->attribute().getColor()[2]));
svRep->setAlpha(sv->attribute().getAlpha());
svRep->setTexCoord(Vec2r((real)u, 1), true);
i++;
++currentSV;
}
@ -729,6 +679,10 @@ StrokeRep::StrokeRep()
{
_stroke = 0;
_strokeType = Stroke::OPAQUE_MEDIUM;
_textureStep = 1.0;
for (int a = 0; a < MAX_MTEX; a++) {
_mtex[a] = NULL;
}
TextureManager *ptm = TextureManager::getInstance();
if (ptm)
_textureId = ptm->getDefaultTextureId();
@ -746,6 +700,15 @@ StrokeRep::StrokeRep(Stroke *iStroke)
_stroke = iStroke;
_strokeType = iStroke->getMediumType();
_textureId = iStroke->getTextureId();
_textureStep = iStroke->getTextureStep();
for (int a = 0; a < MAX_MTEX; a++) {
if (iStroke->getMTex(a)) {
_mtex[a] = iStroke->getMTex(a);
}
else {
_mtex[a] = NULL;
}
}
if (_textureId == 0) {
TextureManager *ptm = TextureManager::getInstance();
if (ptm)
@ -768,6 +731,15 @@ StrokeRep::StrokeRep(const StrokeRep& iBrother)
_stroke = iBrother._stroke;
_strokeType = iBrother._strokeType;
_textureId = iBrother._textureId;
_textureStep = iBrother._textureStep;
for (int a = 0; a < MAX_MTEX; a++) {
if (iBrother._mtex[a]) {
_mtex[a] = iBrother._mtex[a];
}
else {
_mtex[a] = NULL;
}
}
for (vector<Strip*>::const_iterator s = iBrother._strips.begin(), send = iBrother._strips.end();
s != send;
++s)
@ -811,7 +783,7 @@ void StrokeRep::create()
end = true;
}
if ((!strip.empty()) && (strip.size() > 1)) {
_strips.push_back(new Strip(strip, _stroke->hasTips(), first, end));
_strips.push_back(new Strip(strip, _stroke->hasTips(), first, end, _stroke->getTextureStep()));
strip.clear();
}
first = false;

@ -36,6 +36,10 @@
#include "MEM_guardedalloc.h"
#endif
extern "C" {
#include "DNA_material_types.h"
}
namespace Freestyle {
using namespace Geometry;
@ -78,8 +82,12 @@ public:
return _point2d;
}
inline Vec2r& texCoord()
inline Vec2r& texCoord(bool tips=false)
{
if (tips) {
return _texCoord_w_tips;
}
else
return _texCoord;
}
@ -98,10 +106,15 @@ public:
_point2d = p;
}
inline void setTexCoord(const Vec2r& p)
inline void setTexCoord(const Vec2r& p, bool tips=false)
{
if (tips) {
_texCoord_w_tips = p;
}
else {
_texCoord = p;
}
}
inline void setColor(const Vec3r& p)
{
@ -116,6 +129,7 @@ public:
protected:
Vec2r _point2d;
Vec2r _texCoord;
Vec2r _texCoord_w_tips;
Vec3r _color;
float _alpha;
@ -135,15 +149,15 @@ protected:
public:
Strip(const std::vector<StrokeVertex*>& iStrokeVertices, bool hasTips = false,
bool tipBegin = false, bool tipEnd = false);
bool tipBegin = false, bool tipEnd = false, float texStep = 1.0);
Strip(const Strip& iBrother);
virtual ~Strip();
protected:
void createStrip(const std::vector<StrokeVertex*>& iStrokeVertices);
void cleanUpSingularities(const std::vector<StrokeVertex*>& iStrokeVertices);
void computeTexCoord (const std::vector<StrokeVertex*>& iStrokeVertices);
void computeTexCoordWithTips (const std::vector<StrokeVertex*>& iStrokeVertices, bool tipBegin, bool tipEnd);
void computeTexCoord (const std::vector<StrokeVertex*>& iStrokeVertices, float texStep);
void computeTexCoordWithTips (const std::vector<StrokeVertex*>& iStrokeVertices, bool tipBegin, bool tipEnd, float texStep);
public:
inline int sizeStrip() const
@ -168,6 +182,9 @@ protected:
vector<Strip*> _strips;
Stroke::MediumType _strokeType;
unsigned int _textureId;
float _textureStep;
MTex *_mtex[MAX_MTEX];
Material *_material;
// float _averageTextureAlpha;
@ -194,6 +211,16 @@ public:
return _textureId;
}
inline MTex *getMTex(int idx) const
{
return _mtex[idx];
}
inline Material *getMaterial() const
{
return _material;
}
inline vector<Strip*>& getStrips()
{
return _strips;
@ -220,6 +247,16 @@ public:
_textureId = textureId;
}
inline void setMaterial(Material *mat)
{
_material = mat;
}
/*
inline void setMTex(int idx, MTex *mtex_ptr)
{
_mtex[idx] = mtex_ptr;
}*/
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:StrokeRep")
#endif

@ -35,8 +35,16 @@
#include "DNA_listBase.h"
#include "DNA_ID.h"
#ifndef MAX_MTEX
#define MAX_MTEX 18
#endif
/* texco (also in DNA_material_types.h) */
#define TEXCO_STROKE 16 /* actually it's UV */
struct ColorBand;
struct CurveMapping;
struct MTex;
typedef struct LineStyleModifier {
struct LineStyleModifier *next, *prev;
@ -354,7 +362,8 @@ typedef struct LineStyleThicknessModifier_Calligraphy {
#define LS_PANEL_ALPHA 3
#define LS_PANEL_THICKNESS 4
#define LS_PANEL_GEOMETRY 5
#define LS_PANEL_MISC 6
#define LS_PANEL_TEXTURE 6
#define LS_PANEL_MISC 7
/* FreestyleLineStyle::flag */
#define LS_DS_EXPAND (1 << 0) /* for animation editors */
@ -370,6 +379,7 @@ typedef struct LineStyleThicknessModifier_Calligraphy {
#define LS_SPLIT_PATTERN (1 << 10)
#define LS_NO_SORTING (1 << 11)
#define LS_REVERSE_ORDER (1 << 12) /* for sorting */
#define LS_TEXTURE (1 << 13)
/* FreestyleLineStyle::chaining */
#define LS_CHAINING_PLAIN 1
@ -415,10 +425,16 @@ typedef struct FreestyleLineStyle {
unsigned short split_dash2, split_gap2;
unsigned short split_dash3, split_gap3;
int sort_key, integration_type;
int pad;
float texstep;
short texact, pr_texture;
short use_nodes, pad;
unsigned short dash1, gap1, dash2, gap2, dash3, gap3;
int panel; /* for UI */
struct MTex *mtex[18]; /* MAX_MTEX */
/* nodes */
struct bNodeTree *nodetree;
ListBase color_modifiers;
ListBase alpha_modifiers;
ListBase thickness_modifiers;

@ -209,6 +209,7 @@ typedef enum eSpaceButtons_Texture_Context {
SB_TEXC_LAMP = 2,
SB_TEXC_PARTICLES = 3,
SB_TEXC_OTHER = 4,
SB_TEXC_LINESTYLE = 5,
} eSpaceButtons_Texture_Context;
/* sbuts->align */
@ -981,6 +982,7 @@ typedef enum eSpaceNode_TexFrom {
SNODE_TEX_OBJECT = 0,
SNODE_TEX_WORLD = 1,
SNODE_TEX_BRUSH = 2,
SNODE_TEX_LINESTYLE = 3,
} eSpaceNode_TexFrom;
/* snode->shaderfrom */

@ -479,6 +479,7 @@ typedef struct ColorMapping {
#define MTEX_BUMP_OBJECTSPACE 1024
#define MTEX_BUMP_TEXTURESPACE 2048
/* #define MTEX_BUMP_FLIPPED 4096 */ /* UNUSED */
#define MTEX_TIPS 4096 /* should use with_freestyle flag? */
#define MTEX_BICUBIC_BUMP 8192
#define MTEX_MAPTO_BOUNDS 16384

@ -331,6 +331,7 @@ extern StructRNA RNA_LineStyleGeometryModifier_SinusDisplacement;
extern StructRNA RNA_LineStyleGeometryModifier_SpatialNoise;
extern StructRNA RNA_LineStyleGeometryModifier_TipRemover;
extern StructRNA RNA_LineStyleModifier;
extern StructRNA RNA_LineStyleTextureSlot;
extern StructRNA RNA_LineStyleThicknessModifier;
extern StructRNA RNA_LineStyleThicknessModifier_AlongStroke;
extern StructRNA RNA_LineStyleThicknessModifier_Calligraphy;

@ -84,6 +84,8 @@ EnumPropertyItem linestyle_geometry_modifier_type_items[] = {
#ifdef RNA_RUNTIME
#include "BKE_linestyle.h"
#include "BKE_texture.h"
#include "BKE_depsgraph.h"
static StructRNA *rna_LineStyle_color_modifier_refine(struct PointerRNA *ptr)
{
@ -249,10 +251,148 @@ static void rna_LineStyleGeometryModifier_name_set(PointerRNA *ptr, const char *
offsetof(LineStyleModifier, name), sizeof(m->name));
}
static void rna_LineStyle_mtex_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->id.data;
rna_iterator_array_begin(iter, (void *)linestyle->mtex, sizeof(MTex *), MAX_MTEX, 0, NULL);
}
static PointerRNA rna_LineStyle_active_texture_get(PointerRNA *ptr)
{
FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->id.data;
Tex *tex;
tex = give_current_linestyle_texture(linestyle);
return rna_pointer_inherit_refine(ptr, &RNA_Texture, tex);
}
static void rna_LineStyle_active_texture_set(PointerRNA *ptr, PointerRNA value)
{
FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->id.data;
set_current_linestyle_texture(linestyle, value.data);
}
static void rna_LineStyle_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
FreestyleLineStyle *linestyle = ptr->id.data;
DAG_id_tag_update(&linestyle->id, 0);
WM_main_add_notifier(NC_LINESTYLE, linestyle);
}
#else
#include "BLI_math.h"
static void rna_def_linestyle_mtex(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
static EnumPropertyItem texco_items[] = {
{TEXCO_WINDOW, "WINDOW", 0, "Window", "Use screen coordinates as texture coordinates"},
{TEXCO_GLOB, "GLOBAL", 0, "Global", "Use global coordinates for the texture coordinates"},
{TEXCO_STROKE, "ALONG_STROKE", 0, "Along stroke", "Use stroke lenght for texture coordinates"},
{TEXCO_ORCO, "ORCO", 0, "Generated", "Use the original undeformed coordinates of the object"},
{0, NULL, 0, NULL, NULL}
};
static EnumPropertyItem prop_mapping_items[] = {
{MTEX_FLAT, "FLAT", 0, "Flat", "Map X and Y coordinates directly"},
{MTEX_CUBE, "CUBE", 0, "Cube", "Map using the normal vector"},
{MTEX_TUBE, "TUBE", 0, "Tube", "Map with Z as central axis"},
{MTEX_SPHERE, "SPHERE", 0, "Sphere", "Map with Z as central axis"},
{0, NULL, 0, NULL, NULL}
};
static EnumPropertyItem prop_x_mapping_items[] = {
{0, "NONE", 0, "None", ""},
{1, "X", 0, "X", ""},
{2, "Y", 0, "Y", ""},
{3, "Z", 0, "Z", ""},
{0, NULL, 0, NULL, NULL}
};
static EnumPropertyItem prop_y_mapping_items[] = {
{0, "NONE", 0, "None", ""},
{1, "X", 0, "X", ""},
{2, "Y", 0, "Y", ""},
{3, "Z", 0, "Z", ""},
{0, NULL, 0, NULL, NULL}
};
static EnumPropertyItem prop_z_mapping_items[] = {
{0, "NONE", 0, "None", ""},
{1, "X", 0, "X", ""},
{2, "Y", 0, "Y", ""},
{3, "Z", 0, "Z", ""},
{0, NULL, 0, NULL, NULL}
};
srna = RNA_def_struct(brna, "LineStyleTextureSlot", "TextureSlot");
RNA_def_struct_sdna(srna, "MTex");
RNA_def_struct_ui_text(srna, "LineStyle Texture Slot", "Texture slot for textures in a LineStyle datablock");
prop = RNA_def_property(srna, "mapping_x", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "projx");
RNA_def_property_enum_items(prop, prop_x_mapping_items);
RNA_def_property_ui_text(prop, "X Mapping", "");
RNA_def_property_update(prop, 0, "rna_LineStyle_update");
prop = RNA_def_property(srna, "mapping_y", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "projy");
RNA_def_property_enum_items(prop, prop_y_mapping_items);
RNA_def_property_ui_text(prop, "Y Mapping", "");
RNA_def_property_update(prop, 0, "rna_LineStyle_update");
prop = RNA_def_property(srna, "mapping_z", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "projz");
RNA_def_property_enum_items(prop, prop_z_mapping_items);
RNA_def_property_ui_text(prop, "Z Mapping", "");
RNA_def_property_update(prop, 0, "rna_LineStyle_update");
prop = RNA_def_property(srna, "mapping", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, prop_mapping_items);
RNA_def_property_ui_text(prop, "Mapping", "");
RNA_def_property_update(prop, 0, "rna_LineStyle_update");
/* map to */
prop = RNA_def_property(srna, "use_map_color_diffuse", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_COL);
RNA_def_property_ui_text(prop, "Diffuse Color", "The texture affects basic color of the stroke");
RNA_def_property_update(prop, 0, "rna_LineStyle_update");
prop = RNA_def_property(srna, "use_map_alpha", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_ALPHA);
RNA_def_property_ui_text(prop, "Alpha", "The texture affects the alpha value");
RNA_def_property_update(prop, 0, "rna_LineStyle_update");
prop = RNA_def_property(srna, "use_tips", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "texflag", MTEX_TIPS);
RNA_def_property_ui_text(prop, "Use tips", "Lower half of the texture is for tips of the stroke");
RNA_def_property_update(prop, 0, "rna_LineStyle_update");
prop = RNA_def_property(srna, "texture_coords", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "texco");
RNA_def_property_enum_items(prop, texco_items);
RNA_def_property_ui_text(prop, "Texture Coordinates",
"Texture coordinates used to map the texture onto the background");
RNA_def_property_update(prop, 0, "rna_LineStyle_update");
prop = RNA_def_property(srna, "alpha_factor", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "alphafac");
RNA_def_property_ui_range(prop, -1, 1, 10, 3);
RNA_def_property_ui_text(prop, "Alpha Factor", "Amount texture affects alpha");
RNA_def_property_update(prop, 0, "rna_LineStyle_update");
prop = RNA_def_property(srna, "diffuse_color_factor", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "colfac");
RNA_def_property_ui_range(prop, 0, 1, 10, 3);
RNA_def_property_ui_text(prop, "Diffuse Color Factor", "Amount texture affects diffuse color");
RNA_def_property_update(prop, 0, "rna_LineStyle_update");
}
static void rna_def_modifier_type_common(StructRNA *srna, EnumPropertyItem *modifier_type_items,
const char *set_name_func, const bool blend, const bool color)
{
@ -892,6 +1032,7 @@ static void rna_def_linestyle(BlenderRNA *brna)
{LS_PANEL_ALPHA, "ALPHA", 0, "Alpha", "Show the panel for alpha transparency options"},
{LS_PANEL_THICKNESS, "THICKNESS", 0, "Thickness", "Show the panel for line thickness options"},
{LS_PANEL_GEOMETRY, "GEOMETRY", 0, "Geometry", "Show the panel for stroke geometry options"},
{LS_PANEL_TEXTURE, "TEXTURE", 0, "Texture", "Show the panel for stroke texture options"},
#if 0 /* hidden for now */
{LS_PANEL_MISC, "MISC", 0, "Misc", "Show the panel for miscellaneous options"},
#endif
@ -938,6 +1079,9 @@ static void rna_def_linestyle(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Freestyle Line Style", "Freestyle line style, reusable by multiple line sets");
RNA_def_struct_ui_icon(srna, ICON_LINE_DATA);
rna_def_mtex_common(brna, srna, "rna_LineStyle_mtex_begin", "rna_LineStyle_active_texture_get",
"rna_LineStyle_active_texture_set", NULL, "LineStyleTextureSlot", "LineStyleTextureSlots", "rna_LineStyle_update");
prop = RNA_def_property(srna, "panel", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "panel");
RNA_def_property_enum_items(prop, panel_items);
@ -1192,12 +1336,36 @@ static void rna_def_linestyle(BlenderRNA *brna)
RNA_def_property_range(prop, 0, USHRT_MAX);
RNA_def_property_ui_text(prop, "Gap 3", "Length of the 3rd gap for dashed lines");
RNA_def_property_update(prop, NC_LINESTYLE, NULL);
prop = RNA_def_property(srna, "use_texture", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", LS_TEXTURE);
RNA_def_property_ui_text(prop, "Texture", "Enable or disable textured strokes");
RNA_def_property_update(prop, NC_LINESTYLE, NULL);
prop = RNA_def_property(srna, "texture_spacing", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "texstep");
RNA_def_property_range(prop, 0.01f, 100.0f);
RNA_def_property_ui_text(prop, "Texture spacing", "Spacing for textures along stroke lenght");
RNA_def_property_update(prop, NC_LINESTYLE, NULL);
/* nodes */
prop = RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "nodetree");
RNA_def_property_ui_text(prop, "Node Tree", "Node tree for node based textures");
prop = RNA_def_property(srna, "use_nodes", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "use_nodes", 1);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Use Nodes", "Use texture nodes for the line style");
RNA_def_property_update(prop, NC_LINESTYLE, NULL);
}
void RNA_def_linestyle(BlenderRNA *brna)
{
rna_def_linestyle_modifiers(brna);
rna_def_linestyle(brna);
rna_def_linestyle_mtex(brna);
}
#endif

@ -166,6 +166,7 @@ static EnumPropertyItem buttons_texture_context_items[] = {
{SB_TEXC_WORLD, "WORLD", ICON_WORLD, "", "Show world textures"},
{SB_TEXC_LAMP, "LAMP", ICON_LAMP, "", "Show lamp textures"},
{SB_TEXC_PARTICLES, "PARTICLES", ICON_PARTICLES, "", "Show particles textures"},
{SB_TEXC_LINESTYLE, "LINESTYLE", ICON_LINE_DATA, "", "Show linestyle textures"},
{SB_TEXC_OTHER, "OTHER", ICON_TEXTURE, "", "Show other data textures"},
{0, NULL, 0, NULL, NULL}
};
@ -983,6 +984,10 @@ static EnumPropertyItem *rna_SpaceProperties_texture_context_itemf(bContext *C,
RNA_enum_items_add_value(&item, &totitem, buttons_texture_context_items, SB_TEXC_PARTICLES);
}
if (ED_texture_context_check_linestyle(C)) {
RNA_enum_items_add_value(&item, &totitem, buttons_texture_context_items, SB_TEXC_LINESTYLE);
}
if (ED_texture_context_check_others(C)) {
RNA_enum_items_add_value(&item, &totitem, buttons_texture_context_items, SB_TEXC_OTHER);
}
@ -3393,6 +3398,7 @@ static void rna_def_space_node(BlenderRNA *brna)
{SNODE_TEX_OBJECT, "OBJECT", ICON_OBJECT_DATA, "Object", "Edit texture nodes from Object"},
{SNODE_TEX_WORLD, "WORLD", ICON_WORLD_DATA, "World", "Edit texture nodes from World"},
{SNODE_TEX_BRUSH, "BRUSH", ICON_BRUSH_DATA, "Brush", "Edit texture nodes from Brush"},
{SNODE_TEX_LINESTYLE, "LINESTYLE", ICON_LINE_DATA, "Line Style", "Edit texture nodes from Line Style"},
{0, NULL, 0, NULL, NULL}
};

@ -92,7 +92,7 @@ static void texture_get_from_context(const bContext *C, bNodeTreeType *UNUSED(tr
}
}
}
else {
else if (snode->texfrom == SNODE_TEX_BRUSH) {
struct Brush *brush = NULL;
if (ob && (ob->mode & OB_MODE_SCULPT))
@ -109,6 +109,17 @@ static void texture_get_from_context(const bContext *C, bNodeTreeType *UNUSED(tr
}
}
}
else if (snode->texfrom == SNODE_TEX_LINESTYLE) {
FreestyleLineStyle *linestyle = CTX_data_linestyle_from_scene(scene);
if (linestyle) {
*r_from = (ID *)linestyle;
tx = give_current_linestyle_texture(linestyle);
if (tx) {
*r_id = &tx->id;
*r_ntree = tx->nodetree;
}
}
}
}
static void foreach_nodeclass(Scene *UNUSED(scene), void *calldata, bNodeClassCallback func)