<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/OdeState.h"
#include "SurgSim/Math/Vector.h"
#include "SurgSim/Physics/Fem3DPlyReaderDelegate.h"
#include "SurgSim/Physics/Fem3DRepresentation.h"
#include "SurgSim/Physics/Fem3DElementCube.h"
#include "SurgSim/Physics/PerformanceTests/DivisibleCubeRepresentation.h"
#include "SurgSim/Testing/MockPhysicsManager.h"

using SurgSim::Math::Vector3d;

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

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 FEM3DSOLUTIONCOMPONEMENTSTEST_MAP_NAME(map, name) (map)[name] = #name
	FEM3DSOLUTIONCOMPONEMENTSTEST_MAP_NAME(result, SurgSim::Math::INTEGRATIONSCHEME_EXPLICIT_EULER);
	FEM3DSOLUTIONCOMPONEMENTSTEST_MAP_NAME(result, SurgSim::Math::INTEGRATIONSCHEME_LINEAR_EXPLICIT_EULER);
	FEM3DSOLUTIONCOMPONEMENTSTEST_MAP_NAME(result, SurgSim::Math::INTEGRATIONSCHEME_MODIFIED_EXPLICIT_EULER);
	FEM3DSOLUTIONCOMPONEMENTSTEST_MAP_NAME(result, SurgSim::Math::INTEGRATIONSCHEME_LINEAR_MODIFIED_EXPLICIT_EULER);
	FEM3DSOLUTIONCOMPONEMENTSTEST_MAP_NAME(result, SurgSim::Math::INTEGRATIONSCHEME_IMPLICIT_EULER);
	FEM3DSOLUTIONCOMPONEMENTSTEST_MAP_NAME(result, SurgSim::Math::INTEGRATIONSCHEME_LINEAR_IMPLICIT_EULER);
	FEM3DSOLUTIONCOMPONEMENTSTEST_MAP_NAME(result, SurgSim::Math::INTEGRATIONSCHEME_STATIC);
	FEM3DSOLUTIONCOMPONEMENTSTEST_MAP_NAME(result, SurgSim::Math::INTEGRATIONSCHEME_LINEAR_STATIC);
	FEM3DSOLUTIONCOMPONEMENTSTEST_MAP_NAME(result, SurgSim::Math::INTEGRATIONSCHEME_RUNGE_KUTTA_4);
	FEM3DSOLUTIONCOMPONEMENTSTEST_MAP_NAME(result, SurgSim::Math::INTEGRATIONSCHEME_LINEAR_RUNGE_KUTTA_4);
#undef FEM3DSOLUTIONCOMPONEMENTSTEST_MAP_NAME

	return result;
}

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

namespace SurgSim
{
namespace Physics
{

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

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

	void timeInitializeRepresentation(std::shared_ptr<DivisibleCubeRepresentation> fem)
	{
		SurgSim::Framework::Timer totalTime;
		totalTime.beginFrame();
		for (int i = 0; i < frameCount; i++)
		{
			fem->initializeNoWakeUp();
		}
		totalTime.endFrame();
		RecordProperty("Duration", boost::to_string(totalTime.getCumulativeTime()));
	}

	void timeMatrixAssembly(std::shared_ptr<DivisibleCubeRepresentation> fem)
	{
		SurgSim::Framework::Timer totalTime;
		totalTime.beginFrame();
		for (int i = 0; i < frameCount; i++)
		{
			fem->getOdeSolver()->computeMatrices(dt, *(fem->getInitialState()));
		}
		totalTime.endFrame();
		RecordProperty("Duration", boost::to_string(totalTime.getCumulativeTime()));
	}

	void timeComputeLinearSystem(std::shared_ptr<DivisibleCubeRepresentation> fem)
	{
		fem->getOdeSolver()->computeMatrices(dt, *(fem->getInitialState()));
		SurgSim::Framework::Timer totalTime;
		totalTime.beginFrame();
		for (int i = 0; i < frameCount; i++)
		{
			fem->getOdeSolver()->getLinearSolver()->setMatrix(fem->getOdeSolver()->getSystemMatrix());
		}
		totalTime.endFrame();
		RecordProperty("Duration", boost::to_string(totalTime.getCumulativeTime()));
	}

	void timeSolveSystem(std::shared_ptr<DivisibleCubeRepresentation> fem)
	{
		fem->getOdeSolver()->computeMatrices(dt, *(fem->getInitialState()));
		fem->getOdeSolver()->getLinearSolver()->setMatrix(fem->getOdeSolver()->getSystemMatrix());
		SurgSim::Framework::Timer totalTime;
		totalTime.beginFrame();
		for (int i = 0; i < frameCount; i++)
		{
			fem->getOdeSolver()->getLinearSolver()->solve(Math::Vector::Ones(fem->getInitialState()->getNumDof()));
		}
		totalTime.endFrame();
		RecordProperty("Duration", boost::to_string(totalTime.getCumulativeTime()));
	}

	void timeInvertSystem(std::shared_ptr<DivisibleCubeRepresentation> fem)
	{
		fem->getOdeSolver()->computeMatrices(dt, *(fem->getInitialState()));
		fem->getOdeSolver()->getLinearSolver()->setMatrix(fem->getOdeSolver()->getSystemMatrix());
		SurgSim::Framework::Timer totalTime;
		totalTime.beginFrame();
		for (int i = 0; i < frameCount; i++)
		{
			fem->getOdeSolver()->getLinearSolver()->getInverse();
		}
		totalTime.endFrame();
		RecordProperty("Duration", boost::to_string(totalTime.getCumulativeTime()));
	}

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

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

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

TEST_P(ComponentIntegrationSchemeAndCountParamTest, TimeMatrixInitialization)
{
	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<DivisibleCubeRepresentation>("cube", numCubes);
	fem->setIntegrationScheme(integrationScheme);

	timeInitializeRepresentation(fem);
}

TEST_P(ComponentIntegrationSchemeAndCountParamTest, TimeMatrixAssembly)
{
	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<DivisibleCubeRepresentation>("cube", numCubes);
	fem->setIntegrationScheme(integrationScheme);
	initializeRepresentation(fem);

	timeMatrixAssembly(fem);
}

TEST_P(ComponentIntegrationSchemeAndCountParamTest, TimeComputeLinearSystem)
{
	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<DivisibleCubeRepresentation>("cube", numCubes);
	fem->setIntegrationScheme(integrationScheme);
	initializeRepresentation(fem);

	timeComputeLinearSystem(fem);
}

TEST_P(ComponentIntegrationSchemeAndCountParamTest, TimeSolveSystem)
{
	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<DivisibleCubeRepresentation>("cube", numCubes);
	fem->setIntegrationScheme(integrationScheme);
	initializeRepresentation(fem);

	timeSolveSystem(fem);
}

TEST_P(ComponentIntegrationSchemeAndCountParamTest, TimeInvertSystem)
{
	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<DivisibleCubeRepresentation>("cube", numCubes);
	fem->setIntegrationScheme(integrationScheme);
	initializeRepresentation(fem);

	timeInvertSystem(fem);
}

INSTANTIATE_TEST_CASE_P(
	Fem3DSolutionComponentsTest,
	ComponentIntegrationSchemeAndCountParamTest,
	::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,
					   SurgSim::Math::INTEGRATIONSCHEME_STATIC,
					   SurgSim::Math::INTEGRATIONSCHEME_LINEAR_STATIC,
					   SurgSim::Math::INTEGRATIONSCHEME_RUNGE_KUTTA_4,
					   SurgSim::Math::INTEGRATIONSCHEME_LINEAR_RUNGE_KUTTA_4),
					   ::testing::Values(2, 3, 4, 5, 6, 7, 8)));

} // namespace Physics
} // namespace SurgSim
<commit_msg>Fix other performance test as well (same fix)<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/OdeState.h"
#include "SurgSim/Math/Vector.h"
#include "SurgSim/Physics/Fem3DPlyReaderDelegate.h"
#include "SurgSim/Physics/Fem3DRepresentation.h"
#include "SurgSim/Physics/Fem3DElementCube.h"
#include "SurgSim/Physics/PerformanceTests/DivisibleCubeRepresentation.h"
#include "SurgSim/Testing/MockPhysicsManager.h"

using SurgSim::Math::Vector3d;

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

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 FEM3DSOLUTIONCOMPONEMENTSTEST_MAP_NAME(map, name) (map)[name] = #name
	FEM3DSOLUTIONCOMPONEMENTSTEST_MAP_NAME(result, SurgSim::Math::INTEGRATIONSCHEME_EXPLICIT_EULER);
	FEM3DSOLUTIONCOMPONEMENTSTEST_MAP_NAME(result, SurgSim::Math::INTEGRATIONSCHEME_LINEAR_EXPLICIT_EULER);
	FEM3DSOLUTIONCOMPONEMENTSTEST_MAP_NAME(result, SurgSim::Math::INTEGRATIONSCHEME_MODIFIED_EXPLICIT_EULER);
	FEM3DSOLUTIONCOMPONEMENTSTEST_MAP_NAME(result, SurgSim::Math::INTEGRATIONSCHEME_LINEAR_MODIFIED_EXPLICIT_EULER);
	FEM3DSOLUTIONCOMPONEMENTSTEST_MAP_NAME(result, SurgSim::Math::INTEGRATIONSCHEME_IMPLICIT_EULER);
	FEM3DSOLUTIONCOMPONEMENTSTEST_MAP_NAME(result, SurgSim::Math::INTEGRATIONSCHEME_LINEAR_IMPLICIT_EULER);
	FEM3DSOLUTIONCOMPONEMENTSTEST_MAP_NAME(result, SurgSim::Math::INTEGRATIONSCHEME_STATIC);
	FEM3DSOLUTIONCOMPONEMENTSTEST_MAP_NAME(result, SurgSim::Math::INTEGRATIONSCHEME_LINEAR_STATIC);
	FEM3DSOLUTIONCOMPONEMENTSTEST_MAP_NAME(result, SurgSim::Math::INTEGRATIONSCHEME_RUNGE_KUTTA_4);
	FEM3DSOLUTIONCOMPONEMENTSTEST_MAP_NAME(result, SurgSim::Math::INTEGRATIONSCHEME_LINEAR_RUNGE_KUTTA_4);
#undef FEM3DSOLUTIONCOMPONEMENTSTEST_MAP_NAME

	return result;
}

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

namespace SurgSim
{
namespace Physics
{

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

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

	void timeInitializeRepresentation(std::shared_ptr<DivisibleCubeRepresentation> fem)
	{
		SurgSim::Framework::Timer totalTime;
		totalTime.beginFrame();
		for (int i = 0; i < frameCount; i++)
		{
			fem->initializeNoWakeUp();
		}
		totalTime.endFrame();
		RecordProperty("Duration", boost::to_string(totalTime.getCumulativeTime()));
	}

	void timeMatrixAssembly(std::shared_ptr<DivisibleCubeRepresentation> fem)
	{
		SurgSim::Framework::Timer totalTime;
		totalTime.beginFrame();
		for (int i = 0; i < frameCount; i++)
		{
			fem->getOdeSolver()->computeMatrices(dt, *(fem->getInitialState()));
		}
		totalTime.endFrame();
		RecordProperty("Duration", boost::to_string(totalTime.getCumulativeTime()));
	}

	void timeComputeLinearSystem(std::shared_ptr<DivisibleCubeRepresentation> fem)
	{
		fem->getOdeSolver()->computeMatrices(dt, *(fem->getInitialState()));
		SurgSim::Framework::Timer totalTime;
		totalTime.beginFrame();
		for (int i = 0; i < frameCount; i++)
		{
			fem->getOdeSolver()->getLinearSolver()->setMatrix(fem->getOdeSolver()->getSystemMatrix());
		}
		totalTime.endFrame();
		RecordProperty("Duration", boost::to_string(totalTime.getCumulativeTime()));
	}

