存档

2016年7月 的存档

MacOS的菜单状态栏App添加饼型进度

2016年7月30日 没有评论

猴子原创,欢迎转载。转载请注明: 转载自Cocos2Der-CSDN,谢谢!
原文地址: http://blog.csdn.net/cocos2der/article/details/52075418

使用swift如何开发一个MacOS的状态栏App,上一篇已经讲了。里面我忘记提如何修改状态icon为饼型进度。比如App在处理什么事情的时候,可以添加进度状态提示用户。如下图所示:
MacOS的菜单状态栏App添加饼型进度

/// 显示状态栏菜单饼型进度
    private func showStatusItemProgress() {
        if let button = statusItem.button {
            // FIXME: it works, but obviously not good.
            button.subviews.removeAll()
        }
        if let button = statusItem.button {
            // FIXME: it works, but obviously not good.
            let frame = NSRect(x: 6, y: 2, width: 18, height: 18)
            let progressIndicator = NSProgressIndicator(frame: frame)
            progressIndicator.style = .SpinningStyle
            progressIndicator.indeterminate = false
            progressIndicator.minValue = 0
            progressIndicator.maxValue = 100
            progressIndicator.doubleValue = 0
            self.progressIndicator = progressIndicator

            // 当添加进度后,发现状态栏frame大小错误了,没找到解决办法,但是填充一个图片可以解决这个尺寸错误问题
            statusItem.image = NSImage(named: "EmptyIcon")
            statusItem.image?.template = true
            button.addSubview(progressIndicator)
        }
    }

请注意,
– 我们是把一个NSProgressIndicator添加到了NSStatusItem的button视图上,不要添加到view视图上,如果添加到view上,view会挡住状态栏点击事件,这样NSStatusItem会不能响应用户点击了。(当然,如果你app恰好不需要用户点击,可以这样做)
– 你应该留意到了,我在NSStatusItem的image里放了一张透明图片,因为这了是为了解决它frame大小错误的问题

当然,如果你知道如何解决的话,可以告诉我下。哈哈。

分类: 未分类 标签:

使用Swift开发一个MacOS的菜单状态栏App

2016年7月28日 没有评论

猴子原创,欢迎转载。转载请注明: 转载自Cocos2Der-CSDN,谢谢!
原文地址: http://blog.csdn.net/cocos2der/article/details/52054107

这两天突然想看看OSX下的App开发,看了几篇文章。下面这一篇我觉得入门是非常好的。我仅转述为中文,并非原文翻译。原文地址:http://footle.org/WeatherBar/

下面开始介绍如何使用Swift开发一个Mac Menu Bar(Status Bar) App。通过做一个简单的天气app。天气数据来源于OpenWeatherMap

完成后的效果如下:
使用Swift开发一个MacOS的菜单状态栏App

一、开始建立工程

打开Xcode,Create a New Project or File ⟶ New ⟶ Project ⟶ Application ⟶ Cocoa Application ( OS X 这一栏)。点击下一步。
使用Swift开发一个MacOS的菜单状态栏App

二、开始代码工作

  1. 打开MainMenu.xib,删除默认的windows和menu菜单。因为我们是状态栏app,不需要菜单栏,不需要主窗口。
    使用Swift开发一个MacOS的菜单状态栏App

  2. 添加一个Menu菜单
    使用Swift开发一个MacOS的菜单状态栏App
    删除其中默认的2个子菜单选项,仅保留1个。并将保留的这个改名为“Quit”。

  3. 打开双视图绑定Outlet

    • 将Menu Outlet到AppDelegate,命名为statusMenu
      使用Swift开发一个MacOS的菜单状态栏App

    • 将子菜单Quit绑定Action到AppDelegate,命名为quitClicked
      使用Swift开发一个MacOS的菜单状态栏App

    • 你可以删除 @IBOutlet weak var window: NSWindow! ,这个app中用不上。

  4. 代码

    • 在AppDelegate.swift中statusMenu下方添加

      let statusItem = NSStatusBar.systemStatusBar().statusItemWithLength(NSVariableStatusItemLength)
    • applicationDidFinishLaunching函数中添加:

      statusItem.title = "WeatherBar"
      statusItem.menu = statusMenu
    • 在quitClicked中添加:

      NSApplication.sharedApplication().terminate(self)
    • 此时你的代码应该如下:

