⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 actionmap.cc

📁 五行MMORPG引擎系统V1.0
💻 CC
📖 第 1 页 / 共 4 页
字号:
//   if (action >= KEY_A && action <= KEY_Z) {
//      buffer[0] = char(action - KEY_A + 'a');
//      buffer[1] = '\0';
//      return true;
//   } else if (action >= KEY_0 && action <= KEY_9) {
//      buffer[0] = char(action - KEY_0 + '0');
//      buffer[1] = '\0';
   if ( (asciiCode != 0) && dIsDecentChar((char)asciiCode))
   {
      for (U32 i = 0; gAsciiMap[i].asciiCode != 0xFFFF; i++) {
         if (gAsciiMap[i].asciiCode == asciiCode)
         {
            dStrcpy(buffer, gAsciiMap[i].pDescription);
            return true;
         }
      }
      // Must not have found a string for that ascii code just record the char
      buffer[0] = char(asciiCode);
      buffer[1] = '\0';
      return true;
   }
   else
   {
      if (action >= KEY_A && action <= KEY_Z)
      {
         buffer[0] = char(action - KEY_A + 'a');
         buffer[1] = '\0';
         return true;
      }
      else if (action >= KEY_0 && action <= KEY_9) {
         buffer[0] = char(action - KEY_0 + '0');
         buffer[1] = '\0';
         return true;
      }
      for (U32 i = 0; gVirtualMap[i].code != 0xFFFFFFFF; i++) {
         if (gVirtualMap[i].code == action) {
            dStrcpy(buffer, gVirtualMap[i].pDescription);
            return true;
         }
      }
   }

   Con::errorf( "ActionMap::getKeyString: no string for action %d", action );
   return false;
}

//--------------------------------------------------------------------------
bool ActionMap::processBindCmd(const char *device, const char *action, const char *makeCmd, const char *breakCmd)
{
   U32 deviceType;
   U32 deviceInst;

   if(!getDeviceTypeAndInstance(device, deviceType, deviceInst))
   {
      Con::printf("processBindCmd: unknown device: %s", device);
      return false;
   }

   // Ok, we now have the deviceType and instance.  Create an event descriptor
   //  for the bind...
   //
   EventDescriptor eventDescriptor;
   if (createEventDescriptor(action, &eventDescriptor) == false) {
      Con::printf("Could not create a description for binding: %s", action);
      return false;
   }

   // Create the full bind entry, and place it in the map
   //
   // DMMTODO
   Node* pBindNode = getNode(deviceType, deviceInst,
                             eventDescriptor.flags,
                             eventDescriptor.eventCode);

   pBindNode->flags           = Node::BindCmd;
   pBindNode->deadZoneBegin   = 0;
   pBindNode->deadZoneEnd     = 0;
   pBindNode->scaleFactor     = 1;
   if(makeCmd[0])
      pBindNode->makeConsoleCommand = dStrdup(makeCmd);
   else
      pBindNode->makeConsoleCommand = dStrdup("");

   if(breakCmd[0])
      pBindNode->breakConsoleCommand = dStrdup(breakCmd);
   else
      pBindNode->breakConsoleCommand = dStrdup("");
   return true;
}

