<commit_before>/* Copyright (c) 2014, Fengping Bao <jamol@live.com>
 *
 * 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" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include "EventLoopImpl.h"
#include "poll/IOPoll.h"
#include "util/kmqueue.h"
#include "util/kmtrace.h"
#include <thread>
#include <condition_variable>

KUMA_NS_BEGIN

IOPoll* createIOPoll(PollType poll_type);

EventLoop::Impl::Impl(PollType poll_type)
: poll_(createIOPoll(poll_type))
, timer_mgr_(new TimerManager(this))
{
    KM_SetObjKey("EventLoop");
}

EventLoop::Impl::~Impl()
{
    if(poll_) {
        delete poll_;
        poll_ = nullptr;
    }
}

bool EventLoop::Impl::init()
{
    if(!poll_->init()) {
        return false;
    }
    stop_loop_ = false;
    thread_id_ = std::this_thread::get_id();
    return true;
}

PollType EventLoop::Impl::getPollType() const
{
    if(poll_) {
        return poll_->getType();
    }
    return PollType::NONE;
}

bool EventLoop::Impl::isPollLT() const
{
    if(poll_) {
        return poll_->isLevelTriggered();
    }
    return false;
}

KMError EventLoop::Impl::registerFd(SOCKET_FD fd, uint32_t events, IOCallback cb)
{
    if(inSameThread()) {
        return poll_->registerFd(fd, events, std::move(cb));
    }
    return async([=] () mutable {
        auto ret = poll_->registerFd(fd, events, cb);
        if(ret != KMError::NOERR) {
            return ;
        }
    });
}

KMError EventLoop::Impl::updateFd(SOCKET_FD fd, uint32_t events)
{
    if(inSameThread()) {
        return poll_->updateFd(fd, events);
    }
    return async([=] {
        auto ret = poll_->updateFd(fd, events);
        if(ret != KMError::NOERR) {
            return ;
        }
    });
}

KMError EventLoop::Impl::unregisterFd(SOCKET_FD fd, bool close_fd)
{
    if(inSameThread()) {
        auto ret = poll_->unregisterFd(fd);
        if(close_fd) {
            closeFd(fd);
        }
        return ret;
    } else {
        auto ret = sync([=] {
            poll_->unregisterFd(fd);
            if(close_fd) {
                closeFd(fd);
            }
        });
        if(KMError::NOERR != ret) {
            return ret;
        }
        return KMError::NOERR;
    }
}

KMError EventLoop::Impl::appendObserver(ObserverCallback cb, EventLoopToken *token)
{
    if (token && token->eventLoop() != this) {
        return KMError::INVALID_PARAM;
    }
    LockGuard g(obs_mutex_);
    if (stop_loop_) {
        return KMError::INVALID_STATE;
    }
    auto obs_node = obs_queue_.enqueue(std::move(cb));
    if (token) {
        token->obs_token_ = obs_node;
        token->observed = true;
    }
    return KMError::NOERR;
}

KMError EventLoop::Impl::removeObserver(EventLoopToken *token)
{
    if (token) {
        if (token->eventLoop() != this) {
            return KMError::INVALID_STATE;
        }
        auto node = token->obs_token_.lock();
        if (node) {
            LockGuard g(obs_mutex_);
            obs_queue_.remove(node);
        }
        token->obs_token_.reset();
        token->observed = false;
    }
    return KMError::NOERR;
}

void EventLoop::Impl::processTasks()
{
    task_mutex_.lock();
    while (auto node = task_queue_.front_node()) {
        task_queue_.pop_front();
        node->element_.state = TaskSlot::State::RUNNING;
        task_mutex_.unlock();
        task_run_mutex_.lock();
        if (node->element_.state != TaskSlot::State::INACTIVE) {
            node->element_();
            node->element_.state = TaskSlot::State::INACTIVE;
        }
        task_run_mutex_.unlock();
        task_mutex_.lock();
        if (node->element_.token) {
            node->element_.token->removeTaskNode(node);
        }
    }
    task_mutex_.unlock();
}

void EventLoop::Impl::loopOnce(uint32_t max_wait_ms)
{
    processTasks();
    unsigned long wait_ms = max_wait_ms;
    timer_mgr_->checkExpire(&wait_ms);
    if(wait_ms > max_wait_ms) {
        wait_ms = max_wait_ms;
    }
    poll_->wait((uint32_t)wait_ms);
}

void EventLoop::Impl::loop(uint32_t max_wait_ms)
{
    while (!stop_loop_) {
        loopOnce(max_wait_ms);
    }
    processTasks();

    {
        LockGuard g(obs_mutex_);
        ObserverCallback cb;
        while (obs_queue_.dequeue(cb)) {
            cb(LoopActivity::EXIT);
        }
    }
    KUMA_INFOXTRACE("loop, stopped");
}

void EventLoop::Impl::notify()
{
    poll_->notify();
}

void EventLoop::Impl::stop()
{
    KUMA_INFOXTRACE("stop");
    stop_loop_ = true;
    poll_->notify();
}

KMError EventLoop::Impl::appendTask(Task task, EventLoopToken *token)
{
    if (token && token->eventLoop() != this) {
        return KMError::INVALID_PARAM;
    }
    auto node = std::make_shared<TaskQueue::DLNode>(std::move(task), token);
    LockGuard g(task_mutex_);
    if (stop_loop_) {
        return KMError::INVALID_STATE;
    }
    task_queue_.enqueue(node);
    if (token) {
        token->appendTaskNode(node);
    }
    return KMError::NOERR;
}

KMError EventLoop::Impl::removeTask(EventLoopToken *token)
{
    if (!token || token->eventLoop() != this) {
        return KMError::INVALID_PARAM;
    }
    bool is_running = false;
    {
        LockGuard g(task_mutex_);
        for (auto &node : token->node_queue_) {
            if (node->element_.state == TaskSlot::State::RUNNING) {
                is_running = true;
                node->element_.state = TaskSlot::State::INACTIVE;
            }
            task_queue_.remove(node);
        }
        token->node_queue_.clear();
    }
    if (is_running && !inSameThread()) {
        // wait for end of running
        task_run_mutex_.lock();
        task_run_mutex_.unlock();
    }
    return KMError::NOERR;
}

KMError EventLoop::Impl::sync(Task task)
{
    if(inSameThread()) {
        task();
    } else {
        std::mutex m;
        std::condition_variable cv;
        bool ready = false;
        Task task_sync([&] {
            task();
            std::unique_lock<std::mutex> lk(m);
            ready = true;
            lk.unlock();
            cv.notify_one();
        });
        auto ret = queue(std::move(task_sync));
        if (ret != KMError::NOERR) {
            return ret;
        }
        std::unique_lock<std::mutex> lk(m);
        cv.wait(lk, [&ready] { return ready; });
    }
    return KMError::NOERR;
}

KMError EventLoop::Impl::async(Task task, EventLoopToken *token)
{
    if(inSameThread()) {
        task();
        return KMError::NOERR;
    } else {
        return queue(std::move(task), token);
    }
}

KMError EventLoop::Impl::queue(Task task, EventLoopToken *token)
{
    auto ret = appendTask(std::move(task), token);
    if (ret != KMError::NOERR) {
        return ret;
    }
    poll_->notify();
    return KMError::NOERR;
}

/////////////////////////////////////////////////////////////////
// EventLoopToken
EventLoopToken::EventLoopToken()
{

}

EventLoopToken::~EventLoopToken()
{
    reset();
}

void EventLoopToken::eventLoop(EventLoop::Impl *loop)
{
    loop_ = loop;
}

EventLoop::Impl* EventLoopToken::eventLoop()
{
    return loop_;
}

void EventLoopToken::appendTaskNode(TaskNodePtr &node)
{
    node_queue_.emplace_back(node);
}

void EventLoopToken::removeTaskNode(TaskNodePtr &node)
{
    for (auto it = node_queue_.begin(); it != node_queue_.end(); ++it) {
        if (*it == node) {
            node_queue_.erase(it);
            break;
        }
    }
}

bool EventLoopToken::expired()
{
    return !loop_ || (observed && obs_token_.expired());
}

void EventLoopToken::reset()
{
    if (loop_) {
        if (!node_queue_.empty()) {
            loop_->removeTask(this);
        }
        if (!obs_token_.expired()) {
            loop_->removeObserver(this);
            obs_token_.reset();
        }
        loop_ = nullptr;
    } else {
        node_queue_.clear();
    }
}

/////////////////////////////////////////////////////////////////
//
IOPoll* createEPoll();
IOPoll* createVPoll();
IOPoll* createKQueue();
IOPoll* createSelectPoll();

IOPoll* createDefaultIOPoll()
{
#ifdef KUMA_OS_WIN
    return createSelectPoll();
#elif defined(KUMA_OS_LINUX)
    return createEPoll();
#elif defined(KUMA_OS_MAC)
    return createKQueue();
    //return createVPoll();
#else
    return createSelectPoll();
#endif
}

IOPoll* createIOPoll(PollType poll_type)
{
    switch (poll_type)
    {
        case PollType::POLL:
            return createVPoll();
        case PollType::SELECT:
            return createSelectPoll();
        case PollType::KQUEUE:
#ifdef KUMA_OS_MAC
            return createKQueue();
#else
            return createDefaultIOPoll();
#endif
        case PollType::EPOLL:
#ifdef KUMA_OS_LINUX
            return createEPoll();
#else
            return createDefaultIOPoll();
#endif
        default:
            return createDefaultIOPoll();
    }
}

KUMA_NS_END
<commit_msg>fix dead loop when append task in running task<commit_after>/* Copyright (c) 2014, Fengping Bao <jamol@live.com>
 *
 * 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" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include "EventLoopImpl.h"
#include "poll/IOPoll.h"
#include "util/kmqueue.h"
#include "util/kmtrace.h"
#include <thread>
#include <condition_variable>

KUMA_NS_BEGIN

IOPoll* createIOPoll(PollType poll_type);

EventLoop::Impl::Impl(PollType poll_type)
: poll_(createIOPoll(poll_type))
, timer_mgr_(new TimerManager(this))
{
    KM_SetObjKey("EventLoop");
}

EventLoop::Impl::~Impl()
{
    if(poll_) {
        delete poll_;
        poll_ = nullptr;
    }
}

bool EventLoop::Impl::init()
{
    if(!poll_->init()) {
        return false;
    }
    stop_loop_ = false;
    thread_id_ = std::this_thread::get_id();
    return true;
}

PollType EventLoop::Impl::getPollType() const
{
    if(poll_) {
        return poll_->getType();
    }
    return PollType::NONE;
}

bool EventLoop::Impl::isPollLT() const
{
    if(poll_) {
        return poll_->isLevelTriggered();
    }
    return false;
}

KMError EventLoop::Impl::registerFd(SOCKET_FD fd, uint32_t events, IOCallback cb)
{
    if(inSameThread()) {
        return poll_->registerFd(fd, events, std::move(cb));
    }
    return async([=] () mutable {
        auto ret = poll_->registerFd(fd, events, cb);
        if(ret != KMError::NOERR) {
            return ;
        }
    });
}

KMError EventLoop::Impl::updateFd(SOCKET_FD fd, uint32_t events)
{
    if(inSameThread()) {
        return poll_->updateFd(fd, events);
    }
    return async([=] {
        auto ret = poll_->updateFd(fd, events);
        if(ret != KMError::NOERR) {
            return ;
        }
    });
}

KMError EventLoop::Impl::unregisterFd(SOCKET_FD fd, bool close_fd)
{
    if(inSameThread()) {
        auto ret = poll_->unregisterFd(fd);
        if(close_fd) {
            closeFd(fd);
        }
        return ret;
    } else {
        auto ret = sync([=] {
            poll_->unregisterFd(fd);
            if(close_fd) {
                closeFd(fd);
            }
        });
        if(KMError::NOERR != ret) {
            return ret;
        }
        return KMError::NOERR;
    }
}

KMError EventLoop::Impl::appendObserver(ObserverCallback cb, EventLoopToken *token)
{
    if (token && token->eventLoop() != this) {
        return KMError::INVALID_PARAM;
    }
    LockGuard g(obs_mutex_);
    if (stop_loop_) {
        return KMError::INVALID_STATE;
    }
    auto obs_node = obs_queue_.enqueue(std::move(cb));
    if (token) {
        token->obs_token_ = obs_node;
        token->observed = true;
    }
    return KMError::NOERR;
}

KMError EventLoop::Impl::removeObserver(EventLoopToken *token)
{
    if (token) {
        if (token->eventLoop() != this) {
            return KMError::INVALID_STATE;
        }
        auto node = token->obs_token_.lock();
        if (node) {
            LockGuard g(obs_mutex_);
            obs_queue_.remove(node);
        }
        token->obs_token_.reset();
        token->observed = false;
    }
    return KMError::NOERR;
}

void EventLoop::Impl::processTasks()
{
    TaskQueue tq;
    task_mutex_.lock();
    task_queue_.swap(tq);

    while (auto node = tq.front_node()) {
        tq.pop_front();
        node->element_.state = TaskSlot::State::RUNNING;
        task_mutex_.unlock();
        task_run_mutex_.lock();
        if (node->element_.state != TaskSlot::State::INACTIVE) {
            node->element_();
            node->element_.state = TaskSlot::State::INACTIVE;
        }
        task_run_mutex_.unlock();
        task_mutex_.lock();
        if (node->element_.token) {
            node->element_.token->removeTaskNode(node);
        }
    }
    task_mutex_.unlock();
}

void EventLoop::Impl::loopOnce(uint32_t max_wait_ms)
{
    processTasks();
    unsigned long wait_ms = max_wait_ms;
    timer_mgr_->checkExpire(&wait_ms);
    if(wait_ms > max_wait_ms) {
        wait_ms = max_wait_ms;
    }
    poll_->wait((uint32_t)wait_ms);
}

void EventLoop::Impl::loop(uint32_t max_wait_ms)
{
    while (!stop_loop_) {
        loopOnce(max_wait_ms);
    }
    processTasks();

    {
        LockGuard g(obs_mutex_);
        ObserverCallback cb;
        while (obs_queue_.dequeue(cb)) {
            cb(LoopActivity::EXIT);
        }
    }
    KUMA_INFOXTRACE("loop, stopped");
}

void EventLoop::Impl::notify()
{
    poll_->notify();
}

void EventLoop::Impl::stop()
{
    KUMA_INFOXTRACE("stop");
    stop_loop_ = true;
    poll_->notify();
}

KMError EventLoop::Impl::appendTask(Task task, EventLoopToken *token)
{
    if (token && token->eventLoop() != this) {
        return KMError::INVALID_PARAM;
    }
    auto node = std::make_shared<TaskQueue::DLNode>(std::move(task), token);
    LockGuard g(task_mutex_);
    if (stop_loop_) {
        return KMError::INVALID_STATE;
    }
    task_queue_.enqueue(node);
    if (token) {
        token->appendTaskNode(node);
    }
    return KMError::NOERR;
}

KMError EventLoop::Impl::removeTask(EventLoopToken *token)
{
    if (!token || token->eventLoop() != this) {
        return KMError::INVALID_PARAM;
    }
    bool is_running = false;
    {
        LockGuard g(task_mutex_);
        for (auto &node : token->node_queue_) {
            if (node->element_.state == TaskSlot::State::RUNNING) {
                is_running = true;
                node->element_.state = TaskSlot::State::INACTIVE;
            }
            task_queue_.remove(node);
        }
        token->node_queue_.clear();
    }
    if (is_running && !inSameThread()) {
        // wait for end of running
        task_run_mutex_.lock();
        task_run_mutex_.unlock();
    }
    return KMError::NOERR;
}

KMError EventLoop::Impl::sync(Task task)
{
    if(inSameThread()) {
        task();
    } else {
        std::mutex m;
        std::condition_variable cv;
        bool ready = false;
        Task task_sync([&] {
            task();
            std::unique_lock<std::mutex> lk(m);
            ready = true;
            lk.unlock();
            cv.notify_one();
        });
        auto ret = queue(std::move(task_sync));
        if (ret != KMError::NOERR) {
            return ret;
        }
        std::unique_lock<std::mutex> lk(m);
        cv.wait(lk, [&ready] { return ready; });
    }
    return KMError::NOERR;
}

KMError EventLoop::Impl::async(Task task, EventLoopToken *token)
{
    if(inSameThread()) {
        task();
        return KMError::NOERR;
    } else {
        return queue(std::move(task), token);
    }
}

KMError EventLoop::Impl::queue(Task task, EventLoopToken *token)
{
    auto ret = appendTask(std::move(task), token);
    if (ret != KMError::NOERR) {
        return ret;
    }
    poll_->notify();
    return KMError::NOERR;
}

/////////////////////////////////////////////////////////////////
// EventLoopToken
EventLoopToken::EventLoopToken()
{

}

EventLoopToken::~EventLoopToken()
{
    reset();
}

void EventLoopToken::eventLoop(EventLoop::Impl *loop)
{
    loop_ = loop;
}

EventLoop::Impl* EventLoopToken::eventLoop()
{
    return loop_;
}

void EventLoopToken::appendTaskNode(TaskNodePtr &node)
{
    node_queue_.emplace_back(node);
}

void EventLoopToken::removeTaskNode(TaskNodePtr &node)
{
    for (auto it = node_queue_.begin(); it != node_queue_.end(); ++it) {
        if (*it == node) {
            node_queue_.erase(it);
            break;
        }
    }
}

bool EventLoopToken::expired()
{
    return !loop_ || (observed && obs_token_.expired());
}

void EventLoopToken::reset()
{
    if (loop_) {
        if (!node_queue_.empty()) {
            loop_->removeTask(this);
        }
        if (!obs_token_.expired()) {
            loop_->removeObserver(this);
            obs_token_.reset();
        }
        loop_ = nullptr;
    } else {
        node_queue_.clear();
    }
}

/////////////////////////////////////////////////////////////////
//
IOPoll* createEPoll();
IOPoll* createVPoll();
IOPoll* createKQueue();
IOPoll* createSelectPoll();

IOPoll* createDefaultIOPoll()
{
#ifdef KUMA_OS_WIN
    return createSelectPoll();
#elif defined(KUMA_OS_LINUX)
    return createEPoll();
#elif defined(KUMA_OS_MAC)
    return createKQueue();
    //return createVPoll();
#else
    return createSelectPoll();
#endif
}

IOPoll* createIOPoll(PollType poll_type)
{
    switch (poll_type)
    {
        case PollType::POLL:
            return createVPoll();
        case PollType::SELECT:
            return createSelectPoll();
        case PollType::KQUEUE:
#ifdef KUMA_OS_MAC
            return createKQueue();
#else
            return createDefaultIOPoll();
#endif
        case PollType::EPOLL:
#ifdef KUMA_OS_LINUX
            return createEPoll();
#else
            return createDefaultIOPoll();
#endif
        default:
            return createDefaultIOPoll();
    }
}

KUMA_NS_END
<|endoftext|>


<commit_before><commit_msg>Liblager_recognize: Raise detection thresholds<commit_after><|endoftext|>


<commit_before>#include <iostream>

#include "libaps.h"
#include "constants.h"
#include <thread>
#include "logger.h"

#include "EthernetControl.h"

using namespace std;

int main ()
{
  cout << "BBN AP2 Test Executable" << endl;

  FILELog::ReportingLevel() = TLogLevel(5);;

  cout << "Testing only EthernetControl" << endl;

  // lookup based on device name
  //string dev("\\Device\\NPF_{F47ACE9E-1961-4A8E-BA14-2564E3764BFA}");

  // lookup based on description
  string dev("Intel(R) 82579LM Gigabit Network Connection");

  EthernetControl *ec = new EthernetControl();

  EthernetControl::set_device_active(dev,true);
  EthernetControl::enumerate();

#if 0
  set_logging_level(5);

  int numDevices = get_numDevices();

  cout << numDevices << " APS device" << (numDevices > 1 ? "s": "")  << " found" << endl;

  if (numDevices < 1)
  	return 0;

  char s[] = "stdout";
  set_log(s);

  cout << "Attempting to initialize libaps" << endl;

  init();

  char serialBuffer[100];

  for (int cnt; cnt < numDevices; cnt++) {
  	get_deviceSerial(cnt, serialBuffer);
  	cout << "Device " << cnt << " serial #: " << serialBuffer << endl;
  }

  int rc;
  rc = connect_by_ID(0);

  cout << "connect_by_ID(0) returned " << rc << endl;

  cout << "Set sample rate " << endl;

  set_sampleRate(0,100);

  cout << "current PLL frequency = " << get_sampleRate(0) << " MHz" << endl;

  cout << "setting trigger source = EXTERNAL" << endl;

  set_trigger_source(0, EXTERNAL);

  cout << "get trigger source returns " << ((get_trigger_source(0) == INTERNAL) ? "INTERNAL" : "EXTERNAL") << endl;

  cout << "setting trigger source = INTERNAL" << endl;

  set_trigger_source(0, INTERNAL);

  cout << "get trigger source returns " << ((get_trigger_source(0) == INTERNAL) ? "INTERNAL" : "EXTERNAL") << endl;

  cout << "get channel(0) enable: " << get_channel_enabled(0,0) << endl;

  cout << "set channel(0) enabled = 1" << endl;

  set_channel_enabled(0,0,true);

  const int wfs = 1000;
  short wf[wfs];
  for (int cnt = 0; cnt < wfs; cnt++)
    wf[cnt] = (cnt < wfs/2) ? 32767 : -32767;

  cout << "loading waveform" << endl;

  set_waveform_int(0, 0, wf, wfs);

  cout << "Running" << endl;

  set_sampleRate(0,50);

  run(0);

  std::this_thread::sleep_for(std::chrono::seconds(10));

  cout << "Stopping" << endl;

  stop(0);

  set_channel_enabled(0,0,false);

  cout << "get channel(0) enable: " << get_channel_enabled(0,0) << endl;

  rc = disconnect_by_ID(0);

  cout << "disconnect_by_ID(0) returned " << rc << endl;
#endif
  return 0;
}<commit_msg>Testing up through init()<commit_after>#include <iostream>

#include "libaps.h"
#include "constants.h"
#include <thread>
#include <string>
#include <algorithm>
#include "logger.h"

#include "EthernetControl.h"

using namespace std;

// command options functions taken from:
// http://stackoverflow.com/questions/865668/parse-command-line-arguments
string getCmdOption(char ** begin, char ** end, const std::string & option)
{
  char ** itr = std::find(begin, end, option);
  if (itr != end && ++itr != end)
  {
    return string(*itr);
  }
  return "";
}

bool cmdOptionExists(char** begin, char** end, const std::string& option)
{
  return std::find(begin, end, option) != end;
}

int main (int argc, char* argv[])
{
  cout << "BBN AP2 Test Executable" << endl;

  FILELog::ReportingLevel() = TLogLevel(5);
  set_logging_level(5);

  // lookup based on device name
  //string dev("\\Device\\NPF_{F47ACE9E-1961-4A8E-BA14-2564E3764BFA}");

  // lookup based on description
  string dev("Intel(R) 82579LM Gigabit Network Connection");

  if (cmdOptionExists(argv, argv + argc, "-e")) {
    EthernetControl::debugAPSEcho(dev);
    return 0;
  }

  set_ethernet_active(const_cast<char*>(dev.c_str()),true);

  int numDevices = get_numDevices();

  cout << numDevices << " APS device" << (numDevices > 1 ? "s": "")  << " found" << endl;

  if (numDevices < 1)
  	return 0;

  cout << "Attempting to initialize libaps" << endl;

  init();

  cout << "Attempting to get serials" << endl;

  char serialBuffer[100];

  for (int cnt; cnt < numDevices; cnt++) {
  	get_deviceSerial(cnt, serialBuffer);
  	cout << "Device " << cnt << " serial #: " << serialBuffer << endl;
  }

#if 0
  int rc;
  rc = connect_by_ID(0);

  cout << "connect_by_ID(0) returned " << rc << endl;

  cout << "Set sample rate " << endl;

  set_sampleRate(0,100);

  cout << "current PLL frequency = " << get_sampleRate(0) << " MHz" << endl;

  cout << "setting trigger source = EXTERNAL" << endl;

  set_trigger_source(0, EXTERNAL);

  cout << "get trigger source returns " << ((get_trigger_source(0) == INTERNAL) ? "INTERNAL" : "EXTERNAL") << endl;

  cout << "setting trigger source = INTERNAL" << endl;

  set_trigger_source(0, INTERNAL);

  cout << "get trigger source returns " << ((get_trigger_source(0) == INTERNAL) ? "INTERNAL" : "EXTERNAL") << endl;

  cout << "get channel(0) enable: " << get_channel_enabled(0,0) << endl;

  cout << "set channel(0) enabled = 1" << endl;

  set_channel_enabled(0,0,true);

  const int wfs = 1000;
  short wf[wfs];
  for (int cnt = 0; cnt < wfs; cnt++)
    wf[cnt] = (cnt < wfs/2) ? 32767 : -32767;

  cout << "loading waveform" << endl;

  set_waveform_int(0, 0, wf, wfs);

  cout << "Running" << endl;

  set_sampleRate(0,50);

  run(0);

  std::this_thread::sleep_for(std::chrono::seconds(10));

  cout << "Stopping" << endl;

  stop(0);

  set_channel_enabled(0,0,false);

  cout << "get channel(0) enable: " << get_channel_enabled(0,0) << endl;

  rc = disconnect_by_ID(0);

  cout << "disconnect_by_ID(0) returned " << rc << endl;
#endif
  return 0;
}<|endoftext|>


<commit_before>// -----------------------------------------------------------------------
// pion-common: a collection of common libraries used by the Pion Platform
// -----------------------------------------------------------------------
// Copyright (C) 2007-2008 Atomic Labs, Inc.  (http://www.atomiclabs.com)
//
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
//

#ifndef __PION_PIONHASHMAP_HEADER__
#define __PION_PIONHASHMAP_HEADER__

#include <string>
#include <cctype>
#include <boost/functional/hash.hpp>
#include <pion/PionConfig.hpp>

#if defined(PION_HAVE_UNORDERED_MAP)
	#include <tr1/unordered_map>
	#define PION_HASH_MAP std::tr1::unordered_map
	#define PION_HASH_MULTIMAP std::tr1::unordered_multimap
	#define PION_HASH_STRING boost::hash<std::string>
	#define PION_HASH(TYPE) boost::hash<TYPE>
#elif defined(PION_HAVE_EXT_HASH_MAP)
	#include <ext/hash_map>
	#if __GNUC__ >= 3
		#define PION_HASH_MAP __gnu_cxx::hash_map
		#define PION_HASH_MULTIMAP __gnu_cxx::hash_multimap
	#else
		#define PION_HASH_MAP hash_map
		#define PION_HASH_MULTIMAP hash_multimap
	#endif
	#define PION_HASH_STRING boost::hash<std::string>
	#define PION_HASH(TYPE) boost::hash<TYPE>
#elif defined(PION_HAVE_HASH_MAP)
	#include <hash_map>
	#ifdef _MSC_VER
		#define PION_HASH_MAP stdext::hash_map
		#define PION_HASH_MULTIMAP stdext::hash_multimap
		#define PION_HASH_STRING stdext::hash_compare<std::string, std::less<std::string> >
		#define PION_HASH(TYPE) stdext::hash_compare<TYPE, std::less<TYPE> >
	#else
		#define PION_HASH_MAP hash_map
		#define PION_HASH_MULTIMAP hash_multimap
		#define PION_HASH_STRING boost::hash<std::string>
		#define PION_HASH(TYPE) boost::hash<TYPE>
	#endif
#endif

/// returns true if two strings are equal (ignoring case)
struct CaseInsensitiveEqual {
	inline bool operator()(const std::string& str1, const std::string& str2) const {
		if (str1.size() != str2.size())
			return false;
		std::string::const_iterator it1 = str1.begin();
		std::string::const_iterator it2 = str2.begin();
		while ( (it1!=str1.end()) && (it2!=str2.end()) ) {
			if (tolower(*it1) != tolower(*it2))
				return false;
			++it1;
			++it2;
		}
		return true;
	}
};

/// case insensitive hash function for std::string
struct CaseInsensitiveHash {
	inline unsigned long operator()(const std::string& str) const {
		unsigned long value = 0;
		for (std::string::const_iterator i = str.begin(); i!= str.end(); ++i)
			value = static_cast<unsigned char>(tolower(*i)) + (value << 6) + (value << 16) - value;
		return value;
	}
};

/// returns true if str1 < str2 (ignoring case)
struct CaseInsensitiveLess {
	inline bool operator()(const std::string& str1, const std::string& str2) const {
		std::string::const_iterator it1 = str1.begin();
		std::string::const_iterator it2 = str2.begin();
		while ( (it1 != str1.end()) && (it2 != str2.end()) ) {
			if (tolower(*it1) != tolower(*it2))
				return (tolower(*it1) < tolower(*it2));
			++it1;
			++it2;
		}
		return (str1.size() < str2.size());
	}
};

#ifdef _MSC_VER
	/// case insensitive extension of stdext::hash_compare for std::string
	struct CaseInsensitiveHashCompare : public stdext::hash_compare<std::string, CaseInsensitiveLess> {
		// makes operator() with two arguments visible, otherwise it would be hidden by the operator() defined here
		using stdext::hash_compare<std::string, CaseInsensitiveLess>::operator();

		inline size_t operator()(const std::string& str) const {
			return CaseInsensitiveHash()(str);
		}
	};
#endif

/// data type for case-insensitive dictionary of strings
#ifdef _MSC_VER
	typedef PION_HASH_MULTIMAP<std::string, std::string, CaseInsensitiveHashCompare>	StringDictionary;
#else
	typedef PION_HASH_MULTIMAP<std::string, std::string, CaseInsensitiveHash, CaseInsensitiveEqual >	StringDictionary;
#endif

/// data type for a dictionary of strings
//typedef PION_HASH_MULTIMAP<std::string, std::string, PION_HASH_STRING >	StringDictionary;

#endif
<commit_msg>Merging r583 from 3.0.x branch into trunk:<commit_after>// -----------------------------------------------------------------------
// pion-common: a collection of common libraries used by the Pion Platform
// -----------------------------------------------------------------------
// Copyright (C) 2007-2008 Atomic Labs, Inc.  (http://www.atomiclabs.com)
//
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
//

#ifndef __PION_PIONHASHMAP_HEADER__
#define __PION_PIONHASHMAP_HEADER__

#include <string>
#include <cctype>
#include <boost/functional/hash.hpp>
#include <pion/PionConfig.hpp>

#if defined(PION_HAVE_UNORDERED_MAP)
	#include <tr1/unordered_map>
#elif defined(PION_HAVE_EXT_HASH_MAP)
	#include <ext/hash_map>
#elif defined(PION_HAVE_HASH_MAP)
	#include <hash_map>
#endif

namespace pion {	// begin namespace pion

#if defined(PION_HAVE_UNORDERED_MAP)
	#define PION_HASH_MAP std::tr1::unordered_map
	#define PION_HASH_MULTIMAP std::tr1::unordered_multimap
	#define PION_HASH_STRING boost::hash<std::string>
	#define PION_HASH(TYPE) boost::hash<TYPE>
#elif defined(PION_HAVE_EXT_HASH_MAP)
	#if __GNUC__ >= 3
		#define PION_HASH_MAP __gnu_cxx::hash_map
		#define PION_HASH_MULTIMAP __gnu_cxx::hash_multimap
	#else
		#define PION_HASH_MAP hash_map
		#define PION_HASH_MULTIMAP hash_multimap
	#endif
	#define PION_HASH_STRING boost::hash<std::string>
	#define PION_HASH(TYPE) boost::hash<TYPE>
#elif defined(PION_HAVE_HASH_MAP)
	#ifdef _MSC_VER
		#define PION_HASH_MAP stdext::hash_map
		#define PION_HASH_MULTIMAP stdext::hash_multimap
		#define PION_HASH_STRING stdext::hash_compare<std::string, std::less<std::string> >
		#define PION_HASH(TYPE) stdext::hash_compare<TYPE, std::less<TYPE> >
	#else
		#define PION_HASH_MAP hash_map
		#define PION_HASH_MULTIMAP hash_multimap
		#define PION_HASH_STRING boost::hash<std::string>
		#define PION_HASH(TYPE) boost::hash<TYPE>
	#endif
#endif

/// returns true if two strings are equal (ignoring case)
struct CaseInsensitiveEqual {
	inline bool operator()(const std::string& str1, const std::string& str2) const {
		if (str1.size() != str2.size())
			return false;
		std::string::const_iterator it1 = str1.begin();
		std::string::const_iterator it2 = str2.begin();
		while ( (it1!=str1.end()) && (it2!=str2.end()) ) {
			if (tolower(*it1) != tolower(*it2))
				return false;
			++it1;
			++it2;
		}
		return true;
	}
};

/// case insensitive hash function for std::string
struct CaseInsensitiveHash {
	inline unsigned long operator()(const std::string& str) const {
		unsigned long value = 0;
		for (std::string::const_iterator i = str.begin(); i!= str.end(); ++i)
			value = static_cast<unsigned char>(tolower(*i)) + (value << 6) + (value << 16) - value;
		return value;
	}
};

/// returns true if str1 < str2 (ignoring case)
struct CaseInsensitiveLess {
	inline bool operator()(const std::string& str1, const std::string& str2) const {
		std::string::const_iterator it1 = str1.begin();
		std::string::const_iterator it2 = str2.begin();
		while ( (it1 != str1.end()) && (it2 != str2.end()) ) {
			if (tolower(*it1) != tolower(*it2))
				return (tolower(*it1) < tolower(*it2));
			++it1;
			++it2;
		}
		return (str1.size() < str2.size());
	}
};

#ifdef _MSC_VER
	/// case insensitive extension of stdext::hash_compare for std::string
	struct CaseInsensitiveHashCompare : public stdext::hash_compare<std::string, CaseInsensitiveLess> {
		// makes operator() with two arguments visible, otherwise it would be hidden by the operator() defined here
		using stdext::hash_compare<std::string, CaseInsensitiveLess>::operator();

		inline size_t operator()(const std::string& str) const {
			return CaseInsensitiveHash()(str);
		}
	};
#endif

/// data type for case-insensitive dictionary of strings
#ifdef _MSC_VER
	typedef PION_HASH_MULTIMAP<std::string, std::string, CaseInsensitiveHashCompare>	StringDictionary;
#else
	typedef PION_HASH_MULTIMAP<std::string, std::string, CaseInsensitiveHash, CaseInsensitiveEqual >	StringDictionary;
#endif

/// data type for a dictionary of strings
//typedef PION_HASH_MULTIMAP<std::string, std::string, PION_HASH_STRING >	StringDictionary;

}	// end namespace pion

#endif
<|endoftext|>


<commit_before><commit_msg>am 16e5aba9: am 4a2a890b: Merge "Fix mismatched new[]/delete."<commit_after><|endoftext|>


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

Copyright (c) 2000-2009 Torus Knot Software Ltd

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 "OgreStableHeaders.h"

#include "OgreMovableObject.h"
#include "OgreSceneNode.h"
#include "OgreTagPoint.h"
#include "OgreLight.h"
#include "OgreEntity.h"
#include "OgreRoot.h"
#include "OgreSceneManager.h"
#include "OgreCamera.h"
#include "OgreLodListener.h"

namespace Ogre {
	//-----------------------------------------------------------------------
	//-----------------------------------------------------------------------
	uint32 MovableObject::msDefaultQueryFlags = 0xFFFFFFFF;
	uint32 MovableObject::msDefaultVisibilityFlags = 0xFFFFFFFF;
    //-----------------------------------------------------------------------
    MovableObject::MovableObject()
        : mCreator(0)
        , mManager(0)
        , mParentNode(0)
        , mParentIsTagPoint(false)
        , mVisible(true)
		, mDebugDisplay(false)
        , mUpperDistance(0)
        , mSquaredUpperDistance(0)
        , mBeyondFarDistance(false)
        , mRenderQueueID(RENDER_QUEUE_MAIN)
        , mRenderQueueIDSet(false)
		, mRenderQueuePriority(100)
		, mRenderQueuePrioritySet(false)
		, mQueryFlags(msDefaultQueryFlags)
        , mVisibilityFlags(msDefaultVisibilityFlags)
        , mCastShadows(true)
        , mRenderingDisabled(false)
        , mListener(0)
        , mLightListUpdated(0)
		, mLightMask(0xFFFFFFFF)
    {
    }
    //-----------------------------------------------------------------------
    MovableObject::MovableObject(const String& name)
        : mName(name)
        , mCreator(0)
        , mManager(0)
        , mParentNode(0)
        , mParentIsTagPoint(false)
        , mVisible(true)
		, mDebugDisplay(false)
        , mUpperDistance(0)
        , mSquaredUpperDistance(0)
        , mBeyondFarDistance(false)
        , mRenderQueueID(RENDER_QUEUE_MAIN)
        , mRenderQueueIDSet(false)
		, mRenderQueuePriority(100)
		, mRenderQueuePrioritySet(false)
		, mQueryFlags(msDefaultQueryFlags)
        , mVisibilityFlags(msDefaultVisibilityFlags)
        , mCastShadows(true)
        , mRenderingDisabled(false)
        , mListener(0)
        , mLightListUpdated(0)
		, mLightMask(0xFFFFFFFF)
    {
    }
    //-----------------------------------------------------------------------
    MovableObject::~MovableObject()
    {
        // Call listener (note, only called if there's something to do)
        if (mListener)
        {
            mListener->objectDestroyed(this);
        }

        if (mParentNode)
        {
            // detach from parent
            if (mParentIsTagPoint)
            {
                // May be we are a lod entity which not in the parent entity child object list,
                // call this method could safely ignore this case.
                static_cast<TagPoint*>(mParentNode)->getParentEntity()->detachObjectFromBone(this);
            }
            else
            {
                // May be we are a lod entity which not in the parent node child object list,
                // call this method could safely ignore this case.
                static_cast<SceneNode*>(mParentNode)->detachObject(this);
            }
        }
    }
    //-----------------------------------------------------------------------
    void MovableObject::_notifyAttached(Node* parent, bool isTagPoint)
    {
        assert(!mParentNode || !parent);

        bool different = (parent != mParentNode);

        mParentNode = parent;
        mParentIsTagPoint = isTagPoint;

        // Mark light list being dirty, simply decrease
        // counter by one for minimise overhead
        --mLightListUpdated;

        // Call listener (note, only called if there's something to do)
        if (mListener && different)
        {
            if (mParentNode)
                mListener->objectAttached(this);
            else
                mListener->objectDetached(this);
        }
    }
    //-----------------------------------------------------------------------
    Node* MovableObject::getParentNode(void) const
    {
        return mParentNode;
    }
    //-----------------------------------------------------------------------
    SceneNode* MovableObject::getParentSceneNode(void) const
    {
        if (mParentIsTagPoint)
        {
            TagPoint* tp = static_cast<TagPoint*>(mParentNode);
            return tp->getParentEntity()->getParentSceneNode();
        }
        else
        {
            return static_cast<SceneNode*>(mParentNode);
        }
    }
    //-----------------------------------------------------------------------
    bool MovableObject::isAttached(void) const
    {
        return (mParentNode != 0);

    }
	//---------------------------------------------------------------------
	void MovableObject::detachFromParent(void)
	{
		if (isAttached())
		{
			if (mParentIsTagPoint)
			{
				TagPoint* tp = static_cast<TagPoint*>(mParentNode);
				tp->getParentEntity()->detachObjectFromBone(this);
			}
			else
			{
				SceneNode* sn = static_cast<SceneNode*>(mParentNode);
				sn->detachObject(this);
			}
		}
	}
    //-----------------------------------------------------------------------
	bool MovableObject::isInScene(void) const
	{
		if (mParentNode != 0)
		{
			if (mParentIsTagPoint)
			{
				TagPoint* tp = static_cast<TagPoint*>(mParentNode);
				return tp->getParentEntity()->isInScene();
			}
			else
			{
				SceneNode* sn = static_cast<SceneNode*>(mParentNode);
				return sn->isInSceneGraph();
			}
		}
		else
		{
			return false;
		}
	}
    //-----------------------------------------------------------------------
    void MovableObject::_notifyMoved(void)
    {
        // Mark light list being dirty, simply decrease
        // counter by one for minimise overhead
        --mLightListUpdated;

        // Notify listener if exists
        if (mListener)
        {
            mListener->objectMoved(this);
        }
    }
    //-----------------------------------------------------------------------
    void MovableObject::setVisible(bool visible)
    {
        mVisible = visible;
    }
    //-----------------------------------------------------------------------
    bool MovableObject::getVisible(void) const
    {
        return mVisible;
    }
    //-----------------------------------------------------------------------
    bool MovableObject::isVisible(void) const
    {
        if (!mVisible || mBeyondFarDistance || mRenderingDisabled)
            return false;

        SceneManager* sm = Root::getSingleton()._getCurrentSceneManager();
        if (sm && !(getVisibilityFlags() & sm->_getCombinedVisibilityMask()))
            return false;

        return true;
    }
	//-----------------------------------------------------------------------
	void MovableObject::_notifyCurrentCamera(Camera* cam)
	{
		if (mParentNode)
		{
			if (cam->getUseRenderingDistance() && mUpperDistance > 0)
			{
				Real rad = getBoundingRadius();
				Real squaredDepth = mParentNode->getSquaredViewDepth(cam->getLodCamera());

				const Vector3& scl = mParentNode->_getDerivedScale();
				Real factor = std::max(std::max(scl.x, scl.y), scl.z);

				// Max distance to still render
				Real maxDist = mUpperDistance + rad * factor;
				if (squaredDepth > Math::Sqr(maxDist))
				{
					mBeyondFarDistance = true;
				}
				else
				{
					mBeyondFarDistance = false;
				}
			}
			else
			{
				mBeyondFarDistance = false;
			}

            // Construct event object
            MovableObjectLodChangedEvent evt;
            evt.movableObject = this;
            evt.camera = cam;

            // Notify lod event listeners
            cam->getSceneManager()->_notifyMovableObjectLodChanged(evt);

		}

        mRenderingDisabled = mListener && !mListener->objectRendering(this, cam);
	}
    //-----------------------------------------------------------------------
    void MovableObject::setRenderQueueGroup(uint8 queueID)
    {
		assert(queueID <= RENDER_QUEUE_MAX && "Render queue out of range!");
        mRenderQueueID = queueID;
        mRenderQueueIDSet = true;
    }

	//-----------------------------------------------------------------------
	void MovableObject::setRenderQueueGroupAndPriority(uint8 queueID, ushort priority)
	{
		setRenderQueueGroup(queueID);
		mRenderQueuePriority = queueID;
		mRenderQueuePrioritySet = true;

	}

    //-----------------------------------------------------------------------
    uint8 MovableObject::getRenderQueueGroup(void) const
    {
        return mRenderQueueID;
    }
    //-----------------------------------------------------------------------
	const Matrix4& MovableObject::_getParentNodeFullTransform(void) const
	{

		if(mParentNode)
		{
			// object attached to a sceneNode
			return mParentNode->_getFullTransform();
		}
        // fallback
        return Matrix4::IDENTITY;
	}
    //-----------------------------------------------------------------------
    const AxisAlignedBox& MovableObject::getWorldBoundingBox(bool derive) const
    {
        if (derive)
        {
            mWorldAABB = this->getBoundingBox();
            mWorldAABB.transformAffine(_getParentNodeFullTransform());
        }

        return mWorldAABB;

    }
    //-----------------------------------------------------------------------
	const Sphere& MovableObject::getWorldBoundingSphere(bool derive) const
	{
		if (derive)
		{
			const Vector3& scl = mParentNode->_getDerivedScale();
			Real factor = std::max(std::max(scl.x, scl.y), scl.z);
			mWorldBoundingSphere.setRadius(getBoundingRadius() * factor);
			mWorldBoundingSphere.setCenter(mParentNode->_getDerivedPosition());
		}
		return mWorldBoundingSphere;
	}
    //-----------------------------------------------------------------------
    const LightList& MovableObject::queryLights(void) const
    {
        // Try listener first
        if (mListener)
        {
            const LightList* lightList =
                mListener->objectQueryLights(this);
            if (lightList)
            {
                return *lightList;
            }
        }

        // Query from parent entity if exists
        if (mParentIsTagPoint)
        {
            TagPoint* tp = static_cast<TagPoint*>(mParentNode);
            return tp->getParentEntity()->queryLights();
        }

        if (mParentNode)
        {
            SceneNode* sn = static_cast<SceneNode*>(mParentNode);

            // Make sure we only update this only if need.
            ulong frame = sn->getCreator()->_getLightsDirtyCounter();
            if (mLightListUpdated != frame)
            {
                mLightListUpdated = frame;

				const Vector3& scl = mParentNode->_getDerivedScale();
				Real factor = std::max(std::max(scl.x, scl.y), scl.z);

                sn->findLights(mLightList, this->getBoundingRadius() * factor, this->getLightMask());
            }
        }
        else
        {
            mLightList.clear();
        }

        return mLightList;
    }
    //-----------------------------------------------------------------------
    ShadowCaster::ShadowRenderableListIterator MovableObject::getShadowVolumeRenderableIterator(
        ShadowTechnique shadowTechnique, const Light* light,
        HardwareIndexBufferSharedPtr* indexBuffer,
        bool inExtrudeVertices, Real extrusionDist, unsigned long flags )
    {
        static ShadowRenderableList dummyList;
        return ShadowRenderableListIterator(dummyList.begin(), dummyList.end());
    }
    //-----------------------------------------------------------------------
    const AxisAlignedBox& MovableObject::getLightCapBounds(void) const
    {
        // Same as original bounds
        return getWorldBoundingBox();
    }
    //-----------------------------------------------------------------------
    const AxisAlignedBox& MovableObject::getDarkCapBounds(const Light& light, Real extrusionDist) const
    {
        // Extrude own light cap bounds
        mWorldDarkCapBounds = getLightCapBounds();
        this->extrudeBounds(mWorldDarkCapBounds, light.getAs4DVector(),
            extrusionDist);
        return mWorldDarkCapBounds;

    }
    //-----------------------------------------------------------------------
    Real MovableObject::getPointExtrusionDistance(const Light* l) const
    {
        if (mParentNode)
        {
            return getExtrusionDistance(mParentNode->_getDerivedPosition(), l);
        }
        else
        {
            return 0;
        }
    }
	//-----------------------------------------------------------------------
	uint32 MovableObject::getTypeFlags(void) const
	{
		if (mCreator)
		{
			return mCreator->getTypeFlags();
		}
		else
		{
			return 0xFFFFFFFF;
		}
	}
	//---------------------------------------------------------------------
	void MovableObject::setLightMask(uint32 lightMask)
	{
		this->mLightMask = lightMask;
		//make sure to request a new light list from the scene manager if mask changed
		mLightListUpdated = 0;
	}
	//---------------------------------------------------------------------
	class MORecvShadVisitor : public Renderable::Visitor
	{
	public:
		bool anyReceiveShadows;
		MORecvShadVisitor() : anyReceiveShadows(false)
		{

		}
		void visit(Renderable* rend, ushort lodIndex, bool isDebug,
			Any* pAny = 0)
		{
			Technique* tech = rend->getTechnique();
			bool techReceivesShadows = tech && tech->getParent()->getReceiveShadows();
			anyReceiveShadows = anyReceiveShadows ||
				techReceivesShadows || !tech;
		}
	};
	//---------------------------------------------------------------------
	bool MovableObject::getReceivesShadows()
	{
		MORecvShadVisitor visitor;
		visitRenderables(&visitor);
		return visitor.anyReceiveShadows;

	}
	//-----------------------------------------------------------------------
	//-----------------------------------------------------------------------
	MovableObject* MovableObjectFactory::createInstance(
		const String& name, SceneManager* manager,
		const NameValuePairList* params)
	{
		MovableObject* m = createInstanceImpl(name, params);
		m->_notifyCreator(this);
		m->_notifyManager(manager);
		return m;
	}

}

<commit_msg>Patch 3153910 - Fix a typo in MovableObject::setRenderQueueGroupAndPriority.  Render queue priority should be set to the priority argument, not the queue ID.<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2009 Torus Knot Software Ltd

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 "OgreStableHeaders.h"

#include "OgreMovableObject.h"
#include "OgreSceneNode.h"
#include "OgreTagPoint.h"
#include "OgreLight.h"
#include "OgreEntity.h"
#include "OgreRoot.h"
#include "OgreSceneManager.h"
#include "OgreCamera.h"
#include "OgreLodListener.h"

namespace Ogre {
	//-----------------------------------------------------------------------
	//-----------------------------------------------------------------------
	uint32 MovableObject::msDefaultQueryFlags = 0xFFFFFFFF;
	uint32 MovableObject::msDefaultVisibilityFlags = 0xFFFFFFFF;
    //-----------------------------------------------------------------------
    MovableObject::MovableObject()
        : mCreator(0)
        , mManager(0)
        , mParentNode(0)
        , mParentIsTagPoint(false)
        , mVisible(true)
		, mDebugDisplay(false)
        , mUpperDistance(0)
        , mSquaredUpperDistance(0)
        , mBeyondFarDistance(false)
        , mRenderQueueID(RENDER_QUEUE_MAIN)
        , mRenderQueueIDSet(false)
		, mRenderQueuePriority(100)
		, mRenderQueuePrioritySet(false)
		, mQueryFlags(msDefaultQueryFlags)
        , mVisibilityFlags(msDefaultVisibilityFlags)
        , mCastShadows(true)
        , mRenderingDisabled(false)
        , mListener(0)
        , mLightListUpdated(0)
		, mLightMask(0xFFFFFFFF)
    {
    }
    //-----------------------------------------------------------------------
    MovableObject::MovableObject(const String& name)
        : mName(name)
        , mCreator(0)
        , mManager(0)
        , mParentNode(0)
        , mParentIsTagPoint(false)
        , mVisible(true)
		, mDebugDisplay(false)
        , mUpperDistance(0)
        , mSquaredUpperDistance(0)
        , mBeyondFarDistance(false)
        , mRenderQueueID(RENDER_QUEUE_MAIN)
        , mRenderQueueIDSet(false)
		, mRenderQueuePriority(100)
		, mRenderQueuePrioritySet(false)
		, mQueryFlags(msDefaultQueryFlags)
        , mVisibilityFlags(msDefaultVisibilityFlags)
        , mCastShadows(true)
        , mRenderingDisabled(false)
        , mListener(0)
        , mLightListUpdated(0)
		, mLightMask(0xFFFFFFFF)
    {
    }
    //-----------------------------------------------------------------------
    MovableObject::~MovableObject()
    {
        // Call listener (note, only called if there's something to do)
        if (mListener)
        {
            mListener->objectDestroyed(this);
        }

        if (mParentNode)
        {
            // detach from parent
            if (mParentIsTagPoint)
            {
                // May be we are a lod entity which not in the parent entity child object list,
                // call this method could safely ignore this case.
                static_cast<TagPoint*>(mParentNode)->getParentEntity()->detachObjectFromBone(this);
            }
            else
            {
                // May be we are a lod entity which not in the parent node child object list,
                // call this method could safely ignore this case.
                static_cast<SceneNode*>(mParentNode)->detachObject(this);
            }
        }
    }
    //-----------------------------------------------------------------------
    void MovableObject::_notifyAttached(Node* parent, bool isTagPoint)
    {
        assert(!mParentNode || !parent);

        bool different = (parent != mParentNode);

        mParentNode = parent;
        mParentIsTagPoint = isTagPoint;

        // Mark light list being dirty, simply decrease
        // counter by one for minimise overhead
        --mLightListUpdated;

        // Call listener (note, only called if there's something to do)
        if (mListener && different)
        {
            if (mParentNode)
                mListener->objectAttached(this);
            else
                mListener->objectDetached(this);
        }
    }
    //-----------------------------------------------------------------------
    Node* MovableObject::getParentNode(void) const
    {
        return mParentNode;
    }
    //-----------------------------------------------------------------------
    SceneNode* MovableObject::getParentSceneNode(void) const
    {
        if (mParentIsTagPoint)
        {
            TagPoint* tp = static_cast<TagPoint*>(mParentNode);
            return tp->getParentEntity()->getParentSceneNode();
        }
        else
        {
            return static_cast<SceneNode*>(mParentNode);
        }
    }
    //-----------------------------------------------------------------------
    bool MovableObject::isAttached(void) const
    {
        return (mParentNode != 0);

    }
	//---------------------------------------------------------------------
	void MovableObject::detachFromParent(void)
	{
		if (isAttached())
		{
			if (mParentIsTagPoint)
			{
				TagPoint* tp = static_cast<TagPoint*>(mParentNode);
				tp->getParentEntity()->detachObjectFromBone(this);
			}
			else
			{
				SceneNode* sn = static_cast<SceneNode*>(mParentNode);
				sn->detachObject(this);
			}
		}
	}
    //-----------------------------------------------------------------------
	bool MovableObject::isInScene(void) const
	{
		if (mParentNode != 0)
		{
			if (mParentIsTagPoint)
			{
				TagPoint* tp = static_cast<TagPoint*>(mParentNode);
				return tp->getParentEntity()->isInScene();
			}
			else
			{
				SceneNode* sn = static_cast<SceneNode*>(mParentNode);
				return sn->isInSceneGraph();
			}
		}
		else
		{
			return false;
		}
	}
    //-----------------------------------------------------------------------
    void MovableObject::_notifyMoved(void)
    {
        // Mark light list being dirty, simply decrease
        // counter by one for minimise overhead
        --mLightListUpdated;

        // Notify listener if exists
        if (mListener)
        {
            mListener->objectMoved(this);
        }
    }
    //-----------------------------------------------------------------------
    void MovableObject::setVisible(bool visible)
    {
        mVisible = visible;
    }
    //-----------------------------------------------------------------------
    bool MovableObject::getVisible(void) const
    {
        return mVisible;
    }
    //-----------------------------------------------------------------------
    bool MovableObject::isVisible(void) const
    {
        if (!mVisible || mBeyondFarDistance || mRenderingDisabled)
            return false;

        SceneManager* sm = Root::getSingleton()._getCurrentSceneManager();
        if (sm && !(getVisibilityFlags() & sm->_getCombinedVisibilityMask()))
            return false;

        return true;
    }
	//-----------------------------------------------------------------------
	void MovableObject::_notifyCurrentCamera(Camera* cam)
	{
		if (mParentNode)
		{
			if (cam->getUseRenderingDistance() && mUpperDistance > 0)
			{
				Real rad = getBoundingRadius();
				Real squaredDepth = mParentNode->getSquaredViewDepth(cam->getLodCamera());

				const Vector3& scl = mParentNode->_getDerivedScale();
				Real factor = std::max(std::max(scl.x, scl.y), scl.z);

				// Max distance to still render
				Real maxDist = mUpperDistance + rad * factor;
				if (squaredDepth > Math::Sqr(maxDist))
				{
					mBeyondFarDistance = true;
				}
				else
				{
					mBeyondFarDistance = false;
				}
			}
			else
			{
				mBeyondFarDistance = false;
			}

            // Construct event object
            MovableObjectLodChangedEvent evt;
            evt.movableObject = this;
            evt.camera = cam;

            // Notify lod event listeners
            cam->getSceneManager()->_notifyMovableObjectLodChanged(evt);

		}

        mRenderingDisabled = mListener && !mListener->objectRendering(this, cam);
	}
    //-----------------------------------------------------------------------
    void MovableObject::setRenderQueueGroup(uint8 queueID)
    {
		assert(queueID <= RENDER_QUEUE_MAX && "Render queue out of range!");
        mRenderQueueID = queueID;
        mRenderQueueIDSet = true;
    }

	//-----------------------------------------------------------------------
	void MovableObject::setRenderQueueGroupAndPriority(uint8 queueID, ushort priority)
	{
		setRenderQueueGroup(queueID);
		mRenderQueuePriority = priority;
		mRenderQueuePrioritySet = true;

	}

    //-----------------------------------------------------------------------
    uint8 MovableObject::getRenderQueueGroup(void) const
    {
        return mRenderQueueID;
    }
    //-----------------------------------------------------------------------
	const Matrix4& MovableObject::_getParentNodeFullTransform(void) const
	{

		if(mParentNode)
		{
			// object attached to a sceneNode
			return mParentNode->_getFullTransform();
		}
        // fallback
        return Matrix4::IDENTITY;
	}
    //-----------------------------------------------------------------------
    const AxisAlignedBox& MovableObject::getWorldBoundingBox(bool derive) const
    {
        if (derive)
        {
            mWorldAABB = this->getBoundingBox();
            mWorldAABB.transformAffine(_getParentNodeFullTransform());
        }

        return mWorldAABB;

    }
    //-----------------------------------------------------------------------
	const Sphere& MovableObject::getWorldBoundingSphere(bool derive) const
	{
		if (derive)
		{
			const Vector3& scl = mParentNode->_getDerivedScale();
			Real factor = std::max(std::max(scl.x, scl.y), scl.z);
			mWorldBoundingSphere.setRadius(getBoundingRadius() * factor);
			mWorldBoundingSphere.setCenter(mParentNode->_getDerivedPosition());
		}
		return mWorldBoundingSphere;
	}
    //-----------------------------------------------------------------------
    const LightList& MovableObject::queryLights(void) const
    {
        // Try listener first
        if (mListener)
        {
            const LightList* lightList =
                mListener->objectQueryLights(this);
            if (lightList)
            {
                return *lightList;
            }
        }

        // Query from parent entity if exists
        if (mParentIsTagPoint)
        {
            TagPoint* tp = static_cast<TagPoint*>(mParentNode);
            return tp->getParentEntity()->queryLights();
        }

        if (mParentNode)
        {
            SceneNode* sn = static_cast<SceneNode*>(mParentNode);

            // Make sure we only update this only if need.
            ulong frame = sn->getCreator()->_getLightsDirtyCounter();
            if (mLightListUpdated != frame)
            {
                mLightListUpdated = frame;

				const Vector3& scl = mParentNode->_getDerivedScale();
				Real factor = std::max(std::max(scl.x, scl.y), scl.z);

                sn->findLights(mLightList, this->getBoundingRadius() * factor, this->getLightMask());
            }
        }
        else
        {
            mLightList.clear();
        }

        return mLightList;
    }
    //-----------------------------------------------------------------------
    ShadowCaster::ShadowRenderableListIterator MovableObject::getShadowVolumeRenderableIterator(
        ShadowTechnique shadowTechnique, const Light* light,
        HardwareIndexBufferSharedPtr* indexBuffer,
        bool inExtrudeVertices, Real extrusionDist, unsigned long flags )
    {
        static ShadowRenderableList dummyList;
        return ShadowRenderableListIterator(dummyList.begin(), dummyList.end());
    }
    //-----------------------------------------------------------------------
    const AxisAlignedBox& MovableObject::getLightCapBounds(void) const
    {
        // Same as original bounds
        return getWorldBoundingBox();
    }
    //-----------------------------------------------------------------------
    const AxisAlignedBox& MovableObject::getDarkCapBounds(const Light& light, Real extrusionDist) const
    {
        // Extrude own light cap bounds
        mWorldDarkCapBounds = getLightCapBounds();
        this->extrudeBounds(mWorldDarkCapBounds, light.getAs4DVector(),
            extrusionDist);
        return mWorldDarkCapBounds;

    }
    //-----------------------------------------------------------------------
    Real MovableObject::getPointExtrusionDistance(const Light* l) const
    {
        if (mParentNode)
        {
            return getExtrusionDistance(mParentNode->_getDerivedPosition(), l);
        }
        else
        {
            return 0;
        }
    }
	//-----------------------------------------------------------------------
	uint32 MovableObject::getTypeFlags(void) const
	{
		if (mCreator)
		{
			return mCreator->getTypeFlags();
		}
		else
		{
			return 0xFFFFFFFF;
		}
	}
	//---------------------------------------------------------------------
	void MovableObject::setLightMask(uint32 lightMask)
	{
		this->mLightMask = lightMask;
		//make sure to request a new light list from the scene manager if mask changed
		mLightListUpdated = 0;
	}
	//---------------------------------------------------------------------
	class MORecvShadVisitor : public Renderable::Visitor
	{
	public:
		bool anyReceiveShadows;
		MORecvShadVisitor() : anyReceiveShadows(false)
		{

		}
		void visit(Renderable* rend, ushort lodIndex, bool isDebug,
			Any* pAny = 0)
		{
			Technique* tech = rend->getTechnique();
			bool techReceivesShadows = tech && tech->getParent()->getReceiveShadows();
			anyReceiveShadows = anyReceiveShadows ||
				techReceivesShadows || !tech;
		}
	};
	//---------------------------------------------------------------------
	bool MovableObject::getReceivesShadows()
	{
		MORecvShadVisitor visitor;
		visitRenderables(&visitor);
		return visitor.anyReceiveShadows;

	}
	//-----------------------------------------------------------------------
	//-----------------------------------------------------------------------
	MovableObject* MovableObjectFactory::createInstance(
		const String& name, SceneManager* manager,
		const NameValuePairList* params)
	{
		MovableObject* m = createInstanceImpl(name, params);
		m->_notifyCreator(this);
		m->_notifyManager(manager);
		return m;
	}

}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: SlsPageObjectViewContact.hxx,v $
 * $Revision: 1.8 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef SD_SLIDESORTER_PAGE_OBJECT_VIEW_CONTACT_HXX
#define SD_SLIDESORTER_PAGE_OBJECT_VIEW_CONTACT_HXX

#include "model/SlsSharedPageDescriptor.hxx"
#include <svx/sdtakitm.hxx>
#include <svx/sdr/contact/viewcontactofpageobj.hxx>

class SdrPageObj;

namespace sdr {namespace contact {
class ViewObjectContact;
class ObjectContact;
} }

namespace sd { namespace slidesorter { namespace view {

/** Details:
    This class has to provide the bounding box but can not determine it
    fully because it has no access to the output device.  It therefore
    retrieves some of the necessary data, the border, from the
    PageDescriptor which acts here as persistent storage.
*/
class PageObjectViewContact
    : public ::sdr::contact::ViewContactOfPageObj
{
public:
    PageObjectViewContact (
        SdrPageObj& rPageObj,
        const model::SharedPageDescriptor& rpDescriptor);
    ~PageObjectViewContact (void);

    /** Create a ViewObjectContact object that buffers its output in a
        bitmap.
        @return
            Ownership of the new object passes to the caller.
    */
    virtual ::sdr::contact::ViewObjectContact&
        CreateObjectSpecificViewObjectContact(
            ::sdr::contact::ObjectContact& rObjectContact);

    const SdrPage* GetPage (void) const;

    SdrPageObj& GetPageObject (void) const;

    Rectangle GetPageObjectBoundingBox (void) const;

    /** Return the original bounding box of the page objects, not the
        enlarged rectangle that encloses the frames, indicators, and the
        title (as returned by GetPaintRectangle()).
    */
    virtual Rectangle GetPageRectangle (void);

    virtual void ActionChanged (void);

protected:
    /** Enlarge the paint rectangle of the base class by the space that is
        used to paint the focus and selection indicators, the fade effect
        indicator, and the slide name.
    */
    virtual void CalcPaintRectangle (void);

    virtual void PrepareDelete (void);

private:
    // The bounding box that is calculated by the base class implementation
    // of the CalcPaintRectangle() method.
    Rectangle maPageObjectBoundingBox;

    /** This flag is set as long as PrepareDelete() has not been called.
    */
    bool mbIsValid;

    model::SharedPageDescriptor mpDescriptor;
};

} } } // end of namespace ::sd::slidesorter::view

