<commit_before>/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.

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 "tensorflow/core/profiler/convert/op_stats_to_overview_page.h"

#include <algorithm>
#include <utility>

#include "google/protobuf/any.pb.h"
#include "absl/strings/str_format.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/platform/protobuf.h"
#include "tensorflow/core/platform/types.h"
#include "tensorflow/core/profiler/convert/op_metrics_to_record.h"
#include "tensorflow/core/profiler/convert/op_stats_to_input_pipeline_analysis.h"
#include "tensorflow/core/profiler/protobuf/hardware_types.pb.h"
#include "tensorflow/core/profiler/protobuf/input_pipeline.pb.h"
#include "tensorflow/core/profiler/protobuf/op_metrics.pb.h"
#include "tensorflow/core/profiler/protobuf/op_stats.pb.h"
#include "tensorflow/core/profiler/protobuf/overview_page.pb.h"
#include "tensorflow/core/profiler/utils/math_utils.h"
#include "tensorflow/core/profiler/utils/op_metrics_db_utils.h"
#include "tensorflow/core/profiler/utils/time_utils.h"

namespace tensorflow {
namespace profiler {

namespace {

// If the use of low-precision ops is less than this percentage threshold, a
// statement of suggestion will be made.
constexpr double kLowPrecisionPercentThreshold = 10;

OverviewPageTip MakeOverviewPageTip(const string& text) {
  OverviewPageTip tip;
  tip.set_link(text);
  return tip;
}

string AnchorElement(const string& url, const string& text) {
  return absl::StrCat("", text, "");
}

// Makes a recommendation for looking up a document.
// doc_url is expected to be already be escaped suitably for use in an HTML
// attribute.
OverviewPageTip MakeOverviewPageTipDocLink(const string& doc_url,
                                           const string& text) {
  OverviewPageTip tip;
  tip.set_link(AnchorElement(doc_url, text));
  return tip;
}

void ComputeHostTips(OverviewPageRecommendation* re) {
  *re->add_host_tips() = MakeOverviewPageTip(
      "input_pipeline_analyzer (especially Section 3 for the breakdown of "
      "input operations on the Host)");
  *re->add_host_tips() = MakeOverviewPageTip(
      "trace_viewer (look at the activities on the timeline of each Host "
      "Thread near the bottom of the trace view)");
}

void ComputeDeviceTips(HardwareType hardware_type,
                       OverviewPageRecommendation* re) {
  const string& device_name = HardwareType_Name(hardware_type);
  string timeline_name =
      (hardware_type == tensorflow::profiler::TPU) ? "TPU core" : device_name;
  *re->add_device_tips() = MakeOverviewPageTip(absl::StrCat(
      "op_profile (identify the time-consuming operations executed on the ",
      device_name, ")"));
  *re->add_device_tips() = MakeOverviewPageTip(absl::StrCat(
      "trace_viewer (look at the activities on the timeline of each ",
      timeline_name, " in the trace view)"));
}

void ComputeFaqTips(OverviewPageRecommendation* re) {
  *re->add_faq_tips() = MakeOverviewPageTip("Refer to the Cloud tools FAQ");
}

void ComputeDocumentationTips(OverviewPageRecommendation* re) {
  *re->add_documentation_tips() = MakeOverviewPageTipDocLink(
      "https://www.tensorflow.org/guide/"
      "data_performance",
      "Better performance with the tf.data API");
}

std::string GeneratePrecisionStatement(const PrecisionStats& precision_stats) {
  uint64 total_compute_ps =
      precision_stats.compute_16bit_ps() + precision_stats.compute_32bit_ps();
  if (total_compute_ps > 0) {
    double percent_16bit =
        (100.0 * precision_stats.compute_16bit_ps()) / total_compute_ps;
    if (percent_16bit < kLowPrecisionPercentThreshold) {
      return absl::StrCat(
          "Only ", absl::StrFormat("%.1lf", percent_16bit),
          "% of device computation is 16 bit. So you might want to replace "
          "more 32-bit Ops by 16-bit Ops to improve performance (if the "
          "reduced accuracy is acceptable).");
    }
  }
  return "";
}

}  // namespace

void SetCommonRecommendation(const string& input_classification,
                             const string& input_statement,
                             HardwareType hardware_type,
                             OverviewPageRecommendation* re) {
  re->set_bottleneck(input_classification);
  re->set_statement(input_statement);
  ComputeHostTips(re);
  ComputeDeviceTips(hardware_type, re);
  ComputeDocumentationTips(re);
  ComputeFaqTips(re);
}

OverviewPageRecommendation ComputeGenericRecommendation(
    const BottleneckAnalysis& bottleneck,
    const PrecisionStats& precision_stats) {
  OverviewPageRecommendation re;
  GenericRecommendation generic;
  generic.set_kernel_launch_bottleneck(
      bottleneck.kernel_launch_classification());
  generic.set_kernel_launch_statement(bottleneck.kernel_launch_statement());
  generic.set_all_other_bottleneck(bottleneck.all_other_classification());
  generic.set_all_other_statement(bottleneck.all_other_statement());
  generic.set_precision_statement(GeneratePrecisionStatement(precision_stats));
  re.mutable_recommendation()->PackFrom(generic);
  return re;
}

OverviewPageAnalysis ComputeAnalysisResult(const OpStats& op_stats) {
  OverviewPageAnalysis analysis;
  OpMetricsDb metrics_db = CreateTfMetricsDbFromHloMetricsDb(
      op_stats.device_op_metrics_db(), /*with_idle=*/false);
  uint64 total_device_time_ps = metrics_db.total_time_ps();
  constexpr int kNumTopOpsShown = 10;
  double device_cumulative_fraction = 0.0;
  for (const OpMetrics* metrics :
       SortedOpMetricsDb(metrics_db, kNumTopOpsShown)) {
    OverviewTfOp* op = analysis.add_top_device_ops();
    op->set_name(metrics->name());
    op->set_category(metrics->category());
    op->set_self_time_fraction(
        SafeDivide(metrics->self_time_ps(), total_device_time_ps));
    device_cumulative_fraction += op->self_time_fraction();
    op->set_cumulative_time_fraction(device_cumulative_fraction);
    op->set_flop_rate(
        SafeDivide(metrics->flops(), PicosToNanos(metrics->time_ps())));
  }
  SetRemarks(op_stats, &analysis);
  uint64 total_device_compute_ps =
      op_stats.device_op_metrics_db().precision_stats().compute_16bit_ps() +
      op_stats.device_op_metrics_db().precision_stats().compute_32bit_ps();
  analysis.set_device_compute_16bit_percent(
      100.0 *
      SafeDivide(
          op_stats.device_op_metrics_db().precision_stats().compute_16bit_ps(),
          total_device_compute_ps));
  analysis.set_device_compute_32bit_percent(
      100.0 *
      SafeDivide(
          op_stats.device_op_metrics_db().precision_stats().compute_32bit_ps(),
          total_device_compute_ps));
  return analysis;
}

// Converts from HostIndependentJobInfo to OverviewPageHostIndependentJobInfo.
OverviewPageHostIndependentJobInfo ToOverviewPageHostIndependentJobInfo(
    const HostIndependentJobInfoResult& host_independent_job_info) {
  OverviewPageHostIndependentJobInfo result;
  result.set_change_list(host_independent_job_info.change_list());
  result.set_build_time(host_independent_job_info.build_time());
  result.set_build_target(host_independent_job_info.build_target());
  result.set_profile_duration_ms(
      host_independent_job_info.profile_duration_ms());
  return result;
}

// Converts from HostDependentJobInfo to OverviewPageHostDependentJobInfo.
OverviewPageHostDependentJobInfo ToOverviewPageHostDependentJobInfo(
    const HostDependentJobInfoResult& host_dependent_job_info) {
  OverviewPageHostDependentJobInfo result;
  result.set_host_id(host_dependent_job_info.host_id());
  result.set_command_line(host_dependent_job_info.command_line());
  result.set_start_time(host_dependent_job_info.start_time());
  result.set_bns_address(host_dependent_job_info.bns_address());
  result.set_profile_time_ns(host_dependent_job_info.profile_time_ns());
  return result;
}

OverviewPageRunEnvironment ComputeRunEnvironment(
    const RunEnvironment& run_environment) {
  OverviewPageRunEnvironment re;
  re.set_host_count(run_environment.host_count());
  re.set_task_count(run_environment.task_count());
  re.set_device_type(run_environment.device_type());
  re.set_device_core_count(run_environment.device_core_count());
  re.set_per_core_batch_size(run_environment.per_core_batch_size());
  re.set_replica_count(run_environment.replica_count());
  re.set_num_cores_per_replica(run_environment.num_cores_per_replica());
  *re.mutable_host_independent_job_info() =
      ToOverviewPageHostIndependentJobInfo(
          run_environment.host_independent_job_info());
  for (const auto& host_dependent_job_info :
       run_environment.host_dependent_job_info()) {
    *re.add_host_dependent_job_info() =
        ToOverviewPageHostDependentJobInfo(host_dependent_job_info);
  }
  return re;
}

OverviewPage ConvertOpStatsToOverviewPage(const OpStats& op_stats,
                                          HardwareType hardware_type) {
  OverviewPageAnalysis analysis = ComputeAnalysisResult(op_stats);
  InputPipelineAnalysisResult input_analysis =
      ConvertOpStatsToInputPipelineAnalysis(op_stats, hardware_type);
  BottleneckAnalysis bottleneck =
      ComputeBottleneckAnalysis(input_analysis.step_details());
  OverviewPageRecommendation recommendation = ComputeGenericRecommendation(
      bottleneck, op_stats.device_op_metrics_db().precision_stats());
  SetCommonRecommendation(bottleneck.input_classification(),
                          bottleneck.input_statement(), hardware_type,
                          &recommendation);

  OverviewPage overview_page;
  *overview_page.mutable_run_environment() =
      ComputeRunEnvironment(op_stats.run_environment());
  *overview_page.mutable_analysis() = analysis;
  *overview_page.mutable_input_analysis() = input_analysis;
  *overview_page.mutable_recommendation() = recommendation;
  return overview_page;
}

void SetRemarks(const OpStats& op_stats, OverviewPageAnalysis* analysis) {
  if (op_stats.step_db().step_sequence_size() == 0) {
    analysis->set_remark_text(
        "WARNING: No step markers observed and hence the step time is actually "
        "unknown. This may happen if your profiling duration is shorter than "
        "the step time. In that case, you may try to profile longer.");
    analysis->set_remark_color("red");
  } else {
    analysis->set_remark_text("");
    analysis->set_remark_color("black");
  }
}

}  // namespace profiler
}  // namespace tensorflow
<commit_msg>Fix some recommendations in the Profiler Overview Page.<commit_after>/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.

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 "tensorflow/core/profiler/convert/op_stats_to_overview_page.h"

#include <algorithm>
#include <utility>

#include "google/protobuf/any.pb.h"
#include "absl/strings/str_format.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/platform/protobuf.h"
#include "tensorflow/core/platform/types.h"
#include "tensorflow/core/profiler/convert/op_metrics_to_record.h"
#include "tensorflow/core/profiler/convert/op_stats_to_input_pipeline_analysis.h"
#include "tensorflow/core/profiler/protobuf/hardware_types.pb.h"
#include "tensorflow/core/profiler/protobuf/input_pipeline.pb.h"
#include "tensorflow/core/profiler/protobuf/op_metrics.pb.h"
#include "tensorflow/core/profiler/protobuf/op_stats.pb.h"
#include "tensorflow/core/profiler/protobuf/overview_page.pb.h"
#include "tensorflow/core/profiler/utils/math_utils.h"
#include "tensorflow/core/profiler/utils/op_metrics_db_utils.h"
#include "tensorflow/core/profiler/utils/time_utils.h"

