static void RepLabelRender()

in layer2/RepLabel.cpp [1172:1503]


static void RepLabelRender(RepLabel * I, RenderInfo * info)
{
  CRay *ray = info->ray;
  auto pick = info->pick;
  PyMOLGlobals *G = I->R.G;
  float *v = I->V;
  int c = I->N;
  lexidx_t *l = I->L;
  int font_id = SettingGet_i(G, I->R.cs->Setting, I->R.obj->Setting,
                             cSetting_label_font_id);
  float font_size = SettingGet_f(G, I->R.cs->Setting, I->R.obj->Setting,
                                 cSetting_label_size);
  int float_text = SettingGet_i(G, I->R.cs->Setting, I->R.obj->Setting,
				cSetting_float_labels);
  if (!(ray || pick) && info->pass >= 0)
    return;

  if(I->R.MaxInvalid >= cRepInvRep){
    return;
  }
  font_id = SettingCheckFontID(G, I->R.cs->Setting, I->R.obj->Setting, font_id);

  if (I->shaderCGO && font_size < 0.f){
    int size;
    if (InvalidateShaderCGOIfTextureNeedsUpdate(G, font_size, I->texture_font_size, &size)){
      CGOFree(I->shaderCGO);
      I->texture_font_size = size;
    }
  }
  if(ray) {
    RepLabelRenderRay(I, info);
  } else if(G->HaveGUI && G->ValidContext) {
    if(pick) {
      int pick_labels = SettingGet_b(G, I->R.cs->Setting, I->R.obj->Setting, cSetting_pick_labels);
      if (!pick_labels)
	return;
      if (I->shaderCGO){
        if(float_text)
          glDisable(GL_DEPTH_TEST);
	CGORenderGLPicking(I->shaderCGO, info, &I->R.context, I->R.cs->Setting, I->R.obj->Setting);
        if(float_text)
          glEnable(GL_DEPTH_TEST);
	return;
      } else {
        Pickable *p = I->R.P;
        unsigned int i;
        TextSetIsPicking(G, true);
        SceneSetupGLPicking(G);
        if(c) {
          const char *st;
          int screenwidth, screenheight;
          if(float_text)
            glDisable(GL_DEPTH_TEST);
          
          if (!I->shaderCGO){
            SceneGetWidthHeight(G, &screenwidth, &screenheight);
          }
          i = pick->begin()->src.index;

          while(c--) {
            if(*l) {
              float xn[3], yn[3], tCenterPt[3], offpt[3];
              short relativeMode = ((short)*(v + 15));
              copy3f(v + 6, tCenterPt);
              SceneGetCenter(G, offpt);
              TextSetPosNColor(G, offpt, v);
              SceneGetScaledAxes(G, I->R.obj, xn, yn);
              if (!I->shaderCGO){
                if (relativeMode & 2){ // label_relative_mode = 1
                  float tmp3f[3];
                  mult3f(xn, tCenterPt[0] * screenwidth/2.f, tmp3f);
                  add3f(tmp3f, offpt, offpt);
                  mult3f(yn, tCenterPt[1] * screenheight/2.f, tmp3f);
                  add3f(tmp3f, offpt, offpt);
                  copy3f(offpt, tCenterPt);
                } else if (relativeMode & 4){ // label_relative_mode = 2
                  float tmp3f[3];
                  mult3f(xn, (tCenterPt[0]  - (.5f * screenwidth)), tmp3f);
                  add3f(tmp3f, offpt, offpt);
                  mult3f(yn, (tCenterPt[1]  - (.5f * screenheight)), tmp3f);
                  add3f(tmp3f, offpt, offpt);
                  copy3f(offpt, tCenterPt);
                }
              }
              i++;
              TextSetPosNColor(G, tCenterPt, v);
              TextSetTargetPos(G, v + 3);
              TextSetLabelBkgrdInfo(G, *(v + 16), *(v + 17), (v + 18));

              if (p) {
                p++;
                AssignNewPickColor(NULL, i, pick, &I->R.context, TextGetColorUChar4uv(G), p->index, p->bond);
              }

              TextSetColorFromUColor(G);

              st = LexStr(G, *l);
              if (!TextRenderOpenGL(G, info, font_id, st, font_size, v + 12, false, (short)*(v + 15), 1, SHADERCGO)){
                TextSetIsPicking(G, false);
                return ;
              }
            }
            l++;
            v += 28;
          }
          if(float_text)
            glEnable(GL_DEPTH_TEST);
          (*pick)[0].src.index = i;       /* pass the count */
        }
        TextSetIsPicking(G, false);
      }
    } else {  // not pick or ray, render
      if(c) {
        const char *st;
	short use_shader, has_connector = 0;
	CGO *connectorCGO = NULL;
	float *PmvMatrix = NULL;
	int screenwidth, screenheight;
	float xn[3] = { 1.0F, 0.0F, 0.0F };
	float yn[3] = { 0.0F, 1.0F, 0.0F };
	int pre_use_shaders = info->use_shaders;
	
	Pickable *p = I->R.P;
	use_shader = SettingGetGlobal_b(G, cSetting_use_shaders)
#ifdef _PYMOL_IOS
          ;
#else
	  && G->ShaderMgr->GeometryShadersPresent();
#endif
	info->use_shaders = use_shader;
	if (use_shader){
	  if (!I->shaderCGO){
	    I->shaderCGO = CGONew(G);
            I->shaderCGO->use_shader = true;
	  } else {
	    info->texture_font_size = I->texture_font_size;
	    if(float_text)
	      glDisable(GL_DEPTH_TEST);
	    CGORenderGL(I->shaderCGO, NULL, NULL, NULL, info, &I->R);
	    if(float_text)
	      glEnable(GL_DEPTH_TEST);
	    return;
	  }
	} else {
          CGOFree(I->shaderCGO);

#ifndef PURE_OPENGL_ES_2
	  if(!info->line_lighting)
	    glDisable(GL_LIGHTING);
#endif
	}
        TextSetOutlineColor(G, I->OutlineColor);
	if (I->shaderCGO && c){
	  connectorCGO = CGONew(G);
	  CGOBegin(connectorCGO, GL_LINES);
	}
	if (!I->shaderCGO){
	  PmvMatrix = SceneGetPmvMatrix(G);
	  SceneGetWidthHeight(G, &screenwidth, &screenheight);
	  MatrixInvTransformC44fAs33f3f(PmvMatrix, xn, xn);
	  MatrixInvTransformC44fAs33f3f(PmvMatrix, yn, yn);
	  normalize3f(xn);
	  normalize3f(yn);
	}
        while(c--) {
          if(*l) {
	    float tCenterPt[3], offpt[3];
	    short relativeMode = ((short)*(v + 15));
	    int draw_var = 127 & (int)*(v + 21);
	    copy3f(v + 6, tCenterPt);
	    SceneGetCenter(G, offpt);
	    TextSetPosNColor(G, offpt, v);
	    SceneGetScaledAxes(G, I->R.obj, xn, yn);
	    if (!I->shaderCGO){
	      if (relativeMode & 2){ // label_relative_mode = 1
		  float tmp3f[3];
		  mult3f(xn, tCenterPt[0] * screenwidth/2.f, tmp3f);
		  add3f(tmp3f, offpt, offpt);
		  mult3f(yn, tCenterPt[1] * screenheight/2.f, tmp3f);
		  add3f(tmp3f, offpt, offpt);
		  copy3f(offpt, tCenterPt);
	      } else if (relativeMode & 4){ // label_relative_mode = 2
		  float tmp3f[3];
		  mult3f(xn, (tCenterPt[0] - .5f * screenwidth), tmp3f);
		  add3f(tmp3f, offpt, offpt);
		  mult3f(yn, (tCenterPt[1] - .5f * screenheight), tmp3f);
		  add3f(tmp3f, offpt, offpt);
		  copy3f(offpt, tCenterPt);
	      }
	    }

            if (p) {
              p++;
              if (I->shaderCGO)
                CGOPickColor(I->shaderCGO, p->index, p->bond);
            }

            TextSetPosNColor(G, tCenterPt, v);
	    TextSetTargetPos(G, v + 3);
            st = LexStr(G, *l);
	    TextSetLabelBkgrdInfo(G, *(v + 16), *(v + 17), (v + 18));
	    if (relativeMode & 8){  // label_z_target, adjust z to target
	      TextGetLabelPos(G)[0] = (SceneGetDepth(G, v+3) - .5) * 2.f;
	      TextSetLabelPosIsSet(G, 1);
	    } else if (relativeMode & 6){ // label_relative_mode 1 or 2, i.e., screen stabilized, adjust z 
	      TextSetLabelPos(G, v+6);
	      TextSetLabelPosIsSet(G, 2);
#ifndef PURE_OPENGL_ES_2
	      glDisable(GL_FOG);
#endif
	    } else {
	      TextSetLabelPosIsSet(G, 0);
	    }
#ifndef PURE_OPENGL_ES_2
	    if (!use_shader)
	      glPushMatrix();
#endif
            if (!TextRenderOpenGL(G, info, font_id, st, font_size, v + 12, (draw_var ? 1 : 0), (short)*(v + 15), use_shader, SHADERCGO)){
	      CGOFree(connectorCGO);
	      return;
	    }
	    if (draw_var){
	
	      float *RotMatrix = NULL;
	      float *screenWorldOffset = TextGetScreenWorldOffset(G);
	      float text_width = TextGetWidth(G), text_height = TextGetHeight(G);
	      float *indentFactor = TextGetIndentFactor(G);
	      RotMatrix = SceneGetMatrix(G);

	      if (I->shaderCGO){
		CGODrawConnector(connectorCGO, v + 3, v + 6, text_width, text_height, indentFactor, screenWorldOffset, v + 9, ((short)*(v + 15)), draw_var, *(v + 22), (v + 23), *(v + 27) * font_size / text_height, *(v + 26)) ;
		has_connector = 1;
	      } else {
#ifndef PURE_OPENGL_ES_2
		RepLabelRenderBackgroundInImmediate(G, I, v, draw_var, tCenterPt, relativeMode, xn, yn, PmvMatrix, RotMatrix, screenwidth, screenheight, screenWorldOffset, indentFactor, text_width, text_height, font_size);
#endif
	      }
	    }
#ifdef PURE_OPENGL_ES_2
	    if (float_text && draw_var){
	      TextRenderOpenGL(G, info, font_id, st, font_size, v + 12, 1, (short)*(v + 15), 1, SHADERCGO);
	    }
#else
	    if (!use_shader){
	      glPopMatrix();
	      {
		// for now, render text twice in immediate mode, some cards don't handle
		// z-buffer offset properly, before, only did this when float_text && draw_var
		glPushMatrix();
		TextRenderOpenGL(G, info, font_id, st, font_size, v + 12, 1, (short)*(v + 15), 1, SHADERCGO);
		glPopMatrix();
	      }
	    }
#endif
	    if (relativeMode & 6){ // label_relative_mode 1 or 2, i.e., screen stabilized, adjust z 
#ifndef PURE_OPENGL_ES_2
	      glEnable(GL_FOG);
#endif
	    }
          }
          l++;
          v += 28;
        }
	if (!has_connector){
	  CGOFree(connectorCGO);
	}
	if (connectorCGO){
	  CGOEnd(connectorCGO);
	  CGOStop(connectorCGO);
	}

        if (I->shaderCGO){
	  CGO *totalCGO = NULL;
	  CGO *labelCGO = NULL;
	  CGOStop(I->shaderCGO);
          CGO * tmpCGO = CGONew(G);
          CGOEnable(tmpCGO, GL_LABEL_SHADER);
          CGOSpecial(tmpCGO, SET_LABEL_SCALE_UNIFORMS);
          labelCGO = CGOConvertToLabelShader(I->shaderCGO, tmpCGO);
          CGOAppendNoStop(tmpCGO, labelCGO);
          CGOFreeWithoutVBOs(labelCGO);
          labelCGO = tmpCGO;
	  if (!labelCGO) return;
	  CGOFree(I->shaderCGO);
	  if (connectorCGO){
	    CGO *tmpCGO = NULL;
	    tmpCGO = CGOOptimizeConnectors(connectorCGO, 0);
	    CGOFree(connectorCGO);
	    connectorCGO = tmpCGO;

	    // need to render connector/backgrounds first
	    totalCGO = CGONew(G);
	    CGOEnable(totalCGO, GL_LABEL_FLOAT_TEXT);
	    CGOEnable(totalCGO, GL_CONNECTOR_SHADER);
#ifndef PURE_OPENGL_ES_2
	    CGODisable(totalCGO, GL_LIGHTING);
#endif
	    CGOAppendNoStop(totalCGO, connectorCGO);
	    CGOFreeWithoutVBOs(connectorCGO);
	    CGODisable(totalCGO, GL_CONNECTOR_SHADER);
	    CGOAppendNoStop(totalCGO, labelCGO); 
	    CGOFreeWithoutVBOs(labelCGO);
	    CGODisable(totalCGO, GL_LABEL_FLOAT_TEXT);
	    CGOStop(totalCGO);
	  } else {
	    totalCGO = CGONew(G);
	    CGOEnable(totalCGO, GL_LABEL_FLOAT_TEXT);
	    CGOAppendNoStop(totalCGO, labelCGO);
	    CGODisable(totalCGO, GL_LABEL_FLOAT_TEXT);
            CGODisable(totalCGO, GL_LABEL_SHADER);
	    CGOStop(totalCGO);
	    CGOFreeWithoutVBOs(labelCGO);
	  }
	  I->shaderCGO = totalCGO;
	  if (I->shaderCGO){
	    I->shaderCGO->use_shader = true;
	    RepLabelRender(I, info);
	    return;
	  }
        } else {
#ifndef PURE_OPENGL_ES_2
	  glEnable(GL_LIGHTING);
#endif
	  glEnable(GL_BLEND);
	}
        if(float_text)
          glEnable(GL_DEPTH_TEST);
	info->use_shaders = pre_use_shaders;
      }
    }
  }
}