<commit_before>#include "starlight_game.h"
#include "starlight_input.h"
#include "starlight_log.h"
#include "starlight_generated.h"
#include "starlight_transform.h"
#include "starlight_renderer.h"
#include "starlight_platform.h"
//#include <process.h> // ?
#include <cstdint>
#include <glm/gtc/matrix_transform.hpp>
#include "starlight_glm.h"
#include "imgui.h"

struct Camera {
	float m_fieldOfView = glm::radians(60.0f); // Field of view angle (radians)
	float m_zNear = 0.3f;
	float m_zFar = 1000.0f;
};

static Transform s_player;
static Camera s_camera;
static float s_deltaTime;

int32_t s_mesh;

int32_t CreateCube(renderer::IGraphicsApi* graphicsApi) {
	Vertex vertices[8] =
	{
		{ { -1.0f, -1.0f, -1.0f },{ 0.0f, 0.0f, 0.0f } }, // 0
		{ { -1.0f,  1.0f, -1.0f },{ 0.0f, 1.0f, 0.0f } }, // 1
		{ { 1.0f,  1.0f, -1.0f },{ 1.0f, 1.0f, 0.0f } }, // 2
		{ { 1.0f, -1.0f, -1.0f },{ 1.0f, 0.0f, 0.0f } }, // 3
		{ { -1.0f, -1.0f,  1.0f },{ 0.0f, 0.0f, 1.0f } }, // 4
		{ { -1.0f,  1.0f,  1.0f },{ 0.0f, 1.0f, 1.0f } }, // 5
		{ { 1.0f,  1.0f,  1.0f },{ 1.0f, 1.0f, 1.0f } }, // 6
		{ { 1.0f, -1.0f,  1.0f },{ 1.0f, 0.0f, 1.0f } }  // 7
	};

	int32_t indices[36] =
	{
		0, 1, 2, 0, 2, 3,
		4, 6, 5, 4, 7, 6,
		4, 5, 1, 4, 1, 0,
		3, 2, 6, 3, 6, 7,
		1, 5, 6, 1, 6, 2,
		4, 0, 3, 4, 3, 7
	};

	return graphicsApi->UploadMesh(vertices, _countof(vertices), indices, _countof(indices));
}

void game::Init(renderer::IGraphicsApi* graphicsApi) {
	input::Init();

	LogInfo("Сука блять!");

	s_player.SetPosition(0, 0, -10);

	// Cube
	s_mesh = CreateCube(graphicsApi);

	// Timing
	s_deltaTime = 0.0f;
}

#if 0
void MoveCamera() {
	// TODO: probably need to check if i'm typing something in ImGui or not
	static glm::vec2 lastRotation;
	static glm::vec2 currentRotation;

	if (input::GetKeyDown('M'))
	{
		input::SetMouseGrabbed(!input::IsMouseGrabbed());
	}

	// Reset
	if (input::GetKeyDown('R'))
	{
		currentRotation = lastRotation = { 0, 0 };
		s_player.SetPosition(glm::vec3(0, 0, 0));
		s_player.SetRotation(glm::quat(1, 0, 0, 0));
	}

	if (input::IsMouseGrabbed())
	{
		// Rotation
		const float ROT_SPEED = 0.0025f;
		currentRotation -= ROT_SPEED * input::GetMouseDelta();
		if (currentRotation.y < glm::radians(-89.0f))
		{
			currentRotation.y = glm::radians(-89.0f);
		}
		if (currentRotation.y > glm::radians(89.0f))
		{
			currentRotation.y = glm::radians(89.0f);
		}
		if (currentRotation.x != lastRotation.x || currentRotation.y != lastRotation.y)
		{
			s_player.SetRotation(glm::quat(glm::vec3(currentRotation.y, currentRotation.x, 0.0f)));
			lastRotation = currentRotation;
		}
	}

	// Translation
	const float SPEED = 20.0f;
	glm::vec3 translation(0, 0, 0);
	if (input::GetKey('W'))		translation += s_player.Forward();
	if (input::GetKey('A'))		translation -= s_player.Right();
	if (input::GetKey('S'))		translation -= s_player.Forward();
	if (input::GetKey('D'))		translation += s_player.Right();
	if (input::GetKey(VK_LCONTROL) || input::GetKey('C') || input::GetKey(VK_LSHIFT)) translation -= glm::vec3(0, 1, 0);
	if (input::GetKey(VK_SPACE)) translation += glm::vec3(0, 1, 0);
	if (translation != glm::vec3(0, 0, 0))
	{
		glm::vec3 pos = s_player.GetPosition();
		pos += glm::normalize(translation) * SPEED * s_deltaTime;
		s_player.SetPosition(pos);
		//printf("pos: %.1f, %.1f, %.1f\n", m_player.GetPosition().x, m_player.GetPosition().y, m_player.GetPosition().z);
	}
}
#endif

void game::Update(renderer::IGraphicsApi* graphicsApi) {
	// Timing
	s_deltaTime = platform::CalculateDeltaTime();

	// Begin logic
	input::BeginFrame();
	//MoveCamera(); // TODO
	input::EndFrame();

	bool stay = true;
	ImGui::Begin("Renderer Test", &stay);
	// These calls should be deferred until next frame
	if (ImGui::Button("Load D3D11")) {
		platform::LoadRenderApi(D3D11);
	}
	if (ImGui::Button("Load D3D10")) {
		platform::LoadRenderApi(D3D10);
	}
	ImGui::End();

	// Does not render, but builds display lists
	logger::Render();

	graphicsApi->SetPlayerCameraViewMatrix(s_player.GetViewMatrix());

#if 0
	renderer::SetPerCamera(&s_perCamera);

	auto windowSize = platform::GetWindowSize();
	if (windowSize.x > 0 && windowSize.y > 0) {
		glm::mat4 projectionMatrix = glm::perspectiveFovLH(glm::radians(45.0f), (float)windowSize.x, (float)windowSize.y, 0.1f, 100.0f);
		s_perCamera.view = s_player.GetViewMatrix();
		s_perFrame.projection = projectionMatrix;
		renderer::SetPerFrame(&s_perFrame);

		s_viewport.Width = static_cast<float>(windowSize.x);
		s_viewport.Height = static_cast<float>(windowSize.y);
	}

	//s_perObject.worldMatrix = glm::mat4();
	s_perObject.worldMatrix = glm::translate(glm::vec3(0, 0, 10.0f));
#endif
}

void game::Destroy() {
	// Free dynamic memory used by game here
}
<commit_msg>Remove utf-8 test<commit_after>#include "starlight_game.h"
#include "starlight_input.h"
#include "starlight_log.h"
#include "starlight_generated.h"
#include "starlight_transform.h"
#include "starlight_renderer.h"
#include "starlight_platform.h"
//#include <process.h> // ?
#include <cstdint>
#include <glm/gtc/matrix_transform.hpp>
#include "starlight_glm.h"
#include "imgui.h"

struct Camera {
	float m_fieldOfView = glm::radians(60.0f); // Field of view angle (radians)
	float m_zNear = 0.3f;
	float m_zFar = 1000.0f;
};

static Transform s_player;
static Camera s_camera;
static float s_deltaTime;

int32_t s_mesh;

int32_t CreateCube(renderer::IGraphicsApi* graphicsApi) {
	Vertex vertices[8] =
	{
		{ { -1.0f, -1.0f, -1.0f },{ 0.0f, 0.0f, 0.0f } }, // 0
		{ { -1.0f,  1.0f, -1.0f },{ 0.0f, 1.0f, 0.0f } }, // 1
		{ { 1.0f,  1.0f, -1.0f },{ 1.0f, 1.0f, 0.0f } }, // 2
		{ { 1.0f, -1.0f, -1.0f },{ 1.0f, 0.0f, 0.0f } }, // 3
		{ { -1.0f, -1.0f,  1.0f },{ 0.0f, 0.0f, 1.0f } }, // 4
		{ { -1.0f,  1.0f,  1.0f },{ 0.0f, 1.0f, 1.0f } }, // 5
		{ { 1.0f,  1.0f,  1.0f },{ 1.0f, 1.0f, 1.0f } }, // 6
		{ { 1.0f, -1.0f,  1.0f },{ 1.0f, 0.0f, 1.0f } }  // 7
	};

	int32_t indices[36] =
	{
		0, 1, 2, 0, 2, 3,
		4, 6, 5, 4, 7, 6,
		4, 5, 1, 4, 1, 0,
		3, 2, 6, 3, 6, 7,
		1, 5, 6, 1, 6, 2,
		4, 0, 3, 4, 3, 7
	};

	return graphicsApi->UploadMesh(vertices, _countof(vertices), indices, _countof(indices));
}

void game::Init(renderer::IGraphicsApi* graphicsApi) {
	input::Init();

	s_player.SetPosition(0, 0, -10);

	// Cube
	s_mesh = CreateCube(graphicsApi);

	// Timing
	s_deltaTime = 0.0f;
}

#if 0
void MoveCamera() {
	// TODO: probably need to check if i'm typing something in ImGui or not
	static glm::vec2 lastRotation;
	static glm::vec2 currentRotation;

	if (input::GetKeyDown('M'))
	{
		input::SetMouseGrabbed(!input::IsMouseGrabbed());
	}

	// Reset
	if (input::GetKeyDown('R'))
	{
		currentRotation = lastRotation = { 0, 0 };
		s_player.SetPosition(glm::vec3(0, 0, 0));
		s_player.SetRotation(glm::quat(1, 0, 0, 0));
	}

	if (input::IsMouseGrabbed())
	{
		// Rotation
		const float ROT_SPEED = 0.0025f;
		currentRotation -= ROT_SPEED * input::GetMouseDelta();
		if (currentRotation.y < glm::radians(-89.0f))
		{
			currentRotation.y = glm::radians(-89.0f);
		}
		if (currentRotation.y > glm::radians(89.0f))
		{
			currentRotation.y = glm::radians(89.0f);
		}
		if (currentRotation.x != lastRotation.x || currentRotation.y != lastRotation.y)
		{
			s_player.SetRotation(glm::quat(glm::vec3(currentRotation.y, currentRotation.x, 0.0f)));
			lastRotation = currentRotation;
		}
	}

	// Translation
	const float SPEED = 20.0f;
	glm::vec3 translation(0, 0, 0);
	if (input::GetKey('W'))		translation += s_player.Forward();
	if (input::GetKey('A'))		translation -= s_player.Right();
	if (input::GetKey('S'))		translation -= s_player.Forward();
	if (input::GetKey('D'))		translation += s_player.Right();
	if (input::GetKey(VK_LCONTROL) || input::GetKey('C') || input::GetKey(VK_LSHIFT)) translation -= glm::vec3(0, 1, 0);
	if (input::GetKey(VK_SPACE)) translation += glm::vec3(0, 1, 0);
	if (translation != glm::vec3(0, 0, 0))
	{
		glm::vec3 pos = s_player.GetPosition();
		pos += glm::normalize(translation) * SPEED * s_deltaTime;
		s_player.SetPosition(pos);
		//printf("pos: %.1f, %.1f, %.1f\n", m_player.GetPosition().x, m_player.GetPosition().y, m_player.GetPosition().z);
	}
}
#endif