#endif
<commit_msg>INTEGRATION: CWS aw033 (1.6.46); FILE MERGED 2008/07/10 12:56:27 aw 1.6.46.4: #i39532# XOutputDevice removed, PrepareDelete removed 2008/05/14 14:51:09 aw 1.6.46.3: RESYNC: (1.6-1.8); FILE MERGED 2008/01/29 10:34:21 aw 1.6.46.2: updated refresh for ActionChanged(), diverse removals 2008/01/22 12:16:41 aw 1.6.46.1: adaptions and 1st stripping<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: SlsPageObjectViewContact.hxx,v $
 * $Revision: 1.9 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef SD_SLIDESORTER_PAGE_OBJECT_VIEW_CONTACT_HXX
#define SD_SLIDESORTER_PAGE_OBJECT_VIEW_CONTACT_HXX

#include "model/SlsSharedPageDescriptor.hxx"
#include <svx/sdtakitm.hxx>
#include <svx/sdr/contact/viewcontactofpageobj.hxx>

class SdrPageObj;

namespace sdr {namespace contact {
class ViewObjectContact;
class ObjectContact;
} }

namespace sd { namespace slidesorter { namespace view {

/** Details:
    This class has to provide the bounding box but can not determine it
    fully because it has no access to the output device.  It therefore
    retrieves some of the necessary data, the border, from the
    PageDescriptor which acts here as persistent storage.
*/
class PageObjectViewContact
    : public ::sdr::contact::ViewContactOfPageObj
{
public:
    PageObjectViewContact (
        SdrPageObj& rPageObj,
        const model::SharedPageDescriptor& rpDescriptor);
    ~PageObjectViewContact (void);

    /** Create a ViewObjectContact object that buffers its output in a
        bitmap.
        @return
            Ownership of the new object passes to the caller.
    */
    virtual ::sdr::contact::ViewObjectContact&
        CreateObjectSpecificViewObjectContact(
            ::sdr::contact::ObjectContact& rObjectContact);

    const SdrPage* GetPage (void) const;

    SdrPageObj& GetPageObject (void) const;

    Rectangle GetPageObjectBoundingBox (void) const;

    virtual void ActionChanged (void);

protected:
    // create graphical visualisation data
    virtual drawinglayer::primitive2d::Primitive2DSequence createViewIndependentPrimitive2DSequence() const;

private:
    /** This flag is set to <TRUE/> when the destructor is called to
        indicate that further calls made to it must not call outside.
    */
    bool mbInDestructor;

    model::SharedPageDescriptor mpDescriptor;
};

} } } // end of namespace ::sd::slidesorter::view

#endif
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
#pragma once
#include <gtest\gtest.h>
#include "SimdX.hpp"
#include "SIMD/Vector2v.hpp"
#include "SIMD/Vector3v.hpp"
#include "SIMD/Vector4v.hpp"

// Test code gen.
TEST(SimdX, IntersectRayBox)
{
	using namespace Cpf;
	using namespace Math;
	using namespace SIMD;

	Vector3v<F32x4_3> rayOrg(0.0f, 0.0f, 0.0f);
	Vector3v<F32x4_3> invDir(0.0f, 0.0f, 1.0f);
	Vector3v<F32x4_3> bbmin(5.0f, 5.0f, 1.0f);
	Vector3v<F32x4_3> bbmax(6.0f, 5.0f, 2.0f);
	float hitT = 0.0f;

	Vector3v<F32x4_3> d0 = (bbmin - rayOrg) * invDir;
	Vector3v<F32x4_3> d1 = (bbmax - rayOrg) * invDir;

	Vector3v<F32x4_3> v0 = Min(d0, d1);
	Vector3v<F32x4_3> v1 = Max(d0, d1);

	auto tmin = HMax(v0);
	auto tmax = HMin(v1);

	hitT = tmin;
	bool hit = (tmax >= 0.0f) && (tmax >= tmin) && (tmin <= hitT);
	EXPECT_FALSE(hit);

	/* Current codegen, looks pretty decent but it is
	   spilling one register though, trying to figure it out.

	   00007FF61A5E3279  movaps      xmm4,xmmword ptr [__xmm@000000003f8000000000000000000000 (07FF61A659F50h)]
	   00007FF61A5E3280  movaps      xmm1,xmm4
	   00007FF61A5E3283  minps       xmm1,xmmword ptr [__xmm@00000000400000000000000000000000 (07FF61A662280h)]
	   00007FF61A5E328A  maxps       xmm4,xmmword ptr [__xmm@00000000400000000000000000000000 (07FF61A662280h)]
	   00007FF61A5E3291  movaps      xmm0,xmm1
	   00007FF61A5E3294  movhlps     xmm0,xmm1
	   00007FF61A5E3297  maxps       xmm1,xmm0
	   00007FF61A5E329A  shufps      xmm0,xmm0,1
	   00007FF61A5E329E  maxss       xmm1,xmm0
	   00007FF61A5E32A2  movaps      xmm0,xmm4
	   00007FF61A5E32A5  movhlps     xmm0,xmm4
	   00007FF61A5E32A8  movaps      xmm2,xmm4
	   00007FF61A5E32AB  minps       xmm2,xmm0
	   00007FF61A5E32AE  shufps      xmm4,xmm4,1
	   00007FF61A5E32B2  minss       xmm2,xmm4
	   00007FF61A5E32B6  movss       dword ptr [rsp+30h],xmm1
	   00007FF61A5E32BC  xorps       xmm0,xmm0
	   00007FF61A5E32BF  cmpleps     xmm0,xmm2
	   00007FF61A5E32C3  movmskps    eax,xmm0
	   00007FF61A5E32C6  test        al,1
	   00007FF61A5E32C8  je          SimdX_IntersectRayBox_Test::TestBody+0A1h (07FF61A5E32F1h)
	   00007FF61A5E32CA  movaps      xmm0,xmm1
	   00007FF61A5E32CD  cmpleps     xmm0,xmm2
	   00007FF61A5E32D1  movmskps    eax,xmm0
	   00007FF61A5E32D4  test        al,1
	   00007FF61A5E32D6  je          SimdX_IntersectRayBox_Test::TestBody+0A1h (07FF61A5E32F1h)
	   00007FF61A5E32D8  movss       xmm0,dword ptr [rsp+30h]
	   00007FF61A5E32DE  shufps      xmm0,xmm0,0
	   00007FF61A5E32E2  cmpleps     xmm1,xmm0
	   00007FF61A5E32E6  movmskps    eax,xmm1
	   00007FF61A5E32E9  test        al,1
	   00007FF61A5E32EB  je          SimdX_IntersectRayBox_Test::TestBody+0A1h (07FF61A5E32F1h)
	   00007FF61A5E32ED  mov         al,1
	   00007FF61A5E32EF  jmp         SimdX_IntersectRayBox_Test::TestBody+0A3h (07FF61A5E32F3h)
	   00007FF61A5E32F1  xor         al,al
	   */
}
<commit_msg>It wasn't actually a problem in the simd, it was the actual test. The codegen looks almost perfect other than some specific optimizations which can be put in the simd code itself.<commit_after>//////////////////////////////////////////////////////////////////////////
#pragma once
#include <gtest\gtest.h>
#include "SimdX.hpp"
#include "SIMD/Vector2v.hpp"
#include "SIMD/Vector3v.hpp"
#include "SIMD/Vector4v.hpp"

