Compare commits

...

8 Commits

Author SHA1 Message Date
8e995bd94c Reorganized app class 2023-02-21 20:31:29 +01:00
17c009c1ac Moved GUI initialize code to gui.py of packages 2023-02-18 16:16:19 +01:00
e56e2afb92 Scene graph tree added 2023-02-18 11:11:37 +01:00
a1cf6a7e05 Tidy up 2023-02-17 22:40:15 +01:00
48a0d4e20c Package manager app started using tkinter 2023-02-15 22:27:45 +01:00
cf6dd4de24 Removed useless files 2023-01-17 21:55:59 +01:00
0a9ef87f4d Merge branch 'main' of https://gitea.ligthert.net/MBH/MBH_Demo_001 2023-01-17 21:55:05 +01:00
a2b83b9810 File system and module reorganized 2023-01-17 21:54:39 +01:00
79 changed files with 423 additions and 849 deletions

15
__main__.py Normal file
View File

@ -0,0 +1,15 @@
import argparse
from source.pkgexplore import start_explorer
def main():
parser = argparse.ArgumentParser(prog='MBH', description='Morrowind with Blackjack and Hookers', epilog='?')
parser.add_argument('-m', '--main', required=True)
parser.add_argument('-p', '--package', nargs='+')
parser.add_argument('-e', '--explore', action='store_true')
args = parser.parse_args()
if args.explore:
start_explorer(args)
if __name__ == '__main__':
main()

5
assets/gamepackage.json Normal file
View File

@ -0,0 +1,5 @@
{
"name": "main-assets",
"version": "0.1-alpha",
"type": "main"
}

View File

