<commit_before>#include <vigra/blockwise_labeling.hxx>
#include <vigra/blockwise_labeling.hxx>

#include <vigra/multi_array.hxx>
#include <vigra/multi_array_chunked.hxx>
#include <vigra/multi_labeling.hxx>
#include <vigra/unittest.hxx>

#include <vector>
#include <utility>
#include <functional>

#include "utils.hxx"

using namespace vigra;
using namespace std;

template <class DatasIterator, class ShapesIterator>
void testOnData(DatasIterator datas_begin, DatasIterator datas_end,
                  ShapesIterator shapes_begin, ShapesIterator shapes_end)
{
    for(DatasIterator datas_it = datas_begin ; datas_it != datas_end; ++datas_it)
    {
        typedef typename DatasIterator::reference DataRef;
        DataRef data = *datas_it;
        for(ShapesIterator shapes_it = shapes_begin; shapes_it != shapes_end; ++shapes_it)
        {
            typedef typename ShapesIterator::reference ShapeRef;
            ShapeRef shape = *shapes_it;

            vector<NeighborhoodType> neighborhoods;
            neighborhoods.push_back(DirectNeighborhood);
            neighborhoods.push_back(IndirectNeighborhood);
            typedef vector<NeighborhoodType>::iterator NeighborhoodIterator;

            for(NeighborhoodIterator neighborhood_it = neighborhoods.begin();
                neighborhood_it != neighborhoods.end();
                ++neighborhood_it)
            {
                NeighborhoodType neighborhood = *neighborhood_it;
                typedef typename DatasIterator::value_type Data;

                std::vector<bool> with_backgrounds;
                with_backgrounds.push_back(true);
                with_backgrounds.push_back(false);
                for(std::vector<bool>::iterator backgrounds_it = with_backgrounds.begin();
                        backgrounds_it != with_backgrounds.end();
                        ++backgrounds_it)
                {
                    bool with_background = *backgrounds_it;
                    Data correct_labels(data.shape());
                    Data tested_labels(data.shape());

                    LabelOptions options;
                    options.neighborhood(neighborhood);
                    options.blockShape(shape);

                    int correct_label_number;
                    int tested_label_number;
                    if(with_background)
                    {
                        correct_label_number = labelMultiArrayWithBackground(data, correct_labels, neighborhood, 1u);
                        options.background(1u);
                    }
                    else
                    {
                        correct_label_number = labelMultiArray(data, correct_labels, neighborhood);
                    }

                    tested_label_number = labelMultiArrayBlockwise(data, tested_labels, options);

                    if(!equivalentLabels(correct_labels.begin(), correct_labels.end(),
                                         tested_labels.begin(), tested_labels.end()) ||
                       correct_label_number != tested_label_number)
                    {
                        std::ostringstream oss;
                        oss << "labeling not equivalent" << endl;
                        oss << "with background: " << boolalpha << with_background << endl;
                        oss << "array shape: " << data.shape() << endl;
                        oss << "block shape: " << shape << endl;
                        oss << "neighborhood: " << neighborhood << endl;
                        oss << "data: " << endl;
                        for(int i = 0; i != data.size(); ++i)
                            oss << data[i] << " ";
                        oss << endl;
                        oss << "expected_labels: " << endl;
                        for(int i = 0; i != correct_labels.size(); ++i)
                            oss << correct_labels[i] << " ";
                        oss << endl;
                        oss << "got" << endl;
                        for(int i = 0; i != tested_labels.size(); ++i)
                            oss << tested_labels[i] << " ";
                        oss << endl;
                        failTest(oss.str().c_str());
                    }
                }
            }
        }
    }
}

struct BlockwiseLabelingTest
{
    typedef MultiArray<5, unsigned int> Array5;
    typedef MultiArray<2, unsigned int> Array2;
    typedef MultiArray<1, unsigned int> Array1;

    typedef Array5::difference_type Shape5;
    typedef Array2::difference_type Shape2;
    typedef Array1::difference_type Shape1;

    vector<Array5> array_fives;
    vector<Array2> array_twos;
    vector<Array1> array_ones;

    vector<Shape5> shape_fives;
    vector<Shape2> shape_twos;
    vector<Shape1> shape_ones;

    BlockwiseLabelingTest()
    {
        array_fives.push_back(Array5(Shape5(1)));
        array_fives.push_back(Array5(Shape5(2,2,3,4,3)));
        array_fives.push_back(Array5(Shape5(5,6,2,2,3)));
        for(int i = 0; i != array_fives.size(); ++i)
        {
            fillRandom(array_fives[i].begin(), array_fives[i].end(), 3);
        }

        array_twos.push_back(Array2(Shape2(1)));
        array_twos.push_back(Array2(Shape2(1,2)));
        array_twos.push_back(Array2(Shape2(2,2)));
        array_twos.push_back(Array2(Shape2(4,4)));
        array_twos.push_back(Array2(Shape2(6,10)));
        array_twos.push_back(Array2(Shape2(19,25)));
        for(int i = 0; i != array_twos.size(); ++i)
        {
            fillRandom(array_twos[i].begin(), array_twos[i].end(), 3);
        }

        array_ones.push_back(Array1(Shape1(1)));
        array_ones.push_back(Array1(Shape1(2)));
        array_ones.push_back(Array1(Shape1(47)));
        array_ones.push_back(Array1(Shape1(81)));
        array_ones.push_back(Array1(Shape1(997)));
        for(int i = 0; i != array_ones.size(); ++i)
        {
            fillRandom(array_ones[i].begin(), array_ones[i].end(), 3);
        }

        shape_fives.push_back(Shape5(1));
        shape_fives.push_back(Shape5(2));
        shape_fives.push_back(Shape5(5,4,3,2,1));
        shape_fives.push_back(Shape5(100000));

        shape_twos.push_back(Shape2(1));
        shape_twos.push_back(Shape2(2));
        shape_twos.push_back(Shape2(5,4));
        shape_twos.push_back(Shape2(1000000));

        shape_ones.push_back(Shape1(1));
        shape_ones.push_back(Shape1(2));
        shape_ones.push_back(Shape1(3));
        shape_ones.push_back(Shape1(5));
        shape_ones.push_back(Shape1(213));
    }

    void debugTest()
    {
        typedef MultiArray<2, int> Array;
        typedef Array::difference_type Shape;

        Shape shape = Shape(2);
        Array data(shape);

        data(0,0) = 1;
        data(1,0) = 1;
        data(0,1) = 1;
        data(1,1) = 1;

        MultiArray<2, size_t> blockwise_labels(shape);
        MultiArray<2, size_t> labels(shape);

        Shape block_shape(1, 1);
        //TinyVector<MultiArrayIndex, 3> block_shape(1, 1, 1);

        NeighborhoodType neighborhood = IndirectNeighborhood;

        size_t count = labelMultiArrayWithBackground(data, labels, neighborhood, 1);
        size_t blockwise_count = labelMultiArrayBlockwise(data, blockwise_labels,
                                                          LabelOptions().neighborhood(neighborhood).background(1).blockShape(block_shape));
        shouldEqual(count, blockwise_count);
        shouldEqual(equivalentLabels(labels.begin(), labels.end(),
                                     blockwise_labels.begin(), blockwise_labels.end()),
                    true);
    }
    void chunkedArrayTest()
    {
        typedef ChunkedArrayLazy<3, int> DataArray;
        typedef ChunkedArrayLazy<3, size_t> LabelArray;
        typedef DataArray::shape_type Shape;

        Shape shape = Shape(100, 200, 300);
        Shape chunk_shape = Shape(32);

        DataArray data(shape, chunk_shape);
        fillRandom(data.begin(), data.end(), 3);
        LabelArray labels(shape, chunk_shape);

        LabelOptions options;
        options.neighborhood(IndirectNeighborhood).background(1);

        size_t tested_label_number = labelMultiArrayBlockwise(data, labels, options);
        MultiArray<3, size_t> checked_out_labels(shape);
        labels.checkoutSubarray(Shape(0), checked_out_labels);

        MultiArray<3, int> oldschool_data_array(shape);
        MultiArray<3, size_t> oldschool_label_array(shape);

        data.checkoutSubarray(Shape(0), oldschool_data_array);
        size_t actual_label_number = labelMultiArrayWithBackground(oldschool_data_array, oldschool_label_array,
                                                                   IndirectNeighborhood, 1);

        shouldEqual(tested_label_number, actual_label_number);
        shouldEqual(equivalentLabels(checked_out_labels.begin(), checked_out_labels.end(),
                                     oldschool_label_array.begin(), oldschool_label_array.end()), true);
    }

    void fiveDimensionalRandomTest()
    {
        testOnData(array_fives.begin(), array_fives.end(),
                     shape_fives.begin(), shape_fives.end());
    }
    void twoDimensionalRandomTest()
    {
        testOnData(array_twos.begin(), array_twos.end(),
                     shape_twos.begin(), shape_twos.end());
    }
    void oneDimensionalRandomTest()
    {
        testOnData(array_ones.begin(), array_ones.end(),
                     shape_ones.begin(), shape_ones.end());
    }
};

struct BlockwiseLabelingTestSuite
  : public test_suite
{
    BlockwiseLabelingTestSuite()
      : test_suite("blockwise labeling test")
    {
        add(testCase(&BlockwiseLabelingTest::fiveDimensionalRandomTest));
        add(testCase(&BlockwiseLabelingTest::twoDimensionalRandomTest));
        add(testCase(&BlockwiseLabelingTest::oneDimensionalRandomTest));
        add(testCase(&BlockwiseLabelingTest::debugTest));
        add(testCase(&BlockwiseLabelingTest::chunkedArrayTest));
    }
};

