<commit_before>/* This file is part of the KDE libraries
   Copyright (C) 2001-2002 Christoph Cullmann <cullmann@kde.org>
   Copyright (C) 2002 Joseph Wenninger <jowenn@kde.org>

   Based on:
     TextLine : Copyright (C) 1999 Jochen Wilhelmy <digisnap@cs.tu-berlin.de>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 as published by the Free Software Foundation.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.
*/

// $Id$

#include "katetextline.h"

#include <qregexp.h>

TextLine::TextLine()
  : m_flags(TextLine::flagVisible)
{
}

TextLine::~TextLine()
{
}

void TextLine::insertText (uint pos, uint insLen, const QChar *insText, uchar *insAttribs)
{
  // nothing to do
  if (insLen == 0)
    return;

  // calc new textLen, store old
  uint textLen = m_text.size();
  uint oldTextLen = textLen;

  if (pos <= textLen)
    textLen += insLen;
  else if (pos > textLen)
    textLen = pos + insLen;

  // resize the arrays
  m_text.resize (textLen);
  m_attributes.resize (textLen);

  // HA, insert behind text end, fill with spaces
  if (pos >= oldTextLen)
  {
    for (uint z = oldTextLen; z < pos; z++)
    {
      m_text[z] = QChar(' ');
      m_attributes[z] = 0;
    }
  }
  // HA, insert in text, move the old text behind pos
  else if (oldTextLen > 0)
  {
    for (int z = oldTextLen -1; z >= (int) pos; z--)
    {
      m_text[z+insLen] = m_text[z];
      m_attributes[z+insLen] = m_attributes[z];
    }
  }

  // BUH, actually insert the new text
  for (uint z = 0; z < insLen; z++)
  {
    m_text[z+pos] = insText[z];

    if (insAttribs == 0)
      m_attributes[z+pos] = 0;
    else
      m_attributes[z+pos] = insAttribs[z];
  }
}

void TextLine::removeText (uint pos, uint delLen)
{
  // nothing to do
  if (delLen == 0)
    return;

  // calc textLen, store old one, calc delLen
  uint textLen = m_text.size();

  if (textLen == 0)
    return; // uh, again nothing real to do ;)

  uint oldTextLen = textLen;

  if (pos >= textLen)
    return;

  if ((pos + delLen) > textLen)
    delLen = textLen - pos;

  if (delLen < textLen)
    textLen -= delLen;
  else
    textLen = 0;

  // BU, MOVE THE OLD TEXT AROUND
  if (textLen > 0)
  {
    for (int z = pos; z < (int) oldTextLen; z++)
    {
      m_text[z] = m_text[z+delLen];
      m_attributes[z] = m_attributes[z+delLen];
    }
  }

  // resize the stuff
  m_text.resize (textLen);
  m_attributes.resize (textLen);
}

void TextLine::append(const QChar *s, uint l)
{
  insertText (m_text.size(), l, s, 0);
}

void TextLine::truncate(uint newLen)
{
  if (newLen < m_text.size())
  {
    m_text.truncate (newLen);
    m_attributes.truncate (newLen);
  }
}

void TextLine::wrap(TextLine::Ptr nextLine, uint pos)
{
  int l = m_text.size() - pos;

  if (l > 0)
  {
    nextLine->insertText (0, l, &m_text[pos], &m_attributes[pos]);
    truncate(pos);
  }
}

void TextLine::unWrap(uint pos, TextLine::Ptr nextLine, uint len)
{
  insertText (pos, len, nextLine->m_text.data(), nextLine->m_attributes.data());
  nextLine->removeText (0, len);
}

int TextLine::nextNonSpaceChar(uint pos) const
{
    for(int i = pos; i < (int)m_text.size(); i++) {
        if(!m_text[i].isSpace())
            return i;
    }
    return -1;
}

int TextLine::previousNonSpaceChar(uint pos) const
{
    if(pos >= m_text.size()) {
        pos = m_text.size() - 1;
    }

    for(int i = pos; i >= 0; i--) {
        if(!m_text[i].isSpace())
            return i;
    }
    return -1;
}

int TextLine::firstChar() const
{
  return nextNonSpaceChar(0);
}

int TextLine::lastChar() const
{
    return previousNonSpaceChar(m_text.size() - 1);
}

QString TextLine::string (uint startCol, uint length) const
{
  if ( startCol >= m_text.size() )
    return QString ();

  if ( (startCol + length) > m_text.size())
    length = m_text.size() - startCol;

  return QString (m_text.data() + startCol, length);
}

void TextLine::removeSpaces()
{
  truncate(lastChar() + 1);
}

QChar *TextLine::firstNonSpace() const
{
  int first = firstChar();
  return (first > -1) ? &m_text[first] : m_text.data();
}

bool TextLine::stringAtPos(uint pos, const QString& match) const
{
  return (QConstString (this->m_text.data(), this->m_text.size()).string().mid(pos, match.length()) == match);
}

bool TextLine::startingWith(const QString& match) const
{
  return (QConstString (this->m_text.data(), this->m_text.size()).string().left(match.length()) == match);
}

bool TextLine::endingWith(const QString& match) const
{
  return (QConstString (this->m_text.data(), this->m_text.size()).string().right(match.length()) == match);
}

int TextLine::cursorX(uint pos, uint tabChars) const
{
  int l, x, z;

  l = (pos < m_text.size()) ? pos : m_text.size();
  x = 0;
  for (z = 0; z < l; z++) {
    if (m_text[z] == QChar('\t')) x += tabChars - (x % tabChars); else x++;
  }
  x += pos - l;
  return x;
}

void TextLine::setAttribs(uchar attribute, uint start, uint end) {
  uint z;

  if (end > m_text.size()) end = m_text.size();
  for (z = start; z < end; z++) m_attributes[z] = attribute;
}

bool TextLine::searchText (uint startCol, const QString &text, uint *foundAtCol, uint *matchLen, bool casesensitive, bool backwards)
{
  int index;

  if (backwards)
    index = QConstString (this->m_text.data(), this->m_text.size()).string().findRev (text, startCol, casesensitive);
  else
    index = QConstString (this->m_text.data(), this->m_text.size()).string().find (text, startCol, casesensitive);

   if (index > -1)
	{
	  (*foundAtCol) = index;
		(*matchLen)=text.length();
		return true;
  }

  return false;
}

bool TextLine::searchText (uint startCol, const QRegExp &regexp, uint *foundAtCol, uint *matchLen, bool backwards)
{
  int index;

  if (backwards)
    index = regexp.searchRev (QConstString (this->m_text.data(), this->m_text.size()).string(), startCol);
  else
    index = regexp.search (QConstString (this->m_text.data(), this->m_text.size()).string(), startCol);

   if (index > -1)
	{
	  (*foundAtCol) = index;
		(*matchLen)=regexp.matchedLength();
		return true;
  }

  return false;
}

uint TextLine::dumpSize () const
{
  uint attributesLen = 0;

  if ( ! m_attributes.isEmpty())
  {
    attributesLen = 1;

    uint lastAttrib = m_attributes[0];

    for (uint z=0; z < m_attributes.size(); z++)
    {
      if (m_attributes[z] != lastAttrib)
      {
        attributesLen++;
        lastAttrib = m_attributes[z];
      }
    }
  }

  return (4*sizeof(uint)) + (m_text.size()*sizeof(QChar)) + (attributesLen * sizeof(uchar)) + (attributesLen * sizeof(uint)) + 1 + (m_ctx.size() * sizeof(uint)) + (m_foldingList.size() * sizeof(signed char));
}

char *TextLine::dump (char *buf) const
{
  uint l = m_text.size();
  uint lctx = m_ctx.size();
  uint lfold = m_foldingList.size();

  memcpy(buf, &l, sizeof(uint));
  buf += sizeof(uint);

  memcpy(buf, (char *) m_text.data(), sizeof(QChar)*l);
  buf += sizeof(QChar)*l;

  memcpy(buf, (char *) &m_flags, 1);
  buf += 1;

  char *attribLenPos = buf;
  buf += sizeof(uint);

  memcpy(buf, &lctx, sizeof(uint));
  buf += sizeof(uint);

  memcpy(buf, &lfold, sizeof(uint));
  buf += sizeof(uint);

  // hl size runlength encoding START

  uint attributesLen = 0;

  if ( ! m_attributes.isEmpty() )
  {
    attributesLen = 1;

    uchar lastAttrib = m_attributes[0];
    uint lastStart = 0;
    uint length = 0;

    for (uint z=0; z < m_attributes.size(); z++)
    {
      if (m_attributes[z] != lastAttrib)
      {
        length = z - lastStart;

        memcpy(buf, &lastAttrib, sizeof(uchar));
        buf += sizeof(uchar);

        memcpy(buf, &length, sizeof(uint));
        buf += sizeof(uint);

        lastStart = z;
        lastAttrib = m_attributes[z];

        attributesLen ++;
      }
    }

    length = m_attributes.size() - lastStart;

    memcpy(buf, &lastAttrib, sizeof(uchar));
    buf += sizeof(uchar);

    memcpy(buf, &length, sizeof(uint));
    buf += sizeof(uint);
  }

  memcpy(attribLenPos, &attributesLen, sizeof(uint));

  // hl size runlength encoding STOP

  memcpy(buf, (char *)m_ctx.data(), sizeof(uint) * lctx);
  buf += sizeof (uint) * lctx;

  memcpy(buf, (char *)m_foldingList.data(), lfold);
  buf += sizeof (signed char) * lfold;

  return buf;
}

char *TextLine::restore (char *buf)
{
  uint l = 0;
  uint lattrib = 0;
  uint lctx = 0;
  uint lfold = 0;

  // text + context length read
  memcpy((char *) &l, buf, sizeof(uint));
  buf += sizeof(uint);

  // text + attributes
  m_text.duplicate ((QChar *) buf, l);
  buf += sizeof(QChar)*l;

  m_attributes.resize (l);

  memcpy((char *) &m_flags, buf, 1);
  buf += 1;

  // we just restore a TextLine from a buffer first time
  if (m_flags == TextLine::flagNoOtherData)
  {
    m_flags = TextLine::flagVisible;
    m_attributes.fill (0);

    return buf;
  }

  memcpy((char *) &lattrib, buf, sizeof(uint));
  buf += sizeof(uint);

  memcpy((char *) &lctx, buf, sizeof(uint));
  buf += sizeof(uint);

  memcpy((char *) &lfold, buf, sizeof(uint));
  buf += sizeof(uint);

  // hl size runlength encoding START

  uchar *attr = m_attributes.data();

  uchar attrib = 0;
  uint length = 0;
  uint pos = 0;

  for (uint z=0; z < lattrib; z++)
  {
    if (pos >= m_attributes.size())
      break;

    memcpy((char *) &attrib, buf, sizeof(uchar));
    buf += sizeof(uchar);

    memcpy((char *) &length, buf, sizeof(uint));
    buf += sizeof(uint);

    if ((pos+length) > m_attributes.size())
      length = m_attributes.size() - pos;

    memset (attr, attrib, length);

    pos += length;
    attr += length;
  }

  // hl size runlength encoding STOP

  m_ctx.duplicate ((uint *) buf, lctx);
  buf += sizeof(uint) * lctx;

  m_foldingList.duplicate ((signed char *) buf, lfold);
  buf += lfold;

  return buf;
}

<commit_msg>Another crash (Q_ASSERT for others) fixed: when deleting text from a line, the loop that moves the chars was going too far. In essence: -    for (int z = pos; z < (int) oldTextLen; z++) +  for (uint z = pos; z < oldTextLen - delLen; z++) (but I also got rid of the useless oldTextLen, moving the -= below that loop). Heavily tested.<commit_after>/* This file is part of the KDE libraries
   Copyright (C) 2001-2002 Christoph Cullmann <cullmann@kde.org>
   Copyright (C) 2002 Joseph Wenninger <jowenn@kde.org>

   Based on:
     TextLine : Copyright (C) 1999 Jochen Wilhelmy <digisnap@cs.tu-berlin.de>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 as published by the Free Software Foundation.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.
*/

// $Id$

#include "katetextline.h"

#include <qregexp.h>

TextLine::TextLine()
  : m_flags(TextLine::flagVisible)
{
}

TextLine::~TextLine()
{
}

void TextLine::insertText (uint pos, uint insLen, const QChar *insText, uchar *insAttribs)
{
  // nothing to do
  if (insLen == 0)
    return;

  // calc new textLen, store old
  uint textLen = m_text.size();
  uint oldTextLen = textLen;

  if (pos <= textLen)
    textLen += insLen;
  else if (pos > textLen)
    textLen = pos + insLen;

  // resize the arrays
  m_text.resize (textLen);
  m_attributes.resize (textLen);

  // HA, insert behind text end, fill with spaces
  if (pos >= oldTextLen)
  {
    for (uint z = oldTextLen; z < pos; z++)
    {
      m_text[z] = QChar(' ');
      m_attributes[z] = 0;
    }
  }
  // HA, insert in text, move the old text behind pos
  else if (oldTextLen > 0)
  {
    for (int z = oldTextLen -1; z >= (int) pos; z--)
    {
      m_text[z+insLen] = m_text[z];
      m_attributes[z+insLen] = m_attributes[z];
    }
  }

  // BUH, actually insert the new text
  for (uint z = 0; z < insLen; z++)
  {
    m_text[z+pos] = insText[z];

    if (insAttribs == 0)
      m_attributes[z+pos] = 0;
    else
      m_attributes[z+pos] = insAttribs[z];
  }
}

void TextLine::removeText (uint pos, uint delLen)
{
  // nothing to do
  if (delLen == 0)
    return;

  uint textLen = m_text.size();

  if (textLen == 0)
    return; // uh, again nothing real to do ;)

  if (pos >= textLen)
    return;

  if ((pos + delLen) > textLen)
    delLen = textLen - pos;

  // BU, MOVE THE OLD TEXT AROUND
  for (uint z = pos; z < textLen - delLen; z++)
  {
      m_text[z] = m_text[z+delLen];
      m_attributes[z] = m_attributes[z+delLen];
  }

  // resize the stuff
  if (delLen < textLen)
    textLen -= delLen;
  else // seems to happen when hitting Backspace at the beginning of a line...
    textLen = 0;

  m_text.resize (textLen);
  m_attributes.resize (textLen);
}

void TextLine::append(const QChar *s, uint l)
{
  insertText (m_text.size(), l, s, 0);
}