void game::Update(renderer::IGraphicsApi* graphicsApi) {
	// Timing
	s_deltaTime = platform::CalculateDeltaTime();

	// Begin logic
	input::BeginFrame();
	//MoveCamera(); // TODO
	input::EndFrame();

	bool stay = true;
	ImGui::Begin("Renderer Test", &stay);
	// These calls should be deferred until next frame
	if (ImGui::Button("Load D3D11")) {
		platform::LoadRenderApi(D3D11);
	}
	if (ImGui::Button("Load D3D10")) {
		platform::LoadRenderApi(D3D10);
	}
	ImGui::End();

	// Does not render, but builds display lists
	logger::Render();

	graphicsApi->SetPlayerCameraViewMatrix(s_player.GetViewMatrix());

#if 0
	renderer::SetPerCamera(&s_perCamera);

	auto windowSize = platform::GetWindowSize();
	if (windowSize.x > 0 && windowSize.y > 0) {
		glm::mat4 projectionMatrix = glm::perspectiveFovLH(glm::radians(45.0f), (float)windowSize.x, (float)windowSize.y, 0.1f, 100.0f);
		s_perCamera.view = s_player.GetViewMatrix();
		s_perFrame.projection = projectionMatrix;
		renderer::SetPerFrame(&s_perFrame);

		s_viewport.Width = static_cast<float>(windowSize.x);
		s_viewport.Height = static_cast<float>(windowSize.y);
	}

	//s_perObject.worldMatrix = glm::mat4();
	s_perObject.worldMatrix = glm::translate(glm::vec3(0, 0, 10.0f));
#endif
}

void game::Destroy() {
	// Free dynamic memory used by game here
}
<|endoftext|>


<commit_before>// @(#)root/tree:$Id$
// Author: Marek Biskup   07/06/2005

/*************************************************************************
 * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//
// A Chain Index
//
//////////////////////////////////////////////////////////////////////////

#include "TChainIndex.h"
#include "TChain.h"
#include "TTreeFormula.h"
#include "TTreeIndex.h"
#include "TFile.h"
#include "TError.h"

ClassImp(TChainIndex)

//______________________________________________________________________________
TChainIndex::TChainIndex(): TVirtualIndex()
{
// Default constructor for TChainIndex

   fTree = 0;
   fMajorFormulaParent = fMinorFormulaParent = 0;
}

//______________________________________________________________________________
TChainIndex::TChainIndex(const TTree *T, const char *majorname, const char *minorname)
           : TVirtualIndex()
{
   // Normal constructor for TChainIndex. See TTreeIndex::TTreeIndex for the description of the
   // parameters.
   // The tree must be a TChain.
   // All the index values in the first tree of the chain must be
   // less then any index value in the second one, and so on.
   // If any of those requirements isn't met the object becomes a zombie.
   // If some subtrees don't have indices the indices are created and stored inside this
   // TChainIndex.

   fTree = 0;
   fMajorFormulaParent = fMinorFormulaParent = 0;

   TChain *chain = dynamic_cast<TChain*>(const_cast<TTree*>(T));
   if (!chain) {
      MakeZombie();
      Error("TChainIndex", "Cannot create a TChainIndex."
            " The Tree passed as an argument is not a TChain");
      return;
   }

   fTree               = (TTree*)T;
   fMajorName          = majorname;
   fMinorName          = minorname;
   Int_t i = 0;

   // Go through all the trees and check if they have indeces. If not then build them.
   for (i = 0; i < chain->GetNtrees(); i++) {
      chain->LoadTree((chain->GetTreeOffset())[i]);
      TVirtualIndex *index = chain->GetTree()->GetTreeIndex();

      TChainIndexEntry entry;
      entry.fTreeIndex = 0;

      //if an index already exists, we must check if major/minorname correspond
      //to the major/minor names in this function call
      if (index) {
         if (strcmp(majorname,index->GetMajorName()) || strcmp(minorname,index->GetMinorName())) {
            MakeZombie();
            Error("TChainIndex","Tree in file %s has an index built with majorname=%s and minorname=%s",chain->GetTree()->GetCurrentFile()->GetName(),index->GetMajorName(),index->GetMinorName());
            return;
         }
      }
      if (!index) {
         chain->GetTree()->BuildIndex(majorname, minorname);
         index = chain->GetTree()->GetTreeIndex();
         chain->GetTree()->SetTreeIndex(0);
         entry.fTreeIndex = index;
      }
      if (!index || index->IsZombie() || index->GetN() == 0) {
         DeleteIndices();
         MakeZombie();
         Error("TChainIndex", "Error creating a tree index on a tree in the chain");
         return;
      }

      TTreeIndex *ti_index = dynamic_cast<TTreeIndex*>(index);
      if (ti_index == 0) {
         Error("TChainIndex", "The underlying TTree must have a TTreeIndex but has a %s.",
               index->IsA()->GetName());
         return;
      }

      entry.fMinIndexValue = ti_index->GetIndexValues()[0];
      entry.fMaxIndexValue = ti_index->GetIndexValues()[index->GetN() - 1];
      fEntries.push_back(entry);
   }

   // Check if the indices of different trees are in order. If not then return an error.
   for (i = 0; i < Int_t(fEntries.size() - 1); i++) {
      if (fEntries[i].fMaxIndexValue > fEntries[i+1].fMinIndexValue) {
         DeleteIndices();
         MakeZombie();
         Error("TChainIndex", "The indices in files of this chain aren't sorted.");
      }
   }

}

//______________________________________________________________________________
void TChainIndex::Append(const TVirtualIndex *index, Bool_t delaySort )
{
   // add an index to this chain
   // if delaySort is kFALSE (default) check if the indices of different trees are in order.
   if (index) {
      const TTreeIndex *ti_index = dynamic_cast<const TTreeIndex*>(index);
      if (ti_index == 0) {
         Error("Append", "The given index is not a TTreeIndex but a %s",
               index->IsA()->GetName());
      }

      TChainIndexEntry entry;
      entry.fTreeIndex = 0;
      entry.fMinIndexValue = ti_index->GetIndexValues()[0];
      entry.fMaxIndexValue = ti_index->GetIndexValues()[index->GetN() - 1];
      fEntries.push_back(entry);
   }

   if (!delaySort) {
      // Check if the indices of different trees are in order. If not then return an error.
      for (Int_t i = 0; i < Int_t(fEntries.size() - 1); i++) {
         if (fEntries[i].fMaxIndexValue > fEntries[i+1].fMinIndexValue) {
            DeleteIndices();
            MakeZombie();
            Error("Append", "The indices in files of this chain aren't sorted.");
         }
      }
   }
}

//______________________________________________________________________________
void TChainIndex::DeleteIndices()
{
   // Delete all the indices which were built by this object
   for (unsigned int i = 0; i < fEntries.size(); i++) {
      if (fEntries[i].fTreeIndex) {
         if (fTree->GetTree() && fTree->GetTree()->GetTreeIndex() == fEntries[i].fTreeIndex) {
            fTree->GetTree()->SetTreeIndex(0);
            SafeDelete(fEntries[i].fTreeIndex);
         }
         SafeDelete(fEntries[i].fTreeIndex);
      }
   }
}

//______________________________________________________________________________
TChainIndex::~TChainIndex()
{
   // The destructor.
   DeleteIndices();
   if (fTree && fTree->GetTreeIndex() == this)
      fTree->SetTreeIndex(0);
}

//______________________________________________________________________________
std::pair<TVirtualIndex*, Int_t> TChainIndex::GetSubTreeIndex(Int_t major, Int_t minor) const
{
   // Returns a TVirtualIndex for a tree which holds the entry with the specified
   // major and minor values and the number of that tree.
   // If the index for that tree was created by this object it's set to the tree.
   // The tree index should be later released using ReleaseSubTreeIndex();

   using namespace std;
   if (fEntries.size() == 0) {
      Warning("GetSubTreeIndex", "No subindices in the chain. The chain is probably empty");
      return make_pair(static_cast<TVirtualIndex*>(0), 0);
   }

   Long64_t indexValue = (Long64_t(major) << 31) + minor;

   if (indexValue < fEntries[0].fMinIndexValue) {
      Warning("GetSubTreeIndex", "The index value is less than the smallest index values in subtrees");
      return make_pair(static_cast<TVirtualIndex*>(0), 0);
   }

   Int_t treeNo = fEntries.size() - 1;
   for (unsigned int i = 0; i < fEntries.size() - 1; i++) {
      if (indexValue < fEntries[i+1].fMinIndexValue) {
         treeNo = i;
         break;
      }
   }
   TChain* chain = dynamic_cast<TChain*> (fTree);
   R__ASSERT(chain);
   chain->LoadTree(chain->GetTreeOffset()[treeNo]);
   TVirtualIndex* index =  fTree->GetTree()->GetTreeIndex();
   if (index)
      return make_pair(static_cast<TVirtualIndex*>(index), treeNo);
   else {
      index = fEntries[treeNo].fTreeIndex;
      if (!index) {
         Warning("GetSubTreeIndex", "The tree has no index and the chain index"
                  " doesn't store an index for that tree");
         return make_pair(static_cast<TVirtualIndex*>(0), 0);
      }
      else {
         fTree->GetTree()->SetTreeIndex(index);
         return make_pair(static_cast<TVirtualIndex*>(index), treeNo);
      }
   }
}

//______________________________________________________________________________
void TChainIndex::ReleaseSubTreeIndex(TVirtualIndex* index, int treeNo) const
{
   // Releases the tree index got using GetSubTreeIndex. If the index was
   // created by this object it is removed from the current tree, so that it isn't
   // deleted in its destructor.

   if (fEntries[treeNo].fTreeIndex == index) {
      R__ASSERT(fTree->GetTree()->GetTreeIndex() == index);
      fTree->GetTree()->SetTreeIndex(0);
   }
}

//______________________________________________________________________________
Long64_t TChainIndex::GetEntryNumberFriend(const TTree *parent)
{
   // see TTreeIndex::GetEntryNumberFriend for description

   if (!parent) return -3;
   GetMajorFormulaParent(parent);
   GetMinorFormulaParent(parent);
   if (!fMajorFormulaParent || !fMinorFormulaParent) return -1;
   if (!fMajorFormulaParent->GetNdim() || !fMinorFormulaParent->GetNdim()) {
      // The Tree Index in the friend has a pair majorname,minorname
      // not available in the parent Tree T.
      // if the friend Tree has less entries than the parent, this is an error
      Long64_t pentry = parent->GetReadEntry();
      if (pentry >= fTree->GetEntries()) return -2;
      // otherwise we ignore the Tree Index and return the entry number
      // in the parent Tree.
      return pentry;
   }

   // majorname, minorname exist in the parent Tree
   // we find the current values pair majorv,minorv in the parent Tree
   Double_t majord = fMajorFormulaParent->EvalInstance();
   Double_t minord = fMinorFormulaParent->EvalInstance();
   Long64_t majorv = (Long64_t)majord;
   Long64_t minorv = (Long64_t)minord;
   // we check if this pair exist in the index.
   // if yes, we return the corresponding entry number
   // if not the function returns -1
   return fTree->GetEntryNumberWithIndex(majorv,minorv);
}

//______________________________________________________________________________
Long64_t TChainIndex::GetEntryNumberWithBestIndex(Int_t major, Int_t minor) const
{
   // See TTreeIndex::GetEntryNumberWithBestIndex for details.

   std::pair<TVirtualIndex*, Int_t> indexAndNumber = GetSubTreeIndex(major, minor);
   if (!indexAndNumber.first) {
      Error("GetEntryNumberWithBestIndex","no index found");
      return -1;
   }
   else {
      Long64_t rv = indexAndNumber.first->GetEntryNumberWithBestIndex(major, minor);
      ReleaseSubTreeIndex(indexAndNumber.first, indexAndNumber.second);
      TChain* chain = dynamic_cast<TChain*> (fTree);
      R__ASSERT(chain);
      return rv + chain->GetTreeOffset()[indexAndNumber.second];
   }
}

//______________________________________________________________________________
Long64_t TChainIndex::GetEntryNumberWithIndex(Int_t major, Int_t minor) const
{
   // Returns the entry number with given index values.
   // See TTreeIndex::GetEntryNumberWithIndex for details.

   std::pair<TVirtualIndex*, Int_t> indexAndNumber = GetSubTreeIndex(major, minor);
   if (!indexAndNumber.first) {
      Error("GetEntryNumberWithIndex","no index found");
      return -1;
   }
   else {
      Long64_t rv = indexAndNumber.first->GetEntryNumberWithIndex(major, minor);
      ReleaseSubTreeIndex(indexAndNumber.first, indexAndNumber.second);
      TChain* chain = dynamic_cast<TChain*> (fTree);
      R__ASSERT(chain);
      return rv + chain->GetTreeOffset()[indexAndNumber.second];
   }
}

//______________________________________________________________________________
TTreeFormula *TChainIndex::GetMajorFormulaParent(const TTree *parent)
{
   // return a pointer to the TreeFormula corresponding to the majorname in parent tree T

   if (!fMajorFormulaParent) {
      TTree::TFriendLock friendlock(fTree, TTree::kFindLeaf | TTree::kFindBranch | TTree::kGetBranch | TTree::kGetLeaf);
      fMajorFormulaParent = new TTreeFormula("MajorP",fMajorName.Data(),const_cast<TTree*>(parent));
      fMajorFormulaParent->SetQuickLoad(kTRUE);
   }
   if (fMajorFormulaParent->GetTree() != parent) {
      fMajorFormulaParent->SetTree(const_cast<TTree*>(parent));
      fMajorFormulaParent->UpdateFormulaLeaves();
   }
   return fMajorFormulaParent;
}

//______________________________________________________________________________
TTreeFormula *TChainIndex::GetMinorFormulaParent(const TTree *parent)
{
   // return a pointer to the TreeFormula corresponding to the minorname in parent tree T

   if (!fMinorFormulaParent) {
      // Prevent TTreeFormula from finding any of the branches in our TTree even if it
      // is a friend of the parent TTree.
      TTree::TFriendLock friendlock(fTree, TTree::kFindLeaf | TTree::kFindBranch | TTree::kGetBranch | TTree::kGetLeaf);
      fMinorFormulaParent = new TTreeFormula("MinorP",fMinorName.Data(),const_cast<TTree*>(parent));
      fMinorFormulaParent->SetQuickLoad(kTRUE);
   }
   if (fMinorFormulaParent->GetTree() != parent) {
      fMinorFormulaParent->SetTree(const_cast<TTree*>(parent));
      fMinorFormulaParent->UpdateFormulaLeaves();
   }

   return fMinorFormulaParent;
}

//______________________________________________________________________________
void TChainIndex::UpdateFormulaLeaves(const TTree *parent)
{
   // Updates the parent formulae.
   // Called by TChain::LoadTree when the parent chain changes it's tree.
   if (fMajorFormulaParent) {
      // Prevent TTreeFormula from finding any of the branches in our TTree even if it
      // is a friend of the parent TTree.
      TTree::TFriendLock friendlock(fTree, TTree::kFindLeaf | TTree::kFindBranch | TTree::kGetBranch | TTree::kGetLeaf);
      if (parent) fMajorFormulaParent->SetTree((TTree*)parent);
      fMajorFormulaParent->UpdateFormulaLeaves();
   }
   if (fMinorFormulaParent) {
      if (parent) fMinorFormulaParent->SetTree((TTree*)parent);
      fMinorFormulaParent->UpdateFormulaLeaves();
   }
}

//______________________________________________________________________________
void TChainIndex::SetTree(const TTree *T)
{
   // See TTreeIndex::SetTree.

   R__ASSERT(fTree == 0 || fTree == T || T==0);
}

<commit_msg>Properly handle the case where the requested index is too high. (See http://root.cern.ch/phpBB3/viewtopic.php?p=61833<commit_after>// @(#)root/tree:$Id$
// Author: Marek Biskup   07/06/2005

/*************************************************************************
 * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//
// A Chain Index
//
//////////////////////////////////////////////////////////////////////////

#include "TChainIndex.h"
#include "TChain.h"
#include "TTreeFormula.h"
#include "TTreeIndex.h"
#include "TFile.h"
#include "TError.h"

ClassImp(TChainIndex)

//______________________________________________________________________________
TChainIndex::TChainIndex(): TVirtualIndex()
{
// Default constructor for TChainIndex

   fTree = 0;
   fMajorFormulaParent = fMinorFormulaParent = 0;
}

//______________________________________________________________________________
TChainIndex::TChainIndex(const TTree *T, const char *majorname, const char *minorname)
           : TVirtualIndex()
{
   // Normal constructor for TChainIndex. See TTreeIndex::TTreeIndex for the description of the
   // parameters.
   // The tree must be a TChain.
   // All the index values in the first tree of the chain must be
   // less then any index value in the second one, and so on.
   // If any of those requirements isn't met the object becomes a zombie.
   // If some subtrees don't have indices the indices are created and stored inside this
   // TChainIndex.

   fTree = 0;
   fMajorFormulaParent = fMinorFormulaParent = 0;

   TChain *chain = dynamic_cast<TChain*>(const_cast<TTree*>(T));
   if (!chain) {
      MakeZombie();
      Error("TChainIndex", "Cannot create a TChainIndex."
            " The Tree passed as an argument is not a TChain");
      return;
   }

   fTree               = (TTree*)T;
   fMajorName          = majorname;
   fMinorName          = minorname;
   Int_t i = 0;

   // Go through all the trees and check if they have indeces. If not then build them.
   for (i = 0; i < chain->GetNtrees(); i++) {
      chain->LoadTree((chain->GetTreeOffset())[i]);
      TVirtualIndex *index = chain->GetTree()->GetTreeIndex();

      TChainIndexEntry entry;
      entry.fTreeIndex = 0;

      //if an index already exists, we must check if major/minorname correspond
      //to the major/minor names in this function call
      if (index) {
         if (strcmp(majorname,index->GetMajorName()) || strcmp(minorname,index->GetMinorName())) {
            MakeZombie();
            Error("TChainIndex","Tree in file %s has an index built with majorname=%s and minorname=%s",chain->GetTree()->GetCurrentFile()->GetName(),index->GetMajorName(),index->GetMinorName());
            return;
         }
      }
      if (!index) {
         chain->GetTree()->BuildIndex(majorname, minorname);
         index = chain->GetTree()->GetTreeIndex();
         chain->GetTree()->SetTreeIndex(0);
         entry.fTreeIndex = index;
      }
      if (!index || index->IsZombie() || index->GetN() == 0) {
         DeleteIndices();
         MakeZombie();
         Error("TChainIndex", "Error creating a tree index on a tree in the chain");
         return;
      }

      TTreeIndex *ti_index = dynamic_cast<TTreeIndex*>(index);
      if (ti_index == 0) {
         Error("TChainIndex", "The underlying TTree must have a TTreeIndex but has a %s.",
               index->IsA()->GetName());
         return;
      }

      entry.fMinIndexValue = ti_index->GetIndexValues()[0];
      entry.fMaxIndexValue = ti_index->GetIndexValues()[index->GetN() - 1];
      fEntries.push_back(entry);
   }

   // Check if the indices of different trees are in order. If not then return an error.
   for (i = 0; i < Int_t(fEntries.size() - 1); i++) {
      if (fEntries[i].fMaxIndexValue > fEntries[i+1].fMinIndexValue) {
         DeleteIndices();
         MakeZombie();
         Error("TChainIndex", "The indices in files of this chain aren't sorted.");
      }
   }

}

//______________________________________________________________________________
void TChainIndex::Append(const TVirtualIndex *index, Bool_t delaySort )
{
   // add an index to this chain
   // if delaySort is kFALSE (default) check if the indices of different trees are in order.
   if (index) {
      const TTreeIndex *ti_index = dynamic_cast<const TTreeIndex*>(index);
      if (ti_index == 0) {
         Error("Append", "The given index is not a TTreeIndex but a %s",
               index->IsA()->GetName());
      }

      TChainIndexEntry entry;
      entry.fTreeIndex = 0;
      entry.fMinIndexValue = ti_index->GetIndexValues()[0];
      entry.fMaxIndexValue = ti_index->GetIndexValues()[index->GetN() - 1];
      fEntries.push_back(entry);
   }

   if (!delaySort) {
      // Check if the indices of different trees are in order. If not then return an error.
      for (Int_t i = 0; i < Int_t(fEntries.size() - 1); i++) {
         if (fEntries[i].fMaxIndexValue > fEntries[i+1].fMinIndexValue) {
            DeleteIndices();
            MakeZombie();
            Error("Append", "The indices in files of this chain aren't sorted.");
         }
      }
   }
}

//______________________________________________________________________________
void TChainIndex::DeleteIndices()
{
   // Delete all the indices which were built by this object
   for (unsigned int i = 0; i < fEntries.size(); i++) {
      if (fEntries[i].fTreeIndex) {
         if (fTree->GetTree() && fTree->GetTree()->GetTreeIndex() == fEntries[i].fTreeIndex) {
            fTree->GetTree()->SetTreeIndex(0);
            SafeDelete(fEntries[i].fTreeIndex);
         }
         SafeDelete(fEntries[i].fTreeIndex);
      }
   }
}

//______________________________________________________________________________
TChainIndex::~TChainIndex()
{
   // The destructor.
   DeleteIndices();
   if (fTree && fTree->GetTreeIndex() == this)
      fTree->SetTreeIndex(0);
}

//______________________________________________________________________________
std::pair<TVirtualIndex*, Int_t> TChainIndex::GetSubTreeIndex(Int_t major, Int_t minor) const
{
   // Returns a TVirtualIndex for a tree which holds the entry with the specified
   // major and minor values and the number of that tree.
   // If the index for that tree was created by this object it's set to the tree.
   // The tree index should be later released using ReleaseSubTreeIndex();

   using namespace std;
   if (fEntries.size() == 0) {
      Warning("GetSubTreeIndex", "No subindices in the chain. The chain is probably empty");
      return make_pair(static_cast<TVirtualIndex*>(0), 0);
   }

   Long64_t indexValue = (Long64_t(major) << 31) + minor;

   if (indexValue < fEntries[0].fMinIndexValue) {
      Warning("GetSubTreeIndex", "The index value is less than the smallest index values in subtrees");
      return make_pair(static_cast<TVirtualIndex*>(0), 0);
   }

   Int_t treeNo = fEntries.size() - 1;
   for (unsigned int i = 0; i < fEntries.size() - 1; i++) {
      if (indexValue < fEntries[i+1].fMinIndexValue) {
         treeNo = i;
         break;
      }
   }
   // Double check we found the right range.
   if (0 && indexValue > fEntries[treeNo].fMaxIndexValue) {
      return make_pair(static_cast<TVirtualIndex*>(0), 0);
   }
   TChain* chain = dynamic_cast<TChain*> (fTree);
   R__ASSERT(chain);
   chain->LoadTree(chain->GetTreeOffset()[treeNo]);
   TVirtualIndex* index =  fTree->GetTree()->GetTreeIndex();
   if (index)
      return make_pair(static_cast<TVirtualIndex*>(index), treeNo);
   else {
      index = fEntries[treeNo].fTreeIndex;
      if (!index) {
         Warning("GetSubTreeIndex", "The tree has no index and the chain index"
                  " doesn't store an index for that tree");
         return make_pair(static_cast<TVirtualIndex*>(0), 0);
      }
      else {
         fTree->GetTree()->SetTreeIndex(index);
         return make_pair(static_cast<TVirtualIndex*>(index), treeNo);
      }
   }
}

//______________________________________________________________________________
void TChainIndex::ReleaseSubTreeIndex(TVirtualIndex* index, int treeNo) const
{
   // Releases the tree index got using GetSubTreeIndex. If the index was
   // created by this object it is removed from the current tree, so that it isn't
   // deleted in its destructor.

   if (fEntries[treeNo].fTreeIndex == index) {
      R__ASSERT(fTree->GetTree()->GetTreeIndex() == index);
      fTree->GetTree()->SetTreeIndex(0);
   }
}

//______________________________________________________________________________
Long64_t TChainIndex::GetEntryNumberFriend(const TTree *parent)
{
   // see TTreeIndex::GetEntryNumberFriend for description

   if (!parent) return -3;
   GetMajorFormulaParent(parent);
   GetMinorFormulaParent(parent);
   if (!fMajorFormulaParent || !fMinorFormulaParent) return -1;
   if (!fMajorFormulaParent->GetNdim() || !fMinorFormulaParent->GetNdim()) {
      // The Tree Index in the friend has a pair majorname,minorname
      // not available in the parent Tree T.
      // if the friend Tree has less entries than the parent, this is an error
      Long64_t pentry = parent->GetReadEntry();
      if (pentry >= fTree->GetEntries()) return -2;
      // otherwise we ignore the Tree Index and return the entry number
      // in the parent Tree.
      return pentry;
   }

   // majorname, minorname exist in the parent Tree
   // we find the current values pair majorv,minorv in the parent Tree
   Double_t majord = fMajorFormulaParent->EvalInstance();
   Double_t minord = fMinorFormulaParent->EvalInstance();
   Long64_t majorv = (Long64_t)majord;
   Long64_t minorv = (Long64_t)minord;
   // we check if this pair exist in the index.
   // if yes, we return the corresponding entry number
   // if not the function returns -1
   return fTree->GetEntryNumberWithIndex(majorv,minorv);
}

//______________________________________________________________________________
Long64_t TChainIndex::GetEntryNumberWithBestIndex(Int_t major, Int_t minor) const
{
   // See TTreeIndex::GetEntryNumberWithBestIndex for details.

   std::pair<TVirtualIndex*, Int_t> indexAndNumber = GetSubTreeIndex(major, minor);
   if (!indexAndNumber.first) {
      Error("GetEntryNumberWithBestIndex","no index found");
      return -1;
   }
   else {
      Long64_t rv = indexAndNumber.first->GetEntryNumberWithBestIndex(major, minor);
      ReleaseSubTreeIndex(indexAndNumber.first, indexAndNumber.second);
      TChain* chain = dynamic_cast<TChain*> (fTree);
      R__ASSERT(chain);
      return rv + chain->GetTreeOffset()[indexAndNumber.second];
   }
}

//______________________________________________________________________________
Long64_t TChainIndex::GetEntryNumberWithIndex(Int_t major, Int_t minor) const
{
   // Returns the entry number with given index values.
   // See TTreeIndex::GetEntryNumberWithIndex for details.

   std::pair<TVirtualIndex*, Int_t> indexAndNumber = GetSubTreeIndex(major, minor);
   if (!indexAndNumber.first) {
      Error("GetEntryNumberWithIndex","no index found");
      return -1;
   }
   else {
      Long64_t rv = indexAndNumber.first->GetEntryNumberWithIndex(major, minor);
      ReleaseSubTreeIndex(indexAndNumber.first, indexAndNumber.second);
      TChain* chain = dynamic_cast<TChain*> (fTree);
      R__ASSERT(chain);
      if (rv > 0) {
         return rv + chain->GetTreeOffset()[indexAndNumber.second];
      } else {
         return rv;
      }
   }
}

//______________________________________________________________________________
TTreeFormula *TChainIndex::GetMajorFormulaParent(const TTree *parent)
{
   // return a pointer to the TreeFormula corresponding to the majorname in parent tree T

   if (!fMajorFormulaParent) {
      TTree::TFriendLock friendlock(fTree, TTree::kFindLeaf | TTree::kFindBranch | TTree::kGetBranch | TTree::kGetLeaf);
      fMajorFormulaParent = new TTreeFormula("MajorP",fMajorName.Data(),const_cast<TTree*>(parent));
      fMajorFormulaParent->SetQuickLoad(kTRUE);
   }
   if (fMajorFormulaParent->GetTree() != parent) {
      fMajorFormulaParent->SetTree(const_cast<TTree*>(parent));
      fMajorFormulaParent->UpdateFormulaLeaves();
   }
   return fMajorFormulaParent;
}

//______________________________________________________________________________
TTreeFormula *TChainIndex::GetMinorFormulaParent(const TTree *parent)
{
   // return a pointer to the TreeFormula corresponding to the minorname in parent tree T

   if (!fMinorFormulaParent) {
      // Prevent TTreeFormula from finding any of the branches in our TTree even if it
      // is a friend of the parent TTree.
      TTree::TFriendLock friendlock(fTree, TTree::kFindLeaf | TTree::kFindBranch | TTree::kGetBranch | TTree::kGetLeaf);
      fMinorFormulaParent = new TTreeFormula("MinorP",fMinorName.Data(),const_cast<TTree*>(parent));
      fMinorFormulaParent->SetQuickLoad(kTRUE);
   }
   if (fMinorFormulaParent->GetTree() != parent) {
      fMinorFormulaParent->SetTree(const_cast<TTree*>(parent));
      fMinorFormulaParent->UpdateFormulaLeaves();
   }

   return fMinorFormulaParent;
}

//______________________________________________________________________________
void TChainIndex::UpdateFormulaLeaves(const TTree *parent)
{
   // Updates the parent formulae.
   // Called by TChain::LoadTree when the parent chain changes it's tree.
   if (fMajorFormulaParent) {
      // Prevent TTreeFormula from finding any of the branches in our TTree even if it
      // is a friend of the parent TTree.
      TTree::TFriendLock friendlock(fTree, TTree::kFindLeaf | TTree::kFindBranch | TTree::kGetBranch | TTree::kGetLeaf);
      if (parent) fMajorFormulaParent->SetTree((TTree*)parent);
      fMajorFormulaParent->UpdateFormulaLeaves();
   }
   if (fMinorFormulaParent) {
      if (parent) fMinorFormulaParent->SetTree((TTree*)parent);
      fMinorFormulaParent->UpdateFormulaLeaves();
   }
}

//______________________________________________________________________________
void TChainIndex::SetTree(const TTree *T)
{
   // See TTreeIndex::SetTree.

   R__ASSERT(fTree == 0 || fTree == T || T==0);
}

<|endoftext|>


<commit_before>#include "stdafx.h"
#include "CtrlrLabel.h"
#include "CtrlrUtilitiesGUI.h"
#include "CtrlrLuaManager.h"
#include "JuceClasses/LLookAndFeel.h"

CtrlrLabelInternal::CtrlrLabelInternal(CtrlrLabel &_owner, const String &componentName, const String &labelText)
	: Label (componentName, labelText), owner(_owner)
{
}

TextEditor *CtrlrLabelInternal::createEditorComponent()
{
	TextEditor* const ed = new TextEditor (getName());
	ed->setFont (getFont());
	ed->setInputRestrictions (owner.getProperty(::Ids::uiLabelInputMaxLength), owner.getProperty(::Ids::uiLabelInputAllowedChars));

	const int cols[] = { TextEditor::backgroundColourId,
                       TextEditor::textColourId,
                       TextEditor::highlightColourId,
                       TextEditor::highlightedTextColourId,
                       TextEditor::outlineColourId,
                       TextEditor::focusedOutlineColourId,
                       TextEditor::shadowColourId,
                       CaretComponent::caretColourId };

	for (int i = 0; i < numElementsInArray (cols); ++i)
		ed->setColour (cols[i], findColour (cols[i]));

	return ed;
}

bool CtrlrLabelInternal::keyPressed (const KeyPress &key)
{
	return (false);
}
//[/MiscUserDefs]

//==============================================================================
CtrlrLabel::CtrlrLabel (CtrlrModulator &owner)
    : CtrlrComponent(owner),
      ctrlrLabel (0)
{
    addAndMakeVisible (ctrlrLabel = new CtrlrLabelInternal (*this, "ctrlrLabel",
                                               "label text"));
    ctrlrLabel->setFont (Font (15.0000f, Font::plain));
    ctrlrLabel->setJustificationType (Justification::centredLeft);
    ctrlrLabel->setEditable (false, false, false);
    ctrlrLabel->setColour (TextEditor::textColourId, Colours::black);
    ctrlrLabel->setColour (TextEditor::backgroundColourId, Colour (0x0));

    //[UserPreSize]
	owner.setProperty (Ids::modulatorIsStatic, true);
	owner.setProperty (Ids::modulatorVstExported, false);

	setProperty (Ids::uiLabelBgColour, "0x00000000");
	setProperty (Ids::uiLabelTextColour, "0xff000000");
	setProperty (Ids::uiLabelOutline, 0);
	setProperty (Ids::uiLabelOutlineColour, "0x00000000");
	setProperty (Ids::uiLabelJustification, "centred");
	setProperty (Ids::uiLabelFitFont, false);
	setProperty (Ids::uiLabelFont, FONT2STR (Font(14)));
	setProperty (Ids::uiLabelText, "Label text");
	setProperty (Ids::uiLabelDisplaysAllValues, false);
	setProperty (Ids::uiLabelDisplayFormat, "%n(%N) = %v(%h)");
	setProperty (Ids::uiLabelInputHighlightTextColour, "0xffffffff");
	setProperty (Ids::uiLabelInputHighlightColour, "0xff0000ff");
	setProperty (Ids::uiLabelEditOnSingleClick, false);
	setProperty (Ids::uiLabelEditOnDoubleClick, false);
	setProperty (Ids::uiLabelEditFocusDiscardsChanges, true);
	setProperty (Ids::uiLabelInputAllowedChars, "");
	setProperty (Ids::uiLabelInputAllowedChars, "");
	setProperty (Ids::uiLabelInputMaxLength, 1024);
	setProperty (Ids::uiLabelChangedCbk, COMBO_NONE_ITEM);

	ctrlrLabel->addListener (this);
	componentTree.addListener (this);
    //[/UserPreSize]

    setSize (88, 24);

    //[Constructor] You can add your own custom stuff here..
    //[/Constructor]
}

CtrlrLabel::~CtrlrLabel()
{
    //[Destructor_pre]. You can add your own custom destruction code here..
	owner.getOwnerPanel().removePanelListener(this);
    //[/Destructor_pre]

    deleteAndZero (ctrlrLabel);

    //[Destructor]. You can add your own custom destruction code here..
    //[/Destructor]
}

//==============================================================================
void CtrlrLabel::paint (Graphics& g)
{
    //[UserPrePaint] Add your own custom painting code here..
    //[/UserPrePaint]

    //[UserPaint] Add your own custom painting code here..
	int i = getProperty(Ids::uiLabelOutline);
	g.setColour (VAR2COLOUR(getProperty(Ids::uiLabelBgColour)));
	g.fillRect( i, i, (getWidth() - 2*i), (getHeight() - 2*i));
    g.setColour (VAR2COLOUR(getProperty(Ids::uiLabelOutlineColour)));
	g.drawRect (0, 0, getWidth(), getHeight(),  i);
    //[/UserPaint]
}

void CtrlrLabel::resized()
{
    //ctrlrLabel->setBounds (0, 0, getWidth() - 0, getHeight() - 0);
    //[UserResized] Add your own custom resize handling here..
	if (restoreStateInProgress)
		return;
	if ((bool)ctrlrLabel->getProperties() ["fh"] == true)
	{
		Font f = ctrlrLabel->getFont();
		f.setHeight (getHeight()*0.95f);
		ctrlrLabel->setFont (f);
	}
	ctrlrLabel->setBounds (getUsableRect());
    //[/UserResized]
}

//[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
double CtrlrLabel::getComponentMaxValue()
{
	return (1);
}

void CtrlrLabel::setComponentValue (const double newValue, const bool sendChangeMessage)
{
	if (sendChangeMessage)
	{
		owner.getProcessor().setValueGeneric (CtrlrModulatorValue(newValue,CtrlrModulatorValue::changedByGUI), true);
	}
}

double CtrlrLabel::getComponentValue()
{
	return (1);
}

int CtrlrLabel::getComponentMidiValue()
{
	return (1);
}

void CtrlrLabel::valueTreePropertyChanged (ValueTree &treeWhosePropertyHasChanged, const Identifier &property)
{
	if (property == Ids::uiLabelDisplaysAllValues)
	{
		if ((bool)getProperty(property) == true)
		{
			owner.getOwnerPanel().addPanelListener(this);
		}
		else
		{
			owner.getOwnerPanel().removePanelListener(this);
		}
	}
	else if (property == Ids::uiLabelText)
	{
		ctrlrLabel->setText (getProperty(Ids::uiLabelText), sendNotification);
	}
	else if (property == Ids::uiLabelBgColour)
	{
		ctrlrLabel->setColour (Label::backgroundColourId, VAR2COLOUR(getProperty(Ids::uiLabelBgColour)));
	}
	else if (property == Ids::uiLabelTextColour)
	{
		ctrlrLabel->setColour (Label::textColourId, VAR2COLOUR(getProperty(Ids::uiLabelTextColour)));
		ctrlrLabel->setColour (TextEditor::textColourId, VAR2COLOUR(getProperty(Ids::uiLabelTextColour)));
	}
	else if (property == Ids::uiLabelOutline)
	{
		ctrlrLabel->setBorderSize (BorderSize <int> (getProperty (property)));
		repaint();
	}
	else if (property == Ids::uiLabelOutlineColour)
	{
		ctrlrLabel->setColour (Label::outlineColourId, VAR2COLOUR(getProperty(Ids::uiLabelOutlineColour)));
		repaint();
	}
	else if (property == Ids::uiLabelFitFont || property == Ids::uiLabelFont)
	{
		ctrlrLabel->getProperties().set ("fh", getProperty(Ids::uiLabelFitFont));
		const String t = ctrlrLabel->getText();
		ctrlrLabel->setFont (STR2FONT(getProperty(Ids::uiLabelFont)));
		ctrlrLabel->setText (t, dontSendNotification);
	}
	else if (property == Ids::uiLabelJustification)
	{
		ctrlrLabel->setJustificationType (justificationFromProperty (getProperty(property)));
	}

	else if (property == Ids::uiLabelEditOnSingleClick
		|| property == Ids::uiLabelEditOnDoubleClick
		|| property == Ids::uiLabelEditFocusDiscardsChanges)
	{
		ctrlrLabel->setEditable ((bool)getProperty(Ids::uiLabelEditOnSingleClick),(bool)getProperty(Ids::uiLabelEditOnDoubleClick),(bool)getProperty(Ids::uiLabelEditFocusDiscardsChanges));
	}
	else if (property == Ids::uiLabelChangedCbk)
	{
		if (getProperty(property) == "")
			return;

		labelChangedCbk = owner.getOwnerPanel().getCtrlrLuaManager().getMethodManager().getMethod(getProperty(property));
	}
	else if (property == Ids::uiLabelInputHighlightTextColour || property == Ids::uiLabelInputHighlightColour)
	{
		ctrlrLabel->setColour (TextEditor::highlightColourId, VAR2COLOUR(getProperty(Ids::uiLabelInputHighlightColour)));
		ctrlrLabel->setColour (TextEditor::highlightedTextColourId, VAR2COLOUR(getProperty(Ids::uiLabelInputHighlightTextColour)));
	}
	else
	{
		CtrlrComponent::valueTreePropertyChanged(treeWhosePropertyHasChanged, property);
	}

	if (restoreStateInProgress == false)
	{
		resized();
	}
}

void CtrlrLabel::setComponentText(const String &componentText)
{
	setProperty (Ids::uiLabelText, componentText);
}

const String CtrlrLabel::getComponentText()
{
	return (ctrlrLabel->getText());
}

void CtrlrLabel::modulatorChanged (CtrlrModulator *modulatorThatChanged)
{
	if (modulatorThatChanged == 0 || modulatorThatChanged->getComponent() == 0)
		return;

	if ((bool)modulatorThatChanged->getComponent()->getProperty(Ids::componentExcludedFromLabelDisplay) == true)
		return;

	ctrlrLabel->setText (labelFromProperty (modulatorThatChanged, getProperty (Ids::uiLabelDisplayFormat)), dontSendNotification);
}

void CtrlrLabel::labelTextChanged (Label* labelThatHasChanged)
{
	if (getProperty (Ids::uiLabelText).toString() != labelThatHasChanged->getText())
        setProperty (Ids::uiLabelText, labelThatHasChanged->getText(), false);

	setComponentValue(0, true);

	if (labelChangedCbk && !labelChangedCbk.wasObjectDeleted())
	{
		if (labelChangedCbk->isValid())
		{
			owner.getOwnerPanel().getCtrlrLuaManager().getMethodManager().call (labelChangedCbk, dynamic_cast<CtrlrComponent*>(this), labelThatHasChanged->getText());
		}
	}
}

void CtrlrLabel::lookAndFeelChanged ()
{
}

CtrlrLabel &CtrlrLabel::setLabelText(const String &text)
{
	setProperty (Ids::uiLabelText, text);

	return (*this);
}

CtrlrLabel &CtrlrLabel::appendText(const String &text)
{
	setProperty (Ids::uiLabelText, ctrlrLabel->getText() + text);

	return (*this);
}

const String CtrlrLabel::getText()
{
	return (ctrlrLabel->getText());
}

void CtrlrLabel::customLookAndFeelChanged(LookAndFeelBase *customLookAndFeel)
{
    ctrlrLabel->setLookAndFeel (customLookAndFeel);
}

bool CtrlrLabel::keyPressed (const KeyPress &key)
{
	return (false);
}
//[/MiscUserCode]

//==============================================================================
#if 0
/*  -- Jucer information section --

    This is where the Jucer puts all of its metadata, so don't change anything in here!

BEGIN_JUCER_METADATA

<JUCER_COMPONENT documentType="Component" className="CtrlrLabel" componentName=""
                 parentClasses="public CtrlrComponent, public CtrlrPanel::PanelListener, public Label::Listener"
                 constructorParams="CtrlrModulator &owner" variableInitialisers="CtrlrComponent(owner)"
                 snapPixels="8" snapActive="1" snapShown="1" overlayOpacity="0.330000013"
                 fixedSize="1" initialWidth="88" initialHeight="24">
  <BACKGROUND backgroundColour="0"/>
  <LABEL name="ctrlrLabel" id="409d64ae540e634d" memberName="ctrlrLabel"
         virtualName="" explicitFocusOrder="0" pos="0 0 0M 0M" edTextCol="ff000000"
         edBkgCol="0" labelText="label text" editableSingleClick="0" editableDoubleClick="0"
         focusDiscardsChanges="0" fontname="Default font" fontsize="15"
         bold="0" italic="0" justification="33"/>
</JUCER_COMPONENT>

END_JUCER_METADATA
*/
#endif
<commit_msg>Draw background only when it is visible.<commit_after>#include "stdafx.h"
#include "CtrlrLabel.h"
#include "CtrlrUtilitiesGUI.h"
#include "CtrlrLuaManager.h"
#include "JuceClasses/LLookAndFeel.h"

CtrlrLabelInternal::CtrlrLabelInternal(CtrlrLabel &_owner, const String &componentName, const String &labelText)
	: Label (componentName, labelText), owner(_owner)
{
}

TextEditor *CtrlrLabelInternal::createEditorComponent()
{
	TextEditor* const ed = new TextEditor (getName());
	ed->setFont (getFont());
	ed->setInputRestrictions (owner.getProperty(::Ids::uiLabelInputMaxLength), owner.getProperty(::Ids::uiLabelInputAllowedChars));

	const int cols[] = { TextEditor::backgroundColourId,
                       TextEditor::textColourId,
                       TextEditor::highlightColourId,
                       TextEditor::highlightedTextColourId,
                       TextEditor::outlineColourId,
                       TextEditor::focusedOutlineColourId,
                       TextEditor::shadowColourId,
                       CaretComponent::caretColourId };

	for (int i = 0; i < numElementsInArray (cols); ++i)
		ed->setColour (cols[i], findColour (cols[i]));

	return ed;
}

bool CtrlrLabelInternal::keyPressed (const KeyPress &key)
{
	return (false);
}
//[/MiscUserDefs]

//==============================================================================
CtrlrLabel::CtrlrLabel (CtrlrModulator &owner)
    : CtrlrComponent(owner),
      ctrlrLabel (0)
{
    addAndMakeVisible (ctrlrLabel = new CtrlrLabelInternal (*this, "ctrlrLabel",
                                               "label text"));
    ctrlrLabel->setFont (Font (15.0000f, Font::plain));
    ctrlrLabel->setJustificationType (Justification::centredLeft);
    ctrlrLabel->setEditable (false, false, false);
    ctrlrLabel->setColour (TextEditor::textColourId, Colours::black);
    ctrlrLabel->setColour (TextEditor::backgroundColourId, Colour (0x0));

    //[UserPreSize]
	owner.setProperty (Ids::modulatorIsStatic, true);
	owner.setProperty (Ids::modulatorVstExported, false);

	setProperty (Ids::uiLabelBgColour, "0x00000000");
	setProperty (Ids::uiLabelTextColour, "0xff000000");
	setProperty (Ids::uiLabelOutline, 0);
	setProperty (Ids::uiLabelOutlineColour, "0x00000000");
	setProperty (Ids::uiLabelJustification, "centred");
	setProperty (Ids::uiLabelFitFont, false);
	setProperty (Ids::uiLabelFont, FONT2STR (Font(14)));
	setProperty (Ids::uiLabelText, "Label text");
	setProperty (Ids::uiLabelDisplaysAllValues, false);
	setProperty (Ids::uiLabelDisplayFormat, "%n(%N) = %v(%h)");
	setProperty (Ids::uiLabelInputHighlightTextColour, "0xffffffff");
	setProperty (Ids::uiLabelInputHighlightColour, "0xff0000ff");
	setProperty (Ids::uiLabelEditOnSingleClick, false);
	setProperty (Ids::uiLabelEditOnDoubleClick, false);
	setProperty (Ids::uiLabelEditFocusDiscardsChanges, true);
	setProperty (Ids::uiLabelInputAllowedChars, "");
	setProperty (Ids::uiLabelInputAllowedChars, "");
	setProperty (Ids::uiLabelInputMaxLength, 1024);
	setProperty (Ids::uiLabelChangedCbk, COMBO_NONE_ITEM);

	ctrlrLabel->addListener (this);
	componentTree.addListener (this);
    //[/UserPreSize]

    setSize (88, 24);

    //[Constructor] You can add your own custom stuff here..
    //[/Constructor]
}

