Overlay-Next: Particle Edit #127518
@ -156,6 +156,7 @@ void Instance::object_sync(ObjectRef &ob_ref, Manager &manager)
|
||||
const bool in_edit_mode = object_is_edit_mode(ob_ref.object);
|
||||
const bool in_paint_mode = object_is_paint_mode(ob_ref.object);
|
||||
const bool in_sculpt_mode = object_is_sculpt_mode(ob_ref);
|
||||
const bool in_particle_edit_mode = object_is_particle_edit_mode(ob_ref);
|
||||
const bool in_edit_paint_mode = object_is_edit_paint_mode(
|
||||
ob_ref, in_edit_mode, in_paint_mode, in_sculpt_mode);
|
||||
const bool needs_prepass = object_needs_prepass(ob_ref, in_paint_mode);
|
||||
@ -166,6 +167,10 @@ void Instance::object_sync(ObjectRef &ob_ref, Manager &manager)
|
||||
layer.prepass.object_sync(manager, ob_ref, resources, state);
|
||||
}
|
||||
|
||||
if (in_particle_edit_mode) {
|
||||
layer.particles.edit_object_sync(manager, ob_ref, resources, state);
|
||||
}
|
||||
|
||||
if (in_paint_mode) {
|
||||
switch (ob_ref.object->type) {
|
||||
case OB_MESH:
|
||||
@ -437,6 +442,7 @@ void Instance::draw(Manager &manager)
|
||||
layer.facing.draw(framebuffer, manager, view);
|
||||
layer.fade.draw(framebuffer, manager, view);
|
||||
layer.paints.draw(framebuffer, manager, view);
|
||||
layer.particles.draw_no_line(framebuffer, manager, view);
|
||||
};
|
||||
|
||||
auto draw_layer = [&](OverlayLayer &layer, Framebuffer &framebuffer) {
|
||||
@ -537,6 +543,11 @@ bool Instance::object_is_sculpt_mode(const ObjectRef &ob_ref)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Instance::object_is_particle_edit_mode(const ObjectRef &ob_ref)
|
||||
{
|
||||
return (ob_ref.object->mode == OB_MODE_PARTICLE_EDIT) && (state.ctx_mode == CTX_MODE_PARTICLE);
|
||||
}
|
||||
|
||||
bool Instance::object_is_sculpt_mode(const Object *object)
|
||||
{
|
||||
if (object->sculpt && (object->sculpt->mode_type == OB_MODE_SCULPT)) {
|
||||
|
@ -119,6 +119,7 @@ class Instance {
|
||||
bool object_is_selected(const ObjectRef &ob_ref);
|
||||
bool object_is_edit_mode(const Object *object);
|
||||
bool object_is_paint_mode(const Object *object);
|
||||
bool object_is_particle_edit_mode(const ObjectRef &ob_ref);
|
||||
/* Checks for both curve sculpt and regular sculpt mode. */
|
||||
bool object_is_sculpt_mode(const ObjectRef &ob_ref);
|
||||
/* Checks only for sculpt mode. */
|
||||
|
@ -13,6 +13,8 @@
|
||||
|
||||
#include "BKE_pointcache.h"
|
||||
|
||||
#include "ED_particle.hh"
|
||||
|
||||
#include "overlay_next_private.hh"
|
||||
|
||||
namespace blender::draw::overlay {
|
||||
@ -24,6 +26,14 @@ class Particles {
|
||||
PassMain::Sub *shape_ps_ = nullptr;
|
||||
PassMain::Sub *hair_ps_ = nullptr;
|
||||
|
||||
PassSimple edit_particle_ps_ = {"edit_particle_ps_"};
|
||||
PassSimple::Sub *edit_vert_ps_ = nullptr;
|
||||
PassSimple::Sub *edit_edge_ps_ = nullptr;
|
||||
|
||||
bool show_weight_ = false;
|
||||
bool show_point_inner_ = false;
|
||||
bool show_point_tip_ = false;
|
||||
|
||||
bool enabled_ = false;
|
||||
|
||||
public:
|
||||
@ -37,6 +47,13 @@ class Particles {
|
||||
|
||||
const bool is_transform = (G.moving & G_TRANSFORM_OBJ) != 0;
|
||||
|
||||
const ParticleEditSettings *edit_settings = PE_settings(const_cast<Scene *>(state.scene));
|
||||
if (edit_settings) {
|
||||
show_weight_ = (edit_settings->brushtype == PE_BRUSH_WEIGHT);
|
||||
show_point_inner_ = edit_settings->selectmode == SCE_SELECT_POINT;
|
||||
show_point_tip_ = ELEM(edit_settings->selectmode, SCE_SELECT_POINT, SCE_SELECT_END);
|
||||
}
|
||||
|
||||
{
|
||||
auto &pass = particle_ps_;
|
||||
pass.init();
|
||||
@ -66,6 +83,32 @@ class Particles {
|
||||
hair_ps_ = ⊂
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto &pass = edit_particle_ps_;
|
||||
pass.init();
|
||||
pass.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL,
|
||||
state.clipping_plane_count);
|
||||
res.select_bind(pass);
|
||||
{
|
||||
auto &sub = pass.sub("Dots");
|
||||
sub.shader_set(res.shaders.particle_edit_vert.get());
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
sub.bind_texture("weightTex", res.weight_ramp_tx);
|
||||
sub.push_constant("useWeight", show_weight_);
|
||||
sub.push_constant("useGreasePencil", false);
|
||||
edit_vert_ps_ = ⊂
|
||||
}
|
||||
{
|
||||
auto &sub = pass.sub("Edges");
|
||||
sub.shader_set(res.shaders.particle_edit_edge.get());
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
sub.bind_texture("weightTex", res.weight_ramp_tx);
|
||||
sub.push_constant("useWeight", false);
|
||||
sub.push_constant("useGreasePencil", false);
|
||||
edit_edge_ps_ = ⊂
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Particle data are stored in world space. If an object is instanced, the associated particle
|
||||
@ -90,6 +133,71 @@ class Particles {
|
||||
return dupli_mat;
|
||||
}
|
||||
|
||||
void edit_object_sync(Manager &manager,
|
||||
const ObjectRef &ob_ref,
|
||||
Resources & /*res*/,
|
||||
const State &state)
|
||||
{
|
||||
if (!enabled_) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Usually the edit structure is created by Particle Edit Mode Toggle
|
||||
* operator, but sometimes it's invoked after tagging hair as outdated
|
||||
* (for example, when toggling edit mode). That makes it impossible to
|
||||
* create edit structure for until after next dependency graph evaluation.
|
||||
*
|
||||
* Ideally, the edit structure will be created here already via some
|
||||
* dependency graph callback or so, but currently trying to make it nicer
|
||||
* only causes bad level calls and breaks design from the past.
|
||||
*/
|
||||
Object *object_eval = ob_ref.object;
|
||||
Object *object_orig = DEG_get_original_object(object_eval);
|
||||
Scene *scene_orig = (Scene *)DEG_get_original_id(const_cast<ID *>(&state.scene->id));
|
||||
PTCacheEdit *edit = PE_create_current(state.depsgraph, scene_orig, object_orig);
|
||||
if (edit == nullptr) {
|
||||
/* Happens when trying to edit particles in EMITTER mode without having them cached. */
|
||||
return;
|
||||
}
|
||||
|
||||
auto find_active_evaluated_psys =
|
||||
[&](ListBaseWrapper<ParticleSystem> particle_systems_orig,
|
||||
ListBaseWrapper<ParticleSystem> particle_systems_eval) -> ParticleSystem * {
|
||||
int psys_index = 0;
|
||||
for (ParticleSystem *psys_orig : particle_systems_orig) {
|
||||
if (PE_get_current_from_psys(psys_orig) == edit) {
|
||||
return particle_systems_eval.get(psys_index);
|
||||
}
|
||||
psys_index++;
|
||||
}
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
ParticleSystem *psys = find_active_evaluated_psys(&object_orig->particlesystem,
|
||||
&object_eval->particlesystem);
|
||||
if (psys == nullptr) {
|
||||
printf("Error getting evaluated particle system for edit.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
Object *ob = ob_ref.object;
|
||||
|
||||
ResourceHandle handle = manager.resource_handle_for_psys(ob_ref, dupli_matrix_get(ob_ref));
|
||||
|
||||
{
|
||||
gpu::Batch *geom = DRW_cache_particles_get_edit_strands(ob, psys, edit, show_weight_);
|
||||
edit_edge_ps_->draw(geom, handle);
|
||||
}
|
||||
if (show_point_inner_) {
|
||||
gpu::Batch *geom = DRW_cache_particles_get_edit_inner_points(ob, psys, edit);
|
||||
edit_vert_ps_->draw(geom, handle);
|
||||
}
|
||||
if (show_point_tip_) {
|
||||
gpu::Batch *geom = DRW_cache_particles_get_edit_tip_points(ob, psys, edit);
|
||||
edit_vert_ps_->draw(geom, handle);
|
||||
}
|
||||
}
|
||||
|
||||
void object_sync(Manager &manager, const ObjectRef &ob_ref, Resources &res, const State &state)
|
||||
{
|
||||
if (!enabled_) {
|
||||
@ -100,7 +208,7 @@ class Particles {
|
||||
|
||||
ResourceHandle handle = {0};
|
||||
|
||||
LISTBASE_FOREACH (ParticleSystem *, psys, &ob->particlesystem) {
|
||||
for (ParticleSystem *psys : ListBaseWrapper<ParticleSystem>(&ob->particlesystem)) {
|
||||
if (!DRW_object_is_visible_psys_in_active_context(ob, psys)) {
|
||||
continue;
|
||||
}
|
||||
@ -181,5 +289,15 @@ class Particles {
|
||||
GPU_framebuffer_bind(framebuffer);
|
||||
manager.submit(particle_ps_, view);
|
||||
}
|
||||
|
||||
void draw_no_line(Framebuffer &framebuffer, Manager &manager, View &view)
|
||||
{
|
||||
if (!enabled_) {
|
||||
return;
|
||||
}
|
||||
|
||||
GPU_framebuffer_bind(framebuffer);
|
||||
manager.submit(edit_particle_ps_, view);
|
||||
}
|
||||
};
|
||||
} // namespace blender::draw::overlay
|
||||
|
@ -231,6 +231,8 @@ class ShaderModule {
|
||||
ShaderPtr outline_prepass_pointcloud;
|
||||
ShaderPtr outline_prepass_gpencil;
|
||||
ShaderPtr outline_detect = shader("overlay_outline_detect");
|
||||
ShaderPtr particle_edit_vert;
|
||||
ShaderPtr particle_edit_edge;
|
||||
ShaderPtr paint_region_edge;
|
||||
ShaderPtr paint_region_face;
|
||||
ShaderPtr paint_region_vert;
|
||||
|
@ -255,6 +255,13 @@ ShaderModule::ShaderModule(const SelectionType selection_type, const bool clippi
|
||||
info.additional_info("draw_gpencil_new", "draw_object_infos_new");
|
||||
});
|
||||
|
||||
particle_edit_vert = shader(
|
||||
"overlay_edit_particle_point",
|
||||
[](gpu::shader::ShaderCreateInfo &info) { shader_patch_common(info); });
|
||||
particle_edit_edge = shader(
|
||||
"overlay_edit_particle_strand",
|
||||
[](gpu::shader::ShaderCreateInfo &info) { shader_patch_common(info); });
|
||||
|
||||
paint_region_edge = shader("overlay_paint_wire", [](gpu::shader::ShaderCreateInfo &info) {
|
||||
shader_patch_common(info);
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user