Python-made grease pencil strokes not updating until manual stroke added #59600

Closed
opened 2018-12-19 04:30:49 +01:00 by Daniel Oakey · 14 comments

System Information
Operating system: Arch Linux
Graphics card: GTX 1060

Blender Version
Broken: 2.80 cef41d0144
Worked: 2.79b

Short description of error
Grease pencil strokes created with python require manually creating a stroke before the pythonically-generated stroke will appear/update. This was a problem with Blender 2.78 as well (according to the comments section for this stack exchange answer) but it was later fixed in blender 2.79. I have confirmed that the following script works as intended in blender 2.79:

  import bpy
  gp = bpy.data.grease_pencil.new("My GPencil")
  scene = bpy.context.scene
  scene.grease_pencil = gp
  scene.frame_set(5) 
  layer = gp.layers.new("Name for new layer", set_active=True)
  frame = layer.frames.new(5)
  stroke = frame.strokes.new()
  stroke.draw_mode = '3DSPACE'
  stroke.points.add(4) # add 4 points
  stroke.points.foreach_set("co", (0,0,0,0,0,4,0,6,4,8,6,4)) # set all at once efficiently

However, my analogous script for blender 2.80 shows the error:

  import bpy
  from mathutils import Vector
  gpencil = bpy.data.grease_pencil.new('gpencil')
  layer = gpencil.layers.new("alayer", set_active=True)
  frame = layer.frames.new(bpy.context.scene.frame_current)
  stroke = frame.strokes.new()
  stroke.line_width = 300
  stroke.display_mode = '3DSPACE'
  points = [
      [0, 0],
      [10, 0]
  ]
  for point in points:
      stroke.points.add(1)
      stroke.points[-1].co.x = point[0]
      stroke.points[-1].co.y = point[1]
  obj = bpy.data.objects.new('agobject', gpencil)
  bpy.context.scene.collection.objects.link(obj)

Exact steps for others to reproduce the error

  1. Open Blender and go to the scripting layout, delete the camera, cube and light in the 3D view
  2. Paste my 2.80 script given above and run it, you should see a display marker indicating a grease pencil object has been created
  3. With the new grease pencil object selected, go to draw mode. You should see a new stroke immediately appear. If you do the above steps multiple times however, you'll need to start drawing a new stroke for the generated stroke to appear.

untitled.gif

**System Information** Operating system: Arch Linux Graphics card: GTX 1060 **Blender Version** Broken: 2.80 cef41d0144e Worked: 2.79b **Short description of error** Grease pencil strokes created with python require manually creating a stroke before the pythonically-generated stroke will appear/update. This was a problem with Blender 2.78 as well (according to [the comments section for this stack exchange answer](https://blender.stackexchange.com/questions/24694/query-grease-pencil-strokes-from-python)) but it was later fixed in blender 2.79. I have confirmed that the following script works as intended in blender 2.79: ``` import bpy ``` ``` gp = bpy.data.grease_pencil.new("My GPencil") scene = bpy.context.scene scene.grease_pencil = gp scene.frame_set(5) ``` ``` layer = gp.layers.new("Name for new layer", set_active=True) ``` ``` frame = layer.frames.new(5) stroke = frame.strokes.new() stroke.draw_mode = '3DSPACE' ``` ``` stroke.points.add(4) # add 4 points stroke.points.foreach_set("co", (0,0,0,0,0,4,0,6,4,8,6,4)) # set all at once efficiently ``` However, my analogous script for blender 2.80 shows the error: ``` import bpy from mathutils import Vector ``` ``` gpencil = bpy.data.grease_pencil.new('gpencil') ``` ``` layer = gpencil.layers.new("alayer", set_active=True) frame = layer.frames.new(bpy.context.scene.frame_current) stroke = frame.strokes.new() stroke.line_width = 300 stroke.display_mode = '3DSPACE' ``` ``` points = [ [0, 0], [10, 0] ] ``` ``` for point in points: stroke.points.add(1) stroke.points[-1].co.x = point[0] stroke.points[-1].co.y = point[1] ``` ``` obj = bpy.data.objects.new('agobject', gpencil) bpy.context.scene.collection.objects.link(obj) ``` **Exact steps for others to reproduce the error** 1. Open Blender and go to the scripting layout, delete the camera, cube and light in the 3D view 2. Paste my 2.80 script given above and run it, you should see a display marker indicating a grease pencil object has been created 3. With the new grease pencil object selected, go to draw mode. You should see a new stroke immediately appear. If you do the above steps multiple times however, you'll need to start drawing a new stroke for the generated stroke to appear. ![untitled.gif](https://archive.blender.org/developer/F6000913/untitled.gif)
Author

Added subscriber: @doakey3

Added subscriber: @doakey3

Added subscribers: @Sergey, @antoniov

Added subscribers: @Sergey, @antoniov

I think the problem is you are not updating the depsgraph data, but not sure how to do that using python.

@Sergey Could you give us any clue here?

I think the problem is you are not updating the depsgraph data, but not sure how to do that using python. @Sergey Could you give us any clue here?

@BKE_object_handle_data_update, In most cases you shouldn't be explicitly updating dependency graph from a script (whatever that means). When running the script i do see DEG_graph_tag_relations_update:(), BKE_gpencil_eval_geometry() and BKE_object_handle_data_update() being run. So as far as dependency graph tags are concerned i don't see issues. So you tell me what it is what drawing code is missing :)

@BKE_object_handle_data_update, In most cases you shouldn't be explicitly updating dependency graph from a script (whatever that means). When running the script i do see `DEG_graph_tag_relations_update:()`, `BKE_gpencil_eval_geometry()` and `BKE_object_handle_data_update()` being run. So as far as dependency graph tags are concerned i don't see issues. So you tell me what it is what drawing code is missing :)
Antonio Vazquez self-assigned this 2018-12-19 23:00:39 +01:00