int main(int argc, char** argv)
{
    BlockwiseLabelingTestSuite test;
    int failed = test.run(testsToBeExecuted(argc, argv));

    cout << test.report() << endl;

    return failed != 0;
}

<commit_msg>add missing #define for bounds checking<commit_after>#define VIGRA_CHECK_BOUNDS

#include <vigra/blockwise_labeling.hxx>
#include <vigra/blockwise_labeling.hxx>

#include <vigra/multi_array.hxx>
#include <vigra/multi_array_chunked.hxx>
#include <vigra/multi_labeling.hxx>
#include <vigra/unittest.hxx>

#include <vector>
#include <utility>
#include <functional>

#include "utils.hxx"

using namespace vigra;
using namespace std;

template <class DatasIterator, class ShapesIterator>
void testOnData(DatasIterator datas_begin, DatasIterator datas_end,
                  ShapesIterator shapes_begin, ShapesIterator shapes_end)
{
    for(DatasIterator datas_it = datas_begin ; datas_it != datas_end; ++datas_it)
    {
        typedef typename DatasIterator::reference DataRef;
        DataRef data = *datas_it;
        for(ShapesIterator shapes_it = shapes_begin; shapes_it != shapes_end; ++shapes_it)
        {
            typedef typename ShapesIterator::reference ShapeRef;
            ShapeRef shape = *shapes_it;

            vector<NeighborhoodType> neighborhoods;
            neighborhoods.push_back(DirectNeighborhood);
            neighborhoods.push_back(IndirectNeighborhood);
            typedef vector<NeighborhoodType>::iterator NeighborhoodIterator;

            for(NeighborhoodIterator neighborhood_it = neighborhoods.begin();
                neighborhood_it != neighborhoods.end();
                ++neighborhood_it)
            {
                NeighborhoodType neighborhood = *neighborhood_it;
                typedef typename DatasIterator::value_type Data;

                std::vector<bool> with_backgrounds;
                with_backgrounds.push_back(true);
                with_backgrounds.push_back(false);
                for(std::vector<bool>::iterator backgrounds_it = with_backgrounds.begin();
                        backgrounds_it != with_backgrounds.end();
                        ++backgrounds_it)
                {
                    bool with_background = *backgrounds_it;
                    Data correct_labels(data.shape());
                    Data tested_labels(data.shape());

                    LabelOptions options;
                    options.neighborhood(neighborhood);
                    options.blockShape(shape);

                    int correct_label_number;
                    int tested_label_number;
                    if(with_background)
                    {
                        correct_label_number = labelMultiArrayWithBackground(data, correct_labels, neighborhood, 1u);
                        options.background(1u);
                    }
                    else
                    {
                        correct_label_number = labelMultiArray(data, correct_labels, neighborhood);
                    }

                    tested_label_number = labelMultiArrayBlockwise(data, tested_labels, options);

                    if(!equivalentLabels(correct_labels.begin(), correct_labels.end(),
                                         tested_labels.begin(), tested_labels.end()) ||
                       correct_label_number != tested_label_number)
                    {
                        std::ostringstream oss;
                        oss << "labeling not equivalent" << endl;
                        oss << "with background: " << boolalpha << with_background << endl;
                        oss << "array shape: " << data.shape() << endl;
                        oss << "block shape: " << shape << endl;
                        oss << "neighborhood: " << neighborhood << endl;
                        oss << "data: " << endl;
                        for(int i = 0; i != data.size(); ++i)
                            oss << data[i] << " ";
                        oss << endl;
                        oss << "expected_labels: " << endl;
                        for(int i = 0; i != correct_labels.size(); ++i)
                            oss << correct_labels[i] << " ";
                        oss << endl;
                        oss << "got" << endl;
                        for(int i = 0; i != tested_labels.size(); ++i)
                            oss << tested_labels[i] << " ";
                        oss << endl;
                        failTest(oss.str().c_str());
                    }
                }
            }
        }
    }
}

struct BlockwiseLabelingTest
{
    typedef MultiArray<5, unsigned int> Array5;
    typedef MultiArray<2, unsigned int> Array2;
    typedef MultiArray<1, unsigned int> Array1;

    typedef Array5::difference_type Shape5;
    typedef Array2::difference_type Shape2;
    typedef Array1::difference_type Shape1;

    vector<Array5> array_fives;
    vector<Array2> array_twos;
    vector<Array1> array_ones;

    vector<Shape5> shape_fives;
    vector<Shape2> shape_twos;
    vector<Shape1> shape_ones;

    BlockwiseLabelingTest()
    {
        array_fives.push_back(Array5(Shape5(1)));
        array_fives.push_back(Array5(Shape5(2,2,3,4,3)));
        array_fives.push_back(Array5(Shape5(5,6,2,2,3)));
        for(int i = 0; i != array_fives.size(); ++i)
        {
            fillRandom(array_fives[i].begin(), array_fives[i].end(), 3);
        }

        array_twos.push_back(Array2(Shape2(1)));
        array_twos.push_back(Array2(Shape2(1,2)));
        array_twos.push_back(Array2(Shape2(2,2)));
        array_twos.push_back(Array2(Shape2(4,4)));
        array_twos.push_back(Array2(Shape2(6,10)));
        array_twos.push_back(Array2(Shape2(19,25)));
        for(int i = 0; i != array_twos.size(); ++i)
        {
            fillRandom(array_twos[i].begin(), array_twos[i].end(), 3);
        }

        array_ones.push_back(Array1(Shape1(1)));
        array_ones.push_back(Array1(Shape1(2)));
        array_ones.push_back(Array1(Shape1(47)));
        array_ones.push_back(Array1(Shape1(81)));
        array_ones.push_back(Array1(Shape1(997)));
        for(int i = 0; i != array_ones.size(); ++i)
        {
            fillRandom(array_ones[i].begin(), array_ones[i].end(), 3);
        }

        shape_fives.push_back(Shape5(1));
        shape_fives.push_back(Shape5(2));
        shape_fives.push_back(Shape5(5,4,3,2,1));
        shape_fives.push_back(Shape5(100000));

        shape_twos.push_back(Shape2(1));
        shape_twos.push_back(Shape2(2));
        shape_twos.push_back(Shape2(5,4));
        shape_twos.push_back(Shape2(1000000));

        shape_ones.push_back(Shape1(1));
        shape_ones.push_back(Shape1(2));
        shape_ones.push_back(Shape1(3));
        shape_ones.push_back(Shape1(5));
        shape_ones.push_back(Shape1(213));
    }

    void debugTest()
    {
        typedef MultiArray<2, int> Array;
        typedef Array::difference_type Shape;

        Shape shape = Shape(2);
        Array data(shape);

        data(0,0) = 1;
        data(1,0) = 1;
        data(0,1) = 1;
        data(1,1) = 1;

        MultiArray<2, size_t> blockwise_labels(shape);
        MultiArray<2, size_t> labels(shape);

        Shape block_shape(1, 1);
        //TinyVector<MultiArrayIndex, 3> block_shape(1, 1, 1);

        NeighborhoodType neighborhood = IndirectNeighborhood;

        size_t count = labelMultiArrayWithBackground(data, labels, neighborhood, 1);
        size_t blockwise_count = labelMultiArrayBlockwise(data, blockwise_labels,
                                                          LabelOptions().neighborhood(neighborhood).background(1).blockShape(block_shape));
        shouldEqual(count, blockwise_count);
        shouldEqual(equivalentLabels(labels.begin(), labels.end(),
                                     blockwise_labels.begin(), blockwise_labels.end()),
                    true);
    }
    void chunkedArrayTest()
    {
        typedef ChunkedArrayLazy<3, int> DataArray;
        typedef ChunkedArrayLazy<3, size_t> LabelArray;
        typedef DataArray::shape_type Shape;

        Shape shape = Shape(100, 200, 300);
        Shape chunk_shape = Shape(32);

        DataArray data(shape, chunk_shape);
        fillRandom(data.begin(), data.end(), 3);
        LabelArray labels(shape, chunk_shape);

        LabelOptions options;
        options.neighborhood(IndirectNeighborhood).background(1);

        size_t tested_label_number = labelMultiArrayBlockwise(data, labels, options);
        MultiArray<3, size_t> checked_out_labels(shape);
        labels.checkoutSubarray(Shape(0), checked_out_labels);

        MultiArray<3, int> oldschool_data_array(shape);
        MultiArray<3, size_t> oldschool_label_array(shape);

        data.checkoutSubarray(Shape(0), oldschool_data_array);
        size_t actual_label_number = labelMultiArrayWithBackground(oldschool_data_array, oldschool_label_array,
                                                                   IndirectNeighborhood, 1);

        shouldEqual(tested_label_number, actual_label_number);
        shouldEqual(equivalentLabels(checked_out_labels.begin(), checked_out_labels.end(),
                                     oldschool_label_array.begin(), oldschool_label_array.end()), true);
    }

    void fiveDimensionalRandomTest()
    {
        testOnData(array_fives.begin(), array_fives.end(),
                     shape_fives.begin(), shape_fives.end());
    }
    void twoDimensionalRandomTest()
    {
        testOnData(array_twos.begin(), array_twos.end(),
                     shape_twos.begin(), shape_twos.end());
    }
    void oneDimensionalRandomTest()
    {
        testOnData(array_ones.begin(), array_ones.end(),
                     shape_ones.begin(), shape_ones.end());
    }
};

