UNPKG

react-umg

Version:

A React renderer for Unreal Motion Graphics With Unreal.js

178 lines (160 loc) 5.23 kB
'use strict'; const ReactMultiChild = require('react-dom/lib/ReactMultiChild'); const ReactCurrentOwner = require('react/lib/ReactCurrentOwner'); const invariant = require('fbjs/lib/invariant'); const warning = require('fbjs/lib/warning'); const shallowEqual = require('fbjs/lib/shallowEqual'); const UmgRoots = require('./UMGRoots'); const TypeThunks = require('./components/ReactUMGClassMap'); // In some cases we might not have a owner and when // that happens there is no need to inlcude "Check the render method of ...". const checkRenderMethod = () => ReactCurrentOwner.owner && ReactCurrentOwner.owner.getName() ? ` Check the render method of "${ReactCurrentOwner.owner.getName()}".` : ''; /** * @constructor ReactUMGComponent * @extends ReactComponent * @extends ReactMultiChild */ const ReactUMGComponent = function(element) { this.node = null; this._mountImage = null; this._renderedChildren = null; this._currentElement = element; this.ueobj = null; this._rootNodeID = null; this._typeThunk = TypeThunks[element.type]; if (process.env.NODE_ENV !== 'production') { warning( Object.keys(TypeThunks).indexOf(element.type) > -1, 'Attempted to render an unsupported generic component "%s". ' + 'Must be one of the following: ' + Object.keys(TypeThunks), element.type, checkRenderMethod() ); } }; /** * Mixin for UMG components. */ ReactUMGComponent.Mixin = { getHostNode() {}, getPublicInstance() { // TODO: This should probably use a composite wrapper return this; }, unmountComponent() { if (this.ueobj) { if (this._currentElement.props.$unlink) { this._currentElement.props.$unlink(this.ueobj); } for (var key in this._currentElement.props) { if (typeof this._currentElement.props[key] === 'function') { this.updateProperty(this.ueobj, null, key); } } this.ueobj.RemoveFromParent(); } this.unmountChildren(); this._rootNodeID = null; this.ueobj = null; }, updateProperty(widget, value, key) { this._typeThunk.applyProperty(widget,value, key); }, sync() { JavascriptWidget.CallSynchronizeProperties(this.ueobj) JavascriptWidget.CallSynchronizeProperties(this.ueobj.Slot) }, mountComponent( transaction, // for creating/updating rootID, // Root ID of this subtree hostContainerInfo, // nativeContainerInfo context // secret context, shhhh ) { var parent = rootID; rootID = typeof rootID === 'object' ? rootID._rootNodeID : rootID; this._rootNodeID = rootID; var umgRoot = parent.ueobj ? parent.ueobj : UmgRoots[rootID]; if (umgRoot instanceof JavascriptWidget) { umgRoot = umgRoot.WidgetTree.RootWidget } var outer = Root.GetEngine ? JavascriptLibrary.CreatePackage(null,'/Script/Javascript') : GWorld this.ueobj = this._typeThunk.createUmgElement( this._currentElement, cls => { var widget = new cls(outer); var props = this._currentElement.props; for (var key in props) { this.updateProperty(widget, props[key], key); } if (widget instanceof JavascriptWidget) { widget.AddChild(new SizeBox(outer)); } if (umgRoot['AddChild'] != null) { var slot = umgRoot.AddChild(widget); if (slot) slot.Content.Slot = slot; return widget; } else { console.error('cannot add child', umgRoot); } } ); this.sync(); if (this._currentElement.props.$link) { this._currentElement.props.$link(this.ueobj); } this.initializeChildren( this._currentElement.props.children, transaction, context ); return rootID; }, /** * Updates the component's currently mounted representation. */ receiveComponent( nextElement, transaction, context) { const prevElement = this._currentElement; this._currentElement = nextElement; this.updateComponent(transaction, prevElement, nextElement, context); }, updateComponent( transaction, prevElement, nextElement, context) { var lastProps = prevElement.props; var nextProps = nextElement.props; if (!shallowEqual(lastProps, nextProps)) { this.updateProperties(lastProps, nextProps, transaction) } this.updateChildren(nextProps.children, transaction, context); }, updateProperties( lastProps, nextProps, transaction) { for (var propKey in nextProps) { var nextProp = nextProps[propKey]; var lastProp = lastProps != null ? lastProps[propKey] : undefined; if (!nextProps.hasOwnProperty(propKey) || nextProp === lastProp || nextProp == null && lastProp == null) { continue; } this.updateProperty(this.ueobj, nextProp, propKey); } }, initializeChildren( children, transaction, context) { this.mountChildren(children, transaction, context); }, }; /** * Order of mixins is important. ReactUMGComponent overrides methods in * ReactMultiChild. */ Object.assign( ReactUMGComponent.prototype, ReactMultiChild.Mixin, ReactUMGComponent.Mixin ); module.exports = ReactUMGComponent;