namespace tensorflow {
namespace profiler {

namespace {

// If the use of low-precision ops is less than this percentage threshold, a
// statement of suggestion will be made.
constexpr double kLowPrecisionPercentThreshold = 10;

OverviewPageTip MakeOverviewPageTip(const string& text) {
  OverviewPageTip tip;
  tip.set_link(text);
  return tip;
}

string AnchorElement(const string& url, const string& text) {
  return absl::StrCat("", text, "");
}

// Makes a recommendation for looking up a document.
// doc_url is expected to be already be escaped suitably for use in an HTML
// attribute.
OverviewPageTip MakeOverviewPageTipDocLink(const string& doc_url,
                                           const string& text) {
  OverviewPageTip tip;
  tip.set_link(AnchorElement(doc_url, text));
  return tip;
}

void ComputeHostTips(OverviewPageRecommendation* re) {
  *re->add_host_tips() = MakeOverviewPageTip(
      "input_pipeline_analyzer (especially Section 3 for the breakdown of "
      "input operations on the Host)");
  *re->add_host_tips() = MakeOverviewPageTip(
      "trace_viewer (look at the activities on the timeline of each Host "
      "Thread near the bottom of the trace view)");
}

void ComputeDeviceTips(HardwareType hardware_type,
                       OverviewPageRecommendation* re) {
  const string& device_name = HardwareType_Name(hardware_type);
  string timeline_name =
      (hardware_type == tensorflow::profiler::TPU) ? "TPU core" : device_name;
  string op_stats_toolname = (hardware_type == tensorflow::profiler::TPU)
                                 ? "op_profile"
                                 : "tensorflow_stats";
  *re->add_device_tips() = MakeOverviewPageTip(
      absl::StrCat(op_stats_toolname,
                   " (identify the time-consuming operations "
                   "executed on the ",
                   device_name, ")"));
  *re->add_device_tips() = MakeOverviewPageTip(absl::StrCat(
      "trace_viewer (look at the activities on the timeline of each ",
      timeline_name, " in the trace view)"));
}

void ComputeFaqTips(OverviewPageRecommendation* re) {
  *re->add_faq_tips() = MakeOverviewPageTip("Refer to the TF2 Profiler FAQ");
}

void ComputeDocumentationTips(OverviewPageRecommendation* re) {
  *re->add_documentation_tips() = MakeOverviewPageTipDocLink(
      "https://www.tensorflow.org/guide/"
      "data_performance",
      "Better performance with the tf.data API");
}

std::string GeneratePrecisionStatement(const PrecisionStats& precision_stats) {
  uint64 total_compute_ps =
      precision_stats.compute_16bit_ps() + precision_stats.compute_32bit_ps();
  if (total_compute_ps > 0) {
    double percent_16bit =
        (100.0 * precision_stats.compute_16bit_ps()) / total_compute_ps;
    if (percent_16bit < kLowPrecisionPercentThreshold) {
      return absl::StrCat(
          "Only ", absl::StrFormat("%.1lf", percent_16bit),
          "% of device computation is 16 bit. So you might want to replace "
          "more 32-bit Ops by 16-bit Ops to improve performance (if the "
          "reduced accuracy is acceptable).");
    }
  }
  return "";
}

}  // namespace

void SetCommonRecommendation(const string& input_classification,
                             const string& input_statement,
                             HardwareType hardware_type,
                             OverviewPageRecommendation* re) {
  re->set_bottleneck(input_classification);
  re->set_statement(input_statement);
  ComputeHostTips(re);
  ComputeDeviceTips(hardware_type, re);
  ComputeDocumentationTips(re);
  ComputeFaqTips(re);
}

OverviewPageRecommendation ComputeGenericRecommendation(
    const BottleneckAnalysis& bottleneck,
    const PrecisionStats& precision_stats) {
  OverviewPageRecommendation re;
  GenericRecommendation generic;
  generic.set_kernel_launch_bottleneck(
      bottleneck.kernel_launch_classification());
  generic.set_kernel_launch_statement(bottleneck.kernel_launch_statement());
  generic.set_all_other_bottleneck(bottleneck.all_other_classification());
  generic.set_all_other_statement(bottleneck.all_other_statement());
  generic.set_precision_statement(GeneratePrecisionStatement(precision_stats));
  re.mutable_recommendation()->PackFrom(generic);
  return re;
}

OverviewPageAnalysis ComputeAnalysisResult(const OpStats& op_stats) {
  OverviewPageAnalysis analysis;
  OpMetricsDb metrics_db = CreateTfMetricsDbFromHloMetricsDb(
      op_stats.device_op_metrics_db(), /*with_idle=*/false);
  uint64 total_device_time_ps = metrics_db.total_time_ps();
  constexpr int kNumTopOpsShown = 10;
  double device_cumulative_fraction = 0.0;
  for (const OpMetrics* metrics :
       SortedOpMetricsDb(metrics_db, kNumTopOpsShown)) {
    OverviewTfOp* op = analysis.add_top_device_ops();
    op->set_name(metrics->name());
    op->set_category(metrics->category());
    op->set_self_time_fraction(
        SafeDivide(metrics->self_time_ps(), total_device_time_ps));
    device_cumulative_fraction += op->self_time_fraction();
    op->set_cumulative_time_fraction(device_cumulative_fraction);
    op->set_flop_rate(
        SafeDivide(metrics->flops(), PicosToNanos(metrics->time_ps())));
  }
  SetRemarks(op_stats, &analysis);
  uint64 total_device_compute_ps =
      op_stats.device_op_metrics_db().precision_stats().compute_16bit_ps() +
      op_stats.device_op_metrics_db().precision_stats().compute_32bit_ps();
  analysis.set_device_compute_16bit_percent(
      100.0 *
      SafeDivide(
          op_stats.device_op_metrics_db().precision_stats().compute_16bit_ps(),
          total_device_compute_ps));
  analysis.set_device_compute_32bit_percent(
      100.0 *
      SafeDivide(
          op_stats.device_op_metrics_db().precision_stats().compute_32bit_ps(),
          total_device_compute_ps));
  return analysis;
}

// Converts from HostIndependentJobInfo to OverviewPageHostIndependentJobInfo.
OverviewPageHostIndependentJobInfo ToOverviewPageHostIndependentJobInfo(
    const HostIndependentJobInfoResult& host_independent_job_info) {
  OverviewPageHostIndependentJobInfo result;
  result.set_change_list(host_independent_job_info.change_list());
  result.set_build_time(host_independent_job_info.build_time());
  result.set_build_target(host_independent_job_info.build_target());
  result.set_profile_duration_ms(
      host_independent_job_info.profile_duration_ms());
  return result;
}

// Converts from HostDependentJobInfo to OverviewPageHostDependentJobInfo.
OverviewPageHostDependentJobInfo ToOverviewPageHostDependentJobInfo(
    const HostDependentJobInfoResult& host_dependent_job_info) {
  OverviewPageHostDependentJobInfo result;
  result.set_host_id(host_dependent_job_info.host_id());
  result.set_command_line(host_dependent_job_info.command_line());
  result.set_start_time(host_dependent_job_info.start_time());
  result.set_bns_address(host_dependent_job_info.bns_address());
  result.set_profile_time_ns(host_dependent_job_info.profile_time_ns());
  return result;
}

OverviewPageRunEnvironment ComputeRunEnvironment(
    const RunEnvironment& run_environment) {
  OverviewPageRunEnvironment re;
  re.set_host_count(run_environment.host_count());
  re.set_task_count(run_environment.task_count());
  re.set_device_type(run_environment.device_type());
  re.set_device_core_count(run_environment.device_core_count());
  re.set_per_core_batch_size(run_environment.per_core_batch_size());
  re.set_replica_count(run_environment.replica_count());
  re.set_num_cores_per_replica(run_environment.num_cores_per_replica());
  *re.mutable_host_independent_job_info() =
      ToOverviewPageHostIndependentJobInfo(
          run_environment.host_independent_job_info());
  for (const auto& host_dependent_job_info :
       run_environment.host_dependent_job_info()) {
    *re.add_host_dependent_job_info() =
        ToOverviewPageHostDependentJobInfo(host_dependent_job_info);
  }
  return re;
}

OverviewPage ConvertOpStatsToOverviewPage(const OpStats& op_stats,
                                          HardwareType hardware_type) {
  OverviewPageAnalysis analysis = ComputeAnalysisResult(op_stats);
  InputPipelineAnalysisResult input_analysis =
      ConvertOpStatsToInputPipelineAnalysis(op_stats, hardware_type);
  BottleneckAnalysis bottleneck =
      ComputeBottleneckAnalysis(input_analysis.step_details());
  OverviewPageRecommendation recommendation = ComputeGenericRecommendation(
      bottleneck, op_stats.device_op_metrics_db().precision_stats());
  SetCommonRecommendation(bottleneck.input_classification(),
                          bottleneck.input_statement(), hardware_type,
                          &recommendation);

  OverviewPage overview_page;
  *overview_page.mutable_run_environment() =
      ComputeRunEnvironment(op_stats.run_environment());
  *overview_page.mutable_analysis() = analysis;
  *overview_page.mutable_input_analysis() = input_analysis;
  *overview_page.mutable_recommendation() = recommendation;
  return overview_page;
}

void SetRemarks(const OpStats& op_stats, OverviewPageAnalysis* analysis) {
  if (op_stats.step_db().step_sequence_size() == 0) {
    analysis->set_remark_text(
        "WARNING: No step markers observed and hence the step time is actually "
        "unknown. This may happen if your profiling duration is shorter than "
        "the step time. In that case, you may try to profile longer.");
    analysis->set_remark_color("red");
  } else {
    analysis->set_remark_text("");
    analysis->set_remark_color("black");
  }
}

}  // namespace profiler
}  // namespace tensorflow
<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2006 Torus Knot Software Ltd
Also see acknowledgements in Readme.html

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.

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 Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.

You may alternatively use this source under the terms of a specific version of
the OGRE Unrestricted License provided you have obtained such a license from
Torus Knot Software Ltd.
-----------------------------------------------------------------------------
*/
#include "OgreStableHeaders.h"
#include "OgreViewport.h"

#include "OgreLogManager.h"
#include "OgreRenderTarget.h"
#include "OgreCamera.h"
#include "OgreMath.h"
#include "OgreRoot.h"
#include "OgreMaterialManager.h"

