Remove SkCurve and SkColorCurve
This was only being used in one effect (and for no good reason). SkSL is plenty powerful to re-implement something similar if required, at no real performance cost. Re-implemented the one effect that used it with simpler math in the script, updated the copy of that effect in the gallery. Docs-Preview: https://skia.org/?cl=247040 Change-Id: I68c86d6550dd4f003f6ba5ecd0febab37b86540b Bug: skia:9513 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/247040 Reviewed-by: Kevin Lubick <kjlubick@google.com> Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
This commit is contained in:
parent
82e1145cd0
commit
7edfb69406
@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!DOCTYPE html>
|
||||
<title>CanvasKit Extra features (Skia via Web Assembly)</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
@ -183,8 +183,9 @@
|
||||
}
|
||||
const context = CanvasKit.currentContext();
|
||||
const canvas = surface.getCanvas();
|
||||
canvas.translate(250, 450);
|
||||
|
||||
const particles = CanvasKit.MakeParticles(JSON.stringify(snowfall));
|
||||
const particles = CanvasKit.MakeParticles(JSON.stringify(curves));
|
||||
particles.start(Date.now() / 1000.0, true);
|
||||
|
||||
function drawFrame(canvas) {
|
||||
@ -197,58 +198,35 @@
|
||||
surface.requestAnimationFrame(drawFrame);
|
||||
}
|
||||
|
||||
const snowfall = {
|
||||
"MaxCount": 4096,
|
||||
const curves = {
|
||||
"MaxCount": 1000,
|
||||
"Drawable": {
|
||||
"Type": "SkCircleDrawable",
|
||||
"Radius": 1
|
||||
"Radius": 2
|
||||
},
|
||||
"EffectCode": [
|
||||
"void effectSpawn(inout Effect effect) {",
|
||||
" effect.rate = 30;",
|
||||
"}",
|
||||
"",
|
||||
"void effectUpdate(inout Effect effect) {",
|
||||
" effect.rate = 200;",
|
||||
" effect.color = float4(1, 0, 0, 1);",
|
||||
"}",
|
||||
""
|
||||
],
|
||||
"Code": [
|
||||
"void spawn(inout Particle p) {",
|
||||
" p.lifetime = 10;",
|
||||
" p.vel.y = 10 + rand * 20;",
|
||||
" p.vel.x = -5 + 10 * rand;",
|
||||
" p.pos.x = rand * 500;",
|
||||
" p.lifetime = 3 + rand;",
|
||||
" p.vel.y = -50;",
|
||||
"}",
|
||||
"",
|
||||
"void update(inout Particle p) {",
|
||||
" p.scale = size(p.age);",
|
||||
" float w = mix(15, 3, p.age);",
|
||||
" p.pos.x = sin(radians(p.age * 320)) * mix(25, 10, p.age) + mix(-w, w, rand);",
|
||||
" if (rand < 0.5) { p.pos.x = -p.pos.x; }",
|
||||
"",
|
||||
" p.color.g = (mix(75, 220, p.age) + mix(-30, 30, rand)) / 255;",
|
||||
"}",
|
||||
""
|
||||
],
|
||||
"Bindings": [
|
||||
{
|
||||
"Type": "SkCurveBinding",
|
||||
"Name": "size",
|
||||
"Curve": {
|
||||
"XValues": [],
|
||||
"Segments": [
|
||||
{
|
||||
"Type": "Cubic",
|
||||
"Ranged": true,
|
||||
"Bidirectional": false,
|
||||
"A0": 10,
|
||||
"B0": 10,
|
||||
"C0": 10,
|
||||
"D0": 0,
|
||||
"A1": 10,
|
||||
"B1": 0,
|
||||
"C1": 0,
|
||||
"D1": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
"Bindings": []
|
||||
};
|
||||
|
||||
function SurfaceAPI1(CanvasKit) {
|
||||
|
@ -1,124 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkCurve_DEFINED
|
||||
#define SkCurve_DEFINED
|
||||
|
||||
#include "include/core/SkColor.h"
|
||||
#include "include/private/SkTArray.h"
|
||||
|
||||
class SkFieldVisitor;
|
||||
class SkRandom;
|
||||
|
||||
/**
|
||||
* SkCurve implements a keyframed 1D function, useful for animating values over time. This pattern
|
||||
* is common in digital content creation tools. An SkCurve might represent rotation, scale, opacity,
|
||||
* or any other scalar quantity.
|
||||
*
|
||||
* An SkCurve has a logical domain of [0, 1], and is made of one or more SkCurveSegments.
|
||||
* Each segment describes the behavior of the curve in some sub-domain. For an SkCurve with N
|
||||
* segments, there are (N - 1) intermediate x-values that subdivide the domain. The first and last
|
||||
* x-values are implicitly 0 and 1:
|
||||
*
|
||||
* 0 ... x[0] ... x[1] ... ... 1
|
||||
* Segment_0 Segment_1 ... Segment_N-1
|
||||
*
|
||||
* Each segment describes a function over [0, 1] - x-values are re-normalized to the segment's
|
||||
* domain when being evaluated. The segments are cubic polynomials, defined by four values (fMin).
|
||||
* These are the values at x=0 and x=1, as well as control points at x=1/3 and x=2/3.
|
||||
*
|
||||
* For segments with fConstant == true, only the first value is used (fMin[0]).
|
||||
*
|
||||
* Each segment has two additional features for creating interesting (and varied) animation:
|
||||
* - A segment can be ranged. Ranged segments have two sets of coefficients, and a random value
|
||||
* taken from the particle's SkRandom is used to lerp betwen them. Typically, the SkRandom is
|
||||
* in the same state at each call, so this value is stable. That causes a ranged SkCurve to
|
||||
* produce a single smooth cubic function somewhere within the range defined by fMin and fMax.
|
||||
* - A segment can be bidirectional. In that case, after a value is computed, it will be negated
|
||||
* 50% of the time.
|
||||
*/
|
||||
|
||||
enum SkCurveSegmentType {
|
||||
kConstant_SegmentType,
|
||||
kLinear_SegmentType,
|
||||
kCubic_SegmentType,
|
||||
};
|
||||
|
||||
struct SkCurveSegment {
|
||||
float eval(float x, float t, bool negate) const;
|
||||
void visitFields(SkFieldVisitor* v);
|
||||
|
||||
void setConstant(float c) {
|
||||
fType = kConstant_SegmentType;
|
||||
fRanged = false;
|
||||
fMin[0] = c;
|
||||
}
|
||||
|
||||
float fMin[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
float fMax[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
|
||||
int fType = kConstant_SegmentType;
|
||||
bool fRanged = false;
|
||||
bool fBidirectional = false;
|
||||
};
|
||||
|
||||
struct SkCurve {
|
||||
SkCurve(float c = 0.0f) {
|
||||
fSegments.push_back().setConstant(c);
|
||||
}
|
||||
|
||||
float eval(float x, SkRandom& random) const;
|
||||
void visitFields(SkFieldVisitor* v);
|
||||
|
||||
// It should always be true that (fXValues.count() + 1) == fSegments.count()
|
||||
SkTArray<float, true> fXValues;
|
||||
SkTArray<SkCurveSegment, true> fSegments;
|
||||
};
|
||||
|
||||
/**
|
||||
* SkColorCurve is similar to SkCurve, but keyframes 4D values - specifically colors. Because
|
||||
* negative colors rarely make sense, SkColorCurves do not support bidirectional segments, but
|
||||
* support all other features (including cubic interpolation).
|
||||
*/
|
||||
|
||||
struct SkColorCurveSegment {
|
||||
SkColorCurveSegment() {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
fMin[i] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
fMax[i] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
}
|
||||
}
|
||||
|
||||
SkColor4f eval(float x, float t) const;
|
||||
void visitFields(SkFieldVisitor* v);
|
||||
|
||||
void setConstant(SkColor4f c) {
|
||||
fType = kConstant_SegmentType;
|
||||
fRanged = false;
|
||||
fMin[0] = c;
|
||||
}
|
||||
|
||||
SkColor4f fMin[4];
|
||||
SkColor4f fMax[4];
|
||||
|
||||
int fType = kConstant_SegmentType;
|
||||
bool fRanged = false;
|
||||
};
|
||||
|
||||
struct SkColorCurve {
|
||||
SkColorCurve(SkColor4f c = { 1.0f, 1.0f, 1.0f, 1.0f }) {
|
||||
fSegments.push_back().setConstant(c);
|
||||
}
|
||||
|
||||
SkColor4f eval(float x, SkRandom& random) const;
|
||||
void visitFields(SkFieldVisitor* v);
|
||||
|
||||
SkTArray<float, true> fXValues;
|
||||
SkTArray<SkColorCurveSegment, true> fSegments;
|
||||
};
|
||||
|
||||
#endif // SkCurve_DEFINED
|
@ -14,8 +14,6 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
struct SkCurve;
|
||||
struct SkColorCurve;
|
||||
class SkParticleEffect;
|
||||
class SkParticleEffectParams;
|
||||
class SkRandom;
|
||||
@ -60,14 +58,6 @@ public:
|
||||
* each kind of binding is described below.
|
||||
*/
|
||||
|
||||
// Binds an SkCurve to an effect's SkSL. The curve is a one-dimensional function, described
|
||||
// in SkCurve.h. It is called in the SkSL as 'name(t)', and returns a single float value.
|
||||
static sk_sp<SkParticleBinding> MakeCurve(const char* name, const SkCurve& curve);
|
||||
|
||||
// Binds an SkColorCurve to an effect's SkSL. The curve is a one-dimensional, function,
|
||||
// described in SkCurve.h. It is called in the SkSL as 'name(t)', and returns a float4 value.
|
||||
static sk_sp<SkParticleBinding> MakeColorCurve(const char* name, const SkColorCurve& curve);
|
||||
|
||||
// Binds an SkPath to an effect's SkSL. The path is specified using SVG syntax. It is called
|
||||
// in the SkSL as 'name(t)'. 't' is a normalized distance along the path. This returns a float4
|
||||
// value, containing the position in .xy, and the normal in .zw.
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include <functional> // std::function
|
||||
#include <string.h>
|
||||
|
||||
struct SkCurve;
|
||||
class SkFieldVisitor;
|
||||
struct SkPoint;
|
||||
class SkString;
|
||||
@ -163,9 +162,6 @@ public:
|
||||
};
|
||||
virtual void visit(const char*, int&, const EnumStringMapping*, int count) = 0;
|
||||
|
||||
// Specific virtual signature for SkCurve, to allow for heavily customized UI in SkGuiVisitor.
|
||||
virtual void visit(const char* name, SkCurve& c);
|
||||
|
||||
// Default visit function for structs with no special behavior. It is assumed that any such
|
||||
// struct implements visitFields(SkFieldVisitor*) to recursively visit each of its fields.
|
||||
template <typename T>
|
||||
|
@ -7,7 +7,6 @@
|
||||
_src = get_path_info("src", "abspath")
|
||||
|
||||
skia_particle_sources = [
|
||||
"$_src/SkCurve.cpp",
|
||||
"$_src/SkParticleBinding.cpp",
|
||||
"$_src/SkParticleDrawable.cpp",
|
||||
"$_src/SkParticleEffect.cpp",
|
||||
|
@ -1,182 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "include/utils/SkRandom.h"
|
||||
#include "modules/particles/include/SkCurve.h"
|
||||
#include "modules/particles/include/SkReflected.h"
|
||||
|
||||
constexpr SkFieldVisitor::EnumStringMapping gCurveSegmentTypeMapping[] = {
|
||||
{ kConstant_SegmentType, "Constant" },
|
||||
{ kLinear_SegmentType, "Linear" },
|
||||
{ kCubic_SegmentType, "Cubic" },
|
||||
};
|
||||
|
||||
static SkColor4f operator+(SkColor4f c1, SkColor4f c2) {
|
||||
return { c1.fR + c2.fR, c1.fG + c2.fG, c1.fB + c2.fB, c1.fA + c2.fA };
|
||||
}
|
||||
|
||||
static SkColor4f operator-(SkColor4f c1, SkColor4f c2) {
|
||||
return { c1.fR - c2.fR, c1.fG - c2.fG, c1.fB - c2.fB, c1.fA - c2.fA };
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static T eval_cubic(const T* pts, float x) {
|
||||
float ix = (1 - x);
|
||||
return pts[0]*(ix*ix*ix) + pts[1]*(3*ix*ix*x) + pts[2]*(3*ix*x*x) + pts[3]*(x*x*x);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static T eval_segment(const T* pts, float x, int type) {
|
||||
switch (type) {
|
||||
case kLinear_SegmentType:
|
||||
return pts[0] + (pts[3] - pts[0]) * x;
|
||||
case kCubic_SegmentType:
|
||||
return eval_cubic(pts, x);
|
||||
case kConstant_SegmentType:
|
||||
default:
|
||||
return pts[0];
|
||||
}
|
||||
}
|
||||
|
||||
float SkCurveSegment::eval(float x, float t, bool negate) const {
|
||||
float result = eval_segment(fMin, x, fType);
|
||||
if (fRanged) {
|
||||
result += (eval_segment(fMax, x, fType) - result) * t;
|
||||
}
|
||||
if (fBidirectional && negate) {
|
||||
result = -result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void SkCurveSegment::visitFields(SkFieldVisitor* v) {
|
||||
v->visit("Type", fType, gCurveSegmentTypeMapping, SK_ARRAY_COUNT(gCurveSegmentTypeMapping));
|
||||
v->visit("Ranged", fRanged);
|
||||
v->visit("Bidirectional", fBidirectional);
|
||||
v->visit("A0", fMin[0]);
|
||||
if (fType == kCubic_SegmentType) {
|
||||
v->visit("B0", fMin[1]);
|
||||
v->visit("C0", fMin[2]);
|
||||
}
|
||||
if (fType != kConstant_SegmentType) {
|
||||
v->visit("D0", fMin[3]);
|
||||
}
|
||||
if (fRanged) {
|
||||
v->visit("A1", fMax[0]);
|
||||
if (fType == kCubic_SegmentType) {
|
||||
v->visit("B1", fMax[1]);
|
||||
v->visit("C1", fMax[2]);
|
||||
}
|
||||
if (fType != kConstant_SegmentType) {
|
||||
v->visit("D1", fMax[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float SkCurve::eval(float x, SkRandom& random) const {
|
||||
SkASSERT(fSegments.count() == fXValues.count() + 1);
|
||||
|
||||
int i = 0;
|
||||
for (; i < fXValues.count(); ++i) {
|
||||
if (x <= fXValues[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
float rangeMin = (i == 0) ? 0.0f : fXValues[i - 1];
|
||||
float rangeMax = (i == fXValues.count()) ? 1.0f : fXValues[i];
|
||||
float segmentX = (x - rangeMin) / (rangeMax - rangeMin);
|
||||
if (!sk_float_isfinite(segmentX)) {
|
||||
segmentX = rangeMin;
|
||||
}
|
||||
SkASSERT(0.0f <= segmentX && segmentX <= 1.0f);
|
||||
|
||||
// Always pull t and negate here, so that the stable generator behaves consistently, even if
|
||||
// our segments use an inconsistent feature-set.
|
||||
float t = random.nextF();
|
||||
bool negate = random.nextBool();
|
||||
return fSegments[i].eval(segmentX, t, negate);
|
||||
}
|
||||
|
||||
void SkCurve::visitFields(SkFieldVisitor* v) {
|
||||
v->visit("XValues", fXValues);
|
||||
v->visit("Segments", fSegments);
|
||||
|
||||
// Validate and fixup
|
||||
if (fSegments.empty()) {
|
||||
fSegments.push_back().setConstant(0.0f);
|
||||
}
|
||||
fXValues.resize_back(fSegments.count() - 1);
|
||||
for (int i = 0; i < fXValues.count(); ++i) {
|
||||
fXValues[i] = SkTPin(fXValues[i], i > 0 ? fXValues[i - 1] : 0.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
SkColor4f SkColorCurveSegment::eval(float x, float t) const {
|
||||
SkColor4f result = eval_segment(fMin, x, fType);
|
||||
if (fRanged) {
|
||||
result = result + (eval_segment(fMax, x, fType) - result) * t;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void SkColorCurveSegment::visitFields(SkFieldVisitor* v) {
|
||||
v->visit("Type", fType, gCurveSegmentTypeMapping, SK_ARRAY_COUNT(gCurveSegmentTypeMapping));
|
||||
v->visit("Ranged", fRanged);
|
||||
v->visit("A0", fMin[0]);
|
||||
if (fType == kCubic_SegmentType) {
|
||||
v->visit("B0", fMin[1]);
|
||||
v->visit("C0", fMin[2]);
|
||||
}
|
||||
if (fType != kConstant_SegmentType) {
|
||||
v->visit("D0", fMin[3]);
|
||||
}
|
||||
if (fRanged) {
|
||||
v->visit("A1", fMax[0]);
|
||||
if (fType == kCubic_SegmentType) {
|
||||
v->visit("B1", fMax[1]);
|
||||
v->visit("C1", fMax[2]);
|
||||
}
|
||||
if (fType != kConstant_SegmentType) {
|
||||
v->visit("D1", fMax[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SkColor4f SkColorCurve::eval(float x, SkRandom& random) const {
|
||||
SkASSERT(fSegments.count() == fXValues.count() + 1);
|
||||
|
||||
int i = 0;
|
||||
for (; i < fXValues.count(); ++i) {
|
||||
if (x <= fXValues[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
float rangeMin = (i == 0) ? 0.0f : fXValues[i - 1];
|
||||
float rangeMax = (i == fXValues.count()) ? 1.0f : fXValues[i];
|
||||
float segmentX = (x - rangeMin) / (rangeMax - rangeMin);
|
||||
if (!sk_float_isfinite(segmentX)) {
|
||||
segmentX = rangeMin;
|
||||
}
|
||||
SkASSERT(0.0f <= segmentX && segmentX <= 1.0f);
|
||||
return fSegments[i].eval(segmentX, random.nextF());
|
||||
}
|
||||
|
||||
void SkColorCurve::visitFields(SkFieldVisitor* v) {
|
||||
v->visit("XValues", fXValues);
|
||||
v->visit("Segments", fSegments);
|
||||
|
||||
// Validate and fixup
|
||||
if (fSegments.empty()) {
|
||||
fSegments.push_back().setConstant(SkColor4f{ 1.0f, 1.0f, 1.0f, 1.0f });
|
||||
}
|
||||
fXValues.resize_back(fSegments.count() - 1);
|
||||
for (int i = 0; i < fXValues.count(); ++i) {
|
||||
fXValues[i] = SkTPin(fXValues[i], i > 0 ? fXValues[i - 1] : 0.0f, 1.0f);
|
||||
}
|
||||
}
|
@ -12,7 +12,6 @@
|
||||
#include "include/utils/SkParsePath.h"
|
||||
#include "include/utils/SkRandom.h"
|
||||
#include "include/utils/SkTextUtils.h"
|
||||
#include "modules/particles/include/SkCurve.h"
|
||||
#include "modules/particles/include/SkParticleEffect.h"
|
||||
#include "modules/particles/include/SkReflected.h"
|
||||
#include "src/sksl/SkSLCompiler.h"
|
||||
@ -21,96 +20,6 @@ void SkParticleBinding::visitFields(SkFieldVisitor* v) {
|
||||
v->visit("Name", fName);
|
||||
}
|
||||
|
||||
// Exposes an SkCurve as an external, callable value. c(x) returns a float.
|
||||
class SkCurveExternalValue : public SkParticleExternalValue {
|
||||
public:
|
||||
SkCurveExternalValue(const char* name, SkSL::Compiler& compiler, const SkCurve& curve)
|
||||
: SkParticleExternalValue(name, compiler, *compiler.context().fFloat_Type)
|
||||
, fCurve(curve) { }
|
||||
|
||||
bool canCall() const override { return true; }
|
||||
int callParameterCount() const override { return 1; }
|
||||
void getCallParameterTypes(const SkSL::Type** outTypes) const override {
|
||||
outTypes[0] = fCompiler.context().fFloat_Type.get();
|
||||
}
|
||||
|
||||
void call(int index, float* arguments, float* outReturn) override {
|
||||
*outReturn = fCurve.eval(*arguments, fRandom[index]);
|
||||
}
|
||||
|
||||
private:
|
||||
SkCurve fCurve;
|
||||
};
|
||||
|
||||
class SkCurveBinding : public SkParticleBinding {
|
||||
public:
|
||||
SkCurveBinding(const char* name = "", const SkCurve& curve = 0.0f)
|
||||
: SkParticleBinding(name)
|
||||
, fCurve(curve) {}
|
||||
|
||||
REFLECTED(SkCurveBinding, SkParticleBinding)
|
||||
|
||||
void visitFields(SkFieldVisitor* v) override {
|
||||
SkParticleBinding::visitFields(v);
|
||||
v->visit("Curve", fCurve);
|
||||
}
|
||||
|
||||
std::unique_ptr<SkParticleExternalValue> toValue(SkSL::Compiler& compiler) override {
|
||||
return std::unique_ptr<SkParticleExternalValue>(
|
||||
new SkCurveExternalValue(fName.c_str(), compiler, fCurve));
|
||||
}
|
||||
|
||||
private:
|
||||
SkCurve fCurve;
|
||||
};
|
||||
|
||||
// Exposes an SkColorCurve as an external, callable value. c(x) returns a float4.
|
||||
class SkColorCurveExternalValue : public SkParticleExternalValue {
|
||||
public:
|
||||
SkColorCurveExternalValue(const char* name, SkSL::Compiler& compiler, const SkColorCurve& curve)
|
||||
: SkParticleExternalValue(name, compiler, *compiler.context().fFloat4_Type)
|
||||
, fCurve(curve) {
|
||||
}
|
||||
|
||||
bool canCall() const override { return true; }
|
||||
int callParameterCount() const override { return 1; }
|
||||
void getCallParameterTypes(const SkSL::Type** outTypes) const override {
|
||||
outTypes[0] = fCompiler.context().fFloat_Type.get();
|
||||
}
|
||||
|
||||
void call(int index, float* arguments, float* outReturn) override {
|
||||
SkColor4f color = fCurve.eval(*arguments, fRandom[index]);
|
||||
memcpy(outReturn, color.vec(), 4 * sizeof(float));
|
||||
}
|
||||
|
||||
private:
|
||||
SkColorCurve fCurve;
|
||||
};
|
||||
|
||||
class SkColorCurveBinding : public SkParticleBinding {
|
||||
public:
|
||||
SkColorCurveBinding(const char* name = "",
|
||||
const SkColorCurve& curve = SkColor4f{ 1.0f, 1.0f, 1.0f, 1.0f })
|
||||
: SkParticleBinding(name)
|
||||
, fCurve(curve) {
|
||||
}
|
||||
|
||||
REFLECTED(SkColorCurveBinding, SkParticleBinding)
|
||||
|
||||
void visitFields(SkFieldVisitor* v) override {
|
||||
SkParticleBinding::visitFields(v);
|
||||
v->visit("Curve", fCurve);
|
||||
}
|
||||
|
||||
std::unique_ptr<SkParticleExternalValue> toValue(SkSL::Compiler& compiler) override {
|
||||
return std::unique_ptr<SkParticleExternalValue>(
|
||||
new SkColorCurveExternalValue(fName.c_str(), compiler, fCurve));
|
||||
}
|
||||
|
||||
private:
|
||||
SkColorCurve fCurve;
|
||||
};
|
||||
|
||||
class SkEffectExternalValue : public SkParticleExternalValue {
|
||||
public:
|
||||
SkEffectExternalValue(const char* name, SkSL::Compiler& compiler,
|
||||
@ -295,15 +204,6 @@ private:
|
||||
SkPathContours fContours;
|
||||
};
|
||||
|
||||
sk_sp<SkParticleBinding> SkParticleBinding::MakeCurve(const char* name, const SkCurve& curve) {
|
||||
return sk_sp<SkParticleBinding>(new SkCurveBinding(name, curve));
|
||||
}
|
||||
|
||||
sk_sp<SkParticleBinding> SkParticleBinding::MakeColorCurve(const char* name,
|
||||
const SkColorCurve& curve) {
|
||||
return sk_sp<SkParticleBinding>(new SkColorCurveBinding(name, curve));
|
||||
}
|
||||
|
||||
sk_sp<SkParticleBinding> SkParticleBinding::MakeEffectBinding(
|
||||
const char* name, sk_sp<SkParticleEffectParams> params) {
|
||||
return sk_sp<SkParticleBinding>(new SkEffectBinding(name, params));
|
||||
@ -315,8 +215,6 @@ sk_sp<SkParticleBinding> SkParticleBinding::MakePathBinding(const char* name, co
|
||||
|
||||
void SkParticleBinding::RegisterBindingTypes() {
|
||||
REGISTER_REFLECTED(SkParticleBinding);
|
||||
REGISTER_REFLECTED(SkCurveBinding);
|
||||
REGISTER_REFLECTED(SkColorCurveBinding);
|
||||
REGISTER_REFLECTED(SkEffectBinding);
|
||||
REGISTER_REFLECTED(SkPathBinding);
|
||||
REGISTER_REFLECTED(SkTextBinding);
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include "modules/particles/include/SkParticleEffect.h"
|
||||
|
||||
#include "include/core/SkPaint.h"
|
||||
#include "modules/particles/include/SkCurve.h"
|
||||
#include "modules/particles/include/SkParticleBinding.h"
|
||||
#include "modules/particles/include/SkParticleDrawable.h"
|
||||
#include "modules/particles/include/SkReflected.h"
|
||||
|
@ -7,8 +7,6 @@
|
||||
|
||||
#include "modules/particles/include/SkReflected.h"
|
||||
|
||||
#include "modules/particles/include/SkCurve.h"
|
||||
|
||||
SkSTArray<16, const SkReflected::Type*, true> SkReflected::gTypes;
|
||||
|
||||
void SkReflected::VisitTypes(std::function<void(const Type*)> visitor) {
|
||||
@ -16,9 +14,3 @@ void SkReflected::VisitTypes(std::function<void(const Type*)> visitor) {
|
||||
visitor(type);
|
||||
}
|
||||
}
|
||||
|
||||
void SkFieldVisitor::visit(const char* name, SkCurve& c) {
|
||||
this->enterObject(name);
|
||||
c.visitFields(this);
|
||||
this->exitObject();
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
"EffectCode": [
|
||||
"void effectSpawn(inout Effect effect) {",
|
||||
" effect.rate = 200;",
|
||||
" effect.color = float4(1, 0, 0, 1);",
|
||||
"}",
|
||||
""
|
||||
],
|
||||
@ -17,50 +18,13 @@
|
||||
"}",
|
||||
"",
|
||||
"void update(inout Particle p) {",
|
||||
" p.pos.x = wave(p.age);",
|
||||
" p.color = color(p.age);",
|
||||
" float w = mix(15, 3, p.age);",
|
||||
" p.pos.x = sin(radians(p.age * 320)) * mix(25, 10, p.age) + mix(-w, w, rand);",
|
||||
" if (rand < 0.5) { p.pos.x = -p.pos.x; }",
|
||||
"",
|
||||
" p.color.g = (mix(75, 220, p.age) + mix(-30, 30, rand)) / 255;",
|
||||
"}",
|
||||
""
|
||||
],
|
||||
"Bindings": [
|
||||
{
|
||||
"Type": "SkCurveBinding",
|
||||
"Name": "wave",
|
||||
"Curve": {
|
||||
"XValues": [],
|
||||
"Segments": [
|
||||
{
|
||||
"Type": "Cubic",
|
||||
"Ranged": true,
|
||||
"Bidirectional": true,
|
||||
"A0": -20,
|
||||
"B0": 50,
|
||||
"C0": -30,
|
||||
"D0": -10,
|
||||
"A1": 20,
|
||||
"B1": 60,
|
||||
"C1": -20,
|
||||
"D1": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Type": "SkColorCurveBinding",
|
||||
"Name": "color",
|
||||
"Curve": {
|
||||
"XValues": [],
|
||||
"Segments": [
|
||||
{
|
||||
"Type": "Linear",
|
||||
"Ranged": true,
|
||||
"A0": [ 1, 0, 0, 1 ],
|
||||
"D0": [ 1, 0.735294, 0, 1 ],
|
||||
"A1": [ 1, 0.588235, 0, 1 ],
|
||||
"D1": [ 0.941177, 1, 0, 1 ]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
"Bindings": []
|
||||
}
|
@ -38,7 +38,7 @@ Samples
|
||||
<figure>
|
||||
<canvas id=curves width=400 height=400></canvas>
|
||||
<figcaption>
|
||||
<a href="https://particles.skia.org/e1b1b1f5e3d31b9fae57bf90dce729a8"
|
||||
<a href="https://particles.skia.org/63b1970cc212740e5a44870691c49307"
|
||||
target=_blank rel=noopener>Curves</a>
|
||||
</figcaption>
|
||||
</figure>
|
||||
@ -87,7 +87,7 @@ Samples
|
||||
}).ready().then((CK) => {
|
||||
CanvasKit = CK;
|
||||
ParticleExample(CanvasKit, 'confetti', confetti, 200, 200);
|
||||
ParticleExample(CanvasKit, 'curves', curves, 200, 200);
|
||||
ParticleExample(CanvasKit, 'curves', curves, 200, 300);
|
||||
ParticleExample(CanvasKit, 'fireworks', fireworks, 200, 300);
|
||||
ParticleExample(CanvasKit, 'raincloud', raincloud, 200, 100);
|
||||
ParticleExample(CanvasKit, 'text', text, 75, 250);
|
||||
@ -178,7 +178,8 @@ const curves = {
|
||||
},
|
||||
"EffectCode": [
|
||||
"void effectSpawn(inout Effect effect) {",
|
||||
" effect.rate = 200; effect.pos.y = 100;",
|
||||
" effect.rate = 200;",
|
||||
" effect.color = float4(1, 0, 0, 1);",
|
||||
"}",
|
||||
""
|
||||
],
|
||||
@ -189,52 +190,15 @@ const curves = {
|
||||
"}",
|
||||
"",
|
||||
"void update(inout Particle p) {",
|
||||
" p.pos.x = wave(p.age);",
|
||||
" p.color = color(p.age);",
|
||||
" float w = mix(15, 3, p.age);",
|
||||
" p.pos.x = sin(radians(p.age * 320)) * mix(25, 10, p.age) + mix(-w, w, rand);",
|
||||
" if (rand < 0.5) { p.pos.x = -p.pos.x; }",
|
||||
"",
|
||||
" p.color.g = (mix(75, 220, p.age) + mix(-30, 30, rand)) / 255;",
|
||||
"}",
|
||||
""
|
||||
],
|
||||
"Bindings": [
|
||||
{
|
||||
"Type": "SkCurveBinding",
|
||||
"Name": "wave",
|
||||
"Curve": {
|
||||
"XValues": [],
|
||||
"Segments": [
|
||||
{
|
||||
"Type": "Cubic",
|
||||
"Ranged": true,
|
||||
"Bidirectional": true,
|
||||
"A0": -20,
|
||||
"B0": 50,
|
||||
"C0": -30,
|
||||
"D0": -10,
|
||||
"A1": 20,
|
||||
"B1": 60,
|
||||
"C1": -20,
|
||||
"D1": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Type": "SkColorCurveBinding",
|
||||
"Name": "color",
|
||||
"Curve": {
|
||||
"XValues": [],
|
||||
"Segments": [
|
||||
{
|
||||
"Type": "Linear",
|
||||
"Ranged": true,
|
||||
"A0": [ 1, 0, 0, 1 ],
|
||||
"D0": [ 1, 0.735294, 0, 0.2 ],
|
||||
"A1": [ 1, 0.588235, 0, 1 ],
|
||||
"D1": [ 0.941177, 1, 0, 0.2 ]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
"Bindings": []
|
||||
};
|
||||
|
||||
const fireworks = {
|
||||
|
Loading…
Reference in New Issue
Block a user