void TextLine::truncate(uint newLen)
{
  if (newLen < m_text.size())
  {
    m_text.truncate (newLen);
    m_attributes.truncate (newLen);
  }
}

void TextLine::wrap(TextLine::Ptr nextLine, uint pos)
{
  int l = m_text.size() - pos;

  if (l > 0)
  {
    nextLine->insertText (0, l, &m_text[pos], &m_attributes[pos]);
    truncate(pos);
  }
}

void TextLine::unWrap(uint pos, TextLine::Ptr nextLine, uint len)
{
  insertText (pos, len, nextLine->m_text.data(), nextLine->m_attributes.data());
  nextLine->removeText (0, len);
}

int TextLine::nextNonSpaceChar(uint pos) const
{
    for(int i = pos; i < (int)m_text.size(); i++) {
        if(!m_text[i].isSpace())
            return i;
    }
    return -1;
}

int TextLine::previousNonSpaceChar(uint pos) const
{
    if(pos >= m_text.size()) {
        pos = m_text.size() - 1;
    }

    for(int i = pos; i >= 0; i--) {
        if(!m_text[i].isSpace())
            return i;
    }
    return -1;
}

int TextLine::firstChar() const
{
  return nextNonSpaceChar(0);
}

int TextLine::lastChar() const
{
    return previousNonSpaceChar(m_text.size() - 1);
}

QString TextLine::string (uint startCol, uint length) const
{
  if ( startCol >= m_text.size() )
    return QString ();

  if ( (startCol + length) > m_text.size())
    length = m_text.size() - startCol;

  return QString (m_text.data() + startCol, length);
}

void TextLine::removeSpaces()
{
  truncate(lastChar() + 1);
}

QChar *TextLine::firstNonSpace() const
{
  int first = firstChar();
  return (first > -1) ? &m_text[first] : m_text.data();
}

bool TextLine::stringAtPos(uint pos, const QString& match) const
{
  return (QConstString (this->m_text.data(), this->m_text.size()).string().mid(pos, match.length()) == match);
}

bool TextLine::startingWith(const QString& match) const
{
  return (QConstString (this->m_text.data(), this->m_text.size()).string().left(match.length()) == match);
}

bool TextLine::endingWith(const QString& match) const
{
  return (QConstString (this->m_text.data(), this->m_text.size()).string().right(match.length()) == match);
}

int TextLine::cursorX(uint pos, uint tabChars) const
{
  int l, x, z;

  l = (pos < m_text.size()) ? pos : m_text.size();
  x = 0;
  for (z = 0; z < l; z++) {
    if (m_text[z] == QChar('\t')) x += tabChars - (x % tabChars); else x++;
  }
  x += pos - l;
  return x;
}

void TextLine::setAttribs(uchar attribute, uint start, uint end) {
  uint z;

  if (end > m_text.size()) end = m_text.size();
  for (z = start; z < end; z++) m_attributes[z] = attribute;
}

bool TextLine::searchText (uint startCol, const QString &text, uint *foundAtCol, uint *matchLen, bool casesensitive, bool backwards)
{
  int index;

  if (backwards)
    index = QConstString (this->m_text.data(), this->m_text.size()).string().findRev (text, startCol, casesensitive);
  else
    index = QConstString (this->m_text.data(), this->m_text.size()).string().find (text, startCol, casesensitive);

   if (index > -1)
	{
	  (*foundAtCol) = index;
		(*matchLen)=text.length();
		return true;
  }

  return false;
}

bool TextLine::searchText (uint startCol, const QRegExp &regexp, uint *foundAtCol, uint *matchLen, bool backwards)
{
  int index;

  if (backwards)
    index = regexp.searchRev (QConstString (this->m_text.data(), this->m_text.size()).string(), startCol);
  else
    index = regexp.search (QConstString (this->m_text.data(), this->m_text.size()).string(), startCol);

   if (index > -1)
	{
	  (*foundAtCol) = index;
		(*matchLen)=regexp.matchedLength();
		return true;
  }

  return false;
}

uint TextLine::dumpSize () const
{
  uint attributesLen = 0;

  if ( ! m_attributes.isEmpty())
  {
    attributesLen = 1;

    uint lastAttrib = m_attributes[0];

    for (uint z=0; z < m_attributes.size(); z++)
    {
      if (m_attributes[z] != lastAttrib)
      {
        attributesLen++;
        lastAttrib = m_attributes[z];
      }
    }
  }

  return (4*sizeof(uint)) + (m_text.size()*sizeof(QChar)) + (attributesLen * sizeof(uchar)) + (attributesLen * sizeof(uint)) + 1 + (m_ctx.size() * sizeof(uint)) + (m_foldingList.size() * sizeof(signed char));
}

char *TextLine::dump (char *buf) const
{
  uint l = m_text.size();
  uint lctx = m_ctx.size();
  uint lfold = m_foldingList.size();

  memcpy(buf, &l, sizeof(uint));
  buf += sizeof(uint);

  memcpy(buf, (char *) m_text.data(), sizeof(QChar)*l);
  buf += sizeof(QChar)*l;

  memcpy(buf, (char *) &m_flags, 1);
  buf += 1;

  char *attribLenPos = buf;
  buf += sizeof(uint);

  memcpy(buf, &lctx, sizeof(uint));
  buf += sizeof(uint);

  memcpy(buf, &lfold, sizeof(uint));
  buf += sizeof(uint);

  // hl size runlength encoding START

  uint attributesLen = 0;

  if ( ! m_attributes.isEmpty() )
  {
    attributesLen = 1;

    uchar lastAttrib = m_attributes[0];
    uint lastStart = 0;
    uint length = 0;

    for (uint z=0; z < m_attributes.size(); z++)
    {
      if (m_attributes[z] != lastAttrib)
      {
        length = z - lastStart;

        memcpy(buf, &lastAttrib, sizeof(uchar));
        buf += sizeof(uchar);

        memcpy(buf, &length, sizeof(uint));
        buf += sizeof(uint);

        lastStart = z;
        lastAttrib = m_attributes[z];

        attributesLen ++;
      }
    }

    length = m_attributes.size() - lastStart;

    memcpy(buf, &lastAttrib, sizeof(uchar));
    buf += sizeof(uchar);

    memcpy(buf, &length, sizeof(uint));
    buf += sizeof(uint);
  }

  memcpy(attribLenPos, &attributesLen, sizeof(uint));

  // hl size runlength encoding STOP

  memcpy(buf, (char *)m_ctx.data(), sizeof(uint) * lctx);
  buf += sizeof (uint) * lctx;

  memcpy(buf, (char *)m_foldingList.data(), lfold);
  buf += sizeof (signed char) * lfold;

  return buf;
}

char *TextLine::restore (char *buf)
{
  uint l = 0;
  uint lattrib = 0;
  uint lctx = 0;
  uint lfold = 0;

  // text + context length read
  memcpy((char *) &l, buf, sizeof(uint));
  buf += sizeof(uint);

  // text + attributes
  m_text.duplicate ((QChar *) buf, l);
  buf += sizeof(QChar)*l;

  m_attributes.resize (l);

  memcpy((char *) &m_flags, buf, 1);
  buf += 1;

  // we just restore a TextLine from a buffer first time
  if (m_flags == TextLine::flagNoOtherData)
  {
    m_flags = TextLine::flagVisible;
    m_attributes.fill (0);

    return buf;
  }

  memcpy((char *) &lattrib, buf, sizeof(uint));
  buf += sizeof(uint);

  memcpy((char *) &lctx, buf, sizeof(uint));
  buf += sizeof(uint);

  memcpy((char *) &lfold, buf, sizeof(uint));
  buf += sizeof(uint);

  // hl size runlength encoding START

  uchar *attr = m_attributes.data();

  uchar attrib = 0;
  uint length = 0;
  uint pos = 0;

  for (uint z=0; z < lattrib; z++)
  {
    if (pos >= m_attributes.size())
      break;

    memcpy((char *) &attrib, buf, sizeof(uchar));
    buf += sizeof(uchar);

    memcpy((char *) &length, buf, sizeof(uint));
    buf += sizeof(uint);

    if ((pos+length) > m_attributes.size())
      length = m_attributes.size() - pos;

    memset (attr, attrib, length);

    pos += length;
    attr += length;
  }

  // hl size runlength encoding STOP

  m_ctx.duplicate ((uint *) buf, lctx);
  buf += sizeof(uint) * lctx;

  m_foldingList.duplicate ((signed char *) buf, lfold);
  buf += lfold;

  return buf;
}

<|endoftext|>


<commit_before>// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/globals.h"
#if defined(TARGET_ARCH_ARM64)

#include "vm/cpu.h"
#include "vm/cpu_arm64.h"

#include "vm/cpuinfo.h"
#include "vm/simulator.h"

#if !defined(USING_SIMULATOR)
#if !defined(HOST_OS_FUCHSIA)
#include <sys/syscall.h> /* NOLINT */
#endif
#include <unistd.h> /* NOLINT */
#endif

namespace dart {

void CPU::FlushICache(uword start, uword size) {
#if HOST_OS_IOS
  // Precompilation never patches code so there should be no I cache flushes.
  UNREACHABLE();
#endif

#if !defined(USING_SIMULATOR) && !HOST_OS_IOS
  // Nothing to do. Flushing no instructions.
  if (size == 0) {
    return;
  }

// ARM recommends using the gcc intrinsic __clear_cache on Linux and Android.
// blogs.arm.com/software-enablement/141-caches-and-self-modifying-code/
#if defined(HOST_OS_ANDROID) || defined(HOST_OS_FUCHSIA) ||                    \
    defined(HOST_OS_LINUX)
  extern void __clear_cache(char*, char*);
  char* beg = reinterpret_cast<char*>(start);
  char* end = reinterpret_cast<char*>(start + size);
  ::__clear_cache(beg, end);
#else
#error FlushICache only tested/supported on Android, Fuchsia, and Linux
#endif

#endif
}

const char* CPU::Id() {
  return
#if defined(USING_SIMULATOR)
      "sim"
#endif  // !defined(HOST_ARCH_ARM64)
      "arm64";
}

const char* HostCPUFeatures::hardware_ = NULL;
#if defined(DEBUG)
bool HostCPUFeatures::initialized_ = false;
#endif

#if !defined(USING_SIMULATOR)
void HostCPUFeatures::InitOnce() {
  CpuInfo::InitOnce();
  hardware_ = CpuInfo::GetCpuModel();
#if defined(DEBUG)
  initialized_ = true;
#endif
}

void HostCPUFeatures::Cleanup() {
  DEBUG_ASSERT(initialized_);
#if defined(DEBUG)
  initialized_ = false;
#endif
  ASSERT(hardware_ != NULL);
  free(const_cast<char*>(hardware_));
  hardware_ = NULL;
  CpuInfo::Cleanup();
}

#else  // !defined(USING_SIMULATOR)

void HostCPUFeatures::InitOnce() {
  CpuInfo::InitOnce();
  hardware_ = CpuInfo::GetCpuModel();
#if defined(DEBUG)
  initialized_ = true;
#endif
}

void HostCPUFeatures::Cleanup() {
  DEBUG_ASSERT(initialized_);
#if defined(DEBUG)
  initialized_ = false;
#endif
  ASSERT(hardware_ != NULL);
  free(const_cast<char*>(hardware_));
  hardware_ = NULL;
  CpuInfo::Cleanup();
}
#endif  // !defined(USING_SIMULATOR)

}  // namespace dart

#endif  // defined TARGET_ARCH_ARM64
<commit_msg>[fuchsia, arm64] Use mx_cache_flush instead of removed __clear_cache.<commit_after>// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/globals.h"
#if defined(TARGET_ARCH_ARM64)

#include "vm/cpu.h"
#include "vm/cpu_arm64.h"

#include "vm/cpuinfo.h"
#include "vm/simulator.h"

#if !defined(USING_SIMULATOR)
#if !defined(HOST_OS_FUCHSIA)
#include <sys/syscall.h>
#else
#include <magenta/syscalls.h>
#endif
#include <unistd.h>
#endif

namespace dart {

void CPU::FlushICache(uword start, uword size) {
#if HOST_OS_IOS
  // Precompilation never patches code so there should be no I cache flushes.
  UNREACHABLE();
#endif

#if !defined(USING_SIMULATOR) && !HOST_OS_IOS
  // Nothing to do. Flushing no instructions.
  if (size == 0) {
    return;
  }

// ARM recommends using the gcc intrinsic __clear_cache on Linux and Android.
// blogs.arm.com/software-enablement/141-caches-and-self-modifying-code/
#if defined(HOST_OS_ANDROID) || defined(HOST_OS_LINUX)
  extern void __clear_cache(char*, char*);
  char* beg = reinterpret_cast<char*>(start);
  char* end = reinterpret_cast<char*>(start + size);
  ::__clear_cache(beg, end);
#elif defined(HOST_OS_FUCHSIA)
  mx_status_t result = mx_cache_flush(reinterpret_cast<const void*>(start),
                                      size, MX_CACHE_FLUSH_INSN);
  ASSERT(result == MX_OK);
#else
#error FlushICache only tested/supported on Android, Fuchsia, and Linux
#endif

#endif
}

const char* CPU::Id() {
  return
#if defined(USING_SIMULATOR)
      "sim"
#endif  // !defined(HOST_ARCH_ARM64)
      "arm64";
}

const char* HostCPUFeatures::hardware_ = NULL;
#if defined(DEBUG)
bool HostCPUFeatures::initialized_ = false;
#endif

#if !defined(USING_SIMULATOR)
void HostCPUFeatures::InitOnce() {
  CpuInfo::InitOnce();
  hardware_ = CpuInfo::GetCpuModel();
#if defined(DEBUG)
  initialized_ = true;
#endif
}

void HostCPUFeatures::Cleanup() {
  DEBUG_ASSERT(initialized_);
#if defined(DEBUG)
  initialized_ = false;
#endif
  ASSERT(hardware_ != NULL);
  free(const_cast<char*>(hardware_));
  hardware_ = NULL;
  CpuInfo::Cleanup();
}

#else  // !defined(USING_SIMULATOR)

void HostCPUFeatures::InitOnce() {
  CpuInfo::InitOnce();
  hardware_ = CpuInfo::GetCpuModel();
#if defined(DEBUG)
  initialized_ = true;
#endif
}

void HostCPUFeatures::Cleanup() {
  DEBUG_ASSERT(initialized_);
#if defined(DEBUG)
  initialized_ = false;
#endif
  ASSERT(hardware_ != NULL);
  free(const_cast<char*>(hardware_));
  hardware_ = NULL;
  CpuInfo::Cleanup();
}
#endif  // !defined(USING_SIMULATOR)

}  // namespace dart

