relying on implicit.context.js to set drawto and listening to world

events
This commit is contained in:
2026-07-04 11:22:52 +02:00
parent 7dfe0beb26
commit 61c7a29113
2 changed files with 129 additions and 79 deletions

View File

@@ -9,7 +9,7 @@
"modernui": 1 "modernui": 1
}, },
"classnamespace": "box", "classnamespace": "box",
"rect": [ 636.0, 100.0, 1444.0, 848.0 ], "rect": [ 334.0, 100.0, 1444.0, 848.0 ],
"integercoordinates": 1, "integercoordinates": 1,
"boxes": [ "boxes": [
{ {
@@ -868,11 +868,11 @@
"box": { "box": {
"id": "obj-4", "id": "obj-4",
"maxclass": "newobj", "maxclass": "newobj",
"numinlets": 2, "numinlets": 1,
"numoutlets": 2, "numoutlets": 1,
"outlettype": [ "", "" ], "outlettype": [ "" ],
"patching_rect": [ 239.0, 374.0, 55.0, 22.0 ], "patching_rect": [ 211.0, 405.0, 125.0, 22.0 ],
"text": "route init" "text": "loadmess controllable"
} }
}, },
{ {
@@ -882,8 +882,8 @@
"maxclass": "comment", "maxclass": "comment",
"numinlets": 1, "numinlets": 1,
"numoutlets": 0, "numoutlets": 0,
"patching_rect": [ 315.0, 532.0, 272.0, 24.0 ], "patching_rect": [ 315.0, 532.0, 256.0, 24.0 ],
"text": "Select which object to control in camera space" "text": "Select which object to control in view space"
} }
}, },
{ {
@@ -1145,12 +1145,12 @@
{ {
"box": { "box": {
"id": "obj-5", "id": "obj-5",
"linecount": 27, "linecount": 26,
"maxclass": "comment", "maxclass": "comment",
"numinlets": 1, "numinlets": 1,
"numoutlets": 0, "numoutlets": 0,
"patching_rect": [ 611.0, 459.0, 568.0, 368.0 ], "patching_rect": [ 611.0, 459.0, 568.0, 355.0 ],
"text": "HOW TO USE IN YOUR OWN PATCH\n\n0. Add [tc.fpcontrol] and, depending on the controls you want, [p mouse_keyboard_controls] and/or [gamepad.drive] . You can also create your own input method as it relies on simple 'move X 0 Z' and 'turn X Y 0' messages\n\n1. In order to initialize [tc.fpcontrol] you need to send 'camera' followed by the name of your jit.gl.camera or a jit.anid.node attached to it. Will serve as the basis for moving objects in view space. This is necessary to control any object. A caveheat is that this message must be sent after the world has been initalized. You can [route init] from [jit.world] right outlet for that.\n\n2. Send 'controllable' to get a list of all controllable jit.gl objects in your patch.\n \n4. Send 'control_camera' followed by the the name of your jit.gl.camera or a jit.anid.node attached to it to control the camera. If flymode is disabled, the camera will remain on the same elevation (Y world pos) unless using the elevation controls (gamepad triggers). If flymode is enabled, the camera will go in the direction it faces and elevation controls will make it move up-down relatively to that direction. \n\n5. Send 'control' followed by the name of a jit.gl or jit.anim.node object to control it in camera space. When using the name of a jit.gl object, its top-level user-created jit.anim.node will be used as entry point for the controls from v8. If there is no user-created jit.anim.node used by this object, its implicit internal jit.anim.node will be used as entry point. When using the name of a jit.anim.node directly, it will be the entry point for the controls comming from v8. If show_bounds is enabled and the target object is a bounds-compatible jit.gl object (or a jit.anim.node controlling bounds-compatible jit.gl objects), its bounds will be displayed\n\n6. Use the mouse+keyboard or gamepad to control the object or camera." "text": "HOW TO USE IN YOUR OWN PATCH\n\n0. Add [tc.fpcontrol] and, depending on the controls you want, [p mouse_keyboard_controls] and/or [gamepad.drive] . You can also create your own input method as it relies on simple 'move X 0 Z' and 'turn X Y 0' messages\n\n1. In order to use [tc.fpcontrol] you to tell it which camera (or jit.anid.node attached to it) to use. You can pass that as an attribute as shown here. This camera/anim.node will serve as the basis for moving objects in view space. This is necessary to control any object.\n\n2. Send 'controllable' to get a list of all controllable jit.gl objects in your patch.\n \n4. Send 'control_camera' followed by the the name of your jit.gl.camera or a jit.anid.node attached to it to control the camera. If flymode is disabled, the camera will remain on the same elevation (Y world pos) unless using the elevation controls (gamepad triggers). If flymode is enabled, the camera will go in the direction it faces and elevation controls will make it move up-down relatively to that direction. \n\n5. Send 'control' followed by the name of a jit.gl or jit.anim.node object to control it in camera space. When using the name of a jit.gl object, its top-level user-created jit.anim.node will be used as entry point for the controls from v8. If there is no user-created jit.anim.node used by this object, its implicit internal jit.anim.node will be used as entry point. When using the name of a jit.anim.node directly, it will be the entry point for the controls comming from v8. If show_bounds is enabled and the target object is a bounds-compatible jit.gl object (or a jit.anim.node controlling bounds-compatible jit.gl objects), its bounds will be displayed\n\n6. Use the mouse+keyboard or gamepad to control the object or camera."
} }
}, },
{ {
@@ -1855,7 +1855,7 @@
{ {
"box": { "box": {
"id": "obj-56", "id": "obj-56",
"items": [ "jit.gl.gridshape", "torus", ",", "jit.gl.plato", "plato", ",", "jit.gl.gridshape", "plane", ",", "jit.gl.light", "u966000628", ",", "jit.gl.model", "model" ], "items": "<empty>",
"maxclass": "umenu", "maxclass": "umenu",
"numinlets": 1, "numinlets": 1,
"numoutlets": 3, "numoutlets": 3,
@@ -2431,17 +2431,6 @@
"text": "gamepad.drive @l_deadzone 0.1 @r_deadzone 0.2 @l_sensitivity 0.4 @r_sensitivity 3 @trigger_sensitivity 0.4" "text": "gamepad.drive @l_deadzone 0.1 @r_deadzone 0.2 @l_sensitivity 0.4 @r_sensitivity 3 @trigger_sensitivity 0.4"
} }
}, },
{
"box": {
"id": "obj-125",
"maxclass": "message",
"numinlets": 2,
"numoutlets": 1,
"outlettype": [ "" ],
"patching_rect": [ 239.0, 405.0, 143.0, 22.0 ],
"text": "camera cam, controllable"
}
},
{ {
"box": { "box": {
"color": [ 0.0, 0.694117647058824, 0.482352941176471, 1.0 ], "color": [ 0.0, 0.694117647058824, 0.482352941176471, 1.0 ],
@@ -2451,12 +2440,12 @@
"numinlets": 1, "numinlets": 1,
"numoutlets": 2, "numoutlets": 2,
"outlettype": [ "", "" ], "outlettype": [ "", "" ],
"patching_rect": [ 53.0, 448.0, 95.0, 22.0 ], "patching_rect": [ 53.0, 448.0, 149.0, 22.0 ],
"saved_object_attributes": { "saved_object_attributes": {
"embed": 0, "embed": 0,
"parameter_enable": 0 "parameter_enable": 0
}, },
"text": "tc.fpcontrol", "text": "tc.fpcontrol @camera cam",
"textfile": { "textfile": {
"filename": "tc.controller.js", "filename": "tc.controller.js",
"flags": 0, "flags": 0,
@@ -2503,13 +2492,12 @@
"box": { "box": {
"dontreplace": 1, "dontreplace": 1,
"id": "obj-60", "id": "obj-60",
"linecount": 2,
"maxclass": "message", "maxclass": "message",
"numinlets": 2, "numinlets": 2,
"numoutlets": 1, "numoutlets": 1,
"outlettype": [ "" ], "outlettype": [ "" ],
"patching_rect": [ 53.0, 647.0, 222.0, 35.0 ], "patching_rect": [ 53.0, 647.0, 222.0, 22.0 ],
"text": "control camera_node_implicit camera_node_implicit" "text": "control torus u787003285"
} }
}, },
{ {
@@ -2569,7 +2557,7 @@
"numoutlets": 1, "numoutlets": 1,
"outlettype": [ "" ], "outlettype": [ "" ],
"parameter_enable": 0, "parameter_enable": 0,
"patching_rect": [ 53.0, 346.0, 97.0, 22.0 ], "patching_rect": [ 53.0, 313.0, 97.0, 22.0 ],
"text_width": 46.0 "text_width": 46.0
} }
}, },
@@ -2582,7 +2570,7 @@
"numoutlets": 1, "numoutlets": 1,
"outlettype": [ "" ], "outlettype": [ "" ],
"parameter_enable": 0, "parameter_enable": 0,
"patching_rect": [ 53.0, 318.0, 87.0, 22.0 ], "patching_rect": [ 53.0, 285.0, 87.0, 22.0 ],
"text_width": 63.0 "text_width": 63.0
} }
}, },
@@ -2595,7 +2583,7 @@
"numoutlets": 1, "numoutlets": 1,
"outlettype": [ "" ], "outlettype": [ "" ],
"parameter_enable": 0, "parameter_enable": 0,
"patching_rect": [ 53.0, 376.0, 121.0, 22.0 ] "patching_rect": [ 53.0, 343.0, 121.0, 22.0 ]
} }
}, },
{ {
@@ -2610,6 +2598,19 @@
"patching_rect": [ 35.5, 63.0, 83.0, 22.0 ], "patching_rect": [ 35.5, 63.0, 83.0, 22.0 ],
"text_width": 61.0 "text_width": 61.0
} }
},
{
"box": {
"attr": "camera",
"id": "obj-7",
"maxclass": "attrui",
"numinlets": 1,
"numoutlets": 1,
"outlettype": [ "" ],
"parameter_enable": 0,
"patching_rect": [ 53.0, 371.0, 186.0, 22.0 ],
"text_width": 61.0
}
} }
], ],
"lines": [ "lines": [
@@ -2637,12 +2638,6 @@
"source": [ "obj-11", 0 ] "source": [ "obj-11", 0 ]
} }
}, },
{
"patchline": {
"destination": [ "obj-109", 0 ],
"source": [ "obj-125", 0 ]
}
},
{ {
"patchline": { "patchline": {
"destination": [ "obj-109", 0 ], "destination": [ "obj-109", 0 ],
@@ -2697,12 +2692,6 @@
"source": [ "obj-3", 1 ] "source": [ "obj-3", 1 ]
} }
}, },
{
"patchline": {
"destination": [ "obj-4", 0 ],
"source": [ "obj-3", 2 ]
}
},
{ {
"patchline": { "patchline": {
"destination": [ "obj-32", 0 ], "destination": [ "obj-32", 0 ],
@@ -2729,7 +2718,7 @@
}, },
{ {
"patchline": { "patchline": {
"destination": [ "obj-125", 0 ], "destination": [ "obj-109", 0 ],
"source": [ "obj-4", 0 ] "source": [ "obj-4", 0 ]
} }
}, },
@@ -2762,6 +2751,12 @@
"destination": [ "obj-109", 0 ], "destination": [ "obj-109", 0 ],
"source": [ "obj-62", 0 ] "source": [ "obj-62", 0 ]
} }
},
{
"patchline": {
"destination": [ "obj-109", 0 ],
"source": [ "obj-7", 0 ]
}
} }
], ],
"autosave": 0 "autosave": 0

View File

@@ -22,8 +22,12 @@ autowatch = 1;
outlets = 2; outlets = 2;
var drawto = ""; // var drawto = "";
declareattribute({ name: "drawto", setter: "setdrawto" }); // declareattribute({ name: "drawto", setter: "setdrawto" });
let world_bangs = false; // is the world banging?
const ctx_finder = require("implicit.context.js");
ctx_finder.register_drawto(this, dosetdrawto, set_root);
var ease = 0.1; var ease = 0.1;
declareattribute({ declareattribute({
@@ -35,10 +39,10 @@ declareattribute({
default: 0.1, default: 0.1,
}); });
var camera_node = ""; var camera = "";
declareattribute({ declareattribute({
name: "camera_node", name: "camera",
setter: "camera", setter: "set_camera",
label: "Camera anim node", label: "Camera anim node",
type: "string", type: "string",
}); });
@@ -227,13 +231,12 @@ class Controller {
} }
if (target) { if (target) {
this.camera_node.name = target; this.camera_node.name = target;
camera_node = target;
this.camera_node.send("animmode", "world"); this.camera_node.send("animmode", "world");
this.get_cam_base_matrix(); this.get_cam_base_matrix();
this.camera_target.name = proxy.name; this.camera_target.name = proxy.name;
this.camera_target.class = proxy.class; this.camera_target.class = proxy.class;
this.camera_target.anim = proxy.anim; this.camera_target.anim = proxy.anim;
camera_node = target; camera = target;
} else { } else {
this.unbind_camera(); this.unbind_camera();
} }
@@ -248,11 +251,11 @@ class Controller {
} else if (this.camera_target.class === "jit_gl_camera") { } else if (this.camera_target.class === "jit_gl_camera") {
// If it was a camera, we set it back as it was, but with the current transform // If it was a camera, we set it back as it was, but with the current transform
const transform = this.camera_node.send("getworldtransform"); const transform = this.camera_node.send("getworldtransform");
const cam = new JitterObject("jit_proxy"); const cam = new JitterObject("jit.proxy");
cam.name = this.camera_target.name; cam.name = this.camera_target.name;
cam.send("anim"); cam.send("anim");
cam.send("anim_reset"); cam.send("anim_reset");
const cam_anim = new JitterObject("jit_proxy"); const cam_anim = new JitterObject("jit.proxy");
cam_anim.name = cam.send("getanim"); cam_anim.name = cam.send("getanim");
cam_anim.send("transform", transform); cam_anim.send("transform", transform);
cam.freepeer(); cam.freepeer();
@@ -262,7 +265,7 @@ class Controller {
this.camera_target.name = ""; this.camera_target.name = "";
this.camera_target.class = ""; this.camera_target.class = "";
this.camera_target.anim = ""; this.camera_target.anim = "";
camera_node = ""; camera = "";
} }
} }
@@ -388,9 +391,11 @@ class Controller {
loadbang(); loadbang();
// Select the object to use as basis for view-space transforms // Select the object to use as basis for view-space transforms
function camera(name) { function set_camera(name) {
camera = name;
if (world_bangs) {
ctlr.camera(name); ctlr.camera(name);
camera_node = ctlr.camera_node.name; }
} }
// Select which object to control in view-space // Select which object to control in view-space
@@ -511,7 +516,9 @@ function loadbang() {
function notifydeleted() { function notifydeleted() {
ctlr.destroy(); ctlr.destroy();
implicit_tracker.freepeer(); ctx_finder.dispose();
if (ctx_lstnr) ctx_lstnr.freepeer();
// implicit_tracker.freepeer();
} }
///////////////////////////////////////////// /////////////////////////////////////////////
@@ -647,29 +654,75 @@ multiplyMatrixVector.local = 1;
///////////////////////////////////////////// /////////////////////////////////////////////
// GL Context // GL Context
///////////////////////////////////////////// /////////////////////////////////////////////
let ctx_root;
let ctx_lstnr;
function set_root(new_root) {
ctx_root = new_root;
if (ctx_lstnr) {
ctx_lstnr.freepeer();
ctw_lstnr = null;
}
ctx_lstnr = new JitterListener(new_root, ctx_callback);
}
set_root.local = 1;
let implicitdrawto = ""; function ctx_callback(event) {
let explicitdrawto = false; switch (event.eventname) {
const implicit_tracker = new JitterObject("jit_gl_implicit"); case "swap": case "draw":
const implicit_lstnr = new JitterListener( if (!world_bangs) {
implicit_tracker.name, // First world bang: world initialized, we can set the camera
implicit_callback world_bangs = true;
); set_camera(camera);
}
break;
// case "mouse":
function implicit_callback(event) { // break;
if (!explicitdrawto && implicitdrawto != implicit_tracker.drawto[0]) { // case "mouseidle":
// important! drawto is an array so get first element
implicitdrawto = implicit_tracker.drawto[0]; // break;
dosetdrawto(implicitdrawto);
// case "keydown":
// // FF_Utils.Print("KEYDOWN", (event.args[0]));
// break;
// case "willfree":
// break;
default:
// post(event.args); post();
break;
} }
} }
implicit_callback.local = 1; ctx_callback.local = 1;
function setdrawto(val) { // let implicitdrawto = "";
explicitdrawto = true; // let explicitdrawto = false;
dosetdrawto(val); // const implicit_tracker = new JitterObject("jit_gl_implicit");
} // const implicit_lstnr = new JitterListener(
setdrawto.local = 1; // implicit_tracker.name,
// implicit_callback
// );
// const ctx_proxy = new JitterObject("jit.proxy");
// function implicit_callback(event) {
// if (!explicitdrawto && implicitdrawto != implicit_tracker.drawto[0]) {
// // important! drawto is an array so get first element
// implicitdrawto = implicit_tracker.drawto[0];
// dosetdrawto(implicitdrawto);
// }
// }
// implicit_callback.local = 1;
// function setdrawto(val) {
// if (val) {
// explicitdrawto = true;
// dosetdrawto(val);
// } else {
// explicitdrawto = false;
// }
// }
// setdrawto.local = 1;
function dosetdrawto(arg) { function dosetdrawto(arg) {
if (arg === drawto || !arg) { if (arg === drawto || !arg) {
@@ -679,5 +732,7 @@ function dosetdrawto(arg) {
drawto = arg; drawto = arg;
ctlr.set_drawto(drawto); ctlr.set_drawto(drawto);
ctx_proxy.name = drawto;
} }
dosetdrawto.local = 1; // dosetdrawto.local = 1;