python类shadingNode()的实例源码

orientjoints.py 文件源码 项目:cmt 作者: chadmv 项目源码 文件源码 阅读 31 收藏 0 点赞 0 评论 0
def create_shaders():
    """
    Creates the red/green/blue shaders.
    @return: (Red, green, blue material nodes)
    """
    red = cmds.shadingNode('lambert', asShader=True)
    cmds.setAttr('{0}.color'.format(red), 1, 0, 0, type='double3')
    cmds.setAttr('{0}.ambientColor'.format(red), 1, 0, 0, type='double3')
    green = cmds.shadingNode('lambert', asShader=True)
    cmds.setAttr('{0}.color'.format(green), 0, 1, 0, type='double3')
    cmds.setAttr('{0}.ambientColor'.format(green), 0, 1, 0, type='double3')
    blue = cmds.shadingNode('lambert', asShader=True)
    cmds.setAttr('{0}.color'.format(blue), 0, 0, 1, type='double3')
    cmds.setAttr('{0}.ambientColor'.format(blue), 0, 0, 1, type='double3')

    t = 0.9
    for node in [red, green, blue]:
        cmds.setAttr('{0}.transparency'.format(node), t, t, t, type='double3')

    return red, green, blue
test_textureSampler.py 文件源码 项目:mayakit 作者: danbradham 项目源码 文件源码 阅读 26 收藏 0 点赞 0 评论 0
def test_texture_sampler():
    '''Test the texture_sampler function'''

    # Compile and reload plugin modules
    from .. import plugins
    plugins._import_plugins()

    # Get texture_sampler
    from ..plugins.textureSampler import texture_sampler
    from maya import cmds

    cmds.file(new=True, force=True)
    plugins.safe_reload('textureSampler')
    ramp = cmds.shadingNode('ramp', asTexture=True)
    spotlight = cmds.shadingNode('spotLight', asLight=True)

    sampler = texture_sampler(ramp, [(0.5, 0.0), (0.5, 0.5), (0.5, 1.0)])
    sampler.connect('color', [spotlight])
textureSampler.py 文件源码 项目:mayakit 作者: danbradham 项目源码 文件源码 阅读 29 收藏 0 点赞 0 评论 0
def texture_sampler(texture, uvs_list=None):
    '''
    Create a textureSampler node

    :param texture_node: Path to texture node like "ramp1"
    :param uvs_list: List of uvs like [(0.0, 0.5), (0.5, 1.0)]
    '''

    texture_attr = texture + '.outColor'
    if not cmds.objExists(texture_attr):
        raise Exception('texture must have an outColor attribute')

    texture_node = cmds.shadingNode('textureSampler', asUtility=True)
    sampler = TextureSampler(texture_node)
    sampler.inColor = texture_attr
    uvs_list = uvs_list or [(0.5, 0.5)]
    sampler.set_uvs(uvs_list)

    return sampler
zbw_rig.py 文件源码 项目:zTools 作者: zethwillie 项目源码 文件源码 阅读 25 收藏 0 点赞 0 评论 0
def positionsAlongCurve(crv="", numPts = 3, *args):
    """
    returns list of numPts evenly distributed world positions along given nurbs crv
    """
    if not crv:
        return

    if isType(crv, "nurbsCurve"):
        posList = []
        shp = cmds.listRelatives(crv, s=True)[0]
        poc = cmds.shadingNode("pointOnCurveInfo", asUtility=True, name="tmpPOCInfo")
        cmds.connectAttr("{}.local".format(shp), "{}.inputCurve".format(poc))
        cmds.setAttr("{}.turnOnPercentage".format(poc), 1)
        lineLen = cmds.arclen(crv, ch=False)
        dist = float(numPts)/lineLen

        for x in range(0, numPts+1):
            perc = 1.0/numPts
            cmds.setAttr("{}.parameter".format(poc),x*perc)
            print x*perc
            pos = cmds.getAttr("{}.position".format(poc))[0]
            posList.append(pos)

        cmds.delete(poc)
        return(posList)
__init__.py 文件源码 项目:sfx 作者: theodox 项目源码 文件源码 阅读 28 收藏 0 点赞 0 评论 0
def create(cls, name):
        """
        Create a new shader and return the ShaderNetwork that wraps it.
        """
        sfx_shader = cmds.shadingNode('ShaderfxShader', asShader=True, name=name)
        cmds.shaderfx(sfxnode=sfx_shader, initShaderAttributes=True)
        network = cls(sfx_shader)
        return network
