<commit_before>/*!
 * FrameReceiverRxThreadUnitTest.cpp
 *
 *  Created on: Feb 5, 2015
 *      Author: Tim Nicholls, STFC Application Engineering Group
 */

#include <boost/test/unit_test.hpp>

#include "FrameReceiverUDPRxThread.h"
#include "IpcMessage.h"
#include "SharedBufferManager.h"
#include "FrameDecoder.h"
#include "PercivalEmulatorFrameDecoder.h"

#include <log4cxx/logger.h>
#include <log4cxx/consoleappender.h>
#include <log4cxx/basicconfigurator.h>
#include <log4cxx/simplelayout.h>

namespace FrameReceiver
{
    class FrameReceiverRxThreadTestProxy
    {
    public:
        FrameReceiverRxThreadTestProxy(FrameReceiver::FrameReceiverConfig& config) :
            config_(config)
        {
            // Override default RX buffer size on OS X as Linux default
            // is too large for test to pass
#ifdef __MACH__
            config_.rx_recv_buffer_size_ = 1048576;
#endif
        }

        std::string& get_rx_channel_endpoint(void)
        {
            return config_.rx_channel_endpoint_;
        }
    private:
        FrameReceiver::FrameReceiverConfig& config_;
    };
}
class FrameReceiverRxThreadTestFixture
{
public:
    FrameReceiverRxThreadTestFixture() :
        rx_channel(ZMQ_PAIR),
        logger(log4cxx::Logger::getLogger("FrameReceiverRxThreadUnitTest")),
        proxy(config),
        frame_decoder(new FrameReceiver::PercivalEmulatorFrameDecoder()),
        buffer_manager(new OdinData::SharedBufferManager("TestSharedBuffer", 10000, 1000))
    {
    	frame_decoder->init(logger);

        BOOST_TEST_MESSAGE("Setup test fixture");

        // Bind the endpoint of the channel to communicate with the RX thread
        rx_channel.bind(proxy.get_rx_channel_endpoint());

        // Create a log4cxx console appender so that thread messages can be printed, suppress debug messages
        log4cxx::ConsoleAppender* consoleAppender = new log4cxx::ConsoleAppender(log4cxx::LayoutPtr(new log4cxx::SimpleLayout()));
        log4cxx::helpers::Pool p;
        consoleAppender->activateOptions(p);
        log4cxx::BasicConfigurator::configure(log4cxx::AppenderPtr(consoleAppender));
        log4cxx::Logger::getRootLogger()->setLevel(log4cxx::Level::getInfo());
    }

    ~FrameReceiverRxThreadTestFixture()
    {
        BOOST_TEST_MESSAGE("Tear down test fixture");
    }

    OdinData::IpcChannel rx_channel;
    FrameReceiver::FrameReceiverConfig config;
    log4cxx::LoggerPtr logger;
    FrameReceiver::FrameReceiverRxThreadTestProxy proxy;
    FrameReceiver::FrameDecoderPtr frame_decoder;
    OdinData::SharedBufferManagerPtr buffer_manager;
};

BOOST_FIXTURE_TEST_SUITE(FrameReceiverRxThreadUnitTest, FrameReceiverRxThreadTestFixture);

BOOST_AUTO_TEST_CASE( CreateAndPingRxThread )
{

    bool initOK = true;

    try {
    	FrameReceiver::FrameReceiverUDPRxThread rxThread(config, logger, buffer_manager, frame_decoder, 1);
    	rxThread.start();
        OdinData::IpcMessage::MsgType msg_type = OdinData::IpcMessage::MsgTypeCmd;
        OdinData::IpcMessage::MsgVal  msg_val =  OdinData::IpcMessage::MsgValCmdStatus;

        int loopCount = 500;
        int replyCount = 0;
        int timeoutCount = 0;
        bool msgMatch = true;

        for (int loop = 0; loop < loopCount; loop++)
        {
            OdinData::IpcMessage message(msg_type, msg_val);
            message.set_param<int>("count", loop);
            rx_channel.send(message.encode());
        }

        while ((replyCount < loopCount) && (timeoutCount < 10))
        {
            if (rx_channel.poll(100))
            {
                std::string reply = rx_channel.recv();

                OdinData::IpcMessage response(reply.c_str());
                msgMatch &= (response.get_msg_type() == OdinData::IpcMessage::MsgTypeAck);
                msgMatch &= (response.get_msg_val() == OdinData::IpcMessage::MsgValCmdStatus);
                msgMatch &= (response.get_param<int>("count", -1) == replyCount);
                replyCount++;
                timeoutCount = 0;
            }
            else
            {
                timeoutCount++;
            }
        }
        rxThread.stop();
        BOOST_CHECK_EQUAL(msgMatch, true);
        BOOST_CHECK_EQUAL(loopCount, replyCount);
        BOOST_CHECK_EQUAL(timeoutCount, 0);
        }
    catch (OdinData::OdinDataException& e)
    {
        initOK = false;
        BOOST_TEST_MESSAGE("Creation of FrameReceiverRxThread failed: " << e.what());
    }
    BOOST_REQUIRE_EQUAL(initOK, true);

}

BOOST_AUTO_TEST_SUITE_END();

<commit_msg>Temporarily excluded RxThread unit test cases from compiliation.<commit_after>/*!
 * FrameReceiverRxThreadUnitTest.cpp
 *
 *  Created on: Feb 5, 2015
 *      Author: Tim Nicholls, STFC Application Engineering Group
 */

#include <boost/test/unit_test.hpp>

#ifdef FRAMERECEIVER_HAS_DUMMY_DECODER

#include "FrameReceiverUDPRxThread.h"
#include "IpcMessage.h"
#include "SharedBufferManager.h"
#include "FrameDecoder.h"
#include "PercivalEmulatorFrameDecoder.h"

#include <log4cxx/logger.h>
#include <log4cxx/consoleappender.h>
#include <log4cxx/basicconfigurator.h>
#include <log4cxx/simplelayout.h>

namespace FrameReceiver
{
    class FrameReceiverRxThreadTestProxy
    {
    public:
        FrameReceiverRxThreadTestProxy(FrameReceiver::FrameReceiverConfig& config) :
            config_(config)
        {
            // Override default RX buffer size on OS X as Linux default
            // is too large for test to pass
#ifdef __MACH__
            config_.rx_recv_buffer_size_ = 1048576;
#endif
        }

        std::string& get_rx_channel_endpoint(void)
        {
            return config_.rx_channel_endpoint_;
        }
    private:
        FrameReceiver::FrameReceiverConfig& config_;
    };
}
class FrameReceiverRxThreadTestFixture
{
public:
    FrameReceiverRxThreadTestFixture() :
        rx_channel(ZMQ_PAIR),
        logger(log4cxx::Logger::getLogger("FrameReceiverRxThreadUnitTest")),
        proxy(config),
        frame_decoder(new FrameReceiver::PercivalEmulatorFrameDecoder()),
        buffer_manager(new OdinData::SharedBufferManager("TestSharedBuffer", 10000, 1000))
    {
    	frame_decoder->init(logger);

        BOOST_TEST_MESSAGE("Setup test fixture");

        // Bind the endpoint of the channel to communicate with the RX thread
        rx_channel.bind(proxy.get_rx_channel_endpoint());

        // Create a log4cxx console appender so that thread messages can be printed, suppress debug messages
        log4cxx::ConsoleAppender* consoleAppender = new log4cxx::ConsoleAppender(log4cxx::LayoutPtr(new log4cxx::SimpleLayout()));
        log4cxx::helpers::Pool p;
        consoleAppender->activateOptions(p);
        log4cxx::BasicConfigurator::configure(log4cxx::AppenderPtr(consoleAppender));
        log4cxx::Logger::getRootLogger()->setLevel(log4cxx::Level::getInfo());
    }

    ~FrameReceiverRxThreadTestFixture()
    {
        BOOST_TEST_MESSAGE("Tear down test fixture");
    }

    OdinData::IpcChannel rx_channel;
    FrameReceiver::FrameReceiverConfig config;
    log4cxx::LoggerPtr logger;
    FrameReceiver::FrameReceiverRxThreadTestProxy proxy;
    FrameReceiver::FrameDecoderPtr frame_decoder;
    OdinData::SharedBufferManagerPtr buffer_manager;
};

BOOST_FIXTURE_TEST_SUITE(FrameReceiverRxThreadUnitTest, FrameReceiverRxThreadTestFixture);

BOOST_AUTO_TEST_CASE( CreateAndPingRxThread )
{

    bool initOK = true;

    try {
    	FrameReceiver::FrameReceiverUDPRxThread rxThread(config, logger, buffer_manager, frame_decoder, 1);
    	rxThread.start();
        OdinData::IpcMessage::MsgType msg_type = OdinData::IpcMessage::MsgTypeCmd;
        OdinData::IpcMessage::MsgVal  msg_val =  OdinData::IpcMessage::MsgValCmdStatus;

        int loopCount = 500;
        int replyCount = 0;
        int timeoutCount = 0;
        bool msgMatch = true;

        for (int loop = 0; loop < loopCount; loop++)
        {
            OdinData::IpcMessage message(msg_type, msg_val);
            message.set_param<int>("count", loop);
            rx_channel.send(message.encode());
        }

        while ((replyCount < loopCount) && (timeoutCount < 10))
        {
            if (rx_channel.poll(100))
            {
                std::string reply = rx_channel.recv();

                OdinData::IpcMessage response(reply.c_str());
                msgMatch &= (response.get_msg_type() == OdinData::IpcMessage::MsgTypeAck);
                msgMatch &= (response.get_msg_val() == OdinData::IpcMessage::MsgValCmdStatus);
                msgMatch &= (response.get_param<int>("count", -1) == replyCount);
                replyCount++;
                timeoutCount = 0;
            }
            else
            {
                timeoutCount++;
            }
        }
        rxThread.stop();
        BOOST_CHECK_EQUAL(msgMatch, true);
        BOOST_CHECK_EQUAL(loopCount, replyCount);
        BOOST_CHECK_EQUAL(timeoutCount, 0);
        }
    catch (OdinData::OdinDataException& e)
    {
        initOK = false;
        BOOST_TEST_MESSAGE("Creation of FrameReceiverRxThread failed: " << e.what());
    }
    BOOST_REQUIRE_EQUAL(initOK, true);

}

BOOST_AUTO_TEST_SUITE_END();
#else
#warning No RxThread unit tests being compiled due to absence of dummy decoder
#endif

<|endoftext|>


<commit_before>// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#define FML_USED_ON_EMBEDDER

#include "flutter/shell/common/shell_test.h"
#include "flutter/shell/common/shell_test_platform_view.h"

#include "flutter/flow/layers/layer_tree.h"
#include "flutter/flow/layers/transform_layer.h"
#include "flutter/fml/make_copyable.h"
#include "flutter/fml/mapping.h"
#include "flutter/runtime/dart_vm.h"
#include "flutter/shell/common/vsync_waiter_fallback.h"
#include "flutter/testing/testing.h"