#endif  // defined TARGET_ARCH_ARM64
<|endoftext|>


<commit_before>#include "WebSocketConnection.h"
#include "Misc.h"
#include "Cryptography.h"
#include "DataStream.h"
#include <mutex>
#include <cstring>
#include <stdexcept>

using namespace Utilities;
using namespace Utilities::Net;
using namespace std;

WebSocketConnection::WebSocketConnection(TCPServer* server, Socket& socket) : TCPConnection(server, socket) {
	this->messageLength = 0;
	this->ready = false;
}

WebSocketConnection::~WebSocketConnection() {

}

void WebSocketConnection::doHandshake() {
	uint16 i, start, end;
	DataStream keyAndMagic;
	DataStream response;
	uint8 hash[Cryptography::SHA1_LENGTH];
	string base64;
	bool found;

	this->bytesReceived = static_cast<uint16>(this->connection.read(this->buffer + this->bytesReceived, TCPConnection::MESSAGE_MAX_SIZE - this->bytesReceived));

	if (this->bytesReceived == 0) {
		TCPConnection::disconnect();
		return;
	}

	for (i = 0; i < this->bytesReceived - 19U; i++) {
		if (memcmp("Sec-WebSocket-Key: ", this->buffer + i, 19) == 0) {
			start = i + 19;
			end = start;

			while ((this->buffer[end] != '\r' || this->buffer[end + 1] != '\n') && end < this->bytesReceived)
				end++;

			if (end == this->bytesReceived) {
				TCPConnection::disconnect();
				return;
			}

			found = true;

			break;
		}
		else {
			found = false;
		}
	}

	if (end == this->bytesReceived) {
		TCPConnection::disconnect();
		return;
	}

	keyAndMagic.write(this->buffer + start, end - start);
	keyAndMagic.write("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
	Cryptography::SHA1(keyAndMagic.getBuffer(), 60, hash);
	base64 = Misc::base64Encode(hash, 20);

	response.write("HTTP/1.1 101 Switching Protocols\r\nUpgrade: WebSocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: ");
	response.write(base64.c_str());
	response.write("\r\n\r\n");

	if (this->connection.ensureWrite(response.getBuffer(), response.getLength(), 10) != response.getLength()) {
		TCPConnection::disconnect();
		return;
	}

	this->ready = true;
	this->bytesReceived = 0;
}

MovableList<TCPConnection::Message> WebSocketConnection::read(uint32 messagesToWaitFor) {
	MovableList<TCPConnection::Message> messages;

	do {
		uint8 bytes[2];
		uint8 FIN;
		uint8 RSV1;
		uint8 RSV2;
		uint8 RSV3;
		uint16 opCode;
		uint8 mask;
		uint16 length;
		uint32 i;
		uint16 received;
		uint8 headerEnd;
		uint8 maskBuffer[MASK_BYTES];
		uint8* payloadBuffer;
		uint8* dataBuffer; //used for websocket's framing. The unmasked data from the current frame is copied to the start of Connection.buffer. Connection.messageLength is then used to point to the end of the data copied to the start of Connection.buffer.

		if (this->ready == false) {
			this->doHandshake();
			return messages;
		}

		dataBuffer = this->buffer + this->messageLength;
		received = static_cast<uint16>(this->connection.read(dataBuffer + this->bytesReceived, TCPConnection::MESSAGE_MAX_SIZE - this->bytesReceived - this->messageLength));
		this->bytesReceived += received;

		if (this->bytesReceived == 0) {
			TCPConnection::disconnect();
			messages.insert(Message(true));
			goto error;
		}

		while (this->bytesReceived > 0) {
			if (this->bytesReceived >= 2) {
				bytes[0] = dataBuffer[0];
				bytes[1] = dataBuffer[1];

				headerEnd = 2;

				FIN = bytes[0] >> 7 & 0x1;
				RSV1 = bytes[0] >> 6 & 0x1;
				RSV2 = bytes[0] >> 5 & 0x1;
				RSV3 = bytes[0] >> 4 & 0x1;
				opCode = bytes[0] & 0xF;

				mask = bytes[1] >> 7 & 0x1;
				length = bytes[1] & 0x7F;

				if (mask == false || RSV1 || RSV2 || RSV3) {
					this->disconnect(CloseCodes::ProtocalError);
					messages.insert(Message(true));
					goto error;
				}

				if (length == 126) {
					if (this->bytesReceived < 4) {
						messages.insert(Message(true));
						goto error;
					}
					length = Net::networkToHostInt16(*reinterpret_cast<uint16*>(dataBuffer + 2));
					headerEnd += 2;
				}
				else if (length == 127) { //we don't support messages this big
					this->disconnect(CloseCodes::MessageTooBig);
					messages.insert(Message(true));
					goto error;
				}

				switch ((OpCodes)opCode) { //ping is handled by the application, not websocket
					case OpCodes::Text:
						this->disconnect(CloseCodes::InvalidDataType);
						messages.insert(Message(true));
						goto error;
					case OpCodes::Close:
						this->disconnect(CloseCodes::Normal);
						messages.insert(Message(true));
						goto error;
					case OpCodes::Pong:
						headerEnd += mask ? MASK_BYTES : 0;
						this->bytesReceived -= headerEnd;
						dataBuffer = this->buffer + headerEnd;
						continue;
					case OpCodes::Ping:
						if (length <= 125) {
							bytes[0] = 128 | static_cast<uint8>(OpCodes::Pong);
							if (this->connection.ensureWrite(bytes, 2, 10) != 2 || this->connection.ensureWrite(dataBuffer + headerEnd, length + 4, 10) != length + 4) {
								TCPConnection::disconnect();
								messages.insert(Message(true));
								goto error;
							}
							headerEnd += mask ? MASK_BYTES : 0;
							this->bytesReceived -= headerEnd;
							dataBuffer = this->buffer + headerEnd;
							continue;
						}
						else {
							this->disconnect(CloseCodes::MessageTooBig);
							messages.insert(Message(true));
							goto error;
						}
					case OpCodes::Continuation:
					case OpCodes::Binary:
						memcpy(maskBuffer, dataBuffer + headerEnd, MASK_BYTES);
						headerEnd += MASK_BYTES;
						payloadBuffer = dataBuffer + headerEnd;

						this->bytesReceived -= length + headerEnd;
						for (i = 0; i < length; i++)
							dataBuffer[i] = payloadBuffer[i] ^ maskBuffer[i % MASK_BYTES];

						if (FIN) {
							messages.insert(Message(this->buffer, this->messageLength + length));
							memcpy(this->buffer, this->buffer + length + headerEnd, this->bytesReceived);
							dataBuffer = this->buffer;
							this->messageLength = 0;
						}
						else {
							this->messageLength += length;
							dataBuffer = this->buffer + this->messageLength;
							memcpy(dataBuffer, payloadBuffer + length, this->bytesReceived);
						}
						continue;
					default:
						this->disconnect(CloseCodes::ProtocalError);
						messages.insert(Message(true));
						goto error;
				}
			}
		}
	} while (messages.getCount() < messagesToWaitFor);

	error:
		return messages;
}

bool WebSocketConnection::send(const uint8* data, uint16 length) {
	return this->send(data, length, OpCodes::Binary);
}

bool WebSocketConnection::send(const uint8* data, uint16 length, OpCodes opCode) {
	uint8 bytes[4];
	uint8 sendLength;

	bytes[0] = 128 | static_cast<uint8>(opCode);
	sendLength = sizeof(length);

	if (length <= 125) {
		bytes[1] = static_cast<uint8>(length);
		*reinterpret_cast<uint16*>(bytes + 2) = 0;
	}
	else {
		bytes[1] = 126;
		sendLength += 2;
		*(reinterpret_cast<uint16*>(bytes + 2)) = Net::hostToNetworkInt16(length);
	}

	if (this->connection.ensureWrite(bytes, sendLength, 10) != sendLength)
		goto sendFailed;
	if (this->connection.ensureWrite(data, length, 10) != length)
		goto sendFailed;

	return true;
sendFailed:
	TCPConnection::disconnect();
	return false;
}

bool WebSocketConnection::sendParts() {
	uint8 bytes[4];
	uint8 sendLength;
	vector<pair<uint8 const*, uint16>>::iterator i;
	uint32 totalLength = 0;

	for (i = this->messageParts.begin(); i != this->messageParts.end(); i++)
		totalLength += i->second;

	bytes[0] = 128 | static_cast<uint8>(OpCodes::Binary);
	sendLength = sizeof(uint16);

	if (totalLength <= 125) {
		bytes[1] = (uint8)totalLength;
		*(uint16*)(bytes + 2) = 0;
	}
	else if (totalLength <= 65536) {
		bytes[1] = 126;
		sendLength += 2;
		*(uint16*)(bytes + 2) = Net::hostToNetworkInt16(static_cast<int16>(totalLength));
	}
	else { // we dont support longer messages
		this->disconnect(CloseCodes::MessageTooBig);
		return false;
	}

	if (this->connection.ensureWrite(bytes, sendLength, 10) != sendLength)
		goto sendFailed;

	for (auto i : this->messageParts)
		if (this->connection.ensureWrite(i.first, i.second, 10) != i.second)
			goto sendFailed;

	this->messageParts.clear();

	return true;
sendFailed:
	TCPConnection::disconnect();
	return false;
}

void WebSocketConnection::disconnect(CloseCodes code) {
	this->send(reinterpret_cast<uint8*>(&code), sizeof(uint16), OpCodes::Close);

	TCPConnection::disconnect();
}
<commit_msg>Fixed another warning.<commit_after>#include "WebSocketConnection.h"
#include "Misc.h"
#include "Cryptography.h"
#include "DataStream.h"
#include <mutex>
#include <cstring>
#include <stdexcept>

using namespace Utilities;
using namespace Utilities::Net;
using namespace std;

WebSocketConnection::WebSocketConnection(TCPServer* server, Socket& socket) : TCPConnection(server, socket) {
	this->messageLength = 0;
	this->ready = false;
}

WebSocketConnection::~WebSocketConnection() {

}

void WebSocketConnection::doHandshake() {
	uint16 start = 0, end = 0;
	DataStream keyAndMagic;
	DataStream response;
	uint8 hash[Cryptography::SHA1_LENGTH];
	string base64;
	bool found;

	this->bytesReceived = static_cast<uint16>(this->connection.read(this->buffer + this->bytesReceived, TCPConnection::MESSAGE_MAX_SIZE - this->bytesReceived));

	if (this->bytesReceived == 0) {
		TCPConnection::disconnect();
		return;
	}

	for (uint16 i = 0; i < this->bytesReceived - 19U; i++) {
		if (memcmp("Sec-WebSocket-Key: ", this->buffer + i, 19) == 0) {
			start = i + 19;
			end = start;

			while ((this->buffer[end] != '\r' || this->buffer[end + 1] != '\n') && end < this->bytesReceived)
				end++;

			if (end == this->bytesReceived) {
				TCPConnection::disconnect();
				return;
			}

			found = true;

			break;
		}
		else {
			found = false;
		}
	}

	if (end == this->bytesReceived) {
		TCPConnection::disconnect();
		return;
	}

	keyAndMagic.write(this->buffer + start, end - start);
	keyAndMagic.write("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
	Cryptography::SHA1(keyAndMagic.getBuffer(), 60, hash);
	base64 = Misc::base64Encode(hash, 20);

	response.write("HTTP/1.1 101 Switching Protocols\r\nUpgrade: WebSocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: ");
	response.write(base64.c_str());
	response.write("\r\n\r\n");

	if (this->connection.ensureWrite(response.getBuffer(), response.getLength(), 10) != response.getLength()) {
		TCPConnection::disconnect();
		return;
	}

	this->ready = true;
	this->bytesReceived = 0;
}

MovableList<TCPConnection::Message> WebSocketConnection::read(uint32 messagesToWaitFor) {
	MovableList<TCPConnection::Message> messages;

	do {
		uint8 bytes[2];
		uint8 FIN;
		uint8 RSV1;
		uint8 RSV2;
		uint8 RSV3;
		uint16 opCode;
		uint8 mask;
		uint16 length;
		uint32 i;
		uint16 received;
		uint8 headerEnd;
		uint8 maskBuffer[MASK_BYTES];
		uint8* payloadBuffer;
		uint8* dataBuffer; //used for websocket's framing. The unmasked data from the current frame is copied to the start of Connection.buffer. Connection.messageLength is then used to point to the end of the data copied to the start of Connection.buffer.

		if (this->ready == false) {
			this->doHandshake();
			return messages;
		}

		dataBuffer = this->buffer + this->messageLength;
		received = static_cast<uint16>(this->connection.read(dataBuffer + this->bytesReceived, TCPConnection::MESSAGE_MAX_SIZE - this->bytesReceived - this->messageLength));
		this->bytesReceived += received;

		if (this->bytesReceived == 0) {
			TCPConnection::disconnect();
			messages.insert(Message(true));
			goto error;
		}

		while (this->bytesReceived > 0) {
			if (this->bytesReceived >= 2) {
				bytes[0] = dataBuffer[0];
				bytes[1] = dataBuffer[1];

				headerEnd = 2;

				FIN = bytes[0] >> 7 & 0x1;
				RSV1 = bytes[0] >> 6 & 0x1;
				RSV2 = bytes[0] >> 5 & 0x1;
				RSV3 = bytes[0] >> 4 & 0x1;
				opCode = bytes[0] & 0xF;

				mask = bytes[1] >> 7 & 0x1;
				length = bytes[1] & 0x7F;

				if (mask == false || RSV1 || RSV2 || RSV3) {
					this->disconnect(CloseCodes::ProtocalError);
					messages.insert(Message(true));
					goto error;
				}

				if (length == 126) {
					if (this->bytesReceived < 4) {
						messages.insert(Message(true));
						goto error;
					}
					length = Net::networkToHostInt16(*reinterpret_cast<uint16*>(dataBuffer + 2));
					headerEnd += 2;
				}
				else if (length == 127) { //we don't support messages this big
					this->disconnect(CloseCodes::MessageTooBig);
					messages.insert(Message(true));
					goto error;
				}

				switch ((OpCodes)opCode) { //ping is handled by the application, not websocket
					case OpCodes::Text:
						this->disconnect(CloseCodes::InvalidDataType);
						messages.insert(Message(true));
						goto error;
					case OpCodes::Close:
						this->disconnect(CloseCodes::Normal);
						messages.insert(Message(true));
						goto error;
					case OpCodes::Pong:
						headerEnd += mask ? MASK_BYTES : 0;
						this->bytesReceived -= headerEnd;
						dataBuffer = this->buffer + headerEnd;
						continue;
					case OpCodes::Ping:
						if (length <= 125) {
							bytes[0] = 128 | static_cast<uint8>(OpCodes::Pong);
							if (this->connection.ensureWrite(bytes, 2, 10) != 2 || this->connection.ensureWrite(dataBuffer + headerEnd, length + 4, 10) != length + 4) {
								TCPConnection::disconnect();
								messages.insert(Message(true));
								goto error;
							}
							headerEnd += mask ? MASK_BYTES : 0;
							this->bytesReceived -= headerEnd;
							dataBuffer = this->buffer + headerEnd;
							continue;
						}
						else {
							this->disconnect(CloseCodes::MessageTooBig);
							messages.insert(Message(true));
							goto error;
						}
					case OpCodes::Continuation:
					case OpCodes::Binary:
						memcpy(maskBuffer, dataBuffer + headerEnd, MASK_BYTES);
						headerEnd += MASK_BYTES;
						payloadBuffer = dataBuffer + headerEnd;

						this->bytesReceived -= length + headerEnd;
						for (i = 0; i < length; i++)
							dataBuffer[i] = payloadBuffer[i] ^ maskBuffer[i % MASK_BYTES];

						if (FIN) {
							messages.insert(Message(this->buffer, this->messageLength + length));
							memcpy(this->buffer, this->buffer + length + headerEnd, this->bytesReceived);
							dataBuffer = this->buffer;
							this->messageLength = 0;
						}
						else {
							this->messageLength += length;
							dataBuffer = this->buffer + this->messageLength;
							memcpy(dataBuffer, payloadBuffer + length, this->bytesReceived);
						}
						continue;
					default:
						this->disconnect(CloseCodes::ProtocalError);
						messages.insert(Message(true));
						goto error;
				}
			}
		}
	} while (messages.getCount() < messagesToWaitFor);

	error:
		return messages;
}

bool WebSocketConnection::send(const uint8* data, uint16 length) {
	return this->send(data, length, OpCodes::Binary);
}

bool WebSocketConnection::send(const uint8* data, uint16 length, OpCodes opCode) {
	uint8 bytes[4];
	uint8 sendLength;

	bytes[0] = 128 | static_cast<uint8>(opCode);
	sendLength = sizeof(length);

	if (length <= 125) {
		bytes[1] = static_cast<uint8>(length);
		*reinterpret_cast<uint16*>(bytes + 2) = 0;
	}
	else {
		bytes[1] = 126;
		sendLength += 2;
		*(reinterpret_cast<uint16*>(bytes + 2)) = Net::hostToNetworkInt16(length);
	}

	if (this->connection.ensureWrite(bytes, sendLength, 10) != sendLength)
		goto sendFailed;
	if (this->connection.ensureWrite(data, length, 10) != length)
		goto sendFailed;

	return true;
sendFailed:
	TCPConnection::disconnect();
	return false;
}

bool WebSocketConnection::sendParts() {
	uint8 bytes[4];
	uint8 sendLength;
	vector<pair<uint8 const*, uint16>>::iterator i;
	uint32 totalLength = 0;

	for (i = this->messageParts.begin(); i != this->messageParts.end(); i++)
		totalLength += i->second;

	bytes[0] = 128 | static_cast<uint8>(OpCodes::Binary);
	sendLength = sizeof(uint16);

	if (totalLength <= 125) {
		bytes[1] = (uint8)totalLength;
		*(uint16*)(bytes + 2) = 0;
	}
	else if (totalLength <= 65536) {
		bytes[1] = 126;
		sendLength += 2;
		*(uint16*)(bytes + 2) = Net::hostToNetworkInt16(static_cast<int16>(totalLength));
	}
	else { // we dont support longer messages
		this->disconnect(CloseCodes::MessageTooBig);
		return false;
	}

	if (this->connection.ensureWrite(bytes, sendLength, 10) != sendLength)
		goto sendFailed;

	for (auto i : this->messageParts)
		if (this->connection.ensureWrite(i.first, i.second, 10) != i.second)
			goto sendFailed;

	this->messageParts.clear();

	return true;
sendFailed:
	TCPConnection::disconnect();
	return false;
}

void WebSocketConnection::disconnect(CloseCodes code) {
	this->send(reinterpret_cast<uint8*>(&code), sizeof(uint16), OpCodes::Close);

	TCPConnection::disconnect();
}
<|endoftext|>


<commit_before>/// @file hdm_serialize_action.cpp
/// @brief Implementation of hdm save & load functions called by clients
/// @author uentity
/// @version
/// @date 30.01.2012
/// @copyright This source code is released under the terms of
///            the BSD License. See LICENSE for more details.

#include "bs_bos_core_data_storage_stdafx.h"

#include "hdm_serialize.h"
#include "bs_misc.h"
#include <fstream>
#include <sstream>

// save to and load from text archives
#include <boost/archive/polymorphic_text_iarchive.hpp>
#include <boost/archive/polymorphic_text_oarchive.hpp>
#include <boost/python.hpp>

// path separator
#ifdef UNIX
#define PATHSEP '/'
#else
#define PATHSEP '\\'
#endif

// extension of file with hdm dump
#define HDM_DUMP_EXT ".hdm"

namespace boarch = boost::archive;
namespace boser = boost::serialization;
namespace bp = boost::python;

namespace blue_sky {

// helper that allows to manually set project path and name for serialization process
// invoke with empty strings to clear kernel table
// returns prev content of kernel table
// pass 3 empty strs to clear kernel table
std::vector< std::string > hdm_serialize_set_project_prop(
	const std::string& prj_path = "",
	const std::string& prj_name = "",
	const std::string& deep_copy_suffix = ""
) {
	// save project path for serialization code
	kernel::idx_dt_ptr p_dt = BS_KERNEL.pert_idx_dt(hdm::bs_type());
	// save existing contents of kernel table
	ulong sz = p_dt->size< std::string >();
	std::vector< std::string > prev_tbl(sz);
	for(ulong i = 0; i < sz; ++i)
		prev_tbl[i] = p_dt->ss< std::string >(i);

	// clear kernel table to not confuse with further saves
	p_dt->clear< std::string >();

	// remember project path
	if(prj_path.size() > 0 || prj_name.size() > 0)
		p_dt->insert< std::string >(prj_path);
	// and project name
	if(prj_name.size() > 0 || deep_copy_suffix.size() > 0)
		p_dt->insert< std::string >(prj_name);
	// and deep copy suffix
	if(deep_copy_suffix.size() > 0) {
		p_dt->insert< std::string >(deep_copy_suffix);
	}

	return prev_tbl;
}

void hdm_serialize_restore_project_prop(const std::vector< std::string >& prev_tbl) {
	kernel::idx_dt_ptr p_dt = BS_KERNEL.pert_idx_dt(hdm::bs_type());
	p_dt->clear< std::string >();
	for(ulong i = 0; i < prev_tbl.size(); ++i)
		p_dt->insert< std::string >(prev_tbl[i]);
}

// hidden implementation details
namespace  {

template< class dst_stream >
dst_stream& hdm_serialize_save_impl(
	dst_stream& f,
	smart_ptr< hdm > t,
	const std::string& prj_path,
	const std::string& prj_name,
	const std::string& deep_copy_suffix
){
	// setup paths
	std::vector< std::string > prev_tbl = hdm_serialize_set_project_prop(
		prj_path, prj_name, deep_copy_suffix
	);

	// make archive
	try {
		boarch::polymorphic_text_oarchive oa(f);
		oa << t;
	}
	catch(const bs_exception& e) {
		BSERR << std::string("Error during hdm_serialize_save: ") + e.what() << bs_end;
	}
	catch(const std::exception& e) {
		BSERR << std::string("Error during hdm_serialize_save: ") + e.what() << bs_end;
	}
	catch(...) {
		BSERR << "Unknown error during hdm_serialize_save!" << bs_end;
		// clear kernel table to not confuse with further saves
		hdm_serialize_restore_project_prop(prev_tbl);
		throw;
	}

	// restore kernel table contents
	hdm_serialize_restore_project_prop(prev_tbl);
	return f;
}

template< class src_stream >
smart_ptr< hdm > hdm_serialize_load_impl(
	src_stream& f,
	const std::string& prj_path,
	const std::string& prj_name
){
	// setup paths
	std::vector< std::string > prev_tbl = hdm_serialize_set_project_prop(
		prj_path, prj_name
	);

	// load archive
	// actually need to rethrow all exceptions
	smart_ptr< hdm > t;
	try {
		boarch::polymorphic_text_iarchive ia(f);
		ia >> t;
	}
	catch(const bs_exception& e) {
		BSERR << std::string("Error during hdm_serialize_load: ") + e.what() << bs_end;
		// clear kernel table
		hdm_serialize_restore_project_prop(prev_tbl);
		throw;
		//t = BS_KERNEL.create_object(hdm::bs_type());
		//t.release();
	}
	catch(const std::exception& e) {
		BSERR << std::string("Error during hdm_serialize_load: ") + e.what() << bs_end;
		// clear kernel table
		hdm_serialize_restore_project_prop(prev_tbl);
		throw;
		//t = BS_KERNEL.create_object(hdm::bs_type());
		//t.release();
	}
	catch(...) {
		BSERR << "Unknown error during hdm_serialize_save!" << bs_end;
		// clear kernel table
		hdm_serialize_restore_project_prop(prev_tbl);
		throw;
	}

	// restore kernel table contents
	hdm_serialize_restore_project_prop(prev_tbl);
	return t;
}

} /* hidden namespace */

/*-----------------------------------------------------------------
 * save hdm
 *----------------------------------------------------------------*/
void hdm_serialize_save(
	smart_ptr< hdm > t,
	const std::string& prj_path,
	const std::string& prj_name,
	const std::string& deep_copy_suffix
){
//#ifdef UNIX
//	const char* enc_name = "ru_RU.UTF-8";
//#else
//	const char* enc_name = "ru_RU.CP1251";
//#endif
//	std::ofstream f(
//		(wstr2str(prj_path, enc_name) + PATHSEP +
//		wstr2str(prj_name, enc_name) + HDM_DUMP_EXT).c_str()
//	);

	std::ofstream f((prj_path + PATHSEP + prj_name + HDM_DUMP_EXT).c_str());
	hdm_serialize_save_impl(f, t, prj_path, prj_name, deep_copy_suffix);
}

std::string hdm_serialize_to_str(
	smart_ptr< hdm > t,
	const std::string& prj_path,
	const std::string& prj_name,
	const std::string& deep_copy_suffix
){
	std::ostringstream f;
	return hdm_serialize_save_impl(f, t, prj_path, prj_name, deep_copy_suffix).str();
}

/*-----------------------------------------------------------------
 * load hdm
 *----------------------------------------------------------------*/
smart_ptr< hdm > hdm_serialize_load(
	const std::string& prj_path,
	const std::string& prj_name
){
//#ifdef UNIX
//	const char* enc_name = "ru_RU.UTF-8";
//#else
//	const char* enc_name = "ru_RU.CP1251";
//#endif
//	std::ifstream f(
//		(wstr2str(prj_path, enc_name) + PATHSEP +
//		wstr2str(prj_name, enc_name) + HDM_DUMP_EXT).c_str()
//	);
	std::ifstream f((prj_path + PATHSEP + prj_name + HDM_DUMP_EXT).c_str());
	return hdm_serialize_load_impl(f, prj_path, prj_name);
}

smart_ptr< hdm > hdm_serialize_from_str(
	const std::string& hdm_dump,
	const std::string& prj_path,
	const std::string& prj_name
){
	std::istringstream f(hdm_dump);
	return hdm_serialize_load_impl(f, prj_path, prj_name);
}

/*-----------------------------------------------------------------
 * export save & load to python
 *----------------------------------------------------------------*/
BOOST_PYTHON_FUNCTION_OVERLOADS(hdm_serialize_save_overl, hdm_serialize_save, 3, 4)
//BOOST_PYTHON_FUNCTION_OVERLOADS(hdm_serialize_load_overl, hdm_serialize_load, 2, 3)
BOOST_PYTHON_FUNCTION_OVERLOADS(hdm_serialize_to_str_overl, hdm_serialize_to_str, 3, 4)
//BOOST_PYTHON_FUNCTION_OVERLOADS(hdm_serialize_from_str_overl, hdm_serialize_from_str, 3, 4)

BOOST_PYTHON_FUNCTION_OVERLOADS(hdm_serialize_setpprop_overl,
	hdm_serialize_set_project_prop, 0, 3
)

namespace python {

BS_API_PLUGIN void py_export_hdm_serialize() {
	bp::def("hdm_serialize_save", &hdm_serialize_save, hdm_serialize_save_overl());
	bp::def("hdm_serialize_load", &hdm_serialize_load);
    // register pvt to/from str serialization
	bp::def("serialize_to_str", &blue_sky::hdm_serialize_to_str, hdm_serialize_to_str_overl());
	bp::def("serialize_from_str", &blue_sky::hdm_serialize_from_str);

	// export only wide-string version
	bp::def(
		"hdm_serialize_set_project_prop", &hdm_serialize_set_project_prop,
		hdm_serialize_setpprop_overl()
	);
	bp::def(
		"hdm_serialize_restore_project_prop", &blue_sky::hdm_serialize_restore_project_prop
	);
}

} /* python */

} /* blue_sky */
<commit_msg>hdm_serialize: allow empty strings to be put in kernel serailzation params<commit_after>/// @file hdm_serialize_action.cpp
/// @brief Implementation of hdm save & load functions called by clients
/// @author uentity
/// @version
/// @date 30.01.2012
/// @copyright This source code is released under the terms of
///            the BSD License. See LICENSE for more details.

#include "bs_bos_core_data_storage_stdafx.h"

#include "hdm_serialize.h"
#include "bs_misc.h"
#include <fstream>
#include <sstream>

// save to and load from text archives
#include <boost/archive/polymorphic_text_iarchive.hpp>
#include <boost/archive/polymorphic_text_oarchive.hpp>
#include <boost/python.hpp>

// path separator
#ifdef UNIX
#define PATHSEP '/'
#else
#define PATHSEP '\\'
#endif

// extension of file with hdm dump
#define HDM_DUMP_EXT ".hdm"

namespace boarch = boost::archive;
namespace boser = boost::serialization;
namespace bp = boost::python;

namespace blue_sky {

// helper that allows to manually set project path and name for serialization process
// invoke with empty strings to clear kernel table
// returns prev content of kernel table
// pass 3 empty strs to clear kernel table
std::vector< std::string > hdm_serialize_set_project_prop(
	const std::string& prj_path = "",
	const std::string& prj_name = "",
	const std::string& deep_copy_suffix = "",
	bool force = false
) {
	// save project path for serialization code
	kernel::idx_dt_ptr p_dt = BS_KERNEL.pert_idx_dt(hdm::bs_type());
	// save existing contents of kernel table
	ulong sz = p_dt->size< std::string >();
	std::vector< std::string > prev_tbl(sz);
	for(ulong i = 0; i < sz; ++i)
		prev_tbl[i] = p_dt->ss< std::string >(i);

	// clear kernel table to not confuse with further saves
	p_dt->clear< std::string >();

	// remember project path
	if(force || prj_path.size() > 0 || prj_name.size() > 0)
		p_dt->insert< std::string >(prj_path);
	// and project name
	if(force || prj_name.size() > 0 || deep_copy_suffix.size() > 0)
		p_dt->insert< std::string >(prj_name);
	// and deep copy suffix
	if(force || deep_copy_suffix.size() > 0) {
		p_dt->insert< std::string >(deep_copy_suffix);
	}

	return prev_tbl;
}

void hdm_serialize_restore_project_prop(const std::vector< std::string >& prev_tbl) {
	kernel::idx_dt_ptr p_dt = BS_KERNEL.pert_idx_dt(hdm::bs_type());
	p_dt->clear< std::string >();
	for(ulong i = 0; i < prev_tbl.size(); ++i)
		p_dt->insert< std::string >(prev_tbl[i]);
}

// hidden implementation details
namespace  {

template< class dst_stream >
dst_stream& hdm_serialize_save_impl(
	dst_stream& f,
	smart_ptr< hdm > t,
	const std::string& prj_path,
	const std::string& prj_name,
	const std::string& deep_copy_suffix
){
	// setup paths
	std::vector< std::string > prev_tbl = hdm_serialize_set_project_prop(
		prj_path, prj_name, deep_copy_suffix
	);

	// make archive
	try {
		boarch::polymorphic_text_oarchive oa(f);
		oa << t;
	}
	catch(const bs_exception& e) {
		BSERR << std::string("Error during hdm_serialize_save: ") + e.what() << bs_end;
	}
	catch(const std::exception& e) {
		BSERR << std::string("Error during hdm_serialize_save: ") + e.what() << bs_end;
	}
	catch(...) {
		BSERR << "Unknown error during hdm_serialize_save!" << bs_end;
		// clear kernel table to not confuse with further saves
		hdm_serialize_restore_project_prop(prev_tbl);
		throw;
	}

	// restore kernel table contents
	hdm_serialize_restore_project_prop(prev_tbl);
	return f;
}

template< class src_stream >
smart_ptr< hdm > hdm_serialize_load_impl(
	src_stream& f,
	const std::string& prj_path,
	const std::string& prj_name
){
	// setup paths
	std::vector< std::string > prev_tbl = hdm_serialize_set_project_prop(
		prj_path, prj_name
	);

	// load archive
	// actually need to rethrow all exceptions
	smart_ptr< hdm > t;
	try {
		boarch::polymorphic_text_iarchive ia(f);
		ia >> t;
	}
	catch(const bs_exception& e) {
		BSERR << std::string("Error during hdm_serialize_load: ") + e.what() << bs_end;
		// clear kernel table
		hdm_serialize_restore_project_prop(prev_tbl);
		throw;
		//t = BS_KERNEL.create_object(hdm::bs_type());
		//t.release();
	}
	catch(const std::exception& e) {
		BSERR << std::string("Error during hdm_serialize_load: ") + e.what() << bs_end;
		// clear kernel table
		hdm_serialize_restore_project_prop(prev_tbl);
		throw;
		//t = BS_KERNEL.create_object(hdm::bs_type());
		//t.release();
	}
	catch(...) {
		BSERR << "Unknown error during hdm_serialize_save!" << bs_end;
		// clear kernel table
		hdm_serialize_restore_project_prop(prev_tbl);
		throw;
	}

	// restore kernel table contents
	hdm_serialize_restore_project_prop(prev_tbl);
	return t;
}

} /* hidden namespace */

/*-----------------------------------------------------------------
 * save hdm
 *----------------------------------------------------------------*/
void hdm_serialize_save(
	smart_ptr< hdm > t,
	const std::string& prj_path,
	const std::string& prj_name,
	const std::string& deep_copy_suffix
){
//#ifdef UNIX
//	const char* enc_name = "ru_RU.UTF-8";
//#else
//	const char* enc_name = "ru_RU.CP1251";
//#endif
//	std::ofstream f(
//		(wstr2str(prj_path, enc_name) + PATHSEP +
//		wstr2str(prj_name, enc_name) + HDM_DUMP_EXT).c_str()
//	);

	std::ofstream f((prj_path + PATHSEP + prj_name + HDM_DUMP_EXT).c_str());
	hdm_serialize_save_impl(f, t, prj_path, prj_name, deep_copy_suffix);
}

std::string hdm_serialize_to_str(
	smart_ptr< hdm > t,
	const std::string& prj_path,
	const std::string& prj_name,
	const std::string& deep_copy_suffix
){
	std::ostringstream f;
	return hdm_serialize_save_impl(f, t, prj_path, prj_name, deep_copy_suffix).str();
}

/*-----------------------------------------------------------------
 * load hdm
 *----------------------------------------------------------------*/
smart_ptr< hdm > hdm_serialize_load(
	const std::string& prj_path,
	const std::string& prj_name
){
//#ifdef UNIX
//	const char* enc_name = "ru_RU.UTF-8";
//#else
//	const char* enc_name = "ru_RU.CP1251";
//#endif
//	std::ifstream f(
//		(wstr2str(prj_path, enc_name) + PATHSEP +
//		wstr2str(prj_name, enc_name) + HDM_DUMP_EXT).c_str()
//	);
	std::ifstream f((prj_path + PATHSEP + prj_name + HDM_DUMP_EXT).c_str());
	return hdm_serialize_load_impl(f, prj_path, prj_name);
}

smart_ptr< hdm > hdm_serialize_from_str(
	const std::string& hdm_dump,
	const std::string& prj_path,
	const std::string& prj_name
){
	std::istringstream f(hdm_dump);
	return hdm_serialize_load_impl(f, prj_path, prj_name);
}

/*-----------------------------------------------------------------
 * export save & load to python
 *----------------------------------------------------------------*/
BOOST_PYTHON_FUNCTION_OVERLOADS(hdm_serialize_save_overl, hdm_serialize_save, 3, 4)
//BOOST_PYTHON_FUNCTION_OVERLOADS(hdm_serialize_load_overl, hdm_serialize_load, 2, 3)
BOOST_PYTHON_FUNCTION_OVERLOADS(hdm_serialize_to_str_overl, hdm_serialize_to_str, 3, 4)
//BOOST_PYTHON_FUNCTION_OVERLOADS(hdm_serialize_from_str_overl, hdm_serialize_from_str, 3, 4)

BOOST_PYTHON_FUNCTION_OVERLOADS(hdm_serialize_setpprop_overl,
	hdm_serialize_set_project_prop, 0, 4
)

namespace python {

BS_API_PLUGIN void py_export_hdm_serialize() {
	bp::def("hdm_serialize_save", &hdm_serialize_save, hdm_serialize_save_overl());
	bp::def("hdm_serialize_load", &hdm_serialize_load);
    // register pvt to/from str serialization
	bp::def("serialize_to_str", &blue_sky::hdm_serialize_to_str, hdm_serialize_to_str_overl());
	bp::def("serialize_from_str", &blue_sky::hdm_serialize_from_str);

	// export only wide-string version
	bp::def(
		"hdm_serialize_set_project_prop", &hdm_serialize_set_project_prop,
		hdm_serialize_setpprop_overl()
	);
	bp::def(
		"hdm_serialize_restore_project_prop", &blue_sky::hdm_serialize_restore_project_prop
	);
}

} /* python */

} /* blue_sky */
<|endoftext|>


<commit_before>#include "Runtime/Character/CAdditiveBodyState.hpp"

#include "Runtime/CStateManager.hpp"
#include "Runtime/Character/CBodyController.hpp"
#include "Runtime/Character/CAnimTreeNode.hpp"
#include "Runtime/Character/CPASDatabase.hpp"
#include "Runtime/Character/CPASAnimParmData.hpp"

namespace urde {

void CABSAim::Start(CBodyController& bc, CStateManager& mgr) {
  // const CBCAdditiveAimCmd* cmd =
  //    static_cast<const CBCAdditiveAimCmd*>(bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveAim));
  const CPASAnimState* aimState = bc.GetPASDatabase().GetAnimState(22);

  // Left, Right, Up, Down
  for (int i = 0; i < 4; ++i) {
    CPASAnimParmData parms(22, CPASAnimParm::FromEnum(i));
    std::pair<float, s32> best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1);
    x8_anims[i] = best.second;
    x18_angles[i] = zeus::degToRad(aimState->GetAnimParmData(x8_anims[i], 1).GetReal32Value());
  }

  const CAnimData& animData = *bc.GetOwner().GetModelData()->GetAnimationData();
  x28_hWeight = -animData.GetAdditiveAnimationWeight(x8_anims[0]);
  x28_hWeight += animData.GetAdditiveAnimationWeight(x8_anims[1]);
  x30_vWeight = -animData.GetAdditiveAnimationWeight(x8_anims[2]);
  x30_vWeight += animData.GetAdditiveAnimationWeight(x8_anims[3]);

  x4_needsIdle = false;
  if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveIdle))
    x4_needsIdle = true;
}

pas::EAnimationState CABSAim::GetBodyStateTransition(float dt, CBodyController& bc) const {
  if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveReaction))
    return pas::EAnimationState::AdditiveReaction;
  if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveFlinch))
    return pas::EAnimationState::AdditiveFlinch;
  if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveIdle) || x4_needsIdle)
    return pas::EAnimationState::AdditiveIdle;
  return pas::EAnimationState::Invalid;
}

pas::EAnimationState CABSAim::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) {
  const pas::EAnimationState st = GetBodyStateTransition(dt, bc);
  if (st == pas::EAnimationState::Invalid) {
    const zeus::CVector3f& target = bc.GetCommandMgr().GetAdditiveTargetVector();
    if (target.canBeNormalized()) {
      CAnimData& animData = *bc.GetOwner().GetModelData()->GetAnimationData();

      float hAngle = zeus::clamp(-x18_angles[0], std::atan2(target.x(), target.y()), x18_angles[1]);
      hAngle *= 0.63661975f;
      hAngle = zeus::clamp(-3.f, (hAngle - x28_hWeight) * 0.25f / dt, 3.f);
      x2c_hWeightVel += dt * zeus::clamp(-10.f, (hAngle - x2c_hWeightVel) / dt, 10.f);

      float hypotenuse = std::sqrt(target.y() * target.y() + target.x() * target.x());
      float vAngle = zeus::clamp(-x18_angles[3], std::atan2(target.z(), hypotenuse), x18_angles[2]);
      vAngle *= 0.63661975f;
      vAngle = zeus::clamp(-3.f, (vAngle - x30_vWeight) * 0.25f / dt, 3.f);
      x34_vWeightVel += dt * zeus::clamp(-10.f, (vAngle - x34_vWeightVel) / dt, 10.f);

      float newHWeight = dt * x2c_hWeightVel + x28_hWeight;
      if (newHWeight != x28_hWeight) {
        if (std::fabs(x28_hWeight) > 0.f && x28_hWeight * newHWeight <= 0.f)
          animData.DelAdditiveAnimation(x8_anims[x28_hWeight < 0.f ? 0 : 1]);
        float absWeight = std::fabs(newHWeight);
        if (absWeight > 0.f)
          animData.AddAdditiveAnimation(x8_anims[newHWeight < 0.f ? 0 : 1], absWeight, false, false);
      }

      float newVWeight = dt * x34_vWeightVel + x30_vWeight;
      if (newVWeight != x30_vWeight) {
        if (std::fabs(x30_vWeight) > 0.f && x30_vWeight * newVWeight <= 0.f)
          animData.DelAdditiveAnimation(x8_anims[x30_vWeight > 0.f ? 2 : 3]);
        float absWeight = std::fabs(newVWeight);
        if (absWeight > 0.f)
          animData.AddAdditiveAnimation(x8_anims[newVWeight > 0.f ? 2 : 3], absWeight, false, false);
      }

      x28_hWeight = newHWeight;
      x30_vWeight = newVWeight;
    }
  }
  return st;
}