@ -1,589 +0,0 @@
//
// Quake game definition file (.fgd)
// for Worldcraft 1.6 and above
//
// written by autolycus / autolycus@planetquake.com
// email me with improvements and suggestions
//
// Modified by CZG : grawert@online.no : http://www.planetquake.com/greyvoid/
// further modified by various authors
//
// worldspawn
//
@SolidClass = worldspawn : "World entity"
[
message(string) : "Text on entering the world"
worldtype(choices) : "Ambience" : 0 =
[
0 : "Medieval"
1 : "Metal (runic)"
2 : "Base"
]
sounds(integer) : "CD track to play" : 0
light(integer) : "Ambient light"
_sunlight(integer) : "Sunlight"
_sun_mangle(string) : "Sun mangle (Yaw pitch roll)"
]
//
// base marker definitions
//
@baseclass = Angle [ angle(integer) : "Direction" ]
@baseclass = Appearflags [
spawnflags(Flags) =
[
256 : "Not on Easy" : 0
512 : "Not on Normal" : 0
1024 : "Not on Hard" : 0
2048 : "Not in Deathmatch" : 0
]
]
@baseclass = Targetname [ targetname(target_source) : "Name" ]
@baseclass = Target [
target(target_destination) : "Target"
killtarget(target_destination) : "Killtarget"
]
//
// player starts, deathmatch, coop, teleport
//
@baseclass base(Appearflags) size(-16 -16 -24, 16 16 32)
color(0 255 0) model({ "path": ":progs/player.mdl" }) = PlayerClass []
@PointClass base(PlayerClass) = info_player_start : "Player 1 start" []
@PointClass base(PlayerClass) = info_player_coop : "Player cooperative start" []
@PointClass base(PlayerClass) = info_player_start2 : "Player episode return point" []
@PointClass base(PlayerClass) = info_player_deathmatch : "Deathmatch start" []
@PointClass base(PlayerClass) = testplayerstart : "Testing player start" []
@PointClass size(-32 -32 0, 32 32 64) base(PlayerClass, Targetname) = info_teleport_destination : "Teleporter destination" []
@PointClass color(200 150 150) = info_null : "info_null (spotlight target)"
[
targetname(target_source) : "Name"
]
@PointClass base(Appearflags, Target, Targetname) color(200 150 150) = info_notnull : "Wildcard entity" // I love you
[
use(string) : "self.use"
think(string) : "self.think"
nextthink(integer) : "nextthink"
noise(string) : "noise"
touch(string) : "self.touch"
]
@PointClass base(Appearflags) = info_intermission : "Intermission camera"
[
mangle(string) : "Camera angle (Pitch Yaw Roll)"
]
//
// items
//
@baseclass base(Appearflags, Target, Targetname) = Item
[
message(string) : "Message"
target(string) : "Target"
killtarget(string) : "Killtarget"
delay(integer) : "Delay"
]
@baseclass size(0 0 0, 32 32 56) color(80 0 200) base(Item) = Ammo
[
spawnflags(flags) =
[
1 : "Large box" : 0
]
]
@PointClass
base(Ammo)
model(
{{
spawnflags & 1 -> ":maps/b_batt1.bsp",
":maps/b_batt0.bsp"
}}
) =
item_cells : "Thunderbolt ammo" []
@PointClass
base(Ammo)
model(
{{
spawnflags & 1 -> ":maps/b_rock1.bsp",
":maps/b_rock0.bsp"
}}
) =
item_rockets : "Rockets" []
@PointClass
base(Ammo)
model(
{{
spawnflags & 1 -> ":maps/b_shell1.bsp",
":maps/b_shell0.bsp"
}}
) = item_shells : "Shells" []
@PointClass
base(Ammo)
model(
{{
spawnflags & 1 -> ":maps/b_nail1.bsp",
":maps/b_nail0.bsp"
}}
) = item_spikes : "Nailgun/Perforator ammo" []
@PointClass
size(0 0 0, 32 32 56)
base(Appearflags)
model(
{{
spawnflags & 2 -> ":maps/b_bh100.bsp",
spawnflags & 1 -> ":maps/b_bh10.bsp",
":maps/b_bh25.bsp"
}}
) =
item_health : "Health pack"
[
spawnflags(flags) =
[
1 : "Rotten" : 0
2 : "Megahealth" : 0
]
]
@PointClass size(-16 -16 -24, 16 16 32) base(Item, Appearflags) model({ "path": ":progs/suit.mdl" }) =
item_artifact_envirosuit : "Environmental protection suit" []
@PointClass size(-16 -16 -24, 16 16 32) base(Item, Appearflags) model({ "path": ":progs/quaddama.mdl" }) =
item_artifact_super_damage : "Quad damage" []
@PointClass size(-16 -16 -24, 16 16 32) base(Item, Appearflags) model({ "path": ":progs/invulner.mdl" }) =
item_artifact_invulnerability : "Pentagram of Protection" []
@PointClass size(-16 -16 -24, 16 16 32) base(Item, Appearflags) model({ "path": ":progs/invisibl.mdl" }) =
item_artifact_invisibility : "Ring of Shadows" []
@PointClass size(-16 -16 0, 16 16 56) base(Item, Appearflags) model({ "path": ":progs/armor.mdl", "skin": 2 }) =
item_armorInv : "Red armor (200%)" []
@PointClass size(-16 -16 0, 16 16 56) base(Item, Appearflags) model({ "path": ":progs/armor.mdl", "skin": 1 }) =
item_armor2 : "Yellow armor (150%)" []
@PointClass size(-16 -16 0, 16 16 56) base(Item, Appearflags) model({ "path": ":progs/armor.mdl" }) =
item_armor1 : "Green armor (100%)" []
@PointClass size(-16 -16 -24, 16 16 32) base(Item, Appearflags) model({ "path": ":progs/w_s_key.mdl" }) =
item_key1 : "Silver key" []
@PointClass size(-16 -16 -24, 16 16 32) base(Item, Appearflags) model({ "path": ":progs/w_g_key.mdl" }) =
item_key2 : "Gold key" []
@PointClass size(-16 -16 -24, 16 16 32) base(Item, Appearflags) model({ "path": ":progs/end1.mdl" }) =
item_sigil : "Sigil"
[
spawnflags(Flags) =
[
1 : "Episode 1" : 1
2 : "Episode 2" : 0
4 : "Episode 3" : 0
8 : "Episode 4" : 0
]
]
//
// weapons
//
@baseclass size(-16 -16 0, 16 16 56) color(0 0 200) base(Item, Appearflags) = Weapon []
@PointClass base(Weapon) model({ "path": ":progs/g_shot.mdl" }) = weapon_supershotgun : "Double-barrelled shotgun" []
@PointClass base(Weapon) model({ "path": ":progs/g_nail.mdl" }) = weapon_nailgun : "Nailgun" []
@PointClass base(Weapon) model({ "path": ":progs/g_nail2.mdl" }) = weapon_supernailgun : "Super nailgun" []
@PointClass base(Weapon) model({ "path": ":progs/g_rock.mdl" }) = weapon_grenadelauncher : "Grenade launcher" []
@PointClass base(Weapon) model({ "path": ":progs/g_rock2.mdl" }) = weapon_rocketlauncher : "Rocket launcher" []
@PointClass base(Weapon) model({ "path": ":progs/g_light.mdl" }) = weapon_lightning : "Thunderbolt" []
//
// monsters
//
@baseclass base(Angle, Appearflags, Target, Targetname) color(220 0 0) = Monster
[
spawnflags(Flags) =
[
1 : "Ambush" : 0
]
]
@PointClass base(Monster) size(-16 -16 -24, 16 16 40) model({ "path": ":progs/soldier.mdl" }) = monster_army : "Grunt" []
@PointClass base(Monster) size(-32 -32 -24, 32 32 40) model({ "path": ":progs/dog.mdl" }) = monster_dog : "Nasty Doggie" []
@PointClass base(Monster) size(-32 -32 -24, 32 32 64) model({ "path": ":progs/ogre.mdl" }) = monster_ogre : "Ogre" []
@PointClass base(Monster) size(-32 -32 -24, 32 32 64) model({ "path": ":progs/ogre.mdl" }) = monster_ogre_marksman : "Ogre marksman" []
@PointClass base(Monster) size(-16 -16 -24, 16 16 40) model({ "path": ":progs/knight.mdl" }) = monster_knight : "Knight" []
@PointClass base(Monster) size(-16 -16 -24, 16 16 40) model({ "path": ":progs/hknight.mdl" }) = monster_hell_knight : "Hell knight" []
@PointClass base(Monster) size(-16 -16 -24, 16 16 40) model({ "path": ":progs/wizard.mdl" }) = monster_wizard : "Scrag" []
@PointClass base(Monster) size(-32 -32 -24, 32 32 64) model({ "path": ":progs/demon.mdl" }) = monster_demon1 : "Fiend" []
@PointClass base(Monster) size(-32 -32 -24, 32 32 64) model({ "path": ":progs/shambler.mdl" }) = monster_shambler : "Shambler" []
@PointClass base(Monster) size(-128 -128 -24, 128 128 256) model({ "path": ":progs/boss.mdl" }) = monster_boss : "Chthon" []
@PointClass base(Monster) size(-16 -16 -24, 16 16 40) model({ "path": ":progs/enforcer.mdl" }) = monster_enforcer : "Enforcer" []
@PointClass base(Monster) size(-32 -32 -24, 32 32 64) model({ "path": ":progs/shalrath.mdl" }) = monster_shalrath : "Vore" []
@PointClass base(Monster) size(-16 -16 -24, 16 16 24) model({ "path": ":progs/tarbaby.mdl" }) = monster_tarbaby : "Spawn" []
@PointClass base(Monster) size(-16 -16 -24, 16 16 24) model({ "path": ":progs/fish.mdl" }) = monster_fish : "Rotfish" []
@PointClass base(Monster) size(-16 -16 -24, 16 16 32) model({ "path": ":progs/oldone.mdl" }) = monster_oldone : "Shub-Niggurath" []
@PointClass base(Monster) size(-16 -16 -24, 16 16 32) model({ "path": ":progs/zombie.mdl" }) = monster_zombie : "Zombie"
[
spawnflags(Flags) =
[
1 : "Crucified" : 0
2 : "Ambush" : 0
]
]
//
// lights
//
@baseclass color(255 255 40) = Light [
light(integer) : "Brightness" : 300
wait(integer) : "Fade distance multiplier" : 1
delay(choices) : "Attenuation" =
[
0 : "Linear falloff (Default)"
1 : "Inverse distance falloff"
2 : "Inverse distance squared"
3 : "No falloff"
4 : "Local minlight"
5 : "Inverse distance squared B"
]
mangle(string) : "Spotlight angle"
style(Choices) : "Appearance" : 0 =
[
0 : "Normal"
10: "Fluorescent flicker"
2 : "Slow, strong pulse"
11: "Slow pulse, noblack"
5 : "Gentle pulse"
1 : "Flicker A"
6 : "Flicker B"
3 : "Candle A"
7 : "Candle B"
8 : "Candle C"
4 : "Fast strobe"
9 : "Slow strobe"
]
]
@PointClass size(-8 -8 -8, 8 8 8) base(Light, Target, Targetname) =
light : "Invisible light source"
[
spawnflags(Flags) = [ 1 : "Start off" : 0 ]
]
@PointClass size(-8 -8 -8, 8 8 8) base(Light, Target, Targetname) =
light_fluoro : "Fluorescent light"
[
spawnflags(Flags) = [ 1 : "Start off" : 0 ]
]
@PointClass size(-8 -8 -8, 8 8 8) base(Light, Target, Targetname) =
light_fluorospark : "Sparking fluorescent light"
[
spawnflags(Flags) = [ 1 : "Start off" : 0 ]
]
@PointClass size(-8 -8 -8, 8 8 8) base(Appearflags, Light, Target, Targetname) model({ "path": "progs/s_light.spr" }) =
light_globe : "Globe light"
[
spawnflags(Flags) = [ 1 : "Start off" : 0 ]
]
@PointClass size(-8 -8 -12, 8 8 20) base(Appearflags, Light, Target, Targetname) model({ "path": ":progs/flame2.mdl" }) =
light_flame_large_yellow : "Large yellow flame"
[
spawnflags(Flags) = [ 1 : "Start off" : 0 ]
]
@PointClass size(-4 -4 -12, 4 4 20) base(Appearflags, Light, Target, Targetname) model({ "path": ":progs/flame2.mdl" }) =
light_flame_small_yellow : "Small yellow flame"
[
spawnflags(Flags) = [ 1 : "Start off" : 0 ]
]
@PointClass size(-4 -4 -12, 4 4 20) base(Appearflags, Light, Target, Targetname) model({ "path": ":progs/flame2.mdl" }) =
light_flame_small_white : "Small white flame"
[
spawnflags(Flags) = [ 1 : "Start off" : 0 ]
]
@PointClass size(-4 -4 -12, 4 4 20) base(Appearflags, Light, Target, Targetname) model({ "path": ":progs/flame.mdl" }) =
light_torch_small_walltorch : "Small walltorch" []
//
// misc
//
@SolidClass base(Appearflags) = func_illusionary : "Static nonsolid model" []
@PointClass base(Appearflags) color(0 150 220) model({ "path": ":progs/s_bubble.spr" }) = air_bubbles : "Air bubbles" []
@PointClass base(Appearflags, Targetname) =
event_lightning : "Chthon's lightning" []
@PointClass base(Appearflags) model({ "path": ":progs/lavaball.mdl" }) = misc_fireball : "Small fireball"
[ speed(integer) : "Speed" : 40 ]
@PointClass base(Appearflags) size(0 0 0, 32 32 64) model({ "path": ":maps/b_explob.bsp" }) = misc_explobox : "Large exploding container" []
@PointClass base(Appearflags) size(0 0 0, 32 32 32) model({ "path": ":maps/b_exbox2.bsp" }) = misc_explobox2 : "Small exploding container" []
@PointClass base(Appearflags) size(-8 -8 -8, 8 8 8) model({ "path": ":progs/teleport.mdl" }) = misc_teleporttrain : "Flying teleporter destination"
[
target(string) : "First stop target"
targetname(target_source) : "Name"
]
@PointClass base(Appearflags, Targetname) color(220 150 150) = trap_spikeshooter : "Triggered shooter"
[
spawnflags(Flags) =
[
1 : "Spike" : 0
2 : "Laser" : 0
]
]
@PointClass base(Appearflags) color(220 150 150) = trap_shooter : "Continuous shooter"
[
nextthink(integer) : "Delay before first spike"
wait(integer) : "Delay between spikes"
spawnflags(Flags) =
[
1 : "Spike" : 0
2 : "Laser" : 0
]
]
@SolidClass = func_group : "Group of brushes for in-editor use" []
@SolidClass = func_detail : "Group of brushes for certain compilers" []
@SolidClass = func_detail_illusionary : "func_detail variant with no collision (players / monsters / gunfire) and doesn't split world faces." []
@SolidClass = func_detail_wall : "func_detail variant that doesn't split world faces." []
//
// ambient sounds
//
@PointClass base(Appearflags) color(150 0 150) = ambient_drip : "Dripping sound" []
@PointClass base(Appearflags) color(150 0 150) = ambient_drone : "Engine/machinery sound" []
@PointClass base(Appearflags) color(150 0 150) = ambient_comp_hum : "Computer background sounds" []
@PointClass base(Appearflags) color(150 0 150) = ambient_flouro_buzz : "Fluorescent buzzing sound" []
@PointClass base(Appearflags) color(150 0 150) = ambient_light_buzz : "Buzzing sound from light" []
@PointClass base(Appearflags) color(150 0 150) = ambient_suck_wind : "Wind sound" []
@PointClass base(Appearflags) color(150 0 150) = ambient_swamp1 : "Frogs croaking" []
@PointClass base(Appearflags) color(150 0 150) = ambient_swamp2 : "Frogs croaking B" []
@PointClass base(Appearflags) color(150 0 150) = ambient_thunder : "Thunder sound" []
//
// moving things
//
@SolidClass base(Angle, Appearflags, Targetname, Target) = func_door : "Basic door"
[
speed(integer) : "Speed" : 100
sounds(choices) : "Sound" : 0 =
[
0: "Silent"
1: "Stone"
2: "Machine"
3: "Stone Chain"
4: "Screechy Metal"
]
wait(string) : "Wait before close" : "3"
lip(integer) : "Lip" : 8
dmg(integer) : "Damage inflicted when blocked" : 2
message(string) : "Message if touched"
health(integer) : "Health (shootable)" : 0
spawnflags(flags) =
[
1 : "Starts Open" : 0
4 : "Don't link" : 0
8 : "Gold Key required" : 0
16: "Silver Key required" : 0
32: "Toggle" : 0
]
]
@SolidClass base(Appearflags, Targetname, Target) = func_door_secret : "Secret door"
[
angle(integer) : "Direction of second move"
t_width(integer) : "First move length"
t_length(integer) : "Second move length"
dmg(integer) : "Damage when blocked" : 2
wait(string) : "Wait before close" : "2"
sounds(choices) : "Sounds" : 3 =
[
1: "Medieval"
2: "Metal"
3: "Base"
]
message(string) : "Message"
spawnflags(flags) =
[
1 : "Open once" : 0
2 : "Move left first" : 0
4 : "Move down first" : 0
8 : "Not shootable" : 0
16 : "Always shootable" : 0
]
]
@SolidClass base(Appearflags, Targetname) = func_wall : "Wall, starts animation when triggered (if supporting texture)" []
@SolidClass base(Angle, Appearflags, Targetname) = func_button : "Button"
[
speed(integer) : "Speed" : 40
lip(integer) : "Lip" : 4
target(target_source) : "Target"
health(integer) : "Health (shootable)"
sounds(choices) : "Sounds" =
[
0 : "Steam metal"
1 : "Wooden clunk"
2 : "Metallic clink"
3 : "In-out"
]
wait(string) : "Wait before reset" : "1"
delay(string) : "Delay before trigger"
message(string) : "Message"
]
@SolidClass base(Appearflags, Targetname) = func_train : "Moving platform"
[
sounds(choices) : "Sound" : 1 =
[
0: "Silent"
1: "Ratchet Metal"
]
speed(integer) : "Speed (units per second)" : 64
target(target_source) : "Target to start at"
dmg(integer) : "Damage on block" : 2
]
@PointClass base(Appearflags, Targetname) size(16 16 16) color(0 255 255) =
path_corner : "Waypoint for platforms and monsters"
[
target(target_source) : "Next target"
wait(integer) : "Wait" : 0
]
@SolidClass base(Appearflags, Targetname) = func_plat : "Elevator"
[
spawnflags(Flags) =
[
1 : "Low trigger volume" : 0
]
speed(integer) : "Speed" : 150
height(integer) : "Travel altitude (can be negative)" : 0
sounds(choices) : "Sound" : 1 =
[
0: "None"
1: "Base fast"
2: "Chain Slow"
]
]
@SolidClass base(Appearflags) = func_episodegate : "Episode Gate"
[
spawnflags(Flags) =
[
1 : "Episode 1" : 1
2 : "Episode 2" : 0
4 : "Episode 3" : 0
8 : "Episode 4" : 0
]
]
@SolidClass base(Appearflags) = func_bossgate : "Boss gate" []
//
// triggers
//
@baseclass base(Appearflags, Target, Targetname) = Trigger
[
sounds(choices) : "Sound style" : 0 =
[
0 : "None"
1 : "Secret sound"
2 : "Beep beep"
3 : "Large switch"
]
delay(string) : "Delay before trigger" : "0"
message(string) : "Message"
]
@SolidClass base(Trigger) = trigger_changelevel : "Trigger: Change level"
[
map(string) : "Next map"
target(target_destination) : "Target"
spawnflags(flags) =
[
1: "No intermission" : 0
]
]
@SolidClass base(Trigger) = trigger_once : "Trigger: Activate once"
[
health(integer) : "Health (shootable)"
spawnflags(flags) = [ 1: "Not touchable" : 0 ]
]
@SolidClass base(Trigger) = trigger_multiple : "Trigger: Activate multiple"
[
wait(string) : "Wait before reset" : "0.2"
health(integer) : "Health (shootable)"
spawnflags(flags) = [ 1: "Not touchable" : 0 ]
]
@SolidClass base(Trigger) = trigger_onlyregistered : "Trigger: Registered only"
[
spawnflags(flags) = [ 1: "Not touchable" : 0 ]
]
@SolidClass base(Trigger) = trigger_secret : "Trigger: Secret"
[
sounds(choices) : "Sound" : 1 =
[
1 : "Secret sound"
2 : "Beep beep"
]
spawnflags(flags) = [ 1: "Not touchable" : 0 ]
]
@SolidClass base(Appearflags, Target, Targetname) = trigger_teleport : "Trigger: Teleporter"
[
spawnflags(Flags) =
[
1 : "Player only" : 0
2 : "Silent" : 0
]
]
@SolidClass base(Appearflags) = trigger_setskill : "Trigger: Set skill"
[
message(choices) : "Skill to change to" : 1 =
[
0 : "Easy"
1 : "Medium"
2 : "Hard"
3 : "Nightmare!"
]
]
@PointClass base(Trigger) = trigger_relay : "Trigger: Relay"
[
]
@SolidClass base(Angle, Appearflags, Targetname) = trigger_monsterjump : "Trigger: Monster jump"
[
speed(integer) : "Jump Speed" : 200
height(integer) : "Jump Height" : 200
]
@PointClass base(Appearflags, Target, Targetname) = trigger_counter : "Trigger: Counter"
[
spawnflags(flags) = [ 1: "No Message" : 0 ]
count(integer) : "Count before trigger" : 2
delay (integer) : "Delay"
message(string) : "Message"
]
@SolidClass base(Angle, Appearflags, Targetname) = trigger_push : "Trigger: Push"
[
spawnflags(flags) = [ 1: "Push once" : 0 ]
speed(integer) : "Speed" : 1000
]
@SolidClass base(Appearflags, Targetname) = trigger_hurt : "Trigger: Hurt"
[
dmg(integer) : "Damage per second" : 5
]
@PointClass size(16 16 16) = misc_noisemaker : "Debug entity: continuously plays enforcer sounds" []
@PointClass size(16 16 16) = viewthing : "Debug entity: fake player model" []

