ui组件也许是最令人着迷的部分。这部分最复杂的要数文字排版系统,比较重要的部分分别是属性集部件,信号槽部件,布局系统。相对复杂的部分是图片顶点数据拼装,和系统事件处理。

仓库:https://bitbucket.org/mm_longcheng/mm-vulkan

扣扣交流群:554329899

一、统一布局坐标系

为了可以适配动态变化的窗体大小,我参考了cegui的“The Unified Co-ordinate System”。它使用两个量来表达一个维度(offset, scale)。offset代表标量,scale代表给予父节点的附加量。当我们定位一个距离右边缘10单位的位置时,就可以使用(-10, 1)来表示。当父窗口的大小发生变动时可以自适应调整。

对于移动设备的屏幕适配也同样好用。

屏幕适配方案

类似unity的自动适配,我们会以设计宽高为基准设计ui布局,在实际设备上产生基于相对最小边的部分不动,执行等宽高缩放,长边会拓宽到实际像素。

举个例子:

Window ----------------------------+----------------------------------
Window                  pWindowName: org.mm.nwsi.vkApp
Window              hDisplayDensity: 2.750000
Window            hDisplayFrameSize: (1080.00, 1920.00)
Window               hDesignDensity: 2.000000
Window             hAbsoluteDensity: 1.000000
Window            hDesignCanvasSize: (720.00, 1280.00)
Window            hPhysicalViewSize: (392.73, 698.18)
Window            hPhysicalSafeRect: (0.00, 0.00, 392.73, 698.18)
Window            hActuallyViewSize: (720.00, 1280.00)
Window            hActuallySafeRect: (0.00, 0.00, 720.00, 1280.00)
Window             hTransformCanvas: 1.833333
Window             hTransformWindow: 0.666667
Window         hViewSizeAspectRatio: 0.562500
Window         hSafeRectAspectRatio: 0.562500
Window ----------------------------+----------------------------------

hDisplayDensity      为px / pt 的比值,这个是从os层获取的。通常在视网膜屏上会大于1.
hDisplayFrameSize 这是全屏幕的像素px的宽高
hDesignDensity       设计的缩放比例,如目标屏幕pt宽高为360x640, 设计资源为720x1280,值为2
hAbsoluteDensity     这是自适应调整的最大阈值,通常是1
hDesignCanvasSize这是设计画布的宽高这里是720x1280
hPhysicalViewSize   这是实际屏幕的pt宽高
hPhysicalSafeRect   这是安全区的pt矩形位置
hActuallyViewSize    设计尺寸的ui逻辑尺寸,不完全与设计尺寸相等,部分设备高度会略大。
hActuallySafeRect    设计尺寸的安全区,在全面屏上会略微小于视图尺寸。

我们按720x1280为设计尺寸做布局,就可以在不同设备上保证相似的效果,部分设备下,逻辑高度会稍微高一点,通过统一坐标系统,我们就可以让相对大的屏幕呈现更多内容,自动适配。

安全区是为了ui不会被全面屏的缺角遮挡而设计的,我们的页面可以挂在在以安全区为基准的页面上就可以避免意外裁剪。安全区的数据我们通过nwsi系统,使用os原生接口获取。

二、视图对象

mmUIView是对标ios里UIView的的组件。它提供以下功能
1.拥有位置,缩放,选择参量
2.可以挂载子节点
3.拥有属性集,我们可以使用属性名字来设置视图的属性数值
4.信号槽,可以挂载事件处理函数,比如按钮的按下回调函数
5.纵横比模式,我们可以使用这个模式自适应调整基于父节点的宽高
6.视图裁剪,裁剪本视图携带的可绘制体和子视图,仅支持普通正交视图的裁剪
7.视图派生,和基于视图元数据的工厂注册。ui系统使用字符串构建具体控件能解耦代码。

如何派生一个视图