namespace Ogre {
    //---------------------------------------------------------------------
    Viewport::Viewport(Camera* cam, RenderTarget* target, Real left, Real top, Real width, Real height, int ZOrder)
        : mCamera(cam)
        , mTarget(target)
        , mRelLeft(left)
        , mRelTop(top)
        , mRelWidth(width)
        , mRelHeight(height)
        // Actual dimensions will update later
        , mZOrder(ZOrder)
        , mBackColour(ColourValue::Black)
        , mClearEveryFrame(true)
		, mClearBuffers(FBT_COLOUR | FBT_DEPTH)
        , mUpdated(false)
        , mShowOverlays(true)
        , mShowSkies(true)
		, mShowShadows(true)
		, mVisibilityMask(0xFFFFFFFF)
		, mRQSequence(0)
		, mMaterialSchemeName(MaterialManager::DEFAULT_SCHEME_NAME)
    {

		LogManager::getSingleton().stream(LML_TRIVIAL)
			<< "Creating viewport on target '" << target->getName() << "'"
			<< ", rendering from camera '" << (cam != 0 ? cam->getName() : "NULL") << "'"
			<< ", relative dimensions "	<< std::ios::fixed << std::setprecision(2)
			<< "L: " << left << " T: " << top << " W: " << width << " H: " << height
			<< " ZOrder: " << ZOrder;

        // Calculate actual dimensions
        _updateDimensions();

        // notify camera
        if(cam) cam->_notifyViewport(this);
    }
    //---------------------------------------------------------------------
    Viewport::~Viewport()
    {

    }
    //---------------------------------------------------------------------
    bool Viewport::_isUpdated(void) const
    {
        return mUpdated;
    }
    //---------------------------------------------------------------------
    void Viewport::_clearUpdatedFlag(void)
    {
        mUpdated = false;
    }
    //---------------------------------------------------------------------
    void Viewport::_updateDimensions(void)
    {
        Real height = (Real) mTarget->getHeight();
        Real width = (Real) mTarget->getWidth();

        mActLeft = (int) (mRelLeft * width);
        mActTop = (int) (mRelTop * height);
        mActWidth = (int) (mRelWidth * width);
        mActHeight = (int) (mRelHeight * height);

        // This will check if  the cameras getAutoAspectRation() property is set.
        // If it's true its aspect ratio is fit to the current viewport
        // If it's false the camera remains unchanged.
        // This allows cameras to be used to render to many viewports,
        // which can have their own dimensions and aspect ratios.

        if (mCamera && mCamera->getAutoAspectRatio())
        {
            mCamera->setAspectRatio((Real) mActWidth / (Real) mActHeight);
        }

		LogManager::getSingleton().stream(LML_TRIVIAL)
			<< "Viewport for camera '" << (mCamera != 0 ? mCamera->getName() : "NULL") << "'"
			<< ", actual dimensions "	<< std::ios::fixed << std::setprecision(2)
			<< "L: " << mActLeft << " T: " << mActTop << " W: " << mActWidth << " H: " << mActHeight;

        mUpdated = true;
    }
	//---------------------------------------------------------------------
	int Viewport::getZOrder(void) const
	{
		return mZOrder;
	}
	//---------------------------------------------------------------------
    RenderTarget* Viewport::getTarget(void) const
    {
        return mTarget;
    }
    //---------------------------------------------------------------------
    Camera* Viewport::getCamera(void) const
    {
        return mCamera;
    }
    //---------------------------------------------------------------------
    Real Viewport::getLeft(void) const
    {
        return mRelLeft;
    }
    //---------------------------------------------------------------------
    Real Viewport::getTop(void) const
    {
        return mRelTop;
    }
    //---------------------------------------------------------------------
    Real Viewport::getWidth(void) const
    {
        return mRelWidth;
    }
    //---------------------------------------------------------------------
    Real Viewport::getHeight(void) const
    {
        return mRelHeight;
    }
    //---------------------------------------------------------------------
    int Viewport::getActualLeft(void) const
    {
        return mActLeft;
    }
    //---------------------------------------------------------------------
    int Viewport::getActualTop(void) const
    {
        return mActTop;
    }
    //---------------------------------------------------------------------
    int Viewport::getActualWidth(void) const
    {
        return mActWidth;
    }
    //---------------------------------------------------------------------
    int Viewport::getActualHeight(void) const
    {
        return mActHeight;
    }
    //---------------------------------------------------------------------
    void Viewport::setDimensions(Real left, Real top, Real width, Real height)
    {
        mRelLeft = left;
        mRelTop = top;
        mRelWidth = width;
        mRelHeight = height;
        _updateDimensions();
    }
    //---------------------------------------------------------------------
    void Viewport::update(void)
    {
        if (mCamera)
        {
            // Tell Camera to render into me
            mCamera->_renderScene(this, mShowOverlays);
        }
    }
    //---------------------------------------------------------------------
    void Viewport::setBackgroundColour(const ColourValue& colour)
    {
        mBackColour = colour;
    }
    //---------------------------------------------------------------------
    const ColourValue& Viewport::getBackgroundColour(void) const
    {
        return mBackColour;
    }
    //---------------------------------------------------------------------
    void Viewport::setClearEveryFrame(bool clear, unsigned int buffers)
    {
        mClearEveryFrame = clear;
		mClearBuffers = buffers;
    }
    //---------------------------------------------------------------------
    bool Viewport::getClearEveryFrame(void) const
    {
        return mClearEveryFrame;
    }
    //---------------------------------------------------------------------
    unsigned int Viewport::getClearBuffers(void) const
    {
        return mClearBuffers;
    }
    //---------------------------------------------------------------------
    void Viewport::getActualDimensions(int &left, int&top, int &width, int &height) const
    {
        left = mActLeft;
        top = mActTop;
        width = mActWidth;
        height = mActHeight;

    }
    //---------------------------------------------------------------------
    unsigned int Viewport::_getNumRenderedFaces(void) const
    {
		return mCamera ? mCamera->_getNumRenderedFaces() : 0;
    }
    //---------------------------------------------------------------------
    unsigned int Viewport::_getNumRenderedBatches(void) const
    {
		return mCamera ? mCamera->_getNumRenderedBatches() : 0;
    }
    //---------------------------------------------------------------------
    void Viewport::setCamera(Camera* cam)
    {
        mCamera = cam;
		if(cam) mCamera->_notifyViewport(this);
    }
    //---------------------------------------------------------------------
    void Viewport::setOverlaysEnabled(bool enabled)
    {
        mShowOverlays = enabled;
    }
    //---------------------------------------------------------------------
    bool Viewport::getOverlaysEnabled(void) const
    {
        return mShowOverlays;
    }
    //---------------------------------------------------------------------
    void Viewport::setSkiesEnabled(bool enabled)
    {
        mShowSkies = enabled;
    }
    //---------------------------------------------------------------------
    bool Viewport::getSkiesEnabled(void) const
    {
        return mShowSkies;
    }
    //---------------------------------------------------------------------
    void Viewport::setShadowsEnabled(bool enabled)
    {
        mShowShadows = enabled;
    }
    //---------------------------------------------------------------------
    bool Viewport::getShadowsEnabled(void) const
    {
        return mShowShadows;
    }
	//-----------------------------------------------------------------------
	void Viewport::setRenderQueueInvocationSequenceName(const String& sequenceName)
	{
		mRQSequenceName = sequenceName;
		if (mRQSequenceName.empty())
		{
			mRQSequence = 0;
		}
		else
		{
			mRQSequence =
				Root::getSingleton().getRenderQueueInvocationSequence(mRQSequenceName);
		}
	}
	//-----------------------------------------------------------------------
	const String& Viewport::getRenderQueueInvocationSequenceName(void) const
	{
		return mRQSequenceName;
	}
	//-----------------------------------------------------------------------
	RenderQueueInvocationSequence* Viewport::_getRenderQueueInvocationSequence(void)
	{
		return mRQSequence;
	}
	//-----------------------------------------------------------------------

}
<commit_msg>Patch 2500036 - make sure aspect ratio of camera is updated when camera newly assigned to a viewport<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2006 Torus Knot Software Ltd
Also see acknowledgements in Readme.html

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.

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 Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.

You may alternatively use this source under the terms of a specific version of
the OGRE Unrestricted License provided you have obtained such a license from
Torus Knot Software Ltd.
-----------------------------------------------------------------------------
*/
#include "OgreStableHeaders.h"
#include "OgreViewport.h"

#include "OgreLogManager.h"
#include "OgreRenderTarget.h"
#include "OgreCamera.h"
#include "OgreMath.h"
#include "OgreRoot.h"
#include "OgreMaterialManager.h"

namespace Ogre {
    //---------------------------------------------------------------------
    Viewport::Viewport(Camera* cam, RenderTarget* target, Real left, Real top, Real width, Real height, int ZOrder)
        : mCamera(cam)
        , mTarget(target)
        , mRelLeft(left)
        , mRelTop(top)
        , mRelWidth(width)
        , mRelHeight(height)
        // Actual dimensions will update later
        , mZOrder(ZOrder)
        , mBackColour(ColourValue::Black)
        , mClearEveryFrame(true)
		, mClearBuffers(FBT_COLOUR | FBT_DEPTH)
        , mUpdated(false)
        , mShowOverlays(true)
        , mShowSkies(true)
		, mShowShadows(true)
		, mVisibilityMask(0xFFFFFFFF)
		, mRQSequence(0)
		, mMaterialSchemeName(MaterialManager::DEFAULT_SCHEME_NAME)
    {

		LogManager::getSingleton().stream(LML_TRIVIAL)
			<< "Creating viewport on target '" << target->getName() << "'"
			<< ", rendering from camera '" << (cam != 0 ? cam->getName() : "NULL") << "'"
			<< ", relative dimensions "	<< std::ios::fixed << std::setprecision(2)
			<< "L: " << left << " T: " << top << " W: " << width << " H: " << height
			<< " ZOrder: " << ZOrder;

        // Calculate actual dimensions
        _updateDimensions();

        // notify camera
        if(cam) cam->_notifyViewport(this);
    }
    //---------------------------------------------------------------------
    Viewport::~Viewport()
    {

    }
    //---------------------------------------------------------------------
    bool Viewport::_isUpdated(void) const
    {
        return mUpdated;
    }
    //---------------------------------------------------------------------
    void Viewport::_clearUpdatedFlag(void)
    {
        mUpdated = false;
    }
    //---------------------------------------------------------------------
    void Viewport::_updateDimensions(void)
    {
        Real height = (Real) mTarget->getHeight();
        Real width = (Real) mTarget->getWidth();

        mActLeft = (int) (mRelLeft * width);
        mActTop = (int) (mRelTop * height);
        mActWidth = (int) (mRelWidth * width);
        mActHeight = (int) (mRelHeight * height);

        // This will check if  the cameras getAutoAspectRation() property is set.
        // If it's true its aspect ratio is fit to the current viewport
        // If it's false the camera remains unchanged.
        // This allows cameras to be used to render to many viewports,
        // which can have their own dimensions and aspect ratios.

        if (mCamera && mCamera->getAutoAspectRatio())
        {
            mCamera->setAspectRatio((Real) mActWidth / (Real) mActHeight);
        }

		LogManager::getSingleton().stream(LML_TRIVIAL)
			<< "Viewport for camera '" << (mCamera != 0 ? mCamera->getName() : "NULL") << "'"
			<< ", actual dimensions "	<< std::ios::fixed << std::setprecision(2)
			<< "L: " << mActLeft << " T: " << mActTop << " W: " << mActWidth << " H: " << mActHeight;

        mUpdated = true;
    }
	//---------------------------------------------------------------------
	int Viewport::getZOrder(void) const
	{
		return mZOrder;
	}
	//---------------------------------------------------------------------
    RenderTarget* Viewport::getTarget(void) const
    {
        return mTarget;
    }
    //---------------------------------------------------------------------
    Camera* Viewport::getCamera(void) const
    {
        return mCamera;
    }
    //---------------------------------------------------------------------
    Real Viewport::getLeft(void) const
    {
        return mRelLeft;
    }
    //---------------------------------------------------------------------
    Real Viewport::getTop(void) const
    {
        return mRelTop;
    }
    //---------------------------------------------------------------------
    Real Viewport::getWidth(void) const
    {
        return mRelWidth;
    }
    //---------------------------------------------------------------------
    Real Viewport::getHeight(void) const
    {
        return mRelHeight;
    }
    //---------------------------------------------------------------------
    int Viewport::getActualLeft(void) const
    {
        return mActLeft;
    }
    //---------------------------------------------------------------------
    int Viewport::getActualTop(void) const
    {
        return mActTop;
    }
    //---------------------------------------------------------------------
    int Viewport::getActualWidth(void) const
    {
        return mActWidth;
    }
    //---------------------------------------------------------------------
    int Viewport::getActualHeight(void) const
    {
        return mActHeight;
    }
    //---------------------------------------------------------------------
    void Viewport::setDimensions(Real left, Real top, Real width, Real height)
    {
        mRelLeft = left;
        mRelTop = top;
        mRelWidth = width;
        mRelHeight = height;
        _updateDimensions();
    }
    //---------------------------------------------------------------------
    void Viewport::update(void)
    {
        if (mCamera)
        {
            // Tell Camera to render into me
            mCamera->_renderScene(this, mShowOverlays);
        }
    }
    //---------------------------------------------------------------------
    void Viewport::setBackgroundColour(const ColourValue& colour)
    {
        mBackColour = colour;
    }
    //---------------------------------------------------------------------
    const ColourValue& Viewport::getBackgroundColour(void) const
    {
        return mBackColour;
    }
    //---------------------------------------------------------------------
    void Viewport::setClearEveryFrame(bool clear, unsigned int buffers)
    {
        mClearEveryFrame = clear;
		mClearBuffers = buffers;
    }
    //---------------------------------------------------------------------
    bool Viewport::getClearEveryFrame(void) const
    {
        return mClearEveryFrame;
    }
    //---------------------------------------------------------------------
    unsigned int Viewport::getClearBuffers(void) const
    {
        return mClearBuffers;
    }
    //---------------------------------------------------------------------
    void Viewport::getActualDimensions(int &left, int&top, int &width, int &height) const
    {
        left = mActLeft;
        top = mActTop;
        width = mActWidth;
        height = mActHeight;

    }
    //---------------------------------------------------------------------
    unsigned int Viewport::_getNumRenderedFaces(void) const
    {
		return mCamera ? mCamera->_getNumRenderedFaces() : 0;
    }
    //---------------------------------------------------------------------
    unsigned int Viewport::_getNumRenderedBatches(void) const
    {
		return mCamera ? mCamera->_getNumRenderedBatches() : 0;
    }
    //---------------------------------------------------------------------
    void Viewport::setCamera(Camera* cam)
    {
        mCamera = cam;
		_updateDimensions();
		if(cam) mCamera->_notifyViewport(this);
    }
    //---------------------------------------------------------------------
    void Viewport::setOverlaysEnabled(bool enabled)
    {
        mShowOverlays = enabled;
    }
    //---------------------------------------------------------------------
    bool Viewport::getOverlaysEnabled(void) const
    {
        return mShowOverlays;
    }
    //---------------------------------------------------------------------
    void Viewport::setSkiesEnabled(bool enabled)
    {
        mShowSkies = enabled;
    }
    //---------------------------------------------------------------------
    bool Viewport::getSkiesEnabled(void) const
    {
        return mShowSkies;
    }
    //---------------------------------------------------------------------
    void Viewport::setShadowsEnabled(bool enabled)
    {
        mShowShadows = enabled;
    }
    //---------------------------------------------------------------------
    bool Viewport::getShadowsEnabled(void) const
    {
        return mShowShadows;
    }
	//-----------------------------------------------------------------------
	void Viewport::setRenderQueueInvocationSequenceName(const String& sequenceName)
	{
		mRQSequenceName = sequenceName;
		if (mRQSequenceName.empty())
		{
			mRQSequence = 0;
		}
		else
		{
			mRQSequence =
				Root::getSingleton().getRenderQueueInvocationSequence(mRQSequenceName);
		}
	}
	//-----------------------------------------------------------------------
	const String& Viewport::getRenderQueueInvocationSequenceName(void) const
	{
		return mRQSequenceName;
	}
	//-----------------------------------------------------------------------
	RenderQueueInvocationSequence* Viewport::_getRenderQueueInvocationSequence(void)
	{
		return mRQSequence;
	}
	//-----------------------------------------------------------------------

}
<|endoftext|>


<commit_before>/**
*  Copyright (C) 2015 3D Repo Ltd
*
*  This program is free software: you can redistribute it and/or modify
*  it under the terms of the GNU Affero General Public License as
*  published by the Free Software Foundation, either version 3 of the
*  License, or (at your option) any later version.
*
*  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 Affero 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, see <http://www.gnu.org/licenses/>.
*/

#include <cstdlib>

#include <gtest/gtest.h>

#include <repo/core/model/bson/repo_node_metadata.h>
#include <repo/core/model/bson/repo_bson_builder.h>
#include <repo/core/model/bson/repo_bson_factory.h>

#include "../../../../repo_test_utils.h"

using namespace repo::core::model;

static MetadataNode makeRandomMetaNode()
{
	uint32_t nItems = rand() % 10 + 1;
	std::vector<std::string> keys, values;
	for (int i = 0; i < nItems; ++i)
	{
		keys.push_back(getRandomString(rand() % 10 + 1));
		values.push_back(getRandomString(rand() % 10 + 1));
	}
	return	RepoBSONFactory::makeMetaDataNode(keys, values);
}

/**
* Construct from mongo builder and mongo bson should give me the same bson
*/
TEST(MetaNodeTest, Constructor)
{
	MetadataNode empty;

	EXPECT_TRUE(empty.isEmpty());
	EXPECT_EQ(NodeType::METADATA, empty.getTypeAsEnum());

	auto repoBson = RepoBSON(BSON("test" << "blah" << "test2" << 2));

	auto fromRepoBSON = MetadataNode(repoBson);
	EXPECT_EQ(NodeType::METADATA, fromRepoBSON.getTypeAsEnum());
	EXPECT_EQ(fromRepoBSON.nFields(), repoBson.nFields());
	EXPECT_EQ(0, fromRepoBSON.getFileList().size());
}

TEST(MetaNodeTest, TypeTest)
{
	MetadataNode node;

	EXPECT_EQ(REPO_NODE_TYPE_METADATA, node.getType());
	EXPECT_EQ(NodeType::METADATA, node.getTypeAsEnum());
}

TEST(MetaNodeTest, PositionDependantTest)
{
	MetadataNode node;
	EXPECT_FALSE(node.positionDependant());
}

TEST(MetaNodeTest, SEqualTest)
{
	MetadataNode empty;
	EXPECT_TRUE(empty.sEqual(empty));

	auto metaNode = makeRandomMetaNode();
	auto metaNode2 = makeRandomMetaNode();

	EXPECT_TRUE(metaNode.sEqual(metaNode));
	EXPECT_FALSE(metaNode.sEqual(empty));
	EXPECT_FALSE(metaNode.sEqual(metaNode2));
}

TEST(MetaNodeTest, CloneAndAddMetadataTest)
{
	MetadataNode empty;

	auto metaNode = makeRandomMetaNode();
	auto metaNode2 = makeRandomMetaNode();

	auto meta1 = metaNode.getObjectField(REPO_NODE_LABEL_METADATA);
	auto meta2 = metaNode2.getObjectField(REPO_NODE_LABEL_METADATA);
	auto updatedMeta = empty.cloneAndAddMetadata(meta1);

	updatedMeta.sEqual(metaNode);

	auto updatedMeta2 = updatedMeta.cloneAndAddMetadata(meta2);

	auto resMeta = updatedMeta2.getObjectField(REPO_NODE_LABEL_METADATA);

	std::set<std::string> fieldNames1, fieldNames2;
	meta1.getFieldNames(fieldNames1);
	meta2.getFieldNames(fieldNames2);

	for (const auto &fieldName : fieldNames1)
	{
		ASSERT_TRUE(resMeta.hasField(fieldName));
		EXPECT_EQ(resMeta.getField(fieldName), meta1.getField(fieldName));
	}

	for (const auto &fieldName : fieldNames2)
	{
		ASSERT_TRUE(resMeta.hasField(fieldName));
		EXPECT_EQ(resMeta.getField(fieldName), meta2.getField(fieldName));
	}
}<commit_msg>#13 travis fix<commit_after>/**
*  Copyright (C) 2015 3D Repo Ltd
*
*  This program is free software: you can redistribute it and/or modify
*  it under the terms of the GNU Affero General Public License as
*  published by the Free Software Foundation, either version 3 of the
*  License, or (at your option) any later version.
*
*  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 Affero 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, see <http://www.gnu.org/licenses/>.
*/

#include <cstdlib>

#include <gtest/gtest.h>

#include <repo/core/model/bson/repo_node_metadata.h>
#include <repo/core/model/bson/repo_bson_builder.h>
#include <repo/core/model/bson/repo_bson_factory.h>

#include "../../../../repo_test_utils.h"

using namespace repo::core::model;

static MetadataNode makeRandomMetaNode()
{
	uint32_t nItems = rand() % 10 + 1;
	std::vector<std::string> keys, values;
	for (int i = 0; i < nItems; ++i)
	{
		keys.push_back(getRandomString(rand() % 10 + 1));
		values.push_back(getRandomString(rand() % 10 + 1));
	}
	return	RepoBSONFactory::makeMetaDataNode(keys, values);
}

/**
* Construct from mongo builder and mongo bson should give me the same bson
*/
TEST(MetaNodeTest, Constructor)
{
	MetadataNode empty;

	EXPECT_TRUE(empty.isEmpty());
	EXPECT_EQ(NodeType::METADATA, empty.getTypeAsEnum());

	auto repoBson = RepoBSON(BSON("test" << "blah" << "test2" << 2));

	auto fromRepoBSON = MetadataNode(repoBson);
	EXPECT_EQ(NodeType::METADATA, fromRepoBSON.getTypeAsEnum());
	EXPECT_EQ(fromRepoBSON.nFields(), repoBson.nFields());
	EXPECT_EQ(0, fromRepoBSON.getFileList().size());
}

TEST(MetaNodeTest, TypeTest)
{
	MetadataNode node;

	EXPECT_EQ(REPO_NODE_TYPE_METADATA, node.getType());
	EXPECT_EQ(NodeType::METADATA, node.getTypeAsEnum());
}

TEST(MetaNodeTest, PositionDependantTest)
{
	MetadataNode node;
	EXPECT_FALSE(node.positionDependant());
}

TEST(MetaNodeTest, SEqualTest)
{
	MetadataNode empty;
	EXPECT_TRUE(empty.sEqual(empty));

	auto metaNode = makeRandomMetaNode();
	auto metaNode2 = makeRandomMetaNode();

	EXPECT_TRUE(metaNode.sEqual(metaNode));
	EXPECT_FALSE(metaNode.sEqual(empty));
	EXPECT_FALSE(metaNode.sEqual(metaNode2));
}

TEST(MetaNodeTest, CloneAndAddMetadataTest)
{
	MetadataNode empty;

	auto metaNode = makeRandomMetaNode();
	auto metaNode2 = makeRandomMetaNode();

	auto meta1 = metaNode.getObjectField(REPO_NODE_LABEL_METADATA);
	auto meta2 = metaNode2.getObjectField(REPO_NODE_LABEL_METADATA);
	auto updatedMeta = empty.cloneAndAddMetadata(meta1);

	updatedMeta.sEqual(metaNode);

	auto updatedMeta2 = updatedMeta.cloneAndAddMetadata(meta2);

	auto resMeta = updatedMeta2.getObjectField(REPO_NODE_LABEL_METADATA);

	std::set<std::string> fieldNames1, fieldNames2;
	meta1.getFieldNames(fieldNames1);
	meta2.getFieldNames(fieldNames2);

	for (const auto &fieldName : fieldNames1)
	{
		//Skip the ones that would be overwritten
		if (meta2.hasField(fieldName)) continue;
		ASSERT_TRUE(resMeta.hasField(fieldName));
		EXPECT_EQ(resMeta.getField(fieldName), meta1.getField(fieldName));
	}

	for (const auto &fieldName : fieldNames2)
	{
		ASSERT_TRUE(resMeta.hasField(fieldName));
		EXPECT_EQ(resMeta.getField(fieldName), meta2.getField(fieldName));
	}
}<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>

#ifdef __GNUC__
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#else
#include <filesystem>
namespace fs = std::tr2::sys;
#endif

#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/asio.hpp>

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/face.hpp>

#define CONFIG_NUM_WORKERS 2
#define CONFIG_FACE_CLASS 41

cv::Ptr<cv::face::BasicFaceRecognizer> make_recognizer(int argc, char *argv[]) {
	std::vector<cv::Mat> images;
	std::vector<int> labels;

	// iterate through subdirectories to locate .pgm files
	fs::path p(argc > 1 ? argv[1] : "../assets/faces");
	for(const auto &entry : fs::recursive_directory_iterator{p}) {
		if(fs::is_regular_file(entry.status())) {
			if(entry.path().extension() == ".pgm") {
				std::string str = entry.path().parent_path().stem().string();
				int label = atoi(str.c_str() + 1);
				images.push_back(cv::imread(entry.path().string().c_str(), 0));
				labels.push_back(label);
			}
		}
	}

	auto recognizer = cv::face::createEigenFaceRecognizer();
	recognizer->train(images, labels);
	return recognizer;
}

void camera_loop(boost::shared_ptr<boost::asio::io_service> service,
                 cv::VideoCapture vid,
                 cv::Ptr<cv::face::BasicFaceRecognizer> recognizer,
                 unsigned int count) {
	cv::Mat frame;
	vid >> frame;

	float actual_aspect = (float)frame.cols / (float)frame.rows;
	float target_aspect = 92.0f / 112.0f;
	int target_width = frame.cols, target_height = frame.rows;
	if(actual_aspect > target_aspect) {
		target_width = target_height * target_aspect;
	} else {
		target_height = target_width / target_aspect;
	}

	cv::Rect rect(frame.cols / 2 - target_width / 2,
	              frame.rows / 2 - target_height / 2,
	              target_width, target_height);

	cv::Mat cropped_frame = frame(rect);
	cv::Mat gray_frame, resized_frame;
	cv::cvtColor(cropped_frame, gray_frame, CV_RGB2GRAY);
	cv::resize(gray_frame, resized_frame, cv::Size(92, 112));

	int predicted = recognizer->predict(resized_frame);
	if(predicted == CONFIG_FACE_CLASS) {
		if(count < 10) { ++count; }
	} else {
		if(count > 0) { --count; }
	}

	cv::Mat flipped_frame;
	cv::flip(cropped_frame, flipped_frame, 1);

	cv::Rect color_rect(0, 0, flipped_frame.cols, flipped_frame.rows);

	cv::rectangle(flipped_frame, color_rect, cv::Scalar(0, 0, 0), 10);
	switch(count) {
	case 0:
		cv::rectangle(flipped_frame, color_rect, cv::Scalar(0, 0, 255), 8);
		break;
	case 10:
		cv::rectangle(flipped_frame, color_rect, cv::Scalar(0, 255, 0), 8);
		break;
	default:
		cv::rectangle(flipped_frame, color_rect, cv::Scalar(0, 255, 255), 8);
		break;
	}
	cv::rectangle(flipped_frame, color_rect, cv::Scalar(0, 0, 0), 2);

	cv::imshow("optflow", flipped_frame);
	cv::waitKey(1000/60);
	service->post(std::bind(camera_loop, service, vid, recognizer, count));
}

