当前位置: 首页>>代码示例>>C#>>正文


C# SerializedProperty.Next方法代码示例

本文整理汇总了C#中UnityEditor.SerializedProperty.Next方法的典型用法代码示例。如果您正苦于以下问题:C# SerializedProperty.Next方法的具体用法?C# SerializedProperty.Next怎么用?C# SerializedProperty.Next使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在UnityEditor.SerializedProperty的用法示例。


在下文中一共展示了SerializedProperty.Next方法的14个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。

示例1: OnGUI

        public override void OnGUI(Rect position, SerializedProperty prop, GUIContent label)
        {
            Rect textFieldPosition = position;
            textFieldPosition.height = 16;
            textFieldPosition.width -= 64;

            // Get the path field
            prop.Next(true);

            EditorGUI.LabelField(textFieldPosition, label);

            Rect buttonPosition = position;
            buttonPosition.height = 16;
            buttonPosition.x += buttonPosition.width - 128;
            buttonPosition.width = 128;

            List<string> mapNames = new List<string>();

            for(int i = 0; i < EditorBuildSettings.scenes.Length; i++)
            {
                string name = Path.GetFileNameWithoutExtension(EditorBuildSettings.scenes[i].path);

                mapNames.Add(name);
            }

            prop.intValue = EditorGUI.Popup(buttonPosition, prop.intValue, mapNames.ToArray());

            prop.serializedObject.ApplyModifiedProperties();
        }
开发者ID:Putaitu,项目名称:unity-boilerplate,代码行数:29,代码来源:MapReferenceDrawer.cs

示例2: OnGUI

        public override void OnGUI(Rect position, SerializedProperty prop, GUIContent label)
        {
            Rect textFieldPosition = position;
            textFieldPosition.height = 16;
            textFieldPosition.width -= 64;

            // Get the path field
            prop.Next(true);

            string pathLabel = prop.stringValue;

            if(string.IsNullOrEmpty(pathLabel))
            {
                pathLabel = "(none)";
            }

            EditorGUI.LabelField(textFieldPosition, label, new GUIContent(pathLabel));

            Rect buttonPosition = position;
            buttonPosition.height = 16;
            buttonPosition.x += buttonPosition.width - 48;
            buttonPosition.width = 48;

            DataTool.Log(prop);

            prop.serializedObject.ApplyModifiedProperties();
        }
开发者ID:Putaitu,项目名称:unity-boilerplate,代码行数:27,代码来源:SpriteReferenceDrawer.cs

示例3: GetPropertyHeight

 //Get property height.
 public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
 {
     SpriteRenderer spriteRenderer = ((SpriteShatter.Shatter) property.serializedObject.targetObject).gameObject.GetComponent<SpriteRenderer>();
     if (spriteRenderer == null || spriteRenderer.sprite == null)
         return base.GetPropertyHeight(property, label) * 2;
     bool textureIsReadable = ((TextureImporter) AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(spriteRenderer.sprite))).isReadable;
     for (int i = 0; i < 3; i++)
         property.Next(true);
     return (base.GetPropertyHeight(property, label) + EditorGUIUtility.standardVerticalSpacing) * ((textureIsReadable ? 15 : 21) +
             (property.boolValue ? 0 : 1)) + (textureIsReadable ? (int) (((float) (int) spriteRenderer.sprite.rect.height /
             (float) (int) spriteRenderer.sprite.rect.width) * Screen.width * 0.75f) : 0);
 }
开发者ID:stonecompass,项目名称:mobilegame,代码行数:13,代码来源:ShatterPropertyDrawer.cs

示例4: CopyPropertyValue

        /// <summary>
        /// Copies value of <paramref name="sourceProperty"/> into <pararef name="destProperty"/>.
        /// </summary>
        /// <param name="destProperty">Destination property.</param>
        /// <param name="sourceProperty">Source property.</param>
        public static void CopyPropertyValue(SerializedProperty destProperty, SerializedProperty sourceProperty)
        {
            if (destProperty == null)
                throw new ArgumentNullException("destProperty");
            if (sourceProperty == null)
                throw new ArgumentNullException("sourceProperty");

            sourceProperty = sourceProperty.Copy();
            destProperty = destProperty.Copy();

            CopyPropertyValueSingular(destProperty, sourceProperty);

            if (sourceProperty.hasChildren) {
                int elementPropertyDepth = sourceProperty.depth;
                while (sourceProperty.Next(true) && destProperty.Next(true) && sourceProperty.depth > elementPropertyDepth)
                    CopyPropertyValueSingular(destProperty, sourceProperty);
            }
        }
开发者ID:Doy32,项目名称:Samurai,代码行数:23,代码来源:SerializedPropertyUtility.cs

示例5: OnGUI

        public override void OnGUI(Rect position, SerializedProperty prop, GUIContent label)
        {
            Rect textFieldPosition = position;
            textFieldPosition.height = 16;
            textFieldPosition.width -= 64;

            // Get the path field
            prop.Next(true);

            string pathLabel = prop.stringValue;

            if(string.IsNullOrEmpty(pathLabel))
            {
                pathLabel = "(none)";
            }

            EditorGUI.LabelField(textFieldPosition, label, new GUIContent(pathLabel));

            Rect buttonPosition = position;
            buttonPosition.height = 16;
            buttonPosition.x += buttonPosition.width - 48;
            buttonPosition.width = 48;

            if(GUI.Button(buttonPosition, "..."))
            {
                string newPath = EditorUtility.OpenFilePanel("Load a conversation file", prop.stringValue, "convo");

                if(!string.IsNullOrEmpty(newPath))
                {
                    newPath = newPath.Replace(Application.dataPath, "");

                    prop.stringValue = newPath;

                    prop.serializedObject.ApplyModifiedProperties();
                }
            }
        }
开发者ID:Putaitu,项目名称:unity-boilerplate,代码行数:37,代码来源:ConversationReferenceDrawer.cs

示例6: FirstOrDefault

 static SerializedProperty FirstOrDefault(SerializedProperty prop, Predicate<SerializedProperty> predicate, bool descendIntoChildren = false)
 {
     while (prop.Next(descendIntoChildren))
     {
         if (predicate(prop))
             return prop.Copy();
     }
     return null;
 }
开发者ID:zhutaorun,项目名称:ugui-mvvm,代码行数:9,代码来源:INPCBindingEditor.cs