View File

@ -1,50 +0,0 @@
// Game: Generic
// Format: Standard
// entity 0
{
"classname" "worldspawn"
"_tb_textures" "textures"
"_tb_def" "external:master.fgd"
"integer" "10"
"floating" "10.248"
"string" "sfdoijsdf"
// brush 0
{
( 0 0 16 ) ( 0 -128 16 ) ( 0 -128 -16 ) generic_tiles 0 0 45 1 1
( 0 -128 16 ) ( 128 -128 16 ) ( 128 -128 -16 ) generic_tiles 0 0 45 1 1
( 128 -128 -16 ) ( 128 0 -16 ) ( 0 0 -16 ) generic_tiles 0 0 45 1 1
( 0 0 16 ) ( 128 0 16 ) ( 128 -128 16 ) generic_tiles 0 0 45 1 1
( 128 0 -16 ) ( 128 0 16 ) ( 0 0 16 ) generic_tiles 0 0 45 1 1
( 128 -128 16 ) ( 128 0 16 ) ( 128 0 -16 ) generic_tiles 0 0 45 1 1
}
// brush 1
{
( -384 384 0 ) ( -384 384 64 ) ( -384 -64 0 ) generic_tiles 0 0 45 1 1
( -384 384 64 ) ( -285.39994983020347 52.87499999999663 64 ) ( -384 -64 0 ) generic_tiles 35.14084 11.834999 45 1 1
( -285.39994983020347 52.87499999999663 64 ) ( -184.606925748656 -41.49999999956605 64 ) ( -384 -64 0 ) generic_tiles 35.14084 11.834999 45 1 1
( -184.606925748656 -41.49999999956605 64 ) ( 0 -64 64 ) ( -384 -64 0 ) generic_tiles 0 1.4594574 45 1 1
( -384 -64 0 ) ( 0 -64 64 ) ( 0 -64 0 ) generic_tiles 0 0 45 1 1
( 0 -64 0 ) ( 0 384 0 ) ( -384 384 0 ) generic_tiles 0 0 45 1 1
( -384 384 64 ) ( 0 384 64 ) ( 0 -64 64 ) generic_tiles 0 0 45 1 1
( 0 384 0 ) ( 0 384 64 ) ( -384 384 64 ) generic_tiles 0 0 45 1 1
( 0 -64 64 ) ( 0 384 64 ) ( 0 384 0 ) generic_tiles 0 0 45 1 1
}
}
// entity 1
{
"classname" "air_bubbles"
"origin" "-136 168 72"
}
// entity 2
{
"classname" "func_detail"
// brush 0
{
( 0 -128 0 ) ( 0 -127 0 ) ( 0 -128 1 ) generic_tiles 0 0 45 1 1
( 0 -128 0 ) ( 0 -128 1 ) ( 1 -128 0 ) generic_tiles 0 0 45 1 1
( 0 -128 0 ) ( 1 -128 0 ) ( 0 -127 0 ) generic_tiles 0 0 45 1 1
( 64 0 64 ) ( 64 1 64 ) ( 65 0 64 ) generic_tiles 0 0 45 1 1
( 64 0 64 ) ( 65 0 64 ) ( 64 0 65 ) generic_tiles 0 0 45 1 1
( 64 0 64 ) ( 64 0 65 ) ( 64 1 64 ) generic_tiles 0 0 45 1 1
}
}

View File

@ -1,20 +0,0 @@
// Game: Generic
// Format: Standard
// entity 0
{
"classname" "worldspawn"
"_tb_textures" "textures"
"_tb_def" "external:master.fgd"
"integer" "10"
"floating" "10.248"
"string" "sfdoijsdf"
// brush 0
{
( -64 160 0 ) ( -64 161 0 ) ( -64 160 1 ) __TB_empty 0 -16 0 1 1
( -64 160 0 ) ( -64 160 1 ) ( -63 160 0 ) __TB_empty 0 -16 0 1 1
( -64 160 0 ) ( -63 160 0 ) ( -64 161 0 ) __TB_empty 0 0 0 1 1
( -32 192 16 ) ( -32 193 16 ) ( -31 192 16 ) __TB_empty 0 0 0 1 1
( -32 192 16 ) ( -31 192 16 ) ( -32 192 17 ) __TB_empty 0 -16 0 1 1
( -32 192 16 ) ( -32 192 17 ) ( -32 193 16 ) __TB_empty 0 -16 0 1 1
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
assets/models/axis.glb Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
assets/models/box.glb Normal file

Binary file not shown.

Binary file not shown.

BIN
assets/models/debugrot.glb Normal file

Binary file not shown.

BIN
assets/models/doortype1.glb Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
assets/models/room1.glb Normal file

Binary file not shown.

BIN
assets/models/suz.glb Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
assets/textures/axis.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

BIN
assets/textures/cursed.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

BIN
assets/textures/floor1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 988 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 458 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 526 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 633 KiB

BIN
assets/textures/wall1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

0
source/__init__.py Normal file
View File

View File

@ -1,55 +0,0 @@
from direct.showbase.ShowBase import ShowBase
from panda3d.core import WindowProperties, GeomVertexArrayFormat, GeomVertexFormat, Geom, GeomVertexData, GeomVertexWriter, GeomTriangles, GeomNode
from panda3d.core import VirtualFileSystem
from panda3d.core import Vec3
from map.file import parse_map_file
class DungeonCell:
def __init__(self):
self.mesh = None
self.bounds = [None, None]
self.connections = []
def getBounds(self):
bmin, bmax = self.mesh.getTightBounds()
self.bounds = [bmin, bmax]
class CellArrange1(DungeonCell):
def __init__(self):
DungeonCell.__init__(self)
self.mesh = loader.loadModel("/models/arrangements/arrange1.glb")
self.connections = [
Vec3(0, 5, 0),
Vec3(0, -5, 0),
Vec3(5, 0, 0),
Vec3(-5, 0, 0)
]
self.getBounds()
class Game(ShowBase):
def __init__(self):
ShowBase.__init__(self)
vfs = VirtualFileSystem.getGlobalPtr()
vfs.mount('assets', '/', 0)
tex_bricks = loader.loadTexture('/textures/generic_bricks.png')
tex_floor = loader.loadTexture('/textures/generic_tiles.png')
self.room = CellArrange1()
self.room.mesh.reparentTo(render)
self.room.mesh.find('**/A1.Walls').setTexture(tex_bricks, 1)
self.room.mesh.find('**/A1.Floor').setTexture(tex_floor, 1)
print(self.room.bounds)
winprops = WindowProperties()
winprops.setSize(1600, 900)
self.win.requestProperties(winprops)
game = Game()
game.run()

View File

@ -1,11 +0,0 @@
from panda3d.core import Vec3
def convert_to_csg(mapfile):
return

View File

@ -1,124 +0,0 @@
from re import match as regexp
from enum import Enum
from panda3d.core import Vec3
class MapFace:
def __init__(self):
self.v1 = Vec3()
self.v2 = Vec3()
self.v3 = Vec3()
self.tex = ''
self.offset = Vec3()
self.scale = Vec3()
self.angle = 0.0
self.normal = Vec3()
class MapBrush:
def __init__(self):
self.faces = []
class MapEntity:
def __init__(self):
self.classname = ''
self.attributes = {}
self.brushes = []
class MapFile:
def __init__(self, filepath, entities):
self.filepath = filepath
self.entities = entities
def entity_count(self):
return len(self.entities)
def brush_count(self):
total = 0
for ent in self.entities:
total += len(ent.brushes)
return total
def face_count(self):
total = 0
for ent in self.entities:
for brush in ent.brushes:
total += len(brush.faces)
return total
class MapStack(Enum):
TOP = 0
ENTITY = 1
BRUSH = 2
def parse_map_file(filepath):
entities = []
with open(filepath, 'r') as mapfile:
current_stack = MapStack.TOP
current_entity = None
current_brush = None
for mapline in mapfile:
if mapline[:2] == '//':
continue
if current_stack == MapStack.TOP and mapline[:1] == '{':
current_stack = MapStack.ENTITY
current_entity = MapEntity()
entities.append(current_entity)
elif current_stack == MapStack.ENTITY and mapline[:1] == '}':
current_stack = MapStack.TOP
current_entity = None
elif current_stack == MapStack.ENTITY and mapline[:1] == '{':
current_stack = MapStack.BRUSH
current_brush = MapBrush()
current_entity.brushes.append(current_brush)
elif current_stack == MapStack.BRUSH and mapline[:1] == '}':
current_stack = MapStack.ENTITY
current_brush = None
elif current_stack == MapStack.ENTITY and mapline[:1] == '"':
result = regexp('^"(.+)" "(.+)"$', mapline)
current_entity.attributes[result.group(1)] = result.group(2)
elif current_stack == MapStack.BRUSH and mapline[:1] == '(':
result = regexp("^(\\(.+\\)) (.+)", mapline)
coordinates = result.group(1)
texture = result.group(2).split(' ')
as_num = lambda v: float(v)
verts = regexp("^\\( (.+?) \\) \\( (.+?) \\) \\( (.+?) \\)$", coordinates)
verts1 = map(as_num, verts.group(1).split(' '))
verts2 = map(as_num, verts.group(2).split(' '))
verts3 = map(as_num, verts.group(3).split(' '))
current_face = MapFace()
current_face.v1 = Vec3(tuple(verts1))
current_face.v2 = Vec3(tuple(verts2))
current_face.v3 = Vec3(tuple(verts3))
current_face.tex = texture[0]
current_face.offset = Vec3(float(texture[1]), float(texture[2]), 0)
current_face.angle = float(texture[3])
current_face.scale = Vec3(float(texture[4]), float(texture[5]), 0)
current_brush.faces.append(current_face)
edge_a = current_face.v2 - current_face.v1
edge_b = current_face.v3 - current_face.v1
current_face.normal = edge_b.cross(edge_a).normalized()
return MapFile(filepath, entities)
'''
mapfile = parse_map_file("C:\\Users\\Bryan\\Documents\\MBH\\assets\\meshes\\maps\\test.map")
print(mapfile.entity_count())
print(mapfile.brush_count())
print(mapfile.face_count())
'''

View File

@ -0,0 +1,2 @@
from .manager import PackageManager

14
source/packages/errors.py Normal file
View File

@ -0,0 +1,14 @@
class FilepathNotFound(Exception):
pass
class GamePackageMissing(Exception):
pass
class GamePackageMalformed(Exception):
pass
class PackageAlreadyLoaded(Exception):
pass
class InvalidPackageType(Exception):
pass

157
source/packages/gui.py Normal file
View File

@ -0,0 +1,157 @@
import posixpath
import tkinter as tk
import tkinter.ttk as ttk
import simplepbr
import gltf
from direct.stdpy.file import walk
from panda3d.core import NodePath, DirectionalLight, TransparencyAttrib
def get_icons():
return type('', (object,), {
'app': tk.PhotoImage(file="ui/icons/application.png"),
'brick': tk.PhotoImage(file="ui/icons/brick.png"),
'bricks': tk.PhotoImage(file="ui/icons/bricks.png"),
'computer': tk.PhotoImage(file="ui/icons/computer.png"),
'folder': tk.PhotoImage(file="ui/icons/folder.png"),
'shape_group': tk.PhotoImage(file="ui/icons/shape_group.png"),
'pictures': tk.PhotoImage(file="ui/icons/pictures.png"),
'picture': tk.PhotoImage(file='ui/icons/picture.png'),
"page_red": tk.PhotoImage(file='ui/icons/page_red.png'),
'shape_square': tk.PhotoImage(file='ui/icons/shape_square.png'),
'color_wheel': tk.PhotoImage(file='ui/icons/color_wheel.png'),
'color_swatch': tk.PhotoImage(file='ui/icons/color_swatch.png'),
'link': tk.PhotoImage(file='ui/icons/link.png'),
'sound': tk.PhotoImage(file='ui/icons/sound.png'),
'chart_organisation': tk.PhotoImage(file='ui/icons/chart_organisation.png'),
'anchor': tk.PhotoImage(file='ui/icons/anchor.png'),
'shape_flip_horizontal': tk.PhotoImage(file='ui/icons/shape_flip_horizontal.png'),
'film': tk.PhotoImage(file='ui/icons/film.png'),
'user': tk.PhotoImage(file='ui/icons/user.png'),
'chart_line_link': tk.PhotoImage(file='ui/icons/chart_line_link.png'),
'music': tk.PhotoImage(file='ui/icons/music.png')
})()
def add_package_contents_to_tree(tree, package, type, name, extensions, icon_folder, icon_group, icon_item):
data_path = posixpath.join(package.mount_dir, type)
tree.insert(package.mount_dir, 'end', data_path, text=f' {name}', image=icon_group)
file_count = 0
for root, paths, files in walk(data_path):
for path in paths:
tree.insert(root, 'end', posixpath.join(root, path), text=f' {path}', image=icon_folder)
for file in files:
if file.lower().endswith(extensions):
file_count += 1
tree.insert(root, 'end', posixpath.join(root, file), text=f' {file}', image=icon_item)
tree.item(data_path, text=f' {name} ({file_count})')
def add_package_models_to_tree(tree, package, icons):
add_package_contents_to_tree(tree, package, 'models/', '3D Models', ('.glb', '.gltf', '.obj', '.egg'), icons.folder, icons.shape_group, icons.shape_square)
def add_package_textures_to_tree(tree, package, icons):
add_package_contents_to_tree(tree, package, 'textures/', 'Image Textures', ('.png', '.jpg', '.bmp'), icons.folder, icons.pictures, icons.picture)
def add_package_materials_to_tree(tree, package, icons):
add_package_contents_to_tree(tree, package, 'materials/', 'Materials', ('.json'), icons.folder, icons.color_wheel, icons.color_swatch)
def add_package_sounds_to_tree(tree, package, icons):
add_package_contents_to_tree(tree, package, 'sounds/', 'Sounds', ('.ogg', '.wav'), icons.folder, icons.sound, icons.sound)
def add_package_music_to_tree(tree, package, icons):
add_package_contents_to_tree(tree, package, 'music/', 'Music', ('.ogg', '.mp3'), icons.folder, icons.music, icons.music)
def add_package_to_tree(tree, package, icons):
add_package_models_to_tree(tree, package, icons)
add_package_textures_to_tree(tree, package, icons)
add_package_materials_to_tree(tree, package, icons)
add_package_sounds_to_tree(tree, package, icons)
add_package_music_to_tree(tree, package, icons)
def init_packages_tree(tree, packages, icons):
tree.insert('', 'end', '/', text=' /', open=True, image=icons.app)
tree.insert('/', 'end', '/main/', text=f' Main Package "{packages.main_package.meta.name}" - {packages.main_package.meta.version}', image=icons.computer)
tree.insert('/', 'end', '/include/', text=f' Included Packages ({len(packages.package_list)})', image=icons.bricks)
add_package_to_tree(tree, packages.main_package, icons)
for package in packages.package_list:
tree.insert('/include/', 'end', package.mount_dir, text=f' "{package.meta.name}" - {package.meta.version}', image=icons.brick)
add_package_to_tree(tree, package, icons)
return tree
def init_gui(app, args):
app.gui.geometry("700x500")
app.gui.grid_rowconfigure(0, weight=10)
app.gui.grid_rowconfigure(1, weight=5)
app.gui.grid_columnconfigure(0, weight=1)
package_frame = tk.Frame(app.gui, padx=4, pady=4)
package_frame.grid(column=0, row=0, sticky="news")
package_frame.grid_columnconfigure(0, weight=1)
package_frame.grid_rowconfigure(0, weight=1)
package_frame.grid_rowconfigure(1, weight=1000)
packages_label = tk.Label(package_frame, text="Packages")
packages_label.grid(column=0, row=0, sticky="w")
packagetree_frame = tk.Frame(package_frame)
packagetree_frame.grid(column=0, row=1, sticky="news")
packagetree_frame.grid_columnconfigure(0, weight=1000)
packagetree_frame.grid_columnconfigure(1, weight=1)
packagetree_frame.grid_rowconfigure(0, weight=1)
app.tree_packages = ttk.Treeview(packagetree_frame, show="tree")
app.tree_packages.grid(column=0, row=0, sticky="news")
packagetree_scrollbar = ttk.Scrollbar(packagetree_frame, orient="vertical", command=app.tree_packages.yview)
packagetree_scrollbar.grid(column=1, row=0)
app.tree_packages.bind('<Double-1>', app.on_packagetree_doubleclick)
scene_frame = tk.Frame(app.gui, padx=4, pady=4)
scene_frame.grid(column=0, row=1, sticky="news")
scene_frame.grid_columnconfigure(0, weight=1)
scene_frame.grid_rowconfigure(0, weight=1)
scene_frame.grid_rowconfigure(1, weight=1000)
scene_label = tk.Label(scene_frame, text="Scene Graph")
scene_label.grid(column=0, row=0, sticky="w")
scenetree_frame = tk.Frame(scene_frame)
scenetree_frame.grid(column=0, row=1, sticky="news")
scenetree_frame.grid_columnconfigure(0, weight=10000)
scenetree_frame.grid_columnconfigure(1, weight=1)
scenetree_frame.grid_rowconfigure(0, weight=1)
app.tree_scene = ttk.Treeview(scenetree_frame, show="tree")
app.tree_scene.grid(column=0, row=0, sticky="news")
scenetree_scrollbar = ttk.Scrollbar(scenetree_frame, orient="vertical", command=app.tree_scene.yview)
scenetree_scrollbar.grid(column=1, row=0)
app.gui.protocol("WM_DELETE_WINDOW", app.on_tk_close)
def init_panda(app, args):
gltf.patch_loader(app.panda.loader)
app.panda.setBackgroundColor(.02, .02, .02)
app.panda.disableMouse()
app.panda.camera.setPos(0, -5, 2.5)
app.panda.camera.setHpr(0, -20, 0)
simplepbr.init()
app.env_root = NodePath('env_root')
app.env_root.reparentTo(app.panda.render)
axis = app.panda.loader.loadModel(app.package_manager.get_model_path('axis.glb'))
axis.setTransparency(TransparencyAttrib.MAlpha)
axis.setAlphaScale(0.2)
axis.reparentTo(app.env_root)
plane = app.panda.loader.loadModel(app.package_manager.get_model_path('debugplane.glb'))
plane.setTransparency(TransparencyAttrib.MAlpha)
plane.setAlphaScale(0.2)
plane.reparentTo(app.env_root)
root = app.panda.loader.loadModel(app.package_manager.get_model_path('debugrot.glb'))
root.setTransparency(TransparencyAttrib.MAlpha)
root.setAlphaScale(0.2)
root.reparentTo(app.env_root)
dlight = DirectionalLight('light')
dlight.setColor((4, 4, 4, 1))
dlight.setShadowCaster(True, 512, 512)
nplight = app.env_root.attachNewNode(dlight)
nplight.setPos(0, 1, 1)
nplight.setHpr(180+15, -45, 15)
app.camera_root = NodePath('camera_root')
app.camera_root.reparentTo(app.panda.render)
app.panda.camera.wrtReparentTo(app.camera_root)
app.panda.render.setLight(nplight)
app.scene_root = NodePath('scene_root')
app.scene_root.reparentTo(app.panda.render)
app.panda.taskMgr.add(app.update_input, "update_input")
app.panda.accept('mouse1', app.mouse1_down, [])
app.panda.accept('mouse1-up', app.mouse1_up, [])
app.panda.accept('wheel_up', app.wheel_up, [])
app.panda.accept('wheel_down', app.wheel_down, [])

View File

@ -0,0 +1,57 @@
import os, json
import posixpath
from .package import Package
from .errors import *
class PackageManager:
def __init__(self, vfs):
self.vfs = vfs
self.package_map = {}
self.package_list = []
self.main_package = None
def unmount_all(self):
self.vfs.unmount(self.main_package.mount_dir)
for package in self.package_list:
self.vfs.unmount(package.mount_dir)
def get_package_meta(self, filepath):
if not os.path.exists(filepath):
raise FilepathNotFound(filepath)
gamepkg_path = os.path.join(filepath, 'gamepackage.json')
if not os.path.exists(gamepkg_path):
raise GamePackageMissing(gamepkg_path)
meta = json.load(open(gamepkg_path))
if 'name' not in meta or 'type' not in meta:
raise GamePackageMalformed(gamepkg_path)
return meta
def set_main_package(self, filepath):
meta = self.get_package_meta(filepath)
if meta['type'] != 'main':
raise InvalidPackageType(filepath, meta['type'])
vfs_path = f'/main/'
self.vfs.mount(filepath, vfs_path, 0)
new_package = Package(type('', (object,), meta), vfs_path, self.vfs)
self.main_package = new_package
def include_package(self, filepath):
meta = self.get_package_meta(filepath)
if meta['name'] in self.package_map:
raise PackageAlreadyLoaded(meta['name'])
vfs_path = f'/include/{meta["name"]}'
self.vfs.mount(filepath, vfs_path, 0)
new_package = Package(type('', (object,), meta), vfs_path, self.vfs)
self.package_map[meta['name']] = new_package
self.package_list.insert(0, new_package)
def get_model_path(self, name):
for imported_package in reversed(self.package_list):
target_path = posixpath.join(imported_package.mount_dir, 'models', name)
if self.vfs.exists(target_path):
return target_path
main_path = posixpath.join(self.main_package.mount_dir, 'models', name)
if (self.vfs.exists(main_path)):
return main_path
return None

View File

@ -0,0 +1,32 @@
import posixpath
from direct.stdpy.file import walk
class Package:
def __init__(self, meta, mount_dir, vfs):
self.meta = meta
self.mount_dir = mount_dir
self.vfs = vfs
def all_models(self):
models_path = posixpath.join(self.mount_dir, 'models')
output = []
for root, paths, files in walk(models_path):
rel_root = root.replace(f'{models_path}', '').strip()
if len(rel_root) > 0 and rel_root[0] == '/':
rel_root = rel_root[1:]
for filepath in files:
output.append(posixpath.join(rel_root, filepath))
return output
def all_textures(self):
textures_path = posixpath.join(self.mount_dir, 'textures')
output = []
for root, paths, files in walk(textures_path):
rel_root = root.replace(f'{textures_path}', '').strip()
if len(rel_root) > 0 and rel_root[0] == '/':
rel_root = rel_root[1:]
for filepath in files:
output.append(posixpath.join(rel_root, filepath))
return output

136
source/pkgexplore.py Normal file
View File

@ -0,0 +1,136 @@
import tkinter as tk
from source.packages import PackageManager
from source.packages.gui import *
from direct.showbase.ShowBase import ShowBase
from panda3d.core import VirtualFileSystem, Material, Vec3, CullFaceAttrib, WindowProperties
from direct.actor.Actor import Actor
class PackageExplorer:
def __init__(self, args):
self.gui = tk.Tk()
self.gui.title("Blackjack and Hookers: Package Explorer")
self.panda = ShowBase()
props = WindowProperties()
props.setTitle('Blackjack and Hookers: 3D Viewport')
self.panda.win.requestProperties(props)
self.package_manager = PackageManager(VirtualFileSystem.getGlobalPtr())
self.package_manager.set_main_package(args.main)
self.icons = get_icons()
self.prev = None
if args.package:
for include in args.package:
self.package_manager.include_package(include)
self.tree_packages = None
self.tree_scene = None
self.running = True
self.env_root = None
self.camera_root = None
self.camera_accel = 100
self.panda_keymap = {
'mouse1': False
}
self.mouse_previous = Vec3()
self.mouse_direction = Vec3()
init_gui(self, args)
init_packages_tree(self.tree_packages, self.package_manager, self.icons)
init_panda(self, args)
def on_tk_close(self):
self.running = False
def on_packagetree_doubleclick(self, event):
item = self.tree_packages.selection()[0]
if item.lower().endswith(('.glb', '.gltf', '.obj', '.egg')):
for child in self.scene_root.getChildren():
child.removeNode()
mat = Material()
mat.setAmbient((1, 0, 0, 1))
node = self.panda.loader.loadModel(item)
path = node.find('**/+Character')
if not path.isEmpty():
node = Actor(node)
node.reparentTo(self.scene_root)
node.setMaterial(mat)
node.setTwoSided(False)
node.setAttrib(CullFaceAttrib.make(CullFaceAttrib.MCullClockwise))
self.display_scenegraph(node, item)
self.prev = node
def display_scenegraph(self, node, item):
self.tree_scene.delete(*self.tree_scene.get_children())
self.tree_scene.insert('', 'end', '/', text=f' {item}', open=True, image=self.icons.shape_square)
joints = node.getJoints() if getattr(node, 'getJoints', None) else []
if len(joints) > 0:
self.tree_scene.insert('/', 'end', 'joints', text=f' Joints ({len(joints)})', image=self.icons.chart_line_link)
for joint in joints:
self.tree_scene.insert('joints', 'end', f'joint_{joint.getName()}', text=f' {joint.getName()}', image=self.icons.anchor)
self.add_scene_nodes(node, '/')
def add_scene_nodes(self, node, parent):
pn = node.node()
tree_id = f'{pn.getType().getName()} {node.getName()}'
tree_name = tree_id
image = ''
match pn.getType().getName():
case 'ModelRoot':
image = self.icons.chart_organisation
case 'PandaNode':
image = self.icons.anchor
case 'GeomNode':
image = self.icons.shape_flip_horizontal
case 'AnimBundleNode':
bundle = pn.getBundle().getName()
tree_id = f'{tree_id}_{bundle}'
tree_name = f'{bundle}'
image = self.icons.film
case 'Character':
image = self.icons.user
self.tree_scene.insert(parent, 'end', tree_id, text=f' {tree_name}', open=True, image=image)
for child in node.getChildren():
self.add_scene_nodes(child, tree_id)
def mouse1_down(self):
self.panda_keymap['mouse1'] = True
def mouse1_up(self):
self.panda_keymap['mouse1'] = False
def wheel_up(self):
quat = self.panda.camera.getQuat(self.camera_root)
forward = quat.getForward()
self.panda.camera.setPos(self.panda.camera.getPos() + forward)
def wheel_down(self):
quat = self.panda.camera.getQuat(self.camera_root)
forward = quat.getForward()
self.panda.camera.setPos(self.panda.camera.getPos() - forward)
def update_input(self, task):
if self.panda.mouseWatcherNode.hasMouse():
mouse = self.panda.mouseWatcherNode.getMouse()
dt = self.panda.clock.getDt()
self.mouse_direction = Vec3(self.mouse_previous.getX() - mouse.getX(),
self.mouse_previous.getY() - mouse.getY(),
0)
self.mouse_previous = Vec3(mouse.getX(), mouse.getY(), 0)
if self.panda_keymap['mouse1']:
self.camera_root.setH(self.panda.render, self.camera_root.getH() + self.mouse_direction.getX() * self.camera_accel)
self.camera_root.setP(self.panda.render, self.camera_root.getP() + -self.mouse_direction.getY() * self.camera_accel)
return task.cont
def loop(self):
try:
while self.running:
self.gui.update_idletasks()
self.gui.update()
self.panda.taskMgr.step()
except KeyboardInterrupt:
return
def start_explorer(args):
app = PackageExplorer(args)
app.loop()

5
testmod/gamepackage.json Normal file
View File

@ -0,0 +1,5 @@
{
"name": "test-mod",
"version": "1.1-beta",
"type": "include"
}

BIN
testmod/models/axis.glb Normal file

Binary file not shown.

BIN
testmod/models/box.glb Normal file

Binary file not shown.

BIN
testmod/models/missing.glb Normal file

Binary file not shown.

BIN
ui/axis.glb Normal file

Binary file not shown.

BIN
ui/header.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

BIN
ui/icons/anchor.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 523 B

BIN
ui/icons/application.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 464 B

BIN
ui/icons/brick.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 B

BIN
ui/icons/bricks.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 825 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 749 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 434 B

BIN
ui/icons/color_swatch.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 B

BIN
ui/icons/color_wheel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 892 B

BIN
ui/icons/computer.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

BIN
ui/icons/film.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 653 B

BIN
ui/icons/folder.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 537 B

BIN
ui/icons/link.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 343 B

BIN
ui/icons/music.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 B

BIN
ui/icons/page_red.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 641 B

BIN
ui/icons/picture.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 606 B

BIN
ui/icons/pictures.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 B

BIN
ui/icons/shape_group.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 553 B

BIN
ui/icons/shape_square.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 B

BIN
ui/icons/sound.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 610 B

BIN
ui/icons/user.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 741 B

BIN
ui/plane.glb Normal file

Binary file not shown.

BIN
ui/rotation.glb Normal file

Binary file not shown.