void CABSAim::Shutdown(CBodyController& bc) {
  CAnimData& animData = *bc.GetOwner().GetModelData()->GetAnimationData();

  if (x28_hWeight != 0.f)
    animData.DelAdditiveAnimation(x8_anims[x28_hWeight < 0.f ? 0 : 1]);
  if (x30_vWeight != 0.f)
    animData.DelAdditiveAnimation(x8_anims[x30_vWeight > 0.f ? 2 : 3]);
}

void CABSFlinch::Start(CBodyController& bc, CStateManager& mgr) {
  const CBCAdditiveFlinchCmd* cmd =
      static_cast<const CBCAdditiveFlinchCmd*>(bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveFlinch));
  x4_weight = cmd->GetWeight();

  CPASAnimParmData parms(23);
  std::pair<float, s32> best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1);
  x8_anim = best.second;

  CAnimData& animData = *bc.GetOwner().GetModelData()->GetAnimationData();
  animData.AddAdditiveAnimation(x8_anim, x4_weight, false, true);
}

pas::EAnimationState CABSFlinch::GetBodyStateTransition(float dt, CBodyController& bc) const {
  if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveReaction))
    return pas::EAnimationState::AdditiveReaction;
  return pas::EAnimationState::Invalid;
}

pas::EAnimationState CABSFlinch::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) {
  const pas::EAnimationState st = GetBodyStateTransition(dt, bc);
  if (st == pas::EAnimationState::Invalid) {
    CAnimData& animData = *bc.GetOwner().GetModelData()->GetAnimationData();
    CCharAnimTime rem = animData.GetAdditiveAnimationTree(x8_anim)->VGetTimeRemaining();
    if (std::fabs(rem.GetSeconds()) < 0.00001f)
      return pas::EAnimationState::AdditiveIdle;
  }
  return st;
}

