Unity Editor中的內(nèi)置圖標(biāo)

首先貼兩個(gè)鏈接
【Unity編輯器】Unity內(nèi)置GUI風(fēng)格和資源
Unity3D研究院之系統(tǒng)內(nèi)置系統(tǒng)圖標(biāo)大整理

這第一篇的作者是傳說中的 號稱 A神 的大神寫的轧房。午笛。shader方面相當(dāng)666邻奠。

寫這篇文章的起因

這兩個(gè)鏈接都是介紹Unity Editor中的內(nèi)置圖標(biāo)的文章峰档。窒百。但是看來看去都只說了個(gè)實(shí)現(xiàn)步驟症杏。。卻沒給出具體的提取圖標(biāo)的代碼之類的伪节。光羞。感到很困惑。怀大。所以打算自己實(shí)現(xiàn)了一遍

經(jīng)過

通過上面兩篇文章的介紹纱兑,剛開始我有點(diǎn)摸不著頭腦。化借。首先一點(diǎn)是最近才開始嘗試著看一點(diǎn)Editor部分的API潜慎,自己做幾個(gè)沒有實(shí)際功能的demo。蓖康。铐炫。

接下來開始說一下過程,不過前提先看一下上面第一篇文章蒜焊,可能看著會有點(diǎn)暈倒信。∮景穑可以跟著我這里貼出的代碼看

一:導(dǎo)出代碼文件

先用工具ILSpy(其他工具也可以鳖悠,只要能導(dǎo)出反編譯的結(jié)果就行),打開Editor.dll优妙,并導(dǎo)出文件

導(dǎo)出的時(shí)候記得先選中根節(jié)點(diǎn)竞穷。。才能將所有代碼導(dǎo)出來鳞溉;如果只選中一個(gè)類瘾带,則只會導(dǎo)出一個(gè)cs文件

ILSpy導(dǎo)出代碼

二:了解加載內(nèi)置圖標(biāo)的一些api

主要有三個(gè)地方

  1. 一個(gè)是窗口標(biāo)題上的圖標(biāo)
  2. 內(nèi)部函數(shù) EditorGUIUtility.LoadIcon
  3. EditorGUIUtility.FindTexture(這個(gè)不是內(nèi)部函數(shù),所以我們可以調(diào)用的到)
二(1)窗口上的圖標(biāo)

我們可以通過 ILSpy熟菲,搜索類型ProjectBrowser看政。。然后可以看到ProjectBrowser這個(gè)類的簽名如下

[EditorWindowTitle(title = "Project", icon = "Project")]
internal class ProjectBrowser : EditorWindow, IHasCustomMenu

一眼看過去就看到 icon抄罕,當(dāng)然是跟到 EditorWindowTitle 這個(gè)特性中去看看允蚣,發(fā)現(xiàn)只有三個(gè)屬性(title, icon, useTypeNameAsIconName),而且屬性名看起來意思很明顯呆贿。所已接下來要找到使用這個(gè)特性的地方嚷兔。

看到OnEnable 方法中 通過 base.GetLocalizedTitleContent() 初始化 titleContent森渐,然后一直跟進(jìn)去就可以了。

private void OnEnable()
{
    base.titleContent = base.GetLocalizedTitleContent();
    ....
}
EditorWindowTitle 初始化 titleContent

也可以通過Sublime 打開剛才的ILSpy導(dǎo)出的文件夾(直接把文件夾拖到Sublime中就可以了)冒晰,然后在Sublime中對根節(jié)點(diǎn)右鍵 -> 點(diǎn)擊 Find in Folder...

Sublime在文件中查找...

然后用 EditorWindowTitle 這個(gè)作為關(guān)鍵字搜索就可以搜到所有使用到的地方了同衣,然后可以看到在 EditorWindowGetLocalizedTitleContent() 方法中有引用到。

Sublime搜索結(jié)果-EditorWindow.cs

然后跟 到 GUIContent GetLocalizedTitleContentFromType(Type t) 這個(gè)函數(shù)中:


internal GUIContent GetLocalizedTitleContent()
{
    return EditorWindow.GetLocalizedTitleContentFromType(base.GetType());
}

internal static GUIContent GetLocalizedTitleContentFromType(Type t)
{
    // 得到 EditorWindowTitleAttribute 特性
    EditorWindowTitleAttribute editorWindowTitleAttribute = EditorWindow.GetEditorWindowTitleAttribute(t);
    if (editorWindowTitleAttribute == null)
    {
        // 若沒有特性壶运,則窗口類名作為窗口的title
        return new GUIContent(t.ToString());
    }
    string text = string.Empty;
    if (!string.IsNullOrEmpty(editorWindowTitleAttribute.icon))
    {
        // 若存在特性耐齐,若 icon屬性 不為空,則用該屬性 的值作為 圖標(biāo)名用于后面加載圖標(biāo)
        text = editorWindowTitleAttribute.icon;
    }
    else if (editorWindowTitleAttribute.useTypeNameAsIconName)
    {
        // 如果 icon屬性 為空蒋情,若屬性 useTypeNameAsIconName 為true埠况,則用窗口類型名來加載圖標(biāo)
        text = t.ToString();
    }
    if (!string.IsNullOrEmpty(text))
    {
        return EditorGUIUtility.TextContentWithIcon(editorWindowTitleAttribute.title, text);
    }
    return EditorGUIUtility.TextContent(editorWindowTitleAttribute.title);
}

繼續(xù)跟進(jìn) EditorGUIUtility.TextContentWithIcon

// UnityEditor.EditorGUIUtility
internal static GUIContent TextContentWithIcon(string textAndTooltip, string icon)
{
    // ...
        gUIContent.image = EditorGUIUtility.LoadIconRequired(icon);
    // ...
    return gUIContent;
}

然后進(jìn)入EditorGUIUtility.LoadIconRequired

// UnityEditor.EditorGUIUtility
internal static Texture2D LoadIconRequired(string name)
{
    Texture2D texture2D = EditorGUIUtility.LoadIcon(name);
    // ...
    return texture2D;
}

到這里就夠了。棵癣。辕翰。可以看出最后是調(diào)用 EditorGUIUtility.LoadIcon 這個(gè)函數(shù)來得到圖標(biāo)的狈谊。喜命。

提取圖標(biāo)

因?yàn)樯厦嫔婕暗降腁PI基本都是 internal 修飾的,所以我們需要通過反射來得到所有繼承自 EditorWindow 且具有 EditorWindowTitleAttribute 特性的類的畴。然后分析特性中屬性值來得到 圖標(biāo)名字渊抄。最后通過反射調(diào)用 EditorGUIUtility.LoadIcon 加載出圖片尝胆。丧裁。代碼在最后貼出

二(2)通過內(nèi)部函數(shù) EditorGUIUtility.LoadIcon 直接加載的圖標(biāo)

也就是 通過如下形式調(diào)用 LoadIcon,只要提取所有 實(shí)參含衔,然后通過反射調(diào)用 LoadIcon 加載出來就可以了煎娇。。這里提取實(shí)參要通過 正則 來提取贪染。缓呛。

EditorGUIUtility.LoadIcon("icon name");
二(3)EditorGUIUtility.FindTexture(這個(gè)不是內(nèi)部函數(shù),所以我們可以調(diào)用的到)

這個(gè)和上面的 EditorGUIUtility.LoadIcon 一樣的思路杭隙,不過 FindTexture 不是內(nèi)部函數(shù)哟绊,所以可以不通過反射直接調(diào)用。痰憎。票髓。我的代碼里面為了 代碼的復(fù)用,所以 也通過反射來調(diào)用 FindTexture的

結(jié)果(貼代碼)

代碼中涉及的面還是有點(diǎn)廣的铣耘。洽沟。。有 反射蜗细、Editor 的Api使用裆操、正則怒详、簡單的Linq。踪区。昆烁。
我主要是想把這些平時(shí)比較少用的趁這之后練練手,所以能用上的我都盡量嘗試一下朽缴。善玫。。

