|
@@ -0,0 +1,2245 @@
|
|
|
+var pas = {};
|
|
|
+
|
|
|
+var rtl = {
|
|
|
+
|
|
|
+ quiet: false,
|
|
|
+ debug_load_units: false,
|
|
|
+ debug_rtti: false,
|
|
|
+
|
|
|
+ debug: function(){
|
|
|
+ if (rtl.quiet || !console || !console.log) return;
|
|
|
+ console.log(arguments);
|
|
|
+ },
|
|
|
+
|
|
|
+ error: function(s){
|
|
|
+ rtl.debug('Error: ',s);
|
|
|
+ throw s;
|
|
|
+ },
|
|
|
+
|
|
|
+ warn: function(s){
|
|
|
+ rtl.debug('Warn: ',s);
|
|
|
+ },
|
|
|
+
|
|
|
+ hasString: function(s){
|
|
|
+ return rtl.isString(s) && (s.length>0);
|
|
|
+ },
|
|
|
+
|
|
|
+ isArray: function(a) {
|
|
|
+ return Array.isArray(a);
|
|
|
+ },
|
|
|
+
|
|
|
+ isFunction: function(f){
|
|
|
+ return typeof(f)==="function";
|
|
|
+ },
|
|
|
+
|
|
|
+ isModule: function(m){
|
|
|
+ return rtl.isObject(m) && rtl.hasString(m.$name) && (pas[m.$name]===m);
|
|
|
+ },
|
|
|
+
|
|
|
+ isImplementation: function(m){
|
|
|
+ return rtl.isObject(m) && rtl.isModule(m.$module) && (m.$module.$impl===m);
|
|
|
+ },
|
|
|
+
|
|
|
+ isNumber: function(n){
|
|
|
+ return typeof(n)==="number";
|
|
|
+ },
|
|
|
+
|
|
|
+ isObject: function(o){
|
|
|
+ var s=typeof(o);
|
|
|
+ return (typeof(o)==="object") && (o!=null);
|
|
|
+ },
|
|
|
+
|
|
|
+ isString: function(s){
|
|
|
+ return typeof(s)==="string";
|
|
|
+ },
|
|
|
+
|
|
|
+ getNumber: function(n){
|
|
|
+ return typeof(n)==="number"?n:NaN;
|
|
|
+ },
|
|
|
+
|
|
|
+ getChar: function(c){
|
|
|
+ return ((typeof(c)==="string") && (c.length===1)) ? c : "";
|
|
|
+ },
|
|
|
+
|
|
|
+ getObject: function(o){
|
|
|
+ return ((typeof(o)==="object") || (typeof(o)==='function')) ? o : null;
|
|
|
+ },
|
|
|
+
|
|
|
+ isPasClass: function(type){
|
|
|
+ return (rtl.isObject(type) && type.hasOwnProperty('$classname') && rtl.isObject(type.$module));
|
|
|
+ },
|
|
|
+
|
|
|
+ isPasClassInstance: function(type){
|
|
|
+ return (rtl.isObject(type) && rtl.isPasClass(type.$class));
|
|
|
+ },
|
|
|
+
|
|
|
+ hexStr: function(n,digits){
|
|
|
+ return ("000000000000000"+n.toString(16).toUpperCase()).slice(-digits);
|
|
|
+ },
|
|
|
+
|
|
|
+ m_loading: 0,
|
|
|
+ m_loading_intf: 1,
|
|
|
+ m_intf_loaded: 2,
|
|
|
+ m_loading_impl: 3, // loading all used unit
|
|
|
+ m_initializing: 4, // running initialization
|
|
|
+ m_initialized: 5,
|
|
|
+
|
|
|
+ module: function(module_name, intfuseslist, intfcode, impluseslist, implcode){
|
|
|
+ if (rtl.debug_load_units) rtl.debug('rtl.module name="'+module_name+'" intfuses='+intfuseslist+' impluses='+impluseslist+' hasimplcode='+rtl.isFunction(implcode));
|
|
|
+ if (!rtl.hasString(module_name)) rtl.error('invalid module name "'+module_name+'"');
|
|
|
+ if (!rtl.isArray(intfuseslist)) rtl.error('invalid interface useslist of "'+module_name+'"');
|
|
|
+ if (!rtl.isFunction(intfcode)) rtl.error('invalid interface code of "'+module_name+'"');
|
|
|
+ if (!(impluseslist==undefined) && !rtl.isArray(impluseslist)) rtl.error('invalid implementation useslist of "'+module_name+'"');
|
|
|
+ if (!(implcode==undefined) && !rtl.isFunction(implcode)) rtl.error('invalid implementation code of "'+module_name+'"');
|
|
|
+
|
|
|
+ if (pas[module_name])
|
|
|
+ rtl.error('module "'+module_name+'" is already registered');
|
|
|
+
|
|
|
+ var module = pas[module_name] = {
|
|
|
+ $name: module_name,
|
|
|
+ $intfuseslist: intfuseslist,
|
|
|
+ $impluseslist: impluseslist,
|
|
|
+ $state: rtl.m_loading,
|
|
|
+ $intfcode: intfcode,
|
|
|
+ $implcode: implcode,
|
|
|
+ $impl: null,
|
|
|
+ $rtti: Object.create(rtl.tSectionRTTI)
|
|
|
+ };
|
|
|
+ module.$rtti.$module = module;
|
|
|
+ if (implcode) module.$impl = {
|
|
|
+ $module: module,
|
|
|
+ $rtti: module.$rtti
|
|
|
+ };
|
|
|
+ },
|
|
|
+
|
|
|
+ exitcode: 0,
|
|
|
+
|
|
|
+ run: function(module_name){
|
|
|
+
|
|
|
+ function doRun(){
|
|
|
+ if (!rtl.hasString(module_name)) module_name='program';
|
|
|
+ if (rtl.debug_load_units) rtl.debug('rtl.run module="'+module_name+'"');
|
|
|
+ rtl.initRTTI();
|
|
|
+ var module = pas[module_name];
|
|
|
+ if (!module) rtl.error('rtl.run module "'+module_name+'" missing');
|
|
|
+ rtl.loadintf(module);
|
|
|
+ rtl.loadimpl(module);
|
|
|
+ if (module_name=='program'){
|
|
|
+ if (rtl.debug_load_units) rtl.debug('running $main');
|
|
|
+ var r = pas.program.$main();
|
|
|
+ if (rtl.isNumber(r)) rtl.exitcode = r;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (rtl.showUncaughtExceptions) {
|
|
|
+ try{
|
|
|
+ doRun();
|
|
|
+ } catch(re) {
|
|
|
+ var errMsg = re.hasOwnProperty('$class') ? re.$class.$classname : '';
|
|
|
+ errMsg += ((errMsg) ? ': ' : '') + (re.hasOwnProperty('fMessage') ? re.fMessage : re);
|
|
|
+ alert('Uncaught Exception : '+errMsg);
|
|
|
+ rtl.exitCode = 216;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ doRun();
|
|
|
+ }
|
|
|
+ return rtl.exitcode;
|
|
|
+ },
|
|
|
+
|
|
|
+ loadintf: function(module){
|
|
|
+ if (module.$state>rtl.m_loading_intf) return; // already finished
|
|
|
+ if (rtl.debug_load_units) rtl.debug('loadintf: "'+module.$name+'"');
|
|
|
+ if (module.$state===rtl.m_loading_intf)
|
|
|
+ rtl.error('unit cycle detected "'+module.$name+'"');
|
|
|
+ module.$state=rtl.m_loading_intf;
|
|
|
+ // load interfaces of interface useslist
|
|
|
+ rtl.loaduseslist(module,module.$intfuseslist,rtl.loadintf);
|
|
|
+ // run interface
|
|
|
+ if (rtl.debug_load_units) rtl.debug('loadintf: run intf of "'+module.$name+'"');
|
|
|
+ module.$intfcode(module.$intfuseslist);
|
|
|
+ // success
|
|
|
+ module.$state=rtl.m_intf_loaded;
|
|
|
+ // Note: units only used in implementations are not yet loaded (not even their interfaces)
|
|
|
+ },
|
|
|
+
|
|
|
+ loaduseslist: function(module,useslist,f){
|
|
|
+ if (useslist==undefined) return;
|
|
|
+ for (var i in useslist){
|
|
|
+ var unitname=useslist[i];
|
|
|
+ if (rtl.debug_load_units) rtl.debug('loaduseslist of "'+module.$name+'" uses="'+unitname+'"');
|
|
|
+ if (pas[unitname]==undefined)
|
|
|
+ rtl.error('module "'+module.$name+'" misses "'+unitname+'"');
|
|
|
+ f(pas[unitname]);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ loadimpl: function(module){
|
|
|
+ if (module.$state>=rtl.m_loading_impl) return; // already processing
|
|
|
+ if (module.$state<rtl.m_intf_loaded) rtl.error('loadimpl: interface not loaded of "'+module.$name+'"');
|
|
|
+ if (rtl.debug_load_units) rtl.debug('loadimpl: load uses of "'+module.$name+'"');
|
|
|
+ module.$state=rtl.m_loading_impl;
|
|
|
+ // load interfaces of implementation useslist
|
|
|
+ rtl.loaduseslist(module,module.$impluseslist,rtl.loadintf);
|
|
|
+ // load implementation of interfaces useslist
|
|
|
+ rtl.loaduseslist(module,module.$intfuseslist,rtl.loadimpl);
|
|
|
+ // load implementation of implementation useslist
|
|
|
+ rtl.loaduseslist(module,module.$impluseslist,rtl.loadimpl);
|
|
|
+ // Note: At this point all interfaces used by this unit are loaded. If
|
|
|
+ // there are implementation uses cycles some used units might not yet be
|
|
|
+ // initialized. This is by design.
|
|
|
+ // run implementation
|
|
|
+ if (rtl.debug_load_units) rtl.debug('loadimpl: run impl of "'+module.$name+'"');
|
|
|
+ if (rtl.isFunction(module.$implcode)) module.$implcode(module.$impluseslist);
|
|
|
+ // run initialization
|
|
|
+ if (rtl.debug_load_units) rtl.debug('loadimpl: run init of "'+module.$name+'"');
|
|
|
+ module.$state=rtl.m_initializing;
|
|
|
+ if (rtl.isFunction(module.$init)) module.$init();
|
|
|
+ // unit initialized
|
|
|
+ module.$state=rtl.m_initialized;
|
|
|
+ },
|
|
|
+
|
|
|
+ createCallback: function(scope, fn){
|
|
|
+ var cb;
|
|
|
+ if (typeof(fn)==='string'){
|
|
|
+ cb = function(){
|
|
|
+ return scope[fn].apply(scope,arguments);
|
|
|
+ };
|
|
|
+ } else {
|
|
|
+ cb = function(){
|
|
|
+ return fn.apply(scope,arguments);
|
|
|
+ };
|
|
|
+ };
|
|
|
+ cb.scope = scope;
|
|
|
+ cb.fn = fn;
|
|
|
+ return cb;
|
|
|
+ },
|
|
|
+
|
|
|
+ cloneCallback: function(cb){
|
|
|
+ return rtl.createCallback(cb.scope,cb.fn);
|
|
|
+ },
|
|
|
+
|
|
|
+ eqCallback: function(a,b){
|
|
|
+ // can be a function or a function wrapper
|
|
|
+ if (a==b){
|
|
|
+ return true;
|
|
|
+ } else {
|
|
|
+ return (a!=null) && (b!=null) && (a.fn) && (a.scope===b.scope) && (a.fn==b.fn);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ initClass: function(c,parent,name,initfn){
|
|
|
+ parent[name] = c;
|
|
|
+ c.$classname = name;
|
|
|
+ if ((parent.$module) && (parent.$module.$impl===parent)) parent=parent.$module;
|
|
|
+ c.$parent = parent;
|
|
|
+ c.$fullname = parent.$name+'.'+name;
|
|
|
+ if (rtl.isModule(parent)){
|
|
|
+ c.$module = parent;
|
|
|
+ c.$name = name;
|
|
|
+ } else {
|
|
|
+ c.$module = parent.$module;
|
|
|
+ c.$name = parent.name+'.'+name;
|
|
|
+ };
|
|
|
+ // rtti
|
|
|
+ if (rtl.debug_rtti) rtl.debug('initClass '+c.$fullname);
|
|
|
+ var t = c.$module.$rtti.$Class(c.$name,{ "class": c, module: parent });
|
|
|
+ c.$rtti = t;
|
|
|
+ if (rtl.isObject(c.$ancestor)) t.ancestor = c.$ancestor.$rtti;
|
|
|
+ if (!t.ancestor) t.ancestor = null;
|
|
|
+ // init members
|
|
|
+ initfn.call(c);
|
|
|
+ },
|
|
|
+
|
|
|
+ createClass: function(parent,name,ancestor,initfn){
|
|
|
+ // create a normal class,
|
|
|
+ // ancestor must be null or a normal class,
|
|
|
+ // the root ancestor can be an external class
|
|
|
+ var c = null;
|
|
|
+ if (ancestor != null){
|
|
|
+ c = Object.create(ancestor);
|
|
|
+ c.$ancestor = ancestor;
|
|
|
+ // Note:
|
|
|
+ // if root is an "object" then c.$ancestor === Object.getPrototypeOf(c)
|
|
|
+ // if root is a "function" then c.$ancestor === c.__proto__, Object.getPrototypeOf(c) returns the root
|
|
|
+ } else {
|
|
|
+ c = {};
|
|
|
+ c.$create = function(fnname,args){
|
|
|
+ if (args == undefined) args = [];
|
|
|
+ var o = Object.create(this);
|
|
|
+ o.$class = this; // Note: o.$class === Object.getPrototypeOf(o)
|
|
|
+ o.$init();
|
|
|
+ try{
|
|
|
+ o[fnname].apply(o,args);
|
|
|
+ o.AfterConstruction();
|
|
|
+ } catch($e){
|
|
|
+ o.$destroy;
|
|
|
+ throw $e;
|
|
|
+ }
|
|
|
+ return o;
|
|
|
+ };
|
|
|
+ c.$destroy = function(fnname){
|
|
|
+ this.BeforeDestruction();
|
|
|
+ this[fnname]();
|
|
|
+ this.$final;
|
|
|
+ };
|
|
|
+ };
|
|
|
+ rtl.initClass(c,parent,name,initfn);
|
|
|
+ },
|
|
|
+
|
|
|
+ createClassExt: function(parent,name,ancestor,newinstancefnname,initfn){
|
|
|
+ // Create a class using an external ancestor.
|
|
|
+ // If newinstancefnname is given, use that function to create the new object.
|
|
|
+ // If exist call BeforeDestruction and AfterConstruction.
|
|
|
+ var c = null;
|
|
|
+ c = Object.create(ancestor);
|
|
|
+ c.$create = function(fnname,args){
|
|
|
+ if (args == undefined) args = [];
|
|
|
+ var o = null;
|
|
|
+ if (newinstancefnname.length>0){
|
|
|
+ o = this[newinstancefnname](fnname,args);
|
|
|
+ } else {
|
|
|
+ o = Object.create(this);
|
|
|
+ }
|
|
|
+ o.$class = this; // Note: o.$class === Object.getPrototypeOf(o)
|
|
|
+ o.$init();
|
|
|
+ try{
|
|
|
+ o[fnname].apply(o,args);
|
|
|
+ if (o.AfterConstruction) o.AfterConstruction();
|
|
|
+ } catch($e){
|
|
|
+ o.$destroy;
|
|
|
+ throw $e;
|
|
|
+ }
|
|
|
+ return o;
|
|
|
+ };
|
|
|
+ c.$destroy = function(fnname){
|
|
|
+ if (this.BeforeDestruction) this.BeforeDestruction();
|
|
|
+ this[fnname]();
|
|
|
+ this.$final;
|
|
|
+ };
|
|
|
+ rtl.initClass(c,parent,name,initfn);
|
|
|
+ },
|
|
|
+
|
|
|
+ tObjectDestroy: "Destroy",
|
|
|
+
|
|
|
+ free: function(obj,name){
|
|
|
+ if (obj[name]==null) return;
|
|
|
+ obj[name].$destroy(rtl.tObjectDestroy);
|
|
|
+ obj[name]=null;
|
|
|
+ },
|
|
|
+
|
|
|
+ freeLoc: function(obj){
|
|
|
+ if (obj==null) return;
|
|
|
+ obj.$destroy(rtl.tObjectDestroy);
|
|
|
+ return null;
|
|
|
+ },
|
|
|
+
|
|
|
+ is: function(instance,type){
|
|
|
+ return type.isPrototypeOf(instance) || (instance===type);
|
|
|
+ },
|
|
|
+
|
|
|
+ isExt: function(instance,type,mode){
|
|
|
+ // mode===1 means instance must be a Pascal class instance
|
|
|
+ // mode===2 means instance must be a Pascal class
|
|
|
+ // Notes:
|
|
|
+ // isPrototypeOf and instanceof return false on equal
|
|
|
+ // isPrototypeOf does not work for Date.isPrototypeOf(new Date())
|
|
|
+ // so if isPrototypeOf is false test with instanceof
|
|
|
+ // instanceof needs a function on right side
|
|
|
+ if (instance == null) return false; // Note: ==null checks for undefined too
|
|
|
+ if ((typeof(type) !== 'object') && (typeof(type) !== 'function')) return false;
|
|
|
+ if (instance === type){
|
|
|
+ if (mode===1) return false;
|
|
|
+ if (mode===2) return rtl.isPasClass(instance);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ if (type.isPrototypeOf && type.isPrototypeOf(instance)){
|
|
|
+ if (mode===1) return rtl.isPasClassInstance(instance);
|
|
|
+ if (mode===2) return rtl.isPasClass(instance);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ if ((typeof type == 'function') && (instance instanceof type)) return true;
|
|
|
+ return false;
|
|
|
+ },
|
|
|
+
|
|
|
+ Exception: null,
|
|
|
+ EInvalidCast: null,
|
|
|
+ EAbstractError: null,
|
|
|
+ ERangeError: null,
|
|
|
+
|
|
|
+ raiseE: function(typename){
|
|
|
+ var t = rtl[typename];
|
|
|
+ if (t==null){
|
|
|
+ var mod = pas.SysUtils;
|
|
|
+ if (!mod) mod = pas.sysutils;
|
|
|
+ if (mod){
|
|
|
+ t = mod[typename];
|
|
|
+ if (!t) t = mod[typename.toLowerCase()];
|
|
|
+ if (!t) t = mod['Exception'];
|
|
|
+ if (!t) t = mod['exception'];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (t){
|
|
|
+ if (t.Create){
|
|
|
+ throw t.$create("Create");
|
|
|
+ } else if (t.create){
|
|
|
+ throw t.$create("create");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (typename === "EInvalidCast") throw "invalid type cast";
|
|
|
+ if (typename === "EAbstractError") throw "Abstract method called";
|
|
|
+ if (typename === "ERangeError") throw "range error";
|
|
|
+ throw typename;
|
|
|
+ },
|
|
|
+
|
|
|
+ as: function(instance,type){
|
|
|
+ if((instance === null) || rtl.is(instance,type)) return instance;
|
|
|
+ rtl.raiseE("EInvalidCast");
|
|
|
+ },
|
|
|
+
|
|
|
+ asExt: function(instance,type,mode){
|
|
|
+ if((instance === null) || rtl.isExt(instance,type,mode)) return instance;
|
|
|
+ rtl.raiseE("EInvalidCast");
|
|
|
+ },
|
|
|
+
|
|
|
+ createInterface: function(module, name, guid, fnnames, ancestor, initfn){
|
|
|
+ //console.log('createInterface name="'+name+'" guid="'+guid+'" names='+fnnames);
|
|
|
+ var i = ancestor?Object.create(ancestor):{};
|
|
|
+ module[name] = i;
|
|
|
+ i.$module = module;
|
|
|
+ i.$name = name;
|
|
|
+ i.$fullname = module.$name+'.'+name;
|
|
|
+ i.$guid = guid;
|
|
|
+ i.$guidr = null;
|
|
|
+ i.$names = fnnames?fnnames:[];
|
|
|
+ if (rtl.isFunction(initfn)){
|
|
|
+ // rtti
|
|
|
+ if (rtl.debug_rtti) rtl.debug('createInterface '+i.$fullname);
|
|
|
+ var t = i.$module.$rtti.$Interface(name,{ "interface": i, module: module });
|
|
|
+ i.$rtti = t;
|
|
|
+ if (ancestor) t.ancestor = ancestor.$rtti;
|
|
|
+ if (!t.ancestor) t.ancestor = null;
|
|
|
+ initfn.call(i);
|
|
|
+ }
|
|
|
+ return i;
|
|
|
+ },
|
|
|
+
|
|
|
+ strToGUIDR: function(s,g){
|
|
|
+ var p = 0;
|
|
|
+ function n(l){
|
|
|
+ var h = s.substr(p,l);
|
|
|
+ p+=l;
|
|
|
+ return parseInt(h,16);
|
|
|
+ }
|
|
|
+ p+=1; // skip {
|
|
|
+ g.D1 = n(8);
|
|
|
+ p+=1; // skip -
|
|
|
+ g.D2 = n(4);
|
|
|
+ p+=1; // skip -
|
|
|
+ g.D3 = n(4);
|
|
|
+ p+=1; // skip -
|
|
|
+ if (!g.D4) g.D4=[];
|
|
|
+ g.D4[0] = n(2);
|
|
|
+ g.D4[1] = n(2);
|
|
|
+ p+=1; // skip -
|
|
|
+ for(var i=2; i<8; i++) g.D4[i] = n(2);
|
|
|
+ return g;
|
|
|
+ },
|
|
|
+
|
|
|
+ guidrToStr: function(g){
|
|
|
+ if (g.$intf) return g.$intf.$guid;
|
|
|
+ var h = rtl.hexStr;
|
|
|
+ var s='{'+h(g.D1,8)+'-'+h(g.D2,4)+'-'+h(g.D3,4)+'-'+h(g.D4[0],2)+h(g.D4[1],2)+'-';
|
|
|
+ for (var i=2; i<8; i++) s+=h(g.D4[i],2);
|
|
|
+ s+='}';
|
|
|
+ return s;
|
|
|
+ },
|
|
|
+
|
|
|
+ createTGUID: function(guid){
|
|
|
+ var TGuid = (pas.System)?pas.System.TGuid:pas.system.tguid;
|
|
|
+ var g = rtl.strToGUIDR(guid,new TGuid());
|
|
|
+ return g;
|
|
|
+ },
|
|
|
+
|
|
|
+ getIntfGUIDR: function(intfTypeOrVar){
|
|
|
+ if (!intfTypeOrVar) return null;
|
|
|
+ if (!intfTypeOrVar.$guidr){
|
|
|
+ var g = rtl.createTGUID(intfTypeOrVar.$guid);
|
|
|
+ if (!intfTypeOrVar.hasOwnProperty('$guid')) intfTypeOrVar = Object.getPrototypeOf(intfTypeOrVar);
|
|
|
+ g.$intf = intfTypeOrVar;
|
|
|
+ intfTypeOrVar.$guidr = g;
|
|
|
+ }
|
|
|
+ return intfTypeOrVar.$guidr;
|
|
|
+ },
|
|
|
+
|
|
|
+ addIntf: function (aclass, intf, map){
|
|
|
+ function jmp(fn){
|
|
|
+ if (typeof(fn)==="function"){
|
|
|
+ return function(){ return fn.apply(this.$o,arguments); };
|
|
|
+ } else {
|
|
|
+ return function(){ rtl.raiseE('EAbstractError'); };
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(!map) map = {};
|
|
|
+ var t = intf;
|
|
|
+ var item = Object.create(t);
|
|
|
+ aclass.$intfmaps[intf.$guid] = item;
|
|
|
+ do{
|
|
|
+ var names = t.$names;
|
|
|
+ if (!names) break;
|
|
|
+ for (var i=0; i<names.length; i++){
|
|
|
+ var intfname = names[i];
|
|
|
+ var fnname = map[intfname];
|
|
|
+ if (!fnname) fnname = intfname;
|
|
|
+ //console.log('addIntf: intftype='+t.$name+' index='+i+' intfname="'+intfname+'" fnname="'+fnname+'" proc='+typeof(fn));
|
|
|
+ item[intfname] = jmp(aclass[fnname]);
|
|
|
+ }
|
|
|
+ t = Object.getPrototypeOf(t);
|
|
|
+ }while(t!=null);
|
|
|
+ },
|
|
|
+
|
|
|
+ getIntfG: function (obj, guid, query){
|
|
|
+ if (!obj) return null;
|
|
|
+ //console.log('getIntfG: obj='+obj.$classname+' guid='+guid+' query='+query);
|
|
|
+ // search
|
|
|
+ var maps = obj.$intfmaps;
|
|
|
+ if (!maps) return null;
|
|
|
+ var item = maps[guid];
|
|
|
+ if (!item) return null;
|
|
|
+ // check delegation
|
|
|
+ //console.log('getIntfG: obj='+obj.$classname+' guid='+guid+' query='+query+' item='+typeof(item));
|
|
|
+ if (typeof item === 'function') return item.call(obj); // COM: contains _AddRef
|
|
|
+ // check cache
|
|
|
+ var intf = null;
|
|
|
+ if (obj.$interfaces){
|
|
|
+ intf = obj.$interfaces[guid];
|
|
|
+ //console.log('getIntfG: obj='+obj.$classname+' guid='+guid+' cache='+typeof(intf));
|
|
|
+ }
|
|
|
+ if (!intf){ // intf can be undefined!
|
|
|
+ intf = Object.create(item);
|
|
|
+ intf.$o = obj;
|
|
|
+ if (!obj.$interfaces) obj.$interfaces = {};
|
|
|
+ obj.$interfaces[guid] = intf;
|
|
|
+ }
|
|
|
+ if (typeof(query)==='object'){
|
|
|
+ // called by queryIntfT
|
|
|
+ var o = null;
|
|
|
+ if (intf.QueryInterface(rtl.getIntfGUIDR(query),
|
|
|
+ {get:function(){ return o; }, set:function(v){ o=v; }}) === 0){
|
|
|
+ return o;
|
|
|
+ } else {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ } else if(query===2){
|
|
|
+ // called by TObject.GetInterfaceByStr
|
|
|
+ if (intf.$kind === 'com') intf._AddRef();
|
|
|
+ }
|
|
|
+ return intf;
|
|
|
+ },
|
|
|
+
|
|
|
+ getIntfT: function(obj,intftype){
|
|
|
+ return rtl.getIntfG(obj,intftype.$guid);
|
|
|
+ },
|
|
|
+
|
|
|
+ queryIntfT: function(obj,intftype){
|
|
|
+ return rtl.getIntfG(obj,intftype.$guid,intftype);
|
|
|
+ },
|
|
|
+
|
|
|
+ queryIntfIsT: function(obj,intftype){
|
|
|
+ var i = rtl.queryIntfG(obj,intftype.$guid);
|
|
|
+ if (!i) return false;
|
|
|
+ if (i.$kind === 'com') i._Release();
|
|
|
+ return true;
|
|
|
+ },
|
|
|
+
|
|
|
+ asIntfT: function (obj,intftype){
|
|
|
+ var i = rtl.getIntfG(obj,intftype.$guid);
|
|
|
+ if (i!==null) return i;
|
|
|
+ rtl.raiseEInvalidCast();
|
|
|
+ },
|
|
|
+
|
|
|
+ intfIsClass: function(intf,classtype){
|
|
|
+ return (intf!=null) && (rtl.is(intf.$o,classtype));
|
|
|
+ },
|
|
|
+
|
|
|
+ intfAsClass: function(intf,classtype){
|
|
|
+ if (intf==null) return null;
|
|
|
+ return rtl.as(intf.$o,classtype);
|
|
|
+ },
|
|
|
+
|
|
|
+ intfToClass: function(intf,classtype){
|
|
|
+ if ((intf!==null) && rtl.is(intf.$o,classtype)) return intf.$o;
|
|
|
+ return null;
|
|
|
+ },
|
|
|
+
|
|
|
+ // interface reference counting
|
|
|
+ intfRefs: { // base object for temporary interface variables
|
|
|
+ ref: function(id,intf){
|
|
|
+ // called for temporary interface references needing delayed release
|
|
|
+ var old = this[id];
|
|
|
+ //console.log('rtl.intfRefs.ref: id='+id+' old="'+(old?old.$name:'null')+'" intf="'+(intf?intf.$name:'null'));
|
|
|
+ if (old){
|
|
|
+ // called again, e.g. in a loop
|
|
|
+ delete this[id];
|
|
|
+ old._Release(); // may fail
|
|
|
+ }
|
|
|
+ this[id]=intf;
|
|
|
+ return intf;
|
|
|
+ },
|
|
|
+ free: function(){
|
|
|
+ //console.log('rtl.intfRefs.free...');
|
|
|
+ for (var id in this){
|
|
|
+ if (this.hasOwnProperty(id)) this[id]._Release;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ createIntfRefs: function(){
|
|
|
+ //console.log('rtl.createIntfRefs');
|
|
|
+ return Object.create(rtl.intfRefs);
|
|
|
+ },
|
|
|
+
|
|
|
+ setIntfP: function(path,name,value,skipAddRef){
|
|
|
+ var old = path[name];
|
|
|
+ //console.log('rtl.setIntfP path='+path+' name='+name+' old="'+(old?old.$name:'null')+'" value="'+(value?value.$name:'null')+'"');
|
|
|
+ if (old === value) return;
|
|
|
+ if (old !== null){
|
|
|
+ path[name]=null;
|
|
|
+ old._Release();
|
|
|
+ }
|
|
|
+ if (value !== null){
|
|
|
+ if (!skipAddRef) value._AddRef();
|
|
|
+ path[name]=value;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ setIntfL: function(old,value,skipAddRef){
|
|
|
+ //console.log('rtl.setIntfL old="'+(old?old.$name:'null')+'" value="'+(value?value.$name:'null')+'"');
|
|
|
+ if (old !== value){
|
|
|
+ if (value!==null){
|
|
|
+ if (!skipAddRef) value._AddRef();
|
|
|
+ }
|
|
|
+ if (old!==null){
|
|
|
+ old._Release(); // Release after AddRef, to avoid double Release if Release creates an exception
|
|
|
+ }
|
|
|
+ } else if (skipAddRef){
|
|
|
+ if (old!==null){
|
|
|
+ old._Release(); // value has an AddRef
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return value;
|
|
|
+ },
|
|
|
+
|
|
|
+ _AddRef: function(intf){
|
|
|
+ //if (intf) console.log('rtl._AddRef intf="'+(intf?intf.$name:'null')+'"');
|
|
|
+ if (intf) intf._AddRef();
|
|
|
+ return intf;
|
|
|
+ },
|
|
|
+
|
|
|
+ _Release: function(intf){
|
|
|
+ //if (intf) console.log('rtl._Release intf="'+(intf?intf.$name:'null')+'"');
|
|
|
+ if (intf) intf._Release();
|
|
|
+ return intf;
|
|
|
+ },
|
|
|
+
|
|
|
+ checkMethodCall: function(obj,type){
|
|
|
+ if (rtl.isObject(obj) && rtl.is(obj,type)) return;
|
|
|
+ rtl.raiseE("EInvalidCast");
|
|
|
+ },
|
|
|
+
|
|
|
+ rc: function(i,minval,maxval){
|
|
|
+ // range check integer
|
|
|
+ if ((Math.floor(i)===i) && (i>=minval) && (i<=maxval)) return i;
|
|
|
+ rtl.raiseE('ERangeError');
|
|
|
+ },
|
|
|
+
|
|
|
+ rcc: function(c,minval,maxval){
|
|
|
+ // range check char
|
|
|
+ if ((typeof(c)==='string') && (c.length===1)){
|
|
|
+ var i = c.charCodeAt(0);
|
|
|
+ if ((i>=minval) && (i<=maxval)) return c;
|
|
|
+ }
|
|
|
+ rtl.raiseE('ERangeError');
|
|
|
+ },
|
|
|
+
|
|
|
+ rcSetCharAt: function(s,index,c){
|
|
|
+ // range check setCharAt
|
|
|
+ if ((typeof(s)!=='string') || (index<0) || (index>=s.length)) rtl.raiseE('ERangeError');
|
|
|
+ return rtl.setCharAt(s,index,c);
|
|
|
+ },
|
|
|
+
|
|
|
+ rcCharAt: function(s,index){
|
|
|
+ // range check charAt
|
|
|
+ if ((typeof(s)!=='string') || (index<0) || (index>=s.length)) rtl.raiseE('ERangeError');
|
|
|
+ return s.charAt(index);
|
|
|
+ },
|
|
|
+
|
|
|
+ rcArrR: function(arr,index){
|
|
|
+ // range check read array
|
|
|
+ if (Array.isArray(arr) && (typeof(index)==='number') && (index>=0) && (index<arr.length)){
|
|
|
+ if (arguments.length>2){
|
|
|
+ // arr,index1,index2,...
|
|
|
+ arr=arr[index];
|
|
|
+ for (var i=2; i<arguments.length; i++) arr=rtl.rcArrR(arr,arguments[i]);
|
|
|
+ return arr;
|
|
|
+ }
|
|
|
+ return arr[index];
|
|
|
+ }
|
|
|
+ rtl.raiseE('ERangeError');
|
|
|
+ },
|
|
|
+
|
|
|
+ rcArrW: function(arr,index,value){
|
|
|
+ // range check write array
|
|
|
+ // arr,index1,index2,...,value
|
|
|
+ for (var i=3; i<arguments.length; i++){
|
|
|
+ arr=rtl.rcArrR(arr,index);
|
|
|
+ index=arguments[i-1];
|
|
|
+ value=arguments[i];
|
|
|
+ }
|
|
|
+ if (Array.isArray(arr) && (typeof(index)==='number') && (index>=0) && (index<arr.length)){
|
|
|
+ return arr[index]=value;
|
|
|
+ }
|
|
|
+ rtl.raiseE('ERangeError');
|
|
|
+ },
|
|
|
+
|
|
|
+ length: function(arr){
|
|
|
+ return (arr == null) ? 0 : arr.length;
|
|
|
+ },
|
|
|
+
|
|
|
+ arraySetLength: function(arr,defaultvalue,newlength){
|
|
|
+ // multi dim: (arr,defaultvalue,dim1,dim2,...)
|
|
|
+ if (arr == null) arr = [];
|
|
|
+ var p = arguments;
|
|
|
+ function setLength(a,argNo){
|
|
|
+ var oldlen = a.length;
|
|
|
+ var newlen = p[argNo];
|
|
|
+ if (oldlen!==newlength){
|
|
|
+ a.length = newlength;
|
|
|
+ if (argNo === p.length-1){
|
|
|
+ if (rtl.isArray(defaultvalue)){
|
|
|
+ for (var i=oldlen; i<newlen; i++) a[i]=[]; // nested array
|
|
|
+ } else if (rtl.isFunction(defaultvalue)){
|
|
|
+ for (var i=oldlen; i<newlen; i++) a[i]=new defaultvalue(); // e.g. record
|
|
|
+ } else if (rtl.isObject(defaultvalue)) {
|
|
|
+ for (var i=oldlen; i<newlen; i++) a[i]={}; // e.g. set
|
|
|
+ } else {
|
|
|
+ for (var i=oldlen; i<newlen; i++) a[i]=defaultvalue;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ for (var i=oldlen; i<newlen; i++) a[i]=[]; // nested array
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (argNo < p.length-1){
|
|
|
+ // multi argNo
|
|
|
+ for (var i=0; i<newlen; i++) a[i]=setLength(a[i],argNo+1);
|
|
|
+ }
|
|
|
+ return a;
|
|
|
+ }
|
|
|
+ return setLength(arr,2);
|
|
|
+ },
|
|
|
+
|
|
|
+ arrayEq: function(a,b){
|
|
|
+ if (a===null) return b===null;
|
|
|
+ if (b===null) return false;
|
|
|
+ if (a.length!==b.length) return false;
|
|
|
+ for (var i=0; i<a.length; i++) if (a[i]!==b[i]) return false;
|
|
|
+ return true;
|
|
|
+ },
|
|
|
+
|
|
|
+ arrayClone: function(type,src,srcpos,end,dst,dstpos){
|
|
|
+ // type: 0 for references, "refset" for calling refSet(), a function for new type()
|
|
|
+ // src must not be null
|
|
|
+ // This function does not range check.
|
|
|
+ if (rtl.isFunction(type)){
|
|
|
+ for (; srcpos<end; srcpos++) dst[dstpos++] = new type(src[srcpos]); // clone record
|
|
|
+ } else if((typeof(type)==="string") && (type === 'refSet')) {
|
|
|
+ for (; srcpos<end; srcpos++) dst[dstpos++] = rtl.refSet(src[srcpos]); // ref set
|
|
|
+ } else {
|
|
|
+ for (; srcpos<end; srcpos++) dst[dstpos++] = src[srcpos]; // reference
|
|
|
+ };
|
|
|
+ },
|
|
|
+
|
|
|
+ arrayConcat: function(type){
|
|
|
+ // type: see rtl.arrayClone
|
|
|
+ var a = [];
|
|
|
+ var l = 0;
|
|
|
+ for (var i=1; i<arguments.length; i++) l+=arguments[i].length;
|
|
|
+ a.length = l;
|
|
|
+ l=0;
|
|
|
+ for (var i=1; i<arguments.length; i++){
|
|
|
+ var src = arguments[i];
|
|
|
+ if (src == null) continue;
|
|
|
+ rtl.arrayClone(type,src,0,src.length,a,l);
|
|
|
+ l+=src.length;
|
|
|
+ };
|
|
|
+ return a;
|
|
|
+ },
|
|
|
+
|
|
|
+ arrayCopy: function(type, srcarray, index, count){
|
|
|
+ // type: see rtl.arrayClone
|
|
|
+ // if count is missing, use srcarray.length
|
|
|
+ if (srcarray == null) return [];
|
|
|
+ if (index < 0) index = 0;
|
|
|
+ if (count === undefined) count=srcarray.length;
|
|
|
+ var end = index+count;
|
|
|
+ if (end>srcarray.length) end = srcarray.length;
|
|
|
+ if (index>=end) return [];
|
|
|
+ if (type===0){
|
|
|
+ return srcarray.slice(index,end);
|
|
|
+ } else {
|
|
|
+ var a = [];
|
|
|
+ a.length = end-index;
|
|
|
+ rtl.arrayClone(type,srcarray,index,end,a,0);
|
|
|
+ return a;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ setCharAt: function(s,index,c){
|
|
|
+ return s.substr(0,index)+c+s.substr(index+1);
|
|
|
+ },
|
|
|
+
|
|
|
+ getResStr: function(mod,name){
|
|
|
+ var rs = mod.$resourcestrings[name];
|
|
|
+ return rs.current?rs.current:rs.org;
|
|
|
+ },
|
|
|
+
|
|
|
+ createSet: function(){
|
|
|
+ var s = {};
|
|
|
+ for (var i=0; i<arguments.length; i++){
|
|
|
+ if (arguments[i]!=null){
|
|
|
+ s[arguments[i]]=true;
|
|
|
+ } else {
|
|
|
+ var first=arguments[i+=1];
|
|
|
+ var last=arguments[i+=1];
|
|
|
+ for(var j=first; j<=last; j++) s[j]=true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return s;
|
|
|
+ },
|
|
|
+
|
|
|
+ cloneSet: function(s){
|
|
|
+ var r = {};
|
|
|
+ for (var key in s) r[key]=true;
|
|
|
+ return r;
|
|
|
+ },
|
|
|
+
|
|
|
+ refSet: function(s){
|
|
|
+ s.$shared = true;
|
|
|
+ return s;
|
|
|
+ },
|
|
|
+
|
|
|
+ includeSet: function(s,enumvalue){
|
|
|
+ if (s.$shared) s = rtl.cloneSet(s);
|
|
|
+ s[enumvalue] = true;
|
|
|
+ return s;
|
|
|
+ },
|
|
|
+
|
|
|
+ excludeSet: function(s,enumvalue){
|
|
|
+ if (s.$shared) s = rtl.cloneSet(s);
|
|
|
+ delete s[enumvalue];
|
|
|
+ return s;
|
|
|
+ },
|
|
|
+
|
|
|
+ diffSet: function(s,t){
|
|
|
+ var r = {};
|
|
|
+ for (var key in s) if (!t[key]) r[key]=true;
|
|
|
+ delete r.$shared;
|
|
|
+ return r;
|
|
|
+ },
|
|
|
+
|
|
|
+ unionSet: function(s,t){
|
|
|
+ var r = {};
|
|
|
+ for (var key in s) r[key]=true;
|
|
|
+ for (var key in t) r[key]=true;
|
|
|
+ delete r.$shared;
|
|
|
+ return r;
|
|
|
+ },
|
|
|
+
|
|
|
+ intersectSet: function(s,t){
|
|
|
+ var r = {};
|
|
|
+ for (var key in s) if (t[key]) r[key]=true;
|
|
|
+ delete r.$shared;
|
|
|
+ return r;
|
|
|
+ },
|
|
|
+
|
|
|
+ symDiffSet: function(s,t){
|
|
|
+ var r = {};
|
|
|
+ for (var key in s) if (!t[key]) r[key]=true;
|
|
|
+ for (var key in t) if (!s[key]) r[key]=true;
|
|
|
+ delete r.$shared;
|
|
|
+ return r;
|
|
|
+ },
|
|
|
+
|
|
|
+ eqSet: function(s,t){
|
|
|
+ for (var key in s) if (!t[key] && (key!='$shared')) return false;
|
|
|
+ for (var key in t) if (!s[key] && (key!='$shared')) return false;
|
|
|
+ return true;
|
|
|
+ },
|
|
|
+
|
|
|
+ neSet: function(s,t){
|
|
|
+ return !rtl.eqSet(s,t);
|
|
|
+ },
|
|
|
+
|
|
|
+ leSet: function(s,t){
|
|
|
+ for (var key in s) if (!t[key] && (key!='$shared')) return false;
|
|
|
+ return true;
|
|
|
+ },
|
|
|
+
|
|
|
+ geSet: function(s,t){
|
|
|
+ for (var key in t) if (!s[key] && (key!='$shared')) return false;
|
|
|
+ return true;
|
|
|
+ },
|
|
|
+
|
|
|
+ strSetLength: function(s,newlen){
|
|
|
+ var oldlen = s.length;
|
|
|
+ if (oldlen > newlen){
|
|
|
+ return s.substring(0,newlen);
|
|
|
+ } else if (s.repeat){
|
|
|
+ // Note: repeat needs ECMAScript6!
|
|
|
+ return s+' '.repeat(newlen-oldlen);
|
|
|
+ } else {
|
|
|
+ while (oldlen<newlen){
|
|
|
+ s+=' ';
|
|
|
+ oldlen++;
|
|
|
+ };
|
|
|
+ return s;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ spaceLeft: function(s,width){
|
|
|
+ var l=s.length;
|
|
|
+ if (l>=width) return s;
|
|
|
+ if (s.repeat){
|
|
|
+ // Note: repeat needs ECMAScript6!
|
|
|
+ return ' '.repeat(width-l) + s;
|
|
|
+ } else {
|
|
|
+ while (l<width){
|
|
|
+ s=' '+s;
|
|
|
+ l++;
|
|
|
+ };
|
|
|
+ };
|
|
|
+ },
|
|
|
+
|
|
|
+ floatToStr : function(d,w,p){
|
|
|
+ // input 1-3 arguments: double, width, precision
|
|
|
+ if (arguments.length>2){
|
|
|
+ return rtl.spaceLeft(d.toFixed(p),w);
|
|
|
+ } else {
|
|
|
+ // exponent width
|
|
|
+ var pad = "";
|
|
|
+ var ad = Math.abs(d);
|
|
|
+ if (ad<1.0e+10) {
|
|
|
+ pad='00';
|
|
|
+ } else if (ad<1.0e+100) {
|
|
|
+ pad='0';
|
|
|
+ }
|
|
|
+ if (arguments.length<2) {
|
|
|
+ w=9;
|
|
|
+ } else if (w<9) {
|
|
|
+ w=9;
|
|
|
+ }
|
|
|
+ var p = w-8;
|
|
|
+ var s=(d>0 ? " " : "" ) + d.toExponential(p);
|
|
|
+ s=s.replace(/e(.)/,'E$1'+pad);
|
|
|
+ return rtl.spaceLeft(s,w);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ initRTTI: function(){
|
|
|
+ if (rtl.debug_rtti) rtl.debug('initRTTI');
|
|
|
+
|
|
|
+ // base types
|
|
|
+ rtl.tTypeInfo = { name: "tTypeInfo" };
|
|
|
+ function newBaseTI(name,kind,ancestor){
|
|
|
+ if (!ancestor) ancestor = rtl.tTypeInfo;
|
|
|
+ if (rtl.debug_rtti) rtl.debug('initRTTI.newBaseTI "'+name+'" '+kind+' ("'+ancestor.name+'")');
|
|
|
+ var t = Object.create(ancestor);
|
|
|
+ t.name = name;
|
|
|
+ t.kind = kind;
|
|
|
+ rtl[name] = t;
|
|
|
+ return t;
|
|
|
+ };
|
|
|
+ function newBaseInt(name,minvalue,maxvalue,ordtype){
|
|
|
+ var t = newBaseTI(name,1 /* tkInteger */,rtl.tTypeInfoInteger);
|
|
|
+ t.minvalue = minvalue;
|
|
|
+ t.maxvalue = maxvalue;
|
|
|
+ t.ordtype = ordtype;
|
|
|
+ return t;
|
|
|
+ };
|
|
|
+ newBaseTI("tTypeInfoInteger",1 /* tkInteger */);
|
|
|
+ newBaseInt("shortint",-0x80,0x7f,0);
|
|
|
+ newBaseInt("byte",0,0xff,1);
|
|
|
+ newBaseInt("smallint",-0x8000,0x7fff,2);
|
|
|
+ newBaseInt("word",0,0xffff,3);
|
|
|
+ newBaseInt("longint",-0x80000000,0x7fffffff,4);
|
|
|
+ newBaseInt("longword",0,0xffffffff,5);
|
|
|
+ newBaseInt("nativeint",-0x10000000000000,0xfffffffffffff,6);
|
|
|
+ newBaseInt("nativeuint",0,0xfffffffffffff,7);
|
|
|
+ newBaseTI("char",2 /* tkChar */);
|
|
|
+ newBaseTI("string",3 /* tkString */);
|
|
|
+ newBaseTI("tTypeInfoEnum",4 /* tkEnumeration */,rtl.tTypeInfoInteger);
|
|
|
+ newBaseTI("tTypeInfoSet",5 /* tkSet */);
|
|
|
+ newBaseTI("double",6 /* tkDouble */);
|
|
|
+ newBaseTI("boolean",7 /* tkBool */);
|
|
|
+ newBaseTI("tTypeInfoProcVar",8 /* tkProcVar */);
|
|
|
+ newBaseTI("tTypeInfoMethodVar",9 /* tkMethod */,rtl.tTypeInfoProcVar);
|
|
|
+ newBaseTI("tTypeInfoArray",10 /* tkArray */);
|
|
|
+ newBaseTI("tTypeInfoDynArray",11 /* tkDynArray */);
|
|
|
+ newBaseTI("tTypeInfoPointer",15 /* tkPointer */);
|
|
|
+ var t = newBaseTI("pointer",15 /* tkPointer */,rtl.tTypeInfoPointer);
|
|
|
+ t.reftype = null;
|
|
|
+ newBaseTI("jsvalue",16 /* tkJSValue */);
|
|
|
+ newBaseTI("tTypeInfoRefToProcVar",17 /* tkRefToProcVar */,rtl.tTypeInfoProcVar);
|
|
|
+
|
|
|
+ // member kinds
|
|
|
+ rtl.tTypeMember = {};
|
|
|
+ function newMember(name,kind){
|
|
|
+ var m = Object.create(rtl.tTypeMember);
|
|
|
+ m.name = name;
|
|
|
+ m.kind = kind;
|
|
|
+ rtl[name] = m;
|
|
|
+ };
|
|
|
+ newMember("tTypeMemberField",1); // tmkField
|
|
|
+ newMember("tTypeMemberMethod",2); // tmkMethod
|
|
|
+ newMember("tTypeMemberProperty",3); // tmkProperty
|
|
|
+
|
|
|
+ // base object for storing members: a simple object
|
|
|
+ rtl.tTypeMembers = {};
|
|
|
+
|
|
|
+ // tTypeInfoStruct - base object for tTypeInfoClass, tTypeInfoRecord, tTypeInfoInterface
|
|
|
+ var tis = newBaseTI("tTypeInfoStruct",0);
|
|
|
+ tis.$addMember = function(name,ancestor,options){
|
|
|
+ if (rtl.debug_rtti){
|
|
|
+ if (!rtl.hasString(name) || (name.charAt()==='$')) throw 'invalid member "'+name+'", this="'+this.name+'"';
|
|
|
+ if (!rtl.is(ancestor,rtl.tTypeMember)) throw 'invalid ancestor "'+ancestor+':'+ancestor.name+'", "'+this.name+'.'+name+'"';
|
|
|
+ if ((options!=undefined) && (typeof(options)!='object')) throw 'invalid options "'+options+'", "'+this.name+'.'+name+'"';
|
|
|
+ };
|
|
|
+ var t = Object.create(ancestor);
|
|
|
+ t.name = name;
|
|
|
+ this.members[name] = t;
|
|
|
+ this.names.push(name);
|
|
|
+ if (rtl.isObject(options)){
|
|
|
+ for (var key in options) if (options.hasOwnProperty(key)) t[key] = options[key];
|
|
|
+ };
|
|
|
+ return t;
|
|
|
+ };
|
|
|
+ tis.addField = function(name,type,options){
|
|
|
+ var t = this.$addMember(name,rtl.tTypeMemberField,options);
|
|
|
+ if (rtl.debug_rtti){
|
|
|
+ if (!rtl.is(type,rtl.tTypeInfo)) throw 'invalid type "'+type+'", "'+this.name+'.'+name+'"';
|
|
|
+ };
|
|
|
+ t.typeinfo = type;
|
|
|
+ this.fields.push(name);
|
|
|
+ return t;
|
|
|
+ };
|
|
|
+ tis.addFields = function(){
|
|
|
+ var i=0;
|
|
|
+ while(i<arguments.length){
|
|
|
+ var name = arguments[i++];
|
|
|
+ var type = arguments[i++];
|
|
|
+ if ((i<arguments.length) && (typeof(arguments[i])==='object')){
|
|
|
+ this.addField(name,type,arguments[i++]);
|
|
|
+ } else {
|
|
|
+ this.addField(name,type);
|
|
|
+ };
|
|
|
+ };
|
|
|
+ };
|
|
|
+ tis.addMethod = function(name,methodkind,params,result,options){
|
|
|
+ var t = this.$addMember(name,rtl.tTypeMemberMethod,options);
|
|
|
+ t.methodkind = methodkind;
|
|
|
+ t.procsig = rtl.newTIProcSig(params);
|
|
|
+ t.procsig.resulttype = result?result:null;
|
|
|
+ this.methods.push(name);
|
|
|
+ return t;
|
|
|
+ };
|
|
|
+ tis.addProperty = function(name,flags,result,getter,setter,options){
|
|
|
+ var t = this.$addMember(name,rtl.tTypeMemberProperty,options);
|
|
|
+ t.flags = flags;
|
|
|
+ t.typeinfo = result;
|
|
|
+ t.getter = getter;
|
|
|
+ t.setter = setter;
|
|
|
+ // Note: in options: params, stored, defaultvalue
|
|
|
+ if (rtl.isArray(t.params)) t.params = rtl.newTIParams(t.params);
|
|
|
+ this.properties.push(name);
|
|
|
+ if (!rtl.isString(t.stored)) t.stored = "";
|
|
|
+ return t;
|
|
|
+ };
|
|
|
+ tis.getField = function(index){
|
|
|
+ return this.members[this.fields[index]];
|
|
|
+ };
|
|
|
+ tis.getMethod = function(index){
|
|
|
+ return this.members[this.methods[index]];
|
|
|
+ };
|
|
|
+ tis.getProperty = function(index){
|
|
|
+ return this.members[this.properties[index]];
|
|
|
+ };
|
|
|
+
|
|
|
+ newBaseTI("tTypeInfoRecord",12 /* tkRecord */,rtl.tTypeInfoStruct);
|
|
|
+ newBaseTI("tTypeInfoClass",13 /* tkClass */,rtl.tTypeInfoStruct);
|
|
|
+ newBaseTI("tTypeInfoClassRef",14 /* tkClassRef */);
|
|
|
+ newBaseTI("tTypeInfoInterface",15 /* tkInterface */,rtl.tTypeInfoStruct);
|
|
|
+ },
|
|
|
+
|
|
|
+ tSectionRTTI: {
|
|
|
+ $module: null,
|
|
|
+ $inherited: function(name,ancestor,o){
|
|
|
+ if (rtl.debug_rtti){
|
|
|
+ rtl.debug('tSectionRTTI.newTI "'+(this.$module?this.$module.$name:"(no module)")
|
|
|
+ +'"."'+name+'" ('+ancestor.name+') '+(o?'init':'forward'));
|
|
|
+ };
|
|
|
+ var t = this[name];
|
|
|
+ if (t){
|
|
|
+ if (!t.$forward) throw 'duplicate type "'+name+'"';
|
|
|
+ if (!ancestor.isPrototypeOf(t)) throw 'typeinfo ancestor mismatch "'+name+'" ancestor="'+ancestor.name+'" t.name="'+t.name+'"';
|
|
|
+ } else {
|
|
|
+ t = Object.create(ancestor);
|
|
|
+ t.name = name;
|
|
|
+ t.$module = this.$module;
|
|
|
+ this[name] = t;
|
|
|
+ }
|
|
|
+ if (o){
|
|
|
+ delete t.$forward;
|
|
|
+ for (var key in o) if (o.hasOwnProperty(key)) t[key]=o[key];
|
|
|
+ } else {
|
|
|
+ t.$forward = true;
|
|
|
+ }
|
|
|
+ return t;
|
|
|
+ },
|
|
|
+ $Scope: function(name,ancestor,o){
|
|
|
+ var t=this.$inherited(name,ancestor,o);
|
|
|
+ t.members = {};
|
|
|
+ t.names = [];
|
|
|
+ t.fields = [];
|
|
|
+ t.methods = [];
|
|
|
+ t.properties = [];
|
|
|
+ return t;
|
|
|
+ },
|
|
|
+ $TI: function(name,kind,o){ var t=this.$inherited(name,rtl.tTypeInfo,o); t.kind = kind; return t; },
|
|
|
+ $Int: function(name,o){ return this.$inherited(name,rtl.tTypeInfoInteger,o); },
|
|
|
+ $Enum: function(name,o){ return this.$inherited(name,rtl.tTypeInfoEnum,o); },
|
|
|
+ $Set: function(name,o){ return this.$inherited(name,rtl.tTypeInfoSet,o); },
|
|
|
+ $StaticArray: function(name,o){ return this.$inherited(name,rtl.tTypeInfoArray,o); },
|
|
|
+ $DynArray: function(name,o){ return this.$inherited(name,rtl.tTypeInfoDynArray,o); },
|
|
|
+ $ProcVar: function(name,o){ return this.$inherited(name,rtl.tTypeInfoProcVar,o); },
|
|
|
+ $RefToProcVar: function(name,o){ return this.$inherited(name,rtl.tTypeInfoRefToProcVar,o); },
|
|
|
+ $MethodVar: function(name,o){ return this.$inherited(name,rtl.tTypeInfoMethodVar,o); },
|
|
|
+ $Record: function(name,o){ return this.$Scope(name,rtl.tTypeInfoRecord,o); },
|
|
|
+ $Class: function(name,o){ return this.$Scope(name,rtl.tTypeInfoClass,o); },
|
|
|
+ $ClassRef: function(name,o){ return this.$inherited(name,rtl.tTypeInfoClassRef,o); },
|
|
|
+ $Pointer: function(name,o){ return this.$inherited(name,rtl.tTypeInfoPointer,o); },
|
|
|
+ $Interface: function(name,o){ return this.$Scope(name,rtl.tTypeInfoInterface,o); }
|
|
|
+ },
|
|
|
+
|
|
|
+ newTIParam: function(param){
|
|
|
+ // param is an array, 0=name, 1=type, 2=optional flags
|
|
|
+ var t = {
|
|
|
+ name: param[0],
|
|
|
+ typeinfo: param[1],
|
|
|
+ flags: (rtl.isNumber(param[2]) ? param[2] : 0)
|
|
|
+ };
|
|
|
+ return t;
|
|
|
+ },
|
|
|
+
|
|
|
+ newTIParams: function(list){
|
|
|
+ // list: optional array of [paramname,typeinfo,optional flags]
|
|
|
+ var params = [];
|
|
|
+ if (rtl.isArray(list)){
|
|
|
+ for (var i=0; i<list.length; i++) params.push(rtl.newTIParam(list[i]));
|
|
|
+ };
|
|
|
+ return params;
|
|
|
+ },
|
|
|
+
|
|
|
+ newTIProcSig: function(params,result,flags){
|
|
|
+ var s = {
|
|
|
+ params: rtl.newTIParams(params),
|
|
|
+ resulttype: result,
|
|
|
+ flags: flags
|
|
|
+ };
|
|
|
+ return s;
|
|
|
+ }
|
|
|
+}
|
|
|
+rtl.module("System",[],function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+ var $impl = $mod.$impl;
|
|
|
+ this.LineEnding = "\n";
|
|
|
+ this.sLineBreak = $mod.LineEnding;
|
|
|
+ rtl.createClass($mod,"TObject",null,function () {
|
|
|
+ this.$init = function () {
|
|
|
+ };
|
|
|
+ this.$final = function () {
|
|
|
+ };
|
|
|
+ this.Create = function () {
|
|
|
+ };
|
|
|
+ this.AfterConstruction = function () {
|
|
|
+ };
|
|
|
+ this.BeforeDestruction = function () {
|
|
|
+ };
|
|
|
+ });
|
|
|
+ this.Random = function (Range) {
|
|
|
+ return Math.floor(Math.random()*Range);
|
|
|
+ };
|
|
|
+ this.Trunc = function (A) {
|
|
|
+ if (!Math.trunc) {
|
|
|
+ Math.trunc = function(v) {
|
|
|
+ v = +v;
|
|
|
+ if (!isFinite(v)) return v;
|
|
|
+ return (v - v % 1) || (v < 0 ? -0 : v === 0 ? v : 0);
|
|
|
+ };
|
|
|
+ }
|
|
|
+ $mod.Trunc = Math.trunc;
|
|
|
+ return Math.trunc(A);
|
|
|
+ };
|
|
|
+ this.Writeln = function () {
|
|
|
+ var i = 0;
|
|
|
+ var l = 0;
|
|
|
+ var s = "";
|
|
|
+ l = rtl.length(arguments) - 1;
|
|
|
+ if ($impl.WriteCallBack != null) {
|
|
|
+ for (var $l1 = 0, $end2 = l; $l1 <= $end2; $l1++) {
|
|
|
+ i = $l1;
|
|
|
+ $impl.WriteCallBack(arguments[i],i === l);
|
|
|
+ };
|
|
|
+ } else {
|
|
|
+ s = $impl.WriteBuf;
|
|
|
+ for (var $l3 = 0, $end4 = l; $l3 <= $end4; $l3++) {
|
|
|
+ i = $l3;
|
|
|
+ s = s + ("" + arguments[i]);
|
|
|
+ };
|
|
|
+ console.log(s);
|
|
|
+ $impl.WriteBuf = "";
|
|
|
+ };
|
|
|
+ };
|
|
|
+ this.SetWriteCallBack = function (H) {
|
|
|
+ var Result = null;
|
|
|
+ Result = $impl.WriteCallBack;
|
|
|
+ $impl.WriteCallBack = H;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ $mod.$init = function () {
|
|
|
+ rtl.exitcode = 0;
|
|
|
+ };
|
|
|
+},null,function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+ var $impl = $mod.$impl;
|
|
|
+ $impl.WriteBuf = "";
|
|
|
+ $impl.WriteCallBack = null;
|
|
|
+});
|
|
|
+rtl.module("JS",["System"],function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+});
|
|
|
+rtl.module("SysUtils",["System","JS"],function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+ rtl.createClass($mod,"Exception",pas.System.TObject,function () {
|
|
|
+ this.$init = function () {
|
|
|
+ pas.System.TObject.$init.call(this);
|
|
|
+ this.fMessage = "";
|
|
|
+ };
|
|
|
+ this.Create$1 = function (Msg) {
|
|
|
+ this.fMessage = Msg;
|
|
|
+ };
|
|
|
+ });
|
|
|
+ this.IntToStr = function (Value) {
|
|
|
+ var Result = "";
|
|
|
+ Result = "" + Value;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ rtl.createClass($mod,"TFormatSettings",pas.System.TObject,function () {
|
|
|
+ });
|
|
|
+ this.FormatSettings = null;
|
|
|
+ $mod.$init = function () {
|
|
|
+ $mod.FormatSettings = $mod.TFormatSettings.$create("Create");
|
|
|
+ };
|
|
|
+});
|
|
|
+rtl.module("math",["System","SysUtils"],function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+ this.Floor = function (A) {
|
|
|
+ var Result = 0;
|
|
|
+ Result = pas.System.Trunc(Math.floor(A));
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+});
|
|
|
+rtl.module("Noise",["System","SysUtils","math"],function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+ this.kNoisekPerumationMax = 256;
|
|
|
+ rtl.createClass($mod,"TNoise",pas.System.TObject,function () {
|
|
|
+ this.$init = function () {
|
|
|
+ pas.System.TObject.$init.call(this);
|
|
|
+ this.repeatValue = 0;
|
|
|
+ this.p = rtl.arraySetLength(null,0,512);
|
|
|
+ };
|
|
|
+ this.$final = function () {
|
|
|
+ this.p = undefined;
|
|
|
+ pas.System.TObject.$final.call(this);
|
|
|
+ };
|
|
|
+ this.Create$2 = function (seed) {
|
|
|
+ var i = 0;
|
|
|
+ this.repeatValue = -1;
|
|
|
+ for (i = 0; i <= 511; i++) this.p[i] = seed[i % 256];
|
|
|
+ };
|
|
|
+ this.GetValue = function (x, y, z) {
|
|
|
+ var Self = this;
|
|
|
+ var Result = 0.0;
|
|
|
+ function FMod(a, b) {
|
|
|
+ var Result = 0.0;
|
|
|
+ Result = a - (b * pas.System.Trunc(a / b));
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ var xi = 0;
|
|
|
+ var yi = 0;
|
|
|
+ var zi = 0;
|
|
|
+ var xf = 0.0;
|
|
|
+ var yf = 0.0;
|
|
|
+ var zf = 0.0;
|
|
|
+ var u = 0.0;
|
|
|
+ var v = 0.0;
|
|
|
+ var w = 0.0;
|
|
|
+ var aaa = 0;
|
|
|
+ var aba = 0;
|
|
|
+ var aab = 0;
|
|
|
+ var abb = 0;
|
|
|
+ var baa = 0;
|
|
|
+ var bba = 0;
|
|
|
+ var bab = 0;
|
|
|
+ var bbb = 0;
|
|
|
+ var x1 = 0.0;
|
|
|
+ var x2 = 0.0;
|
|
|
+ var y1 = 0.0;
|
|
|
+ var y2 = 0.0;
|
|
|
+ if (Self.repeatValue > 0) {
|
|
|
+ x = FMod(x,Self.repeatValue);
|
|
|
+ y = FMod(y,Self.repeatValue);
|
|
|
+ z = FMod(z,Self.repeatValue);
|
|
|
+ };
|
|
|
+ xi = pas.math.Floor(x) & 255;
|
|
|
+ yi = pas.math.Floor(y) & 255;
|
|
|
+ zi = pas.math.Floor(z) & 255;
|
|
|
+ xf = x - pas.math.Floor(x);
|
|
|
+ yf = y - pas.math.Floor(y);
|
|
|
+ zf = z - pas.math.Floor(z);
|
|
|
+ u = Self.Fade(xf);
|
|
|
+ v = Self.Fade(yf);
|
|
|
+ w = Self.Fade(zf);
|
|
|
+ aaa = Self.p[Self.p[Self.p[xi] + yi] + zi];
|
|
|
+ aba = Self.p[Self.p[Self.p[xi] + Self.Inc(yi)] + zi];
|
|
|
+ aab = Self.p[Self.p[Self.p[xi] + yi] + Self.Inc(zi)];
|
|
|
+ abb = Self.p[Self.p[Self.p[xi] + Self.Inc(yi)] + Self.Inc(zi)];
|
|
|
+ baa = Self.p[Self.p[Self.p[Self.Inc(xi)] + yi] + zi];
|
|
|
+ bba = Self.p[Self.p[Self.p[Self.Inc(xi)] + Self.Inc(yi)] + zi];
|
|
|
+ bab = Self.p[Self.p[Self.p[Self.Inc(xi)] + yi] + Self.Inc(zi)];
|
|
|
+ bbb = Self.p[Self.p[Self.p[Self.Inc(xi)] + Self.Inc(yi)] + Self.Inc(zi)];
|
|
|
+ x1 = Self.Lerp(Self.Grad(aaa,xf,yf,zf),Self.Grad(baa,xf - 1,yf,zf),u);
|
|
|
+ x2 = Self.Lerp(Self.Grad(aba,xf,yf - 1,zf),Self.Grad(bba,xf - 1,yf - 1,zf),u);
|
|
|
+ y1 = Self.Lerp(x1,x2,v);
|
|
|
+ x1 = Self.Lerp(Self.Grad(aab,xf,yf,zf - 1),Self.Grad(bab,xf - 1,yf,zf - 1),u);
|
|
|
+ x2 = Self.Lerp(Self.Grad(abb,xf,yf - 1,zf - 1),Self.Grad(bbb,xf - 1,yf - 1,zf - 1),u);
|
|
|
+ y2 = Self.Lerp(x1,x2,v);
|
|
|
+ Result = (Self.Lerp(y1,y2,w) + 1) / 2;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.GetValue$1 = function (x, y, z, octaves, persistence) {
|
|
|
+ var Result = 0.0;
|
|
|
+ var total = 0;
|
|
|
+ var frequency = 1;
|
|
|
+ var amplitude = 1;
|
|
|
+ var maxValue = 0;
|
|
|
+ var i = 0;
|
|
|
+ for (var $l1 = 0, $end2 = octaves - 1; $l1 <= $end2; $l1++) {
|
|
|
+ i = $l1;
|
|
|
+ total += this.GetValue(x * frequency,y * frequency,z * frequency) * amplitude;
|
|
|
+ maxValue += amplitude;
|
|
|
+ amplitude *= persistence;
|
|
|
+ frequency *= 2;
|
|
|
+ };
|
|
|
+ Result = total / maxValue;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.GetNoise = function (x, y, width, height, scale, frequency) {
|
|
|
+ var Result = 0.0;
|
|
|
+ var nx = 0.0;
|
|
|
+ var ny = 0.0;
|
|
|
+ nx = (x / width) - 0.5;
|
|
|
+ ny = (y / height) - 0.5;
|
|
|
+ Result = (this.GetValue$1(nx * scale,ny * scale,0,frequency,0.5) / 2) + 0.5;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.Inc = function (num) {
|
|
|
+ var Result = 0;
|
|
|
+ num += 1;
|
|
|
+ if (this.repeatValue > 0) num = num % this.repeatValue;
|
|
|
+ Result = num;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.Grad = function (hash, x, y, z) {
|
|
|
+ var Result = 0.0;
|
|
|
+ var $tmp1 = hash & 0xF;
|
|
|
+ if ($tmp1 === 0x0) {
|
|
|
+ Result = x + y}
|
|
|
+ else if ($tmp1 === 0x1) {
|
|
|
+ Result = -x + y}
|
|
|
+ else if ($tmp1 === 0x2) {
|
|
|
+ Result = x - y}
|
|
|
+ else if ($tmp1 === 0x3) {
|
|
|
+ Result = -x - y}
|
|
|
+ else if ($tmp1 === 0x4) {
|
|
|
+ Result = x + z}
|
|
|
+ else if ($tmp1 === 0x5) {
|
|
|
+ Result = -x + z}
|
|
|
+ else if ($tmp1 === 0x6) {
|
|
|
+ Result = x - z}
|
|
|
+ else if ($tmp1 === 0x7) {
|
|
|
+ Result = -x - z}
|
|
|
+ else if ($tmp1 === 0x8) {
|
|
|
+ Result = y + z}
|
|
|
+ else if ($tmp1 === 0x9) {
|
|
|
+ Result = -y + z}
|
|
|
+ else if ($tmp1 === 0xA) {
|
|
|
+ Result = y - z}
|
|
|
+ else if ($tmp1 === 0xB) {
|
|
|
+ Result = -y - z}
|
|
|
+ else if ($tmp1 === 0xC) {
|
|
|
+ Result = y + x}
|
|
|
+ else if ($tmp1 === 0xD) {
|
|
|
+ Result = -y + z}
|
|
|
+ else if ($tmp1 === 0xE) {
|
|
|
+ Result = y - x}
|
|
|
+ else if ($tmp1 === 0xF) {
|
|
|
+ Result = -y - z}
|
|
|
+ else {
|
|
|
+ Result = 0;
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.Fade = function (t) {
|
|
|
+ var Result = 0.0;
|
|
|
+ Result = ((t * t) * t) * ((t * ((t * 6) - 15)) + 10);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.Lerp = function (a, b, x) {
|
|
|
+ var Result = 0.0;
|
|
|
+ Result = a + (x * (b - a));
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ });
|
|
|
+ this.RandomNoiseSeed = function (seed) {
|
|
|
+ var Result = rtl.arraySetLength(null,0,256);
|
|
|
+ var i = 0;
|
|
|
+ for (i = 0; i <= 255; i++) Result[i] = pas.System.Random(256);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+});
|
|
|
+rtl.module("Matrix",["System","JS"],function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+ rtl.createClass($mod,"TMatrix",pas.System.TObject,function () {
|
|
|
+ this.$init = function () {
|
|
|
+ pas.System.TObject.$init.call(this);
|
|
|
+ this.table = null;
|
|
|
+ this.width = 0;
|
|
|
+ this.height = 0;
|
|
|
+ };
|
|
|
+ this.$final = function () {
|
|
|
+ this.table = undefined;
|
|
|
+ pas.System.TObject.$final.call(this);
|
|
|
+ };
|
|
|
+ this.Create$1 = function (w, h) {
|
|
|
+ this.width = w;
|
|
|
+ this.height = h;
|
|
|
+ this.table = new Array(this.width * this.height);
|
|
|
+ };
|
|
|
+ this.SetValue = function (x, y, value) {
|
|
|
+ this.table[this.IndexFor(x,y)] = value;
|
|
|
+ };
|
|
|
+ this.GetValue = function (x, y) {
|
|
|
+ var Result = undefined;
|
|
|
+ Result = this.table[this.IndexFor(x,y)];
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.GetWidth = function () {
|
|
|
+ var Result = 0;
|
|
|
+ Result = this.width;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.GetHeight = function () {
|
|
|
+ var Result = 0;
|
|
|
+ Result = this.height;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.IndexFor = function (x, y) {
|
|
|
+ var Result = 0;
|
|
|
+ Result = x + (y * this.height);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ });
|
|
|
+});
|
|
|
+rtl.module("Web",["System","JS"],function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+});
|
|
|
+rtl.module("webgl",["System","JS","Web"],function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+});
|
|
|
+rtl.module("GLTypes",["System","webgl","JS","math","SysUtils"],function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+ this.TVec2 = function (s) {
|
|
|
+ if (s) {
|
|
|
+ this.x = s.x;
|
|
|
+ this.y = s.y;
|
|
|
+ } else {
|
|
|
+ this.x = 0.0;
|
|
|
+ this.y = 0.0;
|
|
|
+ };
|
|
|
+ this.$equal = function (b) {
|
|
|
+ return (this.x === b.x) && (this.y === b.y);
|
|
|
+ };
|
|
|
+ };
|
|
|
+ this.TVec3 = function (s) {
|
|
|
+ if (s) {
|
|
|
+ this.x = s.x;
|
|
|
+ this.y = s.y;
|
|
|
+ this.z = s.z;
|
|
|
+ } else {
|
|
|
+ this.x = 0.0;
|
|
|
+ this.y = 0.0;
|
|
|
+ this.z = 0.0;
|
|
|
+ };
|
|
|
+ this.$equal = function (b) {
|
|
|
+ return (this.x === b.x) && ((this.y === b.y) && (this.z === b.z));
|
|
|
+ };
|
|
|
+ };
|
|
|
+ this.V3 = function (x, y, z) {
|
|
|
+ var Result = new $mod.TVec3();
|
|
|
+ Result.x = x;
|
|
|
+ Result.y = y;
|
|
|
+ Result.z = z;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.Divide = function (v, amount) {
|
|
|
+ var Result = new $mod.TVec3();
|
|
|
+ Result = new $mod.TVec3($mod.V3(v.x / amount,v.y / amount,v.z / amount));
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.Magnitude = function (v) {
|
|
|
+ var Result = 0.0;
|
|
|
+ Result = Math.sqrt((Math.pow(v.x,2) + Math.pow(v.y,2)) + Math.pow(v.z,2));
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.Normalize = function (v) {
|
|
|
+ var Result = new $mod.TVec3();
|
|
|
+ Result = new $mod.TVec3($mod.Divide(new $mod.TVec3(v),$mod.Magnitude(new $mod.TVec3(v))));
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.V2 = function (x, y) {
|
|
|
+ var Result = new $mod.TVec2();
|
|
|
+ Result.x = x;
|
|
|
+ Result.y = y;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+});
|
|
|
+rtl.module("browserconsole",["System","JS","Web"],function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+ var $impl = $mod.$impl;
|
|
|
+ this.DefaultMaxConsoleLines = 25;
|
|
|
+ this.DefaultConsoleStyle = (((((((((((".pasconsole { " + pas.System.sLineBreak) + "font-family: courier;") + pas.System.sLineBreak) + "font-size: 14px;") + pas.System.sLineBreak) + "background: #FFFFFF;") + pas.System.sLineBreak) + "color: #000000;") + pas.System.sLineBreak) + "display: block;") + pas.System.sLineBreak) + "}";
|
|
|
+ this.ConsoleElementID = "";
|
|
|
+ this.ConsoleStyle = "";
|
|
|
+ this.MaxConsoleLines = 0;
|
|
|
+ this.ConsoleLinesToBrowserLog = false;
|
|
|
+ this.ResetConsole = function () {
|
|
|
+ if ($impl.LinesParent === null) return;
|
|
|
+ while ($impl.LinesParent.firstElementChild !== null) $impl.LinesParent.removeChild($impl.LinesParent.firstElementChild);
|
|
|
+ $impl.AppendLine();
|
|
|
+ };
|
|
|
+ this.InitConsole = function () {
|
|
|
+ if ($impl.ConsoleElement === null) return;
|
|
|
+ if ($impl.ConsoleElement.nodeName.toLowerCase() !== "body") {
|
|
|
+ while ($impl.ConsoleElement.firstElementChild !== null) $impl.ConsoleElement.removeChild($impl.ConsoleElement.firstElementChild);
|
|
|
+ };
|
|
|
+ $impl.StyleElement = document.createElement("style");
|
|
|
+ $impl.StyleElement.innerText = $mod.ConsoleStyle;
|
|
|
+ $impl.ConsoleElement.appendChild($impl.StyleElement);
|
|
|
+ $impl.LinesParent = document.createElement("div");
|
|
|
+ $impl.ConsoleElement.appendChild($impl.LinesParent);
|
|
|
+ };
|
|
|
+ this.HookConsole = function () {
|
|
|
+ $impl.ConsoleElement = null;
|
|
|
+ if ($mod.ConsoleElementID !== "") $impl.ConsoleElement = document.getElementById($mod.ConsoleElementID);
|
|
|
+ if ($impl.ConsoleElement === null) $impl.ConsoleElement = document.body;
|
|
|
+ if ($impl.ConsoleElement === null) return;
|
|
|
+ $mod.InitConsole();
|
|
|
+ $mod.ResetConsole();
|
|
|
+ pas.System.SetWriteCallBack($impl.WriteConsole);
|
|
|
+ };
|
|
|
+ $mod.$init = function () {
|
|
|
+ $mod.ConsoleLinesToBrowserLog = true;
|
|
|
+ $mod.ConsoleElementID = "pasjsconsole";
|
|
|
+ $mod.ConsoleStyle = $mod.DefaultConsoleStyle;
|
|
|
+ $mod.MaxConsoleLines = 25;
|
|
|
+ $mod.HookConsole();
|
|
|
+ };
|
|
|
+},null,function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+ var $impl = $mod.$impl;
|
|
|
+ $impl.LastLine = null;
|
|
|
+ $impl.StyleElement = null;
|
|
|
+ $impl.LinesParent = null;
|
|
|
+ $impl.ConsoleElement = null;
|
|
|
+ $impl.AppendLine = function () {
|
|
|
+ var CurrentCount = 0;
|
|
|
+ var S = null;
|
|
|
+ CurrentCount = 0;
|
|
|
+ S = $impl.LinesParent.firstChild;
|
|
|
+ while (S != null) {
|
|
|
+ CurrentCount += 1;
|
|
|
+ S = S.nextSibling;
|
|
|
+ };
|
|
|
+ while (CurrentCount > $mod.MaxConsoleLines) {
|
|
|
+ CurrentCount -= 1;
|
|
|
+ $impl.LinesParent.removeChild($impl.LinesParent.firstChild);
|
|
|
+ };
|
|
|
+ $impl.LastLine = document.createElement("div");
|
|
|
+ $impl.LastLine.className = "pasconsole";
|
|
|
+ $impl.LinesParent.appendChild($impl.LastLine);
|
|
|
+ };
|
|
|
+ $impl.WriteConsole = function (S, NewLine) {
|
|
|
+ var CL = "";
|
|
|
+ CL = $impl.LastLine.innerText;
|
|
|
+ CL = CL + ("" + S);
|
|
|
+ $impl.LastLine.innerText = CL;
|
|
|
+ if (NewLine) {
|
|
|
+ if ($mod.ConsoleLinesToBrowserLog) window.console.log(CL);
|
|
|
+ $impl.AppendLine();
|
|
|
+ };
|
|
|
+ };
|
|
|
+});
|
|
|
+rtl.module("Mat4",["System","browserconsole","JS","math"],function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+ var $impl = $mod.$impl;
|
|
|
+ rtl.createClass($mod,"TMat4",pas.System.TObject,function () {
|
|
|
+ this.$init = function () {
|
|
|
+ pas.System.TObject.$init.call(this);
|
|
|
+ this.RawComponents = rtl.arraySetLength(null,0.0,4,4);
|
|
|
+ };
|
|
|
+ this.$final = function () {
|
|
|
+ this.RawComponents = undefined;
|
|
|
+ pas.System.TObject.$final.call(this);
|
|
|
+ };
|
|
|
+ this.Identity = function () {
|
|
|
+ this.RawComponents[0][0] = 1.0;
|
|
|
+ this.RawComponents[0][1] = 0.0;
|
|
|
+ this.RawComponents[0][2] = 0.0;
|
|
|
+ this.RawComponents[0][3] = 0.0;
|
|
|
+ this.RawComponents[1][0] = 0.0;
|
|
|
+ this.RawComponents[1][1] = 1.0;
|
|
|
+ this.RawComponents[1][2] = 0.0;
|
|
|
+ this.RawComponents[1][3] = 0.0;
|
|
|
+ this.RawComponents[2][0] = 0.0;
|
|
|
+ this.RawComponents[2][1] = 0.0;
|
|
|
+ this.RawComponents[2][2] = 1.0;
|
|
|
+ this.RawComponents[2][3] = 0.0;
|
|
|
+ this.RawComponents[3][0] = 0.0;
|
|
|
+ this.RawComponents[3][1] = 0.0;
|
|
|
+ this.RawComponents[3][2] = 0.0;
|
|
|
+ this.RawComponents[3][3] = 1.0;
|
|
|
+ };
|
|
|
+ this.Translate = function (tx, ty, tz) {
|
|
|
+ this.RawComponents[0][0] = 1.0;
|
|
|
+ this.RawComponents[0][1] = 0.0;
|
|
|
+ this.RawComponents[0][2] = 0.0;
|
|
|
+ this.RawComponents[0][3] = 0.0;
|
|
|
+ this.RawComponents[1][0] = 0.0;
|
|
|
+ this.RawComponents[1][1] = 1.0;
|
|
|
+ this.RawComponents[1][2] = 0.0;
|
|
|
+ this.RawComponents[1][3] = 0.0;
|
|
|
+ this.RawComponents[2][0] = 0.0;
|
|
|
+ this.RawComponents[2][1] = 0.0;
|
|
|
+ this.RawComponents[2][2] = 1.0;
|
|
|
+ this.RawComponents[2][3] = 0.0;
|
|
|
+ this.RawComponents[3][0] = tx;
|
|
|
+ this.RawComponents[3][1] = ty;
|
|
|
+ this.RawComponents[3][2] = tz;
|
|
|
+ this.RawComponents[3][3] = 1.0;
|
|
|
+ };
|
|
|
+ this.Perspective = function (fovy, Aspect, zNear, zFar) {
|
|
|
+ var Sine = 0.0;
|
|
|
+ var Cotangent = 0.0;
|
|
|
+ var ZDelta = 0.0;
|
|
|
+ var Radians = 0.0;
|
|
|
+ Radians = (fovy * 0.5) * 0.017453292519944444;
|
|
|
+ ZDelta = zFar - zNear;
|
|
|
+ Sine = Math.sin(Radians);
|
|
|
+ if (!(((ZDelta === 0) || (Sine === 0)) || (Aspect === 0))) {
|
|
|
+ Cotangent = Math.cos(Radians) / Sine;
|
|
|
+ this.RawComponents = $impl.Matrix4x4Identity.RawComponents.slice(0);
|
|
|
+ this.RawComponents[0][0] = Cotangent / Aspect;
|
|
|
+ this.RawComponents[1][1] = Cotangent;
|
|
|
+ this.RawComponents[2][2] = -(zFar + zNear) / ZDelta;
|
|
|
+ this.RawComponents[2][3] = -1 - 0;
|
|
|
+ this.RawComponents[3][2] = -((2.0 * zNear) * zFar) / ZDelta;
|
|
|
+ this.RawComponents[3][3] = 0.0;
|
|
|
+ };
|
|
|
+ };
|
|
|
+ this.Multiply = function (m) {
|
|
|
+ var Result = null;
|
|
|
+ Result = $mod.TMat4.$create("Identity");
|
|
|
+ Result.RawComponents[0][0] = (((m.RawComponents[0][0] * this.RawComponents[0][0]) + (m.RawComponents[0][1] * this.RawComponents[1][0])) + (m.RawComponents[0][2] * this.RawComponents[2][0])) + (m.RawComponents[0][3] * this.RawComponents[3][0]);
|
|
|
+ Result.RawComponents[0][1] = (((m.RawComponents[0][0] * this.RawComponents[0][1]) + (m.RawComponents[0][1] * this.RawComponents[1][1])) + (m.RawComponents[0][2] * this.RawComponents[2][1])) + (m.RawComponents[0][3] * this.RawComponents[3][1]);
|
|
|
+ Result.RawComponents[0][2] = (((m.RawComponents[0][0] * this.RawComponents[0][2]) + (m.RawComponents[0][1] * this.RawComponents[1][2])) + (m.RawComponents[0][2] * this.RawComponents[2][2])) + (m.RawComponents[0][3] * this.RawComponents[3][2]);
|
|
|
+ Result.RawComponents[0][3] = (((m.RawComponents[0][0] * this.RawComponents[0][3]) + (m.RawComponents[0][1] * this.RawComponents[1][3])) + (m.RawComponents[0][2] * this.RawComponents[2][3])) + (m.RawComponents[0][3] * this.RawComponents[3][3]);
|
|
|
+ Result.RawComponents[1][0] = (((m.RawComponents[1][0] * this.RawComponents[0][0]) + (m.RawComponents[1][1] * this.RawComponents[1][0])) + (m.RawComponents[1][2] * this.RawComponents[2][0])) + (m.RawComponents[1][3] * this.RawComponents[3][0]);
|
|
|
+ Result.RawComponents[1][1] = (((m.RawComponents[1][0] * this.RawComponents[0][1]) + (m.RawComponents[1][1] * this.RawComponents[1][1])) + (m.RawComponents[1][2] * this.RawComponents[2][1])) + (m.RawComponents[1][3] * this.RawComponents[3][1]);
|
|
|
+ Result.RawComponents[1][2] = (((m.RawComponents[1][0] * this.RawComponents[0][2]) + (m.RawComponents[1][1] * this.RawComponents[1][2])) + (m.RawComponents[1][2] * this.RawComponents[2][2])) + (m.RawComponents[1][3] * this.RawComponents[3][2]);
|
|
|
+ Result.RawComponents[1][3] = (((m.RawComponents[1][0] * this.RawComponents[0][3]) + (m.RawComponents[1][1] * this.RawComponents[1][3])) + (m.RawComponents[1][2] * this.RawComponents[2][3])) + (m.RawComponents[1][3] * this.RawComponents[3][3]);
|
|
|
+ Result.RawComponents[2][0] = (((m.RawComponents[2][0] * this.RawComponents[0][0]) + (m.RawComponents[2][1] * this.RawComponents[1][0])) + (m.RawComponents[2][2] * this.RawComponents[2][0])) + (m.RawComponents[2][3] * this.RawComponents[3][0]);
|
|
|
+ Result.RawComponents[2][1] = (((m.RawComponents[2][0] * this.RawComponents[0][1]) + (m.RawComponents[2][1] * this.RawComponents[1][1])) + (m.RawComponents[2][2] * this.RawComponents[2][1])) + (m.RawComponents[2][3] * this.RawComponents[3][1]);
|
|
|
+ Result.RawComponents[2][2] = (((m.RawComponents[2][0] * this.RawComponents[0][2]) + (m.RawComponents[2][1] * this.RawComponents[1][2])) + (m.RawComponents[2][2] * this.RawComponents[2][2])) + (m.RawComponents[2][3] * this.RawComponents[3][2]);
|
|
|
+ Result.RawComponents[2][3] = (((m.RawComponents[2][0] * this.RawComponents[0][3]) + (m.RawComponents[2][1] * this.RawComponents[1][3])) + (m.RawComponents[2][2] * this.RawComponents[2][3])) + (m.RawComponents[2][3] * this.RawComponents[3][3]);
|
|
|
+ Result.RawComponents[3][0] = (((m.RawComponents[3][0] * this.RawComponents[0][0]) + (m.RawComponents[3][1] * this.RawComponents[1][0])) + (m.RawComponents[3][2] * this.RawComponents[2][0])) + (m.RawComponents[3][3] * this.RawComponents[3][0]);
|
|
|
+ Result.RawComponents[3][1] = (((m.RawComponents[3][0] * this.RawComponents[0][1]) + (m.RawComponents[3][1] * this.RawComponents[1][1])) + (m.RawComponents[3][2] * this.RawComponents[2][1])) + (m.RawComponents[3][3] * this.RawComponents[3][1]);
|
|
|
+ Result.RawComponents[3][2] = (((m.RawComponents[3][0] * this.RawComponents[0][2]) + (m.RawComponents[3][1] * this.RawComponents[1][2])) + (m.RawComponents[3][2] * this.RawComponents[2][2])) + (m.RawComponents[3][3] * this.RawComponents[3][2]);
|
|
|
+ Result.RawComponents[3][3] = (((m.RawComponents[3][0] * this.RawComponents[0][3]) + (m.RawComponents[3][1] * this.RawComponents[1][3])) + (m.RawComponents[3][2] * this.RawComponents[2][3])) + (m.RawComponents[3][3] * this.RawComponents[3][3]);
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.Inverse = function () {
|
|
|
+ var Result = null;
|
|
|
+ var t0 = 0.0;
|
|
|
+ var t4 = 0.0;
|
|
|
+ var t8 = 0.0;
|
|
|
+ var t12 = 0.0;
|
|
|
+ var d = 0.0;
|
|
|
+ t0 = ((((((this.RawComponents[1][1] * this.RawComponents[2][2]) * this.RawComponents[3][3]) - ((this.RawComponents[1][1] * this.RawComponents[2][3]) * this.RawComponents[3][2])) - ((this.RawComponents[2][1] * this.RawComponents[1][2]) * this.RawComponents[3][3])) + ((this.RawComponents[2][1] * this.RawComponents[1][3]) * this.RawComponents[3][2])) + ((this.RawComponents[3][1] * this.RawComponents[1][2]) * this.RawComponents[2][3])) - ((this.RawComponents[3][1] * this.RawComponents[1][3]) * this.RawComponents[2][2]);
|
|
|
+ t4 = ((((-((this.RawComponents[1][0] * this.RawComponents[2][2]) * this.RawComponents[3][3]) + ((this.RawComponents[1][0] * this.RawComponents[2][3]) * this.RawComponents[3][2])) + ((this.RawComponents[2][0] * this.RawComponents[1][2]) * this.RawComponents[3][3])) - ((this.RawComponents[2][0] * this.RawComponents[1][3]) * this.RawComponents[3][2])) - ((this.RawComponents[3][0] * this.RawComponents[1][2]) * this.RawComponents[2][3])) + ((this.RawComponents[3][0] * this.RawComponents[1][3]) * this.RawComponents[2][2]);
|
|
|
+ t8 = ((((((this.RawComponents[1][0] * this.RawComponents[2][1]) * this.RawComponents[3][3]) - ((this.RawComponents[1][0] * this.RawComponents[2][3]) * this.RawComponents[3][1])) - ((this.RawComponents[2][0] * this.RawComponents[1][1]) * this.RawComponents[3][3])) + ((this.RawComponents[2][0] * this.RawComponents[1][3]) * this.RawComponents[3][1])) + ((this.RawComponents[3][0] * this.RawComponents[1][1]) * this.RawComponents[2][3])) - ((this.RawComponents[3][0] * this.RawComponents[1][3]) * this.RawComponents[2][1]);
|
|
|
+ t12 = ((((-((this.RawComponents[1][0] * this.RawComponents[2][1]) * this.RawComponents[3][2]) + ((this.RawComponents[1][0] * this.RawComponents[2][2]) * this.RawComponents[3][1])) + ((this.RawComponents[2][0] * this.RawComponents[1][1]) * this.RawComponents[3][2])) - ((this.RawComponents[2][0] * this.RawComponents[1][2]) * this.RawComponents[3][1])) - ((this.RawComponents[3][0] * this.RawComponents[1][1]) * this.RawComponents[2][2])) + ((this.RawComponents[3][0] * this.RawComponents[1][2]) * this.RawComponents[2][1]);
|
|
|
+ d = (((this.RawComponents[0][0] * t0) + (this.RawComponents[0][1] * t4)) + (this.RawComponents[0][2] * t8)) + (this.RawComponents[0][3] * t12);
|
|
|
+ Result = $mod.TMat4.$create("Identity");
|
|
|
+ if (d !== 0.0) {
|
|
|
+ d = 1.0 / d;
|
|
|
+ Result.RawComponents[0][0] = t0 * d;
|
|
|
+ Result.RawComponents[0][1] = (((((-((this.RawComponents[0][1] * this.RawComponents[2][2]) * this.RawComponents[3][3]) + ((this.RawComponents[0][1] * this.RawComponents[2][3]) * this.RawComponents[3][2])) + ((this.RawComponents[2][1] * this.RawComponents[0][2]) * this.RawComponents[3][3])) - ((this.RawComponents[2][1] * this.RawComponents[0][3]) * this.RawComponents[3][2])) - ((this.RawComponents[3][1] * this.RawComponents[0][2]) * this.RawComponents[2][3])) + ((this.RawComponents[3][1] * this.RawComponents[0][3]) * this.RawComponents[2][2])) * d;
|
|
|
+ Result.RawComponents[0][2] = (((((((this.RawComponents[0][1] * this.RawComponents[1][2]) * this.RawComponents[3][3]) - ((this.RawComponents[0][1] * this.RawComponents[1][3]) * this.RawComponents[3][2])) - ((this.RawComponents[1][1] * this.RawComponents[0][2]) * this.RawComponents[3][3])) + ((this.RawComponents[1][1] * this.RawComponents[0][3]) * this.RawComponents[3][2])) + ((this.RawComponents[3][1] * this.RawComponents[0][2]) * this.RawComponents[1][3])) - ((this.RawComponents[3][1] * this.RawComponents[0][3]) * this.RawComponents[1][2])) * d;
|
|
|
+ Result.RawComponents[0][3] = (((((-((this.RawComponents[0][1] * this.RawComponents[1][2]) * this.RawComponents[2][3]) + ((this.RawComponents[0][1] * this.RawComponents[1][3]) * this.RawComponents[2][2])) + ((this.RawComponents[1][1] * this.RawComponents[0][2]) * this.RawComponents[2][3])) - ((this.RawComponents[1][1] * this.RawComponents[0][3]) * this.RawComponents[2][2])) - ((this.RawComponents[2][1] * this.RawComponents[0][2]) * this.RawComponents[1][3])) + ((this.RawComponents[2][1] * this.RawComponents[0][3]) * this.RawComponents[1][2])) * d;
|
|
|
+ Result.RawComponents[1][0] = t4 * d;
|
|
|
+ Result.RawComponents[1][1] = (((((((this.RawComponents[0][0] * this.RawComponents[2][2]) * this.RawComponents[3][3]) - ((this.RawComponents[0][0] * this.RawComponents[2][3]) * this.RawComponents[3][2])) - ((this.RawComponents[2][0] * this.RawComponents[0][2]) * this.RawComponents[3][3])) + ((this.RawComponents[2][0] * this.RawComponents[0][3]) * this.RawComponents[3][2])) + ((this.RawComponents[3][0] * this.RawComponents[0][2]) * this.RawComponents[2][3])) - ((this.RawComponents[3][0] * this.RawComponents[0][3]) * this.RawComponents[2][2])) * d;
|
|
|
+ Result.RawComponents[1][2] = (((((-((this.RawComponents[0][0] * this.RawComponents[1][2]) * this.RawComponents[3][3]) + ((this.RawComponents[0][0] * this.RawComponents[1][3]) * this.RawComponents[3][2])) + ((this.RawComponents[1][0] * this.RawComponents[0][2]) * this.RawComponents[3][3])) - ((this.RawComponents[1][0] * this.RawComponents[0][3]) * this.RawComponents[3][2])) - ((this.RawComponents[3][0] * this.RawComponents[0][2]) * this.RawComponents[1][3])) + ((this.RawComponents[3][0] * this.RawComponents[0][3]) * this.RawComponents[1][2])) * d;
|
|
|
+ Result.RawComponents[1][3] = (((((((this.RawComponents[0][0] * this.RawComponents[1][2]) * this.RawComponents[2][3]) - ((this.RawComponents[0][0] * this.RawComponents[1][3]) * this.RawComponents[2][2])) - ((this.RawComponents[1][0] * this.RawComponents[0][2]) * this.RawComponents[2][3])) + ((this.RawComponents[1][0] * this.RawComponents[0][3]) * this.RawComponents[2][2])) + ((this.RawComponents[2][0] * this.RawComponents[0][2]) * this.RawComponents[1][3])) - ((this.RawComponents[2][0] * this.RawComponents[0][3]) * this.RawComponents[1][2])) * d;
|
|
|
+ Result.RawComponents[2][0] = t8 * d;
|
|
|
+ Result.RawComponents[2][1] = (((((-((this.RawComponents[0][0] * this.RawComponents[2][1]) * this.RawComponents[3][3]) + ((this.RawComponents[0][0] * this.RawComponents[2][3]) * this.RawComponents[3][1])) + ((this.RawComponents[2][0] * this.RawComponents[0][1]) * this.RawComponents[3][3])) - ((this.RawComponents[2][0] * this.RawComponents[0][3]) * this.RawComponents[3][1])) - ((this.RawComponents[3][0] * this.RawComponents[0][1]) * this.RawComponents[2][3])) + ((this.RawComponents[3][0] * this.RawComponents[0][3]) * this.RawComponents[2][1])) * d;
|
|
|
+ Result.RawComponents[2][2] = (((((((this.RawComponents[0][0] * this.RawComponents[1][1]) * this.RawComponents[3][3]) - ((this.RawComponents[0][0] * this.RawComponents[1][3]) * this.RawComponents[3][1])) - ((this.RawComponents[1][0] * this.RawComponents[0][1]) * this.RawComponents[3][3])) + ((this.RawComponents[1][0] * this.RawComponents[0][3]) * this.RawComponents[3][1])) + ((this.RawComponents[3][0] * this.RawComponents[0][1]) * this.RawComponents[1][3])) - ((this.RawComponents[3][0] * this.RawComponents[0][3]) * this.RawComponents[1][1])) * d;
|
|
|
+ Result.RawComponents[2][3] = (((((-((this.RawComponents[0][0] * this.RawComponents[1][1]) * this.RawComponents[2][3]) + ((this.RawComponents[0][0] * this.RawComponents[1][3]) * this.RawComponents[2][1])) + ((this.RawComponents[1][0] * this.RawComponents[0][1]) * this.RawComponents[2][3])) - ((this.RawComponents[1][0] * this.RawComponents[0][3]) * this.RawComponents[2][1])) - ((this.RawComponents[2][0] * this.RawComponents[0][1]) * this.RawComponents[1][3])) + ((this.RawComponents[2][0] * this.RawComponents[0][3]) * this.RawComponents[1][1])) * d;
|
|
|
+ Result.RawComponents[3][0] = t12 * d;
|
|
|
+ Result.RawComponents[3][1] = (((((((this.RawComponents[0][0] * this.RawComponents[2][1]) * this.RawComponents[3][2]) - ((this.RawComponents[0][0] * this.RawComponents[2][2]) * this.RawComponents[3][1])) - ((this.RawComponents[2][0] * this.RawComponents[0][1]) * this.RawComponents[3][2])) + ((this.RawComponents[2][0] * this.RawComponents[0][2]) * this.RawComponents[3][1])) + ((this.RawComponents[3][0] * this.RawComponents[0][1]) * this.RawComponents[2][2])) - ((this.RawComponents[3][0] * this.RawComponents[0][2]) * this.RawComponents[2][1])) * d;
|
|
|
+ Result.RawComponents[3][2] = (((((-((this.RawComponents[0][0] * this.RawComponents[1][1]) * this.RawComponents[3][2]) + ((this.RawComponents[0][0] * this.RawComponents[1][2]) * this.RawComponents[3][1])) + ((this.RawComponents[1][0] * this.RawComponents[0][1]) * this.RawComponents[3][2])) - ((this.RawComponents[1][0] * this.RawComponents[0][2]) * this.RawComponents[3][1])) - ((this.RawComponents[3][0] * this.RawComponents[0][1]) * this.RawComponents[1][2])) + ((this.RawComponents[3][0] * this.RawComponents[0][2]) * this.RawComponents[1][1])) * d;
|
|
|
+ Result.RawComponents[3][3] = (((((((this.RawComponents[0][0] * this.RawComponents[1][1]) * this.RawComponents[2][2]) - ((this.RawComponents[0][0] * this.RawComponents[1][2]) * this.RawComponents[2][1])) - ((this.RawComponents[1][0] * this.RawComponents[0][1]) * this.RawComponents[2][2])) + ((this.RawComponents[1][0] * this.RawComponents[0][2]) * this.RawComponents[2][1])) + ((this.RawComponents[2][0] * this.RawComponents[0][1]) * this.RawComponents[1][2])) - ((this.RawComponents[2][0] * this.RawComponents[0][2]) * this.RawComponents[1][1])) * d;
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.CopyList = function () {
|
|
|
+ var Result = [];
|
|
|
+ var x = 0;
|
|
|
+ var y = 0;
|
|
|
+ var list = null;
|
|
|
+ list = new Array();
|
|
|
+ for (x = 0; x <= 3; x++) for (y = 0; y <= 3; y++) list.push(this.RawComponents[x][y]);
|
|
|
+ Result = list;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ });
|
|
|
+ $mod.$init = function () {
|
|
|
+ $impl.Matrix4x4Identity = $mod.TMat4.$create("Identity");
|
|
|
+ };
|
|
|
+},null,function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+ var $impl = $mod.$impl;
|
|
|
+ $impl.PI = 3.14159265359;
|
|
|
+ $impl.DEG2RAD = 3.14159265359 / 180.0;
|
|
|
+ $impl.Matrix4x4Identity = null;
|
|
|
+});
|
|
|
+rtl.module("GLUtils",["System","Mat4","GLTypes","browserconsole","Web","webgl","JS","math","SysUtils"],function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+ var $impl = $mod.$impl;
|
|
|
+ rtl.createClass($mod,"TShader",pas.System.TObject,function () {
|
|
|
+ this.$init = function () {
|
|
|
+ pas.System.TObject.$init.call(this);
|
|
|
+ this.gl = null;
|
|
|
+ this.vertexShader = null;
|
|
|
+ this.fragmentShader = null;
|
|
|
+ this.programID = null;
|
|
|
+ };
|
|
|
+ this.$final = function () {
|
|
|
+ this.gl = undefined;
|
|
|
+ this.vertexShader = undefined;
|
|
|
+ this.fragmentShader = undefined;
|
|
|
+ this.programID = undefined;
|
|
|
+ pas.System.TObject.$final.call(this);
|
|
|
+ };
|
|
|
+ this.Create$1 = function (context, vertexShaderSource, fragmentShaderSource) {
|
|
|
+ this.gl = context;
|
|
|
+ this.vertexShader = this.CreateShader(this.gl.VERTEX_SHADER,vertexShaderSource);
|
|
|
+ this.fragmentShader = this.CreateShader(this.gl.FRAGMENT_SHADER,fragmentShaderSource);
|
|
|
+ };
|
|
|
+ this.Compile = function () {
|
|
|
+ this.programID = this.gl.createProgram();
|
|
|
+ this.gl.attachShader(this.programID,this.vertexShader);
|
|
|
+ this.gl.attachShader(this.programID,this.fragmentShader);
|
|
|
+ };
|
|
|
+ this.Link = function () {
|
|
|
+ this.gl.linkProgram(this.programID);
|
|
|
+ if (!this.gl.getProgramParameter(this.programID,this.gl.LINK_STATUS)) {
|
|
|
+ $impl.Fatal(this.gl.getProgramInfoLog(this.programID));
|
|
|
+ };
|
|
|
+ };
|
|
|
+ this.Use = function () {
|
|
|
+ this.gl.useProgram(this.programID);
|
|
|
+ };
|
|
|
+ this.BindAttribLocation = function (index, name) {
|
|
|
+ this.gl.bindAttribLocation(this.programID,index,name);
|
|
|
+ };
|
|
|
+ this.SetUniformMat4 = function (name, value) {
|
|
|
+ var list = [];
|
|
|
+ list = value.CopyList();
|
|
|
+ this.gl.uniformMatrix4fv(this.GetUniformLocation(name),false,list);
|
|
|
+ $mod.GLFatal(this.gl,"gl.uniformMatrix4fv");
|
|
|
+ };
|
|
|
+ this.SetUniformVec3 = function (name, value) {
|
|
|
+ this.gl.uniform3f(this.GetUniformLocation(name),value.x,value.y,value.z);
|
|
|
+ $mod.GLFatal(this.gl,"gl.uniform3fv");
|
|
|
+ };
|
|
|
+ this.SetUniformFloat = function (name, value) {
|
|
|
+ this.gl.uniform1f(this.GetUniformLocation(name),value);
|
|
|
+ $mod.GLFatal(this.gl,"gl.uniform1f");
|
|
|
+ };
|
|
|
+ this.GetUniformLocation = function (name) {
|
|
|
+ var Result = null;
|
|
|
+ Result = this.gl.getUniformLocation(this.programID,name);
|
|
|
+ $mod.GLFatal(this.gl,"gl.getUniformLocation");
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.CreateShader = function (theType, source) {
|
|
|
+ var Result = null;
|
|
|
+ var shader = null;
|
|
|
+ shader = this.gl.createShader(theType);
|
|
|
+ if (shader === null) $impl.Fatal("create shader failed");
|
|
|
+ this.gl.shaderSource(shader,source);
|
|
|
+ this.gl.compileShader(shader);
|
|
|
+ if (this.gl.getShaderParameter(shader,this.gl.COMPILE_STATUS)) {
|
|
|
+ return shader;
|
|
|
+ } else {
|
|
|
+ $impl.Fatal$1(this.gl.getShaderInfoLog(shader));
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ });
|
|
|
+ this.TModelData = function (s) {
|
|
|
+ if (s) {
|
|
|
+ this.verticies = s.verticies;
|
|
|
+ this.indicies = s.indicies;
|
|
|
+ this.floatsPerVertex = s.floatsPerVertex;
|
|
|
+ } else {
|
|
|
+ this.verticies = null;
|
|
|
+ this.indicies = null;
|
|
|
+ this.floatsPerVertex = 0;
|
|
|
+ };
|
|
|
+ this.$equal = function (b) {
|
|
|
+ return (this.verticies === b.verticies) && ((this.indicies === b.indicies) && (this.floatsPerVertex === b.floatsPerVertex));
|
|
|
+ };
|
|
|
+ };
|
|
|
+ this.kModelVertexFloats = (3 + 2) + 3;
|
|
|
+ this.TModelVertex = function (s) {
|
|
|
+ if (s) {
|
|
|
+ this.pos = new pas.GLTypes.TVec3(s.pos);
|
|
|
+ this.texCoord = new pas.GLTypes.TVec2(s.texCoord);
|
|
|
+ this.normal = new pas.GLTypes.TVec3(s.normal);
|
|
|
+ } else {
|
|
|
+ this.pos = new pas.GLTypes.TVec3();
|
|
|
+ this.texCoord = new pas.GLTypes.TVec2();
|
|
|
+ this.normal = new pas.GLTypes.TVec3();
|
|
|
+ };
|
|
|
+ this.$equal = function (b) {
|
|
|
+ return this.pos.$equal(b.pos) && (this.texCoord.$equal(b.texCoord) && this.normal.$equal(b.normal));
|
|
|
+ };
|
|
|
+ };
|
|
|
+ this.ModelVertexAddToArray = function (vertex, list) {
|
|
|
+ list.push(vertex.pos.x);
|
|
|
+ list.push(vertex.pos.y);
|
|
|
+ list.push(vertex.pos.z);
|
|
|
+ list.push(vertex.texCoord.x);
|
|
|
+ list.push(vertex.texCoord.y);
|
|
|
+ list.push(vertex.normal.x);
|
|
|
+ list.push(vertex.normal.y);
|
|
|
+ list.push(vertex.normal.z);
|
|
|
+ };
|
|
|
+ rtl.createClass($mod,"TModel",pas.System.TObject,function () {
|
|
|
+ this.$init = function () {
|
|
|
+ pas.System.TObject.$init.call(this);
|
|
|
+ this.gl = null;
|
|
|
+ this.data = new $mod.TModelData();
|
|
|
+ this.vertexBuffer = null;
|
|
|
+ this.indexBuffer = null;
|
|
|
+ };
|
|
|
+ this.$final = function () {
|
|
|
+ this.gl = undefined;
|
|
|
+ this.data = undefined;
|
|
|
+ this.vertexBuffer = undefined;
|
|
|
+ this.indexBuffer = undefined;
|
|
|
+ pas.System.TObject.$final.call(this);
|
|
|
+ };
|
|
|
+ this.Create$1 = function (context, modelData) {
|
|
|
+ this.gl = context;
|
|
|
+ this.data = new $mod.TModelData(modelData);
|
|
|
+ this.Load();
|
|
|
+ };
|
|
|
+ this.Draw = function () {
|
|
|
+ this.gl.bindBuffer(this.gl.ARRAY_BUFFER,this.vertexBuffer);
|
|
|
+ this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER,this.indexBuffer);
|
|
|
+ this.EnableAttributes();
|
|
|
+ this.gl.drawElements(this.gl.TRIANGLES,this.data.indicies.length,this.gl.UNSIGNED_SHORT,0);
|
|
|
+ this.gl.bindBuffer(this.gl.ARRAY_BUFFER,null);
|
|
|
+ this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER,null);
|
|
|
+ };
|
|
|
+ this.EnableAttributes = function () {
|
|
|
+ var offset = 0;
|
|
|
+ var stride = 0;
|
|
|
+ offset = 0;
|
|
|
+ stride = this.data.floatsPerVertex * $mod.GLSizeof(WebGLRenderingContext.FLOAT);
|
|
|
+ this.gl.enableVertexAttribArray(0);
|
|
|
+ this.gl.vertexAttribPointer(0,3,this.gl.FLOAT,false,stride,offset);
|
|
|
+ offset += $mod.GLSizeof(WebGLRenderingContext.FLOAT) * 3;
|
|
|
+ this.gl.enableVertexAttribArray(1);
|
|
|
+ this.gl.vertexAttribPointer(1,2,this.gl.FLOAT,false,stride,offset);
|
|
|
+ offset += $mod.GLSizeof(WebGLRenderingContext.FLOAT) * 2;
|
|
|
+ this.gl.enableVertexAttribArray(2);
|
|
|
+ this.gl.vertexAttribPointer(2,3,this.gl.FLOAT,false,stride,offset);
|
|
|
+ offset += $mod.GLSizeof(WebGLRenderingContext.FLOAT) * 3;
|
|
|
+ };
|
|
|
+ this.Load = function () {
|
|
|
+ this.indexBuffer = this.gl.createBuffer();
|
|
|
+ this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER,this.indexBuffer);
|
|
|
+ this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER,this.data.indicies,this.gl.STATIC_DRAW);
|
|
|
+ this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER,null);
|
|
|
+ this.vertexBuffer = this.gl.createBuffer();
|
|
|
+ this.gl.bindBuffer(this.gl.ARRAY_BUFFER,this.vertexBuffer);
|
|
|
+ this.gl.bufferData(this.gl.ARRAY_BUFFER,this.data.verticies,this.gl.STATIC_DRAW);
|
|
|
+ this.gl.bindBuffer(this.gl.ARRAY_BUFFER,null);
|
|
|
+ };
|
|
|
+ });
|
|
|
+ this.GLSizeof = function (glType) {
|
|
|
+ var Result = 0;
|
|
|
+ var $tmp1 = glType;
|
|
|
+ if (($tmp1 === WebGLRenderingContext.UNSIGNED_BYTE) || ($tmp1 === WebGLRenderingContext.BYTE)) {
|
|
|
+ Result = 1}
|
|
|
+ else if (($tmp1 === WebGLRenderingContext.SHORT) || ($tmp1 === WebGLRenderingContext.UNSIGNED_SHORT)) {
|
|
|
+ Result = 2}
|
|
|
+ else if (($tmp1 === WebGLRenderingContext.INT) || ($tmp1 === WebGLRenderingContext.UNSIGNED_INT)) {
|
|
|
+ Result = 4}
|
|
|
+ else if ($tmp1 === WebGLRenderingContext.FLOAT) {
|
|
|
+ Result = 4}
|
|
|
+ else {
|
|
|
+ $impl.Fatal("GLSizeof type is invalid.");
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.GLFatal = function (gl, messageString) {
|
|
|
+ var error = 0;
|
|
|
+ error = gl.getError();
|
|
|
+ if (error !== WebGLRenderingContext.NO_ERROR) {
|
|
|
+ var $tmp1 = error;
|
|
|
+ if ($tmp1 === WebGLRenderingContext.INVALID_VALUE) {
|
|
|
+ messageString = messageString + " (GL_INVALID_VALUE)"}
|
|
|
+ else if ($tmp1 === WebGLRenderingContext.INVALID_OPERATION) {
|
|
|
+ messageString = messageString + " (GL_INVALID_OPERATION)"}
|
|
|
+ else if ($tmp1 === WebGLRenderingContext.INVALID_ENUM) {
|
|
|
+ messageString = messageString + " (GL_INVALID_ENUM)"}
|
|
|
+ else {
|
|
|
+ messageString = (messageString + " ") + pas.SysUtils.IntToStr(error);
|
|
|
+ };
|
|
|
+ $impl.Fatal(messageString);
|
|
|
+ };
|
|
|
+ };
|
|
|
+},null,function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+ var $impl = $mod.$impl;
|
|
|
+ $impl.Fatal = function (messageString) {
|
|
|
+ pas.System.Writeln("*** FATAL: ",messageString);
|
|
|
+ throw pas.SysUtils.Exception.$create("Create$1",["FATAL"]);
|
|
|
+ };
|
|
|
+ $impl.Fatal$1 = function (messageString) {
|
|
|
+ pas.System.Writeln("*** FATAL: ",messageString);
|
|
|
+ throw pas.SysUtils.Exception.$create("Create$1",["FATAL"]);
|
|
|
+ };
|
|
|
+});
|
|
|
+rtl.module("Terrain",["System","Noise","Matrix","GLTypes","GLUtils","webgl","JS","math"],function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+ rtl.createClass($mod,"TTerrain",pas.System.TObject,function () {
|
|
|
+ this.$init = function () {
|
|
|
+ pas.System.TObject.$init.call(this);
|
|
|
+ this.noise$1 = null;
|
|
|
+ this.gl = null;
|
|
|
+ this.noiseOffset = new pas.GLTypes.TVec2();
|
|
|
+ this.terrainSize = 0;
|
|
|
+ this.terrainResolution = 0;
|
|
|
+ this.heights = null;
|
|
|
+ this.model = null;
|
|
|
+ };
|
|
|
+ this.$final = function () {
|
|
|
+ this.noise$1 = undefined;
|
|
|
+ this.gl = undefined;
|
|
|
+ this.noiseOffset = undefined;
|
|
|
+ this.heights = undefined;
|
|
|
+ this.model = undefined;
|
|
|
+ pas.System.TObject.$final.call(this);
|
|
|
+ };
|
|
|
+ this.Create$2 = function (context, inNoise, size, resolution, offset) {
|
|
|
+ this.gl = context;
|
|
|
+ this.noise$1 = inNoise;
|
|
|
+ this.noiseOffset = new pas.GLTypes.TVec2(offset);
|
|
|
+ this.terrainSize = size;
|
|
|
+ this.terrainResolution = resolution;
|
|
|
+ };
|
|
|
+ this.GetHeightAtPoint = function (x, y) {
|
|
|
+ var Result = 0.0;
|
|
|
+ Result = rtl.getNumber(this.heights.GetValue(x,y));
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.GetWidth = function () {
|
|
|
+ var Result = 0;
|
|
|
+ Result = this.heights.GetWidth();
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.GetHeight = function () {
|
|
|
+ var Result = 0;
|
|
|
+ Result = this.heights.GetHeight();
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.Draw = function () {
|
|
|
+ this.model.Draw();
|
|
|
+ };
|
|
|
+ this.Generate = function () {
|
|
|
+ var vertex = new pas.GLUtils.TModelVertex();
|
|
|
+ var topLeft = 0;
|
|
|
+ var topRight = 0;
|
|
|
+ var bottomLeft = 0;
|
|
|
+ var bottomRight = 0;
|
|
|
+ var x = 0;
|
|
|
+ var y = 0;
|
|
|
+ var gz = 0;
|
|
|
+ var gx = 0;
|
|
|
+ var verticies = null;
|
|
|
+ var indicies = null;
|
|
|
+ var data = new pas.GLUtils.TModelData();
|
|
|
+ if (this.noise$1 === null) this.noise$1 = pas.Noise.TNoise.$create("Create$2",[pas.Noise.RandomNoiseSeed(1).slice(0)]);
|
|
|
+ this.heights = pas.Matrix.TMatrix.$create("Create$1",[this.terrainResolution,this.terrainResolution]);
|
|
|
+ verticies = new Array();
|
|
|
+ indicies = new Array();
|
|
|
+ for (var $l1 = 0, $end2 = this.heights.GetWidth() - 1; $l1 <= $end2; $l1++) {
|
|
|
+ y = $l1;
|
|
|
+ for (var $l3 = 0, $end4 = this.heights.GetHeight() - 1; $l3 <= $end4; $l3++) {
|
|
|
+ x = $l3;
|
|
|
+ vertex.pos.x = (x / (this.heights.GetWidth() - 1)) * this.terrainSize;
|
|
|
+ vertex.pos.y = this.GetHeightForVertex(x,y,pas.System.Trunc(this.noiseOffset.x) + x,pas.System.Trunc(this.noiseOffset.y) + y);
|
|
|
+ vertex.pos.z = (y / (this.heights.GetHeight() - 1)) * this.terrainSize;
|
|
|
+ this.heights.SetValue(x,y,vertex.pos.y);
|
|
|
+ vertex.normal = new pas.GLTypes.TVec3(this.CalculateNormal(x,y,pas.System.Trunc(this.noiseOffset.x) + x,pas.System.Trunc(this.noiseOffset.y) + y));
|
|
|
+ vertex.texCoord.x = x / (this.heights.GetWidth() - 1);
|
|
|
+ vertex.texCoord.y = y / (this.heights.GetHeight() - 1);
|
|
|
+ pas.GLUtils.ModelVertexAddToArray(new pas.GLUtils.TModelVertex(vertex),verticies);
|
|
|
+ };
|
|
|
+ };
|
|
|
+ for (var $l5 = 0, $end6 = this.heights.GetWidth() - 2; $l5 <= $end6; $l5++) {
|
|
|
+ gz = $l5;
|
|
|
+ for (var $l7 = 0, $end8 = this.heights.GetHeight() - 2; $l7 <= $end8; $l7++) {
|
|
|
+ gx = $l7;
|
|
|
+ topLeft = (gz * this.heights.GetWidth()) + gx;
|
|
|
+ topRight = topLeft + 1;
|
|
|
+ bottomLeft = ((gz + 1) * this.heights.GetWidth()) + gx;
|
|
|
+ bottomRight = bottomLeft + 1;
|
|
|
+ indicies.push(topLeft);
|
|
|
+ indicies.push(bottomLeft);
|
|
|
+ indicies.push(topRight);
|
|
|
+ indicies.push(topRight);
|
|
|
+ indicies.push(bottomLeft);
|
|
|
+ indicies.push(bottomRight);
|
|
|
+ };
|
|
|
+ };
|
|
|
+ data.verticies = new Float32Array(verticies);
|
|
|
+ data.indicies = new Uint16Array(indicies);
|
|
|
+ data.floatsPerVertex = 8;
|
|
|
+ this.model = pas.GLUtils.TModel.$create("Create$1",[this.gl,new pas.GLUtils.TModelData(data)]);
|
|
|
+ };
|
|
|
+ this.GetHeightForVertex = function (localX, localY, x, y) {
|
|
|
+ var Result = 0.0;
|
|
|
+ Result = this.noise$1.GetNoise(x,y,this.heights.GetWidth(),this.heights.GetHeight(),4,3);
|
|
|
+ Result = Math.pow(Result,5);
|
|
|
+ Result = (Result * 20) - 6;
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ this.CalculateNormal = function (localX, localY, x, y) {
|
|
|
+ var Result = new pas.GLTypes.TVec3();
|
|
|
+ var heightL = 0.0;
|
|
|
+ var heightR = 0.0;
|
|
|
+ var heightD = 0.0;
|
|
|
+ var heightU = 0.0;
|
|
|
+ heightL = this.GetHeightForVertex(localX,localY,x - 1,y);
|
|
|
+ heightR = this.GetHeightForVertex(localX,localY,x + 1,y);
|
|
|
+ heightD = this.GetHeightForVertex(localX,localY,x,y - 1);
|
|
|
+ heightU = this.GetHeightForVertex(localX,localY,x,y + 1);
|
|
|
+ Result = new pas.GLTypes.TVec3(pas.GLTypes.V3(heightL - heightR,2.0,heightD - heightU));
|
|
|
+ Result = new pas.GLTypes.TVec3(pas.GLTypes.Normalize(new pas.GLTypes.TVec3(Result)));
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ });
|
|
|
+});
|
|
|
+rtl.module("program",["System","Terrain","Noise","Mat4","GLUtils","GLTypes","SysUtils","browserconsole","Web","webgl","JS","math"],function () {
|
|
|
+ "use strict";
|
|
|
+ var $mod = this;
|
|
|
+ this.gl = null;
|
|
|
+ this.shader = null;
|
|
|
+ this.projTransform = null;
|
|
|
+ this.viewTransform = null;
|
|
|
+ this.modelTransform = null;
|
|
|
+ this.debugConsole = null;
|
|
|
+ this.canvasAnimationHandler = 0;
|
|
|
+ this.maps = null;
|
|
|
+ this.camera = new pas.GLTypes.TVec3();
|
|
|
+ this.lightPosition = new pas.GLTypes.TVec3();
|
|
|
+ this.terrainNoise = null;
|
|
|
+ this.terrainSize = 64 * 3;
|
|
|
+ this.terrainResolution = 128;
|
|
|
+ this.flySpeed = 1.3;
|
|
|
+ this.visiblity = 4;
|
|
|
+ rtl.createClass($mod,"TTilingTerrain",pas.Terrain.TTerrain,function () {
|
|
|
+ this.$init = function () {
|
|
|
+ pas.Terrain.TTerrain.$init.call(this);
|
|
|
+ this.neighbor = null;
|
|
|
+ };
|
|
|
+ this.$final = function () {
|
|
|
+ this.neighbor = undefined;
|
|
|
+ pas.Terrain.TTerrain.$final.call(this);
|
|
|
+ };
|
|
|
+ this.GetHeightForVertex = function (localX, localY, x, y) {
|
|
|
+ var Result = 0.0;
|
|
|
+ if ((localY === 0) && (this.neighbor !== null)) {
|
|
|
+ Result = this.neighbor.GetHeightAtPoint(localX,(localY + this.neighbor.GetWidth()) - 1)}
|
|
|
+ else {
|
|
|
+ Result = this.noise$1.GetNoise(x,y,this.GetWidth(),this.GetHeight(),6,3);
|
|
|
+ Result = Math.pow(Result,9) * 60;
|
|
|
+ };
|
|
|
+ return Result;
|
|
|
+ };
|
|
|
+ });
|
|
|
+ this.DrawCanvas = function () {
|
|
|
+ var terrainCoord = new pas.GLTypes.TVec3();
|
|
|
+ var startIndex = 0;
|
|
|
+ var endIndex = 0;
|
|
|
+ var i = 0;
|
|
|
+ var map = null;
|
|
|
+ $mod.gl.clear($mod.gl.COLOR_BUFFER_BIT + $mod.gl.DEPTH_BUFFER_BIT);
|
|
|
+ $mod.viewTransform = pas.Mat4.TMat4.$create("Identity");
|
|
|
+ $mod.viewTransform = $mod.viewTransform.Multiply(pas.Mat4.TMat4.$create("Translate",[$mod.camera.x,$mod.camera.y,$mod.camera.z]));
|
|
|
+ $mod.shader.SetUniformMat4("viewTransform",$mod.viewTransform);
|
|
|
+ $mod.lightPosition.z += $mod.flySpeed;
|
|
|
+ $mod.shader.SetUniformVec3("lightPosition",new pas.GLTypes.TVec3($mod.lightPosition));
|
|
|
+ $mod.camera.z -= $mod.flySpeed;
|
|
|
+ $mod.camera.y = -($mod.terrainSize / 4) + (Math.sin($mod.camera.z / $mod.terrainSize) * 14);
|
|
|
+ $mod.camera.x = -($mod.terrainSize / 2) + (Math.cos($mod.camera.z / $mod.terrainSize) * 20);
|
|
|
+ terrainCoord = new pas.GLTypes.TVec3(pas.GLTypes.Divide(new pas.GLTypes.TVec3($mod.camera),$mod.terrainSize));
|
|
|
+ endIndex = pas.System.Trunc(Math.abs(terrainCoord.z));
|
|
|
+ startIndex = endIndex - $mod.visiblity;
|
|
|
+ if (startIndex < 0) startIndex = 0;
|
|
|
+ for (var $l1 = startIndex, $end2 = endIndex; $l1 <= $end2; $l1++) {
|
|
|
+ i = $l1;
|
|
|
+ if (($mod.maps.length === 0) || (($mod.maps.length === i) && ($mod.maps[i] == null))) {
|
|
|
+ map = $mod.TTilingTerrain.$create("Create$2",[$mod.gl,$mod.terrainNoise,$mod.terrainSize,$mod.terrainResolution,new pas.GLTypes.TVec2(pas.GLTypes.V2(0,$mod.terrainSize * i))]);
|
|
|
+ if ((i - 1) >= 0) map.neighbor = rtl.getObject($mod.maps[i - 1]);
|
|
|
+ map.Generate();
|
|
|
+ $mod.maps.push(map);
|
|
|
+ if ((startIndex - 1) >= 0) $mod.maps[startIndex - 1] = null;
|
|
|
+ };
|
|
|
+ map = rtl.getObject($mod.maps[i]);
|
|
|
+ $mod.modelTransform = pas.Mat4.TMat4.$create("Identity");
|
|
|
+ $mod.modelTransform = $mod.modelTransform.Multiply(pas.Mat4.TMat4.$create("Translate",[0,0,$mod.terrainSize * i]));
|
|
|
+ $mod.shader.SetUniformMat4("modelTransform",$mod.modelTransform);
|
|
|
+ map.Draw();
|
|
|
+ };
|
|
|
+ };
|
|
|
+ this.AnimateCanvas = function (time) {
|
|
|
+ $mod.DrawCanvas();
|
|
|
+ if ($mod.canvasAnimationHandler !== 0) $mod.canvasAnimationHandler = window.requestAnimationFrame($mod.AnimateCanvas);
|
|
|
+ };
|
|
|
+ this.StartAnimatingCanvas = function () {
|
|
|
+ $mod.canvasAnimationHandler = window.requestAnimationFrame($mod.AnimateCanvas);
|
|
|
+ };
|
|
|
+ this.canvas = null;
|
|
|
+ this.vertexShaderSource = "";
|
|
|
+ this.fragmentShaderSource = "";
|
|
|
+ this.element = null;
|
|
|
+ this.texture = null;
|
|
|
+ $mod.$main = function () {
|
|
|
+ $mod.debugConsole = document.getElementById("debug-console");
|
|
|
+ $mod.canvas = document.createElement("canvas");
|
|
|
+ $mod.canvas.width = 800;
|
|
|
+ $mod.canvas.height = 600;
|
|
|
+ document.body.appendChild($mod.canvas);
|
|
|
+ $mod.gl = $mod.canvas.getContext("webgl");
|
|
|
+ if ($mod.gl === null) {
|
|
|
+ pas.System.Writeln("failed to load webgl!");
|
|
|
+ return;
|
|
|
+ };
|
|
|
+ $mod.vertexShaderSource = document.getElementById("vertex.glsl").textContent;
|
|
|
+ $mod.fragmentShaderSource = document.getElementById("fragment.glsl").textContent;
|
|
|
+ $mod.shader = pas.GLUtils.TShader.$create("Create$1",[$mod.gl,$mod.vertexShaderSource,$mod.fragmentShaderSource]);
|
|
|
+ $mod.shader.Compile();
|
|
|
+ $mod.shader.BindAttribLocation(0,"in_position");
|
|
|
+ $mod.shader.BindAttribLocation(1,"in_texCoord");
|
|
|
+ $mod.shader.BindAttribLocation(2,"in_normal");
|
|
|
+ $mod.shader.Link();
|
|
|
+ $mod.shader.Use();
|
|
|
+ $mod.gl.clearColor(0.9,0.9,0.9,1);
|
|
|
+ $mod.gl.viewport(0,0,$mod.canvas.width,$mod.canvas.height);
|
|
|
+ $mod.gl.clear($mod.gl.COLOR_BUFFER_BIT);
|
|
|
+ $mod.gl.enable($mod.gl.DEPTH_TEST);
|
|
|
+ $mod.gl.enable($mod.gl.BLEND);
|
|
|
+ $mod.gl.enable($mod.gl.CULL_FACE);
|
|
|
+ $mod.gl.cullFace($mod.gl.BACK);
|
|
|
+ $mod.projTransform = pas.Mat4.TMat4.$create("Perspective",[60.0,$mod.canvas.width / $mod.canvas.height,0.1,2000]);
|
|
|
+ $mod.shader.SetUniformMat4("projTransform",$mod.projTransform);
|
|
|
+ $mod.viewTransform = pas.Mat4.TMat4.$create("Identity");
|
|
|
+ $mod.shader.SetUniformMat4("viewTransform",$mod.viewTransform);
|
|
|
+ $mod.shader.SetUniformMat4("inverseViewTransform",$mod.viewTransform.Inverse());
|
|
|
+ $mod.lightPosition = new pas.GLTypes.TVec3(pas.GLTypes.V3(0,$mod.terrainSize / 2,-($mod.terrainSize / 2)));
|
|
|
+ $mod.shader.SetUniformVec3("lightPosition",new pas.GLTypes.TVec3($mod.lightPosition));
|
|
|
+ $mod.shader.SetUniformVec3("lightColor",new pas.GLTypes.TVec3(pas.GLTypes.V3(1,1,1)));
|
|
|
+ $mod.shader.SetUniformFloat("shineDamper",1000);
|
|
|
+ $mod.shader.SetUniformFloat("reflectivity",1);
|
|
|
+ $mod.gl.clear($mod.gl.COLOR_BUFFER_BIT + $mod.gl.DEPTH_BUFFER_BIT);
|
|
|
+ $mod.modelTransform = pas.Mat4.TMat4.$create("Identity");
|
|
|
+ $mod.shader.SetUniformMat4("modelTransform",$mod.modelTransform);
|
|
|
+ $mod.camera.x = -($mod.terrainSize / 2);
|
|
|
+ $mod.camera.y = -($mod.terrainSize / 4);
|
|
|
+ $mod.camera.z = -($mod.terrainSize / 2);
|
|
|
+ $mod.element = document.getElementById("terrain-texture");
|
|
|
+ $mod.texture = $mod.gl.createTexture();
|
|
|
+ $mod.gl.bindTexture($mod.gl.TEXTURE_2D,$mod.texture);
|
|
|
+ $mod.gl.texParameteri($mod.gl.TEXTURE_2D,$mod.gl.TEXTURE_WRAP_S,$mod.gl.CLAMP_TO_EDGE);
|
|
|
+ $mod.gl.texParameteri($mod.gl.TEXTURE_2D,$mod.gl.TEXTURE_WRAP_T,$mod.gl.CLAMP_TO_EDGE);
|
|
|
+ $mod.gl.texParameteri($mod.gl.TEXTURE_2D,$mod.gl.TEXTURE_MIN_FILTER,$mod.gl.LINEAR);
|
|
|
+ $mod.gl.texParameteri($mod.gl.TEXTURE_2D,$mod.gl.TEXTURE_MAG_FILTER,$mod.gl.LINEAR);
|
|
|
+ $mod.gl.texImage2D($mod.gl.TEXTURE_2D,0,$mod.gl.RGBA,$mod.gl.RGBA,$mod.gl.UNSIGNED_BYTE,rtl.getObject($mod.element));
|
|
|
+ $mod.terrainNoise = pas.Noise.TNoise.$create("Create$2",[pas.Noise.RandomNoiseSeed(1).slice(0)]);
|
|
|
+ $mod.maps = new Array();
|
|
|
+ $mod.StartAnimatingCanvas();
|
|
|
+ };
|
|
|
+});
|