import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    @IBOutlet weak var statusMenu: NSMenu!

    let statusItem = NSStatusBar.systemStatusBar().statusItemWithLength(NSVariableStatusItemLength)

    @IBAction func quitClicked(sender: NSMenuItem) {
        NSApplication.sharedApplication().terminate(self)
    }

    func applicationDidFinishLaunching(aNotification: NSNotification) {
        statusItem.title = "WeatherBar"
        statusItem.menu = statusMenu
    }

    func applicationWillTerminate(aNotification: NSNotification) {
        // Insert code here to tear down your application
    }

}

运行,你可以看到一个状态栏了。

三、进阶一步,让App变得更好

你应该注意到了,当你运行后,底部Dock栏里出现了一个App启动的Icon。但实际上我们也不需要这个启动icon,打开Info,添加 “Application is agent (UIElement)”为YES。
使用Swift开发一个MacOS的菜单状态栏App

运行一下,不会出现dock启动icon了。

四、添加状态栏Icon

状态栏icon尺寸请使用18×18使用Swift开发一个MacOS的菜单状态栏App, 36×36(@2x)使用Swift开发一个MacOS的菜单状态栏App, 54×54(@3x),添加这1x和2x两张图到Assets.xcassets中。
使用Swift开发一个MacOS的菜单状态栏App

在applicationDidFinishLaunching中,修改为如下:

let icon = NSImage(named: "statusIcon")
icon?.template = true // best for dark mode
statusItem.image = icon
statusItem.menu = statusMenu

运行一下,你应该看到状态栏icon了。

五、重构下代码

如果我们进一步写下去,你会发现大量代码在AppDelegate中,我们不希望这样。下面我们为Menu创建一个Controller来管理。

  • 新建一个NSObject的StatusMenuController.swift, File ⟶ New File ⟶ OS X Source ⟶ Cocoa Class ⟶ Next
    使用Swift开发一个MacOS的菜单状态栏App

代码如下:

// StatusMenuController.swift

import Cocoa

class StatusMenuController: NSObject {
    @IBOutlet weak var statusMenu: NSMenu!

    let statusItem = NSStatusBar.systemStatusBar().statusItemWithLength(NSVariableStatusItemLength)

    override func awakeFromNib() {
        let icon = NSImage(named: "statusIcon")
        icon?.template = true // best for dark mode
        statusItem.image = icon
        statusItem.menu = statusMenu
    }

    @IBAction func quitClicked(sender: NSMenuItem) {
        NSApplication.sharedApplication().terminate(self)
    }
}
  • 还原AppDelegate,修改为如下:
// AppDelegate.swift

import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
    func applicationDidFinishLaunching(aNotification: NSNotification) {
        // Insert code here to initialize your application
    }
    func applicationWillTerminate(aNotification: NSNotification) {
        // Insert code here to tear down your application
    }
}

注意,因为删除了AppDelegate中的Outlet注册,所以你需要重新连Outlet,但在这之前我们需要先做一件事。(你可以试试连接StatusMenuController中的Outlet,看看会怎么样?)

  • 打开MainMenu.xib,添加一个Object。
    使用Swift开发一个MacOS的菜单状态栏App
    将该Object的Class指定为StatusMenuController
    使用Swift开发一个MacOS的菜单状态栏App
    重建Outlet到StatusMenuController,注意删除之前连接到AppDelegate的Outlet
    使用Swift开发一个MacOS的菜单状态栏App

当MainMenu.xib被初始化的时候,StatusMenuController下的awakeFromNib将会被执行,所以我们在里面做初始化工作。

运行一下,保证你全部正常工作了。

六、天气Api

我们使用 OpenWeatherMap的天气数据,所以你得注册一个账号,获取到免费的API Key。

  • 添加WeatherAPI.swift, File ⟶ New File ⟶ OS X Source ⟶ Swift File ⟶ WeatherAPI.swift,加入如下代码,并使用你自己的API Key。
