mirror of
https://github.com/mcneel/opennurbs.git
synced 2026-04-26 00:07:32 +08:00
Add source code for rhino 6.8 release
This commit is contained in:
590
opennurbs_3dm_attributes.h
Normal file
590
opennurbs_3dm_attributes.h
Normal file
@@ -0,0 +1,590 @@
|
||||
/* $NoKeywords: $ */
|
||||
/*
|
||||
//
|
||||
// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved.
|
||||
// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
|
||||
// McNeel & Associates.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
|
||||
// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
|
||||
// MERCHANTABILITY ARE HEREBY DISCLAIMED.
|
||||
//
|
||||
// For complete openNURBS copyright information see <http://www.opennurbs.org>.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// defines ON_3dmObjectAttributes
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined(OPENNURBS_3DM_ATTRIBUTES_INC_)
|
||||
#define OPENNURBS_3DM_ATTRIBUTES_INC_
|
||||
|
||||
|
||||
/*
|
||||
Description:
|
||||
Top level OpenNURBS objects have geometry and attributes. The
|
||||
geometry is stored in some class derived from ON_Geometry and
|
||||
the attributes are stored in an ON_3dmObjectAttributes class.
|
||||
Examples of attributes are object name, object id, display
|
||||
attributes, group membership, layer membership, and so on.
|
||||
|
||||
Remarks:
|
||||
7 January 2003 Dale Lear
|
||||
Derived from ON_Object so ON_UserData can be attached
|
||||
to ON_3dmObjectAttributes.
|
||||
*/
|
||||
|
||||
class ON_CLASS ON_3dmObjectAttributes : public ON_Object
|
||||
{
|
||||
ON_OBJECT_DECLARE(ON_3dmObjectAttributes);
|
||||
|
||||
public:
|
||||
static const ON_3dmObjectAttributes Unset;
|
||||
static const ON_3dmObjectAttributes DefaultAttributes;
|
||||
|
||||
public:
|
||||
// ON_Object virtual interface. See ON_Object
|
||||
// for details.
|
||||
|
||||
bool IsValid( class ON_TextLog* text_log = nullptr ) const override;
|
||||
// virtual
|
||||
void Dump( ON_TextLog& ) const override;
|
||||
// virtual
|
||||
unsigned int SizeOf() const override;
|
||||
// virtual
|
||||
bool Write(ON_BinaryArchive&) const override;
|
||||
// virtual
|
||||
bool Read(ON_BinaryArchive&) override;
|
||||
|
||||
/*
|
||||
Returns:
|
||||
True if successful.
|
||||
(xform is invertable or didn't need to be).
|
||||
*/
|
||||
bool Transform( const ON_Xform& xform );
|
||||
|
||||
// attributes of geometry and dimension table objects
|
||||
public:
|
||||
ON_3dmObjectAttributes();
|
||||
~ON_3dmObjectAttributes();
|
||||
|
||||
// Default C++ copy constructor and operator= work fine
|
||||
// Do not provide custom versions
|
||||
// NO // ON_3dmObjectAttributes(const ON_3dmObjectAttributes&);
|
||||
// NO // ON_3dmObjectAttributes& operator=(const ON_3dmObjectAttributes&);
|
||||
|
||||
bool operator==(const ON_3dmObjectAttributes&) const;
|
||||
bool operator!=(const ON_3dmObjectAttributes&) const;
|
||||
|
||||
// Initializes all attributes to the default values.
|
||||
void Default();
|
||||
|
||||
|
||||
bool UpdateReferencedComponents(
|
||||
const class ON_ComponentManifest& source_manifest,
|
||||
const class ON_ComponentManifest& destination_manifest,
|
||||
const class ON_ManifestMap& manifest_map
|
||||
) override;
|
||||
|
||||
// Interface ////////////////////////////////////////////////////////
|
||||
|
||||
// An OpenNURBS object must be in one of three modes: normal, locked
|
||||
// or hidden. If an object is in normal mode, then the object's layer
|
||||
// controls visibility and selectability. If an object is locked, then
|
||||
// the object's layer controls visibility by the object cannot be selected.
|
||||
// If the object is hidden, it is not visible and it cannot be selected.
|
||||
ON::object_mode Mode() const;
|
||||
void SetMode( ON::object_mode ); // See Mode().
|
||||
|
||||
/*
|
||||
Description:
|
||||
Use this query to determine if an object is part of an
|
||||
instance definition.
|
||||
Returns:
|
||||
True if the object is part of an instance definition.
|
||||
*/
|
||||
bool IsInstanceDefinitionObject() const;
|
||||
|
||||
/*
|
||||
Returns:
|
||||
Returns true if object is visible.
|
||||
See Also:
|
||||
ON_3dmObjectAttributes::SetVisible
|
||||
*/
|
||||
bool IsVisible() const;
|
||||
|
||||
/*
|
||||
Description:
|
||||
Controls object visibility
|
||||
Parameters:
|
||||
bVisible - [in] true to make object visible,
|
||||
false to make object invisible
|
||||
See Also:
|
||||
ON_3dmObjectAttributes::IsVisible
|
||||
*/
|
||||
void SetVisible( bool bVisible );
|
||||
|
||||
// The Linetype used to display an OpenNURBS object is specified in one of two ways.
|
||||
// If LinetypeSource() is ON::linetype_from_layer, then the object's layer
|
||||
// ON_Layer::Linetype() is used.
|
||||
// If LinetypeSource() is ON::linetype_from_object, then value of m_linetype is used.
|
||||
ON::object_linetype_source LinetypeSource() const;
|
||||
void SetLinetypeSource( ON::object_linetype_source ); // See LinetypeSource().
|
||||
|
||||
// The color used to display an OpenNURBS object is specified in one of three ways.
|
||||
// If ColorSource() is ON::color_from_layer, then the object's layer
|
||||
// ON_Layer::Color() is used.
|
||||
// If ColorSource() is ON::color_from_object, then value of m_color is used.
|
||||
// If ColorSource() is ON::color_from_material, then the diffuse color of the object's
|
||||
// render material is used. See ON_3dmObjectAttributes::MaterialSource() to
|
||||
// determine where to get the definition of the object's render material.
|
||||
ON::object_color_source ColorSource() const;
|
||||
void SetColorSource( ON::object_color_source ); // See ColorSource().
|
||||
|
||||
// The color used to plot an OpenNURBS object on paper is specified
|
||||
// in one of three ways.
|
||||
// If PlotColorSource() is ON::plot_color_from_layer, then the object's layer
|
||||
// ON_Layer::PlotColor() is used.
|
||||
// If PlotColorSource() is ON::plot_color_from_object, then value of PlotColor() is used.
|
||||
ON::plot_color_source PlotColorSource() const;
|
||||
void SetPlotColorSource( ON::plot_color_source ); // See PlotColorSource().
|
||||
|
||||
ON::plot_weight_source PlotWeightSource() const;
|
||||
void SetPlotWeightSource( ON::plot_weight_source );
|
||||
|
||||
/*
|
||||
Description:
|
||||
If "this" has attributes (color, plot weight, ...) with
|
||||
"by parent" sources, then the values of those attributes
|
||||
on parent_attributes are copied.
|
||||
Parameters:
|
||||
parent_attributes - [in]
|
||||
parent_layer - [in]
|
||||
control_limits - [in]
|
||||
The bits in control_limits determine which attributes may
|
||||
may be copied.
|
||||
1: visibility
|
||||
2: color
|
||||
4: render material
|
||||
8: plot color
|
||||
0x10: plot weight
|
||||
0x20: linetype
|
||||
0x40: display order
|
||||
|
||||
Returns:
|
||||
The bits in the returned integer indicate which attributes were
|
||||
actually modified.
|
||||
|
||||
1: visibility
|
||||
2: color
|
||||
4: render material
|
||||
8: plot color
|
||||
0x10: plot weight
|
||||
0x20: linetype
|
||||
0x40: display order
|
||||
*/
|
||||
//ON_DEPRECATED unsigned int ApplyParentalControl(
|
||||
// const ON_3dmObjectAttributes& parent_attributes,
|
||||
// unsigned int control_limits = 0xFFFFFFFF
|
||||
// );
|
||||
|
||||
unsigned int ApplyParentalControl(
|
||||
const ON_3dmObjectAttributes& parent_attributes,
|
||||
const ON_Layer& parent_layer,
|
||||
unsigned int control_limits = 0xFFFFFFFF
|
||||
);
|
||||
|
||||
// Every OpenNURBS object has a UUID (universally unique identifier). The
|
||||
// default value is nullptr. When an OpenNURBS object is added to a model, the
|
||||
// value is checked. If the value is nullptr, a new UUID is created. If the
|
||||
// value is not nullptr but it is already used by another object in the model,
|
||||
// a new UUID is created. If the value is not nullptr and it is not used by
|
||||
// another object in the model, then that value persists. When an object
|
||||
// is updated, by a move for example, the value of m_uuid persists.
|
||||
ON_UUID m_uuid;
|
||||
|
||||
// The m_name member is public to avoid breaking the SDK.
|
||||
// Use SetName() and Name() for proper validation.
|
||||
// OpenNURBS object have optional text names. More than one object in
|
||||
// a model can have the same name and some objects may have no name.
|
||||
// ON_ModelComponent::IsValidComponentName(m_name) should be true.
|
||||
ON_wString m_name;
|
||||
|
||||
bool SetName(
|
||||
const wchar_t* name,
|
||||
bool bFixInvalidName
|
||||
);
|
||||
|
||||
const ON_wString Name() const;
|
||||
|
||||
// OpenNURBS objects may have an URL. There are no restrictions on what
|
||||
// value this URL may have. As an example, if the object came from a
|
||||
// commercial part library, the URL might point to the definition of that
|
||||
// part.
|
||||
ON_wString m_url;
|
||||
|
||||
// Layer definitions in an OpenNURBS model are stored in a layer table.
|
||||
// The layer table is conceptually an array of ON_Layer classes. Every
|
||||
// OpenNURBS object in a model is on some layer. The object's layer
|
||||
// is specified by zero based indicies into the ON_Layer array.
|
||||
int m_layer_index;
|
||||
|
||||
// Linetype definitions in an OpenNURBS model are stored in a linetype table.
|
||||
// The linetype table is conceptually an array of ON_Linetype classes. Every
|
||||
// OpenNURBS object in a model references some linetype. The object's linetype
|
||||
// is specified by zero based indicies into the ON_Linetype array.
|
||||
// index 0 is reserved for continuous linetype (no pattern)
|
||||
int m_linetype_index;
|
||||
|
||||
// Rendering material:
|
||||
// If you want something simple and fast, set
|
||||
// m_material_index to the index of the rendering material
|
||||
// and ignore m_rendering_attributes.
|
||||
// If you are developing a high quality plug-in renderer,
|
||||
// and a user is assigning one of your fabulous rendering
|
||||
// materials to this object, then add rendering material
|
||||
// information to the m_rendering_attributes.m_materials[]
|
||||
// array.
|
||||
//
|
||||
// Developers:
|
||||
// As soon as m_rendering_attributes.m_materials[] is not empty,
|
||||
// rendering material queries slow down. Do not populate
|
||||
// m_rendering_attributes.m_materials[] when setting
|
||||
// m_material_index will take care of your needs.
|
||||
int m_material_index;
|
||||
ON_ObjectRenderingAttributes m_rendering_attributes;
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// BEGIN: Per object mesh parameter support
|
||||
//
|
||||
|
||||
/*
|
||||
Parameters:
|
||||
mp - [in]
|
||||
per object mesh parameters
|
||||
Returns:
|
||||
True if successful.
|
||||
*/
|
||||
bool SetCustomRenderMeshParameters(const class ON_MeshParameters& mp);
|
||||
|
||||
/*
|
||||
Parameters:
|
||||
bEnable - [in]
|
||||
true to enable use of the per object mesh parameters.
|
||||
false to disable use of the per object mesh parameters.
|
||||
Returns:
|
||||
False if the object doe not have per object mesh parameters
|
||||
and bEnable was true. Use SetMeshParameters() to set
|
||||
per object mesh parameters.
|
||||
Remarks:
|
||||
Sets the value of ON_MeshParameters::m_bCustomSettingsDisabled
|
||||
to !bEnable
|
||||
*/
|
||||
bool EnableCustomRenderMeshParameters(bool bEnable);
|
||||
|
||||
/*
|
||||
Returns:
|
||||
Null or a pointer to fragile mesh parameters.
|
||||
If a non-null pointer is returned, copy it and use the copy.
|
||||
* DO NOT SAVE THIS POINTER FOR LATER USE. A call to
|
||||
DeleteMeshParameters() will delete the class.
|
||||
* DO NOT const_cast the returned pointer and change its
|
||||
settings. You must use either SetMeshParameters()
|
||||
or EnableMeshParameters() to change settings.
|
||||
Remarks:
|
||||
If the value of ON_MeshParameters::m_bCustomSettingsDisabled is
|
||||
true, then do no use these parameters to make a render mesh.
|
||||
*/
|
||||
const ON_MeshParameters* CustomRenderMeshParameters() const;
|
||||
|
||||
/*
|
||||
Description:
|
||||
Deletes any per object mesh parameters.
|
||||
*/
|
||||
void DeleteCustomRenderMeshParameters();
|
||||
|
||||
//
|
||||
// END: Per object mesh parameter support
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/*
|
||||
Description:
|
||||
Determine if the simple material should come from
|
||||
the object or from it's layer.
|
||||
High quality rendering plug-ins should use m_rendering_attributes.
|
||||
Returns:
|
||||
Where to get material information if you do are too lazy
|
||||
to look in m_rendering_attributes.m_materials[].
|
||||
*/
|
||||
ON::object_material_source MaterialSource() const;
|
||||
|
||||
/*
|
||||
Description:
|
||||
Specifies if the simple material should be the one
|
||||
indicated by the material index or the one indicated
|
||||
by the object's layer.
|
||||
Parameters:
|
||||
ms - [in]
|
||||
*/
|
||||
void SetMaterialSource( ON::object_material_source ms );
|
||||
|
||||
// If ON::color_from_object == ColorSource(), then m_color is the object's
|
||||
// display color.
|
||||
ON_Color m_color;
|
||||
|
||||
// If ON::plot_color_from_object == PlotColorSource(), then m_color is the object's
|
||||
// display color.
|
||||
ON_Color m_plot_color;
|
||||
|
||||
// Display order used to force objects to be drawn on top or behind each other
|
||||
// 0 = draw object in standard depth buffered order
|
||||
// <0 = draw object behind "normal" draw order objects
|
||||
// >0 = draw object on top of "noraml" draw order objects
|
||||
// Larger number draws on top of smaller number.
|
||||
int m_display_order;
|
||||
|
||||
// Plot weight in millimeters.
|
||||
// =0.0 means use the default width
|
||||
// <0.0 means don't plot (visible for screen display, but does not show on plot)
|
||||
double m_plot_weight_mm;
|
||||
|
||||
// Used to indicate an object has a decoration (like an arrowhead on a curve)
|
||||
ON::object_decoration m_object_decoration;
|
||||
|
||||
// When a surface object is displayed in wireframe, m_wire_density controls
|
||||
// how many isoparametric wires are used.
|
||||
//
|
||||
// @table
|
||||
// value number of isoparametric wires
|
||||
// -1 boundary wires
|
||||
// 0 boundary and knot wires
|
||||
// 1 boundary and knot wires and, if there are no
|
||||
// interior knots, a single interior wire.
|
||||
// N>=2 boundary and knot wires and (N-1) interior wires
|
||||
int m_wire_density;
|
||||
|
||||
|
||||
// If m_viewport_id is nil, the object is active in
|
||||
// all viewports. If m_viewport_id is not nil, then
|
||||
// this object is only active in a specific view.
|
||||
// This field is primarily used to assign page space
|
||||
// objects to a specific page, but it can also be used
|
||||
// to restrict model space to a specific view.
|
||||
ON_UUID m_viewport_id;
|
||||
|
||||
// Starting with V4, objects can be in either model space
|
||||
// or page space. If an object is in page space, then
|
||||
// m_viewport_id is not nil and identifies the page it
|
||||
// is on.
|
||||
ON::active_space m_space;
|
||||
|
||||
private:
|
||||
bool m_bVisible;
|
||||
unsigned char m_mode; // (m_mode % 16) = ON::object_mode values
|
||||
// (m_mode / 16) = ON::display_mode values
|
||||
unsigned char m_color_source; // ON::object_color_source values
|
||||
unsigned char m_plot_color_source; // ON::plot_color_source values
|
||||
unsigned char m_plot_weight_source; // ON::plot_weight_source values
|
||||
unsigned char m_material_source; // ON::object_material_source values
|
||||
unsigned char m_linetype_source; // ON::object_linetype_source values
|
||||
|
||||
unsigned char m_reserved_0;
|
||||
|
||||
ON_Xform m_reserved_future_frame = ON_Xform::Nan;
|
||||
|
||||
ON_SimpleArray<int> m_group; // array of zero based group indices
|
||||
|
||||
private:
|
||||
ON__UINT_PTR m_reserved_ptr = 0;
|
||||
|
||||
public:
|
||||
// group interface
|
||||
|
||||
// returns number of groups object belongs to
|
||||
int GroupCount() const;
|
||||
|
||||
// Returns and array an array of GroupCount() zero based
|
||||
// group indices. If GroupCount() is zero, then GroupList()
|
||||
// returns nullptr.
|
||||
const int* GroupList() const;
|
||||
|
||||
// Returns GroupCount() and puts a list of zero based group indices
|
||||
// into the array.
|
||||
int GetGroupList(ON_SimpleArray<int>&) const;
|
||||
|
||||
// Returns the index of the last group in the group list
|
||||
// or -1 if the object is not in any groups
|
||||
int TopGroup() const;
|
||||
|
||||
// Returns true if object is in group with the specified index
|
||||
bool IsInGroup(
|
||||
int // zero based group index
|
||||
) const;
|
||||
|
||||
// Returns true if the object is in any of the groups in the list
|
||||
bool IsInGroups(
|
||||
int, // group_list_count
|
||||
const int* // group_list[] array
|
||||
) const;
|
||||
|
||||
// Returns true if object is in any of the groups in the list
|
||||
bool IsInGroups(
|
||||
const ON_SimpleArray<int>& // group_list[] array
|
||||
) const;
|
||||
|
||||
// Adds object to the group with specified index by appending index to
|
||||
// group list (If the object is already in group, nothing is changed.)
|
||||
void AddToGroup(
|
||||
int // zero based group index
|
||||
);
|
||||
|
||||
// Removes object from the group with specified index. If the
|
||||
// object is not in the group, nothing is changed.
|
||||
void RemoveFromGroup(
|
||||
int // zero based group index
|
||||
);
|
||||
|
||||
// removes the object from the last group in the group list
|
||||
void RemoveFromTopGroup();
|
||||
|
||||
// Removes object from all groups.
|
||||
void RemoveFromAllGroups();
|
||||
|
||||
|
||||
// display material references
|
||||
|
||||
/*
|
||||
Description:
|
||||
Searches for a matching display material. For a given
|
||||
viewport id, there is at most one display material.
|
||||
For a given display material id, there can be multiple
|
||||
viewports. If there is a display reference in the
|
||||
list with a nil viewport id, then the display material
|
||||
will be used in all viewports that are not explictly
|
||||
referenced in other ON_DisplayMaterialRefs.
|
||||
|
||||
Parameters:
|
||||
search_material - [in]
|
||||
found_material - [out]
|
||||
|
||||
If FindDisplayMaterialRef(), the input value of search_material
|
||||
is never changed. If FindDisplayMaterialRef() returns true,
|
||||
the chart shows the output value of display_material. When
|
||||
there are multiple possibilities for a match, the matches
|
||||
at the top of the chart have higher priority.
|
||||
|
||||
search_material found_material
|
||||
input value output value
|
||||
|
||||
(nil,nil) (nil,did) if (nil,did) is in the list.
|
||||
(nil,did) (vid,did) if (vid,did) is in the list.
|
||||
(nil,did) (nil,did) if (nil,did) is in the list.
|
||||
(vid,nil) (vid,did) if (vid,did) is in the list
|
||||
(vid,nil) (vid,did) if (nil,did) is in the list
|
||||
(vid,did) (vid,did) if (vid,did) is in the list.
|
||||
|
||||
Example:
|
||||
ON_UUID display_material_id = ON_nil_uuid;
|
||||
ON_Viewport vp = ...;
|
||||
ON_DisplayMaterialRef search_dm;
|
||||
search_dm.m_viewport_id = vp.ViewportId();
|
||||
ON_DisplayMaterialRef found_dm;
|
||||
if ( attributes.FindDisplayMaterial(search_dm, &found_dm) )
|
||||
{
|
||||
display_material_id = found_dm.m_display_material_id;
|
||||
}
|
||||
|
||||
Returns:
|
||||
True if a matching display material is found.
|
||||
See Also:
|
||||
ON_3dmObjectAttributes::AddDisplayMaterialRef
|
||||
ON_3dmObjectAttributes::RemoveDisplayMaterialRef
|
||||
*/
|
||||
bool FindDisplayMaterialRef(
|
||||
const ON_DisplayMaterialRef& search_material,
|
||||
ON_DisplayMaterialRef* found_material = nullptr
|
||||
) const;
|
||||
|
||||
/*
|
||||
Description:
|
||||
Quick way to see if a viewport has a special material.
|
||||
Parameters:
|
||||
viewport_id - [in]
|
||||
display_material_id - [out]
|
||||
Returns:
|
||||
True if a material_id is assigned.
|
||||
*/
|
||||
bool FindDisplayMaterialId(
|
||||
const ON_UUID& viewport_id,
|
||||
ON_UUID* display_material_id = nullptr
|
||||
) const;
|
||||
|
||||
/*
|
||||
Description:
|
||||
Add a display material reference to the attributes. If
|
||||
there is an existing entry with a matching viewport id,
|
||||
the existing entry is replaced.
|
||||
Parameters:
|
||||
display_material - [in]
|
||||
Returns:
|
||||
True if input is valid (material id != nil)
|
||||
See Also:
|
||||
ON_3dmObjectAttributes::FindDisplayMaterialRef
|
||||
ON_3dmObjectAttributes::RemoveDisplayMaterialRef
|
||||
*/
|
||||
bool AddDisplayMaterialRef(
|
||||
ON_DisplayMaterialRef display_material
|
||||
);
|
||||
|
||||
/*
|
||||
Description:
|
||||
Remove a display material reference from the list.
|
||||
Parameters:
|
||||
viewport_id - [in] Any display material references
|
||||
with this viewport id will be removed. If nil,
|
||||
then viewport_id is ignored.
|
||||
display_material_id - [in]
|
||||
Any display material references that match the
|
||||
viewport_id and have this display_material_id
|
||||
will be removed. If nil, then display_material_id
|
||||
is ignored.
|
||||
Returns:
|
||||
True if a display material reference was removed.
|
||||
See Also:
|
||||
ON_3dmObjectAttributes::FindDisplayMaterialRef
|
||||
ON_3dmObjectAttributes::AddDisplayMaterialRef
|
||||
*/
|
||||
bool RemoveDisplayMaterialRef(
|
||||
ON_UUID viewport_id,
|
||||
ON_UUID display_material_id = ON_nil_uuid
|
||||
);
|
||||
|
||||
/*
|
||||
Description:
|
||||
Remove a the entire display material reference list.
|
||||
*/
|
||||
void RemoveAllDisplayMaterialRefs();
|
||||
|
||||
/*
|
||||
Returns:
|
||||
Number of diplay material refences.
|
||||
*/
|
||||
int DisplayMaterialRefCount() const;
|
||||
|
||||
ON_SimpleArray<ON_DisplayMaterialRef> m_dmref;
|
||||
|
||||
private:
|
||||
bool Internal_WriteV5( ON_BinaryArchive& archive ) const;
|
||||
bool Internal_ReadV5( ON_BinaryArchive& archive );
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// Brian G adding another comment on Tim's machine.
|
||||
Reference in New Issue
Block a user