I have seen the problem is not the update, but the material assigned to stroke.

I have not tested yet in python how creates the material, but doing debug the information of the grease pencil data is not available in the material, so the stroke is bypassed when draw the strokes.

I have seen the problem is not the update, but the material assigned to stroke. I have not tested yet in python how creates the material, but doing debug the information of the grease pencil data is not available in the material, so the stroke is bypassed when draw the strokes.

@doakey3 Try this:

import bpy
from mathutils import Vector

gpencil = bpy.data.grease_pencil.new('gpencil')

layer = gpencil.layers.new("alayer", set_active=True)
frame = layer.frames.new(bpy.context.scene.frame_current)
stroke = frame.strokes.new()
stroke.line_width = 300
stroke.display_mode = '3DSPACE'
# assign material
stroke.material_index = 0

points = [
    [0, 0],
    [10, 0]
]

for point in points:
    stroke.points.add(1)
    stroke.points[-1].co.x = point[0]
    stroke.points[-1].co.y = point[1]  

obj = bpy.data.objects.new('agobject', gpencil)
bpy.context.scene.collection.objects.link(obj)

# create material
mat = bpy.data.materials.new('mymaterial')
obj.data.materials.append(mat)

@doakey3 Try this: ``` import bpy from mathutils import Vector gpencil = bpy.data.grease_pencil.new('gpencil') layer = gpencil.layers.new("alayer", set_active=True) frame = layer.frames.new(bpy.context.scene.frame_current) stroke = frame.strokes.new() stroke.line_width = 300 stroke.display_mode = '3DSPACE' # assign material stroke.material_index = 0 points = [ [0, 0], [10, 0] ] for point in points: stroke.points.add(1) stroke.points[-1].co.x = point[0] stroke.points[-1].co.y = point[1] obj = bpy.data.objects.new('agobject', gpencil) bpy.context.scene.collection.objects.link(obj) # create material mat = bpy.data.materials.new('mymaterial') obj.data.materials.append(mat) ```

Still we have some python API missing to manage graese pencil materials.

Still we have some python API missing to manage graese pencil materials.
Author

Nice! Adding a material appears to fix the main issue of the stroke not appearing at all. I noticed something though... The stroke endpoint is not rounded when it is generated, but the rounded endpoint appears when I go into edit mode and move the endpoint vertex as shown below. I'm not sure if this is a related issue or not.

untitled.gif

Nice! Adding a material appears to fix the main issue of the stroke not appearing at all. I noticed something though... The stroke endpoint is not rounded when it is generated, but the rounded endpoint appears when I go into edit mode and move the endpoint vertex as shown below. I'm not sure if this is a related issue or not. ![untitled.gif](https://archive.blender.org/developer/F6010606/untitled.gif)
Author

I found the api for making a grease pencil material . The code below allows me to add color to the grease pencil object. I still have not found a way to make the endpoint update with python, but I'll keep tinkering. Thanks again for your assistance.

  import bpy
  from mathutils import Vector
  gpencil = bpy.data.grease_pencil.new('gpencil')
  layer = gpencil.layers.new("alayer", set_active=True)
  frame = layer.frames.new(bpy.context.scene.frame_current)
  stroke = frame.strokes.new()
  stroke.line_width = 300
  stroke.display_mode = '3DSPACE'
# assign material
  stroke.material_index = 0
  points = [
      [0, 0],
      [10, 0]
  ]
  for point in points:
      stroke.points.add(1)
      stroke.points[-1].co.x = point[0]
      stroke.points[-1].co.y = point[1]  
  obj = bpy.data.objects.new('agobject', gpencil)
  bpy.context.scene.collection.objects.link(obj)
# create material
  mat = bpy.data.materials.new('test')
  bpy.data.materials.create_gpencil_data(mat)
  mat.grease_pencil.color = (0, 0.5, 0, 1)
  obj.data.materials.append(mat)
I found the [api for making a grease pencil material ](https://docs.blender.org/api/blender2.8/bpy.types.BlendDataMaterials.html?highlight=materials#bpy.types.BlendDataMaterials.create_gpencil_data). The code below allows me to add color to the grease pencil object. I still have not found a way to make the endpoint update with python, but I'll keep tinkering. Thanks again for your assistance. ``` import bpy from mathutils import Vector ``` ``` gpencil = bpy.data.grease_pencil.new('gpencil') ``` ``` layer = gpencil.layers.new("alayer", set_active=True) frame = layer.frames.new(bpy.context.scene.frame_current) stroke = frame.strokes.new() stroke.line_width = 300 stroke.display_mode = '3DSPACE' ``` # assign material ``` stroke.material_index = 0 ``` ``` points = [ [0, 0], [10, 0] ] ``` ``` for point in points: stroke.points.add(1) stroke.points[-1].co.x = point[0] stroke.points[-1].co.y = point[1] ``` ``` obj = bpy.data.objects.new('agobject', gpencil) bpy.context.scene.collection.objects.link(obj) ``` # create material ``` mat = bpy.data.materials.new('test') bpy.data.materials.create_gpencil_data(mat) mat.grease_pencil.color = (0, 0.5, 0, 1) obj.data.materials.append(mat)

@doakey3 Yes, I had missed the create_gpencil_data API.

About the end points, I need add a new python function to force the update and internal recalculation.

@doakey3 Yes, I had missed the create_gpencil_data API. About the end points, I need add a new python function to force the update and internal recalculation.

I have added new APIs to update internal data.

frame.strokes.update(stroke)
gpencil.update()

Last lines of python must be like these:

obj = bpy.data.objects.new('agobject', gpencil)
bpy.context.scene.collection.objects.link(obj)
mat = bpy.data.materials.new('mymaterial')
bpy.data.materials.create_gpencil_data(mat)
obj.data.materials.append(mat)
frame.strokes.update(stroke)
gpencil.update()

@Sergey I have done the change in this commit: e79f401ffa

There is a problem with the update of the datablock. If I run both commands in the same python, the gpencil.update() does not work, but if I run the first script without gpencil.update() and then in a new script add the following code works.

import bpy
gpencil = bpy.data.grease_pencil['gpencil']
gpencil.update()

What am I missing?

I have added new APIs to update internal data. ``` frame.strokes.update(stroke) gpencil.update() ``` Last lines of python must be like these: ``` obj = bpy.data.objects.new('agobject', gpencil) bpy.context.scene.collection.objects.link(obj) mat = bpy.data.materials.new('mymaterial') bpy.data.materials.create_gpencil_data(mat) obj.data.materials.append(mat) frame.strokes.update(stroke) gpencil.update() ``` @Sergey I have done the change in this commit: e79f401ffa7d There is a problem with the update of the datablock. If I run both commands in the same python, the gpencil.update() does not work, but if I run the first script without gpencil.update() and then in a new script add the following code works. ``` import bpy gpencil = bpy.data.grease_pencil['gpencil'] gpencil.update() ``` What am I missing?

This issue was referenced by 36121a1bdc

This issue was referenced by 36121a1bdcd8b0122996d9125e0cd4972dd51ff0

I have updated internally the API to recalc the data after adding points. There is a change in the points.add() api, now requires a datablock parameter. This parameter is necessary to tag the corresponding datablock. We could remove this parameter if we add a new API at datablock level to tag the datablock, but this was rejected in a previous commit.

The final code is this:

import bpy
from mathutils import Vector

gpencil = bpy.data.grease_pencil.new('gpencil')

layer = gpencil.layers.new("alayer", set_active=True)
frame = layer.frames.new(bpy.context.scene.frame_current)
stroke = frame.strokes.new()
stroke.line_width = 300
stroke.display_mode = '3DSPACE'
stroke.material_index = 0


points = [
    [2, 0],
    [8, 5]
]

for point in points:
    stroke.points.add(gpencil, 1)
    stroke.points[-1].co.x = point[0]
    stroke.points[-1].co.y = point[1]  

obj = bpy.data.objects.new('agobject', gpencil)
bpy.context.scene.collection.objects.link(obj)
mat = bpy.data.materials.new('mymaterial')
bpy.data.materials.create_gpencil_data(mat)
obj.data.materials.append(mat)

I have updated internally the API to recalc the data after adding points. There is a change in the points.add() api, now requires a datablock parameter. This parameter is necessary to tag the corresponding datablock. We could remove this parameter if we add a new API at datablock level to tag the datablock, but this was rejected in a previous commit. The final code is this: ``` import bpy from mathutils import Vector gpencil = bpy.data.grease_pencil.new('gpencil') layer = gpencil.layers.new("alayer", set_active=True) frame = layer.frames.new(bpy.context.scene.frame_current) stroke = frame.strokes.new() stroke.line_width = 300 stroke.display_mode = '3DSPACE' stroke.material_index = 0 points = [ [2, 0], [8, 5] ] for point in points: stroke.points.add(gpencil, 1) stroke.points[-1].co.x = point[0] stroke.points[-1].co.y = point[1] obj = bpy.data.objects.new('agobject', gpencil) bpy.context.scene.collection.objects.link(obj) mat = bpy.data.materials.new('mymaterial') bpy.data.materials.create_gpencil_data(mat) obj.data.materials.append(mat) ```

Changed status from 'Open' to: 'Resolved'

Changed status from 'Open' to: 'Resolved'
Sign in to join this conversation.
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset Browser
Interest
Asset Browser Project Overview
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Collada
Interest
Compatibility
Interest
Compositing
Interest
Core
Interest
Cycles
Interest
Dependency Graph
Interest
Development Management
Interest
EEVEE
Interest
EEVEE & Viewport
Interest
Freestyle
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
ID Management
Interest
Images & Movies
Interest
Import Export
Interest
Line Art
Interest
Masking
Interest
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overlay
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
Interest
Python API
Interest
Render & Cycles
Interest
Render Pipeline
Interest
Sculpt, Paint & Texture
Interest
Text Editor
Interest
Translations
Interest
Triaging
Interest
Undo
Interest
USD
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Interest
Video Sequencer
Interest
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Module
Animation & Rigging
Module
Core
Module
Development Management
Module
EEVEE & Viewport
Module
Grease Pencil
Module
Modeling
Module
Nodes & Physics
Module
Pipeline, Assets & IO
Module
Platforms, Builds & Tests
Module
Python API
Module
Render & Cycles
Module
Sculpt, Paint & Texture
Module
Triaging
Module
User Interface
Module
VFX & Video
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Priority
High
Priority
Low
Priority
Normal
Priority
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No project
No Assignees
4 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: blender/blender#59600
No description provided.