Skip to content

Commit cfc9cae

Browse files
Ink Open Sourcecopybara-github
authored andcommitted
Add BrushBehavior::Target::kAnimationFrameOffset
This CL adds the necessary boilerplate and plumbing for a new brush behavior target for controlling the starting animation frame of animated particles. Such a target can be wired up to e.g. a noise node to make particles start on a random frame, or a distance-traveled source to make a series of particles that cycle through starting frames in order, or whatever else is desired. The actual extruder change to use the new field in the `BrushTipState` to alter the particle's texture UV coordinates is left as a TODO for the next CL. PiperOrigin-RevId: 720180903
1 parent 97b671a commit cfc9cae

File tree

12 files changed

+64
-0
lines changed

12 files changed

+64
-0
lines changed

ink/brush/brush_behavior.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ bool IsValidBehaviorTarget(BrushBehavior::Target target) {
296296
case BrushBehavior::Target::kPositionOffsetYInMultiplesOfBrushSize:
297297
case BrushBehavior::Target::kPositionOffsetForwardInMultiplesOfBrushSize:
298298
case BrushBehavior::Target::kPositionOffsetLateralInMultiplesOfBrushSize:
299+
case BrushBehavior::Target::kTextureAnimationProgressOffset:
299300
case BrushBehavior::Target::kHueOffsetInRadians:
300301
case BrushBehavior::Target::kSaturationMultiplier:
301302
case BrushBehavior::Target::kLuminosity:
@@ -650,6 +651,8 @@ std::string ToFormattedString(BrushBehavior::Target target) {
650651
return "kPositionOffsetForwardInMultiplesOfBrushSize";
651652
case BrushBehavior::Target::kPositionOffsetLateralInMultiplesOfBrushSize:
652653
return "kPositionOffsetLateralInMultiplesOfBrushSize";
654+
case BrushBehavior::Target::kTextureAnimationProgressOffset:
655+
return "kTextureAnimationProgressOffset";
653656
case BrushBehavior::Target::kHueOffsetInRadians:
654657
return "kHueOffsetInRadians";
655658
case BrushBehavior::Target::kSaturationMultiplier:

ink/brush/brush_behavior.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,12 @@ struct BrushBehavior {
286286
// Y-axis (and a negative value moves the brush tip center towards the
287287
// negative Y-axis).
288288
kPositionOffsetLateralInMultiplesOfBrushSize,
289+
// Adds the target modifier to the initial texture animation progress value
290+
// of the current particle (which is relevant only for strokes with an
291+
// animated texture). The final progress offset is not clamped, but is
292+
// effectively normalized (mod 1). If multiple behaviors have this target,
293+
// they stack additively.
294+
kTextureAnimationProgressOffset,
289295

290296
// The following are targets for tip color adjustments, including opacity.
291297
// Renderers can apply them to the brush color when a stroke is drawn to

ink/brush/brush_behavior_test.cc

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,23 @@ TEST(BrushBehaviorTest, StringifyTarget) {
161161
"kRotationOffsetInRadians");
162162
EXPECT_EQ(absl::StrCat(BrushBehavior::Target::kCornerRoundingOffset),
163163
"kCornerRoundingOffset");
164+
EXPECT_EQ(absl::StrCat(
165+
BrushBehavior::Target::kPositionOffsetXInMultiplesOfBrushSize),
166+
"kPositionOffsetXInMultiplesOfBrushSize");
167+
EXPECT_EQ(absl::StrCat(
168+
BrushBehavior::Target::kPositionOffsetYInMultiplesOfBrushSize),
169+
"kPositionOffsetYInMultiplesOfBrushSize");
170+
EXPECT_EQ(
171+
absl::StrCat(
172+
BrushBehavior::Target::kPositionOffsetForwardInMultiplesOfBrushSize),
173+
"kPositionOffsetForwardInMultiplesOfBrushSize");
174+
EXPECT_EQ(
175+
absl::StrCat(
176+
BrushBehavior::Target::kPositionOffsetLateralInMultiplesOfBrushSize),
177+
"kPositionOffsetLateralInMultiplesOfBrushSize");
178+
EXPECT_EQ(
179+
absl::StrCat(BrushBehavior::Target::kTextureAnimationProgressOffset),
180+
"kTextureAnimationProgressOffset");
164181
EXPECT_EQ(absl::StrCat(BrushBehavior::Target::kHueOffsetInRadians),
165182
"kHueOffsetInRadians");
166183
EXPECT_EQ(absl::StrCat(BrushBehavior::Target::kSaturationMultiplier),

ink/brush/fuzz_domains.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ Domain<BrushBehavior::Target> ArbitraryBrushBehaviorTarget() {
232232
BrushBehavior::Target::kPositionOffsetYInMultiplesOfBrushSize,
233233
BrushBehavior::Target::kPositionOffsetForwardInMultiplesOfBrushSize,
234234
BrushBehavior::Target::kPositionOffsetLateralInMultiplesOfBrushSize,
235+
BrushBehavior::Target::kTextureAnimationProgressOffset,
235236
BrushBehavior::Target::kHueOffsetInRadians,
236237
BrushBehavior::Target::kSaturationMultiplier,
237238
BrushBehavior::Target::kLuminosity,

ink/storage/brush.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,8 @@ proto::BrushBehavior::Target EncodeBrushBehaviorTarget(
389389
case BrushBehavior::Target::kPositionOffsetLateralInMultiplesOfBrushSize:
390390
return proto::BrushBehavior::
391391
TARGET_POSITION_OFFSET_LATERAL_IN_MULTIPLES_OF_BRUSH_SIZE;
392+
case BrushBehavior::Target::kTextureAnimationProgressOffset:
393+
return proto::BrushBehavior::TARGET_TEXTURE_ANIMATION_PROGRESS_OFFSET;
392394
case BrushBehavior::Target::kHueOffsetInRadians:
393395
return proto::BrushBehavior::TARGET_HUE_OFFSET_IN_RADIANS;
394396
case BrushBehavior::Target::kSaturationMultiplier:
@@ -440,6 +442,8 @@ absl::StatusOr<BrushBehavior::Target> DecodeBrushBehaviorTarget(
440442
TARGET_POSITION_OFFSET_LATERAL_IN_MULTIPLES_OF_BRUSH_SIZE:
441443
return BrushBehavior::Target::
442444
kPositionOffsetLateralInMultiplesOfBrushSize;
445+
case proto::BrushBehavior::TARGET_TEXTURE_ANIMATION_PROGRESS_OFFSET:
446+
return BrushBehavior::Target::kTextureAnimationProgressOffset;
443447
default:
444448
return absl::InvalidArgumentError(absl::StrCat(
445449
"invalid ink.proto.BrushBehavior.Target value: ", target_proto));

ink/storage/proto/brush.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ message BrushBehavior {
293293
TARGET_POSITION_OFFSET_FORWARD_IN_MULTIPLES_OF_BRUSH_SIZE = 14;
294294
TARGET_POSITION_OFFSET_LATERAL_IN_MULTIPLES_OF_BRUSH_SIZE = 15;
295295
reserved 16;
296+
TARGET_TEXTURE_ANIMATION_PROGRESS_OFFSET = 17;
296297
}
297298
// LINT.ThenChange(../../brush/brush_behavior.h:target)
298299

ink/strokes/internal/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ cc_library(
117117
"//ink/geometry:point",
118118
"//ink/geometry:vec",
119119
"//ink/geometry/internal:algorithms",
120+
"//ink/geometry/internal:modulo",
120121
"//ink/strokes/input:stroke_input",
121122
"//ink/types:duration",
122123
"//ink/types:physical_distance",

ink/strokes/internal/brush_tip_extruder.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,7 @@ AffineTransform ComputeParticleSurfaceUvTransform(
388388
const BrushTipState& tip_state) {
389389
// This transform takes tip size, position, and rotation into account, but
390390
// deliberately ignores tip slant, pinch, and corner rounding.
391+
// TODO: b/373651450 - Use `tip_state.texture_animation_progress_offset` here.
391392
return AffineTransform::Translate({0.5, 0.5}) *
392393
AffineTransform::Scale(1.0f / tip_state.width,
393394
1.0f / tip_state.height) *

ink/strokes/internal/brush_tip_modeler.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ float InitialTargetModifierValue(BrushBehavior::Target target) {
5555
case BrushBehavior::Target::kPositionOffsetYInMultiplesOfBrushSize:
5656
case BrushBehavior::Target::kPositionOffsetForwardInMultiplesOfBrushSize:
5757
case BrushBehavior::Target::kPositionOffsetLateralInMultiplesOfBrushSize:
58+
case BrushBehavior::Target::kTextureAnimationProgressOffset:
5859
case BrushBehavior::Target::kHueOffsetInRadians:
5960
case BrushBehavior::Target::kLuminosity:
6061
return 0.f;

ink/strokes/internal/brush_tip_modeler_helpers.cc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "ink/brush/brush_tip.h"
2929
#include "ink/geometry/angle.h"
3030
#include "ink/geometry/internal/algorithms.h"
31+
#include "ink/geometry/internal/modulo.h"
3132
#include "ink/geometry/point.h"
3233
#include "ink/geometry/vec.h"
3334
#include "ink/strokes/input/stroke_input.h"
@@ -539,6 +540,7 @@ struct BrushTipStateModifiers {
539540
float corner_rounding_offset = 0;
540541
Angle rotation_offset;
541542
float pinch_offset = 0;
543+
float texture_animation_progress_offset = 0;
542544
Angle hue_offset;
543545
float saturation_multiplier = 1;
544546
float luminosity = 0;
@@ -597,6 +599,9 @@ void ApplyModifierToTarget(float modifier, BrushBehavior::Target target,
597599
modifier * brush_size);
598600
}
599601
break;
602+
case BrushBehavior::Target::kTextureAnimationProgressOffset:
603+
tip_state_modifiers.texture_animation_progress_offset += modifier;
604+
break;
600605
case BrushBehavior::Target::kHueOffsetInRadians:
601606
tip_state_modifiers.hue_offset += Angle::Radians(modifier);
602607
break;
@@ -637,6 +642,13 @@ void ApplyModifiersToTipState(const BrushTipStateModifiers& modifiers,
637642
tip_state.percent_radius = std::clamp(
638643
tip_state.percent_radius + modifiers.corner_rounding_offset, 0.f, 1.f);
639644
}
645+
if (modifiers.texture_animation_progress_offset != 0) {
646+
tip_state.texture_animation_progress_offset =
647+
geometry_internal::FloatModulo(
648+
tip_state.texture_animation_progress_offset +
649+
modifiers.texture_animation_progress_offset,
650+
1);
651+
}
640652
if (modifiers.hue_offset != Angle()) {
641653
tip_state.hue_offset_in_full_turns =
642654
modifiers.hue_offset.Normalized() / kFullTurn;

0 commit comments

Comments
 (0)