void camera_main(boost::shared_ptr<boost::asio::io_service> service,
                 cv::Ptr<cv::face::BasicFaceRecognizer> recognizer) {
	cv::VideoCapture vid(0);
	if(!vid.isOpened()) {
		throw std::runtime_error("failed to open video capture device");
	}
	cv::namedWindow("optflow");
	service->post(std::bind(camera_loop, service, vid, recognizer, 0));
}

void worker_main(boost::shared_ptr<boost::asio::io_service> service) {
	service->run();
}

int main(int argc, char *argv[]) {
	std::cout << "training..." << std::endl;
	auto recognizer = make_recognizer(argc, argv);
	std::cout << "done" << std::endl;

	auto service = boost::make_shared<boost::asio::io_service>();
	auto work    = boost::make_shared<boost::asio::io_service::work>(*service);
	auto strand  = boost::make_shared<boost::asio::io_service::strand>(*service);
	boost::thread_group workers;
	for(unsigned int w = 0; w < CONFIG_NUM_WORKERS; ++w) {
		workers.create_thread(boost::bind(worker_main, service));
	}
	service->post(boost::bind(camera_main, service, recognizer));
	work.reset();
	workers.join_all();
	return 0;
}
<commit_msg>main: tidy up rectangle drawing code<commit_after>#include <iostream>
#include <fstream>

#ifdef __GNUC__
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#else
#include <filesystem>
namespace fs = std::tr2::sys;
#endif

#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/asio.hpp>

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/face.hpp>

#define CONFIG_NUM_WORKERS 2
#define CONFIG_FACE_CLASS 41

cv::Ptr<cv::face::BasicFaceRecognizer> make_recognizer(int argc, char *argv[]) {
	std::vector<cv::Mat> images;
	std::vector<int> labels;

	// iterate through subdirectories to locate .pgm files
	fs::path p(argc > 1 ? argv[1] : "../assets/faces");
	for(const auto &entry : fs::recursive_directory_iterator{p}) {
		if(fs::is_regular_file(entry.status())) {
			if(entry.path().extension() == ".pgm") {
				std::string str = entry.path().parent_path().stem().string();
				int label = atoi(str.c_str() + 1);
				images.push_back(cv::imread(entry.path().string().c_str(), 0));
				labels.push_back(label);
			}
		}
	}

	auto recognizer = cv::face::createEigenFaceRecognizer();
	recognizer->train(images, labels);
	return recognizer;
}

void camera_loop(boost::shared_ptr<boost::asio::io_service> service,
                 cv::VideoCapture vid,
                 cv::Ptr<cv::face::BasicFaceRecognizer> recognizer,
                 unsigned int count) {
	cv::Mat frame;
	vid >> frame;

	float actual_aspect = (float)frame.cols / (float)frame.rows;
	float target_aspect = 92.0f / 112.0f;
	int target_width = frame.cols, target_height = frame.rows;
	if(actual_aspect > target_aspect) {
		target_width = target_height * target_aspect;
	} else {
		target_height = target_width / target_aspect;
	}

	cv::Rect rect(frame.cols / 2 - target_width / 2,
	              frame.rows / 2 - target_height / 2,
	              target_width, target_height);

	cv::Mat cropped_frame = frame(rect);
	cv::Mat gray_frame, resized_frame;
	cv::cvtColor(cropped_frame, gray_frame, CV_RGB2GRAY);
	cv::resize(gray_frame, resized_frame, cv::Size(92, 112));

	int predicted = recognizer->predict(resized_frame);
	if(predicted == CONFIG_FACE_CLASS) {
		if(count < 10) { ++count; }
	} else {
		if(count > 0) { --count; }
	}

	cv::Mat flipped_frame;
	cv::flip(cropped_frame, flipped_frame, 1);

	cv::Rect color_rect(0, 0, flipped_frame.cols, flipped_frame.rows);

	cv::Scalar color(0, 255, 255);
	switch(count) {
	case 0:
		color = cv::Scalar(0, 0, 255);
		break;
	case 10:
		color = cv::Scalar(0, 255, 0);
		break;
	}

	cv::rectangle(flipped_frame, color_rect, cv::Scalar(0), 10);
	cv::rectangle(flipped_frame, color_rect, color, 8);
	cv::rectangle(flipped_frame, color_rect, cv::Scalar(0), 2);

	cv::imshow("optflow", flipped_frame);
	cv::waitKey(1000/60);
	service->post(std::bind(camera_loop, service, vid, recognizer, count));
}

void camera_main(boost::shared_ptr<boost::asio::io_service> service,
                 cv::Ptr<cv::face::BasicFaceRecognizer> recognizer) {
	cv::VideoCapture vid(0);
	if(!vid.isOpened()) {
		throw std::runtime_error("failed to open video capture device");
	}
	cv::namedWindow("optflow");
	service->post(std::bind(camera_loop, service, vid, recognizer, 0));
}

void worker_main(boost::shared_ptr<boost::asio::io_service> service) {
	service->run();
}

int main(int argc, char *argv[]) {
	std::cout << "training..." << std::endl;
	auto recognizer = make_recognizer(argc, argv);
	std::cout << "done" << std::endl;

	auto service = boost::make_shared<boost::asio::io_service>();
	auto work    = boost::make_shared<boost::asio::io_service::work>(*service);
	auto strand  = boost::make_shared<boost::asio::io_service::strand>(*service);
	boost::thread_group workers;
	for(unsigned int w = 0; w < CONFIG_NUM_WORKERS; ++w) {
		workers.create_thread(boost::bind(worker_main, service));
	}
	service->post(boost::bind(camera_main, service, recognizer));
	work.reset();
	workers.join_all();
	return 0;
}
<|endoftext|>


<commit_before>#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include <iostream>
#include <queue>
#include <stdio.h>
#include <math.h>

#include "constants.h"
#include "findEyeCenter.h"
#include "findEyeCorner.h"

/** Constants **/

/** Function Headers */
void detectAndDisplay( cv::Mat frame );

/** Global variables */
//-- Note, either copy these two files from opencv/data/haarscascades to your current folder, or change these locations
cv::String face_cascade_name = "../../../res/haarcascade_frontalface_alt.xml";
cv::CascadeClassifier face_cascade;
std::string main_window_name = "Capture - Face detection";
std::string face_window_name = "Capture - Face";
cv::RNG rng(12345);
cv::Mat debugImage;
cv::Mat skinCrCbHist = cv::Mat::zeros(cv::Size(256, 256), CV_8UC1);

/**
 * @function main
 */
int main( int argc, const char** argv ) {
  CvCapture* capture;
  cv::Mat frame;

  // Load the cascades
  if( !face_cascade.load( face_cascade_name ) ){ printf("--(!)Error loading face cascade, please change face_cascade_name in source code.\n"); return -1; };

  cv::namedWindow(main_window_name,CV_WINDOW_NORMAL);
  cv::moveWindow(main_window_name, 400, 100);
  cv::namedWindow(face_window_name,CV_WINDOW_NORMAL);
  cv::moveWindow(face_window_name, 10, 100);
  cv::namedWindow("Right Eye",CV_WINDOW_NORMAL);
  cv::moveWindow("Right Eye", 10, 600);
  cv::namedWindow("Left Eye",CV_WINDOW_NORMAL);
  cv::moveWindow("Left Eye", 10, 800);
  cv::namedWindow("aa",CV_WINDOW_NORMAL);
  cv::moveWindow("aa", 10, 800);
  cv::namedWindow("aaa",CV_WINDOW_NORMAL);
  cv::moveWindow("aaa", 10, 800);

  createCornerKernels();
  ellipse(skinCrCbHist, cv::Point(113, 155.6), cv::Size(23.4, 15.2),
          43.0, 0.0, 360.0, cv::Scalar(255, 255, 255), -1);

   // Read the video stream
  capture = cvCaptureFromCAM( -1 );
  if( capture ) {
    while( true ) {
      frame = cvQueryFrame( capture );
      // mirror it
      cv::flip(frame, frame, 1);
      frame.copyTo(debugImage);

      // Apply the classifier to the frame
      if( !frame.empty() ) {
        detectAndDisplay( frame );
      }
      else {
        printf(" --(!) No captured frame -- Break!");
        break;
      }

      imshow(main_window_name,debugImage);

      int c = cv::waitKey(10);
      if( (char)c == 'c' ) { break; }
      if( (char)c == 'f' ) {
        imwrite("frame.png",frame);
      }

    }
  }

  releaseCornerKernels();

  return 0;
}

void findEyes(cv::Mat frame_gray, cv::Rect face) {
  cv::Mat faceROI = frame_gray(face);
  cv::Mat debugFace = faceROI;

  if (kSmoothFaceImage) {
    double sigma = kSmoothFaceFactor * face.width;
    GaussianBlur( faceROI, faceROI, cv::Size( 0, 0 ), sigma);
  }
  //-- Find eye regions and draw them
  int eye_region_width = face.width * (kEyePercentWidth/100.0);
  int eye_region_height = face.width * (kEyePercentHeight/100.0);
  int eye_region_top = face.height * (kEyePercentTop/100.0);
  cv::Rect leftEyeRegion(face.width*(kEyePercentSide/100.0),
                         eye_region_top,eye_region_width,eye_region_height);
  cv::Rect rightEyeRegion(face.width - eye_region_width - face.width*(kEyePercentSide/100.0),
                          eye_region_top,eye_region_width,eye_region_height);

  //-- Find Eye Centers
  cv::Point leftPupil = findEyeCenter(faceROI,leftEyeRegion,"Left Eye");
  cv::Point rightPupil = findEyeCenter(faceROI,rightEyeRegion,"Right Eye");
  // get corner regions
  cv::Rect leftRightCornerRegion(leftEyeRegion);
  leftRightCornerRegion.width -= leftPupil.x;
  leftRightCornerRegion.x += leftPupil.x;
  leftRightCornerRegion.height /= 2;
  leftRightCornerRegion.y += leftRightCornerRegion.height / 2;
  cv::Rect leftLeftCornerRegion(leftEyeRegion);
  leftLeftCornerRegion.width = leftPupil.x;
  leftLeftCornerRegion.height /= 2;
  leftLeftCornerRegion.y += leftLeftCornerRegion.height / 2;
  cv::Rect rightLeftCornerRegion(rightEyeRegion);
  rightLeftCornerRegion.width = rightPupil.x;
  rightLeftCornerRegion.height /= 2;
  rightLeftCornerRegion.y += rightLeftCornerRegion.height / 2;
  cv::Rect rightRightCornerRegion(rightEyeRegion);
  rightRightCornerRegion.width -= rightPupil.x;
  rightRightCornerRegion.x += rightPupil.x;
  rightRightCornerRegion.height /= 2;
  rightRightCornerRegion.y += rightRightCornerRegion.height / 2;
  rectangle(debugFace,leftRightCornerRegion,200);
  rectangle(debugFace,leftLeftCornerRegion,200);
  rectangle(debugFace,rightLeftCornerRegion,200);
  rectangle(debugFace,rightRightCornerRegion,200);
  // change eye centers to face coordinates
  rightPupil.x += rightEyeRegion.x;
  rightPupil.y += rightEyeRegion.y;
  leftPupil.x += leftEyeRegion.x;
  leftPupil.y += leftEyeRegion.y;
  // draw eye centers
  circle(debugFace, rightPupil, 3, 1234);
  circle(debugFace, leftPupil, 3, 1234);

  //-- Find Eye Corners
  if (kEnableEyeCorner) {
    cv::Point2f leftRightCorner = findEyeCorner(faceROI(leftRightCornerRegion), true, false);
    leftRightCorner.x += leftRightCornerRegion.x;
    leftRightCorner.y += leftRightCornerRegion.y;
    cv::Point2f leftLeftCorner = findEyeCorner(faceROI(leftLeftCornerRegion), true, true);
    leftLeftCorner.x += leftLeftCornerRegion.x;
    leftLeftCorner.y += leftLeftCornerRegion.y;
    cv::Point2f rightLeftCorner = findEyeCorner(faceROI(rightLeftCornerRegion), false, true);
    rightLeftCorner.x += rightLeftCornerRegion.x;
    rightLeftCorner.y += rightLeftCornerRegion.y;
    cv::Point2f rightRightCorner = findEyeCorner(faceROI(rightRightCornerRegion), false, false);
    rightRightCorner.x += rightRightCornerRegion.x;
    rightRightCorner.y += rightRightCornerRegion.y;
    circle(faceROI, leftRightCorner, 3, 200);
    circle(faceROI, leftLeftCorner, 3, 200);
    circle(faceROI, rightLeftCorner, 3, 200);
    circle(faceROI, rightRightCorner, 3, 200);
  }

  imshow(face_window_name, faceROI);
//  cv::Rect roi( cv::Point( 0, 0 ), faceROI.size());
//  cv::Mat destinationROI = debugImage( roi );
//  faceROI.copyTo( destinationROI );
}