// Test code gen.
TEST(SimdX, IntersectRayBox)
{
	using namespace Cpf;
	using namespace Math;
	using namespace SIMD;

	Vector3v<F32x4_3> rayOrg(0.0f, 0.0f, 0.0f);
	Vector3v<F32x4_3> invDir(0.0f, 0.0f, 1.0f);
	Vector3v<F32x4_3> bbmin(5.0f, 5.0f, 1.0f);
	Vector3v<F32x4_3> bbmax(6.0f, 5.0f, 2.0f);

	Vector3v<F32x4_3> d0 = (bbmin - rayOrg) * invDir;
	Vector3v<F32x4_3> d1 = (bbmax - rayOrg) * invDir;

	Vector3v<F32x4_3> v0 = Min(d0, d1);
	Vector3v<F32x4_3> v1 = Max(d0, d1);

	auto tmin = HMax(v0);
	auto tmax = HMin(v1);

	auto hitT = tmin;
	bool hit = (tmax >= 0.0f) && (tmax >= tmin) && (tmin <= hitT);
	EXPECT_FALSE(hit);

	/* Current codegen, looks almost perfect now, auto is your friend in this case.
	   00007FF6FFA13279  movaps      xmm4,xmmword ptr [__xmm@000000003f8000000000000000000000 (07FF6FFA89F50h)]
	   00007FF6FFA13280  movaps      xmm1,xmm4
	   00007FF6FFA13283  minps       xmm1,xmmword ptr [__xmm@00000000400000000000000000000000 (07FF6FFA92280h)]
	   00007FF6FFA1328A  maxps       xmm4,xmmword ptr [__xmm@00000000400000000000000000000000 (07FF6FFA92280h)]
	   00007FF6FFA13291  movaps      xmm0,xmm1
	   00007FF6FFA13294  movhlps     xmm0,xmm1
	   00007FF6FFA13297  maxps       xmm1,xmm0
	   00007FF6FFA1329A  shufps      xmm0,xmm0,1
	   00007FF6FFA1329E  maxss       xmm1,xmm0
	   00007FF6FFA132A2  movaps      xmm0,xmm4
	   00007FF6FFA132A5  movhlps     xmm0,xmm4
	   00007FF6FFA132A8  movaps      xmm2,xmm4
	   00007FF6FFA132AB  minps       xmm2,xmm0
	   00007FF6FFA132AE  shufps      xmm4,xmm4,1
	   00007FF6FFA132B2  minss       xmm2,xmm4
	   00007FF6FFA132B6  xorps       xmm0,xmm0
	   00007FF6FFA132B9  cmpleps     xmm0,xmm2
	   00007FF6FFA132BD  movmskps    eax,xmm0
	   00007FF6FFA132C0  test        al,1
	   00007FF6FFA132C2  je          SimdX_IntersectRayBox_Test::TestBody+91h (07FF6FFA132E1h)
	   00007FF6FFA132C4  movaps      xmm0,xmm1
	   00007FF6FFA132C7  cmpleps     xmm0,xmm2
	   00007FF6FFA132CB  movmskps    eax,xmm0
	   00007FF6FFA132CE  test        al,1
	   00007FF6FFA132D0  je          SimdX_IntersectRayBox_Test::TestBody+91h (07FF6FFA132E1h)
	   00007FF6FFA132D2  cmpleps     xmm1,xmm1
	   00007FF6FFA132D6  movmskps    eax,xmm1
	   00007FF6FFA132D9  test        al,1
	   00007FF6FFA132DB  je          SimdX_IntersectRayBox_Test::TestBody+91h (07FF6FFA132E1h)
	   00007FF6FFA132DD  mov         al,1
	   00007FF6FFA132DF  jmp         SimdX_IntersectRayBox_Test::TestBody+93h (07FF6FFA132E3h)
	   00007FF6FFA132E1  xor         al,al
	   */
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qquickaccessibleattached_p.h"

#ifndef QT_NO_ACCESSIBILITY

#include "private/qquickitem_p.h"

QT_BEGIN_NAMESPACE

/*!
    \qmltype Accessible
    \instantiates QQuickAccessibleAttached
    \brief Enables accessibility of QML items

    \inqmlmodule QtQuick
    \ingroup qtquick-visual-utility
    \ingroup accessibility

    This class is part of \l {Accessibility for Qt Quick Applications}.

    Items the user interacts with or that give information to the user
    need to expose their information in a semantic way.
    Then assistive tools can make use of that information to enable
    users to interact with the application in various ways.

    This enables Qt Quick applications to be used with screen-readers for example.

    The most important properties to set are \l name and \l role.

    \sa Accessibility
*/

/*!
    \qmlproperty string QtQuick::Accessible::name

    This property sets an accessible name.
    For a button for example, this should have a binding to its text.
    In general this property should be set to a simple and concise
    but human readable name. Do not include the type of control
    you want to represent but just the name.
*/

/*!
    \qmlproperty string QtQuick::Accessible::description

    This property sets an accessible description.
    Similar to the name it describes the item. The description
    can be a little more verbose and tell what the item does,
    for example the functionallity of the button it describes.
*/

/*!
    \qmlproperty enumeration QtQuick::Accessible::role

    This flags sets the semantic type of the widget.
    A button for example would have "Button" as type.
    The value must be one of \l QAccessible::Role .
    Example:
    \qml
    Item {
        id: myButton

        Text {
            id: label
            // ...
        }

        Accessible.name: label.text
        Accessible.role: Accessible.Button

        function accessiblePressAction() {
            //...
        }
    }
    \endqml

    Some roles have special semantics.
    In order to implement check boxes for example a "checked" property is expected.

    \table
    \header
        \li \b {Role}
        \li \b {Expected property}
        \li

    \row
        \li Button
        \li function accessiblePressAction
        \li Called when the button receives a press action. The implementation should visually simulate a button click and perform the button action.
    \row
       \li CheckBox, Radiobutton
       \li checked
       \li The check state of the check box. Updated on Press, Check and Uncheck actions.
    \row
       \li Slider, SpinBox, Dial, ScrollBar
       \li value, minimumValue, maximumValue, stepSize
       \li value will be updated on increase and decrase actions, in accordance with the other properties

    \endtable
*/

/*! \qmlproperty bool focusable
    \brief This property holds whether this item is focusable.

    By default, this property is false except for items where the role is one of
    CheckBox, RadioButton, Button, MenuItem, PageTab, EditableText, SpinBox, ComboBox,
    Terminal or ScrollBar.
*/
/*! \qmlproperty bool focused
    \brief This property holds whether this item currently has the active focus.

    By default, this property is false, but it will return true for items that
    have \l QQuickItem::hasActiveFocus() returning true.
*/
/*! \qmlproperty bool checkable
    \brief This property holds whether this item is checkable (like a check box or some buttons).
*/
/*! \qmlproperty bool checked
    \brief This property holds whether this item is currently checked.
*/
/*! \qmlproperty bool editable
    \brief This property holds whether this item has editable text.
*/
/*! \qmlproperty bool multiLine
    \brief This property holds whether this item has multiple text lines.
*/
/*! \qmlproperty bool readOnly
    \brief This property holds whether this item while being of type \l QAccessible::EditableText
    is set to read-only.
*/
/*! \qmlproperty bool selected
    \brief This property holds whether this item is selected.
*/
/*! \qmlproperty bool selectable
    \brief This property holds whether this item can be selected.
*/
/*! \qmlproperty bool pressed
    \brief This property holds whether this item is pressed (for example a button during a mouse click).
*/
/*! \qmlproperty bool checkStateMixed
    \brief This property holds whether this item is in the partially checked state.
*/
/*! \qmlproperty bool defaultButton
    \brief This property holds whether this item is the default button of a dialog.
*/
/*! \qmlproperty bool passwordEdit
    \brief This property holds whether this item is a password text edit.
*/
/*! \qmlproperty bool selectableText
    \brief This property holds whether this item contains selectable text.
*/

QQuickAccessibleAttached::QQuickAccessibleAttached(QObject *parent)
    : QObject(parent), m_role(QAccessible::NoRole)
{
    Q_ASSERT(parent);
    QQuickItem *item = qobject_cast<QQuickItem*>(parent);
    if (!item)
        return;

    // Enable accessibility for items with accessible content. This also
    // enables accessibility for the ancestors of souch items.
    item->d_func()->setAccessibleFlagAndListener();
    QAccessibleEvent ev(item, QAccessible::ObjectCreated);
    QAccessible::updateAccessibility(&ev);

    if (!parent->property("value").isNull()) {
        connect(parent, SIGNAL(valueChanged()), this, SLOT(valueChanged()));
    }
    if (!parent->property("cursorPosition").isNull()) {
        connect(parent, SIGNAL(cursorPositionChanged()), this, SLOT(cursorPositionChanged()));
    }
}

QQuickAccessibleAttached::~QQuickAccessibleAttached()
{
}

QQuickAccessibleAttached *QQuickAccessibleAttached::qmlAttachedProperties(QObject *obj)
{
    return new QQuickAccessibleAttached(obj);
}

QT_END_NAMESPACE

#endif
<commit_msg>Fix AccessibleAttached property documentation<commit_after>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qquickaccessibleattached_p.h"

#ifndef QT_NO_ACCESSIBILITY

#include "private/qquickitem_p.h"

QT_BEGIN_NAMESPACE

/*!
    \qmltype Accessible
    \instantiates QQuickAccessibleAttached
    \brief Enables accessibility of QML items

    \inqmlmodule QtQuick
    \ingroup qtquick-visual-utility
    \ingroup accessibility

    This class is part of the \l {Accessibility for Qt Quick Applications}.

    Items the user interacts with or that give information to the user
    need to expose their information to the accessibility framework.
    Then assistive tools can make use of that information to enable
    users to interact with the application in various ways.
    This enables Qt Quick applications to be used with screen-readers for example.

    The most important properties are \l name, \l description and \l role.

    Example implementation of a simple button:
    \qml
    Rectangle {
        id: myButton
        Text {
            id: label
            text: "next"
        }
        Accessible.role: Accessible.Button
        Accessible.name: label.text
        Accessible.description: "shows the next page"
        function accessiblePressAction() {
            // do a button click
        }
    }
    \endqml
    The \l role is set to \c Button to indicate the type of control.
    \l Accessible.name is the most important information and bound to the text on the button.
    The name is a short and consise description of the control and should reflect the visual label.
    In this case it is not clear what the button does with the name only, so \l description contains
    an explanation.
    There is also a function \c accessiblePressAction() which can be invoked by assistive tools to trigger
    the button. This function needs to have the same effect as tapping or clicking the button would have.

    \sa Accessibility
*/

/*!
    \qmlproperty string QtQuick::Accessible::name

    This property sets an accessible name.
    For a button for example, this should have a binding to its text.
    In general this property should be set to a simple and concise
    but human readable name. Do not include the type of control
    you want to represent but just the name.
*/

/*!
    \qmlproperty string QtQuick::Accessible::description

    This property sets an accessible description.
    Similar to the name it describes the item. The description
    can be a little more verbose and tell what the item does,
    for example the functionallity of the button it describes.
*/

/*!
    \qmlproperty enumeration QtQuick::Accessible::role

    This flags sets the semantic type of the widget.
    A button for example would have "Button" as type.
    The value must be one of \l QAccessible::Role.

    Some roles have special semantics.
    In order to implement check boxes for example a "checked" property is expected.

    \table
    \header
        \li \b {Role}
        \li \b {Properties and functions}
        \li \b {Explanation}
    \row
        \li All interactive elements
        \li \l focusable and \l focused
        \li All elements that the user can interact with should have focusable set to \c true and
            set \l focus to \c true when they have the focus. This is important even for applications
            that run on touch-only devices since screen readers often implement a virtual focus that
            can be moved from item to item.
    \row
        \li Button, CheckBox, RadioButton
        \li \c accessiblePressAction()
        \li A button should have a function with the name \c accessiblePressAction.
            This function may be called by an assistive tool such as a screen-reader.
            The implementation needs to behave the same as a mouse click or tap on the button.
    \row
       \li CheckBox, RadioButton
       \li \l checkable, \l checked
       \li The check state of the check box. Updated on Press, Check and Uncheck actions.
    \row
       \li Slider, SpinBox, Dial, ScrollBar
       \li \c value, \c minimumValue, \c maximumValue, \c stepSize
       \li These properties reflect the state and possible values for the elements.
    \row
       \li Slider, SpinBox, Dial, ScrollBar
       \li \c accessibleIncreaseAction(), \c accessibleDecreaseAction()
       \li Actions to increase and decrease the value of the element.
    \endtable
*/

/*! \qmlproperty bool QtQuick::Accessible::focusable
    \brief This property holds whether this item is focusable.

    By default, this property is \c false except for items where the role is one of
    \c CheckBox, \c RadioButton, \c Button, \c MenuItem, \c PageTab, \c EditableText, \c SpinBox, \c ComboBox,
    \c Terminal or \c ScrollBar.
    \sa focused
*/
/*! \qmlproperty bool QtQuick::Accessible::focused
    \brief This property holds whether this item currently has the active focus.

    By default, this property is \c false, but it will return \c true for items that
    have \l QQuickItem::hasActiveFocus() returning \c true.
    \sa focusable
*/
/*! \qmlproperty bool QtQuick::Accessible::checkable
    \brief This property holds whether this item is checkable (like a check box or some buttons).

    By default this property is \c false.
    \sa checked
*/
/*! \qmlproperty bool QtQuick::Accessible::checked
    \brief This property holds whether this item is currently checked.

    By default this property is \c false.
    \sa checkable
*/
/*! \qmlproperty bool QtQuick::Accessible::editable
    \brief This property holds whether this item has editable text.

    By default this property is \c false.
*/
/*! \qmlproperty bool QtQuick::Accessible::multiLine
    \brief This property holds whether this item has multiple text lines.

    By default this property is \c false.
*/
/*! \qmlproperty bool QtQuick::Accessible::readOnly
    \brief This property indicates that a text field is read only.

    It is relevant when the role is \l QAccessible::EditableText and set to be read-only.
    By default this property is \c false.
*/
/*! \qmlproperty bool QtQuick::Accessible::selected
    \brief This property holds whether this item is selected.

    By default this property is \c false.
    \sa selectable
*/
/*! \qmlproperty bool QtQuick::Accessible::selectable
    \brief This property holds whether this item can be selected.

    By default this property is \c false.
    \sa selected
*/
/*! \qmlproperty bool QtQuick::Accessible::pressed
    \brief This property holds whether this item is pressed (for example a button during a mouse click).

    By default this property is \c false.
*/
/*! \qmlproperty bool QtQuick::Accessible::checkStateMixed
    \brief This property holds whether this item is in the partially checked state.

    By default this property is \c false.
    \sa checked, checkable
*/
/*! \qmlproperty bool QtQuick::Accessible::defaultButton
    \brief This property holds whether this item is the default button of a dialog.

    By default this property is \c false.
*/
/*! \qmlproperty bool QtQuick::Accessible::passwordEdit
    \brief This property holds whether this item is a password text edit.

    By default this property is \c false.
*/
/*! \qmlproperty bool QtQuick::Accessible::selectableText
    \brief This property holds whether this item contains selectable text.

    By default this property is \c false.
*/

QQuickAccessibleAttached::QQuickAccessibleAttached(QObject *parent)
    : QObject(parent), m_role(QAccessible::NoRole)
{
    Q_ASSERT(parent);
    QQuickItem *item = qobject_cast<QQuickItem*>(parent);
    if (!item)
        return;

    // Enable accessibility for items with accessible content. This also
    // enables accessibility for the ancestors of souch items.
    item->d_func()->setAccessibleFlagAndListener();
    QAccessibleEvent ev(item, QAccessible::ObjectCreated);
    QAccessible::updateAccessibility(&ev);

    if (!parent->property("value").isNull()) {
        connect(parent, SIGNAL(valueChanged()), this, SLOT(valueChanged()));
    }
    if (!parent->property("cursorPosition").isNull()) {
        connect(parent, SIGNAL(cursorPositionChanged()), this, SLOT(cursorPositionChanged()));
    }
}

QQuickAccessibleAttached::~QQuickAccessibleAttached()
{
}

QQuickAccessibleAttached *QQuickAccessibleAttached::qmlAttachedProperties(QObject *obj)
{
    return new QQuickAccessibleAttached(obj);
}

QT_END_NAMESPACE

#endif
<|endoftext|>