本來想 看看能不能通過 部分類(partial)來擴(kuò)展 EditorGUIUtility 來添加一個(gè) LoadIconEx密强,方法中通過反射調(diào)用茅郎,這樣我就可以把反射代碼集中到這個(gè)部分類里面去了。或渤。但是 部分類的前提是 每個(gè)部分都要有 partial 修飾類的聲明系冗,而 UnityEditor.dll 中卻沒有。之前也想過用擴(kuò)展方法來做薪鹦,但是擴(kuò)展方法需要有實(shí)例調(diào)用掌敬。。但是這里反射調(diào)用的API 都是 靜態(tài)的池磁。奔害。

具體的代碼中都有注釋。地熄』伲看不懂的可以問我。端考。

廢話有點(diǎn)多雅潭。。却特。

窗口菜單
結(jié)果圖
using UnityEngine;
using System.Collections;
using UnityEditor;
using System.IO;
using System.Collections.Generic;
using System.Reflection;
using System;
using System.Text.RegularExpressions;
using System.Linq;
using System.Text;

public class ListInternalIconWindow : EditorWindow
{
    [MenuItem("Window/Open Internal Icon Window")]
    static void Open()
    {
        GetWindow<ListInternalIconWindow>();
    }

    private List<GUIContent> lstWindowIcons, lstLoadIconParmContents, lstFindTextureParmContents;
    private Vector2 vct2LoadIconParmScroll;
    private Rect rectScrollViewPos = new Rect(), rectScrollViewRect = new Rect();
    private Rect headerRct = new Rect();
    private Rect rectLoadIcon = new Rect(0, 0, 300, 35);


    private MethodInfo loadIconMethodInfo, findTextureMethodInfo;
    private IEnumerator enumeratorLoadIcon, enumeratorFindTexture;

    void Awake()
    {
        lstWindowIcons = new List<GUIContent>();
        lstLoadIconParmContents = new List<GUIContent>();
        lstFindTextureParmContents = new List<GUIContent>();

        loadIconMethodInfo = typeof(EditorGUIUtility).GetMethod("LoadIcon", BindingFlags.Static | BindingFlags.NonPublic);
        findTextureMethodInfo = typeof(EditorGUIUtility).GetMethod("FindTexture", BindingFlags.Static | BindingFlags.Public);

        InitWindowsIconList();
        enumeratorLoadIcon = MethodParamEnumerator("EditorGUIUtility.LoadIcon", loadIconMethodInfo);
        enumeratorFindTexture = MethodParamEnumerator("EditorGUIUtility.FindTexture", findTextureMethodInfo);

        // LoadIcon 的實(shí)參有的是字符串拼接的扶供。。這種我就沒有加載出來裂明,可以到UnityEditor.dll源碼中查看如何憑借
        // 這里我用一個(gè)源碼中拼接的圖標(biāo)作為該窗口的圖標(biāo)
        titleContent = new GUIContent("InternalIcon", loadIconMethodInfo.Invoke(null, new object[] { "WaitSpin00" }) as Texture);
        minSize = new Vector2(512, 320);
    }
    void OnGUI()
    {
        // Don't use yield in OnGUI() between GUILayout.BeginArea() and GUILayout.EndArea()
        if (null != enumeratorLoadIcon && enumeratorLoadIcon.MoveNext() && null != enumeratorLoadIcon.Current)
        {
            lstLoadIconParmContents.Add(enumeratorLoadIcon.Current as GUIContent);
            Repaint();
        }
        if(null != enumeratorFindTexture && enumeratorFindTexture.MoveNext() && null != enumeratorFindTexture.Current)
        {
            lstFindTextureParmContents.Add(enumeratorFindTexture.Current as GUIContent);
            Repaint();
        }

        headerRct.x = headerRct.y = 0;
        headerRct.width = position.width;
        headerRct.height = 30;

        int colCount = Mathf.Max(1, (int)(position.width / rectLoadIcon.width));
        int rowCount = (lstWindowIcons.Count + lstLoadIconParmContents.Count + lstFindTextureParmContents.Count) / colCount + 2;

        rectScrollViewRect.width = colCount * rectLoadIcon.width;
        rectScrollViewRect.height = rowCount * rectLoadIcon.height + 3 * headerRct.height;
        rectScrollViewPos.width = position.width;
        rectScrollViewPos.height = position.height;

        vct2LoadIconParmScroll = GUI.BeginScrollView(rectScrollViewPos, vct2LoadIconParmScroll, rectScrollViewRect);
        {
            float offsetY = 0;
            string headerText = "添加EditorWindowTitleAttribute 特性的窗口的圖標(biāo):" + lstWindowIcons.Count + " 個(gè)";
            offsetY = DrawList(headerText, offsetY, colCount, lstWindowIcons, false);

            headerRct.y = offsetY;
            headerText = "傳遞給 EditorGUIUtility.LoadIcon 的參數(shù):" + lstLoadIconParmContents.Count + " 個(gè)";
            offsetY = DrawList(headerText, offsetY, colCount, lstLoadIconParmContents, true);

            headerRct.y = offsetY;
            headerText = "傳遞給 EditorGUIUtility.FindTexture 的參數(shù):" + lstFindTextureParmContents.Count + " 個(gè)";
            offsetY = DrawList(headerText, offsetY, colCount, lstFindTextureParmContents, true);
        }
        GUI.EndScrollView();
    }
    /// <summary>
    /// 繪制 GUIContent list
    /// </summary>
    /// <param name="headerText">標(biāo)頭</param>
    /// <param name="offsetY">繪制區(qū)域的垂直偏移量</param>
    /// <param name="colCount">一行繪制幾個(gè)</param>
    /// <param name="lstGUIContent">將要繪制的 GUIContent list</param>
    /// <returns>返回 結(jié)束后的偏移量</returns>
    private float DrawList(string headerText, float offsetY, int colCount, List<GUIContent> lstGUIContent, bool isRemoveReturn)
    {
        GUI.Label(headerRct, headerText);
        offsetY += headerRct.height;
        for (int i = 0; i < lstGUIContent.Count; ++i)
        {
            rectLoadIcon.x = (int)(rectLoadIcon.width * (i % colCount));
            rectLoadIcon.y = (int)(rectLoadIcon.height * (i / colCount)) + offsetY;

            if(GUI.Button(rectLoadIcon, lstGUIContent[i]))
            {
                string str = lstGUIContent[i].text;
                if(isRemoveReturn)
                {
                    str = str.Replace("\r", "");
                    str = str.Replace("\n", "");
                }
                Debug.Log(str);
            }
        }
        return offsetY + (lstGUIContent.Count / colCount + 1) * rectLoadIcon.height;
    }
    /// <summary>
    /// 通過反射得到 EditorWindowTitleAttribute 特性標(biāo)記的 EditorWindow 子類
    /// 并通過這個(gè)特性中的屬性得到 圖標(biāo)的名字椿浓,
    /// 然后繼續(xù)通過反射調(diào)用內(nèi)部方法 EditorGUIUtility.LoadIcon 來得到 圖標(biāo)的 Texture 實(shí)例
    /// </summary>
    private void InitWindowsIconList()
    {
        Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();

        Type editorWindowTitleAttrType = typeof(EditorWindow).Assembly.GetType("UnityEditor.EditorWindowTitleAttribute");

        foreach (Assembly assembly in assemblies)
        {
            Type[] types = assembly.GetTypes();
            foreach (Type type in types)
            {
                if (!type.IsSubclassOf(typeof(EditorWindow)))
                    continue;
                
                object[] attrs = type.GetCustomAttributes(editorWindowTitleAttrType, true);
                for(int i=0; i<attrs.Length; ++i)
                {
                    if(attrs[i].GetType() == editorWindowTitleAttrType)
                    {
                        string icon = GetPropertyValue<string>(editorWindowTitleAttrType, attrs[i], "icon");
                        if (string.IsNullOrEmpty(icon))
                        {
                            bool useTypeNameAsIconName = GetPropertyValue<bool>(editorWindowTitleAttrType, attrs[i], "useTypeNameAsIconName");
                            if (useTypeNameAsIconName)
                                icon = type.ToString();
                        }

                        if(!string.IsNullOrEmpty(icon) && null != loadIconMethodInfo)
                        {
                            var iconTexture = loadIconMethodInfo.Invoke(null, new object[] { icon }) as Texture2D;
                            if (null != iconTexture)
                                lstWindowIcons.Add(new GUIContent(type.Name + "\n" + icon, iconTexture));
                        }
                    }
                }
            }
        }
    }
    /// <summary>
    /// 通過將 Editor.dll 反編譯出來,遍歷反編譯出來的所有文件闽晦,
    /// 通過正則找出所有 調(diào)用 EditorGUIUtility.LoadIcon 時(shí)傳遞 的參數(shù)
    /// </summary>
    /// <param name="methodName">加載貼圖的函數(shù)名</param>
    /// <param name="loadTextureAction">加載貼圖的函數(shù)</param>
    /// <returns></returns>
    private IEnumerator MethodParamEnumerator(string methodName, MethodInfo loadTextureMethodInfo)
    {
        Type editorResourcesUtility = typeof(EditorWindow).Assembly.GetType("UnityEditorInternal.EditorResourcesUtility");

        //Regex regex = new Regex(@"(?<=EditorGUIUtility.LoadIcon\("")[^""]+(?=""\))");
        Regex regex = new Regex(@"(?<=" + methodName + @"\()[^\(\)]*(((?'Open'\()[^\(\)]*)+((?'-Open'\))[^\(\)]*)+)*(?=\))(?(Open)(?!))");
        Regex quatRegex = new Regex(@"(?<=^"")[^""]+(?=""$)");

        // 這里是反編譯 UnityEditor.dll 導(dǎo)出來的文件夾
        string[] files = Directory.GetFiles(@"D:\Unity5\UnityEditor", "*.cs", SearchOption.AllDirectories);

        var enumerable = from matchCollection in
                            (from content in
                                (from file in files select File.ReadAllText(file))
                             select regex.Matches(content))
                         select matchCollection;
        
        foreach (MatchCollection matchCollection in enumerable)
        {
            for(int i=0; i<matchCollection.Count; ++i)
            {
                Match match = matchCollection[i];
                string iconName = ((Match)match).Groups[0].Value;

                if (string.IsNullOrEmpty(iconName) || null == loadTextureMethodInfo)
                    continue;

                bool isDispatchMethod = false;
                Texture iconTexture = null;
                if (quatRegex.IsMatch(iconName))
                {
                    isDispatchMethod = true;
                    iconName = iconName.Replace("\"", "");
                }
                else if(iconName.StartsWith("EditorResourcesUtility."))
                {
                    string resName = GetPropertyValue<string>(editorResourcesUtility, null, iconName.Replace("EditorResourcesUtility.", ""));
                    if(!string.IsNullOrEmpty(resName))
                    {
                        isDispatchMethod = true;
                        iconName = resName;
                    }
                }

                if(isDispatchMethod)
                {
                    try
                    {
                        iconTexture = loadTextureMethodInfo.Invoke(null, new object[] { iconName }) as Texture2D;
                    }
                    catch (Exception e)
                    {
                        Debug.LogError(iconName + "\n" + e);
                    }
                }

                if (null != iconTexture)
                    yield return new GUIContent(InsertReturn(iconName, 20), iconTexture);
                else
                    yield return new GUIContent(InsertReturn(iconName, 30));
            }
        }
    }
    /// <summary>
    /// 反射得到屬性值
    /// </summary>
    /// <typeparam name="T">屬性類型</typeparam>
    /// <param name="type">屬性所在的類型</param>
    /// <param name="obj">類型實(shí)例扳碍,若是靜態(tài)屬性,則obj傳null即可</param>
    /// <param name="propertyName">屬性名</param>
    /// <returns>屬性值</returns>
    private T GetPropertyValue<T>(Type type, object obj, string propertyName)
    {
        T result = default(T);
        PropertyInfo propertyInfo = type.GetProperty(propertyName);
        if(null != propertyInfo)
        {
            result = (T)propertyInfo.GetValue(obj, null);
        }
        return result;
    }
    /// <summary>
    /// 對字符串插入 換行符
    /// </summary>
    /// <param name="str">待處理的字符串</param>
    /// <param name="interval">每幾個(gè)字符插入一個(gè) 換行符</param>
    /// <returns></returns>
    private string InsertReturn(string str, int interval)
    {
        if (string.IsNullOrEmpty(str) || str.Length <= interval)
            return str;

        StringBuilder sb = new StringBuilder();
        int index = 0;
        while(index < str.Length)
        {
            if (0 != index)
                sb.Append("\r\n");

            int len = index + interval >= str.Length ? str.Length-index : interval;
            sb.Append(str.Substring(index, len));
            index += len;
        }
        return sb.ToString();
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末尼荆,一起剝皮案震驚了整個(gè)濱河市左腔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌捅儒,老刑警劉巖液样,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件振亮,死亡現(xiàn)場離奇詭異,居然都是意外死亡鞭莽,警方通過查閱死者的電腦和手機(jī)坊秸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來澎怒,“玉大人褒搔,你說我怎么就攤上這事∨缑妫” “怎么了星瘾?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長惧辈。 經(jīng)常有香客問我琳状,道長,這世上最難降的妖魔是什么盒齿? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任念逞,我火速辦了婚禮,結(jié)果婚禮上边翁,老公的妹妹穿的比我還像新娘翎承。我一直安慰自己,他們只是感情好符匾,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布叨咖。 她就那樣靜靜地躺著,像睡著了一般待讳。 火紅的嫁衣襯著肌膚如雪芒澜。 梳的紋絲不亂的頭發(fā)上仰剿,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天创淡,我揣著相機(jī)與錄音,去河邊找鬼南吮。 笑死琳彩,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的部凑。 我是一名探鬼主播露乏,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼涂邀!你這毒婦竟也來了瘟仿?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤比勉,失蹤者是張志新(化名)和其女友劉穎劳较,沒想到半個(gè)月后驹止,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡观蜗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年臊恋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片墓捻。...
    茶點(diǎn)故事閱讀 39,711評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡抖仅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出砖第,到底是詐尸還是另有隱情撤卢,我是刑警寧澤,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布梧兼,位于F島的核電站凸丸,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏袱院。R本人自食惡果不足惜屎慢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望忽洛。 院中可真熱鬧腻惠,春花似錦、人聲如沸欲虚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽复哆。三九已至欣喧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間梯找,已是汗流浹背唆阿。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留锈锤,地道東北人驯鳖。 一個(gè)月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像久免,于是被迫代替她去往敵國和親浅辙。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容

  • 一 感悟 1.舉著個(gè)人主義的大旗阎姥,宣揚(yáng)著市場經(jīng)濟(jì)记舆,維護(hù)著利己主義,雖然看起來不夠崇高呼巴,但絕對符合人性 2.別對人逼...
    職場成長菌閱讀 572評論 0 2
  • 一個(gè)夢泽腮,兩個(gè)夢泊愧。輪回。 一首歌盛正,兩首歌删咱。循環(huán)。 從《師說》至你反復(fù)宣稱我是你的老師止豪筝,我從應(yīng)答至沉默痰滋。 自,我续崖,你...
    前方是什么閱讀 208評論 0 8
  • ??本文內(nèi)容主要介紹EL表達(dá)式敲街、JSP標(biāo)準(zhǔn)標(biāo)簽庫(JSTL)、JSP自定義標(biāo)簽庫严望。其中拿EL表達(dá)式和JSP技術(shù)做對...
    secondtown閱讀 1,421評論 0 0
  • 周末帶大寶去了動物園多艇。每次去的必看項(xiàng)目就是馬戲表演。高難度的雜技表演像吻,動感的音樂峻黍,萌萌的動物,讓人歡呼拨匆、雀躍...
    丹那閱讀 317評論 0 2