pas::EAnimationState CABSIdle::GetBodyStateTransition(float dt, CBodyController& bc) const {
  if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveReaction))
    return pas::EAnimationState::AdditiveReaction;
  if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveFlinch))
    return pas::EAnimationState::AdditiveFlinch;
  if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveAim))
    return pas::EAnimationState::AdditiveAim;
  return pas::EAnimationState::Invalid;
}

pas::EAnimationState CABSIdle::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) {
  return GetBodyStateTransition(dt, bc);
}

void CABSReaction::Start(CBodyController& bc, CStateManager& mgr) {
  const CBCAdditiveReactionCmd* cmd =
      static_cast<const CBCAdditiveReactionCmd*>(bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveReaction));
  x4_weight = cmd->GetWeight();
  xc_type = cmd->GetType();
  x10_active = cmd->GetIsActive();

  CPASAnimParmData parms(24, CPASAnimParm::FromEnum(s32(xc_type)));
  std::pair<float, s32> best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1);
  x8_anim = best.second;

  if (x8_anim != -1) {
    CAnimData& animData = *bc.GetOwner().GetModelData()->GetAnimationData();
    animData.AddAdditiveAnimation(x8_anim, x4_weight, x10_active, false);
  }
}

pas::EAnimationState CABSReaction::GetBodyStateTransition(float dt, CBodyController& bc) const {
  if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveReaction) && xc_type == pas::EAdditiveReactionType::IceBreakout)
    return pas::EAnimationState::AdditiveReaction;
  return pas::EAnimationState::Invalid;
}

pas::EAnimationState CABSReaction::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) {
  const pas::EAnimationState st = GetBodyStateTransition(dt, bc);
  if (st == pas::EAnimationState::Invalid) {
    if (x8_anim == -1)
      return pas::EAnimationState::AdditiveIdle;

    CAnimData& animData = *bc.GetOwner().GetModelData()->GetAnimationData();
    if (x10_active) {
      if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::StopReaction)) {
        StopAnimation(bc);
        bc.GetOwner().RemoveEmitter();
        return pas::EAnimationState::AdditiveIdle;
      }
    } else {
      if (animData.IsAdditiveAnimationAdded(x8_anim)) {
        CCharAnimTime rem = animData.GetAdditiveAnimationTree(x8_anim)->VGetTimeRemaining();
        if (std::fabs(rem.GetSeconds()) < 0.00001f) {
          StopAnimation(bc);
          return pas::EAnimationState::AdditiveIdle;
        }
      } else {
        return pas::EAnimationState::AdditiveIdle;
      }
    }
  }
  return st;
}

void CABSReaction::StopAnimation(CBodyController& bc) {
  if (x8_anim != -1) {
    CAnimData& animData = *bc.GetOwner().GetModelData()->GetAnimationData();
    animData.DelAdditiveAnimation(x8_anim);
    x8_anim = -1;
  }
}

} // namespace urde
<commit_msg>CAdditiveBodyState: Dehardcode array size<commit_after>#include "Runtime/Character/CAdditiveBodyState.hpp"

#include "Runtime/CStateManager.hpp"
#include "Runtime/Character/CBodyController.hpp"
#include "Runtime/Character/CAnimTreeNode.hpp"
#include "Runtime/Character/CPASDatabase.hpp"
#include "Runtime/Character/CPASAnimParmData.hpp"

namespace urde {

void CABSAim::Start(CBodyController& bc, CStateManager& mgr) {
  // const CBCAdditiveAimCmd* cmd =
  //    static_cast<const CBCAdditiveAimCmd*>(bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveAim));
  const CPASAnimState* aimState = bc.GetPASDatabase().GetAnimState(22);

  // Left, Right, Up, Down
  for (size_t i = 0; i < x8_anims.size(); ++i) {
    const CPASAnimParmData parms(22, CPASAnimParm::FromEnum(s32(i)));
    const std::pair<float, s32> best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1);
    x8_anims[i] = best.second;
    x18_angles[i] = zeus::degToRad(aimState->GetAnimParmData(x8_anims[i], 1).GetReal32Value());
  }

  const CAnimData& animData = *bc.GetOwner().GetModelData()->GetAnimationData();
  x28_hWeight = -animData.GetAdditiveAnimationWeight(x8_anims[0]);
  x28_hWeight += animData.GetAdditiveAnimationWeight(x8_anims[1]);
  x30_vWeight = -animData.GetAdditiveAnimationWeight(x8_anims[2]);
  x30_vWeight += animData.GetAdditiveAnimationWeight(x8_anims[3]);

  x4_needsIdle = false;
  if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveIdle))
    x4_needsIdle = true;
}

pas::EAnimationState CABSAim::GetBodyStateTransition(float dt, CBodyController& bc) const {
  if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveReaction))
    return pas::EAnimationState::AdditiveReaction;
  if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveFlinch))
    return pas::EAnimationState::AdditiveFlinch;
  if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveIdle) || x4_needsIdle)
    return pas::EAnimationState::AdditiveIdle;
  return pas::EAnimationState::Invalid;
}

pas::EAnimationState CABSAim::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) {
  const pas::EAnimationState st = GetBodyStateTransition(dt, bc);
  if (st == pas::EAnimationState::Invalid) {
    const zeus::CVector3f& target = bc.GetCommandMgr().GetAdditiveTargetVector();
    if (target.canBeNormalized()) {
      CAnimData& animData = *bc.GetOwner().GetModelData()->GetAnimationData();

      float hAngle = zeus::clamp(-x18_angles[0], std::atan2(target.x(), target.y()), x18_angles[1]);
      hAngle *= 0.63661975f;
      hAngle = zeus::clamp(-3.f, (hAngle - x28_hWeight) * 0.25f / dt, 3.f);
      x2c_hWeightVel += dt * zeus::clamp(-10.f, (hAngle - x2c_hWeightVel) / dt, 10.f);

      float hypotenuse = std::sqrt(target.y() * target.y() + target.x() * target.x());
      float vAngle = zeus::clamp(-x18_angles[3], std::atan2(target.z(), hypotenuse), x18_angles[2]);
      vAngle *= 0.63661975f;
      vAngle = zeus::clamp(-3.f, (vAngle - x30_vWeight) * 0.25f / dt, 3.f);
      x34_vWeightVel += dt * zeus::clamp(-10.f, (vAngle - x34_vWeightVel) / dt, 10.f);

      float newHWeight = dt * x2c_hWeightVel + x28_hWeight;
      if (newHWeight != x28_hWeight) {
        if (std::fabs(x28_hWeight) > 0.f && x28_hWeight * newHWeight <= 0.f)
          animData.DelAdditiveAnimation(x8_anims[x28_hWeight < 0.f ? 0 : 1]);
        float absWeight = std::fabs(newHWeight);
        if (absWeight > 0.f)
          animData.AddAdditiveAnimation(x8_anims[newHWeight < 0.f ? 0 : 1], absWeight, false, false);
      }

      float newVWeight = dt * x34_vWeightVel + x30_vWeight;
      if (newVWeight != x30_vWeight) {
        if (std::fabs(x30_vWeight) > 0.f && x30_vWeight * newVWeight <= 0.f)
          animData.DelAdditiveAnimation(x8_anims[x30_vWeight > 0.f ? 2 : 3]);
        float absWeight = std::fabs(newVWeight);
        if (absWeight > 0.f)
          animData.AddAdditiveAnimation(x8_anims[newVWeight > 0.f ? 2 : 3], absWeight, false, false);
      }

      x28_hWeight = newHWeight;
      x30_vWeight = newVWeight;
    }
  }
  return st;
}

void CABSAim::Shutdown(CBodyController& bc) {
  CAnimData& animData = *bc.GetOwner().GetModelData()->GetAnimationData();

  if (x28_hWeight != 0.f)
    animData.DelAdditiveAnimation(x8_anims[x28_hWeight < 0.f ? 0 : 1]);
  if (x30_vWeight != 0.f)
    animData.DelAdditiveAnimation(x8_anims[x30_vWeight > 0.f ? 2 : 3]);
}

void CABSFlinch::Start(CBodyController& bc, CStateManager& mgr) {
  const CBCAdditiveFlinchCmd* cmd =
      static_cast<const CBCAdditiveFlinchCmd*>(bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveFlinch));
  x4_weight = cmd->GetWeight();

  CPASAnimParmData parms(23);
  std::pair<float, s32> best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1);
  x8_anim = best.second;

  CAnimData& animData = *bc.GetOwner().GetModelData()->GetAnimationData();
  animData.AddAdditiveAnimation(x8_anim, x4_weight, false, true);
}

pas::EAnimationState CABSFlinch::GetBodyStateTransition(float dt, CBodyController& bc) const {
  if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveReaction))
    return pas::EAnimationState::AdditiveReaction;
  return pas::EAnimationState::Invalid;
}

pas::EAnimationState CABSFlinch::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) {
  const pas::EAnimationState st = GetBodyStateTransition(dt, bc);
  if (st == pas::EAnimationState::Invalid) {
    CAnimData& animData = *bc.GetOwner().GetModelData()->GetAnimationData();
    CCharAnimTime rem = animData.GetAdditiveAnimationTree(x8_anim)->VGetTimeRemaining();
    if (std::fabs(rem.GetSeconds()) < 0.00001f)
      return pas::EAnimationState::AdditiveIdle;
  }
  return st;
}

pas::EAnimationState CABSIdle::GetBodyStateTransition(float dt, CBodyController& bc) const {
  if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveReaction))
    return pas::EAnimationState::AdditiveReaction;
  if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveFlinch))
    return pas::EAnimationState::AdditiveFlinch;
  if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveAim))
    return pas::EAnimationState::AdditiveAim;
  return pas::EAnimationState::Invalid;
}

pas::EAnimationState CABSIdle::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) {
  return GetBodyStateTransition(dt, bc);
}

void CABSReaction::Start(CBodyController& bc, CStateManager& mgr) {
  const CBCAdditiveReactionCmd* cmd =
      static_cast<const CBCAdditiveReactionCmd*>(bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveReaction));
  x4_weight = cmd->GetWeight();
  xc_type = cmd->GetType();
  x10_active = cmd->GetIsActive();

  CPASAnimParmData parms(24, CPASAnimParm::FromEnum(s32(xc_type)));
  std::pair<float, s32> best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1);
  x8_anim = best.second;

  if (x8_anim != -1) {
    CAnimData& animData = *bc.GetOwner().GetModelData()->GetAnimationData();
    animData.AddAdditiveAnimation(x8_anim, x4_weight, x10_active, false);
  }
}

pas::EAnimationState CABSReaction::GetBodyStateTransition(float dt, CBodyController& bc) const {
  if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveReaction) && xc_type == pas::EAdditiveReactionType::IceBreakout)
    return pas::EAnimationState::AdditiveReaction;
  return pas::EAnimationState::Invalid;
}

pas::EAnimationState CABSReaction::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) {
  const pas::EAnimationState st = GetBodyStateTransition(dt, bc);
  if (st == pas::EAnimationState::Invalid) {
    if (x8_anim == -1)
      return pas::EAnimationState::AdditiveIdle;

    CAnimData& animData = *bc.GetOwner().GetModelData()->GetAnimationData();
    if (x10_active) {
      if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::StopReaction)) {
        StopAnimation(bc);
        bc.GetOwner().RemoveEmitter();
        return pas::EAnimationState::AdditiveIdle;
      }
    } else {
      if (animData.IsAdditiveAnimationAdded(x8_anim)) {
        CCharAnimTime rem = animData.GetAdditiveAnimationTree(x8_anim)->VGetTimeRemaining();
        if (std::fabs(rem.GetSeconds()) < 0.00001f) {
          StopAnimation(bc);
          return pas::EAnimationState::AdditiveIdle;
        }
      } else {
        return pas::EAnimationState::AdditiveIdle;
      }
    }
  }
  return st;
}

void CABSReaction::StopAnimation(CBodyController& bc) {
  if (x8_anim != -1) {
    CAnimData& animData = *bc.GetOwner().GetModelData()->GetAnimationData();
    animData.DelAdditiveAnimation(x8_anim);
    x8_anim = -1;
  }
}

} // namespace urde
<|endoftext|>


<commit_before>#include "Runtime/GuiSys/CHudFreeLookInterface.hpp"

#include "Runtime/GameGlobalObjects.hpp"
#include "Runtime/GuiSys/CGuiFrame.hpp"
#include "Runtime/GuiSys/CGuiModel.hpp"

namespace urde {

CHudFreeLookInterface::CHudFreeLookInterface(CGuiFrame& selHud, EHudType hudType, bool inFreeLook, bool lookControlHeld,
                                             bool lockedOnObj)
: x4_hudType(hudType) {
  x70_24_inFreeLook = inFreeLook;
  x70_25_lookControlHeld = lookControlHeld;
  x70_26_lockedOnObj = lockedOnObj;
  x70_27_visibleDebug = true;
  x70_28_visibleGame = true;
  x6c_lockOnInterp = (lockedOnObj && hudType == EHudType::Scan) ? 0.f : 1.f;

  x74_basewidget_freelookleft = selHud.FindWidget("basewidget_freelookleft");
  x78_model_shieldleft = static_cast<CGuiModel*>(selHud.FindWidget("model_shieldleft"));
  x7c_model_freelookleft = static_cast<CGuiModel*>(selHud.FindWidget("model_freelookleft"));
  x80_basewidget_freelookright = selHud.FindWidget("basewidget_freelookright");
  x84_model_shieldright = static_cast<CGuiModel*>(selHud.FindWidget("model_shieldright"));
  x88_model_freelookright = static_cast<CGuiModel*>(selHud.FindWidget("model_freelookright"));
  x8c_basewidget_outlinesb = selHud.FindWidget("basewidget_outlinesb");

  x8_freeLookLeftXf = x7c_model_freelookleft->GetTransform();
  x38_freeLookRightXf = x88_model_freelookright->GetTransform();

  x78_model_shieldleft->SetDepthWrite(true);
  x84_model_shieldright->SetDepthWrite(true);
}

void CHudFreeLookInterface::Update(float dt) {
  if (x70_24_inFreeLook)
    x68_freeLookInterp = std::min(x68_freeLookInterp + dt / g_tweakGui->GetFreeLookFadeTime(), 1.f);
  else
    x68_freeLookInterp = std::max(0.f, x68_freeLookInterp - dt / g_tweakGui->GetFreeLookFadeTime());

  if (x70_26_lockedOnObj && x4_hudType == EHudType::Scan)
    x6c_lockOnInterp = std::min(x6c_lockOnInterp + 2.f * dt, 1.f);
  else
    x6c_lockOnInterp = std::max(0.f, x6c_lockOnInterp - 2.f * dt);
}

void CHudFreeLookInterface::SetIsVisibleDebug(bool v) {
  x70_27_visibleDebug = v;
  UpdateVisibility();
}

void CHudFreeLookInterface::SetIsVisibleGame(bool v) {
  x70_28_visibleGame = v;
  UpdateVisibility();
}

void CHudFreeLookInterface::UpdateVisibility() {
  bool vis = x70_27_visibleDebug && x70_28_visibleGame;
  x74_basewidget_freelookleft->SetVisibility(vis, ETraversalMode::Children);
  x80_basewidget_freelookright->SetVisibility(vis, ETraversalMode::Children);
  if (vis)
    Update(0.f);
}

void CHudFreeLookInterface::SetFreeLookState(bool inFreeLook, bool lookControlHeld, bool lockedOnObj,
                                             float vertLookAngle) {
  x70_24_inFreeLook = inFreeLook;
  vertLookAngle *= 8.f;
  x70_25_lookControlHeld = lookControlHeld;
  x70_26_lockedOnObj = lockedOnObj;

  x7c_model_freelookleft->SetLocalTransform(x8_freeLookLeftXf * zeus::CTransform::Translate(0.f, 0.f, vertLookAngle));

  x88_model_freelookright->SetLocalTransform(x38_freeLookRightXf *
                                             zeus::CTransform::Translate(0.f, 0.f, vertLookAngle));

  zeus::CColor color = zeus::skWhite;
  float totalInterp = x68_freeLookInterp * (1.f - x6c_lockOnInterp);
  color.a() = totalInterp;
  x74_basewidget_freelookleft->SetColor(color);
  x80_basewidget_freelookright->SetColor(color);

  if (x8c_basewidget_outlinesb) {
    color.a() = 0.7f * totalInterp + 0.3f;
    x8c_basewidget_outlinesb->SetColor(color);
  }

  if (totalInterp == 0.f) {
    x74_basewidget_freelookleft->SetVisibility(false, ETraversalMode::Children);
    x80_basewidget_freelookright->SetVisibility(false, ETraversalMode::Children);
  } else {
    x74_basewidget_freelookleft->SetVisibility(true, ETraversalMode::Children);
    x80_basewidget_freelookright->SetVisibility(true, ETraversalMode::Children);
  }
}

CHudFreeLookInterfaceXRay::CHudFreeLookInterfaceXRay(CGuiFrame& selHud, bool inFreeLook, bool lookControlHeld,
                                                     bool lockedOnObj) {
  x20_inFreeLook = inFreeLook;
  x21_lookControlHeld = lookControlHeld;
  x22_24_visibleDebug = true;
  x22_25_visibleGame = true;
  x24_basewidget_freelook = selHud.FindWidget("basewidget_freelook");
  x28_model_shield = static_cast<CGuiModel*>(selHud.FindWidget("model_shield"));
  x2c_model_freelookleft = static_cast<CGuiModel*>(selHud.FindWidget("model_freelookleft"));
  x30_model_freelookright = static_cast<CGuiModel*>(selHud.FindWidget("model_freelookright"));

  x4_freeLookLeftPos = x2c_model_freelookleft->GetLocalPosition();
  x10_freeLookRightPos = x30_model_freelookright->GetLocalPosition();

  x28_model_shield->SetDepthWrite(true);
}

void CHudFreeLookInterfaceXRay::Update(float dt) {
  if (x20_inFreeLook)
    x1c_freeLookInterp = std::min(x1c_freeLookInterp + dt / g_tweakGui->GetFreeLookFadeTime(), 1.f);
  else
    x1c_freeLookInterp = std::max(0.f, x1c_freeLookInterp - dt / g_tweakGui->GetFreeLookFadeTime());
}

void CHudFreeLookInterfaceXRay::UpdateVisibility() {
  bool vis = x22_24_visibleDebug && x22_25_visibleGame;
  x2c_model_freelookleft->SetVisibility(vis, ETraversalMode::Children);
  x30_model_freelookright->SetVisibility(vis, ETraversalMode::Children);
  if (vis)
    Update(0.f);
}

void CHudFreeLookInterfaceXRay::SetIsVisibleDebug(bool v) {
  x22_24_visibleDebug = v;
  UpdateVisibility();
}

void CHudFreeLookInterfaceXRay::SetIsVisibleGame(bool v) {
  x22_25_visibleGame = v;
  UpdateVisibility();
}

void CHudFreeLookInterfaceXRay::SetFreeLookState(bool inFreeLook, bool lookControlHeld, bool lockedOnObj,
                                                 float vertLookAngle) {
  x2c_model_freelookleft->SetLocalTransform(
      zeus::CTransform(zeus::CMatrix3f::RotateY(vertLookAngle), x4_freeLookLeftPos));
  x30_model_freelookright->SetLocalTransform(
      zeus::CTransform(zeus::CMatrix3f::RotateY(-vertLookAngle), x10_freeLookRightPos));

  zeus::CColor color = zeus::skWhite;
  color.a() = x1c_freeLookInterp;
  x24_basewidget_freelook->SetColor(color);

  if (x1c_freeLookInterp == 0.f)
    x24_basewidget_freelook->SetVisibility(false, ETraversalMode::Children);
  else
    x24_basewidget_freelook->SetVisibility(true, ETraversalMode::Children);
}

} // namespace urde
<commit_msg>CHudFreeLookInterface: Collapse conditional within SetFreeLookState()<commit_after>#include "Runtime/GuiSys/CHudFreeLookInterface.hpp"

#include "Runtime/GameGlobalObjects.hpp"
#include "Runtime/GuiSys/CGuiFrame.hpp"
#include "Runtime/GuiSys/CGuiModel.hpp"

namespace urde {

CHudFreeLookInterface::CHudFreeLookInterface(CGuiFrame& selHud, EHudType hudType, bool inFreeLook, bool lookControlHeld,
                                             bool lockedOnObj)
: x4_hudType(hudType) {
  x70_24_inFreeLook = inFreeLook;
  x70_25_lookControlHeld = lookControlHeld;
  x70_26_lockedOnObj = lockedOnObj;
  x70_27_visibleDebug = true;
  x70_28_visibleGame = true;
  x6c_lockOnInterp = (lockedOnObj && hudType == EHudType::Scan) ? 0.f : 1.f;

  x74_basewidget_freelookleft = selHud.FindWidget("basewidget_freelookleft");
  x78_model_shieldleft = static_cast<CGuiModel*>(selHud.FindWidget("model_shieldleft"));
  x7c_model_freelookleft = static_cast<CGuiModel*>(selHud.FindWidget("model_freelookleft"));
  x80_basewidget_freelookright = selHud.FindWidget("basewidget_freelookright");
  x84_model_shieldright = static_cast<CGuiModel*>(selHud.FindWidget("model_shieldright"));
  x88_model_freelookright = static_cast<CGuiModel*>(selHud.FindWidget("model_freelookright"));
  x8c_basewidget_outlinesb = selHud.FindWidget("basewidget_outlinesb");

  x8_freeLookLeftXf = x7c_model_freelookleft->GetTransform();
  x38_freeLookRightXf = x88_model_freelookright->GetTransform();

  x78_model_shieldleft->SetDepthWrite(true);
  x84_model_shieldright->SetDepthWrite(true);
}

void CHudFreeLookInterface::Update(float dt) {
  if (x70_24_inFreeLook)
    x68_freeLookInterp = std::min(x68_freeLookInterp + dt / g_tweakGui->GetFreeLookFadeTime(), 1.f);
  else
    x68_freeLookInterp = std::max(0.f, x68_freeLookInterp - dt / g_tweakGui->GetFreeLookFadeTime());

  if (x70_26_lockedOnObj && x4_hudType == EHudType::Scan)
    x6c_lockOnInterp = std::min(x6c_lockOnInterp + 2.f * dt, 1.f);
  else
    x6c_lockOnInterp = std::max(0.f, x6c_lockOnInterp - 2.f * dt);
}

void CHudFreeLookInterface::SetIsVisibleDebug(bool v) {
  x70_27_visibleDebug = v;
  UpdateVisibility();
}

void CHudFreeLookInterface::SetIsVisibleGame(bool v) {
  x70_28_visibleGame = v;
  UpdateVisibility();
}

void CHudFreeLookInterface::UpdateVisibility() {
  bool vis = x70_27_visibleDebug && x70_28_visibleGame;
  x74_basewidget_freelookleft->SetVisibility(vis, ETraversalMode::Children);
  x80_basewidget_freelookright->SetVisibility(vis, ETraversalMode::Children);
  if (vis)
    Update(0.f);
}

void CHudFreeLookInterface::SetFreeLookState(bool inFreeLook, bool lookControlHeld, bool lockedOnObj,
                                             float vertLookAngle) {
  x70_24_inFreeLook = inFreeLook;
  vertLookAngle *= 8.f;
  x70_25_lookControlHeld = lookControlHeld;
  x70_26_lockedOnObj = lockedOnObj;

  x7c_model_freelookleft->SetLocalTransform(x8_freeLookLeftXf * zeus::CTransform::Translate(0.f, 0.f, vertLookAngle));

  x88_model_freelookright->SetLocalTransform(x38_freeLookRightXf *
                                             zeus::CTransform::Translate(0.f, 0.f, vertLookAngle));

  zeus::CColor color = zeus::skWhite;
  float totalInterp = x68_freeLookInterp * (1.f - x6c_lockOnInterp);
  color.a() = totalInterp;
  x74_basewidget_freelookleft->SetColor(color);
  x80_basewidget_freelookright->SetColor(color);

  if (x8c_basewidget_outlinesb) {
    color.a() = 0.7f * totalInterp + 0.3f;
    x8c_basewidget_outlinesb->SetColor(color);
  }

  const bool visible = totalInterp != 0.0f;
  x74_basewidget_freelookleft->SetVisibility(visible, ETraversalMode::Children);
  x80_basewidget_freelookright->SetVisibility(visible, ETraversalMode::Children);
}

CHudFreeLookInterfaceXRay::CHudFreeLookInterfaceXRay(CGuiFrame& selHud, bool inFreeLook, bool lookControlHeld,
                                                     bool lockedOnObj) {
  x20_inFreeLook = inFreeLook;
  x21_lookControlHeld = lookControlHeld;
  x22_24_visibleDebug = true;
  x22_25_visibleGame = true;
  x24_basewidget_freelook = selHud.FindWidget("basewidget_freelook");
  x28_model_shield = static_cast<CGuiModel*>(selHud.FindWidget("model_shield"));
  x2c_model_freelookleft = static_cast<CGuiModel*>(selHud.FindWidget("model_freelookleft"));
  x30_model_freelookright = static_cast<CGuiModel*>(selHud.FindWidget("model_freelookright"));

  x4_freeLookLeftPos = x2c_model_freelookleft->GetLocalPosition();
  x10_freeLookRightPos = x30_model_freelookright->GetLocalPosition();

  x28_model_shield->SetDepthWrite(true);
}

void CHudFreeLookInterfaceXRay::Update(float dt) {
  if (x20_inFreeLook)
    x1c_freeLookInterp = std::min(x1c_freeLookInterp + dt / g_tweakGui->GetFreeLookFadeTime(), 1.f);
  else
    x1c_freeLookInterp = std::max(0.f, x1c_freeLookInterp - dt / g_tweakGui->GetFreeLookFadeTime());
}

void CHudFreeLookInterfaceXRay::UpdateVisibility() {
  bool vis = x22_24_visibleDebug && x22_25_visibleGame;
  x2c_model_freelookleft->SetVisibility(vis, ETraversalMode::Children);
  x30_model_freelookright->SetVisibility(vis, ETraversalMode::Children);
  if (vis)
    Update(0.f);
}

void CHudFreeLookInterfaceXRay::SetIsVisibleDebug(bool v) {
  x22_24_visibleDebug = v;
  UpdateVisibility();
}

void CHudFreeLookInterfaceXRay::SetIsVisibleGame(bool v) {
  x22_25_visibleGame = v;
  UpdateVisibility();
}

void CHudFreeLookInterfaceXRay::SetFreeLookState(bool inFreeLook, bool lookControlHeld, bool lockedOnObj,
                                                 float vertLookAngle) {
  x2c_model_freelookleft->SetLocalTransform(
      zeus::CTransform(zeus::CMatrix3f::RotateY(vertLookAngle), x4_freeLookLeftPos));
  x30_model_freelookright->SetLocalTransform(
      zeus::CTransform(zeus::CMatrix3f::RotateY(-vertLookAngle), x10_freeLookRightPos));

  zeus::CColor color = zeus::skWhite;
  color.a() = x1c_freeLookInterp;
  x24_basewidget_freelook->SetColor(color);

  const bool visible = x1c_freeLookInterp != 0.0f;
  x24_basewidget_freelook->SetVisibility(visible, ETraversalMode::Children);
}

} // namespace urde
<|endoftext|>


<commit_before>#include "chrono_parallel/lcp/ChLcpSolverParallel.h"
#include "chrono_parallel/math/ChThrustLinearAlgebra.h"
#include "core/ChSpmatrix.h"
#include "physics/ChBody.h"
using namespace chrono;

ChLcpSolverParallel::ChLcpSolverParallel(ChParallelDataManager* dc)
: data_container(dc)
{
  tolerance = 1e-7;
  record_violation_history = true;
  warm_start = false;
  residual = 0;
  solver = new ChSolverAPGD();
}

ChLcpSolverParallel::~ChLcpSolverParallel()
{
  delete solver;
}

void ChLcpSolverParallel::ComputeMassMatrix()
{
  uint num_bodies = data_container->num_bodies;
  uint num_shafts = data_container->num_shafts;
  uint num_dof = data_container->num_dof;

  const custom_vector<real>& shaft_inr = data_container->host_data.shaft_inr;

  const std::vector<ChBody*> *body_list = data_container->body_list;
  const std::vector<ChLink*> *link_list= data_container->link_list;
  const std::vector<ChPhysicsItem*> *other_physics_list= data_container->other_physics_list;

  const DynamicVector<real>& hf = data_container->host_data.hf;
  const DynamicVector<real>& v = data_container->host_data.v;

  DynamicVector<real>& M_invk = data_container->host_data.M_invk;
  CompressedMatrix<real>& M_inv = data_container->host_data.M_inv;

  clear(M_inv);

  // Each rigid object has 3 mass entries and 9 inertia entries
  // Each shaft has one inertia entry
  M_inv.reserve(num_bodies * 12 + num_shafts * 1);
  // The mass matrix is square and each rigid body has 6 DOF
  // Shafts have one DOF
  M_inv.resize(num_dof, num_dof);

  for (int i = 0; i < num_bodies; i++) {

    if (data_container->host_data.active_data[i]) {
      real inv_mass = 1.0/body_list->at(i)->GetMass();
      ChMatrix33<>&   body_inv_inr = body_list->at(i)->VariablesBody().GetBodyInvInertia();

      M_inv.append(i * 6 + 0, i * 6 + 0, inv_mass);
      M_inv.finalize(i * 6 + 0);
      M_inv.append(i * 6 + 1, i * 6 + 1, inv_mass);
      M_inv.finalize(i * 6 + 1);
      M_inv.append(i * 6 + 2, i * 6 + 2, inv_mass);
      M_inv.finalize(i * 6 + 2);

      M_inv.append(i * 6 + 3, i * 6 + 3, body_inv_inr.GetElement(0, 0));
      M_inv.append(i * 6 + 3, i * 6 + 4, body_inv_inr.GetElement(0, 1));
      M_inv.append(i * 6 + 3, i * 6 + 5, body_inv_inr.GetElement(0, 2));
      M_inv.finalize(i * 6 + 3);
      M_inv.append(i * 6 + 4, i * 6 + 3, body_inv_inr.GetElement(1, 0));
      M_inv.append(i * 6 + 4, i * 6 + 4, body_inv_inr.GetElement(1, 1));
      M_inv.append(i * 6 + 4, i * 6 + 5, body_inv_inr.GetElement(1, 2));
      M_inv.finalize(i * 6 + 4);
      M_inv.append(i * 6 + 5, i * 6 + 3, body_inv_inr.GetElement(2, 0));
      M_inv.append(i * 6 + 5, i * 6 + 4, body_inv_inr.GetElement(2, 1));
      M_inv.append(i * 6 + 5, i * 6 + 5, body_inv_inr.GetElement(2, 2));
      M_inv.finalize(i * 6 + 5);
    }
  }

  for (int i = 0; i < num_shafts; i++) {
    M_inv.append(num_bodies * 6 + i, num_bodies * 6 + i, shaft_inr[i]);
    M_inv.finalize(num_bodies * 6 + i);
  }
  //If this experimental feature is requested compute the real mass matrix
  if(data_container->settings.solver.scale_mass_matrix){

    CompressedMatrix<real>& M = data_container->host_data.M;
    clear(M);

      // Each rigid object has 3 mass entries and 9 inertia entries
      // Each shaft has one inertia entry
      M.reserve(num_bodies * 12 + num_shafts * 1);
      // The mass matrix is square and each rigid body has 6 DOF
      // Shafts have one DOF
      M.resize(num_dof, num_dof);

      for (int i = 0; i < num_bodies; i++) {
        if (data_container->host_data.active_data[i]) {

          real mass = body_list->at(i)->GetMass();
          ChMatrix33<>&   body_inr = body_list->at(i)->VariablesBody().GetBodyInertia();

          M.append(i * 6 + 0, i * 6 + 0, mass);
          M.finalize(i * 6 + 0);
          M.append(i * 6 + 1, i * 6 + 1, mass);
          M.finalize(i * 6 + 1);
          M.append(i * 6 + 2, i * 6 + 2, mass);
          M.finalize(i * 6 + 2);

          M.append(i * 6 + 3, i * 6 + 3, body_inr.GetElement(0, 0));
          M.append(i * 6 + 3, i * 6 + 4, body_inr.GetElement(0, 1));
          M.append(i * 6 + 3, i * 6 + 5, body_inr.GetElement(0, 2));
          M.finalize(i * 6 + 3);
          M.append(i * 6 + 4, i * 6 + 3, body_inr.GetElement(1, 0));
          M.append(i * 6 + 4, i * 6 + 4, body_inr.GetElement(1, 1));
          M.append(i * 6 + 4, i * 6 + 5, body_inr.GetElement(1, 2));
          M.finalize(i * 6 + 4);
          M.append(i * 6 + 5, i * 6 + 3, body_inr.GetElement(2, 0));
          M.append(i * 6 + 5, i * 6 + 4, body_inr.GetElement(2, 1));
          M.append(i * 6 + 5, i * 6 + 5, body_inr.GetElement(2, 2));
          M.finalize(i * 6 + 5);
        }
      }
      for (int i = 0; i < num_shafts; i++) {
        M.append(num_bodies * 6 + i, num_bodies * 6 + i, 1.0/shaft_inr[i]);
        M.finalize(num_bodies * 6 + i);
      }
  }

  M_invk = v + M_inv * hf;
}

void ChLcpSolverParallel::PerformStabilization() {
  DynamicVector<real>& R = data_container->host_data.R;
  DynamicVector<real>& gamma = data_container->host_data.gamma;
  uint& num_unilaterals = data_container->num_unilaterals;
  uint& num_bilaterals = data_container->num_bilaterals;

  if (data_container->settings.solver.max_iteration_bilateral <= 0 || data_container->num_bilaterals <= 0) {
    return;
  }
  blaze::DenseSubvector<DynamicVector<real> > bilateral_rhs = blaze::subvector(R, num_unilaterals, num_bilaterals);
  blaze::DenseSubvector<DynamicVector<real> > bilateral_gamma = blaze::subvector(gamma, num_unilaterals, num_bilaterals);

  data_container->system_timer.start("ChLcpSolverParallel_Stab");
  solver->SolveStab(data_container->settings.solver.max_iteration_bilateral, num_bilaterals, bilateral_rhs, bilateral_gamma);
  data_container->system_timer.stop("ChLcpSolverParallel_Stab");
}
<commit_msg>When filling a sparse Blaze matrix, finalize must be called even for rows without non-zero elements!<commit_after>#include "chrono_parallel/lcp/ChLcpSolverParallel.h"
#include "chrono_parallel/math/ChThrustLinearAlgebra.h"
#include "core/ChSpmatrix.h"
#include "physics/ChBody.h"
using namespace chrono;

ChLcpSolverParallel::ChLcpSolverParallel(ChParallelDataManager* dc)
: data_container(dc)
{
  tolerance = 1e-7;
  record_violation_history = true;
  warm_start = false;
  residual = 0;
  solver = new ChSolverAPGD();
}

ChLcpSolverParallel::~ChLcpSolverParallel()
{
  delete solver;
}

void ChLcpSolverParallel::ComputeMassMatrix()
{
  uint num_bodies = data_container->num_bodies;
  uint num_shafts = data_container->num_shafts;
  uint num_dof = data_container->num_dof;

  const custom_vector<real>& shaft_inr = data_container->host_data.shaft_inr;

  const std::vector<ChBody*> *body_list = data_container->body_list;
  const std::vector<ChLink*> *link_list= data_container->link_list;
  const std::vector<ChPhysicsItem*> *other_physics_list= data_container->other_physics_list;

  const DynamicVector<real>& hf = data_container->host_data.hf;
  const DynamicVector<real>& v = data_container->host_data.v;

  DynamicVector<real>& M_invk = data_container->host_data.M_invk;
  CompressedMatrix<real>& M_inv = data_container->host_data.M_inv;

  clear(M_inv);

  // Each rigid object has 3 mass entries and 9 inertia entries
  // Each shaft has one inertia entry
  M_inv.reserve(num_bodies * 12 + num_shafts * 1);
  // The mass matrix is square and each rigid body has 6 DOF
  // Shafts have one DOF
  M_inv.resize(num_dof, num_dof);

  for (int i = 0; i < num_bodies; i++) {

    if (data_container->host_data.active_data[i]) {
      real inv_mass = 1.0/body_list->at(i)->GetMass();
      ChMatrix33<>&   body_inv_inr = body_list->at(i)->VariablesBody().GetBodyInvInertia();

      M_inv.append(i * 6 + 0, i * 6 + 0, inv_mass);
      M_inv.finalize(i * 6 + 0);
      M_inv.append(i * 6 + 1, i * 6 + 1, inv_mass);
      M_inv.finalize(i * 6 + 1);
      M_inv.append(i * 6 + 2, i * 6 + 2, inv_mass);
      M_inv.finalize(i * 6 + 2);

      M_inv.append(i * 6 + 3, i * 6 + 3, body_inv_inr.GetElement(0, 0));
      M_inv.append(i * 6 + 3, i * 6 + 4, body_inv_inr.GetElement(0, 1));
      M_inv.append(i * 6 + 3, i * 6 + 5, body_inv_inr.GetElement(0, 2));
      M_inv.finalize(i * 6 + 3);
      M_inv.append(i * 6 + 4, i * 6 + 3, body_inv_inr.GetElement(1, 0));
      M_inv.append(i * 6 + 4, i * 6 + 4, body_inv_inr.GetElement(1, 1));
      M_inv.append(i * 6 + 4, i * 6 + 5, body_inv_inr.GetElement(1, 2));
      M_inv.finalize(i * 6 + 4);
      M_inv.append(i * 6 + 5, i * 6 + 3, body_inv_inr.GetElement(2, 0));
      M_inv.append(i * 6 + 5, i * 6 + 4, body_inv_inr.GetElement(2, 1));
      M_inv.append(i * 6 + 5, i * 6 + 5, body_inv_inr.GetElement(2, 2));
      M_inv.finalize(i * 6 + 5);
    } else {
      M_inv.finalize(i * 6 + 0);
      M_inv.finalize(i * 6 + 1);
      M_inv.finalize(i * 6 + 2);
      M_inv.finalize(i * 6 + 3);
      M_inv.finalize(i * 6 + 4);
      M_inv.finalize(i * 6 + 5);
    }
  }

  for (int i = 0; i < num_shafts; i++) {
    M_inv.append(num_bodies * 6 + i, num_bodies * 6 + i, shaft_inr[i]);
    M_inv.finalize(num_bodies * 6 + i);
  }

  //If this experimental feature is requested compute the real mass matrix
  if(data_container->settings.solver.scale_mass_matrix){

    CompressedMatrix<real>& M = data_container->host_data.M;
    clear(M);

      // Each rigid object has 3 mass entries and 9 inertia entries
      // Each shaft has one inertia entry
      M.reserve(num_bodies * 12 + num_shafts * 1);
      // The mass matrix is square and each rigid body has 6 DOF
      // Shafts have one DOF
      M.resize(num_dof, num_dof);

      for (int i = 0; i < num_bodies; i++) {
        if (data_container->host_data.active_data[i]) {
          real mass = body_list->at(i)->GetMass();
          ChMatrix33<>&   body_inr = body_list->at(i)->VariablesBody().GetBodyInertia();

          M.append(i * 6 + 0, i * 6 + 0, mass);
          M.finalize(i * 6 + 0);
          M.append(i * 6 + 1, i * 6 + 1, mass);
          M.finalize(i * 6 + 1);
          M.append(i * 6 + 2, i * 6 + 2, mass);
          M.finalize(i * 6 + 2);

          M.append(i * 6 + 3, i * 6 + 3, body_inr.GetElement(0, 0));
          M.append(i * 6 + 3, i * 6 + 4, body_inr.GetElement(0, 1));
          M.append(i * 6 + 3, i * 6 + 5, body_inr.GetElement(0, 2));
          M.finalize(i * 6 + 3);
          M.append(i * 6 + 4, i * 6 + 3, body_inr.GetElement(1, 0));
          M.append(i * 6 + 4, i * 6 + 4, body_inr.GetElement(1, 1));
          M.append(i * 6 + 4, i * 6 + 5, body_inr.GetElement(1, 2));
          M.finalize(i * 6 + 4);
          M.append(i * 6 + 5, i * 6 + 3, body_inr.GetElement(2, 0));
          M.append(i * 6 + 5, i * 6 + 4, body_inr.GetElement(2, 1));
          M.append(i * 6 + 5, i * 6 + 5, body_inr.GetElement(2, 2));
          M.finalize(i * 6 + 5);
        } else {
          M.finalize(i * 6 + 0);
          M.finalize(i * 6 + 1);
          M.finalize(i * 6 + 2);
          M.finalize(i * 6 + 3);
          M.finalize(i * 6 + 4);
          M.finalize(i * 6 + 5);
        }
      }

      for (int i = 0; i < num_shafts; i++) {
        M.append(num_bodies * 6 + i, num_bodies * 6 + i, 1.0/shaft_inr[i]);
        M.finalize(num_bodies * 6 + i);
      }
  }

  M_invk = v + M_inv * hf;
}

void ChLcpSolverParallel::PerformStabilization() {
  DynamicVector<real>& R = data_container->host_data.R;
  DynamicVector<real>& gamma = data_container->host_data.gamma;
  uint& num_unilaterals = data_container->num_unilaterals;
  uint& num_bilaterals = data_container->num_bilaterals;

  if (data_container->settings.solver.max_iteration_bilateral <= 0 || data_container->num_bilaterals <= 0) {
    return;
  }
  blaze::DenseSubvector<DynamicVector<real> > bilateral_rhs = blaze::subvector(R, num_unilaterals, num_bilaterals);
  blaze::DenseSubvector<DynamicVector<real> > bilateral_gamma = blaze::subvector(gamma, num_unilaterals, num_bilaterals);

  data_container->system_timer.start("ChLcpSolverParallel_Stab");
  solver->SolveStab(data_container->settings.solver.max_iteration_bilateral, num_bilaterals, bilateral_rhs, bilateral_gamma);
  data_container->system_timer.stop("ChLcpSolverParallel_Stab");
}
<|endoftext|>