mirror of
https://github.com/Retera/WarsmashModEngine.git
synced 2022-07-31 17:38:59 +02:00
Merge
This commit is contained in:
commit
1af6a438ee
128
.gitignore
vendored
Normal file
128
.gitignore
vendored
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
## Java
|
||||||
|
|
||||||
|
*.class
|
||||||
|
*.war
|
||||||
|
*.ear
|
||||||
|
hs_err_pid*
|
||||||
|
|
||||||
|
## Robovm
|
||||||
|
/ios/robovm-build/
|
||||||
|
|
||||||
|
## GWT
|
||||||
|
/html/war/
|
||||||
|
/html/gwt-unitCache/
|
||||||
|
.apt_generated/
|
||||||
|
.gwt/
|
||||||
|
gwt-unitCache/
|
||||||
|
www-test/
|
||||||
|
.gwt-tmp/
|
||||||
|
|
||||||
|
## Android Studio and Intellij and Android in general
|
||||||
|
/android/libs/armeabi/
|
||||||
|
/android/libs/armeabi-v7a/
|
||||||
|
/android/libs/arm64-v8a/
|
||||||
|
/android/libs/x86/
|
||||||
|
/android/libs/x86_64/
|
||||||
|
/android/gen/
|
||||||
|
.idea/
|
||||||
|
*.ipr
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
/android/out/
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
|
||||||
|
## Eclipse
|
||||||
|
|
||||||
|
.classpath
|
||||||
|
.project
|
||||||
|
.metadata/
|
||||||
|
/android/bin/
|
||||||
|
/core/bin/
|
||||||
|
/desktop/bin/
|
||||||
|
/html/bin/
|
||||||
|
/ios/bin/
|
||||||
|
/ios-moe/bin/
|
||||||
|
*.tmp
|
||||||
|
*.bak
|
||||||
|
*.swp
|
||||||
|
*~.nib
|
||||||
|
.settings/
|
||||||
|
.loadpath
|
||||||
|
.externalToolBuilders/
|
||||||
|
*.launch
|
||||||
|
|
||||||
|
## NetBeans
|
||||||
|
|
||||||
|
/nbproject/private/
|
||||||
|
/android/nbproject/private/
|
||||||
|
/core/nbproject/private/
|
||||||
|
/desktop/nbproject/private/
|
||||||
|
/html/nbproject/private/
|
||||||
|
/ios/nbproject/private/
|
||||||
|
/ios-moe/nbproject/private/
|
||||||
|
|
||||||
|
/build/
|
||||||
|
/android/build/
|
||||||
|
/core/build/
|
||||||
|
/desktop/build/
|
||||||
|
/html/build/
|
||||||
|
/ios/build/
|
||||||
|
/ios-moe/build/
|
||||||
|
|
||||||
|
/nbbuild/
|
||||||
|
/android/nbbuild/
|
||||||
|
/core/nbbuild/
|
||||||
|
/desktop/nbbuild/
|
||||||
|
/html/nbbuild/
|
||||||
|
/ios/nbbuild/
|
||||||
|
/ios-moe/nbbuild/
|
||||||
|
|
||||||
|
/dist/
|
||||||
|
/android/dist/
|
||||||
|
/core/dist/
|
||||||
|
/desktop/dist/
|
||||||
|
/html/dist/
|
||||||
|
/ios/dist/
|
||||||
|
/ios-moe/dist/
|
||||||
|
|
||||||
|
/nbdist/
|
||||||
|
/android/nbdist/
|
||||||
|
/core/nbdist/
|
||||||
|
/desktop/nbdist/
|
||||||
|
/html/nbdist/
|
||||||
|
/ios/nbdist/
|
||||||
|
/ios-moe/nbdist/
|
||||||
|
|
||||||
|
nbactions.xml
|
||||||
|
nb-configuration.xml
|
||||||
|
|
||||||
|
## Gradle
|
||||||
|
|
||||||
|
/local.properties
|
||||||
|
.gradle/
|
||||||
|
gradle-app.setting
|
||||||
|
/build/
|
||||||
|
/android/build/
|
||||||
|
/core/build/
|
||||||
|
/desktop/build/
|
||||||
|
/html/build/
|
||||||
|
/ios/build/
|
||||||
|
/ios-moe/build/
|
||||||
|
|
||||||
|
## OS Specific
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
## iOS
|
||||||
|
/ios/xcode/*.xcodeproj/*
|
||||||
|
!/ios/xcode/*.xcodeproj/xcshareddata
|
||||||
|
!/ios/xcode/*.xcodeproj/project.pbxproj
|
||||||
|
/ios/xcode/native/
|
||||||
|
|
||||||
|
/ios-moe/xcode/*.xcodeproj/*
|
||||||
|
!/ios-moe/xcode/*.xcodeproj/xcshareddata
|
||||||
|
!/ios-moe/xcode/*.xcodeproj/project.pbxproj
|
||||||
|
/ios-moe/xcode/native/
|
||||||
|
|
||||||
|
## data
|
||||||
|
/core/data
|
98
build.gradle
Normal file
98
build.gradle
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
flatDir {
|
||||||
|
dirs "$rootProject.projectDir/jars"
|
||||||
|
}
|
||||||
|
mavenCentral()
|
||||||
|
maven { url "https://plugins.gradle.org/m2/" }
|
||||||
|
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
|
||||||
|
maven { url "https://maven.nikr.net/" }
|
||||||
|
jcenter()
|
||||||
|
google()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allprojects {
|
||||||
|
apply plugin: "eclipse"
|
||||||
|
apply plugin: "idea"
|
||||||
|
|
||||||
|
version = '1.0'
|
||||||
|
ext {
|
||||||
|
appName = "warsmash"
|
||||||
|
gdxVersion = '1.9.8'
|
||||||
|
roboVMVersion = '2.3.5'
|
||||||
|
box2DLightsVersion = '1.4'
|
||||||
|
ashleyVersion = '1.7.0'
|
||||||
|
aiVersion = '1.8.0'
|
||||||
|
antlrVersion = '4.7'
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
mavenCentral()
|
||||||
|
google()
|
||||||
|
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
|
||||||
|
maven { url "https://oss.sonatype.org/content/repositories/releases/" }
|
||||||
|
maven { url "https://maven.nikr.net/" }
|
||||||
|
maven { url 'https://jitpack.io' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
project(":desktop") {
|
||||||
|
apply plugin: "java"
|
||||||
|
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile project(":core")
|
||||||
|
compile "com.badlogicgames.gdx:gdx-backend-lwjgl:$gdxVersion"
|
||||||
|
compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop"
|
||||||
|
compile "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-desktop"
|
||||||
|
compile "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-desktop"
|
||||||
|
compile "com.google.guava:guava:23.5-jre"
|
||||||
|
compile "net.nikr:dds:1.0.0"
|
||||||
|
implementation 'com.github.inwc3:wc3libs:-SNAPSHOT'
|
||||||
|
compile files(fileTree(dir:'../jars', includes: ['*.jar']))
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
project(":core") {
|
||||||
|
apply plugin: "java"
|
||||||
|
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile project(":fdfparser")
|
||||||
|
compile project(":jassparser")
|
||||||
|
compile "com.badlogicgames.gdx:gdx:$gdxVersion"
|
||||||
|
compile "com.badlogicgames.gdx:gdx-box2d:$gdxVersion"
|
||||||
|
compile "com.badlogicgames.gdx:gdx-freetype:$gdxVersion"
|
||||||
|
compile "com.google.guava:guava:23.5-jre"
|
||||||
|
compile "net.nikr:dds:1.0.0"
|
||||||
|
implementation 'com.github.inwc3:wc3libs:-SNAPSHOT'
|
||||||
|
compile files(fileTree(dir:'../jars', includes: ['*.jar']))
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
project(":fdfparser") {
|
||||||
|
apply plugin: "antlr"
|
||||||
|
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
antlr "org.antlr:antlr4:$antlrVersion" // use antlr version 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
project(":jassparser") {
|
||||||
|
apply plugin: "antlr"
|
||||||
|
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
antlr "org.antlr:antlr4:$antlrVersion" // use antlr version 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.eclipse.doLast {
|
||||||
|
delete ".project"
|
||||||
|
}
|
BIN
core/assets/badlogic.jpg
Normal file
BIN
core/assets/badlogic.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 67 KiB |
16
core/assets/shaders/BoneTexture.vs
Normal file
16
core/assets/shaders/BoneTexture.vs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
uniform sampler2D u_boneMap;
|
||||||
|
uniform float u_vectorSize;
|
||||||
|
uniform float u_rowSize;
|
||||||
|
mat4 fetchMatrix(float column, float row) {
|
||||||
|
column *= u_vectorSize * 4.0;
|
||||||
|
row *= u_rowSize;
|
||||||
|
// Add in half texel to sample in the middle of the texel.
|
||||||
|
// Otherwise, since the sample is directly on the boundry, small floating point errors can cause the sample to get the wrong pixel.
|
||||||
|
// This is mostly noticable with NPOT textures, which the bone maps are.
|
||||||
|
column += 0.5 * u_vectorSize;
|
||||||
|
row += 0.5 * u_rowSize;
|
||||||
|
return mat4(texture2D(u_boneMap, vec2(column, row)),
|
||||||
|
texture2D(u_boneMap, vec2(column + u_vectorSize, row)),
|
||||||
|
texture2D(u_boneMap, vec2(column + u_vectorSize * 2.0, row)),
|
||||||
|
texture2D(u_boneMap, vec2(column + u_vectorSize * 3.0, row)));
|
||||||
|
}
|
53
core/assets/warsmash.ini
Normal file
53
core/assets/warsmash.ini
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
[DataSources]
|
||||||
|
Count=8
|
||||||
|
Type00=MPQ
|
||||||
|
Path00="D:\Games\Warcraft III Patch 1.22\war3.mpq"
|
||||||
|
Type01=MPQ
|
||||||
|
Path01="D:\Games\Warcraft III Patch 1.22\War3x.mpq"
|
||||||
|
Type02=MPQ
|
||||||
|
Path02="D:\Games\Warcraft III Patch 1.22\War3xlocal.mpq"
|
||||||
|
Type03=MPQ
|
||||||
|
Path03="D:\Games\Warcraft III Patch 1.22\War3Patch.mpq"
|
||||||
|
Type04=Folder
|
||||||
|
Path04="..\..\resources"
|
||||||
|
Type05=Folder
|
||||||
|
Path05="D:\Backups\Warsmash\Data"
|
||||||
|
Type06=Folder
|
||||||
|
Path06="D:\Games\Warcraft III Patch 1.22\Maps"
|
||||||
|
Type07=Folder
|
||||||
|
Path07="."
|
||||||
|
|
||||||
|
[Map]
|
||||||
|
//FilePath="CombatUnitTests.w3x"
|
||||||
|
//FilePath="PitchRoll.w3x"
|
||||||
|
//FilePath="PeonStartingBase_Simple.w3x"
|
||||||
|
FilePath="PeonStartingBase_Scythe.w3x"
|
||||||
|
//FilePath="MyStromguarde.w3m"
|
||||||
|
//FilePath="ColdArrows.w3m"
|
||||||
|
//FilePath="DungeonGoldMine.w3m"
|
||||||
|
//FilePath="PlayerPeasants.w3m"
|
||||||
|
//FilePath="FireLord.w3x"
|
||||||
|
//FilePath="Maps\Campaign\NightElf03.w3m"
|
||||||
|
//FilePath="PhoenixAttack.w3x"
|
||||||
|
//FilePath="LightEnvironmentTest.w3x"
|
||||||
|
//FilePath="TorchLight2.w3x"
|
||||||
|
//FilePath="OrcAssault.w3x"
|
||||||
|
//FilePath="FrostyVsFarm.w3m"
|
||||||
|
//FilePath="ModelTest.w3x"
|
||||||
|
//FilePath="SpinningSample.w3x"
|
||||||
|
//FilePath="Maps\Campaign\Prologue02.w3m"
|
||||||
|
//FilePath="Pathing.w3x"
|
||||||
|
//FilePath="ItemFacing.w3x"
|
||||||
|
//FilePath=SomeParticleTests.w3x
|
||||||
|
//FilePath="PeonMiningMultiHall.w3x"
|
||||||
|
//FilePath="QuadtreeBugs.w3x"
|
||||||
|
//FilePath="test2.w3x"
|
||||||
|
//FilePath="FarseerHoldPositionTest.w3x"
|
||||||
|
//FilePath="Ramps.w3m"
|
||||||
|
//FilePath="V1\Farm.w3x"
|
||||||
|
//FilePath="PenguinWorld.w3x"
|
||||||
|
//FilePath="Maps\FrozenThrone\Campaign\UndeadX09.w3x"
|
||||||
|
//FilePath="LavellaLagoon.w3x"
|
||||||
|
//FilePath="WiceOrc.w3x"
|
||||||
|
//FilePath="NorthrendPathingDoodle.w3x"
|
||||||
|
//FilePath="Maps\Campaign\Prologue01.w3m"
|
26
core/assets/warsmash131.ini
Normal file
26
core/assets/warsmash131.ini
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
[DataSources]
|
||||||
|
Count=5
|
||||||
|
Type00=Folder
|
||||||
|
Path00="D:\Games\Warcraft III CASC 1.31\war3.w3mod"
|
||||||
|
Type01=Folder
|
||||||
|
Path01="D:\Games\Warcraft III CASC 1.31\war3.w3mod\_locales\enus.w3mod"
|
||||||
|
Type02=Folder
|
||||||
|
Path02="..\..\resources"
|
||||||
|
Type03=Folder
|
||||||
|
Path03="D:\Backups\Warsmash\Data"
|
||||||
|
Type04=Folder
|
||||||
|
Path04="."
|
||||||
|
|
||||||
|
[Map]
|
||||||
|
//FilePath="PitchRoll.w3x"
|
||||||
|
//FilePath="ReforgedGeorgeVacation.w3x"
|
||||||
|
//FilePath="Maps\Campaign\NightElf03.w3m"
|
||||||
|
//FilePath="PrivateDontShare/Cult 8.w3x"
|
||||||
|
//FilePath="TorchLight2.w3x"
|
||||||
|
//FilePath="OrcAssault.w3x"
|
||||||
|
//FilePath="PeonStartingBase.w3x"
|
||||||
|
//FilePath="PhoenixAttack.w3x"
|
||||||
|
//FilePath="OperationReforged.w3x"
|
||||||
|
//FilePath="AzerothRoleplay1.909t03DecoratedV2.w3x"
|
||||||
|
//FilePath="American Colo EX 1.0 unpro.w3x"
|
||||||
|
FilePath="TheSheepAttack.w3x"
|
42
core/assets/warsmash131notworking.ini
Normal file
42
core/assets/warsmash131notworking.ini
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
[DataSources]
|
||||||
|
Count=5
|
||||||
|
Type00=CASC
|
||||||
|
Path00="D:\Games\Warcraft III Patch 1.31\"
|
||||||
|
Prefixes00="war3.w3mod","war3.w3mod\_deprecated.w3mod","war3.w3mod\_locales\enus.w3mod"
|
||||||
|
Type01=Folder
|
||||||
|
Path01="..\..\resources"
|
||||||
|
Type02=Folder
|
||||||
|
Path02="D:\Backups\Warsmash\Data"
|
||||||
|
Type03=Folder
|
||||||
|
Path03="D:\Games\Warcraft III Patch 1.22\Maps"
|
||||||
|
Type04=Folder
|
||||||
|
Path04="."
|
||||||
|
|
||||||
|
[Map]
|
||||||
|
//FilePath="CombatUnitTests.w3x"
|
||||||
|
//FilePath="PitchRoll.w3x"
|
||||||
|
//FilePath="PeonStartingBase.w3x"
|
||||||
|
//FilePath="MyStromguarde.w3m"
|
||||||
|
//FilePath="ColdArrows.w3m"
|
||||||
|
//FilePath="DungeonGoldMine.w3m"
|
||||||
|
//FilePath="PlayerPeasants.w3m"
|
||||||
|
//FilePath="FireLord.w3x"
|
||||||
|
//FilePath="Maps\Campaign\NightElf03.w3m"
|
||||||
|
//FilePath="PhoenixAttack.w3x"
|
||||||
|
//FilePath="LightEnvironmentTest.w3x"
|
||||||
|
//FilePath="TorchLight2.w3x"
|
||||||
|
FilePath="OrcAssault.w3x"
|
||||||
|
//FilePath="FrostyVsFarm.w3m"
|
||||||
|
//FilePath="ModelTest.w3x"
|
||||||
|
//FilePath="SpinningSample.w3x"
|
||||||
|
//FilePath="Maps\Campaign\Prologue02.w3m"
|
||||||
|
//FilePath="Pathing.w3x"
|
||||||
|
//FilePath="ItemFacing.w3x"
|
||||||
|
//FilePath=SomeParticleTests.w3x
|
||||||
|
//FilePath="PeonMiningMultiHall.w3x"
|
||||||
|
//FilePath="QuadtreeBugs.w3x"
|
||||||
|
//FilePath="test2.w3x"
|
||||||
|
//FilePath="FarseerHoldPositionTest.w3x"
|
||||||
|
//FilePath="Ramps.w3m"
|
||||||
|
//FilePath="V1\Farm.w3x"
|
||||||
|
//FilePath="TheSheepAttack.w3x"
|
26
core/assets/warsmashPRSCMOD.ini
Normal file
26
core/assets/warsmashPRSCMOD.ini
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// This is the Warsmash INI file for Project Revolution
|
||||||
|
// PRSCMOD
|
||||||
|
|
||||||
|
[DataSources]
|
||||||
|
Count=9
|
||||||
|
Type00=MPQ
|
||||||
|
Path00="D:\Games\Warcraft III Project Revolution\War3\The Sheep Attack\war3.mpq"
|
||||||
|
Type01=MPQ
|
||||||
|
Path01="D:\Games\Warcraft III Project Revolution\War3\The Sheep Attack\War3x.mpq"
|
||||||
|
Type02=MPQ
|
||||||
|
Path02="D:\Games\Warcraft III Project Revolution\War3\The Sheep Attack\War3xlocal.mpq"
|
||||||
|
Type03=MPQ
|
||||||
|
Path03="D:\Games\Warcraft III Project Revolution\War3\The Sheep Attack\war3patch.mpq"
|
||||||
|
Type04=MPQ
|
||||||
|
Path04="D:\Games\Warcraft III Project Revolution\PRSCMOD\Revolution.mpq"
|
||||||
|
Type05=MPQ
|
||||||
|
Path05="D:\Games\Warcraft III Project Revolution\PRSCMOD\Sound.mpq"
|
||||||
|
Type06=Folder
|
||||||
|
Path06="D:\Games\Warcraft III Project Revolution\ProjectRevolusmash"
|
||||||
|
Type07=Folder
|
||||||
|
Path07="..\..\resources"
|
||||||
|
Type08=Folder
|
||||||
|
Path08="D:\Games\Warcraft III Project Revolution\PRSCMOD\PR-Maps"
|
||||||
|
|
||||||
|
[Map]
|
||||||
|
FilePath="ProjectRevolusmash.w3x"
|
41
core/assets/warsmashRF.ini
Normal file
41
core/assets/warsmashRF.ini
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
[DataSources]
|
||||||
|
Count=5
|
||||||
|
Type00=CASC
|
||||||
|
Path00="C:\Program Files\Warcraft III"
|
||||||
|
Prefixes00=war3.w3mod,war3.w3mod\_deprecated.w3mod,war3.w3mod\_locales\enus.w3mod,war3.w3mod\_hd.w3mod,war3.w3mod\_hd.w3mod\_locales\enus.w3mod
|
||||||
|
Type01=Folder
|
||||||
|
Path01="..\..\resources"
|
||||||
|
Type02=Folder
|
||||||
|
Path02="D:\Backups\Warsmash\Data"
|
||||||
|
Type03=Folder
|
||||||
|
Path03="D:\Games\Warcraft III Patch 1.22\Maps"
|
||||||
|
Type04=Folder
|
||||||
|
Path04="."
|
||||||
|
|
||||||
|
[Map]
|
||||||
|
//FilePath="CombatUnitTests.w3x"
|
||||||
|
//FilePath="PitchRoll.w3x"
|
||||||
|
FilePath="PeonStartingBase.w3x"
|
||||||
|
//FilePath="MyStromguarde.w3m"
|
||||||
|
//FilePath="ColdArrows.w3m"
|
||||||
|
//FilePath="DungeonGoldMine.w3m"
|
||||||
|
//FilePath="PlayerPeasants.w3m"
|
||||||
|
//FilePath="FireLord.w3x"
|
||||||
|
//FilePath="Maps\Campaign\NightElf03.w3m"
|
||||||
|
//FilePath="PhoenixAttack.w3x"
|
||||||
|
//FilePath="LightEnvironmentTest.w3x"
|
||||||
|
//FilePath="TorchLight2.w3x"
|
||||||
|
//FilePath="OrcAssault.w3x"
|
||||||
|
//FilePath="FrostyVsFarm.w3m"
|
||||||
|
//FilePath="ModelTest.w3x"
|
||||||
|
//FilePath="SpinningSample.w3x"
|
||||||
|
//FilePath="Maps\Campaign\Prologue02.w3m"
|
||||||
|
//FilePath="Pathing.w3x"
|
||||||
|
//FilePath="ItemFacing.w3x"
|
||||||
|
//FilePath=SomeParticleTests.w3x
|
||||||
|
//FilePath="PeonMiningMultiHall.w3x"
|
||||||
|
//FilePath="QuadtreeBugs.w3x"
|
||||||
|
//FilePath="test2.w3x"
|
||||||
|
//FilePath="FarseerHoldPositionTest.w3x"
|
||||||
|
//FilePath="Ramps.w3m"
|
||||||
|
//FilePath="V1\Farm.w3x"
|
22
core/assets/warsmashTTOR.ini
Normal file
22
core/assets/warsmashTTOR.ini
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// This is the Warsmash INI file for Project Revolution
|
||||||
|
// PRSCMOD
|
||||||
|
|
||||||
|
[DataSources]
|
||||||
|
Count=7
|
||||||
|
Type00=MPQ
|
||||||
|
Path00="D:\Games\Warcraft III Project Revolution\War3\The Sheep Attack\war3.mpq"
|
||||||
|
Type01=MPQ
|
||||||
|
Path01="D:\Games\Warcraft III Project Revolution\War3\The Sheep Attack\War3x.mpq"
|
||||||
|
Type02=MPQ
|
||||||
|
Path02="D:\Games\Warcraft III Project Revolution\War3\The Sheep Attack\War3xlocal.mpq"
|
||||||
|
Type03=MPQ
|
||||||
|
Path03="D:\Games\Warcraft III Project Revolution\War3\The Sheep Attack\war3patch_TTOR.mpq"
|
||||||
|
Type04=Folder
|
||||||
|
Path04="D:\Games\Warcraft III Project Revolution\ProjectRevolusmash"
|
||||||
|
Type05=Folder
|
||||||
|
Path05="..\..\resources"
|
||||||
|
Type06=Folder
|
||||||
|
Path06="D:\Games\Warcraft III Project Revolution\War3\The Sheep Attack\Maps"
|
||||||
|
|
||||||
|
[Map]
|
||||||
|
FilePath="(2)BootyBay.w3m"
|
22
core/assets/warsmashUF.ini
Normal file
22
core/assets/warsmashUF.ini
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// This is the Warsmash INI file for Project Revolution
|
||||||
|
// PRSCMOD
|
||||||
|
|
||||||
|
[DataSources]
|
||||||
|
Count=7
|
||||||
|
Type00=MPQ
|
||||||
|
Path00="D:\Games\Warcraft III Patch 1.27 Redownload\Warcraft III\war3.mpq"
|
||||||
|
Type01=MPQ
|
||||||
|
Path01="D:\Games\Warcraft III Patch 1.27 Redownload\Warcraft III\War3x.mpq"
|
||||||
|
Type02=MPQ
|
||||||
|
Path02="D:\Games\Warcraft III Patch 1.27 Redownload\Warcraft III\War3xlocal.mpq"
|
||||||
|
Type03=MPQ
|
||||||
|
Path03="D:\Games\Warcraft III Patch 1.27 Redownload\Warcraft III\war3patch.mpq"
|
||||||
|
Type04=MPQ
|
||||||
|
Path04="D:\Games\Warcraft III Patch 1.27 Redownload\Warcraft III\War3Mod.mpq"
|
||||||
|
Type05=Folder
|
||||||
|
Path05="..\..\resources"
|
||||||
|
Type06=Folder
|
||||||
|
Path06="D:\Games\Warcraft III Patch 1.27 Redownload\Warcraft III\Maps"
|
||||||
|
|
||||||
|
[Map]
|
||||||
|
FilePath="Maps\Campaign\Prologue01.w3m"
|
11
core/build.gradle
Normal file
11
core/build.gradle
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
apply plugin: "java"
|
||||||
|
|
||||||
|
sourceCompatibility = 1.8
|
||||||
|
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
|
||||||
|
|
||||||
|
sourceSets.main.java.srcDirs = [ "src/" ]
|
||||||
|
|
||||||
|
|
||||||
|
eclipse.project {
|
||||||
|
name = appName + "-core"
|
||||||
|
}
|
35
core/src/com/etheller/warsmash/CodeCounter.java
Normal file
35
core/src/com/etheller/warsmash/CodeCounter.java
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package com.etheller.warsmash;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
|
||||||
|
public class CodeCounter {
|
||||||
|
|
||||||
|
public static void main(final String[] args) {
|
||||||
|
final int sourceLines = countFile(new File("src/com"));
|
||||||
|
System.out.println(sourceLines);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int countFile(final File file) {
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
int sum = 0;
|
||||||
|
for (final File subFile : file.listFiles()) {
|
||||||
|
sum += countFile(subFile);
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
try {
|
||||||
|
if (file.getName().toLowerCase().endsWith(".java")) {
|
||||||
|
return Files.readAllLines(file.toPath()).size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (final IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
61
core/src/com/etheller/warsmash/MathSpeedBenchmark.java
Normal file
61
core/src/com/etheller/warsmash/MathSpeedBenchmark.java
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
package com.etheller.warsmash;
|
||||||
|
|
||||||
|
public class MathSpeedBenchmark {
|
||||||
|
private static final int NUMBER_OF_ITERATIONS = 100000000;
|
||||||
|
|
||||||
|
public static void main(final String[] args) {
|
||||||
|
// Let us solve for Ground Distance two ways.
|
||||||
|
|
||||||
|
long sumCosineTime = 0;
|
||||||
|
long sumSquareRootTime = 0;
|
||||||
|
final float[] thrallXs = new float[NUMBER_OF_ITERATIONS];
|
||||||
|
final float[] thrallYs = new float[NUMBER_OF_ITERATIONS];
|
||||||
|
final float[] murlocXs = new float[NUMBER_OF_ITERATIONS];
|
||||||
|
final float[] murlocYs = new float[NUMBER_OF_ITERATIONS];
|
||||||
|
for (int i = 0; i < NUMBER_OF_ITERATIONS; i++) {
|
||||||
|
|
||||||
|
thrallXs[i] = getRandomFloat(-25000.0f, 25000.0f);
|
||||||
|
thrallYs[i] = getRandomFloat(-25000.0f, 25000.0f);
|
||||||
|
murlocXs[i] = getRandomFloat(-25000.0f, 25000.0f);
|
||||||
|
murlocYs[i] = getRandomFloat(-25000.0f, 25000.0f);
|
||||||
|
}
|
||||||
|
final long clockTime1 = System.currentTimeMillis();
|
||||||
|
for (int i = 0; i < NUMBER_OF_ITERATIONS; i++) {
|
||||||
|
final float distance2 = groundDistanceSqrt(thrallXs[i], thrallYs[i], murlocXs[i], murlocYs[i]);
|
||||||
|
}
|
||||||
|
final long clockTime2 = System.currentTimeMillis();
|
||||||
|
for (int i = 0; i < NUMBER_OF_ITERATIONS; i++) {
|
||||||
|
final float distance1 = groundDistanceCos(thrallXs[i], thrallYs[i], murlocXs[i], murlocYs[i]);
|
||||||
|
}
|
||||||
|
final long clockTime3 = System.currentTimeMillis();
|
||||||
|
// if (Math.abs(distance2 - distance1) > 0.1) {
|
||||||
|
// System.out.println(thrallX + "," + thrallY);
|
||||||
|
// System.out.println(murlocX + "," + murlocY);
|
||||||
|
// System.err.println(distance1 + " != " + distance2);
|
||||||
|
// throw new RuntimeException("You have failed to do mathematics.");
|
||||||
|
// }
|
||||||
|
sumCosineTime = clockTime2 - clockTime1;
|
||||||
|
sumSquareRootTime = clockTime3 - clockTime2;
|
||||||
|
System.out.println("Square Root: " + sumCosineTime);
|
||||||
|
System.out.println("Cosine: " + sumSquareRootTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
static float getRandomFloat(final float min, final float max) {
|
||||||
|
final float range = max - min;
|
||||||
|
return (float) ((Math.random() * range) + min);
|
||||||
|
}
|
||||||
|
|
||||||
|
static float groundDistanceSqrt(final float thrallX, final float thrallY, final float murlocX,
|
||||||
|
final float murlocY) {
|
||||||
|
final float dx = murlocX - thrallX;
|
||||||
|
final float dy = murlocY - thrallY;
|
||||||
|
return (float) StrictMath.sqrt((dx * dx) + (dy * dy));
|
||||||
|
}
|
||||||
|
|
||||||
|
static float groundDistanceCos(final float thrallX, final float thrallY, final float murlocX, final float murlocY) {
|
||||||
|
final float dx = murlocX - thrallX;
|
||||||
|
final float dy = murlocY - thrallY;
|
||||||
|
final double angle = StrictMath.atan2(dy, dx);
|
||||||
|
return (float) (dx / StrictMath.cos(angle));
|
||||||
|
}
|
||||||
|
}
|
5
core/src/com/etheller/warsmash/SingleModelScreen.java
Normal file
5
core/src/com/etheller/warsmash/SingleModelScreen.java
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package com.etheller.warsmash;
|
||||||
|
|
||||||
|
public interface SingleModelScreen {
|
||||||
|
void setModel(String path);
|
||||||
|
}
|
36
core/src/com/etheller/warsmash/TestMain.java
Normal file
36
core/src/com/etheller/warsmash/TestMain.java
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package com.etheller.warsmash;
|
||||||
|
|
||||||
|
import com.etheller.warsmash.util.War3ID;
|
||||||
|
|
||||||
|
public class TestMain {
|
||||||
|
public static void main(final String[] args) {
|
||||||
|
if (true) {
|
||||||
|
System.out.println(War3ID.fromString("hwat").getValue());
|
||||||
|
System.out.println(Integer.toHexString(War3ID.fromString("hwat").getValue()));
|
||||||
|
System.out.println(new War3ID(0x68776174));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// System.out.println(Integer.parseInt("4294967295"));
|
||||||
|
for (int i = 1; i <= 30; i++) {
|
||||||
|
// System.out.println(a(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
int checkX = 0;
|
||||||
|
int checkY = 0;
|
||||||
|
for (int i = 0; i < 300; i++) {
|
||||||
|
System.out.println(checkX + "," + checkY);
|
||||||
|
final double angle = ((((int) Math.floor(Math.sqrt((4 * i) + 1))) % 4) * Math.PI) / 2;
|
||||||
|
checkX += (int) Math.sin(angle);
|
||||||
|
checkY += (int) Math.cos(angle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int a(final int n) {
|
||||||
|
if (n == 1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return a(n - 1) - (int) Math.sin(((Math.floor(Math.sqrt((4 * (n - 2)) + 1)) % 4) * Math.PI) / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
535
core/src/com/etheller/warsmash/WarsmashGdxGame.java
Normal file
535
core/src/com/etheller/warsmash/WarsmashGdxGame.java
Normal file
@ -0,0 +1,535 @@
|
|||||||
|
package com.etheller.warsmash;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.nio.IntBuffer;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.ApplicationAdapter;
|
||||||
|
import com.badlogic.gdx.Gdx;
|
||||||
|
import com.badlogic.gdx.audio.Music;
|
||||||
|
import com.badlogic.gdx.graphics.GL20;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||||
|
import com.badlogic.gdx.math.Quaternion;
|
||||||
|
import com.badlogic.gdx.math.Rectangle;
|
||||||
|
import com.badlogic.gdx.math.Vector3;
|
||||||
|
import com.etheller.warsmash.datasources.DataSource;
|
||||||
|
import com.etheller.warsmash.units.DataTable;
|
||||||
|
import com.etheller.warsmash.util.DataSourceFileHandle;
|
||||||
|
import com.etheller.warsmash.viewer5.Camera;
|
||||||
|
import com.etheller.warsmash.viewer5.CanvasProvider;
|
||||||
|
import com.etheller.warsmash.viewer5.ModelViewer;
|
||||||
|
import com.etheller.warsmash.viewer5.PathSolver;
|
||||||
|
import com.etheller.warsmash.viewer5.Scene;
|
||||||
|
import com.etheller.warsmash.viewer5.SolvedPath;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.mdx.MdxComplexInstance;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.mdx.MdxHandler;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.mdx.MdxModel;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.mdx.MdxViewer;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.mdx.Sequence;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.mdx.SequenceLoopMode;
|
||||||
|
|
||||||
|
public class WarsmashGdxGame extends ApplicationAdapter implements CanvasProvider {
|
||||||
|
private static final boolean SPIN = false;
|
||||||
|
private static final boolean ADVANCE_ANIMS = true;
|
||||||
|
private DataSource codebase;
|
||||||
|
private ModelViewer viewer;
|
||||||
|
private MdxModel model;
|
||||||
|
private CameraManager cameraManager;
|
||||||
|
public static int VAO;
|
||||||
|
private final Rectangle tempRect = new Rectangle();
|
||||||
|
|
||||||
|
private BitmapFont font;
|
||||||
|
private SpriteBatch batch;
|
||||||
|
private final DataTable warsmashIni;
|
||||||
|
|
||||||
|
public WarsmashGdxGame(final DataTable warsmashIni) {
|
||||||
|
this.warsmashIni = warsmashIni;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void create() {
|
||||||
|
|
||||||
|
final ByteBuffer tempByteBuffer = ByteBuffer.allocateDirect(4);
|
||||||
|
tempByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
final IntBuffer temp = tempByteBuffer.asIntBuffer();
|
||||||
|
//
|
||||||
|
Gdx.gl30.glGenVertexArrays(1, temp);
|
||||||
|
VAO = temp.get(0);
|
||||||
|
|
||||||
|
Gdx.gl30.glBindVertexArray(VAO);
|
||||||
|
|
||||||
|
final String renderer = Gdx.gl.glGetString(GL20.GL_RENDERER);
|
||||||
|
System.err.println("Renderer: " + renderer);
|
||||||
|
|
||||||
|
this.codebase = WarsmashGdxMapScreen.parseDataSources(this.warsmashIni);
|
||||||
|
this.viewer = new MdxViewer(this.codebase, this, new Vector3(0.3f, 0.3f, -0.25f));
|
||||||
|
|
||||||
|
this.viewer.addHandler(new MdxHandler());
|
||||||
|
this.viewer.enableAudio();
|
||||||
|
|
||||||
|
final Scene scene = this.viewer.addSimpleScene();
|
||||||
|
scene.enableAudio();
|
||||||
|
|
||||||
|
this.cameraManager = new CameraManager();
|
||||||
|
this.cameraManager.setupCamera(scene);
|
||||||
|
|
||||||
|
final String musicPath = "Sound\\Music\\mp3Music\\Mainscreen.mp3";
|
||||||
|
final Music music = Gdx.audio.newMusic(new DataSourceFileHandle(this.viewer.dataSource, musicPath));
|
||||||
|
// music.setVolume(0.2f);
|
||||||
|
music.setLooping(true);
|
||||||
|
music.play();
|
||||||
|
|
||||||
|
// this.mainModel = (MdxModel) this.viewer.load("Doodads\\Cinematic\\ArthasIllidanFight\\ArthasIllidanFight.mdx",
|
||||||
|
// this.mainModel = (MdxModel) this.viewer.load("UI\\Glues\\SinglePlayer\\NightElf_Exp\\NightElf_Exp.mdx",
|
||||||
|
// this.mainModel = (MdxModel) this.viewer.load("Abilities\\Spells\\Orc\\FeralSpirit\\feralspirittarget.mdx",
|
||||||
|
// new PathSolver() {
|
||||||
|
// @Override
|
||||||
|
// public SolvedPath solve(final String src, final Object solverParams) {
|
||||||
|
// return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
|
||||||
|
// }
|
||||||
|
// }, null);
|
||||||
|
|
||||||
|
// final EventObjectEmitterObject evt = this.mainModel.getEventObjects().get(1);
|
||||||
|
// for (final Sequence seq : this.mainModel.getSequences()) {
|
||||||
|
// System.out.println(seq.getName() + ": " + Arrays.toString(seq.getInterval()));
|
||||||
|
// }
|
||||||
|
// System.out.println(Arrays.toString(evt.keyFrames));
|
||||||
|
// System.out.println(evt.name);
|
||||||
|
|
||||||
|
// this.mainInstance = (MdxComplexInstance) this.mainModel.addInstance(0);
|
||||||
|
|
||||||
|
// this.mainInstance.setScene(scene);
|
||||||
|
//
|
||||||
|
// final int animIndex = 0;
|
||||||
|
// this.modelCamera = this.mainModel.cameras.get(animIndex);
|
||||||
|
// this.mainInstance.setSequence(animIndex);
|
||||||
|
//
|
||||||
|
// this.mainInstance.setSequenceLoopMode(SequenceLoopMode.LOOP_TO_NEXT_ANIMATION);
|
||||||
|
|
||||||
|
// acolytesHarvestingSceneJoke2(scene);
|
||||||
|
|
||||||
|
// singleModelScene(scene, "Buildings\\Undead\\Necropolis\\Necropolis.mdx", "birth");
|
||||||
|
// singleModelScene(scene, "Units\\Orc\\KotoBeast\\KotoBeast.mdx", "spell slam");
|
||||||
|
singleModelScene(scene, "UI\\Glues\\MainMenu\\MainMenu3D\\MainMenu3D.mdx", "Stand");
|
||||||
|
this.modelCamera = this.mainModel.cameras.get(0);
|
||||||
|
|
||||||
|
System.out.println("Loaded");
|
||||||
|
Gdx.gl30.glClearColor(0.5f, 0.5f, 0.5f, 1); // TODO remove white background
|
||||||
|
|
||||||
|
this.font = new BitmapFont();
|
||||||
|
this.batch = new SpriteBatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makeDruidSquare(final Scene scene) {
|
||||||
|
final MdxModel model2 = (MdxModel) this.viewer.load("units\\nightelf\\druidoftheclaw\\druidoftheclaw.mdx",
|
||||||
|
new PathSolver() {
|
||||||
|
@Override
|
||||||
|
public SolvedPath solve(final String src, final Object solverParams) {
|
||||||
|
return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
makePerfectSquare(scene, model2, 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void singleAcolyteScene(final Scene scene) {
|
||||||
|
final MdxModel model2 = (MdxModel) this.viewer.load("units\\undead\\acolyte\\acolyte.mdx", new PathSolver() {
|
||||||
|
@Override
|
||||||
|
public SolvedPath solve(final String src, final Object solverParams) {
|
||||||
|
return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
|
||||||
|
final MdxComplexInstance instance3 = (MdxComplexInstance) model2.addInstance(0);
|
||||||
|
|
||||||
|
instance3.setScene(scene);
|
||||||
|
|
||||||
|
int animIndex = 0;
|
||||||
|
for (final Sequence s : model2.getSequences()) {
|
||||||
|
if (s.getName().toLowerCase().startsWith("stand work")) {
|
||||||
|
animIndex = model2.getSequences().indexOf(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
instance3.setSequence(animIndex);
|
||||||
|
|
||||||
|
instance3.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void singleModelScene(final Scene scene, final String path, final String animName) {
|
||||||
|
final MdxModel model2 = (MdxModel) this.viewer.load(path, new PathSolver() {
|
||||||
|
@Override
|
||||||
|
public SolvedPath solve(final String src, final Object solverParams) {
|
||||||
|
return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
|
||||||
|
final MdxComplexInstance instance3 = (MdxComplexInstance) model2.addInstance(0);
|
||||||
|
|
||||||
|
instance3.setScene(scene);
|
||||||
|
|
||||||
|
int animIndex = 0;
|
||||||
|
for (final Sequence s : model2.getSequences()) {
|
||||||
|
if (s.getName().toLowerCase().startsWith(animName)) {
|
||||||
|
animIndex = model2.getSequences().indexOf(s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
instance3.setSequence(animIndex);
|
||||||
|
|
||||||
|
instance3.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
|
||||||
|
this.mainInstance = instance3;
|
||||||
|
this.mainModel = model2;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void acolytesHarvestingScene(final Scene scene) {
|
||||||
|
|
||||||
|
final MdxModel acolyteModel = (MdxModel) this.viewer.load("units\\undead\\acolyte\\acolyte.mdx",
|
||||||
|
new PathSolver() {
|
||||||
|
@Override
|
||||||
|
public SolvedPath solve(final String src, final Object solverParams) {
|
||||||
|
return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
final MdxModel mineEffectModel = (MdxModel) this.viewer
|
||||||
|
.load("abilities\\spells\\undead\\undeadmine\\undeadminecircle.mdx", new PathSolver() {
|
||||||
|
@Override
|
||||||
|
public SolvedPath solve(final String src, final Object solverParams) {
|
||||||
|
return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
final MdxComplexInstance acolyteInstance = (MdxComplexInstance) acolyteModel.addInstance(0);
|
||||||
|
|
||||||
|
acolyteInstance.setScene(scene);
|
||||||
|
|
||||||
|
int animIndex = i % acolyteModel.getSequences().size();
|
||||||
|
for (final Sequence s : acolyteModel.getSequences()) {
|
||||||
|
if (s.getName().toLowerCase().startsWith("stand work")) {
|
||||||
|
animIndex = acolyteModel.getSequences().indexOf(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
acolyteInstance.setSequence(animIndex);
|
||||||
|
|
||||||
|
acolyteInstance.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
|
||||||
|
|
||||||
|
final double angle = ((Math.PI * 2) / 5) * i;
|
||||||
|
acolyteInstance.localLocation.x = (float) Math.cos(angle) * 256;
|
||||||
|
acolyteInstance.localLocation.y = (float) Math.sin(angle) * 256;
|
||||||
|
acolyteInstance.localRotation.setFromAxisRad(0, 0, 1, (float) (angle + Math.PI));
|
||||||
|
|
||||||
|
final MdxComplexInstance effectInstance = (MdxComplexInstance) mineEffectModel.addInstance(0);
|
||||||
|
|
||||||
|
effectInstance.setScene(scene);
|
||||||
|
|
||||||
|
effectInstance.setSequence(1);
|
||||||
|
|
||||||
|
effectInstance.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
|
||||||
|
effectInstance.localLocation.x = (float) Math.cos(angle) * 256;
|
||||||
|
effectInstance.localLocation.y = (float) Math.sin(angle) * 256;
|
||||||
|
effectInstance.localRotation.setFromAxisRad(0, 0, 1, (float) (angle));
|
||||||
|
|
||||||
|
}
|
||||||
|
final MdxModel mineModel = (MdxModel) this.viewer.load("buildings\\undead\\hauntedmine\\hauntedmine.mdx",
|
||||||
|
new PathSolver() {
|
||||||
|
@Override
|
||||||
|
public SolvedPath solve(final String src, final Object solverParams) {
|
||||||
|
return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
final MdxComplexInstance mineInstance = (MdxComplexInstance) mineModel.addInstance(0);
|
||||||
|
|
||||||
|
mineInstance.setScene(scene);
|
||||||
|
|
||||||
|
mineInstance.setSequence(2);
|
||||||
|
|
||||||
|
mineInstance.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void acolytesHarvestingSceneJoke2(final Scene scene) {
|
||||||
|
|
||||||
|
final MdxModel acolyteModel = (MdxModel) this.viewer.load("units\\undead\\acolyte\\acolyte.mdx",
|
||||||
|
new PathSolver() {
|
||||||
|
@Override
|
||||||
|
public SolvedPath solve(final String src, final Object solverParams) {
|
||||||
|
return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
final MdxModel mineEffectModel = (MdxModel) this.viewer
|
||||||
|
.load("abilities\\spells\\undead\\undeadmine\\undeadminecircle.mdx", new PathSolver() {
|
||||||
|
@Override
|
||||||
|
public SolvedPath solve(final String src, final Object solverParams) {
|
||||||
|
return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
final MdxComplexInstance acolyteInstance = (MdxComplexInstance) acolyteModel.addInstance(0);
|
||||||
|
|
||||||
|
acolyteInstance.setScene(scene);
|
||||||
|
|
||||||
|
int animIndex = i % acolyteModel.getSequences().size();
|
||||||
|
for (final Sequence s : acolyteModel.getSequences()) {
|
||||||
|
if (s.getName().toLowerCase().startsWith("stand work")) {
|
||||||
|
animIndex = acolyteModel.getSequences().indexOf(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
acolyteInstance.setSequence(animIndex);
|
||||||
|
|
||||||
|
acolyteInstance.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
|
||||||
|
|
||||||
|
final double angle = ((Math.PI * 2) / 5) * i;
|
||||||
|
acolyteInstance.localLocation.x = (float) Math.cos(angle) * 256;
|
||||||
|
acolyteInstance.localLocation.y = (float) Math.sin(angle) * 256;
|
||||||
|
acolyteInstance.localRotation.setFromAxisRad(0, 0, 1, (float) (angle + Math.PI));
|
||||||
|
|
||||||
|
final MdxComplexInstance effectInstance = (MdxComplexInstance) mineEffectModel.addInstance(0);
|
||||||
|
|
||||||
|
effectInstance.setScene(scene);
|
||||||
|
|
||||||
|
effectInstance.setSequence(1);
|
||||||
|
|
||||||
|
effectInstance.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
|
||||||
|
effectInstance.localLocation.x = (float) Math.cos(angle) * 256;
|
||||||
|
effectInstance.localLocation.y = (float) Math.sin(angle) * 256;
|
||||||
|
effectInstance.localRotation.setFromAxisRad(0, 0, 1, (float) (angle));
|
||||||
|
|
||||||
|
}
|
||||||
|
final MdxModel mineModel = (MdxModel) this.viewer.load("units\\orc\\spiritwolf\\spiritwolf.mdx",
|
||||||
|
new PathSolver() {
|
||||||
|
@Override
|
||||||
|
public SolvedPath solve(final String src, final Object solverParams) {
|
||||||
|
return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
final MdxComplexInstance mineInstance = (MdxComplexInstance) mineModel.addInstance(0);
|
||||||
|
|
||||||
|
mineInstance.setScene(scene);
|
||||||
|
|
||||||
|
mineInstance.setSequence(0);
|
||||||
|
mineInstance.localScale.x = 2;
|
||||||
|
mineInstance.localScale.y = 2;
|
||||||
|
mineInstance.localScale.z = 2;
|
||||||
|
|
||||||
|
mineInstance.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
|
||||||
|
final MdxModel mineModel2 = (MdxModel) this.viewer
|
||||||
|
.load("abilities\\spells\\undead\\unsummon\\unsummontarget.mdx", new PathSolver() {
|
||||||
|
@Override
|
||||||
|
public SolvedPath solve(final String src, final Object solverParams) {
|
||||||
|
return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
final MdxComplexInstance mineInstance2 = (MdxComplexInstance) mineModel2.addInstance(0);
|
||||||
|
|
||||||
|
mineInstance2.setScene(scene);
|
||||||
|
|
||||||
|
mineInstance2.setSequence(0);
|
||||||
|
|
||||||
|
mineInstance2.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makeFourHundred(final Scene scene, final MdxModel model2) {
|
||||||
|
for (int i = 0; i < 400; i++) {
|
||||||
|
final MdxComplexInstance instance3 = (MdxComplexInstance) model2.addInstance(0);
|
||||||
|
instance3.localLocation.x = (((i % 20) - 10) * 128);
|
||||||
|
instance3.localLocation.y = (((i / 20) - 10) * 128);
|
||||||
|
|
||||||
|
instance3.setScene(scene);
|
||||||
|
|
||||||
|
final int animIndex = i % model2.getSequences().size();
|
||||||
|
instance3.setSequence(animIndex);
|
||||||
|
|
||||||
|
instance3.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makePerfectSquare(final Scene scene, final MdxModel model2, final int n) {
|
||||||
|
final int n2 = n * n;
|
||||||
|
for (int i = 0; i < n2; i++) {
|
||||||
|
final MdxComplexInstance instance3 = (MdxComplexInstance) model2.addInstance(0);
|
||||||
|
instance3.localLocation.x = (((i % n) - (n / 2)) * 128);
|
||||||
|
instance3.localLocation.y = (((i / n) - (n / 2)) * 128);
|
||||||
|
|
||||||
|
instance3.setScene(scene);
|
||||||
|
|
||||||
|
final int animIndex = i % model2.getSequences().size();
|
||||||
|
instance3.setSequence(animIndex);
|
||||||
|
|
||||||
|
instance3.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void bindDefaultVertexArray() {
|
||||||
|
Gdx.gl30.glBindVertexArray(VAO);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int frame = 0;
|
||||||
|
private MdxComplexInstance mainInstance;
|
||||||
|
private MdxModel mainModel;
|
||||||
|
private com.etheller.warsmash.viewer5.handlers.mdx.Camera modelCamera;
|
||||||
|
private final float[] cameraPositionTemp = new float[3];
|
||||||
|
private final float[] cameraTargetTemp = new float[3];
|
||||||
|
private final boolean firstFrame = true;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render() {
|
||||||
|
Gdx.gl30.glBindVertexArray(VAO);
|
||||||
|
if (SPIN) {
|
||||||
|
this.cameraManager.horizontalAngle += 0.0001;
|
||||||
|
if (this.cameraManager.horizontalAngle > (2 * Math.PI)) {
|
||||||
|
this.cameraManager.horizontalAngle = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// this.modelCamera = this.mainModel.cameras.get(this.mainInstance.sequence);
|
||||||
|
this.cameraManager.updateCamera();
|
||||||
|
this.viewer.updateAndRender();
|
||||||
|
|
||||||
|
// gl.glDrawElements(GL20.GL_TRIANGLES, this.elements, GL20.GL_UNSIGNED_SHORT, this.faceOffset);
|
||||||
|
|
||||||
|
// this.batch.begin();
|
||||||
|
// this.font.draw(this.batch, Integer.toString(Gdx.graphics.getFramesPerSecond()), 0, 0);
|
||||||
|
// this.batch.end();
|
||||||
|
|
||||||
|
this.frame++;
|
||||||
|
if ((this.frame % 1000) == 0) {
|
||||||
|
System.out.println(Integer.toString(Gdx.graphics.getFramesPerSecond()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ADVANCE_ANIMS && this.mainInstance.sequenceEnded) {
|
||||||
|
final int sequence = (this.mainInstance.sequence + 1) % this.mainModel.getSequences().size();
|
||||||
|
this.mainInstance.setSequence(sequence);
|
||||||
|
this.mainInstance.frame += (int) (Gdx.graphics.getRawDeltaTime() * 1000);
|
||||||
|
}
|
||||||
|
// if (this.firstFrame) {
|
||||||
|
// final Music music = Gdx.audio.newMusic(new DataSourceFileHandle(this.viewer.dataSource,
|
||||||
|
// "Sound\\Ambient\\DoodadEffects\\FinalCinematic.mp3"));
|
||||||
|
// music.setVolume(0.2f);
|
||||||
|
// music.setLooping(true);
|
||||||
|
// music.play();
|
||||||
|
// this.firstFrame = false;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getWidth() {
|
||||||
|
return Gdx.graphics.getWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getHeight() {
|
||||||
|
return Gdx.graphics.getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resize(final int width, final int height) {
|
||||||
|
this.tempRect.width = width;
|
||||||
|
this.tempRect.height = height;
|
||||||
|
this.cameraManager.camera.viewport(this.tempRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
class CameraManager {
|
||||||
|
private CanvasProvider canvas;
|
||||||
|
private Camera camera;
|
||||||
|
private float moveSpeed;
|
||||||
|
private float rotationSpeed;
|
||||||
|
private float zoomFactor;
|
||||||
|
private float horizontalAngle;
|
||||||
|
private float verticalAngle;
|
||||||
|
private float distance;
|
||||||
|
private Vector3 position;
|
||||||
|
private Vector3 target;
|
||||||
|
private Vector3 worldUp;
|
||||||
|
private Vector3 vecHeap;
|
||||||
|
private Vector3 vecHeap2;
|
||||||
|
private Quaternion quatHeap;
|
||||||
|
private Quaternion quatHeap2;
|
||||||
|
|
||||||
|
// An orbit camera setup example.
|
||||||
|
// Left mouse button controls the orbit itself.
|
||||||
|
// The right mouse button allows to move the camera and the point it's looking
|
||||||
|
// at on the XY plane.
|
||||||
|
// Scrolling zooms in and out.
|
||||||
|
private void setupCamera(final Scene scene) {
|
||||||
|
this.canvas = scene.viewer.canvas;
|
||||||
|
this.camera = scene.camera;
|
||||||
|
this.moveSpeed = 2;
|
||||||
|
this.rotationSpeed = (float) (Math.PI / 180);
|
||||||
|
this.zoomFactor = 0.1f;
|
||||||
|
this.horizontalAngle = (float) (Math.PI / 2);
|
||||||
|
this.verticalAngle = (float) (Math.PI / 4);
|
||||||
|
this.distance = 500;
|
||||||
|
this.position = new Vector3();
|
||||||
|
this.target = new Vector3(0, 0, 50);
|
||||||
|
this.worldUp = new Vector3(0, 0, 1);
|
||||||
|
this.vecHeap = new Vector3();
|
||||||
|
this.vecHeap2 = new Vector3();
|
||||||
|
this.quatHeap = new Quaternion();
|
||||||
|
this.quatHeap2 = new Quaternion();
|
||||||
|
|
||||||
|
updateCamera();
|
||||||
|
|
||||||
|
// cameraUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateCamera() {
|
||||||
|
// Limit the vertical angle so it doesn't flip.
|
||||||
|
// Since the camera uses a quaternion, flips don't matter to it, but this feels
|
||||||
|
// better.
|
||||||
|
this.verticalAngle = (float) Math.min(Math.max(0.01, this.verticalAngle), Math.PI - 0.01);
|
||||||
|
|
||||||
|
this.quatHeap.idt();
|
||||||
|
this.quatHeap.setFromAxisRad(0, 0, 1, this.horizontalAngle);
|
||||||
|
this.quatHeap2.idt();
|
||||||
|
this.quatHeap2.setFromAxisRad(1, 0, 0, this.verticalAngle);
|
||||||
|
this.quatHeap.mul(this.quatHeap2);
|
||||||
|
|
||||||
|
this.position.set(0, 0, 1);
|
||||||
|
this.quatHeap.transform(this.position);
|
||||||
|
this.position.scl(this.distance);
|
||||||
|
this.position = this.position.add(this.target);
|
||||||
|
if (WarsmashGdxGame.this.modelCamera != null) {
|
||||||
|
WarsmashGdxGame.this.modelCamera.getPositionTranslation(WarsmashGdxGame.this.cameraPositionTemp,
|
||||||
|
WarsmashGdxGame.this.mainInstance.sequence, WarsmashGdxGame.this.mainInstance.frame,
|
||||||
|
WarsmashGdxGame.this.mainInstance.counter);
|
||||||
|
WarsmashGdxGame.this.modelCamera.getTargetTranslation(WarsmashGdxGame.this.cameraTargetTemp,
|
||||||
|
WarsmashGdxGame.this.mainInstance.sequence, WarsmashGdxGame.this.mainInstance.frame,
|
||||||
|
WarsmashGdxGame.this.mainInstance.counter);
|
||||||
|
|
||||||
|
this.position.set(WarsmashGdxGame.this.modelCamera.position);
|
||||||
|
this.target.set(WarsmashGdxGame.this.modelCamera.targetPosition);
|
||||||
|
// this.vecHeap2.set(this.target);
|
||||||
|
// this.vecHeap2.sub(this.position);
|
||||||
|
// this.vecHeap.set(this.vecHeap2);
|
||||||
|
// this.vecHeap.crs(this.worldUp);
|
||||||
|
// this.vecHeap.crs(this.vecHeap2);
|
||||||
|
// this.vecHeap.nor();
|
||||||
|
// this.vecHeap.scl(this.camera.rect.height / 2f);
|
||||||
|
// this.position.add(this.vecHeap);
|
||||||
|
|
||||||
|
this.position.add(WarsmashGdxGame.this.cameraPositionTemp[0],
|
||||||
|
WarsmashGdxGame.this.cameraPositionTemp[1], WarsmashGdxGame.this.cameraPositionTemp[2]);
|
||||||
|
this.target.add(WarsmashGdxGame.this.cameraTargetTemp[0], WarsmashGdxGame.this.cameraTargetTemp[1],
|
||||||
|
WarsmashGdxGame.this.cameraTargetTemp[2]);
|
||||||
|
this.camera.perspective(WarsmashGdxGame.this.modelCamera.fieldOfView * 0.75f,
|
||||||
|
Gdx.graphics.getWidth() / (float) Gdx.graphics.getHeight(),
|
||||||
|
WarsmashGdxGame.this.modelCamera.nearClippingPlane,
|
||||||
|
WarsmashGdxGame.this.modelCamera.farClippingPlane);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.camera.perspective(70, this.camera.getAspect(), 100, 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.camera.moveToAndFace(this.position, this.target, this.worldUp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// private void cameraUpdate() {
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataSource getCodebase() {
|
||||||
|
return this.codebase;
|
||||||
|
}
|
||||||
|
}
|
517
core/src/com/etheller/warsmash/WarsmashGdxMapScreen.java
Normal file
517
core/src/com/etheller/warsmash/WarsmashGdxMapScreen.java
Normal file
@ -0,0 +1,517 @@
|
|||||||
|
package com.etheller.warsmash;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.nio.IntBuffer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.Gdx;
|
||||||
|
import com.badlogic.gdx.InputProcessor;
|
||||||
|
import com.badlogic.gdx.Screen;
|
||||||
|
import com.badlogic.gdx.audio.Music;
|
||||||
|
import com.badlogic.gdx.graphics.GL20;
|
||||||
|
import com.badlogic.gdx.graphics.GL30;
|
||||||
|
import com.badlogic.gdx.graphics.OrthographicCamera;
|
||||||
|
import com.badlogic.gdx.graphics.Texture;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||||
|
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
|
||||||
|
import com.badlogic.gdx.math.Matrix4;
|
||||||
|
import com.badlogic.gdx.math.Rectangle;
|
||||||
|
import com.badlogic.gdx.utils.viewport.ExtendViewport;
|
||||||
|
import com.etheller.warsmash.datasources.CascDataSourceDescriptor;
|
||||||
|
import com.etheller.warsmash.datasources.CompoundDataSourceDescriptor;
|
||||||
|
import com.etheller.warsmash.datasources.DataSource;
|
||||||
|
import com.etheller.warsmash.datasources.DataSourceDescriptor;
|
||||||
|
import com.etheller.warsmash.datasources.FolderDataSourceDescriptor;
|
||||||
|
import com.etheller.warsmash.datasources.MpqDataSourceDescriptor;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.GameUI;
|
||||||
|
import com.etheller.warsmash.parsers.jass.Jass2.RootFrameListener;
|
||||||
|
import com.etheller.warsmash.units.DataTable;
|
||||||
|
import com.etheller.warsmash.units.Element;
|
||||||
|
import com.etheller.warsmash.util.DataSourceFileHandle;
|
||||||
|
import com.etheller.warsmash.util.ImageUtils;
|
||||||
|
import com.etheller.warsmash.util.WarsmashConstants;
|
||||||
|
import com.etheller.warsmash.viewer5.Model;
|
||||||
|
import com.etheller.warsmash.viewer5.ModelInstance;
|
||||||
|
import com.etheller.warsmash.viewer5.ModelViewer;
|
||||||
|
import com.etheller.warsmash.viewer5.PathSolver;
|
||||||
|
import com.etheller.warsmash.viewer5.RenderBatch;
|
||||||
|
import com.etheller.warsmash.viewer5.Scene;
|
||||||
|
import com.etheller.warsmash.viewer5.TextureMapper;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.ModelHandler;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.mdx.MdxModel;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.w3x.War3MapViewer;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.w3x.camera.CameraPreset;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.w3x.camera.CameraRates;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayerUnitOrderExecutor;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.w3x.ui.MeleeUI;
|
||||||
|
|
||||||
|
public class WarsmashGdxMapScreen implements InputProcessor, Screen {
|
||||||
|
public static final boolean ENABLE_AUDIO = true;
|
||||||
|
private static final boolean ENABLE_MUSIC = false;
|
||||||
|
private final War3MapViewer viewer;
|
||||||
|
private final Rectangle tempRect = new Rectangle();
|
||||||
|
|
||||||
|
// libGDX stuff
|
||||||
|
private OrthographicCamera uiCamera;
|
||||||
|
private SpriteBatch batch;
|
||||||
|
private ExtendViewport uiViewport;
|
||||||
|
private GlyphLayout glyphLayout;
|
||||||
|
|
||||||
|
private Texture solidGreenTexture;
|
||||||
|
|
||||||
|
private ShapeRenderer shapeRenderer;
|
||||||
|
|
||||||
|
private MdxModel timeIndicator;
|
||||||
|
|
||||||
|
private Scene uiScene;
|
||||||
|
private MeleeUI meleeUI;
|
||||||
|
|
||||||
|
private Music currentMusic;
|
||||||
|
private final WarsmashGdxMultiScreenGame screenManager;
|
||||||
|
private final WarsmashGdxMenuScreen menuScreen;
|
||||||
|
|
||||||
|
public WarsmashGdxMapScreen(final War3MapViewer mapViewer, final WarsmashGdxMultiScreenGame screenManager,
|
||||||
|
final WarsmashGdxMenuScreen menuScreen) {
|
||||||
|
this.viewer = mapViewer;
|
||||||
|
this.screenManager = screenManager;
|
||||||
|
this.menuScreen = menuScreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see com.badlogic.gdx.ApplicationAdapter#create()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void show() {
|
||||||
|
|
||||||
|
final ByteBuffer tempByteBuffer = ByteBuffer.allocateDirect(4);
|
||||||
|
tempByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
final IntBuffer temp = tempByteBuffer.asIntBuffer();
|
||||||
|
|
||||||
|
Gdx.gl30.glGenVertexArrays(1, temp);
|
||||||
|
WarsmashGdxGame.VAO = temp.get(0);
|
||||||
|
|
||||||
|
Gdx.gl30.glBindVertexArray(WarsmashGdxGame.VAO);
|
||||||
|
|
||||||
|
final String renderer = Gdx.gl.glGetString(GL20.GL_RENDERER);
|
||||||
|
System.err.println("Renderer: " + renderer);
|
||||||
|
|
||||||
|
final Element cameraData = this.viewer.miscData.get("Camera");
|
||||||
|
Element cameraListenerData = this.viewer.miscData.get("Listener");
|
||||||
|
if (cameraListenerData == null) {
|
||||||
|
cameraListenerData = new Element("Listener", new DataTable(null));
|
||||||
|
}
|
||||||
|
final CameraPreset[] cameraPresets = new CameraPreset[6];
|
||||||
|
for (int i = 0; i < cameraPresets.length; i++) {
|
||||||
|
cameraPresets[i] = new CameraPreset(cameraData.getFieldFloatValue("AOA", i),
|
||||||
|
cameraData.getFieldFloatValue("FOV", i), cameraData.getFieldFloatValue("Rotation", i),
|
||||||
|
cameraData.getFieldFloatValue("Rotation", i + cameraPresets.length),
|
||||||
|
cameraData.getFieldFloatValue("Rotation", i + (cameraPresets.length * 2)),
|
||||||
|
cameraData.getFieldFloatValue("Distance", i), cameraData.getFieldFloatValue("FarZ", i),
|
||||||
|
cameraData.getFieldFloatValue("NearZ", i), cameraData.getFieldFloatValue("Height", i),
|
||||||
|
cameraListenerData.getFieldFloatValue("ListenerDistance", i),
|
||||||
|
cameraListenerData.getFieldFloatValue("ListenerAOA", i));
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("Loaded");
|
||||||
|
Gdx.gl30.glClearColor(0.0f, 0.0f, 0.0f, 1); // TODO remove white background
|
||||||
|
Gdx.gl30.glEnable(GL30.GL_SCISSOR_TEST);
|
||||||
|
|
||||||
|
final Scene portraitScene = this.viewer.addSimpleScene();
|
||||||
|
this.uiScene = this.viewer.addSimpleScene();
|
||||||
|
this.uiScene.alpha = true;
|
||||||
|
if (ENABLE_AUDIO) {
|
||||||
|
this.uiScene.enableAudio();
|
||||||
|
}
|
||||||
|
|
||||||
|
// this.mainModel = (MdxModel) this.viewer.load("UI\\Glues\\MainMenu\\MainMenu3D_exp\\MainMenu3D_exp.mdx",
|
||||||
|
|
||||||
|
// libGDX stuff
|
||||||
|
final int width = Gdx.graphics.getWidth();
|
||||||
|
final int height = Gdx.graphics.getHeight();
|
||||||
|
|
||||||
|
this.glyphLayout = new GlyphLayout();
|
||||||
|
|
||||||
|
// Constructs a new OrthographicCamera, using the given viewport width and
|
||||||
|
// height
|
||||||
|
// Height is multiplied by aspect ratio.
|
||||||
|
this.uiCamera = new OrthographicCamera();
|
||||||
|
int aspect3By4Width;
|
||||||
|
int aspect3By4Height;
|
||||||
|
if (width < ((height * 4) / 3)) {
|
||||||
|
aspect3By4Width = width;
|
||||||
|
aspect3By4Height = (width * 3) / 4;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
aspect3By4Width = (height * 4) / 3;
|
||||||
|
aspect3By4Height = height;
|
||||||
|
}
|
||||||
|
this.uiViewport = new ExtendViewport(aspect3By4Width, aspect3By4Height, this.uiCamera);
|
||||||
|
this.uiViewport.update(width, height);
|
||||||
|
|
||||||
|
this.uiCamera.position.set(this.uiViewport.getMinWorldWidth() / 2, this.uiViewport.getMinWorldHeight() / 2, 0);
|
||||||
|
this.uiCamera.update();
|
||||||
|
|
||||||
|
this.batch = new SpriteBatch();
|
||||||
|
|
||||||
|
// this.consoleUITexture = new Texture(new DataSourceFileHandle(this.viewer.dataSource, "AlphaUi.png"));
|
||||||
|
|
||||||
|
this.solidGreenTexture = ImageUtils.getAnyExtensionTexture(this.viewer.dataSource,
|
||||||
|
"ReplaceableTextures\\TeamColor\\TeamColor06.blp");
|
||||||
|
|
||||||
|
Gdx.input.setInputProcessor(this);
|
||||||
|
|
||||||
|
this.shapeRenderer = new ShapeRenderer();
|
||||||
|
|
||||||
|
// Jass2.loadJUI(this.codebase, this.uiViewport, fontGenerator, this.uiScene, this.viewer,
|
||||||
|
// new RootFrameListener() {
|
||||||
|
// @Override
|
||||||
|
// public void onCreate(final GameUI rootFrame) {
|
||||||
|
// WarsmashGdxMapGame.this.gameUI = rootFrame;
|
||||||
|
// }
|
||||||
|
// }, "Scripts\\common.jui", "Scripts\\melee.jui");
|
||||||
|
final Element cameraRatesElement = this.viewer.miscData.get("CameraRates");
|
||||||
|
final CameraRates cameraRates = new CameraRates(cameraRatesElement.getFieldFloatValue("AOA"),
|
||||||
|
cameraRatesElement.getFieldFloatValue("FOV"), cameraRatesElement.getFieldFloatValue("Rotation"),
|
||||||
|
cameraRatesElement.getFieldFloatValue("Distance"), cameraRatesElement.getFieldFloatValue("Forward"),
|
||||||
|
cameraRatesElement.getFieldFloatValue("Strafe"));
|
||||||
|
this.meleeUI = new MeleeUI(this.viewer.mapMpq, this.uiViewport, this.uiScene, portraitScene, cameraPresets,
|
||||||
|
cameraRates, this.viewer, new RootFrameListener() {
|
||||||
|
@Override
|
||||||
|
public void onCreate(final GameUI rootFrame) {
|
||||||
|
WarsmashGdxMapScreen.this.viewer.setGameUI(rootFrame);
|
||||||
|
|
||||||
|
if (ENABLE_MUSIC) {
|
||||||
|
final String musicField = rootFrame
|
||||||
|
.getSkinField("Music_V" + WarsmashConstants.GAME_VERSION);
|
||||||
|
final String[] musics = musicField.split(";");
|
||||||
|
String musicPath = musics[(int) (Math.random() * musics.length)];
|
||||||
|
if (false) {
|
||||||
|
musicPath = "Sound\\Music\\mp3Music\\PH1.mp3";
|
||||||
|
}
|
||||||
|
final Music music = Gdx.audio.newMusic(
|
||||||
|
new DataSourceFileHandle(WarsmashGdxMapScreen.this.viewer.dataSource, musicPath));
|
||||||
|
music.setVolume(1.0f);
|
||||||
|
music.setLooping(true);
|
||||||
|
music.play();
|
||||||
|
WarsmashGdxMapScreen.this.currentMusic = music;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, new CPlayerUnitOrderExecutor(this.viewer.simulation, this.viewer.getLocalPlayerIndex(),
|
||||||
|
this.viewer.getCommandErrorListener()),
|
||||||
|
new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
WarsmashGdxMapScreen.this.menuScreen.onReturnFromGame();
|
||||||
|
WarsmashGdxMapScreen.this.screenManager.setScreen(WarsmashGdxMapScreen.this.menuScreen);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.viewer.getCommandErrorListener().setDelegate(this.meleeUI);
|
||||||
|
final ModelInstance libgdxContentInstance = new LibGDXContentLayerModel(null, this.viewer, "",
|
||||||
|
this.viewer.mapPathSolver, "").addInstance();
|
||||||
|
libgdxContentInstance.setScene(this.uiScene);
|
||||||
|
this.meleeUI.main();
|
||||||
|
|
||||||
|
updateUIScene();
|
||||||
|
|
||||||
|
resize(width, height);
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.viewer.loadAfterUI();
|
||||||
|
}
|
||||||
|
catch (final IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DataSource parseDataSources(final DataTable warsmashIni) {
|
||||||
|
final Element dataSourcesConfig = warsmashIni.get("DataSources");
|
||||||
|
final int dataSourcesCount = dataSourcesConfig.getFieldValue("Count");
|
||||||
|
final List<DataSourceDescriptor> dataSourcesList = new ArrayList<>();
|
||||||
|
for (int i = 0; i < dataSourcesCount; i++) {
|
||||||
|
final String type = dataSourcesConfig.getField("Type" + (i < 10 ? "0" : "") + i);
|
||||||
|
final String path = dataSourcesConfig.getField("Path" + (i < 10 ? "0" : "") + i);
|
||||||
|
switch (type) {
|
||||||
|
case "Folder": {
|
||||||
|
dataSourcesList.add(new FolderDataSourceDescriptor(path));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "MPQ": {
|
||||||
|
dataSourcesList.add(new MpqDataSourceDescriptor(path));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "CASC": {
|
||||||
|
final String prefixes = dataSourcesConfig.getField("Prefixes" + (i < 10 ? "0" : "") + i);
|
||||||
|
dataSourcesList.add(new CascDataSourceDescriptor(path, Arrays.asList(prefixes.split(","))));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("Unknown data source type: " + type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new CompoundDataSourceDescriptor(dataSourcesList).createDataSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateUIScene() {
|
||||||
|
this.tempRect.x = this.uiViewport.getScreenX();
|
||||||
|
this.tempRect.y = this.uiViewport.getScreenY();
|
||||||
|
this.tempRect.width = this.uiViewport.getScreenWidth();
|
||||||
|
this.tempRect.height = this.uiViewport.getScreenHeight();
|
||||||
|
this.uiScene.camera.viewport(this.tempRect);
|
||||||
|
final float worldWidth = this.uiViewport.getWorldWidth();
|
||||||
|
final float worldHeight = this.uiViewport.getWorldHeight();
|
||||||
|
final float xScale = worldWidth / this.uiViewport.getMinWorldWidth();
|
||||||
|
final float yScale = worldHeight / this.uiViewport.getMinWorldHeight();
|
||||||
|
final float uiSceneWidth = 0.8f * xScale;
|
||||||
|
final float uiSceneHeight = 0.6f * yScale;
|
||||||
|
final float uiSceneX = ((0.8f - uiSceneWidth) / 2);
|
||||||
|
final float uiSceneY = ((0.6f - uiSceneHeight) / 2);
|
||||||
|
this.uiScene.camera.ortho(uiSceneX, uiSceneWidth + uiSceneX, uiSceneY, uiSceneHeight + uiSceneY, -1024f, 1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(final float delta) {
|
||||||
|
this.uiCamera.update();
|
||||||
|
Gdx.gl30.glEnable(GL30.GL_SCISSOR_TEST);
|
||||||
|
final float deltaTime = Gdx.graphics.getDeltaTime();
|
||||||
|
Gdx.gl30.glBindVertexArray(WarsmashGdxGame.VAO);
|
||||||
|
this.meleeUI.update(deltaTime);
|
||||||
|
this.viewer.updateAndRender();
|
||||||
|
|
||||||
|
Gdx.gl30.glDisable(GL30.GL_SCISSOR_TEST);
|
||||||
|
|
||||||
|
Gdx.gl30.glDisable(GL30.GL_CULL_FACE);
|
||||||
|
|
||||||
|
this.viewer.webGL.useShaderProgram(null);
|
||||||
|
|
||||||
|
Gdx.gl30.glActiveTexture(GL30.GL_TEXTURE0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void renderLibGDXContent() {
|
||||||
|
|
||||||
|
Gdx.gl30.glDisable(GL30.GL_SCISSOR_TEST);
|
||||||
|
|
||||||
|
Gdx.gl30.glDisable(GL30.GL_CULL_FACE);
|
||||||
|
|
||||||
|
this.viewer.webGL.useShaderProgram(null);
|
||||||
|
|
||||||
|
Gdx.gl30.glActiveTexture(GL30.GL_TEXTURE0);
|
||||||
|
|
||||||
|
this.uiViewport.apply();
|
||||||
|
this.batch.setProjectionMatrix(this.uiCamera.combined);
|
||||||
|
this.batch.begin();
|
||||||
|
this.meleeUI.render(this.batch, this.glyphLayout);
|
||||||
|
this.batch.end();
|
||||||
|
|
||||||
|
Gdx.gl30.glEnable(GL30.GL_SCISSOR_TEST);
|
||||||
|
Gdx.gl30.glBindVertexArray(WarsmashGdxGame.VAO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
this.meleeUI.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resize(final int width, final int height) {
|
||||||
|
// super.resize(width, height);
|
||||||
|
|
||||||
|
this.uiViewport.update(width, height);
|
||||||
|
this.uiCamera.position.set(this.uiViewport.getMinWorldWidth() / 2, this.uiViewport.getMinWorldHeight() / 2, 0);
|
||||||
|
|
||||||
|
this.meleeUI.resize(setupWorldFrameViewport(width, height));
|
||||||
|
updateUIScene();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private Rectangle setupWorldFrameViewport(final int width, final int height) {
|
||||||
|
this.tempRect.x = 0;
|
||||||
|
this.tempRect.width = width;
|
||||||
|
final float topHeight = 0.02666f * height;
|
||||||
|
final float bottomHeight = 0.21333f * height;
|
||||||
|
this.tempRect.y = (int) bottomHeight;
|
||||||
|
this.tempRect.height = height - (int) (topHeight + bottomHeight);
|
||||||
|
return this.tempRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean keyDown(final int keycode) {
|
||||||
|
this.meleeUI.keyDown(keycode);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean keyUp(final int keycode) {
|
||||||
|
this.meleeUI.keyUp(keycode);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean keyTyped(final char character) {
|
||||||
|
if (character == '1') {
|
||||||
|
Gdx.input.setCursorCatched(!Gdx.input.isCursorCatched());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean touchDown(final int screenX, final int screenY, final int pointer, final int button) {
|
||||||
|
final float worldScreenY = this.viewer.canvas.getHeight() - screenY;
|
||||||
|
|
||||||
|
if (this.meleeUI.touchDown(screenX, screenY, worldScreenY, button)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean touchUp(final int screenX, final int screenY, final int pointer, final int button) {
|
||||||
|
final float worldScreenY = this.viewer.canvas.getHeight() - screenY;
|
||||||
|
|
||||||
|
if (this.meleeUI.touchUp(screenX, screenY, worldScreenY, button)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean touchDragged(final int screenX, final int screenY, final int pointer) {
|
||||||
|
final float worldScreenY = this.viewer.canvas.getHeight() - screenY;
|
||||||
|
if (this.meleeUI.touchDragged(screenX, screenY, worldScreenY, pointer)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean mouseMoved(final int screenX, final int screenY) {
|
||||||
|
final float worldScreenY = this.viewer.canvas.getHeight() - screenY;
|
||||||
|
if (this.meleeUI.mouseMoved(screenX, screenY, worldScreenY)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean scrolled(final int amount) {
|
||||||
|
this.meleeUI.scrolled(amount);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Message {
|
||||||
|
private final float time;
|
||||||
|
private final String text;
|
||||||
|
|
||||||
|
public Message(final float time, final String text) {
|
||||||
|
this.time = time;
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class LibGDXContentLayerModelInstance extends ModelInstance {
|
||||||
|
|
||||||
|
public LibGDXContentLayerModelInstance(final Model model) {
|
||||||
|
super(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateAnimations(final float dt) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearEmittedObjects() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void updateLights(final Scene scene2) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderOpaque(final Matrix4 mvp) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderTranslucent() {
|
||||||
|
renderLibGDXContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void load() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected RenderBatch getBatch(final TextureMapper textureMapper2) {
|
||||||
|
throw new UnsupportedOperationException("NOT API");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setReplaceableTexture(final int replaceableTextureId, final String replaceableTextureFile) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBatched() {
|
||||||
|
return super.isBatched();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void removeLights(final Scene scene2) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private class LibGDXContentLayerModel extends Model {
|
||||||
|
|
||||||
|
public LibGDXContentLayerModel(final ModelHandler handler, final ModelViewer viewer, final String extension,
|
||||||
|
final PathSolver pathSolver, final String fetchUrl) {
|
||||||
|
super(handler, viewer, extension, pathSolver, fetchUrl);
|
||||||
|
this.ok = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ModelInstance createInstance(final int type) {
|
||||||
|
return new LibGDXContentLayerModelInstance(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void lateLoad() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void load(final InputStream src, final Object options) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void error(final Exception e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void pause() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resume() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void hide() {
|
||||||
|
if (this.currentMusic != null) {
|
||||||
|
this.currentMusic.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
882
core/src/com/etheller/warsmash/WarsmashGdxMenuScreen.java
Normal file
882
core/src/com/etheller/warsmash/WarsmashGdxMenuScreen.java
Normal file
@ -0,0 +1,882 @@
|
|||||||
|
package com.etheller.warsmash;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.nio.IntBuffer;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.Gdx;
|
||||||
|
import com.badlogic.gdx.InputProcessor;
|
||||||
|
import com.badlogic.gdx.Screen;
|
||||||
|
import com.badlogic.gdx.audio.Music;
|
||||||
|
import com.badlogic.gdx.graphics.GL20;
|
||||||
|
import com.badlogic.gdx.graphics.GL30;
|
||||||
|
import com.badlogic.gdx.graphics.OrthographicCamera;
|
||||||
|
import com.badlogic.gdx.graphics.Texture;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||||
|
import com.badlogic.gdx.math.Matrix4;
|
||||||
|
import com.badlogic.gdx.math.Quaternion;
|
||||||
|
import com.badlogic.gdx.math.Rectangle;
|
||||||
|
import com.badlogic.gdx.math.Vector3;
|
||||||
|
import com.badlogic.gdx.utils.viewport.ExtendViewport;
|
||||||
|
import com.badlogic.gdx.utils.viewport.FitViewport;
|
||||||
|
import com.badlogic.gdx.utils.viewport.Viewport;
|
||||||
|
import com.etheller.warsmash.datasources.DataSource;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.GameUI;
|
||||||
|
import com.etheller.warsmash.parsers.jass.Jass2.RootFrameListener;
|
||||||
|
import com.etheller.warsmash.units.DataTable;
|
||||||
|
import com.etheller.warsmash.util.DataSourceFileHandle;
|
||||||
|
import com.etheller.warsmash.util.ImageUtils;
|
||||||
|
import com.etheller.warsmash.util.WarsmashConstants;
|
||||||
|
import com.etheller.warsmash.viewer5.Camera;
|
||||||
|
import com.etheller.warsmash.viewer5.CanvasProvider;
|
||||||
|
import com.etheller.warsmash.viewer5.Model;
|
||||||
|
import com.etheller.warsmash.viewer5.ModelInstance;
|
||||||
|
import com.etheller.warsmash.viewer5.ModelViewer;
|
||||||
|
import com.etheller.warsmash.viewer5.PathSolver;
|
||||||
|
import com.etheller.warsmash.viewer5.RenderBatch;
|
||||||
|
import com.etheller.warsmash.viewer5.Scene;
|
||||||
|
import com.etheller.warsmash.viewer5.SolvedPath;
|
||||||
|
import com.etheller.warsmash.viewer5.TextureMapper;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.ModelHandler;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.mdx.MdxComplexInstance;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.mdx.MdxHandler;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.mdx.MdxModel;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.mdx.MdxViewer;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.mdx.Sequence;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.mdx.SequenceLoopMode;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.w3x.SequenceUtils;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.w3x.War3MapViewer;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.w3x.ui.MenuUI;
|
||||||
|
|
||||||
|
public class WarsmashGdxMenuScreen implements InputProcessor, Screen, SingleModelScreen {
|
||||||
|
private static final boolean ENABLE_AUDIO = true;
|
||||||
|
private static final boolean ENABLE_MUSIC = false;
|
||||||
|
private DataSource codebase;
|
||||||
|
private MdxViewer viewer;
|
||||||
|
private MdxModel model;
|
||||||
|
private CameraManager cameraManager;
|
||||||
|
private final Rectangle tempRect = new Rectangle();
|
||||||
|
|
||||||
|
// libGDX stuff
|
||||||
|
private OrthographicCamera uiCamera;
|
||||||
|
private SpriteBatch batch;
|
||||||
|
private Viewport uiViewport;
|
||||||
|
private GlyphLayout glyphLayout;
|
||||||
|
|
||||||
|
private final DataTable warsmashIni;
|
||||||
|
private Scene uiScene;
|
||||||
|
private Texture solidGreenTexture;
|
||||||
|
private MenuUI menuUI;
|
||||||
|
private final WarsmashGdxMultiScreenGame game;
|
||||||
|
private Music currentMusic;
|
||||||
|
private boolean hasPlayedStandHack = false;
|
||||||
|
private boolean loaded = false;
|
||||||
|
|
||||||
|
public WarsmashGdxMenuScreen(final DataTable warsmashIni, final WarsmashGdxMultiScreenGame game) {
|
||||||
|
this.warsmashIni = warsmashIni;
|
||||||
|
this.game = game;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void show() {
|
||||||
|
if (!this.loaded) {
|
||||||
|
this.loaded = true;
|
||||||
|
final ByteBuffer tempByteBuffer = ByteBuffer.allocateDirect(4);
|
||||||
|
tempByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
final IntBuffer temp = tempByteBuffer.asIntBuffer();
|
||||||
|
//
|
||||||
|
Gdx.gl30.glGenVertexArrays(1, temp);
|
||||||
|
WarsmashGdxGame.VAO = temp.get(0);
|
||||||
|
|
||||||
|
Gdx.gl30.glBindVertexArray(WarsmashGdxGame.VAO);
|
||||||
|
|
||||||
|
final String renderer = Gdx.gl.glGetString(GL20.GL_RENDERER);
|
||||||
|
System.err.println("Renderer: " + renderer);
|
||||||
|
|
||||||
|
this.codebase = WarsmashGdxMapScreen.parseDataSources(this.warsmashIni);
|
||||||
|
this.viewer = new MdxViewer(this.codebase, this.game, Vector3.Zero);
|
||||||
|
|
||||||
|
this.viewer.addHandler(new MdxHandler());
|
||||||
|
this.viewer.enableAudio();
|
||||||
|
|
||||||
|
this.scene = this.viewer.addSimpleScene();
|
||||||
|
this.scene.enableAudio();
|
||||||
|
|
||||||
|
this.uiScene = this.viewer.addSimpleScene();
|
||||||
|
this.uiScene.alpha = true;
|
||||||
|
if (ENABLE_AUDIO) {
|
||||||
|
this.uiScene.enableAudio();
|
||||||
|
}
|
||||||
|
final int width = Gdx.graphics.getWidth();
|
||||||
|
final int height = Gdx.graphics.getHeight();
|
||||||
|
|
||||||
|
this.glyphLayout = new GlyphLayout();
|
||||||
|
|
||||||
|
// Constructs a new OrthographicCamera, using the given viewport width and
|
||||||
|
// height
|
||||||
|
// Height is multiplied by aspect ratio.
|
||||||
|
this.uiCamera = new OrthographicCamera();
|
||||||
|
int aspect3By4Width;
|
||||||
|
int aspect3By4Height;
|
||||||
|
if (width < ((height * 4) / 3)) {
|
||||||
|
aspect3By4Width = width;
|
||||||
|
aspect3By4Height = (width * 3) / 4;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
aspect3By4Width = (height * 4) / 3;
|
||||||
|
aspect3By4Height = height;
|
||||||
|
}
|
||||||
|
this.uiViewport = new FitViewport(aspect3By4Width, aspect3By4Height, this.uiCamera);
|
||||||
|
this.uiViewport.update(width, height);
|
||||||
|
|
||||||
|
this.uiCamera.position.set(getMinWorldWidth() / 2, getMinWorldHeight() / 2, 0);
|
||||||
|
this.uiCamera.update();
|
||||||
|
|
||||||
|
this.batch = new SpriteBatch();
|
||||||
|
|
||||||
|
// this.consoleUITexture = new Texture(new DataSourceFileHandle(this.viewer.dataSource, "AlphaUi.png"));
|
||||||
|
|
||||||
|
this.solidGreenTexture = ImageUtils.getAnyExtensionTexture(this.viewer.dataSource,
|
||||||
|
"ReplaceableTextures\\TeamColor\\TeamColor06.blp");
|
||||||
|
|
||||||
|
this.cameraManager = new CameraManager();
|
||||||
|
this.cameraManager.setupCamera(this.scene);
|
||||||
|
|
||||||
|
// this.mainModel = (MdxModel) this.viewer.load("Doodads\\Cinematic\\ArthasIllidanFight\\ArthasIllidanFight.mdx",
|
||||||
|
// this.mainModel = (MdxModel) this.viewer.load("UI\\Glues\\SinglePlayer\\NightElf_Exp\\NightElf_Exp.mdx",
|
||||||
|
// this.mainModel = (MdxModel) this.viewer.load("Abilities\\Spells\\Orc\\FeralSpirit\\feralspirittarget.mdx",
|
||||||
|
// new PathSolver() {
|
||||||
|
// @Override
|
||||||
|
// public SolvedPath solve(final String src, final Object solverParams) {
|
||||||
|
// return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
|
||||||
|
// }
|
||||||
|
// }, null);
|
||||||
|
|
||||||
|
// final EventObjectEmitterObject evt = this.mainModel.getEventObjects().get(1);
|
||||||
|
// for (final Sequence seq : this.mainModel.getSequences()) {
|
||||||
|
// System.out.println(seq.getName() + ": " + Arrays.toString(seq.getInterval()));
|
||||||
|
// }
|
||||||
|
// System.out.println(Arrays.toString(evt.keyFrames));
|
||||||
|
// System.out.println(evt.name);
|
||||||
|
|
||||||
|
// this.mainInstance = (MdxComplexInstance) this.mainModel.addInstance(0);
|
||||||
|
|
||||||
|
// this.mainInstance.setScene(scene);
|
||||||
|
//
|
||||||
|
// final int animIndex = 0;
|
||||||
|
// this.modelCamera = this.mainModel.cameras.get(animIndex);
|
||||||
|
// this.mainInstance.setSequence(animIndex);
|
||||||
|
//
|
||||||
|
// this.mainInstance.setSequenceLoopMode(SequenceLoopMode.LOOP_TO_NEXT_ANIMATION);
|
||||||
|
|
||||||
|
// acolytesHarvestingSceneJoke2(scene);
|
||||||
|
|
||||||
|
// singleModelScene(scene, "Buildings\\Undead\\Necropolis\\Necropolis.mdx", "birth");
|
||||||
|
// singleModelScene(scene, "Units\\Orc\\KotoBeast\\KotoBeast.mdx", "spell slam");
|
||||||
|
|
||||||
|
System.out.println("Loaded");
|
||||||
|
Gdx.gl30.glClearColor(0.0f, 0.0f, 0.0f, 1);
|
||||||
|
|
||||||
|
this.menuUI = new MenuUI(this.viewer.dataSource, this.uiViewport, this.uiScene, this.viewer, this.game,
|
||||||
|
this, this.warsmashIni, new RootFrameListener() {
|
||||||
|
@Override
|
||||||
|
public void onCreate(final GameUI rootFrame) {
|
||||||
|
// WarsmashGdxMapGame.this.viewer.setGameUI(rootFrame);
|
||||||
|
|
||||||
|
if (ENABLE_MUSIC) {
|
||||||
|
final String musicField = rootFrame
|
||||||
|
.getSkinField("GlueMusic_V" + WarsmashConstants.GAME_VERSION);
|
||||||
|
final String[] musics = musicField.split(";");
|
||||||
|
final String musicPath = musics[(int) (Math.random() * musics.length)];
|
||||||
|
final Music music = Gdx.audio.newMusic(new DataSourceFileHandle(
|
||||||
|
WarsmashGdxMenuScreen.this.viewer.dataSource, musicPath));
|
||||||
|
// music.setVolume(0.2f);
|
||||||
|
music.setLooping(true);
|
||||||
|
music.play();
|
||||||
|
WarsmashGdxMenuScreen.this.currentMusic = music;
|
||||||
|
}
|
||||||
|
|
||||||
|
singleModelScene(WarsmashGdxMenuScreen.this.scene, War3MapViewer.mdx(rootFrame
|
||||||
|
.getSkinField("GlueSpriteLayerBackground_V" + WarsmashConstants.GAME_VERSION)),
|
||||||
|
"Stand");
|
||||||
|
WarsmashGdxMenuScreen.this.modelCamera = WarsmashGdxMenuScreen.this.mainModel.cameras
|
||||||
|
.get(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
final ModelInstance libgdxContentInstance = new LibGDXContentLayerModel(null, this.viewer, "",
|
||||||
|
PathSolver.DEFAULT, "").addInstance();
|
||||||
|
libgdxContentInstance.setLocation(0f, 0f, -0.5f);
|
||||||
|
libgdxContentInstance.setScene(this.uiScene);
|
||||||
|
this.menuUI.main();
|
||||||
|
|
||||||
|
updateUIScene();
|
||||||
|
|
||||||
|
resize(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
Gdx.input.setInputProcessor(this);
|
||||||
|
if (this.currentMusic != null) {
|
||||||
|
this.currentMusic.play();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private float getMinWorldWidth() {
|
||||||
|
if (this.uiViewport instanceof ExtendViewport) {
|
||||||
|
return ((ExtendViewport) this.uiViewport).getMinWorldWidth();
|
||||||
|
}
|
||||||
|
return this.uiViewport.getWorldWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
private float getMinWorldHeight() {
|
||||||
|
if (this.uiViewport instanceof ExtendViewport) {
|
||||||
|
return ((ExtendViewport) this.uiViewport).getMinWorldHeight();
|
||||||
|
}
|
||||||
|
return this.uiViewport.getWorldHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateUIScene() {
|
||||||
|
this.tempRect.x = this.uiViewport.getScreenX();
|
||||||
|
this.tempRect.y = this.uiViewport.getScreenY();
|
||||||
|
this.tempRect.width = this.uiViewport.getScreenWidth();
|
||||||
|
this.tempRect.height = this.uiViewport.getScreenHeight();
|
||||||
|
this.uiScene.camera.viewport(this.tempRect);
|
||||||
|
final float worldWidth = this.uiViewport.getWorldWidth();
|
||||||
|
final float worldHeight = this.uiViewport.getWorldHeight();
|
||||||
|
final float xScale = worldWidth / getMinWorldWidth();
|
||||||
|
final float yScale = worldHeight / getMinWorldHeight();
|
||||||
|
final float uiSceneWidth = 0.8f * xScale;
|
||||||
|
final float uiSceneHeight = 0.6f * yScale;
|
||||||
|
final float uiSceneX = ((0.8f - uiSceneWidth) / 2);
|
||||||
|
final float uiSceneY = ((0.6f - uiSceneHeight) / 2);
|
||||||
|
this.uiScene.camera.ortho(uiSceneX, uiSceneWidth + uiSceneX, uiSceneY, uiSceneHeight + uiSceneY, -1024f, 1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makeDruidSquare(final Scene scene) {
|
||||||
|
final MdxModel model2 = (MdxModel) this.viewer.load("units\\nightelf\\druidoftheclaw\\druidoftheclaw.mdx",
|
||||||
|
new PathSolver() {
|
||||||
|
@Override
|
||||||
|
public SolvedPath solve(final String src, final Object solverParams) {
|
||||||
|
return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
makePerfectSquare(scene, model2, 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void singleAcolyteScene(final Scene scene) {
|
||||||
|
final MdxModel model2 = (MdxModel) this.viewer.load("units\\undead\\acolyte\\acolyte.mdx", new PathSolver() {
|
||||||
|
@Override
|
||||||
|
public SolvedPath solve(final String src, final Object solverParams) {
|
||||||
|
return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
|
||||||
|
final MdxComplexInstance instance3 = (MdxComplexInstance) model2.addInstance(0);
|
||||||
|
|
||||||
|
instance3.setScene(scene);
|
||||||
|
|
||||||
|
int animIndex = 0;
|
||||||
|
for (final Sequence s : model2.getSequences()) {
|
||||||
|
if (s.getName().toLowerCase().startsWith("stand work")) {
|
||||||
|
animIndex = model2.getSequences().indexOf(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
instance3.setSequence(animIndex);
|
||||||
|
|
||||||
|
instance3.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void singleModelScene(final Scene scene, final String path, final String animName) {
|
||||||
|
final MdxModel model2 = (MdxModel) this.viewer.load(path, new PathSolver() {
|
||||||
|
@Override
|
||||||
|
public SolvedPath solve(final String src, final Object solverParams) {
|
||||||
|
return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
|
||||||
|
final MdxComplexInstance instance3 = (MdxComplexInstance) model2.addInstance(0);
|
||||||
|
|
||||||
|
instance3.setScene(scene);
|
||||||
|
|
||||||
|
int animIndex = 0;
|
||||||
|
for (final Sequence s : model2.getSequences()) {
|
||||||
|
if (s.getName().toLowerCase().startsWith(animName)) {
|
||||||
|
animIndex = model2.getSequences().indexOf(s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
instance3.setSequence(animIndex);
|
||||||
|
|
||||||
|
instance3.setSequenceLoopMode(SequenceLoopMode.NEVER_LOOP);
|
||||||
|
this.mainInstance = instance3;
|
||||||
|
this.mainModel = model2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setModel(final String path) {
|
||||||
|
if (this.mainInstance != null) {
|
||||||
|
this.mainInstance.detach();
|
||||||
|
}
|
||||||
|
if (path == null) {
|
||||||
|
this.modelCamera = null;
|
||||||
|
this.mainInstance = null;
|
||||||
|
this.mainModel = null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
singleModelScene(this.scene, War3MapViewer.mdx(path), "birth");
|
||||||
|
WarsmashGdxMenuScreen.this.modelCamera = WarsmashGdxMenuScreen.this.mainModel.cameras.get(0);
|
||||||
|
// this hack is because we only have the queued animation system in RenderWidget
|
||||||
|
// which is stupid and back and needs to get moved to the model instance
|
||||||
|
// itself... our model instance class is a
|
||||||
|
// hacky replica of a model viewer tool with a bunch of irrelevant loop type
|
||||||
|
// settings instead of what it should be
|
||||||
|
this.hasPlayedStandHack = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void acolytesHarvestingScene(final Scene scene) {
|
||||||
|
|
||||||
|
final MdxModel acolyteModel = (MdxModel) this.viewer.load("units\\undead\\acolyte\\acolyte.mdx",
|
||||||
|
new PathSolver() {
|
||||||
|
@Override
|
||||||
|
public SolvedPath solve(final String src, final Object solverParams) {
|
||||||
|
return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
final MdxModel mineEffectModel = (MdxModel) this.viewer
|
||||||
|
.load("abilities\\spells\\undead\\undeadmine\\undeadminecircle.mdx", new PathSolver() {
|
||||||
|
@Override
|
||||||
|
public SolvedPath solve(final String src, final Object solverParams) {
|
||||||
|
return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
final MdxComplexInstance acolyteInstance = (MdxComplexInstance) acolyteModel.addInstance(0);
|
||||||
|
|
||||||
|
acolyteInstance.setScene(scene);
|
||||||
|
|
||||||
|
int animIndex = i % acolyteModel.getSequences().size();
|
||||||
|
for (final Sequence s : acolyteModel.getSequences()) {
|
||||||
|
if (s.getName().toLowerCase().startsWith("stand work")) {
|
||||||
|
animIndex = acolyteModel.getSequences().indexOf(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
acolyteInstance.setSequence(animIndex);
|
||||||
|
|
||||||
|
acolyteInstance.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
|
||||||
|
|
||||||
|
final double angle = ((Math.PI * 2) / 5) * i;
|
||||||
|
acolyteInstance.localLocation.x = (float) Math.cos(angle) * 256;
|
||||||
|
acolyteInstance.localLocation.y = (float) Math.sin(angle) * 256;
|
||||||
|
acolyteInstance.localRotation.setFromAxisRad(0, 0, 1, (float) (angle + Math.PI));
|
||||||
|
|
||||||
|
final MdxComplexInstance effectInstance = (MdxComplexInstance) mineEffectModel.addInstance(0);
|
||||||
|
|
||||||
|
effectInstance.setScene(scene);
|
||||||
|
|
||||||
|
effectInstance.setSequence(1);
|
||||||
|
|
||||||
|
effectInstance.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
|
||||||
|
effectInstance.localLocation.x = (float) Math.cos(angle) * 256;
|
||||||
|
effectInstance.localLocation.y = (float) Math.sin(angle) * 256;
|
||||||
|
effectInstance.localRotation.setFromAxisRad(0, 0, 1, (float) (angle));
|
||||||
|
|
||||||
|
}
|
||||||
|
final MdxModel mineModel = (MdxModel) this.viewer.load("buildings\\undead\\hauntedmine\\hauntedmine.mdx",
|
||||||
|
new PathSolver() {
|
||||||
|
@Override
|
||||||
|
public SolvedPath solve(final String src, final Object solverParams) {
|
||||||
|
return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
final MdxComplexInstance mineInstance = (MdxComplexInstance) mineModel.addInstance(0);
|
||||||
|
|
||||||
|
mineInstance.setScene(scene);
|
||||||
|
|
||||||
|
mineInstance.setSequence(2);
|
||||||
|
|
||||||
|
mineInstance.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void acolytesHarvestingSceneJoke2(final Scene scene) {
|
||||||
|
|
||||||
|
final MdxModel acolyteModel = (MdxModel) this.viewer.load("units\\undead\\acolyte\\acolyte.mdx",
|
||||||
|
new PathSolver() {
|
||||||
|
@Override
|
||||||
|
public SolvedPath solve(final String src, final Object solverParams) {
|
||||||
|
return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
final MdxModel mineEffectModel = (MdxModel) this.viewer
|
||||||
|
.load("abilities\\spells\\undead\\undeadmine\\undeadminecircle.mdx", new PathSolver() {
|
||||||
|
@Override
|
||||||
|
public SolvedPath solve(final String src, final Object solverParams) {
|
||||||
|
return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
final MdxComplexInstance acolyteInstance = (MdxComplexInstance) acolyteModel.addInstance(0);
|
||||||
|
|
||||||
|
acolyteInstance.setScene(scene);
|
||||||
|
|
||||||
|
int animIndex = i % acolyteModel.getSequences().size();
|
||||||
|
for (final Sequence s : acolyteModel.getSequences()) {
|
||||||
|
if (s.getName().toLowerCase().startsWith("stand work")) {
|
||||||
|
animIndex = acolyteModel.getSequences().indexOf(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
acolyteInstance.setSequence(animIndex);
|
||||||
|
|
||||||
|
acolyteInstance.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
|
||||||
|
|
||||||
|
final double angle = ((Math.PI * 2) / 5) * i;
|
||||||
|
acolyteInstance.localLocation.x = (float) Math.cos(angle) * 256;
|
||||||
|
acolyteInstance.localLocation.y = (float) Math.sin(angle) * 256;
|
||||||
|
acolyteInstance.localRotation.setFromAxisRad(0, 0, 1, (float) (angle + Math.PI));
|
||||||
|
|
||||||
|
final MdxComplexInstance effectInstance = (MdxComplexInstance) mineEffectModel.addInstance(0);
|
||||||
|
|
||||||
|
effectInstance.setScene(scene);
|
||||||
|
|
||||||
|
effectInstance.setSequence(1);
|
||||||
|
|
||||||
|
effectInstance.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
|
||||||
|
effectInstance.localLocation.x = (float) Math.cos(angle) * 256;
|
||||||
|
effectInstance.localLocation.y = (float) Math.sin(angle) * 256;
|
||||||
|
effectInstance.localRotation.setFromAxisRad(0, 0, 1, (float) (angle));
|
||||||
|
|
||||||
|
}
|
||||||
|
final MdxModel mineModel = (MdxModel) this.viewer.load("units\\orc\\spiritwolf\\spiritwolf.mdx",
|
||||||
|
new PathSolver() {
|
||||||
|
@Override
|
||||||
|
public SolvedPath solve(final String src, final Object solverParams) {
|
||||||
|
return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
final MdxComplexInstance mineInstance = (MdxComplexInstance) mineModel.addInstance(0);
|
||||||
|
|
||||||
|
mineInstance.setScene(scene);
|
||||||
|
|
||||||
|
mineInstance.setSequence(0);
|
||||||
|
mineInstance.localScale.x = 2;
|
||||||
|
mineInstance.localScale.y = 2;
|
||||||
|
mineInstance.localScale.z = 2;
|
||||||
|
|
||||||
|
mineInstance.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
|
||||||
|
final MdxModel mineModel2 = (MdxModel) this.viewer
|
||||||
|
.load("abilities\\spells\\undead\\unsummon\\unsummontarget.mdx", new PathSolver() {
|
||||||
|
@Override
|
||||||
|
public SolvedPath solve(final String src, final Object solverParams) {
|
||||||
|
return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
final MdxComplexInstance mineInstance2 = (MdxComplexInstance) mineModel2.addInstance(0);
|
||||||
|
|
||||||
|
mineInstance2.setScene(scene);
|
||||||
|
|
||||||
|
mineInstance2.setSequence(0);
|
||||||
|
|
||||||
|
mineInstance2.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makeFourHundred(final Scene scene, final MdxModel model2) {
|
||||||
|
for (int i = 0; i < 400; i++) {
|
||||||
|
final MdxComplexInstance instance3 = (MdxComplexInstance) model2.addInstance(0);
|
||||||
|
instance3.localLocation.x = (((i % 20) - 10) * 128);
|
||||||
|
instance3.localLocation.y = (((i / 20) - 10) * 128);
|
||||||
|
|
||||||
|
instance3.setScene(scene);
|
||||||
|
|
||||||
|
final int animIndex = i % model2.getSequences().size();
|
||||||
|
instance3.setSequence(animIndex);
|
||||||
|
|
||||||
|
instance3.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makePerfectSquare(final Scene scene, final MdxModel model2, final int n) {
|
||||||
|
final int n2 = n * n;
|
||||||
|
for (int i = 0; i < n2; i++) {
|
||||||
|
final MdxComplexInstance instance3 = (MdxComplexInstance) model2.addInstance(0);
|
||||||
|
instance3.localLocation.x = (((i % n) - (n / 2)) * 128);
|
||||||
|
instance3.localLocation.y = (((i / n) - (n / 2)) * 128);
|
||||||
|
|
||||||
|
instance3.setScene(scene);
|
||||||
|
|
||||||
|
final int animIndex = i % model2.getSequences().size();
|
||||||
|
instance3.setSequence(animIndex);
|
||||||
|
|
||||||
|
instance3.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void bindDefaultVertexArray() {
|
||||||
|
Gdx.gl30.glBindVertexArray(WarsmashGdxGame.VAO);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final int frame = 0;
|
||||||
|
private MdxComplexInstance mainInstance;
|
||||||
|
private MdxModel mainModel;
|
||||||
|
private com.etheller.warsmash.viewer5.handlers.mdx.Camera modelCamera;
|
||||||
|
private final float[] cameraPositionTemp = new float[3];
|
||||||
|
private final float[] cameraTargetTemp = new float[3];
|
||||||
|
private final boolean firstFrame = true;
|
||||||
|
private Scene scene;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(final float delta) {
|
||||||
|
|
||||||
|
Gdx.gl30.glEnable(GL30.GL_SCISSOR_TEST);
|
||||||
|
final float deltaTime = Gdx.graphics.getDeltaTime();
|
||||||
|
Gdx.gl30.glBindVertexArray(WarsmashGdxGame.VAO);
|
||||||
|
this.cameraManager.updateCamera();
|
||||||
|
this.menuUI.update(deltaTime);
|
||||||
|
if ((this.mainInstance != null) && this.mainInstance.sequenceEnded
|
||||||
|
&& (((this.mainModel.getSequences().get(this.mainInstance.sequence).getFlags() & 0x1) == 0)
|
||||||
|
|| !this.hasPlayedStandHack)) {
|
||||||
|
SequenceUtils.randomStandSequence(this.mainInstance);
|
||||||
|
this.hasPlayedStandHack = true;
|
||||||
|
}
|
||||||
|
this.viewer.updateAndRender();
|
||||||
|
|
||||||
|
Gdx.gl30.glDisable(GL30.GL_SCISSOR_TEST);
|
||||||
|
|
||||||
|
Gdx.gl30.glDisable(GL30.GL_CULL_FACE);
|
||||||
|
|
||||||
|
this.viewer.webGL.useShaderProgram(null);
|
||||||
|
|
||||||
|
Gdx.gl30.glActiveTexture(GL30.GL_TEXTURE0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
this.menuUI.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resize(final int width, final int height) {
|
||||||
|
this.tempRect.width = width;
|
||||||
|
this.tempRect.height = height;
|
||||||
|
final float fourThirdsHeight = (this.tempRect.height * 4) / 3;
|
||||||
|
if (fourThirdsHeight < this.tempRect.width) {
|
||||||
|
final float dx = this.tempRect.width - fourThirdsHeight;
|
||||||
|
this.tempRect.width = fourThirdsHeight;
|
||||||
|
this.tempRect.x = dx / 2;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
final float threeFourthsWidth = (this.tempRect.width * 3) / 4;
|
||||||
|
if (threeFourthsWidth < this.tempRect.height) {
|
||||||
|
final float dy = this.tempRect.height - threeFourthsWidth;
|
||||||
|
this.tempRect.height = threeFourthsWidth;
|
||||||
|
this.tempRect.y = dy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.cameraManager.camera.viewport(this.tempRect);
|
||||||
|
|
||||||
|
// super.resize(width, height);
|
||||||
|
|
||||||
|
this.uiViewport.update(width, height);
|
||||||
|
this.uiCamera.position.set(getMinWorldWidth() / 2, getMinWorldHeight() / 2, 0);
|
||||||
|
|
||||||
|
this.menuUI.resize();
|
||||||
|
updateUIScene();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class CameraManager {
|
||||||
|
private CanvasProvider canvas;
|
||||||
|
private Camera camera;
|
||||||
|
private float moveSpeed;
|
||||||
|
private float rotationSpeed;
|
||||||
|
private float zoomFactor;
|
||||||
|
private float horizontalAngle;
|
||||||
|
private float verticalAngle;
|
||||||
|
private float distance;
|
||||||
|
private Vector3 position;
|
||||||
|
private Vector3 target;
|
||||||
|
private Vector3 worldUp;
|
||||||
|
private Vector3 vecHeap;
|
||||||
|
private Vector3 vecHeap2;
|
||||||
|
private Quaternion quatHeap;
|
||||||
|
private Quaternion quatHeap2;
|
||||||
|
|
||||||
|
// An orbit camera setup example.
|
||||||
|
// Left mouse button controls the orbit itself.
|
||||||
|
// The right mouse button allows to move the camera and the point it's looking
|
||||||
|
// at on the XY plane.
|
||||||
|
// Scrolling zooms in and out.
|
||||||
|
private void setupCamera(final Scene scene) {
|
||||||
|
this.canvas = scene.viewer.canvas;
|
||||||
|
this.camera = scene.camera;
|
||||||
|
this.moveSpeed = 2;
|
||||||
|
this.rotationSpeed = (float) (Math.PI / 180);
|
||||||
|
this.zoomFactor = 0.1f;
|
||||||
|
this.horizontalAngle = (float) (Math.PI / 2);
|
||||||
|
this.verticalAngle = (float) (Math.PI / 4);
|
||||||
|
this.distance = 500;
|
||||||
|
this.position = new Vector3();
|
||||||
|
this.target = new Vector3(0, 0, 50);
|
||||||
|
this.worldUp = new Vector3(0, 0, 1);
|
||||||
|
this.vecHeap = new Vector3();
|
||||||
|
this.vecHeap2 = new Vector3();
|
||||||
|
this.quatHeap = new Quaternion();
|
||||||
|
this.quatHeap2 = new Quaternion();
|
||||||
|
|
||||||
|
updateCamera();
|
||||||
|
|
||||||
|
// cameraUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateCamera() {
|
||||||
|
// Limit the vertical angle so it doesn't flip.
|
||||||
|
// Since the camera uses a quaternion, flips don't matter to it, but this feels
|
||||||
|
// better.
|
||||||
|
this.verticalAngle = (float) Math.min(Math.max(0.01, this.verticalAngle), Math.PI - 0.01);
|
||||||
|
|
||||||
|
this.quatHeap.idt();
|
||||||
|
this.quatHeap.setFromAxisRad(0, 0, 1, this.horizontalAngle);
|
||||||
|
this.quatHeap2.idt();
|
||||||
|
this.quatHeap2.setFromAxisRad(1, 0, 0, this.verticalAngle);
|
||||||
|
this.quatHeap.mul(this.quatHeap2);
|
||||||
|
|
||||||
|
this.position.set(0, 0, 1);
|
||||||
|
this.quatHeap.transform(this.position);
|
||||||
|
this.position.scl(this.distance);
|
||||||
|
this.position = this.position.add(this.target);
|
||||||
|
if (WarsmashGdxMenuScreen.this.modelCamera != null) {
|
||||||
|
WarsmashGdxMenuScreen.this.modelCamera.getPositionTranslation(
|
||||||
|
WarsmashGdxMenuScreen.this.cameraPositionTemp, WarsmashGdxMenuScreen.this.mainInstance.sequence,
|
||||||
|
WarsmashGdxMenuScreen.this.mainInstance.frame, WarsmashGdxMenuScreen.this.mainInstance.counter);
|
||||||
|
WarsmashGdxMenuScreen.this.modelCamera.getTargetTranslation(WarsmashGdxMenuScreen.this.cameraTargetTemp,
|
||||||
|
WarsmashGdxMenuScreen.this.mainInstance.sequence, WarsmashGdxMenuScreen.this.mainInstance.frame,
|
||||||
|
WarsmashGdxMenuScreen.this.mainInstance.counter);
|
||||||
|
|
||||||
|
this.position.set(WarsmashGdxMenuScreen.this.modelCamera.position);
|
||||||
|
this.target.set(WarsmashGdxMenuScreen.this.modelCamera.targetPosition);
|
||||||
|
// this.vecHeap2.set(this.target);
|
||||||
|
// this.vecHeap2.sub(this.position);
|
||||||
|
// this.vecHeap.set(this.vecHeap2);
|
||||||
|
// this.vecHeap.crs(this.worldUp);
|
||||||
|
// this.vecHeap.crs(this.vecHeap2);
|
||||||
|
// this.vecHeap.nor();
|
||||||
|
// this.vecHeap.scl(this.camera.rect.height / 2f);
|
||||||
|
// this.position.add(this.vecHeap);
|
||||||
|
|
||||||
|
this.position.add(WarsmashGdxMenuScreen.this.cameraPositionTemp[0],
|
||||||
|
WarsmashGdxMenuScreen.this.cameraPositionTemp[1],
|
||||||
|
WarsmashGdxMenuScreen.this.cameraPositionTemp[2]);
|
||||||
|
this.target.add(WarsmashGdxMenuScreen.this.cameraTargetTemp[0],
|
||||||
|
WarsmashGdxMenuScreen.this.cameraTargetTemp[1], WarsmashGdxMenuScreen.this.cameraTargetTemp[2]);
|
||||||
|
this.camera.perspective(WarsmashGdxMenuScreen.this.modelCamera.fieldOfView * 0.6f,
|
||||||
|
this.camera.rect.width / this.camera.rect.height,
|
||||||
|
WarsmashGdxMenuScreen.this.modelCamera.nearClippingPlane,
|
||||||
|
WarsmashGdxMenuScreen.this.modelCamera.farClippingPlane);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.camera.perspective(70, this.camera.getAspect(), 100, 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.camera.moveToAndFace(this.position, this.target, this.worldUp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// private void cameraUpdate() {
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataSource getCodebase() {
|
||||||
|
return this.codebase;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean keyDown(final int keycode) {
|
||||||
|
return this.menuUI.keyDown(keycode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean keyUp(final int keycode) {
|
||||||
|
return this.menuUI.keyUp(keycode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean keyTyped(final char character) {
|
||||||
|
return this.menuUI.keyTyped(character);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean touchDown(final int screenX, final int screenY, final int pointer, final int button) {
|
||||||
|
final float worldScreenY = this.game.getHeight() - screenY;
|
||||||
|
|
||||||
|
if (this.menuUI.touchDown(screenX, screenY, worldScreenY, button)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean touchUp(final int screenX, final int screenY, final int pointer, final int button) {
|
||||||
|
final float worldScreenY = this.game.getHeight() - screenY;
|
||||||
|
|
||||||
|
if (this.menuUI.touchUp(screenX, screenY, worldScreenY, button)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean touchDragged(final int screenX, final int screenY, final int pointer) {
|
||||||
|
final float worldScreenY = this.game.getHeight() - screenY;
|
||||||
|
if (this.menuUI.touchDragged(screenX, screenY, worldScreenY, pointer)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean mouseMoved(final int screenX, final int screenY) {
|
||||||
|
final float worldScreenY = this.game.getHeight() - screenY;
|
||||||
|
if (this.menuUI.mouseMoved(screenX, screenY, worldScreenY)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean scrolled(final int amount) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void renderLibGDXContent() {
|
||||||
|
|
||||||
|
Gdx.gl30.glDisable(GL30.GL_SCISSOR_TEST);
|
||||||
|
|
||||||
|
Gdx.gl30.glDisable(GL30.GL_CULL_FACE);
|
||||||
|
|
||||||
|
this.viewer.webGL.useShaderProgram(null);
|
||||||
|
|
||||||
|
Gdx.gl30.glActiveTexture(GL30.GL_TEXTURE0);
|
||||||
|
|
||||||
|
this.uiViewport.apply();
|
||||||
|
this.batch.setProjectionMatrix(this.uiCamera.combined);
|
||||||
|
this.batch.begin();
|
||||||
|
this.menuUI.render(this.batch, this.glyphLayout);
|
||||||
|
this.batch.end();
|
||||||
|
|
||||||
|
Gdx.gl30.glEnable(GL30.GL_SCISSOR_TEST);
|
||||||
|
Gdx.gl30.glBindVertexArray(WarsmashGdxGame.VAO);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class LibGDXContentLayerModelInstance extends ModelInstance {
|
||||||
|
|
||||||
|
public LibGDXContentLayerModelInstance(final Model model) {
|
||||||
|
super(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateAnimations(final float dt) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearEmittedObjects() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void updateLights(final Scene scene2) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderOpaque(final Matrix4 mvp) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderTranslucent() {
|
||||||
|
renderLibGDXContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void load() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected RenderBatch getBatch(final TextureMapper textureMapper2) {
|
||||||
|
throw new UnsupportedOperationException("NOT API");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setReplaceableTexture(final int replaceableTextureId, final String replaceableTextureFile) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBatched() {
|
||||||
|
return super.isBatched();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void removeLights(final Scene scene2) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private class LibGDXContentLayerModel extends Model {
|
||||||
|
|
||||||
|
public LibGDXContentLayerModel(final ModelHandler handler, final ModelViewer viewer, final String extension,
|
||||||
|
final PathSolver pathSolver, final String fetchUrl) {
|
||||||
|
super(handler, viewer, extension, pathSolver, fetchUrl);
|
||||||
|
this.ok = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ModelInstance createInstance(final int type) {
|
||||||
|
return new LibGDXContentLayerModelInstance(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void lateLoad() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void load(final InputStream src, final Object options) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void error(final Exception e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void hide() {
|
||||||
|
if (this.currentMusic != null) {
|
||||||
|
this.currentMusic.stop();
|
||||||
|
}
|
||||||
|
this.menuUI.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void pause() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resume() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startMap(final String finalFileToLoad) {
|
||||||
|
this.menuUI.startMap(finalFileToLoad);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onReturnFromGame() {
|
||||||
|
this.menuUI.onReturnFromGame();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package com.etheller.warsmash;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.Game;
|
||||||
|
import com.badlogic.gdx.Gdx;
|
||||||
|
import com.etheller.warsmash.viewer5.CanvasProvider;
|
||||||
|
|
||||||
|
public class WarsmashGdxMultiScreenGame extends Game implements CanvasProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void create() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getWidth() {
|
||||||
|
return Gdx.graphics.getWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getHeight() {
|
||||||
|
return Gdx.graphics.getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
177
core/src/com/etheller/warsmash/WarsmashPreviewApplication.java
Normal file
177
core/src/com/etheller/warsmash/WarsmashPreviewApplication.java
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
package com.etheller.warsmash;
|
||||||
|
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.nio.IntBuffer;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.ApplicationAdapter;
|
||||||
|
import com.badlogic.gdx.Gdx;
|
||||||
|
import com.badlogic.gdx.graphics.GL20;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||||
|
import com.badlogic.gdx.math.Rectangle;
|
||||||
|
import com.badlogic.gdx.math.Vector3;
|
||||||
|
import com.etheller.warsmash.datasources.DataSource;
|
||||||
|
import com.etheller.warsmash.units.DataTable;
|
||||||
|
import com.etheller.warsmash.viewer5.CanvasProvider;
|
||||||
|
import com.etheller.warsmash.viewer5.ModelViewer;
|
||||||
|
import com.etheller.warsmash.viewer5.PathSolver;
|
||||||
|
import com.etheller.warsmash.viewer5.Scene;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.ResourceHandlerConstructionParams;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.mdx.MdxComplexInstance;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.mdx.MdxHandler;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.mdx.MdxModel;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.mdx.MdxViewer;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.w3x.camera.PortraitCameraManager;
|
||||||
|
import com.hiveworkshop.rms.parsers.mdlx.MdlxModel;
|
||||||
|
import com.hiveworkshop.rms.parsers.mdlx.util.MdxUtils;
|
||||||
|
|
||||||
|
public class WarsmashPreviewApplication extends ApplicationAdapter implements CanvasProvider {
|
||||||
|
private DataSource codebase;
|
||||||
|
private ModelViewer viewer;
|
||||||
|
private MdxModel model;
|
||||||
|
private PortraitCameraManager cameraManager;
|
||||||
|
public static int VAO;
|
||||||
|
private final Rectangle tempRect = new Rectangle();
|
||||||
|
|
||||||
|
private BitmapFont font;
|
||||||
|
private SpriteBatch batch;
|
||||||
|
private final DataTable warsmashIni;
|
||||||
|
|
||||||
|
public WarsmashPreviewApplication(final DataTable warsmashIni) {
|
||||||
|
this.warsmashIni = warsmashIni;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void create() {
|
||||||
|
|
||||||
|
final ByteBuffer tempByteBuffer = ByteBuffer.allocateDirect(4);
|
||||||
|
tempByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
final IntBuffer temp = tempByteBuffer.asIntBuffer();
|
||||||
|
//
|
||||||
|
Gdx.gl30.glGenVertexArrays(1, temp);
|
||||||
|
VAO = temp.get(0);
|
||||||
|
|
||||||
|
Gdx.gl30.glBindVertexArray(VAO);
|
||||||
|
|
||||||
|
final String renderer = Gdx.gl.glGetString(GL20.GL_RENDERER);
|
||||||
|
System.err.println("Renderer: " + renderer);
|
||||||
|
|
||||||
|
this.codebase = WarsmashGdxMapScreen.parseDataSources(this.warsmashIni);
|
||||||
|
this.viewer = new MdxViewer(this.codebase, this, new Vector3(0.3f, 0.3f, -0.25f));
|
||||||
|
|
||||||
|
this.mdxHandler = new MdxHandler();
|
||||||
|
this.viewer.addHandler(this.mdxHandler);
|
||||||
|
this.viewer.enableAudio();
|
||||||
|
|
||||||
|
this.scene = this.viewer.addSimpleScene();
|
||||||
|
this.scene.enableAudio();
|
||||||
|
|
||||||
|
this.cameraManager = new PortraitCameraManager();
|
||||||
|
this.cameraManager.setupCamera(this.scene);
|
||||||
|
this.cameraManager.distance = 500;
|
||||||
|
this.cameraManager.horizontalAngle = (float) ((Math.PI) / 2);
|
||||||
|
|
||||||
|
System.out.println("Loaded");
|
||||||
|
Gdx.gl30.glClearColor(0.5f, 0.5f, 0.5f, 1); // TODO remove white background
|
||||||
|
|
||||||
|
this.font = new BitmapFont();
|
||||||
|
this.batch = new SpriteBatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void bindDefaultVertexArray() {
|
||||||
|
Gdx.gl30.glBindVertexArray(VAO);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int frame = 0;
|
||||||
|
private MdxComplexInstance mainInstance;
|
||||||
|
private MdxModel mainModel;
|
||||||
|
private com.etheller.warsmash.viewer5.handlers.mdx.Camera modelCamera;
|
||||||
|
private final float[] cameraPositionTemp = new float[3];
|
||||||
|
private final float[] cameraTargetTemp = new float[3];
|
||||||
|
private final boolean firstFrame = true;
|
||||||
|
private Scene scene;
|
||||||
|
private MdxHandler mdxHandler;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render() {
|
||||||
|
Gdx.gl30.glBindVertexArray(VAO);
|
||||||
|
this.cameraManager.updateCamera();
|
||||||
|
this.viewer.updateAndRender();
|
||||||
|
|
||||||
|
this.frame++;
|
||||||
|
if ((this.frame % 1000) == 0) {
|
||||||
|
System.out.println(Integer.toString(Gdx.graphics.getFramesPerSecond()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getWidth() {
|
||||||
|
return Gdx.graphics.getWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getHeight() {
|
||||||
|
return Gdx.graphics.getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resize(final int width, final int height) {
|
||||||
|
this.tempRect.width = width;
|
||||||
|
this.tempRect.height = height;
|
||||||
|
this.cameraManager.camera.viewport(this.tempRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataSource getCodebase() {
|
||||||
|
return this.codebase;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MdlxModel loadCustomModel(final String filename) {
|
||||||
|
clearMainInstance();
|
||||||
|
final MdxModel mdx = (MdxModel) this.mdxHandler.construct(new ResourceHandlerConstructionParams(this.viewer,
|
||||||
|
this.mdxHandler, ".mdx", PathSolver.DEFAULT, filename));
|
||||||
|
final MdlxModel mdlxModel;
|
||||||
|
try (FileInputStream stream = new FileInputStream(filename)) {
|
||||||
|
mdlxModel = MdxUtils.loadMdlx(stream);
|
||||||
|
mdx.load(mdlxModel);
|
||||||
|
mdx.ok = true;
|
||||||
|
// mdx.lateLoad();
|
||||||
|
}
|
||||||
|
catch (final FileNotFoundException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
catch (final IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
this.mainModel = mdx;
|
||||||
|
final MdxComplexInstance instance = (MdxComplexInstance) mdx.addInstance();
|
||||||
|
// this.cameraManager.setModelInstance(instance, mdx);
|
||||||
|
instance.setScene(this.scene);
|
||||||
|
this.mainInstance = instance;
|
||||||
|
return mdlxModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clearMainInstance() {
|
||||||
|
if (this.mainInstance != null) {
|
||||||
|
this.mainInstance.detach();
|
||||||
|
this.mainInstance = null;
|
||||||
|
}
|
||||||
|
this.mainModel = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PortraitCameraManager getCameraManager() {
|
||||||
|
return this.cameraManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MdxComplexInstance getMainInstance() {
|
||||||
|
return this.mainInstance;
|
||||||
|
}
|
||||||
|
}
|
113
core/src/com/etheller/warsmash/WarsmashTestGame.java
Normal file
113
core/src/com/etheller/warsmash/WarsmashTestGame.java
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
package com.etheller.warsmash;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
|
import java.nio.IntBuffer;
|
||||||
|
import java.nio.ShortBuffer;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.ApplicationAdapter;
|
||||||
|
import com.badlogic.gdx.Gdx;
|
||||||
|
import com.badlogic.gdx.graphics.GL20;
|
||||||
|
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
|
||||||
|
|
||||||
|
public class WarsmashTestGame extends ApplicationAdapter {
|
||||||
|
private int arrayBuffer;
|
||||||
|
private int elementBuffer;
|
||||||
|
private int VAO;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void create() {
|
||||||
|
Gdx.gl.glClearColor(0.5f, 0.5f, 0.5f, 1.0f); // colour to use when clearing
|
||||||
|
|
||||||
|
final ByteBuffer tempByteBuffer = ByteBuffer.allocateDirect(4);
|
||||||
|
tempByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
final IntBuffer temp = tempByteBuffer.asIntBuffer();
|
||||||
|
|
||||||
|
Gdx.gl30.glGenVertexArrays(1, temp);
|
||||||
|
this.VAO = temp.get(0);
|
||||||
|
|
||||||
|
Gdx.gl30.glBindVertexArray(this.VAO);
|
||||||
|
|
||||||
|
this.shaderProgram = new ShaderProgram(vsSimple, fsSimple);
|
||||||
|
if (!this.shaderProgram.isCompiled()) {
|
||||||
|
throw new IllegalStateException(this.shaderProgram.getLog());
|
||||||
|
}
|
||||||
|
|
||||||
|
this.arrayBuffer = Gdx.gl.glGenBuffer();
|
||||||
|
this.elementBuffer = Gdx.gl.glGenBuffer();
|
||||||
|
System.out.println("arrayBuffer: " + this.arrayBuffer + ", elementBuffer: " + this.elementBuffer);
|
||||||
|
|
||||||
|
Gdx.gl.glBindBuffer(GL20.GL_ARRAY_BUFFER, this.arrayBuffer);
|
||||||
|
|
||||||
|
this.shaderProgram.enableVertexAttribute("a_position");
|
||||||
|
this.shaderProgram.setVertexAttribute("a_position", 3, GL20.GL_FLOAT, false, 0, 0);
|
||||||
|
|
||||||
|
Gdx.gl.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER, this.elementBuffer);
|
||||||
|
|
||||||
|
final ByteBuffer vertexByteBuffer = ByteBuffer.allocateDirect(4 * 9);
|
||||||
|
vertexByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
this.vertexBuffer = vertexByteBuffer.asFloatBuffer();
|
||||||
|
|
||||||
|
this.vertexBuffer.put(0, -1f);
|
||||||
|
this.vertexBuffer.put(1, -1f);
|
||||||
|
this.vertexBuffer.put(2, 0);
|
||||||
|
this.vertexBuffer.put(3, 1f);
|
||||||
|
this.vertexBuffer.put(4, -1f);
|
||||||
|
this.vertexBuffer.put(5, 0);
|
||||||
|
this.vertexBuffer.put(6, 0f);
|
||||||
|
this.vertexBuffer.put(7, 1f);
|
||||||
|
this.vertexBuffer.put(8, 0);
|
||||||
|
|
||||||
|
Gdx.gl.glBufferData(GL20.GL_ARRAY_BUFFER, 9 * 4, null, GL20.GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
final ByteBuffer faceByteBuffer = ByteBuffer.allocateDirect(6);
|
||||||
|
faceByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
this.faceBuffer = faceByteBuffer.asShortBuffer();
|
||||||
|
|
||||||
|
this.faceBuffer.put(0, (short) 0);
|
||||||
|
this.faceBuffer.put(1, (short) 1);
|
||||||
|
this.faceBuffer.put(2, (short) 2);
|
||||||
|
|
||||||
|
Gdx.gl.glBufferData(GL20.GL_ELEMENT_ARRAY_BUFFER, 3 * 2, null, GL20.GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render() {
|
||||||
|
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
// Gdx.gl30.glBindVertexArray(this.VAO);
|
||||||
|
this.shaderProgram.begin();
|
||||||
|
Gdx.gl.glBindBuffer(GL20.GL_ARRAY_BUFFER, this.arrayBuffer);
|
||||||
|
Gdx.gl.glBufferSubData(GL20.GL_ARRAY_BUFFER, 0, 9 * 4, this.vertexBuffer);
|
||||||
|
Gdx.gl.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER, this.elementBuffer);
|
||||||
|
Gdx.gl.glBufferSubData(GL20.GL_ELEMENT_ARRAY_BUFFER, 0, 3 * 2, this.faceBuffer);
|
||||||
|
Gdx.gl.glDrawElements(GL20.GL_TRIANGLES, 9, GL20.GL_UNSIGNED_SHORT, 0);
|
||||||
|
// Gdx.gl.glDrawArrays(GL20.GL_TRIANGLES, 0, 3);
|
||||||
|
this.shaderProgram.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resize(final int width, final int height) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String vsSimple = "\r\n" + //
|
||||||
|
" attribute vec3 a_position;\r\n" + //
|
||||||
|
" void main() {\r\n" + //
|
||||||
|
" gl_Position = vec4(a_position, 1.0);\r\n" + //
|
||||||
|
" }\r\n";
|
||||||
|
|
||||||
|
public static final String fsSimple = "\r\n" + //
|
||||||
|
" void main() {\r\n" + //
|
||||||
|
" gl_FragColor = vec4(0.0, 1.0, 1.0, 1.0);\r\n" + //
|
||||||
|
" }\r\n";
|
||||||
|
private ShaderProgram shaderProgram;
|
||||||
|
private FloatBuffer vertexBuffer;
|
||||||
|
private ShortBuffer faceBuffer;
|
||||||
|
|
||||||
|
}
|
138
core/src/com/etheller/warsmash/WarsmashTestGame2.java
Normal file
138
core/src/com/etheller/warsmash/WarsmashTestGame2.java
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
package com.etheller.warsmash;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
|
import java.nio.IntBuffer;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.ApplicationAdapter;
|
||||||
|
import com.badlogic.gdx.Gdx;
|
||||||
|
import com.badlogic.gdx.graphics.GL20;
|
||||||
|
import com.badlogic.gdx.graphics.GL30;
|
||||||
|
|
||||||
|
public class WarsmashTestGame2 extends ApplicationAdapter {
|
||||||
|
private int VBO;
|
||||||
|
private int VAO;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void create() {
|
||||||
|
final ByteBuffer vertexByteBuffer = ByteBuffer.allocateDirect(4 * 9);
|
||||||
|
vertexByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
final FloatBuffer vertexBuffer = vertexByteBuffer.asFloatBuffer();
|
||||||
|
|
||||||
|
vertexBuffer.put(0, -0.5f);
|
||||||
|
vertexBuffer.put(1, -0.5f);
|
||||||
|
vertexBuffer.put(2, 0);
|
||||||
|
vertexBuffer.put(3, 0.5f);
|
||||||
|
vertexBuffer.put(4, -0.5f);
|
||||||
|
vertexBuffer.put(5, 0);
|
||||||
|
vertexBuffer.put(6, 0f);
|
||||||
|
vertexBuffer.put(7, 0.5f);
|
||||||
|
vertexBuffer.put(8, 0);
|
||||||
|
vertexBuffer.clear();
|
||||||
|
|
||||||
|
Gdx.gl30.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
Gdx.gl30.glEnable(GL20.GL_DEPTH_TEST);
|
||||||
|
// Gdx.gl30.glEnable(GL20.GL_CULL_FACE);
|
||||||
|
|
||||||
|
final ByteBuffer tempByteBuffer = ByteBuffer.allocateDirect(4);
|
||||||
|
System.out.println(tempByteBuffer.order());
|
||||||
|
tempByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
final IntBuffer temp = tempByteBuffer.asIntBuffer();
|
||||||
|
|
||||||
|
Gdx.gl30.glGenBuffers(1, temp);
|
||||||
|
this.VBO = temp.get(0);
|
||||||
|
|
||||||
|
temp.clear();
|
||||||
|
Gdx.gl30.glGenVertexArrays(1, temp);
|
||||||
|
this.VAO = temp.get(0);
|
||||||
|
|
||||||
|
Gdx.gl30.glBindVertexArray(this.VAO);
|
||||||
|
|
||||||
|
Gdx.gl30.glBindBuffer(GL30.GL_ARRAY_BUFFER, this.VBO);
|
||||||
|
Gdx.gl30.glBufferData(GL30.GL_ARRAY_BUFFER, 9 * 4, vertexByteBuffer, GL30.GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
Gdx.gl30.glVertexAttribPointer(0, 3, GL30.GL_FLOAT, false, 3 * 4, 0);
|
||||||
|
Gdx.gl30.glEnableVertexAttribArray(0);
|
||||||
|
|
||||||
|
final int vertexShader = Gdx.gl30.glCreateShader(GL30.GL_VERTEX_SHADER);
|
||||||
|
Gdx.gl30.glShaderSource(vertexShader, vsSimple);
|
||||||
|
Gdx.gl30.glCompileShader(vertexShader);
|
||||||
|
|
||||||
|
temp.clear();
|
||||||
|
Gdx.gl30.glGetShaderiv(vertexShader, GL30.GL_COMPILE_STATUS, temp);
|
||||||
|
int success = temp.get(0);
|
||||||
|
if (success == 0) {
|
||||||
|
final String infoLog = Gdx.gl30.glGetShaderInfoLog(vertexShader);
|
||||||
|
System.err.println(infoLog);
|
||||||
|
throw new IllegalStateException("bad vertex shader");
|
||||||
|
}
|
||||||
|
|
||||||
|
final int fragmentShader = Gdx.gl30.glCreateShader(GL30.GL_FRAGMENT_SHADER);
|
||||||
|
Gdx.gl30.glShaderSource(fragmentShader, fsSimple);
|
||||||
|
Gdx.gl30.glCompileShader(fragmentShader);
|
||||||
|
|
||||||
|
temp.clear();
|
||||||
|
Gdx.gl30.glGetShaderiv(fragmentShader, GL30.GL_COMPILE_STATUS, temp);
|
||||||
|
success = temp.get(0);
|
||||||
|
if (success == 0) {
|
||||||
|
final String infoLog = Gdx.gl30.glGetShaderInfoLog(fragmentShader);
|
||||||
|
System.err.println(infoLog);
|
||||||
|
throw new IllegalStateException("bad fragment shader");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.shaderProgram = Gdx.gl30.glCreateProgram();
|
||||||
|
|
||||||
|
Gdx.gl30.glAttachShader(this.shaderProgram, vertexShader);
|
||||||
|
Gdx.gl30.glAttachShader(this.shaderProgram, fragmentShader);
|
||||||
|
Gdx.gl30.glLinkProgram(this.shaderProgram);
|
||||||
|
|
||||||
|
temp.clear();
|
||||||
|
Gdx.gl30.glGetProgramiv(this.shaderProgram, GL30.GL_LINK_STATUS, temp);
|
||||||
|
success = temp.get(0);
|
||||||
|
if (success == 0) {
|
||||||
|
final String infoLog = Gdx.gl30.glGetProgramInfoLog(this.shaderProgram);
|
||||||
|
System.err.println(infoLog);
|
||||||
|
throw new IllegalStateException("bad program");
|
||||||
|
}
|
||||||
|
|
||||||
|
Gdx.gl30.glDeleteShader(vertexShader);
|
||||||
|
Gdx.gl30.glDeleteShader(fragmentShader);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render() {
|
||||||
|
Gdx.gl30.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
|
||||||
|
Gdx.gl30.glUseProgram(this.shaderProgram);
|
||||||
|
Gdx.gl30.glBindVertexArray(this.VAO);
|
||||||
|
|
||||||
|
Gdx.gl30.glDrawArrays(GL30.GL_TRIANGLES, 0, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resize(final int width, final int height) {
|
||||||
|
final int side = Math.min(width, height);
|
||||||
|
Gdx.gl30.glViewport((width - side) / 2, (height - side) / 2, side, side);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String vsSimple = "\r\n" + //
|
||||||
|
"#version 450 core\r\n" + //
|
||||||
|
" layout(location = 0) in vec3 aPos;\r\n" + //
|
||||||
|
" void main() {\r\n" + //
|
||||||
|
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\r\n" + //
|
||||||
|
" }\r\n";
|
||||||
|
|
||||||
|
public static final String fsSimple = "\r\n" + //
|
||||||
|
"#version 450 core\r\n" + //
|
||||||
|
" out vec4 FragColor;\r\n" + //
|
||||||
|
" void main() {\r\n" + //
|
||||||
|
" FragColor = vec4(0.2f, 1.0f, 0.2f, 1.0f);\r\n" + //
|
||||||
|
" }\r\n";
|
||||||
|
private int shaderProgram;
|
||||||
|
|
||||||
|
}
|
145
core/src/com/etheller/warsmash/WarsmashTestGame3.java
Normal file
145
core/src/com/etheller/warsmash/WarsmashTestGame3.java
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
package com.etheller.warsmash;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
|
import java.nio.IntBuffer;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.ApplicationAdapter;
|
||||||
|
import com.badlogic.gdx.Gdx;
|
||||||
|
import com.badlogic.gdx.graphics.GL20;
|
||||||
|
import com.badlogic.gdx.graphics.GL30;
|
||||||
|
|
||||||
|
public class WarsmashTestGame3 extends ApplicationAdapter {
|
||||||
|
private int VBO;
|
||||||
|
private int VAO;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void create() {
|
||||||
|
Gdx.gl30.glBindVertexArray(0);
|
||||||
|
|
||||||
|
this.vertexByteBuffer = ByteBuffer.allocateDirect(4 * 9);
|
||||||
|
this.vertexByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
final FloatBuffer vertexBuffer = this.vertexByteBuffer.asFloatBuffer();
|
||||||
|
|
||||||
|
vertexBuffer.put(0, -0.5f);
|
||||||
|
vertexBuffer.put(1, -0.5f);
|
||||||
|
vertexBuffer.put(2, 0);
|
||||||
|
vertexBuffer.put(3, 0.5f);
|
||||||
|
vertexBuffer.put(4, -0.5f);
|
||||||
|
vertexBuffer.put(5, 0);
|
||||||
|
vertexBuffer.put(6, 0f);
|
||||||
|
vertexBuffer.put(7, 0.5f);
|
||||||
|
vertexBuffer.put(8, 0);
|
||||||
|
vertexBuffer.clear();
|
||||||
|
|
||||||
|
Gdx.gl30.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
Gdx.gl30.glEnable(GL20.GL_DEPTH_TEST);
|
||||||
|
// Gdx.gl30.glEnable(GL20.GL_CULL_FACE);
|
||||||
|
|
||||||
|
final ByteBuffer tempByteBuffer = ByteBuffer.allocateDirect(4);
|
||||||
|
tempByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
final IntBuffer temp = tempByteBuffer.asIntBuffer();
|
||||||
|
|
||||||
|
Gdx.gl30.glGenVertexArrays(1, temp);
|
||||||
|
this.VAO = temp.get(0);
|
||||||
|
|
||||||
|
Gdx.gl30.glBindVertexArray(this.VAO);
|
||||||
|
|
||||||
|
temp.clear();
|
||||||
|
Gdx.gl30.glGenBuffers(1, temp);
|
||||||
|
this.VBO = temp.get(0);
|
||||||
|
|
||||||
|
Gdx.gl30.glBindBuffer(GL30.GL_ARRAY_BUFFER, this.VBO);
|
||||||
|
Gdx.gl30.glBufferData(GL30.GL_ARRAY_BUFFER, 9 * 4, this.vertexByteBuffer, GL30.GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
Gdx.gl30.glVertexAttribPointer(0, 3, GL30.GL_FLOAT, false, 3 * 4, 0);
|
||||||
|
Gdx.gl30.glEnableVertexAttribArray(0);
|
||||||
|
|
||||||
|
final int vertexShader = Gdx.gl30.glCreateShader(GL30.GL_VERTEX_SHADER);
|
||||||
|
Gdx.gl30.glShaderSource(vertexShader, vsSimple);
|
||||||
|
Gdx.gl30.glCompileShader(vertexShader);
|
||||||
|
|
||||||
|
temp.clear();
|
||||||
|
Gdx.gl30.glGetShaderiv(vertexShader, GL30.GL_COMPILE_STATUS, temp);
|
||||||
|
int success = temp.get(0);
|
||||||
|
if (success == 0) {
|
||||||
|
final String infoLog = Gdx.gl30.glGetShaderInfoLog(vertexShader);
|
||||||
|
System.err.println(infoLog);
|
||||||
|
throw new IllegalStateException("bad vertex shader");
|
||||||
|
}
|
||||||
|
|
||||||
|
final int fragmentShader = Gdx.gl30.glCreateShader(GL30.GL_FRAGMENT_SHADER);
|
||||||
|
Gdx.gl30.glShaderSource(fragmentShader, fsSimple);
|
||||||
|
Gdx.gl30.glCompileShader(fragmentShader);
|
||||||
|
|
||||||
|
temp.clear();
|
||||||
|
Gdx.gl30.glGetShaderiv(fragmentShader, GL30.GL_COMPILE_STATUS, temp);
|
||||||
|
success = temp.get(0);
|
||||||
|
if (success == 0) {
|
||||||
|
final String infoLog = Gdx.gl30.glGetShaderInfoLog(fragmentShader);
|
||||||
|
System.err.println(infoLog);
|
||||||
|
throw new IllegalStateException("bad fragment shader");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.shaderProgram = Gdx.gl30.glCreateProgram();
|
||||||
|
|
||||||
|
Gdx.gl30.glAttachShader(this.shaderProgram, vertexShader);
|
||||||
|
Gdx.gl30.glAttachShader(this.shaderProgram, fragmentShader);
|
||||||
|
Gdx.gl30.glLinkProgram(this.shaderProgram);
|
||||||
|
|
||||||
|
temp.clear();
|
||||||
|
Gdx.gl30.glGetProgramiv(this.shaderProgram, GL30.GL_LINK_STATUS, temp);
|
||||||
|
success = temp.get(0);
|
||||||
|
if (success == 0) {
|
||||||
|
final String infoLog = Gdx.gl30.glGetProgramInfoLog(this.shaderProgram);
|
||||||
|
System.err.println(infoLog);
|
||||||
|
throw new IllegalStateException("bad program");
|
||||||
|
}
|
||||||
|
|
||||||
|
Gdx.gl30.glDeleteShader(vertexShader);
|
||||||
|
Gdx.gl30.glDeleteShader(fragmentShader);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render() {
|
||||||
|
|
||||||
|
Gdx.gl30.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
|
||||||
|
Gdx.gl30.glBindVertexArray(this.VAO);
|
||||||
|
Gdx.gl30.glUseProgram(this.shaderProgram);
|
||||||
|
Gdx.gl30.glBindBuffer(GL30.GL_ARRAY_BUFFER, this.VBO);
|
||||||
|
Gdx.gl30.glVertexAttribPointer(0, 3, GL30.GL_FLOAT, false, 3 * 4, 0);
|
||||||
|
Gdx.gl30.glEnableVertexAttribArray(0);
|
||||||
|
|
||||||
|
Gdx.gl30.glDrawArrays(GL30.GL_TRIANGLES, 0, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resize(final int width, final int height) {
|
||||||
|
final int side = Math.min(width, height);
|
||||||
|
Gdx.gl30.glViewport((width - side) / 2, (height - side) / 2, side, side);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String vsSimple = "\r\n" + //
|
||||||
|
"#version 450 core\r\n" + //
|
||||||
|
" layout(location = 0) in vec3 aPos;\r\n" + //
|
||||||
|
" void main() {\r\n" + //
|
||||||
|
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\r\n" + //
|
||||||
|
" }\r\n";
|
||||||
|
|
||||||
|
public static final String fsSimple = "\r\n" + //
|
||||||
|
"#version 450 core\r\n" + //
|
||||||
|
" out vec4 FragColor;\r\n" + //
|
||||||
|
" void main() {\r\n" + //
|
||||||
|
" FragColor = vec4(0.2f, 1.0f, 0.2f, 1.0f);\r\n" + //
|
||||||
|
" }\r\n";
|
||||||
|
private int shaderProgram;
|
||||||
|
|
||||||
|
private ByteBuffer vertexByteBuffer;
|
||||||
|
|
||||||
|
}
|
163
core/src/com/etheller/warsmash/WarsmashTestGameAttributes.java
Normal file
163
core/src/com/etheller/warsmash/WarsmashTestGameAttributes.java
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
package com.etheller.warsmash;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
|
import java.nio.IntBuffer;
|
||||||
|
import java.nio.ShortBuffer;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.ApplicationAdapter;
|
||||||
|
import com.badlogic.gdx.Gdx;
|
||||||
|
import com.badlogic.gdx.graphics.GL20;
|
||||||
|
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
|
||||||
|
|
||||||
|
public class WarsmashTestGameAttributes extends ApplicationAdapter {
|
||||||
|
private int arrayBuffer;
|
||||||
|
private int elementBuffer;
|
||||||
|
private int VAO;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void create() {
|
||||||
|
Gdx.gl.glClearColor(0.5f, 0.5f, 0.5f, 1.0f); // colour to use when clearing
|
||||||
|
|
||||||
|
final ByteBuffer tempByteBuffer = ByteBuffer.allocateDirect(4);
|
||||||
|
tempByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
final IntBuffer temp = tempByteBuffer.asIntBuffer();
|
||||||
|
|
||||||
|
Gdx.gl30.glGenVertexArrays(1, temp);
|
||||||
|
this.VAO = temp.get(0);
|
||||||
|
|
||||||
|
Gdx.gl30.glBindVertexArray(this.VAO);
|
||||||
|
|
||||||
|
this.shaderProgram = new ShaderProgram(vsSimple, fsSimple);
|
||||||
|
if (!this.shaderProgram.isCompiled()) {
|
||||||
|
throw new IllegalStateException(this.shaderProgram.getLog());
|
||||||
|
}
|
||||||
|
|
||||||
|
this.arrayBuffer = Gdx.gl.glGenBuffer();
|
||||||
|
this.elementBuffer = Gdx.gl.glGenBuffer();
|
||||||
|
System.out.println("arrayBuffer: " + this.arrayBuffer + ", elementBuffer: " + this.elementBuffer);
|
||||||
|
|
||||||
|
Gdx.gl.glBindBuffer(GL20.GL_ARRAY_BUFFER, this.arrayBuffer);
|
||||||
|
|
||||||
|
Gdx.gl.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER, this.elementBuffer);
|
||||||
|
|
||||||
|
final ByteBuffer vertexByteBuffer = ByteBuffer.allocateDirect(4 * 9);
|
||||||
|
vertexByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
this.vertexBuffer = vertexByteBuffer.asFloatBuffer();
|
||||||
|
|
||||||
|
this.vertexBuffer.put(0, -1f);
|
||||||
|
this.vertexBuffer.put(1, -1f);
|
||||||
|
this.vertexBuffer.put(2, 0);
|
||||||
|
this.vertexBuffer.put(3, 1f);
|
||||||
|
this.vertexBuffer.put(4, -1f);
|
||||||
|
this.vertexBuffer.put(5, 0);
|
||||||
|
this.vertexBuffer.put(6, 0f);
|
||||||
|
this.vertexBuffer.put(7, 1f);
|
||||||
|
this.vertexBuffer.put(8, 0);
|
||||||
|
|
||||||
|
Gdx.gl.glBufferData(GL20.GL_ARRAY_BUFFER, ((9 * 4) * 2) + 3, null, GL20.GL_STATIC_DRAW);
|
||||||
|
Gdx.gl.glBufferSubData(GL20.GL_ARRAY_BUFFER, 0, 9 * 4, this.vertexBuffer);
|
||||||
|
|
||||||
|
final ByteBuffer vertex2ByteBuffer = ByteBuffer.allocateDirect(4 * 9);
|
||||||
|
vertex2ByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
final FloatBuffer vertexBuffer2 = vertex2ByteBuffer.asFloatBuffer();
|
||||||
|
|
||||||
|
vertexBuffer2.put(0, -1f);
|
||||||
|
vertexBuffer2.put(1, -1f);
|
||||||
|
vertexBuffer2.put(2, 0);
|
||||||
|
vertexBuffer2.put(3, 1f);
|
||||||
|
vertexBuffer2.put(4, -1f);
|
||||||
|
vertexBuffer2.put(5, 0);
|
||||||
|
vertexBuffer2.put(6, 0f);
|
||||||
|
vertexBuffer2.put(7, 1f);
|
||||||
|
vertexBuffer2.put(8, 0);
|
||||||
|
|
||||||
|
Gdx.gl.glBufferSubData(GL20.GL_ARRAY_BUFFER, 9 * 4, 9 * 4, vertexBuffer2);
|
||||||
|
|
||||||
|
final ByteBuffer skinByteBuffer = ByteBuffer.allocateDirect(3);
|
||||||
|
skinByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
skinByteBuffer.put((byte) 34);
|
||||||
|
skinByteBuffer.put((byte) 35);
|
||||||
|
skinByteBuffer.put((byte) 36);
|
||||||
|
skinByteBuffer.clear();
|
||||||
|
Gdx.gl.glBufferSubData(GL20.GL_ARRAY_BUFFER, 9 * 4 * 2, 3, skinByteBuffer);
|
||||||
|
|
||||||
|
// this.shaderProgram.setVertexAttribute("a_position", 3, GL20.GL_FLOAT, false, 0, 0);
|
||||||
|
// this.shaderProgram.enableVertexAttribute("a_position");
|
||||||
|
// this.shaderProgram.setVertexAttribute("a_position2", 3, GL20.GL_FLOAT, false, 0, 4 * 9);
|
||||||
|
// this.shaderProgram.enableVertexAttribute("a_position2");
|
||||||
|
// this.shaderProgram.setVertexAttribute("a_boneNumber", 1, GL20.GL_UNSIGNED_BYTE, false, 1, 4 * 9 * 2);
|
||||||
|
// this.shaderProgram.enableVertexAttribute("a_boneNumber");
|
||||||
|
|
||||||
|
final ByteBuffer faceByteBuffer = ByteBuffer.allocateDirect(6);
|
||||||
|
faceByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
this.faceBuffer = faceByteBuffer.asShortBuffer();
|
||||||
|
|
||||||
|
this.faceBuffer.put(0, (short) 0);
|
||||||
|
this.faceBuffer.put(1, (short) 1);
|
||||||
|
this.faceBuffer.put(2, (short) 2);
|
||||||
|
|
||||||
|
Gdx.gl.glBufferData(GL20.GL_ELEMENT_ARRAY_BUFFER, 3 * 2, null, GL20.GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
final int glGetError = Gdx.gl.glGetError();
|
||||||
|
System.out.println(glGetError);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render() {
|
||||||
|
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
// Gdx.gl30.glBindVertexArray(this.VAO);
|
||||||
|
this.shaderProgram.begin();
|
||||||
|
|
||||||
|
Gdx.gl.glBindBuffer(GL20.GL_ARRAY_BUFFER, this.arrayBuffer);
|
||||||
|
this.shaderProgram.setVertexAttribute("a_position", 3, GL20.GL_FLOAT, false, 0, 0);
|
||||||
|
this.shaderProgram.enableVertexAttribute("a_position");
|
||||||
|
this.shaderProgram.setVertexAttribute("a_position2", 3, GL20.GL_FLOAT, false, 0, 4 * 9);
|
||||||
|
this.shaderProgram.enableVertexAttribute("a_position2");
|
||||||
|
this.shaderProgram.setVertexAttribute("a_boneNumber", 1, GL20.GL_UNSIGNED_BYTE, false, 1, 4 * 9 * 2);
|
||||||
|
this.shaderProgram.enableVertexAttribute("a_boneNumber");
|
||||||
|
Gdx.gl.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER, this.elementBuffer);
|
||||||
|
Gdx.gl.glBufferSubData(GL20.GL_ELEMENT_ARRAY_BUFFER, 0, 3 * 2, this.faceBuffer);
|
||||||
|
Gdx.gl.glDrawElements(GL20.GL_TRIANGLES, 3, GL20.GL_UNSIGNED_SHORT, 0);
|
||||||
|
// Gdx.gl.glDrawArrays(GL20.GL_TRIANGLES, 0, 3);
|
||||||
|
this.shaderProgram.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resize(final int width, final int height) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String vsSimple = "\r\n" + //
|
||||||
|
" attribute vec3 a_position;\r\n" + //
|
||||||
|
" attribute vec3 a_position2;\r\n" + //
|
||||||
|
" attribute float a_boneNumber;\r\n" + //
|
||||||
|
" varying float fragNumber;\r\n" + //
|
||||||
|
" void main() {\r\n" + //
|
||||||
|
" gl_Position = vec4(a_position2.x, a_position2.y, a_position2.z, 1.0);\r\n" + //
|
||||||
|
" fragNumber = a_boneNumber;\r\n" + //
|
||||||
|
" }\r\n";
|
||||||
|
|
||||||
|
public static final String fsSimple = "\r\n" + //
|
||||||
|
" varying float fragNumber;\r\n" + //
|
||||||
|
" void main() {\r\n" + //
|
||||||
|
" if( fragNumber > 35.5 ) {\r\n" + //
|
||||||
|
" gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\r\n" + //
|
||||||
|
" } else if( fragNumber > 34.5 ) {\r\n" + //
|
||||||
|
" gl_FragColor = vec4(0.0, 1.0, 1.0, 1.0);\r\n" + //
|
||||||
|
" } else if( fragNumber > 33.5 ) {\r\n" + //
|
||||||
|
" gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);\r\n" + //
|
||||||
|
" } else {\r\n" + //
|
||||||
|
" gl_FragColor = vec4(fragNumber*100.0, fragNumber, fragNumber, 1.0);\r\n" + //
|
||||||
|
" }\r\n" + //
|
||||||
|
" }\r\n";
|
||||||
|
private ShaderProgram shaderProgram;
|
||||||
|
private FloatBuffer vertexBuffer;
|
||||||
|
private ShortBuffer faceBuffer;
|
||||||
|
|
||||||
|
}
|
213
core/src/com/etheller/warsmash/WarsmashTestGameAttributes2.java
Normal file
213
core/src/com/etheller/warsmash/WarsmashTestGameAttributes2.java
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
package com.etheller.warsmash;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
|
import java.nio.IntBuffer;
|
||||||
|
import java.nio.ShortBuffer;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.ApplicationAdapter;
|
||||||
|
import com.badlogic.gdx.Gdx;
|
||||||
|
import com.badlogic.gdx.graphics.GL20;
|
||||||
|
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
|
||||||
|
import com.etheller.warsmash.datasources.CompoundDataSourceDescriptor;
|
||||||
|
import com.etheller.warsmash.datasources.DataSource;
|
||||||
|
import com.etheller.warsmash.datasources.DataSourceDescriptor;
|
||||||
|
import com.etheller.warsmash.datasources.FolderDataSourceDescriptor;
|
||||||
|
import com.hiveworkshop.rms.parsers.mdlx.MdlxGeoset;
|
||||||
|
import com.hiveworkshop.rms.parsers.mdlx.MdlxModel;
|
||||||
|
|
||||||
|
public class WarsmashTestGameAttributes2 extends ApplicationAdapter {
|
||||||
|
private int arrayBuffer;
|
||||||
|
private int elementBuffer;
|
||||||
|
private int VAO;
|
||||||
|
private DataSource codebase;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void create() {
|
||||||
|
final FolderDataSourceDescriptor war3mpq = new FolderDataSourceDescriptor(
|
||||||
|
"D:\\NEEDS_ORGANIZING\\MPQBuild\\War3.mpq\\war3.mpq");
|
||||||
|
final FolderDataSourceDescriptor testingFolder = new FolderDataSourceDescriptor(
|
||||||
|
"D:\\NEEDS_ORGANIZING\\MPQBuild\\Test");
|
||||||
|
this.codebase = new CompoundDataSourceDescriptor(Arrays.<DataSourceDescriptor>asList(war3mpq, testingFolder))
|
||||||
|
.createDataSource();
|
||||||
|
|
||||||
|
final MdlxModel model;
|
||||||
|
try {
|
||||||
|
model = new MdlxModel(this.codebase.read("Buildings\\Other\\TempArtB\\TempArtB.mdx"));
|
||||||
|
}
|
||||||
|
catch (final IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
Gdx.gl.glClearColor(0.5f, 0.5f, 0.5f, 1.0f); // colour to use when clearing
|
||||||
|
|
||||||
|
final ByteBuffer tempByteBuffer = ByteBuffer.allocateDirect(4);
|
||||||
|
tempByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
final IntBuffer temp = tempByteBuffer.asIntBuffer();
|
||||||
|
|
||||||
|
Gdx.gl30.glGenVertexArrays(1, temp);
|
||||||
|
this.VAO = temp.get(0);
|
||||||
|
|
||||||
|
Gdx.gl30.glBindVertexArray(this.VAO);
|
||||||
|
|
||||||
|
this.shaderProgram = new ShaderProgram(vsSimple, fsSimple);
|
||||||
|
if (!this.shaderProgram.isCompiled()) {
|
||||||
|
throw new IllegalStateException(this.shaderProgram.getLog());
|
||||||
|
}
|
||||||
|
|
||||||
|
this.arrayBuffer = Gdx.gl.glGenBuffer();
|
||||||
|
this.elementBuffer = Gdx.gl.glGenBuffer();
|
||||||
|
System.out.println("arrayBuffer: " + this.arrayBuffer + ", elementBuffer: " + this.elementBuffer);
|
||||||
|
|
||||||
|
Gdx.gl.glBindBuffer(GL20.GL_ARRAY_BUFFER, this.arrayBuffer);
|
||||||
|
|
||||||
|
Gdx.gl.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER, this.elementBuffer);
|
||||||
|
|
||||||
|
final MdlxGeoset geoset0 = model.getGeosets().get(0);
|
||||||
|
final float[] vertices = geoset0.getVertices();
|
||||||
|
final ByteBuffer vertexByteBuffer = ByteBuffer.allocateDirect(4 * 9);
|
||||||
|
vertexByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
this.vertexBuffer = vertexByteBuffer.asFloatBuffer();
|
||||||
|
|
||||||
|
this.vertexBuffer.put(0, -1f);
|
||||||
|
this.vertexBuffer.put(1, -1f);
|
||||||
|
this.vertexBuffer.put(2, 0);
|
||||||
|
this.vertexBuffer.put(3, 1f);
|
||||||
|
this.vertexBuffer.put(4, -1f);
|
||||||
|
this.vertexBuffer.put(5, 0);
|
||||||
|
this.vertexBuffer.put(6, 0f);
|
||||||
|
this.vertexBuffer.put(7, 1f);
|
||||||
|
this.vertexBuffer.put(8, 0);
|
||||||
|
|
||||||
|
Gdx.gl.glBufferData(GL20.GL_ARRAY_BUFFER, ((9 * 4) * 2) + 3, null, GL20.GL_STATIC_DRAW);
|
||||||
|
Gdx.gl.glBufferSubData(GL20.GL_ARRAY_BUFFER, 0, 9 * 4, this.vertexBuffer);
|
||||||
|
|
||||||
|
final ByteBuffer vertex2ByteBuffer = ByteBuffer.allocateDirect(4 * 9);
|
||||||
|
vertex2ByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
final FloatBuffer vertexBuffer2 = vertex2ByteBuffer.asFloatBuffer();
|
||||||
|
|
||||||
|
vertexBuffer2.put(0, -1f);
|
||||||
|
vertexBuffer2.put(1, -1f);
|
||||||
|
vertexBuffer2.put(2, 0);
|
||||||
|
vertexBuffer2.put(3, 1f);
|
||||||
|
vertexBuffer2.put(4, -1f);
|
||||||
|
vertexBuffer2.put(5, 0);
|
||||||
|
vertexBuffer2.put(6, 0f);
|
||||||
|
vertexBuffer2.put(7, 1f);
|
||||||
|
vertexBuffer2.put(8, 0);
|
||||||
|
|
||||||
|
Gdx.gl.glBufferSubData(GL20.GL_ARRAY_BUFFER, 9 * 4, 9 * 4, vertexBuffer2);
|
||||||
|
|
||||||
|
final ByteBuffer skinByteBuffer = ByteBuffer.allocateDirect(3);
|
||||||
|
skinByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
skinByteBuffer.put((byte) 34);
|
||||||
|
skinByteBuffer.put((byte) 35);
|
||||||
|
skinByteBuffer.put((byte) 36);
|
||||||
|
skinByteBuffer.clear();
|
||||||
|
Gdx.gl.glBufferSubData(GL20.GL_ARRAY_BUFFER, 9 * 4 * 2, 3, skinByteBuffer);
|
||||||
|
|
||||||
|
// this.shaderProgram.setVertexAttribute("a_position", 3, GL20.GL_FLOAT, false, 0, 0);
|
||||||
|
// this.shaderProgram.enableVertexAttribute("a_position");
|
||||||
|
// this.shaderProgram.setVertexAttribute("a_position2", 3, GL20.GL_FLOAT, false, 0, 4 * 9);
|
||||||
|
// this.shaderProgram.enableVertexAttribute("a_position2");
|
||||||
|
// this.shaderProgram.setVertexAttribute("a_boneNumber", 1, GL20.GL_UNSIGNED_BYTE, false, 1, 4 * 9 * 2);
|
||||||
|
// this.shaderProgram.enableVertexAttribute("a_boneNumber");
|
||||||
|
|
||||||
|
final ByteBuffer faceByteBuffer = ByteBuffer.allocateDirect(6);
|
||||||
|
faceByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
this.faceBuffer = faceByteBuffer.asShortBuffer();
|
||||||
|
|
||||||
|
this.faceBuffer.put(0, (short) 0);
|
||||||
|
this.faceBuffer.put(1, (short) 1);
|
||||||
|
this.faceBuffer.put(2, (short) 2);
|
||||||
|
|
||||||
|
Gdx.gl.glBufferData(GL20.GL_ELEMENT_ARRAY_BUFFER, 3 * 2, null, GL20.GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
final int glGetError = Gdx.gl.glGetError();
|
||||||
|
System.out.println(glGetError);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render() {
|
||||||
|
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
// Gdx.gl30.glBindVertexArray(this.VAO);
|
||||||
|
this.shaderProgram.begin();
|
||||||
|
|
||||||
|
Gdx.gl.glBindBuffer(GL20.GL_ARRAY_BUFFER, this.arrayBuffer);
|
||||||
|
this.shaderProgram.setVertexAttribute("a_position", 3, GL20.GL_FLOAT, false, 0, 0);
|
||||||
|
this.shaderProgram.enableVertexAttribute("a_position");
|
||||||
|
this.shaderProgram.setVertexAttribute("a_position2", 3, GL20.GL_FLOAT, false, 0, 4 * 9);
|
||||||
|
this.shaderProgram.enableVertexAttribute("a_position2");
|
||||||
|
this.shaderProgram.setVertexAttribute("a_boneNumber", 1, GL20.GL_UNSIGNED_BYTE, false, 1, 4 * 9 * 2);
|
||||||
|
this.shaderProgram.enableVertexAttribute("a_boneNumber");
|
||||||
|
Gdx.gl.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER, this.elementBuffer);
|
||||||
|
Gdx.gl.glBufferSubData(GL20.GL_ELEMENT_ARRAY_BUFFER, 0, 3 * 2, this.faceBuffer);
|
||||||
|
Gdx.gl.glDrawElements(GL20.GL_TRIANGLES, 3, GL20.GL_UNSIGNED_SHORT, 0);
|
||||||
|
// Gdx.gl.glDrawArrays(GL20.GL_TRIANGLES, 0, 3);
|
||||||
|
this.shaderProgram.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resize(final int width, final int height) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String vsSimple = "\r\n" + //
|
||||||
|
" attribute vec3 a_position;\r\n" + //
|
||||||
|
" attribute vec3 a_position2;\r\n" + //
|
||||||
|
" attribute float a_boneNumber;\r\n" + //
|
||||||
|
" varying float fragNumber;\r\n" + //
|
||||||
|
" void main() {\r\n" + //
|
||||||
|
" gl_Position = vec4(a_position2.x, a_position2.y, a_position2.z, 1.0);\r\n" + //
|
||||||
|
" fragNumber = a_boneNumber;\r\n" + //
|
||||||
|
" }\r\n";
|
||||||
|
|
||||||
|
public static final String fsSimple = "\r\n" + //
|
||||||
|
" varying float fragNumber;\r\n" + //
|
||||||
|
" void main() {\r\n" + //
|
||||||
|
" if( fragNumber > 35.5 ) {\r\n" + //
|
||||||
|
" gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\r\n" + //
|
||||||
|
" } else if( fragNumber > 34.5 ) {\r\n" + //
|
||||||
|
" gl_FragColor = vec4(0.0, 1.0, 1.0, 1.0);\r\n" + //
|
||||||
|
" } else if( fragNumber > 33.5 ) {\r\n" + //
|
||||||
|
" gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);\r\n" + //
|
||||||
|
" } else {\r\n" + //
|
||||||
|
" gl_FragColor = vec4(fragNumber*100.0, fragNumber, fragNumber, 1.0);\r\n" + //
|
||||||
|
" }\r\n" + //
|
||||||
|
" }\r\n";
|
||||||
|
private ShaderProgram shaderProgram;
|
||||||
|
private FloatBuffer vertexBuffer;
|
||||||
|
private ShortBuffer faceBuffer;
|
||||||
|
|
||||||
|
private static ShortBuffer wrapFaces(final int[] faces) {
|
||||||
|
final ShortBuffer wrapper = ByteBuffer.allocateDirect(faces.length * 2).order(ByteOrder.nativeOrder())
|
||||||
|
.asShortBuffer();
|
||||||
|
for (final int face : faces) {
|
||||||
|
wrapper.put((short) face);
|
||||||
|
}
|
||||||
|
wrapper.clear();
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ByteBuffer wrap(final byte[] skin) {
|
||||||
|
final ByteBuffer wrapper = ByteBuffer.allocateDirect(skin.length).order(ByteOrder.nativeOrder());
|
||||||
|
wrapper.put(skin);
|
||||||
|
wrapper.clear();
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static FloatBuffer wrap(final float[] positions) {
|
||||||
|
final FloatBuffer wrapper = ByteBuffer.allocateDirect(positions.length * 4).order(ByteOrder.nativeOrder())
|
||||||
|
.asFloatBuffer();
|
||||||
|
wrapper.put(positions);
|
||||||
|
wrapper.clear();
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,244 @@
|
|||||||
|
package com.etheller.warsmash;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
|
import java.nio.IntBuffer;
|
||||||
|
import java.nio.ShortBuffer;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.ApplicationAdapter;
|
||||||
|
import com.badlogic.gdx.Gdx;
|
||||||
|
import com.badlogic.gdx.graphics.GL20;
|
||||||
|
import com.badlogic.gdx.graphics.GL30;
|
||||||
|
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
|
||||||
|
import com.etheller.warsmash.viewer5.Shaders;
|
||||||
|
|
||||||
|
public class WarsmashTestGameTextureBuffer extends ApplicationAdapter {
|
||||||
|
private int arrayBuffer;
|
||||||
|
private int elementBuffer;
|
||||||
|
private int VAO;
|
||||||
|
private ShaderProgram shaderProgram;
|
||||||
|
private FloatBuffer vertexBuffer;
|
||||||
|
private ShortBuffer faceBuffer;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void create() {
|
||||||
|
// ShaderProgram.pedantic = false;
|
||||||
|
Gdx.gl.glClearColor(0.5f, 0.5f, 0.5f, 1.0f); // colour to use when clearing
|
||||||
|
|
||||||
|
final ByteBuffer tempByteBuffer = ByteBuffer.allocateDirect(4);
|
||||||
|
tempByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
final IntBuffer temp = tempByteBuffer.asIntBuffer();
|
||||||
|
|
||||||
|
Gdx.gl30.glGenVertexArrays(1, temp);
|
||||||
|
this.VAO = temp.get(0);
|
||||||
|
|
||||||
|
Gdx.gl30.glBindVertexArray(this.VAO);
|
||||||
|
|
||||||
|
System.out.println(vsSimple);
|
||||||
|
this.shaderProgram = new ShaderProgram(vsSimple, fsSimple);
|
||||||
|
if (!this.shaderProgram.isCompiled()) {
|
||||||
|
throw new IllegalStateException(this.shaderProgram.getLog());
|
||||||
|
}
|
||||||
|
|
||||||
|
this.arrayBuffer = Gdx.gl.glGenBuffer();
|
||||||
|
this.elementBuffer = Gdx.gl.glGenBuffer();
|
||||||
|
System.out.println("arrayBuffer: " + this.arrayBuffer + ", elementBuffer: " + this.elementBuffer);
|
||||||
|
|
||||||
|
Gdx.gl.glBindBuffer(GL20.GL_ARRAY_BUFFER, this.arrayBuffer);
|
||||||
|
|
||||||
|
Gdx.gl.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER, this.elementBuffer);
|
||||||
|
|
||||||
|
final ByteBuffer vertexByteBuffer = ByteBuffer.allocateDirect(4 * 9);
|
||||||
|
vertexByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
this.vertexBuffer = vertexByteBuffer.asFloatBuffer();
|
||||||
|
|
||||||
|
this.vertexBuffer.put(0, -1f);
|
||||||
|
this.vertexBuffer.put(1, -1f);
|
||||||
|
this.vertexBuffer.put(2, 0);
|
||||||
|
this.vertexBuffer.put(3, 1f);
|
||||||
|
this.vertexBuffer.put(4, -1f);
|
||||||
|
this.vertexBuffer.put(5, 0);
|
||||||
|
this.vertexBuffer.put(6, 0f);
|
||||||
|
this.vertexBuffer.put(7, 1f);
|
||||||
|
this.vertexBuffer.put(8, 0);
|
||||||
|
|
||||||
|
Gdx.gl.glBufferData(GL20.GL_ARRAY_BUFFER, ((9 * 4) * 2) + 3, null, GL20.GL_STATIC_DRAW);
|
||||||
|
Gdx.gl.glBufferSubData(GL20.GL_ARRAY_BUFFER, 0, 9 * 4, this.vertexBuffer);
|
||||||
|
|
||||||
|
final ByteBuffer vertex2ByteBuffer = ByteBuffer.allocateDirect(4 * 9);
|
||||||
|
vertex2ByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
final FloatBuffer vertexBuffer2 = vertex2ByteBuffer.asFloatBuffer();
|
||||||
|
|
||||||
|
vertexBuffer2.put(0, -1f);
|
||||||
|
vertexBuffer2.put(1, -1f);
|
||||||
|
vertexBuffer2.put(2, 0);
|
||||||
|
vertexBuffer2.put(3, 1f);
|
||||||
|
vertexBuffer2.put(4, -1f);
|
||||||
|
vertexBuffer2.put(5, 0);
|
||||||
|
vertexBuffer2.put(6, 0f);
|
||||||
|
vertexBuffer2.put(7, 1f);
|
||||||
|
vertexBuffer2.put(8, 0);
|
||||||
|
|
||||||
|
Gdx.gl.glBufferSubData(GL20.GL_ARRAY_BUFFER, 9 * 4, 9 * 4, vertexBuffer2);
|
||||||
|
|
||||||
|
final ByteBuffer skinByteBuffer = ByteBuffer.allocateDirect(3);
|
||||||
|
skinByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
skinByteBuffer.put((byte) 34);
|
||||||
|
skinByteBuffer.put((byte) 35);
|
||||||
|
skinByteBuffer.put((byte) 36);
|
||||||
|
skinByteBuffer.clear();
|
||||||
|
Gdx.gl.glBufferSubData(GL20.GL_ARRAY_BUFFER, 9 * 4 * 2, 3, skinByteBuffer);
|
||||||
|
|
||||||
|
// this.shaderProgram.setVertexAttribute("a_position", 3, GL20.GL_FLOAT, false, 0, 0);
|
||||||
|
// this.shaderProgram.enableVertexAttribute("a_position");
|
||||||
|
// this.shaderProgram.setVertexAttribute("a_position2", 3, GL20.GL_FLOAT, false, 0, 4 * 9);
|
||||||
|
// this.shaderProgram.enableVertexAttribute("a_position2");
|
||||||
|
// this.shaderProgram.setVertexAttribute("a_boneNumber", 1, GL20.GL_UNSIGNED_BYTE, false, 1, 4 * 9 * 2);
|
||||||
|
// this.shaderProgram.enableVertexAttribute("a_boneNumber");
|
||||||
|
// this.shaderProgram.setUniformi("u_boneMap", 15);
|
||||||
|
|
||||||
|
final ByteBuffer faceByteBuffer = ByteBuffer.allocateDirect(6);
|
||||||
|
faceByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
this.faceBuffer = faceByteBuffer.asShortBuffer();
|
||||||
|
|
||||||
|
this.faceBuffer.put(0, (short) 0);
|
||||||
|
this.faceBuffer.put(1, (short) 1);
|
||||||
|
this.faceBuffer.put(2, (short) 2);
|
||||||
|
|
||||||
|
Gdx.gl.glBufferData(GL20.GL_ELEMENT_ARRAY_BUFFER, 3 * 2, null, GL20.GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
final int glGetError = Gdx.gl.glGetError();
|
||||||
|
System.out.println(glGetError);
|
||||||
|
|
||||||
|
final ByteBuffer vertex3ByteBuffer = ByteBuffer.allocateDirect(4 * 16);
|
||||||
|
vertex3ByteBuffer.order(ByteOrder.nativeOrder());
|
||||||
|
this.vertexTextureBuffer3 = vertex3ByteBuffer.asFloatBuffer();
|
||||||
|
|
||||||
|
this.vertexTextureBuffer3.put(0, 0.5f);
|
||||||
|
this.vertexTextureBuffer3.put(1, 0);
|
||||||
|
this.vertexTextureBuffer3.put(2, 0);
|
||||||
|
this.vertexTextureBuffer3.put(3, 0);
|
||||||
|
this.vertexTextureBuffer3.put(4, 0);
|
||||||
|
this.vertexTextureBuffer3.put(5, 1);
|
||||||
|
this.vertexTextureBuffer3.put(6, 0);
|
||||||
|
this.vertexTextureBuffer3.put(7, 0);
|
||||||
|
this.vertexTextureBuffer3.put(8, 0);
|
||||||
|
this.vertexTextureBuffer3.put(9, 0);
|
||||||
|
this.vertexTextureBuffer3.put(10, 1);
|
||||||
|
this.vertexTextureBuffer3.put(11, 0);
|
||||||
|
this.vertexTextureBuffer3.put(12, 0.0f);
|
||||||
|
this.vertexTextureBuffer3.put(13, 0.0f);
|
||||||
|
this.vertexTextureBuffer3.put(14, 0);
|
||||||
|
this.vertexTextureBuffer3.put(15, 1);
|
||||||
|
|
||||||
|
// this.vertexTextureBuffer = Gdx.gl.glGenBuffer();
|
||||||
|
this.vertexTexture = Gdx.gl.glGenTexture();
|
||||||
|
|
||||||
|
Gdx.gl.glActiveTexture(GL20.GL_TEXTURE15);
|
||||||
|
// Gdx.gl.glBindBuffer(GL20.GL_TEXTURE_2D, this.vertexTextureBuffer);
|
||||||
|
// Gdx.gl.glBindBuffer(GL20.GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
Gdx.gl.glBindTexture(GL20.GL_TEXTURE_2D, this.vertexTexture);
|
||||||
|
Gdx.gl.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_WRAP_S, GL20.GL_CLAMP_TO_EDGE);
|
||||||
|
Gdx.gl.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_WRAP_T, GL20.GL_CLAMP_TO_EDGE);
|
||||||
|
Gdx.gl.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_MIN_FILTER, GL20.GL_NEAREST);
|
||||||
|
Gdx.gl.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_MAG_FILTER, GL20.GL_NEAREST);
|
||||||
|
Gdx.gl.glTexImage2D(GL20.GL_TEXTURE_2D, 0, GL30.GL_RGBA, 4, 1, 0, GL30.GL_RGBA, GL20.GL_FLOAT,
|
||||||
|
this.vertexTextureBuffer3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render() {
|
||||||
|
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
// Gdx.gl30.glBindVertexArray(this.VAO);
|
||||||
|
this.shaderProgram.begin();
|
||||||
|
|
||||||
|
Gdx.gl.glBindBuffer(GL20.GL_ARRAY_BUFFER, this.arrayBuffer);
|
||||||
|
this.shaderProgram.setVertexAttribute("a_position", 3, GL20.GL_FLOAT, false, 0, 0);
|
||||||
|
this.shaderProgram.enableVertexAttribute("a_position");
|
||||||
|
this.shaderProgram.setVertexAttribute("a_position2", 3, GL20.GL_FLOAT, false, 0, 4 * 9);
|
||||||
|
this.shaderProgram.enableVertexAttribute("a_position2");
|
||||||
|
this.shaderProgram.setVertexAttribute("a_boneNumber", 1, GL20.GL_UNSIGNED_BYTE, false, 1, 4 * 9 * 2);
|
||||||
|
this.shaderProgram.enableVertexAttribute("a_boneNumber");
|
||||||
|
|
||||||
|
Gdx.gl.glActiveTexture(GL20.GL_TEXTURE15);
|
||||||
|
Gdx.gl.glBindTexture(GL20.GL_TEXTURE_2D, this.vertexTexture);
|
||||||
|
Gdx.gl.glTexSubImage2D(GL20.GL_TEXTURE_2D, 0, 0, 0, 4, 1, GL30.GL_RGBA, GL20.GL_FLOAT,
|
||||||
|
this.vertexTextureBuffer3);
|
||||||
|
this.shaderProgram.setUniformi("u_boneMap", 15);
|
||||||
|
this.shaderProgram.setUniformf("u_vectorSize", 1f / 4);
|
||||||
|
this.shaderProgram.setUniformf("u_rowSize", 1);
|
||||||
|
|
||||||
|
Gdx.gl.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER, this.elementBuffer);
|
||||||
|
Gdx.gl.glBufferSubData(GL20.GL_ELEMENT_ARRAY_BUFFER, 0, 3 * 2, this.faceBuffer);
|
||||||
|
Gdx.gl.glDrawElements(GL20.GL_TRIANGLES, 3, GL20.GL_UNSIGNED_SHORT, 0);
|
||||||
|
// Gdx.gl.glDrawArrays(GL20.GL_TRIANGLES, 0, 3);
|
||||||
|
this.shaderProgram.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resize(final int width, final int height) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String boneTexture = ""//
|
||||||
|
+ " uniform samplerBuffer u_boneMap;\r\n" + //
|
||||||
|
// " uniform uint u_vectorSize;\r\n" + //
|
||||||
|
" uniform uint u_rowSize;\r\n" + //
|
||||||
|
" mat4 fetchMatrix(uint column, uint row) {\r\n" + //
|
||||||
|
// " column *= u_vectorSize * 4.0;\r\n" + //
|
||||||
|
// " row *= u_rowSize;\r\n" + //
|
||||||
|
" // Add in half texel to sample in the middle of the texel.\r\n" + //
|
||||||
|
" // Otherwise, since the sample is directly on the boundry, small floating point errors can cause the sample to get the wrong pixel.\r\n"
|
||||||
|
+ //
|
||||||
|
" // This is mostly noticable with NPOT textures, which the bone maps are.\r\n" + //
|
||||||
|
// " column += 0.5 * u_vectorSize;\r\n" + //
|
||||||
|
// " row += 0.5 * u_rowSize;\r\n" + //
|
||||||
|
" return mat4(texelFetch(u_boneMap, row * u_rowSize + column * 4),\r\n" + //
|
||||||
|
" texelFetch(u_boneMap, row * u_rowSize + column * 4 + 1),\r\n" + //
|
||||||
|
" texelFetch(u_boneMap, row * u_rowSize + column * 4 + 2),\r\n" + //
|
||||||
|
" texelFetch(u_boneMap, row * u_rowSize + column * 4 + 3);\r\n" + //
|
||||||
|
" }";
|
||||||
|
|
||||||
|
public static final String vsSimple = "\r\n" + //
|
||||||
|
"\r\n" + //
|
||||||
|
" attribute vec3 a_position;\r\n" + //
|
||||||
|
" attribute vec3 a_position2;\r\n" + //
|
||||||
|
" attribute float a_boneNumber;\r\n" + //
|
||||||
|
" varying float fragNumber;\r\n" + //
|
||||||
|
Shaders.boneTexture + "\r\n" + //
|
||||||
|
" void main() {\r\n" + //
|
||||||
|
" mat4 bone = fetchMatrix(0.0, 0.0);\r\n" + //
|
||||||
|
" if( a_boneNumber <= 34.5 ) {\r\n" + //
|
||||||
|
" gl_Position = vec4(a_position2.x * bone[0][0], a_position2.y, a_position2.z, 1.0);\r\n" + //
|
||||||
|
" } else {\r\n" + //
|
||||||
|
" gl_Position = vec4(a_position2.x, a_position2.y, a_position2.z, 1.0);\r\n" + //
|
||||||
|
" }\r\n" + //
|
||||||
|
" fragNumber = a_boneNumber;\r\n" + //
|
||||||
|
" }\r\n";
|
||||||
|
|
||||||
|
public static final String fsSimple = "\r\n" + //
|
||||||
|
" varying float fragNumber;\r\n" + //
|
||||||
|
Shaders.boneTexture + "\r\n" + //
|
||||||
|
" void main() {\r\n" + //
|
||||||
|
" mat4 bone = fetchMatrix(0.0, 0.0);\r\n" + //
|
||||||
|
" if( fragNumber > 35.5 ) {\r\n" + //
|
||||||
|
" gl_FragColor = bone[0];//vec4(1.0, 0.0, 0.0, 1.0);\r\n" + //
|
||||||
|
" } else if( fragNumber > 34.5 ) {\r\n" + //
|
||||||
|
" gl_FragColor = bone[1];//vec4(0.0, 1.0, 1.0, 1.0);\r\n" + //
|
||||||
|
" } else if( fragNumber > 33.5 ) {\r\n" + //
|
||||||
|
" gl_FragColor = bone[2];//vec4(1.0, 0.0, 1.0, 1.0);\r\n" + //
|
||||||
|
" } else {\r\n" + //
|
||||||
|
" gl_FragColor = vec4(fragNumber*100.0, fragNumber, fragNumber, 1.0);\r\n" + //
|
||||||
|
" }\r\n" + //
|
||||||
|
" }\r\n";
|
||||||
|
private int vertexTexture;
|
||||||
|
private int vertexTextureBuffer;
|
||||||
|
private FloatBuffer vertexTextureBuffer3;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,203 @@
|
|||||||
|
package com.etheller.warsmash;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
|
import java.nio.IntBuffer;
|
||||||
|
import java.nio.ShortBuffer;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.ApplicationAdapter;
|
||||||
|
import com.badlogic.gdx.Gdx;
|
||||||
|
import com.badlogic.gdx.graphics.GL20;
|
||||||
|
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
|
||||||
|
import com.etheller.warsmash.viewer5.Shaders;
|
||||||
|
import com.etheller.warsmash.viewer5.gl.DataTexture;
|
||||||
|
|
||||||
|
public class WarsmashTestGameTextureBuffer2 extends ApplicationAdapter {
|
||||||
|
private int arrayBuffer;
|
||||||
|
private int elementBuffer;
|
||||||
|
private int VAO;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void create() {
|
||||||
|
// ShaderProgram.pedantic = false;
|
||||||
|
Gdx.gl.glClearColor(0.5f, 0.5f, 0.5f, 1.0f); // colour to use when clearing
|
||||||
|
|
||||||
|
final ByteBuffer tempByteBuffer = ByteBuffer.allocateDirect(4);
|
||||||
|
tempByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
final IntBuffer temp = tempByteBuffer.asIntBuffer();
|
||||||
|
|
||||||
|
Gdx.gl30.glGenVertexArrays(1, temp);
|
||||||
|
this.VAO = temp.get(0);
|
||||||
|
|
||||||
|
Gdx.gl30.glBindVertexArray(this.VAO);
|
||||||
|
|
||||||
|
System.out.println(vsSimple);
|
||||||
|
this.shaderProgram = new ShaderProgram(vsSimple, fsSimple);
|
||||||
|
if (!this.shaderProgram.isCompiled()) {
|
||||||
|
throw new IllegalStateException(this.shaderProgram.getLog());
|
||||||
|
}
|
||||||
|
|
||||||
|
this.arrayBuffer = Gdx.gl.glGenBuffer();
|
||||||
|
this.elementBuffer = Gdx.gl.glGenBuffer();
|
||||||
|
System.out.println("arrayBuffer: " + this.arrayBuffer + ", elementBuffer: " + this.elementBuffer);
|
||||||
|
|
||||||
|
Gdx.gl.glBindBuffer(GL20.GL_ARRAY_BUFFER, this.arrayBuffer);
|
||||||
|
|
||||||
|
Gdx.gl.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER, this.elementBuffer);
|
||||||
|
|
||||||
|
final ByteBuffer vertexByteBuffer = ByteBuffer.allocateDirect(4 * 9);
|
||||||
|
vertexByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
this.vertexBuffer = vertexByteBuffer.asFloatBuffer();
|
||||||
|
|
||||||
|
this.vertexBuffer.put(0, -1f);
|
||||||
|
this.vertexBuffer.put(1, -1f);
|
||||||
|
this.vertexBuffer.put(2, 0);
|
||||||
|
this.vertexBuffer.put(3, 1f);
|
||||||
|
this.vertexBuffer.put(4, -1f);
|
||||||
|
this.vertexBuffer.put(5, 0);
|
||||||
|
this.vertexBuffer.put(6, 0f);
|
||||||
|
this.vertexBuffer.put(7, 1f);
|
||||||
|
this.vertexBuffer.put(8, 0);
|
||||||
|
|
||||||
|
Gdx.gl.glBufferData(GL20.GL_ARRAY_BUFFER, ((9 * 4) * 2) + 3, null, GL20.GL_STATIC_DRAW);
|
||||||
|
Gdx.gl.glBufferSubData(GL20.GL_ARRAY_BUFFER, 0, 9 * 4, this.vertexBuffer);
|
||||||
|
|
||||||
|
final ByteBuffer vertex2ByteBuffer = ByteBuffer.allocateDirect(4 * 9);
|
||||||
|
vertex2ByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
final FloatBuffer vertexBuffer2 = vertex2ByteBuffer.asFloatBuffer();
|
||||||
|
|
||||||
|
vertexBuffer2.put(0, -1f);
|
||||||
|
vertexBuffer2.put(1, -1f);
|
||||||
|
vertexBuffer2.put(2, 0);
|
||||||
|
vertexBuffer2.put(3, 1f);
|
||||||
|
vertexBuffer2.put(4, -1f);
|
||||||
|
vertexBuffer2.put(5, 0);
|
||||||
|
vertexBuffer2.put(6, 0f);
|
||||||
|
vertexBuffer2.put(7, 1f);
|
||||||
|
vertexBuffer2.put(8, 0);
|
||||||
|
|
||||||
|
Gdx.gl.glBufferSubData(GL20.GL_ARRAY_BUFFER, 9 * 4, 9 * 4, vertexBuffer2);
|
||||||
|
|
||||||
|
final ByteBuffer skinByteBuffer = ByteBuffer.allocateDirect(3);
|
||||||
|
skinByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
skinByteBuffer.put((byte) 34);
|
||||||
|
skinByteBuffer.put((byte) 35);
|
||||||
|
skinByteBuffer.put((byte) 36);
|
||||||
|
skinByteBuffer.clear();
|
||||||
|
Gdx.gl.glBufferSubData(GL20.GL_ARRAY_BUFFER, 9 * 4 * 2, 3, skinByteBuffer);
|
||||||
|
|
||||||
|
// this.shaderProgram.setVertexAttribute("a_position", 3, GL20.GL_FLOAT, false, 0, 0);
|
||||||
|
// this.shaderProgram.enableVertexAttribute("a_position");
|
||||||
|
// this.shaderProgram.setVertexAttribute("a_position2", 3, GL20.GL_FLOAT, false, 0, 4 * 9);
|
||||||
|
// this.shaderProgram.enableVertexAttribute("a_position2");
|
||||||
|
// this.shaderProgram.setVertexAttribute("a_boneNumber", 1, GL20.GL_UNSIGNED_BYTE, false, 1, 4 * 9 * 2);
|
||||||
|
// this.shaderProgram.enableVertexAttribute("a_boneNumber");
|
||||||
|
// this.shaderProgram.setUniformi("u_boneMap", 15);
|
||||||
|
|
||||||
|
final ByteBuffer faceByteBuffer = ByteBuffer.allocateDirect(6);
|
||||||
|
faceByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
this.faceBuffer = faceByteBuffer.asShortBuffer();
|
||||||
|
|
||||||
|
this.faceBuffer.put(0, (short) 0);
|
||||||
|
this.faceBuffer.put(1, (short) 1);
|
||||||
|
this.faceBuffer.put(2, (short) 2);
|
||||||
|
|
||||||
|
Gdx.gl.glBufferData(GL20.GL_ELEMENT_ARRAY_BUFFER, 3 * 2, null, GL20.GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
final int glGetError = Gdx.gl.glGetError();
|
||||||
|
System.out.println(glGetError);
|
||||||
|
|
||||||
|
final ByteBuffer vertex3ByteBuffer = ByteBuffer.allocateDirect(4 * 16);
|
||||||
|
vertex3ByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
final FloatBuffer vertexBuffer3 = vertex3ByteBuffer.asFloatBuffer();
|
||||||
|
|
||||||
|
vertexBuffer3.put(0, 1);
|
||||||
|
vertexBuffer3.put(1, 0);
|
||||||
|
vertexBuffer3.put(2, 0);
|
||||||
|
vertexBuffer3.put(3, 0);
|
||||||
|
vertexBuffer3.put(4, 0);
|
||||||
|
vertexBuffer3.put(5, 1);
|
||||||
|
vertexBuffer3.put(6, 0);
|
||||||
|
vertexBuffer3.put(7, 0);
|
||||||
|
vertexBuffer3.put(8, 0);
|
||||||
|
vertexBuffer3.put(9, 0);
|
||||||
|
vertexBuffer3.put(10, 1);
|
||||||
|
vertexBuffer3.put(11, 0);
|
||||||
|
vertexBuffer3.put(12, 0.0f);
|
||||||
|
vertexBuffer3.put(13, 0.0f);
|
||||||
|
vertexBuffer3.put(14, 0);
|
||||||
|
vertexBuffer3.put(15, 1);
|
||||||
|
|
||||||
|
this.dataTexture = new DataTexture(Gdx.gl, 4, 4, 1);
|
||||||
|
this.dataTexture.bindAndUpdate(vertexBuffer3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render() {
|
||||||
|
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
// Gdx.gl30.glBindVertexArray(this.VAO);
|
||||||
|
this.shaderProgram.begin();
|
||||||
|
|
||||||
|
this.dataTexture.bind(15);
|
||||||
|
|
||||||
|
Gdx.gl.glBindBuffer(GL20.GL_ARRAY_BUFFER, this.arrayBuffer);
|
||||||
|
this.shaderProgram.setVertexAttribute("a_position", 3, GL20.GL_FLOAT, false, 0, 0);
|
||||||
|
this.shaderProgram.enableVertexAttribute("a_position");
|
||||||
|
this.shaderProgram.setVertexAttribute("a_position2", 3, GL20.GL_FLOAT, false, 0, 4 * 9);
|
||||||
|
this.shaderProgram.enableVertexAttribute("a_position2");
|
||||||
|
this.shaderProgram.setVertexAttribute("a_boneNumber", 1, GL20.GL_UNSIGNED_BYTE, false, 1, 4 * 9 * 2);
|
||||||
|
this.shaderProgram.enableVertexAttribute("a_boneNumber");
|
||||||
|
|
||||||
|
this.shaderProgram.setUniformi("u_boneMap", 15);
|
||||||
|
this.shaderProgram.setUniformf("u_vectorSize", 1f / this.dataTexture.getWidth());
|
||||||
|
this.shaderProgram.setUniformf("u_rowSize", 1);
|
||||||
|
|
||||||
|
Gdx.gl.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER, this.elementBuffer);
|
||||||
|
Gdx.gl.glBufferSubData(GL20.GL_ELEMENT_ARRAY_BUFFER, 0, 3 * 2, this.faceBuffer);
|
||||||
|
Gdx.gl.glDrawElements(GL20.GL_TRIANGLES, 3, GL20.GL_UNSIGNED_SHORT, 0);
|
||||||
|
// Gdx.gl.glDrawArrays(GL20.GL_TRIANGLES, 0, 3);
|
||||||
|
this.shaderProgram.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resize(final int width, final int height) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String vsSimple = "\r\n" + //
|
||||||
|
"\r\n" + //
|
||||||
|
" attribute vec3 a_position;\r\n" + //
|
||||||
|
" attribute vec3 a_position2;\r\n" + //
|
||||||
|
" attribute float a_boneNumber;\r\n" + //
|
||||||
|
" varying float fragNumber;\r\n" + //
|
||||||
|
Shaders.boneTexture + "\r\n" + //
|
||||||
|
" void main() {\r\n" + //
|
||||||
|
" mat4 bone = fetchMatrix(0.0, 0.0);\r\n" + //
|
||||||
|
" gl_Position = bone * vec4(a_position2.x, a_position2.y, a_position2.z, 1.0);\r\n" + //
|
||||||
|
" fragNumber = a_boneNumber;\r\n" + //
|
||||||
|
" }\r\n";
|
||||||
|
|
||||||
|
public static final String fsSimple = "\r\n" + //
|
||||||
|
" varying float fragNumber;\r\n" + //
|
||||||
|
" void main() {\r\n" + //
|
||||||
|
" if( fragNumber > 35.5 ) {\r\n" + //
|
||||||
|
" gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\r\n" + //
|
||||||
|
" } else if( fragNumber > 34.5 ) {\r\n" + //
|
||||||
|
" gl_FragColor = vec4(0.0, 1.0, 1.0, 1.0);\r\n" + //
|
||||||
|
" } else if( fragNumber > 33.5 ) {\r\n" + //
|
||||||
|
" gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);\r\n" + //
|
||||||
|
" } else {\r\n" + //
|
||||||
|
" gl_FragColor = vec4(fragNumber*100.0, fragNumber, fragNumber, 1.0);\r\n" + //
|
||||||
|
" }\r\n" + //
|
||||||
|
" }\r\n";
|
||||||
|
private ShaderProgram shaderProgram;
|
||||||
|
private FloatBuffer vertexBuffer;
|
||||||
|
private ShortBuffer faceBuffer;
|
||||||
|
private DataTexture dataTexture;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
package com.etheller.warsmash;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.ApplicationAdapter;
|
||||||
|
import com.badlogic.gdx.Gdx;
|
||||||
|
import com.badlogic.gdx.graphics.GL20;
|
||||||
|
import com.badlogic.gdx.graphics.Texture;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||||
|
import com.etheller.warsmash.datasources.CompoundDataSourceDescriptor;
|
||||||
|
import com.etheller.warsmash.datasources.DataSource;
|
||||||
|
import com.etheller.warsmash.datasources.DataSourceDescriptor;
|
||||||
|
import com.etheller.warsmash.datasources.FolderDataSourceDescriptor;
|
||||||
|
import com.etheller.warsmash.util.ImageUtils;
|
||||||
|
|
||||||
|
public class WarsmashTestMyTextureGame extends ApplicationAdapter {
|
||||||
|
|
||||||
|
private DataSource codebase;
|
||||||
|
private Texture texture;
|
||||||
|
private SpriteBatch batch;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void create() {
|
||||||
|
|
||||||
|
final FolderDataSourceDescriptor war3mpq = new FolderDataSourceDescriptor("E:\\Backups\\Warcraft\\Data\\127");
|
||||||
|
final FolderDataSourceDescriptor testingFolder = new FolderDataSourceDescriptor(
|
||||||
|
"D:\\NEEDS_ORGANIZING\\MPQBuild\\Test");
|
||||||
|
final FolderDataSourceDescriptor currentFolder = new FolderDataSourceDescriptor(".");
|
||||||
|
this.codebase = new CompoundDataSourceDescriptor(
|
||||||
|
Arrays.<DataSourceDescriptor>asList(war3mpq, testingFolder, currentFolder)).createDataSource();
|
||||||
|
|
||||||
|
this.texture = ImageUtils.getAnyExtensionTexture(this.codebase, "Textures\\Dust3x.blp");
|
||||||
|
Gdx.gl.glClearColor(0, 0, 0, 1);
|
||||||
|
this.batch = new SpriteBatch();
|
||||||
|
this.batch.enableBlending();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render() {
|
||||||
|
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
this.batch.begin();
|
||||||
|
this.batch.draw(this.texture, 20, 20, 256, 256);
|
||||||
|
this.batch.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
13
core/src/com/etheller/warsmash/common/FetchDataTypeName.java
Normal file
13
core/src/com/etheller/warsmash/common/FetchDataTypeName.java
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package com.etheller.warsmash.common;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* These will probably change the further I get from the source material I am
|
||||||
|
* copying from.
|
||||||
|
*/
|
||||||
|
public enum FetchDataTypeName {
|
||||||
|
IMAGE,
|
||||||
|
TEXT,
|
||||||
|
SLK,
|
||||||
|
ARRAY_BUFFER,
|
||||||
|
BLOB;
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.etheller.warsmash.common;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public interface LoadGenericCallback {
|
||||||
|
Object call(InputStream data); // TODO typing
|
||||||
|
}
|
225
core/src/com/etheller/warsmash/datasources/CascDataSource.java
Normal file
225
core/src/com/etheller/warsmash/datasources/CascDataSource.java
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
package com.etheller.warsmash.datasources;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.channels.FileChannel;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.nio.file.StandardOpenOption;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.hiveworkshop.blizzard.casc.io.WarcraftIIICASC;
|
||||||
|
import com.hiveworkshop.blizzard.casc.io.WarcraftIIICASC.FileSystem;
|
||||||
|
import com.hiveworkshop.json.JSONArray;
|
||||||
|
import com.hiveworkshop.json.JSONObject;
|
||||||
|
import com.hiveworkshop.json.JSONTokener;
|
||||||
|
|
||||||
|
public class CascDataSource implements DataSource {
|
||||||
|
private final String[] prefixes;
|
||||||
|
private WarcraftIIICASC warcraftIIICASC;
|
||||||
|
private FileSystem rootFileSystem;
|
||||||
|
private List<String> listFile;
|
||||||
|
private Map<String, String> fileAliases;
|
||||||
|
|
||||||
|
public CascDataSource(final String warcraft3InstallPath, final String[] prefixes) {
|
||||||
|
this.prefixes = prefixes;
|
||||||
|
for (int i = 0; i < (prefixes.length / 2); i++) {
|
||||||
|
final String temp = prefixes[i];
|
||||||
|
prefixes[i] = prefixes[prefixes.length - i - 1];
|
||||||
|
prefixes[prefixes.length - i - 1] = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.warcraftIIICASC = new WarcraftIIICASC(Paths.get(warcraft3InstallPath), true);
|
||||||
|
this.rootFileSystem = this.warcraftIIICASC.getRootFileSystem();
|
||||||
|
this.listFile = this.rootFileSystem.enumerateFiles();
|
||||||
|
this.fileAliases = new HashMap<>();
|
||||||
|
if (this.has("filealiases.json")) {
|
||||||
|
try (InputStream stream = this.getResourceAsStream("filealiases.json")) {
|
||||||
|
stream.mark(4);
|
||||||
|
if ('\ufeff' != stream.read()) {
|
||||||
|
stream.reset(); // not the BOM marker
|
||||||
|
}
|
||||||
|
final JSONArray jsonObject = new JSONArray(new JSONTokener(stream));
|
||||||
|
for (int i = 0; i < jsonObject.length(); i++) {
|
||||||
|
final JSONObject alias = jsonObject.getJSONObject(i);
|
||||||
|
final String src = alias.getString("src");
|
||||||
|
final String dest = alias.getString("dest");
|
||||||
|
this.fileAliases.put(src.toLowerCase(Locale.US).replace('/', '\\'),
|
||||||
|
dest.toLowerCase(Locale.US).replace('/', '\\'));
|
||||||
|
if ((src.toLowerCase(Locale.US).contains(".blp")
|
||||||
|
|| dest.toLowerCase(Locale.US).contains(".blp"))
|
||||||
|
&& (!alias.has("assetType") || "Texture".equals(alias.getString("assetType")))) {
|
||||||
|
// This case: I saw a texture that resolves in game but was failing in our code
|
||||||
|
// here, because of this entry:
|
||||||
|
// {"src":"Units/Human/WarWagon/SiegeEngine.blp",
|
||||||
|
// "dest":"Textures/Steamtank.blp", "assetType": "Texture"},
|
||||||
|
// Our repo here checks BLP then DDS at a high-up application level thing, and
|
||||||
|
// the problem is that this entry is written using .BLP but we must be able to
|
||||||
|
// resolve .DDS when we go to look it up. The actual model is .BLP so maybe
|
||||||
|
// that's how the game does it, but my alias mapping is happening after the
|
||||||
|
// .BLP->.DDS dynamic fix, and not before.
|
||||||
|
this.fileAliases.put(src.toLowerCase(Locale.US).replace('/', '\\').replace(".blp", ".dds"),
|
||||||
|
dest.toLowerCase(Locale.US).replace('/', '\\').replace(".blp", ".dds"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (final IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream getResourceAsStream(String filepath) {
|
||||||
|
filepath = filepath.toLowerCase(Locale.US).replace('/', '\\').replace(':', '\\');
|
||||||
|
final String resolvedAlias = this.fileAliases.get(filepath);
|
||||||
|
if (resolvedAlias != null) {
|
||||||
|
filepath = resolvedAlias;
|
||||||
|
}
|
||||||
|
for (final String prefix : this.prefixes) {
|
||||||
|
final String tempFilepath = prefix + "\\" + filepath;
|
||||||
|
final InputStream stream = internalGetResourceAsStream(tempFilepath);
|
||||||
|
if (stream != null) {
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return internalGetResourceAsStream(filepath);
|
||||||
|
}
|
||||||
|
|
||||||
|
private InputStream internalGetResourceAsStream(final String tempFilepath) {
|
||||||
|
try {
|
||||||
|
if (this.rootFileSystem.isFile(tempFilepath) && this.rootFileSystem.isFileAvailable(tempFilepath)) {
|
||||||
|
final ByteBuffer buffer = this.rootFileSystem.readFileData(tempFilepath);
|
||||||
|
if (buffer.hasArray()) {
|
||||||
|
return new ByteArrayInputStream(buffer.array());
|
||||||
|
}
|
||||||
|
final byte[] data = new byte[buffer.remaining()];
|
||||||
|
buffer.clear();
|
||||||
|
buffer.get(data);
|
||||||
|
return new ByteArrayInputStream(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (final IOException e) {
|
||||||
|
throw new RuntimeException("CASC parser error for: " + tempFilepath, e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuffer read(String path) {
|
||||||
|
path = path.toLowerCase(Locale.US).replace('/', '\\').replace(':', '\\');
|
||||||
|
final String resolvedAlias = this.fileAliases.get(path);
|
||||||
|
if (resolvedAlias != null) {
|
||||||
|
path = resolvedAlias;
|
||||||
|
}
|
||||||
|
for (final String prefix : this.prefixes) {
|
||||||
|
final String tempFilepath = prefix + "\\" + path;
|
||||||
|
final ByteBuffer stream = internalRead(tempFilepath);
|
||||||
|
if (stream != null) {
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return internalRead(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ByteBuffer internalRead(final String tempFilepath) {
|
||||||
|
try {
|
||||||
|
if (this.rootFileSystem.isFile(tempFilepath) && this.rootFileSystem.isFileAvailable(tempFilepath)) {
|
||||||
|
final ByteBuffer buffer = this.rootFileSystem.readFileData(tempFilepath);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (final IOException e) {
|
||||||
|
throw new RuntimeException("CASC parser error for: " + tempFilepath, e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File getFile(String filepath) {
|
||||||
|
filepath = filepath.toLowerCase(Locale.US).replace('/', '\\').replace(':', '\\');
|
||||||
|
final String resolvedAlias = this.fileAliases.get(filepath);
|
||||||
|
if (resolvedAlias != null) {
|
||||||
|
filepath = resolvedAlias;
|
||||||
|
}
|
||||||
|
for (final String prefix : this.prefixes) {
|
||||||
|
final String tempFilepath = prefix + "\\" + filepath;
|
||||||
|
final File file = internalGetFile(tempFilepath);
|
||||||
|
if (file != null) {
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return internalGetFile(filepath);
|
||||||
|
}
|
||||||
|
|
||||||
|
private File internalGetFile(final String tempFilepath) {
|
||||||
|
try {
|
||||||
|
if (this.rootFileSystem.isFile(tempFilepath) && this.rootFileSystem.isFileAvailable(tempFilepath)) {
|
||||||
|
final ByteBuffer buffer = this.rootFileSystem.readFileData(tempFilepath);
|
||||||
|
String tmpdir = System.getProperty("java.io.tmpdir");
|
||||||
|
if (!tmpdir.endsWith(File.separator)) {
|
||||||
|
tmpdir += File.separator;
|
||||||
|
}
|
||||||
|
final String tempDir = tmpdir + "MatrixEaterExtract/";
|
||||||
|
final File tempProduct = new File(tempDir + tempFilepath.replace('\\', File.separatorChar));
|
||||||
|
tempProduct.delete();
|
||||||
|
tempProduct.getParentFile().mkdirs();
|
||||||
|
try (final FileChannel fileChannel = FileChannel.open(tempProduct.toPath(), StandardOpenOption.CREATE,
|
||||||
|
StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.TRUNCATE_EXISTING)) {
|
||||||
|
fileChannel.write(buffer);
|
||||||
|
}
|
||||||
|
tempProduct.deleteOnExit();
|
||||||
|
return tempProduct;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (final IOException e) {
|
||||||
|
throw new RuntimeException("CASC parser error for: " + tempFilepath, e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean has(String filepath) {
|
||||||
|
filepath = filepath.toLowerCase(Locale.US).replace('/', '\\').replace(':', '\\');
|
||||||
|
final String resolvedAlias = this.fileAliases.get(filepath);
|
||||||
|
if (resolvedAlias != null) {
|
||||||
|
filepath = resolvedAlias;
|
||||||
|
}
|
||||||
|
for (final String prefix : this.prefixes) {
|
||||||
|
final String tempFilepath = prefix + "\\" + filepath;
|
||||||
|
try {
|
||||||
|
if (this.rootFileSystem.isFile(tempFilepath)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (final IOException e) {
|
||||||
|
throw new RuntimeException("CASC parser error for: " + tempFilepath, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return this.rootFileSystem.isFile(filepath);
|
||||||
|
}
|
||||||
|
catch (final IOException e) {
|
||||||
|
throw new RuntimeException("CASC parser error for: " + filepath, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<String> getListfile() {
|
||||||
|
return this.listFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
this.warcraftIIICASC.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,96 @@
|
|||||||
|
package com.etheller.warsmash.datasources;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class CascDataSourceDescriptor implements DataSourceDescriptor {
|
||||||
|
/**
|
||||||
|
* Generated serial id
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 832549098549298820L;
|
||||||
|
private final String gameInstallPath;
|
||||||
|
private final List<String> prefixes;
|
||||||
|
|
||||||
|
public CascDataSourceDescriptor(final String gameInstallPath, final List<String> prefixes) {
|
||||||
|
this.gameInstallPath = gameInstallPath;
|
||||||
|
this.prefixes = prefixes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataSource createDataSource() {
|
||||||
|
return new CascDataSource(this.gameInstallPath, this.prefixes.toArray(new String[this.prefixes.size()]));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDisplayName() {
|
||||||
|
return "CASC: " + this.gameInstallPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPrefix(final String prefix) {
|
||||||
|
this.prefixes.add(prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deletePrefix(final int index) {
|
||||||
|
this.prefixes.remove(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void movePrefixUp(final int index) {
|
||||||
|
if (index > 0) {
|
||||||
|
Collections.swap(this.prefixes, index, index - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void movePrefixDown(final int index) {
|
||||||
|
if (index < (this.prefixes.size() - 1)) {
|
||||||
|
Collections.swap(this.prefixes, index, index + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGameInstallPath() {
|
||||||
|
return this.gameInstallPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getPrefixes() {
|
||||||
|
return this.prefixes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = (prime * result) + ((this.gameInstallPath == null) ? 0 : this.gameInstallPath.hashCode());
|
||||||
|
result = (prime * result) + ((this.prefixes == null) ? 0 : this.prefixes.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final CascDataSourceDescriptor other = (CascDataSourceDescriptor) obj;
|
||||||
|
if (this.gameInstallPath == null) {
|
||||||
|
if (other.gameInstallPath != null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!this.gameInstallPath.equals(other.gameInstallPath)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (this.prefixes == null) {
|
||||||
|
if (other.prefixes != null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!this.prefixes.equals(other.prefixes)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,153 @@
|
|||||||
|
package com.etheller.warsmash.datasources;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class CompoundDataSource implements DataSource {
|
||||||
|
private final List<DataSource> mpqList = new ArrayList<>();
|
||||||
|
|
||||||
|
public CompoundDataSource(final List<DataSource> dataSources) {
|
||||||
|
if (dataSources != null) {
|
||||||
|
for (final DataSource dataSource : dataSources) {
|
||||||
|
this.mpqList.add(dataSource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, File> cache = new HashMap<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File getFile(final String filepath) {
|
||||||
|
if (this.cache.containsKey(filepath)) {
|
||||||
|
return this.cache.get(filepath);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
for (int i = this.mpqList.size() - 1; i >= 0; i--) {
|
||||||
|
final DataSource mpq = this.mpqList.get(i);
|
||||||
|
final File tempProduct = mpq.getFile(filepath);
|
||||||
|
if (tempProduct != null) {
|
||||||
|
this.cache.put(filepath, tempProduct);
|
||||||
|
return tempProduct;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (final IOException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuffer read(final String path) throws IOException {
|
||||||
|
try {
|
||||||
|
for (int i = this.mpqList.size() - 1; i >= 0; i--) {
|
||||||
|
final DataSource mpq = this.mpqList.get(i);
|
||||||
|
final ByteBuffer buffer = mpq.read(path);
|
||||||
|
if (buffer != null) {
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (final IOException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream getResourceAsStream(final String filepath) {
|
||||||
|
try {
|
||||||
|
for (int i = this.mpqList.size() - 1; i >= 0; i--) {
|
||||||
|
final DataSource mpq = this.mpqList.get(i);
|
||||||
|
final InputStream resourceAsStream = mpq.getResourceAsStream(filepath);
|
||||||
|
if (resourceAsStream != null) {
|
||||||
|
return resourceAsStream;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (final IOException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean has(final String filepath) {
|
||||||
|
if (this.cache.containsKey(filepath)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (int i = this.mpqList.size() - 1; i >= 0; i--) {
|
||||||
|
final DataSource mpq = this.mpqList.get(i);
|
||||||
|
if (mpq.has(filepath)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void refresh(final List<DataSourceDescriptor> dataSourceDescriptors) {
|
||||||
|
for (final DataSource dataSource : this.mpqList) {
|
||||||
|
try {
|
||||||
|
dataSource.close();
|
||||||
|
}
|
||||||
|
catch (final NullPointerException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
catch (final IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.cache.clear();
|
||||||
|
this.mpqList.clear();
|
||||||
|
if (dataSourceDescriptors != null) {
|
||||||
|
for (final DataSourceDescriptor descriptor : dataSourceDescriptors) {
|
||||||
|
this.mpqList.add(descriptor.createDataSource());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface LoadedMPQ {
|
||||||
|
void unload();
|
||||||
|
|
||||||
|
boolean hasListfile();
|
||||||
|
|
||||||
|
boolean has(String path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getMergedListfile() {
|
||||||
|
final Set<String> listfile = new HashSet<>();
|
||||||
|
for (final DataSource mpqGuy : this.mpqList) {
|
||||||
|
final Collection<String> dataSourceListfile = mpqGuy.getListfile();
|
||||||
|
if (dataSourceListfile != null) {
|
||||||
|
for (final String element : dataSourceListfile) {
|
||||||
|
listfile.add(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return listfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<String> getListfile() {
|
||||||
|
return getMergedListfile();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
for (final DataSource mpqGuy : this.mpqList) {
|
||||||
|
mpqGuy.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package com.etheller.warsmash.datasources;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class CompoundDataSourceDescriptor implements DataSourceDescriptor {
|
||||||
|
private final List<DataSourceDescriptor> dataSourceDescriptors;
|
||||||
|
|
||||||
|
public CompoundDataSourceDescriptor(final List<DataSourceDescriptor> dataSourceDescriptors) {
|
||||||
|
this.dataSourceDescriptors = dataSourceDescriptors;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataSource createDataSource() {
|
||||||
|
final List<DataSource> dataSources = new ArrayList<>();
|
||||||
|
for (final DataSourceDescriptor descriptor : this.dataSourceDescriptors) {
|
||||||
|
dataSources.add(descriptor.createDataSource());
|
||||||
|
}
|
||||||
|
return new CompoundDataSource(dataSources);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDisplayName() {
|
||||||
|
return "CompoundDataSourceDescriptor";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
49
core/src/com/etheller/warsmash/datasources/DataSource.java
Normal file
49
core/src/com/etheller/warsmash/datasources/DataSource.java
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
package com.etheller.warsmash.datasources;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
public interface DataSource {
|
||||||
|
/**
|
||||||
|
* Efficiently return a stream instance that will read the data source file's
|
||||||
|
* contents directly from the data source. For example, this will read a file
|
||||||
|
* within an MPQ or CASC storage without extracting it.
|
||||||
|
*
|
||||||
|
* @param filepath
|
||||||
|
* @return
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
InputStream getResourceAsStream(String filepath) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inefficiently copy a file from the data source onto the Hard Drive of the
|
||||||
|
* computer, and then return a java File instance pointed at the file.
|
||||||
|
*
|
||||||
|
* @param filepath
|
||||||
|
* @return
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
File getFile(String filepath) throws IOException;
|
||||||
|
|
||||||
|
ByteBuffer read(String path) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the data source contains a valid entry for a particular file.
|
||||||
|
* Some data sources (MPQs) may contain files for which this returns true, even
|
||||||
|
* though they cannot list the file in their Listfile.
|
||||||
|
*
|
||||||
|
* @param filepath
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
boolean has(String filepath);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a list of data source contents, or null if no list is provided
|
||||||
|
*/
|
||||||
|
Collection<String> getListfile();
|
||||||
|
|
||||||
|
void close() throws IOException;
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package com.etheller.warsmash.datasources;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public interface DataSourceDescriptor extends Serializable {
|
||||||
|
DataSource createDataSource();
|
||||||
|
|
||||||
|
String getDisplayName();
|
||||||
|
}
|
@ -0,0 +1,87 @@
|
|||||||
|
package com.etheller.warsmash.datasources;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.nio.file.StandardOpenOption;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
public class FolderDataSource implements DataSource {
|
||||||
|
|
||||||
|
private final Path folderPath;
|
||||||
|
private final Set<String> listfile;
|
||||||
|
|
||||||
|
public FolderDataSource(final Path folderPath) {
|
||||||
|
this.folderPath = folderPath;
|
||||||
|
this.listfile = new HashSet<>();
|
||||||
|
try {
|
||||||
|
Files.walk(folderPath).filter(Files::isRegularFile).forEach(new Consumer<Path>() {
|
||||||
|
@Override
|
||||||
|
public void accept(final Path t) {
|
||||||
|
FolderDataSource.this.listfile.add(folderPath.relativize(t).toString());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (final IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream getResourceAsStream(String filepath) throws IOException {
|
||||||
|
filepath = fixFilepath(filepath);
|
||||||
|
if (!has(filepath)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return Files.newInputStream(this.folderPath.resolve(filepath), StandardOpenOption.READ);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File getFile(String filepath) throws IOException {
|
||||||
|
filepath = fixFilepath(filepath);
|
||||||
|
if (!has(filepath)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new File(this.folderPath.toString() + File.separatorChar + filepath);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuffer read(String path) throws IOException {
|
||||||
|
path = fixFilepath(path);
|
||||||
|
if (!has(path)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return ByteBuffer.wrap(Files.readAllBytes(Paths.get(this.folderPath.toString(), path)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean has(String filepath) {
|
||||||
|
filepath = fixFilepath(filepath);
|
||||||
|
if ("".equals(filepath)) {
|
||||||
|
return false; // special case for folder data source, dont do this
|
||||||
|
}
|
||||||
|
final Path resolvedPath = this.folderPath.resolve(filepath);
|
||||||
|
return Files.exists(resolvedPath) && !Files.isDirectory(resolvedPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<String> getListfile() {
|
||||||
|
return this.listfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String fixFilepath(final String filepath) {
|
||||||
|
return filepath.replace('\\', File.separatorChar).replace('/', File.separatorChar).replace(':',
|
||||||
|
File.separatorChar);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
package com.etheller.warsmash.datasources;
|
||||||
|
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
|
public class FolderDataSourceDescriptor implements DataSourceDescriptor {
|
||||||
|
/**
|
||||||
|
* Generated serial id
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = -476724730967709309L;
|
||||||
|
private final String folderPath;
|
||||||
|
|
||||||
|
public FolderDataSourceDescriptor(final String folderPath) {
|
||||||
|
this.folderPath = folderPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataSource createDataSource() {
|
||||||
|
return new FolderDataSource(Paths.get(this.folderPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDisplayName() {
|
||||||
|
return "Folder: " + this.folderPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = (prime * result) + ((this.folderPath == null) ? 0 : this.folderPath.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final FolderDataSourceDescriptor other = (FolderDataSourceDescriptor) obj;
|
||||||
|
if (this.folderPath == null) {
|
||||||
|
if (other.folderPath != null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!this.folderPath.equals(other.folderPath)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
166
core/src/com/etheller/warsmash/datasources/MpqDataSource.java
Normal file
166
core/src/com/etheller/warsmash/datasources/MpqDataSource.java
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
package com.etheller.warsmash.datasources;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.channels.Channels;
|
||||||
|
import java.nio.channels.SeekableByteChannel;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import mpq.ArchivedFile;
|
||||||
|
import mpq.ArchivedFileExtractor;
|
||||||
|
import mpq.ArchivedFileStream;
|
||||||
|
import mpq.HashLookup;
|
||||||
|
import mpq.MPQArchive;
|
||||||
|
import mpq.MPQException;
|
||||||
|
|
||||||
|
public class MpqDataSource implements DataSource {
|
||||||
|
|
||||||
|
private final MPQArchive archive;
|
||||||
|
private final SeekableByteChannel inputChannel;
|
||||||
|
private final ArchivedFileExtractor extractor = new ArchivedFileExtractor();
|
||||||
|
|
||||||
|
public MpqDataSource(final MPQArchive archive, final SeekableByteChannel inputChannel) {
|
||||||
|
this.archive = archive;
|
||||||
|
this.inputChannel = inputChannel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MPQArchive getArchive() {
|
||||||
|
return this.archive;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SeekableByteChannel getInputChannel() {
|
||||||
|
return this.inputChannel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream getResourceAsStream(final String filepath) throws IOException {
|
||||||
|
ArchivedFile file = null;
|
||||||
|
try {
|
||||||
|
file = this.archive.lookupHash2(new HashLookup(filepath));
|
||||||
|
}
|
||||||
|
catch (final MPQException exc) {
|
||||||
|
if (exc.getMessage().equals("lookup not found")) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new IOException(exc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final ArchivedFileStream stream = new ArchivedFileStream(this.inputChannel, this.extractor, file);
|
||||||
|
final InputStream newInputStream = Channels.newInputStream(stream);
|
||||||
|
return newInputStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuffer read(final String path) throws IOException {
|
||||||
|
ArchivedFile file = null;
|
||||||
|
try {
|
||||||
|
file = this.archive.lookupHash2(new HashLookup(path));
|
||||||
|
}
|
||||||
|
catch (final MPQException exc) {
|
||||||
|
if (exc.getMessage().equals("lookup not found")) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new IOException(exc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try (final ArchivedFileStream stream = new ArchivedFileStream(this.inputChannel, this.extractor, file)) {
|
||||||
|
final long size = stream.size();
|
||||||
|
final ByteBuffer buffer = ByteBuffer.allocate((int) size);
|
||||||
|
stream.read(buffer);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File getFile(final String filepath) throws IOException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
// System.out.println("getting it from the outside: " +
|
||||||
|
// filepath);
|
||||||
|
ArchivedFile file = null;
|
||||||
|
try {
|
||||||
|
file = this.archive.lookupHash2(new HashLookup(filepath));
|
||||||
|
}
|
||||||
|
catch (final MPQException exc) {
|
||||||
|
if (exc.getMessage().equals("lookup not found")) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new IOException(exc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final ArchivedFileStream stream = new ArchivedFileStream(this.inputChannel, this.extractor, file);
|
||||||
|
final InputStream newInputStream = Channels.newInputStream(stream);
|
||||||
|
String tmpdir = System.getProperty("java.io.tmpdir");
|
||||||
|
if (!tmpdir.endsWith(File.separator)) {
|
||||||
|
tmpdir += File.separator;
|
||||||
|
}
|
||||||
|
final String tempDir = tmpdir + "RMSExtract/";
|
||||||
|
final File tempProduct = new File(tempDir + filepath.replace('\\', File.separatorChar));
|
||||||
|
tempProduct.delete();
|
||||||
|
tempProduct.getParentFile().mkdirs();
|
||||||
|
Files.copy(newInputStream, tempProduct.toPath());
|
||||||
|
tempProduct.deleteOnExit();
|
||||||
|
return tempProduct;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean has(final String filepath) {
|
||||||
|
try {
|
||||||
|
this.archive.lookupPath(filepath);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (final MPQException exc) {
|
||||||
|
if (exc.getMessage().equals("lookup not found")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new RuntimeException(exc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<String> getListfile() {
|
||||||
|
try {
|
||||||
|
final Set<String> listfile = new HashSet<>();
|
||||||
|
ArchivedFile listfileContents;
|
||||||
|
listfileContents = this.archive.lookupHash2(new HashLookup("(listfile)"));
|
||||||
|
final ArchivedFileStream stream = new ArchivedFileStream(this.inputChannel, this.extractor,
|
||||||
|
listfileContents);
|
||||||
|
final InputStream newInputStream = Channels.newInputStream(stream);
|
||||||
|
try (BufferedReader reader = new BufferedReader(new InputStreamReader(newInputStream))) {
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
listfile.add(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (final IOException exc) {
|
||||||
|
throw new RuntimeException(exc);
|
||||||
|
}
|
||||||
|
return listfile;
|
||||||
|
}
|
||||||
|
catch (final MPQException exc) {
|
||||||
|
if (exc.getMessage().equals("lookup not found")) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new RuntimeException(exc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
this.inputChannel.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,78 @@
|
|||||||
|
package com.etheller.warsmash.datasources;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.channels.SeekableByteChannel;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.nio.file.StandardOpenOption;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
|
||||||
|
import mpq.MPQArchive;
|
||||||
|
import mpq.MPQException;
|
||||||
|
|
||||||
|
public class MpqDataSourceDescriptor implements DataSourceDescriptor {
|
||||||
|
/**
|
||||||
|
* Generated serial id
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 8424254987711783598L;
|
||||||
|
private final String mpqFilePath;
|
||||||
|
|
||||||
|
public MpqDataSourceDescriptor(final String mpqFilePath) {
|
||||||
|
this.mpqFilePath = mpqFilePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataSource createDataSource() {
|
||||||
|
try {
|
||||||
|
SeekableByteChannel sbc;
|
||||||
|
sbc = Files.newByteChannel(Paths.get(this.mpqFilePath), EnumSet.of(StandardOpenOption.READ));
|
||||||
|
return new MpqDataSource(new MPQArchive(sbc), sbc);
|
||||||
|
}
|
||||||
|
catch (final IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
catch (final MPQException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDisplayName() {
|
||||||
|
return "MPQ Archive: " + this.mpqFilePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = (prime * result) + ((this.mpqFilePath == null) ? 0 : this.mpqFilePath.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final MpqDataSourceDescriptor other = (MpqDataSourceDescriptor) obj;
|
||||||
|
if (this.mpqFilePath == null) {
|
||||||
|
if (other.mpqFilePath != null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!this.mpqFilePath.equals(other.mpqFilePath)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMpqFilePath() {
|
||||||
|
return this.mpqFilePath;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
package com.etheller.warsmash.datasources;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class SubdirDataSource implements DataSource {
|
||||||
|
private final DataSource dataSource;
|
||||||
|
private final String subdir;
|
||||||
|
|
||||||
|
public SubdirDataSource(final DataSource dataSource, final String subdir) {
|
||||||
|
this.dataSource = dataSource;
|
||||||
|
this.subdir = subdir;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File getFile(final String filepath) throws IOException {
|
||||||
|
return this.dataSource.getFile(this.subdir + filepath);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuffer read(final String path) throws IOException {
|
||||||
|
return this.dataSource.read(this.subdir + path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream getResourceAsStream(final String filepath) throws IOException {
|
||||||
|
return this.dataSource.getResourceAsStream(this.subdir + filepath);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean has(final String filepath) {
|
||||||
|
return this.dataSource.has(this.subdir + filepath);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<String> getListfile() {
|
||||||
|
final List<String> results = new ArrayList<>();
|
||||||
|
for (final String x : this.dataSource.getListfile()) {
|
||||||
|
if (x.startsWith(this.subdir)) {
|
||||||
|
results.add(x.substring(this.subdir.length()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
this.dataSource.close();
|
||||||
|
}
|
||||||
|
}
|
32
core/src/com/etheller/warsmash/networking/TestClient.java
Normal file
32
core/src/com/etheller/warsmash/networking/TestClient.java
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package com.etheller.warsmash.networking;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.channels.DatagramChannel;
|
||||||
|
|
||||||
|
import com.etheller.warsmash.util.WarsmashConstants;
|
||||||
|
|
||||||
|
public class TestClient {
|
||||||
|
|
||||||
|
public static void main(final String[] args) {
|
||||||
|
try {
|
||||||
|
try (final DatagramChannel channel = DatagramChannel.open()
|
||||||
|
.connect(new InetSocketAddress(InetAddress.getLocalHost(), WarsmashConstants.PORT_NUMBER))) {
|
||||||
|
final ByteBuffer buffer = ByteBuffer.allocate(256);
|
||||||
|
buffer.clear();
|
||||||
|
buffer.put((byte) 3);
|
||||||
|
buffer.put((byte) 2);
|
||||||
|
buffer.put((byte) 4);
|
||||||
|
buffer.put((byte) 1);
|
||||||
|
buffer.flip();
|
||||||
|
channel.write(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (final IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
package com.etheller.warsmash.networking;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.SocketAddress;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.channels.DatagramChannel;
|
||||||
|
import java.nio.channels.SelectionKey;
|
||||||
|
import java.nio.channels.Selector;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.etheller.warsmash.util.WarsmashConstants;
|
||||||
|
|
||||||
|
public class WarsmashGameServer implements Runnable {
|
||||||
|
|
||||||
|
private final Selector selector;
|
||||||
|
private boolean running;
|
||||||
|
private final SelectionKey key;
|
||||||
|
private final ByteBuffer readBuffer;
|
||||||
|
|
||||||
|
public WarsmashGameServer() throws IOException {
|
||||||
|
this.selector = Selector.open();
|
||||||
|
this.running = true;
|
||||||
|
final DatagramChannel channel = DatagramChannel.open()
|
||||||
|
.bind(new InetSocketAddress(WarsmashConstants.PORT_NUMBER));
|
||||||
|
channel.configureBlocking(false);
|
||||||
|
this.key = channel.register(this.selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
|
||||||
|
this.readBuffer = ByteBuffer.allocate(256);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (this.running) {
|
||||||
|
try {
|
||||||
|
final int selectedKeyCount = this.selector.select();
|
||||||
|
if (selectedKeyCount > 0) {
|
||||||
|
final Set<SelectionKey> selectedKeys = this.selector.selectedKeys();
|
||||||
|
|
||||||
|
final Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
|
||||||
|
|
||||||
|
while (keyIterator.hasNext()) {
|
||||||
|
final SelectionKey key = keyIterator.next();
|
||||||
|
|
||||||
|
if (key.isReadable()) {
|
||||||
|
final DatagramChannel channel = (DatagramChannel) key.channel();
|
||||||
|
this.readBuffer.clear();
|
||||||
|
final SocketAddress receiveAddr = channel.receive(this.readBuffer);
|
||||||
|
this.readBuffer.flip();
|
||||||
|
System.out.println("NOTE - Received from: " + receiveAddr);
|
||||||
|
while (this.readBuffer.hasRemaining()) {
|
||||||
|
System.out.println("NOTE - Received: " + this.readBuffer.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keyIterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (final IOException e) {
|
||||||
|
System.err.println("Error reading from channel:");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRunning(final boolean running) {
|
||||||
|
this.running = running;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(final String[] args) {
|
||||||
|
WarsmashGameServer warsmashGameServer;
|
||||||
|
try {
|
||||||
|
warsmashGameServer = new WarsmashGameServer();
|
||||||
|
new Thread(warsmashGameServer).start();
|
||||||
|
}
|
||||||
|
catch (final IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
package com.etheller.warsmash.parsers.fdf;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.antlr.v4.runtime.BaseErrorListener;
|
||||||
|
import org.antlr.v4.runtime.CharStreams;
|
||||||
|
import org.antlr.v4.runtime.CommonTokenStream;
|
||||||
|
import org.antlr.v4.runtime.RecognitionException;
|
||||||
|
import org.antlr.v4.runtime.Recognizer;
|
||||||
|
|
||||||
|
import com.etheller.warsmash.datasources.DataSource;
|
||||||
|
import com.etheller.warsmash.fdfparser.FDFLexer;
|
||||||
|
import com.etheller.warsmash.fdfparser.FDFParser;
|
||||||
|
import com.etheller.warsmash.fdfparser.FDFParserBuilder;
|
||||||
|
|
||||||
|
public class DataSourceFDFParserBuilder implements FDFParserBuilder {
|
||||||
|
private final DataSource dataSource;
|
||||||
|
|
||||||
|
public DataSourceFDFParserBuilder(final DataSource dataSource) {
|
||||||
|
this.dataSource = dataSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FDFParser build(final String path) {
|
||||||
|
FDFLexer lexer;
|
||||||
|
try {
|
||||||
|
lexer = new FDFLexer(CharStreams.fromStream(this.dataSource.getResourceAsStream(path)));
|
||||||
|
}
|
||||||
|
catch (final IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
final FDFParser fdfParser = new FDFParser(new CommonTokenStream(lexer));
|
||||||
|
final BaseErrorListener errorListener = new BaseErrorListener() {
|
||||||
|
@Override
|
||||||
|
public void syntaxError(final Recognizer<?, ?> recognizer, final Object offendingSymbol, final int line,
|
||||||
|
final int charPositionInLine, final String msg, final RecognitionException e) {
|
||||||
|
String sourceName = path;
|
||||||
|
if (!sourceName.isEmpty()) {
|
||||||
|
sourceName = String.format("%s:%d:%d: ", sourceName, line, charPositionInLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.err.println(sourceName + "line " + line + ":" + charPositionInLine + " " + msg);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fdfParser.addErrorListener(errorListener);
|
||||||
|
return fdfParser;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
package com.etheller.warsmash.parsers.fdf;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
|
||||||
|
import com.etheller.warsmash.datasources.DataSource;
|
||||||
|
import com.etheller.warsmash.units.Element;
|
||||||
|
import com.etheller.warsmash.util.DataSourceFileHandle;
|
||||||
|
|
||||||
|
public class DynamicFontGeneratorHolder {
|
||||||
|
private final DataSource dataSource;
|
||||||
|
private final Element skin;
|
||||||
|
private final Map<String, FreeTypeFontGenerator> fontNameToGenerator;
|
||||||
|
|
||||||
|
public DynamicFontGeneratorHolder(final DataSource dataSource, final Element skin) {
|
||||||
|
this.dataSource = dataSource;
|
||||||
|
this.skin = skin;
|
||||||
|
this.fontNameToGenerator = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public FreeTypeFontGenerator getFontGenerator(final String font) {
|
||||||
|
FreeTypeFontGenerator fontGenerator = this.fontNameToGenerator.get(font);
|
||||||
|
if (fontGenerator == null) {
|
||||||
|
final String fontName = this.skin.getField(font);
|
||||||
|
if (fontName == null) {
|
||||||
|
throw new IllegalStateException("No such font: " + font);
|
||||||
|
}
|
||||||
|
if (!this.dataSource.has(fontName)) {
|
||||||
|
throw new IllegalStateException("No such font file: " + fontName + " (for \"" + font + "\")");
|
||||||
|
}
|
||||||
|
fontGenerator = new FreeTypeFontGenerator(new DataSourceFileHandle(this.dataSource, fontName));
|
||||||
|
this.fontNameToGenerator.put(font, fontGenerator);
|
||||||
|
}
|
||||||
|
return fontGenerator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dispose() {
|
||||||
|
for (final FreeTypeFontGenerator generator : this.fontNameToGenerator.values()) {
|
||||||
|
generator.dispose();
|
||||||
|
}
|
||||||
|
this.fontNameToGenerator.clear();
|
||||||
|
}
|
||||||
|
}
|
22
core/src/com/etheller/warsmash/parsers/fdf/GameSkin.java
Normal file
22
core/src/com/etheller/warsmash/parsers/fdf/GameSkin.java
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package com.etheller.warsmash.parsers.fdf;
|
||||||
|
|
||||||
|
import com.etheller.warsmash.units.DataTable;
|
||||||
|
import com.etheller.warsmash.units.Element;
|
||||||
|
|
||||||
|
public class GameSkin {
|
||||||
|
private final Element skin;
|
||||||
|
private final DataTable skinsTable;
|
||||||
|
|
||||||
|
public GameSkin(final Element skin, final DataTable skinsTable) {
|
||||||
|
this.skin = skin;
|
||||||
|
this.skinsTable = skinsTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Element getSkin() {
|
||||||
|
return this.skin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataTable getSkinsTable() {
|
||||||
|
return this.skinsTable;
|
||||||
|
}
|
||||||
|
}
|
1092
core/src/com/etheller/warsmash/parsers/fdf/GameUI.java
Normal file
1092
core/src/com/etheller/warsmash/parsers/fdf/GameUI.java
Normal file
File diff suppressed because it is too large
Load Diff
55
core/src/com/etheller/warsmash/parsers/fdf/Main.java
Normal file
55
core/src/com/etheller/warsmash/parsers/fdf/Main.java
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
package com.etheller.warsmash.parsers.fdf;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import com.etheller.warsmash.datasources.CompoundDataSourceDescriptor;
|
||||||
|
import com.etheller.warsmash.datasources.DataSource;
|
||||||
|
import com.etheller.warsmash.datasources.DataSourceDescriptor;
|
||||||
|
import com.etheller.warsmash.datasources.FolderDataSourceDescriptor;
|
||||||
|
import com.etheller.warsmash.fdfparser.FDFParser;
|
||||||
|
import com.etheller.warsmash.fdfparser.FrameDefinitionVisitor;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.datamodel.FrameDefinition;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.datamodel.FrameTemplateEnvironment;
|
||||||
|
|
||||||
|
public class Main {
|
||||||
|
public static final boolean REPORT_SYNTAX_ERRORS = true;
|
||||||
|
|
||||||
|
public static void main(final String[] args) {
|
||||||
|
if (args.length < 1) {
|
||||||
|
System.err.println("Usage: <Filename>");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
|
||||||
|
final FolderDataSourceDescriptor war3mpq = new FolderDataSourceDescriptor(
|
||||||
|
"E:\\Backups\\Warcraft\\Data\\127");
|
||||||
|
final FolderDataSourceDescriptor testingFolder = new FolderDataSourceDescriptor(
|
||||||
|
"E:\\Backups\\Warsmash\\Data");
|
||||||
|
final FolderDataSourceDescriptor currentFolder = new FolderDataSourceDescriptor(".");
|
||||||
|
final DataSource dataSource = new CompoundDataSourceDescriptor(
|
||||||
|
Arrays.<DataSourceDescriptor>asList(war3mpq, testingFolder, currentFolder)).createDataSource();
|
||||||
|
|
||||||
|
final FrameTemplateEnvironment templates = new FrameTemplateEnvironment();
|
||||||
|
final DataSourceFDFParserBuilder dataSourceFDFParserBuilder = new DataSourceFDFParserBuilder(dataSource);
|
||||||
|
final FrameDefinitionVisitor fdfVisitor = new FrameDefinitionVisitor(templates, dataSourceFDFParserBuilder);
|
||||||
|
try (BufferedReader reader = new BufferedReader(
|
||||||
|
new InputStreamReader(dataSource.getResourceAsStream("UI\\FrameDef\\FrameDef.toc")))) {
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
final FDFParser firstFileParser = dataSourceFDFParserBuilder.build(line);
|
||||||
|
fdfVisitor.visit(firstFileParser.program());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final FrameDefinition bnetChat = templates.getFrame("ConsoleUI");
|
||||||
|
System.out.println("Value of ConsoleUI: " + bnetChat);
|
||||||
|
}
|
||||||
|
catch (final Exception exc) {
|
||||||
|
exc.printStackTrace();
|
||||||
|
System.err.println(exc.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
38
core/src/com/etheller/warsmash/parsers/fdf/ModelExport.java
Normal file
38
core/src/com/etheller/warsmash/parsers/fdf/ModelExport.java
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package com.etheller.warsmash.parsers.fdf;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import com.etheller.warsmash.datasources.CompoundDataSourceDescriptor;
|
||||||
|
import com.etheller.warsmash.datasources.DataSource;
|
||||||
|
import com.etheller.warsmash.datasources.DataSourceDescriptor;
|
||||||
|
import com.etheller.warsmash.datasources.FolderDataSourceDescriptor;
|
||||||
|
import com.hiveworkshop.rms.parsers.mdlx.MdlxModel;
|
||||||
|
import com.hiveworkshop.rms.parsers.mdlx.util.MdxUtils;
|
||||||
|
|
||||||
|
public class ModelExport {
|
||||||
|
|
||||||
|
public static void main(final String[] args) {
|
||||||
|
|
||||||
|
final FolderDataSourceDescriptor war3mpq = new FolderDataSourceDescriptor("E:\\Backups\\Warcraft\\Data\\127");
|
||||||
|
final FolderDataSourceDescriptor testingFolder = new FolderDataSourceDescriptor("E:\\Backups\\Warsmash\\Data");
|
||||||
|
final FolderDataSourceDescriptor currentFolder = new FolderDataSourceDescriptor(".");
|
||||||
|
final DataSource dataSource = new CompoundDataSourceDescriptor(
|
||||||
|
Arrays.<DataSourceDescriptor>asList(war3mpq, testingFolder, currentFolder)).createDataSource();
|
||||||
|
|
||||||
|
try (InputStream modelStream = dataSource
|
||||||
|
.getResourceAsStream("UI\\Glues\\MainMenu\\MainMenu3D\\MainMenu3D.mdx")) {
|
||||||
|
final MdlxModel model = new MdlxModel(dataSource.read("UI\\Glues\\MainMenu\\MainMenu3D\\MainMenu3D.mdx"));
|
||||||
|
try (FileOutputStream fos = new FileOutputStream(new File("C:\\Temp\\MainMenu3D.mdl"))) {
|
||||||
|
MdxUtils.saveMdl(model, fos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (final IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,397 @@
|
|||||||
|
package com.etheller.warsmash.parsers.fdf.frames;
|
||||||
|
|
||||||
|
import java.util.EnumMap;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||||
|
import com.badlogic.gdx.math.Rectangle;
|
||||||
|
import com.badlogic.gdx.utils.viewport.Viewport;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.GameUI;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.datamodel.AnchorDefinition;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.datamodel.FramePoint;
|
||||||
|
|
||||||
|
public abstract class AbstractRenderableFrame implements UIFrame {
|
||||||
|
private static final FramePoint[] LEFT_ANCHOR_PRIORITY = { FramePoint.LEFT, FramePoint.TOPLEFT,
|
||||||
|
FramePoint.BOTTOMLEFT };
|
||||||
|
private static final FramePoint[] RIGHT_ANCHOR_PRIORITY = { FramePoint.RIGHT, FramePoint.TOPRIGHT,
|
||||||
|
FramePoint.BOTTOMRIGHT };
|
||||||
|
private static final FramePoint[] CENTER_HORIZ_ANCHOR_PRIORITY = { FramePoint.CENTER, FramePoint.TOP,
|
||||||
|
FramePoint.BOTTOM };
|
||||||
|
private static final FramePoint[] CENTER_VERT_ANCHOR_PRIORITY = { FramePoint.CENTER, FramePoint.LEFT,
|
||||||
|
FramePoint.RIGHT };
|
||||||
|
private static final FramePoint[] TOP_ANCHOR_PRIORITY = { FramePoint.TOP, FramePoint.TOPLEFT, FramePoint.TOPRIGHT };
|
||||||
|
private static final FramePoint[] BOTTOM_ANCHOR_PRIORITY = { FramePoint.BOTTOM, FramePoint.BOTTOMLEFT,
|
||||||
|
FramePoint.BOTTOMRIGHT };
|
||||||
|
private static final boolean DEBUG_LOG = false;
|
||||||
|
protected String name;
|
||||||
|
protected UIFrame parent;
|
||||||
|
protected boolean visible = true;
|
||||||
|
protected int level;
|
||||||
|
protected final Rectangle renderBounds = new Rectangle(0, 0, 0, 0); // in libgdx rendering space
|
||||||
|
private final EnumMap<FramePoint, FramePointAssignment> framePointToAssignment = new EnumMap<>(FramePoint.class);
|
||||||
|
protected float assignedHeight;
|
||||||
|
protected float assignedWidth;
|
||||||
|
|
||||||
|
public AbstractRenderableFrame(final String name, final UIFrame parent) {
|
||||||
|
this.name = name;
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSetAllPoints(final boolean setAllPoints) {
|
||||||
|
for (final FramePoint framePoint : FramePoint.values()) {
|
||||||
|
if (!this.framePointToAssignment.containsKey(framePoint)) {
|
||||||
|
this.framePointToAssignment.put(framePoint, new SetPoint(framePoint, this.parent, framePoint, 0, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSetAllPoints(final boolean setAllPoints, final float inset) {
|
||||||
|
this.framePointToAssignment.put(FramePoint.TOPLEFT,
|
||||||
|
new SetPoint(FramePoint.TOPLEFT, this.parent, FramePoint.TOPLEFT, inset, -inset));
|
||||||
|
this.framePointToAssignment.put(FramePoint.LEFT,
|
||||||
|
new SetPoint(FramePoint.LEFT, this.parent, FramePoint.LEFT, inset, 0));
|
||||||
|
this.framePointToAssignment.put(FramePoint.BOTTOMLEFT,
|
||||||
|
new SetPoint(FramePoint.BOTTOMLEFT, this.parent, FramePoint.BOTTOMLEFT, inset, inset));
|
||||||
|
this.framePointToAssignment.put(FramePoint.BOTTOM,
|
||||||
|
new SetPoint(FramePoint.BOTTOM, this.parent, FramePoint.BOTTOM, 0, inset));
|
||||||
|
this.framePointToAssignment.put(FramePoint.BOTTOMRIGHT,
|
||||||
|
new SetPoint(FramePoint.BOTTOMRIGHT, this.parent, FramePoint.BOTTOMRIGHT, -inset, inset));
|
||||||
|
this.framePointToAssignment.put(FramePoint.RIGHT,
|
||||||
|
new SetPoint(FramePoint.RIGHT, this.parent, FramePoint.RIGHT, -inset, 0));
|
||||||
|
this.framePointToAssignment.put(FramePoint.TOPRIGHT,
|
||||||
|
new SetPoint(FramePoint.TOPRIGHT, this.parent, FramePoint.TOPRIGHT, -inset, -inset));
|
||||||
|
this.framePointToAssignment.put(FramePoint.TOP,
|
||||||
|
new SetPoint(FramePoint.TOP, this.parent, FramePoint.TOP, 0, -inset));
|
||||||
|
this.framePointToAssignment.put(FramePoint.CENTER,
|
||||||
|
new SetPoint(FramePoint.CENTER, this.parent, FramePoint.CENTER, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setWidth(final float width) {
|
||||||
|
this.assignedWidth = width;
|
||||||
|
this.renderBounds.width = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getAssignedWidth() {
|
||||||
|
return this.assignedWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getAssignedHeight() {
|
||||||
|
return this.assignedHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setHeight(final float height) {
|
||||||
|
this.assignedHeight = height;
|
||||||
|
this.renderBounds.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
private FramePointAssignment getByPriority(final FramePoint[] priorities) {
|
||||||
|
for (final FramePoint priorityFramePoint : priorities) {
|
||||||
|
final FramePointAssignment framePointAssignment = this.framePointToAssignment.get(priorityFramePoint);
|
||||||
|
if (framePointAssignment != null) {
|
||||||
|
return framePointAssignment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearFramePointAssignments() {
|
||||||
|
this.framePointToAssignment.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private FramePointAssignment getLeftAnchor() {
|
||||||
|
return getByPriority(LEFT_ANCHOR_PRIORITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private FramePointAssignment getRightAnchor() {
|
||||||
|
return getByPriority(RIGHT_ANCHOR_PRIORITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private FramePointAssignment getTopAnchor() {
|
||||||
|
return getByPriority(TOP_ANCHOR_PRIORITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private FramePointAssignment getBottomAnchor() {
|
||||||
|
return getByPriority(BOTTOM_ANCHOR_PRIORITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private FramePointAssignment getCenterHorizontalAnchor() {
|
||||||
|
return getByPriority(CENTER_HORIZ_ANCHOR_PRIORITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private FramePointAssignment getCenterVerticalAnchor() {
|
||||||
|
return getByPriority(CENTER_VERT_ANCHOR_PRIORITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getFramePointX(final FramePoint framePoint) {
|
||||||
|
switch (framePoint) {
|
||||||
|
case CENTER:
|
||||||
|
case BOTTOM:
|
||||||
|
case TOP:
|
||||||
|
return this.renderBounds.x + (this.renderBounds.width / 2);
|
||||||
|
case BOTTOMLEFT:
|
||||||
|
case LEFT:
|
||||||
|
case TOPLEFT:
|
||||||
|
return this.renderBounds.x;
|
||||||
|
case BOTTOMRIGHT:
|
||||||
|
case RIGHT:
|
||||||
|
case TOPRIGHT:
|
||||||
|
return this.renderBounds.x + this.renderBounds.width;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFramePointX(final FramePoint framePoint, final float x) {
|
||||||
|
if (this.renderBounds.width == 0) {
|
||||||
|
this.renderBounds.x = x;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (framePoint) {
|
||||||
|
case CENTER:
|
||||||
|
case BOTTOM:
|
||||||
|
case TOP:
|
||||||
|
this.renderBounds.x = x - (this.renderBounds.width / 2);
|
||||||
|
return;
|
||||||
|
case BOTTOMLEFT:
|
||||||
|
case LEFT:
|
||||||
|
case TOPLEFT:
|
||||||
|
if (getRightAnchor() != null) {
|
||||||
|
final float oldRightX = this.renderBounds.x + this.renderBounds.width;
|
||||||
|
this.renderBounds.x = x;
|
||||||
|
this.renderBounds.width = oldRightX - x;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// no right anchor, keep width
|
||||||
|
this.renderBounds.x = x;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case BOTTOMRIGHT:
|
||||||
|
case RIGHT:
|
||||||
|
case TOPRIGHT:
|
||||||
|
if (getLeftAnchor() != null) {
|
||||||
|
this.renderBounds.width = x - this.renderBounds.x;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.renderBounds.x = x - this.renderBounds.width;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getFramePointY(final FramePoint framePoint) {
|
||||||
|
switch (framePoint) {
|
||||||
|
case LEFT:
|
||||||
|
case CENTER:
|
||||||
|
case RIGHT:
|
||||||
|
return this.renderBounds.y + (this.renderBounds.height / 2);
|
||||||
|
case BOTTOMLEFT:
|
||||||
|
case BOTTOM:
|
||||||
|
case BOTTOMRIGHT:
|
||||||
|
return this.renderBounds.y;
|
||||||
|
case TOPLEFT:
|
||||||
|
case TOP:
|
||||||
|
case TOPRIGHT:
|
||||||
|
return this.renderBounds.y + this.renderBounds.height;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFramePointY(final FramePoint framePoint, final float y) {
|
||||||
|
if (this.renderBounds.height == 0) {
|
||||||
|
this.renderBounds.y = y;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (framePoint) {
|
||||||
|
case LEFT:
|
||||||
|
case CENTER:
|
||||||
|
case RIGHT:
|
||||||
|
this.renderBounds.y = y - (this.renderBounds.height / 2);
|
||||||
|
return;
|
||||||
|
case TOPLEFT:
|
||||||
|
case TOP:
|
||||||
|
case TOPRIGHT:
|
||||||
|
if (getBottomAnchor() != null) {
|
||||||
|
this.renderBounds.height = y - this.renderBounds.y;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.renderBounds.y = y - this.renderBounds.height;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case BOTTOMLEFT:
|
||||||
|
case BOTTOM:
|
||||||
|
case BOTTOMRIGHT:
|
||||||
|
if (getTopAnchor() != null) {
|
||||||
|
final float oldBottomY = this.renderBounds.y + this.renderBounds.height;
|
||||||
|
this.renderBounds.y = y;
|
||||||
|
this.renderBounds.height = oldBottomY - y;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.renderBounds.y = y;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addAnchor(final AnchorDefinition anchorDefinition) {
|
||||||
|
this.framePointToAssignment.put(anchorDefinition.getMyPoint(), new SetPoint(anchorDefinition.getMyPoint(),
|
||||||
|
this.parent, anchorDefinition.getMyPoint(), anchorDefinition.getX(), anchorDefinition.getY()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addSetPoint(final SetPoint setPointDefinition) {
|
||||||
|
this.framePointToAssignment.put(setPointDefinition.getMyPoint(), setPointDefinition);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void positionBounds(final GameUI gameUI, final Viewport viewport) {
|
||||||
|
if (this.parent == null) {
|
||||||
|
// TODO this is a bit of a hack, remove later
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.framePointToAssignment.isEmpty()) {
|
||||||
|
this.renderBounds.x = this.parent.getFramePointX(FramePoint.LEFT);
|
||||||
|
this.renderBounds.y = this.parent.getFramePointY(FramePoint.BOTTOM);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
final FramePointAssignment leftAnchor = getLeftAnchor();
|
||||||
|
final FramePointAssignment rightAnchor = getRightAnchor();
|
||||||
|
final FramePointAssignment topAnchor = getTopAnchor();
|
||||||
|
final FramePointAssignment bottomAnchor = getBottomAnchor();
|
||||||
|
final FramePointAssignment centerHorizontalAnchor = getCenterHorizontalAnchor();
|
||||||
|
final FramePointAssignment centerVerticalAnchor = getCenterVerticalAnchor();
|
||||||
|
if (leftAnchor != null) {
|
||||||
|
this.renderBounds.x = leftAnchor.getX(gameUI, viewport);
|
||||||
|
if (this.assignedWidth == 0) {
|
||||||
|
if (rightAnchor != null) {
|
||||||
|
this.renderBounds.width = rightAnchor.getX(gameUI, viewport) - this.renderBounds.x;
|
||||||
|
}
|
||||||
|
else if (centerHorizontalAnchor != null) {
|
||||||
|
this.renderBounds.width = (centerHorizontalAnchor.getX(gameUI, viewport) - this.renderBounds.x)
|
||||||
|
* 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (rightAnchor != null) {
|
||||||
|
this.renderBounds.x = rightAnchor.getX(gameUI, viewport) - this.renderBounds.width;
|
||||||
|
if (centerHorizontalAnchor != null) {
|
||||||
|
this.renderBounds.width = (this.renderBounds.x - centerHorizontalAnchor.getX(gameUI, viewport)) * 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (centerHorizontalAnchor != null) {
|
||||||
|
this.renderBounds.x = centerHorizontalAnchor.getX(gameUI, viewport) - (this.renderBounds.width / 2);
|
||||||
|
}
|
||||||
|
if (bottomAnchor != null) {
|
||||||
|
this.renderBounds.y = bottomAnchor.getY(gameUI, viewport);
|
||||||
|
if (this.assignedHeight == 0) {
|
||||||
|
if (topAnchor != null) {
|
||||||
|
this.renderBounds.height = topAnchor.getY(gameUI, viewport) - this.renderBounds.y;
|
||||||
|
}
|
||||||
|
else if (centerVerticalAnchor != null) {
|
||||||
|
this.renderBounds.height = (centerVerticalAnchor.getY(gameUI, viewport) - this.renderBounds.y)
|
||||||
|
* 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (topAnchor != null) {
|
||||||
|
this.renderBounds.y = topAnchor.getY(gameUI, viewport) - this.renderBounds.height;
|
||||||
|
if (centerVerticalAnchor != null) {
|
||||||
|
this.renderBounds.height = (this.renderBounds.y - centerVerticalAnchor.getY(gameUI, viewport)) * 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (centerVerticalAnchor != null) {
|
||||||
|
this.renderBounds.y = centerVerticalAnchor.getY(gameUI, viewport) - (this.renderBounds.height / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (DEBUG_LOG) {
|
||||||
|
System.out.println(getClass().getSimpleName() + ":" + this.name + ":" + hashCode()
|
||||||
|
+ " finishing position bounds: " + this.renderBounds);
|
||||||
|
}
|
||||||
|
innerPositionBounds(gameUI, viewport);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void innerPositionBounds(GameUI gameUI, final Viewport viewport);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isVisible() {
|
||||||
|
return this.visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLevel() {
|
||||||
|
return this.level;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setVisible(final boolean visible) {
|
||||||
|
this.visible = visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLevel(final int level) {
|
||||||
|
this.level = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void render(final SpriteBatch batch, final BitmapFont font20, final GlyphLayout glyphLayout) {
|
||||||
|
if (this.visible) {
|
||||||
|
internalRender(batch, font20, glyphLayout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UIFrame getParent() {
|
||||||
|
return this.parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isVisibleOnScreen() {
|
||||||
|
boolean visibleOnScreen = this.visible;
|
||||||
|
UIFrame ancestor = this.parent;
|
||||||
|
while (visibleOnScreen && (ancestor != null)) {
|
||||||
|
visibleOnScreen &= ancestor.isVisible();
|
||||||
|
ancestor = ancestor.getParent();
|
||||||
|
}
|
||||||
|
return visibleOnScreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void internalRender(SpriteBatch batch, BitmapFont baseFont, GlyphLayout glyphLayout);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UIFrame touchDown(final float screenX, final float screenY, final int button) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UIFrame touchUp(final float screenX, final float screenY, final int button) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UIFrame getFrameChildUnderMouse(final float screenX, final float screenY) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Rectangle getRenderBounds() {
|
||||||
|
return this.renderBounds;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,90 @@
|
|||||||
|
package com.etheller.warsmash.parsers.fdf.frames;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||||
|
import com.badlogic.gdx.utils.viewport.Viewport;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.GameUI;
|
||||||
|
|
||||||
|
public abstract class AbstractUIFrame extends AbstractRenderableFrame implements UIFrame {
|
||||||
|
private final List<UIFrame> childFrames = new ArrayList<>();
|
||||||
|
|
||||||
|
public void add(final UIFrame childFrame) {
|
||||||
|
if (childFrame == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.childFrames.add(childFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(final UIFrame childFrame) {
|
||||||
|
if (childFrame == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.childFrames.remove(childFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AbstractUIFrame(final String name, final UIFrame parent) {
|
||||||
|
super(name, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setVisible(final boolean visible) {
|
||||||
|
super.setVisible(visible);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void internalRender(final SpriteBatch batch, final BitmapFont baseFont, final GlyphLayout glyphLayout) {
|
||||||
|
for (final UIFrame childFrame : this.childFrames) {
|
||||||
|
childFrame.render(batch, baseFont, glyphLayout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void innerPositionBounds(final GameUI gameUI, final Viewport viewport) {
|
||||||
|
for (final UIFrame childFrame : this.childFrames) {
|
||||||
|
childFrame.positionBounds(gameUI, viewport);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UIFrame touchDown(final float screenX, final float screenY, final int button) {
|
||||||
|
if (isVisible()) {
|
||||||
|
for (final UIFrame childFrame : this.childFrames) {
|
||||||
|
final UIFrame clickedChild = childFrame.touchDown(screenX, screenY, button);
|
||||||
|
if (clickedChild != null) {
|
||||||
|
return clickedChild;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.touchDown(screenX, screenY, button);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UIFrame touchUp(final float screenX, final float screenY, final int button) {
|
||||||
|
if (isVisible()) {
|
||||||
|
for (final UIFrame childFrame : this.childFrames) {
|
||||||
|
final UIFrame clickedChild = childFrame.touchUp(screenX, screenY, button);
|
||||||
|
if (clickedChild != null) {
|
||||||
|
return clickedChild;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.touchUp(screenX, screenY, button);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UIFrame getFrameChildUnderMouse(final float screenX, final float screenY) {
|
||||||
|
if (isVisible()) {
|
||||||
|
for (final UIFrame childFrame : this.childFrames) {
|
||||||
|
final UIFrame clickedChild = childFrame.getFrameChildUnderMouse(screenX, screenY);
|
||||||
|
if (clickedChild != null) {
|
||||||
|
return clickedChild;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.getFrameChildUnderMouse(screenX, screenY);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
package com.etheller.warsmash.parsers.fdf.frames;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.utils.viewport.Viewport;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.GameUI;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.datamodel.FramePoint;
|
||||||
|
|
||||||
|
public class AnchorPoint implements FramePointAssignment {
|
||||||
|
private final FramePoint framePoint;
|
||||||
|
private final float x;
|
||||||
|
private final float y;
|
||||||
|
|
||||||
|
public AnchorPoint(final FramePoint framePoint, final float x, final float y) {
|
||||||
|
this.framePoint = framePoint;
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getX() {
|
||||||
|
return this.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getY() {
|
||||||
|
return this.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getX(final GameUI gameUI, final Viewport uiViewport) {
|
||||||
|
return gameUI.getFramePointX(this.framePoint) + this.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getY(final GameUI gameUI, final Viewport uiViewport) {
|
||||||
|
return gameUI.getFramePointY(this.framePoint) + this.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,197 @@
|
|||||||
|
package com.etheller.warsmash.parsers.fdf.frames;
|
||||||
|
|
||||||
|
import java.util.EnumSet;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.Texture;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.datamodel.BackdropCornerFlags;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.datamodel.Vector4Definition;
|
||||||
|
|
||||||
|
public class BackdropFrame extends AbstractUIFrame {
|
||||||
|
private final boolean decorateFileNames;
|
||||||
|
private final boolean tileBackground;
|
||||||
|
private final Texture background;
|
||||||
|
private final EnumSet<BackdropCornerFlags> cornerFlags;
|
||||||
|
private final float cornerSize;
|
||||||
|
private float backgroundSize;
|
||||||
|
private final Vector4Definition backgroundInsets;
|
||||||
|
private final Texture edgeFile;
|
||||||
|
private final float edgeFileWidth;
|
||||||
|
private final float edgeUVWidth;
|
||||||
|
private final float edgeFileHeight;
|
||||||
|
private final float edgeUVHeight;
|
||||||
|
private final boolean mirrored;
|
||||||
|
|
||||||
|
public BackdropFrame(final String name, final UIFrame parent, final boolean decorateFileNames,
|
||||||
|
final boolean tileBackground, final Texture background, final EnumSet<BackdropCornerFlags> cornerFlags,
|
||||||
|
final float cornerSize, final float backgroundSize, final Vector4Definition backgroundInsets,
|
||||||
|
final Texture edgeFile, final boolean mirrored) {
|
||||||
|
super(name, parent);
|
||||||
|
this.decorateFileNames = decorateFileNames;
|
||||||
|
this.tileBackground = tileBackground && (backgroundSize > 0);
|
||||||
|
this.background = background;
|
||||||
|
this.cornerFlags = cornerFlags;
|
||||||
|
this.cornerSize = cornerSize;
|
||||||
|
this.backgroundSize = backgroundSize;
|
||||||
|
this.backgroundInsets = backgroundInsets;
|
||||||
|
this.edgeFile = edgeFile;
|
||||||
|
this.edgeFileWidth = edgeFile == null ? 0.0f : edgeFile.getWidth();
|
||||||
|
this.edgeFileHeight = edgeFile == null ? 0.0f : edgeFile.getHeight();
|
||||||
|
this.edgeUVWidth = 1f / 8f;
|
||||||
|
this.edgeUVHeight = 1f;
|
||||||
|
this.mirrored = mirrored;
|
||||||
|
this.backgroundSize -= (backgroundInsets.getX() + backgroundInsets.getY() + backgroundInsets.getZ()
|
||||||
|
+ backgroundInsets.getW()) / 2f;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void internalRender(final SpriteBatch batch, final BitmapFont baseFont, final GlyphLayout glyphLayout) {
|
||||||
|
if (this.background != null) {
|
||||||
|
final float backgroundX = this.renderBounds.x + this.backgroundInsets.getX();
|
||||||
|
final float backgroundY = this.renderBounds.y + this.backgroundInsets.getY();
|
||||||
|
final float backgroundWidth = this.renderBounds.width - this.backgroundInsets.getX()
|
||||||
|
- this.backgroundInsets.getZ();
|
||||||
|
final float backgroundHeight = this.renderBounds.height - this.backgroundInsets.getY()
|
||||||
|
- this.backgroundInsets.getW();
|
||||||
|
if (this.tileBackground) {
|
||||||
|
final float backgroundVerticalRepeatCount = (backgroundHeight / this.backgroundSize);
|
||||||
|
final float backgroundHorizontalRepeatCount = backgroundWidth / this.backgroundSize;
|
||||||
|
final float backgroundHeightRemainder = backgroundHeight % this.backgroundSize;
|
||||||
|
final float backgroundHeightRemainderRatio = backgroundHeightRemainder / this.backgroundSize;
|
||||||
|
final float backgroundWidthRemainder = backgroundWidth % this.backgroundSize;
|
||||||
|
final float backgroundWidthRemainderRatio = backgroundWidthRemainder / this.backgroundSize;
|
||||||
|
final int backgroundVerticalFloorRepeatCount = (int) Math.floor(backgroundVerticalRepeatCount);
|
||||||
|
final int backgroundHorizontalFloorRepeatCount = (int) Math.floor(backgroundHorizontalRepeatCount);
|
||||||
|
for (int j = 0; j < backgroundVerticalFloorRepeatCount; j++) {
|
||||||
|
for (int i = 0; i < backgroundHorizontalFloorRepeatCount; i++) {
|
||||||
|
batch.draw(this.background, backgroundX + (i * this.backgroundSize),
|
||||||
|
backgroundY + (j * this.backgroundSize), this.backgroundSize, this.backgroundSize);
|
||||||
|
}
|
||||||
|
batch.draw(this.background,
|
||||||
|
backgroundX + ((backgroundHorizontalFloorRepeatCount) * this.backgroundSize),
|
||||||
|
backgroundY + (j * this.backgroundSize), backgroundWidthRemainder, this.backgroundSize, 0,
|
||||||
|
1.0f, backgroundWidthRemainderRatio, 0);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < backgroundHorizontalFloorRepeatCount; i++) {
|
||||||
|
batch.draw(this.background, backgroundX + (i * this.backgroundSize),
|
||||||
|
backgroundY + (backgroundVerticalFloorRepeatCount * this.backgroundSize),
|
||||||
|
this.backgroundSize, backgroundHeightRemainder, 0, 1.0f, 1.0f,
|
||||||
|
backgroundHeightRemainderRatio);
|
||||||
|
}
|
||||||
|
batch.draw(this.background,
|
||||||
|
backgroundX + ((backgroundHorizontalFloorRepeatCount) * this.backgroundSize),
|
||||||
|
backgroundY + (backgroundVerticalFloorRepeatCount * this.backgroundSize),
|
||||||
|
backgroundWidthRemainder, backgroundHeightRemainder, 0, 1.0f, backgroundWidthRemainderRatio,
|
||||||
|
backgroundHeightRemainderRatio);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (this.mirrored) {
|
||||||
|
batch.draw(this.background, backgroundX, backgroundY, backgroundWidth, backgroundHeight, 0, 0,
|
||||||
|
this.background.getWidth(), this.background.getHeight(), true, false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
batch.draw(this.background, backgroundX, backgroundY, backgroundWidth, backgroundHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.edgeFile != null) {
|
||||||
|
if (this.cornerFlags.contains(BackdropCornerFlags.BL)) {
|
||||||
|
batch.draw(this.edgeFile, this.renderBounds.x, this.renderBounds.y, this.cornerSize, this.cornerSize,
|
||||||
|
this.edgeUVWidth * 6, this.edgeUVHeight, this.edgeUVWidth * 7, 0);
|
||||||
|
}
|
||||||
|
if (this.cornerFlags.contains(BackdropCornerFlags.BR)) {
|
||||||
|
batch.draw(this.edgeFile, (this.renderBounds.x + this.renderBounds.width) - this.cornerSize,
|
||||||
|
this.renderBounds.y, this.cornerSize, this.cornerSize, this.edgeUVWidth * 7, this.edgeUVHeight,
|
||||||
|
this.edgeUVWidth * 8, 0);
|
||||||
|
}
|
||||||
|
if (this.cornerFlags.contains(BackdropCornerFlags.UL)) {
|
||||||
|
batch.draw(this.edgeFile, this.renderBounds.x,
|
||||||
|
this.renderBounds.y + (this.renderBounds.height - this.cornerSize), this.cornerSize,
|
||||||
|
this.cornerSize, this.edgeUVWidth * 4, this.edgeUVHeight, this.edgeUVWidth * 5, 0);
|
||||||
|
}
|
||||||
|
if (this.cornerFlags.contains(BackdropCornerFlags.UR)) {
|
||||||
|
batch.draw(this.edgeFile, (this.renderBounds.x + this.renderBounds.width) - this.cornerSize,
|
||||||
|
this.renderBounds.y + (this.renderBounds.height - this.cornerSize), this.cornerSize,
|
||||||
|
this.cornerSize, this.edgeUVWidth * 5, this.edgeUVHeight, this.edgeUVWidth * 6, 0);
|
||||||
|
}
|
||||||
|
final float borderVerticalRepeatCount = (this.renderBounds.height / this.cornerSize);
|
||||||
|
final float heightRemainder = this.renderBounds.height % this.cornerSize;
|
||||||
|
final float heightRemainderRatio = heightRemainder / this.cornerSize;
|
||||||
|
final int borderVerticalRepeatCountLessOne = (int) (borderVerticalRepeatCount - 1);
|
||||||
|
if (this.cornerFlags.contains(BackdropCornerFlags.L)) {
|
||||||
|
for (int i = 1; i < borderVerticalRepeatCountLessOne; i++) {
|
||||||
|
batch.draw(this.edgeFile, this.renderBounds.x, this.renderBounds.y + (this.cornerSize * i),
|
||||||
|
this.cornerSize, this.cornerSize, this.edgeUVWidth * 0, this.edgeUVHeight,
|
||||||
|
this.edgeUVWidth * 1, 0);
|
||||||
|
}
|
||||||
|
if (borderVerticalRepeatCountLessOne > 0) {
|
||||||
|
batch.draw(this.edgeFile, this.renderBounds.x,
|
||||||
|
this.renderBounds.y + (this.cornerSize * borderVerticalRepeatCountLessOne), this.cornerSize,
|
||||||
|
heightRemainder, this.edgeUVWidth * 0, heightRemainderRatio, this.edgeUVWidth * 1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.cornerFlags.contains(BackdropCornerFlags.R)) {
|
||||||
|
for (int i = 1; i < borderVerticalRepeatCountLessOne; i++) {
|
||||||
|
batch.draw(this.edgeFile, (this.renderBounds.x + this.renderBounds.width) - this.cornerSize,
|
||||||
|
this.renderBounds.y + (this.cornerSize * i), this.cornerSize, this.cornerSize,
|
||||||
|
this.edgeUVWidth * 1, this.edgeUVHeight, this.edgeUVWidth * 2, 0);
|
||||||
|
}
|
||||||
|
if (borderVerticalRepeatCountLessOne > 0) {
|
||||||
|
batch.draw(this.edgeFile, (this.renderBounds.x + this.renderBounds.width) - this.cornerSize,
|
||||||
|
this.renderBounds.y + (this.cornerSize * borderVerticalRepeatCountLessOne), this.cornerSize,
|
||||||
|
heightRemainder, this.edgeUVWidth * 1, heightRemainderRatio, this.edgeUVWidth * 2, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final float borderHorizontalRepeatCount = this.renderBounds.width / this.cornerSize;
|
||||||
|
final float widthRemainder = (this.renderBounds.width % this.cornerSize) / this.cornerSize;
|
||||||
|
final int widthRemainderByHeight = (int) (widthRemainder * this.edgeFileHeight);
|
||||||
|
final int widthRemainderByCornerSize = (int) (widthRemainder * this.cornerSize);
|
||||||
|
final int borderHorizontalRepeatCountLessOne = (int) (borderHorizontalRepeatCount - 1);
|
||||||
|
final float halfPi = 270;
|
||||||
|
if (this.cornerFlags.contains(BackdropCornerFlags.B)) {
|
||||||
|
for (int i = 1; i < borderHorizontalRepeatCountLessOne; i++) {
|
||||||
|
batch.draw(this.edgeFile, this.renderBounds.x + (this.cornerSize * i), this.renderBounds.y,
|
||||||
|
this.cornerSize / 2, this.cornerSize / 2, this.cornerSize, this.cornerSize, 1.0f, 1.0f,
|
||||||
|
halfPi, (int) ((this.edgeFileWidth * 3f) / 8f), 0, (int) (this.edgeFileWidth / 8),
|
||||||
|
(int) this.edgeFileHeight, false, false);
|
||||||
|
}
|
||||||
|
if (borderHorizontalRepeatCountLessOne > 0) {
|
||||||
|
batch.draw(this.edgeFile,
|
||||||
|
(this.renderBounds.x + (this.cornerSize * borderHorizontalRepeatCountLessOne))
|
||||||
|
- ((this.cornerSize - widthRemainderByCornerSize) / 2),
|
||||||
|
this.renderBounds.y + ((this.cornerSize - widthRemainderByCornerSize) / 2),
|
||||||
|
this.cornerSize / 2, widthRemainderByCornerSize / 2, this.cornerSize,
|
||||||
|
widthRemainderByCornerSize, 1.0f, 1.0f, halfPi, (int) ((this.edgeFileWidth * 3f) / 8f), 0,
|
||||||
|
(int) (this.edgeFileWidth / 8), widthRemainderByHeight, false, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.cornerFlags.contains(BackdropCornerFlags.T)) {
|
||||||
|
for (int i = 1; i < borderHorizontalRepeatCountLessOne; i++) {
|
||||||
|
batch.draw(this.edgeFile, this.renderBounds.x + (this.cornerSize * i),
|
||||||
|
this.renderBounds.y + (this.renderBounds.height - this.cornerSize), this.cornerSize / 2,
|
||||||
|
this.cornerSize / 2, this.cornerSize, this.cornerSize, 1.0f, 1.0f, halfPi,
|
||||||
|
(int) ((this.edgeFileWidth * 2f) / 8f), 0, (int) (this.edgeFileWidth / 8),
|
||||||
|
(int) this.edgeFileHeight, false, false);
|
||||||
|
}
|
||||||
|
if (borderHorizontalRepeatCountLessOne > 0) {
|
||||||
|
batch.draw(this.edgeFile,
|
||||||
|
(this.renderBounds.x + (this.cornerSize * borderHorizontalRepeatCountLessOne))
|
||||||
|
- ((this.cornerSize - widthRemainderByCornerSize) / 2),
|
||||||
|
this.renderBounds.y
|
||||||
|
+ (this.renderBounds.height - ((this.cornerSize + widthRemainderByCornerSize) / 2)),
|
||||||
|
this.cornerSize / 2, widthRemainderByCornerSize / 2, this.cornerSize,
|
||||||
|
widthRemainderByCornerSize, 1.0f, 1.0f, halfPi, (int) ((this.edgeFileWidth * 2f) / 8f), 0,
|
||||||
|
(int) (this.edgeFileWidth / 8), widthRemainderByHeight, false, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.internalRender(batch, baseFont, glyphLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getCornerSize() {
|
||||||
|
return this.cornerSize;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package com.etheller.warsmash.parsers.fdf.frames;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||||
|
import com.badlogic.gdx.utils.viewport.Viewport;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.GameUI;
|
||||||
|
|
||||||
|
public class ControlFrame extends AbstractRenderableFrame {
|
||||||
|
|
||||||
|
private UIFrame controlBackdrop;
|
||||||
|
|
||||||
|
public ControlFrame(final String name, final UIFrame parent) {
|
||||||
|
super(name, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setControlBackdrop(final UIFrame controlBackdrop) {
|
||||||
|
this.controlBackdrop = controlBackdrop;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UIFrame getControlBackdrop() {
|
||||||
|
return this.controlBackdrop;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void innerPositionBounds(final GameUI gameUI, final Viewport viewport) {
|
||||||
|
this.controlBackdrop.positionBounds(gameUI, viewport);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void internalRender(final SpriteBatch batch, final BitmapFont baseFont, final GlyphLayout glyphLayout) {
|
||||||
|
this.controlBackdrop.render(batch, baseFont, glyphLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,179 @@
|
|||||||
|
package com.etheller.warsmash.parsers.fdf.frames;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.Input;
|
||||||
|
import com.badlogic.gdx.graphics.Color;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||||
|
import com.badlogic.gdx.utils.TimeUtils;
|
||||||
|
import com.badlogic.gdx.utils.viewport.Viewport;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.GameUI;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.datamodel.FramePoint;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.FocusableFrame;
|
||||||
|
|
||||||
|
public class EditBoxFrame extends AbstractRenderableFrame implements FocusableFrame {
|
||||||
|
|
||||||
|
private UIFrame controlBackdrop;
|
||||||
|
private final float editBorderSize;
|
||||||
|
private final Color editCursorColor;
|
||||||
|
private StringFrame editTextFrame;
|
||||||
|
private boolean focused = false;
|
||||||
|
private int cursorIndex;
|
||||||
|
|
||||||
|
// TODO design in such a way that references to these are not held !! very bad
|
||||||
|
// code design here
|
||||||
|
private GameUI gameUI;
|
||||||
|
private Viewport viewport;
|
||||||
|
private GlyphLayout glyphLayout;
|
||||||
|
private Runnable onChange;
|
||||||
|
|
||||||
|
public EditBoxFrame(final String name, final UIFrame parent, final float editBorderSize,
|
||||||
|
final Color editCursorColor) {
|
||||||
|
super(name, parent);
|
||||||
|
this.editBorderSize = editBorderSize;
|
||||||
|
this.editCursorColor = editCursorColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setControlBackdrop(final UIFrame controlBackdrop) {
|
||||||
|
this.controlBackdrop = controlBackdrop;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void innerPositionBounds(final GameUI gameUI, final Viewport viewport) {
|
||||||
|
this.gameUI = gameUI;
|
||||||
|
this.viewport = viewport;
|
||||||
|
this.controlBackdrop.positionBounds(gameUI, viewport);
|
||||||
|
this.editTextFrame.positionBounds(gameUI, viewport);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void internalRender(final SpriteBatch batch, final BitmapFont baseFont, final GlyphLayout glyphLayout) {
|
||||||
|
this.glyphLayout = glyphLayout;
|
||||||
|
this.controlBackdrop.render(batch, baseFont, glyphLayout);
|
||||||
|
this.editTextFrame.render(batch, baseFont, glyphLayout);
|
||||||
|
if (this.focused) {
|
||||||
|
final long time = TimeUtils.millis();
|
||||||
|
if ((time % 500) > 250) {
|
||||||
|
final BitmapFont frameFont = this.editTextFrame.getFrameFont();
|
||||||
|
frameFont.setColor(this.editCursorColor);
|
||||||
|
final int cursorRenderPosition = Math.min(this.cursorIndex, this.editTextFrame.getText().length());
|
||||||
|
this.cursorIndex = cursorRenderPosition;
|
||||||
|
glyphLayout.setText(frameFont, this.editTextFrame.getText().substring(0, cursorRenderPosition));
|
||||||
|
final float cursorXOffset = glyphLayout.width;
|
||||||
|
glyphLayout.setText(frameFont, "|");
|
||||||
|
frameFont.draw(batch, "|",
|
||||||
|
(this.editTextFrame.getFramePointX(FramePoint.LEFT) + cursorXOffset) - (glyphLayout.width / 2),
|
||||||
|
this.editTextFrame.getFramePointY(FramePoint.LEFT) + ((frameFont.getCapHeight()) / 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEditTextFrame(final StringFrame editTextFrame) {
|
||||||
|
this.editTextFrame = editTextFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isFocusable() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFocusGained() {
|
||||||
|
this.focused = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFocusLost() {
|
||||||
|
this.focused = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean keyDown(final int keycode) {
|
||||||
|
switch (keycode) {
|
||||||
|
case Input.Keys.LEFT: {
|
||||||
|
this.cursorIndex = Math.max(0, this.cursorIndex - 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Input.Keys.RIGHT: {
|
||||||
|
final String text = this.editTextFrame.getText();
|
||||||
|
this.cursorIndex = Math.min(text.length(), this.cursorIndex + 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Input.Keys.BACKSPACE: {
|
||||||
|
final String prevText = this.editTextFrame.getText();
|
||||||
|
final int prevTextLength = prevText.length();
|
||||||
|
final int cursorIndex = Math.min(this.cursorIndex, prevTextLength);
|
||||||
|
if (cursorIndex >= 1) {
|
||||||
|
this.cursorIndex = cursorIndex - 1;
|
||||||
|
final String newText = prevText.substring(0, cursorIndex - 1)
|
||||||
|
+ prevText.substring(cursorIndex, prevTextLength);
|
||||||
|
this.editTextFrame.setText(newText, this.gameUI, this.viewport);
|
||||||
|
if (this.onChange != null) {
|
||||||
|
this.onChange.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean keyUp(final int keycode) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean keyTyped(final char character) {
|
||||||
|
if (Character.isAlphabetic(character) || Character.isDigit(character)) {
|
||||||
|
final String prevText = this.editTextFrame.getText();
|
||||||
|
final int prevTextLength = prevText.length();
|
||||||
|
final int cursorIndex = Math.min(this.cursorIndex, prevTextLength);
|
||||||
|
final String newText = prevText.substring(0, cursorIndex) + character
|
||||||
|
+ prevText.substring(cursorIndex, prevTextLength);
|
||||||
|
this.editTextFrame.setText(newText, this.gameUI, this.viewport);
|
||||||
|
this.cursorIndex++;
|
||||||
|
if (this.onChange != null) {
|
||||||
|
this.onChange.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UIFrame touchDown(final float screenX, final float screenY, final int button) {
|
||||||
|
if (isVisible() && this.renderBounds.contains(screenX, screenY)) {
|
||||||
|
|
||||||
|
final String text = this.editTextFrame.getText();
|
||||||
|
int indexFound = -1;
|
||||||
|
final float fpXOfEditText = this.editTextFrame.getFramePointX(FramePoint.LEFT);
|
||||||
|
float lastX = 0;
|
||||||
|
for (int i = 0; i < text.length(); i++) {
|
||||||
|
final BitmapFont frameFont = this.editTextFrame.getFrameFont();
|
||||||
|
this.glyphLayout.setText(frameFont, this.editTextFrame.getText().substring(0, i));
|
||||||
|
final float x = fpXOfEditText + this.glyphLayout.width;
|
||||||
|
if (((x + lastX) / 2) > screenX) {
|
||||||
|
indexFound = i - 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lastX = x;
|
||||||
|
}
|
||||||
|
if (indexFound == -1) {
|
||||||
|
indexFound = text.length();
|
||||||
|
}
|
||||||
|
this.cursorIndex = indexFound;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
return super.touchDown(screenX, screenY, button);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getText() {
|
||||||
|
return this.editTextFrame.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnChange(final Runnable onChange) {
|
||||||
|
this.onChange = onChange;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package com.etheller.warsmash.parsers.fdf.frames;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.datamodel.Vector4Definition;
|
||||||
|
import com.hiveworkshop.rms.parsers.mdlx.MdlxLayer.FilterMode;
|
||||||
|
|
||||||
|
public class FilterModeTextureFrame extends TextureFrame {
|
||||||
|
private int blendSrc;
|
||||||
|
private int blendDst;
|
||||||
|
|
||||||
|
public FilterModeTextureFrame(final String name, final UIFrame parent, final boolean decorateFileNames,
|
||||||
|
final Vector4Definition texCoord) {
|
||||||
|
super(name, parent, decorateFileNames, texCoord);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void internalRender(final SpriteBatch batch, final BitmapFont baseFont, final GlyphLayout glyphLayout) {
|
||||||
|
final int blendDstFunc = batch.getBlendDstFunc();
|
||||||
|
final int blendSrcFunc = batch.getBlendSrcFunc();
|
||||||
|
batch.setBlendFunction(this.blendSrc, this.blendDst);
|
||||||
|
super.internalRender(batch, baseFont, glyphLayout);
|
||||||
|
batch.setBlendFunction(blendSrcFunc, blendDstFunc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFilterMode(final FilterMode filterMode) {
|
||||||
|
final int[] layerFilterMode = com.etheller.warsmash.viewer5.handlers.mdx.FilterMode.layerFilterMode(filterMode);
|
||||||
|
this.blendSrc = layerFilterMode[0];
|
||||||
|
this.blendDst = layerFilterMode[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.etheller.warsmash.parsers.fdf.frames;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.utils.viewport.Viewport;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.GameUI;
|
||||||
|
|
||||||
|
public interface FramePointAssignment {
|
||||||
|
float getX(GameUI gameUI, Viewport uiViewport);
|
||||||
|
|
||||||
|
float getY(GameUI gameUI, Viewport uiViewport);
|
||||||
|
}
|
@ -0,0 +1,166 @@
|
|||||||
|
package com.etheller.warsmash.parsers.fdf.frames;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||||
|
import com.badlogic.gdx.utils.viewport.Viewport;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.GameUI;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.ClickableFrame;
|
||||||
|
|
||||||
|
public class GlueButtonFrame extends AbstractRenderableFrame implements ClickableFrame {
|
||||||
|
private UIFrame controlBackdrop;
|
||||||
|
private UIFrame controlPushedBackdrop;
|
||||||
|
private UIFrame controlDisabledBackdrop;
|
||||||
|
private UIFrame controlMouseOverHighlight;
|
||||||
|
|
||||||
|
private boolean enabled = true;
|
||||||
|
private boolean highlightOnMouseOver;
|
||||||
|
private boolean mouseOver = false;
|
||||||
|
|
||||||
|
private UIFrame activeChild;
|
||||||
|
|
||||||
|
private Runnable onClick;
|
||||||
|
|
||||||
|
public GlueButtonFrame(final String name, final UIFrame parent) {
|
||||||
|
super(name, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setControlBackdrop(final UIFrame controlBackdrop) {
|
||||||
|
this.controlBackdrop = controlBackdrop;
|
||||||
|
if (this.activeChild == null) {
|
||||||
|
this.activeChild = controlBackdrop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setControlPushedBackdrop(final UIFrame controlPushedBackdrop) {
|
||||||
|
this.controlPushedBackdrop = controlPushedBackdrop;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setControlDisabledBackdrop(final UIFrame controlDisabledBackdrop) {
|
||||||
|
this.controlDisabledBackdrop = controlDisabledBackdrop;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setControlMouseOverHighlight(final UIFrame controlMouseOverHighlight) {
|
||||||
|
this.controlMouseOverHighlight = controlMouseOverHighlight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnabled(final boolean enabled) {
|
||||||
|
this.enabled = enabled;
|
||||||
|
if (this.enabled) {
|
||||||
|
this.activeChild = this.controlBackdrop;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.activeChild = this.controlDisabledBackdrop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return this.enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHighlightOnMouseOver(final boolean highlightOnMouseOver) {
|
||||||
|
this.highlightOnMouseOver = highlightOnMouseOver;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnClick(final Runnable onClick) {
|
||||||
|
this.onClick = onClick;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void innerPositionBounds(final GameUI gameUI, final Viewport viewport) {
|
||||||
|
if (this.controlBackdrop != null) {
|
||||||
|
this.controlBackdrop.positionBounds(gameUI, viewport);
|
||||||
|
}
|
||||||
|
if (this.controlPushedBackdrop != null) {
|
||||||
|
this.controlPushedBackdrop.positionBounds(gameUI, viewport);
|
||||||
|
}
|
||||||
|
if (this.controlDisabledBackdrop != null) {
|
||||||
|
this.controlDisabledBackdrop.positionBounds(gameUI, viewport);
|
||||||
|
}
|
||||||
|
if (this.controlMouseOverHighlight != null) {
|
||||||
|
this.controlMouseOverHighlight.positionBounds(gameUI, viewport);
|
||||||
|
}
|
||||||
|
if (this.enabled) {
|
||||||
|
this.activeChild = this.controlBackdrop;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.activeChild = this.controlDisabledBackdrop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void internalRender(final SpriteBatch batch, final BitmapFont baseFont, final GlyphLayout glyphLayout) {
|
||||||
|
if (this.activeChild != null) {
|
||||||
|
this.activeChild.render(batch, baseFont, glyphLayout);
|
||||||
|
}
|
||||||
|
if (this.mouseOver) {
|
||||||
|
this.controlMouseOverHighlight.render(batch, baseFont, glyphLayout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseDown(final GameUI gameUI, final Viewport uiViewport) {
|
||||||
|
if (this.enabled) {
|
||||||
|
this.activeChild = this.controlPushedBackdrop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseUp(final GameUI gameUI, final Viewport uiViewport) {
|
||||||
|
if (this.enabled) {
|
||||||
|
this.activeChild = this.controlBackdrop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseEnter(final GameUI gameUI, final Viewport uiViewport) {
|
||||||
|
if (this.highlightOnMouseOver) {
|
||||||
|
this.mouseOver = true;
|
||||||
|
onMouseEnter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onMouseEnter() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseExit(final GameUI gameUI, final Viewport uiViewport) {
|
||||||
|
this.mouseOver = false;
|
||||||
|
onMouseExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onMouseExit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(final int button) {
|
||||||
|
if (this.onClick != null) {
|
||||||
|
this.onClick.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UIFrame touchUp(final float screenX, final float screenY, final int button) {
|
||||||
|
if (isVisible() && this.enabled && this.renderBounds.contains(screenX, screenY)) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
return super.touchUp(screenX, screenY, button);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UIFrame touchDown(final float screenX, final float screenY, final int button) {
|
||||||
|
if (isVisible() && this.enabled && this.renderBounds.contains(screenX, screenY)) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
return super.touchDown(screenX, screenY, button);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UIFrame getFrameChildUnderMouse(final float screenX, final float screenY) {
|
||||||
|
if (isVisible() && this.enabled && this.renderBounds.contains(screenX, screenY)) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
return super.getFrameChildUnderMouse(screenX, screenY);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
package com.etheller.warsmash.parsers.fdf.frames;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.Color;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||||
|
import com.badlogic.gdx.utils.viewport.Viewport;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.GameUI;
|
||||||
|
|
||||||
|
public class GlueTextButtonFrame extends GlueButtonFrame {
|
||||||
|
private UIFrame buttonText;
|
||||||
|
|
||||||
|
public GlueTextButtonFrame(final String name, final UIFrame parent) {
|
||||||
|
super(name, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setButtonText(final UIFrame buttonText) {
|
||||||
|
this.buttonText = buttonText;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void innerPositionBounds(final GameUI gameUI, final Viewport viewport) {
|
||||||
|
super.innerPositionBounds(gameUI, viewport);
|
||||||
|
if (this.buttonText != null) {
|
||||||
|
this.buttonText.positionBounds(gameUI, viewport);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void internalRender(final SpriteBatch batch, final BitmapFont baseFont, final GlyphLayout glyphLayout) {
|
||||||
|
super.internalRender(batch, baseFont, glyphLayout);
|
||||||
|
if (this.buttonText != null) {
|
||||||
|
this.buttonText.render(batch, baseFont, glyphLayout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEnabled(final boolean enabled) {
|
||||||
|
super.setEnabled(enabled);
|
||||||
|
if (this.buttonText instanceof StringFrame) {
|
||||||
|
final StringFrame stringButtonText = (StringFrame) this.buttonText;
|
||||||
|
final Color fontColor = enabled ? stringButtonText.getFontOriginalColor()
|
||||||
|
: stringButtonText.getFontDisabledColor();
|
||||||
|
if (fontColor != null) {
|
||||||
|
stringButtonText.setColor(fontColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onMouseEnter() {
|
||||||
|
super.onMouseEnter();
|
||||||
|
if (isEnabled()) {
|
||||||
|
if (this.buttonText instanceof StringFrame) {
|
||||||
|
final StringFrame stringFrame = (StringFrame) this.buttonText;
|
||||||
|
final Color fontHighlightColor = stringFrame.getFontHighlightColor();
|
||||||
|
if (fontHighlightColor != null) {
|
||||||
|
stringFrame.setColor(fontHighlightColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onMouseExit() {
|
||||||
|
super.onMouseExit();
|
||||||
|
if (isEnabled()) {
|
||||||
|
if (this.buttonText instanceof StringFrame) {
|
||||||
|
final StringFrame stringFrame = (StringFrame) this.buttonText;
|
||||||
|
final Color fontOriginalColor = stringFrame.getFontOriginalColor();
|
||||||
|
if (fontOriginalColor != null) {
|
||||||
|
stringFrame.setColor(fontOriginalColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,202 @@
|
|||||||
|
package com.etheller.warsmash.parsers.fdf.frames;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.Color;
|
||||||
|
import com.badlogic.gdx.graphics.Pixmap;
|
||||||
|
import com.badlogic.gdx.graphics.Pixmap.Format;
|
||||||
|
import com.badlogic.gdx.graphics.Texture;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||||
|
import com.badlogic.gdx.utils.viewport.Viewport;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.GameUI;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.datamodel.FramePoint;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.datamodel.TextJustify;
|
||||||
|
|
||||||
|
public class ListBoxFrame extends ControlFrame {
|
||||||
|
// TODO where are these colors in the UI definition files?
|
||||||
|
private static final Color SELECT_COLOR = Color.BLUE;
|
||||||
|
private static final Color MOUSE_OVER_HIGHLIGHT_COLOR = new Color(0.3f, 0.3f, 1.0f, 0.25f);
|
||||||
|
|
||||||
|
private final List<String> listItems = new ArrayList<>();
|
||||||
|
private final List<SingleStringFrame> stringFrames = new ArrayList<>();
|
||||||
|
private BitmapFont frameFont;
|
||||||
|
private float listBoxBorder;
|
||||||
|
private int selectedIndex = -1;
|
||||||
|
private int mouseOverIndex = -1;
|
||||||
|
|
||||||
|
private final TextureFrame selectionFrame;
|
||||||
|
private final TextureFrame mouseHighlightFrame;
|
||||||
|
private GameUI gameUI;
|
||||||
|
private Viewport viewport;
|
||||||
|
private Runnable onSelect;
|
||||||
|
|
||||||
|
public ListBoxFrame(final String name, final UIFrame parent, final Viewport viewport) {
|
||||||
|
super(name, parent);
|
||||||
|
this.listBoxBorder = GameUI.convertX(viewport, 0.01f);
|
||||||
|
this.selectionFrame = new TextureFrame(null, this, false, null);
|
||||||
|
this.mouseHighlightFrame = new TextureFrame(null, this, false, null);
|
||||||
|
final Pixmap pixmap = new Pixmap(1, 1, Format.RGBA8888);
|
||||||
|
pixmap.setColor(SELECT_COLOR);
|
||||||
|
pixmap.fill();
|
||||||
|
this.selectionFrame.setTexture(new Texture(pixmap));
|
||||||
|
final Pixmap mousePixmap = new Pixmap(1, 1, Format.RGBA8888);
|
||||||
|
mousePixmap.setColor(MOUSE_OVER_HIGHLIGHT_COLOR);
|
||||||
|
mousePixmap.fill();
|
||||||
|
this.mouseHighlightFrame.setTexture(new Texture(mousePixmap));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setListBoxBorder(final float listBoxBorder) {
|
||||||
|
this.listBoxBorder = listBoxBorder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getListBoxBorder() {
|
||||||
|
return this.listBoxBorder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFrameFont(final BitmapFont frameFont) {
|
||||||
|
this.frameFont = frameFont;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void innerPositionBounds(final GameUI gameUI, final Viewport viewport) {
|
||||||
|
this.gameUI = gameUI;
|
||||||
|
this.viewport = viewport;
|
||||||
|
super.innerPositionBounds(gameUI, viewport);
|
||||||
|
updateUI(gameUI, viewport);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void positionChildren(final GameUI gameUI, final Viewport viewport) {
|
||||||
|
for (final SingleStringFrame frame : this.stringFrames) {
|
||||||
|
frame.positionBounds(gameUI, viewport);
|
||||||
|
}
|
||||||
|
this.selectionFrame.positionBounds(gameUI, viewport);
|
||||||
|
this.mouseHighlightFrame.positionBounds(gameUI, viewport);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void internalRender(final SpriteBatch batch, final BitmapFont baseFont, final GlyphLayout glyphLayout) {
|
||||||
|
super.internalRender(batch, baseFont, glyphLayout);
|
||||||
|
this.selectionFrame.render(batch, baseFont, glyphLayout);
|
||||||
|
this.mouseHighlightFrame.render(batch, baseFont, glyphLayout);
|
||||||
|
for (final SingleStringFrame frame : this.stringFrames) {
|
||||||
|
frame.render(batch, baseFont, glyphLayout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addItem(final String item, final GameUI gameUI, final Viewport viewport) {
|
||||||
|
this.listItems.add(item);
|
||||||
|
updateUI(gameUI, viewport);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItems(final List<String> items, final GameUI gameUI, final Viewport viewport) {
|
||||||
|
this.listItems.clear();
|
||||||
|
this.listItems.addAll(items);
|
||||||
|
updateUI(gameUI, viewport);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeItem(final String item, final GameUI gameUI, final Viewport viewport) {
|
||||||
|
this.listItems.remove(item);
|
||||||
|
updateUI(gameUI, viewport);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeItem(final int index, final GameUI gameUI, final Viewport viewport) {
|
||||||
|
this.listItems.remove(index);
|
||||||
|
updateUI(gameUI, viewport);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelectedIndex(final int selectedIndex) {
|
||||||
|
this.selectedIndex = selectedIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSelectedIndex() {
|
||||||
|
return this.selectedIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateUI(final GameUI gameUI, final Viewport viewport) {
|
||||||
|
this.stringFrames.clear();
|
||||||
|
SingleStringFrame prev = null;
|
||||||
|
int i = 0;
|
||||||
|
boolean foundSelected = false;
|
||||||
|
boolean foundMouseOver = false;
|
||||||
|
for (final String string : this.listItems) {
|
||||||
|
final boolean selected = (i == this.selectedIndex);
|
||||||
|
final boolean mousedOver = (i == this.mouseOverIndex);
|
||||||
|
final SingleStringFrame stringFrame = new SingleStringFrame("LISTY" + i++, this, Color.WHITE,
|
||||||
|
TextJustify.LEFT, TextJustify.MIDDLE, this.frameFont);
|
||||||
|
stringFrame.setText(string);
|
||||||
|
stringFrame.setWidth(this.renderBounds.width - (this.listBoxBorder * 2));
|
||||||
|
stringFrame.setHeight(this.frameFont.getLineHeight());
|
||||||
|
if (prev != null) {
|
||||||
|
stringFrame.addSetPoint(new SetPoint(FramePoint.TOPLEFT, prev, FramePoint.BOTTOMLEFT, 0, 0));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
stringFrame.addSetPoint(new SetPoint(FramePoint.TOPLEFT, this, FramePoint.TOPLEFT, this.listBoxBorder,
|
||||||
|
-this.listBoxBorder));
|
||||||
|
}
|
||||||
|
this.stringFrames.add(stringFrame);
|
||||||
|
prev = stringFrame;
|
||||||
|
if (selected) {
|
||||||
|
this.selectionFrame
|
||||||
|
.addSetPoint(new SetPoint(FramePoint.TOPLEFT, stringFrame, FramePoint.TOPLEFT, 0, 0));
|
||||||
|
this.selectionFrame
|
||||||
|
.addSetPoint(new SetPoint(FramePoint.BOTTOMRIGHT, stringFrame, FramePoint.BOTTOMRIGHT, 0, 0));
|
||||||
|
foundSelected = true;
|
||||||
|
}
|
||||||
|
else if (mousedOver) {
|
||||||
|
this.mouseHighlightFrame
|
||||||
|
.addSetPoint(new SetPoint(FramePoint.TOPLEFT, stringFrame, FramePoint.TOPLEFT, 0, 0));
|
||||||
|
this.mouseHighlightFrame
|
||||||
|
.addSetPoint(new SetPoint(FramePoint.BOTTOMRIGHT, stringFrame, FramePoint.BOTTOMRIGHT, 0, 0));
|
||||||
|
foundMouseOver = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.selectionFrame.setVisible(foundSelected);
|
||||||
|
this.mouseHighlightFrame.setVisible(foundMouseOver);
|
||||||
|
positionChildren(gameUI, viewport);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UIFrame touchDown(final float screenX, final float screenY, final int button) {
|
||||||
|
if (isVisible() && this.renderBounds.contains(screenX, screenY)) {
|
||||||
|
int index = 0;
|
||||||
|
for (final SingleStringFrame stringFrame : this.stringFrames) {
|
||||||
|
if (stringFrame.getRenderBounds().contains(screenX, screenY)) {
|
||||||
|
this.selectedIndex = index;
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
updateUI(this.gameUI, this.viewport);
|
||||||
|
if (this.onSelect != null) {
|
||||||
|
this.onSelect.run();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
return super.touchDown(screenX, screenY, button);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UIFrame getFrameChildUnderMouse(final float screenX, final float screenY) {
|
||||||
|
if (isVisible() && this.renderBounds.contains(screenX, screenY)) {
|
||||||
|
int index = 0;
|
||||||
|
int mouseOverIndex = -1;
|
||||||
|
for (final SingleStringFrame stringFrame : this.stringFrames) {
|
||||||
|
if (stringFrame.getRenderBounds().contains(screenX, screenY)) {
|
||||||
|
mouseOverIndex = index;
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
if (this.mouseOverIndex != mouseOverIndex) {
|
||||||
|
this.mouseOverIndex = mouseOverIndex;
|
||||||
|
updateUI(this.gameUI, this.viewport);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.getFrameChildUnderMouse(screenX, screenY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnSelect(final Runnable onSelect) {
|
||||||
|
this.onSelect = onSelect;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
package com.etheller.warsmash.parsers.fdf.frames;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.utils.viewport.Viewport;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.GameUI;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.datamodel.FramePoint;
|
||||||
|
|
||||||
|
public class SetPoint implements FramePointAssignment {
|
||||||
|
private final FramePoint myPoint;
|
||||||
|
private final UIFrame other;
|
||||||
|
private final FramePoint otherPoint;
|
||||||
|
private final float x;
|
||||||
|
private final float y;
|
||||||
|
|
||||||
|
public SetPoint(final FramePoint myPoint, final UIFrame other, final FramePoint otherPoint, final float x,
|
||||||
|
final float y) {
|
||||||
|
this.myPoint = myPoint;
|
||||||
|
this.other = other;
|
||||||
|
this.otherPoint = otherPoint;
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FramePoint getMyPoint() {
|
||||||
|
return this.myPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UIFrame getOther() {
|
||||||
|
return this.other;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FramePoint getOtherPoint() {
|
||||||
|
return this.otherPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getX() {
|
||||||
|
return this.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getY() {
|
||||||
|
return this.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getX(final GameUI gameUI, final Viewport uiViewport) {
|
||||||
|
return this.other.getFramePointX(this.otherPoint) + this.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getY(final GameUI gameUI, final Viewport uiViewport) {
|
||||||
|
return this.other.getFramePointY(this.otherPoint) + this.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "SetPoint [myPoint=" + this.myPoint + ", other=" + this.other + ", otherPoint=" + this.otherPoint
|
||||||
|
+ ", x=" + this.x + ", y=" + this.y + "]";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,217 @@
|
|||||||
|
package com.etheller.warsmash.parsers.fdf.frames;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||||
|
import com.badlogic.gdx.utils.viewport.Viewport;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.GameUI;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.ClickableFrame;
|
||||||
|
|
||||||
|
public class SimpleButtonFrame extends AbstractRenderableFrame implements ClickableFrame {
|
||||||
|
|
||||||
|
private UIFrame controlBackdrop;
|
||||||
|
private UIFrame controlPushedBackdrop;
|
||||||
|
private UIFrame controlDisabledBackdrop;
|
||||||
|
private UIFrame controlMouseOverHighlight;
|
||||||
|
|
||||||
|
private boolean enabled = true;
|
||||||
|
private boolean highlightOnMouseOver;
|
||||||
|
private boolean mouseOver = false;
|
||||||
|
private boolean pushed = false;
|
||||||
|
|
||||||
|
private UIFrame activeChild;
|
||||||
|
private UIFrame activeTextChild;
|
||||||
|
|
||||||
|
private UIFrame buttonText;
|
||||||
|
private UIFrame disabledText;
|
||||||
|
private UIFrame highlightText;
|
||||||
|
|
||||||
|
private UIFrame pushedText;
|
||||||
|
private UIFrame pushedHighlightText;
|
||||||
|
|
||||||
|
private Runnable onClick;
|
||||||
|
|
||||||
|
public SimpleButtonFrame(final String name, final UIFrame parent) {
|
||||||
|
super(name, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setControlBackdrop(final UIFrame controlBackdrop) {
|
||||||
|
this.controlBackdrop = controlBackdrop;
|
||||||
|
if (this.activeChild == null) {
|
||||||
|
this.activeChild = controlBackdrop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setControlPushedBackdrop(final UIFrame controlPushedBackdrop) {
|
||||||
|
this.controlPushedBackdrop = controlPushedBackdrop;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setControlDisabledBackdrop(final UIFrame controlDisabledBackdrop) {
|
||||||
|
this.controlDisabledBackdrop = controlDisabledBackdrop;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setControlMouseOverHighlight(final UIFrame controlMouseOverHighlight) {
|
||||||
|
this.controlMouseOverHighlight = controlMouseOverHighlight;
|
||||||
|
this.highlightOnMouseOver |= controlMouseOverHighlight != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnabled(final boolean enabled) {
|
||||||
|
this.enabled = enabled;
|
||||||
|
if (this.enabled) {
|
||||||
|
this.activeChild = this.controlBackdrop;
|
||||||
|
this.activeTextChild = this.buttonText;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.activeChild = this.controlDisabledBackdrop;
|
||||||
|
this.activeTextChild = this.disabledText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHighlightOnMouseOver(final boolean highlightOnMouseOver) {
|
||||||
|
this.highlightOnMouseOver = highlightOnMouseOver;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnClick(final Runnable onClick) {
|
||||||
|
this.onClick = onClick;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void innerPositionBounds(final GameUI gameUI, final Viewport viewport) {
|
||||||
|
if (this.controlBackdrop != null) {
|
||||||
|
this.controlBackdrop.positionBounds(gameUI, viewport);
|
||||||
|
}
|
||||||
|
if (this.controlPushedBackdrop != null) {
|
||||||
|
this.controlPushedBackdrop.positionBounds(gameUI, viewport);
|
||||||
|
}
|
||||||
|
if (this.controlDisabledBackdrop != null) {
|
||||||
|
this.controlDisabledBackdrop.positionBounds(gameUI, viewport);
|
||||||
|
}
|
||||||
|
if (this.controlMouseOverHighlight != null) {
|
||||||
|
this.controlMouseOverHighlight.positionBounds(gameUI, viewport);
|
||||||
|
}
|
||||||
|
if (this.buttonText != null) {
|
||||||
|
this.buttonText.positionBounds(gameUI, viewport);
|
||||||
|
}
|
||||||
|
if (this.pushedText != null) {
|
||||||
|
this.pushedText.positionBounds(gameUI, viewport);
|
||||||
|
}
|
||||||
|
if (this.disabledText != null) {
|
||||||
|
this.disabledText.positionBounds(gameUI, viewport);
|
||||||
|
}
|
||||||
|
if (this.highlightText != null) {
|
||||||
|
this.highlightText.positionBounds(gameUI, viewport);
|
||||||
|
}
|
||||||
|
if (this.pushedHighlightText != null) {
|
||||||
|
this.pushedHighlightText.positionBounds(gameUI, viewport);
|
||||||
|
}
|
||||||
|
if (this.enabled) {
|
||||||
|
this.activeChild = this.controlBackdrop;
|
||||||
|
this.activeTextChild = this.buttonText;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.activeChild = this.controlDisabledBackdrop;
|
||||||
|
this.activeTextChild = this.disabledText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void internalRender(final SpriteBatch batch, final BitmapFont baseFont, final GlyphLayout glyphLayout) {
|
||||||
|
if (this.activeChild != null) {
|
||||||
|
this.activeChild.render(batch, baseFont, glyphLayout);
|
||||||
|
}
|
||||||
|
if (this.activeTextChild != null) {
|
||||||
|
this.activeTextChild.render(batch, baseFont, glyphLayout);
|
||||||
|
}
|
||||||
|
if (this.mouseOver) {
|
||||||
|
this.controlMouseOverHighlight.render(batch, baseFont, glyphLayout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseDown(final GameUI gameUI, final Viewport uiViewport) {
|
||||||
|
if (this.enabled) {
|
||||||
|
this.activeChild = this.controlPushedBackdrop;
|
||||||
|
this.pushed = true;
|
||||||
|
this.activeTextChild = this.mouseOver ? this.pushedHighlightText : this.pushedText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseUp(final GameUI gameUI, final Viewport uiViewport) {
|
||||||
|
if (this.enabled) {
|
||||||
|
this.activeChild = this.controlBackdrop;
|
||||||
|
this.activeTextChild = this.mouseOver ? this.highlightText : this.buttonText;
|
||||||
|
}
|
||||||
|
this.pushed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseEnter(final GameUI gameUI, final Viewport uiViewport) {
|
||||||
|
if (this.highlightOnMouseOver) {
|
||||||
|
this.mouseOver = true;
|
||||||
|
if (this.enabled) {
|
||||||
|
this.activeTextChild = this.pushed ? this.pushedHighlightText : this.highlightText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseExit(final GameUI gameUI, final Viewport uiViewport) {
|
||||||
|
this.mouseOver = false;
|
||||||
|
if (this.enabled) {
|
||||||
|
this.activeTextChild = this.pushed ? this.pushedText : this.buttonText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(final int button) {
|
||||||
|
if (this.onClick != null) {
|
||||||
|
this.onClick.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UIFrame touchUp(final float screenX, final float screenY, final int button) {
|
||||||
|
if (isVisible() && this.enabled && this.renderBounds.contains(screenX, screenY)) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
return super.touchUp(screenX, screenY, button);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UIFrame touchDown(final float screenX, final float screenY, final int button) {
|
||||||
|
if (isVisible() && this.enabled && this.renderBounds.contains(screenX, screenY)) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
return super.touchDown(screenX, screenY, button);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UIFrame getFrameChildUnderMouse(final float screenX, final float screenY) {
|
||||||
|
if (isVisible() && this.enabled && this.renderBounds.contains(screenX, screenY)) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
return super.getFrameChildUnderMouse(screenX, screenY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setButtonText(final UIFrame buttonText) {
|
||||||
|
this.buttonText = buttonText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPushedHighlightText(final UIFrame pushedHighlightText) {
|
||||||
|
this.pushedHighlightText = pushedHighlightText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPushedText(final UIFrame pushedText) {
|
||||||
|
this.pushedText = pushedText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHighlightText(final UIFrame highlightText) {
|
||||||
|
this.highlightText = highlightText;
|
||||||
|
this.highlightOnMouseOver |= highlightText != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDisabledText(final UIFrame disabledText) {
|
||||||
|
this.disabledText = disabledText;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package com.etheller.warsmash.parsers.fdf.frames;
|
||||||
|
|
||||||
|
public class SimpleFrame extends AbstractUIFrame {
|
||||||
|
|
||||||
|
public SimpleFrame(final String name, final UIFrame parent) {
|
||||||
|
super(name, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package com.etheller.warsmash.parsers.fdf.frames;
|
||||||
|
|
||||||
|
import com.etheller.warsmash.parsers.fdf.datamodel.FramePoint;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.datamodel.Vector4Definition;
|
||||||
|
|
||||||
|
public class SimpleStatusBarFrame extends AbstractUIFrame {
|
||||||
|
private final boolean decorateFileNames;
|
||||||
|
private final TextureFrame barFrame;
|
||||||
|
private final TextureFrame borderFrame;
|
||||||
|
|
||||||
|
public SimpleStatusBarFrame(final String name, final UIFrame parent, final boolean decorateFileNames) {
|
||||||
|
super(name, parent);
|
||||||
|
this.decorateFileNames = decorateFileNames;
|
||||||
|
this.barFrame = new TextureFrame(name + "Bar", this, decorateFileNames, new Vector4Definition(0, 1, 0, 1));
|
||||||
|
this.borderFrame = new TextureFrame(name + "Border", this, decorateFileNames,
|
||||||
|
new Vector4Definition(0, 1, 0, 1));
|
||||||
|
this.borderFrame.setSetAllPoints(true);
|
||||||
|
this.barFrame.addSetPoint(new SetPoint(FramePoint.TOPLEFT, this, FramePoint.TOPLEFT, 0, 0));
|
||||||
|
this.barFrame.addSetPoint(new SetPoint(FramePoint.BOTTOMLEFT, this, FramePoint.BOTTOMLEFT, 0, 0));
|
||||||
|
this.barFrame.setSetAllPoints(true);
|
||||||
|
add(this.barFrame);
|
||||||
|
add(this.borderFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDecorateFileNames() {
|
||||||
|
return this.decorateFileNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(final float value) {
|
||||||
|
this.barFrame.setTexCoord(0, value, 0, 1);
|
||||||
|
this.barFrame.setWidth(this.renderBounds.width * value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextureFrame getBarFrame() {
|
||||||
|
return this.barFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextureFrame getBorderFrame() {
|
||||||
|
return this.borderFrame;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,106 @@
|
|||||||
|
package com.etheller.warsmash.parsers.fdf.frames;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.Color;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||||
|
import com.badlogic.gdx.utils.viewport.Viewport;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.GameUI;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.datamodel.TextJustify;
|
||||||
|
|
||||||
|
public class SingleStringFrame extends AbstractRenderableFrame {
|
||||||
|
private Color color;
|
||||||
|
private String text = "Default string";
|
||||||
|
private final TextJustify justifyH;
|
||||||
|
private final TextJustify justifyV;
|
||||||
|
private final BitmapFont frameFont;
|
||||||
|
private Color fontShadowColor;
|
||||||
|
private float fontShadowOffsetX;
|
||||||
|
private float fontShadowOffsetY;
|
||||||
|
private float alpha = 1.0f;
|
||||||
|
|
||||||
|
public SingleStringFrame(final String name, final UIFrame parent, final Color color, final TextJustify justifyH,
|
||||||
|
final TextJustify justifyV, final BitmapFont frameFont) {
|
||||||
|
super(name, parent);
|
||||||
|
this.color = color;
|
||||||
|
this.justifyH = justifyH;
|
||||||
|
this.justifyV = justifyV;
|
||||||
|
this.frameFont = frameFont;
|
||||||
|
this.text = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setText(final String text) {
|
||||||
|
if (text == null) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColor(final Color color) {
|
||||||
|
this.color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color getColor() {
|
||||||
|
return this.color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFontShadowColor(final Color fontShadowColor) {
|
||||||
|
this.fontShadowColor = fontShadowColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFontShadowOffsetX(final float fontShadowOffsetX) {
|
||||||
|
this.fontShadowOffsetX = fontShadowOffsetX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFontShadowOffsetY(final float fontShadowOffsetY) {
|
||||||
|
this.fontShadowOffsetY = fontShadowOffsetY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void internalRender(final SpriteBatch batch, final BitmapFont baseFont, final GlyphLayout glyphLayout) {
|
||||||
|
glyphLayout.setText(this.frameFont, this.text);
|
||||||
|
final float x;
|
||||||
|
switch (this.justifyH) {
|
||||||
|
case CENTER:
|
||||||
|
x = this.renderBounds.x + ((this.renderBounds.width - glyphLayout.width) / 2);
|
||||||
|
break;
|
||||||
|
case RIGHT:
|
||||||
|
x = (this.renderBounds.x + this.renderBounds.width) - glyphLayout.width;
|
||||||
|
break;
|
||||||
|
case LEFT:
|
||||||
|
default:
|
||||||
|
x = this.renderBounds.x;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
final float y;
|
||||||
|
switch (this.justifyV) {
|
||||||
|
case MIDDLE:
|
||||||
|
y = this.renderBounds.y + ((this.renderBounds.height + this.frameFont.getLineHeight()) / 2);
|
||||||
|
break;
|
||||||
|
case TOP:
|
||||||
|
y = (this.renderBounds.y + this.renderBounds.height);
|
||||||
|
break;
|
||||||
|
case BOTTOM:
|
||||||
|
default:
|
||||||
|
y = this.renderBounds.y + this.frameFont.getLineHeight();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (this.fontShadowColor != null) {
|
||||||
|
this.frameFont.setColor(this.fontShadowColor.r, this.fontShadowColor.g, this.fontShadowColor.b,
|
||||||
|
this.fontShadowColor.a * this.alpha);
|
||||||
|
this.frameFont.draw(batch, this.text, x + this.fontShadowOffsetX, y + this.fontShadowOffsetY);
|
||||||
|
}
|
||||||
|
this.frameFont.setColor(this.color.r, this.color.g, this.color.b, this.color.a * this.alpha);
|
||||||
|
this.frameFont.draw(batch, this.text, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void innerPositionBounds(final GameUI gameUI, final Viewport viewport) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAlpha(final float alpha) {
|
||||||
|
this.alpha = alpha;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
package com.etheller.warsmash.parsers.fdf.frames;
|
||||||
|
|
||||||
|
import java.util.EnumSet;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.utils.viewport.Viewport;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.GameUI;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.datamodel.BackdropCornerFlags;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.datamodel.Vector4Definition;
|
||||||
|
import com.etheller.warsmash.viewer5.Scene;
|
||||||
|
import com.hiveworkshop.rms.parsers.mdlx.MdlxGeoset;
|
||||||
|
import com.hiveworkshop.rms.parsers.mdlx.MdlxLayer;
|
||||||
|
import com.hiveworkshop.rms.parsers.mdlx.MdlxLayer.FilterMode;
|
||||||
|
import com.hiveworkshop.rms.parsers.mdlx.MdlxMaterial;
|
||||||
|
import com.hiveworkshop.rms.parsers.mdlx.MdlxModel;
|
||||||
|
import com.hiveworkshop.rms.parsers.mdlx.MdlxTexture;
|
||||||
|
import com.hiveworkshop.rms.parsers.mdlx.MdlxTexture.WrapMode;
|
||||||
|
|
||||||
|
public class SmartBackdropFrame extends SpriteFrame {
|
||||||
|
private final boolean decorateFileNames;
|
||||||
|
private final boolean tileBackground;
|
||||||
|
private final String backgroundString;
|
||||||
|
private final EnumSet<BackdropCornerFlags> cornerFlags;
|
||||||
|
private final float cornerSize;
|
||||||
|
private final float backgroundSize;
|
||||||
|
private final Vector4Definition backgroundInsets;
|
||||||
|
private final String edgeFileString;
|
||||||
|
|
||||||
|
public SmartBackdropFrame(final String name, final UIFrame parent, final Scene scene, final Viewport uiViewport,
|
||||||
|
final boolean decorateFileNames, final boolean tileBackground, final String backgroundString,
|
||||||
|
final EnumSet<BackdropCornerFlags> cornerFlags, final float cornerSize, final float backgroundSize,
|
||||||
|
final Vector4Definition backgroundInsets, final String edgeFileString) {
|
||||||
|
super(name, parent, scene, uiViewport);
|
||||||
|
this.decorateFileNames = decorateFileNames;
|
||||||
|
this.tileBackground = tileBackground;
|
||||||
|
this.backgroundString = backgroundString;
|
||||||
|
this.cornerFlags = cornerFlags;
|
||||||
|
this.cornerSize = cornerSize;
|
||||||
|
this.backgroundSize = backgroundSize;
|
||||||
|
this.backgroundInsets = backgroundInsets;
|
||||||
|
this.edgeFileString = edgeFileString;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void innerPositionBounds(final GameUI gameUI, final Viewport viewport) {
|
||||||
|
generateBackdropModel();
|
||||||
|
super.innerPositionBounds(gameUI, viewport);
|
||||||
|
}
|
||||||
|
|
||||||
|
private MdlxModel generateBackdropModel() {
|
||||||
|
final MdlxModel model = new MdlxModel();
|
||||||
|
final int edgeFileMaterialId = generateMaterial(model, this.edgeFileString, true);
|
||||||
|
final int backgroundMaterialId = generateMaterial(model, this.backgroundString, this.tileBackground);
|
||||||
|
final MdlxGeoset edgeGeoset = new MdlxGeoset();
|
||||||
|
final float[] edgeGeosetVertices = new float[32 * 4];
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int generateMaterial(final MdlxModel model, final String path, final boolean wrap) {
|
||||||
|
final MdlxTexture edgeFileReference = new MdlxTexture();
|
||||||
|
if (wrap) {
|
||||||
|
edgeFileReference.setWrapMode(WrapMode.REPEAT_BOTH);
|
||||||
|
}
|
||||||
|
edgeFileReference.setPath(path);
|
||||||
|
final int textureId = model.getTextures().size();
|
||||||
|
model.getTextures().add(edgeFileReference);
|
||||||
|
final MdlxMaterial edgeFileMaterial = new MdlxMaterial();
|
||||||
|
final MdlxLayer edgeFileMaterialLayer = new MdlxLayer();
|
||||||
|
edgeFileMaterialLayer.setAlpha(1.0f);
|
||||||
|
edgeFileMaterialLayer.setFilterMode(FilterMode.BLEND);
|
||||||
|
edgeFileMaterialLayer.setTextureId(textureId);
|
||||||
|
edgeFileMaterial.getLayers().add(edgeFileMaterialLayer);
|
||||||
|
final int materialId = model.getMaterials().size();
|
||||||
|
model.getMaterials().add(edgeFileMaterial);
|
||||||
|
return materialId;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,138 @@
|
|||||||
|
package com.etheller.warsmash.parsers.fdf.frames;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||||
|
import com.badlogic.gdx.utils.viewport.Viewport;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.GameUI;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.datamodel.FramePoint;
|
||||||
|
import com.etheller.warsmash.viewer5.Scene;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.mdx.MdxComplexInstance;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.mdx.MdxModel;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.mdx.SequenceLoopMode;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.PrimaryTag;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.w3x.SequenceUtils;
|
||||||
|
|
||||||
|
public class SpriteFrame extends AbstractUIFrame {
|
||||||
|
|
||||||
|
protected final Scene scene;
|
||||||
|
protected final Viewport uiViewport;
|
||||||
|
private MdxComplexInstance instance;
|
||||||
|
private float zDepth;
|
||||||
|
|
||||||
|
public SpriteFrame(final String name, final UIFrame parent, final Scene scene, final Viewport uiViewport) {
|
||||||
|
super(name, parent);
|
||||||
|
this.scene = scene;
|
||||||
|
this.uiViewport = uiViewport;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setModel(final MdxModel model) {
|
||||||
|
if (this.instance != null) {
|
||||||
|
this.scene.removeInstance(this.instance);
|
||||||
|
}
|
||||||
|
if (model != null) {
|
||||||
|
this.instance = (MdxComplexInstance) model.addInstance();
|
||||||
|
this.instance.setSequenceLoopMode(SequenceLoopMode.MODEL_LOOP);
|
||||||
|
this.instance.setScene(this.scene);
|
||||||
|
this.instance.setLocation(this.renderBounds.x, this.renderBounds.y, this.zDepth);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.instance = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setVisible(final boolean visible) {
|
||||||
|
super.setVisible(visible);
|
||||||
|
updateInstanceLocation(this.uiViewport);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void internalRender(final SpriteBatch batch, final BitmapFont baseFont, final GlyphLayout glyphLayout) {
|
||||||
|
super.internalRender(batch, baseFont, glyphLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFramePointX(final FramePoint framePoint, final float x) {
|
||||||
|
super.setFramePointX(framePoint, x);
|
||||||
|
updateInstanceLocation(this.uiViewport);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFramePointY(final FramePoint framePoint, final float y) {
|
||||||
|
super.setFramePointY(framePoint, y);
|
||||||
|
updateInstanceLocation(this.uiViewport);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setZDepth(final float depth) {
|
||||||
|
this.zDepth = depth;
|
||||||
|
updateInstanceLocation(this.uiViewport);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void innerPositionBounds(final GameUI gameUI, final Viewport viewport) {
|
||||||
|
super.innerPositionBounds(gameUI, viewport);
|
||||||
|
updateInstanceLocation(viewport);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSequence(final int index) {
|
||||||
|
if (this.instance != null) {
|
||||||
|
this.instance.setSequence(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSequence(final String animationName) {
|
||||||
|
if (this.instance != null) {
|
||||||
|
SequenceUtils.randomSequence(this.instance, animationName.toLowerCase());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSequence(final PrimaryTag animationName) {
|
||||||
|
if (this.instance != null) {
|
||||||
|
SequenceUtils.randomSequence(this.instance, animationName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAnimationSpeed(final float speedRatio) {
|
||||||
|
if (this.instance != null) {
|
||||||
|
this.instance.setAnimationSpeed(speedRatio);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFrame(final int animationFrame) {
|
||||||
|
if (this.instance != null) {
|
||||||
|
this.instance.setFrame(animationFrame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFrameByRatio(final float ratioOfAnimationCompleted) {
|
||||||
|
if (this.instance != null) {
|
||||||
|
this.instance.setFrameByRatio(ratioOfAnimationCompleted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateInstanceLocation(final Viewport viewport) {
|
||||||
|
if (this.instance != null) {
|
||||||
|
this.instance.setLocation(GameUI.unconvertX(viewport, this.renderBounds.x),
|
||||||
|
GameUI.unconvertY(viewport, this.renderBounds.y), this.zDepth);
|
||||||
|
if (isVisible()) {
|
||||||
|
this.instance.show();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.instance.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSequenceEnded() {
|
||||||
|
return this.instance.sequenceEnded;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReplaceableId(final int replaceableId, final String blpPath) {
|
||||||
|
if (this.instance != null) {
|
||||||
|
this.instance.setReplaceableTexture(replaceableId, blpPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,496 @@
|
|||||||
|
package com.etheller.warsmash.parsers.fdf.frames;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.Color;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||||
|
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
|
||||||
|
import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;
|
||||||
|
import com.badlogic.gdx.utils.viewport.Viewport;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.GameUI;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.datamodel.AnchorDefinition;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.datamodel.FramePoint;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.datamodel.TextJustify;
|
||||||
|
|
||||||
|
public class StringFrame extends AbstractRenderableFrame {
|
||||||
|
private final List<SingleStringFrame> internalFrames = new ArrayList<>();
|
||||||
|
private Color color;
|
||||||
|
private String text = "Default string";
|
||||||
|
private final TextJustify justifyH;
|
||||||
|
private final TextJustify justifyV;
|
||||||
|
private final BitmapFont frameFont;
|
||||||
|
private Color fontShadowColor;
|
||||||
|
private float fontShadowOffsetX;
|
||||||
|
private float fontShadowOffsetY;
|
||||||
|
private float alpha = 1.0f;
|
||||||
|
private final SimpleFrame internalFramesContainer;
|
||||||
|
private float predictedViewportHeight;
|
||||||
|
|
||||||
|
static ShapeRenderer shapeRenderer = new ShapeRenderer();
|
||||||
|
private final Color fontHighlightColor;
|
||||||
|
private final Color fontDisabledColor;
|
||||||
|
private final Color fontColor;
|
||||||
|
|
||||||
|
public StringFrame(final String name, final UIFrame parent, final Color color, final TextJustify justifyH,
|
||||||
|
final TextJustify justifyV, final BitmapFont frameFont, final String text, final Color fontHighlightColor,
|
||||||
|
final Color fontDisabledColor) {
|
||||||
|
super(name, parent);
|
||||||
|
this.fontColor = color;
|
||||||
|
this.color = color;
|
||||||
|
this.justifyH = justifyH;
|
||||||
|
this.justifyV = justifyV;
|
||||||
|
this.frameFont = frameFont;
|
||||||
|
this.text = text;
|
||||||
|
this.fontHighlightColor = fontHighlightColor;
|
||||||
|
this.fontDisabledColor = fontDisabledColor;
|
||||||
|
this.internalFramesContainer = new SimpleFrame(null, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getText() {
|
||||||
|
return this.text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setText(final String text, final GameUI gameUI, final Viewport viewport) {
|
||||||
|
if (text == null) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
this.text = text;
|
||||||
|
positionBounds(gameUI, viewport);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColor(final Color color) {
|
||||||
|
for (final SingleStringFrame internalFrame : this.internalFrames) {
|
||||||
|
if (internalFrame.getColor() == this.color) {
|
||||||
|
internalFrame.setColor(color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color getColor() {
|
||||||
|
return this.color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color getFontOriginalColor() {
|
||||||
|
return this.fontColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color getFontDisabledColor() {
|
||||||
|
return this.fontDisabledColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color getFontHighlightColor() {
|
||||||
|
return this.fontHighlightColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFontShadowColor(final Color fontShadowColor) {
|
||||||
|
this.fontShadowColor = fontShadowColor;
|
||||||
|
for (final SingleStringFrame internalFrame : this.internalFrames) {
|
||||||
|
internalFrame.setFontShadowColor(fontShadowColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFontShadowOffsetX(final float fontShadowOffsetX) {
|
||||||
|
this.fontShadowOffsetX = fontShadowOffsetX;
|
||||||
|
for (final SingleStringFrame internalFrame : this.internalFrames) {
|
||||||
|
internalFrame.setFontShadowOffsetX(fontShadowOffsetX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFontShadowOffsetY(final float fontShadowOffsetY) {
|
||||||
|
this.fontShadowOffsetY = fontShadowOffsetY;
|
||||||
|
for (final SingleStringFrame internalFrame : this.internalFrames) {
|
||||||
|
internalFrame.setFontShadowOffsetY(fontShadowOffsetY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void internalRender(final SpriteBatch batch, final BitmapFont baseFont, final GlyphLayout glyphLayout) {
|
||||||
|
this.internalFramesContainer.render(batch, baseFont, glyphLayout);
|
||||||
|
|
||||||
|
if (GameUI.DEBUG) {
|
||||||
|
batch.end();
|
||||||
|
shapeRenderer.setProjectionMatrix(batch.getProjectionMatrix());
|
||||||
|
shapeRenderer.setColor(1f, 1f, 1f, 1f);
|
||||||
|
shapeRenderer.begin(ShapeType.Line);
|
||||||
|
shapeRenderer.rect(this.renderBounds.x, this.renderBounds.y, this.renderBounds.width,
|
||||||
|
this.renderBounds.height);
|
||||||
|
|
||||||
|
shapeRenderer.end();
|
||||||
|
|
||||||
|
batch.begin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void positionBounds(final GameUI gameUI, final Viewport viewport) {
|
||||||
|
createInternalFrames(gameUI.getGlyphLayout());
|
||||||
|
if (this.renderBounds.height == 0) {
|
||||||
|
this.renderBounds.height = getPredictedViewportHeight();
|
||||||
|
}
|
||||||
|
super.positionBounds(gameUI, viewport);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void innerPositionBounds(final GameUI gameUI, final Viewport viewport) {
|
||||||
|
this.internalFramesContainer.positionBounds(gameUI, viewport);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createInternalFrames(final GlyphLayout glyphLayout) {
|
||||||
|
for (final SingleStringFrame internalFrame : this.internalFrames) {
|
||||||
|
this.internalFramesContainer.remove(internalFrame);
|
||||||
|
}
|
||||||
|
this.internalFrames.clear();
|
||||||
|
final StringBuilder currentLine = new StringBuilder();
|
||||||
|
final StringBuilder currentWord = new StringBuilder();
|
||||||
|
float currentXCoordForWord = 0;
|
||||||
|
float currentXCoordForFrames = 0;
|
||||||
|
final float usedWidth = 0;
|
||||||
|
float usedHeight = 0;
|
||||||
|
float usedWidthMax = 0;
|
||||||
|
final float startingBoundsWidth = this.renderBounds.width;
|
||||||
|
final boolean firstInLine = false;
|
||||||
|
Color currentColor = this.color;
|
||||||
|
for (int i = 0; i < this.text.length(); i++) {
|
||||||
|
final char c = this.text.charAt(i);
|
||||||
|
switch (c) {
|
||||||
|
case '|': {
|
||||||
|
// special control character
|
||||||
|
if ((i + 1) < this.text.length()) {
|
||||||
|
final char escapedCharacter = this.text.charAt(i + 1);
|
||||||
|
switch (escapedCharacter) {
|
||||||
|
case 'c':
|
||||||
|
case 'C':
|
||||||
|
if ((i + 9) < this.text.length()) {
|
||||||
|
int colorInt;
|
||||||
|
try {
|
||||||
|
final String upperCase = this.text.substring(i + 2, i + 10).toUpperCase();
|
||||||
|
colorInt = (int) Long.parseLong(upperCase, 16);
|
||||||
|
}
|
||||||
|
catch (final NumberFormatException exc) {
|
||||||
|
currentWord.append(c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i += 9;
|
||||||
|
{
|
||||||
|
final String wordString = currentWord.toString();
|
||||||
|
currentWord.setLength(0);
|
||||||
|
glyphLayout.setText(this.frameFont, wordString);
|
||||||
|
final float wordWidth = glyphLayout.width;
|
||||||
|
if ((startingBoundsWidth > 0)
|
||||||
|
&& ((currentXCoordForWord + wordWidth) >= startingBoundsWidth)) {
|
||||||
|
final String currentLineString = currentLine.toString();
|
||||||
|
currentLine.setLength(0);
|
||||||
|
glyphLayout.setText(this.frameFont, currentLineString);
|
||||||
|
usedWidthMax = Math.max(currentXCoordForFrames + glyphLayout.width, usedWidthMax);
|
||||||
|
final SingleStringFrame singleStringFrame = new SingleStringFrame(currentLineString,
|
||||||
|
this.internalFramesContainer, currentColor, TextJustify.LEFT,
|
||||||
|
TextJustify.TOP, this.frameFont);
|
||||||
|
singleStringFrame.setHeight(this.frameFont.getLineHeight());
|
||||||
|
singleStringFrame.setWidth(glyphLayout.width);
|
||||||
|
singleStringFrame.setAlpha(this.alpha);
|
||||||
|
singleStringFrame.setFontShadowColor(this.fontShadowColor);
|
||||||
|
singleStringFrame.setFontShadowOffsetX(this.fontShadowOffsetX);
|
||||||
|
singleStringFrame.setFontShadowOffsetY(this.fontShadowOffsetY);
|
||||||
|
singleStringFrame.addAnchor(new AnchorDefinition(FramePoint.TOPLEFT,
|
||||||
|
currentXCoordForFrames, usedHeight));
|
||||||
|
this.internalFrames.add(singleStringFrame);
|
||||||
|
usedHeight += this.frameFont.getLineHeight();
|
||||||
|
currentXCoordForWord = 0;
|
||||||
|
currentXCoordForFrames = 0;
|
||||||
|
}
|
||||||
|
currentXCoordForWord += wordWidth;
|
||||||
|
currentLine.append(wordString);
|
||||||
|
|
||||||
|
final String currentLineString = currentLine.toString();
|
||||||
|
currentLine.setLength(0);
|
||||||
|
glyphLayout.setText(this.frameFont, currentLineString);
|
||||||
|
usedWidthMax = Math.max(currentXCoordForFrames + glyphLayout.width, usedWidthMax);
|
||||||
|
final SingleStringFrame singleStringFrame = new SingleStringFrame(currentLineString,
|
||||||
|
this.internalFramesContainer, currentColor, TextJustify.LEFT, TextJustify.TOP,
|
||||||
|
this.frameFont);
|
||||||
|
singleStringFrame.setHeight(this.frameFont.getLineHeight());
|
||||||
|
singleStringFrame.setWidth(glyphLayout.width);
|
||||||
|
singleStringFrame.setAlpha(this.alpha);
|
||||||
|
singleStringFrame.setFontShadowColor(this.fontShadowColor);
|
||||||
|
singleStringFrame.setFontShadowOffsetX(this.fontShadowOffsetX);
|
||||||
|
singleStringFrame.setFontShadowOffsetY(this.fontShadowOffsetY);
|
||||||
|
singleStringFrame.addAnchor(
|
||||||
|
new AnchorDefinition(FramePoint.TOPLEFT, currentXCoordForFrames, -usedHeight));
|
||||||
|
this.internalFrames.add(singleStringFrame);
|
||||||
|
currentXCoordForFrames = currentXCoordForWord;
|
||||||
|
|
||||||
|
currentColor = new Color((colorInt << 8) | (colorInt >>> 24));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
case 'R':
|
||||||
|
i++; {
|
||||||
|
final String wordString = currentWord.toString();
|
||||||
|
currentWord.setLength(0);
|
||||||
|
glyphLayout.setText(this.frameFont, wordString);
|
||||||
|
final float wordWidth = glyphLayout.width;
|
||||||
|
if ((startingBoundsWidth > 0) && ((currentXCoordForWord + wordWidth) >= startingBoundsWidth)) {
|
||||||
|
final String currentLineString = currentLine.toString();
|
||||||
|
currentLine.setLength(0);
|
||||||
|
glyphLayout.setText(this.frameFont, currentLineString);
|
||||||
|
usedWidthMax = Math.max(currentXCoordForFrames + glyphLayout.width, usedWidthMax);
|
||||||
|
final SingleStringFrame singleStringFrame = new SingleStringFrame(currentLineString,
|
||||||
|
this.internalFramesContainer, currentColor, TextJustify.LEFT, TextJustify.TOP,
|
||||||
|
this.frameFont);
|
||||||
|
singleStringFrame.setHeight(this.frameFont.getLineHeight());
|
||||||
|
singleStringFrame.setWidth(glyphLayout.width);
|
||||||
|
singleStringFrame.setAlpha(this.alpha);
|
||||||
|
singleStringFrame.setFontShadowColor(this.fontShadowColor);
|
||||||
|
singleStringFrame.setFontShadowOffsetX(this.fontShadowOffsetX);
|
||||||
|
singleStringFrame.setFontShadowOffsetY(this.fontShadowOffsetY);
|
||||||
|
singleStringFrame.addAnchor(
|
||||||
|
new AnchorDefinition(FramePoint.TOPLEFT, currentXCoordForFrames, -usedHeight));
|
||||||
|
this.internalFrames.add(singleStringFrame);
|
||||||
|
usedHeight += this.frameFont.getLineHeight();
|
||||||
|
currentXCoordForWord = 0;
|
||||||
|
currentXCoordForFrames = 0;
|
||||||
|
}
|
||||||
|
currentXCoordForWord += wordWidth;
|
||||||
|
currentLine.append(wordString);
|
||||||
|
|
||||||
|
final String currentLineString = currentLine.toString();
|
||||||
|
currentLine.setLength(0);
|
||||||
|
glyphLayout.setText(this.frameFont, currentLineString);
|
||||||
|
usedWidthMax = Math.max(currentXCoordForFrames + glyphLayout.width, usedWidthMax);
|
||||||
|
final SingleStringFrame singleStringFrame = new SingleStringFrame(currentLineString,
|
||||||
|
this.internalFramesContainer, currentColor, TextJustify.LEFT, TextJustify.TOP,
|
||||||
|
this.frameFont);
|
||||||
|
singleStringFrame.setHeight(this.frameFont.getLineHeight());
|
||||||
|
singleStringFrame.setWidth(glyphLayout.width);
|
||||||
|
singleStringFrame.setAlpha(this.alpha);
|
||||||
|
singleStringFrame.setFontShadowColor(this.fontShadowColor);
|
||||||
|
singleStringFrame.setFontShadowOffsetX(this.fontShadowOffsetX);
|
||||||
|
singleStringFrame.setFontShadowOffsetY(this.fontShadowOffsetY);
|
||||||
|
singleStringFrame.addAnchor(
|
||||||
|
new AnchorDefinition(FramePoint.TOPLEFT, currentXCoordForFrames, -usedHeight));
|
||||||
|
this.internalFrames.add(singleStringFrame);
|
||||||
|
currentXCoordForFrames = currentXCoordForWord;
|
||||||
|
}
|
||||||
|
currentColor = this.color;
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
case 'N': {
|
||||||
|
|
||||||
|
final String wordString = currentWord.toString();
|
||||||
|
currentWord.setLength(0);
|
||||||
|
glyphLayout.setText(this.frameFont, wordString);
|
||||||
|
final float wordWidth = glyphLayout.width;
|
||||||
|
if ((startingBoundsWidth > 0) && ((currentXCoordForWord + wordWidth) >= startingBoundsWidth)) {
|
||||||
|
final String currentLineString = currentLine.toString();
|
||||||
|
currentLine.setLength(0);
|
||||||
|
glyphLayout.setText(this.frameFont, currentLineString);
|
||||||
|
usedWidthMax = Math.max(currentXCoordForFrames + glyphLayout.width, usedWidthMax);
|
||||||
|
final SingleStringFrame singleStringFrame = new SingleStringFrame(currentLineString,
|
||||||
|
this.internalFramesContainer, currentColor, TextJustify.LEFT, TextJustify.TOP,
|
||||||
|
this.frameFont);
|
||||||
|
singleStringFrame.setHeight(this.frameFont.getLineHeight());
|
||||||
|
singleStringFrame.setWidth(glyphLayout.width);
|
||||||
|
singleStringFrame.setAlpha(this.alpha);
|
||||||
|
singleStringFrame.setFontShadowColor(this.fontShadowColor);
|
||||||
|
singleStringFrame.setFontShadowOffsetX(this.fontShadowOffsetX);
|
||||||
|
singleStringFrame.setFontShadowOffsetY(this.fontShadowOffsetY);
|
||||||
|
singleStringFrame.addAnchor(
|
||||||
|
new AnchorDefinition(FramePoint.TOPLEFT, currentXCoordForFrames, -usedHeight));
|
||||||
|
this.internalFrames.add(singleStringFrame);
|
||||||
|
usedHeight += this.frameFont.getLineHeight();
|
||||||
|
currentXCoordForWord = 0;
|
||||||
|
currentXCoordForFrames = 0;
|
||||||
|
}
|
||||||
|
currentXCoordForWord += wordWidth;
|
||||||
|
currentLine.append(wordString);
|
||||||
|
|
||||||
|
final String currentLineString = currentLine.toString();
|
||||||
|
currentLine.setLength(0);
|
||||||
|
glyphLayout.setText(this.frameFont, currentLineString);
|
||||||
|
usedWidthMax = Math.max(currentXCoordForFrames + glyphLayout.width, usedWidthMax);
|
||||||
|
final SingleStringFrame singleStringFrame = new SingleStringFrame(currentLineString,
|
||||||
|
this.internalFramesContainer, currentColor, TextJustify.LEFT, TextJustify.TOP,
|
||||||
|
this.frameFont);
|
||||||
|
singleStringFrame.setHeight(this.frameFont.getLineHeight());
|
||||||
|
singleStringFrame.setWidth(glyphLayout.width);
|
||||||
|
singleStringFrame.setAlpha(this.alpha);
|
||||||
|
singleStringFrame.setFontShadowColor(this.fontShadowColor);
|
||||||
|
singleStringFrame.setFontShadowOffsetX(this.fontShadowOffsetX);
|
||||||
|
singleStringFrame.setFontShadowOffsetY(this.fontShadowOffsetY);
|
||||||
|
singleStringFrame.addAnchor(
|
||||||
|
new AnchorDefinition(FramePoint.TOPLEFT, currentXCoordForFrames, -usedHeight));
|
||||||
|
this.internalFrames.add(singleStringFrame);
|
||||||
|
usedHeight += this.frameFont.getLineHeight();
|
||||||
|
currentXCoordForWord = 0;
|
||||||
|
currentXCoordForFrames = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
currentWord.append(c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ' ':
|
||||||
|
currentWord.append(' ');
|
||||||
|
final String wordString = currentWord.toString();
|
||||||
|
currentWord.setLength(0);
|
||||||
|
glyphLayout.setText(this.frameFont, wordString);
|
||||||
|
final float wordWidth = glyphLayout.width;
|
||||||
|
if ((startingBoundsWidth > 0) && ((currentXCoordForWord + wordWidth) >= startingBoundsWidth)) {
|
||||||
|
final String currentLineString = currentLine.toString();
|
||||||
|
currentLine.setLength(0);
|
||||||
|
glyphLayout.setText(this.frameFont, currentLineString);
|
||||||
|
usedWidthMax = Math.max(currentXCoordForFrames + glyphLayout.width, usedWidthMax);
|
||||||
|
final SingleStringFrame singleStringFrame = new SingleStringFrame(currentLineString,
|
||||||
|
this.internalFramesContainer, currentColor, TextJustify.LEFT, TextJustify.TOP,
|
||||||
|
this.frameFont);
|
||||||
|
singleStringFrame.setHeight(this.frameFont.getLineHeight());
|
||||||
|
singleStringFrame.setWidth(glyphLayout.width);
|
||||||
|
singleStringFrame.setAlpha(this.alpha);
|
||||||
|
singleStringFrame.setFontShadowColor(this.fontShadowColor);
|
||||||
|
singleStringFrame.setFontShadowOffsetX(this.fontShadowOffsetX);
|
||||||
|
singleStringFrame.setFontShadowOffsetY(this.fontShadowOffsetY);
|
||||||
|
singleStringFrame
|
||||||
|
.addAnchor(new AnchorDefinition(FramePoint.TOPLEFT, currentXCoordForFrames, -usedHeight));
|
||||||
|
this.internalFrames.add(singleStringFrame);
|
||||||
|
usedHeight += this.frameFont.getLineHeight();
|
||||||
|
currentXCoordForWord = 0;
|
||||||
|
currentXCoordForFrames = 0;
|
||||||
|
}
|
||||||
|
currentXCoordForWord += wordWidth;
|
||||||
|
currentLine.append(wordString);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
currentWord.append(c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
final String wordString = currentWord.toString();
|
||||||
|
currentWord.setLength(0);
|
||||||
|
glyphLayout.setText(this.frameFont, wordString);
|
||||||
|
final float wordWidth = glyphLayout.width;
|
||||||
|
if ((startingBoundsWidth > 0) && ((currentXCoordForWord + wordWidth) >= startingBoundsWidth)) {
|
||||||
|
final String currentLineString = currentLine.toString();
|
||||||
|
currentLine.setLength(0);
|
||||||
|
glyphLayout.setText(this.frameFont, currentLineString);
|
||||||
|
usedWidthMax = Math.max(currentXCoordForFrames + glyphLayout.width, usedWidthMax);
|
||||||
|
final SingleStringFrame singleStringFrame = new SingleStringFrame(currentLineString,
|
||||||
|
this.internalFramesContainer, currentColor, TextJustify.LEFT, TextJustify.TOP, this.frameFont);
|
||||||
|
singleStringFrame.setHeight(this.frameFont.getLineHeight());
|
||||||
|
singleStringFrame.setWidth(glyphLayout.width);
|
||||||
|
singleStringFrame.setAlpha(this.alpha);
|
||||||
|
singleStringFrame.setFontShadowColor(this.fontShadowColor);
|
||||||
|
singleStringFrame.setFontShadowOffsetX(this.fontShadowOffsetX);
|
||||||
|
singleStringFrame.setFontShadowOffsetY(this.fontShadowOffsetY);
|
||||||
|
singleStringFrame
|
||||||
|
.addAnchor(new AnchorDefinition(FramePoint.TOPLEFT, currentXCoordForFrames, -usedHeight));
|
||||||
|
this.internalFrames.add(singleStringFrame);
|
||||||
|
usedHeight += this.frameFont.getLineHeight();
|
||||||
|
currentXCoordForWord = 0;
|
||||||
|
currentXCoordForFrames = 0;
|
||||||
|
}
|
||||||
|
currentXCoordForWord += wordWidth;
|
||||||
|
currentLine.append(wordString);
|
||||||
|
|
||||||
|
final String currentLineString = currentLine.toString();
|
||||||
|
currentLine.setLength(0);
|
||||||
|
glyphLayout.setText(this.frameFont, currentLineString);
|
||||||
|
usedWidthMax = Math.max(currentXCoordForFrames + glyphLayout.width, usedWidthMax);
|
||||||
|
final SingleStringFrame singleStringFrame = new SingleStringFrame(currentLineString,
|
||||||
|
this.internalFramesContainer, currentColor, TextJustify.LEFT, TextJustify.TOP, this.frameFont);
|
||||||
|
singleStringFrame.setHeight(this.frameFont.getLineHeight());
|
||||||
|
singleStringFrame.setWidth(glyphLayout.width);
|
||||||
|
singleStringFrame.setAlpha(this.alpha);
|
||||||
|
singleStringFrame.setFontShadowColor(this.fontShadowColor);
|
||||||
|
singleStringFrame.setFontShadowOffsetX(this.fontShadowOffsetX);
|
||||||
|
singleStringFrame.setFontShadowOffsetY(this.fontShadowOffsetY);
|
||||||
|
singleStringFrame.addAnchor(new AnchorDefinition(FramePoint.TOPLEFT, currentXCoordForFrames, -usedHeight));
|
||||||
|
this.internalFrames.add(singleStringFrame);
|
||||||
|
currentXCoordForFrames = currentXCoordForWord;
|
||||||
|
usedHeight += this.frameFont.getCapHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.internalFramesContainer.setWidth(usedWidthMax);
|
||||||
|
this.internalFramesContainer.setHeight(usedHeight);
|
||||||
|
this.predictedViewportHeight = (usedHeight - this.frameFont.getCapHeight()) + this.frameFont.getLineHeight();
|
||||||
|
|
||||||
|
this.internalFramesContainer.clearFramePointAssignments();
|
||||||
|
switch (this.justifyH) {
|
||||||
|
case CENTER:
|
||||||
|
switch (this.justifyV) {
|
||||||
|
case MIDDLE:
|
||||||
|
this.internalFramesContainer.addAnchor(new AnchorDefinition(FramePoint.CENTER, 0, 0));
|
||||||
|
break;
|
||||||
|
case BOTTOM:
|
||||||
|
this.internalFramesContainer.addAnchor(new AnchorDefinition(FramePoint.BOTTOM, 0, 0));
|
||||||
|
break;
|
||||||
|
case TOP:
|
||||||
|
default:
|
||||||
|
this.internalFramesContainer.addAnchor(new AnchorDefinition(FramePoint.TOP, 0, 0));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RIGHT:
|
||||||
|
switch (this.justifyV) {
|
||||||
|
case MIDDLE:
|
||||||
|
this.internalFramesContainer.addAnchor(new AnchorDefinition(FramePoint.RIGHT, 0, 0));
|
||||||
|
break;
|
||||||
|
case BOTTOM:
|
||||||
|
this.internalFramesContainer.addAnchor(new AnchorDefinition(FramePoint.BOTTOMRIGHT, 0, 0));
|
||||||
|
break;
|
||||||
|
case TOP:
|
||||||
|
default:
|
||||||
|
this.internalFramesContainer.addAnchor(new AnchorDefinition(FramePoint.TOPRIGHT, 0, 0));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LEFT:
|
||||||
|
default:
|
||||||
|
switch (this.justifyV) {
|
||||||
|
case MIDDLE:
|
||||||
|
this.internalFramesContainer.addAnchor(new AnchorDefinition(FramePoint.LEFT, 0, 0));
|
||||||
|
break;
|
||||||
|
case BOTTOM:
|
||||||
|
this.internalFramesContainer.addAnchor(new AnchorDefinition(FramePoint.BOTTOMLEFT, 0, 0));
|
||||||
|
break;
|
||||||
|
case TOP:
|
||||||
|
default:
|
||||||
|
this.internalFramesContainer.addAnchor(new AnchorDefinition(FramePoint.TOPLEFT, 0, 0));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final SingleStringFrame internalFrame : this.internalFrames) {
|
||||||
|
this.internalFramesContainer.add(internalFrame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAlpha(final float alpha) {
|
||||||
|
this.alpha = alpha;
|
||||||
|
for (final SingleStringFrame internalFrame : this.internalFrames) {
|
||||||
|
internalFrame.setAlpha(alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getPredictedViewportHeight() {
|
||||||
|
return this.predictedViewportHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BitmapFont getFrameFont() {
|
||||||
|
return this.frameFont;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package com.etheller.warsmash.parsers.fdf.frames;
|
||||||
|
|
||||||
|
public class TextButtonFrame extends GlueTextButtonFrame {
|
||||||
|
private float buttonPushedTextOffsetX;
|
||||||
|
private float buttonPushedTextOffsetY;
|
||||||
|
|
||||||
|
public TextButtonFrame(final String name, final UIFrame parent) {
|
||||||
|
super(name, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setButtonPushedTextOffsetX(final float buttonPushedTextOffsetX) {
|
||||||
|
this.buttonPushedTextOffsetX = buttonPushedTextOffsetX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setButtonPushedTextOffsetY(final float buttonPushedTextOffsetY) {
|
||||||
|
this.buttonPushedTextOffsetY = buttonPushedTextOffsetY;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,86 @@
|
|||||||
|
package com.etheller.warsmash.parsers.fdf.frames;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.Color;
|
||||||
|
import com.badlogic.gdx.graphics.Texture;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||||
|
import com.badlogic.gdx.utils.viewport.Viewport;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.GameUI;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.datamodel.Vector4Definition;
|
||||||
|
|
||||||
|
public class TextureFrame extends AbstractRenderableFrame {
|
||||||
|
private TextureRegion texture;
|
||||||
|
private final boolean decorateFileNames;
|
||||||
|
private final Vector4Definition texCoord;
|
||||||
|
private Color color;
|
||||||
|
|
||||||
|
public TextureFrame(final String name, final UIFrame parent, final boolean decorateFileNames,
|
||||||
|
final Vector4Definition texCoord) {
|
||||||
|
super(name, parent);
|
||||||
|
this.decorateFileNames = decorateFileNames;
|
||||||
|
this.texCoord = texCoord;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void internalRender(final SpriteBatch batch, final BitmapFont baseFont, final GlyphLayout glyphLayout) {
|
||||||
|
if (this.texture == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.color != null) {
|
||||||
|
batch.setColor(this.color);
|
||||||
|
}
|
||||||
|
batch.draw(this.texture, this.renderBounds.x, this.renderBounds.y, this.renderBounds.width,
|
||||||
|
this.renderBounds.height);
|
||||||
|
if (this.color != null) {
|
||||||
|
batch.setColor(1f, 1f, 1f, 1f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void innerPositionBounds(final GameUI gameUI, final Viewport viewport) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColor(final Color color) {
|
||||||
|
this.color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTexture(String file, final GameUI gameUI) {
|
||||||
|
if (this.decorateFileNames) {
|
||||||
|
file = gameUI.trySkinField(file);
|
||||||
|
}
|
||||||
|
final Texture texture = gameUI.loadTexture(file);
|
||||||
|
if (texture != null) {
|
||||||
|
setTexture(texture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTexCoord(final float x, final float y, final float z, final float w) {
|
||||||
|
this.texCoord.set(x, y, z, w);
|
||||||
|
if (this.texture != null) {
|
||||||
|
this.texture.setRegion(this.texCoord.getX(), this.texCoord.getZ(), this.texCoord.getY(),
|
||||||
|
this.texCoord.getW());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTexture(final Texture texture) {
|
||||||
|
if (texture == null) {
|
||||||
|
this.texture = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final TextureRegion texRegion;
|
||||||
|
if (this.texCoord != null) {
|
||||||
|
texRegion = new TextureRegion(texture, this.texCoord.getX(), this.texCoord.getZ(), this.texCoord.getY(),
|
||||||
|
this.texCoord.getW());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
texRegion = new TextureRegion(texture);
|
||||||
|
}
|
||||||
|
this.texture = texRegion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTexture(final TextureRegion texture) {
|
||||||
|
this.texture = texture;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
package com.etheller.warsmash.parsers.fdf.frames;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||||
|
import com.badlogic.gdx.utils.viewport.Viewport;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.GameUI;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.datamodel.AnchorDefinition;
|
||||||
|
import com.etheller.warsmash.parsers.fdf.datamodel.FramePoint;
|
||||||
|
|
||||||
|
public interface UIFrame {
|
||||||
|
public void render(SpriteBatch batch, BitmapFont baseFont, GlyphLayout glyphLayout);
|
||||||
|
|
||||||
|
public float getFramePointX(FramePoint framePoint);
|
||||||
|
|
||||||
|
public float getFramePointY(FramePoint framePoint);
|
||||||
|
|
||||||
|
void setFramePointX(final FramePoint framePoint, final float x);
|
||||||
|
|
||||||
|
void setFramePointY(final FramePoint framePoint, final float y);
|
||||||
|
|
||||||
|
void positionBounds(GameUI gameUI, final Viewport viewport);
|
||||||
|
|
||||||
|
void addAnchor(final AnchorDefinition anchorDefinition);
|
||||||
|
|
||||||
|
void addSetPoint(SetPoint setPointDefinition);
|
||||||
|
|
||||||
|
void setWidth(final float width);
|
||||||
|
|
||||||
|
void setHeight(final float height);
|
||||||
|
|
||||||
|
float getAssignedWidth();
|
||||||
|
|
||||||
|
float getAssignedHeight();
|
||||||
|
|
||||||
|
void setSetAllPoints(boolean setAllPoints);
|
||||||
|
|
||||||
|
void setSetAllPoints(boolean setAllPoints, float inset);
|
||||||
|
|
||||||
|
void setVisible(boolean visible);
|
||||||
|
|
||||||
|
UIFrame getParent();
|
||||||
|
|
||||||
|
boolean isVisible();
|
||||||
|
|
||||||
|
boolean isVisibleOnScreen();
|
||||||
|
|
||||||
|
UIFrame touchDown(float screenX, float screenY, int button);
|
||||||
|
|
||||||
|
UIFrame touchUp(float screenX, float screenY, int button);
|
||||||
|
|
||||||
|
UIFrame getFrameChildUnderMouse(float screenX, float screenY);
|
||||||
|
|
||||||
|
String getName();
|
||||||
|
}
|
2864
core/src/com/etheller/warsmash/parsers/jass/Jass2.java
Normal file
2864
core/src/com/etheller/warsmash/parsers/jass/Jass2.java
Normal file
File diff suppressed because it is too large
Load Diff
64
core/src/com/etheller/warsmash/parsers/jass/JassTest.java
Normal file
64
core/src/com/etheller/warsmash/parsers/jass/JassTest.java
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
package com.etheller.warsmash.parsers.jass;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import org.antlr.v4.runtime.BaseErrorListener;
|
||||||
|
import org.antlr.v4.runtime.CharStreams;
|
||||||
|
import org.antlr.v4.runtime.CommonTokenStream;
|
||||||
|
import org.antlr.v4.runtime.RecognitionException;
|
||||||
|
import org.antlr.v4.runtime.Recognizer;
|
||||||
|
|
||||||
|
import com.etheller.interpreter.JassLexer;
|
||||||
|
import com.etheller.interpreter.JassParser;
|
||||||
|
import com.etheller.interpreter.ast.visitors.JassProgramVisitor;
|
||||||
|
import com.etheller.warsmash.datasources.CompoundDataSourceDescriptor;
|
||||||
|
import com.etheller.warsmash.datasources.DataSource;
|
||||||
|
import com.etheller.warsmash.datasources.DataSourceDescriptor;
|
||||||
|
import com.etheller.warsmash.datasources.FolderDataSourceDescriptor;
|
||||||
|
|
||||||
|
public class JassTest {
|
||||||
|
public static final boolean REPORT_SYNTAX_ERRORS = true;
|
||||||
|
|
||||||
|
public static void main(final String[] args) {
|
||||||
|
final JassProgramVisitor jassProgramVisitor = new JassProgramVisitor();
|
||||||
|
try {
|
||||||
|
final FolderDataSourceDescriptor war3mpq = new FolderDataSourceDescriptor(
|
||||||
|
"E:\\Backups\\Warcraft\\Data\\127");
|
||||||
|
final FolderDataSourceDescriptor testingFolder = new FolderDataSourceDescriptor(
|
||||||
|
"E:\\Backups\\Warsmash\\Data");
|
||||||
|
final FolderDataSourceDescriptor currentFolder = new FolderDataSourceDescriptor(".");
|
||||||
|
final DataSource dataSource = new CompoundDataSourceDescriptor(
|
||||||
|
Arrays.<DataSourceDescriptor>asList(war3mpq, testingFolder, currentFolder)).createDataSource();
|
||||||
|
JassLexer lexer;
|
||||||
|
try {
|
||||||
|
lexer = new JassLexer(CharStreams.fromStream(dataSource.getResourceAsStream("Scripts\\common.j")));
|
||||||
|
}
|
||||||
|
catch (final IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
final JassParser parser = new JassParser(new CommonTokenStream(lexer));
|
||||||
|
parser.addErrorListener(new BaseErrorListener() {
|
||||||
|
@Override
|
||||||
|
public void syntaxError(final Recognizer<?, ?> recognizer, final Object offendingSymbol, final int line,
|
||||||
|
final int charPositionInLine, final String msg, final RecognitionException e) {
|
||||||
|
if (!REPORT_SYNTAX_ERRORS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String sourceName = recognizer.getInputStream().getSourceName();
|
||||||
|
if (!sourceName.isEmpty()) {
|
||||||
|
sourceName = String.format("%s:%d:%d: ", sourceName, line, charPositionInLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.err.println(sourceName + "line " + line + ":" + charPositionInLine + " " + msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
jassProgramVisitor.visit(parser.program());
|
||||||
|
}
|
||||||
|
catch (final Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
22
core/src/com/etheller/warsmash/parsers/jass/Tmpgen.java
Normal file
22
core/src/com/etheller/warsmash/parsers/jass/Tmpgen.java
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package com.etheller.warsmash.parsers.jass;
|
||||||
|
|
||||||
|
import java.util.Scanner;
|
||||||
|
|
||||||
|
public class Tmpgen {
|
||||||
|
|
||||||
|
public static void main(final String[] args) {
|
||||||
|
// final HandleJassType eventType = globals.registerHandleType("event");
|
||||||
|
|
||||||
|
final Scanner scanner = new Scanner(System.in);
|
||||||
|
while (scanner.hasNextLine()) {
|
||||||
|
final String line = scanner.nextLine();
|
||||||
|
if (line.startsWith("type ")) {
|
||||||
|
final String[] splitLine = line.split("\\s+");
|
||||||
|
System.out.println("final HandleJassType " + splitLine[1] + "Type = globals.registerHandleType(\""
|
||||||
|
+ splitLine[1] + "\");");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
29
core/src/com/etheller/warsmash/parsers/jass/Tmpgen2.java
Normal file
29
core/src/com/etheller/warsmash/parsers/jass/Tmpgen2.java
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package com.etheller.warsmash.parsers.jass;
|
||||||
|
|
||||||
|
import java.util.Scanner;
|
||||||
|
|
||||||
|
public class Tmpgen2 {
|
||||||
|
|
||||||
|
public static void main(final String[] args) {
|
||||||
|
// final HandleJassType eventType = globals.registerHandleType("event");
|
||||||
|
|
||||||
|
final Scanner scanner = new Scanner(System.in);
|
||||||
|
while (scanner.hasNextLine()) {
|
||||||
|
final String line = scanner.nextLine();
|
||||||
|
final String[] splitLine = line.trim().split("\\s+");
|
||||||
|
if (line.trim().startsWith("//")) {
|
||||||
|
System.out.println(line);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (splitLine.length > 3) {
|
||||||
|
System.out.println(splitLine[2] + ",");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
package com.etheller.warsmash.parsers.jass.scope;
|
||||||
|
|
||||||
|
import com.etheller.interpreter.ast.scope.TriggerExecutionScope;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
|
||||||
|
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayerJass;
|
||||||
|
|
||||||
|
public class CommonTriggerExecutionScope extends TriggerExecutionScope {
|
||||||
|
private final CUnit triggeringUnit;
|
||||||
|
private final CUnit filterUnit;
|
||||||
|
private final CUnit enumUnit;
|
||||||
|
private final CPlayerJass filterPlayer;
|
||||||
|
private final CPlayerJass enumPlayer;
|
||||||
|
|
||||||
|
public CommonTriggerExecutionScope(final TriggerExecutionScope parentScope, final CUnit triggeringUnit,
|
||||||
|
final CUnit filterUnit, final CUnit enumUnit, final CPlayerJass filterPlayer,
|
||||||
|
final CPlayerJass enumPlayer) {
|
||||||
|
super(parentScope.getTriggeringTrigger());
|
||||||
|
this.triggeringUnit = triggeringUnit;
|
||||||
|
this.filterUnit = filterUnit;
|
||||||
|
this.enumUnit = enumUnit;
|
||||||
|
this.filterPlayer = filterPlayer;
|
||||||
|
this.enumPlayer = enumPlayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CUnit getEnumUnit() {
|
||||||
|
return this.enumUnit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CUnit getTriggeringUnit() {
|
||||||
|
return this.triggeringUnit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CUnit getFilterUnit() {
|
||||||
|
return this.filterUnit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CPlayerJass getFilterPlayer() {
|
||||||
|
return this.filterPlayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CPlayerJass getEnumPlayer() {
|
||||||
|
return this.enumPlayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CommonTriggerExecutionScope filterScope(final TriggerExecutionScope parentScope,
|
||||||
|
final CUnit filterUnit) {
|
||||||
|
return new CommonTriggerExecutionScope(parentScope, null, filterUnit, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CommonTriggerExecutionScope enumScope(final TriggerExecutionScope parentScope, final CUnit enumUnit) {
|
||||||
|
return new CommonTriggerExecutionScope(parentScope, null, null, enumUnit, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CommonTriggerExecutionScope filterScope(final TriggerExecutionScope parentScope,
|
||||||
|
final CPlayerJass filterPlayer) {
|
||||||
|
return new CommonTriggerExecutionScope(parentScope, null, null, null, filterPlayer, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CommonTriggerExecutionScope enumScope(final TriggerExecutionScope parentScope,
|
||||||
|
final CPlayerJass enumPlayer) {
|
||||||
|
return new CommonTriggerExecutionScope(parentScope, null, null, null, null, enumPlayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package com.etheller.warsmash.parsers.jass.triggers;
|
||||||
|
|
||||||
|
import com.etheller.interpreter.ast.scope.GlobalScope;
|
||||||
|
import com.etheller.interpreter.ast.scope.TriggerExecutionScope;
|
||||||
|
import com.etheller.interpreter.ast.scope.trigger.TriggerBooleanExpression;
|
||||||
|
|
||||||
|
public class BoolExprAnd implements TriggerBooleanExpression {
|
||||||
|
private final TriggerBooleanExpression operandA;
|
||||||
|
private final TriggerBooleanExpression operandB;
|
||||||
|
|
||||||
|
public BoolExprAnd(final TriggerBooleanExpression operandA, final TriggerBooleanExpression operandB) {
|
||||||
|
this.operandA = operandA;
|
||||||
|
this.operandB = operandB;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean evaluate(final GlobalScope globalScope, final TriggerExecutionScope triggerScope) {
|
||||||
|
return this.operandA.evaluate(globalScope, triggerScope) && this.operandB.evaluate(globalScope, triggerScope);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package com.etheller.warsmash.parsers.jass.triggers;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import com.etheller.interpreter.ast.function.JassFunction;
|
||||||
|
import com.etheller.interpreter.ast.scope.GlobalScope;
|
||||||
|
import com.etheller.interpreter.ast.scope.TriggerExecutionScope;
|
||||||
|
import com.etheller.interpreter.ast.scope.trigger.TriggerBooleanExpression;
|
||||||
|
import com.etheller.interpreter.ast.value.JassValue;
|
||||||
|
import com.etheller.interpreter.ast.value.visitor.BooleanJassValueVisitor;
|
||||||
|
|
||||||
|
public class BoolExprCondition implements TriggerBooleanExpression {
|
||||||
|
private final JassFunction takesNothingReturnsBooleanFunction;
|
||||||
|
|
||||||
|
public BoolExprCondition(final JassFunction returnsBooleanFunction) {
|
||||||
|
this.takesNothingReturnsBooleanFunction = returnsBooleanFunction;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean evaluate(final GlobalScope globalScope, final TriggerExecutionScope triggerScope) {
|
||||||
|
final JassValue booleanJassReturnValue = this.takesNothingReturnsBooleanFunction.call(Collections.EMPTY_LIST,
|
||||||
|
globalScope, triggerScope);
|
||||||
|
final Boolean booleanReturnValue = booleanJassReturnValue.visit(BooleanJassValueVisitor.getInstance());
|
||||||
|
return booleanReturnValue.booleanValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package com.etheller.warsmash.parsers.jass.triggers;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import com.etheller.interpreter.ast.function.JassFunction;
|
||||||
|
import com.etheller.interpreter.ast.scope.GlobalScope;
|
||||||
|
import com.etheller.interpreter.ast.scope.TriggerExecutionScope;
|
||||||
|
import com.etheller.interpreter.ast.scope.trigger.TriggerBooleanExpression;
|
||||||
|
import com.etheller.interpreter.ast.value.JassValue;
|
||||||
|
import com.etheller.interpreter.ast.value.visitor.BooleanJassValueVisitor;
|
||||||
|
|
||||||
|
public class BoolExprFilter implements TriggerBooleanExpression {
|
||||||
|
private final JassFunction takesNothingReturnsBooleanFunction;
|
||||||
|
|
||||||
|
public BoolExprFilter(final JassFunction returnsBooleanFunction) {
|
||||||
|
this.takesNothingReturnsBooleanFunction = returnsBooleanFunction;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean evaluate(final GlobalScope globalScope, final TriggerExecutionScope triggerScope) {
|
||||||
|
final JassValue booleanJassReturnValue = this.takesNothingReturnsBooleanFunction.call(Collections.EMPTY_LIST,
|
||||||
|
globalScope, triggerScope);
|
||||||
|
final Boolean booleanReturnValue = booleanJassReturnValue.visit(BooleanJassValueVisitor.getInstance());
|
||||||
|
return booleanReturnValue.booleanValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.etheller.warsmash.parsers.jass.triggers;
|
||||||
|
|
||||||
|
import com.etheller.interpreter.ast.scope.GlobalScope;
|
||||||
|
import com.etheller.interpreter.ast.scope.TriggerExecutionScope;
|
||||||
|
import com.etheller.interpreter.ast.scope.trigger.TriggerBooleanExpression;
|
||||||
|
|
||||||
|
public class BoolExprNot implements TriggerBooleanExpression {
|
||||||
|
private final TriggerBooleanExpression operand;
|
||||||
|
|
||||||
|
public BoolExprNot(final TriggerBooleanExpression operand) {
|
||||||
|
this.operand = operand;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean evaluate(final GlobalScope globalScope, final TriggerExecutionScope triggerScope) {
|
||||||
|
return this.operand.evaluate(globalScope, triggerScope);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package com.etheller.warsmash.parsers.jass.triggers;
|
||||||
|
|
||||||
|
import com.etheller.interpreter.ast.scope.GlobalScope;
|
||||||
|
import com.etheller.interpreter.ast.scope.TriggerExecutionScope;
|
||||||
|
import com.etheller.interpreter.ast.scope.trigger.TriggerBooleanExpression;
|
||||||
|
|
||||||
|
public class BoolExprOr implements TriggerBooleanExpression {
|
||||||
|
private final TriggerBooleanExpression operandA;
|
||||||
|
private final TriggerBooleanExpression operandB;
|
||||||
|
|
||||||
|
public BoolExprOr(final TriggerBooleanExpression operandA, final TriggerBooleanExpression operandB) {
|
||||||
|
this.operandA = operandA;
|
||||||
|
this.operandB = operandB;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean evaluate(final GlobalScope globalScope, final TriggerExecutionScope triggerScope) {
|
||||||
|
return this.operandA.evaluate(globalScope, triggerScope) || this.operandB.evaluate(globalScope, triggerScope);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package com.etheller.warsmash.parsers.jass.triggers;
|
||||||
|
|
||||||
|
import com.etheller.interpreter.ast.function.JassFunction;
|
||||||
|
import com.etheller.interpreter.ast.scope.trigger.Trigger;
|
||||||
|
|
||||||
|
public class TriggerAction {
|
||||||
|
private final Trigger trigger;
|
||||||
|
private final JassFunction actionFunc;
|
||||||
|
private final int actionIndex;
|
||||||
|
|
||||||
|
public TriggerAction(final Trigger trigger, final JassFunction actionFunc, final int actionIndex) {
|
||||||
|
this.trigger = trigger;
|
||||||
|
this.actionFunc = actionFunc;
|
||||||
|
this.actionIndex = actionIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Trigger getTrigger() {
|
||||||
|
return this.trigger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JassFunction getActionFunc() {
|
||||||
|
return this.actionFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getActionIndex() {
|
||||||
|
return this.actionIndex;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package com.etheller.warsmash.parsers.jass.triggers;
|
||||||
|
|
||||||
|
import com.etheller.interpreter.ast.scope.trigger.Trigger;
|
||||||
|
import com.etheller.interpreter.ast.scope.trigger.TriggerBooleanExpression;
|
||||||
|
|
||||||
|
public class TriggerCondition {
|
||||||
|
private final TriggerBooleanExpression boolexpr;
|
||||||
|
private final Trigger trigger;
|
||||||
|
private final int conditionIndex;
|
||||||
|
|
||||||
|
public TriggerCondition(final TriggerBooleanExpression boolexpr, final Trigger trigger, final int index) {
|
||||||
|
this.boolexpr = boolexpr;
|
||||||
|
this.trigger = trigger;
|
||||||
|
this.conditionIndex = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TriggerBooleanExpression getBoolexpr() {
|
||||||
|
return this.boolexpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Trigger getTrigger() {
|
||||||
|
return this.trigger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getConditionIndex() {
|
||||||
|
return this.conditionIndex;
|
||||||
|
}
|
||||||
|
}
|
27
core/src/com/etheller/warsmash/parsers/terrain/Corner.java
Normal file
27
core/src/com/etheller/warsmash/parsers/terrain/Corner.java
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package com.etheller.warsmash.parsers.terrain;
|
||||||
|
|
||||||
|
public class Corner {
|
||||||
|
boolean mapEdge;
|
||||||
|
|
||||||
|
int groundTexture;
|
||||||
|
float height;
|
||||||
|
float waterHeight;
|
||||||
|
boolean ramp;
|
||||||
|
boolean blight;
|
||||||
|
boolean water;
|
||||||
|
boolean boundary;
|
||||||
|
boolean cliff;
|
||||||
|
boolean romp;
|
||||||
|
int groundVariation;
|
||||||
|
int cliffVariation;
|
||||||
|
int cliffTexture;
|
||||||
|
int layerHeight;
|
||||||
|
|
||||||
|
public float finalGroundHeight() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float finalWaterHeight() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
13
core/src/com/etheller/warsmash/parsers/terrain/Terrain.java
Normal file
13
core/src/com/etheller/warsmash/parsers/terrain/Terrain.java
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package com.etheller.warsmash.parsers.terrain;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.utils.FloatArray;
|
||||||
|
|
||||||
|
public class Terrain {
|
||||||
|
private FloatArray groundHeights;
|
||||||
|
private FloatArray groundCornerHeights;
|
||||||
|
|
||||||
|
private FloatArray waterHeights;
|
||||||
|
|
||||||
|
public Terrain() {
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package com.etheller.warsmash.parsers.terrain;
|
||||||
|
|
||||||
|
public class TilePathing {
|
||||||
|
boolean unwalkable = false;
|
||||||
|
boolean unflyable = false;
|
||||||
|
boolean unbuildable = false;
|
||||||
|
|
||||||
|
public byte mask() {
|
||||||
|
byte mask = 0;
|
||||||
|
mask |= this.unwalkable ? 0b00000010 : 0;
|
||||||
|
mask |= this.unflyable ? 0b00000100 : 0;
|
||||||
|
mask |= this.unbuildable ? 0b00001000 : 0;
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
}
|
147
core/src/com/etheller/warsmash/parsers/w3x/War3Map.java
Normal file
147
core/src/com/etheller/warsmash/parsers/w3x/War3Map.java
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
package com.etheller.warsmash.parsers.w3x;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.channels.SeekableByteChannel;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import org.apache.commons.compress.utils.IOUtils;
|
||||||
|
import org.apache.commons.compress.utils.SeekableInMemoryByteChannel;
|
||||||
|
|
||||||
|
import com.etheller.warsmash.datasources.CompoundDataSource;
|
||||||
|
import com.etheller.warsmash.datasources.DataSource;
|
||||||
|
import com.etheller.warsmash.datasources.MpqDataSource;
|
||||||
|
import com.etheller.warsmash.parsers.w3x.doo.War3MapDoo;
|
||||||
|
import com.etheller.warsmash.parsers.w3x.objectdata.Warcraft3MapObjectData;
|
||||||
|
import com.etheller.warsmash.parsers.w3x.unitsdoo.War3MapUnitsDoo;
|
||||||
|
import com.etheller.warsmash.parsers.w3x.w3e.War3MapW3e;
|
||||||
|
import com.etheller.warsmash.parsers.w3x.w3i.War3MapW3i;
|
||||||
|
import com.etheller.warsmash.parsers.w3x.wpm.War3MapWpm;
|
||||||
|
import com.etheller.warsmash.units.custom.WTS;
|
||||||
|
import com.google.common.io.LittleEndianDataInputStream;
|
||||||
|
|
||||||
|
import mpq.MPQArchive;
|
||||||
|
import mpq.MPQException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Warcraft 3 map (W3X and W3M).
|
||||||
|
*/
|
||||||
|
public class War3Map implements DataSource {
|
||||||
|
|
||||||
|
private CompoundDataSource dataSource;
|
||||||
|
private MpqDataSource internalMpqContentsDataSource;
|
||||||
|
|
||||||
|
public War3Map(final DataSource dataSource, final String mapFileName) {
|
||||||
|
try {
|
||||||
|
// Slightly complex. Here's the theory:
|
||||||
|
// 1.) Copy map into RAM
|
||||||
|
// 2.) Setup a Data Source that will read assets
|
||||||
|
// from either the map or the game, giving the map priority.
|
||||||
|
SeekableByteChannel sbc;
|
||||||
|
try (InputStream mapStream = dataSource.getResourceAsStream(mapFileName)) {
|
||||||
|
final byte[] mapData = IOUtils.toByteArray(mapStream);
|
||||||
|
sbc = new SeekableInMemoryByteChannel(mapData);
|
||||||
|
this.internalMpqContentsDataSource = new MpqDataSource(new MPQArchive(sbc), sbc);
|
||||||
|
this.dataSource = new CompoundDataSource(Arrays.asList(dataSource, this.internalMpqContentsDataSource));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (final IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
catch (final MPQException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public War3MapW3i readMapInformation() throws IOException {
|
||||||
|
War3MapW3i mapInfo;
|
||||||
|
try (LittleEndianDataInputStream stream = new LittleEndianDataInputStream(
|
||||||
|
this.dataSource.getResourceAsStream("war3map.w3i"))) {
|
||||||
|
mapInfo = new War3MapW3i(stream);
|
||||||
|
}
|
||||||
|
return mapInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public War3MapW3e readEnvironment() throws IOException {
|
||||||
|
War3MapW3e environment;
|
||||||
|
try (LittleEndianDataInputStream stream = new LittleEndianDataInputStream(
|
||||||
|
this.dataSource.getResourceAsStream("war3map.w3e"))) {
|
||||||
|
environment = new War3MapW3e(stream);
|
||||||
|
}
|
||||||
|
return environment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public War3MapWpm readPathing() throws IOException {
|
||||||
|
War3MapWpm pathingMap;
|
||||||
|
try (LittleEndianDataInputStream stream = new LittleEndianDataInputStream(
|
||||||
|
this.dataSource.getResourceAsStream("war3map.wpm"))) {
|
||||||
|
pathingMap = new War3MapWpm(stream);
|
||||||
|
}
|
||||||
|
return pathingMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public War3MapDoo readDoodads() throws IOException {
|
||||||
|
War3MapDoo doodadsFile;
|
||||||
|
try (LittleEndianDataInputStream stream = new LittleEndianDataInputStream(
|
||||||
|
this.dataSource.getResourceAsStream("war3map.doo"))) {
|
||||||
|
doodadsFile = new War3MapDoo(stream);
|
||||||
|
}
|
||||||
|
return doodadsFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public War3MapUnitsDoo readUnits() throws IOException {
|
||||||
|
War3MapUnitsDoo unitsFile;
|
||||||
|
try (LittleEndianDataInputStream stream = new LittleEndianDataInputStream(
|
||||||
|
this.dataSource.getResourceAsStream("war3mapUnits.doo"))) {
|
||||||
|
unitsFile = new War3MapUnitsDoo(stream);
|
||||||
|
}
|
||||||
|
return unitsFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Warcraft3MapObjectData readModifications() throws IOException {
|
||||||
|
final Warcraft3MapObjectData changes = Warcraft3MapObjectData.load(this.dataSource, true);
|
||||||
|
return changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Warcraft3MapObjectData readModifications(final WTS preloadedWTS) throws IOException {
|
||||||
|
final Warcraft3MapObjectData changes = Warcraft3MapObjectData.load(this.dataSource, true, preloadedWTS);
|
||||||
|
return changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream getResourceAsStream(final String filepath) throws IOException {
|
||||||
|
return this.dataSource.getResourceAsStream(filepath);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File getFile(final String filepath) throws IOException {
|
||||||
|
return this.dataSource.getFile(filepath);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean has(final String filepath) {
|
||||||
|
return this.dataSource.has(filepath);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuffer read(final String path) throws IOException {
|
||||||
|
return this.dataSource.read(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<String> getListfile() {
|
||||||
|
return this.internalMpqContentsDataSource.getListfile();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
this.dataSource.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompoundDataSource getCompoundDataSource() {
|
||||||
|
return this.dataSource;
|
||||||
|
}
|
||||||
|
}
|
157
core/src/com/etheller/warsmash/parsers/w3x/doo/Doodad.java
Normal file
157
core/src/com/etheller/warsmash/parsers/w3x/doo/Doodad.java
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
package com.etheller.warsmash.parsers.w3x.doo;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.etheller.warsmash.util.ParseUtils;
|
||||||
|
import com.etheller.warsmash.util.War3ID;
|
||||||
|
import com.google.common.io.LittleEndianDataInputStream;
|
||||||
|
import com.google.common.io.LittleEndianDataOutputStream;
|
||||||
|
|
||||||
|
public class Doodad {
|
||||||
|
private War3ID id;
|
||||||
|
private int variation;
|
||||||
|
private final float[] location = new float[3];
|
||||||
|
private float angle;
|
||||||
|
private final float[] scale = { 1f, 1f, 1f };
|
||||||
|
private short flags; // short to store unsigned byte, java problem
|
||||||
|
private short life; // short to store unsigned byte, java problem
|
||||||
|
private long itemTable = -1; // long to store unsigned int32, java problem
|
||||||
|
private final List<RandomItemSet> itemSets = new ArrayList<>();
|
||||||
|
private int editorId;
|
||||||
|
private final short[] u1 = new short[8]; // short to store unsigned byte, java problem
|
||||||
|
|
||||||
|
public void load(final LittleEndianDataInputStream stream, final int version) throws IOException {
|
||||||
|
this.id = ParseUtils.readWar3ID(stream);
|
||||||
|
this.variation = stream.readInt();
|
||||||
|
ParseUtils.readFloatArray(stream, this.location);
|
||||||
|
this.angle = stream.readFloat();
|
||||||
|
ParseUtils.readFloatArray(stream, this.scale);
|
||||||
|
this.flags = ParseUtils.readUInt8(stream);
|
||||||
|
this.life = ParseUtils.readUInt8(stream);
|
||||||
|
|
||||||
|
if (version > 7) {
|
||||||
|
this.itemTable = ParseUtils.readUInt32(stream);
|
||||||
|
|
||||||
|
for (long i = 0, l = ParseUtils.readUInt32(stream); i < l; i++) {
|
||||||
|
final RandomItemSet itemSet = new RandomItemSet();
|
||||||
|
|
||||||
|
itemSet.load(stream);
|
||||||
|
|
||||||
|
this.itemSets.add(itemSet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.editorId = stream.readInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save(final LittleEndianDataOutputStream stream, final int version) throws IOException {
|
||||||
|
ParseUtils.writeWar3ID(stream, this.id);
|
||||||
|
;
|
||||||
|
stream.writeInt(this.variation);
|
||||||
|
ParseUtils.writeFloatArray(stream, this.location);
|
||||||
|
stream.writeFloat(this.angle);
|
||||||
|
ParseUtils.writeFloatArray(stream, this.scale);
|
||||||
|
ParseUtils.writeUInt8(stream, this.flags);
|
||||||
|
ParseUtils.writeUInt8(stream, this.life);
|
||||||
|
|
||||||
|
if (version > 7) {
|
||||||
|
ParseUtils.writeUInt32(stream, this.itemTable);
|
||||||
|
ParseUtils.writeUInt32(stream, this.itemSets.size());
|
||||||
|
|
||||||
|
for (final RandomItemSet itemSet : this.itemSets) {
|
||||||
|
itemSet.save(stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.writeInt(this.editorId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getByteLength(final int version) {
|
||||||
|
int size = 42;
|
||||||
|
|
||||||
|
if (version > 7) {
|
||||||
|
size += 8;
|
||||||
|
|
||||||
|
for (final RandomItemSet itemSet : this.itemSets) {
|
||||||
|
size += itemSet.getByteLength();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public War3ID getId() {
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(final War3ID id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVariation() {
|
||||||
|
return this.variation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVariation(final int variation) {
|
||||||
|
this.variation = variation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getAngle() {
|
||||||
|
return this.angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAngle(final float angle) {
|
||||||
|
this.angle = angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short getFlags() {
|
||||||
|
return this.flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFlags(final short flags) {
|
||||||
|
this.flags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short getLife() {
|
||||||
|
return this.life;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLife(final short life) {
|
||||||
|
this.life = life;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getItemTable() {
|
||||||
|
return this.itemTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItemTable(final long itemTable) {
|
||||||
|
this.itemTable = itemTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getEditorId() {
|
||||||
|
return this.editorId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEditorId(final int editorId) {
|
||||||
|
this.editorId = editorId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float[] getLocation() {
|
||||||
|
return this.location;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float[] getScale() {
|
||||||
|
return this.scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<RandomItemSet> getItemSets() {
|
||||||
|
return this.itemSets;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short[] getU1() {
|
||||||
|
return this.u1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package com.etheller.warsmash.parsers.w3x.doo;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import com.etheller.warsmash.util.ParseUtils;
|
||||||
|
import com.etheller.warsmash.util.War3ID;
|
||||||
|
import com.google.common.io.LittleEndianDataInputStream;
|
||||||
|
import com.google.common.io.LittleEndianDataOutputStream;
|
||||||
|
|
||||||
|
public class RandomItem {
|
||||||
|
private War3ID id;
|
||||||
|
private int chance;
|
||||||
|
|
||||||
|
public void load(final LittleEndianDataInputStream stream) throws IOException {
|
||||||
|
this.id = ParseUtils.readWar3ID(stream);
|
||||||
|
this.chance = stream.readInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save(final LittleEndianDataOutputStream stream) throws IOException {
|
||||||
|
ParseUtils.writeWar3ID(stream, this.id);
|
||||||
|
stream.writeInt(this.chance);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package com.etheller.warsmash.parsers.w3x.doo;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.etheller.warsmash.util.ParseUtils;
|
||||||
|
import com.google.common.io.LittleEndianDataInputStream;
|
||||||
|
import com.google.common.io.LittleEndianDataOutputStream;
|
||||||
|
|
||||||
|
public class RandomItemSet {
|
||||||
|
private final List<RandomItem> items = new ArrayList<>();
|
||||||
|
|
||||||
|
public void load(final LittleEndianDataInputStream stream) throws IOException {
|
||||||
|
for (long i = 0, l = ParseUtils.readUInt32(stream); i < l; i++) {
|
||||||
|
final RandomItem item = new RandomItem();
|
||||||
|
|
||||||
|
item.load(stream);
|
||||||
|
|
||||||
|
this.items.add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save(final LittleEndianDataOutputStream stream) throws IOException {
|
||||||
|
ParseUtils.writeUInt32(stream, this.items.size());
|
||||||
|
for (final RandomItem item : this.items) {
|
||||||
|
item.save(stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getByteLength() {
|
||||||
|
return 4 + (this.items.size() * 8);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
package com.etheller.warsmash.parsers.w3x.doo;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import com.etheller.warsmash.util.ParseUtils;
|
||||||
|
import com.etheller.warsmash.util.War3ID;
|
||||||
|
import com.google.common.io.LittleEndianDataInputStream;
|
||||||
|
import com.google.common.io.LittleEndianDataOutputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A terrain doodad.
|
||||||
|
*
|
||||||
|
* This type of doodad works much like cliffs. It uses the height of the
|
||||||
|
* terrain, and gets affected by the ground heightmap. It cannot be manipulated
|
||||||
|
* in any way in the World Editor once placed. Indeed, the only way to change it
|
||||||
|
* is to remove it by changing cliffs around it.
|
||||||
|
*/
|
||||||
|
public class TerrainDoodad {
|
||||||
|
private War3ID id;
|
||||||
|
private long u1;
|
||||||
|
private final long[] location = new long[2];
|
||||||
|
|
||||||
|
public void load(final LittleEndianDataInputStream stream, final int version) throws IOException {
|
||||||
|
this.id = ParseUtils.readWar3ID(stream);
|
||||||
|
this.u1 = ParseUtils.readUInt32(stream);
|
||||||
|
ParseUtils.readUInt32Array(stream, this.location);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save(final LittleEndianDataOutputStream stream, final int version) throws IOException {
|
||||||
|
ParseUtils.writeWar3ID(stream, this.id);
|
||||||
|
ParseUtils.writeUInt32(stream, this.u1);
|
||||||
|
ParseUtils.writeUInt32Array(stream, this.location);
|
||||||
|
}
|
||||||
|
|
||||||
|
public War3ID getId() {
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getU1() {
|
||||||
|
return this.u1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long[] getLocation() {
|
||||||
|
return this.location;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(final War3ID id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setU1(final long u1) {
|
||||||
|
this.u1 = u1;
|
||||||
|
}
|
||||||
|
}
|
108
core/src/com/etheller/warsmash/parsers/w3x/doo/War3MapDoo.java
Normal file
108
core/src/com/etheller/warsmash/parsers/w3x/doo/War3MapDoo.java
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
package com.etheller.warsmash.parsers.w3x.doo;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.etheller.warsmash.util.ParseUtils;
|
||||||
|
import com.etheller.warsmash.util.War3ID;
|
||||||
|
import com.google.common.io.LittleEndianDataInputStream;
|
||||||
|
import com.google.common.io.LittleEndianDataOutputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* war3map.doo - the doodad and destructible file.
|
||||||
|
*/
|
||||||
|
public class War3MapDoo {
|
||||||
|
private static final War3ID MAGIC_NUMBER = War3ID.fromString("W3do");
|
||||||
|
private int version = 0;
|
||||||
|
private final short[] u1 = new short[4];
|
||||||
|
private final List<Doodad> doodads = new ArrayList<>();
|
||||||
|
private final short[] u2 = new short[4];
|
||||||
|
private final List<TerrainDoodad> terrainDoodads = new ArrayList<>();
|
||||||
|
|
||||||
|
public War3MapDoo(final LittleEndianDataInputStream stream) throws IOException {
|
||||||
|
if (stream != null) {
|
||||||
|
this.load(stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean load(final LittleEndianDataInputStream stream) throws IOException {
|
||||||
|
final War3ID firstId = ParseUtils.readWar3ID(stream);
|
||||||
|
if (!MAGIC_NUMBER.equals(firstId)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.version = stream.readInt();
|
||||||
|
ParseUtils.readUInt8Array(stream, this.u1);
|
||||||
|
|
||||||
|
for (int i = 0, l = stream.readInt(); i < l; i++) {
|
||||||
|
final Doodad doodad = new Doodad();
|
||||||
|
|
||||||
|
doodad.load(stream, this.version);
|
||||||
|
|
||||||
|
this.doodads.add(doodad);
|
||||||
|
}
|
||||||
|
|
||||||
|
ParseUtils.readUInt8Array(stream, this.u2);
|
||||||
|
|
||||||
|
for (int i = 0, l = stream.readInt(); i < l; i++) {
|
||||||
|
final TerrainDoodad terrainDoodad = new TerrainDoodad();
|
||||||
|
|
||||||
|
terrainDoodad.load(stream, this.version);
|
||||||
|
|
||||||
|
this.terrainDoodads.add(terrainDoodad);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save(final LittleEndianDataOutputStream stream) throws IOException {
|
||||||
|
|
||||||
|
ParseUtils.writeWar3ID(stream, MAGIC_NUMBER);
|
||||||
|
stream.writeInt(this.version);
|
||||||
|
ParseUtils.writeUInt8Array(stream, this.u1);
|
||||||
|
ParseUtils.writeUInt32(stream, this.doodads.size());
|
||||||
|
|
||||||
|
for (final Doodad doodad : this.doodads) {
|
||||||
|
doodad.save(stream, this.version);
|
||||||
|
}
|
||||||
|
|
||||||
|
ParseUtils.writeUInt8Array(stream, this.u2);
|
||||||
|
ParseUtils.writeUInt32(stream, this.terrainDoodads.size());
|
||||||
|
|
||||||
|
for (final TerrainDoodad terrainDoodad : this.terrainDoodads) {
|
||||||
|
terrainDoodad.save(stream, this.version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getByteLength() {
|
||||||
|
int size = 24 + (this.terrainDoodads.size() * 16);
|
||||||
|
|
||||||
|
for (final Doodad doodad : this.doodads) {
|
||||||
|
size += doodad.getByteLength(this.version);
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVersion() {
|
||||||
|
return this.version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short[] getU1() {
|
||||||
|
return this.u1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Doodad> getDoodads() {
|
||||||
|
return this.doodads;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short[] getU2() {
|
||||||
|
return this.u2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<TerrainDoodad> getTerrainDoodads() {
|
||||||
|
return this.terrainDoodads;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,98 @@
|
|||||||
|
package com.etheller.warsmash.parsers.w3x.objectdata;
|
||||||
|
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import com.etheller.warsmash.datasources.CompoundDataSourceDescriptor;
|
||||||
|
import com.etheller.warsmash.datasources.FolderDataSourceDescriptor;
|
||||||
|
import com.etheller.warsmash.datasources.MpqDataSourceDescriptor;
|
||||||
|
import com.etheller.warsmash.units.GameObject;
|
||||||
|
import com.etheller.warsmash.units.ObjectData;
|
||||||
|
import com.etheller.warsmash.units.manager.MutableObjectData.MutableGameObject;
|
||||||
|
import com.etheller.warsmash.util.War3ID;
|
||||||
|
import com.google.common.io.LittleEndianDataOutputStream;
|
||||||
|
|
||||||
|
public class MakeMeTFTBeROC {
|
||||||
|
|
||||||
|
public static void main(final String[] args) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
final MpqDataSourceDescriptor reignOfChaosData = new MpqDataSourceDescriptor(
|
||||||
|
"E:\\Games\\Warcraft III Patch 1.14\\war3.mpq");
|
||||||
|
final Warcraft3MapObjectData reignOfChaosUnitData = Warcraft3MapObjectData
|
||||||
|
.load(reignOfChaosData.createDataSource(), true);
|
||||||
|
|
||||||
|
final FolderDataSourceDescriptor tftDesc1 = new FolderDataSourceDescriptor(
|
||||||
|
"D:\\NEEDS_ORGANIZING\\Reforged Beta 13991\\war3.w3mod");
|
||||||
|
final FolderDataSourceDescriptor tftDesc2 = new FolderDataSourceDescriptor(
|
||||||
|
"D:\\NEEDS_ORGANIZING\\Reforged Beta 13991\\war3.w3mod\\_balance\\custom_v1.w3mod");
|
||||||
|
final FolderDataSourceDescriptor tftDesc3 = new FolderDataSourceDescriptor(
|
||||||
|
"D:\\NEEDS_ORGANIZING\\Reforged Beta 13991\\war3.w3mod\\_locales\\enus.w3mod");
|
||||||
|
final CompoundDataSourceDescriptor frozenThroneData = new CompoundDataSourceDescriptor(
|
||||||
|
Arrays.asList(tftDesc1, tftDesc2, tftDesc3));
|
||||||
|
|
||||||
|
final Warcraft3MapObjectData frozenThroneUnitData = Warcraft3MapObjectData
|
||||||
|
.load(frozenThroneData.createDataSource(), true);
|
||||||
|
for (final War3ID unitId : reignOfChaosUnitData.getUnits().keySet()) {
|
||||||
|
final MutableGameObject reignOfChaosUnit = reignOfChaosUnitData.getUnits().get(unitId);
|
||||||
|
final MutableGameObject frozenThroneEquivalentUnit = frozenThroneUnitData.getUnits().get(unitId);
|
||||||
|
if (frozenThroneEquivalentUnit == null) {
|
||||||
|
System.err.println("No TFT equivalent for: " + reignOfChaosUnit.getName());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final ObjectData metaDataSlk = reignOfChaosUnitData.getUnits().getSourceSLKMetaData();
|
||||||
|
for (final String fieldTypeId : metaDataSlk.keySet()) {
|
||||||
|
final War3ID fieldTypeIdCode = War3ID.fromString(fieldTypeId);
|
||||||
|
final GameObject unitFieldInformation = metaDataSlk.get(fieldTypeId);
|
||||||
|
if (unitFieldInformation.getFieldValue("useItem") == 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final String fieldType = unitFieldInformation.getField("type");
|
||||||
|
switch (fieldType) {
|
||||||
|
case "int":
|
||||||
|
frozenThroneEquivalentUnit.setField(fieldTypeIdCode, 0,
|
||||||
|
reignOfChaosUnit.getFieldAsInteger(fieldTypeIdCode, 0));
|
||||||
|
break;
|
||||||
|
case "real":
|
||||||
|
case "unreal":
|
||||||
|
frozenThroneEquivalentUnit.setField(fieldTypeIdCode, 0,
|
||||||
|
reignOfChaosUnit.getFieldAsFloat(fieldTypeIdCode, 0));
|
||||||
|
break;
|
||||||
|
case "bool":
|
||||||
|
frozenThroneEquivalentUnit.setField(fieldTypeIdCode, 0,
|
||||||
|
reignOfChaosUnit.getFieldAsBoolean(fieldTypeIdCode, 0));
|
||||||
|
break;
|
||||||
|
case "string":
|
||||||
|
case "abilityList":
|
||||||
|
case "stringList":
|
||||||
|
case "soundLabel":
|
||||||
|
case "unitList":
|
||||||
|
case "itemList":
|
||||||
|
case "techList":
|
||||||
|
case "intList":
|
||||||
|
case "model":
|
||||||
|
case "char":
|
||||||
|
case "icon":
|
||||||
|
frozenThroneEquivalentUnit.setField(fieldTypeIdCode, 0,
|
||||||
|
reignOfChaosUnit.getFieldAsString(fieldTypeIdCode, 0));
|
||||||
|
break;
|
||||||
|
default: // treat as string
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try (LittleEndianDataOutputStream outputStream = new LittleEndianDataOutputStream(
|
||||||
|
new FileOutputStream("C:\\Users\\micro\\OneDrive\\Documents\\Warcraft III\\Data\\roc.w3u"))) {
|
||||||
|
frozenThroneUnitData.getUnits().getEditorData().save(outputStream, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (final IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,184 @@
|
|||||||
|
package com.etheller.warsmash.parsers.w3x.objectdata;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.etheller.warsmash.datasources.DataSource;
|
||||||
|
import com.etheller.warsmash.units.DataTable;
|
||||||
|
import com.etheller.warsmash.units.StandardObjectData;
|
||||||
|
import com.etheller.warsmash.units.StandardObjectData.WarcraftData;
|
||||||
|
import com.etheller.warsmash.units.custom.WTS;
|
||||||
|
import com.etheller.warsmash.units.custom.WTSFile;
|
||||||
|
import com.etheller.warsmash.units.custom.War3ObjectDataChangeset;
|
||||||
|
import com.etheller.warsmash.units.manager.MutableObjectData;
|
||||||
|
import com.etheller.warsmash.units.manager.MutableObjectData.WorldEditorDataType;
|
||||||
|
import com.etheller.warsmash.util.WorldEditStrings;
|
||||||
|
import com.google.common.io.LittleEndianDataInputStream;
|
||||||
|
|
||||||
|
public final class Warcraft3MapObjectData {
|
||||||
|
private final MutableObjectData units;
|
||||||
|
private final MutableObjectData items;
|
||||||
|
private final MutableObjectData destructibles;
|
||||||
|
private final MutableObjectData doodads;
|
||||||
|
private final MutableObjectData abilities;
|
||||||
|
private final MutableObjectData buffs;
|
||||||
|
private final MutableObjectData upgrades;
|
||||||
|
private final List<MutableObjectData> datas;
|
||||||
|
private transient Map<WorldEditorDataType, MutableObjectData> typeToData = new HashMap<>();
|
||||||
|
private final WTS wts;
|
||||||
|
|
||||||
|
public Warcraft3MapObjectData(final MutableObjectData units, final MutableObjectData items,
|
||||||
|
final MutableObjectData destructibles, final MutableObjectData doodads, final MutableObjectData abilities,
|
||||||
|
final MutableObjectData buffs, final MutableObjectData upgrades, final WTS wts) {
|
||||||
|
this.units = units;
|
||||||
|
this.items = items;
|
||||||
|
this.destructibles = destructibles;
|
||||||
|
this.doodads = doodads;
|
||||||
|
this.abilities = abilities;
|
||||||
|
this.buffs = buffs;
|
||||||
|
this.upgrades = upgrades;
|
||||||
|
this.datas = new ArrayList<>();
|
||||||
|
this.datas.add(units);
|
||||||
|
this.datas.add(items);
|
||||||
|
this.datas.add(destructibles);
|
||||||
|
this.datas.add(doodads);
|
||||||
|
this.datas.add(abilities);
|
||||||
|
this.datas.add(buffs);
|
||||||
|
this.datas.add(upgrades);
|
||||||
|
for (final MutableObjectData data : this.datas) {
|
||||||
|
this.typeToData.put(data.getWorldEditorDataType(), data);
|
||||||
|
}
|
||||||
|
this.wts = wts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MutableObjectData getDataByType(final WorldEditorDataType type) {
|
||||||
|
return this.typeToData.get(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MutableObjectData getUnits() {
|
||||||
|
return this.units;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MutableObjectData getItems() {
|
||||||
|
return this.items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MutableObjectData getDestructibles() {
|
||||||
|
return this.destructibles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MutableObjectData getDoodads() {
|
||||||
|
return this.doodads;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MutableObjectData getAbilities() {
|
||||||
|
return this.abilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MutableObjectData getBuffs() {
|
||||||
|
return this.buffs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MutableObjectData getUpgrades() {
|
||||||
|
return this.upgrades;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<MutableObjectData> getDatas() {
|
||||||
|
return this.datas;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WTS getWts() {
|
||||||
|
return this.wts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WTS loadWTS(final DataSource dataSource) throws IOException {
|
||||||
|
final WTS wts = dataSource.has("war3map.wts") ? new WTSFile(dataSource.getResourceAsStream("war3map.wts"))
|
||||||
|
: WTS.DO_NOTHING;
|
||||||
|
return wts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Warcraft3MapObjectData load(final DataSource dataSource, final boolean inlineWTS) throws IOException {
|
||||||
|
final WTS wts = loadWTS(dataSource);
|
||||||
|
return load(dataSource, inlineWTS, wts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Warcraft3MapObjectData load(final DataSource dataSource, final boolean inlineWTS, final WTS wts)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
|
final StandardObjectData standardObjectData = new StandardObjectData(dataSource);
|
||||||
|
final WarcraftData standardUnits = standardObjectData.getStandardUnits();
|
||||||
|
final WarcraftData standardItems = standardObjectData.getStandardItems();
|
||||||
|
final WarcraftData standardDoodads = standardObjectData.getStandardDoodads();
|
||||||
|
final WarcraftData standardDestructables = standardObjectData.getStandardDestructables();
|
||||||
|
final WarcraftData abilities = standardObjectData.getStandardAbilities();
|
||||||
|
final WarcraftData standardAbilityBuffs = standardObjectData.getStandardAbilityBuffs();
|
||||||
|
final WarcraftData standardUpgrades = standardObjectData.getStandardUpgrades();
|
||||||
|
|
||||||
|
final DataTable standardUnitMeta = standardObjectData.getStandardUnitMeta();
|
||||||
|
final DataTable standardDoodadMeta = standardObjectData.getStandardDoodadMeta();
|
||||||
|
final DataTable standardDestructableMeta = standardObjectData.getStandardDestructableMeta();
|
||||||
|
final DataTable abilityMeta = standardObjectData.getStandardAbilityMeta();
|
||||||
|
final DataTable standardAbilityBuffMeta = standardObjectData.getStandardAbilityBuffMeta();
|
||||||
|
final DataTable standardUpgradeMeta = standardObjectData.getStandardUpgradeMeta();
|
||||||
|
|
||||||
|
final War3ObjectDataChangeset unitChangeset = new War3ObjectDataChangeset('u');
|
||||||
|
final War3ObjectDataChangeset itemChangeset = new War3ObjectDataChangeset('t');
|
||||||
|
final War3ObjectDataChangeset doodadChangeset = new War3ObjectDataChangeset('d');
|
||||||
|
final War3ObjectDataChangeset destructableChangeset = new War3ObjectDataChangeset('b');
|
||||||
|
final War3ObjectDataChangeset abilityChangeset = new War3ObjectDataChangeset('a');
|
||||||
|
final War3ObjectDataChangeset buffChangeset = new War3ObjectDataChangeset('h');
|
||||||
|
final War3ObjectDataChangeset upgradeChangeset = new War3ObjectDataChangeset('q');
|
||||||
|
|
||||||
|
if (dataSource.has("war3map.w3u")) {
|
||||||
|
unitChangeset.load(new LittleEndianDataInputStream(dataSource.getResourceAsStream("war3map.w3u")), wts,
|
||||||
|
inlineWTS);
|
||||||
|
}
|
||||||
|
if (dataSource.has("war3map.w3t")) {
|
||||||
|
itemChangeset.load(new LittleEndianDataInputStream(dataSource.getResourceAsStream("war3map.w3t")), wts,
|
||||||
|
inlineWTS);
|
||||||
|
}
|
||||||
|
if (dataSource.has("war3map.w3d")) {
|
||||||
|
doodadChangeset.load(new LittleEndianDataInputStream(dataSource.getResourceAsStream("war3map.w3d")), wts,
|
||||||
|
inlineWTS);
|
||||||
|
}
|
||||||
|
if (dataSource.has("war3map.w3b")) {
|
||||||
|
destructableChangeset.load(new LittleEndianDataInputStream(dataSource.getResourceAsStream("war3map.w3b")),
|
||||||
|
wts, inlineWTS);
|
||||||
|
}
|
||||||
|
if (dataSource.has("war3map.w3a")) {
|
||||||
|
abilityChangeset.load(new LittleEndianDataInputStream(dataSource.getResourceAsStream("war3map.w3a")), wts,
|
||||||
|
inlineWTS);
|
||||||
|
}
|
||||||
|
if (dataSource.has("war3map.w3h")) {
|
||||||
|
buffChangeset.load(new LittleEndianDataInputStream(dataSource.getResourceAsStream("war3map.w3h")), wts,
|
||||||
|
inlineWTS);
|
||||||
|
}
|
||||||
|
if (dataSource.has("war3map.w3q")) {
|
||||||
|
upgradeChangeset.load(new LittleEndianDataInputStream(dataSource.getResourceAsStream("war3map.w3q")), wts,
|
||||||
|
inlineWTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
final WorldEditStrings worldEditStrings = standardObjectData.getWorldEditStrings();
|
||||||
|
final MutableObjectData unitData = new MutableObjectData(worldEditStrings, WorldEditorDataType.UNITS,
|
||||||
|
standardUnits, standardUnitMeta, unitChangeset);
|
||||||
|
final MutableObjectData itemData = new MutableObjectData(worldEditStrings, WorldEditorDataType.ITEM,
|
||||||
|
standardItems, standardUnitMeta, itemChangeset);
|
||||||
|
final MutableObjectData doodadData = new MutableObjectData(worldEditStrings, WorldEditorDataType.DOODADS,
|
||||||
|
standardDoodads, standardDoodadMeta, doodadChangeset);
|
||||||
|
final MutableObjectData destructableData = new MutableObjectData(worldEditStrings,
|
||||||
|
WorldEditorDataType.DESTRUCTIBLES, standardDestructables, standardDestructableMeta,
|
||||||
|
destructableChangeset);
|
||||||
|
final MutableObjectData abilityData = new MutableObjectData(worldEditStrings, WorldEditorDataType.ABILITIES,
|
||||||
|
abilities, abilityMeta, abilityChangeset);
|
||||||
|
final MutableObjectData buffData = new MutableObjectData(worldEditStrings, WorldEditorDataType.BUFFS_EFFECTS,
|
||||||
|
standardAbilityBuffs, standardAbilityBuffMeta, buffChangeset);
|
||||||
|
final MutableObjectData upgradeData = new MutableObjectData(worldEditStrings, WorldEditorDataType.UPGRADES,
|
||||||
|
standardUpgrades, standardUpgradeMeta, upgradeChangeset);
|
||||||
|
|
||||||
|
return new Warcraft3MapObjectData(unitData, itemData, destructableData, doodadData, abilityData, buffData,
|
||||||
|
upgradeData, wts);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package com.etheller.warsmash.parsers.w3x.unitsdoo;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import com.etheller.warsmash.util.ParseUtils;
|
||||||
|
import com.etheller.warsmash.util.War3ID;
|
||||||
|
import com.google.common.io.LittleEndianDataInputStream;
|
||||||
|
import com.google.common.io.LittleEndianDataOutputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A dropped item.
|
||||||
|
*/
|
||||||
|
public class DroppedItem {
|
||||||
|
private War3ID id;
|
||||||
|
private int chance;
|
||||||
|
|
||||||
|
public void load(final LittleEndianDataInputStream stream) throws IOException {
|
||||||
|
this.id = ParseUtils.readWar3ID(stream);
|
||||||
|
this.chance = stream.readInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save(final LittleEndianDataOutputStream stream) throws IOException {
|
||||||
|
ParseUtils.writeWar3ID(stream, this.id);
|
||||||
|
stream.writeInt(this.chance);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
package com.etheller.warsmash.parsers.w3x.unitsdoo;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.etheller.warsmash.util.ParseUtils;
|
||||||
|
import com.google.common.io.LittleEndianDataInputStream;
|
||||||
|
import com.google.common.io.LittleEndianDataOutputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A dropped item set.
|
||||||
|
*/
|
||||||
|
public class DroppedItemSet {
|
||||||
|
private final List<DroppedItem> items = new ArrayList<>();
|
||||||
|
|
||||||
|
public void load(final LittleEndianDataInputStream stream) throws IOException {
|
||||||
|
for (long i = 0, l = ParseUtils.readUInt32(stream); i < l; i++) {
|
||||||
|
final DroppedItem item = new DroppedItem();
|
||||||
|
|
||||||
|
item.load(stream);
|
||||||
|
|
||||||
|
this.items.add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save(final LittleEndianDataOutputStream stream) throws IOException {
|
||||||
|
ParseUtils.writeUInt32(stream, this.items.size());
|
||||||
|
|
||||||
|
for (final DroppedItem item : this.items) {
|
||||||
|
item.save(stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getByteLength() {
|
||||||
|
return 4 + (this.items.size() * 8);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package com.etheller.warsmash.parsers.w3x.unitsdoo;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import com.etheller.warsmash.util.ParseUtils;
|
||||||
|
import com.etheller.warsmash.util.War3ID;
|
||||||
|
import com.google.common.io.LittleEndianDataInputStream;
|
||||||
|
import com.google.common.io.LittleEndianDataOutputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An inventory item.
|
||||||
|
*/
|
||||||
|
public class InventoryItem {
|
||||||
|
private int slot;
|
||||||
|
private War3ID id;
|
||||||
|
|
||||||
|
public void load(final LittleEndianDataInputStream stream) throws IOException {
|
||||||
|
this.slot = stream.readInt();
|
||||||
|
this.id = ParseUtils.readWar3ID(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save(final LittleEndianDataOutputStream stream) throws IOException {
|
||||||
|
stream.writeInt(this.slot);
|
||||||
|
ParseUtils.writeWar3ID(stream, this.id);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package com.etheller.warsmash.parsers.w3x.unitsdoo;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import com.etheller.warsmash.util.ParseUtils;
|
||||||
|
import com.etheller.warsmash.util.War3ID;
|
||||||
|
import com.google.common.io.LittleEndianDataInputStream;
|
||||||
|
import com.google.common.io.LittleEndianDataOutputStream;
|
||||||
|
|
||||||
|
public class ModifiedAbility {
|
||||||
|
private War3ID id;
|
||||||
|
private int activeForAutocast = 0;
|
||||||
|
private int heroLevel = 1;
|
||||||
|
|
||||||
|
public void load(final LittleEndianDataInputStream stream) throws IOException {
|
||||||
|
this.id = ParseUtils.readWar3ID(stream);
|
||||||
|
this.activeForAutocast = stream.readInt();
|
||||||
|
this.heroLevel = stream.readInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save(final LittleEndianDataOutputStream stream) throws IOException {
|
||||||
|
ParseUtils.writeWar3ID(stream, this.id);
|
||||||
|
stream.writeInt(this.activeForAutocast);
|
||||||
|
stream.writeInt(this.heroLevel);
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user