extern const struct mmMetaAllocator mmUIMetaAllocatorViewMaster;
extern const struct mmUIMetadata mmUIMetadataViewMaster;struct mmUIViewMaster
{struct mmUIView view;/* UIView weak reference. */struct mmUIView* MyImage;struct mmUIView* MyText;struct mmUIView* MyEditBox;struct mmUIView* MyButton;
};const struct mmMetaAllocator mmUIMetaAllocatorViewMaster =
{"mmUIViewMaster",sizeof(struct mmUIViewMaster),&mmUIViewMaster_Produce,&mmUIViewMaster_Recycle,
};const struct mmUIMetadata mmUIMetadataViewMaster =
{&mmUIMetaAllocatorViewMaster,/*- Widget -*/&mmUIWidgetOperableViewMaster,NULL,NULL,/*- Responder -*/NULL,NULL,NULL,NULL,
};void mmUIViewFactoryAddTypes(struct mmUIViewFactory* pViewFactory)
{/* other view type */mmUIViewFactory_AddType(pViewFactory, &mmUIViewMaster);
}void mmUIViewFactoryRmvTypes(struct mmUIViewFactory* pViewFactory)
{/* other view type */mmUIViewFactory_RmvType(pViewFactory, &mmUIViewMaster);
}

第一个对象必须是view,是作为主类继承的约定。同时,我们定义了相应的metadata。我们会把metadata注册进视图工厂,通过视图加载器,我们就可以使用"mmUIViewMaster"名字来创建派生视图对象。

如何给派生视图配置属性

// 代码方式配置
mmUIView_SetValueCStr(pView, "View.Anchor", "(0.5f, 0.0f, 0.0f)");
mmUIView_SetValueCStr(pView, "View.Size", "((183.0f, 0.0f), (200.0f, 0.0f), (0.0f, 0.0f))");
mmUIView_SetValueCStr(pView, "View.Position", "((0.0f, 0.0f), (90.0f, 0.0f), (0.0f, 0.0f))");
mmUIView_SetValueCStr(pView, "Drawable.Alignment", "(1, 1, 1)");
mmUIView_SetValueCStr(pView, "Drawable.AspectMode", "3");// 使用json配置文件
{"Type": "mmUIViewImage","Property":{"View.Name": "MyImage","View.Anchor": "(0.5f, 0.0f, 0.0f)","View.Size": "((183.0f, 0.0f), (200.0f, 0.0f), (0.0f, 0.0f))","View.Position": "((0.0f, 0.0f), (90.0f, 0.0f), (0.0f, 0.0f))","View.Alignment": "(1, 0, 0)","View.Clipping": "1","Drawable.Alignment": "(1, 1, 1)","Drawable.AspectMode": "3","Image.SheetName": "imagesets/Image_2.sheet","Image.FrameName": "gz_zhuangshi.png"}
}

由于我们有属性集系统,所以可以使用基类,通过属性名字来设置对应的对象参数。这种方法统一了属性设置接口,也便于做文件配置系统。

属性集的实现参看我的一篇文章组件:c语言版本事件集EventSet_mm_longcheng的专栏-CSDN博客

如何给控件挂接回调处理函数

void
mmUIViewMaster_OnPrepare(struct mmUIViewMaster*                         p)
{struct mmUIViewLoader* pViewLoader = p->view.context->loader;// 使用配置文件构建视图mmUIViewLoader_PrepareViewFromFile(pViewLoader,&p->view,"view/mmUIViewMaster.view.json");// 获取子控件的弱引用p->MyImage = mmUIView_GetChildByCStr(&p->view, "MyImage");p->MyText = mmUIView_GetChildByCStr(&p->view, "MyText");p->MyEditBox = mmUIView_GetChildByCStr(&p->view, "MyEditBox");p->MyButton = mmUIView_GetChildByCStr(&p->view, "MyButton");// 将一个按钮的处理函数注册进按钮的信号槽mmEventSet_SubscribeEvent(&p->MyButton->events,mmUIView_EventClicked,&mmUIViewMaster_OnEventClicked,p);
}

我们的信号槽可以按控件句柄好事件名字注册回调函数,注意需要在结束时解注册。

信号槽的实现可以参看我的一篇文章组件:c语言版本事件集EventSet_mm_longcheng的专栏-CSDN博客

三、ui可渲染对象

mmUIDrawable 保留了vulkan绘制需要的句柄,如管线和描述符。并且提供了对标unity(ImageType)的几种常用图片分解模式.
1.普通模式,就是直接将图片顶点数据分解为两个三角形
2.切片模式,这是九宫格切分方式,顶点数据按井字形切割
3.平铺模式,图片资源为单图非图集,可以采用平铺贴砖模式
4.画刷模式,对标unity的filled模式,在这个模式下,我们有三种填充方式

