From 095aa9bb683e9d0e176cb30ed7100be738ecdf0f Mon Sep 17 00:00:00 2001 From: sphere Date: Fri, 25 Nov 2022 17:14:35 +0000 Subject: [PATCH] GZDB merging - part 1 --- Build/Compilers/ZDoom/acc.exe | Bin 66560 -> 67072 bytes Build/Compilers/ZDoom/zspecial.acs | 76 +- .../Includes/ZDoom_linedefs.cfg | 18 +- Build/Configurations/Includes/ZDoom_misc.cfg | 30 + Build/Scripting/ZDoom_ACS.cfg | 5 +- Build/Scripting/ZDoom_DECORATE.cfg | 199 +- Documents/cmdargs.txt | 52 +- Help/commandlineparams.html | 105 +- Help/gc_decoratekeys.html | 5 + Help/gzdb/compilingtheeditor.html | 27 +- Source/Core/Actions/ActionManager.cs | 2 +- Source/Core/Actions/HintsManager.cs | 2 +- Source/Core/Builder.csproj | 1 + Source/Core/Compilers/Compiler.cs | 8 +- Source/Core/Config/ArgumentInfo.cs | 2 +- Source/Core/Config/CompilerInfo.cs | 4 +- Source/Core/Config/GeneralizedOption.cs | 2 +- Source/Core/Config/MapLumpInfo.cs | 2 +- Source/Core/Config/NodebuilderInfo.cs | 4 +- Source/Core/Config/ProgramConfiguration.cs | 14 +- Source/Core/Config/ScriptConfiguration.cs | 105 +- Source/Core/Config/ThingCategory.cs | 2 +- Source/Core/Config/ThingTypeInfo.cs | 5 +- Source/Core/Config/ThingsFlagsCompare.cs | 4 +- Source/Core/Controls/ArgumentBox.cs | 2 +- Source/Core/Controls/ArgumentsControl.cs | 24 + Source/Core/Controls/FieldsEditorControl.cs | 268 +- Source/Core/Controls/FieldsEditorRow.cs | 106 +- Source/Core/Controls/FlatSelectorControl.cs | 2 +- .../Controls/ImageBrowserControl.Designer.cs | 1 + Source/Core/Controls/ImageBrowserControl.cs | 209 +- Source/Core/Controls/ScriptEditorControl.cs | 2836 +++++++++-------- Source/Core/Controls/ScriptFileDocumentTab.cs | 55 +- .../Controls/StatisticsControl.Designer.cs | 22 +- .../Core/Controls/TextureSelectorControl.cs | 8 +- Source/Core/Controls/ThingBrowserControl.cs | 13 +- Source/Core/Data/ColormapImage.cs | 4 +- Source/Core/Data/DataLocation.cs | 4 +- Source/Core/Data/FileImage.cs | 2 +- Source/Core/Data/FlatImage.cs | 4 +- Source/Core/Data/HighResImage.cs | 44 +- Source/Core/Data/ImageData.cs | 8 +- Source/Core/Data/PK3FileImage.cs | 2 +- Source/Core/Data/SimpleTextureImage.cs | 8 +- Source/Core/Data/SpriteImage.cs | 4 +- Source/Core/Data/TextureImage.cs | 8 +- Source/Core/Data/TexturePatch.cs | 3 + Source/Core/Editing/ClassicMode.cs | 4 + Source/Core/Editing/CopyPasteManager.cs | 55 +- Source/Core/Editing/GridSetup.cs | 8 +- Source/Core/Editing/ThingsFilter.cs | 2 +- Source/Core/Editing/UndoManager.cs | 16 +- .../Controls/TagSelector.Designer.cs | 7 +- Source/Core/GZBuilder/Controls/TagSelector.cs | 6 +- .../Core/GZBuilder/Controls/TagsSelector.cs | 12 +- Source/Core/GZBuilder/Data/EngineInfo.cs | 9 +- Source/Core/GZBuilder/Geometry/Line3D.cs | 8 + .../Core/GZBuilder/Windows/ExceptionDialog.cs | 4 +- Source/Core/GZBuilder/md3/ModelReader.cs | 24 +- Source/Core/General/FileLockChecker.cs | 4 +- Source/Core/General/General.cs | 42 +- Source/Core/General/Launcher.cs | 2 +- Source/Core/General/MapManager.cs | 58 +- Source/Core/General/UpdateChecker.cs | 74 +- Source/Core/Geometry/InterpolationTools.cs | 2 +- Source/Core/Geometry/Tools.cs | 8 +- Source/Core/IO/ClipboardStreamReader.cs | 41 +- Source/Core/IO/ClipboardStreamWriter.cs | 17 +- Source/Core/IO/Configuration.cs | 9 +- Source/Core/IO/UniversalEntry.cs | 2 +- Source/Core/IO/UniversalParser.cs | 16 +- Source/Core/IO/UniversalStreamReader.cs | 6 +- Source/Core/Map/MapSet.cs | 2 +- Source/Core/Plugins/Plugin.cs | 6 +- Source/Core/Properties/Resources.Designer.cs | 14 +- Source/Core/Properties/Resources.resx | 3 + Source/Core/Rendering/D3DDevice.cs | 4 +- Source/Core/Rendering/IRenderer2D.cs | 1 + Source/Core/Rendering/Renderer2D.cs | 74 +- Source/Core/Rendering/Renderer3D.cs | 2 - Source/Core/Resources/Actions.cfg | 10 + Source/Core/Resources/FixedThingsScale.png | Bin 0 -> 1595 bytes Source/Core/Types/AngleDegreesFloatHandler.cs | 5 + Source/Core/Types/AngleDegreesHandler.cs | 5 + Source/Core/Types/AngleRadiansHandler.cs | 5 + Source/Core/Types/BoolHandler.cs | 7 +- Source/Core/Types/ColorHandler.cs | 5 + Source/Core/Types/EnumBitsHandler.cs | 13 +- Source/Core/Types/EnumOptionHandler.cs | 7 +- Source/Core/Types/EnumStringsHandler.cs | 13 +- Source/Core/Types/FlatHandler.cs | 5 + Source/Core/Types/FloatHandler.cs | 5 + Source/Core/Types/IntegerHandler.cs | 13 +- Source/Core/Types/LinedefTypeHandler.cs | 5 + Source/Core/Types/NullHandler.cs | 5 + Source/Core/Types/RandomFloatHandler.cs | 15 +- Source/Core/Types/RandomIntegerHandler.cs | 23 +- Source/Core/Types/SectorEffectHandler.cs | 5 + Source/Core/Types/SectorTagHandler.cs | 7 +- Source/Core/Types/StringHandler.cs | 8 +- Source/Core/Types/TextureHandler.cs | 5 + Source/Core/Types/ThingClassHandler.cs | 5 + Source/Core/Types/ThingTypeHandler.cs | 5 + Source/Core/Types/TypeHandler.cs | 9 +- Source/Core/Windows/AboutForm.cs | 3 +- Source/Core/Windows/ActionBrowserForm.cs | 66 +- Source/Core/Windows/ChangeMapForm.cs | 2 +- Source/Core/Windows/ConfigForm.cs | 12 +- Source/Core/Windows/EffectBrowserForm.cs | 76 +- Source/Core/Windows/GridSetupForm.cs | 12 +- Source/Core/Windows/IMainForm.cs | 14 +- .../Core/Windows/LinedefColorPresetsForm.cs | 2 +- .../Core/Windows/LinedefEditForm.Designer.cs | 35 + Source/Core/Windows/LinedefEditForm.cs | 273 +- .../Windows/LinedefEditFormUDMF.Designer.cs | 39 +- Source/Core/Windows/LinedefEditFormUDMF.cs | 289 +- Source/Core/Windows/LinedefEditFormUDMF.resx | 2 +- Source/Core/Windows/MainForm.Designer.cs | 35 +- Source/Core/Windows/MainForm.cs | 91 +- .../Windows/OpenMapOptionsForm.Designer.cs | 2 +- Source/Core/Windows/OpenMapOptionsForm.cs | 101 +- .../Core/Windows/PreferencesForm.Designer.cs | 51 +- Source/Core/Windows/PreferencesForm.cs | 98 +- .../Core/Windows/SectorEditForm.Designer.cs | 6 +- Source/Core/Windows/ThingEditForm.cs | 12 +- Source/Core/Windows/ThingEditFormUDMF.cs | 66 +- Source/Core/ZDoom/ActorStructure.cs | 253 +- Source/Core/ZDoom/AnimdefsParser.cs | 2 +- Source/Core/ZDoom/DecorateParser.cs | 12 +- Source/Core/ZDoom/PatchStructure.cs | 50 +- Source/Core/ZDoom/TextureStructure.cs | 14 +- Source/Core/ZDoom/ZDTextParser.cs | 18 +- .../Interface/JitterSectorsForm.Designer.cs | 2 +- .../Plugins/BuilderModes/BuilderModes.csproj | 12 + .../BuilderModes/ClassicModes/BridgeMode.cs | 2 +- .../ClassicModes/DrawCurveMode.cs | 145 +- .../ClassicModes/DrawEllipseMode.cs | 127 +- .../ClassicModes/DrawGeometryMode.cs | 122 +- .../BuilderModes/ClassicModes/DrawGridMode.cs | 291 +- .../ClassicModes/DrawRectangleMode.cs | 184 +- .../BuilderModes/ClassicModes/SectorsMode.cs | 2 +- .../BuilderModes/ClassicModes/ThingsMode.cs | 4 +- .../ErrorChecks/ResultTexturesMisaligned.cs | 2 +- .../FindReplace/FindLinedefFlags.cs | 2 +- .../FindReplace/FindLinedefTypes.cs | 56 +- .../FindReplace/FindReplaceType.cs | 6 + .../FindReplace/FindSectorEffect.cs | 38 +- .../FindReplace/FindSectorFlags.cs | 2 +- .../FindReplace/FindSidedefFlags.cs | 2 +- .../FindReplace/FindThingAction.cs | 15 +- .../FindReplace/FindThingFlags.cs | 2 +- .../BuilderModes/General/BuilderModesTools.cs | 2 +- .../BuilderModes/IO/WavefrontExporter.cs | 10 +- .../DrawCurveOptionsPanel.Designer.cs | 32 +- .../Interface/DrawCurveOptionsPanel.cs | 17 +- .../DrawEllipseOptionsPanel.Designer.cs | 65 +- .../Interface/DrawEllipseOptionsPanel.cs | 43 +- .../DrawGridOptionsPanel.Designer.cs | 79 +- .../Interface/DrawGridOptionsPanel.cs | 55 +- .../DrawLineOptionsPanel.Designer.cs | 75 + .../Interface/DrawLineOptionsPanel.cs | 32 + .../Interface/DrawLineOptionsPanel.resx | 123 + .../DrawRectangleOptionsPanel.Designer.cs | 28 +- .../Interface/DrawRectangleOptionsPanel.cs | 33 +- .../BuilderModes/Interface/ErrorCheckForm.cs | 10 +- .../BuilderModes/Interface/FindReplaceForm.cs | 6 +- .../Interface/PreferencesForm.Designer.cs | 11 +- .../Properties/Resources.Designer.cs | 132 +- .../BuilderModes/Properties/Resources.resx | 29 +- .../Plugins/BuilderModes/Resources/Repeat.png | Bin 0 -> 587 bytes .../VisualModes/BaseVisualGeometrySector.cs | 4 +- .../VisualModes/BaseVisualGeometrySidedef.cs | 8 +- .../VisualModes/BaseVisualMode.cs | 28 +- .../VisualModes/BaseVisualSector.cs | 25 +- .../BuilderModes/VisualModes/SectorData.cs | 38 +- .../BuilderModes/VisualModes/VisualCeiling.cs | 33 +- .../BuilderModes/VisualModes/VisualFloor.cs | 43 +- .../BuilderModes/VisualModes/VisualLower.cs | 3 +- .../BuilderModes/VisualModes/VisualUpper.cs | 3 +- Source/Plugins/NodesViewer/NodesViewerMode.cs | 2 +- .../TagExplorer/Controls/TagExplorer.cs | 2 +- .../VisplaneExplorer/VisplaneExplorerMode.cs | 9 +- 182 files changed, 5421 insertions(+), 3249 deletions(-) create mode 100644 Source/Core/Resources/FixedThingsScale.png create mode 100644 Source/Plugins/BuilderModes/Interface/DrawLineOptionsPanel.Designer.cs create mode 100644 Source/Plugins/BuilderModes/Interface/DrawLineOptionsPanel.cs create mode 100644 Source/Plugins/BuilderModes/Interface/DrawLineOptionsPanel.resx create mode 100644 Source/Plugins/BuilderModes/Resources/Repeat.png diff --git a/Build/Compilers/ZDoom/acc.exe b/Build/Compilers/ZDoom/acc.exe index fbdd29fc88b0c6d242e05354a4264c6a6ec16cdb..a295df1d5995775c500cee526358f6410a266d00 100644 GIT binary patch delta 27304 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

yZFtDsTuha|1HpLIeV2jNw*b> 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 delta 26497 zcmd^oi+__v*8h_>DWRk!Knf{s>4mfuC{kz(t!*)t-sBoAO&cyPC~AzT$eRGVr74@% zZ3soyLD$!1wXv+rdRcKrLBY~mpx`2lE-DHrxav*}U{QpiUGn>$dD7zgzQ51!5BTBd zJM%mU$Y z>}Ex}B8M$klq+=X&x+~M-!+3k2RzEYQH+_^v;dE7!0o_B;Aj6#l4QDR#d61Tq*bWn z5Go|ei0Cw%5iw37y>@rR#t4OxT~bbrIGf7Gs1gV9)MCl^Wh%Q>b&KmPp0%wnfId`W z)FHK4^3E~pLOCsXH}I~zCCTddBHJ_RsA>_yPK4TyD0ArJ>?7`Ah4zUqPt1vdG&irf zdNRJ#YO=N;Mq*&0XOcRKie;!5NsTik$4m?V`g$l7c!Ah^OCFEXy53$VNw#I%O;TlG zxTPZ*qHsV^zE5WsrM-J+*kAH|qwmE9#v}B0aqaq=pJ;{?Rgw8eMo$tR_lK3+# z5InsYK>_OA(}K$KbCcPpQAVLb2xhQUx0Ckx#lBF8w}e8Wa8sQ3NmBNyN*i^Ija1K{ zUnE+@$CZKKAuEE5BzOG}R_X0K{%Df+FGJvc&mB}aBD{YOOPLpS)F`?k3L+PnECU|rEkcgDzf?ko5?2T1YH?B153XY2uoj2x7nMPl5 zSfuEEK@}UXo-}9|($P@1RBd$i8evZ*Ms@pnJaqdw!sbqg)*OmG-DZ;9X_O#Y-9?uv zcBt)&P;4(Ux-Fu|I)X^H@TfHs!pln1n#R`m2CSmF(>aJ=bV^b{#jhc; z&9vJjd1C0DPe)yl+g%h)XA`5Br8+=uYokC1qC<`JDDgL7RyGY1Lb(q1a`ZMuGMhDI zEW!td6f3N+?HqDOq4*Ws98;tyVn<_gQ^`~%M?om|GU>51*}YyJ;f!?`k>N^?vECRX z8#}aI@eI3fXs%)g^9@~VhG@{?xH5td8cEDJ>Fi%D_E8`bx`bsXj7t%S+!$a zy&$w3>=FE5cnIaL1To(WA>9Y`(8EYMrOF=1$NVIk=6@e!hBw_03c)!|+x$4CtR6^7 zcj&9^4gBJdp^!bDFCjq=XwY@$0g5zde3jkBkAfoIY6Vdq5y|YVj&HL&o3Ch}=yZ1u zHirc&X9>DE*XM$jzWItn9a53e2696xvgp91fg-B@A`(<%wYJn4Wbz=9MTJyk$8t^M zwN2gV2fNOm!TC}mu3Ng;|I|wOi>5s$2^yLEZ?w25b4IbGuv(piT_CJS8?4=yYW@)D z?CEx;J2=Rx<^PRjZ;=hUyZU)x2!9&vX8TZkino{7 zP-z2(_rusFYn>5bGjji-3Kx}^AdQ-1>X`D-8ohej|H)}ECJ&ohUn8mAxWYl zU7oT8DEw}SVb|JI`A-nmYULd_7-*XcV5y?*7ng{(*ZQ9o*`m3QG+UdjgV}I!_R020 zzI&x>z&>Uyr#{uAij^qizXyTss7#*#`WreM#AhQfFy6LD&b~`I zJBX#h9}jvy5<$peRPv%pkd0j9CHt**ospLaS^Zb-lC+`7z>0^*E;mer(}~ecDwev= zDnlxI^|WMABD{j9B~yMk1LqLC0>kW;tD%t9>Z8KC$tkH#1zq*uWOsJM)pu_wN`Sxv!jltU%*mjS18yy=kJfao5PAeqM3~|NMu6lIy9Yf-eh~ z%%hSCa>)z9UzB7cV~4tCQh`#Q9xibG9!aXw?w|BLRBiF*HewuAdyBT?ZNtB4Jn=Ii zkcVB0Lu2973ef`pY4mkv_9@;ukeTX;=&3%CG$4_r%SH;<}PJj}L? zS~$rljHNl$Fxq`6AvDdFC--p-l4-&{q@3^c+YFdfVKPBB%#fV01j}(NmK!wxVU~Jb zlBCwM1W#!n?_0s<8VX0w{*KD(0wXHTp*89SHa95vH1@0^Y04!i#;)VfO(PblRBa#1 zpP(0aX`j-5zdgO2zf?teybg;+)WN_fwz@w^%3<`@%tOgZRV$y1TxjS-8GicD_| ztx4P!2_g3~BY9*`MOJro70j6Y$J-iqC@xj;JoCq;7~k!sny?z6g}sF4I-)~sjeHRq zK(zLaa-*4#W;cz_o$xXdCZlD-e^w|FsXY~HL>fe2sg3T(W6{cQ6MR_Mi*M6 z=Vva2Lf$fEXce{2&h=pBokk0ZE6y{u-4<^z9wr15N1?c#23s>B%m%yEuCJ3u_%F`64j z{%kOR-h5^KB;EjmKs?yg1a|XaEW|XDoHO0Q@s5AGgQ?E15#(iGKqBNVDl-qB<#4ttTohcJAVS2yf5fN5Kl6!`&D{{1U9y|1^>J z%H;FIa;(^-54%Y?`;kkV__V6UN>qki&9WFyYn_Ps1LdVKtJ_q}p!Y zSI6ci#*Y;v(wPM-gtQL66lBN`sId|}1g11*nKv=j_0|+g(!NnA|J!*{ zsXLAQ5;lR9SLIcgO)mZ#tTZS$e9FxpGPnk6OFeeF! z!+o87k-c`OeJsC!4ysCJ>8V*aQyoTalaAJ+qwVAQIAmeS{zPLyCj|> zIrE=*=X=Rls`M>BUo&8HLHIr|WEl*$y)l1dGsoQStW0sQ6yl{khYU zsgp4wnBjSoLu(3UYAhv+#0bpnADVHYTp}eqlu68dx;%ni-BsT6?(;_9VQloX4`OEV zmZ~jgzO|y?)6bNBcx<Gv9>T(HY;se&x2MAla!8IW=bfZ?T@iK48Uc4D}c@dT%Bt%2d3zRES$})uESjQ8tcuqAU%{S$5^m%Y;CTGG!<# z6jX=35oR^#pzKpEwT3{VSJaP3RN)+KspKzAre=p!Bo_a?X224MIH&h(SkHTq&Z}Tg z=1M+|3IrbDuL)ZAv~fa>*pqnI_hIEYxVn;C;TEjc*3y$^Z)vd7uJ-=j`w`zPCUfk( z$)<)lqbZyJ4r3?00)Qp$CQG92-ov*M1D?qe(u^)LQK6z7^o(62Hs*>vt zI)~xxNh3L<`6v|jlqUz2?t79Yexw?bSHo*~do8vlvM*dCTcl^L!CfT$kz<&JpDUCk zoI>b)CR81W$nNx%C)Cw;yV?G<;mf9@gtye_U7GAEF;;j>GiY0g#|-{Bw1DBp7or|_ zaH?~;aP;*^^_Cj4uUM@Ghn%A<=&?fH@ulc7kHe@3bb-k@*6_?R>M@nDDe1}Tk>k;7 z-fLmj^n_f}QYv{HdkwEdL5#ZR6==%su-$^6v`us9y4sr(uFMyyiqR9L8MiXEt zA8-+WLB|H>g6lN?%@?RTgF7G*tQU*e#qI-{{?B2qGQWxFM!mwR&xeK_Q69&>gn-t< zkEf%GiYN>J4e6+yYAE=r{#e0J4sF5p1{zG$_;114YR&E}_)PmuXNCLhC+^N^W-K$N zf;WyHp>^kwkTZezrL+4p3a58~rM3A~!!Yd|CA$*LyemzT$_l=>)_>bCRQ*CpTEL$S z)A>V=T?u>`JDV|T`jf)=H2w-uz{OaqMW?Tl7o6Eh%nrN96lYX9PelSbyOr#w@e^IY zIw$)B{#7OEz7R{N22E>C$a{!CcM)n*V|g$Y-C~s|)^YT>7yj4P9C9oR&l0JQ`LvMH zpxs(N0Sv8y0{#T}@loo50i5bc0Fm<)ucwUbgCGPZP-^4D>2-#^VdPj>S^ z;+;QEQ`_ts|0=NKj8ZgF{Vhv%=%L}8`CycXA*}^#*lf3dC6V1j!9tYYGYdm8&=Ja| zBOY#}**|c)-*u*<+wY?E_wtD=Ijab(GrC7beh1|wbKpI@6gU#zKs$!H8?q#^{a(x2 zXC$_TKSUeshD?RksfL;B#zHB=OJ?3m>hXV$^_7JmWDjPp$^7;V6$z+1YQbCR_tS=%8XMG>$Ywr&BZ8>`7yd*HTbhxBad_ zgx$i=(~A%yC{}m=z4L{aczlw1(C?8##_pd~pxJpE^7xNMfSrM5-IS0@ZY|B3hm~a& z7M717o8~ZDSpE|n#KQ7{n+&dV$#@B^(Nyyt@VsXJKHlZ=a2YbfWAQAJ{^mgXY0)l& z{~pvu1K8h)`7zulr;taMxY&R1y#8KLI4*`~5p$wMH`nG#wnT4XwPqeXv4W#P#!&G9XK=+4RG zlQt(I(Oa(JS0JC6yYPzL9ahlKL8YJxPM*BTL^PqbnCeJfJOVau<`V}f=Yf(;{WlmW zZXV;9UUB0XxQMU%R7l{z7rEJ2u!(VM^VeoLqpR#Q_(HZJYm}}K6jp0BAB{y#z{1w@rnTSiu}rkj<`0g67+BzzQ(7lfAvZP^=dzf##ojQV@BT!LjWm`v zC3y^qJIEPT#;;+SBvVH@RXiZxjO@-SlO|>rfvFV-R+*LFMA5uIBDb11p||ig=qrrE zm00wl3?#x(6X}Zj7h}$UgtFaK9(tA zZ&c_Q?GBbXV%@*|^Wu+5DqhNdpFMh6rRcA{A@qP)2kjw-@`nI3Y!?Fv>iqfA z@Zv|Z5hmFq!gNzX=k0CFfLVuB6yoH)%)s-63@kPWCy6+p48>4ZLANtCyE9)!Cwg`X z=lpc;G}X-4fUA$lP+>tgR=w*7c{I&BP@*Wm-HV3VF~yZ3JJgRGW;bpunYz37UPUYtmHGWinbZ| zn&=E^5DZT~2lUaIpmu-m^Qy&*g#VHc2I(NF1`W(U1uH4|Uc31TD3I&Gkk)B>;T=f< zR%=gb5Y~aYi*H1&DNBPm5TH}CT>jvP)DNw-3VxEU%FS^7Jr48*pRHF6oE^Se@cDX! zpiKrXRyLcd0vwT!2TSkwfuXd=bp}04Px95}=stbLmjmTO{{pBAxfrWV8W(5{ILo^BSm+#`^^< z+SYPC*ib*lh<+?Y9?g5)^~7|nj{~Cnrt$Uv5Z!m5f`5$_8@J(mR`UhtFnosAJBHX! zqG9|3HKic1UP0?;*wJ`LSHZ>gv^}53XP`KG=_RU4UaNLzU*Nw7E76T7F{ng0?gxQ< zu=}hF>~0+6RXJk#NTgJA9YTC~Vk7CL6Cr%gH2x4#(i9)0+W0D3LWC4pDc4{Z zp8`Uwb$)ZmbuQd!=NMZXl{-h0@x4@}h>C<&azV8Bn_O6Hr~7&_e1ggcax;Gw^g;z4 zVnwX4bJhAAP}zMOW=B>$|6SN>}91rt;6mjC1#^Cu?ji@jxs@-^LG9Qx7fDJ8vLGYkTh6FDlj68KacN2qT~`PIiF7kC$IPv#VxKl5QJ_;x`Jn@NZw=| zOwk7ER_;7bqe0fkbmzQk95Mc&N6{ksip3L9(jp&n^6y|i{7vE#!M{+7Ru6EQEVxvM zDG!sq!eDWRE+laA-6Ey7dx03=`{Y(k?r+8KsR7Ht8BV5}|3>h}cWh^LH3aeA5X(Ek_$t|S6h9wH?H-WrW>F3W4uI6c%SE{0Bo-b!;k$4|l^}{o zVq?P26^tBz(+4y?k!8!`h(6qmR`AMV1Rwqo?n5t2F4W&=2D@-StR>wig9aa)Zxb@y z=)otCk%AyZvZ%g&IJ`+%>QqQ=;XcR$q3de>KVi16v|X0f|M>e5Mpo+~_H5xOR{1OgV$b>m=f($VC#rT>|!h3`KFGvX++WjU-`7L=Kn$Z3@1>%wk zQyI93&>Xl3Y{9>Fcg{ESsc3@yp5c$*f>!9!3bECA1|pgHGmul>YIKdj6)$KYFcsNmUX2BZnKy>Bp}p|8 z8Z%DnzSqIMtN0p3R$c_IVbAGYZND93XgNd;uf)c((i!tzOOFZ_|BWbVW?9@V)EAiffKe2p&4Ea1049w>ZBu@yZK14fukEN*QRhp^R*~P2gnz?`AT{e z7MS6qwVZQ|dtHXSw{$J%r~gJpZSO%D{7w=(kV)CXRouZlL@s|7n_?l@JrK-xjA*BW z79#t#Bw&A|&WUp$Z-vHvEu!Awz82ju#(gcup>Kt4R%h`bQ=Q{ep#NWi?zP6&< z{~{KHIBO4;Zz!S<<&EG?PN0G>5>?aZEFWdyU=m?#POAo;=pCturJDp;chdKCY?nU0 z<(8qJV;AYKiXh9&S2eP6rsRl-57=#{w7KqgA^$jj340Eb`Kkg9XvYTKe}SGRz$wA? zXsYeEaVt?~1Wxduuz~X*qwE*tY*n>=R^W3!>@?eJDju%KurBCvs;ljD{j@sb_p+hI zMMDAslrmDOkC~nj9)p=HfK*k6jLxTrbfMJuv9{ZA3eWo%zyJTt%p zYl7yO@K|~r2a=GQFU0mDa0kB&A8-PT`_BoWsxAhEdkfkS`TmiKC4y1N0lJyhOWO<=TrAuk5c z&>AIwX9&d_{uW|VRF9+){T>MRI+yVwgeQ(S+DrV;4vnRuux zs5J9zh=VCyjj$^!`O-r|^Og3|{3~#T zTsu%cI~1rbIOr@6Mc{vyRVjbAm7CDmH__EQa zH$f1Xj&0emA%0+-U00hwi6nK5MVg1wM#vH<>_clY$tr9csGVyM(BMT5bC-=BN(Ice zWwO#%vt4C(M4##=0(A8emRz1*^P+eS46$niQFaYZ;ncM}dRo84E1c2Ur)KhNxu{O* zT>?dmhTP>;yZ?qY9Fo1q_`Du8N>~;xvv*>cxYJIuXUa#-DiqA!MJLIV(9KW&_8>Id zM!WlvutK>Uip_<8!V)8-qFb-HkymT&=IU`6xR{Zu`S&bTZg35S`FO?cF?{d0(#H-@ zqOkEqx~Jty6egZ1OgvGTcv~toG73_LRb1vsrOT0tFc6168et9HBbkctP6)`XOq$7Ao`y^mOKiDyIq>04x?<*U>3)xff@3l;IVM( zm~`C-)c&nG*frPXIMYG0h>rkCXl-U_Z5DrLKejFBsedqve(Iv434!kXx(vtS{3S+> zvkC?7;a?ylwALj`{FX|b2$y&_Tw?OTwUH$lQ{EshfWepaI@O*!gQqSB*I4D7XY&o7 z@*Gc{vC2D%?ve#52tPd-TxeAxl~*KD4Pd$iBWbJMx+;uXgYm80mE|8IR|wce;j;aLl0*9 z=q`-D<{4lJ`u7LPUwW9DEh@ zZzG<6MWWqiAL|j<);x)1_WYk?g?gVvUM26uqEK9HyzD#4&dwTbj(~ub(BN`@0sV^R zTliWf3gF(OkuwzK75z0$EKm5^z(KE8qhfwPrUi@}{y0|GoUcQ(n93yPU-!`EslVQZ3NkKIo`tju;_18e_VWNw+9fBwtM7DZ7R`HN9 zRh_4ZiUi&Z6CQMnZ6dBERomF}KmwN|1Lg!-z zJ!_+RFEwNfSXbLKc^nF09sEtTE8xwq$A`n1YTHKYXobiSH(H-1CDFM)#@j*XNLz-G zL{E|=QnG(FDlF*HHh&7HVN3T7#;4?>UdZRCtH`_qKHG1=lbg?_WA`jKAL2-H^JvE~ zOujjMN6Fj5HvHGH`l{l$VUG6yn+iULlPCX|NW^L-BKr#Wp<4e5ywg_+Yj^gM><>IK z#ZEW+rQSqc$M;gAc8r8V>O#{_- zT+X+%&UyL_%2zn@wYza$(b7+GR#4Ph`1Jjd!hs*YxLDu3c%w|58x~72>y?=WJHmu3 zSi$`GaWdgemTE7q1XS}+p)GH3nI*hcwn?7~314RG=O+~sEiSlVxPg4V+9RgGe3dwV z%@5_gEe*yhGc5WZx!@wI&8g-+?Bx7$iFty-B#cVi7UWxcO4WaY>3Nn0xweBPm`A&a zqTsN$=`xaqq9=C!_r!PJ54wY@hC98n)G67aL(1q^nmZff<@eTvM>Z}QqKJIIWy#GE zrDF{@z@>PURs$)7~-R5M_N>12dD>Tw-@@o`k{spItF9J31l6Jj`D z>}Y7q8TLl$!Y)NQ{GR7axyT>(vdy=TS}Dsg#p1>G5Pfa2U6!*~5=Zp?Cwt&GO4Y5U zYO`Hg$8!aLLtQNvRFG1ltGP0ZsW3Z?4t`svnBer@U^yk|EjHyTVTPmkvSF1Y$II0D zbU{hfnbS;`2f31EvM(^ksp9#}Tp1r$QSvW`?K-#_d6fQQh^A00)%`;>M`rmjSi(T~ z%iw&&7bNvlnPsX8*oS#q=8)&1Tc|A+c*2S%e0i;X z-P|h45o4B}`Uh{2kEYVfqDENP`Zy}%U7#i&Tg=4cHod21A)CF>SV~iZ)V}KH<^M~R z_r@GYmU{)x%sVO;mrA%^j}M8TY4=BBS3V5$vz5>4CuF-8rW7WNx4^=U3ypej*S(#3 zOxlr$aPhE>HSP<?Em0fG6I#j? z8_Sbh%Gl+qSj9dTZON!E_+=FV<)N}j9H9^|++bGOW>;bDC6tSPpgY4#Tn{%bDE--b zt6`VuCt)yMUq^T!H8GFH=xRc;cQcVvyQ>gkDlqsJ39oD`)l$P$Jz5W<3}D2k0SJ`c7K$aPrU;6d)QYs$smZb zCb_5*oL%b#gX}8>-EWhLYBz6ziM+XlZ0mS_oKsO2`Q9w&6?|;_m0f95pD{^%=nv?T zLtSSh&3p$QMR}+IU*x(QEFH5^GQW11vsC*Aejd7JFqH7`0VQlfhiG>rflp-Htx2Ov zcJ~2edE^h6YF;4@+RZJfzhfRdV@(<e`vEo%aP%E#?Tcs>Sx>dIN1GL1|b+My{HIY)`55-fd`E_CsGyorOO>`;Cpr8Yd!QOvxH$EY{SvOdgS zU2MvtociBY+REk?<6;^gO6NMHJnC;zYH7zz3^fv=1Qp@(+>+ZwM*R+cF-pQuZW?eu zgO;#7lMZ~UZRXo%R#x*3c=6HVO<1GwfKK#k&)XI3PfMmL>e**Ya>Nx(e2L1wkS~^= z+U6h898eu>sMCNzAQf?jBu1FO~&YvX7wH z?fIFlH255fvf_fn^_L2MXt)JZuVlWZ`srb51pm?bnXd~%>|aU*Pr(hWzLsTi7NOq` zHjG7|onJayEJLmJUsT!Vme%0z=QZ_>)}iWCpmgmg-<@Blbd1hVc$pl8b699Pms0T6 z*b$`?y0Dg#xV-)o*zbJEwSrnVq!&v}{sO{&eUbGyOdjBun4eJgx?rfca5w0{c5gqq zwO<7vAri;RtoWczdDGw-?f!@?m~LtBL)sHZgq(RqDcVWq8oU^|PXWr^R_qk@B^;}c>;IlNcl4fCHNujjY}ZCFU`;)&g(Bx9?x8N(KS{$(Up^FJXB zy+Ik(wq#IZMf}oVXu3^Cr$0mK4F<1pp`n}|{9#a+7W{>ht@YfOPd!GfzD;P)h3r%K zYO(oAFc+F}7YZfgYPj2_lpMpMlzWqet_Q?QZ?4OH>J zj=^Vs_rbvh!q;2T(~5e3^Oc4i6jf9G9r(?Fg)fB^R4slkL97~Ly+7fr9};1|g9}8O zwf+Jezm888q*l8!{L6|#HtF;P6TYh0f^ebyLGZ(|M8EUj0^6mdP1>V6aM+c}5|@v4 z)x%NIC(DK9Wa>vf{+uUF1M*IMC(^C`gOGI671< zlCVixt;IXm2{HWr9iqGi?=r(ZxJiShqkXuApQ5}pnpq@wT^c!8N$mZ^whtGeY)?T^ z?JLn%PcH5FdQ_rDYD6c#&tO8YUFxS_jJVTCQ8*@SghY~9ym^%eoA45TZf;^-cT6%2 zl7-3ctnIGEZ@;$5{gCz|i@LMW_V0K|Z!+_LVHI9!_C)cWNPsB@BHiiu%uw6yBktl` zgT=N-F8Ug@gWGGllw-9vq>7bpDCY;N+N1oT1rdJ(A56*$WRm*N=m7uDiP zB(nGfkcDlKxHXIf8&Q5(xI9y@xJ5CQRjjx(scA0mnaz-@opJU`n^ICr-0?j6)Dz`S z#xm+9_U?+Yie2pDid;nkGu~CMIKfulRf&|&yT&8@=B|Vas)DCu&u^t4RAEKan)7;? zt23*gY1ALFdkFJ{e#0vx+`%3=_1eMa-HorGvN$&i?%w|YDrf}-t_5Ms;hn}ia6|w( zY|>|9Ts(vh5Vz#5);&S!$*J1Yi^yWfmyW0Y1y3d~tWLoM>=K{IRYHgC!ri0dM6*5s zJ9sc*q~5t|3%<%VvBZ03=o4iAJ1y&H+(`w7JbvjZ$HL;gVdYdLA7(b zn07>o^~Yo~mSCSS>nSMRzZy-2R7&4gyzv#JN1S)kJ&JXFa~m~;I#(0QdHpGTt0#5a z8f9U&qdjy)k+A0}w#6PBKajse&UXytZ)Kf!W5qadgCFqIF3fgZrkO%I$t6Mf{iO3W zdZZOax9z-4p%oNDxY>eYE6cpEaK4%gg}n6~MjAebr&HDe9roDWwq!Z$S!9KBMZw)7 zSJUka4#lOua2;us1)uLIv2;jm_kD|9C2~O>6@;Uc zCw=fAhSRZ&PjksCmEi~Q!BtkNRi9Px{+f~Y$_4z$GdPcGLtXg7VQnWOZw$SX>U6Dz zifaB(lvm_xT*yMp#pg)hWiW9Eb?Y0%AyC)Z!5uqMCKBfXb3iS!kx1|BsP-75?>aYF z`$m)c6%d;F0ikUjyzZzQ)Hd@sCgjDV2=*gXhJJBAIPw@yKyqBj!<;e#)&y0CRFqA- zWr}s{SF~b3Yvv26D414>(*Hxaox}c9xUF)ZL(5}-QQbnhwm-^ZQf>H{LAPt*Nkm&M zdF})3M1{QHTmMpg#$me6GoP_jm9GX>c8RR@mqTDLZi|fk$ohf z3DXTO_9{0*N4?^w_VRZJ$uZttB--ap_R${z@y4t}=!tO*LDWvqJt`%e{NPB zPHB-lW*RJC{{Dj7J@n@xVBPI2Q7AB6PNsFFx6IIPV~MK@29b^nR1&LO74KRFDu?#D zHbm_tcsnKJ!vY;cdQ|j`B`|*JO<6_s7mLlB4=6WA-%9q3dIf{VYe{QIHC~IR-*Ske(CDklG6g2j;_J~c%x;UeBNtTk#^Ed0FyDRh?g`%@hSz0QR zJv9cN-iCT<0v4wkElXSYo9JRnNN6M9cXPL6L}Ssb?D~I=bSbctZ!K*xb2qdFnF0&) z6NTw4ZEBd+Q`$)MA!nl?>BeRq4_FrbO@1=-xuO(Z`x_N1ZSs~jZ76M|g?E8){PhO| zQQjWhkk1T>KQtt}Tt03q`C2j@eETHNhYM{@FbIC%lO#g|Rc33GRk#L{i^~5I3_m=A z{eg}8Q1+TUghH~qBJt(P7K>`%!eu4hm!Fk&6vZa7Q)JiwhsKj4u9aq?f<(Z11%KN%Bw*dzY#4$p^r2E-?i zRTy%9bfY|-!%}hg^@#d=RPO7>hGF6;b^)J^j)e``jX2nsD;OEB;FV(o+)rZ+iY8n5 zM2t*)HV!#IxxpPSsj;|@f1ve`N{^$|EPx4oy z&@Tw|l;129Pb9{ZK_d&C?hFfyO`znj#lR^n>QAy$(rhHjC9&(3{6C=SvKanv@F;Q& zQYvMgqO4dF$bTG<;LpykizQEcb=@=_^_OVWUeNZaY^>;EgTlrv4`;Yqe=EC&2ly=* zg#7aX%OB^6vEwuU!~8y(f+rzAP>#}I2FD@=3gl;)q7;}cKjT7-6c{TTWgxzA9Q`E> z;xR5<%W!Q+r}%xD+$yDnV|w0$K`$$9oVMwoSc%JJE^iT%`QJwh$XWU$+2S?_F4#!^ za`+)xi4z$|?+LUG0-`P<-5ZW!%-l+=nOxfl+{q`=Mc z^H_Sm=@(5~N%TuWUo8_Q5fN4qWXI`v#%8VcHfd~=N&56RCh7O#I1+I=@I0^q*aRGR zo21_X!Y{zJoW+4U4T6jHW5_3b$l{Z#v*{4J@rV_eREw>s|N!amf zJ1}vuqw8;qqUwB2k2j=DqIpSb$Zjp|GxJArLP;|^uIu$;xrg8B^|jN~gxN)^w%79x zHm@O04EDMs-GONOqhmTwe{&KyU+Np;F||C^kdRxvi6$XFXrsIzfMciW7=JK|CQkk& z$n(XcQ=Knz907b2X5Tb8qUmo$I3vFA_J6}{u8eU1Cv9>l77Hs}CRAlVUTD`Cqw zjL4=JAIXTGMy^K@%B8nZE{Pn<*U+q>2 z-XxMUDipgCZ#|`b(0Rz0!G7HE?)^jDUWgzRyA>(km=(~Q zM;(gYBHosXH{T|Dk=ips$K&Db`RmZPyXZ7}O>$~%Pj1ByH@1a1^1DUONjAlu;mZ4- zmN+>S#%58Nm`P!728BgNgm-U>HH#>wL_~?nB2p!YD9s?ENqR)v9#d5y@|Hqe5i8qG zh;av?eGa`hpB0{`1&vhTKOZvlK#Es%1H!>dsk29wBeKIwZBO$_l<^%!D?H7o@rXY_ zfi|=^GF_8CrWfm;P^KNwotAfx%ewyp|llv2;t8H zLbrNbFaQ%+9U-Cj3fcPRn>0edA9+f@4CUsr-OZDRiUjA`&_`s4dF;F9!l)f6)Ukst zdNhHVA5})}q}QEzJ!UYRhgro!#VdR;CCThQug03jcbJ)e^RgnAUHnag;xHT1GAGLD z1>s?~v}FqtF1DoNJLxb_&0rc^S3mOL?_8|*bhtE^@W&o{CFyJ6D6j{38fXCQfCb0{ zvVhS*D(LB7@rU7NZLf~#-9k3aA4tNQ83wQ@O3Va3xfoKS(29F;vNK!BGCGaV595@8*19kx~ z0o#Emfs3HubYY1k%|eS70!x4uzyrWKp#R_SO{V@wY3gQ^^dY+1_}d$4l-d91jM2%` z44@_eeE8a;)^&=AuCC#u}7m}l6fkKG7AvL+}w<#n4e>Vvnh5xT6@!B6hS*&DR zB9j05nOdpPyf*lYt4i0-PfSu9uoY+m)&VPlWxzt90>}Z90Syp5X_CGKP6J1QeZWp& zJFpGd3Ty(JfO^0IECc2Md4Lhn0}^olW0Old{V^B;dw?ClQ$Q2o09F8IzyxFg34jLZ z`v?vRI0+mEb^+Ugtw0M<53B-K01JT%AO|o48bAWhe~3nW=mG;g>;c+CZ(fC}r0os5~z$#z`un;H#vVdej z0|bwmq_e_zd4Lhn0}^olJ@hwl0N4p^16qJ}fDNbtDu6t| z2VZ|jGQbR& zfK0#usDa?SCCHuoY+o zRsuDE3CIKtfD-6Ej6Mer1G|7Wpaob3ECDKj93UCc0GE3pDBwDY;3%*M*bZz0)&VO3 zGmr-u0UaO#y@yZ{a1_`D>;Sd`jerd>135r4pac32qA|d6U=Pp+v;eDsnuF+n6CN@E zJs<(S2T%cU6xavs0G+03G{Zuuz=%0C$JM}12zHc02@#PQ~-HE z2B7ao|4Vr2eFues<3J~{6W9i{01jXUU1r7tdfNelMunedGa)1Ot z0(d9v0yqHd1hxU2TnOrcmB1390>}akfCPNGAIyPWz;<8@unw>RW}pzr0Q7(aobNy- zzyV+gj<>7+azqdQV=>=F~SvWIYRu28H6RwhcJ(IAuicKs9A?OgUV#^UOV;c~fnGd0fb$t(ME-TrW z-zVU5f#Px!TXq?8TsFj9{--R*7$_wYN*i`IoREYBp%nK1>R>2rucz+F$Li!R*bNoEl22J8xY!<58)Elh0x5-Av7_?6|%1sg!seW zSCUxg6*aS6G2pLUZn%G{#q%a|M|-=O!SKX@5YTZdhgFa&dz~zCsSM{ zYfC}6gB4#*VrQ?Sma7KHyWwim<3TmsftME61%i5Z4&h3s2qr0NSPDW61%wz12#st5 zLOt^#RI;vM5;I*>D}JJW8b%eLJ!hgw>H`Krt0^bL3I9eyzf?rf|9q4cUn5gnj&K*- zfUu4E5N=^z2q6qY2=gNh=tp$ij|OP2_(#&*a)dc-1HxqHL#St62$k&Ik4Z7TXH8Uz zGz!(wh)6jbPS7HuziJ}re?HENe3fyS|UlBOZPjCeZz;hbJP4 U$?Ino84B!Lbi36NieTjb0TWtCGynhq diff --git a/Build/Compilers/ZDoom/zspecial.acs b/Build/Compilers/ZDoom/zspecial.acs index 63e1b6f..e85ca55 100644 --- a/Build/Compilers/ZDoom/zspecial.acs +++ b/Build/Compilers/ZDoom/zspecial.acs @@ -24,12 +24,12 @@ special 17:Thing_Raise(1), 18:StartConversation(1,2), 19:Thing_Stop(1), - 20:Floor_LowerByValue(3), - 21:Floor_LowerToLowest(2), - 22:Floor_LowerToNearest(2), - 23:Floor_RaiseByValue(3), - 24:Floor_RaiseToHighest(2), - 25:Floor_RaiseToNearest(2), + 20:Floor_LowerByValue(3,4), + 21:Floor_LowerToLowest(2,3), + 22:Floor_LowerToNearest(2,3), + 23:Floor_RaiseByValue(3,5), + 24:Floor_RaiseToHighest(2,5), + 25:Floor_RaiseToNearest(2,4), 26:Stairs_BuildDown(5), 27:Stairs_BuildUp(5), 28:Floor_RaiseAndCrush(3,4), @@ -39,19 +39,19 @@ special 32:Stairs_BuildUpSync(4), 33:ForceField(0), 34:ClearForceField(1), - 35:Floor_RaiseByValueTimes8(3), - 36:Floor_LowerByValueTimes8(3), - 37:Floor_MoveToValue(3,4), + 35:Floor_RaiseByValueTimes8(3,5), + 36:Floor_LowerByValueTimes8(3,4), + 37:Floor_MoveToValue(3,5), 38:Ceiling_Waggle(5), 39:Teleport_ZombieChanger(2), - 40:Ceiling_LowerByValue(3), - 41:Ceiling_RaiseByValue(3), + 40:Ceiling_LowerByValue(3,4), + 41:Ceiling_RaiseByValue(3,4), 42:Ceiling_CrushAndRaise(3,4), 43:Ceiling_LowerAndCrush(3,4), 44:Ceiling_CrushStop(1), 45:Ceiling_CrushRaiseAndStay(3,4), 46:Floor_CrushStop(1), - 47:Ceiling_MoveToValue(3,4), + 47:Ceiling_MoveToValue(3,5), // 48:Sector_Attach3dMidtex 49:GlassBreak(0,1), // 50:ExtraFloor_LightOnly @@ -70,10 +70,10 @@ special 63:Plat_DownByValue(4), 64:Plat_UpWaitDownStay(3), 65:Plat_UpByValue(4), - 66:Floor_LowerInstant(3), - 67:Floor_RaiseInstant(3), - 68:Floor_MoveToValueTimes8(4), - 69:Ceiling_MoveToValueTimes8(4), + 66:Floor_LowerInstant(3,4), + 67:Floor_RaiseInstant(3,5), + 68:Floor_MoveToValueTimes8(4,5), + 69:Ceiling_MoveToValueTimes8(4,5), 70:Teleport(1,3), 71:Teleport_NoFog(1,4), 72:ThrustThing(2,4), @@ -109,6 +109,9 @@ special // 102:Scroll_Texture_Up // 103:Scroll_Texture_Down 104:Ceiling_CrushAndRaiseSilentDist(4,5), + 105:Door_WaitRaise(4,5), + 106:Door_WaitClose(3,4), + 107:Line_SetPortalTarget(2), 109:Light_ForceLightning(1), 110:Light_RaiseByValue(2), @@ -177,14 +180,14 @@ special 188:Sector_SetCeilingScale(5), 189:Sector_SetFloorScale(5), 191:SetPlayerProperty(3), - 192:Ceiling_LowerToHighestFloor(2), - 193:Ceiling_LowerInstant(3), - 194:Ceiling_RaiseInstant(3), + 192:Ceiling_LowerToHighestFloor(2,4), + 193:Ceiling_LowerInstant(3,5), + 194:Ceiling_RaiseInstant(3,4), 195:Ceiling_CrushRaiseAndStayA(4,5), 196:Ceiling_CrushAndRaiseA(4,5), 197:Ceiling_CrushAndRaiseSilentA(4,5), - 198:Ceiling_RaiseByValueTimes8(3), - 199:Ceiling_LowerByValueTimes8(3), + 198:Ceiling_RaiseByValueTimes8(3,4), + 199:Ceiling_LowerByValueTimes8(3,4), 200:Generic_Floor(5), 201:Generic_Ceiling(5), 202:Generic_Door(5), @@ -223,9 +226,9 @@ special 235:Floor_TransferTrigger(1), 236:Floor_TransferNumeric(1), 237:ChangeCamera(3), - 238:Floor_RaiseToLowestCeiling(2), + 238:Floor_RaiseToLowestCeiling(2,4), 239:Floor_RaiseByValueTxTy(3), - 240:Floor_RaiseByTexture(2), + 240:Floor_RaiseByTexture(2,4), 241:Floor_LowerToLowestTxTy(2), 242:Floor_LowerToHighest(3,4), 243:Exit_Normal(1), @@ -237,10 +240,31 @@ special 249:Door_CloseWaitOpen(3, 4), 250:Floor_Donut(3), 251:FloorAndCeiling_LowerRaise(3,4), - 252:Ceiling_RaiseToNearest(2), - 253:Ceiling_LowerToLowest(2), - 254:Ceiling_LowerToFloor(2), + 252:Ceiling_RaiseToNearest(2,3), + 253:Ceiling_LowerToLowest(2,4), + 254:Ceiling_LowerToFloor(2,4), 255:Ceiling_CrushRaiseAndStaySilA(4,5), + + // These are specialized versions of the Generic_* specials which are defined for EE Extradata. + 256:Floor_LowerToHighestEE(2, 3), + 257:Floor_RaiseToLowest(2, 3), + 258:Floor_LowerToLowestCeiling(2,3), + 259:Floor_RaiseToCeiling(2, 4), + 260:Floor_ToCeilingInstant(1, 3), + 261:Floor_LowerByTexture(2, 3), + 262:Ceiling_RaiseToHighest(2, 3), + 263:Ceiling_ToHighestInstant(1, 3), + 264:Ceiling_LowerToNearest(2, 4), + 265:Ceiling_RaiseToLowest(2, 3), + 266:Ceiling_RaiseToHighestFloor(2, 3), + 267:Ceiling_ToFloorInstant(1, 3), + 268:Ceiling_RaiseByTexture(2, 3), + 269:Ceiling_LowerByTexture(2, 4), + 270:Stairs_BuildDownDoom(5), + 271:Stairs_BuildUpDoomSync(4), + 272:Stairs_BuildDownDoomSync(4), + + // internal functions have negative values -1:GetLineUDMFInt(2), diff --git a/Build/Configurations/Includes/ZDoom_linedefs.cfg b/Build/Configurations/Includes/ZDoom_linedefs.cfg index 40a3d95..d3cae5b 100644 --- a/Build/Configurations/Includes/ZDoom_linedefs.cfg +++ b/Build/Configurations/Includes/ZDoom_linedefs.cfg @@ -2982,22 +2982,24 @@ zdoom type = 11; enum { - 1 = "Texture only"; - 2 = "Things only"; - 4 = "Both"; + 0 = "Texture only"; + 1 = "Things only"; + 2 = "Both"; } } arg3 { title = "Horizontal Speed"; + default = 128; type = 11; - enum = "scroll_speeds"; + enum = "sector_scroll_speeds_x"; } arg4 { title = "Vertical Speed"; + default = 128; type = 11; - enum = "scroll_speeds"; + enum = "sector_scroll_speeds_y"; } } 224 @@ -3025,14 +3027,16 @@ zdoom arg3 { title = "Horizontal Speed"; + default = 128; type = 11; - enum = "scroll_speeds"; + enum = "sector_scroll_speeds_x"; } arg4 { title = "Vertical Speed"; + default = 128; type = 11; - enum = "scroll_speeds"; + enum = "sector_scroll_speeds_y"; } } 225 diff --git a/Build/Configurations/Includes/ZDoom_misc.cfg b/Build/Configurations/Includes/ZDoom_misc.cfg index 50f36d7..c1f17c0 100644 --- a/Build/Configurations/Includes/ZDoom_misc.cfg +++ b/Build/Configurations/Includes/ZDoom_misc.cfg @@ -661,6 +661,36 @@ enums 128 = "128: Very fast"; } + sector_scroll_speeds_x + { + 0 = "0: West very fast"; + 16 = "16: West fast"; + 32 = "32: West normal"; + 64 = "64: West slow"; + 96 = "96: West very slow"; + 128 = "128: Don't scroll"; + 160 = "144: East very slow"; + 192 = "160: East slow"; + 224 = "176: East normal"; + 240 = "192: East fast"; + 256 = "256: East very fast"; + } + + sector_scroll_speeds_y + { + 0 = "0: South very fast"; + 16 = "16: South fast"; + 32 = "32: South normal"; + 64 = "64: South slow"; + 96 = "96: South very slow"; + 128 = "128: Don't scroll"; + 160 = "144: North very slow"; + 192 = "160: North slow"; + 224 = "176: North normal"; + 240 = "192: North fast"; + 256 = "256: North very fast"; + } + stair_speeds { 2 = "2: Slow"; diff --git a/Build/Scripting/ZDoom_ACS.cfg b/Build/Scripting/ZDoom_ACS.cfg index 0c72080..2982cfe 100644 --- a/Build/Scripting/ZDoom_ACS.cfg +++ b/Build/Scripting/ZDoom_ACS.cfg @@ -72,6 +72,7 @@ keywords Ceiling_CrushAndRaiseA = "Ceiling_CrushAndRaiseA(tag, dspeed, uspeed, crush, crushmode)"; Ceiling_CrushAndRaiseDist = "Ceiling_CrushAndRaiseDist(tag, dist, speed, damage, crushmode)"; Ceiling_CrushAndRaiseSilentA = "Ceiling_CrushAndRaiseSilentA(tag, dspeed, uspeed, crush, crushmode)"; + Ceiling_CrushAndRaiseSilentDist = "Ceiling_CrushAndRaiseSilentDist(tag, dist, speed, damage[, crushmode])"; Ceiling_CrushRaiseAndStay = "Ceiling_CrushRaiseAndStay(tag, speed, crush, crushmode)"; Ceiling_CrushRaiseAndStayA = "Ceiling_CrushRaiseAndStayA(tag, dspeed, uspeed, crush, crushmode)"; Ceiling_CrushRaiseAndStaySilA = "Ceiling_CrushRaiseAndStaySilA(tag, dspeed, uspeed, crush, crushmode)"; @@ -91,8 +92,8 @@ keywords Ceiling_RaiseInstant = "Ceiling_RaiseInstant(tag, unused, height)"; Ceiling_RaiseToNearest = "Ceiling_RaiseToNearest(tag, speed)"; Ceiling_Waggle = "Ceiling_Waggle(tag, amp, freq, offset, time)"; - ChangeActorAngle = "ChangeActorAngle(int tid, fixed angle[, bool interpolate = false])\nSets the angle for the actors with the specified tid.\nIf tid is 0, it sets the angle for the activator of the script.\nangle: a fixed point angle in the range of 0.0 to 1.0 (N = 0.25, W = 0.5, S = 0.75, E = 1.0)."; - ChangeActorPitch = "ChangeActorPitch(int tid, fixed pitch[, bool interpolate = false])\nSets the pitch for the actors with the specified tid. If tid is 0, it sets the pitch for the activator of the script.\npitch: a fixed point angle in the range of 0.0 to 1.0."; + ChangeActorAngle = "void ChangeActorAngle(int tid, fixed angle[, bool interpolate = false])\nSets the angle for the actors with the specified tid.\nIf tid is 0, it sets the angle for the activator of the script.\nangle: a fixed point angle in the range of 0.0 to 1.0 (N = 0.25, W = 0.5, S = 0.75, E = 1.0)."; + ChangeActorPitch = "void ChangeActorPitch(int tid, fixed pitch[, bool interpolate = false])\nSets the pitch for the actors with the specified tid. If tid is 0, it sets the pitch for the activator of the script.\npitch: a fixed point angle in the range of 0.0 to 1.0."; ChangeActorRoll = "void ChangeActorRoll(int tid, fixed angle[, bool interpolate = false])"; ChangeCamera = "ChangeCamera(tid, who, revert)"; ChangeCeiling = "void ChangeCeiling(int tag, str flatname)"; diff --git a/Build/Scripting/ZDoom_DECORATE.cfg b/Build/Scripting/ZDoom_DECORATE.cfg index cb23556..194679d 100644 --- a/Build/Scripting/ZDoom_DECORATE.cfg +++ b/Build/Scripting/ZDoom_DECORATE.cfg @@ -23,7 +23,50 @@ scripttype = 3; //0 = unknown script, 1 = acc, 2 = modeldef, 3 = decorate keywords { +//Editor special comments +//These are handled in a different fascion: key is replaced with the value and the caret is placed at [EP] position + $Angled = "$Angled"; + $NotAngled = "$NotAngled"; + $Category = "//$Category \"[EP]\""; + $Sprite = "//$Sprite \"[EP]\""; + $IgnoreRenderstyle = "//$IgnoreRenderstyle"; + $Title = "//$Title \"[EP]\""; + $Arg0 = "//$Arg0 \"[EP]\""; + $Arg1 = "//$Arg1 \"[EP]\""; + $Arg2 = "//$Arg2 \"[EP]\""; + $Arg3 = "//$Arg3 \"[EP]\""; + $Arg4 = "//$Arg4 \"[EP]\""; + $Arg0Default = "//$Arg0Default "; + $Arg1Default = "//$Arg1Default "; + $Arg2Default = "//$Arg2Default "; + $Arg3Default = "//$Arg3Default "; + $Arg4Default = "//$Arg4Default "; + $Arg0Tooltip = "//$Arg0Tooltip \"[EP]\""; + $Arg1Tooltip = "//$Arg1Tooltip \"[EP]\""; + $Arg2Tooltip = "//$Arg2Tooltip \"[EP]\""; + $Arg3Tooltip = "//$Arg3Tooltip \"[EP]\""; + $Arg4Tooltip = "//$Arg4Tooltip \"[EP]\""; + $Arg0Type = "//$Arg0Type "; + $Arg1Type = "//$Arg1Type "; + $Arg2Type = "//$Arg2Type "; + $Arg3Type = "//$Arg3Type "; + $Arg4Type = "//$Arg4Type "; + $Arg0Enum = "//$Arg0Enum "; + $Arg1Enum = "//$Arg1Enum "; + $Arg2Enum = "//$Arg2Enum "; + $Arg3Enum = "//$Arg3Enum "; + $Arg4Enum = "//$Arg4Enum "; + $Color = "//$Color "; + $Obsolete = "//$Obsolete \"[EP]\""; + $GZDB_SKIP = "//$GZDB_SKIP"; +//Preprocessor directives #Include = "#Include"; + #region = "#region"; + #endregion = "#endregion"; +//WFDS + A_Bool = "return A_Bool(bool result);"; + A_Int = "return A_Int(int result);"; + A_State = "return A_State(str state);\nreturn A_State(int offset);"; //Monster AI A_AlertMonsters = "A_AlertMonsters[(float maxrange = 0.0[, int flags = 0])]"; A_Burst = "A_Burst(str chunktype)"; @@ -49,7 +92,7 @@ keywords A_KillTracer = "A_KillTracer[(str damagetype = \"None\"[, int flags = 0[, str filter = \"None\"[, str species = \"None\"]]])]\ndamagetype: if the actor dies, the actor will enter a death state based on damagetype if present (or pain state if using NODAMAGE).\nflags: KILS flags.\nfilter: the actor class to damage.\nspecies: the actor species to damage."; A_Look = "A_Look"; A_Look2 = "A_Look2"; - A_LookEx = "A_LookEx(int flags, fixed minseedist, fixed maxseedist, fixed maxheardist, fixed fov, state seestate)"; + A_LookEx = "A_LookEx(int flags, float minseedist, float maxseedist, float maxheardist, float fov, state seestate)"; A_RaiseChildren = "A_RaiseChildren[(bool copyaffiliation = false)]"; A_RaiseMaster = "A_RaiseMaster[(bool copyaffiliation = false)]"; A_RaiseSiblings = "A_RaiseSiblings[(bool copyaffiliation = false)]"; @@ -64,23 +107,23 @@ keywords A_Srcr2Decide = "A_Srcr2Decide"; A_SwapTeleFog = "A_SwapTeleFog"; A_TurretLook = "A_TurretLook"; - A_Teleport = "A_Teleport[(str teleportstate = \"Teleport\"[, str targettype = \"BossSpot\"[, str fogtype = \"TeleportFog\"[, int flags = 0[, float mindist = 0.0[, float maxdist = 0.0[, int pointer = AAPTR_DEFAULT]]]]]])]"; + A_Teleport = "state A_Teleport[(str teleportstate = \"Teleport\"[, str targettype = \"BossSpot\"[, str fogtype = \"TeleportFog\"[, int flags = 0[, float mindist = 0.0[, float maxdist = 0.0[, int pointer = AAPTR_DEFAULT]]]]]])]\nbool A_Teleport[(str teleportstate = \"Teleport\"[, str targettype = \"BossSpot\"[, str fogtype = \"TeleportFog\"[, int flags = 0[, float mindist = 0.0[, float maxdist = 0.0[, int pointer = AAPTR_DEFAULT]]]]]])]"; A_VileChase = "A_VileChase"; A_Wander = "A_Wander"; //Generic monster attacks A_CustomMissile = "A_CustomMissile(str missiletype[, float spawnheight = 0.0[, int spawnofs_horiz = 0[, int angle = 0[, int aimflags = 0[, int pitch = 0[, int target = AAPTR_TARGET]]]]]])"; A_CustomBulletAttack = "A_CustomBulletAttack(float horz_spread, float vert_spread, int numbullets, int damageperbullet[, str pufftype = \"BulletPuff\"[, float range = 0.0[, int flags = 0[, int target = AAPTR_TARGET]]]])"; - A_CustomRailgun = "A_CustomRailgun(int damage[, int offset[, color ringcolor[, color corecolor[, int flags = 0[, bool aim = false[, float maxdiff = 0.0[, str pufftype = \"\"[, float spread_xy = 0.0[, float spread_z = 0.0[, fixed range = 8192[, int duration = 35[, float sparsity = 1.0[, float driftspeed = 1.0[, str spawnclass = \"\"[, float spawnofs_z = 0[, int spiraloffset = 270]]]]]]]]]]]]]]]])"; + A_CustomRailgun = "A_CustomRailgun(int damage[, int offset[, color ringcolor[, color corecolor[, int flags = 0[, bool aim = false[, float maxdiff = 0.0[, str pufftype = \"\"[, float spread_xy = 0.0[, float spread_z = 0.0[, float range = 8192[, int duration = 35[, float sparsity = 1.0[, float driftspeed = 1.0[, str spawnclass = \"\"[, float spawnofs_z = 0[, int spiraloffset = 270]]]]]]]]]]]]]]]])"; A_CustomMeleeAttack = "A_CustomMeleeAttack[(int damage = 0[, str meleesound = \"\"[, str misssound = \"\"[, str damagetype = \"Melee\"[, bool bleed = true]]]])]"; A_CustomComboAttack = "A_CustomComboAttack(str missiletype, float spawnheight, int damage, str meleesound[, str damagetype = \"Melee\"[, bool bleed = true]])"; - A_MonsterRefire = "A_MonsterRefire(int chancecontinue, str abortstate) "; + A_MonsterRefire = "state A_MonsterRefire(int chancecontinue, str abortstate)"; A_BasicAttack = "A_BasicAttack(int meleedamage, str meleesound, str missiletype, float missileheight)"; A_BulletAttack = "A_BulletAttack"; A_MonsterRail = "A_MonsterRail"; A_Explode = "A_Explode[(int explosiondamage = 128[, int explosionradius = 128[, int flags = XF_HURTSOURCE[, bool alert = false[, int fulldamageradius = 0[, int nails = 0[, int naildamage = 10[, str pufftype = \"BulletPuff\"]]]]]]])]"; A_RadiusThrust = "A_RadiusThrust(int force, int distance[, int flags[, int fullthrustdistance]])"; A_Detonate = "A_Detonate"; - A_ThrowGrenade = "A_ThrowGrenade(str spawntype[, float spawnheight[, float throwspeed_horz[, float throwspeed_vert[, bool useammo]]]])"; + A_ThrowGrenade = "bool A_ThrowGrenade(str spawntype[, float spawnheight[, float throwspeed_horz[, float throwspeed_vert[, bool useammo]]]])"; A_WolfAttack = "A_WolfAttack[(int flags = 0[, str soundname = \"weapons/pistol\"[, float snipe = 1.0[, int damage = 64[, int blocksize = 128[, int pointblank = 0[, int longrange = 0[, float runspeed = 160.0[, str pufftype = \"BulletPuff\"]]]]]]]])]"; //Freeze death functions A_FreezeDeath = "A_FreezeDeath"; @@ -116,45 +159,45 @@ keywords A_CheckTerrain = "A_CheckTerrain"; A_SetBlend = "A_SetBlend(str blendcolor, float alpha, int duration[, str fadecolor])"; A_CheckPlayerDone = "A_CheckPlayerDone"; - A_PlayerSkinCheck = "A_PlayerSkinCheck(str state)"; + A_PlayerSkinCheck = "state A_PlayerSkinCheck(str state)"; A_SkullPop = "A_SkullPop[(str type = \"BloodySkull\")]"; A_Quake = "A_Quake(int intensity, int duration, int damageradius, int tremorradius[, str sound = \"world/quake\"])"; A_QuakeEx = "A_QuakeEx(int intensityX, int intensityY, int intensityZ, int duration, int damrad, int tremrad[, str sound = \"world/quake\"[, int flags = 0[, float mulwavex = 1.0[, float mulwavey = 1.0[, float mulwavez = 1.0]]]]])"; //Spawn functions A_TossGib = "A_TossGib"; A_SpawnDebris = "A_SpawnDebris(str type[, bool translation = false[, float horizontal_vel = 1.0[, float vertical_vel = 1.0]]])"; - A_SpawnItem = "A_SpawnItem(str type, int distance, float zpos, bool useammo, bool translation)"; - A_SpawnItemEx = "A_SpawnItemEx(str type[, float xoffset = 0.0[, float yoffset = 0.0[, float zoffset = 0.0[, float xvelocity = 0.0[, float yvelocity = 0.0[, float zvelocity = 0.0[, float angle = 0.0[, int flags = 0[, int skipchance = 0[, int tid = 0]]]]]]]]]])"; + A_SpawnItem = "bool A_SpawnItem(str type, int distance, float zpos, bool useammo, bool translation)"; + A_SpawnItemEx = "bool A_SpawnItemEx(str type[, float xoffset = 0.0[, float yoffset = 0.0[, float zoffset = 0.0[, float xvelocity = 0.0[, float yvelocity = 0.0[, float zvelocity = 0.0[, float angle = 0.0[, int flags = 0[, int skipchance = 0[, int tid = 0]]]]]]]]]])"; A_SpawnParticle = "A_SpawnParticle(color color[, int flags = 0[, int lifetime = 35[, int size = 1[, float angle = 0.0[, float xoff = 0.0[, float yoff = 0.0[, float zoff = 0.0[, float velx = 0.0[, float vely = 0.0[, float velz = 0.0[, float accelx = 0.0[, float accely = 0.0[, float accelz = 0.0[, float startalpha = 1.0[, float fadestep = -1.0]]]]]]]]]]]]]]])"; //State jumps - A_CheckBlock = "A_CheckBlock(str block[, int flags = 0[, int pointer = AAPTR_TARGET]])"; - A_CheckCeiling = "A_CheckCeiling(int offset OR str state)"; - A_CheckFloor = "A_CheckFloor(int offset OR str state)"; - A_CheckFlag = "A_CheckFlag(str flagname, state label[, int check_pointer = AAPTR_DEFAULT])"; - A_CheckLOF = "A_CheckLOF(state jump[, int flags = 0[, float range = 0.0[, float minrange = 0.0[, float angle = 0.0[, float pitch = 0.0[, float offsetheight = 0.0[, float offsetwidth = 0.0[, int ptr_target = AAPTR_DEFAULT]]]]]]]])"; - A_CheckProximity = "A_CheckProximity(str jump, str classname, float distance[, int count = 1[, int flags = 0[, int pointer = AAPTR_DEFAULT]]])"; - A_CheckRange = "A_CheckRange(float distance, int offset OR str state[, bool 2d_check = false])"; - A_CheckSight = "A_CheckSight(int offset OR str state)"; - A_CheckSightOrRange = "A_CheckSightOrRange(float distance, int offset OR str state[, bool 2d_check = false])"; - A_CheckSpecies = "A_CheckSpecies(str jump[, str species=\"None\"[, int pointer = AAPTR_DEFAULT]]) "; - A_Jump = "A_Jump(int chance, int offset OR str state, ...)"; - A_JumpIf = "A_JumpIf(expression, int offset OR str state)"; - A_JumpIfArmorType = "A_JumpIfArmorType(str armortype, str state[, int minimum = 1])"; - A_JumpIfCloser = "A_JumpIfCloser(int distance, int offset OR str state[, bool noz = false])"; - A_JumpIfHealthLower = "A_JumpIfHealthLower(int health, int offset OR str state[, int pointer = AAPTR_DEFAULT])"; - A_JumpIfHigherOrLower = "A_JumpIfHigherOrLower(str high, str low[, float offsethigh = 0.0[, float offsetlow = 0.0[, bool includeHeight = true[, int pointer = AAPTR_TARGET]]]])"; - A_JumpIfInventory = "A_JumpIfInventory(str inventorytype, int amount, int offset OR str state[, int owner = AAPTR_DEFAULT])"; - A_JumpIfInTargetInventory = "A_JumpIfInTargetInventory(str item, int count, int offset OR str state[, int forward = AAPTR_DEFAULT])"; - A_JumpIfInTargetLOS = "A_JumpIfInTargetLOS(int offset OR str state[, float fov = 0.0[, int flags = 0[, float dist_max = 0.0[, float dist_close = 0.0]]]])\nflags: JLOSF flags."; - A_JumpIfMasterCloser = "A_JumpIfMasterCloser(int distance, int offset OR str state[, bool noz = false])"; - A_JumpIfNoAmmo = "A_JumpIfNoAmmo(int offset OR str state)"; - A_JumpIfTargetInLOS = "A_JumpIfTargetInLOS(int offset OR str state[, float fov = 0.0[, int flags = 0[, float dist_max = 0.0[, float dist_close = 0.0]]]])\nflags: JLOSF flags."; - A_JumpIfTargetInsideMeleeRange = "A_JumpIfTargetInsideMeleeRange(int offset OR str state)\nJumps the number of frames (offset) forward, or to the specified state\nwhen the target of the calling actor is within melee range of the caller."; - A_JumpIfTargetOutsideMeleeRange = "A_JumpIfTargetOutsideMeleeRange(int offset OR str state)\nJumps the number of frames (offset) forward, or to the specified state\nwhen the target of the calling actor is beyond melee range of the caller."; - A_JumpIfTracerCloser = "A_JumpIfTracerCloser(int distance, int offset OR str state[, bool noz = false])"; + A_CheckBlock = "state A_CheckBlock(str block[, int flags = 0[, int pointer = AAPTR_TARGET]])"; + A_CheckCeiling = "state A_CheckCeiling(str state)\nstate A_CheckCeiling(int offset)"; + A_CheckFloor = "state A_CheckFloor(str state)\nstate A_CheckFloor(int offset)"; + A_CheckFlag = "state A_CheckFlag(str flagname, state label[, int check_pointer = AAPTR_DEFAULT])"; + A_CheckLOF = "state A_CheckLOF(state jump[, int flags = 0[, float range = 0.0[, float minrange = 0.0[, float angle = 0.0[, float pitch = 0.0[, float offsetheight = 0.0[, float offsetwidth = 0.0[, int ptr_target = AAPTR_DEFAULT]]]]]]]])"; + A_CheckProximity = "state A_CheckProximity(str jump, str classname, float distance[, int count = 1[, int flags = 0[, int pointer = AAPTR_DEFAULT]]])"; + A_CheckRange = "state A_CheckRange(float distance, str state[, bool 2d_check = false])\nstate A_CheckRange(float distance, int offset[, bool 2d_check = false])"; + A_CheckSight = "state A_CheckSight(str state)\nstate A_CheckSight(int offsete)"; + A_CheckSightOrRange = "state A_CheckSightOrRange(float distance, str state[, bool 2d_check = false])\nstate A_CheckSightOrRange(float distance, int offset[, bool 2d_check = false])"; + A_CheckSpecies = "state A_CheckSpecies(str jump[, str species=\"None\"[, int pointer = AAPTR_DEFAULT]]) "; + A_Jump = "state A_Jump(int chance, str state, ...)\nstate A_Jump(int chance, int offset, ...)"; + A_JumpIf = "state A_JumpIf(expression, str state)\nstate A_JumpIf(expression, int offset)"; + A_JumpIfArmorType = "state A_JumpIfArmorType(str armortype, str state[, int minimum = 1])"; + A_JumpIfCloser = "state A_JumpIfCloser(int distance, str state[, bool noz = false])\nstate A_JumpIfCloser(int distance, int offset[, bool noz = false])"; + A_JumpIfHealthLower = "state A_JumpIfHealthLower(int health, str state[, int pointer = AAPTR_DEFAULT])\nstate A_JumpIfHealthLower(int health, int offset[, int pointer = AAPTR_DEFAULT])"; + A_JumpIfHigherOrLower = "state A_JumpIfHigherOrLower(str high, str low[, float offsethigh = 0.0[, float offsetlow = 0.0[, bool includeheight = true[, int pointer = AAPTR_TARGET]]]])"; + A_JumpIfInventory = "state A_JumpIfInventory(str inventorytype, int amount, str state[, int owner = AAPTR_DEFAULT])\nstate A_JumpIfInventory(str inventorytype, int amount, int offset[, int owner = AAPTR_DEFAULT])"; + A_JumpIfInTargetInventory = "state A_JumpIfInTargetInventory(str item, int count, str state[, int forward = AAPTR_DEFAULT])\nstate A_JumpIfInTargetInventory(str item, int count, int offset[, int forward = AAPTR_DEFAULT])"; + A_JumpIfInTargetLOS = "state A_JumpIfInTargetLOS(str state[, float fov = 0.0[, int flags = 0[, float dist_max = 0.0[, float dist_close = 0.0]]]])\nstate A_JumpIfInTargetLOS(int offset[, float fov = 0.0[, int flags = 0[, float dist_max = 0.0[, float dist_close = 0.0]]]])\nflags: JLOSF flags."; + A_JumpIfMasterCloser = "state A_JumpIfMasterCloser(int distance, str state[, bool noz = false])\nstate A_JumpIfMasterCloser(int distance, int offset[, bool noz = false])"; + A_JumpIfNoAmmo = "state A_JumpIfNoAmmo(str state)\nstate A_JumpIfNoAmmo(int offset)"; + A_JumpIfTargetInLOS = "state A_JumpIfTargetInLOS(str state[, float fov = 0.0[, int flags = 0[, float dist_max = 0.0[, float dist_close = 0.0]]]])\nstate A_JumpIfTargetInLOS(int offset[, float fov = 0.0[, int flags = 0[, float dist_max = 0.0[, float dist_close = 0.0]]]])\nflags: JLOSF flags."; + A_JumpIfTargetInsideMeleeRange = "state A_JumpIfTargetInsideMeleeRange(str state)\nstate A_JumpIfTargetInsideMeleeRange(int offset)\nJumps the number of frames (offset) forward, or to the specified state\nwhen the target of the calling actor is within melee range of the caller."; + A_JumpIfTargetOutsideMeleeRange = "state A_JumpIfTargetOutsideMeleeRange(str state)\nstate A_JumpIfTargetOutsideMeleeRange(int offset)\nJumps the number of frames (offset) forward, or to the specified state\nwhen the target of the calling actor is beyond melee range of the caller."; + A_JumpIfTracerCloser = "state A_JumpIfTracerCloser(int distance, str state[, bool noz = false])\nstate A_JumpIfTracerCloser(int distance, int offset[, bool noz = false])"; //Status changes A_ActiveAndUnblock = "A_ActiveAndUnblock"; - A_CallSpecial = "A_CallSpecial(int special[, int arg1 = 0[, int arg2 = 0[, int arg3 = 0[, int arg4 = 0[, int arg5 = 0]]]]])"; + A_CallSpecial = "bool A_CallSpecial(int special[, int arg1 = 0[, int arg2 = 0[, int arg3 = 0[, int arg4 = 0[, int arg5 = 0]]]]])"; A_ChangeFlag = "A_ChangeFlag(str flagname, bool value)"; A_ChangeVelocity = "A_ChangeVelocity[(float x = 0.0[, float y = 0.0[, float z = 0.0[, int flags = 0[, int pointer = AAPTR_DEFAULT]]]])]\nflags: CVF flags."; A_ClearShadow = "A_ClearShadow"; @@ -163,7 +206,7 @@ keywords A_FadeIn = "A_FadeIn[(float increase_amount = 0.1[, int flags = 0])]\nflags: FTF flags."; A_FadeOut = "A_FadeOut[(float reduce_amount = 0.1[, int flags = FTF_REMOVE])]\nflags: FTF flags."; A_FadeTo = "A_FadeTo(float target[, float amount = 0.1[, int flags = 0]])\nflags: FTF flags."; - A_FaceMovementDirection = "A_FaceMovementDirection([float offset = 0[, float anglelimit = 0[, float pitchlimit = 0[, int flags = 0[, int pointer = AAPTR_DEFAULT]]]]])"; + A_FaceMovementDirection = "state A_FaceMovementDirection[(float offset = 0[, float anglelimit = 0[, float pitchlimit = 0[, int flags = 0[, int pointer = AAPTR_DEFAULT]]]])]"; A_Fall = "A_Fall"; A_Gravity = "A_Gravity"; A_HideThing = "A_HideThing"; @@ -178,6 +221,7 @@ keywords A_ScreamAndUnblock = "A_ScreamAndUnblock"; A_SetAngle = "A_SetAngle(float angle[, int flags = 0[, int pointer = AAPTR_DEFAULT]])\nangle: the actor's new angle, in degrees.\nflags: SPF flags."; A_SetArg = "A_SetArg(int position, int value)"; + A_SetChaseThreshold = "A_SetChaseThreshold(int threshold[, bool setdefaultthreshhold = false[, int pointer = AAPTR_DEFAULT]])"; A_SetDamageType = "A_SetDamageType(str damagetype)"; A_SetFloat = "A_SetFloat"; A_SetFloatSpeed = "A_SetFloatSpeed(float speed[, int pointer = AAPTR_DEFAULT])"; @@ -220,23 +264,23 @@ keywords A_FaceTracer = "A_FaceTracer[(float angle = 0.0[, float pitch = 270.0])]\nA_FaceTracer([float max_turn = 0.0[, float max_pitch = 270.0[, float ang_offset = 0.0[, float pitch_offset = 0.0[, int flags = 0[, float z_add = 0.0]]]]]])"; A_Fire = "A_Fire[(float height = 0.0)]"; A_Weave = "A_Weave(int horzspeed, int vertspeed, float horzdist, float vertdist)"; - A_Warp = "A_Warp(int ptr_destination[, float x-offset = 0[, float y-offset = 0[, float z-offset = 0[, float angle = 0[, int flags = 0[, str success_state = \"\"[, float heightoffset = 0[, float radiusoffset = 0[, float pitch = 0]]]]]]]]])\nflags: WARPF flags."; + A_Warp = "state A_Warp(int ptr_destination[, float x-offset = 0[, float y-offset = 0[, float z-offset = 0[, float angle = 0[, int flags = 0[, str success_state = \"\"[, float heightoffset = 0[, float radiusoffset = 0[, float pitch = 0]]]]]]]]])\nbool A_Warp(int ptr_destination[, float x-offset = 0[, float y-offset = 0[, float z-offset = 0[, float angle = 0[, int flags = 0[, str success_state = \"\"[, float heightoffset = 0[, float radiusoffset = 0[, float pitch = 0]]]]]]]]])\nflags: WARPF flags."; A_Countdown = "A_Countdown"; A_CountdownArg = "A_CountdownArg(int arg[, str targetstate])"; A_Stop = "A_Stop"; //Inventory functions - A_GiveInventory = "A_GiveInventory(str type[, int count = 0[, int giveto = AAPTR_DEFAULT]])\ntype: the item to give. This should be a valid inventory item.\ncount: the number of samples of this item to give. Default is 0, which is interpreted as 1.\ngiveto: the actor to give the item to"; - A_GiveToChildren = "A_GiveToChildren(str type[, int count])\ntype: the item to give. This should be a valid inventory item.\ncount: the number of samples of this item to give. Default is 0, which is interpreted as 1."; - A_GiveToSiblings = "A_GiveToSiblings(str type[, int count])\ntype: the item to give. This should be a valid inventory item.\ncount: the number of samples of this item to give. Default is 0, which is interpreted as 1."; - A_GiveToTarget = "A_GiveToTarget(str type, int count[, int giveto])"; - A_TakeInventory = "A_TakeInventory(str type, int count[, int flags[, int takefrom = AAPTR_DEFAULT]])"; - A_TakeFromChildren = "A_TakeFromChildren(str type[, int count])\ntype: the item to take. This should be a valid inventory item.\ncount: the number of samples of this item to take.\nIf this is 0, the item is cleared from the inventory unless it has the\nINVENTORY.KEEPDEPLETED flag set, and in which case, its amount is merely reduced to 0.\nDefault is 0."; - A_TakeFromSiblings = "A_TakeFromSiblings(str type[, int count])\ntype: the item to take. This should be a valid inventory item.\ncount: the number of samples of this item to take.\nIf this is 0, the item is cleared from the inventory unless it has the\nINVENTORY.KEEPDEPLETED flag set, and in which case, its amount is merely reduced to 0.\nDefault is 0."; - A_TakeFromTarget = "A_TakeFromTarget(str type, int count[, int flags[, int takefrom]])"; + A_GiveInventory = "bool A_GiveInventory(str type[, int count = 0[, int giveto = AAPTR_DEFAULT]])\ntype: the item to give. This should be a valid inventory item.\ncount: the number of samples of this item to give. Default is 0, which is interpreted as 1.\ngiveto: the actor to give the item to"; + A_GiveToChildren = "int A_GiveToChildren(str type[, int count = 0])\ntype: the item to give. This should be a valid inventory item.\ncount: the number of samples of this item to give. Default is 0, which is interpreted as 1."; + A_GiveToSiblings = "int A_GiveToSiblings(str type[, int count = 0])\ntype: the item to give. This should be a valid inventory item.\ncount: the number of samples of this item to give. Default is 0, which is interpreted as 1."; + A_GiveToTarget = "bool A_GiveToTarget(str type, int count[, int giveto = AAPTR_DEFAULT])"; + A_TakeInventory = "bool A_TakeInventory(str type, int count[, int flags[, int takefrom = AAPTR_DEFAULT]])"; + A_TakeFromChildren = "int A_TakeFromChildren(str type[, int count = 0])\ntype: the item to take. This should be a valid inventory item.\ncount: the number of samples of this item to take.\nIf this is 0, the item is cleared from the inventory unless it has the\nINVENTORY.KEEPDEPLETED flag set, and in which case, its amount is merely reduced to 0.\nDefault is 0."; + A_TakeFromSiblings = "int A_TakeFromSiblings(str type[, int count = 0])\ntype: the item to take. This should be a valid inventory item.\ncount: the number of samples of this item to take.\nIf this is 0, the item is cleared from the inventory unless it has the\nINVENTORY.KEEPDEPLETED flag set, and in which case, its amount is merely reduced to 0.\nDefault is 0."; + A_TakeFromTarget = "bool A_TakeFromTarget(str type, int count[, int flags[, int takefrom = AAPTR_DEFAULT]])"; A_DropInventory = "A_DropInventory(str type)"; A_DropItem = "A_DropItem(str item[, int dropamount = -1[, int chance = 256]])\nThe calling actor drops the specified item.\nThis works in a similar way to the DropItem actor property."; - A_SelectWeapon = "A_SelectWeapon(str type)"; - A_RadiusGive = "A_RadiusGive(str item, fixed distance, int flags[, int amount = 0[, str filter = \"None\"[, str species = \"None\"[, fixed mindist = 0]]]])\nflags: RGF flags."; + A_SelectWeapon = "bool A_SelectWeapon(str type)"; + A_RadiusGive = "int A_RadiusGive(str item, float distance, int flags[, int amount = 0[, str filter = \"None\"[, str species = \"None\"[, float mindist = 0]]]])\nflags: RGF flags."; //Weapon functions A_WeaponReady = "A_WeaponReady[(int flags = 0)]\nflags: WRF flags."; A_Lower = "A_Lower"; @@ -245,7 +289,7 @@ keywords A_ClearReFire = "A_ClearReFire"; A_GunFlash = "A_GunFlash[(str state = \"Flash\"[, int flags = 0])]\nflags: GFF flags."; A_CheckReload = "A_CheckReload"; - A_CheckForReload = "A_CheckForReload(int counter, str state[, bool dontincrement = false])"; + A_CheckForReload = "state A_CheckForReload(int counter, str state[, bool dontincrement = false])"; A_ResetReloadCounter = "A_ResetReloadCounter"; A_Light = "A_Light(int intensity)"; A_Light0 = "A_Light0"; @@ -260,8 +304,8 @@ keywords A_Saw = "A_Saw[(str fullsound = \"weapons/sawfull\"[, str hitsound = \"weapons/sawhit\"[, int damage = 0[, str pufftype = \"BulletPuff\"[, int flags = 0[, float range = 65.0[, float spread_xy = 2.8125[, float spread_z = 0.0[, float lifesteal = 0.0[, int lifestealmax = 0[, str armorbonustype = \"ArmorBonus\"]]]]]]]]]])]"; A_CustomPunch = "A_CustomPunch(int damage[, bool norandom = false[, int flags = 0[, str pufftype = \"BulletPuff\"[, float range = 64.0[, float lifesteal = 0.0[, int lifestealmax = 0[, str armorbonustype = \"ArmorBonus\"[, str meleesound[, str misssound]]]]]]]]])"; A_FireBullets = "A_FireBullets(int spread_horz, int spread_vert, int numbullets, int damage[, str pufftype = \"\"[, int flags = FBF_USEAMMO[, float range = 0.0]]])"; - A_FireCustomMissile = "A_FireCustomMissile(str missiletype[, int angle = 0[, bool useammo = false[, int spawnofs_horz = 0[, int spawnheight = 0[, bool aim = false OR int flags = 0[, angle pitch = 0]]]]]])"; - A_RailAttack = "A_RailAttack(int damage[, int spawnofs_horz[, bool useammo[, str ringcolor[, str corecolor[, int flags[, int maxdiff[, str pufftype[, float spread_xy = 0[, float spread_z = 0.0[, fixed range = 8192[, int duration = 35[, float sparsity = 1.0[, float driftspeed = 1.0[, str spawnclass[, float spawnofs_z = 0.0[, int spiraloffset = 270]]]]]]]]]]]]]]]])"; + A_FireCustomMissile = "A_FireCustomMissile(str missiletype[, int angle = 0[, bool useammo = false[, int spawnofs_horz = 0[, int spawnheight = 0[, int flags = 0[, angle pitch = 0]]]]]])"; + A_RailAttack = "A_RailAttack(int damage[, int spawnofs_horz[, bool useammo[, str ringcolor[, str corecolor[, int flags[, int maxdiff[, str pufftype[, float spread_xy = 0.0[, float spread_z = 0.0[, float range = 8192.0[, int duration = 35[, float sparsity = 1.0[, float driftspeed = 1.0[, str spawnclass[, float spawnofs_z = 0.0[, int spiraloffset = 270]]]]]]]]]]]]]]]])"; A_FireAssaultGun = "A_FireAssaultGun"; A_FireBFG = "A_FireBFG"; A_FireOldBFG = "A_FireOldBFG"; @@ -324,7 +368,7 @@ keywords A_BarrelDestroy = "A_BarrelDestroy"; //Miscellaneous functions not listed in the "Action functions" wiki article A_Bang4Cloud = "A_Bang4Cloud"; - A_Blast = "A_Blast[(int flags = 0[, int strength = 255[, int radius = 255[, float speed = 20.0[, str blasteffect = \"BlastEffect\"[, sound blastsound = \"BlastRadius\"]]]]])]"; + A_Blast = "A_Blast[(int flags = 0[, int strength = 255[, int radius = 255[, float speed = 20.0[, str blasteffect = \"BlastEffect\"[, str blastsound = \"BlastRadius\"]]]]])]\nA_Blast[(int flags = 0[, int strength = 255[, float radius = 255.0[, float speed = 20.0[, str blasteffect = \"BlastEffect\"[, str blastsound = \"BlastRadius\"]]]]])]"; A_BishopMissileWeave = "A_BishopMissileWeave"; A_DropWeaponPieces = "A_DropWeaponPieces(str actorclass1, str actorclass2, str actorclass3)"; A_Feathers = "A_Feathers"; @@ -341,28 +385,48 @@ keywords abs = "abs(x)\nReturns the absolute value of x."; sin = "sin(x)\nTrigonometry function, x must be in degrees."; cos = "cos(x)\nTrigonometry function, x must be in degrees."; + tan = "tan(x)\nTrigonometry function, x must be in degrees."; + asin = "asin(x)\nTrigonometry function, returns an angle in degrees."; + acos = "acos(x)\nTrigonometry function, returns an angle in degrees."; + atan = "atan(x)\nTrigonometry function, returns an angle in degrees."; + sinh = "sinh(x)\nTrigonometry function, x must be in radians."; + cosh = "cosh(x)\nTrigonometry function, x must be in radians."; + tanh = "tanh(x)\nTrigonometry function, x must be in radians."; + exp = "exp(x)\nReturns the base-e exponential function of x, which is e raised to the power x."; + log = "log(x)\nReturns the natural logarithm of x - the opposite of exp."; + log10 = "log10(x)\nReturns the common (base-10) logarithm of x."; + ceil = "ceil(x)\nRounds the number upward to the next closest integer."; + floor = "floor(x)\nRounds the number downward to the next closest integer."; sqrt = "sqrt(x)\nReturns the square root of x."; - random = "random[identifier](min, max)\nReturns a random integer value between min and max."; - random2 = "random2[identifier](mask)\nReturns a random integer value between -mask and +mask."; - frandom = "frandom[identifier](min, max)\nReturns a random floating point value between min and max."; - randompick = "randompick[identifier](int, ...)\nPicks a number from the numbers placed in it.\nThis can take an unlimited amount of parameters."; - frandompick = "frandompick[identifier](int, ...)\nSimilar to randompick but for float-point values."; -//State keywords - //Bright = "Bright"; - CanRaise = "CanRaise"; - Fast = "Fast"; + min = "min(x1, ...)\nGets the smallest value of all values listed.\nCan take any amount of numbers, and can solve both ints and floats."; + max = "max(x1, ...)\nGets the largest value of all values listed.\nCan take any amount of numbers, and can solve both ints and floats."; + clamp = "clamp(src, min, max)\nReturns src within the range of min and max inclusively. All parameters can be ints or floats."; +//Randum number functions + random = "int random[identifier](min, max)\nReturns a random integer value between min and max."; + random2 = "int random2[identifier](mask)\nReturns a random integer value between -mask and +mask."; + frandom = "float frandom[identifier](min, max)\nReturns a random floating point value between min and max."; + randompick = "int randompick[identifier](int, ...)\nPicks a number from the numbers placed in it.\nThis can take an unlimited amount of parameters."; + frandompick = "float frandompick[identifier](float, ...)\nPicks a number from the numbers placed in it.\nThis can take an unlimited amount of parameters."; +//State functions Light = "Light(str lightname)"; - NoDelay = "NoDelay"; Offset = "Offset(int x, int y)"; - Slow = "Slow"; //Special functions CheckClass = "bool CheckClass(str classname[, int ptr_select = AAPTR_DEFAULT[, bool match_superclass = false]])"; - IsPointerEqual = "bool IsPointerEqual(int ptr_select1, int ptr_select2)"; + IsPointerEqual = "bool IsPointerEqual(int ptr1, int ptr2)"; + CountInv = "int CountInv(str itemclassname[, int ptr_select = AAPTR_DEFAULT])"; + GetDistance = "float GetDistance(bool checkz[, int ptr_select = AAPTR_TARGET])"; + GetSpawnHealth = "int GetSpawnHealth()"; + GetGibHealth = "int GetGibHealth()"; } properties { Actor; + enum; + const; + var; + int; + float; //WFDS if; else; @@ -373,7 +437,13 @@ properties Wait; Fail; goto; -//states: +//State keywords + Bright; + CanRaise; + Fast; + Slow; + NoDelay; +//States States; Spawn:; Idle:; @@ -452,6 +522,8 @@ properties Activation; TeleFogSourceType; TeleFogDestType; + Threshold; + DefThreshold; //Collision and 'Physics' Radius; Height; @@ -1008,6 +1080,7 @@ constants CBF_SETTRACER; CBF_SETONPTR; CBF_DROPOFF; + CBF_NOACTORS; CHF_DONTMOVE; CHF_FASTCHASE; CHF_NIGHTMAREFAST; diff --git a/Documents/cmdargs.txt b/Documents/cmdargs.txt index daf8db5..6e490f7 100644 --- a/Documents/cmdargs.txt +++ b/Documents/cmdargs.txt @@ -1,55 +1,63 @@ -Doom Builder 2 command-line arguments +GZDoom Builder command-line arguments ========================================================================================== Usage: - builder.exe [wadfile] [-map mapname] [-cfg configname] [-delaywindow] [-nopreferences] - [-strictpatches] [-resource wad|dir|pk3 [roottextures] [rootflats] - [strictpatches] [notest] resourcename] + GZBuilder.exe [wadfile] [-map mapname] [-cfg configname] [-delaywindow] [-nopreferences] + [-strictpatches] [-portable] [-resource wad|dir|pk3 [roottextures] + [rootflats] [strictpatches] [notest] resourcename] ========================================================================================== Parameters: -- wadfile +wadfile This is a .WAD file to load immediately after Doom Builder has started up. Unless -map and -cfg are used, this will show the map-options dialog. -- map -Where 'mapname' is the name of the map (map header lump name) such as MAP01 or E1M1. When +-map "mapname" +Where "mapname" is the name of the map (map header lump name) such as MAP01 or E1M1. When specified, this will indicate the map to load from the specified wad file. Use in combination with -cfg to provide the required information to skip the map-options dialog. -- cfg -Where 'configname' is a game configuration filename, for example, "ZDoom_DoomHexen.cfg". +-cfg "configname" +-config "configname" +Where "configname" is a game configuration filename, for example, "ZDoom_DoomHexen.cfg". Do NOT include the path, all game configurations must be in the Configurations subfolder. When used in combination with -map this will provide the required information to load a map directly and skip the map-options dialog. -- delaywindow +-delaywindow This delays showing the main interface window until the automatic map loading from command line parameters is completed, and the program is not terminating yet. This is usefull for plugins that can be used to perform batch processes where the showing of the main interface window is not desired. If a plugin completes it's actions on map load and terminates the application immediately, the main window will not be shown at all. -- nosettings +-nosettings When this parameter is specified, Doom Builder will not load your preferences or game configuration settings and will use the default settings instead. You will not lose your original settings, but when this parameter is specified your settings will not be saved. -- strictpatches +-strictpatches Specify this parameter to enforce strictly loading texture patches from between P_START and P_END marker lumps only. This can solve lump name conflicts, but old WAD files do not always adhere to this rule. -- resource +-portable +The editor will be launched in portable mode. It will use the "GZBuilder.cfg" located in +the program directory instead of the one located in the +"%LocalAppData%\Doom Builder\GZBuilder.cfg" to load and save program settings. Log and +crash report files will be also created in the program directory. + +-resource [flags] "path\to\resource" When -wadfile is specified, the -resource option can be used to add additional resources that must be loaded along with the wad file. Note that these are added to the resources which are automatically loaded due to the selection of a game configuration. You can repeat this option for any number of resources you wish to add. As always, the last -specified resource will override any data in earlier specified resource. This parameter -has the following arguments: +specified resource will override any data in earlier specified resource. + +This parameter has the following arguments: wad|dir|pk3 Either 'wad', 'dir' or 'pk3' must be specified to indicate how this resource must be loaded. This is the same as selecting the tabs in @@ -77,16 +85,18 @@ Examples: This loads the file "Ubermegawad.wad" after Doom Builder is initialized and shows the map-options dialog: - builder.exe "C:\Games\Doom\My Maps\Ubermegawad.wad" + GZBuilder.exe "C:\Games\Doom\My Maps\Ubermegawad.wad" Same as the example above, but now without showing the map-options dialog and instead immediately loads map MAP23 with the game configuration for Doom 2: - builder.exe "C:\Games\Doom\My Maps\Ubermegawad.wad" -map MAP23 -cfg "Doom2.cfg" + GZBuilder.exe "C:\Games\Doom\My Maps\Ubermegawad.wad" -map MAP23 -cfg "Doom_Doom2Doom.cfg" -Same as the example above, but with added wad file resource and PK3 file resource: +Same as the example above, but using one of GZDoom game configurations with added wad +file resource and PK3 file resources: - builder.exe "C:\Games\Doom\My Maps\Ubermegawad.wad" -map MAP23 -cfg "Doom2.cfg" - -resource wad strictpatches "C:\Games\Doom\gothtextures.wad" - -resource pk3 "C:\Games\Doom\hardmonsters.pk3" + GZBuilder.exe "C:\Games\Doom\My Maps\Ubermegawad.wad" -map MAP23 -cfg "GZDoom_DoomUDMF.cfg" + -resource pk3 notest "C:\GZDoom\gzdoom.pk3" + -resource wad strictpatches "C:\Games\Doom\gothtextures.wad" + -resource pk3 "C:\Games\Doom\hardmonsters.pk3" diff --git a/Help/commandlineparams.html b/Help/commandlineparams.html index e42a407..8e70ff7 100644 --- a/Help/commandlineparams.html +++ b/Help/commandlineparams.html @@ -7,49 +7,74 @@ - - + +

-

Command Line Parameters

+

Command Line Parameters

-

All command line parameters are case-insensitive.
-
- -portable - GZDB only.
- The editor will be launched in portable mode. It will use the "GZBuilder.cfg" located in the program directory instead of the one located in the "%LocalAppData%\Doom Builder\GZBuilder.cfg" to load and save program settings. Log and crash report files will be also created in the program directory.
-
- -nosettings
- The editor doesn't load or save program settings.
-
- -delaywindow
- Delays showing of the main window.
-
- -map "path\to\mapfile.wad"
- The editor will automatically load the specified map.
-

The following parameters are used only in conjunction with the "-map" parameter

- They replicate the settings, which can be set in the Open Map Window.
-
- -strictpatches
- Enables strict patches rules.
-
- -cfg "path\to\game configuration.cfg"
- -config "path\to\game configuration.cfg"
- The editor will use the specified game configuration file when loading the map.
-
- -resource <resource type> [flags] "path\to\resource"
- Adds a map resource.
- Resource type (required): "wad", "dir" or "pk3".
- Flags (optional): -
    -
  • ROOTTEXTURES - load images in the root directory of the resource as textures.
  • -
  • ROOTFLATS - load images in the root directory of the resource as flats.
  • -
  • STRICTPATCHES - use strict rules for patches.
  • -
  • NOTEST - exclude this resource from testing parameters.
  • -
- Examples: -
-  -resource pk3 notest "c:\GZDoom\gzdoom.pk3"
-  -resource WAD "c:\Doom\DOOM.WAD"
+

Usage:

+ All command line parameters are case-insensitive.
+
+ GZBuilder.exe [wadfile] [-map mapname] [-cfg configname] [-delaywindow] [-nosettings] + [-strictpatches] [-portable] [-resource wad|dir|pk3 [roottextures] [rootflats] + [strictpatches] [notest] resourcename] +

Parameters:

+
+ wadfile
+ This is a .WAD file to load immediately after GZDoom Builder has started up. Unless -map and -cfg are used, this will show the map-options dialog.
+

-map "mapname"
+ Where "mapname" is the name of the map (map header lump name) such as MAP01 or E1M1.
+ When specified, this will indicate the map to load from the specified wad file.
+ Use in combination with -cfg to provide the required information to skip the map-options dialog. +

-delaywindow
+ This delays showing the main interface window until the automatic map loading from command line parameters is completed, and the program is not terminating yet.
This is usefull for plugins that can be used to perform batch processes where the showing of the main interface window is not desired.
If a plugin completes it's actions on map load and terminates the application immediately, the main window will not be shown at all. +

+ -nosettings
+ When this parameter is specified, GZDoom Builder will not load your preferences or game configuration settings and will use the default settings instead.
You will not lose your original settings, but when this parameter is specified your settings will not be saved.
+
+ -portable - GZDB only.
+ The editor will be launched in portable mode. It will use the "GZBuilder.cfg" located in the program directory instead of the one located in the "%LocalAppData%\Doom Builder\GZBuilder.cfg" to load and save program settings. Log and crash report files will be also created in the program directory.
+

The following parameters are used only when both "wadfile" and "-map" parameters are present

+ They replicate the settings, which can be set in the Open Map Window.
+
+ -strictpatches
+ Specify this parameter to enforce strictly loading texture patches from between P_START + and P_END marker lumps only. This can solve lump name conflicts, but old WAD files do not + always adhere to this rule.
+
+ -cfg "game_configuration.cfg"
+ -config "game_configuration.cfg"
+ The editor will use the specified game configuration file when loading the map.
+ Do not include the path, all game configurations must be in the "Configurations" subfolder.
+
+ -resource <resource type> [flags] "path\to\resource"
+ Adds a map resource. Note that these are added to the resources, which are automatically loaded according to selected game configuration.
+ Resource type (required): "wad", "dir" or "pk3".
+ Flags (optional): +
    +
  • ROOTTEXTURES - load images in the root directory of the resource as textures (directory/pk3 resources only).
  • +
  • ROOTFLATS - load images in the root directory of the resource as flats (directory/pk3 resources only).
  • +
  • STRICTPATCHES - use strict rules for patches (wad resources only).
  • +
  • NOTEST - exclude this resource from testing parameters.
  • +
+

Examples:

+ This loads the file "Ubermegawad.wad" after GZDoom Builder is initialized and shows the + map-options dialog: +
+GZBuilder.exe "C:\Games\Doom\My Maps\Ubermegawad.wad"
+
+ Same as the example above, but now without showing the map-options dialog and instead immediately loading map MAP23 with the Doom 2 game configuration: +
+GZBuilder.exe "C:\Games\Doom\My Maps\Ubermegawad.wad" -map MAP23 -cfg "Doom_Doom2Doom.cfg"
+
+ Same as the example above, but using one of GZDoom game configurations with added wad file resource and PK3 file resources: +
+GZBuilder.exe "C:\Games\Doom\My Maps\Ubermegawad.wad" -map MAP23 -cfg "GZDoom_DoomUDMF.cfg"
+               -resource pk3 notest "C:\GZDoom\gzdoom.pk3"
+               -resource wad strictpatches "C:\Games\Doom\gothtextures.wad"
+               -resource pk3 "C:\Games\Doom\hardmonsters.pk3"
+
diff --git a/Help/gc_decoratekeys.html b/Help/gc_decoratekeys.html index 3cc1d5f..fdb1dc0 100644 --- a/Help/gc_decoratekeys.html +++ b/Help/gc_decoratekeys.html @@ -31,6 +31,9 @@ //$Title <title>
Specifies which name to give to the actor. By default, a custom actor not identified in a configuration file will use the Tag property, and if not present, will default to the class name.

+ //$IgnoreRenderstyle - GZDB only.
+ "RenderStyle" DECORATE property will be ignored by the editor. Helpful when you want to see the sprite of an invisible actor in Visual mode.
+
//$ArgN <name> - GZDB only.
Allows to override default argument names for this actor.

@@ -87,6 +90,7 @@ Actor ChexShield : ResistanceRune replaces ResistanceRune 5104 { //$Category "Pickups/Chex Powerups" //$Sprite ARMXA0 + //$IgnoreRenderstyle //$Title "Chex Shield" //$Color 12 //$NotAngled @@ -115,6 +119,7 @@ Actor ChexShield : ResistanceRune replaces ResistanceRune 5104 Height 44 Radius 26 + RenderStyle None Inventory.PickupMessage "Picked up the energized Chex armor!" States diff --git a/Help/gzdb/compilingtheeditor.html b/Help/gzdb/compilingtheeditor.html index 03ef2e3..a515ea5 100644 --- a/Help/gzdb/compilingtheeditor.html +++ b/Help/gzdb/compilingtheeditor.html @@ -28,21 +28,34 @@
  • 7-zip archiver (www.7-zip.org).
  • Inno Setup 5 or newer (http://www.jrsoftware.org/isinfo.php).
  • Microsoft HTML Help compiler (http://www.microsoft.com/en-us/download/details.aspx?id=21138).
  • -
  • SlimDX Developer SDK. You can download it for free from http://slimdx.org/download.php.
  • +
  • SlimDX Developer SDK (http://slimdx.org/download.php).
  • +
  • DirectX SDK (https://www.microsoft.com/en-us/download/details.aspx?id=6812).
  • Obtaining the source:

    - The Doom Builder 2 source code is hosted on SourceForge and is available through SVN at the following location:
    https://svn.code.sf.net/p/doombuilder/code/branches/GZDoomBuilder
    - If you don't want to use a SVN client, head to - https://sourceforge.net/p/doombuilder/code/HEAD/tree/branches/GZDoomBuilder/ - and press "Download Snapshot" button. + The GZDoom Builder source code is hosted on SourceForge and is available through SVN at the following location: +
    https://svn.code.sf.net/p/doombuilder/code/branches/GZDoomBuilder
    + If you don't want to use a SVN client, head to https://sourceforge.net/p/doombuilder/code/HEAD/tree/branches/GZDoomBuilder/ and press "Download Snapshot" button. +

    Quick start guide:

    + This guide assumes you are using Visual Studio 2008 / Visual C# 2008 Express Edition and Tortiose SVN. +
      +
    1. Create an empty folder, right click on it and choose "SVN Checkout..." from the context menu.
    2. +
    3. Enter "https://svn.code.sf.net/p/doombuilder/code/branches/GZDoomBuilder" in the "URL of repository" field and click OK.
    4. +
    5. Open "Builder.sln" in the Visual Studio and make sure it compiles and runs (click the green "Play" button, or press F5). +
        +
      • If the Visual Studio complains about missing SlimDX reference in the Builder project, you'll need to re-add it manually. To do so, delete SlimDX from the References in the Solution Explorer, right click on the Builder project and choose "Add reference". On the .NET tab, choose SlimDX (.net 2.0, x86 version).
      • +
      • You can ignore the warning about missing JetBrains.Profiler.Core.Api reference. Everything should build fine, unless you choose a profiler-enabled build target (or you can use dotTrace Performance, if you have access to it).
      • +
      +
    6. +
    7. If you've made some code changes and want to submit them to the main GZDB repository, you can make a diff patch (right-click on the GZDB source folder and choose "TortioseSVN -> Create patch...") and post it at the official GZDB thread at ZDoom.org (http://forum.zdoom.org/viewtopic.php?f=3&t=32392&start=999999).
    8. +

    Batch files:

    GZDB source comes with several batch files, which can be used to automatically compile and package the editor. Before launching a batch file for the first time, make sure to open it and check that variables holding software paths point to the right directories. These variables are always located near the top of the file, after the info block.
      -
    • Clean Rebuild.bat - removes project cache files, then compiles it in Release mode.
      Requires Visual C# Express Edition / Visual Studio.

    • +
    • Clean Rebuild.bat - removes project cache files, then compiles it in Release mode.
      Requires Visual C# Express Edition / Visual Studio.

    • CompileHelp.bat - compiles "Build\Refmanual.chm". Help source files are located in the "Help" directory.
      Requires Microsoft HTML Help compiler.

    • MakeRelease.bat - removes project cache files, sets project version number to match the latest SVN revision, compiles the project in Release mode, generates "Build\Changelog.txt", compiles "Build\Refmanual.chm", creates an installer and places it in the "Release" folder.
      Requires Subversion command-line client, Visual C# Express Edition / Visual Studio, Microsoft HTML Help compiler and Inno Setup 5.

    • -
    • MakeSVNRelease.bat - removes project cache files, sets project version number to match the latest SVN revision, compiles the project in Release mode, generates "Build\Changelog.txt", compiles "Build\Refmanual.chm", packs the build into 7-zip archive and places it in the "SVN_Build" folder.
      Requires Subversion command-line client, Visual C# Express Edition / Visual Studio, Microsoft HTML Help compiler and 7-zip archiver.
    • +
    • MakeSVNRelease.bat - removes project cache files, sets project version number to match the latest SVN revision, compiles the project in Release mode, generates "Build\Changelog.txt", compiles "Build\Refmanual.chm", packs the build into 7-zip archive and places it in the "SVN_Build" folder.
      Requires Subversion command-line client, Visual C# Express Edition / Visual Studio, Microsoft HTML Help compiler and 7-zip archiver.
    diff --git a/Source/Core/Actions/ActionManager.cs b/Source/Core/Actions/ActionManager.cs index dbc4ae9..ee88257 100644 --- a/Source/Core/Actions/ActionManager.cs +++ b/Source/Core/Actions/ActionManager.cs @@ -193,7 +193,7 @@ namespace CodeImp.DoomBuilder.Actions else { // Action already exists! - General.ErrorLogger.Add(ErrorType.Warning, "Action '" + name + "' already exists. Action names must be unique."); + General.ErrorLogger.Add(ErrorType.Warning, "Action \"" + name + "\" already exists. Action names must be unique."); } } diff --git a/Source/Core/Actions/HintsManager.cs b/Source/Core/Actions/HintsManager.cs index 942665f..5c4a7fc 100644 --- a/Source/Core/Actions/HintsManager.cs +++ b/Source/Core/Actions/HintsManager.cs @@ -142,7 +142,7 @@ namespace CodeImp.DoomBuilder.Actions { General.Interface.ShowHints(DEFAULT_HINT); #if DEBUG - Console.WriteLine("WARNING: Unable to get hints for class '" + fullname + "', group '" + groupname + "'"); + Console.WriteLine("WARNING: Unable to get hints for class \"" + fullname + "\", group \"" + groupname + "\""); #endif return; } diff --git a/Source/Core/Builder.csproj b/Source/Core/Builder.csproj index 4bd3281..b09048e 100644 --- a/Source/Core/Builder.csproj +++ b/Source/Core/Builder.csproj @@ -1143,6 +1143,7 @@ + diff --git a/Source/Core/Compilers/Compiler.cs b/Source/Core/Compilers/Compiler.cs index 7289a4f..bbc18bf 100644 --- a/Source/Core/Compilers/Compiler.cs +++ b/Source/Core/Compilers/Compiler.cs @@ -76,9 +76,9 @@ namespace CodeImp.DoomBuilder.Compilers // Initialize this.info = info; this.errors = new List(); - this.includes = new HashSet(); //mxd - - General.WriteLogLine("Creating compiler '" + info.Name + "' on interface '" + this.GetType().Name + "'..."); + this.includes = new HashSet(StringComparer.OrdinalIgnoreCase); //mxd + + General.WriteLogLine("Creating compiler \"" + info.Name + "\" on interface \"" + this.GetType().Name + "\"..."); // Create temporary directory tempdir = Directory.CreateDirectory(General.MakeTempDirname()); @@ -146,7 +146,7 @@ namespace CodeImp.DoomBuilder.Compilers string srcfile = Path.Combine(info.Path, f); if(!File.Exists(srcfile)) { - General.ErrorLogger.Add(ErrorType.Error, "The file '" + f + "' required by the '" + info.Name + "' compiler is missing. According to the compiler configuration in '" + info.FileName + "', the was expected to be found in the following path: " + info.Path); + General.ErrorLogger.Add(ErrorType.Error, "The file \"" + f + "\" required by the \"" + info.Name + "\" compiler is missing. According to the compiler configuration in \"" + info.FileName + "\", it was expected to be found here: \"" + info.Path + "\""); } else { diff --git a/Source/Core/Config/ArgumentInfo.cs b/Source/Core/Config/ArgumentInfo.cs index e939553..7187af1 100644 --- a/Source/Core/Config/ArgumentInfo.cs +++ b/Source/Core/Config/ArgumentInfo.cs @@ -87,7 +87,7 @@ namespace CodeImp.DoomBuilder.Config } else { - General.ErrorLogger.Add(ErrorType.Warning, "'" + argspath + ".arg" + istr + "' references unknown enumeration '" + argdic["enum"] + "'."); + General.ErrorLogger.Add(ErrorType.Warning, "\"" + argspath + ".arg" + istr + "\" references unknown enumeration \"" + argdic["enum"] + "\"."); } } } diff --git a/Source/Core/Config/CompilerInfo.cs b/Source/Core/Config/CompilerInfo.cs index 3cd1c9f..65b7e9a 100644 --- a/Source/Core/Config/CompilerInfo.cs +++ b/Source/Core/Config/CompilerInfo.cs @@ -59,7 +59,7 @@ namespace CodeImp.DoomBuilder.Config // Constructor internal CompilerInfo(string filename, string name, string path, Configuration cfg) { - General.WriteLogLine("Registered compiler configuration '" + name + "' from '" + filename + "'"); + General.WriteLogLine("Registered compiler configuration \"" + name + "\" from \"" + filename + "\""); // Initialize this.filename = filename; @@ -80,7 +80,7 @@ namespace CodeImp.DoomBuilder.Config //mxd string include = de.Value.ToString().Replace(System.IO.Path.AltDirectorySeparatorChar, System.IO.Path.DirectorySeparatorChar); if(files.Contains(include)) - General.ErrorLogger.Add(ErrorType.Warning, "Include file '" + de.Value + "' is double-defined in '" + name + "' compiler configuration"); + General.ErrorLogger.Add(ErrorType.Warning, "Include file \"" + de.Value + "\" is double defined in \"" + name + "\" compiler configuration"); else files.Add(include); } diff --git a/Source/Core/Config/GeneralizedOption.cs b/Source/Core/Config/GeneralizedOption.cs index 3797388..794292d 100644 --- a/Source/Core/Config/GeneralizedOption.cs +++ b/Source/Core/Config/GeneralizedOption.cs @@ -76,7 +76,7 @@ namespace CodeImp.DoomBuilder.Config } else { - General.ErrorLogger.Add(ErrorType.Warning, "Structure '" + fullpath + "." + name + "' contains invalid entries. The keys must be numeric."); + General.ErrorLogger.Add(ErrorType.Warning, "Structure \"" + fullpath + "." + name + "\" contains invalid entries. The keys must be numeric."); } } diff --git a/Source/Core/Config/MapLumpInfo.cs b/Source/Core/Config/MapLumpInfo.cs index efecc10..802d369 100644 --- a/Source/Core/Config/MapLumpInfo.cs +++ b/Source/Core/Config/MapLumpInfo.cs @@ -55,7 +55,7 @@ namespace CodeImp.DoomBuilder.Config } else { - General.ErrorLogger.Add(ErrorType.Warning, "Map lump '" + name + "' in the current game configuration specifies an unknown script configuration '" + scriptconfig + "'. Using plain text instead."); + General.ErrorLogger.Add(ErrorType.Warning, "Map lump \"" + name + "\" in the current game configuration specifies an unknown script configuration \"" + scriptconfig + "\". Using plain text instead."); this.Script = new ScriptConfiguration(); } } diff --git a/Source/Core/Config/NodebuilderInfo.cs b/Source/Core/Config/NodebuilderInfo.cs index 8dcb20d..7649c72 100644 --- a/Source/Core/Config/NodebuilderInfo.cs +++ b/Source/Core/Config/NodebuilderInfo.cs @@ -55,7 +55,7 @@ namespace CodeImp.DoomBuilder.Config // Constructor public NodebuilderInfo(string filename, string name, Configuration cfg) { - General.WriteLogLine("Registered nodebuilder configuration '" + name + "' from '" + filename + "'"); + General.WriteLogLine("Registered nodebuilder configuration \"" + name + "\" from \"" + filename + "\""); // Initialize this.name = name; @@ -80,7 +80,7 @@ namespace CodeImp.DoomBuilder.Config } // No compiler found? - if(this.compiler == null) throw new Exception("No such compiler defined: '" + compilername + "'"); + if(this.compiler == null) throw new Exception("Compiler \"" + compilername + "\" is not defined"); } // Constructor for "none" nodebuilder diff --git a/Source/Core/Config/ProgramConfiguration.cs b/Source/Core/Config/ProgramConfiguration.cs index e7d1e32..7d6947c 100644 --- a/Source/Core/Config/ProgramConfiguration.cs +++ b/Source/Core/Config/ProgramConfiguration.cs @@ -85,7 +85,8 @@ namespace CodeImp.DoomBuilder.Config private float filteranisotropy; private bool showtexturesizes; private bool locatetexturegroup; //mxd - private SplitLineBehavior splitlinebehavior; //mxd + private bool keeptexturefilterfocused; //mxd + private SplitLineBehavior splitlinebehavior; //mxd //mxd. Script editor settings private string scriptfontname; @@ -131,7 +132,8 @@ namespace CodeImp.DoomBuilder.Config private bool storeSelectedEditTab; private int maxbackups; private bool checkforupdates; - private bool rendercomments; + private bool rendercomments; //mxd + private bool fixedthingsscale; //mxd private bool rendergrid; private bool rendernightspath; private bool dynamicgridsize; @@ -194,6 +196,7 @@ namespace CodeImp.DoomBuilder.Config public float FilterAnisotropy { get { return filteranisotropy; } internal set { filteranisotropy = value; } } public bool ShowTextureSizes { get { return showtexturesizes; } internal set { showtexturesizes = value; } } public bool LocateTextureGroup { get { return locatetexturegroup; } internal set { locatetexturegroup = value; } } //mxd + public bool KeepTextureFilterFocused { get { return keeptexturefilterfocused; } internal set { keeptexturefilterfocused = value; } } //mxd public SplitLineBehavior SplitLineBehavior { get { return splitlinebehavior; } set { splitlinebehavior = value; } } //mxd //mxd. Script editor settings @@ -241,6 +244,7 @@ namespace CodeImp.DoomBuilder.Config internal int MaxBackups { get { return maxbackups; } set { maxbackups = value; } } internal bool CheckForUpdates { get { return checkforupdates; } set { checkforupdates = value; } } //mxd public bool RenderComments { get { return rendercomments; } internal set { rendercomments = value; } } //mxd + public bool FixedThingsScale { get { return fixedthingsscale; } internal set { fixedthingsscale = value; } } //mxd public bool RenderGrid { get { return rendergrid; } internal set { rendergrid = value; } } //mxd public bool RenderNiGHTSPath { get { return rendernightspath; } internal set { rendernightspath = value; } } public bool DynamicGridSize { get { return dynamicgridsize; } internal set { dynamicgridsize = value; } } //mxd @@ -326,6 +330,7 @@ namespace CodeImp.DoomBuilder.Config filteranisotropy = cfg.ReadSetting("filteranisotropy", 8.0f); showtexturesizes = cfg.ReadSetting("showtexturesizes", true); locatetexturegroup = cfg.ReadSetting("locatetexturegroup", true); //mxd + keeptexturefilterfocused = cfg.ReadSetting("keeptexturefilterfocused", true); //mxd splitlinebehavior = (SplitLineBehavior) General.Clamp(cfg.ReadSetting("splitlinebehavior", 0), 0, 3); //mxd //mxd. Script editor @@ -371,6 +376,7 @@ namespace CodeImp.DoomBuilder.Config maxbackups = cfg.ReadSetting("maxbackups", 3); checkforupdates = false; //No update checking for Zone Builder rendercomments = cfg.ReadSetting("rendercomments", true); //mxd + fixedthingsscale = cfg.ReadSetting("fixedthingsscale", false); //mxd rendergrid = cfg.ReadSetting("rendergrid", true); //mxd rendernightspath = cfg.ReadSetting("rendernightspath", true); dynamicgridsize = cfg.ReadSetting("dynamicgridsize", true); //mxd @@ -438,6 +444,7 @@ namespace CodeImp.DoomBuilder.Config cfg.WriteSetting("filteranisotropy", filteranisotropy); cfg.WriteSetting("showtexturesizes", showtexturesizes); cfg.WriteSetting("locatetexturegroup", locatetexturegroup); //mxd + cfg.WriteSetting("keeptexturefilterfocused", keeptexturefilterfocused); //mxd cfg.WriteSetting("splitlinebehavior", (int)splitlinebehavior); //mxd //mxd. Script editor @@ -485,6 +492,7 @@ namespace CodeImp.DoomBuilder.Config cfg.WriteSetting("maxbackups", maxbackups); //cfg.WriteSetting("checkforupdates", checkforupdates); //mxd cfg.WriteSetting("rendercomments", rendercomments); //mxd + cfg.WriteSetting("fixedthingsscale", fixedthingsscale); //mxd cfg.WriteSetting("rendergrid", rendergrid); //mxd cfg.WriteSetting("rendernightspath", rendernightspath); //mxd cfg.WriteSetting("dynamicgridsize", dynamicgridsize); //mxd @@ -498,7 +506,7 @@ namespace CodeImp.DoomBuilder.Config cfg.WriteSetting("defaultbrightness", defaultbrightness); // Save settings configuration - General.WriteLogLine("Saving program configuration to '" + filepathname + "'..."); + General.WriteLogLine("Saving program configuration to \"" + filepathname + "\"..."); cfg.SaveConfiguration(filepathname); } diff --git a/Source/Core/Config/ScriptConfiguration.cs b/Source/Core/Config/ScriptConfiguration.cs index f9c5557..f389cfc 100644 --- a/Source/Core/Config/ScriptConfiguration.cs +++ b/Source/Core/Config/ScriptConfiguration.cs @@ -28,12 +28,20 @@ using ScintillaNET; namespace CodeImp.DoomBuilder.Config { //mxd - internal enum ScriptType + public enum ScriptType { UNKNOWN = 0, ACS = 1, MODELDEF = 2, DECORATE = 3, + GLDEFS = 4, + SNDSEQ = 5, + MAPINFO = 6, + VOXELDEF = 7, + TEXTURES = 8, + ANIMDEFS = 9, + REVERBS = 10, + TERRAIN = 11, } internal class ScriptConfiguration : IComparable @@ -214,7 +222,7 @@ namespace CodeImp.DoomBuilder.Config string keyword = de.Key.ToString(); if(keywords.ContainsKey(keyword)) //mxd { - General.ErrorLogger.Add(ErrorType.Warning, "Keyword \"" + keyword + "\" is double-defined in \"" + description + "\" script configuration."); + General.ErrorLogger.Add(ErrorType.Warning, "Keyword \"" + keyword + "\" is double defined in \"" + description + "\" script configuration."); continue; } @@ -226,16 +234,16 @@ namespace CodeImp.DoomBuilder.Config //mxd. Sort keywords lookup keywordkeyssorted.Sort(); - //mxd. Load properties - dic = cfg.ReadSetting("properties", new Hashtable()); - foreach (DictionaryEntry de in dic) - { - string property = de.Key.ToString(); - if (lowerproperties.ContainsValue(property)) //mxd - { - General.ErrorLogger.Add(ErrorType.Warning, "Property \"" + property + "\" is double-defined in \"" + description + "\" script configuration."); - continue; - } + //mxd. Load properties + dic = cfg.ReadSetting("properties", new Hashtable()); + foreach(DictionaryEntry de in dic) + { + string property = de.Key.ToString(); + if(lowerproperties.ContainsValue(property)) //mxd + { + General.ErrorLogger.Add(ErrorType.Warning, "Property \"" + property + "\" is double defined in \"" + description + "\" script configuration."); + continue; + } properties.Add(property); lowerproperties[property.ToLowerInvariant()] = property; @@ -248,12 +256,12 @@ namespace CodeImp.DoomBuilder.Config dic = cfg.ReadSetting("constants", new Hashtable()); foreach(DictionaryEntry de in dic) { - string constant = de.Key.ToString(); - if (lowerconstants.ContainsValue(constant)) //mxd - { - General.ErrorLogger.Add(ErrorType.Warning, "Constant \"" + constant + "\" is double-defined in \"" + description + "\" script configuration."); - continue; - } + string constant = de.Key.ToString(); + if(lowerconstants.ContainsValue(constant)) //mxd + { + General.ErrorLogger.Add(ErrorType.Warning, "Constant \"" + constant + "\" is double defined in \"" + description + "\" script configuration."); + continue; + } constants.Add(constant); lowerconstants[constant.ToLowerInvariant()] = constant; @@ -275,10 +283,10 @@ namespace CodeImp.DoomBuilder.Config foreach (string file in files) { string name = Path.GetFileNameWithoutExtension(file); - if (string.IsNullOrEmpty(name)) - { - General.ErrorLogger.Add(ErrorType.Warning, "Failed to load snippet '" + file + "' for '" + description + "' script configuration."); - } + if(string.IsNullOrEmpty(name)) + { + General.ErrorLogger.Add(ErrorType.Warning, "Failed to load snippet \"" + file + "\" for \"" + description + "\" script configuration."); + } else { if (name.Contains(" ")) name = name.Replace(' ', '_'); @@ -290,37 +298,36 @@ namespace CodeImp.DoomBuilder.Config } else { - General.ErrorLogger.Add(ErrorType.Warning, "Failed to load snippet '" + file + "' for '" + description + "' script configuration: file is empty!"); + General.ErrorLogger.Add(ErrorType.Warning, "Failed to load snippet \"" + file + "\" for \"" + description + "\" script configuration: file is empty!"); } } } - //mxd. Sort snippets lookup - sortedkeys.Sort(); - snippetkeyssorted = new HashSet(sortedkeys, StringComparer.OrdinalIgnoreCase); - - } - } - - // Compiler specified? - if (compilername.Length > 0) - { - // Find compiler - foreach (CompilerInfo c in General.Compilers) - { - // Compiler name matches? - if (c.Name == compilername) - { - // Apply compiler - this.compiler = c; - break; - } - } - - // No compiler found? - if (this.compiler == null) throw new Exception("No such compiler defined: '" + compilername + "'"); - } - } + //mxd. Sort snippets lookup + sortedkeys.Sort(); + snippetkeyssorted = new HashSet(sortedkeys, StringComparer.OrdinalIgnoreCase); + } + } + + // Compiler specified? + if(compilername.Length > 0) + { + // Find compiler + foreach(CompilerInfo c in General.Compilers) + { + // Compiler name matches? + if(c.Name == compilername) + { + // Apply compiler + this.compiler = c; + break; + } + } + + // No compiler found? + if(this.compiler == null) throw new Exception("Compiler \"" + compilername + "\" is not defined"); + } + } #endregion diff --git a/Source/Core/Config/ThingCategory.cs b/Source/Core/Config/ThingCategory.cs index 05cbbab..06db6ac 100644 --- a/Source/Core/Config/ThingCategory.cs +++ b/Source/Core/Config/ThingCategory.cs @@ -293,7 +293,7 @@ namespace CodeImp.DoomBuilder.Config if(child.IsValid && child.things.Count > 0) { if(cats.ContainsKey(child.title.ToLowerInvariant())) - General.ErrorLogger.Add(ErrorType.Warning, "Thing Category '" + child.title + "' is double-defined in " + this.title); + General.ErrorLogger.Add(ErrorType.Warning, "Thing Category \"" + child.title + "\" is double defined in " + this.title); cats[child.title.ToLowerInvariant()] = child; } } diff --git a/Source/Core/Config/ThingTypeInfo.cs b/Source/Core/Config/ThingTypeInfo.cs index a15f4bd..3bd3ec9 100644 --- a/Source/Core/Config/ThingTypeInfo.cs +++ b/Source/Core/Config/ThingTypeInfo.cs @@ -559,7 +559,7 @@ namespace CodeImp.DoomBuilder.Config //mxd. Marked as obsolete? if(actor.HasPropertyWithValue("$obsolete")) { - obsoletemessage = ZDTextParser.StripQuotes(actor.GetPropertyValueString("$obsolete", 0)); + obsoletemessage = actor.GetPropertyValueString("$obsolete", 0, true); obsolete = true; color = 4; //red } @@ -591,7 +591,8 @@ namespace CodeImp.DoomBuilder.Config if(actor.HasPropertyWithValue("height")) height = actor.GetPropertyValueInt("height", 0); //mxd. Renderstyle - if(actor.HasPropertyWithValue("renderstyle")) renderstyle = actor.GetPropertyValueString("renderstyle", 0).ToLower(); + if(actor.HasPropertyWithValue("renderstyle") && !actor.HasProperty("$ignorerenderstyle")) + renderstyle = actor.GetPropertyValueString("renderstyle", 0, true).ToLower(); //mxd. Alpha if(actor.HasPropertyWithValue("alpha")) diff --git a/Source/Core/Config/ThingsFlagsCompare.cs b/Source/Core/Config/ThingsFlagsCompare.cs index fcbb4a5..365c0f8 100644 --- a/Source/Core/Config/ThingsFlagsCompare.cs +++ b/Source/Core/Config/ThingsFlagsCompare.cs @@ -47,7 +47,7 @@ namespace CodeImp.DoomBuilder.Config // Duplicate flags check if(Flags.ContainsKey(flag)) - General.ErrorLogger.Add(ErrorType.Warning, "ThingFlagsCompare flag '" + flag + "' is double-defined in '" + name + "' group"); + General.ErrorLogger.Add(ErrorType.Warning, "ThingFlagsCompare flag \"" + flag + "\" is double defined in the \"" + name + "\" group"); Flags[flag] = new ThingFlagsCompare(cfg, name, flag); } @@ -294,7 +294,7 @@ namespace CodeImp.DoomBuilder.Config result.Add("Thing is not used by any class."); break; default: - result.Add("At least one '" + group.Key + "' flag should be set."); + result.Add("At least one \"" + group.Key + "\" flag should be set."); break; } } diff --git a/Source/Core/Controls/ArgumentBox.cs b/Source/Core/Controls/ArgumentBox.cs index 37e5293..04e9a03 100644 --- a/Source/Core/Controls/ArgumentBox.cs +++ b/Source/Core/Controls/ArgumentBox.cs @@ -242,7 +242,7 @@ namespace CodeImp.DoomBuilder.Controls //mxd. this sets default value public void SetDefaultValue() { - typehandler.SetDefaultValue(); + typehandler.ApplyDefaultValue(); combobox.SelectedItem = null; combobox.Text = typehandler.GetStringValue(); combobox_Validating(this, new CancelEventArgs()); diff --git a/Source/Core/Controls/ArgumentsControl.cs b/Source/Core/Controls/ArgumentsControl.cs index a511c61..fe9b817 100644 --- a/Source/Core/Controls/ArgumentsControl.cs +++ b/Source/Core/Controls/ArgumentsControl.cs @@ -204,15 +204,21 @@ namespace CodeImp.DoomBuilder.Controls { // Update arguments int showaction = 0; + ArgumentInfo[] oldarginfo = (arginfo != null ? (ArgumentInfo[])arginfo.Clone() : null); //mxd // Only when action type is known if(General.Map.Config.LinedefActions.ContainsKey(action)) showaction = action; + + // Update argument infos if((showaction == 0) && (info != null)) arginfo = info.Args; else arginfo = General.Map.Config.LinedefActions[showaction].Args; // Don't update action args when thing type is changed if(info != null && showaction != 0 && this.action == showaction) return; + //mxd. Don't update action args when old and new argument infos match + if(arginfo != null && oldarginfo != null && ArgumentInfosMatch(arginfo, oldarginfo)) return; + // Change the argument descriptions this.BeginUpdate(); @@ -387,6 +393,24 @@ namespace CodeImp.DoomBuilder.Controls } } + //mxd + private static bool ArgumentInfosMatch(ArgumentInfo[] info1, ArgumentInfo[] info2) + { + if(info1.Length != info2.Length) return false; + bool haveusedargs = false; // Arguments should still be reset if all arguments are unused + + for(int i = 0; i < info1.Length; i++) + { + if(info1[i].Used != info1[2].Used || info1[i].Type != info1[2].Type + || info1[i].Title.ToUpperInvariant() != info2[i].Title.ToUpperInvariant()) + return false; + + haveusedargs |= (info1[i].Used || info1[2].Used); + } + + return haveusedargs; + } + #endregion #region ================== Redraw control diff --git a/Source/Core/Controls/FieldsEditorControl.cs b/Source/Core/Controls/FieldsEditorControl.cs index 9b4fe13..dc095c2 100644 --- a/Source/Core/Controls/FieldsEditorControl.cs +++ b/Source/Core/Controls/FieldsEditorControl.cs @@ -61,27 +61,27 @@ namespace CodeImp.DoomBuilder.Controls private string lasteditfieldname; private bool autoinsertuserprefix; private Dictionary uifields;//mxd - private bool showfixedfields = true; //mxd + private bool showfixedfields = true; //mxd + + #endregion - #endregion + #region ================== Properties - #region ================== Properties - - public bool AllowInsert { get { return fieldslist.AllowUserToAddRows; } set { fieldslist.AllowUserToAddRows = value; SetupNewRowStyle(); } } + public bool AllowInsert { get { return fieldslist.AllowUserToAddRows; } set { fieldslist.AllowUserToAddRows = value; SetupNewRowStyle(); } } public bool AutoInsertUserPrefix { get { return autoinsertuserprefix; } set { autoinsertuserprefix = value; } } public int PropertyColumnWidth { get { return fieldname.Width; } set { fieldname.Width = value; UpdateValueColumn(); UpdateBrowseButton(); } } public int TypeColumnWidth { get { return fieldtype.Width; } set { fieldtype.Width = value; UpdateValueColumn(); UpdateBrowseButton(); } } public bool PropertyColumnVisible { get { return fieldname.Visible; } set { fieldname.Visible = value; UpdateValueColumn(); UpdateBrowseButton(); } } public bool TypeColumnVisible { get { return fieldtype.Visible; } set { fieldtype.Visible = value; UpdateValueColumn(); UpdateBrowseButton(); } } public bool ValueColumnVisible { get { return fieldvalue.Visible; } set { fieldvalue.Visible = value; UpdateValueColumn(); UpdateBrowseButton(); } } - public bool ShowFixedFields { get { return showfixedfields; } set { showfixedfields = value; UpdateFixedFieldsVisibility(); } } //mxd + public bool ShowFixedFields {get { return showfixedfields; } set { showfixedfields = value; UpdateFixedFieldsVisibility(); } } //mxd - #endregion + #endregion - #region ================== Constructor + #region ================== Constructor - // Constructor - public FieldsEditorControl() + // Constructor + public FieldsEditorControl() { InitializeComponent(); autoinsertuserprefix = true; @@ -171,6 +171,7 @@ namespace CodeImp.DoomBuilder.Controls // Go for all rows bool foundrow = false; + bool skiprow = false; //mxd foreach(DataGridViewRow row in fieldslist.Rows) { // Row is a field? @@ -181,11 +182,18 @@ namespace CodeImp.DoomBuilder.Controls // Row name matches with field if(frow.Name == f.Key) { + //mxd. User vars are set separately + if(frow.RowType == FieldsEditorRowType.USERVAR) + { + skiprow = true; + break; + } + // First time? if(first) { // Set type when row is not fixed - if(!frow.IsFixed) frow.ChangeType(f.Value.Type); + if(frow.RowType == FieldsEditorRowType.DYNAMIC) frow.ChangeType(f.Value.Type); // Apply value of field to row frow.Define(f.Value.Value); @@ -207,16 +215,18 @@ namespace CodeImp.DoomBuilder.Controls } } } + + //mxd. User vars are set separately + if(skiprow) continue; // Row not found? if(!foundrow) { // Make new row - FieldsEditorRow frow = new FieldsEditorRow(fieldslist, f.Key, f.Value.Type, f.Value.Value); + FieldsEditorRow frow = new FieldsEditorRow(fieldslist, f.Key, f.Value.Type, f.Value.Value, false); fieldslist.Rows.Insert(fieldslist.Rows.Count - 1, frow); - // When not the first, clear the field - // because the others did not define this one + // When not the first, clear the field because the others did not define this one if(!first) frow.Clear(); } } @@ -245,6 +255,82 @@ namespace CodeImp.DoomBuilder.Controls // Sort fields Sort(); } + + //mxd + public void SetUserVars(Dictionary vars, UniFields fromfields, bool first) + { + foreach(KeyValuePair group in vars) + { + // Go for all rows + bool foundrow = false; + TypeHandler vartype = General.Types.GetFieldHandler((int)group.Value, 0); + object value = fromfields.ContainsKey(group.Key) ? fromfields[group.Key].Value : vartype.GetDefaultValue(); + + foreach(DataGridViewRow row in fieldslist.Rows) + { + // Row is a field? + if(row is FieldsEditorRow) + { + FieldsEditorRow frow = row as FieldsEditorRow; + + // Row name matches with user var? + if(frow.RowType == FieldsEditorRowType.USERVAR && frow.Name == group.Key) + { + // First time? + if(first) + { + frow.Define(value); + } + // Check if the value is different + else if(!frow.TypeHandler.GetValue().Equals(value)) + { + // Clear the value in the row + frow.Define(value); + frow.Clear(); + } + + // Done + foundrow = true; + break; + } + } + } + + // Row not found? + if(!foundrow) + { + // Make new row + object defaultvalue = vartype.GetDefaultValue(); + FieldsEditorRow frow = new FieldsEditorRow(fieldslist, group.Key, (int)group.Value, defaultvalue, true); + if(!value.Equals(defaultvalue)) frow.Define(value); + fieldslist.Rows.Insert(fieldslist.Rows.Count - 1, frow); + } + } + + // Now check for rows that the givens fields do NOT have + foreach(DataGridViewRow row in fieldslist.Rows) + { + // Row is a field? + if(row is FieldsEditorRow) + { + FieldsEditorRow frow = row as FieldsEditorRow; + + // Don't undefine user var rows defined by other actor types + if(frow.RowType != FieldsEditorRowType.USERVAR || !vars.ContainsKey(frow.Name)) continue; + + // Is this row defined previously? + if(frow.IsDefined) + { + // Check if this row can not be found in the fields at all + if(!fromfields.ContainsKey(frow.Name)) + { + // It is not defined in these fields, undefine the value + frow.Undefine(); + } + } + } + } + } // This applies the current fields to a UniFields object public void Apply(UniFields tofields) @@ -259,6 +345,7 @@ namespace CodeImp.DoomBuilder.Controls // Go for all rows bool foundrow = false; + bool skiprow = false; //mxd foreach(DataGridViewRow row in fieldslist.Rows) { // Row is a field and matches field name? @@ -266,6 +353,13 @@ namespace CodeImp.DoomBuilder.Controls { FieldsEditorRow frow = row as FieldsEditorRow; + //mxd. User vars are stored separately + if(frow.RowType == FieldsEditorRowType.USERVAR) + { + skiprow = true; + break; + } + // Field is defined? if(frow.IsDefined) { @@ -275,6 +369,9 @@ namespace CodeImp.DoomBuilder.Controls } } + //mxd. User vars are stored separately + if(skiprow) continue; + // No such row? if(!foundrow) { @@ -292,7 +389,7 @@ namespace CodeImp.DoomBuilder.Controls FieldsEditorRow frow = row as FieldsEditorRow; // Field is defined and not empty? - if(frow.IsDefined && !frow.IsEmpty) + if(frow.RowType != FieldsEditorRowType.USERVAR && frow.IsDefined && !frow.IsEmpty) { // Apply field object oldvalue = null; @@ -300,7 +397,7 @@ namespace CodeImp.DoomBuilder.Controls tofields[frow.Name] = new UniValue(frow.TypeHandler.Index, frow.GetResult(oldvalue)); // Custom row? - if(!frow.IsFixed) + if(frow.RowType == FieldsEditorRowType.DYNAMIC) { // Write type to map configuration General.Map.Options.SetUniversalFieldType(elementname, frow.Name, frow.TypeHandler.Index); @@ -310,6 +407,38 @@ namespace CodeImp.DoomBuilder.Controls } } + //mxd + public void ApplyUserVars(Dictionary vars, UniFields tofields) + { + // Apply user variables when target map element contains user var definition and the value is not default + foreach(DataGridViewRow row in fieldslist.Rows) + { + // Row is a field? + if(row is FieldsEditorRow) + { + FieldsEditorRow frow = row as FieldsEditorRow; + if(frow.RowType != FieldsEditorRowType.USERVAR || !vars.ContainsKey(frow.Name)) continue; + + object oldvalue = (tofields.ContainsKey(frow.Name) ? tofields[frow.Name].Value : null); + object newvalue = frow.GetResult(oldvalue); + + // Skip field when mixed values + if(newvalue == null) continue; + + // Remove field + if(newvalue.Equals(frow.TypeHandler.GetDefaultValue())) + { + if(tofields.ContainsKey(frow.Name)) tofields.Remove(frow.Name); + } + // Add field + else if(!newvalue.Equals(oldvalue)) + { + tofields[frow.Name] = new UniValue(frow.TypeHandler.Index, newvalue); + } + } + } + } + #endregion #region ================== Events @@ -377,16 +506,16 @@ namespace CodeImp.DoomBuilder.Controls // First column? if(e.ColumnIndex == 0) { - // Not a fixed field? - if((frow != null) && !frow.IsFixed) + // Dynamic field? + if((frow != null) && frow.RowType == FieldsEditorRowType.DYNAMIC) { lasteditfieldname = frow.Name; fieldslist.CurrentCell = fieldslist.SelectedRows[0].Cells[0]; fieldslist.CurrentCell.ReadOnly = false; - if((e.RowIndex == fieldslist.NewRowIndex) || - frow.Name.StartsWith(FIELD_PREFIX_SUGGESTION, StringComparison.OrdinalIgnoreCase)) - fieldslist.BeginEdit(false); + if((e.RowIndex == fieldslist.NewRowIndex) || + frow.Name.StartsWith(FIELD_PREFIX_SUGGESTION, StringComparison.OrdinalIgnoreCase)) + fieldslist.BeginEdit(false); else fieldslist.BeginEdit(true); } @@ -399,21 +528,20 @@ namespace CodeImp.DoomBuilder.Controls { // Get the row FieldsEditorRow row = e.Row as FieldsEditorRow; + if(row == null) return; - // Fixed field? - if(row.IsFixed) + // Fixed/uservar field? + if(row.RowType == FieldsEditorRowType.FIXED || row.RowType == FieldsEditorRowType.USERVAR) { // Just undefine the field row.Undefine(); e.Cancel = true; - if(OnFieldUndefined != null) - OnFieldUndefined(row.Name); + if(OnFieldUndefined != null) OnFieldUndefined(row.Name); } else { - if(OnFieldDeleted != null) - OnFieldDeleted(row.Name); + if(OnFieldDeleted != null) OnFieldDeleted(row.Name); } } @@ -428,10 +556,7 @@ namespace CodeImp.DoomBuilder.Controls { // Remove all text fieldslist.Rows[e.RowIndex].Cells[0].Style.ForeColor = SystemColors.WindowText; - if(autoinsertuserprefix) - fieldslist.Rows[e.RowIndex].Cells[0].Value = FIELD_PREFIX_SUGGESTION; - else - fieldslist.Rows[e.RowIndex].Cells[0].Value = ""; + fieldslist.Rows[e.RowIndex].Cells[0].Value = (autoinsertuserprefix ? FIELD_PREFIX_SUGGESTION : string.Empty); } } // Value cell? @@ -470,13 +595,13 @@ namespace CodeImp.DoomBuilder.Controls // Select the value of this field (for DropDownList style combo) foreach(EnumItem i in enumscombo.Items) { - // Matches? - if (string.Compare(i.Title, frow.TypeHandler.GetStringValue(), StringComparison.OrdinalIgnoreCase) == 0) - { + // Matches? + if(string.Compare(i.Title, frow.TypeHandler.GetStringValue(), StringComparison.OrdinalIgnoreCase) == 0) + { // Select this item enumscombo.SelectedItem = i; - break; //mxd - } + break; //mxd + } } // Put the display text in the text (for DropDown style combo) @@ -538,12 +663,11 @@ namespace CodeImp.DoomBuilder.Controls int type = General.Map.Options.GetUniversalFieldType(elementname, validname, 0); // Make new row - frow = new FieldsEditorRow(fieldslist, validname, type, null); + frow = new FieldsEditorRow(fieldslist, validname, type, null, false); frow.Visible = false; fieldslist.Rows.Insert(e.RowIndex + 1, frow); - if(OnFieldInserted != null) - OnFieldInserted(validname); + if(OnFieldInserted != null) OnFieldInserted(validname); } } } @@ -587,11 +711,8 @@ namespace CodeImp.DoomBuilder.Controls row.Cells[0].Value = validname; if(type != -1) frow.ChangeType(type); - if(OnFieldNameChanged != null) - OnFieldNameChanged(lasteditfieldname, validname); - - if(OnFieldTypeChanged != null) - OnFieldTypeChanged(validname); + if(OnFieldNameChanged != null) OnFieldNameChanged(lasteditfieldname, validname); + if(OnFieldTypeChanged != null) OnFieldTypeChanged(validname); } else { @@ -615,8 +736,7 @@ namespace CodeImp.DoomBuilder.Controls // Changing field type? if((e.ColumnIndex == 1) && (frow != null)) { - if(OnFieldTypeChanged != null) - OnFieldTypeChanged(frow.Name); + if(OnFieldTypeChanged != null) OnFieldTypeChanged(frow.Name); } // Changing field value? if((e.ColumnIndex == 2) && (frow != null)) @@ -641,18 +761,18 @@ namespace CodeImp.DoomBuilder.Controls // Delete all rows that must be deleted for(int i = fieldslist.Rows.Count - 1; i >= 0; i--) { - if (fieldslist.Rows[i].ReadOnly) - { - try { fieldslist.Rows.RemoveAt(i); } catch { } - } - else - { - //mxd. Preserve fixed fields visibility setting - FieldsEditorRow frow = (fieldslist.Rows[i] as FieldsEditorRow); - if (frow != null && frow.IsFixed) frow.Visible = showfixedfields; - else fieldslist.Rows[i].Visible = true; - } - } + if(fieldslist.Rows[i].ReadOnly) + { + try { fieldslist.Rows.RemoveAt(i); } catch { } + } + else + { + //mxd. Preserve fixed fields visibility setting + FieldsEditorRow frow = (fieldslist.Rows[i] as FieldsEditorRow); + if(frow != null && frow.RowType == FieldsEditorRowType.FIXED) frow.Visible = showfixedfields; + else fieldslist.Rows[i].Visible = true; + } + } // Update new row SetupNewRowStyle(); @@ -730,17 +850,17 @@ namespace CodeImp.DoomBuilder.Controls private void ApplyValue(FieldsEditorRow frow, object value) { // Defined? - if((value != null) && (!frow.IsFixed || !frow.Info.Default.Equals(value))) + if((value != null) && (frow.RowType == FieldsEditorRowType.DYNAMIC || frow.RowType == FieldsEditorRowType.USERVAR + || !frow.Info.Default.Equals(value))) { frow.Define(value); } - else if(frow.IsFixed) + else if(frow.RowType == FieldsEditorRowType.FIXED) { frow.Undefine(); } - if(OnFieldValueChanged != null) - OnFieldValueChanged(frow.Name); + if(OnFieldValueChanged != null) OnFieldValueChanged(frow.Name); } // This applies the contents of the enums combobox and hides (if opened) @@ -841,16 +961,16 @@ namespace CodeImp.DoomBuilder.Controls } } - //mxd - private void UpdateFixedFieldsVisibility() - { - foreach (var row in fieldslist.Rows) - { - FieldsEditorRow frow = (row as FieldsEditorRow); - if (frow != null && frow.IsFixed) frow.Visible = showfixedfields; - } - } - - #endregion - } + //mxd + private void UpdateFixedFieldsVisibility() + { + foreach(var row in fieldslist.Rows) + { + FieldsEditorRow frow = (row as FieldsEditorRow); + if(frow != null && frow.RowType == FieldsEditorRowType.FIXED) frow.Visible = showfixedfields; + } + } + + #endregion + } } diff --git a/Source/Core/Controls/FieldsEditorRow.cs b/Source/Core/Controls/FieldsEditorRow.cs index 6a27630..99f647b 100644 --- a/Source/Core/Controls/FieldsEditorRow.cs +++ b/Source/Core/Controls/FieldsEditorRow.cs @@ -26,6 +26,23 @@ using CodeImp.DoomBuilder.Types; namespace CodeImp.DoomBuilder.Controls { + internal enum FieldsEditorRowType //mxd + { + // This is a fixed field defined in the game configuration + // The field cannot be deleted (delete will result in a reset) + // and cannot change type. + FIXED, + + // This is an abstartct variable field enetered by user + // The field can be deleted and can change type. + DYNAMIC, + + // This is a user variable field defined in actor's DECORATE + // The field cannot be deleted (delete will result in a reset) + // but can change type. + USERVAR, + } + internal class FieldsEditorRow : DataGridViewRow { #region ================== Constants @@ -34,13 +51,11 @@ namespace CodeImp.DoomBuilder.Controls #region ================== Variables - // This is true when for a fixed field as defined in the game configuration - // This means that the field cannot be deleted (delete will result in a reset) - // and cannot change type. - private bool isfixed; + //mxd. Row type + private readonly FieldsEditorRowType rowtype; // Field information (only for fixed fields) - private UniversalFieldInfo fieldinfo; + private readonly UniversalFieldInfo fieldinfo; // This is true when the field is defined. Cannot be false when this field // is not fixed, because non-fixed fields are deleted from the list when undefined. @@ -53,7 +68,7 @@ namespace CodeImp.DoomBuilder.Controls #region ================== Properties - public bool IsFixed { get { return isfixed; } } + public FieldsEditorRowType RowType { get { return rowtype; } } //mxd public bool IsDefined { get { return isdefined; } } public bool IsEmpty { get { return (this.Cells[2].Value == null) || (this.Cells[2].Value.ToString().Length == 0); } } public string Name { get { return this.Cells[0].Value.ToString(); } } @@ -73,7 +88,7 @@ namespace CodeImp.DoomBuilder.Controls // Fixed this.fieldinfo = fixedfield; - isfixed = true; + this.rowtype = FieldsEditorRowType.FIXED; //mxd // Type this.fieldtype = General.Types.GetFieldHandler(fixedfield); @@ -97,31 +112,54 @@ namespace CodeImp.DoomBuilder.Controls } // Constructor for a non-fixed, defined field - public FieldsEditorRow(DataGridView view, string name, int type, object value) + //mxd. Also for a user variable field. + public FieldsEditorRow(DataGridView view, string name, int type, object value, bool isuservar) { - // Defined - this.DefaultCellStyle.ForeColor = SystemColors.WindowText; - isdefined = true; - - // Non-fixed - isfixed = false; + //mxd. Row type + this.rowtype = (isuservar ? FieldsEditorRowType.USERVAR : FieldsEditorRowType.DYNAMIC); // Type this.fieldtype = General.Types.GetFieldHandler(type, value); // Make all cells base.CreateCells(view); - - // Setup property cell - this.Cells[0].Value = name; - this.Cells[0].ReadOnly = true; - // Setup type cell - this.Cells[1].Value = fieldtype.GetDisplayType(); - this.Cells[1].ReadOnly = false; + //mxd. Our path splits here... + if(isuservar) + { + // Not defined + this.DefaultCellStyle.ForeColor = SystemColors.GrayText; + isdefined = false; + fieldtype.ApplyDefaultValue(); - // Setup value cell - this.Cells[2].Value = fieldtype.GetStringValue(); + // Setup property cell + this.Cells[0].Value = name; + this.Cells[0].ReadOnly = true; + + // Setup type cell + this.Cells[1].Value = fieldtype.GetDisplayType(); + this.Cells[1].ReadOnly = true; + + // Setup value cell + this.Cells[2].Value = fieldtype.GetStringValue(); + } + else + { + // Defined + this.DefaultCellStyle.ForeColor = SystemColors.WindowText; + isdefined = true; + + // Setup property cell + this.Cells[0].Value = name; + this.Cells[0].ReadOnly = true; + + // Setup type cell + this.Cells[1].Value = fieldtype.GetDisplayType(); + this.Cells[1].ReadOnly = false; + + // Setup value cell + this.Cells[2].Value = fieldtype.GetStringValue(); + } // We have no destructor GC.SuppressFinalize(this); @@ -140,7 +178,7 @@ namespace CodeImp.DoomBuilder.Controls fieldtype.Browse(parent); // This is a fixed field? - if(isfixed) + if(rowtype == FieldsEditorRowType.FIXED) { // Does this match the default setting? if(fieldtype.GetValue().Equals(fieldinfo.Default)) @@ -188,7 +226,7 @@ namespace CodeImp.DoomBuilder.Controls this.Cells[2].Value = fieldtype.GetStringValue(); // This is a fixed field? - if(isfixed) + if(rowtype == FieldsEditorRowType.FIXED) { // Does this match the default setting? if(fieldtype.GetValue().Equals(fieldinfo.Default)) @@ -201,15 +239,19 @@ namespace CodeImp.DoomBuilder.Controls } // This undefines the field - // ONLY VALID FOR FIXED FIELDS + // ONLY VALID FOR FIXED AND USERVAR FIELDS // You should just delete non-fixed fields public void Undefine() { // Must be fixed! - if(!isfixed) throw new InvalidOperationException(); + if(rowtype != FieldsEditorRowType.FIXED && rowtype != FieldsEditorRowType.USERVAR) throw new InvalidOperationException(); // Now undefined - fieldtype.SetValue(fieldinfo.Default); + if(rowtype == FieldsEditorRowType.USERVAR) + fieldtype.ApplyDefaultValue(); + else + fieldtype.SetValue(fieldinfo.Default); + this.Cells[2].Value = fieldtype.GetStringValue(); this.DefaultCellStyle.ForeColor = SystemColors.GrayText; isdefined = false; @@ -218,10 +260,13 @@ namespace CodeImp.DoomBuilder.Controls // This defines the field public void Define(object value) { + //mxd. Don't count as defined when default value is passed + if(value.ToString() == fieldtype.GetDefaultValue().ToString()) return; + // Now defined fieldtype.SetValue(value); this.Cells[2].Value = fieldtype.GetStringValue(); - this.DefaultCellStyle.ForeColor = SystemColors.WindowText; + this.DefaultCellStyle.ForeColor = (rowtype == FieldsEditorRowType.USERVAR ? SystemColors.HotTrack : SystemColors.WindowText); isdefined = true; } @@ -229,13 +274,12 @@ namespace CodeImp.DoomBuilder.Controls public void ChangeType(int typeindex) { // Can't do this for a fixed field! - if(isfixed) throw new InvalidOperationException(); + if(rowtype == FieldsEditorRowType.FIXED) throw new InvalidOperationException(); // Different? if(typeindex != fieldtype.Index) { // Change field type! - //TypeHandlerAttribute attrib = General.Types.GetAttribute(typeindex); //mxd fieldtype = General.Types.GetFieldHandler(typeindex, this.Cells[2].Value); this.Cells[1].Value = fieldtype.GetDisplayType(); } diff --git a/Source/Core/Controls/FlatSelectorControl.cs b/Source/Core/Controls/FlatSelectorControl.cs index c466a9a..3c76acb 100644 --- a/Source/Core/Controls/FlatSelectorControl.cs +++ b/Source/Core/Controls/FlatSelectorControl.cs @@ -67,7 +67,7 @@ namespace CodeImp.DoomBuilder.Controls if(usepreviews ? !texture.IsPreviewLoaded : !texture.IsImageLoaded) timer.Start(); //mxd // Set the image - return (usepreviews ? texture.GetPreview() : texture.GetBitmap()); + return new Bitmap(usepreviews ? texture.GetPreview() : texture.GetBitmap()); } } diff --git a/Source/Core/Controls/ImageBrowserControl.Designer.cs b/Source/Core/Controls/ImageBrowserControl.Designer.cs index 567270c..2549132 100644 --- a/Source/Core/Controls/ImageBrowserControl.Designer.cs +++ b/Source/Core/Controls/ImageBrowserControl.Designer.cs @@ -116,6 +116,7 @@ namespace CodeImp.DoomBuilder.Controls this.list.DoubleClick += new System.EventHandler(this.list_DoubleClick); this.list.ItemSelectionChanged += new System.Windows.Forms.ListViewItemSelectionChangedEventHandler(this.list_ItemSelectionChanged); this.list.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.list_KeyPress); + this.list.KeyDown += new System.Windows.Forms.KeyEventHandler(this.list_KeyDown); // // showsubdirtextures // diff --git a/Source/Core/Controls/ImageBrowserControl.cs b/Source/Core/Controls/ImageBrowserControl.cs index ede2166..b7b8c2a 100644 --- a/Source/Core/Controls/ImageBrowserControl.cs +++ b/Source/Core/Controls/ImageBrowserControl.cs @@ -237,6 +237,20 @@ namespace CodeImp.DoomBuilder.Controls } } + //mxd. Handle keyboard navigation the same way regardless of list being focused... + private void list_KeyDown(object sender, KeyEventArgs e) + { + // Check what key is pressed + switch(e.KeyData) + { + // Cursor keys + case Keys.Left: SelectNextItem(SearchDirectionHint.Left); e.SuppressKeyPress = true; break; + case Keys.Right: SelectNextItem(SearchDirectionHint.Right); e.SuppressKeyPress = true; break; + case Keys.Up: SelectNextItem(SearchDirectionHint.Up); e.SuppressKeyPress = true; break; + case Keys.Down: SelectNextItem(SearchDirectionHint.Down); e.SuppressKeyPress = true; break; + } + } + //mxd private void filterSize_WhenTextChanged(object sender, EventArgs e) { @@ -277,6 +291,8 @@ namespace CodeImp.DoomBuilder.Controls //mxd. Transfer focus to Filter textbox private void list_KeyPress(object sender, KeyPressEventArgs e) { + if(!General.Settings.KeepTextureFilterFocused) return; + objectname.Focus(); if(e.KeyChar == '\b') // Any better way to check for Backspace?.. { @@ -388,36 +404,115 @@ namespace CodeImp.DoomBuilder.Controls } else { - // Get selected item - ListViewItem lvi = list.SelectedItems[0]; - Rectangle lvirect = list.GetItemRect(lvi.Index, ItemBoundsPortion.Entire); - Point spos = new Point(lvirect.Location.X + lvirect.Width / 2, lvirect.Y + lvirect.Height / 2); + //mxd + int index = list.SelectedItems[0].Index; + int targetindex = -1; + ListViewGroup startgroup = list.SelectedItems[0].Group; + Rectangle startrect = list.SelectedItems[0].GetBounds(ItemBoundsPortion.Entire); - // Try finding 5 times in the given direction - for(int i = 0; i < 5; i++) + switch(dir) { - // Move point in given direction - switch(dir) - { - case SearchDirectionHint.Left: spos.X -= list.TileSize.Width / 2; break; - case SearchDirectionHint.Right: spos.X += list.TileSize.Width / 2; break; - case SearchDirectionHint.Up: spos.Y -= list.TileSize.Height / 2; break; - case SearchDirectionHint.Down: spos.Y += list.TileSize.Height / 2; break; - } - - // Test position - lvi = list.GetItemAt(spos.X, spos.Y); - if(lvi != null) - { - // Select item - list.SelectedItems.Clear(); - lvi.Selected = true; + // Check previous items untill groups match... + case SearchDirectionHint.Left: + if(list.SelectedIndices[0] > 0) + { + while(--index > -1) + { + if(list.Items[index].Group == startgroup) + { + targetindex = index; + break; + } + } + } break; + + // Same thing, other direction... + case SearchDirectionHint.Right: + if(list.SelectedIndices[0] < list.Items.Count - 1) + { + while(++index < list.Items.Count) + { + if(list.Items[index].Group == startgroup) + { + targetindex = index; + break; + } + } + } + break; + + // Check previous items untill X coordinate match and Y coordinate is less than the start ones... + case SearchDirectionHint.Up: + while(--index > -1) + { + ListViewItem item = list.Items[index]; + if(item != null && item.Group == startgroup) + { + Rectangle rect = item.GetBounds(ItemBoundsPortion.Entire); + if(rect.X == startrect.X && rect.Y < startrect.Y) + { + targetindex = index; + break; + } + } + } + break; + + // Same thing, other direction... + case SearchDirectionHint.Down: + if(list.SelectedIndices[0] < list.Items.Count - 1) + { + while(++index < list.Items.Count) + { + ListViewItem item = list.Items[index]; + if(item != null && item.Group == startgroup) + { + Rectangle rect = item.GetBounds(ItemBoundsPortion.Entire); + if(rect.X == startrect.X && rect.Y > startrect.Y) + { + targetindex = index; + break; + } + } + } + } + break; + } + + //mxd. Use the old method for Up/Down keys, becaue it can jump between Groups... + if(targetindex == -1 && (dir == SearchDirectionHint.Up || dir == SearchDirectionHint.Down)) + { + Point spos = new Point(startrect.Location.X + startrect.Width / 2, startrect.Y + startrect.Height / 2); + + // Try finding 5 times in the given direction + for(int i = 0; i < 5; i++) + { + // Move point in given direction + switch(dir) + { + case SearchDirectionHint.Up: spos.Y -= list.TileSize.Height / 2; break; + case SearchDirectionHint.Down: spos.Y += list.TileSize.Height / 2; break; + } + + // Test position + ListViewItem lvi = list.GetItemAt(spos.X, spos.Y); + if(lvi != null) + { + targetindex = lvi.Index; + break; + } } } - - // Make selection visible - if(list.SelectedItems.Count > 0) list.SelectedItems[0].EnsureVisible(); + + //mxd. Found something?.. + if(targetindex != -1) + { + // Select item + list.SelectedItems.Clear(); + list.Items[targetindex].Selected = true; + list.SelectedItems[0].EnsureVisible(); + } } } @@ -514,6 +609,15 @@ namespace CodeImp.DoomBuilder.Controls private void RefillList(bool selectfirst) { visibleitems = new List(); + + //mxd. Store info about currently selected item + string selectedname = string.Empty; + ListViewGroup selecteditemgroup = null; + if(!selectfirst && keepselected == -1 && list.SelectedIndices.Count > 0) + { + selectedname = list.Items[list.SelectedIndices[0]].Text; + selecteditemgroup = list.Items[list.SelectedIndices[0]].Group; + } // Begin updating list updating = true; @@ -569,6 +673,56 @@ namespace CodeImp.DoomBuilder.Controls { SelectFirstItem(); } + //mxd. Try reselecting the same/next closest item + else if(selecteditemgroup != null && !string.IsNullOrEmpty(selectedname)) + { + ListViewItem bestmatch = null; + int charsmatched = 1; + foreach(ListViewItem item in list.Items) + { + if(item.Group == selecteditemgroup && item.Text[0] == selectedname[0]) + { + if(item.Text == selectedname) + { + bestmatch = item; + break; + } + + for(int i = 1; i < Math.Min(item.Text.Length, selectedname.Length); i++) + { + if(item.Text[i] != selectedname[i]) + { + if(i > charsmatched) + { + bestmatch = item; + charsmatched = i; + } + break; + } + } + } + } + + // Select the first item from the same group... + if(bestmatch == null) + { + foreach(ListViewItem item in list.Items) + { + if(item.Group == selecteditemgroup) + { + bestmatch = item; + break; + } + } + } + + // Select found item + if(bestmatch != null) + { + bestmatch.Selected = true; + bestmatch.EnsureVisible(); + } + } } // Raise event @@ -605,7 +759,10 @@ namespace CodeImp.DoomBuilder.Controls // This sends the focus to the textbox public void FocusTextbox() { - objectname.Focus(); + if(General.Settings.KeepTextureFilterFocused) //mxd + objectname.Focus(); + else + list.Focus(); } #endregion diff --git a/Source/Core/Controls/ScriptEditorControl.cs b/Source/Core/Controls/ScriptEditorControl.cs index c001cc5..14bcc86 100644 --- a/Source/Core/Controls/ScriptEditorControl.cs +++ b/Source/Core/Controls/ScriptEditorControl.cs @@ -35,1417 +35,1425 @@ using ScintillaNET; namespace CodeImp.DoomBuilder.Controls { - internal enum ScriptStyleType - { - PlainText = 0, - Keyword = 1, - Constant = 2, - Comment = 3, - Literal = 4, - LineNumber = 5, - String = 6, //mxd - Include = 7, //mxd - Property = 8, //mxd - } - - internal partial class ScriptEditorControl : UserControl - { - #region ================== Enums - - // Index for registered images - private enum ImageIndex - { - ScriptConstant = 0, - ScriptKeyword = 1, - ScriptError = 2, - ScriptSnippet = 3, //mxd - ScriptProperty = 4, //mxd - } - - #endregion - - #region ================== Constants - - private const string LEXERS_RESOURCE = "Lexers.cfg"; - private const int MAX_BACKTRACK_LENGTH = 200; - private const int HIGHLIGHT_INDICATOR = 8; //mxd. Indicators 0-7 could be in use by a lexer so we'll use indicator 8 to highlight words. - - #endregion - - #region ================== Delegates / Events - - public delegate void ExplicitSaveTabDelegate(); - public delegate void OpenScriptBrowserDelegate(); - public delegate void OpenFindReplaceDelegate(); - public delegate void FindNextDelegate(); - public delegate void FindPreviousDelegate(); //mxd - - public event ExplicitSaveTabDelegate OnExplicitSaveTab; - public event OpenScriptBrowserDelegate OnOpenScriptBrowser; - public event OpenFindReplaceDelegate OnOpenFindAndReplace; - public event FindNextDelegate OnFindNext; - public event FindPreviousDelegate OnFindPrevious; //mxd - public new event EventHandler OnTextChanged; //mxd - - #endregion - - #region ================== Variables - - // Script configuration - private ScriptConfiguration scriptconfig; - - // List of keywords and constants - private List autocompletelist; - - // Style translation from Scintilla style to ScriptStyleType - private Dictionary stylelookup; - - // Current position information - private string curfunctionname = ""; - private int curargumentindex; - private int curfunctionstartpos; - private int linenumbercharlength; //mxd. Current max number of chars in the line number - private int lastcaretpos; //mxd. Used in brace matching - private int caretoffset; //mxd. Used to modify caret position after autogenerating stuff - private bool skiptextinsert; //mxd. Gross hacks - private bool expandcodeblock; //mxd. More gross hacks - private string highlightedword; //mxd - private Encoding encoding; //mxd - - #endregion - - #region ================== Properties - - public bool IsChanged { get { return scriptedit.Modified; } } - public int SelectionStart { get { return scriptedit.SelectionStart; } set { scriptedit.SelectionStart = value; } } - public int SelectionEnd { get { return scriptedit.SelectionEnd; } set { scriptedit.SelectionEnd = value; } } - public new string Text { get { return scriptedit.Text; } set { scriptedit.Text = value; } } //mxd - public string SelectedText { get { return scriptedit.SelectedText; } } //mxd - public bool ShowWhitespace { get { return scriptedit.ViewWhitespace != WhitespaceMode.Invisible; } set { scriptedit.ViewWhitespace = value ? WhitespaceMode.VisibleAlways : WhitespaceMode.Invisible; } } - public bool WrapLongLines { get { return scriptedit.WrapMode != WrapMode.None; } set { scriptedit.WrapMode = (value ? WrapMode.Char : WrapMode.None); } } - public ComboBox FunctionBar { get { return functionbar; } } //mxd - public Scintilla Scintilla { get { return scriptedit; } } //mxd - - #endregion - - #region ================== Contructor / Disposer - - // Constructor - public ScriptEditorControl() - { - // Initialize - InitializeComponent(); - - //mxd. ASCII with cyrillic support... - encoding = Encoding.GetEncoding(1251); - - // Script editor properties - //TODO: use ScintillaNET properties instead when they become available - scriptedit.DirectMessage(NativeMethods.SCI_SETBACKSPACEUNINDENTS, new IntPtr(1)); - scriptedit.DirectMessage(NativeMethods.SCI_SETMOUSEDOWNCAPTURES, new IntPtr(1)); - scriptedit.DirectMessage(NativeMethods.SCI_SETTABINDENTS, new IntPtr(1)); - - // Symbol margin - scriptedit.Margins[0].Type = MarginType.Symbol; - scriptedit.Margins[0].Width = 20; - scriptedit.Margins[0].Mask = 1 << (int)ImageIndex.ScriptError; // Error marker only - scriptedit.Margins[0].Cursor = MarginCursor.Arrow; - scriptedit.Margins[0].Sensitive = true; - - // Line numbers margin - if (General.Settings.ScriptShowLineNumbers) - { - scriptedit.Margins[1].Type = MarginType.Number; - scriptedit.Margins[1].Width = 16; - } - scriptedit.Margins[1].Mask = 0; // No markers here - - // Spacing margin - scriptedit.Margins[2].Type = MarginType.Symbol; - scriptedit.Margins[2].Width = 5; - scriptedit.Margins[2].Cursor = MarginCursor.Arrow; - scriptedit.Margins[2].Mask = 0; // No markers here - - // Images - RegisterAutoCompleteImage(ImageIndex.ScriptConstant, Resources.ScriptConstant); - RegisterAutoCompleteImage(ImageIndex.ScriptKeyword, Resources.ScriptKeyword); - RegisterAutoCompleteImage(ImageIndex.ScriptSnippet, Resources.ScriptSnippet); //mxd - RegisterAutoCompleteImage(ImageIndex.ScriptProperty, Resources.ScriptProperty); //mxd - RegisterMarkerImage(ImageIndex.ScriptError, Resources.ScriptError); - - //mxd. These key combinations put odd characters in the script. Let's disable them - scriptedit.AssignCmdKey(Keys.Control | Keys.Q, Command.Null); - scriptedit.AssignCmdKey(Keys.Control | Keys.W, Command.Null); - scriptedit.AssignCmdKey(Keys.Control | Keys.E, Command.Null); - scriptedit.AssignCmdKey(Keys.Control | Keys.R, Command.Null); - scriptedit.AssignCmdKey(Keys.Control | Keys.Y, Command.Null); - scriptedit.AssignCmdKey(Keys.Control | Keys.U, Command.Null); - scriptedit.AssignCmdKey(Keys.Control | Keys.I, Command.Null); - scriptedit.AssignCmdKey(Keys.Control | Keys.P, Command.Null); - scriptedit.AssignCmdKey(Keys.Control | Keys.Shift | Keys.A, Command.Null); - scriptedit.AssignCmdKey(Keys.Control | Keys.D, Command.Null); - scriptedit.AssignCmdKey(Keys.Control | Keys.G, Command.Null); - scriptedit.AssignCmdKey(Keys.Control | Keys.H, Command.Null); - scriptedit.AssignCmdKey(Keys.Control | Keys.J, Command.Null); - scriptedit.AssignCmdKey(Keys.Control | Keys.K, Command.Null); - scriptedit.AssignCmdKey(Keys.Control | Keys.L, Command.Null); - scriptedit.AssignCmdKey(Keys.Control | Keys.Shift | Keys.Z, Command.Null); - scriptedit.AssignCmdKey(Keys.Control | Keys.Shift | Keys.X, Command.Null); - scriptedit.AssignCmdKey(Keys.Control | Keys.Shift | Keys.C, Command.Null); - scriptedit.AssignCmdKey(Keys.Control | Keys.Shift | Keys.V, Command.Null); - scriptedit.AssignCmdKey(Keys.Control | Keys.B, Command.Null); - scriptedit.AssignCmdKey(Keys.Control | Keys.N, Command.Null); - scriptedit.AssignCmdKey(Keys.Control | Keys.M, Command.Null); - - //mxd. These key combinations are used to perform special actions. Let's disable them - scriptedit.AssignCmdKey(Keys.F3, Command.Null); // F3 for Find Next - scriptedit.AssignCmdKey(Keys.F2, Command.Null); // F2 for Find Previous - scriptedit.AssignCmdKey(Keys.Control | Keys.F, Command.Null); // CTRL+F for find & replace - scriptedit.AssignCmdKey(Keys.Control | Keys.S, Command.Null); // CTRL+S for save - scriptedit.AssignCmdKey(Keys.Control | Keys.O, Command.Null); // CTRL+O for open - scriptedit.AssignCmdKey(Keys.Control | Keys.Space, Command.Null); // CTRL+Space to autocomplete <- TODO: this doesn't seem to work... - } - - #endregion - - #region ================== Public methods - - // This launches keyword help website - public bool LaunchKeywordHelp() - { - string helpsite = scriptconfig.KeywordHelp; - string currentword = GetCurrentWord(); - if (!string.IsNullOrEmpty(currentword) && (currentword.Length > 1) && !string.IsNullOrEmpty(helpsite)) - { - currentword = scriptconfig.GetKeywordCase(currentword); - helpsite = helpsite.Replace("%K", currentword); - General.OpenWebsite(helpsite); - return true; - } - - return !string.IsNullOrEmpty(helpsite); //mxd - } - - // This replaces the selection with the given text - public void ReplaceSelection(string replacement) - { - scriptedit.ReplaceSelection(replacement); //mxd TODO: encoding check/conversion? - } - - // This moves the caret to a given line and ensures the line is visible - public void MoveToLine(int linenumber) - { - scriptedit.Lines[linenumber].Goto(); - EnsureLineVisible(linenumber); - } - - // This makes sure a line is visible - public void EnsureLineVisible(int linenumber) - { - // Determine target lines range - int startline = Math.Max(0, linenumber - 4); - int endline = Math.Min(scriptedit.Lines.Count, Math.Max(linenumber, linenumber + scriptedit.LinesOnScreen - 6)); - - // Go to target line - scriptedit.DirectMessage(NativeMethods.SCI_ENSUREVISIBLEENFORCEPOLICY, (IntPtr)startline); // Unfold the whole text block if needed - scriptedit.ShowLines(startline, endline); - - // We may want to do some scrolling... - if (scriptedit.FirstVisibleLine >= startline) - scriptedit.Lines[startline].Goto(); - else if (scriptedit.FirstVisibleLine + scriptedit.LinesOnScreen <= endline) - scriptedit.Lines[endline].Goto(); - } - - //mxd - private void SelectAndShow(int startpos, int endpos) - { - // Select the result - int startline = scriptedit.LineFromPosition(startpos); - int endline = scriptedit.LineFromPosition(endpos); - - // Go to target line - scriptedit.DirectMessage(NativeMethods.SCI_ENSUREVISIBLEENFORCEPOLICY, (IntPtr)startline); // Unfold the whole text block if needed - scriptedit.ShowLines(startline, endline); - scriptedit.GotoPosition(startpos); - - // We may want to do some extra scrolling... - if (startline > 1 && scriptedit.FirstVisibleLine >= startline - 1) - scriptedit.Lines[startline - 1].Goto(); - else if (endline < scriptedit.Lines.Count - 1 && scriptedit.FirstVisibleLine + scriptedit.LinesOnScreen <= endline + 1) - scriptedit.Lines[endline + 1].Goto(); - - // Update selection - scriptedit.SelectionStart = startpos; - scriptedit.SelectionEnd = endpos; - } - - // This returns the line for a position - public int LineFromPosition(int position) - { - return scriptedit.LineFromPosition(position); - } - - // This clears all marks - public void ClearMarks() - { - scriptedit.MarkerDeleteAll((int)ImageIndex.ScriptError); - } - - // This adds a mark on the given line - public void AddMark(int linenumber) - { - scriptedit.Lines[linenumber].MarkerAdd((int)ImageIndex.ScriptError); - } - - // This refreshes the style setup - public void RefreshStyle() - { - // Re-setup with the same config - SetupStyles(scriptconfig); - } - - // This sets up the script editor with a script configuration - public void SetupStyles(ScriptConfiguration config) - { - Configuration lexercfg = new Configuration(); - - // Make collections - stylelookup = new Dictionary(); - Dictionary autocompletedict = new Dictionary(StringComparer.Ordinal); - - // Keep script configuration - scriptconfig = config; - - // Find a resource named Lexers.cfg - string[] resnames = General.ThisAssembly.GetManifestResourceNames(); - foreach (string rn in resnames) - { - // Found one? - if (rn.EndsWith(LEXERS_RESOURCE, StringComparison.OrdinalIgnoreCase)) - { - // Get a stream from the resource - Stream lexersdata = General.ThisAssembly.GetManifestResourceStream(rn); - if (lexersdata != null) - { - StreamReader lexersreader = new StreamReader(lexersdata, Encoding.ASCII); - - // Load configuration from stream - lexercfg.InputConfiguration(lexersreader.ReadToEnd()); - - // Done with the resource - lexersreader.Dispose(); - lexersdata.Dispose(); - } - - //mxd. We are done here - break; - } - } - - //mxd. Reset document slyle - scriptedit.ClearDocumentStyle(); - scriptedit.StyleResetDefault(); - - // Check if specified lexer exists and set the lexer to use - string lexername = "lexer" + (int)scriptconfig.Lexer; - if (!lexercfg.SettingExists(lexername)) throw new InvalidOperationException("Unknown lexer " + scriptconfig.Lexer + " specified in script configuration!"); - scriptedit.Lexer = scriptconfig.Lexer; - - //mxd. Set word chars - scriptedit.SetWordChars(scriptconfig.WordCharacters); - - // Set the default style and settings - scriptedit.Styles[Style.Default].Font = General.Settings.ScriptFontName; - scriptedit.Styles[Style.Default].Size = General.Settings.ScriptFontSize; - scriptedit.Styles[Style.Default].Bold = General.Settings.ScriptFontBold; - scriptedit.Styles[Style.Default].Italic = false; - scriptedit.Styles[Style.Default].Underline = false; - scriptedit.Styles[Style.Default].Case = StyleCase.Mixed; - scriptedit.Styles[Style.Default].ForeColor = General.Colors.PlainText.ToColor(); - scriptedit.Styles[Style.Default].BackColor = General.Colors.ScriptBackground.ToColor(); - scriptedit.CaretPeriod = SystemInformation.CaretBlinkTime; - scriptedit.CaretForeColor = General.Colors.ScriptBackground.Inverse().ToColor(); - - // Set tabulation settings - scriptedit.UseTabs = General.Settings.ScriptUseTabs; - scriptedit.TabWidth = General.Settings.ScriptTabWidth; - //scriptedit.IndentWidth = General.Settings.ScriptTabWidth; // Equals to TabWidth by default - //TODO: use ScintillaNET properties instead when they become available - scriptedit.DirectMessage(NativeMethods.SCI_SETTABINDENTS, new IntPtr(1)); - scriptedit.DirectMessage(NativeMethods.SCI_SETBACKSPACEUNINDENTS, new IntPtr(1)); - - // This applies the default style to all styles - scriptedit.StyleClearAll(); - - // Set the code page to use. [mxd] No longer needed? - //scriptedit.CodePage = scriptconfig.CodePage; - - //mxd. We can't change Font or Size here because this will screw displayed tab width (because it's based on character width)... - // Set the default to something normal (this is used by the autocomplete list) - //scriptedit.Styles[Style.Default].Font = this.Font.Name; - scriptedit.Styles[Style.Default].Bold = this.Font.Bold; - scriptedit.Styles[Style.Default].Italic = this.Font.Italic; - scriptedit.Styles[Style.Default].Underline = this.Font.Underline; - //scriptedit.Styles[Style.Default].Size = (int)Math.Round(this.Font.SizeInPoints); - - // Set style for linenumbers and margins - scriptedit.Styles[Style.LineNumber].BackColor = General.Colors.ScriptBackground.ToColor(); - scriptedit.SetFoldMarginColor(true, General.Colors.ScriptFoldBackColor.ToColor()); - scriptedit.SetFoldMarginHighlightColor(true, General.Colors.ScriptFoldBackColor.ToColor()); - for (int i = 25; i < 32; i++) - { - scriptedit.Markers[i].SetForeColor(General.Colors.ScriptFoldBackColor.ToColor()); - scriptedit.Markers[i].SetBackColor(General.Colors.ScriptFoldForeColor.ToColor()); - } - - //mxd. Set style for (mis)matching braces - scriptedit.Styles[Style.BraceLight].BackColor = General.Colors.ScriptBraceHighlight.ToColor(); - scriptedit.Styles[Style.BraceBad].BackColor = General.Colors.ScriptBadBraceHighlight.ToColor(); - - //mxd. Set whitespace color - scriptedit.SetWhitespaceForeColor(true, General.Colors.ScriptWhitespace.ToColor()); - - //mxd. Set selection colors - scriptedit.SetSelectionForeColor(true, General.Colors.ScriptSelectionForeColor.ToColor()); - scriptedit.SetSelectionBackColor(true, General.Colors.ScriptSelectionBackColor.ToColor()); - - // Clear all keywords - for (int i = 0; i < 9; i++) scriptedit.SetKeywords(i, null); - - // Now go for all elements in the lexer configuration - // We are looking for the numeric keys, because these are the - // style index to set and the value is our ScriptStyleType - IDictionary dic = lexercfg.ReadSetting(lexername, new Hashtable()); - foreach (DictionaryEntry de in dic) - { - // Check if this is a numeric key - int stylenum; - if (int.TryParse(de.Key.ToString(), out stylenum)) - { - // Add style to lookup table - stylelookup.Add(stylenum, (ScriptStyleType)(int)de.Value); - - // Apply color to style - int colorindex; - ScriptStyleType type = (ScriptStyleType)(int)de.Value; - switch (type) - { - case ScriptStyleType.PlainText: colorindex = ColorCollection.PLAINTEXT; break; - case ScriptStyleType.Comment: colorindex = ColorCollection.COMMENTS; break; - case ScriptStyleType.Constant: colorindex = ColorCollection.CONSTANTS; break; - case ScriptStyleType.Keyword: colorindex = ColorCollection.KEYWORDS; break; - case ScriptStyleType.LineNumber: colorindex = ColorCollection.LINENUMBERS; break; - case ScriptStyleType.Literal: colorindex = ColorCollection.LITERALS; break; - case ScriptStyleType.String: colorindex = ColorCollection.STRINGS; break; - case ScriptStyleType.Include: colorindex = ColorCollection.INCLUDES; break; - case ScriptStyleType.Property: colorindex = ColorCollection.PROPERTIES; break; - default: colorindex = ColorCollection.PLAINTEXT; break; - } - - scriptedit.Styles[stylenum].ForeColor = General.Colors.Colors[colorindex].ToColor(); - } - } - - // Create the keywords list and apply it - string imageindex = ((int)ImageIndex.ScriptKeyword).ToString(CultureInfo.InvariantCulture); - int keywordsindex = lexercfg.ReadSetting(lexername + ".keywordsindex", -1); - if (keywordsindex > -1) - { - StringBuilder keywordslist = new StringBuilder(""); - foreach (string k in scriptconfig.Keywords) - { - if (keywordslist.Length > 0) keywordslist.Append(" "); - keywordslist.Append(k); - - //mxd. Skip adding the keyword if we have a snippet with the same name - if (!scriptconfig.Snippets.Contains(k)) - autocompletedict.Add(k.ToUpperInvariant(), k + "?" + imageindex); - } - string words = keywordslist.ToString(); - scriptedit.SetKeywords(keywordsindex, (scriptconfig.CaseSensitive ? words : words.ToLowerInvariant())); - } - - //mxd. Create the properties list and apply it - imageindex = ((int)ImageIndex.ScriptProperty).ToString(CultureInfo.InvariantCulture); - int propertiesindex = lexercfg.ReadSetting(lexername + ".propertiesindex", -1); - if (propertiesindex > -1) - { - StringBuilder propertieslist = new StringBuilder(""); - HashSet addedprops = new HashSet(); - char[] dot = new[] { '.' }; - foreach (string p in scriptconfig.Properties) - { - if (propertieslist.Length > 0) propertieslist.Append(" "); - - // Scintilla doesn't highlight keywords with '.' or ':', so get rid of those - if (scriptconfig.ScriptType == ScriptType.DECORATE) - { - string prop = p; - if (prop.Contains(":")) prop = prop.Replace(":", string.Empty); - if (prop.Contains(".")) - { - // Split dotted properties into separate entries - string[] parts = prop.Split(dot, StringSplitOptions.RemoveEmptyEntries); - List result = new List(); - foreach (string part in parts) - { - if (!addedprops.Contains(part)) - { - result.Add(part); - addedprops.Add(part); - } - } - - if (result.Count > 0) propertieslist.Append(string.Join(" ", result.ToArray())); - } - else - { - addedprops.Add(prop); - propertieslist.Append(prop); - } - } - else - { - propertieslist.Append(p); - } - - // Autocomplete doesn't mind '.' or ':' - autocompletedict[p.ToUpperInvariant()] = p + "?" + imageindex; - } - string words = propertieslist.ToString(); - scriptedit.SetKeywords(propertiesindex, (scriptconfig.CaseSensitive ? words : words.ToLowerInvariant())); - } - - // Create the constants list and apply it - imageindex = ((int)ImageIndex.ScriptConstant).ToString(CultureInfo.InvariantCulture); - int constantsindex = lexercfg.ReadSetting(lexername + ".constantsindex", -1); - if (constantsindex > -1) - { - StringBuilder constantslist = new StringBuilder(""); - foreach (string c in scriptconfig.Constants) - { - if (autocompletedict.ContainsKey(c.ToUpperInvariant())) //mxd. This happens when there's a keyword and a constant with the same name... - { - General.ErrorLogger.Add(ErrorType.Error, "Constant '" + c + "' is double-defined in '" + scriptconfig.Description + "' script configuration!"); - continue; - } - - if (constantslist.Length > 0) constantslist.Append(" "); - constantslist.Append(c); - - //mxd. Skip adding the constant if we have a snippet with the same name - if (!scriptconfig.Snippets.Contains(c)) - autocompletedict.Add(c.ToUpperInvariant(), c + "?" + imageindex); - } - string words = constantslist.ToString(); - scriptedit.SetKeywords(constantsindex, (scriptconfig.CaseSensitive ? words : words.ToLowerInvariant())); - } - - //mxd. Create the snippets list and apply it - imageindex = ((int)ImageIndex.ScriptSnippet).ToString(CultureInfo.InvariantCulture); - int snippetindex = lexercfg.ReadSetting(lexername + ".snippetindex", -1); - if (snippetindex > -1 && scriptconfig.Snippets.Count > 0) - { - StringBuilder snippetslist = new StringBuilder(""); - foreach (string c in scriptconfig.Snippets) - { - if (autocompletedict.ContainsKey(c.ToUpperInvariant())) continue; - if (snippetslist.Length > 0) snippetslist.Append(" "); - snippetslist.Append(c); - autocompletedict.Add(c.ToUpperInvariant(), c + "?" + imageindex); - } - string words = snippetslist.ToString(); - scriptedit.SetKeywords(snippetindex, (scriptconfig.CaseSensitive ? words : words.ToLowerInvariant())); - } - - // Make autocomplete list - autocompletelist = new List(autocompletedict.Values); - - // Setup folding (https://github.com/jacobslusser/ScintillaNET/wiki/Automatic-Code-Folding) - if (General.Settings.ScriptShowFolding && (scriptconfig.Lexer == Lexer.Cpp || scriptconfig.Lexer == Lexer.CppNoCase)) - { - // Instruct the lexer to calculate folding - scriptedit.SetProperty("fold", "1"); - scriptedit.SetProperty("fold.compact", "0"); // 1 = folds blank lines - scriptedit.SetProperty("fold.comment", "1"); // Enable block comment folding - scriptedit.SetProperty("fold.preprocessor", "1"); // Enable #region folding - scriptedit.SetFoldFlags(FoldFlags.LineAfterContracted); // Draw line below if not expanded - - // Configure a margin to display folding symbols - scriptedit.Margins[2].Type = MarginType.Symbol; - scriptedit.Margins[2].Mask = Marker.MaskFolders; - scriptedit.Margins[2].Sensitive = true; - scriptedit.Margins[2].Width = 12; - - // Configure folding markers with respective symbols - scriptedit.Markers[Marker.Folder].Symbol = MarkerSymbol.BoxPlus; - scriptedit.Markers[Marker.FolderOpen].Symbol = MarkerSymbol.BoxMinus; - scriptedit.Markers[Marker.FolderEnd].Symbol = MarkerSymbol.BoxPlusConnected; - scriptedit.Markers[Marker.FolderMidTail].Symbol = MarkerSymbol.TCorner; - scriptedit.Markers[Marker.FolderOpenMid].Symbol = MarkerSymbol.BoxMinusConnected; - scriptedit.Markers[Marker.FolderSub].Symbol = MarkerSymbol.VLine; - scriptedit.Markers[Marker.FolderTail].Symbol = MarkerSymbol.LCorner; - - // Enable automatic folding - scriptedit.AutomaticFold = (AutomaticFold.Show | AutomaticFold.Click | AutomaticFold.Change); - } - else - { - // Disable folding - scriptedit.SetProperty("fold", "0"); - scriptedit.SetProperty("fold.compact", "0"); - - scriptedit.Margins[2].Type = MarginType.Symbol; - scriptedit.Margins[2].Mask = 0; // No markers here - scriptedit.Margins[2].Sensitive = false; - scriptedit.Margins[2].Width = 5; - - scriptedit.AutomaticFold = AutomaticFold.None; - } - - // Rearrange the layout - this.PerformLayout(); - } - - // This returns the current word (where the caret is at) - public string GetCurrentWord() - { - return GetWordAt(scriptedit.CurrentPosition); - } - - // This returns the word at the given position - public string GetWordAt(int position) - { - return scriptedit.GetWordFromPosition(position); - } - - // Perform undo - public void Undo() - { - scriptedit.Undo(); - } - - // Perform redo - public void Redo() - { - scriptedit.Redo(); - } - - // This clears all undo levels - public void ClearUndoRedo() - { - scriptedit.EmptyUndoBuffer(); - } - - //mxd. This marks the current document as unmodified - public void SetSavePoint() - { - scriptedit.SetSavePoint(); - } - - // Perform cut - public void Cut() - { - scriptedit.Cut(); - } - - // Perform copy - public void Copy() - { - scriptedit.Copy(); - } - - // Perform paste - public void Paste() - { - scriptedit.Paste(); - } - - // This steals the focus (use with care!) - public void GrabFocus() - { - scriptedit.Focus(); - } - - public byte[] GetText() - { - return encoding.GetBytes(scriptedit.Text); //mxd TODO: other encodings?.. - } - - public void SetText(byte[] text) - { - scriptedit.Text = encoding.GetString(text); //mxd TODO: other encodings?.. - } - - //mxd - public void InsertSnippet(string[] lines) - { - // Insert the snippet - int curline = scriptedit.LineFromPosition(scriptedit.SelectionStart); - int indent = scriptedit.Lines[scriptedit.CurrentLine].Indentation; - string tabs = Environment.NewLine + GetIndentationString(indent); - string spaces = new String(' ', General.Settings.ScriptTabWidth); - int entrypos = -1; - int entryline = -1; - string[] processedlines = ProcessLineBreaks(lines); - - // Process special chars, try to find entry position marker - for (int i = 0; i < lines.Length; i++) - { - if (!scriptedit.UseTabs) processedlines[i] = processedlines[i].Replace("\t", spaces); - - // Check if we have the [EP] marker - if (entrypos == -1) - { - int pos = processedlines[i].IndexOf("[EP]", StringComparison.Ordinal); - if (pos != -1) - { - processedlines[i] = processedlines[i].Remove(pos, 4); - entryline = curline + i; - entrypos = processedlines[i].Length - pos; - } - } - } - - // Replace the text - string text = string.Join(tabs, processedlines); - scriptedit.SelectionStart = scriptedit.WordStartPosition(scriptedit.CurrentPosition, true); - scriptedit.SelectionEnd = scriptedit.WordEndPosition(scriptedit.CurrentPosition, true); - scriptedit.ReplaceSelection(text); - - // Move the cursor if we had the [EP] marker - if (entrypos != -1) - { - scriptedit.SetEmptySelection(scriptedit.Lines[entryline].EndPosition - entrypos - 2); - } - } - - //mxd. Find next result - public bool FindNext(FindReplaceOptions options, bool useselectionstart) - { - int startpos = (useselectionstart ? Math.Min(scriptedit.SelectionStart, scriptedit.SelectionEnd) : Math.Max(scriptedit.SelectionStart, scriptedit.SelectionEnd)); - - // Search the document - scriptedit.TargetStart = startpos; - scriptedit.TargetEnd = scriptedit.TextLength; - scriptedit.SearchFlags = options.CaseSensitive ? SearchFlags.MatchCase : SearchFlags.None; - if (options.WholeWord) scriptedit.SearchFlags |= SearchFlags.WholeWord; - - int result = scriptedit.SearchInTarget(options.FindText); - - // Wrap around? - if (result == -1) - { - scriptedit.TargetStart = 0; - scriptedit.TargetEnd = startpos; - result = scriptedit.SearchInTarget(options.FindText); - } - - // Found something - if (result != -1) - { - // Select the result - SelectAndShow(result, result + options.FindText.Length); - - // Update extra highlights - HighlightWord(options.FindText); - - // All done - return true; - } - - // Nothing found... - return false; - } - - //mxd. Find previous result - public bool FindPrevious(FindReplaceOptions options) - { - int endpos = Math.Max(0, Math.Min(scriptedit.SelectionStart, scriptedit.SelectionEnd) - 1); - - // Search the document - scriptedit.TargetStart = endpos; - scriptedit.TargetEnd = 0; - scriptedit.SearchFlags = options.CaseSensitive ? SearchFlags.MatchCase : SearchFlags.None; - if (options.WholeWord) scriptedit.SearchFlags |= SearchFlags.WholeWord; - - int result = scriptedit.SearchInTarget(options.FindText); - - // Wrap around? - if (result == -1) - { - scriptedit.TargetStart = scriptedit.TextLength; - scriptedit.TargetEnd = endpos; - result = scriptedit.SearchInTarget(options.FindText); - } - - // Found something - if (result != -1) - { - // Select the result - SelectAndShow(result, result + options.FindText.Length); - - // Update extra highlights - HighlightWord(options.FindText); - - // All done - return true; - } - - // Nothing found... - return false; - } - - //mxd. (Un)indents selection - public void IndentSelection(bool indent) - { - // Get selected range of lines - int startline = scriptedit.LineFromPosition(scriptedit.SelectionStart); - int endline = scriptedit.LineFromPosition(scriptedit.SelectionEnd); - - for (int i = startline; i < endline + 1; i++) - { - scriptedit.Lines[i].Indentation += (indent ? General.Settings.ScriptTabWidth : -General.Settings.ScriptTabWidth); - } - } - - #endregion - - #region ================== Utility methods - - // This returns the ScriptStyleType for a given Scintilla style - private ScriptStyleType GetScriptStyle(int scintillastyle) - { - return (stylelookup.ContainsKey(scintillastyle) ? stylelookup[scintillastyle] : ScriptStyleType.PlainText); - } - - // This gathers information about the current caret position - private void UpdatePositionInfo() - { - int bracketlevel = 0; // bracket level counting - int argindex = 0; // function argument counting - int pos = scriptedit.CurrentPosition; - - // Get the text - string scripttext = scriptedit.Text; - - // Reset position info - curfunctionname = ""; - curargumentindex = 0; - curfunctionstartpos = 0; - - // Determine lowest backtrack position - int limitpos = scriptedit.CurrentPosition - MAX_BACKTRACK_LENGTH; - if (limitpos < 0) limitpos = 0; - - // We can only do this when we have function syntax information - if ((scriptconfig.ArgumentDelimiter.Length == 0) || (scriptconfig.FunctionClose.Length == 0) || - (scriptconfig.FunctionOpen.Length == 0) || (scriptconfig.Terminator.Length == 0)) return; - - // Get int versions of the function syntax informantion - int argumentdelimiter = scriptconfig.ArgumentDelimiter[0]; - int functionclose = scriptconfig.FunctionClose[0]; - int functionopen = scriptconfig.FunctionOpen[0]; - int terminator = scriptconfig.Terminator[0]; - - // Continue backtracking until we reached the limitpos - while (pos >= limitpos) - { - // Backtrack 1 character - pos--; - - // Get the style and character at this position - ScriptStyleType curstyle = GetScriptStyle(scriptedit.GetStyleAt(pos)); - int curchar = scriptedit.GetCharAt(pos); - - // Then meeting ) then increase bracket level - // When meeting ( then decrease bracket level - // When bracket level goes -1, then the next word should be the function name - // Only when at bracket level 0, count the comma's for argument index - - // TODO: - // Original code checked for scope character here and breaks if found - - // Check if in plain text or keyword - if ((curstyle == ScriptStyleType.PlainText) || (curstyle == ScriptStyleType.Keyword)) - { - // Closing bracket - if (curchar == functionclose) - { - bracketlevel++; - } - // Opening bracket - else if (curchar == functionopen) - { - bracketlevel--; - - // Out of the brackets? - if (bracketlevel < 0) - { - // Skip any whitespace before this bracket - do - { - // Backtrack 1 character - curchar = scriptedit.GetCharAt(--pos); - } - while ((pos >= limitpos) && ((curchar == ' ') || (curchar == '\t') || - (curchar == '\r') || (curchar == '\n'))); - - // NOTE: We may need to set onlyWordCharacters argument in the - // following calls to false to get any argument delimiter included, - // but this may also cause a valid keyword to be combined with other - // surrounding characters that do not belong to the keyword. - - // Find the word before this bracket - int wordstart = scriptedit.WordStartPosition(pos, true); - int wordend = scriptedit.WordEndPosition(pos, true); - string word = scripttext.Substring(wordstart, wordend - wordstart); - if (word.Length > 0) - { - // Check if this is an argument delimiter - // I can't remember why I did this, but I'll probably stumble - // upon the problem if this doesn't work right (see note above) - if (word[0] == argumentdelimiter) - { - // We are now in the parent function - bracketlevel++; - argindex = 0; - } - // Now check if this is a keyword - else if (scriptconfig.IsKeyword(word)) - { - // Found it! - curfunctionname = scriptconfig.GetKeywordCase(word); - curargumentindex = argindex; - curfunctionstartpos = wordstart; - break; - } - else - { - // Don't know this word - break; - } - } - } - } - // Argument delimiter - else if (curchar == argumentdelimiter) - { - // Only count these at brackt level 0 - if (bracketlevel == 0) argindex++; - } - // Terminator - else if (curchar == terminator) - { - // Can't find anything, break now - break; - } - } - } - } - - // This registers an image for the autocomplete list - private void RegisterAutoCompleteImage(ImageIndex index, Bitmap image) - { - // Register image - scriptedit.RegisterRgbaImage((int)index, image); - } - - // This registers an image for the markes list - private void RegisterMarkerImage(ImageIndex index, Bitmap image) - { - // Register image - scriptedit.Markers[(int)index].DefineRgbaImage(image); - scriptedit.Markers[(int)index].Symbol = MarkerSymbol.RgbaImage; - } - - //mxd. This converts [LB] markers to line breaks if necessary - private static string[] ProcessLineBreaks(string[] lines) - { - List result = new List(lines.Length); - string[] separator = new[] { "[LB]" }; - - foreach (string line in lines) - { - if (line.IndexOf(separator[0], StringComparison.Ordinal) != -1) - { - if (General.Settings.ScriptAllmanStyle) - result.AddRange(line.Split(separator, StringSplitOptions.RemoveEmptyEntries)); - else - result.Add(line.Replace(separator[0], " ")); - } - else - { - result.Add(line); - } - } - - return result.ToArray(); - } - - //mxd. Autocompletion handling (https://github.com/jacobslusser/ScintillaNET/wiki/Basic-Autocompletion) - private bool ShowAutoCompletionList() - { - int currentpos = scriptedit.CurrentPosition; - int wordstartpos = scriptedit.WordStartPosition(currentpos, true); - - if (wordstartpos >= currentpos) - { - // Hide the list - scriptedit.AutoCCancel(); - return false; - } - - // Get entered text - string start = scriptedit.GetTextRange(wordstartpos, currentpos - wordstartpos); - if (string.IsNullOrEmpty(start)) - { - // Hide the list - scriptedit.AutoCCancel(); - return false; - } - - // Filter the list - List filtered = new List(); - foreach (string s in autocompletelist) - if (s.IndexOf(start, StringComparison.OrdinalIgnoreCase) != -1) filtered.Add(s); - - // Any matches? - if (filtered.Count > 0) - { - // Show the list - scriptedit.AutoCShow(currentpos - wordstartpos, string.Join(" ", filtered.ToArray())); - return true; - } - - // Hide the list - scriptedit.AutoCCancel(); - return false; - } - - //mxd - private string GetIndentationString(int indent) - { - if (scriptedit.UseTabs) - { - string indentstr = string.Empty; - int numtabs = indent / scriptedit.TabWidth; - if (numtabs > 0) indentstr = new string('\t', numtabs); - - // Mixed padding? Add spaces - if (numtabs * scriptedit.TabWidth < indent) - { - int numspaces = indent - numtabs * scriptedit.TabWidth; - indentstr += new string(' ', numspaces); - } - - return indentstr; - } - else - { - return new string(' ', indent); - } - } - - //mxd. https://github.com/jacobslusser/ScintillaNET/wiki/Find-and-Highlight-Words - private void HighlightWord(string text) - { - // Remove all uses of our indicator - scriptedit.IndicatorCurrent = HIGHLIGHT_INDICATOR; - scriptedit.IndicatorClearRange(0, scriptedit.TextLength); - - // Update indicator appearance - scriptedit.Indicators[HIGHLIGHT_INDICATOR].Style = IndicatorStyle.RoundBox; - scriptedit.Indicators[HIGHLIGHT_INDICATOR].Under = true; - scriptedit.Indicators[HIGHLIGHT_INDICATOR].ForeColor = General.Colors.ScriptIndicator.ToColor(); - scriptedit.Indicators[HIGHLIGHT_INDICATOR].OutlineAlpha = 50; - scriptedit.Indicators[HIGHLIGHT_INDICATOR].Alpha = 30; - - // Search the document - scriptedit.TargetStart = 0; - scriptedit.TargetEnd = scriptedit.TextLength; - scriptedit.SearchFlags = SearchFlags.WholeWord; - - while (scriptedit.SearchInTarget(text) != -1) - { - //mxd. Don't mark currently selected word - if (scriptedit.SelectionStart != scriptedit.TargetStart && scriptedit.SelectionEnd != scriptedit.TargetEnd) - { - // Mark the search results with the current indicator - scriptedit.IndicatorFillRange(scriptedit.TargetStart, scriptedit.TargetEnd - scriptedit.TargetStart); - } - - // Search the remainder of the document - scriptedit.TargetStart = scriptedit.TargetEnd; - scriptedit.TargetEnd = scriptedit.TextLength; - } - } - - #endregion - - #region ================== Events - - // Layout needs to be re-organized - protected override void OnLayout(LayoutEventArgs e) - { - base.OnLayout(e); - - // With or without functions bar? - if (functionbar.Visible) - { - scriptpanel.Top = functionbar.Bottom + 6; - scriptpanel.Height = this.ClientSize.Height - scriptpanel.Top; - } - else - { - scriptpanel.Top = 0; - scriptpanel.Height = this.ClientSize.Height; - } - } - - //mxd. Script text changed - private void scriptedit_TextChanged(object sender, EventArgs e) - { - // Line number margin width needs changing? - int curlinenumbercharlength = scriptedit.Lines.Count.ToString().Length; - - // Calculate the width required to display the last line number - // and include some padding for good measure. - if (curlinenumbercharlength != linenumbercharlength) - { - const int padding = 2; - scriptedit.Margins[1].Width = scriptedit.TextWidth(Style.LineNumber, new string('9', curlinenumbercharlength + 1)) + padding; - linenumbercharlength = curlinenumbercharlength; - } - - if (OnTextChanged != null) OnTextChanged(this, EventArgs.Empty); - } - - //mxd - private void scriptedit_CharAdded(object sender, CharAddedEventArgs e) - { - // Hide call tip if any - scriptedit.CallTipCancel(); - - // Offset caret if needed - if (caretoffset != 0) - { - scriptedit.SetEmptySelection(scriptedit.SelectionStart + caretoffset); - caretoffset = 0; - if (!expandcodeblock) return; - } - - // Move CodeBlockOpen to the new line? - if (expandcodeblock) - { - if (scriptedit.CurrentLine > 0) - { - string linetext = scriptedit.Lines[scriptedit.CurrentLine - 1].Text; - int blockopenpos = (string.IsNullOrEmpty(scriptconfig.CodeBlockOpen) ? -1 : linetext.LastIndexOf(scriptconfig.CodeBlockOpen, StringComparison.Ordinal)); - if (blockopenpos != -1) - { - // Do it only if initial line doesn't start with CodeBlockOpen - string linestart = linetext.Substring(0, blockopenpos).Trim(); - if (linestart.Length > 0) - { - scriptedit.InsertText(scriptedit.Lines[scriptedit.CurrentLine - 1].Position + blockopenpos, - Environment.NewLine + GetIndentationString(scriptedit.Lines[scriptedit.CurrentLine - 1].Indentation)); - } - } - } - - expandcodeblock = false; - return; - } - - // Auto-match braces - if (General.Settings.ScriptAutoCloseBrackets) - { - //TODO: Auto-match quotes - bool endpos = (scriptedit.CurrentPosition == scriptedit.TextLength); - if (!string.IsNullOrEmpty(scriptconfig.CodeBlockOpen) && e.Char == scriptconfig.CodeBlockOpen[0] && !string.IsNullOrEmpty(scriptconfig.CodeBlockClose) && - (endpos || (char)scriptedit.GetCharAt(scriptedit.CurrentPosition + 1) != scriptconfig.CodeBlockClose[0])) - { - scriptedit.InsertText(scriptedit.CurrentPosition, scriptconfig.CodeBlockClose); - return; - } - - if (!string.IsNullOrEmpty(scriptconfig.FunctionOpen) && e.Char == scriptconfig.FunctionOpen[0] && !string.IsNullOrEmpty(scriptconfig.FunctionClose) && - (endpos || (char)scriptedit.GetCharAt(scriptedit.CurrentPosition + 1) != scriptconfig.FunctionClose[0])) - { - scriptedit.InsertText(scriptedit.CurrentPosition, scriptconfig.FunctionClose); - return; - } - - if (!string.IsNullOrEmpty(scriptconfig.ArrayOpen) && e.Char == scriptconfig.ArrayOpen[0] && !string.IsNullOrEmpty(scriptconfig.ArrayClose) && - (endpos || (char)scriptedit.GetCharAt(scriptedit.CurrentPosition + 1) != scriptconfig.ArrayClose[0])) - { - scriptedit.InsertText(scriptedit.CurrentPosition, scriptconfig.ArrayClose); - return; - } - } - - if (General.Settings.ScriptAutoShowAutocompletion) - { - // Display the autocompletion list - ShowAutoCompletionList(); - } - } - - //mxd - private void scriptedit_UpdateUI(object sender, UpdateUIEventArgs e) - { - // If a word is selected, highlight the same words - if (scriptedit.SelectedText != highlightedword) - { - // Highlight only when whole word is selected - if (!string.IsNullOrEmpty(scriptedit.SelectedText) && scriptedit.GetWordFromPosition(scriptedit.SelectionStart) == scriptedit.SelectedText) - { - HighlightWord(scriptedit.SelectedText); - } - else - { - // Clear highlight - scriptedit.IndicatorCurrent = HIGHLIGHT_INDICATOR; - scriptedit.IndicatorClearRange(0, scriptedit.TextLength); - } - - highlightedword = scriptedit.SelectedText; - } - - // Has the caret changed position? - int caretpos = scriptedit.CurrentPosition; - if (lastcaretpos != caretpos && scriptconfig.BraceChars.Count > 0) - { - // Perform brace matching (https://github.com/jacobslusser/ScintillaNET/wiki/Brace-Matching) - lastcaretpos = caretpos; - int bracepos1 = -1; - - // Is there a brace to the left or right? - if (caretpos > 0 && scriptconfig.BraceChars.Contains((char)scriptedit.GetCharAt(caretpos - 1))) - bracepos1 = (caretpos - 1); - else if (scriptconfig.BraceChars.Contains((char)(scriptedit.GetCharAt(caretpos)))) - bracepos1 = caretpos; - - if (bracepos1 > -1) - { - // Find the matching brace - int bracepos2 = scriptedit.BraceMatch(bracepos1); - if (bracepos2 == Scintilla.InvalidPosition) - scriptedit.BraceBadLight(bracepos1); - else - scriptedit.BraceHighlight(bracepos1, bracepos2); - } - else - { - // Turn off brace matching - scriptedit.BraceHighlight(Scintilla.InvalidPosition, Scintilla.InvalidPosition); - } - } - } - - //mxd - private void scriptedit_InsertCheck(object sender, InsertCheckEventArgs e) - { - // Gross hacks... - if (skiptextinsert) - { - e.Text = string.Empty; - skiptextinsert = false; - } - // Do we want auto-indentation? - else if (!expandcodeblock && General.Settings.ScriptAutoIndent && e.Text == "\r\n") - { - // Get current line indentation up to the cursor position - string linetext = scriptedit.Lines[scriptedit.CurrentLine].Text; - int selectionpos = scriptedit.SelectionStart - scriptedit.Lines[scriptedit.CurrentLine].Position; - int indent = 0; - for (int i = 0; i < selectionpos; i++) - { - switch (linetext[i]) - { - case ' ': indent++; break; - case '\t': indent += scriptedit.TabWidth; break; - default: i = selectionpos; break; // break the loop - } - } - - // Store initial indentation - int initialindent = indent; - - // Need to increase indentation? We do this when: - // 1. Line contains '{' and '}' and the cursor is between them - // 2. Line either doesn't contain '}', or it's before '{', or the line contains '{' and the cursor is after it - int blockopenpos = (string.IsNullOrEmpty(scriptconfig.CodeBlockOpen) ? -1 : linetext.LastIndexOf(scriptconfig.CodeBlockOpen, selectionpos, StringComparison.Ordinal)); - int blockclosepos = (string.IsNullOrEmpty(scriptconfig.CodeBlockOpen) ? -1 : linetext.IndexOf(scriptconfig.CodeBlockClose, selectionpos, StringComparison.Ordinal)); - - // Add indentation when the cursor is between { and } - bool addindent = (blockopenpos != -1 && blockopenpos < selectionpos) && (blockclosepos == -1 || (blockopenpos < blockclosepos && blockclosepos >= selectionpos)); - if (addindent) indent += scriptedit.TabWidth; - - // Calculate indentation - string indentstr = GetIndentationString(indent); - - // Move CodeBlockOpen to the new line? (will be applied in scriptedit_CharAdded) - expandcodeblock = General.Settings.ScriptAllmanStyle; - - // Offset closing block char? - if (addindent && blockclosepos != -1) - { - string initialindentstr = GetIndentationString(initialindent); - indentstr += Environment.NewLine + initialindentstr; - - // Offset cursor position (will be performed in scriptedit_CharAdded) - caretoffset = -(initialindentstr.Length + Environment.NewLine.Length); - } - - // Apply new indentation - e.Text += indentstr; - } - } - - //mxd - private void scriptedit_AutoCCompleted(object sender, AutoCSelectionEventArgs e) - { - // Expand snippet? - string[] lines = scriptconfig.GetSnippet(e.Text); - if (lines != null) InsertSnippet(lines); - } - - // Key pressed down - private void scriptedit_KeyDown(object sender, KeyEventArgs e) - { - // F3 for Find Next - if ((e.KeyCode == Keys.F3) && (e.Modifiers == Keys.None)) - { - if (OnFindNext != null) OnFindNext(); - } - // F2 for Find Previous (mxd) - else if ((e.KeyCode == Keys.F2) && (e.Modifiers == Keys.None)) - { - if (OnFindPrevious != null) OnFindPrevious(); - } - // CTRL+F for find & replace - else if ((e.KeyCode == Keys.F) && ((e.Modifiers & Keys.Control) == Keys.Control)) - { - if (OnOpenFindAndReplace != null) OnOpenFindAndReplace(); - } - // CTRL+S for save - else if ((e.KeyCode == Keys.S) && ((e.Modifiers & Keys.Control) == Keys.Control)) - { - if (OnExplicitSaveTab != null) OnExplicitSaveTab(); - } - // CTRL+O for open - else if ((e.KeyCode == Keys.O) && ((e.Modifiers & Keys.Control) == Keys.Control)) - { - if (OnOpenScriptBrowser != null) OnOpenScriptBrowser(); - } - // CTRL+Space to autocomplete - else if ((e.KeyCode == Keys.Space) && (e.Modifiers == Keys.Control)) - { - // Hide call tip if any - scriptedit.CallTipCancel(); - - // Show autocomplete - if (ShowAutoCompletionList()) skiptextinsert = true; - } - //mxd. Tab to expand code snippet. Do it only when the text cursor is at the end of a keyword. - else if (e.KeyCode == Keys.Tab) - { - if (!scriptedit.AutoCActive) - { - string curword = GetCurrentWord().ToLowerInvariant(); - if (scriptconfig.Snippets.Contains(curword) && scriptedit.CurrentPosition == scriptedit.WordEndPosition(scriptedit.CurrentPosition, true)) - { - InsertSnippet(scriptconfig.GetSnippet(curword)); - skiptextinsert = true; - } - } - } - else - { - //mxd. Skip text insert when "save screenshot" action's keys are pressed - Actions.Action[] actions = General.Actions.GetActionsByKey((int)e.KeyData); - foreach (Actions.Action action in actions) - { - if (action.ShortName == "savescreenshot" || action.ShortName == "saveeditareascreenshot") - { - skiptextinsert = true; - return; - } - } - } - } - - // Key released - private void scriptedit_KeyUp(object sender, KeyEventArgs e) - { - bool showcalltip = false; - int highlightstart = 0; - int highlightend = 0; - - UpdatePositionInfo(); - - // Call tip shown - if (scriptedit.CallTipActive) - { - // Should we hide the call tip? - if (curfunctionname.Length == 0) - { - // Hide the call tip - scriptedit.CallTipCancel(); - } - else - { - // Update the call tip - showcalltip = true; - } - } - // No call tip - else - { - // Should we show a call tip? - showcalltip = (curfunctionname.Length > 0) && !scriptedit.AutoCActive; - } - - // Show or update call tip - if (showcalltip) - { - string functiondef = scriptconfig.GetFunctionDefinition(curfunctionname); - if (functiondef != null) - { - // Determine the range to highlight - int argsopenpos = functiondef.IndexOf(scriptconfig.FunctionOpen, StringComparison.Ordinal); - int argsclosepos = functiondef.LastIndexOf(scriptconfig.FunctionClose, StringComparison.Ordinal); - if ((argsopenpos > -1) && (argsclosepos > -1)) - { - string argsstr = functiondef.Substring(argsopenpos + 1, argsclosepos - argsopenpos - 1); - string[] args = argsstr.Split(scriptconfig.ArgumentDelimiter[0]); - if ((curargumentindex >= 0) && (curargumentindex < args.Length)) - { - int argoffset = 0; - for (int i = 0; i < curargumentindex; i++) argoffset += args[i].Length + 1; - highlightstart = argsopenpos + argoffset + 1; - highlightend = highlightstart + args[curargumentindex].Length; - } - } - - //mxd. If the tip obscures the view, move it down - int tippos; - int funcline = scriptedit.LineFromPosition(curfunctionstartpos); - if (scriptedit.CurrentLine > funcline) - tippos = scriptedit.Lines[scriptedit.CurrentLine].Position + scriptedit.Lines[scriptedit.CurrentLine].Indentation; //scriptedit.PositionFromLine(curline) /*+ (curfunctionstartpos - scriptedit.PositionFromLine(funcline))*/; - else - tippos = curfunctionstartpos; - - // Show tip - scriptedit.CallTipShow(tippos, functiondef); - scriptedit.CallTipSetHlt(highlightstart, highlightend); - } - } - } - - #endregion - } -} \ No newline at end of file + internal enum ScriptStyleType + { + PlainText = 0, + Keyword = 1, + Constant = 2, + Comment = 3, + Literal = 4, + LineNumber = 5, + String = 6, //mxd + Include = 7, //mxd + Property = 8, //mxd + } + + internal partial class ScriptEditorControl : UserControl + { + #region ================== Enums + + // Index for registered images + private enum ImageIndex + { + ScriptConstant = 0, + ScriptKeyword = 1, + ScriptError = 2, + ScriptSnippet = 3, //mxd + ScriptProperty = 4, //mxd + } + + #endregion + + #region ================== Constants + + private const string LEXERS_RESOURCE = "Lexers.cfg"; + private const int MAX_BACKTRACK_LENGTH = 200; + private const int HIGHLIGHT_INDICATOR = 8; //mxd. Indicators 0-7 could be in use by a lexer so we'll use indicator 8 to highlight words. + + #endregion + + #region ================== Delegates / Events + + public delegate void ExplicitSaveTabDelegate(); + public delegate void OpenScriptBrowserDelegate(); + public delegate void OpenFindReplaceDelegate(); + public delegate void FindNextDelegate(); + public delegate void FindPreviousDelegate(); //mxd + + public event ExplicitSaveTabDelegate OnExplicitSaveTab; + public event OpenScriptBrowserDelegate OnOpenScriptBrowser; + public event OpenFindReplaceDelegate OnOpenFindAndReplace; + public event FindNextDelegate OnFindNext; + public event FindPreviousDelegate OnFindPrevious; //mxd + public new event EventHandler OnTextChanged; //mxd + + #endregion + + #region ================== Variables + + // Script configuration + private ScriptConfiguration scriptconfig; + + // List of keywords and constants + private List autocompletelist; + + // Style translation from Scintilla style to ScriptStyleType + private Dictionary stylelookup; + + // Current position information + private string curfunctionname = ""; + private int curargumentindex; + private int curfunctionstartpos; + private int linenumbercharlength; //mxd. Current max number of chars in the line number + private int lastcaretpos; //mxd. Used in brace matching + private int caretoffset; //mxd. Used to modify caret position after autogenerating stuff + private bool skiptextinsert; //mxd. Gross hacks + private bool expandcodeblock; //mxd. More gross hacks + private string highlightedword; //mxd + private Encoding encoding; //mxd + + #endregion + + #region ================== Properties + + public bool IsChanged { get { return scriptedit.Modified; } } + public int SelectionStart { get { return scriptedit.SelectionStart; } set { scriptedit.SelectionStart = value; } } + public int SelectionEnd { get { return scriptedit.SelectionEnd; } set { scriptedit.SelectionEnd = value; } } + public new string Text { get { return scriptedit.Text; } set { scriptedit.Text = value; } } //mxd + public string SelectedText { get { return scriptedit.SelectedText; } } //mxd + public bool ShowWhitespace { get { return scriptedit.ViewWhitespace != WhitespaceMode.Invisible; } set { scriptedit.ViewWhitespace = value ? WhitespaceMode.VisibleAlways : WhitespaceMode.Invisible; } } + public bool WrapLongLines { get { return scriptedit.WrapMode != WrapMode.None; } set { scriptedit.WrapMode = (value ? WrapMode.Char : WrapMode.None); } } + public ComboBox FunctionBar { get { return functionbar; } } //mxd + public Scintilla Scintilla { get { return scriptedit; } } //mxd + + #endregion + + #region ================== Contructor / Disposer + + // Constructor + public ScriptEditorControl() + { + // Initialize + InitializeComponent(); + + //mxd. ASCII with cyrillic support... + encoding = Encoding.GetEncoding(1251); + + // Script editor properties + //TODO: use ScintillaNET properties instead when they become available + scriptedit.DirectMessage(NativeMethods.SCI_SETBACKSPACEUNINDENTS, new IntPtr(1)); + scriptedit.DirectMessage(NativeMethods.SCI_SETMOUSEDOWNCAPTURES, new IntPtr(1)); + scriptedit.DirectMessage(NativeMethods.SCI_SETTABINDENTS, new IntPtr(1)); + + // Symbol margin + scriptedit.Margins[0].Type = MarginType.Symbol; + scriptedit.Margins[0].Width = 20; + scriptedit.Margins[0].Mask = 1 << (int)ImageIndex.ScriptError; // Error marker only + scriptedit.Margins[0].Cursor = MarginCursor.Arrow; + scriptedit.Margins[0].Sensitive = true; + + // Line numbers margin + if(General.Settings.ScriptShowLineNumbers) + { + scriptedit.Margins[1].Type = MarginType.Number; + scriptedit.Margins[1].Width = 16; + } + scriptedit.Margins[1].Mask = 0; // No markers here + + // Spacing margin + scriptedit.Margins[2].Type = MarginType.Symbol; + scriptedit.Margins[2].Width = 5; + scriptedit.Margins[2].Cursor = MarginCursor.Arrow; + scriptedit.Margins[2].Mask = 0; // No markers here + + // Images + RegisterAutoCompleteImage(ImageIndex.ScriptConstant, Resources.ScriptConstant); + RegisterAutoCompleteImage(ImageIndex.ScriptKeyword, Resources.ScriptKeyword); + RegisterAutoCompleteImage(ImageIndex.ScriptSnippet, Resources.ScriptSnippet); //mxd + RegisterAutoCompleteImage(ImageIndex.ScriptProperty, Resources.ScriptProperty); //mxd + RegisterMarkerImage(ImageIndex.ScriptError, Resources.ScriptError); + + //mxd. These key combinations put odd characters in the script. Let's disable them + scriptedit.AssignCmdKey(Keys.Control | Keys.Q, Command.Null); + scriptedit.AssignCmdKey(Keys.Control | Keys.W, Command.Null); + scriptedit.AssignCmdKey(Keys.Control | Keys.E, Command.Null); + scriptedit.AssignCmdKey(Keys.Control | Keys.R, Command.Null); + scriptedit.AssignCmdKey(Keys.Control | Keys.Y, Command.Null); + scriptedit.AssignCmdKey(Keys.Control | Keys.U, Command.Null); + scriptedit.AssignCmdKey(Keys.Control | Keys.I, Command.Null); + scriptedit.AssignCmdKey(Keys.Control | Keys.P, Command.Null); + scriptedit.AssignCmdKey(Keys.Control | Keys.Shift | Keys.A, Command.Null); + scriptedit.AssignCmdKey(Keys.Control | Keys.D, Command.Null); + scriptedit.AssignCmdKey(Keys.Control | Keys.G, Command.Null); + scriptedit.AssignCmdKey(Keys.Control | Keys.H, Command.Null); + scriptedit.AssignCmdKey(Keys.Control | Keys.J, Command.Null); + scriptedit.AssignCmdKey(Keys.Control | Keys.K, Command.Null); + scriptedit.AssignCmdKey(Keys.Control | Keys.L, Command.Null); + scriptedit.AssignCmdKey(Keys.Control | Keys.Shift | Keys.Z, Command.Null); + scriptedit.AssignCmdKey(Keys.Control | Keys.Shift | Keys.X, Command.Null); + scriptedit.AssignCmdKey(Keys.Control | Keys.Shift | Keys.C, Command.Null); + scriptedit.AssignCmdKey(Keys.Control | Keys.Shift | Keys.V, Command.Null); + scriptedit.AssignCmdKey(Keys.Control | Keys.B, Command.Null); + scriptedit.AssignCmdKey(Keys.Control | Keys.N, Command.Null); + scriptedit.AssignCmdKey(Keys.Control | Keys.M, Command.Null); + + //mxd. These key combinations are used to perform special actions. Let's disable them + scriptedit.AssignCmdKey(Keys.F3, Command.Null); // F3 for Find Next + scriptedit.AssignCmdKey(Keys.F2, Command.Null); // F2 for Find Previous + scriptedit.AssignCmdKey(Keys.Control | Keys.F, Command.Null); // CTRL+F for find & replace + scriptedit.AssignCmdKey(Keys.Control | Keys.S, Command.Null); // CTRL+S for save + scriptedit.AssignCmdKey(Keys.Control | Keys.O, Command.Null); // CTRL+O for open + scriptedit.AssignCmdKey(Keys.Control | Keys.Space, Command.Null); // CTRL+Space to autocomplete <- TODO: this doesn't seem to work... + } + + #endregion + + #region ================== Public methods + + // This launches keyword help website + public bool LaunchKeywordHelp() + { + string helpsite = scriptconfig.KeywordHelp; + string currentword = GetCurrentWord(); + if(!string.IsNullOrEmpty(currentword) && (currentword.Length > 1) && !string.IsNullOrEmpty(helpsite)) + { + currentword = scriptconfig.GetKeywordCase(currentword); + helpsite = helpsite.Replace("%K", currentword); + General.OpenWebsite(helpsite); + return true; + } + + return !string.IsNullOrEmpty(helpsite); //mxd + } + + // This replaces the selection with the given text + public void ReplaceSelection(string replacement) + { + scriptedit.ReplaceSelection(replacement); //mxd TODO: encoding check/conversion? + } + + // This moves the caret to a given line and ensures the line is visible + public void MoveToLine(int linenumber) + { + scriptedit.Lines[linenumber].Goto(); + EnsureLineVisible(linenumber); + } + + // This makes sure a line is visible + public void EnsureLineVisible(int linenumber) + { + // Determine target lines range + int startline = Math.Max(0, linenumber - 4); + int endline = Math.Min(scriptedit.Lines.Count, Math.Max(linenumber, linenumber + scriptedit.LinesOnScreen - 6)); + + // Go to target line + scriptedit.DirectMessage(NativeMethods.SCI_ENSUREVISIBLEENFORCEPOLICY, (IntPtr)startline); // Unfold the whole text block if needed + scriptedit.ShowLines(startline, endline); + + // We may want to do some scrolling... + if(scriptedit.FirstVisibleLine >= startline) + scriptedit.Lines[startline].Goto(); + else if(scriptedit.FirstVisibleLine + scriptedit.LinesOnScreen <= endline) + scriptedit.Lines[endline].Goto(); + } + + //mxd + private void SelectAndShow(int startpos, int endpos) + { + // Select the result + int startline = scriptedit.LineFromPosition(startpos); + int endline = scriptedit.LineFromPosition(endpos); + + // Go to target line + scriptedit.DirectMessage(NativeMethods.SCI_ENSUREVISIBLEENFORCEPOLICY, (IntPtr)startline); // Unfold the whole text block if needed + scriptedit.ShowLines(startline, endline); + scriptedit.GotoPosition(startpos); + + // We may want to do some extra scrolling... + if(startline > 1 && scriptedit.FirstVisibleLine >= startline - 1) + scriptedit.Lines[startline - 1].Goto(); + else if(endline < scriptedit.Lines.Count - 1 && scriptedit.FirstVisibleLine + scriptedit.LinesOnScreen <= endline + 1) + scriptedit.Lines[endline + 1].Goto(); + + // Update selection + scriptedit.SelectionStart = startpos; + scriptedit.SelectionEnd = endpos; + } + + // This returns the line for a position + public int LineFromPosition(int position) + { + return scriptedit.LineFromPosition(position); + } + + // This clears all marks + public void ClearMarks() + { + scriptedit.MarkerDeleteAll((int)ImageIndex.ScriptError); + } + + // This adds a mark on the given line + public void AddMark(int linenumber) + { + scriptedit.Lines[linenumber].MarkerAdd((int)ImageIndex.ScriptError); + } + + // This refreshes the style setup + public void RefreshStyle() + { + // Re-setup with the same config + SetupStyles(scriptconfig); + } + + // This sets up the script editor with a script configuration + public void SetupStyles(ScriptConfiguration config) + { + Configuration lexercfg = new Configuration(); + + // Make collections + stylelookup = new Dictionary(); + Dictionary autocompletedict = new Dictionary(StringComparer.Ordinal); + + // Keep script configuration + scriptconfig = config; + + // Find a resource named Lexers.cfg + string[] resnames = General.ThisAssembly.GetManifestResourceNames(); + foreach(string rn in resnames) + { + // Found one? + if(rn.EndsWith(LEXERS_RESOURCE, StringComparison.OrdinalIgnoreCase)) + { + // Get a stream from the resource + Stream lexersdata = General.ThisAssembly.GetManifestResourceStream(rn); + if(lexersdata != null) + { + StreamReader lexersreader = new StreamReader(lexersdata, Encoding.ASCII); + + // Load configuration from stream + lexercfg.InputConfiguration(lexersreader.ReadToEnd()); + + // Done with the resource + lexersreader.Dispose(); + lexersdata.Dispose(); + } + + //mxd. We are done here + break; + } + } + + //mxd. Reset document slyle + scriptedit.ClearDocumentStyle(); + scriptedit.StyleResetDefault(); + + // Check if specified lexer exists and set the lexer to use + string lexername = "lexer" + (int)scriptconfig.Lexer; + if(!lexercfg.SettingExists(lexername)) throw new InvalidOperationException("Unknown lexer " + scriptconfig.Lexer + " specified in script configuration!"); + scriptedit.Lexer = scriptconfig.Lexer; + + //mxd. Set word chars + scriptedit.SetWordChars(scriptconfig.WordCharacters); + + // Set the default style and settings + scriptedit.Styles[Style.Default].Font = General.Settings.ScriptFontName; + scriptedit.Styles[Style.Default].Size = General.Settings.ScriptFontSize; + scriptedit.Styles[Style.Default].Bold = General.Settings.ScriptFontBold; + scriptedit.Styles[Style.Default].Italic = false; + scriptedit.Styles[Style.Default].Underline = false; + scriptedit.Styles[Style.Default].Case = StyleCase.Mixed; + scriptedit.Styles[Style.Default].ForeColor = General.Colors.PlainText.ToColor(); + scriptedit.Styles[Style.Default].BackColor = General.Colors.ScriptBackground.ToColor(); + scriptedit.CaretPeriod = SystemInformation.CaretBlinkTime; + scriptedit.CaretForeColor = General.Colors.ScriptBackground.Inverse().ToColor(); + + // Set tabulation settings + scriptedit.UseTabs = General.Settings.ScriptUseTabs; + scriptedit.TabWidth = General.Settings.ScriptTabWidth; + //scriptedit.IndentWidth = General.Settings.ScriptTabWidth; // Equals to TabWidth by default + //TODO: use ScintillaNET properties instead when they become available + scriptedit.DirectMessage(NativeMethods.SCI_SETTABINDENTS, new IntPtr(1)); + scriptedit.DirectMessage(NativeMethods.SCI_SETBACKSPACEUNINDENTS, new IntPtr(1)); + + // This applies the default style to all styles + scriptedit.StyleClearAll(); + + // Set the code page to use. [mxd] No longer needed? + //scriptedit.CodePage = scriptconfig.CodePage; + + //mxd. We can't change Font or Size here because this will screw displayed tab width (because it's based on character width)... + // Set the default to something normal (this is used by the autocomplete list) + //scriptedit.Styles[Style.Default].Font = this.Font.Name; + scriptedit.Styles[Style.Default].Bold = this.Font.Bold; + scriptedit.Styles[Style.Default].Italic = this.Font.Italic; + scriptedit.Styles[Style.Default].Underline = this.Font.Underline; + //scriptedit.Styles[Style.Default].Size = (int)Math.Round(this.Font.SizeInPoints); + + // Set style for linenumbers and margins + scriptedit.Styles[Style.LineNumber].BackColor = General.Colors.ScriptBackground.ToColor(); + scriptedit.SetFoldMarginColor(true, General.Colors.ScriptFoldBackColor.ToColor()); + scriptedit.SetFoldMarginHighlightColor(true, General.Colors.ScriptFoldBackColor.ToColor()); + for(int i = 25; i < 32; i++) + { + scriptedit.Markers[i].SetForeColor(General.Colors.ScriptFoldBackColor.ToColor()); + scriptedit.Markers[i].SetBackColor(General.Colors.ScriptFoldForeColor.ToColor()); + } + + //mxd. Set style for (mis)matching braces + scriptedit.Styles[Style.BraceLight].BackColor = General.Colors.ScriptBraceHighlight.ToColor(); + scriptedit.Styles[Style.BraceBad].BackColor = General.Colors.ScriptBadBraceHighlight.ToColor(); + + //mxd. Set whitespace color + scriptedit.SetWhitespaceForeColor(true, General.Colors.ScriptWhitespace.ToColor()); + + //mxd. Set selection colors + scriptedit.SetSelectionForeColor(true, General.Colors.ScriptSelectionForeColor.ToColor()); + scriptedit.SetSelectionBackColor(true, General.Colors.ScriptSelectionBackColor.ToColor()); + + // Clear all keywords + for(int i = 0; i < 9; i++) scriptedit.SetKeywords(i, null); + + // Now go for all elements in the lexer configuration + // We are looking for the numeric keys, because these are the + // style index to set and the value is our ScriptStyleType + IDictionary dic = lexercfg.ReadSetting(lexername, new Hashtable()); + foreach(DictionaryEntry de in dic) + { + // Check if this is a numeric key + int stylenum; + if(int.TryParse(de.Key.ToString(), out stylenum)) + { + // Add style to lookup table + stylelookup.Add(stylenum, (ScriptStyleType)(int)de.Value); + + // Apply color to style + int colorindex; + ScriptStyleType type = (ScriptStyleType)(int)de.Value; + switch(type) + { + case ScriptStyleType.PlainText: colorindex = ColorCollection.PLAINTEXT; break; + case ScriptStyleType.Comment: colorindex = ColorCollection.COMMENTS; break; + case ScriptStyleType.Constant: colorindex = ColorCollection.CONSTANTS; break; + case ScriptStyleType.Keyword: colorindex = ColorCollection.KEYWORDS; break; + case ScriptStyleType.LineNumber: colorindex = ColorCollection.LINENUMBERS; break; + case ScriptStyleType.Literal: colorindex = ColorCollection.LITERALS; break; + case ScriptStyleType.String: colorindex = ColorCollection.STRINGS; break; + case ScriptStyleType.Include: colorindex = ColorCollection.INCLUDES; break; + case ScriptStyleType.Property: colorindex = ColorCollection.PROPERTIES; break; + default: colorindex = ColorCollection.PLAINTEXT; break; + } + + scriptedit.Styles[stylenum].ForeColor = General.Colors.Colors[colorindex].ToColor(); + } + } + + // Create the keywords list and apply it + string imageindex = ((int)ImageIndex.ScriptKeyword).ToString(CultureInfo.InvariantCulture); + int keywordsindex = lexercfg.ReadSetting(lexername + ".keywordsindex", -1); + if(keywordsindex > -1) + { + StringBuilder keywordslist = new StringBuilder(); + foreach(string k in scriptconfig.Keywords) + { + if(keywordslist.Length > 0) keywordslist.Append(" "); + keywordslist.Append(k); + + //mxd. Skip adding the keyword if we have a snippet with the same name + if(!scriptconfig.Snippets.Contains(k)) + autocompletedict.Add(k, k + "?" + imageindex); + } + string words = keywordslist.ToString(); + scriptedit.SetKeywords(keywordsindex, (scriptconfig.CaseSensitive ? words : words.ToLowerInvariant())); + } + + //mxd. Create the properties list and apply it + imageindex = ((int)ImageIndex.ScriptProperty).ToString(CultureInfo.InvariantCulture); + int propertiesindex = lexercfg.ReadSetting(lexername + ".propertiesindex", -1); + if(propertiesindex > -1) + { + StringBuilder propertieslist = new StringBuilder(); + HashSet addedprops = new HashSet(); + char[] dot = {'.'}; + foreach(string p in scriptconfig.Properties) + { + if(propertieslist.Length > 0) propertieslist.Append(" "); + + // Scintilla doesn't highlight keywords with '.' or ':', so get rid of those + if(scriptconfig.ScriptType == ScriptType.DECORATE) + { + string prop = p; + if(prop.Contains(":")) prop = prop.Replace(":", string.Empty); + if(prop.Contains(".")) + { + // Split dotted properties into separate entries + string[] parts = prop.Split(dot, StringSplitOptions.RemoveEmptyEntries); + List result = new List(); + foreach(string part in parts) + { + if(!addedprops.Contains(part)) + { + result.Add(part); + addedprops.Add(part); + } + } + + if(result.Count > 0) propertieslist.Append(string.Join(" ", result.ToArray())); + } + else + { + addedprops.Add(prop); + propertieslist.Append(prop); + } + } + else + { + propertieslist.Append(p); + } + + // Autocomplete doesn't mind '.' or ':' + // Skip adding the keyword if we have a snippet with the same name + if(!scriptconfig.Snippets.Contains(p)) + autocompletedict.Add(p, p + "?" + imageindex); + } + string words = propertieslist.ToString(); + scriptedit.SetKeywords(propertiesindex, (scriptconfig.CaseSensitive ? words : words.ToLowerInvariant())); + } + + // Create the constants list and apply it + imageindex = ((int)ImageIndex.ScriptConstant).ToString(CultureInfo.InvariantCulture); + int constantsindex = lexercfg.ReadSetting(lexername + ".constantsindex", -1); + if(constantsindex > -1) + { + StringBuilder constantslist = new StringBuilder(); + foreach(string c in scriptconfig.Constants) + { + if(autocompletedict.ContainsKey(c)) continue; //mxd. This happens when there's a keyword and a constant with the same name... + + if(constantslist.Length > 0) constantslist.Append(" "); + constantslist.Append(c); + + //mxd. Skip adding the constant if we have a snippet with the same name + if(!scriptconfig.Snippets.Contains(c)) + autocompletedict.Add(c, c + "?" + imageindex); + } + string words = constantslist.ToString(); + scriptedit.SetKeywords(constantsindex, (scriptconfig.CaseSensitive ? words : words.ToLowerInvariant())); + } + + //mxd. Create the snippets list and apply it + imageindex = ((int)ImageIndex.ScriptSnippet).ToString(CultureInfo.InvariantCulture); + int snippetindex = lexercfg.ReadSetting(lexername + ".snippetindex", -1); + if(snippetindex > -1 && scriptconfig.Snippets.Count > 0) + { + StringBuilder snippetslist = new StringBuilder(); + foreach(string s in scriptconfig.Snippets) + { + if(snippetslist.Length > 0) snippetslist.Append(" "); + snippetslist.Append(s); + autocompletedict.Add(s, s + "?" + imageindex); + } + string words = snippetslist.ToString(); + scriptedit.SetKeywords(snippetindex, (scriptconfig.CaseSensitive ? words : words.ToLowerInvariant())); + } + + // Make autocomplete list + autocompletelist = new List(autocompletedict.Values); + + // Setup folding (https://github.com/jacobslusser/ScintillaNET/wiki/Automatic-Code-Folding) + if(General.Settings.ScriptShowFolding && (scriptconfig.Lexer == Lexer.Cpp || scriptconfig.Lexer == Lexer.CppNoCase)) + { + // Instruct the lexer to calculate folding + scriptedit.SetProperty("fold", "1"); + scriptedit.SetProperty("fold.compact", "0"); // 1 = folds blank lines + scriptedit.SetProperty("fold.comment", "1"); // Enable block comment folding + scriptedit.SetProperty("fold.preprocessor", "1"); // Enable #region folding + scriptedit.SetFoldFlags(FoldFlags.LineAfterContracted); // Draw line below if not expanded + + // Configure a margin to display folding symbols + scriptedit.Margins[2].Type = MarginType.Symbol; + scriptedit.Margins[2].Mask = Marker.MaskFolders; + scriptedit.Margins[2].Sensitive = true; + scriptedit.Margins[2].Width = 12; + + // Configure folding markers with respective symbols + scriptedit.Markers[Marker.Folder].Symbol = MarkerSymbol.BoxPlus; + scriptedit.Markers[Marker.FolderOpen].Symbol = MarkerSymbol.BoxMinus; + scriptedit.Markers[Marker.FolderEnd].Symbol = MarkerSymbol.BoxPlusConnected; + scriptedit.Markers[Marker.FolderMidTail].Symbol = MarkerSymbol.TCorner; + scriptedit.Markers[Marker.FolderOpenMid].Symbol = MarkerSymbol.BoxMinusConnected; + scriptedit.Markers[Marker.FolderSub].Symbol = MarkerSymbol.VLine; + scriptedit.Markers[Marker.FolderTail].Symbol = MarkerSymbol.LCorner; + + // Enable automatic folding + scriptedit.AutomaticFold = (AutomaticFold.Show | AutomaticFold.Click | AutomaticFold.Change); + } + else + { + // Disable folding + scriptedit.SetProperty("fold", "0"); + scriptedit.SetProperty("fold.compact", "0"); + + scriptedit.Margins[2].Type = MarginType.Symbol; + scriptedit.Margins[2].Mask = 0; // No markers here + scriptedit.Margins[2].Sensitive = false; + scriptedit.Margins[2].Width = 5; + + scriptedit.AutomaticFold = AutomaticFold.None; + } + + // Rearrange the layout + this.PerformLayout(); + } + + // This returns the current word (where the caret is at) + public string GetCurrentWord() + { + return GetWordAt(scriptedit.CurrentPosition); + } + + // This returns the word at the given position + public string GetWordAt(int position) + { + return scriptedit.GetWordFromPosition(position); + } + + // Perform undo + public void Undo() + { + scriptedit.Undo(); + } + + // Perform redo + public void Redo() + { + scriptedit.Redo(); + } + + // This clears all undo levels + public void ClearUndoRedo() + { + scriptedit.EmptyUndoBuffer(); + } + + //mxd. This marks the current document as unmodified + public void SetSavePoint() + { + scriptedit.SetSavePoint(); + } + + // Perform cut + public void Cut() + { + scriptedit.Cut(); + } + + // Perform copy + public void Copy() + { + scriptedit.Copy(); + } + + // Perform paste + public void Paste() + { + scriptedit.Paste(); + } + + // This steals the focus (use with care!) + public void GrabFocus() + { + scriptedit.Focus(); + } + + public byte[] GetText() + { + return encoding.GetBytes(scriptedit.Text); //mxd TODO: other encodings?.. + } + + public void SetText(byte[] text) + { + scriptedit.Text = encoding.GetString(text); //mxd TODO: other encodings?.. + } + + //mxd + public void InsertSnippet(string[] lines) + { + // Insert the snippet + int curline = scriptedit.LineFromPosition(scriptedit.SelectionStart); + int indent = scriptedit.Lines[scriptedit.CurrentLine].Indentation; + string tabs = Environment.NewLine + GetIndentationString(indent); + string spaces = new String(' ', General.Settings.ScriptTabWidth); + int entrypos = -1; + int entryline = -1; + string[] processedlines = ProcessLineBreaks(lines); + + // Process special chars, try to find entry position marker + for(int i = 0; i < lines.Length; i++) + { + if(!scriptedit.UseTabs) processedlines[i] = processedlines[i].Replace("\t", spaces); + + // Check if we have the [EP] marker + if(entrypos == -1) + { + int pos = processedlines[i].IndexOf("[EP]", StringComparison.Ordinal); + if(pos != -1) + { + processedlines[i] = processedlines[i].Remove(pos, 4); + entryline = curline + i; + entrypos = processedlines[i].Length - pos; + } + } + } + + // Replace the text + string text = string.Join(tabs, processedlines); + scriptedit.SelectionStart = scriptedit.WordStartPosition(scriptedit.CurrentPosition, true); + scriptedit.SelectionEnd = scriptedit.WordEndPosition(scriptedit.CurrentPosition, true); + scriptedit.ReplaceSelection(text); + + // Move the cursor if we had the [EP] marker + if(entrypos != -1) + { + scriptedit.SetEmptySelection(scriptedit.Lines[entryline].EndPosition - entrypos - 2); + } + } + + //mxd. Find next result + public bool FindNext(FindReplaceOptions options, bool useselectionstart) + { + int startpos = (useselectionstart ? Math.Min(scriptedit.SelectionStart, scriptedit.SelectionEnd) : Math.Max(scriptedit.SelectionStart, scriptedit.SelectionEnd)); + + // Search the document + scriptedit.TargetStart = startpos; + scriptedit.TargetEnd = scriptedit.TextLength; + scriptedit.SearchFlags = options.CaseSensitive ? SearchFlags.MatchCase : SearchFlags.None; + if(options.WholeWord) scriptedit.SearchFlags |= SearchFlags.WholeWord; + + int result = scriptedit.SearchInTarget(options.FindText); + + // Wrap around? + if(result == -1) + { + scriptedit.TargetStart = 0; + scriptedit.TargetEnd = startpos; + result = scriptedit.SearchInTarget(options.FindText); + } + + // Found something + if(result != -1) + { + // Select the result + SelectAndShow(result, result + options.FindText.Length); + + // Update extra highlights + HighlightWord(options.FindText); + + // All done + return true; + } + + // Nothing found... + return false; + } + + //mxd. Find previous result + public bool FindPrevious(FindReplaceOptions options) + { + int endpos = Math.Max(0, Math.Min(scriptedit.SelectionStart, scriptedit.SelectionEnd) - 1); + + // Search the document + scriptedit.TargetStart = endpos; + scriptedit.TargetEnd = 0; + scriptedit.SearchFlags = options.CaseSensitive ? SearchFlags.MatchCase : SearchFlags.None; + if(options.WholeWord) scriptedit.SearchFlags |= SearchFlags.WholeWord; + + int result = scriptedit.SearchInTarget(options.FindText); + + // Wrap around? + if(result == -1) + { + scriptedit.TargetStart = scriptedit.TextLength; + scriptedit.TargetEnd = endpos; + result = scriptedit.SearchInTarget(options.FindText); + } + + // Found something + if(result != -1) + { + // Select the result + SelectAndShow(result, result + options.FindText.Length); + + // Update extra highlights + HighlightWord(options.FindText); + + // All done + return true; + } + + // Nothing found... + return false; + } + + //mxd. (Un)indents selection + public void IndentSelection(bool indent) + { + // Get selected range of lines + int startline = scriptedit.LineFromPosition(scriptedit.SelectionStart); + int endline = scriptedit.LineFromPosition(scriptedit.SelectionEnd); + + for(int i = startline; i < endline + 1; i++) + { + scriptedit.Lines[i].Indentation += (indent ? General.Settings.ScriptTabWidth : -General.Settings.ScriptTabWidth); + } + } + + #endregion + + #region ================== Utility methods + + // This returns the ScriptStyleType for a given Scintilla style + private ScriptStyleType GetScriptStyle(int scintillastyle) + { + return (stylelookup.ContainsKey(scintillastyle) ? stylelookup[scintillastyle] : ScriptStyleType.PlainText); + } + + // This gathers information about the current caret position + private void UpdatePositionInfo() + { + int bracketlevel = 0; // bracket level counting + int argindex = 0; // function argument counting + int pos = scriptedit.CurrentPosition; + + // Get the text + string scripttext = scriptedit.Text; + + // Reset position info + curfunctionname = ""; + curargumentindex = 0; + curfunctionstartpos = 0; + + // Determine lowest backtrack position + int limitpos = scriptedit.CurrentPosition - MAX_BACKTRACK_LENGTH; + if(limitpos < 0) limitpos = 0; + + // We can only do this when we have function syntax information + if((scriptconfig.ArgumentDelimiter.Length == 0) || (scriptconfig.FunctionClose.Length == 0) || + (scriptconfig.FunctionOpen.Length == 0) || (scriptconfig.Terminator.Length == 0)) return; + + // Get int versions of the function syntax informantion + int argumentdelimiter = scriptconfig.ArgumentDelimiter[0]; + int functionclose = scriptconfig.FunctionClose[0]; + int functionopen = scriptconfig.FunctionOpen[0]; + int terminator = scriptconfig.Terminator[0]; + + // Continue backtracking until we reached the limitpos + while(pos >= limitpos) + { + // Backtrack 1 character + pos--; + + // Get the style and character at this position + ScriptStyleType curstyle = GetScriptStyle(scriptedit.GetStyleAt(pos)); + int curchar = scriptedit.GetCharAt(pos); + + // Then meeting ) then increase bracket level + // When meeting ( then decrease bracket level + // When bracket level goes -1, then the next word should be the function name + // Only when at bracket level 0, count the comma's for argument index + + // TODO: + // Original code checked for scope character here and breaks if found + + // Check if in plain text or keyword + if((curstyle == ScriptStyleType.PlainText) || (curstyle == ScriptStyleType.Keyword)) + { + // Closing bracket + if(curchar == functionclose) + { + bracketlevel++; + } + // Opening bracket + else if(curchar == functionopen) + { + bracketlevel--; + + // Out of the brackets? + if(bracketlevel < 0) + { + // Skip any whitespace before this bracket + do + { + // Backtrack 1 character + curchar = scriptedit.GetCharAt(--pos); + } + while((pos >= limitpos) && ((curchar == ' ') || (curchar == '\t') || + (curchar == '\r') || (curchar == '\n'))); + + // NOTE: We may need to set onlyWordCharacters argument in the + // following calls to false to get any argument delimiter included, + // but this may also cause a valid keyword to be combined with other + // surrounding characters that do not belong to the keyword. + + // Find the word before this bracket + int wordstart = scriptedit.WordStartPosition(pos, true); + int wordend = scriptedit.WordEndPosition(pos, true); + string word = scripttext.Substring(wordstart, wordend - wordstart); + if(word.Length > 0) + { + // Check if this is an argument delimiter + // I can't remember why I did this, but I'll probably stumble + // upon the problem if this doesn't work right (see note above) + if(word[0] == argumentdelimiter) + { + // We are now in the parent function + bracketlevel++; + argindex = 0; + } + // Now check if this is a keyword + else if(scriptconfig.IsKeyword(word)) + { + // Found it! + curfunctionname = scriptconfig.GetKeywordCase(word); + curargumentindex = argindex; + curfunctionstartpos = wordstart; + break; + } + else + { + // Don't know this word + break; + } + } + } + } + // Argument delimiter + else if(curchar == argumentdelimiter) + { + // Only count these at brackt level 0 + if(bracketlevel == 0) argindex++; + } + // Terminator + else if(curchar == terminator) + { + // Can't find anything, break now + break; + } + } + } + } + + // This registers an image for the autocomplete list + private void RegisterAutoCompleteImage(ImageIndex index, Bitmap image) + { + // Register image + scriptedit.RegisterRgbaImage((int)index, image); + } + + // This registers an image for the markes list + private void RegisterMarkerImage(ImageIndex index, Bitmap image) + { + // Register image + scriptedit.Markers[(int)index].DefineRgbaImage(image); + scriptedit.Markers[(int)index].Symbol = MarkerSymbol.RgbaImage; + } + + //mxd. This converts [LB] markers to line breaks if necessary + private static string[] ProcessLineBreaks(string[] lines) + { + List result = new List(lines.Length); + string[] separator = new[] { "[LB]" }; + + foreach(string line in lines) + { + if(line.IndexOf(separator[0], StringComparison.Ordinal) != -1) + { + if(General.Settings.ScriptAllmanStyle) + result.AddRange(line.Split(separator, StringSplitOptions.RemoveEmptyEntries)); + else + result.Add(line.Replace(separator[0], " ")); + } + else + { + result.Add(line); + } + } + + return result.ToArray(); + } + + //mxd. Autocompletion handling (https://github.com/jacobslusser/ScintillaNET/wiki/Basic-Autocompletion) + private bool ShowAutoCompletionList() + { + int currentpos = scriptedit.CurrentPosition; + int wordstartpos = scriptedit.WordStartPosition(currentpos, true); + + if(wordstartpos >= currentpos) + { + // Hide the list + scriptedit.AutoCCancel(); + return false; + } + + // Get entered text + string start = scriptedit.GetTextRange(wordstartpos, currentpos - wordstartpos); + if(string.IsNullOrEmpty(start)) + { + // Hide the list + scriptedit.AutoCCancel(); + return false; + } + + // Don't show Auto-completion list when editing comment, include or string + switch(GetScriptStyle(scriptedit.GetStyleAt(currentpos))) + { + case ScriptStyleType.Comment: + case ScriptStyleType.String: + case ScriptStyleType.Include: + // Hide the list + scriptedit.AutoCCancel(); + return false; + } + + // Filter the list + List filtered = new List(); + foreach(string s in autocompletelist) + if(s.IndexOf(start, StringComparison.OrdinalIgnoreCase) != -1) filtered.Add(s); + + // Any matches? + if(filtered.Count > 0) + { + // Show the list + scriptedit.AutoCShow(currentpos - wordstartpos, string.Join(" ", filtered.ToArray())); + return true; + } + + // Hide the list + scriptedit.AutoCCancel(); + return false; + } + + //mxd + private string GetIndentationString(int indent) + { + if(scriptedit.UseTabs) + { + string indentstr = string.Empty; + int numtabs = indent / scriptedit.TabWidth; + if(numtabs > 0) indentstr = new string('\t', numtabs); + + // Mixed padding? Add spaces + if(numtabs * scriptedit.TabWidth < indent) + { + int numspaces = indent - numtabs * scriptedit.TabWidth; + indentstr += new string(' ', numspaces); + } + + return indentstr; + } + else + { + return new string(' ', indent); + } + } + + //mxd. https://github.com/jacobslusser/ScintillaNET/wiki/Find-and-Highlight-Words + private void HighlightWord(string text) + { + // Remove all uses of our indicator + scriptedit.IndicatorCurrent = HIGHLIGHT_INDICATOR; + scriptedit.IndicatorClearRange(0, scriptedit.TextLength); + + // Update indicator appearance + scriptedit.Indicators[HIGHLIGHT_INDICATOR].Style = IndicatorStyle.RoundBox; + scriptedit.Indicators[HIGHLIGHT_INDICATOR].Under = true; + scriptedit.Indicators[HIGHLIGHT_INDICATOR].ForeColor = General.Colors.ScriptIndicator.ToColor(); + scriptedit.Indicators[HIGHLIGHT_INDICATOR].OutlineAlpha = 50; + scriptedit.Indicators[HIGHLIGHT_INDICATOR].Alpha = 30; + + // Search the document + scriptedit.TargetStart = 0; + scriptedit.TargetEnd = scriptedit.TextLength; + scriptedit.SearchFlags = SearchFlags.WholeWord; + + while(scriptedit.SearchInTarget(text) != -1) + { + //mxd. Don't mark currently selected word + if(scriptedit.SelectionStart != scriptedit.TargetStart && scriptedit.SelectionEnd != scriptedit.TargetEnd) + { + // Mark the search results with the current indicator + scriptedit.IndicatorFillRange(scriptedit.TargetStart, scriptedit.TargetEnd - scriptedit.TargetStart); + } + + // Search the remainder of the document + scriptedit.TargetStart = scriptedit.TargetEnd; + scriptedit.TargetEnd = scriptedit.TextLength; + } + } + + #endregion + + #region ================== Events + + // Layout needs to be re-organized + protected override void OnLayout(LayoutEventArgs e) + { + base.OnLayout(e); + + // With or without functions bar? + if(functionbar.Visible) + { + scriptpanel.Top = functionbar.Bottom + 6; + scriptpanel.Height = this.ClientSize.Height - scriptpanel.Top; + } + else + { + scriptpanel.Top = 0; + scriptpanel.Height = this.ClientSize.Height; + } + } + + //mxd. Script text changed + private void scriptedit_TextChanged(object sender, EventArgs e) + { + // Line number margin width needs changing? + int curlinenumbercharlength = scriptedit.Lines.Count.ToString().Length; + + // Calculate the width required to display the last line number + // and include some padding for good measure. + if(curlinenumbercharlength != linenumbercharlength) + { + const int padding = 2; + scriptedit.Margins[1].Width = scriptedit.TextWidth(Style.LineNumber, new string('9', curlinenumbercharlength + 1)) + padding; + linenumbercharlength = curlinenumbercharlength; + } + + if(OnTextChanged != null) OnTextChanged(this, EventArgs.Empty); + } + + //mxd + private void scriptedit_CharAdded(object sender, CharAddedEventArgs e) + { + // Hide call tip if any + scriptedit.CallTipCancel(); + + // Offset caret if needed + if(caretoffset != 0) + { + scriptedit.SetEmptySelection(scriptedit.SelectionStart + caretoffset); + caretoffset = 0; + if(!expandcodeblock) return; + } + + // Move CodeBlockOpen to the new line? + if(expandcodeblock) + { + if(scriptedit.CurrentLine > 0) + { + string linetext = scriptedit.Lines[scriptedit.CurrentLine - 1].Text; + int blockopenpos = (string.IsNullOrEmpty(scriptconfig.CodeBlockOpen) ? -1 : linetext.LastIndexOf(scriptconfig.CodeBlockOpen, StringComparison.Ordinal)); + if(blockopenpos != -1) + { + // Do it only if initial line doesn't start with CodeBlockOpen + string linestart = linetext.Substring(0, blockopenpos).Trim(); + if(linestart.Length > 0) + { + scriptedit.InsertText(scriptedit.Lines[scriptedit.CurrentLine - 1].Position + blockopenpos, + Environment.NewLine + GetIndentationString(scriptedit.Lines[scriptedit.CurrentLine - 1].Indentation)); + } + } + } + + expandcodeblock = false; + return; + } + + // Auto-match braces + if(General.Settings.ScriptAutoCloseBrackets) + { + //TODO: Auto-match quotes + bool endpos = (scriptedit.CurrentPosition == scriptedit.TextLength); + if(!string.IsNullOrEmpty(scriptconfig.CodeBlockOpen) && e.Char == scriptconfig.CodeBlockOpen[0] && !string.IsNullOrEmpty(scriptconfig.CodeBlockClose) && + (endpos || (char)scriptedit.GetCharAt(scriptedit.CurrentPosition + 1) != scriptconfig.CodeBlockClose[0])) + { + scriptedit.InsertText(scriptedit.CurrentPosition, scriptconfig.CodeBlockClose); + return; + } + + if(!string.IsNullOrEmpty(scriptconfig.FunctionOpen) && e.Char == scriptconfig.FunctionOpen[0] && !string.IsNullOrEmpty(scriptconfig.FunctionClose) && + (endpos || (char)scriptedit.GetCharAt(scriptedit.CurrentPosition + 1) != scriptconfig.FunctionClose[0])) + { + scriptedit.InsertText(scriptedit.CurrentPosition, scriptconfig.FunctionClose); + return; + } + + if(!string.IsNullOrEmpty(scriptconfig.ArrayOpen) && e.Char == scriptconfig.ArrayOpen[0] && !string.IsNullOrEmpty(scriptconfig.ArrayClose) && + (endpos || (char)scriptedit.GetCharAt(scriptedit.CurrentPosition + 1) != scriptconfig.ArrayClose[0])) + { + scriptedit.InsertText(scriptedit.CurrentPosition, scriptconfig.ArrayClose); + return; + } + } + + if(General.Settings.ScriptAutoShowAutocompletion) + { + // Display the autocompletion list + ShowAutoCompletionList(); + } + } + + //mxd + private void scriptedit_UpdateUI(object sender, UpdateUIEventArgs e) + { + // If a word is selected, highlight the same words + if(scriptedit.SelectedText != highlightedword) + { + // Highlight only when whole word is selected + if(!string.IsNullOrEmpty(scriptedit.SelectedText) && scriptedit.GetWordFromPosition(scriptedit.SelectionStart) == scriptedit.SelectedText) + { + HighlightWord(scriptedit.SelectedText); + } + else + { + // Clear highlight + scriptedit.IndicatorCurrent = HIGHLIGHT_INDICATOR; + scriptedit.IndicatorClearRange(0, scriptedit.TextLength); + } + + highlightedword = scriptedit.SelectedText; + } + + // Has the caret changed position? + int caretpos = scriptedit.CurrentPosition; + if(lastcaretpos != caretpos && scriptconfig.BraceChars.Count > 0) + { + // Perform brace matching (https://github.com/jacobslusser/ScintillaNET/wiki/Brace-Matching) + lastcaretpos = caretpos; + int bracepos1 = -1; + + // Is there a brace to the left or right? + if(caretpos > 0 && scriptconfig.BraceChars.Contains((char)scriptedit.GetCharAt(caretpos - 1))) + bracepos1 = (caretpos - 1); + else if(scriptconfig.BraceChars.Contains((char)(scriptedit.GetCharAt(caretpos)))) + bracepos1 = caretpos; + + if(bracepos1 > -1) + { + // Find the matching brace + int bracepos2 = scriptedit.BraceMatch(bracepos1); + if(bracepos2 == Scintilla.InvalidPosition) + scriptedit.BraceBadLight(bracepos1); + else + scriptedit.BraceHighlight(bracepos1, bracepos2); + } + else + { + // Turn off brace matching + scriptedit.BraceHighlight(Scintilla.InvalidPosition, Scintilla.InvalidPosition); + } + } + } + + //mxd + private void scriptedit_InsertCheck(object sender, InsertCheckEventArgs e) + { + // Gross hacks... + if(skiptextinsert) + { + e.Text = string.Empty; + skiptextinsert = false; + } + // Do we want auto-indentation? + else if(!expandcodeblock && General.Settings.ScriptAutoIndent && e.Text == "\r\n") + { + // Get current line indentation up to the cursor position + string linetext = scriptedit.Lines[scriptedit.CurrentLine].Text; + int selectionpos = scriptedit.SelectionStart - scriptedit.Lines[scriptedit.CurrentLine].Position; + int indent = 0; + for(int i = 0; i < selectionpos; i++) + { + switch(linetext[i]) + { + case ' ': indent++; break; + case '\t': indent += scriptedit.TabWidth; break; + default: i = selectionpos; break; // break the loop + } + } + + // Store initial indentation + int initialindent = indent; + + // Need to increase indentation? We do this when: + // 1. Line contains '{' and '}' and the cursor is between them + // 2. Line either doesn't contain '}', or it's before '{', or the line contains '{' and the cursor is after it + int blockopenpos = (string.IsNullOrEmpty(scriptconfig.CodeBlockOpen) ? -1 : linetext.LastIndexOf(scriptconfig.CodeBlockOpen, selectionpos, StringComparison.Ordinal)); + int blockclosepos = (string.IsNullOrEmpty(scriptconfig.CodeBlockOpen) ? -1 : linetext.IndexOf(scriptconfig.CodeBlockClose, selectionpos, StringComparison.Ordinal)); + + // Add indentation when the cursor is between { and } + bool addindent = (blockopenpos != -1 && blockopenpos < selectionpos) && (blockclosepos == -1 || (blockopenpos < blockclosepos && blockclosepos >= selectionpos)); + if(addindent) indent += scriptedit.TabWidth; + + // Calculate indentation + string indentstr = GetIndentationString(indent); + + // Move CodeBlockOpen to the new line? (will be applied in scriptedit_CharAdded) + expandcodeblock = General.Settings.ScriptAllmanStyle; + + // Offset closing block char? + if(addindent && blockclosepos != -1) + { + string initialindentstr = GetIndentationString(initialindent); + indentstr += Environment.NewLine + initialindentstr; + + // Offset cursor position (will be performed in scriptedit_CharAdded) + caretoffset = -(initialindentstr.Length + Environment.NewLine.Length); + } + + // Apply new indentation + e.Text += indentstr; + } + } + + //mxd + private void scriptedit_AutoCCompleted(object sender, AutoCSelectionEventArgs e) + { + // Expand snippet? + string[] lines = scriptconfig.GetSnippet(e.Text); + if(lines != null) InsertSnippet(lines); + } + + // Key pressed down + private void scriptedit_KeyDown(object sender, KeyEventArgs e) + { + // F3 for Find Next + if((e.KeyCode == Keys.F3) && (e.Modifiers == Keys.None)) + { + if(OnFindNext != null) OnFindNext(); + } + // F2 for Find Previous (mxd) + else if((e.KeyCode == Keys.F2) && (e.Modifiers == Keys.None)) + { + if(OnFindPrevious != null) OnFindPrevious(); + } + // CTRL+F for find & replace + else if((e.KeyCode == Keys.F) && ((e.Modifiers & Keys.Control) == Keys.Control)) + { + if(OnOpenFindAndReplace != null) OnOpenFindAndReplace(); + } + // CTRL+S for save + else if((e.KeyCode == Keys.S) && ((e.Modifiers & Keys.Control) == Keys.Control)) + { + if(OnExplicitSaveTab != null) OnExplicitSaveTab(); + } + // CTRL+O for open + else if((e.KeyCode == Keys.O) && ((e.Modifiers & Keys.Control) == Keys.Control)) + { + if(OnOpenScriptBrowser != null) OnOpenScriptBrowser(); + } + // CTRL+Space to autocomplete + else if((e.KeyCode == Keys.Space) && (e.Modifiers == Keys.Control)) + { + // Hide call tip if any + scriptedit.CallTipCancel(); + + // Show autocomplete + if(ShowAutoCompletionList()) skiptextinsert = true; + } + //mxd. Tab to expand code snippet. Do it only when the text cursor is at the end of a keyword. + else if(e.KeyCode == Keys.Tab) + { + if(!scriptedit.AutoCActive) + { + string curword = GetCurrentWord().ToLowerInvariant(); + if(scriptconfig.Snippets.Contains(curword) && scriptedit.CurrentPosition == scriptedit.WordEndPosition(scriptedit.CurrentPosition, true)) + { + InsertSnippet(scriptconfig.GetSnippet(curword)); + skiptextinsert = true; + } + } + } + else + { + //mxd. Skip text insert when "save screenshot" action's keys are pressed + Actions.Action[] actions = General.Actions.GetActionsByKey((int)e.KeyData); + foreach(Actions.Action action in actions) + { + if(action.ShortName == "savescreenshot" || action.ShortName == "saveeditareascreenshot") + { + skiptextinsert = true; + return; + } + } + } + } + + // Key released + private void scriptedit_KeyUp(object sender, KeyEventArgs e) + { + bool showcalltip = false; + int highlightstart = 0; + int highlightend = 0; + + UpdatePositionInfo(); + + // Call tip shown + if(scriptedit.CallTipActive) + { + // Should we hide the call tip? + if(curfunctionname.Length == 0) + { + // Hide the call tip + scriptedit.CallTipCancel(); + } + else + { + // Update the call tip + showcalltip = true; + } + } + // No call tip + else + { + // Should we show a call tip? + showcalltip = (curfunctionname.Length > 0) && !scriptedit.AutoCActive; + } + + // Show or update call tip + if(showcalltip) + { + string functiondef = scriptconfig.GetFunctionDefinition(curfunctionname); + if(functiondef != null) + { + // Determine the range to highlight + int argsopenpos = functiondef.IndexOf(scriptconfig.FunctionOpen, StringComparison.Ordinal); + int argsclosepos = functiondef.LastIndexOf(scriptconfig.FunctionClose, StringComparison.Ordinal); + if((argsopenpos > -1) && (argsclosepos > -1)) + { + string argsstr = functiondef.Substring(argsopenpos + 1, argsclosepos - argsopenpos - 1); + string[] args = argsstr.Split(scriptconfig.ArgumentDelimiter[0]); + if((curargumentindex >= 0) && (curargumentindex < args.Length)) + { + int argoffset = 0; + for(int i = 0; i < curargumentindex; i++) argoffset += args[i].Length + 1; + highlightstart = argsopenpos + argoffset + 1; + highlightend = highlightstart + args[curargumentindex].Length; + } + } + + //mxd. If the tip obscures the view, move it down + int tippos; + int funcline = scriptedit.LineFromPosition(curfunctionstartpos); + if(scriptedit.CurrentLine > funcline) + tippos = scriptedit.Lines[scriptedit.CurrentLine].Position + scriptedit.Lines[scriptedit.CurrentLine].Indentation; //scriptedit.PositionFromLine(curline) /*+ (curfunctionstartpos - scriptedit.PositionFromLine(funcline))*/; + else + tippos = curfunctionstartpos; + + // Show tip + scriptedit.CallTipShow(tippos, functiondef); + scriptedit.CallTipSetHlt(highlightstart, highlightend); + } + } + } + + #endregion + } +} diff --git a/Source/Core/Controls/ScriptFileDocumentTab.cs b/Source/Core/Controls/ScriptFileDocumentTab.cs index 98b2cc1..8978b07 100644 --- a/Source/Core/Controls/ScriptFileDocumentTab.cs +++ b/Source/Core/Controls/ScriptFileDocumentTab.cs @@ -61,15 +61,15 @@ namespace CodeImp.DoomBuilder.Controls if(config.Extensions.Length > 0) ext = "." + config.Extensions[0]; SetTitle("Untitled" + ext); editor.ClearUndoRedo(); - editor.FunctionBar.Enabled = (config.ScriptType != ScriptType.UNKNOWN); //mxd - } - - #endregion - - #region ================== Methods - - // This compiles the script file - public override void Compile() + editor.FunctionBar.Enabled = (config.ScriptType != ScriptType.UNKNOWN); //mxd + } + + #endregion + + #region ================== Methods + + // This compiles the script file + public override void Compile() { //mxd. ACS requires special handling... if(config.ScriptType == ScriptType.ACS) @@ -126,8 +126,8 @@ namespace CodeImp.DoomBuilder.Controls // Dispose compiler compiler.Dispose(); - //mxd. Update script navigator - UpdateNavigator(); + //mxd. Update script navigator + UpdateNavigator(); // Feed errors to panel panel.ShowErrors(errors); @@ -147,7 +147,7 @@ namespace CodeImp.DoomBuilder.Controls // Boilderplate if(!General.CompiledScriptConfigs.ContainsKey(General.Map.Options.ScriptCompiler)) { - General.ShowErrorMessage("Unable to compile '" + inputfile + "'. Unable to find required script compiler configuration ('" + General.Map.Options.ScriptCompiler + "').", MessageBoxButtons.OK); + General.ShowErrorMessage("Unable to compile \"" + inputfile + "\". Unable to find required script compiler configuration (\"" + General.Map.Options.ScriptCompiler + "\").", MessageBoxButtons.OK); return; } @@ -232,7 +232,7 @@ namespace CodeImp.DoomBuilder.Controls { // Fail compiler.Dispose(); - errors.Add(new CompilerError("Output file '" + outputfile + "' doesn't exist.")); + errors.Add(new CompilerError("Output file \"" + outputfile + "\" doesn't exist.")); panel.ShowErrors(errors); return; } @@ -247,7 +247,7 @@ namespace CodeImp.DoomBuilder.Controls { // Fail compiler.Dispose(); - errors.Add(new CompilerError("Unable to create library file '" + targetfilename + "'. " + e.GetType().Name + ": " + e.Message)); + errors.Add(new CompilerError("Unable to create library file \"" + targetfilename + "\". " + e.GetType().Name + ": " + e.Message)); panel.ShowErrors(errors); return; } @@ -257,8 +257,8 @@ namespace CodeImp.DoomBuilder.Controls // Dispose compiler compiler.Dispose(); - // Update script navigator - UpdateNavigator(); + // Update script navigator + UpdateNavigator(); // Feed errors to panel panel.ShowErrors(errors); @@ -282,16 +282,16 @@ namespace CodeImp.DoomBuilder.Controls catch(Exception e) { // Failed - General.ErrorLogger.Add(ErrorType.Error, "Cannot open file '" + filepathname + "' for writing. Make sure the path exists and that the file is not in use by another application."); + General.ErrorLogger.Add(ErrorType.Error, "Cannot open file \"" + filepathname + "\" for writing. Make sure the path exists and that the file is not in use by another application."); General.WriteLogLine(e.GetType().Name + ": " + e.Message); General.ShowErrorMessage("Unable to open file \"" + filepathname + "\" for writing. Make sure the path exists and that the file is not in use by another application.", MessageBoxButtons.OK); return false; } - - // Done - editor.SetSavePoint(); //mxd - UpdateTitle(); //mxd - return true; + + // Done + editor.SetSavePoint(); //mxd + UpdateTitle(); //mxd + return true; } // This saves the document to a new file @@ -317,14 +317,13 @@ namespace CodeImp.DoomBuilder.Controls { try { - // Read the file - editor.Text = File.ReadAllText(filepathname); //mxd - } - - catch (Exception e) + // Read the file + editor.Text = File.ReadAllText(filepathname); //mxd + } + catch(Exception e) { // Failed - General.ErrorLogger.Add(ErrorType.Error, "Cannot open file '" + filepathname + "' for reading. Make sure the path exists and that the file is not in use by another application."); + General.ErrorLogger.Add(ErrorType.Error, "Cannot open file \"" + filepathname + "\" for reading. Make sure the path exists and that the file is not in use by another application."); General.WriteLogLine(e.GetType().Name + ": " + e.Message); General.ShowErrorMessage("Unable to open file \"" + filepathname + "\" for reading. Make sure the path exists and that the file is not in use by another application.", MessageBoxButtons.OK); return false; diff --git a/Source/Core/Controls/StatisticsControl.Designer.cs b/Source/Core/Controls/StatisticsControl.Designer.cs index 9ade8ee..387d174 100644 --- a/Source/Core/Controls/StatisticsControl.Designer.cs +++ b/Source/Core/Controls/StatisticsControl.Designer.cs @@ -45,7 +45,7 @@ this.thingscount.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(204))); this.thingscount.Location = new System.Drawing.Point(10, 81); this.thingscount.Name = "thingscount"; - this.thingscount.Size = new System.Drawing.Size(43, 14); + this.thingscount.Size = new System.Drawing.Size(63, 14); this.thingscount.TabIndex = 19; this.thingscount.Text = "0"; this.thingscount.TextAlign = System.Drawing.ContentAlignment.TopRight; @@ -55,7 +55,7 @@ this.sectorscount.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(204))); this.sectorscount.Location = new System.Drawing.Point(10, 62); this.sectorscount.Name = "sectorscount"; - this.sectorscount.Size = new System.Drawing.Size(43, 14); + this.sectorscount.Size = new System.Drawing.Size(63, 14); this.sectorscount.TabIndex = 18; this.sectorscount.Text = "0"; this.sectorscount.TextAlign = System.Drawing.ContentAlignment.TopRight; @@ -65,7 +65,7 @@ this.sidedefscount.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(204))); this.sidedefscount.Location = new System.Drawing.Point(10, 44); this.sidedefscount.Name = "sidedefscount"; - this.sidedefscount.Size = new System.Drawing.Size(43, 14); + this.sidedefscount.Size = new System.Drawing.Size(63, 14); this.sidedefscount.TabIndex = 17; this.sidedefscount.Text = "0"; this.sidedefscount.TextAlign = System.Drawing.ContentAlignment.TopRight; @@ -75,7 +75,7 @@ this.linedefscount.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(204))); this.linedefscount.Location = new System.Drawing.Point(10, 26); this.linedefscount.Name = "linedefscount"; - this.linedefscount.Size = new System.Drawing.Size(43, 14); + this.linedefscount.Size = new System.Drawing.Size(63, 14); this.linedefscount.TabIndex = 16; this.linedefscount.Text = "0"; this.linedefscount.TextAlign = System.Drawing.ContentAlignment.TopRight; @@ -85,7 +85,7 @@ this.verticescount.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(204))); this.verticescount.Location = new System.Drawing.Point(10, 8); this.verticescount.Name = "verticescount"; - this.verticescount.Size = new System.Drawing.Size(43, 14); + this.verticescount.Size = new System.Drawing.Size(63, 14); this.verticescount.TabIndex = 15; this.verticescount.Text = "0"; this.verticescount.TextAlign = System.Drawing.ContentAlignment.TopRight; @@ -93,7 +93,7 @@ // thingslabel // this.thingslabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(204))); - this.thingslabel.Location = new System.Drawing.Point(55, 81); + this.thingslabel.Location = new System.Drawing.Point(75, 81); this.thingslabel.Name = "thingslabel"; this.thingslabel.Size = new System.Drawing.Size(60, 15); this.thingslabel.TabIndex = 14; @@ -102,7 +102,7 @@ // sectorslabel // this.sectorslabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(204))); - this.sectorslabel.Location = new System.Drawing.Point(55, 62); + this.sectorslabel.Location = new System.Drawing.Point(75, 62); this.sectorslabel.Name = "sectorslabel"; this.sectorslabel.Size = new System.Drawing.Size(60, 15); this.sectorslabel.TabIndex = 13; @@ -111,7 +111,7 @@ // sidedefslabel // this.sidedefslabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(204))); - this.sidedefslabel.Location = new System.Drawing.Point(55, 44); + this.sidedefslabel.Location = new System.Drawing.Point(75, 44); this.sidedefslabel.Name = "sidedefslabel"; this.sidedefslabel.Size = new System.Drawing.Size(60, 15); this.sidedefslabel.TabIndex = 12; @@ -120,7 +120,7 @@ // linedefslabel // this.linedefslabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(204))); - this.linedefslabel.Location = new System.Drawing.Point(55, 26); + this.linedefslabel.Location = new System.Drawing.Point(75, 26); this.linedefslabel.Name = "linedefslabel"; this.linedefslabel.Size = new System.Drawing.Size(60, 15); this.linedefslabel.TabIndex = 11; @@ -129,7 +129,7 @@ // verticeslabel // this.verticeslabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(204))); - this.verticeslabel.Location = new System.Drawing.Point(55, 8); + this.verticeslabel.Location = new System.Drawing.Point(75, 8); this.verticeslabel.Name = "verticeslabel"; this.verticeslabel.Size = new System.Drawing.Size(60, 15); this.verticeslabel.TabIndex = 10; @@ -151,7 +151,7 @@ this.Controls.Add(this.verticeslabel); this.ForeColor = System.Drawing.SystemColors.GrayText; this.Name = "StatisticsControl"; - this.Size = new System.Drawing.Size(118, 104); + this.Size = new System.Drawing.Size(138, 104); this.ResumeLayout(false); } diff --git a/Source/Core/Controls/TextureSelectorControl.cs b/Source/Core/Controls/TextureSelectorControl.cs index 0410e3f..4df91dd 100644 --- a/Source/Core/Controls/TextureSelectorControl.cs +++ b/Source/Core/Controls/TextureSelectorControl.cs @@ -74,10 +74,12 @@ namespace CodeImp.DoomBuilder.Controls if(string.IsNullOrEmpty(texture.FilePathName) || texture is UnknownImage) DisplayImageSize(0, 0); //mxd else DisplayImageSize(texture.ScaledWidth, texture.ScaledHeight); //mxd - if(usepreviews ? !texture.IsPreviewLoaded : !texture.IsImageLoaded) timer.Start(); //mxd - + + if(usepreviews && !texture.IsPreviewLoaded) timer.Start(); //mxd + else if(!texture.IsImageLoaded) texture.LoadImage(); //mxd. In some cases the image may never me loaded by the DataManager + // Set the image - return (usepreviews ? texture.GetPreview() : texture.GetBitmap()); + return new Bitmap((usepreviews ? texture.GetPreview() : texture.GetBitmap())); } } diff --git a/Source/Core/Controls/ThingBrowserControl.cs b/Source/Core/Controls/ThingBrowserControl.cs index d010904..be0ffae 100644 --- a/Source/Core/Controls/ThingBrowserControl.cs +++ b/Source/Core/Controls/ThingBrowserControl.cs @@ -495,14 +495,25 @@ namespace CodeImp.DoomBuilder.Controls validnodes.Clear(); string match = tbFilter.Text.ToUpperInvariant(); + HashSet added = new HashSet(StringComparer.OrdinalIgnoreCase); + + // First add nodes, which titles start with given text foreach(TreeNode node in nodes) { - if(node.Text.ToUpperInvariant().Contains(match)) + if(node.Text.ToUpperInvariant().StartsWith(match)) { typelist.Nodes.Add(node); + added.Add(node.Text); } } + // Then add nodes, which titles contain given text + foreach(TreeNode node in nodes) + { + if(!added.Contains(node.Text) && node.Text.ToUpperInvariant().Contains(match)) + typelist.Nodes.Add(node); + } + doupdatenode = true; doupdatetextbox = true; } diff --git a/Source/Core/Data/ColormapImage.cs b/Source/Core/Data/ColormapImage.cs index 487c483..6f05638 100644 --- a/Source/Core/Data/ColormapImage.cs +++ b/Source/Core/Data/ColormapImage.cs @@ -67,7 +67,7 @@ namespace CodeImp.DoomBuilder.Data if(reader is UnknownImageReader) { // Data is in an unknown format! - General.ErrorLogger.Add(ErrorType.Error, "Colormap lump '" + Name + "' data format could not be read. Does this lump contain valid colormap data at all?"); + General.ErrorLogger.Add(ErrorType.Error, "Colormap lump \"" + Name + "\" data format could not be read. Does this lump contain valid colormap data at all?"); bitmap = null; } else @@ -97,7 +97,7 @@ namespace CodeImp.DoomBuilder.Data else { // Missing a patch lump! - General.ErrorLogger.Add(ErrorType.Error, "Missing colormap lump '" + Name + "'. Did you forget to include required resources?"); + General.ErrorLogger.Add(ErrorType.Error, "Missing colormap lump \"" + Name + "\". Did you forget to include required resources?"); loadfailed = true; } diff --git a/Source/Core/Data/DataLocation.cs b/Source/Core/Data/DataLocation.cs index c12df73..1bc1c4c 100644 --- a/Source/Core/Data/DataLocation.cs +++ b/Source/Core/Data/DataLocation.cs @@ -79,8 +79,8 @@ namespace CodeImp.DoomBuilder.Data } } - return name; - } + return (name ?? string.Empty); + } // This compares two locations public int CompareTo(DataLocation other) diff --git a/Source/Core/Data/FileImage.cs b/Source/Core/Data/FileImage.cs index adfefe4..2d99cfa 100644 --- a/Source/Core/Data/FileImage.cs +++ b/Source/Core/Data/FileImage.cs @@ -172,7 +172,7 @@ namespace CodeImp.DoomBuilder.Data // Not loaded? if(bitmap == null) { - General.ErrorLogger.Add(ErrorType.Error, "Image file '" + filepathname + "' data format could not be read, while loading image '" + this.Name + "'. Is this a valid picture file at all?"); + General.ErrorLogger.Add(ErrorType.Error, "Image file \"" + filepathname + "\" data format could not be read, while loading image \"" + this.Name + "\". Is this a valid picture file at all?"); loadfailed = true; } else diff --git a/Source/Core/Data/FlatImage.cs b/Source/Core/Data/FlatImage.cs index 578a6c8..b098a67 100644 --- a/Source/Core/Data/FlatImage.cs +++ b/Source/Core/Data/FlatImage.cs @@ -68,7 +68,7 @@ namespace CodeImp.DoomBuilder.Data if(reader is UnknownImageReader) { // Data is in an unknown format! - General.ErrorLogger.Add(ErrorType.Error, "Flat lump '" + Name + "' data format could not be read. Does this lump contain valid picture data at all?"); + General.ErrorLogger.Add(ErrorType.Error, "Flat lump \"" + Name + "\" data format could not be read. Does this lump contain valid picture data at all?"); bitmap = null; } else @@ -98,7 +98,7 @@ namespace CodeImp.DoomBuilder.Data else { // Missing a patch lump! - General.ErrorLogger.Add(ErrorType.Error, "Missing flat lump '" + Name + "'. Did you forget to include required resources?"); + General.ErrorLogger.Add(ErrorType.Error, "Missing flat lump \"" + Name + "\". Did you forget to include required resources?"); loadfailed = true; } diff --git a/Source/Core/Data/HighResImage.cs b/Source/Core/Data/HighResImage.cs index fb05881..9cb1a82 100644 --- a/Source/Core/Data/HighResImage.cs +++ b/Source/Core/Data/HighResImage.cs @@ -125,17 +125,26 @@ namespace CodeImp.DoomBuilder.Data catch(Exception e) { // Unable to make bitmap - General.ErrorLogger.Add(ErrorType.Error, "Unable to load texture image '" + this.Name + "'. " + e.GetType().Name + ": " + e.Message); + General.ErrorLogger.Add(ErrorType.Error, "Unable to load texture image \"" + this.Name + "\". " + e.GetType().Name + ": " + e.Message); loadfailed = true; } int missingpatches = 0; //mxd - if(!loadfailed) + if(patches.Count == 0) //mxd + { + // No patches! + General.ErrorLogger.Add(ErrorType.Warning, "No patches are defined for texture \"" + this.Name + "\""); + loadfailed = true; + } + else if(!loadfailed) { // Go for all patches foreach(TexturePatch p in patches) { + //mxd. Some patches (like "TNT1A0") should be skipped + if(p.skip) continue; + // Get the patch data stream Stream patchdata = General.Map.Data.GetPatchData(p.lumpname, p.haslongname); @@ -161,7 +170,7 @@ namespace CodeImp.DoomBuilder.Data if(reader is UnknownImageReader) { // Data is in an unknown format! - General.ErrorLogger.Add(ErrorType.Error, "Patch lump '" + p.lumpname + "' data format could not be read, while loading texture '" + this.Name + "'"); + General.ErrorLogger.Add(ErrorType.Error, "Patch lump \"" + p.lumpname + "\" data format could not be read, while loading texture \"" + this.Name + "\""); missingpatches++; //mxd } } @@ -175,7 +184,7 @@ namespace CodeImp.DoomBuilder.Data catch(InvalidDataException) { // Data cannot be read! - General.ErrorLogger.Add(ErrorType.Error, "Patch lump '" + p.lumpname + "' data format could not be read, while loading texture '" + this.Name + "'"); + General.ErrorLogger.Add(ErrorType.Error, "Patch lump \"" + p.lumpname + "\" data format could not be read, while loading texture \"" + this.Name + "\""); missingpatches++; //mxd } @@ -217,7 +226,7 @@ namespace CodeImp.DoomBuilder.Data } // Missing a patch lump! - General.ErrorLogger.Add(ErrorType.Error, "Missing patch lump '" + p.lumpname + "' while loading texture '" + this.Name + "'"); + General.ErrorLogger.Add(ErrorType.Error, "Missing patch lump \"" + p.lumpname + "\" while loading texture \"" + this.Name + "\""); missingpatches++; //mxd } } @@ -243,12 +252,9 @@ namespace CodeImp.DoomBuilder.Data if(p.flipx || p.flipy) { RotateFlipType flip; - if(p.flipx && !p.flipy) - flip = RotateFlipType.RotateNoneFlipX; - else if(!p.flipx && p.flipy) - flip = RotateFlipType.RotateNoneFlipY; - else - flip = RotateFlipType.RotateNoneFlipXY; + if(p.flipx && !p.flipy) flip = RotateFlipType.RotateNoneFlipX; + else if(!p.flipx && p.flipy) flip = RotateFlipType.RotateNoneFlipY; + else flip = RotateFlipType.RotateNoneFlipXY; patchbmp.RotateFlip(flip); } @@ -258,15 +264,9 @@ namespace CodeImp.DoomBuilder.Data RotateFlipType rotate; switch(p.rotate) { - case 90: - rotate = RotateFlipType.Rotate90FlipNone; - break; - case 180: - rotate = RotateFlipType.Rotate180FlipNone; - break; - default: - rotate = RotateFlipType.Rotate270FlipNone; - break; + case 90: rotate = RotateFlipType.Rotate90FlipNone; break; + case 180: rotate = RotateFlipType.Rotate180FlipNone; break; + default: rotate = RotateFlipType.Rotate270FlipNone; break; } patchbmp.RotateFlip(rotate); } @@ -282,7 +282,7 @@ namespace CodeImp.DoomBuilder.Data } catch(Exception e) { - General.ErrorLogger.Add(ErrorType.Error, "Cannot lock image '" + p.lumpname + "' for alpha adjustment. " + e.GetType().Name + ": " + e.Message); + General.ErrorLogger.Add(ErrorType.Error, "Cannot lock image \"" + p.lumpname + "\" for alpha adjustment. " + e.GetType().Name + ": " + e.Message); } if(bmpdata != null) @@ -347,7 +347,7 @@ namespace CodeImp.DoomBuilder.Data } catch(Exception e) { - General.ErrorLogger.Add(ErrorType.Error, "Cannot lock texture '" + this.Name + "' to apply render style. " + e.GetType().Name + ": " + e.Message); + General.ErrorLogger.Add(ErrorType.Error, "Cannot lock texture \"" + this.Name + "\" to apply render style. " + e.GetType().Name + ": " + e.Message); } if(texturebmpdata != null) diff --git a/Source/Core/Data/ImageData.cs b/Source/Core/Data/ImageData.cs index 8fc9610..fc89ce4 100644 --- a/Source/Core/Data/ImageData.cs +++ b/Source/Core/Data/ImageData.cs @@ -277,7 +277,7 @@ namespace CodeImp.DoomBuilder.Data catch(Exception e) { bitmap = oldbitmap; - General.ErrorLogger.Add(ErrorType.Warning, "Cannot lock image '" + name + "' for pixel format conversion. The image may not be displayed correctly.\n" + e.GetType().Name + ": " + e.Message); + General.ErrorLogger.Add(ErrorType.Warning, "Cannot lock image \"" + name + "\" for pixel format conversion. The image may not be displayed correctly.\n" + e.GetType().Name + ": " + e.Message); } } @@ -293,7 +293,7 @@ namespace CodeImp.DoomBuilder.Data } catch(Exception e) { - General.ErrorLogger.Add(ErrorType.Warning, "Cannot lock image '" + name + "' for color correction. The image may not be displayed correctly.\n" + e.GetType().Name + ": " + e.Message); + General.ErrorLogger.Add(ErrorType.Warning, "Cannot lock image \"" + name + "\" for color correction. The image may not be displayed correctly.\n" + e.GetType().Name + ": " + e.Message); } // Bitmap locked? @@ -348,7 +348,7 @@ namespace CodeImp.DoomBuilder.Data { BitmapData bmpdata = null; try { bmpdata = bitmap.LockBits(new Rectangle(0, 0, bitmap.Size.Width, bitmap.Size.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); } - catch(Exception e) { General.ErrorLogger.Add(ErrorType.Error, "Cannot lock image '" + this.filepathname + "' for glow color calculation. " + e.GetType().Name + ": " + e.Message); } + catch(Exception e) { General.ErrorLogger.Add(ErrorType.Error, "Cannot lock image \"" + this.filepathname + "\" for glow color calculation. " + e.GetType().Name + ": " + e.Message); } if(bmpdata != null) { @@ -403,7 +403,7 @@ namespace CodeImp.DoomBuilder.Data { BitmapData bmpdata = null; try { bmpdata = bitmap.LockBits(new Rectangle(0, 0, bitmap.Size.Width, bitmap.Size.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); } - catch(Exception e) { General.ErrorLogger.Add(ErrorType.Error, "Cannot lock image '" + this.filepathname + "' for translucency check. " + e.GetType().Name + ": " + e.Message); } + catch(Exception e) { General.ErrorLogger.Add(ErrorType.Error, "Cannot lock image \"" + this.filepathname + "\" for translucency check. " + e.GetType().Name + ": " + e.Message); } if(bmpdata != null) { diff --git a/Source/Core/Data/PK3FileImage.cs b/Source/Core/Data/PK3FileImage.cs index 33da887..4546fd2 100644 --- a/Source/Core/Data/PK3FileImage.cs +++ b/Source/Core/Data/PK3FileImage.cs @@ -140,7 +140,7 @@ namespace CodeImp.DoomBuilder.Data // Not loaded? if(bitmap == null) { - General.ErrorLogger.Add(ErrorType.Error, "Image file '" + filepathname + "' data format could not be read, while loading texture '" + this.Name + "'"); + General.ErrorLogger.Add(ErrorType.Error, "Image file \"" + filepathname + "\" data format could not be read, while loading texture \"" + this.Name + "\""); loadfailed = true; } else diff --git a/Source/Core/Data/SimpleTextureImage.cs b/Source/Core/Data/SimpleTextureImage.cs index eb79db4..7f74073 100644 --- a/Source/Core/Data/SimpleTextureImage.cs +++ b/Source/Core/Data/SimpleTextureImage.cs @@ -17,8 +17,8 @@ #region ================== Namespaces using System; -using CodeImp.DoomBuilder.IO; using System.IO; +using CodeImp.DoomBuilder.IO; #endregion @@ -32,7 +32,7 @@ namespace CodeImp.DoomBuilder.Data #region ================== Variables - private string lumpname; + private readonly string lumpname; #endregion @@ -93,7 +93,7 @@ namespace CodeImp.DoomBuilder.Data // Not loaded? if(bitmap == null) { - General.ErrorLogger.Add(ErrorType.Error, "Image lump '" + lumpname + "' data format could not be read, while loading texture '" + this.Name + "'. Does this lump contain valid picture data at all?"); + General.ErrorLogger.Add(ErrorType.Error, "Image lump \"" + lumpname + "\" data format could not be read, while loading texture \"" + this.Name + "\". Does this lump contain valid picture data at all?"); loadfailed = true; } else @@ -108,7 +108,7 @@ namespace CodeImp.DoomBuilder.Data } else { - General.ErrorLogger.Add(ErrorType.Error, "Image lump '" + lumpname + "' could not be found, while loading texture '" + this.Name + "'. Did you forget to include required resources?"); + General.ErrorLogger.Add(ErrorType.Error, "Image lump \"" + lumpname + "\" could not be found, while loading texture \"" + this.Name + "\". Did you forget to include required resources?"); loadfailed = true; } diff --git a/Source/Core/Data/SpriteImage.cs b/Source/Core/Data/SpriteImage.cs index 4c31db5..9e1e870 100644 --- a/Source/Core/Data/SpriteImage.cs +++ b/Source/Core/Data/SpriteImage.cs @@ -95,7 +95,7 @@ namespace CodeImp.DoomBuilder.Data if(reader is UnknownImageReader) { // Data is in an unknown format! - General.ErrorLogger.Add(ErrorType.Error, "Sprite lump '" + Name + "' data format could not be read. Does this lump contain valid picture data at all?"); + General.ErrorLogger.Add(ErrorType.Error, "Sprite lump \"" + Name + "\" data format could not be read. Does this lump contain valid picture data at all?"); bitmap = null; } else @@ -133,7 +133,7 @@ namespace CodeImp.DoomBuilder.Data else { // Missing a patch lump! - General.ErrorLogger.Add(ErrorType.Error, "Missing sprite lump '" + Name + "'. Forgot to include required resources?"); + General.ErrorLogger.Add(ErrorType.Error, "Missing sprite lump \"" + Name + "\". Forgot to include required resources?"); } // Pass on to base diff --git a/Source/Core/Data/TextureImage.cs b/Source/Core/Data/TextureImage.cs index 9ca200b..768bf7f 100644 --- a/Source/Core/Data/TextureImage.cs +++ b/Source/Core/Data/TextureImage.cs @@ -90,7 +90,7 @@ namespace CodeImp.DoomBuilder.Data catch(Exception e) { // Unable to make bitmap - General.ErrorLogger.Add(ErrorType.Error, "Unable to load texture image '" + this.Name + "'. " + e.GetType().Name + ": " + e.Message); + General.ErrorLogger.Add(ErrorType.Error, "Unable to load texture image \"" + this.Name + "\". " + e.GetType().Name + ": " + e.Message); loadfailed = true; } @@ -124,7 +124,7 @@ namespace CodeImp.DoomBuilder.Data if(reader is UnknownImageReader) { // Data is in an unknown format! - General.ErrorLogger.Add(ErrorType.Error, "Patch lump '" + p.lumpname + "' data format could not be read, while loading texture '" + this.Name + "'. Does this lump contain valid picture data at all?"); + General.ErrorLogger.Add(ErrorType.Error, "Patch lump \"" + p.lumpname + "\" data format could not be read, while loading texture \"" + this.Name + "\". Does this lump contain valid picture data at all?"); loadfailed = true; missingpatches++; //mxd } @@ -138,7 +138,7 @@ namespace CodeImp.DoomBuilder.Data catch(InvalidDataException) { // Data cannot be read! - General.ErrorLogger.Add(ErrorType.Error, "Patch lump '" + p.lumpname + "' data format could not be read, while loading texture '" + this.Name + "'. Does this lump contain valid picture data at all?"); + General.ErrorLogger.Add(ErrorType.Error, "Patch lump \"" + p.lumpname + "\" data format could not be read, while loading texture \"" + this.Name + "\". Does this lump contain valid picture data at all?"); loadfailed = true; missingpatches++; //mxd } @@ -150,7 +150,7 @@ namespace CodeImp.DoomBuilder.Data else { // Missing a patch lump! - General.ErrorLogger.Add(ErrorType.Error, "Missing patch lump '" + p.lumpname + "' while loading texture '" + this.Name + "'. Did you forget to include required resources?"); + General.ErrorLogger.Add(ErrorType.Error, "Missing patch lump \"" + p.lumpname + "\" while loading texture \"" + this.Name + "\". Did you forget to include required resources?"); loadfailed = true; missingpatches++; //mxd } diff --git a/Source/Core/Data/TexturePatch.cs b/Source/Core/Data/TexturePatch.cs index 7b7c910..efec5da 100644 --- a/Source/Core/Data/TexturePatch.cs +++ b/Source/Core/Data/TexturePatch.cs @@ -59,6 +59,7 @@ namespace CodeImp.DoomBuilder.Data public readonly TexturePathRenderStyle style; public readonly TexturePathBlendStyle blendstyle; //mxd public readonly float tintammount;//mxd + public readonly bool skip; //mxd // Constructor for simple patches public TexturePatch(string lumpname, int x, int y) @@ -76,6 +77,7 @@ namespace CodeImp.DoomBuilder.Data this.blendstyle = TexturePathBlendStyle.None;//mxd this.tintammount = 0; //mxd this.haslongname = false; //mxd + this.skip = false; //mxd } //mxd. Constructor for hires patches @@ -94,6 +96,7 @@ namespace CodeImp.DoomBuilder.Data this.blendstyle = patch.BlendStyle; this.tintammount = patch.TintAmmount; this.haslongname = (Path.GetFileNameWithoutExtension(this.lumpname) != this.lumpname); + this.skip = patch.Skip; //mxd. Check data so we don't perform unneeded operations later on if(this.alpha == 1.0f) diff --git a/Source/Core/Editing/ClassicMode.cs b/Source/Core/Editing/ClassicMode.cs index 3dcedef..2b38cc9 100644 --- a/Source/Core/Editing/ClassicMode.cs +++ b/Source/Core/Editing/ClassicMode.cs @@ -565,6 +565,10 @@ namespace CodeImp.DoomBuilder.Editing // Save mouse down position mousedownpos = mousepos; mousedownmappos = mousemappos; + + //mxd. Looks like in some cases (very detailed maps / slow CPUs) OnMouseUp is not fired + // This is my attempt at fixing this... + if(e.Button == mousedragging) mousedragging = MouseButtons.None; // Let the base class know base.OnMouseDown(e); diff --git a/Source/Core/Editing/CopyPasteManager.cs b/Source/Core/Editing/CopyPasteManager.cs index 8e72b86..618f0cc 100644 --- a/Source/Core/Editing/CopyPasteManager.cs +++ b/Source/Core/Editing/CopyPasteManager.cs @@ -246,7 +246,7 @@ namespace CodeImp.DoomBuilder.Editing // Write data to stream MemoryStream memstream = new MemoryStream(); ClipboardStreamWriter writer = new ClipboardStreamWriter(); //mxd - writer.Write(copyset, memstream, General.Map.Config.UseLongTextureNames); + writer.Write(copyset, memstream); // Set on clipboard Clipboard.SetData(CLIPBOARD_DATA_FORMAT, memstream); @@ -290,37 +290,31 @@ namespace CodeImp.DoomBuilder.Editing // Create undo General.MainWindow.DisplayStatus(StatusType.Action, "Pasted selected elements."); General.Map.UndoRedo.CreateUndo("Paste"); - - // Read from clipboard - Stream memstream = (Stream)Clipboard.GetData(CLIPBOARD_DATA_FORMAT); - memstream.Seek(0, SeekOrigin.Begin); // Mark all current geometry General.Map.Map.ClearAllMarks(true); - // Read data stream - ClipboardStreamReader reader = new ClipboardStreamReader(); //mxd - General.Map.Map.BeginAddRemove(); - reader.Read(General.Map.Map, memstream); - General.Map.Map.EndAddRemove(); + // Read from clipboard + using(Stream memstream = (Stream)Clipboard.GetData(CLIPBOARD_DATA_FORMAT)) + { + // Rewind before use + memstream.Seek(0, SeekOrigin.Begin); + + // Read data stream + ClipboardStreamReader reader = new ClipboardStreamReader(); //mxd + General.Map.Map.BeginAddRemove(); + bool success = reader.Read(General.Map.Map, memstream); + General.Map.Map.EndAddRemove(); + if(!success) //mxd + { + General.Map.UndoRedo.WithdrawUndo(); // This will also mess with the marks... + General.Map.Map.ClearAllMarks(true); // So re-mark all current geometry... + } + } // The new geometry is not marked, so invert the marks to get it marked General.Map.Map.InvertAllMarks(); - // Convert UDMF fields back to flags and activations, if needed - if(!(General.Map.FormatInterface is UniversalMapSetIO || General.Map.FormatInterface is SRB2MapSetIO)) General.Map.Map.TranslateFromUDMF(); - - //mxd. Translate texture names - General.Map.Map.TranslateTextureNames(General.Map.Config.UseLongTextureNames, true); - - // Modify tags and actions if preferred - if(options.ChangeTags == PasteOptions.TAGS_REMOVE) Tools.RemoveMarkedTags(); - if(options.ChangeTags == PasteOptions.TAGS_RENUMBER) Tools.RenumberMarkedTags(); - if(options.RemoveActions) Tools.RemoveMarkedActions(); - - // Clean up - memstream.Dispose(); - // Check if anything was pasted List things = General.Map.Map.GetMarkedThings(true); //mxd int totalpasted = things.Count; @@ -328,14 +322,25 @@ namespace CodeImp.DoomBuilder.Editing totalpasted += General.Map.Map.GetMarkedLinedefs(true).Count; totalpasted += General.Map.Map.GetMarkedSidedefs(true).Count; totalpasted += General.Map.Map.GetMarkedSectors(true).Count; + if(totalpasted > 0) { + // Convert UDMF fields back to flags and activations, if needed + if(!(General.Map.FormatInterface is UniversalMapSetIO || General.Map.FormatInterface is SRB2MapSetIO)) General.Map.Map.TranslateFromUDMF(); + + //mxd. Translate texture names + General.Map.Map.TranslateTextureNames(General.Map.Config.UseLongTextureNames, true); + + // Modify tags and actions if preferred + if(options.ChangeTags == PasteOptions.TAGS_REMOVE) Tools.RemoveMarkedTags(); + if(options.ChangeTags == PasteOptions.TAGS_RENUMBER) Tools.RenumberMarkedTags(); + if(options.RemoveActions) Tools.RemoveMarkedActions(); + foreach(Thing t in things) t.UpdateConfiguration(); //mxd General.Map.ThingsFilter.Update(); General.Editing.Mode.OnPasteEnd(options.Copy()); General.Plugins.OnPasteEnd(options); } - return; } } } diff --git a/Source/Core/Editing/GridSetup.cs b/Source/Core/Editing/GridSetup.cs index a053d69..fd0eb74 100644 --- a/Source/Core/Editing/GridSetup.cs +++ b/Source/Core/Editing/GridSetup.cs @@ -246,7 +246,7 @@ namespace CodeImp.DoomBuilder.Editing // This snaps to the nearest grid coordinate public Vector2D SnappedToGrid(Vector2D v) { - return GridSetup.SnappedToGrid(v, gridsizef, gridsizefinv); + return SnappedToGrid(v, gridsizef, gridsizefinv); } // This snaps to the nearest grid coordinate @@ -291,6 +291,9 @@ namespace CodeImp.DoomBuilder.Editing // Not lower than 1 if(gridsize >= 2) { + //mxd. Disable automatic grid resizing + General.MainWindow.DisableDynamicGridResize(); + // Change grid SetGridSize(gridsize >> 1); @@ -307,6 +310,9 @@ namespace CodeImp.DoomBuilder.Editing // Not higher than 1024 if(gridsize <= 512) { + //mxd. Disable automatic grid resizing + General.MainWindow.DisableDynamicGridResize(); + // Change grid SetGridSize(gridsize << 1); diff --git a/Source/Core/Editing/ThingsFilter.cs b/Source/Core/Editing/ThingsFilter.cs index 9d58a38..d93d645 100644 --- a/Source/Core/Editing/ThingsFilter.cs +++ b/Source/Core/Editing/ThingsFilter.cs @@ -272,7 +272,7 @@ namespace CodeImp.DoomBuilder.Editing //Integrity check if(!IsValid()) - General.ErrorLogger.Add(ErrorType.Warning, "Things filter '" + name + "' has invalid properties. Configure the things filter to fix this!"); + General.ErrorLogger.Add(ErrorType.Warning, "Things filter \"" + name + "\" has invalid properties. Configure the things filter to fix this!"); } //mxd diff --git a/Source/Core/Editing/UndoManager.cs b/Source/Core/Editing/UndoManager.cs index 66f8fea..aab46cc 100644 --- a/Source/Core/Editing/UndoManager.cs +++ b/Source/Core/Editing/UndoManager.cs @@ -1116,8 +1116,12 @@ namespace CodeImp.DoomBuilder.Editing Sidedef sd = (sindex >= 0) ? General.Map.Map.GetSidedefByIndex(sindex) : null; l.AttachFront(sd); l.Marked = true; - if (l.Tag != 0) linedeftags.Add(l.Tag); - if (sd != null) sd.Marked = true; + if (l.Tag != 0) linedeftags.Add(l.Tag); + if (sd != null) + { + sd.Marked = true; + if(sd.Sector != null) sd.Sector.UpdateNeeded = true; //mxd. Sector needs to be updated as well... + } geometrychanged = true; } @@ -1141,8 +1145,12 @@ namespace CodeImp.DoomBuilder.Editing Sidedef sd = (sindex >= 0) ? General.Map.Map.GetSidedefByIndex(sindex) : null; l.AttachBack(sd); l.Marked = true; - if (l.Tag != 0) linedeftags.Add(l.Tag); - if (sd != null) sd.Marked = true; + if (l.Tag != 0) linedeftags.Add(l.Tag); + if (sd != null) + { + sd.Marked = true; + if(sd.Sector != null) sd.Sector.UpdateNeeded = true; //mxd. Sector needs to be updated as well... + } geometrychanged = true; } diff --git a/Source/Core/GZBuilder/Controls/TagSelector.Designer.cs b/Source/Core/GZBuilder/Controls/TagSelector.Designer.cs index be89edf..2e5ea4b 100644 --- a/Source/Core/GZBuilder/Controls/TagSelector.Designer.cs +++ b/Source/Core/GZBuilder/Controls/TagSelector.Designer.cs @@ -68,8 +68,7 @@ this.newTag.Size = new System.Drawing.Size(54, 24); this.newTag.TabIndex = 2; this.newTag.Text = "New"; - this.tooltip.SetToolTip(this.newTag, "Finds a tag, which is not used as a tag or tag action argument \r\nby any map eleme" + - "nt"); + this.tooltip.SetToolTip(this.newTag, "Find a tag, which is not used as a tag or tag action argument\r\nby any map element"); this.newTag.UseVisualStyleBackColor = true; this.newTag.Click += new System.EventHandler(this.newTag_Click); // @@ -80,7 +79,7 @@ this.unusedTag.Size = new System.Drawing.Size(54, 24); this.unusedTag.TabIndex = 3; this.unusedTag.Text = "Unused"; - this.tooltip.SetToolTip(this.unusedTag, "Finds a tag, which is not used as a tag \r\nby any map element of this type"); + this.tooltip.SetToolTip(this.unusedTag, "Find a tag, which is not used as a tag\r\nby any map element of this type"); this.unusedTag.UseVisualStyleBackColor = true; this.unusedTag.Click += new System.EventHandler(this.unusedTag_Click); // @@ -98,7 +97,7 @@ this.clear.Name = "clear"; this.clear.Size = new System.Drawing.Size(26, 24); this.clear.TabIndex = 4; - this.tooltip.SetToolTip(this.clear, "Sets tag to 0"); + this.tooltip.SetToolTip(this.clear, "Set tag to 0"); this.clear.UseVisualStyleBackColor = true; this.clear.Click += new System.EventHandler(this.clear_Click); // diff --git a/Source/Core/GZBuilder/Controls/TagSelector.cs b/Source/Core/GZBuilder/Controls/TagSelector.cs index b874443..937e0f6 100644 --- a/Source/Core/GZBuilder/Controls/TagSelector.cs +++ b/Source/Core/GZBuilder/Controls/TagSelector.cs @@ -255,9 +255,9 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls private void TagSelector_Resize(object sender, EventArgs e) { clear.Left = this.Width - clear.Width - clear.Margin.Right; - unusedTag.Left = clear.Left - clear.Margin.Left - unusedTag.Margin.Right - unusedTag.Width; - newTag.Left = unusedTag.Left - unusedTag.Margin.Left - newTag.Margin.Right - newTag.Width; - cbTagPicker.Width = newTag.Left - newTag.Margin.Left - cbTagPicker.Margin.Right - cbTagPicker.Left; + unusedTag.Left = clear.Left - unusedTag.Margin.Right - unusedTag.Width; + newTag.Left = unusedTag.Left - newTag.Margin.Right - newTag.Width; + cbTagPicker.Width = newTag.Left - cbTagPicker.Margin.Right - cbTagPicker.Left; } #endregion diff --git a/Source/Core/GZBuilder/Controls/TagsSelector.cs b/Source/Core/GZBuilder/Controls/TagsSelector.cs index 7168b9b..427fb97 100644 --- a/Source/Core/GZBuilder/Controls/TagsSelector.cs +++ b/Source/Core/GZBuilder/Controls/TagsSelector.cs @@ -257,6 +257,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls if(tagpicker.SelectedIndex == -1) tagpicker.Text = tag.ToString(); } + clear.Enabled = (tagpicker.Text.Trim() != "0"); + blockupdate = false; } @@ -278,6 +280,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls private void clear_Click(object sender, EventArgs e) { + tagpicker.Focus(); tagpicker.SelectedIndex = -1; tagpicker.Text = "0"; } @@ -356,6 +359,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls { if(blockupdate) return; + clear.Enabled = (tagpicker.Text.Trim() != "0"); if(tagpicker.SelectedItem != null) { TagInfo info = (TagInfo)tagpicker.SelectedItem; @@ -420,11 +424,11 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls private void TagsSelector_Resize(object sender, EventArgs e) { clear.Left = this.Width - clear.Width - clear.Margin.Right; - unusedtag.Left = clear.Left - clear.Margin.Left - unusedtag.Margin.Right - unusedtag.Width; - newtag.Left = unusedtag.Left - unusedtag.Margin.Left - newtag.Margin.Right - newtag.Width; - tagpicker.Width = newtag.Left - newtag.Margin.Left - tagpicker.Margin.Right - tagpicker.Left; + unusedtag.Left = clear.Left - unusedtag.Margin.Right - unusedtag.Width; + newtag.Left = unusedtag.Left - newtag.Margin.Right - newtag.Width; + tagpicker.Width = newtag.Left - tagpicker.Margin.Right - tagpicker.Left; removetag.Left = clear.Left; - addtag.Left = removetag.Left - removetag.Margin.Left - addtag.Margin.Right - addtag.Width; + addtag.Left = removetag.Left - addtag.Margin.Right - addtag.Width; } #endregion diff --git a/Source/Core/GZBuilder/Data/EngineInfo.cs b/Source/Core/GZBuilder/Data/EngineInfo.cs index 55d73a8..de21705 100644 --- a/Source/Core/GZBuilder/Data/EngineInfo.cs +++ b/Source/Core/GZBuilder/Data/EngineInfo.cs @@ -45,7 +45,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data { if(testprogramname == DEFAULT_ENGINE_NAME && !String.IsNullOrEmpty(TestProgram)) { - //get engine name from path + // Get engine name from path testprogramname = Path.GetFileNameWithoutExtension(TestProgram); } @@ -59,12 +59,11 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data if(File.Exists(TestProgram)) { Icon i = Icon.ExtractAssociatedIcon(TestProgram); - if(i != null) icon = i.ToBitmap(); + icon = (i != null ? i.ToBitmap() : new Bitmap(Properties.Resources.Question)); } - - if(icon == null) + else { - icon = new Bitmap(16, 16); + icon = new Bitmap(Properties.Resources.Warning); } } diff --git a/Source/Core/GZBuilder/Geometry/Line3D.cs b/Source/Core/GZBuilder/Geometry/Line3D.cs index 9cd3703..f7ed0d9 100644 --- a/Source/Core/GZBuilder/Geometry/Line3D.cs +++ b/Source/Core/GZBuilder/Geometry/Line3D.cs @@ -22,6 +22,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.Geometry { this.Start = start; this.End = end; + this.Start2D = start; + this.End2D = end; this.Color = General.Colors.InfoLine; this.RenderArrowhead = true; } @@ -30,6 +32,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.Geometry { this.Start = start; this.End = end; + this.Start2D = start; + this.End2D = end; this.Color = General.Colors.InfoLine; this.RenderArrowhead = renderArrowhead; } @@ -38,6 +42,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.Geometry { this.Start = start; this.End = end; + this.Start2D = start; + this.End2D = end; this.Color = color; this.RenderArrowhead = true; } @@ -46,6 +52,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.Geometry { this.Start = start; this.End = end; + this.Start2D = start; + this.End2D = end; this.Color = color; this.RenderArrowhead = renderArrowhead; } diff --git a/Source/Core/GZBuilder/Windows/ExceptionDialog.cs b/Source/Core/GZBuilder/Windows/ExceptionDialog.cs index 55d1056..7773d22 100644 --- a/Source/Core/GZBuilder/Windows/ExceptionDialog.cs +++ b/Source/Core/GZBuilder/Windows/ExceptionDialog.cs @@ -130,7 +130,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.Windows // Get OS name ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT Caption FROM Win32_OperatingSystem"); - foreach(ManagementObject mo in searcher.Get()) + foreach(ManagementBaseObject mo in searcher.Get()) { result += "OS: " + mo["Caption"] + Environment.NewLine; break; @@ -138,7 +138,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.Windows // Get GPU name searcher = new ManagementObjectSearcher("SELECT * FROM Win32_VideoController"); - foreach(ManagementObject mo in searcher.Get()) + foreach(ManagementBaseObject mo in searcher.Get()) { PropertyData bpp = mo.Properties["CurrentBitsPerPixel"]; PropertyData description = mo.Properties["Description"]; diff --git a/Source/Core/GZBuilder/md3/ModelReader.cs b/Source/Core/GZBuilder/md3/ModelReader.cs index 7c5e9f7..bc831fe 100644 --- a/Source/Core/GZBuilder/md3/ModelReader.cs +++ b/Source/Core/GZBuilder/md3/ModelReader.cs @@ -102,7 +102,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3 MemoryStream ms = LoadFile(containers, mde.ModelNames[i], true); if(ms == null) { - General.ErrorLogger.Add(ErrorType.Error, "Error while loading '" + mde.ModelNames[i] + "': unable to find file."); + General.ErrorLogger.Add(ErrorType.Error, "Error while loading \"" + mde.ModelNames[i] + "\": unable to find file."); continue; } @@ -112,7 +112,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3 case ".md3": if(!string.IsNullOrEmpty(mde.FrameNames[i])) { - General.ErrorLogger.Add(ErrorType.Error, "Error while loading '" + mde.ModelNames[i] + "': frame names are not supported for MD3 models!"); + General.ErrorLogger.Add(ErrorType.Error, "Error while loading \"" + mde.ModelNames[i] + "\": frame names are not supported for MD3 models!"); continue; } result = ReadMD3Model(ref bbs, useSkins, ms, device, mde.FrameIndices[i]); @@ -131,7 +131,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3 //got errors? if(!String.IsNullOrEmpty(result.Errors)) { - General.ErrorLogger.Add(ErrorType.Error, "Error while loading '" + mde.ModelNames[i] + "': " + result.Errors); + General.ErrorLogger.Add(ErrorType.Error, "Error while loading \"" + mde.ModelNames[i] + "\": " + result.Errors); } else { @@ -164,7 +164,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3 if(Array.IndexOf(ModelData.SUPPORTED_TEXTURE_EXTENSIONS, ext) == -1) { mde.Model.Textures.Add(General.Map.Data.UnknownTexture3D.Texture); - errors.Add("image format '" + ext + "' is not supported!"); + errors.Add("image format \"" + ext + "\" is not supported!"); continue; } @@ -177,7 +177,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3 if(t == null) { mde.Model.Textures.Add(General.Map.Data.UnknownTexture3D.Texture); - errors.Add("unable to load skin '" + result.Skins[m] + "'"); + errors.Add("unable to load skin \"" + result.Skins[m] + "\""); continue; } @@ -191,7 +191,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3 if(t == null) { mde.Model.Textures.Add(General.Map.Data.UnknownTexture3D.Texture); - errors.Add("unable to load texture '" + mde.TextureNames[i] + "'"); + errors.Add("unable to load texture \"" + mde.TextureNames[i] + "\""); } else { @@ -203,7 +203,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3 if(errors.Count > 0) { foreach(string e in errors) - General.ErrorLogger.Add(ErrorType.Error, "Error while loading '" + mde.ModelNames[i] + "': " + e); + General.ErrorLogger.Add(ErrorType.Error, "Error while loading \"" + mde.ModelNames[i] + "\": " + e); } } } @@ -242,7 +242,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3 string magic = ReadString(br, 4); if(magic != "IDP3") { - result.Errors = "unknown header: expected 'IDP3', but got '" + magic + "'"; + result.Errors = "unknown header: expected \"IDP3\", but got \"" + magic + "\""; return result; } @@ -341,7 +341,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3 long start = br.BaseStream.Position; string magic = ReadString(br, 4); - if(magic != "IDP3") return "error while reading surface. Unknown header: expected 'IDP3', but got '" + magic + "'"; + if(magic != "IDP3") return "error while reading surface. Unknown header: expected \"IDP3\", but got \"" + magic + "\""; string name = ReadString(br, 64); int flags = br.ReadInt32(); @@ -432,8 +432,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3 { string magic = ReadString(br, 4); if(magic != "IDP2") //magic number: "IDP2" - { - result.Errors = "unknown header: expected 'IDP2', but got '" + magic + "'"; + { + result.Errors = "unknown header: expected \"IDP2\", but got \"" + magic + "\""; return result; } @@ -521,7 +521,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3 // No dice? Bail out! if(!framefound) { - result.Errors = "unable to find frame '" + framename + "'!"; + result.Errors = "unable to find frame \"" + framename + "\"!"; return result; } } diff --git a/Source/Core/General/FileLockChecker.cs b/Source/Core/General/FileLockChecker.cs index 79aa82c..64d0226 100644 --- a/Source/Core/General/FileLockChecker.cs +++ b/Source/Core/General/FileLockChecker.cs @@ -176,8 +176,8 @@ namespace CodeImp.DoomBuilder foreach(Process process in result.Processes) { result.Error += Path.GetFileName(process.MainModule.FileName) - + " ('" + process.MainModule.FileName - + "', started at " + process.StartTime + ")" + + " (\"" + process.MainModule.FileName + + "\", started at " + process.StartTime + ")" + Environment.NewLine + Environment.NewLine; } } diff --git a/Source/Core/General/General.cs b/Source/Core/General/General.cs index a31a12e..8307d02 100644 --- a/Source/Core/General/General.cs +++ b/Source/Core/General/General.cs @@ -318,7 +318,7 @@ namespace CodeImp.DoomBuilder ConfigurationInfo cfginfo = new ConfigurationInfo(cfg, fullfilename); // Add to lists - General.WriteLogLine("Registered game configuration '" + cfginfo.Name + "' from '" + fullfilename + "'"); + General.WriteLogLine("Registered game configuration \"" + cfginfo.Name + "\" from \"" + fullfilename + "\""); configs.Add(cfginfo); } } @@ -369,7 +369,7 @@ namespace CodeImp.DoomBuilder catch(Exception e) { // Unable to load configuration - errorlogger.Add(ErrorType.Error, "Unable to load the nodebuilder configuration '" + de.Key + "' from \"" + Path.GetFileName(filepath) + "\". Error: " + e.Message); + errorlogger.Add(ErrorType.Error, "Unable to load the nodebuilder configuration \"" + de.Key + "\" from \"" + Path.GetFileName(filepath) + "\". Error: " + e.Message); } } } @@ -677,7 +677,7 @@ namespace CodeImp.DoomBuilder // Show any errors if preferred if(errorlogger.IsErrorAdded) { - mainwindow.DisplayStatus(StatusType.Warning, "There were errors during program statup!"); + mainwindow.DisplayStatus(StatusType.Warning, "There were errors during program startup!"); if(!delaymainwindow && General.Settings.ShowErrorsWindow) mainwindow.ShowErrors(); } @@ -707,7 +707,7 @@ namespace CodeImp.DoomBuilder if((DateTime.Now - File.GetLastWriteTime(backup)).TotalDays > 30) { File.Delete(backup); - WriteLogLine("Removed '" + backup + "' map backup."); + WriteLogLine("Removed \"" + backup + "\" map backup."); } } } @@ -749,7 +749,7 @@ namespace CodeImp.DoomBuilder MessageBoxIcon.Exclamation) == DialogResult.Yes) { // Go to DirectX End-User Runtime Web Installer page (mxd) - OpenWebsite("http://www.microsoft.com/en-us/download/details.aspx?id=35"); + OpenWebsite("https://www.microsoft.com/en-us/download/details.aspx?id=35&44F86079-8679-400C-BFF2-9CA5F2BCBDFC=1"); } // End program here @@ -859,7 +859,7 @@ namespace CodeImp.DoomBuilder catch(Exception) { } // Warn the user? - if(!portablemode) ShowWarningMessage("Failed to enable portable mode.\nMake sure you have write premission for '" + apppath + "' directory.", MessageBoxButtons.OK); + if(!portablemode) ShowWarningMessage("Failed to enable portable mode.\nMake sure you have write premission for \"" + apppath + "\" directory.", MessageBoxButtons.OK); } // Resource? else if(string.Compare(curarg, "-RESOURCE", true) == 0) @@ -1219,8 +1219,8 @@ namespace CodeImp.DoomBuilder if(changemapwindow.ShowDialog(mainwindow) != DialogResult.OK) return; // Display status - mainwindow.DisplayStatus(StatusType.Busy, "Switching to map '" + changemapwindow.Options.CurrentName + "'..."); - WriteLogLine("Switching to map '" + changemapwindow.Options.CurrentName + "'..."); + mainwindow.DisplayStatus(StatusType.Busy, "Switching to map \"" + changemapwindow.Options.CurrentName + "\"..."); + WriteLogLine("Switching to map \"" + changemapwindow.Options.CurrentName + "\"..."); Cursor.Current = Cursors.WaitCursor; @@ -1431,8 +1431,14 @@ namespace CodeImp.DoomBuilder mainwindow.DisplayStatus(StatusType.Warning, "There were errors during saving!"); if(!delaymainwindow && settings.ShowErrorsWindow) mainwindow.ShowErrors(); } - else + else if(result) + { mainwindow.DisplayStatus(StatusType.Info, "Map saved in " + map.FileTitle + "."); + } + else + { + mainwindow.DisplayStatus(StatusType.Info, "Map saving cancelled."); //mxd + } Cursor.Current = Cursors.Default; } @@ -1499,10 +1505,16 @@ namespace CodeImp.DoomBuilder { // Show any errors if preferred mainwindow.DisplayStatus(StatusType.Warning, "There were errors during saving!"); - if(!delaymainwindow && General.Settings.ShowErrorsWindow) mainwindow.ShowErrors(); + if(!delaymainwindow && settings.ShowErrorsWindow) mainwindow.ShowErrors(); + } + else if(result) + { + mainwindow.DisplayStatus(StatusType.Info, "Map saved in " + map.FileTitle + "."); } else - mainwindow.DisplayStatus(StatusType.Info, "Map saved in " + map.FileTitle + "."); + { + mainwindow.DisplayStatus(StatusType.Info, "Map saving cancelled."); //mxd + } Cursor.Current = Cursors.Default; } @@ -1561,8 +1573,14 @@ namespace CodeImp.DoomBuilder mainwindow.DisplayStatus(StatusType.Warning, "There were errors during saving!"); if(!delaymainwindow && settings.ShowErrorsWindow) mainwindow.ShowErrors(); } + else if(result) + { + mainwindow.DisplayStatus(StatusType.Info, "Map saved in " + map.FileTitle + "."); + } else - mainwindow.DisplayStatus(StatusType.Info, "Map saved into " + map.FileTitle + "."); + { + mainwindow.DisplayStatus(StatusType.Info, "Map saving cancelled."); //mxd + } Cursor.Current = Cursors.Default; } diff --git a/Source/Core/General/Launcher.cs b/Source/Core/General/Launcher.cs index 3f659eb..762ff71 100644 --- a/Source/Core/General/Launcher.cs +++ b/Source/Core/General/Launcher.cs @@ -245,7 +245,7 @@ namespace CodeImp.DoomBuilder { if(process != null) { - General.ShowWarningMessage("Game engine is already running." + Environment.NewLine + "Please close '" + process.MainModule.FileName + "' first.", MessageBoxButtons.OK); + General.ShowWarningMessage("Game engine is already running." + Environment.NewLine + "Please close \"" + process.MainModule.FileName + "\" first.", MessageBoxButtons.OK); return true; } diff --git a/Source/Core/General/MapManager.cs b/Source/Core/General/MapManager.cs index 1ca70b5..6fafb93 100644 --- a/Source/Core/General/MapManager.cs +++ b/Source/Core/General/MapManager.cs @@ -724,7 +724,7 @@ namespace CodeImp.DoomBuilder internal bool SaveMap(string newfilepathname, SavePurpose purpose) { string settingsfile; - WAD targetwad; + WAD targetwad = null; bool includenodes; General.WriteLogLine("Saving map to file: " + newfilepathname); @@ -773,6 +773,31 @@ namespace CodeImp.DoomBuilder includenodes = VerifyNodebuilderLumps(tempwad, TEMP_MAP_HEADER); } + //mxd. Target file is read-only? + FileInfo info = new FileInfo(newfilepathname); + if(info.Exists && info.IsReadOnly) + { + if(General.ShowWarningMessage("Unable to save the map: target file is read-only.\nRemove read-only flag and save the map anyway?", MessageBoxButtons.YesNo) == DialogResult.Yes) + { + General.WriteLogLine("Removing read-only flag from the map file..."); + try + { + info.IsReadOnly = false; + } + catch(Exception e) + { + General.ShowErrorMessage("Failed to remove read-only flag from \"" + filepathname + "\":" + Environment.NewLine + Environment.NewLine + e.Message, MessageBoxButtons.OK); + General.WriteLogLine("Failed to remove read-only flag from \"" + filepathname + "\":" + e.Message); + return false; + } + } + else + { + General.WriteLogLine("Map saving cancelled..."); + return false; + } + } + // Suspend data resources data.Suspend(); @@ -916,22 +941,29 @@ namespace CodeImp.DoomBuilder targetwad = new WAD(newfilepathname); } } - catch (IOException) + catch(Exception e) { - General.ShowErrorMessage("IO Error while writing target file: " + newfilepathname + ". Please make sure the location is accessible and not in use by another program.", MessageBoxButtons.OK); - if(!string.IsNullOrEmpty(origwadfile) && File.Exists(origwadfile)) File.Delete(origwadfile); //mxd. Clean-up + General.ShowErrorMessage("Unable to write the map to target file \"" + newfilepathname + "\":\n" + e.Message, MessageBoxButtons.OK); + if(!string.IsNullOrEmpty(origwadfile) && File.Exists(origwadfile)) + { + //mxd. Clean-up + if(File.Exists(newfilepathname)) + { + //mxd. We MAY've just deleted the map from the target file. Let's pretend this never happened + if(targetwad != null) targetwad.Dispose(); + File.Delete(newfilepathname); + File.Move(origwadfile, newfilepathname); + } + else + { + File.Delete(origwadfile); + } + } + data.Resume(); - General.WriteLogLine("Map saving failed"); + General.WriteLogLine("Map saving failed: " + e.Message); return false; } - catch (UnauthorizedAccessException) - { - General.ShowErrorMessage("Error while accessing target file: " + newfilepathname + ". Please make sure the location is accessible and not in use by another program.", MessageBoxButtons.OK); - if(!string.IsNullOrEmpty(origwadfile) && File.Exists(origwadfile)) File.Delete(origwadfile); //mxd. Clean-up - data.Resume(); - General.WriteLogLine("Map saving failed"); - return false; - } // Copy map lumps to target file CopyLumpsByType(tempwad, TEMP_MAP_HEADER, targetwad, origmapname, true, true, includenodes, true); diff --git a/Source/Core/General/UpdateChecker.cs b/Source/Core/General/UpdateChecker.cs index 26c34fc..1bd87f6 100644 --- a/Source/Core/General/UpdateChecker.cs +++ b/Source/Core/General/UpdateChecker.cs @@ -10,8 +10,9 @@ namespace CodeImp.DoomBuilder { internal static class UpdateChecker { + private const string NO_UPDATE_REQUIRED = "Your version is up to date."; + private static BackgroundWorker worker; - private static string errordesc; private static bool verbose; internal static void PerformCheck(bool verbosemode) @@ -19,15 +20,7 @@ namespace CodeImp.DoomBuilder // Update check already runing? if(worker != null && worker.IsBusy) { - if(verbosemode) - { - General.ShowWarningMessage("Update check is already running!", MessageBoxButtons.OK); - } - else - { - General.ErrorLogger.Add(ErrorType.Warning, "Update check is already running!"); - General.MainWindow.ShowErrors(); - } + if(verbosemode) General.ShowWarningMessage("Update check is already running!", MessageBoxButtons.OK); return; } @@ -45,7 +38,7 @@ namespace CodeImp.DoomBuilder string updaterpath = Path.Combine(General.AppPath, "Updater.exe"); if(!File.Exists(updaterpath)) { - errordesc = "Update check failed: '" + updaterpath + "' does not exist!"; + e.Result = "Update check failed: \"" + updaterpath + "\" does not exist!"; e.Cancel = true; return; } @@ -53,7 +46,7 @@ namespace CodeImp.DoomBuilder string inipath = Path.Combine(General.AppPath, "Updater.ini"); if(!File.Exists(inipath)) { - errordesc = "Update check failed: '" + inipath + "' does not exist!"; + e.Result = "Update check failed: \"" + inipath + "\" does not exist!"; e.Cancel = true; return; } @@ -61,7 +54,7 @@ namespace CodeImp.DoomBuilder string url = GetDownloadUrl(inipath); if(string.IsNullOrEmpty(url)) { - errordesc = "Update check failed: failed to get update url from Updater.ini!"; + e.Result = "Update check failed: failed to get update url from Updater.ini!"; e.Cancel = true; return; } @@ -77,7 +70,7 @@ namespace CodeImp.DoomBuilder { if(stream == null) { - errordesc = "Update check failed: failed to retrieve remote revision info."; + e.Result = "Update check failed: failed to retrieve remote revision info."; e.Cancel = true; return; } @@ -90,7 +83,7 @@ namespace CodeImp.DoomBuilder if(!int.TryParse(s, out remoterev)) { - errordesc = "Update check failed: failed to retrieve remote revision number."; + e.Result = "Update check failed: failed to retrieve remote revision number."; e.Cancel = true; return; } @@ -103,7 +96,7 @@ namespace CodeImp.DoomBuilder if(string.IsNullOrEmpty(changelog)) { - errordesc = "Update check failed: failed to retrieve changelog."; + e.Result = "Update check failed: failed to retrieve changelog."; e.Cancel = true; return; } @@ -113,24 +106,20 @@ namespace CodeImp.DoomBuilder } else if(verbose) { - errordesc = "Your version is up to date"; + e.Result = NO_UPDATE_REQUIRED; } } - private static void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs runWorkerCompletedEventArgs) + private static void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { worker = null; + string errordesc = (e.Result != null ? e.Result.ToString() : string.Empty); if(!string.IsNullOrEmpty(errordesc)) { if(verbose) - { General.ShowWarningMessage(errordesc, MessageBoxButtons.OK); - } - else - { - General.ErrorLogger.Add(ErrorType.Warning, errordesc); - General.MainWindow.ShowErrors(); - } + else if(errordesc != NO_UPDATE_REQUIRED) + General.ErrorLogger.Add(ErrorType.Error, errordesc); } } @@ -178,47 +167,42 @@ namespace CodeImp.DoomBuilder private static MemoryStream DownloadWebFile(string url) { // Open a data stream from the supplied URL - WebRequest webReq = WebRequest.Create(url); - WebResponse webResponse; + WebRequest request = WebRequest.Create(url); + WebResponse response; try { - webResponse = webReq.GetResponse(); + response = request.GetResponse(); } catch(WebException) { return null; } - Stream dataStream = webResponse.GetResponseStream(); + Stream source = response.GetResponseStream(); + if(source == null) return null; // Download the data in chuncks - byte[] dataBuffer = new byte[1024]; + byte[] buffer = new byte[1024]; // Download the data - MemoryStream memoryStream = new MemoryStream(); + MemoryStream result = new MemoryStream(); while(!General.MainWindow.IsDisposed) { // Let's try and read the data - int bytesFromStream = dataStream.Read(dataBuffer, 0, dataBuffer.Length); - if(bytesFromStream == 0) - { - // Download complete - break; - } - else - { - // Write the downloaded data - memoryStream.Write(dataBuffer, 0, bytesFromStream); - } + int numbytes = source.Read(buffer, 0, buffer.Length); + if(numbytes == 0) break; // Download complete + + // Write the downloaded data + result.Write(buffer, 0, numbytes); } // Release resources - dataStream.Close(); + source.Close(); // Rewind and return the stream - memoryStream.Position = 0; - return memoryStream; + result.Position = 0; + return result; } private static string GetDownloadUrl(string filename) diff --git a/Source/Core/Geometry/InterpolationTools.cs b/Source/Core/Geometry/InterpolationTools.cs index 7ca42aa..7d8f2fb 100644 --- a/Source/Core/Geometry/InterpolationTools.cs +++ b/Source/Core/Geometry/InterpolationTools.cs @@ -21,7 +21,7 @@ namespace CodeImp.DoomBuilder.Geometry case Mode.EASE_IN_SINE: return EaseInSine(val1, val2, delta); case Mode.EASE_OUT_SINE: return EaseOutSine(val1, val2, delta); case Mode.EASE_IN_OUT_SINE: return EaseInOutSine(val1, val2, delta); - default: throw new NotImplementedException("InterpolationTools.Interpolate: '" + mode + "' mode is not supported!"); + default: throw new NotImplementedException("InterpolationTools.Interpolate: \"" + mode + "\" mode is not supported!"); } } diff --git a/Source/Core/Geometry/Tools.cs b/Source/Core/Geometry/Tools.cs index 5d076db..fa63121 100644 --- a/Source/Core/Geometry/Tools.cs +++ b/Source/Core/Geometry/Tools.cs @@ -1845,7 +1845,7 @@ namespace CodeImp.DoomBuilder.Geometry return GetSidedefBottomOffsetY(side, offset, scaleY, fromNormalized); default: - throw new NotSupportedException("Tools.GetSidedefOffsetY: '" + part + "' geometry type is not supported!"); + throw new NotSupportedException("Tools.GetSidedefOffsetY: \"" + part + "\" geometry type is not supported!"); } } @@ -2236,7 +2236,7 @@ namespace CodeImp.DoomBuilder.Geometry /// Flips sector linedefs so they all face either inward or outward. public static void FlipSectorLinedefs(ICollection sectors, bool selectedlinesonly) { - Dictionary processed = new Dictionary(); + HashSet processed = new HashSet(); foreach(Sector s in sectors) { @@ -2248,7 +2248,7 @@ namespace CodeImp.DoomBuilder.Geometry //sort lines foreach(Sidedef side in s.Sidedefs) { - if(processed.ContainsKey(side.Line)) continue; + if(processed.Contains(side.Line)) continue; if(selectedlinesonly && !side.Line.Selected) { if(side == side.Line.Front) unselectedfrontlines++; @@ -2261,7 +2261,7 @@ namespace CodeImp.DoomBuilder.Geometry else backlines.Add(side.Line); - processed.Add(side.Line, false); + processed.Add(side.Line); } //flip lines diff --git a/Source/Core/IO/ClipboardStreamReader.cs b/Source/Core/IO/ClipboardStreamReader.cs index 22fc265..4580b84 100644 --- a/Source/Core/IO/ClipboardStreamReader.cs +++ b/Source/Core/IO/ClipboardStreamReader.cs @@ -7,6 +7,7 @@ using CodeImp.DoomBuilder.Config; using CodeImp.DoomBuilder.Geometry; using CodeImp.DoomBuilder.Map; using CodeImp.DoomBuilder.Types; +using CodeImp.DoomBuilder.Windows; #endregion @@ -29,32 +30,56 @@ namespace CodeImp.DoomBuilder.IO public Dictionary Flags; } - private bool uselongtexturenames; //mxd - #endregion #region ================== Properties - public bool UseLongTextureNames { get { return uselongtexturenames; } } //mxd - #endregion #region ================== Reading // This reads from a stream - public MapSet Read(MapSet map, Stream stream) + public bool Read(MapSet map, Stream stream) { BinaryReader reader = new BinaryReader(stream); + //mxd. Sanity checks + int numverts = reader.ReadInt32(); + if(map.Vertices.Count + numverts >= General.Map.FormatInterface.MaxVertices) + { + General.Interface.DisplayStatus(StatusType.Warning, "Cannot paste: resulting number of vertices (" + (map.Vertices.Count + numverts) + ") will exceed map format's maximum (" + General.Map.FormatInterface.MaxVertices + ")."); + return false; + } + + int numsectors = reader.ReadInt32(); + if(map.Sectors.Count + numsectors >= General.Map.FormatInterface.MaxSectors) + { + General.Interface.DisplayStatus(StatusType.Warning, "Cannot paste: resulting number of sectors (" + (map.Sectors.Count + numsectors) + ") will exceed map format's maximum (" + General.Map.FormatInterface.MaxSectors + ")."); + return false; + } + + int numlinedefs = reader.ReadInt32(); + if(map.Linedefs.Count + numlinedefs >= General.Map.FormatInterface.MaxLinedefs) + { + General.Interface.DisplayStatus(StatusType.Warning, "Cannot paste: resulting number of linedefs (" + (map.Linedefs.Count + numlinedefs) + ") will exceed map format's maximum (" + General.Map.FormatInterface.MaxLinedefs + ")."); + return false; + } + + int numthings = reader.ReadInt32(); + if(map.Things.Count + numthings >= General.Map.FormatInterface.MaxThings) + { + General.Interface.DisplayStatus(StatusType.Warning, "Cannot paste: resulting number of things (" + (map.Things.Count + numthings) + ") will exceed map format's maximum (" + General.Map.FormatInterface.MaxThings + ")."); + return false; + } + // Read the map - uselongtexturenames = reader.ReadBoolean(); //mxd Dictionary vertexlink = ReadVertices(map, reader); Dictionary sectorlink = ReadSectors(map, reader); Dictionary sidedeflink = ReadSidedefs(reader); ReadLinedefs(map, reader, vertexlink, sectorlink, sidedeflink); ReadThings(map, reader); - return map; + return true; } private static Dictionary ReadVertices(MapSet map, BinaryReader reader) @@ -388,7 +413,7 @@ namespace CodeImp.DoomBuilder.IO break; default: //WOLOLO! ERRORS! - throw new Exception("Got unknown value type while reading custom fields from clipboard data! Field '" + name + "', type '" + type + "', primitive type '" + valueType + "'"); + throw new Exception("Got unknown value type while reading custom fields from clipboard data! Field \"" + name + "\", type \"" + type + "\", primitive type \"" + valueType + "\""); } } diff --git a/Source/Core/IO/ClipboardStreamWriter.cs b/Source/Core/IO/ClipboardStreamWriter.cs index 28ee6f1..7c7bce2 100644 --- a/Source/Core/IO/ClipboardStreamWriter.cs +++ b/Source/Core/IO/ClipboardStreamWriter.cs @@ -22,7 +22,7 @@ namespace CodeImp.DoomBuilder.IO #region ================== Variables - private Configuration config; + private readonly Configuration config; #endregion @@ -83,13 +83,13 @@ namespace CodeImp.DoomBuilder.IO #region ================== Writing - public void Write(MapSet map, Stream stream, bool longtexturenames) + public void Write(MapSet map, Stream stream) { - Write(map.Vertices, map.Linedefs, map.Sidedefs, map.Sectors, map.Things, stream, longtexturenames); + Write(map.Vertices, map.Linedefs, map.Sidedefs, map.Sectors, map.Things, stream); } public void Write(ICollection vertices, ICollection linedefs, ICollection sidedefs, - ICollection sectors, ICollection things, Stream stream, bool longtexturenames) + ICollection sectors, ICollection things, Stream stream) { // Create collections Dictionary vertexids = new Dictionary(); @@ -104,7 +104,10 @@ namespace CodeImp.DoomBuilder.IO BinaryWriter writer = new BinaryWriter(stream); // Write the data structures to stream - writer.Write(longtexturenames); //mxd + writer.Write(vertices.Count); //mxd + writer.Write(sectors.Count); //mxd + writer.Write(linedefs.Count); //mxd + writer.Write(things.Count); //mxd WriteVertices(vertices, writer); WriteSectors(sectors, writer); WriteSidedefs(sidedefs, writer, sectorids); @@ -292,8 +295,8 @@ namespace CodeImp.DoomBuilder.IO writer.Write(s.ToCharArray()); } else //WOLOLO! ERRORS! - { - General.ErrorLogger.Add(ErrorType.Error, "Unable to copy Universal Field '" + f.Key + "' to clipboard: unknown value type '" + f.Value.Type + "'!"); + { + General.ErrorLogger.Add(ErrorType.Error, "Unable to copy Universal Field \"" + f.Key + "\" to clipboard: unknown value type \"" + f.Value.Type + "\"!"); } } } diff --git a/Source/Core/IO/Configuration.cs b/Source/Core/IO/Configuration.cs index d5008d2..9eb36e9 100644 --- a/Source/Core/IO/Configuration.cs +++ b/Source/Core/IO/Configuration.cs @@ -804,7 +804,8 @@ namespace CodeImp.DoomBuilder.IO case "true": return true; case "false": return false; case "null": return null; - default: RaiseError(file, line, ERROR_KEYWORDUNKNOWN + "\nUnrecognized token: '" + val.Trim().ToLowerInvariant() + "'"); return null; + default: RaiseError(file, line, ERROR_KEYWORDUNKNOWN + "\nUnrecognized token: \"" + val.Trim().ToLowerInvariant() + "\""); + return null; } } } @@ -860,7 +861,7 @@ namespace CodeImp.DoomBuilder.IO } else { - RaiseError(file, line, "Include missing structure '" + args[1] + "' in file '" + includefile + "'"); + RaiseError(file, line, "Include missing structure \"" + args[1] + "\" in file \"" + includefile + "\""); return; } } @@ -885,7 +886,7 @@ namespace CodeImp.DoomBuilder.IO } catch(Exception e) { - RaiseError(file, line, "Unable to include file '" + includefile + "'. " + e.GetType().Name + ": " + e.Message); + RaiseError(file, line, "Unable to include file \"" + includefile + "\". " + e.GetType().Name + ": " + e.Message); return; } @@ -915,7 +916,7 @@ namespace CodeImp.DoomBuilder.IO } else { - RaiseError(file, line, "Include missing structure '" + args[1] + "' in file '" + includefile + "'"); + RaiseError(file, line, "Include missing structure \"" + args[1] + "\" in file \"" + includefile + "\""); return; } } diff --git a/Source/Core/IO/UniversalEntry.cs b/Source/Core/IO/UniversalEntry.cs index a69b948..d08d1b4 100644 --- a/Source/Core/IO/UniversalEntry.cs +++ b/Source/Core/IO/UniversalEntry.cs @@ -60,7 +60,7 @@ namespace CodeImp.DoomBuilder.IO // Will throw and exception when it is not public void ValidateType(Type t) { - if(value.GetType() != t) throw new Exception("The value of entry '" + key + "' is of incompatible type (expected " + t.Name + ")"); + if(value.GetType() != t) throw new Exception("The value of entry \"" + key + "\" is of incompatible type (expected " + t.Name + ")"); } //mxd diff --git a/Source/Core/IO/UniversalParser.cs b/Source/Core/IO/UniversalParser.cs index 6a88152..cd4fa47 100644 --- a/Source/Core/IO/UniversalParser.cs +++ b/Source/Core/IO/UniversalParser.cs @@ -414,13 +414,13 @@ namespace CodeImp.DoomBuilder.IO catch(FormatException) { // ERROR: Invalid value in assignment - RaiseError(line, ERROR_VALUEINVALID + "\n\nUnrecognized token: '" + s.Trim() + "'"); + RaiseError(line, ERROR_VALUEINVALID + "\n\nUnrecognized token: \"" + s.Trim() + "\""); } } catch(FormatException) { // ERROR: Invalid value in assignment - RaiseError(line, ERROR_VALUEINVALID + "\n\nUnrecognized token: '" + s.Trim() + "'"); + RaiseError(line, ERROR_VALUEINVALID + "\n\nUnrecognized token: \"" + s.Trim() + "\""); } } // Floating point? @@ -434,7 +434,7 @@ namespace CodeImp.DoomBuilder.IO catch(FormatException) { // ERROR: Invalid value in assignment - RaiseError(line, ERROR_VALUEINVALID + "\n\nUnrecognized token: '" + s.Trim() + "'"); + RaiseError(line, ERROR_VALUEINVALID + "\n\nUnrecognized token: \"" + s.Trim() + "\""); } // Add it to struct @@ -476,13 +476,13 @@ namespace CodeImp.DoomBuilder.IO catch(FormatException) { // ERROR: Invalid value in assignment - RaiseError(line, ERROR_VALUEINVALID + "\n\nUnrecognized token: '" + s.Trim() + "'"); + RaiseError(line, ERROR_VALUEINVALID + "\n\nUnrecognized token: \"" + s.Trim() + "\""); } } catch(FormatException) { // ERROR: Invalid value in assignment - RaiseError(line, ERROR_VALUEINVALID + "\n\nUnrecognized token: '" + s.Trim() + "'"); + RaiseError(line, ERROR_VALUEINVALID + "\n\nUnrecognized token: \"" + s.Trim() + "\""); } } @@ -533,7 +533,7 @@ namespace CodeImp.DoomBuilder.IO catch(FormatException) { // ERROR: Invalid value in assignment - RaiseError(line, ERROR_VALUEINVALID + "\n\nUnrecognized token: '" + v.Trim() + "'"); + RaiseError(line, ERROR_VALUEINVALID + "\n\nUnrecognized token: \"" + v.Trim() + "\""); } // Convert the number to a char @@ -541,7 +541,7 @@ namespace CodeImp.DoomBuilder.IO catch(FormatException) { // ERROR: Invalid value in assignment - RaiseError(line, ERROR_VALUEINVALID + "\n\nUnrecognized token: '" + v.Trim() + "'"); + RaiseError(line, ERROR_VALUEINVALID + "\n\nUnrecognized token: \"" + v.Trim() + "\""); } // Add the char @@ -623,7 +623,7 @@ namespace CodeImp.DoomBuilder.IO default: // Unknown keyword - RaiseError(line, ERROR_KEYWORDUNKNOWN + "\n\nUnrecognized token: '" + val.ToString().Trim() + "'"); + RaiseError(line, ERROR_KEYWORDUNKNOWN + "\n\nUnrecognized token: \"" + val.ToString().Trim() + "\""); break; } diff --git a/Source/Core/IO/UniversalStreamReader.cs b/Source/Core/IO/UniversalStreamReader.cs index b506246..c52666a 100644 --- a/Source/Core/IO/UniversalStreamReader.cs +++ b/Source/Core/IO/UniversalStreamReader.cs @@ -494,7 +494,7 @@ namespace CodeImp.DoomBuilder.IO } else if(!e.IsValidType(e.Value.GetType())) { - General.ErrorLogger.Add(ErrorType.Warning, element + ": the value of entry '" + e.Key + "' is of incompatible type (expected " + e.GetType().Name + ", but got " + e.Value.GetType().Name + "). If you save the map, this value will be ignored."); + General.ErrorLogger.Add(ErrorType.Warning, element + ": the value of entry \"" + e.Key + "\" is of incompatible type (expected " + e.GetType().Name + ", but got " + e.Value.GetType().Name + "). If you save the map, this value will be ignored."); continue; } @@ -522,7 +522,7 @@ namespace CodeImp.DoomBuilder.IO } else if(!e.IsValidType(e.Value.GetType())) { - General.ErrorLogger.Add(ErrorType.Warning, element + ": the value of entry '" + e.Key + "' is of incompatible type (expected " + e.GetType().Name + ", but got " + e.Value.GetType().Name + "). If you save the map, this value will be ignored."); + General.ErrorLogger.Add(ErrorType.Warning, element + ": the value of entry \"" + e.Key + "\" is of incompatible type (expected " + e.GetType().Name + ", but got " + e.Value.GetType().Name + "). If you save the map, this value will be ignored."); continue; } @@ -582,7 +582,7 @@ namespace CodeImp.DoomBuilder.IO { // Report error when entry is required! if(required) - General.ErrorLogger.Add(ErrorType.Error, "Error while reading UDMF map data: Missing required field '" + entryname + "' at " + where + "."); + General.ErrorLogger.Add(ErrorType.Error, "Error while reading UDMF map data: Missing required field \"" + entryname + "\" at " + where + "."); // Make default entry result = defaultvalue; diff --git a/Source/Core/Map/MapSet.cs b/Source/Core/Map/MapSet.cs index ef6300a..07a8f3f 100644 --- a/Source/Core/Map/MapSet.cs +++ b/Source/Core/Map/MapSet.cs @@ -2721,7 +2721,7 @@ namespace CodeImp.DoomBuilder.Map { float px = t.Position.x; float py = t.Position.y; - float ts = ((t.FixedSize && General.Map.Renderer2D.Scale > 1.0f) ? t.Size / General.Map.Renderer2D.Scale : t.Size); + float ts = (((t.FixedSize || General.Settings.FixedThingsScale) && General.Map.Renderer2D.Scale > 1.0f) ? t.Size / General.Map.Renderer2D.Scale : t.Size); //mxd. Within range? if(px < range.Left - ts || px > range.Right + ts || py < range.Top - ts || py > range.Bottom + ts) continue; diff --git a/Source/Core/Plugins/Plugin.cs b/Source/Core/Plugins/Plugin.cs index 3c54801..536f6e0 100644 --- a/Source/Core/Plugins/Plugin.cs +++ b/Source/Core/Plugins/Plugin.cs @@ -66,7 +66,7 @@ namespace CodeImp.DoomBuilder.Plugins // Initialize string shortfilename = Path.GetFileName(filename); name = Path.GetFileNameWithoutExtension(filename); - General.WriteLogLine("Loading plugin '" + name + "' from '" + shortfilename + "'..."); + General.WriteLogLine("Loading plugin \"" + name + "\" from \"" + shortfilename + "\"..."); try { @@ -218,7 +218,7 @@ namespace CodeImp.DoomBuilder.Plugins catch(TargetInvocationException e) { // Error! - string error = "Failed to create class instance '" + t.Name + "' from plugin '" + name + "'."; + string error = "Failed to create class instance \"" + t.Name + "\" from plugin \"" + name + "\"."; General.ShowErrorMessage(error + Environment.NewLine + Environment.NewLine + "See the error log for more details", MessageBoxButtons.OK, false); General.WriteLogLine(error + " " + e.InnerException.GetType().Name + " at target: " + e.InnerException.Message + Environment.NewLine + "Stacktrace: " + e.InnerException.StackTrace.Trim()); @@ -227,7 +227,7 @@ namespace CodeImp.DoomBuilder.Plugins catch(Exception e) { // Error! - string error = "Failed to create class instance '" + t.Name + "' from plugin '" + name + "'."; + string error = "Failed to create class instance \"" + t.Name + "\" from plugin \"" + name + "\"."; General.ShowErrorMessage(error + Environment.NewLine + Environment.NewLine + "See the error log for more details", MessageBoxButtons.OK, false); General.WriteLogLine(error + " " + e.GetType().Name + ": " + e.Message + Environment.NewLine + "Stacktrace: " + e.StackTrace.Trim()); diff --git a/Source/Core/Properties/Resources.Designer.cs b/Source/Core/Properties/Resources.Designer.cs index 57be92f..a6f6670 100644 --- a/Source/Core/Properties/Resources.Designer.cs +++ b/Source/Core/Properties/Resources.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // -// Dieser Code wurde von einem Tool generiert. -// Laufzeitversion:4.0.30319.42000 +// This code was generated by a tool. +// Runtime Version:2.0.50727.5466 // // Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn // der Code erneut generiert wird. @@ -370,9 +370,13 @@ namespace CodeImp.DoomBuilder.Properties { } } - /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. - /// + internal static System.Drawing.Bitmap FixedThingsScale { + get { + object obj = ResourceManager.GetObject("FixedThingsScale", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + internal static System.Drawing.Bitmap fog { get { object obj = ResourceManager.GetObject("fog", resourceCulture); diff --git a/Source/Core/Properties/Resources.resx b/Source/Core/Properties/Resources.resx index 7ac990d..46ad6a9 100644 --- a/Source/Core/Properties/Resources.resx +++ b/Source/Core/Properties/Resources.resx @@ -574,4 +574,7 @@ ..\Resources\ScriptProperty.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\FixedThingsScale.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/Source/Core/Rendering/D3DDevice.cs b/Source/Core/Rendering/D3DDevice.cs index a4fa7c8..888dfb1 100644 --- a/Source/Core/Rendering/D3DDevice.cs +++ b/Source/Core/Rendering/D3DDevice.cs @@ -168,8 +168,8 @@ namespace CodeImp.DoomBuilder.Rendering device.SetRenderState(RenderState.NormalizeNormals, false); device.SetRenderState(RenderState.PointSpriteEnable, false); device.SetRenderState(RenderState.RangeFogEnable, false); - device.SetRenderState(RenderState.ShadeMode, ShadeMode.Flat); //mxd - device.SetRenderState(RenderState.SourceBlend, Blend.SourceAlpha); + device.SetRenderState(RenderState.ShadeMode, ShadeMode.Gouraud); + device.SetRenderState(RenderState.SourceBlend, Blend.SourceAlpha); device.SetRenderState(RenderState.SpecularEnable, false); device.SetRenderState(RenderState.StencilEnable, false); device.SetRenderState(RenderState.TextureFactor, -1); diff --git a/Source/Core/Rendering/IRenderer2D.cs b/Source/Core/Rendering/IRenderer2D.cs index deae50f..6ae6863 100644 --- a/Source/Core/Rendering/IRenderer2D.cs +++ b/Source/Core/Rendering/IRenderer2D.cs @@ -74,6 +74,7 @@ namespace CodeImp.DoomBuilder.Rendering void RenderRectangleFilled(RectangleF rect, PixelColor c, bool transformrect, ImageData texture); void RenderLine(Vector2D start, Vector2D end, float thickness, PixelColor c, bool transformcoords); void RenderArrows(ICollection line); //mxd + void RenderArrows(ICollection line, bool transformcoords); //mxd void RenderText(TextLabel text); void RenderGeometry(FlatVertex[] vertices, ImageData texture, bool transformcoords); void RenderHighlight(FlatVertex[] vertices, int color); //mxd diff --git a/Source/Core/Rendering/Renderer2D.cs b/Source/Core/Rendering/Renderer2D.cs index e92ce23..e5e5ad8 100644 --- a/Source/Core/Rendering/Renderer2D.cs +++ b/Source/Core/Rendering/Renderer2D.cs @@ -250,7 +250,6 @@ namespace CodeImp.DoomBuilder.Rendering // BACKGROUND case RendererLayer.Background: if((backimageverts == null) || (General.Map.Grid.Background.Texture == null)) break; - graphics.Device.SetTexture(0, General.Map.Grid.Background.Texture); graphics.Shaders.Display2D.Texture1 = General.Map.Grid.Background.Texture; graphics.Shaders.Display2D.SetSettings(1f / windowsize.Width, 1f / windowsize.Height, FSAA_FACTOR, layer.alpha, false); graphics.Shaders.Display2D.BeginPass(aapass); @@ -261,7 +260,6 @@ namespace CodeImp.DoomBuilder.Rendering // GRID case RendererLayer.Grid: - graphics.Device.SetTexture(0, backtex); graphics.Shaders.Display2D.Texture1 = backtex; graphics.Shaders.Display2D.SetSettings(1f / backsize.Width, 1f / backsize.Height, FSAA_FACTOR, layer.alpha, false); graphics.Shaders.Display2D.BeginPass(aapass); @@ -271,7 +269,6 @@ namespace CodeImp.DoomBuilder.Rendering // GEOMETRY case RendererLayer.Geometry: - graphics.Device.SetTexture(0, plottertex); graphics.Shaders.Display2D.Texture1 = plottertex; graphics.Shaders.Display2D.SetSettings(1f / structsize.Width, 1f / structsize.Height, FSAA_FACTOR, layer.alpha, false); graphics.Shaders.Display2D.BeginPass(aapass); @@ -281,7 +278,6 @@ namespace CodeImp.DoomBuilder.Rendering // THINGS case RendererLayer.Things: - graphics.Device.SetTexture(0, thingstex); graphics.Shaders.Display2D.Texture1 = thingstex; graphics.Shaders.Display2D.SetSettings(1f / thingssize.Width, 1f / thingssize.Height, FSAA_FACTOR, layer.alpha, false); graphics.Shaders.Display2D.BeginPass(aapass); @@ -291,7 +287,6 @@ namespace CodeImp.DoomBuilder.Rendering // OVERLAY case RendererLayer.Overlay: - graphics.Device.SetTexture(0, overlaytex); graphics.Shaders.Display2D.Texture1 = overlaytex; graphics.Shaders.Display2D.SetSettings(1f / overlaysize.Width, 1f / overlaysize.Height, FSAA_FACTOR, layer.alpha, false); graphics.Shaders.Display2D.BeginPass(aapass); @@ -301,7 +296,6 @@ namespace CodeImp.DoomBuilder.Rendering // SURFACE case RendererLayer.Surface: - graphics.Device.SetTexture(0, surfacetex); graphics.Shaders.Display2D.Texture1 = surfacetex; graphics.Shaders.Display2D.SetSettings(1f / overlaysize.Width, 1f / overlaysize.Height, FSAA_FACTOR, layer.alpha, false); graphics.Shaders.Display2D.BeginPass(aapass); @@ -317,7 +311,6 @@ namespace CodeImp.DoomBuilder.Rendering graphics.Present(); // Release binds - graphics.Device.SetTexture(0, null); graphics.Shaders.Display2D.Texture1 = null; graphics.Device.SetStreamSource(0, null, 0, 0); } @@ -985,20 +978,22 @@ namespace CodeImp.DoomBuilder.Rendering // This makes vertices for a thing // Returns false when not on the screen - private bool CreateThingBoxVerts(Thing t, ref FlatVertex[] verts, Dictionary thingsByPosition, int offset, PixelColor c) + private bool CreateThingBoxVerts(Thing t, ref FlatVertex[] verts, ref List bboxes, Dictionary thingsByPosition, int offset, PixelColor c, byte bboxalpha) { float thingsize = General.Settings.DrawThingsFixedSize ? General.Settings.DefaultThingSize : t.Size; if(thingsize * scale < MINIMUM_THING_RADIUS) return false; //mxd. Don't render tiny little things - // Determine size - float circlesize = (t.FixedSize && (scale > 1.0f) ? thingsize /* * THING_CIRCLE_SIZE*/ : thingsize * scale /* * THING_CIRCLE_SIZE*/); + // Determine sizes + float circlesize = ((t.FixedSize || General.Settings.FixedThingsScale) && (scale > 1.0f) ? t.Size : t.Size * scale); + float bboxsize = ((!t.FixedSize && General.Settings.FixedThingsScale) && (scale > 1.0f) ? t.Size * scale : -1); //mxd + float screensize = Math.Max(circlesize, bboxsize); //mxd // Transform to screen coordinates Vector2D screenpos = ((Vector2D)t.Position).GetTransformed(translatex, translatey, scale, -scale); // Check if the thing is actually on screen - if(((screenpos.x + circlesize) <= 0.0f) || ((screenpos.x - circlesize) >= windowsize.Width) || - ((screenpos.y + circlesize) <= 0.0f) || ((screenpos.y - circlesize) >= windowsize.Height)) + if(((screenpos.x + screensize) <= 0.0f) || ((screenpos.x - screensize) >= windowsize.Width) || + ((screenpos.y + screensize) <= 0.0f) || ((screenpos.y - screensize) >= windowsize.Height)) return false; // Get integral color @@ -1036,6 +1031,22 @@ namespace CodeImp.DoomBuilder.Rendering //mxd. Add to list thingsByPosition.Add(t, screenpos); + //mxd. Add bounding box? + if(bboxsize > 0) + { + PixelColor boxcolor = c.WithAlpha(bboxalpha); + + Vector2D tl = new Vector2D(screenpos.x - bboxsize, screenpos.y - bboxsize); + Vector2D tr = new Vector2D(screenpos.x + bboxsize, screenpos.y - bboxsize); + Vector2D bl = new Vector2D(screenpos.x - bboxsize, screenpos.y + bboxsize); + Vector2D br = new Vector2D(screenpos.x + bboxsize, screenpos.y + bboxsize); + + bboxes.Add(new Line3D(tl, tr, boxcolor, false)); + bboxes.Add(new Line3D(tr, br, boxcolor, false)); + bboxes.Add(new Line3D(bl, br, boxcolor, false)); + bboxes.Add(new Line3D(tl, bl, boxcolor, false)); + } + // Done return true; } @@ -1045,10 +1056,10 @@ namespace CodeImp.DoomBuilder.Rendering { // Determine size float thingsize = General.Settings.DrawThingsFixedSize ? General.Settings.DefaultThingSize : t.Size; - float arrowsize = (t.FixedSize && (scale > 1.0f) ? thingsize : thingsize * scale) * THING_ARROW_SIZE; //mxd + float arrowsize = ((t.FixedSize || General.Settings.FixedThingsScale) && (scale > 1.0f) ? t.Size : t.Size * scale) * THING_ARROW_SIZE; //mxd - // Setup rotated rect for arrow - float sinarrowsize = (float)Math.Sin(t.Angle + Angle2D.PI * 0.25f) * arrowsize; + // Setup rotated rect for arrow + float sinarrowsize = (float)Math.Sin(t.Angle + Angle2D.PI * 0.25f) * arrowsize; float cosarrowsize = (float)Math.Cos(t.Angle + Angle2D.PI * 0.25f) * arrowsize; verts[offset].x = screenpos.x + sinarrowsize; @@ -1123,6 +1134,7 @@ namespace CodeImp.DoomBuilder.Rendering // Make alpha color Color4 alphacolor = new Color4(alpha, 1.0f, 1.0f, 1.0f); + bool isthingsmode = (General.Editing.Mode.GetType().Name == "ThingsMode"); // Set renderstates for things rendering graphics.Device.SetRenderState(RenderState.CullMode, Cull.None); @@ -1136,7 +1148,6 @@ namespace CodeImp.DoomBuilder.Rendering graphics.Device.SetStreamSource(0, thingsvertices, 0, FlatVertex.Stride); // Set things texture - graphics.Device.SetTexture(0, thingtexture.Texture); graphics.Shaders.Things2D.Texture1 = thingtexture.Texture; SetWorldTransformation(false); graphics.Shaders.Things2D.SetSettings(alpha); @@ -1148,6 +1159,7 @@ namespace CodeImp.DoomBuilder.Rendering // Determine next lock size int locksize = (things.Count > THING_BUFFER_SIZE) ? THING_BUFFER_SIZE : things.Count; FlatVertex[] verts = new FlatVertex[THING_BUFFER_SIZE * 6]; + List bboxes = new List(locksize); //mxd //mxd Dictionary> thingsByType = new Dictionary>(); @@ -1171,7 +1183,8 @@ namespace CodeImp.DoomBuilder.Rendering // Create vertices PixelColor tc = fixedcolor ? c : DetermineThingColor(t); - if(CreateThingBoxVerts(t, ref verts, thingsByPosition, buffercount * 6, tc)) + byte bboxalpha = (byte)(alpha * ((!fixedcolor && !t.Selected && isthingsmode) ? 128 : 255)); + if(CreateThingBoxVerts(t, ref verts, ref bboxes, thingsByPosition, buffercount * 6, tc, bboxalpha)) { buffercount++; @@ -1234,8 +1247,8 @@ namespace CodeImp.DoomBuilder.Rendering } if(sprite.Texture == null) sprite.CreateTexture(); - graphics.Device.SetTexture(0, sprite.Texture); graphics.Shaders.Things2D.Texture1 = sprite.Texture; + graphics.Shaders.Things2D.ApplySettings(); // Determine next lock size locksize = (group.Value.Count > THING_BUFFER_SIZE) ? THING_BUFFER_SIZE : group.Value.Count; @@ -1246,7 +1259,7 @@ namespace CodeImp.DoomBuilder.Rendering totalcount = 0; float spriteWidth, spriteHeight; - float spriteScale = (group.Value[0].FixedSize && (scale > 1.0f)) ? 1.0f : scale; + float spriteScale = ((group.Value[0].FixedSize || General.Settings.FixedThingsScale) && (scale > 1.0f)) ? 1.0f : scale; float radius = General.Settings.DrawThingsFixedSize ? General.Settings.DefaultThingSize : info.Radius; if(sprite.Width > sprite.Height) @@ -1310,7 +1323,6 @@ namespace CodeImp.DoomBuilder.Rendering graphics.Shaders.Things2D.EndPass(); //mxd. Render thing arrows - graphics.Device.SetTexture(0, thingtexture.Texture); graphics.Shaders.Things2D.Texture1 = thingtexture.Texture; graphics.Shaders.Things2D.BeginPass(0); @@ -1418,6 +1430,9 @@ namespace CodeImp.DoomBuilder.Rendering } graphics.Shaders.Things2D.End(); + + //mxd. Render thing boxes + RenderArrows(bboxes, false); } } @@ -1625,7 +1640,6 @@ namespace CodeImp.DoomBuilder.Rendering graphics.Device.SetRenderState(RenderState.TextureFactor, -1); graphics.Device.SetRenderState(RenderState.FogEnable, false); graphics.Shaders.Display2D.Texture1 = t; - graphics.Device.SetTexture(0, t); SetWorldTransformation(transformcoords); graphics.Shaders.Display2D.SetSettings(1f, 1f, 0f, 1f, General.Settings.ClassicBilinear); @@ -1682,7 +1696,6 @@ namespace CodeImp.DoomBuilder.Rendering graphics.Shaders.Display2D.Texture1 = graphics.FontTexture; SetWorldTransformation(false); graphics.Shaders.Display2D.SetSettings(1f, 1f, 0f, 1f, true); - graphics.Device.SetTexture(0, graphics.FontTexture); graphics.Device.SetStreamSource(0, text.VertexBuffer, 0, FlatVertex.Stride); // Draw @@ -1745,7 +1758,6 @@ namespace CodeImp.DoomBuilder.Rendering graphics.Device.SetRenderState(RenderState.TextureFactor, -1); graphics.Device.SetRenderState(RenderState.FogEnable, false); SetWorldTransformation(false); - graphics.Device.SetTexture(0, General.Map.Data.WhiteTexture.Texture); graphics.Shaders.Display2D.Texture1 = General.Map.Data.WhiteTexture.Texture; graphics.Shaders.Display2D.SetSettings(1f, 1f, 0f, 1f, General.Settings.ClassicBilinear); @@ -1784,7 +1796,6 @@ namespace CodeImp.DoomBuilder.Rendering graphics.Device.SetRenderState(RenderState.TextureFactor, -1); graphics.Device.SetRenderState(RenderState.FogEnable, false); SetWorldTransformation(false); - graphics.Device.SetTexture(0, General.Map.Data.WhiteTexture.Texture); graphics.Shaders.Display2D.Texture1 = General.Map.Data.WhiteTexture.Texture; graphics.Shaders.Display2D.SetSettings(1f, 1f, 0f, 1f, General.Settings.ClassicBilinear); @@ -1820,7 +1831,6 @@ namespace CodeImp.DoomBuilder.Rendering graphics.Device.SetRenderState(RenderState.TextureFactor, -1); graphics.Device.SetRenderState(RenderState.FogEnable, false); SetWorldTransformation(false); - graphics.Device.SetTexture(0, texture.Texture); graphics.Shaders.Display2D.Texture1 = texture.Texture; graphics.Shaders.Display2D.SetSettings(1f, 1f, 0f, 1f, General.Settings.ClassicBilinear); @@ -1833,7 +1843,8 @@ namespace CodeImp.DoomBuilder.Rendering } //mxd - public void RenderArrows(ICollection lines) + public void RenderArrows(ICollection lines) { RenderArrows(lines, true); } + public void RenderArrows(ICollection lines, bool transformcoords) { if(lines.Count == 0) return; int pointscount = 0; @@ -1841,9 +1852,12 @@ namespace CodeImp.DoomBuilder.Rendering // Translate to screen coords, determine renderability foreach(Line3D line in lines) { - // Calculate screen positions - line.Start2D = ((Vector2D)line.Start).GetTransformed(translatex, translatey, scale, -scale); //start - line.End2D = ((Vector2D)line.End).GetTransformed(translatex, translatey, scale, -scale); //end + // Calculate screen positions? + if(transformcoords) + { + line.Start2D = ((Vector2D)line.Start).GetTransformed(translatex, translatey, scale, -scale); //start + line.End2D = ((Vector2D)line.End).GetTransformed(translatex, translatey, scale, -scale); //end + } float maxx = Math.Max(line.Start2D.x, line.End2D.x); float minx = Math.Min(line.Start2D.x, line.End2D.x); @@ -1922,7 +1936,6 @@ namespace CodeImp.DoomBuilder.Rendering graphics.Device.SetRenderState(RenderState.TextureFactor, -1); graphics.Device.SetRenderState(RenderState.FogEnable, false); SetWorldTransformation(false); - graphics.Device.SetTexture(0, General.Map.Data.WhiteTexture.Texture); graphics.Shaders.Display2D.Texture1 = General.Map.Data.WhiteTexture.Texture; graphics.Shaders.Display2D.SetSettings(1f, 1f, 0f, 1f, General.Settings.ClassicBilinear); @@ -1999,7 +2012,6 @@ namespace CodeImp.DoomBuilder.Rendering graphics.Device.SetRenderState(RenderState.TextureFactor, -1); graphics.Device.SetRenderState(RenderState.FogEnable, false); SetWorldTransformation(false); - graphics.Device.SetTexture(0, General.Map.Data.WhiteTexture.Texture); graphics.Shaders.Display2D.Texture1 = General.Map.Data.WhiteTexture.Texture; graphics.Shaders.Display2D.SetSettings(1f, 1f, 0f, 1f, General.Settings.ClassicBilinear); diff --git a/Source/Core/Rendering/Renderer3D.cs b/Source/Core/Rendering/Renderer3D.cs index 1cb9e59..2c723f9 100644 --- a/Source/Core/Rendering/Renderer3D.cs +++ b/Source/Core/Rendering/Renderer3D.cs @@ -1874,13 +1874,11 @@ namespace CodeImp.DoomBuilder.Rendering if(crosshairbusy) { if(General.Map.Data.CrosshairBusy3D.Texture == null) General.Map.Data.CrosshairBusy3D.CreateTexture(); - graphics.Device.SetTexture(0, General.Map.Data.CrosshairBusy3D.Texture); graphics.Shaders.Display2D.Texture1 = General.Map.Data.CrosshairBusy3D.Texture; } else { if(General.Map.Data.Crosshair3D.Texture == null) General.Map.Data.Crosshair3D.CreateTexture(); - graphics.Device.SetTexture(0, General.Map.Data.Crosshair3D.Texture); graphics.Shaders.Display2D.Texture1 = General.Map.Data.Crosshair3D.Texture; } diff --git a/Source/Core/Resources/Actions.cfg b/Source/Core/Resources/Actions.cfg index 5c4bb6d..61a629e 100644 --- a/Source/Core/Resources/Actions.cfg +++ b/Source/Core/Resources/Actions.cfg @@ -1037,6 +1037,16 @@ togglecomments //mxd allowscroll = false; } +togglefixedthingsscale //mxd +{ + title = "Toggle Fixed Things Scale"; + category = "view"; + description = "When enabled, Things will no longer be scaled based on current zoom level in Classic modes."; + allowkeys = true; + allowmouse = false; + allowscroll = false; +} + togglebrightness //mxd { title = "Toggle Full Brightness"; diff --git a/Source/Core/Resources/FixedThingsScale.png b/Source/Core/Resources/FixedThingsScale.png new file mode 100644 index 0000000000000000000000000000000000000000..b94d1acfa5e05dfa73f72709313f50e6ec602796 GIT binary patch literal 1595 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+nAI{vB1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxOgGuU%v{0TQqR!T z+}y-mN5ROz&{W^RSl`${*T~q)#K6kLNC66zfVLH-q*(>IxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8E%gnI^o@*kfhu&1EAvVcD|GXUm0>2hq!uR^WfqiV=I1GZOiWD5 zFD$Tv3bSNU;+l1ennz|zM-B0$V)JVzP|XC=H|jx7ncO3BHWAB;NpiyW)Z+ZoqGVvir744~DzI`cN=+=uFAB-e&w+(vKt_H^esM;Afr7I$IMft0!ZY(y z^2>`g!FqgstvvIJOA_;vQ$1a5m4K$`WoD*Wxwsj+xtN)|xLBH*8ydQrIvN_8Ihz_d zIT|^+8ap|g!t}c2Czs}?=9R$orXcjX;?xUD4!H$Dn_W_iGRsm^+=}vZ6~NxM%Eav! zC!FR%^`_uxWXgOCJonyL+(ry*Rn{oZ4{g$nD2IXv(-#K zHV)~KiOPT9-C3Qyg7f2wj_w8xP4C7ByPkiIbf57qSS#|Zs!Y1+!xeP}n;&0Wd6&Jf zeD+z33`553KvwNcPMzuIHD3ZBusz+gC`P>Sld))^NU%ld#B2M~dv!~{F!H%~Z*i7fZKB_Qz9_;99Ev*60D`9D4;elU0RP`0t{xoYmOxO{Se3S&Tu+w+(E z8SLi9eK^e~Q53Pphfnd@?B=VXyvOf}S!D4a4%;d}Nkeg~5kH5`|LF}9yk}fR(n1U( zXC-V~ul|Fitt@>!peje&n^n4bi%`T|gK N?&<31vd$@?2>?X0VY&bS literal 0 HcmV?d00001 diff --git a/Source/Core/Types/AngleDegreesFloatHandler.cs b/Source/Core/Types/AngleDegreesFloatHandler.cs index 82b074a..47f3588 100644 --- a/Source/Core/Types/AngleDegreesFloatHandler.cs +++ b/Source/Core/Types/AngleDegreesFloatHandler.cs @@ -102,6 +102,11 @@ namespace CodeImp.DoomBuilder.Types return this.value.ToString(); } + public override object GetDefaultValue() + { + return 0f; + } + #endregion } } diff --git a/Source/Core/Types/AngleDegreesHandler.cs b/Source/Core/Types/AngleDegreesHandler.cs index ec4e7c9..0120c0c 100644 --- a/Source/Core/Types/AngleDegreesHandler.cs +++ b/Source/Core/Types/AngleDegreesHandler.cs @@ -101,6 +101,11 @@ namespace CodeImp.DoomBuilder.Types return this.value.ToString(); } + public override object GetDefaultValue() + { + return 0; + } + #endregion } } diff --git a/Source/Core/Types/AngleRadiansHandler.cs b/Source/Core/Types/AngleRadiansHandler.cs index 57a9315..dee4904 100644 --- a/Source/Core/Types/AngleRadiansHandler.cs +++ b/Source/Core/Types/AngleRadiansHandler.cs @@ -102,6 +102,11 @@ namespace CodeImp.DoomBuilder.Types return this.value.ToString(); } + public override object GetDefaultValue() + { + return 0f; + } + #endregion } } diff --git a/Source/Core/Types/BoolHandler.cs b/Source/Core/Types/BoolHandler.cs index 0b3f369..d70d48e 100644 --- a/Source/Core/Types/BoolHandler.cs +++ b/Source/Core/Types/BoolHandler.cs @@ -93,7 +93,7 @@ namespace CodeImp.DoomBuilder.Types public override int GetIntValue() { - if(this.value) return 1; else return 0; + return (this.value ? 1 : 0); } public override string GetStringValue() @@ -106,6 +106,11 @@ namespace CodeImp.DoomBuilder.Types { return list; } + + public override object GetDefaultValue() + { + return false; + } #endregion } diff --git a/Source/Core/Types/ColorHandler.cs b/Source/Core/Types/ColorHandler.cs index 37f7ac9..b48c6e7 100644 --- a/Source/Core/Types/ColorHandler.cs +++ b/Source/Core/Types/ColorHandler.cs @@ -113,6 +113,11 @@ namespace CodeImp.DoomBuilder.Types return this.value.ToString("X6"); } + public override object GetDefaultValue() + { + return 0; + } + #endregion } } diff --git a/Source/Core/Types/EnumBitsHandler.cs b/Source/Core/Types/EnumBitsHandler.cs index c392bf5..267e7ab 100644 --- a/Source/Core/Types/EnumBitsHandler.cs +++ b/Source/Core/Types/EnumBitsHandler.cs @@ -38,7 +38,7 @@ namespace CodeImp.DoomBuilder.Types private EnumList list; private int value; - private int defaultValue; //mxd + private int defaultvalue; //mxd #endregion @@ -55,7 +55,7 @@ namespace CodeImp.DoomBuilder.Types // When set up for an argument public override void SetupArgument(TypeHandlerAttribute attr, ArgumentInfo arginfo) { - defaultValue = (int)arginfo.DefaultValue;//mxd + defaultvalue = (int)arginfo.DefaultValue;//mxd base.SetupArgument(attr, arginfo); // Keep enum list reference @@ -100,9 +100,9 @@ namespace CodeImp.DoomBuilder.Types } //mxd - public override void SetDefaultValue() + public override void ApplyDefaultValue() { - value = defaultValue; + value = defaultvalue; } public override object GetValue() @@ -120,6 +120,11 @@ namespace CodeImp.DoomBuilder.Types return this.value.ToString(); } + public override object GetDefaultValue() + { + return defaultvalue; + } + #endregion } } diff --git a/Source/Core/Types/EnumOptionHandler.cs b/Source/Core/Types/EnumOptionHandler.cs index 30184b1..1ce9ce3 100644 --- a/Source/Core/Types/EnumOptionHandler.cs +++ b/Source/Core/Types/EnumOptionHandler.cs @@ -140,7 +140,7 @@ namespace CodeImp.DoomBuilder.Types } //mxd - public override void SetDefaultValue() + public override void ApplyDefaultValue() { value = defaultvalue; } @@ -189,6 +189,11 @@ namespace CodeImp.DoomBuilder.Types { return General.Types.GetAttribute((int)UniversalType.Integer); } + + public override object GetDefaultValue() + { + return defaultvalue; + } #endregion } diff --git a/Source/Core/Types/EnumStringsHandler.cs b/Source/Core/Types/EnumStringsHandler.cs index 0ad1d6d..7503166 100644 --- a/Source/Core/Types/EnumStringsHandler.cs +++ b/Source/Core/Types/EnumStringsHandler.cs @@ -34,7 +34,7 @@ namespace CodeImp.DoomBuilder.Types private EnumList list; private EnumItem value; - private EnumItem defaultValue; //mxd + private EnumItem defaultvalue; //mxd #endregion @@ -50,7 +50,7 @@ namespace CodeImp.DoomBuilder.Types // When set up for an argument public override void SetupArgument(TypeHandlerAttribute attr, ArgumentInfo arginfo) { - defaultValue = new EnumItem(arginfo.DefaultValue.ToString(), arginfo.DefaultValue.ToString()); //mxd + defaultvalue = new EnumItem(arginfo.DefaultValue.ToString(), arginfo.DefaultValue.ToString()); //mxd base.SetupArgument(attr, arginfo); // Keep enum list reference @@ -121,9 +121,9 @@ namespace CodeImp.DoomBuilder.Types } //mxd - public override void SetDefaultValue() + public override void ApplyDefaultValue() { - value = defaultValue; + value = defaultvalue; } public override object GetValue() @@ -171,6 +171,11 @@ namespace CodeImp.DoomBuilder.Types return General.Types.GetAttribute((int)UniversalType.String); } + public override object GetDefaultValue() + { + return defaultvalue; + } + #endregion } } diff --git a/Source/Core/Types/FlatHandler.cs b/Source/Core/Types/FlatHandler.cs index 339ac1f..4aa4036 100644 --- a/Source/Core/Types/FlatHandler.cs +++ b/Source/Core/Types/FlatHandler.cs @@ -70,6 +70,11 @@ namespace CodeImp.DoomBuilder.Types return this.value; } + public override object GetDefaultValue() + { + return string.Empty; + } + #endregion } } diff --git a/Source/Core/Types/FloatHandler.cs b/Source/Core/Types/FloatHandler.cs index 4cb05ed..67ab905 100644 --- a/Source/Core/Types/FloatHandler.cs +++ b/Source/Core/Types/FloatHandler.cs @@ -85,6 +85,11 @@ namespace CodeImp.DoomBuilder.Types return this.value.ToString(); } + public override object GetDefaultValue() + { + return 0f; + } + #endregion } } diff --git a/Source/Core/Types/IntegerHandler.cs b/Source/Core/Types/IntegerHandler.cs index c6fab35..0760e92 100644 --- a/Source/Core/Types/IntegerHandler.cs +++ b/Source/Core/Types/IntegerHandler.cs @@ -34,7 +34,7 @@ namespace CodeImp.DoomBuilder.Types #region ================== Variables private int value; - private int defaultValue; //mxd + private int defaultvalue; //mxd #endregion @@ -47,7 +47,7 @@ namespace CodeImp.DoomBuilder.Types //mxd public override void SetupArgument(TypeHandlerAttribute attr, ArgumentInfo arginfo) { - defaultValue = (int)arginfo.DefaultValue; + defaultvalue = (int)arginfo.DefaultValue; base.SetupArgument(attr, arginfo); } @@ -85,9 +85,9 @@ namespace CodeImp.DoomBuilder.Types } //mxd - public override void SetDefaultValue() + public override void ApplyDefaultValue() { - value = defaultValue; + value = defaultvalue; } public override object GetValue() @@ -104,6 +104,11 @@ namespace CodeImp.DoomBuilder.Types { return this.value.ToString(); } + + public override object GetDefaultValue() + { + return defaultvalue; + } #endregion } diff --git a/Source/Core/Types/LinedefTypeHandler.cs b/Source/Core/Types/LinedefTypeHandler.cs index db7c5b9..ee1cd52 100644 --- a/Source/Core/Types/LinedefTypeHandler.cs +++ b/Source/Core/Types/LinedefTypeHandler.cs @@ -101,6 +101,11 @@ namespace CodeImp.DoomBuilder.Types return this.value.ToString(); } + public override object GetDefaultValue() + { + return 0; + } + #endregion } } diff --git a/Source/Core/Types/NullHandler.cs b/Source/Core/Types/NullHandler.cs index 2de10e8..3e5b87a 100644 --- a/Source/Core/Types/NullHandler.cs +++ b/Source/Core/Types/NullHandler.cs @@ -62,6 +62,11 @@ namespace CodeImp.DoomBuilder.Types { return this.value.ToString(); } + + public override object GetDefaultValue() + { + return 0; + } #endregion } diff --git a/Source/Core/Types/RandomFloatHandler.cs b/Source/Core/Types/RandomFloatHandler.cs index 0d26774..b3b3832 100644 --- a/Source/Core/Types/RandomFloatHandler.cs +++ b/Source/Core/Types/RandomFloatHandler.cs @@ -18,7 +18,7 @@ namespace CodeImp.DoomBuilder.Types #region ================== Variables private float value; - private bool randomValue; + private bool randomvalue; private float min; private float max; @@ -77,7 +77,7 @@ namespace CodeImp.DoomBuilder.Types if(float.TryParse(parts[0], NumberStyles.Float, CultureInfo.CurrentCulture, out min) && float.TryParse(parts[1], NumberStyles.Float, CultureInfo.CurrentCulture, out max)) { - randomValue = (min != max); + randomvalue = (min != max); if(min == max) this.value = min; else if(min > max) General.Swap(ref min, ref max); @@ -91,22 +91,27 @@ namespace CodeImp.DoomBuilder.Types public override object GetValue() { - if(randomValue) return General.Random(min, max); //mxd + if(randomvalue) return General.Random(min, max); //mxd return this.value; } public override int GetIntValue() { - if(randomValue) return (int)General.Random(min, max); //mxd + if(randomvalue) return (int)General.Random(min, max); //mxd return (int)this.value; } public override string GetStringValue() { - if(randomValue) return General.Random(min, max).ToString(CultureInfo.InvariantCulture); //mxd + if(randomvalue) return General.Random(min, max).ToString(CultureInfo.InvariantCulture); //mxd return this.value.ToString(CultureInfo.InvariantCulture); } + public override object GetDefaultValue() + { + return 0f; + } + #endregion } } diff --git a/Source/Core/Types/RandomIntegerHandler.cs b/Source/Core/Types/RandomIntegerHandler.cs index 208168d..3b63513 100644 --- a/Source/Core/Types/RandomIntegerHandler.cs +++ b/Source/Core/Types/RandomIntegerHandler.cs @@ -14,8 +14,8 @@ namespace CodeImp.DoomBuilder.Types #region ================== Variables private int value; - private int defaultValue; - private bool randomValue; + private int defaultvalue; + private bool randomvalue; private int min; private int max; @@ -29,7 +29,7 @@ namespace CodeImp.DoomBuilder.Types public override void SetupArgument(TypeHandlerAttribute attr, ArgumentInfo arginfo) { - defaultValue = (int)arginfo.DefaultValue; + defaultvalue = (int)arginfo.DefaultValue; base.SetupArgument(attr, arginfo); //mxd. We don't want to store this type @@ -74,7 +74,7 @@ namespace CodeImp.DoomBuilder.Types if(int.TryParse(parts[0], NumberStyles.Integer, CultureInfo.CurrentCulture, out min) && int.TryParse(parts[1], NumberStyles.Integer, CultureInfo.CurrentCulture, out max)) { - randomValue = (min != max); + randomvalue = (min != max); if(min == max) this.value = min; else if(min > max) General.Swap(ref min, ref max); } @@ -89,29 +89,34 @@ namespace CodeImp.DoomBuilder.Types } //mxd - public override void SetDefaultValue() + public override void ApplyDefaultValue() { - value = defaultValue; + value = defaultvalue; } public override object GetValue() { - if(randomValue) return General.Random(min, max); //mxd + if(randomvalue) return General.Random(min, max); //mxd return this.value; } public override int GetIntValue() { - if(randomValue) return General.Random(min, max); //mxd + if(randomvalue) return General.Random(min, max); //mxd return this.value; } public override string GetStringValue() { - if(randomValue) return General.Random(min, max).ToString(CultureInfo.InvariantCulture); //mxd + if(randomvalue) return General.Random(min, max).ToString(CultureInfo.InvariantCulture); //mxd return this.value.ToString(CultureInfo.InvariantCulture); } + public override object GetDefaultValue() + { + return defaultvalue; + } + #endregion } } diff --git a/Source/Core/Types/SectorEffectHandler.cs b/Source/Core/Types/SectorEffectHandler.cs index af18f9b..dd342eb 100644 --- a/Source/Core/Types/SectorEffectHandler.cs +++ b/Source/Core/Types/SectorEffectHandler.cs @@ -101,6 +101,11 @@ namespace CodeImp.DoomBuilder.Types return this.value.ToString(); } + public override object GetDefaultValue() + { + return 0; + } + #endregion } } diff --git a/Source/Core/Types/SectorTagHandler.cs b/Source/Core/Types/SectorTagHandler.cs index 3f680fa..79eed31 100644 --- a/Source/Core/Types/SectorTagHandler.cs +++ b/Source/Core/Types/SectorTagHandler.cs @@ -170,7 +170,7 @@ namespace CodeImp.DoomBuilder.Types } //mxd - public override void SetDefaultValue() + public override void ApplyDefaultValue() { value = defaultvalue; } @@ -197,6 +197,11 @@ namespace CodeImp.DoomBuilder.Types return (this.value != null ? this.value.Title : "0: No Tag"); } + public override object GetDefaultValue() + { + return defaultvalue; + } + // This returns an enum list public override EnumList GetEnumList() { diff --git a/Source/Core/Types/StringHandler.cs b/Source/Core/Types/StringHandler.cs index 9f08dd3..e4cee5b 100644 --- a/Source/Core/Types/StringHandler.cs +++ b/Source/Core/Types/StringHandler.cs @@ -68,8 +68,7 @@ namespace CodeImp.DoomBuilder.Types public override int GetIntValue() { int result; - if(int.TryParse(this.value, out result)) return result; - else return 0; + return (int.TryParse(this.value, out result) ? result : 0); } public override string GetStringValue() @@ -77,6 +76,11 @@ namespace CodeImp.DoomBuilder.Types return this.value; } + public override object GetDefaultValue() + { + return string.Empty; + } + #endregion } } diff --git a/Source/Core/Types/TextureHandler.cs b/Source/Core/Types/TextureHandler.cs index 5f338fe..9d89c6a 100644 --- a/Source/Core/Types/TextureHandler.cs +++ b/Source/Core/Types/TextureHandler.cs @@ -70,6 +70,11 @@ namespace CodeImp.DoomBuilder.Types return this.value; } + public override object GetDefaultValue() + { + return string.Empty; + } + #endregion } } diff --git a/Source/Core/Types/ThingClassHandler.cs b/Source/Core/Types/ThingClassHandler.cs index 34663f2..6eb9660 100644 --- a/Source/Core/Types/ThingClassHandler.cs +++ b/Source/Core/Types/ThingClassHandler.cs @@ -91,6 +91,11 @@ namespace CodeImp.DoomBuilder.Types return this.value; } + public override object GetDefaultValue() + { + return string.Empty; + } + #endregion } } diff --git a/Source/Core/Types/ThingTypeHandler.cs b/Source/Core/Types/ThingTypeHandler.cs index 9751c5c..41f5a44 100644 --- a/Source/Core/Types/ThingTypeHandler.cs +++ b/Source/Core/Types/ThingTypeHandler.cs @@ -101,6 +101,11 @@ namespace CodeImp.DoomBuilder.Types return this.value.ToString(); } + public override object GetDefaultValue() + { + return 0; + } + #endregion } } diff --git a/Source/Core/Types/TypeHandler.cs b/Source/Core/Types/TypeHandler.cs index db6ad47..d8f9d50 100644 --- a/Source/Core/Types/TypeHandler.cs +++ b/Source/Core/Types/TypeHandler.cs @@ -120,11 +120,14 @@ namespace CodeImp.DoomBuilder.Types public abstract void SetValue(object value); //mxd. This should replace current value with the default one - public virtual void SetDefaultValue() { } + public virtual void ApplyDefaultValue() { } // This must return the value as one of the primitive data types // supported by UDMF: int, string, float or bool public abstract object GetValue(); + + //mxd. This should return the default value + public abstract object GetDefaultValue(); // This must return the value as integer (for arguments) public virtual int GetIntValue() @@ -136,9 +139,7 @@ namespace CodeImp.DoomBuilder.Types public abstract string GetStringValue(); // This is called when the user presses the browse button - public virtual void Browse(IWin32Window parent) - { - } + public virtual void Browse(IWin32Window parent) { } // This must returns an enum list when IsEnumerable is true public virtual EnumList GetEnumList() diff --git a/Source/Core/Windows/AboutForm.cs b/Source/Core/Windows/AboutForm.cs index d18f72a..cb63115 100644 --- a/Source/Core/Windows/AboutForm.cs +++ b/Source/Core/Windows/AboutForm.cs @@ -67,8 +67,7 @@ namespace CodeImp.DoomBuilder.Windows // This copies the version number to clipboard private void copyversion_Click(object sender, EventArgs e) { - Clipboard.Clear(); - Clipboard.SetText(Application.ProductVersion); + Clipboard.SetDataObject(Application.ProductVersion, true, 5, 200); //mxd } } } \ No newline at end of file diff --git a/Source/Core/Windows/ActionBrowserForm.cs b/Source/Core/Windows/ActionBrowserForm.cs index 8ec6458..71a890e 100644 --- a/Source/Core/Windows/ActionBrowserForm.cs +++ b/Source/Core/Windows/ActionBrowserForm.cs @@ -36,16 +36,20 @@ namespace CodeImp.DoomBuilder.Windows private readonly ComboBox[] options; private readonly Label[] optionlbls; private readonly TreeNode[] allNodes; //mxd + private readonly bool addanyaction; //mxd // Properties public int SelectedAction { get { return selectedaction; } } // Constructor - public ActionBrowserForm(int action) + public ActionBrowserForm(int action, bool addanyaction) { // Initialize InitializeComponent(); + //mxd. Show "Any action" item? + this.addanyaction = addanyaction; + // Make array references for controls options = new[] { option0, option1, option2, option3, option4, option5, option6, option7 }; optionlbls = new[] { option0label, option1label, option2label, option3label, option4label, @@ -94,12 +98,24 @@ namespace CodeImp.DoomBuilder.Windows foreach(GeneralizedBit ab in sc.Options[i].Bits) { // Select this setting if matches - if((actionbits & ab.Index) == ab.Index) options[i].SelectedItem = ab; + if((actionbits & ab.Index) == ab.Index) + { + options[i].SelectedItem = ab; + if(ab.Index > 0) break; //mxd + } } } + else + { + break; //mxd + } } } } + + //mxd. Make sure something is selected + if(category.SelectedIndex == -1 && category.Items.Count > 0) + category.SelectedIndex = 0; } else { @@ -110,9 +126,10 @@ namespace CodeImp.DoomBuilder.Windows // This browses for an action // Returns the new action or the same action when cancelled - public static int BrowseAction(IWin32Window owner, int action) + public static int BrowseAction(IWin32Window owner, int action) { return BrowseAction(owner, action, false); } //mxd + public static int BrowseAction(IWin32Window owner, int action, bool addanyaction) { - ActionBrowserForm f = new ActionBrowserForm(action); + ActionBrowserForm f = new ActionBrowserForm(action, addanyaction); if(f.ShowDialog(owner) == DialogResult.OK) action = f.SelectedAction; f.Dispose(); return action; @@ -123,6 +140,19 @@ namespace CodeImp.DoomBuilder.Windows { actions.BeginUpdate(); actions.ShowLines = true; + + // Add "Any action" item? + if(addanyaction) + { + TreeNode aan = actions.Nodes.Add("Any action"); + aan.Tag = new LinedefActionInfo(-1, "Any action", false, false); + if(action == -1) + { + actions.SelectedNode = aan; + aan.EnsureVisible(); + } + } + foreach(LinedefActionCategory ac in General.Map.Config.ActionCategories) { // Empty category names will not be created @@ -162,24 +192,40 @@ namespace CodeImp.DoomBuilder.Windows } //mxd - private void FilterActions(string p) + private void FilterActions(string text) { - List filteredNodes = new List(); + List filterednodes = new List(); + HashSet added = new HashSet(StringComparer.OrdinalIgnoreCase); + // First add nodes, which titles start with given text foreach(TreeNode n in allNodes) { foreach(TreeNode cn in n.Nodes) { LinedefActionInfo ai = cn.Tag as LinedefActionInfo; - if(ai.Title.ToLowerInvariant().IndexOf(p) != -1) - filteredNodes.Add(cn); + if(ai != null && ai.Title.ToUpperInvariant().StartsWith(text)) + { + filterednodes.Add(cn); + added.Add(ai.Title); + } + } + } + + // Then add nodes, which titles contain given text + foreach(TreeNode n in allNodes) + { + foreach(TreeNode cn in n.Nodes) + { + LinedefActionInfo ai = cn.Tag as LinedefActionInfo; + if(ai != null && !added.Contains(ai.Title) && ai.Title.ToUpperInvariant().Contains(text)) + filterednodes.Add(cn); } } actions.BeginUpdate(); actions.Nodes.Clear(); actions.ShowLines = false; - actions.Nodes.AddRange(filteredNodes.ToArray()); + actions.Nodes.AddRange(filterednodes.ToArray()); actions.EndUpdate(); } @@ -292,7 +338,7 @@ namespace CodeImp.DoomBuilder.Windows { if(!string.IsNullOrEmpty(tbFilter.Text.Trim())) { - FilterActions(tbFilter.Text); + FilterActions(tbFilter.Text.ToUpperInvariant()); } else { diff --git a/Source/Core/Windows/ChangeMapForm.cs b/Source/Core/Windows/ChangeMapForm.cs index 522c4b6..bd3a62c 100644 --- a/Source/Core/Windows/ChangeMapForm.cs +++ b/Source/Core/Windows/ChangeMapForm.cs @@ -180,7 +180,7 @@ namespace CodeImp.DoomBuilder.Windows // Current map is already loaded if(mapslist.SelectedItems[0].Text == options.LevelName) { - MessageBox.Show(this, "Map '" + options.LevelName + "' is already loaded.", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Warning); + MessageBox.Show(this, "Map \"" + options.LevelName + "\" is already loaded.", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Warning); mapslist.Focus(); return; } diff --git a/Source/Core/Windows/ConfigForm.cs b/Source/Core/Windows/ConfigForm.cs index bc76e83..f1e806c 100644 --- a/Source/Core/Windows/ConfigForm.cs +++ b/Source/Core/Windows/ConfigForm.cs @@ -402,7 +402,7 @@ namespace CodeImp.DoomBuilder.Windows ci = listconfigs.Items[i].Tag as ConfigurationInfo; if(!ci.Resources.IsValid()) { - MessageBox.Show(this, "At least one resource doesn't exist in '" + ci.Name + "' game configuration!", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Warning); + MessageBox.Show(this, "At least one resource doesn't exist in \"" + ci.Name + "\" game configuration!", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Warning); tabs.SelectedTab = tabresources; listconfigs.Focus(); listconfigs.Items[i].Selected = true; @@ -871,7 +871,7 @@ namespace CodeImp.DoomBuilder.Windows configinfocopy = current.Clone(); //display info - General.Interface.DisplayStatus(StatusType.Info, "Copied '" + configinfocopy.Name + "' game configuration"); + General.Interface.DisplayStatus(StatusType.Info, "Copied \"" + configinfocopy.Name + "\" game configuration"); } private void pasteall_Click(object sender, EventArgs e) @@ -885,7 +885,7 @@ namespace CodeImp.DoomBuilder.Windows //update display cbEngineSelector.Text = string.Empty; // Otherwise current text from cbEngineSelector will override the pasted one listconfigs_SelectedIndexChanged(listconfigs, EventArgs.Empty); - General.Interface.DisplayStatus(StatusType.Info, "Pasted game configuration from '" + configinfocopy.Name + "'"); + General.Interface.DisplayStatus(StatusType.Info, "Pasted game configuration from \"" + configinfocopy.Name + "\""); } private void pasteresources_Click(object sender, EventArgs e) @@ -898,7 +898,7 @@ namespace CodeImp.DoomBuilder.Windows //update display listconfigs_SelectedIndexChanged(listconfigs, EventArgs.Empty); - General.Interface.DisplayStatus(StatusType.Info, "Pasted resources from '" + configinfocopy.Name + "'"); + General.Interface.DisplayStatus(StatusType.Info, "Pasted resources from \"" + configinfocopy.Name + "\""); } private void pasteengines_Click(object sender, EventArgs e) @@ -912,7 +912,7 @@ namespace CodeImp.DoomBuilder.Windows //update display cbEngineSelector.Text = string.Empty; // Otherwise current text from cbEngineSelector will override the pasted one listconfigs_SelectedIndexChanged(listconfigs, EventArgs.Empty); - General.Interface.DisplayStatus(StatusType.Info, "Pasted engines list from '" + configinfocopy.Name + "'"); + General.Interface.DisplayStatus(StatusType.Info, "Pasted engines list from \"" + configinfocopy.Name + "\""); } private void pastecolorpresets_Click(object sender, EventArgs e) @@ -925,7 +925,7 @@ namespace CodeImp.DoomBuilder.Windows //update display listconfigs_SelectedIndexChanged(listconfigs, EventArgs.Empty); - General.Interface.DisplayStatus(StatusType.Info, "Pasted color presets from '" + configinfocopy.Name + "'"); + General.Interface.DisplayStatus(StatusType.Info, "Pasted color presets from \"" + configinfocopy.Name + "\""); } #endregion diff --git a/Source/Core/Windows/EffectBrowserForm.cs b/Source/Core/Windows/EffectBrowserForm.cs index 0c8d166..e29d2a5 100644 --- a/Source/Core/Windows/EffectBrowserForm.cs +++ b/Source/Core/Windows/EffectBrowserForm.cs @@ -33,28 +33,31 @@ namespace CodeImp.DoomBuilder.Windows // Variables private int selectedeffect; - private ComboBox[] options; - private Label[] optionlbls; - private ListViewItem[] allItems; //mxd + private readonly ComboBox[] options; + private readonly ListViewItem[] allitems; //mxd + private readonly bool addanyeffect; // Properties public int SelectedEffect { get { return selectedeffect; } } // Constructor - public EffectBrowserForm(int effect) + public EffectBrowserForm(int effect, bool addanyeffect) { // Initialize InitializeComponent(); + //mxd. Show "Any action" item? + this.addanyeffect = addanyeffect; + // Make array references for controls options = new[] { option0, option1, option2, option3, option4, option5, option6, option7 }; - optionlbls = new[] { option0label, option1label, option2label, option3label, option4label, - option5label, option6label, option7label }; + Label[] optionlbls = { option0label, option1label, option2label, option3label, + option4label, option5label, option6label, option7label }; // Go for all predefined effects bool selected = CreateEffects(effect); //mxd - allItems = new ListViewItem[effects.Items.Count]; //mxd - effects.Items.CopyTo(allItems, 0); //mxd + allitems = new ListViewItem[effects.Items.Count]; //mxd + effects.Items.CopyTo(allitems, 0); //mxd // Using generalized effects? if(General.Map.Config.GeneralizedEffects) @@ -82,7 +85,11 @@ namespace CodeImp.DoomBuilder.Windows foreach(GeneralizedBit ab in o.Bits) { // Select this setting if matches - if((effect & ab.Index) == ab.Index) options[i].SelectedItem = ab; + if((effect & ab.Index) == ab.Index) + { + options[i].SelectedItem = ab; + if(ab.Index > 0) break; //mxd + } } } } @@ -106,9 +113,10 @@ namespace CodeImp.DoomBuilder.Windows // This browses for an effect // Returns the new effect or the same effect when cancelled - public static int BrowseEffect(IWin32Window owner, int effect) + public static int BrowseEffect(IWin32Window owner, int effect) { return BrowseEffect(owner, effect, false); } //mxd + public static int BrowseEffect(IWin32Window owner, int effect, bool addanyeffect) { - EffectBrowserForm f = new EffectBrowserForm(effect); + EffectBrowserForm f = new EffectBrowserForm(effect, addanyeffect); if(f.ShowDialog(owner) == DialogResult.OK) effect = f.SelectedEffect; f.Dispose(); return effect; @@ -119,6 +127,18 @@ namespace CodeImp.DoomBuilder.Windows { bool selected = false; + if(addanyeffect) + { + ListViewItem n = effects.Items.Add("-1"); + n.SubItems.Add("Any effect"); + n.Tag = new SectorEffectInfo(-1, "Any effect", false, false); + if(effect == -1) + { + selected = true; + n.Selected = true; + } + } + foreach(SectorEffectInfo si in General.Map.Config.SortedSectorEffects) { // Create effect @@ -135,20 +155,36 @@ namespace CodeImp.DoomBuilder.Windows } //mxd - private void FilterEffects(string p) + private void FilterEffects(string text) { - List filteredItems = new List(); + List filtereditems = new List(); + HashSet added = new HashSet(StringComparer.OrdinalIgnoreCase); - foreach(ListViewItem i in allItems) + // First add nodes, which titles start with given text + foreach(ListViewItem i in allitems) { SectorEffectInfo si = i.Tag as SectorEffectInfo; - if(si.Title.ToLowerInvariant().IndexOf(p) != -1) - filteredItems.Add(i); + if(si != null && si.Title.ToUpperInvariant().StartsWith(text)) + { + filtereditems.Add(i); + added.Add(si.Title); + } + } + + // Then add nodes, which titles contain given text + foreach(ListViewItem i in allitems) + { + SectorEffectInfo si = i.Tag as SectorEffectInfo; + if(si != null && !added.Contains(si.Title) && si.Title.ToUpperInvariant().Contains(text)) + { + filtereditems.Add(i); + added.Add(si.Title); + } } effects.BeginUpdate(); effects.Items.Clear(); - effects.Items.AddRange(filteredItems.ToArray()); + effects.Items.AddRange(filtereditems.ToArray()); effects.EndUpdate(); } @@ -181,6 +217,10 @@ namespace CodeImp.DoomBuilder.Windows if(options[i].SelectedIndex > -1) selectedeffect += (options[i].SelectedItem as GeneralizedBit).Index; } + else + { + break; //mxd + } } } @@ -212,7 +252,7 @@ namespace CodeImp.DoomBuilder.Windows { if(!string.IsNullOrEmpty(tbFilter.Text.Trim())) { - FilterEffects(tbFilter.Text); + FilterEffects(tbFilter.Text.ToUpperInvariant()); } else { diff --git a/Source/Core/Windows/GridSetupForm.cs b/Source/Core/Windows/GridSetupForm.cs index a86778c..5eecedc 100644 --- a/Source/Core/Windows/GridSetupForm.cs +++ b/Source/Core/Windows/GridSetupForm.cs @@ -140,8 +140,18 @@ namespace CodeImp.DoomBuilder.Windows // Apply private void apply_Click(object sender, EventArgs e) { + //mxd. Apply + int newgridsize = gridsize.GetResult(General.Map.Grid.GridSize); + if(newgridsize != General.Map.Grid.GridSize) + { + //Disable automatic grid resizing + General.MainWindow.DisableDynamicGridResize(); + + //Apply grid size + General.Map.Grid.SetGridSize(newgridsize); + } + // Apply - General.Map.Grid.SetGridSize(gridsize.GetResult(General.Map.Grid.GridSize)); General.Map.Grid.SetBackgroundView(backoffsetx.GetResult(General.Map.Grid.BackgroundX), backoffsety.GetResult(General.Map.Grid.BackgroundY), backscalex.GetResult((int)(General.Map.Grid.BackgroundScaleX * 100.0f)) / 100.0f, diff --git a/Source/Core/Windows/IMainForm.cs b/Source/Core/Windows/IMainForm.cs index 2b6c7a0..0754b00 100644 --- a/Source/Core/Windows/IMainForm.cs +++ b/Source/Core/Windows/IMainForm.cs @@ -87,12 +87,24 @@ namespace CodeImp.DoomBuilder.Windows /// /// Returns the new action or the same action when cancelled int BrowseLinedefActions(IWin32Window owner, int initialvalue); - + + /// + /// This browses the lindef types + /// + /// Returns the new action or the same action when cancelled + int BrowseLinedefActions(IWin32Window owner, int initialvalue, bool addanyaction); + /// /// This browses sector effects /// /// Returns the new effect or the same effect when cancelled int BrowseSectorEffect(IWin32Window owner, int initialvalue); + + /// + /// This browses sector effects + /// + /// Returns the new effect or the same effect when cancelled + int BrowseSectorEffect(IWin32Window owner, int initialvalue, bool addanyeffect); /// /// This browses for a texture diff --git a/Source/Core/Windows/LinedefColorPresetsForm.cs b/Source/Core/Windows/LinedefColorPresetsForm.cs index dd746db..0eb0014 100644 --- a/Source/Core/Windows/LinedefColorPresetsForm.cs +++ b/Source/Core/Windows/LinedefColorPresetsForm.cs @@ -180,7 +180,7 @@ namespace CodeImp.DoomBuilder.Windows if(gotmismatch) continue; //we have a match - warning = "Preset matches '" + other.Preset.Name + "'!"; + warning = "Preset matches \"" + other.Preset.Name + "\"!"; item.ShowWarning = true; break; } diff --git a/Source/Core/Windows/LinedefEditForm.Designer.cs b/Source/Core/Windows/LinedefEditForm.Designer.cs index 37f9414..c25230b 100644 --- a/Source/Core/Windows/LinedefEditForm.Designer.cs +++ b/Source/Core/Windows/LinedefEditForm.Designer.cs @@ -47,6 +47,8 @@ namespace CodeImp.DoomBuilder.Windows this.backside = new System.Windows.Forms.CheckBox(); this.frontside = new System.Windows.Forms.CheckBox(); this.frontgroup = new System.Windows.Forms.GroupBox(); + this.replaceunusedfronttextures = new System.Windows.Forms.CheckBox(); + this.replaceunusedbacktextures = new System.Windows.Forms.CheckBox(); this.labelFrontTextureOffset = new System.Windows.Forms.Label(); this.frontsector = new CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox(); this.frontlow = new CodeImp.DoomBuilder.Controls.TextureSelectorControl(); @@ -100,6 +102,7 @@ namespace CodeImp.DoomBuilder.Windows // // label5 // + label5.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(204))); label5.Location = new System.Drawing.Point(437, 13); label5.Name = "label5"; label5.Size = new System.Drawing.Size(83, 16); @@ -109,6 +112,7 @@ namespace CodeImp.DoomBuilder.Windows // // label4 // + label4.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(204))); label4.Location = new System.Drawing.Point(346, 13); label4.Name = "label4"; label4.Size = new System.Drawing.Size(83, 16); @@ -118,6 +122,7 @@ namespace CodeImp.DoomBuilder.Windows // // label3 // + label3.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(204))); label3.Location = new System.Drawing.Point(255, 13); label3.Name = "label3"; label3.Size = new System.Drawing.Size(83, 16); @@ -136,6 +141,7 @@ namespace CodeImp.DoomBuilder.Windows // // label8 // + label8.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(204))); label8.Location = new System.Drawing.Point(437, 13); label8.Name = "label8"; label8.Size = new System.Drawing.Size(83, 16); @@ -154,6 +160,7 @@ namespace CodeImp.DoomBuilder.Windows // // label10 // + label3.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(204))); label10.Location = new System.Drawing.Point(255, 13); label10.Name = "label10"; label10.Size = new System.Drawing.Size(83, 16); @@ -257,6 +264,7 @@ namespace CodeImp.DoomBuilder.Windows // this.frontgroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); + this.frontgroup.Controls.Add(this.replaceunusedfronttextures); this.frontgroup.Controls.Add(this.labelFrontTextureOffset); this.frontgroup.Controls.Add(this.frontsector); this.frontgroup.Controls.Add(label11); @@ -275,6 +283,18 @@ namespace CodeImp.DoomBuilder.Windows this.frontgroup.TabStop = false; this.frontgroup.Text = " "; // + // replaceunusedfronttextures + // + this.replaceunusedfronttextures.AutoSize = true; + this.replaceunusedfronttextures.Location = new System.Drawing.Point(90, 121); + this.replaceunusedfronttextures.Name = "replaceunusedfronttextures"; + this.replaceunusedfronttextures.Size = new System.Drawing.Size(144, 17); + this.replaceunusedfronttextures.TabIndex = 43; + this.replaceunusedfronttextures.Text = "Replace unused textures"; + this.replaceunusedfronttextures.UseVisualStyleBackColor = true; + this.replaceunusedfronttextures.CheckedChanged += new System.EventHandler(this.replaceunusedfronttextures_CheckedChanged); + // + // // labelFrontTextureOffset // this.labelFrontTextureOffset.Location = new System.Drawing.Point(6, 70); @@ -354,6 +374,7 @@ namespace CodeImp.DoomBuilder.Windows // this.backgroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); + this.backgroup.Controls.Add(this.replaceunusedbacktextures); this.backgroup.Controls.Add(this.labelBackTextureOffset); this.backgroup.Controls.Add(this.backsector); this.backgroup.Controls.Add(label12); @@ -372,6 +393,18 @@ namespace CodeImp.DoomBuilder.Windows this.backgroup.TabStop = false; this.backgroup.Text = " "; // + // replaceunusedbacktextures + // + this.replaceunusedbacktextures.AutoSize = true; + this.replaceunusedbacktextures.Location = new System.Drawing.Point(90, 121); + this.replaceunusedbacktextures.Name = "replaceunusedbacktextures"; + this.replaceunusedbacktextures.Size = new System.Drawing.Size(144, 17); + this.replaceunusedbacktextures.TabIndex = 44; + this.replaceunusedbacktextures.Text = "Replace unused textures"; + this.replaceunusedbacktextures.UseVisualStyleBackColor = true; + this.replaceunusedbacktextures.CheckedChanged += new System.EventHandler(this.replaceunusedbacktextures_CheckedChanged); + // + // // labelBackTextureOffset // this.labelBackTextureOffset.Location = new System.Drawing.Point(6, 70); @@ -625,5 +658,7 @@ namespace CodeImp.DoomBuilder.Windows private System.Windows.Forms.Label labelFrontTextureOffset; private System.Windows.Forms.Label labelBackTextureOffset; private CodeImp.DoomBuilder.Controls.ArgumentsControl argscontrol; + private System.Windows.Forms.CheckBox replaceunusedfronttextures; + private System.Windows.Forms.CheckBox replaceunusedbacktextures; } } \ No newline at end of file diff --git a/Source/Core/Windows/LinedefEditForm.cs b/Source/Core/Windows/LinedefEditForm.cs index dcf617a..2a09b16 100644 --- a/Source/Core/Windows/LinedefEditForm.cs +++ b/Source/Core/Windows/LinedefEditForm.cs @@ -65,20 +65,20 @@ namespace CodeImp.DoomBuilder.Windows public readonly int OffsetX; public readonly int OffsetY; - public readonly string TextureTop; - public readonly string TextureMid; - public readonly string TextureLow; + public readonly string HighTexture; + public readonly string MiddleTexture; + public readonly string LowTexture; public SidedefProperties(Sidedef side) { - //offset + // Offset OffsetX = side.OffsetX; OffsetY = side.OffsetY; - //textures - TextureTop = side.HighTexture; - TextureMid = side.MiddleTexture; - TextureLow = side.LowTexture; + // Textures + HighTexture = side.HighTexture; + MiddleTexture = side.MiddleTexture; + LowTexture = side.LowTexture; } } @@ -149,6 +149,12 @@ namespace CodeImp.DoomBuilder.Windows apply.Top = panel.Bottom + panel.Margin.Bottom + apply.Margin.Top; cancel.Top = apply.Top; + //mxd. Apply texture replacement settings + preventchanges = true; + replaceunusedfronttextures.Checked = General.Settings.ReadSetting("editlinedefswindow.replaceunusedfronttextures", true); + replaceunusedbacktextures.Checked = General.Settings.ReadSetting("editlinedefswindow.replaceunusedbacktextures", true); + preventchanges = false; + // Update window height this.Height = apply.Bottom + apply.Margin.Bottom * 2 + (this.Height - this.ClientRectangle.Height) + 1; } @@ -285,22 +291,22 @@ namespace CodeImp.DoomBuilder.Windows if(l.Front != null) { //mxd - if(fronthigh.TextureName != l.Front.HighTexture) + if(!string.IsNullOrEmpty(fronthigh.TextureName) && fronthigh.TextureName != l.Front.HighTexture) { if(!fronthigh.Required && l.Front.HighRequired()) fronthigh.Required = true; - fronthigh.MultipleTextures = true; //mxd + fronthigh.MultipleTextures = true; fronthigh.TextureName = string.Empty; } - if(frontmid.TextureName != l.Front.MiddleTexture) + if(!string.IsNullOrEmpty(frontmid.TextureName) && frontmid.TextureName != l.Front.MiddleTexture) { if(!frontmid.Required && l.Front.MiddleRequired()) frontmid.Required = true; - frontmid.MultipleTextures = true; //mxd + frontmid.MultipleTextures = true; frontmid.TextureName = string.Empty; } - if(frontlow.TextureName != l.Front.LowTexture) + if(!string.IsNullOrEmpty(frontlow.TextureName) && frontlow.TextureName != l.Front.LowTexture) { if(!frontlow.Required && l.Front.LowRequired()) frontlow.Required = true; - frontlow.MultipleTextures = true; //mxd + frontlow.MultipleTextures = true; frontlow.TextureName = string.Empty; } if(frontsector.Text != l.Front.Sector.Index.ToString()) frontsector.Text = string.Empty; @@ -312,22 +318,22 @@ namespace CodeImp.DoomBuilder.Windows if(l.Back != null) { //mxd - if(backhigh.TextureName != l.Back.HighTexture) + if(!string.IsNullOrEmpty(backhigh.TextureName) && backhigh.TextureName != l.Back.HighTexture) { if(!backhigh.Required && l.Back.HighRequired()) backhigh.Required = true; - backhigh.MultipleTextures = true; //mxd + backhigh.MultipleTextures = true; backhigh.TextureName = string.Empty; } - if(backmid.TextureName != l.Back.MiddleTexture) + if(!string.IsNullOrEmpty(backmid.TextureName) && backmid.TextureName != l.Back.MiddleTexture) { if(!backmid.Required && l.Back.MiddleRequired()) backmid.Required = true; - backmid.MultipleTextures = true; //mxd + backmid.MultipleTextures = true; backmid.TextureName = string.Empty; } - if(backlow.TextureName != l.Back.LowTexture) + if(!string.IsNullOrEmpty(backlow.TextureName) && backlow.TextureName != l.Back.LowTexture) { if(!backlow.Required && l.Back.LowRequired()) backlow.Required = true; - backlow.MultipleTextures = true; //mxd + backlow.MultipleTextures = true; backlow.TextureName = string.Empty; } if(backsector.Text != l.Back.Sector.Index.ToString()) backsector.Text = string.Empty; @@ -593,7 +599,12 @@ namespace CodeImp.DoomBuilder.Windows //mxd. Store window location private void LinedefEditForm_FormClosing(object sender, FormClosingEventArgs e) { + // Save location location = this.Location; + + // Save persistent settings + General.Settings.WriteSetting("editlinedefswindow.replaceunusedfronttextures", replaceunusedfronttextures.Checked); + General.Settings.WriteSetting("editlinedefswindow.replaceunusedbacktextures", replaceunusedbacktextures.Checked); } // Help! @@ -659,24 +670,31 @@ namespace CodeImp.DoomBuilder.Windows private void fronthigh_OnValueChanged(object sender, EventArgs e) { if(preventchanges) return; - MakeUndo(); //mxd + MakeUndo(); - //restore values + // Restore values if(string.IsNullOrEmpty(fronthigh.TextureName)) { int i = 0; - foreach(Linedef l in lines) { - if(l.Front != null) l.Front.SetTextureHigh(linedefprops[i].Front != null ? linedefprops[i].Front.TextureTop : "-"); + if(l.Front != null) l.Front.SetTextureHigh(linedefprops[i].Front != null ? linedefprops[i].Front.HighTexture : "-"); i++; } - - } - else //update values + } + // Update values + else { - foreach(Linedef l in lines) - if(l.Front != null) l.Front.SetTextureHigh(fronthigh.GetResult(l.Front.HighTexture)); + int i = 0; + foreach(Linedef l in lines) + { + if(l.Front != null + && (replaceunusedfronttextures.Checked + || (l.Front.HighRequired() + || (linedefprops[i].Front != null && linedefprops[i].Front.HighTexture != "-")))) + l.Front.SetTextureHigh(fronthigh.GetResult(l.Front.HighTexture)); + i++; + } } // Update the used textures @@ -689,24 +707,31 @@ namespace CodeImp.DoomBuilder.Windows private void frontmid_OnValueChanged(object sender, EventArgs e) { if(preventchanges) return; - MakeUndo(); //mxd + MakeUndo(); - //restore values + // Restore values if(string.IsNullOrEmpty(frontmid.TextureName)) { int i = 0; - foreach(Linedef l in lines) { - if(l.Front != null) l.Front.SetTextureMid(linedefprops[i].Front != null ? linedefprops[i].Front.TextureMid : "-"); + if(l.Front != null) l.Front.SetTextureMid(linedefprops[i].Front != null ? linedefprops[i].Front.MiddleTexture : "-"); i++; } - - } - else //update values + } + // Update values + else { - foreach(Linedef l in lines) - if(l.Front != null) l.Front.SetTextureMid(frontmid.GetResult(l.Front.MiddleTexture)); + int i = 0; + foreach(Linedef l in lines) + { + if(l.Front != null + && (replaceunusedfronttextures.Checked + || (l.Front.MiddleRequired() + || (linedefprops[i].Front != null && linedefprops[i].Front.MiddleTexture != "-")))) + l.Front.SetTextureMid(frontmid.GetResult(l.Front.MiddleTexture)); + i++; + } } // Update the used textures @@ -719,24 +744,31 @@ namespace CodeImp.DoomBuilder.Windows private void frontlow_OnValueChanged(object sender, EventArgs e) { if(preventchanges) return; - MakeUndo(); //mxd + MakeUndo(); - //restore values + // Restore values if(string.IsNullOrEmpty(frontlow.TextureName)) { int i = 0; - foreach(Linedef l in lines) { - if(l.Front != null) l.Front.SetTextureLow(linedefprops[i].Front != null ? linedefprops[i].Front.TextureLow : "-"); + if(l.Front != null) l.Front.SetTextureLow(linedefprops[i].Front != null ? linedefprops[i].Front.LowTexture : "-"); i++; } - - } - else //update values + } + // Update values + else { + int i = 0; foreach(Linedef l in lines) - if(l.Front != null) l.Front.SetTextureLow(frontlow.GetResult(l.Front.LowTexture)); + { + if(l.Front != null + && (replaceunusedfronttextures.Checked + || (l.Front.LowRequired() + || (linedefprops[i].Front != null && linedefprops[i].Front.LowTexture != "-")))) + l.Front.SetTextureLow(frontlow.GetResult(l.Front.LowTexture)); + i++; + } } // Update the used textures @@ -749,24 +781,31 @@ namespace CodeImp.DoomBuilder.Windows private void backhigh_OnValueChanged(object sender, EventArgs e) { if(preventchanges) return; - MakeUndo(); //mxd + MakeUndo(); - //restore values + // Restore values if(string.IsNullOrEmpty(backhigh.TextureName)) { int i = 0; - foreach(Linedef l in lines) { - if(l.Back != null) l.Back.SetTextureHigh(linedefprops[i].Back != null ? linedefprops[i].Back.TextureTop : "-"); + if(l.Back != null) l.Back.SetTextureHigh(linedefprops[i].Back != null ? linedefprops[i].Back.HighTexture : "-"); i++; } - - } - else //update values + } + // Update values + else { + int i = 0; foreach(Linedef l in lines) - if(l.Back != null) l.Back.SetTextureHigh(backhigh.GetResult(l.Back.HighTexture)); + { + if(l.Back != null + && (replaceunusedbacktextures.Checked + || (l.Back.HighRequired() + || (linedefprops[i].Back != null && linedefprops[i].Back.HighTexture != "-")))) + l.Back.SetTextureHigh(backhigh.GetResult(l.Back.HighTexture)); + i++; + } } // Update the used textures @@ -779,24 +818,31 @@ namespace CodeImp.DoomBuilder.Windows private void backmid_OnValueChanged(object sender, EventArgs e) { if(preventchanges) return; - MakeUndo(); //mxd + MakeUndo(); - //restore values + // Restore values if(string.IsNullOrEmpty(backmid.TextureName)) { int i = 0; - foreach(Linedef l in lines) { - if(l.Back != null) l.Back.SetTextureMid(linedefprops[i].Back != null ? linedefprops[i].Back.TextureMid : "-"); + if(l.Back != null) l.Back.SetTextureMid(linedefprops[i].Back != null ? linedefprops[i].Back.MiddleTexture : "-"); i++; } - - } - else //update values + } + // Update values + else { + int i = 0; foreach(Linedef l in lines) - if(l.Back != null) l.Back.SetTextureMid(backmid.GetResult(l.Back.MiddleTexture)); + { + if(l.Back != null + && (replaceunusedbacktextures.Checked + || (l.Back.MiddleRequired() + || (linedefprops[i].Back != null && linedefprops[i].Back.MiddleTexture != "-")))) + l.Back.SetTextureMid(backmid.GetResult(l.Back.MiddleTexture)); + i++; + } } // Update the used textures @@ -809,24 +855,111 @@ namespace CodeImp.DoomBuilder.Windows private void backlow_OnValueChanged(object sender, EventArgs e) { if(preventchanges) return; - MakeUndo(); //mxd + MakeUndo(); - //restore values + // Restore values if(string.IsNullOrEmpty(backlow.TextureName)) { int i = 0; - foreach(Linedef l in lines) { - if(l.Back != null) l.Back.SetTextureLow(linedefprops[i].Back != null ? linedefprops[i].Back.TextureLow : "-"); + if(l.Back != null) l.Back.SetTextureLow(linedefprops[i].Back != null ? linedefprops[i].Back.LowTexture : "-"); i++; } - - } - else //update values + } + // Update values + else { + int i = 0; foreach(Linedef l in lines) - if(l.Back != null) l.Back.SetTextureLow(backlow.GetResult(l.Back.LowTexture)); + { + if(l.Back != null + && (replaceunusedbacktextures.Checked + || (l.Back.LowRequired() + || (linedefprops[i].Back != null && linedefprops[i].Back.LowTexture != "-")))) + l.Back.SetTextureLow(backlow.GetResult(l.Back.LowTexture)); + i++; + } + } + + // Update the used textures + General.Map.Data.UpdateUsedTextures(); + + General.Map.IsChanged = true; + if(OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty); + } + + private void replaceunusedfronttextures_CheckedChanged(object sender, EventArgs e) + { + //Re-apply front textures + if(preventchanges) return; + MakeUndo(); + + // Set values + int i = 0; + foreach(Linedef l in lines) + { + if(l.Front == null) continue; + + // Update top texture + if(!replaceunusedfronttextures.Checked || string.IsNullOrEmpty(fronthigh.TextureName)) + l.Front.SetTextureHigh(linedefprops[i].Front != null ? linedefprops[i].Front.HighTexture : "-"); + else + l.Front.SetTextureHigh(fronthigh.GetResult(l.Front.HighTexture)); + + // Update middle texture + if(!replaceunusedfronttextures.Checked || string.IsNullOrEmpty(frontmid.TextureName)) + l.Front.SetTextureMid(linedefprops[i].Front != null ? linedefprops[i].Front.MiddleTexture : "-"); + else + l.Front.SetTextureMid(frontmid.GetResult(l.Front.MiddleTexture)); + + // Update bottom texture + if(!replaceunusedfronttextures.Checked || string.IsNullOrEmpty(frontlow.TextureName)) + l.Front.SetTextureLow(linedefprops[i].Front != null ? linedefprops[i].Front.LowTexture : "-"); + else + l.Front.SetTextureLow(frontlow.GetResult(l.Front.LowTexture)); + + i++; + } + + // Update the used textures + General.Map.Data.UpdateUsedTextures(); + + General.Map.IsChanged = true; + if(OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty); + } + + private void replaceunusedbacktextures_CheckedChanged(object sender, EventArgs e) + { + //Re-apply back textures + if(preventchanges) return; + MakeUndo(); + + // Set values + int i = 0; + foreach(Linedef l in lines) + { + if(l.Back == null) continue; + + // Update top texture + if(!replaceunusedbacktextures.Checked || string.IsNullOrEmpty(backhigh.TextureName)) + l.Back.SetTextureHigh(linedefprops[i].Back != null ? linedefprops[i].Back.HighTexture : "-"); + else + l.Back.SetTextureHigh(backhigh.GetResult(l.Back.HighTexture)); + + // Update middle texture + if(!replaceunusedbacktextures.Checked || string.IsNullOrEmpty(backmid.TextureName)) + l.Back.SetTextureMid(linedefprops[i].Back != null ? linedefprops[i].Back.MiddleTexture : "-"); + else + l.Back.SetTextureMid(backmid.GetResult(l.Back.MiddleTexture)); + + // Update bottom texture + if(!replaceunusedbacktextures.Checked || string.IsNullOrEmpty(backlow.TextureName)) + l.Back.SetTextureLow(linedefprops[i].Back != null ? linedefprops[i].Back.LowTexture : "-"); + else + l.Back.SetTextureLow(backlow.GetResult(l.Back.LowTexture)); + + i++; } // Update the used textures diff --git a/Source/Core/Windows/LinedefEditFormUDMF.Designer.cs b/Source/Core/Windows/LinedefEditFormUDMF.Designer.cs index ee76431..902e5c6 100644 --- a/Source/Core/Windows/LinedefEditFormUDMF.Designer.cs +++ b/Source/Core/Windows/LinedefEditFormUDMF.Designer.cs @@ -60,6 +60,7 @@ namespace CodeImp.DoomBuilder.Windows this.tabfront = new System.Windows.Forms.TabPage(); this.frontside = new System.Windows.Forms.CheckBox(); this.frontgroup = new System.Windows.Forms.GroupBox(); + this.replaceunusedfronttextures = new System.Windows.Forms.CheckBox(); this.frontflagsgroup = new System.Windows.Forms.GroupBox(); this.flagsFront = new CodeImp.DoomBuilder.Controls.CheckboxArrayControl(); this.frontscalegroup = new System.Windows.Forms.GroupBox(); @@ -90,6 +91,7 @@ namespace CodeImp.DoomBuilder.Windows this.tabback = new System.Windows.Forms.TabPage(); this.backside = new System.Windows.Forms.CheckBox(); this.backgroup = new System.Windows.Forms.GroupBox(); + this.replaceunusedbacktextures = new System.Windows.Forms.CheckBox(); this.groupBox4 = new System.Windows.Forms.GroupBox(); this.resetbacklight = new System.Windows.Forms.Button(); this.backsector = new CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox(); @@ -496,6 +498,7 @@ namespace CodeImp.DoomBuilder.Windows this.frontgroup.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); + this.frontgroup.Controls.Add(this.replaceunusedfronttextures); this.frontgroup.Controls.Add(this.frontflagsgroup); this.frontgroup.Controls.Add(this.frontscalegroup); this.frontgroup.Controls.Add(this.groupBox6); @@ -511,6 +514,17 @@ namespace CodeImp.DoomBuilder.Windows this.frontgroup.TabStop = false; this.frontgroup.Text = " "; // + // replaceunusedfronttextures + // + this.replaceunusedfronttextures.AutoSize = true; + this.replaceunusedfronttextures.Location = new System.Drawing.Point(312, 15); + this.replaceunusedfronttextures.Name = "replaceunusedfronttextures"; + this.replaceunusedfronttextures.Size = new System.Drawing.Size(144, 17); + this.replaceunusedfronttextures.TabIndex = 46; + this.replaceunusedfronttextures.Text = "Replace unused textures"; + this.replaceunusedfronttextures.UseVisualStyleBackColor = true; + this.replaceunusedfronttextures.CheckedChanged += new System.EventHandler(this.replaceunusedfronttextures_CheckedChanged); + // // frontflagsgroup // this.frontflagsgroup.Controls.Add(this.flagsFront); @@ -862,7 +876,7 @@ namespace CodeImp.DoomBuilder.Windows // // frontmid // - this.frontmid.Location = new System.Drawing.Point(309, 217); + this.frontmid.Location = new System.Drawing.Point(309, 225); this.frontmid.MultipleTextures = false; this.frontmid.Name = "frontmid"; this.frontmid.Required = false; @@ -874,7 +888,7 @@ namespace CodeImp.DoomBuilder.Windows // // fronthigh // - this.fronthigh.Location = new System.Drawing.Point(309, 19); + this.fronthigh.Location = new System.Drawing.Point(309, 35); this.fronthigh.MultipleTextures = false; this.fronthigh.Name = "fronthigh"; this.fronthigh.Required = false; @@ -914,6 +928,7 @@ namespace CodeImp.DoomBuilder.Windows this.backgroup.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); + this.backgroup.Controls.Add(this.replaceunusedbacktextures); this.backgroup.Controls.Add(this.groupBox4); this.backgroup.Controls.Add(this.backflagsgroup); this.backgroup.Controls.Add(this.backscalegroup); @@ -929,6 +944,17 @@ namespace CodeImp.DoomBuilder.Windows this.backgroup.TabStop = false; this.backgroup.Text = " "; // + // replaceunusedbacktextures + // + this.replaceunusedbacktextures.AutoSize = true; + this.replaceunusedbacktextures.Location = new System.Drawing.Point(312, 15); + this.replaceunusedbacktextures.Name = "replaceunusedbacktextures"; + this.replaceunusedbacktextures.Size = new System.Drawing.Size(144, 17); + this.replaceunusedbacktextures.TabIndex = 47; + this.replaceunusedbacktextures.Text = "Replace unused textures"; + this.replaceunusedbacktextures.UseVisualStyleBackColor = true; + this.replaceunusedbacktextures.CheckedChanged += new System.EventHandler(this.replaceunusedbacktextures_CheckedChanged); + // // groupBox4 // this.groupBox4.Controls.Add(this.resetbacklight); @@ -1290,7 +1316,7 @@ namespace CodeImp.DoomBuilder.Windows // // backmid // - this.backmid.Location = new System.Drawing.Point(309, 217); + this.backmid.Location = new System.Drawing.Point(309, 225); this.backmid.MultipleTextures = false; this.backmid.Name = "backmid"; this.backmid.Required = false; @@ -1302,7 +1328,7 @@ namespace CodeImp.DoomBuilder.Windows // // backhigh // - this.backhigh.Location = new System.Drawing.Point(309, 19); + this.backhigh.Location = new System.Drawing.Point(309, 35); this.backhigh.MultipleTextures = false; this.backhigh.Name = "backhigh"; this.backhigh.Required = false; @@ -1359,6 +1385,7 @@ namespace CodeImp.DoomBuilder.Windows this.fieldslist.Name = "fieldslist"; this.fieldslist.PropertyColumnVisible = true; this.fieldslist.PropertyColumnWidth = 150; + this.fieldslist.ShowFixedFields = true; this.fieldslist.Size = new System.Drawing.Size(527, 602); this.fieldslist.TabIndex = 0; this.fieldslist.TypeColumnVisible = true; @@ -1406,6 +1433,7 @@ namespace CodeImp.DoomBuilder.Windows this.tabfront.ResumeLayout(false); this.tabfront.PerformLayout(); this.frontgroup.ResumeLayout(false); + this.frontgroup.PerformLayout(); this.frontflagsgroup.ResumeLayout(false); this.frontscalegroup.ResumeLayout(false); this.groupBox6.ResumeLayout(false); @@ -1414,6 +1442,7 @@ namespace CodeImp.DoomBuilder.Windows this.tabback.ResumeLayout(false); this.tabback.PerformLayout(); this.backgroup.ResumeLayout(false); + this.backgroup.PerformLayout(); this.groupBox4.ResumeLayout(false); this.groupBox4.PerformLayout(); this.backflagsgroup.ResumeLayout(false); @@ -1517,5 +1546,7 @@ namespace CodeImp.DoomBuilder.Windows private CodeImp.DoomBuilder.GZBuilder.Controls.TagsSelector tagsselector; private System.Windows.Forms.Button resetfrontlight; private System.Windows.Forms.Button resetbacklight; + private System.Windows.Forms.CheckBox replaceunusedfronttextures; + private System.Windows.Forms.CheckBox replaceunusedbacktextures; } } \ No newline at end of file diff --git a/Source/Core/Windows/LinedefEditFormUDMF.cs b/Source/Core/Windows/LinedefEditFormUDMF.cs index 8098c5d..35069bf 100644 --- a/Source/Core/Windows/LinedefEditFormUDMF.cs +++ b/Source/Core/Windows/LinedefEditFormUDMF.cs @@ -102,22 +102,22 @@ namespace CodeImp.DoomBuilder.Windows public readonly int Brightness; public readonly bool AbsoluteBrightness; - public readonly string TextureTop; - public readonly string TextureMid; - public readonly string TextureLow; + public readonly string HighTexture; + public readonly string MiddleTexture; + public readonly string LowTexture; public SidedefProperties(Sidedef side) { Flags = side.GetFlags(); - //offset + // Offset OffsetX = side.OffsetX; OffsetY = side.OffsetY; Brightness = UniFields.GetInteger(side.Fields, "light", 0); AbsoluteBrightness = side.Fields.GetValue("lightabsolute", false); - //scales + // Scale ScaleTopX = UniFields.GetFloat(side.Fields, "scalex_top", 1.0f); ScaleTopY = UniFields.GetFloat(side.Fields, "scaley_top", 1.0f); ScaleMidX = UniFields.GetFloat(side.Fields, "scalex_mid", 1.0f); @@ -125,7 +125,7 @@ namespace CodeImp.DoomBuilder.Windows ScaleBottomX = UniFields.GetFloat(side.Fields, "scalex_bottom", 1.0f); ScaleBottomY = UniFields.GetFloat(side.Fields, "scaley_bottom", 1.0f); - //offsets + // Local offsets OffsetTopX = UniFields.GetFloat(side.Fields, "offsetx_top", 0f); OffsetTopY = UniFields.GetFloat(side.Fields, "offsety_top", 0f); OffsetMidX = UniFields.GetFloat(side.Fields, "offsetx_mid", 0f); @@ -133,10 +133,10 @@ namespace CodeImp.DoomBuilder.Windows OffsetBottomX = UniFields.GetFloat(side.Fields, "offsetx_bottom", 0f); OffsetBottomY = UniFields.GetFloat(side.Fields, "offsety_bottom", 0f); - //textures - TextureTop = side.HighTexture; - TextureMid = side.MiddleTexture; - TextureLow = side.LowTexture; + // Textures + HighTexture = side.HighTexture; + MiddleTexture = side.MiddleTexture; + LowTexture = side.LowTexture; } } @@ -149,7 +149,7 @@ namespace CodeImp.DoomBuilder.Windows // Initialize InitializeComponent(); - //mxd. Widow setup + // Widow setup if(location != Point.Empty) { this.StartPosition = FormStartPosition.Manual; @@ -169,7 +169,7 @@ namespace CodeImp.DoomBuilder.Windows flags.Add(lf.Value, lf.Key); flags.Enabled = General.Map.Config.LinedefFlags.Count > 0; - //mxd + // Fill sidedef flags lists foreach(KeyValuePair lf in General.Map.Config.SidedefFlags) { flagsFront.Add(lf.Value, lf.Key); @@ -184,7 +184,7 @@ namespace CodeImp.DoomBuilder.Windows // Fill activations list foreach(LinedefActivateInfo ai in General.Map.Config.LinedefActivates) udmfactivates.Add(ai.Title, ai); - //mxd. Fill keys list + // Fill keys list keynumbers = new List(); if(General.Map.Config.Enums.ContainsKey("keys")) { @@ -211,7 +211,7 @@ namespace CodeImp.DoomBuilder.Windows // Fill universal fields list fieldslist.ListFixedFields(General.Map.Config.LinedefFields); - //initialize controls + // Initialize controls frontUdmfControls = new List { pfcFrontOffsetTop, pfcFrontOffsetMid, pfcFrontOffsetBottom, pfcFrontScaleTop, pfcFrontScaleMid, pfcFrontScaleBottom }; backUdmfControls = new List { pfcBackOffsetTop, pfcBackOffsetMid, pfcBackOffsetBottom, pfcBackScaleTop, pfcBackScaleMid, pfcBackScaleBottom }; @@ -225,13 +225,19 @@ namespace CodeImp.DoomBuilder.Windows foreach(KeyValuePair lf in General.Map.Config.LinedefRenderStyles) renderStyle.Items.Add(lf.Value); - //Restore value linking + // Restore value linking pfcFrontScaleTop.LinkValues = linkFrontTopScale; pfcFrontScaleMid.LinkValues = linkFrontMidScale; pfcFrontScaleBottom.LinkValues = linkFrontBottomScale; pfcBackScaleTop.LinkValues = linkBackTopScale; pfcBackScaleMid.LinkValues = linkBackMidScale; pfcBackScaleBottom.LinkValues = linkBackBottomScale; + + // Apply texture replacement settings + preventchanges = true; + replaceunusedfronttextures.Checked = General.Settings.ReadSetting("editlinedefswindow.replaceunusedfronttextures", true); + replaceunusedbacktextures.Checked = General.Settings.ReadSetting("editlinedefswindow.replaceunusedbacktextures", true); + preventchanges = false; } #endregion @@ -301,11 +307,11 @@ namespace CodeImp.DoomBuilder.Windows frontlow.Required = fl.Front.LowRequired(); frontsector.Text = fl.Front.Sector.Index.ToString(); - //flags + // Flags foreach(CheckBox c in flagsFront.Checkboxes) if(fl.Front.Flags.ContainsKey(c.Tag.ToString())) c.Checked = fl.Front.Flags[c.Tag.ToString()]; - //front settings + // Front settings foreach(PairedFieldsControl pfc in frontUdmfControls) pfc.SetValuesFrom(fl.Front.Fields, true); @@ -326,11 +332,11 @@ namespace CodeImp.DoomBuilder.Windows backlow.Required = fl.Back.LowRequired(); backsector.Text = fl.Back.Sector.Index.ToString(); - //flags + // Flags foreach(CheckBox c in flagsBack.Checkboxes) if(fl.Back.Flags.ContainsKey(c.Tag.ToString())) c.Checked = fl.Back.Flags[c.Tag.ToString()]; - //back settings + // Back settings foreach(PairedFieldsControl pfc in backUdmfControls) pfc.SetValuesFrom(fl.Back.Fields, true); @@ -432,19 +438,19 @@ namespace CodeImp.DoomBuilder.Windows if(l.Front != null) { //mxd - if(fronthigh.TextureName != l.Front.HighTexture) + if(!string.IsNullOrEmpty(fronthigh.TextureName) && fronthigh.TextureName != l.Front.HighTexture) { if(!fronthigh.Required && l.Front.HighRequired()) fronthigh.Required = true; - fronthigh.MultipleTextures = true; //mxd + fronthigh.MultipleTextures = true; fronthigh.TextureName = string.Empty; } - if(frontmid.TextureName != l.Front.MiddleTexture) + if(!string.IsNullOrEmpty(frontmid.TextureName) && frontmid.TextureName != l.Front.MiddleTexture) { if(!frontmid.Required && l.Front.MiddleRequired()) frontmid.Required = true; - frontmid.MultipleTextures = true; //mxd + frontmid.MultipleTextures = true; frontmid.TextureName = string.Empty; } - if(frontlow.TextureName != l.Front.LowTexture) + if(!string.IsNullOrEmpty(frontlow.TextureName) && frontlow.TextureName != l.Front.LowTexture) { if(!frontlow.Required && l.Front.LowRequired()) frontlow.Required = true; frontlow.MultipleTextures = true; //mxd @@ -486,22 +492,22 @@ namespace CodeImp.DoomBuilder.Windows if(l.Back != null) { //mxd - if(backhigh.TextureName != l.Back.HighTexture) + if(!string.IsNullOrEmpty(backhigh.TextureName) && backhigh.TextureName != l.Back.HighTexture) { if(!backhigh.Required && l.Back.HighRequired()) backhigh.Required = true; - backhigh.MultipleTextures = true; //mxd + backhigh.MultipleTextures = true; backhigh.TextureName = string.Empty; } - if(backmid.TextureName != l.Back.MiddleTexture) + if(!string.IsNullOrEmpty(backmid.TextureName) && backmid.TextureName != l.Back.MiddleTexture) { if(!backmid.Required && l.Back.MiddleRequired()) backmid.Required = true; - backmid.MultipleTextures = true; //mxd + backmid.MultipleTextures = true; backmid.TextureName = string.Empty; } - if(backlow.TextureName != l.Back.LowTexture) + if(!string.IsNullOrEmpty(backlow.TextureName) && backlow.TextureName != l.Back.LowTexture) { if(!backlow.Required && l.Back.LowRequired()) backlow.Required = true; - backlow.MultipleTextures = true; //mxd + backlow.MultipleTextures = true; backlow.TextureName = string.Empty; } if(backsector.Text != l.Back.Sector.Index.ToString()) backsector.Text = string.Empty; @@ -829,11 +835,16 @@ namespace CodeImp.DoomBuilder.Windows fieldslist.Focus(); } - //mxd. Store window location + //mxd. Store window settings private void LinedefEditForm_FormClosing(object sender, FormClosingEventArgs e) { + // Save location and active tab location = this.Location; activetab = tabs.SelectedIndex; + + // Save persistent settings + General.Settings.WriteSetting("editlinedefswindow.replaceunusedfronttextures", replaceunusedfronttextures.Checked); + General.Settings.WriteSetting("editlinedefswindow.replaceunusedbacktextures", replaceunusedbacktextures.Checked); } // Help! @@ -1055,23 +1066,31 @@ namespace CodeImp.DoomBuilder.Windows private void fronthigh_OnValueChanged(object sender, EventArgs e) { if(preventchanges) return; - MakeUndo(); //mxd + MakeUndo(); - //restore values + // Restore values if(string.IsNullOrEmpty(fronthigh.TextureName)) { int i = 0; - foreach(Linedef l in lines) { - if(l.Front != null) l.Front.SetTextureHigh(linedefprops[i].Front != null ? linedefprops[i].Front.TextureTop : "-"); + if(l.Front != null) l.Front.SetTextureHigh(linedefprops[i].Front != null ? linedefprops[i].Front.HighTexture : "-"); i++; } - } - else //update values + } + // Update values + else { - foreach(Linedef l in lines) - if(l.Front != null) l.Front.SetTextureHigh(fronthigh.GetResult(l.Front.HighTexture)); + int i = 0; + foreach(Linedef l in lines) + { + if(l.Front != null + && (replaceunusedfronttextures.Checked + || (l.Front.HighRequired() + || (linedefprops[i].Front != null && linedefprops[i].Front.HighTexture != "-")))) + l.Front.SetTextureHigh(fronthigh.GetResult(l.Front.HighTexture)); + i++; + } } // Update the used textures @@ -1084,23 +1103,31 @@ namespace CodeImp.DoomBuilder.Windows private void frontmid_OnValueChanged(object sender, EventArgs e) { if(preventchanges) return; - MakeUndo(); //mxd + MakeUndo(); - //restore values + // Restore values if(string.IsNullOrEmpty(frontmid.TextureName)) { int i = 0; - foreach(Linedef l in lines) { - if(l.Front != null) l.Front.SetTextureMid(linedefprops[i].Front != null ? linedefprops[i].Front.TextureMid : "-"); + if(l.Front != null) l.Front.SetTextureMid(linedefprops[i].Front != null ? linedefprops[i].Front.MiddleTexture : "-"); i++; } - } - else //update values + } + // Update values + else { - foreach(Linedef l in lines) - if(l.Front != null) l.Front.SetTextureMid(frontmid.GetResult(l.Front.MiddleTexture)); + int i = 0; + foreach(Linedef l in lines) + { + if(l.Front != null + && (replaceunusedfronttextures.Checked + || (l.Front.MiddleRequired() + || (linedefprops[i].Front != null && linedefprops[i].Front.MiddleTexture != "-")))) + l.Front.SetTextureMid(frontmid.GetResult(l.Front.MiddleTexture)); + i++; + } } // Update the used textures @@ -1113,23 +1140,31 @@ namespace CodeImp.DoomBuilder.Windows private void frontlow_OnValueChanged(object sender, EventArgs e) { if(preventchanges) return; - MakeUndo(); //mxd + MakeUndo(); - //restore values + // Restore values if(string.IsNullOrEmpty(frontlow.TextureName)) { int i = 0; - foreach(Linedef l in lines) { - if(l.Front != null) l.Front.SetTextureLow(linedefprops[i].Front != null ? linedefprops[i].Front.TextureLow : "-"); + if(l.Front != null) l.Front.SetTextureLow(linedefprops[i].Front != null ? linedefprops[i].Front.LowTexture : "-"); i++; } - } - else //update values + } + // Update values + else { + int i = 0; foreach(Linedef l in lines) - if(l.Front != null) l.Front.SetTextureLow(frontlow.GetResult(l.Front.LowTexture)); + { + if(l.Front != null + && (replaceunusedfronttextures.Checked + || (l.Front.LowRequired() + || (linedefprops[i].Front != null && linedefprops[i].Front.LowTexture != "-")))) + l.Front.SetTextureLow(frontlow.GetResult(l.Front.LowTexture)); + i++; + } } // Update the used textures @@ -1142,23 +1177,31 @@ namespace CodeImp.DoomBuilder.Windows private void backhigh_OnValueChanged(object sender, EventArgs e) { if(preventchanges) return; - MakeUndo(); //mxd + MakeUndo(); - //restore values + // Restore values if(string.IsNullOrEmpty(backhigh.TextureName)) { int i = 0; - foreach(Linedef l in lines) { - if(l.Back != null) l.Back.SetTextureHigh(linedefprops[i].Back != null ? linedefprops[i].Back.TextureTop : "-"); + if(l.Back != null) l.Back.SetTextureHigh(linedefprops[i].Back != null ? linedefprops[i].Back.HighTexture : "-"); i++; } - } - else //update values + } + // Update values + else { + int i = 0; foreach(Linedef l in lines) - if(l.Back != null) l.Back.SetTextureHigh(backhigh.GetResult(l.Back.HighTexture)); + { + if(l.Back != null + && (replaceunusedbacktextures.Checked + || (l.Back.HighRequired() + || (linedefprops[i].Back != null && linedefprops[i].Back.HighTexture != "-")))) + l.Back.SetTextureHigh(backhigh.GetResult(l.Back.HighTexture)); + i++; + } } // Update the used textures @@ -1171,23 +1214,31 @@ namespace CodeImp.DoomBuilder.Windows private void backmid_OnValueChanged(object sender, EventArgs e) { if(preventchanges) return; - MakeUndo(); //mxd + MakeUndo(); - //restore values + // Restore values if(string.IsNullOrEmpty(backmid.TextureName)) { int i = 0; - foreach(Linedef l in lines) { - if(l.Back != null) l.Back.SetTextureMid(linedefprops[i].Back != null ? linedefprops[i].Back.TextureMid : "-"); + if(l.Back != null) l.Back.SetTextureMid(linedefprops[i].Back != null ? linedefprops[i].Back.MiddleTexture : "-"); i++; } - } - else //update values + } + // Update values + else { + int i = 0; foreach(Linedef l in lines) - if(l.Back != null) l.Back.SetTextureMid(backmid.GetResult(l.Back.MiddleTexture)); + { + if(l.Back != null + && (replaceunusedbacktextures.Checked + || (l.Back.MiddleRequired() + || (linedefprops[i].Back != null && linedefprops[i].Back.MiddleTexture != "-")))) + l.Back.SetTextureMid(backmid.GetResult(l.Back.MiddleTexture)); + i++; + } } // Update the used textures @@ -1200,23 +1251,111 @@ namespace CodeImp.DoomBuilder.Windows private void backlow_OnValueChanged(object sender, EventArgs e) { if(preventchanges) return; - MakeUndo(); //mxd + MakeUndo(); - //restore values + // Restore values if(string.IsNullOrEmpty(backlow.TextureName)) { int i = 0; - foreach(Linedef l in lines) { - if(l.Back != null) l.Back.SetTextureLow(linedefprops[i].Back != null ? linedefprops[i].Back.TextureLow : "-"); + if(l.Back != null) l.Back.SetTextureLow(linedefprops[i].Back != null ? linedefprops[i].Back.LowTexture : "-"); i++; } - } - else //update values + } + // Update values + else { + int i = 0; foreach(Linedef l in lines) - if(l.Back != null) l.Back.SetTextureLow(backlow.GetResult(l.Back.LowTexture)); + { + if(l.Back != null + && (replaceunusedbacktextures.Checked + || (l.Back.LowRequired() + || (linedefprops[i].Back != null && linedefprops[i].Back.LowTexture != "-")))) + l.Back.SetTextureLow(backlow.GetResult(l.Back.LowTexture)); + i++; + } + } + + // Update the used textures + General.Map.Data.UpdateUsedTextures(); + + General.Map.IsChanged = true; + if(OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty); + } + + private void replaceunusedfronttextures_CheckedChanged(object sender, EventArgs e) + { + //Re-apply front textures + if(preventchanges) return; + MakeUndo(); + + // Set values + int i = 0; + foreach(Linedef l in lines) + { + if(l.Front == null) continue; + + // Update top texture + if(!replaceunusedfronttextures.Checked || string.IsNullOrEmpty(fronthigh.TextureName)) + l.Front.SetTextureHigh(linedefprops[i].Front != null ? linedefprops[i].Front.HighTexture : "-"); + else + l.Front.SetTextureHigh(fronthigh.GetResult(l.Front.HighTexture)); + + // Update middle texture + if(!replaceunusedfronttextures.Checked || string.IsNullOrEmpty(frontmid.TextureName)) + l.Front.SetTextureMid(linedefprops[i].Front != null ? linedefprops[i].Front.MiddleTexture : "-"); + else + l.Front.SetTextureMid(frontmid.GetResult(l.Front.MiddleTexture)); + + // Update bottom texture + if(!replaceunusedfronttextures.Checked || string.IsNullOrEmpty(frontlow.TextureName)) + l.Front.SetTextureLow(linedefprops[i].Front != null ? linedefprops[i].Front.LowTexture : "-"); + else + l.Front.SetTextureLow(frontlow.GetResult(l.Front.LowTexture)); + + i++; + } + + // Update the used textures + General.Map.Data.UpdateUsedTextures(); + + General.Map.IsChanged = true; + if(OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty); + } + + private void replaceunusedbacktextures_CheckedChanged(object sender, EventArgs e) + { + //Re-apply back textures + if(preventchanges) return; + MakeUndo(); + + // Set values + int i = 0; + foreach(Linedef l in lines) + { + if(l.Back == null) continue; + + // Update top texture + if(!replaceunusedbacktextures.Checked || string.IsNullOrEmpty(backhigh.TextureName)) + l.Back.SetTextureHigh(linedefprops[i].Back != null ? linedefprops[i].Back.HighTexture : "-"); + else + l.Back.SetTextureHigh(backhigh.GetResult(l.Back.HighTexture)); + + // Update middle texture + if(!replaceunusedbacktextures.Checked || string.IsNullOrEmpty(backmid.TextureName)) + l.Back.SetTextureMid(linedefprops[i].Back != null ? linedefprops[i].Back.MiddleTexture : "-"); + else + l.Back.SetTextureMid(backmid.GetResult(l.Back.MiddleTexture)); + + // Update bottom texture + if(!replaceunusedbacktextures.Checked || string.IsNullOrEmpty(backlow.TextureName)) + l.Back.SetTextureLow(linedefprops[i].Back != null ? linedefprops[i].Back.LowTexture : "-"); + else + l.Back.SetTextureLow(backlow.GetResult(l.Back.LowTexture)); + + i++; } // Update the used textures diff --git a/Source/Core/Windows/LinedefEditFormUDMF.resx b/Source/Core/Windows/LinedefEditFormUDMF.resx index d572a5b..e3a990b 100644 --- a/Source/Core/Windows/LinedefEditFormUDMF.resx +++ b/Source/Core/Windows/LinedefEditFormUDMF.resx @@ -146,7 +146,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj0yLjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADM - CAAAAk1TRnQBSQFMAgEBAgEAAcABAAHAAQABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo + CAAAAk1TRnQBSQFMAgEBAgEAAcgBAAHIAQABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo AwABQAMAARADAAEBAQABCAYAAQQYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA diff --git a/Source/Core/Windows/MainForm.Designer.cs b/Source/Core/Windows/MainForm.Designer.cs index ef555c3..ed08300 100644 --- a/Source/Core/Windows/MainForm.Designer.cs +++ b/Source/Core/Windows/MainForm.Designer.cs @@ -182,6 +182,7 @@ namespace CodeImp.DoomBuilder.Windows this.buttonviewceilings = new System.Windows.Forms.ToolStripButton(); this.seperatorviews = new System.Windows.Forms.ToolStripSeparator(); this.buttontogglecomments = new System.Windows.Forms.ToolStripButton(); + this.buttontogglefixedthingsscale = new System.Windows.Forms.ToolStripButton(); this.buttonsnaptogrid = new System.Windows.Forms.ToolStripButton(); this.buttonautomerge = new System.Windows.Forms.ToolStripButton(); this.buttonautoclearsidetextures = new System.Windows.Forms.ToolStripButton(); @@ -256,6 +257,7 @@ namespace CodeImp.DoomBuilder.Windows this.flowLayoutPanel = new System.Windows.Forms.FlowLayoutPanel(); this.modecontrolsloolbar = new System.Windows.Forms.ToolStrip(); this.itemtogglecomments = new System.Windows.Forms.ToolStripMenuItem(); + this.itemtogglefixedthingsscale = new System.Windows.Forms.ToolStripMenuItem(); this.itemdynamicgridsize = new System.Windows.Forms.ToolStripMenuItem(); this.itemrendernightspath = new System.Windows.Forms.ToolStripMenuItem(); toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); @@ -741,6 +743,7 @@ namespace CodeImp.DoomBuilder.Windows this.itemtogglegrid, this.itemrendernightspath, this.itemtogglecomments, + this.itemtogglefixedthingsscale, this.toolStripSeparator4, this.menuzoom, this.itemgotocoords, @@ -1247,6 +1250,7 @@ namespace CodeImp.DoomBuilder.Windows this.buttonfullbrightness, this.buttontogglegrid, this.buttontogglecomments, + this.buttontogglefixedthingsscale, this.separatorfullbrightness, this.buttonviewnormal, this.buttonviewbrightness, @@ -1677,6 +1681,19 @@ namespace CodeImp.DoomBuilder.Windows this.buttontogglecomments.Text = "Show Comments"; this.buttontogglecomments.Click += new System.EventHandler(this.InvokeTaggedAction); // + // buttontogglefixedthingsscale + // + this.buttontogglefixedthingsscale.Checked = true; + this.buttontogglefixedthingsscale.CheckState = System.Windows.Forms.CheckState.Checked; + this.buttontogglefixedthingsscale.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.buttontogglefixedthingsscale.Image = global::CodeImp.DoomBuilder.Properties.Resources.FixedThingsScale; + this.buttontogglefixedthingsscale.ImageTransparentColor = System.Drawing.Color.Magenta; + this.buttontogglefixedthingsscale.Name = "buttontogglefixedthingsscale"; + this.buttontogglefixedthingsscale.Size = new System.Drawing.Size(23, 22); + this.buttontogglefixedthingsscale.Tag = "builder_togglefixedthingsscale"; + this.buttontogglefixedthingsscale.Text = "Fixed Things Scale"; + this.buttontogglefixedthingsscale.Click += new System.EventHandler(this.InvokeTaggedAction); + // // buttonsnaptogrid // this.buttonsnaptogrid.Checked = true; @@ -2234,9 +2251,9 @@ namespace CodeImp.DoomBuilder.Windows // this.statistics.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.statistics.ForeColor = System.Drawing.SystemColors.GrayText; - this.statistics.Location = new System.Drawing.Point(869, 2); + this.statistics.Location = new System.Drawing.Point(849, 2); this.statistics.Name = "statistics"; - this.statistics.Size = new System.Drawing.Size(118, 102); + this.statistics.Size = new System.Drawing.Size(138, 102); this.statistics.TabIndex = 9; this.statistics.Visible = false; // @@ -2448,6 +2465,18 @@ namespace CodeImp.DoomBuilder.Windows this.itemtogglecomments.Text = "Show Comments"; this.itemtogglecomments.Click += new System.EventHandler(this.InvokeTaggedAction); // + // itemtogglefixedthingsscale + // + this.itemtogglefixedthingsscale.Checked = true; + this.itemtogglefixedthingsscale.CheckOnClick = true; + this.itemtogglefixedthingsscale.CheckState = System.Windows.Forms.CheckState.Checked; + this.itemtogglefixedthingsscale.Image = global::CodeImp.DoomBuilder.Properties.Resources.FixedThingsScale; + this.itemtogglefixedthingsscale.Name = "itemtogglefixedthingsscale"; + this.itemtogglefixedthingsscale.Size = new System.Drawing.Size(215, 22); + this.itemtogglefixedthingsscale.Tag = "builder_togglefixedthingsscale"; + this.itemtogglefixedthingsscale.Text = "Fixed Things Scale"; + this.itemtogglefixedthingsscale.Click += new System.EventHandler(this.InvokeTaggedAction); + // // itemdynamicgridsize // this.itemdynamicgridsize.Checked = true; @@ -2725,6 +2754,7 @@ namespace CodeImp.DoomBuilder.Windows private ToolStripMenuItem item2zoom800; private ToolStripMenuItem itemzoom800; private ToolStripButton buttontogglecomments; + private ToolStripButton buttontogglefixedthingsscale; private ToolStripMenuItem itemlinedefcolors; private ToolStripSeparator separatorlinecolors; private ToolStripButton buttonlinededfcolors; @@ -2737,5 +2767,6 @@ namespace CodeImp.DoomBuilder.Windows private ToolStripMenuItem itemdynamicgridsize; private ToolStripMenuItem itemrendernightspath; private ToolStripMenuItem itemtogglecomments; + private ToolStripMenuItem itemtogglefixedthingsscale; } } \ No newline at end of file diff --git a/Source/Core/Windows/MainForm.cs b/Source/Core/Windows/MainForm.cs index cdde40a..64fd4c7 100644 --- a/Source/Core/Windows/MainForm.cs +++ b/Source/Core/Windows/MainForm.cs @@ -734,14 +734,14 @@ namespace CodeImp.DoomBuilder.Windows if(!File.Exists(filePaths[0])) { - General.Interface.DisplayStatus(StatusType.Warning, "Cannot open '" + filePaths[0] + "': file does not exist!"); + General.Interface.DisplayStatus(StatusType.Warning, "Cannot open \"" + filePaths[0] + "\": file does not exist!"); return; } string ext = Path.GetExtension(filePaths[0]); if(string.IsNullOrEmpty(ext) || ext.ToLower() != ".wad") { - General.Interface.DisplayStatus(StatusType.Warning, "Cannot open '" + filePaths[0] + "': only WAD files can be loaded this way!"); + General.Interface.DisplayStatus(StatusType.Warning, "Cannot open \"" + filePaths[0] + "\": only WAD files can be loaded this way!"); return; } @@ -970,6 +970,9 @@ namespace CodeImp.DoomBuilder.Windows // Get integral zoom level int size = int.Parse((sender as ToolStripMenuItem).Tag.ToString(), CultureInfo.InvariantCulture); + //mxd. Disable automatic grid resizing + DisableDynamicGridResize(); + // Change grid size General.Map.Grid.SetGridSize(size); @@ -1493,8 +1496,7 @@ namespace CodeImp.DoomBuilder.Windows if(General.Map != null) { // Make the new items list - ToolStripItem[] items = new ToolStripItem[(General.Map.Config.Skills.Count * 2) + General.Map.ConfigSettings.TestEngines.Count + 2]; //mxd - int addindex = 0; + List items = new List(General.Map.Config.Skills.Count * 2 + General.Map.ConfigSettings.TestEngines.Count + 2); // Positive skills are with monsters foreach(SkillInfo si in General.Map.Config.Skills) @@ -1504,12 +1506,11 @@ namespace CodeImp.DoomBuilder.Windows menuitem.Click += TestSkill_Click; menuitem.Tag = si.Index; menuitem.Checked = (General.Settings.TestMonsters && (General.Map.ConfigSettings.TestSkill == si.Index)); - items[addindex++] = menuitem; + items.Add(menuitem); } // Add seperator - items[addindex] = new ToolStripSeparator { Padding = new Padding(0, 3, 0, 3) }; - addindex++; + items.Add(new ToolStripSeparator { Padding = new Padding(0, 3, 0, 3) }); // Negative skills are without monsters foreach(SkillInfo si in General.Map.Config.Skills) @@ -1519,26 +1520,37 @@ namespace CodeImp.DoomBuilder.Windows menuitem.Click += TestSkill_Click; menuitem.Tag = -si.Index; menuitem.Checked = (!General.Settings.TestMonsters && (General.Map.ConfigSettings.TestSkill == si.Index)); - items[addindex++] = menuitem; + items.Add(menuitem); } //mxd. Add seperator - items[addindex] = new ToolStripSeparator { Padding = new Padding(0, 3, 0, 3) }; - addindex++; + items.Add(new ToolStripSeparator { Padding = new Padding(0, 3, 0, 3) }); //mxd. Add test engines for(int i = 0; i < General.Map.ConfigSettings.TestEngines.Count; i++) { + if(General.Map.ConfigSettings.TestEngines[i].TestProgramName == EngineInfo.DEFAULT_ENGINE_NAME) continue; ToolStripMenuItem menuitem = new ToolStripMenuItem(General.Map.ConfigSettings.TestEngines[i].TestProgramName); menuitem.Image = General.Map.ConfigSettings.TestEngines[i].TestProgramIcon; menuitem.Click += TestEngine_Click; menuitem.Tag = i; menuitem.Checked = (i == General.Map.ConfigSettings.CurrentEngineIndex); - items[addindex++] = menuitem; + items.Add(menuitem); } // Add to list - buttontest.DropDownItems.AddRange(items); + buttontest.DropDownItems.AddRange(items.ToArray()); + } + } + + //mxd + internal void DisableDynamicGridResize() + { + if(General.Settings.DynamicGridSize) + { + General.Settings.DynamicGridSize = false; + itemdynamicgridsize.Checked = false; + buttontoggledynamicgrid.Checked = false; } } @@ -2027,6 +2039,8 @@ namespace CodeImp.DoomBuilder.Windows itemrendernightspath.Checked = General.Settings.RenderNiGHTSPath; buttontogglecomments.Visible = General.Settings.ToolbarViewModes && maploaded && General.Map.UDMF; //mxd buttontogglecomments.Checked = General.Settings.RenderComments; //mxd + buttontogglefixedthingsscale.Visible = General.Settings.ToolbarViewModes && maploaded; //mxd + buttontogglefixedthingsscale.Checked = General.Settings.FixedThingsScale; //mxd separatorfullbrightness.Visible = General.Settings.ToolbarViewModes && maploaded; //mxd buttonviewbrightness.Visible = General.Settings.ToolbarViewModes && maploaded; buttonviewceilings.Visible = General.Settings.ToolbarViewModes && maploaded; @@ -2048,7 +2062,7 @@ namespace CodeImp.DoomBuilder.Windows buttontogglefog.Visible = General.Settings.GZToolbarGZDoom && maploaded; buttontogglesky.Visible = maploaded && (General.Settings.GZToolbarGZDoom || General.Map.SRB2); buttontoggleeventlines.Visible = General.Settings.GZToolbarGZDoom && maploaded; - buttontogglevisualvertices.Visible = General.Settings.GZToolbarGZDoom && maploaded; + buttontogglevisualvertices.Visible = General.Settings.GZToolbarGZDoom && maploaded && General.Map.UDMF; separatorgzmodes.Visible = General.Settings.GZToolbarGZDoom && maploaded; //mxd. Show/hide additional panels @@ -2776,6 +2790,19 @@ namespace CodeImp.DoomBuilder.Windows RedrawDisplay(); } + //mxd. Action to toggle fixed things scale + [BeginAction("togglefixedthingsscale")] + internal void ToggleFixedThingsScale() + { + buttontogglefixedthingsscale.Checked = !buttontogglefixedthingsscale.Checked; + itemtogglefixedthingsscale.Checked = buttontogglefixedthingsscale.Checked; + General.Settings.FixedThingsScale = buttontogglefixedthingsscale.Checked; + DisplayStatus(StatusType.Action, "Fixed things scale is " + (buttontogglefixedthingsscale.Checked ? "ENABLED" : "DISABLED")); + + // Redraw display to show changes + RedrawDisplay(); + } + // Action to toggle snap to grid [BeginAction("togglesnap")] internal void ToggleSnapToGrid() @@ -2888,6 +2915,8 @@ namespace CodeImp.DoomBuilder.Windows itemtoggleinfo.Checked = IsInfoPanelExpanded; itemtogglecomments.Visible = (General.Map != null && General.Map.UDMF); //mxd itemtogglecomments.Checked = General.Settings.RenderComments; //mxd + itemtogglefixedthingsscale.Visible = (General.Map != null); //mxd + itemtogglefixedthingsscale.Checked = General.Settings.FixedThingsScale; //mxd // View mode items if(General.Map != null) @@ -3059,7 +3088,7 @@ namespace CodeImp.DoomBuilder.Windows } //open file - DisplayStatus(StatusType.Info, "Shortcut reference saved to '" + path + "'"); + DisplayStatus(StatusType.Info, "Shortcut reference saved to \"" + path + "\""); Process.Start(path); } @@ -3067,8 +3096,8 @@ namespace CodeImp.DoomBuilder.Windows private void itemopenconfigfolder_Click(object sender, EventArgs e) { if(Directory.Exists(General.SettingsPath)) Process.Start(General.SettingsPath); - else General.ShowErrorMessage("Huh? Where did Settings folder go?.." + Environment.NewLine - + "I swear it was here: '" + General.SettingsPath + "'!", MessageBoxButtons.OK); // I don't think this will ever happen + else General.ShowErrorMessage("Huh? Where did Settings folder go?.." + Environment.NewLine + + "I swear it was here: \"" + General.SettingsPath + "\"!", MessageBoxButtons.OK); // I don't think this will ever happen } #endregion @@ -3195,11 +3224,11 @@ namespace CodeImp.DoomBuilder.Windows string folder = General.Settings.ScreenshotsPath; if(!Directory.Exists(folder)) { - if(folder != General.DefaultScreenshotsPath - && General.ShowErrorMessage("Screenshots save path '" + folder - + "' does not exist!\nPress OK to save to the default folder ('" - + General.DefaultScreenshotsPath - + "').\nPress Cancel to abort.", MessageBoxButtons.OKCancel) == DialogResult.Cancel) return; + if(folder != General.DefaultScreenshotsPath + && General.ShowErrorMessage("Screenshots save path \"" + folder + + "\" does not exist!\nPress OK to save to the default folder (\"" + + General.DefaultScreenshotsPath + + "\").\nPress Cancel to abort.", MessageBoxButtons.OKCancel) == DialogResult.Cancel) return; folder = General.DefaultScreenshotsPath; @@ -3332,7 +3361,7 @@ namespace CodeImp.DoomBuilder.Windows { bitmap.Save(path, ImageFormat.Png); } - DisplayStatus(StatusType.Info, "Screenshot saved to '" + path + "'"); + DisplayStatus(StatusType.Info, "Screenshot saved to \"" + path + "\""); } catch(ExternalException e) { @@ -3690,14 +3719,28 @@ namespace CodeImp.DoomBuilder.Windows // Returns the new action or the same action when cancelled public int BrowseLinedefActions(IWin32Window owner, int initialvalue) { - return ActionBrowserForm.BrowseAction(owner, initialvalue); + return ActionBrowserForm.BrowseAction(owner, initialvalue, false); + } + + //mxd. This browses the lindef types + // Returns the new action or the same action when cancelled + public int BrowseLinedefActions(IWin32Window owner, int initialvalue, bool addanyaction) + { + return ActionBrowserForm.BrowseAction(owner, initialvalue, addanyaction); } // This browses sector effects // Returns the new effect or the same effect when cancelled public int BrowseSectorEffect(IWin32Window owner, int initialvalue) { - return EffectBrowserForm.BrowseEffect(owner, initialvalue); + return EffectBrowserForm.BrowseEffect(owner, initialvalue, false); + } + + //mxd. This browses sector effects + // Returns the new effect or the same effect when cancelled + public int BrowseSectorEffect(IWin32Window owner, int initialvalue, bool addanyeffect) + { + return EffectBrowserForm.BrowseEffect(owner, initialvalue, addanyeffect); } // This browses thing types diff --git a/Source/Core/Windows/OpenMapOptionsForm.Designer.cs b/Source/Core/Windows/OpenMapOptionsForm.Designer.cs index e6db655..93442de 100644 --- a/Source/Core/Windows/OpenMapOptionsForm.Designer.cs +++ b/Source/Core/Windows/OpenMapOptionsForm.Designer.cs @@ -225,7 +225,7 @@ namespace CodeImp.DoomBuilder.Windows this.MaximizeBox = false; this.MinimizeBox = false; this.Name = "OpenMapOptionsForm"; - this.Opacity = 1; + this.Opacity = 0; this.ShowIcon = false; this.ShowInTaskbar = false; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; diff --git a/Source/Core/Windows/OpenMapOptionsForm.cs b/Source/Core/Windows/OpenMapOptionsForm.cs index cfcfe6f..d6dfd94 100644 --- a/Source/Core/Windows/OpenMapOptionsForm.cs +++ b/Source/Core/Windows/OpenMapOptionsForm.cs @@ -30,7 +30,7 @@ using CodeImp.DoomBuilder.Config; namespace CodeImp.DoomBuilder.Windows { - internal partial class OpenMapOptionsForm : DelayedForm + internal partial class OpenMapOptionsForm : Form { // Variables private Configuration mapsettings; @@ -126,72 +126,103 @@ namespace CodeImp.DoomBuilder.Windows scriptcompiler.Items.Add(group.Value); } - //mxd. Go for all enabled configurations - for(int i = 0; i < General.Configs.Count; i++) + // Go for all configurations + foreach(ConfigurationInfo info in General.Configs) { - if(!General.Configs[i].Enabled) continue; - // Add config name to list - index = config.Items.Add(General.Configs[i]); + index = config.Items.Add(info); // Select this item - if(General.Configs[i].Filename == gameconfig) config.SelectedIndex = index; - } - - //mxd. No dice? Try disabled ones - if(config.SelectedIndex == -1) - { - for(int i = 0; i < General.Configs.Count; i++) - { - if(General.Configs[i].Enabled) continue; - if(General.Configs[i].Filename == gameconfig) - { - //add and Select this item - config.SelectedIndex = config.Items.Add(General.Configs[i]); - break; - } - } + if(info.Filename == gameconfig) config.SelectedIndex = index; } // Still no configuration selected? if(config.SelectedIndex == -1) { - // Then go for all configurations with resources to find a suitable one - for(int i = 0; i < General.Configs.Count; i++) + //mxd. Then go for all ENABLED configurations with resources to find a suitable one + foreach(ConfigurationInfo info in General.Configs) { // Check if a resource location is set for this configuration, if so, match the wad against this configuration - if(General.Configs[i].Resources.Count > 0 && MatchConfiguration(General.Configs[i].Configuration, wadfile)) + if(info.Enabled && info.Resources.Count > 0 && MatchConfiguration(info.Configuration, wadfile)) { - index = config.Items.IndexOf(General.Configs[i]); //mxd. Already added? - config.SelectedIndex = (index != -1 ? index : config.Items.Add(General.Configs[i])); // Select or add and select this item + //mxd. Already added? + index = config.Items.IndexOf(info); + + // Select or add and select this item + config.SelectedIndex = (index != -1 ? index : config.Items.Add(info)); break; } } } //mxd. Still no configuration selected? - if(config.SelectedIndex == -1) + if(config.SelectedIndex == -1) { - // Then go for all configurations without resources to find a suitable one - for(int i = 0; i < General.Configs.Count; i++) + // Then go for all DISABLED configurations with resources to find a suitable one + foreach(ConfigurationInfo info in General.Configs) + { + // Check if a resource location is set for this configuration, if so, match the wad against this configuration + if(!info.Enabled && info.Resources.Count > 0 && MatchConfiguration(info.Configuration, wadfile)) + { + //mxd. Already added? + index = config.Items.IndexOf(info); + + // Select or add and select this item + config.SelectedIndex = (index != -1 ? index : config.Items.Add(info)); + break; + } + } + } + + //mxd. Still no configuration selected? + if(config.SelectedIndex == -1) + { + //mxd. Then go for all ENABLED configurations without resources to find a suitable one + foreach(ConfigurationInfo info in General.Configs) { // Check if a resource location is not set for this configuration, if so, match the wad against this configuration - if(General.Configs[i].Resources.Count == 0 && MatchConfiguration(General.Configs[i].Configuration, wadfile)) + if(info.Enabled && info.Resources.Count == 0 && MatchConfiguration(info.Configuration, wadfile)) { - index = config.Items.IndexOf(General.Configs[i]); //mxd. Already added? - config.SelectedIndex = (index != -1 ? index : config.Items.Add(General.Configs[i])); // Select or add and select this item + //mxd. Already added? + index = config.Items.IndexOf(info); + + // Select or add and select this item + config.SelectedIndex = (index != -1 ? index : config.Items.Add(info)); + break; + } + } + } + + //mxd. Still no configuration selected? + if(config.SelectedIndex == -1) + { + // Then go for all DISABLED configurations without resources to find a suitable one + foreach(ConfigurationInfo info in General.Configs) + { + // Check if a resource location is not set for this configuration, if so, match the wad against this configuration + if(!info.Enabled && info.Resources.Count == 0 && MatchConfiguration(info.Configuration, wadfile)) + { + //mxd. Already added? + index = config.Items.IndexOf(info); + + // Select or add and select this item + config.SelectedIndex = (index != -1 ? index : config.Items.Add(info)); break; } } } //mxd. Bail out if still no dice... - if(config.SelectedIndex == -1) + if(config.SelectedIndex == -1 || mapslist.Items.Count == 0) { - this.Visible = false; General.ShowWarningMessage("Unable to find maps using any game configuration.\nDoes this wad contain any maps at all?..", MessageBoxButtons.OK); cancel_Click(this, EventArgs.Empty); } + else + { + // Show the window + this.Opacity = 1; + } // Done Cursor.Current = Cursors.Default; diff --git a/Source/Core/Windows/PreferencesForm.Designer.cs b/Source/Core/Windows/PreferencesForm.Designer.cs index b9fafc3..4871b4d 100644 --- a/Source/Core/Windows/PreferencesForm.Designer.cs +++ b/Source/Core/Windows/PreferencesForm.Designer.cs @@ -40,10 +40,10 @@ namespace CodeImp.DoomBuilder.Windows System.Windows.Forms.Label label21; System.Windows.Forms.Label label29; System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(PreferencesForm)); + this.keepfilterfocused = new System.Windows.Forms.CheckBox(); this.maxBackups = new System.Windows.Forms.TrackBar(); this.labelBackups = new System.Windows.Forms.Label(); this.label27 = new System.Windows.Forms.Label(); - this.checkforupdates = new System.Windows.Forms.CheckBox(); this.cbStoreEditTab = new System.Windows.Forms.CheckBox(); this.locatetexturegroup = new System.Windows.Forms.CheckBox(); this.recentFiles = new System.Windows.Forms.TrackBar(); @@ -215,7 +215,6 @@ namespace CodeImp.DoomBuilder.Windows this.colorliterals = new CodeImp.DoomBuilder.Controls.ColorControl(); this.colorconstants = new CodeImp.DoomBuilder.Controls.ColorControl(); this.previewgroup = new System.Windows.Forms.GroupBox(); - this.scriptedit = new CodeImp.DoomBuilder.Controls.ScriptEditorPreviewControl(); this.tabpasting = new System.Windows.Forms.TabPage(); this.label16 = new System.Windows.Forms.Label(); this.pasteoptions = new CodeImp.DoomBuilder.Controls.PasteOptionsControl(); @@ -266,7 +265,6 @@ namespace CodeImp.DoomBuilder.Windows this.groupBox8.SuspendLayout(); this.groupBox7.SuspendLayout(); this.groupBox6.SuspendLayout(); - this.previewgroup.SuspendLayout(); this.tabpasting.SuspendLayout(); this.SuspendLayout(); // @@ -299,10 +297,10 @@ namespace CodeImp.DoomBuilder.Windows // // groupBox1 // + groupBox1.Controls.Add(this.keepfilterfocused); groupBox1.Controls.Add(this.maxBackups); groupBox1.Controls.Add(this.labelBackups); groupBox1.Controls.Add(this.label27); - groupBox1.Controls.Add(this.checkforupdates); groupBox1.Controls.Add(this.cbStoreEditTab); groupBox1.Controls.Add(this.locatetexturegroup); groupBox1.Controls.Add(this.recentFiles); @@ -332,6 +330,18 @@ namespace CodeImp.DoomBuilder.Windows groupBox1.TabStop = false; groupBox1.Text = " Options "; // + // keepfilterfocused + // + this.keepfilterfocused.AutoSize = true; + this.keepfilterfocused.Location = new System.Drawing.Point(32, 356); + this.keepfilterfocused.Name = "keepfilterfocused"; + this.keepfilterfocused.Size = new System.Drawing.Size(280, 17); + this.keepfilterfocused.TabIndex = 52; + this.keepfilterfocused.Text = "Keep Filter input focused when image browser is open"; + this.toolTip1.SetToolTip(this.keepfilterfocused, "When enabled, all key presses in \r\nimage browsers will be redirected \r\nto the Fil" + + "ter textbox."); + this.keepfilterfocused.UseVisualStyleBackColor = true; + // // maxBackups // this.maxBackups.BackColor = System.Drawing.SystemColors.Window; @@ -364,21 +374,10 @@ namespace CodeImp.DoomBuilder.Windows this.label27.Text = "Max. backups:"; this.toolTip1.SetToolTip(this.label27, "Controls how many backups \r\nare made when a map is saved."); // - // checkforupdates - // - this.checkforupdates.AutoSize = true; - this.checkforupdates.Location = new System.Drawing.Point(32, 440); - this.checkforupdates.Name = "checkforupdates"; - this.checkforupdates.Size = new System.Drawing.Size(160, 17); - this.checkforupdates.TabIndex = 51; - this.checkforupdates.Text = "Check for updates at startup"; - this.checkforupdates.UseVisualStyleBackColor = true; - this.checkforupdates.Visible = false; - // // cbStoreEditTab // this.cbStoreEditTab.AutoSize = true; - this.cbStoreEditTab.Location = new System.Drawing.Point(32, 419); + this.cbStoreEditTab.Location = new System.Drawing.Point(32, 440); this.cbStoreEditTab.Name = "cbStoreEditTab"; this.cbStoreEditTab.Size = new System.Drawing.Size(203, 17); this.cbStoreEditTab.TabIndex = 50; @@ -388,7 +387,7 @@ namespace CodeImp.DoomBuilder.Windows // locatetexturegroup // this.locatetexturegroup.AutoSize = true; - this.locatetexturegroup.Location = new System.Drawing.Point(32, 377); + this.locatetexturegroup.Location = new System.Drawing.Point(32, 398); this.locatetexturegroup.Name = "locatetexturegroup"; this.locatetexturegroup.Size = new System.Drawing.Size(267, 17); this.locatetexturegroup.TabIndex = 49; @@ -465,7 +464,7 @@ namespace CodeImp.DoomBuilder.Windows // cbSynchCameras // this.cbSynchCameras.AutoSize = true; - this.cbSynchCameras.Location = new System.Drawing.Point(32, 398); + this.cbSynchCameras.Location = new System.Drawing.Point(32, 419); this.cbSynchCameras.Name = "cbSynchCameras"; this.cbSynchCameras.Size = new System.Drawing.Size(260, 17); this.cbSynchCameras.TabIndex = 42; @@ -475,7 +474,7 @@ namespace CodeImp.DoomBuilder.Windows // showtexturesizes // this.showtexturesizes.AutoSize = true; - this.showtexturesizes.Location = new System.Drawing.Point(32, 356); + this.showtexturesizes.Location = new System.Drawing.Point(32, 377); this.showtexturesizes.Name = "showtexturesizes"; this.showtexturesizes.Size = new System.Drawing.Size(208, 17); this.showtexturesizes.TabIndex = 41; @@ -612,7 +611,7 @@ namespace CodeImp.DoomBuilder.Windows label1.AutoSize = true; label1.Location = new System.Drawing.Point(28, 29); label1.Name = "label1"; - label1.Size = new System.Drawing.Size(143, 13); + label1.Size = new System.Drawing.Size(135, 13); label1.TabIndex = 20; label1.Text = "Texture and flat brightness:"; label1.TextAlign = System.Drawing.ContentAlignment.TopRight; @@ -2100,6 +2099,7 @@ namespace CodeImp.DoomBuilder.Windows this.scripttabwidth.ButtonStepsUseModifierKeys = false; this.scripttabwidth.ButtonStepsWrapAround = false; this.scripttabwidth.Location = new System.Drawing.Point(181, 22); + this.scripttabwidth.MaximumValue = 2147483647; this.scripttabwidth.Name = "scripttabwidth"; this.scripttabwidth.Size = new System.Drawing.Size(71, 24); this.scripttabwidth.StepValues = null; @@ -2464,7 +2464,6 @@ namespace CodeImp.DoomBuilder.Windows // this.previewgroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.previewgroup.Controls.Add(this.scriptedit); this.previewgroup.Location = new System.Drawing.Point(217, 344); this.previewgroup.Name = "previewgroup"; this.previewgroup.Size = new System.Drawing.Size(457, 157); @@ -2472,13 +2471,6 @@ namespace CodeImp.DoomBuilder.Windows this.previewgroup.TabStop = false; this.previewgroup.Text = " Preview "; // - // scriptedit - // - this.scriptedit.Location = new System.Drawing.Point(6, 19); - this.scriptedit.Name = "scriptedit"; - this.scriptedit.Size = new System.Drawing.Size(445, 132); - this.scriptedit.TabIndex = 0; - // // tabpasting // this.tabpasting.Controls.Add(this.label16); @@ -2589,7 +2581,6 @@ namespace CodeImp.DoomBuilder.Windows this.groupBox7.PerformLayout(); this.groupBox6.ResumeLayout(false); this.groupBox6.PerformLayout(); - this.previewgroup.ResumeLayout(false); this.tabpasting.ResumeLayout(false); this.ResumeLayout(false); @@ -2715,7 +2706,6 @@ namespace CodeImp.DoomBuilder.Windows private System.Windows.Forms.Label label26; private System.Windows.Forms.CheckBox locatetexturegroup; private System.Windows.Forms.CheckBox cbStoreEditTab; - private System.Windows.Forms.CheckBox checkforupdates; private System.Windows.Forms.TrackBar maxBackups; private System.Windows.Forms.Label labelBackups; private System.Windows.Forms.Label label27; @@ -2778,5 +2768,6 @@ namespace CodeImp.DoomBuilder.Windows private System.Windows.Forms.CheckBox cbDrawThingsFixedSize; private System.Windows.Forms.Label labelDefaultThingSize; private System.Windows.Forms.TrackBar tbDefaultThingSize; + private System.Windows.Forms.CheckBox keepfilterfocused; } } \ No newline at end of file diff --git a/Source/Core/Windows/PreferencesForm.cs b/Source/Core/Windows/PreferencesForm.cs index 6e0aab3..7c8b742 100644 --- a/Source/Core/Windows/PreferencesForm.cs +++ b/Source/Core/Windows/PreferencesForm.cs @@ -39,8 +39,8 @@ namespace CodeImp.DoomBuilder.Windows private bool allowapplycontrol; private bool disregardshift; private bool disregardcontrol; - private readonly List actionListItems; //mxd - private readonly List actionListItemsGroupIndices; //mxd + private readonly List allactionitems; //mxd + private readonly List allactionitemsgroups; //mxd private bool reloadresources; @@ -90,8 +90,8 @@ namespace CodeImp.DoomBuilder.Windows //mxd locatetexturegroup.Checked = General.Settings.LocateTextureGroup; + keepfilterfocused.Checked = General.Settings.KeepTextureFilterFocused; cbStoreEditTab.Checked = General.Settings.StoreSelectedEditTab; - checkforupdates.Checked = General.Settings.CheckForUpdates; toolbar_gzdoom.Checked = General.Settings.GZToolbarGZDoom; cbSynchCameras.Checked = General.Settings.GZSynchCameras; tbDynLightCount.Value = General.Clamp(General.Settings.GZMaxDynamicLights, tbDynLightCount.Minimum, tbDynLightCount.Maximum); @@ -154,8 +154,10 @@ namespace CodeImp.DoomBuilder.Windows // Fill list of actions Action[] actions = General.Actions.GetAllActions(); - actionListItems = new List(); //mxd - actionListItemsGroupIndices = new List(); //mxd + allactionitems = new List(); //mxd + allactionitemsgroups = new List(); //mxd + + listactions.BeginUpdate(); //mxd foreach(Action a in actions) { // Create item @@ -167,15 +169,16 @@ namespace CodeImp.DoomBuilder.Windows if(General.Actions.Categories.ContainsKey(a.Category)) { item.Group = listactions.Groups[a.Category]; - actionListItemsGroupIndices.Add(listactions.Groups.IndexOf(item.Group)); + allactionitemsgroups.Add(listactions.Groups.IndexOf(item.Group)); //mxd } else //mxd { - actionListItemsGroupIndices.Add(-1); + allactionitemsgroups.Add(-1); } - actionListItems.Add(item); //mxd + allactionitems.Add(item); //mxd } + listactions.EndUpdate(); //mxd // Set the colors // TODO: Make this automated by using the collection @@ -298,8 +301,8 @@ namespace CodeImp.DoomBuilder.Windows General.Settings.GZToolbarGZDoom = toolbar_gzdoom.Checked; //mxd General.Settings.ShowTextureSizes = showtexturesizes.Checked; General.Settings.StoreSelectedEditTab = cbStoreEditTab.Checked; //mxd - General.Settings.CheckForUpdates = checkforupdates.Checked; //mxd General.Settings.LocateTextureGroup = locatetexturegroup.Checked; //mxd + General.Settings.KeepTextureFilterFocused = keepfilterfocused.Checked; //mxd General.Settings.MaxRecentFiles = recentFiles.Value; //mxd General.Settings.MaxBackups = maxBackups.Value; General.Settings.ScreenshotsPath = screenshotsfolderpath.Text.Trim(); //mxd @@ -323,7 +326,7 @@ namespace CodeImp.DoomBuilder.Windows General.Settings.ScriptFontSize = fontsize; // Apply control keys to actions - foreach(ListViewItem item in actionListItems) //mxd + foreach(ListViewItem item in allactionitems) //mxd General.Actions[item.Name].SetShortcutKey((int)item.SubItems[1].Tag); // Apply the colors @@ -540,7 +543,7 @@ namespace CodeImp.DoomBuilder.Windows if(thiskey != 0) { // Find actions with same key - foreach(ListViewItem item in actionListItems) + foreach(ListViewItem item in allactionitems) { // Don't count the selected action if(item != listactions.SelectedItems[0]) @@ -702,6 +705,9 @@ namespace CodeImp.DoomBuilder.Windows // Item selected private void listactions_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e) { + //mxd. Leave when not allowed to update + if(!allowapplycontrol) return; + string disregardkeys = ""; // Anything selected? @@ -886,51 +892,61 @@ namespace CodeImp.DoomBuilder.Windows } //mxd - private void tbFilterActions_TextChanged(object sender, EventArgs e) + private void tbFilterActions_TextChanged(object sender, EventArgs e) { + ListViewItem curselection = (listactions.SelectedItems.Count > 0 ? listactions.SelectedItems[0] : null); + ListViewItem toselect = null; + + allowapplycontrol = false; listactions.BeginUpdate(); + listactions.Items.Clear(); - //restore everything - if(string.IsNullOrEmpty(tbFilterActions.Text)) + // Restore everything + if(string.IsNullOrEmpty(tbFilterActions.Text)) { - //restore items - listactions.Items.Clear(); - listactions.Items.AddRange(actionListItems.ToArray()); - - //restore groups - for(int i = 0; i < actionListItems.Count; i++) + // Restore items and groups + for(int i = 0; i < allactionitems.Count; i++) { - if(actionListItemsGroupIndices[i] != -1) - actionListItems[i].Group = listactions.Groups[actionListItemsGroupIndices[i]]; + if(allactionitemsgroups[i] != -1) + allactionitems[i].Group = listactions.Groups[allactionitemsgroups[i]]; + + // Item sould be added AFTER restoring it's group, otherwise item sorting will be screwed! + listactions.Items.Add(allactionitems[i]); + + // Restore selection? + if(allactionitems[i] == curselection) toselect = curselection; } - } - else //apply filtering - { + } + // Apply filtering + else + { string match = tbFilterActions.Text.ToUpperInvariant(); - for(int i = 0; i < actionListItems.Count; i++) + for(int i = 0; i < allactionitems.Count; i++) { - if(actionListItems[i].Text.ToUpperInvariant().Contains(match)) + if(allactionitems[i].Text.ToUpperInvariant().Contains(match)) { - //ensure visible - if(!listactions.Items.Contains(actionListItems[i])) - { - listactions.Items.Add(actionListItems[i]); + // Restore group + if(allactionitemsgroups[i] != -1) + allactionitems[i].Group = listactions.Groups[allactionitemsgroups[i]]; - //restore group - if(actionListItemsGroupIndices[i] != -1) - actionListItems[i].Group = listactions.Groups[actionListItemsGroupIndices[i]]; - } + // Add item + listactions.Items.Add(allactionitems[i]); + + // Restore selection? + if(allactionitems[i] == curselection) toselect = curselection; } - else if(listactions.Items.Contains(actionListItems[i])) - { - //ensure invisible - listactions.Items.Remove(actionListItems[i]); - } } } - listactions.Sort(); + // Restore selection? + if(toselect != null) + { + toselect.Selected = true; + listactions.EnsureVisible(toselect.Index); + } + listactions.EndUpdate(); + allowapplycontrol = true; } #endregion diff --git a/Source/Core/Windows/SectorEditForm.Designer.cs b/Source/Core/Windows/SectorEditForm.Designer.cs index dc8df19..0717ce2 100644 --- a/Source/Core/Windows/SectorEditForm.Designer.cs +++ b/Source/Core/Windows/SectorEditForm.Designer.cs @@ -265,7 +265,8 @@ namespace CodeImp.DoomBuilder.Windows // // label2 // - label2.Location = new System.Drawing.Point(193, 16); + label2.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(204))); + label2.Location = new System.Drawing.Point(196, 16); label2.Name = "label2"; label2.Size = new System.Drawing.Size(114, 16); label2.TabIndex = 15; @@ -283,7 +284,8 @@ namespace CodeImp.DoomBuilder.Windows // // label4 // - label4.Location = new System.Drawing.Point(313, 16); + label4.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(204))); + label4.Location = new System.Drawing.Point(316, 16); label4.Name = "label4"; label4.Size = new System.Drawing.Size(114, 16); label4.TabIndex = 14; diff --git a/Source/Core/Windows/ThingEditForm.cs b/Source/Core/Windows/ThingEditForm.cs index 80a4dfd..0b8c119 100644 --- a/Source/Core/Windows/ThingEditForm.cs +++ b/Source/Core/Windows/ThingEditForm.cs @@ -391,7 +391,7 @@ namespace CodeImp.DoomBuilder.Windows } // Verify the type - if(((thingtype.GetFullType(0) < General.Map.FormatInterface.MinThingType) || (thingtype.GetFullType(0) > General.Map.FormatInterface.MaxThingType))) + if(!string.IsNullOrEmpty(thingtype.TypeStringValue) && ((thingtype.GetFullType(0) < General.Map.FormatInterface.MinThingType) || (thingtype.GetFullType(0) > General.Map.FormatInterface.MaxThingType))) { General.ShowWarningMessage("Thing type must be between " + General.Map.FormatInterface.MinThingType + " and " + General.Map.FormatInterface.MaxThingType + ".", MessageBoxButtons.OK); return; @@ -621,12 +621,14 @@ namespace CodeImp.DoomBuilder.Windows action_ValueChanges(this, EventArgs.Empty); //mxd. Update things - if(preventchanges) return; - MakeUndo(); //mxd - - if(((thingtype.GetResult(0) < General.Map.FormatInterface.MinThingType) || (thingtype.GetResult(0) > General.Map.FormatInterface.MaxThingType))) + if(preventchanges || + (!string.IsNullOrEmpty(thingtype.TypeStringValue) && + thingtype.GetResult(0) < General.Map.FormatInterface.MinThingType + || thingtype.GetResult(0) > General.Map.FormatInterface.MaxThingType)) return; + MakeUndo(); //mxd + foreach(Thing t in things) { //Set type diff --git a/Source/Core/Windows/ThingEditFormUDMF.cs b/Source/Core/Windows/ThingEditFormUDMF.cs index dfc1ca4..73f89f9 100644 --- a/Source/Core/Windows/ThingEditFormUDMF.cs +++ b/Source/Core/Windows/ThingEditFormUDMF.cs @@ -131,11 +131,11 @@ namespace CodeImp.DoomBuilder.Windows // Fill universal fields list fieldslist.ListFixedFields(General.Map.Config.ThingFields); - //mxd. Show fixed fields? - hidefixedfields.Checked = !General.Settings.ReadSetting("customfieldsshowfixed", true); + //mxd. Show fixed fields? + hidefixedfields.Checked = !General.Settings.ReadSetting("customfieldsshowfixed", true); - // Thing height? - posZ.Visible = General.Map.FormatInterface.HasThingHeight; + // Thing height? + posZ.Visible = General.Map.FormatInterface.HasThingHeight; zlabel.Visible = General.Map.FormatInterface.HasThingHeight; cbAbsoluteHeight.Visible = General.Map.FormatInterface.HasThingHeight; //mxd @@ -177,7 +177,7 @@ namespace CodeImp.DoomBuilder.Windows Thing ft = General.GetByIndex(things, 0); // Set type - thingtype.SelectType(ft.FullType); + thingtype.SelectType(ft.SRB2Type); // Flags foreach(CheckBox c in flags.Checkboxes) @@ -199,6 +199,11 @@ namespace CodeImp.DoomBuilder.Windows posY.ButtonStep = General.Map.Grid.GridSize; posZ.ButtonStep = General.Map.Grid.GridSize; + //mxd. User vars. Should be done before adding regular fields + ThingTypeInfo fti = General.Map.Data.GetThingInfoEx(ft.SRB2Type); + if(fti != null && fti.Actor != null && fti.Actor.UserVars.Count > 0) + fieldslist.SetUserVars(fti.Actor.UserVars, ft.Fields, true); + // Custom fields fieldslist.SetValues(ft.Fields, true); commenteditor.SetValues(ft.Fields, true); @@ -236,7 +241,7 @@ namespace CodeImp.DoomBuilder.Windows // Type does not match? ThingTypeInfo info = thingtype.GetSelectedInfo(); //mxd - if(info != null && info.Index != t.FullType) thingtype.ClearSelectedType(); + if(info != null && info.Index != t.SRB2Type) thingtype.ClearSelectedType(); // Flags foreach(CheckBox c in flags.Checkboxes) @@ -272,6 +277,11 @@ namespace CodeImp.DoomBuilder.Windows //mxd. Arguments argscontrol.SetValue(t, false); + //mxd. User vars. Should be done before adding regular fields + ThingTypeInfo ti = General.Map.Data.GetThingInfoEx(t.SRB2Type); + if(ti != null && ti.Actor != null && ti.Actor.UserVars.Count > 0) + fieldslist.SetUserVars(ti.Actor.UserVars, t.Fields, false); + //mxd. Custom fields fieldslist.SetValues(t.Fields, false); commenteditor.SetValues(t.Fields, false); //mxd. Comments @@ -294,16 +304,6 @@ namespace CodeImp.DoomBuilder.Windows //mxd. Store initial properties thingprops.Add(new ThingProperties(t)); - - //mxd. add user vars - /*if(info != null && info.Actor != null && info.Actor.UserVars.Count > 0) - { - foreach(string s in info.Actor.UserVars) - { - if(!t.Fields.ContainsKey(s)) - fieldslist.SetValue(s, 0, CodeImp.DoomBuilder.Types.UniversalType.Integer); - } - }*/ } preventchanges = false; @@ -442,7 +442,7 @@ namespace CodeImp.DoomBuilder.Windows } // Verify the type - if(((thingtype.GetResult(0) < General.Map.FormatInterface.MinThingType) || (thingtype.GetResult(0) > General.Map.FormatInterface.MaxThingType))) + if(!string.IsNullOrEmpty(thingtype.TypeStringValue) && ((thingtype.GetResult(0) < General.Map.FormatInterface.MinThingType) || (thingtype.GetResult(0) > General.Map.FormatInterface.MaxThingType))) { General.ShowWarningMessage("Thing type must be between " + General.Map.FormatInterface.MinThingType + " and " + General.Map.FormatInterface.MaxThingType + ".", MessageBoxButtons.OK); return; @@ -490,6 +490,11 @@ namespace CodeImp.DoomBuilder.Windows if(!string.IsNullOrEmpty(score.Text)) UniFields.SetInteger(t.Fields, "score", score.GetResult(t.Fields.GetValue("score", 0)), 0); + //mxd. User vars. Should be called after fieldslist.Apply() + ThingTypeInfo ti = General.Map.Data.GetThingInfoEx(t.SRB2Type); + if(ti != null && ti.Actor != null && ti.Actor.UserVars.Count > 0) + fieldslist.ApplyUserVars(ti.Actor.UserVars, t.Fields); + color.ApplyTo(t.Fields, t.Fields.GetValue("fillcolor", 0)); //mxd. Comments @@ -505,7 +510,7 @@ namespace CodeImp.DoomBuilder.Windows if(c.CheckState == CheckState.Checked) defaultflags.Add(c.Tag.ToString()); } General.Settings.DefaultThingType = thingtype.GetResult(General.Settings.DefaultThingType); - General.Settings.DefaultThingAngle = angle.GetResult(General.Settings.DefaultThingAngle); + General.Settings.DefaultThingAngle = (int)Angle2D.DegToRad((float)angle.GetResult((int)Angle2D.RadToDeg(General.Settings.DefaultThingAngle) - 90) + 90); General.Settings.SetDefaultThingFlags(defaultflags); // Store value linking @@ -581,8 +586,8 @@ namespace CodeImp.DoomBuilder.Windows { location = this.Location; activetab = tabs.SelectedIndex; - General.Settings.WriteSetting("customfieldsshowfixed", !hidefixedfields.Checked); - } + General.Settings.WriteSetting("customfieldsshowfixed", !hidefixedfields.Checked); + } // Help private void ThingEditForm_HelpRequested(object sender, HelpEventArgs hlpevent) @@ -679,9 +684,10 @@ namespace CodeImp.DoomBuilder.Windows action_ValueChanges(this, EventArgs.Empty); //mxd. Update things - if(preventchanges - || (thingtype.GetResult(0) < General.Map.FormatInterface.MinThingType) - || (thingtype.GetResult(0) > General.Map.FormatInterface.MaxThingType)) + if(preventchanges || + (!string.IsNullOrEmpty(thingtype.TypeStringValue) && + thingtype.GetResult(0) < General.Map.FormatInterface.MinThingType + || thingtype.GetResult(0) > General.Map.FormatInterface.MaxThingType)) return; MakeUndo(); //mxd @@ -689,7 +695,7 @@ namespace CodeImp.DoomBuilder.Windows foreach(Thing t in things) { //Set type - t.FullType = thingtype.GetResult(t.FullType); + t.SRB2Type = thingtype.GetResult(t.SRB2Type); // Update settings t.UpdateConfiguration(); @@ -871,12 +877,12 @@ namespace CodeImp.DoomBuilder.Windows if(OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty); } - private void hidefixedfields_CheckedChanged(object sender, EventArgs e) - { - fieldslist.ShowFixedFields = !hidefixedfields.Checked; - } + private void hidefixedfields_CheckedChanged(object sender, EventArgs e) + { + fieldslist.ShowFixedFields = !hidefixedfields.Checked; + } - #endregion + #endregion - } + } } \ No newline at end of file diff --git a/Source/Core/ZDoom/ActorStructure.cs b/Source/Core/ZDoom/ActorStructure.cs index fc99f25..544f814 100644 --- a/Source/Core/ZDoom/ActorStructure.cs +++ b/Source/Core/ZDoom/ActorStructure.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Globalization; using CodeImp.DoomBuilder.Config; using CodeImp.DoomBuilder.Data; +using CodeImp.DoomBuilder.Types; #endregion @@ -52,7 +53,7 @@ namespace CodeImp.DoomBuilder.ZDoom // Properties private Dictionary> props; - private readonly List userVars; //mxd + private readonly Dictionary uservars; //mxd // States private Dictionary states; @@ -68,7 +69,7 @@ namespace CodeImp.DoomBuilder.ZDoom public string ReplacesClass { get { return replaceclass; } } public ActorStructure BaseClass { get { return baseclass; } } internal int DoomEdNum { get { return doomednum; } set { doomednum = value; } } - public List UserVars { get { return userVars; } } //mxd + public Dictionary UserVars { get { return uservars; } } //mxd #endregion @@ -78,10 +79,10 @@ namespace CodeImp.DoomBuilder.ZDoom internal ActorStructure(DecorateParser parser) { // Initialize - flags = new Dictionary(StringComparer.Ordinal); - props = new Dictionary>(StringComparer.Ordinal); - states = new Dictionary(StringComparer.Ordinal); - userVars = new List();//mxd + flags = new Dictionary(StringComparer.OrdinalIgnoreCase); + props = new Dictionary>(StringComparer.OrdinalIgnoreCase); + states = new Dictionary(StringComparer.OrdinalIgnoreCase); + uservars = new Dictionary(StringComparer.OrdinalIgnoreCase);//mxd bool done = false; //mxd // Always define a game property, but default to 0 values @@ -163,7 +164,7 @@ namespace CodeImp.DoomBuilder.ZDoom else if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out doomednum)) // Check if numeric { // Not numeric! - parser.ReportError("Expected editor thing number or start of actor scope while parsing '" + classname + "'"); + parser.ReportError("Expected editor thing number or start of actor scope while parsing \"" + classname + "\""); return; } break; @@ -271,18 +272,87 @@ namespace CodeImp.DoomBuilder.ZDoom break; case "var": //mxd - while(parser.SkipWhitespace(true)) + // Type + parser.SkipWhitespace(true); + string typestr = parser.ReadToken().ToUpperInvariant(); + UniversalType type = UniversalType.EnumOption; // There is no Unknown type, so let's use something impossiburu... + switch(typestr) { - string t = parser.ReadToken(); - if(string.IsNullOrEmpty(t) || t == ";") break; - if(t.StartsWith("user_") && !userVars.Contains(t)) - userVars.Add(t); + case "INT": + type = UniversalType.Integer; + break; + + default: + parser.LogWarning("Unknown user variable type"); + break; + } + + // Name + parser.SkipWhitespace(true); + string name = parser.ReadToken(); + if(string.IsNullOrEmpty(name)) + { + parser.ReportError("Expected User Variable name"); + return; + } + if(!name.StartsWith("user_", StringComparison.OrdinalIgnoreCase)) + { + parser.ReportError("User Variable name must start with \"user_\" prefix"); + return; + } + if(uservars.ContainsKey(name)) + { + parser.ReportError("User Variable \"" + name + "\" is double-defined"); + return; + } + if(!skipsuper && baseclass != null && baseclass.uservars.ContainsKey(name)) + { + parser.ReportError("User variable \"" + name + "\" is already defined in one of the parent classes"); + return; + } + + // Rest + parser.SkipWhitespace(true); + string next = parser.ReadToken(); + if(next == "[") // that's User Array. Let's skip it... + { + int arrlen = -1; + if(!parser.ReadSignedInt(ref arrlen)) + { + parser.ReportError("Expected User Array length, but got \"" + next + "\""); + return; + } + if(arrlen < 1) + { + parser.ReportError("User Array length must be a positive value"); + return; + } + if(!parser.NextTokenIs("]") || !parser.NextTokenIs(";")) + { + return; + } + } + else if(next != ";") + { + parser.ReportError("Expected \";\", but got \"" + next + "\""); + return; + } + else + { + // Add to collection + uservars.Add(name, type); } break; case "}": - // Actor scope ends here, - // break out of this parse loop + //mxd. Get user vars from the BaseClass, if we have one + if(!skipsuper && baseclass != null && baseclass.uservars.Count > 0) + { + foreach(var group in baseclass.uservars) + uservars.Add(group.Key, group.Value); + } + + // Actor scope ends here, break out of this parse loop done = true; break; @@ -414,7 +484,7 @@ namespace CodeImp.DoomBuilder.ZDoom } } - parser.LogWarning("Unable to find '" + inheritclass + "' class to inherit from, while parsing '" + classname + ":" + doomednum + "'"); + parser.LogWarning("Unable to find \"" + inheritclass + "\" class to inherit from, while parsing \"" + classname + ":" + doomednum + "\""); } } @@ -466,12 +536,13 @@ namespace CodeImp.DoomBuilder.ZDoom /// /// This returns a specific value of a specific property as a string. Returns an empty string when the propery does not have the specified value. /// - public string GetPropertyValueString(string propname, int valueindex) + public string GetPropertyValueString(string propname, int valueindex) { return GetPropertyValueString(propname, valueindex, true); } //mxd. Added "stripquotes" parameter + public string GetPropertyValueString(string propname, int valueindex, bool stripquotes) { if(props.ContainsKey(propname) && (props[propname].Count > valueindex)) - return props[propname][valueindex]; + return (stripquotes ? ZDTextParser.StripQuotes(props[propname][valueindex]) : props[propname][valueindex]); if(!skipsuper && (baseclass != null)) - return baseclass.GetPropertyValueString(propname, valueindex); + return baseclass.GetPropertyValueString(propname, valueindex, stripquotes); return ""; } @@ -480,11 +551,11 @@ namespace CodeImp.DoomBuilder.ZDoom /// public int GetPropertyValueInt(string propname, int valueindex) { - string str = GetPropertyValueString(propname, valueindex); + string str = GetPropertyValueString(propname, valueindex, false); //mxd. It can be negative... - if(str == "-" && props.Count > valueindex + 1) - str += GetPropertyValueString(propname, valueindex + 1); + if(str == "-" && props.Count > valueindex + 1) + str += GetPropertyValueString(propname, valueindex + 1, false); int intvalue; if(int.TryParse(str, NumberStyles.Integer, CultureInfo.InvariantCulture, out intvalue)) @@ -497,11 +568,11 @@ namespace CodeImp.DoomBuilder.ZDoom /// public float GetPropertyValueFloat(string propname, int valueindex) { - string str = GetPropertyValueString(propname, valueindex); + string str = GetPropertyValueString(propname, valueindex, false); //mxd. It can be negative... if(str == "-" && props.Count > valueindex + 1) - str += GetPropertyValueString(propname, valueindex + 1); + str += GetPropertyValueString(propname, valueindex + 1, false); float fvalue; if(float.TryParse(str, NumberStyles.Float, CultureInfo.InvariantCulture, out fvalue)) @@ -554,7 +625,7 @@ namespace CodeImp.DoomBuilder.ZDoom /// public Dictionary GetAllStates() { - Dictionary list = new Dictionary(states); + Dictionary list = new Dictionary(states, StringComparer.OrdinalIgnoreCase); if(!skipsuper && (baseclass != null)) { @@ -590,75 +661,75 @@ namespace CodeImp.DoomBuilder.ZDoom // Sprite forced? if(HasPropertyWithValue("$sprite")) { - string sprite = GetPropertyValueString("$sprite", 0); //mxd - if ((sprite.Length > DataManager.INTERNAL_PREFIX.Length) && - sprite.ToLowerInvariant().StartsWith(DataManager.INTERNAL_PREFIX)) return sprite; //mxd - if (General.Map.Data.GetSpriteExists(sprite)) return sprite; //mxd. Added availability check + string sprite = GetPropertyValueString("$sprite", 0, true); //mxd + if((sprite.Length > DataManager.INTERNAL_PREFIX.Length) && + sprite.ToLowerInvariant().StartsWith(DataManager.INTERNAL_PREFIX)) return sprite; //mxd + if(General.Map.Data.GetSpriteExists(sprite)) return sprite; //mxd. Added availability check - //mxd. Bitch and moan - General.ErrorLogger.Add(ErrorType.Warning, "DECORATE warning in " + classname + ":" + doomednum + ". The sprite \"" + sprite + "\" assigned by the \"$sprite\" property does not exist."); - } + //mxd. Bitch and moan + General.ErrorLogger.Add(ErrorType.Warning, "DECORATE warning in " + classname + ":" + doomednum + ". The sprite \"" + sprite + "\" assigned by the \"$sprite\" property does not exist."); + } - // Try the idle state - if (HasState("idle")) - { - StateStructure s = GetState("idle"); - string spritename = s.GetSprite(0); - if (!string.IsNullOrEmpty(spritename)) - result = spritename; - } - - // Try the see state - if (string.IsNullOrEmpty(result) && HasState("see")) - { - StateStructure s = GetState("see"); - string spritename = s.GetSprite(0); - if (!string.IsNullOrEmpty(spritename)) - result = spritename; - } - - // Try the inactive state - if (string.IsNullOrEmpty(result) && HasState("inactive")) - { - StateStructure s = GetState("inactive"); - string spritename = s.GetSprite(0); - if (!string.IsNullOrEmpty(spritename)) - result = spritename; - } - - // Try the spawn state - if (string.IsNullOrEmpty(result) && HasState("spawn")) - { - StateStructure s = GetState("spawn"); - string spritename = s.GetSprite(0); - if (!string.IsNullOrEmpty(spritename)) - result = spritename; - } - - // Still no sprite found? then just pick the first we can find - if (string.IsNullOrEmpty(result)) - { - Dictionary list = GetAllStates(); - foreach (StateStructure s in list.Values) - { - string spritename = s.GetSprite(0); - if (!string.IsNullOrEmpty(spritename)) - { - result = spritename; - break; - } - } - } - - if (!string.IsNullOrEmpty(result)) - { - // The sprite name is not actually complete, we still have to append - // the direction characters to it. Find an existing sprite with direction. - foreach (string postfix in SPRITE_POSTFIXES) - { - if (General.Map.Data.GetSpriteExists(result + postfix)) - return result + postfix; - } + // Try the idle state + if(HasState("idle")) + { + StateStructure s = GetState("idle"); + string spritename = s.GetSprite(0); + if(!string.IsNullOrEmpty(spritename)) + result = spritename; + } + + // Try the see state + if(string.IsNullOrEmpty(result) && HasState("see")) + { + StateStructure s = GetState("see"); + string spritename = s.GetSprite(0); + if(!string.IsNullOrEmpty(spritename)) + result = spritename; + } + + // Try the inactive state + if(string.IsNullOrEmpty(result) && HasState("inactive")) + { + StateStructure s = GetState("inactive"); + string spritename = s.GetSprite(0); + if(!string.IsNullOrEmpty(spritename)) + result = spritename; + } + + // Try the spawn state + if(string.IsNullOrEmpty(result) && HasState("spawn")) + { + StateStructure s = GetState("spawn"); + string spritename = s.GetSprite(0); + if(!string.IsNullOrEmpty(spritename)) + result = spritename; + } + + // Still no sprite found? then just pick the first we can find + if(string.IsNullOrEmpty(result)) + { + Dictionary list = GetAllStates(); + foreach(StateStructure s in list.Values) + { + string spritename = s.GetSprite(0); + if(!string.IsNullOrEmpty(spritename)) + { + result = spritename; + break; + } + } + } + + if(!string.IsNullOrEmpty(result)) + { + // The sprite name is not actually complete, we still have to append + // the direction characters to it. Find an existing sprite with direction. + foreach(string postfix in SPRITE_POSTFIXES) + { + if(General.Map.Data.GetSpriteExists(result + postfix)) + return result + postfix; + } } // No sprite found diff --git a/Source/Core/ZDoom/AnimdefsParser.cs b/Source/Core/ZDoom/AnimdefsParser.cs index d48cc9b..65d0208 100644 --- a/Source/Core/ZDoom/AnimdefsParser.cs +++ b/Source/Core/ZDoom/AnimdefsParser.cs @@ -132,7 +132,7 @@ namespace CodeImp.DoomBuilder.ZDoom // Check results if(cameratextures.ContainsKey(texturename.ToUpperInvariant())) { - ReportError("Camera texture '" + texturename + "' is defined more than once"); + ReportError("Camera texture \"" + texturename + "\" is defined more than once"); return false; } diff --git a/Source/Core/ZDoom/DecorateParser.cs b/Source/Core/ZDoom/DecorateParser.cs index 1475b35..2529e95 100644 --- a/Source/Core/ZDoom/DecorateParser.cs +++ b/Source/Core/ZDoom/DecorateParser.cs @@ -86,12 +86,12 @@ namespace CodeImp.DoomBuilder.ZDoom { // Syntax whitespace = "\n \t\r\u00A0"; //mxd. non-breaking space is also space :) - specialtokens = ":{}+-\n;,"; - - // Initialize - actors = new Dictionary(StringComparer.OrdinalIgnoreCase); - archivedactors = new Dictionary(StringComparer.OrdinalIgnoreCase); - parsedlumps = new HashSet(StringComparer.OrdinalIgnoreCase); //mxd + specialtokens = ":{}[]+-\n;,"; + + // Initialize + actors = new Dictionary(StringComparer.OrdinalIgnoreCase); + archivedactors = new Dictionary(StringComparer.OrdinalIgnoreCase); + parsedlumps = new HashSet(StringComparer.OrdinalIgnoreCase); //mxd } // Disposer diff --git a/Source/Core/ZDoom/PatchStructure.cs b/Source/Core/ZDoom/PatchStructure.cs index 17fb609..1eea528 100644 --- a/Source/Core/ZDoom/PatchStructure.cs +++ b/Source/Core/ZDoom/PatchStructure.cs @@ -30,23 +30,27 @@ namespace CodeImp.DoomBuilder.ZDoom { #region ================== Constants + // Some odd things in ZDoom + private const string IGNORE_SPRITE = "TNT1A0"; + #endregion #region ================== Variables // Declaration - private string name; - private int offsetx; - private int offsety; - private bool flipx; - private bool flipy; - private float alpha; - private int rotation; //mxd - private TexturePathRenderStyle renderStyle; //mxd - private PixelColor blendColor; //mxd - private TexturePathBlendStyle blendStyle; //mxd - private float tintAmmount; //mxd - private static string[] renderStyles = { "copy", "translucent", "add", "subtract", "reversesubtract", "modulate", "copyalpha", "copynewalpha", "overlay" }; //mxd + private readonly string name; + private readonly int offsetx; + private readonly int offsety; + private readonly bool flipx; + private readonly bool flipy; + private readonly float alpha; + private readonly int rotation; //mxd + private readonly TexturePathRenderStyle renderStyle; //mxd + private readonly PixelColor blendColor; //mxd + private readonly TexturePathBlendStyle blendStyle; //mxd + private readonly float tintAmmount; //mxd + private static readonly string[] renderStyles = { "copy", "translucent", "add", "subtract", "reversesubtract", "modulate", "copyalpha", "copynewalpha", "overlay" }; //mxd + private readonly bool skip; //mxd #endregion @@ -63,6 +67,7 @@ namespace CodeImp.DoomBuilder.ZDoom public TexturePathBlendStyle BlendStyle { get { return blendStyle; } } public float TintAmmount { get { return tintAmmount; } } public PixelColor BlendColor { get { return blendColor; } }//mxd + public bool Skip { get { return skip; } } //mxd #endregion @@ -88,6 +93,9 @@ namespace CodeImp.DoomBuilder.ZDoom return; } + //mxd. Skip what must be skipped + skip = (name.ToUpperInvariant() == IGNORE_SPRITE); + //mxd name = name.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); @@ -147,7 +155,7 @@ namespace CodeImp.DoomBuilder.ZDoom if(rotation != 0 && rotation != 90 && rotation != 180 && rotation != 270) { - parser.LogWarning("Unsupported rotation (" + rotation + ") in patch '" + name + "'"); + parser.LogWarning("Unsupported rotation (" + rotation + ") in patch \"" + name + "\""); rotation = 0; } break; @@ -206,7 +214,7 @@ namespace CodeImp.DoomBuilder.ZDoom // Try parsing as value if(!float.TryParse(strvalue, NumberStyles.Float, CultureInfo.InvariantCulture, out value)) { - parser.ReportError("Expected numeric value for property '" + propertyname + "'"); + parser.ReportError("Expected numeric value for property \"" + propertyname + "\""); return false; } // Success @@ -214,7 +222,7 @@ namespace CodeImp.DoomBuilder.ZDoom } // Can't find the property value! - parser.ReportError("Expected a value for property '" + propertyname + "'"); + parser.ReportError("Expected a value for property \"" + propertyname + "\""); value = 0.0f; return false; } @@ -230,7 +238,7 @@ namespace CodeImp.DoomBuilder.ZDoom // Try parsing as value if(!int.TryParse(strvalue, NumberStyles.Integer, CultureInfo.InvariantCulture, out value)) { - parser.ReportError("Expected integral value for property '" + propertyname + "'"); + parser.ReportError("Expected integral value for property \"" + propertyname + "\""); return false; } @@ -239,7 +247,7 @@ namespace CodeImp.DoomBuilder.ZDoom } // Can't find the property value! - parser.ReportError("Expected a value for property '" + propertyname + "'"); + parser.ReportError("Expected a value for property \"" + propertyname + "\""); value = 0; return false; } @@ -253,7 +261,7 @@ namespace CodeImp.DoomBuilder.ZDoom if(string.IsNullOrEmpty(value)) { // Can't find the property value! - parser.ReportError("Expected a value for property '" + propertyname + "'"); + parser.ReportError("Expected a value for property \"" + propertyname + "\""); return false; } @@ -270,20 +278,20 @@ namespace CodeImp.DoomBuilder.ZDoom if(string.IsNullOrEmpty(strvalue)) { // Can't find the property value! - parser.ReportError("Expected a value for property '" + propertyname + "'"); + parser.ReportError("Expected a value for property \"" + propertyname + "\""); return false; } if(strvalue[0] != '#') { - parser.ReportError("Expected color value for property '" + propertyname + "'"); + parser.ReportError("Expected color value for property \"" + propertyname + "\""); return false; } // Try parsing as value if(!int.TryParse(strvalue.Remove(0, 1), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out value)) { - parser.ReportError("Expected color value for property '" + propertyname + "'"); + parser.ReportError("Expected color value for property \"" + propertyname + "\""); return false; } diff --git a/Source/Core/ZDoom/TextureStructure.cs b/Source/Core/ZDoom/TextureStructure.cs index 0650c93..47eda03 100644 --- a/Source/Core/ZDoom/TextureStructure.cs +++ b/Source/Core/ZDoom/TextureStructure.cs @@ -28,9 +28,6 @@ namespace CodeImp.DoomBuilder.ZDoom { #region ================== Constants - // Some odd thing in ZDoom - private const string IGNORE_SPRITE = "TNT1A0"; - #endregion #region ================== Variables @@ -169,9 +166,6 @@ namespace CodeImp.DoomBuilder.ZDoom PatchStructure pt = new PatchStructure(parser); if(parser.HasError) break; - //mxd. Let's ignore TNT1A0 - if(pt.Name == IGNORE_SPRITE) break; - // Add the patch patches.Add(pt); break; @@ -200,7 +194,7 @@ namespace CodeImp.DoomBuilder.ZDoom // Try parsing as value if(!float.TryParse(strvalue, NumberStyles.Float, CultureInfo.InvariantCulture, out value)) { - parser.ReportError("Expected numeric value for property '" + propertyname + "'"); + parser.ReportError("Expected numeric value for property \"" + propertyname + "\""); return false; } @@ -209,7 +203,7 @@ namespace CodeImp.DoomBuilder.ZDoom } // Can't find the property value! - parser.ReportError("Expected a value for property '" + propertyname + "'"); + parser.ReportError("Expected a value for property \"" + propertyname + "\""); value = 0.0f; return false; } @@ -225,7 +219,7 @@ namespace CodeImp.DoomBuilder.ZDoom // Try parsing as value if(!int.TryParse(strvalue, NumberStyles.Integer, CultureInfo.InvariantCulture, out value)) { - parser.ReportError("Expected integral value for property '" + propertyname + "'"); + parser.ReportError("Expected integral value for property \"" + propertyname + "\""); return false; } @@ -234,7 +228,7 @@ namespace CodeImp.DoomBuilder.ZDoom } // Can't find the property value! - parser.ReportError("Expected a value for property '" + propertyname + "'"); + parser.ReportError("Expected a value for property \"" + propertyname + "\""); value = 0; return false; } diff --git a/Source/Core/ZDoom/ZDTextParser.cs b/Source/Core/ZDoom/ZDTextParser.cs index d9df88f..e76247d 100644 --- a/Source/Core/ZDoom/ZDTextParser.cs +++ b/Source/Core/ZDoom/ZDTextParser.cs @@ -201,7 +201,7 @@ namespace CodeImp.DoomBuilder.ZDoom if(datastream.Position == datastream.Length) //mxd { // ZDoom doesn't give even a warning message about this, so we shouldn't report error or fail parsing. - General.ErrorLogger.Add(ErrorType.Warning, "DECORATE warning in '" + sourcename + "', line " + GetCurrentLineNumber() + ". Block comment is not closed."); + General.ErrorLogger.Add(ErrorType.Warning, "DECORATE warning in \"" + sourcename + "\", line " + GetCurrentLineNumber() + ". Block comment is not closed."); return false; } @@ -441,7 +441,7 @@ namespace CodeImp.DoomBuilder.ZDoom if(string.Compare(token, expectedtoken, true) != 0) { - if(reporterror) ReportError("Expected '" + expectedtoken + "', but got '" + token + "'"); + if(reporterror) ReportError("Expected \"" + expectedtoken + "\", but got \"" + token + "\""); // Rewind so this structure can be read again DataStream.Seek(-token.Length - 1, SeekOrigin.Current); @@ -529,18 +529,18 @@ namespace CodeImp.DoomBuilder.ZDoom //mxd. This adds a warning to the ErrorLogger protected internal void LogWarning(string message) { - // Add a warning - int errline = (datastream != null ? GetCurrentLineNumber() : CompilerError.NO_LINE_NUMBER); - General.ErrorLogger.Add(ErrorType.Warning, GetLanguageType() + " warning in '" + sourcename - + (errline != CompilerError.NO_LINE_NUMBER ? "', line " + (errline + 1) : "'") + ". " + // Add a warning + int errline = (datastream != null ? GetCurrentLineNumber() : CompilerError.NO_LINE_NUMBER); + General.ErrorLogger.Add(ErrorType.Warning, GetLanguageType() + " warning in \"" + sourcename + + (errline != CompilerError.NO_LINE_NUMBER ? "\", line " + (errline + 1) : "\"") + ". " + message + "."); } //mxd. This adds an error to the ErrorLogger public void LogError() { - General.ErrorLogger.Add(ErrorType.Error, GetLanguageType() + " error in '" + errorsource - + (errorline != CompilerError.NO_LINE_NUMBER ? "', line " + (errorline + 1) : "'") + ". " + General.ErrorLogger.Add(ErrorType.Error, GetLanguageType() + " error in \"" + errorsource + + (errorline != CompilerError.NO_LINE_NUMBER ? "\", line " + (errorline + 1) : "\"") + ". " + errordesc + "."); } @@ -611,7 +611,7 @@ namespace CodeImp.DoomBuilder.ZDoom // includefilename references something above the root? if(index-- < 0) { - ReportError("Unable to construct rooted path from '" + includefilename + "'"); + ReportError("Unable to construct rooted path from \"" + includefilename + "\""); return string.Empty; } diff --git a/Source/Plugins/BuilderEffects/Interface/JitterSectorsForm.Designer.cs b/Source/Plugins/BuilderEffects/Interface/JitterSectorsForm.Designer.cs index 9abf7d6..902a095 100644 --- a/Source/Plugins/BuilderEffects/Interface/JitterSectorsForm.Designer.cs +++ b/Source/Plugins/BuilderEffects/Interface/JitterSectorsForm.Designer.cs @@ -238,7 +238,7 @@ // this.floorHeightAmmount.AllowNegative = false; this.floorHeightAmmount.ExtendedLimits = false; - this.floorHeightAmmount.Label = "Floor height:"; + this.floorHeightAmmount.Label = "Height:"; this.floorHeightAmmount.Location = new System.Drawing.Point(6, 19); this.floorHeightAmmount.Maximum = 100; this.floorHeightAmmount.Minimum = 0; diff --git a/Source/Plugins/BuilderModes/BuilderModes.csproj b/Source/Plugins/BuilderModes/BuilderModes.csproj index ac6d2a7..accc5ae 100644 --- a/Source/Plugins/BuilderModes/BuilderModes.csproj +++ b/Source/Plugins/BuilderModes/BuilderModes.csproj @@ -361,6 +361,12 @@ DrawGridOptionsPanel.cs + + UserControl + + + DrawLineOptionsPanel.cs + UserControl @@ -563,6 +569,9 @@ + + DrawLineOptionsPanel.cs + FilterSelectedThingsForm.cs @@ -635,6 +644,9 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/Source/Plugins/BuilderModes/Interface/DrawRectangleOptionsPanel.Designer.cs b/Source/Plugins/BuilderModes/Interface/DrawRectangleOptionsPanel.Designer.cs index a86a0f0..edfc164 100644 --- a/Source/Plugins/BuilderModes/Interface/DrawRectangleOptionsPanel.Designer.cs +++ b/Source/Plugins/BuilderModes/Interface/DrawRectangleOptionsPanel.Designer.cs @@ -29,10 +29,12 @@ private void InitializeComponent() { this.toolStrip1 = new System.Windows.Forms.ToolStrip(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); this.radiuslabel = new System.Windows.Forms.ToolStripLabel(); this.radius = new CodeImp.DoomBuilder.Controls.ToolStripNumericUpDown(); this.subdivslabel = new System.Windows.Forms.ToolStripLabel(); this.subdivs = new CodeImp.DoomBuilder.Controls.ToolStripNumericUpDown(); + this.continuousdrawing = new System.Windows.Forms.ToolStripButton(); this.reset = new System.Windows.Forms.ToolStripButton(); this.toolStrip1.SuspendLayout(); this.SuspendLayout(); @@ -40,6 +42,8 @@ // toolStrip1 // this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.continuousdrawing, + this.toolStripSeparator1, this.radiuslabel, this.radius, this.subdivslabel, @@ -47,15 +51,19 @@ this.reset}); this.toolStrip1.Location = new System.Drawing.Point(0, 0); this.toolStrip1.Name = "toolStrip1"; - this.toolStrip1.Size = new System.Drawing.Size(380, 25); + this.toolStrip1.Size = new System.Drawing.Size(488, 25); this.toolStrip1.TabIndex = 7; this.toolStrip1.Text = "toolStrip1"; // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(6, 25); + // // radiuslabel // - this.radiuslabel.Image = global::CodeImp.DoomBuilder.BuilderModes.Properties.Resources.Gear; this.radiuslabel.Name = "radiuslabel"; - this.radiuslabel.Size = new System.Drawing.Size(92, 22); + this.radiuslabel.Size = new System.Drawing.Size(76, 22); this.radiuslabel.Text = "Bevel Radius:"; // // radius @@ -112,6 +120,16 @@ 0}); this.subdivs.ValueChanged += new System.EventHandler(this.ValueChanged); // + // continuousdrawing + // + this.continuousdrawing.CheckOnClick = true; + this.continuousdrawing.Image = global::CodeImp.DoomBuilder.BuilderModes.Properties.Resources.Repeat; + this.continuousdrawing.ImageTransparentColor = System.Drawing.Color.Magenta; + this.continuousdrawing.Name = "continuousdrawing"; + this.continuousdrawing.Size = new System.Drawing.Size(135, 22); + this.continuousdrawing.Text = "Continuous drawing"; + this.continuousdrawing.CheckedChanged += new System.EventHandler(this.continuousdrawing_CheckedChanged); + // // reset // this.reset.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; @@ -128,7 +146,7 @@ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.Controls.Add(this.toolStrip1); this.Name = "DrawRectangleOptionsPanel"; - this.Size = new System.Drawing.Size(380, 60); + this.Size = new System.Drawing.Size(488, 60); this.toolStrip1.ResumeLayout(false); this.toolStrip1.PerformLayout(); this.ResumeLayout(false); @@ -144,5 +162,7 @@ private System.Windows.Forms.ToolStripLabel subdivslabel; private CodeImp.DoomBuilder.Controls.ToolStripNumericUpDown subdivs; private System.Windows.Forms.ToolStripButton reset; + private System.Windows.Forms.ToolStripButton continuousdrawing; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; } } diff --git a/Source/Plugins/BuilderModes/Interface/DrawRectangleOptionsPanel.cs b/Source/Plugins/BuilderModes/Interface/DrawRectangleOptionsPanel.cs index c885ea3..bb4f638 100644 --- a/Source/Plugins/BuilderModes/Interface/DrawRectangleOptionsPanel.cs +++ b/Source/Plugins/BuilderModes/Interface/DrawRectangleOptionsPanel.cs @@ -6,17 +6,16 @@ namespace CodeImp.DoomBuilder.BuilderModes internal partial class DrawRectangleOptionsPanel : UserControl { public event EventHandler OnValueChanged; - private bool blockEvents; + public event EventHandler OnContinuousDrawingChanged; + private bool blockevents; - private static int radiusValue; - private static int subdivsValue; - - public int BevelWidth { get { return (int)radius.Value; } set { blockEvents = true; radius.Value = value; blockEvents = false; } } + public int BevelWidth { get { return (int)radius.Value; } set { blockevents = true; radius.Value = value; blockevents = false; } } public int MaxBevelWidth { get { return (int)radius.Maximum; } set { radius.Maximum = value; } } public int MinBevelWidth { get { return (int)radius.Minimum; } set { radius.Minimum = value; } } - public int Subdivisions { get { return (int)subdivs.Value; } set { blockEvents = true; subdivs.Value = value; blockEvents = false; } } + public int Subdivisions { get { return (int)subdivs.Value; } set { blockevents = true; subdivs.Value = value; blockevents = false; } } public int MaxSubdivisions { get { return (int)subdivs.Maximum; } set { subdivs.Maximum = value; } } public int MinSubdivisions { get { return (int)subdivs.Minimum; } set { subdivs.Minimum = value; } } + public bool ContinuousDrawing { get { return continuousdrawing.Checked; } set { continuousdrawing.Checked = value; } } public DrawRectangleOptionsPanel() { @@ -25,11 +24,11 @@ namespace CodeImp.DoomBuilder.BuilderModes public void Register() { - radius.Value = radiusValue; - subdivs.Value = subdivsValue; radius.ValueChanged += ValueChanged; subdivs.ValueChanged += ValueChanged; + General.Interface.AddButton(continuousdrawing); + General.Interface.AddButton(toolStripSeparator1); General.Interface.AddButton(radiuslabel); General.Interface.AddButton(radius); General.Interface.AddButton(subdivslabel); @@ -44,22 +43,30 @@ namespace CodeImp.DoomBuilder.BuilderModes General.Interface.RemoveButton(subdivslabel); General.Interface.RemoveButton(radius); General.Interface.RemoveButton(radiuslabel); + General.Interface.RemoveButton(toolStripSeparator1); + General.Interface.RemoveButton(continuousdrawing); } private void ValueChanged(object sender, EventArgs e) { - radiusValue = (int)radius.Value; - subdivsValue = (int)subdivs.Value; - if(!blockEvents && OnValueChanged != null) OnValueChanged(this, EventArgs.Empty); + if(!blockevents && OnValueChanged != null) OnValueChanged(this, EventArgs.Empty); } private void reset_Click(object sender, EventArgs e) { - blockEvents = true; + // Reset values + blockevents = true; radius.Value = 0; - blockEvents = false; subdivs.Value = 0; + blockevents = false; + + // Dispatch event + OnValueChanged(this, EventArgs.Empty); } + private void continuousdrawing_CheckedChanged(object sender, EventArgs e) + { + if(OnContinuousDrawingChanged != null) OnContinuousDrawingChanged(continuousdrawing.Checked, EventArgs.Empty); + } } } diff --git a/Source/Plugins/BuilderModes/Interface/ErrorCheckForm.cs b/Source/Plugins/BuilderModes/Interface/ErrorCheckForm.cs index a782ef9..f0dabd2 100644 --- a/Source/Plugins/BuilderModes/Interface/ErrorCheckForm.cs +++ b/Source/Plugins/BuilderModes/Interface/ErrorCheckForm.cs @@ -330,16 +330,16 @@ namespace CodeImp.DoomBuilder.BuilderModes catch(TargetInvocationException ex) { // Error! - General.ErrorLogger.Add(ErrorType.Error, "Failed to create class instance '" + t.Name + "'"); + General.ErrorLogger.Add(ErrorType.Error, "Failed to create class instance \"" + t.Name + "\""); General.WriteLogLine(ex.InnerException.GetType().Name + ": " + ex.InnerException.Message); - throw ex; + throw; } catch(Exception ex) { // Error! - General.ErrorLogger.Add(ErrorType.Error, "Failed to create class instance '" + t.Name + "'"); + General.ErrorLogger.Add(ErrorType.Error, "Failed to create class instance \"" + t.Name + "\""); General.WriteLogLine(ex.GetType().Name + ": " + ex.Message); - throw ex; + throw; } // Add to list @@ -749,7 +749,7 @@ namespace CodeImp.DoomBuilder.BuilderModes foreach(ErrorResult result in results.SelectedItems) sb.AppendLine(result.ToString()); // Set on clipboard - Clipboard.SetText(sb.ToString()); + Clipboard.SetDataObject(sb.ToString(), true, 5, 200); //mxd // Inform the user General.Interface.DisplayStatus(StatusType.Info, "Analysis results copied to clipboard."); diff --git a/Source/Plugins/BuilderModes/Interface/FindReplaceForm.cs b/Source/Plugins/BuilderModes/Interface/FindReplaceForm.cs index 83c7d84..789112f 100644 --- a/Source/Plugins/BuilderModes/Interface/FindReplaceForm.cs +++ b/Source/Plugins/BuilderModes/Interface/FindReplaceForm.cs @@ -80,14 +80,14 @@ namespace CodeImp.DoomBuilder.BuilderModes catch(TargetInvocationException ex) { // Error! - General.ErrorLogger.Add(ErrorType.Error, "Failed to create class instance '" + t.Name + "'"); + General.ErrorLogger.Add(ErrorType.Error, "Failed to create class instance \"" + t.Name + "\""); General.WriteLogLine(ex.InnerException.GetType().Name + ": " + ex.InnerException.Message); throw; } catch(Exception ex) { // Error! - General.ErrorLogger.Add(ErrorType.Error, "Failed to create class instance '" + t.Name + "'"); + General.ErrorLogger.Add(ErrorType.Error, "Failed to create class instance \"" + t.Name + "\""); General.WriteLogLine(ex.GetType().Name + ": " + ex.Message); throw; } @@ -151,7 +151,7 @@ namespace CodeImp.DoomBuilder.BuilderModes // Browse replacement clicked private void browsereplace_Click(object sender, EventArgs e) { - replaceinput.Text = newfinder.Browse(replaceinput.Text); + replaceinput.Text = newfinder.BrowseReplace(replaceinput.Text); } //mxd diff --git a/Source/Plugins/BuilderModes/Interface/PreferencesForm.Designer.cs b/Source/Plugins/BuilderModes/Interface/PreferencesForm.Designer.cs index c61aee0..2b1741a 100644 --- a/Source/Plugins/BuilderModes/Interface/PreferencesForm.Designer.cs +++ b/Source/Plugins/BuilderModes/Interface/PreferencesForm.Designer.cs @@ -263,9 +263,10 @@ namespace CodeImp.DoomBuilder.BuilderModes this.autodrawonedit.AutoSize = true; this.autodrawonedit.Location = new System.Drawing.Point(13, 24); this.autodrawonedit.Name = "autodrawonedit"; - this.autodrawonedit.Size = new System.Drawing.Size(346, 17); + this.autodrawonedit.Size = new System.Drawing.Size(353, 30); this.autodrawonedit.TabIndex = 11; - this.autodrawonedit.Text = "Start drawing when Edit pressed over empty space in Classic modes"; + this.autodrawonedit.Text = "Start drawing when Edit pressed over empty space in Classic modes\r\nInsert new thi" + + "ng when Edit pressed over empty space in Things mode"; this.autodrawonedit.UseVisualStyleBackColor = true; // // syncSelection @@ -331,7 +332,7 @@ namespace CodeImp.DoomBuilder.BuilderModes // editnewthing // this.editnewthing.AutoSize = true; - this.editnewthing.Location = new System.Drawing.Point(13, 49); + this.editnewthing.Location = new System.Drawing.Point(13, 62); this.editnewthing.Name = "editnewthing"; this.editnewthing.Size = new System.Drawing.Size(248, 17); this.editnewthing.TabIndex = 1; @@ -341,7 +342,7 @@ namespace CodeImp.DoomBuilder.BuilderModes // editnewsector // this.editnewsector.AutoSize = true; - this.editnewsector.Location = new System.Drawing.Point(13, 74); + this.editnewsector.Location = new System.Drawing.Point(13, 87); this.editnewsector.Name = "editnewsector"; this.editnewsector.Size = new System.Drawing.Size(258, 17); this.editnewsector.TabIndex = 2; @@ -351,7 +352,7 @@ namespace CodeImp.DoomBuilder.BuilderModes // additiveselect // this.additiveselect.AutoSize = true; - this.additiveselect.Location = new System.Drawing.Point(13, 99); + this.additiveselect.Location = new System.Drawing.Point(13, 112); this.additiveselect.Name = "additiveselect"; this.additiveselect.Size = new System.Drawing.Size(205, 17); this.additiveselect.TabIndex = 3; diff --git a/Source/Plugins/BuilderModes/Properties/Resources.Designer.cs b/Source/Plugins/BuilderModes/Properties/Resources.Designer.cs index aa41c51..b86a964 100644 --- a/Source/Plugins/BuilderModes/Properties/Resources.Designer.cs +++ b/Source/Plugins/BuilderModes/Properties/Resources.Designer.cs @@ -1,10 +1,10 @@ //------------------------------------------------------------------------------ // -// Dieser Code wurde von einem Tool generiert. -// Laufzeitversion:4.0.30319.42000 +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 // -// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn -// der Code erneut generiert wird. +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. // //------------------------------------------------------------------------------ @@ -13,13 +13,13 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { /// - /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. + /// A strongly-typed resource class, for looking up localized strings, etc. /// - // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert - // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. - // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen - // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { @@ -33,7 +33,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. + /// Returns the cached ResourceManager instance used by this class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Resources.ResourceManager ResourceManager { @@ -47,8 +47,8 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle - /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Globalization.CultureInfo Culture { @@ -61,7 +61,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap AlignThings { get { @@ -71,7 +71,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap Angle { get { @@ -81,7 +81,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap BrightnessGradient { get { @@ -91,7 +91,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap CeilingAlign { get { @@ -101,7 +101,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap CeilsGradient { get { @@ -111,7 +111,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap ColorPick { get { @@ -121,7 +121,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap Copy { get { @@ -131,7 +131,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap CopyProperties { get { @@ -141,7 +141,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap CurveLines { get { @@ -151,7 +151,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap Door { get { @@ -161,7 +161,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap DrawCurveMode { get { @@ -171,7 +171,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap DrawEllipseMode { get { @@ -181,7 +181,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap DrawGeometryMode { get { @@ -191,7 +191,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap DrawGridMode { get { @@ -201,7 +201,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap DrawRectangleMode { get { @@ -211,7 +211,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap FilterThings { get { @@ -221,7 +221,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap Flip { get { @@ -231,7 +231,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap FlipSelectionH { get { @@ -241,7 +241,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap FlipSelectionV { get { @@ -251,7 +251,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap FloorAlign { get { @@ -261,7 +261,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap FloorsGradient { get { @@ -271,7 +271,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap Folder { get { @@ -281,7 +281,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap Gear { get { @@ -291,7 +291,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap Hide { get { @@ -301,7 +301,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap HideAll { get { @@ -311,7 +311,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap InsertThingsRadiallyMode { get { @@ -321,7 +321,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap Join { get { @@ -331,7 +331,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap List { get { @@ -341,7 +341,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap List_Images { get { @@ -351,7 +351,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap Merge { get { @@ -361,7 +361,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap PasteProperties { get { @@ -371,7 +371,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap PastePropertiesOptions { get { @@ -381,7 +381,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap PlaceThings { get { @@ -391,7 +391,17 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap Repeat { + get { + object obj = ResourceManager.GetObject("Repeat", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap Reset { get { @@ -401,7 +411,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap Save { get { @@ -411,7 +421,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap SelectThingsInSectors { get { @@ -421,7 +431,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap SelectTouching { get { @@ -431,7 +441,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap Show { get { @@ -441,7 +451,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap Show2 { get { @@ -451,7 +461,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap Show3 { get { @@ -461,7 +471,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap Similar { get { @@ -471,7 +481,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap Text { get { @@ -481,7 +491,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap TextureLock { get { @@ -491,7 +501,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap ThingPointAtCursor { get { @@ -501,7 +511,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap treeview { get { @@ -511,7 +521,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap ViewSelectionEffects { get { @@ -521,7 +531,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap ViewSelectionIndex { get { @@ -531,7 +541,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties { } /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// Looks up a localized resource of type System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap VisualModeGZ { get { diff --git a/Source/Plugins/BuilderModes/Properties/Resources.resx b/Source/Plugins/BuilderModes/Properties/Resources.resx index 5ee3b44..5d591af 100644 --- a/Source/Plugins/BuilderModes/Properties/Resources.resx +++ b/Source/Plugins/BuilderModes/Properties/Resources.resx @@ -118,9 +118,6 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - ..\Resources\Join.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\FloorAlign.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -139,9 +136,6 @@ ..\Resources\ViewSelectionEffects.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\Gear.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\HideAll.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -196,12 +190,12 @@ ..\Resources\ThingPointAtCursor.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\PlaceThings.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\Text.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\Show.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Resources\BrightnessGradient.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -217,8 +211,8 @@ ..\Resources\Reset.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\Show.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\Join.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\ViewSelectionIndex.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -229,6 +223,9 @@ ..\Resources\Show2.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\Folder.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Resources\ColorPick.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -238,8 +235,8 @@ ..\Resources\FlipSelectionH.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\Folder.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\PlaceThings.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\Angle.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -262,4 +259,10 @@ ..\Resources\InsertThingsRadiallyMode.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\Gear.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Repeat.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/Source/Plugins/BuilderModes/Resources/Repeat.png b/Source/Plugins/BuilderModes/Resources/Repeat.png new file mode 100644 index 0000000000000000000000000000000000000000..48350331c3025d345424a05147edaa22ea0ad025 GIT binary patch literal 587 zcmV-R0<`^!P)3+VA|^Q_D{ui@t+`ow=Q=jc1u+Q!#6 z_hV0hi`w*LX>ESyUMNR|9E8qvuJ(VnD<`L2T5fm(qxIt4R5?8Qb)i0d+1ndL@bdY? zYBd}WkAGj%Za2IJI?E=Q1Nr`Q>kyo)p)dTyYn0=xlY}Wm#06xT0cS1PJa58ZlNse4 z1Y@I7Y>K zRgmljdP55CIWM5&VsEvS36J=4J<3w$o~zRAwK|hV8kj==-}*ef{dIYfI7Y zSqhbjBYfNzx8DmXgjK)d5*PpJhM7wXdo3~FQ4}!+k z)=Jzb0E3Db7X*7})IaKghs=}s|3WMvc~3kk0SS673^D|N%uzVBWqQj}=}w#td!4TZ Z7yye%LV1dLeCPlG002ovPDHLkV1nRe2)O_N literal 0 HcmV?d00001 diff --git a/Source/Plugins/BuilderModes/VisualModes/BaseVisualGeometrySector.cs b/Source/Plugins/BuilderModes/VisualModes/BaseVisualGeometrySector.cs index bdd2727..3d33932 100644 --- a/Source/Plugins/BuilderModes/VisualModes/BaseVisualGeometrySector.cs +++ b/Source/Plugins/BuilderModes/VisualModes/BaseVisualGeometrySector.cs @@ -801,7 +801,7 @@ namespace CodeImp.DoomBuilder.BuilderModes // Apply Texture public virtual void ApplyTexture(string texture) { - mode.CreateUndo("Change flat '" + texture + "'"); + mode.CreateUndo("Change flat \"" + texture + "\""); SetTexture(texture); OnTextureChanged(); //mxd } @@ -813,7 +813,7 @@ namespace CodeImp.DoomBuilder.BuilderModes string texturename = ((General.Map.Options.UseLongTextureNames && Texture != null && Texture.UsedInMap) ? Texture.Name : GetTextureName()); BuilderPlug.Me.CopiedFlat = texturename; if(General.Map.Config.MixTexturesFlats) BuilderPlug.Me.CopiedTexture = texturename; - mode.SetActionResult("Copied flat '" + texturename + "'."); + mode.SetActionResult("Copied flat \"" + texturename + "\"."); } public virtual void OnPasteTexture() { } diff --git a/Source/Plugins/BuilderModes/VisualModes/BaseVisualGeometrySidedef.cs b/Source/Plugins/BuilderModes/VisualModes/BaseVisualGeometrySidedef.cs index 6ae0769..2b72450 100644 --- a/Source/Plugins/BuilderModes/VisualModes/BaseVisualGeometrySidedef.cs +++ b/Source/Plugins/BuilderModes/VisualModes/BaseVisualGeometrySidedef.cs @@ -1186,10 +1186,10 @@ namespace CodeImp.DoomBuilder.BuilderModes { if(BuilderPlug.Me.CopiedTexture != null) { - mode.CreateUndo("Paste texture '" + BuilderPlug.Me.CopiedTexture + "'"); - mode.SetActionResult("Pasted texture '" + BuilderPlug.Me.CopiedTexture + "'."); + mode.CreateUndo("Paste texture \"" + BuilderPlug.Me.CopiedTexture + "\""); + mode.SetActionResult("Pasted texture \"" + BuilderPlug.Me.CopiedTexture + "\"."); SetTexture(BuilderPlug.Me.CopiedTexture); - OnTextureChanged();//mxd + OnTextureChanged(); //mxd } } @@ -1221,7 +1221,7 @@ namespace CodeImp.DoomBuilder.BuilderModes string texturename = ((General.Map.Options.UseLongTextureNames && Texture != null && Texture.UsedInMap) ? Texture.Name : GetTextureName()); BuilderPlug.Me.CopiedTexture = texturename; if(General.Map.Config.MixTexturesFlats) BuilderPlug.Me.CopiedFlat = texturename; - mode.SetActionResult("Copied texture '" + texturename + "'."); + mode.SetActionResult("Copied texture \"" + texturename + "\"."); } // Copy texture offsets diff --git a/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs b/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs index a1ebc44..b9db85e 100644 --- a/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs +++ b/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs @@ -517,6 +517,11 @@ namespace CodeImp.DoomBuilder.BuilderModes // This updates the VisualSectors and VisualThings that have their Changed property set private void UpdateChangedObjects() { + //mxd + SectorData[] toupdate = new SectorData[sectordata.Values.Count]; + sectordata.Values.CopyTo(toupdate, 0); + foreach(SectorData data in toupdate) data.Update(); + foreach(KeyValuePair vs in allsectors) { if(vs.Value != null) @@ -1538,8 +1543,6 @@ namespace CodeImp.DoomBuilder.BuilderModes // and uses the marks to check what needs to be reloaded. protected override void ResourcesReloadedPartial() { - bool sectorsmarked = false; - if(General.Map.UndoRedo.GeometryChanged) { // Let the core do this (it will just dispose the sectors that were changed) @@ -1547,6 +1550,8 @@ namespace CodeImp.DoomBuilder.BuilderModes } else { + bool sectorsmarked = false; + // Neighbour sectors must be updated as well foreach(Sector s in General.Map.Map.Sectors) { @@ -1578,7 +1583,7 @@ namespace CodeImp.DoomBuilder.BuilderModes if(s.Marked) { SectorData sd = GetSectorData(s); - sd.Reset(); + sd.Reset(false); //mxd (changed Reset implementation) // UpdateSectorGeometry for associated sectors (sd.UpdateAlso) as well! foreach(KeyValuePair us in sd.UpdateAlso) @@ -1603,8 +1608,22 @@ namespace CodeImp.DoomBuilder.BuilderModes { // No sectors or geometry changed. So we only have // to update things when they have changed. + HashSet toremove = new HashSet(); //mxd foreach(KeyValuePair vt in allthings) - if((vt.Value != null) && vt.Key.Marked) (vt.Value as BaseVisualThing).Rebuild(); + { + if((vt.Value != null) && vt.Key.Marked) + { + if(vt.Key.IsDisposed) toremove.Add(vt.Key); //mxd. Disposed things will cause problems + else (vt.Value as BaseVisualThing).Rebuild(); + } + } + + //mxd. Remove disposed things + foreach(Thing t in toremove) + { + if(allthings[t] != null) allthings[t].Dispose(); + allthings.Remove(t); + } } else { @@ -3011,7 +3030,6 @@ namespace CodeImp.DoomBuilder.BuilderModes renderer.SetCrosshairBusy(true); General.Interface.RedrawDisplay(); GetTargetEventReceiver(false).OnSelectTexture(); - UpdateChangedObjects(); RebuildElementData(); //mxd. Extrafloors or Glow effects may've been changed renderer.SetCrosshairBusy(false); PostAction(); diff --git a/Source/Plugins/BuilderModes/VisualModes/BaseVisualSector.cs b/Source/Plugins/BuilderModes/VisualModes/BaseVisualSector.cs index d28640a..cc06ba6 100644 --- a/Source/Plugins/BuilderModes/VisualModes/BaseVisualSector.cs +++ b/Source/Plugins/BuilderModes/VisualModes/BaseVisualSector.cs @@ -35,14 +35,14 @@ namespace CodeImp.DoomBuilder.BuilderModes #region ================== Variables - private BaseVisualMode mode; + private readonly BaseVisualMode mode; private VisualFloor floor; private VisualCeiling ceiling; private List extrafloors; private List extraceilings; - private List extrabackfloors; //mxd - private List extrabackceilings; //mxd + private readonly List extrabackfloors; //mxd + private readonly List extrabackceilings; //mxd private Dictionary sides; // If this is set to true, the sector will be rebuilt after the action is performed. @@ -121,16 +121,19 @@ namespace CodeImp.DoomBuilder.BuilderModes changed = true; // Not sure what from this part we need, so commented out for now - SectorData data = GetSectorData(); - data.Reset(); - - // Update sectors that rely on this sector - foreach(KeyValuePair s in data.UpdateAlso) + SectorData data = mode.GetSectorDataEx(this.Sector); //mxd + if(data != null) //mxd { - if(mode.VisualSectorExists(s.Key)) + data.Reset(includeneighbours); + + // Update sectors that rely on this sector + foreach(KeyValuePair s in data.UpdateAlso) { - BaseVisualSector vs = (BaseVisualSector)mode.GetVisualSector(s.Key); - vs.UpdateSectorGeometry(s.Value); + if(mode.VisualSectorExists(s.Key)) + { + BaseVisualSector vs = (BaseVisualSector)mode.GetVisualSector(s.Key); + vs.Changed = true; + } } } diff --git a/Source/Plugins/BuilderModes/VisualModes/SectorData.cs b/Source/Plugins/BuilderModes/VisualModes/SectorData.cs index 22349e7..03ea37e 100644 --- a/Source/Plugins/BuilderModes/VisualModes/SectorData.cs +++ b/Source/Plugins/BuilderModes/VisualModes/SectorData.cs @@ -113,6 +113,13 @@ namespace CodeImp.DoomBuilder.BuilderModes Effect3DFloor e = new Effect3DFloor(this, sourcelinedef); extrafloors.Add(e); alleffects.Add(e); + + //mxd. Extrafloor neighbours should be updated when extrafloor is changed + foreach(Sidedef sd in this.Sector.Sidedefs) + { + if(sd.Other != null && sd.Other.Sector != null) + AddUpdateSector(sd.Other.Sector, false); + } } // Brightness level effect @@ -214,7 +221,7 @@ namespace CodeImp.DoomBuilder.BuilderModes } // This resets this sector data and all sectors that require updating after me - public void Reset() + /*public void Reset() { if(isupdating) return; isupdating = true; @@ -236,6 +243,35 @@ namespace CodeImp.DoomBuilder.BuilderModes sd.Reset(); } + isupdating = false; + }*/ + + //mxd. This marks this sector data and all sector datas that require updating as not updated + public void Reset(bool resetneighbours) + { + if(isupdating) return; + isupdating = true; + + // This is set to false so that this sector is rebuilt the next time it is needed! + updated = false; + + // The visual sector associated is now outdated + if(mode.VisualSectorExists(sector)) + { + BaseVisualSector vs = (BaseVisualSector)mode.GetVisualSector(sector); + vs.Changed = true; + } + + // Reset the sectors that depend on this sector + if(resetneighbours) + { + foreach(KeyValuePair s in updatesectors) + { + SectorData sd = mode.GetSectorDataEx(s.Key); + if(sd != null) sd.Reset(s.Value); + } + } + isupdating = false; } diff --git a/Source/Plugins/BuilderModes/VisualModes/VisualCeiling.cs b/Source/Plugins/BuilderModes/VisualModes/VisualCeiling.cs index f8e206c..efb5a88 100644 --- a/Source/Plugins/BuilderModes/VisualModes/VisualCeiling.cs +++ b/Source/Plugins/BuilderModes/VisualModes/VisualCeiling.cs @@ -369,27 +369,11 @@ namespace CodeImp.DoomBuilder.BuilderModes { if(BuilderPlug.Me.CopiedFlat != null) { - mode.CreateUndo("Paste ceiling '" + BuilderPlug.Me.CopiedFlat + "'"); - mode.SetActionResult("Pasted flat '" + BuilderPlug.Me.CopiedFlat + "' on ceiling."); - - //mxd. Glow effect may require SectorData and geometry update - bool prevtextureglows = General.Map.Data.GlowingFlats.ContainsKey(Sector.Sector.LongCeilTexture); + mode.CreateUndo("Paste ceiling \"" + BuilderPlug.Me.CopiedFlat + "\""); + mode.SetActionResult("Pasted flat \"" + BuilderPlug.Me.CopiedFlat + "\" on ceiling."); SetTexture(BuilderPlug.Me.CopiedFlat); - //mxd. Glow effect may require SectorData and geometry update - if(prevtextureglows && !General.Map.Data.GlowingFlats.ContainsKey(Sector.Sector.LongCeilTexture)) - { - SectorData sd = mode.GetSectorData(level.sector); - sd.UpdateForced(); - - if(mode.VisualSectorExists(level.sector)) - { - BaseVisualSector vs = (BaseVisualSector)mode.GetVisualSector(level.sector); - vs.UpdateSectorGeometry(false); - } - } - //mxd. 3D floors may need updating... OnTextureChanged(); } @@ -591,7 +575,20 @@ namespace CodeImp.DoomBuilder.BuilderModes // This changes the texture protected override void SetTexture(string texturename) { + //mxd. Glow effect may require SectorData and geometry update + bool prevtextureglows = General.Map.Data.GlowingFlats.ContainsKey(Sector.Sector.LongCeilTexture); + + // Set new texture level.sector.SetCeilTexture(texturename); + + //mxd. Glow effect may require SectorData and geometry update + if(prevtextureglows + && !General.Map.Data.GlowingFlats.ContainsKey(Sector.Sector.LongCeilTexture) + && mode.VisualSectorExists(level.sector)) + { + ((BaseVisualSector)mode.GetVisualSector(level.sector)).Changed = true; + } + General.Map.Data.UpdateUsedTextures(); } diff --git a/Source/Plugins/BuilderModes/VisualModes/VisualFloor.cs b/Source/Plugins/BuilderModes/VisualModes/VisualFloor.cs index cd09863..c0125c0 100644 --- a/Source/Plugins/BuilderModes/VisualModes/VisualFloor.cs +++ b/Source/Plugins/BuilderModes/VisualModes/VisualFloor.cs @@ -368,27 +368,11 @@ namespace CodeImp.DoomBuilder.BuilderModes { if(BuilderPlug.Me.CopiedFlat != null) { - mode.CreateUndo("Paste floor '" + BuilderPlug.Me.CopiedFlat + "'"); - mode.SetActionResult("Pasted flat '" + BuilderPlug.Me.CopiedFlat + "' on floor."); - - //mxd. Glow effect may require SectorData and geometry update - bool prevtextureglows = General.Map.Data.GlowingFlats.ContainsKey(Sector.Sector.LongFloorTexture); + mode.CreateUndo("Paste floor \"" + BuilderPlug.Me.CopiedFlat + "\""); + mode.SetActionResult("Pasted flat \"" + BuilderPlug.Me.CopiedFlat + "\" on floor."); SetTexture(BuilderPlug.Me.CopiedFlat); - //mxd. Glow effect may require SectorData and geometry update - if(prevtextureglows && !General.Map.Data.GlowingFlats.ContainsKey(Sector.Sector.LongFloorTexture)) - { - SectorData sd = mode.GetSectorData(level.sector); - sd.UpdateForced(); - - if(mode.VisualSectorExists(level.sector)) - { - BaseVisualSector vs = (BaseVisualSector)mode.GetVisualSector(level.sector); - vs.UpdateSectorGeometry(false); - } - } - //mxd. 3D floors may need updating... OnTextureChanged(); } @@ -464,12 +448,20 @@ namespace CodeImp.DoomBuilder.BuilderModes { // This floor is part of 3D-floor if(level.sector != Sector.Sector) - ((BaseVisualSector)mode.GetVisualSector(level.sector)).Floor.OnChangeTargetBrightness(up); + { + BaseVisualSector vs = (BaseVisualSector)mode.GetVisualSector(level.sector); + vs.Floor.OnChangeTargetBrightness(up); + vs.UpdateSectorGeometry(true); + } // This is actual floor of a sector with extrafloors else if(Sector.ExtraFloors.Count > 0 && !Sector.ExtraFloors[0].ExtraFloor.Floor.restrictlighting && !Sector.ExtraFloors[0].ExtraFloor.Floor.disablelighting) + { Sector.ExtraFloors[0].OnChangeTargetBrightness(up); + } else + { base.OnChangeTargetBrightness(up); + } } else { @@ -554,7 +546,20 @@ namespace CodeImp.DoomBuilder.BuilderModes // This changes the texture protected override void SetTexture(string texturename) { + //mxd. Glow effect may require SectorData and geometry update + bool prevtextureglows = General.Map.Data.GlowingFlats.ContainsKey(Sector.Sector.LongFloorTexture); + + // Set new texture level.sector.SetFloorTexture(texturename); + + //mxd. Glow effect may require SectorData and geometry update + if(prevtextureglows + && !General.Map.Data.GlowingFlats.ContainsKey(Sector.Sector.LongFloorTexture) + && mode.VisualSectorExists(level.sector)) + { + ((BaseVisualSector)mode.GetVisualSector(level.sector)).Changed = true; + } + General.Map.Data.UpdateUsedTextures(); } diff --git a/Source/Plugins/BuilderModes/VisualModes/VisualLower.cs b/Source/Plugins/BuilderModes/VisualModes/VisualLower.cs index d2a2793..63f8417 100644 --- a/Source/Plugins/BuilderModes/VisualModes/VisualLower.cs +++ b/Source/Plugins/BuilderModes/VisualModes/VisualLower.cs @@ -240,7 +240,8 @@ namespace CodeImp.DoomBuilder.BuilderModes if(polygons.Count > 0) { // Keep top and bottom planes for intersection testing - top = osd.Floor.plane; + Vector2D linecenter = Sidedef.Line.GetCenterPoint(); //mxd. Our sector's ceiling can be lower than the other sector's floor! + top = (osd.Floor.plane.GetZ(linecenter) < sd.Ceiling.plane.GetZ(linecenter) ? osd.Floor.plane : sd.Ceiling.plane); bottom = sd.Floor.plane; // Process the polygon and create vertices diff --git a/Source/Plugins/BuilderModes/VisualModes/VisualUpper.cs b/Source/Plugins/BuilderModes/VisualModes/VisualUpper.cs index 5bb6463..a281d5f 100644 --- a/Source/Plugins/BuilderModes/VisualModes/VisualUpper.cs +++ b/Source/Plugins/BuilderModes/VisualModes/VisualUpper.cs @@ -235,8 +235,9 @@ namespace CodeImp.DoomBuilder.BuilderModes if(polygons.Count > 0) { // Keep top and bottom planes for intersection testing + Vector2D linecenter = Sidedef.Line.GetCenterPoint(); //mxd. Our sector's floor can be higher than the other sector's ceiling! top = sd.Ceiling.plane; - bottom = osd.Ceiling.plane; + bottom = (osd.Ceiling.plane.GetZ(linecenter) > sd.Floor.plane.GetZ(linecenter) ? osd.Ceiling.plane : sd.Floor.plane); // Process the polygon and create vertices List verts = CreatePolygonVertices(polygons, tp, sd, lightvalue, lightabsolute); diff --git a/Source/Plugins/NodesViewer/NodesViewerMode.cs b/Source/Plugins/NodesViewer/NodesViewerMode.cs index 1552d97..45f89e5 100644 --- a/Source/Plugins/NodesViewer/NodesViewerMode.cs +++ b/Source/Plugins/NodesViewer/NodesViewerMode.cs @@ -244,7 +244,7 @@ namespace CodeImp.DoomBuilder.Plugins.NodesViewer nodesformat = new string(reader.ReadChars(4)); if(!supportedFormats.Contains(nodesformat)) { - MessageBox.Show("'" + nodesformat + "' node format is not supported.", "Nodes Viewer mode", MessageBoxButtons.OK, MessageBoxIcon.Error); + MessageBox.Show("\"" + nodesformat + "\" node format is not supported.", "Nodes Viewer mode", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; } diff --git a/Source/Plugins/TagExplorer/Controls/TagExplorer.cs b/Source/Plugins/TagExplorer/Controls/TagExplorer.cs index 8ccaab4..db2b9e8 100644 --- a/Source/Plugins/TagExplorer/Controls/TagExplorer.cs +++ b/Source/Plugins/TagExplorer/Controls/TagExplorer.cs @@ -655,7 +655,7 @@ namespace CodeImp.DoomBuilder.TagExplorer break; default: - throw new NotImplementedException("Tag Explorer: Sort mode '" + sortMode + "' is not implemented!"); + throw new NotImplementedException("Tag Explorer: Sort mode \"" + sortMode + "\" is not implemented!"); } } diff --git a/Source/Plugins/VisplaneExplorer/VisplaneExplorerMode.cs b/Source/Plugins/VisplaneExplorer/VisplaneExplorerMode.cs index 783d25a..b379f2d 100644 --- a/Source/Plugins/VisplaneExplorer/VisplaneExplorerMode.cs +++ b/Source/Plugins/VisplaneExplorer/VisplaneExplorerMode.cs @@ -260,7 +260,14 @@ namespace CodeImp.DoomBuilder.Plugins.VisplaneExplorer // Export the current map to a temporary WAD file tempfile = BuilderPlug.MakeTempFilename(".wad"); - General.Map.ExportToFile(tempfile); + if(!General.Map.ExportToFile(tempfile)) + { + //mxd. Abort on export fail + Cursor.Current = Cursors.Default; + General.Interface.DisplayStatus(StatusType.Warning, "Unable to set test environment..."); + OnCancel(); + return; + } // Load the map in VPO_DLL BuilderPlug.VPO.Start(tempfile, General.Map.Options.LevelName);