<commit_before>// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/message_handler.h"

#include "vm/dart.h"
#include "vm/lockers.h"
#include "vm/os.h"
#include "vm/port.h"
#include "vm/thread_interrupter.h"

namespace dart {

DECLARE_FLAG(bool, trace_isolates);
DECLARE_FLAG(bool, trace_service_pause_events);

class MessageHandlerTask : public ThreadPool::Task {
 public:
  explicit MessageHandlerTask(MessageHandler* handler)
      : handler_(handler) {
    ASSERT(handler != NULL);
  }

  virtual void Run() {
    handler_->TaskCallback();
  }

 private:
  MessageHandler* handler_;

  DISALLOW_COPY_AND_ASSIGN(MessageHandlerTask);
};

MessageHandler::MessageHandler()
    : queue_(new MessageQueue()),
      oob_queue_(new MessageQueue()),
      oob_message_handling_allowed_(true),
      live_ports_(0),
      paused_(0),
      pause_on_start_(false),
      pause_on_exit_(false),
      paused_on_start_(false),
      paused_on_exit_(false),
      paused_timestamp_(-1),
      pool_(NULL),
      task_(NULL),
      start_callback_(NULL),
      end_callback_(NULL),
      callback_data_(0) {
  ASSERT(queue_ != NULL);
  ASSERT(oob_queue_ != NULL);
}

MessageHandler::~MessageHandler() {
  delete queue_;
  delete oob_queue_;
}

const char* MessageHandler::name() const {
  return "<unnamed>";
}

#if defined(DEBUG)
void MessageHandler::CheckAccess() {
  // By default there is no checking.
}
#endif

void MessageHandler::MessageNotify(Message::Priority priority) {
  // By default, there is no custom message notification.
}

void MessageHandler::Run(ThreadPool* pool,
                         StartCallback start_callback,
                         EndCallback end_callback,
                         CallbackData data) {
  MonitorLocker ml(&monitor_);
  if (FLAG_trace_isolates) {
    OS::Print("[+] Starting message handler:\n"
              "\thandler:    %s\n",
              name());
  }
  ASSERT(pool_ == NULL);
  pool_ = pool;
  start_callback_ = start_callback;
  end_callback_ = end_callback;
  callback_data_ = data;
  task_ = new MessageHandlerTask(this);
  pool_->Run(task_);
}

void MessageHandler::PostMessage(Message* message, bool before_events) {
  Message::Priority saved_priority;
  {
    MonitorLocker ml(&monitor_);
    if (FLAG_trace_isolates) {
      const char* source_name = "<native code>";
      Isolate* source_isolate = Isolate::Current();
      if (source_isolate) {
        source_name = source_isolate->name();
      }
      OS::Print("[>] Posting message:\n"
                "\tlen:        %" Pd "\n"
                "\tsource:     %s\n"
                "\tdest:       %s\n"
                "\tdest_port:  %" Pd64 "\n",
                message->len(), source_name, name(), message->dest_port());
    }

    saved_priority = message->priority();
    if (message->IsOOB()) {
      oob_queue_->Enqueue(message, before_events);
    } else {
      queue_->Enqueue(message, before_events);
    }
    message = NULL;  // Do not access message.  May have been deleted.

    if (pool_ != NULL && task_ == NULL) {
      task_ = new MessageHandlerTask(this);
      pool_->Run(task_);
    }
  }
  // Invoke any custom message notification.
  MessageNotify(saved_priority);
}

Message* MessageHandler::DequeueMessage(Message::Priority min_priority) {
  // TODO(turnidge): Add assert that monitor_ is held here.
  Message* message = oob_queue_->Dequeue();
  if ((message == NULL) && (min_priority < Message::kOOBPriority)) {
    message = queue_->Dequeue();
  }
  return message;
}

bool MessageHandler::HandleMessages(bool allow_normal_messages,
                                    bool allow_multiple_normal_messages) {
  // If isolate() returns NULL StartIsolateScope does nothing.
  StartIsolateScope start_isolate(isolate());

  // ThreadInterrupter may have gone to sleep waiting while waiting for
  // an isolate to start handling messages.
  ThreadInterrupter::WakeUp();

  // TODO(turnidge): Add assert that monitor_ is held here.
  bool result = true;
  Message::Priority min_priority = (allow_normal_messages && !paused()) ?
      Message::kNormalPriority : Message::kOOBPriority;
  Message* message = DequeueMessage(min_priority);
  while (message != NULL) {
    intptr_t message_len = message->len();
    if (FLAG_trace_isolates) {
      OS::Print("[<] Handling message:\n"
                "\tlen:        %" Pd "\n"
                "\thandler:    %s\n"
                "\tport:       %" Pd64 "\n",
                message_len, name(), message->dest_port());
    }

    // Release the monitor_ temporarily while we handle the message.
    // The monitor was acquired in MessageHandler::TaskCallback().
    monitor_.Exit();
    Message::Priority saved_priority = message->priority();
    Dart_Port saved_dest_port = message->dest_port();
    result = HandleMessage(message);
    message = NULL;  // May be deleted by now.
    monitor_.Enter();
    if (FLAG_trace_isolates) {
      OS::Print("[.] Message handled:\n"
                "\tlen:        %" Pd "\n"
                "\thandler:    %s\n"
                "\tport:       %" Pd64 "\n",
                message_len, name(), saved_dest_port);
    }
    if (!result) {
      // If we hit an error, we're done processing messages.
      break;
    }
    // Some callers want to process only one normal message and then quit. At
    // the same time it is OK to process multiple OOB messages.
    if ((saved_priority == Message::kNormalPriority) &&
        !allow_multiple_normal_messages) {
      break;
    }

    // Reevaluate the minimum allowable priority as the paused state might
    // have changed as part of handling the message.
    min_priority = (allow_normal_messages && !paused()) ?
        Message::kNormalPriority : Message::kOOBPriority;
    message = DequeueMessage(min_priority);
  }
  return result;
}

bool MessageHandler::HandleNextMessage() {
  // We can only call HandleNextMessage when this handler is not
  // assigned to a thread pool.
  MonitorLocker ml(&monitor_);
  ASSERT(pool_ == NULL);
#if defined(DEBUG)
  CheckAccess();
#endif
  return HandleMessages(true, false);
}

bool MessageHandler::HandleOOBMessages() {
  if (!oob_message_handling_allowed_) {
    return true;
  }
  MonitorLocker ml(&monitor_);
#if defined(DEBUG)
  CheckAccess();
#endif
  return HandleMessages(false, false);
}

bool MessageHandler::HasOOBMessages() {
  MonitorLocker ml(&monitor_);
  return !oob_queue_->IsEmpty();
}

void MessageHandler::TaskCallback() {
  ASSERT(Isolate::Current() == NULL);
  bool ok = true;
  bool run_end_callback = false;
  bool notify_paused_on_exit = false;
  {
    MonitorLocker ml(&monitor_);
    // Initialize the message handler by running its start function,
    // if we have one.  For an isolate, this will run the isolate's
    // main() function.
    if (pause_on_start()) {
      if (!paused_on_start_) {
        // Temporarily drop the lock when calling out to NotifyPauseOnStart.
        // This avoids a dead lock that can occur when this message handler
        // tries to post a message while a message is being posted to it.
        paused_on_start_ = true;
        paused_timestamp_ = OS::GetCurrentTimeMillis();
        monitor_.Exit();
        NotifyPauseOnStart();
        monitor_.Enter();
      }
      HandleMessages(false, false);
      if (pause_on_start()) {
        // Still paused.
        task_ = NULL;  // No task in queue.
        return;
      } else {
        paused_on_start_ = false;
        paused_timestamp_ = -1;
      }
    }

    if (start_callback_) {
      // Release the monitor_ temporarily while we call the start callback.
      // The monitor was acquired with the MonitorLocker above.
      monitor_.Exit();
      ok = start_callback_(callback_data_);
      ASSERT(Isolate::Current() == NULL);
      start_callback_ = NULL;
      monitor_.Enter();
    }

    // Handle any pending messages for this message handler.
    if (ok) {
      ok = HandleMessages(true, true);
    }
    task_ = NULL;  // No task in queue.

    if (!ok || !HasLivePorts()) {
      if (pause_on_exit()) {
        if (!paused_on_exit_) {
          if (FLAG_trace_service_pause_events) {
            OS::PrintErr("Isolate %s paused before exiting. "
                       "Use the Observatory to release it.\n", name());
          }
          notify_paused_on_exit = true;
          paused_on_exit_ = true;
          paused_timestamp_ = OS::GetCurrentTimeMillis();
        }
      } else {
        if (FLAG_trace_isolates) {
        OS::Print("[-] Stopping message handler (%s):\n"
                  "\thandler:    %s\n",
                  (ok ? "no live ports" : "error"),
                  name());
        }
        pool_ = NULL;
        run_end_callback = true;
        paused_on_exit_ = false;
        paused_timestamp_ = -1;
      }
    }
  }
  // At this point we no longer hold the message handler lock.
  if (notify_paused_on_exit) {
    NotifyPauseOnExit();
  }
  if (run_end_callback && end_callback_ != NULL) {
    end_callback_(callback_data_);
    // The handler may have been deleted after this point.
  }
}

void MessageHandler::ClosePort(Dart_Port port) {
  MonitorLocker ml(&monitor_);
  if (FLAG_trace_isolates) {
    OS::Print("[-] Closing port:\n"
              "\thandler:    %s\n"
              "\tport:       %" Pd64 "\n"
              "\tports:      live(%" Pd ")\n",
              name(), port, live_ports_);
  }
}

void MessageHandler::CloseAllPorts() {
  MonitorLocker ml(&monitor_);
  if (FLAG_trace_isolates) {
    OS::Print("[-] Closing all ports:\n"
              "\thandler:    %s\n",
              name());
  }
  queue_->Clear();
  oob_queue_->Clear();
}

void MessageHandler::increment_live_ports() {
  MonitorLocker ml(&monitor_);
#if defined(DEBUG)
  CheckAccess();
#endif
  live_ports_++;
}

void MessageHandler::decrement_live_ports() {
  MonitorLocker ml(&monitor_);
#if defined(DEBUG)
  CheckAccess();
#endif
  live_ports_--;
}

MessageHandler::AcquiredQueues::AcquiredQueues()
    : handler_(NULL) {
}

MessageHandler::AcquiredQueues::~AcquiredQueues() {
  Reset(NULL);
}

void MessageHandler::AcquiredQueues::Reset(MessageHandler* handler) {
  if (handler_ != NULL) {
    // Release ownership. The OOB flag is set without holding the monitor.
    handler_->monitor_.Exit();
    handler_->oob_message_handling_allowed_ = true;
  }
  handler_ = handler;
  if (handler_ == NULL) {
    return;
  }
  ASSERT(handler_ != NULL);
  // Take ownership. The OOB flag is set without holding the monitor.
  handler_->oob_message_handling_allowed_ = false;
  handler_->monitor_.Enter();
}

void MessageHandler::AcquireQueues(AcquiredQueues* acquired_queues) {
  ASSERT(acquired_queues != NULL);
  // No double dipping.
  ASSERT(acquired_queues->handler_ == NULL);
  acquired_queues->Reset(this);
}

}  // namespace dart
<commit_msg>Fix a bug PauseOnExit notification.<commit_after>// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/message_handler.h"

#include "vm/dart.h"
#include "vm/lockers.h"
#include "vm/os.h"
#include "vm/port.h"
#include "vm/thread_interrupter.h"

namespace dart {

DECLARE_FLAG(bool, trace_isolates);
DECLARE_FLAG(bool, trace_service_pause_events);

class MessageHandlerTask : public ThreadPool::Task {
 public:
  explicit MessageHandlerTask(MessageHandler* handler)
      : handler_(handler) {
    ASSERT(handler != NULL);
  }

  virtual void Run() {
    handler_->TaskCallback();
  }

 private:
  MessageHandler* handler_;