画刷模式的填充方式
1.线性方式,这个方式包含横向填充和纵向填充,对标Horizontal和Vertical
2.环形方式,对标unity的Radial360

顶点数据填充函数在mmUIQuad文件里面,想参考的可以看这个。

可渲染对象可配置的属性列表

    mmPropertyRemove(propertys, "Drawable.Amount");      // 画刷进度[0, 1]mmPropertyRemove(propertys, "Drawable.Opacity");     // 不透明度(r,g,b,a)mmPropertyRemove(propertys, "Drawable.Color");       // 叠加颜色(r,g,b,a)mmPropertyRemove(propertys, "Drawable.Flipped");     // 图片翻转(x,y)mmPropertyRemove(propertys, "Drawable.AspectMode");  // 纵横缩放模式mmPropertyRemove(propertys, "Drawable.Alignment");   // 对齐方式(x,y,z)mmPropertyRemove(propertys, "Drawable.ImageMode");   // 图片分解模式mmPropertyRemove(propertys, "Drawable.BrushMode");   // 画刷填充方式mmPropertyRemove(propertys, "Drawable.Direction");   // 画刷起点朝向(上下左右)mmPropertyRemove(propertys, "Drawable.Reverse");     // 画刷是否反向或逆时针mmPropertyRemove(propertys, "Drawable.PipelineName");// 管线名字mmPropertyRemove(propertys, "Drawable.PoolName");    // 描述符池

四、ui文字排版

文字排版的接口主要使用nwsi抽象的系统接口。这样有很多好处,首先我们无需管理大体积的字库资源,这在中文字库上尤其突出,并且不用关心字库缺字问题。但是可以使用的默认字体没办法调整,在不同系统上表现会略有不同。

mmTextLayout 是主要的部件。我们抽象的文字排版尽可能多的保留os层的可用参数,基本的字号,颜色,下划线,删除线,文字背景色等都是支持的,并且直接支持富文本。文字排版接口仅支持android,windows,ios和macos。

在静态文字的基础上,我们对接了os层的输入法事件,通过mmUIEditBox来管理当前游标位置。我们得到了一份可用的输入框控件。

文本具体参数可以看mmTextFormat,段落格式参数可以看mmTextParagraphFormat

文字组件可配置的属性列表

    /*- MasterFormat -*/mmPropertyRemove(propertys, "Text.MasterFontFamilyName"); // 字体名字mmPropertyRemove(propertys, "Text.MasterFontSize");       // 字号mmPropertyRemove(propertys, "Text.MasterFontStyle");      // 字体风格 黑体斜体mmPropertyRemove(propertys, "Text.MasterFontWeight");     // 字重400是普通mmPropertyRemove(propertys, "Text.MasterForegroundColor");// 背景颜色mmPropertyRemove(propertys, "Text.MasterBackgroundColor");// 字体颜色mmPropertyRemove(propertys, "Text.MasterStrokeWidth");    // 描边正数镂空负数附描边mmPropertyRemove(propertys, "Text.MasterStrokeColor");    // 描边颜色mmPropertyRemove(propertys, "Text.MasterUnderlineWidth"); // 下划线厚度mmPropertyRemove(propertys, "Text.MasterUnderlineColor"); // 下划线颜色mmPropertyRemove(propertys, "Text.MasterStrikeThruWidth");// 删除线厚度mmPropertyRemove(propertys, "Text.MasterStrikeThruColor");// 删除线颜色/*- ParagraphFormat -*/mmPropertyRemove(propertys, "Text.TextAlignment");        // 水平对齐方式mmPropertyRemove(propertys, "Text.ParagraphAlignment");   // 段落对齐方式mmPropertyRemove(propertys, "Text.LineBreakMode");        // 断行模式mmPropertyRemove(propertys, "Text.WritingDirection");     // 书写方向mmPropertyRemove(propertys, "Text.FirstLineHeadIndent");  // 首行缩进mmPropertyRemove(propertys, "Text.HeadIndent");           // 前置缩进mmPropertyRemove(propertys, "Text.TailIndent");           // 后置缩进mmPropertyRemove(propertys, "Text.LineSpacingAddition");  // 行距附加标量mmPropertyRemove(propertys, "Text.LineSpacingMultiple");  // 行距附加乘量mmPropertyRemove(propertys, "Text.ShadowOffset");         // 阴影偏移mmPropertyRemove(propertys, "Text.ShadowBlur");           // 阴影模糊半径mmPropertyRemove(propertys, "Text.ShadowColor");          // 阴影颜色mmPropertyRemove(propertys, "Text.LineCap");              // 线封口模式mmPropertyRemove(propertys, "Text.LineJoin");             // 线连接模式mmPropertyRemove(propertys, "Text.LineMiterLimit");       // 折线阈值mmPropertyRemove(propertys, "Text.WindowSize");           // 文本宽高mmPropertyRemove(propertys, "Text.LayoutRect");           // 布局区域mmPropertyRemove(propertys, "Text.DisplayDensity");       // 缩放比例/*- EditBox -*/mmPropertyRemove(propertys, "Text.CaretIndex");           // 当前游标mmPropertyRemove(propertys, "Text.Selection");            // 当前选中位置mmPropertyRemove(propertys, "Text.CaretWrapping");        // 右边是否处于换行位置mmPropertyRemove(propertys, "Text.CaretStatus");          // 光标是否显示mmPropertyRemove(propertys, "Text.SelectionStatus");      // 是否高亮显示选中文本mmPropertyRemove(propertys, "Text.CaretWidth");           // 光标宽mmPropertyRemove(propertys, "Text.CaretColor");           // 光标颜色mmPropertyRemove(propertys, "Text.SelectionCaptureColor");// 高亮获取焦点颜色mmPropertyRemove(propertys, "Text.SelectionReleaseColor");// 高亮失去焦点颜色/*- Text -*/mmPropertyRemove(propertys, "Text.String");               // 文本(utf16格式)

