public void GenerateCacheData(SignalProcessor localProcessor, OutputEventListener l)
 {
     cache = new SignalDataCache(localProcessor, l);
 }
        private void DrawOutput(ref OutputFunc output)
        {
            int toRemove = -1;
            for (int i = 0; i < output.Listeners.Count; ++i) {
                string cacheKey = processor.name + output.Listeners[i].targetProcessorName;
                SignalDataCache data = null;
                if (!dataCache.Has(cacheKey)) {
                    data = new SignalDataCache(processor, output.Listeners[i]);
                    dataCache.Add(cacheKey, data);
                }
                else {
                    data = dataCache.Get(cacheKey);
                    if (data.GetComponentList() == null || data.GetComponentList().Length == 0) {
                        // stale data through scene switches and such. rebuild.
                        Debug.Log("Rebuilding cached data for " + cacheKey);
                        dataCache.Remove(cacheKey);
                        data = new SignalDataCache(processor, output.Listeners[i]);
                        dataCache.Add(cacheKey, data);
                    }
                }

                dataCache.PutBack(cacheKey); // cause if not, next time we get a null back. Should think about not using the InUse stuff
                EditorGUILayout.BeginHorizontal();
                {
                    EditorGUILayout.LabelField(output.Name, GUILayout.Width(listFieldSize));
                    // Target processors
                    string oldTarget = output.Listeners[i].targetProcessorName;
                    string newTarget = EditorGUILayout.TextField(oldTarget, GUILayout.Width(listFieldSize));
                    if (oldTarget != newTarget) {
                        dataCache.Remove(cacheKey); // uncache junk.
                        output.Listeners[i].targetProcessorName = newTarget; // will be re-cached and processed next time
                        Debug.Log("Target changed!");
                        return;
                    }
                    if (data == null) {
                        EditorGUILayout.LabelField("Target is null", GUILayout.Width(listFieldSize));
                        EditorGUILayout.LabelField("No parameter on null target", GUILayout.Width(listFieldSize));
                        EditorGUILayout.LabelField("No delay on null target", GUILayout.Width(listFieldSize));
                    }
                    else if (data.GetComponentList() == null || data.GetComponentList().Length == 0) {
                        // That means we need to rebuild it since it's all empty!
                        EditorGUILayout.LabelField("No input data on target", GUILayout.Width(listFieldSize));
                        EditorGUILayout.LabelField("No parameter on input", GUILayout.Width(listFieldSize));
                        EditorGUILayout.LabelField("No target, no delay", GUILayout.Width(listFieldSize));
                    }
                    else if (output.Listeners[i] == null) {
                        EditorGUILayout.LabelField("No output listeners target", GUILayout.Width(listFieldSize));
                        EditorGUILayout.LabelField("No parameter on input", GUILayout.Width(listFieldSize));
                        EditorGUILayout.LabelField("No target, no delay", GUILayout.Width(listFieldSize));
                    }
                    else {
                        // Select which input. needs 2 dropdowns because of component selection.

                        // Input on processors: Component selection
                        int componentIndex = EditorGUILayout.Popup(data.GetComponentIndex(output.Listeners[i].component), data.GetComponentList(), GUILayout.Width(listFieldSize / 2.05f));
                        string componentName = data.GetComponentName(componentIndex);
                        if (componentName != output.Listeners[i].component) {
                            output.Listeners[i].component = componentName;
                            var inMethods = data.GetInputList(componentName);
                            if (inMethods == null || inMethods.Length == 0) {
                                output.Listeners[i].method = null; // Reset method, the old one will very likely not apply anymore
                            }
                            else {
                                output.Listeners[i].method = inMethods[0]; // Take first we know
                            }
                        }

                        if (string.IsNullOrEmpty(componentName)) {
                            EditorGUILayout.LabelField("Invalid component", GUILayout.Width(listFieldSize));
                        }
                        else {
                            // Input on processors: Input Method selection
                            var currentIndex = (output.Listeners[i].method != null ? data.GetInputIndex(componentName, output.Listeners[i].method) : 0);
                            int inputIndex = EditorGUILayout.Popup(currentIndex, data.GetInputList(componentName), GUILayout.Width(listFieldSize / 2.05f));
                            string inputName = data.GetInputName(componentName, inputIndex);
                            if (inputName != output.Listeners[i].method) {
                                output.Listeners[i].method = inputName;
                            }

                            if (output.Listeners[i].HasParameter(componentName)) {
                                output.Listeners[i].param = EditorGUILayout.TextField(output.Listeners[i].param, GUILayout.Width(listFieldSize));
                            }
                            else {
                                EditorGUILayout.LabelField("No parameter on input", GUILayout.Width(listFieldSize));
                            }
                            output.Listeners[i].delay = EditorGUILayout.FloatField(output.Listeners[i].delay, GUILayout.Width(listFieldSize));
                        }
                    }

                    if (GUILayout.Button("X", GUILayout.Width(listFieldSize))) {
                        // Schedule listener for removal
                        toRemove = i;
                    }
                }
                EditorGUILayout.EndHorizontal();

                if (toRemove >= 0) {
                    output.DetachAtIndex(i);
                    toRemove = -1;
                }
            }
        }