cv::Mat findSkin (cv::Mat &frame) {
  cv::Mat input;
  cv::Mat output = cv::Mat(frame.rows,frame.cols, CV_8U);

  cvtColor(frame, input, CV_BGR2YCrCb);

  for (int y = 0; y < input.rows; ++y) {
    const cv::Vec3b *Mr = input.ptr<cv::Vec3b>(y);
//    uchar *Or = output.ptr<uchar>(y);
    cv::Vec3b *Or = frame.ptr<cv::Vec3b>(y);
    for (int x = 0; x < input.cols; ++x) {
      cv::Vec3b ycrcb = Mr[x];
//      Or[x] = (skinCrCbHist.at<uchar>(ycrcb[1], ycrcb[2]) > 0) ? 255 : 0;
      if(skinCrCbHist.at<uchar>(ycrcb[1], ycrcb[2]) == 0) {
        Or[x] = cv::Vec3b(0,0,0);
      }
    }
  }
  return output;
}

/**
 * @function detectAndDisplay
 */
void detectAndDisplay( cv::Mat frame ) {
  std::vector<cv::Rect> faces;
  //cv::Mat frame_gray;

  std::vector<cv::Mat> rgbChannels(3);
  cv::split(frame, rgbChannels);
  cv::Mat frame_gray = rgbChannels[2];

  //cvtColor( frame, frame_gray, CV_BGR2GRAY );
  //equalizeHist( frame_gray, frame_gray );
  //cv::pow(frame_gray, CV_64F, frame_gray);
  //-- Detect faces
  face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE|CV_HAAR_FIND_BIGGEST_OBJECT, cv::Size(150, 150) );
//  findSkin(debugImage);

  for( int i = 0; i < faces.size(); i++ )
  {
    rectangle(debugImage, faces[i], 1234);
  }
  //-- Show what you got
  if (faces.size() > 0) {
    findEyes(frame_gray, faces[0]);
  }
}
<commit_msg>added color blob tracking to the app<commit_after>#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include <iostream>
#include <queue>
#include <stdio.h>
#include <math.h>
#include <vector>

#include "constants.h"
#include "findEyeCenter.h"
#include "findEyeCorner.h"

using namespace std;
using namespace cv;

/** Constants **/

/** Function Headers */
void detectAndDisplay( cv::Mat frame );
void findFacialMarkers( cv::Mat frame);

/** Global variables */
//-- Note, either copy these two files from opencv/data/haarscascades to your current folder, or change these locations
cv::String face_cascade_name = "../../res/haarcascade_frontalface_alt.xml";
cv::CascadeClassifier face_cascade;
std::string main_window_name = "Capture - Face detection";
std::string face_window_name = "Capture - Face";
std::string markers_window_name = "Capture - Facial Markers";
cv::RNG rng(12345);
cv::Mat debugImage;
cv::Mat skinCrCbHist = cv::Mat::zeros(cv::Size(256, 256), CV_8UC1);

int iLowH = 48;
int iHighH = 65;
int iLowS = 115;
int iHighS = 255;
int iLowV = 178;
int iHighV = 247;

/**
 * @function main
 */
int main( int argc, const char** argv ) {
  CvCapture* capture;
  cv::Mat frame;

  // Load the cascades
  if( !face_cascade.load( face_cascade_name ) ){ printf("--(!)Error loading face cascade, please change face_cascade_name in source code.\n"); return -1; };

  cv::namedWindow(main_window_name,CV_WINDOW_NORMAL);
  cv::moveWindow(main_window_name, 400, 100);
  cv::namedWindow(face_window_name,CV_WINDOW_NORMAL);
  cv::moveWindow(face_window_name, 10, 100);
  cv::namedWindow(markers_window_name,CV_WINDOW_NORMAL);
  cv::moveWindow(markers_window_name, 800, 100);

  cv::namedWindow("Right Eye",CV_WINDOW_NORMAL);
  cv::moveWindow("Right Eye", 10, 600);
  cv::namedWindow("Left Eye",CV_WINDOW_NORMAL);
  cv::moveWindow("Left Eye", 10, 800);

  // Add trackbars for the HSV settings
  cvCreateTrackbar("LowH",  markers_window_name.c_str(), &iLowH, 179); //Hue (0 - 179)
  cvCreateTrackbar("HighH", markers_window_name.c_str(), &iHighH, 179);
  cvCreateTrackbar("LowS",  markers_window_name.c_str(), &iLowS, 255); //Saturation (0 - 255)
  cvCreateTrackbar("HighS", markers_window_name.c_str(), &iHighS, 255);
  cvCreateTrackbar("LowV",  markers_window_name.c_str(), &iLowV, 255); //Value (0 - 255)
  cvCreateTrackbar("HighV", markers_window_name.c_str(), &iHighV, 255);

  createCornerKernels();
  ellipse(skinCrCbHist, cv::Point(113, 155.6), cv::Size(23.4, 15.2),
          43.0, 0.0, 360.0, cv::Scalar(255, 255, 255), -1);

  // Read the video stream
  //capture = cvCaptureFromFile("../../res/jc.jpg" );
  capture = cvCaptureFromCAM(2);
  if( capture ) {

    while( true ) {
      frame = cvQueryFrame( capture );
      cv::flip(frame, frame, 1);

      // mirror it
      frame.copyTo(debugImage);

      // Apply the classifier to the frame
      if( !frame.empty() ) {
        findFacialMarkers(frame);

        detectAndDisplay(frame);
      }
      else {
        printf(" --(!) No captured frame -- Break!");
        break;
      }

      imshow(main_window_name, debugImage);

      int c = cv::waitKey(10);
      if( (char)c == 'c' ) { break; }
      if( (char)c == 'f' ) {
        imwrite("frame.png",frame);
      }
    }
  }

  releaseCornerKernels();

  return 0;
}

void findFacialMarkers(cv::Mat frame) {
  vector<vector<cv::Point> > contours;
  vector<cv::Vec4i> hierarchy;

  cv::Mat imgHSV;
  cv::cvtColor(frame, imgHSV, cv::COLOR_RGB2HSV); //Convert the captured frame from RGB to HSV

  cv::Mat imgThresholded;
  cv::inRange(imgHSV, cv::Scalar(iLowH, iLowS, iLowV), cv::Scalar(iHighH, iHighS, iHighV), imgThresholded); //Threshold the image

  imshow(markers_window_name.c_str(), imgThresholded);

  cv::findContours(imgThresholded, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE, cv::Point(0, 0));

  for (int i = 0; i < contours.size(); i++) {
    Rect bound = boundingRect(contours[i]);
    Point center = Point( bound.x + (bound.width / 2), bound.y + (bound.height / 2));

    circle(debugImage, center, 3, Scalar(0, 0, 255), -1);
  }
}

void findEyes(cv::Mat frame_gray, cv::Rect face) {
  cv::Mat faceROI = frame_gray(face);
  cv::Mat debugFace = faceROI;

  if (kSmoothFaceImage) {
    double sigma = kSmoothFaceFactor * face.width;
    GaussianBlur( faceROI, faceROI, cv::Size( 0, 0 ), sigma);
  }
  //-- Find eye regions and draw them
  int eye_region_width = face.width * (kEyePercentWidth/100.0);
  int eye_region_height = face.width * (kEyePercentHeight/100.0);
  int eye_region_top = face.height * (kEyePercentTop/100.0);
  cv::Rect leftEyeRegion(face.width*(kEyePercentSide/100.0),
                         eye_region_top,eye_region_width,eye_region_height);
  cv::Rect rightEyeRegion(face.width - eye_region_width - face.width*(kEyePercentSide/100.0),
                          eye_region_top,eye_region_width,eye_region_height);

  //-- Find Eye Centers
  cv::Point leftPupil = findEyeCenter(faceROI,leftEyeRegion,"Left Eye");
  cv::Point rightPupil = findEyeCenter(faceROI,rightEyeRegion,"Right Eye");
  // get corner regions
  cv::Rect leftRightCornerRegion(leftEyeRegion);
  leftRightCornerRegion.width -= leftPupil.x;
  leftRightCornerRegion.x += leftPupil.x;
  leftRightCornerRegion.height /= 2;
  leftRightCornerRegion.y += leftRightCornerRegion.height / 2;
  cv::Rect leftLeftCornerRegion(leftEyeRegion);
  leftLeftCornerRegion.width = leftPupil.x;
  leftLeftCornerRegion.height /= 2;
  leftLeftCornerRegion.y += leftLeftCornerRegion.height / 2;
  cv::Rect rightLeftCornerRegion(rightEyeRegion);
  rightLeftCornerRegion.width = rightPupil.x;
  rightLeftCornerRegion.height /= 2;
  rightLeftCornerRegion.y += rightLeftCornerRegion.height / 2;
  cv::Rect rightRightCornerRegion(rightEyeRegion);
  rightRightCornerRegion.width -= rightPupil.x;
  rightRightCornerRegion.x += rightPupil.x;
  rightRightCornerRegion.height /= 2;
  rightRightCornerRegion.y += rightRightCornerRegion.height / 2;
  rectangle(debugFace,leftRightCornerRegion,200);
  rectangle(debugFace,leftLeftCornerRegion,200);
  rectangle(debugFace,rightLeftCornerRegion,200);
  rectangle(debugFace,rightRightCornerRegion,200);
  // change eye centers to face coordinates
  rightPupil.x += rightEyeRegion.x;
  rightPupil.y += rightEyeRegion.y;
  leftPupil.x += leftEyeRegion.x;
  leftPupil.y += leftEyeRegion.y;
  // draw eye centers
  circle(debugFace, rightPupil, 3, 1234);
  circle(debugFace, leftPupil, 3, 1234);

  //-- Find Eye Corners
  if (kEnableEyeCorner) {
    cv::Point2f leftRightCorner = findEyeCorner(faceROI(leftRightCornerRegion), true, false);
    leftRightCorner.x += leftRightCornerRegion.x;
    leftRightCorner.y += leftRightCornerRegion.y;
    cv::Point2f leftLeftCorner = findEyeCorner(faceROI(leftLeftCornerRegion), true, true);
    leftLeftCorner.x += leftLeftCornerRegion.x;
    leftLeftCorner.y += leftLeftCornerRegion.y;
    cv::Point2f rightLeftCorner = findEyeCorner(faceROI(rightLeftCornerRegion), false, true);
    rightLeftCorner.x += rightLeftCornerRegion.x;
    rightLeftCorner.y += rightLeftCornerRegion.y;
    cv::Point2f rightRightCorner = findEyeCorner(faceROI(rightRightCornerRegion), false, false);
    rightRightCorner.x += rightRightCornerRegion.x;
    rightRightCorner.y += rightRightCornerRegion.y;
    circle(faceROI, leftRightCorner, 3, 200);
    circle(faceROI, leftLeftCorner, 3, 200);
    circle(faceROI, rightLeftCorner, 3, 200);
    circle(faceROI, rightRightCorner, 3, 200);
  }

  imshow(face_window_name, faceROI);
  //  cv::Rect roi( cv::Point( 0, 0 ), faceROI.size());
  //  cv::Mat destinationROI = debugImage( roi );
  //  faceROI.copyTo( destinationROI );
}