__init__.py 文件源码 项目:sfx 作者: theodox 项目源码 文件源码 阅读 27 收藏 0 点赞 0 评论 0
def create(cls, name):
        sfx_shader = cmds.shadingNode('StingrayPBS', asShader=True, name=name)
        cmds.shaderfx(sfxnode=sfx_shader, initShaderAttributes=True)
        network = cls(sfx_shader)
        return network
zbw_rig.py 文件源码 项目:zTools 作者: zethwillie 项目源码 文件源码 阅读 31 收藏 0 点赞 0 评论 0
def createAdd(name, input1, input2):
    """creates an addDoubleLinear node with name, object.attr, object.attr as args"""
    adl = cmds.shadingNode("addDoubleLinear", asUtility=True, name=name)
    cmds.connectAttr(input1, "%s.input1"%adl)
    cmds.connectAttr(input2, "%s.input2"%adl)
    return(adl)
zbw_rig.py 文件源码 项目:zTools 作者: zethwillie 项目源码 文件源码 阅读 29 收藏 0 点赞 0 评论 0
def blendRotation(blend="none", sourceA="none", sourceB="none", target="none", sourceValue="none"):
    #add input and *args?
    """name is first arg, then three objects. Blends rotation from first two selected into third selected. SourceValue (last input) is for the driving obj.attr. First source is active at '1', second at '2'"""
    if blend == "none":
        blend = "blendColors"
    if sourceA == "none":
        sel = getSelection()
        if len(sel) != 3:
            cmds.error("Error: blendRotation, select three transforms")
            #inert some kind of break here
        sourceA = sel[0]
        sourceB = sel[1]
        target = sel[2]
    blend = cmds.shadingNode("blendColors", asUtility=True, name=blend)
    sourceAOut = sourceA + ".rotate"
    sourceBOut = sourceB + ".rotate"
    targetIn = target + ".rotate"
    blend1 = blend + ".color1"
    blend2 = blend + ".color2"
    blendOut = blend + ".output"
    cmds.connectAttr(sourceAOut, blend1)
    cmds.connectAttr(sourceBOut, blend2)
    cmds.connectAttr(blendOut, targetIn)
    if not sourceValue == "none":
        cmds.connectAttr(sourceValue, "%s.blender"%blend)

    return(blend)
zbw_rig.py 文件源码 项目:zTools 作者: zethwillie 项目源码 文件源码 阅读 32 收藏 0 点赞 0 评论 0
def blendTranslate(blend="none", sourceA="none", sourceB="none", target="none", sourceValue="none"):
    """name is first arg, then three objects. Blends translation from first two selected into third selected. SourceValue (last input) is for the driving obj.attr. First source is active at '1', second at '2'"""
    #add input and *args
    if blend == "none":
        blend = "blendColors"
    if sourceA == "none":
        sel = getSelection()
        if len(sel) != 3:
            cmds.error("Error: blendRotation, select three transforms")
            #inert some kind of break here
        sourceA = sel[0]
        sourceB = sel[1]
        target = sel[2]
    blend = cmds.shadingNode("blendColors", asUtility=True, name=blend)
    sourceAOut = sourceA + ".translate"
    sourceBOut = sourceB + ".translate"
    targetIn = target + ".translate"
    blend1 = blend + ".color1"
    blend2 = blend + ".color2"
    blendOut = blend + ".output"
    cmds.connectAttr(sourceAOut, blend1)
    cmds.connectAttr(sourceBOut, blend2)
    cmds.connectAttr(blendOut, targetIn)
    if not sourceValue == "none":
        cmds.connectAttr(sourceValue, "%s.blender"%blend)

    return(blend)