//------------------------------------------------------------------------------
bool ActionMap::processBind(const U32 argc, const char** argv)
{
   // Ok, the bind will come in the following format:
   //  [device] [key or button] <[param spec] [param] ...> [fnName]
   //
   const char* pDeviceName = argv[0];
   const char* pEvent      = argv[1];
   const char* pFnName     = argv[argc - 1];

   // Determine the device
   U32 deviceType;
   U32 deviceInst;

   if(!getDeviceTypeAndInstance(argv[0], deviceType, deviceInst))
   {
      Con::printf("processBind: unknown device: %s", pDeviceName);
      return false;
   }

   // Ok, we now have the deviceType and instance.  Create an event descriptor
   //  for the bind...
   //
   EventDescriptor eventDescriptor;
   if (createEventDescriptor(pEvent, &eventDescriptor) == false) {
      Con::printf("Could not create a description for binding: %s", pEvent);
      return false;
   }

   // Event has now been described, and device determined.  we need now to extract
   //  any modifiers that the action map will apply to incoming events before
   //  calling the bound function...
   //
   // DMMTODO
   U32 assignedFlags = 0;
   F32 deadZoneBegin = 0.0f;
   F32 deadZoneEnd   = 0.0f;
   F32 scaleFactor   = 1.0f;

   if (argc != 3) {
      // We have the following: "[DSIR]" [deadZone] [scale]
      //
      const char* pSpec = argv[2];

      for (U32 i = 0; pSpec[i] != '\0'; i++) {
         switch (pSpec[i]) {
           case 'r': case 'R':
            assignedFlags |= Node::HasScale;
            break;
           case 's': case 'S':
            assignedFlags |= Node::HasScale;
            break;
           case 'd': case 'D':
            assignedFlags |= Node::HasDeadZone;
            break;
           case 'i': case 'I':
            assignedFlags |= Node::Inverted;
            break;

           default:
            AssertFatal(false, avar("Misunderstood specifier in bind (spec string: %s)",
                                    pSpec));
         }
      }

      // Ok, we have the flags.  Scan the dead zone and scale, if any.
      //
      U32 curArg = 3;
      if (assignedFlags & Node::HasDeadZone) {
         dSscanf(argv[curArg], "%g %g", &deadZoneBegin, &deadZoneEnd);
         curArg++;
      }
      if (assignedFlags & Node::HasScale) {
         scaleFactor = dAtof(argv[curArg]);
         curArg++;
      }

      if (curArg != (argc - 1)) {
         AssertFatal(curArg == (argc - 1), "error in bind spec somewhere...");
         Con::printf("Improperly specified bind for key: %s", argv[2]);
         return false;
      }
   }

   // We have decided to only allow one bind per console function, so
   // remove any existing nodes that are bound to the given function:
   if ( pFnName[0] )
   {
      U32 devMapIndex, nodeIndex;
      while ( findBoundNode( pFnName, devMapIndex, nodeIndex ) )
      {
         dFree( mDeviceMaps[devMapIndex]->nodeMap[nodeIndex].makeConsoleCommand );
         dFree( mDeviceMaps[devMapIndex]->nodeMap[nodeIndex].breakConsoleCommand );
         mDeviceMaps[devMapIndex]->nodeMap.erase( nodeIndex );
      }
   }

   // Ensure that the console function is properly specified?
   //
   // DMMTODO

   // Create the full bind entry, and place it in the map
   //
   // DMMTODO
   Node* pBindNode = getNode(deviceType, deviceInst,
                             eventDescriptor.flags,
                             eventDescriptor.eventCode);

   pBindNode->flags           = assignedFlags;
   pBindNode->deadZoneBegin   = deadZoneBegin;
   pBindNode->deadZoneEnd     = deadZoneEnd;
   pBindNode->scaleFactor     = scaleFactor;
   pBindNode->consoleFunction = StringTable->insert(pFnName);

   return true;
}

//------------------------------------------------------------------------------
bool ActionMap::processAction(const InputEvent* pEvent)
{
   static const char *argv[2];
   if (pEvent->action == SI_MAKE) {
      const Node* pNode = findNode(pEvent->deviceType, pEvent->deviceInst,
                                   pEvent->modifier,   pEvent->objInst);

      if (pNode == NULL) {
         // Check to see if we clear the modifiers, do we find an action?
         if (pEvent->modifier != 0)
            pNode = findNode(pEvent->deviceType, pEvent->deviceInst,
                             0,                  pEvent->objInst);

         if (pNode == NULL)
            return false;
      }

      // Whadda ya know, we have this bound.  Set up, and call the console
      //  function associated with it...
      //
      F32 value = pEvent->fValue;
      if (pNode->flags & Node::Ranged) {
         value = (value * 2.0f) - 1.0f;
         if (pNode->flags & Node::Inverted)
            value *= -1.0f;
      } else {
         if (pNode->flags & Node::Inverted)
            value = 1.0f - value;
      }

      if (pNode->flags & Node::HasScale)
         value *= pNode->scaleFactor;

      if (pNode->flags & Node::HasDeadZone)
         if (value >= pNode->deadZoneBegin &&
             value <= pNode->deadZoneEnd)
            value = 0.0f;

      // Ok, we're all set up, call the function.
      if(pNode->flags & Node::BindCmd)
      {
         // it's a bind command
         if(pNode->makeConsoleCommand)
            Con::evaluate(pNode->makeConsoleCommand);
      }
      else if ( pNode->consoleFunction[0] )
      {
         argv[0] = pNode->consoleFunction;
         argv[1] = Con::getFloatArg(value);
         Con::execute(2, argv);
      }
      //
      // And enter the break into the table if this is a make event...
      enterBreakEvent(pEvent, pNode);

      return true;
   } else if (pEvent->action == SI_MOVE) {
      if (pEvent->deviceType == MouseDeviceType) {
         const Node* pNode = findNode(pEvent->deviceType, pEvent->deviceInst,
                                      pEvent->modifier,   pEvent->objType);

         if (pNode == NULL) {
            // Check to see if we clear the modifiers, do we find an action?
            if (pEvent->modifier != 0)
               pNode = findNode(pEvent->deviceType, pEvent->deviceInst,
                                0,                  pEvent->objType);

            if (pNode == NULL)
               return false;
         }

         // "Do nothing" bind:
         if ( !pNode->consoleFunction[0] )
            return( true );

         // Whadda ya know, we have this bound.  Set up, and call the console
         //  function associated with it.  Mouse events ignore range and dead
         //  zone params.
         //
         F32 value = pEvent->fValue;
         if (pNode->flags & Node::Inverted)
            value *= -1.0f;
         if (pNode->flags & Node::HasScale)
            value *= pNode->scaleFactor;

         // Ok, we're all set up, call the function.
         argv[0] = pNode->consoleFunction;
         argv[1] = Con::getFloatArg(value);
         Con::execute(2, argv);

         return true;
      } else
      {
         // Joystick events...
         const Node* pNode = findNode( pEvent->deviceType, pEvent->deviceInst,
                                       pEvent->modifier,   pEvent->objType );

         if ( pNode == NULL )
         {
            // Check to see if we clear the modifiers, do we find an action?
            if (pEvent->modifier != 0)
               pNode = findNode( pEvent->deviceType, pEvent->deviceInst,
                                 0,                  pEvent->objType );

               if ( pNode == NULL )
                  return false;
         }

         // "Do nothing" bind:
         if ( !pNode->consoleFunction[0] )
            return( true );

         // Whadda ya know, we have this bound.  Set up, and call the console
         //  function associated with it.  Joystick move events are the same as mouse
         //  move events except that they don't ignore dead zone.
         //
         F32 value = pEvent->fValue;
         if ( pNode->flags & Node::Inverted )
            value *= -1.0f;

         if ( pNode->flags & Node::HasScale )
            value *= pNode->scaleFactor;

         if ( pNode->flags & Node::HasDeadZone )
            if ( value >= pNode->deadZoneBegin &&
                 value <= pNode->deadZoneEnd )
               value = 0.0f;

         // Ok, we're all set up, call the function.
         argv[0] = pNode->consoleFunction;
         argv[1] = Con::getFloatArg( value );
         Con::execute( 2, argv );

         return true;
      }
   } else if (pEvent->action == SI_BREAK) {
      return checkBreakTable(pEvent);
   }

   return false;
}