import Foundation

class WeatherAPI {
    let API_KEY = "your-api-key-here"
    let BASE_URL = "http://api.openweathermap.org/data/2.5/weather"

    func fetchWeather(query: String) {
        let session = NSURLSession.sharedSession()
        // url-escape the query string we're passed
        let escapedQuery = query.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())
        let url = NSURL(string: "/(BASE_URL)?APPID=/(API_KEY)&units=imperial&q=/(escapedQuery!)")
        let task = session.dataTaskWithURL(url!) { data, response, err in
            // first check for a hard error
            if let error = err {
                NSLog("weather api error: /(error)")
            }

            // then check the response code
            if let httpResponse = response as? NSHTTPURLResponse {
                switch httpResponse.statusCode {
                case 200: // all good!
                    let dataString = NSString(data: data!, encoding: NSUTF8StringEncoding) as! String
                    NSLog(dataString)
                case 401: // unauthorized
                    NSLog("weather api returned an 'unauthorized' response. Did you set your API key?")
                default:
                    NSLog("weather api returned response: %d %@", httpResponse.statusCode, NSHTTPURLResponse.localizedStringForStatusCode(httpResponse.statusCode))
                }
            }
        }
        task.resume()
    }
}
  • 添加一个Update子菜单到Status Menu。
    使用Swift开发一个MacOS的菜单状态栏App
    绑定Action到StatusMenuController.swift,取名为updateClicked

  • 开始使用WeatherAPI, 在StatusMenuController中let statusItem下面加入:
    let weatherAPI = WeatherAPI(),
    在updateClicked中加入:
    weatherAPI.fetchWeather("Seattle")

注意OSX 10.11之后请添加NSAppTransportSecurity,保证http能使用。

运行一下,然后点击Update菜单。你会收到一个json格式的天气数据。

  • 我们再调整下StatusMenuController代码, 添加一个updateWeather函数,修改后如下:
import Cocoa

class StatusMenuController: NSObject {
    @IBOutlet weak var statusMenu: NSMenu!

    let statusItem = NSStatusBar.systemStatusBar().statusItemWithLength(NSVariableStatusItemLength)
    let weatherAPI = WeatherAPI()

    override func awakeFromNib() {
        statusItem.menu = statusMenu
        let icon = NSImage(named: "statusIcon")
        icon?.template = true // best for dark mode
        statusItem.image = icon
        statusItem.menu = statusMenu

        updateWeather()
    }

    func updateWeather() {
        weatherAPI.fetchWeather("Seattle")
    }

    @IBAction func updateClicked(sender: NSMenuItem) {
        updateWeather()
    }

    @IBAction func quitClicked(sender: NSMenuItem) {
        NSApplication.sharedApplication().terminate(self)
    }
}

七、解析Json

你可以使用 SwiftyJSON,但本次我们先不使用第三方库。我们得到的天气数据如下:

{
    "coord": {
        "lon": -122.33,
        "lat": 47.61
    },
    "weather": [{
        "id": 800,
        "main": "Clear",
        "description": "sky is clear",
        "icon": "01n"
    }],
    "base": "cmc stations",
    "main": {
        "temp": 57.45,
        "pressure": 1018,
        "humidity": 59,
        "temp_min": 53.6,
        "temp_max": 62.6
    },
    "wind": {
        "speed": 2.61,
        "deg": 19.5018
    },
    "clouds": {
        "all": 1
    },
    "dt": 1444623405,
    "sys": {
        "type": 1,
        "id": 2949,
        "message": 0.0065,
        "country": "US",
        "sunrise": 1444659833,
        "sunset": 1444699609
    },
    "id": 5809844,
    "name": "Seattle",
    "cod": 200
}
  • 在WeatherAPI.swift添加天气结构体用于解析son
struct Weather {
    var city: String
    var currentTemp: Float
    var conditions: String
}
  • 解析son
 func weatherFromJSONData(data: NSData) -> Weather? {
        typealias JSONDict = [String:AnyObject]
        let json : JSONDict

        do {
            json = try NSJSONSerialization.JSONObjectWithData(data, options: []) as! JSONDict
        } catch {
            NSLog("JSON parsing failed: /(error)")
            return nil
        }

        var mainDict = json["main"] as! JSONDict
        var weatherList = json["weather"] as! [JSONDict]
        var weatherDict = weatherList[0]

        let weather = Weather(
            city: json["name"] as! String,
            currentTemp: mainDict["temp"] as! Float,
            conditions: weatherDict["main"] as! String
        )

        return weather
    }
  • 修改fetchWeather函数去调用weatherFromJSONData
let task = session.dataTaskWithURL(url!) { data, response, error in
        // first check for a hard error
    if let error = err {
        NSLog("weather api error: /(error)")
    }

    // then check the response code
    if let httpResponse = response as? NSHTTPURLResponse {
        switch httpResponse.statusCode {
        case 200: // all good!
            if let weather = self.weatherFromJSONData(data!) {
                NSLog("/(weather)")
            }
        case 401: // unauthorized
            NSLog("weather api returned an 'unauthorized' response. Did you set your API key?")
        default:
            NSLog("weather api returned response: %d %@", httpResponse.statusCode, NSHTTPURLResponse.localizedStringForStatusCode(httpResponse.statusCode))
        }
    }
}

如果此时你运行,你会收到

2016-07-28 11:25:08.457 WeatherBar[49688:1998824] Optional(WeatherBar.Weather(city: "Seattle", currentTemp: 51.6, conditions: "Clouds"))
  • 给Weather结构体添加一个description
struct Weather: CustomStringConvertible {
    var city: String
    var currentTemp: Float
    var conditions: String

    var description: String {
        return "/(city): /(currentTemp)F and /(conditions)"
    }
}

再运行试试。

八、Weather用到Controller中

  • 在 WeatherAPI.swift中增加delegate协议
protocol WeatherAPIDelegate {
    func weatherDidUpdate(weather: Weather)
}
  • 声明var delegate: WeatherAPIDelegate?

  • 添加初始化

init(delegate: WeatherAPIDelegate) {
    self.delegate = delegate
}
  • 修改fetchWeather
let task = session.dataTaskWithURL(url!) { data, response, error in
    // first check for a hard error
    if let error = err {
        NSLog("weather api error: /(error)")
    }

    // then check the response code
    if let httpResponse = response as? NSHTTPURLResponse {
        switch httpResponse.statusCode {
        case 200: // all good!
            if let weather = self.weatherFromJSONData(data!) {
                self.delegate?.weatherDidUpdate(weather)
            }
        case 401: // unauthorized
            NSLog("weather api returned an 'unauthorized' response. Did you set your API key?")
        default:
            NSLog("weather api returned response: %d %@", httpResponse.statusCode, NSHTTPURLResponse.localizedStringForStatusCode(httpResponse.statusCode))
        }
    }
}
  • StatusMenuController添加WeatherAPIDelegate
class StatusMenuController: NSObject, WeatherAPIDelegate {
...
  var weatherAPI: WeatherAPI!

  override func awakeFromNib() {
    ...
    weatherAPI = WeatherAPI(delegate: self)
    updateWeather()
  }
  ...
  func weatherDidUpdate(weather: Weather) {
    NSLog(weather.description)
  }
  ...
  • Callback实现,修改WeatherAPI.swift中fetchWeather:
    func fetchWeather(query: String, success: (Weather) -> Void) {
    修改fetchWeather内容
let task = session.dataTaskWithURL(url!) { data, response, error in
    // first check for a hard error
    if let error = err {
        NSLog("weather api error: /(error)")
    }

    // then check the response code
    if let httpResponse = response as? NSHTTPURLResponse {
        switch httpResponse.statusCode {
        case 200: // all good!
            if let weather = self.weatherFromJSONData(data!) {
                success(weather)
            }
        case 401: // unauthorized
            NSLog("weather api returned an 'unauthorized' response. Did you set your API key?")
        default:
            NSLog("weather api returned response: %d %@", httpResponse.statusCode, NSHTTPURLResponse.localizedStringForStatusCode(httpResponse.statusCode))
        }
    }
}
  • 在controller中
func updateWeather() {
    weatherAPI.fetchWeather("Seattle, WA") { weather in
        NSLog(weather.description)
    }
}

运行一下,确保都正常。

九、显示天气

在MainMenu.xib中添加子菜单 “Weather”(你可以添加2个Separator Menu Item用于子菜单分割线)
使用Swift开发一个MacOS的菜单状态栏App

在updateWeather中,替换NSLog:

if let weatherMenuItem = self.statusMenu.itemWithTitle("Weather") {
    weatherMenuItem.title = weather.description
}

运行一下,看看天气是不是显示出来了。

十、创建一个天气视图

打开MainMenu.xib,拖一个Custom View进来。

  • 拖一个Image View到Custom View中,设置ImageView宽高度为50。
    使用Swift开发一个MacOS的菜单状态栏App

  • 拖两个Label进来,分别为City和Temperature
    使用Swift开发一个MacOS的菜单状态栏App

  • 创建一个名为WeatherView的NSView,New File ⟶ OS X Source ⟶ Cocoa Class
    在MainMenu.xib中,将Custom View的Class指定为WeatherView
    使用Swift开发一个MacOS的菜单状态栏App

  • 绑定WeatherView Outlet:

import Cocoa

class WeatherView: NSView {
    @IBOutlet weak var imageView: NSImageView!
    @IBOutlet weak var cityTextField: NSTextField!
    @IBOutlet weak var currentConditionsTextField: NSTextField!
}

并添加update:

func update(weather: Weather) {
    // do UI updates on the main thread
    dispatch_async(dispatch_get_main_queue()) {
        self.cityTextField.stringValue = weather.city
        self.currentConditionsTextField.stringValue = "/(Int(weather.currentTemp))°F and /(weather.conditions)"
        self.imageView.image = NSImage(named: weather.icon)
    }
}

注意这里使用dispatch_async调用UI线程来刷新UI,因为后面调用此函数的数据来源于网络请求子线程。

  • StatusMenuController添加weatherView outlet
class StatusMenuController: NSObject {
    @IBOutlet weak var statusMenu: NSMenu!
    @IBOutlet weak var weatherView: WeatherView!
    var weatherMenuItem: NSMenuItem!
    ...
  • 子菜单Weather绑定到视图
weatherMenuItem = statusMenu.itemWithTitle("Weather")
weatherMenuItem.view = weatherView
  • update中:
func updateWeather() {
    weatherAPI.fetchWeather("Seattle, WA") { weather in
        self.weatherView.update(weather)
    }
}

运行一下。

十一、添加天气图片

先添加天气素材到Xcode,天气素材可以在http://openweathermap.org/weather-conditions 这里找到。这里我已经提供了一份icon zip, 解压后放Xcode。
使用Swift开发一个MacOS的菜单状态栏App

  • WeatherAPI.swift的Weather struct中,添加 var icon: String

  • 在weatherFromJSONData中:

let weather = Weather(
    city: json["name"] as! String,
    currentTemp: mainDict["temp"] as! Float,
    conditions: weatherDict["main"] as! String,
    icon: weatherDict["icon"] as! String
)
  • 在weatherFromJSONData:
let weather = Weather(
    city: json["name"] as! String,
    currentTemp: mainDict["temp"] as! Float,
    conditions: weatherDict["main"] as! String,
    icon: weatherDict["icon"] as! String
)
  • 在WeatherView的update中:
imageView.image = NSImage(named: weather.icon)

运行一下,Pretty!

使用Swift开发一个MacOS的菜单状态栏App

十二、添加设置

在MainMenu.xib MenuItem中,添加一个Menu Item命名为“Preferences…”
并绑定action,命名为“preferencesClicked”

  • 添加NSWindowController命名为PreferencesWindow.swift New ⟶ File ⟶ OS X Source ⟶ Cocoa Class , 勾选同时创建XIB.在XIB中添加Label和Text Field。效果如下:
    使用Swift开发一个MacOS的菜单状态栏App

Outlet cityTextField到PreferencesWindow.swift

  • 在PreferencesWindow.swift中添加:
override var windowNibName : String! {
    return "PreferencesWindow"
}
  • windowDidLoad()中修改:
self.window?.center()
self.window?.makeKeyAndOrderFront(nil)
NSApp.activateIgnoringOtherApps(true)
  • 最终PreferencesWindow.swift如下:
import Cocoa

class PreferencesWindow: NSWindowController {
    @IBOutlet weak var cityTextField: NSTextField!

    override var windowNibName : String! {
        return "PreferencesWindow"
    }

    override func windowDidLoad() {
        super.windowDidLoad()

        self.window?.center()
        self.window?.makeKeyAndOrderFront(nil)
        NSApp.activateIgnoringOtherApps(true)
    }
}
  • StatusMenuController.swift中添加preferencesWindow
    var preferencesWindow: PreferencesWindow!

  • awakeFromNib中,注意在updateWeather()之前:
    preferencesWindow = PreferencesWindow()

  • preferencesClicked中:
    preferencesWindow.showWindow(nil)

  • 下面为 preferences window 添加NSWindowDelegate,刷新视图。
    class PreferencesWindow: NSWindowController, NSWindowDelegate {
    并增加

func windowWillClose(notification: NSNotification) {
    let defaults = NSUserDefaults.standardUserDefaults()
    defaults.setValue(cityTextField.stringValue, forKey: "city")
}

增加协议:

protocol PreferencesWindowDelegate {
    func preferencesDidUpdate()
}

增加delegate:

var delegate: PreferencesWindowDelegate?

在windowWillClose最下面调用

delegate?.preferencesDidUpdate()
  • 回到StatusMenuController中,添加PreferencesWindowDelegate
class StatusMenuController: NSObject, PreferencesWindowDelegate {

实现代理:

func preferencesDidUpdate() {
    updateWeather()
}

awakeFromNib中:

preferencesWindow = PreferencesWindow()
preferencesWindow.delegate = self
  • 在StatusMenuController中增加默认城市
    let DEFAULT_CITY = “Seattle, WA”

  • 修改updateWeather

func updateWeather() {
    let defaults = NSUserDefaults.standardUserDefaults()
    let city = defaults.stringForKey("city") ?? DEFAULT_CITY
    weatherAPI.fetchWeather(city) { weather in
        self.weatherView.update(weather)
    }
}
  • 咱们也可以在PreferencesWindow.swift windowDidLoad中设置city默认值
let defaults = NSUserDefaults.standardUserDefaults()
let city = defaults.stringForKey("city") ?? DEFAULT_CITY
cityTextField.stringValue = city

运行。一切OK。

其他:
– 你也可以试试使用NSRunLoop.mainRunLoop().addTimer(refreshTimer!, forMode: NSRunLoopCommonModes) 来定时updateWeather.
– 试试点击天气后跳转到天气中心 NSWorkspace.sharedWorkspace().openURL(url: NSURL))
– 完整工程: WeatherBar

分类: 未分类 标签:

Swift中实现Observable机制

2016年7月15日 没有评论

猴子原创,欢迎转载。转载请注明: 转载自Cocos2Der-CSDN,谢谢!
原文地址: http://blog.csdn.net/cocos2der/article/details/51917539

今天给别人讲个Observable的实现和使用场景,结合Observable-Swift github: https://github.com/slazyk/Observable-Swift 讲了半天貌似还没有特别明白,故写了个简易的实现,讲述了下Observable属性监控机制。

//: Playground - noun: a place where people can play

import UIKit
import Foundation

// MARK: - Observable
class Observable<T> {
    // 定义block结构
    typealias Observer = T -> Void

    // 申明一个block,用于数据改变的执行
    private var observer: Observer?

    // 数据发生变更,则通过observer告知
    var value: T {
        didSet {
            observer?(value)
        }
    }

    init(_ v: T) {
        value = v
    }

    func observe(observer: Observer?) {
        self.observer = observer
        observer?(value)
    }
}

// MARK: - People
struct PeopleModel {
    let firstName: Observable<String>
    let lastName: Observable<String>

    init(firstName: String, lastName: String) {
        self.firstName = Observable(firstName)
        self.lastName = Observable(lastName)
    }
}

// MARK: - Test

// test1
let people = PeopleModel(firstName: "sunny", lastName: "liu")
people.firstName.observe {
    newValue in
    print("firstName changed: /(newValue)")
}
people.lastName.observe {
    print("lastName changed: /($0)")
}
people.firstName.value = "sunny2"
people.lastName.value = "liu2"

// test2
class House {
    let lableHouseName =  UILabel()

    init() {

    }

    var people: PeopleModel? {
        didSet {
            people?.firstName.observe{
                [unowned self] in
                self.lableHouseName.text = $0
            }
        }
    }
}

这样貌似容易理解了,O(∩_∩)O哈哈~

分类: 未分类 标签:

[置顶] 继续加油~,用这一款工具帮助更多的Cocos3D团队。

2016年7月11日 没有评论

继续加油~,用这一款工具帮助更多的Cocos3D团队!

              花了一周多时间,完成了一款Cocos Mesh Viewer ,截止现在,终于算有一个凑合的功能版本可以用。

              下载地址:点击打开链接

              已经支持的功能:

             (1)打开任意FBX 转换为C3B文件。

             (2)打开C3B文件,并显示模型的相关信息(顶点数,面数,子模型数量,包围盒大小,骨骼数,当前帧数)。

             (3)显示线框模式,包围盒,骨骼树,隐模型。

             (4)显示骨骼清单,并可以在骨骼上绑定模型进行测试。

             (5)显示子模型清单,并可以从其它C3B中更换子模型,进行换装测试。

             (6)显示纹理清单,并可以提示未找到的贴图,点击贴图名称,显示贴图。

             (7)调节模型大小。

             (8)调节动作播放速度。

              

             对于使用Cocos开发3D项目,我觉得首先一定要有一个功能强大,而使用方便的Mesh Viewer。

            

             怎么样?有没有想试试!

  [置顶]        继续加油~,用这一款工具帮助更多的Cocos3D团队。

[置顶]        继续加油~,用这一款工具帮助更多的Cocos3D团队。

[置顶]        继续加油~,用这一款工具帮助更多的Cocos3D团队。

[置顶]        继续加油~,用这一款工具帮助更多的Cocos3D团队。

[置顶]        继续加油~,用这一款工具帮助更多的Cocos3D团队。

[置顶]        继续加油~,用这一款工具帮助更多的Cocos3D团队。

[置顶]        继续加油~,用这一款工具帮助更多的Cocos3D团队。

[置顶]        继续加油~,用这一款工具帮助更多的Cocos3D团队。

[置顶]        继续加油~,用这一款工具帮助更多的Cocos3D团队。

[置顶]        继续加油~,用这一款工具帮助更多的Cocos3D团队。

分类: 未分类 标签:

[置顶] Cocos开发VR菜鸟宝典 第八讲:为GearVR开发一款深海捕鱼VR游戏

2016年7月7日 没有评论

火云开发课堂开讲啦!

Cocos开发VR菜鸟宝典

        

                  本套课程分为基础班和高级班两种,基础班主要在CSDN上推出视频,学员自学为主。高级班在此基础上再进行项目实训(包含Cocos3D,Shader基础班和VR设备学习套装)

有兴趣参加高级班的可以加我QQ:285421210.


                 一不小心,就又到最后一节课了~,加油!!!

第八章:为GearVR开发一款深海捕鱼VR游戏


视频地址:http://edu.csdn.net/course/detail/2366/36776?auto_start=1


[置顶]        Cocos开发VR菜鸟宝典 第八讲:为GearVR开发一款深海捕鱼VR游戏

1.准备GearVR和三星手机

[置顶]        Cocos开发VR菜鸟宝典 第八讲:为GearVR开发一款深海捕鱼VR游戏

2.登录Oculus

[置顶]        Cocos开发VR菜鸟宝典 第八讲:为GearVR开发一款深海捕鱼VR游戏

[置顶]        Cocos开发VR菜鸟宝典 第八讲:为GearVR开发一款深海捕鱼VR游戏

3.下载ADB工具,打印手机的设备号,通过Oculus下载签名文件。

[置顶]        Cocos开发VR菜鸟宝典 第八讲:为GearVR开发一款深海捕鱼VR游戏

[置顶]        Cocos开发VR菜鸟宝典 第八讲:为GearVR开发一款深海捕鱼VR游戏


4.准备模型资源

[置顶]        Cocos开发VR菜鸟宝典 第八讲:为GearVR开发一款深海捕鱼VR游戏

5.工程讲解和运行

[置顶]        Cocos开发VR菜鸟宝典 第八讲:为GearVR开发一款深海捕鱼VR游戏



[置顶]        Cocos开发VR菜鸟宝典 第八讲:为GearVR开发一款深海捕鱼VR游戏


   

分类: 未分类 标签:

[置顶] 使用CocosMeshViewer来转换和观察Cocos模型

2016年7月5日 没有评论

                前言:使用Cocos来开发3D和VR的基础课程即将结束,为了更好的帮助Cocos程序员学习和掌握使用Cocos开发3D和VR的方法,红孩儿课堂特推出学习套餐:


[置顶]        使用CocosMeshViewer来转换和观察Cocos模型

有兴趣的同学可以到CSDN视频学院购买学习:http://edu.csdn.net/combo/detail/195

另外有参加高级班的可以加我 QQ:285421210.

 

             为了好上加好的帮助Cocos程序员开发项目,我们也会陆续放出各种工具来帮助大家开发哦!本节课程即为讲解一下我们为大家提供的免费的Cocos模型转换和观察器CocosMeshViewer.

         

         使用CocosMeshViewer来转换和观察Cocos模型


         我们在使用Cocos来开发3D项目时,经常会觉得控制台操作FBX -> C3B这个转换很麻烦,而且想看一下C3B文件是否正确也需要开启工程进行查看。能不能有更方便的方式来进行相关处理呢?


         当然!我们为大家提供了一款免费小工具CocosMeshViewer . 它可以方便的帮我们把FBX文件转换成C3B,并且进行查看。下面我们来学习下。


         首先我们可以到任意一个"红孩儿Cocos2dx交流群”去查看群共享(比如 44208467, 275220292等,找到CocosMeshViewer,然后下载下来,解压后打开,如图:

[置顶]        使用CocosMeshViewer来转换和观察Cocos模型  

        然后我们双击“CocosMeshViewer.exe".启动程序.

[置顶]        使用CocosMeshViewer来转换和观察Cocos模型


        可以看到,程序启动后,会显示一个网格,上面有一个按钮。

点击它,就可以在我们电脑上查找相应的FBX或C3B文件进行查看。

        首先,我们来查看一个res目录中的C3B文件。

[置顶]        使用CocosMeshViewer来转换和观察Cocos模型

     点击“打开”之后,模型就显示在网格中央了,也就是位置(0,0,0)点。

      我们可以按着键盘W键离近点观看。

[置顶]        使用CocosMeshViewer来转换和观察Cocos模型

          我们可以看到,在上方还有一些模型的信息进行显示,特别是可以通过滑块对模型进行缩放和动作速度调节,是不是很方便?

 

          当美术用3dsMax做好一个模型并导出成FBX后,转换为C3B是必须要做的工作,手动命令行方式非常麻烦,我们则可以直接在这里通过打开一个FBX来进行转换。下面,我们试着打开其它目录的一个FBX文件。

[置顶]        使用CocosMeshViewer来转换和观察Cocos模型


             打开FBX文件时,它会调用fbx-conv.exe来进行转换,并将转换后的C3B和纹理拷到res中。

      [置顶]        使用CocosMeshViewer来转换和观察Cocos模型

            同时显示在网格中央。

[置顶]        使用CocosMeshViewer来转换和观察Cocos模型


         好了,虽然这个工具很小,但是…它的确很方便,不是么?


           


分类: 未分类 标签: