1
1

Compare commits

...

456 Commits

Author SHA1 Message Date
be37172a61 GPencil: Fix edit curve not being written to file 2020-11-13 19:46:57 +01:00
15e79aeb18 Merge branch 'master' into greasepencil-edit-curve 2020-11-13 18:12:28 +01:00
78fcd5970c Merge branch 'master' into greasepencil-edit-curve 2020-11-12 22:43:01 +01:00
b2b0f35d4e GPencil: Fix curve point extrude selection 2020-11-12 22:42:13 +01:00
76e9d3638f GPencil: Clean up compiler warnings 2020-11-12 22:41:27 +01:00
fe808ca8a0 Merge branch 'master' into greasepencil-edit-curve 2020-11-12 17:21:19 +01:00
7a31486571 GPencil: Fix comments and rename _pad2 to _pad 2020-11-12 17:12:37 +01:00
da40d91d46 GPencil: Fix compiler errors due merge conflicts 2020-11-09 19:56:21 +01:00
50deb5ceaf Merge branch 'master' into greasepencil-edit-curve 2020-11-09 16:25:56 +01:00
c051fd63ff Merge branch 'master' into greasepencil-edit-curve
Conflicts:
	source/blender/blenloader/intern/writefile.c
	source/blender/editors/gpencil/gpencil_edit.c
2020-11-07 11:13:53 +01:00
96a0f736a8 Merge branch 'master' into greasepencil-edit-curve 2020-11-05 15:47:48 +01:00
b00154d2f9 Merge branch 'master' into greasepencil-edit-curve
Conflicts:
	source/blender/editors/gpencil/gpencil_edit.c
2020-11-04 16:15:17 +01:00
a8ec05c587 Merge branch 'master' into greasepencil-edit-curve 2020-10-31 09:25:54 +01:00
eb29a98126 Merge branch 'master' into greasepencil-edit-curve
Conflicts:
	source/blender/editors/gpencil/gpencil_edit.c
2020-10-30 15:48:04 +01:00
2df6272a76 Merge branch 'master' into greasepencil-edit-curve 2020-10-29 19:29:56 +01:00
b650f5d52b Merge branch 'master' into greasepencil-edit-curve 2020-10-28 15:44:50 +01:00
f17c9d9cba Merge branch 'master' into greasepencil-edit-curve 2020-10-27 17:40:33 +01:00
cc0aa15269 Merge branch 'master' into greasepencil-edit-curve 2020-10-23 19:46:35 +02:00
514cb2b549 Merge branch 'master' into greasepencil-edit-curve
Conflicts:
	source/blender/editors/gpencil/gpencil_edit.c
2020-10-22 20:04:42 +02:00
628ac1472f Merge branch 'master' into greasepencil-edit-curve
Conflicts:
	source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c
2020-10-21 19:40:40 +02:00
509c11f2fb Merge branch 'master' into greasepencil-edit-curve 2020-10-21 15:32:50 +02:00
42c6ebfae8 Merge branch 'master' into greasepencil-edit-curve
Conflicts:
	source/blender/blenloader/intern/versioning_290.c
2020-10-19 15:53:08 +02:00
0ed9f4144b Merge branch 'master' into greasepencil-edit-curve 2020-10-17 12:31:29 +02:00
ebf150dca8 Merge branch 'master' into greasepencil-edit-curve 2020-10-15 18:43:42 +02:00
22afae2475 Merge branch 'master' into greasepencil-edit-curve 2020-10-14 15:30:40 +02:00
bae4e21304 Merge branch 'master' into greasepencil-edit-curve
Conflicts:
	source/blender/editors/gpencil/gpencil_edit.c
2020-10-12 15:43:01 +02:00
956bb4bf28 Merge branch 'master' into greasepencil-edit-curve
Conflicts:
	source/blender/blenloader/intern/versioning_290.c
2020-10-08 10:32:02 +02:00
50a86fdcf0 Merge branch 'master' into greasepencil-edit-curve 2020-10-07 17:10:33 +02:00
28d51f775f Merge branch 'master' into greasepencil-edit-curve 2020-10-05 15:34:12 +02:00
218fa0a23c Merge branch 'master' into greasepencil-edit-curve
Conflicts:
	source/blender/blenloader/intern/versioning_290.c
2020-10-03 11:00:19 +02:00
6387426fff Merge branch 'master' into greasepencil-edit-curve
Conflicts:
	source/blender/blenloader/intern/versioning_290.c
2020-10-01 16:23:53 +02:00
493158b5aa GPencil: Fix bug where curve points woud dissapear
When adaptive resolution was active, the calculated resolution for a
segment was not being claped to a minimum of 1, leading to segments
with zero points.
2020-09-28 18:52:06 +02:00
e76362b058 GPencil: Fix missing screen update when use Fixed Simplify 2020-09-28 17:57:48 +02:00
dc255302a4 GPencil: Fix parameter list after merge 2020-09-28 17:33:07 +02:00
b9642bc221 Merge branch 'master' into greasepencil-edit-curve 2020-09-28 17:06:19 +02:00
fdf9ea45af Merge branch 'master' into greasepencil-edit-curve 2020-09-28 10:57:23 +02:00
ff756d9523 GPencil: Remove unused function 2020-09-28 10:56:48 +02:00
eaed745804 Merge branch 'master' into greasepencil-edit-curve 2020-09-25 15:51:39 +02:00
5ce315f2b8 Merge branch 'master' into greasepencil-edit-curve 2020-09-24 15:56:43 +02:00
ea675cb350 Merge branch 'master' into greasepencil-edit-curve 2020-09-24 15:27:26 +02:00
4d44bd9ad2 Merge branch 'master' into greasepencil-edit-curve 2020-09-23 20:10:10 +02:00
da7a753430 Merge branch 'master' into greasepencil-edit-curve 2020-09-22 20:12:44 +02:00
da64eef55a Merge branch 'master' into greasepencil-edit-curve 2020-09-21 20:23:29 +02:00
b8cef3b2dc Merge branch 'master' into greasepencil-edit-curve 2020-09-21 15:48:04 +02:00
b1acd5e9b1 Merge branch 'master' into greasepencil-edit-curve 2020-09-21 12:09:14 +02:00
1e3e873526 GPencil: Check if layer is locked for Handles 2020-09-20 18:34:22 +02:00
261ddd900e GPencil: Hide Curve Handles when layer is locked 2020-09-20 16:58:47 +02:00
aafb5cee67 Merge branch 'master' into greasepencil-edit-curve
Conflicts:
	source/blender/blenloader/intern/versioning_290.c
2020-09-20 15:32:02 +02:00
cca904081e Merge branch 'master' into greasepencil-edit-curve 2020-09-15 15:27:14 +02:00
66aa884b89 Merge branch 'master' into greasepencil-edit-curve 2020-09-14 15:28:04 +02:00
9d186e78c8 Merge branch 'master' into greasepencil-edit-curve 2020-09-12 15:49:43 +02:00
269ceb666b Merge branch 'master' into greasepencil-edit-curve 2020-09-12 12:14:15 +02:00
91066cd0c3 Merge branch 'master' into greasepencil-edit-curve 2020-09-09 15:44:27 +02:00
2db8d319bc GPencil: Fix compiler errors and warnings
The error was related to the draw manager refactor.
2020-09-07 15:28:27 +02:00
8deb0d84eb Merge branch 'master' into greasepencil-edit-curve 2020-09-07 15:23:02 +02:00
b25a87ea49 Merge branch 'master' into greasepencil-edit-curve 2020-09-07 10:13:41 +02:00
61289c3629 Merge branch 'master' into greasepencil-edit-curve
Conflicts:
	source/blender/blenkernel/BKE_gpencil_geom.h
2020-09-05 15:13:10 +02:00
56a8977e92 Merge branch 'master' into greasepencil-edit-curve 2020-09-03 16:07:55 +02:00
c50ead0885 Merge branch 'master' into greasepencil-edit-curve 2020-09-03 08:22:05 +02:00
7c91f3f3a9 Merge branch 'master' into greasepencil-edit-curve 2020-09-01 15:58:58 +02:00
61d8c41378 Merge branch 'master' into greasepencil-edit-curve 2020-08-31 16:08:44 +02:00
0e8a04e1a5 Merge branch 'master' into greasepencil-edit-curve 2020-08-28 18:31:32 +02:00
18f637230d Merge branch 'master' into greasepencil-edit-curve
Conflicts:
	source/blender/blenloader/intern/writefile.c
2020-08-28 16:52:15 +02:00
767b27aabf Merge branch 'master' into greasepencil-edit-curve 2020-08-26 10:10:51 +02:00
22152804cc Merge branch 'master' into greasepencil-edit-curve 2020-08-25 17:52:02 +02:00
f2174e082a GPencil: Fix circle select curve conversion 2020-08-25 17:02:58 +02:00
9c6d0ba923 GPencil: Convert to curve on selection
Conversion to curve was only working for click slection.
This commit adds conversion to curve to box, circle and lasso selection.
2020-08-25 14:47:03 +02:00
d21280432f Merge branch 'master' into greasepencil-edit-curve 2020-08-25 10:36:57 +02:00
1775565a06 GPencil: Fix angle initialization 2020-08-24 19:20:29 +02:00
57ef6dca0b GPencil: Cleanup compiler warnings 2020-08-24 19:19:52 +02:00
9a82fcb51d Merge branch 'soc-2020-greasepencil-curve' of git.blender.org:blender into soc-2020-greasepencil-curve 2020-08-24 16:43:29 +02:00
3b23ce9992 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-08-24 16:43:21 +02:00
23f725e78c GPencil: Rename parameters 2020-08-24 16:42:41 +02:00
50b0bf6215 GPencil: Fix crash when delete stroke
The memory of the stroke is not avaliable after calling `BKE_gpencil_free_stroke` and cannot free the link.

Instead, before calling the free function, remove the link of the listbase.
2020-08-24 16:11:17 +02:00
ddeb4e8423 GPencil: Fix crash when delete stroke
The memory of the stroke is not avaliable after calling `BKE_gpencil_free_stroke` and cannot free the link.

Instead, before calling the free function, remove the link of the listbase.
2020-08-24 15:53:37 +02:00
274c8ae9e2 GPencil: Handle strokes with one or two points
Generating the curve for a stroke with one or two strokes could
crash because it was not handled properly.
2020-08-24 15:23:36 +02:00
ec36b04280 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-08-24 12:34:46 +02:00
79b309bc65 GPencil: Move Curve versioning to the end of the file
Some files were not patched. When move to master we decide if we must do a version bump.
2020-08-24 12:21:49 +02:00
c332956868 Merge branch 'master' into greasepencil-edit-curve 2020-08-23 16:24:02 +02:00
a936573aae GPencil: Move Curve versioning to the end of the file
Some files were not patched. When move to master we decide if we must do a version bump.
2020-08-22 16:24:53 +02:00
d88e1b7cff Merge branch 'master' into greasepencil-edit-curve 2020-08-22 13:10:48 +02:00
062595b6f9 GPencil: Report operators that are not implemented 2020-08-21 15:37:26 +02:00
4474b7c939 GPencil: Remove unessesary curve edit mode test 2020-08-21 14:26:48 +02:00
e0985ffcc1 GPencil: Draw transform gizmo curve edit 2020-08-21 14:25:46 +02:00
3633a6197e GPencil: Fix transform memory issue 2020-08-21 14:25:10 +02:00
1e5f65c91b GPencil: Fix handle lines display 2020-08-21 11:56:09 +02:00
9a89bb4d59 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-08-21 11:04:13 +02:00
2758e560a0 GPencil: Recalc transform only in curve edit mode
When changing the opacity or thickness, only reaclculate stroke if in
curve edit mode.
2020-08-21 11:03:40 +02:00
2cace77aa1 GPencil: Make parameters const 2020-08-21 10:46:35 +02:00
4844379f3f Merge branch 'soc-2020-greasepencil-curve' of git.blender.org:blender into soc-2020-greasepencil-curve 2020-08-21 10:36:42 +02:00
96a690c7ac Merge branch 'master' into greasepencil-edit-curve 2020-08-21 09:48:45 +02:00
30014b0616 GSoC Editing Grease Pencil Strokes Using Curves
This patch includes all the changes made in the soc-2020-greasepencil-curve branch.

Major changes:

* Add a new "sub-mode" to grease pencil edit mode called "curve edit mode".
* Grease pencil stroke data structure has a pointer to a grease pencil curve. It will be saved with the stroke to the blend file.
* Most edit mode operators have been changed to work in curve edit mode.
* Transformation code has been adjusted to work for grease pencil curves.
* New source file added (gpencil_edit_curve.c) for operators exclusive to curve edit mode.

Differential Revision: https://developer.blender.org/D8660
2020-08-20 16:53:55 +02:00
632b978af9 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-08-20 10:11:53 +02:00
2be3e78a7b GPencil: Skip unused code with macro 2020-08-20 10:11:15 +02:00
3e4fb5b5f1 GPencil: Add corner angle parameter 2020-08-20 10:10:09 +02:00
585089cdb6 Merge branch 'master' into greasepencil-edit-curve 2020-08-19 19:53:23 +02:00
e3079476f7 Merge branch 'master' into greasepencil-edit-curve 2020-08-19 07:51:55 +02:00
77efb597ce Merge branch 'master' into greasepencil-edit-curve
Conflicts:
	source/blender/editors/gpencil/gpencil_edit.c
2020-08-18 16:13:08 +02:00
de7470645a Merge branch 'master' into greasepencil-edit-curve 2020-08-18 11:03:29 +02:00
3f0e2dba68 Merge branch 'master' into greasepencil-edit-curve 2020-08-17 11:30:00 +02:00
13bbdc10d8 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-08-15 13:12:48 +02:00
4a00c69416 GPencil: Fix add needed gpd reference 2020-08-15 13:12:09 +02:00
8bd1469d86 GPencil: Add corner angle parameter
This parameter allows the user to control at what angle corners are
detected and considered by the fitting algorithm.
2020-08-15 13:10:37 +02:00
8b4f318f92 GPencil: Fix error and warnings after merge 2020-08-15 11:55:59 +02:00
f24a070d7e Merge branch 'master' into greasepencil-edit-curve 2020-08-15 11:14:53 +02:00
57d9453d8b Merge branch 'master' into greasepencil-edit-curve 2020-08-14 17:57:45 +02:00
b221d8d0a3 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-08-14 15:07:07 +02:00
735c717a63 Merge branch 'master' into greasepencil-edit-curve 2020-08-13 16:57:42 +02:00
a0152042b8 GPencil: UI: Move adaptive resolution
Since the adaptive resolution modifies the behaviour of the
curve resolution parameter, it makes more sense to put the checkbox
underneath the curve resolution silder.
2020-08-13 14:27:34 +02:00
cba7391d4a GPencil: Make format 2020-08-13 11:17:25 +02:00
b109537df1 Merge branch 'soc-2020-greasepencil-curve' into greasepencil-edit-curve 2020-08-13 10:21:29 +02:00
2f68c9fc68 Merge branch 'master' into greasepencil-edit-curve 2020-08-13 10:01:23 +02:00
4b93cdc98a Merge branch 'master' into greasepencil-edit-curve
Conflicts:
	source/blender/blenkernel/intern/gpencil_curve.c
2020-08-12 22:57:46 +02:00
c6650146eb GPencil: Extrude middle curve points
Previously, extruding one of the middle points of a curve would only
move the point. Now it creates a new curve from the point selected.
2020-08-12 16:45:03 +02:00
0e2f5614ef Merge branch 'master' into greasepencil-edit-curve 2020-08-11 19:15:22 +02:00
c934bb5f40 GPencil: Refactor: Make return more explicit 2020-08-11 17:29:37 +02:00
98ef4e0e8e Merge branch 'master' into greasepencil-edit-curve 2020-08-11 15:34:19 +02:00
a8cc21f09e GPencil: Recalculate curve when stroke data changed 2020-08-11 13:35:31 +02:00
f3b140cf0a GPencil: Fix lag editing strokes
During the changes for curves, the Hash insert key line was removed by error.
2020-08-11 11:16:08 +02:00
4d53f12d70 Merge branch 'soc-2020-greasepencil-curve' into greasepencil-edit-curve 2020-08-11 10:17:00 +02:00
d19a342966 Merge branch 'master' into greasepencil-edit-curve 2020-08-11 08:19:50 +02:00
f905f4d464 Gpencil: clang format 2020-08-10 22:47:38 +02:00
e1e1b303fa GPencil: Change handle type while transform
For vector and automatic handles we need to change their type to free
and aligned respectively while transforming.
2020-08-10 22:47:22 +02:00
d8b4d81da0 Merge branch 'master' into greasepencil-edit-curve 2020-08-10 15:35:52 +02:00
3190be57eb GPencil: Apply GSoC changes 2020-08-08 18:52:49 +02:00
e99ffb8dcc Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-08-08 16:43:25 +02:00
0ae02b130a GPencil: Split transform code
This commit splits the grease pencil transform code, so that editcurves and strokes get handled separately.
This fixes a bug where in normal edit mode, proportional editing would be very slow.
The center point of the transform is also more predictable and behaves similar to bezier triples in curve objects.
2020-08-08 16:42:02 +02:00
843eccb200 Merge branch 'master' into greasepencil-edit-curve 2020-08-08 12:49:41 +02:00
acd92bfd28 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-08-08 12:04:02 +02:00
c57ce2eb0b Merge branch 'master' into greasepencil-edit-curve 2020-08-05 18:30:29 +02:00
eee9eee0f5 Merge branch 'master' into greasepencil-edit-curve 2020-08-05 11:30:00 +02:00
6197d4dafa Merge branch 'master' into greasepencil-edit-curve 2020-08-04 16:44:16 +02:00
f0ed70eb12 Merge branch 'master' into greasepencil-edit-curve 2020-08-03 12:35:18 +02:00
d6b842205f Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-08-03 00:26:58 +02:00
944ba1b38d GPencil: Add snap to grid for curve points 2020-08-03 00:25:03 +02:00
c825d70811 GPencil: Implement basic extrude support 2020-08-03 00:24:54 +02:00
cd55053e65 Merge branch 'master' into greasepencil-edit-curve 2020-08-01 12:13:08 +02:00
3cae7df33f Merge branch 'master' into greasepencil-edit-curve 2020-08-01 11:20:57 +02:00
39fd500965 Merge branch 'master' into greasepencil-edit-curve 2020-07-31 12:44:31 +02:00
185aa0b2b1 Merge branch 'master' into greasepencil-edit-curve 2020-07-31 12:05:37 +02:00
438378b59d Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-07-30 14:53:42 +02:00
331e1639c4 GPencil: Fix curve point deletion in cyclic curve 2020-07-30 14:52:29 +02:00
045dc2c434 Merge branch 'master' into greasepencil-edit-curve 2020-07-29 10:38:38 +02:00
f2e2913a58 GPencil: Handle single point curve 2020-07-28 11:20:57 +02:00
c73809fbd1 Merge branch 'master' into greasepencil-edit-curve 2020-07-28 09:14:47 +02:00
68bebaf28f Merge branch 'master' into greasepencil-edit-curve 2020-07-27 18:34:04 +02:00
e64504ec04 Merge branch 'master' into greasepencil-edit-curve 2020-07-27 10:49:51 +02:00
0e478f2acc Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-07-27 00:23:56 +02:00
2b9ae89ad8 GPencil: WIP delete curve point 2020-07-25 17:15:56 +02:00
b9267f600e Merge branch 'master' into greasepencil-edit-curve 2020-07-25 16:24:56 +02:00
8045d8b861 GPencil: WIP delete curve points 2020-07-24 19:23:42 +02:00
cb1be5fed6 Merge branch 'master' into greasepencil-edit-curve 2020-07-24 16:24:58 +02:00
075276ee80 GPencil: Implement curve points dissolve 2020-07-23 19:24:24 +02:00
6f0029c87d GPencil: Fix compiler warnings 2020-07-23 17:56:17 +02:00
5d96ed364f GPencil: Apply GSoC changes 2020-07-23 17:54:11 +02:00
b21df4d473 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-07-23 13:59:20 +02:00
48e52c5a5c GPencil: use smooth interpolation
For the pressure, strength and color atributes, use smooth interpolation
to generate the stroke points.
2020-07-23 13:58:49 +02:00
2d9e869b18 GPencil: Fix coordinate influence fitting problem
The coordinates had a two small influence in the curve fitting.
All the values are now normalized and a factor used to make the
shape of the stroke more important.
2020-07-23 13:41:23 +02:00
c18eb01eb6 GPencil: WIP: multi-dimensional curve fitting 2020-07-23 13:41:13 +02:00
416d28323b Merge branch 'master' into greasepencil-edit-curve 2020-07-23 13:16:22 +02:00
d0c9a62904 GPencil: Update defaults for curve resolution 2020-07-22 17:33:29 +02:00
31ffbfd78f Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-07-22 16:11:18 +02:00
f16a50ba94 GPencil: Implement adaptive editcurve resolution
With adaptive curve resolution the arclength of a curve segment is
used to calculate the number of points between two control points.
This means that in general the stroke points are more spaced out.
2020-07-22 16:10:25 +02:00
02786fc761 Merge branch 'master' into greasepencil-edit-curve 2020-07-22 11:19:18 +02:00
ca6b730da1 Merge branch 'master' into greasepencil-edit-curve 2020-07-21 19:15:27 +02:00
fbbd03ae8a GPencil: remove unnecessary variables 2020-07-21 16:02:07 +02:00
ae4f40ef6b GPencil: Fix compiler warnings 2020-07-21 16:00:20 +02:00
e081c624f9 GPencil: Fix errors after merge 2020-07-21 15:58:37 +02:00
46e0b0404a Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-07-21 15:58:10 +02:00
f7a1512bdf GPencil: deselct curve when deselect all 2020-07-21 15:57:42 +02:00
35a6172ddc Merge branch 'master' into greasepencil-edit-curve
Conflicts:
	source/blender/blenkernel/BKE_gpencil_geom.h
	source/blender/blenkernel/intern/gpencil_geom.c
2020-07-21 15:54:19 +02:00
d28575213d Merge branch 'master' into greasepencil-edit-curve 2020-07-20 20:21:56 +02:00
56e88ada83 GPencil: Fix select fill
The function was not working correctly, because it would select
fills where one of the triangles would have a bounding box
large enought that it would intersect the selction.
2020-07-20 15:55:18 +02:00
5330fe4b70 GPencil: Fix select more
The first control point was not being selected due to an
off-by-one error.
2020-07-20 15:47:40 +02:00
fd0fffaede Merge branch 'master' into greasepencil-edit-curve 2020-07-20 11:11:40 +02:00
bc90636f61 GPencil: Disable box/lasso conversion, fill select
These features are currently not working correctly.
Disable them for now.
2020-07-19 13:44:45 +02:00
a98c9e3de9 GPencil: Fix curve points not deslecting 2020-07-19 13:40:00 +02:00
d7ae232dba GPencil: deselect stroke after convert from curve 2020-07-18 22:06:16 +02:00
88b98dfe32 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-07-18 13:06:25 +02:00
8eedcb6f9d GPencil: WIP: convert to curve box/lasso select 2020-07-18 13:05:06 +02:00
84f744719e Merge branch 'master' into greasepencil-edit-curve 2020-07-18 10:34:41 +02:00
237f9bc106 Merge branch 'master' into greasepencil-edit-curve 2020-07-17 16:46:06 +02:00
76dc552989 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-07-17 14:17:56 +02:00
741cd18398 GPencil: Draw edit lines under curve handles 2020-07-17 14:17:30 +02:00
5bac474903 GPencil: Convert to curve with click select 2020-07-17 14:16:28 +02:00
9d69d642ff GPencil: Recalculate curve when entering editmode 2020-07-17 13:36:14 +02:00
8b35bc7743 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-07-16 19:42:39 +02:00
5f87af907d Merge branch 'master' into greasepencil-edit-curve 2020-07-16 17:45:15 +02:00
030e86768b GPencil: Use GPencil Theme colors for Bezier control points
To flag the point the FREESTYLE flag is reused because the limit is 8 flags and all are already use it. As this handles never are displayed at the same time that freestyle is totally sure to reuse it.
2020-07-16 17:24:20 +02:00
0003809105 GPencil: Display edit line sin Curve edit mode 2020-07-16 16:54:32 +02:00
403d20581f GPencil: Fix errors after merge
The parameter list has changed.
2020-07-16 09:17:40 +02:00
aa72aebabe Merge branch 'master' into greasepencil-edit-curve
Conflicts:
	source/blender/blenkernel/intern/gpencil_geom.c
2020-07-16 08:16:01 +02:00
2e23224829 GPencil: Apply all GSoC changes 2020-07-15 12:18:30 +02:00
610a5452c1 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-07-15 12:11:12 +02:00
477fbf4e44 Gpencil: WIP: Update "enter curve edit mode" op 2020-07-15 12:10:33 +02:00
b474c82135 Merge branch 'master' into greasepencil-edit-curve 2020-07-15 12:08:06 +02:00
bd71007ebd GPencil: Implement select more/less curve points 2020-07-15 11:55:18 +02:00
95d0192308 GPencil: Implement select first/last curve point 2020-07-15 11:07:47 +02:00
fcd22007b5 GPencil: Implement select grouped for curves 2020-07-15 10:40:25 +02:00
d0d9490ac0 GPencil: Implement select alternate curve points 2020-07-15 10:14:19 +02:00
7e6b8f693c GPencil: Fix compiler warnings 2020-07-15 10:08:45 +02:00
eb22e7a650 GPencil: Select fill curves
The previous algorithm used the center of the selection to check if the
fill was selected. This uses the triangle data of the fill so it will
be a bit slower, but results in better select behaviour.
2020-07-14 20:59:28 +02:00
d589d50443 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-07-14 16:53:08 +02:00
5122c75fd6 GPencil: Implement box and lasso curve select 2020-07-14 16:52:35 +02:00
3e5910d273 Merge branch 'master' into greasepencil-edit-curve
Conflicts:
	source/blender/editors/gpencil/gpencil_utils.c
	source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
2020-07-14 10:43:13 +02:00
93acaccecb Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-07-13 11:22:33 +02:00
5b49d8b8d0 Merge branch 'master' into greasepencil-edit-curve 2020-07-13 10:39:11 +02:00
91b9f99f04 Clang formatting 2020-07-11 20:43:29 +02:00
529313da75 GPencil: Fix compiler error after merge 2020-07-11 20:38:34 +02:00
9ff1fd96e8 GPencil: Apply GSoC changes
Also run a `make format`for fixing any clang issue
2020-07-11 20:34:19 +02:00
8b1182d6cf Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-07-11 20:30:58 +02:00
04f9959adf Merge branch 'master' into greasepencil-edit-curve 2020-07-11 20:29:57 +02:00
6b12994ccf GPencil: Adapt box and lasso select for editcurve 2020-07-11 18:10:58 +02:00
b822088014 GPencil: Fix curve handles not updating
When the handle types of the first and last handles of a cyclic curve
were changed, the handles did not update correctly.
2020-07-11 17:08:24 +02:00
9fa9ee6136 GPencil: Implement editcurve subdivide
Implement an algorithm to subdivide an editcurve.
2020-07-11 17:00:15 +02:00
2340540c44 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-07-11 13:12:14 +02:00
6fa8efd815 GPencil: Implement curve point circle select 2020-07-11 13:11:34 +02:00
e88c28d1a6 Merge branch 'master' into greasepencil-edit-curve
Conflicts:
	source/blender/blenloader/intern/versioning_290.c