  DISALLOW_COPY_AND_ASSIGN(MessageHandlerTask);
};

MessageHandler::MessageHandler()
    : queue_(new MessageQueue()),
      oob_queue_(new MessageQueue()),
      oob_message_handling_allowed_(true),
      live_ports_(0),
      paused_(0),
      pause_on_start_(false),
      pause_on_exit_(false),
      paused_on_start_(false),
      paused_on_exit_(false),
      paused_timestamp_(-1),
      pool_(NULL),
      task_(NULL),
      start_callback_(NULL),
      end_callback_(NULL),
      callback_data_(0) {
  ASSERT(queue_ != NULL);
  ASSERT(oob_queue_ != NULL);
}

MessageHandler::~MessageHandler() {
  delete queue_;
  delete oob_queue_;
}

const char* MessageHandler::name() const {
  return "<unnamed>";
}

#if defined(DEBUG)
void MessageHandler::CheckAccess() {
  // By default there is no checking.
}
#endif

void MessageHandler::MessageNotify(Message::Priority priority) {
  // By default, there is no custom message notification.
}

void MessageHandler::Run(ThreadPool* pool,
                         StartCallback start_callback,
                         EndCallback end_callback,
                         CallbackData data) {
  MonitorLocker ml(&monitor_);
  if (FLAG_trace_isolates) {
    OS::Print("[+] Starting message handler:\n"
              "\thandler:    %s\n",
              name());
  }
  ASSERT(pool_ == NULL);
  pool_ = pool;
  start_callback_ = start_callback;
  end_callback_ = end_callback;
  callback_data_ = data;
  task_ = new MessageHandlerTask(this);
  pool_->Run(task_);
}

void MessageHandler::PostMessage(Message* message, bool before_events) {
  Message::Priority saved_priority;
  {
    MonitorLocker ml(&monitor_);
    if (FLAG_trace_isolates) {
      const char* source_name = "<native code>";
      Isolate* source_isolate = Isolate::Current();
      if (source_isolate) {
        source_name = source_isolate->name();
      }
      OS::Print("[>] Posting message:\n"
                "\tlen:        %" Pd "\n"
                "\tsource:     %s\n"
                "\tdest:       %s\n"
                "\tdest_port:  %" Pd64 "\n",
                message->len(), source_name, name(), message->dest_port());
    }

    saved_priority = message->priority();
    if (message->IsOOB()) {
      oob_queue_->Enqueue(message, before_events);
    } else {
      queue_->Enqueue(message, before_events);
    }
    message = NULL;  // Do not access message.  May have been deleted.

    if (pool_ != NULL && task_ == NULL) {
      task_ = new MessageHandlerTask(this);
      pool_->Run(task_);
    }
  }
  // Invoke any custom message notification.
  MessageNotify(saved_priority);
}

Message* MessageHandler::DequeueMessage(Message::Priority min_priority) {
  // TODO(turnidge): Add assert that monitor_ is held here.
  Message* message = oob_queue_->Dequeue();
  if ((message == NULL) && (min_priority < Message::kOOBPriority)) {
    message = queue_->Dequeue();
  }
  return message;
}

bool MessageHandler::HandleMessages(bool allow_normal_messages,
                                    bool allow_multiple_normal_messages) {
  // If isolate() returns NULL StartIsolateScope does nothing.
  StartIsolateScope start_isolate(isolate());

  // ThreadInterrupter may have gone to sleep waiting while waiting for
  // an isolate to start handling messages.
  ThreadInterrupter::WakeUp();

  // TODO(turnidge): Add assert that monitor_ is held here.
  bool result = true;
  Message::Priority min_priority = (allow_normal_messages && !paused()) ?
      Message::kNormalPriority : Message::kOOBPriority;
  Message* message = DequeueMessage(min_priority);
  while (message != NULL) {
    intptr_t message_len = message->len();
    if (FLAG_trace_isolates) {
      OS::Print("[<] Handling message:\n"
                "\tlen:        %" Pd "\n"
                "\thandler:    %s\n"
                "\tport:       %" Pd64 "\n",
                message_len, name(), message->dest_port());
    }

    // Release the monitor_ temporarily while we handle the message.
    // The monitor was acquired in MessageHandler::TaskCallback().
    monitor_.Exit();
    Message::Priority saved_priority = message->priority();
    Dart_Port saved_dest_port = message->dest_port();
    result = HandleMessage(message);
    message = NULL;  // May be deleted by now.
    monitor_.Enter();
    if (FLAG_trace_isolates) {
      OS::Print("[.] Message handled:\n"
                "\tlen:        %" Pd "\n"
                "\thandler:    %s\n"
                "\tport:       %" Pd64 "\n",
                message_len, name(), saved_dest_port);
    }
    if (!result) {
      // If we hit an error, we're done processing messages.
      break;
    }
    // Some callers want to process only one normal message and then quit. At
    // the same time it is OK to process multiple OOB messages.
    if ((saved_priority == Message::kNormalPriority) &&
        !allow_multiple_normal_messages) {
      break;
    }

    // Reevaluate the minimum allowable priority as the paused state might
    // have changed as part of handling the message.
    min_priority = (allow_normal_messages && !paused()) ?
        Message::kNormalPriority : Message::kOOBPriority;
    message = DequeueMessage(min_priority);
  }
  return result;
}

bool MessageHandler::HandleNextMessage() {
  // We can only call HandleNextMessage when this handler is not
  // assigned to a thread pool.
  MonitorLocker ml(&monitor_);
  ASSERT(pool_ == NULL);
#if defined(DEBUG)
  CheckAccess();
#endif
  return HandleMessages(true, false);
}

bool MessageHandler::HandleOOBMessages() {
  if (!oob_message_handling_allowed_) {
    return true;
  }
  MonitorLocker ml(&monitor_);
#if defined(DEBUG)
  CheckAccess();
#endif
  return HandleMessages(false, false);
}

bool MessageHandler::HasOOBMessages() {
  MonitorLocker ml(&monitor_);
  return !oob_queue_->IsEmpty();
}

void MessageHandler::TaskCallback() {
  ASSERT(Isolate::Current() == NULL);
  bool ok = true;
  bool run_end_callback = false;
  {
    MonitorLocker ml(&monitor_);
    // Initialize the message handler by running its start function,
    // if we have one.  For an isolate, this will run the isolate's
    // main() function.
    if (pause_on_start()) {
      if (!paused_on_start_) {
        // Temporarily drop the lock when calling out to NotifyPauseOnStart.
        // This avoids a dead lock that can occur when this message handler
        // tries to post a message while a message is being posted to it.
        paused_on_start_ = true;
        paused_timestamp_ = OS::GetCurrentTimeMillis();
        monitor_.Exit();
        NotifyPauseOnStart();
        monitor_.Enter();
      }
      // More messages may have come in while we released monitor_.
      HandleMessages(false, false);
      if (pause_on_start()) {
        // Still paused.
        ASSERT(oob_queue_->IsEmpty());
        task_ = NULL;  // No task in queue.
        return;
      } else {
        paused_on_start_ = false;
        paused_timestamp_ = -1;
      }
    }

    if (start_callback_) {
      // Release the monitor_ temporarily while we call the start callback.
      // The monitor was acquired with the MonitorLocker above.
      monitor_.Exit();
      ok = start_callback_(callback_data_);
      ASSERT(Isolate::Current() == NULL);
      start_callback_ = NULL;
      monitor_.Enter();
    }

    // Handle any pending messages for this message handler.
    if (ok) {
      ok = HandleMessages(true, true);
    }

    if (!ok || !HasLivePorts()) {
      if (pause_on_exit()) {
        if (!paused_on_exit_) {
          if (FLAG_trace_service_pause_events) {
            OS::PrintErr("Isolate %s paused before exiting. "
                         "Use the Observatory to release it.\n", name());
          }
          // Temporarily drop the lock when calling out to NotifyPauseOnExit.
          // This avoids a dead lock that can occur when this message handler
          // tries to post a message while a message is being posted to it.
          paused_on_exit_ = true;
          paused_timestamp_ = OS::GetCurrentTimeMillis();
          monitor_.Exit();
          NotifyPauseOnExit();
          monitor_.Enter();
        }
        // More messages may have come in while we released monitor_.
        HandleMessages(false, false);
        if (pause_on_exit()) {
          // Still paused.
          ASSERT(oob_queue_->IsEmpty());
          task_ = NULL;  // No task in queue.
          return;
        } else {
          paused_on_exit_ = false;
          paused_timestamp_ = -1;
        }
      }
      if (FLAG_trace_isolates) {
        OS::Print("[-] Stopping message handler (%s):\n"
                  "\thandler:    %s\n",
                  (ok ? "no live ports" : "error"),
                  name());
      }
      pool_ = NULL;
      run_end_callback = true;
    }

    // Clear the task_ last.  We don't want any other tasks to start up
    // until we are done with all messages and pause notifications.
    ASSERT(oob_queue_->IsEmpty());
    ASSERT(!ok || queue_->IsEmpty());
    task_ = NULL;
  }
  if (run_end_callback && end_callback_ != NULL) {
    end_callback_(callback_data_);
    // The handler may have been deleted after this point.
  }
}

void MessageHandler::ClosePort(Dart_Port port) {
  MonitorLocker ml(&monitor_);
  if (FLAG_trace_isolates) {
    OS::Print("[-] Closing port:\n"
              "\thandler:    %s\n"
              "\tport:       %" Pd64 "\n"
              "\tports:      live(%" Pd ")\n",
              name(), port, live_ports_);
  }
}

void MessageHandler::CloseAllPorts() {
  MonitorLocker ml(&monitor_);
  if (FLAG_trace_isolates) {
    OS::Print("[-] Closing all ports:\n"
              "\thandler:    %s\n",
              name());
  }
  queue_->Clear();
  oob_queue_->Clear();
}

void MessageHandler::increment_live_ports() {
  MonitorLocker ml(&monitor_);
#if defined(DEBUG)
  CheckAccess();
#endif
  live_ports_++;
}

void MessageHandler::decrement_live_ports() {
  MonitorLocker ml(&monitor_);
#if defined(DEBUG)
  CheckAccess();
#endif
  live_ports_--;
}

MessageHandler::AcquiredQueues::AcquiredQueues()
    : handler_(NULL) {
}

MessageHandler::AcquiredQueues::~AcquiredQueues() {
  Reset(NULL);
}

void MessageHandler::AcquiredQueues::Reset(MessageHandler* handler) {
  if (handler_ != NULL) {
    // Release ownership. The OOB flag is set without holding the monitor.
    handler_->monitor_.Exit();
    handler_->oob_message_handling_allowed_ = true;
  }
  handler_ = handler;
  if (handler_ == NULL) {
    return;
  }
  ASSERT(handler_ != NULL);
  // Take ownership. The OOB flag is set without holding the monitor.
  handler_->oob_message_handling_allowed_ = false;
  handler_->monitor_.Enter();
}

void MessageHandler::AcquireQueues(AcquiredQueues* acquired_queues) {
  ASSERT(acquired_queues != NULL);
  // No double dipping.
  ASSERT(acquired_queues->handler_ == NULL);
  acquired_queues->Reset(this);
}

}  // namespace dart
<|endoftext|>


<commit_before>#include <babylon/materials/node/node_material_connection_point.h>

#include <babylon/babylon_stl_util.h>
#include <babylon/core/json_util.h>
#include <babylon/materials/node/blocks/input/input_block.h>
#include <babylon/materials/node/node_material_block.h>