struct BlockwiseLabelingTestSuite
  : public test_suite
{
    BlockwiseLabelingTestSuite()
      : test_suite("blockwise labeling test")
    {
        add(testCase(&BlockwiseLabelingTest::fiveDimensionalRandomTest));
        add(testCase(&BlockwiseLabelingTest::twoDimensionalRandomTest));
        add(testCase(&BlockwiseLabelingTest::oneDimensionalRandomTest));
        add(testCase(&BlockwiseLabelingTest::debugTest));
        add(testCase(&BlockwiseLabelingTest::chunkedArrayTest));
    }
};

int main(int argc, char** argv)
{
    BlockwiseLabelingTestSuite test;
    int failed = test.run(testsToBeExecuted(argc, argv));

    cout << test.report() << endl;

    return failed != 0;
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: remote.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: jl $ $Date: 2001-03-12 14:37:21 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _BRIDGES_REMOTE_REMOTE_HXX_
#define _BRIDGES_REMOTE_REMOTE_HXX_
#include <list>

#include <osl/mutex.hxx>
#include <osl/conditn.h>
#include <osl/interlck.h>

//#include <vos/thread.hxx>

#include <uno/environment.h>

#include <bridges/remote/remote.h>
#include <bridges/remote/connection.h>

#include <com/sun/star/uno/Sequence.hxx>

namespace bridges_remote {

class Remote2RemoteStub :
    public remote_Interface
{
public:
    Remote2RemoteStub(rtl_uString *pOid,
                      typelib_InterfaceTypeDescription *pType,
                      uno_Environment *pEnvRemote,
                      requestClientSideDispatcher dispatch );
    ~Remote2RemoteStub();

    static void SAL_CALL thisAcquire( remote_Interface *pThis );
    static void SAL_CALL thisRelease( remote_Interface *pThis );
    static void SAL_CALL thisDispatch( remote_Interface * pUnoI,
                                       typelib_TypeDescription * pMemberType,
                                       void * pReturn,
                                       void * pArgs[],
                                       uno_Any ** ppException );
    static void SAL_CALL thisFree( uno_ExtEnvironment *pEnvRemote , void * );

    void releaseRemote();
public:
    ::rtl::OUString                   m_sOid;
    typelib_InterfaceTypeDescription  *m_pType;
    oslInterlockedCount               m_nRef;
    uno_Environment                   *m_pEnvRemote;
    requestClientSideDispatcher       m_dispatch;
    oslInterlockedCount m_nReleaseRemote;
};

}
#endif
<commit_msg>removed unused include <vos/..><commit_after>/*************************************************************************
 *
 *  $RCSfile: remote.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: jl $ $Date: 2001-03-16 16:27:25 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _BRIDGES_REMOTE_REMOTE_HXX_
#define _BRIDGES_REMOTE_REMOTE_HXX_
#include <list>

#include <osl/mutex.hxx>
#include <osl/conditn.h>
#include <osl/interlck.h>

#include <uno/environment.h>

#include <bridges/remote/remote.h>
#include <bridges/remote/connection.h>

#include <com/sun/star/uno/Sequence.hxx>

namespace bridges_remote {

class Remote2RemoteStub :
    public remote_Interface
{
public:
    Remote2RemoteStub(rtl_uString *pOid,
                      typelib_InterfaceTypeDescription *pType,
                      uno_Environment *pEnvRemote,
                      requestClientSideDispatcher dispatch );
    ~Remote2RemoteStub();

    static void SAL_CALL thisAcquire( remote_Interface *pThis );
    static void SAL_CALL thisRelease( remote_Interface *pThis );
    static void SAL_CALL thisDispatch( remote_Interface * pUnoI,
                                       typelib_TypeDescription * pMemberType,
                                       void * pReturn,
                                       void * pArgs[],
                                       uno_Any ** ppException );
    static void SAL_CALL thisFree( uno_ExtEnvironment *pEnvRemote , void * );

    void releaseRemote();
public:
    ::rtl::OUString                   m_sOid;
    typelib_InterfaceTypeDescription  *m_pType;
    oslInterlockedCount               m_nRef;
    uno_Environment                   *m_pEnvRemote;
    requestClientSideDispatcher       m_dispatch;
    oslInterlockedCount m_nReleaseRemote;
};

}
#endif
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
 *
 * This file is part of Orfeo Toolbox
 *
 *     https://www.orfeo-toolbox.org/
 *
 * 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 "otbWrapperQtWidgetListEditItemModel.h"

/*****************************************************************************/
/* INCLUDE SECTION                                                           */

//
// Qt includes (sorted by alphabetic order)
//// Must be included before system/custom includes.

//
// System includes (sorted by alphabetic order)

//
// ITK includes (sorted by alphabetic order)

//
// OTB includes (sorted by alphabetic order)

#include "otbWrapperStringListInterface.h"

namespace otb
{

namespace Wrapper
{

/*
  TRANSLATOR otb::Wapper::ListEditItemModel

  Necessary for lupdate to be aware of C++ namespaces.

  Context comment for translator.
*/

/*****************************************************************************/
/* CONSTANTS                                                                 */

namespace
{

const char * const
HEADERS[ ListEditItemModel::COLUMN_COUNT ] =
{
  QT_TRANSLATE_NOOP( "otb::Wrapper::ListEditItemModel", "Name" ),
};

} // end of anonymous namespace.

/*****************************************************************************/
/* STATIC IMPLEMENTATION SECTION                                             */

/*****************************************************************************/
/* CLASS IMPLEMENTATION SECTION                                              */

/*******************************************************************************/
ListEditItemModel
::ListEditItemModel( QObject * p ) :
  QAbstractItemModel( p ),
  m_StringList( nullptr )
{
}

/*******************************************************************************/
ListEditItemModel
::~ListEditItemModel()
{
}

/*******************************************************************************/
void
ListEditItemModel
::SetStringList( StringListInterface * stringList )
{
  m_StringList = stringList;
}

/*****************************************************************************/
/* QAbstractItemModel overloads                                              */
/*****************************************************************************/
int
ListEditItemModel
::columnCount( const QModelIndex & ) const
{
  // qDebug() << this << "::columnCount(" << parent << ")";

  return COLUMN_COUNT;
}

/*****************************************************************************/
QVariant
ListEditItemModel
::data( const QModelIndex & idx, int role ) const
{
  // qDebug() << this << "::data(" << idx << "," << role << ")";

  // Get layer.
  assert( m_StringList!=NULL );

  assert( idx.isValid() );
  assert( !idx.parent().isValid() );
  assert( idx.internalPointer()!=NULL );

  const StringListInterface * stringList =
    static_cast< const StringListInterface * >( idx.internalPointer() );

  assert( stringList!=nullptr );

  // Return data given role.
  switch( role )
    {
    case Qt::CheckStateRole:
      if( idx.column()!=COLUMN_NAME )
        return QVariant();
      else
	{
	assert( idx.row() >= 0 );
	return stringList->IsActive( idx.row() );
	}
      break;

    case Qt::DisplayRole:
      switch( idx.column() )
        {
        case COLUMN_NAME:
	  {
	  assert( idx.row() >= 0 );

	  std::string filename(
	    stringList->GetNthFileName( idx.row() )
	  );

	  return
	    filename.empty()
	    ? "NO FILENAME"
	    : QFile::decodeName( filename.c_str()
	    );
	  }
          break;

	default:
	  break;
        }
      break;

    case Qt::FontRole:
      break;

    case Qt::ToolTipRole:
      switch( idx.column() )
	{
	case COLUMN_NAME:
	  assert( idx.row() >= 0 );
	  return QString::fromStdString( stringList->GetToolTip( idx.row() ) );
	  break;
	}
      break;

    default:
      break;
    }

  return QVariant();
}

/*****************************************************************************/
Qt::ItemFlags
ListEditItemModel
::flags( const QModelIndex & idx ) const
{
  if( !idx.isValid() )
    return QAbstractItemModel::flags( idx );

  Qt::ItemFlags iflags =
    QAbstractItemModel::flags( idx )
    // | Qt::ItemIsDragEnabled
    // | Qt::ItemIsDropEnabled
    ;

  if( idx.column()==COLUMN_NAME )
    iflags |=
        Qt::ItemIsUserCheckable
      | Qt::ItemIsEditable
      // | Qt::ItemIsDragEnabled
      ;

  return iflags;
}

/*****************************************************************************/
bool
ListEditItemModel
::hasChildren( const QModelIndex & idx ) const
{
  return !idx.isValid();
}

/*****************************************************************************/
QVariant
ListEditItemModel
::headerData( int section,
              Qt::Orientation /**orientation*/,
              int role ) const
{
  // qDebug()
  //   << this << "::headerData("
  //   << section << "," << orientation << "," << role
  //   << ")";

  // assert( orientation==Qt::Horizontal );

  switch( role )
    {
    case Qt::DisplayRole:
      assert( section>=0 && section<COLUMN_COUNT );
      return tr( HEADERS[ section ] );
      break;

    default:
      break;
    }

  return QVariant();
}

/*****************************************************************************/
QModelIndex
ListEditItemModel
::index( int row,
         int column,
         const QModelIndex & p ) const
{
  // qDebug()
  //   << this << "::index(" << row << "," << column << "," << parent << ")";

  if( m_StringList == nullptr )
    return QModelIndex();

  // qDebug()
  //   << "index:" << row << "," << column << "," << m_StringList->At( row );

  assert( row>=0 && column>=0 );

#if 0
  AbstractLayerModel * layer = m_StringList->At( row );

  if( layer==NULL || p.isValid() )
    return QModelIndex();
#endif

  return
    createIndex(
      row,
      column,
      p.isValid()
      ? NULL
      : m_StringList
    );
}

/*****************************************************************************/
bool
ListEditItemModel
::insertRow( int row, const QModelIndex & parent )
{
  return insertRows( row, 1, parent );
}

/*****************************************************************************/
bool
ListEditItemModel
::insertRows( int row, int count, const QModelIndex & parent )
{
  // qDebug() << this << "::insertRows(" << row << "," << count << "," << parent << ")";

  assert( m_StringList!=nullptr );

  beginInsertRows( parent, row, count );
  {
    for( int r=row; r<row+count; ++r )
      m_StringList->Insert( "", r );
  }
  endInsertRows();

  return true;
}

/*****************************************************************************/
QModelIndex
ListEditItemModel
::parent( const QModelIndex & ) const
{
  // qDebug() << this << "::parent(" << index << ")";

  return QModelIndex();
}

/*****************************************************************************/
int
ListEditItemModel
::rowCount( const QModelIndex & p ) const
{
  // qDebug() << this << "::rowCount(" << p << ")";

  // qDebug() << "row-count:" <<
  //   ( ( m_StringList==NULL || p.isValid() )
  //     ? 0
  //     : m_StringList->GetCount()
  //   );

  return
    ( m_StringList==nullptr || p.isValid() )
    ? 0
    : m_StringList->Size();
}

/*****************************************************************************/
bool
ListEditItemModel
::setData( const QModelIndex & idx,
           const QVariant & value,
           int role )
{
  qDebug()
    << this << "::setData(" << idx << "," << value << "," << role
    << ");";

  assert( !idx.parent().isValid() );
  assert( idx.row()>=0 );
  assert( idx.internalPointer()!=nullptr );

  StringListInterface * stringList =
    static_cast< StringListInterface * >( idx.internalPointer() );

  switch( idx.column() )
    {
    case COLUMN_NAME:
      switch( role )
	{
	case Qt::EditRole:
	  stringList->SetNthFileName(
	    idx.row(),
	    QFile::encodeName( value.toString() ).data()
	  );

	  return true;
	  break;

	case Qt::CheckStateRole:
	  break;

	default:
	  break;
	}
      break;

    default:
      break;
    }

  return false;
}

/*******************************************************************************/
/* SLOTS                                                                       */
/*******************************************************************************/

} // end namespace 'Wrapper'.

} // end namespace 'otb'
<commit_msg>ENH: Disable debug trace.<commit_after>/*
 * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
 *
 * This file is part of Orfeo Toolbox
 *
 *     https://www.orfeo-toolbox.org/
 *
 * 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 "otbWrapperQtWidgetListEditItemModel.h"

/*****************************************************************************/
/* INCLUDE SECTION                                                           */

//
// Qt includes (sorted by alphabetic order)
//// Must be included before system/custom includes.

//
// System includes (sorted by alphabetic order)

//
// ITK includes (sorted by alphabetic order)

//
// OTB includes (sorted by alphabetic order)

#include "otbWrapperStringListInterface.h"

namespace otb
{

namespace Wrapper
{

/*
  TRANSLATOR otb::Wapper::ListEditItemModel

  Necessary for lupdate to be aware of C++ namespaces.

  Context comment for translator.
*/

/*****************************************************************************/
/* CONSTANTS                                                                 */

namespace
{

const char * const
HEADERS[ ListEditItemModel::COLUMN_COUNT ] =
{
  QT_TRANSLATE_NOOP( "otb::Wrapper::ListEditItemModel", "Name" ),
};

} // end of anonymous namespace.

/*****************************************************************************/
/* STATIC IMPLEMENTATION SECTION                                             */

/*****************************************************************************/
/* CLASS IMPLEMENTATION SECTION                                              */

/*******************************************************************************/
ListEditItemModel
::ListEditItemModel( QObject * p ) :
  QAbstractItemModel( p ),
  m_StringList( nullptr )
{
}

/*******************************************************************************/
ListEditItemModel
::~ListEditItemModel()
{
}

/*******************************************************************************/
void
ListEditItemModel
::SetStringList( StringListInterface * stringList )
{
  m_StringList = stringList;
}

/*****************************************************************************/
/* QAbstractItemModel overloads                                              */
/*****************************************************************************/
int
ListEditItemModel
::columnCount( const QModelIndex & ) const
{
  // qDebug() << this << "::columnCount(" << parent << ")";

  return COLUMN_COUNT;
}

/*****************************************************************************/
QVariant
ListEditItemModel
::data( const QModelIndex & idx, int role ) const
{
  // qDebug() << this << "::data(" << idx << "," << role << ")";

  // Get layer.
  assert( m_StringList!=NULL );

  assert( idx.isValid() );
  assert( !idx.parent().isValid() );
  assert( idx.internalPointer()!=NULL );

  const StringListInterface * stringList =
    static_cast< const StringListInterface * >( idx.internalPointer() );

  assert( stringList!=nullptr );

  // Return data given role.
  switch( role )
    {
    case Qt::CheckStateRole:
      if( idx.column()!=COLUMN_NAME )
        return QVariant();
      else
	{
	assert( idx.row() >= 0 );
	return stringList->IsActive( idx.row() );
	}
      break;

    case Qt::DisplayRole:
      switch( idx.column() )
        {
        case COLUMN_NAME:
	  {
	  assert( idx.row() >= 0 );

	  std::string filename(
	    stringList->GetNthFileName( idx.row() )
	  );

	  return
	    filename.empty()
	    ? "NO FILENAME"
	    : QFile::decodeName( filename.c_str()
	    );
	  }
          break;

	default:
	  break;
        }
      break;

    case Qt::FontRole:
      break;

    case Qt::ToolTipRole:
      switch( idx.column() )
	{
	case COLUMN_NAME:
	  assert( idx.row() >= 0 );
	  return QString::fromStdString( stringList->GetToolTip( idx.row() ) );
	  break;
	}
      break;

    default:
      break;
    }

  return QVariant();
}

/*****************************************************************************/
Qt::ItemFlags
ListEditItemModel
::flags( const QModelIndex & idx ) const
{
  if( !idx.isValid() )
    return QAbstractItemModel::flags( idx );

  Qt::ItemFlags iflags =
    QAbstractItemModel::flags( idx )
    // | Qt::ItemIsDragEnabled
    // | Qt::ItemIsDropEnabled
    ;

  if( idx.column()==COLUMN_NAME )
    iflags |=
        Qt::ItemIsUserCheckable
      | Qt::ItemIsEditable
      // | Qt::ItemIsDragEnabled
      ;

  return iflags;
}

/*****************************************************************************/
bool
ListEditItemModel
::hasChildren( const QModelIndex & idx ) const
{
  return !idx.isValid();
}

/*****************************************************************************/
QVariant
ListEditItemModel
::headerData( int section,
              Qt::Orientation /**orientation*/,
              int role ) const
{
  // qDebug()
  //   << this << "::headerData("
  //   << section << "," << orientation << "," << role
  //   << ")";

  // assert( orientation==Qt::Horizontal );

  switch( role )
    {
    case Qt::DisplayRole:
      assert( section>=0 && section<COLUMN_COUNT );
      return tr( HEADERS[ section ] );
      break;

    default:
      break;
    }

  return QVariant();
}

/*****************************************************************************/
QModelIndex
ListEditItemModel
::index( int row,
         int column,
         const QModelIndex & p ) const
{
  // qDebug()
  //   << this << "::index(" << row << "," << column << "," << parent << ")";

  if( m_StringList == nullptr )
    return QModelIndex();

  // qDebug()
  //   << "index:" << row << "," << column << "," << m_StringList->At( row );

  assert( row>=0 && column>=0 );

#if 0
  AbstractLayerModel * layer = m_StringList->At( row );

  if( layer==NULL || p.isValid() )
    return QModelIndex();
#endif

  return
    createIndex(
      row,
      column,
      p.isValid()
      ? NULL
      : m_StringList
    );
}

/*****************************************************************************/
bool
ListEditItemModel
::insertRow( int row, const QModelIndex & parent )
{
  return insertRows( row, 1, parent );
}

/*****************************************************************************/
bool
ListEditItemModel
::insertRows( int row, int count, const QModelIndex & parent )
{
  // qDebug() << this << "::insertRows(" << row << "," << count << "," << parent << ")";

  assert( m_StringList!=nullptr );

  beginInsertRows( parent, row, count );
  {
    for( int r=row; r<row+count; ++r )
      m_StringList->Insert( "", r );
  }
  endInsertRows();

  return true;
}

/*****************************************************************************/
QModelIndex
ListEditItemModel
::parent( const QModelIndex & ) const
{
  // qDebug() << this << "::parent(" << index << ")";

  return QModelIndex();
}

/*****************************************************************************/
int
ListEditItemModel
::rowCount( const QModelIndex & p ) const
{
  // qDebug() << this << "::rowCount(" << p << ")";

  // qDebug() << "row-count:" <<
  //   ( ( m_StringList==NULL || p.isValid() )
  //     ? 0
  //     : m_StringList->GetCount()
  //   );

  return
    ( m_StringList==nullptr || p.isValid() )
    ? 0
    : m_StringList->Size();
}

/*****************************************************************************/
bool
ListEditItemModel
::setData( const QModelIndex & idx,
           const QVariant & value,
           int role )
{
  // qDebug()
  //   << this << "::setData(" << idx << "," << value << "," << role
  //   << ");";

  assert( !idx.parent().isValid() );
  assert( idx.row()>=0 );
  assert( idx.internalPointer()!=nullptr );

  StringListInterface * stringList =
    static_cast< StringListInterface * >( idx.internalPointer() );

  switch( idx.column() )
    {
    case COLUMN_NAME:
      switch( role )
	{
	case Qt::EditRole:
	  stringList->SetNthFileName(
	    idx.row(),
	    QFile::encodeName( value.toString() ).data()
	  );

	  return true;
	  break;

	case Qt::CheckStateRole:
	  break;

	default:
	  break;
	}
      break;

    default:
      break;
    }

  return false;
}

/*******************************************************************************/
/* SLOTS                                                                       */
/*******************************************************************************/

} // end namespace 'Wrapper'.

} // end namespace 'otb'
<|endoftext|>


<commit_before>#include "webcam.hpp"

using namespace cv;
using namespace std;

int main (int argc, char** argv) {

 CvCapture* capture = 0;
 int width, height, fps;

 capture = cvCaptureFromCAM(0);

 if (!capture) {
  printf("No camera detected!");
  return -1;
 }

 ifstream configFile (".config");

 if (configFile.is_open()) {

  //probably want to support corrupted .config
  string line;
  getline(configFile, line);
  istringstream(line)>>width;
  getline(configFile, line);
  istringstream(line)>>height;
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, width);
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, height);

  configFile.close();

 } else {

  initResolutions();

  for (int i=36; i<150; i++) {
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, resolutions[i].width);
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, resolutions[i].height);
  }

  width = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
  height = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);

  ofstream configFileOut(".config");
  configFileOut << width;
  configFileOut << "\n";
  configFileOut << height;
  configFileOut << "\n";
  configFileOut.close();
 }

 bool keepGoing = true;