cv::Mat findSkin (cv::Mat &frame) {
  cv::Mat input;
  cv::Mat output = cv::Mat(frame.rows,frame.cols, CV_8U);

  cvtColor(frame, input, CV_BGR2YCrCb);

  for (int y = 0; y < input.rows; ++y) {
    const cv::Vec3b *Mr = input.ptr<cv::Vec3b>(y);
    //    uchar *Or = output.ptr<uchar>(y);
    cv::Vec3b *Or = frame.ptr<cv::Vec3b>(y);
    for (int x = 0; x < input.cols; ++x) {
      cv::Vec3b ycrcb = Mr[x];
      //      Or[x] = (skinCrCbHist.at<uchar>(ycrcb[1], ycrcb[2]) > 0) ? 255 : 0;
      if(skinCrCbHist.at<uchar>(ycrcb[1], ycrcb[2]) == 0) {
        Or[x] = cv::Vec3b(0,0,0);
      }
    }
  }
  return output;
}

/**
 * @function detectAndDisplay
 */
void detectAndDisplay( cv::Mat frame ) {
  std::vector<cv::Rect> faces;
  //cv::Mat frame_gray;

  std::vector<cv::Mat> rgbChannels(3);
  cv::split(frame, rgbChannels);
  cv::Mat frame_gray = rgbChannels[2]; // Used to be rgbChannels[2], i.e. the blue channel.

  //cvtColor( frame, frame_gray, CV_BGR2GRAY );
  //equalizeHist( frame_gray, frame_gray );
  //cv::pow(frame_gray, CV_64F, frame_gray);
  //-- Detect faces
  face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE|CV_HAAR_FIND_BIGGEST_OBJECT, cv::Size(150, 150) );
  //  findSkin(debugImage);

  for( int i = 0; i < faces.size(); i++ )
    {
      rectangle(debugImage, faces[i], 1234);
    }
  //-- Show what you got
  if (faces.size() > 0) {
    findEyes(frame_gray, faces[0]);
  }
}
<|endoftext|>


<commit_before>#include "FOX_OSG_MDIView.h"

#include <osgViewer/ViewerEventHandlers>

#include <osgGA/TrackballManipulator>

#include <osgDB/ReadFile>

// Map
FXDEFMAP(FOX_OSG_MDIView) FOX_OSG_MDIView_Map[] = {
    //________Message_Type_________        ___ID___                        ________Message_Handler________
    FXMAPFUNC(SEL_CHORE,                FOX_OSG_MDIView::ID_CHORE,        FOX_OSG_MDIView::OnIdle)
};

FXIMPLEMENT(FOX_OSG_MDIView, FXMDIChild, FOX_OSG_MDIView_Map, ARRAYNUMBER(FOX_OSG_MDIView_Map))

FOX_OSG_MDIView::FOX_OSG_MDIView(FXMDIClient *p, const FXString &name,
        FXIcon *ic, FXPopup *pup, FXuint opt,
        FXint x, FXint y, FXint w, FXint h)
        :   FXMDIChild(p, name, ic, pup, opt, x, y, w, h)
{
    // A visual to drag OpenGL in double-buffered mode; note the glvisual is
    // shared between all windows which need the same depths and numbers of buffers
    // Thus, while the first visual may take some time to initialize, each subsequent
    // window can be created very quickly; we need to determine grpaphics hardware
    // characteristics only once.
    FXGLVisual* glVisual=new FXGLVisual(getApp(),VISUAL_DOUBLEBUFFER|VISUAL_STEREO);

    m_gwFox = new GraphicsWindowFOX(this, glVisual, NULL, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y, x, y, w, h );

    osgViewer::Viewer *viewer = new osgViewer::Viewer;
    viewer->getCamera()->setGraphicsContext(m_gwFox);
    viewer->getCamera()->setViewport(0,0,w,h);
    viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);

    // load the scene.
    osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFile("cow.osg");
    if (!loadedModel)
    {
        return ;
    }

    // add the stats handler
    viewer->addEventHandler(new osgViewer::StatsHandler);

    viewer->setSceneData(loadedModel.get());

    viewer->setCameraManipulator(new osgGA::TrackballManipulator);

    SetViewer(viewer);

    getApp()->addChore(this,ID_CHORE);

}

FOX_OSG_MDIView::~FOX_OSG_MDIView()
{
    getApp()->removeChore(this,ID_CHORE);
}

long FOX_OSG_MDIView::OnIdle(FXObject *sender, FXSelector sel, void* ptr)
{
    m_osgViewer->frame();
    getApp()->addChore(this, ID_CHORE);
    return 1;
}

void FOX_OSG_MDIView::SetViewer(osgViewer::Viewer* viewer)
{
    m_osgViewer = viewer;
}
<commit_msg>Disable the escape sets done on the viewer<commit_after>#include "FOX_OSG_MDIView.h"

#include <osgViewer/ViewerEventHandlers>

#include <osgGA/TrackballManipulator>

#include <osgDB/ReadFile>

// Map
FXDEFMAP(FOX_OSG_MDIView) FOX_OSG_MDIView_Map[] = {
    //________Message_Type_________        ___ID___                        ________Message_Handler________
    FXMAPFUNC(SEL_CHORE,                FOX_OSG_MDIView::ID_CHORE,        FOX_OSG_MDIView::OnIdle)
};

FXIMPLEMENT(FOX_OSG_MDIView, FXMDIChild, FOX_OSG_MDIView_Map, ARRAYNUMBER(FOX_OSG_MDIView_Map))

FOX_OSG_MDIView::FOX_OSG_MDIView(FXMDIClient *p, const FXString &name,
        FXIcon *ic, FXPopup *pup, FXuint opt,
        FXint x, FXint y, FXint w, FXint h)
        :   FXMDIChild(p, name, ic, pup, opt, x, y, w, h)
{
    // A visual to drag OpenGL in double-buffered mode; note the glvisual is
    // shared between all windows which need the same depths and numbers of buffers
    // Thus, while the first visual may take some time to initialize, each subsequent
    // window can be created very quickly; we need to determine grpaphics hardware
    // characteristics only once.
    FXGLVisual* glVisual=new FXGLVisual(getApp(),VISUAL_DOUBLEBUFFER|VISUAL_STEREO);

    m_gwFox = new GraphicsWindowFOX(this, glVisual, NULL, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y, x, y, w, h );

    osgViewer::Viewer *viewer = new osgViewer::Viewer;
    viewer->getCamera()->setGraphicsContext(m_gwFox);
    viewer->getCamera()->setViewport(0,0,w,h);
    viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);

    // FOX example does not catch the close of the graphics window, so
    // don't allow the default escape sets to done to be active.
    viewer->setKeyEventSetsDone(0);

    // load the scene.
    osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFile("cow.osg");
    if (!loadedModel)
    {
        return ;
    }

    // add the stats handler
    viewer->addEventHandler(new osgViewer::StatsHandler);

    viewer->setSceneData(loadedModel.get());

    viewer->setCameraManipulator(new osgGA::TrackballManipulator);

    SetViewer(viewer);

    getApp()->addChore(this,ID_CHORE);

}

FOX_OSG_MDIView::~FOX_OSG_MDIView()
{
    getApp()->removeChore(this,ID_CHORE);
}

long FOX_OSG_MDIView::OnIdle(FXObject *sender, FXSelector sel, void* ptr)
{
    m_osgViewer->frame();
    getApp()->addChore(this, ID_CHORE);
    return 1;
}

void FOX_OSG_MDIView::SetViewer(osgViewer::Viewer* viewer)
{
    m_osgViewer = viewer;
}
<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*! @file
    @brief  イグナイター・アプリケーション・クラス
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2017 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#include "main.hpp"
#include "core/glcore.hpp"
#include "utils/i_scene.hpp"
#include "utils/director.hpp"
#include "widgets/widget.hpp"
#include "widgets/widget_frame.hpp"
#include "widgets/widget_null.hpp"
#include "widgets/widget_button.hpp"
#include "widgets/widget_filer.hpp"
#include "widgets/widget_terminal.hpp"
#include "widgets/widget_view.hpp"
#include "widgets/widget_utils.hpp"

#include "ign_client.hpp"
#include "ign_server.hpp"
#include "render_waves.hpp"

namespace app {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  Ignitor アプリケーション・クラス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	class ignitor : public utils::i_scene {

		utils::director<core>&	director_;

		gui::widget_frame*		menu_;
		gui::widget_button*		load_;

		gui::widget_filer*		load_ctx_;

		gui::widget_frame*		wave_;

		gui::widget_frame*		terminal_frame_;
		gui::widget_terminal*	terminal_core_;

		gui::widget_frame*		view_frame_;
		gui::widget_view*		view_core_;

		asio::io_service		io_service_;
		net::ign_client			client_;
		net::ign_server			server_;

		bool					start_client_;

		typedef view::render_waves<uint16_t, 65536 * 4> WAVES;
		WAVES					waves_;

		// ターミナル、行入力
		void term_enter_(const utils::lstring& text) {
			auto s = utils::utf32_to_utf8(text);
//			project_.logic_edit_.command(s);
///			std::cout << s << std::endl;
		}

		// 波形描画
		void update_view_()
		{
		}

		void render_view_(const vtx::irect& clip)
		{
			glDisable(GL_TEXTURE_2D);

			gl::glColor(img::rgba8(255, 255));
			waves_.render(clip.size.x);
		}

		void service_view_()
		{
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
		*/
		//-----------------------------------------------------------------//
		ignitor(utils::director<core>& d) : director_(d),
			menu_(nullptr), load_(nullptr), load_ctx_(nullptr),
			wave_(nullptr),
			terminal_frame_(nullptr), terminal_core_(nullptr),
			view_frame_(nullptr), view_core_(nullptr),
			io_service_(),
			client_(io_service_),
			server_(io_service_),
			start_client_(false)
		{
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  初期化
		*/
		//-----------------------------------------------------------------//
		void initialize()
		{
			using namespace gui;
			widget_director& wd = director_.at().widget_director_;
			gl::core& core = gl::core::get_instance();

			{	// メニューパレット
				widget::param wp(vtx::irect(10, 10, 110, 300));
				widget_frame::param wp_;
				wp_.plate_param_.set_caption(12);
				menu_ = wd.add_widget<widget_frame>(wp, wp_);
				menu_->set_state(gui::widget::state::SIZE_LOCK);
			}

			{ // ロード起動ボタン
				widget::param wp(vtx::irect(10, 20+40*0, 90, 30), menu_);
				widget_button::param wp_("load");
				wp_.select_func_ = [this](int id) {
//					gui::get_open_file_name();
					if(load_ctx_) {
//						script_on_ = false;
						bool f = load_ctx_->get_state(gui::widget::state::ENABLE);
						load_ctx_->enable(!f);
//						save_->set_stall(!f);
//						export_->set_stall(!f);
//						script_->set_stall(!f);
					}
				};
				load_ = wd.add_widget<widget_button>(wp, wp_);
			}

			{ // load ファイラー本体
				widget::param wp(vtx::irect(10, 30, 300, 200));
				widget_filer::param wp_(core.get_current_path());
				wp_.select_file_func_ = [this](const std::string& path) {
#if 0
					bool f = false;
					if(script_on_) {
						f = project_.logic_edit_.injection(path);
					} else {
						f = project_.logic_.load(path);
					}
					load_->set_stall(false);
					save_->set_stall(false);
					export_->set_stall(false);
					script_->set_stall(false);
					if(!f) {  // load error
						if(script_on_) dialog_->set_text("Script error:\n" + path);
						else dialog_->set_text("Load error:\n" + path);
						dialog_->enable();
					}
#endif
				};
				load_ctx_ = wd.add_widget<widget_filer>(wp, wp_);
				load_ctx_->enable(false);
			}

			{	// ターミナル
				{
					widget::param wp(vtx::irect(20, 100, 100, 200));
					widget_frame::param wp_;
					wp_.plate_param_.set_caption(12);
					terminal_frame_ = wd.add_widget<widget_frame>(wp, wp_);
				}
				{
					widget::param wp(vtx::irect(0), terminal_frame_);
					widget_terminal::param wp_;
					wp_.enter_func_ = [this](const utils::lstring& text) {
						term_enter_(text);
					};
					terminal_core_ = wd.add_widget<widget_terminal>(wp, wp_);
					term_chaout::set_output(terminal_core_);
				}

				// ロジック編集クラスの出力先の設定
//				project_.logic_edit_.set_output([this](const std::string& s) {
//					terminal_core_->output(s);
//				}
//				);
			}

			{	// 波形ビュー
				{
					widget::param wp(vtx::irect(40, 150, 200, 200));
					widget_frame::param wp_;
					wp_.plate_param_.set_caption(12);
					view_frame_ = wd.add_widget<widget_frame>(wp, wp_);
				}
				{
					widget::param wp(vtx::irect(0), view_frame_);
					widget_view::param wp_;
					wp_.update_func_ = [this]() {
						update_view_();
					};
					wp_.render_func_ = [this](const vtx::irect& clip) {
						render_view_(clip);
					};
					wp_.service_func_ = [this]() {
						service_view_();
					};
					view_core_ = wd.add_widget<widget_view>(wp, wp_);
				}
			}

			// プリファレンスのロード
			sys::preference& pre = director_.at().preference_;

			if(menu_ != nullptr) {
				menu_->load(pre, false, false);
			}

///			project_.load(pre);

			if(terminal_frame_ != nullptr) {
				terminal_frame_->load(pre);
			}

			if(view_frame_ != nullptr) {
				view_frame_->load(pre);
			}

//			if(argv_frame_ != nullptr) {
//				argv_frame_->load(pre);
//			}

			if(load_ctx_ != nullptr) load_ctx_->load(pre);
///			if(save_ctx_ != nullptr) save_ctx_->load(pre);

///			if(edit_ != nullptr) edit_->load(pre);

			// テスト・サーバー起動
			server_.start();

			// テスト波形生成
			waves_.create_waves(0.5, 5.0 * 10e-6);
			waves_.create_sin(1000);
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  アップデート
		*/
		//-----------------------------------------------------------------//
		void update()
		{
			if(start_client_) {
				client_.service();
			} else {
				client_.start();
				start_client_ = true;
			}
			server_.service();
			io_service_.run();

			gui::widget_director& wd = director_.at().widget_director_;
#if 0
			// Drag & Drop されたファイル
			gl::core& core = gl::core::get_instance();
			int id = core.get_recv_files_id();
			if(drop_file_id_ != id) {
				drop_file_id_ = id;
				const utils::strings& ss = core.get_recv_files_path();
				if(!ss.empty()) {
					std::string path = ss[0];
					if(load_ctx_ != nullptr && load_ctx_->get_local_param().select_file_func_ != nullptr) {
						load_ctx_->get_local_param().select_file_func_(path);
					}
				}
			}
#endif
			wd.update();
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  レンダリング
		*/
		//-----------------------------------------------------------------//
		void render()
		{
			director_.at().widget_director_.service();
			director_.at().widget_director_.render();
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  廃棄
		*/
		//-----------------------------------------------------------------//
		void destroy()
		{
			sys::preference& pre = director_.at().preference_;

///			if(edit_ != nullptr) edit_->save(pre);

			if(load_ctx_ != nullptr) load_ctx_->save(pre);
///			if(save_ctx_ != nullptr) save_ctx_->save(pre);

//			if(argv_frame_ != nullptr) {
//				argv_frame_->save(pre);
//			}

			if(view_frame_ != nullptr) {
				view_frame_->save(pre);
			}

			if(terminal_frame_ != nullptr) {
				terminal_frame_->save(pre);
			}

//			project_.save(pre);

			if(menu_ != nullptr) {
				menu_->save(pre);
			}
		}
	};
}
<commit_msg>update sin wave initial<commit_after>#pragma once
//=====================================================================//
/*! @file
    @brief  イグナイター・アプリケーション・クラス
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2017 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#include "main.hpp"
#include "core/glcore.hpp"
#include "utils/i_scene.hpp"
#include "utils/director.hpp"
#include "widgets/widget.hpp"
#include "widgets/widget_frame.hpp"
#include "widgets/widget_null.hpp"
#include "widgets/widget_button.hpp"
#include "widgets/widget_filer.hpp"
#include "widgets/widget_terminal.hpp"
#include "widgets/widget_view.hpp"
#include "widgets/widget_utils.hpp"

#include "ign_client.hpp"
#include "ign_server.hpp"
#include "gl_fw/render_waves.hpp"

namespace app {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  Ignitor アプリケーション・クラス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	class ignitor : public utils::i_scene {

		utils::director<core>&	director_;

		gui::widget_frame*		menu_;
		gui::widget_button*		load_;

		gui::widget_filer*		load_ctx_;

		gui::widget_frame*		wave_;

		gui::widget_frame*		terminal_frame_;
		gui::widget_terminal*	terminal_core_;

		gui::widget_frame*		view_frame_;
		gui::widget_view*		view_core_;

		asio::io_service		io_service_;
		net::ign_client			client_;
		net::ign_server			server_;

		bool					start_client_;

		typedef view::render_waves<uint16_t, 65536 * 4> WAVES;
		WAVES					waves_;

		// ターミナル、行入力
		void term_enter_(const utils::lstring& text) {
			auto s = utils::utf32_to_utf8(text);
//			project_.logic_edit_.command(s);
///			std::cout << s << std::endl;
		}

		// 波形描画
		void update_view_()
		{
		}

		void render_view_(const vtx::irect& clip)
		{
			glDisable(GL_TEXTURE_2D);

			gl::glColor(img::rgba8(255, 255));
			waves_.render(clip.size.x);
		}

		void service_view_()
		{
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
		*/
		//-----------------------------------------------------------------//
		ignitor(utils::director<core>& d) : director_(d),
			menu_(nullptr), load_(nullptr), load_ctx_(nullptr),
			wave_(nullptr),
			terminal_frame_(nullptr), terminal_core_(nullptr),
			view_frame_(nullptr), view_core_(nullptr),
			io_service_(),
			client_(io_service_),
			server_(io_service_),
			start_client_(false)
		{
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  初期化
		*/
		//-----------------------------------------------------------------//
		void initialize()
		{
			using namespace gui;
			widget_director& wd = director_.at().widget_director_;
			gl::core& core = gl::core::get_instance();

			{	// メニューパレット
				widget::param wp(vtx::irect(10, 10, 110, 300));
				widget_frame::param wp_;
				wp_.plate_param_.set_caption(12);
				menu_ = wd.add_widget<widget_frame>(wp, wp_);
				menu_->set_state(gui::widget::state::SIZE_LOCK);
			}

			{ // ロード起動ボタン
				widget::param wp(vtx::irect(10, 20+40*0, 90, 30), menu_);
				widget_button::param wp_("load");
				wp_.select_func_ = [this](int id) {
//					gui::get_open_file_name();
					if(load_ctx_) {
//						script_on_ = false;
						bool f = load_ctx_->get_state(gui::widget::state::ENABLE);
						load_ctx_->enable(!f);
//						save_->set_stall(!f);
//						export_->set_stall(!f);
//						script_->set_stall(!f);
					}
				};
				load_ = wd.add_widget<widget_button>(wp, wp_);
			}

			{ // load ファイラー本体
				widget::param wp(vtx::irect(10, 30, 300, 200));
				widget_filer::param wp_(core.get_current_path());
				wp_.select_file_func_ = [this](const std::string& path) {
#if 0
					bool f = false;
					if(script_on_) {
						f = project_.logic_edit_.injection(path);
					} else {
						f = project_.logic_.load(path);
					}
					load_->set_stall(false);
					save_->set_stall(false);
					export_->set_stall(false);
					script_->set_stall(false);
					if(!f) {  // load error
						if(script_on_) dialog_->set_text("Script error:\n" + path);
						else dialog_->set_text("Load error:\n" + path);
						dialog_->enable();
					}
#endif
				};
				load_ctx_ = wd.add_widget<widget_filer>(wp, wp_);
				load_ctx_->enable(false);
			}

			{	// ターミナル
				{
					widget::param wp(vtx::irect(20, 100, 100, 200));
					widget_frame::param wp_;
					wp_.plate_param_.set_caption(12);
					terminal_frame_ = wd.add_widget<widget_frame>(wp, wp_);
				}
				{
					widget::param wp(vtx::irect(0), terminal_frame_);
					widget_terminal::param wp_;
					wp_.enter_func_ = [this](const utils::lstring& text) {
						term_enter_(text);
					};
					terminal_core_ = wd.add_widget<widget_terminal>(wp, wp_);
					term_chaout::set_output(terminal_core_);
				}

				// ロジック編集クラスの出力先の設定
//				project_.logic_edit_.set_output([this](const std::string& s) {
//					terminal_core_->output(s);
//				}
//				);
			}

			{	// 波形ビュー
				{
					widget::param wp(vtx::irect(40, 150, 200, 200));
					widget_frame::param wp_;
					wp_.plate_param_.set_caption(12);
					view_frame_ = wd.add_widget<widget_frame>(wp, wp_);
				}
				{
					widget::param wp(vtx::irect(0), view_frame_);
					widget_view::param wp_;
					wp_.update_func_ = [this]() {
						update_view_();
					};
					wp_.render_func_ = [this](const vtx::irect& clip) {
						render_view_(clip);
					};
					wp_.service_func_ = [this]() {
						service_view_();
					};
					view_core_ = wd.add_widget<widget_view>(wp, wp_);
				}
			}

			// プリファレンスのロード
			sys::preference& pre = director_.at().preference_;

			if(menu_ != nullptr) {
				menu_->load(pre, false, false);
			}

///			project_.load(pre);

			if(terminal_frame_ != nullptr) {
				terminal_frame_->load(pre);
			}

			if(view_frame_ != nullptr) {
				view_frame_->load(pre);
			}

//			if(argv_frame_ != nullptr) {
//				argv_frame_->load(pre);
//			}

			if(load_ctx_ != nullptr) load_ctx_->load(pre);
///			if(save_ctx_ != nullptr) save_ctx_->load(pre);

///			if(edit_ != nullptr) edit_->load(pre);

			// テスト・サーバー起動
			server_.start();

			// テスト波形生成
			waves_.create_waves(0.5, 5.0 * 10e-6);
			waves_.create_sin(1000, 5 * 10e-6);
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  アップデート
		*/
		//-----------------------------------------------------------------//
		void update()
		{
			if(start_client_) {
				client_.service();
			} else {
				client_.start();
				start_client_ = true;
			}
			server_.service();
			io_service_.run();

			gui::widget_director& wd = director_.at().widget_director_;
#if 0
			// Drag & Drop されたファイル
			gl::core& core = gl::core::get_instance();
			int id = core.get_recv_files_id();
			if(drop_file_id_ != id) {
				drop_file_id_ = id;
				const utils::strings& ss = core.get_recv_files_path();
				if(!ss.empty()) {
					std::string path = ss[0];
					if(load_ctx_ != nullptr && load_ctx_->get_local_param().select_file_func_ != nullptr) {
						load_ctx_->get_local_param().select_file_func_(path);
					}
				}
			}
#endif
			wd.update();
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  レンダリング
		*/
		//-----------------------------------------------------------------//
		void render()
		{
			director_.at().widget_director_.service();
			director_.at().widget_director_.render();
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  廃棄
		*/
		//-----------------------------------------------------------------//
		void destroy()
		{
			sys::preference& pre = director_.at().preference_;

///			if(edit_ != nullptr) edit_->save(pre);

			if(load_ctx_ != nullptr) load_ctx_->save(pre);
///			if(save_ctx_ != nullptr) save_ctx_->save(pre);

//			if(argv_frame_ != nullptr) {
//				argv_frame_->save(pre);
//			}

			if(view_frame_ != nullptr) {
				view_frame_->save(pre);
			}

			if(terminal_frame_ != nullptr) {
				terminal_frame_->save(pre);
			}

//			project_.save(pre);

			if(menu_ != nullptr) {
				menu_->save(pre);
			}
		}
	};
}
<|endoftext|>