]> git.draconx.ca Git - upkg.git/commitdiff
uobject: Initial support for object imports.
authorNick Bowler <nbowler@draconx.ca>
Sat, 19 May 2012 17:40:03 +0000 (13:40 -0400)
committerNick Bowler <nbowler@draconx.ca>
Sat, 19 May 2012 17:40:03 +0000 (13:40 -0400)
This is missing a lot of features currently; in particular, imports will
get loaded multiple times, but we can at least resolve them and create
the relevant objects.

Add a DetailTexture property to Engine.Texture to demonstrate.

src/engine/texture.gob
src/uobject/uobject.c

index 8e7bb4a54dc5be0fb93009bcf8f6486c7fc188a7..ea5e2665a869ecd80c8bad718834fe1722160d41 100644 (file)
@@ -118,6 +118,7 @@ class Engine:Texture from U:Object (dynamic)
        private unsigned VBits;
 
        private Engine:Palette *Palette;
        private unsigned VBits;
 
        private Engine:Palette *Palette;
+       private Engine:Texture *DetailTexture;
 
        private struct engine_texture_data **mipmap_data;
        private unsigned char mipmap_count;
 
        private struct engine_texture_data **mipmap_data;
        private unsigned char mipmap_count;
@@ -275,4 +276,11 @@ class Engine:Texture from U:Object (dynamic)
                , object_type = Engine:Palette
                , link
                );
                , object_type = Engine:Palette
                , link
                );
+
+       property OBJECT DetailTexture
+               ( nick = "Detail Texture"
+               , blurb = "Reference to the corresponding detail texture."
+               , object_type = Engine:Texture
+               , link
+               );
 }
 }
index b8c24796dafd601c7669482c0d78338f6ffd317f..74734dd1bfd0c73758fe73698c66b66aca0ff292 100644 (file)
@@ -190,6 +190,93 @@ decode_prop_header(struct upkg *upkg, struct prop_head *head,
        return len;
 }
 
        return len;
 }
 
+/*
+ * TODO: Make this use the uobject_module stuff so packages are not loaded
+ * more than once.
+ */
+static GTypeModule *
+open_import_package(UObject *uo, const struct upkg_import *i)
+{
+       GTypeModule *pkg;
+
+       assert(i->parent == NULL);
+
+       if (strcmp(i->class_package, "Core") != 0
+           || strcmp(i->class_name, "Package") != 0) {
+               u_err(uo, "import root must be Core.Package");
+               return NULL;
+       }
+
+       pkg = u_pkg_open(i->name);
+       if (!pkg || !g_type_module_use(pkg)) {
+               u_err(uo, "failed to open package: %s", i->name);
+               return NULL;
+       }
+
+       if (!U_PKG(pkg)->pkg) {
+               g_type_module_unuse(pkg);
+               u_err(uo, "failed to open package: %s", pkg->name);
+               return NULL;
+       }
+
+       return pkg;
+}
+
+/* Find the export index of a package based on the import chain from another
+ * package.  Returns the (non-negative) offset on success, or a negative value
+ * on failure. */
+static long resolve_import(struct upkg *pkg, const struct upkg_import *import)
+{
+       long current, index;
+
+       if (!import->parent)
+               return -1;
+
+       current = resolve_import(pkg, import->parent);
+       if (current != -1 && current >= 0)
+               return -42;
+
+       index = upkg_export_find(pkg, current, import->name);
+       if (index < 0)
+               return -42;
+
+       return index;
+}
+
+static GObject *get_import_object(UObject *uo, unsigned long index)
+{
+       const struct upkg_import *import;
+       GObject *obj = NULL;
+       GTypeModule *pkg;
+       long obj_index;
+
+       import = upkg_get_import(uo->pkg_file->pkg, index);
+       if (!import) {
+               u_err(uo, "invalid package import: %ld", index);
+               return NULL;
+       }
+
+       /* Get the package name at the top of the hierarchy. */
+       for (const struct upkg_import *i = import; i; i = i->parent) {
+               if (i->parent == NULL) {
+                       pkg = open_import_package(uo, i);
+                       if (!pkg)
+                               return NULL;
+               }
+       }
+
+       obj_index = resolve_import(U_PKG(pkg)->pkg, import);
+       if (obj_index < 0) {
+               u_err(uo, "could not find import in package: %s", pkg->name);
+               goto out;
+       }
+
+       obj = u_object_new_from_package(pkg, obj_index);
+out:
+       g_type_module_unuse(pkg);
+       return obj;
+}
+
 static int decode_object_property(UObject *uo, GValue *val, unsigned long len)
 {
        struct u_object_priv *priv = U_OBJECT_GET_PRIV(uo);
 static int decode_object_property(UObject *uo, GValue *val, unsigned long len)
 {
        struct u_object_priv *priv = U_OBJECT_GET_PRIV(uo);
@@ -202,7 +289,7 @@ static int decode_object_property(UObject *uo, GValue *val, unsigned long len)
                return -1;
 
        if (index < 0) {
                return -1;
 
        if (index < 0) {
-               fprintf(stderr, "Imports not supported yet.\n");
+               obj = get_import_object(uo, -(index+1));
        } else {
                obj = u_object_new_from_package(uo->pkg, index-1);
        }
        } else {
                obj = u_object_new_from_package(uo->pkg, index-1);
        }
@@ -392,7 +479,6 @@ GObject *u_object_new_from_package(GTypeModule *pkg, unsigned long idx)
 {
        g_return_val_if_fail(IS_U_PKG(pkg), NULL);
 
 {
        g_return_val_if_fail(IS_U_PKG(pkg), NULL);
 
-       const struct upkg_export *export;
        const char *class, *package;
        GObject *obj = NULL;
        GType type;
        const char *class, *package;
        GObject *obj = NULL;
        GType type;