示例7: OnGUI

    //On GUI.
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        //Set the row height and initial position.
        float rowHeight = base.GetPropertyHeight(property, label);
        position = new Rect(position.xMin, position.yMin, position.width, rowHeight);
        rowHeight += EditorGUIUtility.standardVerticalSpacing;

        //If the sprite doesn't have its "readable" flag set, warn the user and given them the option to set it.
        SpriteRenderer spriteRenderer = ((SpriteShatter.Shatter) property.serializedObject.targetObject).gameObject.GetComponent<SpriteRenderer>();
        if (spriteRenderer == null || spriteRenderer.sprite == null) {
            position.height *= 2;
            EditorGUI.HelpBox(position, "Sprite Renderer does not have a sprite!", MessageType.Error);
            return;
        }
        string assetPath = AssetDatabase.GetAssetPath(spriteRenderer.sprite);
        TextureImporter textureImporter = (TextureImporter) AssetImporter.GetAtPath(assetPath);
        if (!textureImporter.isReadable) {
            addRow(ref position, rowHeight);
            position.height *= 2;
            EditorGUI.HelpBox(position, "Texture \"Read/Write\" flag not set!", MessageType.Error);
            position.height /= 2;
            addRow(ref position, rowHeight * 2);
            if (GUI.Button(position, new GUIContent("Set Texture Read/Write Flag", "Sprite Shatter requires that the sprite's texture has its \"Read/Write\"" +
                    "flag set. This is to ensure that the pixels can be read from the texture in order to shatter it. The flag is not currently set on the " +
                    "texture associated with this sprite, but you can click the button below to set it."))) {
                textureImporter.isReadable = true;
                AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceUpdate);
                EditorUtility.DisplayDialog("Texture Read/Write Flag Set", "The \"Read/Write\" flag has been set on the texture associated with this sprite.",
                        "OK");
            }
            addRow(ref position, rowHeight);
        }

        //Display the property fields.
        addRow(ref position, rowHeight);
        EditorGUI.LabelField(position, "Create Shatter Objects", EditorStyles.boldLabel);
        addRow(ref position, rowHeight);
        property.Next(true);
        EditorGUI.BeginProperty(position, label, property);
        property.intValue = EditorGUI.IntSlider(position, new GUIContent("Horizontal Cuts", "The number of cuts to make going horizontally across the " +
                "sprite. More cuts will shatter the sprite into smaller pieces, but will require more game objects and may affect performance."),
                property.intValue, 1, 32);
        EditorGUI.EndProperty();
        int horizontalCuts = property.intValue;
        addRow(ref position, rowHeight);
        property.Next(false);
        EditorGUI.BeginProperty(position, label, property);
        property.intValue = EditorGUI.IntSlider(position, new GUIContent("Vertical Cuts", "The number of cuts to make going vertically down the sprite. More " +
                "cuts will shatter the sprite into smaller pieces, but will require more game objects and may affect performance."), property.intValue, 1, 32);
        EditorGUI.EndProperty();
        int verticalCuts = property.intValue;
        addRow(ref position, rowHeight);
        property.Next(false);
        EditorGUI.BeginProperty(position, label, property);
        property.boolValue = EditorGUI.Toggle(position, new GUIContent("Randomize at Runtime", "Generate a completely random seed at runtime, meaning the " +
                "layout of the shattered sprite pieces will be different every time the game is run. This only has any effect if \"Randomness\" is set to " +
                "greater than zero."), property.boolValue);
        EditorGUI.EndProperty();
        bool randomizeAtRuntime = property.boolValue;
        addRow(ref position, rowHeight);
        property.Next(false);
        if (!randomizeAtRuntime) {
            EditorGUI.BeginProperty(position, label, property);
            property.intValue = EditorGUI.IntField(position, new GUIContent("Random Seed", "The seed value to use when generating random numbers. The same " +
                    "seed will always generate cuts in the same way, which is useful if you want multiple objects to shatter in an identical way. Otherwise " +
                    "you can select \"Randomize at Runtime\" below to generate a different random set of cuts each time the game runs. The random seed only " +
                    "has any effect if \"Randomness\" is set to greater than zero."), property.intValue);
            EditorGUI.EndProperty();
            addRow(ref position, rowHeight);
        }
        int randomSeed = property.intValue;
        property.Next(false);
        EditorGUI.BeginProperty(position, label, property);
        property.floatValue = EditorGUI.Slider(position, new GUIContent("Randomness", "The amount of randomness to apply to the cuts. A value of zero will " +
                "result in perfectly straight cuts, whereas a value of one will result in cuts that potentially could be almost touching each other."),
                property.floatValue, 0, 1);
        EditorGUI.EndProperty();
        float randomness = property.floatValue;
        addRow(ref position, rowHeight);
        property.Next(false);
        EditorGUI.BeginProperty(position, label, property);
        property.floatValue = EditorGUI.Slider(position, new GUIContent("Zigzag Frequency", "This property, along with \"Zigzag Amplitude\" allows for a " +
                "zigzag shape to be added to the cuts to make more jagged edges and more random-looking pieces. \"Zigzag Frequency\" specifies the number of " +
                "jagged edges across or down the cuts, but will have no effect if \"Zigzag Amplitude\" is zero."), property.floatValue, 0, 1);
        EditorGUI.EndProperty();
        float zigzagFrequency = property.floatValue;
        addRow(ref position, rowHeight);
        property.Next(false);
        EditorGUI.BeginProperty(position, label, property);
        property.floatValue = EditorGUI.Slider(position, new GUIContent("Zigzag Amplitude", "This property, along with \"Zigzag Amplitude\" allows for a " +
                "zigzag shape to be added to the cuts to make more jagged edges and more random-looking pieces. \"Zigzag Frequency\" specifies the number of " +
                "jagged edges across or down the cuts, but will have no effect if \"Zigzag Amplitude\" is zero."), property.floatValue, 0, 1);
        EditorGUI.EndProperty();
        float zigzagAmplitude = property.floatValue;
        addRow(ref position, rowHeight);
        property.Next(false);
        EditorGUI.BeginProperty(position, label, property);
        property.intValue = EditorGUI.IntPopup(position, new GUIContent("Collider Types", "The collider type to add to each of the shattered pieces of the " +
                "sprite. Having no collider is the most efficient way of shattering a sprite, but the shattered pieces will not collide with anything. A " +
//.........这里部分代码省略.........
开发者ID:stonecompass,项目名称:mobilegame,代码行数:101,代码来源:ShatterPropertyDrawer.cs

示例8: RemoveRect

 //removes rect from the font settings and lists
 void RemoveRect()
 {
     ReFocusBlank = true;
     CharCount -= 1;
     SO = new SerializedObject( FontList[Rects[ClickedRectInd].fontIndex] );
     p = SO.FindProperty( "m_CharacterRects" );
     p.Next( true );
     p.DeleteArrayElementAtIndex( Rects[ClickedRectInd].CIIndex );
     SO.ApplyModifiedProperties(); //remove it from the actual font
     for ( int i = 0; i < Rects.Count; i++ ) { //Shift down all the CIindex for all rects in this font
         if ( Rects[i].fontIndex == Rects[ClickedRectInd].fontIndex && Rects[i].CIIndex > Rects[ClickedRectInd].CIIndex ) {
             Rects[i].CIIndex--;
         }
     }
     Rects.RemoveAt( ClickedRectInd ); //delete from the rect list
     if ( SpriteEditor ) { //check if removing has changed dupes
         CheckSprites();
     } else {
         CheckDupeChars();
     }
     ClickedRectInd--;
     ChrL--;
     if ( Rects.Count > 0 && ClickedRectInd == -1 ) {
         ClickedRectInd = 0;
     }
     if ( Rects.Count > 0 ) {
         GetFontInfoToGUI( Rects[ClickedRectInd].CIIndex, Rects[ClickedRectInd].fontIndex );
     } else {
         SpriteIndex = 0;
         SpriteIndexOld = 0;
     }
 }
开发者ID:mutatis,项目名称:cthulhu-free-iphone,代码行数:33,代码来源:FontEditorCs.cs

示例9: OnGUI


//.........这里部分代码省略.........
            GUI.Box( new Rect( position.width - MenuBar.width, 0, MenuBar.width, MenuBar.height ), "" );/////RightBox
            GUI.BeginGroup( new Rect( 4, 4, position.width - 4, MenuBar.height - 8 ) );//Clip The Menu pics
            GUI.DrawTexture( new Rect( position.width - 8 - MenuPics[0].width, 0, MenuPics[0].width, MenuPics[0].height ), MenuPics[0] );
            GUI.EndGroup();
            GUI.enabled = !AutoSetDialog && !SpriteSetDialog;

            GUI.BeginGroup( new Rect( position.width - 140, 10, 130, 80 ) ); //Undo and shrinkwrap buttons
            if ( GUI.Button( new Rect( 0, 0, 130, 30 ), "Undo" ) ) {
                Undo.PerformUndo();
            }
            GUI.enabled = !AutoSetDialog && !SpriteSetDialog && Rects.Count > 0;
            if ( GUI.Button( new Rect( 10, 40, 110, 25 ), "Shrinkwrap" ) ) {
                ShrinkWrap();
            }
            GUI.EndGroup();
            GUI.enabled = true;
            GUI.BeginGroup( new Rect( MenuBar.width, 0, position.width - 150, position.height ) );//Clip The Background Box
            GUI.color = Color.gray;
            GUI.skin = theGUISkin;
            GUI.Box( new Rect( 0, 0, position.width - 300, position.height ), "", "White" );
            GUI.color = Color.white;
            GUI.EndGroup();

            //Controls in sprite setter
            if ( SpriteEditor && !SpriteSetDialog ) {
                GUI.BeginGroup( new Rect( position.width - MenuBar.width, 100, MenuBar.width, 200 ) ); //Animation Properties group
                GUI.Box( new Rect( 0, 0, 150, (int) SpritePropertiesLoopBehaviour == 3 ? 160 : ( (int) SpritePropertiesLoopBehaviour == 2 ? 120 : 140 ) ), "" );
                GUI.Label( new Rect( 10, 2, 130, 20 ), "Animation Properties:" );
                EditorGUIUtility.LookLikeControls( 40, 60 );
                SpritePropertiesFontIndex = EditorGUI.Popup( new Rect( 10, 24, 130, 20 ), "Anim:", SpritePropertiesFontIndex, FontListNames );
                SpritePropertiesLoopBehaviour = (SpritePropertiesLoopBehaviourEnum) EditorGUI.EnumPopup( new Rect( 10, 44, 130, 20 ), "Loop:", SpritePropertiesLoopBehaviour );
                if ( (int) SpritePropertiesLoopBehaviour == 3 ) {
                    EditorGUIUtility.LookLikeControls( 70, 60 );
                    SpritePropertiesNextAnim = EditorGUI.Popup( new Rect( 10, 64, 130, 20 ), "Change to:", SpritePropertiesNextAnim, FontListNames );
                }
                if ( (int) SpritePropertiesLoopBehaviour == 0 || (int) SpritePropertiesLoopBehaviour == 1 || (int) SpritePropertiesLoopBehaviour == 3 ) {
                    EditorGUIUtility.LookLikeControls( 105, 60 );
                    SpritePropertiesLoopStart = Mathf.Clamp( EditorGUI.IntField( new Rect( 10, (int) SpritePropertiesLoopBehaviour == 3 ? 84 : 64, 130, 18 ), (int) SpritePropertiesLoopBehaviour == 3 ? "Starting at:" : "Loop start frame:", SpritePropertiesLoopStart ), 0, FontList[(int) SpritePropertiesLoopBehaviour == 3 ? SpritePropertiesNextAnim : SpritePropertiesFontIndex].characterInfo.Length - 2 );
                }
                EditorGUIUtility.LookLikeControls( 105, 60 );
                SpritePropertiesAnimFPS = EditorGUI.FloatField( new Rect( 10, (int) SpritePropertiesLoopBehaviour == 3 ? 102 : ( (int) SpritePropertiesLoopBehaviour == 2 ? 62 : 82 ), 130, 18 ), "Anim FPS Multip:", SpritePropertiesAnimFPS );
                AutoAnimate = GUI.Toggle( new Rect( 10, (int) SpritePropertiesLoopBehaviour == 3 ? 116 : ( (int) SpritePropertiesLoopBehaviour == 2 ? 76 : 96 ), 130, 20 ), AutoAnimate, "Auto-animate" );
                GUI.Label( new Rect( 10, (int) SpritePropertiesLoopBehaviour == 3 ? 134 : ( (int) SpritePropertiesLoopBehaviour == 2 ? 94 : 114 ), 30, 20 ), "" + SpriteFrame );
                SpriteFrame = (int) GUI.HorizontalSlider( new Rect( 28, (int) SpritePropertiesLoopBehaviour == 3 ? 140 : ( (int) SpritePropertiesLoopBehaviour == 2 ? 100 : 120 ), 112, 18 ), SpriteFrame, 0, FontList[SpritePropertiesFontIndex].characterInfo.Length - 2 );

                //if you switch auto on, go back to the start.
                if ( AutoAnimate != AutoAnimateOld ) {
                    AutoAnimateOld = AutoAnimate;
                    if ( AutoAnimate == true ) {
                        SpriteFrame = 0;
                    }
                }

                //choosing a new font needs to update the other fields
                if ( SpritePropertiesFontIndex != SpritePropertiesFontIndexOld ) {
                    ReFocusBlank = true;
                    SpritePropertiesFontIndexOld = SpritePropertiesFontIndex;
                    SpritePropertiesLoopBehaviour = (SpritePropertiesLoopBehaviourEnum) FontList[SpritePropertiesFontIndex].characterInfo[0].index;
                    SpritePropertiesLoopBehaviourOld = SpritePropertiesLoopBehaviour;
                    SpritePropertiesNextAnim = (int) FontList[SpritePropertiesFontIndex].characterInfo[0].uv.x;
                    SpritePropertiesNextAnimOld = SpritePropertiesNextAnim;
                    SpritePropertiesLoopStart = (int) FontList[SpritePropertiesFontIndex].characterInfo[0].uv.y;
                    SpritePropertiesLoopStartOld = SpritePropertiesLoopStart;
                    SpritePropertiesAnimFPS = FontList[SpritePropertiesFontIndex].characterInfo[0].uv.width + 1;
                    SpritePropertiesAnimFPSOld = SpritePropertiesAnimFPS;
                    if ( SpritePreview != null ) {
开发者ID:mutatis,项目名称:cthulhu-free-iphone,代码行数:67,代码来源:FontEditorCs.cs

示例10: DrawRemainingProp

    private static void DrawRemainingProp(SerializedProperty prop) {
        int depth = prop.depth;

        while (true) {
            bool child = EditorGUILayout.PropertyField(prop, true);

            if (!prop.Next(child) || prop.depth < depth)
                break;
        }
    }
开发者ID:jharger,项目名称:globalgamejam2016,代码行数:10,代码来源:AlloyDeferredRendererPlusEditor.cs

示例11: MultiPropertyField

		internal static void MultiPropertyField(Rect position, GUIContent[] subLabels, SerializedProperty valuesIterator, float labelWidth = 13)
		{
			int num = subLabels.Length;
			float num2 = (position.width - (float)(num - 1) * 2) / (float)num;
			Rect position2 = new Rect(position);
			position2.width = num2;
			float labelWidth2 = EditorGUIUtility.labelWidth;
			int indentLevel = EditorGUI.indentLevel;
			EditorGUIUtility.labelWidth = labelWidth;
			EditorGUI.indentLevel = 0;
			for (int i = 0; i < subLabels.Length; i++)
			{
				EditorGUI.PropertyField(position2, valuesIterator, subLabels[i]);
				position2.x += num2 + 2;
				valuesIterator.Next(false);
			}
			EditorGUIUtility.labelWidth = labelWidth2;
			EditorGUI.indentLevel = indentLevel;
		}
开发者ID:Zammy,项目名称:ProjectSpaceship,代码行数:19,代码来源:PEPropertyHelper.cs

示例12: PropertyField

		static public bool PropertyField(Rect position, SerializedProperty property, GUIContent label, bool includeChildren)
		{
			//if (!includeChildren)
			{
				switch (property.propertyType)
				{
					case SerializedPropertyType.Vector2:
					case SerializedPropertyType.Vector3:
						property = property.Copy();
						var labels = property.propertyType == SerializedPropertyType.Vector2 ? v2Labels : v3Labels;
						if (label == null)
							label = new GUIContent(GetDisplayName(property));

						property.Next(true);

						MultiPropertyField(position, labels, property, label);
						return false;
				}
			}

			return EditorGUI.PropertyField(position, property, label, includeChildren);
		}
开发者ID:Zammy,项目名称:ProjectSpaceship,代码行数:22,代码来源:PEPropertyHelper.cs

示例13: AddPropsFromArray

	private void AddPropsFromArray(PropType type, SerializedProperty props) {
		string original = props.propertyPath;

		props.Next(true);
		props.Next(true);
		props.Next(true);

		do {
			var valueProp = props.FindPropertyRelative("second");
			var nameProp = props.FindPropertyRelative("first.name");



			string propName = nameProp.stringValue;

			AddProperty(propName, type, valueProp);
		} while (props.NextVisible(false) && props.propertyPath.Contains(original));
	}
开发者ID:jharger,项目名称:globalgamejam2016,代码行数:18,代码来源:AlloyInspectorBase.cs

示例14: PropsInArrayMismatched

	private bool PropsInArrayMismatched(SerializedProperty props) {
		string original = props.propertyPath;

		props.Next(true);
		props.Next(true);
		props.Next(true);

		//some weird unity behaviour where it collapses the array 
		if (!props.propertyPath.Contains(original)) {
			return true;
		}

		do {
			var nameProp = props.FindPropertyRelative("first.name");

			if (nameProp.hasMultipleDifferentValues) {
				return true;
			}
		} while (props.NextVisible(false) && props.propertyPath.Contains(original));



		return false;
	}
开发者ID:jharger,项目名称:globalgamejam2016,代码行数:24,代码来源:AlloyInspectorBase.cs


注:本文中的UnityEditor.SerializedProperty.Next方法示例由纯净天空整理自Github/MSDocs等开源代码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。