jax 2.0.6 → 2.0.7

Sign up to get free protection for your applications and to get access to all the features.
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