zbw_rig.py 文件源码 项目:zTools 作者: zethwillie 项目源码 文件源码 阅读 29 收藏 0 点赞 0 评论 0
def measureDistance(mName="none", *args):
    """first the name of the measure node, then the 2 objects ORRRR select the two objects and run (will give name 'distanceBetween'"""
    objs = []
    if mName == "none":
        mName = "distanceBetween"
        objs = getTwoSelection()
    else:
        for each in args:
            objs.append(each)
    #add check for 2 selectiont
    if len(objs) != 2:
        cmds.error("you must enter either a measure name and 2 objects OR no arguments and manually select 2 objs")
    dist = cmds.shadingNode("distanceBetween", asUtility=True, name=mName)
    objA = objs[0]
    objB = objs[1]
    objAMatrix = objA + ".worldMatrix"
    objBMatrix = objB + ".worldMatrix"
    objAPoint = objA + ".rotatePivot"
    objBPoint = objB + ".rotatePivot"
    distPoint1 = dist + ".point1"
    distPoint2 = dist + ".point2"
    distMatrix1 = dist + ".inMatrix1"
    distMatrix2 = dist + ".inMatrix2"
    cmds.connectAttr(objAPoint, distPoint1)
    cmds.connectAttr(objBPoint, distPoint2)
    cmds.connectAttr(objAMatrix, distMatrix1)
    cmds.connectAttr(objBMatrix, distMatrix2)
    cmds.select(clear=True)
    return(dist)
zbw_rig.py 文件源码 项目:zTools 作者: zethwillie 项目源码 文件源码 阅读 30 收藏 0 点赞 0 评论 0
def scaleStretchIK(limbName="none", ikTop="none", ikMid="none", ikLow="none", jntMeasure="none", IKMeasure="none", IKCtrl="none", axis="none", *args):
    """creates a stretch setup for 3 joint IK chain. Inputs (strings) are the limbName, 3 ik joints (top to bottom), the measure input for the whole chain (add up from measure joints), the measure for the ikCtrl, the ik handle or ctrl (which must have 'scaleMin', 'upScale' and 'lowScale' attrs, the axis letter. Returns . . . """

    ratioMult = cmds.shadingNode("multiplyDivide", asUtility=True, n="%s_stretchRatioMult"%limbName)
    cmds.setAttr(ratioMult + ".operation", 2)
    cmds.connectAttr(jntMeasure, "%s.input2X"%ratioMult)
    cmds.connectAttr(IKMeasure, "%s.input1X"%ratioMult)

    #could put this default stuff (next two paragraphs) after the conditional and use another conditional so that minScale is bundled up in "autostretch"
    #create default setting of 1 when autostretch is off
    defaultMult = cmds.shadingNode("multiplyDivide", asUtility=True, n="%s_stretchDefaultMult"%limbName)
    cmds.setAttr("%s.input1X"%defaultMult, 1)

    #create blend node to blend ratio mult and default values, based on blender attr of ikctrl.autoStretch
    defaultBlend = cmds.shadingNode("blendColors", asUtility=True, n="%s_stretchBlend"%limbName)
    cmds.connectAttr("%s.outputX"%defaultMult, "%s.color2R"%defaultBlend)
    cmds.connectAttr("%s.outputX"%ratioMult, "%s.color1R"%defaultBlend)
    cmds.connectAttr("%s.autoStretch"%IKCtrl, "%s.blender"%defaultBlend)

    #blend goes into condition node - firstTerm, secondTerm=ikctrl scaleMin value, operation=2(greaterthan), colorIfTrue is blend, colorIfFalse is scaleMin attr
    conditional = cmds.shadingNode("condition", asUtility=True, n="%s_upStretchCondition"%limbName)
    cmds.setAttr("%s.operation"%conditional, 2)
    cmds.connectAttr("%s.outputR"%defaultBlend, "%s.firstTerm"%conditional)
    cmds.connectAttr("%s.scaleMin"%IKCtrl, "%s.secondTerm"%conditional)
    cmds.connectAttr("%s.outputR"%defaultBlend, "%s.colorIfTrueR"%conditional)
    cmds.connectAttr("%s.scaleMin"%IKCtrl, "%s.colorIfFalseR"%conditional)

    #factor in the upScale/lowScale attrs
    upScaleMult = cmds.shadingNode('multiplyDivide', asUtility=True, n="%s_upScaleMult"%limbName)
    cmds.connectAttr("%s.outColorR"%conditional, "%s.input1X"%upScaleMult)
    cmds.connectAttr("%s.upScale"%IKCtrl, "%s.input2X"%upScaleMult)
    loScaleMult = cmds.shadingNode('multiplyDivide', asUtility=True, n="%s_loScaleMult"%limbName)
    cmds.connectAttr("%s.outColorR"%conditional, "%s.input1X"%loScaleMult)
    cmds.connectAttr("%s.lowScale"%IKCtrl, "%s.input2X"%loScaleMult)

    #hook up the scales of the joints
    cmds.connectAttr("%s.outputX"%upScaleMult, "%s.s%s"%(ikTop, axis))
    cmds.connectAttr("%s.outputX"%loScaleMult, "%s.s%s"%(ikMid, axis))

    return(ratioMult, defaultMult, defaultBlend, conditional, upScaleMult, loScaleMult)
Script_Maya.py 文件源码 项目:3D_Software_and_Python 作者: p4vv37 项目源码 文件源码 阅读 22 收藏 0 点赞 0 评论 0
def change_hierarchy_and_animate():
    """
    Function modifies the hierarchy of scene and creates some final animations, that ware not possible to create earlier.
    It also creates cameras and lights.
    """
    cmds.lookThru( 'perspView', 'RenderCamera1') # Change the perspective viewport to the render camera.

    top_locator = cmds.spaceLocator() # Parent for all the elemements that will rotate together
    objects_list = ['land', 'water', 'cloud', 'shark', ]

    for obj in objects_list:
        cmds.parent(obj, top_locator)

    cmds.setKeyframe(top_locator, attribute='rotateY', v=20, time=260, itt="plateau", ott="plateau")
    cmds.setKeyframe(top_locator, attribute='rotateY', v=0, time=0, itt="linear", ott="linear")

    dome_light = cmds.polySphere(r=500) # This sphere is a substitute of a skylight in 3Ds Max
    cmds.polyNormal(dome_light, normalMode=0) # The normals have to point to inside

    cmds.setAttr(dome_light[0]+".miDeriveFromMaya", 0) # Enable changes in object render settings
    cmds.setAttr(dome_light[0]+".miVisible", 0) # This object will be invisible to camera
    cmds.setAttr(dome_light[0]+".miShadow", 0) # And will not affect shadows
    cmds.rename(dome_light[0], "dome_light")

    area_light = cmds.shadingNode('areaLight', asLight=True)
    cmds.scale(25, 25, 25, area_light, absolute=True)
    cmds.move(-230.59, 178.425, 99.192, area_light)
    cmds.rotate(0, -68.929, -37.987, area_light)

    cmds.setAttr(area_light+".intensity", 120000.0)
    cmds.setAttr(area_light+".areaLight", 1)
    cmds.setAttr(area_light+".areaType", 1)
    cmds.setAttr(area_light+".decayRate", 2)
    cmds.setAttr(area_light+".areaHiSamples", 64)
zbw_curveCVControls.py 文件源码 项目:zTools 作者: zethwillie 项目源码 文件源码 阅读 29 收藏 0 点赞 0 评论 0
def curve_CV_controls_execute(crv, *args):
    """
    takes given curve and makes a ctrl for each cv. Then connects the matrix of the control directly to the point
    position of the cv. Basically hijacking the shape node, more or less. If there's a parent to the curve,
    will put whole rig under that and turn off inherit transforms for the crv itself.
    puts an attr called 'controlScale' on the group controls are under to scale size of controls
    Args:
        crv: string - name of given curve
        *args:

    Returns:
        Void
    """

    par = cmds.listRelatives(crv, p=True)

    ctrlGrps = []
    cvs = cmds.ls("{0}.cv[*]".format(crv), fl=True)
    xformGrp = cmds.group(empty=True, name="{0}_ctrl_GRP".format(crv))
    cmds.addAttr(xformGrp, ln="controlScale", at="float", min=0.01, max=100, dv=1.0, k=True)
    for x in range(0, len(cvs)):
        pos = cmds.pointPosition(cvs[x])
        shp = cmds.listRelatives(crv, s=True)[0]
        ctrl = rig.createControl(type="sphere", name="{0}_{1}_CTRL".format(crv, x), color="red")
        grp = rig.groupFreeze(ctrl)
        cmds.connectAttr("{0}.controlScale".format(xformGrp), "{0}.sx".format(ctrl))
        cmds.connectAttr("{0}.controlScale".format(xformGrp), "{0}.sy".format(ctrl))
        cmds.connectAttr("{0}.controlScale".format(xformGrp), "{0}.sz".format(ctrl))
        cmds.setAttr("{0}.scale".format(ctrl), l=True, k=False)
        cmds.xform(grp, ws=True, t=pos)

        dm = cmds.shadingNode("decomposeMatrix", asUtility=True,name="{0}_{1}_DM".format(crv, x))
        cmds.connectAttr("{0}.worldMatrix[0]".format(ctrl), "{0}.inputMatrix".format(dm))
        cmds.connectAttr("{0}.outputTranslate".format(dm), "{0}.controlPoints[{1}]".format(shp, x))
        ctrlGrps.append(grp)

    cmds.xform(xformGrp, ws=True, t=(cmds.xform(crv, ws=True, q=True, rp=True)))
    cmds.xform(xformGrp, ws=True, ro=(cmds.xform(crv, ws=True, q=True, ro=True)))
    cmds.xform(xformGrp, s=(cmds.xform(crv, q=True, r=True, s=True)))

    if par:
        inhGrp = cmds.group(empty=True, name="noInherit_{0}_GRP".format(crv))
        cmds.parent(xformGrp, par[0])
        cmds.parent(inhGrp, par[0])
        cmds.parent(crv, inhGrp)
        cmds.setAttr("{0}.inheritsTransform".format(inhGrp), 0)

    cmds.parent(ctrlGrps, xformGrp)
    cmds.xform(crv, ws=True, t=(0,0,0))
    cmds.xform(crv, ws=True, ro=(0,0,0))
    cmds.xform(crv, a=True, s=(1,1,1))
zbw_rig.py 文件源码 项目:zTools 作者: zethwillie 项目源码 文件源码 阅读 34 收藏 0 点赞 0 评论 0
def blendScale(blend="none", sourceA="none", sourceB="none", target="none", sourceValue="none"):
    """name is first arg, then three objects. Blends translation from first two selected into third selected. SourceValue (last input) is for the driving obj.attr. First source is active at '1', second at '2'"""
    #add input and *args
    if blend == "none":
        blend = "blendColors"
    if sourceA == "none":
        sel = getSelection()
        if len(sel) != 3:
            cmds.error("Error: blendRotation, select three transforms")
            #inert some kind of break here
        sourceA = sel[0]
        sourceB = sel[1]
        target = sel[2]
    blend = cmds.shadingNode("blendColors", asUtility=True, name=blend)
    sourceAOut = sourceA + ".scale"
    sourceBOut = sourceB + ".scale"
    targetIn = target + ".scale"
    blend1 = blend + ".color1"
    blend2 = blend + ".color2"
    blendOut = blend + ".output"
    cmds.connectAttr(sourceAOut, blend1)
    cmds.connectAttr(sourceBOut, blend2)
    cmds.connectAttr(blendOut, targetIn)
    if not sourceValue == "none":
        cmds.connectAttr(sourceValue, "%s.blender"%blend)

    return(blend)


# def colorControl(color="none", *args):
#   """enter a color (red, blue, green, yellow, dkRed, dkBlue, dkGreen, dkYellow, pink, ltBlue, ltGreen, ltYellow, black, purple), then objs or selection"""
#   if color == "none":
#       cmds.error("must choose a color to use 'colorControl'")
#   #create dictionary
#   colors = {"red":13}
#   if args == ():
#       args = getSelection()
#   for obj in args:
#       #get shape node
#       #check to make sure there is a shape node
#       #set coloroverride to 1
#       #set color to color value of dict
#       pass


