看了Ogitor的代碼後, 自己又實踐了一把, 結合N3中學到的一些技巧, 在編輯器中得到了驗證.
雖說做的是情境編輯器, 但是其它編輯器也可以用的, 畢竟思想都差不多.
對於一個編輯器, 通常是由一個個的"實體"組成, 或者叫"對象". 而"對象"又是由各種"屬性"所組成.
以情境編輯器為例, 我們通常會涉及以下操作:
- 刷地形, 刷紋理
- 擺模型, 設定模型參數
- 擺光源, 設定光源參數
- 擺特效/音效, 設定參數
- 擺NPC, 設定相應參數
- ...
可以看到, 除了地形之外, 其它的操作都差不多. 如果把地形把塊對待, 每個地形塊做為一個"對象", 高度和紋理編輯當成屬性編輯, 那麼上面都可以看成是同一種編輯方式了. 還有"擺"的這個操作, 其實本質上了也是對象的位置變換這個屬性的變化.
由此可以得出: 編輯器的一切操作都是屬性編輯
實體不用說了, 相信每個引擎都有Model/Light/Sound之類的對象類.
那麼怎麼去定義一個屬性呢?
簡單的來說, 一個屬性是一個<名稱, 值>的配對, 對象就是這些屬性的一個集合體. 以點光源為例, 它一般有這麼幾個屬性:
- 名稱. Light0
- 類型. PointLight
- 位置. (100, 100, 100)
- 範圍. 15
- 衰減. 1.0
- 顏色. 0xff00ff00
- .....
實際應用中我使用了FourCC代替String來索引屬性, 這樣可以用map<FourCC, Variant>做快速的訪問. 更進階的實現可以參見N3的Attribute模組.
下面說說使用屬性抽象的好處:
- 編輯操作
- 因為對象都是由屬性群組成的, 所以所有的編輯對象都可以抽象成一種, 那麼只需要實現一種編輯方式就可以適用於所有的對象
- 因為操作是與具體物件相依性不大, 所以擴充新的物件類型對結構的影響很小
- 檔案讀寫
- 對象是屬性群組成, 那麼只需要把屬性儲存下來即可.
- 增刪屬性不用改動檔案格式, 連版本號碼都省了
- Undo/Redo
- 對於建立/刪除操作, 備份該對象所有屬性.
- 對於屬性更改操作, 備份當前編輯屬性.
- Undo/Redo只不過是把屬性進行還原而已
- 介面顯示
- 屬性可以與PropertyGrid良好的結合. 對於MFC的PropertyGrid正好可以用FourCC的uint值做為id. 擴充一下很容易把屬性顯示做成自適應的, 而不依賴於具體代碼實現.
- 考慮與.net的property反射機制相結合(待驗證)
再考查一下WPF下的綁定機制與屬性相結合會產生什麼效果~