2020-07-10 17:10:53 +02:00
dce8986223 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-07-10 16:37:37 +02:00
6394287b1c GPencil: Adapt edit mode operators for curve edit
Change the rest of the edit mode opearators (c62bc08f) so that they
check if curve edit mode is active (if needed).
2020-07-10 16:32:14 +02:00
596f10a0cf GPencil: Curve mode: Set stroke select flag
Set/unset the selection flag for a stroke, when its curve is selected.
This change is needed so that operators like "change end caps"
work as expected in curve edit mode.
2020-07-09 16:24:04 +02:00
c84773b3fb Merge branch 'master' into greasepencil-edit-curve 2020-07-09 15:48:28 +02:00
785e1ea62a Merge branch 'master' into greasepencil-edit-curve 2020-07-08 11:11:07 +02:00
1682e81257 GPencil: Apply all GSoC changes 2020-07-07 17:31:14 +02:00
b8087a2fa6 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-07-07 17:26:25 +02:00
c62bc08f45 GPencil: Adapt edit operators to curve edit mode
Currently all operators do nothing in curve edit mode, but they should
work normally in edit mode. This is the first step of implementing
the operators in curve edit mode.
2020-07-07 17:25:50 +02:00
987d86a127 Merge branch 'master' into greasepencil-edit-curve 2020-07-07 16:21:58 +02:00
967c5b7da5 GPencil: Adapt select operators to curve edit mode
All select operators now check if curve edit mode is active. These include GPENCIL_OT_select, GPENCIL_OT_select_all, GPENCIL_OT_select_circle, GPENCIL_OT_select_box, GPENCIL_OT_select_lasso, GPENCIL_OT_select_linked, GPENCIL_OT_select_grouped, GPENCIL_OT_select_more, GPENCIL_OT_select_less, GPENCIL_OT_select_first, GPENCIL_OT_select_last, GPENCIL_OT_select_alternate and GPENCIL_OT_select_vertex_color
2020-07-07 15:37:05 +02:00
a0fa831bfe GPencil: Remove error threshold as parameter
Use the error threshold in gpd instead of the operator property.
2020-07-07 10:52:57 +02:00
e6ed400b9a Merge branch 'master' into greasepencil-edit-curve 2020-07-06 20:27:26 +02:00
d1b1eaf9bb Merge branch 'soc-2020-greasepencil-curve' of git.blender.org:blender into soc-2020-greasepencil-curve 2020-07-06 17:20:11 +02:00
68a3c874ce GPencil: Set flag to fit curve to cyclic stroke 2020-07-06 17:19:59 +02:00
ab91491963 GPencil: Recalculating handles for cyclic curves 2020-07-06 17:07:34 +02:00
486a06d71b GPencil: Set handle type for individual handle
Before it was only possible to set the handle type for both handles
of a bezier tripple. Now the user can set the type individually.
2020-07-06 17:06:54 +02:00
fa662dceef GPencil: Support cyclic curves
Generte points between the first and last curve point when
converting a curve to a stroke.
2020-07-06 17:05:05 +02:00
96eca6c3d4 GPencil: Fix selection sync for cyclic strokes 2020-07-06 17:02:49 +02:00
b6f852ecec Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-07-05 17:33:02 +02:00
a960897959 Merge branch 'master' into greasepencil-edit-curve 2020-07-05 17:32:11 +02:00
2575fc9181 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-07-05 15:59:40 +02:00
55a3088775 Merge branch 'master' into greasepencil-edit-curve 2020-07-04 11:05:28 +02:00
9bf6743422 GPencil: Cleanup code - move functions 2020-07-04 11:03:14 +02:00
ff66e7afe8 Merge branch 'master' into greasepencil-edit-curve 2020-07-04 10:00:21 +02:00
591047baef GPencil: Apply GSoC changes 2020-07-04 10:00:08 +02:00
1fca1d9f74 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-07-03 20:57:13 +02:00
04fc48300b Gpencil: Fix compiler warning 2020-07-03 20:56:50 +02:00
2c79315b0f Merge branch 'master' into greasepencil-edit-curve 2020-07-03 20:09:00 +02:00
b645caafa6 GPencil: Implement different color by handle type
Before it was hardcode because only one type was supported.
2020-07-03 20:07:56 +02:00
a18bf89232 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-07-03 17:21:23 +02:00
85a11fd2b3 GPencil: Review of curve <> stroke conversion
This commit introduces a new flag GP_STROKE_NEEDS_CURVE_UPDATE in the stroke
that replaces GP_CURVE_RECALC_GEOMETRY. The name was not consistent and
it didn't make much sense to have it in the editcurve. Another flag was
added: GP_CURVE_NEEDS_STROKE_UPDATE. This indicates that the curve data
is dirty and needs to be regenerated.
2020-07-03 17:20:12 +02:00
02215eaae4 GPencil: remove test operator
This operator has no use and can be safely removed.
2020-07-03 17:13:02 +02:00
f37b34b36c Merge branch 'master' into greasepencil-edit-curve 2020-07-03 15:44:55 +02:00
a36c7e75d7 Gpencil: Fix merge error 2020-07-03 14:06:33 +02:00
3064b8d717 Merge branch 'master' into greasepencil-edit-curve
Conflicts:
	source/blender/blenkernel/intern/gpencil.c
	source/blender/blenkernel/intern/gpencil_geom.c
	source/blender/blenkernel/intern/gpencil_modifier.c
2020-07-03 13:56:02 +02:00
808ee09081 Merge branch 'master' into greasepencil-edit-curve
Conflicts:
	source/blender/blenkernel/intern/gpencil_geom.c
2020-07-03 11:22:00 +02:00
47be2d3fd0 GPencil: Fix crash when moving multiple handles
Fix a crash when selecting multiple handles (without the control point)
and then moving them. This was caused by the function
BKE_gpencil_curve_sync_selection which did not sync the
selection correctly. GP_CURVE_SELECT would not be set in gpc->flag if an
individual handle was selected.
2020-07-02 23:02:26 +02:00
f76851d5c1 GPencil: Fix crash when moveing a point in edit mode 2020-07-02 22:37:09 +02:00
99fa08e94f GPencil: Recalculate curve only in curve edit mode
Using bGPdata in BKE_gpencil_stroke_geometry_update we can check if we
are in curve edit mode and then test if we need to recalculate the curve.
2020-07-02 22:08:05 +02:00
a30af67a44 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-07-02 21:49:53 +02:00
998229d892 GPencil: Skip uneditble layer
Don't sync the selection of strokes on an uneditble layer.
2020-07-02 21:48:02 +02:00
d2933762f2 GPencil: sync selection after recalculating curve 2020-07-02 21:46:17 +02:00
b84cc14b51 GPencil: Refactor, add comments 2020-07-02 21:45:43 +02:00
2dc43b4aca GPencil: Remove end point in Operator description
Operator description never must end in period.
2020-07-02 20:13:30 +02:00
90828164a4 Merge branch 'master' into greasepencil-edit-curve 2020-07-02 20:05:28 +02:00
f32ace6712 GPencil: Rename gp_ to gpencil_ 2020-07-02 20:00:13 +02:00
f708aabf90 GPencil: Pass gpd datablock to BKE_gpencil_stroke_geometry_update
This include the reverts commit 6beb37b197.
2020-07-02 19:47:58 +02:00
99c50da0b7 Merge branch 'master' into greasepencil-edit-curve 2020-07-02 09:32:23 +02:00
3b4f98732d GPencil: Add shortcut to toggle curve edit mode
Its set to 'U' for testing. Can be changed later.
2020-07-01 16:02:17 +02:00
039d8fea23 GPencil: Apply GSoC changes 2020-07-01 13:22:28 +02:00
b40dfe6095 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-07-01 13:18:20 +02:00
52d2afae9d GPencil: Add custom keymap for curve edit mode
Added a keymap handler for curve edit mode. This allows us to set
keybindings when curve edit mode is active. Currently only one
keymap was added: set handle type, which is set to 'V' like everywhere
else.
2020-07-01 12:44:17 +02:00
6a256637b0 GPencil: Refactor: fix comment and function name 2020-07-01 09:31:01 +02:00
e0c89befb0 Merge branch 'master' into greasepencil-edit-curve 2020-07-01 09:17:39 +02:00
3e636c23e8 GPencil: Support all handle types in transform
Basic support for all handle types when transforming in curve edit mode.
2020-07-01 00:45:48 +02:00
64bc6f3942 GPencil: Only allow rotations around control point
Limit the center of rotation to only include the control points
2020-07-01 00:44:34 +02:00
1048abd378 GPencil: Add BKE to recalculate handle positions
This function will update the handle position depending on the handle
type that the BezTriple handles have.
2020-07-01 00:41:55 +02:00
dac85d01d2 GPencil: add set handle type operator for editcurve
This operator sets the handle type of the selected editcurve handles
and updates their positions acordingly.
2020-06-30 19:34:09 +02:00
1792c51bdf GPencil: Cleanup - Apply clang format 2020-06-30 16:21:38 +02:00
493695efd1 GPencil: Apply last GSoC changes 2020-06-30 16:17:21 +02:00
4379942a88 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-06-30 16:08:06 +02:00
467b905dbf GPencil: edit curve: Rename 'gp_' to 'gpencil_' 2020-06-30 16:06:42 +02:00
68a9379127 Merge branch 'master' into greasepencil-edit-curve 2020-06-30 15:49:12 +02:00
b2949942e7 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-06-30 15:04:28 +02:00
7cf16db0a2 Merge branch 'master' into greasepencil-edit-curve 2020-06-29 20:20:01 +02:00
2fcdebcc4e Merge branch 'master' into greasepencil-edit-curve
Conflicts:
	source/blender/editors/gpencil/gpencil_select.c
2020-06-29 15:53:45 +02:00
905c94df2d Merge branch 'master' into greasepencil-edit-curve 2020-06-28 16:56:28 +02:00
5a804e3d6f Merge branch 'master' into greasepencil-edit-curve
Conflicts:
	source/blender/editors/gpencil/gpencil_select.c
	source/blender/editors/gpencil/gpencil_utils.c
2020-06-28 11:31:37 +02:00
bc540c57f4 GPencil: Fix selection 2020-06-27 14:31:01 +02:00
73bded4cc6 Merge branch 'soc-2020-greasepencil-curve' of git.blender.org:blender into soc-2020-greasepencil-curve 2020-06-27 13:28:24 +02:00
b5640df6c0 Merge branch 'master' into greasepencil-edit-curve 2020-06-26 12:57:10 +02:00
302499b4a6 Merge branch 'master' into greasepencil-edit-curve 2020-06-25 15:40:40 +02:00
308b203578 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-06-25 11:09:27 +02:00
1e2c87b951 Merge branch 'master' into greasepencil-edit-curve 2020-06-24 16:02:41 +02:00
8cf1479f02 GPencil: Update point index when stroke is updated 2020-06-23 21:35:28 +02:00
995ea2004a Merge branch 'master' into greasepencil-edit-curve 2020-06-23 19:26:25 +02:00
ff3b9d63cb Merge branch 'master' into greasepencil-edit-curve 2020-06-23 16:29:14 +02:00
708ee8d75e Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-06-23 16:01:31 +02:00
78a38f1ec9 GPencil: Selection syncing from/to curve edit mode 2020-06-23 16:00:51 +02:00
769468d125 Merge branch 'master' into greasepencil-edit-curve 2020-06-22 19:47:04 +02:00
1f9965f852 GPencil: WIP: sync selection 2020-06-22 16:10:36 +02:00
aae29a6565 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-06-22 11:20:31 +02:00
f137b897d0 GPencil: Fix compiler warnings 2020-06-22 11:04:16 +02:00
476afb643a GPencil: Fix errors after merge 2020-06-22 11:03:15 +02:00
44173c60fc Merge branch 'master' into greasepencil-edit-curve
Conflicts:
	source/blender/editors/gpencil/gpencil_select.c
2020-06-22 10:57:20 +02:00
a50528ac42 Merge branch 'master' into greasepencil-edit-curve 2020-06-21 15:56:43 +02:00
1b09363d0f Merge branch 'master' into greasepencil-edit-curve 2020-06-20 11:58:16 +02:00
882ffe6a2e GPencil: Hide curve points when the curve in unselected
The points are displayed only if the stroke is selected or if the stroke is unselected but the Handles display mode is ALL.
2020-06-20 11:57:50 +02:00
681aaa32af GPencil: Add Curve Select prop to RNA
This prop is similar to Stroke select.
2020-06-20 10:31:44 +02:00
4a26045a9c Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-06-19 23:07:48 +02:00
028f97ed32 Merge branch 'master' into greasepencil-edit-curve 2020-06-19 23:04:41 +02:00
69e4e9c0c4 GPencil: Apply GSoC changes 2020-06-19 22:57:05 +02:00
82ae1d6d7a Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-06-19 20:46:54 +02:00
74fdcd6673 GPencil: Fix pressure and strength not updateing
Handles could be scaled, but the data was not written back to the
stroke. This fixes this issue by forceing a recalc after the data has
been written to the curve.
2020-06-19 20:46:23 +02:00
6bacfd3baa GPencil: Transformation of handles
Implemented free transformation of edit curve handles.
2020-06-19 20:44:53 +02:00
2d32dd0632 GPencil: Fix error threshold not showing in panel 2020-06-19 20:43:01 +02:00
74c46d11a0 Merge branch 'master' into greasepencil-edit-curve
Conflicts:
	source/blender/blenloader/intern/versioning_290.c
2020-06-19 19:45:05 +02:00
864df7730e Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-06-19 17:08:41 +02:00
915f80ad48 GPencil: Add transform of curve control points
This ignores handles for now. Only transforms control points.
2020-06-19 17:07:56 +02:00
0ba1d68c30 GPencil: Apply GSoC changes 2020-06-19 10:34:14 +02:00
ff52d7f756 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-06-19 10:14:39 +02:00
3536a2aac4 Merge branch 'master' into greasepencil-edit-curve 2020-06-18 20:35:31 +02:00
fc0ac4c032 GPencil: Selection and toggle selection of handles 2020-06-17 23:43:21 +02:00
70421bbe34 GPencil: Add point selection for curve handles 2020-06-17 23:01:37 +02:00
cc31b03417 GPencil: deselect all on curve edit mode exit
This is a temporary change. Selection syncing is planned for later
2020-06-17 23:01:14 +02:00
944d2f1b81 GPencil: Add curve iteration macro 2020-06-17 22:59:49 +02:00
592a833d96 GPencil: Add sync selection BKE for edit curves 2020-06-17 22:55:10 +02:00
362618ec0b GPencil: Apply all GSoC changes 2020-06-17 10:20:24 +02:00
15a065d318 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-06-16 19:54:08 +02:00
8bc6f574f8 GPencil: Add prop error threshold to select all
The error threshold for the curve fitting can be changed, when a
stroke that has no editcurve yet, is selected.
2020-06-16 19:53:35 +02:00
11e4742da9 GPencil: Change default threshold error 2020-06-16 19:51:40 +02:00
dff7a25891 GPencil: Fix compiler error after merge 2020-06-16 19:31:51 +02:00
1aa7698662 Merge branch 'master' into greasepencil-edit-curve
Conflicts:
	source/blender/blenkernel/intern/gpencil_geom.c
2020-06-16 19:27:55 +02:00
3cbfe47a6d Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-06-16 09:47:40 +02:00
46477fc5d7 GPencil: Add operator to enter strokes into curve edit mdoe
This operator creates an editcurve for all selected strokes that
do not have an editcurve already.
2020-06-16 09:46:59 +02:00
e055c0e285 GPencil: Use error_threshold parameter in gpd 2020-06-16 09:45:32 +02:00
9b8b1c8713 GPencil: Fix compiler errors after merge 2020-06-15 12:32:48 +02:00
f078b55485 Merge branch 'master' into greasepencil-edit-curve 2020-06-15 11:50:29 +02:00
213ba56cf6 Merge branch 'master' into greasepencil-edit-curve 2020-06-15 10:31:25 +02:00
9570f4bbd4 GPencil: Apply all GSoC changes 2020-06-14 13:34:32 +02:00
dc428a05fa Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-06-14 13:28:40 +02:00
a424960c06 GPencil: Refactor BKE_gpencil_selected_strokes_editcurve_update 2020-06-14 13:24:51 +02:00
110ad192a7 GPencil: Fix selection of BezTriple 2020-06-14 13:24:27 +02:00
9b4eb0739b GPencil: Replace loops by FOREACH macro 2020-06-14 12:39:11 +02:00
01c52179e5 GPencil: update the stroke after they are fitted to a curve 2020-06-14 12:17:23 +02:00
4cdd9bc497 GPencil: update the stroke after they are fitted to a curve 2020-06-14 12:16:06 +02:00
3cae796db0 GPencil: New macro to invert handles selection 2020-06-13 16:28:26 +02:00
a4b7d5568a Merge branch 'master' into greasepencil-edit-curve 2020-06-13 15:39:04 +02:00
f395cad4a3 GPencil: Fix compiler errors 2020-06-13 15:20:33 +02:00
7a785786bb Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-06-12 21:13:28 +02:00
6f0f441b9f GPencil: Fix crash, pointer to BezTriple was set wrong 2020-06-12 21:13:00 +02:00
065cec17e7 GPencil: Apply GSoC changes 2020-06-12 20:42:19 +02:00
1c7019e088 GPencil: Increase hard limit for curve resolution 2020-06-12 20:40:43 +02:00
c50199a352 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-06-12 20:39:36 +02:00
fd62421c9c GPencil: Implement interpolation for point props
Implement interpolation for point pressure, strength and vertex
color. Currently this uses linear interpolation.
2020-06-12 20:37:50 +02:00
279c4ba199 GPencil: Change update function for curve point props 2020-06-12 20:36:26 +02:00
0b56b60522 GPencil: Cleanup comment lines 2020-06-12 20:25:25 +02:00
6beb37b197 Revert "GPencil: Pass gpd datablock to BKE_gpencil_stroke_geometry_update"
This reverts commit 6a2a5b4589.

Also, some minor tweaks due conflicts
2020-06-12 20:16:55 +02:00
fb9d9130ee Merge branch 'master' into greasepencil-edit-curve 2020-06-12 15:58:10 +02:00
def72c7dcc Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-06-12 13:52:33 +02:00
cf4c3a72ed GPencil: Add curve point data structure
The BezTriple in bGPDcurve was changed to a new data structure: bGPDcurve_point. The RNA properties where adapted to support the new data structure.
2020-06-12 13:37:36 +02:00
01b43c53ff GPencil: Moves Curve Threshold to bGPdata 2020-06-12 13:27:12 +02:00
788efae56b GPencil: Cleanup code 2020-06-12 12:20:39 +02:00
7c825b6665 GPencil: Make editable Curve Editing props when disabled
Some parameters can be required before set to ON the mode, so now it's possible update these parameters before.
2020-06-12 11:25:00 +02:00
903bdac374 GPencil: Update last GSoC branch changes 2020-06-12 11:19:07 +02:00
307a68b91a Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-06-12 11:05:59 +02:00
de52a9c9f4 GPencil: Use resolution parameter
Use the curve resolution parameter in the stroke option panel
to control how many segments are generated from the edit curve.
2020-06-12 11:02:28 +02:00
b94abe6785 GPencil: Add Resolution prop to Curve Editing popover 2020-06-12 10:42:32 +02:00
58d06191fb Merge branch 'master' into greasepencil-edit-curve 2020-06-12 10:33:13 +02:00
1f98596023 GPencil: New Error Threshold parameter
This parameter is used to determine how precise is the curve conversion.
2020-06-12 10:32:51 +02:00
3b34d7a42d GPencil: Fix compiler warning
This is temp hack.
2020-06-11 20:41:01 +02:00
7cc8832ff1 GPencil: More transform cleanup and add is_curve_edit flag check
This is in preparation for transform Bezier handles
2020-06-11 20:39:38 +02:00
3fabcd3458 Merge branch 'master' into greasepencil-edit-curve 2020-06-11 20:36:21 +02:00
55e270878a GPencil: Change UI text Curve Editing 2020-06-11 17:54:03 +02:00
743e6c8750 GPencil: Change UI text
"Resolution" to "Curve Resolution"
2020-06-11 17:25:19 +02:00
97e9b953a4 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-06-11 17:22:06 +02:00
c7bb14f175 GPencil: WIP use resolution parameter, pressure and strength 2020-06-11 17:18:38 +02:00
94e68f4caa GPencil: Add resolution parameter to bGPDcurve 2020-06-11 17:16:26 +02:00
0f2ee2664f Merge branch 'master' into greasepencil-edit-curve 2020-06-11 17:13:53 +02:00
c2f3deb8bd GPencil: Initialize curve resolution for new objects 2020-06-11 17:06:29 +02:00
fa02e9e84d GPencil: Add resolution to strokes panel 2020-06-11 17:06:14 +02:00
3e66f03b86 GPencil: Move geometry functions to right module
These functions were not moved in a previous refactor
2020-06-11 16:47:18 +02:00
6a2a5b4589 GPencil: Pass gpd datablock to BKE_gpencil_stroke_geometry_update
This is needed to get curve edit data parameters
2020-06-11 16:47:12 +02:00
f872c6a8fe GPencil: Add new edit_curve_resolution prop
This will be used to define the qualitty of the generated stroke.
2020-06-11 16:47:05 +02:00
e821b96f3a Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-06-11 12:23:02 +02:00
15669c1c02 GPencil: Convert from curve to stroke in update_geometry
Call the function BKE_gpencil_stroke_update_geometry_from_editcurve
in BKE_gpencil_stroke_geometry_update and force
an update when curve handles change position in RNA.
2020-06-11 12:22:06 +02:00
d87d5f7801 GPencil: Add function to convert curve to stroke
This BKE takes the current editcurve of a stroke, then samples
a number of points on the curve and writes these points
back to the stroke points.
2020-06-11 12:19:28 +02:00
c70dcf9f85 Merge branch 'master' into greasepencil-edit-curve 2020-06-11 10:43:19 +02:00
8882abe767 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-06-10 19:42:13 +02:00
c6185e7693 GPencil: Disable modifiers when Curve Edit is enabled
The handles edition is incompatible with the modifiers due the logic used to recreate the stroke when is editted with handles.
2020-06-10 19:34:48 +02:00
16f5c480d7 Merge branch 'master' into greasepencil-edit-curve 2020-06-10 19:31:23 +02:00
64c0fe90b8 GPencil: Add select more/less for curve points 2020-06-10 17:31:18 +02:00
823d26ea3a GPencil: Use BezTriple selection marcos 2020-06-10 17:30:59 +02:00
073ed552ac Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-06-10 15:15:38 +02:00
7e91d4302d Merge branch 'master' into greasepencil-edit-curve 2020-06-10 11:46:20 +02:00
3579f1be2c Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-06-09 20:03:08 +02:00
ffe6a79c61 GPencil: Remove stroke Curve flag
Not needed
2020-06-09 20:00:06 +02:00
1b917609c0 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-06-09 19:58:11 +02:00
62828dee3c GPencil: todo error threshold should be parameter 2020-06-09 19:56:56 +02:00
9016ba041f GPencil: Implement 'select linked' for editcurve 2020-06-09 19:56:08 +02:00
9d078a02d2 Merge branch 'master' into greasepencil-edit-curve 2020-06-09 19:48:31 +02:00
88daf0fdf6 GPencil: Apply all GSOC changes 2020-06-09 19:35:16 +02:00
c0deb49bde Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-06-09 18:03:16 +02:00
b71ebc4c27 GPencil: Calculate curve when switching to edit curve mode 2020-06-09 18:02:31 +02:00
6a66ca5318 GPencil: Remove not needed macros and functions
Remove marco and function that was no longer needed and use
newer BKE function.
2020-06-09 18:01:57 +02:00
beb655cf7b GPencil: Add update functions for the editcurve
Add new functions that will refir the curve to the grease pencil stroke.
2020-06-09 18:00:18 +02:00
085a59ae6f GPencil: Remove curve flag and replace with RNA dynamic prop
We don't need this flag because we can check the struct pointer itself.
2020-06-09 16:15:47 +02:00
7df5a41d2b GPencil: FIx flag GP_STROKE_CURVE_MODE
The flag was set to 2^11 and it was 2^16 before. The type of the flag is short, so it was
never actually beeing set.
2020-06-09 15:40:38 +02:00
b96a1ac263 GPencil: Add 'select all' operator for curve
Change the 'select all' operator so that, if the stroke
is in curve edit mode, it selects the curve handles.
2020-06-09 14:31:52 +02:00
6cd634b94f GPencil: Use curve fitting write data for operator
Instead of writing test data to editcurve, use the
BKE_gpencil_stroke_curve_create function to write fitted
curve data to editcurve.
2020-06-09 14:28:18 +02:00
5830201294 GPencil: Add function to create editcurve from stroke
This BKE function uses curve_fit_cubic_to_points_fl to fit a curve
to a grease pencil stroke.
2020-06-09 14:23:33 +02:00
d63757e28b GPencil: Write operator creates two curve points
The dummy operator that writes data to the editcurve
of a bGPDstroke now writes two curve points. One for the first stroke
point and one for the last stroke point.
2020-06-08 18:59:46 +02:00
8bf4f78c8e GPencil: Remove duplicated toggle button code 2020-06-08 18:57:02 +02:00
f345d94efb Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-06-08 11:12:17 +02:00
eff629aaad Merge branch 'master' into greasepencil-edit-curve 2020-06-08 09:09:37 +02:00
53a9446b71 GPencil: Cleanup comment 2020-06-07 19:10:14 +02:00
9982d1bc09 GPencil: First test to create handles drawing
Basic structure
2020-06-07 19:03:17 +02:00
9ce9960f10 GPencil: Add RNA update when change handles data 2020-06-07 17:49:03 +02:00
9cac03cb21 GPencil: Add point index array RNA property
This property should be used for debugging purposes.
2020-06-07 17:45:31 +02:00
f99d2e8068 GPencil: Fix merge errors 2020-06-07 15:57:34 +02:00
96e1b26658 Merge branch 'master' into greasepencil-edit-curve 2020-06-07 13:26:47 +02:00
3696ecb0f6 GPencil: Add point index array RNA property
This property should be used for debugging purposes.
2020-06-06 16:50:11 +02:00
c60c721b5d GPencil: New prop to determine if a stroke is using Curve Edit mode
This flag will be used to determine if the selection must be done for points to generate handles or the handles are already visibles.
2020-06-06 12:26:47 +02:00
89724fb52d Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-06-06 12:10:57 +02:00
3cdf852425 GPencil: Fix Selection mode buttons in Beziser submode
Also changed the BEZIER flag bit becaus ethe previous was already used.
2020-06-06 11:53:00 +02:00
5eab1b3f21 GPencil: Include last GSoC commits
Minor update due merge error in writefile.c
2020-06-06 11:18:41 +02:00
be1f9284c1 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-06-06 11:00:40 +02:00
410703aa1a GPencil: Add edit curve mode toggle button 2020-06-06 10:59:06 +02:00
8a686f9ced Merge branch 'master' into greasepencil-edit-curve 2020-06-06 10:24:20 +02:00
39560f5285 Merge branch 'master' into greasepencil-edit-curve 2020-06-06 08:23:45 +02:00
a37a93dc52 GPencil: Fix writing of bGPDcurve struct.
Previously, the bGPDcurve struct itself was not written,
only the data that is referenced inside the struct
2020-06-05 16:14:36 +02:00
f503190be4 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-06-05 15:44:11 +02:00
d0b1606c0d GPencil: Fix wrong write_struct code
This is going to be replaced by new code, but it's better keep the right one.
2020-06-05 15:42:27 +02:00
6dc2ac9ecf GPencil: Fix merge errors 2020-06-05 15:24:15 +02:00
2c4a1fc84d Merge branch 'master' into greasepencil-edit-curve
Conflicts:
	source/blender/blenloader/intern/writefile.c
2020-06-05 15:14:10 +02:00
7c5d6d6074 GPencil: Fix read/load of bGPDcurve.
Remove unnessesary code when reading bGPDcurve struct.
Fix the size of array when writing bGPDCurve struct.
2020-06-05 10:21:57 +02:00
435288d48e Merge branch 'master' into greasepencil-edit-curve 2020-06-04 18:48:57 +02:00
f17e84e1e1 Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-06-04 16:39:59 +02:00
7ea8d3ed39 Merge branch 'master' into greasepencil-edit-curve 2020-06-04 09:42:35 +02:00
af2d86dc2c GPencil: Add num_points property to test operator 2020-06-03 22:27:23 +02:00
b03a479efd GPencil: Add curve point RNA structure 2020-06-03 19:06:18 +02:00
b4ba2458ae Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-06-03 17:22:20 +02:00
d8cbcf4e64 GPencil: Add curve point collection RNA to gp stroke 2020-06-03 17:21:22 +02:00
17f122b913 GPencil: Test write operator only writes to selected strokes
Now the operator will only write to selected strokes and also free previously allocated data.
2020-06-03 17:20:36 +02:00
705c2e81db GPencil: Fix duplicate code 2020-06-03 17:19:10 +02:00
d436ffd68f GPencil: Fixed stroke duplicate kernel function 2020-06-03 16:17:47 +02:00
b099b9035f Merge branch 'master' into greasepencil-edit-curve 2020-06-03 15:59:58 +02:00
b1f2825ce1 GPencil: Add function to write sample data to edit curve 2020-06-03 10:04:02 +02:00
3096fa7f02 GPencil: Change bGPDcurve struct to hold array of BezTriple 2020-06-03 10:00:59 +02:00
67269b82b2 GPencil: Add BKE function to free editcurve 2020-06-03 09:57:20 +02:00
54d02e6acf Merge branch 'greasepencil-edit-curve' into soc-2020-greasepencil-curve 2020-06-02 10:12:22 +02:00
e485836b3a GPencil: created a new file for edit curve mode operators
This new file will hold all the operators for curve edit mode.
Initially only one dummy operator was moved from gpencil_edit
to this file.
2020-06-01 18:51:50 +02:00
5f6bc522b8 GPencil: Added a dummy operator to test curve data
The main purpose for this operator is to test the curve data structure
that was added to the stroke data structure.
2020-06-01 17:55:20 +02:00
be7e61b31f GPencil: New Curve Edit submode flag
Also created the macro GPENCIL_CURVE_EDIT_SESSIONS_ON to make easier to check the submode.
2020-06-01 17:29:41 +02:00
56166b6ad4 GPencil: Initial code to Write and Read curve data 2020-06-01 17:12:35 +02:00
ca06bcdcbf GPencil: Basic structure for the Bezier Editing
This is the minimum data we need to create the Bezier Curve.
2020-06-01 16:07:10 +02:00
5cc3ae6f75 Merge branch 'master' into greasepencil-edit-curve 2020-06-01 15:24:45 +02:00
0892174b63 Merge branch 'master' into greasepencil-edit-curve 2020-05-27 18:41:30 +02:00
63 changed files with 5355 additions and 1081 deletions

View File

