Example #1
0
        /// <summary>
        /// Please define 'bind'. I think it means.. fields are bound to other things
        /// </summary>
        protected virtual void BindManifest(ContentManifestEntry manifest)
        {
            //TODO: consider: prevent from being bound more than once. That's just illegal.
            //just keep a bool for that purpose? What a waste.
            //What if the binding is just so internal to the engine that it's not possible for a user to do it more than once?
            //That would be preferred

            var myType = GetType();

            attributes = manifest.Attributes;

            //bind all children
            if (manifest.Children != null)
            {
                foreach (var child in manifest.Children)
                {
                    var name = child.Name;

                    //even though the manifest may have come from reflection...
                    //it also may NOT have. so we need to reflect again in order to do the binding
                    var fieldInfo = myType.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

                    //check the current value. if it's null, we need to instantiate a proxy
                    var o = fieldInfo.GetValue(this);
                    if (o == null)
                    {
                        o = CreateBoundContentProxy(fieldInfo.FieldType, name, child);
                        fieldInfo.SetValue(this, o);
                    }

                    //bind this child
                    var childContentField = o as ContentBase;
                    if (childContentField == null)
                    {
                        //if it isn't content, then it is a subcontent holder
                        //but what to do about that? we need to set its members
                        //our old concept was to automatically create directories here. but that's actually inappropriate..
                        //if the holder were also a directory, we would automatically do it..
                        //--although I would need to make sure directories hosted on other things work
                        //and really, that's pretty bad
                        //maybe I need a special process here that goes off into the great beyond filling in unknown types...
                        //but.. uh.. it could be pretty cool to have these be directories. maybe lets try it and see how it goes.
                        //or maybe a new type that can enumerate its members
                    }
                    else
                    {
                        childContentField.BindManifest(child);
                    }
                }
            }
        }
Example #2
0
        /// <summary>
        /// Creates a content proxy which is.. 'bound'.. to a field?
        /// That's the intent, but it looks like the different logic in here isn't directly related to that.
        /// It should be possible to do oven stuff without... man, I dont know
        /// </summary>
        protected virtual ContentBase CreateBoundContentProxy(Type type, string name, ContentManifestEntry manifestEntry)
        {
            //manifestEntry has to come in so we can use it during creating content.. yeah.. i should have thought of that.
            //I need to clean that up

            ContentBase content = CreateContentProxy(type, name);

            content.attributes = manifestEntry.Attributes;

            //if we're bruted, just create the baked loader and move on

#if !BRUTED
            //try getting the pipeline we'd use to bake this content. If there's such a pipeline, set us up to use it
            var pipeline = Manager.PipelineConnector.GetPipeline(content);

            if (pipeline != null)
            {
                //TODO - I had intended a 1:1 correspondence of loaders to content instances, but maybe I can have the loaders have the required name and directory context? I think it should be possible
                content._loader = new Loaders.ProtoLoader(content)
                {
                    directoryOwner = this as ContentDirectory,                     //I guess we know this is true
                    name           = name
                };
                return(content);
            }
#endif

            //if we weren't able to setup the proto loader, we can still load it baked
            //this probably doesnt make any sense in a Proto target..
            //maybe it makes sense for binary content not managed by a content type really?
            //but we should probably have some setup that copies it over, anyway
            //else, a ProtoSlimLoader which loads it straight from the content directory.
            //not sure yet. anyway, this is harmless.
            content._loader = new Loaders.BakedLoader(content)
            {
                directoryOwner = this as ContentDirectory,                 //I guess we know this is true
                name           = name
            };

            return(content);
        }
        protected override ContentBase CreateBoundContentProxy(Type type, string name, ContentManifestEntry manifestEntry)
        {
            //special handling for directories--we need to create subdirectories specially
            //EDIT: do we really? can't it get dealt with, like, by tracking the directory owner, and pulling information from that?
            var content = base.CreateBoundContentProxy(type, name, manifestEntry);


            if (typeof(ContentDirectory).IsAssignableFrom(type))
            {
                var newSubdir = (ContentDirectory)content;
                newSubdir.RawContentDiskRoot   = System.IO.Path.Combine(RawContentDiskRoot, name);
                newSubdir.BakedContentDiskRoot = System.IO.Path.Combine(BakedContentDiskRoot, name);

                //special handling:
                var backendSubdirAttrib = content.Attributes.GetAttribute <BackendSubdirectory>();
                if (backendSubdirAttrib != null)
                {
                    newSubdir.RawContentDiskRoot   = System.IO.Path.Combine(newSubdir.RawContentDiskRoot, Manager.SelectedBackend.ToString());
                    newSubdir.BakedContentDiskRoot = System.IO.Path.Combine(newSubdir.BakedContentDiskRoot, Manager.SelectedBackend.ToString());
                }


                newSubdir.LogicalPath = $"{LogicalPath}/{name}";

                //it's responsible for loading itself.. kind of weird..
                //that's different from other content (which is concretely realized on the filesystem)
                newSubdir._loader = newSubdir;
            }

            //we need to track all the content we create, that's one of the purposes of a directory
            childContent[name] = content;

            return(content);
        }
        static ContentManifestEntry _Reflect(Type targetType, bool inContent)
        {
            bool iAmDirectory = targetType.IsSubclassOf(typeof(ContentDirectory));

            ContentManifestEntry ret = new ContentManifestEntry()
            {
                Children = new List <ContentManifestEntry>()
            };

            foreach (var fi in targetType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
            {
                var  fieldType          = fi.FieldType;
                bool isContentType      = fieldType.IsSubclassOf(typeof(ContentBase));
                bool isContentDirectory = fieldType.IsSubclassOf(typeof(ContentDirectory));
                bool isSubcontentHolder = fi.GetCustomAttributes <SubcontentAttribute>().Any();

                if (isContentDirectory)
                {
                    var entry = _Reflect(fi.FieldType, inContent);
                    entry.Name       = fi.Name;
                    entry.Attributes = fi.GetCustomAttributes(false);                     //warning: this may affect how the directory is interpreted, so maybe it should do this
                    ret.Children.Add(entry);
                }
                else if (isContentType)
                {
                    //content can have subcontent holders, so we need to recurse into that
                    var entry = _Reflect(fieldType, true);
                    entry.Name       = fi.Name;
                    entry.Attributes = fi.GetCustomAttributes(false);
                    ret.Children.Add(entry);
                }
                else if (isSubcontentHolder)
                {
                    //subcontent must be under content; moreover it must be legal for that content type (todo)
                    if (!inContent)
                    {
                        throw new Exception("Structural error: subcontent outside of content");                         //todo: just make an informative log message
                        //continue;
                    }

                    var entry = _Reflect(fieldType, true);
                    entry.Name       = fi.Name;
                    entry.Attributes = fi.GetCustomAttributes(false);
                    ret.Children.Add(entry);
                }
                else
                {
                    if (inContent)
                    {
                    }
                    else if (iAmDirectory)
                    {
                    }
                    else
                    {
                        throw new Exception("Non-content found in content manifest type");
                    }
                }
            }

            return(ret);
        }
 internal void DoBindManifest(ContentManifestEntry manifest)
 {
     BindManifest(manifest);
 }