// srand(890);//not interested in good randomness

 Mat image;
 Mat channel[3];

 while (keepGoing) {

  image = cvQueryFrame(capture);
  imshow("webcam", image);

// thresholds on dark regions

  Mat gray, blurred_gray, threshold_gray;
  cvtColor(image, gray, CV_BGR2GRAY);
  blur(gray, blurred_gray, Size(width/10,height/20));
  equalizeHist(blurred_gray, blurred_gray);
  threshold(blurred_gray, threshold_gray, 40, 1, THRESH_BINARY_INV);
  imshow("threshold", threshold_gray);

  Mat inverst;
  bitwise_not(threshold_gray, inverst);
  Mat mask = threshold_gray;//.mult(inverst);

  Moments lol = moments(mask, 1);
  circle(image, Point(lol.m10/lol.m00,lol.m01/lol.m00),20,Scalar(128),30);
  imshow("threshold", image);
  keepGoing = (waitKey(25)<0);

 }

 cvReleaseCapture(&capture);

 return 0;
}
<commit_msg>hacking<commit_after>#include "webcam.hpp"

using namespace cv;
using namespace std;

int main (int argc, char** argv) {

 CvCapture* capture = 0;
 int width, height, fps;

 capture = cvCaptureFromCAM(0);

 if (!capture) {
  printf("No camera detected!");
  return -1;
 }

 ifstream configFile (".config");

 if (configFile.is_open()) {

  //probably want to support corrupted .config
  string line;
  getline(configFile, line);
  istringstream(line)>>width;
  getline(configFile, line);
  istringstream(line)>>height;
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, width);
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, height);

  configFile.close();

 } else {

  initResolutions();

  for (int i=36; i<150; i++) {
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, resolutions[i].width);
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, resolutions[i].height);
  }

  width = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
  height = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);

  ofstream configFileOut(".config");
  configFileOut << width;
  configFileOut << "\n";
  configFileOut << height;
  configFileOut << "\n";
  configFileOut.close();
 }

 bool keepGoing = true;

