code: #!/usr/bin/env python3
  # -*- coding: utf-8 -*-
  
  """
  **Project Name:**      MakeHuman
  
  **Product Home Page:** http://www.makehumancommunity.org/
  
  **Github Code Home Page:**    https://github.com/makehumancommunity/
  
  **Authors:**           Jonas Hauquier
  
  **Copyright(c):**      MakeHuman Team 2001-2019
  
  **Licensing:**         AGPL3
  
      This file is part of MakeHuman Community (www.makehumancommunity.org).
  
      This program is free software: you can redistribute it and/or modify
      it under the terms of the GNU Affero General Public License as
      published by the Free Software Foundation, either version 3 of the
      License, or (at your option) any later version.
  
      This program is distributed in the hope that it will be useful,
      but WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      GNU Affero General Public License for more details.
  
      You should have received a copy of the GNU Affero General Public License
      along with this program.  If not, see <http://www.gnu.org/licenses/>.
  
  
  Abstract
  --------
  
  Blend skin and color properties based on human ethnic values
  """
  
  import material
  import image
  import image_operations
  import numpy as np
  from getpath import getSysDataPath
  
  
  asianColor     = np.asarray([0.721, 0.568, 0.431], dtype=np.float32)
  africanColor   = np.asarray([0.207, 0.113, 0.066], dtype=np.float32)
  caucasianColor = np.asarray([0.843, 0.639, 0.517], dtype=np.float32)
  
  class EthnicSkinBlender(object):
      """
      Skin blender for the adaptive_skin_tone litsphere texture. Makes sure that
      the texture is set to a blend of the three ethnic skin tones based on the
      human macro settings.
      """
      def __init__(self, human):
          self.human = human
          self.skinCache = { 'caucasian' : image.Image(getSysDataPath('litspheres/skinmat_caucasian.png')),
                             'african'   : image.Image(getSysDataPath('litspheres/skinmat_african.png')),
                             'asian'     : image.Image(getSysDataPath('litspheres/skinmat_asian.png')) }
          self._previousEthnicState = [0, 0, 0]
  
          self._litsphereTexture = None
          self._diffuseColor = material.Color()
  
          self.checkUpdate()
  
      def checkUpdate(self):
          newEthnicState = self.getEthnicState()
          if self._previousEthnicState != newEthnicState:
              self.update()
              self._previousEthnicState = newEthnicState
              return True
          return False
  
      def getEthnicState(self):
          return [ self.human.getCaucasian(),
                   self.human.getAfrican(),
                   self.human.getAsian()     ]
  
      def getLitsphereTexture(self):
          self.checkUpdate()
          return self._litsphereTexture
  
      def getDiffuseColor(self):
          self.checkUpdate()
          return self._diffuseColor
  
      def update(self):
          caucasianWeight = self.human.getCaucasian()
          africanWeight   = self.human.getAfrican()
          asianWeight     = self.human.getAsian()
          blends = []
  
          # Set litsphere texture
          if caucasianWeight > 0:
              blends.append( ('caucasian', caucasianWeight) )
          if africanWeight > 0:
              blends.append( ('african', africanWeight) )
          if asianWeight > 0:
              blends.append( ('asian', asianWeight) )
  
          if len(blends) == 1:
              img = self.skinCache[blends[0][0]]
              img.markModified()
          else:
              img = image_operations.mix(self.skinCache[blends[0][0]], self.skinCache[blends[1][0]], blends[0][1], blends[1][1])
              if len(blends) > 2:
                  img = image_operations.mix(img, self.skinCache[blends[2][0]], 1.0, blends[2][1])
  
          # Set parameter so the image can be referenced when material is written to file (and texture can be cached)
          img.sourcePath = getSysDataPath("litspheres/adaptive_skin_tone.png")
          self._litsphereTexture = img
  
          # Set diffuse color
          diffuse = asianWeight     * asianColor   + \
                    africanWeight   * africanColor + \
                    caucasianWeight * caucasianColor
          self._diffuseColor = material.Color(diffuse)
  
  
apis: numpy.asarray