// *********************************************************************************************************
void CDisplayerVisualShape::onPostRender()
{
	//H_AUTO(R2_CDisplayerVisualShape_onPostRender)
	if (!_Active || !getActualVisibility()) return;
	if (_BadShapeName) return;
	if (!_Instance.empty())
	{
		if (getDisplayFlag(FlagSelected))
		{
			//visualSnapToGround();
			drawBBox(CRGBA::Green);
			setEmissive(_Instance, getBlinkColor(CV_SelectedInstanceColor.get()));
		}
		else if (getDisplayFlag(FlagHasFocus))
		{
			//visualSnapToGround();
			drawBBox(CRGBA::White);
			setEmissive(_Instance, getBlinkColor(CV_FocusedInstanceColor.get()));
		}
		else
		{
			CRGBA color = getDisplayModeColorInScene();
			setEmissive(_Instance, color);
			::makeInstanceTransparent(_Instance, color.A, color.A != 255);
		}
	}
	CDisplayerVisual::onPostRender();
}
void FontManager::drawString(float x, float y, float z, int faceID, float size, std::string text)
{
  if (text.size() == 0)
    return;

  if ((faceID < 0) || (faceID > getNumFaces())) {
    DEBUG2("Trying to draw with invalid Font Face ID %d\n", faceID);
    return;
  }

  TextureFont* pFont = getClosestSize(faceID, size);

  if (!pFont)
    return;

  float scale = size / (float)pFont->getSize();

  /* 
   * Colorize text based on ANSI codes embedded in it
   * Break the text every time an ANSI code
   * is encountered and do a separate pFont->drawString code for
   * each segment, with the appropriate color parameter
   */

  // sane defaults
  bool bright = true;
  bool blink = false;	  //FIXME: blinking
  bool underline = false; //FIXME: underline
  // negatives are invalid, we use them to signal "no change"
  GLfloat color[3] = {-1.0f, -1.0f, -1.0f}; 

  // set underline color
  const char* uColor = BZDB.get("underlineColor").c_str();
  GLfloat underlineColor[3] = {-1.0f, -1.0f, -1.0f};
  if (strcasecmp(uColor, "text") == 0) {
    // use the initialized color, no change
  } else if (strcasecmp(uColor, "cyan") == 0) {
    underlineColor[0] = BrightColors[CyanColor][0];
    underlineColor[1] = BrightColors[CyanColor][1];
    underlineColor[2] = BrightColors[CyanColor][2];
  } else if (strcasecmp(uColor, "grey") == 0) {
    underlineColor[0] = BrightColors[GreyColor][0];
    underlineColor[1] = BrightColors[GreyColor][1];
    underlineColor[2] = BrightColors[GreyColor][2];
  }

  /*
   * ANSI code interpretation is somewhat limited, we only accept values
   * which have been defined in AnsiCodes.h
   */

  bool doneLastSection = false;
  int startSend = 0;
  int endSend = (int)text.find("\033[", startSend);
  std::string tmpText;
  bool tookCareOfANSICode = false;
  float width = 0;
  // run at least once
  if (endSend == -1) {
    endSend = (int)text.size();
    doneLastSection = true;
  }
  // split string into parts based on the embedded ANSI codes, render each separately
  // there has got to be a faster way to do this
  while (endSend >= 0) {
    // blink the text, if desired
    if (blink)
      getBlinkColor(color, color);
    // render text
    if (endSend - startSend > 0) {
      tmpText = text.substr(startSend, (endSend - startSend));
      // get substr width, we may need it a couple times
      width = getStrLength(faceID, size, tmpText);
      glPushMatrix();
      glTranslatef(x, y, z);
      GLboolean depthMask;
      glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMask);
      glDepthMask(0);
      pFont->drawString(scale, color, tmpText.c_str());
      if (underline) {
	OpenGLGState::resetState();  // FIXME - full reset required?
	if (underlineColor[0] >= 0)
	  glColor3fv(underlineColor);
	// still have a translated matrix, these coordinates are
	// with respect to the string just drawn
	glBegin(GL_LINES);
	glVertex2f(0, -1.0f);
	glVertex2f(width, -1.0f);
	glEnd();
      }
      glDepthMask(depthMask);
      glPopMatrix();
      // x transform for next substr
      x += width;
    }
    if (!doneLastSection) {
      startSend = (int)text.find("m", endSend) + 1;
    }
    // we stopped sending text at an ANSI code, find out what it is and do something about it
    if (endSend != (int)text.size()) {
      tookCareOfANSICode = false;
      tmpText = text.substr(endSend, (text.find("m", endSend) - endSend) + 1);
      // colors
      for (int i = 0; i < 8; i++) {
	if (tmpText == ColorStrings[i]) {
	  if (bright) {
	    color[0] = BrightColors[i][0];
	    color[1] = BrightColors[i][1];
	    color[2] = BrightColors[i][2];
	  } else {
	    color[0] = DimColors[i][0];
	    color[1] = DimColors[i][1];
	    color[2] = DimColors[i][2];
	  }
	  tookCareOfANSICode = true;
	  break;
	}
      }
      // didn't find a matching color
      if (!tookCareOfANSICode) {
	// settings other than color
	if (tmpText == ANSI_STR_RESET) {
	  bright = true;
	  blink = false;
	  underline = false;
	  color[0] = BrightColors[WhiteColor][0];
	  color[1] = BrightColors[WhiteColor][1];
	  color[2] = BrightColors[WhiteColor][2];
	} else if (tmpText == ANSI_STR_RESET_FINAL) {
	  bright = false;
	  blink = false;
	  underline = false;
	  color[0] = DimColors[WhiteColor][0];
	  color[1] = DimColors[WhiteColor][1];
	  color[2] = DimColors[WhiteColor][2];
	} else if (tmpText == ANSI_STR_BRIGHT) {
	  bright = true;
	} else if (tmpText == ANSI_STR_DIM) {
	  bright = false;
	} else if (tmpText == ANSI_STR_UNDERLINE) {
	  underline = !underline;
	} else if (tmpText == ANSI_STR_BLINK) {
	  blink = !blink;
	} else {
	  DEBUG2("ANSI Code %s not supported\n", tmpText.c_str());
	}
      }
    }
    endSend = (int)text.find("\033[", startSend);
    if ((endSend == -1) && !doneLastSection) {
      endSend = (int)text.size();
      doneLastSection = true;
    }
  }
}