2 |
3 | mxframework-core
4 |
5 |
6 |
7 |
8 |
9 | com.googlecode.jslint4java.eclipse.jsLintBuilder
10 |
11 |
12 |
13 |
14 |
15 | com.googlecode.jslint4java.eclipse.jsLintNature
16 |
17 |
18 |
--------------------------------------------------------------------------------
/scripts/mx/MXComponent.js:
--------------------------------------------------------------------------------
1 | MXComponent = function()
2 | {
3 | var me = $extend(MXObject);
4 | var base = {};
5 |
6 | me.autoInit = true;
7 | me.initialized = false;
8 |
9 | base._ = me._;
10 | me._ = function(p_options)
11 | {
12 | if (me.canConstruct())
13 | {
14 | base._(p_options);
15 | if (me.autoInit)
16 | {
17 | me.init(p_options);
18 | }
19 | }
20 | };
21 |
22 | me.init = function(p_options)
23 | {
24 | me.initialized = true;
25 | };
26 |
27 | me.bind = function(p_eventType, p_function, p_once)
28 | {
29 | var eventType = "on" + p_eventType;
30 | if (typeof (me[eventType]) === "undefined")
31 | {
32 | return me;
33 | }
34 | if (isEmpty(me[eventType]))
35 | {
36 | me[eventType] = new MXEvent();
37 | }
38 | me[eventType].addEventListener(p_function, p_once);
39 | return me;
40 | };
41 | me.on = me.bind;
42 |
43 | me.bindOnce = function(p_eventType, p_function)
44 | {
45 | me.bind(p_eventType, p_function, true);
46 | return me;
47 | };
48 | me.once = me.bindOnce;
49 |
50 | me.unbind = function(p_eventType, p_function)
51 | {
52 | if (isEmpty(p_eventType) && isEmpty(p_function))
53 | {
54 | for ( var name in me)
55 | {
56 | if (notEmpty(me[name]) && me[name].constructor === MXEvent)
57 | {
58 | me[name].clear();
59 | me[name] = null;
60 | }
61 | }
62 | }
63 | else
64 | {
65 | var eventType = "on" + p_eventType;
66 | if (typeof (me[eventType]) === "undefined")
67 | {
68 | return me;
69 | }
70 |
71 | if (notEmpty(me[eventType]))
72 | {
73 | if (notEmpty(p_function))
74 | {
75 | me[eventType].removeEventListener(p_function);
76 | }
77 | else
78 | {
79 | me[eventType].clear();
80 | }
81 | }
82 | }
83 | return me;
84 | };
85 | me.off = me.unbind;
86 |
87 | me.hasBound = function(p_eventType)
88 | {
89 | var eventType = "on" + p_eventType;
90 | if (typeof (me[eventType]) === "undefined")
91 | {
92 | return false;
93 | }
94 | if (notEmpty(me[eventType]))
95 | {
96 | return me[eventType].listeners.length > 0;
97 | }
98 | else
99 | {
100 | return false;
101 | }
102 | };
103 |
104 | me.trigger = function(p_eventType, p_args)
105 | {
106 | var eventType = "on" + p_eventType;
107 | if (typeof (me[eventType]) === "undefined")
108 | {
109 | return me;
110 | }
111 | if (notEmpty(me[eventType]))
112 | {
113 | var e = null;
114 | if (notEmpty(p_args))
115 | {
116 | e = p_args;
117 | }
118 | else
119 | {
120 | e = {};
121 | }
122 | e.target = me;
123 |
124 | e.type = p_eventType;
125 |
126 | me[eventType].fire(e);
127 | }
128 | return me;
129 | };
130 |
131 | base.instanceOf = me.instanceOf;
132 | me.instanceOf = function(p_class)
133 | {
134 | if (p_class === MXComponent)
135 | {
136 | return true;
137 | }
138 | return base.instanceOf(p_class);
139 | };
140 |
141 | base.dispose = me.dispose;
142 | me.dispose = function()
143 | {
144 | me.unbind();
145 | base.dispose();
146 | };
147 |
148 | return me.endOfClass(arguments);
149 | };
150 | MXComponent.className = "MXComponent";
151 |
--------------------------------------------------------------------------------
/scripts/mx/MXEvent.js:
--------------------------------------------------------------------------------
1 | MXEvent = function()
2 | {
3 | var me = this;
4 |
5 | me.listeners = [];
6 |
7 | var _onceListeners = null;
8 |
9 | me.addEventListener = function(p_listener, p_once)
10 | {
11 | if (typeof (p_listener) === "function" && !me.listeners.contains(p_listener))
12 | {
13 | me.listeners.add(p_listener);
14 | if (p_once === true)
15 | {
16 | if (isEmpty(_onceListeners))
17 | {
18 | _onceListeners = [];
19 | }
20 | _onceListeners.add(p_listener);
21 | }
22 | }
23 | };
24 |
25 | me.insertEventListener = function(p_index, p_listener, p_once)
26 | {
27 | if (typeof (p_listener) === "function" && !me.listeners.contains(p_listener))
28 | {
29 | me.listeners.insert(p_index, p_listener);
30 | if (p_once === true)
31 | {
32 | if (isEmpty(_onceListeners))
33 | {
34 | _onceListeners = [];
35 | }
36 | _onceListeners.add(p_listener);
37 | }
38 | }
39 | };
40 |
41 | me.removeEventListener = function(p_listener)
42 | {
43 | if (notEmpty(_onceListeners))
44 | {
45 | _onceListeners.remove(p_listener);
46 | }
47 | return me.listeners.remove(p_listener);
48 | };
49 |
50 | me.clear = function()
51 | {
52 | if (notEmpty(_onceListeners))
53 | {
54 | _onceListeners.clear();
55 | _onceListeners = null;
56 | }
57 | me.listeners.clear();
58 | };
59 |
60 | me.fire = function(e)
61 | {
62 | if (notEmpty(me.listeners) && me.listeners.length > 0)
63 | {
64 | var listeners = me.listeners.clone();
65 | var toBeRemoved = [];
66 | var i = 0;
67 | for (i = 0; i < listeners.length; i++)
68 | {
69 | var listener = listeners[i];
70 | listener(e);
71 |
72 | if (notEmpty(_onceListeners) && _onceListeners.contains(listener))
73 | {
74 | toBeRemoved.add(listener);
75 | _onceListeners.remove(listener);
76 | if (_onceListeners.length === 0)
77 | {
78 | _onceListeners = null;
79 | }
80 | }
81 | }
82 | for (i = 0; i < toBeRemoved.length; i++)
83 | {
84 | me.listeners.remove(toBeRemoved[i]);
85 | }
86 | listeners = null;
87 | }
88 | };
89 |
90 | return me;
91 | };
92 | MXEvent.className = "MXEvent";
93 |
--------------------------------------------------------------------------------
/scripts/mx/MXObject.js:
--------------------------------------------------------------------------------
1 | MXObject = function()
2 | {
3 | var me = this;
4 |
5 | me.__class__ = MXObject;
6 | me.__superClasses__ = [];
7 |
8 | me.constructed = false;
9 | me.disposed = false;
10 |
11 | me._ = function(p_options)
12 | {
13 | if (me.canConstruct())
14 | {
15 | if (isPlainObject(p_options))
16 | {
17 | var isEventDispatcher = typeof (me.on) === "function";
18 | for ( var key in p_options)
19 | {
20 | if (p_options.hasOwnProperty(key))
21 | {
22 | var option = p_options[key];
23 | if (isEventDispatcher && typeof (me[key] === "object") && typeof (option) === "function" && key.startsWith("on"))
24 | {
25 | me.on(key.substr(2), option);
26 | }
27 | else
28 | {
29 | me[key] = option;
30 | }
31 |
32 | option = null;
33 | }
34 | }
35 | }
36 | me.constructed = true;
37 |
38 | p_options = null;
39 | }
40 | };
41 |
42 | me.getClass = function()
43 | {
44 | return me.__class__;
45 | };
46 |
47 | me.getClassName = function()
48 | {
49 | var cls = me.getClass();
50 | if (notEmpty(cls))
51 | {
52 | return cls.className;
53 | }
54 | return null;
55 | };
56 |
57 | me.getNamespace = function()
58 | {
59 | var clsName = me.getClassName();
60 | if (notEmpty(clsName))
61 | {
62 | var parts = clsName.split(".");
63 | if (parts.length > 1)
64 | {
65 | parts = parts.slice(0, parts.length - 1);
66 | return parts.join(".");
67 | }
68 | }
69 | return null;
70 | };
71 |
72 | me.getModuleName = function()
73 | {
74 | var ns = me.getNamespace();
75 | if (notEmpty(ns))
76 | {
77 | var parts = ns.split(".");
78 | if (parts.length > 0)
79 | {
80 | return parts[0];
81 | }
82 | else
83 | {
84 | return ns;
85 | }
86 | }
87 | return null;
88 | };
89 |
90 | me.getResourcePath = function(p_name, p_ext, p_auto2x)
91 | {
92 | var path = me.getModuleName() + ".res." + p_name;
93 | return mx.getResourcePath(path, p_ext, p_auto2x);
94 | };
95 |
96 | me.set = function()
97 | {
98 | var p_options = null;
99 | if (arguments.length === 2 && isString(arguments[0]))
100 | {
101 | var func = "set" + arguments[0].toUpperCamelCase();
102 | if (isFunction(me[func]))
103 | {
104 | me[func](arguments[1]);
105 | }
106 | else
107 | {
108 | me[arguments[0]] = arguments[1];
109 | }
110 | }
111 | else if (arguments.length === 1 && isPlainObject(arguments[0]))
112 | {
113 | p_options = arguments[0];
114 | for ( var key in p_options)
115 | {
116 | if (p_options.hasOwnProperty(key))
117 | {
118 | me.set(key, p_options[key]);
119 | }
120 | }
121 | }
122 | else if (arguments.length === 2 && isPlainObject(arguments[0]) && isPlainObject(arguments[1]))
123 | {
124 | p_options = arguments[0];
125 | var p_defaultOptions = arguments[1];
126 | var options = $.extend({}, p_defaultOptions, p_options);
127 | me.set(options);
128 | }
129 | return me;
130 | };
131 |
132 | me.canConstruct = function()
133 | {
134 | return !me.constructed;
135 | };
136 |
137 | me.instanceOf = function(p_class)
138 | {
139 | if (p_class === me.__class__)
140 | {
141 | return true;
142 | }
143 | else if (p_class === Object || p_class === MXObject)
144 | {
145 | return true;
146 | }
147 | else
148 | {
149 | return me.__superClasses__.indexOf(p_class) !== -1;
150 | }
151 | };
152 |
153 | me.endOfClass = function(p_arguments)
154 | {
155 | if (me.__class__.caller !== $extend)
156 | {
157 | me._(p_arguments[0]);
158 | }
159 | return me;
160 | };
161 |
162 | me.dispose = function()
163 | {
164 | me.disposed = true;
165 | };
166 |
167 | return me.endOfClass(arguments);
168 | };
169 | MXObject.className = "MXObject";
170 |
--------------------------------------------------------------------------------
/scripts/mx/README.md:
--------------------------------------------------------------------------------
1 | # MXFramework
2 | MagicCube MXFramework is a lightweight Object-Oriented JavaScript framework.
3 |
4 | # Quick Examples
5 | Like many other JavaScript frameworks, MXFramework has its own way to define namespace, class and component.
6 | In this quick example, we will demonstrate how to define classes using MXFramework.
7 |
8 | Firstly, let's create a new class named Animal.
9 | ```javascript
10 | scripts/my/namespace/Animal.js
11 |
12 | /*
13 | * Define a namespace.
14 | */
15 | $ns("my.namespace");
16 |
17 | /**
18 | * Define a class which extends MXComponent.
19 | * A MXComponent is a very popular super class.
20 | * Actually, in this case, we can also use MXObject instead.
21 | * MXObject is the super class of MXComponent.
22 | */
23 | my.namespace.Animal = function()
24 | {
25 | /**
26 | * In MXFramework, it always use 'me' instead of 'this'.
27 | */
28 | var me = $extend(MXComponent);
29 | /**
30 | * 'base' is almost the same as 'super' in Java.
31 | */
32 | var base = {};
33 |
34 |
35 | /**
36 | * Define a public field.
37 | * Every public member should under 'me'.
38 | */
39 | me.name = null;
40 |
41 | /**
42 | * Define a private field.
43 | * The names of a private members always start with an underline.
44 | */
45 | var _something = null;
46 | var _someVariable = 0;
47 |
48 |
49 | /**
50 | * Override a public method.
51 | * 'init' method will be automatically called immediately after the instance is created.
52 | * Even though, you can also set the 'autoInit' field to false if you need lazy intialization.
53 | */
54 | base.init = me.init;
55 | me.init = function(p_options)
56 | {
57 | base.init(p_options);
58 | };
59 |
60 |
61 | /**
62 | * Define a public function.
63 | */
64 | me.sayHi = function()
65 | {
66 | if (_canSayHi())
67 | {
68 | /*
69 | String.format provides ability to substitute string with JSON object or array.
70 | In MXFramework you can use the following format methods.
71 | - String.format String.format("Hi, {name}!", { name: "Henry" }); String.format("Hi, {0}", [ "Henry" ])
72 | - Date.format Date.format(new Date(), "yyyy-MM-dd HH:mm:ss"); Date.format(new Date(), "yy年M月d日");
73 | - Number.format Number.format(12.53212, "0.00"); Number.format(123, "00000000");
74 | */
75 | return String.format("Hi, I'm a {name}", { name: me.name });
76 | }
77 | };
78 |
79 |
80 | /**
81 | * Define a private function.
82 | */
83 | function _canSayHi()
84 | {
85 | // MXFramework has a series of methods for type assertions.
86 | return isString(me.name);
87 | }
88 |
89 |
90 | /**
91 | * This is the end of class.
92 | */
93 | return me.endOfClass(arguments);
94 | };
95 | ```
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 | Let's have a class inherits from Animal.
106 |
107 | ```javascript
108 | scripts/your/namespace/Cat.js
109 |
110 | $ns("your.namespace");
111 |
112 | // Import the super class.
113 | $import("my.namespace.Animal");
114 |
115 | /**
116 | * Cat inherits from Animal.
117 | */
118 | your.namespace.Cat = function()
119 | {
120 | var me = $extend(my.namespace.Animal);
121 | /*
122 | * Change the initial value of name.
123 | */
124 | me.name = "Cat";
125 | var base = {};
126 |
127 | me.nickName = "kitty";
128 |
129 | base.init = me.init;
130 | me.init = function(p_options)
131 | {
132 | base.init(p_options);
133 | if (isEmptyString(me.nickName) && isString(me.name))
134 | {
135 | me.nickName = me.name;
136 | }
137 | };
138 |
139 | /**
140 | * Override 'sayHi' method.
141 | */
142 | base.sayHi = me.sayHi;
143 | me.sayHi = function()
144 | {
145 | // $format is a shortcut to String.format, Date.format and Number.format.
146 | return base.sayHi() + $format(" You can call me {0}", [ me.nickName ]);
147 | };
148 |
149 | return me.endOfClass(arguments);
150 | };
151 | ```
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 | Now we need to instantialize the class.
160 | ```JavaScript
161 | // Import Cat class. The Animal class will be automatically imported with Cat.
162 | $import("your.namespace.Cat");
163 |
164 | // Create a new instance with default values.
165 | var cat = new your.namespace.Cat();
166 | alert(cat.sayHi());
167 |
168 | // Create a new instance with initial values using JSON.
169 | // In MXFramework, class only accepts JSON object as constructure parameter.
170 | var tomCat = new your.namespace.Cat({
171 | nickName: "Tom"
172 | });
173 | alert(tomCat.sayHi());
174 | ```
175 |
176 | Finally, build the code with mxbuild or mxtool to generate min.js and min.css
177 | ```
178 | jar mxbuild.jar your;my
179 | ```
180 |
181 |
182 | # Source Code Repository
183 | The source is available for download from GitHub
184 | https://github.com/MagicCube/mxframework-core
185 |
186 | # Documents
187 | For documents, see https://github.com/MagicCube/mxframework-core/wiki
188 |
189 | # Related Projects
190 | * [mxframework-node](https://github.com/MagicCube/mxframework-node) - MagicCube MXFramework for Node.js
191 | * [mxtool](https://github.com/MagicCube/mxtool) - Development tools for MagicCube MXFramework
192 | * [g3d](https://github.com/MagicCube/g3d) - A web GIS library for 3D visualization using WebGL technology
193 |
--------------------------------------------------------------------------------
/scripts/mx/app/Application.js:
--------------------------------------------------------------------------------
1 | $ns("mx.app");
2 |
3 | mx.app.Application = function()
4 | {
5 | var me = $extend(mx.view.View);
6 | var base = {};
7 |
8 | me.$element = null;
9 |
10 | me.appId = null;
11 | me.appDisplayName = null;
12 |
13 | base.init = me.init;
14 | me.init = function(p_options)
15 | {
16 | if (isEmpty(me.$element))
17 | {
18 | me.$element = $(document.body);
19 | }
20 |
21 | if (isEmpty(me.id))
22 | {
23 | me.id = me.appId;
24 | }
25 | base.init(p_options);
26 | if (notEmpty(me.appDisplayName))
27 | {
28 | document.title = me.appDisplayName;
29 | }
30 |
31 | me.frame = {
32 | width : me.$element.width(),
33 | height : me.$element.height()
34 | };
35 |
36 | me.$element.addClass("mx-app");
37 |
38 | mx.app.Application.singleton = me;
39 | };
40 |
41 | me.run = function(p_options)
42 | {
43 |
44 | };
45 |
46 | return me.endOfClass(arguments);
47 | };
48 | mx.app.Application.className = "mx.app.Application";
49 |
50 | mx.app.Application.singleton = null;
51 |
--------------------------------------------------------------------------------
/scripts/mx/debug.js:
--------------------------------------------------------------------------------
1 | (function()
2 | {
3 | var lang = null;
4 | if (typeof ($mx_language) === "undefined")
5 | {
6 | lang = (navigator.language || navigator.userLanguage).toString().toLowerCase();
7 | }
8 | else
9 | {
10 | lang = $mx_language;
11 | }
12 |
13 | var scripts = document.getElementsByTagName("script");
14 | var src = scripts[scripts.length - 1].src;
15 | var srcPath = src.substr(0, src.lastIndexOf("/mx/") + 1);
16 |
17 | function include(p_src)
18 | {
19 | document.write("");
20 | }
21 |
22 | if (typeof (jQuery) === "undefined")
23 | {
24 | include("lib/jquery/jquery.js");
25 | }
26 |
27 | include("mx/javascript-extensions.js");
28 | include("mx/framework-base.js");
29 | include("mx/framework-core.js");
30 |
31 | })();
32 |
--------------------------------------------------------------------------------
/scripts/mx/framework-base.js:
--------------------------------------------------------------------------------
1 | // 判断类型
2 |
3 | function isBoolean(p_value)
4 | {
5 | return typeof (p_value) === "boolean";
6 | }
7 |
8 | function isString(p_value)
9 | {
10 | return typeof (p_value) === "string";
11 | }
12 |
13 | function isNumber(p_value)
14 | {
15 | return typeof (p_value) === "number";
16 | }
17 |
18 | function isDate(p_value)
19 | {
20 | return notEmpty(p_value) && p_value.constructor === Date;
21 | }
22 |
23 | function isArray(p_value)
24 | {
25 | if (typeof(Array.isArray) === "function")
26 | {
27 | return Array.isArray(p_value);
28 | }
29 | else
30 | {
31 | return notEmpty(p_value) && (typeof (p_value) === "object" && typeof (p_value.length) === "number");
32 | }
33 | }
34 |
35 | function isObject(p_value)
36 | {
37 | return notEmpty(p_value) && typeof (p_value) === "object";
38 | }
39 |
40 | function isPlainObject(p_value)
41 | {
42 | return $.isPlainObject(p_value);
43 | }
44 |
45 | function isFunction(p_value)
46 | {
47 | return typeof (p_value) === "function";
48 | }
49 |
50 | function isClass(p_value)
51 | {
52 | return typeof (p_value) === "function";
53 | }
54 |
55 | // 类型转换
56 | function parseBoolean(p_text)
57 | {
58 | if (typeof (p_text) === "boolean")
59 | {
60 | return p_text;
61 | }
62 | else if (typeof(p_text) === "number")
63 | {
64 | return p_text !== 0;
65 | }
66 | else if (typeof(p_text) === "string")
67 | {
68 | var t = p_text.toLowerCase();
69 | return (t === "true") || (t === "t");
70 | }
71 | }
72 |
73 | var __regex_Hms = /^(\S*):(\S*):(\S*)$/;
74 | var __regex_Hm = /^(\S*):(\S*)$/;
75 | function parseTimeString(p_timeString)
76 | {
77 | var value = {
78 | hours : 0,
79 | minutes : 0,
80 | seconds : 0
81 | };
82 |
83 | var matches = p_timeString.match(__regex_Hms);
84 | if (isEmpty(matches))
85 | {
86 | matches = p_timeString.match(__regex_Hm);
87 | if (isEmpty(matches))
88 | {
89 | matches = [p_timeString, p_timeString];
90 | }
91 | }
92 |
93 | if (matches.length >= 2)
94 | {
95 | value.hours = parseInt(matches[1], 10);
96 | if (isNaN(value.hours) || value.hours > 23 || value.hours < 0)
97 | {
98 | value.hours = 0;
99 | }
100 | }
101 |
102 | if (matches.length >= 3)
103 | {
104 | value.minutes = parseInt(matches[2], 10);
105 | if (isNaN(value.minutes) || value.minutes > 60 || value.minutes < 0)
106 | {
107 | value.minutes = 0;
108 | }
109 | }
110 |
111 | if (matches.length >= 4)
112 | {
113 | value.seconds = parseInt(matches[3], 10);
114 | if (isNaN(value.seconds) || value.seconds > 60 || value.seconds < 0)
115 | {
116 | value.seconds = 0;
117 | }
118 | }
119 |
120 | return value;
121 | }
122 |
123 | var __regex_yyyyM = /^(\S*)-(\S*)$/;
124 | var __regex_yyyyMD = /^(\S*)-(\S*)-(\S*)$/;
125 | function parseDateString(p_dateString)
126 | {
127 | var value = {
128 | year : 1900,
129 | month : 1,
130 | date : 1
131 | };
132 |
133 | var matches = p_dateString.match(__regex_yyyyMD);
134 | if (isEmpty(matches))
135 | {
136 | matches = p_dateString.match(__regex_yyyyM);
137 | if (isEmpty(matches))
138 | {
139 | matches = [p_dateString, p_dateString];
140 | }
141 | }
142 | if (notEmpty(matches))
143 | {
144 | if (matches.length >= 2)
145 | {
146 | value.year = parseInt(matches[1], 10);
147 | if (isNaN(value.year))
148 | {
149 | value.year = 1900;
150 | }
151 | }
152 |
153 | if (matches.length >= 3)
154 | {
155 | value.month = parseInt(matches[2], 10);
156 | if (isNaN(value.month) || value.month > 12 || value.month <= 0)
157 | {
158 | value.month = 1;
159 | }
160 | }
161 |
162 | if (matches.length >= 4)
163 | {
164 | var d_max = Date.getDaysInMonth(value.year, value.month - 1);
165 | value.date = parseInt(matches[3], 10);
166 | if (isNaN(value.date) || value.date <= 0)
167 | {
168 | value.date = 1;
169 | }
170 | else if (value.date > d_max)
171 | {
172 | value.date = d_max;
173 | }
174 | }
175 | }
176 | value.month -= 1;
177 | return value;
178 | }
179 |
180 | function parseDate(p_text)
181 | {
182 | if (isEmpty(p_text))
183 | {
184 | return null;
185 | }
186 | if (isDate(p_text))
187 | {
188 | return p_text;
189 | }
190 |
191 | var parts = null;
192 | var datePart = null;
193 | var timePart = null;
194 | p_text = p_text.trim();
195 | if (p_text.indexOf(" ") !== -1)
196 | {
197 | parts = p_text.split(" ");
198 | }
199 | else if (p_text.indexOf("T") !== -1)
200 | {
201 | parts = p_text.split("T");
202 | }
203 |
204 | if (isEmpty(parts))
205 | {
206 | parts = [p_text];
207 | }
208 |
209 | if (parts.length === 1)
210 | {
211 | if (parts[0].indexOf(":") !== -1)
212 | {
213 | timePart = parts[0];
214 | }
215 | else
216 | {
217 | datePart = parts[0];
218 | }
219 | }
220 | else if (parts.length === 2)
221 | {
222 | datePart = parts[0];
223 | timePart = parts[1];
224 | }
225 |
226 | var dateValue = {
227 | year : 1900,
228 | month : 0,
229 | date : 1
230 | };
231 | if (notEmpty(datePart))
232 | {
233 | dateValue = parseDateString(datePart);
234 | }
235 |
236 | var timeValue = {
237 | hours : 0,
238 | minutes : 0,
239 | seconds : 0
240 | };
241 | if (notEmpty(timePart))
242 | {
243 | timeValue = parseTimeString(timePart);
244 | }
245 |
246 | return new Date(dateValue.year, dateValue.month, dateValue.date, timeValue.hours, timeValue.minutes, timeValue.seconds);
247 | }
248 |
249 | // 命名空间
250 | function $namespace(p_namespace)
251 | {
252 | if (!/^[a-z]+[a-z0-9\._\$]*[a-z0-9]$/.test(p_namespace))
253 | {
254 | throw new Error("Invalid namespace '" + p_namespace + "'.");
255 | }
256 | var parts = p_namespace.split(".");
257 | if (parts.length === 0)
258 | {
259 | return null;
260 | }
261 |
262 | var partialNS = null;
263 | var context = window;
264 | for (var i = 0; i < parts.length; i++)
265 | {
266 | partialNS = parts[i];
267 | if (isEmpty(context[partialNS]))
268 | {
269 | context[partialNS] = {};
270 | }
271 | context = context[partialNS];
272 | }
273 | return context;
274 | }
275 | $ns = $namespace;
276 |
277 | // 继承
278 | function $extend(p_baseClass)
279 | {
280 | if (typeof (p_baseClass) === "function")
281 | {
282 | var inst = new p_baseClass();
283 | inst.__class__ = $extend.caller;
284 | if (p_baseClass !== MXObject && p_baseClass !== MXComponent)
285 | {
286 | inst.__superClasses__.push(p_baseClass);
287 | }
288 | return inst;
289 | }
290 | }
291 |
292 | // 获取实例的类型。
293 | function $getclass(p_inst)
294 | {
295 | if (isEmpty(p_inst))
296 | {
297 | return null;
298 | }
299 | switch (typeof (p_inst))
300 | {
301 | case "boolean":
302 | return Boolean;
303 |
304 | case "number":
305 | return Number;
306 |
307 | case "string":
308 | return String;
309 |
310 | case "function":
311 | return Function;
312 |
313 | case "object":
314 | if (typeof (p_inst.getClass) === "function")
315 | {
316 | return p_inst.getClass();
317 | }
318 | else if (isDate(p_inst))
319 | {
320 | return Date;
321 | }
322 | else if (isArray(p_inst))
323 | {
324 | return Array;
325 | }
326 | else
327 | {
328 | return Object;
329 | }
330 | break;
331 | default:
332 | return null;
333 | }
334 | }
335 |
336 | // 判断 p_inst 是否是 p_class 的实例。
337 | function $instanceof(p_inst, p_class)
338 | {
339 | if (isEmpty(p_inst))
340 | {
341 | return false;
342 | }
343 | switch (typeof (p_inst))
344 | {
345 | case "boolean":
346 | return p_class === Boolean;
347 |
348 | case "number":
349 | return p_class === Number;
350 |
351 | case "string":
352 | return p_class === String;
353 |
354 | case "function":
355 | return p_class === Function;
356 |
357 | case "object":
358 | if (typeof (p_inst.instanceOf) === "function")
359 | {
360 | return p_inst.instanceOf(p_class);
361 | }
362 | else if (isDate(p_inst))
363 | {
364 | return p_class === Date;
365 | }
366 | else if (isArray(p_inst))
367 | {
368 | return p_class === Array;
369 | }
370 | else
371 | {
372 | return true;
373 | }
374 | break;
375 | default:
376 | return false;
377 | }
378 | }
379 |
380 | // 格式化
381 | function $format(p_value, p_format)
382 | {
383 | if (isString(p_value) && (isArray(p_format) || isNumber(p_format) || isPlainObject(p_format)))
384 | {
385 | return String.format(p_value, p_format);
386 | }
387 | if (isNumber(p_value))
388 | {
389 | return Number.format(p_value, p_format);
390 | }
391 | else if (isDate(p_value))
392 | {
393 | return Date.format(p_value, p_format);
394 | }
395 | else
396 | {
397 | return notEmpty(p_value) ? p_value.toString() : "";
398 | }
399 | }
400 |
--------------------------------------------------------------------------------
/scripts/mx/mx.build:
--------------------------------------------------------------------------------
1 | javascript-extensions.js
2 | framework-base.js
3 | framework-core.js
--------------------------------------------------------------------------------
/scripts/mx/res/locales/en/language.js:
--------------------------------------------------------------------------------
1 | mx.locales["mx"] = {
2 | "language" : "en",
3 |
4 | "day_0" : "Sunday",
5 | "day_1" : "Monday",
6 | "day_2" : "Tuesday",
7 | "day_3" : "Wednesday",
8 | "day_4" : "Thursday",
9 | "day_5" : "Friday",
10 | "day_6" : "Saturday",
11 |
12 | "day_0_short" : "Sun",
13 | "day_1_short" : "Mon",
14 | "day_2_short" : "Tue",
15 | "day_3_short" : "Wed",
16 | "day_4_short" : "Thu",
17 | "day_5_short" : "Fri",
18 | "day_6_short" : "Sat",
19 |
20 | "day_0_shortest" : "S",
21 | "day_1_shortest" : "M",
22 | "day_2_shortest" : "T",
23 | "day_3_shortest" : "W",
24 | "day_4_shortest" : "T",
25 | "day_5_shortest" : "F",
26 | "day_6_shortest" : "S",
27 |
28 | "month_1" : "January",
29 | "month_2" : "February",
30 | "month_3" : "March",
31 | "month_4" : "April",
32 | "month_5" : "May",
33 | "month_6" : "June",
34 | "month_7" : "July",
35 | "month_8" : "August",
36 | "month_9" : "September",
37 | "month_10" : "October",
38 | "month_11" : "November",
39 | "month_12" : "December",
40 |
41 | "month_1_short" : "Jan",
42 | "month_2_short" : "Feb",
43 | "month_3_short" : "Mar",
44 | "month_4_short" : "Apr",
45 | "month_5_short" : "May",
46 | "month_6_short" : "Jun",
47 | "month_7_short" : "Jul",
48 | "month_8_short" : "Oct",
49 | "month_9_short" : "Sep",
50 | "month_10_short" : "Oct",
51 | "month_11_short" : "Nov",
52 | "month_12_short" : "Dec",
53 |
54 | "ok" : "OK",
55 | "cancel" : "Cancel",
56 | "yes" : "Yes",
57 | "no" : "No"
58 | };
59 |
--------------------------------------------------------------------------------
/scripts/mx/res/locales/zh-cn/language.js:
--------------------------------------------------------------------------------
1 | mx.locales["mx"] = {
2 | "language" : "zh-cn",
3 |
4 | "day_0" : "星期日",
5 | "day_1" : "星期一",
6 | "day_2" : "星期二",
7 | "day_3" : "星期三",
8 | "day_4" : "星期四",
9 | "day_5" : "星期五",
10 | "day_6" : "星期六",
11 |
12 | "day_0_short" : "周日",
13 | "day_1_short" : "周一",
14 | "day_2_short" : "周二",
15 | "day_3_short" : "周三",
16 | "day_4_short" : "周四",
17 | "day_5_short" : "周五",
18 | "day_6_short" : "周六",
19 |
20 | "day_0_shortest" : "日",
21 | "day_1_shortest" : "一",
22 | "day_2_shortest" : "二",
23 | "day_3_shortest" : "三",
24 | "day_4_shortest" : "四",
25 | "day_5_shortest" : "五",
26 | "day_6_shortest" : "六",
27 |
28 | "month_0" : "一月",
29 | "month_1" : "二月",
30 | "month_2" : "三月",
31 | "month_3" : "四月",
32 | "month_4" : "五月",
33 | "month_5" : "六月",
34 | "month_6" : "七月",
35 | "month_7" : "八月",
36 | "month_8" : "九月",
37 | "month_9" : "十月",
38 | "month_10" : "十一月",
39 | "month_11" : "十二月",
40 |
41 | "month_0_short" : "一月",
42 | "month_1_short" : "二月",
43 | "month_2_short" : "三月",
44 | "month_3_short" : "四月",
45 | "month_4_short" : "五月",
46 | "month_5_short" : "六月",
47 | "month_6_short" : "七月",
48 | "month_7_short" : "八月",
49 | "month_8_short" : "九月",
50 | "month_9_short" : "十月",
51 | "month_10_short" : "十一月",
52 | "month_11_short" : "十二月",
53 |
54 | "ok" : "确定",
55 | "cancel" : "取消",
56 | "yes" : "是",
57 | "no" : "否"
58 | };
59 |
--------------------------------------------------------------------------------
/scripts/mx/scn/Scene.js:
--------------------------------------------------------------------------------
1 | $ns("mx.scn");
2 |
3 | mx.scn.Scene = function()
4 | {
5 | var me = $extend(mx.view.View);
6 | var base = {};
7 |
8 | me.title = null;
9 | me.isActive = false;
10 |
11 | me.ontitlechanged = null;
12 | me.onactivate = null;
13 | me.ondeactivate = null;
14 |
15 | base.init = me.init;
16 | me.init = function(p_options)
17 | {
18 | base.init(p_options);
19 | me.$element.addClass("Scene");
20 | };
21 |
22 | me.setTitle = function(p_title)
23 | {
24 | if (me.title !== p_title)
25 | {
26 | me.title = p_title;
27 | me.trigger("titlechanged");
28 | }
29 | };
30 |
31 | me.activate = function(p_args, p_isBack)
32 | {
33 | me.isActive = true;
34 | me.trigger("activate", {
35 | args : p_args,
36 | isBack : p_isBack ? true : false
37 | });
38 | };
39 |
40 | me.deactivate = function()
41 | {
42 | me.isActive = false;
43 | me.trigger("deactivate");
44 | };
45 |
46 | me.toString = function()
47 | {
48 | return "Scene[" + me.id + "]";
49 | };
50 |
51 | return me.endOfClass(arguments);
52 | };
53 | mx.scn.Scene.className = "mx.scn.Scene";
54 |
--------------------------------------------------------------------------------
/scripts/mx/util/ObjectPool.js:
--------------------------------------------------------------------------------
1 | $ns("mx.util");
2 |
3 | mx.util.ObjectPool = function()
4 | {
5 | var me = $extend(MXComponent);
6 | var base = {};
7 |
8 | me.initialSize = 0;
9 | me.maxSize = 0;
10 | me.stack = [];
11 |
12 | base.init = me.init;
13 | me.init = function(p_options)
14 | {
15 | base.init(p_options);
16 | if (me.initialSize > 0 && me.stack.length < me.initialSize)
17 | {
18 | while (me.stack.length < me.initialSize)
19 | {
20 | var obj = me.createObject();
21 | me.addObject(obj);
22 | }
23 | }
24 | };
25 |
26 | me.borrowObject = function()
27 | {
28 | if (me.stack.length === 0)
29 | {
30 | var obj = me.createObject();
31 | return obj;
32 | }
33 | else
34 | {
35 | return me.stack.pop();
36 | }
37 | };
38 |
39 | me.returnObject = function(p_object)
40 | {
41 | if (notEmpty(p_object) && (me.maxSize === 0 || me.stack.length < me.maxSize))
42 | {
43 | me.addObject(p_object);
44 | }
45 | };
46 |
47 | me.addObject = function(p_object)
48 | {
49 | me.stack.push(p_object);
50 | };
51 |
52 | me.removeObject = function(p_object)
53 | {
54 | me.stack.remove(p_object);
55 | };
56 |
57 | me.createObject = function()
58 | {
59 | throw new Error("Must implement 'createObject()' function of the ObjectPool.");
60 | };
61 |
62 | me.clear = function()
63 | {
64 | me.stack.clear();
65 | };
66 |
67 | return me.endOfClass(arguments);
68 | };
69 | mx.util.ObjectPool.className = "mx.util.ObjectPool";
70 |
--------------------------------------------------------------------------------
/scripts/mx/view/View.js:
--------------------------------------------------------------------------------
1 | $ns("mx.view");
2 |
3 | mx.view.View = function()
4 | {
5 | var me = $extend(MXComponent);
6 | var base = {};
7 |
8 | me.id = null;
9 | me.$element = null;
10 | me.$container = null;
11 | me.elementTag = "div";
12 | me.elementClass = null;
13 | me.elementStyle = null;
14 | me.elementPositionMode = "relative";
15 |
16 | me.frame = null;
17 |
18 | me.parentView = null;
19 | me.subviews = [];
20 |
21 | base._ = me._;
22 | me._ = function(p_options)
23 | {
24 | if (notEmpty(me.frame) && notEmpty(p_options) && notEmpty(p_options.frame))
25 | {
26 | p_options.frame = $.extend(me.frame, p_options.frame);
27 | }
28 | base._(p_options);
29 | };
30 |
31 | base.init = me.init;
32 | me.init = function(p_options)
33 | {
34 | base.init(p_options);
35 |
36 | if (isEmpty(me.$element))
37 | {
38 | me.$element = $("<" + me.elementTag + "/>");
39 | }
40 | if (isEmpty(me.$container))
41 | {
42 | me.$container = me.$element;
43 | }
44 |
45 | if (notEmpty(me.$element.attr("id")) && isEmpty(me.id))
46 | {
47 | me.id = me.$element.attr("id");
48 | }
49 |
50 | if (isEmpty(me.id) && isEmpty(me.$element.attr("id")))
51 | {
52 | me.id = String.newGuid();
53 | }
54 | me.$element.attr("id", me.id);
55 | if (mx.debugMode)
56 | {
57 | me.$element.data("view", me);
58 | }
59 |
60 | me.$element.css({
61 | "position" : me.elementPositionMode
62 | });
63 |
64 | if (notEmpty(me.elementClass))
65 | {
66 | me.$element.addClass(me.elementClass);
67 | }
68 |
69 | if (isPlainObject(me.elementStyle))
70 | {
71 | me.css(me.elementStyle);
72 | }
73 |
74 | me.setFrame(me.frame);
75 |
76 | if (me.subviews.length > 0)
77 | {
78 | var subviews = me.subviews.clone();
79 | me.subviews.clear();
80 | me.addSubviews(subviews);
81 | }
82 | };
83 |
84 | me.setFrame = function(p_frame, p_animated)
85 | {
86 | if (notEmpty(p_frame))
87 | {
88 | if (notEmpty(me.frame))
89 | {
90 | me.frame = $.extend(me.frame, p_frame);
91 | }
92 | else
93 | {
94 | me.frame = p_frame;
95 | }
96 |
97 | if (p_animated)
98 | {
99 | me.$element.animate(me.frame, p_animated);
100 | }
101 | else
102 | {
103 | me.$element.css(me.frame);
104 | }
105 |
106 | if (notEmpty(me.frame.left) || notEmpty(me.frame.right) || notEmpty(me.frame.top) || notEmpty(me.frame.bottom))
107 | {
108 | me.$element.css("position", "absolute");
109 | }
110 | }
111 | };
112 |
113 | me.addSubview = function(p_view, $p_element)
114 | {
115 | if (typeof ($p_element) === "undefined")
116 | {
117 | $p_element = me.$container;
118 | }
119 |
120 | if (isFunction(p_view.placeAt))
121 | {
122 | var $container = $("");
123 | p_view.placeAt($container);
124 | $p_element.append($container);
125 | return;
126 | }
127 |
128 | if ($instanceof(p_view, mx.view.View))
129 | {
130 | if (p_view.parentView === me)
131 | {
132 | return;
133 | }
134 |
135 | if (notEmpty(p_view.parentView))
136 | {
137 | p_view.parentView.removeSubview(p_view);
138 | }
139 |
140 | if (notEmpty($p_element))
141 | {
142 | $p_element.append(p_view.$element);
143 | }
144 | me.subviews.add(p_view);
145 |
146 | if (notEmpty(p_view.id))
147 | {
148 | me.subviews[p_view.id] = p_view;
149 | }
150 | p_view.parentView = me;
151 | }
152 | };
153 |
154 | me.addSubviews = function(p_views, $p_element)
155 | {
156 | if (isArray(p_views))
157 | {
158 | p_views.forEach(function(p_view)
159 | {
160 | me.addSubview(p_view, $p_element);
161 | });
162 | }
163 | };
164 |
165 | me.removeSubview = function(p_view)
166 | {
167 | if ($instanceof(p_view, mx.view.View))
168 | {
169 | p_view.$element.detach();
170 | me.subviews.remove(p_view);
171 | if (notEmpty(p_view.id))
172 | {
173 | me.subviews[p_view.id] = null;
174 | delete me.subviews[p_view.id];
175 | }
176 | p_view.parentView = null;
177 | p_view = null;
178 | }
179 | };
180 |
181 | me.clearSubviews = function()
182 | {
183 | while (me.subviews.length > 0)
184 | {
185 | me.removeSubview(me.subviews[0]);
186 | }
187 | };
188 |
189 | me.css = function(p_attrName, p_attrValue)
190 | {
191 | if (arguments.length === 1)
192 | {
193 | return me.$element.css(p_attrName);
194 | }
195 | else if (arguments.length >= 2)
196 | {
197 | return me.$element.css(p_attrName, p_attrValue);
198 | }
199 | };
200 |
201 | me.show = function(p_options)
202 | {
203 | me.$element.show(p_options);
204 | };
205 |
206 | me.hide = function(p_options)
207 | {
208 | me.$element.hide(p_options);
209 | };
210 |
211 | me.toString = function()
212 | {
213 | return "View[" + me.id + "]";
214 | };
215 |
216 | return me.endOfClass(arguments);
217 | };
218 | mx.view.View.className = "mx.view.View";
219 |
220 | $view = function(p_element)
221 | {
222 | var $e = $(p_element);
223 | while ($e.length !== 0 && isEmpty($e.data("view")))
224 | {
225 | $e = $e.parent();
226 | }
227 | return $e.data("view");
228 | };
229 |
--------------------------------------------------------------------------------
/scripts/mx3d/res/Scene3DView.css:
--------------------------------------------------------------------------------
1 | .Scene3DView > #analyphEffect
2 | {
3 | position: absolute;
4 | background: url(images/3d-glasses.png);
5 | width: 48px;
6 | height: 48px;
7 | bottom: 10px;
8 | left: 10px;
9 | cursor: pointer;
10 | }
11 |
12 | .Scene3DView > #analyphEffect.enabled
13 | {
14 | background: url(images/3d-glasses-enabled.png);
15 | }
--------------------------------------------------------------------------------
/scripts/mx3d/res/images/3d-glasses-enabled.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MagicCube/g3d/f0e26e25f28b0bf7095643a077a5d20b5fe867f8/scripts/mx3d/res/images/3d-glasses-enabled.png
--------------------------------------------------------------------------------
/scripts/mx3d/res/images/3d-glasses.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MagicCube/g3d/f0e26e25f28b0bf7095643a077a5d20b5fe867f8/scripts/mx3d/res/images/3d-glasses.png
--------------------------------------------------------------------------------
/scripts/mx3d/res/materials/alphaGradient.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
15 |
23 |
24 |
--------------------------------------------------------------------------------
/scripts/mx3d/util/ShaderMaterialBuilder.js:
--------------------------------------------------------------------------------
1 | $ns("mx3d.util");
2 |
3 | mx3d.util.ShaderMaterialBuilder = function()
4 | {
5 | var me = $extend(MXObject);
6 | var base = {};
7 |
8 | me.url = null;
9 | me.parameters = {};
10 | me.attributes = {};
11 | me.uniforms = {};
12 |
13 | var _vertexShader = null;
14 | var _fragmentShader = null;
15 |
16 | base._ = me._;
17 | me._ = function(p_options)
18 | {
19 | if (me.canConstruct())
20 | {
21 | base._(p_options);
22 |
23 | if (p_options != null && p_options.uniforms != null)
24 | {
25 | me.uniforms = $.extend(p_options.uniforms, me.uniforms);
26 | }
27 | if (p_options != null && p_options.attributes != null)
28 | {
29 | me.attributes = $.extend(p_options.attributes, me.attributes);
30 | }
31 |
32 | if (me.url != null)
33 | {
34 | me.loadXML(me.url);
35 | }
36 | }
37 | };
38 |
39 | me.loadXML = function(p_url)
40 | {
41 | me.url = p_url;
42 | $.ajax({
43 | dataType : "xml",
44 | url : p_url,
45 | async : false
46 | }).success(function(p_result)
47 | {
48 | var $xml = $(p_result);
49 | _vertexShader = $xml.find("material > script[id=vertexShader]").text();
50 | _fragmentShader = $xml.find("material > script[id=fragmentShader]").text();
51 | $xml = null;
52 | p_result = null;
53 | });
54 | };
55 |
56 | me.setAttributeValues = function(p_name, p_values, p_type)
57 | {
58 | var type = p_type;
59 | if (p_type == null)
60 | {
61 | type = _getType(p_values[0]);
62 | }
63 | me.attributes[p_name] = {
64 | t : type,
65 | value : p_values
66 | };
67 | };
68 |
69 | me.setAttributeValue = function(p_name, p_value, p_type)
70 | {
71 | if (me.attributes[p_name] == null)
72 | {
73 | var values = [];
74 | me.setAttributeValues(p_name, values, _getType(p_value, p_type));
75 | }
76 | var attr = me.attributes[p_name];
77 | attr.value.add(p_value);
78 | };
79 |
80 | me.setUniformValue = function(p_name, p_value, p_type)
81 | {
82 | var type = p_type;
83 | if (p_type == null)
84 | {
85 | type = _getType(p_value);
86 | }
87 | var uniform = {
88 | type : type,
89 | value : p_value
90 | };
91 | me.uniforms[p_name] = uniform;
92 | return uniform;
93 | };
94 |
95 | me.build = function()
96 | {
97 | var params = $.extend({}, me.parameters);
98 | params.attributes = $.extend({}, me.attributes);
99 | params.uniforms = $.extend({}, me.uniforms);
100 | params.vertexShader = _vertexShader;
101 | params.fragmentShader = _fragmentShader;
102 | var shaderMaterial = new THREE.ShaderMaterial(params);
103 | return shaderMaterial;
104 | };
105 |
106 | function _getType(p_value, p_type)
107 | {
108 | if (typeof (p_value) === "number")
109 | {
110 | return "f";
111 | }
112 | else if (p_value instanceof THREE.Color)
113 | {
114 | return "c";
115 | }
116 | else if (p_value instanceof THREE.Texture)
117 | {
118 | return "t";
119 | }
120 | return p_type;
121 | }
122 |
123 | return me.endOfClass(arguments);
124 | };
125 | mx3d.util.ShaderMaterialBuilder.className = "mx3d.util.ShaderMaterialBuilder";
126 |
--------------------------------------------------------------------------------
/scripts/mx3d/view/AnimatedScene3DView.js:
--------------------------------------------------------------------------------
1 | $ns("mx3d.view");
2 |
3 | $import("lib.tween.Tween");
4 | $import("lib.threejs.three", function()
5 | {
6 | $import("lib.threejs.plugins.stats");
7 | $import("lib.threejs.controls.TrackballControls");
8 | });
9 |
10 | $import("mx3d.view.Scene3DView");
11 |
12 | mx3d.view.AnimatedScene3DView = function()
13 | {
14 | var me = $extend(mx3d.view.Scene3DView);
15 | var base = {};
16 |
17 | me.cameraControlsEnabled = false;
18 | me.statsVisible = false;
19 | me.animating = true;
20 | me.playState = null;
21 | me.frameIndex = 0;
22 | me.stats = null;
23 | me.cameraControls = null;
24 | me.onframing = null;
25 |
26 | base.init = me.init;
27 | me.init = function(p_options)
28 | {
29 | base.init(p_options);
30 | me.$element.addClass("AnimatedScene3DView");
31 | };
32 |
33 | base.init3D = me.init3D;
34 | me.init3D = function()
35 | {
36 | base.init3D();
37 | me.initStats();
38 | me.initControls();
39 | };
40 |
41 | me.initControls = function()
42 | {
43 | me.initCameraControls();
44 | };
45 |
46 | me.initCameraControls = function()
47 | {
48 | if (me.cameraControlsEnabled && me.cameraControls == null)
49 | {
50 | me.cameraControls = new THREE.TrackballControls(me.camera, me.$element.find("canvas")[0]);
51 | }
52 | };
53 |
54 | me.initStats = function()
55 | {
56 | if (me.statsVisible && me.stats == null)
57 | {
58 | me.stats = new Stats();
59 | me.stats.domElement.style.position = 'absolute';
60 | me.stats.domElement.style.right = '5px';
61 | me.stats.domElement.style.bottom = '5px';
62 | me.stats.domElement.style.whiteSpace = "nowrap";
63 | me.$container.append(me.stats.domElement);
64 | }
65 | };
66 |
67 | me.startAnimation = function()
68 | {
69 | me.animating = true;
70 | me.renderLoop();
71 | };
72 |
73 | me.stopAnimation = function()
74 | {
75 | me.animating = false;
76 | };
77 |
78 | me.renderLoop = function()
79 | {
80 | me.trigger("framing");
81 | if (me.cameraControlsEnabled)
82 | {
83 | if (me.cameraControls == null)
84 | {
85 | me.initCameraControls();
86 | }
87 | if (!me.cameraControls.enabled)
88 | {
89 | me.cameraControls.enabled = true;
90 | }
91 | me.cameraControls.update();
92 | }
93 | else
94 | {
95 | if (me.cameraControls != null && me.cameraControls.enabled)
96 | {
97 | me.cameraControls.enabled = false;
98 | }
99 | }
100 |
101 | me.update();
102 | me.render();
103 |
104 | if (me.statsVisible)
105 | {
106 | if (me.stats == null)
107 | {
108 | me.initStats();
109 | }
110 | me.stats.update();
111 | }
112 |
113 | if (me.animating)
114 | {
115 | requestAnimationFrame(me.renderLoop);
116 | }
117 | };
118 |
119 | me.moveCamera = function(p_position, p_rotation, p_duration, p_up)
120 | {
121 | var deferred = $.Deferred();
122 |
123 | var duration = p_duration;
124 | if (duration == null)
125 | {
126 | duration = 1000;
127 | }
128 |
129 | me.cameraControlsEnabled = false;
130 |
131 | if (p_position != null)
132 | {
133 | new TWEEN.Tween(me.camera.position).to(p_position, duration).easing(TWEEN.Easing.Sinusoidal.Out).start();
134 | }
135 |
136 | if (p_rotation != null)
137 | {
138 | new TWEEN.Tween(me.camera.rotation).to(p_rotation, duration).easing(TWEEN.Easing.Sinusoidal.Out).start();
139 | }
140 |
141 | if (p_up != null)
142 | {
143 | new TWEEN.Tween(me.cameraControls.object.up).to(p_up, duration).easing(TWEEN.Easing.Sinusoidal.Out).start();
144 | }
145 | else
146 | {
147 | me.cameraControls.reset();
148 | }
149 |
150 | setTimeout(function()
151 | {
152 | me.cameraControlsEnabled = true;
153 | deferred.resolve();
154 | }, duration);
155 | return deferred;
156 | };
157 |
158 | me.moveCameraTarget = function(p_position, p_duration)
159 | {
160 | var deferred = $.Deferred();
161 |
162 | if (p_position != null)
163 | {
164 | var duration = p_duration;
165 | if (duration == null)
166 | {
167 | duration = 1000;
168 | }
169 |
170 | me.cameraControlsEnabled = false;
171 | new TWEEN.Tween(me.cameraControls.target).to(p_position, duration).easing(TWEEN.Easing.Sinusoidal.Out).onComplete(function()
172 | {
173 | me.cameraControlsEnabled = true;
174 | deferred.resolve();
175 | }).start();
176 | }
177 | else
178 | {
179 | deferred.resolve();
180 | }
181 | return deferred;
182 | };
183 |
184 | me.focusLine = function(p_vector1, p_vector2, p_overlookDegree, p_duration, p_debug)
185 | {
186 | var deferred = $.Deferred();
187 |
188 | var material = null;
189 | var geometry = null;
190 | var line = null;
191 |
192 | if (p_duration == null)
193 | {
194 | p_duration = 1000;
195 | }
196 |
197 | if (p_debug == null)
198 | {
199 | p_debug = false;
200 | }
201 |
202 | if (p_debug)
203 | {
204 | material = new THREE.LineBasicMaterial({
205 | color : 0xffffff
206 | });
207 | geometry = new THREE.Geometry();
208 | geometry.vertices.push(p_vector1);
209 | geometry.vertices.push(p_vector2);
210 | line = new THREE.Line(geometry, material);
211 | me.addObject(line);
212 | var arrowGeometry = new THREE.CubeGeometry(80, 80, 80);
213 | var arrow = new THREE.Mesh(arrowGeometry);
214 | arrow.position.copy(p_vector2);
215 | me.addObject(arrow);
216 | }
217 |
218 | var mVector = p_vector1.clone();
219 | mVector = mVector.lerp(p_vector2, 0.5);
220 |
221 | var cVector = new THREE.Vector3();
222 | cVector.subVectors(p_vector2, p_vector1);
223 | var vLength = cVector.length();
224 |
225 | var quaternion = new THREE.Quaternion();
226 | var axis = new THREE.Vector3(0, 0, 1);
227 | quaternion.setFromAxisAngle(axis, -Math.PI / 2);
228 | cVector.applyQuaternion(quaternion);
229 |
230 | var angle = (90 - me.camera.fov / 2) * Math.PI / 180;
231 | var focusLength = vLength * 0.5 * Math.tan(angle);
232 | cVector.normalize().multiplyScalar(focusLength);
233 |
234 | var overlookAngle = p_overlookDegree * Math.PI / 180;
235 | cVector.z = focusLength * Math.tan(overlookAngle);
236 | cVector.add(mVector);
237 |
238 | if (p_debug)
239 | {
240 | material = new THREE.LineBasicMaterial({
241 | color : 0xffffff
242 | });
243 | geometry = new THREE.Geometry();
244 | geometry.vertices.push(mVector);
245 | geometry.vertices.push(cVector);
246 | line = new THREE.Line(geometry, material);
247 | me.addObject(line);
248 | }
249 |
250 | if (me.cameraControlsEnabled && me.cameraControls != null)
251 | {
252 | me.cameraControlsEnabled = false;
253 |
254 | var duration = p_duration;
255 | new TWEEN.Tween(me.cameraControls.target).to(mVector, duration).easing(TWEEN.Easing.Sinusoidal.Out).start();
256 | new TWEEN.Tween(me.camera.position).to(cVector, duration).easing(TWEEN.Easing.Sinusoidal.Out).onUpdate(function()
257 | {
258 | me.camera.lookAt(me.cameraControls.target);
259 | }).start();
260 | new TWEEN.Tween(me.cameraControls.object.up).to({
261 | x : 0,
262 | y : 0,
263 | z : 1
264 | }, duration).easing(TWEEN.Easing.Sinusoidal.Out).start();
265 |
266 | setTimeout(function()
267 | {
268 | me.cameraControlsEnabled = true;
269 | deferred.resolve();
270 | }, duration);
271 | }
272 |
273 | return deferred;
274 | };
275 |
276 | me.focusTriangle = function(p_vector1, p_vector2, p_vector3, p_overlookDegree, p_duration, p_debug)
277 | {
278 | var deferred = $.Deferred();
279 |
280 | var material = null;
281 | var geometry = null;
282 | var line = null;
283 |
284 | if (p_duration == null)
285 | {
286 | p_duration = 1000;
287 | }
288 |
289 | if (p_debug == null)
290 | {
291 | p_debug = false;
292 | }
293 |
294 | if (p_debug)
295 | {
296 | material = new THREE.LineBasicMaterial({
297 | color : 0xffffff
298 | });
299 | geometry = new THREE.Geometry();
300 | geometry.vertices.push(p_vector1);
301 | geometry.vertices.push(p_vector2);
302 | geometry.vertices.push(p_vector3);
303 | geometry.vertices.push(p_vector1);
304 | line = new THREE.Line(geometry, material);
305 | me.addObject(line);
306 | var arrowGeometry = new THREE.CubeGeometry(80, 80, 80);
307 | var arrow = new THREE.Mesh(arrowGeometry);
308 | arrow.position.copy(p_vector2);
309 | me.addObject(arrow);
310 | }
311 |
312 | var mVector = p_vector1.clone();
313 | mVector = mVector.lerp(p_vector2, 0.5);
314 |
315 | var cVector = new THREE.Vector3();
316 | cVector.subVectors(p_vector2, p_vector1);
317 | var vLength = cVector.length();
318 |
319 | var quaternion = new THREE.Quaternion();
320 | var axis = new THREE.Vector3(0, 0, 1);
321 | quaternion.setFromAxisAngle(axis, -Math.PI / 2);
322 | cVector.applyQuaternion(quaternion);
323 |
324 | var angle = (90 - me.camera.fov / 2) * Math.PI / 180;
325 | var overlookAngle = p_overlookDegree * Math.PI / 180;
326 |
327 | var focusLength1 = vLength * 0.5 * Math.tan(angle);
328 | var height = Math.abs(p_vector3.z) + 100;
329 | var focusLength2 = height * (Math.sin(overlookAngle) + Math.cos(overlookAngle) * Math.tan(angle)) * Math.cos(overlookAngle);
330 | var focusLength = focusLength1 > focusLength2 ? focusLength1 : focusLength2;
331 |
332 | cVector.normalize().multiplyScalar(focusLength);
333 | cVector.z = focusLength * Math.tan(overlookAngle);
334 | cVector.add(mVector);
335 |
336 | if (p_debug)
337 | {
338 | material = new THREE.LineBasicMaterial({
339 | color : 0xffffff
340 | });
341 | geometry = new THREE.Geometry();
342 | geometry.vertices.push(mVector);
343 | geometry.vertices.push(cVector);
344 | line = new THREE.Line(geometry, material);
345 | me.addObject(line);
346 | }
347 |
348 | if (me.cameraControlsEnabled && me.cameraControls != null)
349 | {
350 | me.cameraControlsEnabled = false;
351 |
352 | var duration = p_duration;
353 | new TWEEN.Tween(me.cameraControls.target).to(mVector, duration).easing(TWEEN.Easing.Sinusoidal.Out).start();
354 | new TWEEN.Tween(me.camera.position).to(cVector, duration).easing(TWEEN.Easing.Sinusoidal.Out).onUpdate(function()
355 | {
356 | me.camera.lookAt(me.cameraControls.target);
357 | }).start();
358 | new TWEEN.Tween(me.cameraControls.object.up).to({
359 | x : 0,
360 | y : 0,
361 | z : 1
362 | }, duration).easing(TWEEN.Easing.Sinusoidal.Out).start();
363 |
364 | setTimeout(function()
365 | {
366 | me.cameraControlsEnabled = true;
367 | deferred.resolve();
368 | }, duration);
369 | }
370 |
371 | return deferred;
372 | };
373 |
374 | base.update = me.update;
375 | me.update = function(p_forceUpdate)
376 | {
377 | TWEEN.update();
378 | base.update(p_forceUpdate);
379 | };
380 |
381 | return me.endOfClass(arguments);
382 | };
383 | mx3d.view.AnimatedScene3DView.className = "mx3d.view.AnimatedScene3DView";
384 |
--------------------------------------------------------------------------------
/scripts/mx3d/view/LabelView.js:
--------------------------------------------------------------------------------
1 | $ns("mx3d.view");
2 |
3 | mx3d.view.LabelView = function()
4 | {
5 | var me = $extend(mx.view.View);
6 | var base = {};
7 |
8 | me.position = null;
9 | me.text = null;
10 | me.fontSize = 16;
11 |
12 | me.camera = null;
13 | me.projector = null;
14 |
15 | me.clickable = false;
16 |
17 | base.init = me.init;
18 | me.init = function(p_options)
19 | {
20 | base.init(p_options);
21 | me.$container.addClass("LabelView");
22 | me.$container.css({
23 | position : "absolute"
24 | });
25 |
26 | if (me.clickable)
27 | {
28 | me.$container.css("cursor", "pointer");
29 | }
30 |
31 | if (me.text != null)
32 | {
33 | me.setText(me.text);
34 | }
35 | };
36 |
37 | me.setText = function(p_text)
38 | {
39 | me.text = p_text;
40 | me.$container.text(me.text != null ? me.text : "");
41 | };
42 |
43 | me.setHtml = function(p_html)
44 | {
45 | me.$container.html(p_html != null ? p_html : "");
46 | me.text = me.$container.text();
47 | };
48 |
49 | me.update = function()
50 | {
51 | var position = me.position.clone();
52 | me.projector.projectVector(position, me.camera);
53 | var position2D = {
54 | x : (position.x + 1) / 2 * me.projector.frame.width,
55 | y : -(position.y - 1) / 2 * me.projector.frame.height,
56 | z : position.z
57 | };
58 |
59 | me.setFrame({
60 | left : position2D.x,
61 | top : position2D.y
62 | });
63 |
64 | if (position2D.z < 1)
65 | {
66 | var scale = (1 - position2D.z) * 50;
67 |
68 | var fontSize = me.fontSize / 4 * scale;
69 | me.$container.css({
70 | display : "block",
71 | fontSize : fontSize
72 | });
73 | }
74 | else
75 | {
76 | me.$container.css({
77 | display : "none"
78 | });
79 | }
80 | };
81 |
82 | return me.endOfClass(arguments);
83 | };
84 | mx3d.view.LabelView.className = "mx3d.view.LabelView";
85 |
--------------------------------------------------------------------------------
/scripts/mx3d/view/MXComponent3D.js:
--------------------------------------------------------------------------------
1 | $ns("mx3d.view");
2 |
3 | mx3d.view.MXComponent3D = function()
4 | {
5 | var me = $extend(MXComponent);
6 | var base = {};
7 |
8 | me.id = null;
9 | me.object3D = null;
10 | me.parentView = null;
11 | me.parentObject3D = null;
12 |
13 | me.needsUpdate = false;
14 |
15 | base.init = me.init;
16 | me.init = function(p_options)
17 | {
18 | base.init(p_options);
19 |
20 | if (me.object3D == null)
21 | {
22 | me.initObject3D();
23 | }
24 |
25 | if (me.object3D != null)
26 | {
27 | me.object3D.id = me.id;
28 | }
29 | };
30 |
31 | me.initObject3D = function()
32 | {
33 | me.object3D = new THREE.Object3D();
34 | };
35 |
36 | me.addObject = function(p_object)
37 | {
38 | me.object3D.add(p_object);
39 | };
40 | me.removeObject = function(p_object)
41 | {
42 | me.object3D.remove(p_object);
43 | };
44 |
45 | me.update = function(p_forceUpdate)
46 | {
47 |
48 | };
49 |
50 | return me.endOfClass(arguments);
51 | };
52 | mx3d.view.MXComponent3D.className = "mx3d.view.MXComponent3D";
53 |
--------------------------------------------------------------------------------
/scripts/mx3d/view/MXObject3D.js:
--------------------------------------------------------------------------------
1 | $ns("mx3d.view");
2 |
3 | mx3d.view.MXObject3D = function()
4 | {
5 | var me = $extend(MXComponent);
6 | var base = {};
7 |
8 | me.id = null;
9 | me.object3D = null;
10 | me.parentView = null;
11 | me.parentObject3D = null;
12 |
13 | me.needsUpdate = false;
14 |
15 | base.init = me.init;
16 | me.init = function(p_options)
17 | {
18 | base.init(p_options);
19 |
20 | if (me.object3D == null)
21 | {
22 | me.initObject3D();
23 | }
24 |
25 | if (me.object3D != null)
26 | {
27 | me.object3D.id = me.id;
28 | }
29 | };
30 |
31 | me.initObject3D = function()
32 | {
33 | me.object3D = new THREE.Object3D();
34 | };
35 |
36 | me.addObject = function(p_object)
37 | {
38 | me.object3D.add(p_object);
39 | };
40 | me.removeObject = function(p_object)
41 | {
42 | me.object3D.remove(p_object);
43 | };
44 |
45 | me.update = function(p_forceUpdate)
46 | {
47 |
48 | };
49 |
50 | return me.endOfClass(arguments);
51 | };
52 | mx3d.view.MXObject3D.className = "mx3d.view.MXObject3D";
53 |
--------------------------------------------------------------------------------
/scripts/mx3d/view/Scene3DView.js:
--------------------------------------------------------------------------------
1 | $ns("mx3d.view");
2 |
3 | $import("lib.threejs.three", function()
4 | {
5 | $import("lib.threejs.effects.AnaglyphEffect");
6 |
7 | $import("lib.threejs.shaders.ColorCorrectionShader");
8 | $import("lib.threejs.shaders.CopyShader");
9 | $import("lib.threejs.shaders.BokehShader");
10 | $import("lib.threejs.shaders.DotScreenShader");
11 | $import("lib.threejs.shaders.FXAAShader");
12 | $import("lib.threejs.shaders.HorizontalTiltShiftShader");
13 | $import("lib.threejs.shaders.RGBShiftShader");
14 | $import("lib.threejs.shaders.ShaderExtras");
15 | $import("lib.threejs.shaders.SSAOShader");
16 | $import("lib.threejs.shaders.VerticalTiltShiftShader");
17 | $import("lib.threejs.shaders.VignetteShader");
18 |
19 | $import("lib.threejs.postprocessing.EffectComposer");
20 | $import("lib.threejs.postprocessing.BokehPass");
21 | $import("lib.threejs.postprocessing.MaskPass");
22 | $import("lib.threejs.postprocessing.RenderPass");
23 | $import("lib.threejs.postprocessing.SavePass");
24 | $import("lib.threejs.postprocessing.ShaderPass");
25 |
26 | $import("lib.threejs.plugins.DepthPassPlugin");
27 | });
28 |
29 | $import("mx3d.view.LabelView");
30 |
31 | $include("mx3d.res.Scene3DView.css");
32 |
33 | mx3d.view.Scene3DView = function()
34 | {
35 | var me = $extend(mx.view.View);
36 | me.frame = {
37 | width : window.innerWidth,
38 | height : window.innerHeight
39 | };
40 | var base = {};
41 |
42 | me.scene = null;
43 |
44 | me.camera = null;
45 | me.cameraParams = null;
46 |
47 | me.renderMode = "renderer";
48 | me.renderer = null;
49 | me.rendererParams = null;
50 |
51 | me.clickable = false;
52 | me.clickableObjects = [];
53 |
54 | me.anaglyphEffectEnabled = false;
55 | me.displayAnalyphEffectButton = false;
56 |
57 | me.labelViews = [];
58 |
59 | me.$anaglyphEffectButton = null;
60 |
61 | me.onobjectclick = null;
62 | me.onlabelviewclick = null;
63 |
64 | base.init = me.init;
65 | me.init = function(p_options)
66 | {
67 | base.init(p_options);
68 | me.init3D();
69 |
70 | me.$element.addClass("Scene3DView");
71 | me.$element.css("overflow", "hidden");
72 | me.$element.on("mouseup", _onmouseup);
73 | me.$element.on("click", ".LabelView", _labelView_onclick);
74 | };
75 |
76 | me.init3D = function()
77 | {
78 | me.initScene();
79 | me.initCamera();
80 | me.initRenderer();
81 | me.initEffects();
82 | me.initObjects();
83 | me.initLights();
84 |
85 | if (me.displayAnalyphEffectButton)
86 | {
87 | me.initAnalyEffectButton();
88 | }
89 | };
90 |
91 | me.initScene = function()
92 | {
93 | me.scene = new THREE.Scene();
94 | };
95 |
96 | me.initCamera = function()
97 | {
98 | var params = $.extend({
99 | fov : 45,
100 | aspect : me.frame.width / me.frame.height,
101 | near : 0.01,
102 | far : 10000
103 | }, me.cameraParams);
104 | me.camera = new THREE.PerspectiveCamera(params.fov, params.aspect, params.near, params.far);
105 | if (params.position != null)
106 | {
107 | if (isArray(params.position))
108 | {
109 | me.camera.position.fromArray(params.position);
110 | }
111 | else
112 | {
113 | var position = $.extend({
114 | x : 0,
115 | y : 0,
116 | z : 0
117 | }, params.position);
118 | me.camera.position.copy(position);
119 | }
120 | }
121 | if (params.rotation != null)
122 | {
123 | if (isArray(params.rotation))
124 | {
125 | me.camera.rotation.fromArray(params.rotation);
126 | }
127 | else
128 | {
129 | var rotation = $.extend({
130 | x : 0,
131 | y : 0,
132 | z : 0
133 | }, params.rotation);
134 | me.camera.rotation.copy(rotation);
135 | }
136 | }
137 | me.addObject(me.camera);
138 | };
139 |
140 | me.initRenderer = function()
141 | {
142 | var params = $.extend({
143 | antialias : true
144 | }, me.rendererParams);
145 | me.renderer = new THREE.WebGLRenderer(params);
146 | me.renderer.setSize(me.frame.width, me.frame.height);
147 | me.renderer.gammaInput = true;
148 | me.renderer.gammaOutput = true;
149 | me.renderer.physicallyBasedShading = true;
150 | me.renderer.shadowMapEnabled = true;
151 | me.renderer.shadowMapSoft = true;
152 | me.$container.append(me.renderer.domElement);
153 |
154 | if (me.renderMode === "composer")
155 | {
156 | me.initComposer();
157 | }
158 | };
159 |
160 | me.initComposer = function()
161 | {
162 | me.composer = new THREE.EffectComposer(me.renderer);
163 | };
164 |
165 | me.initEffects = function()
166 | {
167 | if (me.anaglyphEffectEnabled && me.anaglyphEffect == null)
168 | {
169 | me.anaglyphEffect = new THREE.AnaglyphEffect(me.renderer);
170 | me.anaglyphEffect.setSize(me.frame.width, me.frame.height);
171 | }
172 | };
173 |
174 | me.initAnalyEffectButton = function()
175 | {
176 | me.$anaglyphEffectButton = $("");
177 | me.$anaglyphEffectButton.on("click", function(e)
178 | {
179 | if (e.button !== 0)
180 | {
181 | return;
182 | }
183 | e.preventDefault();
184 | me.anaglyphEffectEnabled = !me.anaglyphEffectEnabled;
185 | me.$anaglyphEffectButton.toggleClass("enabled", me.anaglyphEffectEnabled);
186 | });
187 | me.$container.append(me.$anaglyphEffectButton);
188 | };
189 |
190 | me.initObjects = function()
191 | {
192 |
193 | };
194 |
195 | me.initLights = function()
196 | {
197 |
198 | };
199 |
200 | me.addObject = function(p_object)
201 | {
202 | me.scene.add(p_object);
203 | };
204 | me.removeObject = function(p_object)
205 | {
206 | me.scene.remove(p_object);
207 | };
208 |
209 | me.addLight = function(p_light, p_helperClass)
210 | {
211 | me.scene.add(p_light);
212 |
213 | if (p_helperClass != null)
214 | {
215 | var helper = null;
216 | helper = new p_helperClass(p_light);
217 | me.addObject(helper);
218 | }
219 | };
220 | me.removeLight = function(p_light)
221 | {
222 | me.scene.remove(p_light);
223 | };
224 |
225 | me.render = function()
226 | {
227 | if (me.anaglyphEffectEnabled)
228 | {
229 | if (me.anaglyphEffect == null)
230 | {
231 | me.initEffects();
232 | }
233 | me.anaglyphEffect.render(me.scene, me.camera);
234 | }
235 | else if (me.renderMode === "composer" && me.composer != null)
236 | {
237 | me.composer.render();
238 | }
239 | else
240 | {
241 | me.renderer.render(me.scene, me.camera);
242 | }
243 | };
244 |
245 | me.update = function(p_forceUpdate)
246 | {
247 | me.updateLabels(p_forceUpdate);
248 | };
249 |
250 | me.updateLabels = function(p_forceUpdate)
251 | {
252 | me.labelViews.forEach(function(p_labelView)
253 | {
254 | p_labelView.update(p_forceUpdate);
255 | });
256 | };
257 |
258 | base.setFrame = me.setFrame;
259 | me.setFrame = function(p_frame)
260 | {
261 | base.setFrame(p_frame);
262 | if (typeof (p_frame.width) === "number" || typeof (p_frame.height) === "number")
263 | {
264 | if (me.camera != null)
265 | {
266 | me.camera.aspect = me.frame.width / me.frame.height;
267 | me.camera.updateProjectionMatrix();
268 | }
269 |
270 | me.update();
271 |
272 | if (me.renderer != null)
273 | {
274 | me.renderer.setSize(me.frame.width, me.frame.height);
275 | }
276 |
277 | if (me.anaglyphEffect != null)
278 | {
279 | me.anaglyphEffect.setSize(me.frame.width, me.frame.height);
280 | }
281 | }
282 | };
283 |
284 | var _labelProjector = null;
285 | me.addLabelView = function(p_options)
286 | {
287 | if (_labelProjector == null)
288 | {
289 | _labelProjector = new THREE.Projector();
290 | _labelProjector.frame = me.frame;
291 | }
292 | var options = $.extend({
293 | camera : me.camera,
294 | projector : _labelProjector
295 | }, p_options);
296 | var labelView = new mx3d.view.LabelView(options);
297 | me.addSubview(labelView);
298 | me.labelViews.add(labelView);
299 | labelView.update();
300 | return labelView;
301 | };
302 |
303 | me.removeLabelView = function(p_labelView)
304 | {
305 | me.removeSubview(p_labelView);
306 | p_labelView.camera = null;
307 | p_labelView.projector = null;
308 | me.labelViews.remove(p_labelView);
309 | };
310 |
311 | me.clearLabelViews = function()
312 | {
313 | me.labelViews.forEach(function(p_labelView)
314 | {
315 | me.removeSubview(p_labelView);
316 | });
317 | };
318 |
319 | function _onmouseup(event)
320 | {
321 | if (!me.clickable)
322 | {
323 | return;
324 | }
325 |
326 | if (event.target !== me.renderer.domElement)
327 | {
328 | return;
329 | }
330 |
331 | event.preventDefault();
332 |
333 | if (event.button === 0)
334 | {
335 | // update the mouse variable
336 | var mouse = {
337 | x : 0,
338 | y : 0,
339 | z : 0
340 | };
341 | mouse.x = (event.clientX / me.frame.width) * 2 - 1;
342 | mouse.y = -(event.clientY / me.frame.height) * 2 + 1;
343 | mouse.z = 1;
344 |
345 | // create a Ray with origin at the mouse position
346 | // and direction into the scene (camera direction)
347 | var vector = new THREE.Vector3(mouse.x, mouse.y, mouse.z);
348 | var projector = new THREE.Projector();
349 | projector.unprojectVector(vector, me.camera);
350 |
351 | var origin = me.camera.position;
352 | var dir = vector.sub(me.camera.position).normalize();
353 | var ray = new THREE.Raycaster();
354 | ray.set(origin, dir);
355 |
356 | // create an array containing all objects in the scene with which
357 | // the ray intersects
358 | var intersects = ray.intersectObjects(me.clickableObjects);
359 | if (intersects.length > 0)
360 | {
361 | var objects = intersects.map(function(p_intersect)
362 | {
363 | return p_intersect.object;
364 | });
365 | me.trigger("objectclick", {
366 | objects : objects,
367 | intersects : intersects
368 | });
369 | }
370 |
371 | }
372 |
373 | }
374 |
375 | function _labelView_onclick(e)
376 | {
377 | if (e.button === 0)
378 | {
379 | var id = e.currentTarget.id;
380 | me.trigger("labelviewclick", {
381 | labelView : me.subviews[id]
382 | });
383 | }
384 | }
385 |
386 | return me.endOfClass(arguments);
387 | };
388 | mx3d.view.Scene3DView.className = "mx3d.view.Scene3DView";
389 |
--------------------------------------------------------------------------------