namespace BABYLON {

bool NodeMaterialConnectionPoint::AreEquivalentTypes(NodeMaterialBlockConnectionPointTypes type1,
                                                     NodeMaterialBlockConnectionPointTypes type2)
{
  switch (type1) {
    case NodeMaterialBlockConnectionPointTypes::Vector3: {
      if (type2 == NodeMaterialBlockConnectionPointTypes::Color3) {
        return true;
      }
      break;
    }
    case NodeMaterialBlockConnectionPointTypes::Vector4: {
      if (type2 == NodeMaterialBlockConnectionPointTypes::Color4) {
        return true;
      }
      break;
    }
    case NodeMaterialBlockConnectionPointTypes::Color3: {
      if (type2 == NodeMaterialBlockConnectionPointTypes::Vector3) {
        return true;
      }
      break;
    }
    case NodeMaterialBlockConnectionPointTypes::Color4: {
      if (type2 == NodeMaterialBlockConnectionPointTypes::Vector4) {
        return true;
      }
      break;
    }
    default:
      break;
  }

  return false;
}

NodeMaterialConnectionPoint::NodeMaterialConnectionPoint(
  const std::string& iName, const NodeMaterialBlockPtr& ownerBlock,
  const NodeMaterialConnectionPointDirection& direction)
    : _ownerBlock{nullptr}
    , _connectedPoint{nullptr}
    , _typeConnectionSource{nullptr}
    , _defaultConnectionPointType{std::nullopt}
    , _linkedConnectionSource{nullptr}
    , _acceptedConnectionPointType{nullptr}
    , _enforceAssociatedVariableName{false}
    , direction{this, &NodeMaterialConnectionPoint::get_direction}
    , needDualDirectionValidation{false}
    , associatedVariableName{this, &NodeMaterialConnectionPoint::get_associatedVariableName,
                             &NodeMaterialConnectionPoint::set_associatedVariableName}
    , innerType{this, &NodeMaterialConnectionPoint::get_innerType}
    , type{this, &NodeMaterialConnectionPoint::get_type, &NodeMaterialConnectionPoint::set_type}
    , isOptional{false}
    , isExposedOnFrame{false}
    , exposedPortPosition{-1}
    , _prioritizeVertex{false}
    , target{this, &NodeMaterialConnectionPoint::get_target,
             &NodeMaterialConnectionPoint::set_target}
    , isConnected{this, &NodeMaterialConnectionPoint::get_isConnected}
    , isConnectedToInputBlock{this, &NodeMaterialConnectionPoint::get_isConnectedToInputBlock}
    , connectInputBlock{this, &NodeMaterialConnectionPoint::get_connectInputBlock}
    , connectedPoint{this, &NodeMaterialConnectionPoint::get_connectedPoint}
    , ownerBlock{this, &NodeMaterialConnectionPoint::get_ownerBlock}
    , sourceBlock{this, &NodeMaterialConnectionPoint::get_sourceBlock}
    , connectedBlocks{this, &NodeMaterialConnectionPoint::get_connectedBlocks}
    , endpoints{this, &NodeMaterialConnectionPoint::get_endpoints}
    , hasEndpoints{this, &NodeMaterialConnectionPoint::get_hasEndpoints}
    , isConnectedInVertexShader{this, &NodeMaterialConnectionPoint::get_isConnectedInVertexShader}
    , isConnectedInFragmentShader{this,
                                  &NodeMaterialConnectionPoint::get_isConnectedInFragmentShader}
    , _target{NodeMaterialBlockTargets::VertexAndFragment}
    , _type{NodeMaterialBlockConnectionPointTypes::Float}
    , _connectInputBlock{nullptr}
    , _sourceBlock{nullptr}
{
  _ownerBlock = ownerBlock;
  name        = iName;
  _direction  = direction;
}

NodeMaterialConnectionPointDirection& NodeMaterialConnectionPoint::get_direction()
{
  return _direction;
}

std::string NodeMaterialConnectionPoint::get_associatedVariableName() const
{
  if (_ownerBlock->isInput()) {
    auto inputBlock = std::static_pointer_cast<InputBlock>(_ownerBlock);
    if (inputBlock) {
      return inputBlock->associatedVariableName();
    }
  }

  if ((!_enforceAssociatedVariableName || _associatedVariableName.empty()) && _connectedPoint) {
    return _connectedPoint->associatedVariableName();
  }

  return _associatedVariableName;
}

void NodeMaterialConnectionPoint::set_associatedVariableName(std::string value)
{
  _associatedVariableName = value;
}

NodeMaterialBlockConnectionPointTypes& NodeMaterialConnectionPoint::get_innerType()
{
  if (_linkedConnectionSource && _linkedConnectionSource->isConnected()) {
    return type();
  }
  return _type;
}

NodeMaterialBlockConnectionPointTypes& NodeMaterialConnectionPoint::get_type()
{
  if (_type == NodeMaterialBlockConnectionPointTypes::AutoDetect) {
    if (_ownerBlock->isInput()) {
      auto inputBlock = std::static_pointer_cast<InputBlock>(_ownerBlock);
      if (inputBlock) {
        return inputBlock->type();
      }
    }

    if (_connectedPoint) {
      return _connectedPoint->type();
    }

    if (_linkedConnectionSource && _linkedConnectionSource->isConnected()) {
      return _linkedConnectionSource->type();
    }
  }

  if (_type == NodeMaterialBlockConnectionPointTypes::BasedOnInput) {
    if (_typeConnectionSource) {
      if (!_typeConnectionSource->isConnected() && _defaultConnectionPointType) {
        return *_defaultConnectionPointType;
      }
      return _typeConnectionSource->type();
    }
    else if (_defaultConnectionPointType) {
      return *_defaultConnectionPointType;
    }
  }

  return _type;
}

void NodeMaterialConnectionPoint::set_type(const NodeMaterialBlockConnectionPointTypes& value)
{
  _type = value;
}

NodeMaterialBlockTargets& NodeMaterialConnectionPoint::get_target()
{
  if (!_prioritizeVertex || !_ownerBlock) {
    return _target;
  }

  if (_target != NodeMaterialBlockTargets::VertexAndFragment) {
    return _target;
  }

  if (_ownerBlock->target() == NodeMaterialBlockTargets::Fragment) {
    _tmpTarget = NodeMaterialBlockTargets::Fragment;
    return _tmpTarget;
  }

  _tmpTarget = NodeMaterialBlockTargets::Vertex;
  return _tmpTarget;
}

void NodeMaterialConnectionPoint::set_target(const NodeMaterialBlockTargets& value)
{
  _target = value;
}

bool NodeMaterialConnectionPoint::get_isConnected() const
{
  return connectedPoint() != nullptr || hasEndpoints();
}

bool NodeMaterialConnectionPoint::get_isConnectedToInputBlock() const
{
  return connectedPoint() != nullptr && connectedPoint()->ownerBlock()->isInput();
}

InputBlockPtr& NodeMaterialConnectionPoint::get_connectInputBlock()
{
  if (!isConnectedToInputBlock()) {
    _connectInputBlock = nullptr;
    return _connectInputBlock;
  }

  _connectInputBlock = std::static_pointer_cast<InputBlock>(connectedPoint()->ownerBlock());
  return _connectInputBlock;
}

NodeMaterialConnectionPointPtr& NodeMaterialConnectionPoint::get_connectedPoint()
{
  return _connectedPoint;
}

NodeMaterialBlockPtr& NodeMaterialConnectionPoint::get_ownerBlock()
{
  return _ownerBlock;
}

NodeMaterialBlockPtr& NodeMaterialConnectionPoint::get_sourceBlock()
{
  if (!_connectedPoint) {
    _sourceBlock = nullptr;
    return _sourceBlock;
  }

  _sourceBlock = _connectedPoint->ownerBlock();
  return _sourceBlock;
}

std::vector<NodeMaterialBlockPtr>& NodeMaterialConnectionPoint::get_connectedBlocks()
{
  _connectedBlocks.clear();
  if (_endpoints.empty()) {
    return _connectedBlocks;
  }

  for (const auto& e : _endpoints) {
    _connectedBlocks.emplace_back(e->ownerBlock());
  }

  return _connectedBlocks;
}

std::vector<NodeMaterialConnectionPointPtr>& NodeMaterialConnectionPoint::get_endpoints()
{
  return _endpoints;
}

bool NodeMaterialConnectionPoint::get_hasEndpoints() const
{
  return !_endpoints.empty();
}

bool NodeMaterialConnectionPoint::get_isConnectedInVertexShader() const
{
  if (target() == NodeMaterialBlockTargets::Vertex) {
    return true;
  }

  if (!hasEndpoints()) {
    return false;
  }

  for (const auto& endpoint : _endpoints) {
    if (endpoint->ownerBlock()->target() == NodeMaterialBlockTargets::Vertex) {
      return true;
    }

    if (endpoint->target() == NodeMaterialBlockTargets::Vertex) {
      return true;
    }

    if (endpoint->ownerBlock()->target() == NodeMaterialBlockTargets::Neutral
        || endpoint->ownerBlock()->target() == NodeMaterialBlockTargets::VertexAndFragment) {
      for (const auto& o : endpoint->ownerBlock()->outputs()) {
        if (o->isConnectedInVertexShader()) {
          return true;
        }
      }
    }
  }

  return false;
}

bool NodeMaterialConnectionPoint::get_isConnectedInFragmentShader() const
{
  if (target() == NodeMaterialBlockTargets::Fragment) {
    return true;
  }

  if (!hasEndpoints()) {
    return false;
  }

  for (const auto& endpoint : _endpoints) {
    if (endpoint->ownerBlock()->target() == NodeMaterialBlockTargets::Fragment) {
      return true;
    }

    if (endpoint->ownerBlock()->target() == NodeMaterialBlockTargets::Neutral
        || endpoint->ownerBlock()->target() == NodeMaterialBlockTargets::VertexAndFragment) {
      for (const auto& o : endpoint->ownerBlock()->outputs()) {
        if (o->isConnectedInFragmentShader()) {
          return true;
        }
      }
    }
  }

  return false;
}

std::optional<std::pair<NodeMaterialBlockPtr, std::string>>
NodeMaterialConnectionPoint::createCustomInputBlock()
{
  return std::nullopt;
}

std::string NodeMaterialConnectionPoint::getClassName() const
{
  return "NodeMaterialConnectionPoint";
}

bool NodeMaterialConnectionPoint::canConnectTo(const NodeMaterialConnectionPoint& connectionPoint)
{
  return checkCompatibilityState(connectionPoint)
         == NodeMaterialConnectionPointCompatibilityStates::Compatible;
}

NodeMaterialConnectionPointCompatibilityStates NodeMaterialConnectionPoint::checkCompatibilityState(
  const NodeMaterialConnectionPoint& connectionPoint)
{
  const auto& iOwnerBlock = _ownerBlock;
  const auto& otherBlock  = connectionPoint.ownerBlock();

  if (iOwnerBlock->target() == NodeMaterialBlockTargets::Fragment) {
    // Let's check we are not going reverse

    if (otherBlock->target() == NodeMaterialBlockTargets::Vertex) {
      return NodeMaterialConnectionPointCompatibilityStates::TargetIncompatible;
    }

    for (const auto& output : otherBlock->outputs()) {
      if (output->isConnectedInVertexShader()) {
        return NodeMaterialConnectionPointCompatibilityStates::TargetIncompatible;
      }
    }
  }

  if (type != connectionPoint.type
      && connectionPoint.innerType() != NodeMaterialBlockConnectionPointTypes::AutoDetect) {
    // Equivalents
    if (NodeMaterialConnectionPoint::AreEquivalentTypes(type, connectionPoint.type)) {
      return NodeMaterialConnectionPointCompatibilityStates::Compatible;
    }

    // Accepted types
    if ((!connectionPoint.acceptedConnectionPointTypes.empty()
         && stl_util::contains(connectionPoint.acceptedConnectionPointTypes, type))
        || (connectionPoint._acceptedConnectionPointType
            && NodeMaterialConnectionPoint::AreEquivalentTypes(
                 connectionPoint._acceptedConnectionPointType->type, type))) {
      return NodeMaterialConnectionPointCompatibilityStates::Compatible;
    }
    else {
      return NodeMaterialConnectionPointCompatibilityStates::TypeIncompatible;
    }
  }

  // Excluded
  if ((!connectionPoint.excludedConnectionPointTypes.empty()
       && stl_util::contains(connectionPoint.excludedConnectionPointTypes, type))) {
    return NodeMaterialConnectionPointCompatibilityStates::TypeIncompatible;
  }

  // Check hierarchy
  auto targetBlock  = otherBlock;
  auto iSourceBlock = ownerBlock();
  if (direction() == NodeMaterialConnectionPointDirection::Input) {
    targetBlock  = ownerBlock();
    iSourceBlock = otherBlock;
  }

  if (targetBlock->isAnAncestorOf(iSourceBlock)) {
    return NodeMaterialConnectionPointCompatibilityStates::HierarchyIssue;
  }

  return NodeMaterialConnectionPointCompatibilityStates::Compatible;
}

NodeMaterialConnectionPoint&
NodeMaterialConnectionPoint::connectTo(const NodeMaterialConnectionPointPtr& connectionPoint,
                                       bool ignoreConstraints)
{
  if (!ignoreConstraints && !canConnectTo(*connectionPoint)) {
    throw std::runtime_error("Cannot connect these two connectors.");
  }

  _endpoints.emplace_back(connectionPoint);
  connectionPoint->_connectedPoint = shared_from_this();

  _enforceAssociatedVariableName = false;

  onConnectionObservable.notifyObservers(connectionPoint.get());
  connectionPoint->onConnectionObservable.notifyObservers(this);

  return *this;
}

NodeMaterialConnectionPoint&
NodeMaterialConnectionPoint::disconnectFrom(const NodeMaterialConnectionPointPtr& endpoint)
{
  auto index = stl_util::index_of(_endpoints, endpoint);

  if (index == -1) {
    return *this;
  }

  stl_util::splice(_endpoints, index, 1);
  endpoint->_connectedPoint                = nullptr;
  _enforceAssociatedVariableName           = false;
  endpoint->_enforceAssociatedVariableName = false;
  return *this;
}

json NodeMaterialConnectionPoint::serialize(bool /*isInput*/) const
{
  return nullptr;
}

void NodeMaterialConnectionPoint::dispose()
{
  onConnectionObservable.clear();
}

} // end of namespace BABYLON
<commit_msg>Added extra target type check<commit_after>#include <babylon/materials/node/node_material_connection_point.h>

#include <babylon/babylon_stl_util.h>
#include <babylon/core/json_util.h>
#include <babylon/materials/node/blocks/input/input_block.h>
#include <babylon/materials/node/node_material_block.h>

namespace BABYLON {

bool NodeMaterialConnectionPoint::AreEquivalentTypes(NodeMaterialBlockConnectionPointTypes type1,
                                                     NodeMaterialBlockConnectionPointTypes type2)
{
  switch (type1) {
    case NodeMaterialBlockConnectionPointTypes::Vector3: {
      if (type2 == NodeMaterialBlockConnectionPointTypes::Color3) {
        return true;
      }
      break;
    }
    case NodeMaterialBlockConnectionPointTypes::Vector4: {
      if (type2 == NodeMaterialBlockConnectionPointTypes::Color4) {
        return true;
      }
      break;
    }
    case NodeMaterialBlockConnectionPointTypes::Color3: {
      if (type2 == NodeMaterialBlockConnectionPointTypes::Vector3) {
        return true;
      }
      break;
    }
    case NodeMaterialBlockConnectionPointTypes::Color4: {
      if (type2 == NodeMaterialBlockConnectionPointTypes::Vector4) {
        return true;
      }
      break;
    }
    default:
      break;
  }

  return false;
}

NodeMaterialConnectionPoint::NodeMaterialConnectionPoint(
  const std::string& iName, const NodeMaterialBlockPtr& ownerBlock,
  const NodeMaterialConnectionPointDirection& direction)
    : _ownerBlock{nullptr}
    , _connectedPoint{nullptr}
    , _typeConnectionSource{nullptr}
    , _defaultConnectionPointType{std::nullopt}
    , _linkedConnectionSource{nullptr}
    , _acceptedConnectionPointType{nullptr}
    , _enforceAssociatedVariableName{false}
    , direction{this, &NodeMaterialConnectionPoint::get_direction}
    , needDualDirectionValidation{false}
    , associatedVariableName{this, &NodeMaterialConnectionPoint::get_associatedVariableName,
                             &NodeMaterialConnectionPoint::set_associatedVariableName}
    , innerType{this, &NodeMaterialConnectionPoint::get_innerType}
    , type{this, &NodeMaterialConnectionPoint::get_type, &NodeMaterialConnectionPoint::set_type}
    , isOptional{false}
    , isExposedOnFrame{false}
    , exposedPortPosition{-1}
    , _prioritizeVertex{false}
    , target{this, &NodeMaterialConnectionPoint::get_target,
             &NodeMaterialConnectionPoint::set_target}
    , isConnected{this, &NodeMaterialConnectionPoint::get_isConnected}
    , isConnectedToInputBlock{this, &NodeMaterialConnectionPoint::get_isConnectedToInputBlock}
    , connectInputBlock{this, &NodeMaterialConnectionPoint::get_connectInputBlock}
    , connectedPoint{this, &NodeMaterialConnectionPoint::get_connectedPoint}
    , ownerBlock{this, &NodeMaterialConnectionPoint::get_ownerBlock}
    , sourceBlock{this, &NodeMaterialConnectionPoint::get_sourceBlock}
    , connectedBlocks{this, &NodeMaterialConnectionPoint::get_connectedBlocks}
    , endpoints{this, &NodeMaterialConnectionPoint::get_endpoints}
    , hasEndpoints{this, &NodeMaterialConnectionPoint::get_hasEndpoints}
    , isConnectedInVertexShader{this, &NodeMaterialConnectionPoint::get_isConnectedInVertexShader}
    , isConnectedInFragmentShader{this,
                                  &NodeMaterialConnectionPoint::get_isConnectedInFragmentShader}
    , _target{NodeMaterialBlockTargets::VertexAndFragment}
    , _type{NodeMaterialBlockConnectionPointTypes::Float}
    , _connectInputBlock{nullptr}
    , _sourceBlock{nullptr}
{
  _ownerBlock = ownerBlock;
  name        = iName;
  _direction  = direction;
}

NodeMaterialConnectionPointDirection& NodeMaterialConnectionPoint::get_direction()
{
  return _direction;
}

std::string NodeMaterialConnectionPoint::get_associatedVariableName() const
{
  if (_ownerBlock->isInput()) {
    auto inputBlock = std::static_pointer_cast<InputBlock>(_ownerBlock);
    if (inputBlock) {
      return inputBlock->associatedVariableName();
    }
  }

  if ((!_enforceAssociatedVariableName || _associatedVariableName.empty()) && _connectedPoint) {
    return _connectedPoint->associatedVariableName();
  }

  return _associatedVariableName;
}

void NodeMaterialConnectionPoint::set_associatedVariableName(std::string value)
{
  _associatedVariableName = value;
}

NodeMaterialBlockConnectionPointTypes& NodeMaterialConnectionPoint::get_innerType()
{
  if (_linkedConnectionSource && _linkedConnectionSource->isConnected()) {
    return type();
  }
  return _type;
}

NodeMaterialBlockConnectionPointTypes& NodeMaterialConnectionPoint::get_type()
{
  if (_type == NodeMaterialBlockConnectionPointTypes::AutoDetect) {
    if (_ownerBlock->isInput()) {
      auto inputBlock = std::static_pointer_cast<InputBlock>(_ownerBlock);
      if (inputBlock) {
        return inputBlock->type();
      }
    }

    if (_connectedPoint) {
      return _connectedPoint->type();
    }

    if (_linkedConnectionSource && _linkedConnectionSource->isConnected()) {
      return _linkedConnectionSource->type();
    }
  }

  if (_type == NodeMaterialBlockConnectionPointTypes::BasedOnInput) {
    if (_typeConnectionSource) {
      if (!_typeConnectionSource->isConnected() && _defaultConnectionPointType) {
        return *_defaultConnectionPointType;
      }
      return _typeConnectionSource->type();
    }
    else if (_defaultConnectionPointType) {
      return *_defaultConnectionPointType;
    }
  }

  return _type;
}

void NodeMaterialConnectionPoint::set_type(const NodeMaterialBlockConnectionPointTypes& value)
{
  _type = value;
}

NodeMaterialBlockTargets& NodeMaterialConnectionPoint::get_target()
{
  if (!_prioritizeVertex || !_ownerBlock) {
    return _target;
  }

  if (_target != NodeMaterialBlockTargets::VertexAndFragment) {
    return _target;
  }

  if (_ownerBlock->target() == NodeMaterialBlockTargets::Fragment) {
    _tmpTarget = NodeMaterialBlockTargets::Fragment;
    return _tmpTarget;
  }

  _tmpTarget = NodeMaterialBlockTargets::Vertex;
  return _tmpTarget;
}

void NodeMaterialConnectionPoint::set_target(const NodeMaterialBlockTargets& value)
{
  _target = value;
}

bool NodeMaterialConnectionPoint::get_isConnected() const
{
  return connectedPoint() != nullptr || hasEndpoints();
}

bool NodeMaterialConnectionPoint::get_isConnectedToInputBlock() const
{
  return connectedPoint() != nullptr && connectedPoint()->ownerBlock()->isInput();
}

InputBlockPtr& NodeMaterialConnectionPoint::get_connectInputBlock()
{
  if (!isConnectedToInputBlock()) {
    _connectInputBlock = nullptr;
    return _connectInputBlock;
  }

  _connectInputBlock = std::static_pointer_cast<InputBlock>(connectedPoint()->ownerBlock());
  return _connectInputBlock;
}

NodeMaterialConnectionPointPtr& NodeMaterialConnectionPoint::get_connectedPoint()
{
  return _connectedPoint;
}

NodeMaterialBlockPtr& NodeMaterialConnectionPoint::get_ownerBlock()
{
  return _ownerBlock;
}

NodeMaterialBlockPtr& NodeMaterialConnectionPoint::get_sourceBlock()
{
  if (!_connectedPoint) {
    _sourceBlock = nullptr;
    return _sourceBlock;
  }

  _sourceBlock = _connectedPoint->ownerBlock();
  return _sourceBlock;
}

std::vector<NodeMaterialBlockPtr>& NodeMaterialConnectionPoint::get_connectedBlocks()
{
  _connectedBlocks.clear();
  if (_endpoints.empty()) {
    return _connectedBlocks;
  }

  for (const auto& e : _endpoints) {
    _connectedBlocks.emplace_back(e->ownerBlock());
  }

  return _connectedBlocks;
}

std::vector<NodeMaterialConnectionPointPtr>& NodeMaterialConnectionPoint::get_endpoints()
{
  return _endpoints;
}

bool NodeMaterialConnectionPoint::get_hasEndpoints() const
{
  return !_endpoints.empty();
}

bool NodeMaterialConnectionPoint::get_isConnectedInVertexShader() const
{
  if (target() == NodeMaterialBlockTargets::Vertex) {
    return true;
  }

  if (!hasEndpoints()) {
    return false;
  }

  for (const auto& endpoint : _endpoints) {
    if (endpoint->ownerBlock()->target() == NodeMaterialBlockTargets::Vertex) {
      return true;
    }

    if (endpoint->target() == NodeMaterialBlockTargets::Vertex) {
      return true;
    }

    if (endpoint->ownerBlock()->target() == NodeMaterialBlockTargets::Neutral
        || endpoint->ownerBlock()->target() == NodeMaterialBlockTargets::VertexAndFragment) {
      for (const auto& o : endpoint->ownerBlock()->outputs()) {
        if (o->isConnectedInVertexShader()) {
          return true;
        }
      }
    }
  }

  return false;
}

bool NodeMaterialConnectionPoint::get_isConnectedInFragmentShader() const
{
  if (target() == NodeMaterialBlockTargets::Fragment) {
    return true;
  }

  if (!hasEndpoints()) {
    return false;
  }

  for (const auto& endpoint : _endpoints) {
    if (endpoint->ownerBlock()->target() == NodeMaterialBlockTargets::Fragment) {
      return true;
    }

    if (endpoint->ownerBlock()->target() == NodeMaterialBlockTargets::Neutral
        || endpoint->ownerBlock()->target() == NodeMaterialBlockTargets::VertexAndFragment) {
      for (const auto& o : endpoint->ownerBlock()->outputs()) {
        if (o->isConnectedInFragmentShader()) {
          return true;
        }
      }
    }
  }

  return false;
}

std::optional<std::pair<NodeMaterialBlockPtr, std::string>>
NodeMaterialConnectionPoint::createCustomInputBlock()
{
  return std::nullopt;
}

std::string NodeMaterialConnectionPoint::getClassName() const
{
  return "NodeMaterialConnectionPoint";
}

bool NodeMaterialConnectionPoint::canConnectTo(const NodeMaterialConnectionPoint& connectionPoint)
{
  return checkCompatibilityState(connectionPoint)
         == NodeMaterialConnectionPointCompatibilityStates::Compatible;
}

NodeMaterialConnectionPointCompatibilityStates NodeMaterialConnectionPoint::checkCompatibilityState(
  const NodeMaterialConnectionPoint& connectionPoint)
{
  const auto& iOwnerBlock = _ownerBlock;
  const auto& otherBlock  = connectionPoint.ownerBlock();

  if (iOwnerBlock->target() == NodeMaterialBlockTargets::Fragment) {
    // Let's check we are not going reverse

    if (otherBlock->target() == NodeMaterialBlockTargets::Vertex) {
      return NodeMaterialConnectionPointCompatibilityStates::TargetIncompatible;
    }

    for (const auto& output : otherBlock->outputs()) {
      if (output->ownerBlock()->target() != NodeMaterialBlockTargets::Neutral
          && output->isConnectedInVertexShader()) {
        return NodeMaterialConnectionPointCompatibilityStates::TargetIncompatible;
      }
    }
  }

  if (type != connectionPoint.type
      && connectionPoint.innerType() != NodeMaterialBlockConnectionPointTypes::AutoDetect) {
    // Equivalents
    if (NodeMaterialConnectionPoint::AreEquivalentTypes(type, connectionPoint.type)) {
      return NodeMaterialConnectionPointCompatibilityStates::Compatible;
    }

    // Accepted types
    if ((!connectionPoint.acceptedConnectionPointTypes.empty()
         && stl_util::contains(connectionPoint.acceptedConnectionPointTypes, type))
        || (connectionPoint._acceptedConnectionPointType
            && NodeMaterialConnectionPoint::AreEquivalentTypes(
              connectionPoint._acceptedConnectionPointType->type, type))) {
      return NodeMaterialConnectionPointCompatibilityStates::Compatible;
    }
    else {
      return NodeMaterialConnectionPointCompatibilityStates::TypeIncompatible;
    }
  }

  // Excluded
  if ((!connectionPoint.excludedConnectionPointTypes.empty()
       && stl_util::contains(connectionPoint.excludedConnectionPointTypes, type))) {
    return NodeMaterialConnectionPointCompatibilityStates::TypeIncompatible;
  }

  // Check hierarchy
  auto targetBlock  = otherBlock;
  auto iSourceBlock = ownerBlock();
  if (direction() == NodeMaterialConnectionPointDirection::Input) {
    targetBlock  = ownerBlock();
    iSourceBlock = otherBlock;
  }

  if (targetBlock->isAnAncestorOf(iSourceBlock)) {
    return NodeMaterialConnectionPointCompatibilityStates::HierarchyIssue;
  }

  return NodeMaterialConnectionPointCompatibilityStates::Compatible;
}

NodeMaterialConnectionPoint&
NodeMaterialConnectionPoint::connectTo(const NodeMaterialConnectionPointPtr& connectionPoint,
                                       bool ignoreConstraints)
{
  if (!ignoreConstraints && !canConnectTo(*connectionPoint)) {
    throw std::runtime_error("Cannot connect these two connectors.");
  }

  _endpoints.emplace_back(connectionPoint);
  connectionPoint->_connectedPoint = shared_from_this();

  _enforceAssociatedVariableName = false;

  onConnectionObservable.notifyObservers(connectionPoint.get());
  connectionPoint->onConnectionObservable.notifyObservers(this);

  return *this;
}

NodeMaterialConnectionPoint&
NodeMaterialConnectionPoint::disconnectFrom(const NodeMaterialConnectionPointPtr& endpoint)
{
  auto index = stl_util::index_of(_endpoints, endpoint);

  if (index == -1) {
    return *this;
  }

  stl_util::splice(_endpoints, index, 1);
  endpoint->_connectedPoint                = nullptr;
  _enforceAssociatedVariableName           = false;
  endpoint->_enforceAssociatedVariableName = false;
  return *this;
}

json NodeMaterialConnectionPoint::serialize(bool /*isInput*/) const
{
  return nullptr;
}

void NodeMaterialConnectionPoint::dispose()
{
  onConnectionObservable.clear();
}

} // end of namespace BABYLON
<|endoftext|>


<commit_before>#include <iostream>
#include "submodules/block_oled/Firmware/pong/oled/Edison_OLED.h"
#include "submodules/block_oled/Firmware/pong/gpio/gpio.h"
#include "math.h"
#include <stdio.h>

using namespace std;

// Function prototypes:
void setupOLED();
void startScreen();

void drawGame();
void cleanUp();

// Define an edOLED object:
edOLED oled;

// Pin definitions:
// All buttons have pull-up resistors on-board, so just declare
// them as regular INPUT's
gpio BUTTON_UP(47, INPUT);
gpio BUTTON_DOWN(44, INPUT);
gpio BUTTON_LEFT(165, INPUT);
gpio BUTTON_RIGHT(45, INPUT);
gpio BUTTON_SELECT(48, INPUT);
gpio BUTTON_A(49, INPUT);
gpio BUTTON_B(46, INPUT);

int main(int argc, char * argv[])
{
	printf("WASSUP!?\r\n");

	setupOLED();

	while(1)
	{
		drawGame();
	}

	cleanUp();
	return 0;
}

void setupOLED()
{
	oled.begin();
	//oled.clear(PAGE);
	oled.display();
	oled.setFontType(0);
}

// Draw the paddles, ball and score:
void drawGame()
{
	oled.clear(PAGE);

	oled.display();
}

void cleanUp()
{
	oled.clear(PAGE);
	oled.display();
}
<commit_msg>removed the drawgame clear part...<commit_after>#include <iostream>
#include "submodules/block_oled/Firmware/pong/oled/Edison_OLED.h"
#include "submodules/block_oled/Firmware/pong/gpio/gpio.h"
#include "math.h"
#include <stdio.h>

using namespace std;

// Function prototypes:
void setupOLED();
void startScreen();

void drawGame();
void cleanUp();

// Define an edOLED object:
edOLED oled;

// Pin definitions:
// All buttons have pull-up resistors on-board, so just declare
// them as regular INPUT's
gpio BUTTON_UP(47, INPUT);
gpio BUTTON_DOWN(44, INPUT);
gpio BUTTON_LEFT(165, INPUT);
gpio BUTTON_RIGHT(45, INPUT);
gpio BUTTON_SELECT(48, INPUT);
gpio BUTTON_A(49, INPUT);
gpio BUTTON_B(46, INPUT);

int main(int argc, char * argv[])
{
	printf("WASSUP!?\r\n");

	setupOLED();

	while(1)
	{
	//	drawGame();
	}

	cleanUp();
	return 0;
}

void setupOLED()
{
	oled.begin();
	//oled.clear(PAGE);
	oled.display();
	oled.setFontType(0);
}

// Draw the paddles, ball and score:
void drawGame()
{
	oled.clear(PAGE);

	oled.display();
}

void cleanUp()
{
	oled.clear(PAGE);
	oled.display();
}
<|endoftext|>


<commit_before>// Copyright eeGeo Ltd (2012-2015), All Rights Reserved

#include "NavRoutingCustomLocationPicker.h"
#include "IAppCameraLocationPicker.h"
#include "AppCameraLocationPicker.h"
#include "NavRoutingLocationModel.h"
#include "INavRoutingModel.h"

namespace ExampleApp
{
    namespace NavRouting
    {
        namespace SdkModel
        {
            NavRoutingCustomLocationPicker::NavRoutingCustomLocationPicker(
                    INavRoutingModel& navRoutingModel,
                    AppCamera::SdkModel::IAppCameraLocationPicker& cameraLocationPicker
            )
            : m_navRoutingModel(navRoutingModel)
            , m_cameraLocationPicker(cameraLocationPicker)
            {
            }

            NavRoutingCustomLocationPicker::~NavRoutingCustomLocationPicker()
            {
            }

            void NavRoutingCustomLocationPicker::StartSearching(bool forStartLocation)
            {
                m_isSearching = true;
                m_isStartLocation = forStartLocation;
            }

            void NavRoutingCustomLocationPicker::StopSearching()
            {
                m_isSearching = false;
            }

            bool NavRoutingCustomLocationPicker::HandleTouchTap(float screenX, float screenY)
            {
                if(!m_isSearching)
                {
                    return false;
                }

                AppCamera::SdkModel::AppCameraLocationPickerResult result = m_cameraLocationPicker.PickLocation(screenX, screenY);
                if(!result.IsValidResult())
                {
                    return true;
                }

                NavRoutingLocationModel locationModel("Custom location",
                                                      result.GetLocation(),
                                                      result.IsIndoors(),
                                                      result.GetIndoorId(),
                                                      result.GetIndoorFloorNumber());
                if(m_isStartLocation)
                {
                    m_navRoutingModel.SetStartLocation(locationModel);
                }
                else
                {
                    m_navRoutingModel.SetEndLocation(locationModel);
                }

                return true;
            }
        }
    }
}
<commit_msg>Fixed uninitalised state data for nav location picking. Buddy: Mark<commit_after>// Copyright eeGeo Ltd (2012-2015), All Rights Reserved

#include "NavRoutingCustomLocationPicker.h"
#include "IAppCameraLocationPicker.h"
#include "AppCameraLocationPicker.h"
#include "NavRoutingLocationModel.h"
#include "INavRoutingModel.h"

namespace ExampleApp
{
    namespace NavRouting
    {
        namespace SdkModel
        {
            NavRoutingCustomLocationPicker::NavRoutingCustomLocationPicker(
                    INavRoutingModel& navRoutingModel,
                    AppCamera::SdkModel::IAppCameraLocationPicker& cameraLocationPicker
            )
            : m_navRoutingModel(navRoutingModel)
            , m_cameraLocationPicker(cameraLocationPicker)
            , m_isSearching(false)
            , m_isStartLocation(false)
            {
            }

            NavRoutingCustomLocationPicker::~NavRoutingCustomLocationPicker()
            {
            }

            void NavRoutingCustomLocationPicker::StartSearching(bool forStartLocation)
            {
                m_isSearching = true;
                m_isStartLocation = forStartLocation;
            }

            void NavRoutingCustomLocationPicker::StopSearching()
            {
                m_isSearching = false;
            }

            bool NavRoutingCustomLocationPicker::HandleTouchTap(float screenX, float screenY)
            {
                if(!m_isSearching)
                {
                    return false;
                }

                AppCamera::SdkModel::AppCameraLocationPickerResult result = m_cameraLocationPicker.PickLocation(screenX, screenY);
                if(!result.IsValidResult())
                {
                    return true;
                }

                NavRoutingLocationModel locationModel("Custom location",
                                                      result.GetLocation(),
                                                      result.IsIndoors(),
                                                      result.GetIndoorId(),
                                                      result.GetIndoorFloorNumber());
                if(m_isStartLocation)
                {
                    m_navRoutingModel.SetStartLocation(locationModel);
                }
                else
                {
                    m_navRoutingModel.SetEndLocation(locationModel);
                }

                return true;
            }
        }
    }
}
<|endoftext|>


<commit_before>/*!
	\file rs_mesh_base.cpp
  \brief This file implements base class for reservoir simulation meshes
  \author Mark Khait
  \date 2009-07-20
  */

#include "bs_mesh_stdafx.h"
#include "rs_mesh_base.h"

using namespace blue_sky;

rs_mesh_base ::rs_mesh_base ()
{
  depths = give_kernel::Instance().create_object(bs_array<t_float>::bs_type());
  actnum_array = 0;
  poro_array = 0;
  ntg_array = 0;
  multpv_array = 0;

}

void
rs_mesh_base ::init_props (const sp_hdm_t hdm)
{
  minpv = hdm->get_prop ()->get_f ("minimal_pore_volume");
  minsv = hdm->get_prop ()->get_f ("minimal_splice_volume");
  max_thickness = hdm->get_prop ()->get_f ("maximum_splice_thickness");
  darcy_constant = hdm->get_darcy_constant ();

  spv_float data_array;
  spv_int sp_actnum_array;

  sp_actnum_array = hdm->get_pool ()->get_i_data("ACTNUM");
  if (sp_actnum_array->size()) actnum_array = &(*sp_actnum_array)[0];

  n_elements = static_cast <t_long> (sp_actnum_array->size ());
  n_active_elements =  std::accumulate(sp_actnum_array->begin(), sp_actnum_array->end(),0);

  data_array = hdm->get_pool ()->get_fp_data("PORO");
  if (data_array->size()) poro_array = &(*data_array)[0];

  data_array = hdm->get_pool ()->get_fp_data("NTG");
  if (data_array && data_array->size()) ntg_array = &(*data_array)[0];

  data_array = hdm->get_pool ()->get_fp_data("MULTPV");
  if (data_array && data_array->size()) multpv_array = &(*data_array)[0];
}

int rs_mesh_base::init_int_to_ext()
{
  t_long n_ext = t_long(ext_to_int->size());
  if (n_ext == 0)
    return -1;

  int_to_ext->init (n_active_elements, 0);

  t_long *int_to_ext_data = int_to_ext->data ();
  t_long *ext_to_int_data = ext_to_int->data ();

  for (t_long i = 0; i < n_ext; i++)
    {
      if (ext_to_int_data[i] != -1)
        {
          if (ext_to_int_data[i] >= n_active_elements)
            {
              bs_throw_exception (boost::format ("ext_to_int[%d] == %d >= %d") % i % ext_to_int_data[i] % n_active_elements);
            }

          int_to_ext_data[ext_to_int_data[i]] = i;
        }
    }
  return 0;
}

void rs_mesh_base::check_data() const
{
  base_t::check_data ();

  if (minpv < 0)
    bs_throw_exception (boost::format ("minpv = %d is out of range")% minpv);
  if (minsv < 0)
    bs_throw_exception (boost::format ("minsv = %d is out of range")% minsv);
  if (max_thickness < 0)
    bs_throw_exception (boost::format ("max_thickness = %d is out of range")% max_thickness);

  if (!actnum_array)
    bs_throw_exception ("ACTNUM array is not initialized");
  if (!poro_array)
    bs_throw_exception ("PORO array is not initialized");
  if (!depths->size ())
    bs_throw_exception ("depths array is not initialized");
}

//BS_INST_STRAT(rs_mesh_base);
<commit_msg>A bit better error reporting in init_int_to_ext<commit_after>/*!
	\file rs_mesh_base.cpp
  \brief This file implements base class for reservoir simulation meshes
  \author Mark Khait
  \date 2009-07-20
  */

#include "bs_mesh_stdafx.h"
#include "rs_mesh_base.h"

using namespace blue_sky;

rs_mesh_base ::rs_mesh_base ()
{
  depths = give_kernel::Instance().create_object(bs_array<t_float>::bs_type());
  actnum_array = 0;
  poro_array = 0;
  ntg_array = 0;
  multpv_array = 0;

}

void
rs_mesh_base ::init_props (const sp_hdm_t hdm)
{
  minpv = hdm->get_prop ()->get_f ("minimal_pore_volume");
  minsv = hdm->get_prop ()->get_f ("minimal_splice_volume");
  max_thickness = hdm->get_prop ()->get_f ("maximum_splice_thickness");
  darcy_constant = hdm->get_darcy_constant ();

  spv_float data_array;
  spv_int sp_actnum_array;

  sp_actnum_array = hdm->get_pool ()->get_i_data("ACTNUM");
  if (sp_actnum_array->size()) actnum_array = &(*sp_actnum_array)[0];

  n_elements = static_cast <t_long> (sp_actnum_array->size ());
  n_active_elements =  std::accumulate(sp_actnum_array->begin(), sp_actnum_array->end(),0);

  data_array = hdm->get_pool ()->get_fp_data("PORO");
  if (data_array->size()) poro_array = &(*data_array)[0];

  data_array = hdm->get_pool ()->get_fp_data("NTG");
  if (data_array && data_array->size()) ntg_array = &(*data_array)[0];

  data_array = hdm->get_pool ()->get_fp_data("MULTPV");
  if (data_array && data_array->size()) multpv_array = &(*data_array)[0];
}

int rs_mesh_base::init_int_to_ext()
{
  t_long n_ext = t_long(ext_to_int->size());
  if (n_ext == 0)
    return -1;

  int_to_ext->init (n_active_elements, 0);

  t_long *int_to_ext_data = int_to_ext->data ();
  t_long *ext_to_int_data = ext_to_int->data ();

  stdv_long wrong;
  stdv_long wrong_idx;
  for (t_long i = 0; i < n_ext; i++)
    {
      if (ext_to_int_data[i] != -1)
        {
          if (ext_to_int_data[i] >= n_active_elements)
            {
              wrong.push_back (ext_to_int_data[i]);
              wrong_idx.push_back (i);
            }
          else
            {
              int_to_ext_data[ext_to_int_data[i]] = i;
            }
        }
    }

  if (wrong.size ())
    {
      for (size_t i = 0, cnt = wrong.size (); i < cnt; ++i)
        {
          BOSERR (section::mesh, level::error)
            << boost::format ("ext_to_int[%d] == %s >= %d") % wrong_idx[i] % wrong[i] % n_active_elements
            << bs_end;
        }

      bs_throw_exception ("ext_to_int out of n_active_elements");
    }

  return 0;
}

void rs_mesh_base::check_data() const
{
  base_t::check_data ();

  if (minpv < 0)
    bs_throw_exception (boost::format ("minpv = %d is out of range")% minpv);
  if (minsv < 0)
    bs_throw_exception (boost::format ("minsv = %d is out of range")% minsv);
  if (max_thickness < 0)
    bs_throw_exception (boost::format ("max_thickness = %d is out of range")% max_thickness);

  if (!actnum_array)
    bs_throw_exception ("ACTNUM array is not initialized");
  if (!poro_array)
    bs_throw_exception ("PORO array is not initialized");
  if (!depths->size ())
    bs_throw_exception ("depths array is not initialized");
}

//BS_INST_STRAT(rs_mesh_base);
<|endoftext|>


<commit_before>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "JinSlabCoeffFunc.h"
#include "ElectromagneticEnums.h"
#include <complex>

registerMooseObject("ElectromagneticsTestApp", JinSlabCoeffFunc);

InputParameters
JinSlabCoeffFunc::validParams()
{
  InputParameters params = Function::validParams();
  params.addClassDescription(
      "Function describing a wave incident on a surface at a given angle, wavenumber, and domain "
      "length, for use in the slab reflection benchmark.");
  params.addRequiredParam<Real>("k", "Wavenumber");
  params.addRequiredParam<Real>("theta", "Wave Incidence angle, in degrees");
  params.addRequiredParam<Real>("length", "Length of slab domain");
  MooseEnum component("real imaginary");
  params.addParam<MooseEnum>("component", component, "Real or Imaginary wave component");
  return params;
}

JinSlabCoeffFunc::JinSlabCoeffFunc(const InputParameters & parameters)
  : Function(parameters),

    _k(getParam<Real>("k")),
    _theta(getParam<Real>("theta")),
    _length(getParam<Real>("length")),
    _component(getParam<MooseEnum>("component"))
{
}

Real
JinSlabCoeffFunc::value(Real /*t*/, const Point & p) const
{
  std::complex<double> jay(0, 1);
  std::complex<double> eps_r = 4.0 + (2.0 - jay * 0.1) * std::pow((1 - p(0) / _length), 2);
  std::complex<double> mu_r(2, -0.1);

  std::complex<double> val =
      mu_r * std::pow(_k, 2) * (eps_r - (1 / mu_r) * std::pow(sin(_theta * libMesh::pi / 180.), 2));

  if (_component == electromagnetics::REAL)
  {
    return val.real();
  }
  else
  {
    return val.imag();
  }
}
<commit_msg>Fixup int vs double issue with std::complex and GCC<commit_after>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "JinSlabCoeffFunc.h"
#include "ElectromagneticEnums.h"
#include <complex>

registerMooseObject("ElectromagneticsTestApp", JinSlabCoeffFunc);

InputParameters
JinSlabCoeffFunc::validParams()
{
  InputParameters params = Function::validParams();
  params.addClassDescription(
      "Function describing a wave incident on a surface at a given angle, wavenumber, and domain "
      "length, for use in the slab reflection benchmark.");
  params.addRequiredParam<Real>("k", "Wavenumber");
  params.addRequiredParam<Real>("theta", "Wave Incidence angle, in degrees");
  params.addRequiredParam<Real>("length", "Length of slab domain");
  MooseEnum component("real imaginary");
  params.addParam<MooseEnum>("component", component, "Real or Imaginary wave component");
  return params;
}

JinSlabCoeffFunc::JinSlabCoeffFunc(const InputParameters & parameters)
  : Function(parameters),

    _k(getParam<Real>("k")),
    _theta(getParam<Real>("theta")),
    _length(getParam<Real>("length")),
    _component(getParam<MooseEnum>("component"))
{
}

Real
JinSlabCoeffFunc::value(Real /*t*/, const Point & p) const
{
  std::complex<double> jay(0, 1);
  std::complex<double> eps_r = 4.0 + (2.0 - jay * 0.1) * std::pow((1 - p(0) / _length), 2);
  std::complex<double> mu_r(2, -0.1);

  std::complex<double> val =
      mu_r * std::pow(_k, 2) * (eps_r - (1.0 / mu_r) * std::pow(sin(_theta * libMesh::pi / 180.), 2));

  if (_component == electromagnetics::REAL)
  {
    return val.real();
  }
  else
  {
    return val.imag();
  }
}
<|endoftext|>


<commit_before>/*
 ================================================
 *      ######
 *    #########                            ##
 *   ####    ###                           ##
 *   ##       ##                           ##
 *  ##         ## ##   ##   ####     ### ######
 *  ##         ## ##   ##  ######  ##### ######
 *  ##         ## ##   ## ###  ## ###      ##
 *  ##    #    ## ##   ## ##  ##  #####    ##
 *   ##   ##   ## ##   ## ## ##    #####   ##
 *   ###   ## ##  ##   ## ###   #     ##   ##
 *    ##########  ####### ####### ######   ##
 *      #### ##    ######   ####   ####    ##
 *            ##
 *             ##       CREATE: 2013-09-04
 *              #
 ================================================
        QuestLAB 外部资源文件加载接口
 ================================================
 */

#include "../QstLibs/QstLibs.h"

/* 外部库引用 */
#ifndef _CR_NO_PRAGMA_LIB_
    #pragma comment (lib, "QstLibs_msc.lib")
#endif

/* 从宿主传过来的参数 */
static socket_t         s_netw = NULL;
static const ansi_t*    s_root = NULL;

#if defined(_CR_BUILD_DLL_)
/*
=======================================
    DLL 入口点
=======================================
*/
BOOL WINAPI
DllMain (
  __CR_IN__ HANDLE  hinst,
  __CR_IN__ DWORD   reason,
  __CR_UU__ LPVOID  reserved
    )
{
    switch (reason)
    {
        case DLL_PROCESS_ATTACH:
            s_netw = NULL;
            s_root = NULL;
            break;

        case DLL_PROCESS_DETACH:
            TRY_FREE(s_root)
            break;
    }
    CR_NOUSE(hinst);
    CR_NOUSE(reserved);
    return (TRUE);
}

#endif  /* _CR_BUILD_DLL_ */

/*****************************************************************************/
/*                                 接口实现                                  */
/*****************************************************************************/

/*
---------------------------------------
    启动加载器
---------------------------------------
*/
static void_t
res_init (
  __CR_IN__ socket_t        netw,
  __CR_IN__ const ansi_t*   root
    )
{
    if (netw != NULL)
        s_netw = netw;
    SAFE_FREE(s_root)
    if (root != NULL)
        s_root = str_dupA(root);
}

/*
---------------------------------------
    释放加载器
---------------------------------------
*/
static void_t
res_kill (void_t)
{
    s_netw = NULL;
    SAFE_FREE(s_root)
}

/*
---------------------------------------
    加载外部文件
---------------------------------------
*/
static bool_t
res_load (
  __CR_OT__ sEX_FILE*       filex,
  __CR_IN__ const ansi_t*   type,
  __CR_IN__ const ansi_t*   mount,
  __CR_IN__ const ansi_t*   name,
  __CR_IN__ uint_t          cpage
    )
{
    ansi_t* path;
    ansi_t* full;

    /* 跳过名称的根 */
    if (is_slashA(*name))
        name++;

    /* 直接使用名称预读 */
    if (s_root != NULL) {
        full = path_appendA(s_root, name);
        if (full == NULL)
            return (FALSE);
        if (file_existA(full)) {
            filex->is_free = TRUE;
            set_ldrA(&filex->ex_file, full, "", 0, 0);
            filex->ex_file.page = cpage;
            return (TRUE);
        }
        mem_free(full);
    }
    else {
        if (file_existA(name)) {
            filex->is_free = FALSE;
            set_ldrA(&filex->ex_file, name, "", 0, 0);
            filex->ex_file.page = cpage;
            return (TRUE);
        }
    }

    leng_t  idx, size;

    /* 以挂载名为根目录预读 */
    if (str_cmpA(mount, QST_STR_GLOBALS) != 0) {
        size = str_lenA(mount);
        for (idx = 0; idx < size; idx++) {
            if (mount[idx] == '|')
                break;
        }
        /* 包中包不做预读, 只做一层的预读 */
        if (idx >= size) {
            if (s_root != NULL)
                path = path_appendA(s_root, mount);
            else
                path = str_dupA(mount);
            if (path == NULL)
                return (FALSE);
            filext_removeA(path);
            full = path_appendA(path, name);
            mem_free(path);
            if (full == NULL)
                return (FALSE);
            if (file_existA(full)) {
                filex->is_free = TRUE;
                set_ldrA(&filex->ex_file, full, "", 0, 0);
                filex->ex_file.page = cpage;
                return (TRUE);
            }
            mem_free(full);
        }
    }

    /* 使用网络接口加载 */
    if (s_netw == NULL)
        return (FALSE);

    /* 发送资源加载命令 */
    full = str_fmtA("res:load \"%s\" \"%s\" \"%s\" %u",
                    type, mount, name, cpage);
    if (full == NULL)
        return (FALSE);
    if (!cmd_shl_send(s_netw, full)) {
        mem_free(full);
        return (FALSE);
    }
    mem_free(full);     /* 加大网络超时五倍 */
    socket_set_timeout(s_netw, -1, QST_TCP_TOUT * 5);

    /* 等待资源加载返回 */
    for (;;)
    {
        uint_t      argc;
        ansi_t**    argv;

        /* 接收一条消息, 出错退出 */
        full = netw_cmd_recv(s_netw);
        if (full == NULL)
            break;

        /* 判断是不是需要的消息 */
        path = cmd_shl_get(full);
        mem_free(full);
        if (path == NULL)
            continue;
        argv = cmd_shl_split(path, &argc);
        if (argv == NULL) {
            mem_free(path);
            break;
        }
        if ((argc < 2) ||
            (str_cmpA(argv[1], type) != 0)) {
            mem_free(argv);
            mem_free(path);
            continue;
        }
        if (str_cmpA(argv[0], "res:fail") == 0) {
            mem_free(argv);
            mem_free(path);
            break;
        }
        if (str_cmpA(argv[0], "res:okay") == 0) {
            if (argc < 3) {
                mem_free(argv);
                mem_free(path);
                break;
            }

            void_t* data;

            /* 返回读取的内存数据 */
            size = str2intA(argv[2]);
            mem_free(argv);
            mem_free(path);
            if (size == 0)
                break;
            data = share_file_get(type, size);
            if (data == NULL)
                break;
            filex->is_free = TRUE;
            set_ldrM(&filex->ex_file, data, size, "", 0, 0);
            filex->ex_file.page = cpage;
            socket_set_timeout(s_netw, -1, QST_TCP_TOUT);
            return (TRUE);
        }
        mem_free(argv);
        mem_free(path);
    }

    /* 从循环出来表示失败 */
    socket_set_timeout(s_netw, -1, QST_TCP_TOUT);
    return (FALSE);
}

/*****************************************************************************/
/*                                 接口导出                                  */
/*****************************************************************************/

/* 外部文件加载接口表 */
static const sRES_LOADER
s_res_loader = { res_init, res_kill, res_load };

/*
=======================================
    获取外部文件加载接口表
=======================================
*/
CR_API const sRES_LOADER*
res_loader_get (void_t)
{
    return (&s_res_loader);
}
<commit_msg>ResLoader: 过滤非法的返回数据大小<commit_after>/*
 ================================================
 *      ######
 *    #########                            ##
 *   ####    ###                           ##
 *   ##       ##                           ##
 *  ##         ## ##   ##   ####     ### ######
 *  ##         ## ##   ##  ######  ##### ######
 *  ##         ## ##   ## ###  ## ###      ##
 *  ##    #    ## ##   ## ##  ##  #####    ##
 *   ##   ##   ## ##   ## ## ##    #####   ##
 *   ###   ## ##  ##   ## ###   #     ##   ##
 *    ##########  ####### ####### ######   ##
 *      #### ##    ######   ####   ####    ##
 *            ##
 *             ##       CREATE: 2013-09-04
 *              #
 ================================================
        QuestLAB 外部资源文件加载接口
 ================================================
 */

#include "../QstLibs/QstLibs.h"

/* 外部库引用 */
#ifndef _CR_NO_PRAGMA_LIB_
    #pragma comment (lib, "QstLibs_msc.lib")
#endif

/* 从宿主传过来的参数 */
static socket_t         s_netw = NULL;
static const ansi_t*    s_root = NULL;

#if defined(_CR_BUILD_DLL_)
/*
=======================================
    DLL 入口点
=======================================
*/
BOOL WINAPI
DllMain (
  __CR_IN__ HANDLE  hinst,
  __CR_IN__ DWORD   reason,
  __CR_UU__ LPVOID  reserved
    )
{
    switch (reason)
    {
        case DLL_PROCESS_ATTACH:
            s_netw = NULL;
            s_root = NULL;
            break;

        case DLL_PROCESS_DETACH:
            TRY_FREE(s_root)
            break;
    }
    CR_NOUSE(hinst);
    CR_NOUSE(reserved);
    return (TRUE);
}

#endif  /* _CR_BUILD_DLL_ */

/*****************************************************************************/
/*                                 接口实现                                  */
/*****************************************************************************/

/*
---------------------------------------
    启动加载器
---------------------------------------
*/
static void_t
res_init (
  __CR_IN__ socket_t        netw,
  __CR_IN__ const ansi_t*   root
    )
{
    if (netw != NULL)
        s_netw = netw;
    SAFE_FREE(s_root)
    if (root != NULL)
        s_root = str_dupA(root);
}

/*
---------------------------------------
    释放加载器
---------------------------------------
*/
static void_t
res_kill (void_t)
{
    s_netw = NULL;
    SAFE_FREE(s_root)
}

/*
---------------------------------------
    加载外部文件
---------------------------------------
*/
static bool_t
res_load (
  __CR_OT__ sEX_FILE*       filex,
  __CR_IN__ const ansi_t*   type,
  __CR_IN__ const ansi_t*   mount,
  __CR_IN__ const ansi_t*   name,
  __CR_IN__ uint_t          cpage
    )
{
    ansi_t* path;
    ansi_t* full;

    /* 跳过名称的根 */
    if (is_slashA(*name))
        name++;

    /* 直接使用名称预读 */
    if (s_root != NULL) {
        full = path_appendA(s_root, name);
        if (full == NULL)
            return (FALSE);
        if (file_existA(full)) {
            filex->is_free = TRUE;
            set_ldrA(&filex->ex_file, full, "", 0, 0);
            filex->ex_file.page = cpage;
            return (TRUE);
        }
        mem_free(full);
    }
    else {
        if (file_existA(name)) {
            filex->is_free = FALSE;
            set_ldrA(&filex->ex_file, name, "", 0, 0);
            filex->ex_file.page = cpage;
            return (TRUE);
        }
    }

    leng_t  idx, size;

    /* 以挂载名为根目录预读 */
    if (str_cmpA(mount, QST_STR_GLOBALS) != 0) {
        size = str_lenA(mount);
        for (idx = 0; idx < size; idx++) {
            if (mount[idx] == '|')
                break;
        }
        /* 包中包不做预读, 只做一层的预读 */
        if (idx >= size) {
            if (s_root != NULL)
                path = path_appendA(s_root, mount);
            else
                path = str_dupA(mount);
            if (path == NULL)
                return (FALSE);
            filext_removeA(path);
            full = path_appendA(path, name);
            mem_free(path);
            if (full == NULL)
                return (FALSE);
            if (file_existA(full)) {
                filex->is_free = TRUE;
                set_ldrA(&filex->ex_file, full, "", 0, 0);
                filex->ex_file.page = cpage;
                return (TRUE);
            }
            mem_free(full);
        }
    }

    /* 使用网络接口加载 */
    if (s_netw == NULL)
        return (FALSE);

    /* 发送资源加载命令 */
    full = str_fmtA("res:load \"%s\" \"%s\" \"%s\" %u",
                    type, mount, name, cpage);
    if (full == NULL)
        return (FALSE);
    if (!cmd_shl_send(s_netw, full)) {
        mem_free(full);
        return (FALSE);
    }
    mem_free(full);     /* 加大网络超时五倍 */
    socket_set_timeout(s_netw, -1, QST_TCP_TOUT * 5);

    /* 等待资源加载返回 */
    for (;;)
    {
        uint_t      argc;
        ansi_t**    argv;

        /* 接收一条消息, 出错退出 */
        full = netw_cmd_recv(s_netw);
        if (full == NULL)
            break;

        /* 判断是不是需要的消息 */
        path = cmd_shl_get(full);
        mem_free(full);
        if (path == NULL)
            continue;
        argv = cmd_shl_split(path, &argc);
        if (argv == NULL) {
            mem_free(path);
            break;
        }
        if ((argc < 2) ||
            (str_cmpA(argv[1], type) != 0)) {
            mem_free(argv);
            mem_free(path);
            continue;
        }
        if (str_cmpA(argv[0], "res:fail") == 0) {
            mem_free(argv);
            mem_free(path);
            break;
        }
        if (str_cmpA(argv[0], "res:okay") == 0) {
            if (argc < 3) {
                mem_free(argv);
                mem_free(path);
                break;
            }

            void_t* data;

            /* 返回读取的内存数据 */
            size = str2intA(argv[2]);
            mem_free(argv);
            mem_free(path);
            if ((dist_t)size <= 0)
                break;
            data = share_file_get(type, size);
            if (data == NULL)
                break;
            filex->is_free = TRUE;
            set_ldrM(&filex->ex_file, data, size, "", 0, 0);
            filex->ex_file.page = cpage;
            socket_set_timeout(s_netw, -1, QST_TCP_TOUT);
            return (TRUE);
        }
        mem_free(argv);
        mem_free(path);
    }

    /* 从循环出来表示失败 */
    socket_set_timeout(s_netw, -1, QST_TCP_TOUT);
    return (FALSE);
}

/*****************************************************************************/
/*                                 接口导出                                  */
/*****************************************************************************/

/* 外部文件加载接口表 */
static const sRES_LOADER
s_res_loader = { res_init, res_kill, res_load };

/*
=======================================
    获取外部文件加载接口表
=======================================
*/
CR_API const sRES_LOADER*
res_loader_get (void_t)
{
    return (&s_res_loader);
}
<|endoftext|>


<commit_before><commit_msg>Prediction: process and normalize the feature map tensor<commit_after><|endoftext|>


<commit_before>#include "glincludes.h"
#include "camera.h"
#include <stdio.h>
#include "volumeRenderer.h"
#include "voxelization.h"

//static VoxelMaker* voxel_maker_ptr_s;
static VoxelStructure* voxel_struct_ptr;
static GLuint texName;
static int _x,_y,_z;
//box and its index

static GLfloat vertice[] ={
	-1.0f, 1.0f, -1.0f,
	1.0f, 1.0f, -1.0f,
	1.0f, 1.0f, 1.0f,
	-1.0f, 1.0f, 1.0f,
	-1.0f, -1.0f, -1.0f,
	1.0f, -1.0f, -1.0f,
	1.0f, -1.0f, 1.0f,
	-1.0f, -1.0f, 1.0f
};

static GLfloat color[] = {
	0.0f, 0.0f, 0.0f,
	0.0f, 0.0f, 1.0f,
	0.0f, 1.0f, 0.0f,
	0.0f, 1.0f, 1.0f,
	1.0f, 0.0f, 0.0f,
	1.0f, 0.0f, 1.0f,
	1.0f, 1.0f, 0.0f,
	1.0f, 1.0f, 1.0f
};

static GLfloat texcoord[] = {
	0.0f, 1.0f, 0.0f,
	1.0f, 1.0f, 0.0f,
	1.0f, 1.0f, 1.0f,
	0.0f, 1.0f, 1.0f,
	0.0f, 0.0f, 0.0f,
	1.0f, 0.0f, 0.0f,
	1.0f, 0.0f, 1.0f,
	0.0f, 0.0f, 1.0f
};

static GLushort index[] =
{
	3, 2, 6, 7,
	1, 5, 6, 2,
	6, 5, 4, 7,
	5, 1, 0, 4,
	0, 3, 7, 4,
	0, 1, 2, 3
};

//the file is .raw
bool loadTextures() {

	/*	FILE *pFile = fopen(RAWFILENAME,"rb");
	if (NULL == pFile) {
	return false;
	}

	int size = XMAX*YMAX*ZMAX;
	unsigned char *pVolume = new unsigned char[size];
	bool ok = (size == fread(pVolume,sizeof(unsigned char), size,pFile));
	fclose(pFile);*/

	voxel_struct_ptr->get_size(_x, _y, _z);

	texName = voxel_struct_ptr->Creat3DTexture();

	glBindTexture(GL_TEXTURE_3D, texName);
	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

	//VoxelMaker::SaveToFile(voxel_struct_ptr, ".\\voxelfiles\\earth_voxel_1024.txt");

	return true;
}

void init(void)
{
	glewInit();
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glShadeModel(GL_SMOOTH);
	/***************test voxel maker*************************/
<<<<<<< HEAD
	voxel_maker_ptr_s = VoxelMaker::MakeObjToVoxel("earth.obj", 128);
=======
	//voxel_struct_ptr = VoxelMaker::MakeObjToVoxel("earth.obj", 1024);
	voxel_struct_ptr = VoxelMaker::LoadVoxelFromFile(".\\voxelfiles\\earth_voxel_128.txt");
>>>>>>> xmm_notebook
	/***************test voxel maker*************************/

	/***************test renderer*************************/
	loadTextures();
	/***************test renderer*************************/
}

void display()
{
	glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
	/***************test renderer*************************/
	cameraDisplay();
	glm::mat4 mv = View * Model;
	glm::mat4 p = Projection;
	//int _x,_y,_z;
	//voxel_maker_ptr_s->GetSize(_x, _y, _z);
	//VolumeRenderer::drawPhysicsWorld(texName, &mv, &p,XMAX, YMAX, ZMAX);
	VolumeRenderer::drawPhysicsWorld(texName, &mv, &p,_x, _y, _z);
	/***************test renderer*************************/

	/***************test voxel maker*************************/
	//int _x,_y,_z;
	//voxel_maker_ptr_s->GetSize(_x, _y, _z);
	//voxel_maker_ptr_s->DrawDepth(glm::ivec3(0, 0, 0), glm::ivec3(_x, _y, _z));
	/***************test voxel maker*************************/

	glutPostRedisplay();
	glutSwapBuffers();
}

int main(int argc, char** argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
	glutInitWindowSize(SCREENWIDTH, SCREENHEIGHT);
	glutInitWindowPosition(0, 0);
	glutCreateWindow(argv[0]);
	init();
	glutDisplayFunc(display);
	cameraLoop();

	glutMainLoop();

	return 0;
}
<commit_msg>改回并合并<commit_after>#include "glincludes.h"
#include "camera.h"
#include <stdio.h>
#include "volumeRenderer.h"
#include "voxelization.h"

//static VoxelMaker* voxel_maker_ptr_s;
static VoxelStructure* voxel_struct_ptr;
static GLuint texName;
static int _x,_y,_z;
//box and its index

static GLfloat vertice[] ={
	-1.0f, 1.0f, -1.0f,
	1.0f, 1.0f, -1.0f,
	1.0f, 1.0f, 1.0f,
	-1.0f, 1.0f, 1.0f,
	-1.0f, -1.0f, -1.0f,
	1.0f, -1.0f, -1.0f,
	1.0f, -1.0f, 1.0f,
	-1.0f, -1.0f, 1.0f
};

static GLfloat color[] = {
	0.0f, 0.0f, 0.0f,
	0.0f, 0.0f, 1.0f,
	0.0f, 1.0f, 0.0f,
	0.0f, 1.0f, 1.0f,
	1.0f, 0.0f, 0.0f,
	1.0f, 0.0f, 1.0f,
	1.0f, 1.0f, 0.0f,
	1.0f, 1.0f, 1.0f
};

static GLfloat texcoord[] = {
	0.0f, 1.0f, 0.0f,
	1.0f, 1.0f, 0.0f,
	1.0f, 1.0f, 1.0f,
	0.0f, 1.0f, 1.0f,
	0.0f, 0.0f, 0.0f,
	1.0f, 0.0f, 0.0f,
	1.0f, 0.0f, 1.0f,
	0.0f, 0.0f, 1.0f
};

static GLushort index[] =
{
	3, 2, 6, 7,
	1, 5, 6, 2,
	6, 5, 4, 7,
	5, 1, 0, 4,
	0, 3, 7, 4,
	0, 1, 2, 3
};

//the file is .raw
bool loadTextures() {

	/*	FILE *pFile = fopen(RAWFILENAME,"rb");
	if (NULL == pFile) {
	return false;
	}

	int size = XMAX*YMAX*ZMAX;
	unsigned char *pVolume = new unsigned char[size];
	bool ok = (size == fread(pVolume,sizeof(unsigned char), size,pFile));
	fclose(pFile);*/

	voxel_struct_ptr->get_size(_x, _y, _z);

	texName = voxel_struct_ptr->Creat3DTexture();

	glBindTexture(GL_TEXTURE_3D, texName);
	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

	//VoxelMaker::SaveToFile(voxel_struct_ptr, ".\\voxelfiles\\earth_voxel_1024.txt");

	return true;
}

void init(void)
{
	glewInit();
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glShadeModel(GL_SMOOTH);
	/***************test voxel maker*************************/
	//voxel_struct_ptr = VoxelMaker::MakeObjToVoxel("earth.obj", 1024);
	voxel_struct_ptr = VoxelMaker::LoadVoxelFromFile(".\\voxelfiles\\earth_voxel_128.txt");
	/***************test voxel maker*************************/

	/***************test renderer*************************/
	loadTextures();
	/***************test renderer*************************/
}

void display()
{
	glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
	/***************test renderer*************************/
	cameraDisplay();
	glm::mat4 mv = View * Model;
	glm::mat4 p = Projection;
	//int _x,_y,_z;
	//voxel_maker_ptr_s->GetSize(_x, _y, _z);
	//VolumeRenderer::drawPhysicsWorld(texName, &mv, &p,XMAX, YMAX, ZMAX);
	VolumeRenderer::drawPhysicsWorld(texName, &mv, &p,_x, _y, _z);
	/***************test renderer*************************/

	/***************test voxel maker*************************/
	//int _x,_y,_z;
	//voxel_maker_ptr_s->GetSize(_x, _y, _z);
	//voxel_maker_ptr_s->DrawDepth(glm::ivec3(0, 0, 0), glm::ivec3(_x, _y, _z));
	/***************test voxel maker*************************/

	glutPostRedisplay();
	glutSwapBuffers();
}

int main(int argc, char** argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
	glutInitWindowSize(SCREENWIDTH, SCREENHEIGHT);
	glutInitWindowPosition(0, 0);
	glutCreateWindow(argv[0]);
	init();
	glutDisplayFunc(display);
	cameraLoop();

	glutMainLoop();

	return 0;
}
<|endoftext|>


<commit_before>/*
 ================================================
 *      ######
 *    #########                            ##
 *   ####    ###                           ##
 *   ##       ##                           ##
 *  ##         ## ##   ##   ####     ### ######
 *  ##         ## ##   ##  ######  ##### ######
 *  ##         ## ##   ## ###  ## ###      ##
 *  ##    #    ## ##   ## ##  ##  #####    ##
 *   ##   ##   ## ##   ## ## ##    #####   ##
 *   ###   ## ##  ##   ## ###   #     ##   ##
 *    ##########  ####### ####### ######   ##
 *      #### ##    ######   ####   ####    ##
 *            ##
 *             ##       CREATE: 2015-07-20
 *              #
 ================================================
        QuestLAB Python 脚本启动器
 ================================================
 */

#include "../QstLibs/QstLibs.h"

/* 应用的名称 */
#ifndef EXE_XNAME
    #define EXE_XNAME   "RunPython"
    #define WIN_TITLE   "RunPython"
    #define WIN_CLASS   "RunPythonCLSS"
    #define WIN_ICONF   "RunPython.ini"
    #define WIN_XCONF   "RunPython.xml"
#endif

/*
=======================================
    WinMain 程序入口
=======================================
*/
int WINAPI
WinMain (
  __CR_IN__ HINSTANCE   curt_app,
  __CR_IN__ HINSTANCE   prev_app,
  __CR_IN__ LPSTR       cmd_line,
  __CR_IN__ int         cmd_show
    )
{
    uint_t      argc;
    ansi_t**    argv;

    CR_NOUSE(curt_app);
    CR_NOUSE(prev_app);
    CR_NOUSE(cmd_show);

    /* 建立 CrHack 系统 */
    if (!set_app_type(CR_APP_GUI))
        return (QST_ERROR);

    /* 获取命令行参数, 不包括进程文件名 */
    argv = misc_get_param(cmd_line, &argc);

    /* 参数解析 <脚本文件> */
    if (argc < 1)
        return (QST_ERROR);

    leng_t  size;
    ansi_t* root;
    ansi_t* exec;

    /* 合成 PYTHONHOME 目录 */
    exec = file_load_as_strA(QST_ROOT_START);
    if (exec == NULL)
        return (QST_ERROR);
    root = str_fmtA("%s\\python", exec);
    mem_free(exec);
    if (root == NULL)
        return (QST_ERROR);

    DWORD   cf = 0;

    /* 根据扩展名选择用哪个启动 */
    if (filext_checkA(argv[0], ".py")) {
        exec = str_fmtA("%s.exe \"%s\"", root, argv[0]);
        cf = CREATE_NEW_CONSOLE;
    }
    else
    if (filext_checkA(argv[0], ".pyw")) {
        exec = str_fmtA("%sw.exe \"%s\"", root, argv[0]);
        cf = CREATE_NO_WINDOW;
    }
    else {
        exec = NULL;
    }
    if (exec == NULL) {
        mem_free(root);
        return (QST_ERROR);
    }

    STARTUPINFOA        si;
    PROCESS_INFORMATION pi;

    /* 启动脚本 */
    mem_zero(&si, sizeof(si));
    si.cb = sizeof(STARTUPINFOA);
    SetEnvironmentVariableA("PYTHONHOME", root);
    size  = str_lenA(root);
    size -= str_lenA("\\python");
    root[size] = 0x00;
    if (CreateProcessA(NULL, exec, NULL, NULL, FALSE,
                       cf, NULL, root, &si, &pi)) {
        WaitForSingleObject(pi.hProcess, INFINITE);
        CloseHandle(pi.hThread);
        CloseHandle(pi.hProcess);
    }
    mem_free(exec);
    mem_free(root);
    return (QST_OKAY);
}
<commit_msg>RunPython: 支持从任何目录执行脚本<commit_after>/*
 ================================================
 *      ######
 *    #########                            ##
 *   ####    ###                           ##
 *   ##       ##                           ##
 *  ##         ## ##   ##   ####     ### ######
 *  ##         ## ##   ##  ######  ##### ######
 *  ##         ## ##   ## ###  ## ###      ##
 *  ##    #    ## ##   ## ##  ##  #####    ##
 *   ##   ##   ## ##   ## ## ##    #####   ##
 *   ###   ## ##  ##   ## ###   #     ##   ##
 *    ##########  ####### ####### ######   ##
 *      #### ##    ######   ####   ####    ##
 *            ##
 *             ##       CREATE: 2015-07-20
 *              #
 ================================================
        QuestLAB Python 脚本启动器
 ================================================
 */

#include "../QstLibs/QstLibs.h"

/* 应用的名称 */
#ifndef EXE_XNAME
    #define EXE_XNAME   "RunPython"
    #define WIN_TITLE   "RunPython"
    #define WIN_CLASS   "RunPythonCLSS"
    #define WIN_ICONF   "RunPython.ini"
    #define WIN_XCONF   "RunPython.xml"
#endif

/*
=======================================
    WinMain 程序入口
=======================================
*/
int WINAPI
WinMain (
  __CR_IN__ HINSTANCE   curt_app,
  __CR_IN__ HINSTANCE   prev_app,
  __CR_IN__ LPSTR       cmd_line,
  __CR_IN__ int         cmd_show
    )
{
    uint_t      argc;
    ansi_t**    argv;

    CR_NOUSE(curt_app);
    CR_NOUSE(prev_app);
    CR_NOUSE(cmd_show);

    /* 建立 CrHack 系统 */
    if (!set_app_type(CR_APP_GUI))
        return (QST_ERROR);

    /* 获取命令行参数, 不包括进程文件名 */
    argv = misc_get_param(cmd_line, &argc);

    /* 参数解析 <脚本文件> [相对路径] */
    if (argc < 1)
        return (QST_ERROR);

    leng_t  size;
    ansi_t* root;
    ansi_t* exec;

    /* 合成 PYTHONHOME 目录 */
    exec = file_load_as_strA(QST_ROOT_START);
    if (exec == NULL) {
        if (argc < 2)
            return (QST_ERROR);
        root = str_fmtA("%s\\" QST_ROOT_START, argv[1]);
        if (root == NULL)
            return (QST_ERROR);
        exec = file_load_as_strA(root);
        mem_free(root);
        if (exec == NULL)
            return (QST_ERROR);
    }
    root = str_fmtA("%s\\python", exec);
    mem_free(exec);
    if (root == NULL)
        return (QST_ERROR);

    DWORD   cf = 0;

    /* 根据扩展名选择用哪个启动 */
    if (filext_checkA(argv[0], ".py")) {
        exec = str_fmtA("%s.exe \"%s\"", root, argv[0]);
        cf = CREATE_NEW_CONSOLE;
    }
    else
    if (filext_checkA(argv[0], ".pyw")) {
        exec = str_fmtA("%sw.exe \"%s\"", root, argv[0]);
        cf = CREATE_NO_WINDOW;
    }
    else {
        exec = NULL;
    }
    if (exec == NULL) {
        mem_free(root);
        return (QST_ERROR);
    }

    STARTUPINFOA        si;
    PROCESS_INFORMATION pi;

    /* 启动脚本 */
    mem_zero(&si, sizeof(si));
    si.cb = sizeof(STARTUPINFOA);
    SetEnvironmentVariableA("PYTHONHOME", root);
    size  = str_lenA(root);
    size -= str_lenA("\\python");
    root[size] = 0x00;
    if (CreateProcessA(NULL, exec, NULL, NULL, FALSE,
                       cf, NULL, root, &si, &pi)) {
        WaitForSingleObject(pi.hProcess, INFINITE);
        CloseHandle(pi.hThread);
        CloseHandle(pi.hProcess);
    }
    mem_free(exec);
    mem_free(root);
    return (QST_OKAY);
}
<|endoftext|>