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_edit_mode = object_is_edit_mode(ob_ref.object);
|
||||||
const bool in_paint_mode = object_is_paint_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_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(
|
const bool in_edit_paint_mode = object_is_edit_paint_mode(
|
||||||
ob_ref, in_edit_mode, in_paint_mode, in_sculpt_mode);
|
ob_ref, in_edit_mode, in_paint_mode, in_sculpt_mode);
|
||||||
const bool needs_prepass = object_needs_prepass(ob_ref, in_paint_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);
|
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) {
|
if (in_paint_mode) {
|
||||||
switch (ob_ref.object->type) {
|
switch (ob_ref.object->type) {
|
||||||
case OB_MESH:
|
case OB_MESH:
|
||||||
@ -437,6 +442,7 @@ void Instance::draw(Manager &manager)
|
|||||||
layer.facing.draw(framebuffer, manager, view);
|
layer.facing.draw(framebuffer, manager, view);
|
||||||
layer.fade.draw(framebuffer, manager, view);
|
layer.fade.draw(framebuffer, manager, view);
|
||||||
layer.paints.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) {
|
auto draw_layer = [&](OverlayLayer &layer, Framebuffer &framebuffer) {
|
||||||
@ -537,6 +543,11 @@ bool Instance::object_is_sculpt_mode(const ObjectRef &ob_ref)
|
|||||||
return false;
|
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)
|
bool Instance::object_is_sculpt_mode(const Object *object)
|
||||||
{
|
{
|
||||||
if (object->sculpt && (object->sculpt->mode_type == OB_MODE_SCULPT)) {
|
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_selected(const ObjectRef &ob_ref);
|
||||||
bool object_is_edit_mode(const Object *object);
|
bool object_is_edit_mode(const Object *object);
|
||||||
bool object_is_paint_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. */
|
/* Checks for both curve sculpt and regular sculpt mode. */
|
||||||
bool object_is_sculpt_mode(const ObjectRef &ob_ref);
|
bool object_is_sculpt_mode(const ObjectRef &ob_ref);
|
||||||
/* Checks only for sculpt mode. */
|
/* Checks only for sculpt mode. */
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
|
|
||||||
#include "BKE_pointcache.h"
|
#include "BKE_pointcache.h"
|
||||||
|
|
||||||
|
#include "ED_particle.hh"
|
||||||
|
|
||||||
#include "overlay_next_private.hh"
|
#include "overlay_next_private.hh"
|
||||||
|
|
||||||
namespace blender::draw::overlay {
|
namespace blender::draw::overlay {
|
||||||
@ -24,6 +26,14 @@ class Particles {
|
|||||||
PassMain::Sub *shape_ps_ = nullptr;
|
PassMain::Sub *shape_ps_ = nullptr;
|
||||||
PassMain::Sub *hair_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;
|
bool enabled_ = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -37,6 +47,13 @@ class Particles {
|
|||||||
|
|
||||||
const bool is_transform = (G.moving & G_TRANSFORM_OBJ) != 0;
|
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_;
|
auto &pass = particle_ps_;
|
||||||
pass.init();
|
pass.init();
|
||||||
@ -66,6 +83,32 @@ class Particles {
|
|||||||
hair_ps_ = ⊂
|
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
|
/* Particle data are stored in world space. If an object is instanced, the associated particle
|
||||||
@ -90,6 +133,71 @@ class Particles {
|
|||||||
return dupli_mat;
|
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)
|
void object_sync(Manager &manager, const ObjectRef &ob_ref, Resources &res, const State &state)
|
||||||
{
|
{
|
||||||
if (!enabled_) {
|
if (!enabled_) {
|
||||||
@ -100,7 +208,7 @@ class Particles {
|
|||||||
|
|
||||||
ResourceHandle handle = {0};
|
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)) {
|
if (!DRW_object_is_visible_psys_in_active_context(ob, psys)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -181,5 +289,15 @@ class Particles {
|
|||||||
GPU_framebuffer_bind(framebuffer);
|
GPU_framebuffer_bind(framebuffer);
|
||||||
manager.submit(particle_ps_, view);
|
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
|
} // namespace blender::draw::overlay
|
||||||
|
@ -231,6 +231,8 @@ class ShaderModule {
|
|||||||
ShaderPtr outline_prepass_pointcloud;
|
ShaderPtr outline_prepass_pointcloud;
|
||||||
ShaderPtr outline_prepass_gpencil;
|
ShaderPtr outline_prepass_gpencil;
|
||||||
ShaderPtr outline_detect = shader("overlay_outline_detect");
|
ShaderPtr outline_detect = shader("overlay_outline_detect");
|
||||||
|
ShaderPtr particle_edit_vert;
|
||||||
|
ShaderPtr particle_edit_edge;
|
||||||
ShaderPtr paint_region_edge;
|
ShaderPtr paint_region_edge;
|
||||||
ShaderPtr paint_region_face;
|
ShaderPtr paint_region_face;
|
||||||
ShaderPtr paint_region_vert;
|
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");
|
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) {
|
paint_region_edge = shader("overlay_paint_wire", [](gpu::shader::ShaderCreateInfo &info) {
|
||||||
shader_patch_common(info);
|
shader_patch_common(info);
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user