	void timeSolveSystem(std::shared_ptr<DivisibleCubeRepresentation> fem)
	{
		fem->getOdeSolver()->computeMatrices(dt, *(fem->getInitialState()));
		fem->getOdeSolver()->getLinearSolver()->setMatrix(fem->getOdeSolver()->getSystemMatrix());
		SurgSim::Framework::Timer totalTime;
		totalTime.beginFrame();
		for (int i = 0; i < frameCount; i++)
		{
			fem->getOdeSolver()->getLinearSolver()->solve(Math::Vector::Ones(fem->getInitialState()->getNumDof()));
		}
		totalTime.endFrame();
		RecordProperty("Duration", boost::to_string(totalTime.getCumulativeTime()));
	}

	void timeInvertSystem(std::shared_ptr<DivisibleCubeRepresentation> fem)
	{
		fem->getOdeSolver()->computeMatrices(dt, *(fem->getInitialState()));
		fem->getOdeSolver()->getLinearSolver()->setMatrix(fem->getOdeSolver()->getSystemMatrix());
		SurgSim::Framework::Timer totalTime;
		totalTime.beginFrame();
		for (int i = 0; i < frameCount; i++)
		{
			fem->getOdeSolver()->getLinearSolver()->getInverse();
		}
		totalTime.endFrame();
		RecordProperty("Duration", boost::to_string(totalTime.getCumulativeTime()));
	}

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

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

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

TEST_P(ComponentIntegrationSchemeAndCountParamTest, TimeMatrixInitialization)
{
	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<DivisibleCubeRepresentation>("cube", numCubes);
	// We need to add some boundary conditions for the static solver to not run into a singular matrix
	std::const_pointer_cast<SurgSim::Math::OdeState>(fem->getInitialState())->addBoundaryCondition(0);
	std::const_pointer_cast<SurgSim::Math::OdeState>(fem->getInitialState())->addBoundaryCondition(1);
	std::const_pointer_cast<SurgSim::Math::OdeState>(fem->getInitialState())->addBoundaryCondition(2);
	fem->setIntegrationScheme(integrationScheme);

	timeInitializeRepresentation(fem);
}

TEST_P(ComponentIntegrationSchemeAndCountParamTest, TimeMatrixAssembly)
{
	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<DivisibleCubeRepresentation>("cube", numCubes);
	fem->setIntegrationScheme(integrationScheme);
	// We need to add some boundary conditions for the static solver to not run into a singular matrix
	std::const_pointer_cast<SurgSim::Math::OdeState>(fem->getInitialState())->addBoundaryCondition(0);
	std::const_pointer_cast<SurgSim::Math::OdeState>(fem->getInitialState())->addBoundaryCondition(1);
	std::const_pointer_cast<SurgSim::Math::OdeState>(fem->getInitialState())->addBoundaryCondition(2);
	initializeRepresentation(fem);

	timeMatrixAssembly(fem);
}

TEST_P(ComponentIntegrationSchemeAndCountParamTest, TimeComputeLinearSystem)
{
	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<DivisibleCubeRepresentation>("cube", numCubes);
	fem->setIntegrationScheme(integrationScheme);
	// We need to add some boundary conditions for the static solver to not run into a singular matrix
	std::const_pointer_cast<SurgSim::Math::OdeState>(fem->getInitialState())->addBoundaryCondition(0);
	std::const_pointer_cast<SurgSim::Math::OdeState>(fem->getInitialState())->addBoundaryCondition(1);
	std::const_pointer_cast<SurgSim::Math::OdeState>(fem->getInitialState())->addBoundaryCondition(2);
	initializeRepresentation(fem);

	timeComputeLinearSystem(fem);
}

TEST_P(ComponentIntegrationSchemeAndCountParamTest, TimeSolveSystem)
{
	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<DivisibleCubeRepresentation>("cube", numCubes);
	fem->setIntegrationScheme(integrationScheme);
	// We need to add some boundary conditions for the static solver to not run into a singular matrix
	std::const_pointer_cast<SurgSim::Math::OdeState>(fem->getInitialState())->addBoundaryCondition(0);
	std::const_pointer_cast<SurgSim::Math::OdeState>(fem->getInitialState())->addBoundaryCondition(1);
	std::const_pointer_cast<SurgSim::Math::OdeState>(fem->getInitialState())->addBoundaryCondition(2);
	initializeRepresentation(fem);

	timeSolveSystem(fem);
}

TEST_P(ComponentIntegrationSchemeAndCountParamTest, TimeInvertSystem)
{
	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<DivisibleCubeRepresentation>("cube", numCubes);
	fem->setIntegrationScheme(integrationScheme);
	// We need to add some boundary conditions for the static solver to not run into a singular matrix
	std::const_pointer_cast<SurgSim::Math::OdeState>(fem->getInitialState())->addBoundaryCondition(0);
	std::const_pointer_cast<SurgSim::Math::OdeState>(fem->getInitialState())->addBoundaryCondition(1);
	std::const_pointer_cast<SurgSim::Math::OdeState>(fem->getInitialState())->addBoundaryCondition(2);
	initializeRepresentation(fem);

	timeInvertSystem(fem);
}

INSTANTIATE_TEST_CASE_P(
	Fem3DSolutionComponentsTest,
	ComponentIntegrationSchemeAndCountParamTest,
	::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,
					   SurgSim::Math::INTEGRATIONSCHEME_STATIC,
					   SurgSim::Math::INTEGRATIONSCHEME_LINEAR_STATIC,
					   SurgSim::Math::INTEGRATIONSCHEME_RUNGE_KUTTA_4,
					   SurgSim::Math::INTEGRATIONSCHEME_LINEAR_RUNGE_KUTTA_4),
					   ::testing::Values(2, 3, 4, 5, 6, 7, 8)));

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


<commit_before>//
//  AKPannerDSPKernel.hpp
//  AudioKit
//
//  Created by Aurelius Prochazka, revision history on Github.
//  Copyright © 2017 Aurelius Prochazka. All rights reserved.
//

#pragma once

#import "AKSoundpipeKernel.hpp"

enum {
    panAddress = 0
};

class AKPannerDSPKernel : public AKSoundpipeKernel, public AKBuffered {
public:
    // MARK: Member Functions

    AKPannerDSPKernel() {}

    void init(int _channels, double _sampleRate) override {
        AKSoundpipeKernel::init(_channels, _sampleRate);

        sp_panst_create(&panst);
        sp_panst_init(sp, panst);
        panst->pan = 0;

        panRamper.init();
    }

    void start() {
        started = true;
    }

    void stop() {
        started = false;
    }

    void destroy() {
        sp_panst_destroy(&panst);
        AKSoundpipeKernel::destroy();
    }

    void reset() {
        resetted = true;
        panRamper.reset();
    }

    void setPan(float value) {
        pan = clamp(value, -1.0f, 1.0f);
        panRamper.setImmediate(pan);
    }

    void setParameter(AUParameterAddress address, AUValue value) {
        switch (address) {
            case panAddress:
                panRamper.setUIValue(clamp(value, -1.0f, 1.0f));
                break;

        }
    }

    AUValue getParameter(AUParameterAddress address) {
        switch (address) {
            case panAddress:
                return panRamper.getUIValue();

            default: return 0.0f;
        }
    }

    void startRamp(AUParameterAddress address, AUValue value, AUAudioFrameCount duration) override {
        switch (address) {
            case panAddress:
                panRamper.startRamp(clamp(value, -1.0f, 1.0f), duration);
                break;

        }
    }

    void process(AUAudioFrameCount frameCount, AUAudioFrameCount bufferOffset) override {

        for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) {

            int frameOffset = int(frameIndex + bufferOffset);

            pan = panRamper.getAndStep();
            panst->pan = (float)pan;

            if (!started) {
                outBufferListPtr->mBuffers[0] = inBufferListPtr->mBuffers[0];
                outBufferListPtr->mBuffers[1] = inBufferListPtr->mBuffers[1];
                return;
            }

            float *tmpin[2];
            float *tmpout[2];
            for (int channel = 0; channel < channels; ++channel) {
                float *in  = (float *)inBufferListPtr->mBuffers[channel].mData  + frameOffset;
                float *out = (float *)outBufferListPtr->mBuffers[channel].mData + frameOffset;
                if (channel < 2) {
                    tmpin[channel] = in;
                    tmpout[channel] = out;
                }
            }
            sp_panst_compute(sp, panst, tmpin[0], tmpin[1], tmpout[0], tmpout[1]);

        }
    }

    // MARK: Member Variables

private:

    sp_panst *panst;

    float pan = 0.0;

public:
    bool started = true;
    bool resetted = false;
    ParameterRamper panRamper = 0;
};

<commit_msg>Addresses https://github.com/AudioKit/AudioKit/issues/953<commit_after>//
//  AKPannerDSPKernel.hpp
//  AudioKit
//
//  Created by Aurelius Prochazka, revision history on Github.
//  Copyright © 2017 Aurelius Prochazka. All rights reserved.
//

#pragma once

#import "AKSoundpipeKernel.hpp"

enum {
    panAddress = 0
};

class AKPannerDSPKernel : public AKSoundpipeKernel, public AKBuffered {
public:
    // MARK: Member Functions

    AKPannerDSPKernel() {}

    void init(int _channels, double _sampleRate) override {
        AKSoundpipeKernel::init(_channels, _sampleRate);

        sp_panst_create(&panst);
        sp_panst_init(sp, panst);
        panst->pan = 0;

        panRamper.init();
    }

    void start() {
        started = true;
    }

    void stop() {
        started = false;
    }

    void destroy() {
        sp_panst_destroy(&panst);
        AKSoundpipeKernel::destroy();
    }

    void reset() {
        resetted = true;
        panRamper.reset();
    }

    void setPan(float value) {
        pan = clamp(value, -1.0f, 1.0f);
        panRamper.setImmediate(pan);
    }

    void setParameter(AUParameterAddress address, AUValue value) {
        switch (address) {
            case panAddress:
                panRamper.setUIValue(clamp(value, -1.0f, 1.0f));
                break;

        }
    }

    AUValue getParameter(AUParameterAddress address) {
        switch (address) {
            case panAddress:
                return panRamper.getUIValue();

            default: return 0.0f;
        }
    }

    void startRamp(AUParameterAddress address, AUValue value, AUAudioFrameCount duration) override {
        switch (address) {
            case panAddress:
                panRamper.startRamp(clamp(value, -1.0f, 1.0f), duration);
                break;

        }
    }

    void process(AUAudioFrameCount frameCount, AUAudioFrameCount bufferOffset) override {

        for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) {

            int frameOffset = int(frameIndex + bufferOffset);

            pan = panRamper.getAndStep();
            panst->pan = (float)pan;

            if (!started || AKSettings.numberOfChannels != 2) {
                outBufferListPtr->mBuffers[0] = inBufferListPtr->mBuffers[0];
                outBufferListPtr->mBuffers[1] = inBufferListPtr->mBuffers[1];
                return;
            }

            float *tmpin[2];
            float *tmpout[2];
            for (int channel = 0; channel < channels; ++channel) {
                float *in  = (float *)inBufferListPtr->mBuffers[channel].mData  + frameOffset;
                float *out = (float *)outBufferListPtr->mBuffers[channel].mData + frameOffset;
                if (channel < 2) {
                    tmpin[channel] = in;
                    tmpout[channel] = out;
                }
            }
            sp_panst_compute(sp, panst, tmpin[0], tmpin[1], tmpout[0], tmpout[1]);

        }
    }

    // MARK: Member Variables

private:

    sp_panst *panst;

    float pan = 0.0;

public:
    bool started = true;
    bool resetted = false;
    ParameterRamper panRamper = 0;
};

<|endoftext|>


