Allow variants to be defined in external files. Fixes #3286
This was SVN commit r18054.
This commit is contained in:
parent
5d8e5edbfb
commit
1e6c12de7b
@ -9,6 +9,7 @@ element actor {
|
||||
element group {
|
||||
element variant {
|
||||
attribute name { text }? &
|
||||
attribute file { text }? &
|
||||
attribute frequency { xsd:nonNegativeInteger }? &
|
||||
element mesh {
|
||||
text
|
||||
|
@ -18,6 +18,9 @@
|
||||
<optional>
|
||||
<attribute name="name"/>
|
||||
</optional>
|
||||
<optional>
|
||||
<attribute name="file"/>
|
||||
</optional>
|
||||
<optional>
|
||||
<attribute name="frequency">
|
||||
<data type="nonNegativeInteger"/>
|
||||
|
@ -6,9 +6,6 @@
|
||||
<animations>
|
||||
<animation file="biped/inf_sword_ready_a.dae" name="Idle" speed="100"/>
|
||||
<animation file="biped/inf_sword_ready_a.dae" name="Idle" speed="97"/>
|
||||
<animation event="0.4" file="infantry/sword/attack/isw_s_def_01.psa" name="attack_capture" speed="100"/>
|
||||
<animation event="0.4" file="infantry/sword/attack/isw_s_def_06.psa" name="attack_capture" speed="100"/>
|
||||
<animation event="0.2" file="infantry/sword/attack/isw_s_em_04.psa" name="attack_capture" speed="100"/>
|
||||
<animation event="0.5" file="infantry/sword/attack/isw_s_off_05.psa" name="attack_slaughter" speed="100"/>
|
||||
<animation event="0.84" file="biped/inf_arch_atk_a.psa" load="0.16" name="attack_ranged" speed="90"/>
|
||||
<animation file="infantry/general/dude/dudewalk.psa" name="Walk" speed="100"/>
|
||||
@ -44,11 +41,7 @@
|
||||
</group>
|
||||
<group>
|
||||
<variant frequency="100" name="Idle"/>
|
||||
<variant name="attack_capture">
|
||||
<props>
|
||||
<prop actor="props/units/tools/pitchfork.xml" attachpoint="r_hand"/>
|
||||
</props>
|
||||
</variant>
|
||||
<variant file="biped/attack_capture.xml"/>
|
||||
<variant name="attack_ranged">
|
||||
<props>
|
||||
<prop actor="props/units/weapons/bow_short.xml" attachpoint="l_hand"/>
|
||||
|
@ -5,9 +5,6 @@
|
||||
<variant frequency="100" name="Base">
|
||||
<animations>
|
||||
<animation file="infantry/general/dude/dudeidle.psa" name="Idle" speed="100"/>
|
||||
<animation event="0.4" file="infantry/sword/attack/isw_s_def_01.psa" name="attack_capture" speed="100"/>
|
||||
<animation event="0.4" file="infantry/sword/attack/isw_s_def_06.psa" name="attack_capture" speed="100"/>
|
||||
<animation event="0.2" file="infantry/sword/attack/isw_s_em_04.psa" name="attack_capture" speed="100"/>
|
||||
<animation event="0.5" file="infantry/javelin/attack/ijv_off_01.psa" load="0" name="attack_ranged" speed="75"/>
|
||||
<animation event="0.5" file="infantry/sword/attack/isw_s_off_05.psa" name="attack_slaughter" speed="100"/>
|
||||
<animation file="biped/walk_spearshield.psa" name="Walk" speed="120"/>
|
||||
@ -48,11 +45,7 @@
|
||||
</group>
|
||||
<group>
|
||||
<variant frequency="100" name="Idle"/>
|
||||
<variant name="attack_capture">
|
||||
<props>
|
||||
<prop actor="props/units/tools/pitchfork.xml" attachpoint="r_hand"/>
|
||||
</props>
|
||||
</variant>
|
||||
<variant file="biped/attack_capture.xml"/>
|
||||
<variant name="attack_ranged">
|
||||
<props>
|
||||
<prop attachpoint="r_hand"/>
|
||||
|
@ -11,9 +11,6 @@
|
||||
<animation file="biped/walk_spearshield.psa" name="carry_wood" speed="120"/>
|
||||
<animation file="biped/walk_spearshield.psa" name="carry_stone" speed="120"/>
|
||||
<animation file="biped/walk_spearshield.psa" name="carry_metal" speed="120"/>
|
||||
<animation event="0.4" file="infantry/sword/attack/isw_s_def_01.psa" name="attack_capture" speed="100"/>
|
||||
<animation event="0.4" file="infantry/sword/attack/isw_s_def_06.psa" name="attack_capture" speed="100"/>
|
||||
<animation event="0.2" file="infantry/sword/attack/isw_s_em_04.psa" name="attack_capture" speed="100"/>
|
||||
|
||||
<animation event="0.5" file="biped/inf_sling_atk_a.psa" name="attack_ranged" speed="30"/>
|
||||
<animation event="0.5" file="infantry/sword/attack/isw_s_off_05.psa" name="attack_slaughter" speed="100"/>
|
||||
@ -46,11 +43,7 @@
|
||||
</group>
|
||||
<group>
|
||||
<variant frequency="1" name="Idle"/>
|
||||
<variant name="attack_capture">
|
||||
<props>
|
||||
<prop actor="props/units/tools/pitchfork.xml" attachpoint="r_hand"/>
|
||||
</props>
|
||||
</variant>
|
||||
<variant file="biped/attack_capture.xml"/>
|
||||
<variant name="attack_slaughter">
|
||||
<props>
|
||||
<prop actor="props/units/weapons/knife.xml" attachpoint="r_hand"/>
|
||||
|
@ -12,9 +12,6 @@
|
||||
<animation file="biped/walk_spearshield.psa" name="carry_wood" speed="120"/>
|
||||
<animation file="biped/walk_spearshield.psa" name="carry_stone" speed="120"/>
|
||||
<animation file="biped/walk_spearshield.psa" name="carry_metal" speed="120"/>
|
||||
<animation event="0.4" file="infantry/sword/attack/isw_s_def_01.psa" name="attack_capture" speed="100"/>
|
||||
<animation event="0.4" file="infantry/sword/attack/isw_s_def_06.psa" name="attack_capture" speed="100"/>
|
||||
<animation event="0.2" file="infantry/sword/attack/isw_s_em_04.psa" name="attack_capture" speed="100"/>
|
||||
<animation event="0.5" file="biped/inf_hoplite_atk_a.psa" name="attack_melee" speed="200"/>
|
||||
<animation event="0.5" file="biped/inf_hoplite_atk_a.psa" name="attack_slaughter" speed="200"/>
|
||||
<animation event="0.23" file="infantry/general/chop.psa" name="gather_tree" speed="250"/>
|
||||
@ -55,11 +52,7 @@
|
||||
</group>
|
||||
<group>
|
||||
<variant frequency="1" name="Idle"/>
|
||||
<variant name="attack_capture">
|
||||
<props>
|
||||
<prop actor="props/units/tools/pitchfork.xml" attachpoint="r_hand"/>
|
||||
</props>
|
||||
</variant>
|
||||
<variant file="biped/attack_capture.xml"/>
|
||||
<variant name="attack_melee">
|
||||
<props>
|
||||
<prop actor="props/units/weapons/spear_hoplite.xml" attachpoint="r_hand"/>
|
||||
|
134
binaries/data/mods/public/art/variants/biped/attack_capture.xml
Normal file
134
binaries/data/mods/public/art/variants/biped/attack_capture.xml
Normal file
@ -0,0 +1,134 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<actor version="1">
|
||||
<castshadow/>
|
||||
<group>
|
||||
<variant frequency="1" name="Base">
|
||||
<animations>
|
||||
<animation file="infantry/spear/idle/isp_01.psa" name="Idle" speed="200"/>
|
||||
<animation file="biped/walk_spearshield.psa" name="Walk" speed="120"/>
|
||||
<animation file="biped/walk_spearshield.psa" name="carry_food" speed="120"/>
|
||||
<animation file="biped/walk_spearshield.psa" name="carry_meat" speed="120"/>
|
||||
<animation file="biped/walk_spearshield.psa" name="carry_wood" speed="120"/>
|
||||
<animation file="biped/walk_spearshield.psa" name="carry_stone" speed="120"/>
|
||||
<animation file="biped/walk_spearshield.psa" name="carry_metal" speed="120"/>
|
||||
<animation event="0.5" file="biped/inf_sling_atk_a.psa" name="attack_ranged" speed="30"/>
|
||||
<animation event="0.5" file="infantry/sword/attack/isw_s_off_05.psa" name="attack_slaughter" speed="100"/>
|
||||
<animation file="infantry/sword/move/run/isw_s_off_01.psa" name="Run" speed="38"/>
|
||||
<animation file="infantry/sword/move/run/isw_s_def_02.psa" name="Run" speed="35"/>
|
||||
<animation event="0.23" file="infantry/general/chop.psa" name="gather_tree" speed="250"/>
|
||||
<animation file="biped/hoe.psa" name="gather_grain" speed="300"/>
|
||||
<animation file="infantry/general/forage.psa" name="gather_fruit" speed="125"/>
|
||||
<animation file="infantry/general/forage.psa" name="gather_meat" speed="125"/>
|
||||
<animation event="0.43" file="infantry/general/mine.psa" name="gather_rock" speed="250"/>
|
||||
<animation event="0.43" file="infantry/general/mine.psa" name="gather_ore" speed="250"/>
|
||||
<animation event="0.43" file="infantry/general/mine.psa" name="gather_ruins" speed="250"/>
|
||||
<animation event="0.6" file="infantry/general/dude/dudebuild.psa" name="Build" speed="300"/>
|
||||
<animation file="infantry/general/death/inf_01.psa" name="Death" speed="400"/>
|
||||
<animation file="infantry/general/death/inf_02.psa" name="Death" speed="700"/>
|
||||
<animation file="infantry/general/death/inf_03.psa" name="Death" speed="500"/>
|
||||
<animation file="infantry/general/death/inf_04.psa" name="Death" speed="400"/>
|
||||
<animation file="infantry/general/death/inf_06.psa" name="Death" speed="500"/>
|
||||
<animation file="infantry/general/death/inf_07.psa" name="Death" speed="400"/>
|
||||
<animation file="biped/inf_salute_c.psa" name="Promotion" speed="450"/>
|
||||
</animations>
|
||||
<mesh>skeletal/m_tunic_short.dae</mesh>
|
||||
<props>
|
||||
<prop actor="props/units/heads/head_hele_b.xml" attachpoint="head"/>
|
||||
<prop actor="props/units/weapons/sling.xml" attachpoint="r_hand"/>
|
||||
<prop actor="props/units/weapons/slingrock.xml" attachpoint="projectile"/>
|
||||
</props>
|
||||
<textures>
|
||||
<texture file="skeletal/hele_tunic.dds" name="baseTex"/>
|
||||
</textures>
|
||||
</variant>
|
||||
</group>
|
||||
<group>
|
||||
<variant frequency="1" name="Idle"/>
|
||||
<variant file="biped/attack_capture.xml"/>
|
||||
<variant name="attack_slaughter">
|
||||
<props>
|
||||
<prop actor="props/units/weapons/knife.xml" attachpoint="r_hand"/>
|
||||
</props>
|
||||
</variant>
|
||||
<variant name="gather_tree">
|
||||
<props>
|
||||
<prop actor="props/units/tools/axe.xml" attachpoint="l_hand"/>
|
||||
<prop attachpoint="r_hand"/>
|
||||
</props>
|
||||
</variant>
|
||||
<variant name="gather_grain">
|
||||
<props>
|
||||
<prop actor="props/units/tools/hoe.xml" attachpoint="l_hand"/>
|
||||
<prop attachpoint="r_hand"/>
|
||||
</props>
|
||||
</variant>
|
||||
<variant name="gather_fruit">
|
||||
<props>
|
||||
<prop actor="props/units/tools/basket.xml" attachpoint="l_leg"/>
|
||||
<prop attachpoint="r_hand"/>
|
||||
</props>
|
||||
</variant>
|
||||
<variant name="gather_meat">
|
||||
<props>
|
||||
<prop attachpoint="r_hand"/>
|
||||
<prop actor="props/units/tools/basket.xml" attachpoint="l_leg"/>
|
||||
</props>
|
||||
</variant>
|
||||
<variant name="gather_rock">
|
||||
<props>
|
||||
<prop actor="props/units/tools/pick.xml" attachpoint="l_hand"/>
|
||||
<prop attachpoint="r_hand"/>
|
||||
</props>
|
||||
</variant>
|
||||
<variant name="gather_ore">
|
||||
<props>
|
||||
<prop actor="props/units/tools/pick.xml" attachpoint="l_hand"/>
|
||||
<prop attachpoint="r_hand"/>
|
||||
</props>
|
||||
</variant>
|
||||
<variant name="gather_ruins">
|
||||
<props>
|
||||
<prop actor="props/units/tools/pick.xml" attachpoint="l_hand"/>
|
||||
<prop attachpoint="r_hand"/>
|
||||
</props>
|
||||
</variant>
|
||||
<variant name="Build">
|
||||
<props>
|
||||
<prop actor="props/units/tools/mallet.xml" attachpoint="r_hand"/>
|
||||
<prop attachpoint="l_hand"/>
|
||||
</props>
|
||||
</variant>
|
||||
<variant name="carry_food">
|
||||
<props>
|
||||
<prop actor="props/units/shuttle_basket.xml" attachpoint="r_hand"/>
|
||||
<prop attachpoint="l_hand"/>
|
||||
</props>
|
||||
</variant>
|
||||
<variant name="carry_meat">
|
||||
<props>
|
||||
<prop actor="props/units/shuttle_meat.xml" attachpoint="r_hand"/>
|
||||
<prop attachpoint="l_hand"/>
|
||||
</props>
|
||||
</variant>
|
||||
<variant name="carry_wood">
|
||||
<props>
|
||||
<prop actor="props/units/shuttle_wood.xml" attachpoint="r_hand"/>
|
||||
<prop actor="" attachpoint="l_hand"/>
|
||||
<prop attachpoint="shield"/>
|
||||
</props>
|
||||
</variant>
|
||||
<variant name="carry_stone">
|
||||
<props>
|
||||
<prop actor="props/units/shuttle_stone.xml" attachpoint="r_hand"/>
|
||||
<prop actor="" attachpoint="l_hand"/>
|
||||
</props>
|
||||
</variant>
|
||||
<variant name="carry_metal">
|
||||
<props>
|
||||
<prop actor="props/units/shuttle_metal.xml" attachpoint="r_hand"/>
|
||||
<prop actor="" attachpoint="l_hand"/>
|
||||
</props>
|
||||
</variant>
|
||||
</group>
|
||||
<material>player_trans.xml</material>
|
||||
</actor>
|
54
binaries/data/mods/public/art/variants/variant.rnc
Normal file
54
binaries/data/mods/public/art/variants/variant.rnc
Normal file
@ -0,0 +1,54 @@
|
||||
namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
|
||||
##
|
||||
# NOTE: To modify this Relax NG grammar, edit the Relax NG Compact (.rnc) file
|
||||
# and use a converter tool like trang to generate the Relax NG XML (.rng) file
|
||||
##
|
||||
|
||||
element variant {
|
||||
attribute name { text }? &
|
||||
attribute frequency { xsd:nonNegativeInteger }? &
|
||||
element mesh {
|
||||
text
|
||||
}? &
|
||||
element textures {
|
||||
element texture {
|
||||
attribute file { text }? &
|
||||
attribute name { text }
|
||||
}*
|
||||
}? &
|
||||
element decal {
|
||||
attribute width { xsd:float } & # X
|
||||
attribute depth { xsd:float } & # Z
|
||||
attribute angle { xsd:float } &
|
||||
attribute offsetx { xsd:float } &
|
||||
attribute offsetz { xsd:float }
|
||||
}? &
|
||||
element particles {
|
||||
attribute file { text }
|
||||
}? &
|
||||
element color { list {
|
||||
xsd:nonNegativeInteger, # R
|
||||
xsd:nonNegativeInteger, # G
|
||||
xsd:nonNegativeInteger # B
|
||||
} }? &
|
||||
element animations {
|
||||
element animation {
|
||||
attribute name { text } &
|
||||
attribute file { text }? &
|
||||
attribute speed { xsd:nonNegativeInteger } &
|
||||
attribute event { xsd:decimal { minInclusive = "0" maxInclusive = "1" } }? &
|
||||
attribute load { xsd:decimal { minInclusive = "0" maxInclusive = "1" } }? &
|
||||
attribute sound { xsd:decimal { minInclusive = "0" maxInclusive = "1" } }?
|
||||
}*
|
||||
}? &
|
||||
element props {
|
||||
element prop {
|
||||
(attribute actor { text }? &
|
||||
attribute attachpoint { text } &
|
||||
attribute minheight { xsd:float }? &
|
||||
attribute maxheight { xsd:float }? &
|
||||
attribute selectable { "true" | "false" }?)
|
||||
}*
|
||||
}?
|
||||
}
|
||||
|
153
binaries/data/mods/public/art/variants/variant.rng
Normal file
153
binaries/data/mods/public/art/variants/variant.rng
Normal file
@ -0,0 +1,153 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<element name="variant" xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0" xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
|
||||
<a:documentation/>
|
||||
<!--
|
||||
NOTE: To modify this Relax NG grammar, edit the Relax NG Compact (.rnc) file
|
||||
and use a converter tool like trang to generate the Relax NG XML (.rng) file
|
||||
-->
|
||||
<a:documentation/>
|
||||
<interleave>
|
||||
<optional>
|
||||
<attribute name="name"/>
|
||||
</optional>
|
||||
<optional>
|
||||
<attribute name="frequency">
|
||||
<data type="nonNegativeInteger"/>
|
||||
</attribute>
|
||||
</optional>
|
||||
<optional>
|
||||
<element name="mesh">
|
||||
<text/>
|
||||
</element>
|
||||
</optional>
|
||||
<optional>
|
||||
<element name="textures">
|
||||
<zeroOrMore>
|
||||
<element name="texture">
|
||||
<interleave>
|
||||
<optional>
|
||||
<attribute name="file"/>
|
||||
</optional>
|
||||
<attribute name="name"/>
|
||||
</interleave>
|
||||
</element>
|
||||
</zeroOrMore>
|
||||
</element>
|
||||
</optional>
|
||||
<optional>
|
||||
<element name="decal">
|
||||
<interleave>
|
||||
<attribute name="width">
|
||||
<data type="float"/>
|
||||
</attribute>
|
||||
<!-- X -->
|
||||
<attribute name="depth">
|
||||
<data type="float"/>
|
||||
</attribute>
|
||||
<!-- Z -->
|
||||
<attribute name="angle">
|
||||
<data type="float"/>
|
||||
</attribute>
|
||||
<attribute name="offsetx">
|
||||
<data type="float"/>
|
||||
</attribute>
|
||||
<attribute name="offsetz">
|
||||
<data type="float"/>
|
||||
</attribute>
|
||||
</interleave>
|
||||
</element>
|
||||
</optional>
|
||||
<optional>
|
||||
<element name="particles">
|
||||
<attribute name="file"/>
|
||||
</element>
|
||||
</optional>
|
||||
<optional>
|
||||
<element name="color">
|
||||
<list>
|
||||
<group>
|
||||
<data type="nonNegativeInteger"/>
|
||||
<!-- R -->
|
||||
<data type="nonNegativeInteger"/>
|
||||
<!-- G -->
|
||||
<data type="nonNegativeInteger"/>
|
||||
</group>
|
||||
<!-- B -->
|
||||
</list>
|
||||
</element>
|
||||
</optional>
|
||||
<optional>
|
||||
<element name="animations">
|
||||
<zeroOrMore>
|
||||
<element name="animation">
|
||||
<interleave>
|
||||
<attribute name="name"/>
|
||||
<optional>
|
||||
<attribute name="file"/>
|
||||
</optional>
|
||||
<attribute name="speed">
|
||||
<data type="nonNegativeInteger"/>
|
||||
</attribute>
|
||||
<optional>
|
||||
<attribute name="event">
|
||||
<data type="decimal">
|
||||
<param name="minInclusive">0</param>
|
||||
<param name="maxInclusive">1</param>
|
||||
</data>
|
||||
</attribute>
|
||||
</optional>
|
||||
<optional>
|
||||
<attribute name="load">
|
||||
<data type="decimal">
|
||||
<param name="minInclusive">0</param>
|
||||
<param name="maxInclusive">1</param>
|
||||
</data>
|
||||
</attribute>
|
||||
</optional>
|
||||
<optional>
|
||||
<attribute name="sound">
|
||||
<data type="decimal">
|
||||
<param name="minInclusive">0</param>
|
||||
<param name="maxInclusive">1</param>
|
||||
</data>
|
||||
</attribute>
|
||||
</optional>
|
||||
</interleave>
|
||||
</element>
|
||||
</zeroOrMore>
|
||||
</element>
|
||||
</optional>
|
||||
<optional>
|
||||
<element name="props">
|
||||
<zeroOrMore>
|
||||
<element name="prop">
|
||||
<interleave>
|
||||
<optional>
|
||||
<attribute name="actor"/>
|
||||
</optional>
|
||||
<attribute name="attachpoint"/>
|
||||
<optional>
|
||||
<attribute name="minheight">
|
||||
<data type="float"/>
|
||||
</attribute>
|
||||
</optional>
|
||||
<optional>
|
||||
<attribute name="maxheight">
|
||||
<data type="float"/>
|
||||
</attribute>
|
||||
</optional>
|
||||
<optional>
|
||||
<attribute name="selectable">
|
||||
<choice>
|
||||
<value>true</value>
|
||||
<value>false</value>
|
||||
</choice>
|
||||
</attribute>
|
||||
</optional>
|
||||
</interleave>
|
||||
</element>
|
||||
</zeroOrMore>
|
||||
</element>
|
||||
</optional>
|
||||
</interleave>
|
||||
</element>
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2015 Wildfire Games.
|
||||
/* Copyright (C) 2016 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -38,6 +38,171 @@ CObjectBase::CObjectBase(CObjectManager& objectManager)
|
||||
m_Properties.m_FloatOnWater = false;
|
||||
}
|
||||
|
||||
void CObjectBase::LoadVariant(const CXeromyces& XeroFile, const XMBElement& variant, Variant& currentVariant)
|
||||
{
|
||||
#define EL(x) int el_##x = XeroFile.GetElementID(#x)
|
||||
#define AT(x) int at_##x = XeroFile.GetAttributeID(#x)
|
||||
EL(animation);
|
||||
EL(animations);
|
||||
EL(color);
|
||||
EL(decal);
|
||||
EL(mesh);
|
||||
EL(particles);
|
||||
EL(prop);
|
||||
EL(props);
|
||||
EL(texture);
|
||||
EL(textures);
|
||||
EL(variant);
|
||||
AT(actor);
|
||||
AT(angle);
|
||||
AT(attachpoint);
|
||||
AT(depth);
|
||||
AT(event);
|
||||
AT(file);
|
||||
AT(frequency);
|
||||
AT(load);
|
||||
AT(maxheight);
|
||||
AT(minheight);
|
||||
AT(name);
|
||||
AT(offsetx);
|
||||
AT(offsetz);
|
||||
AT(selectable);
|
||||
AT(sound);
|
||||
AT(speed);
|
||||
AT(width);
|
||||
#undef AT
|
||||
#undef EL
|
||||
|
||||
if (variant.GetNodeName() != el_variant)
|
||||
{
|
||||
LOGERROR("Invalid variant format (unrecognised root element '%s')", XeroFile.GetElementString(variant.GetNodeName()).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
XERO_ITER_ATTR(variant, attr)
|
||||
{
|
||||
if (attr.Name == at_file)
|
||||
{
|
||||
// Open up an external file to load.
|
||||
// Don't crash hard when failures happen, but log them and continue
|
||||
m_UsedFiles.insert(attr.Value);
|
||||
CXeromyces XeroVariant;
|
||||
if (XeroVariant.Load(g_VFS, "art/variants/" + attr.Value) == PSRETURN_OK)
|
||||
{
|
||||
XMBElement variantRoot = XeroVariant.GetRoot();
|
||||
LoadVariant(XeroVariant, variantRoot, currentVariant);
|
||||
}
|
||||
else
|
||||
LOGERROR("Could not open path %s", attr.Value);
|
||||
// Continue loading extra definitions in this variant to allow nested files
|
||||
}
|
||||
else if (attr.Name == at_name)
|
||||
currentVariant.m_VariantName = attr.Value.LowerCase();
|
||||
else if (attr.Name == at_frequency)
|
||||
currentVariant.m_Frequency = attr.Value.ToInt();
|
||||
}
|
||||
|
||||
XERO_ITER_EL(variant, option)
|
||||
{
|
||||
int option_name = option.GetNodeName();
|
||||
|
||||
if (option_name == el_mesh)
|
||||
{
|
||||
currentVariant.m_ModelFilename = VfsPath("art/meshes") / option.GetText().FromUTF8();
|
||||
}
|
||||
else if (option_name == el_textures)
|
||||
{
|
||||
XERO_ITER_EL(option, textures_element)
|
||||
{
|
||||
ENSURE(textures_element.GetNodeName() == el_texture);
|
||||
|
||||
Samp samp;
|
||||
XERO_ITER_ATTR(textures_element, se)
|
||||
{
|
||||
if (se.Name == at_file)
|
||||
samp.m_SamplerFile = VfsPath("art/textures/skins") / se.Value.FromUTF8();
|
||||
else if (se.Name == at_name)
|
||||
samp.m_SamplerName = CStrIntern(se.Value);
|
||||
}
|
||||
currentVariant.m_Samplers.push_back(samp);
|
||||
}
|
||||
}
|
||||
else if (option_name == el_decal)
|
||||
{
|
||||
XMBAttributeList attrs = option.GetAttributes();
|
||||
Decal decal;
|
||||
decal.m_SizeX = attrs.GetNamedItem(at_width).ToFloat();
|
||||
decal.m_SizeZ = attrs.GetNamedItem(at_depth).ToFloat();
|
||||
decal.m_Angle = DEGTORAD(attrs.GetNamedItem(at_angle).ToFloat());
|
||||
decal.m_OffsetX = attrs.GetNamedItem(at_offsetx).ToFloat();
|
||||
decal.m_OffsetZ = attrs.GetNamedItem(at_offsetz).ToFloat();
|
||||
currentVariant.m_Decal = decal;
|
||||
}
|
||||
else if (option_name == el_particles)
|
||||
{
|
||||
XMBAttributeList attrs = option.GetAttributes();
|
||||
VfsPath file = VfsPath("art/particles") / attrs.GetNamedItem(at_file).FromUTF8();
|
||||
currentVariant.m_Particles = file;
|
||||
|
||||
// For particle hotloading, it's easiest to reload the entire actor,
|
||||
// so remember the relevant particle file as a dependency for this actor
|
||||
m_UsedFiles.insert(file);
|
||||
}
|
||||
else if (option_name == el_color)
|
||||
{
|
||||
currentVariant.m_Color = option.GetText();
|
||||
}
|
||||
else if (option_name == el_animations)
|
||||
{
|
||||
XERO_ITER_EL(option, anim_element)
|
||||
{
|
||||
ENSURE(anim_element.GetNodeName() == el_animation);
|
||||
|
||||
Anim anim;
|
||||
XERO_ITER_ATTR(anim_element, ae)
|
||||
{
|
||||
if (ae.Name == at_name)
|
||||
anim.m_AnimName = ae.Value;
|
||||
else if (ae.Name == at_file)
|
||||
anim.m_FileName = VfsPath("art/animation") / ae.Value.FromUTF8();
|
||||
else if (ae.Name == at_speed)
|
||||
anim.m_Speed = ae.Value.ToInt() > 0 ? ae.Value.ToInt() / 100.f : 1.f;
|
||||
else if (ae.Name == at_event)
|
||||
anim.m_ActionPos = clamp(ae.Value.ToFloat(), 0.f, 1.f);
|
||||
else if (ae.Name == at_load)
|
||||
anim.m_ActionPos2 = clamp(ae.Value.ToFloat(), 0.f, 1.f);
|
||||
else if (ae.Name == at_sound)
|
||||
anim.m_SoundPos = clamp(ae.Value.ToFloat(), 0.f, 1.f);
|
||||
}
|
||||
currentVariant.m_Anims.push_back(anim);
|
||||
}
|
||||
}
|
||||
else if (option_name == el_props)
|
||||
{
|
||||
XERO_ITER_EL(option, prop_element)
|
||||
{
|
||||
ENSURE(prop_element.GetNodeName() == el_prop);
|
||||
|
||||
Prop prop;
|
||||
XERO_ITER_ATTR(prop_element, pe)
|
||||
{
|
||||
if (pe.Name == at_attachpoint)
|
||||
prop.m_PropPointName = pe.Value;
|
||||
else if (pe.Name == at_actor)
|
||||
prop.m_ModelName = pe.Value.FromUTF8();
|
||||
else if (pe.Name == at_minheight)
|
||||
prop.m_minHeight = pe.Value.ToFloat();
|
||||
else if (pe.Name == at_maxheight)
|
||||
prop.m_maxHeight = pe.Value.ToFloat();
|
||||
else if (pe.Name == at_selectable)
|
||||
prop.m_selectable = pe.Value != "false";
|
||||
}
|
||||
currentVariant.m_Props.push_back(prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CObjectBase::Load(const VfsPath& pathname)
|
||||
{
|
||||
m_UsedFiles.clear();
|
||||
@ -53,36 +218,8 @@ bool CObjectBase::Load(const VfsPath& pathname)
|
||||
EL(actor);
|
||||
EL(castshadow);
|
||||
EL(float);
|
||||
EL(material);
|
||||
EL(group);
|
||||
EL(variant);
|
||||
EL(animations);
|
||||
EL(animation);
|
||||
EL(props);
|
||||
EL(prop);
|
||||
EL(mesh);
|
||||
EL(texture);
|
||||
EL(textures);
|
||||
EL(color);
|
||||
EL(decal);
|
||||
EL(particles);
|
||||
AT(file);
|
||||
AT(name);
|
||||
AT(speed);
|
||||
AT(event);
|
||||
AT(load);
|
||||
AT(sound);
|
||||
AT(attachpoint);
|
||||
AT(actor);
|
||||
AT(frequency);
|
||||
AT(width);
|
||||
AT(depth);
|
||||
AT(angle);
|
||||
AT(offsetx);
|
||||
AT(offsetz);
|
||||
AT(minheight);
|
||||
AT(maxheight);
|
||||
AT(selectable);
|
||||
EL(material);
|
||||
#undef AT
|
||||
#undef EL
|
||||
|
||||
@ -94,7 +231,6 @@ bool CObjectBase::Load(const VfsPath& pathname)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
m_VariantGroups.clear();
|
||||
|
||||
m_Pathname = pathname;
|
||||
@ -132,155 +268,21 @@ bool CObjectBase::Load(const VfsPath& pathname)
|
||||
std::vector<Variant>::iterator currentVariant = currentGroup->begin();
|
||||
XERO_ITER_EL(child, variant)
|
||||
{
|
||||
ENSURE(variant.GetNodeName() == el_variant);
|
||||
XERO_ITER_ATTR(variant, attr)
|
||||
{
|
||||
if (attr.Name == at_name)
|
||||
currentVariant->m_VariantName = attr.Value.LowerCase();
|
||||
|
||||
else if (attr.Name == at_frequency)
|
||||
currentVariant->m_Frequency = attr.Value.ToInt();
|
||||
}
|
||||
|
||||
XERO_ITER_EL(variant, option)
|
||||
{
|
||||
int option_name = option.GetNodeName();
|
||||
|
||||
if (option_name == el_mesh)
|
||||
{
|
||||
currentVariant->m_ModelFilename = VfsPath("art/meshes") / option.GetText().FromUTF8();
|
||||
}
|
||||
else if (option_name == el_textures)
|
||||
{
|
||||
XERO_ITER_EL(option, textures_element)
|
||||
{
|
||||
ENSURE(textures_element.GetNodeName() == el_texture);
|
||||
|
||||
Samp samp;
|
||||
XERO_ITER_ATTR(textures_element, se)
|
||||
{
|
||||
if (se.Name == at_file)
|
||||
samp.m_SamplerFile = VfsPath("art/textures/skins") / se.Value.FromUTF8();
|
||||
else if (se.Name == at_name)
|
||||
samp.m_SamplerName = CStrIntern(se.Value);
|
||||
}
|
||||
currentVariant->m_Samplers.push_back(samp);
|
||||
}
|
||||
}
|
||||
else if (option_name == el_decal)
|
||||
{
|
||||
XMBAttributeList attrs = option.GetAttributes();
|
||||
Decal decal;
|
||||
decal.m_SizeX = attrs.GetNamedItem(at_width).ToFloat();
|
||||
decal.m_SizeZ = attrs.GetNamedItem(at_depth).ToFloat();
|
||||
decal.m_Angle = DEGTORAD(attrs.GetNamedItem(at_angle).ToFloat());
|
||||
decal.m_OffsetX = attrs.GetNamedItem(at_offsetx).ToFloat();
|
||||
decal.m_OffsetZ = attrs.GetNamedItem(at_offsetz).ToFloat();
|
||||
currentVariant->m_Decal = decal;
|
||||
}
|
||||
else if (option_name == el_particles)
|
||||
{
|
||||
XMBAttributeList attrs = option.GetAttributes();
|
||||
VfsPath file = VfsPath("art/particles") / attrs.GetNamedItem(at_file).FromUTF8();
|
||||
currentVariant->m_Particles = file;
|
||||
|
||||
// For particle hotloading, it's easiest to reload the entire actor,
|
||||
// so remember the relevant particle file as a dependency for this actor
|
||||
m_UsedFiles.insert(file);
|
||||
}
|
||||
else if (option_name == el_color)
|
||||
{
|
||||
currentVariant->m_Color = option.GetText();
|
||||
}
|
||||
else if (option_name == el_animations)
|
||||
{
|
||||
XERO_ITER_EL(option, anim_element)
|
||||
{
|
||||
ENSURE(anim_element.GetNodeName() == el_animation);
|
||||
|
||||
Anim anim;
|
||||
XERO_ITER_ATTR(anim_element, ae)
|
||||
{
|
||||
if (ae.Name == at_name)
|
||||
{
|
||||
anim.m_AnimName = ae.Value;
|
||||
}
|
||||
else if (ae.Name == at_file)
|
||||
{
|
||||
anim.m_FileName = VfsPath("art/animation") / ae.Value.FromUTF8();
|
||||
}
|
||||
else if (ae.Name == at_speed)
|
||||
{
|
||||
anim.m_Speed = ae.Value.ToInt() / 100.f;
|
||||
if (anim.m_Speed <= 0.0) anim.m_Speed = 1.0f;
|
||||
}
|
||||
else if (ae.Name == at_event)
|
||||
{
|
||||
float pos = ae.Value.ToFloat();
|
||||
anim.m_ActionPos = clamp(pos, 0.f, 1.f);
|
||||
}
|
||||
else if (ae.Name == at_load)
|
||||
{
|
||||
float pos = ae.Value.ToFloat();
|
||||
anim.m_ActionPos2 = clamp(pos, 0.f, 1.f);
|
||||
}
|
||||
else if (ae.Name == at_sound)
|
||||
{
|
||||
float pos = ae.Value.ToFloat();
|
||||
anim.m_SoundPos = clamp(pos, 0.f, 1.f);
|
||||
}
|
||||
}
|
||||
currentVariant->m_Anims.push_back(anim);
|
||||
}
|
||||
|
||||
}
|
||||
else if (option_name == el_props)
|
||||
{
|
||||
XERO_ITER_EL(option, prop_element)
|
||||
{
|
||||
ENSURE(prop_element.GetNodeName() == el_prop);
|
||||
|
||||
Prop prop;
|
||||
XERO_ITER_ATTR(prop_element, pe)
|
||||
{
|
||||
if (pe.Name == at_attachpoint)
|
||||
prop.m_PropPointName = pe.Value;
|
||||
else if (pe.Name == at_actor)
|
||||
prop.m_ModelName = pe.Value.FromUTF8();
|
||||
else if (pe.Name == at_minheight)
|
||||
prop.m_minHeight = pe.Value.ToFloat();
|
||||
else if (pe.Name == at_maxheight)
|
||||
prop.m_maxHeight = pe.Value.ToFloat();
|
||||
else if (pe.Name == at_selectable)
|
||||
prop.m_selectable = pe.Value != "false";
|
||||
}
|
||||
currentVariant->m_Props.push_back(prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LoadVariant(XeroFile, variant, *currentVariant);
|
||||
++currentVariant;
|
||||
}
|
||||
|
||||
if (currentGroup->size() == 0)
|
||||
{
|
||||
LOGERROR("Actor group has zero variants ('%s')", pathname.string8());
|
||||
}
|
||||
|
||||
++currentGroup;
|
||||
}
|
||||
else if (child_name == el_castshadow)
|
||||
{
|
||||
m_Properties.m_CastShadows = true;
|
||||
}
|
||||
else if (child_name == el_float)
|
||||
{
|
||||
m_Properties.m_FloatOnWater = true;
|
||||
}
|
||||
else if (child_name == el_material)
|
||||
{
|
||||
m_Material = VfsPath("art/materials") / child.GetText().FromUTF8();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_Material.empty())
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2013 Wildfire Games.
|
||||
/* Copyright (C) 2016 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -29,6 +29,7 @@ class CObjectManager;
|
||||
#include "lib/file/vfs/vfs_path.h"
|
||||
#include "ps/CStr.h"
|
||||
#include "ps/CStrIntern.h"
|
||||
#include "ps/XML/Xeromyces.h"
|
||||
|
||||
#include <boost/random/mersenne_twister.hpp>
|
||||
|
||||
@ -187,6 +188,8 @@ private:
|
||||
CObjectManager& m_ObjectManager;
|
||||
|
||||
boost::unordered_set<VfsPath> m_UsedFiles;
|
||||
|
||||
void LoadVariant(const CXeromyces& XeroFile, const XMBElement& variant, Variant& currentVariant);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -46,13 +46,14 @@ ActorEditorListCtrl::ActorEditorListCtrl(wxWindow* parent)
|
||||
|
||||
#undef COLOR
|
||||
|
||||
AddColumnType(_("Variant"), 90, "@name", new FieldEditCtrl_Text());
|
||||
AddColumnType(_("Ratio"), 50, "@frequency", new FieldEditCtrl_Text());
|
||||
AddColumnType(_("Model"), 140, "mesh", new FieldEditCtrl_File(_T("art/meshes/"), _("Mesh files (*.pmd, *.dae)|*.pmd;*.dae|All files (*.*)|*.*")));
|
||||
AddColumnType(_("Textures"), 250, "textures", new FieldEditCtrl_Dialog(&TexListEditor::Create));
|
||||
AddColumnType(_("Animations"), 250, "animations", new FieldEditCtrl_Dialog(&AnimListEditor::Create));
|
||||
AddColumnType(_("Props"), 220, "props", new FieldEditCtrl_Dialog(&PropListEditor::Create));
|
||||
AddColumnType(_("Color"), 80, "color", new FieldEditCtrl_Color());
|
||||
AddColumnType(_("Variant"), 90, "@name", new FieldEditCtrl_Text());
|
||||
AddColumnType(_("Base File"), 90, "@file", new FieldEditCtrl_File(_T("art/variants/"), _("Variants (*.xml)|*.xml|All files (*.*)|*.*")));
|
||||
AddColumnType(_("Ratio"), 50, "@frequency", new FieldEditCtrl_Text());
|
||||
AddColumnType(_("Model"), 140, "mesh", new FieldEditCtrl_File(_T("art/meshes/"), _("Mesh files (*.pmd, *.dae)|*.pmd;*.dae|All files (*.*)|*.*")));
|
||||
AddColumnType(_("Textures"), 250, "textures", new FieldEditCtrl_Dialog(&TexListEditor::Create));
|
||||
AddColumnType(_("Animations"), 250, "animations", new FieldEditCtrl_Dialog(&AnimListEditor::Create));
|
||||
AddColumnType(_("Props"), 220, "props", new FieldEditCtrl_Dialog(&PropListEditor::Create));
|
||||
AddColumnType(_("Color"), 80, "color", new FieldEditCtrl_Color());
|
||||
}
|
||||
|
||||
void ActorEditorListCtrl::DoImport(AtObj& in)
|
||||
|
@ -77,12 +77,18 @@ sub validate
|
||||
sub validate_actors
|
||||
{
|
||||
my @files = find_files('art/actors', 'xml');
|
||||
validate('actor', \@files, 'art/actors/actor.rng');
|
||||
}
|
||||
|
||||
sub validate_guis
|
||||
{
|
||||
# there are two different gui XML schemas depending on path
|
||||
validate('actor', \@files, 'art/actors/actor.rng');
|
||||
}
|
||||
|
||||
sub validate_variants
|
||||
{
|
||||
my @files = find_files('art/variants', 'xml');
|
||||
validate('variant', \@files, 'art/variants/variant.rng');
|
||||
}
|
||||
|
||||
sub validate_guis
|
||||
{
|
||||
# there are two different gui XML schemas depending on path
|
||||
my @files = find_files('gui', 'xml');
|
||||
my (@guipages, @guixmls);
|
||||
for my $f (@files)
|
||||
@ -164,12 +170,13 @@ sub validate_textures
|
||||
push @files, $f if $f =~ /textures.xml/;
|
||||
}
|
||||
validate('texture', \@files, 'art/textures/texture.rng');
|
||||
}
|
||||
|
||||
validate_actors();
|
||||
validate_guis();
|
||||
validate_maps();
|
||||
validate_materials();
|
||||
}
|
||||
|
||||
validate_actors();
|
||||
validate_variants();
|
||||
validate_guis();
|
||||
validate_maps();
|
||||
validate_materials();
|
||||
validate_particles();
|
||||
validate_simulation();
|
||||
validate_soundgroups();
|
||||
|
Loading…
Reference in New Issue
Block a user