void KeyframeAnim::loadText(TextSplitter &ts) { ts.expectString("section: header"); ts.scanString("flags %x", 1, &_flags); ts.scanString("type %x", 1, &_type); ts.scanString("frames %d", 1, &_numFrames); ts.scanString("fps %f", 1, &_fps); ts.scanString("joints %d", 1, &_numJoints); if (scumm_stricmp(ts.getCurrentLine(), "section: markers") == 0) { ts.nextLine(); ts.scanString("markers %d", 1, &_numMarkers); _markers = new Marker[_numMarkers]; for (int i = 0; i < _numMarkers; i++) ts.scanString("%f %d", 2, &_markers[i].frame, &_markers[i].val); } else { _numMarkers = 0; _markers = NULL; } ts.expectString("section: keyframe nodes"); int numNodes; ts.scanString("nodes %d", 1, &numNodes); _nodes = new KeyframeNode *[_numJoints]; for (int i = 0; i < _numJoints; i++) _nodes[i] = NULL; for (int i = 0; i < numNodes; i++) { int which; ts.scanString("node %d", 1, &which); _nodes[which] = new KeyframeNode; _nodes[which]->loadText(ts); } }
void Light::load(TextSplitter &ts) { char buf[256]; // Light names can be null, but ts doesn't seem flexible enough to allow this if (strlen(ts.getCurrentLine()) > strlen(" light")) ts.scanString(" light %256s", 1, buf); else { ts.nextLine(); strcpy(buf, ""); } _name = buf; ts.scanString(" type %256s", 1, buf); _type = buf; ts.scanString(" position %f %f %f", 3, &_pos.x(), &_pos.y(), &_pos.z()); ts.scanString(" direction %f %f %f", 3, &_dir.x(), &_dir.y(), &_dir.z()); ts.scanString(" intensity %f", 1, &_intensity); ts.scanString(" umbraangle %f", 1, &_umbraangle); ts.scanString(" penumbraangle %f", 1, &_penumbraangle); int r, g, b; ts.scanString(" color %d %d %d", 3, &r, &g, &b); _color.getRed() = r; _color.getGreen() = g; _color.getBlue() = b; _enabled = true; }
void Sector::load(TextSplitter &ts) { char buf[256]; int ident = 0, i = 0; Math::Vector3d tempVert; // Sector NAMES can be null, but ts isn't flexible enough if (strlen(ts.getCurrentLine()) > strlen(" sector")) ts.scanString(" sector %256s", 1, buf); else { ts.nextLine(); strcpy(buf, ""); } ts.scanString(" id %d", 1, &ident); _name = buf; _id = ident; ts.scanString(" type %256s", 1, buf); if (strstr(buf, "walk")) _type = WalkType; else if (strstr(buf, "funnel")) _type = FunnelType; else if (strstr(buf, "camera")) _type = CameraType; else if (strstr(buf, "special")) _type = SpecialType; else if (strstr(buf, "chernobyl")) _type = HotType; else Debug::error(Debug::Sets, "Unknown sector type '%s' in room setup", buf); ts.scanString(" default visibility %256s", 1, buf); if (strcmp(buf, "visible") == 0) _visible = true; else if (strcmp(buf, "invisible") == 0) _visible = false; else error("Invalid visibility spec: %s", buf); ts.scanString(" height %f", 1, &_height); ts.scanString(" numvertices %d", 1, &_numVertices); _vertices = new Math::Vector3d[_numVertices + 1]; ts.scanString(" vertices: %f %f %f", 3, &_vertices[0].x(), &_vertices[0].y(), &_vertices[0].z()); for (i = 1; i < _numVertices; i++) ts.scanString(" %f %f %f", 3, &_vertices[i].x(), &_vertices[i].y(), &_vertices[i].z()); // Repeat the last vertex for convenience _vertices[_numVertices] = _vertices[0]; _normal = Math::Vector3d::crossProduct(_vertices[1] - _vertices[0], _vertices[_numVertices - 1] - _vertices[0]); float length = _normal.getMagnitude(); if (length > 0) _normal /= length; }
void Costume::loadGRIM(TextSplitter &ts, Costume *prevCost) { ts.expectString("costume v0.1"); ts.expectString("section tags"); int numTags; ts.scanString(" numtags %d", 1, &numTags); tag32 *tags = new tag32[numTags]; for (int i = 0; i < numTags; i++) { unsigned char t[4]; int which; // Obtain a tag ID from the file ts.scanString(" %d '%c%c%c%c'", 5, &which, &t[0], &t[1], &t[2], &t[3]); // Force characters to upper case for (int j = 0; j < 4; j++) t[j] = toupper(t[j]); memcpy(&tags[which], t, sizeof(tag32)); } ts.expectString("section components"); ts.scanString(" numcomponents %d", 1, &_numComponents); _components = new Component *[_numComponents]; for (int i = 0; i < _numComponents; i++) { int id, tagID, hash, parentID, namePos; const char *line = ts.getCurrentLine(); Component *prevComponent = NULL; if (sscanf(line, " %d %d %d %d %n", &id, &tagID, &hash, &parentID, &namePos) < 4) error("Bad component specification line: `%s'", line); ts.nextLine(); // A Parent ID of "-1" indicates that the component should // use the properties of the previous costume as a base if (parentID == -1) { if (prevCost) { MainModelComponent *mmc; // However, only the first item can actually share the // node hierarchy with the previous costume, so flag // that component so it knows what to do if (i == 0) parentID = -2; prevComponent = prevCost->_components[0]; mmc = dynamic_cast<MainModelComponent *>(prevComponent); // Make sure that the component is valid if (!mmc) prevComponent = NULL; } else if (id > 0) { // Use the MainModelComponent of this costume as prevComponent, // so that the component can use its colormap. prevComponent = _components[0]; } } // Actually load the appropriate component _components[id] = loadComponent(tags[tagID], parentID < 0 ? NULL : _components[parentID], parentID, line + namePos, prevComponent); _components[id]->setCostume(this); } delete[] tags; for (int i = 0; i < _numComponents; i++) if (_components[i]) { _components[i]->init(); } ts.expectString("section chores"); ts.scanString(" numchores %d", 1, &_numChores); _chores = new Chore[_numChores]; for (int i = 0; i < _numChores; i++) { int id, length, tracks; char name[32]; ts.scanString(" %d %d %d %32s", 4, &id, &length, &tracks, name); _chores[id]._length = length; _chores[id]._numTracks = tracks; memcpy(_chores[id]._name, name, 32); Debug::debug(Debug::Chores, "Loaded chore: %s\n", name); } ts.expectString("section keys"); for (int i = 0; i < _numChores; i++) { int which; ts.scanString("chore %d", 1, &which); _chores[which].load(i, this, ts); } }