// srand(890);//not interested in good randomness

 Mat image;
 Mat channel[3];

 while (keepGoing) {

  image = cvQueryFrame(capture);
  imshow("webcam", image);

// thresholds on dark regions

  Mat gray, blurred_gray, threshold_gray;
  cvtColor(image, gray, CV_BGR2GRAY);
  blur(gray, blurred_gray, Size(width/10,height/20));
  equalizeHist(blurred_gray, blurred_gray);
  threshold(blurred_gray, threshold_gray, 40, 1, THRESH_BINARY_INV);
  imshow("threshold", threshold_gray);

  Mat inverst;
  bitwise_not(threshold_gray, inverst);
  Mat mask = threshold_gray.mult(inverst);

  Moments lol = moments(mask, 1);
  circle(image, Point(lol.m10/lol.m00,lol.m01/lol.m00),20,Scalar(128),30);
  imshow("threshold", image);
  keepGoing = (waitKey(25)<0);

 }

 cvReleaseCapture(&capture);

 return 0;
}
<|endoftext|>


<commit_before>#include "webcam.hpp"
#include <chrono>

using namespace cv;
using namespace std;

Mat ellipticKernel(int width, int height = -1) {
 if (height==-1) {
  return getStructuringElement(MORPH_ELLIPSE,Size(width,width), Point(width/2, width/2));
 } else {
  return getStructuringElement(MORPH_ELLIPSE,Size(width,height), Point(width/2, height/2));
 }
}

unsigned long long getMilliseconds() {
 return chrono::system_clock::now().time_since_epoch()/chrono::milliseconds(1);
}

void morphFast(Mat inout, int smallsize = 100, int factor = 25, int eq = 1, int diler = 0) {
 int width, height;
 width = inout.size().width;
 height = inout.size().height;
 Mat downsample;
 resize(inout, downsample, Size(smallsize,smallsize));
 Mat kernel = ellipticKernel(factor);
 if (diler) {
  erode(downsample, downsample, kernel);
 } else {
  dilate(downsample, downsample, kernel);
 }
 if (eq) {
  equalizeHist(downsample, downsample);
 }
 resize(downsample, inout, Size(width, height));
}

int main (int argc, char** argv) {

 int tracker1, tracker2, tracker3;
 namedWindow("s",1);
 createTrackbar("1","s",&tracker1,100);
 createTrackbar("2","s",&tracker2,100);
 createTrackbar("3","s",&tracker3,100);

 CvCapture* capture = 0;
 int width, height, fps;

 capture = cvCaptureFromCAM(0);

 if (!capture) {
  printf("No camera detected!");
  return -1;
 }

 unsigned long long times[100];
 int f = 0;
 for (int i=0; i<100; i++)
  times[i] = 0;

 ifstream configFile (".config");

 if (configFile.is_open()) {

  //probably want to support corrupted .config
  string line;
  getline(configFile, line);
  istringstream(line)>>width;
  getline(configFile, line);
  istringstream(line)>>height;
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, width);
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, height);

  configFile.close();

 } else {

  initResolutions();

  for (int i=36; i<150; i++) {
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, resolutions[i].width);
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, resolutions[i].height);
  }

  width = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
  height = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);

  ofstream configFileOut(".config");
  configFileOut << width;
  configFileOut << "\n";
  configFileOut << height;
  configFileOut << "\n";
  configFileOut.close();
 }

 bool keepGoing = true;

