imgui
Version:
[demo](https://htmlpreview.github.io/?https://github.com/he110world/imgui/master/demo.html)
823 lines (739 loc) • 25.3 kB
JavaScript
(function(root){
//https://github.com/google/incremental-dom
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e(t.IncrementalDOM={})}(this,function(t){"use strict";function e(){}function n(t,e){this.attrs=a(),this.attrsArr=[],this.newAttrs=a(),this.staticsApplied=!1,this.key=e,this.keyMap=a(),this.keyMapValid=!0,this.focused=!1,this.nodeName=t,this.text=null}function r(){this.created=h.nodesCreated&&[],this.deleted=h.nodesDeleted&&[]}var i=Object.prototype.hasOwnProperty;e.prototype=Object.create(null);var o=function(t,e){return i.call(t,e)},a=function(){return new e},u="__incrementalDOMData",l=function(t,e,r){var i=new n(e,r);return t[u]=i,i},f=function(t){return c(t),t[u]},c=function(t){if(!t[u]){var e=t instanceof Element,n=e?t.localName:t.nodeName,r=e?t.getAttribute("key"):null,i=l(t,n,r);if(r&&(f(t.parentNode).keyMap[r]=t),e)for(var o=t.attributes,a=i.attrs,s=i.newAttrs,d=i.attrsArr,p=0;p<o.length;p+=1){var h=o[p],v=h.name,m=h.value;a[v]=m,s[v]=void 0,d.push(v),d.push(m)}for(var y=t.firstChild;y;y=y.nextSibling)c(y)}},s=function(t,e){return"svg"===t?"http://www.w3.org/2000/svg":"foreignObject"===f(e).nodeName?null:e.namespaceURI},d=function(t,e,n,r){var i=s(n,e),o=void 0;return o=i?t.createElementNS(i,n):t.createElement(n),l(o,n,r),o},p=function(t){var e=t.createTextNode("");return l(e,"#text",null),e},h={nodesCreated:null,nodesDeleted:null};r.prototype.markCreated=function(t){this.created&&this.created.push(t)},r.prototype.markDeleted=function(t){this.deleted&&this.deleted.push(t)},r.prototype.notifyChanges=function(){this.created&&this.created.length>0&&h.nodesCreated(this.created),this.deleted&&this.deleted.length>0&&h.nodesDeleted(this.deleted)};var v=function(t){return t instanceof Document||t instanceof DocumentFragment},m=function(t,e){for(var n=[],r=t;r!==e;)n.push(r),r=r.parentNode;return n},y=function(t){for(var e=t,n=e;e;)n=e,e=e.parentNode;return n},g=function(t){var e=y(t);return v(e)?e.activeElement:null},k=function(t,e){var n=g(t);return n&&t.contains(n)?m(n,e):[]},x=function(t,e,n){for(var r=e.nextSibling,i=n;i!==e;){var o=i.nextSibling;t.insertBefore(i,r),i=o}},w=null,b=null,N=null,C=null,A=function(t,e){for(var n=0;n<t.length;n+=1)f(t[n]).focused=e},D=function(t){var e=function(e,n,i){var o=w,a=C,u=b,l=N;w=new r,C=e.ownerDocument,N=e.parentNode;var f=k(e,N);A(f,!0);var c=t(e,n,i);return A(f,!1),w.notifyChanges(),w=o,C=a,b=u,N=l,c};return e},O=D(function(t,e,n){return b=t,V(),e(n),T(),t}),M=D(function(t,e,n){var r={nextSibling:t};return b=r,e(n),t!==b&&t.parentNode&&j(N,t,f(N).keyMap),r===b?null:b}),S=function(t,e,n){var r=f(t);return e===r.nodeName&&n==r.key},E=function(t,e){if(!b||!S(b,t,e)){var n=f(N),r=b&&f(b),i=n.keyMap,o=void 0;if(e){var a=i[e];a&&(S(a,t,e)?o=a:a===b?w.markDeleted(a):j(N,a,i))}o||(o="#text"===t?p(C):d(C,N,t,e),e&&(i[e]=o),w.markCreated(o)),f(o).focused?x(N,o,b):r&&r.key&&!r.focused?(N.replaceChild(o,b),n.keyMapValid=!1):N.insertBefore(o,b),b=o}},j=function(t,e,n){t.removeChild(e),w.markDeleted(e);var r=f(e).key;r&&delete n[r]},I=function(){var t=N,e=f(t),n=e.keyMap,r=e.keyMapValid,i=t.lastChild,o=void 0;if(i!==b||!r){for(;i!==b;)j(t,i,n),i=t.lastChild;if(!r){for(o in n)i=n[o],i.parentNode!==t&&(w.markDeleted(i),delete n[o]);e.keyMapValid=!0}}},V=function(){N=b,b=null},P=function(){return b?b.nextSibling:N.firstChild},_=function(){b=P()},T=function(){I(),b=N,N=N.parentNode},B=function(t,e){return _(),E(t,e),V(),N},F=function(){return T(),b},L=function(){return _(),E("#text",null),b},R=function(){return N},U=function(){return P()},X=function(){b=N.lastChild},q=_,z={"default":"__default"},G=function(t){return 0===t.lastIndexOf("xml:",0)?"http://www.w3.org/XML/1998/namespace":0===t.lastIndexOf("xlink:",0)?"http://www.w3.org/1999/xlink":void 0},H=function(t,e,n){if(null==n)t.removeAttribute(e);else{var r=G(e);r?t.setAttributeNS(r,e,n):t.setAttribute(e,n)}},J=function(t,e,n){t[e]=n},K=function(t,e,n){e.indexOf("-")>=0?t.setProperty(e,n):t[e]=n},Q=function(t,e,n){if("string"==typeof n)t.style.cssText=n;else{t.style.cssText="";var r=t.style,i=n;for(var a in i)o(i,a)&&K(r,a,i[a])}},W=function(t,e,n){var r=typeof n;"object"===r||"function"===r?J(t,e,n):H(t,e,n)},Y=function(t,e,n){var r=f(t),i=r.attrs;if(i[e]!==n){var o=Z[e]||Z[z["default"]];o(t,e,n),i[e]=n}},Z=a();Z[z["default"]]=W,Z.style=Q;var $=3,tt=[],et=function(t,e,n){var r=B(t,e),i=f(r);if(!i.staticsApplied){if(n)for(var o=0;o<n.length;o+=2){var a=n[o],u=n[o+1];Y(r,a,u)}i.staticsApplied=!0}for(var l=i.attrsArr,c=i.newAttrs,s=!l.length,d=$,p=0;d<arguments.length;d+=2,p+=2){var h=arguments[d];if(s)l[p]=h,c[h]=void 0;else if(l[p]!==h)break;var u=arguments[d+1];(s||l[p+1]!==u)&&(l[p+1]=u,Y(r,h,u))}if(d<arguments.length||p<l.length){for(;d<arguments.length;d+=1,p+=1)l[p]=arguments[d];for(p<l.length&&(l.length=p),d=0;d<l.length;d+=2){var a=l[d],u=l[d+1];c[a]=u}for(var v in c)Y(r,v,c[v]),c[v]=void 0}return r},nt=function(t,e,n){tt[0]=t,tt[1]=e,tt[2]=n},rt=function(t,e){tt.push(t),tt.push(e)},it=function(){var t=et.apply(null,tt);return tt.length=0,t},ot=function(){var t=F();return t},at=function(t){return et.apply(null,arguments),ot(t)},ut=function(t){var e=L(),n=f(e);if(n.text!==t){n.text=t;for(var r=t,i=1;i<arguments.length;i+=1){var o=arguments[i];r=o(r)}e.data=r}return e};t.patch=O,t.patchInner=O,t.patchOuter=M,t.currentElement=R,t.currentPointer=U,t.skip=X,t.skipNode=q,t.elementVoid=at,t.elementOpenStart=nt,t.elementOpenEnd=it,t.elementOpen=et,t.elementClose=ot,t.text=ut,t.attr=rt,t.symbols=z,t.attributes=Z,t.applyAttr=H,t.applyProp=J,t.notifications=h,t.importNode=c});
const {elementOpen,elementOpenStart,elementOpenEnd,elementClose,elementVoid,text,attr,patch} = IncrementalDOM
function Rect(x=0,y=0,w=0,h=0){
this.x = x
this.y = y
this.w = w
this.h = h
}
Rect.prototype = {
css:function(pos){
pos = pos || 'fixed'
return 'position:'+pos+';left:'+this.x+'px;top:'+this.y+'px;width:'+this.w+'px;height:'+this.h+'px;'
},
contains:function(pos){
return pos && this.x<=pos.x && this.x+this.w>=pos.x && this.y<=pos.y && this.y+this.h>=pos.y
},
clone:function(){
return new Rect(this.x,this.y,this.w,this.h)
},
cssAutoHeight:function(pos){
pos = pos || 'fixed'
return 'position:'+pos+';left:'+this.x+'px;top:'+this.y+'px;width:'+this.w+'px;'
}
}
function make_id(length) {
let res = ''
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
var len = chars .length
for (let i = 0; i < length; i++ ) {
res += chars.charAt(Math.floor(Math.random() * len))
}
return res
}
function patch_css(css_source, elem_id){
const prefix = '#' + elem_id + '{'
const postfix = '}'
return less.render(prefix + css_source + postfix)
}
function add_css(rule){
const css = document.createElement('style')
css.type = 'text/css'
css.textContent = rule
document.getElementsByTagName('head')[0].appendChild(css)
}
function get_cursor_pos (elem) {
return elem.selectionStart
}
function set_cursor_pos (e, pos) {
e.selectionStart = e.selectionEnd = pos
}
function gen_elem_id(){
//id可能以数字开头,要加上前缀,否则不能做element id
return 'elem-' + make_id(32)
}
function clear_dict(d){
for(const k of Object.keys(d)){
delete d[k]
}
}
//IMPORTANT:如果有事件值,优先返回事件值
_css_dict = {}
function ImGuiLayout(root){
this._dom_root = root
this._func_list = []
this._rect_dict = {}
this._drag_dict = {}
this._click_pos
this._window_id = 0
this._id_str_dict = {}
this._id_val_dict = {}
this._id_cursor_dict = {}
this._id_cursor_text = {}
this._id_evt_dict = {}
}
ImGuiLayout.prototype = {
_get_return(id,val){
let ret
if (this._id_val_dict.hasOwnProperty(id)) {
ret = this._id_val_dict[id]
delete this._id_val_dict[id]
} else {
ret = val
}
return ret
},
_gen_id(caller_line) {
const id_str = this._window_id + caller_line
let idx = this._id_str_dict[id_str]
if (idx) {//id重复了
++idx
} else {
idx = 1
}
this._id_str_dict[id_str] = idx
return id_str+idx
},
_load_cursor(id, elem){
if (this._id_cursor_dict.hasOwnProperty(id)) {
const pos = this._id_cursor_dict[id]
set_cursor_pos(elem, pos)
}
},
_offset_cursor(id, offset){
if (this._id_cursor_dict.hasOwnProperty(id)) {
offset = offset || 0
this._id_cursor_dict[id]+=offset
}
},
_save_cursor(id, elem){
const pos = get_cursor_pos(elem)
this._id_cursor_dict[id] = pos
this._id_cursor_text[id] = elem.value
},
_clear_cursor(){
for(const id in this._id_cursor_dict){
delete this._id_cursor_dict[id]
}
},
_on_mousedown(id){
let x0, y0, elem
//e.onmousedown = drag_mousedown
const drag_mousedown = (e)=>{
e = e || window.event
e.preventDefault()
e.stopPropagation()
elem = e.target
x0 = e.clientX
y0 = e.clientY
document.onmousemove = drag_mousemove
document.onmouseup = drag_mouseup
}
const drag_mousemove = (e)=>{
e = e || window.event
e.preventDefault()
const dx = e.clientX - x0
const dy = e.clientY - y0
x0 = e.clientX
y0 = e.clientY
const r = this._rect_dict[id]
const left = r.x + dx
const top = r.y + dy
elem.style.left = left + 'px'
elem.style.top = top + 'px'
//更新rect
const rect = this._rect_dict[id]
if (rect) {
rect.x = left
rect.y = top
}
}
const drag_mouseup = (e)=>{
document.onmouseup = null
document.onmousemove = null
}
return drag_mousedown
},
beginArea:function(rect){
},
_beginHorizontal:function(id){
elementOpen('div',id,null,'style','display:flex;flex-direction:row;')
},
beginHorizontal:function(line){
const id = this._gen_id(line)
this._func_list.push(()=>this._beginHorizontal(id))
},
_beginVertical:function(id,str,style){
elementOpen('div',id,null,'style','display:flex;flex-direction:column;'+style)
text(str)
},
beginVertical:function(line,str,style){
str = str || ''
style = style || ''
const id = this._gen_id(line)
this._func_list.push(()=>this._beginVertical(id,str,style))
},
//表格功能
_beginTable:function(){
elementOpen('table',null,null)
},
beginTable:function(){
this._func_list.push(()=>this._beginTable())
},
_endTable:function(){
elementClose('table')
},
endTable:function(){
this._func_list.push(()=>this._endTable())
},
_beginTableRow:function(){
elementOpen('tr',null,null)
},
beginTableRow:function(){
this._func_list.push(()=>this._beginTableRow())
},
_endTableRow:function(){
elementClose('tr')
},
endTableRow:function(){
this._func_list.push(()=>this._endTableRow())
},
_beginTableHead:function(){
elementOpen('th')
},
beginTableHead:function(){
this._func_list.push(()=>this._beginTableHead())
},
_endTableHead:function(){
elementClose('th')
},
endTableHead:function(){
this._func_list.push(()=>this._endTableHead())
},
_beginTableData:function(){
elementOpen('td')
},
beginTableData:function(){
this._func_list.push(()=>this._beginTableData())
},
_endTableData:function(){
elementClose('td')
},
endTableData:function(){
this._func_list.push(()=>this._endTableData())
},
box:function(){
},
_button:function(id,str,style){
elementOpen('button',id,null,
'style','width:100%;'+style+';',
'onclick',evt=>{
this._id_val_dict[id] = true
},
'onmousedown',e=>{
e.stopPropagation()
})
text(str)
elementClose('button')
},
button:function(line,str,style){
const id = this._gen_id(line)
str = str || ''
style = style || ''
this._func_list.push(()=>this._button(id,str,style))
const clicked = !!this._id_val_dict[id]
if (clicked) {
delete this._id_val_dict[id]
}
return clicked
},
_colorField:function(id,hex_color){
const elem = elementVoid(
'input',id,null,
'type','color',
'onmousedown',e=>e.stopPropagation(),
'onchange',e=>{
this._id_val_dict[id] = elem.value
})
elem.value = hex_color
},
colorField:function(line,hex_color){
hex_color = hex_color || '#000000'
if (typeof hex_color==='number') {
hex_color = '#' + hex_color.toString(16)
}
const id = this._gen_id(line)
this._func_list.push(()=>this._colorField(id,hex_color))
return this._get_return(id,hex_color)
},
_dragWindow:function(id,rect){
this._drag_dict[id] = true
},
dragWindow:function(line,rect){
const id = this._window_id //这里必须这样写,_window_id会变的
this._func_list.push(()=>this._dragWindow(id,rect))
},
_dropDown:function(id,idx,list,lab,style){
elementOpen('div',null,null,'style','width:100%;')
if (lab) {
elementOpen('label',null,null,'for',id,'style','float:left;')
text(lab)
elementClose('label')
}
elementOpen('span',null,null,'style','overflow:hidden;display:block;')
const elem = elementOpen(
'select',id,null,
'id',id,
'style','width:100%;'+style,
'onmousedown',e=>e.stopPropagation(),
'onchange',e=>{
this._id_val_dict[id] = elem.selectedIndex
})
for(const opt of list){
elementOpen('option',null,null,'value',opt)
text(opt)
elementClose('option')
}
elementClose('select')
elementClose('span')
elem.selectedIndex = idx
elementClose('div')
},
dropDown:function(line,idx,list,lab,style){
idx = idx || 0
lab = lab || ''
style = style || ''
if (idx>=list.length) {
idx = 0
}
const id = this._gen_id(line)
this._func_list.push(()=>this._dropDown(id,idx,list,lab,style))
return this._get_return(id,idx)
},
endArea:function(){
},
_endHorizontal:function(){
elementClose('div')
},
endHorizontal:function(){
this._func_list.push(()=>this._endHorizontal())
},
_endVertical:function(){
elementClose('div')
},
endVertical:function(){
this._func_list.push(()=>this._endVertical())
},
_foldout:function(id,bval,str){
const s0 = 'width:0;height:0;border-style:solid;display:inline-block;'
const right = 'border-width:5px 0 5px 8.7px;border-color:transparent transparent transparent #000000;'
const down = 'border-width:8.7px 5px 0 5px;border-color:#000000 transparent transparent transparent;'
const s = bval ? s0+down : s0+right
elementOpen('div',id,null,'onclick',e=>{
this._id_val_dict[id] = !bval
})
elementVoid(
'div',null,null,
'style',s)
text(str)
elementClose('div')
},
foldout:function(line,bval,str){
bval = bval || false
str = str || ''
const id = this._gen_id(line)
this._func_list.push(()=>this._foldout(id,bval,str))
return this._get_return(id,bval)
},
horizontalScrollBar:function(){
},
_horizontalSlider:function(id,val,left_val,right_val,lab){
elementOpen('div',null,null)
if (lab){
elementOpen('label',null,null,'for',id)
text(lab)
elementClose('label')
}
const elem = elementVoid(
'input',id,null,
'id',id,
'type','range',
'min',left_val,
'max',right_val,
//'style','width:100%',
'onmousedown',e=>e.stopPropagation(),
'onmousemove',e=>e.stopPropagation(),
'onmouseup',e=>e.stopPropagation(),
'oninput',e=>{
this._id_val_dict[id]=elem.value
})
elem.value = val
elementClose('div')
},
horizontalSlider:function(line,val,left_val,right_val,lab){
const id = this._gen_id(line)
this._func_list.push(()=>this._horizontalSlider(id,val,left_val,right_val,lab))
return this._get_return(id,val)
},
_horizontalRule:function(id){
elementVoid('hr',id,null)
},
horizontalRule:function(line){
const id = this._gen_id(line)
this._func_list.push(()=>this._horizontalRule(id))
},
_hyperlink:function(id,url,str){
elementOpen('a',id,null,'href',url,'style','width:fit-content;','target','_blank')
text(str)
elementClose('a')
},
hyperlink:function(line,url,str){
const id = this._gen_id(line)
this._func_list.push(()=>this._hyperlink(id,url,str))
},
_label:function(id,str,style,onclick){
elementOpen('div',id,null,
'style','width:100%;overflow-wrap:break-word;'+style,
'onmousedown',e=>{
e.stopPropagation()
if (typeof onclick==='function') {
onclick(e)
}
},
'onmousemove',e=>e.stopPropagation(),
'onmouseup',e=>e.stopPropagation())
text(str)
elementClose('div');
},
label:function(line,str,style,onclick){
if (typeof style==='function') {
onclick = style
style = ''
}
style = style || ''
const id = this._gen_id(line)
this._func_list.push(()=>this._label(id,str,style,onclick))
return str
},
_picture:function(id,url){
elementVoid('img',id,null,'src',url)
},
picture:function(line,url){
const id = this._gen_id(line)
this._func_list.push(()=>this._picture(id,url))
},
_video:function(id,url){
elementVoid('video',id,null,'src',url,'controls',true)
},
video:function(line,url){
const id = this._gen_id(line)
this._func_list.push(()=>this._video(id,url))
},
repeatButton:function(str){
},
selectionGrid:function(){
},
space:function(){
},
_textArea2:function(id,str){
elementOpen('div',null,null,'style','border:1px solid gray;')
const elem = elementOpen('p',id,null,
'contenteditable',true,
'onmousedown',e=>{e.stopPropagation()},
'oninput',e=>{
//输入法
//if (e.inputType !== 'insertCompositionText') {
if (!e.isComposing) {
this._id_val_dict[id]=elem.innerText
}
})
text(str)
elementClose('p')
elementClose('div')
},
textArea2:function(line,str){
const id = this._gen_id(line)
this._func_list.push(()=>this._textArea2(id,str))
return this._get_return(id,str)
},
///
_textArea:function(id,str){
//elementOpen('div',null,null,'style','width:100%;')
const elem = elementOpen(
'textarea',id,null,
'style','width:100%;',
'onmousedown',e=>{
e.stopPropagation()
this._clear_cursor()
},
'onmousemove',e=>e.stopPropagation(),
'onmouseup',e=>e.stopPropagation(),
'oninput',e=>{
if (!e.isComposing) {
this._id_val_dict[id] = elem.value
this._save_cursor(id,elem)
}
})
if (!this._id_evt_dict[id]) {
elem.addEventListener('compositionstart',e=>{
this._save_cursor(id,elem)
})
elem.addEventListener('compositionend',e=>{
this._id_val_dict[id]=elem.value
this._offset_cursor(id,e.data.length)
this._load_cursor(id,elem)
})
this._id_evt_dict[id] = true
}
if (!this._id_cursor_text[id]) {
elem.value = str
this._load_cursor(id,elem)
}
elementClose('textarea')
//elementClose('div')
},
textArea:function(line,str){
const id = this._gen_id(line)
this._func_list.push(()=>this._textArea(id,str))
return this._get_return(id,str)
},
///
_textField:function(id,str,lab,type,style){
elementOpen('div',null,null,'style','width:100%;')
if (lab) {
elementOpen('label',null,null,'for',id,'style','float:left;')
text(lab)
elementClose('label')
}
elementOpen('span',null,null,'style','overflow:hidden;display:block;')
const elem = elementVoid(
'input',id,null,
'id',id,
'type',type,
'style','width:100%;box-sizing:border-box;',
'onmousedown',e=>{
e.stopPropagation()
this._clear_cursor()
},
'onmousemove',e=>e.stopPropagation(),
'onmouseup',e=>{
e.stopPropagation()
},
'oninput',e=>{
this._id_val_dict[id] = elem.value
this._save_cursor(id,elem)
}
)
if (!this._id_cursor_text[id]) {
if (elem.value !== str) {
elem.value = str
this._load_cursor(id,elem)
}
} else {
delete this._id_cursor_text[id]
}
elementClose('span')
elementClose('div')
},
textField:function(line,str,lab,style){
str = str || ''
lab = lab || ''
style = style || ''
const id = this._gen_id(line)
this._func_list.push(()=>this._textField(id,str,lab,'text',style))
return this._get_return(id,str)
},
passwordField:function(line,str,lab,style){
str = str || ''
lab = lab || ''
style = style || ''
const id = this._gen_id(line)
this._func_list.push(()=>this._textField(id,str,lab,'password',style))
return this._get_return(id,str)
},
///
_toggle:function(id,bval,str,style){
elementOpen('div',null,null,'style','display:flex;'+style)
const elem = elementVoid(
'input',id,null,
'id',id,
'type','checkbox',
'oninput',e=>this._id_val_dict[id]=elem.checked
)
elem.checked = bval
elementOpen('label',null,null,
'for',id,
'style','word-break:keep-all;',
'onmousedown',e=>e.stopPropagation()
)
text(str)
elementClose('label')
elementClose('div')
},
toggle:function(line,bval,str,style){
bval = !!bval
str = str || ''
style = style || ''
const id = this._gen_id(line)
this._func_list.push(()=>this._toggle(id,bval,str,style))
return this._get_return(id,bval)
},
///
_radio:function(id,idx,list){
elementOpen('div',id,null,'style','width:100%;')
for(let i=0; i<list.length; i++){
const iid = id + i
const elem = elementVoid(
'input',iid,null,
'id',iid,
'type','radio',
'name',id,
'onchange',()=>{this._id_val_dict[id]=i})
if (i===idx) {
elem.checked = true
}
elementOpen(
'label',null,null,
'for',iid)
text(list[i])
elementClose('label')
}
elementClose('div')
},
radio:function(line,idx,list){
const id = this._gen_id(line)
this._func_list.push(()=>this._radio(id,idx,list))
return this._get_return(id,idx)
},
verticalScrollBar:function(){
},
verticalSlider:function(){
},
_window_begin:function(id,rect,cb,str,elem_id){
elementOpenStart('div',id,null)
attr('style',rect.cssAutoHeight('absolute')+'background-color:white;padding:3px;')
if (elem_id) {
attr('id',elem_id)
}
if (!this._drag_dict[id]) {
attr('onmousedown', this._on_mousedown(id).bind(this))
}
elementOpenEnd('div')
if (str) {
text(str)
}
},
_window_end:function(){
elementClose('div')
},
window:function(id,rect,cb,str,style){
this._window_id = id
let elem_id
if (style) {
elem_id = gen_elem_id(style)
if (!_css_dict[elem_id]) {
//style可以是url或者字符串
if (style.trim().startsWith('http')) {
//下载css文件
engine
.getText(style)
.then(css_source=>{
patch_css(css_source, elem_id)
.then(css_out=>add_css(css_out.css))//加到页面上
})
.catch(e=>console.log(e))
} else {
patch_css(style, elem_id)
.then(css_out=>add_css(css_out.css))
}
_css_dict[elem_id] = true
}
}
this._func_list.push(()=>this._window_begin(id,rect,cb,str,elem_id))
if (typeof cb === 'function') {
cb()
}
this._func_list.push(()=>this._window_end())
//返回上一帧的位置?
let rect2 = this._rect_dict[id]
if (!rect2) {
rect2 = rect.clone()
this._rect_dict[id] = rect2 = rect.clone()
}
return rect2
},
update:function(){
patch(this._dom_root, ()=>{
for(const func of this._func_list){
func()
}
})
this._func_list.length = 0
this._click_pos = null
this._window_id = 0
clear_dict(this._drag_dict)
clear_dict(this._id_str_dict)
},
}
function ImGuiManager(){
this._layout_list = []
this._func_list = []
}
ImGuiManager.prototype = {
rect:function(x,y,w,h){
return new Rect(x,y,w,h)
},
_patch:function(f){
const src = f.toString() //包括函数名和参数
const src_body = src.slice(src.indexOf("{")+1, src.lastIndexOf("}"))
const lines = src_body.split('\n')
const out = []
for(let i=0; i<lines.length; i++){
const line = lines[i]
if (line.indexOf('layout') === -1) {
out.push(line)
} else {
const s = make_id(32)
const nl = lines[i].replace(/(layout\.[a-zA-Z_{1}][a-zA-Z0-9_]+\()/g,`$1"${s}",`)
out.push(nl)
}
}
const name = this._get_url()
//HACK
const debug_url = `//# sourceURL=${name}`
out.push(debug_url)
const patched = out.join('\n')
return new Function('layout',patched)
},
contextify:function(f){
const f2 = this._patch(f)
f2()
},
_get_url:function(){
const e = new Error()
const lines = e.stack.split('\n')
const line = lines[lines.length-1]
return line.match(/https?:\/\/.*\/[^:]*/)[0]
},
layout:function(d,f){
const layout = new ImGuiLayout(d)
const func = f//this._patch(f)
this._layout_list.push(layout)
this._func_list.push(func)
requestAnimationFrame(this._update.bind(this))
return layout
},
_update:function(){
for(let i=0; i<this._func_list.length; i++){
const func = this._func_list[i]
const layout = this._layout_list[i]
func(layout)
layout.update()
}
requestAnimationFrame(this._update.bind(this))
}
}
root.imgui = new ImGuiManager()
})(this)