CtrlrLabel::~CtrlrLabel()
{
    //[Destructor_pre]. You can add your own custom destruction code here..
	owner.getOwnerPanel().removePanelListener(this);
    //[/Destructor_pre]

    deleteAndZero (ctrlrLabel);

    //[Destructor]. You can add your own custom destruction code here..
    //[/Destructor]
}

//==============================================================================
void CtrlrLabel::paint (Graphics& g)
{
    //[UserPrePaint] Add your own custom painting code here..
    //[/UserPrePaint]

    //[UserPaint] Add your own custom painting code here..
	const int i = getProperty(Ids::uiLabelOutline);
	const int i2 = 2*i;
	g.setColour (VAR2COLOUR(getProperty(Ids::uiLabelBgColour)));
	// the background may be completely overpainted:
	if (getWidth() > i2 && getHeight() > i2)
	    g.fillRect( i, i, (getWidth() - 2*i), (getHeight() - 2*i));
	g.setColour (VAR2COLOUR(getProperty(Ids::uiLabelOutlineColour)));
	g.drawRect (0, 0, getWidth(), getHeight(),  i);
    //[/UserPaint]
}

void CtrlrLabel::resized()
{
    //ctrlrLabel->setBounds (0, 0, getWidth() - 0, getHeight() - 0);
    //[UserResized] Add your own custom resize handling here..
	if (restoreStateInProgress)
		return;
	if ((bool)ctrlrLabel->getProperties() ["fh"] == true)
	{
		Font f = ctrlrLabel->getFont();
		f.setHeight (getHeight()*0.95f);
		ctrlrLabel->setFont (f);
	}
	ctrlrLabel->setBounds (getUsableRect());
    //[/UserResized]
}

//[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
double CtrlrLabel::getComponentMaxValue()
{
	return (1);
}

void CtrlrLabel::setComponentValue (const double newValue, const bool sendChangeMessage)
{
	if (sendChangeMessage)
	{
		owner.getProcessor().setValueGeneric (CtrlrModulatorValue(newValue,CtrlrModulatorValue::changedByGUI), true);
	}
}

double CtrlrLabel::getComponentValue()
{
	return (1);
}

int CtrlrLabel::getComponentMidiValue()
{
	return (1);
}

void CtrlrLabel::valueTreePropertyChanged (ValueTree &treeWhosePropertyHasChanged, const Identifier &property)
{
	if (property == Ids::uiLabelDisplaysAllValues)
	{
		if ((bool)getProperty(property) == true)
		{
			owner.getOwnerPanel().addPanelListener(this);
		}
		else
		{
			owner.getOwnerPanel().removePanelListener(this);
		}
	}
	else if (property == Ids::uiLabelText)
	{
		ctrlrLabel->setText (getProperty(Ids::uiLabelText), sendNotification);
	}
	else if (property == Ids::uiLabelBgColour)
	{
		ctrlrLabel->setColour (Label::backgroundColourId, VAR2COLOUR(getProperty(Ids::uiLabelBgColour)));
	}
	else if (property == Ids::uiLabelTextColour)
	{
		ctrlrLabel->setColour (Label::textColourId, VAR2COLOUR(getProperty(Ids::uiLabelTextColour)));
		ctrlrLabel->setColour (TextEditor::textColourId, VAR2COLOUR(getProperty(Ids::uiLabelTextColour)));
	}
	else if (property == Ids::uiLabelOutline)
	{
		ctrlrLabel->setBorderSize (BorderSize <int> (getProperty (property)));
		repaint();
	}
	else if (property == Ids::uiLabelOutlineColour)
	{
		ctrlrLabel->setColour (Label::outlineColourId, VAR2COLOUR(getProperty(Ids::uiLabelOutlineColour)));
		repaint();
	}
	else if (property == Ids::uiLabelFitFont || property == Ids::uiLabelFont)
	{
		ctrlrLabel->getProperties().set ("fh", getProperty(Ids::uiLabelFitFont));
		const String t = ctrlrLabel->getText();
		ctrlrLabel->setFont (STR2FONT(getProperty(Ids::uiLabelFont)));
		ctrlrLabel->setText (t, dontSendNotification);
	}
	else if (property == Ids::uiLabelJustification)
	{
		ctrlrLabel->setJustificationType (justificationFromProperty (getProperty(property)));
	}

	else if (property == Ids::uiLabelEditOnSingleClick
		|| property == Ids::uiLabelEditOnDoubleClick
		|| property == Ids::uiLabelEditFocusDiscardsChanges)
	{
		ctrlrLabel->setEditable ((bool)getProperty(Ids::uiLabelEditOnSingleClick),(bool)getProperty(Ids::uiLabelEditOnDoubleClick),(bool)getProperty(Ids::uiLabelEditFocusDiscardsChanges));
	}
	else if (property == Ids::uiLabelChangedCbk)
	{
		if (getProperty(property) == "")
			return;

		labelChangedCbk = owner.getOwnerPanel().getCtrlrLuaManager().getMethodManager().getMethod(getProperty(property));
	}
	else if (property == Ids::uiLabelInputHighlightTextColour || property == Ids::uiLabelInputHighlightColour)
	{
		ctrlrLabel->setColour (TextEditor::highlightColourId, VAR2COLOUR(getProperty(Ids::uiLabelInputHighlightColour)));
		ctrlrLabel->setColour (TextEditor::highlightedTextColourId, VAR2COLOUR(getProperty(Ids::uiLabelInputHighlightTextColour)));
	}
	else
	{
		CtrlrComponent::valueTreePropertyChanged(treeWhosePropertyHasChanged, property);
	}

	if (restoreStateInProgress == false)
	{
		resized();
	}
}

void CtrlrLabel::setComponentText(const String &componentText)
{
	setProperty (Ids::uiLabelText, componentText);
}

const String CtrlrLabel::getComponentText()
{
	return (ctrlrLabel->getText());
}

void CtrlrLabel::modulatorChanged (CtrlrModulator *modulatorThatChanged)
{
	if (modulatorThatChanged == 0 || modulatorThatChanged->getComponent() == 0)
		return;

	if ((bool)modulatorThatChanged->getComponent()->getProperty(Ids::componentExcludedFromLabelDisplay) == true)
		return;

	ctrlrLabel->setText (labelFromProperty (modulatorThatChanged, getProperty (Ids::uiLabelDisplayFormat)), dontSendNotification);
}

void CtrlrLabel::labelTextChanged (Label* labelThatHasChanged)
{
	if (getProperty (Ids::uiLabelText).toString() != labelThatHasChanged->getText())
        setProperty (Ids::uiLabelText, labelThatHasChanged->getText(), false);

	setComponentValue(0, true);

	if (labelChangedCbk && !labelChangedCbk.wasObjectDeleted())
	{
		if (labelChangedCbk->isValid())
		{
			owner.getOwnerPanel().getCtrlrLuaManager().getMethodManager().call (labelChangedCbk, dynamic_cast<CtrlrComponent*>(this), labelThatHasChanged->getText());
		}
	}
}

void CtrlrLabel::lookAndFeelChanged ()
{
}

CtrlrLabel &CtrlrLabel::setLabelText(const String &text)
{
	setProperty (Ids::uiLabelText, text);

	return (*this);
}

CtrlrLabel &CtrlrLabel::appendText(const String &text)
{
	setProperty (Ids::uiLabelText, ctrlrLabel->getText() + text);

	return (*this);
}

const String CtrlrLabel::getText()
{
	return (ctrlrLabel->getText());
}

void CtrlrLabel::customLookAndFeelChanged(LookAndFeelBase *customLookAndFeel)
{
    ctrlrLabel->setLookAndFeel (customLookAndFeel);
}

bool CtrlrLabel::keyPressed (const KeyPress &key)
{
	return (false);
}
//[/MiscUserCode]

//==============================================================================
#if 0
/*  -- Jucer information section --

    This is where the Jucer puts all of its metadata, so don't change anything in here!

BEGIN_JUCER_METADATA

<JUCER_COMPONENT documentType="Component" className="CtrlrLabel" componentName=""
                 parentClasses="public CtrlrComponent, public CtrlrPanel::PanelListener, public Label::Listener"
                 constructorParams="CtrlrModulator &owner" variableInitialisers="CtrlrComponent(owner)"
                 snapPixels="8" snapActive="1" snapShown="1" overlayOpacity="0.330000013"
                 fixedSize="1" initialWidth="88" initialHeight="24">
  <BACKGROUND backgroundColour="0"/>
  <LABEL name="ctrlrLabel" id="409d64ae540e634d" memberName="ctrlrLabel"
         virtualName="" explicitFocusOrder="0" pos="0 0 0M 0M" edTextCol="ff000000"
         edBkgCol="0" labelText="label text" editableSingleClick="0" editableDoubleClick="0"
         focusDiscardsChanges="0" fontname="Default font" fontsize="15"
         bold="0" italic="0" justification="33"/>
</JUCER_COMPONENT>

END_JUCER_METADATA
*/
#endif
<|endoftext|>


<commit_before>// This file is a part of the OpenSurgSim project.
// Copyright 2013, SimQuest Solutions Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <gtest/gtest.h>

#include <unordered_map>
#include <memory>

#include "SurgSim/DataStructures/PlyReader.h"
#include "SurgSim/Framework/Assert.h"
#include "SurgSim/Framework/Runtime.h"
#include "SurgSim/Framework/Timer.h"
#include "SurgSim/Math/Vector.h"
#include "SurgSim/Physics/Fem3DRepresentation.h"
#include "SurgSim/Physics/Fem3DRepresentationPlyReaderDelegate.h"
#include "SurgSim/Physics/FemElement3DCube.h"
#include "SurgSim/Testing/MockPhysicsManager.h"

using SurgSim::Math::Vector3d;

namespace
{
static const double dt = 0.001;
static const int frameCount = 100;

static std::unordered_map<SurgSim::Math::IntegrationScheme, std::string> getIntegrationSchemeNames()
{
	std::unordered_map<SurgSim::Math::IntegrationScheme, std::string> result;

#define FEM3DPERFORMANCETEST_MAP_NAME(map, name) (map)[name] = #name
	FEM3DPERFORMANCETEST_MAP_NAME(result, SurgSim::Math::INTEGRATIONSCHEME_EXPLICIT_EULER);
	FEM3DPERFORMANCETEST_MAP_NAME(result, SurgSim::Math::INTEGRATIONSCHEME_LINEAR_EXPLICIT_EULER);
	FEM3DPERFORMANCETEST_MAP_NAME(result, SurgSim::Math::INTEGRATIONSCHEME_MODIFIED_EXPLICIT_EULER);
	FEM3DPERFORMANCETEST_MAP_NAME(result, SurgSim::Math::INTEGRATIONSCHEME_LINEAR_MODIFIED_EXPLICIT_EULER);
	FEM3DPERFORMANCETEST_MAP_NAME(result, SurgSim::Math::INTEGRATIONSCHEME_IMPLICIT_EULER);
	FEM3DPERFORMANCETEST_MAP_NAME(result, SurgSim::Math::INTEGRATIONSCHEME_LINEAR_IMPLICIT_EULER);
#undef FEM3DPERFORMANCETEST_MAP_NAME

	return result;
}

static std::unordered_map<SurgSim::Math::IntegrationScheme, std::string> IntegrationSchemeNames
	= getIntegrationSchemeNames();
}

namespace SurgSim
{
namespace Physics
{

class DivisbleCubeRepresentation : public Fem3DRepresentation
{
public:
	/// Constructor
	/// \param name	The name of the divisible cube representation.
	/// \param corners The 8 corners of the divisible cube
	DivisbleCubeRepresentation(const std::string& name, size_t nodesPerAxis)
		: Fem3DRepresentation(name), m_numNodesPerAxis(nodesPerAxis)
	{
		// Compute the center point of the cube
		SurgSim::Math::Vector3d center = SurgSim::Math::Vector3d::Zero();

		// Compute the cube's corners for the Fem3d simulation
		double halfLength = static_cast<double>(nodesPerAxis);
		Vector3d X = Vector3d::UnitX();
		Vector3d Y = Vector3d::UnitY();
		Vector3d Z = Vector3d::UnitZ();
		m_cubeNodes[0] = center - halfLength * X - halfLength * Y - halfLength * Z;
		m_cubeNodes[1] = center + halfLength * X - halfLength * Y - halfLength * Z;
		m_cubeNodes[2] = center - halfLength * X + halfLength * Y - halfLength * Z;
		m_cubeNodes[3] = center + halfLength * X + halfLength * Y - halfLength * Z;
		m_cubeNodes[4] = center - halfLength * X - halfLength * Y + halfLength * Z;
		m_cubeNodes[5] = center + halfLength * X - halfLength * Y + halfLength * Z;
		m_cubeNodes[6] = center - halfLength * X + halfLength * Y + halfLength * Z;
		m_cubeNodes[7] = center + halfLength * X + halfLength * Y + halfLength * Z;

		auto initialState = std::make_shared<DeformableRepresentationState>();
		fillUpDeformableState(initialState);
		setInitialState(initialState);
		addFemCubes(initialState);
	}

protected:
	/// Convert a node index from a 3d indexing to a 1d indexing
	/// \param i, j, k Indices along the X, Y and Z axis
	/// \return Unique index of the corresponding point (to access a linear array for example)
	size_t get1DIndexFrom3D(size_t i, size_t j, size_t k)
	{
		return m_numNodesPerAxis * m_numNodesPerAxis * i + m_numNodesPerAxis * j + k;
	}

	/// Fills up a given deformable state with the cube's nodes, border nodes, and internal nodes
	/// \param[in,out] state	The deformable state to be filled up
	void fillUpDeformableState(std::shared_ptr<DeformableRepresentationState> state)
	{
		state->setNumDof(getNumDofPerNode(), m_numNodesPerAxis * m_numNodesPerAxis * m_numNodesPerAxis);
		SurgSim::Math::Vector& nodePositions = state->getPositions();

		for (size_t i = 0; i < m_numNodesPerAxis; i++)
		{
			// For a given index i, we intersect the cube with a (Y Z) plane, which defines a square on a (Y Z) plane
			Vector3d extremitiesX0[4] = {m_cubeNodes[0], m_cubeNodes[2], m_cubeNodes[4], m_cubeNodes[6]};
			Vector3d extremitiesX1[4] = {m_cubeNodes[1], m_cubeNodes[3], m_cubeNodes[5], m_cubeNodes[7]};
			Vector3d extremitiesXi[4];
			double coefI = static_cast<double>(i) / (static_cast<double>(m_numNodesPerAxis) - 1.0);

			for (size_t index = 0; index < 4; index++)
			{
				extremitiesXi[index] =
					extremitiesX0[index] * (1.0 - coefI) +
					extremitiesX1[index] *        coefI;
			}

			for (size_t j = 0; j < m_numNodesPerAxis; j++)
			{
				// For a given index j, we intersect the square with a (X Z) plane, which defines a line along (Z)
				Vector3d extremitiesY0[2] = {extremitiesXi[0], extremitiesXi[2]};
				Vector3d extremitiesY1[2] = {extremitiesXi[1], extremitiesXi[3]};
				Vector3d extremitiesYi[2];
				double coefJ = static_cast<double>(j) / (static_cast<double>(m_numNodesPerAxis) - 1.0);

				for (size_t index = 0; index < 2; index++)
				{
					extremitiesYi[index] =
						extremitiesY0[index] * (1.0 - coefJ) +
						extremitiesY1[index] *        coefJ;
				}

				for (size_t k = 0; k < m_numNodesPerAxis; k++)
				{
					// For a given index k, we intersect the line with a (X Y) plane, which defines a 3d point
					double coefK = static_cast<double>(k) / (static_cast<double>(m_numNodesPerAxis) - 1.0);
					Vector3d position3d = extremitiesYi[0] * (1.0 - coefK) + extremitiesYi[1] * coefK;
					SurgSim::Math::setSubVector(
						position3d, static_cast<unsigned int>(get1DIndexFrom3D(i, j, k)), 3, &nodePositions);
				}
			}
		}
	}

	/// Adds the Fem3D elements of small cubes
	/// \param state	The deformable state for initialization.
	void addFemCubes(std::shared_ptr<DeformableRepresentationState> state)
	{
		for (size_t i = 0; i < m_numNodesPerAxis - 1; i++)
		{
			for (size_t j = 0; j < m_numNodesPerAxis - 1; j++)
			{
				for (size_t k = 0; k < m_numNodesPerAxis - 1; k++)
				{
					std::array<unsigned int, 8> cubeNodeIds;
					cubeNodeIds[0] = static_cast<unsigned int>(get1DIndexFrom3D(i  , j  , k  ));
					cubeNodeIds[1] = static_cast<unsigned int>(get1DIndexFrom3D(i+1, j  , k  ));
					cubeNodeIds[2] = static_cast<unsigned int>(get1DIndexFrom3D(i  , j+1, k  ));
					cubeNodeIds[3] = static_cast<unsigned int>(get1DIndexFrom3D(i+1, j+1, k  ));
					cubeNodeIds[4] = static_cast<unsigned int>(get1DIndexFrom3D(i  , j  , k+1));
					cubeNodeIds[5] = static_cast<unsigned int>(get1DIndexFrom3D(i+1, j  , k+1));
					cubeNodeIds[6] = static_cast<unsigned int>(get1DIndexFrom3D(i  , j+1, k+1));
					cubeNodeIds[7] = static_cast<unsigned int>(get1DIndexFrom3D(i+1, j+1, k+1));

					std::array<unsigned int, 8> cube = {
						cubeNodeIds[0], cubeNodeIds[1], cubeNodeIds[3], cubeNodeIds[2],
						cubeNodeIds[4], cubeNodeIds[5], cubeNodeIds[7], cubeNodeIds[6]};

					// Add FemElement3DCube for each cube
					std::shared_ptr<FemElement3DCube> femElement = std::make_shared<FemElement3DCube>(cube, *state);
					femElement->setMassDensity(980.0);   // 0.98 g/cm^-3 (2-part silicone rubber a.k.a. RTV6166)
					femElement->setPoissonRatio(0.499);  // From the paper (near 0.5)
					femElement->setYoungModulus(15.3e3); // 15.3 kPa (From the paper)
					femElement->initialize(*state);
					addFemElement(femElement);
				}
			}
		}
	}

private:
	// Number of point per dimensions
	size_t m_numNodesPerAxis;

	// Corner nodes of the original cube
	std::array<SurgSim::Math::Vector3d, 8> m_cubeNodes;
};

class Fem3DPerformanceTestBase : public ::testing::Test
{
public:
	virtual void SetUp()
	{
		m_physicsManager = std::make_shared<SurgSim::Testing::MockPhysicsManager>();

		m_physicsManager->doInitialize();
		m_physicsManager->doStartUp();
	}

	void initializeRepresentation(std::shared_ptr<Fem3DRepresentation> fem)
	{
		fem->initialize(std::make_shared<SurgSim::Framework::Runtime>());
		m_physicsManager->executeAdditions(fem);
	}

	void performTimingTest()
	{
		SurgSim::Framework::Timer totalTime;
		totalTime.beginFrame();

		SurgSim::Framework::Timer timer;
		timer.setMaxNumberOfFrames(frameCount);
		for (int i = 0; i < frameCount; i++)
		{
			timer.beginFrame();
			m_physicsManager->doUpdate(dt);
			timer.endFrame();
		}

		totalTime.endFrame();
		RecordProperty("Duration", boost::to_string(totalTime.getCumulativeTime()));
		RecordProperty("FrameRate", boost::to_string(timer.getAverageFrameRate()));
	}

protected:
	std::shared_ptr<SurgSim::Testing::MockPhysicsManager> m_physicsManager;
};

class IntegrationSchemeParamTest : public Fem3DPerformanceTestBase,
								   public ::testing::WithParamInterface<SurgSim::Math::IntegrationScheme>
{
};

class IntegrationSchemeAndCountParamTest
	: public Fem3DPerformanceTestBase,
	  public ::testing::WithParamInterface<std::tuple<SurgSim::Math::IntegrationScheme, int> >
{
};

TEST_P(IntegrationSchemeParamTest, WoundTest)
{
	SurgSim::Math::IntegrationScheme integrationScheme = GetParam();
	RecordProperty("IntegrationScheme", IntegrationSchemeNames[integrationScheme]);

	auto fem = std::make_shared<SurgSim::Physics::Fem3DRepresentation>("wound");
	fem->setFilename("Data/Fem3DPerformanceTest/wound_deformable.ply");
	fem->setIntegrationScheme(integrationScheme);

	initializeRepresentation(fem);
	performTimingTest();
}

TEST_P(IntegrationSchemeAndCountParamTest, CubeTest)
{
	int numCubes;
	SurgSim::Math::IntegrationScheme integrationScheme;
	std::tie(integrationScheme, numCubes) = GetParam();
	RecordProperty("IntegrationScheme", IntegrationSchemeNames[integrationScheme]);
	RecordProperty("CubeDivisions", boost::to_string(numCubes));

	auto fem = std::make_shared<DivisbleCubeRepresentation>("cube", numCubes);
	fem->setIntegrationScheme(integrationScheme);

	initializeRepresentation(fem);
	performTimingTest();
}

INSTANTIATE_TEST_CASE_P(Fem3DPerformanceTest,
						IntegrationSchemeParamTest,
						::testing::Values(SurgSim::Math::INTEGRATIONSCHEME_EXPLICIT_EULER,
										  SurgSim::Math::INTEGRATIONSCHEME_LINEAR_EXPLICIT_EULER,
										  SurgSim::Math::INTEGRATIONSCHEME_MODIFIED_EXPLICIT_EULER,
										  SurgSim::Math::INTEGRATIONSCHEME_LINEAR_MODIFIED_EXPLICIT_EULER,
										  SurgSim::Math::INTEGRATIONSCHEME_IMPLICIT_EULER,
										  SurgSim::Math::INTEGRATIONSCHEME_LINEAR_IMPLICIT_EULER));

INSTANTIATE_TEST_CASE_P(
	Fem3DPerformanceTest,
	IntegrationSchemeAndCountParamTest,
	::testing::Combine(::testing::Values(SurgSim::Math::INTEGRATIONSCHEME_EXPLICIT_EULER,
										 SurgSim::Math::INTEGRATIONSCHEME_LINEAR_EXPLICIT_EULER,
										 SurgSim::Math::INTEGRATIONSCHEME_MODIFIED_EXPLICIT_EULER,
										 SurgSim::Math::INTEGRATIONSCHEME_LINEAR_MODIFIED_EXPLICIT_EULER,
										 SurgSim::Math::INTEGRATIONSCHEME_IMPLICIT_EULER,
										 SurgSim::Math::INTEGRATIONSCHEME_LINEAR_IMPLICIT_EULER),
					   ::testing::Values(2, 3, 4, 5, 6, 7, 8)));

} // namespace Physics
} // namespace SurgSim
<commit_msg>Fem3DPerformanceTest, fix GCC compile error<commit_after>// This file is a part of the OpenSurgSim project.
// Copyright 2013, SimQuest Solutions Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <gtest/gtest.h>

#include <unordered_map>
#include <memory>

#include "SurgSim/DataStructures/PlyReader.h"
#include "SurgSim/Framework/Assert.h"
#include "SurgSim/Framework/Runtime.h"
#include "SurgSim/Framework/Timer.h"
#include "SurgSim/Math/Vector.h"
#include "SurgSim/Physics/Fem3DRepresentation.h"
#include "SurgSim/Physics/Fem3DRepresentationPlyReaderDelegate.h"
#include "SurgSim/Physics/FemElement3DCube.h"
#include "SurgSim/Testing/MockPhysicsManager.h"

using SurgSim::Math::Vector3d;

namespace
{
static const double dt = 0.001;
static const int frameCount = 100;

static std::unordered_map<SurgSim::Math::IntegrationScheme, std::string, std::hash<int>> getIntegrationSchemeNames()
{
	std::unordered_map<SurgSim::Math::IntegrationScheme, std::string, std::hash<int>> result;

#define FEM3DPERFORMANCETEST_MAP_NAME(map, name) (map)[name] = #name
	FEM3DPERFORMANCETEST_MAP_NAME(result, SurgSim::Math::INTEGRATIONSCHEME_EXPLICIT_EULER);
	FEM3DPERFORMANCETEST_MAP_NAME(result, SurgSim::Math::INTEGRATIONSCHEME_LINEAR_EXPLICIT_EULER);
	FEM3DPERFORMANCETEST_MAP_NAME(result, SurgSim::Math::INTEGRATIONSCHEME_MODIFIED_EXPLICIT_EULER);
	FEM3DPERFORMANCETEST_MAP_NAME(result, SurgSim::Math::INTEGRATIONSCHEME_LINEAR_MODIFIED_EXPLICIT_EULER);
	FEM3DPERFORMANCETEST_MAP_NAME(result, SurgSim::Math::INTEGRATIONSCHEME_IMPLICIT_EULER);
	FEM3DPERFORMANCETEST_MAP_NAME(result, SurgSim::Math::INTEGRATIONSCHEME_LINEAR_IMPLICIT_EULER);
#undef FEM3DPERFORMANCETEST_MAP_NAME

	return result;
}

static std::unordered_map<SurgSim::Math::IntegrationScheme, std::string, std::hash<int>> IntegrationSchemeNames
	= getIntegrationSchemeNames();
}

namespace SurgSim
{
namespace Physics
{

class DivisbleCubeRepresentation : public Fem3DRepresentation
{
public:
	/// Constructor
	/// \param name	The name of the divisible cube representation.
	/// \param corners The 8 corners of the divisible cube
	DivisbleCubeRepresentation(const std::string& name, size_t nodesPerAxis)
		: Fem3DRepresentation(name), m_numNodesPerAxis(nodesPerAxis)
	{
		// Compute the center point of the cube
		SurgSim::Math::Vector3d center = SurgSim::Math::Vector3d::Zero();

		// Compute the cube's corners for the Fem3d simulation
		double halfLength = static_cast<double>(nodesPerAxis);
		Vector3d X = Vector3d::UnitX();
		Vector3d Y = Vector3d::UnitY();
		Vector3d Z = Vector3d::UnitZ();
		m_cubeNodes[0] = center - halfLength * X - halfLength * Y - halfLength * Z;
		m_cubeNodes[1] = center + halfLength * X - halfLength * Y - halfLength * Z;
		m_cubeNodes[2] = center - halfLength * X + halfLength * Y - halfLength * Z;
		m_cubeNodes[3] = center + halfLength * X + halfLength * Y - halfLength * Z;
		m_cubeNodes[4] = center - halfLength * X - halfLength * Y + halfLength * Z;
		m_cubeNodes[5] = center + halfLength * X - halfLength * Y + halfLength * Z;
		m_cubeNodes[6] = center - halfLength * X + halfLength * Y + halfLength * Z;
		m_cubeNodes[7] = center + halfLength * X + halfLength * Y + halfLength * Z;

		auto initialState = std::make_shared<DeformableRepresentationState>();
		fillUpDeformableState(initialState);
		setInitialState(initialState);
		addFemCubes(initialState);
	}

protected:
	/// Convert a node index from a 3d indexing to a 1d indexing
	/// \param i, j, k Indices along the X, Y and Z axis
	/// \return Unique index of the corresponding point (to access a linear array for example)
	size_t get1DIndexFrom3D(size_t i, size_t j, size_t k)
	{
		return m_numNodesPerAxis * m_numNodesPerAxis * i + m_numNodesPerAxis * j + k;
	}

	/// Fills up a given deformable state with the cube's nodes, border nodes, and internal nodes
	/// \param[in,out] state	The deformable state to be filled up
	void fillUpDeformableState(std::shared_ptr<DeformableRepresentationState> state)
	{
		state->setNumDof(getNumDofPerNode(), m_numNodesPerAxis * m_numNodesPerAxis * m_numNodesPerAxis);
		SurgSim::Math::Vector& nodePositions = state->getPositions();

		for (size_t i = 0; i < m_numNodesPerAxis; i++)
		{
			// For a given index i, we intersect the cube with a (Y Z) plane, which defines a square on a (Y Z) plane
			Vector3d extremitiesX0[4] = {m_cubeNodes[0], m_cubeNodes[2], m_cubeNodes[4], m_cubeNodes[6]};
			Vector3d extremitiesX1[4] = {m_cubeNodes[1], m_cubeNodes[3], m_cubeNodes[5], m_cubeNodes[7]};
			Vector3d extremitiesXi[4];
			double coefI = static_cast<double>(i) / (static_cast<double>(m_numNodesPerAxis) - 1.0);

			for (size_t index = 0; index < 4; index++)
			{
				extremitiesXi[index] =
					extremitiesX0[index] * (1.0 - coefI) +
					extremitiesX1[index] *        coefI;
			}

			for (size_t j = 0; j < m_numNodesPerAxis; j++)
			{
				// For a given index j, we intersect the square with a (X Z) plane, which defines a line along (Z)
				Vector3d extremitiesY0[2] = {extremitiesXi[0], extremitiesXi[2]};
				Vector3d extremitiesY1[2] = {extremitiesXi[1], extremitiesXi[3]};
				Vector3d extremitiesYi[2];
				double coefJ = static_cast<double>(j) / (static_cast<double>(m_numNodesPerAxis) - 1.0);

				for (size_t index = 0; index < 2; index++)
				{
					extremitiesYi[index] =
						extremitiesY0[index] * (1.0 - coefJ) +
						extremitiesY1[index] *        coefJ;
				}

				for (size_t k = 0; k < m_numNodesPerAxis; k++)
				{
					// For a given index k, we intersect the line with a (X Y) plane, which defines a 3d point
					double coefK = static_cast<double>(k) / (static_cast<double>(m_numNodesPerAxis) - 1.0);
					Vector3d position3d = extremitiesYi[0] * (1.0 - coefK) + extremitiesYi[1] * coefK;
					SurgSim::Math::setSubVector(
						position3d, static_cast<unsigned int>(get1DIndexFrom3D(i, j, k)), 3, &nodePositions);
				}
			}
		}
	}

	/// Adds the Fem3D elements of small cubes
	/// \param state	The deformable state for initialization.
	void addFemCubes(std::shared_ptr<DeformableRepresentationState> state)
	{
		for (size_t i = 0; i < m_numNodesPerAxis - 1; i++)
		{
			for (size_t j = 0; j < m_numNodesPerAxis - 1; j++)
			{
				for (size_t k = 0; k < m_numNodesPerAxis - 1; k++)
				{
					std::array<unsigned int, 8> cubeNodeIds;
					cubeNodeIds[0] = static_cast<unsigned int>(get1DIndexFrom3D(i  , j  , k  ));
					cubeNodeIds[1] = static_cast<unsigned int>(get1DIndexFrom3D(i+1, j  , k  ));
					cubeNodeIds[2] = static_cast<unsigned int>(get1DIndexFrom3D(i  , j+1, k  ));
					cubeNodeIds[3] = static_cast<unsigned int>(get1DIndexFrom3D(i+1, j+1, k  ));
					cubeNodeIds[4] = static_cast<unsigned int>(get1DIndexFrom3D(i  , j  , k+1));
					cubeNodeIds[5] = static_cast<unsigned int>(get1DIndexFrom3D(i+1, j  , k+1));
					cubeNodeIds[6] = static_cast<unsigned int>(get1DIndexFrom3D(i  , j+1, k+1));
					cubeNodeIds[7] = static_cast<unsigned int>(get1DIndexFrom3D(i+1, j+1, k+1));

					std::array<unsigned int, 8> cube = {
						cubeNodeIds[0], cubeNodeIds[1], cubeNodeIds[3], cubeNodeIds[2],
						cubeNodeIds[4], cubeNodeIds[5], cubeNodeIds[7], cubeNodeIds[6]};

					// Add FemElement3DCube for each cube
					std::shared_ptr<FemElement3DCube> femElement = std::make_shared<FemElement3DCube>(cube, *state);
					femElement->setMassDensity(980.0);   // 0.98 g/cm^-3 (2-part silicone rubber a.k.a. RTV6166)
					femElement->setPoissonRatio(0.499);  // From the paper (near 0.5)
					femElement->setYoungModulus(15.3e3); // 15.3 kPa (From the paper)
					femElement->initialize(*state);
					addFemElement(femElement);
				}
			}
		}
	}

private:
	// Number of point per dimensions
	size_t m_numNodesPerAxis;

	// Corner nodes of the original cube
	std::array<SurgSim::Math::Vector3d, 8> m_cubeNodes;
};

class Fem3DPerformanceTestBase : public ::testing::Test
{
public:
	virtual void SetUp()
	{
		m_physicsManager = std::make_shared<SurgSim::Testing::MockPhysicsManager>();

		m_physicsManager->doInitialize();
		m_physicsManager->doStartUp();
	}

	void initializeRepresentation(std::shared_ptr<Fem3DRepresentation> fem)
	{
		fem->initialize(std::make_shared<SurgSim::Framework::Runtime>());
		m_physicsManager->executeAdditions(fem);
	}

	void performTimingTest()
	{
		SurgSim::Framework::Timer totalTime;
		totalTime.beginFrame();

		SurgSim::Framework::Timer timer;
		timer.setMaxNumberOfFrames(frameCount);
		for (int i = 0; i < frameCount; i++)
		{
			timer.beginFrame();
			m_physicsManager->doUpdate(dt);
			timer.endFrame();
		}

		totalTime.endFrame();
		RecordProperty("Duration", boost::to_string(totalTime.getCumulativeTime()));
		RecordProperty("FrameRate", boost::to_string(timer.getAverageFrameRate()));
	}

protected:
	std::shared_ptr<SurgSim::Testing::MockPhysicsManager> m_physicsManager;
};

class IntegrationSchemeParamTest : public Fem3DPerformanceTestBase,
								   public ::testing::WithParamInterface<SurgSim::Math::IntegrationScheme>
{
};

class IntegrationSchemeAndCountParamTest
	: public Fem3DPerformanceTestBase,
	  public ::testing::WithParamInterface<std::tuple<SurgSim::Math::IntegrationScheme, int> >
{
};

TEST_P(IntegrationSchemeParamTest, WoundTest)
{
	SurgSim::Math::IntegrationScheme integrationScheme = GetParam();
	RecordProperty("IntegrationScheme", IntegrationSchemeNames[integrationScheme]);

	auto fem = std::make_shared<SurgSim::Physics::Fem3DRepresentation>("wound");
	fem->setFilename("Data/Fem3DPerformanceTest/wound_deformable.ply");
	fem->setIntegrationScheme(integrationScheme);

	initializeRepresentation(fem);
	performTimingTest();
}

TEST_P(IntegrationSchemeAndCountParamTest, CubeTest)
{
	int numCubes;
	SurgSim::Math::IntegrationScheme integrationScheme;
	std::tie(integrationScheme, numCubes) = GetParam();
	RecordProperty("IntegrationScheme", IntegrationSchemeNames[integrationScheme]);
	RecordProperty("CubeDivisions", boost::to_string(numCubes));

	auto fem = std::make_shared<DivisbleCubeRepresentation>("cube", numCubes);
	fem->setIntegrationScheme(integrationScheme);

	initializeRepresentation(fem);
	performTimingTest();
}

INSTANTIATE_TEST_CASE_P(Fem3DPerformanceTest,
						IntegrationSchemeParamTest,
						::testing::Values(SurgSim::Math::INTEGRATIONSCHEME_EXPLICIT_EULER,
										  SurgSim::Math::INTEGRATIONSCHEME_LINEAR_EXPLICIT_EULER,
										  SurgSim::Math::INTEGRATIONSCHEME_MODIFIED_EXPLICIT_EULER,
										  SurgSim::Math::INTEGRATIONSCHEME_LINEAR_MODIFIED_EXPLICIT_EULER,
										  SurgSim::Math::INTEGRATIONSCHEME_IMPLICIT_EULER,
										  SurgSim::Math::INTEGRATIONSCHEME_LINEAR_IMPLICIT_EULER));

INSTANTIATE_TEST_CASE_P(
	Fem3DPerformanceTest,
	IntegrationSchemeAndCountParamTest,
	::testing::Combine(::testing::Values(SurgSim::Math::INTEGRATIONSCHEME_EXPLICIT_EULER,
										 SurgSim::Math::INTEGRATIONSCHEME_LINEAR_EXPLICIT_EULER,
										 SurgSim::Math::INTEGRATIONSCHEME_MODIFIED_EXPLICIT_EULER,
										 SurgSim::Math::INTEGRATIONSCHEME_LINEAR_MODIFIED_EXPLICIT_EULER,
										 SurgSim::Math::INTEGRATIONSCHEME_IMPLICIT_EULER,
										 SurgSim::Math::INTEGRATIONSCHEME_LINEAR_IMPLICIT_EULER),
					   ::testing::Values(2, 3, 4, 5, 6, 7, 8)));

} // namespace Physics
} // namespace SurgSim
<|endoftext|>


<commit_before><commit_msg>decimal to binary: incomplete<commit_after><|endoftext|>


<commit_before><commit_msg>bug fixes<commit_after><|endoftext|>