@needle-tools/engine
Version:
Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development with great integrations into editors like Unity or Blender - and can be deployed onto any device! It is flexible, extensible and networking and XR are built-in.
91 lines • 3.48 kB
JavaScript
import { DoubleSide, FrontSide } from "three";
import { FrameEvent } from "../../engine/engine_setup.js";
import { $shadowDomOwner } from "./Symbols.js";
export function tryGetUIComponent(obj) {
const owner = obj[$shadowDomOwner];
if (owner) {
return owner;
}
if (obj.parent) {
return tryGetUIComponent(obj.parent);
}
return null;
}
export function isUIObject(obj) {
return obj["isUI"] === true || typeof obj[$shadowDomOwner] === "object";
}
export function updateRenderSettings(shadowComponent, settings) {
if (!shadowComponent)
return;
// const owner = shadowComponent[$shadowDomOwner];
// if (!owner)
// console.log(shadowComponent)
const mat = shadowComponent["material"];
if (mat?.isMaterial === true) {
const parent = shadowComponent.parent;
if (parent && parent["isText"] === true) {
// console.log(shadowComponent, shadowComponent.name);
}
// mat.depthTest = !settings.renderOnTop ?? true;
// mat.depthWrite = settings.depthWrite ?? false;
mat.side = (settings.doubleSided ?? true) ? DoubleSide : FrontSide;
mat.shadowSide = settings.doubleSided ? DoubleSide : FrontSide;
shadowComponent.castShadow = settings.castShadows ? settings.castShadows : false;
shadowComponent.receiveShadow = settings.receiveShadows ? settings.receiveShadows : false;
}
for (const ch of shadowComponent.children) {
updateRenderSettings(ch, settings);
}
}
// TODO: change to use utils Watch since a revocable proxy makes a object completely useless once it is revoked
/** internal method to proxy a field to detect changes */
/**@deprecated use watcher instead */
export function onChange(caller, field, callback) {
if (caller[field] === undefined) {
console.warn("Field", field, "is undefined on", caller);
}
// create proxy that notifies on value change
const res = Proxy.revocable(caller[field], {
// get(target, prop, receiver) {
// return Reflect.get(target, prop, receiver);
// },
set(target, prop, value, receiver) {
const currentValue = target[prop];
const res = Reflect.set(target, prop, value, receiver);
callback(value, currentValue);
return res;
}
});
// setup revokeable
const revoke = res.revoke;
const original = caller[field];
res.revoke = () => {
caller[field] = original;
revoke();
};
caller[field] = res.proxy;
return res;
}
const $scheduledActionKey = Symbol("Scheduled action");
// use to schedule a callback at a specific moment in the frame
/** internal method to schedule a function at a specific moment in the update loop */
export function scheduleAction(caller, action, timing = FrameEvent.OnBeforeRender) {
let cache = caller[$scheduledActionKey];
if (!cache)
cache = caller[$scheduledActionKey] = {};
const key = action.name;
if (!cache[timing])
cache[timing] = {};
const actions = cache[timing];
const existing = actions[key];
if (existing)
return;
function* gen() {
// yield;
action?.call(caller);
actions[key] = null;
}
const coroutine = caller.startCoroutine(gen(), timing);
actions[key] = coroutine;
}
//# sourceMappingURL=Utils.js.map