# def standInGeo():
# ##  check that there is a next joint
# ##  measure distance to next joint?
# ##    create geo that is scaled to that measurement
# ##    snap the geo to the joint
#   pass
zbw_rig.py 文件源码 项目:zTools 作者: zethwillie 项目源码 文件源码 阅读 26 收藏 0 点赞 0 评论 0
def closest_pt_on_mesh_position(point, mesh, *args):
    """rtrns position of closest pt
        #--------------------
        #inputs and outputs for "closestPointOnMesh":

        #inputs:
        #"mesh"->"inputMesh" (mesh node of transform)
        #"clusPos"->"inPosition"
        #"worldMatrix"(transform of point)->"inputMatrix"

        #outputs:
        #"position"->surfacepoint in space
        #"u"->parameter u
        #"v"->parameter v
        #"normal"->normal vector
        #"closestFaceIndex"->index of closest face
        #"closestVertexIndex"->index of closet vertex
        #---------------------
    """
    if isinstance(point, basestring):
        if isType(point, "transform"):
            # cmds.select(point, r=True)
            ptPos = cmds.xform(point, ws=True, q=True, rp=True)
            name = point
        else:
            cmds.warning("zbw_rig.closest_pt_on_mesh_position: the string you gave me isn't a transform")
            return()
    elif isinstance(point, (list, tuple)):
        if len(point)==3:
            ptPos = point
            name = mesh
        else:
            cmds.warning("zbw_rig.closest_pt_on_mesh_position: there are not the right number of indices in the "
                         "iterable you gave me. Need 3, you gave {0}".format(len(point)))
    else:
        cmds.warning("zbw_rig.closest_pt_on_mesh_position: You didn't give me a name of transform or position(array["
                     "3])")
        return()

    cpomNode = cmds.shadingNode("closestPointOnMesh", asUtility=True, n="{0}_CPOM".format(name))
    cmds.connectAttr("{0}.outMesh".format(mesh), "{0}.inMesh".format(cpomNode))
    cmds.setAttr("{0}.inPosition".format(cpomNode), ptPos[0], ptPos[1], ptPos[2])
    cmds.connectAttr("{0}.worldMatrix".format(mesh), "{0}.inputMatrix".format(cpomNode))

    cpomPos = cmds.getAttr("{0}.position".format(cpomNode))[0]
    cmds.delete(cpomNode)

    return (cpomPos)
zbw_rig.py 文件源码 项目:zTools 作者: zethwillie 项目源码 文件源码 阅读 24 收藏 0 点赞 0 评论 0
def align_to_curve(crv=None, obj=None, param=None, *args):
    """
    places the obj on the curve aligned to . . .
    Args:
        obj (string): object to align
        crv: (string): curve TRANSFORM to align to
        param (float): parameter along curve to position and orient to
        *args:

    Returns:
        void

    """
#TODO - check on non-orig geo, check the matrix plugin is loaded
    if not obj and crv and param:
        cmds.warning("zbw_rig.align_to_curve: Didnt' get all the correct params! (obj, crv, param)")
        return()

    if not isType(crv, "nurbsCurve"):
        cmds.warning("zbw_rig.align_to_curve: crv param wasn't a curve!")
        return()

    crvShp = cmds.listRelatives(crv, s=True)[0]
    tempObj = cmds.group(empty=True, name="tempCrvNull")

    poci = cmds.shadingNode("pointOnCurveInfo", asUtility=True, name="tempPOCI")
    cmds.connectAttr("{0}.worldSpace[0]".format(crvShp), "{0}.inputCurve".format(poci))
    cmds.setAttr("{0}.parameter".format(poci), param)
    cmds.connectAttr("{0}.position".format(poci), "{0}.translate".format(tempObj))
    sideVal = cmds.getAttr("{0}.normalizedNormal".format(poci))[0]
    side = om.MVector(sideVal[0], sideVal[1], sideVal[2])
    frontVal = cmds.getAttr("{0}.normalizedTangent".format(poci))[0]
    front = om.MVector(frontVal[0], frontVal[1], frontVal[2])

    up = side ^ front

    mat4 = cmds.shadingNode("fourByFourMatrix", asUtility=True, name="temp4x4")
    decomp = cmds.shadingNode("decomposeMatrix", asUtility=True, name="tempDM")
    yrow = [side[0], side[1], side[2], 0]
    xrow = [front[0], front[1], front[2], 0]
    zrow = [up[0], up[1], up[2], 0]

    for col in range(3):
        cmds.setAttr("{0}.in0{1}".format(mat4, col), xrow[col])
        cmds.setAttr("{0}.in1{1}".format(mat4, col), yrow[col])
        cmds.setAttr("{0}.in2{1}".format(mat4, col), zrow[col])
    cmds.setAttr("{0}.in33".format(mat4), 1)

    cmds.connectAttr("{0}.output".format(mat4), "{0}.inputMatrix".format(decomp))
    cmds.connectAttr("{0}.outputRotate".format(decomp), "{0}.rotate".format(tempObj))
    snapTo(tempObj, obj)

    cmds.delete(tempObj, poci, decomp, mat4)


问题


面经


文章

微信
公众号

扫码关注公众号