class_docstr: Shader program using Function instances as basis for its shaders.
  
  Automatically rebuilds program when functions have changed and uploads
  program variables.
class_docstr_tok: ["Shader","program","using","Function","instances","as","basis","for","its","shaders",".","Automatically","rebuilds","program","when","functions","have","changed","and","uploads","program","variables","."]
code: def update_variables(self):
      # Set any variables that have a new value
      logger.debug("Apply variables:")
      for dep in sorted(
          self._variables, key=lambda d: self.compiler[d]
      ):
          name = self.compiler[dep]
          state_id = dep.state_id
          if self._variable_cache.get(dep, None) != state_id:
              self[name] = dep.value
              self._variable_cache[dep] = state_id
              logger.debug("    %s = %s **", name, dep.value)
          else:
              logger.debug("    %s = %s", name, dep.value)
  
      # Process any pending variables and discard anything else that is
      # not active in the program (otherwise we get lots of warnings).
      self._process_pending_variables()
      logger.debug(
          "Discarding unused variables before draw: %s"
          % self._pending_variables.keys()
      )
      self._pending_variables = {}
  
imports: from __future__ import division
  import logging
  from weakref import WeakKeyDictionary
  from ...gloo import Program
  from ...gloo.preprocessor import preprocess
  from ...util import logger
  from ...util.event import EventEmitter
  from .function import MainFunction
  from .variable import Variable
  from .compiler import Compiler
label_desc: Use image node_id 12 for calling the ModularProgram obj's underlying member method code with example usage: obj.update_variables() without return types