// srand(890);//not interested in good randomness

 for (int i = 0; i < 30; i++) {
  // capture some frames so exposure correction takes place
  cvQueryFrame(capture);
 }

 Mat background = cvQueryFrame(capture);
 background = background.clone();
 blur(background, background, Size(50,50));

 Mat image;
 Mat channel[3];
 unsigned long long timenow = getMilliseconds();

 while (keepGoing) {
  image = cvQueryFrame(capture);
  times[0] += getMilliseconds() - timenow;
  timenow = getMilliseconds();
// preprocess by rotating according to OVR roll
//  imshow("webcam", image);

// let's make multiple masks where 0=not mouth, 1=uncertain

// then multiply them together and multiply that with image
// and run haar classifier on image

  Mat gray, blurred_img;
  cvtColor(image, gray, CV_RGB2GRAY);
  blur(image, blurred_img, Size(50,50));
  times[1] += getMilliseconds() - timenow;
  timenow = getMilliseconds();

// this mask filters out areas with too many edges
// removed for now; it didn't generalize well
/*
  Mat canny;
  Canny(gray, canny, 50, 50, 3);
  blur(canny, canny, Size(width/20,height/20));
  bitwise_not(canny, canny);
  threshold(canny, canny, 200, 1, THRESH_BINARY);
  blur(canny*255, canny, Size(width/10, height/10));
  threshold(canny, canny, 220, 1, THRESH_BINARY);
  imshow("canny mask", gray.mul(canny));
*/

// this mask filters out areas which have not changed much
// background needs to be updated when person is not in frame
// use OVR SDK to do this later
  Mat flow;
  absdiff(blurred_img, background, flow);
  cvtColor(flow, flow, CV_RGB2GRAY);
  morphFast(flow);
  threshold(flow, flow, 60, 1, THRESH_BINARY);
//  imshow("flow mask", gray.mul(flow));
  times[2] += getMilliseconds() - timenow;
  timenow = getMilliseconds();

// this mask gets anything kind of dark (DK2) and dilates
  Mat kindofdark;
  equalizeHist(gray, kindofdark);
  threshold(kindofdark, kindofdark, 100, 1, THRESH_BINARY_INV);
  morphFast(kindofdark, 100, 17, 0);
//  imshow("dark mask", gray.mul(kindofdark));
  times[3] += getMilliseconds() - timenow;
  timenow = getMilliseconds();

// this mask gets rid of anything far away from red stuff
// did not work well and was slow
/*
  Mat notlips;
  Mat channels[3];
  split(image, channels);
  channels[2].convertTo(notlips, CV_32FC1);
  divide(notlips, gray, notlips, 1, CV_32FC1);
  //equalistHist is horrible for a red background
  //equalizeHist(notlips, notlips);
  threshold(notlips, notlips, tracker3/30.0, 1, THRESH_BINARY);
  notlips.convertTo(notlips, CV_8UC1);
  imshow("lip mask", notlips*255);
  Mat otherMorph = notlips.clone();
  int tx = tracker1+1-(tracker1%2);
  if (tx<3) tx=1;
  if (tx>90) tx=91;
  morphFast(notlips, 100, tx, 0, 0);
  int ty = tracker2+1-(tracker2%2);
  if (ty<3) ty=1;
  if (ty>90) ty=91;
  morphFast(notlips, 100, ty, 0, 1);
  imshow("lips2", notlips.mul(gray));
  morphFast(otherMorph, 100, tx, 0, 1);
  morphFast(otherMorph, 100, tx, 0, 0);
  imshow("lips3", otherMorph.mul(gray));
  waitKey(1);
*/

  Mat mask = flow.mul(kindofdark);
// open the mask
  Mat smallMask0, smallMask1;
  resize(mask, smallMask0, Size(width/5,height/5));
  Mat smallKernel = ellipticKernel(69,79);
  erode(smallMask0, smallMask1, smallKernel);
  dilate(smallMask1, smallMask1, smallKernel);
  bitwise_and(smallMask0, smallMask1, smallMask1);
  resize(smallMask1, mask, Size(width, height));
//  imshow("morph mask", gray.mul(mask));
  times[4] += getMilliseconds() - timenow;
  timenow = getMilliseconds();

// update background with new morph mask
// average what we know is background with prior background
// dilate it first since we really want to be sure it's bg

/*
// actually dilation is slow and our current mask is already
// really nice :)
  Mat dilatedMask;
  dilate(smallMask1, dilatedMask, smallKernel);
  resize(dilatedMask, dilatedMask, Size(width, height));
  imshow("erosion", dilatedMask.mul(gray));
*/
//  imshow("background", background);

/*
  Moments lol = moments(gray, 1);
  circle(image, Point(lol.m10/lol.m00,lol.m01/lol.m00),20,Scalar(128),30);
  imshow("leimage", image);
*/

  CascadeClassifier mouth_cascade;
  mouth_cascade.load("Mouth.xml");
  vector<Rect> mouths;
  int scale = 3;
  Mat classifyThis;
  equalizeHist(gray, gray);//ew; watch out not to use this later
  resize(gray.mul(mask), classifyThis, Size(width/scale,height/scale));
//  bilateralFilter(gray, classifyThis, 15, 10, 1);
  mouth_cascade.detectMultiScale(classifyThis, mouths, 1.1, 0, CV_HAAR_SCALE_IMAGE);
  Mat rectImage(height, width, CV_8UC1, Scalar(0));
  for (size_t i=0; i<mouths.size(); i++) {
   Rect scaled(mouths[i].x*scale, mouths[i].y*scale, mouths[i].width*scale,mouths[i].height*scale);
   Mat newRect(height, width, CV_8UC1, Scalar(0));
   rectangle(newRect, scaled, Scalar(1), CV_FILLED);
   rectImage += newRect;
  }
  int minVal, maxVal;//ignore minVal, it'll be 0
  minMaxLoc(rectImage, &minVal, &maxVal);
  threshold(rectImage, rectImage, maxVal, 1, THRESH_BINARY);
  times[6] += getMilliseconds() - timenow;
  timenow = getMilliseconds();
  imshow("MOUTH", rectImage.mul(gray));

  bitwise_and(rectImage, mask, mask);

  Mat mask_;
  subtract(1, mask ,mask_);
  Mat mask3, mask3_;
  channel[0] = mask;
  channel[1] = mask;
  channel[2] = mask;
  merge(channel, 3, mask3);
  channel[0] = mask_;
  channel[1] = mask_;
  channel[2] = mask_;
  merge(channel, 3, mask3_);

  background = background.mul(mask3) +
   (background.mul(mask3_)/2 + blurred_img.mul(mask3_)/2);
  times[5] += getMilliseconds() - timenow;
  timenow = getMilliseconds();

  for (int i=0; i<7; i++) {
   printf("%llu , ", times[i]);
   times[i] = 0;
  }

  printf("\n");

  keepGoing = (waitKey(1)<0);

 }

 cvReleaseCapture(&capture);

 return 0;
}
<commit_msg>hacking<commit_after>#include "webcam.hpp"
#include <chrono>

using namespace cv;
using namespace std;

Mat ellipticKernel(int width, int height = -1) {
 if (height==-1) {
  return getStructuringElement(MORPH_ELLIPSE,Size(width,width), Point(width/2, width/2));
 } else {
  return getStructuringElement(MORPH_ELLIPSE,Size(width,height), Point(width/2, height/2));
 }
}

unsigned long long getMilliseconds() {
 return chrono::system_clock::now().time_since_epoch()/chrono::milliseconds(1);
}

void morphFast(Mat inout, int smallsize = 100, int factor = 25, int eq = 1, int diler = 0) {
 int width, height;
 width = inout.size().width;
 height = inout.size().height;
 Mat downsample;
 resize(inout, downsample, Size(smallsize,smallsize));
 Mat kernel = ellipticKernel(factor);
 if (diler) {
  erode(downsample, downsample, kernel);
 } else {
  dilate(downsample, downsample, kernel);
 }
 if (eq) {
  equalizeHist(downsample, downsample);
 }
 resize(downsample, inout, Size(width, height));
}

int main (int argc, char** argv) {

 int tracker1, tracker2, tracker3;
 namedWindow("s",1);
 createTrackbar("1","s",&tracker1,100);
 createTrackbar("2","s",&tracker2,100);
 createTrackbar("3","s",&tracker3,100);

 CvCapture* capture = 0;
 int width, height, fps;

 capture = cvCaptureFromCAM(0);

 if (!capture) {
  printf("No camera detected!");
  return -1;
 }

 unsigned long long times[100];
 int f = 0;
 for (int i=0; i<100; i++)
  times[i] = 0;

 ifstream configFile (".config");

 if (configFile.is_open()) {

  //probably want to support corrupted .config
  string line;
  getline(configFile, line);
  istringstream(line)>>width;
  getline(configFile, line);
  istringstream(line)>>height;
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, width);
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, height);

  configFile.close();

 } else {

  initResolutions();

  for (int i=36; i<150; i++) {
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, resolutions[i].width);
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, resolutions[i].height);
  }

  width = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
  height = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);

  ofstream configFileOut(".config");
  configFileOut << width;
  configFileOut << "\n";
  configFileOut << height;
  configFileOut << "\n";
  configFileOut.close();
 }

 bool keepGoing = true;