<commit_before>/*
 * Recognizer.cc
 *
 * Copyright (C) 2015 Linas Vepstas
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the
 * exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public
 * License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <opencog/atoms/core/FindUtils.h>
#include "Recognizer.h"

using namespace opencog;

// Uncomment below to enable debug print
#define DEBUG 1
#ifdef DEBUG
#define dbgprt(f, varargs...) logger().fine(f, ##varargs)
#else
#define dbgprt(f, varargs...)
#endif

/* ======================================================== */

bool Recognizer::do_search(PatternMatchEngine* pme, const Handle& top)
{
	if (top->is_link())
	{
		// Recursively drill down and explore every possible node as
		// a search starting point. This is needed, as the patterns we
		// compare against might not be connected.
		for (const Handle& h : top->getOutgoingSet())
		{
			_starter_term = top;
			bool found = do_search(pme, h);
			if (found) return true;
		}
		return false;
	}

	IncomingSet iset = get_incoming_set(top);
	size_t sz = iset.size();
	for (size_t i = 0; i < sz; i++)
	{
		Handle h(iset[i]);
		dbgprt("rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr\n");
		dbgprt("Loop candidate (%lu - %s):\n%s\n", _cnt++,
		       top->to_short_string().c_str(),
		       h->to_short_string().c_str());
		bool found = pme->explore_neighborhood(_root, _starter_term, h);

		// Terminate search if satisfied.
		if (found) return true;
   }

	return false;
}

bool Recognizer::initiate_search(PatternMatchEngine* pme)
{
	const HandleSeq& clauses = _pattern->cnf_clauses;

	_cnt = 0;
	for (const Handle& h: clauses)
	{
		_root = h;
		bool found = do_search(pme, h);
		if (found) return true;
	}
	return false;
}

bool Recognizer::node_match(const Handle& npat_h, const Handle& nsoln_h)
{
	// If it's a match, we can accept it right away, the comparison
	// is done already, see link_match below.
	if (match) return true;

	if (npat_h == nsoln_h) return true;
	if (VARIABLE_NODE == nsoln_h->get_type()) return true;
	return false;
}

bool Recognizer::link_match(const PatternTermPtr& ptm, const Handle& lsoln)
{
	match = false;
	const Handle& lpat = ptm->getHandle();

	// Self-compares always proceed.
	if (lpat == lsoln) return true;

	// mis-matched types are a dead-end.
	if (lpat->get_type() != lsoln->get_type()) return false;

	// TODO: Change to something better if possible...
	// What is happening here is to manually call the
	// fuzzy_match callback immediately if and only if
	// lsoln has one or more GlobNodes AND lpat and lsoln
	// have the same arity.
	// The reason is, if the pat and soln are having the
	// size, pattern matcher will then do a side-by-side
	// comparison on their outgoing atoms.
	// In the typical use cases we have at the moment,
	// the comparison will be done in the node_match
	// callback. However that will cause problems in some
	// situations, for example if we have:
	// === lpat ===      === lsoln ===
	// Concept "A"       Glob $x
	// Concept "B"       Concept "A"
	// Concept "C"       Glob $y
	// and both of the globs $x and $y have an interval
	// restriction of zero to infinity, it should be a
	// match by grounding $x to nothing and $y to Concept
	// "B" and "C". But a side-by-side comparison here
	// only compares their nodes at the same position
	// (i.e. A-$x, B-A, C-$y), and decide whether to
	// reject it when there is a mis-match. As a result
	// a lot of candidates that we are expecting are
	// rejected...
	// And the reason of going to fuzzy_match is that
	// all the glob-matching logic is there, so it
	// should be able to handle this better.
	if (contains_atomtype(lsoln, GLOB_NODE) and
	    lpat->get_arity() == lsoln->get_arity())
	{
		if (fuzzy_match(lpat, lsoln))
		{
			match = true;
			return true;
		}
		else return false;
	}

	return true;
}

bool Recognizer::loose_match(const Handle& npat_h, const Handle& nsoln_h)
{
	Type gtype = nsoln_h->get_type();
	// Variable matches anything; move to next.
	if (VARIABLE_NODE == gtype) return true;

	// Strict match for link types.
	if (npat_h->get_type() != gtype) return false;
	if (not npat_h->is_node()) return true;

	// If we are here, we know we have nodes. Ask for a strict match.
	if (npat_h != nsoln_h) return false;
	return true;
}

bool Recognizer::fuzzy_match(const Handle& npat_h, const Handle& nsoln_h)
{
	// If we are here, then there are probably glob nodes in the soln.
	// Try to match them, fairly rigorously. Exactly what constitutes
	// an OK match is still a bit up in the air.

	if (not npat_h->is_link() or not nsoln_h->is_link()) return false;

	const HandleSeq &osg = nsoln_h->getOutgoingSet();
	size_t osg_size = osg.size();

	// Lets not waste time, if there's no glob there.
	bool have_glob = false;
	for (size_t j=0; j<osg_size; j++)
	{
		if (osg[j]->get_type() == GLOB_NODE)
		{
			have_glob = true;
			break;
		}
	}
	if (not have_glob) return false;

	const HandleSeq &osp = npat_h->getOutgoingSet();
	size_t osp_size = osp.size();

	// Do a side-by-side compare. This is not as rigorous as
	// PatternMatchEngine::tree_compare() nor does it handle the bells
	// and whistles (ChoiceLink, QuoteLink, etc).
	size_t ip=0, jg=0;
	for (; ip<osp_size or jg<osg_size; ip++, jg++)
	{
		if (ip == osp_size) ip--;
		if (jg == osg_size) jg--;

		if (GLOB_NODE != osg[jg]->get_type())
		{
			if (loose_match(osp[ip], osg[jg])) continue;
			return false;
		}

		// If we are here, we have a glob in the soln. If the glob is at
		// the end, it eats everything, so its a match. Else, resume
		// matching at the end of the glob.
		if ((jg+1) == osg_size) return true;

		const Handle& post(osg[jg+1]);

		// If the post is also a GlobNode, we are done for this one.
		if (GLOB_NODE == post->get_type()) return true;

		// Match as many as possible.
		while (ip < osp_size and not loose_match(osp[ip], post))
		{
			ip++;
		}

		// Go around again, look for more GlobNodes. Back up by one, so
		// that the for-loop increment gets us back on track.
		ip--;
	}

	// If we are here, then we should have matched up all the atoms.
	return true;
}

bool Recognizer::grounding(const HandleMap& var_soln,
                           const HandleMap& term_soln)
{
	Handle rule = term_soln.at(_root);

	if (rule != _root) {
		_rules.insert(rule);
	}

	// Look for more groundings.
	return false;
}
<commit_msg>Search only the mandatory clauses.<commit_after>/*
 * Recognizer.cc
 *
 * Copyright (C) 2015 Linas Vepstas
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the
 * exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public
 * License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <opencog/atoms/core/FindUtils.h>
#include "Recognizer.h"

using namespace opencog;

// Uncomment below to enable debug print
#define DEBUG 1
#ifdef DEBUG
#define dbgprt(f, varargs...) logger().fine(f, ##varargs)
#else
#define dbgprt(f, varargs...)
#endif

/* ======================================================== */

bool Recognizer::do_search(PatternMatchEngine* pme, const Handle& top)
{
	if (top->is_link())
	{
		// Recursively drill down and explore every possible node as
		// a search starting point. This is needed, as the patterns we
		// compare against might not be connected.
		for (const Handle& h : top->getOutgoingSet())
		{
			_starter_term = top;
			bool found = do_search(pme, h);
			if (found) return true;
		}
		return false;
	}

	IncomingSet iset = get_incoming_set(top);
	size_t sz = iset.size();
	for (size_t i = 0; i < sz; i++)
	{
		Handle h(iset[i]);
		dbgprt("rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr\n");
		dbgprt("Loop candidate (%lu - %s):\n%s\n", _cnt++,
		       top->to_short_string().c_str(),
		       h->to_short_string().c_str());
		bool found = pme->explore_neighborhood(_root, _starter_term, h);

		// Terminate search if satisfied.
		if (found) return true;
   }

	return false;
}

bool Recognizer::initiate_search(PatternMatchEngine* pme)
{
	const HandleSeq& clauses = _pattern->mandatory;

	_cnt = 0;
	for (const Handle& h: clauses)
	{
		_root = h;
		bool found = do_search(pme, h);
		if (found) return true;
	}
	return false;
}

bool Recognizer::node_match(const Handle& npat_h, const Handle& nsoln_h)
{
	// If it's a match, we can accept it right away, the comparison
	// is done already, see link_match below.
	if (match) return true;

	if (npat_h == nsoln_h) return true;
	if (VARIABLE_NODE == nsoln_h->get_type()) return true;
	return false;
}

bool Recognizer::link_match(const PatternTermPtr& ptm, const Handle& lsoln)
{
	match = false;
	const Handle& lpat = ptm->getHandle();

	// Self-compares always proceed.
	if (lpat == lsoln) return true;

	// mis-matched types are a dead-end.
	if (lpat->get_type() != lsoln->get_type()) return false;

	// TODO: Change to something better if possible...
	// What is happening here is to manually call the
	// fuzzy_match callback immediately if and only if
	// lsoln has one or more GlobNodes AND lpat and lsoln
	// have the same arity.
	// The reason is, if the pat and soln are having the
	// size, pattern matcher will then do a side-by-side
	// comparison on their outgoing atoms.
	// In the typical use cases we have at the moment,
	// the comparison will be done in the node_match
	// callback. However that will cause problems in some
	// situations, for example if we have:
	// === lpat ===      === lsoln ===
	// Concept "A"       Glob $x
	// Concept "B"       Concept "A"
	// Concept "C"       Glob $y
	// and both of the globs $x and $y have an interval
	// restriction of zero to infinity, it should be a
	// match by grounding $x to nothing and $y to Concept
	// "B" and "C". But a side-by-side comparison here
	// only compares their nodes at the same position
	// (i.e. A-$x, B-A, C-$y), and decide whether to
	// reject it when there is a mis-match. As a result
	// a lot of candidates that we are expecting are
	// rejected...
	// And the reason of going to fuzzy_match is that
	// all the glob-matching logic is there, so it
	// should be able to handle this better.
	if (contains_atomtype(lsoln, GLOB_NODE) and
	    lpat->get_arity() == lsoln->get_arity())
	{
		if (fuzzy_match(lpat, lsoln))
		{
			match = true;
			return true;
		}
		else return false;
	}

	return true;
}

bool Recognizer::loose_match(const Handle& npat_h, const Handle& nsoln_h)
{
	Type gtype = nsoln_h->get_type();
	// Variable matches anything; move to next.
	if (VARIABLE_NODE == gtype) return true;

	// Strict match for link types.
	if (npat_h->get_type() != gtype) return false;
	if (not npat_h->is_node()) return true;

	// If we are here, we know we have nodes. Ask for a strict match.
	if (npat_h != nsoln_h) return false;
	return true;
}

bool Recognizer::fuzzy_match(const Handle& npat_h, const Handle& nsoln_h)
{
	// If we are here, then there are probably glob nodes in the soln.
	// Try to match them, fairly rigorously. Exactly what constitutes
	// an OK match is still a bit up in the air.

	if (not npat_h->is_link() or not nsoln_h->is_link()) return false;

	const HandleSeq &osg = nsoln_h->getOutgoingSet();
	size_t osg_size = osg.size();

	// Lets not waste time, if there's no glob there.
	bool have_glob = false;
	for (size_t j=0; j<osg_size; j++)
	{
		if (osg[j]->get_type() == GLOB_NODE)
		{
			have_glob = true;
			break;
		}
	}
	if (not have_glob) return false;

	const HandleSeq &osp = npat_h->getOutgoingSet();
	size_t osp_size = osp.size();

	// Do a side-by-side compare. This is not as rigorous as
	// PatternMatchEngine::tree_compare() nor does it handle the bells
	// and whistles (ChoiceLink, QuoteLink, etc).
	size_t ip=0, jg=0;
	for (; ip<osp_size or jg<osg_size; ip++, jg++)
	{
		if (ip == osp_size) ip--;
		if (jg == osg_size) jg--;

		if (GLOB_NODE != osg[jg]->get_type())
		{
			if (loose_match(osp[ip], osg[jg])) continue;
			return false;
		}

		// If we are here, we have a glob in the soln. If the glob is at
		// the end, it eats everything, so its a match. Else, resume
		// matching at the end of the glob.
		if ((jg+1) == osg_size) return true;

		const Handle& post(osg[jg+1]);

		// If the post is also a GlobNode, we are done for this one.
		if (GLOB_NODE == post->get_type()) return true;

		// Match as many as possible.
		while (ip < osp_size and not loose_match(osp[ip], post))
		{
			ip++;
		}

		// Go around again, look for more GlobNodes. Back up by one, so
		// that the for-loop increment gets us back on track.
		ip--;
	}

	// If we are here, then we should have matched up all the atoms.
	return true;
}

bool Recognizer::grounding(const HandleMap& var_soln,
                           const HandleMap& term_soln)
{
	Handle rule = term_soln.at(_root);

	if (rule != _root) {
		_rules.insert(rule);
	}

	// Look for more groundings.
	return false;
}
<|endoftext|>


<commit_before>#include "AConfig.h"
#if(HAS_STD_CALIBRATIONLASERS)
#include "Device.h"
#include "Pin.h"
#include "CalibrationLaser.h"
#include "Settings.h"

Pin claser("claser", CALIBRATIONLASERS_PIN, claser.analog, claser.out);

void CalibrationLaser::device_setup(){
    Settings::capability_bitarray |= (1 << CALIBRATION_LASERS_CAPABLE);
    claser.write(0);
}

void CalibrationLaser::device_loop(Command command){
    if( command.cmp("claser")){
      int value = command.args[1];
      claser.write(value);
      claser.send(value);
    }

}
#endif

<commit_msg>Revert "Adding laser indicator"<commit_after>#include "AConfig.h"
#if(HAS_STD_CALIBRATIONLASERS)
#include "Device.h"
#include "Pin.h"
#include "CalibrationLaser.h"
#include "Settings.h"

Pin claser("claser", CALIBRATIONLASERS_PIN, claser.analog, claser.out);

void CalibrationLaser::device_setup(){
    Settings::capability_bitarray |= (1 << CALIBRATION_LASERS_CAPABLE);
    claser.write(0);
}

void CalibrationLaser::device_loop(Command command){
    if( command.cmp("claser")){
      int value = command.args[1];
      claser.write(value);
    }

}
#endif

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: HashMaps.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: mtg $ $Date: 2001-07-04 14:56:13 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): Martin Gallwey (gallwey@sun.com)
 *
 *
 ************************************************************************/
#ifndef _HASHMAPS_HXX
#define _HASHMAPS_HXX

#ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_
#include <com/sun/star/container/XNameContainer.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XUNOTUNNEl_HPP_
#include <com/sun/star/lang/XUnoTunnel.hpp>
#endif
#include <hash_map>

struct eqFunc
{
    sal_Bool operator()( const rtl::OUString &r1,
                         const rtl::OUString &r2) const
    {
        return r1 == r2;
    }
};

typedef std::hash_map < rtl::OUString,
                        com::sun::star::uno::Reference < com::sun::star::lang::XUnoTunnel >,
                        ::rtl::OUStringHash,
                        eqFunc > TunnelHash;

typedef std::hash_map < rtl::OUString,
                        com::sun::star::uno::Reference < com::sun::star::container::XNameContainer >,
                        ::rtl::OUStringHash,
                        eqFunc > NameHash;
#endif
<commit_msg>#89303# optimise hash maps for speed (and put them all in one place)<commit_after>/*************************************************************************
 *
 *  $RCSfile: HashMaps.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: mtg $ $Date: 2001-09-14 14:38:16 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): Martin Gallwey (gallwey@sun.com)
 *
 *
 ************************************************************************/
#ifndef _HASHMAPS_HXX
#define _HASHMAPS_HXX

#ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_
#include <com/sun/star/container/XNameContainer.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XUNOTUNNEl_HPP_
#include <com/sun/star/lang/XUnoTunnel.hpp>
#endif
#ifndef _ZIP_ENTRY_HXX_
#include <ZipEntry.hxx>
#endif
#include <hash_map>

struct eqFunc
{
    sal_Bool operator()( const rtl::OUString &r1,
                         const rtl::OUString &r2) const
    {
        return r1 == r2;
    }
};

class ZipPackageFolder;
struct ContentInfo;

typedef std::hash_map < rtl::OUString,
                        ZipPackageFolder *,
                        ::rtl::OUStringHash,
                        eqFunc > FolderHash;

typedef std::hash_map < rtl::OUString,
                        ContentInfo *,
                        ::rtl::OUStringHash,
                        eqFunc > ContentHash;

typedef std::hash_map < rtl::OUString,
                        ZipEntry,
                        rtl::OUStringHash,
                        eqFunc > EntryHash;

#endif
<|endoftext|>


<commit_before>// Declares clang::SyntaxOnlyAction.
#include "clang/Frontend/FrontendActions.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
// Declares llvm::cl::extrahelp.
#include "llvm/Support/CommandLine.h"

#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"

using namespace clang;
using namespace clang::ast_matchers;
using namespace clang::tooling;
using namespace llvm;

// Apply a custom category to all command-line options so that they are the
// only ones displayed.
static llvm::cl::OptionCategory MyToolCategory("my-tool options");

// CommonOptionsParser declares HelpMessage with a description of the common
// command-line options related to the compilation database and input files.
// It's nice to have this help message in all tools.
static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);

// A help message for this specific tool can be added afterwards.
static cl::extrahelp MoreHelp("\nMore help text...");

namespace {
bool areSameVariable(const ValueDecl *First, const ValueDecl *Second) {
  return First && Second &&
         First->getCanonicalDecl() == Second->getCanonicalDecl();
}

bool areSameExpr(ASTContext *Context, const Expr *First, const Expr *Second) {
  if (!First || !Second)
    return false;
  llvm::FoldingSetNodeID FirstID, SecondID;
  First->Profile(FirstID, *Context, true);
  Second->Profile(SecondID, *Context, true);
  return FirstID == SecondID;
}

std::string getName(const CXXRecordDecl &RD) {
  std::string NameWithTemplateArgs;
  llvm::raw_string_ostream OS(NameWithTemplateArgs);
  RD.getNameForDiagnostic(OS, RD.getASTContext().getPrintingPolicy(), true);
  return OS.str();
}

std::string stringRemove(const std::string &S, const std::string &ToRemove) {
  std::string Result;
  size_t Index = 0, Off = 0;
  while ((Index = S.find(ToRemove, Off)) != -1) {
    Result += S.substr(Off, Index - Off);
    Off = Index + ToRemove.length();
  }
  Result += S.substr(Off, S.length() - Off);
  return Result;
}

std::string getName(const TemplateArgument &TA) {
  auto Name = TA.getAsType().getAsString();
  return stringRemove(stringRemove(Name, "struct "), "clang ");
}
} // namespace

enum class TransitionType {
  Sibling,
  Inner,
  InnerEntry,
  No,
};

static const char *TransitionTypeString[] = {"Sibling", "Inner", "InnerEntry",
                                             "No"};

static const char *TransitionTypeVisualString[] = {"--->", "==>>", "===>",
                                                   "XXXX"};

inline TransitionType fuzzyNameToTransitionType(const StringRef &Name) {
  auto contains = [](auto stringRef, auto s) {
    return stringRef.find(s) != StringRef::npos;
  };

  if (contains(Name, "SiblingTransition"))
    return TransitionType::Sibling;
  if (contains(Name, "InnerTransition"))
    return TransitionType::Inner;
  if (contains(Name, "InnerEntryTransition"))
    return TransitionType::InnerEntry;
  assert(contains(Name, "No"));
  return TransitionType::No;
}

// Matches declaration of transition functions that actually cause a transition
// to occur (i.e. everything except NoTransition)
const auto TransitionFunctionDecl = hasDeclaration(eachOf(
    functionDecl(hasName("InnerTransition")).bind("trans_func_decl"),
    functionDecl(hasName("InnerEntryTransition")).bind("trans_func_decl"),
    functionDecl(hasName("SiblingTransition")).bind("trans_func_decl")));

// Matches transition function expressions (i.e. calls to transition functions)
const auto TransitionFunctionMatcher = callExpr(
    expr().bind("call_expr"),
    // Look for calls to transition functions
    TransitionFunctionDecl,
    // We track ancestor call expressions to determine if the call is actually a
    // state arg
    anyOf(hasAncestor(
              callExpr(TransitionFunctionDecl).bind("arg_parent_call_expr")),
          anything()));

// Matches transition function expressions within states
const auto StateTransitionMatcher =
    cxxRecordDecl(decl().bind("state"), isDerivedFrom("hsm::State"),
                  forEachDescendant(TransitionFunctionMatcher));

class StateTransitionMapper : public MatchFinder::MatchCallback {
  using TargetStateName = std::string;
  std::map<const CallExpr *, TargetStateName> _callExprToTargetState;

public:
  virtual void run(const MatchFinder::MatchResult &Result) {
    const auto StateDecl = Result.Nodes.getNodeAs<CXXRecordDecl>("state");
    const auto TransCallExpr = Result.Nodes.getNodeAs<CallExpr>("call_expr");
    const auto TransitionFuncDecl =
        Result.Nodes.getNodeAs<FunctionDecl>("trans_func_decl");
    const auto ArgParentCallExpr =
        Result.Nodes.getNodeAs<CallExpr>("arg_parent_call_expr");

    assert(StateDecl);
    assert(TransCallExpr);
    assert(TransitionFuncDecl);

    const auto TransType = fuzzyNameToTransitionType(
        TransitionFuncDecl->getCanonicalDecl()->getName());

    auto SourceStateName = getName(*StateDecl);

    // We only match transition functions that accept target state as a template
    // parameter
    // @TODO: support transition functions that accept StateFactory?
    assert(TransitionFuncDecl->getTemplateSpecializationInfo());
    const auto TSI = TransitionFuncDecl->getTemplateSpecializationInfo();
    const TemplateArgument &TA = TSI->TemplateArguments->get(0);
    const auto TargetStateName = getName(TA);

    // If our transition is a state arg, we get the top-most transition's
    // target state and assume that this target state is the one that will
    // return the current transition. To do this, we track the top-most
    // CallExpr -> TargetStateName mapping.
    if (!ArgParentCallExpr) {
      // We're top-most, remember current target state
      assert(_callExprToTargetState.find(TransCallExpr) ==
             _callExprToTargetState.end());
      _callExprToTargetState[TransCallExpr] = TargetStateName;
    } else {
      // Othwerise, use immediate parent CallExpr's target state as our
      // source state, and remember it for potential child CallExprs
      auto iter = _callExprToTargetState.find(ArgParentCallExpr);
      assert(iter != _callExprToTargetState.end());
      _callExprToTargetState[TransCallExpr] = iter->second;

      // Override the source state name with the top-most CallExpr one
      SourceStateName = iter->second;
    }

    llvm::outs() << SourceStateName << " "
                 << TransitionTypeVisualString[static_cast<int>(TransType)]
                 << " " << TargetStateName << "\n";
  }
};

int main(int argc, const char **argv) {
  CommonOptionsParser OptionsParser(argc, argv, MyToolCategory);
  ClangTool Tool(OptionsParser.getCompilations(),
                 OptionsParser.getSourcePathList());

  StateTransitionMapper Mapper;
  MatchFinder Finder;
  Finder.addMatcher(StateTransitionMatcher, &Mapper);

  return Tool.run(newFrontendActionFactory(&Finder).get());
}
<commit_msg>Fix assert on non-templated transition functions (e.g. state overrides)<commit_after>// Declares clang::SyntaxOnlyAction.
#include "clang/Frontend/FrontendActions.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
// Declares llvm::cl::extrahelp.
#include "llvm/Support/CommandLine.h"

#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"

using namespace clang;
using namespace clang::ast_matchers;
using namespace clang::tooling;
using namespace llvm;

// Apply a custom category to all command-line options so that they are the
// only ones displayed.
static llvm::cl::OptionCategory MyToolCategory("my-tool options");

// CommonOptionsParser declares HelpMessage with a description of the common
// command-line options related to the compilation database and input files.
// It's nice to have this help message in all tools.
static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);

// A help message for this specific tool can be added afterwards.
static cl::extrahelp MoreHelp("\nMore help text...");

namespace {
bool areSameVariable(const ValueDecl *First, const ValueDecl *Second) {
  return First && Second &&
         First->getCanonicalDecl() == Second->getCanonicalDecl();
}

bool areSameExpr(ASTContext *Context, const Expr *First, const Expr *Second) {
  if (!First || !Second)
    return false;
  llvm::FoldingSetNodeID FirstID, SecondID;
  First->Profile(FirstID, *Context, true);
  Second->Profile(SecondID, *Context, true);
  return FirstID == SecondID;
}

std::string getName(const CXXRecordDecl &RD) {
  std::string NameWithTemplateArgs;
  llvm::raw_string_ostream OS(NameWithTemplateArgs);
  RD.getNameForDiagnostic(OS, RD.getASTContext().getPrintingPolicy(), true);
  return OS.str();
}

std::string stringRemove(const std::string &S, const std::string &ToRemove) {
  std::string Result;
  size_t Index = 0, Off = 0;
  while ((Index = S.find(ToRemove, Off)) != -1) {
    Result += S.substr(Off, Index - Off);
    Off = Index + ToRemove.length();
  }
  Result += S.substr(Off, S.length() - Off);
  return Result;
}

std::string getName(const TemplateArgument &TA) {
  auto Name = TA.getAsType().getAsString();
  return stringRemove(stringRemove(Name, "struct "), "clang ");
}
} // namespace

enum class TransitionType {
  Sibling,
  Inner,
  InnerEntry,
  No,
};

static const char *TransitionTypeString[] = {"Sibling", "Inner", "InnerEntry",
                                             "No"};

static const char *TransitionTypeVisualString[] = {"--->", "==>>", "===>",
                                                   "XXXX"};

inline TransitionType fuzzyNameToTransitionType(const StringRef &Name) {
  auto contains = [](auto stringRef, auto s) {
    return stringRef.find(s) != StringRef::npos;
  };

  if (contains(Name, "SiblingTransition"))
    return TransitionType::Sibling;
  if (contains(Name, "InnerTransition"))
    return TransitionType::Inner;
  if (contains(Name, "InnerEntryTransition"))
    return TransitionType::InnerEntry;
  assert(contains(Name, "No"));
  return TransitionType::No;
}

// Matches declaration of transition functions that actually cause a transition
// to occur (i.e. everything except NoTransition)
const auto TransitionFunctionDecl = hasDeclaration(eachOf(
    functionDecl(hasName("InnerTransition")).bind("trans_func_decl"),
    functionDecl(hasName("InnerEntryTransition")).bind("trans_func_decl"),
    functionDecl(hasName("SiblingTransition")).bind("trans_func_decl")));

// Matches transition function expressions (i.e. calls to transition functions)
const auto TransitionFunctionMatcher = callExpr(
    expr().bind("call_expr"),
    // Look for calls to transition functions
    TransitionFunctionDecl,
    // We track ancestor call expressions to determine if the call is actually a
    // state arg
    anyOf(hasAncestor(
              callExpr(TransitionFunctionDecl).bind("arg_parent_call_expr")),
          anything()));

// Matches transition function expressions within states
const auto StateTransitionMatcher =
    cxxRecordDecl(decl().bind("state"), isDerivedFrom("hsm::State"),
                  forEachDescendant(TransitionFunctionMatcher));

class StateTransitionMapper : public MatchFinder::MatchCallback {
  using TargetStateName = std::string;
  std::map<const CallExpr *, TargetStateName> _callExprToTargetState;

public:
  virtual void run(const MatchFinder::MatchResult &Result) {
    const auto StateDecl = Result.Nodes.getNodeAs<CXXRecordDecl>("state");
    const auto TransCallExpr = Result.Nodes.getNodeAs<CallExpr>("call_expr");
    const auto TransitionFuncDecl =
        Result.Nodes.getNodeAs<FunctionDecl>("trans_func_decl");
    const auto ArgParentCallExpr =
        Result.Nodes.getNodeAs<CallExpr>("arg_parent_call_expr");

    assert(StateDecl);
    assert(TransCallExpr);
    assert(TransitionFuncDecl);

    const auto TransType = fuzzyNameToTransitionType(
        TransitionFuncDecl->getCanonicalDecl()->getName());

    auto SourceStateName = getName(*StateDecl);

    // We currently only support transition functions that accept target state
    // as a template parameter.
    // @TODO: support transition functions that accept StateFactory (e.g. state
    // overrides).
    const auto TSI = TransitionFuncDecl->getTemplateSpecializationInfo();
    if (!TSI)
      return;
    const TemplateArgument &TA = TSI->TemplateArguments->get(0);

    const auto TargetStateName = getName(TA);

    // If our transition is a state arg, we get the top-most transition's
    // target state and assume that this target state is the one that will
    // return the current transition. To do this, we track the top-most
    // CallExpr -> TargetStateName mapping.
    if (!ArgParentCallExpr) {
      // We're top-most, remember current target state
      assert(_callExprToTargetState.find(TransCallExpr) ==
             _callExprToTargetState.end());
      _callExprToTargetState[TransCallExpr] = TargetStateName;
    } else {
      // Othwerise, use immediate parent CallExpr's target state as our
      // source state, and remember it for potential child CallExprs
      auto iter = _callExprToTargetState.find(ArgParentCallExpr);
      assert(iter != _callExprToTargetState.end());
      _callExprToTargetState[TransCallExpr] = iter->second;

      // Override the source state name with the top-most CallExpr one
      SourceStateName = iter->second;
    }

    llvm::outs() << SourceStateName << " "
                 << TransitionTypeVisualString[static_cast<int>(TransType)]
                 << " " << TargetStateName << "\n";
  }
};

int main(int argc, const char **argv) {
  CommonOptionsParser OptionsParser(argc, argv, MyToolCategory);
  ClangTool Tool(OptionsParser.getCompilations(),
                 OptionsParser.getSourcePathList());

  StateTransitionMapper Mapper;
  MatchFinder Finder;
  Finder.addMatcher(StateTransitionMatcher, &Mapper);

  return Tool.run(newFrontendActionFactory(&Finder).get());
}
<|endoftext|>


<commit_before>#include "pch.hpp"
#include "DependentGraphics.hpp"
#include "GameWindow.hpp"
#include "D3DHelpers.hpp"
#include <d3d11.h>

using namespace std::literals;

namespace dx
{
    namespace Internal
    {
        template<typename T>
        wrl::ComPtr<T> GetParent(IDXGIObject& object)
        {
            void* ptr;
            TryHR(object.GetParent(__uuidof(T), &ptr));
            return { static_cast<T*>(ptr) };
        }
    }

    SwapChain::SwapChain(ID3D11Device& device, const GameWindow& window, const SwapChainOptions& options)
        : options_{ options }
    {
        wrl::ComPtr<IDXGIDevice1> dxgiDevice;
        TryHR(device.QueryInterface(dxgiDevice.GetAddressOf()));
        const auto adapter = Internal::GetParent<IDXGIAdapter1>(Ref(dxgiDevice));
        const auto factory = Internal::GetParent<IDXGIFactory1>(Ref(adapter));
        DXGI_SWAP_CHAIN_DESC desc = {};
        desc.BufferCount = gsl::narrow<UINT>(options.CountOfBackBuffers);
        desc.BufferDesc.Width = gsl::narrow<UINT>(window.GetWidth());
        desc.BufferDesc.Height = gsl::narrow<UINT>(window.GetHeight());
        desc.BufferDesc.Format = static_cast<DXGI_FORMAT>(options.BackBufferFormat);
        desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
        desc.OutputWindow = window.NativeHandle();
        desc.SampleDesc.Count = 1;
        desc.SampleDesc.Quality = 0;
        desc.Windowed = options.Windowed == true ? TRUE : FALSE;
        TryHR(factory->CreateSwapChain(&device, &desc, swapChain_.GetAddressOf()));
        UpdateBuffers(device);
    }

    SwapChain::~SwapChain()
    {
    }

    auto SwapChain::Front() -> BackBuffer&
    {
        return backBuffer_;
    }

    void SwapChain::Present()
    {
        TryHR(swapChain_->Present(0, 0));
    }

    void SwapChain::Reset()
    {
        backBuffer_.Reset();
    }

    //https://stackoverflow.com/questions/28095798/how-to-change-window-size-in-directx-11-desktop-application
    void SwapChain::Resize(ID3D11Device& device, std::uint32_t height, std::uint32_t width)
    {
        TryHR(swapChain_->ResizeBuffers(options_.CountOfBackBuffers, gsl::narrow<UINT>(height), gsl::narrow<UINT>(width), static_cast<DXGI_FORMAT>(options_.BackBufferFormat), 0));
        UpdateBuffers(device);
    }

    void SwapChain::UpdateBuffers(ID3D11Device& device)
    {
        //https://msdn.microsoft.com/en-us/library/windows/desktop/mt427784%28v=vs.85%29.aspx
        //In Direct3D 11, applications could call GetBuffer(0, ) only once.Every call to Present implicitly changed the resource identity of the returned interface.
        backBuffer_ = BackBuffer{device, GetBuffer(Ref(swapChain_), 0) };
    }

    wrl::ComPtr<ID3D11Texture2D> GetBuffer(IDXGISwapChain& swapChain, std::uint32_t index)
    {
        wrl::ComPtr<ID3D11Texture2D> tex;
        void* ptr;
        TryHR(swapChain.GetBuffer(gsl::narrow<UINT>(index), __uuidof(ID3D11Texture2D), &ptr));
        tex.Attach(static_cast<ID3D11Texture2D*>(ptr));
        //leak: return wrl::ComPtr<ID3D11Texture2D>{static_cast<ID3D11Texture2D*>(ptr)}
        return tex;
    }

    BackBuffer::BackBuffer(ID3D11Device& device, wrl::ComPtr<ID3D11Texture2D> tex)
        : tex_{std::move(tex)}
    {
        TryHR(device.CreateRenderTargetView(tex_.Get(), {}, rtView_.ReleaseAndGetAddressOf()));
        SetName(Ref(tex_), "BackBuffer"sv);
    }

    void BackBuffer::Clear(ID3D11DeviceContext& context, DirectX::XMVECTOR color)
    {
        DirectX::XMFLOAT4 colorFloats;
        DirectX::XMStoreFloat4(&colorFloats, color);
        context.ClearRenderTargetView(rtView_.Get(), reinterpret_cast<const float*>(&colorFloats));
    }

    void BackBuffer::Reset() noexcept
    {
        rtView_.Reset();
        tex_.Reset();
    }

    DepthStencil::DepthStencil(ID3D11Device & device, std::uint32_t width, std::uint32_t height, DxgiFormat format)
    {
        CD3D11_TEXTURE2D_DESC desc{
            static_cast<DXGI_FORMAT>(format),
            width,
            height
        };
        desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
        TryHR(device.CreateTexture2D(&desc, {}, tex_.GetAddressOf()));
        SetName(Ref(tex_), "Depth Buffer");
        D3D11_DEPTH_STENCIL_VIEW_DESC depthDesc{};
        depthDesc.Format = static_cast<DXGI_FORMAT>(format);
        depthDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
        TryHR(device.CreateDepthStencilView(tex_.Get(), &depthDesc, view_.GetAddressOf()));
    }

    void DepthStencil::ClearDepth(ID3D11DeviceContext & context, float depth)
    {
        context.ClearDepthStencilView(&View(), D3D11_CLEAR_DEPTH, depth, {});
    }

    void DepthStencil::ClearStencil(ID3D11DeviceContext & context, std::uint8_t stencil)
    {
        context.ClearDepthStencilView(&View(), D3D11_CLEAR_STENCIL, {}, stencil);
    }

    void DepthStencil::ClearBoth(ID3D11DeviceContext& context, float depth, std::uint8_t stencil)
    {
        context.ClearDepthStencilView(&View(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, depth, stencil);
    }

    void DepthStencil::Reset()
    {
        view_.Reset();
        tex_.Reset();
    }

    void DependentGraphics::Bind(ID3D11DeviceContext& context3D)
    {
        auto& backBuffer = SwapChain_.Front();
        ID3D11RenderTargetView* views[] = { &backBuffer.RtView() };
        context3D.OMSetRenderTargets(gsl::narrow<UINT>(std::size(views)), views, &DepthStencil_.View());
    }
}<commit_msg>Fix a leak.<commit_after>#include "pch.hpp"
#include "DependentGraphics.hpp"
#include "GameWindow.hpp"
#include "D3DHelpers.hpp"
#include <d3d11.h>

using namespace std::literals;

namespace dx
{
    namespace Internal
    {
        template<typename T>
        wrl::ComPtr<T> GetParent(IDXGIObject& object)
        {
            void* ptr;
            TryHR(object.GetParent(__uuidof(T), &ptr));
            wrl::ComPtr<T> result;
            result.Attach(static_cast<T*>(ptr));
            return result;
        }
    }

    SwapChain::SwapChain(ID3D11Device& device, const GameWindow& window, const SwapChainOptions& options)
        : options_{ options }
    {
        wrl::ComPtr<IDXGIDevice1> dxgiDevice;
        TryHR(device.QueryInterface(dxgiDevice.GetAddressOf()));
        const auto adapter = Internal::GetParent<IDXGIAdapter1>(Ref(dxgiDevice));
        const auto factory = Internal::GetParent<IDXGIFactory1>(Ref(adapter));
        DXGI_SWAP_CHAIN_DESC desc = {};
        desc.BufferCount = gsl::narrow<UINT>(options.CountOfBackBuffers);
        desc.BufferDesc.Width = gsl::narrow<UINT>(window.GetWidth());
        desc.BufferDesc.Height = gsl::narrow<UINT>(window.GetHeight());
        desc.BufferDesc.Format = static_cast<DXGI_FORMAT>(options.BackBufferFormat);
        desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
        desc.OutputWindow = window.NativeHandle();
        desc.SampleDesc.Count = 1;
        desc.SampleDesc.Quality = 0;
        desc.Windowed = options.Windowed == true ? TRUE : FALSE;
        TryHR(factory->CreateSwapChain(&device, &desc, swapChain_.GetAddressOf()));
        UpdateBuffers(device);
    }

    SwapChain::~SwapChain()
    {
    }

    auto SwapChain::Front() -> BackBuffer&
    {
        return backBuffer_;
    }

    void SwapChain::Present()
    {
        TryHR(swapChain_->Present(0, 0));
    }

    void SwapChain::Reset()
    {
        backBuffer_.Reset();
    }

    //https://stackoverflow.com/questions/28095798/how-to-change-window-size-in-directx-11-desktop-application
    void SwapChain::Resize(ID3D11Device& device, std::uint32_t height, std::uint32_t width)
    {
        TryHR(swapChain_->ResizeBuffers(options_.CountOfBackBuffers, gsl::narrow<UINT>(height), gsl::narrow<UINT>(width), static_cast<DXGI_FORMAT>(options_.BackBufferFormat), 0));
        UpdateBuffers(device);
    }

    void SwapChain::UpdateBuffers(ID3D11Device& device)
    {
        //https://msdn.microsoft.com/en-us/library/windows/desktop/mt427784%28v=vs.85%29.aspx
        //In Direct3D 11, applications could call GetBuffer(0, ) only once.Every call to Present implicitly changed the resource identity of the returned interface.
        backBuffer_ = BackBuffer{device, GetBuffer(Ref(swapChain_), 0) };
    }

    wrl::ComPtr<ID3D11Texture2D> GetBuffer(IDXGISwapChain& swapChain, std::uint32_t index)
    {
        wrl::ComPtr<ID3D11Texture2D> tex;
        void* ptr;
        TryHR(swapChain.GetBuffer(gsl::narrow<UINT>(index), __uuidof(ID3D11Texture2D), &ptr));
        tex.Attach(static_cast<ID3D11Texture2D*>(ptr));
        //leak: return wrl::ComPtr<ID3D11Texture2D>{static_cast<ID3D11Texture2D*>(ptr)}
        return tex;
    }

    BackBuffer::BackBuffer(ID3D11Device& device, wrl::ComPtr<ID3D11Texture2D> tex)
        : tex_{std::move(tex)}
    {
        TryHR(device.CreateRenderTargetView(tex_.Get(), {}, rtView_.ReleaseAndGetAddressOf()));
        SetName(Ref(tex_), "BackBuffer"sv);
    }

    void BackBuffer::Clear(ID3D11DeviceContext& context, DirectX::XMVECTOR color)
    {
        DirectX::XMFLOAT4 colorFloats;
        DirectX::XMStoreFloat4(&colorFloats, color);
        context.ClearRenderTargetView(rtView_.Get(), reinterpret_cast<const float*>(&colorFloats));
    }

    void BackBuffer::Reset() noexcept
    {
        rtView_.Reset();
        tex_.Reset();
    }

    DepthStencil::DepthStencil(ID3D11Device & device, std::uint32_t width, std::uint32_t height, DxgiFormat format)
    {
        CD3D11_TEXTURE2D_DESC desc{
            static_cast<DXGI_FORMAT>(format),
            width,
            height
        };
        desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
        TryHR(device.CreateTexture2D(&desc, {}, tex_.GetAddressOf()));
        SetName(Ref(tex_), "Depth Buffer");
        D3D11_DEPTH_STENCIL_VIEW_DESC depthDesc{};
        depthDesc.Format = static_cast<DXGI_FORMAT>(format);
        depthDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
        TryHR(device.CreateDepthStencilView(tex_.Get(), &depthDesc, view_.GetAddressOf()));
    }

    void DepthStencil::ClearDepth(ID3D11DeviceContext & context, float depth)
    {
        context.ClearDepthStencilView(&View(), D3D11_CLEAR_DEPTH, depth, {});
    }

    void DepthStencil::ClearStencil(ID3D11DeviceContext & context, std::uint8_t stencil)
    {
        context.ClearDepthStencilView(&View(), D3D11_CLEAR_STENCIL, {}, stencil);
    }

    void DepthStencil::ClearBoth(ID3D11DeviceContext& context, float depth, std::uint8_t stencil)
    {
        context.ClearDepthStencilView(&View(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, depth, stencil);
    }

    void DepthStencil::Reset()
    {
        view_.Reset();
        tex_.Reset();
    }

    void DependentGraphics::Bind(ID3D11DeviceContext& context3D)
    {
        auto& backBuffer = SwapChain_.Front();
        ID3D11RenderTargetView* views[] = { &backBuffer.RtView() };
        context3D.OMSetRenderTargets(gsl::narrow<UINT>(std::size(views)), views, &DepthStencil_.View());
    }
}<|endoftext|>


<commit_before>#include "stdafx.h"
#include "PostprocessWindow.h"

#include <thread>
#include <Commdlg.h> // openfile
#include <WinBase.h>

using namespace std;
using namespace wiGraphicsTypes;

PostprocessWindow::PostprocessWindow(wiGUI* gui, Renderable3DComponent* comp) : GUI(gui), component(comp)
{
	assert(component && "PostprocessWnd invalid component!");
	assert(GUI && "Invalid GUI!");

	float screenW = (float)wiRenderer::GetDevice()->GetScreenWidth();
	float screenH = (float)wiRenderer::GetDevice()->GetScreenHeight();

	ppWindow = new wiWindow(GUI, "PostProcess Window");
	ppWindow->SetSize(XMFLOAT2(360, 520));
	GUI->AddWidget(ppWindow);

	float x = 110;
	float y = 0;

	lensFlareCheckBox = new wiCheckBox("LensFlare: ");
	lensFlareCheckBox->SetTooltip("Toggle visibility of light source flares. Additional setup needed per light for a lensflare to be visible.");
	lensFlareCheckBox->SetScriptTip("Renderable3DComponent::SetLensFlareEnabled(bool value)");
	lensFlareCheckBox->SetPos(XMFLOAT2(x, y += 35));
	lensFlareCheckBox->SetCheck(component->getLensFlareEnabled());
	lensFlareCheckBox->OnClick([&](wiEventArgs args) {
		component->setLensFlareEnabled(args.bValue);
	});
	ppWindow->AddWidget(lensFlareCheckBox);

	lightShaftsCheckBox = new wiCheckBox("LightShafts: ");
	lightShaftsCheckBox->SetTooltip("Enable light shaft for directional light sources.");
	lightShaftsCheckBox->SetScriptTip("Renderable3DComponent::SetLightShaftsEnabled(bool value)");
	lightShaftsCheckBox->SetPos(XMFLOAT2(x, y += 35));
	lightShaftsCheckBox->SetCheck(component->getLightShaftsEnabled());
	lightShaftsCheckBox->OnClick([&](wiEventArgs args) {
		component->setLightShaftsEnabled(args.bValue);
	});
	ppWindow->AddWidget(lightShaftsCheckBox);

	ssaoCheckBox = new wiCheckBox("SSAO: ");
	ssaoCheckBox->SetTooltip("Enable Screen Space Ambient Occlusion. (Deferred only for now)");
	ssaoCheckBox->SetScriptTip("Renderable3DComponent::SetSSAOEnabled(bool value)");
	ssaoCheckBox->SetPos(XMFLOAT2(x, y += 35));
	ssaoCheckBox->SetCheck(component->getSSAOEnabled());
	ssaoCheckBox->OnClick([&](wiEventArgs args) {
		component->setSSAOEnabled(args.bValue);
	});
	ppWindow->AddWidget(ssaoCheckBox);

	ssrCheckBox = new wiCheckBox("SSR: ");
	ssrCheckBox->SetTooltip("Enable Screen Space Reflections. (Deferred only for now)");
	ssrCheckBox->SetScriptTip("Renderable3DComponent::SetSSREnabled(bool value)");
	ssrCheckBox->SetPos(XMFLOAT2(x, y += 35));
	ssrCheckBox->SetCheck(component->getSSREnabled());
	ssrCheckBox->OnClick([&](wiEventArgs args) {
		component->setSSREnabled(args.bValue);
	});
	ppWindow->AddWidget(ssrCheckBox);

	sssCheckBox = new wiCheckBox("SSS: ");
	sssCheckBox->SetTooltip("Enable Subsurface Scattering. (Deferred only for now)");
	sssCheckBox->SetScriptTip("Renderable3DComponent::SetSSSEnabled(bool value)");
	sssCheckBox->SetPos(XMFLOAT2(x, y += 35));
	sssCheckBox->SetCheck(component->getSSSEnabled());
	sssCheckBox->OnClick([&](wiEventArgs args) {
		component->setSSSEnabled(args.bValue);
	});
	ppWindow->AddWidget(sssCheckBox);

	eyeAdaptionCheckBox = new wiCheckBox("EyeAdaption: ");
	eyeAdaptionCheckBox->SetTooltip("Enable eye adaption for the overall screen luminance");
	eyeAdaptionCheckBox->SetPos(XMFLOAT2(x, y += 35));
	eyeAdaptionCheckBox->SetCheck(component->getEyeAdaptionEnabled());
	eyeAdaptionCheckBox->OnClick([&](wiEventArgs args) {
		component->setEyeAdaptionEnabled(args.bValue);
	});
	ppWindow->AddWidget(eyeAdaptionCheckBox);

	motionBlurCheckBox = new wiCheckBox("MotionBlur: ");
	motionBlurCheckBox->SetTooltip("Enable motion blur for camera movement and animated meshes.");
	motionBlurCheckBox->SetScriptTip("Renderable3DComponent::SetMotionBlurEnabled(bool value)");
	motionBlurCheckBox->SetPos(XMFLOAT2(x, y += 35));
	motionBlurCheckBox->SetCheck(component->getMotionBlurEnabled());
	motionBlurCheckBox->OnClick([&](wiEventArgs args) {
		component->setMotionBlurEnabled(args.bValue);
	});
	ppWindow->AddWidget(motionBlurCheckBox);

	depthOfFieldCheckBox = new wiCheckBox("DepthOfField: ");
	depthOfFieldCheckBox->SetTooltip("Enable Depth of field effect. Additional focus and strength setup required.");
	depthOfFieldCheckBox->SetScriptTip("Renderable3DComponent::SetDepthOfFieldEnabled(bool value)");
	depthOfFieldCheckBox->SetPos(XMFLOAT2(x, y += 35));
	depthOfFieldCheckBox->SetCheck(component->getDepthOfFieldEnabled());
	depthOfFieldCheckBox->OnClick([&](wiEventArgs args) {
		component->setDepthOfFieldEnabled(args.bValue);
	});
	ppWindow->AddWidget(depthOfFieldCheckBox);

	depthOfFieldFocusSlider = new wiSlider(0.01f, 600, 100, 10000, "Focus: ");
	depthOfFieldFocusSlider->SetTooltip("Set the focus distance from the camera. The picture will be sharper near the focus, and blurrier further from it.");
	depthOfFieldFocusSlider->SetScriptTip("Renderable3DComponent::SetDepthOfFieldFocus(float value)");
	depthOfFieldFocusSlider->SetSize(XMFLOAT2(100, 20));
	depthOfFieldFocusSlider->SetPos(XMFLOAT2(x + 100, y));
	depthOfFieldFocusSlider->SetValue(component->getDepthOfFieldFocus());
	depthOfFieldFocusSlider->OnSlide([&](wiEventArgs args) {
		component->setDepthOfFieldFocus(args.fValue);
	});
	ppWindow->AddWidget(depthOfFieldFocusSlider);

	depthOfFieldStrengthSlider = new wiSlider(0.01f, 4, 100, 1000, "Strength: ");
	depthOfFieldStrengthSlider->SetTooltip("Set depth of field blur strength.");
	depthOfFieldStrengthSlider->SetScriptTip("Renderable3DComponent::SetDepthOfFieldStrength(float value)");
	depthOfFieldStrengthSlider->SetSize(XMFLOAT2(100, 20));
	depthOfFieldStrengthSlider->SetPos(XMFLOAT2(x + 100, y += 35));
	depthOfFieldStrengthSlider->SetValue(component->getDepthOfFieldStrength());
	depthOfFieldStrengthSlider->OnSlide([&](wiEventArgs args) {
		component->setDepthOfFieldStrength(args.fValue);
	});
	ppWindow->AddWidget(depthOfFieldStrengthSlider);

	bloomCheckBox = new wiCheckBox("Bloom: ");
	bloomCheckBox->SetTooltip("Enable bloom. The effect adds color bleeding to the brightest parts of the scene.");
	bloomCheckBox->SetScriptTip("Renderable3DComponent::SetBloomEnabled(bool value)");
	bloomCheckBox->SetPos(XMFLOAT2(x, y += 35));
	bloomCheckBox->SetCheck(component->getBloomEnabled());
	bloomCheckBox->OnClick([&](wiEventArgs args) {
		component->setBloomEnabled(args.bValue);
	});
	ppWindow->AddWidget(bloomCheckBox);

	fxaaCheckBox = new wiCheckBox("FXAA: ");
	fxaaCheckBox->SetTooltip("Fast Approximate Anti Aliasing. A fast antialiasing method, but can be a bit too blurry.");
	fxaaCheckBox->SetScriptTip("Renderable3DComponent::SetFXAAEnabled(bool value)");
	fxaaCheckBox->SetPos(XMFLOAT2(x, y += 35));
	fxaaCheckBox->SetCheck(component->getFXAAEnabled());
	fxaaCheckBox->OnClick([&](wiEventArgs args) {
		component->setFXAAEnabled(args.bValue);
	});
	ppWindow->AddWidget(fxaaCheckBox);

	colorGradingCheckBox = new wiCheckBox("Color Grading: ");
	colorGradingCheckBox->SetTooltip("Enable color grading of the final render. An additional lookup texture must be set for it to take effect.");
	colorGradingCheckBox->SetScriptTip("Renderable3DComponent::SetColorGradingEnabled(bool value)");
	colorGradingCheckBox->SetPos(XMFLOAT2(x, y += 35));
	colorGradingCheckBox->SetCheck(component->getColorGradingEnabled());
	colorGradingCheckBox->OnClick([&](wiEventArgs args) {
		component->setColorGradingEnabled(args.bValue);
	});
	ppWindow->AddWidget(colorGradingCheckBox);

	colorGradingButton = new wiButton("Load Color Grading LUT...");
	colorGradingButton->SetTooltip("Load a color grading lookup texture...");
	colorGradingButton->SetPos(XMFLOAT2(x + 35, y));
	colorGradingButton->SetSize(XMFLOAT2(200, 18));
	colorGradingButton->OnClick([=](wiEventArgs args) {
		auto x = wiRenderer::GetColorGrading();

		if (x == nullptr)
		{
			thread([&] {
				char szFile[260];

				OPENFILENAMEA ofn;
				ZeroMemory(&ofn, sizeof(ofn));
				ofn.lStructSize = sizeof(ofn);
				ofn.hwndOwner = nullptr;
				ofn.lpstrFile = szFile;
				// Set lpstrFile[0] to '\0' so that GetOpenFileName does not
				// use the contents of szFile to initialize itself.
				ofn.lpstrFile[0] = '\0';
				ofn.nMaxFile = sizeof(szFile);
				ofn.lpstrFilter = "Color Grading texture\0*.dds;*.png;*.tga\0";
				ofn.nFilterIndex = 1;
				ofn.lpstrFileTitle = NULL;
				ofn.nMaxFileTitle = 0;
				ofn.lpstrInitialDir = NULL;
				ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
				if (GetOpenFileNameA(&ofn) == TRUE) {
					string fileName = ofn.lpstrFile;
					wiRenderer::SetColorGrading((Texture2D*)wiResourceManager::GetGlobal()->add(fileName));
					colorGradingButton->SetText(fileName);
				}
			}).detach();
		}
		else
		{
			wiRenderer::SetColorGrading(nullptr);
			colorGradingButton->SetText("Load Color Grading LUT...");
		}

	});
	ppWindow->AddWidget(colorGradingButton);

	stereogramCheckBox = new wiCheckBox("Stereogram: ");
	stereogramCheckBox->SetTooltip("Compute a stereogram from the depth buffer. It produces a 3D sihouette image when viewed cross eyed.");
	stereogramCheckBox->SetScriptTip("Renderable3DComponent::SetStereogramEnabled(bool value)");
	stereogramCheckBox->SetPos(XMFLOAT2(x, y += 35));
	stereogramCheckBox->SetCheck(component->getStereogramEnabled());
	stereogramCheckBox->OnClick([&](wiEventArgs args) {
		component->setStereogramEnabled(args.bValue);
	});
	ppWindow->AddWidget(stereogramCheckBox);

	sharpenFilterCheckBox = new wiCheckBox("Sharpen Filter: ");
	sharpenFilterCheckBox->SetTooltip("Toggle sharpening post process of the final image.");
	sharpenFilterCheckBox->SetScriptTip("Renderable3DComponent::SetSharpenFilterEnabled(bool value)");
	sharpenFilterCheckBox->SetPos(XMFLOAT2(x, y += 35));
	sharpenFilterCheckBox->SetCheck(component->getSharpenFilterEnabled());
	sharpenFilterCheckBox->OnClick([&](wiEventArgs args) {
		component->setSharpenFilterEnabled(args.bValue);
	});
	ppWindow->AddWidget(sharpenFilterCheckBox);

	sharpenFilterAmountSlider = new wiSlider(0, 4, 1, 1000, "Amount: ");
	sharpenFilterAmountSlider->SetTooltip("Set sharpness filter strength.");
	sharpenFilterAmountSlider->SetScriptTip("Renderable3DComponent::SetSharpenFilterAmount(float value)");
	sharpenFilterAmountSlider->SetSize(XMFLOAT2(100, 20));
	sharpenFilterAmountSlider->SetPos(XMFLOAT2(x + 100, y));
	sharpenFilterAmountSlider->SetValue(component->getSharpenFilterAmount());
	sharpenFilterAmountSlider->OnSlide([&](wiEventArgs args) {
		component->setSharpenFilterAmount(args.fValue);
	});
	ppWindow->AddWidget(sharpenFilterAmountSlider);

	ppWindow->Translate(XMFLOAT3(screenW - 380, 50, 0));
	ppWindow->SetVisible(false);

}

PostprocessWindow::~PostprocessWindow()
{
	ppWindow->RemoveWidgets(true);
	GUI->RemoveWidget(ppWindow);
	SAFE_DELETE(ppWindow);
}
<commit_msg>ssr and ssao no longer deferred only<commit_after>#include "stdafx.h"
#include "PostprocessWindow.h"

#include <thread>
#include <Commdlg.h> // openfile
#include <WinBase.h>

using namespace std;
using namespace wiGraphicsTypes;

PostprocessWindow::PostprocessWindow(wiGUI* gui, Renderable3DComponent* comp) : GUI(gui), component(comp)
{
	assert(component && "PostprocessWnd invalid component!");
	assert(GUI && "Invalid GUI!");

	float screenW = (float)wiRenderer::GetDevice()->GetScreenWidth();
	float screenH = (float)wiRenderer::GetDevice()->GetScreenHeight();

	ppWindow = new wiWindow(GUI, "PostProcess Window");
	ppWindow->SetSize(XMFLOAT2(360, 520));
	GUI->AddWidget(ppWindow);

	float x = 110;
	float y = 0;

	lensFlareCheckBox = new wiCheckBox("LensFlare: ");
	lensFlareCheckBox->SetTooltip("Toggle visibility of light source flares. Additional setup needed per light for a lensflare to be visible.");
	lensFlareCheckBox->SetScriptTip("Renderable3DComponent::SetLensFlareEnabled(bool value)");
	lensFlareCheckBox->SetPos(XMFLOAT2(x, y += 35));
	lensFlareCheckBox->SetCheck(component->getLensFlareEnabled());
	lensFlareCheckBox->OnClick([&](wiEventArgs args) {
		component->setLensFlareEnabled(args.bValue);
	});
	ppWindow->AddWidget(lensFlareCheckBox);

	lightShaftsCheckBox = new wiCheckBox("LightShafts: ");
	lightShaftsCheckBox->SetTooltip("Enable light shaft for directional light sources.");
	lightShaftsCheckBox->SetScriptTip("Renderable3DComponent::SetLightShaftsEnabled(bool value)");
	lightShaftsCheckBox->SetPos(XMFLOAT2(x, y += 35));
	lightShaftsCheckBox->SetCheck(component->getLightShaftsEnabled());
	lightShaftsCheckBox->OnClick([&](wiEventArgs args) {
		component->setLightShaftsEnabled(args.bValue);
	});
	ppWindow->AddWidget(lightShaftsCheckBox);

	ssaoCheckBox = new wiCheckBox("SSAO: ");
	ssaoCheckBox->SetTooltip("Enable Screen Space Ambient Occlusion.");
	ssaoCheckBox->SetScriptTip("Renderable3DComponent::SetSSAOEnabled(bool value)");
	ssaoCheckBox->SetPos(XMFLOAT2(x, y += 35));
	ssaoCheckBox->SetCheck(component->getSSAOEnabled());
	ssaoCheckBox->OnClick([&](wiEventArgs args) {
		component->setSSAOEnabled(args.bValue);
	});
	ppWindow->AddWidget(ssaoCheckBox);

	ssrCheckBox = new wiCheckBox("SSR: ");
	ssrCheckBox->SetTooltip("Enable Screen Space Reflections.");
	ssrCheckBox->SetScriptTip("Renderable3DComponent::SetSSREnabled(bool value)");
	ssrCheckBox->SetPos(XMFLOAT2(x, y += 35));
	ssrCheckBox->SetCheck(component->getSSREnabled());
	ssrCheckBox->OnClick([&](wiEventArgs args) {
		component->setSSREnabled(args.bValue);
	});
	ppWindow->AddWidget(ssrCheckBox);

	sssCheckBox = new wiCheckBox("SSS: ");
	sssCheckBox->SetTooltip("Enable Subsurface Scattering. (Deferred only for now)");
	sssCheckBox->SetScriptTip("Renderable3DComponent::SetSSSEnabled(bool value)");
	sssCheckBox->SetPos(XMFLOAT2(x, y += 35));
	sssCheckBox->SetCheck(component->getSSSEnabled());
	sssCheckBox->OnClick([&](wiEventArgs args) {
		component->setSSSEnabled(args.bValue);
	});
	ppWindow->AddWidget(sssCheckBox);

	eyeAdaptionCheckBox = new wiCheckBox("EyeAdaption: ");
	eyeAdaptionCheckBox->SetTooltip("Enable eye adaption for the overall screen luminance");
	eyeAdaptionCheckBox->SetPos(XMFLOAT2(x, y += 35));
	eyeAdaptionCheckBox->SetCheck(component->getEyeAdaptionEnabled());
	eyeAdaptionCheckBox->OnClick([&](wiEventArgs args) {
		component->setEyeAdaptionEnabled(args.bValue);
	});
	ppWindow->AddWidget(eyeAdaptionCheckBox);

	motionBlurCheckBox = new wiCheckBox("MotionBlur: ");
	motionBlurCheckBox->SetTooltip("Enable motion blur for camera movement and animated meshes.");
	motionBlurCheckBox->SetScriptTip("Renderable3DComponent::SetMotionBlurEnabled(bool value)");
	motionBlurCheckBox->SetPos(XMFLOAT2(x, y += 35));
	motionBlurCheckBox->SetCheck(component->getMotionBlurEnabled());
	motionBlurCheckBox->OnClick([&](wiEventArgs args) {
		component->setMotionBlurEnabled(args.bValue);
	});
	ppWindow->AddWidget(motionBlurCheckBox);

	depthOfFieldCheckBox = new wiCheckBox("DepthOfField: ");
	depthOfFieldCheckBox->SetTooltip("Enable Depth of field effect. Additional focus and strength setup required.");
	depthOfFieldCheckBox->SetScriptTip("Renderable3DComponent::SetDepthOfFieldEnabled(bool value)");
	depthOfFieldCheckBox->SetPos(XMFLOAT2(x, y += 35));
	depthOfFieldCheckBox->SetCheck(component->getDepthOfFieldEnabled());
	depthOfFieldCheckBox->OnClick([&](wiEventArgs args) {
		component->setDepthOfFieldEnabled(args.bValue);
	});
	ppWindow->AddWidget(depthOfFieldCheckBox);

	depthOfFieldFocusSlider = new wiSlider(0.01f, 600, 100, 10000, "Focus: ");
	depthOfFieldFocusSlider->SetTooltip("Set the focus distance from the camera. The picture will be sharper near the focus, and blurrier further from it.");
	depthOfFieldFocusSlider->SetScriptTip("Renderable3DComponent::SetDepthOfFieldFocus(float value)");
	depthOfFieldFocusSlider->SetSize(XMFLOAT2(100, 20));
	depthOfFieldFocusSlider->SetPos(XMFLOAT2(x + 100, y));
	depthOfFieldFocusSlider->SetValue(component->getDepthOfFieldFocus());
	depthOfFieldFocusSlider->OnSlide([&](wiEventArgs args) {
		component->setDepthOfFieldFocus(args.fValue);
	});
	ppWindow->AddWidget(depthOfFieldFocusSlider);

	depthOfFieldStrengthSlider = new wiSlider(0.01f, 4, 100, 1000, "Strength: ");
	depthOfFieldStrengthSlider->SetTooltip("Set depth of field blur strength.");
	depthOfFieldStrengthSlider->SetScriptTip("Renderable3DComponent::SetDepthOfFieldStrength(float value)");
	depthOfFieldStrengthSlider->SetSize(XMFLOAT2(100, 20));
	depthOfFieldStrengthSlider->SetPos(XMFLOAT2(x + 100, y += 35));
	depthOfFieldStrengthSlider->SetValue(component->getDepthOfFieldStrength());
	depthOfFieldStrengthSlider->OnSlide([&](wiEventArgs args) {
		component->setDepthOfFieldStrength(args.fValue);
	});
	ppWindow->AddWidget(depthOfFieldStrengthSlider);

	bloomCheckBox = new wiCheckBox("Bloom: ");
	bloomCheckBox->SetTooltip("Enable bloom. The effect adds color bleeding to the brightest parts of the scene.");
	bloomCheckBox->SetScriptTip("Renderable3DComponent::SetBloomEnabled(bool value)");
	bloomCheckBox->SetPos(XMFLOAT2(x, y += 35));
	bloomCheckBox->SetCheck(component->getBloomEnabled());
	bloomCheckBox->OnClick([&](wiEventArgs args) {
		component->setBloomEnabled(args.bValue);
	});
	ppWindow->AddWidget(bloomCheckBox);

	fxaaCheckBox = new wiCheckBox("FXAA: ");
	fxaaCheckBox->SetTooltip("Fast Approximate Anti Aliasing. A fast antialiasing method, but can be a bit too blurry.");
	fxaaCheckBox->SetScriptTip("Renderable3DComponent::SetFXAAEnabled(bool value)");
	fxaaCheckBox->SetPos(XMFLOAT2(x, y += 35));
	fxaaCheckBox->SetCheck(component->getFXAAEnabled());
	fxaaCheckBox->OnClick([&](wiEventArgs args) {
		component->setFXAAEnabled(args.bValue);
	});
	ppWindow->AddWidget(fxaaCheckBox);

	colorGradingCheckBox = new wiCheckBox("Color Grading: ");
	colorGradingCheckBox->SetTooltip("Enable color grading of the final render. An additional lookup texture must be set for it to take effect.");
	colorGradingCheckBox->SetScriptTip("Renderable3DComponent::SetColorGradingEnabled(bool value)");
	colorGradingCheckBox->SetPos(XMFLOAT2(x, y += 35));
	colorGradingCheckBox->SetCheck(component->getColorGradingEnabled());
	colorGradingCheckBox->OnClick([&](wiEventArgs args) {
		component->setColorGradingEnabled(args.bValue);
	});
	ppWindow->AddWidget(colorGradingCheckBox);

	colorGradingButton = new wiButton("Load Color Grading LUT...");
	colorGradingButton->SetTooltip("Load a color grading lookup texture...");
	colorGradingButton->SetPos(XMFLOAT2(x + 35, y));
	colorGradingButton->SetSize(XMFLOAT2(200, 18));
	colorGradingButton->OnClick([=](wiEventArgs args) {
		auto x = wiRenderer::GetColorGrading();

		if (x == nullptr)
		{
			thread([&] {
				char szFile[260];

				OPENFILENAMEA ofn;
				ZeroMemory(&ofn, sizeof(ofn));
				ofn.lStructSize = sizeof(ofn);
				ofn.hwndOwner = nullptr;
				ofn.lpstrFile = szFile;
				// Set lpstrFile[0] to '\0' so that GetOpenFileName does not
				// use the contents of szFile to initialize itself.
				ofn.lpstrFile[0] = '\0';
				ofn.nMaxFile = sizeof(szFile);
				ofn.lpstrFilter = "Color Grading texture\0*.dds;*.png;*.tga\0";
				ofn.nFilterIndex = 1;
				ofn.lpstrFileTitle = NULL;
				ofn.nMaxFileTitle = 0;
				ofn.lpstrInitialDir = NULL;
				ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
				if (GetOpenFileNameA(&ofn) == TRUE) {
					string fileName = ofn.lpstrFile;
					wiRenderer::SetColorGrading((Texture2D*)wiResourceManager::GetGlobal()->add(fileName));
					colorGradingButton->SetText(fileName);
				}
			}).detach();
		}
		else
		{
			wiRenderer::SetColorGrading(nullptr);
			colorGradingButton->SetText("Load Color Grading LUT...");
		}

	});
	ppWindow->AddWidget(colorGradingButton);

	stereogramCheckBox = new wiCheckBox("Stereogram: ");
	stereogramCheckBox->SetTooltip("Compute a stereogram from the depth buffer. It produces a 3D sihouette image when viewed cross eyed.");
	stereogramCheckBox->SetScriptTip("Renderable3DComponent::SetStereogramEnabled(bool value)");
	stereogramCheckBox->SetPos(XMFLOAT2(x, y += 35));
	stereogramCheckBox->SetCheck(component->getStereogramEnabled());
	stereogramCheckBox->OnClick([&](wiEventArgs args) {
		component->setStereogramEnabled(args.bValue);
	});
	ppWindow->AddWidget(stereogramCheckBox);

	sharpenFilterCheckBox = new wiCheckBox("Sharpen Filter: ");
	sharpenFilterCheckBox->SetTooltip("Toggle sharpening post process of the final image.");
	sharpenFilterCheckBox->SetScriptTip("Renderable3DComponent::SetSharpenFilterEnabled(bool value)");
	sharpenFilterCheckBox->SetPos(XMFLOAT2(x, y += 35));
	sharpenFilterCheckBox->SetCheck(component->getSharpenFilterEnabled());
	sharpenFilterCheckBox->OnClick([&](wiEventArgs args) {
		component->setSharpenFilterEnabled(args.bValue);
	});
	ppWindow->AddWidget(sharpenFilterCheckBox);

	sharpenFilterAmountSlider = new wiSlider(0, 4, 1, 1000, "Amount: ");
	sharpenFilterAmountSlider->SetTooltip("Set sharpness filter strength.");
	sharpenFilterAmountSlider->SetScriptTip("Renderable3DComponent::SetSharpenFilterAmount(float value)");
	sharpenFilterAmountSlider->SetSize(XMFLOAT2(100, 20));
	sharpenFilterAmountSlider->SetPos(XMFLOAT2(x + 100, y));
	sharpenFilterAmountSlider->SetValue(component->getSharpenFilterAmount());
	sharpenFilterAmountSlider->OnSlide([&](wiEventArgs args) {
		component->setSharpenFilterAmount(args.fValue);
	});
	ppWindow->AddWidget(sharpenFilterAmountSlider);

	ppWindow->Translate(XMFLOAT3(screenW - 380, 50, 0));
	ppWindow->SetVisible(false);

}

PostprocessWindow::~PostprocessWindow()
{
	ppWindow->RemoveWidgets(true);
	GUI->RemoveWidget(ppWindow);
	SAFE_DELETE(ppWindow);
}
<|endoftext|>