コード例 #1
0
        public void StartRecording()
        {
            source_type = Source.FILE;
            //NEED to run this world-sycnrhonously
            World currentWorld        = metagen_comp.World;
            int   currentTotalUpdates = currentWorld.TotalUpdates;
            Slot  logix_slot          = metagen_comp.World.RootSlot.AddSlot("temporary logix slot");
            bool  added_logix         = false;

            currentWorld.RunSynchronously(() =>
            {
                foreach (var userItem in metagen_comp.userMetaData)
                {
                    User user             = userItem.Key;
                    UserMetadata metadata = userItem.Value;
                    if (!metadata.isRecording || (metagen_comp.LocalUser == user && !metagen_comp.record_local_user))
                    {
                        continue;
                    }
                    RefID user_id = user.ReferenceID;

                    current_tracked_users.Add(user_id);

                    ReferenceRegister <User> userRegister     = logix_slot.AttachComponent <ReferenceRegister <User> >();
                    userRegister.Target.Target                = user;
                    StandardController standardControllerLeft = logix_slot.AttachComponent <FrooxEngine.LogiX.Input.StandardController>();
                    EnumInput <Chirality> nodeEnum            = logix_slot.AttachComponent <EnumInput <Chirality> >();
                    nodeEnum.Value.Value = Chirality.Left;
                    standardControllerLeft.User.Target = userRegister;
                    standardControllerLeft.Node.Target = nodeEnum;
                    SyncRef <ValueStream <bool> > _primaryStreamLeft   = (SyncRef <ValueStream <bool> >) typeof(StandardController).GetField("_primaryStream", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(standardControllerLeft);
                    SyncRef <ValueStream <bool> > _secondaryStreamLeft = (SyncRef <ValueStream <bool> >) typeof(StandardController).GetField("_secondaryStream", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(standardControllerLeft);
                    SyncRef <ValueStream <bool> > _grabStreamLeft      = (SyncRef <ValueStream <bool> >) typeof(StandardController).GetField("_grabStream", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(standardControllerLeft);
                    SyncRef <ValueStream <bool> > _menuStreamLeft      = (SyncRef <ValueStream <bool> >) typeof(StandardController).GetField("_menuStream", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(standardControllerLeft);
                    SyncRef <ValueStream <float> > _strengthStreamLeft = (SyncRef <ValueStream <float> >) typeof(StandardController).GetField("_strengthStream", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(standardControllerLeft);
                    SyncRef <ValueStream <float2> > _axisStreamLeft    = (SyncRef <ValueStream <float2> >) typeof(StandardController).GetField("_axisStream", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(standardControllerLeft);

                    StandardController standardControllerRight = logix_slot.AttachComponent <FrooxEngine.LogiX.Input.StandardController>();
                    EnumInput <Chirality> nodeEnum2            = logix_slot.AttachComponent <EnumInput <Chirality> >();
                    nodeEnum2.Value.Value = Chirality.Right;
                    standardControllerRight.User.Target = userRegister;
                    standardControllerRight.Node.Target = nodeEnum2;
                    SyncRef <ValueStream <bool> > _primaryStreamRight   = (SyncRef <ValueStream <bool> >) typeof(StandardController).GetField("_primaryStream", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(standardControllerRight);
                    SyncRef <ValueStream <bool> > _secondaryStreamRight = (SyncRef <ValueStream <bool> >) typeof(StandardController).GetField("_secondaryStream", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(standardControllerRight);
                    SyncRef <ValueStream <bool> > _grabStreamRight      = (SyncRef <ValueStream <bool> >) typeof(StandardController).GetField("_grabStream", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(standardControllerRight);
                    SyncRef <ValueStream <bool> > _menuStreamRight      = (SyncRef <ValueStream <bool> >) typeof(StandardController).GetField("_menuStream", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(standardControllerRight);
                    SyncRef <ValueStream <float> > _strengthStreamRight = (SyncRef <ValueStream <float> >) typeof(StandardController).GetField("_strengthStream", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(standardControllerRight);
                    SyncRef <ValueStream <float2> > _axisStreamRight    = (SyncRef <ValueStream <float2> >) typeof(StandardController).GetField("_axisStream", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(standardControllerRight);

                    primaryStreamsRefs[user_id]   = new Tuple <SyncRef <ValueStream <bool> >, SyncRef <ValueStream <bool> > >(_primaryStreamLeft, _primaryStreamRight);
                    secondaryStreamsRefs[user_id] = new Tuple <SyncRef <ValueStream <bool> >, SyncRef <ValueStream <bool> > >(_secondaryStreamLeft, _secondaryStreamRight);
                    grabStreamsRefs[user_id]      = new Tuple <SyncRef <ValueStream <bool> >, SyncRef <ValueStream <bool> > >(_grabStreamLeft, _grabStreamRight);
                    menuStreamsRefs[user_id]      = new Tuple <SyncRef <ValueStream <bool> >, SyncRef <ValueStream <bool> > >(_menuStreamLeft, _menuStreamRight);
                    strengthStreamsRefs[user_id]  = new Tuple <SyncRef <ValueStream <float> >, SyncRef <ValueStream <float> > >(_strengthStreamLeft, _strengthStreamRight);
                    axisStreamsRefs[user_id]      = new Tuple <SyncRef <ValueStream <float2> >, SyncRef <ValueStream <float2> > >(_axisStreamLeft, _axisStreamRight);
                }
                added_logix = true;
                UniLog.Log("Added logix");
            });
            metagen_comp.StartTask(async() =>
            {
                Task task = Task.Run(() =>
                {
                    bool all_streams_not_null        = false;
                    List <RefID> good_tracking_users = new List <RefID>();

                    //UniLog.Log("HO");
                    while (!all_streams_not_null & currentWorld.TotalUpdates <= currentTotalUpdates + 60)
                    {
                        if (!added_logix)
                        {
                            continue;
                        }
                        //UniLog.Log("HI");
                        bool all_user_streams_not_null = true;
                        all_streams_not_null           = true;
                        foreach (RefID user_id in current_tracked_users)
                        {
                            //HMM: why does using .Target here rather than .RawTarget give a NullReferenceException??
                            bool primary_streams_not_null   = (primaryStreamsRefs[user_id].Item1.RawTarget != null) & (primaryStreamsRefs[user_id].Item2.RawTarget != null);
                            bool secondary_streams_not_null = (secondaryStreamsRefs[user_id].Item1.RawTarget != null) & (secondaryStreamsRefs[user_id].Item2.RawTarget != null);
                            bool grab_streams_not_null      = (grabStreamsRefs[user_id].Item1.RawTarget != null) & (grabStreamsRefs[user_id].Item2.RawTarget != null);
                            bool menu_streams_not_null      = (menuStreamsRefs[user_id].Item1.RawTarget != null) & (menuStreamsRefs[user_id].Item2.RawTarget != null);
                            bool strength_streams_not_null  = (strengthStreamsRefs[user_id].Item1.RawTarget != null) & (strengthStreamsRefs[user_id].Item2.RawTarget != null);
                            bool axis_streams_not_null      = (axisStreamsRefs[user_id].Item1.RawTarget != null) & (axisStreamsRefs[user_id].Item2.RawTarget != null);

                            all_user_streams_not_null = primary_streams_not_null & secondary_streams_not_null & grab_streams_not_null & menu_streams_not_null & strength_streams_not_null & axis_streams_not_null;

                            if (all_user_streams_not_null)
                            {
                                if (!good_tracking_users.Contains(user_id))
                                {
                                    good_tracking_users.Add(user_id);
                                    UniLog.Log("Added user " + user_id.ToString());
                                }
                            }

                            all_streams_not_null &= all_user_streams_not_null;
                        }
                    }

                    current_tracked_users = good_tracking_users;

                    //Get CommonToolStreamDriver
                    List <RefID> good_tracking_users2 = new List <RefID>();
                    foreach (RefID user_id in current_tracked_users)
                    {
                        User user = currentWorld.GetUser(user_id);
                        List <CommonToolStreamDriver> commonToolStreamDrivers = user.Root.Slot.GetComponents <CommonToolStreamDriver>();
                        ValueStream <bool> primaryBlockedStreamLeft           = null;
                        ValueStream <bool> secondaryBlockedStreamLeft         = null;
                        ValueStream <bool> laserActiveStreamLeft        = null;
                        ValueStream <bool> showLaserToOthersStreamLeft  = null;
                        ValueStream <float3> laserTargetStreamLeft      = null;
                        ValueStream <float> grabDistanceStreamLeft      = null;
                        ValueStream <bool> primaryBlockedStreamRight    = null;
                        ValueStream <bool> secondaryBlockedStreamRight  = null;
                        ValueStream <bool> laserActiveStreamRight       = null;
                        ValueStream <bool> showLaserToOthersStreamRight = null;
                        ValueStream <float3> laserTargetStreamRight     = null;
                        ValueStream <float> grabDistanceStreamRight     = null;
                        foreach (CommonToolStreamDriver driver in commonToolStreamDrivers)
                        {
                            if (driver.Side.Value == Chirality.Left)
                            {
                                primaryBlockedStreamLeft    = driver.PrimaryBlockedStream.Target;
                                secondaryBlockedStreamLeft  = driver.SecondaryBlockedStream.Target;
                                laserActiveStreamLeft       = driver.LaserActiveStream.Target;
                                showLaserToOthersStreamLeft = driver.ShowLaserToOthersStream.Target;
                                laserTargetStreamLeft       = driver.LaserTargetStream.Target;
                                grabDistanceStreamLeft      = driver.GrabDistanceStream.Target;
                            }
                            else if (driver.Side.Value == Chirality.Right)
                            {
                                primaryBlockedStreamRight    = driver.PrimaryBlockedStream.Target;
                                secondaryBlockedStreamRight  = driver.SecondaryBlockedStream.Target;
                                laserActiveStreamRight       = driver.LaserActiveStream.Target;
                                showLaserToOthersStreamRight = driver.ShowLaserToOthersStream.Target;
                                laserTargetStreamRight       = driver.LaserTargetStream.Target;
                                grabDistanceStreamRight      = driver.GrabDistanceStream.Target;
                            }
                        }
                        bool all_common_tool_streams_not_null = primaryBlockedStreamLeft != null & primaryBlockedStreamRight != null
                                                                & secondaryBlockedStreamLeft != null & secondaryBlockedStreamRight != null
                                                                & laserActiveStreamLeft != null & laserActiveStreamRight != null
                                                                & showLaserToOthersStreamLeft != null & showLaserToOthersStreamRight != null
                                                                & laserTargetStreamLeft != null & laserActiveStreamRight != null
                                                                & grabDistanceStreamLeft != null & grabDistanceStreamRight != null;
                        if (all_common_tool_streams_not_null)
                        {
                            good_tracking_users2.Add(user_id);
                            primaryBlockedStreams[user_id]    = new Tuple <ValueStream <bool>, ValueStream <bool> >(primaryBlockedStreamLeft, primaryBlockedStreamRight);
                            secondaryBlockedStreams[user_id]  = new Tuple <ValueStream <bool>, ValueStream <bool> >(secondaryBlockedStreamLeft, secondaryBlockedStreamRight);
                            laserActiveStreams[user_id]       = new Tuple <ValueStream <bool>, ValueStream <bool> >(laserActiveStreamLeft, laserActiveStreamRight);
                            showLaserToOthersStreams[user_id] = new Tuple <ValueStream <bool>, ValueStream <bool> >(showLaserToOthersStreamLeft, showLaserToOthersStreamRight);
                            laserTargetStreams[user_id]       = new Tuple <ValueStream <float3>, ValueStream <float3> >(laserTargetStreamLeft, laserTargetStreamRight);
                            grabDistanceStreams[user_id]      = new Tuple <ValueStream <float>, ValueStream <float> >(grabDistanceStreamLeft, grabDistanceStreamRight);
                        }
                    }
                    current_tracked_users = good_tracking_users2;
                    foreach (RefID user_id in current_tracked_users)
                    {
                        primaryStreams[user_id]   = new Tuple <ValueStream <bool>, ValueStream <bool> >(primaryStreamsRefs[user_id].Item1.RawTarget, primaryStreamsRefs[user_id].Item2.RawTarget);
                        secondaryStreams[user_id] = new Tuple <ValueStream <bool>, ValueStream <bool> >(secondaryStreamsRefs[user_id].Item1.RawTarget, secondaryStreamsRefs[user_id].Item2.RawTarget);
                        grabStreams[user_id]      = new Tuple <ValueStream <bool>, ValueStream <bool> >(grabStreamsRefs[user_id].Item1.RawTarget, grabStreamsRefs[user_id].Item2.RawTarget);
                        menuStreams[user_id]      = new Tuple <ValueStream <bool>, ValueStream <bool> >(menuStreamsRefs[user_id].Item1.RawTarget, menuStreamsRefs[user_id].Item2.RawTarget);
                        strengthStreams[user_id]  = new Tuple <ValueStream <float>, ValueStream <float> >(strengthStreamsRefs[user_id].Item1.RawTarget, strengthStreamsRefs[user_id].Item2.RawTarget);
                        axisStreams[user_id]      = new Tuple <ValueStream <float2>, ValueStream <float2> >(axisStreamsRefs[user_id].Item1.RawTarget, axisStreamsRefs[user_id].Item2.RawTarget);
                        RegisterUserStream(user_id, "controller_streams");
                    }
                    //Destroy LogiX nodes
                    currentWorld.RunSynchronously(() =>
                    {
                        logix_slot.Destroy();
                    });

                    isRecording = true;
                });

                //await CancelAfterAsync(ct=>task, TimeSpan.FromSeconds(30), CancellationToken.None);
                await task;
            });
        }
コード例 #2
0
        private void OpenConnectedPanel()
        {
            UIBuilder uiBuilder1 = panel.SwapPanel(NeosSwapCanvasPanel.Slide.None, 0.5f);

            //uiBuilder1.VerticalLayout(4f, 0.0f, new Alignment?());
            uiBuilder1.VerticalLayout(4f, 0, new Alignment?());
            uiBuilder1.FitContent(SizeFit.Disabled, SizeFit.PreferredSize);
            uiBuilder1.Style.PreferredHeight = 65f;
            uiBuilder1.Style.MinHeight       = 32f;
            uiBuilder1.Style.TextAutoSizeMin = 45f;
            uiBuilder1.Style.TextAutoSizeMax = 65f;

            //status text
            //SyncRef<Text> status = this._status;
            //LocaleString localeString1 = (LocaleString)"";
            //ref LocaleString local1 = ref localeString1;
            //Alignment? alignment1 = new Alignment?();
            //Text text1 = uiBuilder1.Text(in local1, true, alignment1, true, (string)null);
            //status.Target = text1;

            //Title
            uiBuilder1.Style.PreferredHeight = 200f;
            Text text4 = uiBuilder1.Text("MetaGenNeos");

            text4.AutoSizeMax.Value = 150f;
            text4.Size.Value        = 150f;

            //Description
            uiBuilder1.Style.MinHeight = 350f;
            Text text1 = uiBuilder1.Text("<b>This recording system is currenlty in Beta. Expect bugs</b>. MetaGen is a project to explore the intersection between AI and VR technologies, for Science, Art, and Wonder. See more details at http://metagen.ai");

            uiBuilder1.Style.MinHeight = 32f;

            ////Recording checkbox
            //uiBuilder1.Style.PreferredHeight = 100f;
            //uiBuilder1.Style.MinHeight = 100f;
            //Checkbox checkbox_record_user = uiBuilder1.Checkbox("Record me (local)",false);
            //this._recordUserCheckbox.Target = checkbox_record_user;
            //if (!mg.admin_mode)
            //{
            //    recordUserOverride = uiBuilder1.Current.AttachComponent<ValueUserOverride<bool>>();
            //    recordUserOverride.CreateOverrideOnWrite.Value = true;
            //    recordUserOverride.Target.Target = checkbox_record_user.State;
            //}

            ////Data submission checkbox
            //uiBuilder1.Style.MinHeight = 350f;
            //Text text2 = uiBuilder1.Text("<b>By checking this box you agree to license the recorded data as CC0 (Public domain), as part of the MetaGen Public Dataset (intended for research in AI and other sciences).</b>");
            //text2.HorizontalAlign.Value = CodeX.TextHorizontalAlignment.Left;
            //uiBuilder1.Style.PreferredHeight = 100f;
            //uiBuilder1.Style.MinHeight = 100f;
            //Checkbox checkbox_public_domain = uiBuilder1.Checkbox("Public domain",false);
            //this._publicDomainCheckbox.Target = checkbox_public_domain;
            //if (!mg.admin_mode)
            //{
            //    publicDomainOverride = uiBuilder1.Current.AttachComponent<ValueUserOverride<bool>>();
            //    publicDomainOverride.Target.Target = checkbox_public_domain.State;
            //}

            //recording time
            uiBuilder1.Style.PreferredHeight = 75f;
            uiBuilder1.Style.MinHeight       = 75f;
            SyncRef <Text> recording_time = this._recordingTime;
            LocaleString   localeString2  = (LocaleString)"";
            Text           text3          = uiBuilder1.Text(localeString2);

            recording_time.Target = text3;

            uiBuilder1.Style.PreferredHeight = 100f;
            uiBuilder1.Style.MinHeight       = 100f;

            //animation checkbox
            Checkbox animCheckbox = uiBuilder1.Checkbox("Generate animation", true);

            this._animationsCheckbox.Target = animCheckbox;

            //Generate bvh checkbox
            Checkbox checkbox5 = uiBuilder1.Checkbox("Generate bvh", false);

            this._generateBvhCheckbox.Target = checkbox5;

            //Recording voices checkbox
            Checkbox recording_voices_checkbox = uiBuilder1.Checkbox("Record voices", true);

            this._recordVoicesCheckbox.Target = recording_voices_checkbox;

#if NOHL
            //Recording hearing checkbox
            Checkbox recording_hearing_checkbox = uiBuilder1.Checkbox("Record hearing", true);
            this._recordHearingCheckbox.Target = recording_hearing_checkbox;
#endif

            //video checkbox
            //Checkbox videoCheckbox = uiBuilder1.Checkbox("Record vision",true);
#if NOHL
            Checkbox videoCheckbox = uiBuilder1.Checkbox("Record vision", false);
            this._videoCheckbox.Target = videoCheckbox;
#endif

            //record button
            uiBuilder1.Style.PreferredHeight = 120f;
            uiBuilder1.Style.MinHeight       = 120f;
            SyncRef <Button> recordButton = this._recordButton;
            Button           button1      = uiBuilder1.Button("");
            recordButton.Target = button1;
            ButtonValueSet <bool> comp1 = button1.Slot.AttachComponent <ButtonValueSet <bool> >();
            comp1.SetValue.Value     = true;
            comp1.TargetValue.Target = record_button_pressed.Target;

            ////Hiding for now as its WIP
            ////interact button
            uiBuilder1.Style.PreferredHeight = 120f;
            uiBuilder1.Style.MinHeight       = 120f;
            SyncRef <Button> interactButton = this._interactButton;
            Button           button1b       = uiBuilder1.Button("Toggle Interaction");
            interactButton.Target = button1b;
            ButtonValueSet <bool> comp1b = button1b.Slot.AttachComponent <ButtonValueSet <bool> >();
            comp1b.SetValue.Value     = true;
            comp1b.TargetValue.Target = interact_button_pressed.Target;

            //Text for debug play section
            uiBuilder1.Style.PreferredHeight = 200f;
            uiBuilder1.Style.MinHeight       = 100f;
            Text text5 = uiBuilder1.Text("Debug play");
            text4.AutoSizeMax.Value          = 130f;
            text4.Size.Value                 = 130f;
            uiBuilder1.Style.MinHeight       = 100f;
            uiBuilder1.Style.PreferredHeight = 100f;

            //Recording index
            uiBuilder1.Style.PreferredHeight = 75f;
            uiBuilder1.Style.MinHeight       = 75f;
            Text      text6  = uiBuilder1.Text("Recording index:");
            TextField field1 = uiBuilder1.TextField("0");
            this._recordIndexField.Target = field1;

            uiBuilder1.Style.MinHeight       = 100f;
            uiBuilder1.Style.PreferredHeight = 100f;

            //Voices checkbox
            Checkbox checkbox1 = uiBuilder1.Checkbox("Voices", true);
            this._voicesCheckbox.Target = checkbox1;

            //Hearing checkbox
            Checkbox checkbox2 = uiBuilder1.Checkbox("Hearing", false);
            this._hearingCheckbox.Target = checkbox2;

            //External source checkpoint
            Checkbox checkbox3 = uiBuilder1.Checkbox("External source", false);
            this._externalSourceCheckbox.Target = checkbox3;

            //animation checkbox2
            Checkbox animCheckbox2 = uiBuilder1.Checkbox("Generate animation", false);
            this._animationsCheckbox2.Target = animCheckbox2;

            //Generate bvh checkbox
            Checkbox bvhCheckbox2 = uiBuilder1.Checkbox("Generate bvh", false);
            this._generateBvhCheckbox2.Target = bvhCheckbox2;

            //Avatar ref
            uiBuilder1.Style.PreferredHeight = 75f;
            uiBuilder1.Style.MinHeight       = 75f;
            Text text7 = uiBuilder1.Text("Avatar slot:");
            uiBuilder1.Next("Root");
            ReferenceField <Slot> refField = uiBuilder1.Current.AttachComponent <ReferenceField <Slot> >();
            this._avatarRefField.Target = refField;
            RefEditor avatarRefEditor = uiBuilder1.Current.AttachComponent <RefEditor>();
            avatarRefEditor.Setup(refField.Reference);

            uiBuilder1.Style.MinHeight       = 100f;
            uiBuilder1.Style.PreferredHeight = 100f;

            //play button
            SyncRef <Button> streamButton = this._playButton;
            Button           button2      = uiBuilder1.Button("");
            streamButton.Target = button2;
            ButtonValueSet <bool> comp2 = button2.Slot.AttachComponent <ButtonValueSet <bool> >();
            comp2.SetValue.Value     = true;
            comp2.TargetValue.Target = play_button_pressed.Target;

            ////UI slot ref
            //uiBuilder1.Style.PreferredHeight = 75f;
            //uiBuilder1.Style.MinHeight = 75f;
            //Text text8 = uiBuilder1.Text("UI slot:");
            //uiBuilder1.Next("Root");
            //ReferenceField<Slot> refField2 = uiBuilder1.Current.AttachComponent<ReferenceField<Slot>>();
            //this._uiTemplateRefField.Target = refField2;
            //RefEditor uiTemplateRefEditor = uiBuilder1.Current.AttachComponent<RefEditor>();
            //uiTemplateRefEditor.Setup(refField2.Reference);

            //uiBuilder1.Style.MinHeight = 100f;
            //uiBuilder1.Style.PreferredHeight = 100f;

            ////swapUI button
            //Button button3 = uiBuilder1.Button("");
            //this._swapUIButton.Target = button3;
            //ButtonValueSet<bool> comp3 = button3.Slot.AttachComponent<ButtonValueSet<bool>>();
            //comp3.SetValue.Value = true;
            //comp3.TargetValue.Target = swapUI_button_pressed.Target;
        }
コード例 #3
0
        private async void StartPlayingInternal()
        {
            try
            {
                if (generateAnimation)
                {
                    metagen_comp.World.RunSynchronously(() =>
                    {
                        animationRecorder = metagen_comp.Slot.AttachComponent <RecordingTool>();
                        animationRecorder.metagen_comp = metagen_comp;
                    });
                }
                //Dictionary<RefID, User>.ValueCollection users = metagen_comp.World.AllUsers;
                avatarManager = new metagen.AvatarManager();
                List <UserMetadata> userMetadatas = new List <UserMetadata>();
                userMetadatas.Add(new UserMetadata {
                    userId = "U-test", bodyNodes = "", devices = "", headDevice = "", isPublic = true, isRecording = true, platform = "", userRefId = "ID2B00"
                });
                Dictionary <RefID, AudioOutput> audio_outputs = new Dictionary <RefID, AudioOutput>();
                foreach (UserMetadata user in userMetadatas)
                {
                    if (!user.isRecording || !user.isPublic)
                    {
                        continue;                                      //at the moment we only allow playing back of public recording, for privacy reasons. In the future, we'll allow private access to the data
                    }
                    RefID user_id = RefID.Parse(user.userRefId);
                    UniLog.Log(user_id.ToString());
                    user_ids.Add(user_id);
                    channel = new Channel("127.0.0.1:" + (40052).ToString(), ChannelCredentials.Insecure);
                    client  = new DataComm.DataCommClient(channel);

                    output_readers[user_id]         = client.GetPose(new Empty()).ResponseStream;
                    fake_proxies[user_id]           = new List <Tuple <BodyNode, AvatarObjectSlot> >();
                    avatar_pose_nodes[user_id]      = new List <Tuple <BodyNode, IAvatarObject> >();
                    avatar_stream_channels[user_id] = new Dictionary <BodyNode, Tuple <bool, bool, bool> >();
                    proxy_slots[user_id]            = new Dictionary <BodyNode, Slot>();
                    if (avatarManager.avatar_template == null && avatar_template != null)
                    {
                        avatarManager.avatar_template = avatar_template;
                    }
                    Slot avatar = await avatarManager.GetAvatar();

                    UniLog.Log("AVATAR");
                    UniLog.Log(avatar.ToString());
                    avatars[user_id] = avatar;
                    List <IAvatarObject>    components = avatar.GetComponentsInChildren <IAvatarObject>();
                    List <AvatarObjectSlot> root_comps = avatar.GetComponentsInChildren <AvatarObjectSlot>();
                    boness[user_id] = avatar.GetComponentInChildren <Rig>()?.Bones.ToList();
                    VRIKAvatar avatarIK = avatar.GetComponentInChildren <VRIKAvatar>();

                    //READ absolute time
                    //output_readers[user_id].ReadSingle();
                    //READ number of body nodes
                    int numBodyNodes = 28; //TODO CHECK
                    for (int i = 0; i < numBodyNodes; i++)
                    {
                        //READ body node type
                        //int nodeInt =
                        //READ if scale stream exists
                        bool scale_exists = true;
                        //READ if position stream exists
                        bool pos_exists = true;
                        //READ if rotation stream exists
                        bool     rot_exists   = true;
                        BodyNode bodyNodeType = VNetcBodyNodeConverter[i];

                        bool node_found = false;
                        foreach (IAvatarObject comp in components)
                        {
                            foreach (AvatarObjectSlot comp2 in root_comps)
                            {
                                if (comp.Node == bodyNodeType && comp2.Node == bodyNodeType)
                                {
                                    UniLog.Log((comp.Node, scale_exists, pos_exists, rot_exists));
                                    if (bodyNodeType == BodyNode.Root)
                                    {
                                        proxy_slots[user_id][bodyNodeType] = avatar;
                                    }
                                    else
                                    {
                                        proxy_slots[user_id][bodyNodeType] = comp.Slot;
                                    }
                                    comp.Equip(comp2);
                                    if (bodyNodeType != BodyNode.Root)
                                    {
                                        SyncRef <Slot> sourceField = (SyncRef <Slot>)comp.GetType().GetField("_source", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(comp);
                                        sourceField.Target = null;
                                        FieldDrive <float3> posField = (FieldDrive <float3>)comp.GetType().GetField("_position", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(comp);
                                        posField.Target = null;
                                        FieldDrive <floatQ> rotField = (FieldDrive <floatQ>)comp.GetType().GetField("_rotation", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(comp);
                                        rotField.Target = null;
                                    }
                                    fake_proxies[user_id].Add(new Tuple <BodyNode, AvatarObjectSlot>(bodyNodeType, comp2));
                                    avatar_pose_nodes[user_id].Add(new Tuple <BodyNode, IAvatarObject>(comp.Node, comp));
                                    comp2.IsTracking.Value = true;
                                    if (bodyNodeType == BodyNode.LeftFoot || bodyNodeType == BodyNode.RightFoot)
                                    {
                                        avatarIK.ForceUseFeetProxies.Value = true;
                                    }
                                    if (bodyNodeType == BodyNode.LeftLowerLeg || bodyNodeType == BodyNode.RightLowerLeg)
                                    {
                                        avatarIK.ForceUseKneeProxies.Value = true;
                                    }
                                    if (bodyNodeType == BodyNode.LeftLowerArm || bodyNodeType == BodyNode.RightLowerArm)
                                    {
                                        avatarIK.ForceUseElbowProxies.Value = true;
                                    }
                                    if (bodyNodeType == BodyNode.Chest)
                                    {
                                        avatarIK.ForceUseChestProxy.Value = true;
                                    }
                                    if (bodyNodeType == BodyNode.Hips)
                                    {
                                        avatarIK.ForceUsePelvisProxy.Value = true;
                                    }
                                    node_found = true;
                                    break;
                                }
                                if (node_found)
                                {
                                    break;
                                }
                            }
                        }
                        //if (!node_found) throw new Exception("Node " + bodyNodeType.ToString() + " not found in avatar!");
                        if (!node_found)
                        {
                            fake_proxies[user_id].Add(new Tuple <BodyNode, AvatarObjectSlot>(bodyNodeType, null));
                            avatar_pose_nodes[user_id].Add(new Tuple <BodyNode, IAvatarObject>(bodyNodeType, null));
                        }
                        avatar_stream_channels[user_id][bodyNodeType] = new Tuple <bool, bool, bool>(scale_exists, pos_exists, rot_exists);
                    }
                    Slot avatarRootSlot = avatar.GetComponentInChildren <AvatarRoot>()?.Slot;
                    if (avatarRootSlot != null)
                    {
                        avatarRootSlot.LocalPosition = new float3(0, 0, 0);
                        avatarRootSlot.LocalRotation = new floatQ(0, 0, 0, 1);
                    }
                    //READ whether hands are being tracked
                    hands_are_tracked[user_id] = false;
                    //READ whether metacarpals are being tracked
                    //output_readers[user_id].ReadBoolean();

                    List <HandPoser> these_hand_posers = avatar.GetComponentsInChildren <HandPoser>(null, excludeDisabled: false, includeLocal: false);
                    UniLog.Log("getting finger rotation vars");
                    finger_slots[user_id]         = new Dictionary <BodyNode, Slot>();
                    hand_posers[user_id]          = new Dictionary <Chirality, HandPoser>();
                    finger_compensations[user_id] = new Dictionary <BodyNode, floatQ>();
                    foreach (HandPoser hand_poser in these_hand_posers)
                    {
                        UniLog.Log("HI");
                        hand_posers[user_id][hand_poser.Side] = hand_poser;
                        BodyNode side1 = BodyNode.LeftThumb_Metacarpal.GetSide((Chirality)hand_poser.Side);
                        BodyNode side2 = BodyNode.LeftPinky_Tip.GetSide((Chirality)hand_poser.Side);
                        for (BodyNode nodee = side1; nodee <= side2; ++nodee)
                        {
                            int                     index             = nodee - side1;
                            FingerType              fingerType        = nodee.GetFingerType();
                            FingerSegmentType       fingerSegmentType = nodee.GetFingerSegmentType();
                            HandPoser.FingerSegment fingerSegment     = hand_poser[fingerType][fingerSegmentType];
                            if (fingerSegment != null && fingerSegment.Root.Target != null)//&& fingerSegment.RotationDrive.IsLinkValid)
                            {
                                UniLog.Log(nodee.ToString());
                                finger_slots[user_id][nodee]         = fingerSegment.Root.Target;
                                proxy_slots[user_id][nodee]          = fingerSegment.Root.Target;
                                finger_compensations[user_id][nodee] = fingerSegment.CoordinateCompensation.Value;
                                fingerSegment.RotationDrive.Target   = (IField <floatQ>)null;
                            }
                        }
                    }
                    UniLog.Log("got finger rotation vars");
                    //AUDIO PLAY
                    audio_outputs[user_id] = null;
                    //UniLog.Log("Setting up audio!");
                    //avatar.GetComponentInChildren<AudioOutput>().Source.Target = null;
                    //for (int i = 0; i < 2; i++)
                    //{
                    //    string audio_file;
                    //    if (i==0)
                    //    {
                    //        if (!play_hearing) continue;
                    //        string[] files = Directory.GetFiles(reading_directory, user_id.ToString() + "*_hearing.ogg");
                    //        audio_file = files.Length > 0 ? files[0] : null;
                    //    } else
                    //    {
                    //        if (!play_voice) continue;
                    //        string[] files = Directory.GetFiles(reading_directory, user_id.ToString() + "*_voice.ogg");
                    //        audio_file = files.Length > 0 ? files[0] : null;
                    //    }
                    //    if (File.Exists(audio_file))
                    //    {
                    //        AudioOutput audio_output = avatar.GetComponentInChildren<AudioOutput>();
                    //        if (audio_output.Source.Target != null) audio_output = audio_output.Slot.AttachComponent<AudioOutput>();
                    //        VisemeAnalyzer visemeAnalyzer = avatar.GetComponentInChildren<VisemeAnalyzer>();
                    //        audio_output.Volume.Value = 1f;
                    //        audio_output.Enabled = true;
                    //        //audio_outputs[user_id] = audio_output;
                    //        //AudioX audioData = new AudioX(reading_directory + "/" + user_id.ToString() + "_audio.wav");
                    //        //AssetRef<AudioClip> audioClip = new AssetRef<AudioClip>();
                    //        Uri uri = this.World.Engine.LocalDB.ImportLocalAsset(audio_file, LocalDB.ImportLocation.Original, (string)null);
                    //        //ToWorld thing = new ToWorld();
                    //        //var awaiter = thing.GetAwaiter();
                    //        //awaiter.GetResult();
                    //        StaticAudioClip audioClip = audio_output.Slot.AttachAudioClip(uri);
                    //        AudioClipPlayer player = audio_output.Slot.AttachComponent<AudioClipPlayer>();
                    //        if (visemeAnalyzer != null)
                    //        {
                    //            visemeAnalyzer.Source.Target = player;
                    //        }
                    //        UniLog.Log("attaching clip to player");
                    //        player.Clip.Target = (IAssetProvider<AudioClip>) audioClip;
                    //        UniLog.Log("attaching player to audio output");
                    //        audio_output.Source.Target = (IAudioSource) player;
                    //        audio_output.Slot.AttachComponent<AudioMetadata>(true, (Action<AudioMetadata>)null).SetFromCurrentWorld();
                    //        player.Play();
                    //    }
                    //}
                }
                avatars_finished_loading = true;
                isPlaying = true;
                if (generateAnimation)
                {
                    animationRecorder.StartRecordingAvatars(avatars, audio_outputs);
                }
                if (generateBvh)
                {
                    bvhRecorder.StartRecordingAvatars(avatars);
                }
            }
            catch (Exception e)
            {
                UniLog.Log("TwT: " + e.Message);
                UniLog.Log(e.StackTrace);
            }
        }