Merge branch 'master' into fix-areaswitch-bs
This commit is contained in:
		
						commit
						6738ba6c5e
					
				@ -228,7 +228,6 @@ void AnimationLayer::resetData()
 | 
				
			|||||||
void AnimationLayer::calculateFrameGeometry()
 | 
					void AnimationLayer::calculateFrameGeometry()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  m_mask_rect = QRect();
 | 
					  m_mask_rect = QRect();
 | 
				
			||||||
  m_display_rect = QRect();
 | 
					 | 
				
			||||||
  m_scaled_frame_size = QSize();
 | 
					  m_scaled_frame_size = QSize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  QSize widget_size = size();
 | 
					  QSize widget_size = size();
 | 
				
			||||||
@ -243,19 +242,15 @@ void AnimationLayer::calculateFrameGeometry()
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
  else
 | 
					  else
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    QSize target_frame_size = m_frame_size;
 | 
					    m_scaled_frame_size = m_frame_size;
 | 
				
			||||||
    if (m_frame_rect.contains(m_mask_rect_hint))
 | 
					    if (m_frame_rect.contains(m_mask_rect_hint))
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      m_mask_rect = m_mask_rect_hint;
 | 
					      m_mask_rect = m_mask_rect_hint;
 | 
				
			||||||
      target_frame_size = m_mask_rect_hint.size();
 | 
					      m_scaled_frame_size = m_mask_rect_hint.size();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    double scale = double(widget_size.height()) / double(target_frame_size.height());
 | 
					    double scale = double(widget_size.height()) / double(m_scaled_frame_size.height());
 | 
				
			||||||
    m_scaled_frame_size = target_frame_size * scale;
 | 
					    m_scaled_frame_size *= scale;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    // display the frame in its center
 | 
					 | 
				
			||||||
    int x = (m_scaled_frame_size.width() - widget_size.width()) / 2;
 | 
					 | 
				
			||||||
    m_display_rect = QRect(x, 0, widget_size.width(), m_scaled_frame_size.height());
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (m_transformation_mode_hint == Qt::FastTransformation)
 | 
					    if (m_transformation_mode_hint == Qt::FastTransformation)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@ -294,11 +289,6 @@ void AnimationLayer::displayCurrentFrame()
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
      image = image.scaled(m_scaled_frame_size, Qt::IgnoreAspectRatio, m_transformation_mode);
 | 
					      image = image.scaled(m_scaled_frame_size, Qt::IgnoreAspectRatio, m_transformation_mode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (m_display_rect.isValid())
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        image = image.copy(m_display_rect);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if (m_flipped)
 | 
					      if (m_flipped)
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        image = image.transformed(QTransform().scale(-1.0, 1.0));
 | 
					        image = image.transformed(QTransform().scale(-1.0, 1.0));
 | 
				
			||||||
 | 
				
			|||||||
@ -99,7 +99,6 @@ private:
 | 
				
			|||||||
  QRect m_frame_rect;
 | 
					  QRect m_frame_rect;
 | 
				
			||||||
  QRect m_mask_rect_hint;
 | 
					  QRect m_mask_rect_hint;
 | 
				
			||||||
  QRect m_mask_rect;
 | 
					  QRect m_mask_rect;
 | 
				
			||||||
  QRect m_display_rect;
 | 
					 | 
				
			||||||
  QSize m_scaled_frame_size;
 | 
					  QSize m_scaled_frame_size;
 | 
				
			||||||
  bool m_processing = false;
 | 
					  bool m_processing = false;
 | 
				
			||||||
  bool m_pause = false;
 | 
					  bool m_pause = false;
 | 
				
			||||||
 | 
				
			|||||||
@ -127,7 +127,9 @@ public:
 | 
				
			|||||||
  QString get_asset(QString p_element, QString p_theme = QString(), QString p_subtheme = QString(), QString p_default_theme = QString(), QString p_misc = QString(), QString p_character = QString(), QString p_placeholder = QString());
 | 
					  QString get_asset(QString p_element, QString p_theme = QString(), QString p_subtheme = QString(), QString p_default_theme = QString(), QString p_misc = QString(), QString p_character = QString(), QString p_placeholder = QString());
 | 
				
			||||||
  QString get_image(QString p_element, QString p_theme = QString(), QString p_subtheme = QString(), QString p_default_theme = QString(), QString p_misc = QString(), QString p_character = QString(), QString p_placeholder = QString(), bool static_image = false);
 | 
					  QString get_image(QString p_element, QString p_theme = QString(), QString p_subtheme = QString(), QString p_default_theme = QString(), QString p_misc = QString(), QString p_character = QString(), QString p_placeholder = QString(), bool static_image = false);
 | 
				
			||||||
  QString get_sfx(QString p_sfx, QString p_misc = QString(), QString p_character = QString());
 | 
					  QString get_sfx(QString p_sfx, QString p_misc = QString(), QString p_character = QString());
 | 
				
			||||||
  QPair<QString, QRect> get_pos_path(const QString &pos, bool desk = false);
 | 
					
 | 
				
			||||||
 | 
					  BackgroundPosition get_pos_path(const QString &pos);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  QString get_case_sensitive_path(QString p_file);
 | 
					  QString get_case_sensitive_path(QString p_file);
 | 
				
			||||||
  QString get_real_path(const VPath &vpath, const QStringList &suffixes = {""});
 | 
					  QString get_real_path(const VPath &vpath, const QStringList &suffixes = {""});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1417,7 +1417,7 @@ void Courtroom::set_background(QString p_background, bool display)
 | 
				
			|||||||
    const QStringList overrides = {"def", "wit", "pro"};
 | 
					    const QStringList overrides = {"def", "wit", "pro"};
 | 
				
			||||||
    for (const QString &override_pos : overrides)
 | 
					    for (const QString &override_pos : overrides)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      if (!ao_app->read_design_ini("court:" + override_pos + "/rect", ao_app->get_background_path("design.ini")).isEmpty())
 | 
					      if (!ao_app->read_design_ini("court:" + override_pos + "/origin", ao_app->get_background_path("design.ini")).isEmpty())
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        pos_list.append(override_pos);
 | 
					        pos_list.append(override_pos);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@ -1525,7 +1525,7 @@ void Courtroom::set_pos_dropdown(QStringList pos_dropdowns)
 | 
				
			|||||||
  {
 | 
					  {
 | 
				
			||||||
    QString pos = pos_dropdown_list.at(n);
 | 
					    QString pos = pos_dropdown_list.at(n);
 | 
				
			||||||
    ui_pos_dropdown->addItem(pos);
 | 
					    ui_pos_dropdown->addItem(pos);
 | 
				
			||||||
    QPixmap image = QPixmap(ao_app->get_image_suffix(ao_app->get_background_path(ao_app->get_pos_path(pos).first)));
 | 
					    QPixmap image = QPixmap(ao_app->get_image_suffix(ao_app->get_background_path(ao_app->get_pos_path(pos).background)));
 | 
				
			||||||
    if (!image.isNull())
 | 
					    if (!image.isNull())
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      image = image.scaledToHeight(ui_pos_dropdown->iconSize().height());
 | 
					      image = image.scaledToHeight(ui_pos_dropdown->iconSize().height());
 | 
				
			||||||
@ -3008,13 +3008,13 @@ void Courtroom::do_transition(QString p_desk_mod, QString oldPosId, QString newP
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  QPair<QString, QRect> old_pos_pair = ao_app->get_pos_path(t_old_pos);
 | 
					  BackgroundPosition old_pos = ao_app->get_pos_path(t_old_pos);
 | 
				
			||||||
  QPair<QString, QRect> new_pos_pair = ao_app->get_pos_path(t_new_pos);
 | 
					  BackgroundPosition new_pos = ao_app->get_pos_path(t_new_pos);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  int duration = ao_app->get_pos_transition_duration(t_old_pos, t_new_pos);
 | 
					  int duration = ao_app->get_pos_transition_duration(t_old_pos, t_new_pos);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // conditions to stop slide
 | 
					  // conditions to stop slide
 | 
				
			||||||
  if (oldPosId == newPosId || old_pos_pair.first != new_pos_pair.first || !new_pos_pair.second.isValid() || !Options::getInstance().slidesEnabled() || m_chatmessage[SLIDE] != "1" || duration == -1 || m_chatmessage[EMOTE_MOD].toInt() == ZOOM || m_chatmessage[EMOTE_MOD].toInt() == PREANIM_ZOOM)
 | 
					  if (oldPosId == newPosId || old_pos.background != new_pos.background || !old_pos.origin.has_value() || !new_pos.origin.has_value() || !Options::getInstance().slidesEnabled() || m_chatmessage[SLIDE] != "1" || duration == -1 || m_chatmessage[EMOTE_MOD].toInt() == ZOOM || m_chatmessage[EMOTE_MOD].toInt() == PREANIM_ZOOM)
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
#ifdef DEBUG_TRANSITION
 | 
					#ifdef DEBUG_TRANSITION
 | 
				
			||||||
    qDebug() << "skipping transition - not applicable";
 | 
					    qDebug() << "skipping transition - not applicable";
 | 
				
			||||||
@ -3035,9 +3035,12 @@ void Courtroom::do_transition(QString p_desk_mod, QString oldPosId, QString newP
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  int viewport_width = ui_viewport->width();
 | 
					  int viewport_width = ui_viewport->width();
 | 
				
			||||||
  int viewport_height = ui_viewport->height();
 | 
					  int viewport_height = ui_viewport->height();
 | 
				
			||||||
 | 
					  int frame_width = ui_vp_background->frameSize().width();
 | 
				
			||||||
 | 
					  int frame_height = ui_vp_background->frameSize().height();
 | 
				
			||||||
  double scale = double(viewport_height) / double(ui_vp_background->frameSize().height());
 | 
					  double scale = double(viewport_height) / double(ui_vp_background->frameSize().height());
 | 
				
			||||||
  QPoint scaled_old_pos = QPoint(old_pos_pair.second.x() * scale, 0);
 | 
					  QSize scaled_frame_size = QSize(frame_width * scale, frame_height * scale);
 | 
				
			||||||
  QPoint scaled_new_pos = QPoint(new_pos_pair.second.x() * scale, 0);
 | 
					  QPoint scaled_old_pos = QPoint(old_pos.origin.value() * scale - (viewport_width / 2), 0);
 | 
				
			||||||
 | 
					  QPoint scaled_new_pos = QPoint(new_pos.origin.value() * scale - (viewport_width / 2), 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  QList<kal::AnimationLayer *> affected_list = {ui_vp_background, ui_vp_desk};
 | 
					  QList<kal::AnimationLayer *> affected_list = {ui_vp_background, ui_vp_desk};
 | 
				
			||||||
  for (kal::AnimationLayer *ui_element : affected_list)
 | 
					  for (kal::AnimationLayer *ui_element : affected_list)
 | 
				
			||||||
@ -3303,6 +3306,14 @@ void Courtroom::initialize_chatbox()
 | 
				
			|||||||
  ui_vp_message->move(ui_vp_message->x() + ui_vp_chatbox->x(), ui_vp_message->y() + ui_vp_chatbox->y());
 | 
					  ui_vp_message->move(ui_vp_message->x() + ui_vp_chatbox->x(), ui_vp_message->y() + ui_vp_chatbox->y());
 | 
				
			||||||
  ui_vp_message->setTextInteractionFlags(Qt::NoTextInteraction);
 | 
					  ui_vp_message->setTextInteractionFlags(Qt::NoTextInteraction);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // For some reason, line spacing is done incorrectly unless we set it here.
 | 
				
			||||||
 | 
					  QTextCursor textCursor = ui_vp_message->textCursor();
 | 
				
			||||||
 | 
					  QTextBlockFormat linespacingFormat = QTextBlockFormat();
 | 
				
			||||||
 | 
					  textCursor.clearSelection();
 | 
				
			||||||
 | 
					  textCursor.select(QTextCursor::Document);
 | 
				
			||||||
 | 
					  linespacingFormat.setLineHeight(100, QTextBlockFormat::ProportionalHeight);
 | 
				
			||||||
 | 
					  textCursor.setBlockFormat(linespacingFormat);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (ui_vp_showname->text().trimmed().isEmpty()) // Whitespace showname
 | 
					  if (ui_vp_showname->text().trimmed().isEmpty()) // Whitespace showname
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    ui_vp_chatbox->setImage("chatblank", p_misc);
 | 
					    ui_vp_chatbox->setImage("chatblank", p_misc);
 | 
				
			||||||
@ -4533,13 +4544,12 @@ void Courtroom::play_sfx()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void Courtroom::set_scene(bool show_desk, const QString f_side)
 | 
					void Courtroom::set_scene(bool show_desk, const QString f_side)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  QPair<QString, QRect> bg_pair = ao_app->get_pos_path(f_side);
 | 
					  BackgroundPosition pos = ao_app->get_pos_path(f_side);
 | 
				
			||||||
  QPair<QString, QRect> desk_pair = ao_app->get_pos_path(f_side, true);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (file_exists(ao_app->get_image_suffix(ao_app->get_background_path(bg_pair.first))))
 | 
					  if (file_exists(ao_app->get_image_suffix(ao_app->get_background_path(pos.background))))
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    ui_vp_background->show();
 | 
					    ui_vp_background->show();
 | 
				
			||||||
    ui_vp_background->loadAndPlayAnimation(bg_pair.first);
 | 
					    ui_vp_background->loadAndPlayAnimation(pos.background);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  else if (file_exists(ao_app->get_image_suffix(ao_app->get_background_path("wit"))))
 | 
					  else if (file_exists(ao_app->get_image_suffix(ao_app->get_background_path("wit"))))
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
@ -4551,22 +4561,32 @@ void Courtroom::set_scene(bool show_desk, const QString f_side)
 | 
				
			|||||||
    ui_vp_background->hide();
 | 
					    ui_vp_background->hide();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (file_exists(ao_app->get_image_suffix(ao_app->get_background_path(desk_pair.first))))
 | 
					  if (file_exists(ao_app->get_image_suffix(ao_app->get_background_path(pos.desk))))
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    ui_vp_desk->loadAndPlayAnimation(desk_pair.first);
 | 
					    ui_vp_desk->loadAndPlayAnimation(pos.desk);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  else
 | 
					  else
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    show_desk = false;
 | 
					    show_desk = false;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  double scale = double(ui_viewport->height()) / double(ui_vp_background->frameSize().height());
 | 
					  QSize scaled_frame_size = ui_viewport->size();
 | 
				
			||||||
  QSize scaled_size = ui_vp_background->frameSize() * scale;
 | 
					  QPoint scaled_pos = QPoint(0, 0);
 | 
				
			||||||
  QPoint scaled_offset = QPoint(-(bg_pair.second.x() * scale), 0);
 | 
					  if (pos.origin)
 | 
				
			||||||
  ui_vp_background->resize(scaled_size);
 | 
					  {
 | 
				
			||||||
  ui_vp_background->move(scaled_offset);
 | 
					    int viewport_height = ui_viewport->height();
 | 
				
			||||||
  ui_vp_desk->resize(scaled_size);
 | 
					    int viewport_width = ui_viewport->width();
 | 
				
			||||||
  ui_vp_desk->move(scaled_offset);
 | 
					    QSize frame_size = ui_vp_background->frameSize();
 | 
				
			||||||
 | 
					    int frame_height = frame_size.height();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    double scale = double(viewport_height) / double(frame_height);
 | 
				
			||||||
 | 
					    scaled_frame_size = frame_size * scale;
 | 
				
			||||||
 | 
					    scaled_pos = QPoint(-(pos.origin.value() * scale - viewport_width / 2), 0);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  ui_vp_background->resize(scaled_frame_size);
 | 
				
			||||||
 | 
					  ui_vp_background->move(scaled_pos);
 | 
				
			||||||
 | 
					  ui_vp_desk->resize(scaled_frame_size);
 | 
				
			||||||
 | 
					  ui_vp_desk->move(scaled_pos);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  last_side = f_side;
 | 
					  last_side = f_side;
 | 
				
			||||||
  if (show_desk)
 | 
					  if (show_desk)
 | 
				
			||||||
 | 
				
			|||||||
@ -3,6 +3,8 @@
 | 
				
			|||||||
#include <QMap>
 | 
					#include <QMap>
 | 
				
			||||||
#include <QString>
 | 
					#include <QString>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <optional>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum ServerConnectionType
 | 
					enum ServerConnectionType
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  TcpServerConnection,
 | 
					  TcpServerConnection,
 | 
				
			||||||
@ -37,6 +39,14 @@ struct EvidenceItem
 | 
				
			|||||||
  QString image;
 | 
					  QString image;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class BackgroundPosition
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  QString background;
 | 
				
			||||||
 | 
					  QString desk;
 | 
				
			||||||
 | 
					  std::optional<int> origin;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct pos_size_type
 | 
					struct pos_size_type
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  int x = 0;
 | 
					  int x = 0;
 | 
				
			||||||
 | 
				
			|||||||
@ -78,7 +78,7 @@ VPath AOApplication::get_default_background_path(QString p_file)
 | 
				
			|||||||
  return VPath("background/default/" + p_file);
 | 
					  return VPath("background/default/" + p_file);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QPair<QString, QRect> AOApplication::get_pos_path(const QString &pos, const bool desk)
 | 
					BackgroundPosition AOApplication::get_pos_path(const QString &pos)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  // witness is default if pos is invalid
 | 
					  // witness is default if pos is invalid
 | 
				
			||||||
  QString f_pos = pos;
 | 
					  QString f_pos = pos;
 | 
				
			||||||
@ -97,19 +97,16 @@ QPair<QString, QRect> AOApplication::get_pos_path(const QString &pos, const bool
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
  QStringList f_pos_split = f_pos.split(":");
 | 
					  QStringList f_pos_split = f_pos.split(":");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  QRect f_rect;
 | 
					  std::optional<int> origin;
 | 
				
			||||||
  if (f_pos_split.size() > 1)
 | 
					 | 
				
			||||||
  { // Subposition, get center info
 | 
					 | 
				
			||||||
    QStringList arglist = read_design_ini(f_pos + "/rect", get_background_path("design.ini")).split(",");
 | 
					 | 
				
			||||||
    if (arglist.size() == 4)
 | 
					 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
      f_rect = QRect(arglist[0].toInt(), arglist[1].toInt(), arglist[2].toInt(), arglist[3].toInt());
 | 
					    bool ok;
 | 
				
			||||||
      if (!f_rect.isValid())
 | 
					    int result = read_design_ini(f_pos + "/origin", get_background_path("design.ini")).toInt(&ok);
 | 
				
			||||||
 | 
					    if (ok)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        f_rect = QRect();
 | 
					      origin = result;
 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  QString f_background;
 | 
					  QString f_background;
 | 
				
			||||||
  QString f_desk_image;
 | 
					  QString f_desk_image;
 | 
				
			||||||
  if (file_exists(get_image_suffix(get_background_path("witnessempty"))))
 | 
					  if (file_exists(get_image_suffix(get_background_path("witnessempty"))))
 | 
				
			||||||
@ -171,11 +168,7 @@ QPair<QString, QRect> AOApplication::get_pos_path(const QString &pos, const bool
 | 
				
			|||||||
    f_desk_image = desk_override;
 | 
					    f_desk_image = desk_override;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (desk)
 | 
					  return {f_background, f_desk_image, origin};
 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    return {f_desk_image, f_rect};
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return {f_background, f_rect};
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VPath AOApplication::get_evidence_path(QString p_file)
 | 
					VPath AOApplication::get_evidence_path(QString p_file)
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user