五、ui基础控件

实际上我的ui库基础控件只有四种
1.图片      mmUIViewImage   图片可以使用图集资源,也可以使用单图资源
2.文本      mmUIViewText      文本通常为静态文本,不可编辑
3.输入框  mmUIViewEditBox 输入框在文本的基础上对接了输入法事件处理,可以进行编辑
4.按钮      mmUIViewButton   按钮有五种展现状态,普通,失活,悬停,按下,按下拖拽

图片控件,拥有的属性

    mmPropertyRemove(propertys, "Image.ImageName");  // 单图资源路径mmPropertyRemove(propertys, "Image.SheetName");  // 图集名字mmPropertyRemove(propertys, "Image.FrameName");  // 图集帧名字mmPropertyRemove(propertys, "Image.Frame");      // 单图资源的包围盒mmPropertyRemove(propertys, "Image.Rotated");    // 单图资源是否旋转mmPropertyRemove(propertys, "Image.Filter");     // 采样器筛选参数mmPropertyRemove(propertys, "Image.MipmapMode"); // 采样器mipmap模式mmPropertyRemove(propertys, "Image.AddressMode");// 采样器寻址方式mmPropertyRemove(propertys, "Image.BorderColor");// 采样器边缘颜色

页面层次管理

mmUIViewDirector 不是控件,它可以简单的管理页面关系,比如将mmUIViewRoot设置为根节点,并且在这个节点上挂载mmUIViewMaster作为第一个页面,可以使用名字构建:

    mmUIViewDirector_SetRootWindowFromType(&p->vViewDirector, "mmUIViewRoot", "mmUIViewRoot");mmUIViewDirector_SceneExclusiveForeground(&p->vViewDirector, "mmUIViewMaster", "mmUIViewMaster");

图片在视图中的对齐和缩放方式

图片有时候并不能将视图填满,那么我们需要相应的对齐和缩放方式。

对齐方式
1.mmUIAlignmentMinimum 按最小值为基准,对于x轴就是左对齐
2.mmUIAlignmentMiddled   中部对齐
3.mmUIAlignmentMaximum 按最大值为基准,对于x轴就是右对齐

缩放方式
1.mmUIAspectModeIgnore  忽略图片缩放
2.mmUIAspectModeShrink  缩小缩放,图片会尽量显示在视图中,并保持宽高比
3.mmUIAspectModeExpand 拓展缩放,图片会尽可能铺满视图,并保持快高比,会产生裁剪
4.mmUIAspectModeEntire    铺满缩放,图片宽高会直接拉伸到视图宽高,会产生变形

六、ui事件系统

os层会将鼠标,键盘,触点,输入法,帧更新等事件通过nwsi传过来。

mmUIViewContext 会得到首先得到事件,并使用HitTest得到第一响应链的处理者,之后事件会一次向父节点传递。不同的事件传递方式略有区别。

键盘事件

// Keypad content.
struct mmEventKeypad
{/* modifier mask */mmUInt32_t modifier_mask;/* Key code. */int key;/* Text length. */int length;/* Text buffer. */mmUInt16_t text[4];/* Return value.*     0 Need to handle keyboard event.*     1 Event has been processed.*/mmUInt32_t handle;
};

鼠标事件

struct mmEventCursor
{/* modifier mask */mmUInt32_t modifier_mask;/* button mask */mmUInt32_t button_mask;/* button id */mmUInt32_t button_id;/* Absolute position x */double abs_x;/* Absolute position y */double abs_y;/* Relative position x */double rel_x;/* Relative position y */double rel_y;/* wheel scrolling delta x */double wheel_dx;/* wheel scrolling delta y */double wheel_dy;/* The UTC time of this fix, in milliseconds since January 1, 1970.* The time (in ms) when event trigger.*/mmUInt64_t timestamp;/* Return value.*     0 Need to handle keyboard pop up.*     1 Event has been processed.*/mmUInt32_t handle;
};

触点事件

// Touch point.
struct mmEventTouch
{// Motion event weak ref.uintptr_t motion_id;// The number of times the finger was tapped for this given touch.int tap_count;// The phase of the touch.TouchPhase touch began, moved, ended, or was canceled.int phase;// modifier maskmmUInt32_t modifier_mask;// button maskmmUInt32_t button_mask;// Absolute position x.double abs_x;// Absolute position y.double abs_y;// Relative position x.double rel_x;// Relative position y.double rel_y;// The force of the touch, where a value of 1.0 represents the // force of an average touch (predetermined by the system, not user-specific).double force_value;// The maximum possible force for a touch.double force_maximum;// The major radius (in points) of the touch.double major_radius;// The minor radius (in points) of the touch.double minor_radius;// The area size value, (0, 1) an abstract metric.double size_value;// The UTC time of this fix, in milliseconds since January 1, 1970.// The time (in ms) when event trigger.mmUInt64_t timestamp;
};// Touch point set.
struct mmEventTouchs
{// The touch vector.struct mmVectorValue context;
};

输入法事件

// Text content data.
struct mmEventEditText
{// text utf16 character weak reference pointer.mmUInt16_t* t;// c string utf32 character size.size_t size;// c string utf32 character capacity.size_t capacity;// current cursor position.size_t c;// lift  Selection position.size_t l;// right Selection position.size_t r;// mmEventTextType.int v;
};// String content data.
struct mmEventEditString
{// string pointer.mmUInt16_t* s;// string lenght.size_t l;// Replace character offset. Replace API only.size_t o;// Replace character number. Replace API only.size_t n;
};

软键盘事件

struct mmEventKeypadStatus
{// The surface pointer.void* surface;// Layer://     screen <- window trigger window attach to screen.//     extern           extern screen brothers.//// Rect(x, y, w, h)double screen_rect[4];double safety_area[4];double keypad_rect[4];double window_rect[4];// Animation duration for this event.double animation_duration;// enum mmKeypadAnimationCurve.// Some time the value can be out of enum.int animation_curve;// Status type. mmSurfaceKeypadStatusType.mmUInt32_t state;// Return value.//     0 Need to handle keyboard occlusion.//     1 Event has been processed.mmUInt32_t handle;
};

系统视图窗口变化事件

// Surface metrics.
struct mmEventMetrics
{// The surface pointer.void* surface;// canvas size.//// Size(w, h)double canvas_size[2];// window size.//// Size(w, h)double window_size[2];// safety area.//// Rect(x, y, w, h)double safety_area[4];
};

帧更新事件

// Surface frame update.
struct mmEventUpdate
{// frame number.mmUInt64_t number;// average fps.double average;// index [0x00, 0x3F].mmUInt8_t index;// Time for frame interval, second(s).double interval;
};