//------------------------------------------------------------------------------
void ActionMap::enterBreakEvent(const InputEvent* pEvent, const Node* pNode)
{
   // There aren't likely to be many breaks outstanding at any one given time,
   //  so a simple linear search is probably sufficient.  Note that the break table
   //  is static to the class, all breaks are directed to the action map that received
   //  the make.
   //
   S32 entry = -1;
   for (U32 i = 0; i < smBreakTable.size(); i++) {
      if (smBreakTable[i].deviceType == U32(pEvent->deviceType) &&
          smBreakTable[i].deviceInst == U32(pEvent->deviceInst) &&
          smBreakTable[i].objInst    == U32(pEvent->objInst)) {
         // Match.
         entry = i;
         break;
      }
   }
   if (entry == -1) {
      smBreakTable.increment();
      entry = smBreakTable.size() - 1;

      smBreakTable[entry].deviceType = pEvent->deviceType;
      smBreakTable[entry].deviceInst = pEvent->deviceInst;
      smBreakTable[entry].objInst    = pEvent->objInst;
   }

   // Ok, we now have the entry, and know that the device desc. and the objInst match.
   //  Copy out the node information...
   //
   smBreakTable[entry].consoleFunction = pNode->consoleFunction;
   if(pNode->breakConsoleCommand)
      smBreakTable[entry].breakConsoleCommand = dStrdup(pNode->breakConsoleCommand);
   else
      smBreakTable[entry].breakConsoleCommand = NULL;

   smBreakTable[entry].flags         = pNode->flags;
   smBreakTable[entry].deadZoneBegin = pNode->deadZoneBegin;
   smBreakTable[entry].deadZoneEnd   = pNode->deadZoneEnd;
   smBreakTable[entry].scaleFactor   = pNode->scaleFactor;
}

//------------------------------------------------------------------------------
bool ActionMap::checkBreakTable(const InputEvent* pEvent)
{
   for (U32 i = 0; i < smBreakTable.size(); i++) {
      if (smBreakTable[i].deviceType == U32(pEvent->deviceType) &&
          smBreakTable[i].deviceInst == U32(pEvent->deviceInst) &&
          smBreakTable[i].objInst    == U32(pEvent->objInst)) {
         // Match.  Issue the break event...
         //
         F32 value = pEvent->fValue;
         if (smBreakTable[i].flags & Node::Ranged) {
            value = (value * 2.0f) - 1.0f;
            if (smBreakTable[i].flags & Node::Inverted)
               value *= -1.0f;
         } else {
            if (smBreakTable[i].flags & Node::Inverted)
               value = 1.0f - value;
         }

         if (smBreakTable[i].flags & Node::HasScale)
            value *= smBreakTable[i].scaleFactor;

         if (smBreakTable[i].flags & Node::HasDeadZone)
            if (value >= smBreakTable[i].deadZoneBegin &&
                value <= smBreakTable[i].deadZoneEnd)
               value = 0.0f;

         // Ok, we're all set up, call the function.
         if(smBreakTable[i].consoleFunction)
         {
            if ( smBreakTable[i].consoleFunction[0] )

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -