jax 2.0.6 → 2.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/CHANGELOG CHANGED
@@ -1,3 +1,11 @@
1
+ * 2.0.7 *
2
+
3
+ * Resolved issue #48: Unable to reliably pick any object not explicitly added to World
4
+
5
+ * Resolved issue #54: Default views can't be overridden
6
+
7
+
8
+
1
9
  * 2.0.6 *
2
10
 
3
11
  * Resolved issue #30: `Jax.Framebuffer#getTexture(context, index)` now returns texture
data/Rakefile CHANGED
@@ -21,7 +21,7 @@ end
21
21
 
22
22
  require 'cucumber/rake/task'
23
23
  Cucumber::Rake::Task.new(:cucumber) do |t|
24
- t.cucumber_opts = ["-f", "pretty", "-f", "rerun", "-o", "features/rerun.txt", "-t", "~@wip"]
24
+ t.cucumber_opts = ["-f", "pretty", "-f", "rerun", "-r", "features", "-o", "features/rerun.txt", "-t", "~@wip"]
25
25
  unless ENV['FEATURE']
26
26
  if !ENV['ALL'] &&
27
27
  File.file?(rerun = File.expand_path("features/rerun.txt", File.dirname(__FILE__))) &&
@@ -177,7 +177,7 @@ namespace :doc do
177
177
  "https://github.com/sinisterchipmunk/jax/tree/master/#{obj.file}#L#{obj.line_number}"
178
178
  },
179
179
  :pretty_urls => false,
180
- :bust_cache => false,
180
+ :bust_cache => true,
181
181
  :name => 'Jax WebGL Framework',
182
182
  :short_name => 'Jax',
183
183
  :home_url => 'http://jaxgl.com',
@@ -339,3 +339,4 @@ task :guides => 'guides:generate'
339
339
 
340
340
  # disabled node tests for now, since Jax.DataRegion and friends break it. Rake jasmine instead.
341
341
  task :default => ['spec', 'cucumber', 'travis', 'guides']
342
+ task :release => 'guides:publish'
@@ -8,8 +8,7 @@ Jax::Rails::Application.config.cache_classes = false
8
8
 
9
9
  # IMPORTANT: it is necessary to set this _prior_ to app initialization in order to pick up asset dirs
10
10
  ::Rails.application.config.root = File.expand_path("../../tmp/rails-cukes", File.dirname(__FILE__))
11
-
12
- Jax::Rails::Application.initialize!
11
+ ::Rails.application.config.reload_plugins = true
13
12
 
14
13
  require 'cucumber/rails/action_controller'
15
14
 
@@ -6,9 +6,22 @@ Before do
6
6
  end
7
7
 
8
8
  Before("@rails") do
9
+ FileUtils.rm_rf File.join($cucumber_root, "tmp/rails-cukes").to_s
9
10
  setup_rails_environment
10
11
  create_directory "app/assets/jax/shaders"
12
+ create_directory "vendor/plugins/mine/app/assets/jax"
11
13
  route "mount Jax::Engine => '/'"
14
+
15
+ # boot the app, failing silently if it's already booted
16
+ # silent failure is necessary because we can't boot for
17
+ # each feature in isolation
18
+ begin
19
+ Jax::Rails::Application.initialize!
20
+ rescue
21
+ if $!.message != "Application has been already initialized."
22
+ raise
23
+ end
24
+ end
12
25
  end
13
26
 
14
27
  After do
@@ -89,6 +89,7 @@
89
89
  *
90
90
  **/
91
91
  initialize: function(data) {
92
+ this.__unique_id = Jax.Model.__unique_id_tracker++;
92
93
  this.camera = new Jax.Camera();
93
94
 
94
95
  initProperties(this, Jax.Model.default_properties);
@@ -137,6 +138,9 @@
137
138
  if (this.mesh)
138
139
  {
139
140
  var self = this;
141
+ if (!Jax.Model.__instances[this.__unique_id])
142
+ Jax.Model.__instances[this.__unique_id] = this;
143
+ options = Jax.Util.normalizeOptions(options, { model_index: this.__unique_id });
140
144
  context.pushMatrix(function() {
141
145
  context.multModelMatrix(self.camera.getTransformationMatrix());
142
146
  self.mesh.render(context, options);
@@ -201,6 +205,8 @@
201
205
  dispose: function() {
202
206
  if (this.mesh)
203
207
  this.mesh.dispose();
208
+ if (Jax.Model.__instances[this.__unique_id])
209
+ delete Jax.Model.__instances[this.__unique_id];
204
210
  },
205
211
 
206
212
  /**
@@ -330,4 +336,16 @@
330
336
  Object.extend(klass, model_class_methods);
331
337
  return klass;
332
338
  };
339
+
340
+ /*
341
+ This is touchy. Jax.World needs to be able to look up models
342
+ that aren't necessarily in the world (using its unique ID).
343
+ However, we want to be careful not to leave references to
344
+ models strewn about; the user may need to garbage-collect
345
+ them. So, we'll track them using this variable; they only
346
+ get added to the variable upon render, and the reference
347
+ gets deleted whenever the model is disposed.
348
+ */
349
+ Jax.Model.__unique_id_tracker = 1;
350
+ Jax.Model.__instances = {};
333
351
  })();
@@ -64,9 +64,9 @@ Jax.RouteSet = (function() {
64
64
  map: function(path, controller) {
65
65
  if (!path) throw new Error("path is required");
66
66
  var parts = path.split(/\//);
67
- var controller_name = parts[0];
67
+ var controller_name = Jax.Util.underscore(parts[0]);
68
68
 
69
- this._map[Jax.Util.underscore(controller_name)] = controller;
69
+ this._map[controller_name] = controller;
70
70
 
71
71
  if (!Jax.views.exists(controller_name+"/index"))
72
72
  Jax.views.push(controller_name+"/index", function() {
@@ -104,7 +104,7 @@ Jax.RouteSet = (function() {
104
104
  var parts = path.split(/\//);
105
105
  if (parts.length > 2 || parts.length == 0)
106
106
  throw new Error("Invalid path format. String should look like 'controller/action'.");
107
- var controller_name = parts[0];
107
+ var controller_name = Jax.Util.underscore(parts[0]);
108
108
  var action_name = parts[1] || "index";
109
109
 
110
110
  var controller_class = this._map[Jax.Util.underscore(controller_name)];
@@ -17,7 +17,7 @@ Jax.ViewManager = (function() {
17
17
  * If the path is already stored, the current one will be replaced.
18
18
  **/
19
19
  push: function(path, view) {
20
- this.views[path.toLowerCase()] = view;
20
+ this.views[Jax.Util.underscore(path)] = view;
21
21
  },
22
22
 
23
23
  /**
@@ -29,8 +29,8 @@ Jax.ViewManager = (function() {
29
29
  * if not handled appropriately.
30
30
  **/
31
31
  get: function(path) {
32
- if (this.views[path.toLowerCase()])
33
- return new Jax.View(this.views[path.toLowerCase()]);
32
+ if (this.views[Jax.Util.underscore(path)])
33
+ return new Jax.View(this.views[Jax.Util.underscore(path)]);
34
34
  else throw new Error("Could not find view at '"+path+"'!");
35
35
  },
36
36
 
@@ -51,7 +51,11 @@ Jax.ViewManager = (function() {
51
51
  * Removes the specified view path and, if it existed to begin with, returns it.
52
52
  * Otherwise undefined is returned.
53
53
  **/
54
- remove: function(path) { var result = this.views[path]; delete this.views[path]; return result; },
54
+ remove: function(path) {
55
+ var result = this.views[Jax.Util.underscore(path)];
56
+ delete this.views[Jax.Util.underscore(path)];
57
+ return result;
58
+ },
55
59
 
56
60
  /**
57
61
  * Jax.ViewManager#exists(path) -> Boolean
@@ -59,7 +63,7 @@ Jax.ViewManager = (function() {
59
63
  * Returns true if a view exists for the specified view path, false otherwise.
60
64
  **/
61
65
  exists: function(path) {
62
- return !!this.views[path];
66
+ return !!this.views[Jax.Util.underscore(path)];
63
67
  }
64
68
  });
65
69
  })();
@@ -22,7 +22,7 @@ Jax.World = (function() {
22
22
  initialize: function(context) {
23
23
  this.context = context;
24
24
  this.lighting = new Jax.Scene.LightManager(context);
25
- this.objects = [];
25
+ this.objects = {};
26
26
  },
27
27
 
28
28
  /**
@@ -41,42 +41,40 @@ Jax.World = (function() {
41
41
  *
42
42
  **/
43
43
  addObject: function(object) {
44
- this.objects.push(object);
44
+ this.objects[object.__unique_id] = object;
45
+ // this.objects.push(object);
45
46
  if (object.isLit() || object.isShadowCaster())
46
47
  this.lighting.addObject(object);
47
48
  return object;
48
49
  },
49
50
 
50
51
  /**
51
- * Jax.World#getObject(index) -> Jax.Model
52
- * - index (Number): the world index of this object
52
+ * Jax.World#getObject(unique_id) -> Jax.Model
53
+ * - unique_id (Number): the unique ID associated with this model instance
53
54
  *
54
- * Returns the object with the specified world index, or undefined.
55
+ * Returns the object with the specified unique ID if it has been
56
+ * added to this World, or undefined if it has not.
55
57
  **/
56
- getObject: function(index) { return this.objects[index]; },
58
+ getObject: function(unique_id) { return this.objects[unique_id]; },
57
59
 
58
60
  /**
59
- * Jax.World#removeObject(object_or_index) -> Jax.Model
60
- * - object_or_index (Number|Jax.Model): the model instance to remove, or its world index
61
+ * Jax.World#removeObject(object_or_unique_id) -> Jax.Model
62
+ * - object_or_unique_id (Number|Jax.Model): the model instance to remove,
63
+ * or its unique ID
61
64
  *
62
- * If the model or its index cannot be found, nothing happens and the return value is undefined.
63
- * Otherwise, the object is removed from this World and then returned.
65
+ * If the model or its ID has not been added to this World, nothing happens
66
+ * and the return value is undefined. Otherwise, the object is removed from
67
+ * this World and then returned.
64
68
  **/
65
- removeObject: function(object_or_index) {
66
- if (this.objects[object_or_index]) {
67
- var obj = this.objects[object_or_index];
68
- this.objects.splice(object_or_index, 1);
69
+ removeObject: function(object_or_id) {
70
+ if (typeof(object_or_id) == 'number') {
71
+ var obj = this.objects[object_or_id];
72
+ delete this.objects[object_or_id];
69
73
  this.lighting.removeObject(obj);
70
74
  return obj;
75
+ } else {
76
+ this.removeObject(object_or_id.__unique_id);
71
77
  }
72
- else
73
- for (var i = 0; i < this.objects.length; i++)
74
- if (this.objects[i] == object_or_index)
75
- {
76
- this.objects.splice(i, 1);
77
- this.lighting.removeObject(this.objects[i]);
78
- return this.objects[i];
79
- }
80
78
  },
81
79
 
82
80
  /**
@@ -88,13 +86,13 @@ Jax.World = (function() {
88
86
  * - ary (Array): an optional array to populate. A new one will be created if this is not specified.
89
87
  * (Note: the array's contents will be cleared.)
90
88
  *
91
- * Picks all visible object indices within the specified rectangular regions and returns them as elements in
89
+ * Picks all visible object IDs within the specified rectangular regions and returns them as elements in
92
90
  * an array.
93
91
  *
94
- * An object's index matches its position in the world's object list. That is, the following code is
95
- * valid:
92
+ * An object's ID matches is unique throughout Jax, even across multiple contexts.
96
93
  *
97
- * this.world.getObjects(this.world.pickRegionalIDs(0,0, 100,100));
94
+ * If you want references to the actual objects, instead of just their unique IDs, consider using
95
+ * the #pickRegion() method instead.
98
96
  *
99
97
  **/
100
98
  pickRegionalIndices: function(x1, y1, x2, y2, ary) {
@@ -103,6 +101,8 @@ Jax.World = (function() {
103
101
  else ary = new Array();
104
102
  var world = this, pickBuffer = getPickBuffer(this), context = this.context;
105
103
  var data = new Uint8Array(w*h*4);
104
+ x1 = Math.min(x1, x2);
105
+ y1 = Math.min(y1, y2);
106
106
 
107
107
  pickBuffer.bind(context, function() {
108
108
  pickBuffer.viewport(context);
@@ -122,7 +122,7 @@ Jax.World = (function() {
122
122
  for (var i = 2; i < data.length; i += 4) {
123
123
  if (data[i] > 0) { // blue key exists, we've found an object
124
124
  index = Jax.Util.decodePickingColor(data[i-2], data[i-1], data[i], data[i+1]);
125
- if (index != undefined) {
125
+ if (index != undefined && ary.indexOf(index) == -1) {
126
126
  ary.push(index);
127
127
  }
128
128
  }
@@ -132,7 +132,7 @@ Jax.World = (function() {
132
132
  },
133
133
 
134
134
  /**
135
- * Jax.World#pickRegion(x1, y1, x2, y2) -> Array
135
+ * Jax.World#pickRegion(x1, y1, x2, y2[, ary]) -> Array
136
136
  * - x1 (Number): the screen X coordinate of the first corner of the 2D rectangle within which to pick
137
137
  * - y1 (Number): the screen Y coordinate of the first corner of the 2D rectangle within which to pick
138
138
  * - x2 (Number): the screen X coordinate of the second corner of the 2D rectangle within which to pick
@@ -144,9 +144,9 @@ Jax.World = (function() {
144
144
  * an array.
145
145
  **/
146
146
  pickRegion: function(x1, y1, x2, y2, ary) {
147
- var result = this.pickRegionalIndices(x1, y1, x2, y2);
147
+ var result = this.pickRegionalIndices(x1, y1, x2, y2, ary);
148
148
  for (var i = 0; i < result.length; i++)
149
- result[i] = this.getObject(i);
149
+ result[i] = Jax.Model.__instances[result[i]];
150
150
  return result;
151
151
  },
152
152
 
@@ -176,7 +176,7 @@ Jax.World = (function() {
176
176
  pick: function(x, y) {
177
177
  var index = this.pickIndex(x, y);
178
178
  if (index != undefined) {
179
- return this.getObject(index);
179
+ return Jax.Model.__instances[index];
180
180
  }
181
181
  return index;
182
182
  },
@@ -186,7 +186,9 @@ Jax.World = (function() {
186
186
  * Returns the number of objects currently registered with this World.
187
187
  **/
188
188
  countObjects: function() {
189
- return this.objects.length;
189
+ var count = 0;
190
+ for (var i in this.objects) count++;
191
+ return count;
190
192
  },
191
193
 
192
194
  /**
@@ -216,26 +218,22 @@ Jax.World = (function() {
216
218
  /* this.current_pass is used by the material */
217
219
 
218
220
  this.context.glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
219
- var unlit = Jax.Util.normalizeOptions(options, {unlit:true});
221
+ var _options = Jax.Util.normalizeOptions(options, {unlit:true});
220
222
 
221
- if (this.lighting.isEnabled() && (!unlit.material || (unlit.material.supportsLighting && unlit.material.supportsLighting()))) {
223
+ if (this.lighting.isEnabled() && (!_options.material || (_options.material.supportsLighting && _options.material.supportsLighting()))) {
222
224
  /* illumination pass */
223
225
  this.context.current_pass = Jax.Scene.ILLUMINATION_PASS;
224
226
  this.lighting.illuminate(this.context, options);
225
227
 
226
228
  /* ambient pass - unlit objects only because lit objects get ambient+diffuse+specular in one pass */
227
229
  this.context.current_pass = Jax.Scene.AMBIENT_PASS;
228
- for (i = 0; i < this.objects.length; i++)
229
- if (!this.objects[i].isLit()) {
230
- unlit.model_index = i;
231
- this.objects[i].render(this.context, unlit);
232
- }
230
+ for (i in this.objects)
231
+ if (!this.objects[i].isLit())
232
+ this.objects[i].render(this.context, _options);
233
233
  } else {
234
234
  this.context.current_pass = Jax.Scene.AMBIENT_PASS;
235
- for (i = 0; i < this.objects.length; i++) {
236
- unlit.model_index = i;
237
- this.objects[i].render(this.context, unlit);
238
- }
235
+ for (i in this.objects)
236
+ this.objects[i].render(this.context, _options);
239
237
  }
240
238
 
241
239
  return this;
@@ -250,27 +248,34 @@ Jax.World = (function() {
250
248
  * the objects' respective +update+ functions (if they have one).
251
249
  **/
252
250
  update: function(timechange) {
253
- for (var i = this.objects.length-1; i >= 0; i--)
251
+ for (var i in this.objects) {
254
252
  if (this.objects[i].update)
255
253
  this.objects[i].update(timechange);
254
+ }
256
255
  return this;
257
256
  },
258
257
 
259
258
  /**
260
- * Jax.World#dispose() -> Jax.World
259
+ * Jax.World#dispose([include_objects=true]) -> Jax.World
261
260
  *
262
261
  * Disposes of this world by removing all references to its objects and
263
- * reinitializing its +Jax.Scene.LightManager+ instance. Note that the
264
- * individual objects are not disposed; this is left as a task for either
265
- * the developer or the JavaScript garbage collector. The reason for this
266
- * is because it is impossible for Jax.World to know whether the objects
267
- * in question are in use by other Worlds.
262
+ * reinitializing its +Jax.Scene.LightManager+ instance. Note that by
263
+ * default, objects within this world will also be disposed. Pass
264
+ * `false` as an argument if you do not want the objects to be disposed.
265
+ *
266
+ * Note that both models and meshes _can_ be reused after disposal; they'll just
267
+ * be silently re-initialized. This means it is safe to dispose of models while
268
+ * they are still being used (although this is slow and not recommended if at all
269
+ * avoidable).
270
+ *
268
271
  **/
269
- dispose: function() {
272
+ dispose: function(include_objects) {
270
273
  var i, o;
271
274
 
272
- for (i = this.objects.length-1; i >= 0; i--)
273
- (o = this.objects.pop());// && o.dispose();
275
+ for (i in this.objects) {
276
+ if (include_objects !== false)
277
+ delete this.objects[i];
278
+ }
274
279
 
275
280
  this.lighting = new Jax.Scene.LightManager(this.context);
276
281
  }
data/lib/jax/version.rb CHANGED
@@ -2,7 +2,7 @@ module Jax
2
2
  module Version
3
3
  MAJOR = 2
4
4
  MINOR = 0
5
- PATCH = 6
5
+ PATCH = 7
6
6
  BUILD = nil
7
7
  STRING = BUILD ? [MAJOR, MINOR, PATCH, BUILD].join(".") : [MAJOR, MINOR, PATCH].join(".")
8
8
  end
@@ -8,6 +8,28 @@ describe("Jax.Controller", function() {
8
8
  expect(Jax.views.find("welcome/index")).not.toBeUndefined();
9
9
  });
10
10
 
11
+ describe("with a view defined", function() {
12
+ var view;
13
+ beforeEach(function() {
14
+ view = function() { };
15
+ Jax.views.push("FooBars/index", view);
16
+ });
17
+
18
+ it("should indicate the view exists", function() {
19
+ expect(Jax.views.exists("foo_bars/index")).toBeTruthy();
20
+ });
21
+
22
+ it("should indicate CamelCased variants of the view exist", function() {
23
+ expect(Jax.views.exists("Foo_bars/index")).toBeTruthy();
24
+ expect(Jax.views.exists("FooBars/index")).toBeTruthy();
25
+ });
26
+
27
+ it("should override the default view", function() {
28
+ Jax.Controller.create("FooBars", {});
29
+ expect(Jax.views.find("foo_bars/index").view_func).toBe(view);
30
+ });
31
+ });
32
+
11
33
  describe("with an update method", function() {
12
34
  var context;
13
35
 
@@ -3,7 +3,10 @@ describe("Jax.RouteSet", function() {
3
3
  var controller_class = Jax.Controller.create({index: function() { }});
4
4
  Jax.views.push("generic/index", function() { });
5
5
 
6
- beforeEach(function() { map = Jax.routes; map.clear(); });
6
+ beforeEach(function() {
7
+ map = Jax.routes;
8
+ map.clear();
9
+ });
7
10
 
8
11
  describe("when a CamelCase controller name is given", function() {
9
12
  beforeEach(function() {
@@ -44,64 +44,81 @@ describe("Jax.World", function() {
44
44
  obottomright = world.addObject(new Jax.Model({position:[ 2.5,-2.5, -5],mesh:mesh}));
45
45
  });
46
46
 
47
- it("center", function() { expect(world.pick(at.center_x, at.center_y)).toEqual(ofront); });
48
- it("top left", function() { expect(world.pick(at.left, at.top)).toEqual(otopleft); });
49
- it("top right", function() { expect(world.pick(at.right,at.top)).toEqual(otopright); });
50
- it("bottom left", function() { expect(world.pick(at.left, at.bottom)).toEqual(obottomleft); });
51
- it("bottom right", function() { expect(world.pick(at.right,at.bottom)).toEqual(obottomright); });
52
- /*
47
+ it("center", function() { expect(world.pick(at.center_x, at.center_y) === ofront).toBeTruthy(); });
48
+ it("top left", function() { expect(world.pick(at.left, at.top) === otopleft).toBeTruthy(); });
49
+ it("top right", function() { expect(world.pick(at.right,at.top) === otopright).toBeTruthy(); });
50
+ it("bottom left", function() { expect(world.pick(at.left, at.bottom) === obottomleft).toBeTruthy(); });
51
+ it("bottom right", function() { expect(world.pick(at.right,at.bottom) === obottomright).toBeTruthy(); });
52
+
53
53
  it("region: everything", function() {
54
54
  var objects = world.pickRegion(at.left, at.top, at.right, at.bottom);
55
- expect(objects).toContain(ofront);
56
- expect(objects).toContain(otopleft);
57
- expect(objects).toContain(otopright);
58
- expect(objects).toContain(obottomleft);
59
- expect(objects).toContain(obottomright);
55
+ expect(objects.indexOf(ofront)).not.toEqual(-1);
56
+ expect(objects.indexOf(otopleft)).not.toEqual(-1);
57
+ expect(objects.indexOf(otopright)).not.toEqual(-1);
58
+ expect(objects.indexOf(obottomleft)).not.toEqual(-1);
59
+ expect(objects.indexOf(obottomright)).not.toEqual(-1);
60
60
  });
61
61
 
62
62
  it("region: top-left quadrant", function() {
63
63
  var objects = world.pickRegion(at.left, at.top, at.center_x, at.center_y);
64
- expect(objects).toContain(ofront);
65
- expect(objects).toContain(otopleft);
66
- expect(objects).not.toContain(otopright);
67
- expect(objects).not.toContain(obottomleft);
68
- expect(objects).not.toContain(obottomright);
64
+ expect(objects.indexOf(ofront)).not.toEqual(-1);
65
+ expect(objects.indexOf(otopleft)).not.toEqual(-1);
66
+ expect(objects.indexOf(otopright)).toEqual(-1);
67
+ expect(objects.indexOf(obottomleft)).toEqual(-1);
68
+ expect(objects.indexOf(obottomright)).toEqual(-1);
69
69
  });
70
-
70
+
71
71
  it("region: top-right quadrant", function() {
72
72
  var objects = world.pickRegion(at.right, at.top, at.center_x, at.center_y);
73
- expect(objects).toContain(ofront);
74
- expect(objects).not.toContain(otopleft);
75
- expect(objects).toContain(otopright);
76
- expect(objects).not.toContain(obottomleft);
77
- expect(objects).not.toContain(obottomright);
73
+ expect(objects.indexOf(ofront)).not.toEqual(-1);
74
+ expect(objects.indexOf(otopleft)).toEqual(-1);
75
+ expect(objects.indexOf(otopright)).not.toEqual(-1);
76
+ expect(objects.indexOf(obottomleft)).toEqual(-1);
77
+ expect(objects.indexOf(obottomright)).toEqual(-1);
78
78
  });
79
-
79
+
80
80
  it("region: bottom-left quadrant", function() {
81
81
  var objects = world.pickRegion(at.left, at.bottom, at.center_x, at.center_y);
82
- expect(objects).toContain(ofront);
83
- expect(objects).not.toContain(otopleft);
84
- expect(objects).not.toContain(otopright);
85
- expect(objects).toContain(obottomleft);
86
- expect(objects).not.toContain(obottomright);
82
+ expect(objects.indexOf(ofront)).not.toEqual(-1);
83
+ expect(objects.indexOf(otopleft)).toEqual(-1);
84
+ expect(objects.indexOf(otopright)).toEqual(-1);
85
+ expect(objects.indexOf(obottomleft)).not.toEqual(-1);
86
+ expect(objects.indexOf(obottomright)).toEqual(-1);
87
87
  });
88
88
 
89
89
  it("region: bottom-right quadrant", function() {
90
90
  var objects = world.pickRegion(at.right, at.bottom, at.center_x, at.center_y);
91
- expect(objects).toContain(ofront);
92
- expect(objects).not.toContain(otopleft);
93
- expect(objects).not.toContain(otopright);
94
- expect(objects).not.toContain(obottomleft);
95
- expect(objects).toContain(obottomright);
91
+ expect(objects.indexOf(ofront)).not.toEqual(-1);
92
+ expect(objects.indexOf(otopleft)).toEqual(-1);
93
+ expect(objects.indexOf(otopright)).toEqual(-1);
94
+ expect(objects.indexOf(obottomleft)).toEqual(-1);
95
+ expect(objects.indexOf(obottomright)).not.toEqual(-1);
96
+ });
97
+
98
+ it("should be able to pick objects not explicitly added to the world", function() {
99
+ var onested = new Jax.Model({position: [0.0, 0.0, -5], mesh: mesh});
100
+ ofront.render = function(context, options) { onested.render(context, options); };
101
+ expect(world.pick(at.center_x, at.center_y) === onested).toBeTruthy();
102
+ });
103
+
104
+ it("should be able to regionally pick objects not explicitly added to the world", function() {
105
+ var onested = new Jax.Model({position: [0.0, 0.0, -5], mesh: mesh});
106
+ ofront.render = function(context, options) { onested.render(context, options); };
107
+ expect(world.pickRegion(at.center_x-1, at.center_y-1, at.center_x+1, at.center_y+1)[0] === onested).toBeTruthy();
96
108
  });
97
- */
98
109
  });
99
110
 
100
111
  describe("with an object", function() {
101
- beforeEach(function() { world.addObject(new Jax.Model()); });
112
+ var model;
113
+ beforeEach(function() { world.addObject(model = new Jax.Model()); });
102
114
 
103
- it("should remove the object", function() {
104
- world.removeObject(world.getObject(0));
115
+ it("should remove objects by reference", function() {
116
+ world.removeObject(model);
117
+ expect(world.countObjects()).toEqual(0);
118
+ });
119
+
120
+ it("should remove objects by ID", function() {
121
+ world.removeObject(model.__unique_id);
105
122
  expect(world.countObjects()).toEqual(0);
106
123
  });
107
124
  });
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jax
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.6
4
+ version: 2.0.7
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-12-17 00:00:00.000000000Z
12
+ date: 2012-01-08 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
16
- requirement: &2153610220 !ruby/object:Gem::Requirement
16
+ requirement: &2153840660 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 3.1.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2153610220
24
+ version_requirements: *2153840660
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: jquery-rails
27
- requirement: &2153609620 !ruby/object:Gem::Requirement
27
+ requirement: &2153840160 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 1.0.13
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *2153609620
35
+ version_requirements: *2153840160
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: jasmine
38
- requirement: &2153609040 !ruby/object:Gem::Requirement
38
+ requirement: &2153839600 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 1.0.2.0
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *2153609040
46
+ version_requirements: *2153839600
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rest-client
49
- requirement: &2153608480 !ruby/object:Gem::Requirement
49
+ requirement: &2153839120 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 1.6.3
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *2153608480
57
+ version_requirements: *2153839120
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: rspec
60
- requirement: &2153593920 !ruby/object:Gem::Requirement
60
+ requirement: &2153838620 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: 2.6.0
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *2153593920
68
+ version_requirements: *2153838620
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: coffee-rails
71
- requirement: &2153593380 !ruby/object:Gem::Requirement
71
+ requirement: &2153837980 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ~>
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: 3.1.0
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *2153593380
79
+ version_requirements: *2153837980
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: coderay
82
- requirement: &2153592720 !ruby/object:Gem::Requirement
82
+ requirement: &2153837480 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ~>
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: 0.9.7
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *2153592720
90
+ version_requirements: *2153837480
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: sqlite3
93
- requirement: &2153592180 !ruby/object:Gem::Requirement
93
+ requirement: &2153837020 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ~>
@@ -98,10 +98,10 @@ dependencies:
98
98
  version: 1.3.4
99
99
  type: :development
100
100
  prerelease: false
101
- version_requirements: *2153592180
101
+ version_requirements: *2153837020
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: sass-rails
104
- requirement: &2153591580 !ruby/object:Gem::Requirement
104
+ requirement: &2153836420 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - ~>
@@ -109,10 +109,10 @@ dependencies:
109
109
  version: 3.1.0
110
110
  type: :development
111
111
  prerelease: false
112
- version_requirements: *2153591580
112
+ version_requirements: *2153836420
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: uglifier
115
- requirement: &2153591000 !ruby/object:Gem::Requirement
115
+ requirement: &2153835940 !ruby/object:Gem::Requirement
116
116
  none: false
117
117
  requirements:
118
118
  - - ~>
@@ -120,10 +120,10 @@ dependencies:
120
120
  version: 1.0.2
121
121
  type: :development
122
122
  prerelease: false
123
- version_requirements: *2153591000
123
+ version_requirements: *2153835940
124
124
  - !ruby/object:Gem::Dependency
125
125
  name: genspec
126
- requirement: &2153590400 !ruby/object:Gem::Requirement
126
+ requirement: &2153835460 !ruby/object:Gem::Requirement
127
127
  none: false
128
128
  requirements:
129
129
  - - ~>
@@ -131,10 +131,10 @@ dependencies:
131
131
  version: 0.2.3
132
132
  type: :development
133
133
  prerelease: false
134
- version_requirements: *2153590400
134
+ version_requirements: *2153835460
135
135
  - !ruby/object:Gem::Dependency
136
136
  name: selenium-webdriver
137
- requirement: &2153589820 !ruby/object:Gem::Requirement
137
+ requirement: &2153834860 !ruby/object:Gem::Requirement
138
138
  none: false
139
139
  requirements:
140
140
  - - ~>
@@ -142,10 +142,10 @@ dependencies:
142
142
  version: 2.9.1
143
143
  type: :development
144
144
  prerelease: false
145
- version_requirements: *2153589820
145
+ version_requirements: *2153834860
146
146
  - !ruby/object:Gem::Dependency
147
147
  name: fakeweb
148
- requirement: &2153589220 !ruby/object:Gem::Requirement
148
+ requirement: &2153834380 !ruby/object:Gem::Requirement
149
149
  none: false
150
150
  requirements:
151
151
  - - ~>
@@ -153,10 +153,10 @@ dependencies:
153
153
  version: 1.3.0
154
154
  type: :development
155
155
  prerelease: false
156
- version_requirements: *2153589220
156
+ version_requirements: *2153834380
157
157
  - !ruby/object:Gem::Dependency
158
158
  name: ansi
159
- requirement: &2153588720 !ruby/object:Gem::Requirement
159
+ requirement: &2153834000 !ruby/object:Gem::Requirement
160
160
  none: false
161
161
  requirements:
162
162
  - - ! '>='
@@ -164,10 +164,10 @@ dependencies:
164
164
  version: '0'
165
165
  type: :development
166
166
  prerelease: false
167
- version_requirements: *2153588720
167
+ version_requirements: *2153834000
168
168
  - !ruby/object:Gem::Dependency
169
169
  name: cucumber-rails
170
- requirement: &2153588060 !ruby/object:Gem::Requirement
170
+ requirement: &2153833460 !ruby/object:Gem::Requirement
171
171
  none: false
172
172
  requirements:
173
173
  - - ~>
@@ -175,10 +175,10 @@ dependencies:
175
175
  version: 1.0.2
176
176
  type: :development
177
177
  prerelease: false
178
- version_requirements: *2153588060
178
+ version_requirements: *2153833460
179
179
  - !ruby/object:Gem::Dependency
180
180
  name: RedCloth
181
- requirement: &2153587440 !ruby/object:Gem::Requirement
181
+ requirement: &2153832860 !ruby/object:Gem::Requirement
182
182
  none: false
183
183
  requirements:
184
184
  - - ~>
@@ -186,10 +186,10 @@ dependencies:
186
186
  version: '4.2'
187
187
  type: :development
188
188
  prerelease: false
189
- version_requirements: *2153587440
189
+ version_requirements: *2153832860
190
190
  - !ruby/object:Gem::Dependency
191
191
  name: w3c_validators
192
- requirement: &2153586860 !ruby/object:Gem::Requirement
192
+ requirement: &2153832400 !ruby/object:Gem::Requirement
193
193
  none: false
194
194
  requirements:
195
195
  - - ~>
@@ -197,10 +197,10 @@ dependencies:
197
197
  version: '1.2'
198
198
  type: :development
199
199
  prerelease: false
200
- version_requirements: *2153586860
200
+ version_requirements: *2153832400
201
201
  - !ruby/object:Gem::Dependency
202
202
  name: treetop
203
- requirement: &2153586280 !ruby/object:Gem::Requirement
203
+ requirement: &2153831940 !ruby/object:Gem::Requirement
204
204
  none: false
205
205
  requirements:
206
206
  - - ~>
@@ -208,10 +208,10 @@ dependencies:
208
208
  version: 1.4.9
209
209
  type: :development
210
210
  prerelease: false
211
- version_requirements: *2153586280
211
+ version_requirements: *2153831940
212
212
  - !ruby/object:Gem::Dependency
213
213
  name: bluecloth
214
- requirement: &2153584940 !ruby/object:Gem::Requirement
214
+ requirement: &2153831320 !ruby/object:Gem::Requirement
215
215
  none: false
216
216
  requirements:
217
217
  - - ~>
@@ -219,7 +219,7 @@ dependencies:
219
219
  version: 2.0.11
220
220
  type: :development
221
221
  prerelease: false
222
- version_requirements: *2153584940
222
+ version_requirements: *2153831320
223
223
  description: ! "\n Framework for creating rich WebGL-enabled applications using
224
224
  JavaScript and Ruby.\n Can be used stand-alone to create static JavaScript documents,
225
225
  or integrated\n seamlessly with Ruby on Rails to build dynamic WebGL applications.\n
@@ -648,7 +648,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
648
648
  version: '0'
649
649
  segments:
650
650
  - 0
651
- hash: 1570841926271225879
651
+ hash: -1809678549776687615
652
652
  required_rubygems_version: !ruby/object:Gem::Requirement
653
653
  none: false
654
654
  requirements:
@@ -657,7 +657,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
657
657
  version: '0'
658
658
  segments:
659
659
  - 0
660
- hash: 1570841926271225879
660
+ hash: -1809678549776687615
661
661
  requirements: []
662
662
  rubyforge_project: jax
663
663
  rubygems_version: 1.8.10