用vulkan写个引擎 (三)ui组件相关推荐

  1. 用vulkan写个引擎 (二)vk组件

    这篇文章开始展开介绍工程的组织方式和组件模块.首先从vulkan组件开始.大部分文章都是把官网例子重复一遍,或是罗列接口说明,根本不足以用在生产环境. 注意,文章主要表述组件的功能和要点,和它们之间的 ...

  2. 用vulkan写个引擎 (一)综述

    https://zhuanlan.zhihu.com/p/466830308 自己写个游戏引擎,这是个有趣的工程实践,vulkan的设备覆盖率已经非常高了.android 7.0以上的设备占比75%左 ...

  3. 用vulkan写个引擎 (四)PBR着色器

    PBR全称(Physicallly-Based Rendering),基于物理的渲染.本文将提供一份GLSL实用型着色器.对于理论部分网络上已经有太多文章了. 仓库:https://bitbucket ...

  4. Chrome学习笔记(三):UI组件,皮肤引擎

    原创文章,转载请注明:转载自Soul Apogee 本文链接地址:Chrome学习笔记(三):UI组件,皮肤引擎 -- 控件库 这篇文章是接着上篇文章继续聊的,Chrome的代码实在太多,每一个东西单 ...

  5. Chrome学习笔记(二):UI组件,皮肤引擎

    原创文章,转载请注明:转载自Soul Apogee 本文链接地址:Chrome学习笔记(二):UI组件,皮肤引擎 -- 基础设施篇 Chrome的UI是很奇妙的,因为看起来能很好的跨平台,而且可以很好 ...

  6. android 界面组件,安卓开发学习周第三篇——Android中的UI组件

    原标题:安卓开发学习周第三篇--Android中的UI组件 在Android APP中,所有的用户界面元素都是由View和ViewGroup的对象构成的.View是绘制在屏幕上的用户能与之交互的一个对 ...

  7. [vue] 你有自己用vue写过UI组件库吗?

    [vue] 你有自己用vue写过UI组件库吗? {{item.title}}<dl v-if="item.list.length > 0"><dd v-fo ...

  8. 目前比较火的前端框架及UI组件

    看到的一篇总结性的文章,收藏一下,感兴趣的可以自己看看,哪些是已经会的,哪些是没听说过的,哪些是一知半解的,都可以稍微看看. 一.前端框架库: 1.Zepto.js 地址:点击打开链接 描述:Zept ...

  9. ueditor上传组件显示乱码_最全面的移动端 UI组件设计详解:中篇

    上一期给大家讲解了<最全面的移动端UI组件设计详解:上篇>,主要分享了:布局组件和导航组件2个部分:这次给大家带来:基础组件.表单组件和反馈组件详解,希望你在设计APP.小程序.H5页面中 ...

最新文章

  1. boolean类型_JS核心理论之《数据类型、类型转换、深浅拷贝与参数传递》
  2. 在JAVA语言程序中main_在Java程序main方法中,正确的参数是
  3. elasticsearch 问题
  4. IE6 Hack(转载)
  5. 如何获取jar包的在执行机上面的路径
  6. 常用模块(collections模块,时间模块,random模块,os模块,sys模块,序列化模块,re模块,hashlib模块,configparser模块,logging模块)...
  7. abaqus算出来的转角单位是什么_ABAQUS中的单位制是如何规定的;
  8. TFIDF的原理及实现
  9. 基尼系数,excel计算方法
  10. 《期权、期货及其他衍生产品》读书笔记(第二章:期货市场与中央交易对手)
  11. 虚拟机中安装配置Windows server 2003和iis6
  12. pyttsx3 语音包安装、使用详解
  13. 从国企到互联网,一个六年程序员的「得」与「失」
  14. RANSAC算法实现图像全景拼接
  15. kali渗透综合靶机(三)--bulldog2靶机
  16. 10-A. 在职研究生(多重继承)
  17. mysql server安装报错_安装VtigerCRM报错:MySQL Server should be configured with
  18. 使用Python爬虫爬取简单网页(Python爬虫入门)
  19. 上海市计算机学会-买二送一
  20. CAT客户端架构设计

热门文章

  1. Mapreduce源码分析(一):FileInputFormat切片机制,源码详解
  2. 主定理 - 算法导论摘录
  3. 针对报错 ValueError: When using data tensors as input to a model, you should specify the `steps_per_epoc
  4. 让IIS支持任意扩展名和未知扩展名的下载
  5. 回顾python-集合-day2
  6. FindBugs配置介绍
  7. discuz php接口文档,Discuz二次开发手册.doc
  8. 努力奋进:一个编程界小菜鸟的心里话
  9. 《魅魔succubus》 来自韩国3d建模师 yeonghee cho
  10. 计算机组成原理中01010110,计算机组成原理第二章教案.ppt