@@ -191,6 +191,7 @@ _km_hierarchy = [
]),
('Grease Pencil', 'EMPTY', 'WINDOW', [ # grease pencil stuff (per region)
('Grease Pencil Stroke Curve Edit Mode', 'EMPTY', 'WINDOW', []),
('Grease Pencil Stroke Edit Mode', 'EMPTY', 'WINDOW', []),
('Grease Pencil Stroke Paint (Draw brush)', 'EMPTY', 'WINDOW', []),
('Grease Pencil Stroke Paint (Fill)', 'EMPTY', 'WINDOW', []),

View File

@@ -3226,6 +3226,9 @@ def km_grease_pencil_stroke_edit_mode(params):
{"properties": [("mode", 'GPENCIL_OPACITY')]}),
# Proportional editing.
*_template_items_proportional_editing(connected=True),
# Curve edit mode toggle.
("wm.context_toggle", {"type": 'U', "value": 'PRESS'},
{"properties": [("data_path", 'gpencil_data.use_curve_edit')]}),
# Add menu
("object.gpencil_add", {"type": 'A', "value": 'PRESS', "shift": True}, None),
# Vertex group menu
@@ -3253,6 +3256,20 @@ def km_grease_pencil_stroke_edit_mode(params):
return keymap
def km_grease_pencil_stroke_curve_edit_mode(params):
items = []
keymap = (
"Grease Pencil Stroke Curve Edit Mode",
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
{"items": items},
)
items.extend([
# Set handle type
("gpencil.stroke_editcurve_set_handle_type", {"type": 'V', "value": 'PRESS'}, None),
])
return keymap
def km_grease_pencil_stroke_paint_mode(params):
items = []
@@ -6890,6 +6907,7 @@ def generate_keymaps(params=None):
# Modes.
km_grease_pencil(params),
km_grease_pencil_stroke_curve_edit_mode(params),
km_grease_pencil_stroke_edit_mode(params),
km_grease_pencil_stroke_paint_mode(params),
km_grease_pencil_stroke_paint_draw_brush(params),

View File

@@ -369,6 +369,8 @@ class DATA_PT_gpencil_strokes(DataButtonsPanel, Panel):
sub.active = gpd.stroke_thickness_space == 'WORLDSPACE'
sub.prop(gpd, "pixel_factor", text="Thickness Scale")
col.prop(gpd, "edit_curve_resolution")
class DATA_PT_gpencil_display(DataButtonsPanel, Panel):
bl_label = "Viewport Display"

View File

@@ -661,7 +661,23 @@ class VIEW3D_HT_header(Header):
# Select mode for Editing
if gpd.use_stroke_edit_mode:
row = layout.row(align=True)
row.prop(tool_settings, "gpencil_selectmode_edit", text="", expand=True)
row.prop_enum(tool_settings, "gpencil_selectmode_edit", text="", value='POINT')
row.prop_enum(tool_settings, "gpencil_selectmode_edit", text="", value='STROKE')
subrow = row.row(align=True)
subrow.enabled = not gpd.use_curve_edit
subrow.prop_enum(tool_settings, "gpencil_selectmode_edit", text="", value='SEGMENT')
# Curve edit submode
row = layout.row(align=True)
row.prop(gpd, "use_curve_edit", text="",
icon='IPO_BEZIER')
sub = row.row(align=True)
sub.active = gpd.use_curve_edit
sub.popover(
panel="VIEW3D_PT_gpencil_curve_edit",
text="Curve Editing",
)
# Select mode for Sculpt
if gpd.is_stroke_sculpt_mode:
@@ -687,7 +703,7 @@ class VIEW3D_HT_header(Header):
row.prop(gpd, "use_multiedit", text="", icon='GP_MULTIFRAME_EDITING')
sub = row.row(align=True)
sub.active = gpd.use_multiedit
sub.enabled = gpd.use_multiedit
sub.popover(
panel="VIEW3D_PT_gpencil_multi_frame",
text="Multiframe",
@@ -6802,6 +6818,12 @@ class VIEW3D_PT_overlay_gpencil_options(Panel):
layout.prop(overlay, "vertex_opacity", text="Vertex Opacity", slider=True)
# Handles for Curve Edit
if context.object.mode == 'EDIT_GPENCIL':
gpd = context.object.data
if gpd.use_curve_edit:
layout.prop(overlay, "display_handle", text="Handles")
if context.object.mode in {'PAINT_GPENCIL', 'VERTEX_GPENCIL'}:
layout.label(text="Vertex Paint")
row = layout.row()
@@ -6965,6 +6987,24 @@ class VIEW3D_PT_gpencil_multi_frame(Panel):
layout.template_curve_mapping(settings, "multiframe_falloff_curve", brush=True)
# Grease Pencil Object - Curve Editing tools
class VIEW3D_PT_gpencil_curve_edit(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'HEADER'
bl_label = "Curve Editing"
def draw(self, context):
gpd = context.gpencil_data
settings = context.tool_settings.gpencil_sculpt
layout = self.layout
col = layout.column(align=True)
col.prop(gpd, "edit_curve_resolution")
col.prop(gpd, "curve_edit_threshold")
col.prop(gpd, "curve_edit_corner_angle")
col.prop(gpd, "use_adaptive_curve_resolution")
class VIEW3D_MT_gpencil_edit_context_menu(Menu):
bl_label = ""
@@ -7606,6 +7646,7 @@ classes = (
VIEW3D_PT_grease_pencil,
VIEW3D_PT_annotation_onion,
VIEW3D_PT_gpencil_multi_frame,
VIEW3D_PT_gpencil_curve_edit,
VIEW3D_PT_quad_view,
VIEW3D_PT_view3d_stereo,
VIEW3D_PT_shading,

View File

@@ -48,6 +48,7 @@ struct bGPDlayer;
struct bGPDlayer_Mask;
struct bGPDspoint;
struct bGPDstroke;
struct bGPDcurve;
struct bGPdata;
#define GPENCIL_SIMPLIFY(scene) ((scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ENABLE))
@@ -89,6 +90,7 @@ struct bGPdata;
void BKE_gpencil_free_point_weights(struct MDeformVert *dvert);
void BKE_gpencil_free_stroke_weights(struct bGPDstroke *gps);
void BKE_gpencil_free_stroke_editcurve(struct bGPDstroke *gps);
void BKE_gpencil_free_stroke(struct bGPDstroke *gps);
bool BKE_gpencil_free_strokes(struct bGPDframe *gpf);
void BKE_gpencil_free_frames(struct bGPDlayer *gpl);
@@ -102,6 +104,7 @@ void BKE_gpencil_batch_cache_dirty_tag(struct bGPdata *gpd);
void BKE_gpencil_batch_cache_free(struct bGPdata *gpd);
void BKE_gpencil_stroke_sync_selection(struct bGPDstroke *gps);
void BKE_gpencil_curve_sync_selection(struct bGPDstroke *gps);
struct bGPDframe *BKE_gpencil_frame_addnew(struct bGPDlayer *gpl, int cframe);
struct bGPDframe *BKE_gpencil_frame_addcopy(struct bGPDlayer *gpl, int cframe);
@@ -111,7 +114,10 @@ struct bGPdata *BKE_gpencil_data_addnew(struct Main *bmain, const char name[]);
struct bGPDframe *BKE_gpencil_frame_duplicate(const struct bGPDframe *gpf_src);
struct bGPDlayer *BKE_gpencil_layer_duplicate(const struct bGPDlayer *gpl_src);
void BKE_gpencil_frame_copy_strokes(struct bGPDframe *gpf_src, struct bGPDframe *gpf_dst);
struct bGPDstroke *BKE_gpencil_stroke_duplicate(struct bGPDstroke *gps_src, const bool dup_points);
struct bGPDcurve *BKE_gpencil_stroke_curve_duplicate(struct bGPDcurve *gpc_src);
struct bGPDstroke *BKE_gpencil_stroke_duplicate(struct bGPDstroke *gps_src,
const bool dup_points,
const bool dup_curve);
struct bGPdata *BKE_gpencil_data_duplicate(struct Main *bmain,
const struct bGPdata *gpd,
@@ -160,6 +166,8 @@ struct bGPDstroke *BKE_gpencil_stroke_add_existing_style(struct bGPDframe *gpf,
int totpoints,
short thickness);
struct bGPDcurve *BKE_gpencil_stroke_editcurve_new(const int tot_curve_points);
/* Stroke and Fill - Alpha Visibility Threshold */
#define GPENCIL_ALPHA_OPACITY_THRESH 0.001f
#define GPENCIL_STRENGTH_MIN 0.003f
@@ -247,6 +255,7 @@ float BKE_gpencil_multiframe_falloff_calc(
void BKE_gpencil_palette_ensure(struct Main *bmain, struct Scene *scene);
bool BKE_gpencil_from_image(struct SpaceImage *sima,
struct bGPdata *gpd,
struct bGPDframe *gpf,
const float size,
const bool mask);

View File

@@ -30,6 +30,10 @@ extern "C" {
struct Main;
struct Object;
struct Scene;
struct bGPdata;
struct bGPDlayer;
struct bGPDstroke;
struct bGPDcurve;
void BKE_gpencil_convert_curve(struct Main *bmain,
struct Scene *scene,
@@ -39,6 +43,23 @@ void BKE_gpencil_convert_curve(struct Main *bmain,
const float scale_thickness,
const float sample);
struct bGPDcurve *BKE_gpencil_stroke_editcurve_generate(struct bGPDstroke *gps,
const float error_threshold,
const float corner_angle,
const float stroke_radius);
void BKE_gpencil_stroke_editcurve_update(struct bGPdata *gpd,
struct bGPDlayer *gpl,
struct bGPDstroke *gps);
void BKE_gpencil_editcurve_stroke_sync_selection(struct bGPDstroke *gps, struct bGPDcurve *gpc);
void BKE_gpencil_stroke_editcurve_sync_selection(struct bGPDstroke *gps, struct bGPDcurve *gpc);
void BKE_gpencil_strokes_selected_update_editcurve(struct bGPdata *gpd);
void BKE_gpencil_strokes_selected_sync_selection_editcurve(struct bGPdata *gpd);
void BKE_gpencil_stroke_update_geometry_from_editcurve(struct bGPDstroke *gps,
const uint resolution,
const bool is_adaptive);
void BKE_gpencil_editcurve_recalculate_handles(struct bGPDstroke *gps);
void BKE_gpencil_editcurve_subdivide(struct bGPDstroke *gps, const int cuts);
#ifdef __cplusplus
}
#endif

View File

@@ -51,11 +51,17 @@ void BKE_gpencil_stroke_boundingbox_calc(struct bGPDstroke *gps);
/* stroke geometry utilities */
void BKE_gpencil_stroke_normal(const struct bGPDstroke *gps, float r_normal[3]);
void BKE_gpencil_stroke_simplify_adaptive(struct bGPDstroke *gps, float epsilon);
void BKE_gpencil_stroke_simplify_fixed(struct bGPDstroke *gps);
void BKE_gpencil_stroke_subdivide(struct bGPDstroke *gps, int level, int type);
bool BKE_gpencil_stroke_trim(struct bGPDstroke *gps);
void BKE_gpencil_stroke_merge_distance(struct bGPDframe *gpf,
void BKE_gpencil_stroke_simplify_adaptive(struct bGPdata *gpd,
struct bGPDstroke *gps,
float epsilon);
void BKE_gpencil_stroke_simplify_fixed(struct bGPdata *gpd, struct bGPDstroke *gps);
void BKE_gpencil_stroke_subdivide(struct bGPdata *gpd,
struct bGPDstroke *gps,
int level,
int type);
bool BKE_gpencil_stroke_trim(struct bGPdata *gpd, struct bGPDstroke *gps);
void BKE_gpencil_stroke_merge_distance(struct bGPdata *gpd,
struct bGPDframe *gpf,
struct bGPDstroke *gps,
const float threshold,
const bool use_unselected);
@@ -72,7 +78,7 @@ void BKE_gpencil_stroke_2d_flat_ref(const struct bGPDspoint *ref_points,
const float scale,
int *r_direction);
void BKE_gpencil_stroke_fill_triangulate(struct bGPDstroke *gps);
void BKE_gpencil_stroke_geometry_update(struct bGPDstroke *gps);
void BKE_gpencil_stroke_geometry_update(struct bGPdata *gpd, struct bGPDstroke *gps);
void BKE_gpencil_stroke_uv_update(struct bGPDstroke *gps);
void BKE_gpencil_transform(struct bGPdata *gpd, const float mat[4][4]);
@@ -91,19 +97,26 @@ void BKE_gpencil_point_coords_apply_with_mat4(struct bGPdata *gpd,
const GPencilPointCoordinates *elem_data,
const float mat[4][4]);
bool BKE_gpencil_stroke_sample(struct bGPDstroke *gps, const float dist, const bool select);
bool BKE_gpencil_stroke_sample(struct bGPdata *gpd,
struct bGPDstroke *gps,
const float dist,
const bool select);
bool BKE_gpencil_stroke_smooth(struct bGPDstroke *gps, int i, float inf);
bool BKE_gpencil_stroke_smooth_strength(struct bGPDstroke *gps, int point_index, float influence);
bool BKE_gpencil_stroke_smooth_thickness(struct bGPDstroke *gps, int point_index, float influence);
bool BKE_gpencil_stroke_smooth_uv(struct bGPDstroke *gps, int point_index, float influence);
bool BKE_gpencil_stroke_close(struct bGPDstroke *gps);
void BKE_gpencil_dissolve_points(struct bGPDframe *gpf, struct bGPDstroke *gps, const short tag);
void BKE_gpencil_dissolve_points(struct bGPdata *gpd,
struct bGPDframe *gpf,
struct bGPDstroke *gps,
const short tag);
bool BKE_gpencil_stroke_stretch(struct bGPDstroke *gps, const float dist, const float tip_length);
bool BKE_gpencil_stroke_trim_points(struct bGPDstroke *gps,
const int index_from,
const int index_to);
bool BKE_gpencil_stroke_split(struct bGPDframe *gpf,
bool BKE_gpencil_stroke_split(struct bGPdata *gpd,
struct bGPDframe *gpf,
struct bGPDstroke *gps,
const int before_index,
struct bGPDstroke **remaining_gps);

View File

@@ -155,6 +155,11 @@ static void greasepencil_blend_write(BlendWriter *writer, ID *id, const void *id
BLO_write_struct_array(writer, bGPDspoint, gps->totpoints, gps->points);
BLO_write_struct_array(writer, bGPDtriangle, gps->tot_triangles, gps->triangles);
BKE_defvert_blend_write(writer, gps->totpoints, gps->dvert);
if (gps->editcurve != NULL) {
bGPDcurve *gpc = gps->editcurve;
BLO_write_struct(writer, bGPDcurve, gpc);
BLO_write_struct_array(writer, bGPDcurve_point, gpc->tot_curve_points, gpc->curve_points);
}
}
}
}
@@ -222,6 +227,13 @@ void BKE_gpencil_blend_read_data(BlendDataReader *reader, bGPdata *gpd)
/* Relink geometry*/
BLO_read_data_address(reader, &gps->triangles);
/* relink stroke edit curve. */
BLO_read_data_address(reader, &gps->editcurve);
if (gps->editcurve != NULL) {
/* relink curve point array */
BLO_read_data_address(reader, &gps->editcurve->curve_points);
}
/* relink weight data */
if (gps->dvert) {
BLO_read_data_address(reader, &gps->dvert);
@@ -341,6 +353,20 @@ void BKE_gpencil_free_stroke_weights(bGPDstroke *gps)
}
}
void BKE_gpencil_free_stroke_editcurve(bGPDstroke *gps)
{
if (gps == NULL) {
return;
}
bGPDcurve *editcurve = gps->editcurve;
if (editcurve == NULL) {
return;
}
MEM_freeN(editcurve->curve_points);
MEM_freeN(editcurve);
gps->editcurve = NULL;
}
/* free stroke, doesn't unlink from any listbase */
void BKE_gpencil_free_stroke(bGPDstroke *gps)
{
@@ -358,6 +384,9 @@ void BKE_gpencil_free_stroke(bGPDstroke *gps)
if (gps->triangles) {
MEM_freeN(gps->triangles);
}
if (gps->editcurve != NULL) {
BKE_gpencil_free_stroke_editcurve(gps);
}
MEM_freeN(gps);
}
@@ -688,6 +717,13 @@ bGPdata *BKE_gpencil_data_addnew(Main *bmain, const char name[])
gpd->pixfactor = GP_DEFAULT_PIX_FACTOR;
gpd->curve_edit_resolution = GP_DEFAULT_CURVE_RESOLUTION;
gpd->curve_edit_threshold = GP_DEFAULT_CURVE_ERROR;
gpd->curve_edit_corner_angle = GP_DEFAULT_CURVE_EDIT_CORNER_ANGLE;
/* use adaptive curve resolution by default */
gpd->flag |= GP_DATA_CURVE_ADAPTIVE_RESOLUTION;
gpd->zdepth_offset = 0.150f;
/* grid settings */
@@ -776,6 +812,8 @@ bGPDstroke *BKE_gpencil_stroke_new(int mat_idx, int totpoints, short thickness)
gps->mat_nr = mat_idx;
gps->editcurve = NULL;
return gps;
}
@@ -827,6 +865,16 @@ bGPDstroke *BKE_gpencil_stroke_add_existing_style(
return gps;
}
bGPDcurve *BKE_gpencil_stroke_editcurve_new(const int tot_curve_points)
{
bGPDcurve *new_gp_curve = (bGPDcurve *)MEM_callocN(sizeof(bGPDcurve), __func__);
new_gp_curve->tot_curve_points = tot_curve_points;
new_gp_curve->curve_points = (bGPDcurve_point *)MEM_callocN(
sizeof(bGPDcurve_point) * tot_curve_points, __func__);
return new_gp_curve;
}
/* ************************************************** */
/* Data Duplication */
@@ -845,13 +893,28 @@ void BKE_gpencil_stroke_weights_duplicate(bGPDstroke *gps_src, bGPDstroke *gps_d
BKE_defvert_array_copy(gps_dst->dvert, gps_src->dvert, gps_src->totpoints);
}
/* Make a copy of a given gpencil stroke editcurve */
bGPDcurve *BKE_gpencil_stroke_curve_duplicate(bGPDcurve *gpc_src)
{
bGPDcurve *gpc_dst = MEM_dupallocN(gpc_src);
if (gpc_src->curve_points != NULL) {
gpc_dst->curve_points = MEM_dupallocN(gpc_src->curve_points);
}
return gpc_dst;
}
/**
* Make a copy of a given grease-pencil stroke.
* \param gps_src: Source grease pencil strokes.
* \param dup_points: Duplicate points data.
* \param dup_curve: Duplicate curve data.
* \return Pointer to new stroke.
*/
bGPDstroke *BKE_gpencil_stroke_duplicate(bGPDstroke *gps_src, const bool dup_points)
bGPDstroke *BKE_gpencil_stroke_duplicate(bGPDstroke *gps_src,
const bool dup_points,
const bool dup_curve)
{
bGPDstroke *gps_dst = NULL;
@@ -871,6 +934,10 @@ bGPDstroke *BKE_gpencil_stroke_duplicate(bGPDstroke *gps_src, const bool dup_poi
}
}
if (dup_curve && gps_src->editcurve != NULL) {
gps_dst->editcurve = BKE_gpencil_stroke_curve_duplicate(gps_src->editcurve);
}
/* return new stroke */
return gps_dst;
}
@@ -898,7 +965,7 @@ bGPDframe *BKE_gpencil_frame_duplicate(const bGPDframe *gpf_src)
BLI_listbase_clear(&gpf_dst->strokes);
LISTBASE_FOREACH (bGPDstroke *, gps_src, &gpf_src->strokes) {
/* make copy of source stroke */
gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true);
gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true, true);
BLI_addtail(&gpf_dst->strokes, gps_dst);
}
@@ -923,7 +990,7 @@ void BKE_gpencil_frame_copy_strokes(bGPDframe *gpf_src, struct bGPDframe *gpf_ds
BLI_listbase_clear(&gpf_dst->strokes);
LISTBASE_FOREACH (bGPDstroke *, gps_src, &gpf_src->strokes) {
/* make copy of source stroke */
gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true);
gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true, true);
BLI_addtail(&gpf_dst->strokes, gps_dst);
}
}
@@ -1037,6 +1104,39 @@ void BKE_gpencil_stroke_sync_selection(bGPDstroke *gps)
}
}
void BKE_gpencil_curve_sync_selection(bGPDstroke *gps)
{
bGPDcurve *gpc = gps->editcurve;
if (gpc == NULL) {
return;
}
gps->flag &= ~GP_STROKE_SELECT;
gpc->flag &= ~GP_CURVE_SELECT;
bool is_selected = false;
for (int i = 0; i < gpc->tot_curve_points; i++) {
bGPDcurve_point *gpc_pt = &gpc->curve_points[i];
BezTriple *bezt = &gpc_pt->bezt;
if (BEZT_ISSEL_ANY(bezt)) {
gpc_pt->flag |= GP_SPOINT_SELECT;
}
else {
gpc_pt->flag &= ~GP_SPOINT_SELECT;
}
if (gpc_pt->flag & GP_SPOINT_SELECT) {
is_selected = true;
}
}
if (is_selected) {
gpc->flag |= GP_CURVE_SELECT;
gps->flag |= GP_STROKE_SELECT;
}
}
/* ************************************************** */
/* GP Frame API */
@@ -2304,12 +2404,14 @@ void BKE_gpencil_palette_ensure(Main *bmain, Scene *scene)
/**
* Create grease pencil strokes from image
* \param sima: Image
* \param gpd: Grease pencil data-block
* \param gpf: Grease pencil frame
* \param size: Size
* \param mask: Mask
* \return True if done
*/
bool BKE_gpencil_from_image(SpaceImage *sima, bGPDframe *gpf, const float size, const bool mask)
bool BKE_gpencil_from_image(
SpaceImage *sima, bGPdata *gpd, bGPDframe *gpf, const float size, const bool mask)
{
Image *image = sima->image;
bool done = false;
@@ -2357,7 +2459,7 @@ bool BKE_gpencil_from_image(SpaceImage *sima, bGPDframe *gpf, const float size,
pt->flag |= GP_SPOINT_SELECT;
}
}
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
}
}

View File

@@ -37,8 +37,10 @@
#include "BLT_translation.h"
#include "DNA_gpencil_types.h"
#include "DNA_meshdata_types.h"
#include "BKE_collection.h"
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_gpencil.h"
#include "BKE_gpencil_curve.h"
@@ -47,8 +49,16 @@
#include "BKE_material.h"
#include "BKE_object.h"
#include "curve_fit_nd.h"
#include "DEG_depsgraph_query.h"
#define COORD_FITTING_INFLUENCE 20.0f
/* -------------------------------------------------------------------- */
/** \name Convert to curve object
* \{ */
/* Helper: Check materials with same color. */
static int gpencil_check_same_material_color(Object *ob_gp,
const float color_stroke[4],
@@ -295,6 +305,7 @@ static void gpencil_convert_spline(Main *bmain,
bGPDframe *gpf,
Nurb *nu)
{
bGPdata *gpd = (bGPdata *)ob_gp->data;
bool cyclic = true;
/* Create Stroke. */
@@ -445,11 +456,22 @@ static void gpencil_convert_spline(Main *bmain,
}
if (sample > 0.0f) {
BKE_gpencil_stroke_sample(gps, sample, false);
BKE_gpencil_stroke_sample(gpd, gps, sample, false);
}
/* Recalc fill geometry. */
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
}
static void gpencil_editstroke_deselect_all(bGPDcurve *gpc)
{
for (int i = 0; i < gpc->tot_curve_points; i++) {
bGPDcurve_point *gpc_pt = &gpc->curve_points[i];
BezTriple *bezt = &gpc_pt->bezt;
gpc_pt->flag &= ~GP_CURVE_POINT_SELECT;
BEZT_DESEL_ALL(bezt);
}
gpc->flag &= ~GP_CURVE_SELECT;
}
/**
@@ -536,3 +558,851 @@ void BKE_gpencil_convert_curve(Main *bmain,
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Editcurve kernel functions
* \{ */
static bGPDcurve *gpencil_stroke_editcurve_generate_edgecases(bGPDstroke *gps,
const float stroke_radius)
{
BLI_assert(gps->totpoints < 3);
if (gps->totpoints == 1) {
bGPDcurve *editcurve = BKE_gpencil_stroke_editcurve_new(1);
bGPDspoint *pt = &gps->points[0];
bGPDcurve_point *cpt = &editcurve->curve_points[0];
BezTriple *bezt = &cpt->bezt;
/* Handles are twice as long as the radius of the point. */
float offset = (pt->pressure * stroke_radius) * 2.0f;
float tmp_vec[3];
for (int j = 0; j < 3; j++) {
copy_v3_v3(tmp_vec, &pt->x);
/* Move handles along the x-axis away from the control point */
tmp_vec[0] += (float)(j - 1) * offset;
copy_v3_v3(bezt->vec[j], tmp_vec);
}
cpt->pressure = pt->pressure;
cpt->strength = pt->strength;
copy_v4_v4(cpt->vert_color, pt->vert_color);
/* default handle type */
bezt->h1 = HD_FREE;
bezt->h2 = HD_FREE;
cpt->point_index = 0;
return editcurve;
}
if (gps->totpoints == 2) {
bGPDcurve *editcurve = BKE_gpencil_stroke_editcurve_new(2);
bGPDspoint *first_pt = &gps->points[0];
bGPDspoint *last_pt = &gps->points[1];
float length = len_v3v3(&first_pt->x, &last_pt->x);
float offset = length / 3;
float dir[3];
sub_v3_v3v3(dir, &last_pt->x, &first_pt->x);
for (int i = 0; i < 2; i++) {
bGPDspoint *pt = &gps->points[i];
bGPDcurve_point *cpt = &editcurve->curve_points[i];
BezTriple *bezt = &cpt->bezt;
float tmp_vec[3];
for (int j = 0; j < 3; j++) {
copy_v3_v3(tmp_vec, dir);
normalize_v3_length(tmp_vec, (float)(j - 1) * offset);
add_v3_v3v3(bezt->vec[j], &pt->x, tmp_vec);
}
cpt->pressure = pt->pressure;
cpt->strength = pt->strength;
copy_v4_v4(cpt->vert_color, pt->vert_color);
/* default handle type */
bezt->h1 = HD_VECT;
bezt->h2 = HD_VECT;
cpt->point_index = 0;
}
return editcurve;
}
return NULL;
}
/**
* Creates a bGPDcurve by doing a cubic curve fitting on the grease pencil stroke points.
*/
bGPDcurve *BKE_gpencil_stroke_editcurve_generate(bGPDstroke *gps,
const float error_threshold,
const float corner_angle,
const float stroke_radius)
{
if (gps->totpoints < 3) {
return gpencil_stroke_editcurve_generate_edgecases(gps, stroke_radius);
}
#define POINT_DIM 9
float *points = MEM_callocN(sizeof(float) * gps->totpoints * POINT_DIM, __func__);
float diag_length = len_v3v3(gps->boundbox_min, gps->boundbox_max);
float tmp_vec[3];
for (int i = 0; i < gps->totpoints; i++) {
bGPDspoint *pt = &gps->points[i];
int row = i * POINT_DIM;
/* normalize coordinate to 0..1 */
sub_v3_v3v3(tmp_vec, &pt->x, gps->boundbox_min);
mul_v3_v3fl(&points[row], tmp_vec, COORD_FITTING_INFLUENCE / diag_length);
points[row + 3] = pt->pressure / diag_length;
/* strength and color are already normalized */
points[row + 4] = pt->strength / diag_length;
mul_v4_v4fl(&points[row + 5], pt->vert_color, 1.0f / diag_length);
}
uint calc_flag = CURVE_FIT_CALC_HIGH_QUALIY;
if (gps->totpoints > 2 && gps->flag & GP_STROKE_CYCLIC) {
calc_flag |= CURVE_FIT_CALC_CYCLIC;
}
float *r_cubic_array = NULL;
unsigned int r_cubic_array_len = 0;
unsigned int *r_cubic_orig_index = NULL;
unsigned int *r_corners_index_array = NULL;
unsigned int r_corners_index_len = 0;
int r = curve_fit_cubic_to_points_refit_fl(points,
gps->totpoints,
POINT_DIM,
error_threshold,
calc_flag,
NULL,
0,
corner_angle,
&r_cubic_array,
&r_cubic_array_len,
&r_cubic_orig_index,
&r_corners_index_array,
&r_corners_index_len);
if (r != 0 || r_cubic_array_len < 1) {
return NULL;
}
uint curve_point_size = 3 * POINT_DIM;
bGPDcurve *editcurve = BKE_gpencil_stroke_editcurve_new(r_cubic_array_len);
for (int i = 0; i < r_cubic_array_len; i++) {
bGPDcurve_point *cpt = &editcurve->curve_points[i];
BezTriple *bezt = &cpt->bezt;
float *curve_point = &r_cubic_array[i * curve_point_size];
for (int j = 0; j < 3; j++) {
float *bez = &curve_point[j * POINT_DIM];
madd_v3_v3v3fl(bezt->vec[j], gps->boundbox_min, bez, diag_length / COORD_FITTING_INFLUENCE);
}
float *ctrl_point = &curve_point[1 * POINT_DIM];
cpt->pressure = ctrl_point[3] * diag_length;
cpt->strength = ctrl_point[4] * diag_length;
mul_v4_v4fl(cpt->vert_color, &ctrl_point[5], diag_length);
/* default handle type */
bezt->h1 = HD_ALIGN;
bezt->h2 = HD_ALIGN;
cpt->point_index = r_cubic_orig_index[i];
}
if (r_corners_index_len > 0 && r_corners_index_array != NULL) {
int start = 0, end = r_corners_index_len;
if ((r_corners_index_len > 1) && (calc_flag & CURVE_FIT_CALC_CYCLIC) == 0) {
start = 1;
end = r_corners_index_len - 1;
}
for (int i = start; i < end; i++) {
bGPDcurve_point *cpt = &editcurve->curve_points[r_corners_index_array[i]];
BezTriple *bezt = &cpt->bezt;
bezt->h1 = HD_FREE;
bezt->h2 = HD_FREE;
}
}
MEM_freeN(points);
if (r_cubic_array) {
free(r_cubic_array);
}
if (r_corners_index_array) {
free(r_corners_index_array);
}
if (r_cubic_orig_index) {
free(r_cubic_orig_index);
}
#undef POINT_DIM
return editcurve;
}
/**
* Updates the editcurve for a stroke. Frees the old curve if one exists and generates a new one.
*/
void BKE_gpencil_stroke_editcurve_update(bGPdata *gpd, bGPDlayer *gpl, bGPDstroke *gps)
{
if (gps == NULL || gps->totpoints < 0) {
return;
}
if (gps->editcurve != NULL) {
BKE_gpencil_free_stroke_editcurve(gps);
}
float defaultpixsize = 1000.0f / gpd->pixfactor;
float stroke_radius = ((gps->thickness + gpl->line_change) / defaultpixsize) / 2.0f;
bGPDcurve *editcurve = BKE_gpencil_stroke_editcurve_generate(
gps, gpd->curve_edit_threshold, gpd->curve_edit_corner_angle, stroke_radius);
if (editcurve == NULL) {
return;
}
gps->editcurve = editcurve;
}
/**
* Sync the selection from stroke to editcurve
*/
void BKE_gpencil_editcurve_stroke_sync_selection(bGPDstroke *gps, bGPDcurve *gpc)
{
if (gps->flag & GP_STROKE_SELECT) {
gpc->flag |= GP_CURVE_SELECT;
for (int i = 0; i < gpc->tot_curve_points; i++) {
bGPDcurve_point *gpc_pt = &gpc->curve_points[i];
bGPDspoint *pt = &gps->points[gpc_pt->point_index];
if (pt->flag & GP_SPOINT_SELECT) {
gpc_pt->flag |= GP_CURVE_POINT_SELECT;
BEZT_SEL_ALL(&gpc_pt->bezt);
}
else {
gpc_pt->flag &= ~GP_CURVE_POINT_SELECT;
BEZT_DESEL_ALL(&gpc_pt->bezt);
}
}
}
else {
gpc->flag &= ~GP_CURVE_SELECT;
gpencil_editstroke_deselect_all(gpc);
}
}
/**
* Sync the selection from editcurve to stroke
*/
void BKE_gpencil_stroke_editcurve_sync_selection(bGPDstroke *gps, bGPDcurve *gpc)
{
if (gpc->flag & GP_CURVE_SELECT) {
gps->flag |= GP_STROKE_SELECT;
for (int i = 0; i < gpc->tot_curve_points - 1; i++) {
bGPDcurve_point *gpc_pt = &gpc->curve_points[i];
bGPDspoint *pt = &gps->points[gpc_pt->point_index];
bGPDcurve_point *gpc_pt_next = &gpc->curve_points[i + 1];
if (gpc_pt->flag & GP_CURVE_POINT_SELECT) {
pt->flag |= GP_SPOINT_SELECT;
if (gpc_pt_next->flag & GP_CURVE_POINT_SELECT) {
/* select all the points after */
for (int j = gpc_pt->point_index + 1; j < gpc_pt_next->point_index; j++) {
bGPDspoint *pt_next = &gps->points[j];
pt_next->flag |= GP_SPOINT_SELECT;
}
}
}
else {
pt->flag &= ~GP_SPOINT_SELECT;
/* deselect all points after */
for (int j = gpc_pt->point_index + 1; j < gpc_pt_next->point_index; j++) {
bGPDspoint *pt_next = &gps->points[j];
pt_next->flag &= ~GP_SPOINT_SELECT;
}
}
}
bGPDcurve_point *gpc_first = &gpc->curve_points[0];
bGPDcurve_point *gpc_last = &gpc->curve_points[gpc->tot_curve_points - 1];
bGPDspoint *last_pt = &gps->points[gpc_last->point_index];
if (gpc_last->flag & GP_CURVE_POINT_SELECT) {
last_pt->flag |= GP_SPOINT_SELECT;
}
else {
last_pt->flag &= ~GP_SPOINT_SELECT;
}
if (gps->flag & GP_STROKE_CYCLIC) {
if (gpc_first->flag & GP_CURVE_POINT_SELECT && gpc_last->flag & GP_CURVE_POINT_SELECT) {
for (int i = gpc_last->point_index + 1; i < gps->totpoints; i++) {
bGPDspoint *pt_next = &gps->points[i];
pt_next->flag |= GP_SPOINT_SELECT;
}
}
else {
for (int i = gpc_last->point_index + 1; i < gps->totpoints; i++) {
bGPDspoint *pt_next = &gps->points[i];
pt_next->flag &= ~GP_SPOINT_SELECT;
}
}
}
}
else {
gps->flag &= ~GP_STROKE_SELECT;
for (int i = 0; i < gps->totpoints; i++) {
bGPDspoint *pt = &gps->points[i];
pt->flag &= ~GP_SPOINT_SELECT;
}
}
}
static void gpencil_interpolate_fl_from_to(
float from, float to, float *point_offset, int it, int stride)
{
/* smooth interpolation */
float *r = point_offset;
for (int i = 0; i <= it; i++) {
float fac = (float)i / (float)it;
fac = 3.0f * fac * fac - 2.0f * fac * fac * fac; // smooth
*r = interpf(to, from, fac);
r = POINTER_OFFSET(r, stride);
}
}
static void gpencil_interpolate_v4_from_to(
float from[4], float to[4], float *point_offset, int it, int stride)
{
/* smooth interpolation */
float *r = point_offset;
for (int i = 0; i <= it; i++) {
float fac = (float)i / (float)it;
fac = 3.0f * fac * fac - 2.0f * fac * fac * fac; // smooth
interp_v4_v4v4(r, from, to, fac);
r = POINTER_OFFSET(r, stride);
}
}
static float gpencil_approximate_curve_segment_arclength(bGPDcurve_point *cpt_start,
bGPDcurve_point *cpt_end)
{
BezTriple *bezt_start = &cpt_start->bezt;
BezTriple *bezt_end = &cpt_end->bezt;
float chord_len = len_v3v3(bezt_start->vec[1], bezt_end->vec[1]);
float net_len = len_v3v3(bezt_start->vec[1], bezt_start->vec[2]);
net_len += len_v3v3(bezt_start->vec[2], bezt_end->vec[0]);
net_len += len_v3v3(bezt_end->vec[0], bezt_end->vec[1]);
return (chord_len + net_len) / 2.0f;
}
static void gpencil_calculate_stroke_points_curve_segment(
bGPDcurve_point *cpt, bGPDcurve_point *cpt_next, float *points_offset, int resolu, int stride)
{
/* sample points on all 3 axis between two curve points */
for (uint axis = 0; axis < 3; axis++) {
BKE_curve_forward_diff_bezier(cpt->bezt.vec[1][axis],
cpt->bezt.vec[2][axis],
cpt_next->bezt.vec[0][axis],
cpt_next->bezt.vec[1][axis],
POINTER_OFFSET(points_offset, sizeof(float) * axis),
(int)resolu,
stride);
}
/* interpolate other attributes */
gpencil_interpolate_fl_from_to(cpt->pressure,
cpt_next->pressure,
POINTER_OFFSET(points_offset, sizeof(float) * 3),
resolu,
stride);
gpencil_interpolate_fl_from_to(cpt->strength,
cpt_next->strength,
POINTER_OFFSET(points_offset, sizeof(float) * 4),
resolu,
stride);
gpencil_interpolate_v4_from_to(cpt->vert_color,
cpt_next->vert_color,
POINTER_OFFSET(points_offset, sizeof(float) * 5),
resolu,
stride);
}
static float *gpencil_stroke_points_from_editcurve_adaptive_resolu(
bGPDcurve_point *curve_point_array,
int curve_point_array_len,
int resolution,
bool is_cyclic,
int *r_points_len)
{
/* One stride contains: x, y, z, pressure, strength, Vr, Vg, Vb, Vmix_factor */
const uint stride = sizeof(float[9]);
const uint cpt_last = curve_point_array_len - 1;
const uint num_segments = (is_cyclic) ? curve_point_array_len : curve_point_array_len - 1;
int *segment_point_lengths = MEM_callocN(sizeof(int) * num_segments, __func__);
uint points_len = 1;
for (int i = 0; i < cpt_last; i++) {
bGPDcurve_point *cpt = &curve_point_array[i];
bGPDcurve_point *cpt_next = &curve_point_array[i + 1];
float arclen = gpencil_approximate_curve_segment_arclength(cpt, cpt_next);
int segment_resolu = (int)floorf(arclen * resolution);
CLAMP_MIN(segment_resolu, 1);
segment_point_lengths[i] = segment_resolu;
points_len += segment_resolu;
}
if (is_cyclic) {
bGPDcurve_point *cpt = &curve_point_array[cpt_last];
bGPDcurve_point *cpt_next = &curve_point_array[0];
float arclen = gpencil_approximate_curve_segment_arclength(cpt, cpt_next);
int segment_resolu = (int)floorf(arclen * resolution);
CLAMP_MIN(segment_resolu, 1);
segment_point_lengths[cpt_last] = segment_resolu;
points_len += segment_resolu;
}
float(*r_points)[9] = MEM_callocN((stride * points_len * (is_cyclic ? 2 : 1)), __func__);
float *points_offset = &r_points[0][0];
int point_index = 0;
for (int i = 0; i < cpt_last; i++) {
bGPDcurve_point *cpt_curr = &curve_point_array[i];
bGPDcurve_point *cpt_next = &curve_point_array[i + 1];
int segment_resolu = segment_point_lengths[i];
gpencil_calculate_stroke_points_curve_segment(
cpt_curr, cpt_next, points_offset, segment_resolu, stride);
/* update the index */
cpt_curr->point_index = point_index;
point_index += segment_resolu;
points_offset = POINTER_OFFSET(points_offset, segment_resolu * stride);
}
bGPDcurve_point *cpt_curr = &curve_point_array[cpt_last];
cpt_curr->point_index = point_index;
if (is_cyclic) {
bGPDcurve_point *cpt_next = &curve_point_array[0];
int segment_resolu = segment_point_lengths[cpt_last];
gpencil_calculate_stroke_points_curve_segment(
cpt_curr, cpt_next, points_offset, segment_resolu, stride);
}
MEM_freeN(segment_point_lengths);
*r_points_len = points_len;
return (float(*))r_points;
}
/**
* Helper: calculate the points on a curve with a fixed resolution.
*/
static float *gpencil_stroke_points_from_editcurve_fixed_resolu(bGPDcurve_point *curve_point_array,
int curve_point_array_len,
int resolution,
bool is_cyclic,
int *r_points_len)
{
/* One stride contains: x, y, z, pressure, strength, Vr, Vg, Vb, Vmix_factor */
const uint stride = sizeof(float[9]);
const uint array_last = curve_point_array_len - 1;
const uint resolu_stride = resolution * stride;
const uint points_len = BKE_curve_calc_coords_axis_len(
curve_point_array_len, resolution, is_cyclic, false);
float(*r_points)[9] = MEM_callocN((stride * points_len * (is_cyclic ? 2 : 1)), __func__);
float *points_offset = &r_points[0][0];
for (unsigned int i = 0; i < array_last; i++) {
bGPDcurve_point *cpt_curr = &curve_point_array[i];
bGPDcurve_point *cpt_next = &curve_point_array[i + 1];
gpencil_calculate_stroke_points_curve_segment(
cpt_curr, cpt_next, points_offset, resolution, stride);
/* update the index */
cpt_curr->point_index = i * resolution;
points_offset = POINTER_OFFSET(points_offset, resolu_stride);
}
bGPDcurve_point *cpt_curr = &curve_point_array[array_last];
cpt_curr->point_index = array_last * resolution;
if (is_cyclic) {
bGPDcurve_point *cpt_next = &curve_point_array[0];
gpencil_calculate_stroke_points_curve_segment(
cpt_curr, cpt_next, points_offset, resolution, stride);
}
*r_points_len = points_len;
return (float(*))r_points;
}
/**
* Recalculate stroke points with the editcurve of the stroke.
*/
void BKE_gpencil_stroke_update_geometry_from_editcurve(bGPDstroke *gps,
const uint resolution,
const bool adaptive)
{
if (gps == NULL || gps->editcurve == NULL) {
return;
}
bGPDcurve *editcurve = gps->editcurve;
bGPDcurve_point *curve_point_array = editcurve->curve_points;
int curve_point_array_len = editcurve->tot_curve_points;
if (curve_point_array_len == 0) {
return;
}
/* Handle case for single curve point. */
if (curve_point_array_len == 1) {
bGPDcurve_point *cpt = &curve_point_array[0];
/* resize stroke point array */
gps->totpoints = 1;
gps->points = MEM_recallocN(gps->points, sizeof(bGPDspoint) * gps->totpoints);
if (gps->dvert != NULL) {
gps->dvert = MEM_recallocN(gps->dvert, sizeof(MDeformVert) * gps->totpoints);
}
bGPDspoint *pt = &gps->points[0];
copy_v3_v3(&pt->x, cpt->bezt.vec[1]);
pt->pressure = cpt->pressure;
pt->strength = cpt->strength;
copy_v4_v4(pt->vert_color, cpt->vert_color);
/* deselect */
pt->flag &= ~GP_SPOINT_SELECT;
gps->flag &= ~GP_STROKE_SELECT;
return;
}
bool is_cyclic = gps->flag & GP_STROKE_CYCLIC;
int points_len = 0;
float(*points)[9] = NULL;
if (adaptive) {
points = (float(*)[9])gpencil_stroke_points_from_editcurve_adaptive_resolu(
curve_point_array, curve_point_array_len, resolution, is_cyclic, &points_len);
}
else {
points = (float(*)[9])gpencil_stroke_points_from_editcurve_fixed_resolu(
curve_point_array, curve_point_array_len, resolution, is_cyclic, &points_len);
}
if (points == NULL || points_len == 0) {
return;
}
/* resize stroke point array */
gps->totpoints = points_len;
gps->points = MEM_recallocN(gps->points, sizeof(bGPDspoint) * gps->totpoints);
if (gps->dvert != NULL) {
gps->dvert = MEM_recallocN(gps->dvert, sizeof(MDeformVert) * gps->totpoints);
}
/* write new data to stroke point array */
for (int i = 0; i < points_len; i++) {
bGPDspoint *pt = &gps->points[i];
copy_v3_v3(&pt->x, &points[i][0]);
pt->pressure = points[i][3];
pt->strength = points[i][4];
copy_v4_v4(pt->vert_color, &points[i][5]);
/* deselect points */
pt->flag &= ~GP_SPOINT_SELECT;
}
gps->flag &= ~GP_STROKE_SELECT;
/* free temp data */
MEM_freeN(points);
}
/**
* Recalculate the handles of the edit curve of a grease pencil stroke
*/
void BKE_gpencil_editcurve_recalculate_handles(bGPDstroke *gps)
{
if (gps == NULL || gps->editcurve == NULL) {
return;
}
bool changed = false;
bGPDcurve *gpc = gps->editcurve;
if (gpc->tot_curve_points < 2) {
return;
}
if (gpc->tot_curve_points == 1) {
BKE_nurb_handle_calc(
&(gpc->curve_points[0].bezt), NULL, &(gpc->curve_points[0].bezt), false, 0);
gps->flag |= GP_STROKE_NEEDS_CURVE_UPDATE;
}
for (int i = 1; i < gpc->tot_curve_points - 1; i++) {
bGPDcurve_point *gpc_pt = &gpc->curve_points[i];
bGPDcurve_point *gpc_pt_prev = &gpc->curve_points[i - 1];
bGPDcurve_point *gpc_pt_next = &gpc->curve_points[i + 1];
/* update handle if point or neighbour is selected */
if (gpc_pt->flag & GP_CURVE_POINT_SELECT || gpc_pt_prev->flag & GP_CURVE_POINT_SELECT ||
gpc_pt_next->flag & GP_CURVE_POINT_SELECT) {
BezTriple *bezt = &gpc_pt->bezt;
BezTriple *bezt_prev = &gpc_pt_prev->bezt;
BezTriple *bezt_next = &gpc_pt_next->bezt;
BKE_nurb_handle_calc(bezt, bezt_prev, bezt_next, false, 0);
changed = true;
}
}
bGPDcurve_point *gpc_first = &gpc->curve_points[0];
bGPDcurve_point *gpc_last = &gpc->curve_points[gpc->tot_curve_points - 1];
bGPDcurve_point *gpc_first_next = &gpc->curve_points[1];
bGPDcurve_point *gpc_last_prev = &gpc->curve_points[gpc->tot_curve_points - 2];
if (gps->flag & GP_STROKE_CYCLIC) {
if (gpc_first->flag & GP_CURVE_POINT_SELECT || gpc_last->flag & GP_CURVE_POINT_SELECT) {
BezTriple *bezt_first = &gpc_first->bezt;
BezTriple *bezt_last = &gpc_last->bezt;
BezTriple *bezt_first_next = &gpc_first_next->bezt;
BezTriple *bezt_last_prev = &gpc_last_prev->bezt;
BKE_nurb_handle_calc(bezt_first, bezt_last, bezt_first_next, false, 0);
BKE_nurb_handle_calc(bezt_last, bezt_last_prev, bezt_first, false, 0);
changed = true;
}
}
else {
if (gpc_first->flag & GP_CURVE_POINT_SELECT || gpc_last->flag & GP_CURVE_POINT_SELECT) {
BezTriple *bezt_first = &gpc_first->bezt;
BezTriple *bezt_last = &gpc_last->bezt;
BezTriple *bezt_first_next = &gpc_first_next->bezt;
BezTriple *bezt_last_prev = &gpc_last_prev->bezt;
BKE_nurb_handle_calc(bezt_first, NULL, bezt_first_next, false, 0);
BKE_nurb_handle_calc(bezt_last, bezt_last_prev, NULL, false, 0);
changed = true;
}
}
if (changed) {
gps->flag |= GP_STROKE_NEEDS_CURVE_UPDATE;
}
}
/* Helper: count how many new curve points must be generated. */
static int gpencil_editcurve_subdivide_count(bGPDcurve *gpc, bool is_cyclic)
{
int count = 0;
for (int i = 0; i < gpc->tot_curve_points - 1; i++) {
bGPDcurve_point *cpt = &gpc->curve_points[i];
bGPDcurve_point *cpt_next = &gpc->curve_points[i + 1];
if (cpt->flag & GP_CURVE_POINT_SELECT && cpt_next->flag & GP_CURVE_POINT_SELECT) {
count++;
}
}
if (is_cyclic) {
bGPDcurve_point *cpt = &gpc->curve_points[0];
bGPDcurve_point *cpt_next = &gpc->curve_points[gpc->tot_curve_points - 1];
if (cpt->flag & GP_CURVE_POINT_SELECT && cpt_next->flag & GP_CURVE_POINT_SELECT) {
count++;
}
}
return count;
}
static void gpencil_editcurve_subdivide_curve_segment(bGPDcurve_point *cpt_start,
bGPDcurve_point *cpt_end,
bGPDcurve_point *cpt_new)
{
BezTriple *bezt_start = &cpt_start->bezt;
BezTriple *bezt_end = &cpt_end->bezt;
BezTriple *bezt_new = &cpt_new->bezt;
for (int axis = 0; axis < 3; axis++) {
float p0, p1, p2, p3, m0, m1, q0, q1, b;
p0 = bezt_start->vec[1][axis];
p1 = bezt_start->vec[2][axis];
p2 = bezt_end->vec[0][axis];
p3 = bezt_end->vec[1][axis];
m0 = (p0 + p1) / 2;
q0 = (p0 + 2 * p1 + p2) / 4;
b = (p0 + 3 * p1 + 3 * p2 + p3) / 8;
q1 = (p1 + 2 * p2 + p3) / 4;
m1 = (p2 + p3) / 2;
bezt_new->vec[0][axis] = q0;
bezt_new->vec[2][axis] = q1;
bezt_new->vec[1][axis] = b;
bezt_start->vec[2][axis] = m0;
bezt_end->vec[0][axis] = m1;
}
cpt_new->pressure = interpf(cpt_end->pressure, cpt_start->pressure, 0.5f);
cpt_new->strength = interpf(cpt_end->strength, cpt_start->strength, 0.5f);
interp_v4_v4v4(cpt_new->vert_color, cpt_start->vert_color, cpt_end->vert_color, 0.5f);
}
void BKE_gpencil_editcurve_subdivide(bGPDstroke *gps, const int cuts)
{
bGPDcurve *gpc = gps->editcurve;
if (gpc == NULL || gpc->tot_curve_points < 2) {
return;
}
bool is_cyclic = gps->flag & GP_STROKE_CYCLIC;
/* repeat for number of cuts */
for (int s = 0; s < cuts; s++) {
int old_tot_curve_points = gpc->tot_curve_points;
int new_num_curve_points = gpencil_editcurve_subdivide_count(gpc, is_cyclic);
if (new_num_curve_points == 0) {
break;
}
int new_tot_curve_points = old_tot_curve_points + new_num_curve_points;
bGPDcurve_point *temp_curve_points = (bGPDcurve_point *)MEM_callocN(
sizeof(bGPDcurve_point) * new_tot_curve_points, __func__);
bool prev_subdivided = false;
int j = 0;
for (int i = 0; i < old_tot_curve_points - 1; i++, j++) {
bGPDcurve_point *cpt = &gpc->curve_points[i];
bGPDcurve_point *cpt_next = &gpc->curve_points[i + 1];
if (cpt->flag & GP_CURVE_POINT_SELECT && cpt_next->flag & GP_CURVE_POINT_SELECT) {
bGPDcurve_point *cpt_new = &temp_curve_points[j + 1];
gpencil_editcurve_subdivide_curve_segment(cpt, cpt_next, cpt_new);
memcpy(&temp_curve_points[j], cpt, sizeof(bGPDcurve_point));
memcpy(&temp_curve_points[j + 2], cpt_next, sizeof(bGPDcurve_point));
cpt_new->flag |= GP_CURVE_POINT_SELECT;
cpt_new->bezt.h1 = HD_ALIGN;
cpt_new->bezt.h2 = HD_ALIGN;
BEZT_SEL_ALL(&cpt_new->bezt);
prev_subdivided = true;
j++;
}
else if (!prev_subdivided) {
memcpy(&temp_curve_points[j], cpt, sizeof(bGPDcurve_point));
prev_subdivided = false;
}
else {
prev_subdivided = false;
}
}
if (is_cyclic) {
bGPDcurve_point *cpt = &gpc->curve_points[old_tot_curve_points - 1];
bGPDcurve_point *cpt_next = &gpc->curve_points[0];
if (cpt->flag & GP_CURVE_POINT_SELECT && cpt_next->flag & GP_CURVE_POINT_SELECT) {
bGPDcurve_point *cpt_new = &temp_curve_points[j + 1];
gpencil_editcurve_subdivide_curve_segment(cpt, cpt_next, cpt_new);
memcpy(&temp_curve_points[j], cpt, sizeof(bGPDcurve_point));
memcpy(&temp_curve_points[0], cpt_next, sizeof(bGPDcurve_point));
cpt_new->flag |= GP_CURVE_POINT_SELECT;
cpt_new->bezt.h1 = HD_ALIGN;
cpt_new->bezt.h2 = HD_ALIGN;
BEZT_SEL_ALL(&cpt_new->bezt);
}
else if (!prev_subdivided) {
memcpy(&temp_curve_points[j], cpt, sizeof(bGPDcurve_point));
}
}
else {
bGPDcurve_point *cpt = &gpc->curve_points[old_tot_curve_points - 1];
memcpy(&temp_curve_points[j], cpt, sizeof(bGPDcurve_point));
}
MEM_freeN(gpc->curve_points);
gpc->curve_points = temp_curve_points;
gpc->tot_curve_points = new_tot_curve_points;
}
}
void BKE_gpencil_strokes_selected_update_editcurve(bGPdata *gpd)
{
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
/* For all selected strokes, update edit curve. */
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if (!BKE_gpencil_layer_is_editable(gpl)) {
continue;
}
bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && is_multiedit)) {
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* skip deselected stroke */
if (!(gps->flag & GP_STROKE_SELECT)) {
continue;
}
/* Generate the curve if there is none or the stroke was changed */
if (gps->editcurve == NULL) {
BKE_gpencil_stroke_editcurve_update(gpd, gpl, gps);
/* Continue if curve could not be generated. */
if (gps->editcurve == NULL) {
continue;
}
}
else if (gps->editcurve->flag & GP_CURVE_NEEDS_STROKE_UPDATE) {
BKE_gpencil_stroke_editcurve_update(gpd, gpl, gps);
}
/* Update the selection from the stroke to the curve. */
BKE_gpencil_editcurve_stroke_sync_selection(gps, gps->editcurve);
gps->flag |= GP_STROKE_NEEDS_CURVE_UPDATE;
BKE_gpencil_stroke_geometry_update(gpd, gps);
}
}
}
}
}
void BKE_gpencil_strokes_selected_sync_selection_editcurve(bGPdata *gpd)
{
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
/* Sync selection for all strokes with editcurve. */
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if (!BKE_gpencil_layer_is_editable(gpl)) {
continue;
}
bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && is_multiedit)) {
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
bGPDcurve *gpc = gps->editcurve;
if (gpc != NULL) {
/* Update the selection of every stroke that has an editcurve */
BKE_gpencil_stroke_editcurve_sync_selection(gps, gpc);
}
}
}
}
}
}
/** \} */

View File

@@ -45,8 +45,11 @@
#include "DNA_meshdata_types.h"
#include "DNA_scene_types.h"
#include "BLT_translation.h"
#include "BKE_deform.h"
#include "BKE_gpencil.h"
#include "BKE_gpencil_curve.h"
#include "BKE_gpencil_geom.h"
#include "BKE_main.h"
#include "BKE_material.h"
@@ -415,10 +418,11 @@ static void stroke_interpolate_deform_weights(
/**
* Resample a stroke
* \param gpd: Grease pencil data-block
* \param gps: Stroke to sample
* \param dist: Distance of one segment
*/
bool BKE_gpencil_stroke_sample(bGPDstroke *gps, const float dist, const bool select)
bool BKE_gpencil_stroke_sample(bGPdata *gpd, bGPDstroke *gps, const float dist, const bool select)
{
bGPDspoint *pt = gps->points;
bGPDspoint *pt1 = NULL;
@@ -515,7 +519,7 @@ bool BKE_gpencil_stroke_sample(bGPDstroke *gps, const float dist, const bool sel
gps->totpoints = i;
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
return true;
}
@@ -628,13 +632,15 @@ bool BKE_gpencil_stroke_trim_points(bGPDstroke *gps, const int index_from, const
/**
* Split stroke.
* \param gpd: Grease pencil data-block
* \param gpf: Grease pencil frame
* \param gps: Grease pencil original stroke
* \param before_index: Position of the point to split
* \param remaining_gps: Secondary stroke after split.
* \return True if the split was done
*/
bool BKE_gpencil_stroke_split(bGPDframe *gpf,
bool BKE_gpencil_stroke_split(bGPdata *gpd,
bGPDframe *gpf,
bGPDstroke *gps,
const int before_index,
bGPDstroke **remaining_gps)
@@ -684,7 +690,7 @@ bool BKE_gpencil_stroke_split(bGPDframe *gpf,
* Keep the end point. */
BKE_gpencil_stroke_trim_points(gps, 0, old_count);
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
return true;
}
@@ -1273,14 +1279,31 @@ void BKE_gpencil_stroke_uv_update(bGPDstroke *gps)
/**
* Recalc all internal geometry data for the stroke
* \param gpd: Grease pencil data-block
* \param gps: Grease pencil stroke
*/
void BKE_gpencil_stroke_geometry_update(bGPDstroke *gps)
void BKE_gpencil_stroke_geometry_update(bGPdata *gpd, bGPDstroke *gps)
{
if (gps == NULL) {
return;
}
if (gps->editcurve != NULL) {
if (GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd)) {
/* curve geometry was updated: stroke needs recalculation */
if (gps->flag & GP_STROKE_NEEDS_CURVE_UPDATE) {
bool is_adaptive = gpd->flag & GP_DATA_CURVE_ADAPTIVE_RESOLUTION;
BKE_gpencil_stroke_update_geometry_from_editcurve(
gps, gpd->curve_edit_resolution, is_adaptive);
gps->flag &= ~GP_STROKE_NEEDS_CURVE_UPDATE;
}
}
else {
/* stroke geometry was updated: editcurve needs recalculation */
gps->editcurve->flag |= GP_CURVE_NEEDS_STROKE_UPDATE;
}
}
if (gps->totpoints > 2) {
BKE_gpencil_stroke_fill_triangulate(gps);
}
@@ -1326,7 +1349,7 @@ float BKE_gpencil_stroke_length(const bGPDstroke *gps, bool use_3d)
* Trim stroke to the first intersection or loop.
* \param gps: Stroke data
*/
bool BKE_gpencil_stroke_trim(bGPDstroke *gps)
bool BKE_gpencil_stroke_trim(bGPdata *gpd, bGPDstroke *gps)
{
if (gps->totpoints < 4) {
return false;
@@ -1413,7 +1436,7 @@ bool BKE_gpencil_stroke_trim(bGPDstroke *gps)
MEM_SAFE_FREE(old_dvert);
}
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
return intersect;
}
@@ -1509,11 +1532,12 @@ bool BKE_gpencil_stroke_close(bGPDstroke *gps)
/**
* Dissolve points in stroke.
* \param gpd: Grease pencil data-block
* \param gpf: Grease pencil frame
* \param gps: Grease pencil stroke
* \param tag: Type of tag for point
*/
void BKE_gpencil_dissolve_points(bGPDframe *gpf, bGPDstroke *gps, const short tag)
void BKE_gpencil_dissolve_points(bGPdata *gpd, bGPDframe *gpf, bGPDstroke *gps, const short tag)
{
bGPDspoint *pt;
MDeformVert *dvert = NULL;
@@ -1589,7 +1613,7 @@ void BKE_gpencil_dissolve_points(bGPDframe *gpf, bGPDstroke *gps, const short ta
gps->totpoints = tot;
/* triangles cache needs to be recalculated */
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
}
}
@@ -1635,10 +1659,11 @@ void BKE_gpencil_stroke_normal(const bGPDstroke *gps, float r_normal[3])
*
* Ramer - Douglas - Peucker algorithm
* by http ://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
* \param gpd: Grease pencil data-block
* \param gps: Grease pencil stroke
* \param epsilon: Epsilon value to define precision of the algorithm
*/
void BKE_gpencil_stroke_simplify_adaptive(bGPDstroke *gps, float epsilon)
void BKE_gpencil_stroke_simplify_adaptive(bGPdata *gpd, bGPDstroke *gps, float epsilon)
{
bGPDspoint *old_points = MEM_dupallocN(gps->points);
int totpoints = gps->totpoints;
@@ -1735,7 +1760,7 @@ void BKE_gpencil_stroke_simplify_adaptive(bGPDstroke *gps, float epsilon)
gps->totpoints = j;
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
MEM_SAFE_FREE(old_points);
MEM_SAFE_FREE(old_dvert);
@@ -1744,9 +1769,10 @@ void BKE_gpencil_stroke_simplify_adaptive(bGPDstroke *gps, float epsilon)
/**
* Simplify alternate vertex of stroke except extremes.
* \param gpd: Grease pencil data-block
* \param gps: Grease pencil stroke
*/
void BKE_gpencil_stroke_simplify_fixed(bGPDstroke *gps)
void BKE_gpencil_stroke_simplify_fixed(bGPdata *gpd, bGPDstroke *gps)
{
if (gps->totpoints < 5) {
return;
@@ -1800,19 +1826,20 @@ void BKE_gpencil_stroke_simplify_fixed(bGPDstroke *gps)
gps->totpoints = j;
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
MEM_SAFE_FREE(old_points);
MEM_SAFE_FREE(old_dvert);
}
/**
* Subdivide grease pencil stroke.
* \param gps: Grease pencil stroke
* Subdivide a stroke
* \param gpd: Grease pencil data-block
* \param gps: Stroke
* \param level: Level of subdivision
* \param type: Type of subdivision
*/
void BKE_gpencil_stroke_subdivide(bGPDstroke *gps, int level, int type)
void BKE_gpencil_stroke_subdivide(bGPdata *gpd, bGPDstroke *gps, int level, int type)
{
bGPDspoint *temp_points;
MDeformVert *temp_dverts = NULL;
@@ -1921,7 +1948,7 @@ void BKE_gpencil_stroke_subdivide(bGPDstroke *gps, int level, int type)
}
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
}
/* Merge by distance ------------------------------------- */
@@ -1930,12 +1957,14 @@ void BKE_gpencil_stroke_subdivide(bGPDstroke *gps, int level, int type)
* Reduce a series of points when the distance is below a threshold.
* Special case for first and last points (both are keeped) for other points,
* the merge point always is at first point.
* \param gpd: Grease pencil data-block
* \param gpf: Grease Pencil frame
* \param gps: Grease Pencil stroke
* \param threshold: Distance between points
* \param use_unselected: Set to true to analyze all stroke and not only selected points
*/
void BKE_gpencil_stroke_merge_distance(bGPDframe *gpf,
void BKE_gpencil_stroke_merge_distance(bGPdata *gpd,
bGPDframe *gpf,
bGPDstroke *gps,
const float threshold,
const bool use_unselected)
@@ -2000,11 +2029,11 @@ void BKE_gpencil_stroke_merge_distance(bGPDframe *gpf,
/* Dissolve tagged points */
if (tagged) {
BKE_gpencil_dissolve_points(gpf, gps, GP_SPOINT_TAG);
BKE_gpencil_dissolve_points(gpd, gpf, gps, GP_SPOINT_TAG);
}
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
}
typedef struct GpEdge {
@@ -2093,6 +2122,7 @@ static int gpencil_walk_edge(GHash *v_table,
}
static void gpencil_generate_edgeloops(Object *ob,
bGPdata *gpd,
bGPDframe *gpf_stroke,
int stroke_mat_index,
const float angle,
@@ -2218,7 +2248,7 @@ static void gpencil_generate_edgeloops(Object *ob,
pt->strength = 1.0f;
}
BKE_gpencil_stroke_geometry_update(gps_stroke);
BKE_gpencil_stroke_geometry_update(gpd, gps_stroke);
}
/* Free memory. */
@@ -2397,10 +2427,10 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
}
/* If has only 3 points subdivide. */
if (mp->totloop == 3) {
BKE_gpencil_stroke_subdivide(gps_fill, 1, GP_SUBDIV_SIMPLE);
BKE_gpencil_stroke_subdivide(gpd, gps_fill, 1, GP_SUBDIV_SIMPLE);
}
BKE_gpencil_stroke_geometry_update(gps_fill);
BKE_gpencil_stroke_geometry_update(gpd, gps_fill);
}
}
}
@@ -2417,7 +2447,7 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
gpl_stroke, CFRA + frame_offset, GP_GETFRAME_ADD_NEW);
gpencil_generate_edgeloops(
ob_eval, gpf_stroke, stroke_mat_index, angle, thickness, offset, matrix, use_seams);
ob_eval, gpd, gpf_stroke, stroke_mat_index, angle, thickness, offset, matrix, use_seams);
/* Tag for recalculation */
DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
@@ -2457,7 +2487,7 @@ void BKE_gpencil_transform(bGPdata *gpd, const float mat[4][4])
}
/* Distortion may mean we need to re-triangulate. */
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
}
}
}
@@ -2549,7 +2579,7 @@ void BKE_gpencil_point_coords_apply(bGPdata *gpd, const GPencilPointCoordinates
}
/* Distortion may mean we need to re-triangulate. */
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
}
}
}
@@ -2586,7 +2616,7 @@ void BKE_gpencil_point_coords_apply_with_mat4(bGPdata *gpd,
}
/* Distortion may mean we need to re-triangulate. */
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
}
}
}