// srand(890);//not interested in good randomness

 for (int i = 0; i < 30; i++) {
  // capture some frames so exposure correction takes place
  cvQueryFrame(capture);
 }

 Mat background = cvQueryFrame(capture);
 background = background.clone();
 blur(background, background, Size(50,50));

 Mat image;
 Mat channel[3];
 unsigned long long timenow = getMilliseconds();

 while (keepGoing) {
  image = cvQueryFrame(capture);
  times[0] += getMilliseconds() - timenow;
  timenow = getMilliseconds();
// preprocess by rotating according to OVR roll
//  imshow("webcam", image);

// let's make multiple masks where 0=not mouth, 1=uncertain

// then multiply them together and multiply that with image
// and run haar classifier on image

  Mat gray, blurred_img;
  cvtColor(image, gray, CV_RGB2GRAY);
  blur(image, blurred_img, Size(50,50));
  times[1] += getMilliseconds() - timenow;
  timenow = getMilliseconds();

// this mask filters out areas with too many edges
// removed for now; it didn't generalize well
/*
  Mat canny;
  Canny(gray, canny, 50, 50, 3);
  blur(canny, canny, Size(width/20,height/20));
  bitwise_not(canny, canny);
  threshold(canny, canny, 200, 1, THRESH_BINARY);
  blur(canny*255, canny, Size(width/10, height/10));
  threshold(canny, canny, 220, 1, THRESH_BINARY);
  imshow("canny mask", gray.mul(canny));
*/

// this mask filters out areas which have not changed much
// background needs to be updated when person is not in frame
// use OVR SDK to do this later
  Mat flow;
  absdiff(blurred_img, background, flow);
  cvtColor(flow, flow, CV_RGB2GRAY);
  morphFast(flow);
  threshold(flow, flow, 60, 1, THRESH_BINARY);
//  imshow("flow mask", gray.mul(flow));
  times[2] += getMilliseconds() - timenow;
  timenow = getMilliseconds();

// this mask gets anything kind of dark (DK2) and dilates
  Mat kindofdark;
  equalizeHist(gray, kindofdark);
  threshold(kindofdark, kindofdark, 100, 1, THRESH_BINARY_INV);
  morphFast(kindofdark, 100, 17, 0);
//  imshow("dark mask", gray.mul(kindofdark));
  times[3] += getMilliseconds() - timenow;
  timenow = getMilliseconds();

// this mask gets rid of anything far away from red stuff
// did not work well and was slow
/*
  Mat notlips;
  Mat channels[3];
  split(image, channels);
  channels[2].convertTo(notlips, CV_32FC1);
  divide(notlips, gray, notlips, 1, CV_32FC1);
  //equalistHist is horrible for a red background
  //equalizeHist(notlips, notlips);
  threshold(notlips, notlips, tracker3/30.0, 1, THRESH_BINARY);
  notlips.convertTo(notlips, CV_8UC1);
  imshow("lip mask", notlips*255);
  Mat otherMorph = notlips.clone();
  int tx = tracker1+1-(tracker1%2);
  if (tx<3) tx=1;
  if (tx>90) tx=91;
  morphFast(notlips, 100, tx, 0, 0);
  int ty = tracker2+1-(tracker2%2);
  if (ty<3) ty=1;
  if (ty>90) ty=91;
  morphFast(notlips, 100, ty, 0, 1);
  imshow("lips2", notlips.mul(gray));
  morphFast(otherMorph, 100, tx, 0, 1);
  morphFast(otherMorph, 100, tx, 0, 0);
  imshow("lips3", otherMorph.mul(gray));
  waitKey(1);
*/

  Mat mask = flow.mul(kindofdark);
// open the mask
  Mat smallMask0, smallMask1;
  resize(mask, smallMask0, Size(width/5,height/5));
  Mat smallKernel = ellipticKernel(69,79);
  erode(smallMask0, smallMask1, smallKernel);
  dilate(smallMask1, smallMask1, smallKernel);
  bitwise_and(smallMask0, smallMask1, smallMask1);
  resize(smallMask1, mask, Size(width, height));
//  imshow("morph mask", gray.mul(mask));
  times[4] += getMilliseconds() - timenow;
  timenow = getMilliseconds();

// update background with new morph mask
// average what we know is background with prior background
// dilate it first since we really want to be sure it's bg

/*
// actually dilation is slow and our current mask is already
// really nice :)
  Mat dilatedMask;
  dilate(smallMask1, dilatedMask, smallKernel);
  resize(dilatedMask, dilatedMask, Size(width, height));
  imshow("erosion", dilatedMask.mul(gray));
*/
//  imshow("background", background);

/*
  Moments lol = moments(gray, 1);
  circle(image, Point(lol.m10/lol.m00,lol.m01/lol.m00),20,Scalar(128),30);
  imshow("leimage", image);
*/

  CascadeClassifier mouth_cascade;
  mouth_cascade.load("Mouth.xml");
  vector<Rect> mouths;
  int scale = 3;
  Mat classifyThis;
  equalizeHist(gray, gray);//ew; watch out not to use this later
  resize(gray.mul(mask), classifyThis, Size(width/scale,height/scale));
//  bilateralFilter(gray, classifyThis, 15, 10, 1);
  mouth_cascade.detectMultiScale(classifyThis, mouths, 1.1, 0, CV_HAAR_SCALE_IMAGE);
  Mat rectImage(height, width, CV_8UC1, Scalar(0));
  for (size_t i=0; i<mouths.size(); i++) {
   Rect scaled(mouths[i].x*scale, mouths[i].y*scale, mouths[i].width*scale,mouths[i].height*scale);
   Mat newRect(height, width, CV_8UC1, Scalar(0));
   rectangle(newRect, scaled, Scalar(1), CV_FILLED);
   rectImage += newRect;
  }
  double minVal, maxVal;//ignore minVal, it'll be 0
  minMaxLoc(rectImage, &minVal, &maxVal);
  threshold(rectImage, rectImage, maxVal, 1, THRESH_BINARY);
  times[6] += getMilliseconds() - timenow;
  timenow = getMilliseconds();
  imshow("MOUTH", rectImage.mul(gray));

  bitwise_and(rectImage, mask, mask);

  Mat mask_;
  subtract(1, mask ,mask_);
  Mat mask3, mask3_;
  channel[0] = mask;
  channel[1] = mask;
  channel[2] = mask;
  merge(channel, 3, mask3);
  channel[0] = mask_;
  channel[1] = mask_;
  channel[2] = mask_;
  merge(channel, 3, mask3_);

  background = background.mul(mask3) +
   (background.mul(mask3_)/2 + blurred_img.mul(mask3_)/2);
  times[5] += getMilliseconds() - timenow;
  timenow = getMilliseconds();

  for (int i=0; i<7; i++) {
   printf("%llu , ", times[i]);
   times[i] = 0;
  }

  printf("\n");

  keepGoing = (waitKey(1)<0);

 }

 cvReleaseCapture(&capture);

 return 0;
}
<|endoftext|>


<commit_before>//
// Copyright (c) articy Software GmbH & Co. KG. All rights reserved.
//

#include "Customizations/ArticyRefCustomization.h"
#include "IDetailChildrenBuilder.h"
#include "DetailWidgetRow.h"
#include "Widgets/SWidget.h"
#include "Modules/ModuleManager.h"
#include "IDetailPropertyRow.h"
#include "Delegates/Delegate.h"
#include "ArticyObject.h"
#include "ArticyRef.h"
#include "ClassViewerModule.h"
#include "UObject/ConstructorHelpers.h"

TSharedRef<IPropertyTypeCustomization> FArticyRefCustomization::MakeInstance()
{
	return MakeShareable(new FArticyRefCustomization());
}

void FArticyRefCustomization::CustomizeHeader(TSharedRef<IPropertyHandle> PropertyHandle, FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& CustomizationUtils)
{
	ArticyRefPropertyHandle = PropertyHandle;

	// update the reference upon selecting the ref; this only serves cosmetic purposes. The underlying Id will not be changed
	FArticyRef* ArticyRef = RetrieveArticyRef(ArticyRefPropertyHandle.Get());

	UArticyObject* SelectedObject = UArticyObject::FindAsset(ArticyRef->GetId());

	// attempt to set the class restriction via meta data (cpp means that the programmer has mandated a specific type)
	ClassRestriction = GetClassRestrictionMetaData();

	// if there is no meta data class restriction,
	if (ClassRestriction == nullptr && SelectedObject)
	{
		ClassRestriction = SelectedObject->UObject::GetClass();
	}

	if (ClassRestriction == nullptr)
	{
		ClassRestriction = UArticyObject::StaticClass();
	}

	ArticyRefProperty = SNew(SArticyRefProperty, ArticyRefPropertyHandle.Get())
		.ClassRestriction(this, &FArticyRefCustomization::GetClassRestriction);

	HeaderRow.NameContent()
	[
		ArticyRefPropertyHandle->CreatePropertyNameWidget()
	]
	.ValueContent()
	.MinDesiredWidth(150)
	[
		ArticyRefProperty.ToSharedRef()
	];
}

void FArticyRefCustomization::CustomizeChildren(TSharedRef<IPropertyHandle> PropertyHandle, IDetailChildrenBuilder& ChildBuilder, IPropertyTypeCustomizationUtils& CustomizationUtils)
{
	ClassRestrictionButton =
		SNew(SComboButton)
		.OnGetMenuContent(this, &FArticyRefCustomization::CreateClassPicker)
		.IsEnabled_Lambda([this]() -> bool
	{
		return !HasClassRestrictionMetaData();
	})
		.ContentPadding(2.f)
		.ButtonContent()
		[
			SNew(STextBlock)
			.Text(this, &FArticyRefCustomization::GetChosenClassName)
		];

	ChildBuilder.AddCustomRow(FText::FromString("Class Restriction"))
		.NameContent()
		[
			SNew(SHorizontalBox)
			+ SHorizontalBox::Slot()
			.Padding(FMargin(0, 1, 0, 1))
			.FillWidth(1)
			[
				SNew(SBorder)
				.Padding(FMargin(0.0f, 2.0f))
				.VAlign(VAlign_Center)
				[
					SNew(STextBlock)
					.Text(FText::FromString("Class Restriction"))
				]
			]
		]
		.ValueContent()
		.MinDesiredWidth(150.f)
		.MaxDesiredWidth(250.f)
		[
			ClassRestrictionButton.ToSharedRef()
		];

	uint32 NumChildren;
	ArticyRefPropertyHandle->GetNumChildren(NumChildren);

	// restore all default editor property widgets
	for (uint32 ChildIndex = 0; ChildIndex < NumChildren; ++ChildIndex)
	{
		const TSharedRef< IPropertyHandle > ChildHandle = ArticyRefPropertyHandle->GetChildHandle(ChildIndex).ToSharedRef();
		IDetailPropertyRow& Row = ChildBuilder.AddProperty(ChildHandle);

		// disable the Id property here so that the user can't manipulate the ArticyID directly
		// UProperty is not set to ReadOnly due to needing to be editable to access "SetValue" functions from the IPropertyHandle system
		if(ChildHandle->GetPropertyDisplayName().EqualTo(FText::FromString(TEXT("Id"))))
		{
			Row.IsEnabled(false);
		}
	}
}

FArticyRef* FArticyRefCustomization::RetrieveArticyRef(IPropertyHandle* ArticyRefHandle)
{
	FArticyRef* ArticyRef = nullptr;
	void* ArticyRefAddress;
	ArticyRefHandle->GetValueData(ArticyRefAddress);
	ArticyRef = static_cast<FArticyRef*>(ArticyRefAddress);
	return ArticyRef;
}

UClass* FArticyRefCustomization::GetClassRestriction() const
{
	if (ClassRestriction)
	{
		return ClassRestriction;
	}

	return UArticyObject::StaticClass();
}

FText FArticyRefCustomization::GetChosenClassName() const
{
	if (ClassRestriction) {
		return FText::FromString(ClassRestriction->GetName());
	}

	return FText::FromString("None");
}

void FArticyRefCustomization::OnClassPicked(UClass* InChosenClass)
{
	ClassRestriction = InChosenClass;
	ClassRestrictionButton->SetIsOpen(false, false);
}

