Yes that would be good. Also, add the settings of your draw brush please.
The issue has been submitted, the schedule is waiting for repair, this is #128680 - GPv3: Vertex color by default in paint mods - blender - Blender Projects
I just added a section on the migration page on how to get the āScreen Spaceā effect from 4.2 in 4.3: https://developer.blender.org/docs/release_notes/4.3/grease_pencil_migration/#screen-space-stroke-thickness
Let me know if that works.
Iām not sure if this is the correct thread to post this, it may be more related to the viewport EEVEE render engine, but since the issue has to do with GP, here it goes:
At our studio we have encountered an issue in production where we need to draw some GP lines over the geometry, but keep them as close as they can be to the underlying geo, so the lines donāt appear to float when looked at up-close at an angle. So artists have worked with a tiny offset.
Problem is, they did it while in render/material view mode, and the viewport result is not the same as it would be when doing an f12 render. The actual offset, is what can be seen in solid mode, but they didnāt know this, so all the GP lines appeared inset into the geometry when rendered. You can see the problem in the video below:
Should I report it as a bug? We have encountered in 4.0, so itās not a regression, but I think it should be considered a bug.
As I say, it may have to do more with the viewport render engine than GP per se, if thatās the case let me know.
If this is an issue in 4.2 LTS you could report is as a bug. Iām not entirely sure if this is expected or not. Maybe @fclem can comment.
In any case, this seems unrelated to the topic of this thread which is GPv3 (Blender 4.3).
Thanks, done! I checked and it is present in latest 4.2 LTS (the video recorded is using latest 4.3)
In any case, this seems unrelated to the topic of this thread which is GPv3 (Blender 4.3).
I thought as much, but I wasnāt sure if it was somehow related to GP itself. Sorry
No problem! Better to ask anyway
Hello. Thank you very much for recent updates of the migration document. During testing new high-level APIs, I found them behave differently from GPv2. Each time I get access to a stroke, it returns a different reference. I cannot tell if two variables represent the same stroke, and the reference does not reflect later changes of the stroke:
(Logs from 4.3.0 Beta, branch: blender-v4.3-release, commit date: 2024-10-11 22:23, hash: `bcf6524ca1ee`)
>>> f = bpy.context.object.data.layers[1].current_frame()
>>> s1 = f.drawing.strokes[0]
>>> s2 = f.drawing.strokes[0]
>>> s1 == s2
False
>>> len(s1.points)
32
>>> f.drawing.resize_strokes([15], indices=[0])
>>> len(s1.points)
32
May I ask if it is intentional or will be improved later? I failed to migrate my add-on, because in many cases I need to revisit a stroke after performing some operations that may change the stroke indices and point counts. I did not figure out how to achieve this with the new API.
Yes this is expected and wonāt change.
The stroke class is only a higher level API on top of the drawing.attributes
API. When you access drawing.strokes
it creates new instances of the stroke class every time. The stroke class is just a reference to the drawing + stroke index + point indices.
This is not explained well on the migration page yet. Iām planning on adding this. In the meantime: The strokes API is implemented in python, so you can read the implementation here: drawing.strokes
, GreasePencilStroke
.
To solve your problem you probably want to refer to strokes by their index instead of holding onto a reference.
Thank you for posting the source code. Now I have a better understanding of how these slices work.
I prefer a persistent reference because of the following concerns:
- In the 2D display mode, it is common for a user to rearrange the strokes frequently.
- There may be memory safety issues if an old slice is called after attributes are updated. If the API user is not careful enough, Blender may crash instantly. I do not know if it would be better to have some protective measures.
To provide persistent stroke references, I tried to create my own wrapper class by assigning a random hash value to each stroke as an internal attribute:
import random
class TraceableStroke:
def __init__(self, drawing, identifier, initial_index):
self._drawing = drawing
self._hash = identifier
self._index = initial_index
def update_index(self):
if self._index >= len(self._drawing.attributes['.hash'].data) or self._drawing.attributes['.hash'].data[self._index] != self._hash:
# May need optimization / error handling here
for i, attr in enumerate(self._drawing.attributes['.hash'].data):
if attr.value == self._hash:
self._index = i
def __eq__(self, other):
return (self._drawing == other._drawing) and (self._hash == other._hash)
def __getattr__(self, name):
self.update_index()
return getattr(self._drawing.strokes[self._index], name)
class TraceableStrokeCollection:
def __init__(self, drawing):
# Would be helpful if this part can be automatically done
# Also, need to allocate new hash to duplicated strokes
self._drawing = drawing
self._hash_attr = drawing.attributes.new(".hash", 'INT', 'CURVE') if '.hash' not in drawing.attributes else drawing.attributes['.hash']
for attr in self._hash_attr.data:
if attr.value == 0:
attr.value = random.randint(1, 2**24)
def __getitem__(self, key):
return TraceableStroke(self._drawing, self._hash_attr.data[key].value, key)
# Example of using this class
import bpy
f = bpy.context.object.data.layers[-1].current_frame()
strokes = TraceableStrokeCollection(f.drawing)
s1 = strokes[1]
print(s1.points[0].position)
f.drawing.remove_strokes([0])
print(s1.points[0].position) # Should get the same result
Do you think this is a feasible workaround to adopt?
Besides the reference issue, I also have some other questions about the new API:
- Using
drawing.attributes
API, is there a way to get the point count / the first point index of each stroke? - Is there an equivalent of the GPv2 operator
bpy.ops.gpencil.stroke_sample
? - I got errors when adding new points to a stroke. In this line, should
resize_curves
beresize_strokes
?
If you want to keep a more permanent reference (that stays even when the user closes Blender) I can recommend saving the identifier (Iād probably still use the original index) as an attribute. During operations like reordering strokes or subdividing a stroke, etc., attributes are propagated correctly. Meaning if you store an attribute for a stroke once, it will stay there permanently unless the attribute canāt be propagated (e.g. when the stroke is removed).
See Attribute(bpy_struct) - Blender Python API.
- Yes, using
drawing.curve_offsets
. - I canāt find anything in the API reference. We might have missed this one. Bit of a shame because it would have been easy to port. It will be in 4.4 then.
- Yep! That looks like a bug! EDIT: Fixed!
After more tests, I got some new issues about attributes:
- Each time I use high-level API to assign an attribute value, a redundant attribute is created. I think the problem might be in the AttributeGetterSetter, which always calls the
new
method. Although not visible, I think.selection
setter may have the similar issue.
-
If I first draw strokes using a material without fill, then enable the fill, the fill appears fully opaque. However, the attribute
fill_opacity
is not created. In this case, if I use the high-level APIstroke.fill_opacity
, it returns 0.0 rather than 1. -
The modifier
TextureMapping
creates a new attributeu_scale
. If I apply the modifier, then draw new strokes, all the new strokes have zerou_scale
, which prevents the line texture from showing.
Would be good to create bug reports for these issues, so itās easier for us to track them!
By the way @filedescriptor thanks for adding the move
function to the frames class. Itās cool that it fails on collisions, although it takes some preprocessing to calculate the direction a batch of frames should be moved, but itās not a show stopper.
So big thanks!
- and 3. have been fixed in todays build.
I think 2. is sort of expected at the moment unfortunately. Iām working on a proposal that would change the way this part of the materials would work. This would also solve this issue. Not for 4.3 though.
This has been fixed in the latest beta builds.
@Maurits_Valk Have you reported the drawing performance issue somewhere?
It would be great if I could replicate the setup, specifically the file and the settings of the draw tool.
One of the issue might be a very low Advanced > Spacing
setting. Anything below 50% might result in too many points being generated.
You can check the point count by enabling the Statistics
overlay here:
Thanks a lot for the continuous updates to the Python APIs!
May I ask how to interact with nested layer groups via Python? I figured out to use layer.parent_group
to get the group that a layer belongs to, but I do not know how to handle the case where multiple levels of layer groups exist, since there is no API like layer_group.parent_group
.
I updated the page with more info about this: Migration Process - Blender Developer Documentation
Hello there , I was testing out rigging grease 3.0 , And i noticed thereās a issue that persist from
Grease pencil 2. I was just wondering if people were aware of it because itās a bit niche, But itās important for doing cut out/puppet/bone animation. I made a explanation video of the issue. After you weight paint the gp to a bone, if you move the bone on another frame, and key it you lose the ability to sculpt the grease pencil. Edit: I realized you can kind of edit it, But sculpting it would make this process alot easier. If the gp could be sculpted into any shape no mater where the bone itās attached to is moved and keyed, It opens up alot of options.