View File

@@ -698,7 +698,9 @@ void BKE_gpencil_prepare_eval_data(Depsgraph *depsgraph, Scene *scene, Object *o
}
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd_eval);
const bool do_modifiers = (bool)((!is_multiedit) && (ob->greasepencil_modifiers.first != NULL) &&
const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd_eval);
const bool do_modifiers = (bool)((!is_multiedit) && (!is_curve_edit) &&
(ob->greasepencil_modifiers.first != NULL) &&
(!GPENCIL_SIMPLIFY_MODIF(scene)));
if ((!do_modifiers) && (!do_parent)) {
return;
@@ -734,8 +736,10 @@ void BKE_gpencil_modifiers_calc(Depsgraph *depsgraph, Scene *scene, Object *ob)
bGPdata *gpd = (bGPdata *)ob->data;
const bool is_edit = GPENCIL_ANY_EDIT_MODE(gpd);
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
const bool is_render = (bool)(DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
const bool do_modifiers = (bool)((!is_multiedit) && (ob->greasepencil_modifiers.first != NULL) &&
const bool do_modifiers = (bool)((!is_multiedit) && (!is_curve_edit) &&
(ob->greasepencil_modifiers.first != NULL) &&
(!GPENCIL_SIMPLIFY_MODIF(scene)));
if (!do_modifiers) {
return;

View File

@@ -4871,7 +4871,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
gps->fill_opacity_fac = 1.0f;
/* Calc geometry data because in old versions this data was not saved. */
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
srgb_to_linearrgb_v4(gps->vert_color_fill, gps->vert_color_fill);
int i;

View File

@@ -1067,6 +1067,20 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
part->phystype = PART_PHYS_NO;
}
}
/* Init grease pencil default curve resolution. */
if (!DNA_struct_elem_find(fd->filesdna, "bGPdata", "int", "curve_edit_resolution")) {
LISTBASE_FOREACH (bGPdata *, gpd, &bmain->gpencils) {
gpd->curve_edit_resolution = GP_DEFAULT_CURVE_RESOLUTION;
gpd->flag |= GP_DATA_CURVE_ADAPTIVE_RESOLUTION;
}
}
/* Init grease pencil curve editing error threshold. */
if (!DNA_struct_elem_find(fd->filesdna, "bGPdata", "float", "curve_edit_threshold")) {
LISTBASE_FOREACH (bGPdata *, gpd, &bmain->gpencils) {
gpd->curve_edit_threshold = GP_DEFAULT_CURVE_ERROR;
gpd->curve_edit_corner_angle = GP_DEFAULT_CURVE_EDIT_CORNER_ANGLE;
}
}
}
if (!MAIN_VERSION_ATLEAST(bmain, 291, 9)) {

View File

@@ -49,6 +49,10 @@ void OVERLAY_edit_gpencil_cache_init(OVERLAY_Data *vedata)
pd->edit_gpencil_wires_grp = NULL;
psl->edit_gpencil_ps = NULL;
pd->edit_gpencil_curve_handle_grp = NULL;
pd->edit_gpencil_curve_points_grp = NULL;
psl->edit_gpencil_curve_ps = NULL;
const DRWContextState *draw_ctx = DRW_context_state_get();
View3D *v3d = draw_ctx->v3d;
Object *ob = draw_ctx->obact;
@@ -105,7 +109,8 @@ void OVERLAY_edit_gpencil_cache_init(OVERLAY_Data *vedata)
(GPENCIL_EDIT_MODE(gpd) &&
(ts->gpencil_selectmode_edit != GP_SELECTMODE_STROKE));
if ((!GPENCIL_VERTEX_MODE(gpd) && !GPENCIL_PAINT_MODE(gpd)) || use_vertex_mask) {
if ((!GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd)) &&
((!GPENCIL_VERTEX_MODE(gpd) && !GPENCIL_PAINT_MODE(gpd)) || use_vertex_mask)) {
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
DRW_STATE_BLEND_ALPHA;
DRW_PASS_CREATE(psl->edit_gpencil_ps, state | pd->clipping_state);
@@ -132,6 +137,37 @@ void OVERLAY_edit_gpencil_cache_init(OVERLAY_Data *vedata)
}
}
/* Handles and curve point for Curve Edit submode. */
if (GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd)) {
DRWState state = DRW_STATE_WRITE_COLOR;
DRW_PASS_CREATE(psl->edit_gpencil_curve_ps, state | pd->clipping_state);
/* Edit lines. */
if (show_lines) {
sh = OVERLAY_shader_edit_gpencil_wire();
pd->edit_gpencil_wires_grp = grp = DRW_shgroup_create(sh, psl->edit_gpencil_curve_ps);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_bool_copy(grp, "doMultiframe", show_multi_edit_lines);
DRW_shgroup_uniform_bool_copy(grp, "doWeightColor", is_weight_paint);
DRW_shgroup_uniform_bool_copy(grp, "hideSelect", hide_select);
DRW_shgroup_uniform_float_copy(grp, "gpEditOpacity", v3d->vertex_opacity);
DRW_shgroup_uniform_texture(grp, "weightTex", G_draw.weight_ramp);
}
sh = OVERLAY_shader_edit_curve_handle();
pd->edit_gpencil_curve_handle_grp = grp = DRW_shgroup_create(sh, psl->edit_gpencil_curve_ps);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_bool_copy(grp, "showCurveHandles", pd->edit_curve.show_handles);
DRW_shgroup_uniform_int_copy(grp, "curveHandleDisplay", pd->edit_curve.handle_display);
DRW_shgroup_state_enable(grp, DRW_STATE_BLEND_ALPHA);
sh = OVERLAY_shader_edit_curve_point();
pd->edit_gpencil_curve_points_grp = grp = DRW_shgroup_create(sh, psl->edit_gpencil_curve_ps);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_bool_copy(grp, "showCurveHandles", pd->edit_curve.show_handles);
DRW_shgroup_uniform_int_copy(grp, "curveHandleDisplay", pd->edit_curve.handle_display);
}
/* control points for primitives and speed guide */
const bool is_cppoint = (gpd->runtime.tot_cp_points > 0);
const bool is_speed_guide = (ts->gp_sculpt.guide.use_guide &&
@@ -182,6 +218,7 @@ void OVERLAY_edit_gpencil_cache_init(OVERLAY_Data *vedata)
void OVERLAY_gpencil_cache_init(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
struct GPUShader *sh;
DRWShadingGroup *grp;
@@ -196,6 +233,9 @@ void OVERLAY_gpencil_cache_init(OVERLAY_Data *vedata)
ToolSettings *ts = scene->toolsettings;
const View3DCursor *cursor = &scene->cursor;
pd->edit_curve.show_handles = v3d->overlay.handle_display != CURVE_HANDLE_NONE;
pd->edit_curve.handle_display = v3d->overlay.handle_display;
if (gpd == NULL || ob->type != OB_GPENCIL) {
return;
}
@@ -303,6 +343,20 @@ static void OVERLAY_edit_gpencil_cache_populate(OVERLAY_Data *vedata, Object *ob
struct GPUBatch *geom = DRW_cache_gpencil_edit_points_get(ob, pd->cfra);
DRW_shgroup_call_no_cull(grp, geom, ob);
}
if (pd->edit_gpencil_curve_handle_grp) {
struct GPUBatch *geom = DRW_cache_gpencil_edit_curve_handles_get(ob, pd->cfra);
if (geom) {
DRW_shgroup_call_no_cull(pd->edit_gpencil_curve_handle_grp, geom, ob);
}
}
if (pd->edit_gpencil_curve_points_grp) {
struct GPUBatch *geom = DRW_cache_gpencil_edit_curve_points_get(ob, pd->cfra);
if (geom) {
DRW_shgroup_call_no_cull(pd->edit_gpencil_curve_points_grp, geom, ob);
}
}
}
static void overlay_gpencil_draw_stroke_color_name(bGPDlayer *UNUSED(gpl),
@@ -407,4 +461,9 @@ void OVERLAY_edit_gpencil_draw(OVERLAY_Data *vedata)
if (psl->edit_gpencil_ps) {
DRW_draw_pass(psl->edit_gpencil_ps);
}
/* Curve edit handles. */
if (psl->edit_gpencil_curve_ps) {
DRW_draw_pass(psl->edit_gpencil_curve_ps);
}
}

View File

@@ -77,6 +77,7 @@ typedef struct OVERLAY_PassList {
DRWPass *edit_curve_handle_ps;
DRWPass *edit_gpencil_ps;
DRWPass *edit_gpencil_gizmos_ps;
DRWPass *edit_gpencil_curve_ps;
DRWPass *edit_lattice_ps;
DRWPass *edit_mesh_depth_ps[2];
DRWPass *edit_mesh_verts_ps[2];
@@ -252,6 +253,8 @@ typedef struct OVERLAY_PrivateData {
DRWShadingGroup *edit_lattice_wires_grp;
DRWShadingGroup *edit_gpencil_points_grp;
DRWShadingGroup *edit_gpencil_wires_grp;
DRWShadingGroup *edit_gpencil_curve_handle_grp;
DRWShadingGroup *edit_gpencil_curve_points_grp;
DRWShadingGroup *edit_mesh_depth_grp[2];
DRWShadingGroup *edit_mesh_faces_grp[2];
DRWShadingGroup *edit_mesh_faces_cage_grp[2];

View File

@@ -53,6 +53,9 @@ void main()
bool edge_selected = (((vertFlag[1] | vertFlag[0]) & VERT_SELECTED) != 0);
bool handle_selected = (showCurveHandles &&
(((vertFlag[1] | vertFlag[0]) & VERT_SELECTED_BEZT_HANDLE) != 0));
/* It reuses freestyle flag because the flag is 8 bits and all are already used and this
* flag is not used in this context. */
bool is_gpencil = ((vertFlag[1] & EDGE_FREESTYLE) != 0);
/* If handle type is only selected and the edge is not selected, don't show. */
if ((curveHandleDisplay != CURVE_HANDLE_ALL) && (!handle_selected)) {
@@ -61,6 +64,9 @@ void main()
if ((!is_u_segment) && (color_id <= 4)) {
return;
}
if (is_gpencil) {
return;
}
}
vec4 inner_color;

View File

@@ -17,16 +17,17 @@ void main()
{
GPU_INTEL_VERTEX_SHADER_WORKAROUND
/* Reuse the FREESTYLE flag to determine is GPencil. */
if ((data & VERT_SELECTED) != 0) {
if ((data & VERT_ACTIVE) != 0) {
finalColor = colorEditMeshActive;
}
else {
finalColor = colorVertexSelect;
finalColor = ((data & EDGE_FREESTYLE) == 0) ? colorVertexSelect : colorGpencilVertexSelect;
}
}
else {
finalColor = colorVertex;
finalColor = ((data & EDGE_FREESTYLE) == 0) ? colorVertex : colorGpencilVertex;
}
vec3 world_pos = point_object_to_world(pos);

View File

@@ -253,6 +253,8 @@ struct GPUBatch *DRW_cache_gpencil_strokes_get(struct Object *ob, int cfra);
struct GPUBatch *DRW_cache_gpencil_fills_get(struct Object *ob, int cfra);
struct GPUBatch *DRW_cache_gpencil_edit_lines_get(struct Object *ob, int cfra);
struct GPUBatch *DRW_cache_gpencil_edit_points_get(struct Object *ob, int cfra);
struct GPUBatch *DRW_cache_gpencil_edit_curve_handles_get(struct Object *ob, int cfra);
struct GPUBatch *DRW_cache_gpencil_edit_curve_points_get(struct Object *ob, int cfra);
struct GPUBatch *DRW_cache_gpencil_sbuffer_stroke_get(struct Object *ob);
struct GPUBatch *DRW_cache_gpencil_sbuffer_fill_get(struct Object *ob);

View File

@@ -21,6 +21,7 @@
* \ingroup draw
*/
#include "DNA_curve_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_screen_types.h"
@@ -43,6 +44,9 @@
#include "draw_cache.h"
#include "draw_cache_impl.h"
#define BEZIER_HANDLE 1 << 3
#define COLOR_SHIFT 5
/* ---------------------------------------------------------------------- */
typedef struct GpencilBatchCache {
/** Instancing Data */
@@ -59,6 +63,10 @@ typedef struct GpencilBatchCache {
GPUVertBuf *edit_vbo;
GPUBatch *edit_lines_batch;
GPUBatch *edit_points_batch;
/** Edit Curve Mode */
GPUVertBuf *edit_curve_vbo;
GPUBatch *edit_curve_handles_batch;
GPUBatch *edit_curve_points_batch;
/** Cache is dirty */
bool is_dirty;
@@ -123,6 +131,10 @@ static void gpencil_batch_cache_clear(GpencilBatchCache *cache)
GPU_BATCH_DISCARD_SAFE(cache->edit_points_batch);
GPU_VERTBUF_DISCARD_SAFE(cache->edit_vbo);
GPU_BATCH_DISCARD_SAFE(cache->edit_curve_handles_batch);
GPU_BATCH_DISCARD_SAFE(cache->edit_curve_points_batch);
GPU_VERTBUF_DISCARD_SAFE(cache->edit_curve_vbo);
cache->is_dirty = true;
}
@@ -196,6 +208,23 @@ static GPUVertFormat *gpencil_edit_stroke_format(void)
return &format;
}
/* MUST match the format below. */
typedef struct gpEditCurveVert {
float pos[3];
int data;
} gpEditCurveVert;
static GPUVertFormat *gpencil_edit_curve_format(void)
{
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
/* initialize vertex formats */
GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
GPU_vertformat_attr_add(&format, "data", GPU_COMP_U8, 1, GPU_FETCH_INT);
}
return &format;
}
/* MUST match the format below. */
typedef struct gpColorVert {
float vcol[4]; /* Vertex color */
@@ -228,6 +257,7 @@ typedef struct gpIterData {
GPUIndexBufBuilder ibo;
int vert_len;
int tri_len;
int curve_len;
} gpIterData;
static GPUVertBuf *gpencil_dummy_buffer_get(void)
@@ -383,6 +413,7 @@ static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfr
.ibo = {0},
.vert_len = 1, /* Start at 1 for the gl_InstanceID trick to work (see vert shader). */
.tri_len = 0,
.curve_len = 0,
};
BKE_gpencil_visible_stroke_iter(
NULL, ob, NULL, gpencil_object_verts_count_cb, &iter, do_onion, cfra);
@@ -653,6 +684,11 @@ typedef struct gpEditIterData {
int vgindex;
} gpEditIterData;
typedef struct gpEditCurveIterData {
gpEditCurveVert *verts;
int vgindex;
} gpEditCurveIterData;
static uint32_t gpencil_point_edit_flag(const bool layer_lock,
const bGPDspoint *pt,
int v,
@@ -698,6 +734,92 @@ static void gpencil_edit_stroke_iter_cb(bGPDlayer *gpl,
vert_ptr->weight = gpencil_point_edit_weight(dvert, 0, iter->vgindex);
}
static void gpencil_edit_curve_stroke_count_cb(bGPDlayer *gpl,
bGPDframe *UNUSED(gpf),
bGPDstroke *gps,
void *thunk)
{
if (gpl->flag & GP_LAYER_LOCKED) {
return;
}
gpIterData *iter = (gpIterData *)thunk;
if (gps->editcurve == NULL) {
return;
}
/* Store first index offset */
gps->runtime.curve_start = iter->curve_len;
iter->curve_len += gps->editcurve->tot_curve_points * 4;
}
static char gpencil_beztriple_vflag_get(char flag,
char col_id,
bool handle_point,
const bool handle_selected)
{
char vflag = 0;
SET_FLAG_FROM_TEST(vflag, (flag & SELECT), VFLAG_VERT_SELECTED);
SET_FLAG_FROM_TEST(vflag, handle_point, BEZIER_HANDLE);
SET_FLAG_FROM_TEST(vflag, handle_selected, VFLAG_VERT_SELECTED_BEZT_HANDLE);
/* Reuse flag of Freestyle to indicate is GPencil data. */
vflag |= VFLAG_EDGE_FREESTYLE;
/* Handle color id. */
vflag |= col_id << COLOR_SHIFT;
return vflag;
}
static void gpencil_edit_curve_stroke_iter_cb(bGPDlayer *gpl,
bGPDframe *gpf,
bGPDstroke *gps,
void *thunk)
{
if (gpl->flag & GP_LAYER_LOCKED) {
return;
}
if (gps->editcurve == NULL) {
return;
}
bGPDcurve *editcurve = gps->editcurve;
gpEditCurveIterData *iter = (gpEditCurveIterData *)thunk;
const int v = gps->runtime.curve_start;
gpEditCurveVert *vert_ptr = iter->verts + v;
/* Hide points when the curve is unselected. Passing the control point
* as handle produces the point shader skip it if you are not in ALL mode. */
const bool hide = !(editcurve->flag & GP_CURVE_SELECT);
for (int i = 0; i < editcurve->tot_curve_points; i++) {
BezTriple *bezt = &editcurve->curve_points[i].bezt;
const bool handle_selected = BEZT_ISSEL_ANY(bezt);
const char vflag[3] = {
gpencil_beztriple_vflag_get(bezt->f1, bezt->h1, true, handle_selected),
gpencil_beztriple_vflag_get(bezt->f2, bezt->h1, hide, handle_selected),
gpencil_beztriple_vflag_get(bezt->f3, bezt->h2, true, handle_selected),
};
/* First segment. */
copy_v3_v3(vert_ptr->pos, bezt->vec[0]);
vert_ptr->data = vflag[0];
vert_ptr++;
copy_v3_v3(vert_ptr->pos, bezt->vec[1]);
vert_ptr->data = vflag[1];
vert_ptr++;
/* Second segment. */
copy_v3_v3(vert_ptr->pos, bezt->vec[1]);
vert_ptr->data = vflag[1];
vert_ptr++;
copy_v3_v3(vert_ptr->pos, bezt->vec[2]);
vert_ptr->data = vflag[2];
vert_ptr++;
}
}
static void gpencil_edit_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfra)
{
bGPdata *gpd = (bGPdata *)ob->data;
@@ -737,6 +859,46 @@ static void gpencil_edit_batches_ensure(Object *ob, GpencilBatchCache *cache, in
cache->edit_lines_batch = GPU_batch_create(GPU_PRIM_LINE_STRIP, cache->vbo, NULL);
GPU_batch_vertbuf_add(cache->edit_lines_batch, cache->edit_vbo);
}
/* Curve Handles and Points for Editing. */
if (cache->edit_curve_vbo == NULL) {
gpIterData iterdata = {
.gpd = gpd,
.verts = NULL,
.ibo = {0},
.vert_len = 0,
.tri_len = 0,
.curve_len = 0,
};
/* Create VBO. */
GPUVertFormat *format = gpencil_edit_curve_format();
cache->edit_curve_vbo = GPU_vertbuf_create_with_format(format);
/* Count data. */
BKE_gpencil_visible_stroke_iter(
NULL, ob, NULL, gpencil_edit_curve_stroke_count_cb, &iterdata, false, cfra);
gpEditCurveIterData iter;
int vert_len = iterdata.curve_len;
if (vert_len > 0) {
GPU_vertbuf_data_alloc(cache->edit_curve_vbo, vert_len);
iter.verts = (gpEditCurveVert *)GPU_vertbuf_get_data(cache->edit_curve_vbo);
/* Fill buffers with data. */
BKE_gpencil_visible_stroke_iter(
NULL, ob, NULL, gpencil_edit_curve_stroke_iter_cb, &iter, false, cfra);
cache->edit_curve_handles_batch = GPU_batch_create(
GPU_PRIM_LINES, cache->edit_curve_vbo, NULL);
GPU_batch_vertbuf_add(cache->edit_curve_handles_batch, cache->edit_curve_vbo);
cache->edit_curve_points_batch = GPU_batch_create(
GPU_PRIM_POINTS, cache->edit_curve_vbo, NULL);
GPU_batch_vertbuf_add(cache->edit_curve_points_batch, cache->edit_curve_vbo);
}
gpd->flag &= ~GP_DATA_CACHE_IS_DIRTY;
cache->is_dirty = false;
@@ -761,4 +923,22 @@ GPUBatch *DRW_cache_gpencil_edit_points_get(Object *ob, int cfra)
return cache->edit_points_batch;
}
GPUBatch *DRW_cache_gpencil_edit_curve_handles_get(Object *ob, int cfra)
{
GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra);
gpencil_batches_ensure(ob, cache, cfra);
gpencil_edit_batches_ensure(ob, cache, cfra);
return cache->edit_curve_handles_batch;
}
GPUBatch *DRW_cache_gpencil_edit_curve_points_get(Object *ob, int cfra)
{
GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra);
gpencil_batches_ensure(ob, cache, cfra);
gpencil_edit_batches_ensure(ob, cache, cfra);
return cache->edit_curve_points_batch;
}
/** \} */

View File

@@ -42,6 +42,7 @@ set(SRC
gpencil_convert.c
gpencil_data.c
gpencil_edit.c
gpencil_edit_curve.c
gpencil_fill.c
gpencil_interpolate.c
gpencil_merge.c

View File

@@ -910,7 +910,7 @@ static void annotation_stroke_newfrombuffer(tGPsdata *p)
int totarrowpoints = runtime.arrow_end_style;
/* Setting up arrow stroke. */
bGPDstroke *e_arrow_gps = BKE_gpencil_stroke_duplicate(gps, false);
bGPDstroke *e_arrow_gps = BKE_gpencil_stroke_duplicate(gps, false, false);
annotation_stroke_arrow_allocate(e_arrow_gps, totarrowpoints);
/* Set pointer to first non-initialized point. */
@@ -931,7 +931,7 @@ static void annotation_stroke_newfrombuffer(tGPsdata *p)
int totarrowpoints = runtime.arrow_start_style;
/* Setting up arrow stroke. */
bGPDstroke *s_arrow_gps = BKE_gpencil_stroke_duplicate(gps, false);
bGPDstroke *s_arrow_gps = BKE_gpencil_stroke_duplicate(gps, false, false);
annotation_stroke_arrow_allocate(s_arrow_gps, totarrowpoints);
/* Set pointer to first non-initialized point. */
@@ -1198,7 +1198,7 @@ static void annotation_stroke_eraser_dostroke(tGPsdata *p,
/* Second Pass: Remove any points that are tagged */
if (do_cull) {
gpencil_stroke_delete_tagged_points(gpf, gps, gps->next, GP_SPOINT_TAG, false, 0);
gpencil_stroke_delete_tagged_points(p->gpd, gpf, gps, gps->next, GP_SPOINT_TAG, false, 0);
}
}
}

View File

@@ -486,7 +486,7 @@ bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode)
*/
for (gps = gpfs->strokes.first; gps; gps = gps->next) {
/* make a copy of stroke, then of its points array */
gpsn = BKE_gpencil_stroke_duplicate(gps, true);
gpsn = BKE_gpencil_stroke_duplicate(gps, true, true);
/* append stroke to frame */
BLI_addtail(&gpf->strokes, gpsn);

View File

@@ -861,115 +861,115 @@ void ED_gpencil_create_monkey(bContext *C, Object *ob, float mat[4][4])
/* generate strokes */
gps = BKE_gpencil_stroke_add(frameFills, color_Skin, 270, 75, false);
BKE_gpencil_stroke_add_points(gps, data0, 270, mat);
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 33, 60, false);
BKE_gpencil_stroke_add_points(gps, data1, 33, mat);
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 18, 60, false);
BKE_gpencil_stroke_add_points(gps, data2, 18, mat);
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 64, 60, false);
BKE_gpencil_stroke_add_points(gps, data3, 64, mat);
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 33, 60, false);
BKE_gpencil_stroke_add_points(gps, data4, 33, mat);
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 64, 60, false);
BKE_gpencil_stroke_add_points(gps, data5, 64, mat);
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 33, 60, false);
BKE_gpencil_stroke_add_points(gps, data6, 33, mat);
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 18, 40, false);
BKE_gpencil_stroke_add_points(gps, data7, 18, mat);
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Eyes, 49, 60, false);
BKE_gpencil_stroke_add_points(gps, data8, 49, mat);
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 33, 60, false);
BKE_gpencil_stroke_add_points(gps, data9, 33, mat);
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Eyes, 49, 60, false);
BKE_gpencil_stroke_add_points(gps, data10, 49, mat);
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 18, 40, false);
BKE_gpencil_stroke_add_points(gps, data11, 18, mat);
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 18, 40, false);
BKE_gpencil_stroke_add_points(gps, data12, 18, mat);
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false);
BKE_gpencil_stroke_add_points(gps, data13, 33, mat);
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false);
BKE_gpencil_stroke_add_points(gps, data14, 33, mat);
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 65, 60, false);
BKE_gpencil_stroke_add_points(gps, data15, 65, mat);
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 34, 60, false);
BKE_gpencil_stroke_add_points(gps, data16, 34, mat);
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false);
BKE_gpencil_stroke_add_points(gps, data17, 33, mat);
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 40, false);
BKE_gpencil_stroke_add_points(gps, data18, 33, mat);
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 34, 40, false);
BKE_gpencil_stroke_add_points(gps, data19, 34, mat);
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false);
BKE_gpencil_stroke_add_points(gps, data20, 33, mat);
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 64, 60, false);
BKE_gpencil_stroke_add_points(gps, data21, 64, mat);
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Pupils, 26, 60, false);
BKE_gpencil_stroke_add_points(gps, data22, 26, mat);
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Pupils, 26, 60, false);
BKE_gpencil_stroke_add_points(gps, data23, 26, mat);
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false);
BKE_gpencil_stroke_add_points(gps, data24, 33, mat);
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 18, 40, false);
BKE_gpencil_stroke_add_points(gps, data25, 18, mat);
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 18, 40, false);
BKE_gpencil_stroke_add_points(gps, data26, 18, mat);
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false);
BKE_gpencil_stroke_add_points(gps, data27, 33, mat);
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
/* update depsgraph */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);

View File

