Readfile: Refactor several parts of the process #108016
|
@ -2097,9 +2097,7 @@ class USERPREF_PT_addons(AddOnPanel, Panel):
|
|||
split.label(text=" " + info["warning"], icon='ERROR')
|
||||
|
||||
user_addon = USERPREF_PT_addons.is_user_addon(mod, user_addon_paths)
|
||||
tot_row = bool(info["doc_url"]) + bool(user_addon)
|
||||
|
||||
if tot_row:
|
||||
if info["doc_url"] or info.get("tracker_url"):
|
||||
split = colsub.row().split(factor=0.15)
|
||||
split.label(text="Internet:")
|
||||
sub = split.row()
|
||||
|
@ -2123,10 +2121,13 @@ class USERPREF_PT_addons(AddOnPanel, Panel):
|
|||
)
|
||||
props.type = 'BUG_ADDON'
|
||||
props.id = addon_info
|
||||
if user_addon:
|
||||
sub.operator(
|
||||
"preferences.addon_remove", text="Remove", icon='CANCEL',
|
||||
).module = mod.__name__
|
||||
|
||||
if user_addon:
|
||||
split = colsub.row().split(factor=0.15)
|
||||
split.label(text="User:")
|
||||
split.operator(
|
||||
"preferences.addon_remove", text="Remove", icon='CANCEL',
|
||||
).module = mod.__name__
|
||||
|
||||
# Show addon user preferences
|
||||
if is_enabled:
|
||||
|
|
|
@ -2303,6 +2303,16 @@ class VIEW3D_MT_volume_add(Menu):
|
|||
icon='OUTLINER_DATA_VOLUME')
|
||||
|
||||
|
||||
class VIEW3D_MT_grease_pencil_add(Menu):
|
||||
bl_idname = "VIEW3D_MT_grease_pencil_add"
|
||||
bl_label = "Grease Pencil"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
layout.operator("object.grease_pencil_add", text="Empty", icon='EMPTY_AXIS').type = 'EMPTY'
|
||||
layout.operator("object.grease_pencil_add", text="Stroke", icon='STROKE').type = 'STROKE'
|
||||
|
||||
|
||||
class VIEW3D_MT_add(Menu):
|
||||
bl_label = "Add"
|
||||
bl_translation_context = i18n_contexts.operator_default
|
||||
|
@ -2328,7 +2338,14 @@ class VIEW3D_MT_add(Menu):
|
|||
if context.preferences.experimental.use_new_point_cloud_type:
|
||||
layout.operator("object.pointcloud_add", text="Point Cloud", icon='OUTLINER_OB_POINTCLOUD')
|
||||
layout.menu("VIEW3D_MT_volume_add", text="Volume", text_ctxt=i18n_contexts.id_id, icon='OUTLINER_OB_VOLUME')
|
||||
layout.operator_menu_enum("object.gpencil_add", "type", text="Grease Pencil", icon='OUTLINER_OB_GREASEPENCIL')
|
||||
if context.preferences.experimental.use_grease_pencil_version3:
|
||||
layout.menu("VIEW3D_MT_grease_pencil_add", text="Grease Pencil", icon='OUTLINER_OB_GREASEPENCIL')
|
||||
else:
|
||||
layout.operator_menu_enum(
|
||||
"object.gpencil_add",
|
||||
"type",
|
||||
text="Grease Pencil",
|
||||
icon='OUTLINER_OB_GREASEPENCIL')
|
||||
|
||||
layout.separator()
|
||||
|
||||
|
@ -8188,6 +8205,7 @@ classes = (
|
|||
VIEW3D_MT_lightprobe_add,
|
||||
VIEW3D_MT_camera_add,
|
||||
VIEW3D_MT_volume_add,
|
||||
VIEW3D_MT_grease_pencil_add,
|
||||
VIEW3D_MT_add,
|
||||
VIEW3D_MT_image_add,
|
||||
VIEW3D_MT_object,
|
||||
|
|
|
@ -18,6 +18,13 @@
|
|||
#include "DNA_gpencil_legacy_types.h"
|
||||
#include "DNA_grease_pencil_types.h"
|
||||
|
||||
struct Main;
|
||||
struct Depsgraph;
|
||||
struct BoundBox;
|
||||
struct Scene;
|
||||
struct Object;
|
||||
struct Material;
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
namespace greasepencil {
|
||||
|
@ -196,7 +203,6 @@ class Layer : public ::GreasePencilLayer {
|
|||
* \returns true on success.
|
||||
*/
|
||||
bool insert_frame(int frame_number, const GreasePencilFrame &frame);
|
||||
bool insert_frame(int frame_number, GreasePencilFrame &&frame);
|
||||
|
||||
/**
|
||||
* Inserts the frame into the layer. If there exists a frame at \a frame_number already, it is
|
||||
|
@ -204,7 +210,6 @@ class Layer : public ::GreasePencilLayer {
|
|||
* \returns true on success.
|
||||
*/
|
||||
bool overwrite_frame(int frame_number, const GreasePencilFrame &frame);
|
||||
bool overwrite_frame(int frame_number, GreasePencilFrame &&frame);
|
||||
|
||||
/**
|
||||
* Returns the sorted (start) frame numbers of the frames of this layer.
|
||||
|
@ -365,12 +370,6 @@ inline bool GreasePencil::has_active_layer() const
|
|||
return (this->active_layer != nullptr);
|
||||
}
|
||||
|
||||
struct Main;
|
||||
struct Depsgraph;
|
||||
struct BoundBox;
|
||||
struct Scene;
|
||||
struct Object;
|
||||
|
||||
void *BKE_grease_pencil_add(Main *bmain, const char *name);
|
||||
GreasePencil *BKE_grease_pencil_new_nomain();
|
||||
BoundBox *BKE_grease_pencil_boundbox_get(Object *ob);
|
||||
|
@ -378,5 +377,15 @@ void BKE_grease_pencil_data_update(struct Depsgraph *depsgraph,
|
|||
struct Scene *scene,
|
||||
struct Object *object);
|
||||
|
||||
int BKE_grease_pencil_object_material_index_get_by_name(Object *ob, const char *name);
|
||||
Material *BKE_grease_pencil_object_material_new(Main *bmain,
|
||||
Object *ob,
|
||||
const char *name,
|
||||
int *r_index);
|
||||
Material *BKE_grease_pencil_object_material_ensure_by_name(Main *bmain,
|
||||
Object *ob,
|
||||
const char *name,
|
||||
int *r_index);
|
||||
|
||||
bool BKE_grease_pencil_references_cyclic_check(const GreasePencil *id_reference,
|
||||
const GreasePencil *grease_pencil);
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "BKE_idtype.h"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_lib_query.h"
|
||||
#include "BKE_material.h"
|
||||
#include "BKE_object.h"
|
||||
|
||||
#include "BLI_map.hh"
|
||||
|
@ -408,24 +409,12 @@ bool Layer::insert_frame(int frame_number, const GreasePencilFrame &frame)
|
|||
return this->frames_for_write().add(frame_number, frame);
|
||||
}
|
||||
|
||||
bool Layer::insert_frame(int frame_number, GreasePencilFrame &&frame)
|
||||
{
|
||||
this->tag_frames_map_changed();
|
||||
return this->frames_for_write().add(frame_number, frame);
|
||||
}
|
||||
|
||||
bool Layer::overwrite_frame(int frame_number, const GreasePencilFrame &frame)
|
||||
{
|
||||
this->tag_frames_map_changed();
|
||||
return this->frames_for_write().add_overwrite(frame_number, frame);
|
||||
}
|
||||
|
||||
bool Layer::overwrite_frame(int frame_number, GreasePencilFrame &&frame)
|
||||
{
|
||||
this->tag_frames_map_changed();
|
||||
return this->frames_for_write().add_overwrite(frame_number, std::move(frame));
|
||||
}
|
||||
|
||||
Span<int> Layer::sorted_keys() const
|
||||
{
|
||||
this->runtime->sorted_keys_cache_.ensure([&](Vector<int> &r_data) {
|
||||
|
@ -495,13 +484,13 @@ LayerGroup::LayerGroup(const LayerGroup &other) : LayerGroup()
|
|||
switch (child->type) {
|
||||
case GP_LAYER_TREE_LEAF: {
|
||||
GreasePencilLayer *layer = reinterpret_cast<GreasePencilLayer *>(child);
|
||||
Layer *dup_layer = new Layer(layer->wrap());
|
||||
Layer *dup_layer = MEM_new<Layer>(__func__, layer->wrap());
|
||||
this->add_layer(dup_layer);
|
||||
break;
|
||||
}
|
||||
case GP_LAYER_TREE_GROUP: {
|
||||
GreasePencilLayerTreeGroup *group = reinterpret_cast<GreasePencilLayerTreeGroup *>(child);
|
||||
LayerGroup *dup_group = new LayerGroup(group->wrap());
|
||||
LayerGroup *dup_group = MEM_new<LayerGroup>(__func__, group->wrap());
|
||||
this->add_group(dup_group);
|
||||
break;
|
||||
}
|
||||
|
@ -517,12 +506,12 @@ LayerGroup::~LayerGroup()
|
|||
switch (child->type) {
|
||||
case GP_LAYER_TREE_LEAF: {
|
||||
GreasePencilLayer *layer = reinterpret_cast<GreasePencilLayer *>(child);
|
||||
layer->wrap().~Layer();
|
||||
MEM_delete(&layer->wrap());
|
||||
break;
|
||||
}
|
||||
case GP_LAYER_TREE_GROUP: {
|
||||
GreasePencilLayerTreeGroup *group = reinterpret_cast<GreasePencilLayerTreeGroup *>(child);
|
||||
group->wrap().~LayerGroup();
|
||||
MEM_delete(&group->wrap());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -543,7 +532,7 @@ LayerGroup &LayerGroup::add_group(LayerGroup *group)
|
|||
|
||||
LayerGroup &LayerGroup::add_group(StringRefNull name)
|
||||
{
|
||||
LayerGroup *new_group = new LayerGroup(name);
|
||||
LayerGroup *new_group = MEM_new<LayerGroup>(__func__, name);
|
||||
return this->add_group(new_group);
|
||||
}
|
||||
|
||||
|
@ -558,7 +547,7 @@ Layer &LayerGroup::add_layer(Layer *layer)
|
|||
|
||||
Layer &LayerGroup::add_layer(StringRefNull name)
|
||||
{
|
||||
Layer *new_layer = new Layer(name);
|
||||
Layer *new_layer = MEM_new<Layer>(__func__, name);
|
||||
return this->add_layer(new_layer);
|
||||
}
|
||||
|
||||
|
@ -754,6 +743,56 @@ void BKE_grease_pencil_data_update(struct Depsgraph * /*depsgraph*/,
|
|||
|
||||
/** \} */
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
/** \name Grease Pencil material functions
|
||||
* \{ */
|
||||
|
||||
int BKE_grease_pencil_object_material_index_get_by_name(Object *ob, const char *name)
|
||||
{
|
||||
short *totcol = BKE_object_material_len_p(ob);
|
||||
Material *read_ma = NULL;
|
||||
for (short i = 0; i < *totcol; i++) {
|
||||
read_ma = BKE_object_material_get(ob, i + 1);
|
||||
if (STREQ(name, read_ma->id.name + 2)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
Material *BKE_grease_pencil_object_material_new(Main *bmain,
|
||||
Object *ob,
|
||||
const char *name,
|
||||
int *r_index)
|
||||
{
|
||||
Material *ma = BKE_gpencil_material_add(bmain, name);
|
||||
id_us_min(&ma->id); /* no users yet */
|
||||
|
||||
BKE_object_material_slot_add(bmain, ob);
|
||||
BKE_object_material_assign(bmain, ob, ma, ob->totcol, BKE_MAT_ASSIGN_USERPREF);
|
||||
|
||||
if (r_index) {
|
||||
*r_index = ob->actcol - 1;
|
||||
}
|
||||
return ma;
|
||||
}
|
||||
|
||||
Material *BKE_grease_pencil_object_material_ensure_by_name(Main *bmain,
|
||||
Object *ob,
|
||||
const char *name,
|
||||
int *r_index)
|
||||
{
|
||||
int index = BKE_grease_pencil_object_material_index_get_by_name(ob, name);
|
||||
if (index != -1) {
|
||||
*r_index = index;
|
||||
return BKE_object_material_get(ob, index + 1);
|
||||
}
|
||||
return BKE_grease_pencil_object_material_new(bmain, ob, name, r_index);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
/** \name Grease Pencil reference functions
|
||||
* \{ */
|
||||
|
|
|
@ -152,14 +152,6 @@ IndexMask IndexMask::slice_and_offset(const int64_t start,
|
|||
return sliced_mask;
|
||||
}
|
||||
|
||||
IndexMask IndexMask::complement(const IndexRange universe, IndexMaskMemory &memory) const
|
||||
{
|
||||
/* TODO: Implement more efficient solution. */
|
||||
return IndexMask::from_predicate(universe, GrainSize(512), memory, [&](const int64_t index) {
|
||||
return !this->contains(index);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges consecutive segments in some cases. Having fewer but larger segments generally allows for
|
||||
* better performance when using the mask later on.
|
||||
|
@ -332,6 +324,168 @@ struct ParallelSegmentsCollector {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert a range to potentially multiple index mask segments.
|
||||
*/
|
||||
static void range_to_segments(const IndexRange range, Vector<IndexMaskSegment, 16> &r_segments)
|
||||
{
|
||||
const Span<int16_t> static_indices = get_static_indices_array();
|
||||
for (int64_t start = 0; start < range.size(); start += max_segment_size) {
|
||||
const int64_t size = std::min(max_segment_size, range.size() - start);
|
||||
r_segments.append_as(range.start() + start, static_indices.take_front(size));
|
||||
}
|
||||
}
|
||||
|
||||
static int64_t get_size_before_gap(const Span<int16_t> indices)
|
||||
{
|
||||
BLI_assert(indices.size() >= 2);
|
||||
if (indices[1] > indices[0] + 1) {
|
||||
/* For sparse indices, often the next gap is just after the next index.
|
||||
* In this case we can skip the logarithmic check below.*/
|
||||
return 1;
|
||||
}
|
||||
return unique_sorted_indices::find_size_of_next_range(indices);
|
||||
}
|
||||
|
||||
static void inverted_indices_to_segments(const IndexMaskSegment segment,
|
||||
LinearAllocator<> &allocator,
|
||||
Vector<IndexMaskSegment, 16> &r_segments)
|
||||
{
|
||||
constexpr int64_t range_threshold = 64;
|
||||
const int64_t offset = segment.offset();
|
||||
const Span<int16_t> static_indices = get_static_indices_array();
|
||||
|
||||
int64_t inverted_index_count = 0;
|
||||
std::array<int16_t, max_segment_size> inverted_indices_array;
|
||||
auto add_indices = [&](const int16_t start, const int16_t num) {
|
||||
int16_t *new_indices_begin = inverted_indices_array.data() + inverted_index_count;
|
||||
std::iota(new_indices_begin, new_indices_begin + num, start);
|
||||
inverted_index_count += num;
|
||||
};
|
||||
|
||||
auto finish_indices = [&]() {
|
||||
if (inverted_index_count == 0) {
|
||||
return;
|
||||
}
|
||||
MutableSpan<int16_t> offset_indices = allocator.allocate_array<int16_t>(inverted_index_count);
|
||||
offset_indices.copy_from(Span(inverted_indices_array).take_front(inverted_index_count));
|
||||
r_segments.append_as(offset, offset_indices);
|
||||
inverted_index_count = 0;
|
||||
};
|
||||
|
||||
Span<int16_t> indices = segment.base_span();
|
||||
while (indices.size() > 1) {
|
||||
const int64_t size_before_gap = get_size_before_gap(indices);
|
||||
if (size_before_gap == indices.size()) {
|
||||
break;
|
||||
}
|
||||
|
||||
const int16_t gap_first = indices[size_before_gap - 1] + 1;
|
||||
const int16_t next = indices[size_before_gap];
|
||||
const int16_t gap_size = next - gap_first;
|
||||
if (gap_size > range_threshold) {
|
||||
finish_indices();
|
||||
r_segments.append_as(offset + gap_first, static_indices.take_front(gap_size));
|
||||
}
|
||||
else {
|
||||
add_indices(gap_first, gap_size);
|
||||
}
|
||||
|
||||
indices = indices.drop_front(size_before_gap);
|
||||
}
|
||||
|
||||
finish_indices();
|
||||
}
|
||||
|
||||
static void invert_segments(const IndexMask &mask,
|
||||
const IndexRange segment_range,
|
||||
LinearAllocator<> &allocator,
|
||||
Vector<IndexMaskSegment, 16> &r_segments)
|
||||
{
|
||||
for (const int64_t segment_i : segment_range) {
|
||||
const IndexMaskSegment segment = mask.segment(segment_i);
|
||||
inverted_indices_to_segments(segment, allocator, r_segments);
|
||||
|
||||
const IndexMaskSegment next_segment = mask.segment(segment_i + 1);
|
||||
const int64_t between_start = segment.last() + 1;
|
||||
const int64_t size_between_segments = next_segment[0] - segment.last() - 1;
|
||||
const IndexRange range_between_segments(between_start, size_between_segments);
|
||||
if (!range_between_segments.is_empty()) {
|
||||
range_to_segments(range_between_segments, r_segments);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IndexMask IndexMask::complement(const IndexRange universe, IndexMaskMemory &memory) const
|
||||
{
|
||||
if (this->is_empty()) {
|
||||
return universe;
|
||||
}
|
||||
if (universe.is_empty()) {
|
||||
return {};
|
||||
}
|
||||
const std::optional<IndexRange> this_range = this->to_range();
|
||||
if (this_range) {
|
||||
const bool first_in_range = this_range->first() <= universe.first();
|
||||
const bool last_in_range = this_range->last() >= universe.last();
|
||||
if (first_in_range && last_in_range) {
|
||||
/* This mask fills the entire universe, so the complement is empty. */
|
||||
return {};
|
||||
}
|
||||
if (first_in_range) {
|
||||
/* This mask is a range that contains the start of the universe.
|
||||
* The complement is a range that contains the end of the universe. */
|
||||
const int64_t complement_start = this_range->one_after_last();
|
||||
const int64_t complement_size = universe.one_after_last() - complement_start;
|
||||
return IndexRange(complement_start, complement_size);
|
||||
}
|
||||
if (last_in_range) {
|
||||
/* This mask is a range that contains the end of the universe.
|
||||
* The complement is a range that contains the start of the universe. */
|
||||
const int64_t complement_start = universe.first();
|
||||
const int64_t complement_size = this_range->first() - complement_start;
|
||||
return IndexRange(complement_start, complement_size);
|
||||
}
|
||||
}
|
||||
|
||||
Vector<IndexMaskSegment, 16> segments;
|
||||
|
||||
if (universe.start() < this->first()) {
|
||||
range_to_segments(universe.take_front(this->first() - universe.start()), segments);
|
||||
}
|
||||
|
||||
if (!this_range) {
|
||||
const int64_t segments_num = this->segments_num();
|
||||
|
||||
constexpr int64_t min_grain_size = 16;
|
||||
constexpr int64_t max_grain_size = 4096;
|
||||
const int64_t threads_num = BLI_system_thread_count();
|
||||
const int64_t grain_size = std::clamp(
|
||||
segments_num / threads_num, min_grain_size, max_grain_size);
|
||||
|
||||
const IndexRange non_last_segments = IndexRange(segments_num).drop_back(1);
|
||||
if (segments_num < min_grain_size) {
|
||||
invert_segments(*this, non_last_segments, memory, segments);
|
||||
}
|
||||
else {
|
||||
ParallelSegmentsCollector segments_collector;
|
||||
threading::parallel_for(non_last_segments, grain_size, [&](const IndexRange range) {
|
||||
ParallelSegmentsCollector::LocalData &local_data =
|
||||
segments_collector.data_by_thread.local();
|
||||
invert_segments(*this, range, local_data.allocator, local_data.segments);
|
||||
});
|
||||
segments_collector.reduce(memory, segments);
|
||||
}
|
||||
inverted_indices_to_segments(this->segment(segments_num - 1), memory, segments);
|
||||
}
|
||||
|
||||
if (universe.last() > this->first()) {
|
||||
range_to_segments(universe.take_back(universe.last() - this->last()), segments);
|
||||
}
|
||||
|
||||
return mask_from_segments(segments, memory);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
IndexMask IndexMask::from_indices(const Span<T> indices, IndexMaskMemory &memory)
|
||||
{
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* SPDX-FileCopyrightText: 2009-2010 Sony Pictures Imageworks Inc., et al. All Rights Reserved (BSD-3-Clause).
|
||||
* SPDX-FileCopyrightText: 2011 Blender Foundation (GPL-2.0-or-later).
|
||||
/* SPDX-FileCopyrightText: 2009-2010 Sony Pictures Imageworks Inc., et al. All Rights Reserved
|
||||
* (BSD-3-Clause). SPDX-FileCopyrightText: 2011 Blender Foundation (GPL-2.0-or-later).
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later AND BSD-3-Clause */
|
||||
|
||||
|
|
|
@ -225,4 +225,63 @@ TEST(index_mask, FromPredicateFuzzy)
|
|||
});
|
||||
}
|
||||
|
||||
TEST(index_mask, Complement)
|
||||
{
|
||||
IndexMaskMemory memory;
|
||||
{
|
||||
const IndexMask mask(0);
|
||||
const IndexMask complement = mask.complement(IndexRange(100), memory);
|
||||
EXPECT_EQ(100 - mask.size(), complement.size());
|
||||
complement.foreach_index([&](const int64_t i) { EXPECT_FALSE(mask.contains(i)); });
|
||||
mask.foreach_index([&](const int64_t i) { EXPECT_FALSE(complement.contains(i)); });
|
||||
}
|
||||
{
|
||||
const IndexMask mask(10000);
|
||||
const IndexMask complement = mask.complement(IndexRange(10000), memory);
|
||||
EXPECT_EQ(10000 - mask.size(), complement.size());
|
||||
complement.foreach_index([&](const int64_t i) { EXPECT_FALSE(mask.contains(i)); });
|
||||
mask.foreach_index([&](const int64_t i) { EXPECT_FALSE(complement.contains(i)); });
|
||||
}
|
||||
{
|
||||
const IndexMask mask(IndexRange(100, 900));
|
||||
const IndexMask complement = mask.complement(IndexRange(1000), memory);
|
||||
EXPECT_EQ(1000 - mask.size(), complement.size());
|
||||
complement.foreach_index([&](const int64_t i) { EXPECT_FALSE(mask.contains(i)); });
|
||||
mask.foreach_index([&](const int64_t i) { EXPECT_FALSE(complement.contains(i)); });
|
||||
}
|
||||
{
|
||||
const IndexMask mask(IndexRange(0, 900));
|
||||
const IndexMask complement = mask.complement(IndexRange(1000), memory);
|
||||
EXPECT_EQ(1000 - mask.size(), complement.size());
|
||||
complement.foreach_index([&](const int64_t i) { EXPECT_FALSE(mask.contains(i)); });
|
||||
mask.foreach_index([&](const int64_t i) { EXPECT_FALSE(complement.contains(i)); });
|
||||
}
|
||||
}
|
||||
|
||||
TEST(index_mask, ComplementFuzzy)
|
||||
{
|
||||
RandomNumberGenerator rng;
|
||||
|
||||
const int64_t mask_size = 100;
|
||||
const int64_t iter_num = 100;
|
||||
const int64_t universe_size = 110;
|
||||
|
||||
for (const int64_t iter : IndexRange(iter_num)) {
|
||||
Set<int> values;
|
||||
for ([[maybe_unused]] const int64_t _ : IndexRange(iter)) {
|
||||
values.add(rng.get_int32(mask_size));
|
||||
}
|
||||
IndexMaskMemory memory;
|
||||
const IndexMask mask = IndexMask::from_predicate(
|
||||
IndexRange(mask_size), GrainSize(1024), memory, [&](const int64_t i) {
|
||||
return values.contains(int(i));
|
||||
});
|
||||
|
||||
const IndexMask complement = mask.complement(IndexRange(universe_size), memory);
|
||||
EXPECT_EQ(universe_size - mask.size(), complement.size());
|
||||
complement.foreach_index([&](const int64_t i) { EXPECT_FALSE(mask.contains(i)); });
|
||||
mask.foreach_index([&](const int64_t i) { EXPECT_FALSE(complement.contains(i)); });
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blender::index_mask::tests
|
||||
|
|
|
@ -3053,7 +3053,10 @@ void blo_do_versions_280(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
MEM_callocN(sizeof(ARegion), "navigation bar for properties"));
|
||||
ARegion *region_header = nullptr;
|
||||
|
||||
LISTBASE_FOREACH (ARegion *, region_header, regionbase) {
|
||||
for (region_header = static_cast<ARegion *>(regionbase->first);
|
||||
region_header != nullptr;
|
||||
region_header = static_cast<ARegion *>(region_header->next))
|
||||
{
|
||||
if (region_header->regiontype == RGN_TYPE_HEADER) {
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -861,6 +861,7 @@ class Texture : NonCopyable {
|
|||
}
|
||||
GPU_TEXTURE_FREE_SAFE(stencil_view_);
|
||||
mip_views_.clear();
|
||||
layer_views_.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -15,6 +15,7 @@ if(WITH_BLENDER)
|
|||
add_subdirectory(geometry)
|
||||
add_subdirectory(gizmo_library)
|
||||
add_subdirectory(gpencil_legacy)
|
||||
add_subdirectory(grease_pencil)
|
||||
add_subdirectory(interface)
|
||||
add_subdirectory(io)
|
||||
add_subdirectory(lattice)
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
set(INC
|
||||
../include
|
||||
../../blenkernel
|
||||
../../blenlib
|
||||
../../blentranslation
|
||||
../../depsgraph
|
||||
../../gpu
|
||||
../../imbuf
|
||||
../../makesdna
|
||||
../../makesrna
|
||||
../../windowmanager
|
||||
../../../../intern/guardedalloc
|
||||
# RNA_prototypes.h
|
||||
${CMAKE_BINARY_DIR}/source/blender/makesrna
|
||||
)
|
||||
|
||||
set(INC_SYS
|
||||
)
|
||||
|
||||
set(SRC
|
||||
intern/grease_pencil_add.cc
|
||||
)
|
||||
|
||||
set(LIB
|
||||
bf_blenkernel
|
||||
bf_blenlib
|
||||
)
|
||||
|
||||
blender_add_lib(bf_editor_grease_pencil "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
||||
add_dependencies(bf_editor_curves bf_rna)
|
|
@ -0,0 +1,287 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
* Copyright 2023 Blender Foundation. */
|
||||
|
||||
/** \file
|
||||
* \ingroup edgreasepencil
|
||||
*/
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "BKE_curves.hh"
|
||||
#include "BKE_grease_pencil.hh"
|
||||
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_math_matrix.hh"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "DNA_material_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "ED_grease_pencil.h"
|
||||
|
||||
namespace blender::ed::greasepencil {
|
||||
|
||||
struct ColorTemplate {
|
||||
const char *name;
|
||||
float line[4];
|
||||
float fill[4];
|
||||
bool show_fill;
|
||||
};
|
||||
|
||||
static const ColorTemplate gp_stroke_material_black = {
|
||||
N_("Black"),
|
||||
{0.0f, 0.0f, 0.0f, 1.0f},
|
||||
{0.0f, 0.0f, 0.0f, 0.0f},
|
||||
false,
|
||||
};
|
||||
|
||||
static const ColorTemplate gp_stroke_material_white = {
|
||||
N_("White"),
|
||||
{1.0f, 1.0f, 1.0f, 1.0f},
|
||||
{0.0f, 0.0f, 0.0f, 0.0f},
|
||||
false,
|
||||
};
|
||||
|
||||
static const ColorTemplate gp_stroke_material_red = {
|
||||
N_("Red"),
|
||||
{1.0f, 0.0f, 0.0f, 1.0f},
|
||||
{0.0f, 0.0f, 0.0f, 0.0f},
|
||||
false,
|
||||
};
|
||||
|
||||
static const ColorTemplate gp_stroke_material_green = {
|
||||
N_("Green"),
|
||||
{0.0f, 1.0f, 0.0f, 1.0f},
|
||||
{0.0f, 0.0f, 0.0f, 0.0f},
|
||||
false,
|
||||
};
|
||||
|
||||
static const ColorTemplate gp_stroke_material_blue = {
|
||||
N_("Blue"),
|
||||
{0.0f, 0.0f, 1.0f, 1.0f},
|
||||
{0.0f, 0.0f, 0.0f, 0.0f},
|
||||
false,
|
||||
};
|
||||
|
||||
static const ColorTemplate gp_fill_material_grey = {
|
||||
N_("Grey"),
|
||||
{0.358f, 0.358f, 0.358f, 1.0f},
|
||||
{0.5f, 0.5f, 0.5f, 1.0f},
|
||||
true,
|
||||
};
|
||||
|
||||
static std::array<float3, 175> stroke_positions({
|
||||
float3(-1.281f, 0.0f, -0.315f), float3(-1.269f, 0.0f, -0.302f), float3(-1.261f, 0.0f, -0.293f),
|
||||
float3(-1.251f, 0.0f, -0.282f), float3(-1.241f, 0.0f, -0.271f), float3(-1.23f, 0.0f, -0.259f),
|
||||
float3(-1.219f, 0.0f, -0.247f), float3(-1.208f, 0.0f, -0.234f), float3(-1.196f, 0.0f, -0.221f),
|
||||
float3(-1.184f, 0.0f, -0.208f), float3(-1.172f, 0.0f, -0.194f), float3(-1.159f, 0.0f, -0.18f),
|
||||
float3(-1.147f, 0.0f, -0.165f), float3(-1.134f, 0.0f, -0.151f), float3(-1.121f, 0.0f, -0.136f),
|
||||
float3(-1.108f, 0.0f, -0.121f), float3(-1.094f, 0.0f, -0.106f), float3(-1.08f, 0.0f, -0.091f),
|
||||
float3(-1.066f, 0.0f, -0.076f), float3(-1.052f, 0.0f, -0.061f), float3(-1.037f, 0.0f, -0.047f),
|
||||
float3(-1.022f, 0.0f, -0.032f), float3(-1.007f, 0.0f, -0.017f), float3(-0.991f, 0.0f, -0.003f),
|
||||
float3(-0.975f, 0.0f, 0.012f), float3(-0.959f, 0.0f, 0.027f), float3(-0.942f, 0.0f, 0.041f),
|
||||
float3(-0.926f, 0.0f, 0.056f), float3(-0.909f, 0.0f, 0.071f), float3(-0.893f, 0.0f, 0.086f),
|
||||
float3(-0.876f, 0.0f, 0.1f), float3(-0.859f, 0.0f, 0.115f), float3(-0.842f, 0.0f, 0.129f),
|
||||
float3(-0.824f, 0.0f, 0.144f), float3(-0.807f, 0.0f, 0.158f), float3(-0.79f, 0.0f, 0.172f),
|
||||
float3(-0.773f, 0.0f, 0.186f), float3(-0.755f, 0.0f, 0.199f), float3(-0.738f, 0.0f, 0.212f),
|
||||
float3(-0.721f, 0.0f, 0.224f), float3(-0.703f, 0.0f, 0.236f), float3(-0.686f, 0.0f, 0.248f),
|
||||
float3(-0.67f, 0.0f, 0.26f), float3(-0.653f, 0.0f, 0.27f), float3(-0.637f, 0.0f, 0.28f),
|
||||
float3(-0.621f, 0.0f, 0.29f), float3(-0.605f, 0.0f, 0.298f), float3(-0.589f, 0.0f, 0.306f),
|
||||
float3(-0.574f, 0.0f, 0.313f), float3(-0.559f, 0.0f, 0.319f), float3(-0.544f, 0.0f, 0.325f),
|
||||
float3(-0.53f, 0.0f, 0.331f), float3(-0.516f, 0.0f, 0.336f), float3(-0.503f, 0.0f, 0.34f),
|
||||
float3(-0.489f, 0.0f, 0.344f), float3(-0.477f, 0.0f, 0.347f), float3(-0.464f, 0.0f, 0.35f),
|
||||
float3(-0.452f, 0.0f, 0.352f), float3(-0.44f, 0.0f, 0.354f), float3(-0.429f, 0.0f, 0.355f),
|
||||
float3(-0.418f, 0.0f, 0.355f), float3(-0.407f, 0.0f, 0.355f), float3(-0.397f, 0.0f, 0.354f),
|
||||
float3(-0.387f, 0.0f, 0.353f), float3(-0.378f, 0.0f, 0.351f), float3(-0.368f, 0.0f, 0.348f),
|
||||
float3(-0.36f, 0.0f, 0.344f), float3(-0.351f, 0.0f, 0.34f), float3(-0.344f, 0.0f, 0.336f),
|
||||
float3(-0.336f, 0.0f, 0.33f), float3(-0.329f, 0.0f, 0.324f), float3(-0.322f, 0.0f, 0.318f),
|
||||
float3(-0.316f, 0.0f, 0.31f), float3(-0.311f, 0.0f, 0.303f), float3(-0.306f, 0.0f, 0.294f),
|
||||
float3(-0.301f, 0.0f, 0.285f), float3(-0.297f, 0.0f, 0.275f), float3(-0.293f, 0.0f, 0.264f),
|
||||
float3(-0.29f, 0.0f, 0.253f), float3(-0.288f, 0.0f, 0.241f), float3(-0.286f, 0.0f, 0.229f),
|
||||
float3(-0.285f, 0.0f, 0.216f), float3(-0.284f, 0.0f, 0.202f), float3(-0.283f, 0.0f, 0.188f),
|
||||
float3(-0.283f, 0.0f, 0.173f), float3(-0.284f, 0.0f, 0.158f), float3(-0.285f, 0.0f, 0.142f),
|
||||
float3(-0.286f, 0.0f, 0.125f), float3(-0.288f, 0.0f, 0.108f), float3(-0.29f, 0.0f, 0.091f),
|
||||
float3(-0.293f, 0.0f, 0.073f), float3(-0.295f, 0.0f, 0.054f), float3(-0.298f, 0.0f, 0.035f),
|
||||
float3(-0.302f, 0.0f, 0.016f), float3(-0.305f, 0.0f, -0.004f), float3(-0.309f, 0.0f, -0.024f),
|
||||
float3(-0.313f, 0.0f, -0.044f), float3(-0.317f, 0.0f, -0.065f), float3(-0.321f, 0.0f, -0.085f),
|
||||
float3(-0.326f, 0.0f, -0.106f), float3(-0.33f, 0.0f, -0.127f), float3(-0.335f, 0.0f, -0.148f),
|
||||
float3(-0.339f, 0.0f, -0.168f), float3(-0.344f, 0.0f, -0.189f), float3(-0.348f, 0.0f, -0.21f),
|
||||
float3(-0.353f, 0.0f, -0.23f), float3(-0.357f, 0.0f, -0.25f), float3(-0.361f, 0.0f, -0.27f),
|
||||
float3(-0.365f, 0.0f, -0.29f), float3(-0.369f, 0.0f, -0.309f), float3(-0.372f, 0.0f, -0.328f),
|
||||
float3(-0.375f, 0.0f, -0.347f), float3(-0.377f, 0.0f, -0.365f), float3(-0.379f, 0.0f, -0.383f),
|
||||
float3(-0.38f, 0.0f, -0.4f), float3(-0.38f, 0.0f, -0.417f), float3(-0.38f, 0.0f, -0.434f),
|
||||
float3(-0.379f, 0.0f, -0.449f), float3(-0.377f, 0.0f, -0.464f), float3(-0.374f, 0.0f, -0.478f),
|
||||
float3(-0.371f, 0.0f, -0.491f), float3(-0.366f, 0.0f, -0.503f), float3(-0.361f, 0.0f, -0.513f),
|
||||
float3(-0.354f, 0.0f, -0.523f), float3(-0.347f, 0.0f, -0.531f), float3(-0.339f, 0.0f, -0.538f),
|
||||
float3(-0.33f, 0.0f, -0.543f), float3(-0.32f, 0.0f, -0.547f), float3(-0.31f, 0.0f, -0.549f),
|
||||
float3(-0.298f, 0.0f, -0.55f), float3(-0.286f, 0.0f, -0.55f), float3(-0.274f, 0.0f, -0.548f),
|
||||
float3(-0.261f, 0.0f, -0.544f), float3(-0.247f, 0.0f, -0.539f), float3(-0.232f, 0.0f, -0.533f),
|
||||
float3(-0.218f, 0.0f, -0.525f), float3(-0.202f, 0.0f, -0.515f), float3(-0.186f, 0.0f, -0.503f),
|
||||
float3(-0.169f, 0.0f, -0.49f), float3(-0.151f, 0.0f, -0.475f), float3(-0.132f, 0.0f, -0.458f),
|
||||
float3(-0.112f, 0.0f, -0.44f), float3(-0.091f, 0.0f, -0.42f), float3(-0.069f, 0.0f, -0.398f),
|
||||
float3(-0.045f, 0.0f, -0.375f), float3(-0.021f, 0.0f, -0.35f), float3(0.005f, 0.0f, -0.324f),
|
||||
float3(0.031f, 0.0f, -0.297f), float3(0.06f, 0.0f, -0.268f), float3(0.089f, 0.0f, -0.238f),
|
||||
float3(0.12f, 0.0f, -0.207f), float3(0.153f, 0.0f, -0.175f), float3(0.187f, 0.0f, -0.14f),
|
||||
float3(0.224f, 0.0f, -0.104f), float3(0.262f, 0.0f, -0.067f), float3(0.302f, 0.0f, -0.027f),
|
||||
float3(0.344f, 0.0f, 0.014f), float3(0.388f, 0.0f, 0.056f), float3(0.434f, 0.0f, 0.1f),
|
||||
float3(0.483f, 0.0f, 0.145f), float3(0.533f, 0.0f, 0.191f), float3(0.585f, 0.0f, 0.238f),
|
||||
float3(0.637f, 0.0f, 0.284f), float3(0.69f, 0.0f, 0.33f), float3(0.746f, 0.0f, 0.376f),
|
||||
float3(0.802f, 0.0f, 0.421f), float3(0.859f, 0.0f, 0.464f), float3(0.915f, 0.0f, 0.506f),
|
||||
float3(0.97f, 0.0f, 0.545f), float3(1.023f, 0.0f, 0.581f), float3(1.075f, 0.0f, 0.614f),
|
||||
float3(1.122f, 0.0f, 0.643f), float3(1.169f, 0.0f, 0.671f), float3(1.207f, 0.0f, 0.693f),
|
||||
float3(1.264f, 0.0f, 0.725f),
|
||||
});
|
||||
|
||||
static constexpr std::array<float, 175> stroke_radii({
|
||||
0.038f, 0.069f, 0.089f, 0.112f, 0.134f, 0.155f, 0.175f, 0.194f, 0.211f, 0.227f, 0.242f, 0.256f,
|
||||
0.268f, 0.28f, 0.29f, 0.299f, 0.307f, 0.315f, 0.322f, 0.329f, 0.335f, 0.341f, 0.346f, 0.351f,
|
||||
0.355f, 0.36f, 0.364f, 0.368f, 0.371f, 0.373f, 0.376f, 0.377f, 0.378f, 0.379f, 0.379f, 0.379f,
|
||||
0.38f, 0.38f, 0.381f, 0.382f, 0.384f, 0.386f, 0.388f, 0.39f, 0.393f, 0.396f, 0.399f, 0.403f,
|
||||
0.407f, 0.411f, 0.415f, 0.42f, 0.425f, 0.431f, 0.437f, 0.443f, 0.45f, 0.457f, 0.464f, 0.471f,
|
||||
0.479f, 0.487f, 0.495f, 0.503f, 0.512f, 0.52f, 0.528f, 0.537f, 0.545f, 0.553f, 0.562f, 0.57f,
|
||||
0.579f, 0.588f, 0.597f, 0.606f, 0.615f, 0.625f, 0.635f, 0.644f, 0.654f, 0.664f, 0.675f, 0.685f,
|
||||
0.696f, 0.707f, 0.718f, 0.729f, 0.74f, 0.751f, 0.761f, 0.772f, 0.782f, 0.793f, 0.804f, 0.815f,
|
||||
0.828f, 0.843f, 0.86f, 0.879f, 0.897f, 0.915f, 0.932f, 0.947f, 0.962f, 0.974f, 0.985f, 0.995f,
|
||||
1.004f, 1.011f, 1.018f, 1.024f, 1.029f, 1.033f, 1.036f, 1.037f, 1.037f, 1.035f, 1.032f, 1.029f,
|
||||
1.026f, 1.023f, 1.021f, 1.019f, 1.017f, 1.016f, 1.016f, 1.016f, 1.016f, 1.017f, 1.017f, 1.018f,
|
||||
1.017f, 1.017f, 1.016f, 1.015f, 1.013f, 1.009f, 1.005f, 0.998f, 0.99f, 0.98f, 0.968f, 0.955f,
|
||||
0.939f, 0.923f, 0.908f, 0.895f, 0.882f, 0.87f, 0.858f, 0.844f, 0.828f, 0.81f, 0.79f, 0.769f,
|
||||
0.747f, 0.724f, 0.7f, 0.676f, 0.651f, 0.625f, 0.599f, 0.573f, 0.546f, 0.516f, 0.483f, 0.446f,
|
||||
0.407f, 0.365f, 0.322f, 0.28f, 0.236f, 0.202f, 0.155f,
|
||||
});
|
||||
|
||||
static constexpr std::array<float, 175> stroke_opacities({
|
||||
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
|
||||
});
|
||||
|
||||
static int add_material_from_template(Main &bmain, Object &ob, const ColorTemplate &pct)
|
||||
{
|
||||
int index;
|
||||
Material *ma = BKE_grease_pencil_object_material_ensure_by_name(
|
||||
&bmain, &ob, DATA_(pct.name), &index);
|
||||
|
||||
copy_v4_v4(ma->gp_style->stroke_rgba, pct.line);
|
||||
srgb_to_linearrgb_v4(ma->gp_style->stroke_rgba, ma->gp_style->stroke_rgba);
|
||||
|
||||
copy_v4_v4(ma->gp_style->fill_rgba, pct.fill);
|
||||
srgb_to_linearrgb_v4(ma->gp_style->fill_rgba, ma->gp_style->fill_rgba);
|
||||
|
||||
if (pct.show_fill) {
|
||||
ma->gp_style->flag |= GP_MATERIAL_FILL_SHOW;
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
static bke::CurvesGeometry create_drawing_data(const Span<float3> positions,
|
||||
const Span<float> radii,
|
||||
const Span<float> opacities,
|
||||
const Span<int> offsets,
|
||||
const Span<int> materials,
|
||||
const Span<int> radii_factor,
|
||||
const float4x4 &matrix)
|
||||
{
|
||||
using namespace blender::bke;
|
||||
CurvesGeometry curves(offsets.last(), offsets.size() - 1);
|
||||
curves.offsets_for_write().copy_from(offsets);
|
||||
|
||||
curves.fill_curve_types(CURVE_TYPE_POLY);
|
||||
|
||||
MutableAttributeAccessor attributes = curves.attributes_for_write();
|
||||
MutableSpan<float3> point_positions = curves.positions_for_write();
|
||||
point_positions.copy_from(positions);
|
||||
|
||||
SpanAttributeWriter<float> point_radii = attributes.lookup_or_add_for_write_only_span<float>(
|
||||
"radius", ATTR_DOMAIN_POINT);
|
||||
point_radii.span.copy_from(radii);
|
||||
|
||||
SpanAttributeWriter<float> point_opacities = attributes.lookup_or_add_for_write_span<float>(
|
||||
"opacity", ATTR_DOMAIN_POINT);
|
||||
point_opacities.span.copy_from(opacities);
|
||||
|
||||
SpanAttributeWriter<bool> stroke_cyclic = attributes.lookup_or_add_for_write_span<bool>(
|
||||
"cyclic", ATTR_DOMAIN_CURVE);
|
||||
stroke_cyclic.span.fill(false);
|
||||
|
||||
SpanAttributeWriter<int> stroke_materials = attributes.lookup_or_add_for_write_span<int>(
|
||||
"material_index", ATTR_DOMAIN_CURVE);
|
||||
stroke_materials.span.copy_from(materials);
|
||||
|
||||
const OffsetIndices points_by_curve = curves.points_by_curve();
|
||||
for (const int curve_i : curves.curves_range()) {
|
||||
const IndexRange points = points_by_curve[curve_i];
|
||||
for (const int point_i : points) {
|
||||
point_positions[point_i] = math::transform_point(matrix, point_positions[point_i]);
|
||||
point_radii.span[point_i] *= radii_factor[curve_i];
|
||||
}
|
||||
}
|
||||
|
||||
point_radii.finish();
|
||||
point_opacities.finish();
|
||||
|
||||
stroke_cyclic.finish();
|
||||
stroke_materials.finish();
|
||||
|
||||
return curves;
|
||||
}
|
||||
|
||||
void create_blank(Main &bmain, Object &object, const int frame_numer)
|
||||
{
|
||||
using namespace blender::bke::greasepencil;
|
||||
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object.data);
|
||||
|
||||
int material_index = add_material_from_template(bmain, object, gp_stroke_material_black);
|
||||
object.actcol = material_index + 1;
|
||||
|
||||
Layer &new_layer = grease_pencil.add_layer(grease_pencil.root_group.wrap(), "GP_Layer");
|
||||
grease_pencil.active_layer = &new_layer;
|
||||
|
||||
grease_pencil.add_empty_drawings(1);
|
||||
|
||||
GreasePencilFrame frame{0, 0, BEZT_KEYTYPE_KEYFRAME};
|
||||
new_layer.insert_frame(frame_numer, frame);
|
||||
}
|
||||
|
||||
void create_stroke(Main &bmain, Object &object, float4x4 matrix, const int frame_numer)
|
||||
{
|
||||
using namespace blender::bke::greasepencil;
|
||||
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object.data);
|
||||
|
||||
int material_index = add_material_from_template(bmain, object, gp_stroke_material_black);
|
||||
add_material_from_template(bmain, object, gp_stroke_material_black);
|
||||
add_material_from_template(bmain, object, gp_stroke_material_white);
|
||||
add_material_from_template(bmain, object, gp_stroke_material_red);
|
||||
add_material_from_template(bmain, object, gp_stroke_material_green);
|
||||
add_material_from_template(bmain, object, gp_stroke_material_blue);
|
||||
add_material_from_template(bmain, object, gp_fill_material_grey);
|
||||
object.actcol = material_index + 1;
|
||||
|
||||
Layer &layer_lines = grease_pencil.add_layer(grease_pencil.root_group.wrap(), "Lines");
|
||||
Layer &layer_color = grease_pencil.add_layer(grease_pencil.root_group.wrap(), "Color");
|
||||
grease_pencil.active_layer = &layer_lines;
|
||||
|
||||
grease_pencil.add_empty_drawings(2);
|
||||
|
||||
GreasePencilDrawing &drawing = *reinterpret_cast<GreasePencilDrawing *>(
|
||||
grease_pencil.drawings_for_write()[1]);
|
||||
drawing.geometry.wrap() = create_drawing_data(
|
||||
stroke_positions, stroke_radii, stroke_opacities, {0, 175}, {material_index}, {75}, matrix);
|
||||
|
||||
GreasePencilFrame frame_lines{0, 0, BEZT_KEYTYPE_KEYFRAME};
|
||||
GreasePencilFrame frame_color{1, 0, BEZT_KEYTYPE_KEYFRAME};
|
||||
layer_lines.insert_frame(frame_numer, frame_lines);
|
||||
layer_color.insert_frame(frame_numer, frame_color);
|
||||
}
|
||||
|
||||
} // namespace blender::ed::greasepencil
|
|
@ -0,0 +1,29 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
* Copyright 2023 Blender Foundation. */
|
||||
|
||||
/** \file
|
||||
* \ingroup editors
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
struct Main;
|
||||
struct Object;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
namespace blender::ed::greasepencil {
|
||||
|
||||
void create_blank(Main &bmain, Object &object, int frame_numer);
|
||||
void create_stroke(Main &bmain, Object &object, float4x4 matrix, int frame_numer);
|
||||
|
||||
} // namespace blender::ed::greasepencil
|
||||
#endif
|
|
@ -70,6 +70,7 @@ set(LIB
|
|||
bf_blenkernel
|
||||
bf_blenlib
|
||||
bf_editor_mesh
|
||||
bf_editor_grease_pencil
|
||||
bf_render
|
||||
bf_windowmanager
|
||||
)
|
||||
|
|
|
@ -105,6 +105,7 @@
|
|||
#include "ED_curve.h"
|
||||
#include "ED_curves.h"
|
||||
#include "ED_gpencil_legacy.h"
|
||||
#include "ED_grease_pencil.h"
|
||||
#include "ED_mball.h"
|
||||
#include "ED_mesh.h"
|
||||
#include "ED_node.h"
|
||||
|
@ -1306,7 +1307,7 @@ void OBJECT_OT_drop_named_image(wmOperatorType *ot)
|
|||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Add Gpencil Operator
|
||||
/** \name Add Gpencil (legacy) Operator
|
||||
* \{ */
|
||||
|
||||
static bool object_gpencil_add_poll(bContext *C)
|
||||
|
@ -1529,8 +1530,8 @@ static EnumPropertyItem rna_enum_gpencil_add_stroke_depth_order_items[] = {
|
|||
void OBJECT_OT_gpencil_add(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Add Grease Pencil";
|
||||
ot->description = "Add a Grease Pencil object to the scene";
|
||||
ot->name = "Add Grease Pencil (legacy)";
|
||||
ot->description = "Add a Grease Pencil (legacy) object to the scene";
|
||||
ot->idname = "OBJECT_OT_gpencil_add";
|
||||
|
||||
/* api callbacks */
|
||||
|
@ -1576,6 +1577,109 @@ void OBJECT_OT_gpencil_add(wmOperatorType *ot)
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Add Grease Pencil Operator
|
||||
* \{ */
|
||||
|
||||
static int object_grease_pencil_add_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
using namespace blender::ed;
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
/* TODO: For now, only support adding the 'Stroke' type. */
|
||||
const int type = RNA_enum_get(op->ptr, "type");
|
||||
|
||||
ushort local_view_bits;
|
||||
float loc[3], rot[3];
|
||||
|
||||
/* NOTE: We use 'Y' here (not 'Z'), as. */
|
||||
WM_operator_view3d_unit_defaults(C, op);
|
||||
if (!ED_object_add_generic_get_opts(
|
||||
C, op, 'Y', loc, rot, nullptr, nullptr, &local_view_bits, nullptr))
|
||||
{
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
const char *ob_name = nullptr;
|
||||
switch (type) {
|
||||
case GP_EMPTY: {
|
||||
ob_name = CTX_DATA_(BLT_I18NCONTEXT_ID_GPENCIL, "GPencil");
|
||||
break;
|
||||
}
|
||||
case GP_STROKE: {
|
||||
ob_name = CTX_DATA_(BLT_I18NCONTEXT_ID_GPENCIL, "Stroke");
|
||||
break;
|
||||
}
|
||||
case GP_MONKEY: {
|
||||
ob_name = CTX_DATA_(BLT_I18NCONTEXT_ID_GPENCIL, "Suzanne");
|
||||
break;
|
||||
}
|
||||
case GP_LRT_OBJECT:
|
||||
case GP_LRT_SCENE:
|
||||
case GP_LRT_COLLECTION: {
|
||||
ob_name = CTX_DATA_(BLT_I18NCONTEXT_ID_GPENCIL, "LineArt");
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Object *object = ED_object_add_type(
|
||||
C, OB_GREASE_PENCIL, ob_name, loc, rot, false, local_view_bits);
|
||||
GreasePencil &grease_pencil_id = *static_cast<GreasePencil *>(object->data);
|
||||
switch (type) {
|
||||
case GP_EMPTY: {
|
||||
greasepencil::create_blank(*bmain, *object, scene->r.cfra);
|
||||
break;
|
||||
}
|
||||
case GP_STROKE: {
|
||||
const float radius = RNA_float_get(op->ptr, "radius");
|
||||
const float3 scale(radius);
|
||||
|
||||
float4x4 mat;
|
||||
ED_object_new_primitive_matrix(C, object, loc, rot, scale, mat.ptr());
|
||||
|
||||
greasepencil::create_stroke(*bmain, *object, mat, scene->r.cfra);
|
||||
break;
|
||||
}
|
||||
case GP_MONKEY:
|
||||
case GP_LRT_OBJECT:
|
||||
case GP_LRT_SCENE:
|
||||
case GP_LRT_COLLECTION: {
|
||||
/* TODO. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DEG_id_tag_update(&grease_pencil_id.id, ID_RECALC_GEOMETRY);
|
||||
WM_main_add_notifier(NC_GEOM | ND_DATA, &grease_pencil_id.id);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void OBJECT_OT_grease_pencil_add(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Add Grease Pencil";
|
||||
ot->description = "Add a Grease Pencil object to the scene";
|
||||
ot->idname = "OBJECT_OT_grease_pencil_add";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = object_grease_pencil_add_exec;
|
||||
ot->poll = ED_operator_objectmode;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_object_gpencil_type_items, 0, "Type", "");
|
||||
|
||||
ED_object_add_unit_props_radius(ot);
|
||||
ED_object_add_generic_props(ot, false);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Add Light Operator
|
||||
* \{ */
|
||||
|
|
|
@ -119,6 +119,7 @@ void OBJECT_OT_empty_add(struct wmOperatorType *ot);
|
|||
void OBJECT_OT_lightprobe_add(struct wmOperatorType *ot);
|
||||
void OBJECT_OT_drop_named_image(struct wmOperatorType *ot);
|
||||
void OBJECT_OT_gpencil_add(struct wmOperatorType *ot);
|
||||
void OBJECT_OT_grease_pencil_add(struct wmOperatorType *ot);
|
||||
void OBJECT_OT_light_add(struct wmOperatorType *ot);
|
||||
void OBJECT_OT_effector_add(struct wmOperatorType *ot);
|
||||
void OBJECT_OT_camera_add(struct wmOperatorType *ot);
|
||||
|
|
|
@ -90,6 +90,7 @@ void ED_operatortypes_object(void)
|
|||
WM_operatortype_append(OBJECT_OT_lightprobe_add);
|
||||
WM_operatortype_append(OBJECT_OT_drop_named_image);
|
||||
WM_operatortype_append(OBJECT_OT_gpencil_add);
|
||||
WM_operatortype_append(OBJECT_OT_grease_pencil_add);
|
||||
WM_operatortype_append(OBJECT_OT_light_add);
|
||||
WM_operatortype_append(OBJECT_OT_camera_add);
|
||||
WM_operatortype_append(OBJECT_OT_speaker_add);
|
||||
|
|
|
@ -58,6 +58,7 @@ set(SRC
|
|||
tree/tree_element_gpencil_layer.cc
|
||||
tree/tree_element_id.cc
|
||||
tree/tree_element_id_library.cc
|
||||
tree/tree_element_id_mesh.cc
|
||||
tree/tree_element_id_scene.cc
|
||||
tree/tree_element_label.cc
|
||||
tree/tree_element_nla.cc
|
||||
|
@ -78,6 +79,7 @@ set(SRC
|
|||
tree/tree_element_gpencil_layer.hh
|
||||
tree/tree_element_id.hh
|
||||
tree/tree_element_id_library.hh
|
||||
tree/tree_element_id_mesh.hh
|
||||
tree/tree_element_id_scene.hh
|
||||
tree/tree_element_label.hh
|
||||
tree/tree_element_nla.hh
|
||||
|
|
|
@ -551,27 +551,13 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner,
|
|||
switch (GS(id->name)) {
|
||||
case ID_LI:
|
||||
case ID_SCE:
|
||||
case ID_ME:
|
||||
BLI_assert_msg(0, "ID type expected to be expanded through new tree-element design");
|
||||
break;
|
||||
case ID_OB: {
|
||||
outliner_add_object_contents(space_outliner, te, tselem, (Object *)id);
|
||||
break;
|
||||
}
|
||||
case ID_ME: {
|
||||
Mesh *me = (Mesh *)id;
|
||||
|
||||
if (outliner_animdata_test(me->adt)) {
|
||||
outliner_add_element(space_outliner, &te->subtree, me, te, TSE_ANIM_DATA, 0);
|
||||
}
|
||||
|
||||
outliner_add_element(space_outliner, &te->subtree, me->key, te, TSE_SOME_ID, 0);
|
||||
for (int a = 0; a < me->totcol; a++) {
|
||||
outliner_add_element(space_outliner, &te->subtree, me->mat[a], te, TSE_SOME_ID, a);
|
||||
}
|
||||
/* could do tfaces with image links, but the images are not grouped nicely.
|
||||
* would require going over all tfaces, sort images in use. etc... */
|
||||
break;
|
||||
}
|
||||
case ID_CU_LEGACY: {
|
||||
Curve *cu = (Curve *)id;
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "../outliner_intern.hh"
|
||||
#include "common.hh"
|
||||
#include "tree_element_id_library.hh"
|
||||
#include "tree_element_id_mesh.hh"
|
||||
#include "tree_element_id_scene.hh"
|
||||
|
||||
#include "tree_element_id.hh"
|
||||
|
@ -39,8 +40,9 @@ std::unique_ptr<TreeElementID> TreeElementID::createFromID(TreeElement &legacy_t
|
|||
return std::make_unique<TreeElementIDLibrary>(legacy_te, (Library &)id);
|
||||
case ID_SCE:
|
||||
return std::make_unique<TreeElementIDScene>(legacy_te, (Scene &)id);
|
||||
case ID_OB:
|
||||
case ID_ME:
|
||||
return std::make_unique<TreeElementIDMesh>(legacy_te, (Mesh &)id);
|
||||
case ID_OB:
|
||||
case ID_CU_LEGACY:
|
||||
case ID_MB:
|
||||
case ID_MA:
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup spoutliner
|
||||
*/
|
||||
|
||||
#include "DNA_listBase.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_outliner_types.h"
|
||||
|
||||
#include "../outliner_intern.hh"
|
||||
|
||||
#include "tree_element_id_mesh.hh"
|
||||
|
||||
namespace blender::ed::outliner {
|
||||
|
||||
TreeElementIDMesh::TreeElementIDMesh(TreeElement &legacy_te_, Mesh &mesh)
|
||||
: TreeElementID(legacy_te_, mesh.id), mesh_(mesh)
|
||||
{
|
||||
}
|
||||
|
||||
bool TreeElementIDMesh::isExpandValid() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void TreeElementIDMesh::expand(SpaceOutliner &space_outliner) const
|
||||
{
|
||||
expand_animation_data(space_outliner, mesh_.adt);
|
||||
|
||||
expandKey(space_outliner);
|
||||
expandMaterials(space_outliner);
|
||||
}
|
||||
|
||||
void TreeElementIDMesh::expandKey(SpaceOutliner &space_outliner) const
|
||||
{
|
||||
outliner_add_element(
|
||||
&space_outliner, &legacy_te_.subtree, mesh_.key, &legacy_te_, TSE_SOME_ID, 0);
|
||||
}
|
||||
|
||||
void TreeElementIDMesh::expandMaterials(SpaceOutliner &space_outliner) const
|
||||
{
|
||||
for (int a = 0; a < mesh_.totcol; a++) {
|
||||
outliner_add_element(
|
||||
&space_outliner, &legacy_te_.subtree, mesh_.mat[a], &legacy_te_, TSE_SOME_ID, a);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blender::ed::outliner
|
|
@ -0,0 +1,27 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup spoutliner
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "tree_element_id.hh"
|
||||
|
||||
namespace blender::ed::outliner {
|
||||
|
||||
class TreeElementIDMesh final : public TreeElementID {
|
||||
Mesh &mesh_;
|
||||
|
||||
public:
|
||||
TreeElementIDMesh(TreeElement &legacy_te_, Mesh &mesh);
|
||||
|
||||
void expand(SpaceOutliner &) const override;
|
||||
bool isExpandValid() const override;
|
||||
|
||||
private:
|
||||
void expandKey(SpaceOutliner &) const;
|
||||
void expandMaterials(SpaceOutliner &) const;
|
||||
};
|
||||
|
||||
} // namespace blender::ed::outliner
|
|
@ -57,6 +57,7 @@
|
|||
#include "PIL_time.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
#include "UI_view2d.h"
|
||||
|
||||
#include "ED_image.h"
|
||||
|
@ -1190,7 +1191,7 @@ static void uvedit_pack_islands_multi(const Scene *scene,
|
|||
|
||||
bool only_selected_faces = params->only_selected_faces;
|
||||
bool only_selected_uvs = params->only_selected_uvs;
|
||||
const bool ignore_pinned = params->pin_method == ED_UVPACK_PIN_IGNORED;
|
||||
const bool ignore_pinned = params->pin_method == ED_UVPACK_PIN_IGNORE;
|
||||
if (ignore_pinned && params->pin_unselected) {
|
||||
only_selected_faces = false;
|
||||
only_selected_uvs = false;
|
||||
|
@ -1502,11 +1503,17 @@ static int pack_islands_exec(bContext *C, wmOperator *op)
|
|||
}
|
||||
|
||||
pack_island_params.setFromUnwrapOptions(options);
|
||||
pack_island_params.rotate_method = eUVPackIsland_RotationMethod(
|
||||
RNA_enum_get(op->ptr, "rotate_method"));
|
||||
if (RNA_boolean_get(op->ptr, "rotate")) {
|
||||
pack_island_params.rotate_method = eUVPackIsland_RotationMethod(
|
||||
RNA_enum_get(op->ptr, "rotate_method"));
|
||||
}
|
||||
else {
|
||||
pack_island_params.rotate_method = ED_UVPACK_ROTATION_NONE;
|
||||
}
|
||||
pack_island_params.scale_to_fit = RNA_boolean_get(op->ptr, "scale");
|
||||
pack_island_params.merge_overlap = RNA_boolean_get(op->ptr, "merge_overlap");
|
||||
pack_island_params.pin_method = eUVPackIsland_PinMethod(RNA_enum_get(op->ptr, "pin_method"));
|
||||
pack_island_params.pin_method = eUVPackIsland_PinMethod(RNA_enum_get(op->ptr, "pin"));
|
||||
|
||||
pack_island_params.margin_method = eUVPackIsland_MarginMethod(
|
||||
RNA_enum_get(op->ptr, "margin_method"));
|
||||
pack_island_params.margin = RNA_float_get(op->ptr, "margin");
|
||||
|
@ -1562,7 +1569,6 @@ static const EnumPropertyItem pack_margin_method_items[] = {
|
|||
};
|
||||
|
||||
static const EnumPropertyItem pack_rotate_method_items[] = {
|
||||
{ED_UVPACK_ROTATION_NONE, "NONE", 0, "No rotation", "No rotation is applied to the islands"},
|
||||
RNA_ENUM_ITEM_SEPR,
|
||||
{ED_UVPACK_ROTATION_AXIS_ALIGNED,
|
||||
"AXIS_ALIGNED",
|
||||
|
@ -1579,27 +1585,48 @@ static const EnumPropertyItem pack_rotate_method_items[] = {
|
|||
};
|
||||
|
||||
static const EnumPropertyItem pack_shape_method_items[] = {
|
||||
{ED_UVPACK_SHAPE_CONCAVE, "CONCAVE", 0, "Exact shape (Concave)", "Uses exact geometry"},
|
||||
{ED_UVPACK_SHAPE_CONVEX, "CONVEX", 0, "Boundary shape (Convex)", "Uses convex hull"},
|
||||
{ED_UVPACK_SHAPE_CONCAVE, "CONCAVE", 0, "Exact Shape (Concave)", "Uses exact geometry"},
|
||||
{ED_UVPACK_SHAPE_CONVEX, "CONVEX", 0, "Boundary Shape (Convex)", "Uses convex hull"},
|
||||
RNA_ENUM_ITEM_SEPR,
|
||||
{ED_UVPACK_SHAPE_AABB, "AABB", 0, "Bounding box", "Uses bounding boxes"},
|
||||
{ED_UVPACK_SHAPE_AABB, "AABB", 0, "Bounding Box", "Uses bounding boxes"},
|
||||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
|
||||
static const EnumPropertyItem pinned_islands_method_items[] = {
|
||||
{ED_UVPACK_PIN_DEFAULT, "DEFAULT", 0, "Default", "Pin information is not used"},
|
||||
{ED_UVPACK_PIN_IGNORED, "IGNORED", 0, "Ignored", "Pinned islands are not packed"},
|
||||
{ED_UVPACK_PIN_LOCK_SCALE, "SCALE", 0, "Locked scale", "Pinned islands won't rescale"},
|
||||
{ED_UVPACK_PIN_LOCK_ROTATION, "ROTATION", 0, "Locked rotation", "Pinned islands won't rotate"},
|
||||
{ED_UVPACK_PIN_PACK, "PACK", 0, "Pack", "Pinned islands are packed normally"},
|
||||
{ED_UVPACK_PIN_LOCK_SCALE, "SCALE", 0, "Lock Scale", "Pinned islands won't rescale"},
|
||||
{ED_UVPACK_PIN_LOCK_ROTATION, "ROTATION", 0, "Lock Rotation", "Pinned islands won't rotate"},
|
||||
{ED_UVPACK_PIN_LOCK_ROTATION_SCALE,
|
||||
"ROTATION_SCALE",
|
||||
0,
|
||||
"Locked rotation and scale",
|
||||
"Lock Rotation and Scale",
|
||||
"Pinned islands will translate only"},
|
||||
{ED_UVPACK_PIN_LOCK_ALL, "LOCKED", 0, "Locked position", "Pinned islands are locked in place"},
|
||||
{ED_UVPACK_PIN_LOCK_ALL, "LOCKED", 0, "Lock in Place", "Pinned islands are locked in place"},
|
||||
{ED_UVPACK_PIN_IGNORE, "IGNORE", 0, "Ignore", "Pinned islands are not packed"},
|
||||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
|
||||
static void uv_pack_islands_ui(bContext * /*C*/, wmOperator *op)
|
||||
{
|
||||
uiLayout *layout = op->layout;
|
||||
uiLayoutSetPropSep(layout, true);
|
||||
uiLayoutSetPropDecorate(layout, false);
|
||||
uiItemR(layout, op->ptr, "shape_method", 0, nullptr, ICON_NONE);
|
||||
uiItemR(layout, op->ptr, "scale", 0, nullptr, ICON_NONE);
|
||||
uiItemR(layout, op->ptr, "rotate", 0, nullptr, ICON_NONE);
|
||||
uiLayout *sub = uiLayoutRow(layout, true);
|
||||
uiLayoutSetActive(sub, RNA_boolean_get(op->ptr, "rotate"));
|
||||
uiItemR(sub, op->ptr, "rotate_method", 0, nullptr, ICON_NONE);
|
||||
uiItemS(layout);
|
||||
uiItemR(layout, op->ptr, "margin_method", 0, nullptr, ICON_NONE);
|
||||
uiItemR(layout, op->ptr, "margin", 0, nullptr, ICON_NONE);
|
||||
uiItemS(layout);
|
||||
uiItemR(layout, op->ptr, "pin", 0, nullptr, ICON_NONE);
|
||||
uiItemR(layout, op->ptr, "merge_overlap", 0, nullptr, ICON_NONE);
|
||||
uiItemR(layout, op->ptr, "udim_source", 0, nullptr, ICON_NONE);
|
||||
uiItemS(layout);
|
||||
}
|
||||
|
||||
void UV_OT_pack_islands(wmOperatorType *ot)
|
||||
{
|
||||
static const EnumPropertyItem pack_target[] = {
|
||||
|
@ -1637,10 +1664,12 @@ void UV_OT_pack_islands(wmOperatorType *ot)
|
|||
#else
|
||||
ot->invoke = WM_operator_props_popup_confirm;
|
||||
#endif
|
||||
ot->ui = uv_pack_islands_ui;
|
||||
ot->poll = ED_operator_uvedit;
|
||||
|
||||
/* properties */
|
||||
RNA_def_enum(ot->srna, "udim_source", pack_target, PACK_UDIM_SRC_CLOSEST, "Pack to", "");
|
||||
RNA_def_boolean(ot->srna, "rotate", true, "Rotate", "Rotate islands to improve layout");
|
||||
RNA_def_enum(ot->srna,
|
||||
"rotate_method",
|
||||
pack_rotate_method_items,
|
||||
|
@ -1649,7 +1678,7 @@ void UV_OT_pack_islands(wmOperatorType *ot)
|
|||
"");
|
||||
RNA_def_boolean(ot->srna, "scale", true, "Scale", "Scale islands to fill unit square");
|
||||
RNA_def_boolean(
|
||||
ot->srna, "merge_overlap", false, "Merge Overlapped", "Overlapping islands stick together");
|
||||
ot->srna, "merge_overlap", false, "Merge Overlapping", "Overlapping islands stick together");
|
||||
RNA_def_enum(ot->srna,
|
||||
"margin_method",
|
||||
pack_margin_method_items,
|
||||
|
@ -1658,12 +1687,8 @@ void UV_OT_pack_islands(wmOperatorType *ot)
|
|||
"");
|
||||
RNA_def_float_factor(
|
||||
ot->srna, "margin", 0.001f, 0.0f, 1.0f, "Margin", "Space between islands", 0.0f, 1.0f);
|
||||
RNA_def_enum(ot->srna,
|
||||
"pin_method",
|
||||
pinned_islands_method_items,
|
||||
ED_UVPACK_PIN_DEFAULT,
|
||||
"Pinned Islands",
|
||||
"");
|
||||
RNA_def_enum(
|
||||
ot->srna, "pin", pinned_islands_method_items, ED_UVPACK_PIN_PACK, "Pinned Islands", "");
|
||||
RNA_def_enum(ot->srna,
|
||||
"shape_method",
|
||||
pack_shape_method_items,
|
||||
|
@ -2385,7 +2410,7 @@ void ED_uvedit_live_unwrap(const Scene *scene, Object **objects, int objects_len
|
|||
blender::geometry::UVPackIsland_Params pack_island_params;
|
||||
pack_island_params.setFromUnwrapOptions(options);
|
||||
pack_island_params.rotate_method = ED_UVPACK_ROTATION_ANY;
|
||||
pack_island_params.pin_method = ED_UVPACK_PIN_IGNORED;
|
||||
pack_island_params.pin_method = ED_UVPACK_PIN_IGNORE;
|
||||
pack_island_params.margin_method = ED_UVPACK_MARGIN_SCALED;
|
||||
pack_island_params.margin = scene->toolsettings->uvcalc_margin;
|
||||
|
||||
|
@ -2527,7 +2552,7 @@ static int unwrap_exec(bContext *C, wmOperator *op)
|
|||
blender::geometry::UVPackIsland_Params pack_island_params;
|
||||
pack_island_params.setFromUnwrapOptions(options);
|
||||
pack_island_params.rotate_method = ED_UVPACK_ROTATION_ANY;
|
||||
pack_island_params.pin_method = ED_UVPACK_PIN_IGNORED;
|
||||
pack_island_params.pin_method = ED_UVPACK_PIN_IGNORE;
|
||||
pack_island_params.margin_method = eUVPackIsland_MarginMethod(
|
||||
RNA_enum_get(op->ptr, "margin_method"));
|
||||
pack_island_params.margin = RNA_float_get(op->ptr, "margin");
|
||||
|
|
|
@ -49,12 +49,11 @@ enum eUVPackIsland_ShapeMethod {
|
|||
};
|
||||
|
||||
enum eUVPackIsland_PinMethod {
|
||||
ED_UVPACK_PIN_IGNORED = 0,
|
||||
ED_UVPACK_PIN_DEFAULT,
|
||||
ED_UVPACK_PIN_IGNORE = 0,
|
||||
ED_UVPACK_PIN_PACK,
|
||||
ED_UVPACK_PIN_LOCK_ROTATION,
|
||||
ED_UVPACK_PIN_LOCK_ROTATION_SCALE,
|
||||
ED_UVPACK_PIN_LOCK_SCALE,
|
||||
ED_UVPACK_PIN_LOCK_TRANSLATION,
|
||||
ED_UVPACK_PIN_LOCK_ALL, /* Lock translation, rotation and scale. */
|
||||
};
|
||||
|
||||
|
|
|
@ -339,7 +339,7 @@ UVPackIsland_Params::UVPackIsland_Params()
|
|||
only_selected_faces = false;
|
||||
use_seams = false;
|
||||
correct_aspect = false;
|
||||
pin_method = ED_UVPACK_PIN_DEFAULT;
|
||||
pin_method = ED_UVPACK_PIN_PACK;
|
||||
pin_unselected = false;
|
||||
merge_overlap = false;
|
||||
margin = 0.001f;
|
||||
|
@ -1546,6 +1546,13 @@ static float pack_islands_scale_margin(const Span<PackIsland *> islands,
|
|||
r_phis,
|
||||
&final_extent);
|
||||
|
||||
/* Housekeeping. */
|
||||
for (const int64_t i : aabbs.index_range()) {
|
||||
UVAABBIsland *aabb = aabbs[i];
|
||||
aabbs[i] = nullptr;
|
||||
delete aabb;
|
||||
}
|
||||
|
||||
return get_aspect_scaled_extent(final_extent, params);
|
||||
}
|
||||
|
||||
|
@ -1981,7 +1988,6 @@ bool PackIsland::can_translate_(const UVPackIsland_Params ¶ms) const
|
|||
}
|
||||
switch (params.pin_method) {
|
||||
case ED_UVPACK_PIN_LOCK_ALL:
|
||||
case ED_UVPACK_PIN_LOCK_TRANSLATION:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
|
|
|
@ -15,20 +15,19 @@ static void node_declare(NodeDeclarationBuilder &b)
|
|||
{
|
||||
b.add_input<decl::Int>(N_("Edge Index"))
|
||||
.implicit_field(implicit_field_inputs::index)
|
||||
.description(
|
||||
N_("The edge to retrieve data from. Defaults to the edge from the context"));
|
||||
.description(N_("The edge to retrieve data from. Defaults to the edge from the context"));
|
||||
b.add_input<decl::Float>(N_("Weights"))
|
||||
.supports_field()
|
||||
.hide_value()
|
||||
.description(
|
||||
N_("Values that sort the corners attached to the edge"));
|
||||
.description(N_("Values that sort the corners attached to the edge"));
|
||||
b.add_input<decl::Int>(N_("Sort Index"))
|
||||
.min(0)
|
||||
.supports_field()
|
||||
.description(N_("Which of the sorted corners to output"));
|
||||
b.add_output<decl::Int>(N_("Corner Index"))
|
||||
.field_source_reference_all()
|
||||
.description(N_("A corner of the input edge in its face's winding order, chosen by the sort index"));
|
||||
.description(
|
||||
N_("A corner of the input edge in its face's winding order, chosen by the sort index"));
|
||||
b.add_output<decl::Int>(N_("Total"))
|
||||
.field_source()
|
||||
.reference_pass({0})
|
||||
|
|
Loading…
Reference in New Issue