namespace flutter {
namespace testing {

ShellTest::ShellTest()
    : native_resolver_(std::make_shared<TestDartNativeResolver>()),
      thread_host_("io.flutter.test." + GetCurrentTestName() + ".",
                   ThreadHost::Type::Platform | ThreadHost::Type::IO |
                       ThreadHost::Type::UI | ThreadHost::Type::GPU),
      assets_dir_(fml::OpenDirectory(GetFixturesPath(),
                                     false,
                                     fml::FilePermission::kRead)),
      aot_symbols_(LoadELFSymbolFromFixturesIfNeccessary()) {}

void ShellTest::SendEnginePlatformMessage(
    Shell* shell,
    fml::RefPtr<PlatformMessage> message) {
  fml::AutoResetWaitableEvent latch;
  fml::TaskRunner::RunNowOrPostTask(
      shell->GetTaskRunners().GetPlatformTaskRunner(),
      [shell, &latch, message = std::move(message)]() {
        if (auto engine = shell->weak_engine_) {
          engine->HandlePlatformMessage(std::move(message));
        }
        latch.Signal();
      });
  latch.Wait();
}

void ShellTest::SetSnapshotsAndAssets(Settings& settings) {
  if (!assets_dir_.is_valid()) {
    return;
  }

  settings.assets_dir = assets_dir_.get();

  // In JIT execution, all snapshots are present within the binary itself and
  // don't need to be explicitly suppiled by the embedder.
  if (DartVM::IsRunningPrecompiledCode()) {
    PrepareSettingsForAOTWithSymbols(settings, aot_symbols_);
  } else {
    settings.application_kernels = [this]() {
      std::vector<std::unique_ptr<const fml::Mapping>> kernel_mappings;
      kernel_mappings.emplace_back(
          fml::FileMapping::CreateReadOnly(assets_dir_, "kernel_blob.bin"));
      return kernel_mappings;
    };
  }
}

void ShellTest::PlatformViewNotifyCreated(Shell* shell) {
  fml::AutoResetWaitableEvent latch;
  fml::TaskRunner::RunNowOrPostTask(
      shell->GetTaskRunners().GetPlatformTaskRunner(), [shell, &latch]() {
        shell->GetPlatformView()->NotifyCreated();
        latch.Signal();
      });
  latch.Wait();
}

void ShellTest::RunEngine(Shell* shell, RunConfiguration configuration) {
  fml::AutoResetWaitableEvent latch;
  fml::TaskRunner::RunNowOrPostTask(
      shell->GetTaskRunners().GetPlatformTaskRunner(),
      [shell, &latch, &configuration]() {
        shell->RunEngine(std::move(configuration),
                         [&latch](Engine::RunStatus run_status) {
                           ASSERT_EQ(run_status, Engine::RunStatus::Success);
                           latch.Signal();
                         });
      });
  latch.Wait();
}

void ShellTest::RestartEngine(Shell* shell, RunConfiguration configuration) {
  std::promise<bool> restarted;
  fml::TaskRunner::RunNowOrPostTask(
      shell->GetTaskRunners().GetUITaskRunner(),
      [shell, &restarted, &configuration]() {
        restarted.set_value(shell->engine_->Restart(std::move(configuration)));
      });
  ASSERT_TRUE(restarted.get_future().get());
}

void ShellTest::VSyncFlush(Shell* shell, bool& will_draw_new_frame) {
  fml::AutoResetWaitableEvent latch;
  shell->GetTaskRunners().GetPlatformTaskRunner()->PostTask(
      [shell, &will_draw_new_frame, &latch] {
        // The following UI task ensures that all previous UI tasks are flushed.
        fml::AutoResetWaitableEvent ui_latch;
        shell->GetTaskRunners().GetUITaskRunner()->PostTask(
            [&ui_latch, &will_draw_new_frame]() {
              will_draw_new_frame = true;
              ui_latch.Signal();
            });

        ShellTestPlatformView* test_platform_view =
            static_cast<ShellTestPlatformView*>(shell->GetPlatformView().get());
        do {
          test_platform_view->SimulateVSync();
        } while (ui_latch.WaitWithTimeout(fml::TimeDelta::FromMilliseconds(1)));

        latch.Signal();
      });
  latch.Wait();
}

void ShellTest::PumpOneFrame(Shell* shell,
                             double width,
                             double height,
                             LayerTreeBuilder builder) {
  PumpOneFrame(shell,
               flutter::ViewportMetrics{1, width, height, flutter::kUnsetDepth,
                                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
               std::move(builder));
}

void ShellTest::PumpOneFrame(Shell* shell,
                             flutter::ViewportMetrics viewport_metrics,
                             LayerTreeBuilder builder) {
  // Set viewport to nonempty, and call Animator::BeginFrame to make the layer
  // tree pipeline nonempty. Without either of this, the layer tree below
  // won't be rasterized.
  fml::AutoResetWaitableEvent latch;
  shell->GetTaskRunners().GetUITaskRunner()->PostTask(
      [&latch, engine = shell->weak_engine_, viewport_metrics]() {
        engine->SetViewportMetrics(std::move(viewport_metrics));
        const auto frame_begin_time = fml::TimePoint::Now();
        const auto frame_end_time =
            frame_begin_time + fml::TimeDelta::FromSecondsF(1.0 / 60.0);
        engine->animator_->BeginFrame(frame_begin_time, frame_end_time);
        latch.Signal();
      });
  latch.Wait();

  latch.Reset();
  // Call |Render| to rasterize a layer tree and trigger |OnFrameRasterized|
  fml::WeakPtr<RuntimeDelegate> runtime_delegate = shell->weak_engine_;
  shell->GetTaskRunners().GetUITaskRunner()->PostTask(
      [&latch, runtime_delegate, &builder, viewport_metrics]() {
        auto layer_tree = std::make_unique<LayerTree>(
            SkISize::Make(viewport_metrics.physical_width,
                          viewport_metrics.physical_height),
            static_cast<float>(viewport_metrics.physical_depth),
            static_cast<float>(viewport_metrics.device_pixel_ratio));
        SkMatrix identity;
        identity.setIdentity();
        auto root_layer = std::make_shared<TransformLayer>(identity);
        layer_tree->set_root_layer(root_layer);
        if (builder) {
          builder(root_layer);
        }
        runtime_delegate->Render(std::move(layer_tree));
        latch.Signal();
      });
  latch.Wait();
}

void ShellTest::DispatchFakePointerData(Shell* shell) {
  auto packet = std::make_unique<PointerDataPacket>(1);
  DispatchPointerData(shell, std::move(packet));
}

void ShellTest::DispatchPointerData(Shell* shell,
                                    std::unique_ptr<PointerDataPacket> packet) {
  fml::AutoResetWaitableEvent latch;
  shell->GetTaskRunners().GetPlatformTaskRunner()->PostTask(
      [&latch, shell, &packet]() {
        // Goes through PlatformView to ensure packet is corrected converted.
        shell->GetPlatformView()->DispatchPointerDataPacket(std::move(packet));
        latch.Signal();
      });
  latch.Wait();
}

int ShellTest::UnreportedTimingsCount(Shell* shell) {
  return shell->unreported_timings_.size();
}

void ShellTest::SetNeedsReportTimings(Shell* shell, bool value) {
  shell->SetNeedsReportTimings(value);
}

bool ShellTest::GetNeedsReportTimings(Shell* shell) {
  return shell->needs_report_timings_;
}

std::shared_ptr<txt::FontCollection> ShellTest::GetFontCollection(
    Shell* shell) {
  return shell->weak_engine_->GetFontCollection().GetFontCollection();
}

Settings ShellTest::CreateSettingsForFixture() {
  Settings settings;
  settings.leak_vm = false;
  settings.task_observer_add = [](intptr_t key, fml::closure handler) {
    fml::MessageLoop::GetCurrent().AddTaskObserver(key, handler);
  };
  settings.task_observer_remove = [](intptr_t key) {
    fml::MessageLoop::GetCurrent().RemoveTaskObserver(key);
  };
  settings.isolate_create_callback = [this]() {
    native_resolver_->SetNativeResolverForIsolate();
  };
  SetSnapshotsAndAssets(settings);
  return settings;
}

TaskRunners ShellTest::GetTaskRunnersForFixture() {
  return {
      "test",
      thread_host_.platform_thread->GetTaskRunner(),  // platform
      thread_host_.gpu_thread->GetTaskRunner(),       // gpu
      thread_host_.ui_thread->GetTaskRunner(),        // ui
      thread_host_.io_thread->GetTaskRunner()         // io
  };
}

std::unique_ptr<Shell> ShellTest::CreateShell(Settings settings,
                                              bool simulate_vsync) {
  return CreateShell(std::move(settings), GetTaskRunnersForFixture(),
                     simulate_vsync);
}

std::unique_ptr<Shell> ShellTest::CreateShell(Settings settings,
                                              TaskRunners task_runners,
                                              bool simulate_vsync) {
  const auto vsync_clock = std::make_shared<ShellTestVsyncClock>();
  CreateVsyncWaiter create_vsync_waiter = [&]() {
    if (simulate_vsync) {
      return static_cast<std::unique_ptr<VsyncWaiter>>(
          std::make_unique<ShellTestVsyncWaiter>(task_runners, vsync_clock));
    } else {
      return static_cast<std::unique_ptr<VsyncWaiter>>(
          std::make_unique<VsyncWaiterFallback>(task_runners));
    }
  };
  return Shell::Create(
      task_runners, settings,
      [vsync_clock, &create_vsync_waiter](Shell& shell) {
        return ShellTestPlatformView::Create(
            shell, shell.GetTaskRunners(), vsync_clock,
            std::move(create_vsync_waiter),
            ShellTestPlatformView::BackendType::kDefaultBackend);
      },
      [](Shell& shell) {
        return std::make_unique<Rasterizer>(shell, shell.GetTaskRunners());
      });
}

void ShellTest::DestroyShell(std::unique_ptr<Shell> shell) {
  DestroyShell(std::move(shell), GetTaskRunnersForFixture());
}

void ShellTest::DestroyShell(std::unique_ptr<Shell> shell,
                             TaskRunners task_runners) {
  fml::AutoResetWaitableEvent latch;
  fml::TaskRunner::RunNowOrPostTask(task_runners.GetPlatformTaskRunner(),
                                    [&shell, &latch]() mutable {
                                      shell.reset();
                                      latch.Signal();
                                    });
  latch.Wait();
}

void ShellTest::AddNativeCallback(std::string name,
                                  Dart_NativeFunction callback) {
  native_resolver_->AddNativeCallback(std::move(name), callback);
}

}  // namespace testing
}  // namespace flutter
<commit_msg>Enable verbose logging for shell unittests on Fuchsia (#16526)<commit_after>// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#define FML_USED_ON_EMBEDDER

#include "flutter/shell/common/shell_test.h"
#include "flutter/shell/common/shell_test_platform_view.h"

#include "flutter/flow/layers/layer_tree.h"
#include "flutter/flow/layers/transform_layer.h"
#include "flutter/fml/build_config.h"
#include "flutter/fml/make_copyable.h"
#include "flutter/fml/mapping.h"
#include "flutter/runtime/dart_vm.h"
#include "flutter/shell/common/vsync_waiter_fallback.h"
#include "flutter/testing/testing.h"

namespace flutter {
namespace testing {

ShellTest::ShellTest()
    : native_resolver_(std::make_shared<TestDartNativeResolver>()),
      thread_host_("io.flutter.test." + GetCurrentTestName() + ".",
                   ThreadHost::Type::Platform | ThreadHost::Type::IO |
                       ThreadHost::Type::UI | ThreadHost::Type::GPU),
      assets_dir_(fml::OpenDirectory(GetFixturesPath(),
                                     false,
                                     fml::FilePermission::kRead)),
      aot_symbols_(LoadELFSymbolFromFixturesIfNeccessary()) {}

void ShellTest::SendEnginePlatformMessage(
    Shell* shell,
    fml::RefPtr<PlatformMessage> message) {
  fml::AutoResetWaitableEvent latch;
  fml::TaskRunner::RunNowOrPostTask(
      shell->GetTaskRunners().GetPlatformTaskRunner(),
      [shell, &latch, message = std::move(message)]() {
        if (auto engine = shell->weak_engine_) {
          engine->HandlePlatformMessage(std::move(message));
        }
        latch.Signal();
      });
  latch.Wait();
}

void ShellTest::SetSnapshotsAndAssets(Settings& settings) {
  if (!assets_dir_.is_valid()) {
    return;
  }

  settings.assets_dir = assets_dir_.get();

  // In JIT execution, all snapshots are present within the binary itself and
  // don't need to be explicitly suppiled by the embedder.
  if (DartVM::IsRunningPrecompiledCode()) {
    PrepareSettingsForAOTWithSymbols(settings, aot_symbols_);
  } else {
    settings.application_kernels = [this]() {
      std::vector<std::unique_ptr<const fml::Mapping>> kernel_mappings;
      kernel_mappings.emplace_back(
          fml::FileMapping::CreateReadOnly(assets_dir_, "kernel_blob.bin"));
      return kernel_mappings;
    };
  }
}

void ShellTest::PlatformViewNotifyCreated(Shell* shell) {
  fml::AutoResetWaitableEvent latch;
  fml::TaskRunner::RunNowOrPostTask(
      shell->GetTaskRunners().GetPlatformTaskRunner(), [shell, &latch]() {
        shell->GetPlatformView()->NotifyCreated();
        latch.Signal();
      });
  latch.Wait();
}

void ShellTest::RunEngine(Shell* shell, RunConfiguration configuration) {
  fml::AutoResetWaitableEvent latch;
  fml::TaskRunner::RunNowOrPostTask(
      shell->GetTaskRunners().GetPlatformTaskRunner(),
      [shell, &latch, &configuration]() {
        shell->RunEngine(std::move(configuration),
                         [&latch](Engine::RunStatus run_status) {
                           ASSERT_EQ(run_status, Engine::RunStatus::Success);
                           latch.Signal();
                         });
      });
  latch.Wait();
}

void ShellTest::RestartEngine(Shell* shell, RunConfiguration configuration) {
  std::promise<bool> restarted;
  fml::TaskRunner::RunNowOrPostTask(
      shell->GetTaskRunners().GetUITaskRunner(),
      [shell, &restarted, &configuration]() {
        restarted.set_value(shell->engine_->Restart(std::move(configuration)));
      });
  ASSERT_TRUE(restarted.get_future().get());
}

void ShellTest::VSyncFlush(Shell* shell, bool& will_draw_new_frame) {
  fml::AutoResetWaitableEvent latch;
  shell->GetTaskRunners().GetPlatformTaskRunner()->PostTask(
      [shell, &will_draw_new_frame, &latch] {
        // The following UI task ensures that all previous UI tasks are flushed.
        fml::AutoResetWaitableEvent ui_latch;
        shell->GetTaskRunners().GetUITaskRunner()->PostTask(
            [&ui_latch, &will_draw_new_frame]() {
              will_draw_new_frame = true;
              ui_latch.Signal();
            });

        ShellTestPlatformView* test_platform_view =
            static_cast<ShellTestPlatformView*>(shell->GetPlatformView().get());
        do {
          test_platform_view->SimulateVSync();
        } while (ui_latch.WaitWithTimeout(fml::TimeDelta::FromMilliseconds(1)));

        latch.Signal();
      });
  latch.Wait();
}

void ShellTest::PumpOneFrame(Shell* shell,
                             double width,
                             double height,
                             LayerTreeBuilder builder) {
  PumpOneFrame(shell,
               flutter::ViewportMetrics{1, width, height, flutter::kUnsetDepth,
                                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
               std::move(builder));
}

void ShellTest::PumpOneFrame(Shell* shell,
                             flutter::ViewportMetrics viewport_metrics,
                             LayerTreeBuilder builder) {
  // Set viewport to nonempty, and call Animator::BeginFrame to make the layer
  // tree pipeline nonempty. Without either of this, the layer tree below
  // won't be rasterized.
  fml::AutoResetWaitableEvent latch;
  shell->GetTaskRunners().GetUITaskRunner()->PostTask(
      [&latch, engine = shell->weak_engine_, viewport_metrics]() {
        engine->SetViewportMetrics(std::move(viewport_metrics));
        const auto frame_begin_time = fml::TimePoint::Now();
        const auto frame_end_time =
            frame_begin_time + fml::TimeDelta::FromSecondsF(1.0 / 60.0);
        engine->animator_->BeginFrame(frame_begin_time, frame_end_time);
        latch.Signal();
      });
  latch.Wait();

  latch.Reset();
  // Call |Render| to rasterize a layer tree and trigger |OnFrameRasterized|
  fml::WeakPtr<RuntimeDelegate> runtime_delegate = shell->weak_engine_;
  shell->GetTaskRunners().GetUITaskRunner()->PostTask(
      [&latch, runtime_delegate, &builder, viewport_metrics]() {
        auto layer_tree = std::make_unique<LayerTree>(
            SkISize::Make(viewport_metrics.physical_width,
                          viewport_metrics.physical_height),
            static_cast<float>(viewport_metrics.physical_depth),
            static_cast<float>(viewport_metrics.device_pixel_ratio));
        SkMatrix identity;
        identity.setIdentity();
        auto root_layer = std::make_shared<TransformLayer>(identity);
        layer_tree->set_root_layer(root_layer);
        if (builder) {
          builder(root_layer);
        }
        runtime_delegate->Render(std::move(layer_tree));
        latch.Signal();
      });
  latch.Wait();
}

void ShellTest::DispatchFakePointerData(Shell* shell) {
  auto packet = std::make_unique<PointerDataPacket>(1);
  DispatchPointerData(shell, std::move(packet));
}

void ShellTest::DispatchPointerData(Shell* shell,
                                    std::unique_ptr<PointerDataPacket> packet) {
  fml::AutoResetWaitableEvent latch;
  shell->GetTaskRunners().GetPlatformTaskRunner()->PostTask(
      [&latch, shell, &packet]() {
        // Goes through PlatformView to ensure packet is corrected converted.
        shell->GetPlatformView()->DispatchPointerDataPacket(std::move(packet));
        latch.Signal();
      });
  latch.Wait();
}

int ShellTest::UnreportedTimingsCount(Shell* shell) {
  return shell->unreported_timings_.size();
}

void ShellTest::SetNeedsReportTimings(Shell* shell, bool value) {
  shell->SetNeedsReportTimings(value);
}

bool ShellTest::GetNeedsReportTimings(Shell* shell) {
  return shell->needs_report_timings_;
}

std::shared_ptr<txt::FontCollection> ShellTest::GetFontCollection(
    Shell* shell) {
  return shell->weak_engine_->GetFontCollection().GetFontCollection();
}

Settings ShellTest::CreateSettingsForFixture() {
  Settings settings;
  settings.leak_vm = false;
  settings.task_observer_add = [](intptr_t key, fml::closure handler) {
    fml::MessageLoop::GetCurrent().AddTaskObserver(key, handler);
  };
  settings.task_observer_remove = [](intptr_t key) {
    fml::MessageLoop::GetCurrent().RemoveTaskObserver(key);
  };
  settings.isolate_create_callback = [this]() {
    native_resolver_->SetNativeResolverForIsolate();
  };
#if OS_FUCHSIA
  settings.verbose_logging = true;
#endif
  SetSnapshotsAndAssets(settings);
  return settings;
}

TaskRunners ShellTest::GetTaskRunnersForFixture() {
  return {
      "test",
      thread_host_.platform_thread->GetTaskRunner(),  // platform
      thread_host_.gpu_thread->GetTaskRunner(),       // gpu
      thread_host_.ui_thread->GetTaskRunner(),        // ui
      thread_host_.io_thread->GetTaskRunner()         // io
  };
}

std::unique_ptr<Shell> ShellTest::CreateShell(Settings settings,
                                              bool simulate_vsync) {
  return CreateShell(std::move(settings), GetTaskRunnersForFixture(),
                     simulate_vsync);
}

std::unique_ptr<Shell> ShellTest::CreateShell(Settings settings,
                                              TaskRunners task_runners,
                                              bool simulate_vsync) {
  const auto vsync_clock = std::make_shared<ShellTestVsyncClock>();
  CreateVsyncWaiter create_vsync_waiter = [&]() {
    if (simulate_vsync) {
      return static_cast<std::unique_ptr<VsyncWaiter>>(
          std::make_unique<ShellTestVsyncWaiter>(task_runners, vsync_clock));
    } else {
      return static_cast<std::unique_ptr<VsyncWaiter>>(
          std::make_unique<VsyncWaiterFallback>(task_runners));
    }
  };
  return Shell::Create(
      task_runners, settings,
      [vsync_clock, &create_vsync_waiter](Shell& shell) {
        return ShellTestPlatformView::Create(
            shell, shell.GetTaskRunners(), vsync_clock,
            std::move(create_vsync_waiter),
            ShellTestPlatformView::BackendType::kDefaultBackend);
      },
      [](Shell& shell) {
        return std::make_unique<Rasterizer>(shell, shell.GetTaskRunners());
      });
}

void ShellTest::DestroyShell(std::unique_ptr<Shell> shell) {
  DestroyShell(std::move(shell), GetTaskRunnersForFixture());
}

void ShellTest::DestroyShell(std::unique_ptr<Shell> shell,
                             TaskRunners task_runners) {
  fml::AutoResetWaitableEvent latch;
  fml::TaskRunner::RunNowOrPostTask(task_runners.GetPlatformTaskRunner(),
                                    [&shell, &latch]() mutable {
                                      shell.reset();
                                      latch.Signal();
                                    });
  latch.Wait();
}

void ShellTest::AddNativeCallback(std::string name,
                                  Dart_NativeFunction callback) {
  native_resolver_->AddNativeCallback(std::move(name), callback);
}

}  // namespace testing
}  // namespace flutter
<|endoftext|>


<commit_before>#include "eventdispatcher.h"
#include <core/log/log.h>
#include <core/video/context.h>

namespace fd {
namespace core {
namespace event {

using namespace utils;
using namespace log;
using namespace video;

List<EventListener*> EventDispatcher::allListeners;
List<EventListener*> EventDispatcher::windowListeners;
List<EventListener*> EventDispatcher::mouseListeners;
List<EventListener*> EventDispatcher::keyboardListeners;

void EventDispatcher::DispatchEvent(const Event* const event) {
	OnEvent(event);
}

bool EventDispatcher::OnEvent(const Event* const event) {
	uint_t size = allListeners.GetSize();

	for (uint_t i = 0; i < size; i++) {
		EventListener* listener = allListeners[i];

		bool handled = listener->OnEvent(event);

		if (handled) continue;

		switch (event->type) {
			case EventType::Unknown:
				Log::Warning("[EventDispatcher] Received unknown event");
				return false;
			case EventType::InputKeyboard:
				handled = OnKeyboardEvent(listener, (KeyboardEvent*)event);
				break;
			case EventType::InputMouse:
				handled = OnMouseEvent(listener, (MouseEvent*)event);
				break;
			case EventType::Window:
				handled = OnWindowEvent(listener, (WindowEvent*)event);
				break;
		}
	}

	if (event->type == EventType::Window) {
		size = windowListeners.GetSize();

		WindowEvent* e = (WindowEvent*)event;

		for (uint_t i = 0; i < size; i++) {
			EventListener* listener = windowListeners[i];

			OnWindowEvent(listener, (WindowEvent*)event);
		}
	} else if (event->type == EventType::InputMouse) {
		size = mouseListeners.GetSize();

		for (uint_t i = 0; i < size; i++) {
			EventListener* listener = mouseListeners[i];

			OnMouseEvent(listener, (MouseEvent*)event);
		}
	} else if (event->type == EventType::InputKeyboard) {
		size = keyboardListeners.GetSize();

		for (uint_t i = 0; i < size; i++) {
			EventListener* listener = keyboardListeners[i];

			OnKeyboardEvent(listener, (KeyboardEvent*)event);
		}
	}
}

bool EventDispatcher::OnWindowEvent(EventListener* const listener, const WindowEvent* const event) {
	if (listener->OnWindowEvent(event)) return true;

	bool handled = false;

	switch (event->action) {
		case EventAction::Move:
			handled = listener->OnWindowEventMove(event->position);
			break;
		case EventAction::Resize:
			handled = listener->OnWindowEventResize(event->size);
			break;
		case EventAction::Focus:
			handled = listener->OnWindowEventFocus(event->focus);
			break;
		case EventAction::MinimizeMaximize:
			handled = listener->OnWindowEventVisiblity(event->visibility);
			break;
	}

	return handled;
}

bool EventDispatcher::OnKeyboardEvent(EventListener* const listener, const KeyboardEvent* const event) {
	if (listener->OnKeyboardEvent(event)) return true;

	bool handled = false;

	switch (event->action) {
		case EventAction::Pressed:
			handled = listener->OnKeyboardEventPressed(event->key);
			break;
		case EventAction::Released:
			handled = listener->OnKeyboardEventReleased(event->key);
			break;
	}

	return handled;
}

bool EventDispatcher::OnMouseEvent(EventListener* const listener, const MouseEvent* const event) {
	if (listener->OnMouseEvent(event)) return true;

	bool handled = false;

	switch (event->action) {
		case EventAction::Move:
			handled = listener->OnMouseEventMove(event->absolute, event->relative);
			break;
		case EventAction::Pressed:
			handled = listener->OnMouseEventPressed(event->button);
			break;
		case EventAction::Released:
			handled = listener->OnMouseEventReleased(event->button);
			break;
	}

	return handled;
}

void EventDispatcher::RegisterListener(EventListener* listener, EventListenerTypes events) {

	if (events == EventAll) {
		allListeners.Push_back(listener);
		return;
	}

	if (events & EventWindow) {
		windowListeners.Push_back(listener);
	}

	if (events & EventMouse) {
		mouseListeners.Push_back(listener);
	}

	if (events & EventKeyboard) {
		keyboardListeners.Push_back(listener);
	}
}

void EventDispatcher::UnRegisterListener(EventListener* listener, EventListenerTypes events) {
	if (events == EventAll) {
		allListeners.Remove(listener);
		return;
	}

	if (events & EventWindow) {
		windowListeners.Remove(listener);
	}

	if (events & EventMouse) {
		mouseListeners.Remove(listener);
	}

	if (events & EventKeyboard) {
		keyboardListeners.Remove(listener);
	}
}

}
}
}<commit_msg>Removed warning<commit_after>#include "eventdispatcher.h"
#include <core/log/log.h>
#include <core/video/context.h>

namespace fd {
namespace core {
namespace event {

using namespace utils;
using namespace log;
using namespace video;

List<EventListener*> EventDispatcher::allListeners;
List<EventListener*> EventDispatcher::windowListeners;
List<EventListener*> EventDispatcher::mouseListeners;
List<EventListener*> EventDispatcher::keyboardListeners;

void EventDispatcher::DispatchEvent(const Event* const event) {
	OnEvent(event);
}

bool EventDispatcher::OnEvent(const Event* const event) {
	uint_t size = allListeners.GetSize();

	for (uint_t i = 0; i < size; i++) {
		EventListener* listener = allListeners[i];

		bool handled = listener->OnEvent(event);

		if (handled) continue;

		switch (event->type) {
			case EventType::Unknown:
				Log::Warning("[EventDispatcher] Received unknown event");
				return false;
			case EventType::InputKeyboard:
				handled = OnKeyboardEvent(listener, (KeyboardEvent*)event);
				break;
			case EventType::InputMouse:
				handled = OnMouseEvent(listener, (MouseEvent*)event);
				break;
			case EventType::Window:
				handled = OnWindowEvent(listener, (WindowEvent*)event);
				break;
		}
	}

	if (event->type == EventType::Window) {
		size = windowListeners.GetSize();

		WindowEvent* e = (WindowEvent*)event;

		for (uint_t i = 0; i < size; i++) {
			EventListener* listener = windowListeners[i];

			OnWindowEvent(listener, (WindowEvent*)event);
		}
	} else if (event->type == EventType::InputMouse) {
		size = mouseListeners.GetSize();

		for (uint_t i = 0; i < size; i++) {
			EventListener* listener = mouseListeners[i];

			OnMouseEvent(listener, (MouseEvent*)event);
		}
	} else if (event->type == EventType::InputKeyboard) {
		size = keyboardListeners.GetSize();

		for (uint_t i = 0; i < size; i++) {
			EventListener* listener = keyboardListeners[i];

			OnKeyboardEvent(listener, (KeyboardEvent*)event);
		}
	}

	return true;
}

bool EventDispatcher::OnWindowEvent(EventListener* const listener, const WindowEvent* const event) {
	if (listener->OnWindowEvent(event)) return true;

	bool handled = false;

	switch (event->action) {
		case EventAction::Move:
			handled = listener->OnWindowEventMove(event->position);
			break;
		case EventAction::Resize:
			handled = listener->OnWindowEventResize(event->size);
			break;
		case EventAction::Focus:
			handled = listener->OnWindowEventFocus(event->focus);
			break;
		case EventAction::MinimizeMaximize:
			handled = listener->OnWindowEventVisiblity(event->visibility);
			break;
	}

	return handled;
}

bool EventDispatcher::OnKeyboardEvent(EventListener* const listener, const KeyboardEvent* const event) {
	if (listener->OnKeyboardEvent(event)) return true;

	bool handled = false;

	switch (event->action) {
		case EventAction::Pressed:
			handled = listener->OnKeyboardEventPressed(event->key);
			break;
		case EventAction::Released:
			handled = listener->OnKeyboardEventReleased(event->key);
			break;
	}

	return handled;
}

bool EventDispatcher::OnMouseEvent(EventListener* const listener, const MouseEvent* const event) {
	if (listener->OnMouseEvent(event)) return true;

	bool handled = false;

	switch (event->action) {
		case EventAction::Move:
			handled = listener->OnMouseEventMove(event->absolute, event->relative);
			break;
		case EventAction::Pressed:
			handled = listener->OnMouseEventPressed(event->button);
			break;
		case EventAction::Released:
			handled = listener->OnMouseEventReleased(event->button);
			break;
	}

	return handled;
}

void EventDispatcher::RegisterListener(EventListener* listener, EventListenerTypes events) {

	if (events == EventAll) {
		allListeners.Push_back(listener);
		return;
	}

	if (events & EventWindow) {
		windowListeners.Push_back(listener);
	}

	if (events & EventMouse) {
		mouseListeners.Push_back(listener);
	}

	if (events & EventKeyboard) {
		keyboardListeners.Push_back(listener);
	}
}

void EventDispatcher::UnRegisterListener(EventListener* listener, EventListenerTypes events) {
	if (events == EventAll) {
		allListeners.Remove(listener);
		return;
	}

	if (events & EventWindow) {
		windowListeners.Remove(listener);
	}

	if (events & EventMouse) {
		mouseListeners.Remove(listener);
	}

	if (events & EventKeyboard) {
		keyboardListeners.Remove(listener);
	}
}

}
}
}<|endoftext|>


<commit_before>//=============================================================================
// Copyright (c) 2017 Ryooooooga
// https://github.com/Ryooooooga
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom
// the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//=============================================================================

#include "../../Platform.hpp"
#if defined(NENE_OS_WINDOWS)

#include <iostream>
#include <Windows.h>
#include "../Console.hpp"

namespace Nene::Console
{
	bool show()
	{
		if (!::AllocConsole())
		{
			return false;
		}

		NENE_SUPPRESS_WARNING_MSVC(4996) std::freopen("CONOUT$", "w", stdout );
		NENE_SUPPRESS_WARNING_MSVC(4996) std::freopen("CONOUT$", "w", stderr );
		NENE_SUPPRESS_WARNING_MSVC(4996) std::freopen("CONIN$",  "r", stdin  );

		std::cout.clear();

		return true;
	}

	void hide()
	{
		::FreeConsole();
	}
}

#endif
<commit_msg>:bug: Fix bug.<commit_after>//=============================================================================
// Copyright (c) 2017 Ryooooooga
// https://github.com/Ryooooooga
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom
// the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//=============================================================================

#include "../../Platform.hpp"
#if defined(NENE_OS_WINDOWS)

#include <iostream>
#include <Windows.h>
#include "../Console.hpp"

namespace Nene::Console
{
	bool show()
	{
		if (!::AllocConsole())
		{
			return false;
		}

		NENE_SUPPRESS_WARNING_MSVC(4996) std::freopen("CONOUT$", "w", stdout );
		NENE_SUPPRESS_WARNING_MSVC(4996) std::freopen("CONOUT$", "w", stderr );
		NENE_SUPPRESS_WARNING_MSVC(4996) std::freopen("CONIN$",  "r", stdin  );

		std::cout.clear();
		std::cerr.clear();

		return true;
	}

	void hide()
	{
		::FreeConsole();
	}
}

#endif
<|endoftext|>


<commit_before>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// 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.

#pragma once
#ifndef NET_ETHERNET_HPP
#define NET_ETHERNET_HPP

#include <string>

#include <net/inet_common.hpp>

namespace net {

  /** Ethernet packet handling. */
  class Ethernet {
  public:
    static constexpr size_t ETHER_ADDR_LEN  = 6;
    static constexpr size_t MINIMUM_PAYLOAD = 46;

    /**
     *  Some big-endian ethernet types
     *
     *  From http://en.wikipedia.org/wiki/EtherType
     */
    enum ethertype_le {
      _ETH_IP4   = 0x0800,
      _ETH_ARP   = 0x0806,
      _ETH_WOL   = 0x0842,
      _ETH_IP6   = 0x86DD,
      _ETH_FLOW  = 0x8808,
      _ETH_JUMBO = 0x8870
    };

    /** Little-endian ethertypes. */
    enum ethertype {
      ETH_IP4   = 0x8,
      ETH_ARP   = 0x608,
      ETH_WOL   = 0x4208,
      ETH_IP6   = 0xdd86,
      ETH_FLOW  = 0x888,
      ETH_JUMBO = 0x7088,
      ETH_VLAN  = 0x81
    };

    // MAC address
    union addr {
      uint8_t part[ETHER_ADDR_LEN];

      struct {
        uint16_t minor;
        uint32_t major;
      } __attribute__((packed));

      addr& operator=(const addr cpy) noexcept {
        minor = cpy.minor;
        major = cpy.major;
        return *this;
      }

      // hex string representation
      std::string str() const {
        char eth_addr[18];
        snprintf(eth_addr, sizeof(eth_addr), "%1x:%1x:%1x:%1x:%1x:%1x",
                part[0], part[1], part[2],
                part[3], part[4], part[5]);
        return eth_addr;
      }

      /** Check for equality */
      bool operator==(const addr mac) const noexcept
      {
        return strncmp(
                       reinterpret_cast<const char*>(part),
                       reinterpret_cast<const char*>(mac.part),
                       ETHER_ADDR_LEN) == 0;
      }

      static const addr MULTICAST_FRAME;
      static const addr BROADCAST_FRAME;

      static const addr IPv6mcast_01;
      static const addr IPv6mcast_02;

    }  __attribute__((packed)); //< union addr

    /** Constructor */
    explicit Ethernet(addr mac) noexcept;

    struct header {
      addr dest;
      addr src;
      unsigned short type;

    } __attribute__((packed)) ;

    using trailer = uint32_t;

    /** Bottom upstream input, "Bottom up". Handle raw ethernet buffer. */
    void bottom(Packet_ptr);

    /** Delegate upstream ARP handler. */
    void set_arp_handler(upstream del)
    { arp_handler_ = del; }

    upstream get_arp_handler()
    { return arp_handler_; }

    /** Delegate upstream IPv4 handler. */
    void set_ip4_handler(upstream del)
    { ip4_handler_ = del; }

    /** Delegate upstream IPv4 handler. */
    upstream get_ip4_handler()
    { return ip4_handler_; }

    /** Delegate upstream IPv6 handler. */
    void set_ip6_handler(upstream del)
    { ip6_handler_ = del; };

    /** Delegate downstream */
    void set_physical_out(downstream del)
    { physical_out_ = del; }

    /** @return Mac address of the underlying device */
    const addr mac() const noexcept
    { return mac_; }

    /** Transmit data, with preallocated space for eth.header */
    void transmit(Packet_ptr);

  private:
    /** MAC address */
    addr mac_;

    /** Upstream OUTPUT connections */
    upstream ip4_handler_ = [](Packet_ptr){};
    upstream ip6_handler_ = [](Packet_ptr){};
    upstream arp_handler_ = [](Packet_ptr){};

    /** Downstream OUTPUT connection */
    downstream physical_out_ = [](Packet_ptr){};

    /*

      +--|IP4|---|ARP|---|IP6|---+
      |                          |
      |        Ethernet          |
      |                          |
      +---------|Phys|-----------+

    */
  }; //< class Ethernet
} // namespace net

#endif //< NET_ETHERNET_HPP
<commit_msg>ethernet.hpp: Fix MAC address string representation<commit_after>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// 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.

#pragma once
#ifndef NET_ETHERNET_HPP
#define NET_ETHERNET_HPP

#include <string>

#include <net/inet_common.hpp>

namespace net {

  /** Ethernet packet handling. */
  class Ethernet {
  public:
    static constexpr size_t ETHER_ADDR_LEN  = 6;
    static constexpr size_t MINIMUM_PAYLOAD = 46;

    /**
     *  Some big-endian ethernet types
     *
     *  From http://en.wikipedia.org/wiki/EtherType
     */
    enum ethertype_le {
      _ETH_IP4   = 0x0800,
      _ETH_ARP   = 0x0806,
      _ETH_WOL   = 0x0842,
      _ETH_IP6   = 0x86DD,
      _ETH_FLOW  = 0x8808,
      _ETH_JUMBO = 0x8870
    };

    /** Little-endian ethertypes. */
    enum ethertype {
      ETH_IP4   = 0x8,
      ETH_ARP   = 0x608,
      ETH_WOL   = 0x4208,
      ETH_IP6   = 0xdd86,
      ETH_FLOW  = 0x888,
      ETH_JUMBO = 0x7088,
      ETH_VLAN  = 0x81
    };

    // MAC address
    union addr {
      uint8_t part[ETHER_ADDR_LEN];

      struct {
        uint16_t minor;
        uint32_t major;
      } __attribute__((packed));

      addr& operator=(const addr cpy) noexcept {
        minor = cpy.minor;
        major = cpy.major;
        return *this;
      }

      // hex string representation
      std::string str() const {
        char eth_addr[18];
        snprintf(eth_addr, sizeof(eth_addr), "%02x:%02x:%02x:%02x:%02x:%02x",
                part[0], part[1], part[2],
                part[3], part[4], part[5]);
        return eth_addr;
      }

      /** Check for equality */
      bool operator==(const addr mac) const noexcept
      {
        return strncmp(
                       reinterpret_cast<const char*>(part),
                       reinterpret_cast<const char*>(mac.part),
                       ETHER_ADDR_LEN) == 0;
      }

      static const addr MULTICAST_FRAME;
      static const addr BROADCAST_FRAME;

      static const addr IPv6mcast_01;
      static const addr IPv6mcast_02;

    }  __attribute__((packed)); //< union addr

    /** Constructor */
    explicit Ethernet(addr mac) noexcept;

    struct header {
      addr dest;
      addr src;
      unsigned short type;

    } __attribute__((packed)) ;

    using trailer = uint32_t;

    /** Bottom upstream input, "Bottom up". Handle raw ethernet buffer. */
    void bottom(Packet_ptr);

    /** Delegate upstream ARP handler. */
    void set_arp_handler(upstream del)
    { arp_handler_ = del; }

    upstream get_arp_handler()
    { return arp_handler_; }

    /** Delegate upstream IPv4 handler. */
    void set_ip4_handler(upstream del)
    { ip4_handler_ = del; }

    /** Delegate upstream IPv4 handler. */
    upstream get_ip4_handler()
    { return ip4_handler_; }

    /** Delegate upstream IPv6 handler. */
    void set_ip6_handler(upstream del)
    { ip6_handler_ = del; };

    /** Delegate downstream */
    void set_physical_out(downstream del)
    { physical_out_ = del; }

    /** @return Mac address of the underlying device */
    const addr mac() const noexcept
    { return mac_; }

    /** Transmit data, with preallocated space for eth.header */
    void transmit(Packet_ptr);

  private:
    /** MAC address */
    addr mac_;

    /** Upstream OUTPUT connections */
    upstream ip4_handler_ = [](Packet_ptr){};
    upstream ip6_handler_ = [](Packet_ptr){};
    upstream arp_handler_ = [](Packet_ptr){};

    /** Downstream OUTPUT connection */
    downstream physical_out_ = [](Packet_ptr){};

    /*

      +--|IP4|---|ARP|---|IP6|---+
      |                          |
      |        Ethernet          |
      |                          |
      +---------|Phys|-----------+

    */
  }; //< class Ethernet
} // namespace net

#endif //< NET_ETHERNET_HPP
<|endoftext|>


<commit_before>// Copyright 2016 AUV-IITK
#include <ros.h>
#include <Arduino.h>
#include <std_msgs/Int32.h>
#include <std_msgs/Float64.h>

// /*************************** for AUV ****************************/
// #define led 13

// #define pwmPinWest 5
// #define pwmPinEast 4
// #define directionPinWest1 27
// #define directionPinWest2 26
// #define directionPinEast1 29
// #define directionPinEast2 28

// #define pwmPinNorthSway 5
// #define pwmPinSouthSway 4
// #define directionPinNorthSway1 27
// #define directionPinNorthSway2 26
// #define directionPinSouthSway1 29
// #define directionPinSouthSway2 28

// #define pwmPinNorthUp 5
// #define pwmPinSouthUp 4
// #define directionPinNorthUp1 27
// #define directionPinNorthUp2 26
// #define directionPinSouthUp1 29
// #define directionPinSouthUp2 28

/************************ for New Ground Testing Bot *******************/
#define led 13  // 13

#define pwmPinWest 5         // 3
#define pwmPinEast 2         // 2
#define directionPinWest1 6  // 31
#define directionPinWest2 7  // 30
#define directionPinEast1 3  // 33
#define directionPinEast2 4  // 32

#define pwmPinNorthSway 23         // 3
#define pwmPinSouthSway 13         // 2
#define directionPinNorthSway1 8   // 31
#define directionPinNorthSway2 9   // 30
#define directionPinSouthSway1 11  // 33
#define directionPinSouthSway2 12  // 32

#define pwmPinNorthUp 13        // 3
#define pwmPinSouthUp 13        // 2
#define directionPinNorthUp1 0  // 31
#define directionPinNorthUp2 0  // 30
#define directionPinSouthUp1 0  // 33
#define directionPinSouthUp2 0  // 32

#define analogPinPressureSensor A0
/************************ for old ground bot ******************************/
// #define pwmPinWest 4
// #define pwmPinEast 5
// #define directionPinWest1 2
// #define directionPinWest2 3
// #define directionPinEast1 7
// #define directionPinEast2 6
// #define led 13

const float c092 = 506.22;
const float s092 = -2.65;
const float c093 = 448.62;
const float s093 = -2.92;
const float c099 = 397.65;   // reference as their graph is at lowest
const float s099 = -2.71;  // reference as their graph is at lowest
const float c113 = 539.85;
const float s113 = -3.38;
const float c117 = 441.32;
const float s117 = -3.03;
const float c122 = 547.39;
const float s122 = -2.93;

int Delay = 1500;
bool isMovingForward = true;
float v;
std_msgs::Float64 voltage;
ros::NodeHandle nh;

int btd092(int pwm)
{
  pwm = (c099 + s099 * pwm - c092) / (s092);
  return pwm;
}

int btd093(int pwm)
{
  pwm = (c099 + s099 * pwm - c093) / (s093);
  return pwm;
}

int btd099(int pwm)
{
  return pwm;
}

int btd113(int pwm)
{
  pwm = (c099 + s099 * pwm - c113) / (s113);
  return pwm;
}

int btd117(int pwm)
{
  pwm = (c099 + s099 * pwm - c117) / (s117);
  return pwm;
}

int btd122(int pwm)
{
  pwm = (c099 + s099 * pwm - c122) / (s122);
  return pwm;
}

void thrusterNorthUp(int pwm, int isUpward)
{
  pwm = btd122(pwm);
  analogWrite(pwmPinNorthUp, pwm);
  if (isUpward)
  {
    digitalWrite(directionPinNorthUp1, HIGH);
    digitalWrite(directionPinNorthUp2, LOW);
  }
  else
  {
    digitalWrite(directionPinNorthUp1, LOW);
    digitalWrite(directionPinNorthUp2, HIGH);
  }
}

void thrusterSouthUp(int pwm, int isUpward)
{
  pwm = btd117(pwm);
  analogWrite(pwmPinSouthUp, pwm);
  if (isUpward)
  {
    digitalWrite(directionPinSouthUp1, HIGH);
    digitalWrite(directionPinSouthUp2, LOW);
  }
  else
  {
    digitalWrite(directionPinSouthUp1, LOW);
    digitalWrite(directionPinSouthUp2, HIGH);
  }
}

void thrusterNorthSway(int pwm, int isRight)
{
  pwm = btd113(pwm);
  analogWrite(pwmPinNorthSway, pwm);
  if (isRight)
  {
    digitalWrite(directionPinNorthSway1, HIGH);
    digitalWrite(directionPinNorthSway2, LOW);
  }
  else
  {
    digitalWrite(directionPinNorthSway1, LOW);
    digitalWrite(directionPinNorthSway2, HIGH);
  }
}

void thrusterSouthSway(int pwm, int isRight)
{
  pwm = btd099(pwm);
  analogWrite(pwmPinSouthSway, pwm);
  if (isRight)
  {
    digitalWrite(directionPinSouthSway1, HIGH);
    digitalWrite(directionPinSouthSway2, LOW);
  }
  else
  {
    digitalWrite(directionPinSouthSway1, LOW);
    digitalWrite(directionPinSouthSway2, HIGH);
  }
}

void thrusterEast(int pwm, int isForward)
{
  pwm = btd093(pwm);
  analogWrite(pwmPinEast, pwm);
  if (isForward)
  {
    digitalWrite(directionPinEast1, HIGH);
    digitalWrite(directionPinEast2, LOW);
  }
  else
  {
    digitalWrite(directionPinEast1, LOW);
    digitalWrite(directionPinEast2, HIGH);
  }
}

void thrusterWest(int pwm, int isForward)
{
  pwm = btd092(pwm);
  analogWrite(pwmPinWest, pwm);
  if (isForward)
  {
    digitalWrite(directionPinWest1, HIGH);
    digitalWrite(directionPinWest2, LOW);
  }
  else
  {
    digitalWrite(directionPinWest1, LOW);
    digitalWrite(directionPinWest2, HIGH);
  }
}

void PWMCbForward(const std_msgs::Int32& msg)
{
  if (msg.data > 0)
  {
    thrusterEast(255 - msg.data, true);
    thrusterWest(255 - msg.data, true);
  }
  else
  {
    thrusterEast(255 + msg.data, false);
    thrusterWest(255 + msg.data, false);
  }
  isMovingForward = true;
}

void PWMCbSideward(const std_msgs::Int32& msg)
{
  if (msg.data > 0)
  {
    thrusterNorthSway(255 - msg.data, true);
    thrusterSouthSway(255 - msg.data, true);
  }
  else
  {
    thrusterNorthSway(255 + msg.data, false);
    thrusterSouthSway(255 + msg.data, false);
  }
  isMovingForward = false;
}

void PWMCbUpward(const std_msgs::Int32& msg)
{
  if (msg.data > 0)
  {
    thrusterNorthUp(255 - msg.data, true);
    thrusterSouthUp(255 - msg.data, true);
  }
  else
  {
    thrusterNorthUp(255 + msg.data, false);
    thrusterSouthUp(255 + msg.data, false);
  }
}

void PWMCbTurn(const std_msgs::Int32& msg)
{
  if (isMovingForward)
  {
    if (msg.data > 0)
    {
      thrusterEast(255 - msg.data, true);
      thrusterWest(255 - msg.data, false);
    }
    else
    {
      thrusterEast(255 + msg.data, false);
      thrusterWest(255 + msg.data, true);
    }
  }
  else
  {
    if (msg.data > 0)
    {
      thrusterNorthSway(255 - msg.data, false);
      thrusterSouthSway(255 - msg.data, true);
    }
    else
    {
      thrusterNorthSway(255 + msg.data, true);
      thrusterSouthSway(255 + msg.data, false);
    }
  }
}

ros::Subscriber<std_msgs::Int32> subPwmForward("/pwm/forward", &PWMCbForward);
ros::Subscriber<std_msgs::Int32> subPwmSideward("/pwm/sideward", &PWMCbSideward);
ros::Subscriber<std_msgs::Int32> subPwmUpward("/pwm/upward", &PWMCbUpward);
ros::Subscriber<std_msgs::Int32> subPwmTurn("/pwm/turn", &PWMCbTurn);
ros::Publisher ps_voltage("zDistance", &voltage);

void setup()
{
  nh.initNode();

  pinMode(led, OUTPUT);
  pinMode(directionPinEast1, OUTPUT);
  pinMode(directionPinEast2, OUTPUT);
  pinMode(pwmPinWest, OUTPUT);
  pinMode(directionPinWest2, OUTPUT);
  pinMode(pwmPinEast, OUTPUT);
  pinMode(directionPinWest1, OUTPUT);

  pinMode(directionPinSouthSway1, OUTPUT);
  pinMode(directionPinSouthSway2, OUTPUT);
  pinMode(pwmPinNorthSway, OUTPUT);
  pinMode(directionPinNorthSway2, OUTPUT);
  pinMode(pwmPinSouthSway, OUTPUT);
  pinMode(directionPinNorthSway1, OUTPUT);

  pinMode(directionPinSouthUp1, OUTPUT);
  pinMode(directionPinSouthUp2, OUTPUT);
  pinMode(pwmPinNorthUp, OUTPUT);
  pinMode(directionPinNorthUp2, OUTPUT);
  pinMode(pwmPinSouthUp, OUTPUT);
  pinMode(directionPinNorthUp1, OUTPUT);

  nh.subscribe(subPwmForward);
  nh.subscribe(subPwmSideward);
  nh.subscribe(subPwmUpward);
  nh.subscribe(subPwmTurn);
  nh.advertise(ps_voltage);
  Serial.begin(57600);
}

void loop()
{
  v = analogRead(analogPinPressureSensor);
  voltage.data = v;
  ps_voltage.publish(&voltage);
  nh.spinOnce();
  delay(1);
}
<commit_msg>add pressure sensor, fix bugs<commit_after>// Copyright 2016 AUV-IITK
#include <ros.h>
#include <Arduino.h>
#include <std_msgs/Int32.h>
#include <std_msgs/Float64.h>
#include <math.h>

#define pwmPinWest 4
#define pwmPinEast 5
#define directionPinWest1 26
#define directionPinWest2 27
#define directionPinEast1 35
#define directionPinEast2 29

#define pwmPinNorthSway 2
#define pwmPinSouthSway 3
#define directionPinNorthSway1 31
#define directionPinNorthSway2 30
#define directionPinSouthSway1 33
#define directionPinSouthSway2 32

#define pwmPinNorthUp 6
#define pwmPinSouthUp 7
#define directionPinNorthUp1 24
#define directionPinNorthUp2 25
#define directionPinSouthUp1 22
#define directionPinSouthUp2 23

#define analogPinPressureSensor A0

const float c092 = 506.22;
const float s092 = -2.65;
const float c093 = 448.62;
const float s093 = -2.92;
const float c099 = 397.65;   // reference as their graph is at lowest
const float s099 = -2.71;  // reference as their graph is at lowest
const float c113 = 539.85;
const float s113 = -3.38;
const float c117 = 441.32;
const float s117 = -3.03;
const float c122 = 547.39;
const float s122 = -2.93;

bool isMovingForward = true;
float v;
std_msgs::Float64 voltage;
ros::NodeHandle nh;

int btd092(int pwm)
{
  pwm = (c099 + s099 * pwm - c092) / (s092);
  if(pwm<147)
    return 0;
  return pwm;
}

int btd093(int pwm)
{
  pwm = (c099 + s099 * pwm - c093) / (s093);
  if(pwm<147)
    return 0;
  return pwm;
}

int btd099(int pwm)
{
  if(pwm<147)
    return 0;
  return pwm;
}

int btd113(int pwm)
{
  pwm = (c099 + s099 * pwm - c113) / (s113);
  if(pwm<147)
    return 0;
  return pwm;
}

int btd117(int pwm)
{
  pwm = (c099 + s099 * pwm - c117) / (s117);
  if(pwm<147)
    return 0;
  return pwm;
}

int btd122(int pwm)
{
  pwm = (c099 + s099 * pwm - c122) / (s122);
  if(pwm<147)
    return 0;
  return pwm;
}

void thrusterNorthUp(int pwm, int isUpward)
{
  pwm = abs(pwm);
  pwm = btd122(pwm);
  analogWrite(pwmPinNorthUp, 255 - pwm);
  if (isUpward)
  {
    digitalWrite(directionPinNorthUp1, HIGH);
    digitalWrite(directionPinNorthUp2, LOW);
  }
  else
  {
    digitalWrite(directionPinNorthUp1, LOW);
    digitalWrite(directionPinNorthUp2, HIGH);
  }
}

void thrusterSouthUp(int pwm, int isUpward)
{
  pwm = abs(pwm);
  pwm = btd117(pwm);
  analogWrite(pwmPinSouthUp, 255 - pwm);
  if (isUpward)
  {
    digitalWrite(directionPinSouthUp1, HIGH);
    digitalWrite(directionPinSouthUp2, LOW);
  }
  else
  {
    digitalWrite(directionPinSouthUp1, LOW);
    digitalWrite(directionPinSouthUp2, HIGH);
  }
}

void thrusterNorthSway(int pwm, int isRight)
{
  pwm = abs(pwm);
  pwm = btd113(pwm);
  analogWrite(pwmPinNorthSway, 255 - pwm);
  if (isRight)
  {
    digitalWrite(directionPinNorthSway1, HIGH);
    digitalWrite(directionPinNorthSway2, LOW);
  }
  else
  {
    digitalWrite(directionPinNorthSway1, LOW);
    digitalWrite(directionPinNorthSway2, HIGH);
  }
}

void thrusterSouthSway(int pwm, int isRight)
{
  pwm = abs(pwm);
  pwm = btd099(pwm);
  analogWrite(pwmPinSouthSway, 255 - pwm);
  if (isRight)
  {
    digitalWrite(directionPinSouthSway1, HIGH);
    digitalWrite(directionPinSouthSway2, LOW);
  }
  else
  {
    digitalWrite(directionPinSouthSway1, LOW);
    digitalWrite(directionPinSouthSway2, HIGH);
  }
}

void thrusterEast(int pwm, int isForward)
{
  pwm = abs(pwm);
  pwm = btd093(pwm);
  analogWrite(pwmPinEast, 255 - pwm);
  if (isForward)
  {
    digitalWrite(directionPinEast1, HIGH);
    digitalWrite(directionPinEast2, LOW);
  }
  else
  {
    digitalWrite(directionPinEast1, LOW);
    digitalWrite(directionPinEast2, HIGH);
  }
}

void thrusterWest(int pwm, int isForward)
{
  pwm = abs(pwm);
  pwm = btd092(pwm);
  analogWrite(pwmPinWest, 255 - pwm);
  if (isForward)
  {
    digitalWrite(directionPinWest1, HIGH);
    digitalWrite(directionPinWest2, LOW);
  }
  else
  {
    digitalWrite(directionPinWest1, LOW);
    digitalWrite(directionPinWest2, HIGH);
  }
}

void PWMCbForward(const std_msgs::Int32& msg)
{
  if (msg.data > 0)
  {
    thrusterEast(msg.data, true);
    thrusterWest(msg.data, true);
  }
  else
  {
    thrusterEast(msg.data, false);
    thrusterWest(msg.data, false);
  }
  isMovingForward = true;
}

void PWMCbSideward(const std_msgs::Int32& msg)
{
  if (msg.data > 0)
  {
    thrusterNorthSway(msg.data, true);
    thrusterSouthSway(msg.data, true);
  }
  else
  {
    thrusterNorthSway(msg.data, false);
    thrusterSouthSway(msg.data, false);
  }
  isMovingForward = false;
}

void PWMCbUpward(const std_msgs::Int32& msg)
{
  if (msg.data > 0)
  {
    thrusterNorthUp(msg.data, true);
    thrusterSouthUp(msg.data, true);
  }
  else
  {
    thrusterNorthUp(msg.data, false);
    thrusterSouthUp(msg.data, false);
  }
}

void PWMCbTurn(const std_msgs::Int32& msg)
{
  if (!isMovingForward)
  {
    if (msg.data > 0)
    {
      thrusterEast(msg.data, true);
      thrusterWest(msg.data, false);
    }
    else
    {
      thrusterEast(msg.data, false);
      thrusterWest(msg.data, true);
    }
  }
  else
  {
    if (msg.data > 0)
    {
      thrusterNorthSway(msg.data, false);
      thrusterSouthSway(msg.data, true);
    }
    else
    {
      thrusterNorthSway(msg.data, true);
      thrusterSouthSway(msg.data, false);
    }
  }
}

ros::Subscriber<std_msgs::Int32> subPwmForward("/pwm/forward", &PWMCbForward);
ros::Subscriber<std_msgs::Int32> subPwmSideward("/pwm/sideward", &PWMCbSideward);
ros::Subscriber<std_msgs::Int32> subPwmUpward("/pwm/upward", &PWMCbUpward);
ros::Subscriber<std_msgs::Int32> subPwmTurn("/pwm/turn", &PWMCbTurn);
ros::Publisher ps_voltage("zDistance", &voltage);

void setup()
{
  nh.initNode();

  pinMode(pwmPinEast, OUTPUT);
  pinMode(directionPinEast1, OUTPUT);
  pinMode(directionPinEast2, OUTPUT);
  pinMode(pwmPinWest, OUTPUT);
  pinMode(directionPinWest1, OUTPUT);
  pinMode(directionPinWest2, OUTPUT);

  pinMode(directionPinSouthSway1, OUTPUT);
  pinMode(directionPinSouthSway2, OUTPUT);
  pinMode(pwmPinNorthSway, OUTPUT);
  pinMode(directionPinNorthSway2, OUTPUT);
  pinMode(pwmPinSouthSway, OUTPUT);
  pinMode(directionPinNorthSway1, OUTPUT);

  pinMode(directionPinSouthUp1, OUTPUT);
  pinMode(directionPinSouthUp2, OUTPUT);
  pinMode(pwmPinNorthUp, OUTPUT);
  pinMode(directionPinNorthUp2, OUTPUT);
  pinMode(pwmPinSouthUp, OUTPUT);
  pinMode(directionPinNorthUp1, OUTPUT);

  nh.subscribe(subPwmForward);
  nh.subscribe(subPwmSideward);
  nh.subscribe(subPwmUpward);
  nh.subscribe(subPwmTurn);
  nh.advertise(ps_voltage);
  Serial.begin(57600);
  std_msgs::Int32 msg;
  msg.data = 0;
  PWMCbForward(msg);
  PWMCbSideward(msg);
  PWMCbUpward(msg);
  PWMCbTurn(msg);
}

void loop()
{
  v = analogRead(analogPinPressureSensor);
  voltage.data = v;
  ps_voltage.publish(&voltage);
  nh.spinOnce();
  delay(1);
}
<|endoftext|>


<commit_before>// Copyright 2015-2019 Elviss Strazdins. All rights reserved.

#include <stdexcept>
#include "Cursor.hpp"
#include "InputManager.hpp"
#include "core/Engine.hpp"
#include "stb_image.h"

namespace ouzel
{
    namespace input
    {
        Cursor::Cursor(InputManager& initInputManager):
            inputManager(initInputManager)
        {
            cursorResource = inputManager.getInputSystem()->getResourceId();
        }

        Cursor::Cursor(InputManager& initInputManager, SystemCursor systemCursor):
            Cursor(initInputManager)
        {
            init(systemCursor);
        }

        Cursor::Cursor(InputManager& initInputManager, const std::string& filename, const Vector2F& hotSpot):
            Cursor(initInputManager)
        {
            init(filename, hotSpot);
        }

        Cursor::~Cursor()
        {
            if (cursorResource)
            {
                InputSystem::Command command(InputSystem::Command::Type::DestroyCursor);
                command.cursorResource = cursorResource;
                inputManager.getInputSystem()->addCommand(command);

                inputManager.getInputSystem()->deleteResourceId(cursorResource);
            }
        }

        void Cursor::init(SystemCursor systemCursor)
        {
            InputSystem::Command command(InputSystem::Command::Type::InitCursor);
            command.cursorResource = cursorResource;
            command.systemCursor = systemCursor;
            inputManager.getInputSystem()->addCommand(command);
        }

        void Cursor::init(const std::string& filename, const Vector2F& hotSpot)
        {
            // TODO: load with asset loader
            const std::vector<uint8_t> data = engine->getFileSystem().readFile(filename);

            int width;
            int height;
            int comp;

            stbi_uc* tempData = stbi_load_from_memory(data.data(), static_cast<int>(data.size()), &width, &height, &comp, STBI_default);

            if (!tempData)
                throw std::runtime_error("Failed to load texture, reason: " + std::string(stbi_failure_reason()));

            size_t pixelSize;
            graphics::PixelFormat pixelFormat;
            std::vector<uint8_t> imageData;

            switch (comp)
            {
                case STBI_grey:
                {
                    pixelFormat = graphics::PixelFormat::RGBA8UNorm;
                    pixelSize = 4;

                    imageData.resize(static_cast<size_t>(width * height * 4));

                    for (int y = 0; y < height; ++y)
                    {
                        for (int x = 0; x < width; ++x)
                        {
                            auto sourceOffset = static_cast<size_t>(y * height + x);
                            auto destinationOffset = static_cast<size_t>((y * height + x) * 4);
                            imageData[destinationOffset + 0] = tempData[sourceOffset];
                            imageData[destinationOffset + 1] = tempData[sourceOffset];
                            imageData[destinationOffset + 2] = tempData[sourceOffset];
                            imageData[destinationOffset + 3] = 255;
                        }
                    }
                    stbi_image_free(tempData);
                    break;
                }
                case STBI_grey_alpha:
                {
                    pixelFormat = graphics::PixelFormat::RGBA8UNorm;
                    pixelSize = 4;

                    imageData.resize(static_cast<size_t>(width * height * 4));

                    for (int y = 0; y < height; ++y)
                    {
                        for (int x = 0; x < width; ++x)
                        {
                            auto sourceOffset = static_cast<size_t>((y * height + x) * 2);
                            auto destinationOffset = static_cast<size_t>((y * height + x) * 4);
                            imageData[destinationOffset + 0] = tempData[sourceOffset + 0];
                            imageData[destinationOffset + 1] = tempData[sourceOffset + 0];
                            imageData[destinationOffset + 2] = tempData[sourceOffset + 0];
                            imageData[destinationOffset + 3] = tempData[sourceOffset + 1];
                        }
                    }
                    stbi_image_free(tempData);
                    break;
                }
                case STBI_rgb:
                {
                    pixelFormat = graphics::PixelFormat::RGBA8UNorm;
                    pixelSize = 4;

                    imageData.resize(static_cast<size_t>(width * height * 4));

                    for (int y = 0; y < height; ++y)
                    {
                        for (int x = 0; x < width; ++x)
                        {
                            auto sourceOffset = static_cast<size_t>((y * height + x) * 3);
                            auto destinationOffset = static_cast<size_t>((y * height + x) * 4);
                            imageData[destinationOffset + 0] = tempData[sourceOffset + 0];
                            imageData[destinationOffset + 1] = tempData[sourceOffset + 1];
                            imageData[destinationOffset + 2] = tempData[sourceOffset + 2];
                            imageData[destinationOffset + 3] = 255;
                        }
                    }
                    stbi_image_free(tempData);
                    break;
                }
                case STBI_rgb_alpha:
                {
                    pixelFormat = graphics::PixelFormat::RGBA8UNorm;
                    pixelSize = 4;
                    imageData.assign(tempData,
                                     tempData + static_cast<size_t>(width * height) * pixelSize);
                    stbi_image_free(tempData);
                    break;
                }
                default:
                    stbi_image_free(tempData);
                    throw std::runtime_error("Unsupported pixel size");
            }

            init(imageData,
                 Size2F(static_cast<float>(width), static_cast<float>(height)),
                 pixelFormat,
                 hotSpot);
        }

        void Cursor::init(const std::vector<uint8_t>& data,
                          const Size2F& size,
                          graphics::PixelFormat pixelFormat,
                          const Vector2F& hotSpot)
        {
            InputSystem::Command command(InputSystem::Command::Type::InitCursor);
            command.cursorResource = cursorResource;
            command.data = data;
            command.size = size;
            command.pixelFormat = pixelFormat;
            command.hotSpot = hotSpot;
            inputManager.getInputSystem()->addCommand(command);
        }
    } // namespace input
} // namespace ouzel
<commit_msg>Make the offset const<commit_after>// Copyright 2015-2019 Elviss Strazdins. All rights reserved.

#include <stdexcept>
#include "Cursor.hpp"
#include "InputManager.hpp"
#include "core/Engine.hpp"
#include "stb_image.h"

namespace ouzel
{
    namespace input
    {
        Cursor::Cursor(InputManager& initInputManager):
            inputManager(initInputManager)
        {
            cursorResource = inputManager.getInputSystem()->getResourceId();
        }

        Cursor::Cursor(InputManager& initInputManager, SystemCursor systemCursor):
            Cursor(initInputManager)
        {
            init(systemCursor);
        }

        Cursor::Cursor(InputManager& initInputManager, const std::string& filename, const Vector2F& hotSpot):
            Cursor(initInputManager)
        {
            init(filename, hotSpot);
        }

        Cursor::~Cursor()
        {
            if (cursorResource)
            {
                InputSystem::Command command(InputSystem::Command::Type::DestroyCursor);
                command.cursorResource = cursorResource;
                inputManager.getInputSystem()->addCommand(command);

                inputManager.getInputSystem()->deleteResourceId(cursorResource);
            }
        }

        void Cursor::init(SystemCursor systemCursor)
        {
            InputSystem::Command command(InputSystem::Command::Type::InitCursor);
            command.cursorResource = cursorResource;
            command.systemCursor = systemCursor;
            inputManager.getInputSystem()->addCommand(command);
        }

        void Cursor::init(const std::string& filename, const Vector2F& hotSpot)
        {
            // TODO: load with asset loader
            const std::vector<uint8_t> data = engine->getFileSystem().readFile(filename);

            int width;
            int height;
            int comp;

            stbi_uc* tempData = stbi_load_from_memory(data.data(), static_cast<int>(data.size()), &width, &height, &comp, STBI_default);

            if (!tempData)
                throw std::runtime_error("Failed to load texture, reason: " + std::string(stbi_failure_reason()));

            size_t pixelSize;
            graphics::PixelFormat pixelFormat;
            std::vector<uint8_t> imageData;

            switch (comp)
            {
                case STBI_grey:
                {
                    pixelFormat = graphics::PixelFormat::RGBA8UNorm;
                    pixelSize = 4;

                    imageData.resize(static_cast<size_t>(width * height * 4));

                    for (int y = 0; y < height; ++y)
                    {
                        for (int x = 0; x < width; ++x)
                        {
                            const auto sourceOffset = static_cast<size_t>(y * height + x);
                            const auto destinationOffset = static_cast<size_t>((y * height + x) * 4);
                            imageData[destinationOffset + 0] = tempData[sourceOffset];
                            imageData[destinationOffset + 1] = tempData[sourceOffset];
                            imageData[destinationOffset + 2] = tempData[sourceOffset];
                            imageData[destinationOffset + 3] = 255;
                        }
                    }
                    stbi_image_free(tempData);
                    break;
                }
                case STBI_grey_alpha:
                {
                    pixelFormat = graphics::PixelFormat::RGBA8UNorm;
                    pixelSize = 4;

                    imageData.resize(static_cast<size_t>(width * height * 4));

                    for (int y = 0; y < height; ++y)
                    {
                        for (int x = 0; x < width; ++x)
                        {
                            const auto sourceOffset = static_cast<size_t>((y * height + x) * 2);
                            const auto destinationOffset = static_cast<size_t>((y * height + x) * 4);
                            imageData[destinationOffset + 0] = tempData[sourceOffset + 0];
                            imageData[destinationOffset + 1] = tempData[sourceOffset + 0];
                            imageData[destinationOffset + 2] = tempData[sourceOffset + 0];
                            imageData[destinationOffset + 3] = tempData[sourceOffset + 1];
                        }
                    }
                    stbi_image_free(tempData);
                    break;
                }
                case STBI_rgb:
                {
                    pixelFormat = graphics::PixelFormat::RGBA8UNorm;
                    pixelSize = 4;

                    imageData.resize(static_cast<size_t>(width * height * 4));

                    for (int y = 0; y < height; ++y)
                    {
                        for (int x = 0; x < width; ++x)
                        {
                            const auto sourceOffset = static_cast<size_t>((y * height + x) * 3);
                            const auto destinationOffset = static_cast<size_t>((y * height + x) * 4);
                            imageData[destinationOffset + 0] = tempData[sourceOffset + 0];
                            imageData[destinationOffset + 1] = tempData[sourceOffset + 1];
                            imageData[destinationOffset + 2] = tempData[sourceOffset + 2];
                            imageData[destinationOffset + 3] = 255;
                        }
                    }
                    stbi_image_free(tempData);
                    break;
                }
                case STBI_rgb_alpha:
                {
                    pixelFormat = graphics::PixelFormat::RGBA8UNorm;
                    pixelSize = 4;
                    imageData.assign(tempData,
                                     tempData + static_cast<size_t>(width * height) * pixelSize);
                    stbi_image_free(tempData);
                    break;
                }
                default:
                    stbi_image_free(tempData);
                    throw std::runtime_error("Unsupported pixel size");
            }

            init(imageData,
                 Size2F(static_cast<float>(width), static_cast<float>(height)),
                 pixelFormat,
                 hotSpot);
        }

        void Cursor::init(const std::vector<uint8_t>& data,
                          const Size2F& size,
                          graphics::PixelFormat pixelFormat,
                          const Vector2F& hotSpot)
        {
            InputSystem::Command command(InputSystem::Command::Type::InitCursor);
            command.cursorResource = cursorResource;
            command.data = data;
            command.size = size;
            command.pixelFormat = pixelFormat;
            command.hotSpot = hotSpot;
            inputManager.getInputSystem()->addCommand(command);
        }
    } // namespace input
} // namespace ouzel
<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2004 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "common.h"

/* interface header */
#include "CustomSphere.h"

/* system headers */
#include <vector>
#include "math.h"

/* common implementation headers */
#include "MeshObstacle.h"
#include "vectors.h"

/* bzfs implementation headers */
#include "ParseMaterial.h"
#include "MeshUtils.h"

CustomSphere::CustomSphere()
{
  divisions = 4;
  pos[2] = 10.0f;
  size[0] = size[1] = size[2] = 10.0f;
  material.texture = "boxwall";
  return;
}

CustomSphere::~CustomSphere()
{
  return;
}

bool CustomSphere::read(const char *cmd, std::istream& input)
{
  bool materror;

  if (strcasecmp(cmd, "divisions") == 0) {
    input >> divisions;
  }
  else if (strcasecmp(cmd, "radius") == 0) {
    float radius;
    input >> radius;
    size[0] = size[1] = size[2] = radius;
  }
  else if (parseMaterial(cmd, input, material, materror)) {
    if (materror) {
      return false;
    }
  }
  else {
    return WorldFileObstacle::read(cmd, input);
  }

  return true;
}

void CustomSphere::write(WorldInfo *world) const
{
  int i, j, q;
  cfvec3 v, n;
  cfvec2 t;

  // setup the coordinates
  std::vector<char> checkTypes;
  std::vector<cfvec3> checkPoints;
  std::vector<cfvec3> vertices;
  std::vector<cfvec3> normals;
  std::vector<cfvec2> texcoords;

  // the center vertices
  v[0] = pos[0];
  v[1] = pos[1];
  v[2] = pos[2] + size[2];
  vertices.push_back(v);
  v[2] = pos[2] - size[2];
  vertices.push_back(v);
  n[0] = 0.0f;
  n[1] = 0.0f;
  n[2] = 1.0f;
  normals.push_back(n);
  n[2] = -1.0f;
  normals.push_back(n);
  t[0] = 0.5f; // weirdness
  t[1] = 1.0f;
  texcoords.push_back(t);
  t[1] = 0.0f;
  texcoords.push_back(t);

  // the rest of the vertices
  for (i = 0; i < divisions; i++) {
    for (j = 0; j < (4 * (i + 1)); j++) {
      float h_angle = ((M_PI * 2.0f) *
                      (float)j / (float)(4 * (i + 1)));
      float v_angle = ((M_PI / 2.0f) *
                      (float)(divisions - i - 1) / (float)(divisions));
      float delta[3];
      delta[0] = size[0] * (cos(h_angle) * cos(v_angle));
      delta[1] = size[1] * (sin(h_angle) * cos(v_angle));
      delta[2] = size[2] * sin(v_angle);
      // vertex
      v[0] = pos[0] + delta[0];
      v[1] = pos[1] + delta[1];
      v[2] = pos[2] + delta[2];
      vertices.push_back(v);
      // normal
      const float len = 1.0f / sqrtf(vec3dot(delta, delta));
      n[0] = delta[0] * len;
      n[1] = delta[1] * len;
      n[2] = delta[2] * len;
      normals.push_back(v);
      // texcoord
      t[0] = (float)j / (float)(4 * (i + 1));
      t[1] = (float)(divisions - i - 1) / (float)divisions;
      t[1] = 0.5f + (0.5f * t[1]);
      texcoords.push_back(t);

      // the bottom hemisphere
      if (i != (divisions - 1)) {
        // vertex
        v[2] = (2 * pos[2]) - v[2];
        vertices.push_back(v);
        // normal
        n[2] = -n[2];
        normals.push_back(v);
        // texcoord
        t[1] = 1.0f - t[1];
        texcoords.push_back(t);
      }
    }
  }

  // the closing strip of texture coordinates
//  const int texStripOffset = (2 * ringOffset) + (divisions * 4) + 1;
  const int texStripOffset = texcoords.size();
  t[0] = 0.5f; // weirdness
  t[1] = 1.0f;
  texcoords.push_back(t);
  t[1] = 0.0f;
  texcoords.push_back(t);
  for (i = 0; i < divisions; i++) {
    t[0] = 1.0f;
    t[1] = (float)(divisions - i - 1) / (float)divisions;
    t[1] = 0.5f + (0.5f * t[1]);
    texcoords.push_back(t);
    // the bottom hemisphere
    if (i != (divisions - 1)) {
      t[1] = 1.0f - t[1];
      texcoords.push_back(t);
    }
  }

  // add the checkpoint (one is sufficient)

  v[0] = pos[0];
  v[1] = pos[1];
  v[2] = pos[2];
  checkPoints.push_back(v);
  checkTypes.push_back(MeshObstacle::CheckInside);

  // make the mesh
  int faceCount = (divisions * divisions) * 8;
  MeshObstacle* mesh =
    new MeshObstacle(checkTypes, checkPoints, vertices, normals, texcoords,
                     faceCount, driveThrough, shootThrough);

  // add the faces to the mesh
  std::vector<int> verticesList;
  std::vector<int> normalsList;
  std::vector<int> texcoordsList;

  int k = (divisions - 1);
  const int ringOffset = 1 + (((k*k)+k)*2);

  for (q = 0; q < 4; q++) {
    for (i = 0; i < divisions; i++) {
      for (j = 0; j < (i + 1); j++) {
        int a, b, c, d, ta, tc;
        const bool lastStrip = ((q == 3) && (j == i));
        const bool lastCircle = (i == (divisions - 1));

        // setup 'a'
        if (i > 0) {
          if (lastStrip) {
            int k = (i - 1);
            a = 1 + (((k*k)+k)*2);
          } else {
            int k = (i - 1);
            a = 1 + (((k*k)+k)*2) + (q*(k+1)) + j;
          }
        } else {
          a = 0;
        }

        // setup 'b'
        b = 1 + (((i*i)+i)*2) + (q*(i+1)) + j;

        // setup 'c'
        if (lastStrip) {
          c = 1 + (((i*i)+i)*2);
        } else {
          c = b + 1;
        }

        // setup 'd' for the down-pointing triangle
        int k = (i + 1);
        d = 1 + (((k*k)+k)*2) + (q*(k+1)) + (j + 1);

        // top hemisphere
        a = a * 2;
        if (!lastCircle) {
          b = b * 2;
          c = c * 2;
        } else {
          b = b + ringOffset;
          c = c + ringOffset;
        }
        if (i != (divisions - 2)) {
          d = d * 2;
        } else {
          d = d + ringOffset;
        }

        // deal with the last strip of texture coordinates
        if (!lastStrip) {
          ta = a;
          tc = c;
        } else {
          ta = texStripOffset + (i * 2);
          tc = texStripOffset + ((i + 1) * 2);
        }

        push3Ints(verticesList, a, b, c);
        push3Ints(normalsList, a, b, c);
        push3Ints(texcoordsList, ta, b, tc);
        addFace(mesh, verticesList, normalsList, texcoordsList, material);
        if (!lastCircle) {
          push3Ints(verticesList, b, d, c);
          push3Ints(normalsList, b, d, c);
          push3Ints(texcoordsList, b, d, tc);
          addFace(mesh, verticesList, normalsList, texcoordsList, material);
        }

        // bottom hemisphere
        a = a + 1;
        ta = ta + 1;
        if (!lastCircle) {
          b = b + 1;
          c = c + 1;
          tc = tc + 1;
        }
        if (i != (divisions - 2)) {
          d = d + 1;
        }
        push3Ints(verticesList, a, c, b);
        push3Ints(normalsList, a, c, b);
        push3Ints(texcoordsList, ta, tc, b);
        addFace(mesh, verticesList, normalsList, texcoordsList, material);
        if (!lastCircle) {
          push3Ints(verticesList, b, c, d);
          push3Ints(normalsList, b, c, d);
          push3Ints(texcoordsList, b, tc, d);
          addFace(mesh, verticesList, normalsList, texcoordsList, material);
        }
      }
    }
  }

  // add the mesh
  mesh->finalize();
  world->addMesh(mesh);

  return;
}

// Local variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>fix bottom hemisphere lighting normals<commit_after>/* bzflag
 * Copyright (c) 1993 - 2004 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "common.h"

/* interface header */
#include "CustomSphere.h"

/* system headers */
#include <vector>
#include "math.h"

/* common implementation headers */
#include "MeshObstacle.h"
#include "vectors.h"

/* bzfs implementation headers */
#include "ParseMaterial.h"
#include "MeshUtils.h"

CustomSphere::CustomSphere()
{
  divisions = 4;
  pos[2] = 10.0f;
  size[0] = size[1] = size[2] = 10.0f;
  material.texture = "boxwall";
  return;
}

CustomSphere::~CustomSphere()
{
  return;
}

bool CustomSphere::read(const char *cmd, std::istream& input)
{
  bool materror;

  if (strcasecmp(cmd, "divisions") == 0) {
    input >> divisions;
  }
  else if (strcasecmp(cmd, "radius") == 0) {
    float radius;
    input >> radius;
    size[0] = size[1] = size[2] = radius;
  }
  else if (parseMaterial(cmd, input, material, materror)) {
    if (materror) {
      return false;
    }
  }
  else {
    return WorldFileObstacle::read(cmd, input);
  }

  return true;
}

void CustomSphere::write(WorldInfo *world) const
{
  int i, j, q;
  cfvec3 v, n;
  cfvec2 t;

  // setup the coordinates
  std::vector<char> checkTypes;
  std::vector<cfvec3> checkPoints;
  std::vector<cfvec3> vertices;
  std::vector<cfvec3> normals;
  std::vector<cfvec2> texcoords;

  // the center vertices
  v[0] = pos[0];
  v[1] = pos[1];
  v[2] = pos[2] + size[2];
  vertices.push_back(v);
  v[2] = pos[2] - size[2];
  vertices.push_back(v);
  n[0] = 0.0f;
  n[1] = 0.0f;
  n[2] = 1.0f;
  normals.push_back(n);
  n[2] = -1.0f;
  normals.push_back(n);
  t[0] = 0.5f; // weirdness
  t[1] = 1.0f;
  texcoords.push_back(t);
  t[1] = 0.0f;
  texcoords.push_back(t);

  // the rest of the vertices
  for (i = 0; i < divisions; i++) {
    for (j = 0; j < (4 * (i + 1)); j++) {
      float h_angle = ((M_PI * 2.0f) *
                      (float)j / (float)(4 * (i + 1)));
      float v_angle = ((M_PI / 2.0f) *
                      (float)(divisions - i - 1) / (float)(divisions));
      float delta[3];
      delta[0] = size[0] * (cos(h_angle) * cos(v_angle));
      delta[1] = size[1] * (sin(h_angle) * cos(v_angle));
      delta[2] = size[2] * sin(v_angle);
      // vertex
      v[0] = pos[0] + delta[0];
      v[1] = pos[1] + delta[1];
      v[2] = pos[2] + delta[2];
      vertices.push_back(v);
      // normal
      const float len = 1.0f / sqrtf(vec3dot(delta, delta));
      n[0] = delta[0] * len;
      n[1] = delta[1] * len;
      n[2] = delta[2] * len;
      normals.push_back(v);
      // texcoord
      t[0] = (float)j / (float)(4 * (i + 1));
      t[1] = (float)(divisions - i - 1) / (float)divisions;
      t[1] = 0.5f + (0.5f * t[1]);
      texcoords.push_back(t);

      // the bottom hemisphere
      if (i != (divisions - 1)) {
        // vertex
        v[2] = (2 * pos[2]) - v[2];
        vertices.push_back(v);
        // normal
        n[2] = -n[2];
        normals.push_back(n);
        // texcoord
        t[1] = 1.0f - t[1];
        texcoords.push_back(t);
      }
    }
  }

  // the closing strip of texture coordinates
//  const int texStripOffset = (2 * ringOffset) + (divisions * 4) + 1;
  const int texStripOffset = texcoords.size();
  t[0] = 0.5f; // weirdness
  t[1] = 1.0f;
  texcoords.push_back(t);
  t[1] = 0.0f;
  texcoords.push_back(t);
  for (i = 0; i < divisions; i++) {
    t[0] = 1.0f;
    t[1] = (float)(divisions - i - 1) / (float)divisions;
    t[1] = 0.5f + (0.5f * t[1]);
    texcoords.push_back(t);
    // the bottom hemisphere
    if (i != (divisions - 1)) {
      t[1] = 1.0f - t[1];
      texcoords.push_back(t);
    }
  }

  // add the checkpoint (one is sufficient)

  v[0] = pos[0];
  v[1] = pos[1];
  v[2] = pos[2];
  checkPoints.push_back(v);
  checkTypes.push_back(MeshObstacle::CheckInside);

  // make the mesh
  int faceCount = (divisions * divisions) * 8;
  MeshObstacle* mesh =
    new MeshObstacle(checkTypes, checkPoints, vertices, normals, texcoords,
                     faceCount, driveThrough, shootThrough);

  // add the faces to the mesh
  std::vector<int> verticesList;
  std::vector<int> normalsList;
  std::vector<int> texcoordsList;

  int k = (divisions - 1);
  const int ringOffset = 1 + (((k*k)+k)*2);

  for (q = 0; q < 4; q++) {
    for (i = 0; i < divisions; i++) {
      for (j = 0; j < (i + 1); j++) {
        int a, b, c, d, ta, tc;
        const bool lastStrip = ((q == 3) && (j == i));
        const bool lastCircle = (i == (divisions - 1));

        // setup 'a'
        if (i > 0) {
          if (lastStrip) {
            int k = (i - 1);
            a = 1 + (((k*k)+k)*2);
          } else {
            int k = (i - 1);
            a = 1 + (((k*k)+k)*2) + (q*(k+1)) + j;
          }
        } else {
          a = 0;
        }

        // setup 'b'
        b = 1 + (((i*i)+i)*2) + (q*(i+1)) + j;

        // setup 'c'
        if (lastStrip) {
          c = 1 + (((i*i)+i)*2);
        } else {
          c = b + 1;
        }

        // setup 'd' for the down-pointing triangle
        int k = (i + 1);
        d = 1 + (((k*k)+k)*2) + (q*(k+1)) + (j + 1);

        // top hemisphere
        a = a * 2;
        if (!lastCircle) {
          b = b * 2;
          c = c * 2;
        } else {
          b = b + ringOffset;
          c = c + ringOffset;
        }
        if (i != (divisions - 2)) {
          d = d * 2;
        } else {
          d = d + ringOffset;
        }

        // deal with the last strip of texture coordinates
        if (!lastStrip) {
          ta = a;
          tc = c;
        } else {
          ta = texStripOffset + (i * 2);
          tc = texStripOffset + ((i + 1) * 2);
        }

        push3Ints(verticesList, a, b, c);
        push3Ints(normalsList, a, b, c);
        push3Ints(texcoordsList, ta, b, tc);
        addFace(mesh, verticesList, normalsList, texcoordsList, material);
        if (!lastCircle) {
          push3Ints(verticesList, b, d, c);
          push3Ints(normalsList, b, d, c);
          push3Ints(texcoordsList, b, d, tc);
          addFace(mesh, verticesList, normalsList, texcoordsList, material);
        }

        // bottom hemisphere
        a = a + 1;
        ta = ta + 1;
        if (!lastCircle) {
          b = b + 1;
          c = c + 1;
          tc = tc + 1;
        }
        if (i != (divisions - 2)) {
          d = d + 1;
        }
        push3Ints(verticesList, a, c, b);
        push3Ints(normalsList, a, c, b);
        push3Ints(texcoordsList, ta, tc, b);
        addFace(mesh, verticesList, normalsList, texcoordsList, material);
        if (!lastCircle) {
          push3Ints(verticesList, b, c, d);
          push3Ints(normalsList, b, c, d);
          push3Ints(texcoordsList, b, tc, d);
          addFace(mesh, verticesList, normalsList, texcoordsList, material);
        }
      }
    }
  }

  // add the mesh
  mesh->finalize();
  world->addMesh(mesh);

  return;
}

// Local variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>