TSharedRef<SWidget> FArticyRefCustomization::CreateClassPicker()
{
	FClassViewerInitializationOptions ClassViewerConfig;
	ClassViewerConfig.DisplayMode = EClassViewerDisplayMode::TreeView;
	ClassViewerConfig.bAllowViewOptions = true;
	ClassViewerConfig.ClassFilter = MakeShareable(new FArticyRefClassFilter);
	return FModuleManager::LoadModuleChecked<FClassViewerModule>("ClassViewer").CreateClassViewer(ClassViewerConfig, FOnClassPicked::CreateRaw(this, &FArticyRefCustomization::OnClassPicked));
}

UClass* FArticyRefCustomization::GetClassRestrictionMetaData() const
{
	UClass* Restriction = nullptr;

	if(HasClassRestrictionMetaData())
	{
		const FString ArticyClassRestriction = ArticyRefPropertyHandle->GetProperty()->GetMetaData(TEXT("ArticyClassRestriction"));

		auto FullClassName = FString::Printf(TEXT("Class'/Script/%s.%s'"), TEXT("ArticyRuntime"), *ArticyClassRestriction);
		Restriction = ConstructorHelpersInternal::FindOrLoadClass(FullClassName, UArticyObject::StaticClass());

		// the class name can be in the ArticyRuntime module or in the project module. If it wasn't found in ArticyRuntime, check the project module
		if(Restriction == nullptr)
		{
			FullClassName = FString::Printf(TEXT("Class'/Script/%s.%s'"), FApp::GetProjectName(), *ArticyClassRestriction);
			Restriction = ConstructorHelpersInternal::FindOrLoadClass(FullClassName, UArticyObject::StaticClass());
		}
	}

	return Restriction;
}

bool FArticyRefCustomization::HasClassRestrictionMetaData() const
{
	return ArticyRefPropertyHandle->GetProperty()->HasMetaData(TEXT("ArticyClassRestriction"));
}

FArticyId FArticyRefCustomization::GetIdFromValueString(FString SourceString)
{
	int32 Low, High = 0;
	const bool bSuccess = FParse::Value(*SourceString, TEXT("Low="), Low) && FParse::Value(*SourceString, TEXT("High="), High);

	FArticyId Id;
	Id.High = High;
	Id.Low = Low;
	return Id;
}
<commit_msg>Add support for MetaData on Arrays of ArticyRefs.<commit_after>//
// Copyright (c) articy Software GmbH & Co. KG. All rights reserved.
//

#include "Customizations/ArticyRefCustomization.h"
#include "IDetailChildrenBuilder.h"
#include "DetailWidgetRow.h"
#include "Widgets/SWidget.h"
#include "Modules/ModuleManager.h"
#include "IDetailPropertyRow.h"
#include "Delegates/Delegate.h"
#include "ArticyObject.h"
#include "ArticyRef.h"
#include "ClassViewerModule.h"
#include "UObject/ConstructorHelpers.h"

TSharedRef<IPropertyTypeCustomization> FArticyRefCustomization::MakeInstance()
{
	return MakeShareable(new FArticyRefCustomization());
}

void FArticyRefCustomization::CustomizeHeader(TSharedRef<IPropertyHandle> PropertyHandle, FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& CustomizationUtils)
{
	ArticyRefPropertyHandle = PropertyHandle;

	// update the reference upon selecting the ref; this only serves cosmetic purposes. The underlying Id will not be changed
	FArticyRef* ArticyRef = RetrieveArticyRef(ArticyRefPropertyHandle.Get());

	UArticyObject* SelectedObject = UArticyObject::FindAsset(ArticyRef->GetId());

	// attempt to set the class restriction via meta data (cpp means that the programmer has mandated a specific type)
	ClassRestriction = GetClassRestrictionMetaData();

	// if there is no meta data class restriction,
	if (ClassRestriction == nullptr && SelectedObject)
	{
		ClassRestriction = SelectedObject->UObject::GetClass();
	}

	if (ClassRestriction == nullptr)
	{
		ClassRestriction = UArticyObject::StaticClass();
	}

	ArticyRefProperty = SNew(SArticyRefProperty, ArticyRefPropertyHandle.Get())
		.ClassRestriction(this, &FArticyRefCustomization::GetClassRestriction);

	HeaderRow.NameContent()
	[
		ArticyRefPropertyHandle->CreatePropertyNameWidget()
	]
	.ValueContent()
	.MinDesiredWidth(150)
	[
		ArticyRefProperty.ToSharedRef()
	];
}

void FArticyRefCustomization::CustomizeChildren(TSharedRef<IPropertyHandle> PropertyHandle, IDetailChildrenBuilder& ChildBuilder, IPropertyTypeCustomizationUtils& CustomizationUtils)
{
	ClassRestrictionButton =
		SNew(SComboButton)
		.OnGetMenuContent(this, &FArticyRefCustomization::CreateClassPicker)
		.IsEnabled_Lambda([this]() -> bool
	{
		return !HasClassRestrictionMetaData();
	})
		.ContentPadding(2.f)
		.ButtonContent()
		[
			SNew(STextBlock)
			.Text(this, &FArticyRefCustomization::GetChosenClassName)
		];

	ChildBuilder.AddCustomRow(FText::FromString("Class Restriction"))
		.NameContent()
		[
			SNew(SHorizontalBox)
			+ SHorizontalBox::Slot()
			.Padding(FMargin(0, 1, 0, 1))
			.FillWidth(1)
			[
				SNew(SBorder)
				.Padding(FMargin(0.0f, 2.0f))
				.VAlign(VAlign_Center)
				[
					SNew(STextBlock)
					.Text(FText::FromString("Class Restriction"))
				]
			]
		]
		.ValueContent()
		.MinDesiredWidth(150.f)
		.MaxDesiredWidth(250.f)
		[
			ClassRestrictionButton.ToSharedRef()
		];

	uint32 NumChildren;
	ArticyRefPropertyHandle->GetNumChildren(NumChildren);

	// restore all default editor property widgets
	for (uint32 ChildIndex = 0; ChildIndex < NumChildren; ++ChildIndex)
	{
		const TSharedRef< IPropertyHandle > ChildHandle = ArticyRefPropertyHandle->GetChildHandle(ChildIndex).ToSharedRef();
		IDetailPropertyRow& Row = ChildBuilder.AddProperty(ChildHandle);

		// disable the Id property here so that the user can't manipulate the ArticyID directly
		// UProperty is not set to ReadOnly due to needing to be editable to access "SetValue" functions from the IPropertyHandle system
		if(ChildHandle->GetPropertyDisplayName().EqualTo(FText::FromString(TEXT("Id"))))
		{
			Row.IsEnabled(false);
		}
	}
}

FArticyRef* FArticyRefCustomization::RetrieveArticyRef(IPropertyHandle* ArticyRefHandle)
{
	FArticyRef* ArticyRef = nullptr;
	void* ArticyRefAddress;
	ArticyRefHandle->GetValueData(ArticyRefAddress);
	ArticyRef = static_cast<FArticyRef*>(ArticyRefAddress);
	return ArticyRef;
}

UClass* FArticyRefCustomization::GetClassRestriction() const
{
	if (ClassRestriction)
	{
		return ClassRestriction;
	}

	return UArticyObject::StaticClass();
}

FText FArticyRefCustomization::GetChosenClassName() const
{
	if (ClassRestriction) {
		return FText::FromString(ClassRestriction->GetName());
	}

	return FText::FromString("None");
}

void FArticyRefCustomization::OnClassPicked(UClass* InChosenClass)
{
	ClassRestriction = InChosenClass;
	ClassRestrictionButton->SetIsOpen(false, false);
}

TSharedRef<SWidget> FArticyRefCustomization::CreateClassPicker()
{
	FClassViewerInitializationOptions ClassViewerConfig;
	ClassViewerConfig.DisplayMode = EClassViewerDisplayMode::TreeView;
	ClassViewerConfig.bAllowViewOptions = true;
	ClassViewerConfig.ClassFilter = MakeShareable(new FArticyRefClassFilter);
	return FModuleManager::LoadModuleChecked<FClassViewerModule>("ClassViewer").CreateClassViewer(ClassViewerConfig, FOnClassPicked::CreateRaw(this, &FArticyRefCustomization::OnClassPicked));
}

UClass* FArticyRefCustomization::GetClassRestrictionMetaData() const
{
	UClass* Restriction = nullptr;

	if(HasClassRestrictionMetaData())
	{
		const FString ArticyClassRestriction = ArticyRefPropertyHandle->GetMetaData(TEXT("ArticyClassRestriction"));

		auto FullClassName = FString::Printf(TEXT("Class'/Script/%s.%s'"), TEXT("ArticyRuntime"), *ArticyClassRestriction);
		Restriction = ConstructorHelpersInternal::FindOrLoadClass(FullClassName, UArticyObject::StaticClass());

		// the class name can be in the ArticyRuntime module or in the project module. If it wasn't found in ArticyRuntime, check the project module
		if(Restriction == nullptr)
		{
			FullClassName = FString::Printf(TEXT("Class'/Script/%s.%s'"), FApp::GetProjectName(), *ArticyClassRestriction);
			Restriction = ConstructorHelpersInternal::FindOrLoadClass(FullClassName, UArticyObject::StaticClass());
		}
	}

	return Restriction;
}

bool FArticyRefCustomization::HasClassRestrictionMetaData() const
{
	return ArticyRefPropertyHandle->HasMetaData(TEXT("ArticyClassRestriction"));
}

FArticyId FArticyRefCustomization::GetIdFromValueString(FString SourceString)
{
	int32 Low, High = 0;
	const bool bSuccess = FParse::Value(*SourceString, TEXT("Low="), Low) && FParse::Value(*SourceString, TEXT("High="), High);

	FArticyId Id;
	Id.High = High;
	Id.Low = Low;
	return Id;
}
<|endoftext|>