skia2/tools/viewer/ParticlesSlide.cpp

342 lines
11 KiB
C++
Raw Normal View History

Experimental Particle System This adds a new "Particles" slide to viewer, that allows editing, loading, and saving particle effects. All of the particle system code is in modules/particles. There are many rough edges and some not-yet-finished changes to generalize the model[1]. A rough overview: - SkReflected.h implements a lightweight reflection system for classes derived from SkReflected. Adding a new class involves deriving from SkReflected, adding a macro to the class declaration, and implementing visitFields(), which simply calls a virtual on an SkFieldVisitor for each field. Currently, emitters and affectors use this mechanism. - SkParticleSerialization.h demonstrates two useful field visitors - for serializing to and from JSON. The driver code that uses those is directly in ParticlesSlide. - SkParticleData.h and SkCurve.h define a variety of helper types for talking about particles, both for parameterizing individual values, and communicating about the state of a particle among the effect, affectors, and emitters. - SkParticleEffect.h defines the static data definition of an effect (SkParticleEffectParams), as well as a running instance of an effect (SkParticleEffect). The effect has simple update() and draw() methods. - ParticlesSlide.cpp adds a third field visitor to generate GUIs for interactively editing the running effect. --- 1: The critical change I'd like to make is to remove all special case behavior over time and at spawn (setting sprite frames, size over time, color over time, etc...). Integration is the only fixed function behavior. Everything else is driven by two lists of affectors. One is applied at spawn time, using the effect's lifetime to evaluate curves. This allows spawning particles with different colors as the effect ages out, for example. The second list is applied every frame to update existing particles, and is driven by the particle's lifetime. This allows particles to change color after being spawned, for example. With a small set of affectors using a single expressive curve primitive (keyframed list of cubic curve segments), we can have affectors that update color, size, velocity, position, sprite frame, etc., and implement many complex behaviors. Bug: skia: Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4 Reviewed-on: https://skia-review.googlesource.com/c/181404 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
/*
* 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 "ParticlesSlide.h"
#include "ImGuiLayer.h"
Experimental Particle System This adds a new "Particles" slide to viewer, that allows editing, loading, and saving particle effects. All of the particle system code is in modules/particles. There are many rough edges and some not-yet-finished changes to generalize the model[1]. A rough overview: - SkReflected.h implements a lightweight reflection system for classes derived from SkReflected. Adding a new class involves deriving from SkReflected, adding a macro to the class declaration, and implementing visitFields(), which simply calls a virtual on an SkFieldVisitor for each field. Currently, emitters and affectors use this mechanism. - SkParticleSerialization.h demonstrates two useful field visitors - for serializing to and from JSON. The driver code that uses those is directly in ParticlesSlide. - SkParticleData.h and SkCurve.h define a variety of helper types for talking about particles, both for parameterizing individual values, and communicating about the state of a particle among the effect, affectors, and emitters. - SkParticleEffect.h defines the static data definition of an effect (SkParticleEffectParams), as well as a running instance of an effect (SkParticleEffect). The effect has simple update() and draw() methods. - ParticlesSlide.cpp adds a third field visitor to generate GUIs for interactively editing the running effect. --- 1: The critical change I'd like to make is to remove all special case behavior over time and at spawn (setting sprite frames, size over time, color over time, etc...). Integration is the only fixed function behavior. Everything else is driven by two lists of affectors. One is applied at spawn time, using the effect's lifetime to evaluate curves. This allows spawning particles with different colors as the effect ages out, for example. The second list is applied every frame to update existing particles, and is driven by the particle's lifetime. This allows particles to change color after being spawned, for example. With a small set of affectors using a single expressive curve primitive (keyframed list of cubic curve segments), we can have affectors that update color, size, velocity, position, sprite frame, etc., and implement many complex behaviors. Bug: skia: Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4 Reviewed-on: https://skia-review.googlesource.com/c/181404 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
#include "SkParticleAffector.h"
#include "SkParticleDrawable.h"
Experimental Particle System This adds a new "Particles" slide to viewer, that allows editing, loading, and saving particle effects. All of the particle system code is in modules/particles. There are many rough edges and some not-yet-finished changes to generalize the model[1]. A rough overview: - SkReflected.h implements a lightweight reflection system for classes derived from SkReflected. Adding a new class involves deriving from SkReflected, adding a macro to the class declaration, and implementing visitFields(), which simply calls a virtual on an SkFieldVisitor for each field. Currently, emitters and affectors use this mechanism. - SkParticleSerialization.h demonstrates two useful field visitors - for serializing to and from JSON. The driver code that uses those is directly in ParticlesSlide. - SkParticleData.h and SkCurve.h define a variety of helper types for talking about particles, both for parameterizing individual values, and communicating about the state of a particle among the effect, affectors, and emitters. - SkParticleEffect.h defines the static data definition of an effect (SkParticleEffectParams), as well as a running instance of an effect (SkParticleEffect). The effect has simple update() and draw() methods. - ParticlesSlide.cpp adds a third field visitor to generate GUIs for interactively editing the running effect. --- 1: The critical change I'd like to make is to remove all special case behavior over time and at spawn (setting sprite frames, size over time, color over time, etc...). Integration is the only fixed function behavior. Everything else is driven by two lists of affectors. One is applied at spawn time, using the effect's lifetime to evaluate curves. This allows spawning particles with different colors as the effect ages out, for example. The second list is applied every frame to update existing particles, and is driven by the particle's lifetime. This allows particles to change color after being spawned, for example. With a small set of affectors using a single expressive curve primitive (keyframed list of cubic curve segments), we can have affectors that update color, size, velocity, position, sprite frame, etc., and implement many complex behaviors. Bug: skia: Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4 Reviewed-on: https://skia-review.googlesource.com/c/181404 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
#include "SkParticleEffect.h"
#include "SkParticleEmitter.h"
#include "SkParticleSerialization.h"
#include "SkReflected.h"
#include "imgui.h"
using namespace sk_app;
namespace {
static SkScalar kDragSize = 8.0f;
static SkTArray<SkPoint*> gDragPoints;
int gDragIndex = -1;
}
///////////////////////////////////////////////////////////////////////////////
static int InputTextCallback(ImGuiInputTextCallbackData* data) {
if (data->EventFlag == ImGuiInputTextFlags_CallbackResize) {
SkString* s = (SkString*)data->UserData;
SkASSERT(data->Buf == s->writable_str());
SkString tmp(data->Buf, data->BufTextLen);
s->swap(tmp);
data->Buf = s->writable_str();
}
return 0;
}
class SkGuiVisitor : public SkFieldVisitor {
public:
SkGuiVisitor() {
fTreeStack.push_back(true);
}
#define IF_OPEN(WIDGET) if (fTreeStack.back()) { WIDGET; }
void visit(const char* name, float& f, SkField field) override {
if (fTreeStack.back()) {
if (field.fFlags & SkField::kAngle_Field) {
ImGui::SliderAngle(item(name), &f, 0.0f);
Experimental Particle System This adds a new "Particles" slide to viewer, that allows editing, loading, and saving particle effects. All of the particle system code is in modules/particles. There are many rough edges and some not-yet-finished changes to generalize the model[1]. A rough overview: - SkReflected.h implements a lightweight reflection system for classes derived from SkReflected. Adding a new class involves deriving from SkReflected, adding a macro to the class declaration, and implementing visitFields(), which simply calls a virtual on an SkFieldVisitor for each field. Currently, emitters and affectors use this mechanism. - SkParticleSerialization.h demonstrates two useful field visitors - for serializing to and from JSON. The driver code that uses those is directly in ParticlesSlide. - SkParticleData.h and SkCurve.h define a variety of helper types for talking about particles, both for parameterizing individual values, and communicating about the state of a particle among the effect, affectors, and emitters. - SkParticleEffect.h defines the static data definition of an effect (SkParticleEffectParams), as well as a running instance of an effect (SkParticleEffect). The effect has simple update() and draw() methods. - ParticlesSlide.cpp adds a third field visitor to generate GUIs for interactively editing the running effect. --- 1: The critical change I'd like to make is to remove all special case behavior over time and at spawn (setting sprite frames, size over time, color over time, etc...). Integration is the only fixed function behavior. Everything else is driven by two lists of affectors. One is applied at spawn time, using the effect's lifetime to evaluate curves. This allows spawning particles with different colors as the effect ages out, for example. The second list is applied every frame to update existing particles, and is driven by the particle's lifetime. This allows particles to change color after being spawned, for example. With a small set of affectors using a single expressive curve primitive (keyframed list of cubic curve segments), we can have affectors that update color, size, velocity, position, sprite frame, etc., and implement many complex behaviors. Bug: skia: Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4 Reviewed-on: https://skia-review.googlesource.com/c/181404 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
} else {
ImGui::DragFloat(item(name), &f);
Experimental Particle System This adds a new "Particles" slide to viewer, that allows editing, loading, and saving particle effects. All of the particle system code is in modules/particles. There are many rough edges and some not-yet-finished changes to generalize the model[1]. A rough overview: - SkReflected.h implements a lightweight reflection system for classes derived from SkReflected. Adding a new class involves deriving from SkReflected, adding a macro to the class declaration, and implementing visitFields(), which simply calls a virtual on an SkFieldVisitor for each field. Currently, emitters and affectors use this mechanism. - SkParticleSerialization.h demonstrates two useful field visitors - for serializing to and from JSON. The driver code that uses those is directly in ParticlesSlide. - SkParticleData.h and SkCurve.h define a variety of helper types for talking about particles, both for parameterizing individual values, and communicating about the state of a particle among the effect, affectors, and emitters. - SkParticleEffect.h defines the static data definition of an effect (SkParticleEffectParams), as well as a running instance of an effect (SkParticleEffect). The effect has simple update() and draw() methods. - ParticlesSlide.cpp adds a third field visitor to generate GUIs for interactively editing the running effect. --- 1: The critical change I'd like to make is to remove all special case behavior over time and at spawn (setting sprite frames, size over time, color over time, etc...). Integration is the only fixed function behavior. Everything else is driven by two lists of affectors. One is applied at spawn time, using the effect's lifetime to evaluate curves. This allows spawning particles with different colors as the effect ages out, for example. The second list is applied every frame to update existing particles, and is driven by the particle's lifetime. This allows particles to change color after being spawned, for example. With a small set of affectors using a single expressive curve primitive (keyframed list of cubic curve segments), we can have affectors that update color, size, velocity, position, sprite frame, etc., and implement many complex behaviors. Bug: skia: Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4 Reviewed-on: https://skia-review.googlesource.com/c/181404 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
}
}
}
void visit(const char* name, int& i, SkField) override {
IF_OPEN(ImGui::DragInt(item(name), &i))
Experimental Particle System This adds a new "Particles" slide to viewer, that allows editing, loading, and saving particle effects. All of the particle system code is in modules/particles. There are many rough edges and some not-yet-finished changes to generalize the model[1]. A rough overview: - SkReflected.h implements a lightweight reflection system for classes derived from SkReflected. Adding a new class involves deriving from SkReflected, adding a macro to the class declaration, and implementing visitFields(), which simply calls a virtual on an SkFieldVisitor for each field. Currently, emitters and affectors use this mechanism. - SkParticleSerialization.h demonstrates two useful field visitors - for serializing to and from JSON. The driver code that uses those is directly in ParticlesSlide. - SkParticleData.h and SkCurve.h define a variety of helper types for talking about particles, both for parameterizing individual values, and communicating about the state of a particle among the effect, affectors, and emitters. - SkParticleEffect.h defines the static data definition of an effect (SkParticleEffectParams), as well as a running instance of an effect (SkParticleEffect). The effect has simple update() and draw() methods. - ParticlesSlide.cpp adds a third field visitor to generate GUIs for interactively editing the running effect. --- 1: The critical change I'd like to make is to remove all special case behavior over time and at spawn (setting sprite frames, size over time, color over time, etc...). Integration is the only fixed function behavior. Everything else is driven by two lists of affectors. One is applied at spawn time, using the effect's lifetime to evaluate curves. This allows spawning particles with different colors as the effect ages out, for example. The second list is applied every frame to update existing particles, and is driven by the particle's lifetime. This allows particles to change color after being spawned, for example. With a small set of affectors using a single expressive curve primitive (keyframed list of cubic curve segments), we can have affectors that update color, size, velocity, position, sprite frame, etc., and implement many complex behaviors. Bug: skia: Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4 Reviewed-on: https://skia-review.googlesource.com/c/181404 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
}
void visit(const char* name, bool& b, SkField) override {
IF_OPEN(ImGui::Checkbox(item(name), &b))
Experimental Particle System This adds a new "Particles" slide to viewer, that allows editing, loading, and saving particle effects. All of the particle system code is in modules/particles. There are many rough edges and some not-yet-finished changes to generalize the model[1]. A rough overview: - SkReflected.h implements a lightweight reflection system for classes derived from SkReflected. Adding a new class involves deriving from SkReflected, adding a macro to the class declaration, and implementing visitFields(), which simply calls a virtual on an SkFieldVisitor for each field. Currently, emitters and affectors use this mechanism. - SkParticleSerialization.h demonstrates two useful field visitors - for serializing to and from JSON. The driver code that uses those is directly in ParticlesSlide. - SkParticleData.h and SkCurve.h define a variety of helper types for talking about particles, both for parameterizing individual values, and communicating about the state of a particle among the effect, affectors, and emitters. - SkParticleEffect.h defines the static data definition of an effect (SkParticleEffectParams), as well as a running instance of an effect (SkParticleEffect). The effect has simple update() and draw() methods. - ParticlesSlide.cpp adds a third field visitor to generate GUIs for interactively editing the running effect. --- 1: The critical change I'd like to make is to remove all special case behavior over time and at spawn (setting sprite frames, size over time, color over time, etc...). Integration is the only fixed function behavior. Everything else is driven by two lists of affectors. One is applied at spawn time, using the effect's lifetime to evaluate curves. This allows spawning particles with different colors as the effect ages out, for example. The second list is applied every frame to update existing particles, and is driven by the particle's lifetime. This allows particles to change color after being spawned, for example. With a small set of affectors using a single expressive curve primitive (keyframed list of cubic curve segments), we can have affectors that update color, size, velocity, position, sprite frame, etc., and implement many complex behaviors. Bug: skia: Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4 Reviewed-on: https://skia-review.googlesource.com/c/181404 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
}
void visit(const char* name, SkString& s, SkField) override {
if (fTreeStack.back()) {
ImGuiInputTextFlags flags = ImGuiInputTextFlags_CallbackResize;
ImGui::InputText(item(name), s.writable_str(), s.size() + 1, flags, InputTextCallback,
&s);
Experimental Particle System This adds a new "Particles" slide to viewer, that allows editing, loading, and saving particle effects. All of the particle system code is in modules/particles. There are many rough edges and some not-yet-finished changes to generalize the model[1]. A rough overview: - SkReflected.h implements a lightweight reflection system for classes derived from SkReflected. Adding a new class involves deriving from SkReflected, adding a macro to the class declaration, and implementing visitFields(), which simply calls a virtual on an SkFieldVisitor for each field. Currently, emitters and affectors use this mechanism. - SkParticleSerialization.h demonstrates two useful field visitors - for serializing to and from JSON. The driver code that uses those is directly in ParticlesSlide. - SkParticleData.h and SkCurve.h define a variety of helper types for talking about particles, both for parameterizing individual values, and communicating about the state of a particle among the effect, affectors, and emitters. - SkParticleEffect.h defines the static data definition of an effect (SkParticleEffectParams), as well as a running instance of an effect (SkParticleEffect). The effect has simple update() and draw() methods. - ParticlesSlide.cpp adds a third field visitor to generate GUIs for interactively editing the running effect. --- 1: The critical change I'd like to make is to remove all special case behavior over time and at spawn (setting sprite frames, size over time, color over time, etc...). Integration is the only fixed function behavior. Everything else is driven by two lists of affectors. One is applied at spawn time, using the effect's lifetime to evaluate curves. This allows spawning particles with different colors as the effect ages out, for example. The second list is applied every frame to update existing particles, and is driven by the particle's lifetime. This allows particles to change color after being spawned, for example. With a small set of affectors using a single expressive curve primitive (keyframed list of cubic curve segments), we can have affectors that update color, size, velocity, position, sprite frame, etc., and implement many complex behaviors. Bug: skia: Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4 Reviewed-on: https://skia-review.googlesource.com/c/181404 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
}
}
void visit(const char* name, SkPoint& p, SkField) override {
if (fTreeStack.back()) {
ImGui::DragFloat2(item(name), &p.fX);
Experimental Particle System This adds a new "Particles" slide to viewer, that allows editing, loading, and saving particle effects. All of the particle system code is in modules/particles. There are many rough edges and some not-yet-finished changes to generalize the model[1]. A rough overview: - SkReflected.h implements a lightweight reflection system for classes derived from SkReflected. Adding a new class involves deriving from SkReflected, adding a macro to the class declaration, and implementing visitFields(), which simply calls a virtual on an SkFieldVisitor for each field. Currently, emitters and affectors use this mechanism. - SkParticleSerialization.h demonstrates two useful field visitors - for serializing to and from JSON. The driver code that uses those is directly in ParticlesSlide. - SkParticleData.h and SkCurve.h define a variety of helper types for talking about particles, both for parameterizing individual values, and communicating about the state of a particle among the effect, affectors, and emitters. - SkParticleEffect.h defines the static data definition of an effect (SkParticleEffectParams), as well as a running instance of an effect (SkParticleEffect). The effect has simple update() and draw() methods. - ParticlesSlide.cpp adds a third field visitor to generate GUIs for interactively editing the running effect. --- 1: The critical change I'd like to make is to remove all special case behavior over time and at spawn (setting sprite frames, size over time, color over time, etc...). Integration is the only fixed function behavior. Everything else is driven by two lists of affectors. One is applied at spawn time, using the effect's lifetime to evaluate curves. This allows spawning particles with different colors as the effect ages out, for example. The second list is applied every frame to update existing particles, and is driven by the particle's lifetime. This allows particles to change color after being spawned, for example. With a small set of affectors using a single expressive curve primitive (keyframed list of cubic curve segments), we can have affectors that update color, size, velocity, position, sprite frame, etc., and implement many complex behaviors. Bug: skia: Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4 Reviewed-on: https://skia-review.googlesource.com/c/181404 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
gDragPoints.push_back(&p);
}
}
void visit(const char* name, SkColor4f& c, SkField) override {
IF_OPEN(ImGui::ColorEdit4(item(name), c.vec()))
Experimental Particle System This adds a new "Particles" slide to viewer, that allows editing, loading, and saving particle effects. All of the particle system code is in modules/particles. There are many rough edges and some not-yet-finished changes to generalize the model[1]. A rough overview: - SkReflected.h implements a lightweight reflection system for classes derived from SkReflected. Adding a new class involves deriving from SkReflected, adding a macro to the class declaration, and implementing visitFields(), which simply calls a virtual on an SkFieldVisitor for each field. Currently, emitters and affectors use this mechanism. - SkParticleSerialization.h demonstrates two useful field visitors - for serializing to and from JSON. The driver code that uses those is directly in ParticlesSlide. - SkParticleData.h and SkCurve.h define a variety of helper types for talking about particles, both for parameterizing individual values, and communicating about the state of a particle among the effect, affectors, and emitters. - SkParticleEffect.h defines the static data definition of an effect (SkParticleEffectParams), as well as a running instance of an effect (SkParticleEffect). The effect has simple update() and draw() methods. - ParticlesSlide.cpp adds a third field visitor to generate GUIs for interactively editing the running effect. --- 1: The critical change I'd like to make is to remove all special case behavior over time and at spawn (setting sprite frames, size over time, color over time, etc...). Integration is the only fixed function behavior. Everything else is driven by two lists of affectors. One is applied at spawn time, using the effect's lifetime to evaluate curves. This allows spawning particles with different colors as the effect ages out, for example. The second list is applied every frame to update existing particles, and is driven by the particle's lifetime. This allows particles to change color after being spawned, for example. With a small set of affectors using a single expressive curve primitive (keyframed list of cubic curve segments), we can have affectors that update color, size, velocity, position, sprite frame, etc., and implement many complex behaviors. Bug: skia: Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4 Reviewed-on: https://skia-review.googlesource.com/c/181404 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
}
#undef IF_OPEN
Experimental Particle System This adds a new "Particles" slide to viewer, that allows editing, loading, and saving particle effects. All of the particle system code is in modules/particles. There are many rough edges and some not-yet-finished changes to generalize the model[1]. A rough overview: - SkReflected.h implements a lightweight reflection system for classes derived from SkReflected. Adding a new class involves deriving from SkReflected, adding a macro to the class declaration, and implementing visitFields(), which simply calls a virtual on an SkFieldVisitor for each field. Currently, emitters and affectors use this mechanism. - SkParticleSerialization.h demonstrates two useful field visitors - for serializing to and from JSON. The driver code that uses those is directly in ParticlesSlide. - SkParticleData.h and SkCurve.h define a variety of helper types for talking about particles, both for parameterizing individual values, and communicating about the state of a particle among the effect, affectors, and emitters. - SkParticleEffect.h defines the static data definition of an effect (SkParticleEffectParams), as well as a running instance of an effect (SkParticleEffect). The effect has simple update() and draw() methods. - ParticlesSlide.cpp adds a third field visitor to generate GUIs for interactively editing the running effect. --- 1: The critical change I'd like to make is to remove all special case behavior over time and at spawn (setting sprite frames, size over time, color over time, etc...). Integration is the only fixed function behavior. Everything else is driven by two lists of affectors. One is applied at spawn time, using the effect's lifetime to evaluate curves. This allows spawning particles with different colors as the effect ages out, for example. The second list is applied every frame to update existing particles, and is driven by the particle's lifetime. This allows particles to change color after being spawned, for example. With a small set of affectors using a single expressive curve primitive (keyframed list of cubic curve segments), we can have affectors that update color, size, velocity, position, sprite frame, etc., and implement many complex behaviors. Bug: skia: Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4 Reviewed-on: https://skia-review.googlesource.com/c/181404 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
void visit(const char* name, SkCurve& c, SkField) override {
this->enterObject(item(name));
Experimental Particle System This adds a new "Particles" slide to viewer, that allows editing, loading, and saving particle effects. All of the particle system code is in modules/particles. There are many rough edges and some not-yet-finished changes to generalize the model[1]. A rough overview: - SkReflected.h implements a lightweight reflection system for classes derived from SkReflected. Adding a new class involves deriving from SkReflected, adding a macro to the class declaration, and implementing visitFields(), which simply calls a virtual on an SkFieldVisitor for each field. Currently, emitters and affectors use this mechanism. - SkParticleSerialization.h demonstrates two useful field visitors - for serializing to and from JSON. The driver code that uses those is directly in ParticlesSlide. - SkParticleData.h and SkCurve.h define a variety of helper types for talking about particles, both for parameterizing individual values, and communicating about the state of a particle among the effect, affectors, and emitters. - SkParticleEffect.h defines the static data definition of an effect (SkParticleEffectParams), as well as a running instance of an effect (SkParticleEffect). The effect has simple update() and draw() methods. - ParticlesSlide.cpp adds a third field visitor to generate GUIs for interactively editing the running effect. --- 1: The critical change I'd like to make is to remove all special case behavior over time and at spawn (setting sprite frames, size over time, color over time, etc...). Integration is the only fixed function behavior. Everything else is driven by two lists of affectors. One is applied at spawn time, using the effect's lifetime to evaluate curves. This allows spawning particles with different colors as the effect ages out, for example. The second list is applied every frame to update existing particles, and is driven by the particle's lifetime. This allows particles to change color after being spawned, for example. With a small set of affectors using a single expressive curve primitive (keyframed list of cubic curve segments), we can have affectors that update color, size, velocity, position, sprite frame, etc., and implement many complex behaviors. Bug: skia: Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4 Reviewed-on: https://skia-review.googlesource.com/c/181404 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
if (fTreeStack.back()) {
// Get vertical extents of the curve
SkScalar extents[2];
c.getExtents(extents);
// Grow the extents by 10%, at least 1.0f
SkScalar grow = SkTMax((extents[1] - extents[0]) * 0.1f, 1.0f);
extents[0] -= grow;
extents[1] += grow;
{
ImGui::DragCanvas dc(&c, { 0.0f, extents[1] }, { 1.0f, extents[0] }, 0.5f);
dc.fillColor(IM_COL32(0, 0, 0, 128));
for (int i = 0; i < c.fSegments.count(); ++i) {
SkSTArray<8, ImVec2, true> pts;
SkScalar rangeMin = (i == 0) ? 0.0f : c.fXValues[i - 1];
SkScalar rangeMax = (i == c.fXValues.count()) ? 1.0f : c.fXValues[i];
auto screenPoint = [&](int idx, bool useMax) {
SkScalar xVal = rangeMin + (idx / 3.0f) * (rangeMax - rangeMin);
SkScalar* yVals = useMax ? c.fSegments[i].fMax : c.fSegments[i].fMin;
SkScalar yVal = yVals[c.fSegments[i].fConstant ? 0 : idx];
SkPoint pt = dc.fLocalToScreen.mapXY(xVal, yVal);
return ImVec2(pt.fX, pt.fY);
};
for (int i = 0; i < 4; ++i) {
pts.push_back(screenPoint(i, false));
}
if (c.fSegments[i].fRanged) {
for (int i = 3; i >= 0; --i) {
pts.push_back(screenPoint(i, true));
}
}
if (c.fSegments[i].fRanged) {
dc.fDrawList->PathLineTo(pts[0]);
dc.fDrawList->PathBezierCurveTo(pts[1], pts[2], pts[3]);
dc.fDrawList->PathLineTo(pts[4]);
dc.fDrawList->PathBezierCurveTo(pts[5], pts[6], pts[7]);
dc.fDrawList->PathFillConvex(IM_COL32(255, 255, 255, 128));
} else {
dc.fDrawList->AddBezierCurve(pts[0], pts[1], pts[2], pts[3],
IM_COL32(255, 255, 255, 255), 1.0f);
}
}
Experimental Particle System This adds a new "Particles" slide to viewer, that allows editing, loading, and saving particle effects. All of the particle system code is in modules/particles. There are many rough edges and some not-yet-finished changes to generalize the model[1]. A rough overview: - SkReflected.h implements a lightweight reflection system for classes derived from SkReflected. Adding a new class involves deriving from SkReflected, adding a macro to the class declaration, and implementing visitFields(), which simply calls a virtual on an SkFieldVisitor for each field. Currently, emitters and affectors use this mechanism. - SkParticleSerialization.h demonstrates two useful field visitors - for serializing to and from JSON. The driver code that uses those is directly in ParticlesSlide. - SkParticleData.h and SkCurve.h define a variety of helper types for talking about particles, both for parameterizing individual values, and communicating about the state of a particle among the effect, affectors, and emitters. - SkParticleEffect.h defines the static data definition of an effect (SkParticleEffectParams), as well as a running instance of an effect (SkParticleEffect). The effect has simple update() and draw() methods. - ParticlesSlide.cpp adds a third field visitor to generate GUIs for interactively editing the running effect. --- 1: The critical change I'd like to make is to remove all special case behavior over time and at spawn (setting sprite frames, size over time, color over time, etc...). Integration is the only fixed function behavior. Everything else is driven by two lists of affectors. One is applied at spawn time, using the effect's lifetime to evaluate curves. This allows spawning particles with different colors as the effect ages out, for example. The second list is applied every frame to update existing particles, and is driven by the particle's lifetime. This allows particles to change color after being spawned, for example. With a small set of affectors using a single expressive curve primitive (keyframed list of cubic curve segments), we can have affectors that update color, size, velocity, position, sprite frame, etc., and implement many complex behaviors. Bug: skia: Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4 Reviewed-on: https://skia-review.googlesource.com/c/181404 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
}
c.visitFields(this);
Experimental Particle System This adds a new "Particles" slide to viewer, that allows editing, loading, and saving particle effects. All of the particle system code is in modules/particles. There are many rough edges and some not-yet-finished changes to generalize the model[1]. A rough overview: - SkReflected.h implements a lightweight reflection system for classes derived from SkReflected. Adding a new class involves deriving from SkReflected, adding a macro to the class declaration, and implementing visitFields(), which simply calls a virtual on an SkFieldVisitor for each field. Currently, emitters and affectors use this mechanism. - SkParticleSerialization.h demonstrates two useful field visitors - for serializing to and from JSON. The driver code that uses those is directly in ParticlesSlide. - SkParticleData.h and SkCurve.h define a variety of helper types for talking about particles, both for parameterizing individual values, and communicating about the state of a particle among the effect, affectors, and emitters. - SkParticleEffect.h defines the static data definition of an effect (SkParticleEffectParams), as well as a running instance of an effect (SkParticleEffect). The effect has simple update() and draw() methods. - ParticlesSlide.cpp adds a third field visitor to generate GUIs for interactively editing the running effect. --- 1: The critical change I'd like to make is to remove all special case behavior over time and at spawn (setting sprite frames, size over time, color over time, etc...). Integration is the only fixed function behavior. Everything else is driven by two lists of affectors. One is applied at spawn time, using the effect's lifetime to evaluate curves. This allows spawning particles with different colors as the effect ages out, for example. The second list is applied every frame to update existing particles, and is driven by the particle's lifetime. This allows particles to change color after being spawned, for example. With a small set of affectors using a single expressive curve primitive (keyframed list of cubic curve segments), we can have affectors that update color, size, velocity, position, sprite frame, etc., and implement many complex behaviors. Bug: skia: Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4 Reviewed-on: https://skia-review.googlesource.com/c/181404 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
}
this->exitObject();
}
void visit(sk_sp<SkReflected>& e, const SkReflected::Type* baseType) override {
if (fTreeStack.back()) {
const SkReflected::Type* curType = e ? e->getType() : nullptr;
if (ImGui::BeginCombo("Type", curType ? curType->fName : "Null")) {
auto visitType = [curType,&e](const SkReflected::Type* t) {
if (ImGui::Selectable(t->fName, curType == t)) {
e = t->fFactory();
}
};
SkReflected::VisitTypes(visitType, baseType);
ImGui::EndCombo();
}
}
}
void enterObject(const char* name) override {
if (fTreeStack.back()) {
fTreeStack.push_back(ImGui::TreeNodeEx(item(name),
ImGuiTreeNodeFlags_AllowItemOverlap));
Experimental Particle System This adds a new "Particles" slide to viewer, that allows editing, loading, and saving particle effects. All of the particle system code is in modules/particles. There are many rough edges and some not-yet-finished changes to generalize the model[1]. A rough overview: - SkReflected.h implements a lightweight reflection system for classes derived from SkReflected. Adding a new class involves deriving from SkReflected, adding a macro to the class declaration, and implementing visitFields(), which simply calls a virtual on an SkFieldVisitor for each field. Currently, emitters and affectors use this mechanism. - SkParticleSerialization.h demonstrates two useful field visitors - for serializing to and from JSON. The driver code that uses those is directly in ParticlesSlide. - SkParticleData.h and SkCurve.h define a variety of helper types for talking about particles, both for parameterizing individual values, and communicating about the state of a particle among the effect, affectors, and emitters. - SkParticleEffect.h defines the static data definition of an effect (SkParticleEffectParams), as well as a running instance of an effect (SkParticleEffect). The effect has simple update() and draw() methods. - ParticlesSlide.cpp adds a third field visitor to generate GUIs for interactively editing the running effect. --- 1: The critical change I'd like to make is to remove all special case behavior over time and at spawn (setting sprite frames, size over time, color over time, etc...). Integration is the only fixed function behavior. Everything else is driven by two lists of affectors. One is applied at spawn time, using the effect's lifetime to evaluate curves. This allows spawning particles with different colors as the effect ages out, for example. The second list is applied every frame to update existing particles, and is driven by the particle's lifetime. This allows particles to change color after being spawned, for example. With a small set of affectors using a single expressive curve primitive (keyframed list of cubic curve segments), we can have affectors that update color, size, velocity, position, sprite frame, etc., and implement many complex behaviors. Bug: skia: Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4 Reviewed-on: https://skia-review.googlesource.com/c/181404 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
} else {
fTreeStack.push_back(false);
}
}
void exitObject() override {
if (fTreeStack.back()) {
ImGui::TreePop();
}
fTreeStack.pop_back();
}
int enterArray(const char* name, int oldCount) override {
this->enterObject(item(name));
fArrayCounterStack.push_back(0);
fArrayEditStack.push_back();
Experimental Particle System This adds a new "Particles" slide to viewer, that allows editing, loading, and saving particle effects. All of the particle system code is in modules/particles. There are many rough edges and some not-yet-finished changes to generalize the model[1]. A rough overview: - SkReflected.h implements a lightweight reflection system for classes derived from SkReflected. Adding a new class involves deriving from SkReflected, adding a macro to the class declaration, and implementing visitFields(), which simply calls a virtual on an SkFieldVisitor for each field. Currently, emitters and affectors use this mechanism. - SkParticleSerialization.h demonstrates two useful field visitors - for serializing to and from JSON. The driver code that uses those is directly in ParticlesSlide. - SkParticleData.h and SkCurve.h define a variety of helper types for talking about particles, both for parameterizing individual values, and communicating about the state of a particle among the effect, affectors, and emitters. - SkParticleEffect.h defines the static data definition of an effect (SkParticleEffectParams), as well as a running instance of an effect (SkParticleEffect). The effect has simple update() and draw() methods. - ParticlesSlide.cpp adds a third field visitor to generate GUIs for interactively editing the running effect. --- 1: The critical change I'd like to make is to remove all special case behavior over time and at spawn (setting sprite frames, size over time, color over time, etc...). Integration is the only fixed function behavior. Everything else is driven by two lists of affectors. One is applied at spawn time, using the effect's lifetime to evaluate curves. This allows spawning particles with different colors as the effect ages out, for example. The second list is applied every frame to update existing particles, and is driven by the particle's lifetime. This allows particles to change color after being spawned, for example. With a small set of affectors using a single expressive curve primitive (keyframed list of cubic curve segments), we can have affectors that update color, size, velocity, position, sprite frame, etc., and implement many complex behaviors. Bug: skia: Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4 Reviewed-on: https://skia-review.googlesource.com/c/181404 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
int count = oldCount;
Experimental Particle System This adds a new "Particles" slide to viewer, that allows editing, loading, and saving particle effects. All of the particle system code is in modules/particles. There are many rough edges and some not-yet-finished changes to generalize the model[1]. A rough overview: - SkReflected.h implements a lightweight reflection system for classes derived from SkReflected. Adding a new class involves deriving from SkReflected, adding a macro to the class declaration, and implementing visitFields(), which simply calls a virtual on an SkFieldVisitor for each field. Currently, emitters and affectors use this mechanism. - SkParticleSerialization.h demonstrates two useful field visitors - for serializing to and from JSON. The driver code that uses those is directly in ParticlesSlide. - SkParticleData.h and SkCurve.h define a variety of helper types for talking about particles, both for parameterizing individual values, and communicating about the state of a particle among the effect, affectors, and emitters. - SkParticleEffect.h defines the static data definition of an effect (SkParticleEffectParams), as well as a running instance of an effect (SkParticleEffect). The effect has simple update() and draw() methods. - ParticlesSlide.cpp adds a third field visitor to generate GUIs for interactively editing the running effect. --- 1: The critical change I'd like to make is to remove all special case behavior over time and at spawn (setting sprite frames, size over time, color over time, etc...). Integration is the only fixed function behavior. Everything else is driven by two lists of affectors. One is applied at spawn time, using the effect's lifetime to evaluate curves. This allows spawning particles with different colors as the effect ages out, for example. The second list is applied every frame to update existing particles, and is driven by the particle's lifetime. This allows particles to change color after being spawned, for example. With a small set of affectors using a single expressive curve primitive (keyframed list of cubic curve segments), we can have affectors that update color, size, velocity, position, sprite frame, etc., and implement many complex behaviors. Bug: skia: Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4 Reviewed-on: https://skia-review.googlesource.com/c/181404 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
if (fTreeStack.back()) {
ImGui::SameLine();
Experimental Particle System This adds a new "Particles" slide to viewer, that allows editing, loading, and saving particle effects. All of the particle system code is in modules/particles. There are many rough edges and some not-yet-finished changes to generalize the model[1]. A rough overview: - SkReflected.h implements a lightweight reflection system for classes derived from SkReflected. Adding a new class involves deriving from SkReflected, adding a macro to the class declaration, and implementing visitFields(), which simply calls a virtual on an SkFieldVisitor for each field. Currently, emitters and affectors use this mechanism. - SkParticleSerialization.h demonstrates two useful field visitors - for serializing to and from JSON. The driver code that uses those is directly in ParticlesSlide. - SkParticleData.h and SkCurve.h define a variety of helper types for talking about particles, both for parameterizing individual values, and communicating about the state of a particle among the effect, affectors, and emitters. - SkParticleEffect.h defines the static data definition of an effect (SkParticleEffectParams), as well as a running instance of an effect (SkParticleEffect). The effect has simple update() and draw() methods. - ParticlesSlide.cpp adds a third field visitor to generate GUIs for interactively editing the running effect. --- 1: The critical change I'd like to make is to remove all special case behavior over time and at spawn (setting sprite frames, size over time, color over time, etc...). Integration is the only fixed function behavior. Everything else is driven by two lists of affectors. One is applied at spawn time, using the effect's lifetime to evaluate curves. This allows spawning particles with different colors as the effect ages out, for example. The second list is applied every frame to update existing particles, and is driven by the particle's lifetime. This allows particles to change color after being spawned, for example. With a small set of affectors using a single expressive curve primitive (keyframed list of cubic curve segments), we can have affectors that update color, size, velocity, position, sprite frame, etc., and implement many complex behaviors. Bug: skia: Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4 Reviewed-on: https://skia-review.googlesource.com/c/181404 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
if (ImGui::Button("+")) {
++count;
Experimental Particle System This adds a new "Particles" slide to viewer, that allows editing, loading, and saving particle effects. All of the particle system code is in modules/particles. There are many rough edges and some not-yet-finished changes to generalize the model[1]. A rough overview: - SkReflected.h implements a lightweight reflection system for classes derived from SkReflected. Adding a new class involves deriving from SkReflected, adding a macro to the class declaration, and implementing visitFields(), which simply calls a virtual on an SkFieldVisitor for each field. Currently, emitters and affectors use this mechanism. - SkParticleSerialization.h demonstrates two useful field visitors - for serializing to and from JSON. The driver code that uses those is directly in ParticlesSlide. - SkParticleData.h and SkCurve.h define a variety of helper types for talking about particles, both for parameterizing individual values, and communicating about the state of a particle among the effect, affectors, and emitters. - SkParticleEffect.h defines the static data definition of an effect (SkParticleEffectParams), as well as a running instance of an effect (SkParticleEffect). The effect has simple update() and draw() methods. - ParticlesSlide.cpp adds a third field visitor to generate GUIs for interactively editing the running effect. --- 1: The critical change I'd like to make is to remove all special case behavior over time and at spawn (setting sprite frames, size over time, color over time, etc...). Integration is the only fixed function behavior. Everything else is driven by two lists of affectors. One is applied at spawn time, using the effect's lifetime to evaluate curves. This allows spawning particles with different colors as the effect ages out, for example. The second list is applied every frame to update existing particles, and is driven by the particle's lifetime. This allows particles to change color after being spawned, for example. With a small set of affectors using a single expressive curve primitive (keyframed list of cubic curve segments), we can have affectors that update color, size, velocity, position, sprite frame, etc., and implement many complex behaviors. Bug: skia: Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4 Reviewed-on: https://skia-review.googlesource.com/c/181404 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
}
}
return count;
}
ArrayEdit exitArray() override {
fArrayCounterStack.pop_back();
auto edit = fArrayEditStack.back();
fArrayEditStack.pop_back();
Experimental Particle System This adds a new "Particles" slide to viewer, that allows editing, loading, and saving particle effects. All of the particle system code is in modules/particles. There are many rough edges and some not-yet-finished changes to generalize the model[1]. A rough overview: - SkReflected.h implements a lightweight reflection system for classes derived from SkReflected. Adding a new class involves deriving from SkReflected, adding a macro to the class declaration, and implementing visitFields(), which simply calls a virtual on an SkFieldVisitor for each field. Currently, emitters and affectors use this mechanism. - SkParticleSerialization.h demonstrates two useful field visitors - for serializing to and from JSON. The driver code that uses those is directly in ParticlesSlide. - SkParticleData.h and SkCurve.h define a variety of helper types for talking about particles, both for parameterizing individual values, and communicating about the state of a particle among the effect, affectors, and emitters. - SkParticleEffect.h defines the static data definition of an effect (SkParticleEffectParams), as well as a running instance of an effect (SkParticleEffect). The effect has simple update() and draw() methods. - ParticlesSlide.cpp adds a third field visitor to generate GUIs for interactively editing the running effect. --- 1: The critical change I'd like to make is to remove all special case behavior over time and at spawn (setting sprite frames, size over time, color over time, etc...). Integration is the only fixed function behavior. Everything else is driven by two lists of affectors. One is applied at spawn time, using the effect's lifetime to evaluate curves. This allows spawning particles with different colors as the effect ages out, for example. The second list is applied every frame to update existing particles, and is driven by the particle's lifetime. This allows particles to change color after being spawned, for example. With a small set of affectors using a single expressive curve primitive (keyframed list of cubic curve segments), we can have affectors that update color, size, velocity, position, sprite frame, etc., and implement many complex behaviors. Bug: skia: Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4 Reviewed-on: https://skia-review.googlesource.com/c/181404 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
this->exitObject();
return edit;
Experimental Particle System This adds a new "Particles" slide to viewer, that allows editing, loading, and saving particle effects. All of the particle system code is in modules/particles. There are many rough edges and some not-yet-finished changes to generalize the model[1]. A rough overview: - SkReflected.h implements a lightweight reflection system for classes derived from SkReflected. Adding a new class involves deriving from SkReflected, adding a macro to the class declaration, and implementing visitFields(), which simply calls a virtual on an SkFieldVisitor for each field. Currently, emitters and affectors use this mechanism. - SkParticleSerialization.h demonstrates two useful field visitors - for serializing to and from JSON. The driver code that uses those is directly in ParticlesSlide. - SkParticleData.h and SkCurve.h define a variety of helper types for talking about particles, both for parameterizing individual values, and communicating about the state of a particle among the effect, affectors, and emitters. - SkParticleEffect.h defines the static data definition of an effect (SkParticleEffectParams), as well as a running instance of an effect (SkParticleEffect). The effect has simple update() and draw() methods. - ParticlesSlide.cpp adds a third field visitor to generate GUIs for interactively editing the running effect. --- 1: The critical change I'd like to make is to remove all special case behavior over time and at spawn (setting sprite frames, size over time, color over time, etc...). Integration is the only fixed function behavior. Everything else is driven by two lists of affectors. One is applied at spawn time, using the effect's lifetime to evaluate curves. This allows spawning particles with different colors as the effect ages out, for example. The second list is applied every frame to update existing particles, and is driven by the particle's lifetime. This allows particles to change color after being spawned, for example. With a small set of affectors using a single expressive curve primitive (keyframed list of cubic curve segments), we can have affectors that update color, size, velocity, position, sprite frame, etc., and implement many complex behaviors. Bug: skia: Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4 Reviewed-on: https://skia-review.googlesource.com/c/181404 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
}
private:
const char* item(const char* name) {
if (name) {
return name;
}
// We're in an array. Add extra controls and a dynamic label.
int index = fArrayCounterStack.back()++;
ArrayEdit& edit(fArrayEditStack.back());
fScratchLabel = SkStringPrintf("[%d]", index);
ImGui::PushID(index);
if (ImGui::Button("X")) {
edit.fVerb = ArrayEdit::Verb::kRemove;
edit.fIndex = index;
}
ImGui::SameLine();
if (ImGui::Button("^")) {
edit.fVerb = ArrayEdit::Verb::kMoveForward;
edit.fIndex = index;
}
ImGui::SameLine();
if (ImGui::Button("v")) {
edit.fVerb = ArrayEdit::Verb::kMoveForward;
edit.fIndex = index + 1;
}
ImGui::SameLine();
ImGui::PopID();
return fScratchLabel.c_str();
}
Experimental Particle System This adds a new "Particles" slide to viewer, that allows editing, loading, and saving particle effects. All of the particle system code is in modules/particles. There are many rough edges and some not-yet-finished changes to generalize the model[1]. A rough overview: - SkReflected.h implements a lightweight reflection system for classes derived from SkReflected. Adding a new class involves deriving from SkReflected, adding a macro to the class declaration, and implementing visitFields(), which simply calls a virtual on an SkFieldVisitor for each field. Currently, emitters and affectors use this mechanism. - SkParticleSerialization.h demonstrates two useful field visitors - for serializing to and from JSON. The driver code that uses those is directly in ParticlesSlide. - SkParticleData.h and SkCurve.h define a variety of helper types for talking about particles, both for parameterizing individual values, and communicating about the state of a particle among the effect, affectors, and emitters. - SkParticleEffect.h defines the static data definition of an effect (SkParticleEffectParams), as well as a running instance of an effect (SkParticleEffect). The effect has simple update() and draw() methods. - ParticlesSlide.cpp adds a third field visitor to generate GUIs for interactively editing the running effect. --- 1: The critical change I'd like to make is to remove all special case behavior over time and at spawn (setting sprite frames, size over time, color over time, etc...). Integration is the only fixed function behavior. Everything else is driven by two lists of affectors. One is applied at spawn time, using the effect's lifetime to evaluate curves. This allows spawning particles with different colors as the effect ages out, for example. The second list is applied every frame to update existing particles, and is driven by the particle's lifetime. This allows particles to change color after being spawned, for example. With a small set of affectors using a single expressive curve primitive (keyframed list of cubic curve segments), we can have affectors that update color, size, velocity, position, sprite frame, etc., and implement many complex behaviors. Bug: skia: Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4 Reviewed-on: https://skia-review.googlesource.com/c/181404 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
SkSTArray<16, bool, true> fTreeStack;
SkSTArray<16, int, true> fArrayCounterStack;
SkSTArray<16, ArrayEdit, true> fArrayEditStack;
SkString fScratchLabel;
Experimental Particle System This adds a new "Particles" slide to viewer, that allows editing, loading, and saving particle effects. All of the particle system code is in modules/particles. There are many rough edges and some not-yet-finished changes to generalize the model[1]. A rough overview: - SkReflected.h implements a lightweight reflection system for classes derived from SkReflected. Adding a new class involves deriving from SkReflected, adding a macro to the class declaration, and implementing visitFields(), which simply calls a virtual on an SkFieldVisitor for each field. Currently, emitters and affectors use this mechanism. - SkParticleSerialization.h demonstrates two useful field visitors - for serializing to and from JSON. The driver code that uses those is directly in ParticlesSlide. - SkParticleData.h and SkCurve.h define a variety of helper types for talking about particles, both for parameterizing individual values, and communicating about the state of a particle among the effect, affectors, and emitters. - SkParticleEffect.h defines the static data definition of an effect (SkParticleEffectParams), as well as a running instance of an effect (SkParticleEffect). The effect has simple update() and draw() methods. - ParticlesSlide.cpp adds a third field visitor to generate GUIs for interactively editing the running effect. --- 1: The critical change I'd like to make is to remove all special case behavior over time and at spawn (setting sprite frames, size over time, color over time, etc...). Integration is the only fixed function behavior. Everything else is driven by two lists of affectors. One is applied at spawn time, using the effect's lifetime to evaluate curves. This allows spawning particles with different colors as the effect ages out, for example. The second list is applied every frame to update existing particles, and is driven by the particle's lifetime. This allows particles to change color after being spawned, for example. With a small set of affectors using a single expressive curve primitive (keyframed list of cubic curve segments), we can have affectors that update color, size, velocity, position, sprite frame, etc., and implement many complex behaviors. Bug: skia: Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4 Reviewed-on: https://skia-review.googlesource.com/c/181404 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
};
static sk_sp<SkParticleEffectParams> LoadEffectParams(const char* filename) {
sk_sp<SkParticleEffectParams> params(new SkParticleEffectParams());
if (auto fileData = SkData::MakeFromFileName(filename)) {
skjson::DOM dom(static_cast<const char*>(fileData->data()), fileData->size());
SkFromJsonVisitor fromJson(dom.root());
params->visitFields(&fromJson);
}
return params;
}
ParticlesSlide::ParticlesSlide() {
// Register types for serialization
REGISTER_REFLECTED(SkReflected);
SkParticleAffector::RegisterAffectorTypes();
SkParticleDrawable::RegisterDrawableTypes();
Experimental Particle System This adds a new "Particles" slide to viewer, that allows editing, loading, and saving particle effects. All of the particle system code is in modules/particles. There are many rough edges and some not-yet-finished changes to generalize the model[1]. A rough overview: - SkReflected.h implements a lightweight reflection system for classes derived from SkReflected. Adding a new class involves deriving from SkReflected, adding a macro to the class declaration, and implementing visitFields(), which simply calls a virtual on an SkFieldVisitor for each field. Currently, emitters and affectors use this mechanism. - SkParticleSerialization.h demonstrates two useful field visitors - for serializing to and from JSON. The driver code that uses those is directly in ParticlesSlide. - SkParticleData.h and SkCurve.h define a variety of helper types for talking about particles, both for parameterizing individual values, and communicating about the state of a particle among the effect, affectors, and emitters. - SkParticleEffect.h defines the static data definition of an effect (SkParticleEffectParams), as well as a running instance of an effect (SkParticleEffect). The effect has simple update() and draw() methods. - ParticlesSlide.cpp adds a third field visitor to generate GUIs for interactively editing the running effect. --- 1: The critical change I'd like to make is to remove all special case behavior over time and at spawn (setting sprite frames, size over time, color over time, etc...). Integration is the only fixed function behavior. Everything else is driven by two lists of affectors. One is applied at spawn time, using the effect's lifetime to evaluate curves. This allows spawning particles with different colors as the effect ages out, for example. The second list is applied every frame to update existing particles, and is driven by the particle's lifetime. This allows particles to change color after being spawned, for example. With a small set of affectors using a single expressive curve primitive (keyframed list of cubic curve segments), we can have affectors that update color, size, velocity, position, sprite frame, etc., and implement many complex behaviors. Bug: skia: Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4 Reviewed-on: https://skia-review.googlesource.com/c/181404 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
SkParticleEmitter::RegisterEmitterTypes();
fName = "Particles";
}
void ParticlesSlide::load(SkScalar winWidth, SkScalar winHeight) {
fEffect.reset(new SkParticleEffect(LoadEffectParams("resources/particles/default.json"),
fRandom));
Experimental Particle System This adds a new "Particles" slide to viewer, that allows editing, loading, and saving particle effects. All of the particle system code is in modules/particles. There are many rough edges and some not-yet-finished changes to generalize the model[1]. A rough overview: - SkReflected.h implements a lightweight reflection system for classes derived from SkReflected. Adding a new class involves deriving from SkReflected, adding a macro to the class declaration, and implementing visitFields(), which simply calls a virtual on an SkFieldVisitor for each field. Currently, emitters and affectors use this mechanism. - SkParticleSerialization.h demonstrates two useful field visitors - for serializing to and from JSON. The driver code that uses those is directly in ParticlesSlide. - SkParticleData.h and SkCurve.h define a variety of helper types for talking about particles, both for parameterizing individual values, and communicating about the state of a particle among the effect, affectors, and emitters. - SkParticleEffect.h defines the static data definition of an effect (SkParticleEffectParams), as well as a running instance of an effect (SkParticleEffect). The effect has simple update() and draw() methods. - ParticlesSlide.cpp adds a third field visitor to generate GUIs for interactively editing the running effect. --- 1: The critical change I'd like to make is to remove all special case behavior over time and at spawn (setting sprite frames, size over time, color over time, etc...). Integration is the only fixed function behavior. Everything else is driven by two lists of affectors. One is applied at spawn time, using the effect's lifetime to evaluate curves. This allows spawning particles with different colors as the effect ages out, for example. The second list is applied every frame to update existing particles, and is driven by the particle's lifetime. This allows particles to change color after being spawned, for example. With a small set of affectors using a single expressive curve primitive (keyframed list of cubic curve segments), we can have affectors that update color, size, velocity, position, sprite frame, etc., and implement many complex behaviors. Bug: skia: Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4 Reviewed-on: https://skia-review.googlesource.com/c/181404 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
}
void ParticlesSlide::draw(SkCanvas* canvas) {
canvas->clear(0);
gDragPoints.reset();
if (ImGui::Begin("Particles")) {
static bool looped = true;
ImGui::Checkbox("Looped", &looped);
if (fTimer && ImGui::Button("Play")) {
fEffect->start(*fTimer, looped);
}
Experimental Particle System This adds a new "Particles" slide to viewer, that allows editing, loading, and saving particle effects. All of the particle system code is in modules/particles. There are many rough edges and some not-yet-finished changes to generalize the model[1]. A rough overview: - SkReflected.h implements a lightweight reflection system for classes derived from SkReflected. Adding a new class involves deriving from SkReflected, adding a macro to the class declaration, and implementing visitFields(), which simply calls a virtual on an SkFieldVisitor for each field. Currently, emitters and affectors use this mechanism. - SkParticleSerialization.h demonstrates two useful field visitors - for serializing to and from JSON. The driver code that uses those is directly in ParticlesSlide. - SkParticleData.h and SkCurve.h define a variety of helper types for talking about particles, both for parameterizing individual values, and communicating about the state of a particle among the effect, affectors, and emitters. - SkParticleEffect.h defines the static data definition of an effect (SkParticleEffectParams), as well as a running instance of an effect (SkParticleEffect). The effect has simple update() and draw() methods. - ParticlesSlide.cpp adds a third field visitor to generate GUIs for interactively editing the running effect. --- 1: The critical change I'd like to make is to remove all special case behavior over time and at spawn (setting sprite frames, size over time, color over time, etc...). Integration is the only fixed function behavior. Everything else is driven by two lists of affectors. One is applied at spawn time, using the effect's lifetime to evaluate curves. This allows spawning particles with different colors as the effect ages out, for example. The second list is applied every frame to update existing particles, and is driven by the particle's lifetime. This allows particles to change color after being spawned, for example. With a small set of affectors using a single expressive curve primitive (keyframed list of cubic curve segments), we can have affectors that update color, size, velocity, position, sprite frame, etc., and implement many complex behaviors. Bug: skia: Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4 Reviewed-on: https://skia-review.googlesource.com/c/181404 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
static char filename[64] = "resources/particles/default.json";
ImGui::InputText("Filename", filename, sizeof(filename));
if (ImGui::Button("Load")) {
if (auto newParams = LoadEffectParams(filename)) {
fEffect.reset(new SkParticleEffect(std::move(newParams), fRandom));
Experimental Particle System This adds a new "Particles" slide to viewer, that allows editing, loading, and saving particle effects. All of the particle system code is in modules/particles. There are many rough edges and some not-yet-finished changes to generalize the model[1]. A rough overview: - SkReflected.h implements a lightweight reflection system for classes derived from SkReflected. Adding a new class involves deriving from SkReflected, adding a macro to the class declaration, and implementing visitFields(), which simply calls a virtual on an SkFieldVisitor for each field. Currently, emitters and affectors use this mechanism. - SkParticleSerialization.h demonstrates two useful field visitors - for serializing to and from JSON. The driver code that uses those is directly in ParticlesSlide. - SkParticleData.h and SkCurve.h define a variety of helper types for talking about particles, both for parameterizing individual values, and communicating about the state of a particle among the effect, affectors, and emitters. - SkParticleEffect.h defines the static data definition of an effect (SkParticleEffectParams), as well as a running instance of an effect (SkParticleEffect). The effect has simple update() and draw() methods. - ParticlesSlide.cpp adds a third field visitor to generate GUIs for interactively editing the running effect. --- 1: The critical change I'd like to make is to remove all special case behavior over time and at spawn (setting sprite frames, size over time, color over time, etc...). Integration is the only fixed function behavior. Everything else is driven by two lists of affectors. One is applied at spawn time, using the effect's lifetime to evaluate curves. This allows spawning particles with different colors as the effect ages out, for example. The second list is applied every frame to update existing particles, and is driven by the particle's lifetime. This allows particles to change color after being spawned, for example. With a small set of affectors using a single expressive curve primitive (keyframed list of cubic curve segments), we can have affectors that update color, size, velocity, position, sprite frame, etc., and implement many complex behaviors. Bug: skia: Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4 Reviewed-on: https://skia-review.googlesource.com/c/181404 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
}
}
ImGui::SameLine();
if (ImGui::Button("Save")) {
SkFILEWStream fileStream(filename);
if (fileStream.isValid()) {
SkJSONWriter writer(&fileStream, SkJSONWriter::Mode::kPretty);
SkToJsonVisitor toJson(writer);
writer.beginObject();
fEffect->getParams()->visitFields(&toJson);
writer.endObject();
writer.flush();
fileStream.flush();
} else {
SkDebugf("Failed to open file\n");
}
}
SkGuiVisitor gui;
fEffect->getParams()->visitFields(&gui);
}
ImGui::End();
SkPaint dragPaint;
dragPaint.setColor(SK_ColorLTGRAY);
dragPaint.setAntiAlias(true);
SkPaint dragHighlight;
dragHighlight.setStyle(SkPaint::kStroke_Style);
dragHighlight.setColor(SK_ColorGREEN);
dragHighlight.setStrokeWidth(2);
dragHighlight.setAntiAlias(true);
for (int i = 0; i < gDragPoints.count(); ++i) {
canvas->drawCircle(*gDragPoints[i], kDragSize, dragPaint);
if (gDragIndex == i) {
canvas->drawCircle(*gDragPoints[i], kDragSize, dragHighlight);
}
}
fEffect->draw(canvas);
}
bool ParticlesSlide::animate(const SkAnimTimer& timer) {
fTimer = &timer;
fEffect->update(timer);
Experimental Particle System This adds a new "Particles" slide to viewer, that allows editing, loading, and saving particle effects. All of the particle system code is in modules/particles. There are many rough edges and some not-yet-finished changes to generalize the model[1]. A rough overview: - SkReflected.h implements a lightweight reflection system for classes derived from SkReflected. Adding a new class involves deriving from SkReflected, adding a macro to the class declaration, and implementing visitFields(), which simply calls a virtual on an SkFieldVisitor for each field. Currently, emitters and affectors use this mechanism. - SkParticleSerialization.h demonstrates two useful field visitors - for serializing to and from JSON. The driver code that uses those is directly in ParticlesSlide. - SkParticleData.h and SkCurve.h define a variety of helper types for talking about particles, both for parameterizing individual values, and communicating about the state of a particle among the effect, affectors, and emitters. - SkParticleEffect.h defines the static data definition of an effect (SkParticleEffectParams), as well as a running instance of an effect (SkParticleEffect). The effect has simple update() and draw() methods. - ParticlesSlide.cpp adds a third field visitor to generate GUIs for interactively editing the running effect. --- 1: The critical change I'd like to make is to remove all special case behavior over time and at spawn (setting sprite frames, size over time, color over time, etc...). Integration is the only fixed function behavior. Everything else is driven by two lists of affectors. One is applied at spawn time, using the effect's lifetime to evaluate curves. This allows spawning particles with different colors as the effect ages out, for example. The second list is applied every frame to update existing particles, and is driven by the particle's lifetime. This allows particles to change color after being spawned, for example. With a small set of affectors using a single expressive curve primitive (keyframed list of cubic curve segments), we can have affectors that update color, size, velocity, position, sprite frame, etc., and implement many complex behaviors. Bug: skia: Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4 Reviewed-on: https://skia-review.googlesource.com/c/181404 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
return true;
}
bool ParticlesSlide::onMouse(SkScalar x, SkScalar y, Window::InputState state, uint32_t modifiers) {
if (gDragIndex == -1) {
if (state == Window::kDown_InputState) {
float bestDistance = kDragSize;
SkPoint mousePt = { x, y };
for (int i = 0; i < gDragPoints.count(); ++i) {
float distance = SkPoint::Distance(*gDragPoints[i], mousePt);
if (distance < bestDistance) {
gDragIndex = i;
bestDistance = distance;
}
}
return gDragIndex != -1;
}
} else {
// Currently dragging
SkASSERT(gDragIndex < gDragPoints.count());
gDragPoints[gDragIndex]->set(x, y);
if (state == Window::kUp_InputState) {
gDragIndex = -1;
}
return true;
}
return false;
}