@@ -249,7 +249,7 @@ void ED_gpencil_create_stroke(bContext *C, Object *ob, float mat[4][4])
/* generate stroke */
gps = BKE_gpencil_stroke_add(frame_lines, color_black, 175, 75, false);
BKE_gpencil_stroke_add_points(gps, data0, 175, mat);
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
/* update depsgraph */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);

View File

@@ -1855,12 +1855,12 @@ static int image_to_gpencil_exec(bContext *C, wmOperator *op)
bGPdata *gpd = (bGPdata *)ob->data;
bGPDlayer *gpl = BKE_gpencil_layer_addnew(gpd, "Image Layer", true);
bGPDframe *gpf = BKE_gpencil_frame_addnew(gpl, CFRA);
done = BKE_gpencil_from_image(sima, gpf, size, is_mask);
done = BKE_gpencil_from_image(sima, gpd, gpf, size, is_mask);
if (done) {
/* Delete any selected point. */
LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
gpencil_stroke_delete_tagged_points(gpf, gps, gps->next, GP_SPOINT_SELECT, false, 0);
gpencil_stroke_delete_tagged_points(gpd, gpf, gps, gps->next, GP_SPOINT_SELECT, false, 0);
}
BKE_reportf(op->reports, RPT_INFO, "Object created");

View File

@@ -580,7 +580,7 @@ static int gpencil_layer_duplicate_object_exec(bContext *C, wmOperator *op)
LISTBASE_FOREACH (bGPDstroke *, gps_src, &gpf_src->strokes) {
/* Make copy of source stroke. */
bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true);
bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true, true);
/* Check if material is in destination object,
* otherwise add the slot with the material. */
@@ -1531,6 +1531,7 @@ static int gpencil_stroke_arrange_exec(bContext *C, wmOperator *op)
const int direction = RNA_enum_get(op->ptr, "direction");
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
bool changed = false;
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
/* temp listbase to store selected strokes */
ListBase selected = {NULL};
@@ -1589,7 +1590,7 @@ static int gpencil_stroke_arrange_exec(bContext *C, wmOperator *op)
break;
/* Bring Forward */
case GP_STROKE_MOVE_UP:
for (LinkData *link = selected.last; link; link = link->prev) {
LISTBASE_FOREACH_BACKWARD (LinkData *, link, &selected) {
gps = link->data;
BLI_listbase_link_move(&gpf->strokes, gps, 1);
}
@@ -1603,7 +1604,7 @@ static int gpencil_stroke_arrange_exec(bContext *C, wmOperator *op)
break;
/* Send to Back */
case GP_STROKE_MOVE_BOTTOM:
for (LinkData *link = selected.last; link; link = link->prev) {
LISTBASE_FOREACH_BACKWARD (LinkData *, link, &selected) {
gps = link->data;
BLI_remlink(&gpf->strokes, gps);
BLI_addhead(&gpf->strokes, gps);
@@ -1612,6 +1613,7 @@ static int gpencil_stroke_arrange_exec(bContext *C, wmOperator *op)
default:
BLI_assert(0);
break;
changed = true;
}
}
BLI_freelistN(&selected);
@@ -1625,9 +1627,11 @@ static int gpencil_stroke_arrange_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
/* notifiers */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
if (changed) {
/* notifiers */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
}
return OPERATOR_FINISHED;
}
@@ -1693,6 +1697,7 @@ static int gpencil_stroke_change_color_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
bool changed = false;
/* loop all strokes */
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
@@ -1717,6 +1722,8 @@ static int gpencil_stroke_change_color_exec(bContext *C, wmOperator *op)
/* assign new color */
gps->mat_nr = idx;
changed = true;
}
}
}
@@ -1728,9 +1735,11 @@ static int gpencil_stroke_change_color_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
/* notifiers */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
if (changed) {
/* notifiers */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
}
return OPERATOR_FINISHED;
}
@@ -1757,9 +1766,7 @@ void GPENCIL_OT_stroke_change_color(wmOperatorType *ot)
static int gpencil_material_lock_unsused_exec(bContext *C, wmOperator *UNUSED(op))
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
Object *ob = CTX_data_active_object(C);
short *totcol = BKE_object_material_len_p(ob);
/* sanity checks */
@@ -1776,6 +1783,7 @@ static int gpencil_material_lock_unsused_exec(bContext *C, wmOperator *UNUSED(op
}
}
bool changed = false;
/* loop all selected strokes and unlock any color */
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* only editable and visible layers are considered */
@@ -1793,19 +1801,24 @@ static int gpencil_material_lock_unsused_exec(bContext *C, wmOperator *UNUSED(op
tmp_ma->gp_style->flag &= ~GP_MATERIAL_LOCKED;
DEG_id_tag_update(&tmp_ma->id, ID_RECALC_COPY_ON_WRITE);
}
changed = true;
}
}
}
}
/* updates */
DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
/* copy on write tag is needed, or else no refresh happens */
DEG_id_tag_update(&gpd->id, ID_RECALC_COPY_ON_WRITE);
if (changed) {
/* updates */
DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
/* notifiers */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
/* copy on write tag is needed, or else no refresh happens */
DEG_id_tag_update(&gpd->id, ID_RECALC_COPY_ON_WRITE);
/* notifiers */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
}
return OPERATOR_FINISHED;
}
@@ -3476,7 +3489,6 @@ static int gpencil_set_active_material_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_active_object(C);
bGPdata *gpd = ED_gpencil_data_get_active(C);
bool changed = false;
/* Sanity checks. */
if (gpd == NULL) {
@@ -3484,6 +3496,7 @@ static int gpencil_set_active_material_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
bool changed = false;
/* Loop all selected strokes. */
GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
if (gps->flag & GP_STROKE_SELECT) {

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,214 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2008, Blender Foundation
* This is a new part of Blender
* Operators for editing Grease Pencil strokes
*/
/** \file
* \ingroup edgpencil
*/
#include <math.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MEM_guardedalloc.h"
#include "DNA_gpencil_types.h"
#include "DNA_view3d_types.h"
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_gpencil.h"
#include "BKE_gpencil_curve.h"
#include "BKE_gpencil_geom.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "WM_api.h"
#include "WM_types.h"
#include "ED_gpencil.h"
#include "DEG_depsgraph.h"
#include "gpencil_intern.h"
/* Poll callback for checking if there is an active layer and we are in curve edit mode. */
static bool gpencil_curve_edit_mode_poll(bContext *C)
{
Object *ob = CTX_data_active_object(C);
if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
return false;
}
bGPdata *gpd = (bGPdata *)ob->data;
if (!GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd)) {
return false;
}
bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
return (gpl != NULL);
}
static int gpencil_stroke_enter_editcurve_mode_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_active_object(C);
bGPdata *gpd = ob->data;
float error_threshold = RNA_float_get(op->ptr, "error_threshold");
gpd->curve_edit_threshold = error_threshold;
if (ELEM(NULL, gpd)) {
return OPERATOR_CANCELLED;
}
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
if (gpf == gpl->actframe) {
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* only allow selected and non-converted strokes to be transformed */
if ((gps->flag & GP_STROKE_SELECT && gps->editcurve == NULL) ||
(gps->editcurve != NULL && gps->editcurve->flag & GP_CURVE_NEEDS_STROKE_UPDATE)) {
BKE_gpencil_stroke_editcurve_update(gpd, gpl, gps);
/* Update the selection from the stroke to the curve. */
BKE_gpencil_editcurve_stroke_sync_selection(gps, gps->editcurve);
gps->flag |= GP_STROKE_NEEDS_CURVE_UPDATE;
BKE_gpencil_stroke_geometry_update(gpd, gps);
}
}
}
}
}
gpd->flag |= GP_DATA_CURVE_EDIT_MODE;
/* notifiers */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
}
void GPENCIL_OT_stroke_enter_editcurve_mode(wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
ot->name = "Enter curve edit mode";
ot->idname = "GPENCIL_OT_stroke_enter_editcurve_mode";
ot->description = "Called to transform a stroke into a curve";
/* api callbacks */
ot->exec = gpencil_stroke_enter_editcurve_mode_exec;
ot->poll = gpencil_active_layer_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
prop = RNA_def_float(ot->srna,
"error_threshold",
0.1f,
FLT_MIN,
100.0f,
"Error Threshold",
"Threshold on the maximum deviation from the actual stroke",
FLT_MIN,
10.f);
RNA_def_property_ui_range(prop, FLT_MIN, 10.0f, 0.1f, 5);
}
static int gpencil_editcurve_set_handle_type_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_active_object(C);
bGPdata *gpd = ob->data;
const int handle_type = RNA_enum_get(op->ptr, "type");
if (ELEM(NULL, gpd)) {
return OPERATOR_CANCELLED;
}
GP_EDITABLE_CURVES_BEGIN(gps_iter, C, gpl, gps, gpc)
{
for (int i = 0; i < gpc->tot_curve_points; i++) {
bGPDcurve_point *gpc_pt = &gpc->curve_points[i];
if (gpc_pt->flag & GP_CURVE_POINT_SELECT) {
BezTriple *bezt = &gpc_pt->bezt;
if (bezt->f2 & SELECT) {
bezt->h1 = handle_type;
bezt->h2 = handle_type;
}
else {
if (bezt->f1 & SELECT) {
bezt->h1 = handle_type;
}
if (bezt->f3 & SELECT) {
bezt->h2 = handle_type;
}
}
}
}
BKE_gpencil_editcurve_recalculate_handles(gps);
gps->flag |= GP_STROKE_NEEDS_CURVE_UPDATE;
BKE_gpencil_stroke_geometry_update(gpd, gps);
}
GP_EDITABLE_CURVES_END(gps_iter);
/* notifiers */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
}
void GPENCIL_OT_stroke_editcurve_set_handle_type(wmOperatorType *ot)
{
static const EnumPropertyItem editcurve_handle_type_items[] = {
{HD_FREE, "FREE", 0, "Free", ""},
{HD_AUTO, "AUTOMATIC", 0, "Automatic", ""},
{HD_VECT, "VECTOR", 0, "Vector", ""},
{HD_ALIGN, "ALIGNED", 0, "Aligned", ""},
{0, NULL, 0, NULL, NULL},
};
/* identifiers */
ot->name = "Set handle type";
ot->idname = "GPENCIL_OT_stroke_editcurve_set_handle_type";
ot->description = "Set the type of a edit curve handle";
/* api callbacks */
ot->invoke = WM_menu_invoke;
ot->exec = gpencil_editcurve_set_handle_type_exec;
ot->poll = gpencil_curve_edit_mode_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
ot->prop = RNA_def_enum(ot->srna, "type", editcurve_handle_type_items, 1, "Type", "Spline type");
}
/** \} */

View File

@@ -1299,11 +1299,11 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf)
/* simplify stroke */
for (int b = 0; b < tgpf->fill_simplylvl; b++) {
BKE_gpencil_stroke_simplify_fixed(gps);
BKE_gpencil_stroke_simplify_fixed(tgpf->gpd, gps);
}
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(tgpf->gpd, gps);
}
/* ----------------------- */

View File

@@ -343,7 +343,8 @@ struct GHash *gpencil_copybuf_validate_colormap(struct bContext *C);
/* Stroke Editing ------------------------------------ */
void gpencil_stroke_delete_tagged_points(bGPDframe *gpf,
void gpencil_stroke_delete_tagged_points(bGPdata *gpd,
bGPDframe *gpf,
bGPDstroke *gps,
bGPDstroke *next_stroke,
int tag_flags,
@@ -351,7 +352,7 @@ void gpencil_stroke_delete_tagged_points(bGPDframe *gpf,
int limit);
int gpencil_delete_selected_point_wrap(bContext *C);
void gpencil_subdivide_stroke(bGPDstroke *gps, const int subdivide);
void gpencil_subdivide_stroke(bGPdata *gpd, bGPDstroke *gps, const int subdivide);
/* Layers Enums -------------------------------------- */
@@ -447,6 +448,11 @@ void GPENCIL_OT_snap_cursor_to_selected(struct wmOperatorType *ot);
void GPENCIL_OT_reproject(struct wmOperatorType *ot);
void GPENCIL_OT_recalc_geometry(struct wmOperatorType *ot);
/* stroke editcurve */
void GPENCIL_OT_stroke_enter_editcurve_mode(struct wmOperatorType *ot);
void GPENCIL_OT_stroke_editcurve_set_handle_type(struct wmOperatorType *ot);
/* stroke sculpting -- */
void GPENCIL_OT_sculpt_paint(struct wmOperatorType *ot);
@@ -692,6 +698,55 @@ struct GP_EditableStrokes_Iter {
} \
(void)0
/**
* Iterate over all editable editcurves in the current context,
* stopping on each usable layer + stroke + curve pair (i.e. gpl, gps and gpc)
* to perform some operations on the curve.
*
* \param gpl: The identifier to use for the layer of the stroke being processed.
* Choose a suitable value to avoid name clashes.
* \param gps: The identifier to use for current stroke being processed.
* Choose a suitable value to avoid name clashes.
* \param gpc: The identifier to use for current editcurve being processed.
* Choose a suitable value to avoid name clashes.
*/
#define GP_EDITABLE_CURVES_BEGIN(gpstroke_iter, C, gpl, gps, gpc) \
{ \
struct GP_EditableStrokes_Iter gpstroke_iter = {{{0}}}; \
Depsgraph *depsgraph_ = CTX_data_ensure_evaluated_depsgraph(C); \
Object *obact_ = CTX_data_active_object(C); \
bGPdata *gpd_ = CTX_data_gpencil_data(C); \
const bool is_multiedit_ = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd_); \
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) { \
bGPDframe *init_gpf_ = (is_multiedit_) ? gpl->frames.first : gpl->actframe; \
for (bGPDframe *gpf_ = init_gpf_; gpf_; gpf_ = gpf_->next) { \
if ((gpf_ == gpl->actframe) || ((gpf_->flag & GP_FRAME_SELECT) && is_multiedit_)) { \
BKE_gpencil_parent_matrix_get(depsgraph_, obact_, gpl, gpstroke_iter.diff_mat); \
invert_m4_m4(gpstroke_iter.inverse_diff_mat, gpstroke_iter.diff_mat); \
/* loop over strokes */ \
bGPDstroke *gpsn_; \
for (bGPDstroke *gps = gpf_->strokes.first; gps; gps = gpsn_) { \
gpsn_ = gps->next; \
/* skip strokes that are invalid for current view */ \
if (ED_gpencil_stroke_can_use(C, gps) == false) \
continue; \
if (gps->editcurve == NULL) \
continue; \
bGPDcurve *gpc = gps->editcurve; \
/* ... Do Stuff With Strokes ... */
#define GP_EDITABLE_CURVES_END(gpstroke_iter) \
} \
} \
if (!is_multiedit_) { \
break; \
} \
} \
} \
CTX_DATA_END; \
} \
(void)0
/**
* Iterate over all editable strokes using evaluated data in the current context,
* stopping on each usable layer + stroke pair (i.e. gpl and gps)

View File

@@ -184,7 +184,7 @@ static void gpencil_interpolate_update_strokes(bContext *C, tGPDinterpolate *tgp
/* Add temp strokes. */
if (gpf) {
bGPDstroke *gps_eval = BKE_gpencil_stroke_duplicate(new_stroke, true);
bGPDstroke *gps_eval = BKE_gpencil_stroke_duplicate(new_stroke, true, true);
gps_eval->flag |= GP_STROKE_TAG;
BLI_addtail(&gpf->strokes, gps_eval);
}
@@ -327,7 +327,7 @@ static void gpencil_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
}
/* create new stroke */
new_stroke = BKE_gpencil_stroke_duplicate(gps_from, true);
new_stroke = BKE_gpencil_stroke_duplicate(gps_from, true, true);
if (valid) {
/* if destination stroke is smaller, resize new_stroke to size of gps_to stroke */
@@ -353,7 +353,7 @@ static void gpencil_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
}
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(new_stroke);
BKE_gpencil_stroke_geometry_update(gpd, new_stroke);
/* add to strokes */
BLI_addtail(&tgpil->interFrame->strokes, new_stroke);
}
@@ -608,11 +608,11 @@ static int gpencil_interpolate_modal(bContext *C, wmOperator *op, const wmEvent
}
/* make copy of source stroke, then adjust pointer to points too */
gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true);
gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true, true);
gps_dst->flag &= ~GP_STROKE_TAG;
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(gps_dst);
BKE_gpencil_stroke_geometry_update(tgpi->gpd, gps_dst);
BLI_addtail(&gpf_dst->strokes, gps_dst);
}
@@ -1050,7 +1050,7 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
}
/* create new stroke */
bGPDstroke *new_stroke = BKE_gpencil_stroke_duplicate(gps_from, true);
bGPDstroke *new_stroke = BKE_gpencil_stroke_duplicate(gps_from, true, true);
/* if destination stroke is smaller, resize new_stroke to size of gps_to stroke */
if (gps_from->totpoints > gps_to->totpoints) {
@@ -1075,7 +1075,7 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
gpencil_interpolate_update_points(gps_from, gps_to, new_stroke, factor);
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(new_stroke);
BKE_gpencil_stroke_geometry_update(gpd, new_stroke);
/* add to strokes */
BLI_addtail(&interFrame->strokes, new_stroke);

View File

@@ -172,6 +172,9 @@ static void gpencil_get_elements_len(bContext *C, int *totstrokes, int *totpoint
static void gpencil_dissolve_points(bContext *C)
{
Object *ob = CTX_data_active_object(C);
bGPdata *gpd = ob->data;
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
bGPDframe *gpf = gpl->actframe;
if (gpf == NULL) {
@@ -179,7 +182,7 @@ static void gpencil_dissolve_points(bContext *C)
}
LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
gpencil_stroke_delete_tagged_points(gpf, gps, gps->next, GP_SPOINT_TAG, false, 0);
gpencil_stroke_delete_tagged_points(gpd, gpf, gps, gps->next, GP_SPOINT_TAG, false, 0);
}
}
CTX_DATA_END;
@@ -519,7 +522,7 @@ static int gpencil_stroke_merge_exec(bContext *C, wmOperator *op)
gpencil_dissolve_points(C);
}
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
/* free memory */
MEM_SAFE_FREE(original_array);

View File

@@ -69,6 +69,13 @@ static bool gpencil_stroke_editmode_poll(bContext *C)
return (gpd && (gpd->flag & GP_DATA_STROKE_EDITMODE));
}
/* Poll callback for stroke curve editing mode */
static bool gpencil_stroke_editmode_curve_poll(bContext *C)
{
bGPdata *gpd = CTX_data_gpencil_data(C);
return (GPENCIL_EDIT_MODE(gpd) && GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd));
}
/* Poll callback for stroke painting mode */
static bool gpencil_stroke_paintmode_poll(bContext *C)
{
@@ -315,6 +322,15 @@ static void ed_keymap_gpencil_editing(wmKeyConfig *keyconf)
keymap->poll = gpencil_stroke_editmode_poll;
}
/* Stroke Curve Editing Keymap - Only when editmode is enabled and in curve edit mode */
static void ed_keymap_gpencil_curve_editing(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Curve Edit Mode", 0, 0);
/* set poll callback - so that this keymap only gets enabled when curve editmode is enabled */
keymap->poll = gpencil_stroke_editmode_curve_poll;
}
/* keys for draw with a drawing brush (no fill) */
static void ed_keymap_gpencil_painting_draw(wmKeyConfig *keyconf)
{
@@ -471,6 +487,7 @@ static void ed_keymap_gpencil_weightpainting_draw(wmKeyConfig *keyconf)
void ED_keymap_gpencil(wmKeyConfig *keyconf)
{
ed_keymap_gpencil_general(keyconf);
ed_keymap_gpencil_curve_editing(keyconf);
ed_keymap_gpencil_editing(keyconf);
ed_keymap_gpencil_painting(keyconf);
ed_keymap_gpencil_painting_draw(keyconf);
@@ -568,6 +585,11 @@ void ED_operatortypes_gpencil(void)
WM_operatortype_append(GPENCIL_OT_sculpt_paint);
WM_operatortype_append(GPENCIL_OT_weight_paint);
/* Edit stroke editcurve */
WM_operatortype_append(GPENCIL_OT_stroke_enter_editcurve_mode);
WM_operatortype_append(GPENCIL_OT_stroke_editcurve_set_handle_type);
/* Editing (Buttons) ------------ */
WM_operatortype_append(GPENCIL_OT_annotation_add);

View File

@@ -1195,7 +1195,7 @@ static void gpencil_stroke_newfrombuffer(tGPsdata *p)
/* subdivide and smooth the stroke */
if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_SETTINGS) && (subdivide > 0)) {
gpencil_subdivide_stroke(gps, subdivide);
gpencil_subdivide_stroke(gpd, gps, subdivide);
}
/* Smooth stroke after subdiv - only if there's something to do for each iteration,
@@ -1226,7 +1226,7 @@ static void gpencil_stroke_newfrombuffer(tGPsdata *p)
/* Simplify adaptive */
if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_SETTINGS) &&
(brush->gpencil_settings->simplify_f > 0.0f)) {
BKE_gpencil_stroke_simplify_adaptive(gps, brush->gpencil_settings->simplify_f);
BKE_gpencil_stroke_simplify_adaptive(gpd, gps, brush->gpencil_settings->simplify_f);
}
/* reproject to plane (only in 3d space) */
@@ -1279,11 +1279,11 @@ static void gpencil_stroke_newfrombuffer(tGPsdata *p)
/* post process stroke */
if ((p->brush->gpencil_settings->flag & GP_BRUSH_GROUP_SETTINGS) &&
p->brush->gpencil_settings->flag & GP_BRUSH_TRIM_STROKE) {
BKE_gpencil_stroke_trim(gps);
BKE_gpencil_stroke_trim(gpd, gps);
}
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gpencil_stroke_added_enable(p);
}
@@ -1652,7 +1652,7 @@ static void gpencil_stroke_eraser_dostroke(tGPsdata *p,
gpencil_stroke_soft_refine(gps);
}
gpencil_stroke_delete_tagged_points(gpf, gps, gps->next, GP_SPOINT_TAG, false, 0);
gpencil_stroke_delete_tagged_points(p->gpd, gpf, gps, gps->next, GP_SPOINT_TAG, false, 0);
}
gpencil_update_cache(p->gpd);
}

View File

@@ -1082,7 +1082,7 @@ static void gpencil_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
}
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
/* Update evaluated data. */
ED_gpencil_sbuffer_update_eval(tgpi->gpd, tgpi->ob_eval);
@@ -1323,7 +1323,7 @@ static void gpencil_primitive_interaction_end(bContext *C,
copy_v2_v2(gps->aspect_ratio, brush_settings->aspect_ratio);
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(tgpi->gpd, gps);
}
/* transfer stroke from temporary buffer to the actual frame */

View File

@@ -303,7 +303,7 @@ static void gpencil_update_geometry(bGPdata *gpd)
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
if (gps->flag & GP_STROKE_TAG) {
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
gps->flag &= ~GP_STROKE_TAG;
}
}
@@ -1021,7 +1021,7 @@ static void gpencil_brush_clone_add(bContext *C, tGP_BrushEditData *gso)
bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_ADD_NEW);
/* Make a new stroke */
new_stroke = BKE_gpencil_stroke_duplicate(gps, true);
new_stroke = BKE_gpencil_stroke_duplicate(gps, true, true);
new_stroke->next = new_stroke->prev = NULL;
BLI_addtail(&gpf->strokes, new_stroke);
@@ -1574,6 +1574,7 @@ static bool gpencil_sculpt_brush_do_frame(bContext *C,
bool changed = false;
bool redo_geom = false;
Object *ob = gso->object;
bGPdata *gpd = ob->data;
char tool = gso->brush->gpencil_sculpt_tool;
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
@@ -1672,7 +1673,7 @@ static bool gpencil_sculpt_brush_do_frame(bContext *C,
MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
/* Update active frame now, only if material has fill. */
if (gp_style->flag & GP_MATERIAL_FILL_SHOW) {
BKE_gpencil_stroke_geometry_update(gps_active);
BKE_gpencil_stroke_geometry_update(gpd, gps_active);
}
else {
gpencil_recalc_geometry_tag(gps_active);

File diff suppressed because it is too large Load Diff

View File

@@ -352,13 +352,14 @@ void ED_gpencil_trace_data_to_strokes(Main *bmain,
* long stroke. Here the length is checked and removed if the length is too big. */
float length = BKE_gpencil_stroke_length(gps, true);
if (length <= MAX_LENGTH) {
bGPdata *gpd = ob->data;
if (sample > 0.0f) {
/* Resample stroke. Don't need to call to BKE_gpencil_stroke_geometry_update() because
* the sample function already call that. */
BKE_gpencil_stroke_sample(gps, sample, false);
BKE_gpencil_stroke_sample(gpd, gps, sample, false);
}
else {
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
}
}
else {

View File

@@ -55,6 +55,7 @@
#include "BKE_context.h"
#include "BKE_deform.h"
#include "BKE_gpencil.h"
#include "BKE_gpencil_curve.h"
#include "BKE_gpencil_geom.h"
#include "BKE_main.h"
#include "BKE_material.h"
@@ -1144,7 +1145,7 @@ void ED_gpencil_stroke_reproject(Depsgraph *depsgraph,
bGPDstroke *gps_active = gps;
/* if duplicate, deselect all points. */
if (keep_original) {
gps_active = BKE_gpencil_stroke_duplicate(gps, true);
gps_active = BKE_gpencil_stroke_duplicate(gps, true, true);
gps_active->flag &= ~GP_STROKE_SELECT;
for (i = 0, pt = gps_active->points; i < gps_active->totpoints; i++, pt++) {
pt->flag &= ~GP_SPOINT_SELECT;
@@ -1320,10 +1321,11 @@ void ED_gpencil_project_point_to_plane(const Scene *scene,
/**
* Subdivide a stroke once, by adding a point half way between each pair of existing points
* \param gpd: Datablock
* \param gps: Stroke data
* \param subdivide: Number of times to subdivide
*/
void gpencil_subdivide_stroke(bGPDstroke *gps, const int subdivide)
void gpencil_subdivide_stroke(bGPdata *gpd, bGPDstroke *gps, const int subdivide)
{
bGPDspoint *temp_points;
int totnewpoints, oldtotpoints;
@@ -1413,7 +1415,7 @@ void gpencil_subdivide_stroke(bGPDstroke *gps, const int subdivide)
MEM_SAFE_FREE(temp_points);
}
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
}
/* Reset parent matrix for all layers. */
@@ -2243,8 +2245,12 @@ static void gpencil_copy_points(
}
}
static void gpencil_insert_point(
bGPDstroke *gps, bGPDspoint *a_pt, bGPDspoint *b_pt, const float co_a[3], const float co_b[3])
static void gpencil_insert_point(bGPdata *gpd,
bGPDstroke *gps,
bGPDspoint *a_pt,
bGPDspoint *b_pt,
const float co_a[3],
float co_b[3])
{
bGPDspoint *temp_points;
int totnewpoints, oldtotpoints;
@@ -2303,8 +2309,8 @@ static void gpencil_insert_point(
i2++;
}
/* Calculate geometry data. */
BKE_gpencil_stroke_geometry_update(gps);
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(gpd, gps);
MEM_SAFE_FREE(temp_points);
}
@@ -2328,7 +2334,8 @@ static float gpencil_calc_factor(const float p2d_a1[2],
}
/* extend selection to stroke intersections */
int ED_gpencil_select_stroke_segment(bGPDlayer *gpl,
int ED_gpencil_select_stroke_segment(bGPdata *gpd,
bGPDlayer *gpl,
bGPDstroke *gps,
bGPDspoint *pt,
bool select,
@@ -2483,7 +2490,7 @@ int ED_gpencil_select_stroke_segment(bGPDlayer *gpl,
/* insert new point in the collision points */
if (insert) {
gpencil_insert_point(gps, hit_pointa, hit_pointb, r_hita, r_hitb);
gpencil_insert_point(gpd, gps, hit_pointa, hit_pointb, r_hita, r_hitb);
}
/* free memory */
@@ -2611,6 +2618,82 @@ void ED_gpencil_select_toggle_all(bContext *C, int action)
}
}
void ED_gpencil_select_curve_toggle_all(bContext *C, int action)
{
/* if toggle, check if we need to select or deselect */
if (action == SEL_TOGGLE) {
action = SEL_SELECT;
GP_EDITABLE_CURVES_BEGIN(gps_iter, C, gpl, gps, gpc)
{
if (gpc->flag & GP_CURVE_SELECT) {
action = SEL_DESELECT;
}
}
GP_EDITABLE_CURVES_END(gps_iter);
}
if (action == SEL_DESELECT) {
GP_EDITABLE_CURVES_BEGIN(gps_iter, C, gpl, gps, gpc)
{
for (int i = 0; i < gpc->tot_curve_points; i++) {
bGPDcurve_point *gpc_pt = &gpc->curve_points[i];
BezTriple *bezt = &gpc_pt->bezt;
gpc_pt->flag &= ~GP_CURVE_POINT_SELECT;
BEZT_DESEL_ALL(bezt);
}
gpc->flag &= ~GP_CURVE_SELECT;
gps->flag &= ~GP_STROKE_SELECT;
}
GP_EDITABLE_CURVES_END(gps_iter);
}
else {
GP_EDITABLE_STROKES_BEGIN(gps_iter, C, gpl, gps){
Object *ob = CTX_data_active_object(C);
bGPdata *gpd = ob->data;
bool selected = false;
/* Make sure stroke has an editcurve */
if (gps->editcurve == NULL) {
BKE_gpencil_stroke_editcurve_update(gpd, gpl, gps);
gps->flag |= GP_STROKE_NEEDS_CURVE_UPDATE;
BKE_gpencil_stroke_geometry_update(gpd, gps);
}
bGPDcurve *gpc = gps->editcurve;
for (int i = 0; i < gpc->tot_curve_points; i++) {
bGPDcurve_point *gpc_pt = &gpc->curve_points[i];
BezTriple *bezt = &gpc_pt->bezt;
switch (action) {
case SEL_SELECT:
gpc_pt->flag |= GP_CURVE_POINT_SELECT;
BEZT_SEL_ALL(bezt);
break;
case SEL_INVERT:
gpc_pt->flag ^= GP_CURVE_POINT_SELECT;
BEZT_SEL_INVERT(bezt);
break;
default:
break;
}
if (gpc_pt->flag & GP_CURVE_POINT_SELECT) {
selected = true;
}
}
if (selected) {
gpc->flag |= GP_CURVE_SELECT;
gps->flag |= GP_STROKE_SELECT;
}
else {
gpc->flag &= ~GP_CURVE_SELECT;
gps->flag &= ~GP_STROKE_SELECT;
}
}
GP_EDITABLE_STROKES_END(gps_iter);
}
}
/**
* Ensure the #tGPspoint buffer (while drawing stroke)
* size is enough to save all points of the stroke.

View File

@@ -273,7 +273,7 @@ static bool gpencil_uv_transform_calc(bContext *C, wmOperator *op)
changed = true;
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
i++;
}
}
@@ -291,7 +291,7 @@ static bool gpencil_uv_transform_calc(bContext *C, wmOperator *op)
gps->uv_rotation = opdata->array_rot[i] - uv_rotation;
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
i++;
}
}
@@ -316,7 +316,7 @@ static bool gpencil_uv_transform_calc(bContext *C, wmOperator *op)
if (gps->flag & GP_STROKE_SELECT) {
gps->uv_scale = opdata->array_scale[i] + scale;
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
i++;
}
}
@@ -512,7 +512,7 @@ static int gpencil_reset_transform_fill_exec(bContext *C, wmOperator *op)
gps->uv_scale = 1.0f;
}
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
changed = true;
}
}

View File

@@ -819,8 +819,9 @@ static void gpencil_save_selected_point(tGP_BrushVertexpaintData *gso,
gso->pbuffer_used++;
}
/* Select points in this stroke and add to an array to be used later. */
static void gpencil_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso,
/* Select points in this stroke and add to an array to be used later.
* Returns true if any point was hit and got saved */
static bool gpencil_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso,
bGPDstroke *gps,
const char tool,
const float diff_mat[4][4])
@@ -841,9 +842,11 @@ static void gpencil_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso,
int index;
bool include_last = false;
bool saved = false;
/* Check if the stroke collide with brush. */
if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, diff_mat)) {
return;
return false;
}
if (gps->totpoints == 1) {
@@ -862,6 +865,7 @@ static void gpencil_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso,
/* apply operation to this point */
if (pt_active != NULL) {
gpencil_save_selected_point(gso, gps_active, 0, pc1);
saved = true;
}
}
}
@@ -913,6 +917,7 @@ static void gpencil_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso,
}
hit = true;
gpencil_save_selected_point(gso, gps_active, index, pc1);
saved = true;
}
/* Only do the second point if this is the last segment,
@@ -931,6 +936,7 @@ static void gpencil_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso,
hit = true;
gpencil_save_selected_point(gso, gps_active, index, pc2);
include_last = false;
saved = true;
}
}
else {
@@ -949,8 +955,8 @@ static void gpencil_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso,
if (pt_active != NULL) {
hit = true;
gpencil_save_selected_point(gso, gps_active, index, pc1);
include_last = false;
saved = true;
}
}
}
@@ -970,10 +976,13 @@ static void gpencil_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso,
for (int repeat = 0; repeat < 50; repeat++) {
gpencil_save_selected_point(gso, gps_active, -1, NULL);
}
saved = true;
}
}
}
}
return saved;
}
/* Apply vertex paint brushes to strokes in the given frame. */
@@ -1008,7 +1017,13 @@ static bool gpencil_vertexpaint_brush_do_frame(bContext *C,
}
/* Check points below the brush. */
gpencil_vertexpaint_select_stroke(gso, gps, tool, diff_mat);
bool hit = gpencil_vertexpaint_select_stroke(gso, gps, tool, diff_mat);
/* If stroke was hit and has an editcurve the curve needs an update. */
bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps;
if (gps_active->editcurve != NULL && hit) {
gps_active->editcurve->flag |= GP_CURVE_NEEDS_STROKE_UPDATE;
}
}
/* For Average tool, need calculate the average resulting color from all colors

View File

@@ -314,7 +314,8 @@ void ED_gpencil_update_color_uv(struct Main *bmain, struct Material *mat);
* 2 - Hit in point B
* 3 - Hit in point A and B
*/
int ED_gpencil_select_stroke_segment(struct bGPDlayer *gpl,
int ED_gpencil_select_stroke_segment(struct bGPdata *gpd,
struct bGPDlayer *gpl,
struct bGPDstroke *gps,
struct bGPDspoint *pt,
bool select,
@@ -324,6 +325,7 @@ int ED_gpencil_select_stroke_segment(struct bGPDlayer *gpl,
float r_hitb[3]);
void ED_gpencil_select_toggle_all(struct bContext *C, int action);
void ED_gpencil_select_curve_toggle_all(struct bContext *C, int action);
/* Ensure stroke sbuffer size is enough */
struct tGPspoint *ED_gpencil_sbuffer_ensure(struct tGPspoint *buffer_array,

View File

@@ -1738,6 +1738,10 @@ static void ed_default_handlers(
wmKeyMap *keymap_general = WM_keymap_ensure(wm->defaultconf, "Grease Pencil", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_general);
wmKeyMap *keymap_curve_edit = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Curve Edit Mode", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_curve_edit);
wmKeyMap *keymap_edit = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Edit Mode", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_edit);

View File

@@ -31,7 +31,9 @@
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_gpencil.h"
#include "BKE_gpencil_curve.h"
#include "BKE_gpencil_geom.h"
#include "ED_gpencil.h"
@@ -63,33 +65,351 @@ static void createTransGPencil_center_get(bGPDstroke *gps, float r_center[3])
}
}
void createTransGPencil(bContext *C, TransInfo *t)
static short get_bezt_sel_triple_flag(BezTriple *bezt, const bool handles_visible)
{
if (t->data_container_len == 0) {
#define SEL_F1 (1 << 0)
#define SEL_F2 (1 << 1)
#define SEL_F3 (1 << 2)
#define SEL_ALL ((1 << 0) | (1 << 1) | (1 << 2))
short flag = 0;
if (handles_visible) {
flag = ((bezt->f1 & SELECT) ? SEL_F1 : 0) | ((bezt->f2 & SELECT) ? SEL_F2 : 0) |
((bezt->f3 & SELECT) ? SEL_F3 : 0);
}
else {
if (bezt->f2 & SELECT) {
flag = SEL_ALL;
}
}
/* Special case for auto & aligned handles */
if (flag != SEL_ALL && flag & SEL_F2) {
if (ELEM(bezt->h1, HD_AUTO, HD_ALIGN) && ELEM(bezt->h2, HD_AUTO, HD_ALIGN)) {
flag = SEL_ALL;
}
}
#undef SEL_F1
#undef SEL_F2
#undef SEL_F3
return flag;
}
static void createTransGPencil_curves(bContext *C,
TransInfo *t,
Depsgraph *depsgraph,
ToolSettings *ts,
Object *obact,
bGPdata *gpd,
const int cfra_scene,
const bool is_multiedit,
const bool use_multiframe_falloff,
const bool is_prop_edit,
const bool is_prop_edit_connected,
const bool is_scale_thickness)
{
#define SEL_F1 (1 << 0)
#define SEL_F2 (1 << 1)
#define SEL_F3 (1 << 2)
View3D *v3d = t->view;
const bool handle_only_selected_visible = (v3d->overlay.handle_display == CURVE_HANDLE_SELECTED);
const bool handle_all_visible = (v3d->overlay.handle_display == CURVE_HANDLE_ALL);
TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
tc->data_len = 0;
/* Number of selected curve points */
uint32_t tot_curve_points = 0, tot_sel_curve_points = 0, tot_points = 0, tot_sel_points = 0;
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* Only editable and visible layers are considered. */
if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
}
/* Check if the color is editable. */
if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) {
continue;
}
/* Check if stroke has an editcurve */
if (gps->editcurve == NULL) {
continue;
}
bGPDcurve *gpc = gps->editcurve;
for (int i = 0; i < gpc->tot_curve_points; i++) {
bGPDcurve_point *gpc_pt = &gpc->curve_points[i];
BezTriple *bezt = &gpc_pt->bezt;
if (bezt->hide) {
continue;
}
const bool handles_visible = (handle_all_visible ||
(handle_only_selected_visible &&
(gpc_pt->flag & GP_CURVE_POINT_SELECT)));
const short sel_flag = get_bezt_sel_triple_flag(bezt, handles_visible);
if (sel_flag & (SEL_F1 | SEL_F2 | SEL_F3)) {
if (sel_flag & SEL_F1) {
tot_sel_points++;
}
if (sel_flag & SEL_F2) {
tot_sel_points++;
}
if (sel_flag & SEL_F3) {
tot_sel_points++;
}
tot_sel_curve_points++;
}
if (is_prop_edit) {
tot_points += 3;
tot_curve_points++;
}
}
}
}
/* If not multiedit out of loop. */
if (!is_multiedit) {
break;
}
}
}
}
if (((is_prop_edit && !is_prop_edit_connected) ? tot_curve_points : tot_sel_points) == 0) {
tc->data_len = 0;
return;
}
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
bGPdata *gpd = ED_gpencil_data_get_active(C);
ToolSettings *ts = CTX_data_tool_settings(C);
int data_len_pt = 0;
bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
bool use_multiframe_falloff = (ts->gp_sculpt.flag & GP_SCULPT_SETT_FLAG_FRAME_FALLOFF) != 0;
if (is_prop_edit) {
tc->data_len = tot_points;
data_len_pt = tot_curve_points;
}
else {
tc->data_len = tot_sel_points;
data_len_pt = tot_sel_curve_points;
}
Object *obact = CTX_data_active_object(C);
if (tc->data_len == 0) {
return;
}
transform_around_single_fallback_ex(t, data_len_pt);
tc->data = MEM_callocN(tc->data_len * sizeof(TransData), __func__);
TransData *td = tc->data;
const bool use_around_origins_for_handles_test = ((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
transform_mode_use_local_origins(t));
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* Only editable and visible layers are considered. */
if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
const int cfra = (gpl->flag & GP_LAYER_FRAMELOCK) ? gpl->actframe->framenum : cfra_scene;
bGPDframe *gpf = gpl->actframe;
bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
float diff_mat[4][4], mtx[3][3];
float smtx[3][3];
/* Init multiframe falloff options. */
int f_init = 0;
int f_end = 0;
if (use_multiframe_falloff) {
BKE_gpencil_frame_range_selected(gpl, &f_init, &f_end);
}
if ((gpf->framenum != cfra) && (!is_multiedit)) {
gpf = BKE_gpencil_frame_addcopy(gpl, cfra);
/* in some weird situations (framelock enabled) return NULL */
if (gpf == NULL) {
continue;
}
if (!is_multiedit) {
init_gpf = gpf;
}
}
/* Calculate difference matrix. */
BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat);
copy_m3_m4(mtx, diff_mat);
pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
for (gpf = init_gpf; gpf; gpf = gpf->next) {
if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
/* If multi-frame and falloff, recalculate and save value. */
float falloff = 1.0f; /* by default no falloff */
if ((is_multiedit) && (use_multiframe_falloff)) {
/* Falloff depends on distance to active frame
* (relative to the overall frame range). */
falloff = BKE_gpencil_multiframe_falloff_calc(
gpf, gpl->actframe->framenum, f_init, f_end, ts->gp_sculpt.cur_falloff);
}
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
}
/* Check if the color is editable. */
if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) {
continue;
}
/* Check if stroke has an editcurve */
if (gps->editcurve == NULL) {
continue;
}
TransData *head, *tail;
head = tail = td;
gps->runtime.multi_frame_falloff = falloff;
bool need_handle_recalc = false;
bGPDcurve *gpc = gps->editcurve;
const bool is_cyclic = gps->flag & GP_STROKE_CYCLIC;
for (int i = 0; i < gpc->tot_curve_points; i++) {
bGPDcurve_point *gpc_pt = &gpc->curve_points[i];
BezTriple *bezt = &gpc_pt->bezt;
if (bezt->hide) {
continue;
}
TransDataCurveHandleFlags *hdata = NULL;
bool bezt_use = false;
const bool handles_visible = (handle_all_visible ||
(handle_only_selected_visible &&
(gpc_pt->flag & GP_CURVE_POINT_SELECT)));
const short sel_flag = get_bezt_sel_triple_flag(bezt, handles_visible);
/* Iterate over bezier triple */
for (int j = 0; j < 3; j++) {
bool is_ctrl_point = (j == 1);
bool sel = sel_flag & (1 << j);
if (is_prop_edit || sel) {
copy_v3_v3(td->iloc, bezt->vec[j]);
td->loc = bezt->vec[j];
bool rotate_around_ctrl = !handles_visible ||
(t->around == V3D_AROUND_LOCAL_ORIGINS) ||
(bezt->f2 & SELECT);
copy_v3_v3(td->center, bezt->vec[rotate_around_ctrl ? 1 : j]);
if (!handles_visible || is_ctrl_point) {
if (bezt->f2 & SELECT) {
td->flag = TD_SELECTED;
}
else {
td->flag = 0;
}
}
else if (handles_visible) {
if (BEZT_ISSEL_IDX(bezt, j)) {
td->flag = TD_SELECTED;
}
else {
td->flag = 0;
}
}
td->ext = NULL;
if (is_ctrl_point) {
if (t->mode != TFM_MIRROR) {
if (t->mode != TFM_GPENCIL_OPACITY) {
if (is_scale_thickness) {
td->val = &(gpc_pt->pressure);
td->ival = gpc_pt->pressure;
}
}
else {
td->val = &(gpc_pt->strength);
td->ival = gpc_pt->strength;
}
}
}
else {
td->val = NULL;
}
if (hdata == NULL) {
if (is_ctrl_point && ((sel_flag & SEL_F1 & SEL_F3) == 0)) {
hdata = initTransDataCurveHandles(td, bezt);
}
else if (!is_ctrl_point) {
hdata = initTransDataCurveHandles(td, bezt);
}
}
td->extra = gps;
td->ob = obact;
copy_m3_m3(td->smtx, smtx);
copy_m3_m3(td->mtx, mtx);
copy_m3_m3(td->axismtx, mtx);
td++;
tail++;
}
bezt_use |= sel;
}
/* Update the handle types so transformation is possible */
if (bezt_use && !ELEM(t->mode, TFM_GPENCIL_OPACITY, TFM_GPENCIL_SHRINKFATTEN)) {
BKE_nurb_bezt_handle_test(
bezt, SELECT, handles_visible, use_around_origins_for_handles_test);
need_handle_recalc = true;
}
}
if (is_prop_edit && (head != tail)) {
calc_distanceCurveVerts(head, tail - 1, is_cyclic);
}
if (need_handle_recalc) {
BKE_gpencil_editcurve_recalculate_handles(gps);
}
}
}
/* If not multiedit out of loop. */
if (!is_multiedit) {
break;
}
}
}
}
#undef SEL_F1
#undef SEL_F2
#undef SEL_F3
}
static void createTransGPencil_strokes(bContext *C,
TransInfo *t,
Depsgraph *depsgraph,
ToolSettings *ts,
Object *obact,
bGPdata *gpd,
const int cfra_scene,
const bool is_multiedit,
const bool use_multiframe_falloff,
const bool is_prop_edit,
const bool is_prop_edit_connected,
const bool is_scale_thickness)
{
TransData *td = NULL;
float mtx[3][3], smtx[3][3];
const Scene *scene = CTX_data_scene(C);
const int cfra_scene = CFRA;
const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
const bool is_prop_edit_connected = (t->flag & T_PROP_CONNECTED) != 0;
const bool is_scale_thickness = ((t->mode == TFM_GPENCIL_SHRINKFATTEN) ||
(ts->gp_sculpt.flag & GP_SCULPT_SETT_FLAG_SCALE_THICKNESS));
TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
/* == Grease Pencil Strokes to Transform Data ==
* Grease Pencil stroke points can be a mixture of 2D (screen-space),
* or 3D coordinates. However, they're always saved as 3D points.
@@ -98,15 +418,6 @@ void createTransGPencil(bContext *C, TransInfo *t)
*/
tc->data_len = 0;
if (gpd == NULL) {
return;
}
/* initialize falloff curve */
if (is_multiedit) {
BKE_curvemapping_init(ts->gp_sculpt.cur_falloff);
}
/* First Pass: Count the number of data-points required for the strokes,
* (and additional info about the configuration - e.g. 2D/3D?).
*/
@@ -368,6 +679,71 @@ void createTransGPencil(bContext *C, TransInfo *t)
}
}
void createTransGPencil(bContext *C, TransInfo *t)
{
if (t->data_container_len == 0) {
return;
}
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
const Scene *scene = CTX_data_scene(C);
ToolSettings *ts = scene->toolsettings;
Object *obact = CTX_data_active_object(C);
bGPdata *gpd = obact->data;
BLI_assert(gpd != NULL);
const int cfra_scene = CFRA;
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
const bool use_multiframe_falloff = (ts->gp_sculpt.flag & GP_SCULPT_SETT_FLAG_FRAME_FALLOFF) !=
0;
const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
const bool is_prop_edit_connected = (t->flag & T_PROP_CONNECTED) != 0;
const bool is_scale_thickness = ((t->mode == TFM_GPENCIL_SHRINKFATTEN) ||
(ts->gp_sculpt.flag & GP_SCULPT_SETT_FLAG_SCALE_THICKNESS));
const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
/* initialize falloff curve */
if (is_multiedit) {
BKE_curvemapping_init(ts->gp_sculpt.cur_falloff);
}
if (gpd == NULL) {
return;
}
if (is_curve_edit) {
createTransGPencil_curves(C,
t,
depsgraph,
ts,
obact,
gpd,
cfra_scene,
is_multiedit,
use_multiframe_falloff,
is_prop_edit,
is_prop_edit_connected,
is_scale_thickness);
}
else {
createTransGPencil_strokes(C,
t,
depsgraph,
ts,
obact,
gpd,
cfra_scene,
is_multiedit,
use_multiframe_falloff,
is_prop_edit,
is_prop_edit_connected,
is_scale_thickness);
}
}
/* force recalculation of triangles during transformation */
void recalcData_gpencil_strokes(TransInfo *t)
{
@@ -375,13 +751,19 @@ void recalcData_gpencil_strokes(TransInfo *t)
GHash *strokes = BLI_ghash_ptr_new(__func__);
TransData *td = tc->data;
bGPdata *gpd = td->ob->data;
const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
for (int i = 0; i < tc->data_len; i++, td++) {
bGPDstroke *gps = td->extra;
if ((gps != NULL) && (!BLI_ghash_haskey(strokes, gps))) {
BLI_ghash_insert(strokes, gps, gps);
if (is_curve_edit && gps->editcurve != NULL) {
BKE_gpencil_editcurve_recalculate_handles(gps);
gps->flag |= GP_STROKE_NEEDS_CURVE_UPDATE;
}
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
}
}
BLI_ghash_free(strokes, NULL, NULL);

View File

@@ -799,7 +799,7 @@ void postTrans(bContext *C, TransInfo *t)
if (t->data_len_all != 0) {
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
/* free data malloced per trans-data */
if (ELEM(t->obedit_type, OB_CURVE, OB_SURF) || (t->spacetype == SPACE_GRAPH)) {
if (ELEM(t->obedit_type, OB_CURVE, OB_SURF, OB_GPENCIL) || (t->spacetype == SPACE_GRAPH)) {
TransData *td = tc->data;
for (int a = 0; a < tc->data_len; a++, td++) {
if (td->flag & TD_BEZTRIPLE) {

View File

@@ -653,6 +653,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
Object *ob = OBACT(view_layer);
bGPdata *gpd = CTX_data_gpencil_data(C);
const bool is_gp_edit = GPENCIL_ANY_MODE(gpd);
const bool is_curve_edit = GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
int a, totsel = 0;
const int pivot_point = scene->toolsettings->transform_pivot_point;
@@ -711,16 +712,39 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
continue;
}
/* we're only interested in selected points here... */
if (gps->flag & GP_STROKE_SELECT) {
bGPDspoint *pt;
int i;
if (is_curve_edit) {
if (gps->editcurve == NULL) {
continue;
}
/* Change selection status of all points, then make the stroke match */
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
if (pt->flag & GP_SPOINT_SELECT) {
calc_tw_center_with_matrix(tbounds, &pt->x, use_mat_local, diff_mat);
totsel++;
bGPDcurve *gpc = gps->editcurve;
if (gpc->flag & GP_CURVE_SELECT) {
for (uint32_t i = 0; i < gpc->tot_curve_points; i++) {
bGPDcurve_point *gpc_pt = &gpc->curve_points[i];
BezTriple *bezt = &gpc_pt->bezt;
if (gpc_pt->flag & GP_CURVE_POINT_SELECT) {
for (uint32_t j = 0; j < 3; j++) {
if (BEZT_ISSEL_IDX(bezt, j)) {
calc_tw_center_with_matrix(tbounds, bezt->vec[j], use_mat_local, diff_mat);
totsel++;
}
}
}
}
}
}
else {
/* we're only interested in selected points here... */
if (gps->flag & GP_STROKE_SELECT) {
bGPDspoint *pt;
int i;
/* Change selection status of all points, then make the stroke match */
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
if (pt->flag & GP_SPOINT_SELECT) {
calc_tw_center_with_matrix(tbounds, &pt->x, use_mat_local, diff_mat);
totsel++;
}
}
}
}

View File

@@ -29,6 +29,8 @@
#include "BKE_context.h"
#include "BKE_unit.h"
#include "DNA_gpencil_types.h"
#include "ED_screen.h"
#include "UI_interface.h"
@@ -68,8 +70,16 @@ static void applyGPOpacity(TransInfo *t, const int UNUSED(mval[2]))
BLI_snprintf(str, sizeof(str), TIP_("Opacity: %3f"), ratio);
}
bool recalc = false;
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
bGPdata *gpd = td->ob->data;
const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
/* Only recalculate data when in curve edit mode. */
if (is_curve_edit) {
recalc = true;
}
for (i = 0; i < tc->data_len; i++, td++) {
if (td->flag & TD_SKIP) {
continue;
@@ -84,6 +94,10 @@ static void applyGPOpacity(TransInfo *t, const int UNUSED(mval[2]))
}
}
if (recalc) {
recalcData(t);
}
ED_area_status_text(t->area, str);
}

View File

@@ -29,6 +29,8 @@
#include "BKE_context.h"
#include "BKE_unit.h"
#include "DNA_gpencil_types.h"
#include "ED_screen.h"
#include "UI_interface.h"
@@ -68,8 +70,16 @@ static void applyGPShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
BLI_snprintf(str, sizeof(str), TIP_("Shrink/Fatten: %3f"), ratio);
}
bool recalc = false;
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
bGPdata *gpd = td->ob->data;
const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
/* Only recalculate data when in curve edit mode. */
if (is_curve_edit) {
recalc = true;
}
for (i = 0; i < tc->data_len; i++, td++) {
if (td->flag & TD_SKIP) {
continue;
@@ -86,6 +96,10 @@ static void applyGPShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
}
}
if (recalc) {
recalcData(t);
}
ED_area_status_text(t->area, str);
}

View File

@@ -125,10 +125,11 @@ static void deformStroke(GpencilModifierData *md,
if (!mmd->object) {
return;
}
bGPdata *gpd = ob->data;
gpencil_deform_verts(mmd, ob, gps);
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
}
static void bakeModifier(Main *UNUSED(bmain),

View File

@@ -255,7 +255,7 @@ static void generate_geometry(GpencilModifierData *md,
/* Duplicate original strokes to create this instance. */
LISTBASE_FOREACH_BACKWARD (tmpStrokes *, iter, &stroke_cache) {
/* Duplicate stroke */
bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(iter->gps, true);
bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(iter->gps, true, true);
/* Move points */
for (int i = 0; i < iter->gps->totpoints; i++) {

View File

@@ -115,7 +115,8 @@ static void gpf_clear_all_strokes(bGPDframe *gpf)
*
* Note: This won't be called if all points are present/removed
*/
static void reduce_stroke_points(bGPDstroke *gps,
static void reduce_stroke_points(bGPdata *gpd,
bGPDstroke *gps,
const int num_points,
const eBuildGpencil_Transition transition)
{
@@ -180,7 +181,7 @@ static void reduce_stroke_points(bGPDstroke *gps,
gps->totpoints = num_points;
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
}
/* --------------------------------------------- */
@@ -197,7 +198,10 @@ typedef struct tStrokeBuildDetails {
} tStrokeBuildDetails;
/* Sequential - Show strokes one after the other */
static void build_sequential(BuildGpencilModifierData *mmd, bGPDframe *gpf, float fac)
static void build_sequential(BuildGpencilModifierData *mmd,
bGPdata *gpd,
bGPDframe *gpf,
float fac)
{
const size_t tot_strokes = BLI_listbase_count(&gpf->strokes);
bGPDstroke *gps;
@@ -236,25 +240,25 @@ static void build_sequential(BuildGpencilModifierData *mmd, bGPDframe *gpf, floa
size_t last_visible = 0;
switch (mmd->transition) {
/* Show in forward order
* - As fac increases, the number of visible points increases
*/
/* Show in forward order
* - As fac increases, the number of visible points increases
*/
case GP_BUILD_TRANSITION_GROW:
first_visible = 0; /* always visible */
last_visible = (size_t)roundf(totpoints * fac);
break;
/* Hide in reverse order
* - As fac increases, the number of points visible at the end decreases
*/
/* Hide in reverse order
* - As fac increases, the number of points visible at the end decreases
*/
case GP_BUILD_TRANSITION_SHRINK:
first_visible = 0; /* always visible (until last point removed) */
last_visible = (size_t)(totpoints * (1.0f - fac));
break;
/* Hide in forward order
* - As fac increases, the early points start getting hidden
*/
/* Hide in forward order
* - As fac increases, the early points start getting hidden
*/
case GP_BUILD_TRANSITION_FADE:
first_visible = (size_t)(totpoints * fac);
last_visible = totpoints; /* i.e. visible until the end, unless first overlaps this */
@@ -278,12 +282,12 @@ static void build_sequential(BuildGpencilModifierData *mmd, bGPDframe *gpf, floa
else if (first_visible > cell->start_idx) {
/* Starts partway through this stroke */
int num_points = cell->end_idx - first_visible;
reduce_stroke_points(cell->gps, num_points, mmd->transition);
reduce_stroke_points(gpd, cell->gps, num_points, mmd->transition);
}
else {
/* Ends partway through this stroke */
int num_points = last_visible - cell->start_idx;
reduce_stroke_points(cell->gps, num_points, mmd->transition);
reduce_stroke_points(gpd, cell->gps, num_points, mmd->transition);
}
}
}
@@ -295,7 +299,10 @@ static void build_sequential(BuildGpencilModifierData *mmd, bGPDframe *gpf, floa
/* --------------------------------------------- */
/* Concurrent - Show multiple strokes at once */
static void build_concurrent(BuildGpencilModifierData *mmd, bGPDframe *gpf, float fac)
static void build_concurrent(BuildGpencilModifierData *mmd,
bGPdata *gpd,
bGPDframe *gpf,
float fac)
{
bGPDstroke *gps, *gps_next;
int max_points = 0;
@@ -390,16 +397,14 @@ static void build_concurrent(BuildGpencilModifierData *mmd, bGPDframe *gpf, floa
}
else if (num_points < gps->totpoints) {
/* Remove some points */
reduce_stroke_points(gps, num_points, mmd->transition);
reduce_stroke_points(gpd, gps, num_points, mmd->transition);
}
}
}
/* --------------------------------------------- */
static void generate_geometry(GpencilModifierData *md,
Depsgraph *depsgraph,
bGPDlayer *gpl,
bGPDframe *gpf)
static void generate_geometry(
GpencilModifierData *md, Depsgraph *depsgraph, bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf)
{
BuildGpencilModifierData *mmd = (BuildGpencilModifierData *)md;
const bool reverse = (mmd->transition != GP_BUILD_TRANSITION_GROW);
@@ -504,11 +509,11 @@ static void generate_geometry(GpencilModifierData *md,
/* Time management mode */
switch (mmd->mode) {
case GP_BUILD_MODE_SEQUENTIAL:
build_sequential(mmd, gpf, fac);
build_sequential(mmd, gpd, gpf, fac);
break;
case GP_BUILD_MODE_CONCURRENT:
build_concurrent(mmd, gpf, fac);
build_concurrent(mmd, gpd, gpf, fac);
break;
default:
@@ -530,7 +535,7 @@ static void generateStrokes(GpencilModifierData *md, Depsgraph *depsgraph, Objec
if (gpf == NULL) {
continue;
}
generate_geometry(md, depsgraph, gpl, gpf);
generate_geometry(md, depsgraph, gpd, gpl, gpf);
}
}

View File

@@ -228,6 +228,7 @@ static void deformStroke(GpencilModifierData *md,
mmd->flag & GP_HOOK_INVERT_MATERIAL)) {
return;
}
bGPdata *gpd = ob->data;
/* init struct */
tData.curfalloff = mmd->curfalloff;
@@ -273,7 +274,7 @@ static void deformStroke(GpencilModifierData *md,
gpencil_hook_co_apply(&tData, weight, pt);
}
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
}
/* FIXME: Ideally we be doing this on a copy of the main depsgraph

View File

@@ -85,6 +85,7 @@ static void deformStroke(GpencilModifierData *md,
bGPDframe *UNUSED(gpf),
bGPDstroke *gps)
{
bGPdata *gpd = ob->data;
LatticeGpencilModifierData *mmd = (LatticeGpencilModifierData *)md;
const int def_nr = BKE_object_defgroup_name_index(ob, mmd->vgname);
@@ -121,7 +122,7 @@ static void deformStroke(GpencilModifierData *md,
(struct LatticeDeformData *)mmd->cache_data, &pt->x, mmd->strength * weight);
}
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
}
/* FIXME: Ideally we be doing this on a copy of the main depsgraph

View File

@@ -151,7 +151,7 @@ static void generate_geometry(GpencilModifierData *md, Object *ob, bGPDlayer *gp
mmd->flag & GP_MIRROR_INVERT_PASS,
mmd->flag & GP_MIRROR_INVERT_LAYERPASS,
mmd->flag & GP_MIRROR_INVERT_MATERIAL)) {
gps_new = BKE_gpencil_stroke_duplicate(gps, true);
gps_new = BKE_gpencil_stroke_duplicate(gps, true, true);
update_position(ob, mmd, gps_new, xi);
BLI_addtail(&gpf->strokes, gps_new);
}

View File

@@ -129,6 +129,7 @@ static void duplicateStroke(Object *ob,
float fading_thickness,
float fading_opacity)
{
bGPdata *gpd = ob->data;
int i;
bGPDstroke *new_gps = NULL;
float stroke_normal[3];
@@ -172,7 +173,7 @@ static void duplicateStroke(Object *ob,
* to be processed, since we duplicate its data. */
for (i = count - 1; i >= 0; i--) {
if (i != 0) {
new_gps = BKE_gpencil_stroke_duplicate(gps, true);
new_gps = BKE_gpencil_stroke_duplicate(gps, true, true);
BLI_addtail(results, new_gps);
}
else {
@@ -199,7 +200,7 @@ static void duplicateStroke(Object *ob,
}
/* Calc geometry data. */
if (new_gps != NULL) {
BKE_gpencil_stroke_geometry_update(new_gps);
BKE_gpencil_stroke_geometry_update(gpd, new_gps);
}
MEM_freeN(t1_array);
MEM_freeN(t2_array);

View File

@@ -100,6 +100,7 @@ static void deformStroke(GpencilModifierData *md,
mmd->flag & GP_OFFSET_INVERT_MATERIAL)) {
return;
}
bGPdata *gpd = ob->data;
for (int i = 0; i < gps->totpoints; i++) {
bGPDspoint *pt = &gps->points[i];
@@ -125,7 +126,7 @@ static void deformStroke(GpencilModifierData *md,
mul_m4_v3(mat, &pt->x);
}
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
}
static void bakeModifier(struct Main *UNUSED(bmain),

View File

@@ -92,26 +92,26 @@ static void deformStroke(GpencilModifierData *md,
mmd->flag & GP_SIMPLIFY_INVERT_MATERIAL)) {
return;
}
bGPdata *gpd = ob->data;
/* Select simplification mode. */
switch (mmd->mode) {
case GP_SIMPLIFY_FIXED: {
for (int i = 0; i < mmd->step; i++) {
BKE_gpencil_stroke_simplify_fixed(gps);
BKE_gpencil_stroke_simplify_fixed(gpd, gps);
}
break;
}
case GP_SIMPLIFY_ADAPTIVE: {
/* simplify stroke using Ramer-Douglas-Peucker algorithm */
BKE_gpencil_stroke_simplify_adaptive(gps, mmd->factor);
BKE_gpencil_stroke_simplify_adaptive(gpd, gps, mmd->factor);
break;
}
case GP_SIMPLIFY_SAMPLE: {
BKE_gpencil_stroke_sample(gps, mmd->length, false);
BKE_gpencil_stroke_sample(gpd, gps, mmd->length, false);
break;
}
case GP_SIMPLIFY_MERGE: {
BKE_gpencil_stroke_merge_distance(gpf, gps, mmd->distance, true);
BKE_gpencil_stroke_merge_distance(gpd, gpf, gps, mmd->distance, true);
break;
}
default:

View File

@@ -80,6 +80,7 @@ static void deformStroke(GpencilModifierData *md,
bGPDstroke *gps)
{
SubdivGpencilModifierData *mmd = (SubdivGpencilModifierData *)md;
bGPdata *gpd = ob->data;
/* It makes sense when adding points to a straight line */
/* e.g. for creating thickness variation in later modifiers. */
@@ -100,7 +101,7 @@ static void deformStroke(GpencilModifierData *md,
return;
}
BKE_gpencil_stroke_subdivide(gps, mmd->level, mmd->type);
BKE_gpencil_stroke_subdivide(gpd, gps, mmd->level, mmd->type);
/* If the stroke is cyclic, must generate the closing geometry. */
if (gps->flag & GP_STROKE_CYCLIC) {

View File

@@ -82,6 +82,7 @@ static void deformStroke(GpencilModifierData *md,
{
TextureGpencilModifierData *mmd = (TextureGpencilModifierData *)md;
const int def_nr = BKE_object_defgroup_name_index(ob, mmd->vgname);
bGPdata *gpd = ob->data;
if (!is_stroke_affected_by_modifier(ob,
mmd->layername,
@@ -102,7 +103,7 @@ static void deformStroke(GpencilModifierData *md,
gps->uv_translation[0] += mmd->fill_offset[0];
gps->uv_translation[1] += mmd->fill_offset[1];
gps->uv_scale *= mmd->fill_scale;
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
}
if (ELEM(mmd->mode, STROKE, STROKE_AND_FILL)) {

View File

@@ -519,6 +519,10 @@ typedef enum eBezTriple_KeyframeType {
(bezt)->f2 & SELECT : \
BEZT_ISSEL_ANY(bezt))
#define BEZT_ISSEL_IDX(bezt, i) \
((i == 0 && (bezt)->f1 & SELECT) || (i == 1 && (bezt)->f2 & SELECT) || \
(i == 2 && (bezt)->f3 & SELECT))
#define BEZT_SEL_ALL(bezt) \
{ \
(bezt)->f1 |= SELECT; \
@@ -533,6 +537,49 @@ typedef enum eBezTriple_KeyframeType {
(bezt)->f3 &= ~SELECT; \
} \
((void)0)
#define BEZT_SEL_INVERT(bezt) \
{ \
(bezt)->f1 ^= SELECT; \
(bezt)->f2 ^= SELECT; \
(bezt)->f3 ^= SELECT; \
} \
((void)0)
#define BEZT_SEL_IDX(bezt, i) \
{ \
switch (i) { \
case 0: \
(bezt)->f1 |= SELECT; \
break; \
case 1: \
(bezt)->f2 |= SELECT; \
break; \
case 2: \
(bezt)->f3 |= SELECT; \
break; \
default: \
break; \
} \
} \
((void)0)
#define BEZT_DESEL_IDX(bezt, i) \
{ \
switch (i) { \
case 0: \
(bezt)->f1 &= ~SELECT; \
break; \
case 1: \
(bezt)->f2 &= ~SELECT; \
break; \
case 2: \
(bezt)->f3 &= ~SELECT; \
break; \
default: \
break; \
} \
} \
((void)0)
#define BEZT_IS_AUTOH(bezt) \
(ELEM((bezt)->h1, HD_AUTO, HD_AUTO_ANIM) && ELEM((bezt)->h2, HD_AUTO, HD_AUTO_ANIM))

View File

@@ -29,6 +29,7 @@
struct AnimData;
struct MDeformVert;
struct Curve;
#define GP_DEFAULT_PIX_FACTOR 1.0f
#define GP_DEFAULT_GRID_LINES 4
@@ -36,6 +37,10 @@ struct MDeformVert;
#define GP_MATERIAL_BUFFER_LEN 256
#define GP_DEFAULT_CURVE_RESOLUTION 32
#define GP_DEFAULT_CURVE_ERROR 0.1f
#define GP_DEFAULT_CURVE_EDIT_CORNER_ANGLE M_PI_2
/* ***************************************** */
/* GP Stroke Points */
@@ -165,6 +170,61 @@ typedef enum eGPDpalette_Flag {
PL_PALETTE_ACTIVE = (1 << 0),
} eGPDpalette_Flag;
/* ***************************************** */
/* GP Curve Point */
typedef struct bGPDcurve_point {
/** Bezier Triple for the handles and control points. */
BezTriple bezt;
/** Pressure of input device (from 0 to 1) at this point. */
float pressure;
/** Color strength (used for alpha factor). */
float strength;
/** Index of corresponding point in gps->points. */
int point_index;
/** Additional options. */
int flag;
/** Factor of uv along the stroke. */
float uv_fac;
/** Uv rotation for dot mode. */
float uv_rot;
/** Uv for fill mode. */
float uv_fill[2];
/** Vertex Color RGBA (A=mix factor). */
float vert_color[4];
char _pad[4];
} bGPDcurve_point;
/* bGPDcurve_point->flag */
typedef enum eGPDcurve_point_Flag {
GP_CURVE_POINT_SELECT = (1 << 0),
} eGPDcurve_point_Flag;
/* ***************************************** */
/* GP Curve */
/* Curve for Bezier Editing. */
typedef struct bGPDcurve {
/** Array of BezTriple. */
bGPDcurve_point *curve_points;
/** Total number of curve points. */
int tot_curve_points;
/** General flag. */
short flag;
char _pad[2];
} bGPDcurve;
/* bGPDcurve_Flag->flag */
typedef enum bGPDcurve_Flag {
/* Flag to indicated that the stroke data has been changed and the curve needs to be refitted */
GP_CURVE_NEEDS_STROKE_UPDATE = (1 << 0),
/* Curve is selected */
GP_CURVE_SELECT = (1 << 1),
} bGPDcurve_Flag;
/* ***************************************** */
/* GP Strokes */
@@ -180,7 +240,8 @@ typedef struct bGPDstroke_Runtime {
int stroke_start;
/** Triangle offset in the ibo where this fill starts. */
int fill_start;
int _pad[1];
/** Curve Handles offset in the ibo where this handle starts. */
int curve_start;
/** Original stroke (used to dereference evaluated data) */
struct bGPDstroke *gps_orig;
@@ -245,6 +306,9 @@ typedef struct bGPDstroke {
/** Vertex Color for Fill (one for all stroke, A=mix factor). */
float vert_color_fill[4];
/** Curve used to edit the stroke using Bezier handlers. */
struct bGPDcurve *editcurve;
bGPDstroke_Runtime runtime;
} bGPDstroke;
@@ -263,6 +327,9 @@ typedef enum eGPDstroke_Flag {
/* Flag used to indicate that stroke is used for fill close and must use
* fill color for stroke and no fill area */
GP_STROKE_NOFILL = (1 << 8),
/* Flag to indicated that the editcurve has been changed and the stroke needs to be updated with
* the curve data */
GP_STROKE_NEEDS_CURVE_UPDATE = (1 << 9),
/* only for use with stroke-buffer (while drawing arrows) */
GP_STROKE_USE_ARROW_START = (1 << 12),
/* only for use with stroke-buffer (while drawing arrows) */
@@ -562,7 +629,12 @@ typedef struct bGPdata {
ListBase layers;
/** Settings for this data-block. */
int flag;
char _pad1[4];
/** Default resolution for generated curves using curve editing method. */
int curve_edit_resolution;
/** Curve Editing error threshold. */
float curve_edit_threshold;
/** Curve Editing corner angle (less or equal is treated as corner). */
float curve_edit_corner_angle;
/* Palettes */
/** List of bGPDpalette's - Deprecated (2.78 - 2.79 only). */
@@ -680,6 +752,11 @@ typedef enum eGPdata_Flag {
/* Autolock not active layers */
GP_DATA_AUTOLOCK_LAYERS = (1 << 20),
/* Enable Bezier Editing Curve (a submode of Edit mode). */
GP_DATA_CURVE_EDIT_MODE = (1 << 21),
/* Use adaptive curve resolution */
GP_DATA_CURVE_ADAPTIVE_RESOLUTION = (1 << 22),
} eGPdata_Flag;
/* gpd->onion_flag */
@@ -725,6 +802,9 @@ typedef enum eGP_DrawMode {
GP_DATA_STROKE_WEIGHTMODE | GP_DATA_STROKE_VERTEXMODE)) && \
((gpd)->flag & GP_DATA_STROKE_MULTIEDIT))
#define GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd) \
((gpd) && ((gpd)->flag & (GP_DATA_STROKE_EDITMODE)) && ((gpd)->flag & GP_DATA_CURVE_EDIT_MODE))
/* Macros to check grease pencil modes */
#define GPENCIL_ANY_MODE(gpd) \
((gpd) && ((gpd)->flag & \

View File

@@ -1090,7 +1090,7 @@ typedef struct GP_Sculpt_Settings {
int lock_axis;
/** Threshold for intersections */
float isect_threshold;
char _pad_[4];
char _pad[4];
/** Multiframe edit falloff effect by frame. */
struct CurveMapping *cur_falloff;
/** Curve used for primitive tools. */

View File

@@ -23,6 +23,7 @@
#include "BLI_math.h"
#include "DNA_brush_types.h"
#include "DNA_curve_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
@@ -160,6 +161,7 @@ static const EnumPropertyItem rna_enum_gpencil_caps_modes_items[] = {
#ifdef RNA_RUNTIME
# include "BLI_ghash.h"
# include "BLI_listbase.h"
# include "BLI_string_utils.h"
# include "WM_api.h"
@@ -167,6 +169,7 @@ static const EnumPropertyItem rna_enum_gpencil_caps_modes_items[] = {
# include "BKE_action.h"
# include "BKE_animsys.h"
# include "BKE_gpencil.h"
# include "BKE_gpencil_curve.h"
# include "BKE_gpencil_geom.h"
# include "BKE_icons.h"
@@ -179,6 +182,71 @@ static void rna_GPencil_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Pointe
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
}
static void rna_GPencil_curve_edit_mode_toggle(Main *bmain, Scene *scene, PointerRNA *ptr)
{
ToolSettings *ts = scene->toolsettings;
bGPdata *gpd = (bGPdata *)ptr->owner_id;
/* Curve edit mode is turned on. */
if (GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd)) {
/* If the current select mode is segment and the Bezier mode is on, change
* to Point because segment is not supported. */
if (ts->gpencil_selectmode_edit == GP_SELECTMODE_SEGMENT) {
ts->gpencil_selectmode_edit = GP_SELECTMODE_POINT;
}
BKE_gpencil_strokes_selected_update_editcurve(gpd);
}
/* Curve edit mode is turned off. */
else {
BKE_gpencil_strokes_selected_sync_selection_editcurve(gpd);
}
/* Standard update. */
rna_GPencil_update(bmain, scene, ptr);
}
static void rna_GPencil_stroke_curve_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
bGPdata *gpd = (bGPdata *)ptr->owner_id;
if (GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd)) {
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if (gpl->actframe != NULL) {
bGPDframe *gpf = gpl->actframe;
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
if (gps->editcurve != NULL) {
gps->flag |= GP_STROKE_NEEDS_CURVE_UPDATE;
BKE_gpencil_stroke_geometry_update(gpd, gps);
}
}
}
}
}
rna_GPencil_update(bmain, scene, ptr);
}
static void rna_GPencil_stroke_curve_resolution_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
bGPdata *gpd = (bGPdata *)ptr->owner_id;
if (GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd)) {
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if (gpl->actframe != NULL) {
bGPDframe *gpf = gpl->actframe;
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
if (gps->editcurve != NULL) {
gps->flag |= GP_STROKE_NEEDS_CURVE_UPDATE;
BKE_gpencil_stroke_geometry_update(gpd, gps);
}
}
}
}
}
rna_GPencil_update(bmain, scene, ptr);
}
static void rna_GPencil_dependency_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
DEG_id_tag_update(ptr->owner_id, ID_RECALC_TRANSFORM);
@@ -191,11 +259,12 @@ static void rna_GPencil_dependency_update(Main *bmain, Scene *UNUSED(scene), Poi
static void rna_GPencil_uv_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
bGPdata *gpd = (bGPdata *)ptr->owner_id;
/* Force to recalc the UVs. */
bGPDstroke *gps = (bGPDstroke *)ptr->data;
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(gps);
BKE_gpencil_stroke_geometry_update(gpd, gps);
DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
@@ -669,7 +738,7 @@ static void rna_GPencil_stroke_point_add(
stroke->totpoints += count;
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(stroke);
BKE_gpencil_stroke_geometry_update(gpd, stroke);
DEG_id_tag_update(&gpd->id,
ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
@@ -730,7 +799,7 @@ static void rna_GPencil_stroke_point_pop(ID *id,
}
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(stroke);
BKE_gpencil_stroke_geometry_update(gpd, stroke);
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
@@ -808,6 +877,32 @@ static void rna_GPencil_stroke_select_set(PointerRNA *ptr, const bool value)
}
}
static void rna_GPencil_curve_select_set(PointerRNA *ptr, const bool value)
{
bGPDcurve *gpc = ptr->data;
/* Set new value. */
if (value) {
gpc->flag |= GP_CURVE_SELECT;
}
else {
gpc->flag &= ~GP_CURVE_SELECT;
}
/* Ensure that the curves's points are selected in the same way. */
for (int i = 0; i < gpc->tot_curve_points; i++) {
bGPDcurve_point *gpc_pt = &gpc->curve_points[i];
BezTriple *bezt = &gpc_pt->bezt;
if (value) {
gpc_pt->flag |= GP_CURVE_POINT_SELECT;
BEZT_SEL_ALL(bezt);
}
else {
gpc_pt->flag &= ~GP_CURVE_POINT_SELECT;
BEZT_DESEL_ALL(bezt);
}
}
}
static bGPDframe *rna_GPencil_frame_new(bGPDlayer *layer,
ReportList *reports,
int frame_number,
@@ -969,6 +1064,100 @@ static char *rna_GreasePencilGrid_path(PointerRNA *UNUSED(ptr))
return BLI_strdup("grid");
}
static void rna_GpencilCurvePoint_BezTriple_handle1_get(PointerRNA *ptr, float *values)
{
bGPDcurve_point *cpt = (bGPDcurve_point *)ptr->data;
copy_v3_v3(values, cpt->bezt.vec[0]);
}
static void rna_GpencilCurvePoint_BezTriple_handle1_set(PointerRNA *ptr, const float *values)
{
bGPDcurve_point *cpt = (bGPDcurve_point *)ptr->data;
copy_v3_v3(cpt->bezt.vec[0], values);
}
static bool rna_GpencilCurvePoint_BezTriple_handle1_select_get(PointerRNA *ptr)
{
bGPDcurve_point *cpt = (bGPDcurve_point *)ptr->data;
return cpt->bezt.f1;
}
static void rna_GpencilCurvePoint_BezTriple_handle1_select_set(PointerRNA *ptr, const bool value)
{
bGPDcurve_point *cpt = (bGPDcurve_point *)ptr->data;
cpt->bezt.f1 = value;
}
static void rna_GpencilCurvePoint_BezTriple_handle2_get(PointerRNA *ptr, float *values)
{
bGPDcurve_point *cpt = (bGPDcurve_point *)ptr->data;
copy_v3_v3(values, cpt->bezt.vec[2]);
}
static void rna_GpencilCurvePoint_BezTriple_handle2_set(PointerRNA *ptr, const float *values)
{
bGPDcurve_point *cpt = (bGPDcurve_point *)ptr->data;
copy_v3_v3(cpt->bezt.vec[2], values);
}
static bool rna_GpencilCurvePoint_BezTriple_handle2_select_get(PointerRNA *ptr)
{
bGPDcurve_point *cpt = (bGPDcurve_point *)ptr->data;
return cpt->bezt.f3;
}
static void rna_GpencilCurvePoint_BezTriple_handle2_select_set(PointerRNA *ptr, const bool value)
{
bGPDcurve_point *cpt = (bGPDcurve_point *)ptr->data;
cpt->bezt.f3 = value;
}
static void rna_GpencilCurvePoint_BezTriple_ctrlpoint_get(PointerRNA *ptr, float *values)
{
bGPDcurve_point *cpt = (bGPDcurve_point *)ptr->data;
copy_v3_v3(values, cpt->bezt.vec[1]);
}
static void rna_GpencilCurvePoint_BezTriple_ctrlpoint_set(PointerRNA *ptr, const float *values)
{
bGPDcurve_point *cpt = (bGPDcurve_point *)ptr->data;
copy_v3_v3(cpt->bezt.vec[1], values);
}
static bool rna_GpencilCurvePoint_BezTriple_ctrlpoint_select_get(PointerRNA *ptr)
{
bGPDcurve_point *cpt = (bGPDcurve_point *)ptr->data;
return cpt->bezt.f2;
}
static void rna_GpencilCurvePoint_BezTriple_ctrlpoint_select_set(PointerRNA *ptr, const bool value)
{
bGPDcurve_point *cpt = (bGPDcurve_point *)ptr->data;
cpt->bezt.f2 = value;
}
static bool rna_GpencilCurvePoint_BezTriple_hide_get(PointerRNA *ptr)
{
bGPDcurve_point *cpt = (bGPDcurve_point *)ptr->data;
return (bool)cpt->bezt.hide;
}
static void rna_GpencilCurvePoint_BezTriple_hide_set(PointerRNA *ptr, const bool value)
{
bGPDcurve_point *cpt = (bGPDcurve_point *)ptr->data;
cpt->bezt.hide = value;
}
static bool rna_stroke_has_edit_curve_get(PointerRNA *ptr)
{
bGPDstroke *gps = (bGPDstroke *)ptr->data;
if (gps->editcurve != NULL) {
return true;
}
return false;
}
#else
static void rna_def_gpencil_stroke_point(BlenderRNA *brna)
@@ -1106,6 +1295,149 @@ static void rna_def_gpencil_triangle(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
}
static void rna_def_gpencil_curve_point(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "GPencilEditCurvePoint", NULL);
RNA_def_struct_sdna(srna, "bGPDcurve_point");
RNA_def_struct_ui_text(srna, "Bezier Curve Point", "Bezier curve point with two handles");
/* Boolean values */
prop = RNA_def_property(srna, "select_left_handle", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop,
"rna_GpencilCurvePoint_BezTriple_handle1_select_get",
"rna_GpencilCurvePoint_BezTriple_handle1_select_set");
RNA_def_property_ui_text(prop, "Handle 1 selected", "Handle 1 selection status");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
prop = RNA_def_property(srna, "select_right_handle", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop,
"rna_GpencilCurvePoint_BezTriple_handle2_select_get",
"rna_GpencilCurvePoint_BezTriple_handle2_select_set");
RNA_def_property_ui_text(prop, "Handle 2 selected", "Handle 2 selection status");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
prop = RNA_def_property(srna, "select_control_point", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop,
"rna_GpencilCurvePoint_BezTriple_ctrlpoint_select_get",
"rna_GpencilCurvePoint_BezTriple_ctrlpoint_select_set");
RNA_def_property_ui_text(prop, "Control Point selected", "Control point selection status");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop,
"rna_GpencilCurvePoint_BezTriple_hide_get",
"rna_GpencilCurvePoint_BezTriple_hide_set");
RNA_def_property_ui_text(prop, "Hide", "Visibility status");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
/* Vector values */
prop = RNA_def_property(srna, "handle_left", PROP_FLOAT, PROP_TRANSLATION);
RNA_def_property_array(prop, 3);
RNA_def_property_float_funcs(prop,
"rna_GpencilCurvePoint_BezTriple_handle1_get",
"rna_GpencilCurvePoint_BezTriple_handle1_set",
NULL);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Handle 1", "Coordinates of the first handle");
RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT);
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_stroke_curve_update");
prop = RNA_def_property(srna, "co", PROP_FLOAT, PROP_TRANSLATION);
RNA_def_property_array(prop, 3);
RNA_def_property_float_funcs(prop,
"rna_GpencilCurvePoint_BezTriple_ctrlpoint_get",
"rna_GpencilCurvePoint_BezTriple_ctrlpoint_set",
NULL);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Control Point", "Coordinates of the control point");
RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT);
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_stroke_curve_update");
prop = RNA_def_property(srna, "handle_right", PROP_FLOAT, PROP_TRANSLATION);
RNA_def_property_array(prop, 3);
RNA_def_property_float_funcs(prop,
"rna_GpencilCurvePoint_BezTriple_handle2_get",
"rna_GpencilCurvePoint_BezTriple_handle2_set",
NULL);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Handle 2", "Coordinates of the second handle");
RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT);
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_stroke_curve_update");
/* Pressure */
prop = RNA_def_property(srna, "pressure", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "pressure");
RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 1, RNA_TRANSLATION_PREC_DEFAULT);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Pressure", "Pressure of the grease pencil stroke point");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_stroke_curve_update");
/* Strength */
prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "strength");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(
prop, "Strength", "Color intensity (alpha factor) of the grease pencil stroke point");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_stroke_curve_update");
/* read-only index */
prop = RNA_def_property(srna, "point_index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "point_index");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(
prop, "Point Index", "Index of the corresponding grease pencil stroke point");
prop = RNA_def_property(srna, "uv_factor", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "uv_fac");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "UV Factor", "Internal UV factor");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_stroke_curve_update");
prop = RNA_def_property(srna, "uv_rotation", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, NULL, "uv_rot");
RNA_def_property_range(prop, -M_PI_2, M_PI_2);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "UV Rotation", "Internal UV factor for dot mode");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_stroke_curve_update");
prop = RNA_def_property(srna, "vertex_color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_sdna(prop, NULL, "vert_color");
RNA_def_property_array(prop, 4);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Vertex Color", "Vertex color of the grease pencil stroke point");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_stroke_curve_update");
}
/* Editing Curve data. */
static void rna_def_gpencil_curve(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "GPencilEditCurve", NULL);
RNA_def_struct_sdna(srna, "bGPDcurve");
RNA_def_struct_ui_text(srna, "Edit Curve", "Edition Curve");
prop = RNA_def_property(srna, "curve_points", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "curve_points", "tot_curve_points");
RNA_def_property_struct_type(prop, "GPencilEditCurvePoint");
RNA_def_property_ui_text(prop, "Curve Points", "Curve data points");
prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_CURVE_SELECT);
RNA_def_property_boolean_funcs(prop, NULL, "rna_GPencil_curve_select_set");
RNA_def_property_ui_text(prop, "Select", "Curve is selected for viewport editing");
RNA_def_property_update(prop, 0, "rna_GPencil_update");
}
static void rna_def_gpencil_mvert_group(BlenderRNA *brna)
{
StructRNA *srna;
@@ -1180,6 +1512,12 @@ static void rna_def_gpencil_stroke(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "GPencilTriangle");
RNA_def_property_ui_text(prop, "Triangles", "Triangulation data for HQ fill");
/* Edit Curve. */
prop = RNA_def_property(srna, "edit_curve", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "editcurve");
RNA_def_property_struct_type(prop, "GPencilEditCurve");
RNA_def_property_ui_text(prop, "Edit Curve", "Temporary data for Edit Curve");
/* Material Index */
prop = RNA_def_property(srna, "material_index", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "mat_nr");
@@ -1205,6 +1543,12 @@ static void rna_def_gpencil_stroke(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Cyclic", "Enable cyclic drawing, closing the stroke");
RNA_def_property_update(prop, 0, "rna_GPencil_update");
/* The stroke has Curve Edit data. */
prop = RNA_def_property(srna, "has_edit_curve", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_stroke_has_edit_curve_get", NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Has Curve Data", "Stroke has Curve data to edit shape");
/* Caps mode */
prop = RNA_def_property(srna, "start_cap_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "caps[0]");
@@ -2017,6 +2361,47 @@ static void rna_def_gpencil_data(BlenderRNA *brna)
"Scale conversion factor for pixel size (use larger values for thicker lines)");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
prop = RNA_def_property(srna, "edit_curve_resolution", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "curve_edit_resolution");
RNA_def_property_range(prop, 1, 256);
RNA_def_property_ui_range(prop, 1, 64, 1, 1);
RNA_def_property_int_default(prop, GP_DEFAULT_CURVE_RESOLUTION);
RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
RNA_def_property_ui_text(
prop,
"Curve Resolution",
"Number of segments generated between control points when editing strokes in curve mode");
RNA_def_property_update(
prop, NC_GPENCIL | ND_DATA, "rna_GPencil_stroke_curve_resolution_update");
prop = RNA_def_property(srna, "use_adaptive_curve_resolution", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_DATA_CURVE_ADAPTIVE_RESOLUTION);
RNA_def_property_boolean_default(prop, true);
RNA_def_property_ui_text(prop,
"Adaptive Resolution",
"Set the resolution of each editcurve segment dynamically depending on "
"the length of the segment. The resolution is the number of points "
"generated per unit distance");
RNA_def_property_update(
prop, NC_GPENCIL | ND_DATA, "rna_GPencil_stroke_curve_resolution_update");
/* Curve editing error threshold. */
prop = RNA_def_property(srna, "curve_edit_threshold", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "curve_edit_threshold");
RNA_def_property_range(prop, FLT_MIN, 10.0);
RNA_def_property_float_default(prop, GP_DEFAULT_CURVE_ERROR);
RNA_def_property_ui_text(prop, "Threshold", "Curve conversion error threshold");
RNA_def_property_ui_range(prop, FLT_MIN, 10.0, 2, 5);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
/* Curve editing corner angle. */
prop = RNA_def_property(srna, "curve_edit_corner_angle", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, NULL, "curve_edit_corner_angle");
RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f));
RNA_def_property_float_default(prop, DEG2RADF(90.0f));
RNA_def_property_ui_text(prop, "Corner Angle", "Angle threshold to be treated as corners");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
prop = RNA_def_property(srna, "use_multiedit", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_DATA_STROKE_MULTIEDIT);
RNA_def_property_ui_text(prop,
@@ -2025,6 +2410,11 @@ static void rna_def_gpencil_data(BlenderRNA *brna)
"(keyframes must be selected to be included)");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
prop = RNA_def_property(srna, "use_curve_edit", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_DATA_CURVE_EDIT_MODE);
RNA_def_property_ui_text(prop, "Curve Editing", "Edit strokes using curve handles");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_curve_edit_mode_toggle");
prop = RNA_def_property(srna, "use_autolock_layers", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_DATA_AUTOLOCK_LAYERS);
RNA_def_property_ui_text(
@@ -2176,6 +2566,8 @@ void RNA_def_gpencil(BlenderRNA *brna)
rna_def_gpencil_stroke(brna);
rna_def_gpencil_stroke_point(brna);
rna_def_gpencil_triangle(brna);
rna_def_gpencil_curve(brna);
rna_def_gpencil_curve_point(brna);
rna_def_gpencil_mvert_group(brna);
}